scene_timer_running.c - timed-remote - Flipper Zero app for sending delayed IR commands
HTML git clone git://src.adamsgaard.dk/timed-remote
DIR Log
DIR Files
DIR Refs
DIR README
DIR LICENSE
---
scene_timer_running.c (3424B)
---
1 #include <stdio.h>
2
3 #include "../helpers/ir_helper.h"
4 #include "../helpers/time_helper.h"
5 #include "../timed_remote.h"
6 #include "timed_remote_scene.h"
7
8 static uint32_t countdown_seconds(const TimedRemoteApp *);
9 static void render_timer(TimedRemoteApp *);
10
11 #define REPEAT_UNLIMITED 255U
12
13 static void
14 on_timer_tick(void *context)
15 {
16 TimedRemoteApp *app;
17
18 app = context;
19 view_dispatcher_send_custom_event(app->vd, EVENT_TIMER_TICK);
20 }
21
22 static uint32_t
23 countdown_seconds(const TimedRemoteApp *app)
24 {
25 return time_hms_sec(app->h, app->m, app->s);
26 }
27
28 static void
29 render_timer(TimedRemoteApp *app)
30 {
31 char timer[16];
32 uint8_t h;
33 uint8_t m;
34 uint8_t s;
35
36 time_sec_hms(app->left, &h, &m, &s);
37 snprintf(timer, sizeof(timer), "%02d:%02d:%02d", h, m, s);
38
39 widget_reset(app->widget);
40 widget_add_string_element(
41 app->widget,
42 64,
43 5,
44 AlignCenter,
45 AlignTop,
46 FontSecondary,
47 app->sig);
48 widget_add_string_element(
49 app->widget,
50 64,
51 25,
52 AlignCenter,
53 AlignTop,
54 FontBigNumbers,
55 timer);
56
57 if (app->repeat > 0 && app->repeat < REPEAT_UNLIMITED) {
58 char repeat[24];
59
60 snprintf(
61 repeat,
62 sizeof(repeat),
63 "Repeat: %d/%d",
64 app->repeat - app->repeat_left + 1,
65 app->repeat);
66 widget_add_string_element(
67 app->widget,
68 64,
69 52,
70 AlignCenter,
71 AlignTop,
72 FontSecondary,
73 repeat);
74 } else if (app->repeat == REPEAT_UNLIMITED) {
75 widget_add_string_element(
76 app->widget,
77 64,
78 52,
79 AlignCenter,
80 AlignTop,
81 FontSecondary,
82 "Repeat: Unlimited");
83 }
84 }
85
86 void
87 scene_run_enter(void *context)
88 {
89 TimedRemoteApp *app;
90
91 app = context;
92 if (app->mode == MODE_COUNTDOWN) {
93 app->left = countdown_seconds(app);
94 } else {
95 app->left = time_until(app->h, app->m, app->s);
96 if (app->left == 0) {
97 view_dispatcher_send_custom_event(app->vd, EVENT_FIRE_SIGNAL);
98 return;
99 }
100 }
101
102 if (app->repeat == 0)
103 app->repeat_left = 1;
104
105 render_timer(app);
106 view_dispatcher_switch_to_view(app->vd, VIEW_RUN);
107
108 app->timer = furi_timer_alloc(on_timer_tick, FuriTimerTypePeriodic, app);
109 if (app->timer == NULL)
110 return;
111
112 furi_timer_start(app->timer, furi_kernel_get_tick_frequency());
113 }
114
115 bool
116 scene_run_event(void *context, SceneManagerEvent event)
117 {
118 TimedRemoteApp *app;
119
120 app = context;
121 if (event.type == SceneManagerEventTypeBack) {
122 scene_manager_search_and_switch_to_previous_scene(
123 app->sm,
124 SCENE_BROWSE);
125 return true;
126 }
127 if (event.type != SceneManagerEventTypeCustom)
128 return false;
129
130 if (event.event == EVENT_TIMER_TICK) {
131 if (app->left > 0) {
132 app->left--;
133 render_timer(app);
134 }
135 if (app->left == 0)
136 view_dispatcher_send_custom_event(app->vd, EVENT_FIRE_SIGNAL);
137 return true;
138 }
139 if (event.event != EVENT_FIRE_SIGNAL)
140 return false;
141
142 if (app->ir != NULL)
143 ir_tx(app->ir);
144
145 if (app->repeat == REPEAT_UNLIMITED) {
146 app->left = countdown_seconds(app);
147 render_timer(app);
148 return true;
149 }
150
151 if (app->repeat_left > 0)
152 app->repeat_left--;
153
154 if (app->repeat != 0 && app->repeat_left > 0) {
155 app->left = countdown_seconds(app);
156 render_timer(app);
157 return true;
158 }
159
160 scene_manager_next_scene(app->sm, SCENE_DONE);
161 return true;
162 }
163
164 void
165 scene_run_exit(void *context)
166 {
167 TimedRemoteApp *app;
168
169 app = context;
170 if (app->timer != NULL) {
171 furi_timer_stop(app->timer);
172 furi_timer_free(app->timer);
173 app->timer = NULL;
174 }
175 widget_reset(app->widget);
176 }