From c95b17b536b4437f001d5f5e8a54753969e36bb2 Mon Sep 17 00:00:00 2001 From: Fred Sundvik Date: Sun, 24 Apr 2016 13:46:19 +0300 Subject: [PATCH 01/23] Add simple led support Also the first version of a led testing animation --- led_test.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ led_test.h | 35 +++++++++++++++++++++++++++++++++++ visualizer.c | 8 ++++++++ visualizer.h | 3 +++ visualizer.mk | 10 ++++++++-- 5 files changed, 99 insertions(+), 2 deletions(-) create mode 100644 led_test.c create mode 100644 led_test.h diff --git a/led_test.c b/led_test.c new file mode 100644 index 000000000..1aadd5541 --- /dev/null +++ b/led_test.c @@ -0,0 +1,45 @@ +/* +The MIT License (MIT) + +Copyright (c) 2016 Fred Sundvik + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +#include "led_test.h" +#include "gfx.h" + +keyframe_animation_t led_test_animation = { + .num_frames = 1, + .loop = true, + .frame_lengths = {MS2ST(1000)}, + .frame_functions = { + keyframe_fade_in_all_leds, + }, +}; + +bool keyframe_fade_in_all_leds(keyframe_animation_t* animation, visualizer_state_t* state) { + (void)state; + int frame_length = animation->frame_lengths[animation->current_frame]; + int current_pos = frame_length - animation->time_left_in_frame; + uint8_t luma = 0x255 * current_pos / frame_length; + color_t color = LUMA2COLOR(luma); + gdispGClear(LED_DISPLAY, color); + gdispGFlush(LED_DISPLAY); + return true; +} diff --git a/led_test.h b/led_test.h new file mode 100644 index 000000000..521e05216 --- /dev/null +++ b/led_test.h @@ -0,0 +1,35 @@ +/* +The MIT License (MIT) + +Copyright (c) 2016 Fred Sundvik + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +#ifndef TMK_VISUALIZER_LED_TEST_H_ +#define TMK_VISUALIZER_LED_TEST_H_ + +#include "visualizer.h" + +bool keyframe_fade_in_all_leds(keyframe_animation_t* animation, visualizer_state_t* state); + +extern keyframe_animation_t led_test_animation; + + +#endif /* TMK_VISUALIZER_LED_TEST_H_ */ diff --git a/visualizer.c b/visualizer.c index 867a1d334..ed5c9fa2c 100644 --- a/visualizer.c +++ b/visualizer.c @@ -77,6 +77,9 @@ static remote_object_t* remote_objects[] = { #endif +GDisplay* LCDDisplay; +GDisplay* LEDDisplay; + void start_keyframe_animation(keyframe_animation_t* animation) { animation->current_frame = -1; @@ -405,6 +408,11 @@ void visualizer_init(void) { #ifdef USE_SERIAL_LINK add_remote_objects(remote_objects, sizeof(remote_objects) / sizeof(remote_object_t*) ); #endif + // TODO: Make sure these works when either of these are disabled + LCDDisplay = gdispGetDisplay(0); + LEDDisplay = gdispGetDisplay(1); + + // 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); diff --git a/visualizer.h b/visualizer.h index 22798cda6..6a72fde1f 100644 --- a/visualizer.h +++ b/visualizer.h @@ -99,6 +99,9 @@ typedef struct keyframe_animation_t { } keyframe_animation_t; +extern GDisplay* LCD_DISPLAY; +extern GDisplay* LED_DISPLAY; + void start_keyframe_animation(keyframe_animation_t* animation); void stop_keyframe_animation(keyframe_animation_t* animation); diff --git a/visualizer.mk b/visualizer.mk index 13c5d3158..96ca468e8 100644 --- a/visualizer.mk +++ b/visualizer.mk @@ -21,13 +21,14 @@ # SOFTWARE. GFXLIB = $(VISUALIZER_DIR)/ugfx +SRC += $(GFXSRC) $(VISUALIZER_DIR)/visualizer.c +UINCDIR += $(GFXINC) $(VISUALIZER_DIR) + ifdef LCD_ENABLE include $(GFXLIB)/gfx.mk UDEFS += -DLCD_ENABLE ULIBS += -lm endif -SRC += $(GFXSRC) $(VISUALIZER_DIR)/visualizer.c -UINCDIR += $(GFXINC) $(VISUALIZER_DIR) ifdef LCD_BACKLIGHT_ENABLE SRC += $(VISUALIZER_DIR)/lcd_backlight.c @@ -35,6 +36,11 @@ SRC += lcd_backlight_hal.c UDEFS += -DLCD_BACKLIGHT_ENABLE endif +ifdef LED_ENABLE +SRC += $(VISUALIZER_DIR)/led_test.c +UDEFS += -DLED_ENABLE +endif + ifndef VISUALIZER_USER VISUALIZER_USER = visualizer_user.c endif From a960a1b0066b84bbf279fbebe2d62dfee6ea3812 Mon Sep 17 00:00:00 2001 From: Fred Sundvik Date: Sun, 24 Apr 2016 14:10:01 +0300 Subject: [PATCH 02/23] Add fade out for the led test --- led_test.c | 24 +++++++++++++++++++----- led_test.h | 1 + 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/led_test.c b/led_test.c index 1aadd5541..1fba32fa0 100644 --- a/led_test.c +++ b/led_test.c @@ -25,21 +25,35 @@ SOFTWARE. #include "gfx.h" keyframe_animation_t led_test_animation = { - .num_frames = 1, + .num_frames = 3, .loop = true, - .frame_lengths = {MS2ST(1000)}, + .frame_lengths = {MS2ST(1000), MS2ST(1000), MS2ST(1000)}, .frame_functions = { keyframe_fade_in_all_leds, + keyframe_no_operation, + keyframe_fade_out_all_leds, }, }; -bool keyframe_fade_in_all_leds(keyframe_animation_t* animation, visualizer_state_t* state) { - (void)state; +static void keyframe_fade_all_leds_from_to(keyframe_animation_t* animation, uint8_t from, uint8_t to) { int frame_length = animation->frame_lengths[animation->current_frame]; int current_pos = frame_length - animation->time_left_in_frame; - uint8_t luma = 0x255 * current_pos / frame_length; + int delta = to - from; + int luma = (delta * current_pos) / frame_length; + luma += from; color_t color = LUMA2COLOR(luma); gdispGClear(LED_DISPLAY, color); gdispGFlush(LED_DISPLAY); +} + +bool keyframe_fade_in_all_leds(keyframe_animation_t* animation, visualizer_state_t* state) { + (void)state; + keyframe_fade_all_leds_from_to(animation, 0, 255); + return true; +} + +bool keyframe_fade_out_all_leds(keyframe_animation_t* animation, visualizer_state_t* state) { + (void)state; + keyframe_fade_all_leds_from_to(animation, 255, 0); return true; } diff --git a/led_test.h b/led_test.h index 521e05216..a722cd9fe 100644 --- a/led_test.h +++ b/led_test.h @@ -28,6 +28,7 @@ SOFTWARE. #include "visualizer.h" bool keyframe_fade_in_all_leds(keyframe_animation_t* animation, visualizer_state_t* state); +bool keyframe_fade_out_all_leds(keyframe_animation_t* animation, visualizer_state_t* state); extern keyframe_animation_t led_test_animation; From 0e0488623e8d8820a909a48a6c847866a65bf845 Mon Sep 17 00:00:00 2001 From: Fred Sundvik Date: Sun, 24 Apr 2016 14:54:40 +0300 Subject: [PATCH 03/23] Add left to right gradient keyframe for leds --- led_test.c | 34 ++++++++++++++++++++++++++++++++-- led_test.h | 1 + 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/led_test.c b/led_test.c index 1fba32fa0..197550fdd 100644 --- a/led_test.c +++ b/led_test.c @@ -23,15 +23,21 @@ SOFTWARE. */ #include "led_test.h" #include "gfx.h" +#include "math.h" keyframe_animation_t led_test_animation = { - .num_frames = 3, + .num_frames = 4, .loop = true, - .frame_lengths = {MS2ST(1000), MS2ST(1000), MS2ST(1000)}, + .frame_lengths = { + MS2ST(1000), + MS2ST(1000), + MS2ST(1000), + MS2ST(3000)}, .frame_functions = { keyframe_fade_in_all_leds, keyframe_no_operation, keyframe_fade_out_all_leds, + keyframe_led_left_to_right_gradient, }, }; @@ -46,6 +52,18 @@ static void keyframe_fade_all_leds_from_to(keyframe_animation_t* animation, uint gdispGFlush(LED_DISPLAY); } +// TODO: Should be customizable per keyboard +#define NUM_ROWS 7 +#define NUM_COLS 7 + +static uint8_t compute_gradient_color(float t, float index, float num) { + float d = fabs(index - t); + if (d > num / 2.0f) { + d = num - d; + } + return (uint8_t)(255.0f * d); +} + bool keyframe_fade_in_all_leds(keyframe_animation_t* animation, visualizer_state_t* state) { (void)state; keyframe_fade_all_leds_from_to(animation, 0, 255); @@ -57,3 +75,15 @@ bool keyframe_fade_out_all_leds(keyframe_animation_t* animation, visualizer_stat keyframe_fade_all_leds_from_to(animation, 255, 0); return true; } + +bool keyframe_led_left_to_right_gradient(keyframe_animation_t* animation, visualizer_state_t* state) { + (void)state; + int frame_length = animation->frame_lengths[animation->current_frame]; + int current_pos = frame_length - animation->time_left_in_frame; + float t = current_pos / frame_length; + for (int i=0; i< NUM_COLS; i++) { + uint8_t color = compute_gradient_color(t, i, NUM_COLS); + gdispGDrawLine(LED_DISPLAY, i, 0, i, NUM_ROWS - 1, LUMA2COLOR(color)); + } + return true; +} diff --git a/led_test.h b/led_test.h index a722cd9fe..03737a717 100644 --- a/led_test.h +++ b/led_test.h @@ -29,6 +29,7 @@ SOFTWARE. bool keyframe_fade_in_all_leds(keyframe_animation_t* animation, visualizer_state_t* state); bool keyframe_fade_out_all_leds(keyframe_animation_t* animation, visualizer_state_t* state); +bool keyframe_led_left_to_right_gradient(keyframe_animation_t* animation, visualizer_state_t* state); extern keyframe_animation_t led_test_animation; From 444132edd056cd52a60e3551d1f6c1a07909c040 Mon Sep 17 00:00:00 2001 From: Fred Sundvik Date: Sun, 24 Apr 2016 15:45:52 +0300 Subject: [PATCH 04/23] Add last and first update of frame for anims --- visualizer.c | 9 +++++++++ visualizer.h | 2 ++ 2 files changed, 11 insertions(+) diff --git a/visualizer.c b/visualizer.c index ed5c9fa2c..219d44cd3 100644 --- a/visualizer.c +++ b/visualizer.c @@ -103,6 +103,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;icurrent_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; } } @@ -133,16 +137,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; @@ -159,6 +167,7 @@ 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; diff --git a/visualizer.h b/visualizer.h index 6a72fde1f..82d7a71d3 100644 --- a/visualizer.h +++ b/visualizer.h @@ -95,6 +95,8 @@ typedef struct keyframe_animation_t { // keyframe update functions int current_frame; int time_left_in_frame; + bool first_update_of_frame; + bool last_update_of_frame; bool need_update; } keyframe_animation_t; From 891edbd533acdffec66416c59f4b6066e5e18aaa Mon Sep 17 00:00:00 2001 From: Fred Sundvik Date: Sun, 24 Apr 2016 16:19:31 +0300 Subject: [PATCH 05/23] Add function for running the next keyframe --- visualizer.c | 15 +++++++++++++++ visualizer.h | 3 +++ 2 files changed, 18 insertions(+) diff --git a/visualizer.c b/visualizer.c index 219d44cd3..2ec6e34f5 100644 --- a/visualizer.c +++ b/visualizer.c @@ -178,6 +178,21 @@ static bool update_keyframe_animation(keyframe_animation_t* animation, visualize 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; diff --git a/visualizer.h b/visualizer.h index 82d7a71d3..5375e0130 100644 --- a/visualizer.h +++ b/visualizer.h @@ -106,6 +106,9 @@ extern GDisplay* LED_DISPLAY; void start_keyframe_animation(keyframe_animation_t* animation); void stop_keyframe_animation(keyframe_animation_t* animation); +// This runs the next keyframe, but does not update the animation state +// Useful for crossfades for example +void run_next_keyframe(keyframe_animation_t* animation, visualizer_state_t* state); // Some predefined keyframe functions that can be used by the user code // Does nothing, useful for adding delays From 0530ebb77d6961a7edc14f3a5b943165a8b52497 Mon Sep 17 00:00:00 2001 From: Fred Sundvik Date: Sun, 24 Apr 2016 16:20:00 +0300 Subject: [PATCH 06/23] Add led crossfading --- led_test.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++----- led_test.h | 2 ++ 2 files changed, 64 insertions(+), 6 deletions(-) diff --git a/led_test.c b/led_test.c index 197550fdd..8c0de604a 100644 --- a/led_test.c +++ b/led_test.c @@ -26,27 +26,41 @@ SOFTWARE. #include "math.h" keyframe_animation_t led_test_animation = { - .num_frames = 4, + .num_frames = 8, .loop = true, .frame_lengths = { - MS2ST(1000), - MS2ST(1000), - MS2ST(1000), - MS2ST(3000)}, + MS2ST(1000), // fade in + MS2ST(1000), // no op (leds on) + MS2ST(1000), // fade out + MS2ST(1000), // crossfade + MS2ST(3000), // left to rigt + MS2ST(1000), // crossfade + MS2ST(3000), // top_to_bottom + MS2ST(1000), // crossfade + }, .frame_functions = { keyframe_fade_in_all_leds, keyframe_no_operation, keyframe_fade_out_all_leds, + keyframe_led_crossfade, keyframe_led_left_to_right_gradient, + keyframe_led_crossfade, + keyframe_led_top_to_bottom_gradient, + keyframe_led_crossfade }, }; -static void keyframe_fade_all_leds_from_to(keyframe_animation_t* animation, uint8_t from, uint8_t to) { +static uint8_t fade_led_color(keyframe_animation_t* animation, uint8_t from, uint8_t to) { int frame_length = animation->frame_lengths[animation->current_frame]; int current_pos = frame_length - animation->time_left_in_frame; int delta = to - from; int luma = (delta * current_pos) / frame_length; luma += from; + return luma; +} + +static void keyframe_fade_all_leds_from_to(keyframe_animation_t* animation, uint8_t from, uint8_t to) { + uint8_t luma = fade_led_color(animation, from, to); color_t color = LUMA2COLOR(luma); gdispGClear(LED_DISPLAY, color); gdispGFlush(LED_DISPLAY); @@ -56,6 +70,9 @@ static void keyframe_fade_all_leds_from_to(keyframe_animation_t* animation, uint #define NUM_ROWS 7 #define NUM_COLS 7 +static uint8_t crossfade_start_frame[NUM_ROWS][NUM_COLS]; +static uint8_t crossfade_end_frame[NUM_ROWS][NUM_COLS]; + static uint8_t compute_gradient_color(float t, float index, float num) { float d = fabs(index - t); if (d > num / 2.0f) { @@ -85,5 +102,44 @@ bool keyframe_led_left_to_right_gradient(keyframe_animation_t* animation, visual uint8_t color = compute_gradient_color(t, i, NUM_COLS); gdispGDrawLine(LED_DISPLAY, i, 0, i, NUM_ROWS - 1, LUMA2COLOR(color)); } + gdispGFlush(LED_DISPLAY); + return true; +} + +bool keyframe_led_top_to_bottom_gradient(keyframe_animation_t* animation, visualizer_state_t* state) { + (void)state; + int frame_length = animation->frame_lengths[animation->current_frame]; + int current_pos = frame_length - animation->time_left_in_frame; + float t = current_pos / frame_length; + for (int i=0; i< NUM_ROWS; i++) { + uint8_t color = compute_gradient_color(t, i, NUM_ROWS); + gdispGDrawLine(LED_DISPLAY, 0, i, NUM_COLS - 1, i, LUMA2COLOR(color)); + } + gdispGFlush(LED_DISPLAY); + return true; +} + +static void copy_current_led_state(uint8_t* dest) { + for (int i=0;ifirst_update_of_frame) { + copy_current_led_state(&crossfade_start_frame[0][0]); + run_next_keyframe(animation, state); + copy_current_led_state(&crossfade_end_frame[0][0]); + } + for (int i=0;i Date: Sun, 24 Apr 2016 16:26:53 +0300 Subject: [PATCH 07/23] LEDS are flushed automatically After running the animation, instead of having to do it manually. This avoids duplicate flushing, and better support for cross-fades. --- led_test.c | 4 ---- visualizer.c | 4 ++++ 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/led_test.c b/led_test.c index 8c0de604a..c987eca38 100644 --- a/led_test.c +++ b/led_test.c @@ -63,7 +63,6 @@ static void keyframe_fade_all_leds_from_to(keyframe_animation_t* animation, uint uint8_t luma = fade_led_color(animation, from, to); color_t color = LUMA2COLOR(luma); gdispGClear(LED_DISPLAY, color); - gdispGFlush(LED_DISPLAY); } // TODO: Should be customizable per keyboard @@ -102,7 +101,6 @@ bool keyframe_led_left_to_right_gradient(keyframe_animation_t* animation, visual uint8_t color = compute_gradient_color(t, i, NUM_COLS); gdispGDrawLine(LED_DISPLAY, i, 0, i, NUM_ROWS - 1, LUMA2COLOR(color)); } - gdispGFlush(LED_DISPLAY); return true; } @@ -115,7 +113,6 @@ bool keyframe_led_top_to_bottom_gradient(keyframe_animation_t* animation, visual uint8_t color = compute_gradient_color(t, i, NUM_ROWS); gdispGDrawLine(LED_DISPLAY, 0, i, NUM_COLS - 1, i, LUMA2COLOR(color)); } - gdispGFlush(LED_DISPLAY); return true; } @@ -140,6 +137,5 @@ bool keyframe_led_crossfade(keyframe_animation_t* animation, visualizer_state_t* gdispGDrawPixel(LED_DISPLAY, j, i, color); } } - gdispGFlush(LED_DISPLAY); return true; } diff --git a/visualizer.c b/visualizer.c index 2ec6e34f5..81ec8298f 100644 --- a/visualizer.c +++ b/visualizer.c @@ -127,6 +127,7 @@ void stop_all_keyframe_animations(void) { } static bool update_keyframe_animation(keyframe_animation_t* animation, visualizer_state_t* state, systime_t delta, systime_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) { @@ -394,6 +395,9 @@ static THD_FUNCTION(visualizerThread, arg) { update_keyframe_animation(animations[i], &state, delta, &sleep_time); } } +#ifdef LED_ENABLE + gdispGFlush(LED_DISPLAY); +#endif // The animation can enable the visualizer // And we might need to update the state when that happens // so don't sleep From 74baa4895c8efd409eb10eaf1e6cfc0e2677b45c Mon Sep 17 00:00:00 2001 From: Fred Sundvik Date: Sun, 24 Apr 2016 16:40:41 +0300 Subject: [PATCH 08/23] Run mirrored keyframes for led tests as well --- led_test.c | 34 ++++++++++++++++++++++++++++++---- led_test.h | 2 ++ visualizer.h | 4 ++-- 3 files changed, 34 insertions(+), 6 deletions(-) diff --git a/led_test.c b/led_test.c index c987eca38..ce6c2e68e 100644 --- a/led_test.c +++ b/led_test.c @@ -26,17 +26,24 @@ SOFTWARE. #include "math.h" keyframe_animation_t led_test_animation = { - .num_frames = 8, + .num_frames = 14, .loop = true, .frame_lengths = { MS2ST(1000), // fade in MS2ST(1000), // no op (leds on) MS2ST(1000), // fade out MS2ST(1000), // crossfade - MS2ST(3000), // left to rigt + MS2ST(3000), // left to rigt (outside in) MS2ST(1000), // crossfade MS2ST(3000), // top_to_bottom + 0, // mirror leds MS2ST(1000), // crossfade + MS2ST(3000), // left_to_right (mirrored, so inside out) + MS2ST(1000), // crossfade + MS2ST(3000), // top_to_bottom + 0, // normal leds + MS2ST(1000), // crossfade + }, .frame_functions = { keyframe_fade_in_all_leds, @@ -46,7 +53,13 @@ keyframe_animation_t led_test_animation = { keyframe_led_left_to_right_gradient, keyframe_led_crossfade, keyframe_led_top_to_bottom_gradient, - keyframe_led_crossfade + keyframe_mirror_led_orientation, + keyframe_led_crossfade, + keyframe_led_left_to_right_gradient, + keyframe_led_crossfade, + keyframe_led_top_to_bottom_gradient, + keyframe_normal_led_orientation, + keyframe_led_crossfade, }, }; @@ -123,7 +136,6 @@ static void copy_current_led_state(uint8_t* dest) { } } } - bool keyframe_led_crossfade(keyframe_animation_t* animation, visualizer_state_t* state) { (void)state; if (animation->first_update_of_frame) { @@ -139,3 +151,17 @@ bool keyframe_led_crossfade(keyframe_animation_t* animation, visualizer_state_t* } return true; } + +bool keyframe_mirror_led_orientation(keyframe_animation_t* animation, visualizer_state_t* state) { + (void)state; + (void)animation; + gdispGSetOrientation(LED_DISPLAY, GDISP_ROTATE_180); + return true; +} + +bool keyframe_normal_led_orientation(keyframe_animation_t* animation, visualizer_state_t* state) { + (void)state; + (void)animation; + gdispGSetOrientation(LED_DISPLAY, GDISP_ROTATE_0); + return true; +} diff --git a/led_test.h b/led_test.h index e14b25e79..5e2325753 100644 --- a/led_test.h +++ b/led_test.h @@ -32,6 +32,8 @@ bool keyframe_fade_out_all_leds(keyframe_animation_t* animation, visualizer_stat bool keyframe_led_left_to_right_gradient(keyframe_animation_t* animation, visualizer_state_t* state); bool keyframe_led_top_to_bottom_gradient(keyframe_animation_t* animation, visualizer_state_t* state); bool keyframe_led_crossfade(keyframe_animation_t* animation, visualizer_state_t* state); +bool keyframe_mirror_led_orientation(keyframe_animation_t* animation, visualizer_state_t* state); +bool keyframe_normal_led_orientation(keyframe_animation_t* animation, visualizer_state_t* state); extern keyframe_animation_t led_test_animation; diff --git a/visualizer.h b/visualizer.h index 5375e0130..8a2772c6d 100644 --- a/visualizer.h +++ b/visualizer.h @@ -45,8 +45,8 @@ 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 +// If you need support for more than 16 keyframes per animation, you can change this +#define MAX_VISUALIZER_KEY_FRAMES 16 struct keyframe_animation_t; From 6313cfd5597ffce0c70a472aa87ed68b6daa4419 Mon Sep 17 00:00:00 2001 From: Fred Sundvik Date: Sun, 24 Apr 2016 17:44:11 +0300 Subject: [PATCH 09/23] Fix some makefile issues, and symbol issues --- visualizer.c | 8 ++++---- visualizer.mk | 10 ++++++++-- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/visualizer.c b/visualizer.c index 81ec8298f..0684a26d8 100644 --- a/visualizer.c +++ b/visualizer.c @@ -77,8 +77,8 @@ static remote_object_t* remote_objects[] = { #endif -GDisplay* LCDDisplay; -GDisplay* LEDDisplay; +GDisplay* LCD_DISPLAY = 0; +GDisplay* LED_DISPLAY = 0; void start_keyframe_animation(keyframe_animation_t* animation) { @@ -437,8 +437,8 @@ void visualizer_init(void) { add_remote_objects(remote_objects, sizeof(remote_objects) / sizeof(remote_object_t*) ); #endif // TODO: Make sure these works when either of these are disabled - LCDDisplay = gdispGetDisplay(0); - LEDDisplay = gdispGetDisplay(1); + LCD_DISPLAY = gdispGetDisplay(0); + LED_DISPLAY = gdispGetDisplay(1); // We are using a low priority thread, the idea is to have it run only diff --git a/visualizer.mk b/visualizer.mk index 96ca468e8..5cc199cf4 100644 --- a/visualizer.mk +++ b/visualizer.mk @@ -21,13 +21,13 @@ # SOFTWARE. GFXLIB = $(VISUALIZER_DIR)/ugfx -SRC += $(GFXSRC) $(VISUALIZER_DIR)/visualizer.c +SRC += $(VISUALIZER_DIR)/visualizer.c UINCDIR += $(GFXINC) $(VISUALIZER_DIR) ifdef LCD_ENABLE -include $(GFXLIB)/gfx.mk UDEFS += -DLCD_ENABLE ULIBS += -lm +USE_UGFX = yes endif ifdef LCD_BACKLIGHT_ENABLE @@ -39,6 +39,12 @@ endif ifdef LED_ENABLE SRC += $(VISUALIZER_DIR)/led_test.c UDEFS += -DLED_ENABLE +USE_UGFX = yes +endif + +ifdef USE_UGFX +include $(GFXLIB)/gfx.mk +SRC += $(GFXSRC) endif ifndef VISUALIZER_USER From f0c8e7c495af2aad476f4c428b700ed26188a8e5 Mon Sep 17 00:00:00 2001 From: Fred Sundvik Date: Sat, 30 Apr 2016 22:45:41 +0300 Subject: [PATCH 10/23] Fix a few led test animation issues --- led_test.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/led_test.c b/led_test.c index ce6c2e68e..ed65a0baa 100644 --- a/led_test.c +++ b/led_test.c @@ -63,7 +63,7 @@ keyframe_animation_t led_test_animation = { }, }; -static uint8_t fade_led_color(keyframe_animation_t* animation, uint8_t from, uint8_t to) { +static uint8_t fade_led_color(keyframe_animation_t* animation, int from, int to) { int frame_length = animation->frame_lengths[animation->current_frame]; int current_pos = frame_length - animation->time_left_in_frame; int delta = to - from; @@ -107,8 +107,8 @@ bool keyframe_fade_out_all_leds(keyframe_animation_t* animation, visualizer_stat bool keyframe_led_left_to_right_gradient(keyframe_animation_t* animation, visualizer_state_t* state) { (void)state; - int frame_length = animation->frame_lengths[animation->current_frame]; - int current_pos = frame_length - animation->time_left_in_frame; + float frame_length = animation->frame_lengths[animation->current_frame]; + float current_pos = frame_length - animation->time_left_in_frame; float t = current_pos / frame_length; for (int i=0; i< NUM_COLS; i++) { uint8_t color = compute_gradient_color(t, i, NUM_COLS); @@ -119,8 +119,8 @@ bool keyframe_led_left_to_right_gradient(keyframe_animation_t* animation, visual bool keyframe_led_top_to_bottom_gradient(keyframe_animation_t* animation, visualizer_state_t* state) { (void)state; - int frame_length = animation->frame_lengths[animation->current_frame]; - int current_pos = frame_length - animation->time_left_in_frame; + float frame_length = animation->frame_lengths[animation->current_frame]; + float current_pos = frame_length - animation->time_left_in_frame; float t = current_pos / frame_length; for (int i=0; i< NUM_ROWS; i++) { uint8_t color = compute_gradient_color(t, i, NUM_ROWS); @@ -156,12 +156,12 @@ bool keyframe_mirror_led_orientation(keyframe_animation_t* animation, visualizer (void)state; (void)animation; gdispGSetOrientation(LED_DISPLAY, GDISP_ROTATE_180); - return true; + return false; } bool keyframe_normal_led_orientation(keyframe_animation_t* animation, visualizer_state_t* state) { (void)state; (void)animation; gdispGSetOrientation(LED_DISPLAY, GDISP_ROTATE_0); - return true; + return false; } From 25382cb6f21b6136b0f490a618ce8d494ca5cd38 Mon Sep 17 00:00:00 2001 From: Fred Sundvik Date: Wed, 11 May 2016 22:06:26 +0300 Subject: [PATCH 11/23] Fix compute_gradient_color --- led_test.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/led_test.c b/led_test.c index ed65a0baa..d358ef81e 100644 --- a/led_test.c +++ b/led_test.c @@ -86,10 +86,13 @@ static uint8_t crossfade_start_frame[NUM_ROWS][NUM_COLS]; static uint8_t crossfade_end_frame[NUM_ROWS][NUM_COLS]; static uint8_t compute_gradient_color(float t, float index, float num) { - float d = fabs(index - t); - if (d > num / 2.0f) { + const float target = t * (num - 1.0f); + const float half_num = num / 2.0f; + float d = fabs(index - target); + if (d > half_num) { d = num - d; } + d = 1.0f - (d / half_num); return (uint8_t)(255.0f * d); } From 15bdef3ee92e6809ec5d0f25901f4a490cd91b58 Mon Sep 17 00:00:00 2001 From: Fred Sundvik Date: Mon, 16 May 2016 09:45:39 +0300 Subject: [PATCH 12/23] Makefile changes to support emulator build --- ugfx | 2 +- visualizer.mk | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ugfx b/ugfx index e221a6906..314a066d1 160000 --- a/ugfx +++ b/ugfx @@ -1 +1 @@ -Subproject commit e221a690616e20f87e0b0088baffdbd5427be862 +Subproject commit 314a066d11f09d295d42054a0b53fa1a95c0ba0a diff --git a/visualizer.mk b/visualizer.mk index 5cc199cf4..c51f8ba5d 100644 --- a/visualizer.mk +++ b/visualizer.mk @@ -21,7 +21,9 @@ # SOFTWARE. GFXLIB = $(VISUALIZER_DIR)/ugfx +ifndef EMULATOR SRC += $(VISUALIZER_DIR)/visualizer.c +endif UINCDIR += $(GFXINC) $(VISUALIZER_DIR) ifdef LCD_ENABLE @@ -45,9 +47,13 @@ endif ifdef USE_UGFX include $(GFXLIB)/gfx.mk SRC += $(GFXSRC) +UDEFS += $(patsubst %,-D%,$(patsubst -D%,%,$(GFXDEFS))) +ULIBS += $(patsubst %,-l%,$(patsubst -l%,%,$(GFXLIBS))) endif ifndef VISUALIZER_USER +ifndef EMULATOR VISUALIZER_USER = visualizer_user.c endif +endif SRC += $(VISUALIZER_USER) \ No newline at end of file From d79e94adb1182ae867df0cc7621ef3d44d213bbc Mon Sep 17 00:00:00 2001 From: Fred Sundvik Date: Tue, 17 May 2016 09:35:02 +0300 Subject: [PATCH 13/23] Use ugfx API instead of chibios --- ugfx | 2 +- visualizer.c | 34 ++++++++++++++++++---------------- visualizer.mk | 12 +++++++++--- 3 files changed, 28 insertions(+), 20 deletions(-) diff --git a/ugfx b/ugfx index 314a066d1..7d7eeef0a 160000 --- a/ugfx +++ b/ugfx @@ -1 +1 @@ -Subproject commit 314a066d11f09d295d42054a0b53fa1a95c0ba0a +Subproject commit 7d7eeef0ad0f1b28f4fb86ad931cb6774c7b9e81 diff --git a/visualizer.c b/visualizer.c index 579837edc..ea84546fb 100644 --- a/visualizer.c +++ b/visualizer.c @@ -23,7 +23,6 @@ SOFTWARE. */ #include "visualizer.h" -#include "ch.h" #include "config.h" #include @@ -68,7 +67,7 @@ static bool same_status(visualizer_keyboard_status_t* status1, visualizer_keyboa status1->suspended == status2->suspended; } -static event_source_t layer_changed_event; +static GSourceHandle layer_changed_event; static bool visualizer_enabled = false; #define MAX_SIMULTANEOUS_ANIMATIONS 4 @@ -132,7 +131,7 @@ void stop_all_keyframe_animations(void) { } } -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); @@ -331,12 +330,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, layer_changed_event, 0); visualizer_keyboard_status_t initial_status = { .default_layer = 0xFFFFFFFF, @@ -363,12 +363,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)) { @@ -411,7 +411,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) { @@ -422,12 +422,14 @@ 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); + geventEventWait(&event_listener, sleep_time); } #ifdef LCD_ENABLE gdispCloseFont(state.font_fixed5x8); gdispCloseFont(state.font_dejavusansbold12); #endif + + return 0; } void visualizer_init(void) { @@ -449,14 +451,14 @@ void visualizer_init(void) { // 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(layer_changed_event, NULL); + geventSendEvent(listener); } #ifdef USE_SERIAL_LINK static systime_t last_update = 0; diff --git a/visualizer.mk b/visualizer.mk index c51f8ba5d..678829329 100644 --- a/visualizer.mk +++ b/visualizer.mk @@ -21,9 +21,7 @@ # SOFTWARE. GFXLIB = $(VISUALIZER_DIR)/ugfx -ifndef EMULATOR SRC += $(VISUALIZER_DIR)/visualizer.c -endif UINCDIR += $(GFXINC) $(VISUALIZER_DIR) ifdef LCD_ENABLE @@ -33,13 +31,17 @@ USE_UGFX = yes endif ifdef LCD_BACKLIGHT_ENABLE +ifndef EMULATOR SRC += $(VISUALIZER_DIR)/lcd_backlight.c SRC += lcd_backlight_hal.c +endif UDEFS += -DLCD_BACKLIGHT_ENABLE endif ifdef LED_ENABLE +ifndef EMULATOR SRC += $(VISUALIZER_DIR)/led_test.c +endif UDEFS += -DLED_ENABLE USE_UGFX = yes endif @@ -56,4 +58,8 @@ ifndef EMULATOR VISUALIZER_USER = visualizer_user.c endif endif -SRC += $(VISUALIZER_USER) \ No newline at end of file +SRC += $(VISUALIZER_USER) + +ifdef EMULATOR +UINCDIR += $(TMK_DIR)/common +endif \ No newline at end of file From 4e89732617454a600189242d417f5e2ba0855683 Mon Sep 17 00:00:00 2001 From: Fred Sundvik Date: Tue, 17 May 2016 09:45:05 +0300 Subject: [PATCH 14/23] Enable and fix compilation of more files --- led_test.c | 24 ++++++++++++------------ visualizer.mk | 6 +----- 2 files changed, 13 insertions(+), 17 deletions(-) diff --git a/led_test.c b/led_test.c index d358ef81e..6d3f3b2ed 100644 --- a/led_test.c +++ b/led_test.c @@ -29,20 +29,20 @@ keyframe_animation_t led_test_animation = { .num_frames = 14, .loop = true, .frame_lengths = { - MS2ST(1000), // fade in - MS2ST(1000), // no op (leds on) - MS2ST(1000), // fade out - MS2ST(1000), // crossfade - MS2ST(3000), // left to rigt (outside in) - MS2ST(1000), // crossfade - MS2ST(3000), // top_to_bottom + gfxMillisecondsToTicks(1000), // fade in + gfxMillisecondsToTicks(1000), // no op (leds on) + gfxMillisecondsToTicks(1000), // fade out + gfxMillisecondsToTicks(1000), // crossfade + gfxMillisecondsToTicks(3000), // left to rigt (outside in) + gfxMillisecondsToTicks(1000), // crossfade + gfxMillisecondsToTicks(3000), // top_to_bottom 0, // mirror leds - MS2ST(1000), // crossfade - MS2ST(3000), // left_to_right (mirrored, so inside out) - MS2ST(1000), // crossfade - MS2ST(3000), // top_to_bottom + gfxMillisecondsToTicks(1000), // crossfade + gfxMillisecondsToTicks(3000), // left_to_right (mirrored, so inside out) + gfxMillisecondsToTicks(1000), // crossfade + gfxMillisecondsToTicks(3000), // top_to_bottom 0, // normal leds - MS2ST(1000), // crossfade + gfxMillisecondsToTicks(1000), // crossfade }, .frame_functions = { diff --git a/visualizer.mk b/visualizer.mk index 678829329..56525ffd9 100644 --- a/visualizer.mk +++ b/visualizer.mk @@ -31,17 +31,15 @@ USE_UGFX = yes endif ifdef LCD_BACKLIGHT_ENABLE -ifndef EMULATOR SRC += $(VISUALIZER_DIR)/lcd_backlight.c +ifndef EMULATOR SRC += lcd_backlight_hal.c endif UDEFS += -DLCD_BACKLIGHT_ENABLE endif ifdef LED_ENABLE -ifndef EMULATOR SRC += $(VISUALIZER_DIR)/led_test.c -endif UDEFS += -DLED_ENABLE USE_UGFX = yes endif @@ -54,10 +52,8 @@ ULIBS += $(patsubst %,-l%,$(patsubst -l%,%,$(GFXLIBS))) endif ifndef VISUALIZER_USER -ifndef EMULATOR VISUALIZER_USER = visualizer_user.c endif -endif SRC += $(VISUALIZER_USER) ifdef EMULATOR From 15300cb681f74672547aa5e53d165ac748d43a17 Mon Sep 17 00:00:00 2001 From: Fred Sundvik Date: Tue, 17 May 2016 09:51:27 +0300 Subject: [PATCH 15/23] Build lcd_backlight_hal_emulator.c When the emulator is set, instead of the lcd_backlight_hal.c file. --- visualizer.mk | 2 ++ 1 file changed, 2 insertions(+) diff --git a/visualizer.mk b/visualizer.mk index 56525ffd9..3e361491c 100644 --- a/visualizer.mk +++ b/visualizer.mk @@ -34,6 +34,8 @@ ifdef LCD_BACKLIGHT_ENABLE SRC += $(VISUALIZER_DIR)/lcd_backlight.c ifndef EMULATOR SRC += lcd_backlight_hal.c +else +SRC += lcd_backlight_hal_emulator.c endif UDEFS += -DLCD_BACKLIGHT_ENABLE endif From 07e412c53829c66e948eb147873a04cd27b0771b Mon Sep 17 00:00:00 2001 From: Fred Sundvik Date: Tue, 17 May 2016 11:21:38 +0300 Subject: [PATCH 16/23] Fix crash when event listener not created --- visualizer.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/visualizer.c b/visualizer.c index ea84546fb..ff99e960f 100644 --- a/visualizer.c +++ b/visualizer.c @@ -458,7 +458,9 @@ void visualizer_init(void) { void update_status(bool changed) { if (changed) { GSourceListener* listener = geventGetSourceListener(layer_changed_event, NULL); - geventSendEvent(listener); + if (listener) { + geventSendEvent(listener); + } } #ifdef USE_SERIAL_LINK static systime_t last_update = 0; From fa8feb21a4709dba552df4a96205c50a319f5e3b Mon Sep 17 00:00:00 2001 From: Fred Sundvik Date: Wed, 18 May 2016 08:40:36 +0300 Subject: [PATCH 17/23] Add custom led and lcd display support --- visualizer.c | 18 +++++++++++++++--- visualizer.h | 5 +++++ 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/visualizer.c b/visualizer.c index ff99e960f..bbb00debc 100644 --- a/visualizer.c +++ b/visualizer.c @@ -85,6 +85,15 @@ static remote_object_t* remote_objects[] = { 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; @@ -444,10 +453,13 @@ void visualizer_init(void) { #ifdef USE_SERIAL_LINK add_remote_objects(remote_objects, sizeof(remote_objects) / sizeof(remote_object_t*) ); #endif - // TODO: Make sure these works when either of these are disabled - LCD_DISPLAY = gdispGetDisplay(0); - LED_DISPLAY = gdispGetDisplay(1); +#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 diff --git a/visualizer.h b/visualizer.h index 8a2772c6d..4d6a61dda 100644 --- a/visualizer.h +++ b/visualizer.h @@ -45,6 +45,11 @@ void visualizer_suspend(void); // This should be called when the keyboard wakes up from suspend state void visualizer_resume(void); +// These functions are week, so they can be overridden by the keyboard +// if needed +GDisplay* get_lcd_display(void); +GDisplay* get_led_display(void); + // If you need support for more than 16 keyframes per animation, you can change this #define MAX_VISUALIZER_KEY_FRAMES 16 From 94519e387a85e3b4ab72bd7d837ff590cc690eb9 Mon Sep 17 00:00:00 2001 From: Fred Sundvik Date: Wed, 18 May 2016 09:03:42 +0300 Subject: [PATCH 18/23] Add callback function for emulator drawing --- visualizer.c | 4 ++++ visualizer.h | 7 ++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/visualizer.c b/visualizer.c index bbb00debc..607a64566 100644 --- a/visualizer.c +++ b/visualizer.c @@ -413,6 +413,10 @@ static DECLARE_THREAD_FUNCTION(visualizerThread, arg) { #ifdef LED_ENABLE gdispGFlush(LED_DISPLAY); #endif + +#if 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 diff --git a/visualizer.h b/visualizer.h index 4d6a61dda..a3828e35f 100644 --- a/visualizer.h +++ b/visualizer.h @@ -50,6 +50,11 @@ void visualizer_resume(void); GDisplay* get_lcd_display(void); GDisplay* get_led_display(void); +// For emulator builds, this function need to be implemented +#if EMULATOR +void draw_emulator(void); +#endif + // If you need support for more than 16 keyframes per animation, you can change this #define MAX_VISUALIZER_KEY_FRAMES 16 @@ -134,7 +139,7 @@ bool keyframe_enable_lcd_and_backlight(keyframe_animation_t* animation, visualiz // directly from the initalize_user_visualizer function (the animation can be null) bool enable_visualization(keyframe_animation_t* animation, visualizer_state_t* state); -// These two functions have to be implemented by the user +// These 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); From 4d7e4a4780bc779a3960497a9084ef6c9d6ef87e Mon Sep 17 00:00:00 2001 From: Fred Sundvik Date: Sat, 28 May 2016 11:13:08 +0300 Subject: [PATCH 19/23] Don't include lcd_backlight_hal for emulator --- visualizer.mk | 2 -- 1 file changed, 2 deletions(-) diff --git a/visualizer.mk b/visualizer.mk index 3e361491c..56525ffd9 100644 --- a/visualizer.mk +++ b/visualizer.mk @@ -34,8 +34,6 @@ ifdef LCD_BACKLIGHT_ENABLE SRC += $(VISUALIZER_DIR)/lcd_backlight.c ifndef EMULATOR SRC += lcd_backlight_hal.c -else -SRC += lcd_backlight_hal_emulator.c endif UDEFS += -DLCD_BACKLIGHT_ENABLE endif From 9c955145f50abebcbe5ad5e203a91ca83249fee6 Mon Sep 17 00:00:00 2001 From: Fred Sundvik Date: Sun, 29 May 2016 02:08:46 +0300 Subject: [PATCH 20/23] Fix emulator #ifdef check --- visualizer.c | 2 +- visualizer.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/visualizer.c b/visualizer.c index 607a64566..0e587221f 100644 --- a/visualizer.c +++ b/visualizer.c @@ -414,7 +414,7 @@ static DECLARE_THREAD_FUNCTION(visualizerThread, arg) { gdispGFlush(LED_DISPLAY); #endif -#if EMULATOR +#ifdef EMULATOR draw_emulator(); #endif // The animation can enable the visualizer diff --git a/visualizer.h b/visualizer.h index a3828e35f..45cfa9aa9 100644 --- a/visualizer.h +++ b/visualizer.h @@ -51,7 +51,7 @@ GDisplay* get_lcd_display(void); GDisplay* get_led_display(void); // For emulator builds, this function need to be implemented -#if EMULATOR +#ifdef EMULATOR void draw_emulator(void); #endif From 0c3189055f049e6023471e75139d488b288aead9 Mon Sep 17 00:00:00 2001 From: Fred Sundvik Date: Sun, 29 May 2016 17:42:32 +0300 Subject: [PATCH 21/23] Make LED visualization times configurable --- led_test.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/led_test.c b/led_test.c index 6d3f3b2ed..d53f0b7fb 100644 --- a/led_test.c +++ b/led_test.c @@ -25,6 +25,9 @@ SOFTWARE. #include "gfx.h" #include "math.h" +#define CROSSFADE_TIME 1000 +#define GRADIENT_TIME 3000 + keyframe_animation_t led_test_animation = { .num_frames = 14, .loop = true, @@ -32,17 +35,17 @@ keyframe_animation_t led_test_animation = { gfxMillisecondsToTicks(1000), // fade in gfxMillisecondsToTicks(1000), // no op (leds on) gfxMillisecondsToTicks(1000), // fade out - gfxMillisecondsToTicks(1000), // crossfade - gfxMillisecondsToTicks(3000), // left to rigt (outside in) - gfxMillisecondsToTicks(1000), // crossfade - gfxMillisecondsToTicks(3000), // top_to_bottom + gfxMillisecondsToTicks(CROSSFADE_TIME), // crossfade + gfxMillisecondsToTicks(GRADIENT_TIME), // left to rigt (outside in) + gfxMillisecondsToTicks(CROSSFADE_TIME), // crossfade + gfxMillisecondsToTicks(GRADIENT_TIME), // top_to_bottom 0, // mirror leds - gfxMillisecondsToTicks(1000), // crossfade - gfxMillisecondsToTicks(3000), // left_to_right (mirrored, so inside out) - gfxMillisecondsToTicks(1000), // crossfade - gfxMillisecondsToTicks(3000), // top_to_bottom + gfxMillisecondsToTicks(CROSSFADE_TIME), // crossfade + gfxMillisecondsToTicks(GRADIENT_TIME), // left_to_right (mirrored, so inside out) + gfxMillisecondsToTicks(CROSSFADE_TIME), // crossfade + gfxMillisecondsToTicks(GRADIENT_TIME), // top_to_bottom 0, // normal leds - gfxMillisecondsToTicks(1000), // crossfade + gfxMillisecondsToTicks(CROSSFADE_TIME), // crossfade }, .frame_functions = { From 489288f67462e0c6fae8e54644af2fa4593e4406 Mon Sep 17 00:00:00 2001 From: Fred Sundvik Date: Sun, 29 May 2016 18:27:32 +0300 Subject: [PATCH 22/23] Add a nicer sine based gradient for the LEDs --- led_test.c | 13 +++++-------- ugfx | 2 +- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/led_test.c b/led_test.c index d53f0b7fb..c2ea30b55 100644 --- a/led_test.c +++ b/led_test.c @@ -89,14 +89,11 @@ static uint8_t crossfade_start_frame[NUM_ROWS][NUM_COLS]; static uint8_t crossfade_end_frame[NUM_ROWS][NUM_COLS]; static uint8_t compute_gradient_color(float t, float index, float num) { - const float target = t * (num - 1.0f); - const float half_num = num / 2.0f; - float d = fabs(index - target); - if (d > half_num) { - d = num - d; - } - d = 1.0f - (d / half_num); - return (uint8_t)(255.0f * d); + const float two_pi = 2.0f * PI; + float normalized_index = (1.0f - index / (num - 1)) * two_pi; + float x = t * two_pi + normalized_index; + float v = 0.5 * (cosf(x) + 1.0f); + return (uint8_t)(255.0f * v); } bool keyframe_fade_in_all_leds(keyframe_animation_t* animation, visualizer_state_t* state) { diff --git a/ugfx b/ugfx index 7d7eeef0a..dc5786acc 160000 --- a/ugfx +++ b/ugfx @@ -1 +1 @@ -Subproject commit 7d7eeef0ad0f1b28f4fb86ad931cb6774c7b9e81 +Subproject commit dc5786acc246fb23503517647c386e43f1bfb247 From 73d890a2c9c34b905cd5e74e7146fdd4578dcb96 Mon Sep 17 00:00:00 2001 From: Fred Sundvik Date: Wed, 1 Jun 2016 09:22:47 +0300 Subject: [PATCH 23/23] Fix visualizer sleeping too long The documentation for ugfx gEventWait wait is wrong and the function takes the time in milliseconds, instead of system ticks. This caused the the thread to sleep way too long. It also caused somewhat random sleeping behaviour as the MS2ST function overflows at around 43 seconds sleep. The event source is also now initialized correctly, so that the thread actually can be woken up by events. --- visualizer.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/visualizer.c b/visualizer.c index 0e587221f..c24073405 100644 --- a/visualizer.c +++ b/visualizer.c @@ -25,6 +25,9 @@ SOFTWARE. #include "visualizer.h" #include "config.h" #include +#ifdef PROTOCOL_CHIBIOS +#include "ch.h" +#endif #ifdef LCD_ENABLE #include "gfx.h" @@ -67,7 +70,6 @@ static bool same_status(visualizer_keyboard_status_t* status1, visualizer_keyboa status1->suspended == status2->suspended; } -static GSourceHandle layer_changed_event; static bool visualizer_enabled = false; #define MAX_SIMULTANEOUS_ANIMATIONS 4 @@ -185,8 +187,8 @@ static bool update_keyframe_animation(keyframe_animation_t* animation, visualize 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; } @@ -345,7 +347,7 @@ static DECLARE_THREAD_FUNCTION(visualizerThread, arg) { GListener event_listener; geventListenerInit(&event_listener); - geventAttachSource(&event_listener, layer_changed_event, 0); + geventAttachSource(&event_listener, (GSourceHandle)¤t_status, 0); visualizer_keyboard_status_t initial_status = { .default_layer = 0xFFFFFFFF, @@ -435,6 +437,16 @@ static DECLARE_THREAD_FUNCTION(visualizerThread, arg) { } } dprintf("Update took %d, last delta %d, sleep_time %d\n", update_delta, delta, 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 @@ -473,7 +485,7 @@ void visualizer_init(void) { void update_status(bool changed) { if (changed) { - GSourceListener* listener = geventGetSourceListener(layer_changed_event, NULL); + GSourceListener* listener = geventGetSourceListener((GSourceHandle)¤t_status, NULL); if (listener) { geventSendEvent(listener); }