Compare commits
8 commits
Author | SHA1 | Date | |
---|---|---|---|
D. Scott Boggs | cfd1ac4567 | ||
D. Scott Boggs | 6a9d13fe77 | ||
d689e5e874 | |||
D. Scott Boggs | 8abe9d428b | ||
D. Scott Boggs | b7cf42156c | ||
D. Scott Boggs | 7d8e58d863 | ||
D. Scott Boggs | fd15fd238d | ||
a9a36793ad |
3
.gitmodules
vendored
3
.gitmodules
vendored
|
@ -4,6 +4,9 @@
|
||||||
[submodule "src/libs/littlefs"]
|
[submodule "src/libs/littlefs"]
|
||||||
path = src/libs/littlefs
|
path = src/libs/littlefs
|
||||||
url = https://github.com/littlefs-project/littlefs.git
|
url = https://github.com/littlefs-project/littlefs.git
|
||||||
|
[submodule "src/libs/QCBOR"]
|
||||||
|
path = src/libs/QCBOR
|
||||||
|
url = https://github.com/laurencelundblade/QCBOR.git
|
||||||
[submodule "src/libs/arduinoFFT"]
|
[submodule "src/libs/arduinoFFT"]
|
||||||
path = src/libs/arduinoFFT
|
path = src/libs/arduinoFFT
|
||||||
url = https://github.com/kosme/arduinoFFT.git
|
url = https://github.com/kosme/arduinoFFT.git
|
||||||
|
|
5
.vscode/settings.json
vendored
5
.vscode/settings.json
vendored
|
@ -66,5 +66,8 @@
|
||||||
"streambuf": "cpp",
|
"streambuf": "cpp",
|
||||||
"cinttypes": "cpp",
|
"cinttypes": "cpp",
|
||||||
"typeinfo": "cpp"
|
"typeinfo": "cpp"
|
||||||
}
|
},
|
||||||
|
"cSpell.words": [
|
||||||
|
"Pinetime"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.10)
|
||||||
|
|
||||||
set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose Debug or Release")
|
set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose Debug or Release")
|
||||||
|
|
||||||
project(pinetime VERSION 1.15.3 LANGUAGES C CXX ASM)
|
project(pinetime VERSION 1.15.1 LANGUAGES C CXX ASM)
|
||||||
|
|
||||||
set(CMAKE_C_STANDARD 99)
|
set(CMAKE_C_STANDARD 99)
|
||||||
set(CMAKE_CXX_STANDARD 20)
|
set(CMAKE_CXX_STANDARD 20)
|
||||||
|
|
|
@ -16,11 +16,11 @@
|
||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1728492678,
|
"lastModified": 1725634671,
|
||||||
"narHash": "sha256-9UTxR8eukdg+XZeHgxW5hQA9fIKHsKCdOIUycTryeVw=",
|
"narHash": "sha256-v3rIhsJBOMLR8e/RNWxr828tB+WywYIoajrZKFM+0Gg=",
|
||||||
"owner": "nixos",
|
"owner": "nixos",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "5633bcff0c6162b9e4b5f1264264611e950c8ec7",
|
"rev": "574d1eac1c200690e27b8eb4e24887f8df7ac27c",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
40
flake.nix
40
flake.nix
|
@ -32,26 +32,28 @@
|
||||||
with pkgs; {
|
with pkgs; {
|
||||||
default = stdenv.mkDerivation rec {
|
default = stdenv.mkDerivation rec {
|
||||||
name = "infinitime";
|
name = "infinitime";
|
||||||
version = "1.14.1";
|
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
src = fetchFromGitea {
|
||||||
owner = "InfiniTimeOrg";
|
domain = "git.techwork.zone";
|
||||||
|
owner = "scott";
|
||||||
repo = "InfiniTime";
|
repo = "InfiniTime";
|
||||||
rev = "refs/tags/${version}";
|
rev = "1.15.1";
|
||||||
hash = "sha256-IrsN+9LgEjgfoRR6H7FhsdLMK+GLxc41IBnSbdpwv/E=";
|
hash = "sha256-9cy7qYRZrg7qZZwQzYeMIZivGLZ5uGUoTyPgHEvdnZ8=";
|
||||||
fetchSubmodules = true;
|
fetchSubmodules = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
nativeBuildInputs = [
|
nativeBuildInputs = [
|
||||||
adafruit-nrfutil
|
cmake
|
||||||
nodePackages.lv_font_conv
|
nodePackages.lv_font_conv
|
||||||
patch
|
|
||||||
python3
|
python3
|
||||||
python3.pkgs.cbor
|
python3.pkgs.cbor
|
||||||
python3.pkgs.click
|
python3.pkgs.click
|
||||||
python3.pkgs.cryptography
|
python3.pkgs.cryptography
|
||||||
python3.pkgs.intelhex
|
python3.pkgs.intelhex
|
||||||
python3.pkgs.pillow
|
python3.pkgs.pillow
|
||||||
|
adafruit-nrfutil
|
||||||
|
patch
|
||||||
|
git
|
||||||
];
|
];
|
||||||
|
|
||||||
postPatch = ''
|
postPatch = ''
|
||||||
|
@ -84,17 +86,27 @@
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
in
|
in
|
||||||
with pkgs; {
|
{
|
||||||
default =
|
default =
|
||||||
mkShell {
|
pkgs.buildFHSUserEnv {
|
||||||
packages = [
|
name = "infinitime-devenv";
|
||||||
(writeShellScriptBin "cmake_infinitime" ''
|
# build tools
|
||||||
${cmake}/bin/cmake -DARM_NONE_EABI_TOOLCHAIN_PATH="${gcc-arm-embedded-10}" \
|
targetPkgs = pkgs: (with pkgs; [
|
||||||
|
cmake
|
||||||
|
nodePackages.lv_font_conv
|
||||||
|
python3
|
||||||
|
python3.pkgs.cbor
|
||||||
|
python3.pkgs.click
|
||||||
|
python3.pkgs.cryptography
|
||||||
|
python3.pkgs.intelhex
|
||||||
|
adafruit-nrfutil
|
||||||
|
|
||||||
|
(pkgs.writeShellScriptBin "cmake_infinitime" ''
|
||||||
|
cmake -DARM_NONE_EABI_TOOLCHAIN_PATH="${pkgs.gcc-arm-embedded-10}" \
|
||||||
-DNRF5_SDK_PATH="${infinitime-nrf5-sdk}/share/nRF5_SDK" \
|
-DNRF5_SDK_PATH="${infinitime-nrf5-sdk}/share/nRF5_SDK" \
|
||||||
"$@"
|
"$@"
|
||||||
'')
|
'')
|
||||||
ninja
|
]);
|
||||||
] ++ self.packages.${pkgs.system}.default.nativeBuildInputs;
|
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -479,7 +479,6 @@ 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
|
||||||
|
@ -544,7 +543,6 @@ 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
|
||||||
|
@ -663,7 +661,6 @@ 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
|
||||||
|
|
|
@ -19,13 +19,11 @@
|
||||||
#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, Controllers::FS& fs)
|
AlarmController::AlarmController(Controllers::DateTime& dateTimeController) : dateTimeController {dateTimeController} {
|
||||||
: dateTimeController {dateTimeController}, fs {fs} {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -38,28 +36,11 @@ 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) {
|
||||||
if (alarm.hours == alarmHr && alarm.minutes == alarmMin) {
|
hours = alarmHr;
|
||||||
return;
|
minutes = alarmMin;
|
||||||
}
|
|
||||||
alarm.hours = alarmHr;
|
|
||||||
alarm.minutes = alarmMin;
|
|
||||||
alarmChanged = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AlarmController::ScheduleAlarm() {
|
void AlarmController::ScheduleAlarm() {
|
||||||
|
@ -72,19 +53,18 @@ 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 (alarm.hours < dateTimeController.Hours() ||
|
if (hours < dateTimeController.Hours() || (hours == dateTimeController.Hours() && minutes <= dateTimeController.Minutes())) {
|
||||||
(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 = alarm.hours;
|
tmAlarmTime->tm_hour = hours;
|
||||||
tmAlarmTime->tm_min = alarm.minutes;
|
tmAlarmTime->tm_min = 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 (alarm.recurrence == RecurType::Weekdays) {
|
if (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
|
||||||
|
@ -99,10 +79,7 @@ void AlarmController::ScheduleAlarm() {
|
||||||
xTimerChangePeriod(alarmTimer, secondsToAlarm * configTICK_RATE_HZ, 0);
|
xTimerChangePeriod(alarmTimer, secondsToAlarm * configTICK_RATE_HZ, 0);
|
||||||
xTimerStart(alarmTimer, 0);
|
xTimerStart(alarmTimer, 0);
|
||||||
|
|
||||||
if (!alarm.isEnabled) {
|
state = AlarmState::Set;
|
||||||
alarm.isEnabled = true;
|
|
||||||
alarmChanged = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t AlarmController::SecondsToAlarm() const {
|
uint32_t AlarmController::SecondsToAlarm() const {
|
||||||
|
@ -111,72 +88,20 @@ uint32_t AlarmController::SecondsToAlarm() const {
|
||||||
|
|
||||||
void AlarmController::DisableAlarm() {
|
void AlarmController::DisableAlarm() {
|
||||||
xTimerStop(alarmTimer, 0);
|
xTimerStop(alarmTimer, 0);
|
||||||
isAlerting = false;
|
state = AlarmState::Not_Set;
|
||||||
if (alarm.isEnabled) {
|
|
||||||
alarm.isEnabled = false;
|
|
||||||
alarmChanged = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AlarmController::SetOffAlarmNow() {
|
void AlarmController::SetOffAlarmNow() {
|
||||||
isAlerting = true;
|
state = AlarmState::Alerting;
|
||||||
systemTask->PushMessage(System::Messages::SetOffAlarm);
|
systemTask->PushMessage(System::Messages::SetOffAlarm);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AlarmController::StopAlerting() {
|
void AlarmController::StopAlerting() {
|
||||||
isAlerting = false;
|
// Alarm state is off unless this is a recurring alarm
|
||||||
// Disable alarm unless it is recurring
|
if (recurrence == RecurType::None) {
|
||||||
if (alarm.recurrence == RecurType::None) {
|
state = AlarmState::Not_Set;
|
||||||
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,65 +30,47 @@ namespace Pinetime {
|
||||||
namespace Controllers {
|
namespace Controllers {
|
||||||
class AlarmController {
|
class AlarmController {
|
||||||
public:
|
public:
|
||||||
AlarmController(Controllers::DateTime& dateTimeController, Controllers::FS& fs);
|
AlarmController(Controllers::DateTime& dateTimeController);
|
||||||
|
|
||||||
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 alarm.hours;
|
return hours;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t Minutes() const {
|
uint8_t Minutes() const {
|
||||||
return alarm.minutes;
|
return minutes;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsAlerting() const {
|
AlarmState State() const {
|
||||||
return isAlerting;
|
return state;
|
||||||
}
|
|
||||||
|
|
||||||
bool IsEnabled() const {
|
|
||||||
return alarm.isEnabled;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RecurType Recurrence() const {
|
RecurType Recurrence() const {
|
||||||
return alarm.recurrence;
|
return recurrence;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetRecurrence(RecurType recurrence);
|
void SetRecurrence(RecurType recurType) {
|
||||||
|
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;
|
||||||
AlarmSettings alarm;
|
uint8_t hours = 7;
|
||||||
|
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;
|
||||||
void LoadSettingsFromFile();
|
RecurType recurrence = RecurType::None;
|
||||||
void SaveSettingsToFile() const;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -124,11 +124,9 @@ int DfuService::WritePacketHandler(uint16_t connectionHandle, os_mbuf* om) {
|
||||||
bootloaderSize,
|
bootloaderSize,
|
||||||
applicationSize);
|
applicationSize);
|
||||||
|
|
||||||
// Wait until SystemTask has disabled sleeping
|
// wait until SystemTask has finished waking up all devices
|
||||||
// This isn't quite correct, as we don't actually know
|
while (systemTask.IsSleeping()) {
|
||||||
// if BleFirmwareUpdateStarted has been received yet
|
vTaskDelay(50); // 50ms
|
||||||
while (!systemTask.IsSleepDisabled()) {
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(5));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dfuImage.Erase();
|
dfuImage.Erase();
|
||||||
|
|
|
@ -18,8 +18,6 @@
|
||||||
#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,7 +25,6 @@
|
||||||
#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,15 +454,9 @@ 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(uint16_t hrs, uint16_t als) {
|
int8_t Ppg::Preprocess(uint32_t hrs, uint32_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(uint16_t hrs, uint16_t als);
|
int8_t Preprocess(uint32_t hrs, uint32_t als);
|
||||||
int HeartRate();
|
int HeartRate();
|
||||||
void Reset(bool resetDaqBuffer);
|
void Reset(bool resetDaqBuffer);
|
||||||
static constexpr int deltaTms = 100;
|
static constexpr int deltaTms = 100;
|
||||||
|
|
|
@ -53,7 +53,7 @@ namespace Pinetime {
|
||||||
enum class HeartRateBackgroundMeasurementInterval : uint8_t {
|
enum class HeartRateBackgroundMeasurementInterval : uint8_t {
|
||||||
Off,
|
Off,
|
||||||
Continuous,
|
Continuous,
|
||||||
FifteenSeconds,
|
TenSeconds,
|
||||||
ThirtySeconds,
|
ThirtySeconds,
|
||||||
OneMinute,
|
OneMinute,
|
||||||
FiveMinutes,
|
FiveMinutes,
|
||||||
|
|
|
@ -256,20 +256,9 @@ void DisplayApp::Refresh() {
|
||||||
isDimmed = true;
|
isDimmed = true;
|
||||||
brightnessController.Set(Controllers::BrightnessController::Levels::Low);
|
brightnessController.Set(Controllers::BrightnessController::Levels::Low);
|
||||||
}
|
}
|
||||||
if (IsPastSleepTime() && uxQueueMessagesWaiting(msgQueue) == 0) {
|
if (IsPastSleepTime()) {
|
||||||
PushMessageToSystemTask(System::Messages::GoToSleep);
|
systemTask->PushMessage(System::Messages::GoToSleep);
|
||||||
// Can't set state to Idle here, something may send
|
state = States::Idle;
|
||||||
// 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;
|
||||||
|
@ -285,9 +274,6 @@ 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);
|
||||||
|
@ -322,9 +308,6 @@ 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 {
|
||||||
|
@ -586,7 +569,7 @@ void DisplayApp::LoadScreen(Apps app, DisplayApp::FullRefreshDirections directio
|
||||||
currentScreen = std::make_unique<Screens::SettingHeartRate>(settingsController);
|
currentScreen = std::make_unique<Screens::SettingHeartRate>(settingsController);
|
||||||
break;
|
break;
|
||||||
case Apps::SettingDisplay:
|
case Apps::SettingDisplay:
|
||||||
currentScreen = std::make_unique<Screens::SettingDisplay>(settingsController);
|
currentScreen = std::make_unique<Screens::SettingDisplay>(this, settingsController);
|
||||||
break;
|
break;
|
||||||
case Apps::SettingSteps:
|
case Apps::SettingSteps:
|
||||||
currentScreen = std::make_unique<Screens::SettingSteps>(settingsController);
|
currentScreen = std::make_unique<Screens::SettingSteps>(settingsController);
|
||||||
|
|
|
@ -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}, wakeLock(systemTask), motorController {motorController} {
|
: alarmController {alarmController}, systemTask {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.IsAlerting()) {
|
if (alarmController.State() == Controllers::AlarmController::AlarmState::Alerting) {
|
||||||
SetAlerting();
|
SetAlerting();
|
||||||
} else {
|
} else {
|
||||||
SetSwitchState(LV_ANIM_OFF);
|
SetSwitchState(LV_ANIM_OFF);
|
||||||
|
@ -125,15 +125,14 @@ Alarm::Alarm(Controllers::AlarmController& alarmController,
|
||||||
}
|
}
|
||||||
|
|
||||||
Alarm::~Alarm() {
|
Alarm::~Alarm() {
|
||||||
if (alarmController.IsAlerting()) {
|
if (alarmController.State() == AlarmController::AlarmState::Alerting) {
|
||||||
StopAlerting();
|
StopAlerting();
|
||||||
}
|
}
|
||||||
lv_obj_clean(lv_scr_act());
|
lv_obj_clean(lv_scr_act());
|
||||||
alarmController.SaveAlarm();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Alarm::DisableAlarm() {
|
void Alarm::DisableAlarm() {
|
||||||
if (alarmController.IsEnabled()) {
|
if (alarmController.State() == AlarmController::AlarmState::Set) {
|
||||||
alarmController.DisableAlarm();
|
alarmController.DisableAlarm();
|
||||||
lv_switch_off(enableSwitch, LV_ANIM_ON);
|
lv_switch_off(enableSwitch, LV_ANIM_ON);
|
||||||
}
|
}
|
||||||
|
@ -173,7 +172,7 @@ bool Alarm::OnButtonPushed() {
|
||||||
HideInfo();
|
HideInfo();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (alarmController.IsAlerting()) {
|
if (alarmController.State() == AlarmController::AlarmState::Alerting) {
|
||||||
StopAlerting();
|
StopAlerting();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -182,7 +181,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.IsAlerting() && event == TouchEvents::SwipeDown;
|
return alarmController.State() == AlarmController::AlarmState::Alerting && event == TouchEvents::SwipeDown;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Alarm::OnValueChanged() {
|
void Alarm::OnValueChanged() {
|
||||||
|
@ -206,7 +205,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();
|
||||||
wakeLock.Lock();
|
systemTask.PushMessage(System::Messages::DisableSleeping);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Alarm::StopAlerting() {
|
void Alarm::StopAlerting() {
|
||||||
|
@ -217,16 +216,21 @@ void Alarm::StopAlerting() {
|
||||||
lv_task_del(taskStopAlarm);
|
lv_task_del(taskStopAlarm);
|
||||||
taskStopAlarm = nullptr;
|
taskStopAlarm = nullptr;
|
||||||
}
|
}
|
||||||
wakeLock.Release();
|
systemTask.PushMessage(System::Messages::EnableSleeping);
|
||||||
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) {
|
||||||
if (alarmController.IsEnabled()) {
|
switch (alarmController.State()) {
|
||||||
|
case AlarmController::AlarmState::Set:
|
||||||
lv_switch_on(enableSwitch, anim);
|
lv_switch_on(enableSwitch, anim);
|
||||||
} else {
|
break;
|
||||||
|
case AlarmController::AlarmState::Not_Set:
|
||||||
lv_switch_off(enableSwitch, anim);
|
lv_switch_off(enableSwitch, anim);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -243,7 +247,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.IsEnabled()) {
|
if (alarmController.State() == AlarmController::AlarmState::Set) {
|
||||||
auto timeToAlarm = alarmController.SecondsToAlarm();
|
auto timeToAlarm = alarmController.SecondsToAlarm();
|
||||||
|
|
||||||
auto daysToAlarm = timeToAlarm / 86400;
|
auto daysToAlarm = timeToAlarm / 86400;
|
||||||
|
|
|
@ -22,7 +22,6 @@
|
||||||
#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 {
|
||||||
|
@ -44,7 +43,7 @@ namespace Pinetime {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Controllers::AlarmController& alarmController;
|
Controllers::AlarmController& alarmController;
|
||||||
System::WakeLock wakeLock;
|
System::SystemTask& systemTask;
|
||||||
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)
|
||||||
: wakeLock(systemTask), brightnessController {brightnessController} {
|
: systemTask {systemTask}, brightnessController {brightnessController} {
|
||||||
|
|
||||||
previousBrightnessLevel = brightnessController.Level();
|
previousBrightnessLevel = brightnessController.Level();
|
||||||
brightnessController.Set(Controllers::BrightnessController::Levels::Low);
|
brightnessController.Set(Controllers::BrightnessController::Levels::Low);
|
||||||
|
@ -47,13 +47,14 @@ 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);
|
||||||
|
|
||||||
wakeLock.Lock();
|
systemTask.PushMessage(Pinetime::System::Messages::DisableSleeping);
|
||||||
}
|
}
|
||||||
|
|
||||||
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,7 +3,6 @@
|
||||||
#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>
|
||||||
|
|
||||||
|
@ -24,7 +23,7 @@ namespace Pinetime {
|
||||||
void SetIndicators();
|
void SetIndicators();
|
||||||
void SetColors();
|
void SetColors();
|
||||||
|
|
||||||
Pinetime::System::WakeLock wakeLock;
|
Pinetime::System::SystemTask& systemTask;
|
||||||
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}, wakeLock(systemTask) {
|
: heartRateController {heartRateController}, systemTask {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) {
|
||||||
wakeLock.Lock();
|
systemTask.PushMessage(Pinetime::System::Messages::DisableSleeping);
|
||||||
}
|
}
|
||||||
|
|
||||||
taskRefresh = lv_task_create(RefreshTaskCallback, 100, LV_TASK_PRIO_MID, this);
|
taskRefresh = lv_task_create(RefreshTaskCallback, 100, LV_TASK_PRIO_MID, this);
|
||||||
|
@ -72,6 +72,7 @@ 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() {
|
||||||
|
@ -100,12 +101,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);
|
||||||
wakeLock.Lock();
|
systemTask.PushMessage(Pinetime::System::Messages::DisableSleeping);
|
||||||
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);
|
||||||
wakeLock.Release();
|
systemTask.PushMessage(Pinetime::System::Messages::EnableSleeping);
|
||||||
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,7 +4,6 @@
|
||||||
#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>
|
||||||
|
@ -28,7 +27,7 @@ namespace Pinetime {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Controllers::HeartRateController& heartRateController;
|
Controllers::HeartRateController& heartRateController;
|
||||||
Pinetime::System::WakeLock wakeLock;
|
Pinetime::System::SystemTask& systemTask;
|
||||||
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}, wakeLock(systemTask) {
|
: motorController {motorController}, systemTask {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,6 +72,7 @@ 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());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,12 +128,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);
|
||||||
wakeLock.Lock();
|
systemTask.PushMessage(System::Messages::DisableSleeping);
|
||||||
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);
|
||||||
wakeLock.Release();
|
systemTask.PushMessage(System::Messages::EnableSleeping);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
#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"
|
||||||
|
@ -22,7 +21,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::WakeLock wakeLock;
|
System::SystemTask& systemTask;
|
||||||
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},
|
||||||
wakeLock(systemTask),
|
systemTask {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) {
|
||||||
wakeLock.Lock();
|
systemTask.PushMessage(System::Messages::DisableSleeping);
|
||||||
if (notification.category == Controllers::NotificationManager::Categories::IncomingCall) {
|
if (notification.category == Controllers::NotificationManager::Categories::IncomingCall) {
|
||||||
motorController.StartRinging();
|
motorController.StartRinging();
|
||||||
} else {
|
} else {
|
||||||
|
@ -65,6 +65,7 @@ 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());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,6 +82,7 @@ void Notifications::Refresh() {
|
||||||
|
|
||||||
} else if (mode == Modes::Preview && dismissingNotification) {
|
} else if (mode == Modes::Preview && dismissingNotification) {
|
||||||
running = false;
|
running = false;
|
||||||
|
currentItem = std::make_unique<NotificationItem>(alertNotificationService, motorController);
|
||||||
|
|
||||||
} else if (dismissingNotification) {
|
} else if (dismissingNotification) {
|
||||||
dismissingNotification = false;
|
dismissingNotification = false;
|
||||||
|
@ -111,15 +113,15 @@ void Notifications::Refresh() {
|
||||||
alertNotificationService,
|
alertNotificationService,
|
||||||
motorController);
|
motorController);
|
||||||
} else {
|
} else {
|
||||||
running = false;
|
currentItem = std::make_unique<NotificationItem>(alertNotificationService, motorController);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
running = running && currentItem->IsRunning();
|
running = currentItem->IsRunning() && running;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Notifications::OnPreviewInteraction() {
|
void Notifications::OnPreviewInteraction() {
|
||||||
wakeLock.Release();
|
systemTask.PushMessage(System::Messages::EnableSleeping);
|
||||||
motorController.StopRinging();
|
motorController.StopRinging();
|
||||||
if (timeoutLine != nullptr) {
|
if (timeoutLine != nullptr) {
|
||||||
lv_obj_del(timeoutLine);
|
lv_obj_del(timeoutLine);
|
||||||
|
@ -171,9 +173,7 @@ bool Notifications::OnTouchEvent(Pinetime::Applications::TouchEvents event) {
|
||||||
} else if (nextMessage.valid) {
|
} else if (nextMessage.valid) {
|
||||||
currentId = nextMessage.id;
|
currentId = nextMessage.id;
|
||||||
} else {
|
} else {
|
||||||
// don't update id, notification manager will try to fetch
|
// don't update id, won't be found be refresh and try to load latest message or no message box
|
||||||
// but not find it. Refresh will try to load latest message
|
|
||||||
// or dismiss to watchface
|
|
||||||
}
|
}
|
||||||
DismissToBlack();
|
DismissToBlack();
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
#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 {
|
||||||
|
@ -74,7 +73,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::WakeLock wakeLock;
|
System::SystemTask& systemTask;
|
||||||
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;
|
||||||
|
|
|
@ -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) : wakeLock(systemTask) {
|
StopWatch::StopWatch(System::SystemTask& systemTask) : systemTask {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,6 +79,7 @@ StopWatch::StopWatch(System::SystemTask& systemTask) : wakeLock(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());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,7 +135,7 @@ void StopWatch::Start() {
|
||||||
SetInterfaceRunning();
|
SetInterfaceRunning();
|
||||||
startTime = xTaskGetTickCount();
|
startTime = xTaskGetTickCount();
|
||||||
currentState = States::Running;
|
currentState = States::Running;
|
||||||
wakeLock.Lock();
|
systemTask.PushMessage(Pinetime::System::Messages::DisableSleeping);
|
||||||
}
|
}
|
||||||
|
|
||||||
void StopWatch::Pause() {
|
void StopWatch::Pause() {
|
||||||
|
@ -144,7 +145,7 @@ void StopWatch::Pause() {
|
||||||
oldTimeElapsed = laps[lapsDone];
|
oldTimeElapsed = laps[lapsDone];
|
||||||
blinkTime = xTaskGetTickCount() + blinkInterval;
|
blinkTime = xTaskGetTickCount() + blinkInterval;
|
||||||
currentState = States::Halted;
|
currentState = States::Halted;
|
||||||
wakeLock.Release();
|
systemTask.PushMessage(Pinetime::System::Messages::EnableSleeping);
|
||||||
}
|
}
|
||||||
|
|
||||||
void StopWatch::Refresh() {
|
void StopWatch::Refresh() {
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
#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"
|
||||||
|
@ -44,7 +43,7 @@ namespace Pinetime {
|
||||||
void Start();
|
void Start();
|
||||||
void Pause();
|
void Pause();
|
||||||
|
|
||||||
Pinetime::System::WakeLock wakeLock;
|
Pinetime::System::SystemTask& systemTask;
|
||||||
States currentState = States::Init;
|
States currentState = States::Init;
|
||||||
TickType_t startTime;
|
TickType_t startTime;
|
||||||
TickType_t oldTimeElapsed = 0;
|
TickType_t oldTimeElapsed = 0;
|
||||||
|
|
|
@ -40,7 +40,8 @@ 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)
|
||||||
: dateTimeController {dateTimeController},
|
: app {app},
|
||||||
|
dateTimeController {dateTimeController},
|
||||||
batteryController {batteryController},
|
batteryController {batteryController},
|
||||||
brightnessController {brightnessController},
|
brightnessController {brightnessController},
|
||||||
bleController {bleController},
|
bleController {bleController},
|
||||||
|
|
|
@ -35,6 +35,7 @@ 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,7 +24,8 @@ namespace {
|
||||||
|
|
||||||
constexpr std::array<uint16_t, 6> SettingDisplay::options;
|
constexpr std::array<uint16_t, 6> SettingDisplay::options;
|
||||||
|
|
||||||
SettingDisplay::SettingDisplay(Pinetime::Controllers::Settings& settingsController) : settingsController {settingsController} {
|
SettingDisplay::SettingDisplay(Pinetime::Applications::DisplayApp* app, Pinetime::Controllers::Settings& 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,13 +14,14 @@ namespace Pinetime {
|
||||||
|
|
||||||
class SettingDisplay : public Screen {
|
class SettingDisplay : public Screen {
|
||||||
public:
|
public:
|
||||||
SettingDisplay(Pinetime::Controllers::Settings& settingsController);
|
SettingDisplay(DisplayApp* app, 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;
|
||||||
|
|
|
@ -32,7 +32,7 @@ namespace Pinetime {
|
||||||
static constexpr std::array<Option, 8> options = {{
|
static constexpr std::array<Option, 8> options = {{
|
||||||
{Pinetime::Controllers::Settings::HeartRateBackgroundMeasurementInterval::Off, " Off"},
|
{Pinetime::Controllers::Settings::HeartRateBackgroundMeasurementInterval::Off, " Off"},
|
||||||
{Pinetime::Controllers::Settings::HeartRateBackgroundMeasurementInterval::Continuous, "Cont"},
|
{Pinetime::Controllers::Settings::HeartRateBackgroundMeasurementInterval::Continuous, "Cont"},
|
||||||
{Pinetime::Controllers::Settings::HeartRateBackgroundMeasurementInterval::FifteenSeconds, " 15s"},
|
{Pinetime::Controllers::Settings::HeartRateBackgroundMeasurementInterval::TenSeconds, " 10s"},
|
||||||
{Pinetime::Controllers::Settings::HeartRateBackgroundMeasurementInterval::ThirtySeconds, " 30s"},
|
{Pinetime::Controllers::Settings::HeartRateBackgroundMeasurementInterval::ThirtySeconds, " 30s"},
|
||||||
{Pinetime::Controllers::Settings::HeartRateBackgroundMeasurementInterval::OneMinute, " 1m"},
|
{Pinetime::Controllers::Settings::HeartRateBackgroundMeasurementInterval::OneMinute, " 1m"},
|
||||||
{Pinetime::Controllers::Settings::HeartRateBackgroundMeasurementInterval::FiveMinutes, " 5m"},
|
{Pinetime::Controllers::Settings::HeartRateBackgroundMeasurementInterval::FiveMinutes, " 5m"},
|
||||||
|
|
|
@ -15,7 +15,8 @@ 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)
|
||||||
: dateTimeController {dateTimeController},
|
: app {app},
|
||||||
|
dateTimeController {dateTimeController},
|
||||||
settingsController {settingsController},
|
settingsController {settingsController},
|
||||||
screens {app,
|
screens {app,
|
||||||
0,
|
0,
|
||||||
|
|
|
@ -20,6 +20,7 @@ namespace Pinetime {
|
||||||
void Quit();
|
void Quit();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
DisplayApp* app;
|
||||||
Controllers::DateTime& dateTimeController;
|
Controllers::DateTime& dateTimeController;
|
||||||
Controllers::Settings& settingsController;
|
Controllers::Settings& settingsController;
|
||||||
|
|
||||||
|
|
|
@ -54,7 +54,8 @@ 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)
|
||||||
: watchfaceItems {std::move(watchfaceItems)},
|
: app {app},
|
||||||
|
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,6 +34,7 @@ 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;
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
|
|
||||||
#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>
|
||||||
|
@ -68,37 +67,40 @@ void Hrs3300::Disable() {
|
||||||
WriteRegister(static_cast<uint8_t>(Registers::PDriver), 0);
|
WriteRegister(static_cast<uint8_t>(Registers::PDriver), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Hrs3300::PackedHrsAls Hrs3300::ReadHrsAls() {
|
uint32_t Hrs3300::ReadHrs() {
|
||||||
constexpr Registers dataRegisters[] =
|
auto m = ReadRegister(static_cast<uint8_t>(Registers::C0DataM));
|
||||||
{Registers::C1dataM, Registers::C0DataM, Registers::C0DataH, Registers::C1dataH, Registers::C1dataL, Registers::C0dataL};
|
auto h = ReadRegister(static_cast<uint8_t>(Registers::C0DataH));
|
||||||
// Calculate smallest register address
|
auto l = ReadRegister(static_cast<uint8_t>(Registers::C0dataL));
|
||||||
constexpr uint8_t baseOffset = static_cast<uint8_t>(*std::min_element(std::begin(dataRegisters), std::end(dataRegisters)));
|
return ((l & 0x30) << 12) | (m << 8) | ((h & 0x0f) << 4) | (l & 0x0f);
|
||||||
// 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;
|
|
||||||
|
|
||||||
Hrs3300::PackedHrsAls res;
|
|
||||||
uint8_t buf[length];
|
|
||||||
auto ret = twiMaster.Read(twiAddress, baseOffset, buf, length);
|
|
||||||
if (ret != TwiMaster::ErrorCodes::NoError) {
|
|
||||||
NRF_LOG_INFO("READ ERROR");
|
|
||||||
}
|
}
|
||||||
// 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);
|
|
||||||
|
|
||||||
// als
|
uint32_t Hrs3300::ReadAls() {
|
||||||
m = static_cast<uint8_t>(Registers::C1dataM) - baseOffset;
|
auto m = ReadRegister(static_cast<uint8_t>(Registers::C1dataM));
|
||||||
h = static_cast<uint8_t>(Registers::C1dataH) - baseOffset;
|
auto h = ReadRegister(static_cast<uint8_t>(Registers::C1dataH));
|
||||||
l = static_cast<uint8_t>(Registers::C1dataL) - baseOffset;
|
auto l = ReadRegister(static_cast<uint8_t>(Registers::C1dataL));
|
||||||
res.als = ((buf[h] & 0x3f) << 11) | (buf[m] << 3) | (buf[l] & 0x07);
|
return ((h & 0x3f) << 11) | (m << 3) | (l & 0x07);
|
||||||
|
}
|
||||||
|
|
||||||
return res;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
WriteRegister(static_cast<uint8_t>(Registers::Hgain), hgain << 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Hrs3300::SetDrive(uint8_t drive) {
|
||||||
|
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,11 +21,6 @@ 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;
|
||||||
|
@ -35,7 +30,10 @@ namespace Pinetime {
|
||||||
void Init();
|
void Init();
|
||||||
void Enable();
|
void Enable();
|
||||||
void Disable();
|
void Disable();
|
||||||
PackedHrsAls ReadHrsAls();
|
uint32_t ReadHrs();
|
||||||
|
uint32_t ReadAls();
|
||||||
|
void SetGain(uint8_t gain);
|
||||||
|
void SetDrive(uint8_t drive);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TwiMaster& twiMaster;
|
TwiMaster& twiMaster;
|
||||||
|
|
|
@ -97,6 +97,11 @@ void HeartRateTask::StopMeasurement() {
|
||||||
vTaskDelay(100);
|
vTaskDelay(100);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HeartRateTask::StartWaiting() {
|
||||||
|
StopMeasurement();
|
||||||
|
backgroundWaitingStart = xTaskGetTickCount();
|
||||||
|
}
|
||||||
|
|
||||||
void HeartRateTask::HandleGoToSleep() {
|
void HeartRateTask::HandleGoToSleep() {
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case States::ScreenOnAndStopped:
|
case States::ScreenOnAndStopped:
|
||||||
|
@ -171,7 +176,8 @@ void HeartRateTask::HandleBackgroundWaiting() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ShouldStartBackgroundMeasuring()) {
|
TickType_t ticksSinceWaitingStart = xTaskGetTickCount() - backgroundWaitingStart;
|
||||||
|
if (ticksSinceWaitingStart >= GetHeartRateBackgroundMeasurementIntervalInTicks()) {
|
||||||
state = States::ScreenOffAndMeasuring;
|
state = States::ScreenOffAndMeasuring;
|
||||||
StartMeasurement();
|
StartMeasurement();
|
||||||
}
|
}
|
||||||
|
@ -192,45 +198,34 @@ void HeartRateTask::HandleSensorData(int* lastBpm) {
|
||||||
bpm = 0;
|
bpm = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool notEnoughData = *lastBpm == 0 && bpm == 0;
|
if (*lastBpm == 0 && bpm == 0) {
|
||||||
if (notEnoughData) {
|
|
||||||
controller.Update(Controllers::HeartRateController::States::NotEnoughData, bpm);
|
controller.Update(Controllers::HeartRateController::States::NotEnoughData, bpm);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bpm != 0) {
|
if (bpm != 0) {
|
||||||
*lastBpm = bpm;
|
*lastBpm = bpm;
|
||||||
controller.Update(Controllers::HeartRateController::States::Running, bpm);
|
controller.Update(Controllers::HeartRateController::States::Running, bpm);
|
||||||
}
|
|
||||||
|
|
||||||
if (state == States::ScreenOnAndMeasuring || IsContinuousModeActivated()) {
|
if (state == States::ScreenOnAndMeasuring || IsContinuousModeActivated()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (state == States::ScreenOffAndMeasuring) {
|
||||||
// state == States::ScreenOffAndMeasuring
|
|
||||||
// (because state != ScreenOnAndMeasuring and the only state that enables measuring is ScreenOffAndMeasuring)
|
|
||||||
// !IsContinuousModeActivated()
|
|
||||||
|
|
||||||
if (ShouldStartBackgroundMeasuring()) {
|
|
||||||
// This doesn't change the state but resets the measurment timer, which basically starts the next measurment without resetting the sensor.
|
|
||||||
// This is basically a fall back to continuous mode, when measurments take too long.
|
|
||||||
measurementStart = xTaskGetTickCount();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool noDataWithinTimeLimit = bpm == 0 && ShoudStopTryingToGetData();
|
|
||||||
bool dataWithinTimeLimit = bpm != 0;
|
|
||||||
if (dataWithinTimeLimit || noDataWithinTimeLimit) {
|
|
||||||
state = States::ScreenOffAndWaiting;
|
state = States::ScreenOffAndWaiting;
|
||||||
StopMeasurement();
|
StartWaiting();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TickType_t ticksSinceMeasurementStart = xTaskGetTickCount() - measurementStart;
|
||||||
|
if (bpm == 0 && state == States::ScreenOffAndMeasuring && !IsContinuousModeActivated() &&
|
||||||
|
ticksSinceMeasurementStart >= DURATION_UNTIL_BACKGROUND_MEASUREMENT_IS_STOPPED) {
|
||||||
|
state = States::ScreenOffAndWaiting;
|
||||||
|
StartWaiting();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TickType_t HeartRateTask::GetHeartRateBackgroundMeasurementIntervalInTicks() {
|
TickType_t HeartRateTask::GetHeartRateBackgroundMeasurementIntervalInTicks() {
|
||||||
int ms;
|
int ms;
|
||||||
switch (settings.GetHeartRateBackgroundMeasurementInterval()) {
|
switch (settings.GetHeartRateBackgroundMeasurementInterval()) {
|
||||||
case Pinetime::Controllers::Settings::HeartRateBackgroundMeasurementInterval::FifteenSeconds:
|
case Pinetime::Controllers::Settings::HeartRateBackgroundMeasurementInterval::TenSeconds:
|
||||||
ms = 15 * 1000;
|
ms = 10 * 1000;
|
||||||
break;
|
break;
|
||||||
case Pinetime::Controllers::Settings::HeartRateBackgroundMeasurementInterval::ThirtySeconds:
|
case Pinetime::Controllers::Settings::HeartRateBackgroundMeasurementInterval::ThirtySeconds:
|
||||||
ms = 30 * 1000;
|
ms = 30 * 1000;
|
||||||
|
@ -263,15 +258,3 @@ bool HeartRateTask::IsBackgroundMeasurementActivated() {
|
||||||
return settings.GetHeartRateBackgroundMeasurementInterval() !=
|
return settings.GetHeartRateBackgroundMeasurementInterval() !=
|
||||||
Pinetime::Controllers::Settings::HeartRateBackgroundMeasurementInterval::Off;
|
Pinetime::Controllers::Settings::HeartRateBackgroundMeasurementInterval::Off;
|
||||||
}
|
}
|
||||||
|
|
||||||
TickType_t HeartRateTask::GetTicksSinceLastMeasurementStarted() {
|
|
||||||
return xTaskGetTickCount() - measurementStart;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool HeartRateTask::ShoudStopTryingToGetData() {
|
|
||||||
return GetTicksSinceLastMeasurementStarted() >= DURATION_UNTIL_BACKGROUND_MEASUREMENT_IS_STOPPED;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool HeartRateTask::ShouldStartBackgroundMeasuring() {
|
|
||||||
return GetTicksSinceLastMeasurementStarted() >= GetHeartRateBackgroundMeasurementIntervalInTicks();
|
|
||||||
}
|
|
|
@ -45,6 +45,7 @@ namespace Pinetime {
|
||||||
static void Process(void* instance);
|
static void Process(void* instance);
|
||||||
void StartMeasurement();
|
void StartMeasurement();
|
||||||
void StopMeasurement();
|
void StopMeasurement();
|
||||||
|
void StartWaiting();
|
||||||
|
|
||||||
void HandleGoToSleep();
|
void HandleGoToSleep();
|
||||||
void HandleWakeUp();
|
void HandleWakeUp();
|
||||||
|
@ -58,10 +59,6 @@ namespace Pinetime {
|
||||||
bool IsContinuousModeActivated();
|
bool IsContinuousModeActivated();
|
||||||
bool IsBackgroundMeasurementActivated();
|
bool IsBackgroundMeasurementActivated();
|
||||||
|
|
||||||
TickType_t GetTicksSinceLastMeasurementStarted();
|
|
||||||
bool ShoudStopTryingToGetData();
|
|
||||||
bool ShouldStartBackgroundMeasuring();
|
|
||||||
|
|
||||||
TaskHandle_t taskHandle;
|
TaskHandle_t taskHandle;
|
||||||
QueueHandle_t messageQueue;
|
QueueHandle_t messageQueue;
|
||||||
States state = States::ScreenOnAndStopped;
|
States state = States::ScreenOnAndStopped;
|
||||||
|
@ -69,6 +66,7 @@ namespace Pinetime {
|
||||||
Controllers::HeartRateController& controller;
|
Controllers::HeartRateController& controller;
|
||||||
Controllers::Settings& settings;
|
Controllers::Settings& settings;
|
||||||
Controllers::Ppg ppg;
|
Controllers::Ppg ppg;
|
||||||
|
TickType_t backgroundWaitingStart = 0;
|
||||||
TickType_t measurementStart = 0;
|
TickType_t measurementStart = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
1
src/libs/QCBOR
Submodule
1
src/libs/QCBOR
Submodule
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 56b17bf9f74096774944bcac0829adcd887d391e
|
|
@ -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, fs};
|
Pinetime::Controllers::AlarmController alarmController {dateTimeController};
|
||||||
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,14 +189,36 @@ 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:
|
||||||
wakeLocksHeld--;
|
// Make sure that exiting an app doesn't enable sleeping,
|
||||||
|
// if the exiting was caused by a firmware update
|
||||||
|
if (!bleController.IsFirmwareUpdating()) {
|
||||||
|
doNotGoToSleep = false;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case Messages::DisableSleeping:
|
case Messages::DisableSleeping:
|
||||||
GoToRunning();
|
doNotGoToSleep = true;
|
||||||
wakeLocksHeld++;
|
|
||||||
break;
|
break;
|
||||||
case Messages::GoToRunning:
|
case Messages::GoToRunning:
|
||||||
GoToRunning();
|
// SPI doesn't go to sleep for always on mode
|
||||||
|
if (!settingsController.GetAlwaysOnDisplay()) {
|
||||||
|
spi.Wakeup();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Double Tap needs the touch screen to be in normal mode
|
||||||
|
if (!settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::DoubleTap)) {
|
||||||
|
touchPanel.Wakeup();
|
||||||
|
}
|
||||||
|
|
||||||
|
spiNorFlash.Wakeup();
|
||||||
|
|
||||||
|
displayApp.PushMessage(Pinetime::Applications::Display::Messages::GoToRunning);
|
||||||
|
heartRateApp.PushMessage(Pinetime::Applications::HeartRateTask::Messages::WakeUp);
|
||||||
|
|
||||||
|
if (bleController.IsRadioEnabled() && !bleController.IsConnected()) {
|
||||||
|
nimbleController.RestartFastAdv();
|
||||||
|
}
|
||||||
|
|
||||||
|
state = SystemTaskState::Running;
|
||||||
break;
|
break;
|
||||||
case Messages::TouchWakeUp: {
|
case Messages::TouchWakeUp: {
|
||||||
if (touchHandler.ProcessTouchInfo(touchPanel.GetTouchInfo())) {
|
if (touchHandler.ProcessTouchInfo(touchPanel.GetTouchInfo())) {
|
||||||
|
@ -213,23 +235,31 @@ void SystemTask::Work() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Messages::GoToSleep:
|
case Messages::GoToSleep:
|
||||||
GoToSleep();
|
if (doNotGoToSleep) {
|
||||||
|
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.IsEnabled()) {
|
if (alarmController.State() == Controllers::AlarmController::AlarmState::Set) {
|
||||||
alarmController.ScheduleAlarm();
|
alarmController.ScheduleAlarm();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Messages::OnNewNotification:
|
case Messages::OnNewNotification:
|
||||||
if (settingsController.GetNotificationStatus() == Pinetime::Controllers::Settings::Notification::On) {
|
if (settingsController.GetNotificationStatus() == Pinetime::Controllers::Settings::Notification::On) {
|
||||||
if (IsSleeping()) {
|
if (state == SystemTaskState::Sleeping) {
|
||||||
GoToRunning();
|
GoToRunning();
|
||||||
}
|
}
|
||||||
displayApp.PushMessage(Pinetime::Applications::Display::Messages::NewNotification);
|
displayApp.PushMessage(Pinetime::Applications::Display::Messages::NewNotification);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Messages::SetOffAlarm:
|
case Messages::SetOffAlarm:
|
||||||
|
if (state == SystemTaskState::Sleeping) {
|
||||||
GoToRunning();
|
GoToRunning();
|
||||||
|
}
|
||||||
displayApp.PushMessage(Pinetime::Applications::Display::Messages::AlarmTriggered);
|
displayApp.PushMessage(Pinetime::Applications::Display::Messages::AlarmTriggered);
|
||||||
break;
|
break;
|
||||||
case Messages::BleConnected:
|
case Messages::BleConnected:
|
||||||
|
@ -238,25 +268,29 @@ void SystemTask::Work() {
|
||||||
bleDiscoveryTimer = 5;
|
bleDiscoveryTimer = 5;
|
||||||
break;
|
break;
|
||||||
case Messages::BleFirmwareUpdateStarted:
|
case Messages::BleFirmwareUpdateStarted:
|
||||||
|
doNotGoToSleep = true;
|
||||||
|
if (state == SystemTaskState::Sleeping) {
|
||||||
GoToRunning();
|
GoToRunning();
|
||||||
wakeLocksHeld++;
|
}
|
||||||
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();
|
||||||
}
|
}
|
||||||
wakeLocksHeld--;
|
doNotGoToSleep = false;
|
||||||
break;
|
break;
|
||||||
case Messages::StartFileTransfer:
|
case Messages::StartFileTransfer:
|
||||||
NRF_LOG_INFO("[systemtask] FS Started");
|
NRF_LOG_INFO("[systemtask] FS Started");
|
||||||
|
doNotGoToSleep = true;
|
||||||
|
if (state == SystemTaskState::Sleeping) {
|
||||||
GoToRunning();
|
GoToRunning();
|
||||||
wakeLocksHeld++;
|
}
|
||||||
// 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");
|
||||||
wakeLocksHeld--;
|
doNotGoToSleep = false;
|
||||||
// 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:
|
||||||
|
@ -284,13 +318,6 @@ void SystemTask::Work() {
|
||||||
HandleButtonAction(action);
|
HandleButtonAction(action);
|
||||||
} break;
|
} break;
|
||||||
case Messages::OnDisplayTaskSleeping:
|
case Messages::OnDisplayTaskSleeping:
|
||||||
// The state was set to GoingToSleep when GoToSleep() was called
|
|
||||||
// If the state is no longer GoingToSleep, we have since transitioned back to Running
|
|
||||||
// In this case absorb the OnDisplayTaskSleeping
|
|
||||||
// as DisplayApp is about to receive GoToRunning
|
|
||||||
if (state != SystemTaskState::GoingToSleep) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (BootloaderVersion::IsValid()) {
|
if (BootloaderVersion::IsValid()) {
|
||||||
// First versions of the bootloader do not expose their version and cannot initialize the SPI NOR FLASH
|
// First versions of the bootloader do not expose their version and cannot initialize the SPI NOR FLASH
|
||||||
// if it's in sleep mode. Avoid bricked device by disabling sleep mode on these versions.
|
// if it's in sleep mode. Avoid bricked device by disabling sleep mode on these versions.
|
||||||
|
@ -317,23 +344,39 @@ 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 && !alarmController.IsAlerting()) {
|
settingsController.GetChimeOption() == Controllers::Settings::ChimesOption::Hours &&
|
||||||
|
alarmController.State() != AlarmController::AlarmState::Alerting) {
|
||||||
|
// if sleeping, we can't send a chime to displayApp yet (SPI flash switched off)
|
||||||
|
// request running first and repush the chime message
|
||||||
|
if (state == SystemTaskState::Sleeping) {
|
||||||
GoToRunning();
|
GoToRunning();
|
||||||
|
PushMessage(msg);
|
||||||
|
} else {
|
||||||
displayApp.PushMessage(Pinetime::Applications::Display::Messages::Chime);
|
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 && !alarmController.IsAlerting()) {
|
settingsController.GetChimeOption() == Controllers::Settings::ChimesOption::HalfHours &&
|
||||||
|
alarmController.State() != AlarmController::AlarmState::Alerting) {
|
||||||
|
// if sleeping, we can't send a chime to displayApp yet (SPI flash switched off)
|
||||||
|
// request running first and repush the chime message
|
||||||
|
if (state == SystemTaskState::Sleeping) {
|
||||||
GoToRunning();
|
GoToRunning();
|
||||||
|
PushMessage(msg);
|
||||||
|
} else {
|
||||||
displayApp.PushMessage(Pinetime::Applications::Display::Messages::Chime);
|
displayApp.PushMessage(Pinetime::Applications::Display::Messages::Chime);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case Messages::OnChargingEvent:
|
case Messages::OnChargingEvent:
|
||||||
batteryController.ReadPowerState();
|
batteryController.ReadPowerState();
|
||||||
GoToRunning();
|
|
||||||
displayApp.PushMessage(Applications::Display::Messages::OnChargingEvent);
|
displayApp.PushMessage(Applications::Display::Messages::OnChargingEvent);
|
||||||
|
if (state == SystemTaskState::Sleeping) {
|
||||||
|
GoToRunning();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case Messages::MeasureBatteryTimerExpired:
|
case Messages::MeasureBatteryTimerExpired:
|
||||||
batteryController.MeasureVoltage();
|
batteryController.MeasureVoltage();
|
||||||
|
@ -342,7 +385,9 @@ void SystemTask::Work() {
|
||||||
nimbleController.NotifyBatteryLevel(batteryController.PercentRemaining());
|
nimbleController.NotifyBatteryLevel(batteryController.PercentRemaining());
|
||||||
break;
|
break;
|
||||||
case Messages::OnPairing:
|
case Messages::OnPairing:
|
||||||
|
if (state == SystemTaskState::Sleeping) {
|
||||||
GoToRunning();
|
GoToRunning();
|
||||||
|
}
|
||||||
displayApp.PushMessage(Pinetime::Applications::Display::Messages::ShowPairingKey);
|
displayApp.PushMessage(Pinetime::Applications::Display::Messages::ShowPairingKey);
|
||||||
break;
|
break;
|
||||||
case Messages::BleRadioEnableToggle:
|
case Messages::BleRadioEnableToggle:
|
||||||
|
@ -377,48 +422,12 @@ void SystemTask::Work() {
|
||||||
#pragma clang diagnostic pop
|
#pragma clang diagnostic pop
|
||||||
}
|
}
|
||||||
|
|
||||||
void SystemTask::GoToRunning() {
|
|
||||||
if (state == SystemTaskState::Running) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// SPI doesn't go to sleep for always on mode
|
|
||||||
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;
|
|
||||||
};
|
|
||||||
|
|
||||||
void SystemTask::GoToSleep() {
|
|
||||||
if (IsSleeping()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (IsSleepDisabled()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
NRF_LOG_INFO("[systemtask] Going to sleep");
|
|
||||||
displayApp.PushMessage(Pinetime::Applications::Display::Messages::GoToSleep);
|
|
||||||
heartRateApp.PushMessage(Pinetime::Applications::HeartRateTask::Messages::GoToSleep);
|
|
||||||
|
|
||||||
state = SystemTaskState::GoingToSleep;
|
|
||||||
};
|
|
||||||
|
|
||||||
void SystemTask::UpdateMotion() {
|
void SystemTask::UpdateMotion() {
|
||||||
if (IsSleeping() && !(settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::RaiseWrist) ||
|
if (state == SystemTaskState::GoingToSleep || state == SystemTaskState::WakingUp) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state == SystemTaskState::Sleeping && !(settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::RaiseWrist) ||
|
||||||
settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::Shake) ||
|
settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::Shake) ||
|
||||||
motionController.GetService()->IsMotionNotificationSubscribed())) {
|
motionController.GetService()->IsMotionNotificationSubscribed())) {
|
||||||
return;
|
return;
|
||||||
|
@ -443,7 +452,7 @@ void SystemTask::UpdateMotion() {
|
||||||
}
|
}
|
||||||
if (settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::LowerWrist) && state == SystemTaskState::Running &&
|
if (settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::LowerWrist) && state == SystemTaskState::Running &&
|
||||||
motionController.ShouldLowerSleep()) {
|
motionController.ShouldLowerSleep()) {
|
||||||
GoToSleep();
|
PushMessage(Messages::GoToSleep);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -459,7 +468,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) {
|
if (!fastWakeUpDone && state != SystemTaskState::GoingToSleep) {
|
||||||
displayApp.PushMessage(Applications::Display::Messages::ButtonPushed);
|
displayApp.PushMessage(Applications::Display::Messages::ButtonPushed);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -479,10 +488,17 @@ 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 {
|
} else if (state == SystemTaskState::Sleeping) {
|
||||||
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);
|
||||||
|
@ -491,6 +507,10 @@ 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,7 @@ namespace Pinetime {
|
||||||
namespace System {
|
namespace System {
|
||||||
class SystemTask {
|
class SystemTask {
|
||||||
public:
|
public:
|
||||||
enum class SystemTaskState { Sleeping, Running, GoingToSleep };
|
enum class SystemTaskState { Sleeping, Running, GoingToSleep, WakingUp };
|
||||||
SystemTask(Drivers::SpiMaster& spi,
|
SystemTask(Drivers::SpiMaster& spi,
|
||||||
Pinetime::Drivers::SpiNorFlash& spiNorFlash,
|
Pinetime::Drivers::SpiNorFlash& spiNorFlash,
|
||||||
Drivers::TwiMaster& twiMaster,
|
Drivers::TwiMaster& twiMaster,
|
||||||
|
@ -79,8 +79,11 @@ namespace Pinetime {
|
||||||
|
|
||||||
void OnTouchEvent();
|
void OnTouchEvent();
|
||||||
|
|
||||||
|
void OnIdle();
|
||||||
|
void OnDim();
|
||||||
|
|
||||||
bool IsSleepDisabled() {
|
bool IsSleepDisabled() {
|
||||||
return wakeLocksHeld > 0;
|
return doNotGoToSleep;
|
||||||
}
|
}
|
||||||
|
|
||||||
Pinetime::Controllers::NimbleController& nimble() {
|
Pinetime::Controllers::NimbleController& nimble() {
|
||||||
|
@ -88,7 +91,7 @@ namespace Pinetime {
|
||||||
};
|
};
|
||||||
|
|
||||||
bool IsSleeping() const {
|
bool IsSleeping() const {
|
||||||
return state != SystemTaskState::Running;
|
return state == SystemTaskState::Sleeping || state == SystemTaskState::WakingUp;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -124,14 +127,13 @@ namespace Pinetime {
|
||||||
bool isBleDiscoveryTimerRunning = false;
|
bool isBleDiscoveryTimerRunning = false;
|
||||||
uint8_t bleDiscoveryTimer = 0;
|
uint8_t bleDiscoveryTimer = 0;
|
||||||
TimerHandle_t measureBatteryTimer;
|
TimerHandle_t measureBatteryTimer;
|
||||||
uint8_t wakeLocksHeld = 0;
|
bool doNotGoToSleep = false;
|
||||||
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);
|
||||||
|
|
|
@ -1,27 +0,0 @@
|
||||||
#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;
|
|
||||||
}
|
|
|
@ -1,19 +0,0 @@
|
||||||
#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;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in a new issue