summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMark Russell <mruss660@gmail.com>2021-09-10 18:40:13 -0400
committerMark Russell <mruss660@gmail.com>2021-09-10 18:40:13 -0400
commit1fb5757655c1cdf0e93f03ad27869e8c043d69f0 (patch)
tree398a6762e69a9ba41f4cbd4e9f8f9995c94cfb21 /src
parent6f9f0e8b0e42a5526d47ca664534fb6b0ccb6ace (diff)
Created basic alarm app
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt5
-rw-r--r--src/components/alarm/AlarmController.cpp118
-rw-r--r--src/components/alarm/AlarmController.h50
-rw-r--r--src/components/motor/MotorController.cpp6
-rw-r--r--src/components/motor/MotorController.h1
-rw-r--r--src/displayapp/Apps.h1
-rw-r--r--src/displayapp/DisplayApp.cpp13
-rw-r--r--src/displayapp/DisplayApp.h4
-rw-r--r--src/displayapp/Messages.h3
-rw-r--r--src/displayapp/screens/Alarm.cpp225
-rw-r--r--src/displayapp/screens/Alarm.h31
-rw-r--r--src/displayapp/screens/ApplicationList.cpp2
-rw-r--r--src/main.cpp3
-rw-r--r--src/systemtask/Messages.h4
-rw-r--r--src/systemtask/SystemTask.cpp14
-rw-r--r--src/systemtask/SystemTask.h3
16 files changed, 480 insertions, 3 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index a7242903..ccade83e 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -418,6 +418,7 @@ list(APPEND SOURCE_FILES
displayapp/screens/BatteryInfo.cpp
displayapp/screens/Steps.cpp
displayapp/screens/Timer.cpp
+ displayapp/screens/Alarm.cpp
displayapp/Colors.cpp
## Settings
@@ -474,6 +475,7 @@ list(APPEND SOURCE_FILES
components/motor/MotorController.cpp
components/settings/Settings.cpp
components/timer/TimerController.cpp
+ components/alarm/AlarmController.cpp
components/fs/FS.cpp
drivers/Cst816s.cpp
FreeRTOS/port.c
@@ -540,6 +542,7 @@ list(APPEND RECOVERY_SOURCE_FILES
components/firmwarevalidator/FirmwareValidator.cpp
components/settings/Settings.cpp
components/timer/TimerController.cpp
+ components/alarm/AlarmController.cpp
drivers/Cst816s.cpp
FreeRTOS/port.c
FreeRTOS/port_cmsis_systick.c
@@ -612,6 +615,7 @@ set(INCLUDE_FILES
displayapp/screens/Metronome.h
displayapp/screens/Motion.h
displayapp/screens/Timer.h
+ displayapp/screens/Alarm.h
displayapp/Colors.h
drivers/St7789.h
drivers/SpiNorFlash.h
@@ -643,6 +647,7 @@ set(INCLUDE_FILES
components/ble/HeartRateService.h
components/settings/Settings.h
components/timer/TimerController.h
+ components/alarm/AlarmController.h
drivers/Cst816s.h
FreeRTOS/portmacro.h
FreeRTOS/portmacro_cmsis.h
diff --git a/src/components/alarm/AlarmController.cpp b/src/components/alarm/AlarmController.cpp
new file mode 100644
index 00000000..5097936f
--- /dev/null
+++ b/src/components/alarm/AlarmController.cpp
@@ -0,0 +1,118 @@
+//
+// Created by mrussell on 30.08.21.
+//
+// Copied from Florian's Timer app
+
+#include "AlarmController.h"
+#include "systemtask/SystemTask.h"
+#include "app_timer.h"
+#include "task.h"
+#include <chrono>
+
+using namespace Pinetime::Controllers;
+using namespace std::chrono_literals;
+
+AlarmController::AlarmController(Controllers::DateTime& dateTimeController) : dateTimeController {dateTimeController} {
+}
+
+APP_TIMER_DEF(alarmAppTimer);
+
+namespace {
+ void SetOffAlarm(void* p_context) {
+ auto* controller = static_cast<Pinetime::Controllers::AlarmController*>(p_context);
+ if (controller != nullptr)
+ controller->SetOffAlarmNow();
+ }
+}
+
+void AlarmController::Init() {
+ app_timer_create(&alarmAppTimer, APP_TIMER_MODE_SINGLE_SHOT, SetOffAlarm);
+}
+
+void AlarmController::SetAlarm(uint8_t alarmHr, uint8_t alarmMin) {
+ hours = alarmHr;
+ minutes = alarmMin;
+ state = AlarmState::Set;
+ scheduleAlarm();
+}
+
+void AlarmController::scheduleAlarm() {
+ // Determine the next time the alarm needs to go off and set the app_timer
+ app_timer_stop(alarmAppTimer);
+
+ auto now = dateTimeController.CurrentDateTime();
+ alarmTime = now;
+ time_t ttAlarmTime = std::chrono::system_clock::to_time_t(alarmTime);
+ tm* tmAlarmTime = std::localtime(&ttAlarmTime);
+
+ // If the time being set has already passed today,the alarm should be set for tomorrow
+ if (hours < dateTimeController.Hours() || (hours == dateTimeController.Hours() && minutes <= dateTimeController.Minutes())) {
+ tmAlarmTime->tm_mday += 1;
+ // tm_wday doesn't update automatically
+ tmAlarmTime->tm_wday = (tmAlarmTime->tm_wday + 1) % 7;
+ }
+
+ tmAlarmTime->tm_hour = hours;
+ tmAlarmTime->tm_min = minutes;
+ tmAlarmTime->tm_sec = 0;
+
+ // if alarm is in weekday-only mode, make sure it shifts to the next weekday
+ if (recurrence == RecurType::Weekdays) {
+ if (tmAlarmTime->tm_wday == 0) { // Sunday, shift 1 day
+ tmAlarmTime->tm_mday += 1;
+ } else if (tmAlarmTime->tm_wday == 6) { // Saturday, shift 2 days
+ tmAlarmTime->tm_mday += 2;
+ }
+ }
+ tmAlarmTime->tm_isdst = -1; // use system timezone setting to determine DST
+
+ // now can convert back to a time_point
+ alarmTime = std::chrono::system_clock::from_time_t(std::mktime(tmAlarmTime));
+ auto mSecToAlarm = std::chrono::duration_cast<std::chrono::milliseconds>(alarmTime - now).count();
+ app_timer_start(alarmAppTimer, APP_TIMER_TICKS(mSecToAlarm), this);
+}
+
+uint32_t AlarmController::SecondsToAlarm() {
+ return std::chrono::duration_cast<std::chrono::seconds>(alarmTime - dateTimeController.CurrentDateTime()).count();
+}
+
+void AlarmController::DisableAlarm() {
+ app_timer_stop(alarmAppTimer);
+ state = AlarmState::Not_Set;
+}
+
+void AlarmController::SetOffAlarmNow() {
+ state = AlarmState::Alerting;
+ if (systemTask != nullptr) {
+ systemTask->PushMessage(System::Messages::SetOffAlarm);
+ }
+}
+
+void AlarmController::StopAlerting() {
+ if (systemTask != nullptr) {
+ systemTask->PushMessage(System::Messages::StopRinging);
+ }
+
+ // Alarm state is off unless this is a recurring alarm
+ if (recurrence == RecurType::None) {
+ state = AlarmState::Not_Set;
+ } else {
+ state = AlarmState::Set;
+ // set next instance
+ scheduleAlarm();
+ }
+}
+
+void AlarmController::ToggleRecurrence() {
+ if (recurrence == AlarmController::RecurType::None) {
+ recurrence = AlarmController::RecurType::Daily;
+ } else if (recurrence == AlarmController::RecurType::Daily) {
+ recurrence = AlarmController::RecurType::Weekdays;
+ } else {
+ recurrence = AlarmController::RecurType::None;
+ }
+}
+
+void AlarmController::Register(Pinetime::System::SystemTask* systemTask) {
+ this->systemTask = systemTask;
+}
diff --git a/src/components/alarm/AlarmController.h b/src/components/alarm/AlarmController.h
new file mode 100644
index 00000000..22259da8
--- /dev/null
+++ b/src/components/alarm/AlarmController.h
@@ -0,0 +1,50 @@
+#pragma once
+
+#include <cstdint>
+#include "app_timer.h"
+#include "components/datetime/DateTimeController.h"
+
+namespace Pinetime {
+ namespace System {
+ class SystemTask;
+ }
+ namespace Controllers {
+ class AlarmController {
+ public:
+ AlarmController(Controllers::DateTime& dateTimeController);
+
+ void Init();
+ void SetAlarm(uint8_t alarmHr, uint8_t alarmMin);
+ void DisableAlarm();
+ void SetOffAlarmNow();
+ uint32_t SecondsToAlarm();
+ void StopAlerting();
+ void Register(System::SystemTask* systemTask);
+ enum class AlarmState { Not_Set, Set, Alerting };
+ enum class RecurType { None, Daily, Weekdays };
+ void ToggleRecurrence();
+ uint8_t Hours() const {
+ return hours;
+ }
+ uint8_t Minutes() const {
+ return minutes;
+ }
+ AlarmState State() const {
+ return state;
+ }
+ RecurType Recurrence() const {
+ return recurrence;
+ }
+
+ private:
+ Controllers::DateTime& dateTimeController;
+ System::SystemTask* systemTask = nullptr;
+ uint8_t hours;
+ uint8_t minutes;
+ std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds> alarmTime;
+ AlarmState state = AlarmState::Not_Set;
+ RecurType recurrence = RecurType::None;
+ void scheduleAlarm();
+ };
+ }
+} \ No newline at end of file
diff --git a/src/components/motor/MotorController.cpp b/src/components/motor/MotorController.cpp
index b25e6bc8..5ade19e4 100644
--- a/src/components/motor/MotorController.cpp
+++ b/src/components/motor/MotorController.cpp
@@ -42,6 +42,12 @@ void MotorController::StartRinging() {
app_timer_start(longVibTimer, APP_TIMER_TICKS(1000), this);
}
+// This function is the same as StartRinging(), but will ring even if notifications are turned off in Settings
+void MotorController::StartRingingDisregardSettings() {
+ Ring(this);
+ app_timer_start(longVibTimer, APP_TIMER_TICKS(1000), this);
+}
+
void MotorController::StopRinging() {
app_timer_stop(longVibTimer);
nrf_gpio_pin_set(pinMotor);
diff --git a/src/components/motor/MotorController.h b/src/components/motor/MotorController.h
index d2c9fe5f..d3b96b07 100644
--- a/src/components/motor/MotorController.h
+++ b/src/components/motor/MotorController.h
@@ -15,6 +15,7 @@ namespace Pinetime {
void RunForDuration(uint8_t motorDuration);
void StartRinging();
static void StopRinging();
+ void StartRingingDisregardSettings();
private:
static void Ring(void* p_context);
diff --git a/src/displayapp/Apps.h b/src/displayapp/Apps.h
index dd51fdb4..e3aca8cf 100644
--- a/src/displayapp/Apps.h
+++ b/src/displayapp/Apps.h
@@ -12,6 +12,7 @@ namespace Pinetime {
NotificationsPreview,
Notifications,
Timer,
+ Alarm,
FlashLight,
BatteryInfo,
Music,
diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp
index d6100ece..33c67e22 100644
--- a/src/displayapp/DisplayApp.cpp
+++ b/src/displayapp/DisplayApp.cpp
@@ -3,6 +3,7 @@
#include <displayapp/screens/HeartRate.h>
#include <displayapp/screens/Motion.h>
#include <displayapp/screens/Timer.h>
+#include <displayapp/screens/Alarm.h>
#include "components/battery/BatteryController.h"
#include "components/ble/BleController.h"
#include "components/datetime/DateTimeController.h"
@@ -90,6 +91,7 @@ DisplayApp::DisplayApp(Drivers::St7789& lcd,
Pinetime::Controllers::MotorController& motorController,
Pinetime::Controllers::MotionController& motionController,
Pinetime::Controllers::TimerController& timerController,
+ Pinetime::Controllers::AlarmController& alarmController,
Pinetime::Controllers::TouchHandler& touchHandler)
: lcd {lcd},
lvgl {lvgl},
@@ -104,6 +106,7 @@ DisplayApp::DisplayApp(Drivers::St7789& lcd,
motorController {motorController},
motionController {motionController},
timerController {timerController},
+ alarmController {alarmController},
touchHandler {touchHandler} {
}
@@ -208,6 +211,13 @@ void DisplayApp::Refresh() {
LoadApp(Apps::Timer, DisplayApp::FullRefreshDirections::Down);
}
break;
+ case Messages::AlarmTriggered:
+ if (currentApp == Apps::Alarm) {
+ auto* alarm = static_cast<Screens::Alarm*>(currentScreen.get());
+ alarm->SetAlerting();
+ } else {
+ LoadApp(Apps::Alarm, DisplayApp::FullRefreshDirections::None);
+ }
case Messages::TouchEvent: {
if (state != States::Running) {
break;
@@ -340,6 +350,9 @@ void DisplayApp::LoadApp(Apps app, DisplayApp::FullRefreshDirections direction)
case Apps::Timer:
currentScreen = std::make_unique<Screens::Timer>(this, timerController);
break;
+ case Apps::Alarm:
+ currentScreen = std::make_unique<Screens::Alarm>(this, alarmController);
+ break;
// Settings
case Apps::QuickSettings:
diff --git a/src/displayapp/DisplayApp.h b/src/displayapp/DisplayApp.h
index 96951d1c..4254523a 100644
--- a/src/displayapp/DisplayApp.h
+++ b/src/displayapp/DisplayApp.h
@@ -14,7 +14,9 @@
#include "components/settings/Settings.h"
#include "displayapp/screens/Screen.h"
#include "components/timer/TimerController.h"
+#include "components/alarm/AlarmController.h"
#include "touchhandler/TouchHandler.h"
+
#include "Messages.h"
namespace Pinetime {
@@ -57,6 +59,7 @@ namespace Pinetime {
Pinetime::Controllers::MotorController& motorController,
Pinetime::Controllers::MotionController& motionController,
Pinetime::Controllers::TimerController& timerController,
+ Pinetime::Controllers::AlarmController& alarmController,
Pinetime::Controllers::TouchHandler& touchHandler);
void Start();
void PushMessage(Display::Messages msg);
@@ -82,6 +85,7 @@ namespace Pinetime {
Pinetime::Controllers::MotorController& motorController;
Pinetime::Controllers::MotionController& motionController;
Pinetime::Controllers::TimerController& timerController;
+ Pinetime::Controllers::AlarmController& alarmController;
Pinetime::Controllers::TouchHandler& touchHandler;
Pinetime::Controllers::FirmwareValidator validator;
diff --git a/src/displayapp/Messages.h b/src/displayapp/Messages.h
index 322505e6..c23cdfe3 100644
--- a/src/displayapp/Messages.h
+++ b/src/displayapp/Messages.h
@@ -15,7 +15,8 @@ namespace Pinetime {
BleFirmwareUpdateStarted,
UpdateTimeOut,
DimScreen,
- RestoreBrightness
+ RestoreBrightness,
+ AlarmTriggered
};
}
}
diff --git a/src/displayapp/screens/Alarm.cpp b/src/displayapp/screens/Alarm.cpp
new file mode 100644
index 00000000..e122cabd
--- /dev/null
+++ b/src/displayapp/screens/Alarm.cpp
@@ -0,0 +1,225 @@
+#include "Alarm.h"
+#include "Screen.h"
+#include "Symbols.h"
+
+using namespace Pinetime::Applications::Screens;
+using Pinetime::Controllers::AlarmController;
+
+static void btnEventHandler(lv_obj_t* obj, lv_event_t event) {
+ Alarm* screen = static_cast<Alarm*>(obj->user_data);
+ screen->OnButtonEvent(obj, event);
+}
+
+Alarm::Alarm(DisplayApp* app, Controllers::AlarmController& alarmController)
+ : Screen(app), running {true}, alarmController {alarmController} {
+
+ 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);
+
+ alarmHours = alarmController.Hours();
+ alarmMinutes = alarmController.Minutes();
+ lv_label_set_text_fmt(time, "%02lu:%02lu", alarmHours, alarmMinutes);
+
+ lv_obj_align(time, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, -20);
+
+ btnHoursUp = lv_btn_create(lv_scr_act(), nullptr);
+ btnHoursUp->user_data = this;
+ lv_obj_set_event_cb(btnHoursUp, btnEventHandler);
+ lv_obj_align(btnHoursUp, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 20, -80);
+ lv_obj_set_height(btnHoursUp, 40);
+ lv_obj_set_width(btnHoursUp, 60);
+ txtHrUp = lv_label_create(btnHoursUp, nullptr);
+ lv_label_set_text(txtHrUp, "+");
+
+ btnHoursDown = lv_btn_create(lv_scr_act(), nullptr);
+ btnHoursDown->user_data = this;
+ lv_obj_set_event_cb(btnHoursDown, btnEventHandler);
+ lv_obj_align(btnHoursDown, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 20, +40);
+ lv_obj_set_height(btnHoursDown, 40);
+ lv_obj_set_width(btnHoursDown, 60);
+ txtHrDown = lv_label_create(btnHoursDown, nullptr);
+ lv_label_set_text(txtHrDown, "-");
+
+ 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_RIGHT_MID, 10, -80);
+ lv_obj_set_height(btnMinutesUp, 40);
+ lv_obj_set_width(btnMinutesUp, 60);
+ txtMinUp = lv_label_create(btnMinutesUp, nullptr);
+ lv_label_set_text(txtMinUp, "+");
+
+ 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_RIGHT_MID, 10, +40);
+ lv_obj_set_height(btnMinutesDown, 40);
+ lv_obj_set_width(btnMinutesDown, 60);
+ txtMinDown = lv_label_create(btnMinutesDown, nullptr);
+ lv_label_set_text(txtMinDown, "-");
+
+ btnEnable = lv_btn_create(lv_scr_act(), nullptr);
+ btnEnable->user_data = this;
+ lv_obj_set_event_cb(btnEnable, btnEventHandler);
+ lv_obj_align(btnEnable, lv_scr_act(), LV_ALIGN_IN_BOTTOM_LEFT, 3, -10);
+ lv_obj_set_height(btnEnable, 40);
+ txtEnable = lv_label_create(btnEnable, nullptr);
+ setEnableButtonState();
+
+ btnRecur = lv_btn_create(lv_scr_act(), nullptr);
+ btnRecur->user_data = this;
+ lv_obj_set_event_cb(btnRecur, btnEventHandler);
+ lv_obj_align(btnRecur, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, -3, -10);
+ lv_obj_set_height(btnRecur, 40);
+ txtRecur = lv_label_create(btnRecur, nullptr);
+ setRecurButtonState();
+
+ btnInfo = lv_btn_create(lv_scr_act(), nullptr);
+ btnInfo->user_data = this;
+ lv_obj_set_event_cb(btnInfo, btnEventHandler);
+ lv_obj_align(btnInfo, lv_scr_act(), LV_ALIGN_CENTER, 30, -80);
+ lv_obj_set_height(btnInfo, 40);
+ lv_obj_set_width(btnInfo, 30);
+ txtInfo = lv_label_create(btnInfo, nullptr);
+ lv_label_set_text(txtInfo, "i");
+}
+
+Alarm::~Alarm() {
+ lv_obj_clean(lv_scr_act());
+}
+
+void Alarm::OnButtonEvent(lv_obj_t* obj, lv_event_t event) {
+ using Pinetime::Controllers::AlarmController;
+ if (event == LV_EVENT_CLICKED) {
+ if (obj == btnEnable) {
+ if (alarmController.State() == AlarmController::AlarmState::Alerting) {
+ alarmController.StopAlerting();
+ } else if (alarmController.State() == AlarmController::AlarmState::Set) {
+ alarmController.DisableAlarm();
+ } else {
+ alarmController.SetAlarm(alarmHours, alarmMinutes);
+ }
+ setEnableButtonState();
+ return;
+ }
+ if (obj == btnInfo) {
+ showInfo();
+ return;
+ }
+ if (obj == btnMessage) {
+ lv_obj_del(txtMessage);
+ lv_obj_del(btnMessage);
+ txtMessage = nullptr;
+ btnMessage = nullptr;
+ return;
+ }
+ // If any other button was pressed, disable the alarm
+ // this is to make it clear that the alarm won't be set until it is turned back on
+ // this avoids calling the AlarmController to change the alarm time every time the user hits minute-up or minute-down;
+ // can just do it once when the alarm is re-enabled
+ if (alarmController.State() == AlarmController::AlarmState::Set) {
+ alarmController.DisableAlarm();
+ setEnableButtonState();
+ }
+ if (obj == btnMinutesUp) {
+ if (alarmMinutes >= 59) {
+ alarmMinutes = 0;
+ } else {
+ alarmMinutes++;
+ }
+ lv_label_set_text_fmt(time, "%02d:%02d", alarmHours, alarmMinutes);
+ return;
+ }
+ if (obj == btnMinutesDown) {
+ if (alarmMinutes == 0) {
+ alarmMinutes = 59;
+ } else {
+ alarmMinutes--;
+ }
+ lv_label_set_text_fmt(time, "%02d:%02d", alarmHours, alarmMinutes);
+ return;
+ }
+ if (obj == btnHoursUp) {
+ if (alarmHours >= 23) {
+ alarmHours = 0;
+ } else {
+ alarmHours++;
+ }
+ lv_label_set_text_fmt(time, "%02d:%02d", alarmHours, alarmMinutes);
+ return;
+ }
+ if (obj == btnHoursDown) {
+ if (alarmHours == 0) {
+ alarmHours = 23;
+ } else {
+ alarmHours--;
+ }
+ lv_label_set_text_fmt(time, "%02d:%02d", alarmHours, alarmMinutes);
+ return;
+ }
+ if (obj == btnRecur) {
+ alarmController.ToggleRecurrence();
+ setRecurButtonState();
+ }
+ }
+}
+
+void Alarm::SetAlerting() {
+ setEnableButtonState();
+}
+
+void Alarm::setEnableButtonState() {
+ switch (alarmController.State()) {
+ case AlarmController::AlarmState::Set:
+ lv_label_set_text(txtEnable, "ON");
+ lv_obj_set_style_local_bg_color(btnEnable, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GREEN);
+ break;
+ case AlarmController::AlarmState::Not_Set:
+ lv_label_set_text(txtEnable, "OFF");
+ lv_obj_set_style_local_bg_color(btnEnable, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GRAY);
+ break;
+ case AlarmController::AlarmState::Alerting:
+ lv_label_set_text(txtEnable, Symbols::stop);
+ lv_obj_set_style_local_bg_color(btnEnable, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_RED);
+ }
+}
+
+void Alarm::showInfo() {
+ btnMessage = lv_btn_create(lv_scr_act(), nullptr);
+ btnMessage->user_data = this;
+ lv_obj_set_event_cb(btnMessage, btnEventHandler);
+ lv_obj_set_height(btnMessage, 200);
+ lv_obj_set_width(btnMessage, 150);
+ lv_obj_align(btnMessage, lv_scr_act(), LV_ALIGN_CENTER, 0, 0);
+ txtMessage = lv_label_create(btnMessage, nullptr);
+ lv_obj_set_style_local_bg_color(btnMessage, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_NAVY);
+
+ if (alarmController.State() == AlarmController::AlarmState::Set) {
+ auto timeToAlarm = alarmController.SecondsToAlarm();
+
+ auto daysToAlarm = timeToAlarm / 86400;
+ auto hrsToAlarm = (timeToAlarm % 86400) / 3600;
+ auto minToAlarm = (timeToAlarm % 3600) / 60;
+ auto secToAlarm = timeToAlarm % 60;
+
+ lv_label_set_text_fmt(
+ txtMessage, "Time to\nalarm:\n%2d Days\n%2d Hours\n%2d Minutes\n%2d Seconds", daysToAlarm, hrsToAlarm, minToAlarm, secToAlarm);
+ } else {
+ lv_label_set_text(txtMessage, "Alarm\nis not\nset.");
+ }
+}
+
+void Alarm::setRecurButtonState() {
+ using Pinetime::Controllers::AlarmController;
+ switch (alarmController.Recurrence()) {
+ case AlarmController::RecurType::None:
+ lv_label_set_text(txtRecur, "ONCE");
+ break;
+ case AlarmController::RecurType::Daily:
+ lv_label_set_text(txtRecur, "DAILY");
+ break;
+ case AlarmController::RecurType::Weekdays:
+ lv_label_set_text(txtRecur, "WKDAYS");
+ }
+} \ No newline at end of file
diff --git a/src/displayapp/screens/Alarm.h b/src/displayapp/screens/Alarm.h
new file mode 100644
index 00000000..30bcb73e
--- /dev/null
+++ b/src/displayapp/screens/Alarm.h
@@ -0,0 +1,31 @@
+#pragma once
+
+#include "Screen.h"
+#include "systemtask/SystemTask.h"
+#include "../LittleVgl.h"
+#include "components/alarm/AlarmController.h"
+
+namespace Pinetime::Applications::Screens {
+ class Alarm : public Screen {
+ public:
+ Alarm(DisplayApp* app, Controllers::AlarmController& alarmController);
+ ~Alarm() override;
+ void SetAlerting();
+ void OnButtonEvent(lv_obj_t* obj, lv_event_t event);
+
+ private:
+ bool running;
+ uint8_t alarmHours = 0;
+ uint8_t alarmMinutes = 0;
+ Controllers::AlarmController& alarmController;
+
+ lv_obj_t *time, *btnEnable, *txtEnable, *btnMinutesUp, *btnMinutesDown, *btnHoursUp, *btnHoursDown, *txtMinUp, *txtMinDown, *txtHrUp,
+ *txtHrDown, *btnRecur, *txtRecur, *btnMessage, *txtMessage, *btnInfo, *txtInfo;
+
+ enum class EnableButtonState { On, Off, Alerting };
+ void setEnableButtonState();
+ void setRecurButtonState();
+ void setAlarm();
+ void showInfo();
+ };
+} \ No newline at end of file
diff --git a/src/displayapp/screens/ApplicationList.cpp b/src/displayapp/screens/ApplicationList.cpp
index 6e7bbb74..5c582f60 100644
--- a/src/displayapp/screens/ApplicationList.cpp
+++ b/src/displayapp/screens/ApplicationList.cpp
@@ -58,7 +58,7 @@ std::unique_ptr<Screen> ApplicationList::CreateScreen2() {
{"2", Apps::Twos},
{Symbols::chartLine, Apps::Motion},
{Symbols::drum, Apps::Metronome},
- {"", Apps::None},
+ {Symbols::clock, Apps::Alarm},
}};
return std::make_unique<Screens::Tile>(1, 2, app, settingsController, batteryController, dateTimeController, applications);
diff --git a/src/main.cpp b/src/main.cpp
index 79e2ad86..6a7f5eb3 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -119,6 +119,7 @@ Pinetime::Drivers::WatchdogView watchdogView(watchdog);
Pinetime::Controllers::NotificationManager notificationManager;
Pinetime::Controllers::MotionController motionController;
Pinetime::Controllers::TimerController timerController;
+Pinetime::Controllers::AlarmController alarmController {dateTimeController};
Pinetime::Controllers::TouchHandler touchHandler(touchPanel, lvgl);
Pinetime::Controllers::FS fs {spiNorFlash};
@@ -139,6 +140,7 @@ Pinetime::Applications::DisplayApp displayApp(lcd,
motorController,
motionController,
timerController,
+ alarmController,
touchHandler);
Pinetime::System::SystemTask systemTask(spi,
@@ -151,6 +153,7 @@ Pinetime::System::SystemTask systemTask(spi,
bleController,
dateTimeController,
timerController,
+ alarmController,
watchdog,
notificationManager,
motorController,
diff --git a/src/systemtask/Messages.h b/src/systemtask/Messages.h
index 3a195e2d..93fcf940 100644
--- a/src/systemtask/Messages.h
+++ b/src/systemtask/Messages.h
@@ -20,7 +20,9 @@ namespace Pinetime {
EnableSleeping,
DisableSleeping,
OnNewDay,
- OnChargingEvent
+ OnChargingEvent,
+ SetOffAlarm,
+ StopRinging
};
}
}
diff --git a/src/systemtask/SystemTask.cpp b/src/systemtask/SystemTask.cpp
index 0617b0ce..98685c31 100644
--- a/src/systemtask/SystemTask.cpp
+++ b/src/systemtask/SystemTask.cpp
@@ -57,6 +57,7 @@ SystemTask::SystemTask(Drivers::SpiMaster& spi,
Controllers::Ble& bleController,
Controllers::DateTime& dateTimeController,
Controllers::TimerController& timerController,
+ Controllers::AlarmController& alarmController,
Drivers::Watchdog& watchdog,
Pinetime::Controllers::NotificationManager& notificationManager,
Pinetime::Controllers::MotorController& motorController,
@@ -79,6 +80,7 @@ SystemTask::SystemTask(Drivers::SpiMaster& spi,
bleController {bleController},
dateTimeController {dateTimeController},
timerController {timerController},
+ alarmController {alarmController},
watchdog {watchdog},
notificationManager {notificationManager},
motorController {motorController},
@@ -132,6 +134,8 @@ void SystemTask::Work() {
motionSensor.SoftReset();
timerController.Register(this);
timerController.Init();
+ alarmController.Register(this);
+ alarmController.Init();
// Reset the TWI device because the motion sensor chip most probably crashed it...
twiMaster.Sleep();
@@ -275,6 +279,16 @@ void SystemTask::Work() {
motorController.RunForDuration(35);
displayApp.PushMessage(Pinetime::Applications::Display::Messages::TimerDone);
break;
+ case Messages::SetOffAlarm:
+ if (isSleeping && !isWakingUp) {
+ GoToRunning();
+ }
+ motorController.StartRingingDisregardSettings();
+ displayApp.PushMessage(Pinetime::Applications::Display::Messages::AlarmTriggered);
+ break;
+ case Messages::StopRinging:
+ motorController.StopRinging();
+ break;
case Messages::BleConnected:
ReloadIdleTimer();
isBleDiscoveryTimerRunning = true;
diff --git a/src/systemtask/SystemTask.h b/src/systemtask/SystemTask.h
index 0266ba8a..cbd98d26 100644
--- a/src/systemtask/SystemTask.h
+++ b/src/systemtask/SystemTask.h
@@ -16,6 +16,7 @@
#include "components/ble/NotificationManager.h"
#include "components/motor/MotorController.h"
#include "components/timer/TimerController.h"
+#include "components/alarm/AlarmController.h"
#include "components/fs/FS.h"
#include "touchhandler/TouchHandler.h"
@@ -56,6 +57,7 @@ namespace Pinetime {
Controllers::Ble& bleController,
Controllers::DateTime& dateTimeController,
Controllers::TimerController& timerController,
+ Controllers::AlarmController& alarmController,
Drivers::Watchdog& watchdog,
Pinetime::Controllers::NotificationManager& notificationManager,
Pinetime::Controllers::MotorController& motorController,
@@ -100,6 +102,7 @@ namespace Pinetime {
Pinetime::Controllers::Ble& bleController;
Pinetime::Controllers::DateTime& dateTimeController;
Pinetime::Controllers::TimerController& timerController;
+ Pinetime::Controllers::AlarmController& alarmController;
QueueHandle_t systemTasksMsgQueue;
std::atomic<bool> isSleeping {false};
std::atomic<bool> isGoingToSleep {false};