InfiniTime.git

commit 20ac7e8df38836d0a72c378b900b99c827c996c2

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;
   }