diff options
Diffstat (limited to 'src')
40 files changed, 4094 insertions, 282 deletions
diff --git a/src/BLE/BleManager.h b/src/BLE/BleManager.h index 13b12a62..68fdff9a 100644 --- a/src/BLE/BleManager.h +++ b/src/BLE/BleManager.h @@ -1,4 +1,5 @@ #pragma once +#include <ble/ble_services/ble_cts_c/ble_cts_c.h> #ifdef __cplusplus extern "C" { diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 580c4653..c93feb38 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -26,20 +26,159 @@ add_definitions(-DDEBUG) include_directories(.) +include_directories(libs/) + +set(LVGL_SRC + libs/lv_conf.h + libs/lvgl/lvgl.h + libs/lvgl/src/lv_core/lv_obj.c + libs/lvgl/src/lv_core/lv_obj.h + libs/lvgl/src/lv_core/lv_group.c + libs/lvgl/src/lv_core/lv_group.h + libs/lvgl/src/lv_core/lv_disp.c + libs/lvgl/src/lv_core/lv_disp.h + libs/lvgl/src/lv_core/lv_debug.h + libs/lvgl/src/lv_core/lv_debug.c + libs/lvgl/src/lv_core/lv_indev.c + libs/lvgl/src/lv_core/lv_indev.h + libs/lvgl/src/lv_core/lv_refr.c + libs/lvgl/src/lv_core/lv_refr.h + libs/lvgl/src/lv_core/lv_style.c + libs/lvgl/src/lv_core/lv_style.h + + libs/lvgl/src/lv_misc/lv_anim.c + libs/lvgl/src/lv_misc/lv_anim.h + libs/lvgl/src/lv_misc/lv_async.h + libs/lvgl/src/lv_misc/lv_async.c + libs/lvgl/src/lv_misc/lv_fs.c + libs/lvgl/src/lv_misc/lv_fs.h + libs/lvgl/src/lv_misc/lv_task.c + libs/lvgl/src/lv_misc/lv_task.h + libs/lvgl/src/lv_misc/lv_area.c + libs/lvgl/src/lv_misc/lv_area.h + libs/lvgl/src/lv_misc/lv_bidi.c + libs/lvgl/src/lv_misc/lv_bidi.h + libs/lvgl/src/lv_misc/lv_circ.c + libs/lvgl/src/lv_misc/lv_circ.h + libs/lvgl/src/lv_misc/lv_color.c + libs/lvgl/src/lv_misc/lv_color.h + libs/lvgl/src/lv_misc/lv_fs.c + libs/lvgl/src/lv_misc/lv_fs.h + libs/lvgl/src/lv_misc/lv_gc.c + libs/lvgl/src/lv_misc/lv_gc.h + libs/lvgl/src/lv_misc/lv_ll.c + libs/lvgl/src/lv_misc/lv_ll.h + libs/lvgl/src/lv_misc/lv_log.c + libs/lvgl/src/lv_misc/lv_log.h + libs/lvgl/src/lv_misc/lv_math.c + libs/lvgl/src/lv_misc/lv_math.h + libs/lvgl/src/lv_misc/lv_mem.c + libs/lvgl/src/lv_misc/lv_mem.h + libs/lvgl/src/lv_misc/lv_printf.c + libs/lvgl/src/lv_misc/lv_printf.h + libs/lvgl/src/lv_misc/lv_task.c + libs/lvgl/src/lv_misc/lv_task.h + libs/lvgl/src/lv_misc/lv_templ.c + libs/lvgl/src/lv_misc/lv_templ.h + libs/lvgl/src/lv_misc/lv_txt.c + libs/lvgl/src/lv_misc/lv_txt.h + libs/lvgl/src/lv_misc/lv_types.h + libs/lvgl/src/lv_misc/lv_utils.c + libs/lvgl/src/lv_misc/lv_utils.h + + libs/lvgl/src/lv_draw/lv_draw.c + libs/lvgl/src/lv_draw/lv_draw.h + libs/lvgl/src/lv_draw/lv_draw_arc.c + libs/lvgl/src/lv_draw/lv_draw_arc.h + libs/lvgl/src/lv_draw/lv_draw_basic.c + libs/lvgl/src/lv_draw/lv_draw_basic.h + libs/lvgl/src/lv_draw/lv_draw_img.c + libs/lvgl/src/lv_draw/lv_draw_img.h + libs/lvgl/src/lv_draw/lv_draw_label.c + libs/lvgl/src/lv_draw/lv_draw_label.h + libs/lvgl/src/lv_draw/lv_draw_line.c + libs/lvgl/src/lv_draw/lv_draw_line.h + libs/lvgl/src/lv_draw/lv_draw_rect.c + libs/lvgl/src/lv_draw/lv_draw_rect.h + libs/lvgl/src/lv_draw/lv_draw_triangle.c + libs/lvgl/src/lv_draw/lv_draw_triangle.h + libs/lvgl/src/lv_draw/lv_img_cache.c + libs/lvgl/src/lv_draw/lv_img_cache.h + libs/lvgl/src/lv_draw/lv_img_decoder.c + libs/lvgl/src/lv_draw/lv_img_decoder.h + + libs/lvgl/src/lv_hal/lv_hal.h + libs/lvgl/src/lv_hal/lv_hal_disp.c + libs/lvgl/src/lv_hal/lv_hal_disp.h + libs/lvgl/src/lv_hal/lv_hal_indev.c + libs/lvgl/src/lv_hal/lv_hal_indev.h + libs/lvgl/src/lv_hal/lv_hal_tick.c + libs/lvgl/src/lv_hal/lv_hal_tick.h + + libs/lvgl/src/lv_font/lv_font.c + libs/lvgl/src/lv_font/lv_font.h + libs/lvgl/src/lv_font/lv_font_fmt_txt.c + libs/lvgl/src/lv_font/lv_font_fmt_txt.h +# libs/lvgl/src/lv_font/lv_font_roboto_16.c + libs/lvgl/src/lv_font/lv_symbol_def.h + + libs/lvgl/src/lv_themes/lv_theme.c + libs/lvgl/src/lv_themes/lv_theme.h + + libs/lvgl/src/lv_objx/lv_btn.h + libs/lvgl/src/lv_objx/lv_btn.c + + libs/lvgl/src/lv_objx/lv_cont.h + libs/lvgl/src/lv_objx/lv_cont.c + + libs/lvgl/src/lv_objx/lv_label.h + libs/lvgl/src/lv_objx/lv_label.c + + libs/lvgl/src/lv_themes/lv_theme.c + libs/lvgl/src/lv_themes/lv_theme.h + libs/lvgl/src/lv_themes/lv_theme_night.h + libs/lvgl/src/lv_themes/lv_theme_night.c + + libs/lvgl/src/lv_objx/lv_list.c + libs/lvgl/src/lv_objx/lv_list.h + libs/lvgl/src/lv_objx/lv_tileview.c + libs/lvgl/src/lv_objx/lv_tileview.h + libs/lvgl/src/lv_objx/lv_tabview.c + libs/lvgl/src/lv_objx/lv_tabview.h + libs/lvgl/src/lv_objx/lv_btnm.c + libs/lvgl/src/lv_objx/lv_btnm.h + libs/lvgl/src/lv_objx/lv_page.c + libs/lvgl/src/lv_objx/lv_page.h + libs/lvgl/src/lv_objx/lv_img.c + libs/lvgl/src/lv_objx/lv_img.h + libs/lvgl/src/lv_objx/lv_lmeter.c + libs/lvgl/src/lv_objx/lv_lmeter.h + libs/lvgl/src/lv_objx/lv_arc.c + libs/lvgl/src/lv_objx/lv_arc.h + libs/lvgl/src/lv_objx/lv_gauge.c + libs/lvgl/src/lv_objx/lv_gauge.h + + libs/lvgl/src/lv_objx/lv_mbox.c + libs/lvgl/src/lv_objx/lv_mbox.h + + ) list(APPEND SOURCE_FILES Logging/NrfLogger.cpp BlinkApp/BlinkApp.cpp DisplayApp/DisplayApp.cpp - DisplayApp/Fonts/lcdfont70.c - DisplayApp/Fonts/lcdfont14.c DisplayApp/Screens/Screen.cpp DisplayApp/Screens/Clock.cpp DisplayApp/Screens/Message.cpp + DisplayApp/Screens/Tile.cpp + DisplayApp/Screens/Meter.cpp + DisplayApp/Screens/Gauge.cpp + DisplayApp/Screens/Modal.cpp main.cpp drivers/St7789.cpp drivers/SpiMaster.cpp - Components/Gfx/Gfx.cpp + drivers/Watchdog.cpp + drivers/DebugPins.cpp BLE/BleManager.c Components/Battery/BatteryController.cpp Components/Ble/BleController.cpp @@ -48,6 +187,13 @@ list(APPEND SOURCE_FILES FreeRTOS/port.c FreeRTOS/port_cmsis_systick.c FreeRTOS/port_cmsis.c + ${LVGL_SRC} + + DisplayApp/LittleVgl.cpp + DisplayApp/Fonts/jetbrains_mono_extrabold_compressed.c + DisplayApp/Fonts/jetbrains_mono_bold_20.c + + SystemTask/SystemTask.cpp ) set(INCLUDE_FILES @@ -55,14 +201,18 @@ set(INCLUDE_FILES Logging/NrfLogger.h BlinkApp/BlinkApp.h DisplayApp/DisplayApp.h - DisplayApp/Fonts/lcdfont70.h - DisplayApp/Fonts/lcdfont14.h DisplayApp/Screens/Screen.h DisplayApp/Screens/Clock.h DisplayApp/Screens/Message.h + DisplayApp/Screens/Tile.h + DisplayApp/Screens/Meter.h + DisplayApp/Screens/Gauge.h + DisplayApp/Screens/Modal.h +# DisplayApp/Screens/Tab.h drivers/St7789.h drivers/SpiMaster.h - Components/Gfx/Gfx.h + drivers/Watchdog.h + drivers/DebugPins.h BLE/BleManager.h Components/Battery/BatteryController.h Components/Ble/BleController.h @@ -78,6 +228,10 @@ set(INCLUDE_FILES libs/date/includes/date/julian.h libs/date/includes/date/ptz.h libs/date/includes/date/tz_private.h + + DisplayApp/LittleVgl.h + + SystemTask/SystemTask.h ) include_directories( diff --git a/src/Components/DateTime/DateTimeController.cpp b/src/Components/DateTime/DateTimeController.cpp index ed6d70fb..5cfa08eb 100644 --- a/src/Components/DateTime/DateTimeController.cpp +++ b/src/Components/DateTime/DateTimeController.cpp @@ -7,25 +7,23 @@ using namespace Pinetime::Controllers; void DateTime::SetTime(uint16_t year, uint8_t month, uint8_t day, uint8_t dayOfWeek, uint8_t hour, uint8_t minute, uint8_t second, uint32_t systickCounter) { + std::tm tm = { /* .tm_sec = */ second, + /* .tm_min = */ minute, + /* .tm_hour = */ hour, + /* .tm_mday = */ day, + /* .tm_mon = */ month - 1, + /* .tm_year = */ year - 1900, + }; + tm.tm_isdst = -1; // Use DST value from local time zone + currentDateTime = std::chrono::system_clock::from_time_t(std::mktime(&tm)); - currentDateTime = {}; - currentDateTime += date::years( year-1970); - currentDateTime += date::days( day - 1); - currentDateTime += date::months( month - 1); - - currentDateTime += std::chrono::hours(hour); - currentDateTime += std::chrono::minutes (minute); - currentDateTime += std::chrono::seconds (second); - - currentDateTime -= std::chrono::hours(3); // TODO WHYYYY? NRF_LOG_INFO("%d %d %d ", day, month, year); NRF_LOG_INFO("%d %d %d ", hour, minute, second); previousSystickCounter = systickCounter; + UpdateTime(systickCounter); NRF_LOG_INFO("* %d %d %d ", this->hour, this->minute, this->second); NRF_LOG_INFO("* %d %d %d ", this->day, this->month, this->year); - - } void DateTime::UpdateTime(uint32_t systickCounter) { diff --git a/src/Components/DateTime/DateTimeController.h b/src/Components/DateTime/DateTimeController.h index 9e7392cd..1e65bd11 100644 --- a/src/Components/DateTime/DateTimeController.h +++ b/src/Components/DateTime/DateTimeController.h @@ -20,7 +20,7 @@ namespace Pinetime { uint8_t Minutes() const { return minute; } uint8_t Seconds() const { return second; } - std::chrono::time_point<std::chrono::system_clock, std::chrono::milliseconds> CurrentDateTime() const { return currentDateTime; } + std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds> CurrentDateTime() const { return currentDateTime; } private: uint16_t year = 0; Months month = Months::Unknown; @@ -31,7 +31,7 @@ namespace Pinetime { uint8_t second = 0; uint32_t previousSystickCounter = 0; - std::chrono::time_point<std::chrono::system_clock, std::chrono::milliseconds> currentDateTime; + std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds> currentDateTime; }; } diff --git a/src/DisplayApp/DisplayApp.cpp b/src/DisplayApp/DisplayApp.cpp index ca139423..d7d62dde 100644 --- a/src/DisplayApp/DisplayApp.cpp +++ b/src/DisplayApp/DisplayApp.cpp @@ -4,35 +4,39 @@ #include <libraries/log/nrf_log.h> #include <boards.h> #include <nrf_font.h> -#include <hal/nrf_rtc.h> -#include "Components/Gfx/Gfx.h" #include <queue.h> #include <Components/DateTime/DateTimeController.h> #include <drivers/Cst816s.h> -#include <chrono> #include <string> +#include <lvgl/lvgl.h> +#include <DisplayApp/Screens/Tile.h> +#include <DisplayApp/Screens/Message.h> +#include <DisplayApp/Screens/Meter.h> +#include <DisplayApp/Screens/Gauge.h> +#include "../SystemTask/SystemTask.h" using namespace Pinetime::Applications; DisplayApp::DisplayApp(Pinetime::Drivers::St7789& lcd, - Pinetime::Components::Gfx& gfx, + Pinetime::Components::LittleVgl& lvgl, Pinetime::Drivers::Cst816S& touchPanel, Controllers::Battery &batteryController, Controllers::Ble &bleController, - Controllers::DateTime &dateTimeController) : + Controllers::DateTime &dateTimeController, + Pinetime::System::SystemTask& systemTask) : lcd{lcd}, - gfx{gfx}, + lvgl{lvgl}, touchPanel{touchPanel}, batteryController{batteryController}, bleController{bleController}, dateTimeController{dateTimeController}, - clockScreen{gfx} { + currentScreen{new Screens::Clock(this, dateTimeController, batteryController, bleController) }, + systemTask{systemTask} { msgQueue = xQueueCreate(queueSize, itemSize); - currentScreen = &clockScreen; } void DisplayApp::Start() { - if (pdPASS != xTaskCreate(DisplayApp::Process, "DisplayApp", 256, this, 0, &taskHandle)) + if (pdPASS != xTaskCreate(DisplayApp::Process, "DisplayApp", 512, this, 0, &taskHandle)) APP_ERROR_HANDLER(NRF_ERROR_NO_MEM); } @@ -40,8 +44,14 @@ void DisplayApp::Process(void *instance) { auto *app = static_cast<DisplayApp *>(instance); NRF_LOG_INFO("DisplayApp task started!"); app->InitHw(); + + // Send a dummy notification to unlock the lvgl display driver for the first iteration + xTaskNotifyGive(xTaskGetCurrentTaskHandle()); + while (1) { + app->Refresh(); + } } @@ -52,8 +62,6 @@ void DisplayApp::InitHw() { nrf_gpio_pin_clear(pinLcdBacklight1); nrf_gpio_pin_clear(pinLcdBacklight2); nrf_gpio_pin_clear(pinLcdBacklight3); - - currentScreen->Refresh(true); } uint32_t acc = 0; @@ -68,7 +76,7 @@ void DisplayApp::Refresh() { break; case States::Running: RunningState(); - queueTimeout = 1000; + queueTimeout = 20; break; } @@ -99,25 +107,51 @@ void DisplayApp::Refresh() { case Messages::UpdateDateTime: break; case Messages::UpdateBleConnection: - clockScreen.SetBleConnectionState(bleController.IsConnected() ? Screens::Clock::BleConnectionStates::Connected : Screens::Clock::BleConnectionStates::NotConnected); +// clockScreen.SetBleConnectionState(bleController.IsConnected() ? Screens::Clock::BleConnectionStates::Connected : Screens::Clock::BleConnectionStates::NotConnected); break; case Messages::UpdateBatteryLevel: - clockScreen.SetBatteryPercentRemaining(batteryController.PercentRemaining()); +// clockScreen.SetBatteryPercentRemaining(batteryController.PercentRemaining()); break; case Messages::TouchEvent: if(state != States::Running) break; OnTouchEvent(); break; + case Messages::ButtonPushed: + if(!currentScreen->OnButtonPushed()) { + systemTask.PushMessage(System::SystemTask::Messages::GoToSleep); + } +// currentScreen.reset(nullptr); +// if(toggle) { +// modal.Show(); +//// currentScreen.reset(new Screens::Tile(this)); +// toggle = false; +// } else { +// modal.Hide(); +//// currentScreen.reset(new Screens::Clock(this, dateTimeController, batteryController, bleController)); +// toggle = true; +// } + + break; } } } void DisplayApp::RunningState() { - clockScreen.SetCurrentDateTime(dateTimeController.CurrentDateTime()); - - if(currentScreen != nullptr) { - currentScreen->Refresh(false); +// clockScreen.SetCurrentDateTime(dateTimeController.CurrentDateTime()); + + if(!currentScreen->Refresh()) { + currentScreen.reset(nullptr); + switch(nextApp) { + case Apps::None: + case Apps::Launcher: currentScreen.reset(new Screens::Tile(this)); break; + case Apps::Clock: currentScreen.reset(new Screens::Clock(this, dateTimeController, batteryController, bleController)); break; + case Apps::Test: currentScreen.reset(new Screens::Message(this)); break; + case Apps::Meter: currentScreen.reset(new Screens::Meter(this)); break; + case Apps::Gauge: currentScreen.reset(new Screens::Gauge(this)); break; + } + nextApp = Apps::None; } + lv_task_handler(); } void DisplayApp::IdleState() { @@ -136,10 +170,14 @@ void DisplayApp::PushMessage(DisplayApp::Messages msg) { static uint16_t pointColor = 0x07e0; void DisplayApp::OnTouchEvent() { - auto info = touchPanel.GetTouchInfo(); +// auto info = touchPanel.GetTouchInfo(); +// +// if(info.isTouch) { +// lcd.DrawPixel(info.x, info.y, pointColor); +// pointColor+=10; +// } +} - if(info.isTouch) { - gfx.FillRectangle(info.x-10, info.y-10, 20,20, pointColor); - pointColor+=10; - } +void DisplayApp::StartApp(DisplayApp::Apps app) { + nextApp = app; } diff --git a/src/DisplayApp/DisplayApp.h b/src/DisplayApp/DisplayApp.h index 5a5d3ee6..348fd5bf 100644 --- a/src/DisplayApp/DisplayApp.h +++ b/src/DisplayApp/DisplayApp.h @@ -11,35 +11,39 @@ #include <Components/DateTime/DateTimeController.h> #include "Fonts/lcdfont14.h" #include "../drivers/Cst816s.h" +#include "LittleVgl.h" #include <date/date.h> #include <DisplayApp/Screens/Clock.h> -#include <DisplayApp/Screens/Message.h> -extern const FONT_INFO lCD_70ptFontInfo; namespace Pinetime { + namespace System { + class SystemTask; + }; namespace Applications { class DisplayApp { public: enum class States {Idle, Running}; - enum class Messages : uint8_t {GoToSleep, GoToRunning, UpdateDateTime, UpdateBleConnection, UpdateBatteryLevel, TouchEvent} ; + enum class Messages : uint8_t {GoToSleep, GoToRunning, UpdateDateTime, UpdateBleConnection, UpdateBatteryLevel, TouchEvent, SwitchScreen,ButtonPushed} ; DisplayApp(Pinetime::Drivers::St7789& lcd, - Pinetime::Components::Gfx& gfx, + Pinetime::Components::LittleVgl& lvgl, Pinetime::Drivers::Cst816S&, Controllers::Battery &batteryController, Controllers::Ble &bleController, - Controllers::DateTime& dateTimeController); + Controllers::DateTime& dateTimeController, + Pinetime::System::SystemTask& systemTask); void Start(); void PushMessage(Messages msg); + enum class Apps {None, Launcher, Clock, Test, Meter, Gauge}; + void StartApp(Apps app); + private: TaskHandle_t taskHandle; static void Process(void* instance); void InitHw(); Pinetime::Drivers::St7789& lcd; - Pinetime::Components::Gfx& gfx; - const FONT_INFO largeFont {lCD_70ptFontInfo.height, lCD_70ptFontInfo.startChar, lCD_70ptFontInfo.endChar, lCD_70ptFontInfo.spacePixels, lCD_70ptFontInfo.charInfo, lCD_70ptFontInfo.data}; - const FONT_INFO smallFont {lCD_14ptFontInfo.height, lCD_14ptFontInfo.startChar, lCD_14ptFontInfo.endChar, lCD_14ptFontInfo.spacePixels, lCD_14ptFontInfo.charInfo, lCD_14ptFontInfo.data}; + Pinetime::Components::LittleVgl lvgl; void Refresh(); States state = States::Running; @@ -57,11 +61,15 @@ namespace Pinetime { Pinetime::Drivers::Cst816S& touchPanel; void OnTouchEvent(); - Screens::Clock clockScreen; - Screens::Screen* currentScreen = nullptr; + std::unique_ptr<Screens::Screen> currentScreen; static constexpr uint8_t pinLcdBacklight1 = 14; static constexpr uint8_t pinLcdBacklight2 = 22; static constexpr uint8_t pinLcdBacklight3 = 23; + + bool isClock = true; + + Pinetime::System::SystemTask& systemTask; + Apps nextApp = Apps::None; }; } } diff --git a/src/DisplayApp/Fonts/jetbrains_mono_bold_20.c b/src/DisplayApp/Fonts/jetbrains_mono_bold_20.c new file mode 100644 index 00000000..e7d053b8 --- /dev/null +++ b/src/DisplayApp/Fonts/jetbrains_mono_bold_20.c @@ -0,0 +1,594 @@ +#include "lvgl/lvgl.h" + +/******************************************************************************* + * Size: 20 px + * Bpp: 1 + * Opts: + ******************************************************************************/ + +#ifndef JETBRAINS_MONO_BOLD_20 +#define JETBRAINS_MONO_BOLD_20 1 +#endif + +#if JETBRAINS_MONO_BOLD_20 + +/*----------------- + * BITMAPS + *----------------*/ + +/*Store the image of the glyphs*/ +static LV_ATTRIBUTE_LARGE_CONST const uint8_t gylph_bitmap[] = { + /* U+20 " " */ + 0x0, + + /* U+21 "!" */ + 0xff, 0xff, 0xff, 0xe0, 0xf, 0xc0, + + /* U+22 "\"" */ + 0xef, 0xdf, 0xbf, 0x7e, 0xfd, 0xc0, + + /* U+23 "#" */ + 0x8, 0xc3, 0x10, 0x62, 0x3f, 0xf7, 0xfe, 0x23, + 0x4, 0x61, 0x88, 0x31, 0x1f, 0xfb, 0xff, 0x19, + 0x82, 0x30, 0xc4, 0x0, + + /* U+24 "$" */ + 0x1c, 0x7, 0x3, 0xf1, 0xfe, 0xe3, 0xf8, 0x7e, + 0x3, 0xe0, 0x7f, 0x7, 0xe0, 0x3c, 0x7, 0xe1, + 0xfc, 0xf7, 0xf8, 0xfc, 0x1c, 0x7, 0x0, + + /* U+25 "%" */ + 0x78, 0x1f, 0x83, 0x30, 0x66, 0x1f, 0xcc, 0xf2, + 0x1, 0x80, 0xde, 0x67, 0xf8, 0xcc, 0x19, 0x83, + 0x30, 0x7e, 0x7, 0x80, + + /* U+26 "&" */ + 0x1e, 0x7, 0xe1, 0xce, 0x38, 0x7, 0x0, 0x70, + 0x1e, 0x7, 0x66, 0xed, 0xdc, 0xf3, 0x9c, 0x73, + 0xcf, 0xfc, 0xf9, 0x80, + + /* U+27 "'" */ + 0xff, 0xff, 0xc0, + + /* U+28 "(" */ + 0x2, 0x1c, 0xfb, 0xc7, 0x1e, 0x38, 0x70, 0xe1, + 0xc3, 0x87, 0xe, 0x1c, 0x3c, 0x38, 0x38, 0x7c, + 0x38, + + /* U+29 ")" */ + 0x1, 0xc3, 0xc1, 0xc1, 0xc3, 0xc3, 0x87, 0xe, + 0x1c, 0x38, 0x70, 0xe1, 0xc7, 0x8e, 0x79, 0xe3, + 0x80, + + /* U+2A "*" */ + 0xc, 0x3, 0x8, 0xc7, 0xb7, 0x7f, 0x83, 0x1, + 0xe0, 0xcc, 0x73, 0x80, 0x0, + + /* U+2B "+" */ + 0x1c, 0x7, 0x1, 0xc3, 0xff, 0xff, 0xc7, 0x1, + 0xc0, 0x70, 0x1c, 0x0, + + /* U+2C "," */ + 0x7b, 0x9c, 0xce, 0x60, + + /* U+2D "-" */ + 0xff, 0xff, + + /* U+2E "." */ + 0x6f, 0xf6, + + /* U+2F "/" */ + 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" */ + 0x3f, 0x1f, 0xef, 0x3f, 0x87, 0xe1, 0xfb, 0x7e, + 0xdf, 0xb7, 0xed, 0xf8, 0x7e, 0x1f, 0xcf, 0x7f, + 0x8f, 0x80, + + /* U+31 "1" */ + 0x3c, 0x3e, 0x3f, 0x13, 0x81, 0xc0, 0xe0, 0x70, + 0x38, 0x1c, 0xe, 0x7, 0x3, 0x8f, 0xff, 0xfc, + + /* U+32 "2" */ + 0x1f, 0x1f, 0xef, 0x3f, 0x87, 0x1, 0xc0, 0x70, + 0x38, 0x1e, 0xf, 0x7, 0x87, 0x83, 0xc0, 0xff, + 0xff, 0xf0, + + /* U+33 "3" */ + 0x7f, 0xdf, 0xf0, 0x3c, 0x1c, 0x1c, 0x7, 0xc1, + 0xf8, 0xf, 0x1, 0xc0, 0x7e, 0x1d, 0x8f, 0x7f, + 0x87, 0xc0, + + /* U+34 "4" */ + 0x7, 0x7, 0x3, 0x83, 0x83, 0x81, 0xc1, 0xcf, + 0xe7, 0xe3, 0xff, 0xff, 0xe0, 0x70, 0x38, 0x1c, + + /* U+35 "5" */ + 0xff, 0x7f, 0xb8, 0x1c, 0xe, 0x7, 0x73, 0xfd, + 0xcf, 0x3, 0x81, 0xc0, 0xfc, 0xff, 0xf1, 0xf0, + + /* U+36 "6" */ + 0x6, 0x3, 0x1, 0xc0, 0x60, 0x30, 0x1b, 0xc7, + 0xfb, 0xcf, 0xe1, 0xf8, 0x7e, 0x1f, 0xcf, 0x7f, + 0x87, 0x80, + + /* U+37 "7" */ + 0xff, 0xff, 0xfe, 0xb, 0x86, 0x1, 0x80, 0xc0, + 0x30, 0x18, 0x6, 0x3, 0x80, 0xc0, 0x70, 0x18, + 0xe, 0x0, + + /* U+38 "8" */ + 0x3e, 0x1f, 0xce, 0x3b, 0x6, 0xe3, 0x9f, 0xc7, + 0xf1, 0x8e, 0xc1, 0xf0, 0x7c, 0x1f, 0x8f, 0x7f, + 0x8f, 0x80, + + /* U+39 "9" */ + 0x1e, 0x1f, 0xef, 0x3f, 0x87, 0xe1, 0xf8, 0x7f, + 0x3d, 0xfe, 0x3d, 0x80, 0xc0, 0x60, 0x38, 0xc, + 0x6, 0x0, + + /* U+3A ":" */ + 0xff, 0x80, 0x0, 0xff, 0x80, + + /* U+3B ";" */ + 0x7b, 0xde, 0x0, 0x0, 0x0, 0x7b, 0x9c, 0xce, + 0x60, + + /* U+3C "<" */ + 0x0, 0x81, 0xc3, 0xe7, 0xcf, 0x6, 0x3, 0xc0, + 0x7c, 0xf, 0x81, 0xc0, 0x20, + + /* U+3D "=" */ + 0xff, 0xff, 0xc0, 0x0, 0x0, 0x7, 0xff, 0xfe, + + /* U+3E ">" */ + 0x0, 0x70, 0x3e, 0x7, 0xc0, 0xf8, 0xc, 0x1e, + 0x7c, 0xf8, 0x70, 0x20, 0x0, + + /* U+3F "?" */ + 0xfc, 0xfe, 0xf, 0x7, 0x7, 0xf, 0x3e, 0x3c, + 0x30, 0x30, 0x0, 0x0, 0x70, 0x70, + + /* U+40 "@" */ + 0x1f, 0x87, 0xf9, 0xc3, 0xf0, 0x3c, 0x77, 0x9f, + 0xf3, 0x1e, 0x63, 0xcc, 0x79, 0x8f, 0x31, 0xe7, + 0xfc, 0x77, 0xc0, 0x1c, 0x1, 0xf0, 0x1e, 0x0, + + /* U+41 "A" */ + 0xf, 0x0, 0xf0, 0xf, 0x1, 0xf8, 0x19, 0x81, + 0x98, 0x19, 0x83, 0x9c, 0x3f, 0xc3, 0xfc, 0x70, + 0xe7, 0xe, 0x60, 0x66, 0x6, + + /* U+42 "B" */ + 0xfe, 0x3f, 0xce, 0x3b, 0x8e, 0xe3, 0xb8, 0xcf, + 0xe3, 0xfc, 0xe3, 0xb8, 0x7e, 0x1f, 0x8f, 0xff, + 0xbf, 0xc0, + + /* U+43 "C" */ + 0x3f, 0x1f, 0xef, 0x3f, 0x87, 0xe0, 0x38, 0xe, + 0x3, 0x80, 0xe0, 0x38, 0xe, 0x1f, 0xcf, 0x7f, + 0x8f, 0xc0, + + /* U+44 "D" */ + 0xfe, 0x3f, 0xee, 0x3f, 0x87, 0xe1, 0xf8, 0x7e, + 0x1f, 0x87, 0xe1, 0xf8, 0x7e, 0x1f, 0x8f, 0xff, + 0xbf, 0x80, + + /* U+45 "E" */ + 0xff, 0xff, 0xf8, 0x1c, 0xe, 0x7, 0x3, 0xfd, + 0xfe, 0xe0, 0x70, 0x38, 0x1c, 0xf, 0xff, 0xfc, + + /* U+46 "F" */ + 0xff, 0xff, 0xf8, 0x1c, 0xe, 0x7, 0x3, 0xff, + 0xff, 0xe0, 0x70, 0x38, 0x1c, 0xe, 0x7, 0x0, + + /* U+47 "G" */ + 0x3f, 0x1f, 0xef, 0x3f, 0x87, 0xe0, 0x38, 0xe, + 0x7f, 0x9f, 0xe1, 0xf8, 0x7e, 0x1f, 0xcf, 0x7f, + 0x87, 0x80, + + /* U+48 "H" */ + 0xe3, 0xf1, 0xf8, 0xfc, 0x7e, 0x3f, 0x1f, 0xff, + 0xff, 0xe3, 0xf1, 0xf8, 0xfc, 0x7e, 0x3f, 0x1c, + + /* U+49 "I" */ + 0xff, 0xff, 0xc7, 0x3, 0x81, 0xc0, 0xe0, 0x70, + 0x38, 0x1c, 0xe, 0x7, 0x3, 0x8f, 0xff, 0xfc, + + /* U+4A "J" */ + 0x3f, 0xcf, 0xf0, 0x1c, 0x7, 0x1, 0xc0, 0x70, + 0x1c, 0x7, 0x1, 0xc0, 0x7e, 0x1f, 0x8f, 0x7f, + 0x8f, 0xc0, + + /* U+4B "K" */ + 0xe1, 0xdc, 0x3b, 0x8e, 0x71, 0xce, 0x31, 0xce, + 0x3f, 0x87, 0xf0, 0xe7, 0x1c, 0x63, 0x8e, 0x70, + 0xce, 0x1d, 0xc3, 0x80, + + /* U+4C "L" */ + 0xe0, 0x70, 0x38, 0x1c, 0xe, 0x7, 0x3, 0x81, + 0xc0, 0xe0, 0x70, 0x38, 0x1c, 0xf, 0xff, 0xfc, + + /* U+4D "M" */ + 0xe1, 0xf8, 0x7f, 0x3f, 0xcf, 0xda, 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+4F "O" */ + 0x3f, 0x1f, 0xef, 0x3f, 0x87, 0xe1, 0xf8, 0x7e, + 0x1f, 0x87, 0xe1, 0xf8, 0x7e, 0x1f, 0xcf, 0x7f, + 0x8f, 0x80, + + /* U+50 "P" */ + 0xff, 0x3f, 0xee, 0x3f, 0x87, 0xe1, 0xf8, 0xff, + 0xfb, 0xfc, 0xe0, 0x38, 0xe, 0x3, 0x80, 0xe0, + 0x38, 0x0, + + /* U+51 "Q" */ + 0x3f, 0x1f, 0xef, 0x3f, 0x87, 0xe1, 0xf8, 0x7e, + 0x1f, 0x87, 0xe1, 0xf8, 0x7e, 0x1f, 0xcf, 0x7f, + 0x8f, 0x80, 0x70, 0xe, 0x1, 0xc0, + + /* U+52 "R" */ + 0xff, 0x3f, 0xee, 0x3f, 0x87, 0xe1, 0xf8, 0xff, + 0xfb, 0xf8, 0xe6, 0x39, 0xce, 0x33, 0x8e, 0xe3, + 0xb8, 0x70, + + /* U+53 "S" */ + 0x3f, 0x1f, 0xee, 0x3f, 0x87, 0xe0, 0x3e, 0x7, + 0xf0, 0x7e, 0x3, 0xc0, 0x7e, 0x1f, 0xcf, 0x7f, + 0x8f, 0xc0, + + /* U+54 "T" */ + 0xff, 0xff, 0xf0, 0xe0, 0x38, 0xe, 0x3, 0x80, + 0xe0, 0x38, 0xe, 0x3, 0x80, 0xe0, 0x38, 0xe, + 0x3, 0x80, + + /* U+55 "U" */ + 0xe3, 0xf1, 0xf8, 0xfc, 0x7e, 0x3f, 0x1f, 0x8f, + 0xc7, 0xe3, 0xf1, 0xf8, 0xfc, 0x77, 0xf1, 0xf0, + + /* U+56 "V" */ + 0x60, 0x66, 0x6, 0x70, 0xe7, 0xe, 0x30, 0xc3, + 0xc, 0x39, 0xc1, 0x98, 0x19, 0x81, 0x98, 0x1f, + 0x80, 0xf0, 0xf, 0x0, 0xf0, + + /* U+57 "W" */ + 0xc6, 0x3c, 0x73, 0x47, 0x36, 0xf3, 0x6f, 0x26, + 0xf6, 0x6d, 0x66, 0xd6, 0x69, 0x66, 0x9e, 0x69, + 0xe6, 0x9e, 0x39, 0xe3, 0x9e, + + /* U+58 "X" */ + 0xe1, 0xd8, 0x67, 0x38, 0xcc, 0x3f, 0x7, 0x81, + 0xe0, 0x78, 0x1e, 0xf, 0xc3, 0x31, 0xce, 0xe1, + 0xf8, 0x70, + + /* U+59 "Y" */ + 0xe0, 0xfc, 0x1d, 0xc7, 0x38, 0xe3, 0x98, 0x77, + 0x6, 0xc0, 0xf8, 0xe, 0x1, 0xc0, 0x38, 0x7, + 0x0, 0xe0, 0x1c, 0x0, + + /* U+5A "Z" */ + 0xff, 0xff, 0xc0, 0xe0, 0xe0, 0x60, 0x70, 0x70, + 0x38, 0x38, 0x38, 0x1c, 0x1c, 0xf, 0xff, 0xfc, + + /* U+5B "[" */ + 0xff, 0xfe, 0x38, 0xe3, 0x8e, 0x38, 0xe3, 0x8e, + 0x38, 0xe3, 0x8e, 0x38, 0xff, 0xf0, + + /* U+5C "\\" */ + 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 "]" */ + 0xff, 0xf1, 0xc7, 0x1c, 0x71, 0xc7, 0x1c, 0x71, + 0xc7, 0x1c, 0x71, 0xc7, 0xff, 0xf0, + + /* U+5E "^" */ + 0xc, 0x7, 0x81, 0xe0, 0xfc, 0x33, 0x1c, 0xe6, + 0x19, 0x86, + + /* U+5F "_" */ + 0xff, 0xff, 0xf0, + + /* U+60 "`" */ + 0x63, 0x8e, + + /* U+61 "a" */ + 0x1f, 0x1f, 0xef, 0x1c, 0x7, 0x3f, 0xdf, 0xfe, + 0x1f, 0x87, 0xe3, 0xff, 0xf7, 0x9c, + + /* U+62 "b" */ + 0xe0, 0x38, 0xe, 0x3, 0xbc, 0xff, 0xbc, 0xfe, + 0x1f, 0x87, 0xe1, 0xf8, 0x7e, 0x1f, 0xcf, 0xff, + 0xbb, 0xc0, + + /* U+63 "c" */ + 0x3f, 0x1f, 0xef, 0x1f, 0x83, 0xe0, 0x38, 0xe, + 0x3, 0x87, 0xf1, 0xdf, 0xe3, 0xe0, + + /* U+64 "d" */ + 0x1, 0xc0, 0x70, 0x1c, 0xf7, 0x7f, 0xfc, 0xfe, + 0x1f, 0x87, 0xe1, 0xf8, 0x7e, 0x1f, 0xcf, 0x7f, + 0xcf, 0x70, + + /* U+65 "e" */ + 0x3f, 0x1f, 0xef, 0x3f, 0x87, 0xff, 0xff, 0xfe, + 0x3, 0x80, 0xf1, 0xdf, 0xe3, 0xf0, + + /* U+66 "f" */ + 0xf, 0xc7, 0xf1, 0xc0, 0x70, 0xff, 0xff, 0xf1, + 0xc0, 0x70, 0x1c, 0x7, 0x1, 0xc0, 0x70, 0x1c, + 0x7, 0x0, + + /* U+67 "g" */ + 0x3d, 0xdf, 0xff, 0x3f, 0x87, 0xe1, 0xf8, 0x7e, + 0x1f, 0xcf, 0x7f, 0xcf, 0x70, 0x1c, 0xf, 0x3f, + 0x8f, 0xc0, + + /* U+68 "h" */ + 0xe0, 0x70, 0x38, 0x1d, 0xcf, 0xf7, 0x9f, 0x8f, + 0xc7, 0xe3, 0xf1, 0xf8, 0xfc, 0x7e, 0x3f, 0x1c, + + /* U+69 "i" */ + 0x8, 0x7, 0x0, 0x80, 0x0, 0xfc, 0x3f, 0x1, + 0xc0, 0x70, 0x1c, 0x7, 0x1, 0xc0, 0x70, 0x1c, + 0x3f, 0xff, 0xfc, + + /* U+6A "j" */ + 0x2, 0x7, 0x2, 0x0, 0x7f, 0x7f, 0x7, 0x7, + 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0xf, + 0xfe, 0xfc, + + /* U+6B "k" */ + 0xe0, 0x38, 0xe, 0x3, 0x87, 0xe1, 0xb8, 0xee, + 0x33, 0x9c, 0xfe, 0x3f, 0x8e, 0x73, 0x8e, 0xe3, + 0xb8, 0x70, + + /* U+6C "l" */ + 0xfe, 0x1f, 0xc0, 0x38, 0x7, 0x0, 0xe0, 0x1c, + 0x3, 0x80, 0x70, 0xe, 0x1, 0xc0, 0x38, 0x7, + 0x0, 0xfe, 0xf, 0xc0, + + /* U+6D "m" */ + 0xd9, 0xbf, 0xfc, 0xcf, 0x33, 0xcc, 0xf3, 0x3c, + 0xcf, 0x33, 0xcc, 0xf3, 0x3c, 0xcc, + + /* U+6E "n" */ + 0xee, 0x7f, 0xbc, 0xfc, 0x7e, 0x3f, 0x1f, 0x8f, + 0xc7, 0xe3, 0xf1, 0xf8, 0xe0, + + /* U+6F "o" */ + 0x3f, 0x1f, 0xef, 0x3f, 0x87, 0xe1, 0xf8, 0x7e, + 0x1f, 0x87, 0xf3, 0xdf, 0xe1, 0xf0, + + /* U+70 "p" */ + 0xef, 0x3f, 0xef, 0x3f, 0x87, 0xe1, 0xf8, 0x7e, + 0x1f, 0x87, 0xf3, 0xff, 0xee, 0xf3, 0x80, 0xe0, + 0x38, 0x0, + + /* U+71 "q" */ + 0x3d, 0xdf, 0xff, 0x3f, 0x87, 0xe1, 0xf8, 0x7e, + 0x1f, 0x87, 0xf3, 0xdf, 0xf3, 0xdc, 0x7, 0x1, + 0xc0, 0x70, + + /* U+72 "r" */ + 0xef, 0x3f, 0xef, 0x3f, 0x87, 0xe1, 0xf8, 0xe, + 0x3, 0x80, 0xe0, 0x38, 0xe, 0x0, + + /* U+73 "s" */ + 0x3f, 0x3f, 0xee, 0x1f, 0x80, 0xfc, 0x1f, 0xe0, + 0x3c, 0x7, 0xe1, 0xff, 0xe3, 0xf0, + + /* U+74 "t" */ + 0x1c, 0x7, 0x1, 0xc3, 0xff, 0xff, 0xc7, 0x1, + 0xc0, 0x70, 0x1c, 0x7, 0x1, 0xc0, 0x70, 0xf, + 0xc1, 0xf0, + + /* U+75 "u" */ + 0xe3, 0xf1, 0xf8, 0xfc, 0x7e, 0x3f, 0x1f, 0x8f, + 0xc7, 0xe3, 0xbf, 0x8f, 0x80, + + /* U+76 "v" */ + 0xc0, 0xf8, 0x76, 0x19, 0x86, 0x73, 0x8c, 0xc3, + 0x30, 0xfc, 0x1e, 0x7, 0x81, 0xe0, + + /* U+77 "w" */ + 0xc6, 0x24, 0x62, 0x4e, 0x66, 0xf6, 0x6f, 0x66, + 0xf6, 0x6b, 0x66, 0x94, 0x79, 0x43, 0x9c, 0x39, + 0xc0, + + /* U+78 "x" */ + 0xe1, 0xdc, 0xe3, 0x30, 0xfc, 0x1e, 0x7, 0x81, + 0xe0, 0xfc, 0x73, 0x9c, 0x6e, 0x1c, + + /* U+79 "y" */ + 0xe1, 0xf8, 0x76, 0x19, 0xce, 0x33, 0x8e, 0xc3, + 0xf0, 0x7c, 0x1e, 0x3, 0x80, 0xc0, 0x70, 0x1c, + 0x6, 0x0, + + /* U+7A "z" */ + 0xff, 0xff, 0xc0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, + 0xe0, 0xe0, 0x7f, 0xff, 0xe0, + + /* U+7B "{" */ + 0x3, 0x87, 0xc3, 0x81, 0xc0, 0xe0, 0x70, 0x38, + 0x1c, 0xfc, 0x7e, 0x3, 0x81, 0xc0, 0xe0, 0x70, + 0x38, 0x1c, 0xf, 0x83, 0xc0, + + /* U+7C "|" */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, + + /* U+7D "}" */ + 0xf0, 0x3f, 0x1, 0xc0, 0x70, 0x1c, 0x7, 0x1, + 0xc0, 0x70, 0xf, 0xc3, 0xf1, 0xc0, 0x70, 0x1c, + 0x7, 0x1, 0xc0, 0x70, 0xf8, 0x3c, 0x0, + + /* U+7E "~" */ + 0x78, 0xff, 0x3c, 0xff, 0x1e +}; + + +/*--------------------- + * 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 = 192, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1, .adv_w = 192, .box_w = 3, .box_h = 14, .ofs_x = 4, .ofs_y = 0}, + {.bitmap_index = 7, .adv_w = 192, .box_w = 7, .box_h = 6, .ofs_x = 3, .ofs_y = 8}, + {.bitmap_index = 13, .adv_w = 192, .box_w = 11, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 33, .adv_w = 192, .box_w = 10, .box_h = 18, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 56, .adv_w = 192, .box_w = 11, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 76, .adv_w = 192, .box_w = 11, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 96, .adv_w = 192, .box_w = 3, .box_h = 6, .ofs_x = 5, .ofs_y = 8}, + {.bitmap_index = 99, .adv_w = 192, .box_w = 7, .box_h = 19, .ofs_x = 3, .ofs_y = -2}, + {.bitmap_index = 116, .adv_w = 192, .box_w = 7, .box_h = 19, .ofs_x = 2, .ofs_y = -2}, + {.bitmap_index = 133, .adv_w = 192, .box_w = 10, .box_h = 10, .ofs_x = 1, .ofs_y = 1}, + {.bitmap_index = 146, .adv_w = 192, .box_w = 10, .box_h = 9, .ofs_x = 1, .ofs_y = 2}, + {.bitmap_index = 158, .adv_w = 192, .box_w = 5, .box_h = 6, .ofs_x = 3, .ofs_y = -3}, + {.bitmap_index = 162, .adv_w = 192, .box_w = 8, .box_h = 2, .ofs_x = 2, .ofs_y = 5}, + {.bitmap_index = 164, .adv_w = 192, .box_w = 4, .box_h = 4, .ofs_x = 4, .ofs_y = 0}, + {.bitmap_index = 166, .adv_w = 192, .box_w = 10, .box_h = 19, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 190, .adv_w = 192, .box_w = 10, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 208, .adv_w = 192, .box_w = 9, .box_h = 14, .ofs_x = 2, .ofs_y = 0}, + {.bitmap_index = 224, .adv_w = 192, .box_w = 10, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 242, .adv_w = 192, .box_w = 10, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 260, .adv_w = 192, .box_w = 9, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 276, .adv_w = 192, .box_w = 9, .box_h = 14, .ofs_x = 2, .ofs_y = 0}, + {.bitmap_index = 292, .adv_w = 192, .box_w = 10, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 310, .adv_w = 192, .box_w = 10, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 328, .adv_w = 192, .box_w = 10, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 346, .adv_w = 192, .box_w = 10, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 364, .adv_w = 192, .box_w = 3, .box_h = 11, .ofs_x = 4, .ofs_y = 0}, + {.bitmap_index = 369, .adv_w = 192, .box_w = 5, .box_h = 14, .ofs_x = 3, .ofs_y = -3}, + {.bitmap_index = 378, .adv_w = 192, .box_w = 9, .box_h = 11, .ofs_x = 2, .ofs_y = 1}, + {.bitmap_index = 391, .adv_w = 192, .box_w = 9, .box_h = 7, .ofs_x = 2, .ofs_y = 3}, + {.bitmap_index = 399, .adv_w = 192, .box_w = 9, .box_h = 11, .ofs_x = 2, .ofs_y = 1}, + {.bitmap_index = 412, .adv_w = 192, .box_w = 8, .box_h = 14, .ofs_x = 2, .ofs_y = 0}, + {.bitmap_index = 426, .adv_w = 192, .box_w = 11, .box_h = 17, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 450, .adv_w = 192, .box_w = 12, .box_h = 14, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 471, .adv_w = 192, .box_w = 10, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 489, .adv_w = 192, .box_w = 10, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 507, .adv_w = 192, .box_w = 10, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 525, .adv_w = 192, .box_w = 9, .box_h = 14, .ofs_x = 2, .ofs_y = 0}, + {.bitmap_index = 541, .adv_w = 192, .box_w = 9, .box_h = 14, .ofs_x = 2, .ofs_y = 0}, + {.bitmap_index = 557, .adv_w = 192, .box_w = 10, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 575, .adv_w = 192, .box_w = 9, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 591, .adv_w = 192, .box_w = 9, .box_h = 14, .ofs_x = 2, .ofs_y = 0}, + {.bitmap_index = 607, .adv_w = 192, .box_w = 10, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 625, .adv_w = 192, .box_w = 11, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 645, .adv_w = 192, .box_w = 9, .box_h = 14, .ofs_x = 2, .ofs_y = 0}, + {.bitmap_index = 661, .adv_w = 192, .box_w = 10, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 679, .adv_w = 192, .box_w = 9, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 695, .adv_w = 192, .box_w = 10, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 713, .adv_w = 192, .box_w = 10, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 731, .adv_w = 192, .box_w = 10, .box_h = 17, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 753, .adv_w = 192, .box_w = 10, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 771, .adv_w = 192, .box_w = 10, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 789, .adv_w = 192, .box_w = 10, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 807, .adv_w = 192, .box_w = 9, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 823, .adv_w = 192, .box_w = 12, .box_h = 14, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 844, .adv_w = 192, .box_w = 12, .box_h = 14, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 865, .adv_w = 192, .box_w = 10, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 883, .adv_w = 192, .box_w = 11, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 903, .adv_w = 192, .box_w = 9, .box_h = 14, .ofs_x = 2, .ofs_y = 0}, + {.bitmap_index = 919, .adv_w = 192, .box_w = 6, .box_h = 18, .ofs_x = 4, .ofs_y = -2}, + {.bitmap_index = 933, .adv_w = 192, .box_w = 10, .box_h = 19, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 957, .adv_w = 192, .box_w = 6, .box_h = 18, .ofs_x = 3, .ofs_y = -2}, + {.bitmap_index = 971, .adv_w = 192, .box_w = 10, .box_h = 8, .ofs_x = 1, .ofs_y = 6}, + {.bitmap_index = 981, .adv_w = 192, .box_w = 10, .box_h = 2, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 984, .adv_w = 192, .box_w = 5, .box_h = 3, .ofs_x = 3, .ofs_y = 13}, + {.bitmap_index = 986, .adv_w = 192, .box_w = 10, .box_h = 11, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1000, .adv_w = 192, .box_w = 10, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1018, .adv_w = 192, .box_w = 10, .box_h = 11, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1032, .adv_w = 192, .box_w = 10, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1050, .adv_w = 192, .box_w = 10, .box_h = 11, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1064, .adv_w = 192, .box_w = 10, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1082, .adv_w = 192, .box_w = 10, .box_h = 14, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 1100, .adv_w = 192, .box_w = 9, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1116, .adv_w = 192, .box_w = 10, .box_h = 15, .ofs_x = 2, .ofs_y = 0}, + {.bitmap_index = 1135, .adv_w = 192, .box_w = 8, .box_h = 18, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 1153, .adv_w = 192, .box_w = 10, .box_h = 14, .ofs_x = 2, .ofs_y = 0}, + {.bitmap_index = 1171, .adv_w = 192, .box_w = 11, .box_h = 14, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1191, .adv_w = 192, .box_w = 10, .box_h = 11, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1205, .adv_w = 192, .box_w = 9, .box_h = 11, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1218, .adv_w = 192, .box_w = 10, .box_h = 11, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1232, .adv_w = 192, .box_w = 10, .box_h = 14, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 1250, .adv_w = 192, .box_w = 10, .box_h = 14, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 1268, .adv_w = 192, .box_w = 10, .box_h = 11, .ofs_x = 2, .ofs_y = 0}, + {.bitmap_index = 1282, .adv_w = 192, .box_w = 10, .box_h = 11, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1296, .adv_w = 192, .box_w = 10, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1314, .adv_w = 192, .box_w = 9, .box_h = 11, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1327, .adv_w = 192, .box_w = 10, .box_h = 11, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1341, .adv_w = 192, .box_w = 12, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1358, .adv_w = 192, .box_w = 10, .box_h = 11, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1372, .adv_w = 192, .box_w = 10, .box_h = 14, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 1390, .adv_w = 192, .box_w = 9, .box_h = 11, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1403, .adv_w = 192, .box_w = 9, .box_h = 18, .ofs_x = 2, .ofs_y = -2}, + {.bitmap_index = 1424, .adv_w = 192, .box_w = 3, .box_h = 18, .ofs_x = 5, .ofs_y = -2}, + {.bitmap_index = 1431, .adv_w = 192, .box_w = 10, .box_h = 18, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 1454, .adv_w = 192, .box_w = 10, .box_h = 4, .ofs_x = 1, .ofs_y = 5} +}; + +/*--------------------- + * CHARACTER MAPPING + *--------------------*/ + + + +/*Collect the unicode lists and glyph_id offsets*/ +static const lv_font_fmt_txt_cmap_t cmaps[] = +{ + { + .range_start = 32, .range_length = 95, .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 + *--------------------*/ + +/*Store all the custom data of the font*/ +static lv_font_fmt_txt_dsc_t font_dsc = { + .glyph_bitmap = gylph_bitmap, + .glyph_dsc = glyph_dsc, + .cmaps = cmaps, + .kern_dsc = NULL, + .kern_scale = 0, + .cmap_num = 1, + .bpp = 1, + .kern_classes = 0, + .bitmap_format = 0 +}; + + +/*----------------- + * PUBLIC FONT + *----------------*/ + +/*Initialize a public general font descriptor*/ +lv_font_t jetbrains_mono_bold_20 = { + .get_glyph_dsc = lv_font_get_glyph_dsc_fmt_txt, /*Function pointer to get glyph's data*/ + .get_glyph_bitmap = lv_font_get_bitmap_fmt_txt, /*Function pointer to get glyph's bitmap*/ + .line_height = 20, /*The maximum line height required by the font*/ + .base_line = 3, /*Baseline measured from the bottom of the line*/ +#if !(LVGL_VERSION_MAJOR == 6 && LVGL_VERSION_MINOR == 0) + .subpx = LV_FONT_SUBPX_NONE, +#endif + .dsc = &font_dsc /*The custom font data. Will be accessed by `get_glyph_bitmap/dsc` */ +}; + +#endif /*#if JETBRAINS_MONO_BOLD_20*/ + diff --git a/src/DisplayApp/Fonts/jetbrains_mono_extrabold_compressed.c b/src/DisplayApp/Fonts/jetbrains_mono_extrabold_compressed.c new file mode 100644 index 00000000..c9917e40 --- /dev/null +++ b/src/DisplayApp/Fonts/jetbrains_mono_extrabold_compressed.c @@ -0,0 +1,507 @@ +#include "lvgl/lvgl.h" + +/******************************************************************************* + * Size: 80 px + * Bpp: 1 + * Opts: + ******************************************************************************/ + +#ifndef JETBRAINS_MONO_EXTRABOLD_COMPRESSED +#define JETBRAINS_MONO_EXTRABOLD_COMPRESSED 1 +#endif + +#if JETBRAINS_MONO_EXTRABOLD_COMPRESSED + +/*----------------- + * BITMAPS + *----------------*/ + +/*Store the image of the glyphs*/ +static LV_ATTRIBUTE_LARGE_CONST const uint8_t gylph_bitmap[] = { + /* U+30 "0" */ + 0x0, 0x1, 0xff, 0xc0, 0x0, 0x0, 0xf, 0xff, + 0xfe, 0x0, 0x0, 0x1f, 0xff, 0xff, 0xc0, 0x0, + 0x3f, 0xff, 0xff, 0xf8, 0x0, 0x3f, 0xff, 0xff, + 0xfe, 0x0, 0x3f, 0xff, 0xff, 0xff, 0x80, 0x3f, + 0xff, 0xff, 0xff, 0xe0, 0x3f, 0xff, 0xff, 0xff, + 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xfc, 0x1f, 0xff, + 0xff, 0xff, 0xff, 0x1f, 0xff, 0xe0, 0x3f, 0xff, + 0xcf, 0xff, 0xc0, 0x7, 0xff, 0xe7, 0xff, 0xc0, + 0x1, 0xff, 0xf7, 0xff, 0xc0, 0x0, 0x7f, 0xff, + 0xff, 0xe0, 0x0, 0x3f, 0xff, 0xff, 0xe0, 0x0, + 0xf, 0xff, 0xff, 0xf0, 0x0, 0x7, 0xff, 0xff, + 0xf8, 0x0, 0x3, 0xff, 0xff, 0xfc, 0x0, 0x1, + 0xff, 0xff, 0xfe, 0x0, 0x0, 0xff, 0xff, 0xff, + 0x0, 0x0, 0x7f, 0xff, 0xff, 0x80, 0x0, 0x3f, + 0xff, 0xff, 0xc0, 0x70, 0x1f, 0xff, 0xff, 0xe0, + 0x7c, 0xf, 0xff, 0xff, 0xf0, 0x7f, 0x7, 0xff, + 0xff, 0xf8, 0x3f, 0x83, 0xff, 0xff, 0xfc, 0x1f, + 0xc1, 0xff, 0xff, 0xfe, 0xf, 0xe0, 0xff, 0xff, + 0xff, 0x7, 0xf0, 0x7f, 0xff, 0xff, 0x83, 0xf8, + 0x3f, 0xff, 0xff, 0xc1, 0xfc, 0x1f, 0xff, 0xff, + 0xe0, 0xfe, 0xf, 0xff, 0xff, 0xf0, 0x7f, 0x7, + 0xff, 0xff, 0xf8, 0x3f, 0x83, 0xff, 0xff, 0xfc, + 0x1f, 0xc1, 0xff, 0xff, 0xfe, 0xf, 0xe0, 0xff, + 0xff, 0xff, 0x3, 0xe0, 0x7f, 0xff, 0xff, 0x80, + 0xe0, 0x3f, 0xff, 0xff, 0xc0, 0x0, 0x1f, 0xff, + 0xff, 0xe0, 0x0, 0xf, 0xff, 0xff, 0xf0, 0x0, + 0x7, 0xff, 0xff, 0xf8, 0x0, 0x3, 0xff, 0xff, + 0xfc, 0x0, 0x1, 0xff, 0xff, 0xfe, 0x0, 0x0, + 0xff, 0xff, 0xff, 0x80, 0x0, 0xff, 0xff, 0xff, + 0xc0, 0x0, 0x7f, 0xf9, 0xff, 0xf0, 0x0, 0x7f, + 0xfc, 0xff, 0xfc, 0x0, 0x7f, 0xfe, 0x7f, 0xff, + 0x80, 0xff, 0xfe, 0x1f, 0xff, 0xff, 0xff, 0xff, + 0x7, 0xff, 0xff, 0xff, 0xff, 0x3, 0xff, 0xff, + 0xff, 0xff, 0x80, 0xff, 0xff, 0xff, 0xff, 0x80, + 0x3f, 0xff, 0xff, 0xff, 0x80, 0xf, 0xff, 0xff, + 0xff, 0x80, 0x3, 0xff, 0xff, 0xff, 0x0, 0x0, + 0x7f, 0xff, 0xff, 0x0, 0x0, 0xf, 0xff, 0xfc, + 0x0, 0x0, 0x0, 0x7f, 0xf0, 0x0, 0x0, + + /* U+31 "1" */ + 0x0, 0x7, 0xff, 0xe0, 0x0, 0x0, 0xf, 0xff, + 0xe0, 0x0, 0x0, 0x3f, 0xff, 0xe0, 0x0, 0x0, + 0x7f, 0xff, 0xe0, 0x0, 0x1, 0xff, 0xff, 0xe0, + 0x0, 0x3, 0xff, 0xff, 0xe0, 0x0, 0x7, 0xff, + 0xff, 0xe0, 0x0, 0x1f, 0xff, 0xff, 0xe0, 0x0, + 0x3f, 0xff, 0xff, 0xe0, 0x0, 0x7f, 0xff, 0xff, + 0xe0, 0x0, 0x7f, 0xff, 0xff, 0xe0, 0x0, 0x7f, + 0xfd, 0xff, 0xe0, 0x0, 0x7f, 0xf9, 0xff, 0xe0, + 0x0, 0x7f, 0xf1, 0xff, 0xe0, 0x0, 0x7f, 0xe1, + 0xff, 0xe0, 0x0, 0x7f, 0x81, 0xff, 0xe0, 0x0, + 0x7f, 0x1, 0xff, 0xe0, 0x0, 0x7c, 0x1, 0xff, + 0xe0, 0x0, 0x78, 0x1, 0xff, 0xe0, 0x0, 0x60, + 0x1, 0xff, 0xe0, 0x0, 0x40, 0x1, 0xff, 0xe0, + 0x0, 0x0, 0x1, 0xff, 0xe0, 0x0, 0x0, 0x1, + 0xff, 0xe0, 0x0, 0x0, 0x1, 0xff, 0xe0, 0x0, + 0x0, 0x1, 0xff, 0xe0, 0x0, 0x0, 0x1, 0xff, + 0xe0, 0x0, 0x0, 0x1, 0xff, 0xe0, 0x0, 0x0, + 0x1, 0xff, 0xe0, 0x0, 0x0, 0x1, 0xff, 0xe0, + 0x0, 0x0, 0x1, 0xff, 0xe0, 0x0, 0x0, 0x1, + 0xff, 0xe0, 0x0, 0x0, 0x1, 0xff, 0xe0, 0x0, + 0x0, 0x1, 0xff, 0xe0, 0x0, 0x0, 0x1, 0xff, + 0xe0, 0x0, 0x0, 0x1, 0xff, 0xe0, 0x0, 0x0, + 0x1, 0xff, 0xe0, 0x0, 0x0, 0x1, 0xff, 0xe0, + 0x0, 0x0, 0x1, 0xff, 0xe0, 0x0, 0x0, 0x1, + 0xff, 0xe0, 0x0, 0x0, 0x1, 0xff, 0xe0, 0x0, + 0x0, 0x1, 0xff, 0xe0, 0x0, 0x0, 0x1, 0xff, + 0xe0, 0x0, 0x0, 0x1, 0xff, 0xe0, 0x0, 0x0, + 0x1, 0xff, 0xe0, 0x0, 0x0, 0x1, 0xff, 0xe0, + 0x0, 0x0, 0x1, 0xff, 0xe0, 0x0, 0x0, 0x1, + 0xff, 0xe0, 0x0, 0x0, 0x1, 0xff, 0xe0, 0x0, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, + + /* U+32 "2" */ + 0x0, 0x1, 0xff, 0xc0, 0x0, 0x0, 0xf, 0xff, + 0xfc, 0x0, 0x0, 0x1f, 0xff, 0xff, 0x80, 0x0, + 0x3f, 0xff, 0xff, 0xf0, 0x0, 0x3f, 0xff, 0xff, + 0xfc, 0x0, 0x3f, 0xff, 0xff, 0xff, 0x0, 0x3f, + 0xff, 0xff, 0xff, 0xc0, 0x3f, 0xff, 0xff, 0xff, + 0xf0, 0x3f, 0xff, 0xff, 0xff, 0xfc, 0x1f, 0xff, + 0xff, 0xff, 0xfe, 0x1f, 0xff, 0xe0, 0x7f, 0xff, + 0x8f, 0xff, 0xc0, 0xf, 0xff, 0xc7, 0xff, 0xc0, + 0x3, 0xff, 0xe7, 0xff, 0xc0, 0x0, 0xff, 0xfb, + 0xff, 0xc0, 0x0, 0x7f, 0xfd, 0xff, 0xe0, 0x0, + 0x1f, 0xfe, 0xff, 0xf0, 0x0, 0xf, 0xff, 0x0, + 0x0, 0x0, 0x7, 0xff, 0x80, 0x0, 0x0, 0x3, + 0xff, 0xc0, 0x0, 0x0, 0x1, 0xff, 0xe0, 0x0, + 0x0, 0x0, 0xff, 0xf0, 0x0, 0x0, 0x0, 0xff, + 0xf8, 0x0, 0x0, 0x0, 0x7f, 0xf8, 0x0, 0x0, + 0x0, 0x7f, 0xfc, 0x0, 0x0, 0x0, 0x3f, 0xfe, + 0x0, 0x0, 0x0, 0x3f, 0xfe, 0x0, 0x0, 0x0, + 0x3f, 0xff, 0x0, 0x0, 0x0, 0x3f, 0xff, 0x0, + 0x0, 0x0, 0x3f, 0xff, 0x0, 0x0, 0x0, 0x3f, + 0xff, 0x80, 0x0, 0x0, 0x7f, 0xff, 0x80, 0x0, + 0x0, 0x7f, 0xff, 0x80, 0x0, 0x0, 0x7f, 0xff, + 0x80, 0x0, 0x0, 0x7f, 0xff, 0x80, 0x0, 0x0, + 0xff, 0xff, 0x80, 0x0, 0x0, 0xff, 0xff, 0x80, + 0x0, 0x0, 0xff, 0xff, 0x80, 0x0, 0x0, 0xff, + 0xff, 0x80, 0x0, 0x1, 0xff, 0xff, 0x0, 0x0, + 0x1, 0xff, 0xff, 0x0, 0x0, 0x1, 0xff, 0xff, + 0x0, 0x0, 0x1, 0xff, 0xfe, 0x0, 0x0, 0x3, + 0xff, 0xfe, 0x0, 0x0, 0x3, 0xff, 0xfe, 0x0, + 0x0, 0x3, 0xff, 0xfc, 0x0, 0x0, 0x3, 0xff, + 0xfc, 0x0, 0x0, 0x1, 0xff, 0xf0, 0x0, 0x0, + 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, + 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, + 0xdf, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xff, + 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xfb, + 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, + 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, + 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, + 0xff, 0xc0, + + /* U+33 "3" */ + 0x1f, 0xff, 0xff, 0xff, 0xfe, 0xf, 0xff, 0xff, + 0xff, 0xff, 0x7, 0xff, 0xff, 0xff, 0xff, 0x83, + 0xff, 0xff, 0xff, 0xff, 0xc1, 0xff, 0xff, 0xff, + 0xff, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x7f, + 0xff, 0xff, 0xff, 0xf8, 0x3f, 0xff, 0xff, 0xff, + 0xfc, 0x1f, 0xff, 0xff, 0xff, 0xfe, 0xf, 0xff, + 0xff, 0x8f, 0xff, 0x0, 0x0, 0x0, 0xf, 0xff, + 0x80, 0x0, 0x0, 0x1f, 0xff, 0x80, 0x0, 0x0, + 0x1f, 0xff, 0x80, 0x0, 0x0, 0x3f, 0xff, 0x80, + 0x0, 0x0, 0x3f, 0xff, 0x0, 0x0, 0x0, 0x3f, + 0xff, 0x0, 0x0, 0x0, 0x3f, 0xff, 0x0, 0x0, + 0x0, 0x3f, 0xff, 0x0, 0x0, 0x0, 0x3f, 0xfe, + 0x0, 0x0, 0x0, 0x3f, 0xfe, 0x0, 0x0, 0x0, + 0x3f, 0xfe, 0x0, 0x0, 0x0, 0x3f, 0xfc, 0x0, + 0x0, 0x0, 0x1f, 0xff, 0x80, 0x0, 0x0, 0xf, + 0xff, 0xf8, 0x0, 0x0, 0x7, 0xff, 0xff, 0x0, + 0x0, 0x3, 0xff, 0xff, 0xe0, 0x0, 0x1, 0xff, + 0xff, 0xf8, 0x0, 0x0, 0xff, 0xff, 0xfe, 0x0, + 0x0, 0x7f, 0xff, 0xff, 0x80, 0x0, 0x3f, 0xff, + 0xff, 0xe0, 0x0, 0x1f, 0xff, 0xff, 0xf0, 0x0, + 0xf, 0xff, 0xff, 0xfc, 0x0, 0x0, 0x0, 0xff, + 0xfe, 0x0, 0x0, 0x0, 0x1f, 0xff, 0x80, 0x0, + 0x0, 0x7, 0xff, 0xc0, 0x0, 0x0, 0x1, 0xff, + 0xe0, 0x0, 0x0, 0x0, 0xff, 0xf8, 0x0, 0x0, + 0x0, 0x3f, 0xfc, 0x0, 0x0, 0x0, 0x1f, 0xfe, + 0x0, 0x0, 0x0, 0xf, 0xff, 0x0, 0x0, 0x0, + 0x7, 0xff, 0x80, 0x0, 0x0, 0x3, 0xff, 0xc0, + 0x0, 0x0, 0x1, 0xff, 0xff, 0xfe, 0x0, 0x0, + 0xff, 0xff, 0xff, 0x80, 0x0, 0xff, 0xff, 0xff, + 0xc0, 0x0, 0x7f, 0xf9, 0xff, 0xf0, 0x0, 0x7f, + 0xfc, 0xff, 0xfc, 0x0, 0x7f, 0xfe, 0x7f, 0xff, + 0x80, 0xff, 0xfe, 0x1f, 0xff, 0xff, 0xff, 0xff, + 0xf, 0xff, 0xff, 0xff, 0xff, 0x3, 0xff, 0xff, + 0xff, 0xff, 0x80, 0xff, 0xff, 0xff, 0xff, 0x80, + 0x3f, 0xff, 0xff, 0xff, 0x80, 0xf, 0xff, 0xff, + 0xff, 0x80, 0x3, 0xff, 0xff, 0xff, 0x0, 0x0, + 0x7f, 0xff, 0xff, 0x0, 0x0, 0xf, 0xff, 0xfc, + 0x0, 0x0, 0x0, 0x7f, 0xf0, 0x0, 0x0, + + /* U+34 "4" */ + 0x0, 0x0, 0x3, 0xff, 0xf0, 0x0, 0x0, 0x1f, + 0xff, 0x80, 0x0, 0x0, 0x7f, 0xfc, 0x0, 0x0, + 0x3, 0xff, 0xe0, 0x0, 0x0, 0x1f, 0xff, 0x80, + 0x0, 0x0, 0xff, 0xfc, 0x0, 0x0, 0x3, 0xff, + 0xe0, 0x0, 0x0, 0x1f, 0xff, 0x0, 0x0, 0x0, + 0xff, 0xfc, 0x0, 0x0, 0x7, 0xff, 0xe0, 0x0, + 0x0, 0x1f, 0xff, 0x0, 0x0, 0x0, 0xff, 0xfc, + 0x0, 0x0, 0x7, 0xff, 0xe0, 0x0, 0x0, 0x3f, + 0xff, 0x0, 0x0, 0x0, 0xff, 0xf8, 0x0, 0x0, + 0x7, 0xff, 0xe0, 0x0, 0x0, 0x3f, 0xff, 0x0, + 0x0, 0x0, 0xff, 0xf8, 0x0, 0x0, 0x7, 0xff, + 0xc0, 0x0, 0x0, 0x3f, 0xff, 0x0, 0x0, 0x1, + 0xff, 0xf8, 0x0, 0x0, 0x7, 0xff, 0xc0, 0x0, + 0x0, 0x3f, 0xfe, 0x0, 0x0, 0x1, 0xff, 0xf8, + 0x0, 0x0, 0xf, 0xff, 0xc0, 0x0, 0x0, 0x3f, + 0xfe, 0x0, 0xff, 0xf1, 0xff, 0xf0, 0x3, 0xff, + 0xcf, 0xff, 0xc0, 0xf, 0xff, 0x7f, 0xfe, 0x0, + 0x3f, 0xfd, 0xff, 0xf0, 0x0, 0xff, 0xff, 0xff, + 0xc0, 0x3, 0xff, 0xff, 0xfe, 0x0, 0xf, 0xff, + 0xff, 0xf0, 0x0, 0x3f, 0xff, 0xff, 0x80, 0x0, + 0xff, 0xff, 0xfe, 0x0, 0x3, 0xff, 0xff, 0xf8, + 0x0, 0xf, 0xff, 0xff, 0xe0, 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, 0xc0, + 0x0, 0x0, 0xf, 0xff, 0x0, 0x0, 0x0, 0x3f, + 0xfc, 0x0, 0x0, 0x0, 0xff, 0xf0, 0x0, 0x0, + 0x3, 0xff, 0xc0, 0x0, 0x0, 0xf, 0xff, 0x0, + 0x0, 0x0, 0x3f, 0xfc, 0x0, 0x0, 0x0, 0xff, + 0xf0, 0x0, 0x0, 0x3, 0xff, 0xc0, 0x0, 0x0, + 0xf, 0xff, 0x0, 0x0, 0x0, 0x3f, 0xfc, 0x0, + 0x0, 0x0, 0xff, 0xf0, + + /* U+35 "5" */ + 0x3f, 0xff, 0xff, 0xff, 0xfe, 0x1f, 0xff, 0xff, + 0xff, 0xff, 0xf, 0xff, 0xff, 0xff, 0xff, 0x87, + 0xff, 0xff, 0xff, 0xff, 0xc3, 0xff, 0xff, 0xff, + 0xff, 0xe1, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xff, + 0xff, 0xff, 0xff, 0xf8, 0x7f, 0xff, 0xff, 0xff, + 0xfc, 0x3f, 0xff, 0xff, 0xff, 0xfe, 0x1f, 0xff, + 0xff, 0xff, 0xff, 0xf, 0xff, 0x0, 0x0, 0x0, + 0x7, 0xff, 0x80, 0x0, 0x0, 0x3, 0xff, 0xc0, + 0x0, 0x0, 0x1, 0xff, 0xe0, 0x0, 0x0, 0x0, + 0xff, 0xf0, 0x0, 0x0, 0x0, 0x7f, 0xf8, 0x0, + 0x0, 0x0, 0x3f, 0xfc, 0x0, 0x0, 0x0, 0x1f, + 0xfe, 0x0, 0x0, 0x0, 0xf, 0xff, 0x0, 0x0, + 0x0, 0x7, 0xff, 0x80, 0x0, 0x0, 0x3, 0xff, + 0xc0, 0x7f, 0x80, 0x1, 0xff, 0xe1, 0xff, 0xf8, + 0x0, 0xff, 0xf1, 0xff, 0xff, 0x0, 0x7f, 0xf9, + 0xff, 0xff, 0xc0, 0x3f, 0xfd, 0xff, 0xff, 0xf0, + 0x1f, 0xff, 0xff, 0xff, 0xfc, 0xf, 0xff, 0xff, + 0xff, 0xff, 0x7, 0xff, 0xff, 0xff, 0xff, 0xc3, + 0xff, 0xff, 0xff, 0xff, 0xe1, 0xff, 0xfc, 0x7, + 0xff, 0xf8, 0xff, 0xf8, 0x0, 0xff, 0xfc, 0x0, + 0x0, 0x0, 0x3f, 0xfe, 0x0, 0x0, 0x0, 0xf, + 0xff, 0x80, 0x0, 0x0, 0x7, 0xff, 0xc0, 0x0, + 0x0, 0x1, 0xff, 0xe0, 0x0, 0x0, 0x0, 0xff, + 0xf0, 0x0, 0x0, 0x0, 0x7f, 0xf8, 0x0, 0x0, + 0x0, 0x3f, 0xfc, 0x0, 0x0, 0x0, 0x1f, 0xfe, + 0x0, 0x0, 0x0, 0xf, 0xff, 0x0, 0x0, 0x0, + 0x7, 0xff, 0x80, 0x0, 0x0, 0x3, 0xff, 0xc0, + 0x0, 0x0, 0x1, 0xff, 0xff, 0xff, 0x0, 0x1, + 0xff, 0xff, 0xff, 0x80, 0x0, 0xff, 0xfb, 0xff, + 0xe0, 0x0, 0xff, 0xf9, 0xff, 0xf8, 0x0, 0xff, + 0xfc, 0xff, 0xff, 0x81, 0xff, 0xfe, 0x3f, 0xff, + 0xff, 0xff, 0xfe, 0x1f, 0xff, 0xff, 0xff, 0xff, + 0x7, 0xff, 0xff, 0xff, 0xff, 0x1, 0xff, 0xff, + 0xff, 0xff, 0x0, 0x7f, 0xff, 0xff, 0xff, 0x0, + 0x1f, 0xff, 0xff, 0xff, 0x0, 0x7, 0xff, 0xff, + 0xff, 0x0, 0x0, 0xff, 0xff, 0xfe, 0x0, 0x0, + 0x1f, 0xff, 0xfc, 0x0, 0x0, 0x0, 0xff, 0xe0, + 0x0, 0x0, + + /* U+36 "6" */ + 0x0, 0x0, 0xf, 0xff, 0x80, 0x0, 0x0, 0x7, + 0xff, 0xe0, 0x0, 0x0, 0x3, 0xff, 0xf0, 0x0, + 0x0, 0x0, 0xff, 0xf8, 0x0, 0x0, 0x0, 0x7f, + 0xfe, 0x0, 0x0, 0x0, 0x3f, 0xff, 0x0, 0x0, + 0x0, 0xf, 0xff, 0x80, 0x0, 0x0, 0x7, 0xff, + 0xc0, 0x0, 0x0, 0x3, 0xff, 0xf0, 0x0, 0x0, + 0x0, 0xff, 0xf8, 0x0, 0x0, 0x0, 0x7f, 0xfc, + 0x0, 0x0, 0x0, 0x3f, 0xff, 0x0, 0x0, 0x0, + 0xf, 0xff, 0x80, 0x0, 0x0, 0x7, 0xff, 0xc0, + 0x0, 0x0, 0x3, 0xff, 0xf0, 0x0, 0x0, 0x1, + 0xff, 0xf8, 0x0, 0x0, 0x0, 0x7f, 0xfc, 0x0, + 0x0, 0x0, 0x3f, 0xfe, 0x0, 0x0, 0x0, 0xf, + 0xff, 0x80, 0x0, 0x0, 0x7, 0xff, 0xc0, 0x0, + 0x0, 0x3, 0xff, 0xe0, 0x0, 0x0, 0x0, 0xff, + 0xf8, 0x0, 0x0, 0x0, 0x7f, 0xfc, 0x3f, 0xc0, + 0x0, 0x1f, 0xfe, 0x3f, 0xfe, 0x0, 0xf, 0xff, + 0xbf, 0xff, 0xe0, 0x3, 0xff, 0xdf, 0xff, 0xfc, + 0x1, 0xff, 0xef, 0xff, 0xff, 0x80, 0x7f, 0xff, + 0xff, 0xff, 0xf0, 0x3f, 0xff, 0xff, 0xff, 0xfe, + 0xf, 0xff, 0xff, 0xff, 0xff, 0x87, 0xff, 0xff, + 0xff, 0xff, 0xf1, 0xff, 0xff, 0x3, 0xff, 0xfc, + 0x7f, 0xff, 0x0, 0x3f, 0xff, 0x9f, 0xff, 0x0, + 0x3, 0xff, 0xef, 0xff, 0xc0, 0x0, 0xff, 0xfb, + 0xff, 0xe0, 0x0, 0x1f, 0xff, 0xff, 0xf8, 0x0, + 0x7, 0xff, 0xff, 0xfc, 0x0, 0x0, 0xff, 0xff, + 0xff, 0x0, 0x0, 0x3f, 0xff, 0xff, 0xc0, 0x0, + 0xf, 0xff, 0xff, 0xf0, 0x0, 0x3, 0xff, 0xff, + 0xfc, 0x0, 0x0, 0xff, 0xff, 0xff, 0x0, 0x0, + 0x3f, 0xff, 0xff, 0xe0, 0x0, 0x1f, 0xff, 0x7f, + 0xf8, 0x0, 0x7, 0xff, 0xdf, 0xfe, 0x0, 0x3, + 0xff, 0xe7, 0xff, 0xc0, 0x0, 0xff, 0xf9, 0xff, + 0xfc, 0x0, 0xff, 0xfe, 0x3f, 0xff, 0xc0, 0xff, + 0xff, 0xf, 0xff, 0xff, 0xff, 0xff, 0xc1, 0xff, + 0xff, 0xff, 0xff, 0xe0, 0x3f, 0xff, 0xff, 0xff, + 0xf0, 0x7, 0xff, 0xff, 0xff, 0xf8, 0x0, 0xff, + 0xff, 0xff, 0xfe, 0x0, 0x1f, 0xff, 0xff, 0xfe, + 0x0, 0x3, 0xff, 0xff, 0xff, 0x0, 0x0, 0x3f, + 0xff, 0xff, 0x0, 0x0, 0x3, 0xff, 0xff, 0x0, + 0x0, 0x0, 0xf, 0xfc, 0x0, 0x0, + + /* U+37 "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, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xe0, 0x0, 0xf, 0xff, 0xff, 0xe0, 0x0, 0x1f, + 0xfe, 0xff, 0xe0, 0x0, 0x1f, 0xfe, 0xff, 0xe0, + 0x0, 0x3f, 0xfc, 0xff, 0xe0, 0x0, 0x3f, 0xfc, + 0xff, 0xe0, 0x0, 0x7f, 0xf8, 0xff, 0xe0, 0x0, + 0x7f, 0xf8, 0xff, 0xe0, 0x0, 0xff, 0xf8, 0xff, + 0xe0, 0x0, 0xff, 0xf0, 0x0, 0x0, 0x1, 0xff, + 0xf0, 0x0, 0x0, 0x1, 0xff, 0xe0, 0x0, 0x0, + 0x3, 0xff, 0xe0, 0x0, 0x0, 0x3, 0xff, 0xc0, + 0x0, 0x0, 0x7, 0xff, 0xc0, 0x0, 0x0, 0x7, + 0xff, 0x80, 0x0, 0x0, 0x7, 0xff, 0x80, 0x0, + 0x0, 0xf, 0xff, 0x80, 0x0, 0x0, 0xf, 0xff, + 0x0, 0x0, 0x0, 0x1f, 0xff, 0x0, 0x0, 0x0, + 0x1f, 0xfe, 0x0, 0x0, 0x0, 0x3f, 0xfe, 0x0, + 0x0, 0x0, 0x3f, 0xfc, 0x0, 0x0, 0x0, 0x7f, + 0xfc, 0x0, 0x0, 0x0, 0x7f, 0xf8, 0x0, 0x0, + 0x0, 0xff, 0xf8, 0x0, 0x0, 0x0, 0xff, 0xf8, + 0x0, 0x0, 0x1, 0xff, 0xf0, 0x0, 0x0, 0x1, + 0xff, 0xf0, 0x0, 0x0, 0x1, 0xff, 0xe0, 0x0, + 0x0, 0x3, 0xff, 0xe0, 0x0, 0x0, 0x3, 0xff, + 0xc0, 0x0, 0x0, 0x7, 0xff, 0xc0, 0x0, 0x0, + 0x7, 0xff, 0x80, 0x0, 0x0, 0xf, 0xff, 0x80, + 0x0, 0x0, 0xf, 0xff, 0x80, 0x0, 0x0, 0x1f, + 0xff, 0x0, 0x0, 0x0, 0x1f, 0xff, 0x0, 0x0, + 0x0, 0x3f, 0xfe, 0x0, 0x0, 0x0, 0x3f, 0xfe, + 0x0, 0x0, 0x0, 0x7f, 0xfc, 0x0, 0x0, 0x0, + 0x7f, 0xfc, 0x0, 0x0, 0x0, 0x7f, 0xf8, 0x0, + 0x0, 0x0, 0xff, 0xf8, 0x0, 0x0, 0x0, 0xff, + 0xf8, 0x0, 0x0, 0x1, 0xff, 0xf0, 0x0, 0x0, + 0x1, 0xff, 0xf0, 0x0, 0x0, 0x3, 0xff, 0xe0, + 0x0, 0x0, + + /* U+38 "8" */ + 0x0, 0x1, 0xff, 0xe0, 0x0, 0x0, 0x7, 0xff, + 0xff, 0x80, 0x0, 0x7, 0xff, 0xff, 0xf8, 0x0, + 0x7, 0xff, 0xff, 0xff, 0x80, 0x3, 0xff, 0xff, + 0xff, 0xf0, 0x1, 0xff, 0xff, 0xff, 0xfe, 0x0, + 0xff, 0xff, 0xff, 0xff, 0xc0, 0x7f, 0xff, 0xff, + 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xfe, 0xf, + 0xff, 0xe0, 0x3f, 0xff, 0xc3, 0xff, 0xe0, 0x3, + 0xff, 0xf0, 0xff, 0xf0, 0x0, 0x7f, 0xfc, 0x7f, + 0xf8, 0x0, 0xf, 0xff, 0x9f, 0xfe, 0x0, 0x3, + 0xff, 0xe7, 0xff, 0x0, 0x0, 0x7f, 0xf9, 0xff, + 0xc0, 0x0, 0x1f, 0xfe, 0x7f, 0xf0, 0x0, 0x7, + 0xff, 0x9f, 0xfc, 0x0, 0x1, 0xff, 0xe7, 0xff, + 0x0, 0x0, 0x7f, 0xf9, 0xff, 0xc0, 0x0, 0x1f, + 0xfe, 0x3f, 0xf8, 0x0, 0xf, 0xff, 0xf, 0xfe, + 0x0, 0x3, 0xff, 0xc3, 0xff, 0xc0, 0x1, 0xff, + 0xe0, 0x7f, 0xf8, 0x0, 0xff, 0xf8, 0xf, 0xff, + 0x80, 0xff, 0xfc, 0x1, 0xff, 0xff, 0xff, 0xfe, + 0x0, 0x3f, 0xff, 0xff, 0xff, 0x0, 0x7, 0xff, + 0xff, 0xff, 0x0, 0x0, 0x7f, 0xff, 0xff, 0x0, + 0x0, 0x3, 0xff, 0xfe, 0x0, 0x0, 0x7, 0xff, + 0xff, 0xf0, 0x0, 0x7, 0xff, 0xff, 0xff, 0x80, + 0x7, 0xff, 0xff, 0xff, 0xf0, 0x3, 0xff, 0xff, + 0xff, 0xff, 0x1, 0xff, 0xf8, 0xf, 0xff, 0xe0, + 0xff, 0xf8, 0x0, 0x7f, 0xf8, 0x3f, 0xfc, 0x0, + 0xf, 0xff, 0x1f, 0xfe, 0x0, 0x1, 0xff, 0xe7, + 0xff, 0x80, 0x0, 0x7f, 0xfb, 0xff, 0xc0, 0x0, + 0xf, 0xfe, 0xff, 0xf0, 0x0, 0x3, 0xff, 0xff, + 0xfc, 0x0, 0x0, 0xff, 0xff, 0xff, 0x0, 0x0, + 0x3f, 0xff, 0xff, 0xc0, 0x0, 0xf, 0xff, 0xff, + 0xf0, 0x0, 0x3, 0xff, 0xff, 0xfe, 0x0, 0x1, + 0xff, 0xff, 0xff, 0x80, 0x0, 0x7f, 0xff, 0xff, + 0xf0, 0x0, 0x3f, 0xff, 0x7f, 0xfe, 0x0, 0x1f, + 0xff, 0x9f, 0xff, 0xe0, 0x3f, 0xff, 0xe3, 0xff, + 0xff, 0xff, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, + 0xfc, 0x1f, 0xff, 0xff, 0xff, 0xfe, 0x3, 0xff, + 0xff, 0xff, 0xff, 0x0, 0x7f, 0xff, 0xff, 0xff, + 0x80, 0xf, 0xff, 0xff, 0xff, 0xc0, 0x1, 0xff, + 0xff, 0xff, 0xe0, 0x0, 0x1f, 0xff, 0xff, 0xe0, + 0x0, 0x1, 0xff, 0xff, 0xe0, 0x0, 0x0, 0x7, + 0xff, 0x80, 0x0, + + /* U+39 "9" */ + 0x0, 0x0, 0xff, 0xc0, 0x0, 0x0, 0x3, 0xff, + 0xff, 0x0, 0x0, 0x3, 0xff, 0xff, 0xf0, 0x0, + 0x3, 0xff, 0xff, 0xff, 0x0, 0x1, 0xff, 0xff, + 0xff, 0xe0, 0x1, 0xff, 0xff, 0xff, 0xfc, 0x0, + 0x7f, 0xff, 0xff, 0xff, 0x80, 0x3f, 0xff, 0xff, + 0xff, 0xf0, 0x1f, 0xff, 0xff, 0xff, 0xfe, 0xf, + 0xff, 0xff, 0xff, 0xff, 0x83, 0xff, 0xfc, 0xf, + 0xff, 0xf1, 0xff, 0xf8, 0x0, 0xff, 0xfc, 0x7f, + 0xfc, 0x0, 0xf, 0xff, 0x9f, 0xff, 0x0, 0x3, + 0xff, 0xef, 0xff, 0x80, 0x0, 0x7f, 0xfb, 0xff, + 0xe0, 0x0, 0x1f, 0xff, 0xff, 0xf0, 0x0, 0x3, + 0xff, 0xff, 0xfc, 0x0, 0x0, 0xff, 0xff, 0xff, + 0x0, 0x0, 0x3f, 0xff, 0xff, 0xc0, 0x0, 0xf, + 0xff, 0xff, 0xf0, 0x0, 0x3, 0xff, 0xff, 0xfc, + 0x0, 0x0, 0xff, 0xff, 0xff, 0x80, 0x0, 0x7f, + 0xff, 0xff, 0xe0, 0x0, 0x1f, 0xff, 0x7f, 0xf8, + 0x0, 0xf, 0xff, 0xdf, 0xff, 0x0, 0x3, 0xff, + 0xe7, 0xff, 0xf0, 0x3, 0xff, 0xf8, 0xff, 0xff, + 0x3, 0xff, 0xfe, 0x3f, 0xff, 0xff, 0xff, 0xff, + 0x87, 0xff, 0xff, 0xff, 0xff, 0xc1, 0xff, 0xff, + 0xff, 0xff, 0xf0, 0x3f, 0xff, 0xff, 0xff, 0xf8, + 0x7, 0xff, 0xff, 0xdf, 0xfe, 0x0, 0xff, 0xff, + 0xef, 0xff, 0x80, 0x1f, 0xff, 0xf7, 0xff, 0xc0, + 0x1, 0xff, 0xf1, 0xff, 0xf0, 0x0, 0xf, 0xf0, + 0xff, 0xf8, 0x0, 0x0, 0x0, 0x7f, 0xfc, 0x0, + 0x0, 0x0, 0x1f, 0xff, 0x0, 0x0, 0x0, 0xf, + 0xff, 0x80, 0x0, 0x0, 0x7, 0xff, 0xe0, 0x0, + 0x0, 0x1, 0xff, 0xf0, 0x0, 0x0, 0x0, 0xff, + 0xf8, 0x0, 0x0, 0x0, 0x7f, 0xfe, 0x0, 0x0, + 0x0, 0x1f, 0xff, 0x0, 0x0, 0x0, 0xf, 0xff, + 0x80, 0x0, 0x0, 0x7, 0xff, 0xe0, 0x0, 0x0, + 0x1, 0xff, 0xf0, 0x0, 0x0, 0x0, 0xff, 0xf8, + 0x0, 0x0, 0x0, 0x7f, 0xfe, 0x0, 0x0, 0x0, + 0x1f, 0xff, 0x0, 0x0, 0x0, 0xf, 0xff, 0x80, + 0x0, 0x0, 0x7, 0xff, 0xe0, 0x0, 0x0, 0x3, + 0xff, 0xf0, 0x0, 0x0, 0x0, 0xff, 0xf8, 0x0, + 0x0, 0x0, 0x7f, 0xfe, 0x0, 0x0, 0x0, 0x3f, + 0xff, 0x0, 0x0, 0x0, 0xf, 0xff, 0x80, 0x0, + 0x0, 0x7, 0xff, 0xe0, 0x0, 0x0, + + /* U+3A ":" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, + 0x7f, 0xfe, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x7, 0xe0, 0x1f, 0xf8, + 0x3f, 0xfc, 0x7f, 0xfe, 0x7f, 0xfe, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x7f, 0xfe, 0x7f, 0xfe, 0x3f, 0xfc, + 0x1f, 0xf8, 0x7, 0xe0 +}; + + +/*--------------------- + * 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 = 768, .box_w = 41, .box_h = 59, .ofs_x = 4, .ofs_y = -1}, + {.bitmap_index = 303, .adv_w = 768, .box_w = 40, .box_h = 58, .ofs_x = 6, .ofs_y = 0}, + {.bitmap_index = 593, .adv_w = 768, .box_w = 41, .box_h = 58, .ofs_x = 4, .ofs_y = 0}, + {.bitmap_index = 891, .adv_w = 768, .box_w = 41, .box_h = 59, .ofs_x = 3, .ofs_y = -1}, + {.bitmap_index = 1194, .adv_w = 768, .box_w = 38, .box_h = 58, .ofs_x = 4, .ofs_y = 0}, + {.bitmap_index = 1470, .adv_w = 768, .box_w = 41, .box_h = 58, .ofs_x = 4, .ofs_y = -1}, + {.bitmap_index = 1768, .adv_w = 768, .box_w = 42, .box_h = 59, .ofs_x = 3, .ofs_y = -1}, + {.bitmap_index = 2078, .adv_w = 768, .box_w = 40, .box_h = 58, .ofs_x = 4, .ofs_y = 0}, + {.bitmap_index = 2368, .adv_w = 768, .box_w = 42, .box_h = 60, .ofs_x = 3, .ofs_y = -1}, + {.bitmap_index = 2683, .adv_w = 768, .box_w = 42, .box_h = 59, .ofs_x = 3, .ofs_y = 0}, + {.bitmap_index = 2993, .adv_w = 768, .box_w = 16, .box_h = 46, .ofs_x = 16, .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 = 11, .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 + *--------------------*/ + +/*Store all the custom data of the font*/ +static lv_font_fmt_txt_dsc_t font_dsc = { + .glyph_bitmap = gylph_bitmap, + .glyph_dsc = glyph_dsc, + .cmaps = cmaps, + .kern_dsc = NULL, + .kern_scale = 0, + .cmap_num = 1, + .bpp = 1, + .kern_classes = 0, + .bitmap_format = 0 +}; + + +/*----------------- + * PUBLIC FONT + *----------------*/ + +/*Initialize a public general font descriptor*/ +lv_font_t jetbrains_mono_extrabold_compressed = { + .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 = 60, /*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 + .dsc = &font_dsc /*The custom font data. Will be accessed by `get_glyph_bitmap/dsc` */ +}; + +#endif /*#if JETBRAINS_MONO_EXTRABOLD_COMPRESSED*/ + diff --git a/src/DisplayApp/LittleVgl.cpp b/src/DisplayApp/LittleVgl.cpp new file mode 100644 index 00000000..905c00ba --- /dev/null +++ b/src/DisplayApp/LittleVgl.cpp @@ -0,0 +1,717 @@ +#include <FreeRTOS.h> +#include <projdefs.h> +#include <task.h> +#include <libs/lvgl/src/lv_core/lv_obj.h> +#include <hal/nrf_rtc.h> +#include <libraries/log/nrf_log.h> + +#include <libs/lvgl/src/lv_themes/lv_theme.h> +#include <libs/lvgl/src/lv_themes/lv_theme_night.h> + +#include "LittleVgl.h" + +using namespace Pinetime::Components; + +extern "C" { +LV_FONT_DECLARE(jetbrains_mono_extrabold_compressed) +LV_FONT_DECLARE(jetbrains_mono_bold_20) +} + +static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p) { + auto* lvgl = static_cast<LittleVgl*>(disp_drv->user_data); + lvgl->FlushDisplay(area, color_p); +} + +bool touchpad_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data) { + auto* lvgl = static_cast<LittleVgl*>(indev_drv->user_data); + return lvgl->GetTouchPadInfo(data); +} + +LittleVgl::LittleVgl(Pinetime::Drivers::St7789& lcd, Pinetime::Drivers::Cst816S& touchPanel) : lcd{lcd}, touchPanel{touchPanel}, previousClick{0,0} { + lv_init(); + InitTheme(); + InitDisplay(); + InitTouchpad(); +} + +void LittleVgl::InitDisplay() { + lv_disp_buf_init(&disp_buf_2, buf2_1, buf2_2, LV_HOR_RES_MAX * 4); /*Initialize the display buffer*/ + lv_disp_drv_init(&disp_drv); /*Basic initialization*/ + + /*Set up the functions to access to your display*/ + + /*Set the resolution of the display*/ + disp_drv.hor_res = 240; + disp_drv.ver_res = 240; + + /*Used to copy the buffer's content to the display*/ + disp_drv.flush_cb = disp_flush; + /*Set a display buffer*/ + disp_drv.buffer = &disp_buf_2; + disp_drv.user_data = this; + + /*Finally register the driver*/ + lv_disp_drv_register(&disp_drv); +} + +void LittleVgl::InitTouchpad() { + lv_indev_drv_t indev_drv; + + lv_indev_drv_init(&indev_drv); + indev_drv.type = LV_INDEV_TYPE_POINTER; + indev_drv.read_cb = touchpad_read; + indev_drv.user_data = this; + lv_indev_drv_register(&indev_drv); +} + +void LittleVgl::FlushDisplay(const lv_area_t *area, lv_color_t *color_p) { + ulTaskNotifyTake(pdTRUE, 500); + + auto x = area->x1; + auto y = area->y1; + auto width = (area->x2-area->x1)+1; + auto height = (area->y2-area->y1)+1; + lcd.BeginDrawBuffer(x, y, width, height); + lcd.NextDrawBuffer(reinterpret_cast<const uint8_t *>(color_p), width * height*2) ; + + /* IMPORTANT!!! + * Inform the graphics library that you are ready with the flushing*/ + lv_disp_flush_ready(&disp_drv); +} + +bool LittleVgl::GetTouchPadInfo(lv_indev_data_t *ptr) { + auto info = touchPanel.GetTouchInfo(); + + if((previousClick.x != info.x || previousClick.y != info.y) && + (info.gesture == Drivers::Cst816S::Gestures::SingleTap)) { + // TODO For an unknown reason, the first touch is taken twice into account. + // 'firstTouch' is a quite'n'dirty workaound until I find a better solution + if(firstTouch) ptr->state = LV_INDEV_STATE_REL; + else ptr->state = LV_INDEV_STATE_PR; + firstTouch = false; + previousClick.x = info.x; + previousClick.y = info.y; + } + else { + ptr->state = LV_INDEV_STATE_REL; + } + + ptr->point.x = info.x; + ptr->point.y = info.y; + return false; +} + +void LittleVgl::InitTheme() { + uint16_t i; + lv_style_t ** style_p = (lv_style_t **)&theme.style; + for(i = 0; i < LV_THEME_STYLE_COUNT; i++) { + *style_p = &def; + style_p++; + } + + InitBaseTheme(); + InitThemeContainer(); + InitThemeButton(); + InitThemeLabel(); + InitThemeLine(); + InitThemeLed(); + InitThemeImage(); + InitThemeBar(); + InitThemeSlider(); + InitThemeSwitch(); + InitThemeMeter(); + InitThemeGauge(); + InitThemeArc(); + InitThemePreload(); + InitThemeChart(); + InitThemeCalendar(); + InitThemeCheckBox(); + InitThemeButtonMatrix(); + InitThemeKnob(); + InitThemeMessageBox(); + InitThemePage(); + InitThemeTextArea(); + InitThemeSpinBox(); + InitThemeList(); + InitThemeDropDownList(); + InitThemeRoller(); + InitThemeTabView(); + InitThemeTileView(); + InitThemeTable(); + InitThemeWindow(); + + lv_theme_set_current(&theme); +} + +void LittleVgl::InitBaseTheme() { + if(font == nullptr) font = &jetbrains_mono_bold_20; + lv_style_copy(&def, &lv_style_plain); /*Initialize the default style*/ + def.text.font = font; + + lv_style_copy(&bg, &lv_style_plain); + bg.body.main_color = LV_COLOR_BLACK; + bg.body.grad_color = LV_COLOR_BLACK; + bg.text.color = LV_COLOR_WHITE; + bg.text.font = font; + bg.image.color = LV_COLOR_WHITE; + + lv_style_copy(&scr, &bg); + scr.body.padding.bottom = 0; + scr.body.padding.top = 0; + scr.body.padding.left = 0; + scr.body.padding.right = 0; + + lv_style_copy(&sb, &def); + sb.body.main_color = lv_color_hsv_to_rgb(hue, 30, 60); + sb.body.grad_color = lv_color_hsv_to_rgb(hue, 30, 60); + sb.body.border.width = 0; + sb.body.padding.inner = LV_DPI / 20; + sb.body.padding.left = 0; + sb.body.padding.right = 0; + sb.body.padding.top = 0; + sb.body.padding.bottom = 0; + sb.body.radius = LV_DPI / 30; + sb.body.opa = LV_OPA_COVER; + + lv_style_copy(&panel, &bg); + panel.body.main_color = lv_color_hsv_to_rgb(hue, 11, 18); + panel.body.grad_color = lv_color_hsv_to_rgb(hue, 11, 18); + panel.body.radius = LV_DPI / 20; + panel.body.border.color = lv_color_hsv_to_rgb(hue, 10, 25); + panel.body.border.width = 1; + panel.body.border.opa = LV_OPA_COVER; + panel.body.padding.left = LV_DPI / 10; + panel.body.padding.right = LV_DPI / 10; + panel.body.padding.top = LV_DPI / 10; + panel.body.padding.bottom = LV_DPI / 10; + panel.line.color = lv_color_hsv_to_rgb(hue, 20, 40); + panel.line.width = 1; + + theme.style.scr = &scr; + theme.style.bg = &bg; + theme.style.panel = &def; +} + +void LittleVgl::InitThemeContainer() { + theme.style.cont = &panel; +} + +void LittleVgl::InitThemeButton() { + + + lv_style_copy(&btn_rel, &def); + btn_rel.body.main_color = lv_color_hsv_to_rgb(hue, 10, 40); + btn_rel.body.grad_color = lv_color_hsv_to_rgb(hue, 10, 20); + btn_rel.body.border.color = lv_color_hex3(0x111); + btn_rel.body.border.width = 1; + btn_rel.body.border.opa = LV_OPA_70; + btn_rel.body.padding.left = LV_DPI / 4; + btn_rel.body.padding.right = LV_DPI / 4; + btn_rel.body.padding.top = LV_DPI / 8; + btn_rel.body.padding.bottom = LV_DPI / 8; + btn_rel.body.shadow.type = LV_SHADOW_BOTTOM; + btn_rel.body.shadow.color = lv_color_hex3(0x111); + btn_rel.body.shadow.width = LV_DPI / 30; + btn_rel.text.color = lv_color_hex3(0xeee); + btn_rel.image.color = lv_color_hex3(0xeee); + + lv_style_copy(&btn_pr, &btn_rel); + btn_pr.body.main_color = lv_color_hsv_to_rgb(hue, 10, 30); + btn_pr.body.grad_color = lv_color_hsv_to_rgb(hue, 10, 10); + + lv_style_copy(&btn_tgl_rel, &btn_rel); + btn_tgl_rel.body.main_color = lv_color_hsv_to_rgb(hue, 10, 20); + btn_tgl_rel.body.grad_color = lv_color_hsv_to_rgb(hue, 10, 40); + btn_tgl_rel.body.shadow.width = LV_DPI / 40; + btn_tgl_rel.text.color = lv_color_hex3(0xddd); + btn_tgl_rel.image.color = lv_color_hex3(0xddd); + + lv_style_copy(&btn_tgl_pr, &btn_rel); + btn_tgl_pr.body.main_color = lv_color_hsv_to_rgb(hue, 10, 10); + btn_tgl_pr.body.grad_color = lv_color_hsv_to_rgb(hue, 10, 30); + btn_tgl_pr.body.shadow.width = LV_DPI / 30; + btn_tgl_pr.text.color = lv_color_hex3(0xddd); + btn_tgl_pr.image.color = lv_color_hex3(0xddd); + + lv_style_copy(&btn_ina, &btn_rel); + btn_ina.body.main_color = lv_color_hsv_to_rgb(hue, 10, 20); + btn_ina.body.grad_color = lv_color_hsv_to_rgb(hue, 10, 20); + btn_ina.body.shadow.width = 0; + btn_ina.text.color = lv_color_hex3(0xaaa); + btn_ina.image.color = lv_color_hex3(0xaaa); + + theme.style.btn.rel = &btn_rel; + theme.style.btn.pr = &btn_pr; + theme.style.btn.tgl_rel = &btn_tgl_rel; + theme.style.btn.tgl_pr = &btn_tgl_pr; + theme.style.btn.ina = &btn_ina; +} + +void LittleVgl::InitThemeLabel() { + lv_style_copy(&prim, &bg); + prim.text.color = lv_color_hsv_to_rgb(hue, 5, 95); + + lv_style_copy(&sec, &bg); + sec.text.color = lv_color_hsv_to_rgb(hue, 15, 65); + + lv_style_copy(&hint, &bg); + hint.text.color = lv_color_hsv_to_rgb(hue, 20, 55); + + theme.style.label.prim = &prim; + theme.style.label.sec = &sec; + theme.style.label.hint = &hint; +} + +void LittleVgl::InitThemeLine() { + theme.style.line.decor = &def; +} + +void LittleVgl::InitThemeLed() { + lv_style_copy(&led, &def); + led.body.shadow.width = LV_DPI / 10; + led.body.radius = LV_RADIUS_CIRCLE; + led.body.border.width = LV_DPI / 30; + led.body.border.opa = LV_OPA_30; + led.body.main_color = lv_color_hsv_to_rgb(hue, 100, 100); + led.body.grad_color = lv_color_hsv_to_rgb(hue, 100, 40); + led.body.border.color = lv_color_hsv_to_rgb(hue, 60, 60); + led.body.shadow.color = lv_color_hsv_to_rgb(hue, 100, 100); + + theme.style.led = &led; +} + +void LittleVgl::InitThemeImage() { + theme.style.img.light = &def; + theme.style.img.dark = &def; +} + +void LittleVgl::InitThemeBar() { + lv_style_copy(&bar_bg, &panel); + bar_bg.body.padding.left = LV_DPI / 16; + bar_bg.body.padding.right = LV_DPI / 16; + bar_bg.body.padding.top = LV_DPI / 16; + bar_bg.body.padding.bottom = LV_DPI / 16; + bar_bg.body.radius = LV_RADIUS_CIRCLE; + + lv_style_copy(&bar_indic, &def); + bar_indic.body.main_color = lv_color_hsv_to_rgb(hue, 80, 70); + bar_indic.body.grad_color = lv_color_hsv_to_rgb(hue, 80, 70); + bar_indic.body.border.color = lv_color_hsv_to_rgb(hue, 20, 15); + bar_indic.body.border.width = 1; + bar_indic.body.border.opa = LV_OPA_COVER; + bar_indic.body.radius = LV_RADIUS_CIRCLE; + bar_indic.body.padding.left = 0; + bar_indic.body.padding.right = 0; + bar_indic.body.padding.top = 0; + bar_indic.body.padding.bottom = 0; + + theme.style.bar.bg = &bar_bg; + theme.style.bar.indic = &bar_indic; +} + +void LittleVgl::InitThemeSlider() { + lv_style_copy(&slider_knob, theme.style.btn.rel); + slider_knob.body.radius = LV_RADIUS_CIRCLE; + + theme.style.slider.bg = theme.style.bar.bg; + theme.style.slider.indic = theme.style.bar.indic; + theme.style.slider.knob = &slider_knob; +} + +void LittleVgl::InitThemeSwitch() { + theme.style.sw.bg = theme.style.bar.bg; + theme.style.sw.indic = theme.style.bar.indic; + theme.style.sw.knob_off = theme.style.slider.knob; + theme.style.sw.knob_on = theme.style.slider.knob; +} + +void LittleVgl::InitThemeMeter() { + static lv_style_t lmeter_bg; + lv_style_copy(&lmeter_bg, &def); + lmeter_bg.body.main_color = lv_color_hsv_to_rgb(hue, 10, 70); + lmeter_bg.body.grad_color = lv_color_hsv_to_rgb(hue, 95, 90); + lmeter_bg.body.padding.left = LV_DPI / 10; /*Scale line length*/ + lmeter_bg.body.padding.inner = LV_DPI / 10; /*Text padding*/ + lmeter_bg.body.border.color = lv_color_hex3(0x333); + lmeter_bg.line.color = lv_color_hex3(0x555); + lmeter_bg.line.width = 1; + lmeter_bg.text.color = lv_color_hex3(0xddd); + + theme.style.lmeter = &lmeter_bg; +} + +void LittleVgl::InitThemeGauge() { + static lv_style_t gauge_bg; + lv_style_copy(&gauge_bg, &def); + gauge_bg.body.main_color = lv_color_hsv_to_rgb(hue, 10, 70); + gauge_bg.body.grad_color = gauge_bg.body.main_color; + gauge_bg.line.color = lv_color_hsv_to_rgb(hue, 80, 75); + gauge_bg.line.width = 1; + gauge_bg.text.color = lv_color_hex3(0xddd); + + theme.style.gauge = &gauge_bg; +} + +void LittleVgl::InitThemeArc() { + lv_style_copy(&arc, &def); + arc.line.width = 8; + arc.line.color = lv_color_hsv_to_rgb(hue, 80, 70); + arc.line.rounded = 1; + + /*For preloader*/ + arc.body.border.width = 7; + arc.body.border.color = lv_color_hsv_to_rgb(hue, 11, 48); + arc.body.padding.left = 1; + arc.body.padding.right = 1; + arc.body.padding.top = 1; + arc.body.padding.bottom = 1; + + theme.style.arc = &arc; +} + +void LittleVgl::InitThemePreload() { +// theme.style.preload = theme.style.arc; +} + +void LittleVgl::InitThemeChart() { + theme.style.chart = &panel; +} + +void LittleVgl::InitThemeCalendar() { + + lv_style_copy(&cal_bg, &bg); + cal_bg.body.main_color = lv_color_hsv_to_rgb(hue, 10, 40); + cal_bg.body.grad_color = lv_color_hsv_to_rgb(hue, 10, 40); + cal_bg.body.border.color = lv_color_hex3(0x333); + cal_bg.body.border.width = 1; + cal_bg.body.radius = LV_DPI / 20; + cal_bg.body.padding.left = LV_DPI / 10; + cal_bg.body.padding.right = LV_DPI / 10; + cal_bg.body.padding.top = LV_DPI / 10; + cal_bg.body.padding.bottom = LV_DPI / 10; + + + lv_style_copy(&cal_header, &bg); + cal_header.body.main_color = lv_color_hsv_to_rgb(hue, 10, 20); + cal_header.body.grad_color = lv_color_hsv_to_rgb(hue, 10, 20); + cal_header.body.radius = 0; + cal_header.body.border.width = 1; + cal_header.body.border.color = lv_color_hex3(0x333); + cal_header.body.padding.left = LV_DPI / 10; + cal_header.body.padding.right = LV_DPI / 10; + cal_header.body.padding.top = LV_DPI / 10; + cal_header.body.padding.bottom = LV_DPI / 10; + + + lv_style_copy(&week_box, &panel); + week_box.body.main_color = lv_color_hsv_to_rgb(hue, 30, 45); + week_box.body.grad_color = lv_color_hsv_to_rgb(hue, 30, 45); + week_box.body.radius = LV_DPI / 20; + week_box.body.border.width = 1; + week_box.body.padding.left = LV_DPI / 20; + week_box.body.padding.right = LV_DPI / 20; + week_box.body.padding.top = LV_DPI / 25; + week_box.body.padding.bottom = LV_DPI / 25; + + lv_style_copy(&today_box, &week_box); + today_box.body.main_color = lv_color_hsv_to_rgb(hue, 80, 70); + today_box.body.grad_color = lv_color_hsv_to_rgb(hue, 80, 70); + today_box.body.radius = LV_DPI / 20; + today_box.body.padding.left = LV_DPI / 14; + today_box.body.padding.right = LV_DPI / 14; + today_box.body.padding.top = LV_DPI / 14; + today_box.body.padding.bottom = LV_DPI / 14; + + lv_style_copy(&highlighted_days, &bg); + highlighted_days.text.color = lv_color_hsv_to_rgb(hue, 40, 80); + + lv_style_copy(&ina_days, &bg); + ina_days.text.color = lv_color_hsv_to_rgb(hue, 0, 60); + + theme.style.calendar.bg = &cal_bg; + theme.style.calendar.header = &cal_header; + theme.style.calendar.week_box = &week_box; + theme.style.calendar.today_box = &today_box; + theme.style.calendar.highlighted_days = &highlighted_days; + theme.style.calendar.day_names = &cal_bg; + theme.style.calendar.inactive_days = &ina_days; +} + +void LittleVgl::InitThemeCheckBox() { + + lv_style_copy(&rel, &def); + rel.body.radius = LV_DPI / 20; + rel.body.main_color = lv_color_hsv_to_rgb(hue, 10, 95); + rel.body.grad_color = lv_color_hsv_to_rgb(hue, 10, 95); + rel.body.border.color = lv_color_hsv_to_rgb(hue, 10, 50); + rel.body.border.width = 2; + ; + + lv_style_copy(&pr, &rel); + pr.body.main_color = lv_color_hsv_to_rgb(hue, 10, 80); + pr.body.grad_color = lv_color_hsv_to_rgb(hue, 10, 80); + pr.body.border.color = lv_color_hsv_to_rgb(hue, 10, 20); + pr.body.border.width = 1; + ; + + lv_style_copy(&tgl_rel, &rel); + tgl_rel.body.main_color = lv_color_hsv_to_rgb(hue, 80, 90); + tgl_rel.body.grad_color = lv_color_hsv_to_rgb(hue, 80, 90); + tgl_rel.body.border.color = lv_color_hsv_to_rgb(hue, 80, 50); + + lv_style_copy(&tgl_pr, &tgl_rel); + tgl_pr.body.main_color = lv_color_hsv_to_rgb(hue, 80, 70); + tgl_pr.body.grad_color = lv_color_hsv_to_rgb(hue, 80, 70); + tgl_pr.body.border.color = lv_color_hsv_to_rgb(hue, 80, 30); + tgl_pr.body.border.width = 1; + ; + + lv_style_copy(&ina, &rel); + ina.body.main_color = lv_color_hex3(0x777); + ina.body.grad_color = lv_color_hex3(0x777); + ina.body.border.width = 0; + + theme.style.cb.bg = &lv_style_transp; + theme.style.cb.box.rel = &rel; + theme.style.cb.box.pr = ≺ + theme.style.cb.box.tgl_rel = &tgl_rel; + theme.style.cb.box.tgl_pr = &tgl_pr; + theme.style.cb.box.ina = &def; +} + +void LittleVgl::InitThemeButtonMatrix() { + + lv_style_copy(&btnm_bg, theme.style.btn.rel); + btnm_bg.body.padding.left = 2; + btnm_bg.body.padding.right = 2; + btnm_bg.body.padding.top = 2; + btnm_bg.body.padding.bottom = 2; + btnm_bg.body.padding.inner = 0; + btnm_bg.body.border.width = 1; + + lv_style_copy(&btnm_rel, theme.style.btn.rel); + btnm_rel.body.border.part = LV_BORDER_FULL | LV_BORDER_INTERNAL; + btnm_rel.body.border.width = 1; + btnm_rel.body.radius = 2; + + lv_style_copy(&btnm_pr, theme.style.btn.pr); + btnm_pr.body.border.part = btnm_rel.body.border.part; + btnm_pr.body.border.width = btnm_rel.body.border.width; + btnm_pr.body.radius = btnm_rel.body.radius; + + lv_style_copy(&btnm_tgl_rel, theme.style.btn.tgl_rel); + btnm_tgl_rel.body.border.part = btnm_rel.body.border.part; + btnm_tgl_rel.body.border.width = btnm_rel.body.border.width; + btnm_tgl_rel.body.radius = btnm_rel.body.radius; + + lv_style_copy(&btnm_tgl_pr, theme.style.btn.pr); + btnm_tgl_pr.body.border.part = btnm_rel.body.border.part; + btnm_tgl_pr.body.border.width = btnm_rel.body.border.width; + btnm_tgl_pr.body.radius = btnm_rel.body.radius; + + lv_style_copy(&btnm_ina, theme.style.btn.ina); + btnm_ina.body.border.part = btnm_rel.body.border.part; + btnm_ina.body.border.width = btnm_rel.body.border.width; + btnm_ina.body.radius = btnm_rel.body.radius; + + theme.style.btnm.bg = &btnm_bg; + theme.style.btnm.btn.rel = &btnm_rel; + theme.style.btnm.btn.pr = &btnm_pr; + theme.style.btnm.btn.tgl_rel = &btnm_tgl_rel; + theme.style.btnm.btn.tgl_pr = &btnm_tgl_pr; + theme.style.btnm.btn.ina = &btnm_ina; +} + +void LittleVgl::InitThemeKnob() { + theme.style.kb.bg = &bg; + theme.style.kb.btn.rel = theme.style.btn.rel; + theme.style.kb.btn.pr = theme.style.btn.pr; + theme.style.kb.btn.tgl_rel = theme.style.btn.tgl_rel; + theme.style.kb.btn.tgl_pr = theme.style.btn.tgl_pr; + theme.style.kb.btn.ina = theme.style.btn.ina; +} + +void LittleVgl::InitThemeMessageBox() { + lv_style_copy(&mbox_bg, &bg); + mbox_bg.body.main_color = lv_color_hsv_to_rgb(hue, 30, 30); + mbox_bg.body.grad_color = lv_color_hsv_to_rgb(hue, 30, 30); + mbox_bg.body.border.color = lv_color_hsv_to_rgb(hue, 11, 20); + mbox_bg.body.border.width = 1; + mbox_bg.body.shadow.width = LV_DPI / 10; + mbox_bg.body.shadow.color = lv_color_hex3(0x222); + mbox_bg.body.radius = LV_DPI / 20; + theme.style.mbox.bg = &mbox_bg; + theme.style.mbox.btn.bg = &lv_style_transp; + theme.style.mbox.btn.rel = theme.style.btn.rel; + theme.style.mbox.btn.pr = theme.style.btn.pr; +} + +void LittleVgl::InitThemePage() { + lv_style_copy(&page_scrl, &bg); + page_scrl.body.main_color = lv_color_hsv_to_rgb(hue, 10, 40); + page_scrl.body.grad_color = lv_color_hsv_to_rgb(hue, 10, 40); + page_scrl.body.border.color = lv_color_hex3(0x333); + page_scrl.body.border.width = 1; + page_scrl.body.radius = LV_DPI / 20; + + theme.style.page.bg = &panel; + theme.style.page.scrl = &page_scrl; + theme.style.page.sb = &sb; +} + +void LittleVgl::InitThemeTextArea() { + theme.style.ta.area = &panel; + theme.style.ta.oneline = &panel; + theme.style.ta.cursor = NULL; + theme.style.ta.sb = &def; +} + +void LittleVgl::InitThemeSpinBox() { + theme.style.spinbox.bg = &panel; + theme.style.spinbox.cursor = theme.style.ta.cursor; + theme.style.spinbox.sb = theme.style.ta.sb; +} + +void LittleVgl::InitThemeList() { + + lv_style_copy(&list_bg, &panel); + list_bg.body.padding.top = 0; + list_bg.body.padding.bottom = 0; + list_bg.body.padding.left = 0; + list_bg.body.padding.right = 0; + list_bg.body.padding.inner = 0; + + lv_style_copy(&list_btn_rel, &bg); + list_btn_rel.body.opa = LV_OPA_TRANSP; + list_btn_rel.body.border.part = LV_BORDER_BOTTOM; + list_btn_rel.body.border.color = lv_color_hsv_to_rgb(hue, 10, 5); + list_btn_rel.body.border.width = 1; + list_btn_rel.body.radius = LV_DPI / 10; + list_btn_rel.text.color = lv_color_hsv_to_rgb(hue, 5, 80); + list_btn_rel.image.color = lv_color_hsv_to_rgb(hue, 5, 80); + list_btn_rel.body.padding.top = LV_DPI / 6; + list_btn_rel.body.padding.bottom = LV_DPI / 6; + list_btn_rel.body.padding.left = LV_DPI / 8; + list_btn_rel.body.padding.right = LV_DPI / 8; + + lv_style_copy(&list_btn_pr, theme.style.btn.pr); + list_btn_pr.body.main_color = lv_color_hsv_to_rgb(hue, 10, 5); + list_btn_pr.body.grad_color = lv_color_hsv_to_rgb(hue, 10, 5); + list_btn_pr.body.border.color = lv_color_hsv_to_rgb(hue, 10, 5); + list_btn_pr.body.border.width = 0; + list_btn_pr.body.padding.top = LV_DPI / 6; + list_btn_pr.body.padding.bottom = LV_DPI / 6; + list_btn_pr.body.padding.left = LV_DPI / 8; + list_btn_pr.body.padding.right = LV_DPI / 8; + list_btn_pr.text.color = lv_color_hsv_to_rgb(hue, 5, 80); + list_btn_pr.image.color = lv_color_hsv_to_rgb(hue, 5, 80); + + lv_style_copy(&list_btn_tgl_rel, &list_btn_rel); + list_btn_tgl_rel.body.opa = LV_OPA_COVER; + list_btn_tgl_rel.body.main_color = lv_color_hsv_to_rgb(hue, 80, 70); + list_btn_tgl_rel.body.grad_color = lv_color_hsv_to_rgb(hue, 80, 70); + list_btn_tgl_rel.body.border.color = lv_color_hsv_to_rgb(hue, 60, 40); + list_btn_tgl_rel.body.radius = list_bg.body.radius; + + lv_style_copy(&list_btn_tgl_pr, &list_btn_tgl_rel); + list_btn_tgl_pr.body.main_color = lv_color_hsv_to_rgb(hue, 80, 60); + list_btn_tgl_pr.body.grad_color = lv_color_hsv_to_rgb(hue, 80, 60); + + theme.style.list.sb = &sb; + theme.style.list.bg = &list_bg; + theme.style.list.scrl = &lv_style_transp_tight; + theme.style.list.btn.rel = &list_btn_rel; + theme.style.list.btn.pr = &list_btn_pr; + theme.style.list.btn.tgl_rel = &list_btn_tgl_rel; + theme.style.list.btn.tgl_pr = &list_btn_tgl_pr; + theme.style.list.btn.ina = &def; +} + +void LittleVgl::InitThemeDropDownList() { + lv_style_copy(&ddlist_bg, theme.style.btn.rel); + ddlist_bg.text.line_space = LV_DPI / 8; + ddlist_bg.body.padding.top = LV_DPI / 8; + ddlist_bg.body.padding.bottom = LV_DPI / 8; + ddlist_bg.body.padding.left = LV_DPI / 8; + ddlist_bg.body.padding.right = LV_DPI / 8; + ddlist_bg.body.radius = LV_DPI / 30; + + lv_style_copy(&ddlist_sel, theme.style.btn.rel); + ddlist_sel.body.main_color = lv_color_hsv_to_rgb(hue, 20, 50); + ddlist_sel.body.grad_color = lv_color_hsv_to_rgb(hue, 20, 50); + ddlist_sel.body.radius = 0; + + theme.style.ddlist.bg = &ddlist_bg; + theme.style.ddlist.sel = &ddlist_sel; + theme.style.ddlist.sb = &def; +} + +void LittleVgl::InitThemeRoller() { + lv_style_t roller_bg; + + lv_style_copy(&roller_bg, theme.style.ddlist.bg); + roller_bg.body.main_color = lv_color_hsv_to_rgb(hue, 10, 20); + roller_bg.body.grad_color = lv_color_hsv_to_rgb(hue, 10, 40); + roller_bg.text.color = lv_color_hsv_to_rgb(hue, 5, 70); + roller_bg.text.opa = LV_OPA_60; + + theme.style.roller.bg = &roller_bg; + theme.style.roller.sel = theme.style.ddlist.sel; +} + +void LittleVgl::InitThemeTabView() { + theme.style.tabview.bg = &bg; + theme.style.tabview.indic = &lv_style_transp; + theme.style.tabview.btn.bg = &lv_style_transp; + theme.style.tabview.btn.rel = theme.style.btn.rel; + theme.style.tabview.btn.pr = theme.style.btn.pr; + theme.style.tabview.btn.tgl_rel = theme.style.btn.tgl_rel; + theme.style.tabview.btn.tgl_pr = theme.style.btn.tgl_pr; +} + +void LittleVgl::InitThemeTileView() { + theme.style.tileview.bg = &lv_style_transp_tight; + theme.style.tileview.scrl = &lv_style_transp_tight; + theme.style.tileview.sb = theme.style.page.sb; +} + +void LittleVgl::InitThemeTable() { + lv_style_copy(&cell, &panel); + cell.body.radius = 0; + cell.body.border.width = 1; + cell.body.padding.left = LV_DPI / 12; + cell.body.padding.right = LV_DPI / 12; + cell.body.padding.top = LV_DPI / 12; + cell.body.padding.bottom = LV_DPI / 12; + + theme.style.table.bg = &lv_style_transp_tight; + theme.style.table.cell = &cell; +} + +void LittleVgl::InitThemeWindow() { +// lv_style_copy(&win_bg, &bg); +// win_bg.body.border.color = lv_color_hex3(0x333); +// win_bg.body.border.width = 1; +// +// lv_style_copy(&win_header, &win_bg); +// win_header.body.main_color = lv_color_hsv_to_rgb(hue, 10, 20); +// win_header.body.grad_color = lv_color_hsv_to_rgb(hue, 10, 20); +// win_header.body.radius = 0; +// win_header.body.padding.left = 0; +// win_header.body.padding.right = 0; +// win_header.body.padding.top = 0; +// win_header.body.padding.bottom = 0; +// +// lv_style_copy(&win_btn_pr, &def); +// win_btn_pr.body.main_color = lv_color_hsv_to_rgb(hue, 10, 10); +// win_btn_pr.body.grad_color = lv_color_hsv_to_rgb(hue, 10, 10); +// win_btn_pr.text.color = lv_color_hex3(0xaaa); +// win_btn_pr.image.color = lv_color_hex3(0xaaa); +// +// theme.style.win.bg = &win_bg; +// theme.style.win.sb = &sb; +// theme.style.win.header = &win_header; +// theme.style.win.content = &lv_style_transp; +// theme.style.win.btn.rel = &lv_style_transp; +// theme.style.win.btn.pr = &win_btn_pr; +} diff --git a/src/DisplayApp/LittleVgl.h b/src/DisplayApp/LittleVgl.h new file mode 100644 index 00000000..40fb1809 --- /dev/null +++ b/src/DisplayApp/LittleVgl.h @@ -0,0 +1,100 @@ +#pragma once + +#include <libs/lvgl/src/lv_core/lv_style.h> +#include <libs/lvgl/src/lv_themes/lv_theme.h> +#include <libs/lvgl/src/lv_hal/lv_hal.h> +#include <drivers/St7789.h> +#include <drivers/Cst816s.h> + + +static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p); +static bool touchpad_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data); + +namespace Pinetime { + namespace Components { + class LittleVgl { + public: + LittleVgl(Pinetime::Drivers::St7789& lcd, Pinetime::Drivers::Cst816S& touchPanel); + void FlushDisplay(const lv_area_t * area, lv_color_t * color_p); + + + bool GetTouchPadInfo(lv_indev_data_t *ptr); + private: + void InitDisplay(); + void InitTouchpad(); + void InitTheme(); + void InitBaseTheme(); + void InitThemeContainer(); + void InitThemeButton(); + void InitThemeLabel(); + void InitThemeLine(); + void InitThemeLed(); + void InitThemeImage(); + void InitThemeBar(); + void InitThemeSlider(); + void InitThemeSwitch(); + void InitThemeMeter(); + void InitThemeGauge(); + void InitThemeArc(); + void InitThemePreload(); + void InitThemeChart(); + void InitThemeCalendar(); + void InitThemeCheckBox(); + void InitThemeButtonMatrix(); + void InitThemeKnob(); + void InitThemeMessageBox(); + void InitThemePage(); + void InitThemeTextArea(); + void InitThemeSpinBox(); + void InitThemeList(); + void InitThemeDropDownList(); + void InitThemeRoller(); + void InitThemeTabView(); + void InitThemeTileView(); + void InitThemeTable(); + void InitThemeWindow(); + + Pinetime::Drivers::St7789& lcd; + Pinetime::Drivers::Cst816S& touchPanel; + + + lv_disp_buf_t disp_buf_2; + lv_color_t buf2_1[LV_HOR_RES_MAX * 4]; + lv_color_t buf2_2[LV_HOR_RES_MAX * 4]; + + lv_disp_drv_t disp_drv; + lv_point_t previousClick; + + lv_style_t def; + lv_style_t scr, bg, sb, panel; + lv_font_t * font = nullptr; + uint16_t hue = 10; + lv_theme_t theme; + lv_style_t btn_rel, btn_pr, btn_tgl_rel, btn_tgl_pr, btn_ina; + lv_style_t prim, sec, hint; + lv_style_t led; + lv_style_t bar_bg, bar_indic; + lv_style_t slider_knob; + lv_style_t arc; + lv_style_t cal_bg; + lv_style_t cal_header; + lv_style_t week_box; + lv_style_t today_box; + lv_style_t highlighted_days; + lv_style_t ina_days; + lv_style_t rel, pr, tgl_rel, tgl_pr, ina; + lv_style_t btnm_bg, btnm_rel, btnm_pr, btnm_tgl_rel, btnm_tgl_pr, btnm_ina; + lv_style_t mbox_bg; + lv_style_t page_scrl; + lv_style_t list_bg, list_btn_rel, list_btn_pr, list_btn_tgl_rel, list_btn_tgl_pr; + lv_style_t ddlist_bg, ddlist_sel; + lv_style_t cell; + lv_style_t win_bg; + lv_style_t win_header; + lv_style_t win_btn_pr; + + bool firstTouch = true; + }; + } +} + diff --git a/src/DisplayApp/Screens/Clock.cpp b/src/DisplayApp/Screens/Clock.cpp index 16f4cfeb..7051c433 100644 --- a/src/DisplayApp/Screens/Clock.cpp +++ b/src/DisplayApp/Screens/Clock.cpp @@ -2,36 +2,94 @@ #include <libs/date/includes/date/date.h> #include <Components/DateTime/DateTimeController.h> #include <Version.h> +#include <libs/lvgl/lvgl.h> #include "Clock.h" +#include "../DisplayApp.h" using namespace Pinetime::Applications::Screens; +extern lv_font_t jetbrains_mono_extrabold_compressed; +extern lv_font_t jetbrains_mono_bold_20; -void Clock::Refresh(bool fullRefresh) { - if(fullRefresh) { - gfx.FillRectangle(0,0,240,240,0x0000); - currentChar[0] = 1; - currentChar[1] = 2; - currentChar[2] = 3; - currentChar[3] = 4; - auto dummy = currentDateTime.Get(); - } +static void event_handler(lv_obj_t * obj, lv_event_t event) { + Clock* screen = static_cast<Clock *>(obj->user_data); + screen->OnObjectEvent(obj, event); +} + +Clock::Clock(DisplayApp* app, + Controllers::DateTime& dateTimeController, + Controllers::Battery& batteryController, + Controllers::Ble& bleController) : Screen(app), currentDateTime{{}}, version {{}}, + dateTimeController{dateTimeController}, batteryController{batteryController}, bleController{bleController} { + displayedChar[0] = 0; + displayedChar[1] = 0; + displayedChar[2] = 0; + displayedChar[3] = 0; + displayedChar[4] = 0; + + label_battery = lv_label_create(lv_scr_act(), NULL); + lv_obj_align(label_battery, lv_scr_act(), LV_ALIGN_IN_TOP_RIGHT, -80, 0); + + labelStyle = const_cast<lv_style_t *>(lv_label_get_style(label_battery, LV_LABEL_STYLE_MAIN)); + labelStyle->text.font = &jetbrains_mono_bold_20; + + lv_style_copy(&labelBigStyle, labelStyle); + labelBigStyle.text.font = &jetbrains_mono_extrabold_compressed; + + lv_label_set_style(label_battery, LV_LABEL_STYLE_MAIN, labelStyle); + + label_ble = lv_label_create(lv_scr_act(), NULL); + lv_label_set_style(label_ble, LV_LABEL_STYLE_MAIN, labelStyle); + lv_obj_align(label_ble, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, 10, 0); + + label_time = lv_label_create(lv_scr_act(), NULL); + lv_label_set_style(label_time, LV_LABEL_STYLE_MAIN, &labelBigStyle); + lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 0); + + + label_date = lv_label_create(lv_scr_act(), NULL); + lv_label_set_style(label_date, LV_LABEL_STYLE_MAIN, labelStyle); + lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 60); + + backgroundLabel = lv_label_create(lv_scr_act(), NULL); + backgroundLabel->user_data = this; + lv_label_set_style(backgroundLabel, LV_LABEL_STYLE_MAIN, labelStyle); + lv_obj_set_click(backgroundLabel, true); + lv_obj_set_event_cb(backgroundLabel, event_handler); + 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, ""); +} + +Clock::~Clock() { + lv_obj_clean(lv_scr_act()); +} - if (fullRefresh || batteryPercentRemaining.IsUpdated()) { +bool Clock::Refresh() { + batteryPercentRemaining = batteryController.PercentRemaining(); + if (batteryPercentRemaining.IsUpdated()) { char batteryChar[11]; auto newBatteryValue = batteryPercentRemaining.Get(); newBatteryValue = (newBatteryValue > 100) ? 100 : newBatteryValue; newBatteryValue = (newBatteryValue < 0) ? 0 : newBatteryValue; sprintf(batteryChar, "BAT: %d%%", newBatteryValue); - gfx.DrawString((240 - 108), 0, 0xffff, batteryChar, &smallFont, false); + lv_label_set_text(label_battery, batteryChar); } - if (fullRefresh || bleState.IsUpdated()) { - uint16_t color = (bleState.Get() == BleConnectionStates::Connected) ? 0xffff : 0x0000; - gfx.DrawString(10, 0, color, "BLE", &smallFont, false); + bleState = bleController.IsConnected(); + if (bleState.IsUpdated()) { + if(bleState.Get() == true) { + lv_obj_set_hidden(label_ble, false); + lv_label_set_text(label_ble, "BLE"); + } else { + lv_obj_set_hidden(label_ble, true); + } } - if(fullRefresh || currentDateTime.IsUpdated()) { + currentDateTime = dateTimeController.CurrentDateTime(); + + if(currentDateTime.IsUpdated()) { auto newDateTime = currentDateTime.Get(); auto dp = date::floor<date::days>(newDateTime); @@ -53,35 +111,23 @@ void Clock::Refresh(bool fullRefresh) { char hoursChar[3]; sprintf(hoursChar, "%02d", hour); - uint8_t x = 7; - if (hoursChar[0] != currentChar[0]) { - gfx.DrawChar(&largeFont, hoursChar[0], &x, 78, 0xffff); - currentChar[0] = hoursChar[0]; - } - - x = 61; - if (hoursChar[1] != currentChar[1]) { - gfx.DrawChar(&largeFont, hoursChar[1], &x, 78, 0xffff); - currentChar[1] = hoursChar[1]; - } + char timeStr[6]; + sprintf(timeStr, "%c%c:%c%c", hoursChar[0],hoursChar[1],minutesChar[0], minutesChar[1]); - x = 127; - if (minutesChar[0] != currentChar[2]) { - gfx.DrawChar(&largeFont, minutesChar[0], &x, 78, 0xffff); - currentChar[2] = minutesChar[0]; - } + if(hoursChar[0] != displayedChar[0] || hoursChar[1] != displayedChar[1] || minutesChar[0] != displayedChar[2] || minutesChar[1] != displayedChar[3]) { + displayedChar[0] = hoursChar[0]; + displayedChar[1] = hoursChar[1]; + displayedChar[2] = minutesChar[0]; + displayedChar[3] = minutesChar[1]; - x = 181; - if (minutesChar[1] != currentChar[3]) { - gfx.DrawChar(&largeFont, minutesChar[1], &x, 78, 0xffff); - currentChar[3] = minutesChar[1]; + lv_label_set_text(label_time, timeStr); } if ((year != currentYear) || (month != currentMonth) || (dayOfWeek != currentDayOfWeek) || (day != currentDay)) { - gfx.FillRectangle(0,180, 240, 15, 0x0000); char dateStr[22]; sprintf(dateStr, "%s %d %s %d", DayOfWeekToString(dayOfWeek), day, MonthToString(month), year); - gfx.DrawString(10, 180, 0xffff, dateStr, &smallFont, false); + lv_label_set_text(label_date, dateStr); + currentYear = year; currentMonth = month; @@ -90,12 +136,7 @@ void Clock::Refresh(bool fullRefresh) { } } - if(fullRefresh || version.IsUpdated()) { - auto dummy = version.Get(); - char versionStr[20]; - sprintf(versionStr, "VERSION: %d.%d.%d", Version::Major(), Version::Minor(), Version::Patch()); - gfx.DrawString(20, 220, 0xffff, versionStr, &smallFont, false); - } + return running; } const char *Clock::MonthToString(Pinetime::Controllers::DateTime::Months month) { @@ -132,3 +173,18 @@ char const *Clock::MonthsString[] = { "NOV", "DEC" }; + +void Clock::OnObjectEvent(lv_obj_t *obj, lv_event_t event) { + if(obj == backgroundLabel) { + if (event == LV_EVENT_CLICKED) { + + running = false; + } + } +} + +bool Clock::OnButtonPushed() { + return Screen::OnButtonPushed(); +} + + diff --git a/src/DisplayApp/Screens/Clock.h b/src/DisplayApp/Screens/Clock.h index 75ea34dd..d14595b0 100644 --- a/src/DisplayApp/Screens/Clock.h +++ b/src/DisplayApp/Screens/Clock.h @@ -5,6 +5,10 @@ #include <Components/Gfx/Gfx.h> #include "Screen.h" #include <bits/unique_ptr.h> +#include <libs/lvgl/src/lv_core/lv_style.h> +#include <libs/lvgl/src/lv_core/lv_obj.h> +#include <Components/Battery/BatteryController.h> +#include <Components/Ble/BleController.h> #include "../Fonts/lcdfont14.h" #include "../Fonts/lcdfont70.h" #include "../../Version.h" @@ -19,11 +23,13 @@ namespace Pinetime { explicit DirtyValue(T v) { value = v; } explicit DirtyValue(T& v) { value = v; } bool IsUpdated() const { return isUpdated; } - T& Get() { this->isUpdated = false; return value;} + T& Get() { this->isUpdated = false; return value; } DirtyValue& operator=(const T& other) { - this->value = other; - this->isUpdated = true; + if (this->value != other) { + this->value = other; + this->isUpdated = true; + } return *this; } private: @@ -32,33 +38,50 @@ namespace Pinetime { }; class Clock : public Screen{ public: - enum class BleConnectionStates{ NotConnected, Connected}; - Clock(Components::Gfx& gfx) : Screen(gfx), currentDateTime{{}}, version {{}} {} - void Refresh(bool fullRefresh) override; + Clock(DisplayApp* app, + Controllers::DateTime& dateTimeController, + Controllers::Battery& batteryController, + Controllers::Ble& bleController); + ~Clock() override; - void SetBatteryPercentRemaining(uint8_t percent) { batteryPercentRemaining = percent; } - void SetBleConnectionState(BleConnectionStates state) { bleState = state; } - void SetCurrentDateTime(const std::chrono::time_point<std::chrono::system_clock, std::chrono::milliseconds>& tp) { currentDateTime = tp;} + bool Refresh() override; + bool OnButtonPushed() override; + void OnObjectEvent(lv_obj_t *pObj, lv_event_t i); private: static const char* MonthToString(Pinetime::Controllers::DateTime::Months month); static const char* DayOfWeekToString(Pinetime::Controllers::DateTime::Days dayOfWeek); static char const *DaysString[]; static char const *MonthsString[]; - const FONT_INFO largeFont {lCD_70ptFontInfo.height, lCD_70ptFontInfo.startChar, lCD_70ptFontInfo.endChar, lCD_70ptFontInfo.spacePixels, lCD_70ptFontInfo.charInfo, lCD_70ptFontInfo.data}; - const FONT_INFO smallFont {lCD_14ptFontInfo.height, lCD_14ptFontInfo.startChar, lCD_14ptFontInfo.endChar, lCD_14ptFontInfo.spacePixels, lCD_14ptFontInfo.charInfo, lCD_14ptFontInfo.data}; + char displayedChar[5]; - char currentChar[4]; 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 {0}; - DirtyValue<BleConnectionStates> bleState {BleConnectionStates::NotConnected}; - DirtyValue<std::chrono::time_point<std::chrono::system_clock, std::chrono::milliseconds>> currentDateTime; + DirtyValue<bool> bleState {false}; + DirtyValue<std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds>> currentDateTime; DirtyValue<Pinetime::Version> version; + + lv_style_t* labelStyle; + lv_style_t labelBigStyle; + lv_obj_t * label_battery; + + lv_obj_t * label_ble; + lv_obj_t* label_time; + lv_obj_t* label_date; + lv_obj_t* label_version; + lv_obj_t* backgroundLabel; + + Controllers::DateTime& dateTimeController; + Controllers::Battery& batteryController; + Controllers::Ble& bleController; + + bool running = true; + }; } } diff --git a/src/DisplayApp/Screens/Gauge.cpp b/src/DisplayApp/Screens/Gauge.cpp new file mode 100644 index 00000000..4c4cccd9 --- /dev/null +++ b/src/DisplayApp/Screens/Gauge.cpp @@ -0,0 +1,57 @@ +#include <libs/lvgl/lvgl.h> +#include "Gauge.h" +#include "../DisplayApp.h" + +using namespace Pinetime::Applications::Screens; +extern lv_font_t jetbrains_mono_extrabold_compressed; +extern lv_font_t jetbrains_mono_bold_20; + + +Gauge::Gauge(Pinetime::Applications::DisplayApp *app) : Screen(app) { + /*Create a style*/ + lv_style_copy(&style, &lv_style_pretty_color); + style.body.main_color = LV_COLOR_CYAN; /*Line color at the beginning*/ + style.body.grad_color = LV_COLOR_RED; /*Line color at the end*/ + style.body.padding.left = 10; /*Scale line length*/ + style.body.padding.inner = 8 ; /*Scale label padding*/ + style.body.border.color = lv_color_hex3(0x333); /*Needle middle circle color*/ + style.line.width = 3; + style.text.color = LV_COLOR_WHITE; + style.line.color = LV_COLOR_RED; /*Line color after the critical value*/ + + /*Describe the color for the needles*/ + + needle_colors[0] = LV_COLOR_ORANGE; + + /*Create a gauge*/ + gauge1 = lv_gauge_create(lv_scr_act(), NULL); + lv_gauge_set_style(gauge1, LV_GAUGE_STYLE_MAIN, &style); + lv_gauge_set_needle_count(gauge1, 1, needle_colors); + lv_obj_set_size(gauge1, 180, 180); + lv_obj_align(gauge1, NULL, LV_ALIGN_CENTER, 0, 0); + lv_gauge_set_scale(gauge1, 360, 60, 0); + lv_gauge_set_range(gauge1, 0, 59); + + /*Set the values*/ + lv_gauge_set_value(gauge1, 0, value); +} + +Gauge::~Gauge() { + + + lv_obj_clean(lv_scr_act()); +} + +bool Gauge::Refresh() { +// lv_lmeter_set_value(lmeter, value++); /*Set the current value*/ +// if(value>=60) value = 0; + + lv_gauge_set_value(gauge1, 0, value++); + if(value == 59) value = 0; + return running; +} + +bool Gauge::OnButtonPushed() { + running = false; + return true; +} diff --git a/src/DisplayApp/Screens/Gauge.h b/src/DisplayApp/Screens/Gauge.h new file mode 100644 index 00000000..463654ee --- /dev/null +++ b/src/DisplayApp/Screens/Gauge.h @@ -0,0 +1,39 @@ +#pragma once + +#include <cstdint> +#include <chrono> +#include <Components/Gfx/Gfx.h> +#include "Screen.h" +#include <bits/unique_ptr.h> +#include <libs/lvgl/src/lv_core/lv_style.h> +#include <libs/lvgl/src/lv_core/lv_obj.h> +#include <Components/Battery/BatteryController.h> +#include <Components/Ble/BleController.h> +#include "../Fonts/lcdfont14.h" +#include "../Fonts/lcdfont70.h" +#include "../../Version.h" + +namespace Pinetime { + namespace Applications { + namespace Screens { + + class Gauge : public Screen{ + public: + Gauge(DisplayApp* app); + ~Gauge() override; + + bool Refresh() override; + bool OnButtonPushed() override; + + private: + lv_style_t style; + lv_color_t needle_colors[3]; + lv_obj_t * gauge1; + + uint32_t value=30; + bool running = true; + + }; + } + } +} diff --git a/src/DisplayApp/Screens/Message.cpp b/src/DisplayApp/Screens/Message.cpp index 121e34b9..c8a4ea1f 100644 --- a/src/DisplayApp/Screens/Message.cpp +++ b/src/DisplayApp/Screens/Message.cpp @@ -2,13 +2,87 @@ #include <libs/date/includes/date/date.h> #include <Components/DateTime/DateTimeController.h> #include <Version.h> +#include <libs/lvgl/src/lv_core/lv_obj.h> +#include <libs/lvgl/src/lv_font/lv_font.h> +#include <libs/lvgl/lvgl.h> +#include <libraries/log/nrf_log.h> #include "Message.h" +#include <DisplayApp/DisplayApp.h> + using namespace Pinetime::Applications::Screens; -void Message::Refresh(bool fullRefresh) { - if(fullRefresh) { - gfx.FillRectangle(0,0,240,240,0xffff); - gfx.DrawString(120, 10, 0x5555, "COUCOU", &smallFont, false); +extern lv_font_t jetbrains_mono_bold_20; + +static void event_handler(lv_obj_t * obj, lv_event_t event) { + Message* screen = static_cast<Message *>(obj->user_data); + screen->OnObjectEvent(obj, event); +} + +Message::Message(DisplayApp* app) : Screen(app) { + + backgroundLabel = lv_label_create(lv_scr_act(), NULL); + backgroundLabel->user_data = this; + + labelStyle = const_cast<lv_style_t *>(lv_label_get_style(backgroundLabel, LV_LABEL_STYLE_MAIN)); + labelStyle->text.font = &jetbrains_mono_bold_20; + + lv_label_set_style(backgroundLabel, LV_LABEL_STYLE_MAIN, labelStyle); + lv_obj_set_click(backgroundLabel, true); + lv_obj_set_event_cb(backgroundLabel, event_handler); + 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, ""); +// lv_obj_align(backgroundLabel, NULL, LV_ALIGN_IN_TOP_LEFT, 0, 0); + + button = lv_btn_create(lv_scr_act(), NULL); + lv_obj_set_event_cb(button, event_handler); + lv_obj_align(button, NULL, LV_ALIGN_CENTER, 0, -40); + button->user_data = this; + + label = lv_label_create(button, NULL); + lv_label_set_style(label, LV_LABEL_STYLE_MAIN, labelStyle); + lv_label_set_text(label, "Hello!"); + + labelClick = lv_label_create(lv_scr_act(), NULL); + lv_label_set_style(labelClick, LV_LABEL_STYLE_MAIN, labelStyle); + lv_obj_align(labelClick, button, LV_ALIGN_OUT_BOTTOM_MID, 0, 30); + lv_label_set_text(labelClick, "0"); +} + +Message::~Message() { + lv_obj_clean(lv_scr_act()); +} + +bool Message::Refresh() { + if(previousClickCount != clickCount) { + lv_label_set_text_fmt(labelClick, "%d", clickCount); + previousClickCount = clickCount; + } + + return running; +} + +void Message::OnObjectEvent(lv_obj_t *obj, lv_event_t event) { + if(obj == backgroundLabel) { + if(event == LV_EVENT_CLICKED) { + app->PushMessage(DisplayApp::Messages::SwitchScreen); + NRF_LOG_INFO("SCREEN"); + } + return ; } + + if(event == LV_EVENT_CLICKED) { + NRF_LOG_INFO("Clicked"); + clickCount++; + } + else if(event == LV_EVENT_VALUE_CHANGED) { + NRF_LOG_INFO("Toggled"); + } +} + +bool Message::OnButtonPushed() { + running = false; + return true; } diff --git a/src/DisplayApp/Screens/Message.h b/src/DisplayApp/Screens/Message.h index ac300faf..4e87bba4 100644 --- a/src/DisplayApp/Screens/Message.h +++ b/src/DisplayApp/Screens/Message.h @@ -8,18 +8,30 @@ #include "../Fonts/lcdfont14.h" #include "../Fonts/lcdfont70.h" #include "../../Version.h" +#include <lvgl/src/lv_core/lv_style.h> namespace Pinetime { namespace Applications { namespace Screens { class Message : public Screen{ public: - Message(Components::Gfx& gfx) : Screen(gfx) {} - void Refresh(bool fullRefresh) override; + explicit Message(DisplayApp* app); + ~Message() override; + bool Refresh() override; + bool OnButtonPushed(); + void OnObjectEvent(lv_obj_t* obj, lv_event_t event); private: - const FONT_INFO largeFont {lCD_70ptFontInfo.height, lCD_70ptFontInfo.startChar, lCD_70ptFontInfo.endChar, lCD_70ptFontInfo.spacePixels, lCD_70ptFontInfo.charInfo, lCD_70ptFontInfo.data}; - const FONT_INFO smallFont {lCD_14ptFontInfo.height, lCD_14ptFontInfo.startChar, lCD_14ptFontInfo.endChar, lCD_14ptFontInfo.spacePixels, lCD_14ptFontInfo.charInfo, lCD_14ptFontInfo.data}; + + lv_style_t* labelStyle; + lv_obj_t * label; + lv_obj_t* backgroundLabel; + lv_obj_t * button; + lv_obj_t * labelClick; + + uint32_t clickCount = 0 ; + uint32_t previousClickCount = 0; + bool running = true; }; } } diff --git a/src/DisplayApp/Screens/Meter.cpp b/src/DisplayApp/Screens/Meter.cpp new file mode 100644 index 00000000..c74b8bdf --- /dev/null +++ b/src/DisplayApp/Screens/Meter.cpp @@ -0,0 +1,47 @@ +#include <libs/lvgl/lvgl.h> +#include "Meter.h" +#include "../DisplayApp.h" + +using namespace Pinetime::Applications::Screens; +extern lv_font_t jetbrains_mono_extrabold_compressed; +extern lv_font_t jetbrains_mono_bold_20; + + +Meter::Meter(Pinetime::Applications::DisplayApp *app) : Screen(app) { + + lv_style_copy(&style_lmeter, &lv_style_pretty_color); + style_lmeter.line.width = 2; + style_lmeter.line.color = LV_COLOR_SILVER; + style_lmeter.body.main_color = lv_color_make(255,0,0); + style_lmeter.body.grad_color = lv_color_make(160,0,0); + style_lmeter.body.padding.left = 16; /*Line length*/ + + /*Create a line meter */ + lmeter = lv_lmeter_create(lv_scr_act(), NULL); + lv_lmeter_set_range(lmeter, 0, 60); /*Set the range*/ + lv_lmeter_set_value(lmeter, value); /*Set the current value*/ + lv_lmeter_set_angle_offset(lmeter, 180); + lv_lmeter_set_scale(lmeter, 360, 60); /*Set the angle and number of lines*/ + lv_lmeter_set_style(lmeter, LV_LMETER_STYLE_MAIN, &style_lmeter); /*Apply the new style*/ + lv_obj_set_size(lmeter, 150, 150); + lv_obj_align(lmeter, NULL, LV_ALIGN_CENTER, 0, 0); + +} + +Meter::~Meter() { + + + lv_obj_clean(lv_scr_act()); +} + +bool Meter::Refresh() { + lv_lmeter_set_value(lmeter, value++); /*Set the current value*/ + if(value>=60) value = 0; + + return running; +} + +bool Meter::OnButtonPushed() { + running = false; + return true; +} diff --git a/src/DisplayApp/Screens/Meter.h b/src/DisplayApp/Screens/Meter.h new file mode 100644 index 00000000..1a08b46c --- /dev/null +++ b/src/DisplayApp/Screens/Meter.h @@ -0,0 +1,38 @@ +#pragma once + +#include <cstdint> +#include <chrono> +#include <Components/Gfx/Gfx.h> +#include "Screen.h" +#include <bits/unique_ptr.h> +#include <libs/lvgl/src/lv_core/lv_style.h> +#include <libs/lvgl/src/lv_core/lv_obj.h> +#include <Components/Battery/BatteryController.h> +#include <Components/Ble/BleController.h> +#include "../Fonts/lcdfont14.h" +#include "../Fonts/lcdfont70.h" +#include "../../Version.h" + +namespace Pinetime { + namespace Applications { + namespace Screens { + + class Meter : public Screen{ + public: + Meter(DisplayApp* app); + ~Meter() override; + + bool Refresh() override; + bool OnButtonPushed() override; + + private: + lv_style_t style_lmeter; + lv_obj_t * lmeter; + + uint32_t value=0; + bool running = true; + + }; + } + } +} diff --git a/src/DisplayApp/Screens/Modal.cpp b/src/DisplayApp/Screens/Modal.cpp new file mode 100644 index 00000000..fc353c49 --- /dev/null +++ b/src/DisplayApp/Screens/Modal.cpp @@ -0,0 +1,81 @@ +#include <libs/lvgl/lvgl.h> +#include "Modal.h" +#include "../DisplayApp.h" + +using namespace Pinetime::Applications::Screens; +extern lv_font_t jetbrains_mono_extrabold_compressed; +extern lv_font_t jetbrains_mono_bold_20; + +Modal::Modal(Pinetime::Applications::DisplayApp *app) : Screen(app) { + + +} + +Modal::~Modal() { + lv_obj_clean(lv_scr_act()); +} + +bool Modal::Refresh() { + + return running; +} + +bool Modal::OnButtonPushed() { + running = false; + return true; +} + +void Modal::Show() { + lv_style_copy(&modal_style, &lv_style_plain_color); + modal_style.body.main_color = modal_style.body.grad_color = LV_COLOR_BLACK; + modal_style.body.opa = LV_OPA_50; + + obj = lv_obj_create(lv_scr_act(), NULL); + lv_obj_set_style(obj, &modal_style); + lv_obj_set_pos(obj, 0, 0); + lv_obj_set_size(obj, LV_HOR_RES, LV_VER_RES); + lv_obj_set_opa_scale_enable(obj, true); /* Enable opacity scaling for the animation */ + + static const char * btns2[] = {"Ok", ""}; + + /* Create the message box as a child of the modal background */ + mbox = lv_mbox_create(obj, NULL); + lv_mbox_add_btns(mbox, btns2); + char versionStr[20]; + sprintf(versionStr, "VERSION: %d.%d.%d", Version::Major(), Version::Minor(), Version::Patch()); + lv_mbox_set_text(mbox, versionStr); +// lv_mbox_set_text(mbox, "Hello world!"); + lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0); + lv_obj_set_event_cb(mbox, Modal::mbox_event_cb); + + mbox->user_data = this; + + /* Fade the message box in with an animation */ + lv_anim_t a; + lv_anim_init(&a); + lv_anim_set_time(&a, 500, 0); + lv_anim_set_values(&a, LV_OPA_TRANSP, LV_OPA_COVER); + lv_anim_set_exec_cb(&a, obj, (lv_anim_exec_xcb_t)lv_obj_set_opa_scale); + lv_anim_create(&a); +} + +void Modal::Hide() { + /* Delete the parent modal background */ + lv_obj_del_async(lv_obj_get_parent(mbox)); + mbox = NULL; /* happens before object is actually deleted! */ +} + +void Modal::mbox_event_cb(lv_obj_t *obj, lv_event_t evt) { + auto* m = static_cast<Modal *>(obj->user_data); + m->OnEvent(obj, evt); +} + +void Modal::OnEvent(lv_obj_t *event_obj, lv_event_t evt) { + if(evt == LV_EVENT_DELETE && event_obj == mbox) { + Hide(); + } else if(evt == LV_EVENT_VALUE_CHANGED) { + /* A button was clicked */ + lv_mbox_start_auto_close(mbox, 0); +// Hide(); + } +} diff --git a/src/DisplayApp/Screens/Modal.h b/src/DisplayApp/Screens/Modal.h new file mode 100644 index 00000000..de287293 --- /dev/null +++ b/src/DisplayApp/Screens/Modal.h @@ -0,0 +1,44 @@ +#pragma once + +#include <cstdint> +#include <chrono> +#include <Components/Gfx/Gfx.h> +#include "Screen.h" +#include <bits/unique_ptr.h> +#include <libs/lvgl/src/lv_core/lv_style.h> +#include <libs/lvgl/src/lv_core/lv_obj.h> +#include <Components/Battery/BatteryController.h> +#include <Components/Ble/BleController.h> +#include "../Fonts/lcdfont14.h" +#include "../Fonts/lcdfont70.h" +#include "../../Version.h" + +namespace Pinetime { + namespace Applications { + namespace Screens { + + class Modal : public Screen{ + public: + Modal(DisplayApp* app); + ~Modal() override; + + void Show(); + void Hide(); + + bool Refresh() override; + bool OnButtonPushed() override; + + static void mbox_event_cb(lv_obj_t *obj, lv_event_t evt); + private: + void OnEvent(lv_obj_t *event_obj, lv_event_t evt); + + lv_style_t modal_style; + lv_obj_t *obj; + lv_obj_t *mbox; + lv_obj_t *info; + bool running = true; + + }; + } + } +} diff --git a/src/DisplayApp/Screens/Screen.h b/src/DisplayApp/Screens/Screen.h index 5e2fa43e..6cbd41ad 100644 --- a/src/DisplayApp/Screens/Screen.h +++ b/src/DisplayApp/Screens/Screen.h @@ -1,17 +1,22 @@ #pragma once -#include <Components/Gfx/Gfx.h> - namespace Pinetime { namespace Applications { + class DisplayApp; namespace Screens { class Screen { public: - Screen(Components::Gfx& gfx) : gfx{gfx} {} - virtual void Refresh(bool fullRefresh) = 0; + Screen(DisplayApp* app) : app{app} {} + virtual ~Screen() = default; + + // Return false if the app can be closed, true if it must continue to run + virtual bool Refresh() = 0; + + // Return false if the button hasn't been handled by the app, true if it has been handled + virtual bool OnButtonPushed() { return false; } protected: - Components::Gfx& gfx; + DisplayApp* app; }; } } diff --git a/src/DisplayApp/Screens/Tab.cpp b/src/DisplayApp/Screens/Tab.cpp new file mode 100644 index 00000000..adc32578 --- /dev/null +++ b/src/DisplayApp/Screens/Tab.cpp @@ -0,0 +1,67 @@ +#include <cstdio> +#include <libs/date/includes/date/date.h> +#include <Components/DateTime/DateTimeController.h> +#include <Version.h> +#include <libs/lvgl/src/lv_core/lv_obj.h> +#include <libs/lvgl/src/lv_font/lv_font.h> +#include <libs/lvgl/lvgl.h> +#include <libraries/log/nrf_log.h> +#include "Tab.h" +#include <DisplayApp/DisplayApp.h> + + +using namespace Pinetime::Applications::Screens; + +extern lv_font_t jetbrains_mono_bold_20; + +//static void event_handler(lv_obj_t * obj, lv_event_t event) { +// Tile* screen = static_cast<Tile *>(obj->user_data); +// screen->OnObjectEvent(obj, event); +//} + +Tab::Tab(DisplayApp* app, Pinetime::Components::Gfx &gfx) : Screen(app, gfx) { +/*Create a Tab view object*/ + lv_obj_t *tabview; + tabview = lv_tabview_create(lv_scr_act(), NULL); + + /*Add 3 tabs (the tabs are page (lv_page) and can be scrolled*/ + lv_obj_t *tab1 = lv_tabview_add_tab(tabview, "Tab 1"); + lv_obj_t *tab2 = lv_tabview_add_tab(tabview, "Tab 2"); + lv_obj_t *tab3 = lv_tabview_add_tab(tabview, "Tab 3"); + + + /*Add content to the tabs*/ + lv_obj_t * label = lv_label_create(tab1, NULL); + lv_label_set_text(label, "This the first tab\n\n" + "If the content\n" + "of a tab\n" + "become too long\n" + "the it \n" + "automatically\n" + "become\n" + "scrollable."); + + label = lv_label_create(tab2, NULL); + lv_label_set_text(label, "Second tab"); + + label = lv_label_create(tab3, NULL); + lv_label_set_text(label, "Third tab"); + +} + +Tab::~Tab() { + lv_obj_clean(lv_scr_act()); +} + +void Tab::Refresh(bool fullRefresh) { + +} + +void Tab::OnObjectEvent(lv_obj_t *obj, lv_event_t event) { + if(event == LV_EVENT_CLICKED) { + NRF_LOG_INFO("Clicked"); + } + else if(event == LV_EVENT_VALUE_CHANGED) { + NRF_LOG_INFO("Toggled"); + } +} diff --git a/src/DisplayApp/Screens/Tab.h b/src/DisplayApp/Screens/Tab.h new file mode 100644 index 00000000..1af956f4 --- /dev/null +++ b/src/DisplayApp/Screens/Tab.h @@ -0,0 +1,28 @@ +#pragma once + +#include <cstdint> +#include <chrono> +#include <Components/Gfx/Gfx.h> +#include "Screen.h" +#include <bits/unique_ptr.h> +#include "../Fonts/lcdfont14.h" +#include "../Fonts/lcdfont70.h" +#include "../../Version.h" +#include <lvgl/src/lv_core/lv_style.h> + +namespace Pinetime { + namespace Applications { + namespace Screens { + class Tab : public Screen { + public: + explicit Tab(DisplayApp* app, Components::Gfx& gfx); + ~Tab() override; + void Refresh(bool fullRefresh) override; + void OnObjectEvent(lv_obj_t* obj, lv_event_t event); + + private: + + }; + } + } +} diff --git a/src/DisplayApp/Screens/Tile.cpp b/src/DisplayApp/Screens/Tile.cpp new file mode 100644 index 00000000..004c8d31 --- /dev/null +++ b/src/DisplayApp/Screens/Tile.cpp @@ -0,0 +1,163 @@ +#include <libs/lvgl/src/lv_core/lv_obj.h> +#include <libs/lvgl/src/lv_font/lv_font.h> +#include <libs/lvgl/lvgl.h> +#include "Tile.h" +#include <DisplayApp/DisplayApp.h> + + +using namespace Pinetime::Applications::Screens; + +extern lv_font_t jetbrains_mono_bold_20; + +static void event_handler(lv_obj_t * obj, lv_event_t event) { + Tile* screen = static_cast<Tile *>(obj->user_data); + uint32_t* eventDataPtr = (uint32_t*) lv_event_get_data(); + uint32_t eventData = *eventDataPtr; + screen->OnObjectEvent(obj, event, eventData); +} + +static const char * btnm_map1[] = {"Meter", "Gauge", "Clock", "\n", "Soft\nversion", "App2", "App3", ""}; + +Tile::Tile(DisplayApp* app) : Screen(app) { + modal.reset(new Modal(app)); +/* + static lv_point_t valid_pos[] = {{0,0}, {LV_COORD_MIN, LV_COORD_MIN}}; + tileview = lv_tileview_create(lv_scr_act(), NULL); + lv_tileview_set_valid_positions(tileview, valid_pos, 1); + lv_tileview_set_edge_flash(tileview, false); + + tile1 = lv_obj_create(tileview, NULL); + lv_obj_set_pos(tile1, 0, 0); + lv_obj_set_size(tile1, LV_HOR_RES, LV_VER_RES); + lv_tileview_add_element(tileview, tile1); +*/ + btnm1 = lv_btnm_create(lv_scr_act(), NULL); + lv_btnm_set_map(btnm1, btnm_map1); + lv_obj_set_size(btnm1, LV_HOR_RES, LV_VER_RES); + +// labelRelStyle = const_cast<lv_style_t *>(lv_label_get_style(btnm1, LV_BTNM_STYLE_BTN_REL)); +// labelRelStyle->text.font = &jetbrains_mono_bold_20; +// labelRelStyle->body.grad_color = labelRelStyle->body.main_color; +// lv_btnm_set_style(btnm1, LV_BTNM_STYLE_BTN_REL, labelRelStyle); +// +// labelPrStyle = const_cast<lv_style_t *>(lv_label_get_style(btnm1, LV_BTNM_STYLE_BTN_PR)); +// labelPrStyle->text.font = &jetbrains_mono_bold_20; +// labelPrStyle->body.grad_color = labelPrStyle->body.shadow.color; + + + +// lv_btnm_set_style(btnm1, LV_BTNM_STYLE_BTN_PR, labelPrStyle); +//TODO better style handling +// lv_obj_align(btnm1, tile1, LV_ALIGN_CENTER, 0, 0); + btnm1->user_data = this; + lv_obj_set_event_cb(btnm1, event_handler); + +/* + tile2 = lv_obj_create(tileview, NULL); + lv_obj_set_pos(tile2, 0, LV_VER_RES); + lv_obj_set_size(tile2, LV_HOR_RES, LV_VER_RES); + lv_tileview_add_element(tileview, tile2); + + btnm2 = lv_btnm_create(tileview, NULL); + lv_btnm_set_map(btnm2, btnm_map2); + lv_obj_align(btnm2, tile2, LV_ALIGN_CENTER, 0, 0); +*/ +/* + tile1 = lv_obj_create(tileview, NULL); + lv_obj_set_pos(tile1, 0, 0); + lv_obj_set_size(tile1, LV_HOR_RES, LV_VER_RES); + lv_tileview_add_element(tileview, tile1); + + btn1 = lv_btn_create(tile1, NULL); + lv_obj_align(btn1, tile1, LV_ALIGN_CENTER, 0, 0); + + label1 = lv_label_create(btn1, NULL); + lv_label_set_text(label1, "Button1"); +*/ +/* + tile2 = lv_obj_create(tileview, NULL); + lv_obj_set_pos(tile2, 0, LV_VER_RES); + lv_obj_set_size(tile2, LV_HOR_RES, LV_VER_RES); + lv_tileview_add_element(tileview, tile2); + + btn2 = lv_btn_create(tile2, NULL); + lv_obj_align(btn2, tile2, LV_ALIGN_CENTER, 0, 0); + + + label2 = lv_label_create(btn2, NULL); + lv_label_set_text(label2, "Button2"); + + tile3 = lv_obj_create(tileview, NULL); + lv_obj_set_pos(tile3, 0, LV_VER_RES*2); + lv_obj_set_size(tile3, LV_HOR_RES, LV_VER_RES); + lv_tileview_add_element(tileview, tile3); + + btn3 = lv_btn_create(tile3, NULL); + lv_obj_align(btn3, tile3, LV_ALIGN_CENTER, 0, 0); + + + label3 = lv_label_create(btn3, NULL); + lv_label_set_text(label3, "Button3"); +*/ +} + +Tile::~Tile() { + lv_obj_clean(lv_scr_act()); +} + +bool Tile::Refresh() { + return running; +} + +void Tile::OnObjectEvent(lv_obj_t *obj, lv_event_t event, uint32_t buttonId) { + auto* tile = static_cast<Tile*>(obj->user_data); + if(event == LV_EVENT_VALUE_CHANGED) { + switch(buttonId) { + case 0: + tile->StartMeterApp(); + break; + case 1: + tile->StartGaugeApp(); + break; + case 2: + tile->StartClockApp(); + break; + case 3: + modal->Show(); + break; + case 4: + case 5: + tile->StartTestApp(); + + break; + } + clickCount++; + } +} + +bool Tile::OnButtonPushed() { + app->StartApp(DisplayApp::Apps::Clock); + running = false; + return true; +} + +void Tile::StartClockApp() { + app->StartApp(DisplayApp::Apps::Clock); + running = false; +} + +void Tile::StartTestApp() { + app->StartApp(DisplayApp::Apps::Test); + running = false; +} + +void Tile::StartMeterApp() { + app->StartApp(DisplayApp::Apps::Meter); + running = false; +} + +void Tile::StartGaugeApp() { + app->StartApp(DisplayApp::Apps::Gauge); + running = false; +} + diff --git a/src/DisplayApp/Screens/Tile.h b/src/DisplayApp/Screens/Tile.h new file mode 100644 index 00000000..eb253435 --- /dev/null +++ b/src/DisplayApp/Screens/Tile.h @@ -0,0 +1,64 @@ +#pragma once + +#include <cstdint> +#include <chrono> +#include <Components/Gfx/Gfx.h> +#include "Screen.h" +#include <bits/unique_ptr.h> +#include "../Fonts/lcdfont14.h" +#include "../Fonts/lcdfont70.h" +#include "../../Version.h" +#include "Modal.h" +#include <lvgl/src/lv_core/lv_style.h> + +namespace Pinetime { + namespace Applications { + namespace Screens { + class Tile : public Screen { + public: + explicit Tile(DisplayApp* app); + ~Tile() override; + + bool Refresh() override; + bool OnButtonPushed() override; + + void OnObjectEvent(lv_obj_t* obj, lv_event_t event, uint32_t buttonId); + + private: + + lv_style_t* labelRelStyle; + lv_style_t* labelPrStyle; + lv_obj_t * label1; + lv_obj_t * label2; + lv_obj_t * label3; + + lv_obj_t* backgroundLabel; + lv_obj_t * button; + lv_obj_t * labelClick; + + lv_obj_t *tileview; + lv_obj_t * tile1; + lv_obj_t * tile2; + lv_obj_t * list; + lv_obj_t * list_btn; + lv_obj_t * tile3; + lv_obj_t * btn1; + lv_obj_t * btn2; + lv_obj_t * btn3; + + lv_obj_t * btnm1; + lv_obj_t * btnm2; + + uint32_t clickCount = 0 ; + uint32_t previousClickCount = 0; + void StartClockApp(); + void StartTestApp(); + void StartMeterApp(); + void StartGaugeApp(); + bool running = true; + + std::unique_ptr<Modal> modal; + }; + } + } +} diff --git a/src/FreeRTOSConfig.h b/src/FreeRTOSConfig.h index ecc631bb..609c3f2b 100644 --- a/src/FreeRTOSConfig.h +++ b/src/FreeRTOSConfig.h @@ -63,7 +63,7 @@ #define configTICK_RATE_HZ 1024 #define configMAX_PRIORITIES ( 3 ) #define configMINIMAL_STACK_SIZE ( 120 ) -#define configTOTAL_HEAP_SIZE ( 24000 ) +#define configTOTAL_HEAP_SIZE ( 1024*10 ) #define configMAX_TASK_NAME_LEN ( 4 ) #define configUSE_16_BIT_TICKS 0 #define configIDLE_SHOULD_YIELD 1 @@ -78,7 +78,7 @@ #define configENABLE_BACKWARD_COMPATIBILITY 1 /* Hook function related definitions. */ -#define configUSE_IDLE_HOOK 0 +#define configUSE_IDLE_HOOK 1 #define configUSE_TICK_HOOK 0 #define configCHECK_FOR_STACK_OVERFLOW 0 #define configUSE_MALLOC_FAILED_HOOK 0 diff --git a/src/SystemTask/SystemTask.cpp b/src/SystemTask/SystemTask.cpp new file mode 100644 index 00000000..e15846da --- /dev/null +++ b/src/SystemTask/SystemTask.cpp @@ -0,0 +1,123 @@ +#include <libraries/log/nrf_log.h> +#include <libraries/gpiote/app_gpiote.h> +#include <drivers/Cst816s.h> +#include <DisplayApp/LittleVgl.h> +#include <hal/nrf_rtc.h> +#include <BLE/BleManager.h> +#include <softdevice/common/nrf_sdh_freertos.h> +#include "SystemTask.h" +#include "../main.h" +using namespace Pinetime::System; + +SystemTask::SystemTask(Pinetime::Drivers::SpiMaster &spi, Pinetime::Drivers::St7789 &lcd, + Pinetime::Drivers::Cst816S &touchPanel, Pinetime::Components::LittleVgl &lvgl, + Pinetime::Controllers::Battery &batteryController, Pinetime::Controllers::Ble &bleController, + Pinetime::Controllers::DateTime& dateTimeController) : + spi{spi}, lcd{lcd}, touchPanel{touchPanel}, lvgl{lvgl}, batteryController{batteryController}, bleController{bleController}, dateTimeController{dateTimeController} { + systemTaksMsgQueue = xQueueCreate(10, 1); +} + +void SystemTask::Start() { + if (pdPASS != xTaskCreate(SystemTask::Process, "MAIN", 350, this, 0, &taskHandle)) + APP_ERROR_HANDLER(NRF_ERROR_NO_MEM); +} + +void SystemTask::Process(void *instance) { + auto *app = static_cast<SystemTask *>(instance); + NRF_LOG_INFO("SystemTask task started!"); + app->Work(); +} + +void SystemTask::Work() { + watchdog.Setup(7); + watchdog.Start(); + NRF_LOG_INFO("Last reset reason : %s", Pinetime::Drivers::Watchdog::ResetReasonToString(watchdog.ResetReason())); + APP_GPIOTE_INIT(2); + bool erase_bonds=false; + nrf_sdh_freertos_init(ble_manager_start_advertising, &erase_bonds); + + spi.Init(); + lcd.Init(); + touchPanel.Init(); + batteryController.Init(); + + displayApp.reset(new Pinetime::Applications::DisplayApp(lcd, lvgl, touchPanel, batteryController, bleController, dateTimeController, *this)); + displayApp->Start(); + + batteryController.Update(); + displayApp->PushMessage(Pinetime::Applications::DisplayApp::Messages::UpdateBatteryLevel); + + nrf_gpio_cfg_sense_input(pinButton, (nrf_gpio_pin_pull_t)GPIO_PIN_CNF_PULL_Pulldown, (nrf_gpio_pin_sense_t)GPIO_PIN_CNF_SENSE_High); + nrf_gpio_cfg_output(15); + nrf_gpio_pin_set(15); + + nrfx_gpiote_in_config_t pinConfig; + pinConfig.skip_gpio_setup = true; + pinConfig.hi_accuracy = false; + pinConfig.is_watcher = false; + pinConfig.sense = (nrf_gpiote_polarity_t)NRF_GPIOTE_POLARITY_HITOLO; + pinConfig.pull = (nrf_gpio_pin_pull_t)GPIO_PIN_CNF_PULL_Pulldown; + + nrfx_gpiote_in_init(pinButton, &pinConfig, nrfx_gpiote_evt_handler); + + nrf_gpio_cfg_sense_input(pinTouchIrq, (nrf_gpio_pin_pull_t)GPIO_PIN_CNF_PULL_Pullup, (nrf_gpio_pin_sense_t)GPIO_PIN_CNF_SENSE_Low); + + pinConfig.skip_gpio_setup = true; + pinConfig.hi_accuracy = false; + pinConfig.is_watcher = false; + pinConfig.sense = (nrf_gpiote_polarity_t)NRF_GPIOTE_POLARITY_HITOLO; + pinConfig.pull = (nrf_gpio_pin_pull_t)GPIO_PIN_CNF_PULL_Pullup; + + nrfx_gpiote_in_init(pinTouchIrq, &pinConfig, nrfx_gpiote_evt_handler); + + + while(true) { + uint8_t msg; + if (xQueueReceive(systemTaksMsgQueue, &msg, isSleeping?2500 : 1000)) { + Messages message = static_cast<Messages >(msg); + switch(message) { + case Messages::GoToRunning: isSleeping = false; break; + case Messages::GoToSleep: + NRF_LOG_INFO("[SystemTask] Going to sleep"); + displayApp->PushMessage(Pinetime::Applications::DisplayApp::Messages::GoToSleep); + isSleeping = true; break; + default: break; + } + } + uint32_t systick_counter = nrf_rtc_counter_get(portNRF_RTC_REG); + dateTimeController.UpdateTime(systick_counter); + + if(!nrf_gpio_pin_read(pinButton)) + watchdog.Kick(); + } +} + +void SystemTask::OnButtonPushed() { + + if(!isSleeping) { + NRF_LOG_INFO("[SystemTask] Button pushed"); + displayApp->PushMessage(Pinetime::Applications::DisplayApp::Messages::ButtonPushed); + } + else { + NRF_LOG_INFO("[SystemTask] Button pushed, waking up"); + displayApp->PushMessage(Pinetime::Applications::DisplayApp::Messages::GoToRunning); + isSleeping = false; + batteryController.Update(); + displayApp->PushMessage(Pinetime::Applications::DisplayApp::Messages::UpdateBatteryLevel); + } +} + +void SystemTask::OnTouchEvent() { + NRF_LOG_INFO("[SystemTask] Touch event"); + displayApp->PushMessage(Pinetime::Applications::DisplayApp::Messages::TouchEvent); +} + +void SystemTask::PushMessage(SystemTask::Messages msg) { + BaseType_t xHigherPriorityTaskWoken; + xHigherPriorityTaskWoken = pdFALSE; + xQueueSendFromISR(systemTaksMsgQueue, &msg, &xHigherPriorityTaskWoken); + if (xHigherPriorityTaskWoken) { + /* Actual macro used here is port specific. */ + // TODO : should I do something here? + } +} diff --git a/src/SystemTask/SystemTask.h b/src/SystemTask/SystemTask.h new file mode 100644 index 00000000..f5ba2d75 --- /dev/null +++ b/src/SystemTask/SystemTask.h @@ -0,0 +1,62 @@ +#pragma once + +#include <FreeRTOS.h> +#include <task.h> +#include <memory> +#include <drivers/SpiMaster.h> +#include <drivers/St7789.h> +#include <Components/Battery/BatteryController.h> +#include <DisplayApp/DisplayApp.h> +#include <drivers/Watchdog.h> + +namespace Pinetime { + namespace System { + class SystemTask { + public: + enum class Messages {GoToSleep, GoToRunning}; + + SystemTask(Pinetime::Drivers::SpiMaster& spi, + Pinetime::Drivers::St7789& lcd, + Pinetime::Drivers::Cst816S& touchPanel, + Pinetime::Components::LittleVgl& lvgl, + Pinetime::Controllers::Battery& batteryController, + Pinetime::Controllers::Ble& bleController, + Pinetime::Controllers::DateTime& dateTimeController); + + + void Start(); + void PushMessage(Messages msg); + + void OnButtonPushed(); + void OnTouchEvent(); + private: + TaskHandle_t taskHandle; + + Pinetime::Drivers::SpiMaster& spi; + Pinetime::Drivers::St7789& lcd; + Pinetime::Drivers::Cst816S& touchPanel; + Pinetime::Components::LittleVgl& lvgl; + Pinetime::Controllers::Battery& batteryController; + std::unique_ptr<Pinetime::Applications::DisplayApp> displayApp; + Pinetime::Controllers::Ble& bleController; + Pinetime::Controllers::DateTime& dateTimeController; + QueueHandle_t systemTaksMsgQueue; + bool isSleeping = false; + Pinetime::Drivers::Watchdog watchdog; + + + static constexpr uint8_t pinSpiSck = 2; + static constexpr uint8_t pinSpiMosi = 3; + static constexpr uint8_t pinSpiMiso = 4; + static constexpr uint8_t pinSpiCsn = 25; + static constexpr uint8_t pinLcdDataCommand = 18; + static constexpr uint8_t pinButton = 13; + static constexpr uint8_t pinTouchIrq = 28; + + static void Process(void* instance); + void Work(); + + + }; + } +}
\ No newline at end of file diff --git a/src/drivers/Cst816s.cpp b/src/drivers/Cst816s.cpp index 67700f53..61bce94c 100644 --- a/src/drivers/Cst816s.cpp +++ b/src/drivers/Cst816s.cpp @@ -50,29 +50,58 @@ Cst816S::TouchInfos Cst816S::GetTouchInfo() { nrfx_twi_rx(&twi, address, touchData, 63); auto nbTouchPoints = touchData[2] & 0x0f; - uint8_t i = 0; +// uint8_t i = 0; +// NRF_LOG_INFO("#########################") + for(int i = 0; i < 1; i++) { uint8_t pointId = (touchData[touchIdIndex + (touchStep * i)]) >> 4; if(nbTouchPoints == 0 && pointId == lastTouchId) return info; // We fetch only the first touch point (the controller seems to handle only one anyway...) info.isTouch = true; - auto xHigh = touchData[touchXHighIndex + (touchStep * i)] & 0x0f; - auto xLow = touchData[touchXLowIndex + (touchStep * i)]; - uint16_t x = (xHigh << 8) | xLow; - auto yHigh = touchData[touchYHighIndex + (touchStep * i)] & 0x0f; - auto yLow = touchData[touchYLowIndex + (touchStep * i)]; - uint16_t y = (yHigh << 8) | yLow; + auto xHigh = touchData[touchXHighIndex + (touchStep * i)] & 0x0f; + auto xLow = touchData[touchXLowIndex + (touchStep * i)]; + uint16_t x = (xHigh << 8) | xLow; + + auto yHigh = touchData[touchYHighIndex + (touchStep * i)] & 0x0f; + auto yLow = touchData[touchYLowIndex + (touchStep * i)]; + uint16_t y = (yHigh << 8) | yLow; + + auto action = touchData[touchEventIndex + (touchStep * i)] >> 6; /* 0 = Down, 1 = Up, 2 = contact*/ + auto finger = touchData[touchIdIndex + (touchStep * i)] >> 4; + auto pressure = touchData[touchXYIndex + (touchStep * i)]; + auto area = touchData[touchMiscIndex + (touchStep * i)] >> 4; + + info.x = x; + info.y = y; + info.action = action; + info.gesture = static_cast<Gestures>(touchData[gestureIndex]); + +// NRF_LOG_INFO("---------------") +// NRF_LOG_INFO("ID : %d", pointId); +// NRF_LOG_INFO("NB : %d", nbTouchPoints); +// NRF_LOG_INFO("X/Y :%d / %d", info.x, info.y); +// NRF_LOG_INFO("Action : %d", action); +// NRF_LOG_INFO("Finger : %d", finger); +// NRF_LOG_INFO("Pressure : %d", pressure); +// NRF_LOG_INFO("area : %d", area); +// NRF_LOG_INFO("Touch : %s", info.isTouch?"Yes" : "No"); +// switch(info.gesture) {// gesture +// case Gestures::None: NRF_LOG_INFO("Gesture : None"); break; +// case Gestures::SlideDown: NRF_LOG_INFO("Gesture : Slide Down"); break; +// case Gestures::SlideUp: NRF_LOG_INFO("Gesture : Slide Up"); break; +// case Gestures::SlideLeft: NRF_LOG_INFO("Gesture : Slide Left"); break; +// case Gestures::SlideRight: NRF_LOG_INFO("Gesture : Slide Right"); break; +// case Gestures::SingleTap: NRF_LOG_INFO("Gesture : Single click"); break; +// case Gestures::DoubleTap: NRF_LOG_INFO("Gesture : Double click"); break; +// case Gestures::LongPress: NRF_LOG_INFO("Gesture : Long press"); break; +// default : NRF_LOG_INFO("Unknown"); break; +// } + + } - auto action = touchData[touchEventIndex + (touchStep * i)] >> 6; /* 0 = Down, 1 = Up, 2 = contact*/ - auto finger = touchData[touchIdIndex + (touchStep * i)] >> 4; - auto pressure = touchData[touchXYIndex + (touchStep * i)]; - auto area = touchData[touchMiscIndex + (touchStep * i)] >> 4; - info.x = x; - info.y = y; - info.action = action; return info; } diff --git a/src/drivers/Cst816s.h b/src/drivers/Cst816s.h index 0adb448b..93b05df1 100644 --- a/src/drivers/Cst816s.h +++ b/src/drivers/Cst816s.h @@ -6,6 +6,16 @@ namespace Pinetime { namespace Drivers { class Cst816S { public : + enum class Gestures : uint8_t { + None = 0x00, + SlideDown = 0x01, + SlideUp = 0x02, + SlideLeft = 0x03, + SlideRight = 0x04, + SingleTap = 0x05, + DoubleTap = 0x0B, + LongPress = 0x0C + }; struct TouchInfos { uint16_t x; uint16_t y; @@ -13,6 +23,7 @@ namespace Pinetime { uint8_t finger; uint8_t pressure; uint8_t area; + Gestures gesture; bool isTouch = false; }; @@ -36,6 +47,7 @@ namespace Pinetime { static constexpr uint8_t touchYLowIndex = 6; static constexpr uint8_t touchIdIndex = 5; static constexpr uint8_t touchStep = 6; + static constexpr uint8_t gestureIndex = 1; uint8_t touchData[63]; diff --git a/src/drivers/DebugPins.cpp b/src/drivers/DebugPins.cpp new file mode 100644 index 00000000..5a12fd86 --- /dev/null +++ b/src/drivers/DebugPins.cpp @@ -0,0 +1,49 @@ +#include <hal/nrf_gpio.h> +#include "DebugPins.h" + +#ifdef USE_DEBUG_PINS +void debugpins_init() { + nrf_gpio_cfg_output(DebugPin0); + nrf_gpio_pin_clear(DebugPin0); + + nrf_gpio_cfg_output(DebugPin1); + nrf_gpio_pin_clear(DebugPin1); + + nrf_gpio_cfg_output(DebugPin2); + nrf_gpio_pin_clear(DebugPin2); + + nrf_gpio_cfg_output(DebugPin3); + nrf_gpio_pin_clear(DebugPin3); + + nrf_gpio_cfg_output(DebugPin4); + nrf_gpio_pin_clear(DebugPin4); +} +void debugpins_set(debugpins_pins pin) { + nrf_gpio_pin_set((uint32_t)(pin)); +} + +void debugpins_clear(debugpins_pins pin) { + nrf_gpio_pin_clear((uint32_t)(pin)); +} + +void debugpins_pulse(debugpins_pins pin) { + nrf_gpio_pin_set((uint32_t)(pin)); + nrf_gpio_pin_clear((uint32_t)(pin)); +} +#else +void debugpins_init() { + +} +void debugpins_set(debugpins_pins pin) { + +} + +void debugpins_clear(debugpins_pins pin) { + +} + +void debugpins_pulse(debugpins_pins pin) { + +} + +#endif
\ No newline at end of file diff --git a/src/drivers/DebugPins.h b/src/drivers/DebugPins.h new file mode 100644 index 00000000..cb20bac5 --- /dev/null +++ b/src/drivers/DebugPins.h @@ -0,0 +1,25 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdint.h> + +typedef enum { + DebugPin0 = 27, + DebugPin1 = 29, + DebugPin2 = 20, + DebugPin3 = 17, + DebugPin4 = 11, +} debugpins_pins; + +void debugpins_init(); +void debugpins_set(debugpins_pins pin); +void debugpins_clear(debugpins_pins pin); +void debugpins_pulse(debugpins_pins pin); + +#ifdef __cplusplus +} +#endif + diff --git a/src/drivers/SpiMaster.cpp b/src/drivers/SpiMaster.cpp index 4a875b9e..71986054 100644 --- a/src/drivers/SpiMaster.cpp +++ b/src/drivers/SpiMaster.cpp @@ -1,7 +1,10 @@ +#include <FreeRTOS.h> #include <hal/nrf_gpio.h> #include <hal/nrf_spim.h> #include "SpiMaster.h" #include <algorithm> +#include <task.h> + using namespace Pinetime::Drivers; SpiMaster::SpiMaster(const SpiMaster::SpiModule spi, const SpiMaster::Parameters ¶ms) : @@ -96,7 +99,7 @@ void SpiMaster::DisableWorkaroundForFtpan58(NRF_SPIM_Type *spim, uint32_t ppi_ch spim->INTENSET = (1<<19); } -void SpiMaster::OnEndEvent(BufferProvider& provider) { +void SpiMaster::OnEndEvent() { if(!busy) return; auto s = currentBufferSize; @@ -110,24 +113,20 @@ void SpiMaster::OnEndEvent(BufferProvider& provider) { } else { uint8_t* buffer = nullptr; size_t size = 0; - if(provider.GetNextBuffer(&buffer, size)) { - currentBufferAddr = (uint32_t) buffer; - currentBufferSize = size; - auto s = currentBufferSize; - auto currentSize = std::min((size_t)255, s); - PrepareTx(currentBufferAddr, currentSize); - currentBufferAddr += currentSize; - currentBufferSize -= currentSize; - - spiBaseAddress->TASKS_START = 1; - } else { - busy = false; - nrf_gpio_pin_set(pinCsn); + busy = false; + + + if(taskToNotify != nullptr) { + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + vTaskNotifyGiveFromISR(taskToNotify, &xHigherPriorityTaskWoken); + portYIELD_FROM_ISR(xHigherPriorityTaskWoken); } + + nrf_gpio_pin_set(pinCsn); } } -void SpiMaster::OnStartedEvent(BufferProvider& provider) { +void SpiMaster::OnStartedEvent() { if(!busy) return; } @@ -143,7 +142,7 @@ void SpiMaster::PrepareTx(const volatile uint32_t bufferAddress, const volatile bool SpiMaster::Write(const uint8_t *data, size_t size) { if(data == nullptr) return false; - + taskToNotify = xTaskGetCurrentTaskHandle(); while(busy) { asm("nop"); } diff --git a/src/drivers/SpiMaster.h b/src/drivers/SpiMaster.h index 60013242..82042bdf 100644 --- a/src/drivers/SpiMaster.h +++ b/src/drivers/SpiMaster.h @@ -1,8 +1,10 @@ #pragma once +#include <FreeRTOS.h> #include <cstdint> #include <cstddef> #include <array> #include <atomic> +#include <task.h> #include "BufferProvider.h" namespace Pinetime { @@ -27,8 +29,8 @@ namespace Pinetime { bool Init(); bool Write(const uint8_t* data, size_t size); - void OnStartedEvent(BufferProvider& provider); - void OnEndEvent(BufferProvider& provider); + void OnStartedEvent(); + void OnEndEvent(); void Sleep(); void Wakeup(); @@ -47,6 +49,7 @@ namespace Pinetime { volatile bool busy = false; volatile uint32_t currentBufferAddr = 0; volatile size_t currentBufferSize = 0; + volatile TaskHandle_t taskToNotify; }; } } diff --git a/src/drivers/Watchdog.cpp b/src/drivers/Watchdog.cpp new file mode 100644 index 00000000..b0dc12e5 --- /dev/null +++ b/src/drivers/Watchdog.cpp @@ -0,0 +1,60 @@ +#include <mdk/nrf52.h> +#include <mdk/nrf52_bitfields.h> +#include <nrf_soc.h> +#include "Watchdog.h" +using namespace Pinetime::Drivers; + + +void Watchdog::Setup(uint8_t timeoutSeconds) { + NRF_WDT->CONFIG &= ~(WDT_CONFIG_SLEEP_Msk << WDT_CONFIG_SLEEP_Pos); + NRF_WDT->CONFIG |= (WDT_CONFIG_HALT_Run << WDT_CONFIG_SLEEP_Pos); + + NRF_WDT->CONFIG &= ~(WDT_CONFIG_HALT_Msk << WDT_CONFIG_HALT_Pos); + NRF_WDT->CONFIG |= (WDT_CONFIG_HALT_Pause << WDT_CONFIG_HALT_Pos); + + /* timeout (s) = (CRV + 1) / 32768 */ + // JF : 7500 = 7.5s + uint32_t crv = (((timeoutSeconds*1000u) << 15u) / 1000) - 1; + NRF_WDT->CRV = crv; + + /* Enable reload requests */ + NRF_WDT->RREN = (WDT_RREN_RR0_Enabled << WDT_RREN_RR0_Pos); +} + +void Watchdog::Start() { + NRF_WDT->TASKS_START = 1; +} + +void Watchdog::Kick() { + NRF_WDT->RR[0] = WDT_RR_RR_Reload; +} + +Watchdog::ResetReasons Watchdog::ResetReason() { + uint32_t resetReason; + sd_power_reset_reason_get(&resetReason); + sd_power_reset_reason_clr(0xFFFFFFFF); + if(resetReason & 0x01) return ResetReasons::ResetPin; + if((resetReason >> 1) & 0x01) return ResetReasons::Watchdog; + if((resetReason >> 2) & 0x01) return ResetReasons::SoftReset; + if((resetReason >> 3) & 0x01) return ResetReasons::CpuLockup; + if((resetReason >> 16) & 0x01) return ResetReasons::SystemOff; + if((resetReason >> 17) & 0x01) return ResetReasons::LpComp; + if((resetReason >> 18) & 0x01) return ResetReasons::DebugInterface; + if((resetReason >> 19) & 0x01) return ResetReasons::NFC; + return ResetReasons::HardReset; +} + +const char *Watchdog::ResetReasonToString(Watchdog::ResetReasons reason) { + switch(reason) { + case ResetReasons::ResetPin: return "Reset pin"; + case ResetReasons::Watchdog: return "Watchdog"; + case ResetReasons::DebugInterface: return "Debug interface"; + case ResetReasons::LpComp: return "LPCOMP"; + case ResetReasons::SystemOff: return "System OFF"; + case ResetReasons::CpuLockup: return "CPU Lock-up"; + case ResetReasons::SoftReset: return "Soft reset"; + case ResetReasons::NFC: return "NFC"; + case ResetReasons::HardReset: return "Hard reset"; + default: return "Unknown"; + } +} diff --git a/src/drivers/Watchdog.h b/src/drivers/Watchdog.h new file mode 100644 index 00000000..da192d9e --- /dev/null +++ b/src/drivers/Watchdog.h @@ -0,0 +1,17 @@ +#pragma once + +namespace Pinetime { + namespace Drivers { + class Watchdog { + public: + enum class ResetReasons { ResetPin, Watchdog, SoftReset, CpuLockup, SystemOff, LpComp, DebugInterface, NFC, HardReset }; + void Setup(uint8_t timeoutSeconds); + void Start(); + void Kick(); + + ResetReasons ResetReason(); + static const char* ResetReasonToString(ResetReasons reason); + + }; + } +} diff --git a/src/libs/lv_conf.h b/src/libs/lv_conf.h new file mode 100644 index 00000000..2f9c00e7 --- /dev/null +++ b/src/libs/lv_conf.h @@ -0,0 +1,587 @@ +/** + * @file lv_conf.h + * + */ + +#if 1 /*Set it to "1" to enable content*/ + +#ifndef LV_CONF_H +#define LV_CONF_H +/* clang-format off */ + +#include <stdint.h> + +/*==================== + Graphical settings + *====================*/ + +/* Maximal horizontal and vertical resolution to support by the library.*/ +#define LV_HOR_RES_MAX (240) +#define LV_VER_RES_MAX (240) + +/* Color depth: + * - 1: 1 byte per pixel + * - 8: RGB233 + * - 16: RGB565 + * - 32: ARGB8888 + */ +#define LV_COLOR_DEPTH 16 + +/* Swap the 2 bytes of RGB565 color. + * Useful if the display has a 8 bit interface (e.g. SPI)*/ +#define LV_COLOR_16_SWAP 1 + +/* 1: Enable screen transparency. + * Useful for OSD or other overlapping GUIs. + * Requires `LV_COLOR_DEPTH = 32` colors and the screen's style should be modified: `style.body.opa = ...`*/ +#define LV_COLOR_SCREEN_TRANSP 0 + +/*Images pixels with this color will not be drawn (with chroma keying)*/ +#define LV_COLOR_TRANSP LV_COLOR_LIME /*LV_COLOR_LIME: pure green*/ + +/* Enable chroma keying for indexed images. */ +#define LV_INDEXED_CHROMA 1 + +/* Enable anti-aliasing (lines, and radiuses will be smoothed) */ +#define LV_ANTIALIAS 1 + +/* Default display refresh period. + * Can be changed in the display driver (`lv_disp_drv_t`).*/ +#define LV_DISP_DEF_REFR_PERIOD 30 /*[ms]*/ + +/* Dot Per Inch: used to initialize default sizes. + * E.g. a button with width = LV_DPI / 2 -> half inch wide + * (Not so important, you can adjust it to modify default sizes and spaces)*/ +#define LV_DPI 100 /*[px]*/ + +/* Type of coordinates. Should be `int16_t` (or `int32_t` for extreme cases) */ +typedef int16_t lv_coord_t; + +/*========================= + Memory manager settings + *=========================*/ + +/* LittelvGL's internal memory manager's settings. + * The graphical objects and other related data are stored here. */ + +/* 1: use custom malloc/free, 0: use the built-in `lv_mem_alloc` and `lv_mem_free` */ +#define LV_MEM_CUSTOM 0 +#if LV_MEM_CUSTOM == 0 +/* Size of the memory used by `lv_mem_alloc` in bytes (>= 2kB)*/ +# define LV_MEM_SIZE (4U * 1024U) + +/* Complier prefix for a big array declaration */ +# define LV_MEM_ATTR + +/* Set an address for the memory pool instead of allocating it as an array. + * Can be in external SRAM too. */ +# define LV_MEM_ADR 0 + +/* Automatically defrag. on free. Defrag. means joining the adjacent free cells. */ +# define LV_MEM_AUTO_DEFRAG 1 +#else /*LV_MEM_CUSTOM*/ +# define LV_MEM_CUSTOM_INCLUDE <stdlib.h> /*Header for the dynamic memory function*/ +# define LV_MEM_CUSTOM_ALLOC malloc /*Wrapper to malloc*/ +# define LV_MEM_CUSTOM_FREE free /*Wrapper to free*/ +#endif /*LV_MEM_CUSTOM*/ + +/* Garbage Collector settings + * Used if lvgl is binded to higher level language and the memory is managed by that language */ +#define LV_ENABLE_GC 0 +#if LV_ENABLE_GC != 0 +# define LV_GC_INCLUDE "gc.h" /*Include Garbage Collector related things*/ +# define LV_MEM_CUSTOM_REALLOC your_realloc /*Wrapper to realloc*/ +# define LV_MEM_CUSTOM_GET_SIZE your_mem_get_size /*Wrapper to lv_mem_get_size*/ +#endif /* LV_ENABLE_GC */ + +/*======================= + Input device settings + *=======================*/ + +/* Input device default settings. + * 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 + +/* Drag threshold in pixels */ +#define LV_INDEV_DEF_DRAG_LIMIT 10 + +/* Drag throw slow-down in [%]. Greater value -> faster slow-down */ +#define LV_INDEV_DEF_DRAG_THROW 20 + +/* Long press time in milliseconds. + * Time to send `LV_EVENT_LONG_PRESSSED`) */ +#define LV_INDEV_DEF_LONG_PRESS_TIME 400 + +/* Repeated trigger period in long press [ms] + * Time between `LV_EVENT_LONG_PRESSED_REPEAT */ +#define LV_INDEV_DEF_LONG_PRESS_REP_TIME 100 + +/*================== + * Feature usage + *==================*/ + +/*1: Enable the Animations */ +#define LV_USE_ANIMATION 1 +#if LV_USE_ANIMATION + +/*Declare the type of the user data of animations (can be e.g. `void *`, `int`, `struct`)*/ +typedef void * lv_anim_user_data_t; + +#endif + +/* 1: Enable shadow drawing*/ +#define LV_USE_SHADOW 0 + +/* 1: Enable object groups (for keyboard/encoder navigation) */ +#define LV_USE_GROUP 0 +#if LV_USE_GROUP +typedef void * lv_group_user_data_t; +#endif /*LV_USE_GROUP*/ + +/* 1: Enable GPU interface*/ +#define LV_USE_GPU 0 + +/* 1: Enable file system (might be required for images */ +#define LV_USE_FILESYSTEM 0 +#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; +#endif + +/*1: Add a `user_data` to drivers and objects*/ +#define LV_USE_USER_DATA 1 + +/*======================== + * Image decoder and cache + *========================*/ + +/* 1: Enable indexed (palette) images */ +#define LV_IMG_CF_INDEXED 1 + +/* 1: Enable alpha indexed images */ +#define LV_IMG_CF_ALPHA 1 + +/* Default image cache size. Image caching keeps the images opened. + * If only the built-in image formats are used there is no real advantage of caching. + * (I.e. no new image decoder is added) + * 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 + +/*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; + +/*===================== + * Compiler settings + *====================*/ +/* Define a custom attribute to `lv_tick_inc` function */ +#define LV_ATTRIBUTE_TICK_INC + +/* Define a custom attribute to `lv_task_handler` function */ +#define LV_ATTRIBUTE_TASK_HANDLER + +/* With size optimization (-Os) the compiler might not align data to + * 4 or 8 byte boundary. This alignment will be explicitly applied where needed. + * E.g. __attribute__((aligned(4))) */ +#define LV_ATTRIBUTE_MEM_ALIGN + +/* Attribute to mark large constant arrays for example + * font's bitmaps */ +#define LV_ATTRIBUTE_LARGE_CONST + +/* Export integer constant to binding. + * This macro is used with constants in the form of LV_<CONST> that + * should also appear on lvgl binding API such as Micropython + * + * The default value just prevents a GCC warning. + */ +#define LV_EXPORT_CONST_INT(int_value) struct _silence_gcc_warning + +/*=================== + * HAL settings + *==================*/ + +/* 1: use a custom tick source. + * It removes the need to manually update the tick with `lv_tick_inc`) */ +#define LV_TICK_CUSTOM 0 +#if LV_TICK_CUSTOM == 1 +#define LV_TICK_CUSTOM_INCLUDE "something.h" /*Header for the sys time function*/ +#define LV_TICK_CUSTOM_SYS_TIME_EXPR (millis()) /*Expression evaluating to current systime in ms*/ +#endif /*LV_TICK_CUSTOM*/ + +typedef void * lv_disp_drv_user_data_t; /*Type of user data in the display driver*/ +typedef void * lv_indev_drv_user_data_t; /*Type of user data in the input device driver*/ + +/*================ + * Log settings + *===============*/ + +/*1: Enable the log module*/ +#define LV_USE_LOG 0 +#if LV_USE_LOG +/* How important log should be added: + * LV_LOG_LEVEL_TRACE A lot of logs to give detailed information + * LV_LOG_LEVEL_INFO Log important events + * LV_LOG_LEVEL_WARN Log if something unwanted happened but didn't cause a problem + * LV_LOG_LEVEL_ERROR Only critical issue, when the system may fail + * LV_LOG_LEVEL_NONE Do not log anything + */ +# define LV_LOG_LEVEL LV_LOG_LEVEL_WARN + +/* 1: Print the log with 'printf'; + * 0: user need to register a callback with `lv_log_register_print_cb`*/ +# define LV_LOG_PRINTF 0 +#endif /*LV_USE_LOG*/ + +/*================= + * Debug settings + *================*/ + +/* If Debug is enabled LittelvGL validates the parameters of the functions. + * If an invalid parameter is found an error log message is printed and + * the MCU halts at the error. (`LV_USE_LOG` should be enabled) + * If you are debugging the MCU you can pause + * the debugger to see exactly where the issue is. + * + * The behavior of asserts can be overwritten by redefining them here. + * E.g. #define LV_ASSERT_MEM(p) <my_assert_code> + */ +#define LV_USE_DEBUG 0 +#if LV_USE_DEBUG + +/*Check if the parameter is NULL. (Quite fast) */ +#define LV_USE_ASSERT_NULL 1 + +/*Checks is the memory is successfully allocated or no. (Quite fast)*/ +#define LV_USE_ASSERT_MEM 1 + +/* Check the strings. + * Search for NULL, very long strings, invalid characters, and unnatural repetitions. (Slow) + * If disabled `LV_USE_ASSERT_NULL` will be performed instead (if it's enabled) */ +#define LV_USE_ASSERT_STR 0 + +/* Check NULL, the object's type and existence (e.g. not deleted). (Quite slow) + * If disabled `LV_USE_ASSERT_NULL` will be performed instead (if it's enabled) */ +#define LV_USE_ASSERT_OBJ 0 + +/*Check if the styles are properly initialized. (Fast)*/ +#define LV_USE_ASSERT_STYLE 1 + +#endif /*LV_USE_DEBUG*/ + +/*================ + * THEME USAGE + *================*/ +#define LV_THEME_LIVE_UPDATE 0 /*1: Allow theme switching at run time. Uses 8..10 kB of RAM*/ + +#define LV_USE_THEME_TEMPL 0 /*Just for test*/ +#define LV_USE_THEME_DEFAULT 1 /*Built mainly from the built-in styles. Consumes very few RAM*/ +#define LV_USE_THEME_ALIEN 0 /*Dark futuristic theme*/ +#define LV_USE_THEME_NIGHT 1 /*Dark elegant theme*/ +#define LV_USE_THEME_MONO 0 /*Mono color theme for monochrome displays*/ +#define LV_USE_THEME_MATERIAL 0 /*Flat theme with bold colors and light shadows*/ +#define LV_USE_THEME_ZEN 0 /*Peaceful, mainly light theme */ +#define LV_USE_THEME_NEMO 0 /*Water-like theme based on the movie "Finding Nemo"*/ + +/*================== + * FONT USAGE + *===================*/ + +/* The built-in fonts contains the ASCII range and some Symbols with 4 bit-per-pixel. + * The symbols are available via `LV_SYMBOL_...` defines + * More info about fonts: https://docs.littlevgl.com/#Fonts + * To create a new font go to: https://littlevgl.com/ttf-font-to-c-array + */ + +/* Robot fonts with bpp = 4 + * https://fonts.google.com/specimen/Roboto */ +#define LV_FONT_ROBOTO_12 0 +#define LV_FONT_ROBOTO_16 0 +#define LV_FONT_ROBOTO_22 0 +#define LV_FONT_ROBOTO_28 0 + +/* Demonstrate special features */ +#define LV_FONT_ROBOTO_12_SUBPX 1 +#define LV_FONT_ROBOTO_28_COMPRESSED 1 /*bpp = 3*/ + +/*Pixel perfect monospace font + * http://pelulamu.net/unscii/ */ +#define LV_FONT_UNSCII_8 0 + +/* Optionally declare your custom fonts here. + * You can use these fonts as default font too + * and they will be available globally. E.g. + * #define LV_FONT_CUSTOM_DECLARE LV_FONT_DECLARE(my_font_1) \LV_SUBPX_BGR + * LV_FONT_DECLARE(my_font_2) + */ +#define LV_FONT_CUSTOM_DECLARE + +/*Always set a default font from the built-in fonts*/ +#define LV_FONT_DEFAULT NULL; // The default font is specified in the custom theme. + +/* Enable it if you have fonts with a lot of characters. + * The limit depends on the font size, font face and bpp + * but with > 10,000 characters if you see issues probably you need to enable it.*/ +#define LV_FONT_FMT_TXT_LARGE 0 + +/* Set the pixel order of the display. + * Important only if "subpx fonts" are used. + * With "normal" font it doesn't matter. + */ +#define LV_FONT_SUBPX_BGR 0 + +/*Declare the type of the user data of fonts (can be e.g. `void *`, `int`, `struct`)*/ +typedef void * lv_font_user_data_t; + +/*================= + * Text settings + *=================*/ + +/* Select a character encoding for strings. + * Your IDE or editor should have the same character encoding + * - LV_TXT_ENC_UTF8 + * - LV_TXT_ENC_ASCII + * */ +#define LV_TXT_ENC LV_TXT_ENC_UTF8 + + /*Can break (wrap) texts on these chars*/ +#define LV_TXT_BREAK_CHARS " ,.;:-_" + +/* If a word is at least this long, will break wherever "prettiest" + * To disable, set to a value <= 0 */ +#define LV_TXT_LINE_BREAK_LONG_LEN 12 + +/* Minimum number of characters in a long word to put on a line before a break. + * Depends on LV_TXT_LINE_BREAK_LONG_LEN. */ +#define LV_TXT_LINE_BREAK_LONG_PRE_MIN_LEN 3 + +/* Minimum number of characters in a long word to put on a line after a break. + * Depends on LV_TXT_LINE_BREAK_LONG_LEN. */ +#define LV_TXT_LINE_BREAK_LONG_POST_MIN_LEN 3 + +/* The control character to use for signalling text recoloring. */ +#define LV_TXT_COLOR_CMD "#" + +/* Support bidirectional texts. + * Allows mixing Left-to-Right and Right-to-Left texts. + * The direction will be processed according to the Unicode Bidirectioanl Algorithm: + * https://www.w3.org/International/articles/inline-bidi-markup/uba-basics*/ +#define LV_USE_BIDI 0 +#if LV_USE_BIDI +/* Set the default direction. Supported values: + * `LV_BIDI_DIR_LTR` Left-to-Right + * `LV_BIDI_DIR_RTL` Right-to-Left + * `LV_BIDI_DIR_AUTO` detect texts base direction */ +#define LV_BIDI_BASE_DIR_DEF LV_BIDI_DIR_AUTO +#endif + +/*Change the built in (v)snprintf functions*/ +#define LV_SPRINTF_CUSTOM 0 +#if LV_SPRINTF_CUSTOM +# define LV_SPRINTF_INCLUDE <stdio.h> +# define lv_snprintf snprintf +# define lv_vsnprintf vsnprintf +#endif /*LV_SPRINTF_CUSTOM*/ + +/*=================== + * LV_OBJ SETTINGS + *==================*/ + +/*Declare the type of the user data of object (can be e.g. `void *`, `int`, `struct`)*/ +typedef void * lv_obj_user_data_t; + +/*1: enable `lv_obj_realaign()` based on `lv_obj_align()` parameters*/ +#define LV_USE_OBJ_REALIGN 1 + +/* Enable to make the object clickable on a larger area. + * LV_EXT_CLICK_AREA_OFF or 0: Disable this feature + * LV_EXT_CLICK_AREA_TINY: The extra area can be adjusted horizontally and vertically (0..255 px) + * LV_EXT_CLICK_AREA_FULL: The extra area can be adjusted in all 4 directions (-32k..+32k px) + */ +#define LV_USE_EXT_CLICK_AREA LV_EXT_CLICK_AREA_OFF + +/*================== + * LV OBJ X USAGE + *================*/ +/* + * Documentation of the object types: https://docs.littlevgl.com/#Object-types + */ + +/*Arc (dependencies: -)*/ +#define LV_USE_ARC 1 + +/*Bar (dependencies: -)*/ +#define LV_USE_BAR 1 + +/*Button (dependencies: lv_cont*/ +#define LV_USE_BTN 1 +#if LV_USE_BTN != 0 +/*Enable button-state animations - draw a circle on click (dependencies: LV_USE_ANIMATION)*/ +# define LV_BTN_INK_EFFECT 0 +#endif + +/*Button matrix (dependencies: -)*/ +#define LV_USE_BTNM 1 + +/*Calendar (dependencies: -)*/ +#define LV_USE_CALENDAR 1 + +/*Canvas (dependencies: lv_img)*/ +#define LV_USE_CANVAS 1 + +/*Check box (dependencies: lv_btn, lv_label)*/ +#define LV_USE_CB 1 + +/*Chart (dependencies: -)*/ +#define LV_USE_CHART 1 +#if LV_USE_CHART +# define LV_CHART_AXIS_TICK_LABEL_MAX_LEN 20 +#endif + +/*Container (dependencies: -*/ +#define LV_USE_CONT 1 + +/*Color picker (dependencies: -*/ +#define LV_USE_CPICKER 1 + +/*Drop down list (dependencies: lv_page, lv_label, lv_symbol_def.h)*/ +#define LV_USE_DDLIST 1 +#if LV_USE_DDLIST != 0 +/*Open and close default animation time [ms] (0: no animation)*/ +# define LV_DDLIST_DEF_ANIM_TIME 200 +#endif + +/*Gauge (dependencies:lv_bar, lv_lmeter)*/ +#define LV_USE_GAUGE 1 + +/*Image (dependencies: lv_label*/ +#define LV_USE_IMG 1 + +/*Image Button (dependencies: lv_btn*/ +#define LV_USE_IMGBTN 1 +#if LV_USE_IMGBTN +/*1: The imgbtn requires left, mid and right parts and the width can be set freely*/ +# define LV_IMGBTN_TILED 0 +#endif + +/*Keyboard (dependencies: lv_btnm)*/ +#define LV_USE_KB 1 + +/*Label (dependencies: -*/ +#define LV_USE_LABEL 1 +#if LV_USE_LABEL != 0 +/*Hor, or ver. scroll speed [px/sec] in 'LV_LABEL_LONG_ROLL/ROLL_CIRC' mode*/ +# define LV_LABEL_DEF_SCROLL_SPEED 25 + +/* Waiting period at beginning/end of animation cycle */ +# define LV_LABEL_WAIT_CHAR_COUNT 3 + +/*Enable selecting text of the label */ +# define LV_LABEL_TEXT_SEL 0 + +/*Store extra some info in labels (12 bytes) to speed up drawing of very long texts*/ +# define LV_LABEL_LONG_TXT_HINT 0 +#endif + +/*LED (dependencies: -)*/ +#define LV_USE_LED 1 + +/*Line (dependencies: -*/ +#define LV_USE_LINE 1 + +/*List (dependencies: lv_page, lv_btn, lv_label, (lv_img optionally for icons ))*/ +#define LV_USE_LIST 1 +#if LV_USE_LIST != 0 +/*Default animation time of focusing to a list element [ms] (0: no animation) */ +# define LV_LIST_DEF_ANIM_TIME 100 +#endif + +/*Line meter (dependencies: *;)*/ +#define LV_USE_LMETER 1 + +/*Message box (dependencies: lv_rect, lv_btnm, lv_label)*/ +#define LV_USE_MBOX 1 + +/*Page (dependencies: lv_cont)*/ +#define LV_USE_PAGE 1 +#if LV_USE_PAGE != 0 +/*Focus default animation time [ms] (0: no animation)*/ +# define LV_PAGE_DEF_ANIM_TIME 400 +#endif + +/*Preload (dependencies: lv_arc, lv_anim)*/ +#define LV_USE_PRELOAD 0 +#if LV_USE_PRELOAD != 0 +# define LV_PRELOAD_DEF_ARC_LENGTH 60 /*[deg]*/ +# define LV_PRELOAD_DEF_SPIN_TIME 1000 /*[ms]*/ +# define LV_PRELOAD_DEF_ANIM LV_PRELOAD_TYPE_SPINNING_ARC +#endif + +/*Roller (dependencies: lv_ddlist)*/ +#define LV_USE_ROLLER 1 +#if LV_USE_ROLLER != 0 +/*Focus animation time [ms] (0: no animation)*/ +# define LV_ROLLER_DEF_ANIM_TIME 200 + +/*Number of extra "pages" when the roller is infinite*/ +# define LV_ROLLER_INF_PAGES 7 +#endif + +/*Slider (dependencies: lv_bar)*/ +#define LV_USE_SLIDER 1 + +/*Spinbox (dependencies: lv_ta)*/ +#define LV_USE_SPINBOX 1 + +/*Switch (dependencies: lv_slider)*/ +#define LV_USE_SW 1 + +/*Text area (dependencies: lv_label, lv_page)*/ +#define LV_USE_TA 1 +#if LV_USE_TA != 0 +# define LV_TA_DEF_CURSOR_BLINK_TIME 400 /*ms*/ +# define LV_TA_DEF_PWD_SHOW_TIME 1500 /*ms*/ +#endif + +/*Table (dependencies: lv_label)*/ +#define LV_USE_TABLE 1 +#if LV_USE_TABLE +# define LV_TABLE_COL_MAX 12 +#endif + +/*Tab (dependencies: lv_page, lv_btnm)*/ +#define LV_USE_TABVIEW 1 +# if LV_USE_TABVIEW != 0 +/*Time of slide animation [ms] (0: no animation)*/ +# define LV_TABVIEW_DEF_ANIM_TIME 300 +#endif + +/*Tileview (dependencies: lv_page) */ +#define LV_USE_TILEVIEW 1 +#if LV_USE_TILEVIEW +/*Time of slide animation [ms] (0: no animation)*/ +# define LV_TILEVIEW_DEF_ANIM_TIME 300 +#endif + +/*Window (dependencies: lv_cont, lv_btn, lv_label, lv_img, lv_page)*/ +#define LV_USE_WIN 1 + +/*================== + * Non-user section + *==================*/ + +#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS) /* Disable warnings for Visual Studio*/ +# define _CRT_SECURE_NO_WARNINGS +#endif + +/*--END OF LV_CONF_H--*/ + +/*Be sure every define has a default value*/ +#include "lvgl/src/lv_conf_checker.h" + +#endif /*LV_CONF_H*/ + +#endif /*End of "Content enable"*/ diff --git a/src/libs/lvgl b/src/libs/lvgl new file mode 160000 +Subproject ee95d1c9cf74899585f9165458911f2d54ca750 diff --git a/src/main.cpp b/src/main.cpp index 13dddca6..3b08efdc 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,24 +1,21 @@ #include <FreeRTOS.h> #include <task.h> -#include <libraries/bsp/bsp.h> #include <legacy/nrf_drv_clock.h> #include <libraries/timer/app_timer.h> #include <libraries/gpiote/app_gpiote.h> #include <DisplayApp/DisplayApp.h> #include <softdevice/common/nrf_sdh.h> -#include <softdevice/common/nrf_sdh_freertos.h> #include <hal/nrf_rtc.h> #include <timers.h> -#include <libraries/log/nrf_log.h> #include <ble/ble_services/ble_cts_c/ble_cts_c.h> #include <Components/DateTime/DateTimeController.h> #include "BLE/BleManager.h" #include "Components/Battery/BatteryController.h" #include "Components/Ble/BleController.h" -#include "../drivers/Cst816s.h" #include <drivers/St7789.h> #include <drivers/SpiMaster.h> -#include <Components/Gfx/Gfx.h> +#include <DisplayApp/LittleVgl.h> +#include <SystemTask/SystemTask.h> #if NRF_LOG_ENABLED #include "Logging/NrfLogger.h" @@ -28,39 +25,40 @@ Pinetime::Logging::NrfLogger logger; Pinetime::Logging::DummyLogger logger; #endif -std::unique_ptr<Pinetime::Drivers::SpiMaster> spi; -std::unique_ptr<Pinetime::Drivers::St7789> lcd; -std::unique_ptr<Pinetime::Components::Gfx> gfx; -std::unique_ptr<Pinetime::Drivers::Cst816S> touchPanel; - static constexpr uint8_t pinSpiSck = 2; static constexpr uint8_t pinSpiMosi = 3; static constexpr uint8_t pinSpiMiso = 4; static constexpr uint8_t pinSpiCsn = 25; static constexpr uint8_t pinLcdDataCommand = 18; +Pinetime::Drivers::SpiMaster spi{Pinetime::Drivers::SpiMaster::SpiModule::SPI0, { + Pinetime::Drivers::SpiMaster::BitOrder::Msb_Lsb, + Pinetime::Drivers::SpiMaster::Modes::Mode3, + Pinetime::Drivers::SpiMaster::Frequencies::Freq8Mhz, + pinSpiSck, + pinSpiMosi, + pinSpiMiso, + pinSpiCsn + } +}; +Pinetime::Drivers::St7789 lcd {spi, pinLcdDataCommand}; +Pinetime::Drivers::Cst816S touchPanel {}; +Pinetime::Components::LittleVgl lvgl {lcd, touchPanel}; + -std::unique_ptr<Pinetime::Applications::DisplayApp> displayApp; -TaskHandle_t systemThread; -bool isSleeping = false; TimerHandle_t debounceTimer; Pinetime::Controllers::Battery batteryController; Pinetime::Controllers::Ble bleController; Pinetime::Controllers::DateTime dateTimeController; - - void ble_manager_set_ble_connection_callback(void (*connection)()); void ble_manager_set_ble_disconnection_callback(void (*disconnection)()); -static constexpr uint8_t pinButton = 13; static constexpr uint8_t pinTouchIrq = 28; -QueueHandle_t systemTaksMsgQueue; -enum class SystemTaskMessages {GoToSleep, GoToRunning}; -void SystemTask_PushMessage(SystemTaskMessages message); +std::unique_ptr<Pinetime::System::SystemTask> systemTask; void nrfx_gpiote_evt_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action) { if(pin == pinTouchIrq) { - displayApp->PushMessage(Pinetime::Applications::DisplayApp::Messages::TouchEvent); - if(!isSleeping) return; + systemTask->OnTouchEvent(); + return ; } BaseType_t xHigherPriorityTaskWoken = pdFALSE; @@ -68,117 +66,23 @@ void nrfx_gpiote_evt_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action portYIELD_FROM_ISR(xHigherPriorityTaskWoken); } -void DebounceTimerCallback(TimerHandle_t xTimer) { - xTimerStop(xTimer, 0); - if(isSleeping) { - SystemTask_PushMessage(SystemTaskMessages::GoToRunning); - displayApp->PushMessage(Pinetime::Applications::DisplayApp::Messages::GoToRunning); - isSleeping = false; - batteryController.Update(); - displayApp->PushMessage(Pinetime::Applications::DisplayApp::Messages::UpdateBatteryLevel); - } - else { - SystemTask_PushMessage(SystemTaskMessages::GoToSleep); - displayApp->PushMessage(Pinetime::Applications::DisplayApp::Messages::GoToSleep); - isSleeping = true; - } -} - -void SystemTask_PushMessage(SystemTaskMessages message) { - BaseType_t xHigherPriorityTaskWoken; - xHigherPriorityTaskWoken = pdFALSE; - xQueueSendFromISR(systemTaksMsgQueue, &message, &xHigherPriorityTaskWoken); - if (xHigherPriorityTaskWoken) { - /* Actual macro used here is port specific. */ - // TODO : should I do something here? +extern "C" { + void vApplicationIdleHook(void) { + lv_tick_inc(1); } } -// TODO The whole SystemTask should go in its own class -// BUT... it has to work with pure C callback (nrfx_gpiote_evt_handler) and i've still not found -// a good design for that (the callback does not allow to pass a pointer to an instance...) -void SystemTask(void *) { - APP_GPIOTE_INIT(2); - bool erase_bonds=false; - nrf_sdh_freertos_init(ble_manager_start_advertising, &erase_bonds); - - spi.reset(new Pinetime::Drivers::SpiMaster {Pinetime::Drivers::SpiMaster::SpiModule::SPI0, { - Pinetime::Drivers::SpiMaster::BitOrder::Msb_Lsb, - Pinetime::Drivers::SpiMaster::Modes::Mode3, - Pinetime::Drivers::SpiMaster::Frequencies::Freq8Mhz, - pinSpiSck, - pinSpiMosi, - pinSpiMiso, - pinSpiCsn - }}); - - lcd.reset(new Pinetime::Drivers::St7789(*spi, pinLcdDataCommand)); - gfx.reset(new Pinetime::Components::Gfx(*lcd)); - touchPanel.reset(new Pinetime::Drivers::Cst816S()); - - spi->Init(); - lcd->Init(); - touchPanel->Init(); - batteryController.Init(); - - displayApp.reset(new Pinetime::Applications::DisplayApp(*lcd, *gfx, *touchPanel, batteryController, bleController, dateTimeController)); - displayApp->Start(); - - batteryController.Update(); - displayApp->PushMessage(Pinetime::Applications::DisplayApp::Messages::UpdateBatteryLevel); - - debounceTimer = xTimerCreate ("debounceTimer", 200, pdFALSE, (void *) 0, DebounceTimerCallback); - - nrf_gpio_cfg_sense_input(pinButton, (nrf_gpio_pin_pull_t)GPIO_PIN_CNF_PULL_Pulldown, (nrf_gpio_pin_sense_t)GPIO_PIN_CNF_SENSE_High); - nrf_gpio_cfg_output(15); - nrf_gpio_pin_set(15); - - nrfx_gpiote_in_config_t pinConfig; - pinConfig.skip_gpio_setup = true; - pinConfig.hi_accuracy = false; - pinConfig.is_watcher = false; - pinConfig.sense = (nrf_gpiote_polarity_t)NRF_GPIOTE_POLARITY_HITOLO; - pinConfig.pull = (nrf_gpio_pin_pull_t)GPIO_PIN_CNF_PULL_Pulldown; - - nrfx_gpiote_in_init(pinButton, &pinConfig, nrfx_gpiote_evt_handler); - - nrf_gpio_cfg_sense_input(pinTouchIrq, (nrf_gpio_pin_pull_t)GPIO_PIN_CNF_PULL_Pullup, (nrf_gpio_pin_sense_t)GPIO_PIN_CNF_SENSE_Low); - - pinConfig.skip_gpio_setup = true; - pinConfig.hi_accuracy = false; - pinConfig.is_watcher = false; - pinConfig.sense = (nrf_gpiote_polarity_t)NRF_GPIOTE_POLARITY_HITOLO; - pinConfig.pull = (nrf_gpio_pin_pull_t)GPIO_PIN_CNF_PULL_Pullup; - - nrfx_gpiote_in_init(pinTouchIrq, &pinConfig, nrfx_gpiote_evt_handler); - - systemTaksMsgQueue = xQueueCreate(10, 1); - bool systemTaskSleeping = false; - - while(true) { - uint8_t msg; - - if (xQueueReceive(systemTaksMsgQueue, &msg, systemTaskSleeping?3600000 : 1000)) { - SystemTaskMessages message = static_cast<SystemTaskMessages >(msg); - switch(message) { - case SystemTaskMessages::GoToRunning: systemTaskSleeping = false; break; - case SystemTaskMessages::GoToSleep: systemTaskSleeping = true; break; - default: break; - } - } - uint32_t systick_counter = nrf_rtc_counter_get(portNRF_RTC_REG); - dateTimeController.UpdateTime(systick_counter); - } +void DebounceTimerCallback(TimerHandle_t xTimer) { + xTimerStop(xTimer, 0); + systemTask->OnButtonPushed(); } void OnBleConnection() { bleController.Connect(); - displayApp->PushMessage(Pinetime::Applications::DisplayApp::Messages::UpdateBleConnection); } void OnBleDisconnection() { bleController.Disconnect(); - displayApp->PushMessage(Pinetime::Applications::DisplayApp::Messages::UpdateBleConnection); } void OnNewTime(current_time_char_t* currentTime) { @@ -197,24 +101,44 @@ void OnNewTime(current_time_char_t* currentTime) { void SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQHandler(void) { if(((NRF_SPIM0->INTENSET & (1<<6)) != 0) && NRF_SPIM0->EVENTS_END == 1) { NRF_SPIM0->EVENTS_END = 0; - spi->OnEndEvent(*gfx); + spi.OnEndEvent(); } if(((NRF_SPIM0->INTENSET & (1<<19)) != 0) && NRF_SPIM0->EVENTS_STARTED == 1) { NRF_SPIM0->EVENTS_STARTED = 0; - spi->OnStartedEvent(*gfx); + spi.OnStartedEvent(); } if(((NRF_SPIM0->INTENSET & (1<<1)) != 0) && NRF_SPIM0->EVENTS_STOPPED == 1) { NRF_SPIM0->EVENTS_STOPPED = 0; } } + int main(void) { logger.Init(); + + nrf_gpio_cfg_output(27); + nrf_gpio_pin_clear(27); + nrf_gpio_cfg_output(29); + nrf_gpio_pin_clear(29); + + nrf_gpio_cfg_output(20); + nrf_gpio_pin_clear(20); + + nrf_gpio_cfg_output(17); + nrf_gpio_pin_clear(17); + + nrf_gpio_cfg_output(11); + nrf_gpio_pin_clear(11); + + + nrf_drv_clock_init(); - if (pdPASS != xTaskCreate(SystemTask, "MAIN", 256, nullptr, 0, &systemThread)) - APP_ERROR_HANDLER(NRF_ERROR_NO_MEM); + debounceTimer = xTimerCreate ("debounceTimer", 200, pdFALSE, (void *) 0, DebounceTimerCallback); + + systemTask.reset(new Pinetime::System::SystemTask(spi, lcd, touchPanel, lvgl, batteryController, bleController, dateTimeController)); + systemTask->Start(); ble_manager_init(); ble_manager_set_new_time_callback(OnNewTime); diff --git a/src/main.h b/src/main.h new file mode 100644 index 00000000..b0a8a57e --- /dev/null +++ b/src/main.h @@ -0,0 +1,7 @@ +#pragma once + +#include <FreeRTOS.h> +#include <timers.h> + +void nrfx_gpiote_evt_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action); +void DebounceTimerCallback(TimerHandle_t xTimer);
\ No newline at end of file |