summaryrefslogtreecommitdiff
path: root/src/displayapp/screens
diff options
context:
space:
mode:
Diffstat (limited to 'src/displayapp/screens')
-rw-r--r--src/displayapp/screens/ApplicationList.cpp1
-rw-r--r--src/displayapp/screens/Clock.cpp3
-rw-r--r--src/displayapp/screens/Clock.h3
-rw-r--r--src/displayapp/screens/HeartRate.cpp115
-rw-r--r--src/displayapp/screens/HeartRate.h40
-rw-r--r--src/displayapp/screens/WatchFaceDigital.cpp27
-rw-r--r--src/displayapp/screens/WatchFaceDigital.h7
7 files changed, 196 insertions, 0 deletions
diff --git a/src/displayapp/screens/ApplicationList.cpp b/src/displayapp/screens/ApplicationList.cpp
index b7c8ebd..c8d608a 100644
--- a/src/displayapp/screens/ApplicationList.cpp
+++ b/src/displayapp/screens/ApplicationList.cpp
@@ -37,6 +37,7 @@ bool ApplicationList::OnTouchEvent(Pinetime::Applications::TouchEvents event) {
std::unique_ptr<Screen> ApplicationList::CreateScreen1() {
std::array<Screens::Tile::Applications, 6> applications {{
{Symbols::clock},
+ {Symbols::heartBeat, Apps::HeartRate},
}};
return std::make_unique<Screens::Tile>(0, 1, app, settingsController, batteryController, dateTimeController, applications);
diff --git a/src/displayapp/screens/Clock.cpp b/src/displayapp/screens/Clock.cpp
index ab4cafd..1893856 100644
--- a/src/displayapp/screens/Clock.cpp
+++ b/src/displayapp/screens/Clock.cpp
@@ -19,6 +19,7 @@ Clock::Clock(DisplayApp* app,
Controllers::Ble& bleController,
Controllers::NotificationManager& notificatioManager,
Controllers::Settings& settingsController,
+ Controllers::HeartRateController& heartRateController,
Controllers::MotionController& motionController,
System::SystemTask& systemTask)
: Screen(app),
@@ -28,6 +29,7 @@ Clock::Clock(DisplayApp* app,
bleController {bleController},
notificatioManager {notificatioManager},
settingsController {settingsController},
+ heartRateController {heartRateController},
motionController {motionController},
screen {[this, &settingsController]() {
switch (settingsController.GetClockFace()) {
@@ -59,6 +61,7 @@ std::unique_ptr<Screen> Clock::WatchFaceDigitalScreen() {
bleController,
notificatioManager,
settingsController,
+ heartRateController,
motionController,
systemTask);
}
diff --git a/src/displayapp/screens/Clock.h b/src/displayapp/screens/Clock.h
index 5001dce..86793e9 100644
--- a/src/displayapp/screens/Clock.h
+++ b/src/displayapp/screens/Clock.h
@@ -4,6 +4,7 @@
#include <chrono>
#include <cstdint>
#include <memory>
+#include <components/heartrate/HeartRateController.h>
#include "displayapp/screens/Screen.h"
#include "components/datetime/DateTimeController.h"
#include "systemtask/SystemTask.h"
@@ -27,6 +28,7 @@ namespace Pinetime {
Controllers::Ble& bleController,
Controllers::NotificationManager& notificatioManager,
Controllers::Settings& settingsController,
+ Controllers::HeartRateController& heartRateController,
Controllers::MotionController& motionController,
System::SystemTask& systemTask);
~Clock() override;
@@ -41,6 +43,7 @@ namespace Pinetime {
Controllers::Ble& bleController;
Controllers::NotificationManager& notificatioManager;
Controllers::Settings& settingsController;
+ Controllers::HeartRateController& heartRateController;
Controllers::MotionController& motionController;
std::unique_ptr<Screen> screen;
diff --git a/src/displayapp/screens/HeartRate.cpp b/src/displayapp/screens/HeartRate.cpp
new file mode 100644
index 0000000..6f9154b
--- /dev/null
+++ b/src/displayapp/screens/HeartRate.cpp
@@ -0,0 +1,115 @@
+#include "displayapp/screens/HeartRate.h"
+#include <lvgl/lvgl.h>
+#include <components/heartrate/HeartRateController.h>
+
+#include "displayapp/DisplayApp.h"
+
+using namespace Pinetime::Applications::Screens;
+
+namespace {
+ const char* ToString(Pinetime::Controllers::HeartRateController::States s) {
+ switch (s) {
+ case Pinetime::Controllers::HeartRateController::States::NotEnoughData:
+ return "Not enough data,\nplease wait...";
+ case Pinetime::Controllers::HeartRateController::States::NoTouch:
+ return "No touch detected";
+ case Pinetime::Controllers::HeartRateController::States::Running:
+ return "Measuring...";
+ case Pinetime::Controllers::HeartRateController::States::Stopped:
+ return "Stopped";
+ }
+ return "";
+ }
+
+ static void btnStartStopEventHandler(lv_obj_t* obj, lv_event_t event) {
+ HeartRate* screen = static_cast<HeartRate*>(obj->user_data);
+ screen->OnStartStopEvent(event);
+ }
+}
+
+HeartRate::HeartRate(Pinetime::Applications::DisplayApp* app,
+ Controllers::HeartRateController& heartRateController,
+ System::SystemTask& systemTask)
+ : Screen(app), heartRateController {heartRateController}, systemTask {systemTask} {
+ bool isHrRunning = heartRateController.State() != Controllers::HeartRateController::States::Stopped;
+ label_hr = lv_label_create(lv_scr_act(), nullptr);
+
+ lv_obj_set_style_local_text_font(label_hr, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &neofont3);
+
+ if (isHrRunning)
+ lv_obj_set_style_local_text_color(label_hr, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GREEN);
+ else
+ lv_obj_set_style_local_text_color(label_hr, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GRAY);
+
+ lv_label_set_text(label_hr, "000");
+ lv_obj_align(label_hr, nullptr, LV_ALIGN_CENTER, 0, -40);
+
+ label_bpm = lv_label_create(lv_scr_act(), nullptr);
+ lv_label_set_text(label_bpm, "Heart rate BPM");
+ lv_obj_align(label_bpm, label_hr, LV_ALIGN_OUT_TOP_MID, 0, -20);
+
+ label_status = lv_label_create(lv_scr_act(), nullptr);
+ lv_obj_set_style_local_text_color(label_status, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x222222));
+ lv_label_set_text(label_status, ToString(Pinetime::Controllers::HeartRateController::States::NotEnoughData));
+
+ lv_obj_align(label_status, label_hr, LV_ALIGN_OUT_BOTTOM_MID, 0, 10);
+
+ btn_startStop = lv_btn_create(lv_scr_act(), nullptr);
+ btn_startStop->user_data = this;
+ lv_obj_set_height(btn_startStop, 50);
+ lv_obj_set_event_cb(btn_startStop, btnStartStopEventHandler);
+ lv_obj_align(btn_startStop, nullptr, LV_ALIGN_IN_BOTTOM_MID, 0, 0);
+
+ label_startStop = lv_label_create(btn_startStop, nullptr);
+ UpdateStartStopButton(isHrRunning);
+ if (isHrRunning)
+ systemTask.PushMessage(Pinetime::System::Messages::DisableSleeping);
+
+ taskRefresh = lv_task_create(RefreshTaskCallback, 100, LV_TASK_PRIO_MID, this);
+}
+
+HeartRate::~HeartRate() {
+ lv_task_del(taskRefresh);
+ lv_obj_clean(lv_scr_act());
+ systemTask.PushMessage(Pinetime::System::Messages::EnableSleeping);
+}
+
+void HeartRate::Refresh() {
+
+ auto state = heartRateController.State();
+ switch (state) {
+ case Controllers::HeartRateController::States::NoTouch:
+ case Controllers::HeartRateController::States::NotEnoughData:
+ // case Controllers::HeartRateController::States::Stopped:
+ lv_label_set_text(label_hr, "000");
+ break;
+ default:
+ lv_label_set_text_fmt(label_hr, "%03d", heartRateController.HeartRate());
+ }
+
+ lv_label_set_text(label_status, ToString(state));
+ lv_obj_align(label_status, label_hr, LV_ALIGN_OUT_BOTTOM_MID, 0, 10);
+}
+
+void HeartRate::OnStartStopEvent(lv_event_t event) {
+ if (event == LV_EVENT_CLICKED) {
+ if (heartRateController.State() == Controllers::HeartRateController::States::Stopped) {
+ heartRateController.Start();
+ UpdateStartStopButton(heartRateController.State() != Controllers::HeartRateController::States::Stopped);
+ systemTask.PushMessage(Pinetime::System::Messages::DisableSleeping);
+ lv_obj_set_style_local_text_color(label_hr, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GREEN);
+ } else {
+ heartRateController.Stop();
+ UpdateStartStopButton(heartRateController.State() != Controllers::HeartRateController::States::Stopped);
+ systemTask.PushMessage(Pinetime::System::Messages::EnableSleeping);
+ lv_obj_set_style_local_text_color(label_hr, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GRAY);
+ }
+ }
+}
+
+void HeartRate::UpdateStartStopButton(bool isRunning) {
+ if (isRunning)
+ lv_label_set_text(label_startStop, "Stop");
+ else
+ lv_label_set_text(label_startStop, "Start");
+}
diff --git a/src/displayapp/screens/HeartRate.h b/src/displayapp/screens/HeartRate.h
new file mode 100644
index 0000000..2ad0035
--- /dev/null
+++ b/src/displayapp/screens/HeartRate.h
@@ -0,0 +1,40 @@
+#pragma once
+
+#include <cstdint>
+#include <chrono>
+#include "displayapp/screens/Screen.h"
+#include "systemtask/SystemTask.h"
+#include <lvgl/src/lv_core/lv_style.h>
+#include <lvgl/src/lv_core/lv_obj.h>
+
+namespace Pinetime {
+ namespace Controllers {
+ class HeartRateController;
+ }
+ namespace Applications {
+ namespace Screens {
+
+ class HeartRate : public Screen {
+ public:
+ HeartRate(DisplayApp* app, Controllers::HeartRateController& HeartRateController, System::SystemTask& systemTask);
+ ~HeartRate() override;
+
+ void Refresh() override;
+
+ void OnStartStopEvent(lv_event_t event);
+
+ private:
+ Controllers::HeartRateController& heartRateController;
+ Pinetime::System::SystemTask& systemTask;
+ void UpdateStartStopButton(bool isRunning);
+ lv_obj_t* label_hr;
+ lv_obj_t* label_bpm;
+ lv_obj_t* label_status;
+ lv_obj_t* btn_startStop;
+ lv_obj_t* label_startStop;
+
+ lv_task_t* taskRefresh;
+ };
+ }
+ }
+}
diff --git a/src/displayapp/screens/WatchFaceDigital.cpp b/src/displayapp/screens/WatchFaceDigital.cpp
index 963bfe4..44421ff 100644
--- a/src/displayapp/screens/WatchFaceDigital.cpp
+++ b/src/displayapp/screens/WatchFaceDigital.cpp
@@ -10,6 +10,7 @@
#include "components/battery/BatteryController.h"
#include "components/ble/BleController.h"
#include "components/ble/NotificationManager.h"
+#include "components/heartrate/HeartRateController.h"
#include "components/motion/MotionController.h"
#include "components/settings/Settings.h"
#include "displayapp/fonts/neofont.h"
@@ -21,6 +22,7 @@ WatchFaceDigital::WatchFaceDigital(DisplayApp* app,
Controllers::Ble& bleController,
Controllers::NotificationManager& notificatioManager,
Controllers::Settings& settingsController,
+ Controllers::HeartRateController& heartRateController,
Controllers::MotionController& motionController,
System::SystemTask& systemTask)
: Screen(app),
@@ -31,6 +33,7 @@ WatchFaceDigital::WatchFaceDigital(DisplayApp* app,
bleController {bleController},
notificatioManager {notificatioManager},
settingsController {settingsController},
+ heartRateController {heartRateController},
motionController {motionController} {
if (1) {
@@ -254,6 +257,16 @@ WatchFaceDigital::WatchFaceDigital(DisplayApp* app,
lv_obj_set_pos(backgroundLabel, 0, 0);
lv_label_set_text_static(backgroundLabel, "");
+ heartbeatIcon = lv_label_create(lv_scr_act(), nullptr);
+ lv_label_set_text_static(heartbeatIcon, Symbols::heartBeat);
+ lv_obj_set_style_local_text_color(heartbeatIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0xCE1B1B));
+ lv_obj_align(heartbeatIcon, lv_scr_act(), LV_ALIGN_IN_BOTTOM_LEFT, 0, 0);
+
+ heartbeatValue = lv_label_create(lv_scr_act(), nullptr);
+ lv_obj_set_style_local_text_color(heartbeatValue, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0xCE1B1B));
+ lv_label_set_text_static(heartbeatValue, "");
+ lv_obj_align(heartbeatValue, heartbeatIcon, LV_ALIGN_OUT_RIGHT_MID, 5, 0);
+
taskRefresh = lv_task_create(RefreshTaskCallback, LV_DISP_DEF_REFR_PERIOD, LV_TASK_PRIO_MID, this);
Refresh();
}
@@ -380,4 +393,18 @@ void WatchFaceDigital::Refresh() {
}
}
+ heartbeat = heartRateController.HeartRate();
+ heartbeatRunning = heartRateController.State() != Controllers::HeartRateController::States::Stopped;
+ if (heartbeat.IsUpdated() || heartbeatRunning.IsUpdated()) {
+ if (heartbeatRunning.Get()) {
+ lv_obj_set_style_local_text_color(heartbeatIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0xCE1B1B));
+ lv_label_set_text_fmt(heartbeatValue, "%d", heartbeat.Get());
+ } else {
+ lv_obj_set_style_local_text_color(heartbeatIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x1B1B1B));
+ lv_label_set_text_static(heartbeatValue, "");
+ }
+
+ lv_obj_realign(heartbeatIcon);
+ lv_obj_realign(heartbeatValue);
+ }
}
diff --git a/src/displayapp/screens/WatchFaceDigital.h b/src/displayapp/screens/WatchFaceDigital.h
index 8382996..93719c1 100644
--- a/src/displayapp/screens/WatchFaceDigital.h
+++ b/src/displayapp/screens/WatchFaceDigital.h
@@ -15,6 +15,7 @@ namespace Pinetime {
class Battery;
class Ble;
class NotificationManager;
+ class HeartRateController;
class MotionController;
}
@@ -29,6 +30,7 @@ namespace Pinetime {
Controllers::Ble& bleController,
Controllers::NotificationManager& notificatioManager,
Controllers::Settings& settingsController,
+ Controllers::HeartRateController& heartRateController,
Controllers::MotionController& motionController,
System::SystemTask& systemTask);
~WatchFaceDigital() override;
@@ -54,6 +56,8 @@ namespace Pinetime {
DirtyValue<std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds>> currentDateTime {};
DirtyValue<bool> motionSensorOk {};
DirtyValue<uint32_t> stepCount {};
+ DirtyValue<uint8_t> heartbeat {};
+ DirtyValue<bool> heartbeatRunning {};
DirtyValue<bool> notificationState {};
lv_obj_t* label_temp;
@@ -68,6 +72,8 @@ namespace Pinetime {
lv_obj_t* batteryIcon;
lv_obj_t* bleIcon;
lv_obj_t* batteryPlug;
+ lv_obj_t* heartbeatIcon;
+ lv_obj_t* heartbeatValue;
lv_obj_t* stepIcon;
lv_obj_t* stepValue;
lv_obj_t* notificationIcon;
@@ -77,6 +83,7 @@ namespace Pinetime {
Controllers::Ble& bleController;
Controllers::NotificationManager& notificatioManager;
Controllers::Settings& settingsController;
+ Controllers::HeartRateController& heartRateController;
Controllers::MotionController& motionController;
lv_task_t* taskRefresh;