From 084123b752c74f7b8a6da23cb9bce0ac4efa3715 Mon Sep 17 00:00:00 2001 From: "joaquim.org" Date: Sun, 11 Jul 2021 14:06:06 +0100 Subject: Using littlefs (#438) * add submodule littlefs * base fs * Save settings using littlefs * Small fixes and suggestions from PR * More small fixes from PR suggestions * Code clean up * Change SpiNorFlash functions to be private in FS --- src/components/settings/Settings.h | 58 ++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 30 deletions(-) (limited to 'src/components/settings/Settings.h') diff --git a/src/components/settings/Settings.h b/src/components/settings/Settings.h index 4409425b..577455eb 100644 --- a/src/components/settings/Settings.h +++ b/src/components/settings/Settings.h @@ -2,25 +2,26 @@ #include #include "components/datetime/DateTimeController.h" #include "components/brightness/BrightnessController.h" -#include "drivers/SpiNorFlash.h" +#include "components/fs/FS.h" #include "drivers/Cst816s.h" namespace Pinetime { namespace Controllers { class Settings { public: - enum class ClockType { H24, H12 }; - enum class Vibration { ON, OFF }; - enum class WakeUpMode { None, SingleTap, DoubleTap, RaiseWrist }; + enum class ClockType : uint8_t { H24, H12 }; + enum class Vibration : uint8_t { ON, OFF }; + enum class WakeUpMode : uint8_t { None, SingleTap, DoubleTap, RaiseWrist }; - Settings(Pinetime::Drivers::SpiNorFlash& spiNorFlash); + Settings(Pinetime::Controllers::FS& fs); void Init(); void SaveSettings(); void SetClockFace(uint8_t face) { - if (face != settings.clockFace) + if (face != settings.clockFace) { settingsChanged = true; + } settings.clockFace = face; }; uint8_t GetClockFace() const { @@ -42,8 +43,9 @@ namespace Pinetime { }; void SetClockType(ClockType clocktype) { - if (clocktype != settings.clockType) + if (clocktype != settings.clockType) { settingsChanged = true; + } settings.clockType = clocktype; }; ClockType GetClockType() const { @@ -51,8 +53,9 @@ namespace Pinetime { }; void SetVibrationStatus(Vibration status) { - if (status != settings.vibrationStatus) + if (status != settings.vibrationStatus) { settingsChanged = true; + } settings.vibrationStatus = status; }; Vibration GetVibrationStatus() const { @@ -60,8 +63,9 @@ namespace Pinetime { }; void SetScreenTimeOut(uint32_t timeout) { - if (timeout != settings.screenTimeOut) + if (timeout != settings.screenTimeOut) { settingsChanged = true; + } settings.screenTimeOut = timeout; }; uint32_t GetScreenTimeOut() const { @@ -69,8 +73,9 @@ namespace Pinetime { }; void setWakeUpMode(WakeUpMode wakeUp) { - if (wakeUp != settings.wakeUpMode) + if (wakeUp != settings.wakeUpMode) { settingsChanged = true; + } settings.wakeUpMode = wakeUp; }; WakeUpMode getWakeUpMode() const { @@ -78,8 +83,9 @@ namespace Pinetime { }; void SetBrightness(Controllers::BrightnessController::Levels level) { - if (level != settings.brightLevel) + if (level != settings.brightLevel) { settingsChanged = true; + } settings.brightLevel = level; }; Controllers::BrightnessController::Levels GetBrightness() const { @@ -87,25 +93,29 @@ namespace Pinetime { }; void SetStepsGoal( uint32_t goal ) { - if ( goal != settings.stepsGoal ) + if ( goal != settings.stepsGoal ) { settingsChanged = true; + } settings.stepsGoal = goal; }; uint32_t GetStepsGoal() const { return settings.stepsGoal; }; private: - Pinetime::Drivers::SpiNorFlash& spiNorFlash; + Pinetime::Controllers::FS& fs; + + static constexpr uint32_t settingsVersion = 0x0001; struct SettingsData { + uint32_t version = settingsVersion; + uint32_t stepsGoal = 10000; + uint32_t screenTimeOut = 15000; + ClockType clockType = ClockType::H24; Vibration vibrationStatus = Vibration::ON; uint8_t clockFace = 0; - uint32_t stepsGoal = 10000; - uint32_t screenTimeOut = 15000; - WakeUpMode wakeUpMode = WakeUpMode::None; Controllers::BrightnessController::Levels brightLevel = Controllers::BrightnessController::Levels::Medium; @@ -117,20 +127,8 @@ namespace Pinetime { uint8_t appMenu = 0; uint8_t settingsMenu = 0; - // There are 10 blocks of reserved flash to save settings - // to minimize wear, the recording is done in a rotating way by the 10 blocks - uint8_t settingsFlashBlock = 99; // default to indicate it needs to find the active block - - static constexpr uint32_t settingsBaseAddr = 0x3F6000; // Flash Settings Location - static constexpr uint16_t settingsVersion = 0x0100; // Flash Settings Version - - bool FindHeader(); - void ReadSettingsData(); - void EraseBlock(); - void SetHeader(bool state); - void SaveSettingsData(); - void LoadSettingsFromFlash(); - void SaveSettingsToFlash(); + void LoadSettingsFromFile(); + void SaveSettingsToFile(); }; } } \ No newline at end of file -- cgit v1.2.3 From 57b339707861c5688f5d432f1506a99df6bb0fce Mon Sep 17 00:00:00 2001 From: Kozova1 <30871100+Kozova1@users.noreply.github.com> Date: Wed, 14 Jul 2021 21:51:51 +0300 Subject: Multiple wakeup sources (#290) * Allow multiple wakeup modes at the same time. This commit adds multiple wakeup modes support. It does so by storing them as a uint8_t bitfield enum. It changes the following functions: Since multiple modes can be on now, older version would not cut it: WakeUpMode getWakeupMode() -> std::bitset<3> getWakeUpModes() Where each bit corresponds to a WakeUpMode We still need a way to check whether a specific wakeup mode is on, so: bool isWakeUpModeOn(const WakeUpMode mode) This function was changed to work correctly with the new implementation. setWakeUpMode(WakeupMode mode, bool enable) Previously, systemtask would exit SystemTask::OnTouchEvent() if the wake up mode was None or RaiseWrist, to prevent waking up when a touch was received. However, after enabling using multiple WakeUpModes, this caused a bug where when RaiseWrist was checked with SingleTap or DoubleTap, the tap detection wouldn't work. This commit fixes that bug. Next commit will update the settings WakeUpMode select UI to reflect these changes. Signed-off-by: Kozova1 * Updated UI to reflect multiple WakeUp sources being available. Signed-off-by: Kozova1 --- src/components/settings/Settings.h | 39 ++++++++++++--- src/displayapp/screens/settings/SettingWakeUp.cpp | 60 +++++++++++------------ src/displayapp/screens/settings/SettingWakeUp.h | 5 ++ src/systemtask/SystemTask.cpp | 18 +++---- 4 files changed, 73 insertions(+), 49 deletions(-) (limited to 'src/components/settings/Settings.h') diff --git a/src/components/settings/Settings.h b/src/components/settings/Settings.h index 577455eb..93d6d217 100644 --- a/src/components/settings/Settings.h +++ b/src/components/settings/Settings.h @@ -1,5 +1,6 @@ #pragma once #include +#include #include "components/datetime/DateTimeController.h" #include "components/brightness/BrightnessController.h" #include "components/fs/FS.h" @@ -11,7 +12,11 @@ namespace Pinetime { public: enum class ClockType : uint8_t { H24, H12 }; enum class Vibration : uint8_t { ON, OFF }; - enum class WakeUpMode : uint8_t { None, SingleTap, DoubleTap, RaiseWrist }; + enum class WakeUpMode : uint8_t { + SingleTap = 0, + DoubleTap = 1, + RaiseWrist = 2, + }; Settings(Pinetime::Controllers::FS& fs); @@ -72,15 +77,33 @@ namespace Pinetime { return settings.screenTimeOut; }; - void setWakeUpMode(WakeUpMode wakeUp) { - if (wakeUp != settings.wakeUpMode) { + void setWakeUpMode(WakeUpMode wakeUp, bool enabled) { + if (!isWakeUpModeOn(wakeUp)) { settingsChanged = true; } - settings.wakeUpMode = wakeUp; + settings.wakeUpMode.set(static_cast(wakeUp), enabled); + // Handle special behavior + if (enabled) { + switch (wakeUp) { + case WakeUpMode::SingleTap: + settings.wakeUpMode.set(static_cast(WakeUpMode::DoubleTap), false); + break; + case WakeUpMode::DoubleTap: + settings.wakeUpMode.set(static_cast(WakeUpMode::SingleTap), false); + break; + case WakeUpMode::RaiseWrist: + break; + } + } }; - WakeUpMode getWakeUpMode() const { + + std::bitset<3> getWakeUpModes() const { return settings.wakeUpMode; - }; + } + + bool isWakeUpModeOn(const WakeUpMode mode) const { + return getWakeUpModes()[static_cast(mode)]; + } void SetBrightness(Controllers::BrightnessController::Levels level) { if (level != settings.brightLevel) { @@ -116,7 +139,7 @@ namespace Pinetime { uint8_t clockFace = 0; - WakeUpMode wakeUpMode = WakeUpMode::None; + std::bitset<3> wakeUpMode {0}; Controllers::BrightnessController::Levels brightLevel = Controllers::BrightnessController::Levels::Medium; }; @@ -131,4 +154,4 @@ namespace Pinetime { void SaveSettingsToFile(); }; } -} \ No newline at end of file +} diff --git a/src/displayapp/screens/settings/SettingWakeUp.cpp b/src/displayapp/screens/settings/SettingWakeUp.cpp index 89f0c098..0e080353 100644 --- a/src/displayapp/screens/settings/SettingWakeUp.cpp +++ b/src/displayapp/screens/settings/SettingWakeUp.cpp @@ -16,7 +16,7 @@ namespace { SettingWakeUp::SettingWakeUp(Pinetime::Applications::DisplayApp* app, Pinetime::Controllers::Settings& settingsController) : Screen(app), settingsController {settingsController} { - + ignoringEvents = false; lv_obj_t* container1 = lv_cont_create(lv_scr_act(), nullptr); lv_obj_set_style_local_bg_opa(container1, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_TRANSP); @@ -42,18 +42,10 @@ SettingWakeUp::SettingWakeUp(Pinetime::Applications::DisplayApp* app, Pinetime:: optionsTotal = 0; cbOption[optionsTotal] = lv_checkbox_create(container1, nullptr); - lv_checkbox_set_text_static(cbOption[optionsTotal], " None"); - cbOption[optionsTotal]->user_data = this; - lv_obj_set_event_cb(cbOption[optionsTotal], event_handler); - if (settingsController.getWakeUpMode() == Pinetime::Controllers::Settings::WakeUpMode::None) { - lv_checkbox_set_checked(cbOption[optionsTotal], true); - } - optionsTotal++; - cbOption[optionsTotal] = lv_checkbox_create(container1, nullptr); lv_checkbox_set_text_static(cbOption[optionsTotal], " Single Tap"); cbOption[optionsTotal]->user_data = this; lv_obj_set_event_cb(cbOption[optionsTotal], event_handler); - if (settingsController.getWakeUpMode() == Pinetime::Controllers::Settings::WakeUpMode::SingleTap) { + if (settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::SingleTap)) { lv_checkbox_set_checked(cbOption[optionsTotal], true); } optionsTotal++; @@ -61,7 +53,7 @@ SettingWakeUp::SettingWakeUp(Pinetime::Applications::DisplayApp* app, Pinetime:: lv_checkbox_set_text_static(cbOption[optionsTotal], " Double Tap"); cbOption[optionsTotal]->user_data = this; lv_obj_set_event_cb(cbOption[optionsTotal], event_handler); - if (settingsController.getWakeUpMode() == Pinetime::Controllers::Settings::WakeUpMode::DoubleTap) { + if (settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::DoubleTap)) { lv_checkbox_set_checked(cbOption[optionsTotal], true); } optionsTotal++; @@ -69,7 +61,7 @@ SettingWakeUp::SettingWakeUp(Pinetime::Applications::DisplayApp* app, Pinetime:: lv_checkbox_set_text_static(cbOption[optionsTotal], " Raise Wrist"); cbOption[optionsTotal]->user_data = this; lv_obj_set_event_cb(cbOption[optionsTotal], event_handler); - if (settingsController.getWakeUpMode() == Pinetime::Controllers::Settings::WakeUpMode::RaiseWrist) { + if (settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::RaiseWrist)) { lv_checkbox_set_checked(cbOption[optionsTotal], true); } optionsTotal++; @@ -85,27 +77,31 @@ bool SettingWakeUp::Refresh() { } void SettingWakeUp::UpdateSelected(lv_obj_t* object, lv_event_t event) { - if (event == LV_EVENT_VALUE_CHANGED) { - for (int i = 0; i < optionsTotal; i++) { - if (object == cbOption[i]) { - lv_checkbox_set_checked(cbOption[i], true); + using WakeUpMode = Pinetime::Controllers::Settings::WakeUpMode; + if (event == LV_EVENT_VALUE_CHANGED && !ignoringEvents) { + ignoringEvents = true; - if (i == 0) { - settingsController.setWakeUpMode(Pinetime::Controllers::Settings::WakeUpMode::None); - }; - if (i == 1) { - settingsController.setWakeUpMode(Pinetime::Controllers::Settings::WakeUpMode::SingleTap); - }; - if (i == 2) { - settingsController.setWakeUpMode(Pinetime::Controllers::Settings::WakeUpMode::DoubleTap); - }; - if (i == 3) { - settingsController.setWakeUpMode(Pinetime::Controllers::Settings::WakeUpMode::RaiseWrist); - }; - - } else { - lv_checkbox_set_checked(cbOption[i], false); + // Find the index of the checkbox that triggered the event + int index = 0; + for (; index < optionsTotal; ++index) { + if (cbOption[index] == object) { + break; } } + + // Toggle needed wakeup mode + auto mode = static_cast(index); + auto currentState = settingsController.isWakeUpModeOn(mode); + settingsController.setWakeUpMode(mode, !currentState); + + // Update checkbox according to current wakeup modes. + // This is needed because we can have extra logic when setting or unsetting wakeup modes, + // for example, when setting SingleTap, DoubleTap is unset and vice versa. + auto modes = settingsController.getWakeUpModes(); + for (int i = 0; i < optionsTotal; ++i) { + lv_checkbox_set_checked(cbOption[i], modes[i]); + } + + ignoringEvents = false; } -} \ No newline at end of file +} diff --git a/src/displayapp/screens/settings/SettingWakeUp.h b/src/displayapp/screens/settings/SettingWakeUp.h index 8b33eb06..248dd9ac 100644 --- a/src/displayapp/screens/settings/SettingWakeUp.h +++ b/src/displayapp/screens/settings/SettingWakeUp.h @@ -22,6 +22,11 @@ namespace Pinetime { Controllers::Settings& settingsController; uint8_t optionsTotal; lv_obj_t* cbOption[4]; + // When UpdateSelected is called, it uses lv_checkbox_set_checked, + // which can cause extra events to be fired, + // which might trigger UpdateSelected again, causing a loop. + // This variable is used as a mutex to prevent that. + bool ignoringEvents; }; } } diff --git a/src/systemtask/SystemTask.cpp b/src/systemtask/SystemTask.cpp index eb29638a..d8b965b1 100644 --- a/src/systemtask/SystemTask.cpp +++ b/src/systemtask/SystemTask.cpp @@ -211,7 +211,7 @@ void SystemTask::Work() { twiMaster.Wakeup(); // Double Tap needs the touch screen to be in normal mode - if (settingsController.getWakeUpMode() != Pinetime::Controllers::Settings::WakeUpMode::DoubleTap) { + if (!settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::DoubleTap)) { touchPanel.Wakeup(); } @@ -232,9 +232,9 @@ void SystemTask::Work() { auto touchInfo = touchPanel.GetTouchInfo(); twiMaster.Sleep(); if (touchInfo.isTouch and ((touchInfo.gesture == Pinetime::Drivers::Cst816S::Gestures::DoubleTap and - settingsController.getWakeUpMode() == Pinetime::Controllers::Settings::WakeUpMode::DoubleTap) or + settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::DoubleTap)) or (touchInfo.gesture == Pinetime::Drivers::Cst816S::Gestures::SingleTap and - settingsController.getWakeUpMode() == Pinetime::Controllers::Settings::WakeUpMode::SingleTap))) { + settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::SingleTap)))) { GoToRunning(); } } break; @@ -296,7 +296,7 @@ void SystemTask::Work() { spi.Sleep(); // Double Tap needs the touch screen to be in normal mode - if (settingsController.getWakeUpMode() != Pinetime::Controllers::Settings::WakeUpMode::DoubleTap) { + if (!settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::DoubleTap)) { touchPanel.Sleep(); } twiMaster.Sleep(); @@ -348,7 +348,7 @@ void SystemTask::UpdateMotion() { if (isGoingToSleep or isWakingUp) return; - if (isSleeping && settingsController.getWakeUpMode() != Pinetime::Controllers::Settings::WakeUpMode::RaiseWrist) + if (isSleeping && !settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::RaiseWrist)) return; if (isSleeping) @@ -399,10 +399,10 @@ void SystemTask::OnTouchEvent() { PushMessage(Messages::OnTouchEvent); displayApp.PushMessage(Pinetime::Applications::Display::Messages::TouchEvent); } else if (!isWakingUp) { - if (settingsController.getWakeUpMode() == Pinetime::Controllers::Settings::WakeUpMode::None or - settingsController.getWakeUpMode() == Pinetime::Controllers::Settings::WakeUpMode::RaiseWrist) - return; - PushMessage(Messages::TouchWakeUp); + if (settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::SingleTap) or + settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::DoubleTap)) { + PushMessage(Messages::TouchWakeUp); + } } } -- cgit v1.2.3