diff options
Diffstat (limited to 'src/displayapp')
-rw-r--r-- | src/displayapp/Apps.h | 2 | ||||
-rw-r--r-- | src/displayapp/DisplayApp.cpp | 12 | ||||
-rw-r--r-- | src/displayapp/DisplayApp.h | 5 | ||||
-rw-r--r-- | src/displayapp/screens/ApplicationList.cpp | 2 | ||||
-rw-r--r-- | src/displayapp/screens/Clock.cpp | 18 | ||||
-rw-r--r-- | src/displayapp/screens/Clock.h | 6 | ||||
-rw-r--r-- | src/displayapp/screens/HeartRate.cpp | 115 | ||||
-rw-r--r-- | src/displayapp/screens/HeartRate.h | 42 |
8 files changed, 189 insertions, 13 deletions
diff --git a/src/displayapp/Apps.h b/src/displayapp/Apps.h index f5fb24d0..fcadf2a2 100644 --- a/src/displayapp/Apps.h +++ b/src/displayapp/Apps.h @@ -2,6 +2,6 @@ namespace Pinetime { namespace Applications { - enum class Apps {None, Launcher, Clock, SysInfo, Meter, Gauge, Brightness, Music, FirmwareValidation, Paint, Paddle, Notifications, Twos}; + enum class Apps {None, Launcher, Clock, SysInfo, Meter, Gauge, Brightness, Music, FirmwareValidation, Paint, Paddle, Notifications, Twos, HeartRate}; } } diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index 162d0226..7ae9f819 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -1,5 +1,6 @@ #include "DisplayApp.h" #include <libraries/log/nrf_log.h> +#include <displayapp/screens/HeartRate.h> #include "components/battery/BatteryController.h" #include "components/ble/BleController.h" #include "components/datetime/DateTimeController.h" @@ -29,7 +30,8 @@ DisplayApp::DisplayApp(Drivers::St7789 &lcd, Components::LittleVgl &lvgl, Driver Controllers::Battery &batteryController, Controllers::Ble &bleController, Controllers::DateTime &dateTimeController, Drivers::WatchdogView &watchdog, System::SystemTask &systemTask, - Pinetime::Controllers::NotificationManager& notificationManager) : + Pinetime::Controllers::NotificationManager& notificationManager, + Pinetime::Controllers::HeartRateController& heartRateController) : lcd{lcd}, lvgl{lvgl}, batteryController{batteryController}, @@ -37,9 +39,10 @@ DisplayApp::DisplayApp(Drivers::St7789 &lcd, Components::LittleVgl &lvgl, Driver dateTimeController{dateTimeController}, watchdog{watchdog}, touchPanel{touchPanel}, - currentScreen{new Screens::Clock(this, dateTimeController, batteryController, bleController, notificationManager) }, + currentScreen{new Screens::Clock(this, dateTimeController, batteryController, bleController, notificationManager, heartRateController) }, systemTask{systemTask}, - notificationManager{notificationManager} { + notificationManager{notificationManager}, + heartRateController{heartRateController} { msgQueue = xQueueCreate(queueSize, itemSize); onClockApp = true; modal.reset(new Screens::Modal(this)); @@ -197,7 +200,7 @@ void DisplayApp::RunningState() { case Apps::None: case Apps::Launcher: currentScreen.reset(new Screens::ApplicationList(this)); break; case Apps::Clock: - currentScreen.reset(new Screens::Clock(this, dateTimeController, batteryController, bleController, notificationManager)); + currentScreen.reset(new Screens::Clock(this, dateTimeController, batteryController, bleController, notificationManager, heartRateController)); onClockApp = true; break; // case Apps::Test: currentScreen.reset(new Screens::Message(this)); break; @@ -211,6 +214,7 @@ void DisplayApp::RunningState() { case Apps::Music : currentScreen.reset(new Screens::Music(this, systemTask.nimble().music())); break; case Apps::FirmwareValidation: currentScreen.reset(new Screens::FirmwareValidation(this, validator)); break; case Apps::Notifications: currentScreen.reset(new Screens::Notifications(this, notificationManager, Screens::Notifications::Modes::Normal)); break; + case Apps::HeartRate: currentScreen.reset(new Screens::HeartRate(this, heartRateController)); break; } nextApp = Apps::None; } diff --git a/src/displayapp/DisplayApp.h b/src/displayapp/DisplayApp.h index 25cd2813..da5a7b22 100644 --- a/src/displayapp/DisplayApp.h +++ b/src/displayapp/DisplayApp.h @@ -23,6 +23,7 @@ namespace Pinetime { class Ble; class DateTime; class NotificationManager; + class HeartRateController; } namespace System { @@ -42,7 +43,8 @@ namespace Pinetime { Controllers::Battery &batteryController, Controllers::Ble &bleController, Controllers::DateTime &dateTimeController, Drivers::WatchdogView &watchdog, System::SystemTask &systemTask, - Pinetime::Controllers::NotificationManager& notificationManager); + Pinetime::Controllers::NotificationManager& notificationManager, + Pinetime::Controllers::HeartRateController& heartRateController); void Start(); void PushMessage(Messages msg); @@ -87,6 +89,7 @@ namespace Pinetime { Pinetime::Controllers::NotificationManager& notificationManager; Pinetime::Controllers::FirmwareValidator validator; TouchModes touchMode = TouchModes::Gestures; + Pinetime::Controllers::HeartRateController& heartRateController; }; } } diff --git a/src/displayapp/screens/ApplicationList.cpp b/src/displayapp/screens/ApplicationList.cpp index 0b8face3..57fbde20 100644 --- a/src/displayapp/screens/ApplicationList.cpp +++ b/src/displayapp/screens/ApplicationList.cpp @@ -45,7 +45,7 @@ std::unique_ptr<Screen> ApplicationList::CreateScreen1() { {Symbols::sun, Apps::Brightness}, {Symbols::list, Apps::SysInfo}, {Symbols::check, Apps::FirmwareValidation}, - {Symbols::none, Apps::None} + {Symbols::heartBeat, Apps::HeartRate} } diff --git a/src/displayapp/screens/Clock.cpp b/src/displayapp/screens/Clock.cpp index 57659141..2988922e 100644 --- a/src/displayapp/screens/Clock.cpp +++ b/src/displayapp/screens/Clock.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 "../DisplayApp.h" using namespace Pinetime::Applications::Screens; @@ -26,9 +27,11 @@ Clock::Clock(DisplayApp* app, Controllers::DateTime& dateTimeController, Controllers::Battery& batteryController, Controllers::Ble& bleController, - Controllers::NotificationManager& notificatioManager) : Screen(app), currentDateTime{{}}, + Controllers::NotificationManager& notificatioManager, + Controllers::HeartRateController& heartRateController): Screen(app), currentDateTime{{}}, dateTimeController{dateTimeController}, batteryController{batteryController}, - bleController{bleController}, notificatioManager{notificatioManager} { + bleController{bleController}, notificatioManager{notificatioManager}, + heartRateController{heartRateController} { displayedChar[0] = 0; displayedChar[1] = 0; displayedChar[2] = 0; @@ -171,10 +174,15 @@ bool Clock::Refresh() { } } - // TODO heartbeat = heartBeatController.GetValue(); - if(heartbeat.IsUpdated()) { + heartbeat = heartRateController.HeartRate(); + heartbeatRunning = heartRateController.State() != Controllers::HeartRateController::States::Stopped; + if(heartbeat.IsUpdated() || heartbeatRunning.IsUpdated()) { char heartbeatBuffer[4]; - sprintf(heartbeatBuffer, "%d", heartbeat.Get()); + if(heartbeatRunning.Get()) + sprintf(heartbeatBuffer, "%d", heartbeat.Get()); + else + sprintf(heartbeatBuffer, "---"); + lv_label_set_text(heartbeatValue, heartbeatBuffer); lv_obj_align(heartbeatIcon, lv_scr_act(), LV_ALIGN_IN_BOTTOM_LEFT, 5, -2); lv_obj_align(heartbeatValue, heartbeatIcon, LV_ALIGN_OUT_RIGHT_MID, 5, 0); diff --git a/src/displayapp/screens/Clock.h b/src/displayapp/screens/Clock.h index 4c5f60a0..4d5be282 100644 --- a/src/displayapp/screens/Clock.h +++ b/src/displayapp/screens/Clock.h @@ -12,6 +12,7 @@ namespace Pinetime { class Battery; class Ble; class NotificationManager; + class HeartRateController; } namespace Applications { @@ -42,7 +43,8 @@ namespace Pinetime { Controllers::DateTime& dateTimeController, Controllers::Battery& batteryController, Controllers::Ble& bleController, - Controllers::NotificationManager& notificatioManager); + Controllers::NotificationManager& notificatioManager, + Controllers::HeartRateController& heartRateController); ~Clock() override; bool Refresh() override; @@ -67,6 +69,7 @@ namespace Pinetime { DirtyValue<std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds>> currentDateTime; DirtyValue<uint32_t> stepCount {0}; DirtyValue<uint8_t> heartbeat {0}; + DirtyValue<bool> heartbeatRunning {false}; DirtyValue<bool> notificationState {false}; lv_obj_t* label_time; @@ -86,6 +89,7 @@ namespace Pinetime { Controllers::Battery& batteryController; Controllers::Ble& bleController; Controllers::NotificationManager& notificatioManager; + Controllers::HeartRateController& heartRateController; bool running = true; diff --git a/src/displayapp/screens/HeartRate.cpp b/src/displayapp/screens/HeartRate.cpp new file mode 100644 index 00000000..d55ed019 --- /dev/null +++ b/src/displayapp/screens/HeartRate.cpp @@ -0,0 +1,115 @@ +#include <libs/lvgl/lvgl.h> +#include "HeartRate.h" +#include <components/heartrate/HeartRateController.h> + +#include "../DisplayApp.h" + +using namespace Pinetime::Applications::Screens; +extern lv_font_t jetbrains_mono_extrabold_compressed; +extern lv_font_t jetbrains_mono_bold_20; + +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) : Screen(app), heartRateController{heartRateController} { + label_bpm = lv_label_create(lv_scr_act(), NULL); + + labelStyle = const_cast<lv_style_t *>(lv_label_get_style(label_bpm, LV_LABEL_STYLE_MAIN)); + labelStyle->text.font = &jetbrains_mono_bold_20; + + lv_style_copy(&labelBigStyle, labelStyle); + labelBigStyle.text.font = &jetbrains_mono_extrabold_compressed; + + lv_label_set_style(label_bpm, LV_LABEL_STYLE_MAIN, labelStyle); + + label_hr = lv_label_create(lv_scr_act(), NULL); + lv_label_set_style(label_hr, LV_LABEL_STYLE_MAIN, &labelBigStyle); + lv_obj_align(label_hr, lv_scr_act(), LV_ALIGN_CENTER, -70, -40); + lv_label_set_text(label_hr, "000"); + + 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(), NULL); + lv_label_set_text(label_status, ToString(Pinetime::Controllers::HeartRateController::States::NotEnoughData)); + lv_label_set_style(label_status, LV_LABEL_STYLE_MAIN, labelStyle); + lv_obj_align(label_status, label_hr, LV_ALIGN_OUT_BOTTOM_MID, 0, 10); + + btn_startStop = lv_btn_create(lv_scr_act(), NULL); + 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(heartRateController.State() != Controllers::HeartRateController::States::Stopped); +} + +HeartRate::~HeartRate() { + lv_obj_clean(lv_scr_act()); +} + +bool HeartRate::Refresh() { + char hr[4]; + + 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: + sprintf(hr, "%03d", heartRateController.HeartRate()); + lv_label_set_text(label_hr, hr); + } + + lv_label_set_text(label_status, ToString(state)); + lv_obj_align(label_status, label_hr, LV_ALIGN_OUT_BOTTOM_MID, 0, 10); + + return running; +} + +bool HeartRate::OnButtonPushed() { + running = false; + return true; +} + +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); + } + else { + heartRateController.Stop(); + UpdateStartStopButton(heartRateController.State() != Controllers::HeartRateController::States::Stopped); + } + } +} + +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 00000000..b9424998 --- /dev/null +++ b/src/displayapp/screens/HeartRate.h @@ -0,0 +1,42 @@ +#pragma once + +#include <cstdint> +#include <chrono> +#include "Screen.h" +#include <bits/unique_ptr.h> +#include <libs/lvgl/src/lv_core/lv_style.h> +#include <libs/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); + ~HeartRate() override; + + bool Refresh() override; + bool OnButtonPushed() override; + void OnStartStopEvent(lv_event_t event); + + private: + Controllers::HeartRateController& heartRateController; + void UpdateStartStopButton(bool isRunning); + lv_obj_t* label_hr; + lv_obj_t* label_bpm; + lv_obj_t* label_status; + lv_style_t labelBigStyle; + lv_style_t* labelStyle; + lv_obj_t* btn_startStop; + lv_obj_t* label_startStop; + + bool running = true; + + }; + } + } +} |