diff options
-rw-r--r-- | keyboards/ergodox/infinity/config.h | 2 | ||||
-rw-r--r-- | keyboards/ergodox/infinity/infinity.c | 22 | ||||
-rw-r--r-- | keyboards/ergodox/infinity/infinity.h | 71 | ||||
-rw-r--r-- | keyboards/ergodox/infinity/visualizer.c | 175 | ||||
-rw-r--r-- | quantum/visualizer/visualizer.c | 25 | ||||
-rw-r--r-- | quantum/visualizer/visualizer.h | 8 |
6 files changed, 258 insertions, 45 deletions
diff --git a/keyboards/ergodox/infinity/config.h b/keyboards/ergodox/infinity/config.h index 9e264083b..6cde193e1 100644 --- a/keyboards/ergodox/infinity/config.h +++ b/keyboards/ergodox/infinity/config.h | |||
@@ -54,6 +54,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
54 | // The visualizer needs gfx thread priorities | 54 | // The visualizer needs gfx thread priorities |
55 | #define VISUALIZER_THREAD_PRIORITY (NORMAL_PRIORITY - 2) | 55 | #define VISUALIZER_THREAD_PRIORITY (NORMAL_PRIORITY - 2) |
56 | 56 | ||
57 | #define VISUALIZER_USER_DATA_SIZE 16 | ||
58 | |||
57 | /* | 59 | /* |
58 | * Feature disable options | 60 | * Feature disable options |
59 | * These options are also useful to firmware size reduction. | 61 | * These options are also useful to firmware size reduction. |
diff --git a/keyboards/ergodox/infinity/infinity.c b/keyboards/ergodox/infinity/infinity.c index ecc072abb..62259ed3f 100644 --- a/keyboards/ergodox/infinity/infinity.c +++ b/keyboards/ergodox/infinity/infinity.c | |||
@@ -126,34 +126,48 @@ void matrix_scan_kb(void) { | |||
126 | matrix_scan_user(); | 126 | matrix_scan_user(); |
127 | } | 127 | } |
128 | 128 | ||
129 | __attribute__ ((weak)) | ||
129 | void ergodox_board_led_on(void){ | 130 | void ergodox_board_led_on(void){ |
130 | } | 131 | } |
131 | 132 | ||
133 | __attribute__ ((weak)) | ||
132 | void ergodox_right_led_1_on(void){ | 134 | void ergodox_right_led_1_on(void){ |
133 | } | 135 | } |
134 | 136 | ||
137 | __attribute__ ((weak)) | ||
135 | void ergodox_right_led_2_on(void){ | 138 | void ergodox_right_led_2_on(void){ |
136 | } | 139 | } |
137 | 140 | ||
141 | __attribute__ ((weak)) | ||
138 | void ergodox_right_led_3_on(void){ | 142 | void ergodox_right_led_3_on(void){ |
139 | } | 143 | } |
140 | 144 | ||
141 | void ergodox_right_led_on(uint8_t led){ | 145 | __attribute__ ((weak)) |
142 | } | ||
143 | |||
144 | void ergodox_board_led_off(void){ | 146 | void ergodox_board_led_off(void){ |
145 | } | 147 | } |
146 | 148 | ||
149 | __attribute__ ((weak)) | ||
147 | void ergodox_right_led_1_off(void){ | 150 | void ergodox_right_led_1_off(void){ |
148 | } | 151 | } |
149 | 152 | ||
153 | __attribute__ ((weak)) | ||
150 | void ergodox_right_led_2_off(void){ | 154 | void ergodox_right_led_2_off(void){ |
151 | } | 155 | } |
152 | 156 | ||
157 | __attribute__ ((weak)) | ||
153 | void ergodox_right_led_3_off(void){ | 158 | void ergodox_right_led_3_off(void){ |
154 | } | 159 | } |
155 | 160 | ||
156 | void ergodox_right_led_off(uint8_t led){ | 161 | __attribute__ ((weak)) |
162 | void ergodox_right_led_1_set(uint8_t n) { | ||
163 | } | ||
164 | |||
165 | __attribute__ ((weak)) | ||
166 | void ergodox_right_led_2_set(uint8_t n) { | ||
167 | } | ||
168 | |||
169 | __attribute__ ((weak)) | ||
170 | void ergodox_right_led_3_set(uint8_t n) { | ||
157 | } | 171 | } |
158 | 172 | ||
159 | #ifdef ONEHAND_ENABLE | 173 | #ifdef ONEHAND_ENABLE |
diff --git a/keyboards/ergodox/infinity/infinity.h b/keyboards/ergodox/infinity/infinity.h index fec9e565c..73a0f4bf7 100644 --- a/keyboards/ergodox/infinity/infinity.h +++ b/keyboards/ergodox/infinity/infinity.h | |||
@@ -7,13 +7,38 @@ void ergodox_board_led_on(void); | |||
7 | void ergodox_right_led_1_on(void); | 7 | void ergodox_right_led_1_on(void); |
8 | void ergodox_right_led_2_on(void); | 8 | void ergodox_right_led_2_on(void); |
9 | void ergodox_right_led_3_on(void); | 9 | void ergodox_right_led_3_on(void); |
10 | void ergodox_right_led_on(uint8_t led); | 10 | |
11 | inline void ergodox_right_led_on(uint8_t led) { | ||
12 | switch (led) { | ||
13 | case 0: | ||
14 | ergodox_right_led_1_on(); | ||
15 | break; | ||
16 | case 1: | ||
17 | ergodox_right_led_2_on(); | ||
18 | break; | ||
19 | case 2: | ||
20 | ergodox_right_led_3_on(); | ||
21 | break; | ||
22 | } | ||
23 | } | ||
11 | 24 | ||
12 | void ergodox_board_led_off(void); | 25 | void ergodox_board_led_off(void); |
13 | void ergodox_right_led_1_off(void); | 26 | void ergodox_right_led_1_off(void); |
14 | void ergodox_right_led_2_off(void); | 27 | void ergodox_right_led_2_off(void); |
15 | void ergodox_right_led_3_off(void); | 28 | void ergodox_right_led_3_off(void); |
16 | void ergodox_right_led_off(uint8_t led); | 29 | inline void ergodox_right_led_off(uint8_t led) { |
30 | switch (led) { | ||
31 | case 0: | ||
32 | ergodox_right_led_1_off(); | ||
33 | break; | ||
34 | case 1: | ||
35 | ergodox_right_led_2_off(); | ||
36 | break; | ||
37 | case 2: | ||
38 | ergodox_right_led_3_off(); | ||
39 | break; | ||
40 | } | ||
41 | } | ||
17 | 42 | ||
18 | inline void ergodox_led_all_on(void) | 43 | inline void ergodox_led_all_on(void) |
19 | { | 44 | { |
@@ -31,36 +56,22 @@ inline void ergodox_led_all_off(void) | |||
31 | ergodox_right_led_3_off(); | 56 | ergodox_right_led_3_off(); |
32 | } | 57 | } |
33 | 58 | ||
34 | inline void ergodox_right_led_1_set(uint8_t n){ | 59 | void ergodox_right_led_1_set(uint8_t n); |
35 | if (n) { | 60 | void ergodox_right_led_2_set(uint8_t n); |
36 | ergodox_right_led_1_on(); | 61 | void ergodox_right_led_3_set(uint8_t n); |
37 | } else { | ||
38 | ergodox_right_led_1_off(); | ||
39 | } | ||
40 | } | ||
41 | |||
42 | inline void ergodox_right_led_2_set(uint8_t n){ | ||
43 | if (n) { | ||
44 | ergodox_right_led_2_on(); | ||
45 | } else { | ||
46 | ergodox_right_led_2_off(); | ||
47 | } | ||
48 | } | ||
49 | |||
50 | inline void ergodox_right_led_3_set(uint8_t n){ | ||
51 | if (n) { | ||
52 | ergodox_right_led_3_on(); | ||
53 | } else { | ||
54 | ergodox_right_led_3_off(); | ||
55 | } | ||
56 | } | ||
57 | 62 | ||
58 | inline void ergodox_right_led_set(uint8_t led, uint8_t n){ | 63 | inline void ergodox_right_led_set(uint8_t led, uint8_t n){ |
59 | if (n) { | 64 | switch (led) { |
60 | ergodox_right_led_on(led); | 65 | case 0: |
61 | } else { | 66 | ergodox_right_led_1_set(n); |
62 | ergodox_right_led_off(led); | 67 | break; |
63 | } | 68 | case 1: |
69 | ergodox_right_led_2_set(n); | ||
70 | break; | ||
71 | case 2: | ||
72 | ergodox_right_led_3_set(n); | ||
73 | break; | ||
74 | } | ||
64 | } | 75 | } |
65 | 76 | ||
66 | inline void ergodox_led_all_set(uint8_t n) { | 77 | inline void ergodox_led_all_set(uint8_t n) { |
diff --git a/keyboards/ergodox/infinity/visualizer.c b/keyboards/ergodox/infinity/visualizer.c index 6af3a72ee..7bc42fbc7 100644 --- a/keyboards/ergodox/infinity/visualizer.c +++ b/keyboards/ergodox/infinity/visualizer.c | |||
@@ -27,6 +27,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
27 | #endif | 27 | #endif |
28 | 28 | ||
29 | #include "visualizer.h" | 29 | #include "visualizer.h" |
30 | #include "system/serial_link.h" | ||
30 | 31 | ||
31 | // To generate an image array like this | 32 | // To generate an image array like this |
32 | // Ensure the image is 128 x 32 or smaller | 33 | // Ensure the image is 128 x 32 or smaller |
@@ -73,6 +74,15 @@ static const uint8_t image_data_lcd_logo[512] = { | |||
73 | static const uint32_t logo_background_color = LCD_COLOR(0x00, 0x00, 0xFF); | 74 | static const uint32_t logo_background_color = LCD_COLOR(0x00, 0x00, 0xFF); |
74 | static const uint32_t initial_color = LCD_COLOR(0, 0, 0); | 75 | static const uint32_t initial_color = LCD_COLOR(0, 0, 0); |
75 | 76 | ||
77 | static const uint32_t led_emulation_colors[4] = { | ||
78 | LCD_COLOR(0, 0, 0), | ||
79 | LCD_COLOR(255, 255, 255), | ||
80 | LCD_COLOR(84, 255, 255), | ||
81 | LCD_COLOR(168, 255, 255), | ||
82 | }; | ||
83 | |||
84 | static uint32_t next_led_target_color = 0; | ||
85 | |||
76 | typedef enum { | 86 | typedef enum { |
77 | LCD_STATE_INITIAL, | 87 | LCD_STATE_INITIAL, |
78 | LCD_STATE_LAYER_BITMAP, | 88 | LCD_STATE_LAYER_BITMAP, |
@@ -81,6 +91,19 @@ typedef enum { | |||
81 | 91 | ||
82 | static lcd_state_t lcd_state = LCD_STATE_INITIAL; | 92 | static lcd_state_t lcd_state = LCD_STATE_INITIAL; |
83 | 93 | ||
94 | typedef struct { | ||
95 | uint8_t led_on; | ||
96 | uint8_t led1; | ||
97 | uint8_t led2; | ||
98 | uint8_t led3; | ||
99 | } visualizer_user_data_t; | ||
100 | |||
101 | // Don't access from visualization function, use the visualizer state instead | ||
102 | static visualizer_user_data_t user_data_keyboard = {}; | ||
103 | |||
104 | _Static_assert(sizeof(visualizer_user_data_t) <= VISUALIZER_USER_DATA_SIZE, | ||
105 | "Please increase the VISUALIZER_USER_DATA_SIZE"); | ||
106 | |||
84 | bool display_logo(keyframe_animation_t* animation, visualizer_state_t* state) { | 107 | bool display_logo(keyframe_animation_t* animation, visualizer_state_t* state) { |
85 | (void)state; | 108 | (void)state; |
86 | (void)animation; | 109 | (void)animation; |
@@ -117,16 +140,27 @@ static keyframe_animation_t startup_animation = { | |||
117 | }; | 140 | }; |
118 | 141 | ||
119 | // The color animation animates the LCD color when you change layers | 142 | // The color animation animates the LCD color when you change layers |
120 | static keyframe_animation_t color_animation = { | 143 | static keyframe_animation_t one_led_color = { |
121 | .num_frames = 2, | 144 | .num_frames = 1, |
122 | .loop = false, | 145 | .loop = false, |
123 | // Note that there's a 200 ms no-operation frame, | 146 | .frame_lengths = {gfxMillisecondsToTicks(0)}, |
124 | // this prevents the color from changing when activating the layer | 147 | .frame_functions = {keyframe_set_backlight_color}, |
125 | // momentarily | ||
126 | .frame_lengths = {gfxMillisecondsToTicks(200), gfxMillisecondsToTicks(500)}, | ||
127 | .frame_functions = {keyframe_no_operation, keyframe_animate_backlight_color}, | ||
128 | }; | 148 | }; |
129 | 149 | ||
150 | bool swap_led_target_color(keyframe_animation_t* animation, visualizer_state_t* state) { | ||
151 | uint32_t temp = next_led_target_color; | ||
152 | next_led_target_color = state->target_lcd_color; | ||
153 | state->target_lcd_color = temp; | ||
154 | return false; | ||
155 | } | ||
156 | |||
157 | // The color animation animates the LCD color when you change layers | ||
158 | static keyframe_animation_t two_led_colors = { | ||
159 | .num_frames = 2, | ||
160 | .loop = true, | ||
161 | .frame_lengths = {gfxMillisecondsToTicks(1000), gfxMillisecondsToTicks(0)}, | ||
162 | .frame_functions = {keyframe_set_backlight_color, swap_led_target_color}, | ||
163 | }; | ||
130 | 164 | ||
131 | // The LCD animation alternates between the layer name display and a | 165 | // The LCD animation alternates between the layer name display and a |
132 | // bitmap that displays all active layers | 166 | // bitmap that displays all active layers |
@@ -177,6 +211,45 @@ void initialize_user_visualizer(visualizer_state_t* state) { | |||
177 | start_keyframe_animation(&startup_animation); | 211 | start_keyframe_animation(&startup_animation); |
178 | } | 212 | } |
179 | 213 | ||
214 | static const uint32_t red; | ||
215 | static const uint32_t green; | ||
216 | static const uint32_t blue; | ||
217 | |||
218 | inline bool is_led_on(visualizer_user_data_t* user_data, uint8_t num) { | ||
219 | return user_data->led_on & (1u << num); | ||
220 | } | ||
221 | |||
222 | static uint8_t get_led_index_master(visualizer_user_data_t* user_data) { | ||
223 | for (int i=0; i < 3; i++) { | ||
224 | if (is_led_on(user_data, i)) { | ||
225 | return i + 1; | ||
226 | } | ||
227 | } | ||
228 | return 0; | ||
229 | } | ||
230 | |||
231 | static uint8_t get_led_index_slave(visualizer_user_data_t* user_data) { | ||
232 | uint8_t master_index = get_led_index_master(user_data); | ||
233 | if (master_index!=0) { | ||
234 | for (int i=master_index; i < 3; i++) { | ||
235 | if (is_led_on(user_data, i)) { | ||
236 | return i + 1; | ||
237 | } | ||
238 | } | ||
239 | } | ||
240 | |||
241 | return 0; | ||
242 | } | ||
243 | |||
244 | static uint8_t get_secondary_led_index(visualizer_user_data_t* user_data) { | ||
245 | if (is_led_on(user_data, 0) && | ||
246 | is_led_on(user_data, 1) && | ||
247 | is_led_on(user_data, 2)) { | ||
248 | return 3; | ||
249 | } | ||
250 | return 0; | ||
251 | } | ||
252 | |||
180 | void update_user_visualizer_state(visualizer_state_t* state, visualizer_keyboard_status_t prev_status) { | 253 | void update_user_visualizer_state(visualizer_state_t* state, visualizer_keyboard_status_t prev_status) { |
181 | // Check the status here to start and stop animations | 254 | // Check the status here to start and stop animations |
182 | // You might have to save some state, like the current animation here so that you can start the right | 255 | // You might have to save some state, like the current animation here so that you can start the right |
@@ -186,9 +259,38 @@ void update_user_visualizer_state(visualizer_state_t* state, visualizer_keyboard | |||
186 | // This is also important because the slave won't have access to the active layer for example outside the | 259 | // This is also important because the slave won't have access to the active layer for example outside the |
187 | // status. | 260 | // status. |
188 | 261 | ||
189 | if (lcd_state == LCD_STATE_INITIAL) { | 262 | |
190 | state->target_lcd_color = LCD_COLOR(0x40, 0xB0, 0xFF); | 263 | visualizer_user_data_t* user_data_new = (visualizer_user_data_t*)state->status.user_data; |
191 | start_keyframe_animation(&color_animation); | 264 | visualizer_user_data_t* user_data_old = (visualizer_user_data_t*)prev_status.user_data; |
265 | |||
266 | uint8_t new_index; | ||
267 | uint8_t old_index; | ||
268 | |||
269 | if (is_serial_link_master()) { | ||
270 | new_index = get_led_index_master(user_data_new); | ||
271 | old_index = get_led_index_master(user_data_old); | ||
272 | } | ||
273 | else { | ||
274 | new_index = get_led_index_slave(user_data_new); | ||
275 | old_index = get_led_index_slave(user_data_old); | ||
276 | } | ||
277 | uint8_t new_secondary_index = get_secondary_led_index(user_data_new); | ||
278 | uint8_t old_secondary_index = get_secondary_led_index(user_data_old); | ||
279 | |||
280 | if (lcd_state == LCD_STATE_INITIAL || | ||
281 | new_index != old_index || | ||
282 | new_secondary_index != old_secondary_index) { | ||
283 | |||
284 | if (new_secondary_index != 0) { | ||
285 | state->target_lcd_color = led_emulation_colors[new_index]; | ||
286 | next_led_target_color = led_emulation_colors[new_secondary_index]; | ||
287 | stop_keyframe_animation(&one_led_color); | ||
288 | start_keyframe_animation(&two_led_colors); | ||
289 | } else { | ||
290 | state->target_lcd_color = led_emulation_colors[new_index]; | ||
291 | stop_keyframe_animation(&two_led_colors); | ||
292 | start_keyframe_animation(&one_led_color); | ||
293 | } | ||
192 | } | 294 | } |
193 | 295 | ||
194 | if (state->status.leds) { | 296 | if (state->status.leds) { |
@@ -233,3 +335,56 @@ void user_visualizer_resume(visualizer_state_t* state) { | |||
233 | lcd_state = LCD_STATE_INITIAL; | 335 | lcd_state = LCD_STATE_INITIAL; |
234 | start_keyframe_animation(&resume_animation); | 336 | start_keyframe_animation(&resume_animation); |
235 | } | 337 | } |
338 | |||
339 | void ergodox_board_led_on(void){ | ||
340 | // No board led support | ||
341 | } | ||
342 | |||
343 | void ergodox_right_led_1_on(void){ | ||
344 | user_data_keyboard.led_on |= (1u << 0); | ||
345 | visualizer_set_user_data(&user_data_keyboard); | ||
346 | } | ||
347 | |||
348 | void ergodox_right_led_2_on(void){ | ||
349 | user_data_keyboard.led_on |= (1u << 1); | ||
350 | visualizer_set_user_data(&user_data_keyboard); | ||
351 | } | ||
352 | |||
353 | void ergodox_right_led_3_on(void){ | ||
354 | user_data_keyboard.led_on |= (1u << 2); | ||
355 | visualizer_set_user_data(&user_data_keyboard); | ||
356 | } | ||
357 | |||
358 | void ergodox_board_led_off(void){ | ||
359 | // No board led support | ||
360 | } | ||
361 | |||
362 | void ergodox_right_led_1_off(void){ | ||
363 | user_data_keyboard.led_on &= ~(1u << 0); | ||
364 | visualizer_set_user_data(&user_data_keyboard); | ||
365 | } | ||
366 | |||
367 | void ergodox_right_led_2_off(void){ | ||
368 | user_data_keyboard.led_on &= ~(1u << 1); | ||
369 | visualizer_set_user_data(&user_data_keyboard); | ||
370 | } | ||
371 | |||
372 | void ergodox_right_led_3_off(void){ | ||
373 | user_data_keyboard.led_on &= ~(1u << 2); | ||
374 | visualizer_set_user_data(&user_data_keyboard); | ||
375 | } | ||
376 | |||
377 | void ergodox_right_led_1_set(uint8_t n) { | ||
378 | user_data_keyboard.led1 = n; | ||
379 | visualizer_set_user_data(&user_data_keyboard); | ||
380 | } | ||
381 | |||
382 | void ergodox_right_led_2_set(uint8_t n) { | ||
383 | user_data_keyboard.led2 = n; | ||
384 | visualizer_set_user_data(&user_data_keyboard); | ||
385 | } | ||
386 | |||
387 | void ergodox_right_led_3_set(uint8_t n) { | ||
388 | user_data_keyboard.led3 = n; | ||
389 | visualizer_set_user_data(&user_data_keyboard); | ||
390 | } | ||
diff --git a/quantum/visualizer/visualizer.c b/quantum/visualizer/visualizer.c index 62ebebcee..bff0df494 100644 --- a/quantum/visualizer/visualizer.c +++ b/quantum/visualizer/visualizer.c | |||
@@ -64,6 +64,9 @@ static visualizer_keyboard_status_t current_status = { | |||
64 | .mods = 0xFF, | 64 | .mods = 0xFF, |
65 | .leds = 0xFFFFFFFF, | 65 | .leds = 0xFFFFFFFF, |
66 | .suspended = false, | 66 | .suspended = false, |
67 | #ifdef VISUALIZER_USER_DATA_SIZE | ||
68 | .user_data = {0} | ||
69 | #endif | ||
67 | }; | 70 | }; |
68 | 71 | ||
69 | static bool same_status(visualizer_keyboard_status_t* status1, visualizer_keyboard_status_t* status2) { | 72 | static bool same_status(visualizer_keyboard_status_t* status1, visualizer_keyboard_status_t* status2) { |
@@ -71,11 +74,19 @@ static bool same_status(visualizer_keyboard_status_t* status1, visualizer_keyboa | |||
71 | status1->default_layer == status2->default_layer && | 74 | status1->default_layer == status2->default_layer && |
72 | status1->mods == status2->mods && | 75 | status1->mods == status2->mods && |
73 | status1->leds == status2->leds && | 76 | status1->leds == status2->leds && |
74 | status1->suspended == status2->suspended; | 77 | status1->suspended == status2->suspended |
78 | #ifdef VISUALIZER_USER_DATA_SIZE | ||
79 | && memcmp(status1->user_data, status2->user_data, VISUALIZER_USER_DATA_SIZE) == 0 | ||
80 | #endif | ||
81 | ; | ||
75 | } | 82 | } |
76 | 83 | ||
77 | static bool visualizer_enabled = false; | 84 | static bool visualizer_enabled = false; |
78 | 85 | ||
86 | #ifdef VISUALIZER_USER_DATA_SIZE | ||
87 | static uint8_t user_data[VISUALIZER_USER_DATA_SIZE]; | ||
88 | #endif | ||
89 | |||
79 | #define MAX_SIMULTANEOUS_ANIMATIONS 4 | 90 | #define MAX_SIMULTANEOUS_ANIMATIONS 4 |
80 | static keyframe_animation_t* animations[MAX_SIMULTANEOUS_ANIMATIONS] = {}; | 91 | static keyframe_animation_t* animations[MAX_SIMULTANEOUS_ANIMATIONS] = {}; |
81 | 92 | ||
@@ -431,6 +442,9 @@ static DECLARE_THREAD_FUNCTION(visualizerThread, arg) { | |||
431 | .mods = 0xFF, | 442 | .mods = 0xFF, |
432 | .leds = 0xFFFFFFFF, | 443 | .leds = 0xFFFFFFFF, |
433 | .suspended = false, | 444 | .suspended = false, |
445 | #ifdef VISUALIZER_USER_DATA_SIZE | ||
446 | .user_data = {0}, | ||
447 | #endif | ||
434 | }; | 448 | }; |
435 | 449 | ||
436 | visualizer_state_t state = { | 450 | visualizer_state_t state = { |
@@ -590,6 +604,12 @@ uint8_t visualizer_get_mods() { | |||
590 | return mods; | 604 | return mods; |
591 | } | 605 | } |
592 | 606 | ||
607 | #ifdef VISUALIZER_USER_DATA_SIZE | ||
608 | void visualizer_set_user_data(void* u) { | ||
609 | memcpy(user_data, u, VISUALIZER_USER_DATA_SIZE); | ||
610 | } | ||
611 | #endif | ||
612 | |||
593 | void visualizer_update(uint32_t default_state, uint32_t state, uint8_t mods, uint32_t leds) { | 613 | void visualizer_update(uint32_t default_state, uint32_t state, uint8_t mods, uint32_t leds) { |
594 | // Note that there's a small race condition here, the thread could read | 614 | // Note that there's a small race condition here, the thread could read |
595 | // a state where one of these are set but not the other. But this should | 615 | // a state where one of these are set but not the other. But this should |
@@ -618,6 +638,9 @@ void visualizer_update(uint32_t default_state, uint32_t state, uint8_t mods, uin | |||
618 | .leds = leds, | 638 | .leds = leds, |
619 | .suspended = current_status.suspended, | 639 | .suspended = current_status.suspended, |
620 | }; | 640 | }; |
641 | #ifdef VISUALIZER_USER_DATA_SIZE | ||
642 | memcpy(new_status.user_data, user_data, VISUALIZER_USER_DATA_SIZE); | ||
643 | #endif | ||
621 | if (!same_status(¤t_status, &new_status)) { | 644 | if (!same_status(¤t_status, &new_status)) { |
622 | changed = true; | 645 | changed = true; |
623 | current_status = new_status; | 646 | current_status = new_status; |
diff --git a/quantum/visualizer/visualizer.h b/quantum/visualizer/visualizer.h index 2c81cb9f7..beb8f2ab4 100644 --- a/quantum/visualizer/visualizer.h +++ b/quantum/visualizer/visualizer.h | |||
@@ -68,6 +68,9 @@ typedef struct { | |||
68 | uint8_t mods; | 68 | uint8_t mods; |
69 | uint32_t leds; // See led.h for available statuses | 69 | uint32_t leds; // See led.h for available statuses |
70 | bool suspended; | 70 | bool suspended; |
71 | #ifdef VISUALIZER_USER_DATA_SIZE | ||
72 | uint8_t user_data[VISUALIZER_USER_DATA_SIZE]; | ||
73 | #endif | ||
71 | } visualizer_keyboard_status_t; | 74 | } visualizer_keyboard_status_t; |
72 | 75 | ||
73 | // The state struct is used by the various keyframe functions | 76 | // The state struct is used by the various keyframe functions |
@@ -146,6 +149,11 @@ bool keyframe_enable_lcd_and_backlight(keyframe_animation_t* animation, visualiz | |||
146 | // directly from the initalize_user_visualizer function (the animation can be null) | 149 | // directly from the initalize_user_visualizer function (the animation can be null) |
147 | bool enable_visualization(keyframe_animation_t* animation, visualizer_state_t* state); | 150 | bool enable_visualization(keyframe_animation_t* animation, visualizer_state_t* state); |
148 | 151 | ||
152 | // The master can set userdata which will be transferred to the slave | ||
153 | #ifdef VISUALIZER_USER_DATA_SIZE | ||
154 | void visualizer_set_user_data(void* user_data); | ||
155 | #endif | ||
156 | |||
149 | // These functions have to be implemented by the user | 157 | // These functions have to be implemented by the user |
150 | void initialize_user_visualizer(visualizer_state_t* state); | 158 | void initialize_user_visualizer(visualizer_state_t* state); |
151 | void update_user_visualizer_state(visualizer_state_t* state, visualizer_keyboard_status_t prev_status); | 159 | void update_user_visualizer_state(visualizer_state_t* state, visualizer_keyboard_status_t prev_status); |