diff options
| -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 | ||
