aboutsummaryrefslogtreecommitdiffstats
path: root/src/systemtask/SystemTask.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/systemtask/SystemTask.cpp')
-rw-r--r--src/systemtask/SystemTask.cpp315
1 files changed, 122 insertions, 193 deletions
diff --git a/src/systemtask/SystemTask.cpp b/src/systemtask/SystemTask.cpp
index 041cb209..8e0435e3 100644
--- a/src/systemtask/SystemTask.cpp
+++ b/src/systemtask/SystemTask.cpp
@@ -27,20 +27,6 @@ namespace {
}
}
-void DimTimerCallback(TimerHandle_t xTimer) {
-
- NRF_LOG_INFO("DimTimerCallback");
- auto* sysTask = static_cast<SystemTask*>(pvTimerGetTimerID(xTimer));
- sysTask->OnDim();
-}
-
-void IdleTimerCallback(TimerHandle_t xTimer) {
-
- NRF_LOG_INFO("IdleTimerCallback");
- auto* sysTask = static_cast<SystemTask*>(pvTimerGetTimerID(xTimer));
- sysTask->OnIdle();
-}
-
void MeasureBatteryTimerCallback(TimerHandle_t xTimer) {
auto* sysTask = static_cast<SystemTask*>(pvTimerGetTimerID(xTimer));
sysTask->PushMessage(Pinetime::System::Messages::MeasureBatteryTimerExpired);
@@ -53,7 +39,6 @@ SystemTask::SystemTask(Drivers::SpiMaster& spi,
Controllers::Battery& batteryController,
Controllers::Ble& bleController,
Controllers::DateTime& dateTimeController,
- Controllers::TimerController& timerController,
Controllers::AlarmController& alarmController,
Drivers::Watchdog& watchdog,
Pinetime::Controllers::NotificationManager& notificationManager,
@@ -74,7 +59,6 @@ SystemTask::SystemTask(Drivers::SpiMaster& spi,
batteryController {batteryController},
bleController {bleController},
dateTimeController {dateTimeController},
- timerController {timerController},
alarmController {alarmController},
watchdog {watchdog},
notificationManager {notificationManager},
@@ -115,10 +99,12 @@ void SystemTask::Process(void* instance) {
void SystemTask::Work() {
BootErrors bootError = BootErrors::None;
- watchdog.Setup(7);
+ watchdog.Setup(7, Drivers::Watchdog::SleepBehaviour::Run, Drivers::Watchdog::HaltBehaviour::Pause);
watchdog.Start();
- NRF_LOG_INFO("Last reset reason : %s", Pinetime::Drivers::Watchdog::ResetReasonToString(watchdog.ResetReason()));
- APP_GPIOTE_INIT(2);
+ NRF_LOG_INFO("Last reset reason : %s", Pinetime::Drivers::ResetReasonToString(watchdog.GetResetReason()));
+ if (!nrfx_gpiote_is_init()) {
+ nrfx_gpiote_init();
+ }
spi.Init();
spiNorFlash.Init();
@@ -141,7 +127,6 @@ void SystemTask::Work() {
dateTimeController.Register(this);
batteryController.Register(this);
motionSensor.SoftReset();
- timerController.Init(this);
alarmController.Init(this);
// Reset the TWI device because the motion sensor chip most probably crashed it...
@@ -153,6 +138,9 @@ void SystemTask::Work() {
settingsController.Init();
displayApp.Register(this);
+ displayApp.Register(&nimbleController.weather());
+ displayApp.Register(&nimbleController.music());
+ displayApp.Register(&nimbleController.navigation());
displayApp.Start(bootError);
heartRateSensor.Init();
@@ -189,10 +177,7 @@ void SystemTask::Work() {
batteryController.MeasureVoltage();
- idleTimer = xTimerCreate("idleTimer", pdMS_TO_TICKS(2000), pdFALSE, this, IdleTimerCallback);
- dimTimer = xTimerCreate("dimTimer", pdMS_TO_TICKS(settingsController.GetScreenTimeOut() - 2000), pdFALSE, this, DimTimerCallback);
measureBatteryTimer = xTimerCreate("measureBattery", batteryMeasurementPeriod, pdTRUE, this, MeasureBatteryTimerCallback);
- xTimerStart(dimTimer, 0);
xTimerStart(measureBatteryTimer, portMAX_DELAY);
#pragma clang diagnostic push
@@ -204,131 +189,80 @@ void SystemTask::Work() {
if (xQueueReceive(systemTasksMsgQueue, &msg, 100) == pdTRUE) {
switch (msg) {
case Messages::EnableSleeping:
- // Make sure that exiting an app doesn't enable sleeping,
- // if the exiting was caused by a firmware update
- if (!bleController.IsFirmwareUpdating()) {
- doNotGoToSleep = false;
- }
- ReloadIdleTimer();
+ wakeLocksHeld--;
break;
case Messages::DisableSleeping:
- doNotGoToSleep = true;
- break;
- case Messages::UpdateTimeOut:
- xTimerChangePeriod(dimTimer, pdMS_TO_TICKS(settingsController.GetScreenTimeOut() - 2000), 0);
+ GoToRunning();
+ wakeLocksHeld++;
break;
case Messages::GoToRunning:
- spi.Wakeup();
-
- // Double Tap needs the touch screen to be in normal mode
- if (!settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::DoubleTap)) {
- touchPanel.Wakeup();
- }
-
- xTimerStart(dimTimer, 0);
- 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;
- isDimmed = false;
- break;
- case Messages::TouchWakeUp: {
- if (touchHandler.ProcessTouchInfo(touchPanel.GetTouchInfo())) {
- auto gesture = touchHandler.GestureGet();
- if (settingsController.GetNotificationStatus() != Controllers::Settings::Notification::Sleep &&
- gesture != Pinetime::Applications::TouchEvents::None &&
- ((gesture == Pinetime::Applications::TouchEvents::DoubleTap &&
- settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::DoubleTap)) ||
- (gesture == Pinetime::Applications::TouchEvents::Tap &&
- settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::SingleTap)))) {
- GoToRunning();
- }
- }
+ GoToRunning();
break;
- }
case Messages::GoToSleep:
- if (doNotGoToSleep) {
- break;
- }
- state = SystemTaskState::GoingToSleep; // Already set in PushMessage()
- NRF_LOG_INFO("[systemtask] Going to sleep");
- xTimerStop(idleTimer, 0);
- xTimerStop(dimTimer, 0);
- displayApp.PushMessage(Pinetime::Applications::Display::Messages::GoToSleep);
- heartRateApp.PushMessage(Pinetime::Applications::HeartRateTask::Messages::GoToSleep);
+ GoToSleep();
break;
case Messages::OnNewTime:
- ReloadIdleTimer();
- displayApp.PushMessage(Pinetime::Applications::Display::Messages::UpdateDateTime);
- if (alarmController.State() == Controllers::AlarmController::AlarmState::Set) {
+ if (alarmController.IsEnabled()) {
alarmController.ScheduleAlarm();
}
break;
case Messages::OnNewNotification:
if (settingsController.GetNotificationStatus() == Pinetime::Controllers::Settings::Notification::On) {
- if (state == SystemTaskState::Sleeping) {
+ if (IsSleeping()) {
GoToRunning();
- } else {
- ReloadIdleTimer();
}
displayApp.PushMessage(Pinetime::Applications::Display::Messages::NewNotification);
}
break;
- case Messages::OnTimerDone:
- if (state == SystemTaskState::Sleeping) {
- GoToRunning();
- }
- displayApp.PushMessage(Pinetime::Applications::Display::Messages::TimerDone);
- break;
case Messages::SetOffAlarm:
- if (state == SystemTaskState::Sleeping) {
- GoToRunning();
- }
+ GoToRunning();
displayApp.PushMessage(Pinetime::Applications::Display::Messages::AlarmTriggered);
break;
case Messages::BleConnected:
- ReloadIdleTimer();
+ displayApp.PushMessage(Pinetime::Applications::Display::Messages::NotifyDeviceActivity);
isBleDiscoveryTimerRunning = true;
bleDiscoveryTimer = 5;
break;
case Messages::BleFirmwareUpdateStarted:
- doNotGoToSleep = true;
- if (state == SystemTaskState::Sleeping) {
- GoToRunning();
- }
+ GoToRunning();
+ wakeLocksHeld++;
displayApp.PushMessage(Pinetime::Applications::Display::Messages::BleFirmwareUpdateStarted);
break;
case Messages::BleFirmwareUpdateFinished:
if (bleController.State() == Pinetime::Controllers::Ble::FirmwareUpdateStates::Validated) {
NVIC_SystemReset();
}
- doNotGoToSleep = false;
- xTimerStart(dimTimer, 0);
+ wakeLocksHeld--;
break;
case Messages::StartFileTransfer:
NRF_LOG_INFO("[systemtask] FS Started");
- doNotGoToSleep = true;
- if (state == SystemTaskState::Sleeping) {
- GoToRunning();
- }
+ GoToRunning();
+ wakeLocksHeld++;
// TODO add intent of fs access icon or something
break;
case Messages::StopFileTransfer:
NRF_LOG_INFO("[systemtask] FS Stopped");
- doNotGoToSleep = false;
- xTimerStart(dimTimer, 0);
+ wakeLocksHeld--;
// TODO add intent of fs access icon or something
break;
case Messages::OnTouchEvent:
- if (touchHandler.ProcessTouchInfo(touchPanel.GetTouchInfo())) {
- ReloadIdleTimer();
+ // Finish immediately if no new events
+ if (!touchHandler.ProcessTouchInfo(touchPanel.GetTouchInfo())) {
+ break;
+ }
+ if (state == SystemTaskState::Running) {
displayApp.PushMessage(Pinetime::Applications::Display::Messages::TouchEvent);
+ } else {
+ // If asleep, check for touch panel wake triggers
+ auto gesture = touchHandler.GestureGet();
+ if (settingsController.GetNotificationStatus() != Controllers::Settings::Notification::Sleep &&
+ gesture != Pinetime::Applications::TouchEvents::None &&
+ ((gesture == Pinetime::Applications::TouchEvents::DoubleTap &&
+ settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::DoubleTap)) ||
+ (gesture == Pinetime::Applications::TouchEvents::Tap &&
+ settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::SingleTap)))) {
+ GoToRunning();
+ }
}
break;
case Messages::HandleButtonEvent: {
@@ -351,19 +285,35 @@ void SystemTask::Work() {
HandleButtonAction(action);
} break;
case Messages::OnDisplayTaskSleeping:
+ case Messages::OnDisplayTaskAOD:
+ // 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/AOD
+ // as DisplayApp is about to receive GoToRunning
+ if (state != SystemTaskState::GoingToSleep) {
+ break;
+ }
if (BootloaderVersion::IsValid()) {
// First versions of the bootloader do not expose their version and cannot initialize the SPI NOR FLASH
// if it's in sleep mode. Avoid bricked device by disabling sleep mode on these versions.
spiNorFlash.Sleep();
}
- spi.Sleep();
+
+ // Must keep SPI awake when still updating the display for always on
+ if (msg == Messages::OnDisplayTaskSleeping) {
+ spi.Sleep();
+ }
// Double Tap needs the touch screen to be in normal mode
if (!settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::DoubleTap)) {
touchPanel.Sleep();
}
- state = SystemTaskState::Sleeping;
+ if (msg == Messages::OnDisplayTaskSleeping) {
+ state = SystemTaskState::Sleeping;
+ } else {
+ state = SystemTaskState::AODSleeping;
+ }
break;
case Messages::OnNewDay:
// We might be sleeping (with TWI device disabled.
@@ -373,32 +323,22 @@ void SystemTask::Work() {
case Messages::OnNewHour:
using Pinetime::Controllers::AlarmController;
if (settingsController.GetNotificationStatus() != Controllers::Settings::Notification::Sleep &&
- settingsController.GetChimeOption() == Controllers::Settings::ChimesOption::Hours &&
- alarmController.State() != AlarmController::AlarmState::Alerting) {
- if (state == SystemTaskState::Sleeping) {
- GoToRunning();
- displayApp.PushMessage(Pinetime::Applications::Display::Messages::Chime);
- }
+ settingsController.GetChimeOption() == Controllers::Settings::ChimesOption::Hours && !alarmController.IsAlerting()) {
+ GoToRunning();
+ displayApp.PushMessage(Pinetime::Applications::Display::Messages::Chime);
}
break;
case Messages::OnNewHalfHour:
using Pinetime::Controllers::AlarmController;
if (settingsController.GetNotificationStatus() != Controllers::Settings::Notification::Sleep &&
- settingsController.GetChimeOption() == Controllers::Settings::ChimesOption::HalfHours &&
- alarmController.State() != AlarmController::AlarmState::Alerting) {
- if (state == SystemTaskState::Sleeping) {
- GoToRunning();
- displayApp.PushMessage(Pinetime::Applications::Display::Messages::Chime);
- }
+ settingsController.GetChimeOption() == Controllers::Settings::ChimesOption::HalfHours && !alarmController.IsAlerting()) {
+ GoToRunning();
+ displayApp.PushMessage(Pinetime::Applications::Display::Messages::Chime);
}
break;
case Messages::OnChargingEvent:
batteryController.ReadPowerState();
- displayApp.PushMessage(Applications::Display::Messages::OnChargingEvent);
- ReloadIdleTimer();
- if (state == SystemTaskState::Sleeping) {
- GoToRunning();
- }
+ GoToRunning();
break;
case Messages::MeasureBatteryTimerExpired:
batteryController.MeasureVoltage();
@@ -407,9 +347,7 @@ void SystemTask::Work() {
nimbleController.NotifyBatteryLevel(batteryController.PercentRemaining());
break;
case Messages::OnPairing:
- if (state == SystemTaskState::Sleeping) {
- GoToRunning();
- }
+ GoToRunning();
displayApp.PushMessage(Pinetime::Applications::Display::Messages::ShowPairingKey);
break;
case Messages::BleRadioEnableToggle:
@@ -436,23 +374,66 @@ void SystemTask::Work() {
}
monitor.Process();
- uint32_t systick_counter = nrf_rtc_counter_get(portNRF_RTC_REG);
- dateTimeController.UpdateTime(systick_counter);
NoInit_BackUpTime = dateTimeController.CurrentDateTime();
if (nrf_gpio_pin_read(PinMap::Button) == 0) {
- watchdog.Kick();
+ watchdog.Reload();
}
}
#pragma clang diagnostic pop
}
-void SystemTask::UpdateMotion() {
- if (state == SystemTaskState::GoingToSleep || state == SystemTaskState::WakingUp) {
+void SystemTask::GoToRunning() {
+ if (state == SystemTaskState::Running) {
return;
}
+ if (state == SystemTaskState::Sleeping || state == SystemTaskState::AODSleeping) {
+ // SPI only switched off when entering Sleeping, not AOD or GoingToSleep
+ if (state == SystemTaskState::Sleeping) {
+ 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;
+};
+void SystemTask::GoToSleep() {
+ if (IsSleeping()) {
+ return;
+ }
+ if (IsSleepDisabled()) {
+ return;
+ }
+ NRF_LOG_INFO("[systemtask] Going to sleep");
+ if (settingsController.GetAlwaysOnDisplay()) {
+ displayApp.PushMessage(Pinetime::Applications::Display::Messages::GoToAOD);
+ } else {
+ displayApp.PushMessage(Pinetime::Applications::Display::Messages::GoToSleep);
+ }
+ heartRateApp.PushMessage(Pinetime::Applications::HeartRateTask::Messages::GoToSleep);
+
+ state = SystemTaskState::GoingToSleep;
+};
+
+void SystemTask::UpdateMotion() {
+ // Only consider disabling motion updates specifically in the Sleeping state
+ // AOD needs motion on to show up to date step counts
if (state == SystemTaskState::Sleeping && !(settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::RaiseWrist) ||
- settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::Shake))) {
+ settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::Shake) ||
+ motionController.GetService()->IsMotionNotificationSubscribed())) {
return;
}
@@ -463,17 +444,20 @@ void SystemTask::UpdateMotion() {
auto motionValues = motionSensor.Process();
- motionController.IsSensorOk(motionSensor.IsOk());
motionController.Update(motionValues.x, motionValues.y, motionValues.z, motionValues.steps);
if (settingsController.GetNotificationStatus() != Controllers::Settings::Notification::Sleep) {
if ((settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::RaiseWrist) &&
- motionController.ShouldRaiseWake(state == SystemTaskState::Sleeping)) ||
+ motionController.ShouldRaiseWake()) ||
(settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::Shake) &&
motionController.ShouldShakeWake(settingsController.GetShakeThreshold()))) {
GoToRunning();
}
}
+ if (settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::LowerWrist) && state == SystemTaskState::Running &&
+ motionController.ShouldLowerSleep()) {
+ GoToSleep();
+ }
}
void SystemTask::HandleButtonAction(Controllers::ButtonActions action) {
@@ -481,14 +465,14 @@ void SystemTask::HandleButtonAction(Controllers::ButtonActions action) {
return;
}
- ReloadIdleTimer();
+ displayApp.PushMessage(Pinetime::Applications::Display::Messages::NotifyDeviceActivity);
using Actions = Controllers::ButtonActions;
switch (action) {
case Actions::Click:
// 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);
}
break;
@@ -508,67 +492,12 @@ void SystemTask::HandleButtonAction(Controllers::ButtonActions action) {
fastWakeUpDone = false;
}
-void SystemTask::GoToRunning() {
- if (state == SystemTaskState::Sleeping) {
- state = SystemTaskState::WakingUp;
- PushMessage(Messages::GoToRunning);
- }
-}
-
-void SystemTask::OnTouchEvent() {
- if (state == SystemTaskState::Running) {
- PushMessage(Messages::OnTouchEvent);
- } else if (state == SystemTaskState::Sleeping) {
- if (settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::SingleTap) or
- settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::DoubleTap)) {
- PushMessage(Messages::TouchWakeUp);
- }
- }
-}
-
void SystemTask::PushMessage(System::Messages msg) {
- if (msg == Messages::GoToSleep && !doNotGoToSleep) {
- state = SystemTaskState::GoingToSleep;
- }
-
if (in_isr()) {
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
xQueueSendFromISR(systemTasksMsgQueue, &msg, &xHigherPriorityTaskWoken);
- if (xHigherPriorityTaskWoken == pdTRUE) {
- /* Actual macro used here is port specific. */
- portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
- }
+ portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
} else {
xQueueSend(systemTasksMsgQueue, &msg, portMAX_DELAY);
}
}
-
-void SystemTask::OnDim() {
- if (doNotGoToSleep) {
- return;
- }
- NRF_LOG_INFO("Dim timeout -> Dim screen")
- displayApp.PushMessage(Pinetime::Applications::Display::Messages::DimScreen);
- xTimerStart(idleTimer, 0);
- isDimmed = true;
-}
-
-void SystemTask::OnIdle() {
- if (doNotGoToSleep) {
- return;
- }
- NRF_LOG_INFO("Idle timeout -> Going to sleep")
- PushMessage(Messages::GoToSleep);
-}
-
-void SystemTask::ReloadIdleTimer() {
- if (state != SystemTaskState::Running) {
- return;
- }
- if (isDimmed) {
- displayApp.PushMessage(Pinetime::Applications::Display::Messages::RestoreBrightness);
- isDimmed = false;
- }
- xTimerReset(dimTimer, 0);
- xTimerStop(idleTimer, 0);
-}