From 63484f1c29a890a53e37864c717c673f5ab3b19c Mon Sep 17 00:00:00 2001 From: Florian Kraupa Date: Sun, 16 May 2021 12:10:47 +0200 Subject: [PATCH 1/5] built timer app --- src/CMakeLists.txt | 5 + src/components/motor/MotorController.cpp | 1 - src/components/timer/TimerController.cpp | 59 +++++++ src/components/timer/TimerController.h | 28 ++++ src/displayapp/Apps.h | 1 + src/displayapp/DisplayApp.cpp | 19 ++- src/displayapp/DisplayApp.h | 5 +- src/displayapp/Messages.h | 1 + src/displayapp/screens/ApplicationList.cpp | 2 +- src/displayapp/screens/Timer.cpp | 175 +++++++++++++++++++++ src/displayapp/screens/Timer.h | 36 +++++ src/systemtask/SystemTask.cpp | 13 +- src/systemtask/SystemTask.h | 3 + 13 files changed, 342 insertions(+), 6 deletions(-) create mode 100644 src/components/timer/TimerController.cpp create mode 100644 src/components/timer/TimerController.h create mode 100644 src/displayapp/screens/Timer.cpp create mode 100644 src/displayapp/screens/Timer.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index acbfba18c8..7ccd4ce77f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -407,6 +407,7 @@ list(APPEND SOURCE_FILES displayapp/screens/List.cpp displayapp/screens/BatteryInfo.cpp displayapp/screens/Steps.cpp + displayapp/screens/Timer.cpp ## Settings displayapp/screens/settings/QuickSettings.cpp @@ -459,6 +460,7 @@ list(APPEND SOURCE_FILES components/firmwarevalidator/FirmwareValidator.cpp components/motor/MotorController.cpp components/settings/Settings.cpp + components/timer/TimerController.cpp drivers/Cst816s.cpp FreeRTOS/port.c FreeRTOS/port_cmsis_systick.c @@ -520,6 +522,7 @@ list(APPEND RECOVERY_SOURCE_FILES components/ble/HeartRateService.cpp components/firmwarevalidator/FirmwareValidator.cpp components/settings/Settings.cpp + components/timer/TimerController.cpp drivers/Cst816s.cpp FreeRTOS/port.c FreeRTOS/port_cmsis_systick.c @@ -590,6 +593,7 @@ set(INCLUDE_FILES displayapp/screens/Notifications.h displayapp/screens/HeartRate.h displayapp/screens/Motion.h + displayapp/screens/Timer.h drivers/St7789.h drivers/SpiNorFlash.h drivers/SpiMaster.h @@ -619,6 +623,7 @@ set(INCLUDE_FILES components/ble/BleClient.h components/ble/HeartRateService.h components/settings/Settings.h + components/timer/TimerController.h drivers/Cst816s.h FreeRTOS/portmacro.h FreeRTOS/portmacro_cmsis.h diff --git a/src/components/motor/MotorController.cpp b/src/components/motor/MotorController.cpp index a834ab6b4c..3afa0cedd8 100644 --- a/src/components/motor/MotorController.cpp +++ b/src/components/motor/MotorController.cpp @@ -13,7 +13,6 @@ MotorController::MotorController(Controllers::Settings& settingsController) : se void MotorController::Init() { nrf_gpio_cfg_output(pinMotor); nrf_gpio_pin_set(pinMotor); - app_timer_init(); app_timer_create(&vibTimer, APP_TIMER_MODE_SINGLE_SHOT, vibrate); } diff --git a/src/components/timer/TimerController.cpp b/src/components/timer/TimerController.cpp new file mode 100644 index 0000000000..20138af293 --- /dev/null +++ b/src/components/timer/TimerController.cpp @@ -0,0 +1,59 @@ +// +// Created by florian on 16.05.21. +// + +#include "TimerController.h" +#include "systemtask/SystemTask.h" +#include "app_timer.h" +#include "task.h" + +using namespace Pinetime::Controllers; + + +APP_TIMER_DEF(timerAppTimer); + + +TimerController::TimerController(System::SystemTask& systemTask) : systemTask {systemTask} { +} + + +void TimerController::Init() { + app_timer_create(&timerAppTimer, APP_TIMER_MODE_SINGLE_SHOT, timerEnd); + +} + +void TimerController::StartTimer(uint32_t duration) { + app_timer_stop(timerAppTimer); + app_timer_start(timerAppTimer, APP_TIMER_TICKS(duration), this); + //dont ask why this random scaling factor is here. i got a difference between the time set and the time displayed and it works out to + //be exactly this linear factor + //you might be wondering why im not simply using app_timer_cnt_get() here. I am too. It is in app_timer.h, but the compiler says it + // doesnt exist + endTime = ((static_cast(xTaskGetTickCount()) / static_cast(configTICK_RATE_HZ)) * 1000 + APP_TIMER_TICKS(duration)) - + APP_TIMER_TICKS(duration) * 0.024; + timerRunning = true; +} + +uint32_t TimerController::GetTimeRemaining() { + if (!timerRunning) { + return 0; + } + uint32_t currentTime = (static_cast(xTaskGetTickCount()) / static_cast(configTICK_RATE_HZ)) * 1000; + return endTime - currentTime; +} + +void TimerController::timerEnd(void* p_context) { + + auto *controller = static_cast (p_context); + controller->timerRunning = false; + controller->systemTask.PushMessage(System::SystemTask::Messages::OnTimerDone); +} + +void TimerController::StopTimer() { + app_timer_stop(timerAppTimer); + timerRunning = false; +} + +bool TimerController::IsRunning() { + return timerRunning; +} \ No newline at end of file diff --git a/src/components/timer/TimerController.h b/src/components/timer/TimerController.h new file mode 100644 index 0000000000..b08b8a6aaf --- /dev/null +++ b/src/components/timer/TimerController.h @@ -0,0 +1,28 @@ +#pragma once + +#include +#include "app_timer.h" + +namespace Pinetime { + namespace System { + class SystemTask; + } + namespace Controllers { + + class TimerController { + public: + TimerController(Pinetime::System::SystemTask& systemTask); + void Init(); + void StartTimer(uint32_t duration); + void StopTimer(); + uint32_t GetTimeRemaining(); + bool IsRunning(); + + private: + System::SystemTask& systemTask; + static void timerEnd(void* p_context); + uint32_t endTime; + bool timerRunning = false; + }; + } +} \ No newline at end of file diff --git a/src/displayapp/Apps.h b/src/displayapp/Apps.h index 09a2018178..2df517f89d 100644 --- a/src/displayapp/Apps.h +++ b/src/displayapp/Apps.h @@ -11,6 +11,7 @@ namespace Pinetime { FirmwareValidation, NotificationsPreview, Notifications, + Timer, FlashLight, BatteryInfo, Music, diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index a6c4a3ec9e..9e86685eea 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include "components/battery/BatteryController.h" #include "components/ble/BleController.h" #include "components/datetime/DateTimeController.h" @@ -55,7 +56,8 @@ DisplayApp::DisplayApp(Drivers::St7789& lcd, Pinetime::Controllers::HeartRateController& heartRateController, Controllers::Settings& settingsController, Pinetime::Controllers::MotorController& motorController, - Pinetime::Controllers::MotionController& motionController) + Pinetime::Controllers::MotionController& motionController, + Pinetime::Controllers::TimerController& timerController) : lcd {lcd}, lvgl {lvgl}, touchPanel {touchPanel}, @@ -68,7 +70,8 @@ DisplayApp::DisplayApp(Drivers::St7789& lcd, heartRateController {heartRateController}, settingsController {settingsController}, motorController {motorController}, - motionController {motionController} { + motionController {motionController}, + timerController {timerController} { msgQueue = xQueueCreate(queueSize, itemSize); // Start clock when smartwatch boots LoadApp(Apps::Clock, DisplayApp::FullRefreshDirections::None); @@ -148,6 +151,14 @@ void DisplayApp::Refresh() { case Messages::NewNotification: LoadApp(Apps::NotificationsPreview, DisplayApp::FullRefreshDirections::Down); break; + case Messages::TimerDone: + if (currentApp == Apps::Timer) { + auto *timer = dynamic_cast(currentScreen.get()); + timer->setDone(); + } else { + LoadApp(Apps::Timer, DisplayApp::FullRefreshDirections::Down); + } + break; case Messages::TouchEvent: { if (state != States::Running) break; @@ -264,6 +275,10 @@ void DisplayApp::LoadApp(Apps app, DisplayApp::FullRefreshDirections direction) this, notificationManager, systemTask.nimble().alertService(), Screens::Notifications::Modes::Preview); ReturnApp(Apps::Clock, FullRefreshDirections::Up, TouchEvents::SwipeUp); break; + case Apps::Timer: + currentScreen = std::make_unique( + this, timerController); + break; // Settings case Apps::QuickSettings: diff --git a/src/displayapp/DisplayApp.h b/src/displayapp/DisplayApp.h index ffe27cf1bc..0c7bd21622 100644 --- a/src/displayapp/DisplayApp.h +++ b/src/displayapp/DisplayApp.h @@ -12,6 +12,7 @@ #include "components/firmwarevalidator/FirmwareValidator.h" #include "components/settings/Settings.h" #include "displayapp/screens/Screen.h" +#include "components/timer/TimerController.h" #include "Messages.h" namespace Pinetime { @@ -53,7 +54,8 @@ namespace Pinetime { Pinetime::Controllers::HeartRateController& heartRateController, Controllers::Settings& settingsController, Pinetime::Controllers::MotorController& motorController, - Pinetime::Controllers::MotionController& motionController); + Pinetime::Controllers::MotionController& motionController, + Pinetime::Controllers::TimerController& timerController); void Start(); void PushMessage(Display::Messages msg); @@ -76,6 +78,7 @@ namespace Pinetime { Pinetime::Controllers::Settings& settingsController; Pinetime::Controllers::MotorController& motorController; Pinetime::Controllers::MotionController& motionController; + Pinetime::Controllers::TimerController& timerController; Pinetime::Controllers::FirmwareValidator validator; Controllers::BrightnessController brightnessController; diff --git a/src/displayapp/Messages.h b/src/displayapp/Messages.h index 81871c54b9..ce65f84645 100644 --- a/src/displayapp/Messages.h +++ b/src/displayapp/Messages.h @@ -11,6 +11,7 @@ namespace Pinetime { TouchEvent, ButtonPushed, NewNotification, + TimerDone, BleFirmwareUpdateStarted, UpdateTimeOut }; diff --git a/src/displayapp/screens/ApplicationList.cpp b/src/displayapp/screens/ApplicationList.cpp index 1eb36999ef..d75bab2e8c 100644 --- a/src/displayapp/screens/ApplicationList.cpp +++ b/src/displayapp/screens/ApplicationList.cpp @@ -51,7 +51,7 @@ std::unique_ptr ApplicationList::CreateScreen1() { {Symbols::map, Apps::Navigation}, {Symbols::shoe, Apps::Steps}, {Symbols::heartBeat, Apps::HeartRate}, - {"", Apps::None}, + {Symbols::stopWatch, Apps::Timer}, }}; return std::make_unique(0, 2, app, settingsController, batteryController, dateTimeController, applications); diff --git a/src/displayapp/screens/Timer.cpp b/src/displayapp/screens/Timer.cpp new file mode 100644 index 0000000000..c43eb12c11 --- /dev/null +++ b/src/displayapp/screens/Timer.cpp @@ -0,0 +1,175 @@ +#include "Timer.h" + +#include "Screen.h" +#include "Symbols.h" +#include "lvgl/lvgl.h" + + + +using namespace Pinetime::Applications::Screens; + + +static void btnEventHandler(lv_obj_t* obj, lv_event_t event) { + Timer* screen = static_cast(obj->user_data); + screen->OnButtonEvent(obj, event); +} + +void Timer::createButtons() { + btnMinutesUp = lv_btn_create(lv_scr_act(), nullptr); + btnMinutesUp->user_data = this; + lv_obj_set_event_cb(btnMinutesUp, btnEventHandler); + lv_obj_align(btnMinutesUp, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 20, -80); + lv_obj_set_height(btnMinutesUp, 40); + lv_obj_set_width(btnMinutesUp, 60); + txtMUp = lv_label_create(btnMinutesUp, nullptr); + lv_label_set_text(txtMUp, "+"); + + btnMinutesDown = lv_btn_create(lv_scr_act(), nullptr); + btnMinutesDown->user_data = this; + lv_obj_set_event_cb(btnMinutesDown, btnEventHandler); + lv_obj_align(btnMinutesDown, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 20, +40); + lv_obj_set_height(btnMinutesDown, 40); + lv_obj_set_width(btnMinutesDown, 60); + txtMDown = lv_label_create(btnMinutesDown, nullptr); + lv_label_set_text(txtMDown, "-"); + + btnSecondsUp = lv_btn_create(lv_scr_act(), nullptr); + btnSecondsUp->user_data = this; + lv_obj_set_event_cb(btnSecondsUp, btnEventHandler); + lv_obj_align(btnSecondsUp, lv_scr_act(), LV_ALIGN_IN_RIGHT_MID,10 , -80); + lv_obj_set_height(btnSecondsUp, 40); + lv_obj_set_width(btnSecondsUp, 60); + txtSUp = lv_label_create(btnSecondsUp, nullptr); + lv_label_set_text(txtSUp, "+"); + + btnSecondsDown = lv_btn_create(lv_scr_act(), nullptr); + btnSecondsDown->user_data = this; + lv_obj_set_event_cb(btnSecondsDown, btnEventHandler); + lv_obj_align(btnSecondsDown, lv_scr_act(), LV_ALIGN_IN_RIGHT_MID, 10, +40); + lv_obj_set_height(btnSecondsDown, 40); + lv_obj_set_width(btnSecondsDown, 60); + txtSDown = lv_label_create(btnSecondsDown, nullptr); + lv_label_set_text(txtSDown, "-"); + +} + + +Timer::Timer(DisplayApp* app, Controllers::TimerController& timerController) + : Screen(app), + running {true}, + timerController {timerController}{ + + time = lv_label_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_text_font(time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_76); + lv_obj_set_style_local_text_color(time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GRAY); + + uint32_t seconds = timerController.GetTimeRemaining()/1000; + lv_label_set_text_fmt(time, "%02d:%02d" , seconds/60, seconds%60); + + lv_obj_align(time, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, -20); + + btnPlayPause = lv_btn_create(lv_scr_act(), nullptr); + btnPlayPause->user_data = this; + lv_obj_set_event_cb(btnPlayPause, btnEventHandler); + lv_obj_align(btnPlayPause, lv_scr_act(), LV_ALIGN_IN_BOTTOM_MID, 0, -10); + lv_obj_set_height(btnPlayPause, 40); + txtPlayPause = lv_label_create(btnPlayPause, nullptr); + if (timerController.IsRunning()) { + lv_label_set_text(txtPlayPause, Symbols::pause); + } else { + lv_label_set_text(txtPlayPause, Symbols::play); + } + + createButtons(); + +} + +Timer::~Timer() { + lv_obj_clean(lv_scr_act()); + +} + +bool Timer::Refresh() { + if (timerController.IsRunning()) { + uint32_t seconds = timerController.GetTimeRemaining()/1000; + lv_label_set_text_fmt(time, "%02d:%02d" , seconds/60, seconds%60); + } + return running; +} + +void Timer::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { + if (event == LV_EVENT_CLICKED) { + if (obj == btnPlayPause) { + if (timerController.IsRunning()) { + lv_label_set_text(txtPlayPause, Symbols::play); + uint32_t seconds = timerController.GetTimeRemaining()/1000; + minutesToSet = seconds/60; + secondsToSet = seconds%60; + timerController.StopTimer(); + createButtons(); + + } else if (secondsToSet + minutesToSet > 0) { + lv_label_set_text(txtPlayPause, Symbols::pause); + timerController.StartTimer((secondsToSet + minutesToSet * 60)*1000); + + lv_obj_del(btnSecondsDown); + btnSecondsDown = nullptr; + lv_obj_del(btnSecondsUp); + btnSecondsUp = nullptr; + lv_obj_del(btnMinutesDown); + btnMinutesDown = nullptr; + lv_obj_del(btnMinutesUp); + btnMinutesUp = nullptr; + + } + } + else { + if (!timerController.IsRunning()) { + if (obj == btnMinutesUp) { + if (minutesToSet >= 59) { + minutesToSet = 0; + } else { + minutesToSet++; + } + lv_label_set_text_fmt(time, "%02d:%02d" , minutesToSet, secondsToSet); + + } else if (obj == btnMinutesDown) { + if (minutesToSet == 0) { + minutesToSet = 59; + } else { + minutesToSet--; + } + lv_label_set_text_fmt(time, "%02d:%02d" , minutesToSet, secondsToSet); + + } else if (obj == btnSecondsUp) { + if (secondsToSet >= 59) { + secondsToSet = 0; + } else { + secondsToSet++; + } + lv_label_set_text_fmt(time, "%02d:%02d" , minutesToSet, secondsToSet); + + } else if (obj == btnSecondsDown) { + if (secondsToSet == 0) { + secondsToSet = 59; + } else { + secondsToSet--; + } + lv_label_set_text_fmt(time, "%02d:%02d" , minutesToSet, secondsToSet); + + } + } + + } + + } + +} + + +void Timer::setDone() { + lv_label_set_text(time, "00:00"); + lv_label_set_text(txtPlayPause, Symbols::play); + secondsToSet = 0; + minutesToSet = 0; +} \ No newline at end of file diff --git a/src/displayapp/screens/Timer.h b/src/displayapp/screens/Timer.h new file mode 100644 index 0000000000..d080c45bde --- /dev/null +++ b/src/displayapp/screens/Timer.h @@ -0,0 +1,36 @@ +#pragma once + +#include "Screen.h" +#include "components/datetime/DateTimeController.h" +#include "systemtask/SystemTask.h" +#include "../LittleVgl.h" + +#include "components/timer/TimerController.h" + +namespace Pinetime::Applications::Screens { + + + class Timer : public Screen { + public: + + enum class Modes { Normal, Done }; + Timer(DisplayApp* app, Controllers::TimerController& timerController); + ~Timer() override; + bool Refresh() override; + + void setDone(); + void OnButtonEvent(lv_obj_t* obj, lv_event_t event); + + private: + + bool running; + uint8_t secondsToSet = 0; + uint8_t minutesToSet = 0; + Controllers::TimerController& timerController; + + void createButtons(); + + lv_obj_t *time, *msecTime, *btnPlayPause, *txtPlayPause, *btnMinutesUp, *btnMinutesDown, *btnSecondsUp, *btnSecondsDown, *txtMUp, + *txtMDown, *txtSUp, *txtSDown; + }; +} \ No newline at end of file diff --git a/src/systemtask/SystemTask.cpp b/src/systemtask/SystemTask.cpp index 6d695e2cd1..b7b592f388 100644 --- a/src/systemtask/SystemTask.cpp +++ b/src/systemtask/SystemTask.cpp @@ -56,6 +56,7 @@ SystemTask::SystemTask(Drivers::SpiMaster& spi, heartRateController {*this}, bleController {bleController}, dateTimeController {*this}, + timerController {*this}, watchdog {}, watchdogView {watchdog}, motorController {motorController}, @@ -83,6 +84,8 @@ void SystemTask::Work() { NRF_LOG_INFO("Last reset reason : %s", Pinetime::Drivers::Watchdog::ResetReasonToString(watchdog.ResetReason())); APP_GPIOTE_INIT(2); + app_timer_init(); + spi.Init(); spiNorFlash.Init(); spiNorFlash.Wakeup(); @@ -96,6 +99,7 @@ void SystemTask::Work() { batteryController.Init(); motorController.Init(); motionSensor.SoftReset(); + timerController.Init(); // Reset the TWI device because the motion sensor chip most probably crashed it... twiMaster.Sleep(); @@ -116,7 +120,8 @@ void SystemTask::Work() { heartRateController, settingsController, motorController, - motionController); + motionController, + timerController); displayApp->Start(); displayApp->PushMessage(Pinetime::Applications::Display::Messages::UpdateBatteryLevel); @@ -228,6 +233,12 @@ void SystemTask::Work() { motorController.SetDuration(35); displayApp->PushMessage(Pinetime::Applications::Display::Messages::NewNotification); break; + case Messages::OnTimerDone: + if (isSleeping && !isWakingUp) + GoToRunning(); + motorController.SetDuration(35); + displayApp->PushMessage(Pinetime::Applications::Display::Messages::TimerDone); + break; case Messages::BleConnected: ReloadIdleTimer(); isBleDiscoveryTimerRunning = true; diff --git a/src/systemtask/SystemTask.h b/src/systemtask/SystemTask.h index e65fbea018..542b3acc0c 100644 --- a/src/systemtask/SystemTask.h +++ b/src/systemtask/SystemTask.h @@ -16,6 +16,7 @@ #include "components/ble/NimbleController.h" #include "components/ble/NotificationManager.h" #include "components/motor/MotorController.h" +#include "components/timer/TimerController.h" #ifdef PINETIME_IS_RECOVERY #include "displayapp/DisplayAppRecovery.h" #include "displayapp/DummyLittleVgl.h" @@ -45,6 +46,7 @@ namespace Pinetime { TouchWakeUp, OnNewTime, OnNewNotification, + OnTimerDone, OnNewCall, BleConnected, UpdateTimeOut, @@ -99,6 +101,7 @@ namespace Pinetime { Pinetime::Controllers::Ble& bleController; Pinetime::Controllers::DateTime dateTimeController; + Pinetime::Controllers::TimerController timerController; QueueHandle_t systemTasksMsgQueue; std::atomic isSleeping {false}; std::atomic isGoingToSleep {false}; From 807a19d0cf584b60e0d3667e315cc7f12a909cd2 Mon Sep 17 00:00:00 2001 From: Florian Kraupa Date: Sun, 16 May 2021 12:22:35 +0200 Subject: [PATCH 2/5] Style improvements --- src/components/timer/TimerController.cpp | 8 ++-- src/components/timer/TimerController.h | 11 +++++- src/displayapp/DisplayApp.cpp | 3 +- src/displayapp/screens/Timer.cpp | 50 ++++++++++++------------ src/displayapp/screens/Timer.h | 14 +++++-- src/systemtask/SystemTask.cpp | 6 ++- 6 files changed, 52 insertions(+), 40 deletions(-) diff --git a/src/components/timer/TimerController.cpp b/src/components/timer/TimerController.cpp index 20138af293..21ec757f64 100644 --- a/src/components/timer/TimerController.cpp +++ b/src/components/timer/TimerController.cpp @@ -13,13 +13,13 @@ using namespace Pinetime::Controllers; APP_TIMER_DEF(timerAppTimer); -TimerController::TimerController(System::SystemTask& systemTask) : systemTask {systemTask} { +TimerController::TimerController(System::SystemTask& systemTask) : systemTask{systemTask} { } void TimerController::Init() { app_timer_create(&timerAppTimer, APP_TIMER_MODE_SINGLE_SHOT, timerEnd); - + } void TimerController::StartTimer(uint32_t duration) { @@ -30,7 +30,7 @@ void TimerController::StartTimer(uint32_t duration) { //you might be wondering why im not simply using app_timer_cnt_get() here. I am too. It is in app_timer.h, but the compiler says it // doesnt exist endTime = ((static_cast(xTaskGetTickCount()) / static_cast(configTICK_RATE_HZ)) * 1000 + APP_TIMER_TICKS(duration)) - - APP_TIMER_TICKS(duration) * 0.024; + APP_TIMER_TICKS(duration) * 0.024; timerRunning = true; } @@ -44,7 +44,7 @@ uint32_t TimerController::GetTimeRemaining() { void TimerController::timerEnd(void* p_context) { - auto *controller = static_cast (p_context); + auto* controller = static_cast (p_context); controller->timerRunning = false; controller->systemTask.PushMessage(System::SystemTask::Messages::OnTimerDone); } diff --git a/src/components/timer/TimerController.h b/src/components/timer/TimerController.h index b08b8a6aaf..ab8a207759 100644 --- a/src/components/timer/TimerController.h +++ b/src/components/timer/TimerController.h @@ -12,16 +12,23 @@ namespace Pinetime { class TimerController { public: TimerController(Pinetime::System::SystemTask& systemTask); + void Init(); + void StartTimer(uint32_t duration); + void StopTimer(); + uint32_t GetTimeRemaining(); - bool IsRunning(); + bool IsRunning(); + private: System::SystemTask& systemTask; + static void timerEnd(void* p_context); - uint32_t endTime; + + uint32_t endTime{}; bool timerRunning = false; }; } diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index 9e86685eea..419b9f6fd2 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -276,8 +276,7 @@ void DisplayApp::LoadApp(Apps app, DisplayApp::FullRefreshDirections direction) ReturnApp(Apps::Clock, FullRefreshDirections::Up, TouchEvents::SwipeUp); break; case Apps::Timer: - currentScreen = std::make_unique( - this, timerController); + currentScreen = std::make_unique(this, timerController); break; // Settings diff --git a/src/displayapp/screens/Timer.cpp b/src/displayapp/screens/Timer.cpp index c43eb12c11..114dad8093 100644 --- a/src/displayapp/screens/Timer.cpp +++ b/src/displayapp/screens/Timer.cpp @@ -5,7 +5,6 @@ #include "lvgl/lvgl.h" - using namespace Pinetime::Applications::Screens; @@ -36,7 +35,7 @@ void Timer::createButtons() { btnSecondsUp = lv_btn_create(lv_scr_act(), nullptr); btnSecondsUp->user_data = this; lv_obj_set_event_cb(btnSecondsUp, btnEventHandler); - lv_obj_align(btnSecondsUp, lv_scr_act(), LV_ALIGN_IN_RIGHT_MID,10 , -80); + lv_obj_align(btnSecondsUp, lv_scr_act(), LV_ALIGN_IN_RIGHT_MID, 10, -80); lv_obj_set_height(btnSecondsUp, 40); lv_obj_set_width(btnSecondsUp, 60); txtSUp = lv_label_create(btnSecondsUp, nullptr); @@ -56,16 +55,16 @@ void Timer::createButtons() { Timer::Timer(DisplayApp* app, Controllers::TimerController& timerController) : Screen(app), - running {true}, - timerController {timerController}{ + running{true}, + timerController{timerController} { time = lv_label_create(lv_scr_act(), nullptr); lv_obj_set_style_local_text_font(time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_76); lv_obj_set_style_local_text_color(time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GRAY); - - uint32_t seconds = timerController.GetTimeRemaining()/1000; - lv_label_set_text_fmt(time, "%02d:%02d" , seconds/60, seconds%60); - + + uint32_t seconds = timerController.GetTimeRemaining() / 1000; + lv_label_set_text_fmt(time, "%02d:%02d", seconds / 60, seconds % 60); + lv_obj_align(time, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, -20); btnPlayPause = lv_btn_create(lv_scr_act(), nullptr); @@ -91,8 +90,8 @@ Timer::~Timer() { bool Timer::Refresh() { if (timerController.IsRunning()) { - uint32_t seconds = timerController.GetTimeRemaining()/1000; - lv_label_set_text_fmt(time, "%02d:%02d" , seconds/60, seconds%60); + uint32_t seconds = timerController.GetTimeRemaining() / 1000; + lv_label_set_text_fmt(time, "%02d:%02d", seconds / 60, seconds % 60); } return running; } @@ -102,15 +101,15 @@ void Timer::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { if (obj == btnPlayPause) { if (timerController.IsRunning()) { lv_label_set_text(txtPlayPause, Symbols::play); - uint32_t seconds = timerController.GetTimeRemaining()/1000; - minutesToSet = seconds/60; - secondsToSet = seconds%60; + uint32_t seconds = timerController.GetTimeRemaining() / 1000; + minutesToSet = seconds / 60; + secondsToSet = seconds % 60; timerController.StopTimer(); createButtons(); - + } else if (secondsToSet + minutesToSet > 0) { lv_label_set_text(txtPlayPause, Symbols::pause); - timerController.StartTimer((secondsToSet + minutesToSet * 60)*1000); + timerController.StartTimer((secondsToSet + minutesToSet * 60) * 1000); lv_obj_del(btnSecondsDown); btnSecondsDown = nullptr; @@ -120,10 +119,9 @@ void Timer::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { btnMinutesDown = nullptr; lv_obj_del(btnMinutesUp); btnMinutesUp = nullptr; - + } - } - else { + } else { if (!timerController.IsRunning()) { if (obj == btnMinutesUp) { if (minutesToSet >= 59) { @@ -131,32 +129,32 @@ void Timer::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { } else { minutesToSet++; } - lv_label_set_text_fmt(time, "%02d:%02d" , minutesToSet, secondsToSet); - + lv_label_set_text_fmt(time, "%02d:%02d", minutesToSet, secondsToSet); + } else if (obj == btnMinutesDown) { if (minutesToSet == 0) { minutesToSet = 59; } else { minutesToSet--; } - lv_label_set_text_fmt(time, "%02d:%02d" , minutesToSet, secondsToSet); - + lv_label_set_text_fmt(time, "%02d:%02d", minutesToSet, secondsToSet); + } else if (obj == btnSecondsUp) { if (secondsToSet >= 59) { secondsToSet = 0; } else { secondsToSet++; } - lv_label_set_text_fmt(time, "%02d:%02d" , minutesToSet, secondsToSet); - + lv_label_set_text_fmt(time, "%02d:%02d", minutesToSet, secondsToSet); + } else if (obj == btnSecondsDown) { if (secondsToSet == 0) { secondsToSet = 59; } else { secondsToSet--; } - lv_label_set_text_fmt(time, "%02d:%02d" , minutesToSet, secondsToSet); - + lv_label_set_text_fmt(time, "%02d:%02d", minutesToSet, secondsToSet); + } } diff --git a/src/displayapp/screens/Timer.h b/src/displayapp/screens/Timer.h index d080c45bde..0d66f2d46e 100644 --- a/src/displayapp/screens/Timer.h +++ b/src/displayapp/screens/Timer.h @@ -12,13 +12,19 @@ namespace Pinetime::Applications::Screens { class Timer : public Screen { public: - - enum class Modes { Normal, Done }; + + enum class Modes { + Normal, Done + }; + Timer(DisplayApp* app, Controllers::TimerController& timerController); + ~Timer() override; + bool Refresh() override; void setDone(); + void OnButtonEvent(lv_obj_t* obj, lv_event_t event); private: @@ -30,7 +36,7 @@ namespace Pinetime::Applications::Screens { void createButtons(); - lv_obj_t *time, *msecTime, *btnPlayPause, *txtPlayPause, *btnMinutesUp, *btnMinutesDown, *btnSecondsUp, *btnSecondsDown, *txtMUp, - *txtMDown, *txtSUp, *txtSDown; + lv_obj_t* time, * msecTime, * btnPlayPause, * txtPlayPause, * btnMinutesUp, * btnMinutesDown, * btnSecondsUp, * btnSecondsDown, * txtMUp, + * txtMDown, * txtSUp, * txtSDown; }; } \ No newline at end of file diff --git a/src/systemtask/SystemTask.cpp b/src/systemtask/SystemTask.cpp index b7b592f388..800c636b4d 100644 --- a/src/systemtask/SystemTask.cpp +++ b/src/systemtask/SystemTask.cpp @@ -228,14 +228,16 @@ void SystemTask::Work() { displayApp->PushMessage(Pinetime::Applications::Display::Messages::UpdateDateTime); break; case Messages::OnNewNotification: - if (isSleeping && !isWakingUp) + if (isSleeping && !isWakingUp) { GoToRunning(); + } motorController.SetDuration(35); displayApp->PushMessage(Pinetime::Applications::Display::Messages::NewNotification); break; case Messages::OnTimerDone: - if (isSleeping && !isWakingUp) + if (isSleeping && !isWakingUp) { GoToRunning(); + } motorController.SetDuration(35); displayApp->PushMessage(Pinetime::Applications::Display::Messages::TimerDone); break; From f370dc93a43dd50e5f9cf6797c9ba8d3fa287eac Mon Sep 17 00:00:00 2001 From: Florian Kraupa Date: Sun, 16 May 2021 12:54:23 +0200 Subject: [PATCH 3/5] making sure buttons stay hidden when the app is reopened and reappear after the timer runs out --- src/displayapp/screens/Timer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/displayapp/screens/Timer.cpp b/src/displayapp/screens/Timer.cpp index 114dad8093..260a17ef00 100644 --- a/src/displayapp/screens/Timer.cpp +++ b/src/displayapp/screens/Timer.cpp @@ -77,10 +77,9 @@ Timer::Timer(DisplayApp* app, Controllers::TimerController& timerController) lv_label_set_text(txtPlayPause, Symbols::pause); } else { lv_label_set_text(txtPlayPause, Symbols::play); + createButtons(); } - createButtons(); - } Timer::~Timer() { @@ -170,4 +169,5 @@ void Timer::setDone() { lv_label_set_text(txtPlayPause, Symbols::play); secondsToSet = 0; minutesToSet = 0; + createButtons(); } \ No newline at end of file From 0a680a430cc6ff6354152ef35eaa7cbd3f8e86b1 Mon Sep 17 00:00:00 2001 From: Florian Kraupa Date: Sun, 16 May 2021 21:23:45 +0200 Subject: [PATCH 4/5] more sensible calculations of time deltas. eliminated that mysterious scaling factor --- src/components/timer/TimerController.cpp | 21 +++++++++++++-------- src/components/timer/TimerController.h | 5 +++-- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/components/timer/TimerController.cpp b/src/components/timer/TimerController.cpp index 21ec757f64..3b25901c7e 100644 --- a/src/components/timer/TimerController.cpp +++ b/src/components/timer/TimerController.cpp @@ -24,13 +24,9 @@ void TimerController::Init() { void TimerController::StartTimer(uint32_t duration) { app_timer_stop(timerAppTimer); + auto currentTicks = xTaskGetTickCount(); app_timer_start(timerAppTimer, APP_TIMER_TICKS(duration), this); - //dont ask why this random scaling factor is here. i got a difference between the time set and the time displayed and it works out to - //be exactly this linear factor - //you might be wondering why im not simply using app_timer_cnt_get() here. I am too. It is in app_timer.h, but the compiler says it - // doesnt exist - endTime = ((static_cast(xTaskGetTickCount()) / static_cast(configTICK_RATE_HZ)) * 1000 + APP_TIMER_TICKS(duration)) - - APP_TIMER_TICKS(duration) * 0.024; + endTicks = currentTicks + APP_TIMER_TICKS(duration); timerRunning = true; } @@ -38,8 +34,17 @@ uint32_t TimerController::GetTimeRemaining() { if (!timerRunning) { return 0; } - uint32_t currentTime = (static_cast(xTaskGetTickCount()) / static_cast(configTICK_RATE_HZ)) * 1000; - return endTime - currentTime; + auto currentTicks = xTaskGetTickCount(); + + TickType_t deltaTicks = 0; + if (currentTicks > endTicks) { + deltaTicks = 0xffffffff - currentTicks; + deltaTicks += (endTicks + 1); + } else { + deltaTicks = endTicks - currentTicks; + } + + return (static_cast(deltaTicks) / static_cast(configTICK_RATE_HZ)) * 1000; } void TimerController::timerEnd(void* p_context) { diff --git a/src/components/timer/TimerController.h b/src/components/timer/TimerController.h index ab8a207759..5a0b293ee5 100644 --- a/src/components/timer/TimerController.h +++ b/src/components/timer/TimerController.h @@ -2,6 +2,7 @@ #include #include "app_timer.h" +#include "portmacro_cmsis.h" namespace Pinetime { namespace System { @@ -27,8 +28,8 @@ namespace Pinetime { System::SystemTask& systemTask; static void timerEnd(void* p_context); - - uint32_t endTime{}; + + TickType_t endTicks; bool timerRunning = false; }; } From f09f894eb0cf6dfbff05f5aa3a2f2f5369538769 Mon Sep 17 00:00:00 2001 From: Florian Kraupa Date: Thu, 20 May 2021 04:12:27 +0200 Subject: [PATCH 5/5] changing the timer icon --- src/displayapp/fonts/README.md | 2 +- src/displayapp/fonts/jetbrains_mono_bold_20.c | 36 +++++++++++-------- src/displayapp/screens/ApplicationList.cpp | 2 +- src/displayapp/screens/Symbols.h | 1 + 4 files changed, 25 insertions(+), 16 deletions(-) diff --git a/src/displayapp/fonts/README.md b/src/displayapp/fonts/README.md index f43e9c52de..183ad7e416 100644 --- a/src/displayapp/fonts/README.md +++ b/src/displayapp/fonts/README.md @@ -12,7 +12,7 @@ * Do not enable font compression and horizontal subpixel hinting * Load the file `JetBrainsMono-Bold.tff` and specify the following range : `0x20-0x7f, 0x410-0x44f` * Add a 2nd font, load the file `FontAwesome5-Solid+Brands+Regular.woff` and specify the following - range : `0xf293, 0xf294, 0xf244, 0xf240, 0xf242, 0xf243, 0xf241, 0xf54b, 0xf21e, 0xf1e6, 0xf54b, 0xf017, 0xf129, 0xf03a, 0xf185, 0xf560, 0xf001, 0xf3fd, 0xf069, 0xf1fc, 0xf45d, 0xf59f, 0xf5a0, 0xf029, 0xf027, 0xf028, 0xf6a9, 0xf04b, 0xf04c, 0xf048, 0xf051, 0xf095, 0xf3dd, 0xf04d, 0xf2f2, 0xf024` + range : `0xf293, 0xf294, 0xf244, 0xf240, 0xf242, 0xf243, 0xf241, 0xf54b, 0xf21e, 0xf1e6, 0xf54b, 0xf017, 0xf129, 0xf03a, 0xf185, 0xf560, 0xf001, 0xf3fd, 0xf069, 0xf1fc, 0xf45d, 0xf59f, 0xf5a0, 0xf029, 0xf027, 0xf028, 0xf6a9, 0xf04b, 0xf04c, 0xf048, 0xf051, 0xf095, 0xf3dd, 0xf04d, 0xf2f2, 0xf024, 0xf252` * Click on Convert, and download the file `jetbrains_mono_bold_20.c` and copy it in `src/DisplayApp/Fonts` Add new symbols: diff --git a/src/displayapp/fonts/jetbrains_mono_bold_20.c b/src/displayapp/fonts/jetbrains_mono_bold_20.c index f4050db830..9174ff489e 100644 --- a/src/displayapp/fonts/jetbrains_mono_bold_20.c +++ b/src/displayapp/fonts/jetbrains_mono_bold_20.c @@ -900,6 +900,13 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t gylph_bitmap[] = { 0x7, 0xe0, 0x0, 0x7, 0xf0, 0x0, 0x3, 0xff, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xe0, + /* U+F252 "" */ + 0xff, 0xff, 0xff, 0xfd, 0x80, 0x33, 0x80, 0xe7, + 0xff, 0xc7, 0xff, 0xf, 0xfe, 0xf, 0xf8, 0xf, + 0xe0, 0xf, 0x80, 0x7f, 0xc0, 0xe3, 0x83, 0x83, + 0x86, 0x3, 0x1f, 0xff, 0x3f, 0xfe, 0x7f, 0xfd, + 0xff, 0xff, 0xff, 0xf8, + /* U+F293 "" */ 0x7, 0xe0, 0x3f, 0xe0, 0xfb, 0xe3, 0xf3, 0xe7, 0xe3, 0xdf, 0xd3, 0xf9, 0xb3, 0xf9, 0x4f, 0xf8, @@ -1184,17 +1191,18 @@ static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = { {.bitmap_index = 3380, .adv_w = 400, .box_w = 25, .box_h = 12, .ofs_x = 0, .ofs_y = 1}, {.bitmap_index = 3418, .adv_w = 400, .box_w = 25, .box_h = 12, .ofs_x = 0, .ofs_y = 1}, {.bitmap_index = 3456, .adv_w = 400, .box_w = 25, .box_h = 12, .ofs_x = 0, .ofs_y = 1}, - {.bitmap_index = 3494, .adv_w = 280, .box_w = 15, .box_h = 20, .ofs_x = 1, .ofs_y = -3}, - {.bitmap_index = 3532, .adv_w = 200, .box_w = 11, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 3561, .adv_w = 280, .box_w = 16, .box_h = 19, .ofs_x = 1, .ofs_y = -2}, - {.bitmap_index = 3599, .adv_w = 400, .box_w = 25, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 3665, .adv_w = 360, .box_w = 23, .box_h = 17, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 3714, .adv_w = 320, .box_w = 20, .box_h = 20, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 3764, .adv_w = 400, .box_w = 25, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 3824, .adv_w = 320, .box_w = 20, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 3877, .adv_w = 360, .box_w = 22, .box_h = 20, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 3932, .adv_w = 360, .box_w = 22, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 3985, .adv_w = 320, .box_w = 20, .box_h = 15, .ofs_x = 0, .ofs_y = 0} + {.bitmap_index = 3494, .adv_w = 240, .box_w = 15, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 3530, .adv_w = 280, .box_w = 15, .box_h = 20, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 3568, .adv_w = 200, .box_w = 11, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 3597, .adv_w = 280, .box_w = 16, .box_h = 19, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 3635, .adv_w = 400, .box_w = 25, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 3701, .adv_w = 360, .box_w = 23, .box_h = 17, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 3750, .adv_w = 320, .box_w = 20, .box_h = 20, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 3800, .adv_w = 400, .box_w = 25, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 3860, .adv_w = 320, .box_w = 20, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 3913, .adv_w = 360, .box_w = 22, .box_h = 20, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 3968, .adv_w = 360, .box_w = 22, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 4021, .adv_w = 320, .box_w = 20, .box_h = 15, .ofs_x = 0, .ofs_y = 0} }; /*--------------------- @@ -1205,8 +1213,8 @@ static const uint16_t unicode_list_2[] = { 0x0, 0x16, 0x23, 0x26, 0x27, 0x28, 0x39, 0x47, 0x4a, 0x4b, 0x4c, 0x50, 0x68, 0x94, 0x128, 0x184, 0x1e5, 0x1fb, 0x21d, 0x23f, 0x240, 0x241, 0x242, 0x243, - 0x292, 0x293, 0x2f1, 0x3dc, 0x3fc, 0x45c, 0x54a, 0x55f, - 0x59e, 0x59f, 0x6a8 + 0x251, 0x292, 0x293, 0x2f1, 0x3dc, 0x3fc, 0x45c, 0x54a, + 0x55f, 0x59e, 0x59f, 0x6a8 }; /*Collect the unicode lists and glyph_id offsets*/ @@ -1222,7 +1230,7 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = }, { .range_start = 61441, .range_length = 1705, .glyph_id_start = 160, - .unicode_list = unicode_list_2, .glyph_id_ofs_list = NULL, .list_length = 35, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY + .unicode_list = unicode_list_2, .glyph_id_ofs_list = NULL, .list_length = 36, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY } }; diff --git a/src/displayapp/screens/ApplicationList.cpp b/src/displayapp/screens/ApplicationList.cpp index d75bab2e8c..d599f5cc80 100644 --- a/src/displayapp/screens/ApplicationList.cpp +++ b/src/displayapp/screens/ApplicationList.cpp @@ -51,7 +51,7 @@ std::unique_ptr ApplicationList::CreateScreen1() { {Symbols::map, Apps::Navigation}, {Symbols::shoe, Apps::Steps}, {Symbols::heartBeat, Apps::HeartRate}, - {Symbols::stopWatch, Apps::Timer}, + {Symbols::hourGlass, Apps::Timer}, }}; return std::make_unique(0, 2, app, settingsController, batteryController, dateTimeController, applications); diff --git a/src/displayapp/screens/Symbols.h b/src/displayapp/screens/Symbols.h index e60825c15e..8d55f693f1 100644 --- a/src/displayapp/screens/Symbols.h +++ b/src/displayapp/screens/Symbols.h @@ -38,6 +38,7 @@ namespace Pinetime { static constexpr const char* pause = "\xEF\x81\x8C"; static constexpr const char* stop = "\xEF\x81\x8D"; static constexpr const char* stopWatch = "\xEF\x8B\xB2"; + static constexpr const char* hourGlass = "\xEF\x89\x92"; static constexpr const char* lapsFlag = "\xEF\x80\xA4"; // lv_font_sys_48.c