diff options
| author | Fred Sundvik <fsundvik@gmail.com> | 2016-03-13 17:54:45 +0200 |
|---|---|---|
| committer | Fred Sundvik <fsundvik@gmail.com> | 2016-03-13 20:13:02 +0200 |
| commit | b93d07198a18063594a59dd193d0961622087868 (patch) | |
| tree | 4978d505018cdd97cb8683511676bba0f097cf56 /visualizer.c | |
| parent | 315edb48265e6baedd07f34c9e6e323d28814b4e (diff) | |
| download | qmk_firmware-b93d07198a18063594a59dd193d0961622087868.tar.gz qmk_firmware-b93d07198a18063594a59dd193d0961622087868.zip | |
Suspend support for the visualizer
Diffstat (limited to 'visualizer.c')
| -rw-r--r-- | visualizer.c | 114 |
1 files changed, 88 insertions, 26 deletions
diff --git a/visualizer.c b/visualizer.c index ca7bcb776..5b0d560ed 100644 --- a/visualizer.c +++ b/visualizer.c | |||
| @@ -52,10 +52,14 @@ static visualizer_keyboard_status_t current_status = { | |||
| 52 | .layer = 0xFFFFFFFF, | 52 | .layer = 0xFFFFFFFF, |
| 53 | .default_layer = 0xFFFFFFFF, | 53 | .default_layer = 0xFFFFFFFF, |
| 54 | .leds = 0xFFFFFFFF, | 54 | .leds = 0xFFFFFFFF, |
| 55 | .suspended = false, | ||
| 55 | }; | 56 | }; |
| 56 | 57 | ||
| 57 | static bool same_status(visualizer_keyboard_status_t* status1, visualizer_keyboard_status_t* status2) { | 58 | static bool same_status(visualizer_keyboard_status_t* status1, visualizer_keyboard_status_t* status2) { |
| 58 | return memcmp(status1, status2, sizeof(visualizer_keyboard_status_t)) == 0; | 59 | return status1->layer == status2->layer && |
| 60 | status1->default_layer == status2->default_layer && | ||
| 61 | status1->leds == status2->leds && | ||
| 62 | status1->suspended == status2->suspended; | ||
| 59 | } | 63 | } |
| 60 | 64 | ||
| 61 | static event_source_t layer_changed_event; | 65 | static event_source_t layer_changed_event; |
| @@ -104,6 +108,17 @@ void stop_keyframe_animation(keyframe_animation_t* animation) { | |||
| 104 | } | 108 | } |
| 105 | } | 109 | } |
| 106 | 110 | ||
| 111 | void stop_all_keyframe_animations(void) { | ||
| 112 | for (int i=0;i<MAX_SIMULTANEOUS_ANIMATIONS;i++) { | ||
| 113 | if (animations[i]) { | ||
| 114 | animations[i]->current_frame = animations[i]->num_frames; | ||
| 115 | animations[i]->time_left_in_frame = 0; | ||
| 116 | animations[i]->need_update = true; | ||
| 117 | animations[i] = NULL; | ||
| 118 | } | ||
| 119 | } | ||
| 120 | } | ||
| 121 | |||
| 107 | static bool update_keyframe_animation(keyframe_animation_t* animation, visualizer_state_t* state, systime_t delta, systime_t* sleep_time) { | 122 | static bool update_keyframe_animation(keyframe_animation_t* animation, visualizer_state_t* state, systime_t delta, systime_t* sleep_time) { |
| 108 | dprintf("Animation frame%d, left %d, delta %d\n", animation->current_frame, | 123 | dprintf("Animation frame%d, left %d, delta %d\n", animation->current_frame, |
| 109 | animation->time_left_in_frame, delta); | 124 | animation->time_left_in_frame, delta); |
| @@ -252,7 +267,19 @@ bool keyframe_display_layer_bitmap(keyframe_animation_t* animation, visualizer_s | |||
| 252 | } | 267 | } |
| 253 | #endif // LCD_ENABLE | 268 | #endif // LCD_ENABLE |
| 254 | 269 | ||
| 255 | bool user_visualizer_inited(keyframe_animation_t* animation, visualizer_state_t* state) { | 270 | bool keyframe_disable_lcd_and_backlight(keyframe_animation_t* animation, visualizer_state_t* state) { |
| 271 | (void)animation; | ||
| 272 | (void)state; | ||
| 273 | return false; | ||
| 274 | } | ||
| 275 | |||
| 276 | bool keyframe_enable_lcd_and_backlight(keyframe_animation_t* animation, visualizer_state_t* state) { | ||
| 277 | (void)animation; | ||
| 278 | (void)state; | ||
| 279 | return false; | ||
| 280 | } | ||
| 281 | |||
| 282 | bool enable_visualization(keyframe_animation_t* animation, visualizer_state_t* state) { | ||
| 256 | (void)animation; | 283 | (void)animation; |
| 257 | (void)state; | 284 | (void)state; |
| 258 | dprint("User visualizer inited\n"); | 285 | dprint("User visualizer inited\n"); |
| @@ -268,13 +295,15 @@ static THD_FUNCTION(visualizerThread, arg) { | |||
| 268 | event_listener_t event_listener; | 295 | event_listener_t event_listener; |
| 269 | chEvtRegister(&layer_changed_event, &event_listener, 0); | 296 | chEvtRegister(&layer_changed_event, &event_listener, 0); |
| 270 | 297 | ||
| 271 | visualizer_state_t state = { | 298 | visualizer_keyboard_status_t initial_status = { |
| 272 | .status = { | 299 | .default_layer = 0xFFFFFFFF, |
| 273 | .default_layer = 0xFFFFFFFF, | 300 | .layer = 0xFFFFFFFF, |
| 274 | .layer = 0xFFFFFFFF, | 301 | .leds = 0xFFFFFFFF, |
| 275 | .leds = 0xFFFFFFFF, | 302 | .suspended = false, |
| 276 | }, | 303 | }; |
| 277 | 304 | ||
| 305 | visualizer_state_t state = { | ||
| 306 | .status = initial_status, | ||
| 278 | .current_lcd_color = 0, | 307 | .current_lcd_color = 0, |
| 279 | #ifdef LCD_ENABLE | 308 | #ifdef LCD_ENABLE |
| 280 | .font_fixed5x8 = gdispOpenFont("fixed_5x8"), | 309 | .font_fixed5x8 = gdispOpenFont("fixed_5x8"), |
| @@ -301,17 +330,36 @@ static THD_FUNCTION(visualizerThread, arg) { | |||
| 301 | bool enabled = visualizer_enabled; | 330 | bool enabled = visualizer_enabled; |
| 302 | if (!same_status(&state.status, ¤t_status)) { | 331 | if (!same_status(&state.status, ¤t_status)) { |
| 303 | if (visualizer_enabled) { | 332 | if (visualizer_enabled) { |
| 304 | state.status = current_status; | 333 | if (current_status.suspended) { |
| 305 | update_user_visualizer_state(&state); | 334 | stop_all_keyframe_animations(); |
| 306 | state.prev_lcd_color = state.current_lcd_color; | 335 | visualizer_enabled = false; |
| 336 | state.status = current_status; | ||
| 337 | user_visualizer_suspend(&state); | ||
| 338 | } | ||
| 339 | else { | ||
| 340 | state.status = current_status; | ||
| 341 | update_user_visualizer_state(&state); | ||
| 342 | state.prev_lcd_color = state.current_lcd_color; | ||
| 343 | } | ||
| 307 | } | 344 | } |
| 308 | } | 345 | } |
| 346 | if (!enabled && state.status.suspended && current_status.suspended == false) { | ||
| 347 | // Setting the status to the initial status will force an update | ||
| 348 | // when the visualizer is enabled again | ||
| 349 | state.status = initial_status; | ||
| 350 | state.status.suspended = false; | ||
| 351 | stop_all_keyframe_animations(); | ||
| 352 | user_visualizer_resume(&state); | ||
| 353 | } | ||
| 309 | sleep_time = TIME_INFINITE; | 354 | sleep_time = TIME_INFINITE; |
| 310 | for (int i=0;i<MAX_SIMULTANEOUS_ANIMATIONS;i++) { | 355 | for (int i=0;i<MAX_SIMULTANEOUS_ANIMATIONS;i++) { |
| 311 | if (animations[i]) { | 356 | if (animations[i]) { |
| 312 | update_keyframe_animation(animations[i], &state, delta, &sleep_time); | 357 | update_keyframe_animation(animations[i], &state, delta, &sleep_time); |
| 313 | } | 358 | } |
| 314 | } | 359 | } |
| 360 | // The animation can enable the visualizer | ||
| 361 | // And we might need to update the state when that happens | ||
| 362 | // so don't sleep | ||
| 315 | if (enabled != visualizer_enabled) { | 363 | if (enabled != visualizer_enabled) { |
| 316 | sleep_time = 0; | 364 | sleep_time = 0; |
| 317 | } | 365 | } |
| @@ -354,7 +402,24 @@ void visualizer_init(void) { | |||
| 354 | LOWPRIO, visualizerThread, NULL); | 402 | LOWPRIO, visualizerThread, NULL); |
| 355 | } | 403 | } |
| 356 | 404 | ||
| 357 | void visualizer_set_state(uint32_t default_state, uint32_t state, uint32_t leds) { | 405 | void update_status(bool changed) { |
| 406 | if (changed) { | ||
| 407 | chEvtBroadcast(&layer_changed_event); | ||
| 408 | } | ||
| 409 | #ifdef USE_SERIAL_LINK | ||
| 410 | static systime_t last_update = 0; | ||
| 411 | systime_t current_update = chVTGetSystemTimeX(); | ||
| 412 | systime_t delta = current_update - last_update; | ||
| 413 | if (changed || delta > MS2ST(10)) { | ||
| 414 | last_update = current_update; | ||
| 415 | visualizer_keyboard_status_t* r = begin_write_current_status(); | ||
| 416 | *r = current_status; | ||
| 417 | end_write_current_status(); | ||
| 418 | } | ||
| 419 | #endif | ||
| 420 | } | ||
| 421 | |||
| 422 | void visualizer_update(uint32_t default_state, uint32_t state, uint32_t leds) { | ||
| 358 | // Note that there's a small race condition here, the thread could read | 423 | // Note that there's a small race condition here, the thread could read |
| 359 | // a state where one of these are set but not the other. But this should | 424 | // a state where one of these are set but not the other. But this should |
| 360 | // not really matter as it will be fixed during the next loop step. | 425 | // not really matter as it will be fixed during the next loop step. |
| @@ -379,25 +444,22 @@ void visualizer_set_state(uint32_t default_state, uint32_t state, uint32_t leds) | |||
| 379 | .layer = state, | 444 | .layer = state, |
| 380 | .default_layer = default_state, | 445 | .default_layer = default_state, |
| 381 | .leds = leds, | 446 | .leds = leds, |
| 447 | .suspended = current_status.suspended, | ||
| 382 | }; | 448 | }; |
| 383 | if (!same_status(¤t_status, &new_status)) { | 449 | if (!same_status(¤t_status, &new_status)) { |
| 384 | changed = true; | 450 | changed = true; |
| 385 | current_status = new_status; | 451 | current_status = new_status; |
| 386 | } | 452 | } |
| 387 | } | 453 | } |
| 388 | if (changed) { | 454 | update_status(changed); |
| 389 | chEvtBroadcast(&layer_changed_event); | 455 | } |
| 390 | 456 | ||
| 391 | } | 457 | void visualizer_suspend(void) { |
| 392 | #ifdef USE_SERIAL_LINK | 458 | current_status.suspended = true; |
| 393 | static systime_t last_update = 0; | 459 | update_status(true); |
| 394 | systime_t current_update = chVTGetSystemTimeX(); | 460 | } |
| 395 | systime_t delta = current_update - last_update; | 461 | |
| 396 | if (changed || delta > MS2ST(10)) { | 462 | void visualizer_resume(void) { |
| 397 | last_update = current_update; | 463 | current_status.suspended = false; |
| 398 | visualizer_keyboard_status_t* r = begin_write_current_status(); | 464 | update_status(true); |
| 399 | *r = current_status; | ||
| 400 | end_write_current_status(); | ||
| 401 | } | ||
| 402 | #endif | ||
| 403 | } | 465 | } |
