diff options
Diffstat (limited to 'src/components')
-rw-r--r-- | src/components/alarm/AlarmController.cpp | 118 | ||||
-rw-r--r-- | src/components/alarm/AlarmController.h | 50 | ||||
-rw-r--r-- | src/components/motor/MotorController.cpp | 6 | ||||
-rw-r--r-- | src/components/motor/MotorController.h | 1 |
4 files changed, 175 insertions, 0 deletions
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); |