mirror of
https://github.com/InfiniTimeOrg/InfiniTime.git
synced 2024-10-22 15:11:51 +02:00
Compare commits
12 commits
88dfcefb3f
...
90a71175a4
Author | SHA1 | Date | |
---|---|---|---|
90a71175a4 | |||
f0211e5fcb | |||
8f3b7b1f41 | |||
56e98195df | |||
a2356f2f4a | |||
3db4e012ce | |||
a0cd439efc | |||
997e4cee8c | |||
ad3bf49c7b | |||
7ca0418c82 | |||
c3d05901a0 | |||
b3756e45fa |
|
@ -402,6 +402,7 @@ list(APPEND SOURCE_FILES
|
||||||
displayapp/widgets/PageIndicator.cpp
|
displayapp/widgets/PageIndicator.cpp
|
||||||
displayapp/widgets/DotIndicator.cpp
|
displayapp/widgets/DotIndicator.cpp
|
||||||
displayapp/widgets/StatusIcons.cpp
|
displayapp/widgets/StatusIcons.cpp
|
||||||
|
displayapp/widgets/PopupMessage.cpp
|
||||||
|
|
||||||
## Settings
|
## Settings
|
||||||
displayapp/screens/settings/QuickSettings.cpp
|
displayapp/screens/settings/QuickSettings.cpp
|
||||||
|
@ -478,6 +479,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 +544,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 +663,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
|
||||||
|
|
|
@ -62,7 +62,7 @@
|
||||||
#define configTICK_RATE_HZ 1024
|
#define configTICK_RATE_HZ 1024
|
||||||
#define configMAX_PRIORITIES (3)
|
#define configMAX_PRIORITIES (3)
|
||||||
#define configMINIMAL_STACK_SIZE (120)
|
#define configMINIMAL_STACK_SIZE (120)
|
||||||
#define configTOTAL_HEAP_SIZE (1024 * 40)
|
#define configTOTAL_HEAP_SIZE (1024 * 35)
|
||||||
#define configMAX_TASK_NAME_LEN (4)
|
#define configMAX_TASK_NAME_LEN (4)
|
||||||
#define configUSE_16_BIT_TICKS 0
|
#define configUSE_16_BIT_TICKS 0
|
||||||
#define configIDLE_SHOULD_YIELD 1
|
#define configIDLE_SHOULD_YIELD 1
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -13,7 +13,14 @@ namespace Pinetime {
|
||||||
enum class WeatherFormat : uint8_t { Metric, Imperial };
|
enum class WeatherFormat : uint8_t { Metric, Imperial };
|
||||||
enum class Notification : uint8_t { On, Off, Sleep };
|
enum class Notification : uint8_t { On, Off, Sleep };
|
||||||
enum class ChimesOption : uint8_t { None, Hours, HalfHours };
|
enum class ChimesOption : uint8_t { None, Hours, HalfHours };
|
||||||
enum class WakeUpMode : uint8_t { SingleTap = 0, DoubleTap = 1, RaiseWrist = 2, Shake = 3, LowerWrist = 4 };
|
enum class WakeUpMode : uint8_t {
|
||||||
|
SingleTap = 0,
|
||||||
|
DoubleTap = 1,
|
||||||
|
RaiseWrist = 2,
|
||||||
|
Shake = 3,
|
||||||
|
LowerWrist = 4,
|
||||||
|
ButtonUnlocks = 5,
|
||||||
|
};
|
||||||
enum class Colors : uint8_t {
|
enum class Colors : uint8_t {
|
||||||
White,
|
White,
|
||||||
Silver,
|
Silver,
|
||||||
|
@ -260,7 +267,7 @@ namespace Pinetime {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
std::bitset<5> getWakeUpModes() const {
|
std::bitset<6> getWakeUpModes() const {
|
||||||
return settings.wakeUpMode;
|
return settings.wakeUpMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -321,7 +328,7 @@ namespace Pinetime {
|
||||||
|
|
||||||
WatchFaceInfineat watchFaceInfineat;
|
WatchFaceInfineat watchFaceInfineat;
|
||||||
|
|
||||||
std::bitset<5> wakeUpMode {0};
|
std::bitset<6> wakeUpMode {0};
|
||||||
uint16_t shakeWakeThreshold = 150;
|
uint16_t shakeWakeThreshold = 150;
|
||||||
|
|
||||||
Controllers::BrightnessController::Levels brightLevel = Controllers::BrightnessController::Levels::Medium;
|
Controllers::BrightnessController::Levels brightLevel = Controllers::BrightnessController::Levels::Medium;
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#include "displayapp/screens/Weather.h"
|
#include "displayapp/screens/Weather.h"
|
||||||
#include "displayapp/screens/PassKey.h"
|
#include "displayapp/screens/PassKey.h"
|
||||||
#include "displayapp/screens/Error.h"
|
#include "displayapp/screens/Error.h"
|
||||||
|
#include "displayapp/screens/Symbols.h"
|
||||||
|
|
||||||
#include "drivers/Cst816s.h"
|
#include "drivers/Cst816s.h"
|
||||||
#include "drivers/St7789.h"
|
#include "drivers/St7789.h"
|
||||||
|
@ -101,6 +102,7 @@ DisplayApp::DisplayApp(Drivers::St7789& lcd,
|
||||||
spiNorFlash {spiNorFlash},
|
spiNorFlash {spiNorFlash},
|
||||||
lvgl {lcd, filesystem},
|
lvgl {lcd, filesystem},
|
||||||
timer(this, TimerCallback),
|
timer(this, TimerCallback),
|
||||||
|
popupMessage {Screens::Symbols::lock, 90, 90},
|
||||||
controllers {batteryController,
|
controllers {batteryController,
|
||||||
bleController,
|
bleController,
|
||||||
dateTimeController,
|
dateTimeController,
|
||||||
|
@ -255,9 +257,20 @@ void DisplayApp::Refresh() {
|
||||||
isDimmed = true;
|
isDimmed = true;
|
||||||
brightnessController.Set(Controllers::BrightnessController::Levels::Low);
|
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) {
|
||||||
isDimmed = false;
|
isDimmed = false;
|
||||||
|
@ -273,6 +286,9 @@ void DisplayApp::Refresh() {
|
||||||
if (xQueueReceive(msgQueue, &msg, queueTimeout) == pdTRUE) {
|
if (xQueueReceive(msgQueue, &msg, queueTimeout) == pdTRUE) {
|
||||||
switch (msg) {
|
switch (msg) {
|
||||||
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);
|
||||||
|
@ -307,6 +323,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 {
|
||||||
|
@ -439,6 +458,12 @@ void DisplayApp::Refresh() {
|
||||||
case Messages::OnChargingEvent:
|
case Messages::OnChargingEvent:
|
||||||
motorController.RunForDuration(15);
|
motorController.RunForDuration(15);
|
||||||
break;
|
break;
|
||||||
|
case Messages::ShowIgnoreTouchPopup:
|
||||||
|
popupMessage.SetHidden(false);
|
||||||
|
break;
|
||||||
|
case Messages::HideIgnoreTouchPopup:
|
||||||
|
popupMessage.SetHidden(true);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -562,10 +587,10 @@ void DisplayApp::LoadScreen(Apps app, DisplayApp::FullRefreshDirections directio
|
||||||
currentScreen = std::make_unique<Screens::SettingWeatherFormat>(settingsController);
|
currentScreen = std::make_unique<Screens::SettingWeatherFormat>(settingsController);
|
||||||
break;
|
break;
|
||||||
case Apps::SettingWakeUp:
|
case Apps::SettingWakeUp:
|
||||||
currentScreen = std::make_unique<Screens::SettingWakeUp>(settingsController);
|
currentScreen = std::make_unique<Screens::SettingWakeUp>(this, 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);
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include "components/timer/Timer.h"
|
#include "components/timer/Timer.h"
|
||||||
#include "components/alarm/AlarmController.h"
|
#include "components/alarm/AlarmController.h"
|
||||||
#include "touchhandler/TouchHandler.h"
|
#include "touchhandler/TouchHandler.h"
|
||||||
|
#include "displayapp/widgets/PopupMessage.h"
|
||||||
|
|
||||||
#include "displayapp/Messages.h"
|
#include "displayapp/Messages.h"
|
||||||
#include "BootErrors.h"
|
#include "BootErrors.h"
|
||||||
|
@ -102,8 +103,10 @@ namespace Pinetime {
|
||||||
Pinetime::Controllers::FirmwareValidator validator;
|
Pinetime::Controllers::FirmwareValidator validator;
|
||||||
Pinetime::Components::LittleVgl lvgl;
|
Pinetime::Components::LittleVgl lvgl;
|
||||||
Pinetime::Controllers::Timer timer;
|
Pinetime::Controllers::Timer timer;
|
||||||
|
Pinetime::Applications::Widgets::PopupMessage popupMessage;
|
||||||
|
|
||||||
AppControllers controllers;
|
AppControllers controllers;
|
||||||
|
|
||||||
TaskHandle_t taskHandle;
|
TaskHandle_t taskHandle;
|
||||||
|
|
||||||
States state = States::Running;
|
States state = States::Running;
|
||||||
|
|
|
@ -24,6 +24,8 @@ namespace Pinetime {
|
||||||
Chime,
|
Chime,
|
||||||
BleRadioEnableToggle,
|
BleRadioEnableToggle,
|
||||||
OnChargingEvent,
|
OnChargingEvent,
|
||||||
|
ShowIgnoreTouchPopup,
|
||||||
|
HideIgnoreTouchPopup
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
set(FONTS jetbrains_mono_42 jetbrains_mono_76 jetbrains_mono_bold_20
|
set(FONTS jetbrains_mono_42 jetbrains_mono_76 jetbrains_mono_bold_20
|
||||||
jetbrains_mono_extrabold_compressed lv_font_sys_48
|
jetbrains_mono_extrabold_compressed lv_font_sys_48 lv_font_sys_80
|
||||||
open_sans_light fontawesome_weathericons)
|
open_sans_light fontawesome_weathericons)
|
||||||
find_program(LV_FONT_CONV "lv_font_conv" NO_CACHE REQUIRED
|
find_program(LV_FONT_CONV "lv_font_conv" NO_CACHE REQUIRED
|
||||||
HINTS "${CMAKE_SOURCE_DIR}/node_modules/.bin")
|
HINTS "${CMAKE_SOURCE_DIR}/node_modules/.bin")
|
||||||
|
|
|
@ -64,6 +64,16 @@
|
||||||
"bpp": 1,
|
"bpp": 1,
|
||||||
"size": 48
|
"size": 48
|
||||||
},
|
},
|
||||||
|
"lv_font_sys_80": {
|
||||||
|
"sources": [
|
||||||
|
{
|
||||||
|
"file": "material-design-icons/MaterialIcons-Regular.ttf",
|
||||||
|
"range": "0xe897"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"bpp": 1,
|
||||||
|
"size": 80
|
||||||
|
},
|
||||||
"fontawesome_weathericons": {
|
"fontawesome_weathericons": {
|
||||||
"sources": [
|
"sources": [
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,7 +119,7 @@ void Notifications::Refresh() {
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
29
src/displayapp/screens/Page.h
Normal file
29
src/displayapp/screens/Page.h
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <lvgl/lvgl.h>
|
||||||
|
#include "displayapp/screens/Screen.h"
|
||||||
|
#include "displayapp/widgets/PageIndicator.h"
|
||||||
|
|
||||||
|
namespace Pinetime {
|
||||||
|
|
||||||
|
namespace Applications {
|
||||||
|
namespace Screens {
|
||||||
|
|
||||||
|
class Page : public Screen {
|
||||||
|
public:
|
||||||
|
Page(uint8_t screenID, uint8_t numScreens, lv_obj_t* contentObj) : contentObj {contentObj}, pageIndicator(screenID, numScreens) {
|
||||||
|
pageIndicator.Create();
|
||||||
|
}
|
||||||
|
|
||||||
|
~Page() override {
|
||||||
|
lv_obj_clean(lv_scr_act());
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
lv_obj_t* contentObj = nullptr;
|
||||||
|
Widgets::PageIndicator pageIndicator;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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() {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -64,6 +64,9 @@ namespace Pinetime {
|
||||||
|
|
||||||
static constexpr const char* flashlight = "\xEF\x80\x8B";
|
static constexpr const char* flashlight = "\xEF\x80\x8B";
|
||||||
static constexpr const char* paintbrushLg = "\xEE\x90\x8A";
|
static constexpr const char* paintbrushLg = "\xEE\x90\x8A";
|
||||||
|
|
||||||
|
// wake-up screenlock icon, from material icons
|
||||||
|
static constexpr const char* lock = "\xEE\xA2\x97";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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},
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,17 @@
|
||||||
|
|
||||||
using namespace Pinetime::Applications::Screens;
|
using namespace Pinetime::Applications::Screens;
|
||||||
|
|
||||||
constexpr std::array<SettingWakeUp::Option, 5> SettingWakeUp::options;
|
constexpr std::array<SettingWakeUp::Option, SettingWakeUp::numOptions> SettingWakeUp::options;
|
||||||
|
|
||||||
|
auto SettingWakeUp::CreateScreenList() {
|
||||||
|
std::array<std::function<std::unique_ptr<Screen>()>, nScreens> screens;
|
||||||
|
for (size_t i = 0; i < screens.size(); i++) {
|
||||||
|
screens[i] = [this, i]() -> std::unique_ptr<Screen> {
|
||||||
|
return CreateScreen(i);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return screens;
|
||||||
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
void event_handler(lv_obj_t* obj, lv_event_t event) {
|
void event_handler(lv_obj_t* obj, lv_event_t event) {
|
||||||
|
@ -19,7 +29,16 @@ namespace {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SettingWakeUp::SettingWakeUp(Pinetime::Controllers::Settings& settingsController) : settingsController {settingsController} {
|
SettingWakeUp::SettingWakeUp(Pinetime::Applications::DisplayApp* app, Pinetime::Controllers::Settings& settingsController)
|
||||||
|
: settingsController {settingsController}, screens {app, 0, CreateScreenList(), Screens::ScreenListModes::UpDown} {
|
||||||
|
}
|
||||||
|
|
||||||
|
SettingWakeUp::~SettingWakeUp() {
|
||||||
|
lv_obj_clean(lv_scr_act());
|
||||||
|
settingsController.SaveSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<Screen> SettingWakeUp::CreateScreen(size_t screenNum) {
|
||||||
lv_obj_t* container1 = lv_cont_create(lv_scr_act(), nullptr);
|
lv_obj_t* container1 = lv_cont_create(lv_scr_act(), nullptr);
|
||||||
|
|
||||||
lv_obj_set_style_local_bg_opa(container1, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_TRANSP);
|
lv_obj_set_style_local_bg_opa(container1, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_TRANSP);
|
||||||
|
@ -43,20 +62,29 @@ SettingWakeUp::SettingWakeUp(Pinetime::Controllers::Settings& settingsController
|
||||||
lv_label_set_align(icon, LV_LABEL_ALIGN_CENTER);
|
lv_label_set_align(icon, LV_LABEL_ALIGN_CENTER);
|
||||||
lv_obj_align(icon, title, LV_ALIGN_OUT_LEFT_MID, -10, 0);
|
lv_obj_align(icon, title, LV_ALIGN_OUT_LEFT_MID, -10, 0);
|
||||||
|
|
||||||
for (unsigned int i = 0; i < options.size(); i++) {
|
// cleanup any old pointers
|
||||||
|
cbOption.fill(nullptr);
|
||||||
|
|
||||||
|
// only loop as far as the list size aĺlows
|
||||||
|
unsigned int loopMax = screenNum * optionsPerScreen + optionsPerScreen;
|
||||||
|
if (loopMax > options.size()) {
|
||||||
|
loopMax = options.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned int i = screenNum * optionsPerScreen; i < loopMax; i++) {
|
||||||
cbOption[i] = lv_checkbox_create(container1, nullptr);
|
cbOption[i] = lv_checkbox_create(container1, nullptr);
|
||||||
lv_checkbox_set_text(cbOption[i], options[i].name);
|
lv_checkbox_set_text(cbOption[i], options[i].name);
|
||||||
if (settingsController.isWakeUpModeOn(static_cast<Controllers::Settings::WakeUpMode>(i))) {
|
if (settingsController.isWakeUpModeOn(options[i].wakeUpMode)) {
|
||||||
lv_checkbox_set_checked(cbOption[i], true);
|
lv_checkbox_set_checked(cbOption[i], true);
|
||||||
}
|
}
|
||||||
cbOption[i]->user_data = this;
|
cbOption[i]->user_data = this;
|
||||||
lv_obj_set_event_cb(cbOption[i], event_handler);
|
lv_obj_set_event_cb(cbOption[i], event_handler);
|
||||||
}
|
}
|
||||||
|
return std::make_unique<Screens::Page>(screenNum, nScreens, container1);
|
||||||
}
|
}
|
||||||
|
|
||||||
SettingWakeUp::~SettingWakeUp() {
|
bool SettingWakeUp::OnTouchEvent(Pinetime::Applications::TouchEvents event) {
|
||||||
lv_obj_clean(lv_scr_act());
|
return screens.OnTouchEvent(event);
|
||||||
settingsController.SaveSettings();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SettingWakeUp::UpdateSelected(lv_obj_t* object) {
|
void SettingWakeUp::UpdateSelected(lv_obj_t* object) {
|
||||||
|
@ -74,6 +102,8 @@ void SettingWakeUp::UpdateSelected(lv_obj_t* object) {
|
||||||
// for example, when setting SingleTap, DoubleTap is unset and vice versa.
|
// for example, when setting SingleTap, DoubleTap is unset and vice versa.
|
||||||
auto modes = settingsController.getWakeUpModes();
|
auto modes = settingsController.getWakeUpModes();
|
||||||
for (size_t i = 0; i < options.size(); ++i) {
|
for (size_t i = 0; i < options.size(); ++i) {
|
||||||
lv_checkbox_set_checked(cbOption[i], modes[i]);
|
if (cbOption[i]) {
|
||||||
|
lv_checkbox_set_checked(cbOption[i], modes[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,10 @@
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <lvgl/lvgl.h>
|
#include <lvgl/lvgl.h>
|
||||||
#include "components/settings/Settings.h"
|
#include "components/settings/Settings.h"
|
||||||
|
#include "displayapp/screens/Page.h"
|
||||||
#include "displayapp/screens/Screen.h"
|
#include "displayapp/screens/Screen.h"
|
||||||
|
#include "displayapp/screens/ScreenList.h"
|
||||||
|
#include "displayapp/widgets/PageIndicator.h"
|
||||||
|
|
||||||
namespace Pinetime {
|
namespace Pinetime {
|
||||||
|
|
||||||
|
@ -13,27 +16,40 @@ namespace Pinetime {
|
||||||
|
|
||||||
class SettingWakeUp : public Screen {
|
class SettingWakeUp : public Screen {
|
||||||
public:
|
public:
|
||||||
SettingWakeUp(Pinetime::Controllers::Settings& settingsController);
|
SettingWakeUp(Pinetime::Applications::DisplayApp* app, Pinetime::Controllers::Settings& settingsController);
|
||||||
~SettingWakeUp() override;
|
~SettingWakeUp() override;
|
||||||
|
|
||||||
void UpdateSelected(lv_obj_t* object);
|
void UpdateSelected(lv_obj_t* object);
|
||||||
|
|
||||||
|
bool OnTouchEvent(TouchEvents event) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
auto CreateScreenList();
|
||||||
|
std::unique_ptr<Screen> CreateScreen(size_t screenNum);
|
||||||
|
|
||||||
struct Option {
|
struct Option {
|
||||||
Controllers::Settings::WakeUpMode wakeUpMode;
|
Controllers::Settings::WakeUpMode wakeUpMode;
|
||||||
const char* name;
|
const char* name;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static constexpr size_t numOptions = 6;
|
||||||
|
static constexpr size_t optionsPerScreen = 4;
|
||||||
|
static constexpr size_t nScreens = 2;
|
||||||
|
|
||||||
Controllers::Settings& settingsController;
|
Controllers::Settings& settingsController;
|
||||||
static constexpr std::array<Option, 5> options = {{
|
|
||||||
|
ScreenList<nScreens> screens;
|
||||||
|
|
||||||
|
static constexpr std::array<Option, numOptions> options = {{
|
||||||
{Controllers::Settings::WakeUpMode::SingleTap, "Single Tap"},
|
{Controllers::Settings::WakeUpMode::SingleTap, "Single Tap"},
|
||||||
{Controllers::Settings::WakeUpMode::DoubleTap, "Double Tap"},
|
{Controllers::Settings::WakeUpMode::DoubleTap, "Double Tap"},
|
||||||
{Controllers::Settings::WakeUpMode::RaiseWrist, "Raise Wrist"},
|
{Controllers::Settings::WakeUpMode::RaiseWrist, "Raise Wrist"},
|
||||||
{Controllers::Settings::WakeUpMode::Shake, "Shake Wake"},
|
{Controllers::Settings::WakeUpMode::Shake, "Shake Wake"},
|
||||||
{Controllers::Settings::WakeUpMode::LowerWrist, "Lower Wrist"},
|
{Controllers::Settings::WakeUpMode::LowerWrist, "Lower Wrist"},
|
||||||
|
{Controllers::Settings::WakeUpMode::ButtonUnlocks, "Button Unlock"},
|
||||||
}};
|
}};
|
||||||
|
|
||||||
lv_obj_t* cbOption[options.size()];
|
std::array<lv_obj_t*, numOptions> cbOption;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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} {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
37
src/displayapp/widgets/PopupMessage.cpp
Normal file
37
src/displayapp/widgets/PopupMessage.cpp
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
#include "displayapp/widgets/PopupMessage.h"
|
||||||
|
#include <libraries/log/nrf_log.h>
|
||||||
|
|
||||||
|
using namespace Pinetime::Applications::Widgets;
|
||||||
|
|
||||||
|
PopupMessage::PopupMessage(const char* msg, int16_t h, int16_t w) : message {msg}, height {h}, width {w} {
|
||||||
|
}
|
||||||
|
|
||||||
|
void PopupMessage::Create() {
|
||||||
|
btnPopup = lv_btn_create(lv_scr_act(), nullptr);
|
||||||
|
btnPopup->user_data = this;
|
||||||
|
lv_obj_set_size(btnPopup, height, width);
|
||||||
|
lv_obj_align(btnPopup, lv_scr_act(), LV_ALIGN_CENTER, 0, 0);
|
||||||
|
lv_obj_set_style_local_bg_opa(btnPopup, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_60);
|
||||||
|
lv_obj_set_style_local_text_font(btnPopup, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &lv_font_sys_80);
|
||||||
|
lv_obj_t* lblMessage = lv_label_create(btnPopup, nullptr);
|
||||||
|
lv_label_set_text_static(lblMessage, message);
|
||||||
|
lv_obj_set_hidden(btnPopup, isHidden);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PopupMessage::SetHidden(bool hidden) {
|
||||||
|
if (isHidden == hidden) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
isHidden = hidden;
|
||||||
|
// create/delete on demand
|
||||||
|
if (btnPopup == nullptr && !isHidden) {
|
||||||
|
Create();
|
||||||
|
} else if (btnPopup != nullptr) {
|
||||||
|
lv_obj_del(btnPopup);
|
||||||
|
btnPopup = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PopupMessage::IsHidden() {
|
||||||
|
return isHidden;
|
||||||
|
}
|
24
src/displayapp/widgets/PopupMessage.h
Normal file
24
src/displayapp/widgets/PopupMessage.h
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
#pragma once
|
||||||
|
#include <lvgl/lvgl.h>
|
||||||
|
|
||||||
|
namespace Pinetime {
|
||||||
|
namespace Applications {
|
||||||
|
namespace Widgets {
|
||||||
|
class PopupMessage {
|
||||||
|
public:
|
||||||
|
// The caller owns the message string, it is not copied.
|
||||||
|
PopupMessage(const char* msg, int16_t h, int16_t w);
|
||||||
|
void Create();
|
||||||
|
void SetHidden(bool hidden);
|
||||||
|
bool IsHidden();
|
||||||
|
|
||||||
|
private:
|
||||||
|
const char* message;
|
||||||
|
lv_obj_t* btnPopup = nullptr;
|
||||||
|
bool isHidden = true;
|
||||||
|
int16_t height;
|
||||||
|
int16_t width;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -419,7 +419,8 @@ typedef void* lv_indev_drv_user_data_t; /*Type of user data in the in
|
||||||
LV_FONT_DECLARE(jetbrains_mono_76) \
|
LV_FONT_DECLARE(jetbrains_mono_76) \
|
||||||
LV_FONT_DECLARE(open_sans_light) \
|
LV_FONT_DECLARE(open_sans_light) \
|
||||||
LV_FONT_DECLARE(fontawesome_weathericons) \
|
LV_FONT_DECLARE(fontawesome_weathericons) \
|
||||||
LV_FONT_DECLARE(lv_font_sys_48)
|
LV_FONT_DECLARE(lv_font_sys_48) \
|
||||||
|
LV_FONT_DECLARE(lv_font_sys_80)
|
||||||
|
|
||||||
/* Enable it if you have fonts with a lot of characters.
|
/* Enable it if you have fonts with a lot of characters.
|
||||||
* The limit depends on the font size, font face and bpp
|
* The limit depends on the font size, font face and bpp
|
||||||
|
|
|
@ -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 {};
|
||||||
|
|
|
@ -189,39 +189,21 @@ 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;
|
|
||||||
}
|
|
||||||
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())) {
|
Pinetime::Controllers::TouchHandler::TouchProcessReply reply;
|
||||||
|
reply =
|
||||||
|
touchHandler.ProcessTouchInfo(touchPanel.GetTouchInfo(),
|
||||||
|
settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::ButtonUnlocks));
|
||||||
|
if (reply == Pinetime::Controllers::TouchHandler::TouchProcessReply::TouchEvent) {
|
||||||
auto gesture = touchHandler.GestureGet();
|
auto gesture = touchHandler.GestureGet();
|
||||||
if (settingsController.GetNotificationStatus() != Controllers::Settings::Notification::Sleep &&
|
if (settingsController.GetNotificationStatus() != Controllers::Settings::Notification::Sleep &&
|
||||||
gesture != Pinetime::Applications::TouchEvents::None &&
|
gesture != Pinetime::Applications::TouchEvents::None &&
|
||||||
|
@ -229,37 +211,32 @@ void SystemTask::Work() {
|
||||||
settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::DoubleTap)) ||
|
settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::DoubleTap)) ||
|
||||||
(gesture == Pinetime::Applications::TouchEvents::Tap &&
|
(gesture == Pinetime::Applications::TouchEvents::Tap &&
|
||||||
settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::SingleTap)))) {
|
settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::SingleTap)))) {
|
||||||
|
touchHandler.SetWokenBy(Pinetime::Controllers::TouchHandler::WokenBy::WakeUpAction, true);
|
||||||
GoToRunning();
|
GoToRunning();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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:
|
||||||
if (alarmController.State() == Controllers::AlarmController::AlarmState::Set) {
|
if (alarmController.IsEnabled()) {
|
||||||
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();
|
||||||
}
|
}
|
||||||
|
touchHandler.SetWokenBy(Pinetime::Controllers::TouchHandler::WokenBy::Other, false);
|
||||||
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();
|
touchHandler.SetWokenBy(Pinetime::Controllers::TouchHandler::WokenBy::Other, false);
|
||||||
}
|
|
||||||
displayApp.PushMessage(Pinetime::Applications::Display::Messages::AlarmTriggered);
|
displayApp.PushMessage(Pinetime::Applications::Display::Messages::AlarmTriggered);
|
||||||
break;
|
break;
|
||||||
case Messages::BleConnected:
|
case Messages::BleConnected:
|
||||||
|
@ -268,56 +245,76 @@ void SystemTask::Work() {
|
||||||
bleDiscoveryTimer = 5;
|
bleDiscoveryTimer = 5;
|
||||||
break;
|
break;
|
||||||
case Messages::BleFirmwareUpdateStarted:
|
case Messages::BleFirmwareUpdateStarted:
|
||||||
doNotGoToSleep = true;
|
GoToRunning();
|
||||||
if (state == SystemTaskState::Sleeping) {
|
wakeLocksHeld++;
|
||||||
GoToRunning();
|
touchHandler.SetWokenBy(Pinetime::Controllers::TouchHandler::WokenBy::Other, false);
|
||||||
}
|
|
||||||
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();
|
touchHandler.SetWokenBy(Pinetime::Controllers::TouchHandler::WokenBy::Other, false);
|
||||||
}
|
|
||||||
// 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:
|
||||||
if (touchHandler.ProcessTouchInfo(touchPanel.GetTouchInfo())) {
|
Pinetime::Controllers::TouchHandler::TouchProcessReply reply;
|
||||||
|
reply =
|
||||||
|
touchHandler.ProcessTouchInfo(touchPanel.GetTouchInfo(),
|
||||||
|
settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::ButtonUnlocks));
|
||||||
|
if (reply == Pinetime::Controllers::TouchHandler::TouchProcessReply::TouchEvent) {
|
||||||
displayApp.PushMessage(Pinetime::Applications::Display::Messages::TouchEvent);
|
displayApp.PushMessage(Pinetime::Applications::Display::Messages::TouchEvent);
|
||||||
|
} else if (reply == Pinetime::Controllers::TouchHandler::TouchProcessReply::IgnoreTouchPopup) {
|
||||||
|
displayApp.PushMessage(Pinetime::Applications::Display::Messages::ShowIgnoreTouchPopup);
|
||||||
|
touchHandler.SetIgnoreTouchPopupHidden(false);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Messages::HandleButtonEvent: {
|
case Messages::HandleButtonEvent: {
|
||||||
Controllers::ButtonActions action = Controllers::ButtonActions::None;
|
// if the IgnoreTouchPopup is active the first button event unlocks the device
|
||||||
if (nrf_gpio_pin_read(Pinetime::PinMap::Button) == 0) {
|
if (!touchHandler.IsIgnoreTouchPopupHidden()) {
|
||||||
action = buttonHandler.HandleEvent(Controllers::ButtonHandler::Events::Release);
|
touchHandler.SetWokenBy(Pinetime::Controllers::TouchHandler::WokenBy::Button, false);
|
||||||
|
touchHandler.SetIgnoreTouchPopupHidden(true);
|
||||||
|
displayApp.PushMessage(Pinetime::Applications::Display::Messages::HideIgnoreTouchPopup);
|
||||||
} else {
|
} else {
|
||||||
action = buttonHandler.HandleEvent(Controllers::ButtonHandler::Events::Press);
|
Controllers::ButtonActions action = Controllers::ButtonActions::None;
|
||||||
// This is for faster wakeup, sacrificing special longpress and doubleclick handling while sleeping
|
if (nrf_gpio_pin_read(Pinetime::PinMap::Button) == 0) {
|
||||||
if (IsSleeping()) {
|
action = buttonHandler.HandleEvent(Controllers::ButtonHandler::Events::Release);
|
||||||
fastWakeUpDone = true;
|
} else {
|
||||||
GoToRunning();
|
action = buttonHandler.HandleEvent(Controllers::ButtonHandler::Events::Press);
|
||||||
break;
|
touchHandler.SetWokenBy(Pinetime::Controllers::TouchHandler::WokenBy::Button, false);
|
||||||
|
// This is for faster wakeup, sacrificing special longpress and doubleclick handling while sleeping
|
||||||
|
if (IsSleeping()) {
|
||||||
|
fastWakeUpDone = true;
|
||||||
|
GoToRunning();
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
HandleButtonAction(action);
|
||||||
}
|
}
|
||||||
HandleButtonAction(action);
|
|
||||||
} break;
|
} break;
|
||||||
case Messages::HandleButtonTimerEvent: {
|
case Messages::HandleButtonTimerEvent: {
|
||||||
auto action = buttonHandler.HandleEvent(Controllers::ButtonHandler::Events::Timer);
|
auto action = buttonHandler.HandleEvent(Controllers::ButtonHandler::Events::Timer);
|
||||||
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.
|
||||||
|
@ -335,6 +332,8 @@ void SystemTask::Work() {
|
||||||
}
|
}
|
||||||
|
|
||||||
state = SystemTaskState::Sleeping;
|
state = SystemTaskState::Sleeping;
|
||||||
|
// reset touch restrictions when going to sleep
|
||||||
|
touchHandler.SetWokenBy(Pinetime::Controllers::TouchHandler::WokenBy::Other, false);
|
||||||
break;
|
break;
|
||||||
case Messages::OnNewDay:
|
case Messages::OnNewDay:
|
||||||
// We might be sleeping (with TWI device disabled.
|
// We might be sleeping (with TWI device disabled.
|
||||||
|
@ -344,39 +343,26 @@ 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)
|
touchHandler.SetWokenBy(Pinetime::Controllers::TouchHandler::WokenBy::Other, false);
|
||||||
// request running first and repush the chime message
|
displayApp.PushMessage(Pinetime::Applications::Display::Messages::Chime);
|
||||||
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)
|
touchHandler.SetWokenBy(Pinetime::Controllers::TouchHandler::WokenBy::Other, false);
|
||||||
// request running first and repush the chime message
|
displayApp.PushMessage(Pinetime::Applications::Display::Messages::Chime);
|
||||||
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();
|
||||||
|
touchHandler.SetWokenBy(Pinetime::Controllers::TouchHandler::WokenBy::Other, false);
|
||||||
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();
|
||||||
|
@ -385,9 +371,8 @@ 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();
|
touchHandler.SetWokenBy(Pinetime::Controllers::TouchHandler::WokenBy::Other, false);
|
||||||
}
|
|
||||||
displayApp.PushMessage(Pinetime::Applications::Display::Messages::ShowPairingKey);
|
displayApp.PushMessage(Pinetime::Applications::Display::Messages::ShowPairingKey);
|
||||||
break;
|
break;
|
||||||
case Messages::BleRadioEnableToggle:
|
case Messages::BleRadioEnableToggle:
|
||||||
|
@ -422,14 +407,52 @@ 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);
|
||||||
|
touchHandler.SetIgnoreTouchPopupHidden(true);
|
||||||
|
displayApp.PushMessage(Pinetime::Applications::Display::Messages::HideIgnoreTouchPopup);
|
||||||
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -447,12 +470,15 @@ void SystemTask::UpdateMotion() {
|
||||||
motionController.ShouldRaiseWake()) ||
|
motionController.ShouldRaiseWake()) ||
|
||||||
(settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::Shake) &&
|
(settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::Shake) &&
|
||||||
motionController.ShouldShakeWake(settingsController.GetShakeThreshold()))) {
|
motionController.ShouldShakeWake(settingsController.GetShakeThreshold()))) {
|
||||||
|
if (state == SystemTaskState::Sleeping) {
|
||||||
|
touchHandler.SetWokenBy(Pinetime::Controllers::TouchHandler::WokenBy::WakeUpAction, true);
|
||||||
|
}
|
||||||
GoToRunning();
|
GoToRunning();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -468,7 +494,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;
|
||||||
|
@ -488,17 +514,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);
|
||||||
|
@ -507,10 +526,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);
|
||||||
|
|
|
@ -52,7 +52,12 @@ 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 };
|
||||||
|
// Enum describes how the watch was woken:
|
||||||
|
// * WakeUpAction: The actions selected in the wakeup settings, single/double tap, raise, shake
|
||||||
|
// * Button: The hardware button
|
||||||
|
// * Other: Other things that can wake the watch up, eg. apps and notifications.
|
||||||
|
enum class WokenBy { WakeUpAction, Button, Other };
|
||||||
SystemTask(Drivers::SpiMaster& spi,
|
SystemTask(Drivers::SpiMaster& spi,
|
||||||
Pinetime::Drivers::SpiNorFlash& spiNorFlash,
|
Pinetime::Drivers::SpiNorFlash& spiNorFlash,
|
||||||
Drivers::TwiMaster& twiMaster,
|
Drivers::TwiMaster& twiMaster,
|
||||||
|
@ -79,11 +84,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 +93,7 @@ namespace Pinetime {
|
||||||
};
|
};
|
||||||
|
|
||||||
bool IsSleeping() const {
|
bool IsSleeping() const {
|
||||||
return state == SystemTaskState::Sleeping || state == SystemTaskState::WakingUp;
|
return state != SystemTaskState::Running;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -127,13 +129,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);
|
||||||
|
|
27
src/systemtask/WakeLock.cpp
Normal file
27
src/systemtask/WakeLock.cpp
Normal 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
19
src/systemtask/WakeLock.h
Normal 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;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -33,9 +33,9 @@ Pinetime::Applications::TouchEvents TouchHandler::GestureGet() {
|
||||||
return returnGesture;
|
return returnGesture;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TouchHandler::ProcessTouchInfo(Drivers::Cst816S::TouchInfos info) {
|
TouchHandler::TouchProcessReply TouchHandler::ProcessTouchInfo(Drivers::Cst816S::TouchInfos info, bool buttonUnlocksOn) {
|
||||||
if (!info.isValid) {
|
if (!info.isValid) {
|
||||||
return false;
|
return TouchHandler::TouchProcessReply::NoAction;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only a single gesture per touch
|
// Only a single gesture per touch
|
||||||
|
@ -62,5 +62,19 @@ bool TouchHandler::ProcessTouchInfo(Drivers::Cst816S::TouchInfos info) {
|
||||||
|
|
||||||
currentTouchPoint = {info.x, info.y, info.touching};
|
currentTouchPoint = {info.x, info.y, info.touching};
|
||||||
|
|
||||||
return true;
|
// if the watch was just woken by touch and button must be used to unlock, ignore the first touch event which
|
||||||
|
// is the touch event that woke the watch. Otherwise the lock-popup will be displayed
|
||||||
|
if (buttonUnlocksOn && ignoreNextTouchEvent) {
|
||||||
|
ignoreNextTouchEvent = false;
|
||||||
|
return TouchHandler::TouchProcessReply::NoAction;
|
||||||
|
|
||||||
|
} else if (!buttonUnlocksOn || wokenBy != WokenBy::WakeUpAction) {
|
||||||
|
|
||||||
|
// if we get to here TouchEvents is allowed and the "ButtonUnlocks" requirement can be overridden
|
||||||
|
wokenBy = WokenBy::Other;
|
||||||
|
|
||||||
|
return TouchHandler::TouchProcessReply::TouchEvent;
|
||||||
|
} else {
|
||||||
|
return TouchHandler::TouchProcessReply::IgnoreTouchPopup;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,13 +6,25 @@ namespace Pinetime {
|
||||||
namespace Controllers {
|
namespace Controllers {
|
||||||
class TouchHandler {
|
class TouchHandler {
|
||||||
public:
|
public:
|
||||||
|
// Enum describes how the watch was woken:
|
||||||
|
// * WakeUpAction: The actions selected in the wakeup settings, single/double tap, raise, shake
|
||||||
|
// * Button: The hardware button
|
||||||
|
// * Other: Other things that can wake the watch up, eg. apps and notifications.
|
||||||
|
enum class WokenBy { WakeUpAction, Button, Other };
|
||||||
|
|
||||||
|
// Enum describes how the reply from ProcessTouchInfo should be interpreted:
|
||||||
|
// * NoAction: Do nothing, ignore input.
|
||||||
|
// * TouchEvent: The input should be treated as a normal touch event.
|
||||||
|
// * IgnoreTouchPopup: Show the popup when ignoring touch input.
|
||||||
|
enum class TouchProcessReply { NoAction, TouchEvent, IgnoreTouchPopup };
|
||||||
|
|
||||||
struct TouchPoint {
|
struct TouchPoint {
|
||||||
int x;
|
int x;
|
||||||
int y;
|
int y;
|
||||||
bool touching;
|
bool touching;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool ProcessTouchInfo(Drivers::Cst816S::TouchInfos info);
|
TouchProcessReply ProcessTouchInfo(Drivers::Cst816S::TouchInfos info, bool buttonUnlocksOn = false);
|
||||||
|
|
||||||
bool IsTouching() const {
|
bool IsTouching() const {
|
||||||
return currentTouchPoint.touching;
|
return currentTouchPoint.touching;
|
||||||
|
@ -26,12 +38,29 @@ namespace Pinetime {
|
||||||
return currentTouchPoint.y;
|
return currentTouchPoint.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetIgnoreTouchPopupHidden(bool hidden) {
|
||||||
|
ignoreTouchPopupHidden = hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsIgnoreTouchPopupHidden() {
|
||||||
|
return ignoreTouchPopupHidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetWokenBy(WokenBy woken, bool ifButtonUnlocksIgnoreTouch) {
|
||||||
|
wokenBy = woken;
|
||||||
|
ignoreNextTouchEvent = ifButtonUnlocksIgnoreTouch;
|
||||||
|
}
|
||||||
|
|
||||||
Pinetime::Applications::TouchEvents GestureGet();
|
Pinetime::Applications::TouchEvents GestureGet();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Pinetime::Applications::TouchEvents gesture;
|
Pinetime::Applications::TouchEvents gesture;
|
||||||
TouchPoint currentTouchPoint = {};
|
TouchPoint currentTouchPoint = {};
|
||||||
bool gestureReleased = true;
|
bool gestureReleased = true;
|
||||||
|
|
||||||
|
WokenBy wokenBy;
|
||||||
|
bool ignoreNextTouchEvent = false;
|
||||||
|
bool ignoreTouchPopupHidden = true;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue