diff options
Diffstat (limited to 'quantum/visualizer/visualizer.c')
-rw-r--r-- | quantum/visualizer/visualizer.c | 104 |
1 files changed, 86 insertions, 18 deletions
diff --git a/quantum/visualizer/visualizer.c b/quantum/visualizer/visualizer.c index 605be3059..c24073405 100644 --- a/quantum/visualizer/visualizer.c +++ b/quantum/visualizer/visualizer.c @@ -23,9 +23,11 @@ SOFTWARE. */ #include "visualizer.h" -#include "ch.h" #include "config.h" #include <string.h> +#ifdef PROTOCOL_CHIBIOS +#include "ch.h" +#endif #ifdef LCD_ENABLE #include "gfx.h" @@ -68,7 +70,6 @@ static bool same_status(visualizer_keyboard_status_t* status1, visualizer_keyboa status1->suspended == status2->suspended; } -static event_source_t layer_changed_event; static bool visualizer_enabled = false; #define MAX_SIMULTANEOUS_ANIMATIONS 4 @@ -83,6 +84,18 @@ static remote_object_t* remote_objects[] = { #endif +GDisplay* LCD_DISPLAY = 0; +GDisplay* LED_DISPLAY = 0; + +__attribute__((weak)) +GDisplay* get_lcd_display(void) { + return gdispGetDisplay(0); +} + +__attribute__((weak)) +GDisplay* get_led_display(void) { + return gdispGetDisplay(1); +} void start_keyframe_animation(keyframe_animation_t* animation) { animation->current_frame = -1; @@ -106,6 +119,8 @@ void stop_keyframe_animation(keyframe_animation_t* animation) { animation->current_frame = animation->num_frames; animation->time_left_in_frame = 0; animation->need_update = true; + animation->first_update_of_frame = false; + animation->last_update_of_frame = false; for (int i=0;i<MAX_SIMULTANEOUS_ANIMATIONS;i++) { if (animations[i] == animation) { animations[i] = NULL; @@ -120,12 +135,15 @@ void stop_all_keyframe_animations(void) { animations[i]->current_frame = animations[i]->num_frames; animations[i]->time_left_in_frame = 0; animations[i]->need_update = true; + animations[i]->first_update_of_frame = false; + animations[i]->last_update_of_frame = false; 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, systemticks_t delta, systemticks_t* sleep_time) { + // TODO: Clean up this messy code dprintf("Animation frame%d, left %d, delta %d\n", animation->current_frame, animation->time_left_in_frame, delta); if (animation->current_frame == animation->num_frames) { @@ -136,16 +154,20 @@ static bool update_keyframe_animation(keyframe_animation_t* animation, visualize animation->current_frame = 0; animation->time_left_in_frame = animation->frame_lengths[0]; animation->need_update = true; + animation->first_update_of_frame = true; } else { animation->time_left_in_frame -= delta; while (animation->time_left_in_frame <= 0) { int left = animation->time_left_in_frame; if (animation->need_update) { animation->time_left_in_frame = 0; + animation->last_update_of_frame = true; (*animation->frame_functions[animation->current_frame])(animation, state); + animation->last_update_of_frame = false; } animation->current_frame++; animation->need_update = true; + animation->first_update_of_frame = true; if (animation->current_frame == animation->num_frames) { if (animation->loop) { animation->current_frame = 0; @@ -162,16 +184,32 @@ static bool update_keyframe_animation(keyframe_animation_t* animation, visualize } if (animation->need_update) { animation->need_update = (*animation->frame_functions[animation->current_frame])(animation, state); + animation->first_update_of_frame = false; } - int wanted_sleep = animation->need_update ? 10 : animation->time_left_in_frame; - if ((unsigned)wanted_sleep < *sleep_time) { + systemticks_t wanted_sleep = animation->need_update ? gfxMillisecondsToTicks(10) : (unsigned)animation->time_left_in_frame; + if (wanted_sleep < *sleep_time) { *sleep_time = wanted_sleep; } return true; } +void run_next_keyframe(keyframe_animation_t* animation, visualizer_state_t* state) { + int next_frame = animation->current_frame + 1; + if (next_frame == animation->num_frames) { + next_frame = 0; + } + keyframe_animation_t temp_animation = *animation; + temp_animation.current_frame = next_frame; + temp_animation.time_left_in_frame = animation->frame_lengths[next_frame]; + temp_animation.first_update_of_frame = true; + temp_animation.last_update_of_frame = false; + temp_animation.need_update = false; + visualizer_state_t temp_state = *state; + (*temp_animation.frame_functions[next_frame])(&temp_animation, &temp_state); +} + bool keyframe_no_operation(keyframe_animation_t* animation, visualizer_state_t* state) { (void)animation; (void)state; @@ -303,12 +341,13 @@ bool enable_visualization(keyframe_animation_t* animation, visualizer_state_t* s } // TODO: Optimize the stack size, this is probably way too big -static THD_WORKING_AREA(visualizerThreadStack, 1024); -static THD_FUNCTION(visualizerThread, arg) { +static DECLARE_THREAD_STACK(visualizerThreadStack, 1024); +static DECLARE_THREAD_FUNCTION(visualizerThread, arg) { (void)arg; - event_listener_t event_listener; - chEvtRegister(&layer_changed_event, &event_listener, 0); + GListener event_listener; + geventListenerInit(&event_listener); + geventAttachSource(&event_listener, (GSourceHandle)¤t_status, 0); visualizer_keyboard_status_t initial_status = { .default_layer = 0xFFFFFFFF, @@ -335,12 +374,12 @@ static THD_FUNCTION(visualizerThread, arg) { LCD_INT(state.current_lcd_color)); #endif - systime_t sleep_time = TIME_INFINITE; - systime_t current_time = chVTGetSystemTimeX(); + systemticks_t sleep_time = TIME_INFINITE; + systemticks_t current_time = gfxSystemTicks(); while(true) { - systime_t new_time = chVTGetSystemTimeX(); - systime_t delta = new_time - current_time; + systemticks_t new_time = gfxSystemTicks(); + systemticks_t delta = new_time - current_time; current_time = new_time; bool enabled = visualizer_enabled; if (!same_status(&state.status, ¤t_status)) { @@ -373,6 +412,13 @@ static THD_FUNCTION(visualizerThread, arg) { update_keyframe_animation(animations[i], &state, delta, &sleep_time); } } +#ifdef LED_ENABLE + gdispGFlush(LED_DISPLAY); +#endif + +#ifdef EMULATOR + draw_emulator(); +#endif // The animation can enable the visualizer // And we might need to update the state when that happens // so don't sleep @@ -380,7 +426,7 @@ static THD_FUNCTION(visualizerThread, arg) { sleep_time = 0; } - systime_t after_update = chVTGetSystemTimeX(); + systemticks_t after_update = gfxSystemTicks(); unsigned update_delta = after_update - current_time; if (sleep_time != TIME_INFINITE) { if (sleep_time > update_delta) { @@ -391,12 +437,24 @@ static THD_FUNCTION(visualizerThread, arg) { } } dprintf("Update took %d, last delta %d, sleep_time %d\n", update_delta, delta, sleep_time); - chEvtWaitOneTimeout(EVENT_MASK(0), sleep_time); +#ifdef PROTOCOL_CHIBIOS + // The gEventWait function really takes milliseconds, even if the documentation says ticks. + // Unfortunately there's no generic ugfx conversion from system time to milliseconds, + // so let's do it in a platform dependent way. + + // On windows the system ticks is the same as milliseconds anyway + if (sleep_time != TIME_INFINITE) { + sleep_time = ST2MS(sleep_time); + } +#endif + geventEventWait(&event_listener, sleep_time); } #ifdef LCD_ENABLE gdispCloseFont(state.font_fixed5x8); gdispCloseFont(state.font_dejavusansbold12); #endif + + return 0; } void visualizer_init(void) { @@ -411,16 +469,26 @@ void visualizer_init(void) { #ifdef USE_SERIAL_LINK add_remote_objects(remote_objects, sizeof(remote_objects) / sizeof(remote_object_t*) ); #endif + +#ifdef LCD_ENABLE + LCD_DISPLAY = get_lcd_display(); +#endif +#ifdef LED_ENABLE + LED_DISPLAY = get_led_display(); +#endif + // We are using a low priority thread, the idea is to have it run only // when the main thread is sleeping during the matrix scanning - chEvtObjectInit(&layer_changed_event); - (void)chThdCreateStatic(visualizerThreadStack, sizeof(visualizerThreadStack), + gfxThreadCreate(visualizerThreadStack, sizeof(visualizerThreadStack), VISUALIZER_THREAD_PRIORITY, visualizerThread, NULL); } void update_status(bool changed) { if (changed) { - chEvtBroadcast(&layer_changed_event); + GSourceListener* listener = geventGetSourceListener((GSourceHandle)¤t_status, NULL); + if (listener) { + geventSendEvent(listener); + } } #ifdef USE_SERIAL_LINK static systime_t last_update = 0; |