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 <mug66kk@gmail.com>

* Updated UI to reflect multiple WakeUp sources being available.

Signed-off-by: Kozova1 <mug66kk@gmail.com>
This commit is contained in:
Kozova1 2021-07-14 21:51:51 +03:00 committed by GitHub
parent 7133287b76
commit 57b3397078
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 73 additions and 49 deletions

View file

@ -1,5 +1,6 @@
#pragma once #pragma once
#include <cstdint> #include <cstdint>
#include <bitset>
#include "components/datetime/DateTimeController.h" #include "components/datetime/DateTimeController.h"
#include "components/brightness/BrightnessController.h" #include "components/brightness/BrightnessController.h"
#include "components/fs/FS.h" #include "components/fs/FS.h"
@ -11,7 +12,11 @@ namespace Pinetime {
public: public:
enum class ClockType : uint8_t { H24, H12 }; enum class ClockType : uint8_t { H24, H12 };
enum class Vibration : uint8_t { ON, OFF }; 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); Settings(Pinetime::Controllers::FS& fs);
@ -72,15 +77,33 @@ namespace Pinetime {
return settings.screenTimeOut; return settings.screenTimeOut;
}; };
void setWakeUpMode(WakeUpMode wakeUp) { void setWakeUpMode(WakeUpMode wakeUp, bool enabled) {
if (wakeUp != settings.wakeUpMode) { if (!isWakeUpModeOn(wakeUp)) {
settingsChanged = true; settingsChanged = true;
} }
settings.wakeUpMode = wakeUp; settings.wakeUpMode.set(static_cast<size_t>(wakeUp), enabled);
// Handle special behavior
if (enabled) {
switch (wakeUp) {
case WakeUpMode::SingleTap:
settings.wakeUpMode.set(static_cast<size_t>(WakeUpMode::DoubleTap), false);
break;
case WakeUpMode::DoubleTap:
settings.wakeUpMode.set(static_cast<size_t>(WakeUpMode::SingleTap), false);
break;
case WakeUpMode::RaiseWrist:
break;
}
}
}; };
WakeUpMode getWakeUpMode() const {
std::bitset<3> getWakeUpModes() const {
return settings.wakeUpMode; return settings.wakeUpMode;
}; }
bool isWakeUpModeOn(const WakeUpMode mode) const {
return getWakeUpModes()[static_cast<size_t>(mode)];
}
void SetBrightness(Controllers::BrightnessController::Levels level) { void SetBrightness(Controllers::BrightnessController::Levels level) {
if (level != settings.brightLevel) { if (level != settings.brightLevel) {
@ -116,7 +139,7 @@ namespace Pinetime {
uint8_t clockFace = 0; uint8_t clockFace = 0;
WakeUpMode wakeUpMode = WakeUpMode::None; std::bitset<3> wakeUpMode {0};
Controllers::BrightnessController::Levels brightLevel = Controllers::BrightnessController::Levels::Medium; Controllers::BrightnessController::Levels brightLevel = Controllers::BrightnessController::Levels::Medium;
}; };

View file

@ -16,7 +16,7 @@ namespace {
SettingWakeUp::SettingWakeUp(Pinetime::Applications::DisplayApp* app, Pinetime::Controllers::Settings& settingsController) SettingWakeUp::SettingWakeUp(Pinetime::Applications::DisplayApp* app, Pinetime::Controllers::Settings& settingsController)
: Screen(app), settingsController {settingsController} { : Screen(app), settingsController {settingsController} {
ignoringEvents = false;
lv_obj_t* container1 = lv_cont_create(lv_scr_act(), nullptr); 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); 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; optionsTotal = 0;
cbOption[optionsTotal] = lv_checkbox_create(container1, nullptr); 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"); lv_checkbox_set_text_static(cbOption[optionsTotal], " Single Tap");
cbOption[optionsTotal]->user_data = this; cbOption[optionsTotal]->user_data = this;
lv_obj_set_event_cb(cbOption[optionsTotal], event_handler); 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); lv_checkbox_set_checked(cbOption[optionsTotal], true);
} }
optionsTotal++; optionsTotal++;
@ -61,7 +53,7 @@ SettingWakeUp::SettingWakeUp(Pinetime::Applications::DisplayApp* app, Pinetime::
lv_checkbox_set_text_static(cbOption[optionsTotal], " Double Tap"); lv_checkbox_set_text_static(cbOption[optionsTotal], " Double Tap");
cbOption[optionsTotal]->user_data = this; cbOption[optionsTotal]->user_data = this;
lv_obj_set_event_cb(cbOption[optionsTotal], event_handler); 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); lv_checkbox_set_checked(cbOption[optionsTotal], true);
} }
optionsTotal++; optionsTotal++;
@ -69,7 +61,7 @@ SettingWakeUp::SettingWakeUp(Pinetime::Applications::DisplayApp* app, Pinetime::
lv_checkbox_set_text_static(cbOption[optionsTotal], " Raise Wrist"); lv_checkbox_set_text_static(cbOption[optionsTotal], " Raise Wrist");
cbOption[optionsTotal]->user_data = this; cbOption[optionsTotal]->user_data = this;
lv_obj_set_event_cb(cbOption[optionsTotal], event_handler); 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); lv_checkbox_set_checked(cbOption[optionsTotal], true);
} }
optionsTotal++; optionsTotal++;
@ -85,27 +77,31 @@ bool SettingWakeUp::Refresh() {
} }
void SettingWakeUp::UpdateSelected(lv_obj_t* object, lv_event_t event) { void SettingWakeUp::UpdateSelected(lv_obj_t* object, lv_event_t event) {
if (event == LV_EVENT_VALUE_CHANGED) { using WakeUpMode = Pinetime::Controllers::Settings::WakeUpMode;
for (int i = 0; i < optionsTotal; i++) { if (event == LV_EVENT_VALUE_CHANGED && !ignoringEvents) {
if (object == cbOption[i]) { ignoringEvents = true;
lv_checkbox_set_checked(cbOption[i], true);
if (i == 0) { // Find the index of the checkbox that triggered the event
settingsController.setWakeUpMode(Pinetime::Controllers::Settings::WakeUpMode::None); int index = 0;
}; for (; index < optionsTotal; ++index) {
if (i == 1) { if (cbOption[index] == object) {
settingsController.setWakeUpMode(Pinetime::Controllers::Settings::WakeUpMode::SingleTap); break;
};
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);
} }
} }
// Toggle needed wakeup mode
auto mode = static_cast<WakeUpMode>(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;
} }
} }

