From 2c9c07ccf5ae8fed672d029b6f6c29ca9e2bd144 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Milants?= Date: Mon, 23 Oct 2023 20:12:34 +0200 Subject: [PATCH 1/5] Application selection at build time A list of "user applications" is built at compile time. It contains all the info needed to create the application at runtime (ptr to a create() function) and to display the app in the application menu. All applications declare a TypeTrait with these information. When a new app must be loaded, DisplayApp first check if this app is a System app (in which case it creates it like it did before). If it's not a System app, it looks for the app in the list of User applications and creates it if it found it. Those changes allow to more easily add new app and to select which app must be built into the firmware. Switch to C++20 (and fix a few issues in SpiMaster.cpp and Watchdog.cpp. --- CMakeLists.txt | 2 +- src/CMakeLists.txt | 1 - src/displayapp/Apps.h | 29 +++++- src/displayapp/Controllers.h | 51 ++++++++++ src/displayapp/DisplayApp.cpp | 102 ++++++++++---------- src/displayapp/DisplayApp.h | 5 + src/displayapp/UserApps.h | 36 +++++++ src/displayapp/screens/Alarm.cpp | 4 + src/displayapp/screens/Alarm.h | 26 +++-- src/displayapp/screens/ApplicationList.cpp | 24 +++-- src/displayapp/screens/ApplicationList.h | 38 ++------ src/displayapp/screens/Clock.h | 11 ++- src/displayapp/screens/HeartRate.h | 9 ++ src/displayapp/screens/InfiniPaint.h | 11 +++ src/displayapp/screens/Metronome.h | 9 ++ src/displayapp/screens/Motion.h | 10 ++ src/displayapp/screens/Music.h | 11 +++ src/displayapp/screens/Navigation.h | 11 +++ src/displayapp/screens/Paddle.h | 11 +++ src/displayapp/screens/Steps.h | 11 +++ src/displayapp/screens/StopWatch.h | 105 ++++++++++++--------- src/displayapp/screens/Tile.cpp | 1 - src/displayapp/screens/Timer.cpp | 2 +- src/displayapp/screens/Timer.h | 76 ++++++++------- src/displayapp/screens/Twos.h | 9 +- src/displayapp/screens/Weather.h | 13 ++- src/drivers/SpiMaster.cpp | 12 +-- src/drivers/Watchdog.cpp | 2 +- src/systemtask/SystemTask.cpp | 3 + 29 files changed, 445 insertions(+), 190 deletions(-) create mode 100644 src/displayapp/Controllers.h create mode 100644 src/displayapp/UserApps.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 83c6e98db8..41989489bc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,7 @@ set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose Debug or Release") project(pinetime VERSION 1.13.0 LANGUAGES C CXX ASM) set(CMAKE_C_STANDARD 99) -set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_STANDARD 20) # set(CMAKE_GENERATOR "Unix Makefiles") set(CMAKE_C_EXTENSIONS OFF) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8e8e96863b..dc718bab13 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -394,7 +394,6 @@ list(APPEND SOURCE_FILES displayapp/screens/Notifications.cpp displayapp/screens/Twos.cpp displayapp/screens/HeartRate.cpp - displayapp/screens/Motion.cpp displayapp/screens/FlashLight.cpp displayapp/screens/List.cpp displayapp/screens/CheckboxList.cpp diff --git a/src/displayapp/Apps.h b/src/displayapp/Apps.h index f253bc0387..d96e6ea721 100644 --- a/src/displayapp/Apps.h +++ b/src/displayapp/Apps.h @@ -1,5 +1,5 @@ #pragma once - +#include namespace Pinetime { namespace Applications { enum class Apps { @@ -37,7 +37,32 @@ namespace Pinetime { SettingChimes, SettingShakeThreshold, SettingBluetooth, - Error + Error, + Weather + }; + template + struct AppTraits {}; + + template + struct TypeList { + static constexpr size_t Count = sizeof...(As); }; + + using UserAppTypes = TypeList; } } diff --git a/src/displayapp/Controllers.h b/src/displayapp/Controllers.h new file mode 100644 index 0000000000..cef989867e --- /dev/null +++ b/src/displayapp/Controllers.h @@ -0,0 +1,51 @@ +#pragma once +namespace Pinetime { + namespace Applications { + class DisplayApp; + } + namespace Components { + class LittleVgl; + } + namespace Controllers { + class Battery; + class Ble; + class DateTime; + class NotificationManager; + class HeartRateController; + class Settings; + class MotorController; + class MotionController; + class AlarmController; + class BrightnessController; + class WeatherService; + class FS; + class Timer; + class MusicService; + class NavigationService; + } + namespace System { + class SystemTask; + } + namespace Applications { + struct AppControllers { + const Pinetime::Controllers::Battery& batteryController; + const Pinetime::Controllers::Ble& bleController; + Pinetime::Controllers::DateTime& dateTimeController; + Pinetime::Controllers::NotificationManager& notificationManager; + Pinetime::Controllers::HeartRateController& heartRateController; + Pinetime::Controllers::Settings& settingsController; + Pinetime::Controllers::MotorController& motorController; + Pinetime::Controllers::MotionController& motionController; + Pinetime::Controllers::AlarmController& alarmController; + Pinetime::Controllers::BrightnessController& brightnessController; + Pinetime::Controllers::WeatherService* weatherController; + Pinetime::Controllers::FS& filesystem; + Pinetime::Controllers::Timer& timer; + Pinetime::System::SystemTask* systemTask; + Pinetime::Applications::DisplayApp* displayApp; + Pinetime::Components::LittleVgl& lvgl; + Pinetime::Controllers::MusicService* musicService; + Pinetime::Controllers::NavigationService* navigationService; + }; + } +} \ No newline at end of file diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index 682ea12cb3..a195361ddb 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -50,6 +50,7 @@ #include "displayapp/screens/settings/SettingBluetooth.h" #include "libs/lv_conf.h" +#include "UserApps.h" using namespace Pinetime::Applications; using namespace Pinetime::Applications::Display; @@ -96,7 +97,12 @@ DisplayApp::DisplayApp(Drivers::St7789& lcd, touchHandler {touchHandler}, filesystem {filesystem}, lvgl {lcd, filesystem}, - timer(this, TimerCallback) { + timer(this, TimerCallback), + controllers{ + batteryController, bleController, dateTimeController, notificationManager, heartRateController, + settingsController, motorController, motionController, alarmController, brightnessController, + nullptr, filesystem, timer, nullptr, this, lvgl, nullptr, nullptr} + { } void DisplayApp::Start(System::BootErrors error) { @@ -402,14 +408,21 @@ void DisplayApp::LoadScreen(Apps app, DisplayApp::FullRefreshDirections directio SetFullRefresh(direction); switch (app) { - case Apps::Launcher: - currentScreen = - std::make_unique(this, settingsController, batteryController, bleController, dateTimeController, filesystem); - break; - case Apps::Motion: - // currentScreen = std::make_unique(motionController); - // break; - case Apps::None: + case Apps::Launcher: { + std::array apps; + int i = 0; + for (const auto& userApp : userApps) { + apps[i++] = Screens::Tile::Applications {userApp.icon, userApp.app, true}; + } + currentScreen = std::make_unique(this, + settingsController, + batteryController, + bleController, + dateTimeController, + filesystem, + std::move(apps)); + } + break; case Apps::Clock: currentScreen = std::make_unique(dateTimeController, batteryController, @@ -421,7 +434,6 @@ void DisplayApp::LoadScreen(Apps app, DisplayApp::FullRefreshDirections directio systemTask->nimble().weather(), filesystem); break; - case Apps::Error: currentScreen = std::make_unique(bootError); break; @@ -453,14 +465,6 @@ void DisplayApp::LoadScreen(Apps app, DisplayApp::FullRefreshDirections directio *systemTask, Screens::Notifications::Modes::Preview); break; - case Apps::Timer: - currentScreen = std::make_unique(timer); - break; - case Apps::Alarm: - currentScreen = std::make_unique(alarmController, settingsController.GetClockType(), *systemTask, motorController); - break; - - // Settings case Apps::QuickSettings: currentScreen = std::make_unique(this, batteryController, @@ -516,38 +520,25 @@ void DisplayApp::LoadScreen(Apps app, DisplayApp::FullRefreshDirections directio case Apps::FlashLight: currentScreen = std::make_unique(*systemTask, brightnessController); break; - case Apps::StopWatch: - currentScreen = std::make_unique(*systemTask); - break; - case Apps::Twos: - currentScreen = std::make_unique(); - break; - case Apps::Paint: - currentScreen = std::make_unique(lvgl, motorController); - break; - case Apps::Paddle: - currentScreen = std::make_unique(lvgl); - break; - case Apps::Music: - currentScreen = std::make_unique(systemTask->nimble().music()); - break; - case Apps::Navigation: - currentScreen = std::make_unique(systemTask->nimble().navigation()); - break; - case Apps::HeartRate: - currentScreen = std::make_unique(heartRateController, *systemTask); - break; - case Apps::Metronome: - currentScreen = std::make_unique(motorController, *systemTask); - break; - /* Weather debug app - case Apps::Weather: - currentScreen = std::make_unique(this, systemTask->nimble().weather()); - break; - */ - case Apps::Steps: - currentScreen = std::make_unique(motionController, settingsController); + default: { + const auto* d = std::find_if(userApps.begin(), userApps.end(), [app](const AppDescription& appDescription) { + return appDescription.app == app; + }); + if (d != userApps.end()) + currentScreen.reset(d->create(controllers)); + else { + currentScreen = std::make_unique(dateTimeController, + batteryController, + bleController, + notificationManager, + settingsController, + heartRateController, + motionController, + systemTask->nimble().weather(), + filesystem); + } break; + } } currentApp = app; } @@ -605,6 +596,19 @@ void DisplayApp::PushMessageToSystemTask(Pinetime::System::Messages message) { void DisplayApp::Register(Pinetime::System::SystemTask* systemTask) { this->systemTask = systemTask; + this->controllers.systemTask = systemTask; +} + +void DisplayApp::Register(Pinetime::Controllers::WeatherService* weatherService) { + this->controllers.weatherController = weatherService; +} + +void DisplayApp::Register(Pinetime::Controllers::MusicService* musicService) { + this->controllers.musicService = musicService; +} + +void DisplayApp::Register(Pinetime::Controllers::NavigationService* NavigationService) { + this->controllers.navigationService = NavigationService; } void DisplayApp::ApplyBrightness() { diff --git a/src/displayapp/DisplayApp.h b/src/displayapp/DisplayApp.h index f537651dbf..7dbac850aa 100644 --- a/src/displayapp/DisplayApp.h +++ b/src/displayapp/DisplayApp.h @@ -20,6 +20,7 @@ #include "BootErrors.h" #include "utility/StaticStack.h" +#include "displayapp/Controllers.h" namespace Pinetime { @@ -73,6 +74,9 @@ namespace Pinetime { void SetFullRefresh(FullRefreshDirections direction); void Register(Pinetime::System::SystemTask* systemTask); + void Register(Pinetime::Controllers::WeatherService* weatherService); + void Register(Pinetime::Controllers::MusicService* musicService); + void Register(Pinetime::Controllers::NavigationService* NavigationService); private: Pinetime::Drivers::St7789& lcd; @@ -96,6 +100,7 @@ namespace Pinetime { Pinetime::Components::LittleVgl lvgl; Pinetime::Controllers::Timer timer; + AppControllers controllers; TaskHandle_t taskHandle; States state = States::Running; diff --git a/src/displayapp/UserApps.h b/src/displayapp/UserApps.h new file mode 100644 index 0000000000..d0165cf9de --- /dev/null +++ b/src/displayapp/UserApps.h @@ -0,0 +1,36 @@ +#pragma once +#include "Apps.h" +#include "Controllers.h" + +#include "displayapp/screens/Alarm.h" +#include "displayapp/screens/Timer.h" +#include "displayapp/screens/Twos.h" +#include "displayapp/screens/Tile.h" +#include "displayapp/screens/ApplicationList.h" +#include "displayapp/screens/Clock.h" + +namespace Pinetime { + namespace Applications { + namespace Screens { + class Screen; + } + + struct AppDescription { + Apps app; + const char* icon; + Screens::Screen* (*create)(AppControllers& controllers); + }; + + template + consteval AppDescription CreateAppDescription() { + return {AppTraits::app, AppTraits::icon, &AppTraits::Create}; + } + + template typename T, Apps ...ts> + consteval std::array CreateAppDescriptions(T) { + return {CreateAppDescription()...}; + } + + constexpr auto userApps = CreateAppDescriptions(UserAppTypes {}); + } +} diff --git a/src/displayapp/screens/Alarm.cpp b/src/displayapp/screens/Alarm.cpp index 4e6ce79747..cbc702f312 100644 --- a/src/displayapp/screens/Alarm.cpp +++ b/src/displayapp/screens/Alarm.cpp @@ -19,6 +19,10 @@ #include "displayapp/screens/Screen.h" #include "displayapp/screens/Symbols.h" #include "displayapp/InfiniTimeTheme.h" +#include "components/settings/Settings.h" +#include "components/alarm/AlarmController.h" +#include "components/motor/MotorController.h" +#include "systemtask/SystemTask.h" using namespace Pinetime::Applications::Screens; using Pinetime::Controllers::AlarmController; diff --git a/src/displayapp/screens/Alarm.h b/src/displayapp/screens/Alarm.h index 911773662a..efa38eb74f 100644 --- a/src/displayapp/screens/Alarm.h +++ b/src/displayapp/screens/Alarm.h @@ -17,21 +17,22 @@ */ #pragma once +#include "displayapp/Apps.h" +#include "components/settings/Settings.h" #include "displayapp/screens/Screen.h" -#include "systemtask/SystemTask.h" -#include "displayapp/LittleVgl.h" -#include "components/alarm/AlarmController.h" #include "displayapp/widgets/Counter.h" +#include "displayapp/Controllers.h" +#include "Symbols.h" namespace Pinetime { namespace Applications { namespace Screens { class Alarm : public Screen { public: - Alarm(Controllers::AlarmController& alarmController, - Controllers::Settings::ClockType clockType, - System::SystemTask& systemTask, - Controllers::MotorController& motorController); + explicit Alarm(Controllers::AlarmController& alarmController, + Controllers::Settings::ClockType clockType, + System::SystemTask& systemTask, + Controllers::MotorController& motorController); ~Alarm() override; void SetAlerting(); void OnButtonEvent(lv_obj_t* obj, lv_event_t event); @@ -63,6 +64,15 @@ namespace Pinetime { Widgets::Counter hourCounter = Widgets::Counter(0, 23, jetbrains_mono_76); Widgets::Counter minuteCounter = Widgets::Counter(0, 59, jetbrains_mono_76); }; + } + template<> + struct AppTraits { + static constexpr Apps app = Apps::Alarm; + static constexpr const char* icon = Screens::Symbols::clock; + static Screens::Screen *Create(AppControllers& controllers) { return new Screens::Alarm(controllers.alarmController, + controllers.settingsController.GetClockType(), + *controllers.systemTask, + controllers.motorController); }; }; - }; + } } diff --git a/src/displayapp/screens/ApplicationList.cpp b/src/displayapp/screens/ApplicationList.cpp index 6014cf53e0..e5e26098d8 100644 --- a/src/displayapp/screens/ApplicationList.cpp +++ b/src/displayapp/screens/ApplicationList.cpp @@ -1,8 +1,9 @@ #include "displayapp/screens/ApplicationList.h" +#include "displayapp/screens/Tile.h" #include #include -#include "displayapp/Apps.h" -#include "displayapp/DisplayApp.h" +#include +#include "components/settings/Settings.h" using namespace Pinetime::Applications::Screens; @@ -16,18 +17,20 @@ auto ApplicationList::CreateScreenList() const { return screens; } -ApplicationList::ApplicationList(Pinetime::Applications::DisplayApp* app, +ApplicationList::ApplicationList(DisplayApp* app, Pinetime::Controllers::Settings& settingsController, const Pinetime::Controllers::Battery& batteryController, const Pinetime::Controllers::Ble& bleController, Controllers::DateTime& dateTimeController, - Pinetime::Controllers::FS& filesystem) + Pinetime::Controllers::FS& filesystem, + std::array&& apps) : app {app}, settingsController {settingsController}, batteryController {batteryController}, bleController {bleController}, dateTimeController {dateTimeController}, filesystem{filesystem}, + apps{std::move(apps)}, screens {app, settingsController.GetAppMenu(), CreateScreenList(), Screens::ScreenListModes::UpDown} { } @@ -40,9 +43,14 @@ bool ApplicationList::OnTouchEvent(Pinetime::Applications::TouchEvents event) { } std::unique_ptr ApplicationList::CreateScreen(unsigned int screenNum) const { - std::array apps; - for (int i = 0; i < appsPerScreen; i++) { - apps[i] = applications[screenNum * appsPerScreen + i]; + std::array pageApps; + + for(int i = 0; i < appsPerScreen; i++) { + if(i+(screenNum * appsPerScreen) >= apps.size()) { + pageApps[i] = {"", Pinetime::Applications::Apps::None, false}; + } else { + pageApps[i] = apps[i + (screenNum * appsPerScreen)]; + } } return std::make_unique(screenNum, @@ -52,5 +60,5 @@ std::unique_ptr ApplicationList::CreateScreen(unsigned int screenNum) co batteryController, bleController, dateTimeController, - apps); + pageApps); } diff --git a/src/displayapp/screens/ApplicationList.h b/src/displayapp/screens/ApplicationList.h index 371ee710b5..2ad9c7c717 100644 --- a/src/displayapp/screens/ApplicationList.h +++ b/src/displayapp/screens/ApplicationList.h @@ -2,15 +2,12 @@ #include #include - -#include "displayapp/screens/Screen.h" -#include "displayapp/screens/ScreenList.h" -#include "components/datetime/DateTimeController.h" -#include "components/settings/Settings.h" -#include "components/battery/BatteryController.h" -#include "displayapp/screens/Symbols.h" -#include "displayapp/screens/Tile.h" -#include "displayapp/screens/Navigation.h" +#include "displayapp/Apps.h" +#include "Screen.h" +#include "ScreenList.h" +#include "displayapp/Controllers.h" +#include "Symbols.h" +#include "Tile.h" namespace Pinetime { namespace Applications { @@ -22,7 +19,8 @@ namespace Pinetime { const Pinetime::Controllers::Battery& batteryController, const Pinetime::Controllers::Ble& bleController, Controllers::DateTime& dateTimeController, - Pinetime::Controllers::FS& filesystem); + Pinetime::Controllers::FS& filesystem, + std::array&& apps); ~ApplicationList() override; bool OnTouchEvent(TouchEvents event) override; @@ -36,29 +34,13 @@ namespace Pinetime { const Pinetime::Controllers::Ble& bleController; Controllers::DateTime& dateTimeController; Pinetime::Controllers::FS& filesystem; + std::array apps; static constexpr int appsPerScreen = 6; // Increment this when more space is needed - static constexpr int nScreens = 2; - - std::array applications {{ - {Symbols::stopWatch, Apps::StopWatch, true}, - {Symbols::clock, Apps::Alarm, true}, - {Symbols::hourGlass, Apps::Timer, true}, - {Symbols::shoe, Apps::Steps, true}, - {Symbols::heartBeat, Apps::HeartRate, true}, - {Symbols::music, Apps::Music, true}, - - {Symbols::paintbrush, Apps::Paint, true}, - {Symbols::paddle, Apps::Paddle, true}, - {"2", Apps::Twos, true}, - {Symbols::drum, Apps::Metronome, true}, - {Symbols::map, Apps::Navigation, Applications::Screens::Navigation::IsAvailable(filesystem)}, - {Symbols::none, Apps::None, false}, + static constexpr int nScreens = (UserAppTypes::Count/appsPerScreen)+1; - // {"M", Apps::Motion}, - }}; ScreenList screens; }; } diff --git a/src/displayapp/screens/Clock.h b/src/displayapp/screens/Clock.h index f3591f43c6..e67c0260f4 100644 --- a/src/displayapp/screens/Clock.h +++ b/src/displayapp/screens/Clock.h @@ -1,13 +1,12 @@ #pragma once -#include #include #include #include -#include +#include "displayapp/Controllers.h" #include "displayapp/screens/Screen.h" -#include "components/datetime/DateTimeController.h" -#include "components/ble/weather/WeatherService.h" +#include "displayapp/Apps.h" +#include "Symbols.h" namespace Pinetime { namespace Controllers { @@ -16,6 +15,10 @@ namespace Pinetime { class Ble; class NotificationManager; class MotionController; + class DateTime; + class HeartRateController; + class WeatherService; + class FS; } namespace Applications { diff --git a/src/displayapp/screens/HeartRate.h b/src/displayapp/screens/HeartRate.h index 78ae63db5f..85da8dee31 100644 --- a/src/displayapp/screens/HeartRate.h +++ b/src/displayapp/screens/HeartRate.h @@ -4,6 +4,7 @@ #include #include "displayapp/screens/Screen.h" #include "systemtask/SystemTask.h" +#include "Symbols.h" #include #include @@ -37,5 +38,13 @@ namespace Pinetime { lv_task_t* taskRefresh; }; } + template <> + struct AppTraits { + static constexpr Apps app = Apps::HeartRate; + static constexpr const char* icon = Screens::Symbols::heartBeat; + static Screens::Screen* Create(AppControllers& controllers) { + return new Screens::HeartRate(controllers.heartRateController, *controllers.systemTask); + }; + }; } } diff --git a/src/displayapp/screens/InfiniPaint.h b/src/displayapp/screens/InfiniPaint.h index ec184c44c5..a25ace55a2 100644 --- a/src/displayapp/screens/InfiniPaint.h +++ b/src/displayapp/screens/InfiniPaint.h @@ -5,6 +5,9 @@ #include // std::fill #include "displayapp/screens/Screen.h" #include "components/motor/MotorController.h" +#include "Symbols.h" +#include +#include namespace Pinetime { namespace Components { @@ -35,5 +38,13 @@ namespace Pinetime { uint8_t color = 2; }; } + template <> + struct AppTraits { + static constexpr Apps app = Apps::Paint; + static constexpr const char* icon = Screens::Symbols::paintbrush; + static Screens::Screen* Create(AppControllers& controllers) { + return new Screens::InfiniPaint(controllers.lvgl, controllers.motorController); + }; + }; } } diff --git a/src/displayapp/screens/Metronome.h b/src/displayapp/screens/Metronome.h index 13b0d66491..8820962dca 100644 --- a/src/displayapp/screens/Metronome.h +++ b/src/displayapp/screens/Metronome.h @@ -3,6 +3,7 @@ #include "systemtask/SystemTask.h" #include "components/motor/MotorController.h" #include "displayapp/screens/Screen.h" +#include "Symbols.h" namespace Pinetime { namespace Applications { @@ -36,5 +37,13 @@ namespace Pinetime { lv_task_t* taskRefresh; }; } + template <> + struct AppTraits { + static constexpr Apps app = Apps::Metronome; + static constexpr const char* icon = Screens::Symbols::drum; + static Screens::Screen* Create(AppControllers& controllers) { + return new Screens::Metronome(controllers.motorController, *controllers.systemTask); + }; + }; } } diff --git a/src/displayapp/screens/Motion.h b/src/displayapp/screens/Motion.h index e4cbe48393..3ef570d675 100644 --- a/src/displayapp/screens/Motion.h +++ b/src/displayapp/screens/Motion.h @@ -6,6 +6,8 @@ #include #include #include +#include "displayapp/Controllers.h" +#include "displayapp/Apps.h" namespace Pinetime { namespace Applications { @@ -30,5 +32,13 @@ namespace Pinetime { lv_task_t* taskRefresh; }; } + template <> + struct AppTraits { + static constexpr Apps app = Apps::Motion; + static constexpr const char* icon = "M"; + static Screens::Screen* Create(AppControllers& controllers) { + return new Screens::Motion(controllers.motionController); + }; + }; } } diff --git a/src/displayapp/screens/Music.h b/src/displayapp/screens/Music.h index 847c6e7444..acbb63120d 100644 --- a/src/displayapp/screens/Music.h +++ b/src/displayapp/screens/Music.h @@ -21,6 +21,9 @@ #include #include #include "displayapp/screens/Screen.h" +#include "displayapp/Apps.h" +#include "displayapp/Controllers.h" +#include "Symbols.h" namespace Pinetime { namespace Controllers { @@ -82,5 +85,13 @@ namespace Pinetime { /** Watchapp */ }; } + template <> + struct AppTraits { + static constexpr Apps app = Apps::Music; + static constexpr const char* icon = Screens::Symbols::music; + static Screens::Screen* Create(AppControllers& controllers) { + return new Screens::Music(*controllers.musicService); + }; + }; } } diff --git a/src/displayapp/screens/Navigation.h b/src/displayapp/screens/Navigation.h index eb243b011a..d54df13ce3 100644 --- a/src/displayapp/screens/Navigation.h +++ b/src/displayapp/screens/Navigation.h @@ -22,6 +22,9 @@ #include #include "displayapp/screens/Screen.h" #include +#include "displayapp/Apps.h" +#include "displayapp/Controllers.h" +#include "Symbols.h" namespace Pinetime { namespace Controllers { @@ -55,5 +58,13 @@ namespace Pinetime { lv_task_t* taskRefresh; }; } + template <> + struct AppTraits { + static constexpr Apps app = Apps::Navigation; + static constexpr const char* icon = Screens::Symbols::map; + static Screens::Screen* Create(AppControllers& controllers) { + return new Screens::Navigation(*controllers.navigationService); + }; + }; } } diff --git a/src/displayapp/screens/Paddle.h b/src/displayapp/screens/Paddle.h index 33dac191b5..0670e5b1f1 100644 --- a/src/displayapp/screens/Paddle.h +++ b/src/displayapp/screens/Paddle.h @@ -3,6 +3,9 @@ #include #include #include "displayapp/screens/Screen.h" +#include "displayapp/Apps.h" +#include "displayapp/Controllers.h" +#include "Symbols.h" namespace Pinetime { namespace Components { @@ -45,5 +48,13 @@ namespace Pinetime { lv_task_t* taskRefresh; }; } + template <> + struct AppTraits { + static constexpr Apps app = Apps::Paddle; + static constexpr const char* icon = Screens::Symbols::paddle; + static Screens::Screen* Create(AppControllers& controllers) { + return new Screens::Paddle(controllers.lvgl); + }; + }; } } diff --git a/src/displayapp/screens/Steps.h b/src/displayapp/screens/Steps.h index 5dc07eff94..5299d67f9f 100644 --- a/src/displayapp/screens/Steps.h +++ b/src/displayapp/screens/Steps.h @@ -4,6 +4,9 @@ #include #include "displayapp/screens/Screen.h" #include +#include "displayapp/Apps.h" +#include "displayapp/Controllers.h" +#include "Symbols.h" namespace Pinetime { @@ -39,5 +42,13 @@ namespace Pinetime { lv_task_t* taskRefresh; }; } + template <> + struct AppTraits { + static constexpr Apps app = Apps::Steps; + static constexpr const char* icon = Screens::Symbols::shoe; + static Screens::Screen* Create(AppControllers& controllers) { + return new Screens::Steps(controllers.motionController, controllers.settingsController); + }; + }; } } diff --git a/src/displayapp/screens/StopWatch.h b/src/displayapp/screens/StopWatch.h index d1acd1624e..c3550fc41d 100644 --- a/src/displayapp/screens/StopWatch.h +++ b/src/displayapp/screens/StopWatch.h @@ -7,50 +7,65 @@ #include "portmacro_cmsis.h" #include "systemtask/SystemTask.h" +#include "displayapp/Apps.h" +#include "displayapp/Controllers.h" +#include "Symbols.h" -namespace Pinetime::Applications::Screens { - - enum class States { Init, Running, Halted }; - - struct TimeSeparated_t { - int hours; - int mins; - int secs; - int hundredths; - }; - - class StopWatch : public Screen { - public: - explicit StopWatch(System::SystemTask& systemTask); - ~StopWatch() override; - void Refresh() override; - - void playPauseBtnEventHandler(); - void stopLapBtnEventHandler(); - bool OnButtonPushed() override; - - private: - void SetInterfacePaused(); - void SetInterfaceRunning(); - void SetInterfaceStopped(); - - void Reset(); - void Start(); - void Pause(); - - Pinetime::System::SystemTask& systemTask; - States currentState = States::Init; - TickType_t startTime; - TickType_t oldTimeElapsed = 0; - TickType_t blinkTime = 0; - static constexpr int maxLapCount = 20; - TickType_t laps[maxLapCount + 1]; - static constexpr int displayedLaps = 2; - int lapsDone = 0; - lv_obj_t *time, *msecTime, *btnPlayPause, *btnStopLap, *txtPlayPause, *txtStopLap; - lv_obj_t* lapText; - bool isHoursLabelUpdated = false; - - lv_task_t* taskRefresh; - }; +namespace Pinetime { + namespace Applications { + namespace Screens { + + enum class States { Init, Running, Halted }; + + struct TimeSeparated_t { + int hours; + int mins; + int secs; + int hundredths; + }; + + class StopWatch : public Screen { + public: + explicit StopWatch(System::SystemTask& systemTask); + ~StopWatch() override; + void Refresh() override; + + void playPauseBtnEventHandler(); + void stopLapBtnEventHandler(); + bool OnButtonPushed() override; + + private: + void SetInterfacePaused(); + void SetInterfaceRunning(); + void SetInterfaceStopped(); + + void Reset(); + void Start(); + void Pause(); + + Pinetime::System::SystemTask& systemTask; + States currentState = States::Init; + TickType_t startTime; + TickType_t oldTimeElapsed = 0; + TickType_t blinkTime = 0; + static constexpr int maxLapCount = 20; + TickType_t laps[maxLapCount + 1]; + static constexpr int displayedLaps = 2; + int lapsDone = 0; + lv_obj_t *time, *msecTime, *btnPlayPause, *btnStopLap, *txtPlayPause, *txtStopLap; + lv_obj_t* lapText; + bool isHoursLabelUpdated = false; + + lv_task_t* taskRefresh; + }; + } + template <> + struct AppTraits { + static constexpr Apps app = Apps::StopWatch; + static constexpr const char* icon = Screens::Symbols::stopWatch; + static Screens::Screen* Create(AppControllers& controllers) { + return new Screens::StopWatch(*controllers.systemTask); + }; + }; + } } diff --git a/src/displayapp/screens/Tile.cpp b/src/displayapp/screens/Tile.cpp index 343755e3f0..7c392c59e5 100644 --- a/src/displayapp/screens/Tile.cpp +++ b/src/displayapp/screens/Tile.cpp @@ -1,5 +1,4 @@ #include "displayapp/screens/Tile.h" -#include "displayapp/DisplayApp.h" #include "displayapp/screens/BatteryIcon.h" #include "components/ble/BleController.h" #include "displayapp/InfiniTimeTheme.h" diff --git a/src/displayapp/screens/Timer.cpp b/src/displayapp/screens/Timer.cpp index d94887404e..a1ede6bed6 100644 --- a/src/displayapp/screens/Timer.cpp +++ b/src/displayapp/screens/Timer.cpp @@ -62,7 +62,7 @@ Timer::Timer(Controllers::Timer& timerController) : timer {timerController} { txtPlayPause = lv_label_create(lv_scr_act(), nullptr); lv_obj_align(txtPlayPause, btnPlayPause, LV_ALIGN_CENTER, 0, 0); - if (timerController.IsRunning()) { + if (timer.IsRunning()) { SetTimerRunning(); } else { SetTimerStopped(); diff --git a/src/displayapp/screens/Timer.h b/src/displayapp/screens/Timer.h index e452a9d9dc..f8e337c2ec 100644 --- a/src/displayapp/screens/Timer.h +++ b/src/displayapp/screens/Timer.h @@ -8,38 +8,48 @@ #include #include "components/timer/Timer.h" - -namespace Pinetime::Applications::Screens { - class Timer : public Screen { - public: - Timer(Controllers::Timer& timerController); - ~Timer() override; - void Refresh() override; - void Reset(); - void ToggleRunning(); - void ButtonPressed(); - void MaskReset(); - - private: - void SetTimerRunning(); - void SetTimerStopped(); - void UpdateMask(); - Controllers::Timer& timer; - - lv_obj_t* btnPlayPause; - lv_obj_t* txtPlayPause; - - lv_obj_t* btnObjectMask; - lv_obj_t* highlightObjectMask; - lv_objmask_mask_t* btnMask; - lv_objmask_mask_t* highlightMask; - - lv_task_t* taskRefresh; - Widgets::Counter minuteCounter = Widgets::Counter(0, 59, jetbrains_mono_76); - Widgets::Counter secondCounter = Widgets::Counter(0, 59, jetbrains_mono_76); - - bool buttonPressing = false; - lv_coord_t maskPosition = 0; - TickType_t pressTime = 0; +#include "Symbols.h" + +namespace Pinetime::Applications{ + namespace Screens { + class Timer : public Screen { + public: + Timer(Controllers::Timer& timerController); + ~Timer() override; + void Refresh() override; + void Reset(); + void ToggleRunning(); + void ButtonPressed(); + void MaskReset(); + + private: + void SetTimerRunning(); + void SetTimerStopped(); + void UpdateMask(); + Pinetime::Controllers::Timer& timer; + + lv_obj_t* btnPlayPause; + lv_obj_t* txtPlayPause; + + lv_obj_t* btnObjectMask; + lv_obj_t* highlightObjectMask; + lv_objmask_mask_t* btnMask; + lv_objmask_mask_t* highlightMask; + + lv_task_t* taskRefresh; + Widgets::Counter minuteCounter = Widgets::Counter(0, 59, jetbrains_mono_76); + Widgets::Counter secondCounter = Widgets::Counter(0, 59, jetbrains_mono_76); + + bool buttonPressing = false; + lv_coord_t maskPosition = 0; + TickType_t pressTime = 0; + }; + } + + template<> + struct AppTraits { + static constexpr Apps app = Apps::Timer; + static constexpr const char* icon = Screens::Symbols::hourGlass; + static Screens::Screen *Create(AppControllers& controllers) { return new Screens::Timer(controllers.timer); }; }; } diff --git a/src/displayapp/screens/Twos.h b/src/displayapp/screens/Twos.h index e731eae62f..4e6980f53a 100644 --- a/src/displayapp/screens/Twos.h +++ b/src/displayapp/screens/Twos.h @@ -1,7 +1,8 @@ #pragma once -#include +#include "displayapp/Apps.h" #include "displayapp/screens/Screen.h" +#include "displayapp/Controllers.h" namespace Pinetime { namespace Applications { @@ -35,5 +36,11 @@ namespace Pinetime { bool placeNewTile(); }; } + template<> + struct AppTraits { + static constexpr Apps app = Apps::Twos; + static constexpr const char* icon = "2"; + static Screens::Screen *Create(AppControllers& /*controllers*/) { return new Screens::Twos(); }; + }; } } diff --git a/src/displayapp/screens/Weather.h b/src/displayapp/screens/Weather.h index 459534aa2a..888dc257cf 100644 --- a/src/displayapp/screens/Weather.h +++ b/src/displayapp/screens/Weather.h @@ -1,9 +1,12 @@ #pragma once #include -#include +#include "components/ble/weather/WeatherService.h" #include "Screen.h" #include "ScreenList.h" +#include "displayapp/Apps.h" +#include "displayapp/Controllers.h" +#include "Symbols.h" namespace Pinetime { namespace Applications { @@ -41,5 +44,13 @@ namespace Pinetime { std::unique_ptr CreateScreenHumidity(); }; } + template <> + struct AppTraits { + static constexpr Apps app = Apps::Weather; + static constexpr const char* icon = Screens::Symbols::sun; + static Screens::Screen* Create(AppControllers& controllers) { + return new Screens::Weather(controllers.displayApp, *controllers.weatherController); + }; + }; } } diff --git a/src/drivers/SpiMaster.cpp b/src/drivers/SpiMaster.cpp index 1a2fab9c27..3446d639fa 100644 --- a/src/drivers/SpiMaster.cpp +++ b/src/drivers/SpiMaster.cpp @@ -131,8 +131,8 @@ void SpiMaster::OnEndEvent() { if (s > 0) { auto currentSize = std::min((size_t) 255, s); PrepareTx(currentBufferAddr, currentSize); - currentBufferAddr += currentSize; - currentBufferSize -= currentSize; + currentBufferAddr = currentBufferAddr + currentSize; + currentBufferSize = currentBufferSize - currentSize; spiBaseAddress->TASKS_START = 1; } else { @@ -153,7 +153,7 @@ void SpiMaster::OnEndEvent() { void SpiMaster::OnStartedEvent() { } -void SpiMaster::PrepareTx(const volatile uint32_t bufferAddress, const volatile size_t size) { +void SpiMaster::PrepareTx(const uint32_t bufferAddress, const size_t size) { spiBaseAddress->TXD.PTR = bufferAddress; spiBaseAddress->TXD.MAXCNT = size; spiBaseAddress->TXD.LIST = 0; @@ -163,7 +163,7 @@ void SpiMaster::PrepareTx(const volatile uint32_t bufferAddress, const volatile spiBaseAddress->EVENTS_END = 0; } -void SpiMaster::PrepareRx(const volatile uint32_t bufferAddress, const volatile size_t size) { +void SpiMaster::PrepareRx(const uint32_t bufferAddress, const size_t size) { spiBaseAddress->TXD.PTR = 0; spiBaseAddress->TXD.MAXCNT = 0; spiBaseAddress->TXD.LIST = 0; @@ -195,8 +195,8 @@ bool SpiMaster::Write(uint8_t pinCsn, const uint8_t* data, size_t size) { auto currentSize = std::min((size_t) 255, (size_t) currentBufferSize); PrepareTx(currentBufferAddr, currentSize); - currentBufferSize -= currentSize; - currentBufferAddr += currentSize; + currentBufferSize = currentBufferSize - currentSize; + currentBufferAddr = currentBufferAddr + currentSize; spiBaseAddress->TASKS_START = 1; if (size == 1) { diff --git a/src/drivers/Watchdog.cpp b/src/drivers/Watchdog.cpp index 6c2c963be3..eeeb6cfdf5 100644 --- a/src/drivers/Watchdog.cpp +++ b/src/drivers/Watchdog.cpp @@ -41,7 +41,7 @@ namespace { // RRED (Reload Register Enable) is a bitfield of 8 bits. Each bit represent // one of the eight reload registers available. // In this case, we enable only the first one. - NRF_WDT->RREN |= 1; + NRF_WDT->RREN = NRF_WDT->RREN | 1; } /// Returns the reset reason provided by the POWER subsystem diff --git a/src/systemtask/SystemTask.cpp b/src/systemtask/SystemTask.cpp index e59a0ff7a4..b245e39227 100644 --- a/src/systemtask/SystemTask.cpp +++ b/src/systemtask/SystemTask.cpp @@ -136,6 +136,9 @@ void SystemTask::Work() { settingsController.Init(); displayApp.Register(this); + displayApp.Register(&nimbleController.weather()); + displayApp.Register(&nimbleController.music()); + displayApp.Register(&nimbleController.navigation()); displayApp.Start(bootError); heartRateSensor.Init(); From 3886ebf0942f79f141ed5dd3a65bdf880f990efc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Milants?= Date: Mon, 23 Oct 2023 21:43:05 +0200 Subject: [PATCH 2/5] Application selection at build time Fix DisplayAppRecovery so it builds with -std=c++20. --- src/components/gfx/Gfx.cpp | 4 ++-- src/displayapp/DisplayAppRecovery.cpp | 9 +++++++++ src/displayapp/DisplayAppRecovery.h | 7 +++++++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/components/gfx/Gfx.cpp b/src/components/gfx/Gfx.cpp index 3eaaa3fecc..d3ef3d087a 100644 --- a/src/components/gfx/Gfx.cpp +++ b/src/components/gfx/Gfx.cpp @@ -141,7 +141,7 @@ void Gfx::SetBackgroundColor(uint16_t color) { bool Gfx::GetNextBuffer(uint8_t** data, size_t& size) { if (!state.busy) return false; - state.remainingIterations--; + state.remainingIterations = state.remainingIterations-1; if (state.remainingIterations == 0) { state.busy = false; NotifyEndOfTransfer(state.taskToNotify); @@ -170,7 +170,7 @@ bool Gfx::GetNextBuffer(uint8_t** data, size_t& size) { size = bytes_in_line * 8 * 2; } - state.currentIteration++; + state.currentIteration = state.currentIteration + 1; return true; } diff --git a/src/displayapp/DisplayAppRecovery.cpp b/src/displayapp/DisplayAppRecovery.cpp index de165c2922..9fe59c40a8 100644 --- a/src/displayapp/DisplayAppRecovery.cpp +++ b/src/displayapp/DisplayAppRecovery.cpp @@ -121,3 +121,12 @@ void DisplayApp::PushMessage(Display::Messages msg) { void DisplayApp::Register(Pinetime::System::SystemTask* /*systemTask*/) { } + +void DisplayApp::Register(Pinetime::Controllers::WeatherService* /*weatherService*/) { +} + +void DisplayApp::Register(Pinetime::Controllers::MusicService* /*musicService*/) { +} + +void DisplayApp::Register(Pinetime::Controllers::NavigationService* /*NavigationService*/) { +} diff --git a/src/displayapp/DisplayAppRecovery.h b/src/displayapp/DisplayAppRecovery.h index 3ce9518773..a42d3e2fb1 100644 --- a/src/displayapp/DisplayAppRecovery.h +++ b/src/displayapp/DisplayAppRecovery.h @@ -34,6 +34,9 @@ namespace Pinetime { class AlarmController; class BrightnessController; class FS; + class WeatherService; + class MusicService; + class NavigationService; } namespace System { @@ -66,6 +69,10 @@ namespace Pinetime { void PushMessage(Pinetime::Applications::Display::Messages msg); void Register(Pinetime::System::SystemTask* systemTask); + void Register(Pinetime::Controllers::WeatherService* weatherService); + void Register(Pinetime::Controllers::MusicService* musicService); + void Register(Pinetime::Controllers::NavigationService* NavigationService); + private: TaskHandle_t taskHandle; From 27df3ff03543985850d5c3631638d39813fcd248 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Milants?= Date: Wed, 1 Nov 2023 20:52:47 +0100 Subject: [PATCH 3/5] Add missing new line at end of file. --- src/displayapp/Controllers.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/displayapp/Controllers.h b/src/displayapp/Controllers.h index cef989867e..a2f8238880 100644 --- a/src/displayapp/Controllers.h +++ b/src/displayapp/Controllers.h @@ -48,4 +48,4 @@ namespace Pinetime { Pinetime::Controllers::NavigationService* navigationService; }; } -} \ No newline at end of file +} From a868322b49c8a80dd66e9686b354a0f91c8c4a79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Milants?= Date: Wed, 1 Nov 2023 21:06:26 +0100 Subject: [PATCH 4/5] Fix code formatting --- src/components/gfx/Gfx.cpp | 2 +- src/displayapp/Apps.h | 3 ++- src/displayapp/Controllers.h | 5 +++++ src/displayapp/DisplayApp.cpp | 26 ++++++++++++++++------ src/displayapp/DisplayAppRecovery.h | 1 - src/displayapp/UserApps.h | 2 +- src/displayapp/screens/Alarm.h | 10 ++++++--- src/displayapp/screens/ApplicationList.cpp | 10 ++++----- src/displayapp/screens/ApplicationList.h | 2 +- src/displayapp/screens/HeartRate.h | 2 ++ src/displayapp/screens/InfiniPaint.h | 2 ++ src/displayapp/screens/Metronome.h | 2 ++ src/displayapp/screens/Motion.h | 2 ++ src/displayapp/screens/Music.h | 2 ++ src/displayapp/screens/Navigation.h | 2 ++ src/displayapp/screens/Paddle.h | 2 ++ src/displayapp/screens/Steps.h | 2 ++ src/displayapp/screens/StopWatch.h | 2 ++ src/displayapp/screens/Timer.h | 9 +++++--- src/displayapp/screens/Twos.h | 8 +++++-- src/displayapp/screens/Weather.h | 2 ++ 21 files changed, 73 insertions(+), 25 deletions(-) diff --git a/src/components/gfx/Gfx.cpp b/src/components/gfx/Gfx.cpp index d3ef3d087a..baa6486a4a 100644 --- a/src/components/gfx/Gfx.cpp +++ b/src/components/gfx/Gfx.cpp @@ -141,7 +141,7 @@ void Gfx::SetBackgroundColor(uint16_t color) { bool Gfx::GetNextBuffer(uint8_t** data, size_t& size) { if (!state.busy) return false; - state.remainingIterations = state.remainingIterations-1; + state.remainingIterations = state.remainingIterations - 1; if (state.remainingIterations == 0) { state.busy = false; NotifyEndOfTransfer(state.taskToNotify); diff --git a/src/displayapp/Apps.h b/src/displayapp/Apps.h index d96e6ea721..0dd8157e2d 100644 --- a/src/displayapp/Apps.h +++ b/src/displayapp/Apps.h @@ -40,10 +40,11 @@ namespace Pinetime { Error, Weather }; + template struct AppTraits {}; - template + template struct TypeList { static constexpr size_t Count = sizeof...(As); }; diff --git a/src/displayapp/Controllers.h b/src/displayapp/Controllers.h index a2f8238880..df6b2284b4 100644 --- a/src/displayapp/Controllers.h +++ b/src/displayapp/Controllers.h @@ -1,11 +1,14 @@ #pragma once + namespace Pinetime { namespace Applications { class DisplayApp; } + namespace Components { class LittleVgl; } + namespace Controllers { class Battery; class Ble; @@ -23,9 +26,11 @@ namespace Pinetime { class MusicService; class NavigationService; } + namespace System { class SystemTask; } + namespace Applications { struct AppControllers { const Pinetime::Controllers::Battery& batteryController; diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index a195361ddb..98be6324a9 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -98,11 +98,24 @@ DisplayApp::DisplayApp(Drivers::St7789& lcd, filesystem {filesystem}, lvgl {lcd, filesystem}, timer(this, TimerCallback), - controllers{ - batteryController, bleController, dateTimeController, notificationManager, heartRateController, - settingsController, motorController, motionController, alarmController, brightnessController, - nullptr, filesystem, timer, nullptr, this, lvgl, nullptr, nullptr} - { + controllers {batteryController, + bleController, + dateTimeController, + notificationManager, + heartRateController, + settingsController, + motorController, + motionController, + alarmController, + brightnessController, + nullptr, + filesystem, + timer, + nullptr, + this, + lvgl, + nullptr, + nullptr} { } void DisplayApp::Start(System::BootErrors error) { @@ -421,8 +434,7 @@ void DisplayApp::LoadScreen(Apps app, DisplayApp::FullRefreshDirections directio dateTimeController, filesystem, std::move(apps)); - } - break; + } break; case Apps::Clock: currentScreen = std::make_unique(dateTimeController, batteryController, diff --git a/src/displayapp/DisplayAppRecovery.h b/src/displayapp/DisplayAppRecovery.h index a42d3e2fb1..41aedb1793 100644 --- a/src/displayapp/DisplayAppRecovery.h +++ b/src/displayapp/DisplayAppRecovery.h @@ -73,7 +73,6 @@ namespace Pinetime { void Register(Pinetime::Controllers::MusicService* musicService); void Register(Pinetime::Controllers::NavigationService* NavigationService); - private: TaskHandle_t taskHandle; static void Process(void* instance); diff --git a/src/displayapp/UserApps.h b/src/displayapp/UserApps.h index d0165cf9de..0ed9d60294 100644 --- a/src/displayapp/UserApps.h +++ b/src/displayapp/UserApps.h @@ -26,7 +26,7 @@ namespace Pinetime { return {AppTraits::app, AppTraits::icon, &AppTraits::Create}; } - template typename T, Apps ...ts> + template