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 00000000..1aadd554 --- /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 00000000..521e0521 --- /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 867a1d33..ed5c9fa2 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 22798cda..6a72fde1 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 13c5d315..96ca468e 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 1aadd554..1fba32fa 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 521e0521..a722cd9f 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 1fba32fa..197550fd 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 a722cd9f..03737a71 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 ed5c9fa2..219d44cd 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 6a72fde1..82d7a71d 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 219d44cd..2ec6e34f 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 82d7a71d..5375e013 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 197550fd..8c0de604 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 8c0de604..c987eca3 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 2ec6e34f..81ec8298 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 c987eca3..ce6c2e68 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 e14b25e7..5e232575 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 5375e013..8a2772c6 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 81ec8298..0684a26d 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 96ca468e..5cc199cf 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 ce6c2e68..ed65a0ba 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 ed65a0ba..d358ef81 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 e221a690..314a066d 160000 --- a/ugfx +++ b/ugfx @@ -1 +1 @@ -Subproject commit e221a690616e20f87e0b0088baffdbd5427be862 +Subproject commit 314a066d11f09d295d42054a0b53fa1a95c0ba0a diff --git a/visualizer.mk b/visualizer.mk index 5cc199cf..c51f8ba5 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 314a066d..7d7eeef0 160000 --- a/ugfx +++ b/ugfx @@ -1 +1 @@ -Subproject commit 314a066d11f09d295d42054a0b53fa1a95c0ba0a +Subproject commit 7d7eeef0ad0f1b28f4fb86ad931cb6774c7b9e81 diff --git a/visualizer.c b/visualizer.c index 579837ed..ea84546f 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 c51f8ba5..67882932 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 d358ef81..6d3f3b2e 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 67882932..56525ffd 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 56525ffd..3e361491 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 ea84546f..ff99e960 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 ff99e960..bbb00deb 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 8a2772c6..4d6a61dd 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 bbb00deb..607a6456 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 4d6a61dd..a3828e35 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 3e361491..56525ffd 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 607a6456..0e587221 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 a3828e35..45cfa9aa 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 6d3f3b2e..d53f0b7f 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 d53f0b7f..c2ea30b5 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 7d7eeef0..dc5786ac 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 0e587221..c2407340 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); }