summaryrefslogtreecommitdiffstats
path: root/quantum
diff options
context:
space:
mode:
Diffstat (limited to 'quantum')
-rw-r--r--quantum/led_tables.c71
-rw-r--r--quantum/led_tables.h30
-rw-r--r--quantum/quantum.c10
-rw-r--r--quantum/rgblight.c58
-rw-r--r--quantum/serial_link/system/serial_link.c2
-rw-r--r--quantum/visualizer/example_integration/callbacks.c36
-rw-r--r--quantum/visualizer/example_integration/gfxconf.h325
-rw-r--r--quantum/visualizer/example_integration/lcd_backlight_hal.c91
-rw-r--r--quantum/visualizer/example_integration/visualizer_user.c121
-rw-r--r--quantum/visualizer/lcd_backlight.c8
-rw-r--r--quantum/visualizer/lcd_backlight.h4
-rw-r--r--quantum/visualizer/lcd_backlight_keyframes.c77
-rw-r--r--quantum/visualizer/lcd_backlight_keyframes.h30
-rw-r--r--quantum/visualizer/lcd_keyframes.c188
-rw-r--r--quantum/visualizer/lcd_keyframes.h39
-rw-r--r--quantum/visualizer/led_keyframes.c (renamed from quantum/visualizer/led_test.c)57
-rw-r--r--quantum/visualizer/led_keyframes.h (renamed from quantum/visualizer/led_test.h)20
-rw-r--r--quantum/visualizer/resources/lcd_logo.c61
-rw-r--r--quantum/visualizer/resources/lcd_logo.pngbin0 -> 490 bytes
-rw-r--r--quantum/visualizer/resources/resources.h27
-rw-r--r--quantum/visualizer/visualizer.c226
-rw-r--r--quantum/visualizer/visualizer.h41
-rw-r--r--quantum/visualizer/visualizer.mk21
-rw-r--r--quantum/visualizer/visualizer_keyframes.c23
-rw-r--r--quantum/visualizer/visualizer_keyframes.h26
25 files changed, 688 insertions, 904 deletions
diff --git a/quantum/led_tables.c b/quantum/led_tables.c
new file mode 100644
index 000000000..b99f26209
--- /dev/null
+++ b/quantum/led_tables.c
@@ -0,0 +1,71 @@
+/*
+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 "led_tables.h"
+
+
+#ifdef USE_CIE1931_CURVE
+// Lightness curve using the CIE 1931 lightness formula
+//Generated by the python script provided in http://jared.geek.nz/2013/feb/linear-led-pwm
+const uint8_t CIE1931_CURVE[] PROGMEM = {
+ 0, 0, 0, 0, 0, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 3, 3, 3, 3, 3, 3, 3,
+ 3, 4, 4, 4, 4, 4, 4, 5, 5, 5,
+ 5, 5, 6, 6, 6, 6, 6, 7, 7, 7,
+ 7, 8, 8, 8, 8, 9, 9, 9, 10, 10,
+ 10, 10, 11, 11, 11, 12, 12, 12, 13, 13,
+ 13, 14, 14, 15, 15, 15, 16, 16, 17, 17,
+ 17, 18, 18, 19, 19, 20, 20, 21, 21, 22,
+ 22, 23, 23, 24, 24, 25, 25, 26, 26, 27,
+ 28, 28, 29, 29, 30, 31, 31, 32, 32, 33,
+ 34, 34, 35, 36, 37, 37, 38, 39, 39, 40,
+ 41, 42, 43, 43, 44, 45, 46, 47, 47, 48,
+ 49, 50, 51, 52, 53, 54, 54, 55, 56, 57,
+ 58, 59, 60, 61, 62, 63, 64, 65, 66, 67,
+ 68, 70, 71, 72, 73, 74, 75, 76, 77, 79,
+ 80, 81, 82, 83, 85, 86, 87, 88, 90, 91,
+ 92, 94, 95, 96, 98, 99, 100, 102, 103, 105,
+ 106, 108, 109, 110, 112, 113, 115, 116, 118, 120,
+ 121, 123, 124, 126, 128, 129, 131, 132, 134, 136,
+ 138, 139, 141, 143, 145, 146, 148, 150, 152, 154,
+ 155, 157, 159, 161, 163, 165, 167, 169, 171, 173,
+ 175, 177, 179, 181, 183, 185, 187, 189, 191, 193,
+ 196, 198, 200, 202, 204, 207, 209, 211, 214, 216,
+ 218, 220, 223, 225, 228, 230, 232, 235, 237, 240,
+ 242, 245, 247, 250, 252, 255,
+ };
+#endif
+
+#ifdef USE_LED_BREATHING_TABLE
+const uint8_t LED_BREATHING_TABLE[] PROGMEM = {
+ 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 5, 5, 6, 7, 9,
+ 10, 11, 12, 14, 15, 17, 18, 20, 21, 23, 25, 27, 29, 31, 33, 35,
+ 37, 40, 42, 44, 47, 49, 52, 54, 57, 59, 62, 65, 67, 70, 73, 76,
+ 79, 82, 85, 88, 90, 93, 97, 100, 103, 106, 109, 112, 115, 118, 121, 124,
+ 127, 131, 134, 137, 140, 143, 146, 149, 152, 155, 158, 162, 165, 167, 170, 173,
+ 176, 179, 182, 185, 188, 190, 193, 196, 198, 201, 203, 206, 208, 211, 213, 215,
+ 218, 220, 222, 224, 226, 228, 230, 232, 234, 235, 237, 238, 240, 241, 243, 244,
+ 245, 246, 248, 249, 250, 250, 251, 252, 253, 253, 254, 254, 254, 255, 255, 255,
+ 255, 255, 255, 255, 254, 254, 254, 253, 253, 252, 251, 250, 250, 249, 248, 246,
+ 245, 244, 243, 241, 240, 238, 237, 235, 234, 232, 230, 228, 226, 224, 222, 220,
+ 218, 215, 213, 211, 208, 206, 203, 201, 198, 196, 193, 190, 188, 185, 182, 179,
+ 176, 173, 170, 167, 165, 162, 158, 155, 152, 149, 146, 143, 140, 137, 134, 131,
+ 128, 124, 121, 118, 115, 112, 109, 106, 103, 100, 97, 93, 90, 88, 85, 82,
+ 79, 76, 73, 70, 67, 65, 62, 59, 57, 54, 52, 49, 47, 44, 42, 40,
+ 37, 35, 33, 31, 29, 27, 25, 23, 21, 20, 18, 17, 15, 14, 12, 11,
+ 10, 9, 7, 6, 5, 5, 4, 3, 2, 2, 1, 1, 1, 0, 0, 0
+};
+#endif
diff --git a/quantum/led_tables.h b/quantum/led_tables.h
new file mode 100644
index 000000000..af49bf332
--- /dev/null
+++ b/quantum/led_tables.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 LED_TABLES_H
+#define LED_TABLES_H
+
+#include "progmem.h"
+#include <stdint.h>
+
+#ifdef USE_CIE1931_CURVE
+extern const uint8_t CIE1931_CURVE[] PROGMEM;
+#endif
+
+#ifdef USE_LED_BREATHING_TABLE
+extern const uint8_t LED_BREATHING_TABLE[] PROGMEM;
+#endif
+
+#endif
diff --git a/quantum/quantum.c b/quantum/quantum.c
index 62d9ef923..4f4cee4e9 100644
--- a/quantum/quantum.c
+++ b/quantum/quantum.c
@@ -135,7 +135,7 @@ void reset_keyboard(void) {
#endif
static bool shift_interrupted[2] = {0, 0};
-static uint16_t scs_timer = 0;
+static uint16_t scs_timer[2] = {0, 0};
bool process_record_quantum(keyrecord_t *record) {
@@ -395,7 +395,7 @@ bool process_record_quantum(keyrecord_t *record) {
case KC_LSPO: {
if (record->event.pressed) {
shift_interrupted[0] = false;
- scs_timer = timer_read ();
+ scs_timer[0] = timer_read ();
register_mods(MOD_BIT(KC_LSFT));
}
else {
@@ -405,7 +405,7 @@ bool process_record_quantum(keyrecord_t *record) {
shift_interrupted[1] = true;
}
#endif
- if (!shift_interrupted[0] && timer_elapsed(scs_timer) < TAPPING_TERM) {
+ if (!shift_interrupted[0] && timer_elapsed(scs_timer[0]) < TAPPING_TERM) {
register_code(LSPO_KEY);
unregister_code(LSPO_KEY);
}
@@ -418,7 +418,7 @@ bool process_record_quantum(keyrecord_t *record) {
case KC_RSPC: {
if (record->event.pressed) {
shift_interrupted[1] = false;
- scs_timer = timer_read ();
+ scs_timer[1] = timer_read ();
register_mods(MOD_BIT(KC_RSFT));
}
else {
@@ -428,7 +428,7 @@ bool process_record_quantum(keyrecord_t *record) {
shift_interrupted[1] = true;
}
#endif
- if (!shift_interrupted[1] && timer_elapsed(scs_timer) < TAPPING_TERM) {
+ if (!shift_interrupted[1] && timer_elapsed(scs_timer[1]) < TAPPING_TERM) {
register_code(RSPC_KEY);
unregister_code(RSPC_KEY);
}
diff --git a/quantum/rgblight.c b/quantum/rgblight.c
index eff70aae1..4eec2a776 100644
--- a/quantum/rgblight.c
+++ b/quantum/rgblight.c
@@ -20,56 +20,8 @@
#include "timer.h"
#include "rgblight.h"
#include "debug.h"
+#include "led_tables.h"
-// Lightness curve using the CIE 1931 lightness formula
-//Generated by the python script provided in http://jared.geek.nz/2013/feb/linear-led-pwm
-const uint8_t DIM_CURVE[] PROGMEM = {
- 0, 0, 0, 0, 0, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 3, 3, 3, 3, 3, 3, 3,
- 3, 4, 4, 4, 4, 4, 4, 5, 5, 5,
- 5, 5, 6, 6, 6, 6, 6, 7, 7, 7,
- 7, 8, 8, 8, 8, 9, 9, 9, 10, 10,
- 10, 10, 11, 11, 11, 12, 12, 12, 13, 13,
- 13, 14, 14, 15, 15, 15, 16, 16, 17, 17,
- 17, 18, 18, 19, 19, 20, 20, 21, 21, 22,
- 22, 23, 23, 24, 24, 25, 25, 26, 26, 27,
- 28, 28, 29, 29, 30, 31, 31, 32, 32, 33,
- 34, 34, 35, 36, 37, 37, 38, 39, 39, 40,
- 41, 42, 43, 43, 44, 45, 46, 47, 47, 48,
- 49, 50, 51, 52, 53, 54, 54, 55, 56, 57,
- 58, 59, 60, 61, 62, 63, 64, 65, 66, 67,
- 68, 70, 71, 72, 73, 74, 75, 76, 77, 79,
- 80, 81, 82, 83, 85, 86, 87, 88, 90, 91,
- 92, 94, 95, 96, 98, 99, 100, 102, 103, 105,
- 106, 108, 109, 110, 112, 113, 115, 116, 118, 120,
- 121, 123, 124, 126, 128, 129, 131, 132, 134, 136,
- 138, 139, 141, 143, 145, 146, 148, 150, 152, 154,
- 155, 157, 159, 161, 163, 165, 167, 169, 171, 173,
- 175, 177, 179, 181, 183, 185, 187, 189, 191, 193,
- 196, 198, 200, 202, 204, 207, 209, 211, 214, 216,
- 218, 220, 223, 225, 228, 230, 232, 235, 237, 240,
- 242, 245, 247, 250, 252, 255,
- };
-
-const uint8_t RGBLED_BREATHING_TABLE[] PROGMEM = {
- 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 5, 5, 6, 7, 9,
- 10, 11, 12, 14, 15, 17, 18, 20, 21, 23, 25, 27, 29, 31, 33, 35,
- 37, 40, 42, 44, 47, 49, 52, 54, 57, 59, 62, 65, 67, 70, 73, 76,
- 79, 82, 85, 88, 90, 93, 97, 100, 103, 106, 109, 112, 115, 118, 121, 124,
- 127, 131, 134, 137, 140, 143, 146, 149, 152, 155, 158, 162, 165, 167, 170, 173,
- 176, 179, 182, 185, 188, 190, 193, 196, 198, 201, 203, 206, 208, 211, 213, 215,
- 218, 220, 222, 224, 226, 228, 230, 232, 234, 235, 237, 238, 240, 241, 243, 244,
- 245, 246, 248, 249, 250, 250, 251, 252, 253, 253, 254, 254, 254, 255, 255, 255,
- 255, 255, 255, 255, 254, 254, 254, 253, 253, 252, 251, 250, 250, 249, 248, 246,
- 245, 244, 243, 241, 240, 238, 237, 235, 234, 232, 230, 228, 226, 224, 222, 220,
- 218, 215, 213, 211, 208, 206, 203, 201, 198, 196, 193, 190, 188, 185, 182, 179,
- 176, 173, 170, 167, 165, 162, 158, 155, 152, 149, 146, 143, 140, 137, 134, 131,
- 128, 124, 121, 118, 115, 112, 109, 106, 103, 100, 97, 93, 90, 88, 85, 82,
- 79, 76, 73, 70, 67, 65, 62, 59, 57, 54, 52, 49, 47, 44, 42, 40,
- 37, 35, 33, 31, 29, 27, 25, 23, 21, 20, 18, 17, 15, 14, 12, 11,
- 10, 9, 7, 6, 5, 5, 4, 3, 2, 2, 1, 1, 1, 0, 0, 0
-};
__attribute__ ((weak))
const uint8_t RGBLED_BREATHING_INTERVALS[] PROGMEM = {30, 20, 10, 5};
@@ -135,9 +87,9 @@ void sethsv(uint16_t hue, uint8_t sat, uint8_t val, LED_TYPE *led1) {
break;
}
}
- r = pgm_read_byte(&DIM_CURVE[r]);
- g = pgm_read_byte(&DIM_CURVE[g]);
- b = pgm_read_byte(&DIM_CURVE[b]);
+ r = pgm_read_byte(&CIE1931_CURVE[r]);
+ g = pgm_read_byte(&CIE1931_CURVE[g]);
+ b = pgm_read_byte(&CIE1931_CURVE[b]);
setrgb(r, g, b, led1);
}
@@ -509,7 +461,7 @@ void rgblight_effect_breathing(uint8_t interval) {
}
last_timer = timer_read();
- rgblight_sethsv_noeeprom(rgblight_config.hue, rgblight_config.sat, pgm_read_byte(&RGBLED_BREATHING_TABLE[pos]));
+ rgblight_sethsv_noeeprom(rgblight_config.hue, rgblight_config.sat, pgm_read_byte(&LED_BREATHING_TABLE[pos]));
pos = (pos + 1) % 256;
}
void rgblight_effect_rainbow_mood(uint8_t interval) {
diff --git a/quantum/serial_link/system/serial_link.c b/quantum/serial_link/system/serial_link.c
index 75c7e77a7..b3bee62a1 100644
--- a/quantum/serial_link/system/serial_link.c
+++ b/quantum/serial_link/system/serial_link.c
@@ -212,7 +212,7 @@ void serial_link_update(void) {
systime_t current_time = chVTGetSystemTimeX();
systime_t delta = current_time - last_update;
- if (changed || delta > US2ST(1000)) {
+ if (changed || delta > US2ST(5000)) {
last_update = current_time;
last_matrix = matrix;
matrix_object_t* m = begin_write_keyboard_matrix();
diff --git a/quantum/visualizer/example_integration/callbacks.c b/quantum/visualizer/example_integration/callbacks.c
deleted file mode 100644
index 2539615d6..000000000
--- a/quantum/visualizer/example_integration/callbacks.c
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
-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 "keyboard.h"
-#include "action_layer.h"
-#include "visualizer.h"
-#include "host.h"
-
-void post_keyboard_init(void) {
- visualizer_init();
-}
-
-void post_keyboard_task() {
- visualizer_set_state(default_layer_state, layer_state, host_keyboard_leds());
-}
diff --git a/quantum/visualizer/example_integration/gfxconf.h b/quantum/visualizer/example_integration/gfxconf.h
deleted file mode 100644
index 304c5d187..000000000
--- a/quantum/visualizer/example_integration/gfxconf.h
+++ /dev/null
@@ -1,325 +0,0 @@
-/**
- * This file has a different license to the rest of the uGFX system.
- * You can copy, modify and distribute this file as you see fit.
- * You do not need to publish your source modifications to this file.
- * The only thing you are not permitted to do is to relicense it
- * under a different license.
- */
-
-/**
- * Copy this file into your project directory and rename it as gfxconf.h
- * Edit your copy to turn on the uGFX features you want to use.
- * The values below are the defaults.
- *
- * Only remove the comments from lines where you want to change the
- * default value. This allows definitions to be included from
- * driver makefiles when required and provides the best future
- * compatibility for your project.
- *
- * Please use spaces instead of tabs in this file.
- */
-
-#ifndef _GFXCONF_H
-#define _GFXCONF_H
-
-
-///////////////////////////////////////////////////////////////////////////
-// GOS - One of these must be defined, preferably in your Makefile //
-///////////////////////////////////////////////////////////////////////////
-#define GFX_USE_OS_CHIBIOS TRUE
-//#define GFX_USE_OS_FREERTOS FALSE
-// #define GFX_FREERTOS_USE_TRACE FALSE
-//#define GFX_USE_OS_WIN32 FALSE
-//#define GFX_USE_OS_LINUX FALSE
-//#define GFX_USE_OS_OSX FALSE
-//#define GFX_USE_OS_ECOS FALSE
-//#define GFX_USE_OS_RAWRTOS FALSE
-//#define GFX_USE_OS_ARDUINO FALSE
-//#define GFX_USE_OS_KEIL FALSE
-//#define GFX_USE_OS_CMSIS FALSE
-//#define GFX_USE_OS_RAW32 FALSE
-// #define INTERRUPTS_OFF() optional_code
-// #define INTERRUPTS_ON() optional_code
-// These are not defined by default for some reason
-#define GOS_NEED_X_THREADS FALSE
-#define GOS_NEED_X_HEAP FALSE
-
-// Options that (should where relevant) apply to all operating systems
- #define GFX_NO_INLINE FALSE
-// #define GFX_COMPILER GFX_COMPILER_UNKNOWN
-// #define GFX_CPU GFX_CPU_UNKNOWN
-// #define GFX_OS_HEAP_SIZE 0
-// #define GFX_OS_NO_INIT FALSE
-// #define GFX_OS_INIT_NO_WARNING FALSE
-// #define GFX_OS_PRE_INIT_FUNCTION myHardwareInitRoutine
-// #define GFX_OS_EXTRA_INIT_FUNCTION myOSInitRoutine
-// #define GFX_OS_EXTRA_DEINIT_FUNCTION myOSDeInitRoutine
-
-
-///////////////////////////////////////////////////////////////////////////
-// GDISP //
-///////////////////////////////////////////////////////////////////////////
-#define GFX_USE_GDISP TRUE
-
-//#define GDISP_NEED_AUTOFLUSH FALSE
-//#define GDISP_NEED_TIMERFLUSH FALSE
-//#define GDISP_NEED_VALIDATION TRUE
-//#define GDISP_NEED_CLIP TRUE
-//#define GDISP_NEED_CIRCLE FALSE
-//#define GDISP_NEED_ELLIPSE FALSE
-//#define GDISP_NEED_ARC FALSE
-//#define GDISP_NEED_ARCSECTORS FALSE
-//#define GDISP_NEED_CONVEX_POLYGON FALSE
-//#define GDISP_NEED_SCROLL FALSE
-//#define GDISP_NEED_PIXELREAD FALSE
-//#define GDISP_NEED_CONTROL FALSE
-//#define GDISP_NEED_QUERY FALSE
-//#define GDISP_NEED_MULTITHREAD FALSE
-//#define GDISP_NEED_STREAMING FALSE
-#define GDISP_NEED_TEXT TRUE
-// #define GDISP_NEED_TEXT_WORDWRAP FALSE
-// #define GDISP_NEED_ANTIALIAS FALSE
-// #define GDISP_NEED_UTF8 FALSE
- #define GDISP_NEED_TEXT_KERNING TRUE
-// #define GDISP_INCLUDE_FONT_UI1 FALSE
-// #define GDISP_INCLUDE_FONT_UI2 FALSE // The smallest preferred font.
-// #define GDISP_INCLUDE_FONT_LARGENUMBERS FALSE
-// #define GDISP_INCLUDE_FONT_DEJAVUSANS10 FALSE
-// #define GDISP_INCLUDE_FONT_DEJAVUSANS12 FALSE
-// #define GDISP_INCLUDE_FONT_DEJAVUSANS16 FALSE
-// #define GDISP_INCLUDE_FONT_DEJAVUSANS20 FALSE
-// #define GDISP_INCLUDE_FONT_DEJAVUSANS24 FALSE
-// #define GDISP_INCLUDE_FONT_DEJAVUSANS32 FALSE
- #define GDISP_INCLUDE_FONT_DEJAVUSANSBOLD12 TRUE
-// #define GDISP_INCLUDE_FONT_FIXED_10X20 FALSE
-// #define GDISP_INCLUDE_FONT_FIXED_7X14 FALSE
- #define GDISP_INCLUDE_FONT_FIXED_5X8 TRUE
-// #define GDISP_INCLUDE_FONT_DEJAVUSANS12_AA FALSE
-// #define GDISP_INCLUDE_FONT_DEJAVUSANS16_AA FALSE
-// #define GDISP_INCLUDE_FONT_DEJAVUSANS20_AA FALSE
-// #define GDISP_INCLUDE_FONT_DEJAVUSANS24_AA FALSE
-// #define GDISP_INCLUDE_FONT_DEJAVUSANS32_AA FALSE
-// #define GDISP_INCLUDE_FONT_DEJAVUSANSBOLD12_AA FALSE
-// #define GDISP_INCLUDE_USER_FONTS FALSE
-
-//#define GDISP_NEED_IMAGE FALSE
-// #define GDISP_NEED_IMAGE_NATIVE FALSE
-// #define GDISP_NEED_IMAGE_GIF FALSE
-// #define GDISP_NEED_IMAGE_BMP FALSE
-// #define GDISP_NEED_IMAGE_BMP_1 FALSE
-// #define GDISP_NEED_IMAGE_BMP_4 FALSE
-// #define GDISP_NEED_IMAGE_BMP_4_RLE FALSE
-// #define GDISP_NEED_IMAGE_BMP_8 FALSE
-// #define GDISP_NEED_IMAGE_BMP_8_RLE FALSE
-// #define GDISP_NEED_IMAGE_BMP_16 FALSE
-// #define GDISP_NEED_IMAGE_BMP_24 FALSE
-// #define GDISP_NEED_IMAGE_BMP_32 FALSE
-// #define GDISP_NEED_IMAGE_JPG FALSE
-// #define GDISP_NEED_IMAGE_PNG FALSE
-// #define GDISP_NEED_IMAGE_ACCOUNTING FALSE
-
-//#define GDISP_NEED_PIXMAP FALSE
-// #define GDISP_NEED_PIXMAP_IMAGE FALSE
-
-//#define GDISP_DEFAULT_ORIENTATION GDISP_ROTATE_LANDSCAPE // If not defined the native hardware orientation is used.
-//#define GDISP_LINEBUF_SIZE 128
-//#define GDISP_STARTUP_COLOR Black
-#define GDISP_NEED_STARTUP_LOGO FALSE
-
-//#define GDISP_TOTAL_DISPLAYS 1
-
-//#define GDISP_DRIVER_LIST GDISPVMT_Win32, GDISPVMT_Win32
-// #ifdef GDISP_DRIVER_LIST
-// // For code and speed optimization define as TRUE or FALSE if all controllers have the same capability
-// #define GDISP_HARDWARE_STREAM_WRITE FALSE
-// #define GDISP_HARDWARE_STREAM_READ FALSE
-// #define GDISP_HARDWARE_STREAM_POS FALSE
-// #define GDISP_HARDWARE_DRAWPIXEL FALSE
-// #define GDISP_HARDWARE_CLEARS FALSE
-// #define GDISP_HARDWARE_FILLS FALSE
-// #define GDISP_HARDWARE_BITFILLS FALSE
-// #define GDISP_HARDWARE_SCROLL FALSE
-// #define GDISP_HARDWARE_PIXELREAD FALSE
-// #define GDISP_HARDWARE_CONTROL FALSE
-// #define GDISP_HARDWARE_QUERY FALSE
-// #define GDISP_HARDWARE_CLIP FALSE
-
- #define GDISP_PIXELFORMAT GDISP_PIXELFORMAT_RGB888
-// #endif
-
-// The custom format is not defined for some reason, so define it as error
-// so we don't get compiler warnings
-#define GDISP_PIXELFORMAT_CUSTOM GDISP_PIXELFORMAT_ERROR
-
-#define GDISP_USE_GFXNET FALSE
-// #define GDISP_GFXNET_PORT 13001
-// #define GDISP_GFXNET_CUSTOM_LWIP_STARTUP FALSE
-// #define GDISP_DONT_WAIT_FOR_NET_DISPLAY FALSE
-// #define GDISP_GFXNET_UNSAFE_SOCKETS FALSE
-
-
-///////////////////////////////////////////////////////////////////////////
-// GWIN //
-///////////////////////////////////////////////////////////////////////////
-#define GFX_USE_GWIN FALSE
-
-//#define GWIN_NEED_WINDOWMANAGER FALSE
-// #define GWIN_REDRAW_IMMEDIATE FALSE
-// #define GWIN_REDRAW_SINGLEOP FALSE
-// #define GWIN_NEED_FLASHING FALSE
-// #define GWIN_FLASHING_PERIOD 250
-
-//#define GWIN_NEED_CONSOLE FALSE
-// #define GWIN_CONSOLE_USE_HISTORY FALSE
-// #define GWIN_CONSOLE_HISTORY_AVERAGING FALSE
-// #define GWIN_CONSOLE_HISTORY_ATCREATE FALSE
-// #define GWIN_CONSOLE_ESCSEQ FALSE
-// #define GWIN_CONSOLE_USE_BASESTREAM FALSE
-// #define GWIN_CONSOLE_USE_FLOAT FALSE
-//#define GWIN_NEED_GRAPH FALSE
-//#define GWIN_NEED_GL3D FALSE
-
-//#define GWIN_NEED_WIDGET FALSE
-//#define GWIN_FOCUS_HIGHLIGHT_WIDTH 1
-// #define GWIN_NEED_LABEL FALSE
-// #define GWIN_LABEL_ATTRIBUTE FALSE
-// #define GWIN_NEED_BUTTON FALSE
-// #define GWIN_BUTTON_LAZY_RELEASE FALSE
-// #define GWIN_NEED_SLIDER FALSE
-// #define GWIN_SLIDER_NOSNAP FALSE
-// #define GWIN_SLIDER_DEAD_BAND 5
-// #define GWIN_SLIDER_TOGGLE_INC 20
-// #define GWIN_NEED_CHECKBOX FALSE
-// #define GWIN_NEED_IMAGE FALSE
-// #define GWIN_NEED_IMAGE_ANIMATION FALSE
-// #define GWIN_NEED_RADIO FALSE
-// #define GWIN_NEED_LIST FALSE
-// #define GWIN_NEED_LIST_IMAGES FALSE
-// #define GWIN_NEED_PROGRESSBAR FALSE
-// #define GWIN_PROGRESSBAR_AUTO FALSE
-// #define GWIN_NEED_KEYBOARD FALSE
-// #define GWIN_KEYBOARD_DEFAULT_LAYOUT VirtualKeyboard_English1
-// #define GWIN_NEED_KEYBOARD_ENGLISH1 TRUE
-// #define GWIN_NEED_TEXTEDIT FALSE
-// #define GWIN_FLAT_STYLING FALSE
-// #define GWIN_WIDGET_TAGS FALSE
-
-//#define GWIN_NEED_CONTAINERS FALSE
-// #define GWIN_NEED_CONTAINER FALSE
-// #define GWIN_NEED_FRAME FALSE
-// #define GWIN_NEED_TABSET FALSE
-// #define GWIN_TABSET_TABHEIGHT 18
-
-
-///////////////////////////////////////////////////////////////////////////
-// GEVENT //
-///////////////////////////////////////////////////////////////////////////
-#define GFX_USE_GEVENT FALSE
-
-//#define GEVENT_ASSERT_NO_RESOURCE FALSE
-//#define GEVENT_MAXIMUM_SIZE 32
-//#define GEVENT_MAX_SOURCE_LISTENERS 32
-
-
-///////////////////////////////////////////////////////////////////////////
-// GTIMER //
-///////////////////////////////////////////////////////////////////////////
-#define GFX_USE_GTIMER FALSE
-
-//#define GTIMER_THREAD_PRIORITY HIGH_PRIORITY
-//#define GTIMER_THREAD_WORKAREA_SIZE 2048
-
-
-///////////////////////////////////////////////////////////////////////////
-// GQUEUE //
-///////////////////////////////////////////////////////////////////////////
-#define GFX_USE_GQUEUE FALSE
-
-//#define GQUEUE_NEED_ASYNC FALSE
-//#define GQUEUE_NEED_GSYNC FALSE
-//#define GQUEUE_NEED_FSYNC FALSE
-//#define GQUEUE_NEED_BUFFERS FALSE
-
-///////////////////////////////////////////////////////////////////////////
-// GINPUT //
-///////////////////////////////////////////////////////////////////////////
-#define GFX_USE_GINPUT FALSE
-
-//#define GINPUT_NEED_MOUSE FALSE
-// #define GINPUT_TOUCH_STARTRAW FALSE
-// #define GINPUT_TOUCH_NOTOUCH FALSE
-// #define GINPUT_TOUCH_NOCALIBRATE FALSE
-// #define GINPUT_TOUCH_NOCALIBRATE_GUI FALSE
-// #define GINPUT_MOUSE_POLL_PERIOD 25
-// #define GINPUT_MOUSE_CLICK_TIME 300
-// #define GINPUT_TOUCH_CXTCLICK_TIME 700
-// #define GINPUT_TOUCH_USER_CALIBRATION_LOAD FALSE
-// #define GINPUT_TOUCH_USER_CALIBRATION_SAVE FALSE
-// #define GMOUSE_DRIVER_LIST GMOUSEVMT_Win32, GMOUSEVMT_Win32
-//#define GINPUT_NEED_KEYBOARD FALSE
-// #define GINPUT_KEYBOARD_POLL_PERIOD 200
-// #define GKEYBOARD_DRIVER_LIST GKEYBOARDVMT_Win32, GKEYBOARDVMT_Win32
-// #define GKEYBOARD_LAYOUT_OFF FALSE
-// #define GKEYBOARD_LAYOUT_SCANCODE2_US FALSE
-//#define GINPUT_NEED_TOGGLE FALSE
-//#define GINPUT_NEED_DIAL FALSE
-
-
-///////////////////////////////////////////////////////////////////////////
-// GFILE //
-///////////////////////////////////////////////////////////////////////////
-#define GFX_USE_GFILE FALSE
-
-//#define GFILE_NEED_PRINTG FALSE
-//#define GFILE_NEED_SCANG FALSE
-//#define GFILE_NEED_STRINGS FALSE
-//#define GFILE_NEED_FILELISTS FALSE
-//#define GFILE_NEED_STDIO FALSE
-//#define GFILE_NEED_NOAUTOMOUNT FALSE
-//#define GFILE_NEED_NOAUTOSYNC FALSE
-
-//#define GFILE_NEED_MEMFS FALSE
-//#define GFILE_NEED_ROMFS FALSE
-//#define GFILE_NEED_RAMFS FALSE
-//#define GFILE_NEED_FATFS FALSE
-//#define GFILE_NEED_NATIVEFS FALSE
-//#define GFILE_NEED_CHBIOSFS FALSE
-
-//#define GFILE_ALLOW_FLOATS FALSE
-//#define GFILE_ALLOW_DEVICESPECIFIC FALSE
-//#define GFILE_MAX_GFILES 3
-
-///////////////////////////////////////////////////////////////////////////
-// GADC //
-///////////////////////////////////////////////////////////////////////////
-#define GFX_USE_GADC FALSE
-
-//#define GADC_MAX_LOWSPEED_DEVICES 4
-
-
-///////////////////////////////////////////////////////////////////////////
-// GAUDIO //
-///////////////////////////////////////////////////////////////////////////
-#define GFX_USE_GAUDIO FALSE
-// There seems to be a bug in the ugfx code, the wrong define is used
-// So define it in order to avoid warnings
-#define GFX_USE_GAUDIN GFX_USE_GAUDIO
-// #define GAUDIO_NEED_PLAY FALSE
-// #define GAUDIO_NEED_RECORD FALSE
-
-
-///////////////////////////////////////////////////////////////////////////
-// GMISC //
-///////////////////////////////////////////////////////////////////////////
-#define GFX_USE_GMISC FALSE
-
-//#define GMISC_NEED_ARRAYOPS FALSE
-//#define GMISC_NEED_FASTTRIG FALSE
-//#define GMISC_NEED_FIXEDTRIG FALSE
-//#define GMISC_NEED_INVSQRT FALSE
-// #define GMISC_INVSQRT_MIXED_ENDIAN FALSE
-// #define GMISC_INVSQRT_REAL_SLOW FALSE
-//#define GMISC_NEED_MATRIXFLOAT2D FALSE
-//#define GMISC_NEED_MATRIXFIXED2D FALSE
-
-#endif /* _GFXCONF_H */
diff --git a/quantum/visualizer/example_integration/lcd_backlight_hal.c b/quantum/visualizer/example_integration/lcd_backlight_hal.c
deleted file mode 100644
index 913131b16..000000000
--- a/quantum/visualizer/example_integration/lcd_backlight_hal.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
-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 "hal.h"
-
-#define RED_PIN 1
-#define GREEN_PIN 2
-#define BLUE_PIN 3
-#define CHANNEL_RED FTM0->CHANNEL[0]
-#define CHANNEL_GREEN FTM0->CHANNEL[1]
-#define CHANNEL_BLUE FTM0->CHANNEL[2]
-
-#define RGB_PORT PORTC
-#define RGB_PORT_GPIO GPIOC
-
-// Base FTM clock selection (72 MHz system clock)
-// @ 0xFFFF period, 72 MHz / (0xFFFF * 2) = Actual period
-// Higher pre-scalar will use the most power (also look the best)
-// Pre-scalar calculations
-// 0 - 72 MHz -> 549 Hz
-// 1 - 36 MHz -> 275 Hz
-// 2 - 18 MHz -> 137 Hz
-// 3 - 9 MHz -> 69 Hz (Slightly visible flicker)
-// 4 - 4 500 kHz -> 34 Hz (Visible flickering)
-// 5 - 2 250 kHz -> 17 Hz
-// 6 - 1 125 kHz -> 9 Hz
-// 7 - 562 500 Hz -> 4 Hz
-// Using a higher pre-scalar without flicker is possible but FTM0_MOD will need to be reduced
-// Which will reduce the brightness range
-#define PRESCALAR_DEFINE 0
-
-void lcd_backlight_hal_init(void) {
- // Setup Backlight
- SIM->SCGC6 |= SIM_SCGC6_FTM0;
- FTM0->CNT = 0; // Reset counter
-
- // PWM Period
- // 16-bit maximum
- FTM0->MOD = 0xFFFF;
-
- // Set FTM to PWM output - Edge Aligned, Low-true pulses
-#define CNSC_MODE FTM_SC_CPWMS | FTM_SC_PS(4) | FTM_SC_CLKS(0)
- CHANNEL_RED.CnSC = CNSC_MODE;
- CHANNEL_GREEN.CnSC = CNSC_MODE;
- CHANNEL_BLUE.CnSC = CNSC_MODE;
-
- // System clock, /w prescalar setting
- FTM0->SC = FTM_SC_CLKS(1) | FTM_SC_PS(PRESCALAR_DEFINE);
-
- CHANNEL_RED.CnV = 0;
- CHANNEL_GREEN.CnV = 0;
- CHANNEL_BLUE.CnV = 0;
-
- RGB_PORT_GPIO->PDDR |= (1 << RED_PIN);
- RGB_PORT_GPIO->PDDR |= (1 << GREEN_PIN);
- RGB_PORT_GPIO->PDDR |= (1 << BLUE_PIN);
-
-#define RGB_MODE PORTx_PCRn_SRE | PORTx_PCRn_DSE | PORTx_PCRn_MUX(4)
- RGB_PORT->PCR[RED_PIN] = RGB_MODE;
- RGB_PORT->PCR[GREEN_PIN] = RGB_MODE;
- RGB_PORT->PCR[BLUE_PIN] = RGB_MODE;
-}
-
-void lcd_backlight_hal_color(uint16_t r, uint16_t g, uint16_t b) {
- CHANNEL_RED.CnV = r;
- CHANNEL_GREEN.CnV = g;
- CHANNEL_BLUE.CnV = b;
-}
-
diff --git a/quantum/visualizer/example_integration/visualizer_user.c b/quantum/visualizer/example_integration/visualizer_user.c
deleted file mode 100644
index fc09fe2ea..000000000
--- a/quantum/visualizer/example_integration/visualizer_user.c
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
-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.
-*/
-
-// Currently we are assuming that both the backlight and LCD are enabled
-// But it's entirely possible to write a custom visualizer that use only
-// one of them
-#ifndef LCD_BACKLIGHT_ENABLE
-#error This visualizer needs that LCD backlight is enabled
-#endif
-
-#ifndef LCD_ENABLE
-#error This visualizer needs that LCD is enabled
-#endif
-
-#include "visualizer.h"
-
-static const char* welcome_text[] = {"TMK", "Infinity Ergodox"};
-
-// Just an example how to write custom keyframe functions, we could have moved
-// all this into the init function
-bool display_welcome(keyframe_animation_t* animation, visualizer_state_t* 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
- gdispDrawString(0, 3, welcome_text[0], state->font_dejavusansbold12, Black);
- gdispDrawString(0, 15, welcome_text[1], state->font_dejavusansbold12, Black);
- // Always remember to flush the display
- gdispFlush();
- // you could set the backlight color as well, but we won't do it here, since
- // it's part of the following animation
- // lcd_backlight_color(hue, saturation, intensity);
- // We don't need constant updates, just drawing the screen once is enough
- return false;
-}
-
-// Feel free to modify the animations below, or even add new ones if needed
-
-// Don't worry, if the startup animation is long, you can use the keyboard like normal
-// during that time
-static keyframe_animation_t startup_animation = {
- .num_frames = 4,
- .loop = false,
- .frame_lengths = {0, MS2ST(1000), MS2ST(5000), 0},
- .frame_functions = {display_welcome, keyframe_animate_backlight_color, keyframe_no_operation, enable_visualization},
-};
-
-// The color animation animates the LCD color when you change layers
-static keyframe_animation_t color_animation = {
- .num_frames = 2,
- .loop = false,
- // Note that there's a 200 ms no-operation frame,
- // this prevents the color from changing when activating the layer
- // momentarily
- .frame_lengths = {MS2ST(200), MS2ST(500)},
- .frame_functions = {keyframe_no_operation, keyframe_animate_backlight_color},
-};
-
-// The LCD animation alternates between the layer name display and a
-// bitmap that displays all active layers
-static keyframe_animation_t lcd_animation = {
- .num_frames = 2,
- .loop = true,
- .frame_lengths = {MS2ST(2000), MS2ST(2000)},
- .frame_functions = {keyframe_display_layer_text, keyframe_display_layer_bitmap},
-};
-
-void initialize_user_visualizer(visualizer_state_t* state) {
- // The brightness will be dynamically adjustable in the future
- // But for now, change it here.
- lcd_backlight_brightness(0x50);
- state->current_lcd_color = LCD_COLOR(0x00, 0x00, 0xFF);
- state->target_lcd_color = LCD_COLOR(0x10, 0xFF, 0xFF);
- start_keyframe_animation(&startup_animation);
-}
-
-void update_user_visualizer_state(visualizer_state_t* state) {
- // Add more tests, change the colors and layer texts here
- // Usually you want to check the high bits (higher layers first)
- // because that's the order layers are processed for keypresses
- // You can for check for example:
- // state->status.layer
- // state->status.default_layer
- // state->status.leds (see led.h for available statuses)
- if (state->status.layer & 0x2) {
- state->target_lcd_color = LCD_COLOR(0xA0, 0xB0, 0xFF);
- state->layer_text = "Layer 2";
- }
- else {
- state->target_lcd_color = LCD_COLOR(0x50, 0xB0, 0xFF);
- state->layer_text = "Layer 1";
- }
- // You can also stop existing animations, and start your custom ones here
- // remember that you should normally have only one animation for the LCD
- // and one for the background. But you can also combine them if you want.
- start_keyframe_animation(&lcd_animation);
- start_keyframe_animation(&color_animation);
-}
diff --git a/quantum/visualizer/lcd_backlight.c b/quantum/visualizer/lcd_backlight.c
index 70187d1e0..00de3fab5 100644
--- a/quantum/visualizer/lcd_backlight.c
+++ b/quantum/visualizer/lcd_backlight.c
@@ -25,10 +25,10 @@ SOFTWARE.
#include "lcd_backlight.h"
#include <math.h>
-static uint8_t current_hue = 0x00;
-static uint8_t current_saturation = 0x00;
-static uint8_t current_intensity = 0xFF;
-static uint8_t current_brightness = 0x7F;
+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();
diff --git a/quantum/visualizer/lcd_backlight.h b/quantum/visualizer/lcd_backlight.h
index dd3e37a06..14dde64a1 100644
--- a/quantum/visualizer/lcd_backlight.h
+++ b/quantum/visualizer/lcd_backlight.h
@@ -32,6 +32,10 @@ SOFTWARE.
#define LCD_SAT(color) ((color >> 8) & 0xFF)
#define LCD_INT(color) (color & 0xFF)
+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);
diff --git a/quantum/visualizer/lcd_backlight_keyframes.c b/quantum/visualizer/lcd_backlight_keyframes.c
new file mode 100644
index 000000000..8436d4e3d
--- /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 000000000..e1c125cf9
--- /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 000000000..df11861dd
--- /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 ", 5);
+ pos += 5;
+ }
+ 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 000000000..2e912b4c7
--- /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_test.c b/quantum/visualizer/led_keyframes.c
index a9abace8d..2dacd990d 100644
--- a/quantum/visualizer/led_test.c
+++ b/quantum/visualizer/led_keyframes.c
@@ -21,50 +21,9 @@ 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"
#include "math.h"
-
-#define CROSSFADE_TIME 1000
-#define GRADIENT_TIME 3000
-
-keyframe_animation_t led_test_animation = {
- .num_frames = 14,
- .loop = true,
- .frame_lengths = {
- gfxMillisecondsToTicks(1000), // fade in
- gfxMillisecondsToTicks(1000), // no op (leds on)
- gfxMillisecondsToTicks(1000), // fade out
- 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(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(CROSSFADE_TIME), // 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_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,
- },
-};
+#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];
@@ -96,19 +55,19 @@ static uint8_t compute_gradient_color(float t, float index, float num) {
return (uint8_t)(255.0f * v);
}
-bool keyframe_fade_in_all_leds(keyframe_animation_t* animation, visualizer_state_t* state) {
+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 keyframe_fade_out_all_leds(keyframe_animation_t* animation, visualizer_state_t* state) {
+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 keyframe_led_left_to_right_gradient(keyframe_animation_t* animation, visualizer_state_t* state) {
+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;
@@ -120,7 +79,7 @@ bool keyframe_led_left_to_right_gradient(keyframe_animation_t* animation, visual
return true;
}
-bool keyframe_led_top_to_bottom_gradient(keyframe_animation_t* animation, visualizer_state_t* state) {
+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;
@@ -139,7 +98,7 @@ static void copy_current_led_state(uint8_t* dest) {
}
}
}
-bool keyframe_led_crossfade(keyframe_animation_t* animation, visualizer_state_t* state) {
+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]);
@@ -155,14 +114,14 @@ 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) {
+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 keyframe_normal_led_orientation(keyframe_animation_t* animation, visualizer_state_t* state) {
+bool led_keyframe_normal_orientation(keyframe_animation_t* animation, visualizer_state_t* state) {
(void)state;
(void)animation;
gdispGSetOrientation(LED_DISPLAY, GDISP_ROTATE_0);
diff --git a/quantum/visualizer/led_test.h b/quantum/visualizer/led_keyframes.h
index 5e2325753..a68943041 100644
--- a/quantum/visualizer/led_test.h
+++ b/quantum/visualizer/led_keyframes.h
@@ -22,20 +22,20 @@ 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_
+#ifndef LED_KEYFRAMES_H
+#define LED_KEYFRAMES_H
#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);
-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);
+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);
extern keyframe_animation_t led_test_animation;
-#endif /* TMK_VISUALIZER_LED_TEST_H_ */
+#endif /* LED_KEYFRAMES_H */
diff --git a/quantum/visualizer/resources/lcd_logo.c b/quantum/visualizer/resources/lcd_logo.c
new file mode 100644
index 000000000..d1a0ffa7f
--- /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, 0x00, 0x00, 0x00,
+ 0x00, 0x38, 0x38, 0x38, 0x09, 0x55, 0x42, 0xaa, 0xaa, 0xaa, 0xa8, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x38, 0x38, 0x38, 0x09, 0x55, 0x82, 0x28, 0xaa, 0xae, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x38, 0x38, 0x38, 0x09, 0x55, 0x43, 0x28, 0xaa, 0xaa, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x38, 0x38, 0x38, 0x0a, 0x55, 0x42, 0x28, 0xaa, 0xaa, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x38, 0x38, 0x38, 0x05, 0x45, 0x42, 0x28, 0x89, 0x4a, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x18, 0x38, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x1c, 0x38, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x0e, 0x38, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x03, 0xff, 0x80, 0x04, 0x45, 0x14, 0xa4, 0x92, 0x83, 0x52, 0x22, 0x22, 0x36, 0x00, 0x00,
+ 0x00, 0x00, 0x38, 0x00, 0x0a, 0xaa, 0xaa, 0xaa, 0xba, 0x84, 0x55, 0x55, 0x57, 0x45, 0x00, 0x00,
+ 0x00, 0x00, 0x38, 0x00, 0x08, 0xaa, 0xaa, 0xaa, 0x92, 0xb2, 0x55, 0x55, 0x42, 0x65, 0x00, 0x00,
+ 0x00, 0x00, 0x38, 0x00, 0x08, 0xaa, 0xaa, 0xaa, 0x92, 0x81, 0x56, 0x65, 0x42, 0x45, 0x00, 0x00,
+ 0x00, 0x00, 0x38, 0x00, 0x0a, 0xaa, 0xaa, 0xaa, 0x92, 0x81, 0x54, 0x45, 0x42, 0x45, 0x00, 0x00,
+ 0x00, 0x00, 0x38, 0x00, 0x04, 0x48, 0xa2, 0x4a, 0x89, 0x06, 0x24, 0x42, 0x41, 0x36, 0x00, 0x00,
+ 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
diff --git a/quantum/visualizer/resources/lcd_logo.png b/quantum/visualizer/resources/lcd_logo.png
new file mode 100644
index 000000000..6cf26fc67
--- /dev/null
+++ b/quantum/visualizer/resources/lcd_logo.png
Binary files differ
diff --git a/quantum/visualizer/resources/resources.h b/quantum/visualizer/resources/resources.h
new file mode 100644
index 000000000..1ea27a536
--- /dev/null
+++ b/quantum/visualizer/resources/resources.h
@@ -0,0 +1,27 @@
+/* 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_RESOURCES_RESOURCES_H_
+#define QUANTUM_VISUALIZER_RESOURCES_RESOURCES_H_
+
+#include <stdint.h>
+
+#ifdef LCD_ENABLE
+extern const uint8_t resource_lcd_logo[];
+#endif
+
+
+#endif /* QUANTUM_VISUALIZER_RESOURCES_RESOURCES_H_ */
diff --git a/quantum/visualizer/visualizer.c b/quantum/visualizer/visualizer.c
index 5826d909e..6f134097f 100644
--- a/quantum/visualizer/visualizer.c
+++ b/quantum/visualizer/visualizer.c
@@ -48,20 +48,22 @@ SOFTWARE.
#include "serial_link/system/serial_link.h"
#endif
+#include "action_util.h"
+
// Define this in config.h
#ifndef VISUALIZER_THREAD_PRIORITY
#define "Visualizer thread priority not defined"
#endif
-// mods status
-#include "action_util.h"
-
static visualizer_keyboard_status_t current_status = {
.layer = 0xFFFFFFFF,
.default_layer = 0xFFFFFFFF,
.mods = 0xFF,
.leds = 0xFFFFFFFF,
.suspended = false,
+#ifdef VISUALIZER_USER_DATA_SIZE
+ .user_data = {0}
+#endif
};
static bool same_status(visualizer_keyboard_status_t* status1, visualizer_keyboard_status_t* status2) {
@@ -69,11 +71,19 @@ static bool same_status(visualizer_keyboard_status_t* status1, visualizer_keyboa
status1->default_layer == status2->default_layer &&
status1->mods == status2->mods &&
status1->leds == status2->leds &&
- status1->suspended == status2->suspended;
+ status1->suspended == status2->suspended
+#ifdef VISUALIZER_USER_DATA_SIZE
+ && memcmp(status1->user_data, status2->user_data, VISUALIZER_USER_DATA_SIZE) == 0
+#endif
+ ;
}
static bool visualizer_enabled = false;
+#ifdef VISUALIZER_USER_DATA_SIZE
+static uint8_t user_data[VISUALIZER_USER_DATA_SIZE];
+#endif
+
#define MAX_SIMULTANEOUS_ANIMATIONS 4
static keyframe_animation_t* animations[MAX_SIMULTANEOUS_ANIMATIONS] = {};
@@ -144,6 +154,14 @@ void stop_all_keyframe_animations(void) {
}
}
+static uint8_t get_num_running_animations(void) {
+ uint8_t count = 0;
+ for (int i=0;i<MAX_SIMULTANEOUS_ANIMATIONS;i++) {
+ count += animations[i] ? 1 : 0;
+ }
+ return count;
+}
+
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,
@@ -212,175 +230,6 @@ void run_next_keyframe(keyframe_animation_t* animation, visualizer_state_t* stat
(*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;
- return false;
-}
-
-#ifdef LCD_BACKLIGHT_ENABLE
-bool keyframe_animate_backlight_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 keyframe_set_backlight_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;
-}
-#endif // LCD_BACKLIGHT_ENABLE
-
-#ifdef LCD_ENABLE
-bool 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);
- gdispFlush();
- 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 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);
- gdispFlush();
- 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 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);
-
- gdispFlush();
- return false;
-}
-#endif // LCD_ENABLE
-
-bool keyframe_disable_lcd_and_backlight(keyframe_animation_t* animation, visualizer_state_t* state) {
- (void)animation;
- (void)state;
-#ifdef LCD_ENABLE
- gdispSetPowerMode(powerOff);
-#endif
-#ifdef LCD_BACKLIGHT_ENABLE
- lcd_backlight_hal_color(0, 0, 0);
-#endif
- return false;
-}
-
-bool keyframe_enable_lcd_and_backlight(keyframe_animation_t* animation, visualizer_state_t* state) {
- (void)animation;
- (void)state;
-#ifdef LCD_ENABLE
- gdispSetPowerMode(powerOn);
-#endif
- return false;
-}
-
-bool enable_visualization(keyframe_animation_t* animation, visualizer_state_t* state) {
- (void)animation;
- (void)state;
- dprint("User visualizer inited\n");
- visualizer_enabled = true;
- return false;
-}
-
// TODO: Optimize the stack size, this is probably way too big
static DECLARE_THREAD_STACK(visualizerThreadStack, 1024);
static DECLARE_THREAD_FUNCTION(visualizerThread, arg) {
@@ -396,6 +245,9 @@ static DECLARE_THREAD_FUNCTION(visualizerThread, arg) {
.mods = 0xFF,
.leds = 0xFFFFFFFF,
.suspended = false,
+#ifdef VISUALIZER_USER_DATA_SIZE
+ .user_data = {0},
+#endif
};
visualizer_state_t state = {
@@ -418,13 +270,15 @@ static DECLARE_THREAD_FUNCTION(visualizerThread, arg) {
systemticks_t sleep_time = TIME_INFINITE;
systemticks_t current_time = gfxSystemTicks();
+ bool force_update = true;
while(true) {
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, &current_status)) {
+ if (force_update || !same_status(&state.status, &current_status)) {
+ force_update = false;
if (visualizer_enabled) {
if (current_status.suspended) {
stop_all_keyframe_animations();
@@ -433,8 +287,9 @@ static DECLARE_THREAD_FUNCTION(visualizerThread, arg) {
user_visualizer_suspend(&state);
}
else {
+ visualizer_keyboard_status_t prev_status = state.status;
state.status = current_status;
- update_user_visualizer_state(&state);
+ update_user_visualizer_state(&state, &prev_status);
}
state.prev_lcd_color = state.current_lcd_color;
}
@@ -458,13 +313,17 @@ static DECLARE_THREAD_FUNCTION(visualizerThread, arg) {
gdispGFlush(LED_DISPLAY);
#endif
+#ifdef LCD_ENABLE
+ gdispGFlush(LCD_DISPLAY);
+#endif
+
#ifdef EMULATOR
draw_emulator();
#endif
- // The animation can enable the visualizer
- // And we might need to update the state when that happens
- // so don't sleep
- if (enabled != visualizer_enabled) {
+ // Enable the visualizer when the startup or the suspend animation has finished
+ if (!visualizer_enabled && state.status.suspended == false && get_num_running_animations() == 0) {
+ visualizer_enabled = true;
+ force_update = true;
sleep_time = 0;
}
@@ -554,6 +413,12 @@ uint8_t visualizer_get_mods() {
return mods;
}
+#ifdef VISUALIZER_USER_DATA_SIZE
+void visualizer_set_user_data(void* u) {
+ memcpy(user_data, u, VISUALIZER_USER_DATA_SIZE);
+}
+#endif
+
void visualizer_update(uint32_t default_state, uint32_t state, uint8_t mods, uint32_t leds) {
// Note that there's a small race condition here, the thread could read
// a state where one of these are set but not the other. But this should
@@ -582,6 +447,9 @@ void visualizer_update(uint32_t default_state, uint32_t state, uint8_t mods, uin
.leds = leds,
.suspended = current_status.suspended,
};
+#ifdef VISUALIZER_USER_DATA_SIZE
+ memcpy(new_status.user_data, user_data, VISUALIZER_USER_DATA_SIZE);
+#endif
if (!same_status(&current_status, &new_status)) {
changed = true;
current_status = new_status;
diff --git a/quantum/visualizer/visualizer.h b/quantum/visualizer/visualizer.h
index 315af5022..d6f279e10 100644
--- a/quantum/visualizer/visualizer.h
+++ b/quantum/visualizer/visualizer.h
@@ -34,7 +34,7 @@ SOFTWARE.
#include "lcd_backlight.h"
#endif
-// use this function to merget both real_mods and oneshot_mods in a uint16_t
+// use this function to merge both real_mods and oneshot_mods in a uint16_t
uint8_t visualizer_get_mods(void);
// This need to be called once at the start
@@ -68,6 +68,9 @@ typedef struct {
uint8_t mods;
uint32_t leds; // See led.h for available statuses
bool suspended;
+#ifdef VISUALIZER_USER_DATA_SIZE
+ uint8_t user_data[VISUALIZER_USER_DATA_SIZE];
+#endif
} visualizer_keyboard_status_t;
// The state struct is used by the various keyframe functions
@@ -123,32 +126,22 @@ void stop_keyframe_animation(keyframe_animation_t* animation);
// 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
-bool keyframe_no_operation(keyframe_animation_t* animation, visualizer_state_t* state);
-// Animates the LCD backlight color between the current color and the target color (of the state)
-bool keyframe_animate_backlight_color(keyframe_animation_t* animation, visualizer_state_t* state);
-// Sets the backlight color to the target color
-bool keyframe_set_backlight_color(keyframe_animation_t* animation, visualizer_state_t* state);
-// Displays the layer text centered vertically on the screen
-bool keyframe_display_layer_text(keyframe_animation_t* animation, visualizer_state_t* state);
-// Displays a bitmap (0/1) of all the currently active layers
-bool keyframe_display_layer_bitmap(keyframe_animation_t* animation, visualizer_state_t* state);
-// Displays a bitmap (0/1) of all the currently active mods
-bool keyframe_display_mods_bitmap(keyframe_animation_t* animation, visualizer_state_t* state);
-
-bool keyframe_disable_lcd_and_backlight(keyframe_animation_t* animation, visualizer_state_t* state);
-bool keyframe_enable_lcd_and_backlight(keyframe_animation_t* animation, visualizer_state_t* state);
-
-// Call this once, when the initial animation has finished, alternatively you can call it
-// directly from the initalize_user_visualizer function (the animation can be null)
-bool enable_visualization(keyframe_animation_t* animation, visualizer_state_t* state);
+// The master can set userdata which will be transferred to the slave
+#ifdef VISUALIZER_USER_DATA_SIZE
+void visualizer_set_user_data(void* user_data);
+#endif
// 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);
+// Called regularly each time the state has changed (but not every scan loop)
+void update_user_visualizer_state(visualizer_state_t* state, visualizer_keyboard_status_t* prev_status);
+// Called when the computer goes to suspend, will also stop calling update_user_visualizer_state
void user_visualizer_suspend(visualizer_state_t* state);
+// You have to start at least one animation as a response to the following two functions
+// When the animation has finished the visualizer will resume normal operation and start calling the
+// update_user_visualizer_state again
+// Called when the keyboard boots up
+void initialize_user_visualizer(visualizer_state_t* state);
+// Called when the computer resumes from a suspend
void user_visualizer_resume(visualizer_state_t* state);
-
#endif /* VISUALIZER_H */
diff --git a/quantum/visualizer/visualizer.mk b/quantum/visualizer/visualizer.mk
index 2f4a41d66..5f710124b 100644
--- a/quantum/visualizer/visualizer.mk
+++ b/quantum/visualizer/visualizer.mk
@@ -20,7 +20,8 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
-SRC += $(VISUALIZER_DIR)/visualizer.c
+SRC += $(VISUALIZER_DIR)/visualizer.c \
+ $(VISUALIZER_DIR)/visualizer_keyframes.c
EXTRAINCDIRS += $(GFXINC) $(VISUALIZER_DIR)
GFXLIB = $(LIB_PATH)/ugfx
VPATH += $(VISUALIZER_PATH)
@@ -32,25 +33,33 @@ OPT_DEFS += -DLCD_ENABLE
ULIBS += -lm
endif
-ifdef LCD_BACKLIGHT_ENABLE
+ifeq ($(strip $(LCD_ENABLE)), yes)
SRC += $(VISUALIZER_DIR)/lcd_backlight.c
+SRC += $(VISUALIZER_DIR)/lcd_keyframes.c
+SRC += $(VISUALIZER_DIR)/lcd_backlight_keyframes.c
+# Note, that the linker will strip out any resources that are not actually in use
+SRC += $(VISUALIZER_DIR)/resources/lcd_logo.c
OPT_DEFS += -DLCD_BACKLIGHT_ENABLE
endif
-ifdef LED_ENABLE
-SRC += $(VISUALIZER_DIR)/led_test.c
+ifeq ($(strip $(LED_ENABLE)), yes)
+SRC += $(VISUALIZER_DIR)/led_keyframes.c
OPT_DEFS += -DLED_ENABLE
endif
include $(GFXLIB)/gfx.mk
-SRC += $(patsubst $(TOP_DIR)/%,%,$(GFXSRC))
-OPT_DEFS += $(patsubst %,-D%,$(patsubst -D%,%,$(GFXDEFS)))
+GFXSRC := $(patsubst $(TOP_DIR)/%,%,$(GFXSRC))
+GFXDEFS := $(patsubst %,-D%,$(patsubst -D%,%,$(GFXDEFS)))
ifneq ("$(wildcard $(KEYMAP_PATH)/visualizer.c)","")
SRC += keyboards/$(KEYBOARD)/keymaps/$(KEYMAP)/visualizer.c
else
ifeq ("$(wildcard $(SUBPROJECT_PATH)/keymaps/$(KEYMAP)/visualizer.c)","")
+ ifeq ("$(wildcard $(SUBPROJECT_PATH)/visualizer.c)","")
$(error "$(KEYMAP_PATH)/visualizer.c" does not exist)
+ else
+ SRC += keyboards/$(KEYBOARD)/$(SUBPROJECT)/visualizer.c
+ endif
else
SRC += keyboards/$(KEYBOARD)/$(SUBPROJECT)/keymaps/$(KEYMAP)/visualizer.c
endif
diff --git a/quantum/visualizer/visualizer_keyframes.c b/quantum/visualizer/visualizer_keyframes.c
new file mode 100644
index 000000000..8f6a7e15a
--- /dev/null
+++ b/quantum/visualizer/visualizer_keyframes.c
@@ -0,0 +1,23 @@
+/* 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 "visualizer_keyframes.h"
+
+bool keyframe_no_operation(keyframe_animation_t* animation, visualizer_state_t* state) {
+ (void)animation;
+ (void)state;
+ return false;
+}
diff --git a/quantum/visualizer/visualizer_keyframes.h b/quantum/visualizer/visualizer_keyframes.h
new file mode 100644
index 000000000..9ef7653c5
--- /dev/null
+++ b/quantum/visualizer/visualizer_keyframes.h
@@ -0,0 +1,26 @@
+/* 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_VISUALIZER_KEYFRAMES_H_
+#define QUANTUM_VISUALIZER_VISUALIZER_KEYFRAMES_H_
+
+#include "visualizer.h"
+
+// Some predefined keyframe functions that can be used by the user code
+// Does nothing, useful for adding delays
+bool keyframe_no_operation(keyframe_animation_t* animation, visualizer_state_t* state);
+
+#endif /* QUANTUM_VISUALIZER_VISUALIZER_KEYFRAMES_H_ */