Lamp-Da 0.1
A compact lantern project
Loading...
Searching...
No Matches
indexable_behavior.hpp
Go to the documentation of this file.
1
5#ifndef INDEXABLE_BEHAVIOR_MANAGER_H
6#define INDEXABLE_BEHAVIOR_MANAGER_H
7
9
11
12//
13// note: this code is included as-is by:
14// - user/indexable_functions.h
15//
16
17#include <cstdint>
18namespace lampda::user {
19
20bool button_clicked_default(const uint8_t clicks)
21{
22 // Handle default common behavior
24 {
25 // some event is already handled
26 return true;
27 }
28
29 auto manager = get_context();
30
31 switch (clicks)
32 {
33 case 2: // 2 clicks: next mode
34 {
35 if (manager.state.isInFavoriteMockGroup)
36 {
37 // if in favorite, next favorite
38 manager.state.lastFavoriteStep += 1;
39 // sanity check, if it fails, quit favorites
40 if (not manager.jump_to_favorite(manager.state.lastFavoriteStep, false))
41 {
42 manager.exit_favorite_group(manager.state.beforeFavoriteActiveIndex);
43 }
44 }
45 else
46 {
47 if (manager.state.isLastScrollAGroupChange and manager.lamp.now - manager.state.lastScrollStopped < 2000)
48 {
49 // last action was a group change & timer did not run out yet:
50 // change group
51 manager.next_group();
52
53 // prevent further jumps
54 manager.state.isLastScrollAGroupChange = false;
55 }
56 else
57 {
58 // else: just change mode
59 manager.next_mode();
60 }
61 }
62#ifdef LMBD_SIMULATION
63 {
64 int _groupId = manager.get_active_group();
65 int _modeId = manager.get_active_mode();
66 fprintf(stderr, "group %d *mode %d\n", _groupId, _modeId);
67 if (manager.everySunsetCallback[_groupId][_modeId])
68 fprintf(stderr, " - hasSunsetAnimation\n");
69 if (manager.everyBrightCallback[_groupId][_modeId])
70 fprintf(stderr, " - hasBrightCallback\n");
71 if (manager.everyCustomRamp[_groupId][_modeId])
72 fprintf(stderr, " - hasCustomRamp\n");
73 if (manager.state.rampHandler.animEffect)
74 fprintf(stderr, " - has anim effect\n");
75 if (manager.everyRequireUserThread[_groupId][_modeId])
76 fprintf(stderr, " - requireUserThread\n");
77 if (manager.everySystemCallbacks[_groupId][_modeId])
78 fprintf(stderr, " - hasSystemCallbacks\n");
79 if (manager.everyButtonCustomUI[_groupId][_modeId])
80 fprintf(stderr, " - hasButtonCustomUI\n");
81 }
82#endif
83
84 return true;
85 }
86
87 case 3: // 3 clicks: next group or quit favorite group
88 {
89 if (manager.state.isInFavoriteMockGroup)
90 {
91 // return to previous state
92 manager.exit_favorite_group(manager.state.beforeFavoriteActiveIndex);
93 }
94 else
95 {
96 // true next group
97 manager.next_group();
98 }
99
100#ifdef LMBD_SIMULATION
101 {
102 int _groupId = manager.get_active_group();
103 int _modeId = manager.get_active_mode();
104 fprintf(stderr, "group %d *mode %d\n", _groupId, _modeId);
105 if (manager.everySunsetCallback[_groupId][_modeId])
106 fprintf(stderr, " - hasSunsetAnimation\n");
107 if (manager.everyBrightCallback[_groupId][_modeId])
108 fprintf(stderr, " - hasBrightCallback\n");
109 if (manager.everyCustomRamp[_groupId][_modeId])
110 fprintf(stderr, " - hasCustomRamp\n");
111 if (manager.state.rampHandler.animEffect)
112 fprintf(stderr, " - has anim effect\n");
113 if (manager.everyRequireUserThread[_groupId][_modeId])
114 fprintf(stderr, " - requireUserThread\n");
115 if (manager.everySystemCallbacks[_groupId][_modeId])
116 fprintf(stderr, " - hasSystemCallbacks\n");
117 if (manager.everyButtonCustomUI[_groupId][_modeId])
118 fprintf(stderr, " - hasButtonCustomUI\n");
119 }
120#endif
121 return true;
122 }
123
124 case 4: // 4 clicks: jump to favorite
125 {
126 if (not manager.state.isInFavoriteMockGroup)
127 {
128 // jump and save last used mode
129 manager.jump_to_favorite(manager.state.lastFavoriteStep, true);
130 }
131#ifdef LMBD_SIMULATION
132 {
133 int _groupId = manager.get_active_group();
134 int _modeId = manager.get_active_mode();
135 fprintf(stderr, "group %d *mode %d\n", _groupId, _modeId);
136 if (manager.everySunsetCallback[_groupId][_modeId])
137 fprintf(stderr, " - hasSunsetAnimation\n");
138 if (manager.everyBrightCallback[_groupId][_modeId])
139 fprintf(stderr, " - hasBrightCallback\n");
140 if (manager.everyCustomRamp[_groupId][_modeId])
141 fprintf(stderr, " - hasCustomRamp\n");
142 if (manager.state.rampHandler.animEffect)
143 fprintf(stderr, " - has anim effect\n");
144 if (manager.everyRequireUserThread[_groupId][_modeId])
145 fprintf(stderr, " - requireUserThread\n");
146 if (manager.everySystemCallbacks[_groupId][_modeId])
147 fprintf(stderr, " - hasSystemCallbacks\n");
148 if (manager.everyButtonCustomUI[_groupId][_modeId])
149 fprintf(stderr, " - hasButtonCustomUI\n");
150 }
151#endif
152 return true;
153 }
154 }
155
156 return false;
157}
158
159bool button_hold_default(const uint8_t clicks, const bool isEndOfHoldEvent, const uint32_t holdDuration)
160{
161 // Handle default common behavior
162 if (default_behaviors::button_hold(clicks, isEndOfHoldEvent, holdDuration))
163 {
164 // some event is already handled
165 return true;
166 }
167
168 auto manager = get_context();
169 auto& rampHandler = manager.state.rampHandler;
170
171 switch (clicks)
172 {
173 case 4: // 4 click+hold: configure favorite
174 {
175 if (not isEndOfHoldEvent)
176 {
177 // lock to prevent addition of favorite from favorite & if we are deleting favorites
178 // the second case can happen when the user delete all favorites
179 if (not manager.state.isInFavoriteMockGroup && not manager.state.isInDeleteFavorite)
180 {
181 // no new favorite in favorite
182 manager.animate_favorite_pick(holdDuration, 1500);
183 }
184 else
185 {
186 // remove current favorite
187 manager.animate_favorite_delete(holdDuration, 2000);
188 }
189 }
190 else
191 {
192 manager.state.isInDeleteFavorite = false;
193 }
194 return true;
195 }
196
197 case 6: // 6 click+hold: scroll across modes and group
198 {
199 // no scroll in favorite
200 if (not manager.state.isInFavoriteMockGroup)
201 {
202 // register end of scroll
203 if (isEndOfHoldEvent)
204 {
205 // update release time
206 manager.state.lastScrollStopped = manager.lamp.now;
207 }
208 else
209 {
210 manager.handle_scroll_modes(holdDuration);
211 }
212 }
213 return true;
214 }
215
216 default:
217 break;
218 }
219 return false;
220}
221
222namespace __private {
223
229void handle_pattern_select_command(const uint8_t patternIndex, const uint32_t requestedColor = 0)
230{
231 // ignore if not on
233 return;
234
235 // get manager and execute a mode or group change
236 auto manager = get_context();
237 if (manager.get_hidden_groups_count() <= 0)
238 {
239 bsp::lampda_print("Cannot use bluetooth control without an hidden bluetooth group");
240 return;
241 }
242
243 const auto bluetoothGroup = manager.template get_group_id_of_mode<modes::bluetooth::ColorControlMode>();
244 if (bluetoothGroup < 0)
245 {
246 bsp::lampda_print("Cannot find the bluetooth group and modes");
247 return;
248 }
249
250 const auto availableModes = manager.get_modes_count();
251 if (availableModes <= patternIndex)
252 {
253 bsp::lampda_print("Unimplemented pattern id %d", patternIndex);
254 return;
255 }
256
257 manager.exit_favorite_group(manager.state.beforeFavoriteActiveIndex);
258 manager.set_active_group(bluetoothGroup);
259 manager.set_active_mode(patternIndex);
260
261 // sanity check
262 const int trueIndex = manager.template get_mode_id<modes::bluetooth::ColorControlMode>();
263 assert(trueIndex == 0 && "Bluetooth group should have the programmable color output as the first group index");
264
265 // handle special programmable group mode
266 if (patternIndex == 0)
267 {
268 auto& modeState = manager.template get_state_of_mode<modes::bluetooth::ColorControlMode>();
269
270 // Convert color to compressed color
271 const uint16_t compressedColor = modes::colors::get_compressed_16b_color(requestedColor);
272 const uint8_t ramp = (compressedColor >> 8) & 0xFF;
273 const uint8_t index = compressedColor & 0xFF;
274 manager.set_active_custom_ramp(ramp);
275 manager.set_active_custom_index(index);
276 }
277}
278
283void handle_go_to_favorite_command(const uint8_t favoriteIndex)
284{
285 // ignore if not on
287 return;
288
289 auto manager = get_context();
290 if (favoriteIndex >= manager.state.usedFavoriteCount)
291 {
292 bsp::lampda_print("Cannot jump to favorite %d, max index should be less than %d",
293 favoriteIndex,
294 manager.state.usedFavoriteCount);
295 return;
296 }
297 // jump and save last used mode
298 manager.jump_to_favorite(favoriteIndex, true);
299}
300
305void handle_set_favorite_command(const uint8_t favoriteIndex)
306{
307 // ignore if not on
309 return;
310
311 auto manager = get_context();
312
313 // Cannot add a favorite mode to te favorite group: we are already here
314 if (manager.state.isInFavoriteMockGroup)
315 return;
316
317 const uint8_t allowedFavorites = manager.get_number_of_allowed_favorites();
318
319 // not enought favorite set
320 if (favoriteIndex >= allowedFavorites)
321 {
322 bsp::lampda_print("Max favorites is [0; %d[, cannot add index %d", allowedFavorites, favoriteIndex);
323 return;
324 }
325
326 // Set the favorite !
327 manager.set_current_mode_as_favorite(favoriteIndex, 1000);
328}
329
330} // namespace __private
331
333{
334 // Handle default common behavior
335 if (default_behaviors::handle_user_command(command))
336 {
337 // some event is already handled
338 return;
339 }
340
341 switch (command.get_type())
342 {
344 {
345 uint32_t color;
347 __private::handle_pattern_select_command(0, color);
348 else
349 bsp::lampda_print("Failed to parse set_ble_custom_color command");
350 return;
351 }
353 {
354 uint8_t index;
355 if (command.parse_set_ble_mode_command(index))
356 __private::handle_pattern_select_command(index);
357 else
358 bsp::lampda_print("Failed to parse set_ble_mode command");
359 return;
360 }
362 {
363 uint8_t index;
364 if (command.parse_go_to_favorite_command(index))
365 __private::handle_go_to_favorite_command(index);
366 else
367 bsp::lampda_print("Failed to parse go_to_favorite command");
368 return;
369 }
371 {
372 uint8_t index;
373 if (command.parse_set_favorite_command(index))
374 __private::handle_set_favorite_command(index);
375 else
376 bsp::lampda_print("Failed to parse set_favorite command");
377 return;
378 }
379 default:
380 break;
381 }
382
383 bsp::lampda_print("Unsupported user command message type");
384}
385
386} // namespace lampda::user
387
388#endif
Define assertions helpers.
Define a command destined to the user layer. Command can only be created by the static make_* methods...
Definition: user_commands.h:21
bool parse_set_favorite_command(uint8_t &index) const
Parse the current command for a set favorite.
Definition: user_commands.cpp:214
bool parse_set_ble_mode_command(uint8_t &index) const
Parse the current command for a set current mode to BLE mode.
Definition: user_commands.cpp:198
bool parse_go_to_favorite_command(uint8_t &index) const
Parse the current command for a go to favorite.
Definition: user_commands.cpp:206
@ SetBleMode
switch to a target BLE mode
@ SetBleCustomColorMode
switch to BLE custom color mode
@ SetFavoriteIndex
Set the current mode to the target favorite index.
@ GoToFavoriteIndex
Go to the target favorite index.
bool parse_set_ble_custom_color_mode_command(uint32_t &color) const
Parse the current command for a set current mode to BLE custom color.
Definition: user_commands.cpp:189
Manipulate color representations.
void handle_set_favorite_command(const uint8_t favoriteIndex)
Set the current mode to favorite.
Definition: indexable_behavior.hpp:305
void handle_go_to_favorite_command(const uint8_t favoriteIndex)
Go to the given favorite index if possible.
Definition: indexable_behavior.hpp:283
void handle_pattern_select_command(const uint8_t patternIndex, const uint32_t requestedColor=0)
Handle a pattern change command.
Definition: indexable_behavior.hpp:229
void lampda_print(const char *format,...)
C linkage to print functions.
Definition: text_out.cpp:227
bool is_in_output_state()
return true if the system is in output mode
Definition: behavior.cpp:139
bool button_hold(const uint8_t clicks, const bool isEndOfHoldEvent, const uint32_t holdDuration)
must be called by the lampda::user::button_hold_default
Definition: default_behavior.hpp:247
bool button_clicked(const uint8_t clicks)
must be called by the lampda::user::button_clicked_default
Definition: default_behavior.hpp:219
Contains code handling custom user mode functions for indexable strips.
Definition: default_behavior.hpp:18
bool button_clicked_default(const uint8_t)
Called to handle button click events for default user mode behaviors.
Definition: indexable_behavior.hpp:20
bool button_hold_default(const uint8_t, const bool, const uint32_t)
Called to handle button click+hold events for user mode behaviors.
Definition: indexable_behavior.hpp:159
void handle_user_command(const common::UserCommand &command)
Handle user command.
Definition: indexable_behavior.hpp:332