mirror of
				https://github.com/mfulz/qmk_firmware.git
				synced 2025-10-31 13:22:31 +01:00 
			
		
		
		
	Suspend support for the visualizer
This commit is contained in:
		
							parent
							
								
									315edb4826
								
							
						
					
					
						commit
						b93d07198a
					
				| @ -65,7 +65,7 @@ static keyframe_animation_t startup_animation = { | |||||||
|     .num_frames = 4, |     .num_frames = 4, | ||||||
|     .loop = false, |     .loop = false, | ||||||
|     .frame_lengths = {0, MS2ST(1000), MS2ST(5000), 0}, |     .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
 | // The color animation animates the LCD color when you change layers
 | ||||||
|  | |||||||
							
								
								
									
										104
									
								
								visualizer.c
									
									
									
									
									
								
							
							
						
						
									
										104
									
								
								visualizer.c
									
									
									
									
									
								
							| @ -52,10 +52,14 @@ static visualizer_keyboard_status_t current_status = { | |||||||
|     .layer = 0xFFFFFFFF, |     .layer = 0xFFFFFFFF, | ||||||
|     .default_layer = 0xFFFFFFFF, |     .default_layer = 0xFFFFFFFF, | ||||||
|     .leds = 0xFFFFFFFF, |     .leds = 0xFFFFFFFF, | ||||||
|  |     .suspended = false, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| static bool same_status(visualizer_keyboard_status_t* status1, visualizer_keyboard_status_t* status2) { | 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; | 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) { | 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, |     dprintf("Animation frame%d, left %d, delta %d\n", animation->current_frame, | ||||||
|             animation->time_left_in_frame, delta); |             animation->time_left_in_frame, delta); | ||||||
| @ -252,7 +267,19 @@ bool keyframe_display_layer_bitmap(keyframe_animation_t* animation, visualizer_s | |||||||
| } | } | ||||||
| #endif // LCD_ENABLE
 | #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)animation; | ||||||
|     (void)state; |     (void)state; | ||||||
|     dprint("User visualizer inited\n"); |     dprint("User visualizer inited\n"); | ||||||
| @ -268,13 +295,15 @@ static THD_FUNCTION(visualizerThread, arg) { | |||||||
|     event_listener_t event_listener; |     event_listener_t event_listener; | ||||||
|     chEvtRegister(&layer_changed_event, &event_listener, 0); |     chEvtRegister(&layer_changed_event, &event_listener, 0); | ||||||
| 
 | 
 | ||||||
|     visualizer_state_t state = { |     visualizer_keyboard_status_t initial_status = { | ||||||
|         .status = { |  | ||||||
|         .default_layer = 0xFFFFFFFF, |         .default_layer = 0xFFFFFFFF, | ||||||
|         .layer = 0xFFFFFFFF, |         .layer = 0xFFFFFFFF, | ||||||
|         .leds = 0xFFFFFFFF, |         .leds = 0xFFFFFFFF, | ||||||
|         }, |         .suspended = false, | ||||||
|  |     }; | ||||||
| 
 | 
 | ||||||
|  |     visualizer_state_t state = { | ||||||
|  |         .status = initial_status, | ||||||
|         .current_lcd_color = 0, |         .current_lcd_color = 0, | ||||||
| #ifdef LCD_ENABLE | #ifdef LCD_ENABLE | ||||||
|         .font_fixed5x8 = gdispOpenFont("fixed_5x8"), |         .font_fixed5x8 = gdispOpenFont("fixed_5x8"), | ||||||
| @ -301,17 +330,36 @@ static THD_FUNCTION(visualizerThread, arg) { | |||||||
|         bool enabled = visualizer_enabled; |         bool enabled = visualizer_enabled; | ||||||
|         if (!same_status(&state.status, ¤t_status)) { |         if (!same_status(&state.status, ¤t_status)) { | ||||||
|             if (visualizer_enabled) { |             if (visualizer_enabled) { | ||||||
|  |                 if (current_status.suspended) { | ||||||
|  |                     stop_all_keyframe_animations(); | ||||||
|  |                     visualizer_enabled = false; | ||||||
|  |                     state.status = current_status; | ||||||
|  |                     user_visualizer_suspend(&state); | ||||||
|  |                 } | ||||||
|  |                 else { | ||||||
|                     state.status = current_status; |                     state.status = current_status; | ||||||
|                     update_user_visualizer_state(&state); |                     update_user_visualizer_state(&state); | ||||||
|                     state.prev_lcd_color = state.current_lcd_color; |                     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; |         sleep_time = TIME_INFINITE; | ||||||
|         for (int i=0;i<MAX_SIMULTANEOUS_ANIMATIONS;i++) { |         for (int i=0;i<MAX_SIMULTANEOUS_ANIMATIONS;i++) { | ||||||
|             if (animations[i]) { |             if (animations[i]) { | ||||||
|                 update_keyframe_animation(animations[i], &state, delta, &sleep_time); |                 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) { |         if (enabled != visualizer_enabled) { | ||||||
|             sleep_time = 0; |             sleep_time = 0; | ||||||
|         } |         } | ||||||
| @ -354,7 +402,24 @@ void visualizer_init(void) { | |||||||
|                               LOWPRIO, visualizerThread, NULL); |                               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
 |     // 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
 |     // 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.
 |     // 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, |             .layer = state, | ||||||
|             .default_layer = default_state, |             .default_layer = default_state, | ||||||
|             .leds = leds, |             .leds = leds, | ||||||
|  |             .suspended = current_status.suspended, | ||||||
|         }; |         }; | ||||||
|         if (!same_status(¤t_status, &new_status)) { |         if (!same_status(¤t_status, &new_status)) { | ||||||
|             changed = true; |             changed = true; | ||||||
|             current_status = new_status; |             current_status = new_status; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     if (changed) { |     update_status(changed); | ||||||
|         chEvtBroadcast(&layer_changed_event); | } | ||||||
| 
 | 
 | ||||||
|     } | void visualizer_suspend(void) { | ||||||
| #ifdef USE_SERIAL_LINK |     current_status.suspended = true; | ||||||
|     static systime_t last_update = 0; |     update_status(true); | ||||||
|     systime_t current_update = chVTGetSystemTimeX(); | } | ||||||
|     systime_t delta = current_update - last_update; | 
 | ||||||
|     if (changed || delta > MS2ST(10)) { | void visualizer_resume(void) { | ||||||
|         last_update = current_update; |     current_status.suspended = false; | ||||||
|         visualizer_keyboard_status_t* r = begin_write_current_status(); |     update_status(true); | ||||||
|         *r = current_status; |  | ||||||
|         end_write_current_status(); |  | ||||||
|     } |  | ||||||
| #endif |  | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										17
									
								
								visualizer.h
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								visualizer.h
									
									
									
									
									
								
							| @ -38,8 +38,12 @@ SOFTWARE. | |||||||
| 
 | 
 | ||||||
| // This need to be called once at the start
 | // This need to be called once at the start
 | ||||||
| void visualizer_init(void); | void visualizer_init(void); | ||||||
| // This should be called before every matrix scan
 | // This should be called at every matrix scan
 | ||||||
| void visualizer_set_state(uint32_t default_state, uint32_t state, uint32_t leds); | 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
 | // If you need support for more than 8 keyframes per animation, you can change this
 | ||||||
| #define MAX_VISUALIZER_KEY_FRAMES 8 | #define MAX_VISUALIZER_KEY_FRAMES 8 | ||||||
| @ -50,6 +54,7 @@ typedef struct { | |||||||
|     uint32_t layer; |     uint32_t layer; | ||||||
|     uint32_t default_layer; |     uint32_t default_layer; | ||||||
|     uint32_t leds; // See led.h for available statuses
 |     uint32_t leds; // See led.h for available statuses
 | ||||||
|  |     bool suspended; | ||||||
| } visualizer_keyboard_status_t; | } visualizer_keyboard_status_t; | ||||||
| 
 | 
 | ||||||
| // The state struct is used by the various keyframe functions
 | // 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); | bool keyframe_display_layer_text(keyframe_animation_t* animation, visualizer_state_t* state); | ||||||
| // Displays a bitmap (0/1) of all the currently active layers
 | // 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_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
 | // 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)
 | // 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
 | // These two functions have to be implemented by the user
 | ||||||
| void initialize_user_visualizer(visualizer_state_t* state); | void initialize_user_visualizer(visualizer_state_t* state); | ||||||
| void update_user_visualizer_state(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 */ | #endif /* VISUALIZER_H */ | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Fred Sundvik
						Fred Sundvik