Suspend support for the visualizer
This commit is contained in:
		
							parent
							
								
									315edb4826
								
							
						
					
					
						commit
						b93d07198a
					
				
					 3 changed files with 104 additions and 31 deletions
				
			
		|  | @ -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
 | ||||
|  |  | |||
							
								
								
									
										116
									
								
								visualizer.c
									
										
									
									
									
								
							
							
						
						
									
										116
									
								
								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;i<MAX_SIMULTANEOUS_ANIMATIONS;i++) { | ||||
|         if (animations[i]) { | ||||
|             animations[i]->current_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<MAX_SIMULTANEOUS_ANIMATIONS;i++) { | ||||
|             if (animations[i]) { | ||||
|                 update_keyframe_animation(animations[i], &state, delta, &sleep_time); | ||||
|             } | ||||
|         } | ||||
|         // The animation can enable the visualizer
 | ||||
|         // And we might need to update the state when that happens
 | ||||
|         // so don't sleep
 | ||||
|         if (enabled != visualizer_enabled) { | ||||
|             sleep_time = 0; | ||||
|         } | ||||
|  | @ -354,7 +402,24 @@ void visualizer_init(void) { | |||
|                               LOWPRIO, visualizerThread, NULL); | ||||
| } | ||||
| 
 | ||||
| void visualizer_set_state(uint32_t default_state, uint32_t state, uint32_t leds) { | ||||
| void update_status(bool changed) { | ||||
|     if (changed) { | ||||
|         chEvtBroadcast(&layer_changed_event); | ||||
|     } | ||||
| #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_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); | ||||
| 
 | ||||
|     } | ||||
| #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 | ||||
|     update_status(changed); | ||||
| } | ||||
| 
 | ||||
| void visualizer_suspend(void) { | ||||
|     current_status.suspended = true; | ||||
|     update_status(true); | ||||
| } | ||||
| 
 | ||||
| void visualizer_resume(void) { | ||||
|     current_status.suspended = false; | ||||
|     update_status(true); | ||||
| } | ||||
|  |  | |||
							
								
								
									
										17
									
								
								visualizer.h
									
										
									
									
									
								
							
							
						
						
									
										17
									
								
								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 */ | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Fred Sundvik
						Fred Sundvik