scene_timer_config.c (5444B)
1 #include <stdio.h> 2 3 #include "../timed_remote.h" 4 #include "timed_remote_scene.h" 5 6 enum 7 { 8 ITEM_MODE, 9 ITEM_HOURS, 10 ITEM_MINUTES, 11 ITEM_SECONDS, 12 ITEM_REPEAT, 13 ITEM_START, 14 }; 15 16 #define REPEAT_OFF 0U 17 #define REPEAT_UNLIMITED 255U 18 19 static void add_time_item(VariableItemList *, const char *, uint8_t, uint8_t, 20 VariableItemChangeCallback, TimedRemoteApp *); 21 static void build_items(TimedRemoteApp *); 22 static uint8_t index_from_repeat(uint8_t); 23 static void set_repeat_text(VariableItem *, uint8_t); 24 static uint8_t repeat_from_index(uint8_t); 25 static void set_two_digits(VariableItem *, uint8_t); 26 static uint32_t start_item_index(const TimedRemoteApp *); 27 28 static void 29 set_two_digits(VariableItem *item, uint8_t value) 30 { 31 char text[4]; 32 33 snprintf(text, sizeof(text), "%02d", value); 34 variable_item_set_current_value_text(item, text); 35 } 36 37 static uint8_t 38 repeat_from_index(uint8_t index) 39 { 40 if (index == 0) 41 return REPEAT_OFF; 42 if (index == 1) 43 return REPEAT_UNLIMITED; 44 return index - 1; 45 } 46 47 static uint8_t 48 index_from_repeat(uint8_t repeat) 49 { 50 if (repeat == REPEAT_OFF) 51 return 0; 52 if (repeat == REPEAT_UNLIMITED) 53 return 1; 54 return repeat + 1; 55 } 56 57 static void 58 set_repeat_text(VariableItem *item, uint8_t repeat) 59 { 60 char text[16]; 61 62 if (repeat == REPEAT_OFF) { 63 variable_item_set_current_value_text(item, "Off"); 64 return; 65 } 66 if (repeat == REPEAT_UNLIMITED) { 67 variable_item_set_current_value_text(item, "Unlimited"); 68 return; 69 } 70 71 snprintf(text, sizeof(text), "%u", repeat); 72 variable_item_set_current_value_text(item, text); 73 } 74 75 static uint32_t 76 start_item_index(const TimedRemoteApp *app) 77 { 78 if (app->mode == MODE_COUNTDOWN) 79 return ITEM_START; 80 return ITEM_REPEAT; 81 } 82 83 static void 84 on_mode_change(VariableItem *item) 85 { 86 TimedRemoteApp *app; 87 uint8_t mode_index; 88 89 app = variable_item_get_context(item); 90 mode_index = variable_item_get_current_value_index(item); 91 app->mode = mode_index == 0 ? MODE_COUNTDOWN : MODE_SCHEDULED; 92 variable_item_set_current_value_text( 93 item, 94 app->mode == MODE_COUNTDOWN ? "Countdown" : "Scheduled"); 95 if (app->mode == MODE_SCHEDULED) 96 app->repeat = REPEAT_OFF; 97 98 view_dispatcher_send_custom_event(app->vd, EVENT_MODE_CHANGED); 99 } 100 101 static void 102 on_hours_change(VariableItem *item) 103 { 104 TimedRemoteApp *app; 105 106 app = variable_item_get_context(item); 107 app->h = variable_item_get_current_value_index(item); 108 set_two_digits(item, app->h); 109 } 110 111 static void 112 on_minutes_change(VariableItem *item) 113 { 114 TimedRemoteApp *app; 115 116 app = variable_item_get_context(item); 117 app->m = variable_item_get_current_value_index(item); 118 set_two_digits(item, app->m); 119 } 120 121 static void 122 on_seconds_change(VariableItem *item) 123 { 124 TimedRemoteApp *app; 125 126 app = variable_item_get_context(item); 127 app->s = variable_item_get_current_value_index(item); 128 set_two_digits(item, app->s); 129 } 130 131 static void 132 on_repeat_change(VariableItem *item) 133 { 134 TimedRemoteApp *app; 135 136 app = variable_item_get_context(item); 137 app->repeat = repeat_from_index(variable_item_get_current_value_index(item)); 138 set_repeat_text(item, app->repeat); 139 } 140 141 static void 142 on_enter(void *context, uint32_t index) 143 { 144 TimedRemoteApp *app; 145 146 app = context; 147 if (index != start_item_index(app)) 148 return; 149 150 view_dispatcher_send_custom_event(app->vd, EVENT_TIMER_CONFIGURED); 151 } 152 153 static void 154 add_time_item(VariableItemList *list, 155 const char *name, 156 uint8_t value_count, 157 uint8_t value, 158 VariableItemChangeCallback callback, 159 TimedRemoteApp *app) 160 { 161 VariableItem *item; 162 163 item = variable_item_list_add(list, name, value_count, callback, app); 164 variable_item_set_current_value_index(item, value); 165 set_two_digits(item, value); 166 } 167 168 static void 169 build_items(TimedRemoteApp *app) 170 { 171 VariableItem *item; 172 173 variable_item_list_reset(app->vlist); 174 175 item = variable_item_list_add(app->vlist, "Mode", 2, on_mode_change, app); 176 variable_item_set_current_value_index( 177 item, 178 app->mode == MODE_COUNTDOWN ? 0 : 1); 179 variable_item_set_current_value_text( 180 item, 181 app->mode == MODE_COUNTDOWN ? "Countdown" : "Scheduled"); 182 183 add_time_item(app->vlist, "Hours", 24, app->h, on_hours_change, app); 184 add_time_item(app->vlist, "Minutes", 60, app->m, on_minutes_change, app); 185 add_time_item(app->vlist, "Seconds", 60, app->s, on_seconds_change, app); 186 187 if (app->mode == MODE_COUNTDOWN) { 188 item = variable_item_list_add( 189 app->vlist, 190 "Repeat", 191 101, 192 on_repeat_change, 193 app); 194 variable_item_set_current_value_index(item, index_from_repeat(app->repeat)); 195 set_repeat_text(item, app->repeat); 196 } 197 198 variable_item_list_add(app->vlist, ">> Start Timer <<", 0, NULL, NULL); 199 variable_item_list_set_enter_callback(app->vlist, on_enter, app); 200 } 201 202 void 203 scene_cfg_enter(void *context) 204 { 205 TimedRemoteApp *app; 206 207 app = context; 208 build_items(app); 209 view_dispatcher_switch_to_view(app->vd, VIEW_LIST); 210 } 211 212 bool 213 scene_cfg_event(void *context, SceneManagerEvent event) 214 { 215 TimedRemoteApp *app; 216 217 app = context; 218 if (event.type != SceneManagerEventTypeCustom) 219 return false; 220 221 if (event.event == EVENT_MODE_CHANGED) { 222 build_items(app); 223 return true; 224 } 225 if (event.event != EVENT_TIMER_CONFIGURED) 226 return false; 227 228 if (app->repeat == REPEAT_OFF) 229 app->repeat_left = 1; 230 else if (app->repeat == REPEAT_UNLIMITED) 231 app->repeat_left = REPEAT_UNLIMITED; 232 else 233 app->repeat_left = app->repeat + 1; 234 235 scene_manager_next_scene(app->sm, SCENE_RUN); 236 return true; 237 } 238 239 void 240 scene_cfg_exit(void *context) 241 { 242 TimedRemoteApp *app; 243 244 app = context; 245 variable_item_list_reset(app->vlist); 246 }