From b93d07198a18063594a59dd193d0961622087868 Mon Sep 17 00:00:00 2001 From: Fred Sundvik Date: Sun, 13 Mar 2016 17:54:45 +0200 Subject: [PATCH] Suspend support for the visualizer --- example_integration/visualizer_user.c | 2 +- visualizer.c | 114 ++++++++++++++++++++------ visualizer.h | 17 +++- 3 files changed, 103 insertions(+), 30 deletions(-) diff --git a/example_integration/visualizer_user.c b/example_integration/visualizer_user.c index 6c4619d9..fc09fe2e 100644 --- a/example_integration/visualizer_user.c +++ b/example_integration/visualizer_user.c @@ -65,7 +65,7 @@ static keyframe_animation_t startup_animation = { .num_frames = 4, .loop = false, .frame_lengths = {0, MS2ST(1000), MS2ST(5000), 0}, - .frame_functions = {display_welcome, keyframe_animate_backlight_color, keyframe_no_operation, user_visualizer_inited}, + .frame_functions = {display_welcome, keyframe_animate_backlight_color, keyframe_no_operation, enable_visualization}, }; // The color animation animates the LCD color when you change layers diff --git a/visualizer.c b/visualizer.c index ca7bcb77..5b0d560e 100644 --- a/visualizer.c +++ b/visualizer.c @@ -52,10 +52,14 @@ static visualizer_keyboard_status_t current_status = { .layer = 0xFFFFFFFF, .default_layer = 0xFFFFFFFF, .leds = 0xFFFFFFFF, + .suspended = false, }; static bool same_status(visualizer_keyboard_status_t* status1, visualizer_keyboard_status_t* status2) { - return memcmp(status1, status2, sizeof(visualizer_keyboard_status_t)) == 0; + return status1->layer == status2->layer && + status1->default_layer == status2->default_layer && + status1->leds == status2->leds && + status1->suspended == status2->suspended; } static event_source_t layer_changed_event; @@ -104,6 +108,17 @@ void stop_keyframe_animation(keyframe_animation_t* animation) { } } +void stop_all_keyframe_animations(void) { + for (int i=0;icurrent_frame = animations[i]->num_frames; + animations[i]->time_left_in_frame = 0; + animations[i]->need_update = true; + animations[i] = NULL; + } + } +} + static bool update_keyframe_animation(keyframe_animation_t* animation, visualizer_state_t* state, systime_t delta, systime_t* sleep_time) { dprintf("Animation frame%d, left %d, delta %d\n", animation->current_frame, animation->time_left_in_frame, delta); @@ -252,7 +267,19 @@ bool keyframe_display_layer_bitmap(keyframe_animation_t* animation, visualizer_s } #endif // LCD_ENABLE -bool user_visualizer_inited(keyframe_animation_t* animation, visualizer_state_t* state) { +bool keyframe_disable_lcd_and_backlight(keyframe_animation_t* animation, visualizer_state_t* state) { + (void)animation; + (void)state; + return false; +} + +bool keyframe_enable_lcd_and_backlight(keyframe_animation_t* animation, visualizer_state_t* state) { + (void)animation; + (void)state; + return false; +} + +bool enable_visualization(keyframe_animation_t* animation, visualizer_state_t* state) { (void)animation; (void)state; dprint("User visualizer inited\n"); @@ -268,13 +295,15 @@ static THD_FUNCTION(visualizerThread, arg) { event_listener_t event_listener; chEvtRegister(&layer_changed_event, &event_listener, 0); - visualizer_state_t state = { - .status = { - .default_layer = 0xFFFFFFFF, - .layer = 0xFFFFFFFF, - .leds = 0xFFFFFFFF, - }, + visualizer_keyboard_status_t initial_status = { + .default_layer = 0xFFFFFFFF, + .layer = 0xFFFFFFFF, + .leds = 0xFFFFFFFF, + .suspended = false, + }; + visualizer_state_t state = { + .status = initial_status, .current_lcd_color = 0, #ifdef LCD_ENABLE .font_fixed5x8 = gdispOpenFont("fixed_5x8"), @@ -301,17 +330,36 @@ static THD_FUNCTION(visualizerThread, arg) { bool enabled = visualizer_enabled; if (!same_status(&state.status, ¤t_status)) { if (visualizer_enabled) { - state.status = current_status; - update_user_visualizer_state(&state); - state.prev_lcd_color = state.current_lcd_color; + if (current_status.suspended) { + stop_all_keyframe_animations(); + visualizer_enabled = false; + state.status = current_status; + user_visualizer_suspend(&state); + } + else { + state.status = current_status; + update_user_visualizer_state(&state); + state.prev_lcd_color = state.current_lcd_color; + } } } + if (!enabled && state.status.suspended && current_status.suspended == false) { + // Setting the status to the initial status will force an update + // when the visualizer is enabled again + state.status = initial_status; + state.status.suspended = false; + stop_all_keyframe_animations(); + user_visualizer_resume(&state); + } sleep_time = TIME_INFINITE; for (int i=0;i MS2ST(10)) { + last_update = current_update; + visualizer_keyboard_status_t* r = begin_write_current_status(); + *r = current_status; + end_write_current_status(); + } +#endif +} + +void visualizer_update(uint32_t default_state, uint32_t state, uint32_t leds) { // Note that there's a small race condition here, the thread could read // a state where one of these are set but not the other. But this should // 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) .layer = state, .default_layer = default_state, .leds = leds, + .suspended = current_status.suspended, }; if (!same_status(¤t_status, &new_status)) { changed = true; current_status = new_status; } } - if (changed) { - chEvtBroadcast(&layer_changed_event); + update_status(changed); +} - } -#ifdef USE_SERIAL_LINK - static systime_t last_update = 0; - systime_t current_update = chVTGetSystemTimeX(); - systime_t delta = current_update - last_update; - if (changed || delta > MS2ST(10)) { - last_update = current_update; - visualizer_keyboard_status_t* r = begin_write_current_status(); - *r = current_status; - end_write_current_status(); - } -#endif +void visualizer_suspend(void) { + current_status.suspended = true; + update_status(true); +} + +void visualizer_resume(void) { + current_status.suspended = false; + update_status(true); } diff --git a/visualizer.h b/visualizer.h index b7b0a3a7..22798cda 100644 --- a/visualizer.h +++ b/visualizer.h @@ -38,8 +38,12 @@ SOFTWARE. // This need to be called once at the start void visualizer_init(void); -// This should be called before every matrix scan -void visualizer_set_state(uint32_t default_state, uint32_t state, uint32_t leds); +// This should be called at every matrix scan +void visualizer_update(uint32_t default_state, uint32_t state, uint32_t leds); +// This should be called when the keyboard goes to suspend state +void visualizer_suspend(void); +// This should be called when the keyboard wakes up from suspend state +void visualizer_resume(void); // If you need support for more than 8 keyframes per animation, you can change this #define MAX_VISUALIZER_KEY_FRAMES 8 @@ -50,6 +54,7 @@ typedef struct { uint32_t layer; uint32_t default_layer; uint32_t leds; // See led.h for available statuses + bool suspended; } visualizer_keyboard_status_t; // The state struct is used by the various keyframe functions @@ -108,13 +113,19 @@ bool keyframe_set_backlight_color(keyframe_animation_t* animation, visualizer_st bool keyframe_display_layer_text(keyframe_animation_t* animation, visualizer_state_t* state); // Displays a bitmap (0/1) of all the currently active layers bool keyframe_display_layer_bitmap(keyframe_animation_t* animation, visualizer_state_t* state); + +bool keyframe_disable_lcd_and_backlight(keyframe_animation_t* animation, visualizer_state_t* state); +bool keyframe_enable_lcd_and_backlight(keyframe_animation_t* animation, visualizer_state_t* state); + // Call this once, when the initial animation has finished, alternatively you can call it // directly from the initalize_user_visualizer function (the animation can be null) -bool user_visualizer_inited(keyframe_animation_t* animation, visualizer_state_t* state); +bool enable_visualization(keyframe_animation_t* animation, visualizer_state_t* state); // These two functions have to be implemented by the user void initialize_user_visualizer(visualizer_state_t* state); void update_user_visualizer_state(visualizer_state_t* state); +void user_visualizer_suspend(visualizer_state_t* state); +void user_visualizer_resume(visualizer_state_t* state); #endif /* VISUALIZER_H */