diff options
Diffstat (limited to 'src')
80 files changed, 3729 insertions, 1263 deletions
diff --git a/src/BootloaderVersion.cpp b/src/BootloaderVersion.cpp index 5eba7a1d..07a1da4e 100644 --- a/src/BootloaderVersion.cpp +++ b/src/BootloaderVersion.cpp @@ -1,26 +1,36 @@ #include <cstdint> +#include <cstdio> #include "BootloaderVersion.h" using namespace Pinetime; -// NOTE : current bootloader does not export its version to the application firmware. +// NOTE : version < 1.0.0 of bootloader does not export its version to the application firmware. -uint32_t BootloaderVersion::Major() { - return 0; +uint32_t BootloaderVersion::version = 0; +char BootloaderVersion::versionString[BootloaderVersion::VERSION_STR_LEN] = "0.0.0"; + +const uint32_t BootloaderVersion::Major() { + return (BootloaderVersion::version >> 16u) & 0xff; } -uint32_t BootloaderVersion::Minor() { - return 0; +const uint32_t BootloaderVersion::Minor() { + return (BootloaderVersion::version >> 8u) & 0xff; } -uint32_t BootloaderVersion::Patch() { - return 0; +const uint32_t BootloaderVersion::Patch() { + return BootloaderVersion::version & 0xff; } const char* BootloaderVersion::VersionString() { - return "0.0.0"; + return BootloaderVersion::versionString; +} + +const bool BootloaderVersion::IsValid() { + return BootloaderVersion::version >= 0x00010000; } -bool BootloaderVersion::IsValid() { - return false; +void BootloaderVersion::SetVersion(uint32_t v) { + BootloaderVersion::version = v; + snprintf(BootloaderVersion::versionString, BootloaderVersion::VERSION_STR_LEN, "%ld.%ld.%ld", + BootloaderVersion::Major(), BootloaderVersion::Minor(), BootloaderVersion::Patch()); } diff --git a/src/BootloaderVersion.h b/src/BootloaderVersion.h index c1ede0f5..f8127414 100644 --- a/src/BootloaderVersion.h +++ b/src/BootloaderVersion.h @@ -3,10 +3,15 @@ namespace Pinetime { class BootloaderVersion { public: - static uint32_t Major(); - static uint32_t Minor(); - static uint32_t Patch(); + static const uint32_t Major(); + static const uint32_t Minor(); + static const uint32_t Patch(); static const char* VersionString(); - static bool IsValid(); + static const bool IsValid(); + static void SetVersion(uint32_t v); + private: + static uint32_t version; + static constexpr size_t VERSION_STR_LEN = 12; + static char versionString[VERSION_STR_LEN]; }; -}
\ No newline at end of file +} diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7721d6b8..40e1f2a5 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -166,6 +166,13 @@ set(NIMBLE_SRC libs/mynewt-nimble/nimble/host/util/src/addr.c ) +set(LITTLEFS_SRC + libs/littlefs/lfs_util.h + libs/littlefs/lfs.h + libs/littlefs/lfs_util.c + libs/littlefs/lfs.c + ) + set(LVGL_SRC libs/lv_conf.h libs/lvgl/lvgl.h @@ -235,6 +242,7 @@ set(LVGL_SRC libs/lvgl/src/lv_widgets/lv_cont.h libs/lvgl/src/lv_widgets/lv_cpicker.h libs/lvgl/src/lv_widgets/lv_dropdown.h + libs/lvgl/src/lv_widgets/lv_gauge.h libs/lvgl/src/lv_widgets/lv_img.h libs/lvgl/src/lv_widgets/lv_imgbtn.h libs/lvgl/src/lv_widgets/lv_keyboard.h @@ -321,6 +329,7 @@ set(LVGL_SRC libs/lvgl/src/lv_widgets/lv_cont.c libs/lvgl/src/lv_widgets/lv_cpicker.c libs/lvgl/src/lv_widgets/lv_dropdown.c + libs/lvgl/src/lv_widgets/lv_gauge.c libs/lvgl/src/lv_widgets/lv_img.c libs/lvgl/src/lv_widgets/lv_imgbtn.c libs/lvgl/src/lv_widgets/lv_keyboard.c @@ -423,6 +432,7 @@ list(APPEND SOURCE_FILES displayapp/icons/bg_clock.c displayapp/screens/WatchFaceAnalog.cpp displayapp/screens/WatchFaceDigital.cpp + displayapp/screens/PineTimeStyle.cpp ## @@ -462,6 +472,7 @@ list(APPEND SOURCE_FILES components/motor/MotorController.cpp components/settings/Settings.cpp components/timer/TimerController.cpp + components/fs/FS.cpp drivers/Cst816s.cpp FreeRTOS/port.c FreeRTOS/port_cmsis_systick.c @@ -473,6 +484,7 @@ list(APPEND SOURCE_FILES displayapp/fonts/jetbrains_mono_76.c displayapp/fonts/jetbrains_mono_42.c displayapp/fonts/lv_font_sys_48.c + displayapp/fonts/open_sans_light.c displayapp/lv_pinetime_theme.c systemtask/SystemTask.cpp @@ -539,6 +551,7 @@ list(APPEND RECOVERY_SOURCE_FILES components/heartrate/Biquad.cpp components/heartrate/Ptagc.cpp components/motor/MotorController.cpp + components/fs/FS.cpp ) list(APPEND RECOVERYLOADER_SOURCE_FILES @@ -797,13 +810,25 @@ target_compile_options(lvgl PRIVATE $<$<COMPILE_LANGUAGE:ASM>: -MP -MD -x assembler-with-cpp> ) +# LITTLEFS_SRC +add_library(littlefs STATIC ${LITTLEFS_SRC}) +target_include_directories(littlefs SYSTEM PUBLIC . ../) +target_include_directories(littlefs SYSTEM PUBLIC ${INCLUDES_FROM_LIBS}) +target_compile_options(littlefs PRIVATE + $<$<AND:$<COMPILE_LANGUAGE:C>,$<CONFIG:DEBUG>>: ${COMMON_FLAGS} -Wno-unused-function -Og -g3> + $<$<AND:$<COMPILE_LANGUAGE:C>,$<CONFIG:RELEASE>>: ${COMMON_FLAGS} -Wno-unused-function -Os> + $<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CONFIG:DEBUG>>: ${COMMON_FLAGS} -Wno-unused-function -Og -g3 -fno-rtti> + $<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CONFIG:RELEASE>>: ${COMMON_FLAGS} -Wno-unused-function -Os -fno-rtti> + $<$<COMPILE_LANGUAGE:ASM>: -MP -MD -x assembler-with-cpp> + ) + # Build autonomous binary (without support for bootloader) set(EXECUTABLE_NAME "pinetime-app") set(EXECUTABLE_FILE_NAME ${EXECUTABLE_NAME}-${pinetime_VERSION_MAJOR}.${pinetime_VERSION_MINOR}.${pinetime_VERSION_PATCH}) set(NRF5_LINKER_SCRIPT "${CMAKE_SOURCE_DIR}/gcc_nrf52.ld") add_executable(${EXECUTABLE_NAME} ${SOURCE_FILES}) set_target_properties(${EXECUTABLE_NAME} PROPERTIES OUTPUT_NAME ${EXECUTABLE_FILE_NAME}) -target_link_libraries(${EXECUTABLE_NAME} nimble nrf-sdk lvgl) +target_link_libraries(${EXECUTABLE_NAME} nimble nrf-sdk lvgl littlefs) target_compile_options(${EXECUTABLE_NAME} PUBLIC $<$<AND:$<COMPILE_LANGUAGE:C>,$<CONFIG:DEBUG>>: ${COMMON_FLAGS} -Og -g3> $<$<AND:$<COMPILE_LANGUAGE:C>,$<CONFIG:RELEASE>>: ${COMMON_FLAGS} -Os> @@ -832,7 +857,7 @@ set(IMAGE_MCUBOOT_FILE_NAME ${EXECUTABLE_MCUBOOT_NAME}-image-${pinetime_VERSION_ set(DFU_MCUBOOT_FILE_NAME ${EXECUTABLE_MCUBOOT_NAME}-dfu-${pinetime_VERSION_MAJOR}.${pinetime_VERSION_MINOR}.${pinetime_VERSION_PATCH}.zip) set(NRF5_LINKER_SCRIPT_MCUBOOT "${CMAKE_SOURCE_DIR}/gcc_nrf52-mcuboot.ld") add_executable(${EXECUTABLE_MCUBOOT_NAME} ${SOURCE_FILES}) -target_link_libraries(${EXECUTABLE_MCUBOOT_NAME} nimble nrf-sdk lvgl) +target_link_libraries(${EXECUTABLE_MCUBOOT_NAME} nimble nrf-sdk lvgl littlefs) set_target_properties(${EXECUTABLE_MCUBOOT_NAME} PROPERTIES OUTPUT_NAME ${EXECUTABLE_MCUBOOT_FILE_NAME}) target_compile_options(${EXECUTABLE_MCUBOOT_NAME} PUBLIC $<$<AND:$<COMPILE_LANGUAGE:C>,$<CONFIG:DEBUG>>: ${COMMON_FLAGS} -Og -g3> @@ -868,7 +893,7 @@ endif() set(EXECUTABLE_RECOVERY_NAME "pinetime-recovery") set(EXECUTABLE_RECOVERY_FILE_NAME ${EXECUTABLE_RECOVERY_NAME}-${pinetime_VERSION_MAJOR}.${pinetime_VERSION_MINOR}.${pinetime_VERSION_PATCH}) add_executable(${EXECUTABLE_RECOVERY_NAME} ${RECOVERY_SOURCE_FILES}) -target_link_libraries(${EXECUTABLE_RECOVERY_NAME} nimble nrf-sdk) +target_link_libraries(${EXECUTABLE_RECOVERY_NAME} nimble nrf-sdk littlefs) set_target_properties(${EXECUTABLE_RECOVERY_NAME} PROPERTIES OUTPUT_NAME ${EXECUTABLE_RECOVERY_FILE_NAME}) target_compile_definitions(${EXECUTABLE_RECOVERY_NAME} PUBLIC "PINETIME_IS_RECOVERY") target_compile_options(${EXECUTABLE_RECOVERY_NAME} PUBLIC @@ -898,7 +923,7 @@ set(EXECUTABLE_RECOVERY_MCUBOOT_FILE_NAME ${EXECUTABLE_RECOVERY_MCUBOOT_NAME}-${ set(IMAGE_RECOVERY_MCUBOOT_FILE_NAME ${EXECUTABLE_RECOVERY_MCUBOOT_NAME}-image-${pinetime_VERSION_MAJOR}.${pinetime_VERSION_MINOR}.${pinetime_VERSION_PATCH}.bin) set(DFU_RECOVERY_MCUBOOT_FILE_NAME ${EXECUTABLE_RECOVERY_MCUBOOT_NAME}-dfu-${pinetime_VERSION_MAJOR}.${pinetime_VERSION_MINOR}.${pinetime_VERSION_PATCH}.zip) add_executable(${EXECUTABLE_RECOVERY_MCUBOOT_NAME} ${RECOVERY_SOURCE_FILES}) -target_link_libraries(${EXECUTABLE_RECOVERY_MCUBOOT_NAME} nimble nrf-sdk) +target_link_libraries(${EXECUTABLE_RECOVERY_MCUBOOT_NAME} nimble nrf-sdk littlefs) set_target_properties(${EXECUTABLE_RECOVERY_MCUBOOT_NAME} PROPERTIES OUTPUT_NAME ${EXECUTABLE_RECOVERY_MCUBOOT_FILE_NAME}) target_compile_definitions(${EXECUTABLE_RECOVERY_MCUBOOT_NAME} PUBLIC "PINETIME_IS_RECOVERY") target_compile_options(${EXECUTABLE_RECOVERY_MCUBOOT_NAME} PUBLIC diff --git a/src/FreeRTOSConfig.h b/src/FreeRTOSConfig.h index 07c152dc..adbbc8f0 100644 --- a/src/FreeRTOSConfig.h +++ b/src/FreeRTOSConfig.h @@ -77,7 +77,7 @@ #define configENABLE_BACKWARD_COMPATIBILITY 1 /* Hook function related definitions. */ -#define configUSE_IDLE_HOOK 1 +#define configUSE_IDLE_HOOK 0 #define configUSE_TICK_HOOK 0 #define configCHECK_FOR_STACK_OVERFLOW 0 #define configUSE_MALLOC_FAILED_HOOK 0 diff --git a/src/components/battery/BatteryController.cpp b/src/components/battery/BatteryController.cpp index bc146457..fa476ea3 100644 --- a/src/components/battery/BatteryController.cpp +++ b/src/components/battery/BatteryController.cpp @@ -1,9 +1,7 @@ #include "BatteryController.h" #include <hal/nrf_gpio.h> #include <nrfx_saadc.h> -#include <libraries/log/nrf_log.h> #include <algorithm> -#include <math.h> using namespace Pinetime::Controllers; @@ -14,16 +12,16 @@ Battery::Battery() { } void Battery::Init() { - nrf_gpio_cfg_input(chargingPin, (nrf_gpio_pin_pull_t) GPIO_PIN_CNF_PULL_Pullup); + nrf_gpio_cfg_input(chargingPin, static_cast<nrf_gpio_pin_pull_t> GPIO_PIN_CNF_PULL_Pullup); } void Battery::Update() { - isCharging = !nrf_gpio_pin_read(chargingPin); isPowerPresent = !nrf_gpio_pin_read(powerPresentPin); - if (isReading) + if (isReading) { return; + } // Non blocking read samples = 0; isReading = true; @@ -32,13 +30,13 @@ void Battery::Update() { nrfx_saadc_sample(); } -void Battery::adcCallbackStatic(nrfx_saadc_evt_t const* event) { +void Battery::AdcCallbackStatic(nrfx_saadc_evt_t const* event) { instance->SaadcEventHandler(event); } void Battery::SaadcInit() { nrfx_saadc_config_t adcConfig = NRFX_SAADC_DEFAULT_CONFIG; - APP_ERROR_CHECK(nrfx_saadc_init(&adcConfig, adcCallbackStatic)); + APP_ERROR_CHECK(nrfx_saadc_init(&adcConfig, AdcCallbackStatic)); nrf_saadc_channel_config_t adcChannelConfig = {.resistor_p = NRF_SAADC_RESISTOR_DISABLED, .resistor_n = NRF_SAADC_RESISTOR_DISABLED, @@ -54,23 +52,23 @@ void Battery::SaadcInit() { } void Battery::SaadcEventHandler(nrfx_saadc_evt_t const* p_event) { - - const float battery_max = 4.18; // maximum voltage of battery ( max charging voltage is 4.21 ) - const float battery_min = 3.20; // minimum voltage of battery before shutdown ( depends on the battery ) + const uint16_t battery_max = 4180; // maximum voltage of battery ( max charging voltage is 4.21 ) + const uint16_t battery_min = 3200; // minimum voltage of battery before shutdown ( depends on the battery ) if (p_event->type == NRFX_SAADC_EVT_DONE) { APP_ERROR_CHECK(nrfx_saadc_buffer_convert(&saadc_value, 1)); - voltage = (static_cast<float>(p_event->data.done.p_buffer[0]) * 2.04f) / (1024 / 3.0f); - voltage = roundf(voltage * 100) / 100; - - percentRemaining = static_cast<int>(((voltage - battery_min) / (battery_max - battery_min)) * 100); - + // A hardware voltage divider divides the battery voltage by 2 + // ADC gain is 1/5 + // thus adc_voltage = battery_voltage / 2 * gain = battery_voltage / 10 + // reference_voltage is 0.6V + // p_event->data.done.p_buffer[0] = (adc_voltage / reference_voltage) * 1024 + voltage = p_event->data.done.p_buffer[0] * 6000 / 1024; + percentRemaining = (voltage - battery_min) * 100 / (battery_max - battery_min); percentRemaining = std::max(percentRemaining, 0); percentRemaining = std::min(percentRemaining, 100); - - percentRemainingBuffer.insert(percentRemaining); + percentRemainingBuffer.Insert(percentRemaining); samples++; if (samples > percentRemainingSamples) { diff --git a/src/components/battery/BatteryController.h b/src/components/battery/BatteryController.h index 04bcf6b8..1333ad0e 100644 --- a/src/components/battery/BatteryController.h +++ b/src/components/battery/BatteryController.h @@ -19,7 +19,7 @@ namespace Pinetime { insert member function overwrites the next data to the current HEAD and moves the HEAD to the newly inserted value. */ - void insert(const int num) { + void Insert(const uint8_t num) { head %= cap; arr[head++] = num; if (sz != cap) { @@ -27,13 +27,13 @@ namespace Pinetime { } } - int GetAverage() const { + uint8_t GetAverage() const { int sum = std::accumulate(arr.begin(), arr.end(), 0); - return (sum / sz); + return static_cast<uint8_t>(sum / sz); } private: - std::array<int, N> arr; /**< internal array used to store the values*/ + std::array<uint8_t, N> arr; /**< internal array used to store the values*/ uint8_t sz; /**< The current size of the array.*/ uint8_t cap; /**< Total capacity of the CircBuffer.*/ uint8_t head; /**< The current head of the CircBuffer*/ @@ -46,17 +46,21 @@ namespace Pinetime { void Init(); void Update(); - int PercentRemaining() const { - return percentRemainingBuffer.GetAverage(); + uint8_t PercentRemaining() const { + auto avg = percentRemainingBuffer.GetAverage(); + avg = std::min(avg, static_cast<uint8_t>(100)); + avg = std::max(avg, static_cast<uint8_t>(0)); + return avg; } - float Voltage() const { + uint16_t Voltage() const { return voltage; } bool IsCharging() const { return isCharging; } + bool IsPowerPresent() const { return isPowerPresent; } @@ -71,7 +75,7 @@ namespace Pinetime { static constexpr uint32_t chargingPin = 12; static constexpr uint32_t powerPresentPin = 19; static constexpr nrf_saadc_input_t batteryVoltageAdcInput = NRF_SAADC_INPUT_AIN7; - float voltage = 0.0f; + uint16_t voltage = 0; int percentRemaining = -1; bool isCharging = false; @@ -80,10 +84,10 @@ namespace Pinetime { void SaadcInit(); void SaadcEventHandler(nrfx_saadc_evt_t const* p_event); - static void adcCallbackStatic(nrfx_saadc_evt_t const* event); + static void AdcCallbackStatic(nrfx_saadc_evt_t const* event); bool isReading = false; uint8_t samples = 0; }; } -}
\ No newline at end of file +} diff --git a/src/components/ble/BatteryInformationService.cpp b/src/components/ble/BatteryInformationService.cpp index 10a78d67..7f176904 100644 --- a/src/components/ble/BatteryInformationService.cpp +++ b/src/components/ble/BatteryInformationService.cpp @@ -17,7 +17,7 @@ BatteryInformationService::BatteryInformationService(Controllers::Battery& batte characteristicDefinition {{.uuid = (ble_uuid_t*) &batteryLevelUuid, .access_cb = BatteryInformationServiceCallback, .arg = this, - .flags = BLE_GATT_CHR_F_READ, + .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY, .val_handle = &batteryLevelHandle}, {0}}, serviceDefinition { @@ -48,4 +48,8 @@ int BatteryInformationService::OnBatteryServiceRequested(uint16_t connectionHand return (res == 0) ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES; } return 0; -}
\ No newline at end of file +} +void BatteryInformationService::NotifyBatteryLevel(uint16_t connectionHandle, uint8_t level) { + auto* om = ble_hs_mbuf_from_flat(&level, 1); + ble_gattc_notify_custom(connectionHandle, batteryLevelHandle, om); +} diff --git a/src/components/ble/BatteryInformationService.h b/src/components/ble/BatteryInformationService.h index 7d060909..1303fd6c 100644 --- a/src/components/ble/BatteryInformationService.h +++ b/src/components/ble/BatteryInformationService.h @@ -17,7 +17,7 @@ namespace Pinetime { void Init(); int OnBatteryServiceRequested(uint16_t connectionHandle, uint16_t attributeHandle, ble_gatt_access_ctxt* context); - + void NotifyBatteryLevel(uint16_t connectionHandle, uint8_t level); private: Controllers::Battery& batteryController; static constexpr uint16_t batteryInformationServiceId {0x180F}; diff --git a/src/components/ble/DfuService.cpp b/src/components/ble/DfuService.cpp index cec194cc..4179994d 100644 --- a/src/components/ble/DfuService.cpp +++ b/src/components/ble/DfuService.cpp @@ -121,6 +121,11 @@ int DfuService::WritePacketHandler(uint16_t connectionHandle, os_mbuf* om) { NRF_LOG_INFO( "[DFU] -> Start data received : SD size : %d, BT size : %d, app size : %d", softdeviceSize, bootloaderSize, applicationSize); + // wait until SystemTask has finished waking up all devices + while (systemTask.IsSleeping()) { + vTaskDelay(50); // 50ms + } + dfuImage.Erase(); uint8_t data[] {16, 1, 1}; @@ -261,13 +266,14 @@ int DfuService::ControlPointHandler(uint16_t connectionHandle, os_mbuf* om) { static_cast<uint8_t>(ErrorCodes::NoError)}; notificationManager.AsyncSend(connectionHandle, controlPointCharacteristicHandle, data, 3); } else { - bleController.State(Pinetime::Controllers::Ble::FirmwareUpdateStates::Error); NRF_LOG_INFO("Image Error : bad CRC"); uint8_t data[3] {static_cast<uint8_t>(Opcodes::Response), static_cast<uint8_t>(Opcodes::ValidateFirmware), static_cast<uint8_t>(ErrorCodes::CrcError)}; notificationManager.AsyncSend(connectionHandle, controlPointCharacteristicHandle, data, 3); + bleController.State(Pinetime::Controllers::Ble::FirmwareUpdateStates::Error); + Reset(); } return 0; @@ -278,10 +284,8 @@ int DfuService::ControlPointHandler(uint16_t connectionHandle, os_mbuf* om) { return 0; } NRF_LOG_INFO("[DFU] -> Activate image and reset!"); - bleController.StopFirmwareUpdate(); - systemTask.PushMessage(Pinetime::System::Messages::BleFirmwareUpdateFinished); - Reset(); bleController.State(Pinetime::Controllers::Ble::FirmwareUpdateStates::Validated); + Reset(); return 0; default: return 0; @@ -289,6 +293,7 @@ int DfuService::ControlPointHandler(uint16_t connectionHandle, os_mbuf* om) { } void DfuService::OnTimeout() { + bleController.State(Pinetime::Controllers::Ble::FirmwareUpdateStates::Error); Reset(); } @@ -302,7 +307,6 @@ void DfuService::Reset() { applicationSize = 0; expectedCrc = 0; notificationManager.Reset(); - bleController.State(Pinetime::Controllers::Ble::FirmwareUpdateStates::Error); bleController.StopFirmwareUpdate(); systemTask.PushMessage(Pinetime::System::Messages::BleFirmwareUpdateFinished); } diff --git a/src/components/ble/MusicService.cpp b/src/components/ble/MusicService.cpp index c420a576..74fe9522 100644 --- a/src/components/ble/MusicService.cpp +++ b/src/components/ble/MusicService.cpp @@ -18,79 +18,99 @@ #include "MusicService.h" #include "systemtask/SystemTask.h" -int MusicCallback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt, void* arg) { - return static_cast<Pinetime::Controllers::MusicService*>(arg)->OnCommand(conn_handle, attr_handle, ctxt); +namespace { + // 0000yyxx-78fc-48fe-8e23-433b3a1942d0 + constexpr ble_uuid128_t CharUuid(uint8_t x, uint8_t y) { + return ble_uuid128_t{ + .u = {.type = BLE_UUID_TYPE_128}, + .value = { 0xd0, 0x42, 0x19, 0x3a, 0x3b, 0x43, 0x23, 0x8e, 0xfe, 0x48, 0xfc, 0x78, x, y, 0x00, 0x00 } + }; + } + + // 00000000-78fc-48fe-8e23-433b3a1942d0 + constexpr ble_uuid128_t BaseUuid() { + return CharUuid(0x00, 0x00); + } + + constexpr ble_uuid128_t msUuid {BaseUuid()}; + + constexpr ble_uuid128_t msEventCharUuid {CharUuid(0x01, 0x00)}; + constexpr ble_uuid128_t msStatusCharUuid {CharUuid(0x02, 0x00)}; + constexpr ble_uuid128_t msArtistCharUuid {CharUuid(0x03, 0x00)}; + constexpr ble_uuid128_t msTrackCharUuid {CharUuid(0x04, 0x00)}; + constexpr ble_uuid128_t msAlbumCharUuid {CharUuid(0x05, 0x00)}; + constexpr ble_uuid128_t msPositionCharUuid {CharUuid(0x06, 0x00)}; + constexpr ble_uuid128_t msTotalLengthCharUuid {CharUuid(0x07, 0x00)}; + constexpr ble_uuid128_t msTrackNumberCharUuid {CharUuid(0x08, 0x00)}; + constexpr ble_uuid128_t msTrackTotalCharUuid {CharUuid(0x09, 0x00)}; + constexpr ble_uuid128_t msPlaybackSpeedCharUuid {CharUuid(0x0a, 0x00)}; + constexpr ble_uuid128_t msRepeatCharUuid {CharUuid(0x0b, 0x00)}; + constexpr ble_uuid128_t msShuffleCharUuid {CharUuid(0x0c, 0x00)}; + + int MusicCallback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt, void* arg) { + return static_cast<Pinetime::Controllers::MusicService*>(arg)->OnCommand(conn_handle, attr_handle, ctxt); + } } Pinetime::Controllers::MusicService::MusicService(Pinetime::System::SystemTask& system) : m_system(system) { - characteristicDefinition[0] = {.uuid = reinterpret_cast<ble_uuid_t*>(&msEventCharUuid), + characteristicDefinition[0] = {.uuid = &msEventCharUuid.u, .access_cb = MusicCallback, .arg = this, .flags = BLE_GATT_CHR_F_NOTIFY, .val_handle = &eventHandle}; - characteristicDefinition[1] = {.uuid = reinterpret_cast<ble_uuid_t*>(&msStatusCharUuid), + characteristicDefinition[1] = {.uuid = &msStatusCharUuid.u, .access_cb = MusicCallback, .arg = this, .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ}; - characteristicDefinition[2] = {.uuid = reinterpret_cast<ble_uuid_t*>(&msTrackCharUuid), + characteristicDefinition[2] = {.uuid = &msTrackCharUuid.u, .access_cb = MusicCallback, .arg = this, .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ}; - characteristicDefinition[3] = {.uuid = reinterpret_cast<ble_uuid_t*>(&msArtistCharUuid), + characteristicDefinition[3] = {.uuid = &msArtistCharUuid.u, .access_cb = MusicCallback, .arg = this, .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ}; - characteristicDefinition[4] = {.uuid = reinterpret_cast<ble_uuid_t*>(&msAlbumCharUuid), + characteristicDefinition[4] = {.uuid = &msAlbumCharUuid.u, .access_cb = MusicCallback, .arg = this, .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ}; - characteristicDefinition[5] = {.uuid = reinterpret_cast<ble_uuid_t*>(&msPositionCharUuid), + characteristicDefinition[5] = {.uuid = &msPositionCharUuid.u, .access_cb = MusicCallback, .arg = this, .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ}; - characteristicDefinition[6] = {.uuid = reinterpret_cast<ble_uuid_t*>(&msTotalLengthCharUuid), + characteristicDefinition[6] = {.uuid = &msTotalLengthCharUuid.u, .access_cb = MusicCallback, .arg = this, .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ}; - characteristicDefinition[7] = {.uuid = reinterpret_cast<ble_uuid_t*>(&msTotalLengthCharUuid), + characteristicDefinition[7] = {.uuid = &msTotalLengthCharUuid.u, .access_cb = MusicCallback, .arg = this, .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ}; - characteristicDefinition[8] = {.uuid = reinterpret_cast<ble_uuid_t*>(&msTrackNumberCharUuid), + characteristicDefinition[8] = {.uuid = &msTrackNumberCharUuid.u, .access_cb = MusicCallback, .arg = this, .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ}; - characteristicDefinition[9] = {.uuid = reinterpret_cast<ble_uuid_t*>(&msTrackTotalCharUuid), + characteristicDefinition[9] = {.uuid = &msTrackTotalCharUuid.u, .access_cb = MusicCallback, .arg = this, .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ}; - characteristicDefinition[10] = {.uuid = reinterpret_cast<ble_uuid_t*>(&msPlaybackSpeedCharUuid), + characteristicDefinition[10] = {.uuid = &msPlaybackSpeedCharUuid.u, .access_cb = MusicCallback, .arg = this, .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ}; - characteristicDefinition[11] = {.uuid = reinterpret_cast<ble_uuid_t*>(&msRepeatCharUuid), + characteristicDefinition[11] = {.uuid = &msRepeatCharUuid.u, .access_cb = MusicCallback, .arg = this, .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ}; - characteristicDefinition[12] = {.uuid = reinterpret_cast<ble_uuid_t*>(&msShuffleCharUuid), + characteristicDefinition[12] = {.uuid = &msShuffleCharUuid.u, .access_cb = MusicCallback, .arg = this, .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ}; characteristicDefinition[13] = {0}; serviceDefinition[0] = { - .type = BLE_GATT_SVC_TYPE_PRIMARY, .uuid = reinterpret_cast<ble_uuid_t*>(&msUuid), .characteristics = characteristicDefinition}; + .type = BLE_GATT_SVC_TYPE_PRIMARY, .uuid = &msUuid.u, .characteristics = characteristicDefinition}; serviceDefinition[1] = {0}; - - artistName = "Waiting for"; - albumName = ""; - trackName = "track information.."; - playing = false; - repeat = false; - shuffle = false; - playbackSpeed = 1.0f; - trackProgress = 0; - trackLength = 0; } void Pinetime::Controllers::MusicService::Init() { @@ -109,27 +129,27 @@ int Pinetime::Controllers::MusicService::OnCommand(uint16_t conn_handle, uint16_ data[notifSize] = '\0'; os_mbuf_copydata(ctxt->om, 0, notifSize, data); char* s = &data[0]; - if (ble_uuid_cmp(ctxt->chr->uuid, reinterpret_cast<ble_uuid_t*>(&msArtistCharUuid)) == 0) { + if (ble_uuid_cmp(ctxt->chr->uuid, &msArtistCharUuid.u) == 0) { artistName = s; - } else if (ble_uuid_cmp(ctxt->chr->uuid, reinterpret_cast<ble_uuid_t*>(&msTrackCharUuid)) == 0) { + } else if (ble_uuid_cmp(ctxt->chr->uuid, &msTrackCharUuid.u) == 0) { trackName = s; - } else if (ble_uuid_cmp(ctxt->chr->uuid, reinterpret_cast<ble_uuid_t*>(&msAlbumCharUuid)) == 0) { + } else if (ble_uuid_cmp(ctxt->chr->uuid, &msAlbumCharUuid.u) == 0) { albumName = s; - } else if (ble_uuid_cmp(ctxt->chr->uuid, reinterpret_cast<ble_uuid_t*>(&msStatusCharUuid)) == 0) { + } else if (ble_uuid_cmp(ctxt->chr->uuid, &msStatusCharUuid.u) == 0) { playing = s[0]; - } else if (ble_uuid_cmp(ctxt->chr->uuid, reinterpret_cast<ble_uuid_t*>(&msRepeatCharUuid)) == 0) { + } else if (ble_uuid_cmp(ctxt->chr->uuid, &msRepeatCharUuid.u) == 0) { repeat = s[0]; - } else if (ble_uuid_cmp(ctxt->chr->uuid, reinterpret_cast<ble_uuid_t*>(&msShuffleCharUuid)) == 0) { + } else if (ble_uuid_cmp(ctxt->chr->uuid, &msShuffleCharUuid.u) == 0) { shuffle = s[0]; - } else if (ble_uuid_cmp(ctxt->chr->uuid, reinterpret_cast<ble_uuid_t*>(&msPositionCharUuid)) == 0) { + } else if (ble_uuid_cmp(ctxt->chr->uuid, &msPositionCharUuid.u) == 0) { trackProgress = (s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3]; - } else if (ble_uuid_cmp(ctxt->chr->uuid, reinterpret_cast<ble_uuid_t*>(&msTotalLengthCharUuid)) == 0) { + } else if (ble_uuid_cmp(ctxt->chr->uuid, &msTotalLengthCharUuid.u) == 0) { trackLength = (s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3]; - } else if (ble_uuid_cmp(ctxt->chr->uuid, reinterpret_cast<ble_uuid_t*>(&msTrackNumberCharUuid)) == 0) { + } else if (ble_uuid_cmp(ctxt->chr->uuid, &msTrackNumberCharUuid.u) == 0) { trackNumber = (s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3]; - } else if (ble_uuid_cmp(ctxt->chr->uuid, reinterpret_cast<ble_uuid_t*>(&msTrackTotalCharUuid)) == 0) { + } else if (ble_uuid_cmp(ctxt->chr->uuid, &msTrackTotalCharUuid.u) == 0) { tracksTotal = (s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3]; - } else if (ble_uuid_cmp(ctxt->chr->uuid, reinterpret_cast<ble_uuid_t*>(&msPlaybackSpeedCharUuid)) == 0) { + } else if (ble_uuid_cmp(ctxt->chr->uuid, &msPlaybackSpeedCharUuid.u) == 0) { playbackSpeed = static_cast<float>(((s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3])) / 100.0f; } } @@ -174,4 +194,4 @@ void Pinetime::Controllers::MusicService::event(char event) { } ble_gattc_notify_custom(connectionHandle, eventHandle, om); -}
\ No newline at end of file +} diff --git a/src/components/ble/MusicService.h b/src/components/ble/MusicService.h index 0b5a7464..1ad9a420 100644 --- a/src/components/ble/MusicService.h +++ b/src/components/ble/MusicService.h @@ -26,18 +26,11 @@ #undef max #undef min -// 00000000-78fc-48fe-8e23-433b3a1942d0 -#define MUSIC_SERVICE_UUID_BASE \ - { 0xd0, 0x42, 0x19, 0x3a, 0x3b, 0x43, 0x23, 0x8e, 0xfe, 0x48, 0xfc, 0x78, 0x00, 0x00, 0x00, 0x00 } -#define MUSIC_SERVICE_CHAR_UUID(x, y) \ - { 0xd0, 0x42, 0x19, 0x3a, 0x3b, 0x43, 0x23, 0x8e, 0xfe, 0x48, 0xfc, 0x78, x, y, 0x00, 0x00 } - namespace Pinetime { namespace System { class SystemTask; } namespace Controllers { - class MusicService { public: explicit MusicService(Pinetime::System::SystemTask& system); @@ -73,41 +66,26 @@ namespace Pinetime { enum MusicStatus { NotPlaying = 0x00, Playing = 0x01 }; private: - ble_uuid128_t msUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = MUSIC_SERVICE_UUID_BASE}; - - ble_uuid128_t msEventCharUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = MUSIC_SERVICE_CHAR_UUID(0x01, 0x00)}; - ble_uuid128_t msStatusCharUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = MUSIC_SERVICE_CHAR_UUID(0x02, 0x00)}; - ble_uuid128_t msArtistCharUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = MUSIC_SERVICE_CHAR_UUID(0x03, 0x00)}; - ble_uuid128_t msTrackCharUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = MUSIC_SERVICE_CHAR_UUID(0x04, 0x00)}; - ble_uuid128_t msAlbumCharUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = MUSIC_SERVICE_CHAR_UUID(0x05, 0x00)}; - ble_uuid128_t msPositionCharUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = MUSIC_SERVICE_CHAR_UUID(0x06, 0x00)}; - ble_uuid128_t msTotalLengthCharUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = MUSIC_SERVICE_CHAR_UUID(0x07, 0x00)}; - ble_uuid128_t msTrackNumberCharUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = MUSIC_SERVICE_CHAR_UUID(0x08, 0x00)}; - ble_uuid128_t msTrackTotalCharUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = MUSIC_SERVICE_CHAR_UUID(0x09, 0x00)}; - ble_uuid128_t msPlaybackSpeedCharUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = MUSIC_SERVICE_CHAR_UUID(0x0a, 0x00)}; - ble_uuid128_t msRepeatCharUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = MUSIC_SERVICE_CHAR_UUID(0x0b, 0x00)}; - ble_uuid128_t msShuffleCharUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = MUSIC_SERVICE_CHAR_UUID(0x0c, 0x00)}; - struct ble_gatt_chr_def characteristicDefinition[14]; struct ble_gatt_svc_def serviceDefinition[2]; - uint16_t eventHandle; + uint16_t eventHandle {}; - std::string artistName; - std::string albumName; - std::string trackName; + std::string artistName {"Waiting for"}; + std::string albumName {}; + std::string trackName {"track information.."}; - bool playing; + bool playing {false}; - int trackProgress; - int trackLength; - int trackNumber; - int tracksTotal; + int trackProgress {0}; + int trackLength {0}; + int trackNumber {}; + int tracksTotal {}; - float playbackSpeed; + float playbackSpeed {1.0f}; - bool repeat; - bool shuffle; + bool repeat {false}; + bool shuffle {false}; Pinetime::System::SystemTask& m_system; }; diff --git a/src/components/ble/NimbleController.cpp b/src/components/ble/NimbleController.cpp index 2c1d0f99..5eb227bf 100644 --- a/src/components/ble/NimbleController.cpp +++ b/src/components/ble/NimbleController.cpp @@ -235,3 +235,9 @@ void NimbleController::StartDiscovery() { uint16_t NimbleController::connHandle() { return connectionHandle; } + +void NimbleController::NotifyBatteryLevel(uint8_t level) { + if(connectionHandle != BLE_HS_CONN_HANDLE_NONE) { + batteryInformationService.NotifyBatteryLevel(connectionHandle, level); + } +} diff --git a/src/components/ble/NimbleController.h b/src/components/ble/NimbleController.h index 5dd01e42..0cfe983c 100644 --- a/src/components/ble/NimbleController.h +++ b/src/components/ble/NimbleController.h @@ -70,6 +70,7 @@ namespace Pinetime { }; uint16_t connHandle(); + void NotifyBatteryLevel(uint8_t level); private: static constexpr const char* deviceName = "InfiniTime"; @@ -92,7 +93,7 @@ namespace Pinetime { HeartRateService heartRateService; uint8_t addrType; // 1 = Random, 0 = PUBLIC - uint16_t connectionHandle = 0; + uint16_t connectionHandle = BLE_HS_CONN_HANDLE_NONE; ble_uuid128_t dfuServiceUuid { .u {.type = BLE_UUID_TYPE_128}, diff --git a/src/components/datetime/DateTimeController.cpp b/src/components/datetime/DateTimeController.cpp index 28a70abc..d6aa83c8 100644 --- a/src/components/datetime/DateTimeController.cpp +++ b/src/components/datetime/DateTimeController.cpp @@ -55,9 +55,9 @@ void DateTime::UpdateTime(uint32_t systickCounter) { auto time = date::make_time(currentDateTime - dp); auto yearMonthDay = date::year_month_day(dp); - year = (int) yearMonthDay.year(); - month = static_cast<Months>((unsigned) yearMonthDay.month()); - day = (unsigned) yearMonthDay.day(); + year = static_cast<int>(yearMonthDay.year()); + month = static_cast<Months>(static_cast<unsigned>(yearMonthDay.month())); + day = static_cast<unsigned>(yearMonthDay.day()); dayOfWeek = static_cast<Days>(date::weekday(yearMonthDay).iso_encoding()); hour = time.hours().count(); @@ -75,31 +75,31 @@ void DateTime::UpdateTime(uint32_t systickCounter) { } const char* DateTime::MonthShortToString() { - return DateTime::MonthsString[(uint8_t) month]; + return DateTime::MonthsString[static_cast<uint8_t>(month)]; } const char* DateTime::MonthShortToStringLow() { - return DateTime::MonthsStringLow[(uint8_t) month]; + return DateTime::MonthsStringLow[static_cast<uint8_t>(month)]; } const char* DateTime::MonthsToStringLow() { - return DateTime::MonthsLow[(uint8_t) month]; + return DateTime::MonthsLow[static_cast<uint8_t>(month)]; } const char* DateTime::DayOfWeekToString() { - return DateTime::DaysString[(uint8_t) dayOfWeek]; + return DateTime::DaysString[static_cast<uint8_t>(dayOfWeek)]; } const char* DateTime::DayOfWeekShortToString() { - return DateTime::DaysStringShort[(uint8_t) dayOfWeek]; + return DateTime::DaysStringShort[static_cast<uint8_t>(dayOfWeek)]; } const char* DateTime::DayOfWeekToStringLow() { - return DateTime::DaysStringLow[(uint8_t) dayOfWeek]; + return DateTime::DaysStringLow[static_cast<uint8_t>(dayOfWeek)]; } const char* DateTime::DayOfWeekShortToStringLow() { - return DateTime::DaysStringShortLow[(uint8_t) dayOfWeek]; + return DateTime::DaysStringShortLow[static_cast<uint8_t>(dayOfWeek)]; } void DateTime::Register(Pinetime::System::SystemTask* systemTask) { diff --git a/src/components/fs/FS.cpp b/src/components/fs/FS.cpp new file mode 100644 index 00000000..857e6bf9 --- /dev/null +++ b/src/components/fs/FS.cpp @@ -0,0 +1,197 @@ +#include "FS.h" +#include <cstring> +#include <littlefs/lfs.h> +#include <lvgl/lvgl.h> + +using namespace Pinetime::Controllers; + +FS::FS(Pinetime::Drivers::SpiNorFlash& driver) : + flashDriver{ driver }, + lfsConfig{ + .context = this, + .read = SectorRead, + .prog = SectorProg, + .erase = SectorErase, + .sync = SectorSync, + + .read_size = 16, + .prog_size = 8, + .block_size = blockSize, + .block_count = size / blockSize, + .block_cycles = 1000u, + + .cache_size = 16, + .lookahead_size = 16, + + .name_max = 50, + .attr_max = 50, + } +{ } + + +void FS::Init() { + + // try mount + int err = lfs_mount(&lfs, &lfsConfig); + + // reformat if we can't mount the filesystem + // this should only happen on the first boot + if (err != LFS_ERR_OK) { + lfs_format(&lfs, &lfsConfig); + err = lfs_mount(&lfs, &lfsConfig); + if (err != LFS_ERR_OK) { + return; + } + } + +#ifndef PINETIME_IS_RECOVERY + VerifyResource(); + LVGLFileSystemInit(); +#endif + +} + +void FS::VerifyResource() { + // validate the resource metadata + resourcesValid = true; +} + +int FS::FileOpen(lfs_file_t* file_p, const char* fileName, const int flags) { + return lfs_file_open(&lfs, file_p, fileName, flags); +} + +int FS::FileClose(lfs_file_t* file_p) { + return lfs_file_close(&lfs, file_p); +} + +int FS::FileRead(lfs_file_t* file_p, uint8_t* buff, uint32_t size) { + return lfs_file_read(&lfs, file_p, buff, size); +} + +int FS::FileWrite(lfs_file_t* file_p, const uint8_t* buff, uint32_t size) { + return lfs_file_write(&lfs, file_p, buff, size); +} + +int FS::FileSeek(lfs_file_t* file_p, uint32_t pos) { + return lfs_file_seek(&lfs, file_p, pos, LFS_SEEK_SET); +} + +int FS::FileDelete(const char* fileName) { + return lfs_remove(&lfs, fileName); +} + + +int FS::DirCreate(const char* path) { + return lfs_mkdir(&lfs, path); +} + +// Delete directory and all files inside +int FS::DirDelete(const char* path) { + + lfs_dir_t lfs_dir; + lfs_info entryInfo; + + int err; + err = lfs_dir_open(&lfs, &lfs_dir, path); + if (err) { + return err; + } + while (lfs_dir_read(&lfs, &lfs_dir, &entryInfo)) { + lfs_remove(&lfs, entryInfo.name); + } + lfs_dir_close(&lfs, &lfs_dir); + return LFS_ERR_OK; +} + +/* + + ----------- Interface between littlefs and SpiNorFlash ----------- + +*/ +int FS::SectorSync(const struct lfs_config* c) { + return 0; +} + +int FS::SectorErase(const struct lfs_config* c, lfs_block_t block) { + Pinetime::Controllers::FS& lfs = *(static_cast<Pinetime::Controllers::FS*>(c->context)); + const size_t address = startAddress + (block * blockSize); + lfs.flashDriver.SectorErase(address); + return lfs.flashDriver.EraseFailed() ? -1 : 0; +} + +int FS::SectorProg(const struct lfs_config* c, lfs_block_t block, lfs_off_t off, const void* buffer, lfs_size_t size) { + Pinetime::Controllers::FS& lfs = *(static_cast<Pinetime::Controllers::FS*>(c->context)); + const size_t address = startAddress + (block * blockSize) + off; + lfs.flashDriver.Write(address, (uint8_t*) buffer, size); + return lfs.flashDriver.ProgramFailed() ? -1 : 0; +} + +int FS::SectorRead(const struct lfs_config* c, lfs_block_t block, lfs_off_t off, void* buffer, lfs_size_t size) { + Pinetime::Controllers::FS& lfs = *(static_cast<Pinetime::Controllers::FS*>(c->context)); + const size_t address = startAddress + (block * blockSize) + off; + lfs.flashDriver.Read(address, static_cast<uint8_t*>(buffer), size); + return 0; +} + +/* + + ----------- LVGL filesystem integration ----------- + +*/ + +namespace { + lv_fs_res_t lvglOpen(lv_fs_drv_t* drv, void* file_p, const char* path, lv_fs_mode_t mode) { + + lfs_file_t* file = static_cast<lfs_file_t*>(file_p); + FS* filesys = static_cast<FS*>(drv->user_data); + filesys->FileOpen(file, path, LFS_O_RDONLY); + + if (file->type == 0) { + return LV_FS_RES_FS_ERR; + } + else { + return LV_FS_RES_OK; + } + } + + lv_fs_res_t lvglClose(lv_fs_drv_t* drv, void* file_p) { + FS* filesys = static_cast<FS*>(drv->user_data); + lfs_file_t* file = static_cast<lfs_file_t*>(file_p); + filesys->FileClose(file); + + return LV_FS_RES_OK; + } + + lv_fs_res_t lvglRead(lv_fs_drv_t* drv, void* file_p, void* buf, uint32_t btr, uint32_t* br) { + FS* filesys = static_cast<FS*>(drv->user_data); + lfs_file_t* file = static_cast<lfs_file_t*>(file_p); + filesys->FileRead(file, static_cast<uint8_t*>(buf), btr); + *br = btr; + return LV_FS_RES_OK; + } + + lv_fs_res_t lvglSeek(lv_fs_drv_t* drv, void* file_p, uint32_t pos) { + FS* filesys = static_cast<FS*>(drv->user_data); + lfs_file_t* file = static_cast<lfs_file_t*>(file_p); + filesys->FileSeek(file, pos); + return LV_FS_RES_OK; + } +} + +void FS::LVGLFileSystemInit() { + + lv_fs_drv_t fs_drv; + lv_fs_drv_init(&fs_drv); + + fs_drv.file_size = sizeof(lfs_file_t); + fs_drv.letter = 'F'; + fs_drv.open_cb = lvglOpen; + fs_drv.close_cb = lvglClose; + fs_drv.read_cb = lvglRead; + fs_drv.seek_cb = lvglSeek; + + fs_drv.user_data = this; + + lv_fs_drv_register(&fs_drv); + +}
\ No newline at end of file diff --git a/src/components/fs/FS.h b/src/components/fs/FS.h new file mode 100644 index 00000000..1f2eb7e0 --- /dev/null +++ b/src/components/fs/FS.h @@ -0,0 +1,71 @@ +#pragma once + +#include <cstdint> +#include "drivers/SpiNorFlash.h" +#include <littlefs/lfs.h> + +namespace Pinetime { + namespace Controllers { + class FS { + public: + FS(Pinetime::Drivers::SpiNorFlash&); + + void Init(); + void LVGLFileSystemInit(); + + int FileOpen(lfs_file_t* file_p, const char* fileName, const int flags); + int FileClose(lfs_file_t* file_p); + int FileRead(lfs_file_t* file_p, uint8_t* buff, uint32_t size); + int FileWrite(lfs_file_t* file_p, const uint8_t* buff, uint32_t size); + int FileSeek(lfs_file_t* file_p, uint32_t pos); + + int FileDelete(const char* fileName); + + int DirCreate(const char* path); + int DirDelete(const char* path); + + void VerifyResource(); + + private: + + Pinetime::Drivers::SpiNorFlash& flashDriver; + + /* + * External Flash MAP (4 MBytes) + * + * 0x000000 +---------------------------------------+ + * | Bootloader Assets | + * | 256 KBytes | + * | | + * 0x040000 +---------------------------------------+ + * | OTA | + * | 464 KBytes | + * | | + * | | + * | | + * 0x0B4000 +---------------------------------------+ + * | File System | + * | | + * | | + * | | + * | | + * 0x400000 +---------------------------------------+ + * + */ + static constexpr size_t startAddress = 0x0B4000; + static constexpr size_t size = 0x3C0000; + static constexpr size_t blockSize = 4096; + + bool resourcesValid = false; + const struct lfs_config lfsConfig; + + lfs_t lfs; + + static int SectorSync(const struct lfs_config* c); + static int SectorErase(const struct lfs_config* c, lfs_block_t block); + static int SectorProg(const struct lfs_config* c, lfs_block_t block, lfs_off_t off, const void* buffer, lfs_size_t size); + static int SectorRead(const struct lfs_config* c, lfs_block_t block, lfs_off_t off, void* buffer, lfs_size_t size); + + }; + } +} diff --git a/src/components/motion/MotionController.cpp b/src/components/motion/MotionController.cpp index e9ee314b..b0dbada4 100644 --- a/src/components/motion/MotionController.cpp +++ b/src/components/motion/MotionController.cpp @@ -34,3 +34,10 @@ bool MotionController::ShouldWakeUp(bool isSleeping) { void MotionController::IsSensorOk(bool isOk) { isSensorOk = isOk; } +void MotionController::Init(Pinetime::Drivers::Bma421::DeviceTypes types) { + switch(types){ + case Drivers::Bma421::DeviceTypes::BMA421: this->deviceType = DeviceTypes::BMA421; break; + case Drivers::Bma421::DeviceTypes::BMA425: this->deviceType = DeviceTypes::BMA425; break; + default: this->deviceType = DeviceTypes::Unknown; break; + } +} diff --git a/src/components/motion/MotionController.h b/src/components/motion/MotionController.h index 3a238262..ff715093 100644 --- a/src/components/motion/MotionController.h +++ b/src/components/motion/MotionController.h @@ -1,11 +1,18 @@ #pragma once #include <cstdint> +#include <drivers/Bma421.h> namespace Pinetime { namespace Controllers { class MotionController { public: + enum class DeviceTypes{ + Unknown, + BMA421, + BMA425, + }; + void Update(int16_t x, int16_t y, int16_t z, uint32_t nbSteps); int16_t X() const { @@ -27,6 +34,12 @@ namespace Pinetime { return isSensorOk; } + DeviceTypes DeviceType() const { + return deviceType; + } + + void Init(Pinetime::Drivers::Bma421::DeviceTypes types); + private: uint32_t nbSteps; int16_t x; @@ -34,6 +47,7 @@ namespace Pinetime { int16_t z; int16_t lastYForWakeUp = 0; bool isSensorOk = false; + DeviceTypes deviceType = DeviceTypes::Unknown; }; } }
\ No newline at end of file diff --git a/src/components/settings/Settings.cpp b/src/components/settings/Settings.cpp index 071940b8..37c09f91 100644 --- a/src/components/settings/Settings.cpp +++ b/src/components/settings/Settings.cpp @@ -4,108 +4,44 @@ using namespace Pinetime::Controllers; -struct SettingsHeader { - uint8_t isActive; // 0xF1 = Block is active, 0xF0 = Block is inactive - uint16_t version; // Current version, to verify if the saved data is for the current Version -}; - -#define HEADER_SIZE sizeof(SettingsHeader) - -Settings::Settings(Pinetime::Drivers::SpiNorFlash& spiNorFlash) : spiNorFlash {spiNorFlash} { +Settings::Settings(Pinetime::Controllers::FS& fs) : fs {fs} { } void Settings::Init() { // Load default settings from Flash - LoadSettingsFromFlash(); + LoadSettingsFromFile(); } void Settings::SaveSettings() { // verify if is necessary to save if (settingsChanged) { - SaveSettingsToFlash(); + SaveSettingsToFile(); } settingsChanged = false; } -bool Settings::FindHeader() { - SettingsHeader settingsHeader; - uint8_t bufferHead[sizeof(settingsHeader)]; - - for (uint8_t block = 0; block < 10; block++) { +void Settings::LoadSettingsFromFile() { + SettingsData bufferSettings; + lfs_file_t settingsFile; - spiNorFlash.Read(settingsBaseAddr + (block * 0x1000), bufferHead, sizeof(settingsHeader)); - std::memcpy(&settingsHeader, bufferHead, sizeof(settingsHeader)); - if (settingsHeader.isActive == 0xF1 && settingsHeader.version == settingsVersion) { - settingsFlashBlock = block; - return true; - } + if ( fs.FileOpen(&settingsFile, "/settings.dat", LFS_O_RDWR | LFS_O_CREAT) != LFS_ERR_OK) { + return; } - return false; -} - -void Settings::ReadSettingsData() { - uint8_t bufferSettings[sizeof(settings)]; - spiNorFlash.Read(settingsBaseAddr + (settingsFlashBlock * 0x1000) + HEADER_SIZE, bufferSettings, sizeof(settings)); - std::memcpy(&settings, bufferSettings, sizeof(settings)); -} - -void Settings::EraseBlock() { - - spiNorFlash.SectorErase(settingsBaseAddr + (settingsFlashBlock * 0x1000)); -} - -void Settings::SetHeader(bool state) { - SettingsHeader settingsHeader; - uint8_t bufferHead[sizeof(settingsHeader)]; - settingsHeader.isActive = state ? 0xF1 : 0xF0; - settingsHeader.version = settingsVersion; - - std::memcpy(bufferHead, &settingsHeader, sizeof(settingsHeader)); - spiNorFlash.Write(settingsBaseAddr + (settingsFlashBlock * 0x1000), bufferHead, sizeof(settingsHeader)); -} - -void Settings::SaveSettingsData() { - uint8_t bufferSettings[sizeof(settings)]; - std::memcpy(bufferSettings, &settings, sizeof(settings)); - spiNorFlash.Write(settingsBaseAddr + (settingsFlashBlock * 0x1000) + HEADER_SIZE, bufferSettings, sizeof(settings)); -} - -void Settings::LoadSettingsFromFlash() { - - if (settingsFlashBlock == 99) { - // Find current Block, if can't find use default settings and set block to 0 ans save ! - if (FindHeader()) { - ReadSettingsData(); - } else { - SaveSettingsToFlash(); - } - } else { - // Read Settings from flash... - // never used :) - ReadSettingsData(); + fs.FileRead(&settingsFile, reinterpret_cast<uint8_t*>(&bufferSettings), sizeof(settings)); + fs.FileClose(&settingsFile); + if ( bufferSettings.version == settingsVersion ) { + settings = bufferSettings; } } -void Settings::SaveSettingsToFlash() { - - // calculate where to save... - // mark current to inactive - // erase the new location and save - // set settingsFlashBlock - - // if first time hever, only saves to block 0 and set settingsFlashBlock +void Settings::SaveSettingsToFile() { + lfs_file_t settingsFile; - if (settingsFlashBlock != 99) { - SetHeader(false); + if ( fs.FileOpen(&settingsFile, "/settings.dat", LFS_O_RDWR | LFS_O_CREAT) != LFS_ERR_OK) { + return; } - - settingsFlashBlock++; - if (settingsFlashBlock > 9) - settingsFlashBlock = 0; - - EraseBlock(); - SetHeader(true); - SaveSettingsData(); + fs.FileWrite(&settingsFile, reinterpret_cast<uint8_t*>(&settings), sizeof(settings)); + fs.FileClose(&settingsFile); } diff --git a/src/components/settings/Settings.h b/src/components/settings/Settings.h index 4409425b..93d6d217 100644 --- a/src/components/settings/Settings.h +++ b/src/components/settings/Settings.h @@ -1,26 +1,32 @@ #pragma once #include <cstdint> +#include <bitset> #include "components/datetime/DateTimeController.h" #include "components/brightness/BrightnessController.h" -#include "drivers/SpiNorFlash.h" +#include "components/fs/FS.h" #include "drivers/Cst816s.h" namespace Pinetime { namespace Controllers { class Settings { public: - enum class ClockType { H24, H12 }; - enum class Vibration { ON, OFF }; - enum class WakeUpMode { None, SingleTap, DoubleTap, RaiseWrist }; + enum class ClockType : uint8_t { H24, H12 }; + enum class Vibration : uint8_t { ON, OFF }; + enum class WakeUpMode : uint8_t { + SingleTap = 0, + DoubleTap = 1, + RaiseWrist = 2, + }; - Settings(Pinetime::Drivers::SpiNorFlash& spiNorFlash); + Settings(Pinetime::Controllers::FS& fs); void Init(); void SaveSettings(); void SetClockFace(uint8_t face) { - if (face != settings.clockFace) + if (face != settings.clockFace) { settingsChanged = true; + } settings.clockFace = face; }; uint8_t GetClockFace() const { @@ -42,8 +48,9 @@ namespace Pinetime { }; void SetClockType(ClockType clocktype) { - if (clocktype != settings.clockType) + if (clocktype != settings.clockType) { settingsChanged = true; + } settings.clockType = clocktype; }; ClockType GetClockType() const { @@ -51,8 +58,9 @@ namespace Pinetime { }; void SetVibrationStatus(Vibration status) { - if (status != settings.vibrationStatus) + if (status != settings.vibrationStatus) { settingsChanged = true; + } settings.vibrationStatus = status; }; Vibration GetVibrationStatus() const { @@ -60,26 +68,47 @@ namespace Pinetime { }; void SetScreenTimeOut(uint32_t timeout) { - if (timeout != settings.screenTimeOut) + if (timeout != settings.screenTimeOut) { settingsChanged = true; + } settings.screenTimeOut = timeout; }; uint32_t GetScreenTimeOut() const { return settings.screenTimeOut; }; - void setWakeUpMode(WakeUpMode wakeUp) { - if (wakeUp != settings.wakeUpMode) + void setWakeUpMode(WakeUpMode wakeUp, bool enabled) { + if (!isWakeUpModeOn(wakeUp)) { settingsChanged = true; - settings.wakeUpMode = wakeUp; - }; - WakeUpMode getWakeUpMode() const { + } + settings.wakeUpMode.set(static_cast<size_t>(wakeUp), enabled); + // Handle special behavior + if (enabled) { + switch (wakeUp) { + case WakeUpMode::SingleTap: + settings.wakeUpMode.set(static_cast<size_t>(WakeUpMode::DoubleTap), false); + break; + case WakeUpMode::DoubleTap: + settings.wakeUpMode.set(static_cast<size_t>(WakeUpMode::SingleTap), false); + break; + case WakeUpMode::RaiseWrist: + break; + } + } + }; + + std::bitset<3> getWakeUpModes() const { return settings.wakeUpMode; - }; + } + + bool isWakeUpModeOn(const WakeUpMode mode) const { + return getWakeUpModes()[static_cast<size_t>(mode)]; + } void SetBrightness(Controllers::BrightnessController::Levels level) { - if (level != settings.brightLevel) + if (level != settings.brightLevel) { settingsChanged = true; + } settings.brightLevel = level; }; Controllers::BrightnessController::Levels GetBrightness() const { @@ -87,26 +116,30 @@ namespace Pinetime { }; void SetStepsGoal( uint32_t goal ) { - if ( goal != settings.stepsGoal ) + if ( goal != settings.stepsGoal ) { settingsChanged = true; + } settings.stepsGoal = goal; }; uint32_t GetStepsGoal() const { return settings.stepsGoal; }; private: - Pinetime::Drivers::SpiNorFlash& spiNorFlash; + Pinetime::Controllers::FS& fs; + + static constexpr uint32_t settingsVersion = 0x0001; struct SettingsData { + uint32_t version = settingsVersion; + uint32_t stepsGoal = 10000; + uint32_t screenTimeOut = 15000; + ClockType clockType = ClockType::H24; Vibration vibrationStatus = Vibration::ON; uint8_t clockFace = 0; - uint32_t stepsGoal = 10000; - uint32_t screenTimeOut = 15000; - - WakeUpMode wakeUpMode = WakeUpMode::None; + std::bitset<3> wakeUpMode {0}; Controllers::BrightnessController::Levels brightLevel = Controllers::BrightnessController::Levels::Medium; }; @@ -117,20 +150,8 @@ namespace Pinetime { uint8_t appMenu = 0; uint8_t settingsMenu = 0; - // There are 10 blocks of reserved flash to save settings - // to minimize wear, the recording is done in a rotating way by the 10 blocks - uint8_t settingsFlashBlock = 99; // default to indicate it needs to find the active block - - static constexpr uint32_t settingsBaseAddr = 0x3F6000; // Flash Settings Location - static constexpr uint16_t settingsVersion = 0x0100; // Flash Settings Version - - bool FindHeader(); - void ReadSettingsData(); - void EraseBlock(); - void SetHeader(bool state); - void SaveSettingsData(); - void LoadSettingsFromFlash(); - void SaveSettingsToFlash(); + void LoadSettingsFromFile(); + void SaveSettingsToFile(); }; } -}
\ No newline at end of file +} diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index ab73969d..d4a73f5e 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -43,6 +43,8 @@ #include "displayapp/screens/settings/SettingDisplay.h" #include "displayapp/screens/settings/SettingSteps.h" +#include "libs/lv_conf.h" + using namespace Pinetime::Applications; using namespace Pinetime::Applications::Display; @@ -50,6 +52,31 @@ namespace { static inline bool in_isr(void) { return (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) != 0; } + + TouchEvents Convert(Pinetime::Drivers::Cst816S::TouchInfos info) { + if (info.isTouch) { + switch (info.gesture) { + case Pinetime::Drivers::Cst816S::Gestures::SingleTap: + return TouchEvents::Tap; + case Pinetime::Drivers::Cst816S::Gestures::LongPress: + return TouchEvents::LongTap; + case Pinetime::Drivers::Cst816S::Gestures::DoubleTap: + return TouchEvents::DoubleTap; + case Pinetime::Drivers::Cst816S::Gestures::SlideRight: + return TouchEvents::SwipeRight; + case Pinetime::Drivers::Cst816S::Gestures::SlideLeft: + return TouchEvents::SwipeLeft; + case Pinetime::Drivers::Cst816S::Gestures::SlideDown: + return TouchEvents::SwipeDown; + case Pinetime::Drivers::Cst816S::Gestures::SlideUp: + return TouchEvents::SwipeUp; + case Pinetime::Drivers::Cst816S::Gestures::None: + default: + return TouchEvents::None; + } + } + return TouchEvents::None; + } } DisplayApp::DisplayApp(Drivers::St7789& lcd, @@ -114,6 +141,7 @@ uint32_t count = 0; bool toggle = true; void DisplayApp::Refresh() { TickType_t queueTimeout; + TickType_t delta; switch (state) { case States::Idle: IdleState(); @@ -121,7 +149,11 @@ void DisplayApp::Refresh() { break; case States::Running: RunningState(); - queueTimeout = 20; + delta = xTaskGetTickCount() - lastWakeTime; + if (delta > LV_DISP_DEF_REFR_PERIOD) { + delta = LV_DISP_DEF_REFR_PERIOD; + } + queueTimeout = LV_DISP_DEF_REFR_PERIOD - delta; break; default: queueTimeout = portMAX_DELAY; @@ -129,10 +161,19 @@ void DisplayApp::Refresh() { } Messages msg; - if (xQueueReceive(msgQueue, &msg, queueTimeout)) { + bool messageReceived = xQueueReceive(msgQueue, &msg, queueTimeout); + lastWakeTime = xTaskGetTickCount(); + if (messageReceived) { switch (msg) { - case Messages::GoToSleep: + case Messages::DimScreen: + // Backup brightness is the brightness to return to after dimming or sleeping brightnessController.Backup(); + brightnessController.Set(Controllers::BrightnessController::Levels::Low); + break; + case Messages::RestoreBrightness: + brightnessController.Restore(); + break; + case Messages::GoToSleep: while (brightnessController.Level() != Controllers::BrightnessController::Levels::Off) { brightnessController.Lower(); vTaskDelay(100); @@ -161,16 +202,21 @@ void DisplayApp::Refresh() { break; case Messages::TimerDone: if (currentApp == Apps::Timer) { - auto *timer = static_cast<Screens::Timer*>(currentScreen.get()); + auto* timer = static_cast<Screens::Timer*>(currentScreen.get()); timer->setDone(); } else { LoadApp(Apps::Timer, DisplayApp::FullRefreshDirections::Down); } break; case Messages::TouchEvent: { - if (state != States::Running) + if (state != States::Running) { break; - auto gesture = OnTouchEvent(); + } + auto info = touchPanel.GetTouchInfo(); + auto gesture = Convert(info); + if (gesture == TouchEvents::None) { + break; + } if (!currentScreen->OnTouchEvent(gesture)) { if (currentApp == Apps::Clock) { switch (gesture) { @@ -191,6 +237,12 @@ void DisplayApp::Refresh() { } } else if (returnTouchEvent == gesture) { LoadApp(returnToApp, returnDirection); + brightnessController.Set(settingsController.GetBrightness()); + brightnessController.Backup(); + } else if (touchMode == TouchModes::Gestures) { + if (gesture == TouchEvents::Tap) { + lvgl.SetNewTapEvent(info.x, info.y); + } } } } break; @@ -200,6 +252,8 @@ void DisplayApp::Refresh() { } else { if (!currentScreen->OnButtonPushed()) { LoadApp(returnToApp, returnDirection); + brightnessController.Set(settingsController.GetBrightness()); + brightnessController.Backup(); } } break; @@ -214,7 +268,7 @@ void DisplayApp::Refresh() { } } - if(nextApp != Apps::None) { + if (nextApp != Apps::None) { LoadApp(nextApp, nextDirection); nextApp = Apps::None; } @@ -277,6 +331,7 @@ void DisplayApp::LoadApp(Apps app, DisplayApp::FullRefreshDirections direction) break; case Apps::FirmwareUpdate: currentScreen = std::make_unique<Screens::FirmwareUpdate>(this, bleController); + ReturnApp(Apps::Clock, FullRefreshDirections::Down, TouchEvents::None); break; case Apps::Notifications: @@ -328,8 +383,8 @@ void DisplayApp::LoadApp(Apps app, DisplayApp::FullRefreshDirections direction) ReturnApp(Apps::Settings, FullRefreshDirections::Down, TouchEvents::SwipeDown); break; case Apps::SysInfo: - currentScreen = - std::make_unique<Screens::SystemInfo>(this, dateTimeController, batteryController, brightnessController, bleController, watchdog); + currentScreen = std::make_unique<Screens::SystemInfo>( + this, dateTimeController, batteryController, brightnessController, bleController, watchdog, motionController); ReturnApp(Apps::Settings, FullRefreshDirections::Down, TouchEvents::SwipeDown); break; case Apps::FlashLight: @@ -337,7 +392,7 @@ void DisplayApp::LoadApp(Apps app, DisplayApp::FullRefreshDirections direction) ReturnApp(Apps::Clock, FullRefreshDirections::Down, TouchEvents::None); break; case Apps::StopWatch: - currentScreen = std::make_unique<Screens::StopWatch>(this); + currentScreen = std::make_unique<Screens::StopWatch>(this, *systemTask); break; case Apps::Twos: currentScreen = std::make_unique<Screens::Twos>(this); @@ -374,7 +429,7 @@ void DisplayApp::IdleState() { } void DisplayApp::PushMessage(Messages msg) { - if(in_isr()) { + if (in_isr()) { BaseType_t xHigherPriorityTaskWoken; xHigherPriorityTaskWoken = pdFALSE; xQueueSendFromISR(msgQueue, &msg, &xHigherPriorityTaskWoken); @@ -386,35 +441,6 @@ void DisplayApp::PushMessage(Messages msg) { } } -TouchEvents DisplayApp::OnTouchEvent() { - auto info = touchPanel.GetTouchInfo(); - if (info.isTouch) { - switch (info.gesture) { - case Pinetime::Drivers::Cst816S::Gestures::SingleTap: - if (touchMode == TouchModes::Gestures) { - lvgl.SetNewTapEvent(info.x, info.y); - } - return TouchEvents::Tap; - case Pinetime::Drivers::Cst816S::Gestures::LongPress: - return TouchEvents::LongTap; - case Pinetime::Drivers::Cst816S::Gestures::DoubleTap: - return TouchEvents::DoubleTap; - case Pinetime::Drivers::Cst816S::Gestures::SlideRight: - return TouchEvents::SwipeRight; - case Pinetime::Drivers::Cst816S::Gestures::SlideLeft: - return TouchEvents::SwipeLeft; - case Pinetime::Drivers::Cst816S::Gestures::SlideDown: - return TouchEvents::SwipeDown; - case Pinetime::Drivers::Cst816S::Gestures::SlideUp: - return TouchEvents::SwipeUp; - case Pinetime::Drivers::Cst816S::Gestures::None: - default: - return TouchEvents::None; - } - } - return TouchEvents::None; -} - void DisplayApp::SetFullRefresh(DisplayApp::FullRefreshDirections direction) { switch (direction) { case DisplayApp::FullRefreshDirections::Down: @@ -445,7 +471,7 @@ void DisplayApp::SetTouchMode(DisplayApp::TouchModes mode) { } void DisplayApp::PushMessageToSystemTask(Pinetime::System::Messages message) { - if(systemTask != nullptr) + if (systemTask != nullptr) systemTask->PushMessage(message); } diff --git a/src/displayapp/DisplayApp.h b/src/displayapp/DisplayApp.h index 73a7cc36..574be63f 100644 --- a/src/displayapp/DisplayApp.h +++ b/src/displayapp/DisplayApp.h @@ -102,7 +102,6 @@ namespace Pinetime { TouchModes touchMode = TouchModes::Gestures; - TouchEvents OnTouchEvent(); void RunningState(); void IdleState(); static void Process(void* instance); @@ -114,6 +113,7 @@ namespace Pinetime { Apps nextApp = Apps::None; DisplayApp::FullRefreshDirections nextDirection; + TickType_t lastWakeTime; }; } } diff --git a/src/displayapp/Messages.h b/src/displayapp/Messages.h index ce65f846..322505e6 100644 --- a/src/displayapp/Messages.h +++ b/src/displayapp/Messages.h @@ -13,8 +13,10 @@ namespace Pinetime { NewNotification, TimerDone, BleFirmwareUpdateStarted, - UpdateTimeOut + UpdateTimeOut, + DimScreen, + RestoreBrightness }; } } -}
\ No newline at end of file +} diff --git a/src/displayapp/fonts/JetBrainsMono-Bold.ttf b/src/displayapp/fonts/JetBrainsMono-Bold.ttf Binary files differnew file mode 100644 index 00000000..0cd1cb66 --- /dev/null +++ b/src/displayapp/fonts/JetBrainsMono-Bold.ttf diff --git a/src/displayapp/fonts/README.md b/src/displayapp/fonts/README.md index 183ad7e4..8a260846 100644 --- a/src/displayapp/fonts/README.md +++ b/src/displayapp/fonts/README.md @@ -2,6 +2,7 @@ * [Jetbrains Mono](https://www.jetbrains.com/fr-fr/lp/mono/) * [Awesome font from LVGL](https://lvgl.io/assets/others/FontAwesome5-Solid+Brands+Regular.woff) +* [Open Sans Light from Google](https://fonts.google.com/specimen/Open+Sans) ## Generate the fonts: @@ -10,10 +11,12 @@ * Size : 20 * Bpp : 1 bit-per-pixel * Do not enable font compression and horizontal subpixel hinting -* Load the file `JetBrainsMono-Bold.tff` and specify the following range : `0x20-0x7f, 0x410-0x44f` +* Load the file `JetBrainsMono-Bold.tff` (use the file in this repo to ensure the version matches) and specify the following range : `0x20-0x7f, 0x410-0x44f` * Add a 2nd font, load the file `FontAwesome5-Solid+Brands+Regular.woff` and specify the following - range : `0xf293, 0xf294, 0xf244, 0xf240, 0xf242, 0xf243, 0xf241, 0xf54b, 0xf21e, 0xf1e6, 0xf54b, 0xf017, 0xf129, 0xf03a, 0xf185, 0xf560, 0xf001, 0xf3fd, 0xf069, 0xf1fc, 0xf45d, 0xf59f, 0xf5a0, 0xf029, 0xf027, 0xf028, 0xf6a9, 0xf04b, 0xf04c, 0xf048, 0xf051, 0xf095, 0xf3dd, 0xf04d, 0xf2f2, 0xf024, 0xf252` + range : `0xf293, 0xf294, 0xf244, 0xf240, 0xf242, 0xf243, 0xf241, 0xf54b, 0xf21e, 0xf1e6, 0xf54b, 0xf017, 0xf129, 0xf03a, 0xf185, 0xf560, 0xf001, 0xf3fd, 0xf069, 0xf1fc, 0xf45d, 0xf59f, 0xf5a0, 0xf029, 0xf027, 0xf028, 0xf6a9, 0xf04b, 0xf04c, 0xf048, 0xf051, 0xf095, 0xf3dd, 0xf04d, 0xf2f2, 0xf024, 0xf252, 0xf569, 0xf201, 0xf06e, 0xf015` * Click on Convert, and download the file `jetbrains_mono_bold_20.c` and copy it in `src/DisplayApp/Fonts` +* Add the font .c file path to src/CMakeLists.txt +* Add an LV_FONT_DECLARE line in src/libs/lv_conf.h Add new symbols: @@ -28,6 +31,21 @@ Add new symbols: static constexpr const char* newSymbol = "\xEF\x86\x85"; ``` +## Simple method to generate a font + +If you want to generate a basic font containing only numbers and letters, you can use the above settings but instead of specifying a range, simply list the characters you need in the Symbols field and leave the range blank. This is the approach used for the PineTimeStyle watchface. +This works well for fonts which will only be used to display numbers, but will fail if you try to add a colon or other punctuation. + +* Open the [LVGL font converter](https://lvgl.io/tools/fontconverter) +* Name : open_sans_light +* Size : 150 +* Bpp : 1 bit-per-pixel +* Do not enable font compression and horizontal subpixel hinting +* Load the file `open_sans_light.tff` (use the file in this repo to ensure the version matches) and specify the following symbols : `0123456789` +* Click on Convert, and download the file `open_sans_light.c` and copy it in `src/DisplayApp/Fonts` +* Add the font .c file path to src/CMakeLists.txt (search for jetbrains to find the appropriate location/format) +* Add an LV_FONT_DECLARE line in src/libs/lv_conf.h (as above) + #### Navigation font To create the navigtion.ttf I use the web app [icomoon](https://icomoon.io/app) diff --git a/src/displayapp/fonts/jetbrains_mono_bold_20.c b/src/displayapp/fonts/jetbrains_mono_bold_20.c index 9174ff48..d8705528 100644 --- a/src/displayapp/fonts/jetbrains_mono_bold_20.c +++ b/src/displayapp/fonts/jetbrains_mono_bold_20.c @@ -1,11 +1,15 @@ -#include "lvgl/lvgl.h" - /******************************************************************************* * Size: 20 px * Bpp: 1 * Opts: ******************************************************************************/ +#ifdef LV_LVGL_H_INCLUDE_SIMPLE +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + #ifndef JETBRAINS_MONO_BOLD_20 #define JETBRAINS_MONO_BOLD_20 1 #endif @@ -17,707 +21,707 @@ *----------------*/ /*Store the image of the glyphs*/ -static LV_ATTRIBUTE_LARGE_CONST const uint8_t gylph_bitmap[] = { - /* U+20 " " */ +static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { + /* U+0020 " " */ 0x0, - /* U+21 "!" */ + /* U+0021 "!" */ 0xff, 0xff, 0xff, 0xfc, 0xf, 0xc0, - /* U+22 "\"" */ + /* U+0022 "\"" */ 0xef, 0xdf, 0xbf, 0x7e, 0xfd, 0xc0, - /* U+23 "#" */ + /* U+0023 "#" */ 0x8, 0xc3, 0x10, 0x66, 0x3f, 0xf7, 0xfe, 0x23, 0x4, 0x61, 0x88, 0x31, 0x1f, 0xfb, 0xff, 0x19, 0x82, 0x30, 0xc4, 0x0, - /* U+24 "$" */ - 0x8, 0x2, 0x0, 0x80, 0xfc, 0x7f, 0xba, 0x7e, + /* U+0024 "$" */ + 0x8, 0x2, 0x0, 0x81, 0xfc, 0x7f, 0xba, 0x7e, 0x9f, 0xa0, 0xf8, 0x1f, 0x83, 0xf8, 0x3f, 0x9, 0xfa, 0x7e, 0x9d, 0xfe, 0x7f, 0x2, 0x0, 0x80, 0x20, - /* U+25 "%" */ + /* U+0025 "%" */ 0x78, 0x3f, 0xc6, 0xcc, 0xcc, 0xcc, 0xfd, 0x87, 0xb0, 0x6, 0x0, 0x7e, 0xf, 0xf1, 0xb3, 0x33, 0x33, 0x33, 0x63, 0xfc, 0x1e, - /* U+26 "&" */ + /* U+0026 "&" */ 0x1e, 0xf, 0xe1, 0x8e, 0x30, 0x6, 0x0, 0x60, 0x1e, 0x7, 0xe6, 0xed, 0xdc, 0xf3, 0x9e, 0x73, - 0xcf, 0xfc, 0x79, 0x80, + 0xcf, 0xfc, 0xf9, 0x80, - /* U+27 "'" */ + /* U+0027 "'" */ 0xff, 0xff, 0xc0, - /* U+28 "(" */ + /* U+0028 "(" */ 0x2, 0x1c, 0x79, 0xc7, 0x1e, 0x38, 0x70, 0xe1, 0xc3, 0x87, 0xe, 0x1c, 0x3c, 0x38, 0x3c, 0x3c, 0x38, - /* U+29 ")" */ + /* U+0029 ")" */ 0x1, 0xc3, 0xc3, 0xc1, 0xc3, 0xc3, 0x87, 0xe, 0x1c, 0x38, 0x70, 0xe1, 0xc7, 0xe, 0x79, 0xe3, 0x0, - /* U+2A "*" */ + /* U+002A "*" */ 0xc, 0x3, 0x8, 0xc7, 0xb7, 0x7f, 0x83, 0x1, 0xe0, 0xcc, 0x73, 0x80, 0x0, - /* U+2B "+" */ + /* U+002B "+" */ 0x1c, 0x7, 0x1, 0xc3, 0xff, 0xff, 0xc7, 0x1, 0xc0, 0x70, 0x1c, 0x0, - /* U+2C "," */ + /* U+002C "," */ 0x7b, 0x9c, 0xce, 0x60, - /* U+2D "-" */ + /* U+002D "-" */ 0xff, 0xf0, - /* U+2E "." */ + /* U+002E "." */ 0xff, 0xf0, - /* U+2F "/" */ + /* U+002F "/" */ 0x1, 0xc0, 0x60, 0x38, 0xe, 0x3, 0x1, 0xc0, 0x70, 0x18, 0xe, 0x3, 0x1, 0xc0, 0x70, 0x18, 0xe, 0x3, 0x80, 0xc0, 0x70, 0x18, 0xe, 0x0, - /* U+30 "0" */ + /* U+0030 "0" */ 0x3f, 0x1f, 0xef, 0x3f, 0x87, 0xe1, 0xf8, 0x7f, 0xdf, 0xf7, 0xe1, 0xf8, 0x7e, 0x1f, 0xcf, 0x7f, 0x8f, 0xc0, - /* U+31 "1" */ + /* U+0031 "1" */ 0x1e, 0x3f, 0x3b, 0x99, 0xc8, 0xe0, 0x70, 0x38, 0x1c, 0xe, 0x7, 0x3, 0x81, 0xcf, 0xff, 0xfc, - /* U+32 "2" */ + /* U+0032 "2" */ 0x3e, 0x3f, 0xbc, 0xfc, 0x70, 0x38, 0x1c, 0x1c, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0xf, 0xff, 0xfc, - /* U+33 "3" */ + /* U+0033 "3" */ 0x7f, 0x9f, 0xe0, 0x30, 0x18, 0xc, 0x7, 0xc1, 0xf8, 0xf, 0x1, 0xc0, 0x7e, 0x1f, 0xcf, 0x7f, 0x8f, 0xc0, - /* U+34 "4" */ + /* U+0034 "4" */ 0x7, 0x7, 0x3, 0x83, 0x83, 0x83, 0xc1, 0xcf, 0xe7, 0xe3, 0xff, 0xff, 0xe0, 0x70, 0x38, 0x1c, - /* U+35 "5" */ + /* U+0035 "5" */ 0x7f, 0x9f, 0xe7, 0x1, 0xc0, 0x77, 0x1f, 0xe7, 0x3c, 0x7, 0x1, 0xc0, 0x77, 0x1d, 0xcf, 0x7f, 0x87, 0xc0, - /* U+36 "6" */ + /* U+0036 "6" */ 0xe, 0x3, 0x1, 0xc0, 0x60, 0x38, 0x1d, 0xc7, 0xfb, 0xcf, 0xe1, 0xf8, 0x7e, 0x1f, 0xcf, 0x7f, - 0x87, 0x80, + 0x8f, 0x80, - /* U+37 "7" */ + /* U+0037 "7" */ 0xff, 0xff, 0xfe, 0x1f, 0x86, 0x3, 0x80, 0xe0, 0x30, 0x1c, 0x6, 0x3, 0x80, 0xc0, 0x70, 0x1c, 0x6, 0x0, - /* U+38 "8" */ + /* U+0038 "8" */ 0x3f, 0x1f, 0xef, 0x3f, 0x87, 0xe1, 0xdc, 0xe3, 0xf0, 0xfc, 0x73, 0xb8, 0x7e, 0x1f, 0xcf, 0x7f, 0x8f, 0xc0, - /* U+39 "9" */ + /* U+0039 "9" */ 0x1e, 0x1f, 0xef, 0x3f, 0x87, 0xe1, 0xf8, 0x7f, 0x3d, 0xfe, 0x3b, 0x81, 0xc0, 0x60, 0x38, 0xc, 0x7, 0x0, - /* U+3A ":" */ + /* U+003A ":" */ 0xff, 0x80, 0x0, 0xff, 0x80, - /* U+3B ";" */ + /* U+003B ";" */ 0x7b, 0xde, 0x0, 0x0, 0x0, 0x3, 0xdc, 0xe6, 0x73, 0x0, - /* U+3C "<" */ + /* U+003C "<" */ 0x0, 0x81, 0xc3, 0xe7, 0xcf, 0x6, 0x3, 0xc0, 0x7c, 0xf, 0x81, 0xc0, 0x20, - /* U+3D "=" */ + /* U+003D "=" */ 0xff, 0xff, 0xc0, 0x0, 0x0, 0x7, 0xff, 0xfe, - /* U+3E ">" */ + /* U+003E ">" */ 0x80, 0x70, 0x3e, 0x7, 0xc0, 0xf8, 0xc, 0x1e, 0x3c, 0xf8, 0x70, 0x20, 0x0, - /* U+3F "?" */ + /* U+003F "?" */ 0xfc, 0xfe, 0xf, 0x7, 0x7, 0xf, 0x3e, 0x3c, 0x30, 0x30, 0x0, 0x0, 0x70, 0x70, - /* U+40 "@" */ + /* U+0040 "@" */ 0x1f, 0x7, 0xf9, 0xc3, 0x70, 0x3c, 0x7, 0x8f, 0xf3, 0xfe, 0x63, 0xcc, 0x79, 0x8f, 0x31, 0xe6, 0x3c, 0xff, 0x8e, 0xf8, 0x3, 0x80, 0x3e, 0x3, 0xc0, - /* U+41 "A" */ + /* U+0041 "A" */ 0x1e, 0x7, 0x81, 0xe0, 0xfc, 0x3f, 0xc, 0xc3, 0x31, 0xce, 0x73, 0x9f, 0xe7, 0xfb, 0x87, 0xe1, 0xf0, 0x30, - /* U+42 "B" */ + /* U+0042 "B" */ 0xfe, 0x3f, 0xce, 0x3b, 0x8e, 0xe3, 0xb8, 0xcf, 0xe3, 0xfc, 0xe3, 0xb8, 0x7e, 0x1f, 0x8f, 0xff, 0xbf, 0xc0, - /* U+43 "C" */ + /* U+0043 "C" */ 0x3f, 0x1f, 0xef, 0x3f, 0x87, 0xe0, 0x38, 0xe, 0x3, 0x80, 0xe0, 0x38, 0xe, 0x1f, 0xcf, 0x7f, 0x8f, 0xc0, - /* U+44 "D" */ + /* U+0044 "D" */ 0xfe, 0x7f, 0xb9, 0xfc, 0x7e, 0x3f, 0x1f, 0x8f, 0xc7, 0xe3, 0xf1, 0xf8, 0xfc, 0xff, 0xf7, 0xf0, - /* U+45 "E" */ + /* U+0045 "E" */ 0xff, 0xff, 0xf8, 0x1c, 0xe, 0x7, 0x3, 0xfd, 0xfe, 0xe0, 0x70, 0x38, 0x1c, 0xf, 0xff, 0xfc, - /* U+46 "F" */ + /* U+0046 "F" */ 0xff, 0xff, 0xf8, 0x1c, 0xe, 0x7, 0x3, 0xff, 0xff, 0xe0, 0x70, 0x38, 0x1c, 0xe, 0x7, 0x0, - /* U+47 "G" */ - 0x3f, 0x1f, 0xef, 0x1f, 0x87, 0xe0, 0x38, 0xe, + /* U+0047 "G" */ + 0x3f, 0x1f, 0xef, 0x3f, 0x87, 0xe0, 0x38, 0xe, 0x7f, 0x9f, 0xe1, 0xf8, 0x7e, 0x1f, 0xcf, 0x7f, 0x8f, 0xc0, - /* U+48 "H" */ + /* U+0048 "H" */ 0xe3, 0xf1, 0xf8, 0xfc, 0x7e, 0x3f, 0x1f, 0xff, 0xff, 0xe3, 0xf1, 0xf8, 0xfc, 0x7e, 0x3f, 0x1c, - /* U+49 "I" */ + /* U+0049 "I" */ 0xff, 0xff, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xff, 0xff, - /* U+4A "J" */ + /* U+004A "J" */ 0x1f, 0xc7, 0xf0, 0x1c, 0x7, 0x1, 0xc0, 0x70, 0x1c, 0x7, 0x1, 0xc0, 0x7e, 0x1f, 0xcf, 0x7f, 0x8f, 0xc0, - /* U+4B "K" */ + /* U+004B "K" */ 0xe1, 0xf8, 0x7e, 0x3b, 0x8e, 0xe7, 0x39, 0xcf, 0xe3, 0xf8, 0xe7, 0x39, 0xce, 0x3b, 0x8e, 0xe1, 0xf8, 0x70, - /* U+4C "L" */ + /* U+004C "L" */ 0xe0, 0x70, 0x38, 0x1c, 0xe, 0x7, 0x3, 0x81, 0xc0, 0xe0, 0x70, 0x38, 0x1c, 0xf, 0xff, 0xfc, - /* U+4D "M" */ + /* U+004D "M" */ 0xe1, 0xf8, 0x7f, 0x3f, 0xcf, 0xd2, 0xf7, 0xbd, 0xef, 0x33, 0xc0, 0xf0, 0x3c, 0xf, 0x3, 0xc0, 0xf0, 0x30, - /* U+4E "N" */ - 0xe1, 0xf0, 0xfc, 0x7e, 0x3d, 0x9e, 0xcf, 0x67, - 0x9b, 0xcd, 0xe6, 0xf1, 0xf8, 0xfc, 0x3e, 0x1c, + /* U+004E "N" */ + 0xe1, 0xf0, 0xfc, 0x7e, 0x3f, 0x9e, 0xcf, 0x67, + 0x9b, 0xcd, 0xe6, 0xf1, 0xf8, 0xfc, 0x7e, 0x1c, - /* U+4F "O" */ + /* U+004F "O" */ 0x3e, 0x3f, 0xb8, 0xfc, 0x7e, 0x3f, 0x1f, 0x8f, 0xc7, 0xe3, 0xf1, 0xf8, 0xfc, 0x77, 0xf1, 0xf0, - /* U+50 "P" */ + /* U+0050 "P" */ 0xff, 0x3f, 0xee, 0x3f, 0x87, 0xe1, 0xf8, 0xff, 0xfb, 0xfc, 0xe0, 0x38, 0xe, 0x3, 0x80, 0xe0, 0x38, 0x0, - /* U+51 "Q" */ + /* U+0051 "Q" */ 0x3f, 0x1f, 0xef, 0x3f, 0x87, 0xe1, 0xf8, 0x7e, 0x1f, 0x87, 0xe1, 0xf8, 0x7e, 0x1f, 0xcf, 0x7f, 0x8f, 0x80, 0x70, 0xe, 0x3, 0x80, 0x70, - /* U+52 "R" */ + /* U+0052 "R" */ 0xff, 0x3f, 0xee, 0x3f, 0x87, 0xe1, 0xf8, 0xff, 0xfb, 0xf8, 0xe6, 0x39, 0xce, 0x33, 0x8e, 0xe3, 0xb8, 0x70, - /* U+53 "S" */ + /* U+0053 "S" */ 0x3f, 0x1f, 0xee, 0x3f, 0x87, 0xe0, 0x3c, 0x7, 0xf0, 0xfe, 0x3, 0xc0, 0x7e, 0x1f, 0xcf, 0x7f, 0x8f, 0xc0, - /* U+54 "T" */ + /* U+0054 "T" */ 0xff, 0xff, 0xf0, 0xe0, 0x38, 0xe, 0x3, 0x80, 0xe0, 0x38, 0xe, 0x3, 0x80, 0xe0, 0x38, 0xe, 0x3, 0x80, - /* U+55 "U" */ + /* U+0055 "U" */ 0xe3, 0xf1, 0xf8, 0xfc, 0x7e, 0x3f, 0x1f, 0x8f, 0xc7, 0xe3, 0xf1, 0xf8, 0xfc, 0x77, 0xf1, 0xf0, - /* U+56 "V" */ + /* U+0056 "V" */ 0xc0, 0xf8, 0x7e, 0x1d, 0x86, 0x61, 0x9c, 0xe7, 0x38, 0xcc, 0x33, 0xf, 0xc3, 0xf0, 0x78, 0x1e, 0x7, 0x80, - /* U+57 "W" */ + /* U+0057 "W" */ 0xce, 0x79, 0xcf, 0x29, 0xe5, 0x3c, 0xa7, 0xd5, 0xda, 0xb3, 0x56, 0x7b, 0xcf, 0x79, 0xef, 0x38, 0xe7, 0x1c, 0xe3, 0x80, - /* U+58 "X" */ + /* U+0058 "X" */ 0xe1, 0xd8, 0x67, 0x38, 0xcc, 0x3f, 0x7, 0x81, 0xe0, 0x78, 0x1e, 0xf, 0xc3, 0x31, 0xce, 0xe1, 0xf8, 0x70, - /* U+59 "Y" */ + /* U+0059 "Y" */ 0xe0, 0xfc, 0x1d, 0xc7, 0x38, 0xe3, 0xb8, 0x77, 0x6, 0xc0, 0xf8, 0xe, 0x1, 0xc0, 0x38, 0x7, 0x0, 0xe0, 0x1c, 0x0, - /* U+5A "Z" */ + /* U+005A "Z" */ 0xff, 0xff, 0xc0, 0xe0, 0xe0, 0x70, 0x70, 0x70, 0x38, 0x38, 0x38, 0x1c, 0x1c, 0xf, 0xff, 0xfc, - /* U+5B "[" */ + /* U+005B "[" */ 0xff, 0xfe, 0x38, 0xe3, 0x8e, 0x38, 0xe3, 0x8e, 0x38, 0xe3, 0x8e, 0x38, 0xff, 0xf0, - /* U+5C "\\" */ + /* U+005C "\\" */ 0xe0, 0x18, 0x7, 0x1, 0xc0, 0x30, 0xe, 0x3, 0x80, 0x60, 0x1c, 0x3, 0x0, 0xe0, 0x38, 0x6, 0x1, 0xc0, 0x70, 0xc, 0x3, 0x80, 0x60, 0x1c, - /* U+5D "]" */ + /* U+005D "]" */ 0xff, 0xf1, 0xc7, 0x1c, 0x71, 0xc7, 0x1c, 0x71, 0xc7, 0x1c, 0x71, 0xc7, 0xff, 0xf0, - /* U+5E "^" */ + /* U+005E "^" */ 0xc, 0x7, 0x81, 0xe0, 0xfc, 0x33, 0x1c, 0xe6, 0x19, 0x86, - /* U+5F "_" */ + /* U+005F "_" */ 0xff, 0xff, 0xf0, - /* U+60 "`" */ + /* U+0060 "`" */ 0xe3, 0x8c, - /* U+61 "a" */ + /* U+0061 "a" */ 0x1f, 0x1f, 0xe7, 0x1c, 0x7, 0x3f, 0xdf, 0xfe, 0x1f, 0x87, 0xe3, 0xff, 0xf3, 0xdc, - /* U+62 "b" */ + /* U+0062 "b" */ 0xe0, 0x70, 0x38, 0x1d, 0xcf, 0xf7, 0x1f, 0x8f, 0xc7, 0xe3, 0xf1, 0xf8, 0xfc, 0x7f, 0xf7, 0x70, - /* U+63 "c" */ + /* U+0063 "c" */ 0x3e, 0x3f, 0xb8, 0xfc, 0x7e, 0x7, 0x3, 0x81, 0xc7, 0xe3, 0xbf, 0x8f, 0x80, - /* U+64 "d" */ + /* U+0064 "d" */ 0x3, 0x81, 0xc0, 0xe7, 0x77, 0xff, 0x1f, 0x8f, 0xc7, 0xe3, 0xf1, 0xf8, 0xfc, 0x77, 0xf9, 0xdc, - /* U+65 "e" */ + /* U+0065 "e" */ 0x3e, 0x3f, 0xb8, 0xfc, 0x7f, 0xff, 0xff, 0x81, 0xc0, 0xe3, 0xbf, 0x8f, 0x80, - /* U+66 "f" */ + /* U+0066 "f" */ 0xf, 0xc7, 0xf1, 0xc0, 0x70, 0xff, 0xff, 0xf1, 0xc0, 0x70, 0x1c, 0x7, 0x1, 0xc0, 0x70, 0x1c, 0x7, 0x0, - /* U+67 "g" */ + /* U+0067 "g" */ 0x3b, 0xbf, 0xfd, 0xfc, 0x7e, 0x3f, 0x1f, 0x8f, 0xc7, 0xf7, 0xbf, 0xce, 0xe0, 0x70, 0x39, 0xf8, 0xf8, - /* U+68 "h" */ + /* U+0068 "h" */ 0xe0, 0x70, 0x38, 0x1d, 0xcf, 0xf7, 0x1f, 0x8f, 0xc7, 0xe3, 0xf1, 0xf8, 0xfc, 0x7e, 0x3f, 0x1c, - /* U+69 "i" */ + /* U+0069 "i" */ 0x1c, 0x7, 0x1, 0xc0, 0x0, 0x0, 0x3f, 0xf, 0xc0, 0x70, 0x1c, 0x7, 0x1, 0xc0, 0x70, 0x1c, 0x7, 0xf, 0xff, 0xff, - /* U+6A "j" */ + /* U+006A "j" */ 0x7, 0x7, 0x7, 0x0, 0xff, 0xff, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0xf, 0xfe, 0xfc, - /* U+6B "k" */ + /* U+006B "k" */ 0xe0, 0x38, 0xe, 0x3, 0x87, 0xe3, 0xb8, 0xee, 0x73, 0xf8, 0xfe, 0x39, 0xce, 0x33, 0x8e, 0xe1, 0xb8, 0x70, - /* U+6C "l" */ + /* U+006C "l" */ 0xfe, 0x1f, 0xc0, 0x38, 0x7, 0x0, 0xe0, 0x1c, 0x3, 0x80, 0x70, 0xe, 0x1, 0xc0, 0x38, 0x7, 0x0, 0x7e, 0x7, 0xc0, - /* U+6D "m" */ + /* U+006D "m" */ 0xd9, 0xbf, 0xfc, 0xcf, 0x33, 0xcc, 0xf3, 0x3c, 0xcf, 0x33, 0xcc, 0xf3, 0x3c, 0xcc, - /* U+6E "n" */ + /* U+006E "n" */ 0xee, 0x7f, 0xb8, 0xfc, 0x7e, 0x3f, 0x1f, 0x8f, 0xc7, 0xe3, 0xf1, 0xf8, 0xe0, - /* U+6F "o" */ + /* U+006F "o" */ 0x3e, 0x3f, 0xb8, 0xfc, 0x7e, 0x3f, 0x1f, 0x8f, 0xc7, 0xe3, 0xbf, 0x8f, 0x80, - /* U+70 "p" */ + /* U+0070 "p" */ 0xee, 0x7f, 0xb8, 0xfc, 0x7e, 0x3f, 0x1f, 0x8f, 0xc7, 0xe3, 0xff, 0xbb, 0x9c, 0xe, 0x7, 0x3, 0x80, - /* U+71 "q" */ + /* U+0071 "q" */ 0x3b, 0xbf, 0xf8, 0xfc, 0x7e, 0x3f, 0x1f, 0x8f, 0xc7, 0xe3, 0xbf, 0xce, 0xe0, 0x70, 0x38, 0x1c, 0xe, - /* U+72 "r" */ - 0xee, 0x7f, 0xb8, 0xfc, 0x7e, 0x3f, 0x3, 0x81, + /* U+0072 "r" */ + 0xee, 0x7f, 0xb9, 0xfc, 0x7e, 0x3f, 0x3, 0x81, 0xc0, 0xe0, 0x70, 0x38, 0x0, - /* U+73 "s" */ + /* U+0073 "s" */ 0x1f, 0x1f, 0xf7, 0x1d, 0xc0, 0x7c, 0xf, 0xe0, 0x3c, 0x7, 0x71, 0xdf, 0xe3, 0xf0, - /* U+74 "t" */ + /* U+0074 "t" */ 0x1c, 0x7, 0x1, 0xc3, 0xff, 0xff, 0xc7, 0x1, 0xc0, 0x70, 0x1c, 0x7, 0x1, 0xc0, 0x70, 0x1f, 0xc3, 0xf0, - /* U+75 "u" */ + /* U+0075 "u" */ 0xe3, 0xf1, 0xf8, 0xfc, 0x7e, 0x3f, 0x1f, 0x8f, 0xc7, 0xe3, 0xbf, 0x8f, 0x80, - /* U+76 "v" */ + /* U+0076 "v" */ 0xe0, 0xf8, 0x76, 0x19, 0x86, 0x73, 0x8c, 0xc3, 0x30, 0xfc, 0x1e, 0x7, 0x81, 0xe0, - /* U+77 "w" */ + /* U+0077 "w" */ 0xe6, 0x36, 0x66, 0x66, 0x66, 0xf6, 0x6f, 0x66, 0x96, 0x69, 0x62, 0x94, 0x39, 0xc3, 0x9c, 0x39, 0xc0, - /* U+78 "x" */ + /* U+0078 "x" */ 0xe1, 0xdc, 0xe3, 0x30, 0xfc, 0x1e, 0x7, 0x81, - 0xe0, 0xfc, 0x73, 0x9c, 0x6e, 0x1c, + 0xe0, 0xfc, 0x73, 0x9c, 0xee, 0x1c, - /* U+79 "y" */ + /* U+0079 "y" */ 0xe1, 0xf8, 0x76, 0x19, 0xce, 0x73, 0x8c, 0xc3, 0xf0, 0x7c, 0x1e, 0x7, 0x80, 0xe0, 0x30, 0x1c, 0x6, 0x3, 0x80, - /* U+7A "z" */ + /* U+007A "z" */ 0xff, 0xff, 0xc0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0x7f, 0xff, 0xe0, - /* U+7B "{" */ + /* U+007B "{" */ 0x3, 0x87, 0xc3, 0x81, 0xc0, 0xe0, 0x70, 0x38, 0x1c, 0xfc, 0x7e, 0x3, 0x81, 0xc0, 0xe0, 0x70, 0x38, 0x1c, 0xf, 0x81, 0xc0, - /* U+7C "|" */ + /* U+007C "|" */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, - /* U+7D "}" */ + /* U+007D "}" */ 0xf0, 0x3e, 0x1, 0xc0, 0x70, 0x1c, 0x7, 0x1, 0xc0, 0x70, 0xf, 0xc3, 0xf1, 0xc0, 0x70, 0x1c, 0x7, 0x1, 0xc0, 0x70, 0xf8, 0x3c, 0x0, - /* U+7E "~" */ + /* U+007E "~" */ 0x78, 0xff, 0x3c, 0xcf, 0x3f, 0xc7, 0x80, - /* U+410 "А" */ + /* U+0410 "А" */ 0x1e, 0x7, 0x81, 0xe0, 0xfc, 0x3f, 0xc, 0xc3, 0x31, 0xce, 0x73, 0x9f, 0xe7, 0xfb, 0x87, 0xe1, 0xf0, 0x30, - /* U+411 "Б" */ + /* U+0411 "Б" */ 0xff, 0xbf, 0xee, 0x3, 0x80, 0xe0, 0x3f, 0xcf, 0xfb, 0x8f, 0xe1, 0xf8, 0x7e, 0x1f, 0x8f, 0xff, - 0xbf, 0x80, + 0xbf, 0xc0, - /* U+412 "В" */ + /* U+0412 "В" */ 0xfe, 0x3f, 0xce, 0x3b, 0x8e, 0xe3, 0xb8, 0xcf, 0xe3, 0xfc, 0xe3, 0xb8, 0x7e, 0x1f, 0x8f, 0xff, 0xbf, 0xc0, - /* U+413 "Г" */ + /* U+0413 "Г" */ 0xff, 0xff, 0xf8, 0x1c, 0xe, 0x7, 0x3, 0x81, 0xc0, 0xe0, 0x70, 0x38, 0x1c, 0xe, 0x7, 0x0, - /* U+414 "Д" */ + /* U+0414 "Д" */ 0x3f, 0xc7, 0xf8, 0xe7, 0x1c, 0xe3, 0x9c, 0x73, 0x8e, 0x71, 0xce, 0x39, 0xc7, 0x38, 0xe7, 0x38, 0xef, 0xff, 0xff, 0xf8, 0x3f, 0x7, 0xe0, 0xe0, - /* U+415 "Е" */ + /* U+0415 "Е" */ 0xff, 0xff, 0xf8, 0x1c, 0xe, 0x7, 0x3, 0xfd, 0xfe, 0xe0, 0x70, 0x38, 0x1c, 0xf, 0xff, 0xfc, - /* U+416 "Ж" */ + /* U+0416 "Ж" */ 0xe6, 0x76, 0x66, 0x66, 0x67, 0x66, 0x36, 0xc3, 0x6c, 0x3f, 0xc3, 0x6c, 0x36, 0xc7, 0x6e, 0x66, 0x66, 0x66, 0x66, 0x6c, 0x63, - /* U+417 "З" */ + /* U+0417 "З" */ 0x1f, 0xf, 0xf3, 0xc7, 0x0, 0x60, 0x1c, 0x1e, 0x3, 0xf0, 0xe, 0x0, 0xe0, 0x1f, 0x83, 0xf8, 0xf7, 0xfc, 0x3e, 0x0, - /* U+418 "И" */ + /* U+0418 "И" */ 0xc3, 0xe3, 0xf1, 0xf8, 0xfc, 0xde, 0x6f, 0x37, 0xb3, 0xd9, 0xfc, 0xfc, 0x7e, 0x3e, 0x1f, 0xc, - /* U+419 "Й" */ + /* U+0419 "Й" */ 0x63, 0x31, 0x8f, 0x83, 0x80, 0x6, 0x1f, 0x1f, 0x8f, 0xc7, 0xe7, 0xf3, 0x79, 0xbd, 0x9e, 0xcf, 0xe7, 0xe3, 0xf1, 0xf8, 0xf8, 0x60, - /* U+41A "К" */ + /* U+041A "К" */ 0xe1, 0xf8, 0x7e, 0x3b, 0x8e, 0xe7, 0x39, 0xcf, 0xe3, 0xf8, 0xe7, 0x39, 0xce, 0x3b, 0x8e, 0xe1, 0xf8, 0x70, - /* U+41B "Л" */ + /* U+041B "Л" */ 0x3f, 0xcf, 0xf3, 0x9c, 0xe7, 0x39, 0xce, 0x73, 0x9c, 0xe7, 0x39, 0xce, 0x73, 0x9d, 0xe7, 0xf1, 0xf8, 0x70, - /* U+41C "М" */ + /* U+041C "М" */ 0xe1, 0xf8, 0x7f, 0x3f, 0xcf, 0xd2, 0xf7, 0xbd, 0xef, 0x33, 0xc0, 0xf0, 0x3c, 0xf, 0x3, 0xc0, 0xf0, 0x30, - /* U+41D "Н" */ + /* U+041D "Н" */ 0xe3, 0xf1, 0xf8, 0xfc, 0x7e, 0x3f, 0x1f, 0xff, 0xff, 0xe3, 0xf1, 0xf8, 0xfc, 0x7e, 0x3f, 0x1c, - /* U+41E "О" */ + /* U+041E "О" */ 0x3e, 0x3f, 0xb8, 0xfc, 0x7e, 0x3f, 0x1f, 0x8f, 0xc7, 0xe3, 0xf1, 0xf8, 0xfc, 0x77, 0xf1, 0xf0, - /* U+41F "П" */ + /* U+041F "П" */ 0xff, 0xff, 0xf8, 0xfc, 0x7e, 0x3f, 0x1f, 0x8f, 0xc7, 0xe3, 0xf1, 0xf8, 0xfc, 0x7e, 0x3f, 0x1c, - /* U+420 "Р" */ + /* U+0420 "Р" */ 0xff, 0x3f, 0xee, 0x3f, 0x87, 0xe1, 0xf8, 0xff, 0xfb, 0xfc, 0xe0, 0x38, 0xe, 0x3, 0x80, 0xe0, 0x38, 0x0, - /* U+421 "С" */ + /* U+0421 "С" */ 0x3f, 0x1f, 0xef, 0x3f, 0x87, 0xe0, 0x38, 0xe, 0x3, 0x80, 0xe0, 0x38, 0xe, 0x1f, 0xcf, 0x7f, 0x8f, 0xc0, - /* U+422 "Т" */ + /* U+0422 "Т" */ 0xff, 0xff, 0xf0, 0xe0, 0x38, 0xe, 0x3, 0x80, 0xe0, 0x38, 0xe, 0x3, 0x80, 0xe0, 0x38, 0xe, 0x3, 0x80, - /* U+423 "У" */ + /* U+0423 "У" */ 0xe1, 0xf8, 0x76, 0x19, 0xce, 0x33, 0x8c, 0xc3, 0xb0, 0x7c, 0x1e, 0x3, 0x80, 0xc0, 0x70, 0x1c, 0x6, 0x0, - /* U+424 "Ф" */ + /* U+0424 "Ф" */ 0xc, 0xf, 0xc7, 0xfb, 0xb7, 0xcc, 0xf3, 0x3c, 0xcf, 0x33, 0xcc, 0xf3, 0x3c, 0xcf, 0xb7, 0x7f, 0x8f, 0xc0, 0xc0, 0x30, - /* U+425 "Х" */ + /* U+0425 "Х" */ 0xe1, 0xd8, 0x67, 0x38, 0xcc, 0x3f, 0x7, 0x81, 0xe0, 0x78, 0x1e, 0xf, 0xc3, 0x31, 0xce, 0xe1, 0xf8, 0x70, - /* U+426 "Ц" */ + /* U+0426 "Ц" */ 0xe3, 0xb8, 0xee, 0x3b, 0x8e, 0xe3, 0xb8, 0xee, 0x3b, 0x8e, 0xe3, 0xb8, 0xee, 0x3b, 0x8e, 0xff, 0xff, 0xf0, 0x1c, 0x7, 0x1, 0xc0, - /* U+427 "Ч" */ + /* U+0427 "Ч" */ 0xe3, 0xf1, 0xf8, 0xfc, 0x7e, 0x3f, 0x1f, 0xce, 0xff, 0x3f, 0x81, 0xc0, 0xe0, 0x70, 0x38, 0x1c, - /* U+428 "Ш" */ + /* U+0428 "Ш" */ 0xcc, 0xf3, 0x3c, 0xcf, 0x33, 0xcc, 0xf3, 0x3c, 0xcf, 0x33, 0xcc, 0xf3, 0x3c, 0xcf, 0x33, 0xff, 0xff, 0xf0, - /* U+429 "Щ" */ + /* U+0429 "Щ" */ 0xcc, 0xd9, 0x9b, 0x33, 0x66, 0x6c, 0xcd, 0x99, 0xb3, 0x36, 0x66, 0xcc, 0xd9, 0x9b, 0x33, 0x66, 0x6f, 0xff, 0xff, 0xc0, 0x18, 0x3, - /* U+42A "Ъ" */ + /* U+042A "Ъ" */ 0xfc, 0xf, 0xc0, 0x1c, 0x1, 0xc0, 0x1c, 0x1, 0xfc, 0x1f, 0xe1, 0xcf, 0x1c, 0x71, 0xc7, 0x1c, - 0x71, 0xcf, 0x1f, 0xe1, 0xf8, + 0x71, 0xcf, 0x1f, 0xe1, 0xfc, - /* U+42B "Ы" */ + /* U+042B "Ы" */ 0xc0, 0xf0, 0x3c, 0xf, 0x3, 0xc0, 0xfe, 0x3f, 0xcf, 0x3b, 0xc6, 0xf1, 0xbc, 0x6f, 0x3b, 0xfc, 0xfe, 0x30, - /* U+42C "Ь" */ + /* U+042C "Ь" */ 0xe0, 0x38, 0xe, 0x3, 0x80, 0xe0, 0x3f, 0xcf, 0xfb, 0x8f, 0xe1, 0xf8, 0x7e, 0x1f, 0x8f, 0xff, 0xbf, 0x80, - /* U+42D "Э" */ + /* U+042D "Э" */ 0x3e, 0x3f, 0xb8, 0xfc, 0x70, 0x38, 0x1c, 0x7e, 0x3f, 0x3, 0x81, 0xf8, 0xfc, 0x77, 0xf1, 0xf0, - /* U+42E "Ю" */ + /* U+042E "Ю" */ 0xc7, 0xb3, 0xfc, 0xcf, 0x33, 0xcc, 0xff, 0x3f, 0xcf, 0x33, 0xcc, 0xf3, 0x3c, 0xcf, 0x33, 0xcf, 0xf1, 0xe0, - /* U+42F "Я" */ + /* U+042F "Я" */ 0x3f, 0xdf, 0xff, 0x1f, 0x87, 0xe1, 0xfc, 0x77, 0xfc, 0x7f, 0x19, 0xce, 0x73, 0x1d, 0xc7, 0x71, 0xf8, 0x70, - /* U+430 "а" */ + /* U+0430 "а" */ 0x1f, 0x1f, 0xe7, 0x1c, 0x7, 0x3f, 0xdf, 0xfe, 0x1f, 0x87, 0xe3, 0xff, 0xf3, 0xdc, - /* U+431 "б" */ + /* U+0431 "б" */ 0x1f, 0x3f, 0x9c, 0x1c, 0xe, 0xe7, 0xfb, 0x8f, 0xc7, 0xe3, 0xf1, 0xf8, 0xfc, 0x77, 0xf1, 0xf0, - /* U+432 "в" */ + /* U+0432 "в" */ 0xff, 0x3f, 0xee, 0x3b, 0x8e, 0xfe, 0x3f, 0xee, 0x1f, 0x87, 0xe1, 0xff, 0xef, 0xf0, - /* U+433 "г" */ + /* U+0433 "г" */ 0xff, 0xff, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, - /* U+434 "д" */ + /* U+0434 "д" */ 0x3f, 0xc7, 0xf8, 0xe7, 0x1c, 0xe3, 0x9c, 0x73, 0x8e, 0x71, 0xce, 0x71, 0xdf, 0xff, 0xff, 0xf0, 0x7e, 0xf, 0xc1, 0xc0, - /* U+435 "е" */ + /* U+0435 "е" */ 0x3e, 0x3f, 0xb8, 0xfc, 0x7f, 0xff, 0xff, 0x81, 0xc0, 0xe3, 0xbf, 0x8f, 0x80, - /* U+436 "ж" */ + /* U+0436 "ж" */ 0xe6, 0x76, 0x66, 0x66, 0x63, 0x6c, 0x36, 0xc3, - 0xfc, 0x36, 0xc3, 0x6c, 0x66, 0x66, 0x66, 0xe6, + 0xfc, 0x36, 0xc3, 0x6e, 0x66, 0x66, 0x66, 0xe6, 0x70, - /* U+437 "з" */ + /* U+0437 "з" */ 0x3f, 0x1f, 0xfe, 0x1c, 0x7, 0x1f, 0x87, 0xe0, 0x1c, 0x7, 0xe1, 0xdf, 0xe3, 0xf0, - /* U+438 "и" */ + /* U+0438 "и" */ 0xc3, 0xe3, 0xf1, 0xf9, 0xfc, 0xde, 0xef, 0x67, 0xb3, 0xf1, 0xf8, 0xf8, 0x60, - /* U+439 "й" */ + /* U+0439 "й" */ 0x63, 0x31, 0x8f, 0x83, 0x80, 0x6, 0x1f, 0x1f, 0x8f, 0xcf, 0xe6, 0xf7, 0x7b, 0x3f, 0x9f, 0x8f, 0xc7, 0xc3, - /* U+43A "к" */ + /* U+043A "к" */ 0xe1, 0xf8, 0xee, 0x33, 0x9c, 0xfe, 0x3f, 0x8e, 0x73, 0x9c, 0xe3, 0xb8, 0x6e, 0x1c, - /* U+43B "л" */ + /* U+043B "л" */ 0x3f, 0xcf, 0xf3, 0x9c, 0xe7, 0x39, 0xce, 0x73, 0x9c, 0xe7, 0x39, 0xfc, 0x7e, 0x1c, - /* U+43C "м" */ + /* U+043C "м" */ 0xe1, 0xf8, 0x7f, 0x3f, 0xcf, 0xda, 0xf7, 0xbd, 0xef, 0x33, 0xc0, 0xf0, 0x3c, 0xc, - /* U+43D "н" */ + /* U+043D "н" */ 0xe3, 0xf1, 0xf8, 0xfc, 0x7e, 0x3f, 0xff, 0xff, 0xc7, 0xe3, 0xf1, 0xf8, 0xe0, - /* U+43E "о" */ + /* U+043E "о" */ 0x3e, 0x3f, 0xb8, 0xfc, 0x7e, 0x3f, 0x1f, 0x8f, 0xc7, 0xe3, 0xbf, 0x8f, 0x80, - /* U+43F "п" */ + /* U+043F "п" */ 0xff, 0xff, 0xf8, 0xfc, 0x7e, 0x3f, 0x1f, 0x8f, 0xc7, 0xe3, 0xf1, 0xf8, 0xe0, - /* U+440 "р" */ + /* U+0440 "р" */ 0xee, 0x7f, 0xb8, 0xfc, 0x7e, 0x3f, 0x1f, 0x8f, 0xc7, 0xe3, 0xff, 0xbb, 0x9c, 0xe, 0x7, 0x3, 0x80, - /* U+441 "с" */ + /* U+0441 "с" */ 0x3e, 0x3f, 0xb8, 0xfc, 0x7e, 0x7, 0x3, 0x81, 0xc7, 0xe3, 0xbf, 0x8f, 0x80, - /* U+442 "т" */ + /* U+0442 "т" */ 0xff, 0xff, 0xf0, 0xe0, 0x38, 0xe, 0x3, 0x80, 0xe0, 0x38, 0xe, 0x3, 0x80, 0xe0, - /* U+443 "у" */ + /* U+0443 "у" */ 0xe1, 0xf8, 0x76, 0x19, 0xce, 0x73, 0x8c, 0xc3, 0xf0, 0x7c, 0x1e, 0x7, 0x80, 0xe0, 0x30, 0x1c, 0x6, 0x3, 0x80, - /* U+444 "ф" */ + /* U+0444 "ф" */ 0xc, 0x3, 0x0, 0xc0, 0xfc, 0x7f, 0xbb, 0x7c, 0xcf, 0x33, 0xcc, 0xf3, 0x3c, 0xcf, 0xb7, 0x7f, 0x8f, 0xc0, 0xc0, 0x30, 0xc, 0x3, 0x0, - /* U+445 "х" */ + /* U+0445 "х" */ 0xe1, 0xdc, 0xe3, 0x30, 0xfc, 0x1e, 0x7, 0x81, - 0xe0, 0xfc, 0x73, 0x9c, 0x6e, 0x1c, + 0xe0, 0xfc, 0x73, 0x9c, 0xee, 0x1c, - /* U+446 "ц" */ + /* U+0446 "ц" */ 0xe3, 0xb8, 0xee, 0x3b, 0x8e, 0xe3, 0xb8, 0xee, 0x3b, 0x8e, 0xe3, 0xbf, 0xff, 0xfc, 0x7, 0x1, 0xc0, 0x70, - /* U+447 "ч" */ + /* U+0447 "ч" */ 0xe3, 0xf1, 0xf8, 0xfc, 0x7e, 0x3b, 0xfc, 0xfe, 0x7, 0x3, 0x81, 0xc0, 0xe0, - /* U+448 "ш" */ + /* U+0448 "ш" */ 0xcc, 0xf3, 0x3c, 0xcf, 0x33, 0xcc, 0xf3, 0x3c, 0xcf, 0x33, 0xcc, 0xff, 0xff, 0xfc, - /* U+449 "щ" */ + /* U+0449 "щ" */ 0xcc, 0xd9, 0x9b, 0x33, 0x66, 0x6c, 0xcd, 0x99, 0xb3, 0x36, 0x66, 0xcc, 0xdf, 0xff, 0xff, 0x80, 0x30, 0x6, - /* U+44A "ъ" */ + /* U+044A "ъ" */ 0xfc, 0xf, 0xc0, 0x1c, 0x1, 0xc0, 0x1f, 0xc1, 0xfe, 0x1c, 0x71, 0xc7, 0x1c, 0x71, 0xfe, 0x1f, 0xc0, - /* U+44B "ы" */ + /* U+044B "ы" */ 0xc0, 0xf0, 0x3c, 0xf, 0x3, 0xf8, 0xff, 0x3c, - 0x6f, 0x1b, 0xc6, 0xff, 0x3f, 0x8c, + 0xef, 0x1b, 0xc6, 0xff, 0x3f, 0x8c, - /* U+44C "ь" */ + /* U+044C "ь" */ 0xe0, 0x38, 0xe, 0x3, 0x80, 0xff, 0x3f, 0xee, 0x1f, 0x87, 0xe1, 0xff, 0xef, 0xf0, - /* U+44D "э" */ + /* U+044D "э" */ 0x3e, 0x3f, 0xb8, 0xe0, 0x70, 0xf8, 0x7c, 0xf, 0xc7, 0xe7, 0xbf, 0x8f, 0x80, - /* U+44E "ю" */ + /* U+044E "ю" */ 0xc7, 0xb3, 0xfc, 0xcf, 0x33, 0xfc, 0xff, 0x3c, 0xcf, 0x33, 0xcc, 0xf3, 0xfc, 0x78, - /* U+44F "я" */ + /* U+044F "я" */ 0x3f, 0xbf, 0xf8, 0xfc, 0x7e, 0x3b, 0xfc, 0xfe, 0x77, 0x33, 0xb9, 0xf8, 0xe0, @@ -727,9 +731,18 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t gylph_bitmap[] = { 0xfc, 0x70, 0x7e, 0x7, 0x7, 0x0, 0x70, 0x70, 0x7, 0x7, 0x0, 0x70, 0x70, 0x7, 0x7, 0x0, 0x70, 0x70, 0x7f, 0x7, 0xf, 0xf7, 0xf0, 0xff, - 0xff, 0x7, 0xef, 0xf0, 0x0, 0xff, 0x0, 0x3, + 0xff, 0x7, 0xef, 0xf0, 0x10, 0xff, 0x0, 0x3, 0xc0, 0x0, + /* U+F015 "" */ + 0x0, 0x38, 0xe0, 0x0, 0xf9, 0xc0, 0x3, 0xfb, + 0x80, 0x1e, 0x3f, 0x0, 0x79, 0x3e, 0x1, 0xe7, + 0x3c, 0xf, 0x9f, 0xbc, 0x3c, 0xff, 0x9e, 0xf3, + 0xff, 0x9e, 0xcf, 0xff, 0x98, 0x3f, 0xff, 0x80, + 0x7f, 0xff, 0x0, 0xfc, 0x7e, 0x1, 0xf8, 0xfc, + 0x3, 0xf1, 0xf8, 0x7, 0xe3, 0xf0, 0xf, 0xc7, + 0xe0, + /* U+F017 "" */ 0x3, 0xf8, 0x1, 0xff, 0xc0, 0x7f, 0xfc, 0x1f, 0xff, 0xc7, 0xf1, 0xfc, 0xfe, 0x3f, 0x9f, 0xc7, @@ -739,11 +752,11 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t gylph_bitmap[] = { 0x1, 0xff, 0xc0, 0x1f, 0xf0, 0x0, 0x70, 0x0, /* U+F024 "" */ - 0x70, 0x0, 0xf, 0x80, 0x0, 0xf8, 0x0, 0xf, + 0x70, 0x0, 0xf, 0x80, 0x0, 0xf9, 0x0, 0xf, 0xff, 0xf, 0x7f, 0xff, 0xf7, 0xff, 0xff, 0x7f, 0xff, 0xf7, 0xff, 0xff, 0x7f, 0xff, 0xf7, 0xff, 0xff, 0x7f, 0xff, 0xf7, 0xff, 0xff, 0x7f, 0xff, - 0xf7, 0xff, 0xff, 0x7f, 0x7f, 0xe7, 0x0, 0x78, + 0xf7, 0xff, 0xff, 0x7f, 0xff, 0xe7, 0x0, 0xf8, 0x70, 0x0, 0x7, 0x0, 0x0, 0x70, 0x0, 0x7, 0x0, 0x0, @@ -819,6 +832,14 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t gylph_bitmap[] = { 0xdf, 0x9e, 0x38, 0xf3, 0x7, 0x6, 0x0, 0xe0, 0x0, 0x1c, 0x0, 0x3, 0x80, 0x0, 0x70, 0x0, + /* U+F06E "" */ + 0x0, 0xfe, 0x0, 0xf, 0xff, 0x80, 0x3e, 0xf, + 0x80, 0xf8, 0xf, 0x83, 0xe3, 0x8f, 0x8f, 0x87, + 0x8f, 0xbf, 0x1f, 0x9f, 0xfe, 0xff, 0x3f, 0xfd, + 0xfe, 0x7e, 0xf9, 0xf8, 0xf8, 0xf9, 0xe3, 0xe0, + 0xf8, 0xf, 0x80, 0xf8, 0x3e, 0x0, 0xff, 0xf0, + 0x0, 0x3f, 0x80, 0x0, + /* U+F095 "" */ 0x0, 0x0, 0x0, 0x0, 0x3e, 0x0, 0x7, 0xf0, 0x0, 0x7f, 0x0, 0x7, 0xf0, 0x0, 0xff, 0x0, @@ -857,6 +878,13 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t gylph_bitmap[] = { 0x1, 0xf8, 0x0, 0x9f, 0xc0, 0xf, 0xfc, 0x0, 0x7f, 0xc0, 0x7, 0xf8, 0x0, 0x1f, 0x0, 0x0, + /* U+F201 "" */ + 0x40, 0x0, 0x7, 0x0, 0x0, 0x38, 0x1, 0xf9, + 0xc0, 0x7, 0xce, 0x18, 0x1e, 0x71, 0xe1, 0xf3, + 0x9f, 0x9d, 0x9d, 0xff, 0xc4, 0xe6, 0x7c, 0x7, + 0x1, 0xc0, 0x38, 0x0, 0x1, 0xc0, 0x0, 0xe, + 0x0, 0x0, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xe0, + /* U+F21E "" */ 0x1e, 0x7, 0x83, 0xf9, 0xfe, 0x7f, 0xff, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xff, 0xfc, @@ -869,35 +897,35 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t gylph_bitmap[] = { 0x7f, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xb8, 0x0, 0x1, 0xfd, 0xff, 0xfe, 0xfe, 0xff, 0xff, 0x7f, 0x7f, 0xff, 0x9f, 0xbf, 0xff, 0xcf, 0xdf, 0xff, - 0xe7, 0xe0, 0x0, 0x7, 0xf0, 0x0, 0x3, 0xff, + 0xef, 0xe0, 0x0, 0x7, 0xf0, 0x0, 0x3, 0xff, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xe0, /* U+F241 "" */ 0x7f, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xb8, 0x0, 0x1, 0xfd, 0xff, 0xe0, 0xfe, 0xff, 0xf0, 0x7f, 0x7f, 0xf8, 0x1f, 0xbf, 0xfc, 0xf, 0xdf, 0xfe, - 0x7, 0xe0, 0x0, 0x7, 0xf0, 0x0, 0x3, 0xff, + 0xf, 0xe0, 0x0, 0x7, 0xf0, 0x0, 0x3, 0xff, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xe0, /* U+F242 "" */ 0x7f, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xb8, 0x0, 0x1, 0xfd, 0xfe, 0x0, 0xfe, 0xff, 0x0, 0x7f, 0x7f, 0x80, 0x1f, 0xbf, 0xc0, 0xf, 0xdf, 0xe0, - 0x7, 0xe0, 0x0, 0x7, 0xf0, 0x0, 0x3, 0xff, + 0xf, 0xe0, 0x0, 0x7, 0xf0, 0x0, 0x3, 0xff, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xe0, /* U+F243 "" */ 0x7f, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xb8, 0x0, 0x1, 0xfd, 0xf0, 0x0, 0xfe, 0xf8, 0x0, 0x7f, 0x7c, 0x0, 0x1f, 0xbe, 0x0, 0xf, 0xdf, 0x0, - 0x7, 0xe0, 0x0, 0x7, 0xf0, 0x0, 0x3, 0xff, + 0xf, 0xe0, 0x0, 0x7, 0xf0, 0x0, 0x3, 0xff, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xe0, /* U+F244 "" */ 0x7f, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xb8, 0x0, 0x1, 0xfc, 0x0, 0x0, 0xfe, 0x0, 0x0, 0x7f, 0x0, 0x0, 0x1f, 0x80, 0x0, 0xf, 0xc0, 0x0, - 0x7, 0xe0, 0x0, 0x7, 0xf0, 0x0, 0x3, 0xff, + 0xf, 0xe0, 0x0, 0x7, 0xf0, 0x0, 0x3, 0xff, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xe0, /* U+F252 "" */ @@ -933,9 +961,9 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t gylph_bitmap[] = { 0x78, 0xf, 0xe0, 0x1e, 0x7, 0xf0, 0x3, 0xc1, 0xf8, 0x0, 0xf0, 0x78, 0x0, 0x3c, 0x3c, 0x0, 0xf, 0xbe, 0x0, 0x1, 0xfe, 0x0, 0x0, 0x7e, - 0x0, 0x1c, 0x1f, 0x0, 0x7f, 0x3, 0xc0, 0x7f, + 0x0, 0x1c, 0x1f, 0x0, 0x7f, 0x3, 0xc0, 0x3f, 0xf0, 0xf0, 0x1f, 0xfc, 0x3c, 0xf, 0xfe, 0x7, - 0x87, 0xfe, 0x1, 0xe3, 0xf8, 0x0, 0x70, 0x0, + 0x87, 0xfe, 0x1, 0xe3, 0xf8, 0x0, 0x70, 0x80, 0x0, 0x10, /* U+F3FD "" */ @@ -975,6 +1003,16 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t gylph_bitmap[] = { 0x1f, 0xf0, 0x0, 0xfe, 0x0, 0x7, 0xc0, 0x0, 0x38, 0x0, 0x1, 0x0, 0x0, + /* U+F569 "" */ + 0x0, 0x0, 0x4, 0x0, 0x0, 0x3c, 0x0, 0x0, + 0xf0, 0x0, 0x7, 0xc0, 0x1f, 0xfe, 0x3, 0xff, + 0xfe, 0xf, 0x87, 0xfe, 0x38, 0x3e, 0xe, 0xc0, + 0xf8, 0x7, 0x81, 0xc0, 0xf, 0x0, 0x0, 0x1f, + 0x80, 0x0, 0xff, 0xe0, 0xf, 0xff, 0xff, 0xff, + 0xf9, 0xff, 0xf3, 0xf3, 0xe3, 0xe7, 0xe7, 0xc7, + 0xce, 0xcf, 0x8f, 0x98, 0x9f, 0x1f, 0x20, 0x3e, + 0x3e, 0x0, 0x4, 0x60, 0x0, + /* U+F59F "" */ 0x0, 0x78, 0x0, 0x7, 0xf8, 0x0, 0x1f, 0xe0, 0x0, 0xff, 0xc0, 0x3, 0xff, 0x0, 0xf, 0xfc, @@ -1168,41 +1206,45 @@ static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = { {.bitmap_index = 2484, .adv_w = 192, .box_w = 10, .box_h = 11, .ofs_x = 1, .ofs_y = 0}, {.bitmap_index = 2498, .adv_w = 192, .box_w = 9, .box_h = 11, .ofs_x = 1, .ofs_y = 0}, {.bitmap_index = 2511, .adv_w = 320, .box_w = 20, .box_h = 20, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 2561, .adv_w = 320, .box_w = 19, .box_h = 20, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 2609, .adv_w = 320, .box_w = 20, .box_h = 20, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 2659, .adv_w = 240, .box_w = 15, .box_h = 15, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 2688, .adv_w = 360, .box_w = 23, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 2743, .adv_w = 280, .box_w = 18, .box_h = 17, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 2782, .adv_w = 320, .box_w = 20, .box_h = 17, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 2825, .adv_w = 280, .box_w = 13, .box_h = 17, .ofs_x = 2, .ofs_y = -1}, - {.bitmap_index = 2853, .adv_w = 280, .box_w = 18, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 2901, .adv_w = 280, .box_w = 18, .box_h = 17, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 2940, .adv_w = 280, .box_w = 18, .box_h = 17, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 2979, .adv_w = 280, .box_w = 13, .box_h = 17, .ofs_x = 2, .ofs_y = -1}, - {.bitmap_index = 3007, .adv_w = 320, .box_w = 19, .box_h = 20, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 3055, .adv_w = 320, .box_w = 20, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 3108, .adv_w = 120, .box_w = 8, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 3127, .adv_w = 320, .box_w = 20, .box_h = 20, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 3177, .adv_w = 240, .box_w = 15, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 3213, .adv_w = 320, .box_w = 20, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 3261, .adv_w = 320, .box_w = 20, .box_h = 17, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 3304, .adv_w = 400, .box_w = 25, .box_h = 12, .ofs_x = 0, .ofs_y = 1}, - {.bitmap_index = 3342, .adv_w = 400, .box_w = 25, .box_h = 12, .ofs_x = 0, .ofs_y = 1}, - {.bitmap_index = 3380, .adv_w = 400, .box_w = 25, .box_h = 12, .ofs_x = 0, .ofs_y = 1}, - {.bitmap_index = 3418, .adv_w = 400, .box_w = 25, .box_h = 12, .ofs_x = 0, .ofs_y = 1}, - {.bitmap_index = 3456, .adv_w = 400, .box_w = 25, .box_h = 12, .ofs_x = 0, .ofs_y = 1}, - {.bitmap_index = 3494, .adv_w = 240, .box_w = 15, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 3530, .adv_w = 280, .box_w = 15, .box_h = 20, .ofs_x = 1, .ofs_y = -3}, - {.bitmap_index = 3568, .adv_w = 200, .box_w = 11, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 3597, .adv_w = 280, .box_w = 16, .box_h = 19, .ofs_x = 1, .ofs_y = -2}, - {.bitmap_index = 3635, .adv_w = 400, .box_w = 25, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 3701, .adv_w = 360, .box_w = 23, .box_h = 17, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 3750, .adv_w = 320, .box_w = 20, .box_h = 20, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 3800, .adv_w = 400, .box_w = 25, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 3860, .adv_w = 320, .box_w = 20, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 3913, .adv_w = 360, .box_w = 22, .box_h = 20, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 3968, .adv_w = 360, .box_w = 22, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 4021, .adv_w = 320, .box_w = 20, .box_h = 15, .ofs_x = 0, .ofs_y = 0} + {.bitmap_index = 2561, .adv_w = 360, .box_w = 23, .box_h = 17, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 2610, .adv_w = 320, .box_w = 19, .box_h = 20, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 2658, .adv_w = 320, .box_w = 20, .box_h = 20, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 2708, .adv_w = 240, .box_w = 15, .box_h = 15, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2737, .adv_w = 360, .box_w = 23, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 2792, .adv_w = 280, .box_w = 18, .box_h = 17, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 2831, .adv_w = 320, .box_w = 20, .box_h = 17, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 2874, .adv_w = 280, .box_w = 13, .box_h = 17, .ofs_x = 2, .ofs_y = -1}, + {.bitmap_index = 2902, .adv_w = 280, .box_w = 18, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 2950, .adv_w = 280, .box_w = 18, .box_h = 17, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 2989, .adv_w = 280, .box_w = 18, .box_h = 17, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 3028, .adv_w = 280, .box_w = 13, .box_h = 17, .ofs_x = 2, .ofs_y = -1}, + {.bitmap_index = 3056, .adv_w = 320, .box_w = 19, .box_h = 20, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 3104, .adv_w = 360, .box_w = 23, .box_h = 15, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 3148, .adv_w = 320, .box_w = 20, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 3201, .adv_w = 120, .box_w = 8, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 3220, .adv_w = 320, .box_w = 20, .box_h = 20, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 3270, .adv_w = 240, .box_w = 15, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 3306, .adv_w = 320, .box_w = 20, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 3354, .adv_w = 320, .box_w = 21, .box_h = 15, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 3394, .adv_w = 320, .box_w = 20, .box_h = 17, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 3437, .adv_w = 400, .box_w = 25, .box_h = 12, .ofs_x = 0, .ofs_y = 1}, + {.bitmap_index = 3475, .adv_w = 400, .box_w = 25, .box_h = 12, .ofs_x = 0, .ofs_y = 1}, + {.bitmap_index = 3513, .adv_w = 400, .box_w = 25, .box_h = 12, .ofs_x = 0, .ofs_y = 1}, + {.bitmap_index = 3551, .adv_w = 400, .box_w = 25, .box_h = 12, .ofs_x = 0, .ofs_y = 1}, + {.bitmap_index = 3589, .adv_w = 400, .box_w = 25, .box_h = 12, .ofs_x = 0, .ofs_y = 1}, + {.bitmap_index = 3627, .adv_w = 240, .box_w = 15, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 3663, .adv_w = 280, .box_w = 15, .box_h = 20, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 3701, .adv_w = 200, .box_w = 11, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 3730, .adv_w = 280, .box_w = 16, .box_h = 19, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 3768, .adv_w = 400, .box_w = 25, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 3834, .adv_w = 360, .box_w = 23, .box_h = 17, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 3883, .adv_w = 320, .box_w = 20, .box_h = 20, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 3933, .adv_w = 400, .box_w = 25, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 3993, .adv_w = 320, .box_w = 20, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 4046, .adv_w = 360, .box_w = 23, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 4107, .adv_w = 360, .box_w = 22, .box_h = 20, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 4162, .adv_w = 360, .box_w = 22, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 4215, .adv_w = 320, .box_w = 20, .box_h = 15, .ofs_x = 0, .ofs_y = 0} }; /*--------------------- @@ -1210,11 +1252,11 @@ static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = { *--------------------*/ static const uint16_t unicode_list_2[] = { - 0x0, 0x16, 0x23, 0x26, 0x27, 0x28, 0x39, 0x47, - 0x4a, 0x4b, 0x4c, 0x50, 0x68, 0x94, 0x128, 0x184, - 0x1e5, 0x1fb, 0x21d, 0x23f, 0x240, 0x241, 0x242, 0x243, - 0x251, 0x292, 0x293, 0x2f1, 0x3dc, 0x3fc, 0x45c, 0x54a, - 0x55f, 0x59e, 0x59f, 0x6a8 + 0x0, 0x14, 0x16, 0x23, 0x26, 0x27, 0x28, 0x39, + 0x47, 0x4a, 0x4b, 0x4c, 0x50, 0x68, 0x6d, 0x94, + 0x128, 0x184, 0x1e5, 0x1fb, 0x200, 0x21d, 0x23f, 0x240, + 0x241, 0x242, 0x243, 0x251, 0x292, 0x293, 0x2f1, 0x3dc, + 0x3fc, 0x45c, 0x54a, 0x55f, 0x568, 0x59e, 0x59f, 0x6a8 }; /*Collect the unicode lists and glyph_id offsets*/ @@ -1230,7 +1272,7 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = }, { .range_start = 61441, .range_length = 1705, .glyph_id_start = 160, - .unicode_list = unicode_list_2, .glyph_id_ofs_list = NULL, .list_length = 36, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY + .unicode_list = unicode_list_2, .glyph_id_ofs_list = NULL, .list_length = 40, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY } }; @@ -1240,9 +1282,14 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = * ALL CUSTOM DATA *--------------------*/ +#if LV_VERSION_CHECK(8, 0, 0) /*Store all the custom data of the font*/ +static lv_font_fmt_txt_glyph_cache_t cache; +static const lv_font_fmt_txt_dsc_t font_dsc = { +#else static lv_font_fmt_txt_dsc_t font_dsc = { - .glyph_bitmap = gylph_bitmap, +#endif + .glyph_bitmap = glyph_bitmap, .glyph_dsc = glyph_dsc, .cmaps = cmaps, .kern_dsc = NULL, @@ -1250,7 +1297,10 @@ static lv_font_fmt_txt_dsc_t font_dsc = { .cmap_num = 3, .bpp = 1, .kern_classes = 0, - .bitmap_format = 0 + .bitmap_format = 0, +#if LV_VERSION_CHECK(8, 0, 0) + .cache = &cache +#endif }; @@ -1259,7 +1309,11 @@ static lv_font_fmt_txt_dsc_t font_dsc = { *----------------*/ /*Initialize a public general font descriptor*/ +#if LV_VERSION_CHECK(8, 0, 0) +const lv_font_t jetbrains_mono_bold_20 = { +#else lv_font_t jetbrains_mono_bold_20 = { +#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 = 23, /*The maximum line height required by the font*/ diff --git a/src/displayapp/fonts/open_sans_light.c b/src/displayapp/fonts/open_sans_light.c new file mode 100644 index 00000000..15f0ddf6 --- /dev/null +++ b/src/displayapp/fonts/open_sans_light.c @@ -0,0 +1,1261 @@ +/******************************************************************************* + * Size: 150 px + * Bpp: 1 + * Opts: + ******************************************************************************/ + +#ifdef LV_LVGL_H_INCLUDE_SIMPLE +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + +#ifndef OPEN_SANS_LIGHT +#define OPEN_SANS_LIGHT 1 +#endif + +#if OPEN_SANS_LIGHT + +/*----------------- + * BITMAPS + *----------------*/ + +/*Store the image of the glyphs*/ +static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { + /* U+0030 "0" */ + 0x0, 0x0, 0x0, 0xf, 0xff, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x7, 0xff, 0xff, 0xc0, 0x0, + 0x0, 0x0, 0x0, 0x1, 0xff, 0xff, 0xff, 0x80, + 0x0, 0x0, 0x0, 0x0, 0x3f, 0xff, 0xff, 0xff, + 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, 0xff, 0xff, + 0xfe, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xff, 0xff, + 0xff, 0xf8, 0x0, 0x0, 0x0, 0xf, 0xff, 0xe0, + 0x3, 0xff, 0xf0, 0x0, 0x0, 0x0, 0xff, 0xf8, + 0x0, 0x3, 0xff, 0xc0, 0x0, 0x0, 0xf, 0xfe, + 0x0, 0x0, 0x7, 0xff, 0x0, 0x0, 0x0, 0xff, + 0xe0, 0x0, 0x0, 0xf, 0xfc, 0x0, 0x0, 0x7, + 0xfe, 0x0, 0x0, 0x0, 0x3f, 0xf0, 0x0, 0x0, + 0x7f, 0xc0, 0x0, 0x0, 0x0, 0xff, 0x80, 0x0, + 0x7, 0xfc, 0x0, 0x0, 0x0, 0x1, 0xfe, 0x0, + 0x0, 0x7f, 0xc0, 0x0, 0x0, 0x0, 0xf, 0xf8, + 0x0, 0x3, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x3f, + 0xc0, 0x0, 0x3f, 0xe0, 0x0, 0x0, 0x0, 0x0, + 0xff, 0x0, 0x1, 0xfe, 0x0, 0x0, 0x0, 0x0, + 0x3, 0xfc, 0x0, 0x1f, 0xf0, 0x0, 0x0, 0x0, + 0x0, 0x1f, 0xe0, 0x0, 0xff, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x7f, 0x80, 0xf, 0xf8, 0x0, 0x0, + 0x0, 0x0, 0x3, 0xfc, 0x0, 0x7f, 0x80, 0x0, + 0x0, 0x0, 0x0, 0xf, 0xe0, 0x3, 0xfc, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x7f, 0x80, 0x3f, 0xc0, + 0x0, 0x0, 0x0, 0x0, 0x3, 0xfc, 0x1, 0xfe, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, 0xf, + 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0x80, + 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xfc, + 0x7, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, + 0xf0, 0x3f, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x7f, 0x81, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x3, 0xfc, 0x1f, 0xe0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0xf, 0xe0, 0xff, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x7f, 0x87, 0xf8, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x3, 0xfc, 0x3f, 0xc0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x1f, 0xe1, 0xfe, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0xff, 0x1f, 0xe0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x3, 0xf8, 0xff, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xe7, 0xf8, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x3f, + 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xf9, + 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, + 0xcf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, + 0xfe, 0x7f, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, + 0xf, 0xf3, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x7f, 0xbf, 0xc0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x3, 0xfd, 0xfe, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xf, 0xff, 0xf0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x7f, 0xff, 0x80, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x3, 0xff, 0xfc, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x1f, 0xff, 0xe0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, 0xf8, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xff, + 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, + 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, + 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x7f, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x3, 0xff, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x1f, 0xff, 0xe0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x7, 0xff, 0xf8, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x3f, 0xff, 0xc0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x1, 0xff, 0xfe, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, 0xf0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xff, 0x80, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, 0xfc, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xff, + 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, + 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, + 0xff, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x3f, 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x1, 0xfe, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x1f, 0xe7, 0xf8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xff, 0x3f, 0xc0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x7, 0xf9, 0xfe, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x3f, 0xcf, 0xf0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x1, 0xfe, 0x7f, 0x80, 0x0, + 0x0, 0x0, 0x0, 0x0, 0xf, 0xf3, 0xfc, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0x9f, 0xe0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xfc, 0x7f, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xe3, + 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xfe, + 0x1f, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, + 0xf0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x7f, 0x87, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x3, 0xfc, 0x1f, 0xc0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x1f, 0xe0, 0xff, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x1, 0xfe, 0x7, 0xf8, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xf, 0xf0, 0x3f, 0xc0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x7f, 0x80, 0xfe, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x7, 0xfc, 0x7, 0xf8, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x3f, 0xc0, 0x3f, 0xc0, + 0x0, 0x0, 0x0, 0x0, 0x1, 0xfe, 0x0, 0xfe, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xf0, 0x7, + 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, + 0x3f, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xf8, + 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, + 0x80, 0x7, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x3, + 0xfc, 0x0, 0x1f, 0xe0, 0x0, 0x0, 0x0, 0x0, + 0x3f, 0xe0, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, + 0x1, 0xfe, 0x0, 0x3, 0xfc, 0x0, 0x0, 0x0, + 0x0, 0x1f, 0xf0, 0x0, 0x1f, 0xf0, 0x0, 0x0, + 0x0, 0x1, 0xff, 0x0, 0x0, 0x7f, 0xc0, 0x0, + 0x0, 0x0, 0x1f, 0xf0, 0x0, 0x1, 0xfe, 0x0, + 0x0, 0x0, 0x0, 0xff, 0x80, 0x0, 0xf, 0xf8, + 0x0, 0x0, 0x0, 0xf, 0xf8, 0x0, 0x0, 0x3f, + 0xf0, 0x0, 0x0, 0x1, 0xff, 0x80, 0x0, 0x0, + 0xff, 0xc0, 0x0, 0x0, 0x1f, 0xf8, 0x0, 0x0, + 0x3, 0xff, 0x80, 0x0, 0x3, 0xff, 0x80, 0x0, + 0x0, 0xf, 0xff, 0x0, 0x0, 0x7f, 0xf8, 0x0, + 0x0, 0x0, 0x3f, 0xff, 0x0, 0x1f, 0xff, 0x80, + 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xf8, + 0x0, 0x0, 0x0, 0x1, 0xff, 0xff, 0xff, 0xff, + 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, 0xff, 0xff, + 0xf0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, 0xff, + 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, + 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, + 0xff, 0xc0, 0x0, 0x0, 0x0, + + /* U+0031 "1" */ + 0x0, 0x0, 0x0, 0xf, 0xe0, 0x0, 0x0, 0x3, + 0xfc, 0x0, 0x0, 0x1, 0xff, 0x80, 0x0, 0x0, + 0x7f, 0xf0, 0x0, 0x0, 0x1f, 0xfe, 0x0, 0x0, + 0xf, 0xff, 0xc0, 0x0, 0x3, 0xff, 0xf8, 0x0, + 0x0, 0xff, 0xbf, 0x0, 0x0, 0x7f, 0xe7, 0xe0, + 0x0, 0x1f, 0xf8, 0xfc, 0x0, 0x7, 0xfe, 0x1f, + 0x80, 0x3, 0xff, 0x83, 0xf0, 0x0, 0xff, 0xc0, + 0xfe, 0x0, 0x3f, 0xf0, 0x1f, 0xc0, 0x1f, 0xfc, + 0x3, 0xf8, 0x7, 0xff, 0x0, 0x7f, 0x1, 0xff, + 0x80, 0xf, 0xe0, 0xff, 0xe0, 0x1, 0xfc, 0x3f, + 0xf8, 0x0, 0x3f, 0x8f, 0xfc, 0x0, 0x7, 0xf7, + 0xff, 0x0, 0x0, 0xff, 0xff, 0xc0, 0x0, 0x1f, + 0xff, 0xf0, 0x0, 0x3, 0xfb, 0xf8, 0x0, 0x0, + 0x7f, 0x3e, 0x0, 0x0, 0xf, 0xe3, 0x80, 0x0, + 0x1, 0xfc, 0x20, 0x0, 0x0, 0x3f, 0x80, 0x0, + 0x0, 0x7, 0xf0, 0x0, 0x0, 0x0, 0xfe, 0x0, + 0x0, 0x0, 0x1f, 0xc0, 0x0, 0x0, 0x3, 0xf8, + 0x0, 0x0, 0x0, 0x7f, 0x0, 0x0, 0x0, 0xf, + 0xe0, 0x0, 0x0, 0x1, 0xfc, 0x0, 0x0, 0x0, + 0x3f, 0x80, 0x0, 0x0, 0x7, 0xf0, 0x0, 0x0, + 0x0, 0xfe, 0x0, 0x0, 0x0, 0x1f, 0xc0, 0x0, + 0x0, 0x3, 0xf8, 0x0, 0x0, 0x0, 0x7f, 0x0, + 0x0, 0x0, 0xf, 0xe0, 0x0, 0x0, 0x1, 0xfc, + 0x0, 0x0, 0x0, 0x3f, 0x80, 0x0, 0x0, 0x7, + 0xf0, 0x0, 0x0, 0x0, 0xfe, 0x0, 0x0, 0x0, + 0x1f, 0xc0, 0x0, 0x0, 0x3, 0xf8, 0x0, 0x0, + 0x0, 0x7f, 0x0, 0x0, 0x0, 0xf, 0xe0, 0x0, + 0x0, 0x1, 0xfc, 0x0, 0x0, 0x0, 0x3f, 0x80, + 0x0, 0x0, 0x7, 0xf0, 0x0, 0x0, 0x0, 0xfe, + 0x0, 0x0, 0x0, 0x1f, 0xc0, 0x0, 0x0, 0x3, + 0xf8, 0x0, 0x0, 0x0, 0x7f, 0x0, 0x0, 0x0, + 0xf, 0xe0, 0x0, 0x0, 0x1, 0xfc, 0x0, 0x0, + 0x0, 0x3f, 0x80, 0x0, 0x0, 0x7, 0xf0, 0x0, + 0x0, 0x0, 0xfe, 0x0, 0x0, 0x0, 0x1f, 0xc0, + 0x0, 0x0, 0x3, 0xf8, 0x0, 0x0, 0x0, 0x7f, + 0x0, 0x0, 0x0, 0xf, 0xe0, 0x0, 0x0, 0x1, + 0xfc, 0x0, 0x0, 0x0, 0x3f, 0x80, 0x0, 0x0, + 0x7, 0xf0, 0x0, 0x0, 0x0, 0xfe, 0x0, 0x0, + 0x0, 0x1f, 0xc0, 0x0, 0x0, 0x3, 0xf8, 0x0, + 0x0, 0x0, 0x7f, 0x0, 0x0, 0x0, 0xf, 0xe0, + 0x0, 0x0, 0x1, 0xfc, 0x0, 0x0, 0x0, 0x3f, + 0x80, 0x0, 0x0, 0x7, 0xf0, 0x0, 0x0, 0x0, + 0xfe, 0x0, 0x0, 0x0, 0x1f, 0xc0, 0x0, 0x0, + 0x3, 0xf8, 0x0, 0x0, 0x0, 0x7f, 0x0, 0x0, + 0x0, 0xf, 0xe0, 0x0, 0x0, 0x1, 0xfc, 0x0, + 0x0, 0x0, 0x3f, 0x80, 0x0, 0x0, 0x7, 0xf0, + 0x0, 0x0, 0x0, 0xfe, 0x0, 0x0, 0x0, 0x1f, + 0xc0, 0x0, 0x0, 0x3, 0xf8, 0x0, 0x0, 0x0, + 0x7f, 0x0, 0x0, 0x0, 0xf, 0xe0, 0x0, 0x0, + 0x1, 0xfc, 0x0, 0x0, 0x0, 0x3f, 0x80, 0x0, + 0x0, 0x7, 0xf0, 0x0, 0x0, 0x0, 0xfe, 0x0, + 0x0, 0x0, 0x1f, 0xc0, 0x0, 0x0, 0x3, 0xf8, + 0x0, 0x0, 0x0, 0x7f, 0x0, 0x0, 0x0, 0xf, + 0xe0, 0x0, 0x0, 0x1, 0xfc, 0x0, 0x0, 0x0, + 0x3f, 0x80, 0x0, 0x0, 0x7, 0xf0, 0x0, 0x0, + 0x0, 0xfe, 0x0, 0x0, 0x0, 0x1f, 0xc0, 0x0, + 0x0, 0x3, 0xf8, 0x0, 0x0, 0x0, 0x7f, 0x0, + 0x0, 0x0, 0xf, 0xe0, 0x0, 0x0, 0x1, 0xfc, + 0x0, 0x0, 0x0, 0x3f, 0x80, + + /* U+0032 "2" */ + 0x0, 0x0, 0x0, 0x7f, 0xfe, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x1, 0xff, 0xff, 0xfc, 0x0, 0x0, + 0x0, 0x0, 0x1, 0xff, 0xff, 0xff, 0xf0, 0x0, + 0x0, 0x0, 0x1, 0xff, 0xff, 0xff, 0xff, 0x80, + 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xfc, + 0x0, 0x0, 0x0, 0x7f, 0xff, 0xff, 0xff, 0xff, + 0xe0, 0x0, 0x0, 0x1f, 0xff, 0xf0, 0x1, 0xff, + 0xfe, 0x0, 0x0, 0xf, 0xff, 0xc0, 0x0, 0x3, + 0xff, 0xe0, 0x0, 0x7, 0xff, 0xe0, 0x0, 0x0, + 0x1f, 0xfe, 0x0, 0x1, 0xff, 0xe0, 0x0, 0x0, + 0x0, 0xff, 0xe0, 0x0, 0x7f, 0xf0, 0x0, 0x0, + 0x0, 0xf, 0xfe, 0x0, 0xf, 0xfc, 0x0, 0x0, + 0x0, 0x0, 0xff, 0xc0, 0x0, 0xfe, 0x0, 0x0, + 0x0, 0x0, 0xf, 0xfc, 0x0, 0xf, 0x80, 0x0, + 0x0, 0x0, 0x0, 0xff, 0xc0, 0x1, 0xc0, 0x0, + 0x0, 0x0, 0x0, 0xf, 0xf8, 0x0, 0x10, 0x0, + 0x0, 0x0, 0x0, 0x0, 0xff, 0x80, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x1f, 0xf0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x1, 0xfe, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xe0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xfc, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0x80, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, + 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, + 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x7f, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0xf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x1, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x3f, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x7, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x1f, 0xe0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x3, 0xfc, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x7f, 0x80, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x1f, 0xf0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x3, 0xfc, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x7f, 0x80, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x3, 0xfe, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0x80, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xfe, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0x80, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xfe, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, + 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, + 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, + 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x3f, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x7, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x1, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x7f, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0xf, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x3, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x3f, 0xf0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x7, 0xfc, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x1, 0xff, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x7f, 0xc0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x1f, 0xf8, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x7, 0xfe, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x1, 0xff, 0x80, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x7f, 0xe0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0xf, 0xf8, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xc0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xf0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xfc, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xc0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xf0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xfc, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, + 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, + 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, + 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, + 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x7f, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x1f, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x7, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x1, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x7f, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x1f, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x7, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x1, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x7f, 0xe0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x1f, 0xf8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x7, 0xfe, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x1, 0xff, 0x80, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x7f, 0xe0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x1f, 0xf8, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x7, 0xfe, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0xff, 0x80, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x3f, 0xe0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0xf, 0xf8, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x3, 0xfe, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x80, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xe0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf8, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xfe, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x80, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xf0, + + /* U+0033 "3" */ + 0x0, 0x0, 0x0, 0x1f, 0xff, 0x80, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x7f, 0xff, 0xff, 0xc0, 0x0, + 0x0, 0x0, 0x0, 0x3f, 0xff, 0xff, 0xff, 0x80, + 0x0, 0x0, 0x0, 0x1f, 0xff, 0xff, 0xff, 0xff, + 0x0, 0x0, 0x0, 0xf, 0xff, 0xff, 0xff, 0xff, + 0xf8, 0x0, 0x0, 0x3, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xe0, 0x0, 0x0, 0xff, 0xff, 0xe0, 0x0, + 0xff, 0xff, 0x0, 0x0, 0x3f, 0xff, 0xc0, 0x0, + 0x0, 0xff, 0xf8, 0x0, 0x7, 0xff, 0xe0, 0x0, + 0x0, 0x3, 0xff, 0xc0, 0x1, 0xff, 0xf0, 0x0, + 0x0, 0x0, 0xf, 0xfe, 0x0, 0x3f, 0xfc, 0x0, + 0x0, 0x0, 0x0, 0x7f, 0xf0, 0x7, 0xff, 0x0, + 0x0, 0x0, 0x0, 0x1, 0xff, 0x80, 0x3f, 0xc0, + 0x0, 0x0, 0x0, 0x0, 0xf, 0xfc, 0x1, 0xf8, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xc0, 0xe, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xfe, 0x0, + 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xe0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xfe, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, + 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0xf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x7, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x7f, 0x80, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x7, 0xf8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x7f, 0x80, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x7, 0xf8, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x7f, 0x80, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x7, 0xf8, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0x80, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xf8, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0x80, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf8, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, + 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x1f, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x1, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x3f, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x3, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x7f, 0xc0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xf, 0xf8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x1, 0xff, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x3f, 0xf0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x7, 0xfe, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0xff, 0xc0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x3f, 0xf8, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x7, 0xfe, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, 0xc0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xf8, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, 0xfe, 0x0, + 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0x0, + 0x0, 0x0, 0x0, 0xf, 0xff, 0xff, 0xff, 0x80, + 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xc0, + 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, 0xff, 0xff, + 0xc0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, + 0xff, 0xc0, 0x0, 0x0, 0x0, 0xf, 0xff, 0xff, + 0xff, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, + 0xf, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x3, 0xff, 0xf8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x7, 0xff, 0xc0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0xf, 0xff, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x3f, 0xf8, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, 0xc0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xfe, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xf0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, + 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x7, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x3f, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x3, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x1f, 0xe0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x1, 0xfe, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x1f, 0xe0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, + 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0xf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x1f, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x1, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x1f, 0xe0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x1, 0xfe, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x3f, 0xe0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x3, 0xfc, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x7f, 0xc0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x7, 0xfc, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x80, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf8, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xe0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xfe, + 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, + 0xc0, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, + 0xf8, 0xf, 0x80, 0x0, 0x0, 0x0, 0x0, 0x7, + 0xff, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x1, + 0xff, 0xe0, 0xf, 0xfe, 0x0, 0x0, 0x0, 0x0, + 0x7f, 0xfc, 0x0, 0xff, 0xfe, 0x0, 0x0, 0x0, + 0x7f, 0xff, 0x80, 0xf, 0xff, 0xff, 0x80, 0x0, + 0xff, 0xff, 0xe0, 0x0, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xfc, 0x0, 0x1, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x0, 0x0, 0x7, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xc0, 0x0, 0x0, 0xf, 0xff, + 0xff, 0xff, 0xff, 0xe0, 0x0, 0x0, 0x0, 0x7, + 0xff, 0xff, 0xff, 0xe0, 0x0, 0x0, 0x0, 0x0, + 0x1, 0xff, 0xff, 0x80, 0x0, 0x0, 0x0, + + /* U+0034 "4" */ + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xfc, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x7, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x7, 0xff, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, 0x80, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, + 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x3, 0xff, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x3, 0xfb, 0xf0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x1, 0xfd, 0xf8, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xfc, + 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x1, 0xfc, 0x7e, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0xfe, 0x3f, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x1f, 0x80, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, + 0xf, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x7f, 0x7, 0xe0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x7f, 0x3, 0xf0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0x1, 0xf8, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, + 0x80, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x3f, 0x80, 0x7e, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x3f, 0xc0, 0x3f, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xc0, 0x1f, + 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, + 0xc0, 0xf, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x1f, 0xc0, 0x7, 0xe0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x1f, 0xe0, 0x3, 0xf0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xe0, 0x1, + 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, + 0xe0, 0x0, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0xf, 0xf0, 0x0, 0x7e, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0xf, 0xf0, 0x0, 0x3f, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xf0, 0x0, + 0x1f, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, + 0xf8, 0x0, 0xf, 0xc0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x7, 0xf8, 0x0, 0x7, 0xe0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x3, 0xf8, 0x0, 0x3, 0xf0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xf8, 0x0, + 0x1, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, + 0xfc, 0x0, 0x0, 0xfc, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x3, 0xfc, 0x0, 0x0, 0x7e, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x1, 0xfc, 0x0, 0x0, 0x3f, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xfe, 0x0, + 0x0, 0x1f, 0x80, 0x0, 0x0, 0x0, 0x0, 0x1, + 0xfe, 0x0, 0x0, 0xf, 0xc0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xfe, 0x0, 0x0, 0x7, 0xe0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x3, + 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, + 0x0, 0x1, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, + 0xff, 0x0, 0x0, 0x0, 0xfc, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x7f, 0x0, 0x0, 0x0, 0x7e, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x7f, 0x80, 0x0, 0x0, + 0x3f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0x80, + 0x0, 0x0, 0x1f, 0x80, 0x0, 0x0, 0x0, 0x0, + 0x3f, 0x80, 0x0, 0x0, 0xf, 0xc0, 0x0, 0x0, + 0x0, 0x0, 0x3f, 0xc0, 0x0, 0x0, 0x7, 0xe0, + 0x0, 0x0, 0x0, 0x0, 0x3f, 0xc0, 0x0, 0x0, + 0x3, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xc0, + 0x0, 0x0, 0x1, 0xf8, 0x0, 0x0, 0x0, 0x0, + 0x1f, 0xe0, 0x0, 0x0, 0x0, 0xfc, 0x0, 0x0, + 0x0, 0x0, 0x1f, 0xe0, 0x0, 0x0, 0x0, 0x7e, + 0x0, 0x0, 0x0, 0x0, 0x1f, 0xe0, 0x0, 0x0, + 0x0, 0x3f, 0x0, 0x0, 0x0, 0x0, 0xf, 0xe0, + 0x0, 0x0, 0x0, 0x1f, 0x80, 0x0, 0x0, 0x0, + 0xf, 0xf0, 0x0, 0x0, 0x0, 0xf, 0xc0, 0x0, + 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, 0x0, 0x7, + 0xe0, 0x0, 0x0, 0x0, 0x7, 0xf0, 0x0, 0x0, + 0x0, 0x3, 0xf0, 0x0, 0x0, 0x0, 0x7, 0xf8, + 0x0, 0x0, 0x0, 0x1, 0xf8, 0x0, 0x0, 0x0, + 0x7, 0xf8, 0x0, 0x0, 0x0, 0x0, 0xfc, 0x0, + 0x0, 0x0, 0x3, 0xf8, 0x0, 0x0, 0x0, 0x0, + 0x7e, 0x0, 0x0, 0x0, 0x3, 0xfc, 0x0, 0x0, + 0x0, 0x0, 0x3f, 0x0, 0x0, 0x0, 0x3, 0xfc, + 0x0, 0x0, 0x0, 0x0, 0x1f, 0x80, 0x0, 0x0, + 0x3, 0xfc, 0x0, 0x0, 0x0, 0x0, 0xf, 0xc0, + 0x0, 0x0, 0x1, 0xfc, 0x0, 0x0, 0x0, 0x0, + 0x7, 0xe0, 0x0, 0x0, 0x1, 0xfe, 0x0, 0x0, + 0x0, 0x0, 0x3, 0xf0, 0x0, 0x0, 0x1, 0xfe, + 0x0, 0x0, 0x0, 0x0, 0x1, 0xf8, 0x0, 0x0, + 0x0, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfc, + 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x7e, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x3f, 0x0, 0x0, 0x0, 0xff, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0x80, 0x0, + 0x0, 0x7f, 0x80, 0x0, 0x0, 0x0, 0x0, 0xf, + 0xc0, 0x0, 0x0, 0x7f, 0x80, 0x0, 0x0, 0x0, + 0x0, 0x7, 0xe0, 0x0, 0x0, 0x7f, 0x80, 0x0, + 0x0, 0x0, 0x0, 0x3, 0xf0, 0x0, 0x0, 0x3f, + 0x80, 0x0, 0x0, 0x0, 0x0, 0x1, 0xf8, 0x0, + 0x0, 0x3f, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0xfc, 0x0, 0x0, 0x3f, 0xc0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x7e, 0x0, 0x0, 0x1f, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x1, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0xfe, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, + 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x1f, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0xf, 0xe0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xf0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, + 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x1, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0xfe, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x3f, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x1f, 0xc0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0xf, 0xe0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xf0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x3, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x1, 0xfc, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x3f, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x1f, 0xc0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xe0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, + 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x3, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x1, 0xfc, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x7f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x3f, 0x80, 0x0, 0x0, + + /* U+0035 "5" */ + 0x1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, + 0x0, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, + 0x0, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, + 0x0, 0x7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x80, 0x1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xe0, 0x0, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xf8, 0x0, 0x1f, 0xc0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x7, 0xf0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x1, 0xfc, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x7f, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x3f, 0xc0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x3, 0xfc, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x3f, 0x80, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0xf, 0xe0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x3, 0xf8, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0x80, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xe0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xf8, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xfe, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0x80, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xe0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xf8, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xfe, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, + 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, + 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, + 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x7f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x1f, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0xf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x3, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x3f, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0xf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x3, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x3f, 0x80, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xf, 0xe0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x3, 0xf8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0xfe, 0x0, 0x7f, 0xff, 0x80, + 0x0, 0x0, 0x0, 0x3f, 0x8f, 0xff, 0xff, 0xff, + 0x0, 0x0, 0x0, 0x1f, 0xff, 0xff, 0xff, 0xff, + 0xfc, 0x0, 0x0, 0x7, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xc0, 0x0, 0x1, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xfc, 0x0, 0x0, 0x7f, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xc0, 0x0, 0xf, 0xff, 0xf0, 0x0, + 0x3f, 0xff, 0xfc, 0x0, 0x1, 0xfe, 0x0, 0x0, + 0x0, 0x7f, 0xff, 0x80, 0x0, 0x18, 0x0, 0x0, + 0x0, 0x3, 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x3f, 0xfe, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x3, 0xff, 0xc0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x3f, 0xf8, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x7, 0xff, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0xff, 0xe0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x1f, 0xfc, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xe0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf8, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xc0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xfe, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, + 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, + 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, + 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, + 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x3f, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0xf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x3, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x3f, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0xf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x3, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x3f, 0xc0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x3, 0xfc, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x7f, 0x80, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x1f, 0xe0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x7, 0xf8, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x1, 0xfe, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0xff, 0x80, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x3f, 0xc0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x1f, 0xf0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x7, 0xfc, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x3, 0xfe, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x80, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xc0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xf0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xf8, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xfc, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, 0x3, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, 0x80, + 0xf0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, 0xc0, + 0x3f, 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, 0xe0, + 0xf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xf0, + 0x3, 0xff, 0x80, 0x0, 0x0, 0x1, 0xff, 0xf8, + 0x0, 0xff, 0xfc, 0x0, 0x0, 0x3, 0xff, 0xfc, + 0x0, 0x3f, 0xff, 0xfc, 0x0, 0xf, 0xff, 0xfc, + 0x0, 0xf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, + 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, + 0x0, 0x0, 0x7, 0xff, 0xff, 0xff, 0xff, 0xfe, + 0x0, 0x0, 0x0, 0x3f, 0xff, 0xff, 0xff, 0xfc, + 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xf8, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xc0, + 0x0, 0x0, 0x0, + + /* U+0036 "6" */ + 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xfe, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, + 0x80, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xff, 0xff, + 0xfc, 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, 0xff, + 0xff, 0xe0, 0x0, 0x0, 0x0, 0x3, 0xff, 0xff, + 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xff, + 0xff, 0xff, 0xf8, 0x0, 0x0, 0x0, 0x7, 0xff, + 0xfc, 0x0, 0xf, 0xc0, 0x0, 0x0, 0x0, 0xff, + 0xfe, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0xf, + 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0xf, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0xf, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xf, 0xf8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0xff, 0x80, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0xf, 0xf8, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x7f, 0x80, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x7, 0xfc, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xc0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xfc, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xc0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xfe, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, + 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0xf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x7f, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x7, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x3f, 0xc0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x1, 0xfc, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x1f, 0xe0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0xfe, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x7, 0xf0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0x80, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xf8, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xc0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xfe, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, + 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x7f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x3, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x3f, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x1, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xf, 0xe0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x7f, 0x0, 0x0, 0x3, 0xff, + 0xe0, 0x0, 0x0, 0x3, 0xf8, 0x0, 0x1, 0xff, + 0xff, 0xf0, 0x0, 0x0, 0x1f, 0xc0, 0x0, 0x7f, + 0xff, 0xff, 0xf0, 0x0, 0x0, 0xfe, 0x0, 0xf, + 0xff, 0xff, 0xff, 0xf0, 0x0, 0xf, 0xf0, 0x1, + 0xff, 0xff, 0xff, 0xff, 0xc0, 0x0, 0x7f, 0x0, + 0x3f, 0xff, 0xff, 0xff, 0xff, 0x80, 0x3, 0xf8, + 0x3, 0xff, 0xf0, 0x1, 0xff, 0xfe, 0x0, 0x1f, + 0xc0, 0x7f, 0xf8, 0x0, 0x0, 0xff, 0xf8, 0x0, + 0xfe, 0x7, 0xfe, 0x0, 0x0, 0x1, 0xff, 0xe0, + 0x7, 0xf0, 0x7f, 0xc0, 0x0, 0x0, 0x3, 0xff, + 0x80, 0x3f, 0x87, 0xf8, 0x0, 0x0, 0x0, 0x7, + 0xfe, 0x1, 0xfc, 0x7f, 0x80, 0x0, 0x0, 0x0, + 0x1f, 0xf8, 0xf, 0xe7, 0xf8, 0x0, 0x0, 0x0, + 0x0, 0x7f, 0xe0, 0x7f, 0x7f, 0x0, 0x0, 0x0, + 0x0, 0x1, 0xff, 0x3, 0xff, 0xf0, 0x0, 0x0, + 0x0, 0x0, 0x7, 0xfc, 0x1f, 0xff, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x1f, 0xf0, 0xff, 0xf8, 0x0, + 0x0, 0x0, 0x0, 0x0, 0xff, 0x8f, 0xff, 0x80, + 0x0, 0x0, 0x0, 0x0, 0x3, 0xfc, 0x7f, 0xf8, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xf3, 0xff, + 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0x9f, + 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xfc, + 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, + 0xf3, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x7f, 0x9f, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x3, 0xfc, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x1f, 0xe7, 0xf8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xff, 0xbf, 0xc0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x3, 0xfd, 0xfe, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x1f, 0xef, 0xf0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0xff, 0x7f, 0x80, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x7, 0xfb, 0xfc, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xdf, 0xe0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xfe, 0xff, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf7, + 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, + 0x9f, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, + 0xfc, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x1f, 0xe7, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0xff, 0x3f, 0xc0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x7, 0xf8, 0xfe, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x3f, 0xc7, 0xf0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x3, 0xfc, 0x3f, 0x80, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x1f, 0xe1, 0xfe, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0xff, 0x7, 0xf0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x7, 0xf8, 0x3f, 0xc0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xc1, 0xfe, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xfc, 0x7, + 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xe0, + 0x3f, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, + 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, + 0xf0, 0x7, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x7f, 0x80, 0x1f, 0xe0, 0x0, 0x0, 0x0, 0x0, + 0x7, 0xfc, 0x0, 0xff, 0x80, 0x0, 0x0, 0x0, + 0x0, 0x3f, 0xc0, 0x3, 0xfc, 0x0, 0x0, 0x0, + 0x0, 0x3, 0xfe, 0x0, 0x1f, 0xf0, 0x0, 0x0, + 0x0, 0x0, 0x3f, 0xe0, 0x0, 0x7f, 0xc0, 0x0, + 0x0, 0x0, 0x3, 0xfe, 0x0, 0x1, 0xff, 0x0, + 0x0, 0x0, 0x0, 0x3f, 0xf0, 0x0, 0x7, 0xfc, + 0x0, 0x0, 0x0, 0x3, 0xff, 0x0, 0x0, 0x3f, + 0xf8, 0x0, 0x0, 0x0, 0x3f, 0xf0, 0x0, 0x0, + 0xff, 0xe0, 0x0, 0x0, 0x3, 0xff, 0x0, 0x0, + 0x3, 0xff, 0xc0, 0x0, 0x0, 0x7f, 0xf0, 0x0, + 0x0, 0xf, 0xff, 0x80, 0x0, 0x1f, 0xff, 0x0, + 0x0, 0x0, 0x1f, 0xff, 0xc0, 0xf, 0xff, 0xf0, + 0x0, 0x0, 0x0, 0x7f, 0xff, 0xff, 0xff, 0xfe, + 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, + 0xe0, 0x0, 0x0, 0x0, 0x3, 0xff, 0xff, 0xff, + 0xfc, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, 0xff, + 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, + 0xff, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, + 0xff, 0xe0, 0x0, 0x0, 0x0, + + /* U+0037 "7" */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xfc, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x3f, 0xc0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x1, 0xfe, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x1f, 0xe0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0x80, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xfc, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, + 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, + 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x1f, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0xf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x7f, 0x80, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x7, 0xfc, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x3f, 0xc0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x3, 0xfe, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x1f, 0xe0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0x80, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xf8, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, + 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, + 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x1f, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0xf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x7f, 0x80, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x7, 0xf8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x3f, 0xc0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x3, 0xfe, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x1f, 0xe0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0x80, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xf8, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, + 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, + 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x1f, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x1, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0xf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x7f, 0x80, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x7, 0xf8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x3f, 0xc0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x3, 0xfc, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x1f, 0xe0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x80, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xf8, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, + 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, + 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x1f, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x1, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0xf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x7, 0xf8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x7f, 0xc0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x3, 0xfc, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x1f, 0xe0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x80, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xf8, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, + 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, + 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x1f, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x1, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0xf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x7, 0xf8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x7f, 0xc0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x3, 0xfc, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x3f, 0xe0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x1, 0xfe, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x80, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xf8, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, + 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, + 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x3f, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x1, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0xf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x7, 0xf8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x7f, 0xc0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x3, 0xfc, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x3f, 0xe0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x1, 0xfe, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xf0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x80, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xf8, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, + 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, + 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x3f, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x1, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x1f, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xf, 0xf8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x7f, 0xc0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x3, 0xfc, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, + + /* U+0038 "8" */ + 0x0, 0x0, 0x0, 0x1f, 0xff, 0x80, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x3f, 0xff, 0xff, 0x80, 0x0, + 0x0, 0x0, 0x0, 0x1f, 0xff, 0xff, 0xff, 0x0, + 0x0, 0x0, 0x0, 0x7, 0xff, 0xff, 0xff, 0xfc, + 0x0, 0x0, 0x0, 0x1, 0xff, 0xff, 0xff, 0xff, + 0xf0, 0x0, 0x0, 0x0, 0x3f, 0xff, 0xff, 0xff, + 0xff, 0xc0, 0x0, 0x0, 0xf, 0xff, 0xf0, 0x1, + 0xff, 0xfe, 0x0, 0x0, 0x1, 0xff, 0xf0, 0x0, + 0x1, 0xff, 0xf0, 0x0, 0x0, 0x3f, 0xf8, 0x0, + 0x0, 0x3, 0xff, 0x80, 0x0, 0x7, 0xfe, 0x0, + 0x0, 0x0, 0xf, 0xfc, 0x0, 0x0, 0xff, 0xc0, + 0x0, 0x0, 0x0, 0x7f, 0xe0, 0x0, 0x1f, 0xf8, + 0x0, 0x0, 0x0, 0x3, 0xff, 0x0, 0x1, 0xff, + 0x0, 0x0, 0x0, 0x0, 0x1f, 0xf8, 0x0, 0x3f, + 0xe0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x80, 0x7, + 0xfc, 0x0, 0x0, 0x0, 0x0, 0x7, 0xfc, 0x0, + 0x7f, 0x80, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xc0, + 0x7, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x3, 0xfc, + 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, + 0xe0, 0xf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x1, + 0xfe, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x1f, 0xe0, 0x1f, 0xe0, 0x0, 0x0, 0x0, 0x0, + 0x1, 0xff, 0x1, 0xfe, 0x0, 0x0, 0x0, 0x0, + 0x0, 0xf, 0xf0, 0x1f, 0xe0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xff, 0x1, 0xfe, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xf, 0xf0, 0x1f, 0xe0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0xff, 0x1, 0xfe, 0x0, 0x0, + 0x0, 0x0, 0x0, 0xf, 0xf0, 0x1f, 0xe0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0xff, 0x1, 0xfe, 0x0, + 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, 0x1f, 0xe0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x1, 0xfe, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, 0x1f, + 0xf0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xfe, 0x0, + 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xe0, + 0xf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xfe, + 0x0, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, 0x3f, + 0xe0, 0x7, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x3, + 0xfc, 0x0, 0x7f, 0xc0, 0x0, 0x0, 0x0, 0x0, + 0x7f, 0xc0, 0x7, 0xfe, 0x0, 0x0, 0x0, 0x0, + 0x7, 0xf8, 0x0, 0x3f, 0xf0, 0x0, 0x0, 0x0, + 0x0, 0xff, 0x80, 0x1, 0xff, 0x0, 0x0, 0x0, + 0x0, 0x1f, 0xf0, 0x0, 0x1f, 0xf8, 0x0, 0x0, + 0x0, 0x3, 0xfe, 0x0, 0x0, 0xff, 0xe0, 0x0, + 0x0, 0x0, 0x7f, 0xc0, 0x0, 0x7, 0xff, 0x0, + 0x0, 0x0, 0xf, 0xf8, 0x0, 0x0, 0x3f, 0xf8, + 0x0, 0x0, 0x1, 0xff, 0x80, 0x0, 0x1, 0xff, + 0xe0, 0x0, 0x0, 0x7f, 0xe0, 0x0, 0x0, 0xf, + 0xff, 0x80, 0x0, 0x1f, 0xfc, 0x0, 0x0, 0x0, + 0x7f, 0xfe, 0x0, 0x3, 0xff, 0x80, 0x0, 0x0, + 0x1, 0xff, 0xf8, 0x0, 0xff, 0xe0, 0x0, 0x0, + 0x0, 0xf, 0xff, 0xe0, 0x3f, 0xfc, 0x0, 0x0, + 0x0, 0x0, 0x3f, 0xff, 0x9f, 0xff, 0x0, 0x0, + 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xc0, 0x0, + 0x0, 0x0, 0x0, 0x3, 0xff, 0xff, 0xf0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, 0xfc, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xf0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xff, 0xff, + 0xc0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xff, 0xff, + 0xff, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, 0xe7, + 0xff, 0xfc, 0x0, 0x0, 0x0, 0x0, 0xff, 0xf8, + 0xf, 0xff, 0xf0, 0x0, 0x0, 0x0, 0x3f, 0xfe, + 0x0, 0x3f, 0xff, 0xc0, 0x0, 0x0, 0x7, 0xff, + 0x80, 0x0, 0xff, 0xfe, 0x0, 0x0, 0x1, 0xff, + 0xe0, 0x0, 0x3, 0xff, 0xf8, 0x0, 0x0, 0x3f, + 0xf8, 0x0, 0x0, 0x7, 0xff, 0xc0, 0x0, 0x7, + 0xfe, 0x0, 0x0, 0x0, 0x3f, 0xfe, 0x0, 0x0, + 0xff, 0xc0, 0x0, 0x0, 0x0, 0xff, 0xf0, 0x0, + 0x1f, 0xf8, 0x0, 0x0, 0x0, 0x3, 0xff, 0x80, + 0x3, 0xff, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xfc, + 0x0, 0x7f, 0xc0, 0x0, 0x0, 0x0, 0x0, 0xff, + 0xe0, 0xf, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x3, + 0xff, 0x0, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, + 0x1f, 0xf0, 0x1f, 0xf0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0xff, 0x81, 0xfe, 0x0, 0x0, 0x0, 0x0, + 0x0, 0xf, 0xf8, 0x3f, 0xe0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x7f, 0xc3, 0xfc, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x3, 0xfc, 0x7f, 0xc0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x3f, 0xe7, 0xf8, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x3, 0xfe, 0x7f, 0x80, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x1f, 0xe7, 0xf8, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x1, 0xfe, 0xff, 0x80, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xff, 0xf0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, + 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, + 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, + 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0xf, 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0xf, 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xf, 0xff, 0xf0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x1, 0xfe, 0x7f, 0x80, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x1f, 0xe7, 0xf8, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x1, 0xfe, 0x7f, 0x80, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x3f, 0xe7, 0xfc, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x3, 0xfc, 0x3f, 0xc0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xc3, 0xfe, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xf8, 0x1f, + 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x81, + 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xf0, + 0xf, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, + 0x0, 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x7f, + 0xe0, 0x7, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xf, + 0xfc, 0x0, 0x3f, 0xf0, 0x0, 0x0, 0x0, 0x1, + 0xff, 0x80, 0x3, 0xff, 0xc0, 0x0, 0x0, 0x0, + 0x7f, 0xf0, 0x0, 0x1f, 0xff, 0x0, 0x0, 0x0, + 0x1f, 0xfe, 0x0, 0x0, 0x7f, 0xfe, 0x0, 0x0, + 0xf, 0xff, 0xc0, 0x0, 0x3, 0xff, 0xfe, 0x0, + 0xf, 0xff, 0xf8, 0x0, 0x0, 0x1f, 0xff, 0xff, + 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x7f, 0xff, + 0xff, 0xff, 0xff, 0xc0, 0x0, 0x0, 0x1, 0xff, + 0xff, 0xff, 0xff, 0xf0, 0x0, 0x0, 0x0, 0x7, + 0xff, 0xff, 0xff, 0xf8, 0x0, 0x0, 0x0, 0x0, + 0x7, 0xff, 0xff, 0xfc, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x7, 0xff, 0xf8, 0x0, 0x0, 0x0, + + /* U+0039 "9" */ + 0x0, 0x0, 0x0, 0x1f, 0xfe, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x3f, 0xff, 0xfe, 0x0, 0x0, + 0x0, 0x0, 0x0, 0xf, 0xff, 0xff, 0xfc, 0x0, + 0x0, 0x0, 0x0, 0x3, 0xff, 0xff, 0xff, 0xf0, + 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, + 0xc0, 0x0, 0x0, 0x0, 0x3f, 0xff, 0xff, 0xff, + 0xfe, 0x0, 0x0, 0x0, 0x7, 0xff, 0xf0, 0x3, + 0xff, 0xf8, 0x0, 0x0, 0x0, 0xff, 0xf0, 0x0, + 0x3, 0xff, 0xc0, 0x0, 0x0, 0x1f, 0xfc, 0x0, + 0x0, 0xf, 0xfe, 0x0, 0x0, 0x3, 0xff, 0x0, + 0x0, 0x0, 0x3f, 0xf0, 0x0, 0x0, 0x7f, 0xc0, + 0x0, 0x0, 0x0, 0xff, 0x80, 0x0, 0xf, 0xf8, + 0x0, 0x0, 0x0, 0x7, 0xfc, 0x0, 0x1, 0xff, + 0x0, 0x0, 0x0, 0x0, 0x3f, 0xe0, 0x0, 0x3f, + 0xe0, 0x0, 0x0, 0x0, 0x1, 0xfe, 0x0, 0x3, + 0xfc, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, 0x0, + 0x7f, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0x80, + 0xf, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x7, 0xf8, + 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, + 0xc0, 0x1f, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x1, + 0xfc, 0x1, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x1f, 0xe0, 0x1f, 0xe0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0xfe, 0x3, 0xfc, 0x0, 0x0, 0x0, 0x0, + 0x0, 0xf, 0xf0, 0x3f, 0xc0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x7f, 0x3, 0xfc, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x7, 0xf0, 0x7f, 0x80, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x3f, 0x87, 0xf8, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x3, 0xf8, 0x7f, 0x80, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x3f, 0x87, 0xf8, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x1, 0xfc, 0xff, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xcf, 0xf0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xfc, 0xff, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xcf, + 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xfe, + 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, + 0xef, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0xfe, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0xf, 0xef, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0xfe, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0xf, 0xef, 0xf0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xfe, 0xff, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xf, 0xff, 0xf0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0xf, 0xff, 0xf0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x80, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x1f, 0xf7, 0xf8, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, 0x7f, 0x80, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xf7, 0xf8, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, 0x7f, + 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xf3, + 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, + 0x3f, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, + 0xf3, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, + 0xff, 0x1f, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x1, + 0xff, 0xf1, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x3f, 0xff, 0xf, 0xf8, 0x0, 0x0, 0x0, 0x0, + 0x7, 0xf7, 0xf0, 0xff, 0x80, 0x0, 0x0, 0x0, + 0x0, 0xfe, 0x7f, 0x7, 0xfc, 0x0, 0x0, 0x0, + 0x0, 0x1f, 0xc7, 0xf0, 0x7f, 0xe0, 0x0, 0x0, + 0x0, 0x3, 0xf8, 0x7f, 0x3, 0xff, 0x80, 0x0, + 0x0, 0x0, 0xff, 0xf, 0xf0, 0x1f, 0xfc, 0x0, + 0x0, 0x0, 0x1f, 0xe0, 0xff, 0x0, 0xff, 0xf0, + 0x0, 0x0, 0x7, 0xfc, 0xf, 0xf0, 0x7, 0xff, + 0xc0, 0x0, 0x3, 0xff, 0x80, 0xfe, 0x0, 0x3f, + 0xff, 0xc0, 0x3, 0xff, 0xf0, 0xf, 0xe0, 0x1, + 0xff, 0xff, 0xff, 0xff, 0xfc, 0x0, 0xfe, 0x0, + 0x7, 0xff, 0xff, 0xff, 0xff, 0x0, 0xf, 0xe0, + 0x0, 0x1f, 0xff, 0xff, 0xff, 0xe0, 0x0, 0xfe, + 0x0, 0x0, 0x7f, 0xff, 0xff, 0xf0, 0x0, 0xf, + 0xe0, 0x0, 0x0, 0xff, 0xff, 0xf8, 0x0, 0x1, + 0xfe, 0x0, 0x0, 0x0, 0xff, 0xf8, 0x0, 0x0, + 0x1f, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x1, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x1f, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x1, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x3f, 0xc0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x3, 0xfc, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x3f, 0x80, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x3, 0xf8, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x7f, 0x80, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x7, 0xf8, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xe0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xfe, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, + 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, + 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x3f, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x7, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x7f, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0xf, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x1f, 0xf0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x3, 0xfe, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x3f, 0xc0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x7, 0xfc, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0xff, 0x80, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x1f, 0xf0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xe0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xfc, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, 0x80, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xf0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xfe, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, + 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, + 0xf8, 0x0, 0x0, 0x1, 0x80, 0x0, 0x0, 0xff, + 0xff, 0x0, 0x0, 0x0, 0x1f, 0xe0, 0x0, 0xff, + 0xff, 0xc0, 0x0, 0x0, 0x1, 0xff, 0xff, 0xff, + 0xff, 0xf0, 0x0, 0x0, 0x0, 0x1f, 0xff, 0xff, + 0xff, 0xfc, 0x0, 0x0, 0x0, 0x1, 0xff, 0xff, + 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xff, + 0xff, 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, 0xff, + 0xff, 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x7f, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0 +}; + + +/*--------------------- + * GLYPH DESCRIPTION + *--------------------*/ + +static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = { + {.bitmap_index = 0, .adv_w = 0, .box_w = 0, .box_h = 0, .ofs_x = 0, .ofs_y = 0} /* id = 0 reserved */, + {.bitmap_index = 0, .adv_w = 1370, .box_w = 69, .box_h = 110, .ofs_x = 8, .ofs_y = -1}, + {.bitmap_index = 949, .adv_w = 1370, .box_w = 35, .box_h = 107, .ofs_x = 15, .ofs_y = 0}, + {.bitmap_index = 1418, .adv_w = 1370, .box_w = 67, .box_h = 108, .ofs_x = 8, .ofs_y = 0}, + {.bitmap_index = 2323, .adv_w = 1370, .box_w = 68, .box_h = 110, .ofs_x = 7, .ofs_y = -1}, + {.bitmap_index = 3258, .adv_w = 1370, .box_w = 81, .box_h = 108, .ofs_x = 3, .ofs_y = -1}, + {.bitmap_index = 4352, .adv_w = 1370, .box_w = 66, .box_h = 108, .ofs_x = 10, .ofs_y = -1}, + {.bitmap_index = 5243, .adv_w = 1370, .box_w = 69, .box_h = 110, .ofs_x = 9, .ofs_y = -1}, + {.bitmap_index = 6192, .adv_w = 1370, .box_w = 69, .box_h = 106, .ofs_x = 8, .ofs_y = 0}, + {.bitmap_index = 7107, .adv_w = 1370, .box_w = 68, .box_h = 110, .ofs_x = 9, .ofs_y = -1}, + {.bitmap_index = 8042, .adv_w = 1370, .box_w = 68, .box_h = 110, .ofs_x = 8, .ofs_y = -1} +}; + +/*--------------------- + * CHARACTER MAPPING + *--------------------*/ + + + +/*Collect the unicode lists and glyph_id offsets*/ +static const lv_font_fmt_txt_cmap_t cmaps[] = +{ + { + .range_start = 48, .range_length = 10, .glyph_id_start = 1, + .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY + } +}; + + + +/*-------------------- + * ALL CUSTOM DATA + *--------------------*/ + +#if LV_VERSION_CHECK(8, 0, 0) +/*Store all the custom data of the font*/ +static lv_font_fmt_txt_glyph_cache_t cache; +static const lv_font_fmt_txt_dsc_t font_dsc = { +#else +static lv_font_fmt_txt_dsc_t font_dsc = { +#endif + .glyph_bitmap = glyph_bitmap, + .glyph_dsc = glyph_dsc, + .cmaps = cmaps, + .kern_dsc = NULL, + .kern_scale = 0, + .cmap_num = 1, + .bpp = 1, + .kern_classes = 0, + .bitmap_format = 0, +#if LV_VERSION_CHECK(8, 0, 0) + .cache = &cache +#endif +}; + + +/*----------------- + * PUBLIC FONT + *----------------*/ + +/*Initialize a public general font descriptor*/ +#if LV_VERSION_CHECK(8, 0, 0) +const lv_font_t open_sans_light = { +#else +lv_font_t open_sans_light = { +#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 = 110, /*The maximum line height required by the font*/ + .base_line = 1, /*Baseline measured from the bottom of the line*/ +#if !(LVGL_VERSION_MAJOR == 6 && LVGL_VERSION_MINOR == 0) + .subpx = LV_FONT_SUBPX_NONE, +#endif +#if LV_VERSION_CHECK(7, 4, 0) + .underline_position = -11, + .underline_thickness = 7, +#endif + .dsc = &font_dsc /*The custom font data. Will be accessed by `get_glyph_bitmap/dsc` */ +}; + + + +#endif /*#if OPEN_SANS_LIGHT*/ + diff --git a/src/displayapp/fonts/open_sans_light.ttf b/src/displayapp/fonts/open_sans_light.ttf Binary files differnew file mode 100644 index 00000000..6580d3a1 --- /dev/null +++ b/src/displayapp/fonts/open_sans_light.ttf diff --git a/src/displayapp/screens/ApplicationList.cpp b/src/displayapp/screens/ApplicationList.cpp index d434c177..d6c3970b 100644 --- a/src/displayapp/screens/ApplicationList.cpp +++ b/src/displayapp/screens/ApplicationList.cpp @@ -62,8 +62,8 @@ std::unique_ptr<Screen> ApplicationList::CreateScreen2() { {Symbols::paintbrush, Apps::Paint}, {Symbols::paddle, Apps::Paddle}, {"2", Apps::Twos}, - {"M", Apps::Motion}, - {"b", Apps::Metronome}, + {Symbols::chartLine, Apps::Motion}, + {Symbols::drum, Apps::Metronome}, {"", Apps::None}, }}; diff --git a/src/displayapp/screens/BatteryIcon.cpp b/src/displayapp/screens/BatteryIcon.cpp index ff8a1381..c67bcb23 100644 --- a/src/displayapp/screens/BatteryIcon.cpp +++ b/src/displayapp/screens/BatteryIcon.cpp @@ -1,9 +1,10 @@ +#include <cstdint> #include "BatteryIcon.h" #include "Symbols.h" using namespace Pinetime::Applications::Screens; -const char* BatteryIcon::GetBatteryIcon(int batteryPercent) { +const char* BatteryIcon::GetBatteryIcon(uint8_t batteryPercent) { if (batteryPercent > 87) return Symbols::batteryFull; if (batteryPercent > 62) diff --git a/src/displayapp/screens/BatteryIcon.h b/src/displayapp/screens/BatteryIcon.h index 9c192ff7..b370b331 100644 --- a/src/displayapp/screens/BatteryIcon.h +++ b/src/displayapp/screens/BatteryIcon.h @@ -6,7 +6,7 @@ namespace Pinetime { class BatteryIcon { public: static const char* GetUnknownIcon(); - static const char* GetBatteryIcon(int batteryPercent); + static const char* GetBatteryIcon(uint8_t batteryPercent); static const char* GetPlugIcon(bool isCharging); }; } diff --git a/src/displayapp/screens/BatteryInfo.cpp b/src/displayapp/screens/BatteryInfo.cpp index 1ab8b0ad..0ab47ebf 100644 --- a/src/displayapp/screens/BatteryInfo.cpp +++ b/src/displayapp/screens/BatteryInfo.cpp @@ -9,11 +9,6 @@ static void lv_update_task(struct _lv_task_t* task) { user_data->UpdateScreen(); } -static void lv_anim_task(struct _lv_task_t* task) { - auto user_data = static_cast<BatteryInfo*>(task->user_data); - user_data->UpdateAnim(); -} - BatteryInfo::BatteryInfo(Pinetime::Applications::DisplayApp* app, Pinetime::Controllers::Battery& batteryController) : Screen(app), batteryController {batteryController} { @@ -24,12 +19,12 @@ BatteryInfo::BatteryInfo(Pinetime::Applications::DisplayApp* app, Pinetime::Cont lv_obj_set_size(charging_bar, 200, 15); lv_bar_set_range(charging_bar, 0, 100); lv_obj_align(charging_bar, nullptr, LV_ALIGN_CENTER, 0, 10); - lv_bar_set_anim_time(charging_bar, 2000); + lv_bar_set_anim_time(charging_bar, 1000); lv_obj_set_style_local_radius(charging_bar, LV_BAR_PART_BG, LV_STATE_DEFAULT, LV_RADIUS_CIRCLE); lv_obj_set_style_local_bg_color(charging_bar, LV_BAR_PART_BG, LV_STATE_DEFAULT, lv_color_hex(0x222222)); lv_obj_set_style_local_bg_opa(charging_bar, LV_BAR_PART_BG, LV_STATE_DEFAULT, LV_OPA_100); lv_obj_set_style_local_bg_color(charging_bar, LV_BAR_PART_INDIC, LV_STATE_DEFAULT, lv_color_hex(0xFF0000)); - lv_bar_set_value(charging_bar, batteryPercent, LV_ANIM_OFF); + lv_bar_set_value(charging_bar, batteryPercent, LV_ANIM_ON); status = lv_label_create(lv_scr_act(), nullptr); lv_label_set_text_static(status, "Reading Battery status"); @@ -38,24 +33,13 @@ BatteryInfo::BatteryInfo(Pinetime::Applications::DisplayApp* app, Pinetime::Cont percent = lv_label_create(lv_scr_act(), nullptr); lv_obj_set_style_local_text_font(percent, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_76); - if (batteryPercent >= 0) { - lv_label_set_text_fmt(percent, "%02i%%", batteryPercent); - } else { - lv_label_set_text(percent, "--%"); - } + lv_label_set_text_fmt(percent, "%02i%%", batteryPercent); lv_label_set_align(percent, LV_LABEL_ALIGN_LEFT); lv_obj_align(percent, nullptr, LV_ALIGN_CENTER, 0, -60); - // hack to not use the flot functions from printf - uint8_t batteryVoltageBytes[2]; - batteryVoltageBytes[1] = static_cast<uint8_t>(batteryVoltage); // truncate whole numbers - batteryVoltageBytes[0] = - static_cast<uint8_t>((batteryVoltage - batteryVoltageBytes[1]) * 100); // remove whole part of flt and shift 2 places over - // - voltage = lv_label_create(lv_scr_act(), nullptr); lv_obj_set_style_local_text_color(voltage, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0xC6A600)); - lv_label_set_text_fmt(voltage, "%1i.%02i volts", batteryVoltageBytes[1], batteryVoltageBytes[0]); + lv_label_set_text_fmt(voltage, "%1i.%02i volts", batteryVoltage / 1000, batteryVoltage % 1000 / 10); lv_label_set_align(voltage, LV_LABEL_ALIGN_CENTER); lv_obj_align(voltage, nullptr, LV_ALIGN_CENTER, 0, 95); @@ -65,40 +49,15 @@ BatteryInfo::BatteryInfo(Pinetime::Applications::DisplayApp* app, Pinetime::Cont lv_obj_set_pos(backgroundLabel, 0, 0); lv_label_set_text_static(backgroundLabel, ""); - taskUpdate = lv_task_create(lv_update_task, 500000, LV_TASK_PRIO_LOW, this); - taskAnim = lv_task_create(lv_anim_task, 1000, LV_TASK_PRIO_LOW, this); + taskUpdate = lv_task_create(lv_update_task, 5000, LV_TASK_PRIO_LOW, this); UpdateScreen(); } BatteryInfo::~BatteryInfo() { lv_task_del(taskUpdate); - lv_task_del(taskAnim); lv_obj_clean(lv_scr_act()); } -void BatteryInfo::UpdateAnim() { - batteryPercent = batteryController.PercentRemaining(); - - if (batteryPercent >= 0) { - if (batteryController.IsCharging() and batteryPercent < 100) { - animation += 1; - if (animation >= 100) { - animation = 0; - } - - } else { - if (animation > batteryPercent) { - animation--; - } - if (animation < batteryPercent) { - animation++; - } - } - - lv_bar_set_value(charging_bar, animation, LV_ANIM_OFF); - } -} - void BatteryInfo::UpdateScreen() { batteryController.Update(); @@ -106,39 +65,27 @@ void BatteryInfo::UpdateScreen() { batteryPercent = batteryController.PercentRemaining(); batteryVoltage = batteryController.Voltage(); - if (batteryPercent >= 0) { - if (batteryController.IsCharging() and batteryPercent < 100) { - lv_obj_set_style_local_bg_color(charging_bar, LV_BAR_PART_INDIC, LV_STATE_DEFAULT, LV_COLOR_RED); - lv_label_set_text_static(status, "Battery charging"); - } else if (batteryPercent == 100) { - lv_obj_set_style_local_bg_color(charging_bar, LV_BAR_PART_INDIC, LV_STATE_DEFAULT, LV_COLOR_BLUE); - lv_label_set_text_static(status, "Battery is fully charged"); - } else if (batteryPercent < 10) { - lv_obj_set_style_local_bg_color(charging_bar, LV_BAR_PART_INDIC, LV_STATE_DEFAULT, LV_COLOR_YELLOW); - lv_label_set_text_static(status, "Battery is low"); - } else { - lv_obj_set_style_local_bg_color(charging_bar, LV_BAR_PART_INDIC, LV_STATE_DEFAULT, LV_COLOR_GREEN); - lv_label_set_text_static(status, "Battery discharging"); - } - - lv_label_set_text_fmt(percent, "%02i%%", batteryPercent); - + if (batteryController.IsCharging() and batteryPercent < 100) { + lv_obj_set_style_local_bg_color(charging_bar, LV_BAR_PART_INDIC, LV_STATE_DEFAULT, LV_COLOR_RED); + lv_label_set_text_static(status, "Charging"); + } else if (batteryPercent == 100) { + lv_obj_set_style_local_bg_color(charging_bar, LV_BAR_PART_INDIC, LV_STATE_DEFAULT, LV_COLOR_BLUE); + lv_label_set_text_static(status, "Fully charged"); + } else if (batteryPercent < 10) { + lv_obj_set_style_local_bg_color(charging_bar, LV_BAR_PART_INDIC, LV_STATE_DEFAULT, LV_COLOR_YELLOW); + lv_label_set_text_static(status, "Battery low"); } else { - lv_label_set_text_static(status, "Reading Battery status"); - lv_label_set_text(percent, "--%"); + lv_obj_set_style_local_bg_color(charging_bar, LV_BAR_PART_INDIC, LV_STATE_DEFAULT, LV_COLOR_GREEN); + lv_label_set_text_static(status, "Discharging"); } + lv_label_set_text_fmt(percent, "%02i%%", batteryPercent); + lv_obj_align(status, charging_bar, LV_ALIGN_OUT_BOTTOM_MID, 0, 20); - // hack to not use the flot functions from printf - uint8_t batteryVoltageBytes[2]; - batteryVoltageBytes[1] = static_cast<uint8_t>(batteryVoltage); // truncate whole numbers - batteryVoltageBytes[0] = - static_cast<uint8_t>((batteryVoltage - batteryVoltageBytes[1]) * 100); // remove whole part of flt and shift 2 places over - // - lv_label_set_text_fmt(voltage, "%1i.%02i volts", batteryVoltageBytes[1], batteryVoltageBytes[0]); + lv_label_set_text_fmt(voltage, "%1i.%02i volts", batteryVoltage / 1000, batteryVoltage % 1000 / 10); + lv_bar_set_value(charging_bar, batteryPercent, LV_ANIM_ON); } bool BatteryInfo::Refresh() { - return running; } diff --git a/src/displayapp/screens/BatteryInfo.h b/src/displayapp/screens/BatteryInfo.h index 8805db58..69793244 100644 --- a/src/displayapp/screens/BatteryInfo.h +++ b/src/displayapp/screens/BatteryInfo.h @@ -22,7 +22,6 @@ namespace Pinetime { bool Refresh() override; void UpdateScreen(); - void UpdateAnim(); private: Pinetime::Controllers::Battery& batteryController; @@ -33,11 +32,9 @@ namespace Pinetime { lv_obj_t* status; lv_task_t* taskUpdate; - lv_task_t* taskAnim; - int8_t animation = 0; - int8_t batteryPercent = -1; - float batteryVoltage = 0.0f; + uint8_t batteryPercent = 0; + uint16_t batteryVoltage = 0; }; } } diff --git a/src/displayapp/screens/Clock.cpp b/src/displayapp/screens/Clock.cpp index 05e47a39..86afee0c 100644 --- a/src/displayapp/screens/Clock.cpp +++ b/src/displayapp/screens/Clock.cpp @@ -2,11 +2,6 @@ #include <date/date.h> #include <lvgl/lvgl.h> -#include <cstdio> -#include "BatteryIcon.h" -#include "BleIcon.h" -#include "NotificationIcon.h" -#include "Symbols.h" #include "components/battery/BatteryController.h" #include "components/motion/MotionController.h" #include "components/ble/BleController.h" @@ -14,6 +9,7 @@ #include "../DisplayApp.h" #include "WatchFaceDigital.h" #include "WatchFaceAnalog.h" +#include "PineTimeStyle.h" using namespace Pinetime::Applications::Screens; @@ -41,6 +37,9 @@ Clock::Clock(DisplayApp* app, case 1: return WatchFaceAnalogScreen(); break; + case 2: + return PineTimeStyleScreen(); + break; } return WatchFaceDigitalScreen(); }()} { @@ -76,15 +75,12 @@ std::unique_ptr<Screen> Clock::WatchFaceAnalogScreen() { app, dateTimeController, batteryController, bleController, notificatioManager, settingsController); } -/* -// Examples for more watch faces -std::unique_ptr<Screen> Clock::WatchFaceMinimalScreen() { - return std::make_unique<Screens::WatchFaceMinimal>(app, dateTimeController, batteryController, bleController, notificatioManager, -settingsController); -} - -std::unique_ptr<Screen> Clock::WatchFaceCustomScreen() { - return std::make_unique<Screens::WatchFaceCustom>(app, dateTimeController, batteryController, bleController, notificatioManager, -settingsController); -} -*/
\ No newline at end of file +std::unique_ptr<Screen> Clock::PineTimeStyleScreen() { + return std::make_unique<Screens::PineTimeStyle>(app, + dateTimeController, + batteryController, + bleController, + notificatioManager, + settingsController, + motionController); +}
\ No newline at end of file diff --git a/src/displayapp/screens/Clock.h b/src/displayapp/screens/Clock.h index 174c73b7..7968cced 100644 --- a/src/displayapp/screens/Clock.h +++ b/src/displayapp/screens/Clock.h @@ -9,9 +9,6 @@ #include "components/datetime/DateTimeController.h" namespace Pinetime { - namespace Drivers { - class BMA421; - } namespace Controllers { class Settings; class Battery; @@ -50,10 +47,7 @@ namespace Pinetime { std::unique_ptr<Screen> screen; std::unique_ptr<Screen> WatchFaceDigitalScreen(); std::unique_ptr<Screen> WatchFaceAnalogScreen(); - - // Examples for more watch faces - // std::unique_ptr<Screen> WatchFaceMinimalScreen(); - // std::unique_ptr<Screen> WatchFaceCustomScreen(); + std::unique_ptr<Screen> PineTimeStyleScreen(); }; } } diff --git a/src/displayapp/screens/FirmwareUpdate.cpp b/src/displayapp/screens/FirmwareUpdate.cpp index 4086b152..edb2e49d 100644 --- a/src/displayapp/screens/FirmwareUpdate.cpp +++ b/src/displayapp/screens/FirmwareUpdate.cpp @@ -27,9 +27,10 @@ FirmwareUpdate::FirmwareUpdate(Pinetime::Applications::DisplayApp* app, Pinetime lv_bar_set_value(bar1, 0, LV_ANIM_OFF); percentLabel = lv_label_create(lv_scr_act(), nullptr); - lv_label_set_text(percentLabel, ""); + lv_label_set_text(percentLabel, "Waiting..."); lv_obj_set_auto_realign(percentLabel, true); lv_obj_align(percentLabel, bar1, LV_ALIGN_OUT_TOP_MID, 0, 60); + startTime = xTaskGetTickCount(); } FirmwareUpdate::~FirmwareUpdate() { @@ -40,26 +41,42 @@ bool FirmwareUpdate::Refresh() { switch (bleController.State()) { default: case Pinetime::Controllers::Ble::FirmwareUpdateStates::Idle: + // This condition makes sure that the app is exited if somehow it got + // launched without a firmware update. This should never happen. + if (state != States::Error) { + if (xTaskGetTickCount() - startTime > (60 * 1024)) { + UpdateError(); + state = States::Error; + } + } else if (xTaskGetTickCount() - startTime > (5 * 1024)) { + running = false; + } + break; case Pinetime::Controllers::Ble::FirmwareUpdateStates::Running: if (state != States::Running) state = States::Running; - return DisplayProgression(); + DisplayProgression(); + break; case Pinetime::Controllers::Ble::FirmwareUpdateStates::Validated: if (state != States::Validated) { UpdateValidated(); state = States::Validated; } - return running; + break; case Pinetime::Controllers::Ble::FirmwareUpdateStates::Error: if (state != States::Error) { UpdateError(); state = States::Error; } - return running; + if (xTaskGetTickCount() - startTime > (5 * 1024)) { + running = false; + } + break; } + return running; } -bool FirmwareUpdate::DisplayProgression() const { +void FirmwareUpdate::DisplayProgression() const { float current = bleController.FirmwareUpdateCurrentBytes() / 1024.0f; float total = bleController.FirmwareUpdateTotalBytes() / 1024.0f; int16_t pc = (current / total) * 100.0f; @@ -67,7 +84,6 @@ bool FirmwareUpdate::DisplayProgression() const { lv_label_set_text(percentLabel, percentStr); lv_bar_set_value(bar1, pc, LV_ANIM_OFF); - return running; } void FirmwareUpdate::UpdateValidated() { @@ -78,4 +94,9 @@ void FirmwareUpdate::UpdateValidated() { void FirmwareUpdate::UpdateError() { lv_label_set_recolor(percentLabel, true); lv_label_set_text(percentLabel, "#ff0000 Error!#"); + startTime = xTaskGetTickCount(); +} + +bool FirmwareUpdate::OnButtonPushed() { + return true; } diff --git a/src/displayapp/screens/FirmwareUpdate.h b/src/displayapp/screens/FirmwareUpdate.h index f4d34df0..90c99f4c 100644 --- a/src/displayapp/screens/FirmwareUpdate.h +++ b/src/displayapp/screens/FirmwareUpdate.h @@ -2,6 +2,7 @@ #include "Screen.h" #include <lvgl/src/lv_core/lv_obj.h> +#include "FreeRTOS.h" namespace Pinetime { namespace Controllers { @@ -25,13 +26,17 @@ namespace Pinetime { lv_obj_t* titleLabel; mutable char percentStr[10]; - States state; + States state = States::Idle; - bool DisplayProgression() const; + void DisplayProgression() const; + + bool OnButtonPushed() override; void UpdateValidated(); void UpdateError(); + + TickType_t startTime; }; } } diff --git a/src/displayapp/screens/FirmwareValidation.cpp b/src/displayapp/screens/FirmwareValidation.cpp index ad37a3df..1d05be8d 100644 --- a/src/displayapp/screens/FirmwareValidation.cpp +++ b/src/displayapp/screens/FirmwareValidation.cpp @@ -16,30 +16,18 @@ namespace { FirmwareValidation::FirmwareValidation(Pinetime::Applications::DisplayApp* app, Pinetime::Controllers::FirmwareValidator& validator) : Screen {app}, validator {validator} { - labelVersionInfo = lv_label_create(lv_scr_act(), nullptr); - lv_obj_align(labelVersionInfo, nullptr, LV_ALIGN_IN_TOP_LEFT, 0, 0); - lv_label_set_text(labelVersionInfo, "Version : "); - lv_label_set_align(labelVersionInfo, LV_LABEL_ALIGN_LEFT); - - labelVersionValue = lv_label_create(lv_scr_act(), nullptr); - lv_obj_align(labelVersionValue, labelVersionInfo, LV_ALIGN_OUT_RIGHT_MID, 0, 0); - lv_label_set_recolor(labelVersionValue, true); - sprintf(version, "%ld.%ld.%ld", Version::Major(), Version::Minor(), Version::Patch()); - lv_label_set_text(labelVersionValue, version); - - labelShortRefInfo = lv_label_create(lv_scr_act(), nullptr); - lv_obj_align(labelShortRefInfo, nullptr, LV_ALIGN_IN_TOP_LEFT, 0, 25); - lv_label_set_text(labelShortRefInfo, "ShortRef : "); - lv_label_set_align(labelShortRefInfo, LV_LABEL_ALIGN_LEFT); - - labelShortRefValue = lv_label_create(lv_scr_act(), nullptr); - lv_obj_align(labelShortRefValue, labelShortRefInfo, LV_ALIGN_OUT_RIGHT_MID, 0, 0); - lv_label_set_recolor(labelShortRefValue, true); - sprintf(shortref, "%s", Version::GitCommitHash()); - lv_label_set_text(labelShortRefValue, shortref); + labelVersion = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_text_fmt(labelVersion, + "Version : %d.%d.%d\n" + "ShortRef : %s", + Version::Major(), + Version::Minor(), + Version::Patch(), + Version::GitCommitHash()); + lv_obj_align(labelVersion, nullptr, LV_ALIGN_IN_TOP_LEFT, 0, 0); labelIsValidated = lv_label_create(lv_scr_act(), nullptr); - lv_obj_align(labelIsValidated, nullptr, LV_ALIGN_IN_TOP_LEFT, 0, 50); + lv_obj_align(labelIsValidated, labelVersion, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 0); lv_label_set_recolor(labelIsValidated, true); lv_label_set_long_mode(labelIsValidated, LV_LABEL_LONG_BREAK); lv_obj_set_width(labelIsValidated, 240); diff --git a/src/displayapp/screens/FirmwareValidation.h b/src/displayapp/screens/FirmwareValidation.h index 303c2154..1ef5ba0a 100644 --- a/src/displayapp/screens/FirmwareValidation.h +++ b/src/displayapp/screens/FirmwareValidation.h @@ -23,12 +23,7 @@ namespace Pinetime { private: Pinetime::Controllers::FirmwareValidator& validator; - lv_obj_t* labelVersionInfo; - lv_obj_t* labelVersionValue; - lv_obj_t* labelShortRefInfo; - lv_obj_t* labelShortRefValue; - char version[9]; - char shortref[9]; + lv_obj_t* labelVersion; lv_obj_t* labelIsValidated; lv_obj_t* buttonValidate; lv_obj_t* labelButtonValidate; diff --git a/src/displayapp/screens/FlashLight.cpp b/src/displayapp/screens/FlashLight.cpp index 7db2c6c8..63b2345e 100644 --- a/src/displayapp/screens/FlashLight.cpp +++ b/src/displayapp/screens/FlashLight.cpp @@ -70,5 +70,5 @@ bool FlashLight::Refresh() { } bool FlashLight::OnTouchEvent(Pinetime::Applications::TouchEvents event) { - return true; + return false; } diff --git a/src/displayapp/screens/Label.h b/src/displayapp/screens/Label.h index 62b80bec..834f8c88 100644 --- a/src/displayapp/screens/Label.h +++ b/src/displayapp/screens/Label.h @@ -15,8 +15,6 @@ namespace Pinetime { bool Refresh() override; private: - bool running = true; - lv_obj_t* labelText = nullptr; lv_point_t pageIndicatorBasePoints[2]; lv_point_t pageIndicatorPoints[2]; @@ -25,4 +23,4 @@ namespace Pinetime { }; } } -}
\ No newline at end of file +} diff --git a/src/displayapp/screens/Motion.cpp b/src/displayapp/screens/Motion.cpp index a8bb3c18..43a5575e 100644 --- a/src/displayapp/screens/Motion.cpp +++ b/src/displayapp/screens/Motion.cpp @@ -32,11 +32,10 @@ Motion::Motion(Pinetime::Applications::DisplayApp* app, Controllers::MotionContr lv_label_set_align(label, LV_LABEL_ALIGN_CENTER); lv_obj_align(label, NULL, LV_ALIGN_IN_TOP_MID, 0, 10); lv_label_set_recolor(label, true); - + labelStep = lv_label_create(lv_scr_act(), NULL); lv_obj_align(labelStep, chart, LV_ALIGN_IN_BOTTOM_LEFT, 0, 0); lv_label_set_text(labelStep, "Steps ---"); - } Motion::~Motion() { @@ -50,13 +49,12 @@ bool Motion::Refresh() { lv_label_set_text_fmt(labelStep, "Steps %lu", motionController.NbSteps()); - lv_label_set_text_fmt(label, "X #FF0000 %d# Y #008000 %d# Z #FFFF00 %d#", motionController.X() / 0x10, motionController.Y() / 0x10, motionController.Z() / 0x10); + lv_label_set_text_fmt(label, + "X #FF0000 %d# Y #008000 %d# Z #FFFF00 %d#", + motionController.X() / 0x10, + motionController.Y() / 0x10, + motionController.Z() / 0x10); lv_obj_align(label, NULL, LV_ALIGN_IN_TOP_MID, 0, 10); return running; } - -bool Motion::OnButtonPushed() { - running = false; - return true; -} diff --git a/src/displayapp/screens/Motion.h b/src/displayapp/screens/Motion.h index 132b20ec..7e65197b 100644 --- a/src/displayapp/screens/Motion.h +++ b/src/displayapp/screens/Motion.h @@ -18,7 +18,6 @@ namespace Pinetime { ~Motion() override; bool Refresh() override; - bool OnButtonPushed() override; private: Controllers::MotionController& motionController; @@ -29,10 +28,7 @@ namespace Pinetime { lv_obj_t* label; lv_obj_t* labelStep; - static constexpr uint8_t nbStepsBufferSize = 9; - char nbStepsBuffer[nbStepsBufferSize + 1]; - bool running = true; }; } } -}
\ No newline at end of file +} diff --git a/src/displayapp/screens/Music.cpp b/src/displayapp/screens/Music.cpp index 9f10f508..c8d5e4b0 100644 --- a/src/displayapp/screens/Music.cpp +++ b/src/displayapp/screens/Music.cpp @@ -119,7 +119,6 @@ Music::Music(Pinetime::Applications::DisplayApp* app, Pinetime::Controllers::Mus constexpr int8_t MIDDLE_OFFSET = -25; txtArtist = lv_label_create(lv_scr_act(), nullptr); lv_label_set_long_mode(txtArtist, LV_LABEL_LONG_SROLL_CIRC); - lv_label_set_anim_speed(txtArtist, 1); lv_obj_align(txtArtist, nullptr, LV_ALIGN_IN_LEFT_MID, 12, MIDDLE_OFFSET + 1 * FONT_HEIGHT); lv_label_set_align(txtArtist, LV_ALIGN_IN_LEFT_MID); lv_obj_set_width(txtArtist, LV_HOR_RES - 12); @@ -127,7 +126,6 @@ Music::Music(Pinetime::Applications::DisplayApp* app, Pinetime::Controllers::Mus txtTrack = lv_label_create(lv_scr_act(), nullptr); lv_label_set_long_mode(txtTrack, LV_LABEL_LONG_SROLL_CIRC); - lv_label_set_anim_speed(txtTrack, 1); lv_obj_align(txtTrack, nullptr, LV_ALIGN_IN_LEFT_MID, 12, MIDDLE_OFFSET + 2 * FONT_HEIGHT + LINE_PAD); lv_label_set_align(txtTrack, LV_ALIGN_IN_LEFT_MID); @@ -303,4 +301,4 @@ bool Music::OnTouchEvent(Pinetime::Applications::TouchEvents event) { return true; } } -}
\ No newline at end of file +} diff --git a/src/displayapp/screens/Notifications.cpp b/src/displayapp/screens/Notifications.cpp index 1a1729ea..5c23ed1f 100644 --- a/src/displayapp/screens/Notifications.cpp +++ b/src/displayapp/screens/Notifications.cpp @@ -163,10 +163,10 @@ Notifications::NotificationItem::NotificationItem(const char* title, lv_obj_set_style_local_border_width(container1, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 0); lv_obj_set_pos(container1, 0, 50); - lv_obj_set_width(container1, 240); - lv_obj_set_height(container1, 190); + lv_obj_set_size(container1, LV_HOR_RES, 190); lv_cont_set_layout(container1, LV_LAYOUT_COLUMN_LEFT); + lv_cont_set_fit(container1, LV_FIT_NONE); lv_obj_t* alert_count = lv_label_create(lv_scr_act(), nullptr); lv_label_set_text_fmt(alert_count, "%i/%i", notifNr, notifNb); @@ -184,7 +184,6 @@ Notifications::NotificationItem::NotificationItem(const char* title, } lv_label_set_text(alert_type, title); lv_label_set_long_mode(alert_type, LV_LABEL_LONG_SROLL_CIRC); - lv_label_set_anim_speed(alert_type, 3); lv_obj_set_width(alert_type, 180); lv_obj_align(alert_type, NULL, LV_ALIGN_IN_TOP_LEFT, 0, 16); @@ -198,6 +197,7 @@ Notifications::NotificationItem::NotificationItem(const char* title, lv_label_set_text(alert_subject, msg); } break; case Controllers::NotificationManager::Categories::IncomingCall: { + lv_obj_set_height(container1, 108); lv_obj_t* alert_subject = lv_label_create(container1, nullptr); lv_obj_set_style_local_text_color(alert_subject, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_ORANGE); lv_label_set_long_mode(alert_subject, LV_LABEL_LONG_BREAK); @@ -210,38 +210,29 @@ Notifications::NotificationItem::NotificationItem(const char* title, lv_obj_set_width(alert_caller, LV_HOR_RES - 20); lv_label_set_text(alert_caller, msg); - lv_obj_t* callBtnContainer = lv_cont_create(container1, NULL); - lv_obj_set_width(callBtnContainer, 240); - lv_obj_set_height(callBtnContainer, 90); - lv_cont_set_layout(callBtnContainer, LV_LAYOUT_ROW_MID); - - lv_obj_set_style_local_bg_color(callBtnContainer, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x222222)); - lv_obj_set_style_local_pad_all(callBtnContainer, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 0); - lv_obj_set_style_local_margin_top(callBtnContainer, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 40); - lv_obj_set_style_local_margin_left(callBtnContainer, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, -8); - lv_obj_set_style_local_pad_inner(callBtnContainer, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 5); - lv_obj_set_style_local_border_width(callBtnContainer, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 0); - - bt_accept = lv_btn_create(callBtnContainer, nullptr); + bt_accept = lv_btn_create(lv_scr_act(), nullptr); bt_accept->user_data = this; lv_obj_set_event_cb(bt_accept, AcceptIncomingCallEventHandler); - lv_obj_set_size(bt_accept, (LV_HOR_RES / 3) - 5, 80); + lv_obj_set_size(bt_accept, 76, 76); + lv_obj_align(bt_accept, NULL, LV_ALIGN_IN_BOTTOM_LEFT, 0, 0); label_accept = lv_label_create(bt_accept, nullptr); lv_label_set_text(label_accept, Symbols::phone); lv_obj_set_style_local_bg_color(bt_accept, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GREEN); - bt_reject = lv_btn_create(callBtnContainer, nullptr); + bt_reject = lv_btn_create(lv_scr_act(), nullptr); bt_reject->user_data = this; lv_obj_set_event_cb(bt_reject, RejectIncomingCallEventHandler); - lv_obj_set_size(bt_reject, (LV_HOR_RES / 3) - 5, 80); + lv_obj_set_size(bt_reject, 76, 76); + lv_obj_align(bt_reject, NULL, LV_ALIGN_IN_BOTTOM_MID, 0, 0); label_reject = lv_label_create(bt_reject, nullptr); lv_label_set_text(label_reject, Symbols::phoneSlash); lv_obj_set_style_local_bg_color(bt_reject, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_RED); - bt_mute = lv_btn_create(callBtnContainer, nullptr); + bt_mute = lv_btn_create(lv_scr_act(), nullptr); bt_mute->user_data = this; lv_obj_set_event_cb(bt_mute, MuteIncomingCallEventHandler); - lv_obj_set_size(bt_mute, (LV_HOR_RES / 3) - 5, 80); + lv_obj_set_size(bt_mute, 76, 76); + lv_obj_align(bt_mute, NULL, LV_ALIGN_IN_BOTTOM_RIGHT, 0, 0); label_mute = lv_label_create(bt_mute, nullptr); lv_label_set_text(label_mute, Symbols::volumMute); lv_obj_set_style_local_bg_color(bt_mute, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GRAY); diff --git a/src/displayapp/screens/Paddle.cpp b/src/displayapp/screens/Paddle.cpp index 161f175b..5a939ac7 100644 --- a/src/displayapp/screens/Paddle.cpp +++ b/src/displayapp/screens/Paddle.cpp @@ -4,98 +4,31 @@ using namespace Pinetime::Applications::Screens; -namespace { - const uint8_t paddle_map[] = { - 0xfc, 0xfe, 0xfc, 0xff, /*Color of index 0*/ - 0xff, 0xff, 0xff, 0xff, /*Color of index 1*/ - - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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 uint8_t ball_map[] = { - 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, - 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6f, 0xed, 0x6f, 0xed, - 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, - 0x6f, 0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6f, 0xed, - 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x6f, 0xed, 0x6f, 0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6f, 0xed, 0x6f, 0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6f, 0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6f, 0xed, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6f, 0xed, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x6f, 0xed, 0x6f, 0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, - 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, - 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, - 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, - 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, - }; -} - Paddle::Paddle(Pinetime::Applications::DisplayApp* app, Pinetime::Components::LittleVgl& lvgl) : Screen(app), lvgl {lvgl} { app->SetTouchMode(DisplayApp::TouchModes::Polling); + background = lv_obj_create(lv_scr_act(), nullptr); + lv_obj_set_size(background, LV_HOR_RES + 1, LV_VER_RES); + lv_obj_set_pos(background, -1, 0); + lv_obj_set_style_local_radius(background, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 0); + lv_obj_set_style_local_bg_color(background, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK); + lv_obj_set_style_local_border_color(background, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE); + lv_obj_set_style_local_border_width(background, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 1); + points = lv_label_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_text_font(points, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_42); lv_label_set_text(points, "0000"); - lv_obj_set_style_local_text_color(points, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x444444)); - lv_obj_align(points, lv_scr_act(), LV_ALIGN_IN_TOP_MID, 0, 0); + lv_obj_align(points, lv_scr_act(), LV_ALIGN_IN_TOP_MID, 0, 10); - paddle.header.always_zero = 0; - paddle.header.w = 4; - paddle.header.h = 60; - paddle.data_size = 68; - paddle.header.cf = LV_IMG_CF_INDEXED_1BIT; - paddle.data = paddle_map; - paddle_image = lv_img_create(lv_scr_act(), nullptr); - lv_img_set_src(paddle_image, &paddle); + paddle = lv_obj_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_bg_color(paddle, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE); + lv_obj_set_style_local_radius(paddle, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 0); + lv_obj_set_size(paddle, 4, 60); - ball.header.always_zero = 0; - ball.header.w = 24; - ball.header.h = 24; - ball.data_size = 24 * 24 * LV_COLOR_SIZE / 8; - ball.header.cf = LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED; - ball.data = ball_map; - ball_image = lv_img_create(lv_scr_act(), nullptr); - lv_img_set_src(ball_image, &ball); + ball = lv_obj_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_bg_color(ball, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE); + lv_obj_set_style_local_radius(ball, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_RADIUS_CIRCLE); + lv_obj_set_size(ball, ballSize, ballSize); } Paddle::~Paddle() { @@ -105,41 +38,37 @@ Paddle::~Paddle() { } bool Paddle::Refresh() { - if ((counter++ % 5) == 0) { - counter = 0; - - ballX += dx; - ballY += dy; + ballX += dx; + ballY += dy; - lv_obj_set_pos(ball_image, ballX, ballY); + lv_obj_set_pos(ball, ballX, ballY); - // checks if it has touched the sides (floor and ceiling) - if (ballY <= 0 || ballY >= 215) { - dy *= -1; - } + // checks if it has touched the sides (floor and ceiling) + if (ballY <= 1 || ballY >= LV_VER_RES - ballSize - 2) { + dy *= -1; + } - // checks if it has touched the side (left side) - if (ballX >= 215) { - dx *= -1; - } + // checks if it has touched the side (left side) + if (ballX >= LV_VER_RES - ballSize - 1) { + dx *= -1; + } - // checks if it is in the position of the paddle - if (ballY <= (paddleBottomY + 16) && ballY >= (paddleTopY - 8)) { - if (ballX >= 0 && ballX < 4) { - lv_obj_set_pos(ball_image, 5, ballY); + // checks if it is in the position of the paddle + if (dx < 0 && ballX <= 4) { + if (ballX >= -ballSize / 4) { + if (ballY <= (paddlePos + 30 - ballSize / 4) && ballY >= (paddlePos - 30 - ballSize + ballSize / 4)) { dx *= -1; score++; } } - // checks if it has gone behind the paddle - else if (ballX <= -40) { - ballX = 107; - ballY = 107; + else if (ballX <= -ballSize * 2) { + ballX = (LV_HOR_RES - ballSize) / 2; + ballY = (LV_VER_RES - ballSize) / 2; score = 0; } - lv_label_set_text_fmt(points, "%04d", score); } + lv_label_set_text_fmt(points, "%04d", score); return running; } @@ -148,11 +77,8 @@ bool Paddle::OnTouchEvent(Pinetime::Applications::TouchEvents event) { } bool Paddle::OnTouchEvent(uint16_t x, uint16_t y) { - lv_obj_set_pos( - paddle_image, - 0, - y - 30); // sets the center paddle pos. (30px offset) with the the y_coordinate of the finger and defaults the x_coordinate to 0 - paddleTopY = y - 30; // refreshes the upper extreme of the paddle - paddleBottomY = y + 30; // refreshes the lower extreme of the paddle + // sets the center paddle pos. (30px offset) with the the y_coordinate of the finger + lv_obj_set_pos(paddle, 0, y - 30); + paddlePos = y; return true; } diff --git a/src/displayapp/screens/Paddle.h b/src/displayapp/screens/Paddle.h index e133244f..30ab8f94 100644 --- a/src/displayapp/screens/Paddle.h +++ b/src/displayapp/screens/Paddle.h @@ -24,24 +24,22 @@ namespace Pinetime { private: Pinetime::Components::LittleVgl& lvgl; - int paddleBottomY = 90; // bottom extreme of the paddle - int paddleTopY = 150; // top extreme of the paddle + const uint8_t ballSize = 16; - int ballX = 107; // Initial x_coordinate for the ball (12px offset from the center to counteract the ball's 24px size) - int ballY = 107; // Initial y_coordinate for the ball + uint16_t paddlePos = 30; // Paddle center - int dx = 2; // Velocity of the ball in the x_coordinate - int dy = 3; // Velocity of the ball in the y_coordinate + int16_t ballX = (LV_HOR_RES - ballSize) / 2; + int16_t ballY = (LV_VER_RES - ballSize) / 2; - int counter = 0; // init Frame refresh limit counter - int score = 0; + int8_t dx = 2; // Velocity of the ball in the x_coordinate + int8_t dy = 3; // Velocity of the ball in the y_coordinate - lv_img_dsc_t paddle; - lv_img_dsc_t ball; + uint16_t score = 0; lv_obj_t* points; - lv_obj_t* paddle_image; // pointer to paddle image - lv_obj_t* ball_image; // pointer to ball image + lv_obj_t* paddle; + lv_obj_t* ball; + lv_obj_t* background; }; } } diff --git a/src/displayapp/screens/PineTimeStyle.cpp b/src/displayapp/screens/PineTimeStyle.cpp new file mode 100644 index 00000000..98fd976c --- /dev/null +++ b/src/displayapp/screens/PineTimeStyle.cpp @@ -0,0 +1,308 @@ +/* + * This file is part of the Infinitime distribution (https://github.com/JF002/Infinitime). + * Copyright (c) 2021 Kieran Cawthray. + * + * 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, version 3. + * + * 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 <http://www.gnu.org/licenses/>. + * + * PineTimeStyle watchface for Infinitime created by Kieran Cawthray + * Based on WatchFaceDigital + * Style/layout copied from TimeStyle for Pebble by Dan Tilden (github.com/tilden) + */ + +#include "PineTimeStyle.h" +#include <date/date.h> +#include <lvgl/lvgl.h> +#include <cstdio> +#include "BatteryIcon.h" +#include "BleIcon.h" +#include "NotificationIcon.h" +#include "Symbols.h" +#include "components/battery/BatteryController.h" +#include "components/ble/BleController.h" +#include "components/ble/NotificationManager.h" +#include "components/motion/MotionController.h" +#include "components/settings/Settings.h" +#include "../DisplayApp.h" + +using namespace Pinetime::Applications::Screens; + +PineTimeStyle::PineTimeStyle(DisplayApp* app, + Controllers::DateTime& dateTimeController, + Controllers::Battery& batteryController, + Controllers::Ble& bleController, + Controllers::NotificationManager& notificatioManager, + Controllers::Settings& settingsController, + Controllers::MotionController& motionController) + : Screen(app), + currentDateTime {{}}, + dateTimeController {dateTimeController}, + batteryController {batteryController}, + bleController {bleController}, + notificatioManager {notificatioManager}, + settingsController {settingsController}, + motionController {motionController} { + /* This sets the watchface number to return to after leaving the menu */ + settingsController.SetClockFace(2); + + displayedChar[0] = 0; + displayedChar[1] = 0; + displayedChar[2] = 0; + displayedChar[3] = 0; + displayedChar[4] = 0; + + /* Create a 200px wide background rectangle */ + timebar = lv_obj_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_bg_color(timebar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000)); + lv_obj_set_style_local_radius(timebar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 0); + lv_obj_set_size(timebar, 200, 240); + lv_obj_align(timebar, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, 5, 0); + + /* Display the time */ + timeDD1 = lv_label_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_text_font(timeDD1, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &open_sans_light); + lv_obj_set_style_local_text_color(timeDD1, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x008080)); + lv_label_set_text(timeDD1, "12"); + lv_obj_align(timeDD1, timebar, LV_ALIGN_IN_TOP_MID, 5, 5); + + timeDD2 = lv_label_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_text_font(timeDD2, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &open_sans_light); + lv_obj_set_style_local_text_color(timeDD2, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x008080)); + lv_label_set_text(timeDD2, "34"); + lv_obj_align(timeDD2, timebar, LV_ALIGN_IN_BOTTOM_MID, 5, -5); + + timeAMPM = lv_label_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_text_color(timeAMPM, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x008080)); + lv_obj_set_style_local_text_line_space(timeAMPM, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, -3); + lv_label_set_text(timeAMPM, ""); + lv_obj_align(timeAMPM, timebar, LV_ALIGN_IN_BOTTOM_LEFT, 2, -20); + + /* Create a 40px wide bar down the right side of the screen */ + sidebar = lv_obj_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_bg_color(sidebar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x008080)); + lv_obj_set_style_local_radius(sidebar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 0); + lv_obj_set_size(sidebar, 40, 240); + lv_obj_align(sidebar, lv_scr_act(), LV_ALIGN_IN_TOP_RIGHT, 0, 0); + + /* Display icons */ + batteryIcon = lv_label_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_text_color(batteryIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000)); + lv_label_set_text(batteryIcon, Symbols::batteryFull); + lv_obj_align(batteryIcon, sidebar, LV_ALIGN_IN_TOP_MID, 0, 2); + + batteryPlug = lv_label_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_text_color(batteryPlug, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000)); + lv_obj_align(batteryPlug, sidebar, LV_ALIGN_IN_TOP_MID, 0, 2); + + bleIcon = lv_label_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_text_color(bleIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000)); + lv_obj_align(bleIcon, sidebar, LV_ALIGN_IN_TOP_MID, 0, 25); + + notificationIcon = lv_label_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_text_color(notificationIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000)); + lv_obj_align(notificationIcon, sidebar, LV_ALIGN_IN_TOP_MID, 0, 40); + + /* Calendar icon */ + calendarOuter = lv_obj_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_bg_color(calendarOuter, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000)); + lv_obj_set_style_local_radius(calendarOuter, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 0); + lv_obj_set_size(calendarOuter, 34, 34); + lv_obj_align(calendarOuter, sidebar, LV_ALIGN_CENTER, 0, 0); + + calendarInner = lv_obj_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_bg_color(calendarInner, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0xffffff)); + lv_obj_set_style_local_radius(calendarInner, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 0); + lv_obj_set_size(calendarInner, 27, 27); + lv_obj_align(calendarInner, calendarOuter, LV_ALIGN_CENTER, 0, 0); + + calendarBar1 = lv_obj_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_bg_color(calendarBar1, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000)); + lv_obj_set_style_local_radius(calendarBar1, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 0); + lv_obj_set_size(calendarBar1, 3, 12); + lv_obj_align(calendarBar1, calendarOuter, LV_ALIGN_IN_TOP_MID, -6, -3); + + calendarBar2 = lv_obj_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_bg_color(calendarBar2, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000)); + lv_obj_set_style_local_radius(calendarBar2, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 0); + lv_obj_set_size(calendarBar2, 3, 12); + lv_obj_align(calendarBar2, calendarOuter, LV_ALIGN_IN_TOP_MID, 6, -3); + + calendarCrossBar1 = lv_obj_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_bg_color(calendarCrossBar1, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000)); + lv_obj_set_style_local_radius(calendarCrossBar1, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 0); + lv_obj_set_size(calendarCrossBar1, 8, 3); + lv_obj_align(calendarCrossBar1, calendarBar1, LV_ALIGN_IN_BOTTOM_MID, 0, 0); + + calendarCrossBar2 = lv_obj_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_bg_color(calendarCrossBar2, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000)); + lv_obj_set_style_local_radius(calendarCrossBar2, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 0); + lv_obj_set_size(calendarCrossBar2, 8, 3); + lv_obj_align(calendarCrossBar2, calendarBar2, LV_ALIGN_IN_BOTTOM_MID, 0, 0); + + /* Display date */ + dateDayOfWeek = lv_label_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_text_color(dateDayOfWeek, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000)); + lv_label_set_text(dateDayOfWeek, "THU"); + lv_obj_align(dateDayOfWeek, sidebar, LV_ALIGN_CENTER, 0, -34); + + dateDay = lv_label_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_text_color(dateDay, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000)); + lv_label_set_text(dateDay, "25"); + lv_obj_align(dateDay, sidebar, LV_ALIGN_CENTER, 0, 3); + + dateMonth = lv_label_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_text_color(dateMonth, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000)); + lv_label_set_text(dateMonth, "MAR"); + lv_obj_align(dateMonth, sidebar, LV_ALIGN_CENTER, 0, 32); + + // Step count gauge + needle_colors[0] = LV_COLOR_WHITE; + stepGauge = lv_gauge_create(lv_scr_act(), nullptr); + lv_gauge_set_needle_count(stepGauge, 1, needle_colors); + lv_obj_set_size(stepGauge, 40, 40); + lv_obj_align(stepGauge, sidebar, LV_ALIGN_IN_BOTTOM_MID, 0, 0); + lv_gauge_set_scale(stepGauge, 360, 11, 0); + lv_gauge_set_angle_offset(stepGauge, 180); + lv_gauge_set_critical_value(stepGauge, 100); + lv_gauge_set_range(stepGauge, 0, 100); + lv_gauge_set_value(stepGauge, 0, 0); + + lv_obj_set_style_local_pad_right(stepGauge, LV_GAUGE_PART_MAIN, LV_STATE_DEFAULT, 3); + lv_obj_set_style_local_pad_left(stepGauge, LV_GAUGE_PART_MAIN, LV_STATE_DEFAULT, 3); + lv_obj_set_style_local_pad_bottom(stepGauge, LV_GAUGE_PART_MAIN, LV_STATE_DEFAULT, 3); + lv_obj_set_style_local_line_opa(stepGauge, LV_GAUGE_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_COVER); + lv_obj_set_style_local_scale_width(stepGauge, LV_GAUGE_PART_MAIN, LV_STATE_DEFAULT, 4); + lv_obj_set_style_local_line_width(stepGauge, LV_GAUGE_PART_MAIN, LV_STATE_DEFAULT, 4); + lv_obj_set_style_local_line_color(stepGauge, LV_GAUGE_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK); + lv_obj_set_style_local_line_opa(stepGauge, LV_GAUGE_PART_NEEDLE, LV_STATE_DEFAULT, LV_OPA_COVER); + lv_obj_set_style_local_line_width(stepGauge, LV_GAUGE_PART_NEEDLE, LV_STATE_DEFAULT, 4); + lv_obj_set_style_local_pad_inner(stepGauge, LV_GAUGE_PART_NEEDLE, LV_STATE_DEFAULT, 4); + + backgroundLabel = lv_label_create(lv_scr_act(), nullptr); + lv_obj_set_click(backgroundLabel, true); + lv_label_set_long_mode(backgroundLabel, LV_LABEL_LONG_CROP); + lv_obj_set_size(backgroundLabel, 240, 240); + lv_obj_set_pos(backgroundLabel, 0, 0); + lv_label_set_text(backgroundLabel, ""); +} + +PineTimeStyle::~PineTimeStyle() { + lv_obj_clean(lv_scr_act()); +} + +bool PineTimeStyle::Refresh() { + batteryPercentRemaining = batteryController.PercentRemaining(); + if (batteryPercentRemaining.IsUpdated()) { + auto batteryPercent = batteryPercentRemaining.Get(); + if (batteryController.IsCharging()) { + auto isCharging = batteryController.IsCharging() || batteryController.IsPowerPresent(); + lv_label_set_text(batteryPlug, BatteryIcon::GetPlugIcon(isCharging)); + lv_obj_realign(batteryPlug); + lv_label_set_text(batteryIcon, ""); + } else { + lv_label_set_text(batteryIcon, BatteryIcon::GetBatteryIcon(batteryPercent)); + lv_label_set_text(batteryPlug, ""); + } + } + + bleState = bleController.IsConnected(); + if (bleState.IsUpdated()) { + lv_label_set_text(bleIcon, BleIcon::GetIcon(bleState.Get())); + lv_obj_realign(bleIcon); + } + + notificationState = notificatioManager.AreNewNotificationsAvailable(); + if (notificationState.IsUpdated()) { + lv_label_set_text(notificationIcon, NotificationIcon::GetIcon(notificationState.Get())); + lv_obj_realign(notificationIcon); + } + + currentDateTime = dateTimeController.CurrentDateTime(); + if (currentDateTime.IsUpdated()) { + auto newDateTime = currentDateTime.Get(); + + auto dp = date::floor<date::days>(newDateTime); + auto time = date::make_time(newDateTime - dp); + auto yearMonthDay = date::year_month_day(dp); + + auto year = static_cast<int>(yearMonthDay.year()); + auto month = static_cast<Pinetime::Controllers::DateTime::Months>(static_cast<unsigned>(yearMonthDay.month())); + auto day = static_cast<unsigned>(yearMonthDay.day()); + auto dayOfWeek = static_cast<Pinetime::Controllers::DateTime::Days>(date::weekday(yearMonthDay).iso_encoding()); + + int hour = time.hours().count(); + auto minute = time.minutes().count(); + + char minutesChar[3]; + sprintf(minutesChar, "%02d", static_cast<int>(minute)); + + char hoursChar[3]; + char ampmChar[5]; + if (settingsController.GetClockType() == Controllers::Settings::ClockType::H24) { + sprintf(hoursChar, "%02d", hour); + } else { + if (hour == 0 && hour != 12) { + hour = 12; + sprintf(ampmChar, "A\nM"); + } else if (hour == 12 && hour != 0) { + hour = 12; + sprintf(ampmChar, "P\nM"); + } else if (hour < 12 && hour != 0) { + sprintf(ampmChar, "A\nM"); + } else if (hour > 12 && hour != 0) { + hour = hour - 12; + sprintf(ampmChar, "P\nM"); + } + sprintf(hoursChar, "%02d", hour); + } + + if (hoursChar[0] != displayedChar[0] or hoursChar[1] != displayedChar[1] or minutesChar[0] != displayedChar[2] or + minutesChar[1] != displayedChar[3]) { + displayedChar[0] = hoursChar[0]; + displayedChar[1] = hoursChar[1]; + displayedChar[2] = minutesChar[0]; + displayedChar[3] = minutesChar[1]; + + if (settingsController.GetClockType() == Controllers::Settings::ClockType::H12) { + lv_label_set_text(timeAMPM, ampmChar); + } + + lv_label_set_text_fmt(timeDD1, "%s", hoursChar); + lv_label_set_text_fmt(timeDD2, "%s", minutesChar); + } + + if ((year != currentYear) || (month != currentMonth) || (dayOfWeek != currentDayOfWeek) || (day != currentDay)) { + lv_label_set_text_fmt(dateDayOfWeek, "%s", dateTimeController.DayOfWeekShortToString()); + lv_label_set_text_fmt(dateDay, "%d", day); + lv_obj_realign(dateDay); + lv_label_set_text_fmt(dateMonth, "%s", dateTimeController.MonthShortToString()); + + currentYear = year; + currentMonth = month; + currentDayOfWeek = dayOfWeek; + currentDay = day; + } + } + + stepCount = motionController.NbSteps(); + motionSensorOk = motionController.IsSensorOk(); + if (stepCount.IsUpdated() || motionSensorOk.IsUpdated()) { + lv_gauge_set_value(stepGauge, 0, (stepCount.Get() / (settingsController.GetStepsGoal() / 100))); + lv_obj_realign(stepGauge); + if (stepCount.Get() > settingsController.GetStepsGoal()) { + lv_obj_set_style_local_line_color(stepGauge, LV_GAUGE_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE); + lv_obj_set_style_local_scale_grad_color(stepGauge, LV_GAUGE_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE); + } + } + + return running; +}
\ No newline at end of file diff --git a/src/displayapp/screens/PineTimeStyle.h b/src/displayapp/screens/PineTimeStyle.h new file mode 100644 index 00000000..f4cd28e4 --- /dev/null +++ b/src/displayapp/screens/PineTimeStyle.h @@ -0,0 +1,81 @@ +#pragma once + +#include <lvgl/src/lv_core/lv_obj.h> +#include <chrono> +#include <cstdint> +#include <memory> +#include "Screen.h" +#include "ScreenList.h" +#include "components/datetime/DateTimeController.h" + +namespace Pinetime { + namespace Controllers { + class Settings; + class Battery; + class Ble; + class NotificationManager; + class HeartRateController; + } + + namespace Applications { + namespace Screens { + class PineTimeStyle : public Screen { + public: + PineTimeStyle(DisplayApp* app, + Controllers::DateTime& dateTimeController, + Controllers::Battery& batteryController, + Controllers::Ble& bleController, + Controllers::NotificationManager& notificatioManager, + Controllers::Settings& settingsController, + Controllers::MotionController& motionController); + ~PineTimeStyle() override; + + bool Refresh() override; + + private: + char displayedChar[5]; + + uint16_t currentYear = 1970; + Pinetime::Controllers::DateTime::Months currentMonth = Pinetime::Controllers::DateTime::Months::Unknown; + Pinetime::Controllers::DateTime::Days currentDayOfWeek = Pinetime::Controllers::DateTime::Days::Unknown; + uint8_t currentDay = 0; + + DirtyValue<uint8_t> batteryPercentRemaining {}; + DirtyValue<bool> bleState {}; + DirtyValue<std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds>> currentDateTime {}; + DirtyValue<bool> motionSensorOk {}; + DirtyValue<uint32_t> stepCount {}; + DirtyValue<bool> notificationState {}; + + lv_obj_t* timebar; + lv_obj_t* sidebar; + lv_obj_t* timeDD1; + lv_obj_t* timeDD2; + lv_obj_t* timeAMPM; + lv_obj_t* dateDayOfWeek; + lv_obj_t* dateDay; + lv_obj_t* dateMonth; + lv_obj_t* backgroundLabel; + lv_obj_t* batteryIcon; + lv_obj_t* bleIcon; + lv_obj_t* batteryPlug; + lv_obj_t* calendarOuter; + lv_obj_t* calendarInner; + lv_obj_t* calendarBar1; + lv_obj_t* calendarBar2; + lv_obj_t* calendarCrossBar1; + lv_obj_t* calendarCrossBar2; + lv_obj_t* notificationIcon; + lv_obj_t* stepGauge; + lv_color_t needle_colors[1]; + + Controllers::DateTime& dateTimeController; + Controllers::Battery& batteryController; + Controllers::Ble& bleController; + Controllers::NotificationManager& notificatioManager; + Controllers::Settings& settingsController; + Controllers::MotionController& motionController; + }; + } + } +} diff --git a/src/displayapp/screens/Screen.h b/src/displayapp/screens/Screen.h index 8e49c9de..6c9110c6 100644 --- a/src/displayapp/screens/Screen.h +++ b/src/displayapp/screens/Screen.h @@ -13,8 +13,12 @@ namespace Pinetime { DirtyValue() = default; // Use NSDMI explicit DirtyValue(T const& v) : value {v} { } // Use MIL and const-lvalue-ref - bool IsUpdated() const { - return isUpdated; + bool IsUpdated() { + if (this->isUpdated) { + this->isUpdated = false; + return true; + } + return false; } T const& Get() { this->isUpdated = false; diff --git a/src/displayapp/screens/Steps.cpp b/src/displayapp/screens/Steps.cpp index b485c975..d72e8333 100644 --- a/src/displayapp/screens/Steps.cpp +++ b/src/displayapp/screens/Steps.cpp @@ -5,20 +5,17 @@ using namespace Pinetime::Applications::Screens; -Steps::Steps( - Pinetime::Applications::DisplayApp *app, - Controllers::MotionController& motionController, - Controllers::Settings &settingsController) - : Screen(app), - motionController{motionController}, - settingsController{settingsController} { +Steps::Steps(Pinetime::Applications::DisplayApp* app, + Controllers::MotionController& motionController, + Controllers::Settings& settingsController) + : Screen(app), motionController {motionController}, settingsController {settingsController} { stepsArc = lv_arc_create(lv_scr_act(), nullptr); - lv_obj_set_style_local_bg_opa(stepsArc, LV_ARC_PART_BG, LV_STATE_DEFAULT, LV_OPA_0); - lv_obj_set_style_local_border_width(stepsArc, LV_ARC_PART_BG, LV_STATE_DEFAULT, 2); - lv_obj_set_style_local_radius(stepsArc, LV_ARC_PART_BG, LV_STATE_DEFAULT, 0); - lv_obj_set_style_local_line_color(stepsArc, LV_ARC_PART_INDIC, LV_STATE_DEFAULT, lv_color_hex(0x0000FF)); + lv_obj_set_style_local_bg_opa(stepsArc, LV_ARC_PART_BG, LV_STATE_DEFAULT, LV_OPA_0); + lv_obj_set_style_local_border_width(stepsArc, LV_ARC_PART_BG, LV_STATE_DEFAULT, 2); + lv_obj_set_style_local_radius(stepsArc, LV_ARC_PART_BG, LV_STATE_DEFAULT, 0); + lv_obj_set_style_local_line_color(stepsArc, LV_ARC_PART_INDIC, LV_STATE_DEFAULT, lv_color_hex(0x0000FF)); lv_arc_set_end_angle(stepsArc, 200); lv_obj_set_size(stepsArc, 220, 220); lv_arc_set_range(stepsArc, 0, 500); @@ -30,27 +27,26 @@ Steps::Steps( lSteps = lv_label_create(lv_scr_act(), nullptr); lv_obj_set_style_local_text_color(lSteps, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x00FF00)); - lv_obj_set_style_local_text_font(lSteps, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_42); - lv_label_set_text_fmt(lSteps, "%li", stepsCount); + lv_obj_set_style_local_text_font(lSteps, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_42); + lv_label_set_text_fmt(lSteps, "%li", stepsCount); lv_obj_align(lSteps, nullptr, LV_ALIGN_CENTER, 0, -20); - lv_obj_t * lstepsL = lv_label_create(lv_scr_act(), nullptr); + lv_obj_t* lstepsL = lv_label_create(lv_scr_act(), nullptr); lv_obj_set_style_local_text_color(lstepsL, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x111111)); - lv_label_set_text_static(lstepsL, "Steps"); + lv_label_set_text_static(lstepsL, "Steps"); lv_obj_align(lstepsL, lSteps, LV_ALIGN_OUT_BOTTOM_MID, 0, 10); - lv_obj_t * lstepsGoal = lv_label_create(lv_scr_act(), nullptr); + lv_obj_t* lstepsGoal = lv_label_create(lv_scr_act(), nullptr); lv_obj_set_style_local_text_color(lstepsGoal, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_CYAN); - lv_label_set_text_fmt(lstepsGoal,"Goal\n%i", settingsController.GetStepsGoal()); + lv_label_set_text_fmt(lstepsGoal, "Goal\n%lu", settingsController.GetStepsGoal()); lv_label_set_align(lstepsGoal, LV_LABEL_ALIGN_CENTER); lv_obj_align(lstepsGoal, lSteps, LV_ALIGN_OUT_BOTTOM_MID, 0, 60); - lv_obj_t * backgroundLabel = lv_label_create(lv_scr_act(), nullptr); + lv_obj_t* backgroundLabel = lv_label_create(lv_scr_act(), nullptr); lv_label_set_long_mode(backgroundLabel, LV_LABEL_LONG_CROP); lv_obj_set_size(backgroundLabel, 240, 240); lv_obj_set_pos(backgroundLabel, 0, 0); lv_label_set_text_static(backgroundLabel, ""); - } Steps::~Steps() { @@ -58,15 +54,13 @@ Steps::~Steps() { } bool Steps::Refresh() { - + stepsCount = motionController.NbSteps(); - lv_label_set_text_fmt(lSteps,"%li", stepsCount); + lv_label_set_text_fmt(lSteps, "%li", stepsCount); lv_obj_align(lSteps, nullptr, LV_ALIGN_CENTER, 0, -20); - + lv_arc_set_value(stepsArc, int16_t(500 * stepsCount / settingsController.GetStepsGoal())); return running; } - - diff --git a/src/displayapp/screens/StopWatch.cpp b/src/displayapp/screens/StopWatch.cpp index 7c128d1b..f4db5d6e 100644 --- a/src/displayapp/screens/StopWatch.cpp +++ b/src/displayapp/screens/StopWatch.cpp @@ -45,17 +45,16 @@ static void stop_lap_event_handler(lv_obj_t* obj, lv_event_t event) { stopWatch->stopLapBtnEventHandler(event); } -StopWatch::StopWatch(DisplayApp* app) +StopWatch::StopWatch(DisplayApp* app, System::SystemTask& systemTask) : Screen(app), + systemTask {systemTask}, running {true}, currentState {States::Init}, - currentEvent {Events::Stop}, startTime {}, oldTimeElapsed {}, currentTimeSeparated {}, lapBuffer {}, - lapNr {}, - lapPressed {false} { + lapNr {} { time = lv_label_create(lv_scr_act(), nullptr); lv_obj_set_style_local_text_font(time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_76); @@ -105,128 +104,100 @@ StopWatch::StopWatch(DisplayApp* app) } StopWatch::~StopWatch() { + systemTask.PushMessage(Pinetime::System::Messages::EnableSleeping); lv_obj_clean(lv_scr_act()); } +void StopWatch::reset() { + currentState = States::Init; + oldTimeElapsed = 0; + lv_obj_set_style_local_text_color(time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GRAY); + lv_obj_set_style_local_text_color(msecTime, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GRAY); + + lv_label_set_text(time, "00:00"); + lv_label_set_text(msecTime, "00"); + + lv_label_set_text(lapOneText, ""); + lv_label_set_text(lapTwoText, ""); + lapBuffer.clearBuffer(); + lapNr = 0; + lv_obj_set_state(btnStopLap, LV_STATE_DISABLED); + lv_obj_set_state(txtStopLap, LV_STATE_DISABLED); +} + +void StopWatch::start() { + lv_obj_set_state(btnStopLap, LV_STATE_DEFAULT); + lv_obj_set_state(txtStopLap, LV_STATE_DEFAULT); + lv_obj_set_style_local_text_color(time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GREEN); + lv_obj_set_style_local_text_color(msecTime, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GREEN); + lv_label_set_text(txtPlayPause, Symbols::pause); + lv_label_set_text(txtStopLap, Symbols::lapsFlag); + startTime = xTaskGetTickCount(); + currentState = States::Running; + systemTask.PushMessage(Pinetime::System::Messages::DisableSleeping); +} + +void StopWatch::pause() { + startTime = 0; + // Store the current time elapsed in cache + oldTimeElapsed += timeElapsed; + currentState = States::Halted; + lv_label_set_text(txtPlayPause, Symbols::play); + lv_label_set_text(txtStopLap, Symbols::stop); + lv_obj_set_style_local_text_color(time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_YELLOW); + lv_obj_set_style_local_text_color(msecTime, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_YELLOW); + systemTask.PushMessage(Pinetime::System::Messages::EnableSleeping); +} + bool StopWatch::Refresh() { - // @startuml CHIP8_state - // State "Init" as init - // State "Running" as run - // State "Halted" as halt - - // [*] --> init - // init -> run : press play - // run -> run : press lap - // run --> halt : press pause - // halt --> run : press play - // halt --> init : press stop - // @enduml - // Copy paste the above plantuml text to visualize the state diagram - switch (currentState) { - // Init state when an user first opens the app - // and when a stop/reset button is pressed - case States::Init: { - // The initial default value - lv_label_set_text(time, "00:00"); - lv_label_set_text(msecTime, "00"); - - lv_label_set_text(lapOneText, ""); - lv_label_set_text(lapTwoText, ""); - lapBuffer.clearBuffer(); - lapNr = 0; - - if (currentEvent == Events::Play) { - lv_obj_set_state(btnStopLap, LV_STATE_DEFAULT); - lv_obj_set_state(txtStopLap, LV_STATE_DEFAULT); - - startTime = xTaskGetTickCount(); - currentState = States::Running; - } else { - lv_obj_set_state(btnStopLap, LV_STATE_DISABLED); - lv_obj_set_state(txtStopLap, LV_STATE_DISABLED); - } - break; - } - case States::Running: { - lv_label_set_text(txtPlayPause, Symbols::pause); - lv_label_set_text(txtStopLap, Symbols::lapsFlag); - - const auto timeElapsed = calculateDelta(startTime, xTaskGetTickCount()); - currentTimeSeparated = convertTicksToTimeSegments((oldTimeElapsed + timeElapsed)); - - lv_label_set_text_fmt(time, "%02d:%02d", currentTimeSeparated.mins, currentTimeSeparated.secs); - lv_label_set_text_fmt(msecTime, "%02d", currentTimeSeparated.hundredths); - - if (lapPressed == true) { - if (lapBuffer[1]) { - lv_label_set_text_fmt( - lapOneText, "#%2d %2d:%02d.%02d", (lapNr - 1), lapBuffer[1]->mins, lapBuffer[1]->secs, lapBuffer[1]->hundredths); - } - if (lapBuffer[0]) { - lv_label_set_text_fmt( - lapTwoText, "#%2d %2d:%02d.%02d", lapNr, lapBuffer[0]->mins, lapBuffer[0]->secs, lapBuffer[0]->hundredths); - } - // Reset the bool to avoid setting the text in each cycle until there is a change - lapPressed = false; - } - - if (currentEvent == Events::Pause) { - // Reset the start time - startTime = 0; - // Store the current time elapsed in cache - oldTimeElapsed += timeElapsed; - currentState = States::Halted; - lv_obj_set_style_local_text_color(time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_YELLOW); - lv_obj_set_style_local_text_color(msecTime, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_YELLOW); - } else { - lv_obj_set_style_local_text_color(time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GREEN); - lv_obj_set_style_local_text_color(msecTime, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GREEN); - } - break; - } - case States::Halted: { - lv_label_set_text(txtPlayPause, Symbols::play); - lv_label_set_text(txtStopLap, Symbols::stop); - - if (currentEvent == Events::Play) { - startTime = xTaskGetTickCount(); - currentState = States::Running; - } - if (currentEvent == Events::Stop) { - currentState = States::Init; - oldTimeElapsed = 0; - lv_obj_set_style_local_text_color(time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GRAY); - lv_obj_set_style_local_text_color(msecTime, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GRAY); - } - break; - } + if (currentState == States::Running) { + timeElapsed = calculateDelta(startTime, xTaskGetTickCount()); + currentTimeSeparated = convertTicksToTimeSegments((oldTimeElapsed + timeElapsed)); + + lv_label_set_text_fmt(time, "%02d:%02d", currentTimeSeparated.mins, currentTimeSeparated.secs); + lv_label_set_text_fmt(msecTime, "%02d", currentTimeSeparated.hundredths); } return running; } void StopWatch::playPauseBtnEventHandler(lv_event_t event) { - if (event == LV_EVENT_CLICKED) { - if (currentState == States::Init) { - currentEvent = Events::Play; - } else { - // Simple Toggle for play/pause - currentEvent = (currentEvent == Events::Play ? Events::Pause : Events::Play); - } + if (event != LV_EVENT_PRESSED) { + return; + } + if (currentState == States::Init) { + start(); + } else if (currentState == States::Running) { + pause(); + } else if (currentState == States::Halted) { + start(); } } void StopWatch::stopLapBtnEventHandler(lv_event_t event) { - if (event == LV_EVENT_CLICKED) { - // If running, then this button is used to save laps - if (currentState == States::Running) { - lapBuffer.addLaps(currentTimeSeparated); - lapNr++; - lapPressed = true; - - } else if (currentState == States::Halted) { - currentEvent = Events::Stop; - } else { - // Not possible to reach here. Do nothing. + if (event != LV_EVENT_PRESSED) { + return; + } + // If running, then this button is used to save laps + if (currentState == States::Running) { + lapBuffer.addLaps(currentTimeSeparated); + lapNr++; + if (lapBuffer[1]) { + lv_label_set_text_fmt( + lapOneText, "#%2d %2d:%02d.%02d", (lapNr - 1), lapBuffer[1]->mins, lapBuffer[1]->secs, lapBuffer[1]->hundredths); + } + if (lapBuffer[0]) { + lv_label_set_text_fmt(lapTwoText, "#%2d %2d:%02d.%02d", lapNr, lapBuffer[0]->mins, lapBuffer[0]->secs, lapBuffer[0]->hundredths); } + } else if (currentState == States::Halted) { + reset(); + } +} + +bool StopWatch::OnButtonPushed() { + if (currentState == States::Running) { + pause(); + } else { + running = false; } + return true; } diff --git a/src/displayapp/screens/StopWatch.h b/src/displayapp/screens/StopWatch.h index ff604361..e132f158 100644 --- a/src/displayapp/screens/StopWatch.h +++ b/src/displayapp/screens/StopWatch.h @@ -8,13 +8,12 @@ #include "portmacro_cmsis.h" #include <array> +#include "systemtask/SystemTask.h" namespace Pinetime::Applications::Screens { enum class States { Init, Running, Halted }; - enum class Events { Play, Pause, Stop }; - struct TimeSeparated_t { int mins; int secs; @@ -63,23 +62,28 @@ namespace Pinetime::Applications::Screens { class StopWatch : public Screen { public: - StopWatch(DisplayApp* app); + StopWatch(DisplayApp* app, System::SystemTask& systemTask); ~StopWatch() override; bool Refresh() override; void playPauseBtnEventHandler(lv_event_t event); void stopLapBtnEventHandler(lv_event_t event); + bool OnButtonPushed() override; + + void reset(); + void start(); + void pause(); private: + Pinetime::System::SystemTask& systemTask; + TickType_t timeElapsed; bool running; States currentState; - Events currentEvent; TickType_t startTime; TickType_t oldTimeElapsed; TimeSeparated_t currentTimeSeparated; // Holds Mins, Secs, millisecs LapTextBuffer_t<2> lapBuffer; - int lapNr; - bool lapPressed; + int lapNr = 0; lv_obj_t *time, *msecTime, *btnPlayPause, *btnStopLap, *txtPlayPause, *txtStopLap; lv_obj_t *lapOneText, *lapTwoText; }; diff --git a/src/displayapp/screens/Symbols.h b/src/displayapp/screens/Symbols.h index 8d55f693..e68a7af6 100644 --- a/src/displayapp/screens/Symbols.h +++ b/src/displayapp/screens/Symbols.h @@ -40,6 +40,10 @@ namespace Pinetime { static constexpr const char* stopWatch = "\xEF\x8B\xB2"; static constexpr const char* hourGlass = "\xEF\x89\x92"; static constexpr const char* lapsFlag = "\xEF\x80\xA4"; + static constexpr const char* drum = "\xEF\x95\xA9"; + static constexpr const char* chartLine = "\xEF\x88\x81"; + static constexpr const char* eye = "\xEF\x81\xAE"; + static constexpr const char* home = "\xEF\x80\x95"; // lv_font_sys_48.c static constexpr const char* settings = "\xEE\xA4\x82"; // e902 diff --git a/src/displayapp/screens/SystemInfo.cpp b/src/displayapp/screens/SystemInfo.cpp index 9ff28288..e7c5b65a 100644 --- a/src/displayapp/screens/SystemInfo.cpp +++ b/src/displayapp/screens/SystemInfo.cpp @@ -3,26 +3,44 @@ #include "../DisplayApp.h" #include "Label.h" #include "Version.h" +#include "BootloaderVersion.h" #include "components/battery/BatteryController.h" #include "components/ble/BleController.h" #include "components/brightness/BrightnessController.h" #include "components/datetime/DateTimeController.h" +#include "components/motion/MotionController.h" #include "drivers/Watchdog.h" using namespace Pinetime::Applications::Screens; +namespace { + const char* ToString(const Pinetime::Controllers::MotionController::DeviceTypes deviceType) { + switch (deviceType) { + case Pinetime::Controllers::MotionController::DeviceTypes::BMA421: + return "BMA421"; + case Pinetime::Controllers::MotionController::DeviceTypes::BMA425: + return "BMA425"; + case Pinetime::Controllers::MotionController::DeviceTypes::Unknown: + return "???"; + } + return "???"; + } +} + SystemInfo::SystemInfo(Pinetime::Applications::DisplayApp* app, Pinetime::Controllers::DateTime& dateTimeController, Pinetime::Controllers::Battery& batteryController, Pinetime::Controllers::BrightnessController& brightnessController, Pinetime::Controllers::Ble& bleController, - Pinetime::Drivers::WatchdogView& watchdog) + Pinetime::Drivers::WatchdogView& watchdog, + Pinetime::Controllers::MotionController& motionController) : Screen(app), dateTimeController {dateTimeController}, batteryController {batteryController}, brightnessController {brightnessController}, bleController {bleController}, watchdog {watchdog}, + motionController{motionController}, screens {app, 0, {[this]() -> std::unique_ptr<Screen> { @@ -54,11 +72,6 @@ bool SystemInfo::Refresh() { return running; } -bool SystemInfo::OnButtonPushed() { - running = false; - return true; -} - bool SystemInfo::OnTouchEvent(Pinetime::Applications::TouchEvents event) { return screens.OnTouchEvent(event); } @@ -68,26 +81,26 @@ std::unique_ptr<Screen> SystemInfo::CreateScreen1() { lv_label_set_recolor(label, true); lv_label_set_text_fmt(label, "#FFFF00 InfiniTime#\n\n" - "#444444 Version# %ld.%ld.%ld\n\n" - "#444444 Short Ref# %s\n\n" + "#444444 Version# %ld.%ld.%ld\n" + "#444444 Short Ref# %s\n" "#444444 Build date#\n" "%s\n" - "%s\n", + "%s\n\n" + "#444444 Bootloader# %s", Version::Major(), Version::Minor(), Version::Patch(), Version::GitCommitHash(), __DATE__, - __TIME__); + __TIME__, + BootloaderVersion::VersionString()); lv_label_set_align(label, LV_LABEL_ALIGN_CENTER); lv_obj_align(label, lv_scr_act(), LV_ALIGN_CENTER, 0, 0); return std::make_unique<Screens::Label>(0, 5, app, label); } std::unique_ptr<Screen> SystemInfo::CreateScreen2() { - auto batteryPercent = static_cast<uint8_t>(batteryController.PercentRemaining()); - float batteryVoltage = batteryController.Voltage(); - + auto batteryPercent = batteryController.PercentRemaining(); auto resetReason = [this]() { switch (watchdog.ResetReason()) { case Drivers::Watchdog::ResetReasons::Watchdog: @@ -126,25 +139,16 @@ std::unique_ptr<Screen> SystemInfo::CreateScreen2() { uptimeSeconds = uptimeSeconds % secondsInAMinute; // TODO handle more than 100 days of uptime - if (batteryPercent == -1) - batteryPercent = 0; - - // hack to not use the flot functions from printf - uint8_t batteryVoltageBytes[2]; - batteryVoltageBytes[1] = static_cast<uint8_t>(batteryVoltage); // truncate whole numbers - batteryVoltageBytes[0] = - static_cast<uint8_t>((batteryVoltage - batteryVoltageBytes[1]) * 100); // remove whole part of flt and shift 2 places over - // - lv_obj_t* label = lv_label_create(lv_scr_act(), nullptr); lv_label_set_recolor(label, true); lv_label_set_text_fmt(label, "#444444 Date# %02d/%02d/%04d\n" "#444444 Time# %02d:%02d:%02d\n" "#444444 Uptime#\n %02lud %02lu:%02lu:%02lu\n" - "#444444 Battery# %d%%/%1i.%02iv\n" + "#444444 Battery# %d%%/%03imV\n" "#444444 Backlight# %s\n" - "#444444 Last reset# %s\n", + "#444444 Last reset# %s\n" + "#444444 Accel.# %s\n", dateTimeController.Day(), static_cast<uint8_t>(dateTimeController.Month()), dateTimeController.Year(), @@ -156,10 +160,10 @@ std::unique_ptr<Screen> SystemInfo::CreateScreen2() { uptimeMinutes, uptimeSeconds, batteryPercent, - batteryVoltageBytes[1], - batteryVoltageBytes[0], + batteryController.Voltage(), brightnessController.ToString(), - resetReason); + resetReason, + ToString(motionController.DeviceType())); lv_obj_align(label, lv_scr_act(), LV_ALIGN_CENTER, 0, 0); return std::make_unique<Screens::Label>(1, 5, app, label); } @@ -177,22 +181,22 @@ std::unique_ptr<Screen> SystemInfo::CreateScreen3() { "\n" "#444444 LVGL Memory#\n" " #444444 used# %d (%d%%)\n" - " #444444 max used# %d\n" + " #444444 max used# %lu\n" " #444444 frag# %d%%\n" " #444444 free# %d" "\n" - "#444444 Steps# %li", + "#444444 Steps# %i", bleAddr[5], bleAddr[4], bleAddr[3], bleAddr[2], bleAddr[1], bleAddr[0], - (int) mon.total_size - mon.free_size, + static_cast<int>(mon.total_size - mon.free_size), mon.used_pct, mon.max_used, mon.frag_pct, - (int) mon.free_biggest_size, + static_cast<int>(mon.free_biggest_size), 0); lv_obj_align(label, lv_scr_act(), LV_ALIGN_CENTER, 0, 0); return std::make_unique<Screens::Label>(2, 5, app, label); @@ -205,28 +209,50 @@ bool SystemInfo::sortById(const TaskStatus_t& lhs, const TaskStatus_t& rhs) { std::unique_ptr<Screen> SystemInfo::CreateScreen4() { TaskStatus_t tasksStatus[7]; lv_obj_t* infoTask = lv_table_create(lv_scr_act(), NULL); - lv_table_set_col_cnt(infoTask, 3); + lv_table_set_col_cnt(infoTask, 4); lv_table_set_row_cnt(infoTask, 8); - lv_obj_set_pos(infoTask, 10, 10); + lv_obj_set_pos(infoTask, 0, 10); lv_table_set_cell_value(infoTask, 0, 0, "#"); - lv_table_set_col_width(infoTask, 0, 50); - lv_table_set_cell_value(infoTask, 0, 1, "Task"); - lv_table_set_col_width(infoTask, 1, 80); - lv_table_set_cell_value(infoTask, 0, 2, "Free"); - lv_table_set_col_width(infoTask, 2, 90); + lv_table_set_col_width(infoTask, 0, 30); + lv_table_set_cell_value(infoTask, 0, 1, "S"); // State + lv_table_set_col_width(infoTask, 1, 30); + lv_table_set_cell_value(infoTask, 0, 2, "Task"); + lv_table_set_col_width(infoTask, 2, 80); + lv_table_set_cell_value(infoTask, 0, 3, "Free"); + lv_table_set_col_width(infoTask, 3, 90); auto nb = uxTaskGetSystemState(tasksStatus, 7, nullptr); std::sort(tasksStatus, tasksStatus + nb, sortById); for (uint8_t i = 0; i < nb; i++) { lv_table_set_cell_value(infoTask, i + 1, 0, std::to_string(tasksStatus[i].xTaskNumber).c_str()); - lv_table_set_cell_value(infoTask, i + 1, 1, tasksStatus[i].pcTaskName); + char state[2] = {0}; + switch (tasksStatus[i].eCurrentState) { + case eReady: + case eRunning: + state[0] = 'R'; + break; + case eBlocked: + state[0] = 'B'; + break; + case eSuspended: + state[0] = 'S'; + break; + case eDeleted: + state[0] = 'D'; + break; + default: + state[0] = 'I'; // Invalid + break; + } + lv_table_set_cell_value(infoTask, i + 1, 1, state); + lv_table_set_cell_value(infoTask, i + 1, 2, tasksStatus[i].pcTaskName); if (tasksStatus[i].usStackHighWaterMark < 20) { std::string str1 = std::to_string(tasksStatus[i].usStackHighWaterMark) + " low"; - lv_table_set_cell_value(infoTask, i + 1, 2, str1.c_str()); + lv_table_set_cell_value(infoTask, i + 1, 3, str1.c_str()); } else { - lv_table_set_cell_value(infoTask, i + 1, 2, std::to_string(tasksStatus[i].usStackHighWaterMark).c_str()); + lv_table_set_cell_value(infoTask, i + 1, 3, std::to_string(tasksStatus[i].usStackHighWaterMark).c_str()); } } return std::make_unique<Screens::Label>(3, 5, app, infoTask); diff --git a/src/displayapp/screens/SystemInfo.h b/src/displayapp/screens/SystemInfo.h index c61a07a2..a9ad652d 100644 --- a/src/displayapp/screens/SystemInfo.h +++ b/src/displayapp/screens/SystemInfo.h @@ -27,20 +27,19 @@ namespace Pinetime { Pinetime::Controllers::Battery& batteryController, Pinetime::Controllers::BrightnessController& brightnessController, Pinetime::Controllers::Ble& bleController, - Pinetime::Drivers::WatchdogView& watchdog); + Pinetime::Drivers::WatchdogView& watchdog, + Pinetime::Controllers::MotionController& motionController); ~SystemInfo() override; bool Refresh() override; - bool OnButtonPushed() override; bool OnTouchEvent(TouchEvents event) override; private: - bool running = true; - Pinetime::Controllers::DateTime& dateTimeController; Pinetime::Controllers::Battery& batteryController; Pinetime::Controllers::BrightnessController& brightnessController; Pinetime::Controllers::Ble& bleController; Pinetime::Drivers::WatchdogView& watchdog; + Pinetime::Controllers::MotionController& motionController; ScreenList<5> screens; @@ -54,4 +53,4 @@ namespace Pinetime { }; } } -}
\ No newline at end of file +} diff --git a/src/displayapp/screens/Tile.cpp b/src/displayapp/screens/Tile.cpp index ec36af38..d5d6cb80 100644 --- a/src/displayapp/screens/Tile.cpp +++ b/src/displayapp/screens/Tile.cpp @@ -6,15 +6,17 @@ using namespace Pinetime::Applications::Screens; namespace { static void lv_update_task(struct _lv_task_t* task) { - auto user_data = static_cast<Tile*>(task->user_data); + auto* user_data = static_cast<Tile*>(task->user_data); user_data->UpdateScreen(); } static void event_handler(lv_obj_t* obj, lv_event_t event) { + if (event != LV_EVENT_VALUE_CHANGED) return; + Tile* screen = static_cast<Tile*>(obj->user_data); - uint32_t* eventDataPtr = (uint32_t*) lv_event_get_data(); + auto* eventDataPtr = (uint32_t*) lv_event_get_data(); uint32_t eventData = *eventDataPtr; - screen->OnObjectEvent(obj, event, eventData); + screen->OnValueChangedEvent(obj, eventData); } } @@ -107,7 +109,7 @@ Tile::Tile(uint8_t screenID, lv_obj_set_pos(backgroundLabel, 0, 0); lv_label_set_text_static(backgroundLabel, ""); - taskUpdate = lv_task_create(lv_update_task, 500000, LV_TASK_PRIO_MID, this); + taskUpdate = lv_task_create(lv_update_task, 5000, LV_TASK_PRIO_MID, this); } Tile::~Tile() { @@ -124,9 +126,9 @@ bool Tile::Refresh() { return running; } -void Tile::OnObjectEvent(lv_obj_t* obj, lv_event_t event, uint32_t buttonId) { - if (event == LV_EVENT_VALUE_CHANGED) { - app->StartApp(apps[buttonId], DisplayApp::FullRefreshDirections::Up); - running = false; - } +void Tile::OnValueChangedEvent(lv_obj_t* obj, uint32_t buttonId) { + if(obj != btnm1) return; + + app->StartApp(apps[buttonId], DisplayApp::FullRefreshDirections::Up); + running = false; } diff --git a/src/displayapp/screens/Tile.h b/src/displayapp/screens/Tile.h index 4ebd81cd..765a8def 100644 --- a/src/displayapp/screens/Tile.h +++ b/src/displayapp/screens/Tile.h @@ -32,7 +32,7 @@ namespace Pinetime { bool Refresh() override; void UpdateScreen(); - void OnObjectEvent(lv_obj_t* obj, lv_event_t event, uint32_t buttonId); + void OnValueChangedEvent(lv_obj_t* obj, uint32_t buttonId); private: Pinetime::Controllers::Battery& batteryController; diff --git a/src/displayapp/screens/Timer.cpp b/src/displayapp/screens/Timer.cpp index 260a17ef..99e979ba 100644 --- a/src/displayapp/screens/Timer.cpp +++ b/src/displayapp/screens/Timer.cpp @@ -63,8 +63,8 @@ Timer::Timer(DisplayApp* app, Controllers::TimerController& timerController) lv_obj_set_style_local_text_color(time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GRAY); uint32_t seconds = timerController.GetTimeRemaining() / 1000; - lv_label_set_text_fmt(time, "%02d:%02d", seconds / 60, seconds % 60); - + lv_label_set_text_fmt(time, "%02lu:%02lu", seconds / 60, seconds % 60); + lv_obj_align(time, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, -20); btnPlayPause = lv_btn_create(lv_scr_act(), nullptr); @@ -90,7 +90,7 @@ Timer::~Timer() { bool Timer::Refresh() { if (timerController.IsRunning()) { uint32_t seconds = timerController.GetTimeRemaining() / 1000; - lv_label_set_text_fmt(time, "%02d:%02d", seconds / 60, seconds % 60); + lv_label_set_text_fmt(time, "%02lu:%02lu", seconds / 60, seconds % 60); } return running; } diff --git a/src/displayapp/screens/WatchFaceAnalog.cpp b/src/displayapp/screens/WatchFaceAnalog.cpp index 02f1fc2a..621929b8 100644 --- a/src/displayapp/screens/WatchFaceAnalog.cpp +++ b/src/displayapp/screens/WatchFaceAnalog.cpp @@ -5,39 +5,55 @@ #include "Symbols.h" #include "NotificationIcon.h" -#include <cmath> - LV_IMG_DECLARE(bg_clock); using namespace Pinetime::Applications::Screens; -#define HOUR_LENGTH 70 -#define MINUTE_LENGTH 90 -#define SECOND_LENGTH 110 -#define PI 3.14159265358979323846 +namespace { +constexpr int16_t HourLength = 70; +constexpr int16_t MinuteLength = 90; +constexpr int16_t SecondLength = 110; + +// sin(90) = 1 so the value of _lv_trigo_sin(90) is the scaling factor +const auto LV_TRIG_SCALE = _lv_trigo_sin(90); + +int16_t Cosine(int16_t angle) { + return _lv_trigo_sin(angle + 90); +} + +int16_t Sine(int16_t angle) { + return _lv_trigo_sin(angle); +} + +int16_t CoordinateXRelocate(int16_t x) { + return (x + LV_HOR_RES / 2); +} + +int16_t CoordinateYRelocate(int16_t y) { + return std::abs(y - LV_HOR_RES / 2); +} -// ## -static int16_t coordinate_x_relocate(int16_t x) { - return ((x) + LV_HOR_RES / 2); +lv_point_t CoordinateRelocate(int16_t radius, int16_t angle) { + return lv_point_t{ + .x = CoordinateXRelocate(radius * static_cast<int32_t>(Sine(angle)) / LV_TRIG_SCALE), + .y = CoordinateYRelocate(radius * static_cast<int32_t>(Cosine(angle)) / LV_TRIG_SCALE) + }; } -// ## -static int16_t coordinate_y_relocate(int16_t y) { - return (((y) -LV_HOR_RES / 2) < 0) ? (0 - ((y) -LV_HOR_RES / 2)) : ((y) -LV_HOR_RES / 2); } WatchFaceAnalog::WatchFaceAnalog(Pinetime::Applications::DisplayApp* app, Controllers::DateTime& dateTimeController, Controllers::Battery& batteryController, Controllers::Ble& bleController, - Controllers::NotificationManager& notificatioManager, + Controllers::NotificationManager& notificationManager, Controllers::Settings& settingsController) : Screen(app), currentDateTime {{}}, dateTimeController {dateTimeController}, batteryController {batteryController}, bleController {bleController}, - notificatioManager {notificatioManager}, + notificationManager {notificationManager}, settingsController {settingsController} { settingsController.SetClockFace(1); @@ -106,7 +122,6 @@ WatchFaceAnalog::WatchFaceAnalog(Pinetime::Applications::DisplayApp* app, } WatchFaceAnalog::~WatchFaceAnalog() { - lv_style_reset(&hour_line_style); lv_style_reset(&hour_line_style_trace); lv_style_reset(&minute_line_style); @@ -117,21 +132,17 @@ WatchFaceAnalog::~WatchFaceAnalog() { } void WatchFaceAnalog::UpdateClock() { - hour = dateTimeController.Hours(); minute = dateTimeController.Minutes(); second = dateTimeController.Seconds(); if (sMinute != minute) { - minute_point[0].x = coordinate_x_relocate(30 * sin(minute * 6 * PI / 180)); - minute_point[0].y = coordinate_y_relocate(30 * cos(minute * 6 * PI / 180)); - minute_point[1].x = coordinate_x_relocate(MINUTE_LENGTH * sin(minute * 6 * PI / 180)); - minute_point[1].y = coordinate_y_relocate(MINUTE_LENGTH * cos(minute * 6 * PI / 180)); + auto const angle = minute * 6; + minute_point[0] = CoordinateRelocate(30, angle); + minute_point[1] = CoordinateRelocate(MinuteLength, angle); - minute_point_trace[0].x = coordinate_x_relocate(5 * sin(minute * 6 * PI / 180)); - minute_point_trace[0].y = coordinate_y_relocate(5 * cos(minute * 6 * PI / 180)); - minute_point_trace[1].x = coordinate_x_relocate(31 * sin(minute * 6 * PI / 180)); - minute_point_trace[1].y = coordinate_y_relocate(31 * cos(minute * 6 * PI / 180)); + minute_point_trace[0] = CoordinateRelocate(5, angle); + minute_point_trace[1] = CoordinateRelocate(31, angle); lv_line_set_points(minute_body, minute_point, 2); lv_line_set_points(minute_body_trace, minute_point_trace, 2); @@ -140,15 +151,13 @@ void WatchFaceAnalog::UpdateClock() { if (sHour != hour || sMinute != minute) { sHour = hour; sMinute = minute; - hour_point[0].x = coordinate_x_relocate(30 * sin((((hour > 12 ? hour - 12 : hour) * 30) + (minute * 0.5)) * PI / 180)); - hour_point[0].y = coordinate_y_relocate(30 * cos((((hour > 12 ? hour - 12 : hour) * 30) + (minute * 0.5)) * PI / 180)); - hour_point[1].x = coordinate_x_relocate(HOUR_LENGTH * sin((((hour > 12 ? hour - 12 : hour) * 30) + (minute * 0.5)) * PI / 180)); - hour_point[1].y = coordinate_y_relocate(HOUR_LENGTH * cos((((hour > 12 ? hour - 12 : hour) * 30) + (minute * 0.5)) * PI / 180)); + auto const angle = (hour * 30 + minute / 2); - hour_point_trace[0].x = coordinate_x_relocate(5 * sin((((hour > 12 ? hour - 12 : hour) * 30) + (minute * 0.5)) * PI / 180)); - hour_point_trace[0].y = coordinate_y_relocate(5 * cos((((hour > 12 ? hour - 12 : hour) * 30) + (minute * 0.5)) * PI / 180)); - hour_point_trace[1].x = coordinate_x_relocate(31 * sin((((hour > 12 ? hour - 12 : hour) * 30) + (minute * 0.5)) * PI / 180)); - hour_point_trace[1].y = coordinate_y_relocate(31 * cos((((hour > 12 ? hour - 12 : hour) * 30) + (minute * 0.5)) * PI / 180)); + hour_point[0] = CoordinateRelocate(30, angle); + hour_point[1] = CoordinateRelocate(HourLength, angle); + + hour_point_trace[0] = CoordinateRelocate(5, angle); + hour_point_trace[1] = CoordinateRelocate(31, angle); lv_line_set_points(hour_body, hour_point, 2); lv_line_set_points(hour_body_trace, hour_point_trace, 2); @@ -156,35 +165,30 @@ void WatchFaceAnalog::UpdateClock() { if (sSecond != second) { sSecond = second; - second_point[0].x = coordinate_x_relocate(20 * sin((180 + second * 6) * PI / 180)); - second_point[0].y = coordinate_y_relocate(20 * cos((180 + second * 6) * PI / 180)); - second_point[1].x = coordinate_x_relocate(SECOND_LENGTH * sin(second * 6 * PI / 180)); - second_point[1].y = coordinate_y_relocate(SECOND_LENGTH * cos(second * 6 * PI / 180)); + auto const angle = second * 6; + + second_point[0] = CoordinateRelocate(-20, angle); + second_point[1] = CoordinateRelocate(SecondLength, angle); lv_line_set_points(second_body, second_point, 2); } } bool WatchFaceAnalog::Refresh() { - batteryPercentRemaining = batteryController.PercentRemaining(); if (batteryPercentRemaining.IsUpdated()) { auto batteryPercent = batteryPercentRemaining.Get(); lv_label_set_text(batteryIcon, BatteryIcon::GetBatteryIcon(batteryPercent)); } - notificationState = notificatioManager.AreNewNotificationsAvailable(); + notificationState = notificationManager.AreNewNotificationsAvailable(); if (notificationState.IsUpdated()) { - if (notificationState.Get() == true) - lv_label_set_text(notificationIcon, NotificationIcon::GetIcon(true)); - else - lv_label_set_text(notificationIcon, NotificationIcon::GetIcon(false)); + lv_label_set_text(notificationIcon, NotificationIcon::GetIcon(notificationState.Get())); } currentDateTime = dateTimeController.CurrentDateTime(); if (currentDateTime.IsUpdated()) { - month = dateTimeController.Month(); day = dateTimeController.Day(); dayOfWeek = dateTimeController.DayOfWeek(); @@ -192,7 +196,6 @@ bool WatchFaceAnalog::Refresh() { UpdateClock(); if ((month != currentMonth) || (dayOfWeek != currentDayOfWeek) || (day != currentDay)) { - lv_label_set_text_fmt(label_date_day, "%s\n%02i", dateTimeController.DayOfWeekShortToString(), day); currentMonth = month; @@ -202,4 +205,4 @@ bool WatchFaceAnalog::Refresh() { } return true; -}
\ No newline at end of file +} diff --git a/src/displayapp/screens/WatchFaceAnalog.h b/src/displayapp/screens/WatchFaceAnalog.h index 667f6241..5d8c6a24 100644 --- a/src/displayapp/screens/WatchFaceAnalog.h +++ b/src/displayapp/screens/WatchFaceAnalog.h @@ -27,7 +27,7 @@ namespace Pinetime { Controllers::DateTime& dateTimeController, Controllers::Battery& batteryController, Controllers::Ble& bleController, - Controllers::NotificationManager& notificatioManager, + Controllers::NotificationManager& notificationManager, Controllers::Settings& settingsController); ~WatchFaceAnalog() override; @@ -48,7 +48,7 @@ namespace Pinetime { Pinetime::Controllers::DateTime::Days currentDayOfWeek = Pinetime::Controllers::DateTime::Days::Unknown; uint8_t currentDay = 0; - DirtyValue<float> batteryPercentRemaining {0}; + DirtyValue<uint8_t> batteryPercentRemaining {0}; DirtyValue<std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds>> currentDateTime; DirtyValue<bool> notificationState {false}; @@ -58,14 +58,12 @@ namespace Pinetime { lv_obj_t* minute_body_trace; lv_obj_t* second_body; - // ## lv_point_t hour_point[2]; lv_point_t hour_point_trace[2]; lv_point_t minute_point[2]; lv_point_t minute_point_trace[2]; lv_point_t second_point[2]; - // ## lv_style_t hour_line_style; lv_style_t hour_line_style_trace; lv_style_t minute_line_style; @@ -79,11 +77,11 @@ namespace Pinetime { Controllers::DateTime& dateTimeController; Controllers::Battery& batteryController; Controllers::Ble& bleController; - Controllers::NotificationManager& notificatioManager; + Controllers::NotificationManager& notificationManager; Controllers::Settings& settingsController; void UpdateClock(); }; } } -}
\ No newline at end of file +} diff --git a/src/displayapp/screens/WatchFaceDigital.cpp b/src/displayapp/screens/WatchFaceDigital.cpp index f1285eaf..7a240f1f 100644 --- a/src/displayapp/screens/WatchFaceDigital.cpp +++ b/src/displayapp/screens/WatchFaceDigital.cpp @@ -12,9 +12,6 @@ #include "components/ble/NotificationManager.h" #include "components/heartrate/HeartRateController.h" #include "components/motion/MotionController.h" -#include "components/settings/Settings.h" -#include "../DisplayApp.h" - using namespace Pinetime::Applications::Screens; WatchFaceDigital::WatchFaceDigital(DisplayApp* app, @@ -36,12 +33,6 @@ WatchFaceDigital::WatchFaceDigital(DisplayApp* app, motionController {motionController} { settingsController.SetClockFace(0); - displayedChar[0] = 0; - displayedChar[1] = 0; - displayedChar[2] = 0; - displayedChar[3] = 0; - displayedChar[4] = 0; - batteryIcon = lv_label_create(lv_scr_act(), nullptr); lv_label_set_text(batteryIcon, Symbols::batteryFull); lv_obj_align(batteryIcon, lv_scr_act(), LV_ALIGN_IN_TOP_RIGHT, -5, 2); @@ -56,7 +47,7 @@ WatchFaceDigital::WatchFaceDigital(DisplayApp* app, lv_label_set_text(bleIcon, Symbols::bluetooth); lv_obj_align(bleIcon, batteryPlug, LV_ALIGN_OUT_LEFT_MID, -5, 0); - notificationIcon = lv_label_create(lv_scr_act(), NULL); + notificationIcon = lv_label_create(lv_scr_act(), nullptr); lv_obj_set_style_local_text_color(notificationIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x00FF00)); lv_label_set_text(notificationIcon, NotificationIcon::GetIcon(false)); lv_obj_align(notificationIcon, nullptr, LV_ALIGN_IN_TOP_LEFT, 10, 0); @@ -111,17 +102,13 @@ bool WatchFaceDigital::Refresh() { if (batteryPercentRemaining.IsUpdated()) { auto batteryPercent = batteryPercentRemaining.Get(); lv_label_set_text(batteryIcon, BatteryIcon::GetBatteryIcon(batteryPercent)); - auto isCharging = batteryController.IsCharging() || batteryController.IsPowerPresent(); + auto isCharging = batteryController.IsCharging() or batteryController.IsPowerPresent(); lv_label_set_text(batteryPlug, BatteryIcon::GetPlugIcon(isCharging)); } bleState = bleController.IsConnected(); if (bleState.IsUpdated()) { - if (bleState.Get() == true) { - lv_label_set_text(bleIcon, BleIcon::GetIcon(true)); - } else { - lv_label_set_text(bleIcon, BleIcon::GetIcon(false)); - } + lv_label_set_text(bleIcon, BleIcon::GetIcon(bleState.Get())); } lv_obj_align(batteryIcon, lv_scr_act(), LV_ALIGN_IN_TOP_RIGHT, -5, 5); lv_obj_align(batteryPlug, batteryIcon, LV_ALIGN_OUT_LEFT_MID, -5, 0); @@ -129,10 +116,7 @@ bool WatchFaceDigital::Refresh() { notificationState = notificatioManager.AreNewNotificationsAvailable(); if (notificationState.IsUpdated()) { - if (notificationState.Get() == true) - lv_label_set_text(notificationIcon, NotificationIcon::GetIcon(true)); - else - lv_label_set_text(notificationIcon, NotificationIcon::GetIcon(false)); + lv_label_set_text(notificationIcon, NotificationIcon::GetIcon(notificationState.Get())); } currentDateTime = dateTimeController.CurrentDateTime(); @@ -144,9 +128,9 @@ bool WatchFaceDigital::Refresh() { auto time = date::make_time(newDateTime - dp); auto yearMonthDay = date::year_month_day(dp); - auto year = (int) yearMonthDay.year(); - auto month = static_cast<Pinetime::Controllers::DateTime::Months>((unsigned) yearMonthDay.month()); - auto day = (unsigned) yearMonthDay.day(); + auto year = static_cast<int>(yearMonthDay.year()); + auto month = static_cast<Pinetime::Controllers::DateTime::Months>(static_cast<unsigned>(yearMonthDay.month())); + auto day = static_cast<unsigned>(yearMonthDay.day()); auto dayOfWeek = static_cast<Pinetime::Controllers::DateTime::Days>(date::weekday(yearMonthDay).iso_encoding()); int hour = time.hours().count(); @@ -175,15 +159,13 @@ bool WatchFaceDigital::Refresh() { sprintf(hoursChar, "%02d", hour); } - if (hoursChar[0] != displayedChar[0] || hoursChar[1] != displayedChar[1] || minutesChar[0] != displayedChar[2] || - minutesChar[1] != displayedChar[3]) { + if ((hoursChar[0] != displayedChar[0]) or (hoursChar[1] != displayedChar[1]) or (minutesChar[0] != displayedChar[2]) or + (minutesChar[1] != displayedChar[3])) { displayedChar[0] = hoursChar[0]; displayedChar[1] = hoursChar[1]; displayedChar[2] = minutesChar[0]; displayedChar[3] = minutesChar[1]; - char timeStr[6]; - if (settingsController.GetClockType() == Controllers::Settings::ClockType::H12) { lv_label_set_text(label_time_ampm, ampmChar); if (hoursChar[0] == '0') { @@ -191,8 +173,7 @@ bool WatchFaceDigital::Refresh() { } } - sprintf(timeStr, "%c%c:%c%c", hoursChar[0], hoursChar[1], minutesChar[0], minutesChar[1]); - lv_label_set_text(label_time, timeStr); + lv_label_set_text_fmt(label_time, "%s:%s", hoursChar, minutesChar); if (settingsController.GetClockType() == Controllers::Settings::ClockType::H12) { lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_IN_RIGHT_MID, 0, 0); @@ -202,13 +183,11 @@ bool WatchFaceDigital::Refresh() { } if ((year != currentYear) || (month != currentMonth) || (dayOfWeek != currentDayOfWeek) || (day != currentDay)) { - char dateStr[22]; if (settingsController.GetClockType() == Controllers::Settings::ClockType::H24) { - sprintf(dateStr, "%s %d %s %d", dateTimeController.DayOfWeekShortToString(), day, dateTimeController.MonthShortToString(), year); + lv_label_set_text_fmt(label_date, "%s %d %s %d", dateTimeController.DayOfWeekShortToString(), day, dateTimeController.MonthShortToString(), year); } else { - sprintf(dateStr, "%s %s %d %d", dateTimeController.DayOfWeekShortToString(), dateTimeController.MonthShortToString(), day, year); + lv_label_set_text_fmt(label_date, "%s %s %d %d", dateTimeController.DayOfWeekShortToString(), dateTimeController.MonthShortToString(), day, year); } - lv_label_set_text(label_date, dateStr); lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_CENTER, 0, 60); currentYear = year; diff --git a/src/displayapp/screens/WatchFaceDigital.h b/src/displayapp/screens/WatchFaceDigital.h index 246efc95..6a6e1ac6 100644 --- a/src/displayapp/screens/WatchFaceDigital.h +++ b/src/displayapp/screens/WatchFaceDigital.h @@ -35,17 +35,15 @@ namespace Pinetime { bool Refresh() override; - void OnObjectEvent(lv_obj_t* pObj, lv_event_t i); - private: - char displayedChar[5]; + char displayedChar[5] {}; uint16_t currentYear = 1970; Pinetime::Controllers::DateTime::Months currentMonth = Pinetime::Controllers::DateTime::Months::Unknown; Pinetime::Controllers::DateTime::Days currentDayOfWeek = Pinetime::Controllers::DateTime::Days::Unknown; uint8_t currentDay = 0; - DirtyValue<int> batteryPercentRemaining {}; + DirtyValue<uint8_t> batteryPercentRemaining {}; DirtyValue<bool> bleState {}; DirtyValue<std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds>> currentDateTime {}; DirtyValue<bool> motionSensorOk {}; @@ -63,7 +61,6 @@ namespace Pinetime { lv_obj_t* batteryPlug; lv_obj_t* heartbeatIcon; lv_obj_t* heartbeatValue; - lv_obj_t* heartbeatBpm; lv_obj_t* stepIcon; lv_obj_t* stepValue; lv_obj_t* notificationIcon; diff --git a/src/displayapp/screens/settings/QuickSettings.cpp b/src/displayapp/screens/settings/QuickSettings.cpp index 5db7468c..2cd24876 100644 --- a/src/displayapp/screens/settings/QuickSettings.cpp +++ b/src/displayapp/screens/settings/QuickSettings.cpp @@ -27,7 +27,7 @@ QuickSettings::QuickSettings(Pinetime::Applications::DisplayApp* app, batteryController {batteryController}, dateTimeController {dateTimeController}, brightness {brightness}, - motorController{motorController}, + motorController {motorController}, settingsController {settingsController} { // Time @@ -110,7 +110,7 @@ QuickSettings::QuickSettings(Pinetime::Applications::DisplayApp* app, lv_obj_set_pos(backgroundLabel, 0, 0); lv_label_set_text_static(backgroundLabel, ""); - taskUpdate = lv_task_create(lv_update_task, 500000, LV_TASK_PRIO_MID, this); + taskUpdate = lv_task_create(lv_update_task, 5000, LV_TASK_PRIO_MID, this); } QuickSettings::~QuickSettings() { @@ -154,17 +154,6 @@ void QuickSettings::OnButtonEvent(lv_obj_t* object, lv_event_t event) { } } -bool QuickSettings::OnTouchEvent(Pinetime::Applications::TouchEvents event) { - switch (event) { - case Pinetime::Applications::TouchEvents::SwipeLeft: - running = false; - return false; - - default: - return true; - } -} - bool QuickSettings::Refresh() { return running; } diff --git a/src/displayapp/screens/settings/QuickSettings.h b/src/displayapp/screens/settings/QuickSettings.h index a14f46bf..e0fc0a87 100644 --- a/src/displayapp/screens/settings/QuickSettings.h +++ b/src/displayapp/screens/settings/QuickSettings.h @@ -29,7 +29,6 @@ namespace Pinetime { bool Refresh() override; - bool OnTouchEvent(Pinetime::Applications::TouchEvents event) override; void OnButtonEvent(lv_obj_t* object, lv_event_t event); void UpdateScreen(); diff --git a/src/displayapp/screens/settings/SettingSteps.cpp b/src/displayapp/screens/settings/SettingSteps.cpp index b7c024f1..faa843e6 100644 --- a/src/displayapp/screens/settings/SettingSteps.cpp +++ b/src/displayapp/screens/settings/SettingSteps.cpp @@ -45,7 +45,7 @@ SettingSteps::SettingSteps( stepValue = lv_label_create(lv_scr_act(), NULL); lv_obj_set_style_local_text_font(stepValue, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_42); - lv_label_set_text_fmt(stepValue,"%i", settingsController.GetStepsGoal()); + lv_label_set_text_fmt(stepValue, "%lu", settingsController.GetStepsGoal()); lv_label_set_align(stepValue, LV_LABEL_ALIGN_CENTER); lv_obj_align(stepValue, lv_scr_act(), LV_ALIGN_CENTER, 0, -10); @@ -81,7 +81,7 @@ void SettingSteps::UpdateSelected(lv_obj_t *object, lv_event_t event) { value += 1000; if ( value <= 500000 ) { settingsController.SetStepsGoal(value); - lv_label_set_text_fmt(stepValue,"%i", settingsController.GetStepsGoal()); + lv_label_set_text_fmt(stepValue, "%lu", settingsController.GetStepsGoal()); lv_obj_align(stepValue, lv_scr_act(), LV_ALIGN_CENTER, 0, -10); } } @@ -90,7 +90,7 @@ void SettingSteps::UpdateSelected(lv_obj_t *object, lv_event_t event) { value -= 1000; if ( value >= 1000 ) { settingsController.SetStepsGoal(value); - lv_label_set_text_fmt(stepValue,"%i", settingsController.GetStepsGoal()); + lv_label_set_text_fmt(stepValue, "%lu", settingsController.GetStepsGoal()); lv_obj_align(stepValue, lv_scr_act(), LV_ALIGN_CENTER, 0, -10); } } diff --git a/src/displayapp/screens/settings/SettingWakeUp.cpp b/src/displayapp/screens/settings/SettingWakeUp.cpp index 89f0c098..cce9a60d 100644 --- a/src/displayapp/screens/settings/SettingWakeUp.cpp +++ b/src/displayapp/screens/settings/SettingWakeUp.cpp @@ -16,7 +16,7 @@ namespace { SettingWakeUp::SettingWakeUp(Pinetime::Applications::DisplayApp* app, Pinetime::Controllers::Settings& settingsController) : Screen(app), settingsController {settingsController} { - + ignoringEvents = false; lv_obj_t* container1 = lv_cont_create(lv_scr_act(), nullptr); lv_obj_set_style_local_bg_opa(container1, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_TRANSP); @@ -36,24 +36,16 @@ SettingWakeUp::SettingWakeUp(Pinetime::Applications::DisplayApp* app, Pinetime:: lv_obj_t* icon = lv_label_create(lv_scr_act(), nullptr); lv_obj_set_style_local_text_color(icon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_ORANGE); - lv_label_set_text_static(icon, Symbols::clock); + lv_label_set_text_static(icon, Symbols::eye); lv_label_set_align(icon, LV_LABEL_ALIGN_CENTER); lv_obj_align(icon, title, LV_ALIGN_OUT_LEFT_MID, -10, 0); optionsTotal = 0; cbOption[optionsTotal] = lv_checkbox_create(container1, nullptr); - lv_checkbox_set_text_static(cbOption[optionsTotal], " None"); - cbOption[optionsTotal]->user_data = this; - lv_obj_set_event_cb(cbOption[optionsTotal], event_handler); - if (settingsController.getWakeUpMode() == Pinetime::Controllers::Settings::WakeUpMode::None) { - lv_checkbox_set_checked(cbOption[optionsTotal], true); - } - optionsTotal++; - cbOption[optionsTotal] = lv_checkbox_create(container1, nullptr); lv_checkbox_set_text_static(cbOption[optionsTotal], " Single Tap"); cbOption[optionsTotal]->user_data = this; lv_obj_set_event_cb(cbOption[optionsTotal], event_handler); - if (settingsController.getWakeUpMode() == Pinetime::Controllers::Settings::WakeUpMode::SingleTap) { + if (settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::SingleTap)) { lv_checkbox_set_checked(cbOption[optionsTotal], true); } optionsTotal++; @@ -61,7 +53,7 @@ SettingWakeUp::SettingWakeUp(Pinetime::Applications::DisplayApp* app, Pinetime:: lv_checkbox_set_text_static(cbOption[optionsTotal], " Double Tap"); cbOption[optionsTotal]->user_data = this; lv_obj_set_event_cb(cbOption[optionsTotal], event_handler); - if (settingsController.getWakeUpMode() == Pinetime::Controllers::Settings::WakeUpMode::DoubleTap) { + if (settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::DoubleTap)) { lv_checkbox_set_checked(cbOption[optionsTotal], true); } optionsTotal++; @@ -69,7 +61,7 @@ SettingWakeUp::SettingWakeUp(Pinetime::Applications::DisplayApp* app, Pinetime:: lv_checkbox_set_text_static(cbOption[optionsTotal], " Raise Wrist"); cbOption[optionsTotal]->user_data = this; lv_obj_set_event_cb(cbOption[optionsTotal], event_handler); - if (settingsController.getWakeUpMode() == Pinetime::Controllers::Settings::WakeUpMode::RaiseWrist) { + if (settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::RaiseWrist)) { lv_checkbox_set_checked(cbOption[optionsTotal], true); } optionsTotal++; @@ -85,27 +77,31 @@ bool SettingWakeUp::Refresh() { } void SettingWakeUp::UpdateSelected(lv_obj_t* object, lv_event_t event) { - if (event == LV_EVENT_VALUE_CHANGED) { - for (int i = 0; i < optionsTotal; i++) { - if (object == cbOption[i]) { - lv_checkbox_set_checked(cbOption[i], true); + using WakeUpMode = Pinetime::Controllers::Settings::WakeUpMode; + if (event == LV_EVENT_VALUE_CHANGED && !ignoringEvents) { + ignoringEvents = true; - if (i == 0) { - settingsController.setWakeUpMode(Pinetime::Controllers::Settings::WakeUpMode::None); - }; - if (i == 1) { - settingsController.setWakeUpMode(Pinetime::Controllers::Settings::WakeUpMode::SingleTap); - }; - if (i == 2) { - settingsController.setWakeUpMode(Pinetime::Controllers::Settings::WakeUpMode::DoubleTap); - }; - if (i == 3) { - settingsController.setWakeUpMode(Pinetime::Controllers::Settings::WakeUpMode::RaiseWrist); - }; - - } else { - lv_checkbox_set_checked(cbOption[i], false); + // Find the index of the checkbox that triggered the event + int index = 0; + for (; index < optionsTotal; ++index) { + if (cbOption[index] == object) { + break; } } + + // Toggle needed wakeup mode + auto mode = static_cast<WakeUpMode>(index); + auto currentState = settingsController.isWakeUpModeOn(mode); + settingsController.setWakeUpMode(mode, !currentState); + + // Update checkbox according to current wakeup modes. + // This is needed because we can have extra logic when setting or unsetting wakeup modes, + // for example, when setting SingleTap, DoubleTap is unset and vice versa. + auto modes = settingsController.getWakeUpModes(); + for (int i = 0; i < optionsTotal; ++i) { + lv_checkbox_set_checked(cbOption[i], modes[i]); + } + + ignoringEvents = false; } -}
\ No newline at end of file +} diff --git a/src/displayapp/screens/settings/SettingWakeUp.h b/src/displayapp/screens/settings/SettingWakeUp.h index 8b33eb06..248dd9ac 100644 --- a/src/displayapp/screens/settings/SettingWakeUp.h +++ b/src/displayapp/screens/settings/SettingWakeUp.h @@ -22,6 +22,11 @@ namespace Pinetime { Controllers::Settings& settingsController; uint8_t optionsTotal; lv_obj_t* cbOption[4]; + // When UpdateSelected is called, it uses lv_checkbox_set_checked, + // which can cause extra events to be fired, + // which might trigger UpdateSelected again, causing a loop. + // This variable is used as a mutex to prevent that. + bool ignoringEvents; }; } } diff --git a/src/displayapp/screens/settings/SettingWatchFace.cpp b/src/displayapp/screens/settings/SettingWatchFace.cpp index 457cebf6..02b90816 100644 --- a/src/displayapp/screens/settings/SettingWatchFace.cpp +++ b/src/displayapp/screens/settings/SettingWatchFace.cpp @@ -36,7 +36,7 @@ SettingWatchFace::SettingWatchFace(Pinetime::Applications::DisplayApp* app, Pine lv_obj_t* icon = lv_label_create(lv_scr_act(), nullptr); lv_obj_set_style_local_text_color(icon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_ORANGE); - lv_label_set_text_static(icon, Symbols::clock); + lv_label_set_text_static(icon, Symbols::home); lv_label_set_align(icon, LV_LABEL_ALIGN_CENTER); lv_obj_align(icon, title, LV_ALIGN_OUT_LEFT_MID, -10, 0); @@ -59,6 +59,15 @@ SettingWatchFace::SettingWatchFace(Pinetime::Applications::DisplayApp* app, Pine } optionsTotal++; + cbOption[optionsTotal] = lv_checkbox_create(container1, nullptr); + lv_checkbox_set_text_static(cbOption[optionsTotal], " PineTimeStyle"); + cbOption[optionsTotal]->user_data = this; + lv_obj_set_event_cb(cbOption[optionsTotal], event_handler); + if (settingsController.GetClockFace() == 2) { + lv_checkbox_set_checked(cbOption[optionsTotal], true); + } + + optionsTotal++; } SettingWatchFace::~SettingWatchFace() { @@ -81,4 +90,4 @@ void SettingWatchFace::UpdateSelected(lv_obj_t* object, lv_event_t event) { } } } -}
\ No newline at end of file +} diff --git a/src/displayapp/screens/settings/Settings.cpp b/src/displayapp/screens/settings/Settings.cpp index e63a3584..0ab21377 100644 --- a/src/displayapp/screens/settings/Settings.cpp +++ b/src/displayapp/screens/settings/Settings.cpp @@ -41,9 +41,9 @@ std::unique_ptr<Screen> Settings::CreateScreen1() { std::array<Screens::List::Applications, 4> applications {{ {Symbols::sun, "Display", Apps::SettingDisplay}, - {Symbols::clock, "Wake Up", Apps::SettingWakeUp}, + {Symbols::eye, "Wake Up", Apps::SettingWakeUp}, {Symbols::clock, "Time format", Apps::SettingTimeFormat}, - {Symbols::clock, "Watch face", Apps::SettingWatchFace}, + {Symbols::home, "Watch face", Apps::SettingWatchFace}, }}; return std::make_unique<Screens::List>(0, 2, app, settingsController, applications); diff --git a/src/drivers/Bma421.cpp b/src/drivers/Bma421.cpp index 35b2c105..dd284000 100644 --- a/src/drivers/Bma421.cpp +++ b/src/drivers/Bma421.cpp @@ -42,6 +42,12 @@ void Bma421::Init() { if (ret != BMA4_OK) return; + switch(bma.chip_id) { + case BMA423_CHIP_ID: deviceType = DeviceTypes::BMA421; break; + case BMA425_CHIP_ID: deviceType = DeviceTypes::BMA425; break; + default: deviceType = DeviceTypes::Unknown; break; + } + ret = bma423_write_config_file(&bma); if (ret != BMA4_OK) return; @@ -121,3 +127,6 @@ void Bma421::SoftReset() { nrf_delay_ms(1); } } +Bma421::DeviceTypes Bma421::DeviceType() const { + return deviceType; +} diff --git a/src/drivers/Bma421.h b/src/drivers/Bma421.h index e4d925f5..ace644bd 100644 --- a/src/drivers/Bma421.h +++ b/src/drivers/Bma421.h @@ -6,6 +6,11 @@ namespace Pinetime { class TwiMaster; class Bma421 { public: + enum class DeviceTypes : uint8_t { + Unknown, + BMA421, + BMA425 + }; struct Values { uint32_t steps; int16_t x; @@ -29,6 +34,7 @@ namespace Pinetime { void Write(uint8_t registerAddress, const uint8_t* data, size_t size); bool IsOk() const; + DeviceTypes DeviceType() const; private: void Reset(); @@ -38,6 +44,7 @@ namespace Pinetime { struct bma4_dev bma; bool isOk = false; bool isResetOk = false; + DeviceTypes deviceType = DeviceTypes::Unknown; }; } }
\ No newline at end of file diff --git a/src/drivers/Bma421_C/bma423.c b/src/drivers/Bma421_C/bma423.c index 1d782705..7d6c2e0a 100644 --- a/src/drivers/Bma421_C/bma423.c +++ b/src/drivers/Bma421_C/bma423.c @@ -43,6 +43,521 @@ #include "bma423.h" /**\name Feature configuration file */ +const uint8_t bma425_config_file[] = { + 0x80, 0x2e, 0xfd, 0x00, 0x80, 0x2e, 0xff, 0x00, 0xc8, 0x2e, 0x00, 0x2e, + 0x80, 0x2e, 0xfb, 0x00, 0x80, 0x2e, 0xdd, 0xb0, 0x80, 0x2e, 0xfe, 0x00, + 0x80, 0x2e, 0xfc, 0x00, 0x80, 0x2e, 0x0d, 0xb1, 0x50, 0x39, 0x21, 0x2e, + 0xb0, 0xf0, 0x10, 0x30, 0x21, 0x2e, 0x16, 0xf0, 0x80, 0x2e, 0x34, 0xb1, + 0x65, 0x50, 0x4f, 0x52, 0x01, 0x42, 0x3b, 0x80, 0x41, 0x30, 0x01, 0x42, + 0x3c, 0x80, 0x00, 0x2e, 0x01, 0x40, 0x01, 0x42, 0x21, 0x2e, 0xff, 0xaf, + 0xb8, 0x2e, 0x1f, 0x7f, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0xfd, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x08, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 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, 0x01, 0x2e, + 0x55, 0xf0, 0xc0, 0x2e, 0x21, 0x2e, 0x55, 0xf0, 0x30, 0x50, 0x00, 0x30, + 0x51, 0x56, 0x05, 0x30, 0x05, 0x2c, 0xfb, 0x7f, 0x3e, 0xbe, 0xd2, 0xba, + 0xb2, 0xb9, 0x6c, 0x0b, 0x53, 0x0e, 0xf9, 0x2f, 0x53, 0x1a, 0x01, 0x2f, + 0x4d, 0x0e, 0xf5, 0x2f, 0xd2, 0x7f, 0x04, 0x30, 0x1f, 0x2c, 0xe1, 0x7f, + 0xc5, 0x01, 0xa3, 0x03, 0x72, 0x0e, 0x03, 0x2f, 0x72, 0x1a, 0x0f, 0x2f, + 0x79, 0x0f, 0x0d, 0x2f, 0xe1, 0x6f, 0x4f, 0x04, 0x5f, 0xb9, 0xb1, 0xbf, + 0xfa, 0x0b, 0xd2, 0x6f, 0x96, 0x06, 0xb1, 0x25, 0x51, 0xbf, 0xeb, 0x7f, + 0x06, 0x00, 0xb2, 0x25, 0x27, 0x03, 0xdb, 0x7f, 0xcf, 0xbf, 0x3e, 0xbf, + 0x01, 0xb8, 0xd2, 0xba, 0x41, 0xba, 0xb2, 0xb9, 0x07, 0x0a, 0x6e, 0x0b, + 0xc0, 0x90, 0xdf, 0x2f, 0x40, 0x91, 0xdd, 0x2f, 0xfb, 0x6f, 0xd0, 0x5f, + 0xb8, 0x2e, 0x00, 0x31, 0xc0, 0x2e, 0x21, 0x2e, 0xba, 0xf0, 0xc8, 0x2e, + 0xc8, 0x2e, 0xc8, 0x2e, 0xc8, 0x2e, 0xc8, 0x2e, 0xaa, 0x00, 0x05, 0x00, + 0xaa, 0x00, 0x05, 0x00, 0x2d, 0x01, 0xd4, 0x7b, 0x3b, 0x01, 0xdb, 0x7a, + 0x04, 0x00, 0x3f, 0x7b, 0xcd, 0x6c, 0xc3, 0x04, 0x85, 0x09, 0xc3, 0x04, + 0xec, 0xe6, 0x0c, 0x46, 0x01, 0x00, 0x27, 0x00, 0x19, 0x00, 0x96, 0x00, + 0xa0, 0x00, 0x01, 0x00, 0x0c, 0x00, 0xf0, 0x3c, 0x00, 0x01, 0x01, 0x00, + 0x03, 0x00, 0x01, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, + 0x00, 0x00, 0x47, 0x28, 0x88, 0x00, 0x54, 0x00, 0x51, 0x00, 0x97, 0x00, + 0xa0, 0x00, 0x80, 0x00, 0x00, 0x40, 0xff, 0x7f, 0x00, 0x80, 0xaf, 0x00, + 0xff, 0x00, 0xff, 0xb7, 0x00, 0x02, 0x00, 0xb0, 0x05, 0x80, 0xb1, 0xf0, + 0x5e, 0xf0, 0xc0, 0x00, 0x59, 0xf0, 0x39, 0xf0, 0x57, 0x00, 0x89, 0xf0, + 0x54, 0x00, 0x00, 0x20, 0x82, 0x00, 0x59, 0x00, 0x5d, 0x00, 0x81, 0x00, + 0xff, 0xfb, 0x52, 0xf0, 0x56, 0xf0, 0x33, 0x09, 0x33, 0x07, 0x00, 0x08, + 0x90, 0x01, 0x00, 0xf8, 0x00, 0x01, 0x02, 0x01, 0x60, 0x00, 0x6a, 0x00, + 0x4c, 0x04, 0xa0, 0x00, 0xe8, 0x03, 0x81, 0x00, 0x82, 0x00, 0xeb, 0x07, + 0xae, 0x07, 0xaa, 0x00, 0x75, 0x00, 0xff, 0x0f, 0xdb, 0x00, 0xb6, 0x01, + 0x70, 0x69, 0x26, 0xd3, 0x9c, 0x07, 0xbc, 0x02, 0x1f, 0x05, 0x9d, 0x00, + 0xa8, 0x05, 0xee, 0x06, 0x01, 0xf0, 0xbc, 0x05, 0x37, 0x08, 0xbb, 0x06, + 0x37, 0xfa, 0xb2, 0x00, 0xff, 0x03, 0x98, 0x2e, 0x15, 0xb0, 0x20, 0x26, + 0x98, 0x2e, 0xf7, 0x00, 0x98, 0x2e, 0xc4, 0xb0, 0x10, 0x30, 0x21, 0x2e, + 0x59, 0xf0, 0x98, 0x2e, 0xb9, 0x00, 0x98, 0x2e, 0x7a, 0xb4, 0x98, 0x2e, + 0x89, 0xb4, 0x00, 0x2e, 0x00, 0x2e, 0xd0, 0x2e, 0x98, 0x2e, 0xa7, 0xb0, + 0x01, 0x2e, 0x58, 0x00, 0x00, 0xb2, 0x1a, 0x2f, 0x00, 0x30, 0x21, 0x2e, + 0x58, 0x00, 0x47, 0x50, 0x98, 0x2e, 0x65, 0xb0, 0x03, 0x2e, 0x1e, 0x01, + 0x47, 0x50, 0x02, 0x30, 0x98, 0x2e, 0x28, 0xb5, 0x03, 0x2e, 0x1f, 0x01, + 0x47, 0x50, 0x12, 0x30, 0x98, 0x2e, 0x28, 0xb5, 0x01, 0x2e, 0x03, 0xf0, + 0x0d, 0xbc, 0x0f, 0xb8, 0x00, 0x90, 0x02, 0x2f, 0x4f, 0x50, 0x21, 0x2e, + 0xbc, 0xf0, 0x01, 0x2e, 0x57, 0x00, 0x00, 0xb2, 0x25, 0x2f, 0x00, 0x30, + 0x21, 0x2e, 0x57, 0x00, 0x49, 0x50, 0x98, 0x2e, 0x65, 0xb0, 0x49, 0x50, + 0x98, 0x2e, 0xc1, 0xb1, 0x49, 0x50, 0x98, 0x2e, 0x34, 0xb6, 0x49, 0x50, + 0x4b, 0x52, 0x98, 0x2e, 0xa4, 0xb4, 0x49, 0x50, 0x4d, 0x52, 0x98, 0x2e, + 0xa4, 0xb4, 0x01, 0x2e, 0x1e, 0x01, 0x0f, 0xbc, 0x0f, 0xb8, 0x00, 0x90, + 0x4f, 0x50, 0x08, 0x2f, 0x03, 0x2e, 0x1f, 0x01, 0x9f, 0xbc, 0x9f, 0xb8, + 0x40, 0x90, 0x02, 0x2f, 0x21, 0x2e, 0xbc, 0xf0, 0x02, 0x2d, 0x21, 0x2e, + 0xba, 0xf0, 0x98, 0x2e, 0xb9, 0x00, 0xaf, 0x2d, 0x10, 0x50, 0xfb, 0x7f, + 0x21, 0x25, 0x98, 0x2e, 0xf4, 0x01, 0xfb, 0x6f, 0x21, 0x25, 0xf0, 0x5f, + 0x10, 0x25, 0x80, 0x2e, 0xbe, 0x00, 0x94, 0x01, 0xdd, 0x03, 0xc0, 0xad, + 0x0b, 0x2f, 0xc0, 0xa8, 0x03, 0x2f, 0xc0, 0x90, 0x07, 0x2f, 0x80, 0xa6, + 0x05, 0x2f, 0x40, 0xa9, 0x12, 0x2f, 0x40, 0x91, 0x01, 0x2f, 0x00, 0xab, + 0x0e, 0x2f, 0xc0, 0xac, 0x00, 0x30, 0x55, 0x52, 0x07, 0x2f, 0xc0, 0xa9, + 0x03, 0x2f, 0xc0, 0x91, 0x03, 0x2f, 0x80, 0xa7, 0x01, 0x2f, 0x40, 0xa1, + 0x05, 0x2f, 0xc0, 0x2e, 0x17, 0x25, 0x06, 0x25, 0xc0, 0x2e, 0xf0, 0x3f, + 0x53, 0x52, 0xb8, 0x2e, 0x83, 0x86, 0x01, 0x30, 0x00, 0x30, 0x94, 0x40, + 0x24, 0x18, 0x06, 0x00, 0x53, 0x0e, 0x4f, 0x02, 0xf9, 0x2f, 0xb8, 0x2e, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0xa8, 0x03, 0x25, 0x10, 0x2f, 0x80, 0x90, + 0x01, 0x2f, 0x41, 0x0e, 0x0c, 0x2f, 0xf3, 0x3f, 0x18, 0x05, 0x05, 0x30, + 0x5d, 0x07, 0x15, 0x0e, 0x03, 0x2f, 0x55, 0x1a, 0x02, 0x2f, 0xcc, 0x0f, + 0x00, 0x2f, 0x58, 0x04, 0x01, 0x25, 0xb8, 0x2e, 0xb8, 0x2e, 0x63, 0x50, + 0x41, 0x30, 0x02, 0x40, 0x51, 0x0a, 0x01, 0x42, 0x18, 0x82, 0x57, 0x50, + 0x60, 0x42, 0x70, 0x3c, 0x59, 0x54, 0x42, 0x42, 0x69, 0x82, 0x82, 0x32, + 0x43, 0x40, 0x18, 0x08, 0x02, 0x0a, 0x40, 0x42, 0x42, 0x80, 0x02, 0x3f, + 0x01, 0x40, 0x10, 0x50, 0x4a, 0x08, 0xfb, 0x7f, 0x11, 0x42, 0x0b, 0x31, + 0x0b, 0x42, 0x3e, 0x80, 0x31, 0x32, 0x01, 0x42, 0x00, 0x2e, 0x01, 0x2e, + 0x40, 0xf0, 0x13, 0x90, 0x20, 0x2f, 0x03, 0x30, 0x5d, 0x50, 0x5b, 0x54, + 0x14, 0x35, 0x06, 0x30, 0x61, 0x52, 0x55, 0x32, 0x1d, 0x1a, 0xe3, 0x22, + 0x18, 0x1a, 0x5f, 0x58, 0xe3, 0x22, 0x04, 0x30, 0xd5, 0x40, 0xb5, 0x0d, + 0xe1, 0xbe, 0x6f, 0xbb, 0x80, 0x91, 0xa9, 0x0d, 0x01, 0x89, 0xb5, 0x23, + 0x10, 0xa1, 0xf7, 0x2f, 0xda, 0x0e, 0x14, 0x35, 0xeb, 0x2f, 0x01, 0x2e, + 0x25, 0x00, 0x70, 0x1a, 0x00, 0x30, 0x21, 0x30, 0x02, 0x2c, 0x08, 0x22, + 0x30, 0x30, 0x00, 0xb2, 0x06, 0x2f, 0x21, 0x2e, 0x59, 0xf0, 0x98, 0x2e, + 0xb9, 0x00, 0x00, 0x2e, 0x00, 0x2e, 0xd0, 0x2e, 0xfb, 0x6f, 0xf0, 0x5f, + 0xb8, 0x2e, 0x70, 0x50, 0x03, 0x2e, 0x22, 0x01, 0xf1, 0x7f, 0x2a, 0x25, + 0xb9, 0x82, 0xe0, 0x7f, 0xdb, 0x7f, 0x00, 0x30, 0x45, 0x30, 0x32, 0x30, + 0x03, 0x30, 0x04, 0x30, 0xf6, 0x6f, 0xf2, 0x09, 0xfc, 0x13, 0xc2, 0xab, + 0xb5, 0x09, 0xc7, 0x23, 0x80, 0xb3, 0xe6, 0x6f, 0xb7, 0x01, 0x00, 0x2e, + 0x8b, 0x41, 0x4b, 0x42, 0x05, 0x2f, 0xc5, 0x7f, 0x05, 0x30, 0x46, 0x40, + 0xae, 0x05, 0xc5, 0x6f, 0x46, 0x42, 0x01, 0x80, 0x23, 0xbd, 0xd3, 0xbe, + 0x03, 0x89, 0x41, 0x82, 0xdf, 0x0c, 0x03, 0xa2, 0xe4, 0x2f, 0xe0, 0x6f, + 0x91, 0x6f, 0x11, 0x42, 0xc3, 0xb2, 0xa1, 0x6f, 0x11, 0x42, 0x00, 0x2e, + 0xb1, 0x6f, 0x01, 0x42, 0x06, 0x2f, 0x00, 0x32, 0x03, 0x2e, 0x59, 0xf0, + 0x08, 0x0a, 0x21, 0x2e, 0x59, 0xf0, 0x06, 0x2d, 0xf1, 0x3d, 0x01, 0x2e, + 0x59, 0xf0, 0x01, 0x08, 0x21, 0x2e, 0x59, 0xf0, 0xdb, 0x6f, 0x90, 0x5f, + 0xb8, 0x2e, 0x69, 0x50, 0x05, 0x2e, 0x00, 0xf0, 0x4f, 0x56, 0xd3, 0x0f, + 0x01, 0x40, 0xf4, 0x33, 0xcc, 0x08, 0x0d, 0x2f, 0xf4, 0x30, 0x94, 0x08, + 0xb9, 0x88, 0x02, 0xa3, 0x04, 0x2f, 0x67, 0x58, 0x4c, 0x0a, 0x87, 0xa2, + 0x05, 0x2c, 0xcb, 0x22, 0x4f, 0x54, 0x4a, 0x0a, 0xf2, 0x3b, 0xca, 0x08, + 0x3c, 0x80, 0x27, 0x2e, 0x59, 0xf0, 0x01, 0x40, 0x01, 0x42, 0xb8, 0x2e, + 0x01, 0x2e, 0xb1, 0xf0, 0x67, 0x52, 0x01, 0x0a, 0x21, 0x2e, 0xb1, 0xf0, + 0x01, 0x2e, 0x1e, 0x01, 0x0f, 0xbc, 0x0f, 0xb8, 0x00, 0x90, 0x4f, 0x50, + 0x08, 0x2f, 0x03, 0x2e, 0x1f, 0x01, 0x9f, 0xbc, 0x9f, 0xb8, 0x40, 0x90, + 0x02, 0x2f, 0xc0, 0x2e, 0x21, 0x2e, 0xbc, 0xf0, 0xc0, 0x2e, 0x21, 0x2e, + 0xba, 0xf0, 0x70, 0x50, 0xf7, 0x7f, 0x00, 0x2e, 0x0f, 0x2e, 0xb8, 0xf0, + 0xf8, 0xbf, 0xff, 0xbb, 0xc0, 0xb3, 0x23, 0x2f, 0xb2, 0x7f, 0x94, 0x7f, + 0xc6, 0x7f, 0xe5, 0x7f, 0xd3, 0x7f, 0xa1, 0x7f, 0x35, 0x30, 0x05, 0x2e, + 0x01, 0xf0, 0x2e, 0xbd, 0x2e, 0xbb, 0x6b, 0x58, 0x6e, 0x05, 0x47, 0x56, + 0x6d, 0x54, 0x11, 0x30, 0x27, 0x41, 0x06, 0x41, 0xf8, 0xbf, 0xbe, 0x0b, + 0xb5, 0x11, 0xd6, 0x42, 0x03, 0x89, 0x5a, 0x0e, 0xf6, 0x2f, 0x23, 0x2e, + 0x58, 0x00, 0x4f, 0x52, 0x23, 0x2e, 0xb8, 0xf0, 0xb2, 0x6f, 0xe5, 0x6f, + 0xd3, 0x6f, 0xa1, 0x6f, 0x94, 0x6f, 0xc6, 0x6f, 0xf7, 0x6f, 0x90, 0x5f, + 0xc8, 0x2e, 0x60, 0x50, 0xc3, 0x7f, 0xd4, 0x7f, 0xe7, 0x7f, 0xf6, 0x7f, + 0xb2, 0x7f, 0xa5, 0x7f, 0x36, 0x30, 0x07, 0x2e, 0x01, 0xf0, 0xbe, 0xbd, + 0xbe, 0xbb, 0x6f, 0x58, 0x77, 0x05, 0x49, 0x56, 0x71, 0x54, 0x27, 0x41, + 0x06, 0x41, 0xf8, 0xbf, 0xbe, 0x0b, 0xb5, 0x11, 0xd6, 0x42, 0x03, 0x89, + 0x5a, 0x0e, 0xf6, 0x2f, 0x12, 0x30, 0x25, 0x2e, 0x57, 0x00, 0x02, 0x31, + 0x25, 0x2e, 0xb8, 0xf0, 0xd4, 0x6f, 0xc3, 0x6f, 0xe7, 0x6f, 0xb2, 0x6f, + 0xa5, 0x6f, 0xf6, 0x6f, 0xa0, 0x5f, 0xc8, 0x2e, 0x1a, 0x24, 0x26, 0x00, + 0x80, 0x2e, 0x65, 0x01, 0x70, 0x50, 0x42, 0x8e, 0xd4, 0x7f, 0xf6, 0x7f, + 0x47, 0x25, 0x1a, 0x18, 0x73, 0x52, 0xf1, 0x00, 0x64, 0x25, 0x01, 0x30, + 0x39, 0x02, 0x94, 0x41, 0x81, 0x41, 0xe2, 0x7f, 0xbe, 0xbb, 0xbd, 0x8d, + 0x02, 0xbd, 0xb5, 0x7f, 0x8e, 0xb5, 0xba, 0x0a, 0xc6, 0x7f, 0xab, 0x7f, + 0x51, 0x25, 0x98, 0x2e, 0xd1, 0x01, 0xd5, 0x6f, 0xe2, 0x6f, 0x2a, 0x18, + 0x73, 0x54, 0xb2, 0x01, 0x02, 0x30, 0xc4, 0x6f, 0x7a, 0x03, 0x12, 0x41, + 0x74, 0x25, 0xd0, 0x7f, 0x52, 0xbc, 0xd3, 0x41, 0x6e, 0xba, 0xde, 0xb6, + 0x20, 0x0b, 0xc7, 0x7f, 0x91, 0x7f, 0x98, 0x2e, 0xd1, 0x01, 0xf2, 0x6f, + 0xd5, 0x6f, 0xca, 0x16, 0x55, 0x18, 0xdd, 0x18, 0x95, 0x6f, 0xea, 0x18, + 0x73, 0x5a, 0x31, 0x25, 0x75, 0x01, 0x01, 0x30, 0x20, 0x25, 0x39, 0x02, + 0x5e, 0xba, 0x82, 0xbc, 0x8e, 0xb6, 0x21, 0x0b, 0x98, 0x2e, 0xd1, 0x01, + 0xe2, 0x6f, 0xb5, 0x6f, 0x2a, 0x18, 0xe0, 0x7f, 0xf1, 0x7f, 0x04, 0x30, + 0x73, 0x54, 0xf2, 0x00, 0x7c, 0x02, 0x85, 0x6f, 0xd0, 0x6f, 0x0d, 0x17, + 0x68, 0x18, 0xe0, 0x18, 0x90, 0x6f, 0xc4, 0x6f, 0xc5, 0x18, 0xeb, 0x6f, + 0xb2, 0x01, 0x1b, 0x43, 0x02, 0x30, 0x7a, 0x03, 0xfb, 0x6f, 0x3d, 0x8f, + 0x0b, 0x43, 0x3e, 0xba, 0x12, 0xbd, 0x52, 0xbc, 0x6e, 0xbb, 0xa2, 0x0a, + 0x9e, 0xb5, 0xde, 0xb6, 0x30, 0x0b, 0xf7, 0x7f, 0x98, 0x2e, 0xd1, 0x01, + 0xf5, 0x6f, 0x31, 0x25, 0xd1, 0x6f, 0x92, 0x6f, 0xab, 0x6f, 0x50, 0x43, + 0x43, 0x43, 0x90, 0x5f, 0x53, 0x56, 0x80, 0x2e, 0x00, 0xb0, 0x10, 0x50, + 0x03, 0x40, 0x19, 0x18, 0x55, 0x56, 0x19, 0x05, 0x36, 0x25, 0xf7, 0x7f, + 0x4a, 0x17, 0x54, 0x18, 0xec, 0x18, 0x09, 0x17, 0x01, 0x30, 0x0c, 0x07, + 0xe2, 0x18, 0xde, 0x00, 0xf2, 0x6f, 0x97, 0x02, 0x51, 0x58, 0xdc, 0x00, + 0x91, 0x02, 0xbf, 0xb8, 0x21, 0xbd, 0x8a, 0x0a, 0xc0, 0x2e, 0x02, 0x42, + 0xf0, 0x5f, 0x09, 0x2e, 0x1d, 0x01, 0x05, 0x2e, 0x1d, 0x01, 0xa3, 0xbc, + 0x44, 0xbe, 0x90, 0x50, 0x4f, 0xb9, 0x07, 0x2e, 0x1d, 0x01, 0x4a, 0x25, + 0x9f, 0xb8, 0x39, 0x8f, 0xb2, 0xbd, 0xf2, 0x7f, 0xbf, 0xb9, 0xeb, 0x7f, + 0x8a, 0x0a, 0x37, 0x89, 0x0b, 0x30, 0x93, 0x0a, 0x8b, 0x7f, 0xcb, 0x43, + 0x0b, 0x43, 0x80, 0xb2, 0xd3, 0x7f, 0xc1, 0x7f, 0x90, 0x2e, 0x6c, 0xb2, + 0x20, 0x25, 0x01, 0x2e, 0x5f, 0x00, 0x01, 0x90, 0x0e, 0x2f, 0x75, 0x52, + 0x01, 0x2e, 0x5c, 0x00, 0xb4, 0x7f, 0xa2, 0x7f, 0x98, 0x2e, 0x72, 0xb2, + 0x00, 0x30, 0x21, 0x2e, 0x5f, 0x00, 0xc1, 0x6f, 0xd3, 0x6f, 0xa2, 0x6f, + 0xb4, 0x6f, 0x0b, 0x30, 0x01, 0x2e, 0x1d, 0x01, 0x06, 0xbc, 0x06, 0xbb, + 0x57, 0x25, 0x01, 0x2e, 0x1d, 0x01, 0x94, 0xb1, 0x05, 0xbc, 0xb6, 0x7f, + 0x0f, 0xbb, 0x79, 0x50, 0x80, 0xb3, 0x0f, 0x2f, 0x0d, 0x2e, 0x1d, 0x01, + 0x7d, 0x5e, 0xb7, 0x09, 0x2d, 0x2e, 0x1d, 0x01, 0x7f, 0x5c, 0x77, 0x5e, + 0x9b, 0x43, 0x9b, 0x43, 0xdb, 0x43, 0x9b, 0x43, 0x1b, 0x42, 0xcb, 0x43, + 0x0b, 0x42, 0x8b, 0x43, 0x40, 0xb2, 0x05, 0x2f, 0x77, 0x50, 0x00, 0x2e, + 0x16, 0x40, 0x0b, 0x40, 0x76, 0x7f, 0x8b, 0x7f, 0xcb, 0x0a, 0x01, 0x2e, + 0x5c, 0x00, 0x75, 0x52, 0x7b, 0x5c, 0x98, 0x2e, 0xbe, 0xb2, 0x90, 0x6f, + 0x00, 0xb2, 0x0b, 0x2f, 0xf0, 0x6f, 0x00, 0xb2, 0x08, 0x2f, 0x77, 0x58, + 0x79, 0x50, 0x12, 0x41, 0x12, 0x42, 0x21, 0x30, 0x04, 0x41, 0x04, 0x42, + 0x23, 0x2e, 0x5e, 0xf0, 0xc0, 0x6f, 0x00, 0xb2, 0x26, 0x2f, 0x74, 0x6f, + 0x80, 0x6f, 0x7f, 0x54, 0x88, 0xbd, 0xc8, 0xb8, 0x4b, 0x0a, 0x94, 0x42, + 0x91, 0x42, 0x90, 0x42, 0x88, 0xba, 0x77, 0x52, 0xf3, 0x6f, 0x54, 0x42, + 0x85, 0x42, 0xc0, 0x90, 0x40, 0x42, 0x15, 0x2f, 0x79, 0x52, 0x00, 0x2e, + 0x52, 0x40, 0x41, 0x40, 0xa2, 0x04, 0x41, 0x06, 0x40, 0xaa, 0x04, 0x2f, + 0x40, 0x90, 0x0b, 0x2f, 0xb1, 0x6f, 0x4a, 0x0f, 0x08, 0x2f, 0xb2, 0x6f, + 0x80, 0xb2, 0x05, 0x2f, 0x79, 0x54, 0x21, 0x30, 0x94, 0x42, 0x80, 0x42, + 0x23, 0x2e, 0x5e, 0xf0, 0xd0, 0x6f, 0x00, 0xb2, 0x13, 0x2f, 0x01, 0x2e, + 0x5b, 0x00, 0x09, 0x2e, 0x81, 0x00, 0x04, 0x1a, 0x0d, 0x2f, 0x81, 0x50, + 0x29, 0x2e, 0x5b, 0x00, 0x24, 0x42, 0x44, 0x30, 0x02, 0x40, 0x02, 0x42, + 0x09, 0x80, 0x00, 0x2e, 0x04, 0x42, 0x03, 0x2d, 0x10, 0x30, 0x21, 0x2e, + 0x5f, 0x00, 0xeb, 0x6f, 0x70, 0x5f, 0xb8, 0x2e, 0x09, 0x86, 0x51, 0x54, + 0xe4, 0x40, 0xc3, 0x80, 0x94, 0x04, 0xc3, 0x40, 0x13, 0x05, 0x05, 0x40, + 0x25, 0x05, 0x8a, 0x17, 0x73, 0x30, 0x73, 0x09, 0x8c, 0x17, 0xf3, 0x08, + 0xe3, 0x00, 0x4c, 0x82, 0x15, 0x01, 0xb3, 0xb5, 0x53, 0x42, 0x8b, 0x16, + 0x43, 0xb6, 0x52, 0x42, 0x4c, 0x17, 0x54, 0x42, 0x55, 0x42, 0x53, 0x42, + 0x52, 0x42, 0x54, 0x42, 0x45, 0x42, 0x6d, 0x82, 0x83, 0x54, 0x52, 0x42, + 0x10, 0x50, 0x85, 0x54, 0x52, 0x42, 0xfb, 0x7f, 0x22, 0x30, 0x87, 0x56, + 0x43, 0x42, 0x44, 0x82, 0x0b, 0x30, 0x52, 0x42, 0x5b, 0x42, 0x7c, 0x84, + 0x4b, 0x42, 0x35, 0x82, 0x90, 0x80, 0x8b, 0x42, 0x0b, 0x42, 0x35, 0x80, + 0x04, 0x30, 0x0b, 0x42, 0x37, 0x80, 0x15, 0x30, 0x60, 0x25, 0x98, 0x2e, + 0xb1, 0xb2, 0x8b, 0x83, 0xfb, 0x6f, 0x65, 0x42, 0xc0, 0x2e, 0x44, 0x42, + 0xf0, 0x5f, 0x05, 0x80, 0x02, 0x30, 0x51, 0x82, 0x02, 0x42, 0x13, 0x30, + 0x41, 0x40, 0x4b, 0x08, 0x89, 0x54, 0x3e, 0x80, 0x51, 0x14, 0xc0, 0x2e, + 0x01, 0x42, 0x00, 0x2e, 0x40, 0x51, 0xd1, 0x7f, 0x12, 0x25, 0x02, 0x30, + 0x42, 0x43, 0x32, 0x30, 0x82, 0x43, 0xc6, 0x7f, 0xe5, 0x7f, 0xb4, 0x7f, + 0xa3, 0x7f, 0x90, 0x7f, 0x8b, 0x7f, 0x98, 0x2e, 0xc6, 0x01, 0xc0, 0x7e, + 0x00, 0xac, 0x01, 0x2f, 0x53, 0x50, 0xc0, 0x7e, 0x00, 0x2e, 0x90, 0x6f, + 0x09, 0x8a, 0xd1, 0x6f, 0x75, 0x7f, 0x4c, 0x82, 0x63, 0x41, 0x65, 0x7f, + 0x11, 0x7f, 0x00, 0x2e, 0x64, 0x41, 0x44, 0x85, 0x52, 0x7f, 0x45, 0x7f, + 0x00, 0x2e, 0xa6, 0x40, 0x80, 0x40, 0x32, 0x7f, 0x82, 0x8e, 0xc2, 0x6e, + 0x45, 0x41, 0xf0, 0x7f, 0x27, 0x7f, 0x02, 0x7f, 0x98, 0x2e, 0x38, 0xb1, + 0x23, 0x6f, 0xd1, 0x6f, 0xc2, 0x40, 0xf9, 0x86, 0x23, 0x7f, 0x80, 0xb2, + 0xe0, 0x7e, 0x0f, 0x2f, 0x32, 0x6f, 0x64, 0x6f, 0x82, 0x40, 0xf2, 0x7f, + 0x50, 0x82, 0x42, 0x6f, 0x50, 0x6f, 0x73, 0x6f, 0x85, 0x40, 0xc3, 0x40, + 0x04, 0x41, 0x06, 0x40, 0xe2, 0x6e, 0x98, 0x2e, 0x38, 0xb1, 0xe0, 0x7e, + 0xf3, 0x31, 0x10, 0x6f, 0x36, 0x80, 0xe1, 0x6e, 0x02, 0x40, 0x71, 0x7f, + 0x51, 0x04, 0x02, 0x30, 0x40, 0xa8, 0x91, 0x04, 0x4a, 0x22, 0x89, 0x16, + 0x93, 0x08, 0x4a, 0x00, 0x95, 0xb4, 0x09, 0x18, 0x8e, 0x16, 0x13, 0x30, + 0x93, 0x08, 0x21, 0x6f, 0x60, 0x7f, 0x4d, 0x86, 0x02, 0x80, 0xb2, 0x00, + 0x41, 0x40, 0x21, 0xb5, 0x50, 0x7f, 0x43, 0x7f, 0x98, 0x2e, 0xa7, 0xb1, + 0x40, 0x6f, 0x62, 0x6f, 0x55, 0x6f, 0x13, 0x40, 0x84, 0x40, 0x01, 0x40, + 0x45, 0x41, 0x42, 0xbe, 0x1d, 0x18, 0x4c, 0x04, 0x31, 0x0f, 0x04, 0x8a, + 0xc0, 0x6f, 0x11, 0x30, 0x02, 0x2f, 0x00, 0x2e, 0x03, 0x2c, 0x01, 0x42, + 0x23, 0x30, 0x03, 0x42, 0x00, 0x2e, 0xd6, 0x6f, 0x44, 0x41, 0x8a, 0x87, + 0x76, 0x8b, 0x00, 0xb3, 0x53, 0x7f, 0x15, 0x2f, 0x04, 0x6f, 0x8b, 0x5e, + 0x8b, 0x8d, 0xe7, 0x01, 0xc0, 0xa5, 0x84, 0x41, 0x01, 0x2f, 0x00, 0xa1, + 0x03, 0x2f, 0xc0, 0xad, 0x08, 0x2f, 0x00, 0xa5, 0x06, 0x2f, 0xc6, 0x40, + 0x81, 0x8d, 0x07, 0x30, 0x3c, 0x05, 0xd6, 0x42, 0x04, 0x2c, 0xc4, 0x42, + 0x02, 0x2c, 0x07, 0x30, 0x07, 0x30, 0x86, 0x86, 0x94, 0x6f, 0xd7, 0x7e, + 0x0e, 0x8d, 0x00, 0x40, 0x74, 0x89, 0xc7, 0x40, 0x02, 0xb2, 0xf9, 0x29, + 0x45, 0x41, 0x86, 0x41, 0xbe, 0x80, 0x21, 0x41, 0x75, 0x23, 0x82, 0x40, + 0xc7, 0x42, 0x45, 0x7f, 0x34, 0x7f, 0x20, 0x7f, 0x98, 0x2e, 0xa7, 0xb1, + 0x31, 0x6f, 0x60, 0x6f, 0x24, 0x6f, 0x22, 0x40, 0x05, 0x41, 0x43, 0x40, + 0x13, 0x01, 0x43, 0x86, 0xac, 0x0f, 0xd1, 0x6f, 0x30, 0x7f, 0x00, 0x2f, + 0x44, 0x42, 0x48, 0x8a, 0x41, 0x88, 0xe1, 0x40, 0x13, 0x7f, 0x04, 0x7f, + 0xf5, 0x7e, 0x98, 0x2e, 0xa7, 0xb1, 0x11, 0x6f, 0x60, 0x6f, 0x34, 0x6f, + 0x42, 0x40, 0x03, 0x40, 0x9a, 0x04, 0x04, 0x41, 0x43, 0x82, 0xa2, 0x0e, + 0x03, 0x6f, 0x00, 0x2f, 0xc2, 0x42, 0x00, 0x2e, 0x41, 0x40, 0x72, 0x6f, + 0x98, 0x2e, 0xa7, 0xb1, 0x25, 0x6f, 0x72, 0x6f, 0x53, 0x41, 0x93, 0x0e, + 0xd1, 0x6f, 0x46, 0x80, 0x1b, 0x30, 0x03, 0x30, 0x0c, 0x2f, 0x04, 0x40, + 0x00, 0x91, 0x42, 0x42, 0x08, 0x2f, 0xf6, 0x6e, 0x44, 0x6f, 0x86, 0x41, + 0xb4, 0x0e, 0x03, 0x2f, 0x02, 0x88, 0xdb, 0x7e, 0x03, 0x43, 0x0b, 0x42, + 0x46, 0x8d, 0x44, 0x41, 0x47, 0x80, 0x05, 0x6f, 0x94, 0x0f, 0x76, 0x7f, + 0x60, 0x7f, 0x02, 0x2f, 0x45, 0x89, 0x42, 0x43, 0x03, 0x43, 0x49, 0x88, + 0xa5, 0x6f, 0x40, 0x91, 0xa4, 0x7f, 0x15, 0x30, 0xe2, 0x6f, 0xd3, 0x6e, + 0x03, 0x2f, 0x04, 0x30, 0x83, 0x42, 0x80, 0x2e, 0x62, 0xb4, 0x04, 0x40, + 0x25, 0x29, 0x04, 0x42, 0x83, 0x42, 0x45, 0x82, 0x94, 0x6f, 0x04, 0x85, + 0xc0, 0xb2, 0x90, 0x2e, 0x4e, 0xb4, 0x15, 0x87, 0x3c, 0x8c, 0xc4, 0x40, + 0x46, 0x7f, 0xc2, 0x86, 0x07, 0x40, 0x86, 0x41, 0xf4, 0xbf, 0x00, 0xb3, + 0x0c, 0x2f, 0x90, 0x6f, 0x16, 0x80, 0x46, 0x25, 0x00, 0x40, 0x57, 0x25, + 0x04, 0x18, 0xae, 0x0e, 0x10, 0x30, 0x06, 0x30, 0x75, 0x25, 0x46, 0x23, + 0x60, 0x6f, 0x64, 0x25, 0xc4, 0x40, 0xfa, 0x86, 0x00, 0xb3, 0x33, 0x7f, + 0x09, 0x2f, 0x93, 0x6f, 0xd8, 0x88, 0x53, 0x6f, 0x04, 0x41, 0xc3, 0x40, + 0xdc, 0x0e, 0x13, 0x30, 0x04, 0x30, 0xdc, 0x22, 0xb3, 0x25, 0x40, 0xb3, + 0x02, 0x2f, 0x3b, 0x25, 0xc0, 0x90, 0x05, 0x2f, 0x91, 0x6f, 0xd0, 0x6f, + 0x98, 0x2e, 0xb1, 0xb2, 0x4d, 0x2c, 0x04, 0x30, 0x8d, 0x88, 0x43, 0x40, + 0x82, 0x40, 0x54, 0x7f, 0xda, 0x0f, 0x04, 0x30, 0x08, 0x2f, 0xc1, 0x80, + 0x40, 0x42, 0xc2, 0x0f, 0x02, 0x2f, 0x00, 0x30, 0xc0, 0x7e, 0x1b, 0x2d, + 0xc0, 0x7e, 0x19, 0x2d, 0xe1, 0xbc, 0x92, 0x6f, 0x4f, 0x04, 0x90, 0x84, + 0x40, 0xa8, 0x21, 0x05, 0x83, 0x40, 0x4c, 0x22, 0x4b, 0x0e, 0xb6, 0x84, + 0x21, 0x30, 0x02, 0x2f, 0x11, 0x30, 0x04, 0x2c, 0xc1, 0x7e, 0xe3, 0x6f, + 0xc1, 0x7e, 0xc1, 0x42, 0x00, 0x2e, 0x00, 0x40, 0x81, 0x40, 0x04, 0xbd, + 0x40, 0x6f, 0x98, 0x2e, 0xa7, 0xb1, 0x50, 0x6f, 0x11, 0x30, 0x02, 0x40, + 0x51, 0x08, 0xc3, 0x6e, 0x03, 0x80, 0x99, 0x15, 0x0b, 0x40, 0xb1, 0x6f, + 0xd0, 0x6f, 0xb6, 0x7f, 0x5b, 0x7f, 0x04, 0x30, 0x59, 0x54, 0x03, 0x30, + 0x11, 0x2c, 0x14, 0x80, 0x55, 0x6f, 0x06, 0x40, 0x75, 0x01, 0x58, 0xbb, + 0x6a, 0x09, 0x05, 0x42, 0xc1, 0x86, 0x47, 0x40, 0x51, 0x25, 0xbe, 0x01, + 0x56, 0x43, 0x00, 0x2e, 0x46, 0x41, 0xf4, 0x03, 0xb6, 0x6f, 0x47, 0x43, + 0x5e, 0x0e, 0xed, 0x2f, 0x31, 0x6f, 0x60, 0x6f, 0x42, 0x40, 0x15, 0x30, + 0x02, 0x82, 0x95, 0x08, 0x04, 0x42, 0x52, 0x42, 0x02, 0x2c, 0x44, 0x42, + 0x04, 0x30, 0x3e, 0x8e, 0x91, 0x6f, 0x4f, 0x8c, 0x02, 0x40, 0x83, 0x41, + 0xb5, 0x8d, 0x93, 0x0e, 0xd0, 0x6f, 0x01, 0x2f, 0x98, 0x2e, 0xb1, 0xb2, + 0x00, 0x2e, 0xc0, 0x41, 0x81, 0x41, 0xc1, 0x0f, 0xc0, 0x6f, 0x01, 0x2f, + 0x04, 0x42, 0x00, 0x2e, 0x70, 0x6f, 0x3c, 0x82, 0x00, 0x40, 0x41, 0x40, + 0x89, 0x16, 0x95, 0x08, 0x4a, 0x00, 0x04, 0xbc, 0x91, 0xb4, 0x01, 0x0e, + 0xe0, 0x6f, 0x07, 0x2f, 0xa1, 0x6f, 0x00, 0x2e, 0x41, 0x40, 0x40, 0xb2, + 0x02, 0x2f, 0xa1, 0x6f, 0x05, 0x42, 0x44, 0x42, 0x00, 0x2e, 0x8b, 0x6f, + 0xc0, 0x5e, 0xb8, 0x2e, 0x10, 0x50, 0x8d, 0x52, 0x4b, 0x50, 0xfb, 0x7f, + 0x98, 0x2e, 0x98, 0xb4, 0x4b, 0x52, 0x45, 0x82, 0x10, 0x30, 0x50, 0x42, + 0x60, 0x30, 0xfb, 0x6f, 0xc0, 0x2e, 0x40, 0x42, 0xf0, 0x5f, 0x10, 0x50, + 0x8f, 0x52, 0x4d, 0x50, 0xfb, 0x7f, 0x98, 0x2e, 0x98, 0xb4, 0x4d, 0x52, + 0x45, 0x82, 0x00, 0x30, 0x50, 0x42, 0x70, 0x30, 0xfb, 0x6f, 0xc0, 0x2e, + 0x40, 0x42, 0xf0, 0x5f, 0x12, 0x30, 0x12, 0x42, 0x02, 0x30, 0x12, 0x42, + 0x12, 0x42, 0x12, 0x42, 0x02, 0x42, 0x03, 0x80, 0x41, 0x84, 0x11, 0x42, + 0x02, 0x42, 0xb8, 0x2e, 0x48, 0x86, 0x90, 0x50, 0xc4, 0x40, 0x42, 0x84, + 0xf2, 0x7f, 0x5a, 0x25, 0x02, 0x41, 0xa2, 0xbf, 0x77, 0x85, 0x06, 0x41, + 0xff, 0xbb, 0x87, 0x42, 0x61, 0xbf, 0x07, 0x41, 0x6f, 0xbb, 0x86, 0x7f, + 0x7f, 0xbb, 0x96, 0x7f, 0xfe, 0x86, 0x86, 0x40, 0x80, 0x91, 0xc3, 0x40, + 0xd3, 0x7f, 0xe0, 0x7f, 0x13, 0x30, 0x05, 0x2f, 0x86, 0x6f, 0x80, 0x91, + 0x02, 0x2f, 0x96, 0x6f, 0x80, 0xb3, 0x60, 0x2f, 0x61, 0x25, 0x57, 0x40, + 0xc1, 0x91, 0xc1, 0x7f, 0x0f, 0x2f, 0x01, 0x30, 0x81, 0x43, 0x00, 0x2e, + 0xf2, 0x6f, 0x13, 0x40, 0x93, 0x42, 0x00, 0x2e, 0x13, 0x40, 0x93, 0x42, + 0x00, 0x2e, 0x00, 0x40, 0x80, 0x42, 0xbd, 0x80, 0xc0, 0x2e, 0x01, 0x42, + 0x70, 0x5f, 0x87, 0x83, 0x7a, 0x8d, 0x45, 0x40, 0x7b, 0x82, 0x45, 0x41, + 0x04, 0x41, 0xd5, 0xbf, 0x43, 0xbe, 0xc3, 0xba, 0xa5, 0x7f, 0x75, 0xba, + 0xb6, 0x7f, 0x05, 0x30, 0x97, 0x40, 0xc0, 0xb3, 0x09, 0x2f, 0x06, 0x40, + 0x47, 0x40, 0xb7, 0x05, 0x07, 0x30, 0x80, 0xa9, 0xfe, 0x05, 0xb7, 0x23, + 0x74, 0x0f, 0x5d, 0x23, 0xb6, 0x6f, 0x41, 0x82, 0x01, 0x80, 0x56, 0x0e, + 0xee, 0x2f, 0x40, 0x40, 0x28, 0x1a, 0xc4, 0x6f, 0xe0, 0x6f, 0xf2, 0x6f, + 0x02, 0x2f, 0x03, 0x30, 0x19, 0x2c, 0x03, 0x43, 0x05, 0x41, 0x6b, 0x29, + 0xa6, 0x6f, 0x05, 0x43, 0x6e, 0x0e, 0x11, 0x2f, 0xd4, 0x6f, 0x00, 0xb3, + 0x03, 0x2f, 0x3f, 0x89, 0xdc, 0x14, 0x27, 0x2e, 0x5e, 0xf0, 0x40, 0x25, + 0x32, 0x25, 0x15, 0x41, 0xd5, 0x42, 0x00, 0x2e, 0x15, 0x41, 0xd5, 0x42, + 0x00, 0x2e, 0x04, 0x41, 0xc4, 0x42, 0x00, 0x2e, 0x00, 0x2e, 0x41, 0x40, + 0x40, 0x90, 0x09, 0x2f, 0x11, 0x40, 0x91, 0x42, 0x00, 0x2e, 0x11, 0x40, + 0x91, 0x42, 0x00, 0x2e, 0x00, 0x40, 0x02, 0x2c, 0x80, 0x42, 0x43, 0x42, + 0x70, 0x5f, 0xb8, 0x2e, 0xb0, 0x50, 0x3a, 0x25, 0xf5, 0x86, 0x91, 0x58, + 0xc4, 0x42, 0x15, 0x30, 0x93, 0x58, 0x4d, 0x09, 0x81, 0x90, 0x64, 0x7f, + 0xf2, 0x7f, 0xeb, 0x7f, 0x02, 0x2f, 0x40, 0xb3, 0x90, 0x2e, 0x05, 0xb6, + 0x15, 0x0b, 0x00, 0xb3, 0x90, 0x2e, 0x05, 0xb6, 0x9a, 0x00, 0xe3, 0x30, + 0xcb, 0x08, 0x81, 0x40, 0x44, 0x84, 0xb1, 0xba, 0x46, 0x86, 0x49, 0x8e, + 0x97, 0x5c, 0xc2, 0x7f, 0x02, 0x84, 0x07, 0x25, 0xd3, 0x7f, 0x2b, 0x2e, + 0xa9, 0x00, 0x84, 0x40, 0xe3, 0x41, 0xe3, 0x04, 0xc4, 0x41, 0xc3, 0x43, + 0x2e, 0x18, 0x95, 0x5a, 0x8b, 0x40, 0x0b, 0x42, 0xb5, 0x00, 0x99, 0x5a, + 0xb2, 0x7f, 0x3a, 0x80, 0x95, 0x00, 0x05, 0x40, 0x41, 0x8b, 0x05, 0x42, + 0x03, 0x8a, 0xa2, 0x7f, 0x43, 0x84, 0x40, 0x41, 0x7b, 0x8b, 0x85, 0x7f, + 0x00, 0xb2, 0xdc, 0x05, 0x91, 0x7f, 0x04, 0x2f, 0xc3, 0x6f, 0x00, 0x2e, + 0xc4, 0x40, 0x01, 0x89, 0xc4, 0x42, 0x47, 0x86, 0x66, 0x41, 0x75, 0x7f, + 0x45, 0x88, 0x42, 0x82, 0x3e, 0x0f, 0x45, 0x41, 0x34, 0x2f, 0x46, 0x40, + 0x3e, 0x0e, 0x26, 0x2f, 0x85, 0x40, 0xc1, 0x33, 0xa9, 0x0e, 0x01, 0x30, + 0x02, 0x2f, 0xc3, 0x40, 0xc0, 0xb2, 0x1b, 0x2f, 0x82, 0x34, 0xaa, 0x0e, + 0x31, 0x2f, 0x01, 0x41, 0x7f, 0x82, 0x43, 0xa2, 0x02, 0x30, 0x02, 0x2f, + 0x00, 0x2e, 0x0c, 0x2c, 0x01, 0x30, 0x00, 0xb2, 0xd0, 0x6f, 0x11, 0x30, + 0x01, 0x2f, 0x02, 0x42, 0x02, 0x2d, 0x01, 0x42, 0x01, 0x30, 0xc0, 0x6f, + 0x00, 0x2e, 0x02, 0x42, 0x3e, 0x81, 0x04, 0x86, 0x02, 0x42, 0x02, 0x43, + 0xc2, 0x42, 0x19, 0x2d, 0xc0, 0x33, 0x80, 0x42, 0x16, 0x2d, 0xa0, 0x6f, + 0x28, 0x04, 0x38, 0x1e, 0x40, 0x42, 0x11, 0x30, 0x90, 0x6f, 0x22, 0x30, + 0x98, 0x2e, 0x08, 0xb6, 0x0c, 0x2c, 0x01, 0x30, 0xa1, 0x6f, 0xa9, 0x00, + 0x90, 0x6f, 0x01, 0x82, 0xba, 0x1c, 0x42, 0x42, 0x21, 0x30, 0x12, 0x30, + 0x98, 0x2e, 0x08, 0xb6, 0x01, 0x30, 0x72, 0x6f, 0xd4, 0xb1, 0xf5, 0xbd, + 0x6b, 0xba, 0x9f, 0x5a, 0x80, 0x40, 0x05, 0x18, 0xf5, 0xbe, 0xe3, 0x0a, + 0xeb, 0xbb, 0x3d, 0x0b, 0x80, 0x6f, 0xe3, 0x00, 0x04, 0x40, 0x63, 0x05, + 0xa1, 0x58, 0x2c, 0x18, 0xf5, 0xbe, 0x83, 0x42, 0xeb, 0xbb, 0xfd, 0x0b, + 0xb2, 0x6f, 0x5a, 0x01, 0xdf, 0x01, 0x7d, 0x1f, 0x15, 0x42, 0x9a, 0x04, + 0x05, 0x40, 0x5d, 0x05, 0x2c, 0x18, 0x75, 0xbe, 0xeb, 0xba, 0x2c, 0x0b, + 0xdc, 0x04, 0x9a, 0x1c, 0x02, 0x42, 0x04, 0x80, 0x00, 0x2e, 0x00, 0x40, + 0x00, 0xb2, 0x10, 0x2f, 0xc2, 0x6f, 0xc0, 0x33, 0x82, 0x40, 0x90, 0x0e, + 0x0b, 0x2f, 0xd1, 0x6f, 0x7e, 0x88, 0x03, 0x81, 0x3c, 0x84, 0x0b, 0x30, + 0x82, 0x86, 0x4b, 0x42, 0x0b, 0x42, 0x0b, 0x43, 0x8b, 0x42, 0xcb, 0x42, + 0x21, 0x30, 0x42, 0xb2, 0x02, 0x30, 0x9d, 0x50, 0x02, 0x22, 0x41, 0xb2, + 0x9b, 0x52, 0x08, 0x22, 0xf1, 0x6f, 0x40, 0x90, 0x11, 0x30, 0x06, 0x2f, + 0x22, 0x30, 0x02, 0x08, 0x00, 0xb2, 0x08, 0x2f, 0x23, 0x2e, 0x5e, 0xf0, + 0x06, 0x2d, 0x01, 0x08, 0x00, 0xb2, 0x02, 0x2f, 0x00, 0x31, 0x21, 0x2e, + 0x5e, 0xf0, 0xeb, 0x6f, 0x50, 0x5f, 0xb8, 0x2e, 0x07, 0x86, 0xfc, 0x88, + 0xc6, 0x40, 0x05, 0x41, 0x31, 0x1a, 0x12, 0x2f, 0x80, 0x91, 0x22, 0x2f, + 0xc1, 0x33, 0x29, 0x0f, 0x0a, 0x2f, 0x06, 0x80, 0x00, 0x2e, 0x00, 0x40, + 0x00, 0xb2, 0x01, 0x2f, 0x44, 0xa9, 0x03, 0x2f, 0x00, 0x30, 0xc0, 0x42, + 0x00, 0x43, 0xb8, 0x2e, 0xc2, 0x42, 0x01, 0x43, 0xb8, 0x2e, 0xc1, 0x33, + 0xa9, 0x0e, 0x0e, 0x2f, 0x43, 0x3c, 0xeb, 0x00, 0xcc, 0xa8, 0x0a, 0x2f, + 0x05, 0x86, 0xc2, 0x80, 0xc3, 0x40, 0x02, 0x42, 0x3c, 0x84, 0xc1, 0x80, + 0x81, 0x42, 0x82, 0x84, 0xc0, 0x2e, 0x80, 0x42, 0x00, 0x2e, 0xb8, 0x2e, + 0x05, 0x2e, 0x20, 0x01, 0x11, 0x30, 0x20, 0x50, 0x91, 0x08, 0xf0, 0x7f, + 0x80, 0xb2, 0xeb, 0x7f, 0x13, 0x2f, 0x01, 0x2e, 0x74, 0x00, 0x01, 0x90, + 0x02, 0x30, 0xa3, 0x50, 0x03, 0x2f, 0x25, 0x2e, 0x74, 0x00, 0x98, 0x2e, + 0xad, 0xb7, 0xf2, 0x6f, 0xa3, 0x52, 0x98, 0x2e, 0x57, 0xb6, 0x00, 0xb2, + 0x06, 0x2f, 0x80, 0x30, 0x21, 0x2e, 0x5e, 0xf0, 0x03, 0x2d, 0x10, 0x30, + 0x21, 0x2e, 0x74, 0x00, 0xeb, 0x6f, 0xe0, 0x5f, 0xb8, 0x2e, 0x30, 0x51, + 0x42, 0x8a, 0xe1, 0x7f, 0x83, 0x88, 0xdb, 0x7f, 0xc5, 0x7f, 0x1a, 0x25, + 0x05, 0x25, 0x93, 0x40, 0x06, 0x40, 0xb3, 0x01, 0x16, 0x42, 0xcb, 0x16, + 0x06, 0x40, 0xf3, 0x02, 0x13, 0x42, 0x54, 0x0e, 0xf5, 0x2f, 0x04, 0x40, + 0x12, 0x30, 0xa2, 0x28, 0x02, 0x42, 0x88, 0xa0, 0x00, 0x30, 0x90, 0x2e, + 0xa9, 0xb7, 0x6d, 0x84, 0x73, 0x88, 0x92, 0x7f, 0x70, 0x7f, 0x84, 0x7f, + 0xa2, 0x7f, 0x70, 0x86, 0xb5, 0x7f, 0x63, 0x7f, 0x75, 0x30, 0xa5, 0x52, + 0xa7, 0x54, 0xbd, 0x50, 0xaf, 0x58, 0xb7, 0x6f, 0xf4, 0x7f, 0x51, 0x7f, + 0x00, 0x2e, 0xd6, 0x41, 0xd4, 0x41, 0xb7, 0x7f, 0xcc, 0x17, 0x7d, 0x09, + 0x75, 0x01, 0x06, 0x30, 0x26, 0x03, 0x4d, 0xbe, 0xd3, 0xba, 0x6c, 0x0b, + 0x28, 0x0e, 0x05, 0x22, 0x2a, 0x0f, 0x90, 0x22, 0xd2, 0x42, 0x43, 0x7f, + 0x32, 0x7f, 0x00, 0x2e, 0xa9, 0x5a, 0xab, 0x58, 0xad, 0x5c, 0xa9, 0x56, + 0x98, 0x2e, 0x38, 0xb1, 0x91, 0x6f, 0x32, 0x6f, 0x50, 0x42, 0x91, 0x7f, + 0xb3, 0x30, 0x10, 0x25, 0x98, 0x2e, 0xdb, 0xb7, 0x71, 0x6f, 0x88, 0x28, + 0x43, 0x6f, 0x80, 0x6f, 0x72, 0x7f, 0x58, 0x0e, 0x51, 0x6f, 0x44, 0x82, + 0xa7, 0x54, 0xbd, 0x50, 0x75, 0x30, 0xaf, 0x58, 0xcd, 0x2f, 0xb1, 0x6f, + 0x46, 0x84, 0xe1, 0x6f, 0x4e, 0x80, 0x81, 0x40, 0xb2, 0x7f, 0x90, 0x7f, + 0x12, 0x30, 0x98, 0x2e, 0xcc, 0xb7, 0xb1, 0x6f, 0x7c, 0x8a, 0xa2, 0x6f, + 0xb5, 0x7f, 0x40, 0x42, 0x98, 0x2e, 0xf4, 0x01, 0x95, 0xbc, 0x0b, 0xb9, + 0x51, 0x0a, 0x62, 0x6f, 0xa1, 0x7f, 0x98, 0x2e, 0xf4, 0x01, 0x95, 0xbc, + 0x0b, 0xb9, 0x11, 0x0a, 0xa1, 0x6f, 0x49, 0x17, 0x48, 0x18, 0x88, 0x16, + 0xe8, 0x18, 0xd1, 0x18, 0x27, 0x25, 0x16, 0x25, 0x80, 0x7f, 0x98, 0x2e, + 0xbe, 0x00, 0xb5, 0x6f, 0xe1, 0x6f, 0x43, 0x41, 0x4b, 0x84, 0x4c, 0x8c, + 0xb0, 0x7f, 0x62, 0x7f, 0x4a, 0x88, 0x7e, 0x8b, 0xc0, 0x90, 0x56, 0x7f, + 0x13, 0x2f, 0x45, 0x7f, 0x34, 0x7f, 0xb3, 0x30, 0xb1, 0x52, 0xb2, 0x6f, + 0x98, 0x2e, 0xdb, 0xb7, 0x71, 0x6f, 0x88, 0x0e, 0x34, 0x6f, 0x45, 0x6f, + 0xe1, 0x6f, 0x06, 0x2f, 0x34, 0x25, 0x1b, 0x30, 0x10, 0x6f, 0x22, 0x6f, + 0xdb, 0x42, 0xd0, 0x42, 0xc2, 0x42, 0x02, 0x30, 0x00, 0x6f, 0x00, 0xa8, + 0x90, 0x05, 0x13, 0x6f, 0x86, 0x23, 0xc0, 0xa8, 0xd3, 0x05, 0xdf, 0x23, + 0xb7, 0x05, 0xb3, 0x5e, 0x37, 0x0f, 0x4d, 0x8c, 0x07, 0x30, 0x19, 0x2f, + 0x44, 0x7f, 0x00, 0x2e, 0x24, 0x6f, 0xb3, 0x5e, 0xa7, 0x0e, 0x44, 0x6f, + 0x07, 0x30, 0x11, 0x2f, 0xc7, 0x5e, 0xdf, 0x00, 0xc1, 0x5e, 0x5f, 0x0e, + 0x02, 0x2f, 0x00, 0x2e, 0x0b, 0x2c, 0x07, 0x30, 0xc9, 0x56, 0x03, 0x00, + 0xc3, 0x56, 0x43, 0x0e, 0x02, 0x2f, 0x00, 0x2e, 0x03, 0x2c, 0x07, 0x30, + 0x82, 0x43, 0x17, 0x30, 0x41, 0x86, 0xc0, 0x91, 0x0e, 0x2f, 0xc0, 0x40, + 0x01, 0x90, 0x09, 0x2f, 0x80, 0x41, 0x14, 0x30, 0x04, 0x28, 0x80, 0x43, + 0x06, 0xa0, 0x03, 0x2f, 0xc8, 0x80, 0xbb, 0x58, 0xc2, 0x42, 0x04, 0x42, + 0x66, 0x2c, 0x00, 0x30, 0x90, 0x6f, 0x00, 0x2e, 0x00, 0x40, 0x00, 0xa8, + 0x00, 0x30, 0x5e, 0x2f, 0x00, 0x41, 0x00, 0xb2, 0x00, 0x30, 0x5a, 0x2f, + 0x49, 0x82, 0xb2, 0x6f, 0x43, 0x7f, 0xb5, 0x7f, 0x94, 0x7f, 0xb3, 0x30, + 0x41, 0x40, 0x98, 0x2e, 0xdb, 0xb7, 0x71, 0x6f, 0x88, 0x0f, 0xb5, 0x6f, + 0xe1, 0x6f, 0x02, 0x30, 0x00, 0x30, 0x4a, 0x2f, 0x80, 0x6f, 0xc5, 0x58, + 0x04, 0x00, 0xbf, 0x58, 0x44, 0x0e, 0x02, 0x2f, 0x00, 0x2e, 0x43, 0x2c, + 0x00, 0x30, 0xa0, 0x6f, 0xb5, 0x58, 0x84, 0x0e, 0x00, 0x30, 0x3c, 0x2f, + 0xb7, 0x54, 0x21, 0x6f, 0xb5, 0x7f, 0x98, 0x2e, 0xcc, 0xb7, 0x10, 0x25, + 0xb3, 0x30, 0x21, 0x25, 0x98, 0x2e, 0xdb, 0xb7, 0x02, 0x6f, 0xa0, 0x7f, + 0xb3, 0x30, 0x12, 0x25, 0x98, 0x2e, 0xdb, 0xb7, 0x12, 0x6f, 0x80, 0x7f, + 0xb3, 0x30, 0x12, 0x25, 0x98, 0x2e, 0xdb, 0xb7, 0x81, 0x6f, 0x88, 0x28, + 0x87, 0x52, 0x98, 0x2e, 0xcc, 0xb7, 0xa1, 0x6f, 0x88, 0x0f, 0xb5, 0x6f, + 0xe1, 0x6f, 0x02, 0x30, 0x00, 0x30, 0x1a, 0x2f, 0x44, 0x6f, 0x00, 0x2e, + 0x00, 0x41, 0x00, 0xb2, 0x0f, 0x2f, 0x64, 0x6f, 0x10, 0x6f, 0x04, 0x41, + 0x84, 0x0e, 0x00, 0x30, 0x0f, 0x2f, 0x54, 0x6f, 0x20, 0x6f, 0x04, 0x41, + 0x84, 0x0f, 0x00, 0x30, 0x09, 0x2f, 0x94, 0x6f, 0x10, 0x30, 0x07, 0x2c, + 0x02, 0x43, 0x08, 0x87, 0xb9, 0x50, 0xd0, 0x42, 0x10, 0x30, 0x00, 0x43, + 0xc2, 0x42, 0x0b, 0x30, 0x4b, 0x43, 0x7a, 0x8b, 0xc4, 0x6f, 0x06, 0x89, + 0x52, 0x43, 0x52, 0x43, 0x6c, 0x0e, 0xfb, 0x2f, 0x78, 0x85, 0x00, 0x2e, + 0x82, 0x40, 0x02, 0x1a, 0x02, 0x2f, 0x00, 0x2e, 0x02, 0x2c, 0x40, 0x42, + 0x00, 0x30, 0x00, 0x2e, 0xdb, 0x6f, 0xd0, 0x5e, 0xb8, 0x2e, 0x08, 0x82, + 0x02, 0x30, 0x12, 0x42, 0x08, 0x86, 0xc2, 0x88, 0x87, 0x5a, 0x12, 0x43, + 0x05, 0x43, 0x02, 0x8b, 0x7c, 0x8d, 0x42, 0x43, 0x14, 0x30, 0xbe, 0x8b, + 0x04, 0x42, 0x45, 0x81, 0x42, 0x43, 0x02, 0x42, 0x35, 0x80, 0xb9, 0x5e, + 0xa5, 0x5a, 0xc7, 0x42, 0x84, 0x43, 0x52, 0x43, 0x12, 0x42, 0x52, 0x43, + 0x12, 0x42, 0x52, 0x43, 0x52, 0x43, 0x41, 0x0e, 0xf7, 0x2f, 0xb8, 0x2e, + 0x0a, 0x0c, 0x55, 0x56, 0x03, 0x09, 0x0a, 0x04, 0x00, 0xb3, 0x07, 0x2f, + 0x88, 0x0c, 0x93, 0x08, 0x80, 0xb2, 0x03, 0x2f, 0x53, 0x50, 0xc0, 0x2e, + 0x40, 0xac, 0x03, 0x22, 0xb8, 0x2e, 0xff, 0x88, 0x10, 0x30, 0x4a, 0x0d, + 0x0a, 0x18, 0x04, 0x15, 0x4c, 0x16, 0x5f, 0xb9, 0x79, 0x08, 0x53, 0x5a, + 0x95, 0x00, 0x34, 0x09, 0x40, 0x90, 0x02, 0x2f, 0x00, 0x91, 0x00, 0x2f, + 0x00, 0x30, 0xd8, 0x00, 0xc0, 0xb2, 0x0b, 0x2f, 0xd0, 0xa0, 0x03, 0x2f, + 0xf0, 0x86, 0xbb, 0x11, 0x07, 0x2c, 0xce, 0x17, 0x01, 0x31, 0x4b, 0x04, + 0x79, 0x14, 0x33, 0x12, 0xfb, 0x11, 0x81, 0x0b, 0xce, 0x16, 0xc0, 0x2e, + 0x7b, 0x1a, 0x16, 0x22, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00 +}; + const uint8_t bma423_config_file[] = { 0x80, 0x2e, 0xfe, 0x00, 0x80, 0x2e, 0xf1, 0x01, 0xc8, 0x2e, 0x00, 0x2e, 0x80, 0x2e, 0xfc, 0x00, 0x80, 0x2e, 0xfb, 0x00, 0x80, 0x2e, 0xff, 0x00, 0x80, 0x2e, 0xfd, 0x00, 0x80, 0x2e, 0x42, 0xb0, 0x50, 0x39, 0x21, 0x2e, 0xb0, 0xf0, @@ -450,7 +965,7 @@ int8_t bma423_init(struct bma4_dev *dev) rslt = bma4_init(dev); if (rslt == BMA4_OK) { - if (dev->chip_id == BMA423_CHIP_ID) + if (dev->chip_id == BMA423_CHIP_ID || dev->chip_id == BMA425_CHIP_ID) { /* Resolution of BMA423 sensor is 12 bit */ dev->resolution = 12; @@ -478,7 +993,7 @@ int8_t bma423_write_config_file(struct bma4_dev *dev) if (dev != NULL) { - if (dev->chip_id == BMA423_CHIP_ID) + if (dev->chip_id == BMA423_CHIP_ID || dev->chip_id == BMA425_CHIP_ID) { /* Configuration stream read/write length boundary * check @@ -492,7 +1007,10 @@ int8_t bma423_write_config_file(struct bma4_dev *dev) } /*Assign stream data */ - dev->config_file_ptr = bma423_config_file; + if(dev->chip_id == BMA423_CHIP_ID) + dev->config_file_ptr = bma423_config_file; + else if(dev->chip_id == BMA425_CHIP_ID) + dev->config_file_ptr = bma425_config_file; rslt = bma4_write_config_file(dev); } else @@ -526,7 +1044,7 @@ int8_t bma423_get_config_id(uint16_t *config_id, struct bma4_dev *dev) if (dev != NULL) { - if (dev->chip_id == BMA423_CHIP_ID) + if (dev->chip_id == BMA423_CHIP_ID || dev->chip_id == BMA425_CHIP_ID) { rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_FEATURE_SIZE, dev); if (rslt == BMA4_OK) @@ -559,7 +1077,7 @@ int8_t bma423_map_interrupt(uint8_t int_line, uint16_t int_map, uint8_t enable, if (dev != NULL) { - if (dev->chip_id == BMA423_CHIP_ID) + if (dev->chip_id == BMA423_CHIP_ID || dev->chip_id == BMA425_CHIP_ID) { if (int_line <= 1) { @@ -593,7 +1111,7 @@ int8_t bma423_read_int_status(uint16_t *int_status, struct bma4_dev *dev) if (dev != NULL) { - if (dev->chip_id == BMA423_CHIP_ID) + if (dev->chip_id == BMA423_CHIP_ID || dev->chip_id == BMA425_CHIP_ID) { /* Read the interrupt status */ rslt = bma4_read_int_status(int_status, dev); @@ -622,7 +1140,7 @@ int8_t bma423_feature_enable(uint8_t feature, uint8_t enable, struct bma4_dev *d if (dev != NULL) { - if (dev->chip_id == BMA423_CHIP_ID) + if (dev->chip_id == BMA423_CHIP_ID || dev->chip_id == BMA425_CHIP_ID) { /* Read feature configuration data */ rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, len, dev); @@ -669,7 +1187,7 @@ int8_t bma423_set_remap_axes(const struct bma423_axes_remap *remap_data, struct if (dev != NULL) { - if (dev->chip_id == BMA423_CHIP_ID) + if (dev->chip_id == BMA423_CHIP_ID || dev->chip_id == BMA425_CHIP_ID) { rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_FEATURE_SIZE, dev); if (rslt == BMA4_OK) @@ -708,7 +1226,7 @@ int8_t bma423_get_remap_axes(struct bma423_axes_remap *remap_data, struct bma4_d if (dev != NULL) { - if (dev->chip_id == BMA423_CHIP_ID) + if (dev->chip_id == BMA423_CHIP_ID || dev->chip_id == BMA425_CHIP_ID) { rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_FEATURE_SIZE, dev); if (rslt == BMA4_OK) @@ -997,7 +1515,7 @@ int8_t bma423_step_detector_enable(uint8_t enable, struct bma4_dev *dev) if (dev != NULL) { - if (dev->chip_id == BMA423_CHIP_ID) + if (dev->chip_id == BMA423_CHIP_ID || dev->chip_id == BMA425_CHIP_ID) { rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_FEATURE_SIZE, dev); if (rslt == BMA4_OK) @@ -1034,7 +1552,7 @@ int8_t bma423_step_counter_set_watermark(uint16_t step_counter_wm, struct bma4_d if (dev != NULL) { - if (dev->chip_id == BMA423_CHIP_ID) + if (dev->chip_id == BMA423_CHIP_ID || dev->chip_id == BMA425_CHIP_ID) { rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_FEATURE_SIZE, dev); if (rslt == BMA4_OK) @@ -1088,7 +1606,7 @@ int8_t bma423_step_counter_get_watermark(uint16_t *step_counter_wm, struct bma4_ if (dev != NULL) { - if (dev->chip_id == BMA423_CHIP_ID) + if (dev->chip_id == BMA423_CHIP_ID || dev->chip_id == BMA425_CHIP_ID) { rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_FEATURE_SIZE, dev); if (rslt == BMA4_OK) @@ -1125,7 +1643,7 @@ int8_t bma423_reset_step_counter(struct bma4_dev *dev) if (dev != NULL) { - if (dev->chip_id == BMA423_CHIP_ID) + if (dev->chip_id == BMA423_CHIP_ID || dev->chip_id == BMA425_CHIP_ID) { rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_FEATURE_SIZE, dev); if (rslt == BMA4_OK) @@ -1162,7 +1680,7 @@ int8_t bma423_step_counter_output(uint32_t *step_count, struct bma4_dev *dev) if (dev != NULL) { - if (dev->chip_id == BMA423_CHIP_ID) + if (dev->chip_id == BMA423_CHIP_ID || dev->chip_id == BMA425_CHIP_ID) { /* Reads the step counter output data from the * gpio register @@ -1200,7 +1718,7 @@ int8_t bma423_activity_output(uint8_t *activity, struct bma4_dev *dev) if (dev != NULL) { - if (dev->chip_id == BMA423_CHIP_ID) + if (dev->chip_id == BMA423_CHIP_ID || dev->chip_id == BMA425_CHIP_ID) { /* Reads the activity output from the gpio register */ rslt = bma4_read_regs(BMA4_ACTIVITY_OUT_ADDR, &data, 1, dev); @@ -1234,7 +1752,7 @@ int8_t bma423_stepcounter_get_parameter(struct bma423_stepcounter_settings *sett if (dev != NULL) { - if (dev->chip_id == BMA423_CHIP_ID) + if (dev->chip_id == BMA423_CHIP_ID || dev->chip_id == BMA425_CHIP_ID) { rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_FEATURE_SIZE, dev); if (rslt == BMA4_OK) @@ -1269,7 +1787,7 @@ int8_t bma423_stepcounter_set_parameter(const struct bma423_stepcounter_settings if (dev != NULL) { - if (dev->chip_id == BMA423_CHIP_ID) + if (dev->chip_id == BMA423_CHIP_ID || dev->chip_id == BMA425_CHIP_ID) { rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_FEATURE_SIZE, dev); if (rslt == BMA4_OK) @@ -1306,7 +1824,7 @@ int8_t bma423_single_tap_set_sensitivity(uint8_t sensitivity, struct bma4_dev *d if (dev != NULL) { - if (dev->chip_id == BMA423_CHIP_ID) + if (dev->chip_id == BMA423_CHIP_ID || dev->chip_id == BMA425_CHIP_ID) { rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_FEATURE_SIZE, dev); if (rslt == BMA4_OK) @@ -1341,7 +1859,7 @@ int8_t bma423_double_tap_set_sensitivity(uint8_t sensitivity, struct bma4_dev *d if (dev != NULL) { - if (dev->chip_id == BMA423_CHIP_ID) + if (dev->chip_id == BMA423_CHIP_ID || dev->chip_id == BMA425_CHIP_ID) { rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_FEATURE_SIZE, dev); if (rslt == BMA4_OK) @@ -1376,7 +1894,7 @@ int8_t bma423_single_tap_get_sensitivity(uint8_t *sensitivity, struct bma4_dev * if (dev != NULL) { - if (dev->chip_id == BMA423_CHIP_ID) + if (dev->chip_id == BMA423_CHIP_ID || dev->chip_id == BMA425_CHIP_ID) { rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_FEATURE_SIZE, dev); if (rslt == BMA4_OK) @@ -1409,7 +1927,7 @@ int8_t bma423_double_tap_get_sensitivity(uint8_t *sensitivity, struct bma4_dev * if (dev != NULL) { - if (dev->chip_id == BMA423_CHIP_ID) + if (dev->chip_id == BMA423_CHIP_ID || dev->chip_id == BMA425_CHIP_ID) { rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_FEATURE_SIZE, dev); if (rslt == BMA4_OK) diff --git a/src/drivers/Bma421_C/bma423.h b/src/drivers/Bma421_C/bma423.h index 96e5d8e3..b58e0d21 100644 --- a/src/drivers/Bma421_C/bma423.h +++ b/src/drivers/Bma421_C/bma423.h @@ -52,6 +52,7 @@ extern "C" { /**\name Chip ID of BMA423 sensor */ #define BMA423_CHIP_ID UINT8_C(0x11) +#define BMA425_CHIP_ID UINT8_C(0x13) /**\ Configuration ID start position of BMA423 sensor */ #define BMA423_CONFIG_ID_START_ADDR UINT8_C(66) diff --git a/src/drivers/St7789.cpp b/src/drivers/St7789.cpp index 39218e77..0f1dc02e 100644 --- a/src/drivers/St7789.cpp +++ b/src/drivers/St7789.cpp @@ -140,8 +140,9 @@ void St7789::Uninit() { } void St7789::DrawPixel(uint16_t x, uint16_t y, uint32_t color) { - if ((x < 0) || (x >= Width) || (y < 0) || (y >= Height)) + if (x >= Width || y >= Height) { return; + } SetAddrWindow(x, y, x + 1, y + 1); diff --git a/src/libs/littlefs b/src/libs/littlefs new file mode 160000 +Subproject ead50807f1ca3fdf2da00b77a0ce02651ded2d1 diff --git a/src/libs/lv_conf.h b/src/libs/lv_conf.h index 761baba2..73109c5a 100644 --- a/src/libs/lv_conf.h +++ b/src/libs/lv_conf.h @@ -42,7 +42,7 @@ /* Default display refresh period. * Can be changed in the display driver (`lv_disp_drv_t`).*/ -#define LV_DISP_DEF_REFR_PERIOD 30 /*[ms]*/ +#define LV_DISP_DEF_REFR_PERIOD 20 /*[ms]*/ /* Dot Per Inch: used to initialize default sizes. * E.g. a button with width = LV_DPI / 2 -> half inch wide @@ -112,7 +112,7 @@ typedef int16_t lv_coord_t; * Can be changed in the Input device driver (`lv_indev_drv_t`)*/ /* Input device read period in milliseconds */ -#define LV_INDEV_DEF_READ_PERIOD 30 +#define LV_INDEV_DEF_READ_PERIOD 20 /* Drag threshold in pixels */ #define LV_INDEV_DEF_DRAG_LIMIT 10 @@ -128,7 +128,6 @@ typedef int16_t lv_coord_t; * Time between `LV_EVENT_LONG_PRESSED_REPEAT */ #define LV_INDEV_DEF_LONG_PRESS_REP_TIME 100 - /* Gesture threshold in pixels */ #define LV_INDEV_DEF_GESTURE_LIMIT 50 @@ -204,7 +203,7 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h" */ /* 1: Enable file system (might be required for images */ // TODO: Enable FS -#define LV_USE_FILESYSTEM 0 +#define LV_USE_FILESYSTEM 1 #if LV_USE_FILESYSTEM /*Declare the type of the user data of file system drivers (can be e.g. `void *`, `int`, `struct`)*/ typedef void * lv_fs_drv_user_data_t; @@ -236,7 +235,7 @@ typedef void * lv_fs_drv_user_data_t; * With complex image decoders (e.g. PNG or JPG) caching can save the continuous open/decode of images. * However the opened images might consume additional RAM. * LV_IMG_CACHE_DEF_SIZE must be >= 1 */ -#define LV_IMG_CACHE_DEF_SIZE 1 +#define LV_IMG_CACHE_DEF_SIZE 6 /*Declare the type of the user data of image decoder (can be e.g. `void *`, `int`, `struct`)*/ typedef void* lv_img_decoder_user_data_t; @@ -293,10 +292,11 @@ typedef void* lv_img_decoder_user_data_t; /* 1: use a custom tick source. * It removes the need to manually update the tick with `lv_tick_inc`) */ -#define LV_TICK_CUSTOM 0 +#define LV_TICK_CUSTOM 1 #if LV_TICK_CUSTOM == 1 -#define LV_TICK_CUSTOM_INCLUDE "Arduino.h" /*Header for the system time function*/ -#define LV_TICK_CUSTOM_SYS_TIME_EXPR (millis()) /*Expression evaluating to current system time in ms*/ +#define LV_TICK_CUSTOM_INCLUDE "FreeRTOS.h" /*Header for the system time function*/ +uint32_t xTaskGetTickCount(); /*Forward declare to avoid compiler warning*/ +#define LV_TICK_CUSTOM_SYS_TIME_EXPR (xTaskGetTickCount()) /*Expression evaluating to current system time in ms*/ #endif /*LV_TICK_CUSTOM*/ typedef void* lv_disp_drv_user_data_t; /*Type of user data in the display driver*/ @@ -417,6 +417,7 @@ typedef void* lv_indev_drv_user_data_t; /*Type of user data in the in LV_FONT_DECLARE(jetbrains_mono_extrabold_compressed) \ LV_FONT_DECLARE(jetbrains_mono_42) \ LV_FONT_DECLARE(jetbrains_mono_76) \ + LV_FONT_DECLARE(open_sans_light) \ LV_FONT_DECLARE(lv_font_sys_48) /* Enable it if you have fonts with a lot of characters. @@ -758,4 +759,4 @@ typedef void* lv_obj_user_data_t; /*--END OF LV_CONF_H--*/ -#endif /*LV_CONF_H*/
\ No newline at end of file +#endif /*LV_CONF_H*/ diff --git a/src/main.cpp b/src/main.cpp index 4c2c5de8..ffbba5e7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -28,12 +28,14 @@ #include <drivers/Hrs3300.h> #include <drivers/Bma421.h> +#include "BootloaderVersion.h" #include "components/battery/BatteryController.h" #include "components/ble/BleController.h" #include "components/ble/NotificationManager.h" #include "components/motor/MotorController.h" #include "components/datetime/DateTimeController.h" #include "components/heartrate/HeartRateController.h" +#include "components/fs/FS.h" #include "drivers/Spi.h" #include "drivers/SpiMaster.h" #include "drivers/SpiNorFlash.h" @@ -107,10 +109,6 @@ void ble_manager_set_ble_disconnection_callback(void (*disconnection)()); static constexpr uint8_t pinTouchIrq = 28; static constexpr uint8_t pinPowerPresentIrq = 19; -Pinetime::Controllers::Settings settingsController {spiNorFlash}; - -Pinetime::Controllers::MotorController motorController {settingsController}; - Pinetime::Controllers::HeartRateController heartRateController; Pinetime::Applications::HeartRateTask heartRateApp(heartRateSensor, heartRateController); @@ -121,6 +119,11 @@ Pinetime::Controllers::NotificationManager notificationManager; Pinetime::Controllers::MotionController motionController; Pinetime::Controllers::TimerController timerController; +Pinetime::Controllers::FS fs {spiNorFlash}; +Pinetime::Controllers::Settings settingsController {fs}; +Pinetime::Controllers::MotorController motorController {settingsController}; + + Pinetime::Applications::DisplayApp displayApp(lcd, lvgl, touchPanel, @@ -154,7 +157,8 @@ Pinetime::System::SystemTask systemTask(spi, settingsController, heartRateController, displayApp, - heartRateApp); + heartRateApp, + fs); void nrfx_gpiote_evt_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action) { if (pin == pinTouchIrq) { @@ -174,13 +178,6 @@ void nrfx_gpiote_evt_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action portYIELD_FROM_ISR(xHigherPriorityTaskWoken); } -extern "C" { -void vApplicationIdleHook(void) { - if (!isFactory) - lv_tick_inc(1); -} -} - void DebounceTimerChargeCallback(TimerHandle_t xTimer) { xTimerStop(xTimer, 0); systemTask.PushMessage(Pinetime::System::Messages::OnChargingEvent); @@ -306,6 +303,9 @@ int main(void) { debounceTimer = xTimerCreate("debounceTimer", 200, pdFALSE, (void*) 0, DebounceTimerCallback); debounceChargeTimer = xTimerCreate("debounceTimerCharge", 200, pdFALSE, (void*) 0, DebounceTimerChargeCallback); + // retrieve version stored by bootloader + Pinetime::BootloaderVersion::SetVersion(NRF_TIMER2->CC[0]); + lvgl.Init(); systemTask.Start(); diff --git a/src/systemtask/SystemTask.cpp b/src/systemtask/SystemTask.cpp index 38e9793c..8915ce74 100644 --- a/src/systemtask/SystemTask.cpp +++ b/src/systemtask/SystemTask.cpp @@ -33,6 +33,13 @@ namespace { } } +void DimTimerCallback(TimerHandle_t xTimer) { + + NRF_LOG_INFO("DimTimerCallback"); + auto sysTask = static_cast<SystemTask*>(pvTimerGetTimerID(xTimer)); + sysTask->OnDim(); +} + void IdleTimerCallback(TimerHandle_t xTimer) { NRF_LOG_INFO("IdleTimerCallback"); @@ -59,7 +66,8 @@ SystemTask::SystemTask(Drivers::SpiMaster& spi, Controllers::Settings& settingsController, Pinetime::Controllers::HeartRateController& heartRateController, Pinetime::Applications::DisplayApp& displayApp, - Pinetime::Applications::HeartRateTask& heartRateApp) + Pinetime::Applications::HeartRateTask& heartRateApp, + Pinetime::Controllers::FS& fs) : spi {spi}, lcd {lcd}, spiNorFlash {spiNorFlash}, @@ -77,10 +85,11 @@ SystemTask::SystemTask(Drivers::SpiMaster& spi, motionSensor {motionSensor}, settingsController {settingsController}, heartRateController{heartRateController}, - nimbleController(*this, bleController, dateTimeController, notificationManager, batteryController, spiNorFlash, heartRateController), motionController{motionController}, displayApp{displayApp}, - heartRateApp(heartRateApp) { + heartRateApp(heartRateApp), + fs{fs}, + nimbleController(*this, bleController, dateTimeController, notificationManager, batteryController, spiNorFlash, heartRateController) { } @@ -103,13 +112,15 @@ void SystemTask::Work() { APP_GPIOTE_INIT(2); app_timer_init(); - + spi.Init(); spiNorFlash.Init(); spiNorFlash.Wakeup(); + + fs.Init(); + nimbleController.Init(); nimbleController.StartAdvertising(); - brightnessController.Init(); lcd.Init(); twiMaster.Init(); @@ -126,6 +137,7 @@ void SystemTask::Work() { twiMaster.Init(); motionSensor.Init(); + motionController.Init(motionSensor.DeviceType()); settingsController.Init(); displayApp.Register(this); @@ -173,8 +185,9 @@ void SystemTask::Work() { nrf_gpio_cfg_sense_input(pinPowerPresentIrq, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_SENSE_HIGH); } - idleTimer = xTimerCreate("idleTimer", pdMS_TO_TICKS(settingsController.GetScreenTimeOut()), pdFALSE, this, IdleTimerCallback); - xTimerStart(idleTimer, 0); + idleTimer = xTimerCreate("idleTimer", pdMS_TO_TICKS(2000), pdFALSE, this, IdleTimerCallback); + dimTimer = xTimerCreate("dimTimer", pdMS_TO_TICKS(settingsController.GetScreenTimeOut() - 2000), pdFALSE, this, DimTimerCallback); + xTimerStart(dimTimer, 0); // Suppress endless loop diagnostic #pragma clang diagnostic push @@ -192,25 +205,29 @@ void SystemTask::Work() { Messages message = static_cast<Messages>(msg); switch (message) { case Messages::EnableSleeping: - doNotGoToSleep = false; + // Make sure that exiting an app doesn't enable sleeping, + // if the exiting was caused by a firmware update + if (!bleController.IsFirmwareUpdating()) { + doNotGoToSleep = false; + } break; case Messages::DisableSleeping: doNotGoToSleep = true; break; case Messages::UpdateTimeOut: - xTimerChangePeriod(idleTimer, pdMS_TO_TICKS(settingsController.GetScreenTimeOut()), 0); + xTimerChangePeriod(dimTimer, pdMS_TO_TICKS(settingsController.GetScreenTimeOut() - 2000), 0); break; case Messages::GoToRunning: spi.Wakeup(); twiMaster.Wakeup(); // Double Tap needs the touch screen to be in normal mode - if (settingsController.getWakeUpMode() != Pinetime::Controllers::Settings::WakeUpMode::DoubleTap) { + if (!settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::DoubleTap)) { touchPanel.Wakeup(); } nimbleController.StartAdvertising(); - xTimerStart(idleTimer, 0); + xTimerStart(dimTimer, 0); spiNorFlash.Wakeup(); lcd.Wakeup(); @@ -220,15 +237,16 @@ void SystemTask::Work() { isSleeping = false; isWakingUp = false; + isDimmed = false; break; case Messages::TouchWakeUp: { twiMaster.Wakeup(); auto touchInfo = touchPanel.GetTouchInfo(); twiMaster.Sleep(); if (touchInfo.isTouch and ((touchInfo.gesture == Pinetime::Drivers::Cst816S::Gestures::DoubleTap and - settingsController.getWakeUpMode() == Pinetime::Controllers::Settings::WakeUpMode::DoubleTap) or + settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::DoubleTap)) or (touchInfo.gesture == Pinetime::Drivers::Cst816S::Gestures::SingleTap and - settingsController.getWakeUpMode() == Pinetime::Controllers::Settings::WakeUpMode::SingleTap))) { + settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::SingleTap)))) { GoToRunning(); } } break; @@ -236,6 +254,7 @@ void SystemTask::Work() { isGoingToSleep = true; NRF_LOG_INFO("[systemtask] Going to sleep"); xTimerStop(idleTimer, 0); + xTimerStop(dimTimer, 0); displayApp.PushMessage(Pinetime::Applications::Display::Messages::GoToSleep); heartRateApp.PushMessage(Pinetime::Applications::HeartRateTask::Messages::GoToSleep); break; @@ -269,16 +288,19 @@ void SystemTask::Work() { displayApp.PushMessage(Pinetime::Applications::Display::Messages::BleFirmwareUpdateStarted); break; case Messages::BleFirmwareUpdateFinished: - doNotGoToSleep = false; - xTimerStart(idleTimer, 0); - if (bleController.State() == Pinetime::Controllers::Ble::FirmwareUpdateStates::Validated) + if (bleController.State() == Pinetime::Controllers::Ble::FirmwareUpdateStates::Validated) { NVIC_SystemReset(); + } + doNotGoToSleep = false; + xTimerStart(dimTimer, 0); break; case Messages::OnTouchEvent: ReloadIdleTimer(); + displayApp.PushMessage(Pinetime::Applications::Display::Messages::TouchEvent); break; case Messages::OnButtonEvent: ReloadIdleTimer(); + displayApp.PushMessage(Pinetime::Applications::Display::Messages::ButtonPushed); break; case Messages::OnDisplayTaskSleeping: if (BootloaderVersion::IsValid()) { @@ -290,7 +312,7 @@ void SystemTask::Work() { spi.Sleep(); // Double Tap needs the touch screen to be in normal mode - if (settingsController.getWakeUpMode() != Pinetime::Controllers::Settings::WakeUpMode::DoubleTap) { + if (!settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::DoubleTap)) { touchPanel.Sleep(); } twiMaster.Sleep(); @@ -324,6 +346,11 @@ void SystemTask::Work() { } } + if (xTaskGetTickCount() - batteryNotificationTick > batteryNotificationPeriod) { + nimbleController.NotifyBatteryLevel(batteryController.PercentRemaining()); + batteryNotificationTick = xTaskGetTickCount(); + } + monitor.Process(); uint32_t systick_counter = nrf_rtc_counter_get(portNRF_RTC_REG); dateTimeController.UpdateTime(systick_counter); @@ -337,7 +364,7 @@ void SystemTask::UpdateMotion() { if (isGoingToSleep or isWakingUp) return; - if (isSleeping && settingsController.getWakeUpMode() != Pinetime::Controllers::Settings::WakeUpMode::RaiseWrist) + if (isSleeping && !settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::RaiseWrist)) return; if (isSleeping) @@ -365,7 +392,6 @@ void SystemTask::OnButtonPushed() { if (!isSleeping) { NRF_LOG_INFO("[systemtask] Button pushed"); PushMessage(Messages::OnButtonEvent); - displayApp.PushMessage(Pinetime::Applications::Display::Messages::ButtonPushed); } else { if (!isWakingUp) { NRF_LOG_INFO("[systemtask] Button pushed, waking up"); @@ -386,12 +412,11 @@ void SystemTask::OnTouchEvent() { return; if (!isSleeping) { PushMessage(Messages::OnTouchEvent); - displayApp.PushMessage(Pinetime::Applications::Display::Messages::TouchEvent); } else if (!isWakingUp) { - if (settingsController.getWakeUpMode() == Pinetime::Controllers::Settings::WakeUpMode::None or - settingsController.getWakeUpMode() == Pinetime::Controllers::Settings::WakeUpMode::RaiseWrist) - return; - PushMessage(Messages::TouchWakeUp); + if (settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::SingleTap) or + settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::DoubleTap)) { + PushMessage(Messages::TouchWakeUp); + } } } @@ -414,6 +439,15 @@ void SystemTask::PushMessage(System::Messages msg) { } } +void SystemTask::OnDim() { + if (doNotGoToSleep) + return; + NRF_LOG_INFO("Dim timeout -> Dim screen") + displayApp.PushMessage(Pinetime::Applications::Display::Messages::DimScreen); + xTimerStart(idleTimer, 0); + isDimmed = true; +} + void SystemTask::OnIdle() { if (doNotGoToSleep) return; @@ -421,8 +455,13 @@ void SystemTask::OnIdle() { PushMessage(Messages::GoToSleep); } -void SystemTask::ReloadIdleTimer() const { +void SystemTask::ReloadIdleTimer() { if (isSleeping || isGoingToSleep) return; - xTimerReset(idleTimer, 0); + if (isDimmed) { + displayApp.PushMessage(Pinetime::Applications::Display::Messages::RestoreBrightness); + isDimmed = false; + } + xTimerReset(dimTimer, 0); + xTimerStop(idleTimer, 0); } diff --git a/src/systemtask/SystemTask.h b/src/systemtask/SystemTask.h index fa6a949c..ba434298 100644 --- a/src/systemtask/SystemTask.h +++ b/src/systemtask/SystemTask.h @@ -16,13 +16,15 @@ #include "components/ble/NotificationManager.h" #include "components/motor/MotorController.h" #include "components/timer/TimerController.h" +#include "components/fs/FS.h" + #ifdef PINETIME_IS_RECOVERY #include "displayapp/DisplayAppRecovery.h" #include "displayapp/DummyLittleVgl.h" #else #include "components/settings/Settings.h" #include "displayapp/DisplayApp.h" - #include "displayapp/LittleVgl.h" + #include "displayapp/LittleVgl.h" #endif #include "drivers/Watchdog.h" @@ -59,7 +61,8 @@ namespace Pinetime { Controllers::Settings& settingsController, Pinetime::Controllers::HeartRateController& heartRateController, Pinetime::Applications::DisplayApp& displayApp, - Pinetime::Applications::HeartRateTask& heartRateApp); + Pinetime::Applications::HeartRateTask& heartRateApp, + Pinetime::Controllers::FS& fs); void Start(); void PushMessage(Messages msg); @@ -68,11 +71,16 @@ namespace Pinetime { void OnTouchEvent(); void OnIdle(); + void OnDim(); Pinetime::Controllers::NimbleController& nimble() { return nimbleController; }; + bool IsSleeping() const { + return isSleeping; + } + private: TaskHandle_t taskHandle; @@ -92,6 +100,7 @@ namespace Pinetime { std::atomic<bool> isSleeping {false}; std::atomic<bool> isGoingToSleep {false}; std::atomic<bool> isWakingUp {false}; + std::atomic<bool> isDimmed {false}; Pinetime::Drivers::Watchdog& watchdog; Pinetime::Controllers::NotificationManager& notificationManager; Pinetime::Controllers::MotorController& motorController; @@ -99,13 +108,12 @@ namespace Pinetime { Pinetime::Drivers::Bma421& motionSensor; Pinetime::Controllers::Settings& settingsController; Pinetime::Controllers::HeartRateController& heartRateController; - Pinetime::Controllers::NimbleController nimbleController; - Controllers::BrightnessController brightnessController; Pinetime::Controllers::MotionController& motionController; Pinetime::Applications::DisplayApp& displayApp; Pinetime::Applications::HeartRateTask& heartRateApp; - + Pinetime::Controllers::FS& fs; + Pinetime::Controllers::NimbleController nimbleController; static constexpr uint8_t pinSpiSck = 2; static constexpr uint8_t pinSpiMosi = 3; @@ -118,15 +126,18 @@ namespace Pinetime { static void Process(void* instance); void Work(); - void ReloadIdleTimer() const; + void ReloadIdleTimer(); bool isBleDiscoveryTimerRunning = false; uint8_t bleDiscoveryTimer = 0; + TimerHandle_t dimTimer; TimerHandle_t idleTimer; bool doNotGoToSleep = false; void GoToRunning(); void UpdateMotion(); bool stepCounterMustBeReset = false; + static constexpr TickType_t batteryNotificationPeriod = 1000 * 60 * 10; // 1 tick ~= 1ms. 1ms * 60 * 10 = 10 minutes + TickType_t batteryNotificationTick = 0; #if configUSE_TRACE_FACILITY == 1 SystemMonitor<FreeRtosMonitor> monitor; |