Author: KaffeinatedKat <coffeeboi47@protonmail.com>
feat: always on display
src/components/settings/Settings.h | 15 ++++++++++++++- src/displayapp/DisplayApp.cpp | 6 +++++- src/displayapp/screens/settings/SettingDisplay.cpp | 14 ++++++++++++-- src/displayapp/screens/settings/SettingDisplay.h | 2 +- src/systemtask/SystemTask.cpp | 15 +++++++++++----
diff --git a/src/components/settings/Settings.h b/src/components/settings/Settings.h index 063120774a8548024da3935a03a5c84532f111a6..d75cd678abd641b2fe264a787667915f1cadf441 100644 --- a/src/components/settings/Settings.h +++ b/src/components/settings/Settings.h @@ -214,6 +214,17 @@ uint32_t GetScreenTimeOut() const { return settings.screenTimeOut; }; + void SetAlwaysOnDisplay(bool state) { + if (state != settings.alwaysOnDisplay) { + settingsChanged = true; + } + settings.alwaysOnDisplay = state; + }; + + bool GetAlwaysOnDisplay() const { + return settings.alwaysOnDisplay; + }; + void SetShakeThreshold(uint16_t thresh) { if (settings.shakeWakeThreshold != thresh) { settings.shakeWakeThreshold = thresh; @@ -286,12 +297,14 @@ private: Pinetime::Controllers::FS& fs; - static constexpr uint32_t settingsVersion = 0x0007; + static constexpr uint32_t settingsVersion = 0x0008; struct SettingsData { uint32_t version = settingsVersion; uint32_t stepsGoal = 10000; uint32_t screenTimeOut = 15000; + + bool alwaysOnDisplay = false; ClockType clockType = ClockType::H24; WeatherFormat weatherFormat = WeatherFormat::Metric; diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index 3fd34b3a8ce3295871c9dde5164bb0d3ce092bbe..c7fb62abc582f79b42f8a6f860b6d8316b0328e1 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -203,7 +203,11 @@ TickType_t queueTimeout; switch (state) { case States::Idle: - queueTimeout = portMAX_DELAY; + if (settingsController.GetAlwaysOnDisplay()) { + queueTimeout = lv_task_handler(); + } else { + queueTimeout = portMAX_DELAY; + } break; case States::Running: if (!currentScreen->IsRunning()) { diff --git a/src/displayapp/screens/settings/SettingDisplay.cpp b/src/displayapp/screens/settings/SettingDisplay.cpp index bd533e675b7de2405257f8857f0af197cf1bd101..760f1e9e0f9e2dc868127119c7d67a45ade11655 100644 --- a/src/displayapp/screens/settings/SettingDisplay.cpp +++ b/src/displayapp/screens/settings/SettingDisplay.cpp @@ -15,7 +15,7 @@ screen->UpdateSelected(obj, event); } } -constexpr std::array<uint16_t, 6> SettingDisplay::options; +constexpr std::array<uint16_t, 7> SettingDisplay::options; SettingDisplay::SettingDisplay(Pinetime::Applications::DisplayApp* app, Pinetime::Controllers::Settings& settingsController) : app {app}, settingsController {settingsController} { @@ -46,7 +46,11 @@ char buffer[4]; for (unsigned int i = 0; i < options.size(); i++) { cbOption[i] = lv_checkbox_create(container1, nullptr); - snprintf(buffer, sizeof(buffer), "%2" PRIu16 "s", options[i] / 1000); + if (options[i] == 0) { + sprintf(buffer, "%s", "Always On"); + } else { + sprintf(buffer, "%2ds", options[i] / 1000); + } lv_checkbox_set_text(cbOption[i], buffer); cbOption[i]->user_data = this; lv_obj_set_event_cb(cbOption[i], event_handler); @@ -64,6 +68,12 @@ settingsController.SaveSettings(); } void SettingDisplay::UpdateSelected(lv_obj_t* object, lv_event_t event) { + if (settingsController.GetScreenTimeOut() == 0) { + settingsController.SetAlwaysOnDisplay(true); + } else { + settingsController.SetAlwaysOnDisplay(false); + } + if (event == LV_EVENT_CLICKED) { for (unsigned int i = 0; i < options.size(); i++) { if (object == cbOption[i]) { diff --git a/src/displayapp/screens/settings/SettingDisplay.h b/src/displayapp/screens/settings/SettingDisplay.h index 64212c021756b77c1131e3d9bc39c34287fad55b..a43704637f57ae0d83e539aa5d533f15988fd81e 100644 --- a/src/displayapp/screens/settings/SettingDisplay.h +++ b/src/displayapp/screens/settings/SettingDisplay.h @@ -21,7 +21,7 @@ void UpdateSelected(lv_obj_t* object, lv_event_t event); private: DisplayApp* app; - static constexpr std::array<uint16_t, 6> options = {5000, 7000, 10000, 15000, 20000, 30000}; + static constexpr std::array<uint16_t, 7> options = {5000, 7000, 10000, 15000, 20000, 30000, 0}; Controllers::Settings& settingsController; lv_obj_t* cbOption[options.size()]; diff --git a/src/systemtask/SystemTask.cpp b/src/systemtask/SystemTask.cpp index a56c259105145b4e5856e99d7e9f998efa418617..fb7493aaf5b4b932f26d030394ebb102384d8f6c 100644 --- a/src/systemtask/SystemTask.cpp +++ b/src/systemtask/SystemTask.cpp @@ -198,7 +198,10 @@ case Messages::DisableSleeping: doNotGoToSleep = true; break; case Messages::GoToRunning: - spi.Wakeup(); + // SPI doesn't go to sleep for always on mode + if (!settingsController.GetAlwaysOnDisplay()) { + spi.Wakeup(); + } // Double Tap needs the touch screen to be in normal mode if (!settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::DoubleTap)) { @@ -231,7 +234,7 @@ } break; } case Messages::GoToSleep: - if (doNotGoToSleep) { + if (doNotGoToSleep or settingsController.GetAlwaysOnDisplay()) { break; } state = SystemTaskState::GoingToSleep; // Already set in PushMessage() @@ -323,7 +326,11 @@ // First versions of the bootloader do not expose their version and cannot initialize the SPI NOR FLASH // if it's in sleep mode. Avoid bricked device by disabling sleep mode on these versions. spiNorFlash.Sleep(); } - spi.Sleep(); + + // Must keep SPI awake when still updating the display for always on + if (!settingsController.GetAlwaysOnDisplay()) { + spi.Sleep(); + } // Double Tap needs the touch screen to be in normal mode if (!settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::DoubleTap)) { @@ -503,7 +510,7 @@ } } void SystemTask::PushMessage(System::Messages msg) { - if (msg == Messages::GoToSleep && !doNotGoToSleep) { + if (msg == Messages::GoToSleep && !doNotGoToSleep && !settingsController.GetAlwaysOnDisplay()) { state = SystemTaskState::GoingToSleep; }