]> git.donarmstrong.com Git - qmk_firmware.git/commitdiff
Suspend support for the visualizer
authorFred Sundvik <fsundvik@gmail.com>
Sun, 13 Mar 2016 15:54:45 +0000 (17:54 +0200)
committerFred Sundvik <fsundvik@gmail.com>
Sun, 13 Mar 2016 18:13:02 +0000 (20:13 +0200)
example_integration/visualizer_user.c
visualizer.c
visualizer.h

index 6c4619d9540fe84c053b838ab35faf6cb0ba66fe..fc09fe2eafcdbc81d7cf432a60f93ffa6d31ef5a 100644 (file)
@@ -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
index ca7bcb77650f3a13fd1d10cd65e1747a5ff8deb1..5b0d560ed976a9890d91ef9dd97caf49b943e02e 100644 (file)
@@ -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, &current_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(&current_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);
 }
index b7b0a3a7d06593fb31d76c67aaa9b06ac14ab9e6..22798cda6befe789c80b09d5f4b4d71135985441 100644 (file)
@@ -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 */