View file

@ -22,6 +22,11 @@ namespace Pinetime {
Controllers::Settings& settingsController; Controllers::Settings& settingsController;
uint8_t optionsTotal; uint8_t optionsTotal;
lv_obj_t* cbOption[4]; 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;
}; };
} }
} }

View file

@ -211,7 +211,7 @@ void SystemTask::Work() {
twiMaster.Wakeup(); twiMaster.Wakeup();
// Double Tap needs the touch screen to be in normal mode // 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(); touchPanel.Wakeup();
} }
@ -232,9 +232,9 @@ void SystemTask::Work() {
auto touchInfo = touchPanel.GetTouchInfo(); auto touchInfo = touchPanel.GetTouchInfo();
twiMaster.Sleep(); twiMaster.Sleep();
if (touchInfo.isTouch and ((touchInfo.gesture == Pinetime::Drivers::Cst816S::Gestures::DoubleTap and 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 (touchInfo.gesture == Pinetime::Drivers::Cst816S::Gestures::SingleTap and
settingsController.getWakeUpMode() == Pinetime::Controllers::Settings::WakeUpMode::SingleTap))) { settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::SingleTap)))) {
GoToRunning(); GoToRunning();
} }
} break; } break;
@ -296,7 +296,7 @@ void SystemTask::Work() {
spi.Sleep(); spi.Sleep();
// Double Tap needs the touch screen to be in normal mode // 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(); touchPanel.Sleep();
} }
twiMaster.Sleep(); twiMaster.Sleep();
@ -348,7 +348,7 @@ void SystemTask::UpdateMotion() {
if (isGoingToSleep or isWakingUp) if (isGoingToSleep or isWakingUp)
return; return;
if (isSleeping && settingsController.getWakeUpMode() != Pinetime::Controllers::Settings::WakeUpMode::RaiseWrist) if (isSleeping && !settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::RaiseWrist))
return; return;
if (isSleeping) if (isSleeping)
@ -399,10 +399,10 @@ void SystemTask::OnTouchEvent() {
PushMessage(Messages::OnTouchEvent); PushMessage(Messages::OnTouchEvent);
displayApp.PushMessage(Pinetime::Applications::Display::Messages::TouchEvent); displayApp.PushMessage(Pinetime::Applications::Display::Messages::TouchEvent);
} else if (!isWakingUp) { } else if (!isWakingUp) {
if (settingsController.getWakeUpMode() == Pinetime::Controllers::Settings::WakeUpMode::None or if (settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::SingleTap) or
settingsController.getWakeUpMode() == Pinetime::Controllers::Settings::WakeUpMode::RaiseWrist) settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::DoubleTap)) {
return; PushMessage(Messages::TouchWakeUp);
PushMessage(Messages::TouchWakeUp); }
} }
} }