@@ -17,7 +17,8 @@ static void btnEventHandler(lv_obj_t* obj, lv_event_t event) {
1717 }
1818}
1919
20- Timer::Timer (Controllers::Timer& timerController) : timer {timerController} {
20+ Timer::Timer (Controllers::Timer& timerController, Controllers::MotorController& motorController, System::SystemTask& systemTask)
21+ : timer {timerController}, motorController {motorController}, wakeLock(systemTask) {
2122
2223 lv_obj_t * colonLabel = lv_label_create (lv_scr_act (), nullptr );
2324 lv_obj_set_style_local_text_font (colonLabel, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_76);
@@ -62,7 +63,11 @@ Timer::Timer(Controllers::Timer& timerController) : timer {timerController} {
6263 // Create the label as a child of the button so it stays centered by default
6364 txtPlayPause = lv_label_create (btnPlayPause, nullptr );
6465
65- if (timer.IsRunning ()) {
66+ auto timerStatus = timer.GetTimerState ();
67+
68+ if (timerStatus && timerStatus->expired ) {
69+ SetTimerRinging ();
70+ } else if (timer.IsRunning ()) {
6671 SetTimerRunning ();
6772 } else {
6873 SetTimerStopped ();
@@ -73,6 +78,14 @@ Timer::Timer(Controllers::Timer& timerController) : timer {timerController} {
7378
7479Timer::~Timer () {
7580 lv_task_del (taskRefresh);
81+
82+ // If timer has expired, reset it when leaving the screen
83+ auto timerStatus = timer.GetTimerState ();
84+ if (timerStatus && timerStatus->expired ) {
85+ motorController.StopRinging ();
86+ timer.ResetExpiredTime ();
87+ }
88+
7689 lv_obj_clean (lv_scr_act ());
7790}
7891
@@ -103,7 +116,23 @@ void Timer::UpdateMask() {
103116}
104117
105118void Timer::Refresh () {
106- if (timer.IsRunning ()) {
119+ auto timerStatus = timer.GetTimerState ();
120+
121+ if (timerStatus && timerStatus->expired ) {
122+ // Timer exists and has expired, so we're in ringing mode
123+ DisplayTime ();
124+
125+ if (timerStatus->distanceToExpiry .count () > 10000 && motorController.IsRinging ()) {
126+ // Stop buzzing after 10 seconds, but continue the counter
127+ motorController.StopRinging ();
128+ wakeLock.Release ();
129+ }
130+
131+ // Reset timer after 1 minute
132+ if (timerStatus->distanceToExpiry .count () > 60000 ) {
133+ Reset ();
134+ }
135+ } else if (timer.IsRunning ()) {
107136 DisplayTime ();
108137 } else if (buttonPressing && xTaskGetTickCount () - pressTime > pdMS_TO_TICKS (150 )) {
109138 lv_label_set_text_static (txtPlayPause, " Reset" );
@@ -130,16 +159,31 @@ void Timer::SetTimerRunning() {
130159 minuteCounter.HideControls ();
131160 secondCounter.HideControls ();
132161 lv_label_set_text_static (txtPlayPause, " Pause" );
162+ lv_obj_set_style_local_bg_color (btnPlayPause, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgAlt);
133163}
134164
135165void Timer::SetTimerStopped () {
136166 minuteCounter.ShowControls ();
137167 secondCounter.ShowControls ();
138168 lv_label_set_text_static (txtPlayPause, " Start" );
169+ lv_obj_set_style_local_bg_color (btnPlayPause, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GREEN);
170+ }
171+
172+ void Timer::SetTimerRinging () {
173+ motorController.StartRinging ();
174+ wakeLock.Lock ();
175+ minuteCounter.HideControls ();
176+ secondCounter.HideControls ();
177+ lv_label_set_text_static (txtPlayPause, " Reset" );
178+ lv_obj_set_style_local_bg_color (btnPlayPause, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_RED);
139179}
140180
141181void Timer::ToggleRunning () {
142- if (timer.IsRunning ()) {
182+ auto timerStatus = timer.GetTimerState ();
183+ if (timerStatus && timerStatus->expired ) {
184+ motorController.StopRinging ();
185+ Reset ();
186+ } else if (timer.IsRunning ()) {
143187 DisplayTime ();
144188 timer.StopTimer ();
145189 SetTimerStopped ();
@@ -152,6 +196,7 @@ void Timer::ToggleRunning() {
152196}
153197
154198void Timer::Reset () {
199+ timer.ResetExpiredTime ();
155200 DisplayTime ();
156201 SetTimerStopped ();
157202}
0 commit comments