Merge branch 'main' into main

This commit is contained in:
Jozef Mlich 2024-10-03 07:48:46 +02:00 committed by GitHub
commit 5bcaa4f09a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
42 changed files with 396 additions and 279 deletions

View file

@ -478,6 +478,7 @@ list(APPEND SOURCE_FILES
systemtask/SystemTask.cpp systemtask/SystemTask.cpp
systemtask/SystemMonitor.cpp systemtask/SystemMonitor.cpp
systemtask/WakeLock.cpp
drivers/TwiMaster.cpp drivers/TwiMaster.cpp
heartratetask/HeartRateTask.cpp heartratetask/HeartRateTask.cpp
@ -542,6 +543,7 @@ list(APPEND RECOVERY_SOURCE_FILES
systemtask/SystemTask.cpp systemtask/SystemTask.cpp
systemtask/SystemMonitor.cpp systemtask/SystemMonitor.cpp
systemtask/WakeLock.cpp
drivers/TwiMaster.cpp drivers/TwiMaster.cpp
components/rle/RleDecoder.cpp components/rle/RleDecoder.cpp
components/heartrate/HeartRateController.cpp components/heartrate/HeartRateController.cpp
@ -660,6 +662,7 @@ set(INCLUDE_FILES
displayapp/InfiniTimeTheme.h displayapp/InfiniTimeTheme.h
systemtask/SystemTask.h systemtask/SystemTask.h
systemtask/SystemMonitor.h systemtask/SystemMonitor.h
systemtask/WakeLock.h
displayapp/screens/Symbols.h displayapp/screens/Symbols.h
drivers/TwiMaster.h drivers/TwiMaster.h
heartratetask/HeartRateTask.h heartratetask/HeartRateTask.h
@ -860,7 +863,6 @@ target_compile_options(nrf-sdk PRIVATE
$<$<CONFIG:RELEASE>: ${RELEASE_FLAGS}> $<$<CONFIG:RELEASE>: ${RELEASE_FLAGS}>
$<$<COMPILE_LANGUAGE:CXX>: ${CXX_FLAGS}> $<$<COMPILE_LANGUAGE:CXX>: ${CXX_FLAGS}>
$<$<COMPILE_LANGUAGE:ASM>: ${ASM_FLAGS}> $<$<COMPILE_LANGUAGE:ASM>: ${ASM_FLAGS}>
-O3
) )
# NimBLE # NimBLE

View file

@ -19,11 +19,13 @@
#include "systemtask/SystemTask.h" #include "systemtask/SystemTask.h"
#include "task.h" #include "task.h"
#include <chrono> #include <chrono>
#include <libraries/log/nrf_log.h>
using namespace Pinetime::Controllers; using namespace Pinetime::Controllers;
using namespace std::chrono_literals; using namespace std::chrono_literals;
AlarmController::AlarmController(Controllers::DateTime& dateTimeController) : dateTimeController {dateTimeController} { AlarmController::AlarmController(Controllers::DateTime& dateTimeController, Controllers::FS& fs)
: dateTimeController {dateTimeController}, fs {fs} {
} }
namespace { namespace {
@ -36,11 +38,28 @@ namespace {
void AlarmController::Init(System::SystemTask* systemTask) { void AlarmController::Init(System::SystemTask* systemTask) {
this->systemTask = systemTask; this->systemTask = systemTask;
alarmTimer = xTimerCreate("Alarm", 1, pdFALSE, this, SetOffAlarm); alarmTimer = xTimerCreate("Alarm", 1, pdFALSE, this, SetOffAlarm);
LoadSettingsFromFile();
if (alarm.isEnabled) {
NRF_LOG_INFO("[AlarmController] Loaded alarm was enabled, scheduling");
ScheduleAlarm();
}
}
void AlarmController::SaveAlarm() {
// verify if it is necessary to save
if (alarmChanged) {
SaveSettingsToFile();
}
alarmChanged = false;
} }
void AlarmController::SetAlarmTime(uint8_t alarmHr, uint8_t alarmMin) { void AlarmController::SetAlarmTime(uint8_t alarmHr, uint8_t alarmMin) {
hours = alarmHr; if (alarm.hours == alarmHr && alarm.minutes == alarmMin) {
minutes = alarmMin; return;
}
alarm.hours = alarmHr;
alarm.minutes = alarmMin;
alarmChanged = true;
} }
void AlarmController::ScheduleAlarm() { void AlarmController::ScheduleAlarm() {
@ -53,18 +72,19 @@ void AlarmController::ScheduleAlarm() {
tm* tmAlarmTime = std::localtime(&ttAlarmTime); tm* tmAlarmTime = std::localtime(&ttAlarmTime);
// If the time being set has already passed today,the alarm should be set for tomorrow // If the time being set has already passed today,the alarm should be set for tomorrow
if (hours < dateTimeController.Hours() || (hours == dateTimeController.Hours() && minutes <= dateTimeController.Minutes())) { if (alarm.hours < dateTimeController.Hours() ||
(alarm.hours == dateTimeController.Hours() && alarm.minutes <= dateTimeController.Minutes())) {
tmAlarmTime->tm_mday += 1; tmAlarmTime->tm_mday += 1;
// tm_wday doesn't update automatically // tm_wday doesn't update automatically
tmAlarmTime->tm_wday = (tmAlarmTime->tm_wday + 1) % 7; tmAlarmTime->tm_wday = (tmAlarmTime->tm_wday + 1) % 7;
} }
tmAlarmTime->tm_hour = hours; tmAlarmTime->tm_hour = alarm.hours;
tmAlarmTime->tm_min = minutes; tmAlarmTime->tm_min = alarm.minutes;
tmAlarmTime->tm_sec = 0; tmAlarmTime->tm_sec = 0;
// if alarm is in weekday-only mode, make sure it shifts to the next weekday // if alarm is in weekday-only mode, make sure it shifts to the next weekday
if (recurrence == RecurType::Weekdays) { if (alarm.recurrence == RecurType::Weekdays) {
if (tmAlarmTime->tm_wday == 0) { // Sunday, shift 1 day if (tmAlarmTime->tm_wday == 0) { // Sunday, shift 1 day
tmAlarmTime->tm_mday += 1; tmAlarmTime->tm_mday += 1;
} else if (tmAlarmTime->tm_wday == 6) { // Saturday, shift 2 days } else if (tmAlarmTime->tm_wday == 6) { // Saturday, shift 2 days
@ -79,7 +99,10 @@ void AlarmController::ScheduleAlarm() {
xTimerChangePeriod(alarmTimer, secondsToAlarm * configTICK_RATE_HZ, 0); xTimerChangePeriod(alarmTimer, secondsToAlarm * configTICK_RATE_HZ, 0);
xTimerStart(alarmTimer, 0); xTimerStart(alarmTimer, 0);
state = AlarmState::Set; if (!alarm.isEnabled) {
alarm.isEnabled = true;
alarmChanged = true;
}
} }
uint32_t AlarmController::SecondsToAlarm() const { uint32_t AlarmController::SecondsToAlarm() const {
@ -88,20 +111,72 @@ uint32_t AlarmController::SecondsToAlarm() const {
void AlarmController::DisableAlarm() { void AlarmController::DisableAlarm() {
xTimerStop(alarmTimer, 0); xTimerStop(alarmTimer, 0);
state = AlarmState::Not_Set; isAlerting = false;
if (alarm.isEnabled) {
alarm.isEnabled = false;
alarmChanged = true;
}
} }
void AlarmController::SetOffAlarmNow() { void AlarmController::SetOffAlarmNow() {
state = AlarmState::Alerting; isAlerting = true;
systemTask->PushMessage(System::Messages::SetOffAlarm); systemTask->PushMessage(System::Messages::SetOffAlarm);
} }
void AlarmController::StopAlerting() { void AlarmController::StopAlerting() {
// Alarm state is off unless this is a recurring alarm isAlerting = false;
if (recurrence == RecurType::None) { // Disable alarm unless it is recurring
state = AlarmState::Not_Set; if (alarm.recurrence == RecurType::None) {
alarm.isEnabled = false;
alarmChanged = true;
} else { } else {
// set next instance // set next instance
ScheduleAlarm(); ScheduleAlarm();
} }
} }
void AlarmController::SetRecurrence(RecurType recurrence) {
if (alarm.recurrence != recurrence) {
alarm.recurrence = recurrence;
alarmChanged = true;
}
}
void AlarmController::LoadSettingsFromFile() {
lfs_file_t alarmFile;
AlarmSettings alarmBuffer;
if (fs.FileOpen(&alarmFile, "/.system/alarm.dat", LFS_O_RDONLY) != LFS_ERR_OK) {
NRF_LOG_WARNING("[AlarmController] Failed to open alarm data file");
return;
}
fs.FileRead(&alarmFile, reinterpret_cast<uint8_t*>(&alarmBuffer), sizeof(alarmBuffer));
fs.FileClose(&alarmFile);
if (alarmBuffer.version != alarmFormatVersion) {
NRF_LOG_WARNING("[AlarmController] Loaded alarm settings has version %u instead of %u, discarding",
alarmBuffer.version,
alarmFormatVersion);
return;
}
alarm = alarmBuffer;
NRF_LOG_INFO("[AlarmController] Loaded alarm settings from file");
}
void AlarmController::SaveSettingsToFile() const {
lfs_dir systemDir;
if (fs.DirOpen("/.system", &systemDir) != LFS_ERR_OK) {
fs.DirCreate("/.system");
}
fs.DirClose(&systemDir);
lfs_file_t alarmFile;
if (fs.FileOpen(&alarmFile, "/.system/alarm.dat", LFS_O_WRONLY | LFS_O_CREAT) != LFS_ERR_OK) {
NRF_LOG_WARNING("[AlarmController] Failed to open alarm data file for saving");
return;
}
fs.FileWrite(&alarmFile, reinterpret_cast<const uint8_t*>(&alarm), sizeof(alarm));
fs.FileClose(&alarmFile);
NRF_LOG_INFO("[AlarmController] Saved alarm settings with format version %u to file", alarm.version);
}

View file

@ -30,47 +30,65 @@ namespace Pinetime {
namespace Controllers { namespace Controllers {
class AlarmController { class AlarmController {
public: public:
AlarmController(Controllers::DateTime& dateTimeController); AlarmController(Controllers::DateTime& dateTimeController, Controllers::FS& fs);
void Init(System::SystemTask* systemTask); void Init(System::SystemTask* systemTask);
void SaveAlarm();
void SetAlarmTime(uint8_t alarmHr, uint8_t alarmMin); void SetAlarmTime(uint8_t alarmHr, uint8_t alarmMin);
void ScheduleAlarm(); void ScheduleAlarm();
void DisableAlarm(); void DisableAlarm();
void SetOffAlarmNow(); void SetOffAlarmNow();
uint32_t SecondsToAlarm() const; uint32_t SecondsToAlarm() const;
void StopAlerting(); void StopAlerting();
enum class AlarmState { Not_Set, Set, Alerting };
enum class RecurType { None, Daily, Weekdays }; enum class RecurType { None, Daily, Weekdays };
uint8_t Hours() const { uint8_t Hours() const {
return hours; return alarm.hours;
} }
uint8_t Minutes() const { uint8_t Minutes() const {
return minutes; return alarm.minutes;
} }
AlarmState State() const { bool IsAlerting() const {
return state; return isAlerting;
}
bool IsEnabled() const {
return alarm.isEnabled;
} }
RecurType Recurrence() const { RecurType Recurrence() const {
return recurrence; return alarm.recurrence;
} }
void SetRecurrence(RecurType recurType) { void SetRecurrence(RecurType recurrence);
recurrence = recurType;
}
private: private:
// Versions 255 is reserved for now, so the version field can be made
// bigger, should it ever be needed.
static constexpr uint8_t alarmFormatVersion = 1;
struct AlarmSettings {
uint8_t version = alarmFormatVersion;
uint8_t hours = 7;
uint8_t minutes = 0;
RecurType recurrence = RecurType::None;
bool isEnabled = false;
};
bool isAlerting = false;
bool alarmChanged = false;
Controllers::DateTime& dateTimeController; Controllers::DateTime& dateTimeController;
Controllers::FS& fs;
System::SystemTask* systemTask = nullptr; System::SystemTask* systemTask = nullptr;
TimerHandle_t alarmTimer; TimerHandle_t alarmTimer;
uint8_t hours = 7; AlarmSettings alarm;
uint8_t minutes = 0;
std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds> alarmTime; std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds> alarmTime;
AlarmState state = AlarmState::Not_Set;
RecurType recurrence = RecurType::None; void LoadSettingsFromFile();
void SaveSettingsToFile() const;
}; };
} }
} }

View file

@ -124,9 +124,11 @@ int DfuService::WritePacketHandler(uint16_t connectionHandle, os_mbuf* om) {
bootloaderSize, bootloaderSize,
applicationSize); applicationSize);
// wait until SystemTask has finished waking up all devices // Wait until SystemTask has disabled sleeping
while (systemTask.IsSleeping()) { // This isn't quite correct, as we don't actually know
vTaskDelay(50); // 50ms // if BleFirmwareUpdateStarted has been received yet
while (!systemTask.IsSleepDisabled()) {
vTaskDelay(pdMS_TO_TICKS(5));
} }
dfuImage.Erase(); dfuImage.Erase();

View file

@ -18,6 +18,8 @@
#include "components/ble/MusicService.h" #include "components/ble/MusicService.h"
#include "components/ble/NimbleController.h" #include "components/ble/NimbleController.h"
#include <cstring> #include <cstring>
#include <FreeRTOS.h>
#include <task.h>
namespace { namespace {
// 0000yyxx-78fc-48fe-8e23-433b3a1942d0 // 0000yyxx-78fc-48fe-8e23-433b3a1942d0

View file

@ -25,6 +25,7 @@
#include <host/ble_uuid.h> #include <host/ble_uuid.h>
#undef max #undef max
#undef min #undef min
#include <FreeRTOS.h>
namespace Pinetime { namespace Pinetime {
namespace Controllers { namespace Controllers {

View file

@ -454,9 +454,15 @@ void NimbleController::PersistBond(struct ble_gap_conn_desc& desc) {
/* Wakeup Spi and SpiNorFlash before accessing the file system /* Wakeup Spi and SpiNorFlash before accessing the file system
* This should be fixed in the FS driver * This should be fixed in the FS driver
*/ */
systemTask.PushMessage(Pinetime::System::Messages::GoToRunning);
systemTask.PushMessage(Pinetime::System::Messages::DisableSleeping); systemTask.PushMessage(Pinetime::System::Messages::DisableSleeping);
vTaskDelay(10);
// This isn't quite correct
// SystemTask could receive EnableSleeping right after passing this check
// We need some guarantee that the SystemTask has processed the above message
// before we can continue
while (!systemTask.IsSleepDisabled()) {
vTaskDelay(pdMS_TO_TICKS(5));
}
lfs_file_t file_p; lfs_file_t file_p;

View file

@ -142,7 +142,7 @@ Ppg::Ppg() {
spectrum.fill(0.0f); spectrum.fill(0.0f);
} }
int8_t Ppg::Preprocess(uint32_t hrs, uint32_t als) { int8_t Ppg::Preprocess(uint16_t hrs, uint16_t als) {
if (dataIndex < dataLength) { if (dataIndex < dataLength) {
dataHRS[dataIndex++] = hrs; dataHRS[dataIndex++] = hrs;
} }

View file

@ -14,7 +14,7 @@ namespace Pinetime {
class Ppg { class Ppg {
public: public:
Ppg(); Ppg();
int8_t Preprocess(uint32_t hrs, uint32_t als); int8_t Preprocess(uint16_t hrs, uint16_t als);
int HeartRate(); int HeartRate();
void Reset(bool resetDaqBuffer); void Reset(bool resetDaqBuffer);
static constexpr int deltaTms = 100; static constexpr int deltaTms = 100;

View file

@ -209,21 +209,6 @@ void DisplayApp::Refresh() {
LoadScreen(returnAppStack.Pop(), returnDirection); LoadScreen(returnAppStack.Pop(), returnDirection);
}; };
auto DimScreen = [this]() {
if (brightnessController.Level() != Controllers::BrightnessController::Levels::Off) {
isDimmed = true;
brightnessController.Set(Controllers::BrightnessController::Levels::Low);
}
};
auto RestoreBrightness = [this]() {
if (brightnessController.Level() != Controllers::BrightnessController::Levels::Off) {
isDimmed = false;
lv_disp_trig_activity(nullptr);
ApplyBrightness();
}
};
auto IsPastDimTime = [this]() -> bool { auto IsPastDimTime = [this]() -> bool {
return lv_disp_get_inactive_time(nullptr) >= pdMS_TO_TICKS(settingsController.GetScreenTimeOut() - 2000); return lv_disp_get_inactive_time(nullptr) >= pdMS_TO_TICKS(settingsController.GetScreenTimeOut() - 2000);
}; };
@ -267,14 +252,27 @@ void DisplayApp::Refresh() {
if (!systemTask->IsSleepDisabled() && IsPastDimTime()) { if (!systemTask->IsSleepDisabled() && IsPastDimTime()) {
if (!isDimmed) { if (!isDimmed) {
DimScreen(); isDimmed = true;
brightnessController.Set(Controllers::BrightnessController::Levels::Low);
} }
if (IsPastSleepTime()) { if (IsPastSleepTime() && uxQueueMessagesWaiting(msgQueue) == 0) {
systemTask->PushMessage(System::Messages::GoToSleep); PushMessageToSystemTask(System::Messages::GoToSleep);
state = States::Idle; // Can't set state to Idle here, something may send
// DisableSleeping before this GoToSleep arrives
// Instead we check we have no messages queued before sending GoToSleep
// This works as the SystemTask is higher priority than DisplayApp
// As soon as we send GoToSleep, SystemTask pre-empts DisplayApp
// Whenever DisplayApp is running again, it is guaranteed that
// SystemTask has handled the message
// If it responded, we will have a GoToSleep waiting in the queue
// By checking that there are no messages in the queue, we avoid
// resending GoToSleep when we already have a response
// SystemTask is resilient to duplicate messages, this is an
// optimisation to reduce pressure on the message queues
} }
} else if (isDimmed) { } else if (isDimmed) {
RestoreBrightness(); isDimmed = false;
ApplyBrightness();
} }
break; break;
default: default:
@ -285,10 +283,10 @@ void DisplayApp::Refresh() {
Messages msg; Messages msg;
if (xQueueReceive(msgQueue, &msg, queueTimeout) == pdTRUE) { if (xQueueReceive(msgQueue, &msg, queueTimeout) == pdTRUE) {
switch (msg) { switch (msg) {
case Messages::DimScreen:
DimScreen();
break;
case Messages::GoToSleep: case Messages::GoToSleep:
if (state != States::Running) {
break;
}
while (brightnessController.Level() != Controllers::BrightnessController::Levels::Low) { while (brightnessController.Level() != Controllers::BrightnessController::Levels::Low) {
brightnessController.Lower(); brightnessController.Lower();
vTaskDelay(100); vTaskDelay(100);
@ -323,6 +321,9 @@ void DisplayApp::Refresh() {
lv_disp_trig_activity(nullptr); lv_disp_trig_activity(nullptr);
break; break;
case Messages::GoToRunning: case Messages::GoToRunning:
if (state == States::Running) {
break;
}
if (settingsController.GetAlwaysOnDisplay()) { if (settingsController.GetAlwaysOnDisplay()) {
lcd.LowPowerOff(); lcd.LowPowerOff();
} else { } else {
@ -333,8 +334,7 @@ void DisplayApp::Refresh() {
state = States::Running; state = States::Running;
break; break;
case Messages::UpdateBleConnection: case Messages::UpdateBleConnection:
// clockScreen.SetBleConnectionState(bleController.IsConnected() ? Screens::Clock::BleConnectionStates::Connected : // Only used for recovery firmware
// Screens::Clock::BleConnectionStates::NotConnected);
break; break;
case Messages::NewNotification: case Messages::NewNotification:
LoadNewScreen(Apps::NotificationsPreview, DisplayApp::FullRefreshDirections::Down); LoadNewScreen(Apps::NotificationsPreview, DisplayApp::FullRefreshDirections::Down);
@ -449,16 +449,11 @@ void DisplayApp::Refresh() {
case Messages::BleRadioEnableToggle: case Messages::BleRadioEnableToggle:
PushMessageToSystemTask(System::Messages::BleRadioEnableToggle); PushMessageToSystemTask(System::Messages::BleRadioEnableToggle);
break; break;
case Messages::UpdateDateTime:
// Added to remove warning
// What should happen here?
break;
case Messages::Chime: case Messages::Chime:
LoadNewScreen(Apps::Clock, DisplayApp::FullRefreshDirections::None); LoadNewScreen(Apps::Clock, DisplayApp::FullRefreshDirections::None);
motorController.RunForDuration(35); motorController.RunForDuration(35);
break; break;
case Messages::OnChargingEvent: case Messages::OnChargingEvent:
RestoreBrightness();
motorController.RunForDuration(15); motorController.RunForDuration(15);
break; break;
} }
@ -589,7 +584,7 @@ void DisplayApp::LoadScreen(Apps app, DisplayApp::FullRefreshDirections directio
currentScreen = std::make_unique<Screens::SettingWakeUp>(settingsController); currentScreen = std::make_unique<Screens::SettingWakeUp>(settingsController);
break; break;
case Apps::SettingDisplay: case Apps::SettingDisplay:
currentScreen = std::make_unique<Screens::SettingDisplay>(this, settingsController); currentScreen = std::make_unique<Screens::SettingDisplay>(settingsController);
break; break;
case Apps::SettingSteps: case Apps::SettingSteps:
currentScreen = std::make_unique<Screens::SettingSteps>(settingsController); currentScreen = std::make_unique<Screens::SettingSteps>(settingsController);

View file

@ -7,7 +7,6 @@ namespace Pinetime {
enum class Messages : uint8_t { enum class Messages : uint8_t {
GoToSleep, GoToSleep,
GoToRunning, GoToRunning,
UpdateDateTime,
UpdateBleConnection, UpdateBleConnection,
TouchEvent, TouchEvent,
ButtonPushed, ButtonPushed,
@ -17,7 +16,8 @@ namespace Pinetime {
NewNotification, NewNotification,
TimerDone, TimerDone,
BleFirmwareUpdateStarted, BleFirmwareUpdateStarted,
DimScreen, // Resets the screen timeout timer when awake
// Does nothing when asleep
NotifyDeviceActivity, NotifyDeviceActivity,
ShowPairingKey, ShowPairingKey,
AlarmTriggered, AlarmTriggered,

View file

@ -48,7 +48,7 @@ Alarm::Alarm(Controllers::AlarmController& alarmController,
Controllers::Settings::ClockType clockType, Controllers::Settings::ClockType clockType,
System::SystemTask& systemTask, System::SystemTask& systemTask,
Controllers::MotorController& motorController) Controllers::MotorController& motorController)
: alarmController {alarmController}, systemTask {systemTask}, motorController {motorController} { : alarmController {alarmController}, wakeLock(systemTask), motorController {motorController} {
hourCounter.Create(); hourCounter.Create();
lv_obj_align(hourCounter.GetObject(), nullptr, LV_ALIGN_IN_TOP_LEFT, 0, 0); lv_obj_align(hourCounter.GetObject(), nullptr, LV_ALIGN_IN_TOP_LEFT, 0, 0);
@ -117,7 +117,7 @@ Alarm::Alarm(Controllers::AlarmController& alarmController,
UpdateAlarmTime(); UpdateAlarmTime();
if (alarmController.State() == Controllers::AlarmController::AlarmState::Alerting) { if (alarmController.IsAlerting()) {
SetAlerting(); SetAlerting();
} else { } else {
SetSwitchState(LV_ANIM_OFF); SetSwitchState(LV_ANIM_OFF);
@ -125,14 +125,15 @@ Alarm::Alarm(Controllers::AlarmController& alarmController,
} }
Alarm::~Alarm() { Alarm::~Alarm() {
if (alarmController.State() == AlarmController::AlarmState::Alerting) { if (alarmController.IsAlerting()) {
StopAlerting(); StopAlerting();
} }
lv_obj_clean(lv_scr_act()); lv_obj_clean(lv_scr_act());
alarmController.SaveAlarm();
} }
void Alarm::DisableAlarm() { void Alarm::DisableAlarm() {
if (alarmController.State() == AlarmController::AlarmState::Set) { if (alarmController.IsEnabled()) {
alarmController.DisableAlarm(); alarmController.DisableAlarm();
lv_switch_off(enableSwitch, LV_ANIM_ON); lv_switch_off(enableSwitch, LV_ANIM_ON);
} }
@ -172,7 +173,7 @@ bool Alarm::OnButtonPushed() {
HideInfo(); HideInfo();
return true; return true;
} }
if (alarmController.State() == AlarmController::AlarmState::Alerting) { if (alarmController.IsAlerting()) {
StopAlerting(); StopAlerting();
return true; return true;
} }
@ -181,7 +182,7 @@ bool Alarm::OnButtonPushed() {
bool Alarm::OnTouchEvent(Pinetime::Applications::TouchEvents event) { bool Alarm::OnTouchEvent(Pinetime::Applications::TouchEvents event) {
// Don't allow closing the screen by swiping while the alarm is alerting // Don't allow closing the screen by swiping while the alarm is alerting
return alarmController.State() == AlarmController::AlarmState::Alerting && event == TouchEvents::SwipeDown; return alarmController.IsAlerting() && event == TouchEvents::SwipeDown;
} }
void Alarm::OnValueChanged() { void Alarm::OnValueChanged() {
@ -205,7 +206,7 @@ void Alarm::SetAlerting() {
lv_obj_set_hidden(btnStop, false); lv_obj_set_hidden(btnStop, false);
taskStopAlarm = lv_task_create(StopAlarmTaskCallback, pdMS_TO_TICKS(60 * 1000), LV_TASK_PRIO_MID, this); taskStopAlarm = lv_task_create(StopAlarmTaskCallback, pdMS_TO_TICKS(60 * 1000), LV_TASK_PRIO_MID, this);
motorController.StartRinging(); motorController.StartRinging();
systemTask.PushMessage(System::Messages::DisableSleeping); wakeLock.Lock();
} }
void Alarm::StopAlerting() { void Alarm::StopAlerting() {
@ -216,21 +217,16 @@ void Alarm::StopAlerting() {
lv_task_del(taskStopAlarm); lv_task_del(taskStopAlarm);
taskStopAlarm = nullptr; taskStopAlarm = nullptr;
} }
systemTask.PushMessage(System::Messages::EnableSleeping); wakeLock.Release();
lv_obj_set_hidden(enableSwitch, false); lv_obj_set_hidden(enableSwitch, false);
lv_obj_set_hidden(btnStop, true); lv_obj_set_hidden(btnStop, true);
} }
void Alarm::SetSwitchState(lv_anim_enable_t anim) { void Alarm::SetSwitchState(lv_anim_enable_t anim) {
switch (alarmController.State()) { if (alarmController.IsEnabled()) {
case AlarmController::AlarmState::Set: lv_switch_on(enableSwitch, anim);
lv_switch_on(enableSwitch, anim); } else {
break; lv_switch_off(enableSwitch, anim);
case AlarmController::AlarmState::Not_Set:
lv_switch_off(enableSwitch, anim);
break;
default:
break;
} }
} }
@ -247,7 +243,7 @@ void Alarm::ShowInfo() {
txtMessage = lv_label_create(btnMessage, nullptr); txtMessage = lv_label_create(btnMessage, nullptr);
lv_obj_set_style_local_bg_color(btnMessage, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_NAVY); lv_obj_set_style_local_bg_color(btnMessage, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_NAVY);
if (alarmController.State() == AlarmController::AlarmState::Set) { if (alarmController.IsEnabled()) {
auto timeToAlarm = alarmController.SecondsToAlarm(); auto timeToAlarm = alarmController.SecondsToAlarm();
auto daysToAlarm = timeToAlarm / 86400; auto daysToAlarm = timeToAlarm / 86400;

View file

@ -22,6 +22,7 @@
#include "displayapp/screens/Screen.h" #include "displayapp/screens/Screen.h"
#include "displayapp/widgets/Counter.h" #include "displayapp/widgets/Counter.h"
#include "displayapp/Controllers.h" #include "displayapp/Controllers.h"
#include "systemtask/WakeLock.h"
#include "Symbols.h" #include "Symbols.h"
namespace Pinetime { namespace Pinetime {
@ -43,7 +44,7 @@ namespace Pinetime {
private: private:
Controllers::AlarmController& alarmController; Controllers::AlarmController& alarmController;
System::SystemTask& systemTask; System::WakeLock wakeLock;
Controllers::MotorController& motorController; Controllers::MotorController& motorController;
lv_obj_t *btnStop, *txtStop, *btnRecur, *txtRecur, *btnInfo, *enableSwitch; lv_obj_t *btnStop, *txtStop, *btnRecur, *txtRecur, *btnInfo, *enableSwitch;

View file

@ -15,7 +15,7 @@ namespace {
} }
FlashLight::FlashLight(System::SystemTask& systemTask, Controllers::BrightnessController& brightnessController) FlashLight::FlashLight(System::SystemTask& systemTask, Controllers::BrightnessController& brightnessController)
: systemTask {systemTask}, brightnessController {brightnessController} { : wakeLock(systemTask), brightnessController {brightnessController} {
previousBrightnessLevel = brightnessController.Level(); previousBrightnessLevel = brightnessController.Level();
brightnessController.Set(Controllers::BrightnessController::Levels::Low); brightnessController.Set(Controllers::BrightnessController::Levels::Low);
@ -47,14 +47,13 @@ FlashLight::FlashLight(System::SystemTask& systemTask, Controllers::BrightnessCo
backgroundAction->user_data = this; backgroundAction->user_data = this;
lv_obj_set_event_cb(backgroundAction, EventHandler); lv_obj_set_event_cb(backgroundAction, EventHandler);
systemTask.PushMessage(Pinetime::System::Messages::DisableSleeping); wakeLock.Lock();
} }
FlashLight::~FlashLight() { FlashLight::~FlashLight() {
lv_obj_clean(lv_scr_act()); lv_obj_clean(lv_scr_act());
lv_obj_set_style_local_bg_color(lv_scr_act(), LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK); lv_obj_set_style_local_bg_color(lv_scr_act(), LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK);
brightnessController.Set(previousBrightnessLevel); brightnessController.Set(previousBrightnessLevel);
systemTask.PushMessage(Pinetime::System::Messages::EnableSleeping);
} }
void FlashLight::SetColors() { void FlashLight::SetColors() {

View file

@ -3,6 +3,7 @@
#include "displayapp/screens/Screen.h" #include "displayapp/screens/Screen.h"
#include "components/brightness/BrightnessController.h" #include "components/brightness/BrightnessController.h"
#include "systemtask/SystemTask.h" #include "systemtask/SystemTask.h"
#include "systemtask/WakeLock.h"
#include <cstdint> #include <cstdint>
#include <lvgl/lvgl.h> #include <lvgl/lvgl.h>
@ -23,7 +24,7 @@ namespace Pinetime {
void SetIndicators(); void SetIndicators();
void SetColors(); void SetColors();
Pinetime::System::SystemTask& systemTask; Pinetime::System::WakeLock wakeLock;
Controllers::BrightnessController& brightnessController; Controllers::BrightnessController& brightnessController;
Controllers::BrightnessController::Levels brightnessLevel = Controllers::BrightnessController::Levels::High; Controllers::BrightnessController::Levels brightnessLevel = Controllers::BrightnessController::Levels::High;

View file

@ -29,7 +29,7 @@ namespace {
} }
HeartRate::HeartRate(Controllers::HeartRateController& heartRateController, System::SystemTask& systemTask) HeartRate::HeartRate(Controllers::HeartRateController& heartRateController, System::SystemTask& systemTask)
: heartRateController {heartRateController}, systemTask {systemTask} { : heartRateController {heartRateController}, wakeLock(systemTask) {
bool isHrRunning = heartRateController.State() != Controllers::HeartRateController::States::Stopped; bool isHrRunning = heartRateController.State() != Controllers::HeartRateController::States::Stopped;
label_hr = lv_label_create(lv_scr_act(), nullptr); label_hr = lv_label_create(lv_scr_act(), nullptr);
@ -63,7 +63,7 @@ HeartRate::HeartRate(Controllers::HeartRateController& heartRateController, Syst
label_startStop = lv_label_create(btn_startStop, nullptr); label_startStop = lv_label_create(btn_startStop, nullptr);
UpdateStartStopButton(isHrRunning); UpdateStartStopButton(isHrRunning);
if (isHrRunning) { if (isHrRunning) {
systemTask.PushMessage(Pinetime::System::Messages::DisableSleeping); wakeLock.Lock();
} }
taskRefresh = lv_task_create(RefreshTaskCallback, 100, LV_TASK_PRIO_MID, this); taskRefresh = lv_task_create(RefreshTaskCallback, 100, LV_TASK_PRIO_MID, this);
@ -72,7 +72,6 @@ HeartRate::HeartRate(Controllers::HeartRateController& heartRateController, Syst
HeartRate::~HeartRate() { HeartRate::~HeartRate() {
lv_task_del(taskRefresh); lv_task_del(taskRefresh);
lv_obj_clean(lv_scr_act()); lv_obj_clean(lv_scr_act());
systemTask.PushMessage(Pinetime::System::Messages::EnableSleeping);
} }
void HeartRate::Refresh() { void HeartRate::Refresh() {
@ -101,12 +100,12 @@ void HeartRate::OnStartStopEvent(lv_event_t event) {
if (heartRateController.State() == Controllers::HeartRateController::States::Stopped) { if (heartRateController.State() == Controllers::HeartRateController::States::Stopped) {
heartRateController.Start(); heartRateController.Start();
UpdateStartStopButton(heartRateController.State() != Controllers::HeartRateController::States::Stopped); UpdateStartStopButton(heartRateController.State() != Controllers::HeartRateController::States::Stopped);
systemTask.PushMessage(Pinetime::System::Messages::DisableSleeping); wakeLock.Lock();
lv_obj_set_style_local_text_color(label_hr, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::highlight); lv_obj_set_style_local_text_color(label_hr, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::highlight);
} else { } else {
heartRateController.Stop(); heartRateController.Stop();
UpdateStartStopButton(heartRateController.State() != Controllers::HeartRateController::States::Stopped); UpdateStartStopButton(heartRateController.State() != Controllers::HeartRateController::States::Stopped);
systemTask.PushMessage(Pinetime::System::Messages::EnableSleeping); wakeLock.Release();
lv_obj_set_style_local_text_color(label_hr, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::lightGray); lv_obj_set_style_local_text_color(label_hr, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::lightGray);
} }
} }

View file

@ -4,6 +4,7 @@
#include <chrono> #include <chrono>
#include "displayapp/screens/Screen.h" #include "displayapp/screens/Screen.h"
#include "systemtask/SystemTask.h" #include "systemtask/SystemTask.h"
#include "systemtask/WakeLock.h"
#include "Symbols.h" #include "Symbols.h"
#include <lvgl/src/lv_core/lv_style.h> #include <lvgl/src/lv_core/lv_style.h>
#include <lvgl/src/lv_core/lv_obj.h> #include <lvgl/src/lv_core/lv_obj.h>
@ -27,7 +28,7 @@ namespace Pinetime {
private: private:
Controllers::HeartRateController& heartRateController; Controllers::HeartRateController& heartRateController;
Pinetime::System::SystemTask& systemTask; Pinetime::System::WakeLock wakeLock;
void UpdateStartStopButton(bool isRunning); void UpdateStartStopButton(bool isRunning);
lv_obj_t* label_hr; lv_obj_t* label_hr;
lv_obj_t* label_bpm; lv_obj_t* label_bpm;

View file

@ -22,7 +22,7 @@ namespace {
} }
Metronome::Metronome(Controllers::MotorController& motorController, System::SystemTask& systemTask) Metronome::Metronome(Controllers::MotorController& motorController, System::SystemTask& systemTask)
: motorController {motorController}, systemTask {systemTask} { : motorController {motorController}, wakeLock(systemTask) {
bpmArc = lv_arc_create(lv_scr_act(), nullptr); bpmArc = lv_arc_create(lv_scr_act(), nullptr);
bpmArc->user_data = this; bpmArc->user_data = this;
@ -72,7 +72,6 @@ Metronome::Metronome(Controllers::MotorController& motorController, System::Syst
Metronome::~Metronome() { Metronome::~Metronome() {
lv_task_del(taskRefresh); lv_task_del(taskRefresh);
systemTask.PushMessage(System::Messages::EnableSleeping);
lv_obj_clean(lv_scr_act()); lv_obj_clean(lv_scr_act());
} }
@ -128,12 +127,12 @@ void Metronome::OnEvent(lv_obj_t* obj, lv_event_t event) {
metronomeStarted = !metronomeStarted; metronomeStarted = !metronomeStarted;
if (metronomeStarted) { if (metronomeStarted) {
lv_label_set_text_static(lblPlayPause, Symbols::pause); lv_label_set_text_static(lblPlayPause, Symbols::pause);
systemTask.PushMessage(System::Messages::DisableSleeping); wakeLock.Lock();
startTime = xTaskGetTickCount(); startTime = xTaskGetTickCount();
counter = 1; counter = 1;
} else { } else {
lv_label_set_text_static(lblPlayPause, Symbols::play); lv_label_set_text_static(lblPlayPause, Symbols::play);
systemTask.PushMessage(System::Messages::EnableSleeping); wakeLock.Release();
} }
} }
break; break;

View file

@ -1,6 +1,7 @@
#pragma once #pragma once
#include "systemtask/SystemTask.h" #include "systemtask/SystemTask.h"
#include "systemtask/WakeLock.h"
#include "components/motor/MotorController.h" #include "components/motor/MotorController.h"
#include "displayapp/screens/Screen.h" #include "displayapp/screens/Screen.h"
#include "Symbols.h" #include "Symbols.h"
@ -21,7 +22,7 @@ namespace Pinetime {
TickType_t startTime = 0; TickType_t startTime = 0;
TickType_t tappedTime = 0; TickType_t tappedTime = 0;
Controllers::MotorController& motorController; Controllers::MotorController& motorController;
System::SystemTask& systemTask; System::WakeLock wakeLock;
int16_t bpm = 120; int16_t bpm = 120;
uint8_t bpb = 4; uint8_t bpb = 4;
uint8_t counter = 1; uint8_t counter = 1;

View file

@ -20,7 +20,7 @@ Notifications::Notifications(DisplayApp* app,
notificationManager {notificationManager}, notificationManager {notificationManager},
alertNotificationService {alertNotificationService}, alertNotificationService {alertNotificationService},
motorController {motorController}, motorController {motorController},
systemTask {systemTask}, wakeLock(systemTask),
mode {mode} { mode {mode} {
notificationManager.ClearNewNotificationFlag(); notificationManager.ClearNewNotificationFlag();
@ -40,7 +40,7 @@ Notifications::Notifications(DisplayApp* app,
validDisplay = false; validDisplay = false;
} }
if (mode == Modes::Preview) { if (mode == Modes::Preview) {
systemTask.PushMessage(System::Messages::DisableSleeping); wakeLock.Lock();
if (notification.category == Controllers::NotificationManager::Categories::IncomingCall) { if (notification.category == Controllers::NotificationManager::Categories::IncomingCall) {
motorController.StartRinging(); motorController.StartRinging();
} else { } else {
@ -65,7 +65,6 @@ Notifications::~Notifications() {
lv_task_del(taskRefresh); lv_task_del(taskRefresh);
// make sure we stop any vibrations before exiting // make sure we stop any vibrations before exiting
motorController.StopRinging(); motorController.StopRinging();
systemTask.PushMessage(System::Messages::EnableSleeping);
lv_obj_clean(lv_scr_act()); lv_obj_clean(lv_scr_act());
} }
@ -82,7 +81,6 @@ void Notifications::Refresh() {
} else if (mode == Modes::Preview && dismissingNotification) { } else if (mode == Modes::Preview && dismissingNotification) {
running = false; running = false;
currentItem = std::make_unique<NotificationItem>(alertNotificationService, motorController);
} else if (dismissingNotification) { } else if (dismissingNotification) {
dismissingNotification = false; dismissingNotification = false;
@ -113,15 +111,15 @@ void Notifications::Refresh() {
alertNotificationService, alertNotificationService,
motorController); motorController);
} else { } else {
currentItem = std::make_unique<NotificationItem>(alertNotificationService, motorController); running = false;
} }
} }
running = currentItem->IsRunning() && running; running = running && currentItem->IsRunning();
} }
void Notifications::OnPreviewInteraction() { void Notifications::OnPreviewInteraction() {
systemTask.PushMessage(System::Messages::EnableSleeping); wakeLock.Release();
motorController.StopRinging(); motorController.StopRinging();
if (timeoutLine != nullptr) { if (timeoutLine != nullptr) {
lv_obj_del(timeoutLine); lv_obj_del(timeoutLine);
@ -173,7 +171,9 @@ bool Notifications::OnTouchEvent(Pinetime::Applications::TouchEvents event) {
} else if (nextMessage.valid) { } else if (nextMessage.valid) {
currentId = nextMessage.id; currentId = nextMessage.id;
} else { } else {
// don't update id, won't be found be refresh and try to load latest message or no message box // don't update id, notification manager will try to fetch
// but not find it. Refresh will try to load latest message
// or dismiss to watchface
} }
DismissToBlack(); DismissToBlack();
return true; return true;

View file

@ -8,6 +8,7 @@
#include "components/ble/NotificationManager.h" #include "components/ble/NotificationManager.h"
#include "components/motor/MotorController.h" #include "components/motor/MotorController.h"
#include "systemtask/SystemTask.h" #include "systemtask/SystemTask.h"
#include "systemtask/WakeLock.h"
namespace Pinetime { namespace Pinetime {
namespace Controllers { namespace Controllers {
@ -73,7 +74,7 @@ namespace Pinetime {
Pinetime::Controllers::NotificationManager& notificationManager; Pinetime::Controllers::NotificationManager& notificationManager;
Pinetime::Controllers::AlertNotificationService& alertNotificationService; Pinetime::Controllers::AlertNotificationService& alertNotificationService;
Pinetime::Controllers::MotorController& motorController; Pinetime::Controllers::MotorController& motorController;
System::SystemTask& systemTask; System::WakeLock wakeLock;
Modes mode = Modes::Normal; Modes mode = Modes::Normal;
std::unique_ptr<NotificationItem> currentItem; std::unique_ptr<NotificationItem> currentItem;
Pinetime::Controllers::NotificationManager::Notification::Id currentId; Pinetime::Controllers::NotificationManager::Notification::Id currentId;

View file

@ -34,7 +34,7 @@ namespace {
constexpr TickType_t blinkInterval = pdMS_TO_TICKS(1000); constexpr TickType_t blinkInterval = pdMS_TO_TICKS(1000);
} }
StopWatch::StopWatch(System::SystemTask& systemTask) : systemTask {systemTask} { StopWatch::StopWatch(System::SystemTask& systemTask) : wakeLock(systemTask) {
static constexpr uint8_t btnWidth = 115; static constexpr uint8_t btnWidth = 115;
static constexpr uint8_t btnHeight = 80; static constexpr uint8_t btnHeight = 80;
btnPlayPause = lv_btn_create(lv_scr_act(), nullptr); btnPlayPause = lv_btn_create(lv_scr_act(), nullptr);
@ -79,7 +79,6 @@ StopWatch::StopWatch(System::SystemTask& systemTask) : systemTask {systemTask} {
StopWatch::~StopWatch() { StopWatch::~StopWatch() {
lv_task_del(taskRefresh); lv_task_del(taskRefresh);
systemTask.PushMessage(Pinetime::System::Messages::EnableSleeping);
lv_obj_clean(lv_scr_act()); lv_obj_clean(lv_scr_act());
} }
@ -135,7 +134,7 @@ void StopWatch::Start() {
SetInterfaceRunning(); SetInterfaceRunning();
startTime = xTaskGetTickCount(); startTime = xTaskGetTickCount();
currentState = States::Running; currentState = States::Running;
systemTask.PushMessage(Pinetime::System::Messages::DisableSleeping); wakeLock.Lock();
} }
void StopWatch::Pause() { void StopWatch::Pause() {
@ -145,7 +144,7 @@ void StopWatch::Pause() {
oldTimeElapsed = laps[lapsDone]; oldTimeElapsed = laps[lapsDone];
blinkTime = xTaskGetTickCount() + blinkInterval; blinkTime = xTaskGetTickCount() + blinkInterval;
currentState = States::Halted; currentState = States::Halted;
systemTask.PushMessage(Pinetime::System::Messages::EnableSleeping); wakeLock.Release();
} }
void StopWatch::Refresh() { void StopWatch::Refresh() {

View file

@ -7,6 +7,7 @@
#include "portmacro_cmsis.h" #include "portmacro_cmsis.h"
#include "systemtask/SystemTask.h" #include "systemtask/SystemTask.h"
#include "systemtask/WakeLock.h"
#include "displayapp/apps/Apps.h" #include "displayapp/apps/Apps.h"
#include "displayapp/Controllers.h" #include "displayapp/Controllers.h"
#include "Symbols.h" #include "Symbols.h"
@ -43,7 +44,7 @@ namespace Pinetime {
void Start(); void Start();
void Pause(); void Pause();
Pinetime::System::SystemTask& systemTask; Pinetime::System::WakeLock wakeLock;
States currentState = States::Init; States currentState = States::Init;
TickType_t startTime; TickType_t startTime;
TickType_t oldTimeElapsed = 0; TickType_t oldTimeElapsed = 0;

View file

@ -40,8 +40,7 @@ SystemInfo::SystemInfo(Pinetime::Applications::DisplayApp* app,
Pinetime::Controllers::MotionController& motionController, Pinetime::Controllers::MotionController& motionController,
const Pinetime::Drivers::Cst816S& touchPanel, const Pinetime::Drivers::Cst816S& touchPanel,
const Pinetime::Drivers::SpiNorFlash& spiNorFlash) const Pinetime::Drivers::SpiNorFlash& spiNorFlash)
: app {app}, : dateTimeController {dateTimeController},
dateTimeController {dateTimeController},
batteryController {batteryController}, batteryController {batteryController},
brightnessController {brightnessController}, brightnessController {brightnessController},
bleController {bleController}, bleController {bleController},

View file

@ -35,7 +35,6 @@ namespace Pinetime {
bool OnTouchEvent(TouchEvents event) override; bool OnTouchEvent(TouchEvents event) override;
private: private:
DisplayApp* app;
Pinetime::Controllers::DateTime& dateTimeController; Pinetime::Controllers::DateTime& dateTimeController;
const Pinetime::Controllers::Battery& batteryController; const Pinetime::Controllers::Battery& batteryController;
Pinetime::Controllers::BrightnessController& brightnessController; Pinetime::Controllers::BrightnessController& brightnessController;

View file

@ -104,9 +104,7 @@ void Timer::UpdateMask() {
void Timer::Refresh() { void Timer::Refresh() {
if (timer.IsRunning()) { if (timer.IsRunning()) {
auto secondsRemaining = std::chrono::duration_cast<std::chrono::seconds>(timer.GetTimeRemaining()); DisplayTime();
minuteCounter.SetValue(secondsRemaining.count() / 60);
secondCounter.SetValue(secondsRemaining.count() % 60);
} else if (buttonPressing && xTaskGetTickCount() > pressTime + pdMS_TO_TICKS(150)) { } else if (buttonPressing && xTaskGetTickCount() > pressTime + pdMS_TO_TICKS(150)) {
lv_label_set_text_static(txtPlayPause, "Reset"); lv_label_set_text_static(txtPlayPause, "Reset");
maskPosition += 15; maskPosition += 15;
@ -119,6 +117,14 @@ void Timer::Refresh() {
} }
} }
void Timer::DisplayTime() {
displaySeconds = std::chrono::duration_cast<std::chrono::seconds>(timer.GetTimeRemaining());
if (displaySeconds.IsUpdated()) {
minuteCounter.SetValue(displaySeconds.Get().count() / 60);
secondCounter.SetValue(displaySeconds.Get().count() % 60);
}
}
void Timer::SetTimerRunning() { void Timer::SetTimerRunning() {
minuteCounter.HideControls(); minuteCounter.HideControls();
secondCounter.HideControls(); secondCounter.HideControls();
@ -133,9 +139,7 @@ void Timer::SetTimerStopped() {
void Timer::ToggleRunning() { void Timer::ToggleRunning() {
if (timer.IsRunning()) { if (timer.IsRunning()) {
auto secondsRemaining = std::chrono::duration_cast<std::chrono::seconds>(timer.GetTimeRemaining()); DisplayTime();
minuteCounter.SetValue(secondsRemaining.count() / 60);
secondCounter.SetValue(secondsRemaining.count() % 60);
timer.StopTimer(); timer.StopTimer();
SetTimerStopped(); SetTimerStopped();
} else if (secondCounter.GetValue() + minuteCounter.GetValue() > 0) { } else if (secondCounter.GetValue() + minuteCounter.GetValue() > 0) {
@ -147,7 +151,6 @@ void Timer::ToggleRunning() {
} }
void Timer::Reset() { void Timer::Reset() {
minuteCounter.SetValue(0); DisplayTime();
secondCounter.SetValue(0);
SetTimerStopped(); SetTimerStopped();
} }

View file

@ -5,6 +5,7 @@
#include "systemtask/SystemTask.h" #include "systemtask/SystemTask.h"
#include "displayapp/LittleVgl.h" #include "displayapp/LittleVgl.h"
#include "displayapp/widgets/Counter.h" #include "displayapp/widgets/Counter.h"
#include "utility/DirtyValue.h"
#include <lvgl/lvgl.h> #include <lvgl/lvgl.h>
#include "components/timer/Timer.h" #include "components/timer/Timer.h"
@ -26,6 +27,7 @@ namespace Pinetime::Applications {
void SetTimerRunning(); void SetTimerRunning();
void SetTimerStopped(); void SetTimerStopped();
void UpdateMask(); void UpdateMask();
void DisplayTime();
Pinetime::Controllers::Timer& timer; Pinetime::Controllers::Timer& timer;
lv_obj_t* btnPlayPause; lv_obj_t* btnPlayPause;
@ -43,6 +45,7 @@ namespace Pinetime::Applications {
bool buttonPressing = false; bool buttonPressing = false;
lv_coord_t maskPosition = 0; lv_coord_t maskPosition = 0;
TickType_t pressTime = 0; TickType_t pressTime = 0;
Utility::DirtyValue<std::chrono::seconds> displaySeconds;
}; };
} }

View file

@ -24,8 +24,7 @@ namespace {
constexpr std::array<uint16_t, 6> SettingDisplay::options; constexpr std::array<uint16_t, 6> SettingDisplay::options;
SettingDisplay::SettingDisplay(Pinetime::Applications::DisplayApp* app, Pinetime::Controllers::Settings& settingsController) SettingDisplay::SettingDisplay(Pinetime::Controllers::Settings& settingsController) : settingsController {settingsController} {
: app {app}, settingsController {settingsController} {
lv_obj_t* container1 = lv_cont_create(lv_scr_act(), nullptr); lv_obj_t* container1 = lv_cont_create(lv_scr_act(), nullptr);

View file

@ -14,14 +14,13 @@ namespace Pinetime {
class SettingDisplay : public Screen { class SettingDisplay : public Screen {
public: public:
SettingDisplay(DisplayApp* app, Pinetime::Controllers::Settings& settingsController); SettingDisplay(Pinetime::Controllers::Settings& settingsController);
~SettingDisplay() override; ~SettingDisplay() override;
void UpdateSelected(lv_obj_t* object, lv_event_t event); void UpdateSelected(lv_obj_t* object, lv_event_t event);
void ToggleAlwaysOn(); void ToggleAlwaysOn();
private: private:
DisplayApp* app;
static constexpr std::array<uint16_t, 6> options = {5000, 7000, 10000, 15000, 20000, 30000}; static constexpr std::array<uint16_t, 6> options = {5000, 7000, 10000, 15000, 20000, 30000};
Controllers::Settings& settingsController; Controllers::Settings& settingsController;

View file

@ -15,8 +15,7 @@ bool SettingSetDateTime::OnTouchEvent(Pinetime::Applications::TouchEvents event)
SettingSetDateTime::SettingSetDateTime(Pinetime::Applications::DisplayApp* app, SettingSetDateTime::SettingSetDateTime(Pinetime::Applications::DisplayApp* app,
Pinetime::Controllers::DateTime& dateTimeController, Pinetime::Controllers::DateTime& dateTimeController,
Pinetime::Controllers::Settings& settingsController) Pinetime::Controllers::Settings& settingsController)
: app {app}, : dateTimeController {dateTimeController},
dateTimeController {dateTimeController},
settingsController {settingsController}, settingsController {settingsController},
screens {app, screens {app,
0, 0,

View file

@ -20,7 +20,6 @@ namespace Pinetime {
void Quit(); void Quit();
private: private:
DisplayApp* app;
Controllers::DateTime& dateTimeController; Controllers::DateTime& dateTimeController;
Controllers::Settings& settingsController; Controllers::Settings& settingsController;

View file

@ -54,8 +54,7 @@ SettingWatchFace::SettingWatchFace(Pinetime::Applications::DisplayApp* app,
std::array<Screens::SettingWatchFace::Item, UserWatchFaceTypes::Count>&& watchfaceItems, std::array<Screens::SettingWatchFace::Item, UserWatchFaceTypes::Count>&& watchfaceItems,
Pinetime::Controllers::Settings& settingsController, Pinetime::Controllers::Settings& settingsController,
Pinetime::Controllers::FS& filesystem) Pinetime::Controllers::FS& filesystem)
: app {app}, : watchfaceItems {std::move(watchfaceItems)},
watchfaceItems {std::move(watchfaceItems)},
settingsController {settingsController}, settingsController {settingsController},
filesystem {filesystem}, filesystem {filesystem},
screens {app, 0, CreateScreenList(), Screens::ScreenListModes::UpDown} { screens {app, 0, CreateScreenList(), Screens::ScreenListModes::UpDown} {

View file

@ -34,7 +34,6 @@ namespace Pinetime {
bool OnTouchEvent(TouchEvents event) override; bool OnTouchEvent(TouchEvents event) override;
private: private:
DisplayApp* app;
auto CreateScreenList() const; auto CreateScreenList() const;
std::unique_ptr<Screen> CreateScreen(unsigned int screenNum) const; std::unique_ptr<Screen> CreateScreen(unsigned int screenNum) const;

View file

@ -6,6 +6,7 @@
#include "drivers/Hrs3300.h" #include "drivers/Hrs3300.h"
#include <algorithm> #include <algorithm>
#include <iterator>
#include <nrf_gpio.h> #include <nrf_gpio.h>
#include <FreeRTOS.h> #include <FreeRTOS.h>
@ -67,40 +68,37 @@ void Hrs3300::Disable() {
WriteRegister(static_cast<uint8_t>(Registers::PDriver), 0); WriteRegister(static_cast<uint8_t>(Registers::PDriver), 0);
} }
uint32_t Hrs3300::ReadHrs() { Hrs3300::PackedHrsAls Hrs3300::ReadHrsAls() {
auto m = ReadRegister(static_cast<uint8_t>(Registers::C0DataM)); constexpr Registers dataRegisters[] =
auto h = ReadRegister(static_cast<uint8_t>(Registers::C0DataH)); {Registers::C1dataM, Registers::C0DataM, Registers::C0DataH, Registers::C1dataH, Registers::C1dataL, Registers::C0dataL};
auto l = ReadRegister(static_cast<uint8_t>(Registers::C0dataL)); // Calculate smallest register address
return ((l & 0x30) << 12) | (m << 8) | ((h & 0x0f) << 4) | (l & 0x0f); constexpr uint8_t baseOffset = static_cast<uint8_t>(*std::min_element(std::begin(dataRegisters), std::end(dataRegisters)));
} // Calculate largest address to determine length of read needed
// Add one to largest relative index to find the length
constexpr uint8_t length = static_cast<uint8_t>(*std::max_element(std::begin(dataRegisters), std::end(dataRegisters))) - baseOffset + 1;
uint32_t Hrs3300::ReadAls() { Hrs3300::PackedHrsAls res;
auto m = ReadRegister(static_cast<uint8_t>(Registers::C1dataM)); uint8_t buf[length];
auto h = ReadRegister(static_cast<uint8_t>(Registers::C1dataH)); auto ret = twiMaster.Read(twiAddress, baseOffset, buf, length);
auto l = ReadRegister(static_cast<uint8_t>(Registers::C1dataL)); if (ret != TwiMaster::ErrorCodes::NoError) {
return ((h & 0x3f) << 11) | (m << 3) | (l & 0x07); NRF_LOG_INFO("READ ERROR");
}
void Hrs3300::SetGain(uint8_t gain) {
constexpr uint8_t maxGain = 64U;
gain = std::min(gain, maxGain);
uint8_t hgain = 0;
while ((1 << hgain) < gain) {
++hgain;
} }
// hrs
uint8_t m = static_cast<uint8_t>(Registers::C0DataM) - baseOffset;
uint8_t h = static_cast<uint8_t>(Registers::C0DataH) - baseOffset;
uint8_t l = static_cast<uint8_t>(Registers::C0dataL) - baseOffset;
// There are two extra bits (17 and 18) but they are not read here
// as resolutions >16bit aren't practically useful (too slow) and
// all hrs values throughout InfiniTime are 16bit
res.hrs = (buf[m] << 8) | ((buf[h] & 0x0f) << 4) | (buf[l] & 0x0f);
WriteRegister(static_cast<uint8_t>(Registers::Hgain), hgain << 2); // als
} m = static_cast<uint8_t>(Registers::C1dataM) - baseOffset;
h = static_cast<uint8_t>(Registers::C1dataH) - baseOffset;
l = static_cast<uint8_t>(Registers::C1dataL) - baseOffset;
res.als = ((buf[h] & 0x3f) << 11) | (buf[m] << 3) | (buf[l] & 0x07);
void Hrs3300::SetDrive(uint8_t drive) { return res;
auto en = ReadRegister(static_cast<uint8_t>(Registers::Enable));
auto pd = ReadRegister(static_cast<uint8_t>(Registers::PDriver));
en = (en & 0xf7) | ((drive & 2) << 2);
pd = (pd & 0xbf) | ((drive & 1) << 6);
WriteRegister(static_cast<uint8_t>(Registers::Enable), en);
WriteRegister(static_cast<uint8_t>(Registers::PDriver), pd);
} }
void Hrs3300::WriteRegister(uint8_t reg, uint8_t data) { void Hrs3300::WriteRegister(uint8_t reg, uint8_t data) {

View file

@ -21,6 +21,11 @@ namespace Pinetime {
Hgain = 0x17 Hgain = 0x17
}; };
struct PackedHrsAls {
uint16_t hrs;
uint16_t als;
};
Hrs3300(TwiMaster& twiMaster, uint8_t twiAddress); Hrs3300(TwiMaster& twiMaster, uint8_t twiAddress);
Hrs3300(const Hrs3300&) = delete; Hrs3300(const Hrs3300&) = delete;
Hrs3300& operator=(const Hrs3300&) = delete; Hrs3300& operator=(const Hrs3300&) = delete;
@ -30,10 +35,7 @@ namespace Pinetime {
void Init(); void Init();
void Enable(); void Enable();
void Disable(); void Disable();
uint32_t ReadHrs(); PackedHrsAls ReadHrsAls();
uint32_t ReadAls();
void SetGain(uint8_t gain);
void SetDrive(uint8_t drive);
private: private:
TwiMaster& twiMaster; TwiMaster& twiMaster;

View file

@ -70,7 +70,8 @@ void HeartRateTask::Work() {
} }
if (measurementStarted) { if (measurementStarted) {
int8_t ambient = ppg.Preprocess(heartRateSensor.ReadHrs(), heartRateSensor.ReadAls()); auto sensorData = heartRateSensor.ReadHrsAls();
int8_t ambient = ppg.Preprocess(sensorData.hrs, sensorData.als);
int bpm = ppg.HeartRate(); int bpm = ppg.HeartRate();
// If ambient light detected or a reset requested (bpm < 0) // If ambient light detected or a reset requested (bpm < 0)

View file

@ -104,7 +104,7 @@ Pinetime::Controllers::DateTime dateTimeController {settingsController};
Pinetime::Drivers::Watchdog watchdog; Pinetime::Drivers::Watchdog watchdog;
Pinetime::Controllers::NotificationManager notificationManager; Pinetime::Controllers::NotificationManager notificationManager;
Pinetime::Controllers::MotionController motionController; Pinetime::Controllers::MotionController motionController;
Pinetime::Controllers::AlarmController alarmController {dateTimeController}; Pinetime::Controllers::AlarmController alarmController {dateTimeController, fs};
Pinetime::Controllers::TouchHandler touchHandler; Pinetime::Controllers::TouchHandler touchHandler;
Pinetime::Controllers::ButtonHandler buttonHandler; Pinetime::Controllers::ButtonHandler buttonHandler;
Pinetime::Controllers::BrightnessController brightnessController {}; Pinetime::Controllers::BrightnessController brightnessController {};

View file

@ -1,5 +1,5 @@
#include "systemtask/SystemTask.h" #include "systemtask/SystemTask.h"
#if configUSE_TRACE_FACILITY == 1 #if NRF_LOG_ENABLED
// FreeRtosMonitor // FreeRtosMonitor
#include <FreeRTOS.h> #include <FreeRTOS.h>
#include <task.h> #include <task.h>

View file

@ -189,37 +189,14 @@ void SystemTask::Work() {
if (xQueueReceive(systemTasksMsgQueue, &msg, 100) == pdTRUE) { if (xQueueReceive(systemTasksMsgQueue, &msg, 100) == pdTRUE) {
switch (msg) { switch (msg) {
case Messages::EnableSleeping: case Messages::EnableSleeping:
// Make sure that exiting an app doesn't enable sleeping, wakeLocksHeld--;
// if the exiting was caused by a firmware update
if (!bleController.IsFirmwareUpdating()) {
doNotGoToSleep = false;
}
displayApp.PushMessage(Pinetime::Applications::Display::Messages::NotifyDeviceActivity);
break; break;
case Messages::DisableSleeping: case Messages::DisableSleeping:
doNotGoToSleep = true; GoToRunning();
wakeLocksHeld++;
break; break;
case Messages::GoToRunning: case Messages::GoToRunning:
// SPI doesn't go to sleep for always on mode GoToRunning();
if (!settingsController.GetAlwaysOnDisplay()) {
spi.Wakeup();
}
// Double Tap needs the touch screen to be in normal mode
if (!settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::DoubleTap)) {
touchPanel.Wakeup();
}
spiNorFlash.Wakeup();
displayApp.PushMessage(Pinetime::Applications::Display::Messages::GoToRunning);
heartRateApp.PushMessage(Pinetime::Applications::HeartRateTask::Messages::WakeUp);
if (bleController.IsRadioEnabled() && !bleController.IsConnected()) {
nimbleController.RestartFastAdv();
}
state = SystemTaskState::Running;
break; break;
case Messages::TouchWakeUp: { case Messages::TouchWakeUp: {
if (touchHandler.ProcessTouchInfo(touchPanel.GetTouchInfo())) { if (touchHandler.ProcessTouchInfo(touchPanel.GetTouchInfo())) {
@ -236,35 +213,23 @@ void SystemTask::Work() {
break; break;
} }
case Messages::GoToSleep: case Messages::GoToSleep:
if (doNotGoToSleep) { GoToSleep();
break;
}
state = SystemTaskState::GoingToSleep; // Already set in PushMessage()
NRF_LOG_INFO("[systemtask] Going to sleep");
displayApp.PushMessage(Pinetime::Applications::Display::Messages::GoToSleep);
heartRateApp.PushMessage(Pinetime::Applications::HeartRateTask::Messages::GoToSleep);
break; break;
case Messages::OnNewTime: case Messages::OnNewTime:
displayApp.PushMessage(Pinetime::Applications::Display::Messages::NotifyDeviceActivity); if (alarmController.IsEnabled()) {
displayApp.PushMessage(Pinetime::Applications::Display::Messages::UpdateDateTime);
if (alarmController.State() == Controllers::AlarmController::AlarmState::Set) {
alarmController.ScheduleAlarm(); alarmController.ScheduleAlarm();
} }
break; break;
case Messages::OnNewNotification: case Messages::OnNewNotification:
if (settingsController.GetNotificationStatus() == Pinetime::Controllers::Settings::Notification::On) { if (settingsController.GetNotificationStatus() == Pinetime::Controllers::Settings::Notification::On) {
if (state == SystemTaskState::Sleeping) { if (IsSleeping()) {
GoToRunning(); GoToRunning();
} else {
displayApp.PushMessage(Pinetime::Applications::Display::Messages::NotifyDeviceActivity);
} }
displayApp.PushMessage(Pinetime::Applications::Display::Messages::NewNotification); displayApp.PushMessage(Pinetime::Applications::Display::Messages::NewNotification);
} }
break; break;
case Messages::SetOffAlarm: case Messages::SetOffAlarm:
if (state == SystemTaskState::Sleeping) { GoToRunning();
GoToRunning();
}
displayApp.PushMessage(Pinetime::Applications::Display::Messages::AlarmTriggered); displayApp.PushMessage(Pinetime::Applications::Display::Messages::AlarmTriggered);
break; break;
case Messages::BleConnected: case Messages::BleConnected:
@ -273,29 +238,25 @@ void SystemTask::Work() {
bleDiscoveryTimer = 5; bleDiscoveryTimer = 5;
break; break;
case Messages::BleFirmwareUpdateStarted: case Messages::BleFirmwareUpdateStarted:
doNotGoToSleep = true; GoToRunning();
if (state == SystemTaskState::Sleeping) { wakeLocksHeld++;
GoToRunning();
}
displayApp.PushMessage(Pinetime::Applications::Display::Messages::BleFirmwareUpdateStarted); displayApp.PushMessage(Pinetime::Applications::Display::Messages::BleFirmwareUpdateStarted);
break; break;
case Messages::BleFirmwareUpdateFinished: case Messages::BleFirmwareUpdateFinished:
if (bleController.State() == Pinetime::Controllers::Ble::FirmwareUpdateStates::Validated) { if (bleController.State() == Pinetime::Controllers::Ble::FirmwareUpdateStates::Validated) {
NVIC_SystemReset(); NVIC_SystemReset();
} }
doNotGoToSleep = false; wakeLocksHeld--;
break; break;
case Messages::StartFileTransfer: case Messages::StartFileTransfer:
NRF_LOG_INFO("[systemtask] FS Started"); NRF_LOG_INFO("[systemtask] FS Started");
doNotGoToSleep = true; GoToRunning();
if (state == SystemTaskState::Sleeping) { wakeLocksHeld++;
GoToRunning();
}
// TODO add intent of fs access icon or something // TODO add intent of fs access icon or something
break; break;
case Messages::StopFileTransfer: case Messages::StopFileTransfer:
NRF_LOG_INFO("[systemtask] FS Stopped"); NRF_LOG_INFO("[systemtask] FS Stopped");
doNotGoToSleep = false; wakeLocksHeld--;
// TODO add intent of fs access icon or something // TODO add intent of fs access icon or something
break; break;
case Messages::OnTouchEvent: case Messages::OnTouchEvent:
@ -323,6 +284,13 @@ void SystemTask::Work() {
HandleButtonAction(action); HandleButtonAction(action);
} break; } break;
case Messages::OnDisplayTaskSleeping: case Messages::OnDisplayTaskSleeping:
// The state was set to GoingToSleep when GoToSleep() was called
// If the state is no longer GoingToSleep, we have since transitioned back to Running
// In this case absorb the OnDisplayTaskSleeping
// as DisplayApp is about to receive GoToRunning
if (state != SystemTaskState::GoingToSleep) {
break;
}
if (BootloaderVersion::IsValid()) { if (BootloaderVersion::IsValid()) {
// First versions of the bootloader do not expose their version and cannot initialize the SPI NOR FLASH // 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. // if it's in sleep mode. Avoid bricked device by disabling sleep mode on these versions.
@ -349,39 +317,23 @@ void SystemTask::Work() {
case Messages::OnNewHour: case Messages::OnNewHour:
using Pinetime::Controllers::AlarmController; using Pinetime::Controllers::AlarmController;
if (settingsController.GetNotificationStatus() != Controllers::Settings::Notification::Sleep && if (settingsController.GetNotificationStatus() != Controllers::Settings::Notification::Sleep &&
settingsController.GetChimeOption() == Controllers::Settings::ChimesOption::Hours && settingsController.GetChimeOption() == Controllers::Settings::ChimesOption::Hours && !alarmController.IsAlerting()) {
alarmController.State() != AlarmController::AlarmState::Alerting) { GoToRunning();
// if sleeping, we can't send a chime to displayApp yet (SPI flash switched off) displayApp.PushMessage(Pinetime::Applications::Display::Messages::Chime);
// request running first and repush the chime message
if (state == SystemTaskState::Sleeping) {
GoToRunning();
PushMessage(msg);
} else {
displayApp.PushMessage(Pinetime::Applications::Display::Messages::Chime);
}
} }
break; break;
case Messages::OnNewHalfHour: case Messages::OnNewHalfHour:
using Pinetime::Controllers::AlarmController; using Pinetime::Controllers::AlarmController;
if (settingsController.GetNotificationStatus() != Controllers::Settings::Notification::Sleep && if (settingsController.GetNotificationStatus() != Controllers::Settings::Notification::Sleep &&
settingsController.GetChimeOption() == Controllers::Settings::ChimesOption::HalfHours && settingsController.GetChimeOption() == Controllers::Settings::ChimesOption::HalfHours && !alarmController.IsAlerting()) {
alarmController.State() != AlarmController::AlarmState::Alerting) { GoToRunning();
// if sleeping, we can't send a chime to displayApp yet (SPI flash switched off) displayApp.PushMessage(Pinetime::Applications::Display::Messages::Chime);
// request running first and repush the chime message
if (state == SystemTaskState::Sleeping) {
GoToRunning();
PushMessage(msg);
} else {
displayApp.PushMessage(Pinetime::Applications::Display::Messages::Chime);
}
} }
break; break;
case Messages::OnChargingEvent: case Messages::OnChargingEvent:
batteryController.ReadPowerState(); batteryController.ReadPowerState();
GoToRunning();
displayApp.PushMessage(Applications::Display::Messages::OnChargingEvent); displayApp.PushMessage(Applications::Display::Messages::OnChargingEvent);
if (state == SystemTaskState::Sleeping) {
GoToRunning();
}
break; break;
case Messages::MeasureBatteryTimerExpired: case Messages::MeasureBatteryTimerExpired:
batteryController.MeasureVoltage(); batteryController.MeasureVoltage();
@ -390,9 +342,7 @@ void SystemTask::Work() {
nimbleController.NotifyBatteryLevel(batteryController.PercentRemaining()); nimbleController.NotifyBatteryLevel(batteryController.PercentRemaining());
break; break;
case Messages::OnPairing: case Messages::OnPairing:
if (state == SystemTaskState::Sleeping) { GoToRunning();
GoToRunning();
}
displayApp.PushMessage(Pinetime::Applications::Display::Messages::ShowPairingKey); displayApp.PushMessage(Pinetime::Applications::Display::Messages::ShowPairingKey);
break; break;
case Messages::BleRadioEnableToggle: case Messages::BleRadioEnableToggle:
@ -427,14 +377,50 @@ void SystemTask::Work() {
#pragma clang diagnostic pop #pragma clang diagnostic pop
} }
void SystemTask::UpdateMotion() { void SystemTask::GoToRunning() {
if (state == SystemTaskState::GoingToSleep || state == SystemTaskState::WakingUp) { if (state == SystemTaskState::Running) {
return; return;
} }
// SPI doesn't go to sleep for always on mode
if (!settingsController.GetAlwaysOnDisplay()) {
spi.Wakeup();
}
if (state == SystemTaskState::Sleeping && !(settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::RaiseWrist) || // Double Tap needs the touch screen to be in normal mode
settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::Shake) || if (!settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::DoubleTap)) {
motionController.GetService()->IsMotionNotificationSubscribed())) { touchPanel.Wakeup();
}
spiNorFlash.Wakeup();
displayApp.PushMessage(Pinetime::Applications::Display::Messages::GoToRunning);
heartRateApp.PushMessage(Pinetime::Applications::HeartRateTask::Messages::WakeUp);
if (bleController.IsRadioEnabled() && !bleController.IsConnected()) {
nimbleController.RestartFastAdv();
}
state = SystemTaskState::Running;
};
void SystemTask::GoToSleep() {
if (IsSleeping()) {
return;
}
if (IsSleepDisabled()) {
return;
}
NRF_LOG_INFO("[systemtask] Going to sleep");
displayApp.PushMessage(Pinetime::Applications::Display::Messages::GoToSleep);
heartRateApp.PushMessage(Pinetime::Applications::HeartRateTask::Messages::GoToSleep);
state = SystemTaskState::GoingToSleep;
};
void SystemTask::UpdateMotion() {
if (IsSleeping() && !(settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::RaiseWrist) ||
settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::Shake) ||
motionController.GetService()->IsMotionNotificationSubscribed())) {
return; return;
} }
@ -457,7 +443,7 @@ void SystemTask::UpdateMotion() {
} }
if (settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::LowerWrist) && state == SystemTaskState::Running && if (settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::LowerWrist) && state == SystemTaskState::Running &&
motionController.ShouldLowerSleep()) { motionController.ShouldLowerSleep()) {
PushMessage(Messages::GoToSleep); GoToSleep();
} }
} }
@ -473,7 +459,7 @@ void SystemTask::HandleButtonAction(Controllers::ButtonActions action) {
switch (action) { switch (action) {
case Actions::Click: case Actions::Click:
// If the first action after fast wakeup is a click, it should be ignored. // If the first action after fast wakeup is a click, it should be ignored.
if (!fastWakeUpDone && state != SystemTaskState::GoingToSleep) { if (!fastWakeUpDone) {
displayApp.PushMessage(Applications::Display::Messages::ButtonPushed); displayApp.PushMessage(Applications::Display::Messages::ButtonPushed);
} }
break; break;
@ -493,17 +479,10 @@ void SystemTask::HandleButtonAction(Controllers::ButtonActions action) {
fastWakeUpDone = false; fastWakeUpDone = false;
} }
void SystemTask::GoToRunning() {
if (state == SystemTaskState::Sleeping) {
state = SystemTaskState::WakingUp;
PushMessage(Messages::GoToRunning);
}
}
void SystemTask::OnTouchEvent() { void SystemTask::OnTouchEvent() {
if (state == SystemTaskState::Running) { if (state == SystemTaskState::Running) {
PushMessage(Messages::OnTouchEvent); PushMessage(Messages::OnTouchEvent);
} else if (state == SystemTaskState::Sleeping) { } else {
if (settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::SingleTap) or if (settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::SingleTap) or
settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::DoubleTap)) { settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::DoubleTap)) {
PushMessage(Messages::TouchWakeUp); PushMessage(Messages::TouchWakeUp);
@ -512,10 +491,6 @@ void SystemTask::OnTouchEvent() {
} }
void SystemTask::PushMessage(System::Messages msg) { void SystemTask::PushMessage(System::Messages msg) {
if (msg == Messages::GoToSleep && !doNotGoToSleep) {
state = SystemTaskState::GoingToSleep;
}
if (in_isr()) { if (in_isr()) {
BaseType_t xHigherPriorityTaskWoken = pdFALSE; BaseType_t xHigherPriorityTaskWoken = pdFALSE;
xQueueSendFromISR(systemTasksMsgQueue, &msg, &xHigherPriorityTaskWoken); xQueueSendFromISR(systemTasksMsgQueue, &msg, &xHigherPriorityTaskWoken);

View file

@ -52,7 +52,7 @@ namespace Pinetime {
namespace System { namespace System {
class SystemTask { class SystemTask {
public: public:
enum class SystemTaskState { Sleeping, Running, GoingToSleep, WakingUp }; enum class SystemTaskState { Sleeping, Running, GoingToSleep };
SystemTask(Drivers::SpiMaster& spi, SystemTask(Drivers::SpiMaster& spi,
Pinetime::Drivers::SpiNorFlash& spiNorFlash, Pinetime::Drivers::SpiNorFlash& spiNorFlash,
Drivers::TwiMaster& twiMaster, Drivers::TwiMaster& twiMaster,
@ -79,11 +79,8 @@ namespace Pinetime {
void OnTouchEvent(); void OnTouchEvent();
void OnIdle();
void OnDim();
bool IsSleepDisabled() { bool IsSleepDisabled() {
return doNotGoToSleep; return wakeLocksHeld > 0;
} }
Pinetime::Controllers::NimbleController& nimble() { Pinetime::Controllers::NimbleController& nimble() {
@ -91,7 +88,7 @@ namespace Pinetime {
}; };
bool IsSleeping() const { bool IsSleeping() const {
return state == SystemTaskState::Sleeping || state == SystemTaskState::WakingUp; return state != SystemTaskState::Running;
} }
private: private:
@ -127,13 +124,14 @@ namespace Pinetime {
bool isBleDiscoveryTimerRunning = false; bool isBleDiscoveryTimerRunning = false;
uint8_t bleDiscoveryTimer = 0; uint8_t bleDiscoveryTimer = 0;
TimerHandle_t measureBatteryTimer; TimerHandle_t measureBatteryTimer;
bool doNotGoToSleep = false; uint8_t wakeLocksHeld = 0;
SystemTaskState state = SystemTaskState::Running; SystemTaskState state = SystemTaskState::Running;
void HandleButtonAction(Controllers::ButtonActions action); void HandleButtonAction(Controllers::ButtonActions action);
bool fastWakeUpDone = false; bool fastWakeUpDone = false;
void GoToRunning(); void GoToRunning();
void GoToSleep();
void UpdateMotion(); void UpdateMotion();
bool stepCounterMustBeReset = false; bool stepCounterMustBeReset = false;
static constexpr TickType_t batteryMeasurementPeriod = pdMS_TO_TICKS(10 * 60 * 1000); static constexpr TickType_t batteryMeasurementPeriod = pdMS_TO_TICKS(10 * 60 * 1000);

View file

@ -0,0 +1,27 @@
#include "systemtask/WakeLock.h"
using namespace Pinetime::System;
WakeLock::WakeLock(SystemTask& systemTask) : systemTask {systemTask} {
lockHeld = false;
}
WakeLock::~WakeLock() {
Release();
}
void WakeLock::Lock() {
if (lockHeld) {
return;
}
systemTask.PushMessage(Messages::DisableSleeping);
lockHeld = true;
}
void WakeLock::Release() {
if (!lockHeld) {
return;
}
systemTask.PushMessage(Messages::EnableSleeping);
lockHeld = false;
}

19
src/systemtask/WakeLock.h Normal file
View file

@ -0,0 +1,19 @@
#pragma once
#include "systemtask/SystemTask.h"
namespace Pinetime {
namespace System {
class WakeLock {
public:
WakeLock(SystemTask& systemTask);
~WakeLock();
void Lock();
void Release();
private:
bool lockHeld;
SystemTask& systemTask;
};
}
}