diff options
author | Fred Sundvik <fsundvik@gmail.com> | 2017-04-01 22:52:58 +0300 |
---|---|---|
committer | Fred Sundvik <fsundvik@gmail.com> | 2017-04-09 18:34:59 +0300 |
commit | 9a4ce28683b667ab67d48d92196bab7e277d4800 (patch) | |
tree | ad518ba049f16a6877775d28aa283d2ff8cc8c34 | |
parent | 951b6f33a0dc479d29831aaa5c73fc526faf0471 (diff) | |
download | qmk_firmware-9a4ce28683b667ab67d48d92196bab7e277d4800.tar.gz qmk_firmware-9a4ce28683b667ab67d48d92196bab7e277d4800.zip |
Display layer bitmap and keyboard led states on the LCD
-rw-r--r-- | keyboards/ergodox/infinity/visualizer.c | 86 | ||||
-rw-r--r-- | quantum/visualizer/visualizer.c | 38 | ||||
-rw-r--r-- | quantum/visualizer/visualizer.h | 4 |
3 files changed, 97 insertions, 31 deletions
diff --git a/keyboards/ergodox/infinity/visualizer.c b/keyboards/ergodox/infinity/visualizer.c index 12336fdc5..6af3a72ee 100644 --- a/keyboards/ergodox/infinity/visualizer.c +++ b/keyboards/ergodox/infinity/visualizer.c | |||
@@ -73,6 +73,14 @@ static const uint8_t image_data_lcd_logo[512] = { | |||
73 | static const uint32_t logo_background_color = LCD_COLOR(0x00, 0x00, 0xFF); | 73 | static const uint32_t logo_background_color = LCD_COLOR(0x00, 0x00, 0xFF); |
74 | static const uint32_t initial_color = LCD_COLOR(0, 0, 0); | 74 | static const uint32_t initial_color = LCD_COLOR(0, 0, 0); |
75 | 75 | ||
76 | typedef enum { | ||
77 | LCD_STATE_INITIAL, | ||
78 | LCD_STATE_LAYER_BITMAP, | ||
79 | LCD_STATE_BITMAP_AND_LEDS, | ||
80 | } lcd_state_t; | ||
81 | |||
82 | static lcd_state_t lcd_state = LCD_STATE_INITIAL; | ||
83 | |||
76 | bool display_logo(keyframe_animation_t* animation, visualizer_state_t* state) { | 84 | bool display_logo(keyframe_animation_t* animation, visualizer_state_t* state) { |
77 | (void)state; | 85 | (void)state; |
78 | (void)animation; | 86 | (void)animation; |
@@ -122,11 +130,18 @@ static keyframe_animation_t color_animation = { | |||
122 | 130 | ||
123 | // The LCD animation alternates between the layer name display and a | 131 | // The LCD animation alternates between the layer name display and a |
124 | // bitmap that displays all active layers | 132 | // bitmap that displays all active layers |
125 | static keyframe_animation_t lcd_animation = { | 133 | static keyframe_animation_t lcd_bitmap_animation = { |
134 | .num_frames = 1, | ||
135 | .loop = false, | ||
136 | .frame_lengths = {gfxMillisecondsToTicks(0)}, | ||
137 | .frame_functions = {keyframe_display_layer_bitmap}, | ||
138 | }; | ||
139 | |||
140 | static keyframe_animation_t lcd_bitmap_leds_animation = { | ||
126 | .num_frames = 2, | 141 | .num_frames = 2, |
127 | .loop = true, | 142 | .loop = true, |
128 | .frame_lengths = {gfxMillisecondsToTicks(2000), gfxMillisecondsToTicks(2000)}, | 143 | .frame_lengths = {gfxMillisecondsToTicks(2000), gfxMillisecondsToTicks(2000)}, |
129 | .frame_functions = {keyframe_display_layer_text, keyframe_display_layer_bitmap}, | 144 | .frame_functions = {keyframe_display_layer_bitmap, keyframe_display_led_states}, |
130 | }; | 145 | }; |
131 | 146 | ||
132 | static keyframe_animation_t suspend_animation = { | 147 | static keyframe_animation_t suspend_animation = { |
@@ -158,38 +173,50 @@ void initialize_user_visualizer(visualizer_state_t* state) { | |||
158 | lcd_backlight_brightness(130); | 173 | lcd_backlight_brightness(130); |
159 | state->current_lcd_color = initial_color; | 174 | state->current_lcd_color = initial_color; |
160 | state->target_lcd_color = logo_background_color; | 175 | state->target_lcd_color = logo_background_color; |
176 | lcd_state = LCD_STATE_INITIAL; | ||
161 | start_keyframe_animation(&startup_animation); | 177 | start_keyframe_animation(&startup_animation); |
162 | } | 178 | } |
163 | 179 | ||
164 | void update_user_visualizer_state(visualizer_state_t* state) { | 180 | void update_user_visualizer_state(visualizer_state_t* state, visualizer_keyboard_status_t prev_status) { |
165 | // Add more tests, change the colors and layer texts here | 181 | // Check the status here to start and stop animations |
166 | // Usually you want to check the high bits (higher layers first) | 182 | // You might have to save some state, like the current animation here so that you can start the right |
167 | // because that's the order layers are processed for keypresses | 183 | // This function is called every time the status changes |
168 | // You can for check for example: | 184 | |
169 | // state->status.layer | 185 | // NOTE that this is called from the visualizer thread, so don't access anything else outside the status |
170 | // state->status.default_layer | 186 | // This is also important because the slave won't have access to the active layer for example outside the |
171 | // state->status.leds (see led.h for available statuses) | 187 | // status. |
172 | if (state->status.layer & 0x8) { | 188 | |
173 | state->target_lcd_color = LCD_COLOR(0xC0, 0xB0, 0xFF); | 189 | if (lcd_state == LCD_STATE_INITIAL) { |
174 | state->layer_text = "Numpad"; | ||
175 | } | ||
176 | else if (state->status.layer & 0x4) { | ||
177 | state->target_lcd_color = LCD_COLOR(0, 0xB0, 0xFF); | ||
178 | state->layer_text = "KBD functions"; | ||
179 | } | ||
180 | else if (state->status.layer & 0x2) { | ||
181 | state->target_lcd_color = LCD_COLOR(0x80, 0xB0, 0xFF); | ||
182 | state->layer_text = "Function keys"; | ||
183 | } | ||
184 | else { | ||
185 | state->target_lcd_color = LCD_COLOR(0x40, 0xB0, 0xFF); | 190 | state->target_lcd_color = LCD_COLOR(0x40, 0xB0, 0xFF); |
186 | state->layer_text = "Default"; | 191 | start_keyframe_animation(&color_animation); |
192 | } | ||
193 | |||
194 | if (state->status.leds) { | ||
195 | if (lcd_state != LCD_STATE_BITMAP_AND_LEDS || | ||
196 | state->status.leds != prev_status.leds || | ||
197 | state->status.layer != prev_status.layer || | ||
198 | state->status.default_layer != prev_status.default_layer) { | ||
199 | |||
200 | // NOTE: that it doesn't matter if the animation isn't playing, stop will do nothing in that case | ||
201 | stop_keyframe_animation(&lcd_bitmap_animation); | ||
202 | |||
203 | lcd_state = LCD_STATE_BITMAP_AND_LEDS; | ||
204 | // For information: | ||
205 | // The logic in this function makes sure that this doesn't happen, but if you call start on an | ||
206 | // animation that is already playing it will be restarted. | ||
207 | start_keyframe_animation(&lcd_bitmap_leds_animation); | ||
208 | } | ||
209 | } else { | ||
210 | if (lcd_state != LCD_STATE_LAYER_BITMAP || | ||
211 | state->status.layer != prev_status.layer || | ||
212 | state->status.default_layer != prev_status.default_layer) { | ||
213 | |||
214 | stop_keyframe_animation(&lcd_bitmap_leds_animation); | ||
215 | |||
216 | lcd_state = LCD_STATE_LAYER_BITMAP; | ||
217 | start_keyframe_animation(&lcd_bitmap_animation); | ||
218 | } | ||
187 | } | 219 | } |
188 | // You can also stop existing animations, and start your custom ones here | ||
189 | // remember that you should normally have only one animation for the LCD | ||
190 | // and one for the background. But you can also combine them if you want. | ||
191 | start_keyframe_animation(&lcd_animation); | ||
192 | start_keyframe_animation(&color_animation); | ||
193 | } | 220 | } |
194 | 221 | ||
195 | void user_visualizer_suspend(visualizer_state_t* state) { | 222 | void user_visualizer_suspend(visualizer_state_t* state) { |
@@ -203,5 +230,6 @@ void user_visualizer_suspend(visualizer_state_t* state) { | |||
203 | void user_visualizer_resume(visualizer_state_t* state) { | 230 | void user_visualizer_resume(visualizer_state_t* state) { |
204 | state->current_lcd_color = initial_color; | 231 | state->current_lcd_color = initial_color; |
205 | state->target_lcd_color = logo_background_color; | 232 | state->target_lcd_color = logo_background_color; |
233 | lcd_state = LCD_STATE_INITIAL; | ||
206 | start_keyframe_animation(&resume_animation); | 234 | start_keyframe_animation(&resume_animation); |
207 | } | 235 | } |
diff --git a/quantum/visualizer/visualizer.c b/quantum/visualizer/visualizer.c index 5826d909e..62ebebcee 100644 --- a/quantum/visualizer/visualizer.c +++ b/quantum/visualizer/visualizer.c | |||
@@ -56,6 +56,8 @@ SOFTWARE. | |||
56 | // mods status | 56 | // mods status |
57 | #include "action_util.h" | 57 | #include "action_util.h" |
58 | 58 | ||
59 | #include "led.h" | ||
60 | |||
59 | static visualizer_keyboard_status_t current_status = { | 61 | static visualizer_keyboard_status_t current_status = { |
60 | .layer = 0xFFFFFFFF, | 62 | .layer = 0xFFFFFFFF, |
61 | .default_layer = 0xFFFFFFFF, | 63 | .default_layer = 0xFFFFFFFF, |
@@ -350,6 +352,39 @@ bool keyframe_display_mods_bitmap(keyframe_animation_t* animation, visualizer_st | |||
350 | gdispFlush(); | 352 | gdispFlush(); |
351 | return false; | 353 | return false; |
352 | } | 354 | } |
355 | |||
356 | bool keyframe_display_led_states(keyframe_animation_t* animation, visualizer_state_t* state) | ||
357 | { | ||
358 | char output[sizeof("NUM CAPS SCRL COMP KANA")]; | ||
359 | uint8_t pos = 0; | ||
360 | |||
361 | if (state->status.leds & (1u << USB_LED_NUM_LOCK)) { | ||
362 | memcpy(output + pos, "NUM ", 4); | ||
363 | pos += 4; | ||
364 | } | ||
365 | if (state->status.leds & (1u << USB_LED_CAPS_LOCK)) { | ||
366 | memcpy(output + pos, "CAPS ", 5); | ||
367 | pos += 5; | ||
368 | } | ||
369 | if (state->status.leds & (1u << USB_LED_SCROLL_LOCK)) { | ||
370 | memcpy(output + pos, "SCRL ", 5); | ||
371 | pos += 5; | ||
372 | } | ||
373 | if (state->status.leds & (1u << USB_LED_COMPOSE)) { | ||
374 | memcpy(output + pos, "COMP ", 5); | ||
375 | pos += 5; | ||
376 | } | ||
377 | if (state->status.leds & (1u << USB_LED_KANA)) { | ||
378 | memcpy(output + pos, "KANA ", 5); | ||
379 | pos += 5; | ||
380 | } | ||
381 | output[pos] = 0; | ||
382 | gdispClear(White); | ||
383 | gdispDrawString(0, 10, output, state->font_dejavusansbold12, Black); | ||
384 | gdispFlush(); | ||
385 | return false; | ||
386 | } | ||
387 | |||
353 | #endif // LCD_ENABLE | 388 | #endif // LCD_ENABLE |
354 | 389 | ||
355 | bool keyframe_disable_lcd_and_backlight(keyframe_animation_t* animation, visualizer_state_t* state) { | 390 | bool keyframe_disable_lcd_and_backlight(keyframe_animation_t* animation, visualizer_state_t* state) { |
@@ -433,8 +468,9 @@ static DECLARE_THREAD_FUNCTION(visualizerThread, arg) { | |||
433 | user_visualizer_suspend(&state); | 468 | user_visualizer_suspend(&state); |
434 | } | 469 | } |
435 | else { | 470 | else { |
471 | visualizer_keyboard_status_t prev_status = state.status; | ||
436 | state.status = current_status; | 472 | state.status = current_status; |
437 | update_user_visualizer_state(&state); | 473 | update_user_visualizer_state(&state, prev_status); |
438 | } | 474 | } |
439 | state.prev_lcd_color = state.current_lcd_color; | 475 | state.prev_lcd_color = state.current_lcd_color; |
440 | } | 476 | } |
diff --git a/quantum/visualizer/visualizer.h b/quantum/visualizer/visualizer.h index 315af5022..2c81cb9f7 100644 --- a/quantum/visualizer/visualizer.h +++ b/quantum/visualizer/visualizer.h | |||
@@ -136,6 +136,8 @@ bool keyframe_display_layer_text(keyframe_animation_t* animation, visualizer_sta | |||
136 | bool keyframe_display_layer_bitmap(keyframe_animation_t* animation, visualizer_state_t* state); | 136 | bool keyframe_display_layer_bitmap(keyframe_animation_t* animation, visualizer_state_t* state); |
137 | // Displays a bitmap (0/1) of all the currently active mods | 137 | // Displays a bitmap (0/1) of all the currently active mods |
138 | bool keyframe_display_mods_bitmap(keyframe_animation_t* animation, visualizer_state_t* state); | 138 | bool keyframe_display_mods_bitmap(keyframe_animation_t* animation, visualizer_state_t* state); |
139 | // Displays the keyboard led states (CAPS (Caps lock), NUM (Num lock), SCRL (Scroll lock), COMP (Compose), KANA) | ||
140 | bool keyframe_display_led_states(keyframe_animation_t* animation, visualizer_state_t* state); | ||
139 | 141 | ||
140 | bool keyframe_disable_lcd_and_backlight(keyframe_animation_t* animation, visualizer_state_t* state); | 142 | bool keyframe_disable_lcd_and_backlight(keyframe_animation_t* animation, visualizer_state_t* state); |
141 | bool keyframe_enable_lcd_and_backlight(keyframe_animation_t* animation, visualizer_state_t* state); | 143 | bool keyframe_enable_lcd_and_backlight(keyframe_animation_t* animation, visualizer_state_t* state); |
@@ -146,7 +148,7 @@ bool enable_visualization(keyframe_animation_t* animation, visualizer_state_t* s | |||
146 | 148 | ||
147 | // These functions have to be implemented by the user | 149 | // These functions have to be implemented by the user |
148 | void initialize_user_visualizer(visualizer_state_t* state); | 150 | void initialize_user_visualizer(visualizer_state_t* state); |
149 | void update_user_visualizer_state(visualizer_state_t* state); | 151 | void update_user_visualizer_state(visualizer_state_t* state, visualizer_keyboard_status_t prev_status); |
150 | void user_visualizer_suspend(visualizer_state_t* state); | 152 | void user_visualizer_suspend(visualizer_state_t* state); |
151 | void user_visualizer_resume(visualizer_state_t* state); | 153 | void user_visualizer_resume(visualizer_state_t* state); |
152 | 154 | ||