diff options
Diffstat (limited to 'quantum/visualizer')
-rw-r--r-- | quantum/visualizer/LICENSE.md | 29 | ||||
-rw-r--r-- | quantum/visualizer/lcd_backlight.c | 89 | ||||
-rw-r--r-- | quantum/visualizer/lcd_backlight.h | 47 | ||||
-rw-r--r-- | quantum/visualizer/lcd_backlight_keyframes.c | 77 | ||||
-rw-r--r-- | quantum/visualizer/lcd_backlight_keyframes.h | 30 | ||||
-rw-r--r-- | quantum/visualizer/lcd_keyframes.c | 188 | ||||
-rw-r--r-- | quantum/visualizer/lcd_keyframes.h | 39 | ||||
-rw-r--r-- | quantum/visualizer/led_keyframes.c | 143 | ||||
-rw-r--r-- | quantum/visualizer/led_keyframes.h | 44 | ||||
-rw-r--r-- | quantum/visualizer/readme.md | 18 | ||||
-rw-r--r-- | quantum/visualizer/resources/lcd_logo.c | 61 | ||||
-rw-r--r-- | quantum/visualizer/resources/lcd_logo.png | bin | 0 -> 490 bytes | |||
-rw-r--r-- | quantum/visualizer/resources/resources.h | 27 | ||||
-rw-r--r-- | quantum/visualizer/visualizer.c | 502 | ||||
-rw-r--r-- | quantum/visualizer/visualizer.h | 155 | ||||
-rw-r--r-- | quantum/visualizer/visualizer.mk | 73 | ||||
-rw-r--r-- | quantum/visualizer/visualizer_keyframes.c | 23 | ||||
-rw-r--r-- | quantum/visualizer/visualizer_keyframes.h | 26 |
18 files changed, 1571 insertions, 0 deletions
diff --git a/quantum/visualizer/LICENSE.md b/quantum/visualizer/LICENSE.md new file mode 100644 index 0000000000..22d4c3f08b --- /dev/null +++ b/quantum/visualizer/LICENSE.md @@ -0,0 +1,29 @@ +The files in this project are licensed under the MIT license +It uses the following libraries +uGFX - with it's own license, see the license.html file in the uGFX subfolder for more information +tmk_core - is indirectly used and not included in the repository. It's licensed under the GPLv2 license +Chibios - which is used by tmk_core is licensed under GPLv3. + +Therefore the effective license for any project using the library is GPLv3 + +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. diff --git a/quantum/visualizer/lcd_backlight.c b/quantum/visualizer/lcd_backlight.c new file mode 100644 index 0000000000..6cd996f75e --- /dev/null +++ b/quantum/visualizer/lcd_backlight.c @@ -0,0 +1,89 @@ +/* +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 "lcd_backlight.h" +#include <math.h> + +static uint8_t current_hue = 0; +static uint8_t current_saturation = 0; +static uint8_t current_intensity = 0; +static uint8_t current_brightness = 0; + +void lcd_backlight_init(void) { + lcd_backlight_hal_init(); + lcd_backlight_color(current_hue, current_saturation, current_intensity); +} + +// This code is based on Brian Neltner's blogpost and example code +// "Why every LED light should be using HSI colorspace". +// http://blog.saikoled.com/post/43693602826/why-every-led-light-should-be-using-hsi +static void hsi_to_rgb(float h, float s, float i, uint16_t* r_out, uint16_t* g_out, uint16_t* b_out) { + unsigned int r, g, b; + h = fmodf(h, 360.0f); // cycle h around to 0-360 degrees + h = 3.14159f * h / 180.0f; // Convert to radians. + s = s > 0.0f ? (s < 1.0f ? s : 1.0f) : 0.0f; // clamp s and i to interval [0,1] + i = i > 0.0f ? (i < 1.0f ? i : 1.0f) : 0.0f; + + // Math! Thanks in part to Kyle Miller. + if(h < 2.09439f) { + r = 65535.0f * i/3.0f *(1.0f + s * cos(h) / cosf(1.047196667f - h)); + g = 65535.0f * i/3.0f *(1.0f + s *(1.0f - cosf(h) / cos(1.047196667f - h))); + b = 65535.0f * i/3.0f *(1.0f - s); + } else if(h < 4.188787) { + h = h - 2.09439; + g = 65535.0f * i/3.0f *(1.0f + s * cosf(h) / cosf(1.047196667f - h)); + b = 65535.0f * i/3.0f *(1.0f + s * (1.0f - cosf(h) / cosf(1.047196667f - h))); + r = 65535.0f * i/3.0f *(1.0f - s); + } else { + h = h - 4.188787; + b = 65535.0f*i/3.0f * (1.0f + s * cosf(h) / cosf(1.047196667f - h)); + r = 65535.0f*i/3.0f * (1.0f + s * (1.0f - cosf(h) / cosf(1.047196667f - h))); + g = 65535.0f*i/3.0f * (1.0f - s); + } + *r_out = r > 65535 ? 65535 : r; + *g_out = g > 65535 ? 65535 : g; + *b_out = b > 65535 ? 65535 : b; +} + +void lcd_backlight_color(uint8_t hue, uint8_t saturation, uint8_t intensity) { + uint16_t r, g, b; + float hue_f = 360.0f * (float)hue / 255.0f; + float saturation_f = (float)saturation / 255.0f; + float intensity_f = (float)intensity / 255.0f; + intensity_f *= (float)current_brightness / 255.0f; + hsi_to_rgb(hue_f, saturation_f, intensity_f, &r, &g, &b); + current_hue = hue; + current_saturation = saturation; + current_intensity = intensity; + lcd_backlight_hal_color(r, g, b); +} + +void lcd_backlight_brightness(uint8_t b) { + current_brightness = b; + lcd_backlight_color(current_hue, current_saturation, current_intensity); +} + +uint8_t lcd_get_backlight_brightness(void) { + return current_brightness; +} diff --git a/quantum/visualizer/lcd_backlight.h b/quantum/visualizer/lcd_backlight.h new file mode 100644 index 0000000000..95d7a07b46 --- /dev/null +++ b/quantum/visualizer/lcd_backlight.h @@ -0,0 +1,47 @@ +/* +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 LCD_BACKLIGHT_H_ +#define LCD_BACKLIGHT_H_ +#include "stdint.h" + +// Helper macros for storing hue, staturation and intensity as unsigned integers +#define LCD_COLOR(hue, saturation, intensity) (hue << 16 | saturation << 8 | intensity) +#define LCD_HUE(color) ((color >> 16) & 0xFF) +#define LCD_SAT(color) ((color >> 8) & 0xFF) +#define LCD_INT(color) (color & 0xFF) + +static inline uint32_t change_lcd_color_intensity(uint32_t color, uint8_t new_intensity) { + return (color & 0xFFFFFF00) | new_intensity; +} + +void lcd_backlight_init(void); +void lcd_backlight_color(uint8_t hue, uint8_t saturation, uint8_t intensity); +void lcd_backlight_brightness(uint8_t b); +uint8_t lcd_get_backlight_brightness(void); + +void lcd_backlight_hal_init(void); +void lcd_backlight_hal_color(uint16_t r, uint16_t g, uint16_t b); + +#endif /* LCD_BACKLIGHT_H_ */ diff --git a/quantum/visualizer/lcd_backlight_keyframes.c b/quantum/visualizer/lcd_backlight_keyframes.c new file mode 100644 index 0000000000..8436d4e3dd --- /dev/null +++ b/quantum/visualizer/lcd_backlight_keyframes.c @@ -0,0 +1,77 @@ +/* Copyright 2017 Fred Sundvik + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "lcd_backlight_keyframes.h" + +bool backlight_keyframe_animate_color(keyframe_animation_t* animation, visualizer_state_t* state) { + int frame_length = animation->frame_lengths[animation->current_frame]; + int current_pos = frame_length - animation->time_left_in_frame; + uint8_t t_h = LCD_HUE(state->target_lcd_color); + uint8_t t_s = LCD_SAT(state->target_lcd_color); + uint8_t t_i = LCD_INT(state->target_lcd_color); + uint8_t p_h = LCD_HUE(state->prev_lcd_color); + uint8_t p_s = LCD_SAT(state->prev_lcd_color); + uint8_t p_i = LCD_INT(state->prev_lcd_color); + + uint8_t d_h1 = t_h - p_h; //Modulo arithmetic since we want to wrap around + int d_h2 = t_h - p_h; + // Chose the shortest way around + int d_h = abs(d_h2) < d_h1 ? d_h2 : d_h1; + int d_s = t_s - p_s; + int d_i = t_i - p_i; + + int hue = (d_h * current_pos) / frame_length; + int sat = (d_s * current_pos) / frame_length; + int intensity = (d_i * current_pos) / frame_length; + //dprintf("%X -> %X = %X\n", p_h, t_h, hue); + hue += p_h; + sat += p_s; + intensity += p_i; + state->current_lcd_color = LCD_COLOR(hue, sat, intensity); + lcd_backlight_color( + LCD_HUE(state->current_lcd_color), + LCD_SAT(state->current_lcd_color), + LCD_INT(state->current_lcd_color)); + + return true; +} + +bool backlight_keyframe_set_color(keyframe_animation_t* animation, visualizer_state_t* state) { + (void)animation; + state->prev_lcd_color = state->target_lcd_color; + state->current_lcd_color = state->target_lcd_color; + lcd_backlight_color( + LCD_HUE(state->current_lcd_color), + LCD_SAT(state->current_lcd_color), + LCD_INT(state->current_lcd_color)); + return false; +} + +bool backlight_keyframe_disable(keyframe_animation_t* animation, visualizer_state_t* state) { + (void)animation; + (void)state; + lcd_backlight_hal_color(0, 0, 0); + return false; +} + +bool backlight_keyframe_enable(keyframe_animation_t* animation, visualizer_state_t* state) { + (void)animation; + (void)state; + lcd_backlight_color(LCD_HUE(state->current_lcd_color), + LCD_SAT(state->current_lcd_color), + LCD_INT(state->current_lcd_color)); + return false; +} diff --git a/quantum/visualizer/lcd_backlight_keyframes.h b/quantum/visualizer/lcd_backlight_keyframes.h new file mode 100644 index 0000000000..e1c125cf91 --- /dev/null +++ b/quantum/visualizer/lcd_backlight_keyframes.h @@ -0,0 +1,30 @@ +/* Copyright 2017 Fred Sundvik + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef QUANTUM_VISUALIZER_LCD_BACKLIGHT_KEYFRAMES_H_ +#define QUANTUM_VISUALIZER_LCD_BACKLIGHT_KEYFRAMES_H_ + +#include "visualizer.h" + +// Animates the LCD backlight color between the current color and the target color (of the state) +bool backlight_keyframe_animate_color(keyframe_animation_t* animation, visualizer_state_t* state); +// Sets the backlight color to the target color +bool backlight_keyframe_set_color(keyframe_animation_t* animation, visualizer_state_t* state); + +bool backlight_keyframe_disable(keyframe_animation_t* animation, visualizer_state_t* state); +bool backlight_keyframe_enable(keyframe_animation_t* animation, visualizer_state_t* state); + +#endif /* QUANTUM_VISUALIZER_LCD_BACKLIGHT_KEYFRAMES_H_ */ diff --git a/quantum/visualizer/lcd_keyframes.c b/quantum/visualizer/lcd_keyframes.c new file mode 100644 index 0000000000..82e4184d2c --- /dev/null +++ b/quantum/visualizer/lcd_keyframes.c @@ -0,0 +1,188 @@ +/* Copyright 2017 Fred Sundvik + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "lcd_keyframes.h" +#include <string.h> +#include "action_util.h" +#include "led.h" +#include "resources/resources.h" + +bool lcd_keyframe_display_layer_text(keyframe_animation_t* animation, visualizer_state_t* state) { + (void)animation; + gdispClear(White); + gdispDrawString(0, 10, state->layer_text, state->font_dejavusansbold12, Black); + return false; +} + +static void format_layer_bitmap_string(uint16_t default_layer, uint16_t layer, char* buffer) { + for (int i=0; i<16;i++) + { + uint32_t mask = (1u << i); + if (default_layer & mask) { + if (layer & mask) { + *buffer = 'B'; + } else { + *buffer = 'D'; + } + } else if (layer & mask) { + *buffer = '1'; + } else { + *buffer = '0'; + } + ++buffer; + + if (i==3 || i==7 || i==11) { + *buffer = ' '; + ++buffer; + } + } + *buffer = 0; +} + +bool lcd_keyframe_display_layer_bitmap(keyframe_animation_t* animation, visualizer_state_t* state) { + (void)animation; + const char* layer_help = "1=On D=Default B=Both"; + char layer_buffer[16 + 4]; // 3 spaces and one null terminator + gdispClear(White); + gdispDrawString(0, 0, layer_help, state->font_fixed5x8, Black); + format_layer_bitmap_string(state->status.default_layer, state->status.layer, layer_buffer); + gdispDrawString(0, 10, layer_buffer, state->font_fixed5x8, Black); + format_layer_bitmap_string(state->status.default_layer >> 16, state->status.layer >> 16, layer_buffer); + gdispDrawString(0, 20, layer_buffer, state->font_fixed5x8, Black); + return false; +} + +static void format_mods_bitmap_string(uint8_t mods, char* buffer) { + *buffer = ' '; + ++buffer; + + for (int i = 0; i<8; i++) + { + uint32_t mask = (1u << i); + if (mods & mask) { + *buffer = '1'; + } else { + *buffer = '0'; + } + ++buffer; + + if (i==3) { + *buffer = ' '; + ++buffer; + } + } + *buffer = 0; +} + +bool lcd_keyframe_display_mods_bitmap(keyframe_animation_t* animation, visualizer_state_t* state) { + (void)animation; + + const char* title = "Modifier states"; + const char* mods_header = " CSAG CSAG "; + char status_buffer[12]; + + gdispClear(White); + gdispDrawString(0, 0, title, state->font_fixed5x8, Black); + gdispDrawString(0, 10, mods_header, state->font_fixed5x8, Black); + format_mods_bitmap_string(state->status.mods, status_buffer); + gdispDrawString(0, 20, status_buffer, state->font_fixed5x8, Black); + + return false; +} + +#define LED_STATE_STRING_SIZE sizeof("NUM CAPS SCRL COMP KANA") + +static void get_led_state_string(char* output, visualizer_state_t* state) { + uint8_t pos = 0; + + if (state->status.leds & (1u << USB_LED_NUM_LOCK)) { + memcpy(output + pos, "NUM ", 4); + pos += 4; + } + if (state->status.leds & (1u << USB_LED_CAPS_LOCK)) { + memcpy(output + pos, "CAPS ", 5); + pos += 5; + } + if (state->status.leds & (1u << USB_LED_SCROLL_LOCK)) { + memcpy(output + pos, "SCRL ", 5); + pos += 5; + } + if (state->status.leds & (1u << USB_LED_COMPOSE)) { + memcpy(output + pos, "COMP ", 5); + pos += 5; + } + if (state->status.leds & (1u << USB_LED_KANA)) { + memcpy(output + pos, "KANA", 4); + pos += 4; + } + output[pos] = 0; +} + +bool lcd_keyframe_display_led_states(keyframe_animation_t* animation, visualizer_state_t* state) +{ + (void)animation; + char output[LED_STATE_STRING_SIZE]; + get_led_state_string(output, state); + gdispClear(White); + gdispDrawString(0, 10, output, state->font_dejavusansbold12, Black); + return false; +} + +bool lcd_keyframe_display_layer_and_led_states(keyframe_animation_t* animation, visualizer_state_t* state) { + (void)animation; + gdispClear(White); + uint8_t y = 10; + if (state->status.leds) { + char output[LED_STATE_STRING_SIZE]; + get_led_state_string(output, state); + gdispDrawString(0, 1, output, state->font_dejavusansbold12, Black); + y = 17; + } + gdispDrawString(0, y, state->layer_text, state->font_dejavusansbold12, Black); + return false; +} + +bool lcd_keyframe_draw_logo(keyframe_animation_t* animation, visualizer_state_t* state) { + (void)state; + (void)animation; + // Read the uGFX documentation for information how to use the displays + // http://wiki.ugfx.org/index.php/Main_Page + gdispClear(White); + + // You can use static variables for things that can't be found in the animation + // or state structs, here we use the image + + //gdispGBlitArea is a tricky function to use since it supports blitting part of the image + // if you have full screen image, then just use 128 and 32 for both source and target dimensions + gdispGBlitArea(GDISP, 0, 0, 128, 32, 0, 0, 128, (pixel_t*)resource_lcd_logo); + + return false; +} + + +bool lcd_keyframe_disable(keyframe_animation_t* animation, visualizer_state_t* state) { + (void)animation; + (void)state; + gdispSetPowerMode(powerOff); + return false; +} + +bool lcd_keyframe_enable(keyframe_animation_t* animation, visualizer_state_t* state) { + (void)animation; + (void)state; + gdispSetPowerMode(powerOn); + return false; +} diff --git a/quantum/visualizer/lcd_keyframes.h b/quantum/visualizer/lcd_keyframes.h new file mode 100644 index 0000000000..2e912b4c73 --- /dev/null +++ b/quantum/visualizer/lcd_keyframes.h @@ -0,0 +1,39 @@ +/* Copyright 2017 Fred Sundvik + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef QUANTUM_VISUALIZER_LCD_KEYFRAMES_H_ +#define QUANTUM_VISUALIZER_LCD_KEYFRAMES_H_ + +#include "visualizer.h" + +// Displays the layer text centered vertically on the screen +bool lcd_keyframe_display_layer_text(keyframe_animation_t* animation, visualizer_state_t* state); +// Displays a bitmap (0/1) of all the currently active layers +bool lcd_keyframe_display_layer_bitmap(keyframe_animation_t* animation, visualizer_state_t* state); +// Displays a bitmap (0/1) of all the currently active mods +bool lcd_keyframe_display_mods_bitmap(keyframe_animation_t* animation, visualizer_state_t* state); +// Displays the keyboard led states (CAPS (Caps lock), NUM (Num lock), SCRL (Scroll lock), COMP (Compose), KANA) +bool lcd_keyframe_display_led_states(keyframe_animation_t* animation, visualizer_state_t* state); +// Displays both the layer text and the led states +bool lcd_keyframe_display_layer_and_led_states(keyframe_animation_t* animation, visualizer_state_t* state); +// Displays the QMK logo on the LCD screen +bool lcd_keyframe_draw_logo(keyframe_animation_t* animation, visualizer_state_t* state); + +bool lcd_keyframe_disable(keyframe_animation_t* animation, visualizer_state_t* state); +bool lcd_keyframe_enable(keyframe_animation_t* animation, visualizer_state_t* state); + + +#endif /* QUANTUM_VISUALIZER_LCD_KEYFRAMES_H_ */ diff --git a/quantum/visualizer/led_keyframes.c b/quantum/visualizer/led_keyframes.c new file mode 100644 index 0000000000..7e6e5d1ab9 --- /dev/null +++ b/quantum/visualizer/led_keyframes.c @@ -0,0 +1,143 @@ +/* +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 "gfx.h" +#include "math.h" +#include "led_keyframes.h" + +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; + 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); +} + +// TODO: Should be customizable per keyboard +#define NUM_ROWS LED_NUM_ROWS +#define NUM_COLS LED_NUM_COLS + +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 two_pi = M_PI * 2.0f; + float normalized_index = (1.0f - index / (num - 1.0f)) * two_pi; + float x = t * two_pi + normalized_index; + float v = 0.5 * (cosf(x) + 1.0f); + return (uint8_t)(255.0f * v); +} + +bool led_keyframe_fade_in_all(keyframe_animation_t* animation, visualizer_state_t* state) { + (void)state; + keyframe_fade_all_leds_from_to(animation, 0, 255); + return true; +} + +bool led_keyframe_fade_out_all(keyframe_animation_t* animation, visualizer_state_t* state) { + (void)state; + keyframe_fade_all_leds_from_to(animation, 255, 0); + return true; +} + +bool led_keyframe_left_to_right_gradient(keyframe_animation_t* animation, visualizer_state_t* state) { + (void)state; + 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); + gdispGDrawLine(LED_DISPLAY, i, 0, i, NUM_ROWS - 1, LUMA2COLOR(color)); + } + return true; +} + +bool led_keyframe_top_to_bottom_gradient(keyframe_animation_t* animation, visualizer_state_t* state) { + (void)state; + 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); + gdispGDrawLine(LED_DISPLAY, 0, i, NUM_COLS - 1, i, LUMA2COLOR(color)); + } + return true; +} + +static void copy_current_led_state(uint8_t* dest) { + for (int i=0;i<NUM_ROWS;i++) { + for (int j=0;j<NUM_COLS;j++) { + dest[i*NUM_COLS + j] = gdispGGetPixelColor(LED_DISPLAY, j, i); + } + } +} +bool led_keyframe_crossfade(keyframe_animation_t* animation, visualizer_state_t* state) { + (void)state; + if (animation->first_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<NUM_ROWS;i++) { + for (int j=0;j<NUM_COLS;j++) { + color_t color = LUMA2COLOR(fade_led_color(animation, crossfade_start_frame[i][j], crossfade_end_frame[i][j])); + gdispGDrawPixel(LED_DISPLAY, j, i, color); + } + } + return true; +} + +bool led_keyframe_mirror_orientation(keyframe_animation_t* animation, visualizer_state_t* state) { + (void)state; + (void)animation; + gdispGSetOrientation(LED_DISPLAY, GDISP_ROTATE_180); + return false; +} + +bool led_keyframe_normal_orientation(keyframe_animation_t* animation, visualizer_state_t* state) { + (void)state; + (void)animation; + gdispGSetOrientation(LED_DISPLAY, GDISP_ROTATE_0); + return false; +} + +bool led_keyframe_disable(keyframe_animation_t* animation, visualizer_state_t* state) { + (void)state; + (void)animation; + gdispGSetPowerMode(LED_DISPLAY, powerOff); + return false; +} + +bool led_keyframe_enable(keyframe_animation_t* animation, visualizer_state_t* state) { + (void)state; + (void)animation; + gdispGSetPowerMode(LED_DISPLAY, powerOn); + return false; +} diff --git a/quantum/visualizer/led_keyframes.h b/quantum/visualizer/led_keyframes.h new file mode 100644 index 0000000000..a59a4f37d1 --- /dev/null +++ b/quantum/visualizer/led_keyframes.h @@ -0,0 +1,44 @@ +/* +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 LED_KEYFRAMES_H +#define LED_KEYFRAMES_H + +#include "visualizer.h" + +bool led_keyframe_fade_in_all(keyframe_animation_t* animation, visualizer_state_t* state); +bool led_keyframe_fade_out_all(keyframe_animation_t* animation, visualizer_state_t* state); +bool led_keyframe_left_to_right_gradient(keyframe_animation_t* animation, visualizer_state_t* state); +bool led_keyframe_top_to_bottom_gradient(keyframe_animation_t* animation, visualizer_state_t* state); +bool led_keyframe_crossfade(keyframe_animation_t* animation, visualizer_state_t* state); +bool led_keyframe_mirror_orientation(keyframe_animation_t* animation, visualizer_state_t* state); +bool led_keyframe_normal_orientation(keyframe_animation_t* animation, visualizer_state_t* state); + +bool led_keyframe_disable(keyframe_animation_t* animation, visualizer_state_t* state); +bool led_keyframe_enable(keyframe_animation_t* animation, visualizer_state_t* state); + +extern keyframe_animation_t led_test_animation; + + +#endif /* LED_KEYFRAMES_H */ diff --git a/quantum/visualizer/readme.md b/quantum/visualizer/readme.md new file mode 100644 index 0000000000..545ba22707 --- /dev/null +++ b/quantum/visualizer/readme.md @@ -0,0 +1,18 @@ +# A visualization library for the TMK keyboard firmware + +This library is designed to work together with the [TMK keyboard firmware](https://github.com/tmk/tmk_keyboard). Currently it only works for [Chibios](http://www.chibios.org/) + flavors, but it would be possible to add support for other configurations as well. The LCD display functionality is provided by the [uGFX library](http://www.ugfx.org/). + +## To use this library as a user +You can and should modify the visualizer\_user.c file. Check the comments in the file for more information. + +## To add this library to custom keyboard projects + +1. Add tmk_visualizer as a submodule to your project +1. Set VISUALIZER_DIR in the main keyboard project makefile to point to the submodule +1. Define LCD\_ENABLE and/or LCD\_BACKLIGHT\_ENABLE, to enable support +1. Include the visualizer.mk make file +1. Copy the files in the example\_integration folder to your keyboard project +1. All other files than the callback.c file are included automatically, so you will need to add callback.c to your makefile manually. If you already have a similar file in your project, you can just copy the functions instead of the whole file. +1. Edit the files to match your hardware. You might might want to read the Chibios and UGfx documentation, for more information. +1. If you enable LCD support you might also have to write a custom uGFX display driver, check the uGFX documentation for that. You probably also want to enable SPI support in your Chibios configuration. diff --git a/quantum/visualizer/resources/lcd_logo.c b/quantum/visualizer/resources/lcd_logo.c new file mode 100644 index 0000000000..d1a0ffa7f9 --- /dev/null +++ b/quantum/visualizer/resources/lcd_logo.c @@ -0,0 +1,61 @@ +/* Copyright 2017 Fred Sundvik + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "resources.h" + + +// To generate an image array like this +// Ensure the image is 128 x 32 or smaller +// Convert the bitmap to a C array using a program like http://www.riuson.com/lcd-image-converter/ +// Ensure the the conversion process produces a monochrome format array - 1 bit/pixel, left to right, top to bottom +// Update array in the source code with the C array produced by the conversion program + +// The image below is generated from lcd_logo.png +const uint8_t resource_lcd_logo[512] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xf8, 0xfe, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x38, 0x38, 0x06, 0x29, 0x41, 0x24, 0x52, 0x24, 0x46, 0x00, 0x00, 0 |