summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFred Sundvik <fsundvik@gmail.com>2016-03-13 17:54:45 +0200
committerFred Sundvik <fsundvik@gmail.com>2016-03-13 20:13:02 +0200
commitb93d07198a18063594a59dd193d0961622087868 (patch)
tree4978d505018cdd97cb8683511676bba0f097cf56
parent315edb48265e6baedd07f34c9e6e323d28814b4e (diff)
Suspend support for the visualizer
-rw-r--r--example_integration/visualizer_user.c2
-rw-r--r--visualizer.c114
-rw-r--r--visualizer.h17
3 files changed, 103 insertions, 30 deletions
diff --git a/example_integration/visualizer_user.c b/example_integration/visualizer_user.c
index 6c4619d954..fc09fe2eaf 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 ca7bcb7765..5b0d560ed9 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;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);
}
diff --git a/visualizer.h b/visualizer.h
index b7b0a3a7d0..22798cda6b 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 */