Skip to content

Commit

Permalink
Merge pull request #12 from tituscmd/patricgruber-heartrate-measureme…
Browse files Browse the repository at this point in the history
…nts-in-background

Patricgruber heartrate measurements in background
  • Loading branch information
tituscmd authored Aug 22, 2024
2 parents e10f5bd + 10d9ea2 commit 1440faa
Show file tree
Hide file tree
Showing 3 changed files with 142 additions and 62 deletions.
8 changes: 7 additions & 1 deletion src/displayapp/screens/settings/Settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,18 @@ namespace Pinetime {
{Symbols::cloudSunRain, "Weather", Apps::SettingWeatherFormat},

{Symbols::batteryHalf, "Battery", Apps::BatteryInfo},

{Symbols::clock, "Chimes", Apps::SettingChimes},
{Symbols::tachometer, "Shake Calib.", Apps::SettingShakeThreshold},
{Symbols::check, "Firmware", Apps::FirmwareValidation},

{Symbols::bluetooth, "Bluetooth", Apps::SettingBluetooth},
{Symbols::list, "About", Apps::SysInfo}
{Symbols::list, "About", Apps::SysInfo},

// {Symbols::none, "None", Apps::None},
// {Symbols::none, "None", Apps::None},
// {Symbols::none, "None", Apps::None},
// {Symbols::none, "None", Apps::None},

}};
ScreenList<nScreens> screens;
Expand Down
163 changes: 106 additions & 57 deletions src/heartratetask/HeartRateTask.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,21 @@

using namespace Pinetime::Applications;

TickType_t CurrentTaskDelay(HeartRateTask::States state, TickType_t ppgDeltaTms) {
switch (state) {
case HeartRateTask::States::Measuring:
case HeartRateTask::States::BackgroundMeasuring:
return ppgDeltaTms;
case HeartRateTask::States::Running:
return pdMS_TO_TICKS(100);
case HeartRateTask::States::BackgroundWaiting:
return pdMS_TO_TICKS(10000);
default:
return portMAX_DELAY;
}
}


