mirror of
https://github.com/InfiniTimeOrg/InfiniTime.git
synced 2026-01-21 08:22:25 +01:00
This should ensure better readability of the pin setup procedure, as well as allow the configuration of the hardware button enable pin and the accelerometer interrupt pin via the pin mapping header.
596 lines
21 KiB
C++
596 lines
21 KiB
C++
#include "systemtask/SystemTask.h"
|
|
#include <hal/nrf_rtc.h>
|
|
#include <libraries/gpiote/app_gpiote.h>
|
|
#include <libraries/log/nrf_log.h>
|
|
#include <app_timer.h>
|
|
#include "BootloaderVersion.h"
|
|
#include "components/battery/BatteryController.h"
|
|
#include "components/ble/BleController.h"
|
|
#include "displayapp/TouchEvents.h"
|
|
#include "drivers/Cst816s.h"
|
|
#include "drivers/St7789.h"
|
|
#include "drivers/InternalFlash.h"
|
|
#include "drivers/SpiMaster.h"
|
|
#include "drivers/SpiNorFlash.h"
|
|
#include "drivers/TwiMaster.h"
|
|
#include "drivers/Hrs3300.h"
|
|
#include "drivers/PinMap.h"
|
|
#include "main.h"
|
|
#include "BootErrors.h"
|
|
|
|
#include <memory>
|
|
|
|
using namespace Pinetime::System;
|
|
|
|
namespace {
|
|
static inline bool in_isr(void) {
|
|
return (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) != 0;
|
|
}
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
SystemTask::SystemTask(Drivers::SpiMaster& spi,
|
|
Drivers::St7789& lcd,
|
|
Pinetime::Drivers::SpiNorFlash& spiNorFlash,
|
|
Drivers::TwiMaster& twiMaster,
|
|
Drivers::Cst816S& touchPanel,
|
|
Components::LittleVgl& lvgl,
|
|
Controllers::Battery& batteryController,
|
|
Controllers::Ble& bleController,
|
|
Controllers::DateTime& dateTimeController,
|
|
Controllers::TimerController& timerController,
|
|
Controllers::AlarmController& alarmController,
|
|
Drivers::Watchdog& watchdog,
|
|
Pinetime::Controllers::NotificationManager& notificationManager,
|
|
Pinetime::Controllers::MotorController& motorController,
|
|
Pinetime::Drivers::Hrs3300& heartRateSensor,
|
|
Pinetime::Controllers::MotionController& motionController,
|
|
Pinetime::Drivers::Bma421& motionSensor,
|
|
Controllers::Settings& settingsController,
|
|
Pinetime::Controllers::HeartRateController& heartRateController,
|
|
Pinetime::Applications::DisplayApp& displayApp,
|
|
Pinetime::Applications::HeartRateTask& heartRateApp,
|
|
Pinetime::Controllers::FS& fs,
|
|
Pinetime::Controllers::TouchHandler& touchHandler,
|
|
Pinetime::Controllers::ButtonHandler& buttonHandler)
|
|
: spi {spi},
|
|
lcd {lcd},
|
|
spiNorFlash {spiNorFlash},
|
|
twiMaster {twiMaster},
|
|
touchPanel {touchPanel},
|
|
lvgl {lvgl},
|
|
batteryController {batteryController},
|
|
bleController {bleController},
|
|
dateTimeController {dateTimeController},
|
|
timerController {timerController},
|
|
alarmController {alarmController},
|
|
watchdog {watchdog},
|
|
notificationManager {notificationManager},
|
|
motorController {motorController},
|
|
heartRateSensor {heartRateSensor},
|
|
motionSensor {motionSensor},
|
|
settingsController {settingsController},
|
|
heartRateController {heartRateController},
|
|
motionController {motionController},
|
|
displayApp {displayApp},
|
|
heartRateApp(heartRateApp),
|
|
fs {fs},
|
|
touchHandler {touchHandler},
|
|
buttonHandler {buttonHandler},
|
|
nimbleController(*this,
|
|
bleController,
|
|
dateTimeController,
|
|
notificationManager,
|
|
batteryController,
|
|
spiNorFlash,
|
|
heartRateController,
|
|
motionController,
|
|
fs) {
|
|
}
|
|
|
|
void SystemTask::Start() {
|
|
systemTasksMsgQueue = xQueueCreate(10, 1);
|
|
if (pdPASS != xTaskCreate(SystemTask::Process, "MAIN", 350, this, 1, &taskHandle)) {
|
|
APP_ERROR_HANDLER(NRF_ERROR_NO_MEM);
|
|
}
|
|
}
|
|
|
|
void SystemTask::Process(void* instance) {
|
|
auto* app = static_cast<SystemTask*>(instance);
|
|
NRF_LOG_INFO("systemtask task started!");
|
|
app->Work();
|
|
}
|
|
|
|
void SystemTask::Work() {
|
|
BootErrors bootError = BootErrors::None;
|
|
|
|
watchdog.Setup(7);
|
|
watchdog.Start();
|
|
NRF_LOG_INFO("Last reset reason : %s", Pinetime::Drivers::Watchdog::ResetReasonToString(watchdog.ResetReason()));
|
|
APP_GPIOTE_INIT(2);
|
|
|
|
app_timer_init();
|
|
|
|
spi.Init();
|
|
spiNorFlash.Init();
|
|
spiNorFlash.Wakeup();
|
|
|
|
fs.Init();
|
|
|
|
nimbleController.Init();
|
|
lcd.Init();
|
|
|
|
twiMaster.Init();
|
|
/*
|
|
* TODO We disable this warning message until we ensure it won't be displayed
|
|
* on legitimate PineTime equipped with a compatible touch controller.
|
|
* (some users reported false positive). See https://github.com/InfiniTimeOrg/InfiniTime/issues/763
|
|
if (!touchPanel.Init()) {
|
|
bootError = BootErrors::TouchController;
|
|
}
|
|
*/
|
|
touchPanel.Init();
|
|
dateTimeController.Register(this);
|
|
batteryController.Register(this);
|
|
motorController.Init();
|
|
motionSensor.SoftReset();
|
|
timerController.Init(this);
|
|
alarmController.Init(this);
|
|
|
|
// Reset the TWI device because the motion sensor chip most probably crashed it...
|
|
twiMaster.Sleep();
|
|
twiMaster.Init();
|
|
|
|
motionSensor.Init();
|
|
motionController.Init(motionSensor.DeviceType());
|
|
settingsController.Init();
|
|
|
|
displayApp.Register(this);
|
|
displayApp.Start(bootError);
|
|
|
|
heartRateSensor.Init();
|
|
heartRateSensor.Disable();
|
|
heartRateApp.Start();
|
|
|
|
buttonHandler.Init(this);
|
|
|
|
// Setup Interrupts
|
|
nrfx_gpiote_in_config_t pinConfig;
|
|
pinConfig.skip_gpio_setup = false;
|
|
pinConfig.hi_accuracy = false;
|
|
pinConfig.is_watcher = false;
|
|
|
|
// Button
|
|
nrf_gpio_cfg_output(PinMap::ButtonEnable);
|
|
nrf_gpio_pin_set(PinMap::ButtonEnable);
|
|
pinConfig.sense = NRF_GPIOTE_POLARITY_TOGGLE;
|
|
pinConfig.pull = NRF_GPIO_PIN_PULLDOWN;
|
|
nrfx_gpiote_in_init(PinMap::Button, &pinConfig, nrfx_gpiote_evt_handler);
|
|
nrfx_gpiote_in_event_enable(PinMap::Button, true);
|
|
|
|
// Touchscreen
|
|
pinConfig.sense = NRF_GPIOTE_POLARITY_HITOLO;
|
|
pinConfig.pull = NRF_GPIO_PIN_PULLUP;
|
|
nrfx_gpiote_in_init(PinMap::Cst816sIrq, &pinConfig, nrfx_gpiote_evt_handler);
|
|
nrfx_gpiote_in_event_enable(PinMap::Cst816sIrq, true);
|
|
|
|
// Power present
|
|
pinConfig.sense = NRF_GPIOTE_POLARITY_TOGGLE;
|
|
pinConfig.pull = NRF_GPIO_PIN_NOPULL;
|
|
nrfx_gpiote_in_init(PinMap::PowerPresent, &pinConfig, nrfx_gpiote_evt_handler);
|
|
nrfx_gpiote_in_event_enable(PinMap::PowerPresent, true);
|
|
|
|
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
|
|
#pragma ide diagnostic ignored "EndlessLoop"
|
|
while (true) {
|
|
UpdateMotion();
|
|
|
|
uint8_t msg;
|
|
if (xQueueReceive(systemTasksMsgQueue, &msg, 100)) {
|
|
Messages message = static_cast<Messages>(msg);
|
|
switch (message) {
|
|
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();
|
|
break;
|
|
case Messages::DisableSleeping:
|
|
doNotGoToSleep = true;
|
|
break;
|
|
case Messages::UpdateTimeOut:
|
|
xTimerChangePeriod(dimTimer, pdMS_TO_TICKS(settingsController.GetScreenTimeOut() - 2000), 0);
|
|
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();
|
|
lcd.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.GetNewTouchInfo()) {
|
|
auto gesture = touchHandler.GestureGet();
|
|
if (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::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);
|
|
break;
|
|
case Messages::OnNewTime:
|
|
ReloadIdleTimer();
|
|
displayApp.PushMessage(Pinetime::Applications::Display::Messages::UpdateDateTime);
|
|
if (alarmController.State() == Controllers::AlarmController::AlarmState::Set) {
|
|
alarmController.ScheduleAlarm();
|
|
}
|
|
break;
|
|
case Messages::OnNewNotification:
|
|
if (settingsController.GetNotificationStatus() == Pinetime::Controllers::Settings::Notification::ON) {
|
|
if (state == SystemTaskState::Sleeping) {
|
|
GoToRunning();
|
|
} else {
|
|
ReloadIdleTimer();
|
|
}
|
|
displayApp.PushMessage(Pinetime::Applications::Display::Messages::NewNotification);
|
|
}
|
|
break;
|
|
case Messages::OnTimerDone:
|
|
if (state == SystemTaskState::Sleeping) {
|
|
GoToRunning();
|
|
}
|
|
motorController.RunForDuration(35);
|
|
displayApp.PushMessage(Pinetime::Applications::Display::Messages::TimerDone);
|
|
break;
|
|
case Messages::SetOffAlarm:
|
|
if (state == SystemTaskState::Sleeping) {
|
|
GoToRunning();
|
|
}
|
|
motorController.StartRinging();
|
|
displayApp.PushMessage(Pinetime::Applications::Display::Messages::AlarmTriggered);
|
|
break;
|
|
case Messages::StopRinging:
|
|
motorController.StopRinging();
|
|
break;
|
|
case Messages::BleConnected:
|
|
ReloadIdleTimer();
|
|
isBleDiscoveryTimerRunning = true;
|
|
bleDiscoveryTimer = 5;
|
|
break;
|
|
case Messages::BleFirmwareUpdateStarted:
|
|
doNotGoToSleep = true;
|
|
if (state == SystemTaskState::Sleeping) {
|
|
GoToRunning();
|
|
}
|
|
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);
|
|
break;
|
|
case Messages::StartFileTransfer:
|
|
NRF_LOG_INFO("[systemtask] FS Started");
|
|
doNotGoToSleep = true;
|
|
if (state == SystemTaskState::Sleeping) {
|
|
GoToRunning();
|
|
}
|
|
// TODO add intent of fs access icon or something
|
|
break;
|
|
case Messages::StopFileTransfer:
|
|
NRF_LOG_INFO("[systemtask] FS Stopped");
|
|
doNotGoToSleep = false;
|
|
xTimerStart(dimTimer, 0);
|
|
// TODO add intent of fs access icon or something
|
|
break;
|
|
case Messages::OnTouchEvent:
|
|
if (touchHandler.GetNewTouchInfo()) {
|
|
touchHandler.UpdateLvglTouchPoint();
|
|
}
|
|
ReloadIdleTimer();
|
|
displayApp.PushMessage(Pinetime::Applications::Display::Messages::TouchEvent);
|
|
break;
|
|
case Messages::HandleButtonEvent: {
|
|
Controllers::ButtonActions action;
|
|
if (nrf_gpio_pin_read(Pinetime::PinMap::Button) == 0) {
|
|
action = buttonHandler.HandleEvent(Controllers::ButtonHandler::Events::Release);
|
|
} else {
|
|
action = buttonHandler.HandleEvent(Controllers::ButtonHandler::Events::Press);
|
|
// This is for faster wakeup, sacrificing special longpress and doubleclick handling while sleeping
|
|
if (IsSleeping()) {
|
|
fastWakeUpDone = true;
|
|
GoToRunning();
|
|
break;
|
|
}
|
|
}
|
|
HandleButtonAction(action);
|
|
} break;
|
|
case Messages::HandleButtonTimerEvent: {
|
|
auto action = buttonHandler.HandleEvent(Controllers::ButtonHandler::Events::Timer);
|
|
HandleButtonAction(action);
|
|
} break;
|
|
case Messages::OnDisplayTaskSleeping:
|
|
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();
|
|
}
|
|
lcd.Sleep();
|
|
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;
|
|
break;
|
|
case Messages::OnNewDay:
|
|
// We might be sleeping (with TWI device disabled.
|
|
// Remember we'll have to reset the counter next time we're awake
|
|
stepCounterMustBeReset = true;
|
|
break;
|
|
case Messages::OnNewHour:
|
|
using Pinetime::Controllers::AlarmController;
|
|
if (settingsController.GetChimeOption() == Controllers::Settings::ChimesOption::Hours &&
|
|
alarmController.State() != AlarmController::AlarmState::Alerting) {
|
|
if (state == SystemTaskState::Sleeping) {
|
|
GoToRunning();
|
|
displayApp.PushMessage(Pinetime::Applications::Display::Messages::Clock);
|
|
}
|
|
motorController.RunForDuration(35);
|
|
}
|
|
break;
|
|
case Messages::OnNewHalfHour:
|
|
using Pinetime::Controllers::AlarmController;
|
|
if (settingsController.GetChimeOption() == Controllers::Settings::ChimesOption::HalfHours &&
|
|
alarmController.State() != AlarmController::AlarmState::Alerting) {
|
|
if (state == SystemTaskState::Sleeping) {
|
|
GoToRunning();
|
|
displayApp.PushMessage(Pinetime::Applications::Display::Messages::Clock);
|
|
}
|
|
motorController.RunForDuration(35);
|
|
}
|
|
break;
|
|
case Messages::OnChargingEvent:
|
|
batteryController.ReadPowerState();
|
|
motorController.RunForDuration(15);
|
|
ReloadIdleTimer();
|
|
if (state == SystemTaskState::Sleeping) {
|
|
GoToRunning();
|
|
}
|
|
break;
|
|
case Messages::MeasureBatteryTimerExpired:
|
|
batteryController.MeasureVoltage();
|
|
break;
|
|
case Messages::BatteryPercentageUpdated:
|
|
nimbleController.NotifyBatteryLevel(batteryController.PercentRemaining());
|
|
break;
|
|
case Messages::OnPairing:
|
|
if (state == SystemTaskState::Sleeping) {
|
|
GoToRunning();
|
|
}
|
|
motorController.RunForDuration(35);
|
|
displayApp.PushMessage(Pinetime::Applications::Display::Messages::ShowPairingKey);
|
|
break;
|
|
case Messages::BleRadioEnableToggle:
|
|
if (settingsController.GetBleRadioEnabled()) {
|
|
nimbleController.EnableRadio();
|
|
} else {
|
|
nimbleController.DisableRadio();
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (isBleDiscoveryTimerRunning) {
|
|
if (bleDiscoveryTimer == 0) {
|
|
isBleDiscoveryTimerRunning = false;
|
|
// Services discovery is deferred from 3 seconds to avoid the conflicts between the host communicating with the
|
|
// target and vice-versa. I'm not sure if this is the right way to handle this...
|
|
nimbleController.StartDiscovery();
|
|
} else {
|
|
bleDiscoveryTimer--;
|
|
}
|
|
}
|
|
|
|
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)) {
|
|
watchdog.Kick();
|
|
}
|
|
}
|
|
#pragma clang diagnostic pop
|
|
}
|
|
|
|
void SystemTask::UpdateMotion() {
|
|
if (state == SystemTaskState::GoingToSleep || state == SystemTaskState::WakingUp) {
|
|
return;
|
|
}
|
|
|
|
if (state == SystemTaskState::Sleeping && !(settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::RaiseWrist) ||
|
|
settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::Shake))) {
|
|
return;
|
|
}
|
|
|
|
if (stepCounterMustBeReset) {
|
|
motionSensor.ResetStepCounter();
|
|
stepCounterMustBeReset = false;
|
|
}
|
|
|
|
auto motionValues = motionSensor.Process();
|
|
|
|
motionController.IsSensorOk(motionSensor.IsOk());
|
|
motionController.Update(motionValues.x, motionValues.y, motionValues.z, motionValues.steps);
|
|
|
|
if (settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::RaiseWrist) &&
|
|
motionController.Should_RaiseWake(state == SystemTaskState::Sleeping)) {
|
|
GoToRunning();
|
|
}
|
|
if (settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::Shake) &&
|
|
motionController.Should_ShakeWake(settingsController.GetShakeThreshold())) {
|
|
GoToRunning();
|
|
}
|
|
}
|
|
|
|
void SystemTask::HandleButtonAction(Controllers::ButtonActions action) {
|
|
if (IsSleeping()) {
|
|
return;
|
|
}
|
|
|
|
ReloadIdleTimer();
|
|
|
|
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) {
|
|
displayApp.PushMessage(Applications::Display::Messages::ButtonPushed);
|
|
}
|
|
break;
|
|
case Actions::DoubleClick:
|
|
displayApp.PushMessage(Applications::Display::Messages::ButtonDoubleClicked);
|
|
break;
|
|
case Actions::LongPress:
|
|
displayApp.PushMessage(Applications::Display::Messages::ButtonLongPressed);
|
|
break;
|
|
case Actions::LongerPress:
|
|
displayApp.PushMessage(Applications::Display::Messages::ButtonLongerPressed);
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
|
|
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;
|
|
xHigherPriorityTaskWoken = pdFALSE;
|
|
xQueueSendFromISR(systemTasksMsgQueue, &msg, &xHigherPriorityTaskWoken);
|
|
if (xHigherPriorityTaskWoken) {
|
|
/* Actual macro used here is port specific. */
|
|
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);
|
|
}
|