HeartRateTask::HeartRateTask(Drivers::Hrs3300& heartRateSensor,
Controllers::HeartRateController& controller,
Controllers::Settings& settings)
Expand All @@ -29,47 +44,22 @@ void HeartRateTask::Work() {
int lastBpm = 0;

while (true) {
TickType_t delay = CurrentTaskDelay();
TickType_t delay = CurrentTaskDelay(state, ppg.deltaTms);
Messages msg;

if (xQueueReceive(messageQueue, &msg, delay) == pdTRUE) {
switch (msg) {
case Messages::GoToSleep:
if (state == States::Running) {
state = States::Idle;
} else if (state == States::Measuring) {
state = States::BackgroundWaiting;
StartWaiting();
}
HandleGoToSleep();
break;
case Messages::WakeUp:
if (state == States::Idle) {
state = States::Running;
} else if (state == States::BackgroundMeasuring) {
state = States::Measuring;
} else if (state == States::BackgroundWaiting) {
state = States::Measuring;
StartMeasurement();
}
HandleWakeUp();
break;
case Messages::StartMeasurement:
if (state == States::Measuring || state == States::BackgroundMeasuring) {
break;
}
state = States::Measuring;
lastBpm = 0;
StartMeasurement();
HandleStartMeasurement(&lastBpm);
break;
case Messages::StopMeasurement:
if (state == States::Running || state == States::Idle) {
break;
}
if (state == States::Measuring) {
state = States::Running;
} else if (state == States::BackgroundMeasuring) {
state = States::Idle;
}
StopMeasurement();
HandleStopMeasurement();
break;
}
}
Expand Down Expand Up @@ -106,6 +96,75 @@ void HeartRateTask::StartWaiting() {
backgroundWaitingStart = xTaskGetTickCount();
}

void HeartRateTask::HandleGoToSleep() {
switch (state) {
case States::Running:
state = States::Idle;
break;
case States::Measuring:
state = States::BackgroundMeasuring;
break;
case States::Idle:
case States::BackgroundWaiting:
case States::BackgroundMeasuring:
// shouldn't happen -> ignore
break;
}
}

void HeartRateTask::HandleWakeUp() {
switch (state) {
case States::Idle:
state = States::Running;
break;
case States::BackgroundMeasuring:
state = States::Measuring;
break;
case States::BackgroundWaiting:
state = States::Measuring;
StartMeasurement();
break;
case States::Running:
case States::Measuring:
// shouldn't happen -> ignore
break;
}
}

void HeartRateTask::HandleStartMeasurement(int* lastBpm) {
switch (state) {
case States::Idle:
case States::Running:
state = States::Measuring;
*lastBpm = 0;
StartMeasurement();
break;
case States::Measuring:
case States::BackgroundMeasuring:
case States::BackgroundWaiting:
// shouldn't happen -> ignore
break;
}
}

void HeartRateTask::HandleStopMeasurement() {
switch (state) {
case States::Measuring:
state = States::Running;
StopMeasurement();
break;
case States::BackgroundMeasuring:
case States::BackgroundWaiting:
state = States::Idle;
StopMeasurement();
break;
case States::Running:
case States::Idle:
// shouldn't happen -> ignore
break;
}
}

void HeartRateTask::HandleBackgroundWaiting() {
if (!IsBackgroundMeasurementActivated()) {
return;
Expand Down Expand Up @@ -150,48 +209,38 @@ void HeartRateTask::HandleSensorData(int* lastBpm) {
}
TickType_t ticksSinceMeasurementStart = xTaskGetTickCount() - measurementStart;
if (bpm == 0 && state == States::BackgroundMeasuring && !IsContinuosModeActivated() &&
ticksSinceMeasurementStart >= DURATION_UNTIL_BACKGROUND_MEASURMENT_IS_STOPPED) {
state = States::BackgroundWaiting;
StartWaiting();
}
if (bpm == 0 && state == States::BackgroundMeasuring &&
xTaskGetTickCount() - measurementStart >= DURATION_UNTIL_BACKGROUND_MEASURMENT_IS_STOPPED) {
ticksSinceMeasurementStart >= DURATION_UNTIL_BACKGROUND_MEASUREMENT_IS_STOPPED) {
state = States::BackgroundWaiting;
StartWaiting();
}
}

TickType_t HeartRateTask::CurrentTaskDelay() {
switch (state) {
case States::Measuring:
case States::BackgroundMeasuring:
return ppg.deltaTms;
case States::Running:
return pdMS_TO_TICKS(100);
case States::BackgroundWaiting:
return pdMS_TO_TICKS(10000);
default:
return portMAX_DELAY;
}
}

TickType_t HeartRateTask::GetHeartRateBackgroundMeasurementIntervalInTicks() {
int ms;
switch (settings.GetHeartRateBackgroundMeasurementInterval()) {
case Pinetime::Controllers::Settings::HeartRateBackgroundMeasurementInterval::TenSeconds:
return pdMS_TO_TICKS(10 * 1000);
ms = 10 * 1000;
break;
case Pinetime::Controllers::Settings::HeartRateBackgroundMeasurementInterval::ThirtySeconds:
return pdMS_TO_TICKS(30 * 1000);
ms = 30 * 1000;
break;
case Pinetime::Controllers::Settings::HeartRateBackgroundMeasurementInterval::OneMinute:
return pdMS_TO_TICKS(60 * 1000);
ms = 60 * 1000;
break;
case Pinetime::Controllers::Settings::HeartRateBackgroundMeasurementInterval::FiveMinutes:
return pdMS_TO_TICKS(5 * 60 * 1000);
ms = 5 * 60 * 1000;
break;
case Pinetime::Controllers::Settings::HeartRateBackgroundMeasurementInterval::TenMinutes:
return pdMS_TO_TICKS(10 * 60 * 1000);
ms = 10 * 60 * 1000;
break;
case Pinetime::Controllers::Settings::HeartRateBackgroundMeasurementInterval::ThirtyMinutes:
return pdMS_TO_TICKS(30 * 60 * 1000);
ms = 30 * 60 * 1000;
break;
default:
return 0;
ms = 0;
break;
}
return pdMS_TO_TICKS(ms);
}

bool HeartRateTask::IsContinuosModeActivated() {
Expand Down
33 changes: 29 additions & 4 deletions src/heartratetask/HeartRateTask.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
#include <components/heartrate/Ppg.h>
#include "components/settings/Settings.h"

#define DURATION_UNTIL_BACKGROUND_MEASURMENT_IS_STOPPED pdMS_TO_TICKS(30 * 1000)
#define DURATION_UNTIL_BACKGROUND_MEASUREMENT_IS_STOPPED pdMS_TO_TICKS(30 * 1000)

namespace Pinetime {
namespace Drivers {
Expand All @@ -19,8 +19,29 @@ namespace Pinetime {
namespace Applications {
class HeartRateTask {
public:
enum class Messages : uint8_t { GoToSleep, WakeUp, StartMeasurement, StopMeasurement };
enum class States { Idle, Running, Measuring, BackgroundWaiting, BackgroundMeasuring };
enum class Messages : uint8_t {
// Screen gets turned off
GoToSleep,
// Screen gets turned on
WakeUp,
// Start button pressed
StartMeasurement,
// Stop button pressed
StopMeasurement
};

enum class States {
// Screen turned off, heartrate not measured
Idle,
// Screen turned on, heartrate app open, heartrate not measured
Running,
// Screen turned on, heartrate app open, heartrate actively measured
Measuring,
// Screen turned off, heartrate task is waiting until the next measurement should be started
BackgroundWaiting,
// Screen turned off, heartrate actively measured
BackgroundMeasuring
};

explicit HeartRateTask(Drivers::Hrs3300& heartRateSensor,
Controllers::HeartRateController& controller,
Expand All @@ -35,9 +56,13 @@ namespace Pinetime {
void StopMeasurement();
void StartWaiting();

void HandleGoToSleep();
void HandleWakeUp();
void HandleStartMeasurement(int* lastBpm);
void HandleStopMeasurement();

void HandleBackgroundWaiting();
void HandleSensorData(int* lastBpm);
TickType_t CurrentTaskDelay();

TickType_t GetHeartRateBackgroundMeasurementIntervalInTicks();
bool IsContinuosModeActivated();
Expand Down

0 comments on commit 1440faa

Please sign in to comment.