summaryrefslogtreecommitdiff
path: root/quantum
diff options
context:
space:
mode:
Diffstat (limited to 'quantum')
-rw-r--r--quantum/backlight/backlight.c21
-rw-r--r--quantum/backlight/backlight.h23
-rw-r--r--quantum/backlight/backlight_arm.c29
-rw-r--r--quantum/backlight/backlight_avr.c35
-rw-r--r--quantum/backlight/backlight_soft.c37
-rw-r--r--quantum/color.c14
-rw-r--r--quantum/color.h4
-rw-r--r--quantum/dynamic_keymap.c55
-rw-r--r--quantum/encoder.c26
-rw-r--r--quantum/keymap_common.c14
-rw-r--r--quantum/matrix.c88
-rw-r--r--quantum/matrix_common.c107
-rw-r--r--quantum/mcu_selection.mk123
-rw-r--r--quantum/process_keycode/process_magic.c178
-rw-r--r--quantum/process_keycode/process_magic.h20
-rw-r--r--quantum/process_keycode/process_rgb.c141
-rw-r--r--quantum/process_keycode/process_rgb.h20
-rw-r--r--quantum/process_keycode/process_steno.c4
-rw-r--r--quantum/process_keycode/process_steno.h4
-rw-r--r--quantum/process_keycode/process_terminal.c2
-rw-r--r--quantum/quantum.c470
-rw-r--r--quantum/quantum.h65
-rw-r--r--quantum/quantum_keycodes.h35
-rw-r--r--quantum/rgb_matrix.c28
-rw-r--r--quantum/rgb_matrix.h40
-rw-r--r--quantum/rgb_matrix_animations/gradient_left_right_anim.h22
-rw-r--r--quantum/rgb_matrix_animations/rgb_matrix_effects.inc1
-rw-r--r--quantum/rgb_matrix_drivers.c2
-rw-r--r--quantum/rgblight.c9
-rw-r--r--quantum/send_string_keycodes.h575
-rw-r--r--quantum/split_common/matrix.c124
-rw-r--r--quantum/split_common/matrix.h3
-rw-r--r--quantum/split_common/post_config.h2
-rw-r--r--quantum/split_common/split_util.c6
-rw-r--r--quantum/split_common/transport.c2
-rw-r--r--quantum/stm32/proton_c.mk4
-rw-r--r--quantum/template/base/keymaps/default/keymap.c2
-rw-r--r--quantum/via.c400
-rw-r--r--quantum/via.h151
39 files changed, 1886 insertions, 1000 deletions
diff --git a/quantum/backlight/backlight.c b/quantum/backlight/backlight.c
index 708022f68f..e57b31d103 100644
--- a/quantum/backlight/backlight.c
+++ b/quantum/backlight/backlight.c
@@ -21,6 +21,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
backlight_config_t backlight_config;
+// TODO: migrate to backlight_config_t
+static uint8_t breathing_period = BREATHING_PERIOD;
+
/** \brief Backlight initialization
*
* FIXME: needs doc
@@ -191,3 +194,21 @@ void backlight_disable_breathing(void) {
*/
bool is_backlight_breathing(void) { return backlight_config.breathing; }
#endif
+
+// following are marked as weak purely for backwards compatibility
+__attribute__((weak)) void breathing_period_set(uint8_t value) { breathing_period = value ? value : 1; }
+
+__attribute__((weak)) uint8_t get_breathing_period(void) { return breathing_period; }
+
+__attribute__((weak)) void breathing_period_default(void) { breathing_period_set(BREATHING_PERIOD); }
+
+__attribute__((weak)) void breathing_period_inc(void) { breathing_period_set(breathing_period + 1); }
+
+__attribute__((weak)) void breathing_period_dec(void) { breathing_period_set(breathing_period - 1); }
+
+// defaults for backlight api
+__attribute__((weak)) void backlight_init_ports(void) {}
+
+__attribute__((weak)) void backlight_set(uint8_t level) {}
+
+__attribute__((weak)) void backlight_task(void) {}
diff --git a/quantum/backlight/backlight.h b/quantum/backlight/backlight.h
index 1e581055db..9f0a5e81d7 100644
--- a/quantum/backlight/backlight.h
+++ b/quantum/backlight/backlight.h
@@ -41,22 +41,39 @@ typedef union {
} backlight_config_t;
void backlight_init(void);
-void backlight_increase(void);
-void backlight_decrease(void);
void backlight_toggle(void);
void backlight_enable(void);
void backlight_disable(void);
bool is_backlight_enabled(void);
void backlight_step(void);
-void backlight_set(uint8_t level);
+void backlight_increase(void);
+void backlight_decrease(void);
void backlight_level(uint8_t level);
uint8_t get_backlight_level(void);
+// implementation specific
+void backlight_init_ports(void);
+void backlight_set(uint8_t level);
+void backlight_task(void);
+
#ifdef BACKLIGHT_BREATHING
+
void backlight_toggle_breathing(void);
void backlight_enable_breathing(void);
void backlight_disable_breathing(void);
bool is_backlight_breathing(void);
+
+void breathing_period_set(uint8_t value);
+uint8_t get_breathing_period(void);
+void breathing_period_default(void);
+void breathing_period_inc(void);
+void breathing_period_dec(void);
+
+// implementation specific
void breathing_enable(void);
void breathing_disable(void);
+void breathing_toggle(void);
+bool is_breathing(void);
+void breathing_pulse(void);
+void breathing_task(void);
#endif
diff --git a/quantum/backlight/backlight_arm.c b/quantum/backlight/backlight_arm.c
index 3f94ccef8e..f7065906f8 100644
--- a/quantum/backlight/backlight_arm.c
+++ b/quantum/backlight/backlight_arm.c
@@ -10,10 +10,6 @@
# error "Backlight support for STMF072 is not available. Please disable."
# endif
-# if defined(STM32F1XX) || defined(STM32F1xx)
-# define USE_GPIOV1
-# endif
-
// GPIOV2 && GPIOV3
# ifndef BACKLIGHT_PAL_MODE
# define BACKLIGHT_PAL_MODE 2
@@ -110,7 +106,6 @@ void backlight_task(void) {}
# define BREATHING_HALT_ON 2
# define BREATHING_STEPS 128
-static uint8_t breathing_period = BREATHING_PERIOD;
static uint8_t breathing_halt = BREATHING_NO_HALT;
static uint16_t breathing_counter = 0;
@@ -118,7 +113,7 @@ bool is_breathing(void) { return BACKLIGHT_PWM_DRIVER.config == &pwmCFG_breathin
static inline void breathing_min(void) { breathing_counter = 0; }
-static inline void breathing_max(void) { breathing_counter = breathing_period * 256 / 2; }
+static inline void breathing_max(void) { breathing_counter = get_breathing_period() * 256 / 2; }
void breathing_interrupt_enable(void) {
pwmStop(&BACKLIGHT_PWM_DRIVER);
@@ -170,17 +165,6 @@ void breathing_toggle(void) {
breathing_enable();
}
-void breathing_period_set(uint8_t value) {
- if (!value) value = 1;
- breathing_period = value;
-}
-
-void breathing_period_default(void) { breathing_period_set(BREATHING_PERIOD); }
-
-void breathing_period_inc(void) { breathing_period_set(breathing_period + 1); }
-
-void breathing_period_dec(void) { breathing_period_set(breathing_period - 1); }
-
/* To generate breathing curve in python:
* from math import sin, pi; [int(sin(x/128.0*pi)**4*255) for x in range(128)]
*/
@@ -191,7 +175,8 @@ static inline uint16_t scale_backlight(uint16_t v) { return v / BACKLIGHT_LEVELS
static void breathing_callback(PWMDriver *pwmp) {
(void)pwmp;
- uint16_t interval = (uint16_t)breathing_period * 256 / BREATHING_STEPS;
+ uint8_t breathing_period = get_breathing_period();
+ uint16_t interval = (uint16_t)breathing_period * 256 / BREATHING_STEPS;
// resetting after one period to prevent ugly reset at overflow.
breathing_counter = (breathing_counter + 1) % (breathing_period * 256);
uint8_t index = breathing_counter / interval % BREATHING_STEPS;
@@ -207,12 +192,4 @@ static void breathing_callback(PWMDriver *pwmp) {
chSysUnlockFromISR();
}
-#else
-
-__attribute__((weak)) void backlight_init_ports(void) {}
-
-__attribute__((weak)) void backlight_set(uint8_t level) {}
-
-__attribute__((weak)) void backlight_task(void) {}
-
#endif
diff --git a/quantum/backlight/backlight_avr.c b/quantum/backlight/backlight_avr.c
index edda6ea0b6..7cf1e0fb30 100644
--- a/quantum/backlight/backlight_avr.c
+++ b/quantum/backlight/backlight_avr.c
@@ -206,7 +206,7 @@ static const pin_t backlight_pin = BACKLIGHT_PIN;
# endif
# ifdef NO_HARDWARE_PWM
-__attribute__((weak)) void backlight_init_ports(void) {
+void backlight_init_ports(void) {
// Setup backlight pin as output and output to on state.
FOR_EACH_LED(setPinOutput(backlight_pin); backlight_on(backlight_pin);)
@@ -217,8 +217,6 @@ __attribute__((weak)) void backlight_init_ports(void) {
# endif
}
-__attribute__((weak)) void backlight_set(uint8_t level) {}
-
uint8_t backlight_tick = 0;
# ifndef BACKLIGHT_CUSTOM_DRIVER
@@ -303,7 +301,7 @@ static uint16_t cie_lightness(uint16_t v) {
static inline void set_pwm(uint16_t val) { OCRxx = val; }
# ifndef BACKLIGHT_CUSTOM_DRIVER
-__attribute__((weak)) void backlight_set(uint8_t level) {
+void backlight_set(uint8_t level) {
if (level > BACKLIGHT_LEVELS) level = BACKLIGHT_LEVELS;
if (level == 0) {
@@ -342,7 +340,6 @@ void backlight_task(void) {}
# define BREATHING_HALT_ON 2
# define BREATHING_STEPS 128
-static uint8_t breathing_period = BREATHING_PERIOD;
static uint8_t breathing_halt = BREATHING_NO_HALT;
static uint16_t breathing_counter = 0;
@@ -377,9 +374,9 @@ bool is_breathing(void) { return !!(TIMSKx & _BV(TOIEx)); }
do { \
breathing_counter = 0; \
} while (0)
-# define breathing_max() \
- do { \
- breathing_counter = breathing_period * 244 / 2; \
+# define breathing_max() \
+ do { \
+ breathing_counter = get_breathing_period() * 244 / 2; \
} while (0)
void breathing_enable(void) {
@@ -417,17 +414,6 @@ void breathing_toggle(void) {
breathing_enable();
}
-void breathing_period_set(uint8_t value) {
- if (!value) value = 1;
- breathing_period = value;
-}
-
-void breathing_period_default(void) { breathing_period_set(BREATHING_PERIOD); }
-
-void breathing_period_inc(void) { breathing_period_set(breathing_period + 1); }
-
-void breathing_period_dec(void) { breathing_period_set(breathing_period - 1); }
-
/* To generate breathing curve in python:
* from math import sin, pi; [int(sin(x/128.0*pi)**4*255) for x in range(128)]
*/
@@ -445,6 +431,7 @@ void breathing_task(void)
ISR(TIMERx_OVF_vect)
# endif
{
+ uint8_t breathing_period = get_breathing_period();
uint16_t interval = (uint16_t)breathing_period * 244 / BREATHING_STEPS;
// resetting after one period to prevent ugly reset at overflow.
breathing_counter = (breathing_counter + 1) % (breathing_period * 244);
@@ -459,7 +446,7 @@ ISR(TIMERx_OVF_vect)
# endif // BACKLIGHT_BREATHING
-__attribute__((weak)) void backlight_init_ports(void) {
+void backlight_init_ports(void) {
// Setup backlight pin as output and output to on state.
FOR_EACH_LED(setPinOutput(backlight_pin); backlight_on(backlight_pin);)
@@ -500,10 +487,4 @@ __attribute__((weak)) void backlight_init_ports(void) {
# endif // hardware backlight
-#else // no backlight
-
-__attribute__((weak)) void backlight_init_ports(void) {}
-
-__attribute__((weak)) void backlight_set(uint8_t level) {}
-
-#endif // backlight \ No newline at end of file
+#endif // backlight
diff --git a/quantum/backlight/backlight_soft.c b/quantum/backlight/backlight_soft.c
index a6aba7782c..096b41d910 100644
--- a/quantum/backlight/backlight_soft.c
+++ b/quantum/backlight/backlight_soft.c
@@ -10,7 +10,7 @@
#endif
#ifndef BACKLIGHT_ON_STATE
-# define BACKLIGHT_ON_STATE 0
+# define BACKLIGHT_ON_STATE 1
#endif
#ifdef BACKLIGHT_PINS
@@ -20,6 +20,7 @@
{ BACKLIGHT_PIN }
#endif
+static uint16_t s_duty_pattern = 0;
static const pin_t backlight_pins[] = BACKLIGHT_PIN_INIT;
#define BACKLIGHT_LED_COUNT (sizeof(backlight_pins) / sizeof(pin_t))
@@ -46,14 +47,38 @@ void backlight_off(pin_t backlight_pin) {
}
void backlight_init_ports(void) {
- // Setup backlight pin as output and output to on state.
- FOR_EACH_LED(setPinOutput(backlight_pin); backlight_on(backlight_pin);)
+ // Setup backlight pin as output and output to off state.
+ FOR_EACH_LED(setPinOutput(backlight_pin); backlight_off(backlight_pin);)
}
+// clang-format off
+
+/** \brief PWM duty patterns
+ *
+ * We scale the current backlight level to an index within this array. This allows
+ * backlight_task to focus on just switching LEDs on/off, and we can predict the duty pattern
+ */
+static uint16_t backlight_duty_table[] = {
+ 0b0000000000000000,
+ 0b1000000000000000,
+ 0b1000000010000000,
+ 0b1000001000010000,
+ 0b1000100010001000,
+ 0b1001001001001000,
+ 0b1010101010101010,
+ 0b1110111011101110,
+ 0b1111111111111111,
+};
+#define backlight_duty_table_size (sizeof(backlight_duty_table) / sizeof(backlight_duty_table[0]))
+
+// clang-format on
+
+static uint8_t scale_backlight(uint8_t v) { return v * (backlight_duty_table_size - 1) / BACKLIGHT_LEVELS; }
+
void backlight_task(void) {
static uint8_t backlight_tick = 0;
- if ((0xFFFF >> (get_backlight_level() * ((BACKLIGHT_LEVELS + 1) / 2))) & (1 << backlight_tick)) {
+ if (s_duty_pattern & ((uint16_t)1 << backlight_tick)) {
FOR_EACH_LED(backlight_on(backlight_pin);)
} else {
FOR_EACH_LED(backlight_off(backlight_pin);)
@@ -61,6 +86,4 @@ void backlight_task(void) {
backlight_tick = (backlight_tick + 1) % 16;
}
-void backlight_set(uint8_t level) {
- // noop as backlight_task uses get_backlight_level()
-}
+void backlight_set(uint8_t level) { s_duty_pattern = backlight_duty_table[scale_backlight(level)]; }
diff --git a/quantum/color.c b/quantum/color.c
index 1f398e2403..8bd52444fa 100644
--- a/quantum/color.c
+++ b/quantum/color.c
@@ -85,3 +85,17 @@ RGB hsv_to_rgb(HSV hsv) {
return rgb;
}
+
+#ifdef RGBW
+#ifndef MIN
+# define MIN(a, b) ((a) < (b) ? (a) : (b))
+#endif
+void convert_rgb_to_rgbw(LED_TYPE *led) {
+ // Determine lowest value in all three colors, put that into
+ // the white channel and then shift all colors by that amount
+ led->w = MIN(led->r, MIN(led->g, led->b));
+ led->r -= led->w;
+ led->g -= led->w;
+ led->b -= led->w;
+}
+#endif
diff --git a/quantum/color.h b/quantum/color.h
index 6781646628..58d4f0407f 100644
--- a/quantum/color.h
+++ b/quantum/color.h
@@ -64,5 +64,7 @@ typedef struct PACKED {
#endif
RGB hsv_to_rgb(HSV hsv);
-
+#ifdef RGBW
+void convert_rgb_to_rgbw(LED_TYPE *led);
+#endif
#endif // COLOR_H
diff --git a/quantum/dynamic_keymap.c b/quantum/dynamic_keymap.c
index ca056f630e..11d28592d6 100644
--- a/quantum/dynamic_keymap.c
+++ b/quantum/dynamic_keymap.c
@@ -20,28 +20,37 @@
#include "progmem.h" // to read default from flash
#include "quantum.h" // for send_string()
#include "dynamic_keymap.h"
-
-#ifdef DYNAMIC_KEYMAP_ENABLE
-
-# ifndef DYNAMIC_KEYMAP_EEPROM_ADDR
-# error DYNAMIC_KEYMAP_EEPROM_ADDR not defined
-# endif
-
-# ifndef DYNAMIC_KEYMAP_LAYER_COUNT
-# error DYNAMIC_KEYMAP_LAYER_COUNT not defined
-# endif
-
-# ifndef DYNAMIC_KEYMAP_MACRO_COUNT
-# error DYNAMIC_KEYMAP_MACRO_COUNT not defined
-# endif
-
-# ifndef DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR
-# error DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR not defined
-# endif
-
-# ifndef DYNAMIC_KEYMAP_MACRO_EEPROM_SIZE
-# error DYNAMIC_KEYMAP_MACRO_EEPROM_SIZE not defined
-# endif
+#include "via.h" // for default VIA_EEPROM_ADDR_END
+
+#ifndef DYNAMIC_KEYMAP_LAYER_COUNT
+# define DYNAMIC_KEYMAP_LAYER_COUNT 4
+#endif
+
+#ifndef DYNAMIC_KEYMAP_MACRO_COUNT
+# define DYNAMIC_KEYMAP_MACRO_COUNT 16
+#endif
+
+// If DYNAMIC_KEYMAP_EEPROM_ADDR not explicitly defined in config.h,
+// default it start after VIA_EEPROM_CUSTOM_ADDR+VIA_EEPROM_CUSTOM_SIZE
+#ifndef DYNAMIC_KEYMAP_EEPROM_ADDR
+# ifdef VIA_EEPROM_CUSTOM_CONFIG_ADDR
+# define DYNAMIC_KEYMAP_EEPROM_ADDR (VIA_EEPROM_CUSTOM_CONFIG_ADDR+VIA_EEPROM_CUSTOM_CONFIG_SIZE)
+# else
+# error DYNAMIC_KEYMAP_EEPROM_ADDR not defined
+# endif
+#endif
+
+// Dynamic macro starts after dynamic keymaps
+#ifndef DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR
+# define DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR (DYNAMIC_KEYMAP_EEPROM_ADDR+(DYNAMIC_KEYMAP_LAYER_COUNT*MATRIX_ROWS*MATRIX_COLS*2))
+#endif
+
+// Dynamic macro uses up all remaining memory
+// Assumes 1K EEPROM on ATMega32U4
+// Override for anything different
+#ifndef DYNAMIC_KEYMAP_MACRO_EEPROM_SIZE
+# define DYNAMIC_KEYMAP_MACRO_EEPROM_SIZE (1024-DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR)
+#endif
uint8_t dynamic_keymap_get_layer_count(void) { return DYNAMIC_KEYMAP_LAYER_COUNT; }
@@ -208,5 +217,3 @@ void dynamic_keymap_macro_send(uint8_t id) {
send_string(data);
}
}
-
-#endif // DYNAMIC_KEYMAP_ENABLE
diff --git a/quantum/encoder.c b/quantum/encoder.c
index 4aeb3d0cde..c41b89f495 100644
--- a/quantum/encoder.c
+++ b/quantum/encoder.c
@@ -37,8 +37,8 @@ static pin_t encoders_pad_b[] = ENCODERS_PAD_B;
static int8_t encoder_LUT[] = {0, -1, 1, 0, 1, 0, 0, -1, -1, 0, 0, 1, 0, 1, -1, 0};
-static uint8_t encoder_state[NUMBER_OF_ENCODERS] = {0};
-static int8_t encoder_pulses[NUMBER_OF_ENCODERS] = {0};
+static uint8_t encoder_state[NUMBER_OF_ENCODERS] = {0};
+static int8_t encoder_pulses[NUMBER_OF_ENCODERS] = {0};
#ifdef SPLIT_KEYBOARD
// right half encoders come over as second set of encoders
@@ -79,27 +79,27 @@ void encoder_init(void) {
}
static void encoder_update(int8_t index, uint8_t state) {
- encoder_pulses[index] += encoder_LUT[state & 0xF];
- if (encoder_pulses[index] >= ENCODER_RESOLUTION) {
+ uint8_t i = index;
+#ifdef SPLIT_KEYBOARD
+ index += thisHand;
+#endif
+ encoder_pulses[i] += encoder_LUT[state & 0xF];
+ if (encoder_pulses[i] >= ENCODER_RESOLUTION) {
encoder_value[index]++;
encoder_update_kb(index, true);
}
- if (encoder_pulses[index] <= -ENCODER_RESOLUTION) { // direction is arbitrary here, but this clockwise
+ if (encoder_pulses[i] <= -ENCODER_RESOLUTION) { // direction is arbitrary here, but this clockwise
encoder_value[index]--;
encoder_update_kb(index, false);
}
- encoder_pulses[index] %= ENCODER_RESOLUTION;
+ encoder_pulses[i] %= ENCODER_RESOLUTION;
}
void encoder_read(void) {
- for (int i = 0; i < NUMBER_OF_ENCODERS; i++) {
+ for (uint8_t i = 0; i < NUMBER_OF_ENCODERS; i++) {
encoder_state[i] <<= 2;
encoder_state[i] |= (readPin(encoders_pad_a[i]) << 0) | (readPin(encoders_pad_b[i]) << 1);
-#if SPLIT_KEYBOARD
- encoder_update(i + thisHand, encoder_state[i]);
-#else
encoder_update(i, encoder_state[i]);
-#endif
}
}
@@ -107,9 +107,9 @@ void encoder_read(void) {
void encoder_state_raw(uint8_t* slave_state) { memcpy(slave_state, &encoder_value[thisHand], sizeof(uint8_t) * NUMBER_OF_ENCODERS); }
void encoder_update_raw(uint8_t* slave_state) {
- for (int i = 0; i < NUMBER_OF_ENCODERS; i++) {
+ for (uint8_t i = 0; i < NUMBER_OF_ENCODERS; i++) {
uint8_t index = i + thatHand;
- int8_t delta = slave_state[i] - encoder_value[index];
+ int8_t delta = slave_state[i] - encoder_value[index];
while (delta > 0) {
delta--;
encoder_value[index]++;
diff --git a/quantum/keymap_common.c b/quantum/keymap_common.c
index 4fa45ac37b..c82c446399 100644
--- a/quantum/keymap_common.c
+++ b/quantum/keymap_common.c
@@ -48,13 +48,10 @@ action_t action_for_key(uint8_t layer, keypos_t key) {
// keycode remapping
keycode = keycode_config(keycode);
- action_t action;
+ action_t action = {};
uint8_t action_layer, when, mod;
switch (keycode) {
- case KC_FN0 ... KC_FN31:
- action.code = keymap_function_id_to_action(FN_INDEX(keycode));
- break;
case KC_A ... KC_EXSEL:
case KC_LCTRL ... KC_RGUI:
action.code = ACTION_KEY(keycode);
@@ -65,9 +62,11 @@ action_t action_for_key(uint8_t layer, keypos_t key) {
case KC_AUDIO_MUTE ... KC_BRIGHTNESS_DOWN:
action.code = ACTION_USAGE_CONSUMER(KEYCODE2CONSUMER(keycode));
break;
+#ifdef MOUSEKEY_ENABLE
case KC_MS_UP ... KC_MS_ACCEL2:
action.code = ACTION_MOUSEKEY(keycode);
break;
+#endif
case KC_TRNS:
action.code = ACTION_TRANSPARENT;
break;
@@ -76,17 +75,24 @@ action_t action_for_key(uint8_t layer, keypos_t key) {
// Split it up
action.code = ACTION_MODS_KEY(keycode >> 8, keycode & 0xFF); // adds modifier to key
break;
+#ifndef NO_ACTION_FUNCTION
+ case KC_FN0 ... KC_FN31:
+ action.code = keymap_function_id_to_action(FN_INDEX(keycode));
+ break;
case QK_FUNCTION ... QK_FUNCTION_MAX:;
// Is a shortcut for function action_layer, pull last 12bits
// This means we have 4,096 FN macros at our disposal
action.code = keymap_function_id_to_action((int)keycode & 0xFFF);
break;
+#endif
+#ifndef NO_ACTION_MACRO
case QK_MACRO ... QK_MACRO_MAX:
if (keycode & 0x800) // tap macros have upper bit set
action.code = ACTION_MACRO_TAP(keycode & 0xFF);
else
action.code = ACTION_MACRO(keycode & 0xFF);
break;
+#endif
case QK_LAYER_TAP ... QK_LAYER_TAP_MAX:
action.code = ACTION_LAYER_TAP_KEY((keycode >> 0x8) & 0xF, keycode & 0xFF);
break;
diff --git a/quantum/matrix.c b/quantum/matrix.c
index 907492a0f6..1675f2477b 100644
--- a/quantum/matrix.c
+++ b/quantum/matrix.c
@@ -17,34 +17,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <stdint.h>
#include <stdbool.h>
#include "wait.h"
-#include "print.h"
-#include "debug.h"
#include "util.h"
#include "matrix.h"
#include "debounce.h"
#include "quantum.h"
-#if (MATRIX_COLS <= 8)
-# define print_matrix_header() print("\nr/c 01234567\n")
-# define print_matrix_row(row) print_bin_reverse8(matrix_get_row(row))
-# define matrix_bitpop(i) bitpop(matrix[i])
-# define ROW_SHIFTER ((uint8_t)1)
-#elif (MATRIX_COLS <= 16)
-# define print_matrix_header() print("\nr/c 0123456789ABCDEF\n")
-# define print_matrix_row(row) print_bin_reverse16(matrix_get_row(row))
-# define matrix_bitpop(i) bitpop16(matrix[i])
-# define ROW_SHIFTER ((uint16_t)1)
-#elif (MATRIX_COLS <= 32)
-# define print_matrix_header() print("\nr/c 0123456789ABCDEF0123456789ABCDEF\n")
-# define print_matrix_row(row) print_bin_reverse32(matrix_get_row(row))
-# define matrix_bitpop(i) bitpop32(matrix[i])
-# define ROW_SHIFTER ((uint32_t)1)
-#endif
-
-#ifdef MATRIX_MASKED
-extern const matrix_row_t matrix_mask[];
-#endif
-
#ifdef DIRECT_PINS
static pin_t direct_pins[MATRIX_ROWS][MATRIX_COLS] = DIRECT_PINS;
#elif (DIODE_DIRECTION == ROW2COL) || (DIODE_DIRECTION == COL2ROW)
@@ -53,61 +30,10 @@ static const pin_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS;
#endif
/* matrix state(1:on, 0:off) */
-static matrix_row_t raw_matrix[MATRIX_ROWS]; // raw values
-static matrix_row_t matrix[MATRIX_ROWS]; // debounced values
-
-__attribute__((weak)) void matrix_init_quantum(void) { matrix_init_kb(); }
-
-__attribute__((weak)) void matrix_scan_quantum(void) { matrix_scan_kb(); }
-
-__attribute__((weak)) void matrix_init_kb(void) { matrix_init_user(); }
+extern matrix_row_t raw_matrix[MATRIX_ROWS]; // raw values
+extern matrix_row_t matrix[MATRIX_ROWS]; // debounced values
-__attribute__((weak)) void matrix_scan_kb(void) { matrix_scan_user(); }
-
-__attribute__((weak)) void matrix_init_user(void) {}
-
-__attribute__((weak)) void matrix_scan_user(void) {}
-
-inline uint8_t matrix_rows(void) { return MATRIX_ROWS; }
-
-inline uint8_t matrix_cols(void) { return MATRIX_COLS; }
-
-// Deprecated.
-bool matrix_is_modified(void) {
- if (debounce_active()) return false;
- return true;
-}
-
-inline bool matrix_is_on(uint8_t row, uint8_t col) { return (matrix[row] & ((matrix_row_t)1 << col)); }
-
-inline matrix_row_t matrix_get_row(uint8_t row) {
- // Matrix mask lets you disable switches in the returned matrix data. For example, if you have a
- // switch blocker installed and the switch is always pressed.
-#ifdef MATRIX_MASKED
- return matrix[row] & matrix_mask[row];
-#else
- return matrix[row];
-#endif
-}
-
-void matrix_print(void) {
- print_matrix_header();
-
- for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
- phex(row);
- print(": ");
- print_matrix_row(row);
- print("\n");
- }
-}
-
-uint8_t matrix_key_count(void) {
- uint8_t count = 0;
- for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
- count += matrix_bitpop(i);
- }
- return count;
-}
+// matrix code
#ifdef DIRECT_PINS
@@ -129,7 +55,7 @@ static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row)
for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) {
pin_t pin = direct_pins[current_row][col_index];
if (pin != NO_PIN) {
- current_matrix[current_row] |= readPin(pin) ? 0 : (ROW_SHIFTER << col_index);
+ current_matrix[current_row] |= readPin(pin) ? 0 : (MATRIX_ROW_SHIFTER << col_index);
}
}
@@ -175,7 +101,7 @@ static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row)
uint8_t pin_state = readPin(col_pins[col_index]);
// Populate the matrix row with the state of the col pin
- current_matrix[current_row] |= pin_state ? 0 : (ROW_SHIFTER << col_index);
+ current_matrix[current_row] |= pin_state ? 0 : (MATRIX_ROW_SHIFTER << col_index);
}
// Unselect row
@@ -221,10 +147,10 @@ static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col)
// Check row pin state
if (readPin(row_pins[row_index]) == 0) {
// Pin LO, set col bit
- current_matrix[row_index] |= (ROW_SHIFTER << current_col);
+ current_matrix[row_index] |= (MATRIX_ROW_SHIFTER << current_col);
} else {
// Pin HI, clear col bit
- current_matrix[row_index] &= ~(ROW_SHIFTER << current_col);
+ current_matrix[row_index] &= ~(MATRIX_ROW_SHIFTER << current_col);
}
// Determine if the matrix changed state
diff --git a/quantum/matrix_common.c b/quantum/matrix_common.c
new file mode 100644
index 0000000000..c326e59ca3
--- /dev/null
+++ b/quantum/matrix_common.c
@@ -0,0 +1,107 @@
+#include "matrix.h"
+#include "debounce.h"
+#include "print.h"
+#include "debug.h"
+
+/* matrix state(1:on, 0:off) */
+matrix_row_t raw_matrix[MATRIX_ROWS];
+matrix_row_t matrix[MATRIX_ROWS];
+
+#ifdef MATRIX_MASKED
+extern const matrix_row_t matrix_mask[];
+#endif
+
+// user-defined overridable functions
+
+__attribute__((weak)) void matrix_init_kb(void) { matrix_init_user(); }
+
+__attribute__((weak)) void matrix_scan_kb(void) { matrix_scan_user(); }
+
+__attribute__((weak)) void matrix_init_user(void) {}
+
+__attribute__((weak)) void matrix_scan_user(void) {}
+
+// helper functions
+
+inline uint8_t matrix_rows(void) { return MATRIX_ROWS; }
+
+inline uint8_t matrix_cols(void) { return MATRIX_COLS; }
+
+inline bool matrix_is_on(uint8_t row, uint8_t col) { return (matrix[row] & ((matrix_row_t)1 << col)); }
+
+inline matrix_row_t matrix_get_row(uint8_t row) {
+ // Matrix mask lets you disable switches in the returned matrix data. For example, if you have a
+ // switch blocker installed and the switch is always pressed.
+#ifdef MATRIX_MASKED
+ return matrix[row] & matrix_mask[row];
+#else
+ return matrix[row];
+#endif
+}
+
+// Deprecated.
+bool matrix_is_modified(void) {
+ if (debounce_active()) return false;
+ return true;
+}
+
+#if (MATRIX_COLS <= 8)
+# define print_matrix_header() print("\nr/c 01234567\n")
+# define print_matrix_row(row) print_bin_reverse8(matrix_get_row(row))
+# define matrix_bitpop(row) bitpop(matrix_get_row(row))
+#elif (MATRIX_COLS <= 16)
+# define print_matrix_header() print("\nr/c 0123456789ABCDEF\n")
+# define print_matrix_row(row) print_bin_reverse16(matrix_get_row(row))
+# define matrix_bitpop(row) bitpop16(matrix_get_row(row))
+#elif (MATRIX_COLS <= 32)
+# define print_matrix_header() print("\nr/c 0123456789ABCDEF0123456789ABCDEF\n")
+# define print_matrix_row(row) print_bin_reverse32(matrix_get_row(row))
+# define matrix_bitpop(row) bitpop32(matrix_get_row(row))
+#endif
+
+void matrix_print(void) {
+ print_matrix_header();
+
+ for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
+ phex(row);
+ print(": ");
+ print_matrix_row(row);
+ print("\n");
+ }
+}
+
+uint8_t matrix_key_count(void) {
+ uint8_t count = 0;
+ for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
+ count += matrix_bitpop(i);
+ }
+ return count;
+}
+
+// CUSTOM MATRIX 'LITE'
+__attribute__((weak)) void matrix_init_custom(void) {}
+
+__attribute__((weak)) bool matrix_scan_custom(matrix_row_t current_matrix[]) { return true; }
+
+__attribute__((weak)) void matrix_init(void) {
+ matrix_init_custom();
+
+ // initialize matrix state: all keys off
+ for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
+ raw_matrix[i] = 0;
+ matrix[i] = 0;
+ }
+
+ debounce_init(MATRIX_ROWS);
+
+ matrix_init_quantum();
+}
+
+__attribute__((weak)) uint8_t matrix_scan(void) {
+ bool changed = matrix_scan_custom(raw_matrix);
+
+ debounce(raw_matrix, matrix, MATRIX_ROWS, changed);
+
+ matrix_scan_quantum();
+ return changed;
+}
diff --git a/quantum/mcu_selection.mk b/quantum/mcu_selection.mk
index 6815a0d8a5..bddafa6a4c 100644
--- a/quantum/mcu_selection.mk
+++ b/quantum/mcu_selection.mk
@@ -1,9 +1,15 @@
ifneq ($(findstring STM32F303, $(MCU)),)
+ # Cortex version
+ MCU = cortex-m4
+
+ # ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7
+ ARMV = 7
+
## chip/board settings
# - the next two should match the directories in
# <chibios>/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)
- MCU_FAMILY ?= STM32
- MCU_SERIES ?= STM32F3xx
+ MCU_FAMILY = STM32
+ MCU_SERIES = STM32F3xx
# Linker script to use
# - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/
@@ -18,22 +24,110 @@ ifneq ($(findstring STM32F303, $(MCU)),)
# <keyboard_dir>/boards/, or drivers/boards/
BOARD ?= GENERIC_STM32_F303XC
+ USE_FPU ?= yes
+
+ # Options to pass to dfu-util when flashing
+ DFU_ARGS ?= -d 0483:df11 -a 0 -s 0x08000000:leave
+ DFU_SUFFIX_ARGS ?= -v 0483 -p df11
+endif
+
+ifneq ($(findstring STM32F072, $(MCU)),)
# Cortex version
- MCU = cortex-m4
+ MCU = cortex-m0
# ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7
- ARMV ?= 7
+ ARMV = 6
- USE_FPU = yes
+ ## chip/board settings
+ # - the next two should match the directories in
+ # <chibios>/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)
+ MCU_FAMILY = STM32
+ MCU_SERIES = STM32F0xx
- # Vector table for application
- # 0x00000000-0x00001000 area is occupied by bootloader.*/
- # The CORTEX_VTOR... is needed only for MCHCK/Infinity KB
- # OPT_DEFS = -DCORTEX_VTOR_INIT=0x08005000
+ # Linker script to use
+ # - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/
+ # or <keyboard_dir>/ld/
+ MCU_LDSCRIPT ?= STM32F072xB
+
+ # Startup code to use
+ # - it should exist in <chibios>/os/common/startup/ARMCMx/compilers/GCC/mk/
+ MCU_STARTUP ?= stm32f0xx
+
+ # Board: it should exist either in <chibios>/os/hal/boards/,
+ # <keyboard_dir>/boards/, or drivers/boards/
+ BOARD ?= ST_STM32F072B_DISCOVERY
+
+ USE_FPU ?= no
# Options to pass to dfu-util when flashing
DFU_ARGS ?= -d 0483:df11 -a 0 -s 0x08000000:leave
- DFU_SUFFIX_ARGS = -p DF11 -v 0483
+ DFU_SUFFIX_ARGS ?= -v 0483 -p df11
+endif
+
+ifneq ($(findstring STM32F042, $(MCU)),)
+ # Cortex version
+ MCU = cortex-m0
+
+ # ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7
+ ARMV = 6
+
+ ## chip/board settings
+ # - the next two should match the directories in
+ # <chibios>/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)
+ MCU_FAMILY = STM32
+ MCU_SERIES = STM32F0xx
+
+ # Linker script to use
+ # - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/
+ # or <keyboard_dir>/ld/
+ MCU_LDSCRIPT ?= STM32F042x6
+
+ # Startup code to use
+ # - it should exist in <chibios>/os/common/startup/ARMCMx/compilers/GCC/mk/
+ MCU_STARTUP ?= stm32f0xx
+
+ # Board: it should exist either in <chibios>/os/hal/boards/,
+ # <keyboard_dir>/boards/, or drivers/boards/
+ BOARD ?= GENERIC_STM32_F042X6
+
+ USE_FPU ?= no
+
+ # Options to pass to dfu-util when flashing
+ DFU_ARGS ?= -d 0483:df11 -a 0 -s 0x08000000:leave
+ DFU_SUFFIX_ARGS ?= -v 0483 -p df11
+endif
+
+ifneq ($(findstring STM32F103, $(MCU)),)
+ # Cortex version
+ MCU = cortex-m3
+
+ # ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7
+ ARMV = 7
+
+ ## chip/board settings
+ # - the next two should match the directories in
+ # <chibios>/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)
+ MCU_FAMILY = STM32
+ MCU_SERIES = STM32F1xx
+
+ # Linker script to use
+ # - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/
+ # or <keyboard_dir>/ld/
+ MCU_LDSCRIPT ?= STM32F103x8
+
+ # Startup code to use
+ # - it should exist in <chibios>/os/common/startup/ARMCMx/compilers/GCC/mk/
+ MCU_STARTUP ?= stm32f1xx
+
+ # Board: it should exist either in <chibios>/os/hal/boards/,
+ # <keyboard_dir>/boards/, or drivers/boards/
+ BOARD ?= GENERIC_STM32_F103
+
+ USE_FPU ?= no
+
+ # Options to pass to dfu-util when flashing
+ DFU_ARGS ?= -d 0483:df11 -a 0 -s 0x08000000:leave
+ DFU_SUFFIX_ARGS ?= -v 0483 -p df11
endif
ifneq (,$(filter $(MCU),atmega16u2 atmega32u2 atmega16u4 atmega32u4 at90usb646 at90usb1286))
@@ -75,6 +169,9 @@ ifneq (,$(filter $(MCU),atmega16u2 atmega32u2 atmega16u4 atmega32u4 at90usb646 a
endif
ifneq (,$(filter $(MCU),atmega32a))
+ # MCU name for avrdude
+ AVRDUDE_MCU = m32
+
PROTOCOL = VUSB
# Processor frequency.
@@ -87,12 +184,12 @@ ifneq (,$(filter $(MCU),atmega32a))
# unsupported features for now
NO_UART ?= yes
NO_SUSPEND_POWER_DOWN ?= yes
-
- # Programming options
- PROGRAM_CMD ?= ./util/atmega32a_program.py $(TARGET).hex
endif
ifneq (,$(filter $(MCU),atmega328p))
+ # MCU name for avrdude
+ AVRDUDE_MCU = m328p
+
PROTOCOL = VUSB
# Processor frequency.
diff --git a/quantum/process_keycode/process_magic.c b/quantum/process_keycode/process_magic.c
new file mode 100644
index 0000000000..44dd5f0579
--- /dev/null
+++ b/quantum/process_keycode/process_magic.c
@@ -0,0 +1,178 @@
+/* Copyright 2019 Jack Humbert
+ *
+ * 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 "process_magic.h"
+
+#ifdef AUDIO_ENABLE
+# ifndef AG_NORM_SONG
+# define AG_NORM_SONG SONG(AG_NORM_SOUND)
+# endif
+# ifndef AG_SWAP_SONG
+# define AG_SWAP_SONG SONG(AG_SWAP_SOUND)
+# endif
+# ifndef CG_NORM_SONG
+# define CG_NORM_SONG SONG(AG_NORM_SOUND)
+# endif
+# ifndef CG_SWAP_SONG
+# define CG_SWAP_SONG SONG(AG_SWAP_SOUND)
+# endif
+float ag_norm_song[][2] = AG_NORM_SONG;
+float ag_swap_song[][2] = AG_SWAP_SONG;
+float cg_norm_song[][2] = CG_NORM_SONG;
+float cg_swap_song[][2] = CG_SWAP_SONG;
+#endif
+
+/**
+ * MAGIC actions (BOOTMAGIC without the boot)
+ */
+bool process_magic(uint16_t keycode, keyrecord_t *record) {
+ // skip anything that isn't a keyup
+ if (record->event.pressed) {
+ switch (keycode) {
+ case MAGIC_SWAP_CONTROL_CAPSLOCK ... MAGIC_TOGGLE_ALT_GUI:
+ case MAGIC_SWAP_LCTL_LGUI ... MAGIC_EE_HANDS_RIGHT:
+ /* keymap config */
+ keymap_config.raw = eeconfig_read_keymap();
+ switch (keycode) {
+ case MAGIC_SWAP_CONTROL_CAPSLOCK:
+ keymap_config.swap_control_capslock = true;
+ break;
+ case MAGIC_CAPSLOCK_TO_CONTROL:
+ keymap_config.capslock_to_control = true;
+ break;
+ case MAGIC_SWAP_LALT_LGUI:
+ keymap_config.swap_lalt_lgui = true;
+ break;
+ case MAGIC_SWAP_RALT_RGUI:
+ keymap_config.swap_ralt_rgui = true;
+ break;
+ case MAGIC_SWAP_LCTL_LGUI:
+ keymap_config.swap_lctl_lgui = true;
+ break;
+ case MAGIC_SWAP_RCTL_RGUI:
+ keymap_config.swap_rctl_rgui = true;
+ break;
+ case MAGIC_NO_GUI:
+ keymap_config.no_gui = true;
+ break;
+ case MAGIC_SWAP_GRAVE_ESC:
+ keymap_config.swap_grave_esc = true;
+ break;
+ case MAGIC_SWAP_BACKSLASH_BACKSPACE:
+ keymap_config.swap_backslash_backspace = true;
+ break;
+ case MAGIC_HOST_NKRO:
+ clear_keyboard(); // clear first buffer to prevent stuck keys
+ keymap_config.nkro = true;
+ break;
+ case MAGIC_SWAP_ALT_GUI:
+ keymap_config.swap_lalt_lgui = keymap_config.swap_ralt_rgui = true;
+#ifdef AUDIO_ENABLE
+ PLAY_SONG(ag_swap_song);
+#endif
+ break;
+ case MAGIC_SWAP_CTL_GUI:
+ keymap_config.swap_lctl_lgui = keymap_config.swap_rctl_rgui = true;
+#ifdef AUDIO_ENABLE
+ PLAY_SONG(cg_swap_song);
+#endif
+ break;
+ case MAGIC_UNSWAP_CONTROL_CAPSLOCK:
+ keymap_config.swap_control_capslock = false;
+ break;
+ case MAGIC_UNCAPSLOCK_TO_CONTROL:
+ keymap_config.capslock_to_control = false;
+ break;
+ case MAGIC_UNSWAP_LALT_LGUI:
+ keymap_config.swap_lalt_lgui = false;
+ break;
+ case MAGIC_UNSWAP_RALT_RGUI:
+ keymap_config.swap_ralt_rgui = false;
+ break;
+ case MAGIC_UNSWAP_LCTL_LGUI:
+ keymap_config.swap_lctl_lgui = false;
+ break;
+ case MAGIC_UNSWAP_RCTL_RGUI:
+ keymap_config.swap_rctl_rgui = false;
+ break;
+ case MAGIC_UNNO_GUI:
+ keymap_config.no_gui = false;
+ break;
+ case MAGIC_UNSWAP_GRAVE_ESC:
+ keymap_config.swap_grave_esc = false;
+ break;
+ case MAGIC_UNSWAP_BACKSLASH_BACKSPACE:
+ keymap_config.swap_backslash_backspace = false;
+ break;
+ case MAGIC_UNHOST_NKRO:
+ clear_keyboard(); // clear first buffer to prevent stuck keys
+ keymap_config.nkro = false;
+ break;
+ case MAGIC_UNSWAP_ALT_GUI:
+ keymap_config.swap_lalt_lgui = keymap_config.swap_ralt_rgui = false;
+#ifdef AUDIO_ENABLE
+ PLAY_SONG(ag_norm_song);
+#endif
+ break;
+ case MAGIC_UNSWAP_CTL_GUI:
+ keymap_config.swap_lctl_lgui = keymap_config.swap_rctl_rgui = false;
+#ifdef AUDIO_ENABLE
+ PLAY_SONG(cg_norm_song);
+#endif
+ break;
+ case MAGIC_TOGGLE_ALT_GUI:
+ keymap_config.swap_lalt_lgui = !keymap_config.swap_lalt_lgui;
+ keymap_config.swap_ralt_rgui = keymap_config.swap_lalt_lgui;
+#ifdef AUDIO_ENABLE
+ if (keymap_config.swap_ralt_rgui) {
+ PLAY_SONG(ag_swap_song);
+ } else {
+ PLAY_SONG(ag_norm_song);
+ }
+#endif
+ break;
+ case MAGIC_TOGGLE_CTL_GUI:
+ keymap_config.swap_lctl_lgui = !keymap_config.swap_lctl_lgui;
+ keymap_config.swap_rctl_rgui = keymap_config.swap_lctl_lgui;
+#ifdef AUDIO_ENABLE
+ if (keymap_config.swap_rctl_rgui) {
+ PLAY_SONG(cg_swap_song);
+ } else {
+ PLAY_SONG(cg_norm_song);
+ }
+#endif
+ break;
+ case MAGIC_TOGGLE_NKRO:
+ clear_keyboard(); // clear first buffer to prevent stuck keys
+ keymap_config.nkro = !keymap_config.nkro;
+ break;
+ case MAGIC_EE_HANDS_LEFT:
+ eeconfig_update_handedness(true);
+ break;
+ case MAGIC_EE_HANDS_RIGHT:
+ eeconfig_update_handedness(false);
+ break;
+ }
+
+ eeconfig_update_keymap(keymap_config.raw);
+ clear_keyboard(); // clear to prevent stuck keys
+
+ return false;
+ }
+ }
+
+ // Not a magic keycode so continue processing
+ return true;
+}
diff --git a/quantum/process_keycode/process_magic.h b/quantum/process_keycode/process_magic.h
new file mode 100644
index 0000000000..1eb39f1455
--- /dev/null
+++ b/quantum/process_keycode/process_magic.h
@@ -0,0 +1,20 @@
+/* Copyright 2019
+ *
+ * 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/>.
+ */
+#pragma once
+
+#include "quantum.h"
+
+bool process_magic(uint16_t keycode, keyrecord_t *record);
diff --git a/quantum/process_keycode/process_rgb.c b/quantum/process_keycode/process_rgb.c
new file mode 100644
index 0000000000..c76166342f
--- /dev/null
+++ b/quantum/process_keycode/process_rgb.c
@@ -0,0 +1,141 @@
+/* Copyright 2019
+ *
+ * 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 "process_rgb.h"
+#include "rgb.h"
+
+typedef void (*rgb_func_pointer)(void);
+
+/**
+ * Wrapper for inc/dec rgb keycode
+ *
+ * noinline to optimise for firmware size not speed (not in hot path)
+ */
+static void __attribute__((noinline)) handleKeycodeRGB(const uint8_t is_shifted, const rgb_func_pointer inc_func, const rgb_func_pointer dec_func) {
+ if (is_shifted) {
+ dec_func();
+ } else {
+ inc_func();
+ }
+}
+
+/**
+ * Wrapper for animation mode
+ * - if not in animation family -> jump to that animation
+ * - otherwise -> wrap round animation speed
+ *
+ * noinline to optimise for firmware size not speed (not in hot path)
+ */
+static void __attribute__((noinline,unused)) handleKeycodeRGBMode(const uint8_t start, const uint8_t end) {
+ if ((start <= rgblight_get_mode()) && (rgblight_get_mode() < end)) {
+ rgblight_step();
+ } else {
+ rgblight_mode(start);
+ }
+}
+
+/**
+ * Handle keycodes for both rgblight and rgbmatrix
+ */
+bool process_rgb(const uint16_t keycode, const keyrecord_t *record) {
+#ifndef SPLIT_KEYBOARD
+ if (record->event.pressed) {
+#else
+ // Split keyboards need to trigger on key-up for edge-case issue
+ if (!record->event.pressed) {
+#endif
+ uint8_t shifted = get_mods() & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT));
+ switch (keycode) {
+ case RGB_TOG:
+ rgblight_toggle();
+ return false;
+ case RGB_MODE_FORWARD:
+ handleKeycodeRGB(shifted, rgblight_step, rgblight_step_reverse);
+ return false;
+ case RGB_MODE_REVERSE:
+ handleKeycodeRGB(shifted, rgblight_step_reverse, rgblight_step);
+ return false;
+ case RGB_HUI:
+ handleKeycodeRGB(shifted, rgblight_increase_hue, rgblight_decrease_hue);
+ return false;
+ case RGB_HUD:
+ handleKeycodeRGB(shifted, rgblight_decrease_hue, rgblight_increase_hue);
+ return false;
+ case RGB_SAI:
+ handleKeycodeRGB(shifted, rgblight_increase_sat, rgblight_decrease_sat);
+ return false;
+ case RGB_SAD:
+ handleKeycodeRGB(shifted, rgblight_decrease_sat, rgblight_increase_sat);
+ return false;
+ case RGB_VAI:
+ handleKeycodeRGB(shifted, rgblight_increase_val, rgblight_decrease_val);
+ return false;
+ case RGB_VAD:
+ handleKeycodeRGB(shifted, rgblight_decrease_val, rgblight_increase_val);
+ return false;
+ case RGB_SPI:
+ handleKeycodeRGB(shifted, rgblight_increase_speed, rgblight_decrease_speed);
+ return false;
+ case RGB_SPD:
+ handleKeycodeRGB(shifted, rgblight_decrease_speed, rgblight_increase_speed);
+ return false;
+ case RGB_MODE_PLAIN:
+ rgblight_mode(RGBLIGHT_MODE_STATIC_LIGHT);
+ return false;
+ case RGB_MODE_BREATHE:
+#ifdef RGBLIGHT_EFFECT_BREATHING
+ handleKeycodeRGBMode(RGBLIGHT_MODE_BREATHING, RGBLIGHT_MODE_BREATHING_end);
+#endif
+ return false;
+ case RGB_MODE_RAINBOW:
+#ifdef RGBLIGHT_EFFECT_RAINBOW_MOOD
+ handleKeycodeRGBMode(RGBLIGHT_MODE_RAINBOW_MOOD, RGBLIGHT_MODE_RAINBOW_MOOD_end);
+#endif
+ return false;
+ case RGB_MODE_SWIRL:
+#ifdef RGBLIGHT_EFFECT_RAINBOW_SWIRL
+ handleKeycodeRGBMode(RGBLIGHT_MODE_RAINBOW_SWIRL, RGBLIGHT_MODE_RAINBOW_SWIRL_end);
+#endif
+ return false;
+ case RGB_MODE_SNAKE:
+#ifdef RGBLIGHT_EFFECT_SNAKE
+ handleKeycodeRGBMode(RGBLIGHT_MODE_SNAKE, RGBLIGHT_MODE_SNAKE_end);
+#endif
+ return false;
+ case RGB_MODE_KNIGHT:
+#ifdef RGBLIGHT_EFFECT_KNIGHT
+ handleKeycodeRGBMode(RGBLIGHT_MODE_KNIGHT, RGBLIGHT_MODE_KNIGHT_end);
+#endif
+ return false;
+ case RGB_MODE_XMAS:
+#ifdef RGBLIGHT_EFFECT_CHRISTMAS
+ rgblight_mode(RGBLIGHT_MODE_CHRISTMAS);
+#endif
+ return false;
+ case RGB_MODE_GRADIENT:
+#ifdef RGBLIGHT_EFFECT_STATIC_GRADIENT
+ handleKeycodeRGBMode(RGBLIGHT_MODE_STATIC_GRADIENT, RGBLIGHT_MODE_STATIC_GRADIENT_end);
+#endif
+ return false;
+ case RGB_MODE_RGBTEST:
+#ifdef RGBLIGHT_EFFECT_RGB_TEST
+ rgblight_mode(RGBLIGHT_MODE_RGB_TEST);
+#endif
+ return false;
+ }
+ }
+
+ return true;
+}
diff --git a/quantum/process_keycode/process_rgb.h b/quantum/process_keycode/process_rgb.h
new file mode 100644
index 0000000000..26aca46896
--- /dev/null
+++ b/quantum/process_keycode/process_rgb.h
@@ -0,0 +1,20 @@
+/* Copyright 2019
+ *
+ * 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/>.
+ */
+#pragma once
+
+#include "quantum.h"
+
+bool process_rgb(const uint16_t keycode, const keyrecord_t *record);
diff --git a/quantum/process_keycode/process_steno.c b/quantum/process_keycode/process_steno.c
index e0b33ec861..57e279f211 100644
--- a/quantum/process_keycode/process_steno.c
+++ b/quantum/process_keycode/process_steno.c
@@ -73,7 +73,9 @@ static void steno_clear_state(void) {
static void send_steno_state(uint8_t size, bool send_empty) {
for (uint8_t i = 0; i < size; ++i) {
if (chord[i] || send_empty) {
+#ifdef VIRTSER_ENABLE
virtser_send(chord[i]);
+#endif
}
}
}
@@ -105,7 +107,9 @@ static void send_steno_chord(void) {
switch (mode) {
case STENO_MODE_BOLT:
send_steno_state(BOLT_STATE_SIZE, false);
+#ifdef VIRTSER_ENABLE
virtser_send(0); // terminating byte
+#endif
break;
case STENO_MODE_GEMINI:
chord[0] |= 0x80; // Indicate start of packet
diff --git a/quantum/process_keycode/process_steno.h b/quantum/process_keycode/process_steno.h
index 3675423728..ed049eb13f 100644
--- a/quantum/process_keycode/process_steno.h
+++ b/quantum/process_keycode/process_steno.h
@@ -18,10 +18,6 @@
#include "quantum.h"
-#if defined(STENO_ENABLE) && !defined(VIRTSER_ENABLE)
-# error "must have virtser enabled to use steno"
-#endif
-
typedef enum { STENO_MODE_BOLT, STENO_MODE_GEMINI } steno_mode_t;
bool process_steno(uint16_t keycode, keyrecord_t *record);
diff --git a/quantum/process_keycode/process_terminal.c b/quantum/process_keycode/process_terminal.c
index f48f3d702d..7d1eefa9ed 100644
--- a/quantum/process_keycode/process_terminal.c
+++ b/quantum/process_keycode/process_terminal.c
@@ -61,7 +61,7 @@ void enable_terminal(void) {
memset(cmd_buffer, 0, CMD_BUFF_SIZE * 80);
for (int i = 0; i < 6; i++) strcpy(arguments[i], "");
// select all text to start over
- // SEND_STRING(SS_LCTRL("a"));
+ // SEND_STRING(SS_LCTL("a"));
send_string(terminal_prompt);
}
diff --git a/quantum/quantum.c b/quantum/quantum.c
index 2e5e6376b7..9cd50b11d8 100644
--- a/quantum/quantum.c
+++ b/quantum/quantum.c
@@ -16,10 +16,6 @@
#include "quantum.h"
-#if !defined(RGBLIGHT_ENABLE) && !defined(RGB_MATRIX_ENABLE)
-# include "rgb.h"
-#endif
-
#ifdef PROTOCOL_LUFA
# include "outputselect.h"
#endif
@@ -57,26 +53,13 @@ extern backlight_config_t backlight_config;
# ifndef GOODBYE_SONG
# define GOODBYE_SONG SONG(GOODBYE_SOUND)
# endif
-# ifndef AG_NORM_SONG
-# define AG_NORM_SONG SONG(AG_NORM_SOUND)
-# endif
-# ifndef AG_SWAP_SONG
-# define AG_SWAP_SONG SONG(AG_SWAP_SOUND)
-# endif
-# ifndef CG_NORM_SONG
-# define CG_NORM_SONG SONG(AG_NORM_SOUND)
-# endif
-# ifndef CG_SWAP_SONG
-# define CG_SWAP_SONG SONG(AG_SWAP_SOUND)
-# endif
float goodbye_song[][2] = GOODBYE_SONG;
-float ag_norm_song[][2] = AG_NORM_SONG;
-float ag_swap_song[][2] = AG_SWAP_SONG;
-float cg_norm_song[][2] = CG_NORM_SONG;
-float cg_swap_song[][2] = CG_SWAP_SONG;
# ifdef DEFAULT_LAYER_SONGS
float default_layer_songs[][16][2] = DEFAULT_LAYER_SONGS;
# endif
+# ifdef SENDSTRING_BELL
+float bell_song[][2] = SONG(TERMINAL_SOUND);
+# endif
#endif
static void do_code16(uint16_t code, void (*f)(uint8_t)) {
@@ -164,11 +147,6 @@ void reset_keyboard(void) {
bootloader_jump();
}
-/* true if the last press of GRAVE_ESC was shifted (i.e. GUI or SHIFT were pressed), false otherwise.
- * Used to ensure that the correct keycode is released if the key is released.
- */
-static bool grave_esc_was_shifted = false;
-
/* Convert record into usable keycode via the contained event. */
uint16_t get_record_keycode(keyrecord_t *record) { return get_event_keycode(record->event); }
@@ -235,6 +213,9 @@ bool process_record_quantum(keyrecord_t *record) {
#if defined(RGB_MATRIX_ENABLE)
process_rgb_matrix(keycode, record) &&
#endif
+#if defined(VIA_ENABLE)
+ process_record_via(keycode, record) &&
+#endif
process_record_kb(keycode, record) &&
#if defined(MIDI_ENABLE) && defined(MIDI_ADVANCED)
process_midi(keycode, record) &&
@@ -272,402 +253,77 @@ bool process_record_quantum(keyrecord_t *record) {
#ifdef SPACE_CADET_ENABLE
process_space_cadet(keycode, record) &&
#endif
+#ifdef MAGIC_KEYCODE_ENABLE
+ process_magic(keycode, record) &&
+#endif
+#if defined(RGBLIGHT_ENABLE) || defined(RGB_MATRIX_ENABLE)
+ process_rgb(keycode, record) &&
+#endif
true)) {
return false;
}
- // Shift / paren setup
-
- switch (keycode) {
- case RESET:
- if (record->event.pressed) {
+ if (record->event.pressed) {
+ switch (keycode) {
+ case RESET:
reset_keyboard();
- }
- return false;
- case DEBUG:
- if (record->event.pressed) {
+ return false;
+#ifndef NO_DEBUG
+ case DEBUG:
debug_enable ^= 1;
if (debug_enable) {
print("DEBUG: enabled.\n");
} else {
print("DEBUG: disabled.\n");
}
- }
- return false;
- case EEPROM_RESET:
- if (record->event.pressed) {
+#endif
+ return false;
+ case EEPROM_RESET:
eeconfig_init();
- }
- return false;
+ return false;
#ifdef FAUXCLICKY_ENABLE
- case FC_TOG:
- if (record->event.pressed) {
+ case FC_TOG:
FAUXCLICKY_TOGGLE;
- }
- return false;
- case FC_ON:
- if (record->event.pressed) {
+ return false;
+ case FC_ON:
FAUXCLICKY_ON;
- }
- return false;
- case FC_OFF:
- if (record->event.pressed) {
+ return false;
+ case FC_OFF:
FAUXCLICKY_OFF;
- }
- return false;
+ return false;
#endif
-#if defined(RGBLIGHT_ENABLE) || defined(RGB_MATRIX_ENABLE)
- case RGB_TOG:
-// Split keyboards need to trigger on key-up for edge-case issue
-# ifndef SPLIT_KEYBOARD
- if (record->event.pressed) {
-# else
- if (!record->event.pressed) {
-# endif
- rgblight_toggle();
- }
- return false;
- case RGB_MODE_FORWARD:
- if (record->event.pressed) {
- uint8_t shifted = get_mods() & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT));
- if (shifted) {
- rgblight_step_reverse();
- } else {
- rgblight_step();
- }
- }
- return false;
- case RGB_MODE_REVERSE:
- if (record->event.pressed) {
- uint8_t shifted = get_mods() & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT));
- if (shifted) {
- rgblight_step();
- } else {
- rgblight_step_reverse();
- }
- }
- return false;
- case RGB_HUI:
-// Split keyboards need to trigger on key-up for edge-case issue
-# ifndef SPLIT_KEYBOARD
- if (record->event.pressed) {
-# else
- if (!record->event.pressed) {
-# endif
- rgblight_increase_hue();
- }
- return false;
- case RGB_HUD:
-// Split keyboards need to trigger on key-up for edge-case issue
-# ifndef SPLIT_KEYBOARD
- if (record->event.pressed) {
-# else
- if (!record->event.pressed) {
-# endif
- rgblight_decrease_hue();
- }
- return false;
- case RGB_SAI:
-// Split keyboards need to trigger on key-up for edge-case issue
-# ifndef SPLIT_KEYBOARD
- if (record->event.pressed) {
-# else
- if (!record->event.pressed) {
-# endif
- rgblight_increase_sat();
- }
- return false;
- case RGB_SAD:
-// Split keyboards need to trigger on key-up for edge-case issue
-# ifndef SPLIT_KEYBOARD
- if (record->event.pressed) {
-# else
- if (!record->event.pressed) {
-# endif
- rgblight_decrease_sat();
- }
- return false;
- case RGB_VAI:
-// Split keyboards need to trigger on key-up for edge-case issue
-# ifndef SPLIT_KEYBOARD
- if (record->event.pressed) {
-# else
- if (!record->event.pressed) {
-# endif
- rgblight_increase_val();
- }
- return false;
- case RGB_VAD:
-// Split keyboards need to trigger on key-up for edge-case issue
-# ifndef SPLIT_KEYBOARD
- if (record->event.pressed) {
-# else
- if (!record->event.pressed) {
-# endif
- rgblight_decrease_val();
- }
- return false;
- case RGB_SPI:
- if (record->event.pressed) {
- rgblight_increase_speed();
- }
- return false;
- case RGB_SPD:
- if (record->event.pressed) {
- rgblight_decrease_speed();
- }
- return false;
- case RGB_MODE_PLAIN:
- if (record->event.pressed) {
- rgblight_mode(RGBLIGHT_MODE_STATIC_LIGHT);
- }
- return false;
- case RGB_MODE_BREATHE:
-# ifdef RGBLIGHT_EFFECT_BREATHING
- if (record->event.pressed) {
- if ((RGBLIGHT_MODE_BREATHING <= rgblight_get_mode()) && (rgblight_get_mode() < RGBLIGHT_MODE_BREATHING_end)) {
- rgblight_step();
- } else {
- rgblight_mode(RGBLIGHT_MODE_BREATHING);
- }
- }
-# endif
- return false;
- case RGB_MODE_RAINBOW:
-# ifdef RGBLIGHT_EFFECT_RAINBOW_MOOD
- if (record->event.pressed) {
- if ((RGBLIGHT_MODE_RAINBOW_MOOD <= rgblight_get_mode()) && (rgblight_get_mode() < RGBLIGHT_MODE_RAINBOW_MOOD_end)) {
- rgblight_step();
- } else {
- rgblight_mode(RGBLIGHT_MODE_RAINBOW_MOOD);
- }
- }
-# endif
- return false;
- case RGB_MODE_SWIRL:
-# ifdef RGBLIGHT_EFFECT_RAINBOW_SWIRL
- if (record->event.pressed) {
- if ((RGBLIGHT_MODE_RAINBOW_SWIRL <= rgblight_get_mode()) && (rgblight_get_mode() < RGBLIGHT_MODE_RAINBOW_SWIRL_end)) {
- rgblight_step();
- } else {
- rgblight_mode(RGBLIGHT_MODE_RAINBOW_SWIRL);
- }
- }
-# endif
- return false;
- case RGB_MODE_SNAKE:
-# ifdef RGBLIGHT_EFFECT_SNAKE
- if (record->event.pressed) {
- if ((RGBLIGHT_MODE_SNAKE <= rgblight_get_mode()) && (rgblight_get_mode() < RGBLIGHT_MODE_SNAKE_end)) {
- rgblight_step();
- } else {
- rgblight_mode(RGBLIGHT_MODE_SNAKE);
- }
- }
-# endif
- return false;
- case RGB_MODE_KNIGHT:
-# ifdef RGBLIGHT_EFFECT_KNIGHT
- if (record->event.pressed) {
- if ((RGBLIGHT_MODE_KNIGHT <= rgblight_get_mode()) && (rgblight_get_mode() < RGBLIGHT_MODE_KNIGHT_end)) {
- rgblight_step();
- } else {
- rgblight_mode(RGBLIGHT_MODE_KNIGHT);
- }
- }
-# endif
- return false;
- case RGB_MODE_XMAS:
-# ifdef RGBLIGHT_EFFECT_CHRISTMAS
- if (record->event.pressed) {
- rgblight_mode(RGBLIGHT_MODE_CHRISTMAS);
- }
-# endif
- return false;
- case RGB_MODE_GRADIENT:
-# ifdef RGBLIGHT_EFFECT_STATIC_GRADIENT
- if (record->event.pressed) {
- if ((RGBLIGHT_MODE_STATIC_GRADIENT <= rgblight_get_mode()) && (rgblight_get_mode() < RGBLIGHT_MODE_STATIC_GRADIENT_end)) {
- rgblight_step();
- } else {
- rgblight_mode(RGBLIGHT_MODE_STATIC_GRADIENT);
- }
- }
-# endif
- return false;
- case RGB_MODE_RGBTEST:
-# ifdef RGBLIGHT_EFFECT_RGB_TEST
- if (record->event.pressed) {
- rgblight_mode(RGBLIGHT_MODE_RGB_TEST);
- }
-# endif
- return false;
-#endif // defined(RGBLIGHT_ENABLE) || defined(RGB_MATRIX_ENABLE)
#ifdef VELOCIKEY_ENABLE
- case VLK_TOG:
- if (record->event.pressed) {
+ case VLK_TOG:
velocikey_toggle();
- }
- return false;
+ return false;
#endif
-#ifdef PROTOCOL_LUFA
- case OUT_AUTO:
- if (record->event.pressed) {
+#ifdef BLUETOOTH_ENABLE
+ case OUT_AUTO:
set_output(OUTPUT_AUTO);
- }
- return false;
- case OUT_USB:
- if (record->event.pressed) {
+ return false;
+ case OUT_USB:
set_output(OUTPUT_USB);
- }
- return false;
-# ifdef BLUETOOTH_ENABLE
- case OUT_BT:
- if (record->event.pressed) {
+ return false;
+ case OUT_BT:
set_output(OUTPUT_BLUETOOTH);
- }
- return false;
-# endif
-#endif
- case MAGIC_SWAP_CONTROL_CAPSLOCK ... MAGIC_TOGGLE_ALT_GUI:
- case MAGIC_SWAP_LCTL_LGUI ... MAGIC_EE_HANDS_RIGHT:
- if (record->event.pressed) {
- // MAGIC actions (BOOTMAGIC without the boot)
- if (!eeconfig_is_enabled()) {
- eeconfig_init();
- }
- /* keymap config */
- keymap_config.raw = eeconfig_read_keymap();
- switch (keycode) {
- case MAGIC_SWAP_CONTROL_CAPSLOCK:
- keymap_config.swap_control_capslock = true;
- break;
- case MAGIC_CAPSLOCK_TO_CONTROL:
- keymap_config.capslock_to_control = true;
- break;
- case MAGIC_SWAP_LALT_LGUI:
- keymap_config.swap_lalt_lgui = true;
- break;
- case MAGIC_SWAP_RALT_RGUI:
- keymap_config.swap_ralt_rgui = true;
- break;
- case MAGIC_SWAP_LCTL_LGUI:
- keymap_config.swap_lctl_lgui = true;
- break;
- case MAGIC_SWAP_RCTL_RGUI:
- keymap_config.swap_rctl_rgui = true;
- break;
- case MAGIC_NO_GUI:
- keymap_config.no_gui = true;
- break;
- case MAGIC_SWAP_GRAVE_ESC:
- keymap_config.swap_grave_esc = true;
- break;
- case MAGIC_SWAP_BACKSLASH_BACKSPACE:
- keymap_config.swap_backslash_backspace = true;
- break;
- case MAGIC_HOST_NKRO:
- clear_keyboard(); // clear first buffer to prevent stuck keys
- keymap_config.nkro = true;
- break;
- case MAGIC_SWAP_ALT_GUI:
- keymap_config.swap_lalt_lgui = keymap_config.swap_ralt_rgui = true;
-#ifdef AUDIO_ENABLE
- PLAY_SONG(ag_swap_song);
-#endif
- break;
- case MAGIC_SWAP_CTL_GUI:
- keymap_config.swap_lctl_lgui = keymap_config.swap_rctl_rgui = true;
-#ifdef AUDIO_ENABLE
- PLAY_SONG(cg_swap_song);
-#endif
- break;
- case MAGIC_UNSWAP_CONTROL_CAPSLOCK:
- keymap_config.swap_control_capslock = false;
- break;
- case MAGIC_UNCAPSLOCK_TO_CONTROL:
- keymap_config.capslock_to_control = false;
- break;
- case MAGIC_UNSWAP_LALT_LGUI:
- keymap_config.swap_lalt_lgui = false;
- break;
- case MAGIC_UNSWAP_RALT_RGUI:
- keymap_config.swap_ralt_rgui = false;
- break;
- case MAGIC_UNSWAP_LCTL_LGUI:
- keymap_config.swap_lctl_lgui = false;
- break;
- case MAGIC_UNSWAP_RCTL_RGUI:
- keymap_config.swap_rctl_rgui = false;
- break;
- case MAGIC_UNNO_GUI:
- keymap_config.no_gui = false;
- break;
- case MAGIC_UNSWAP_GRAVE_ESC:
- keymap_config.swap_grave_esc = false;
- break;
- case MAGIC_UNSWAP_BACKSLASH_BACKSPACE:
- keymap_config.swap_backslash_backspace = false;
- break;
- case MAGIC_UNHOST_NKRO:
- clear_keyboard(); // clear first buffer to prevent stuck keys
- keymap_config.nkro = false;
- break;
- case MAGIC_UNSWAP_ALT_GUI:
- keymap_config.swap_lalt_lgui = keymap_config.swap_ralt_rgui = false;
-#ifdef AUDIO_ENABLE
- PLAY_SONG(ag_norm_song);
-#endif
- break;
- case MAGIC_UNSWAP_CTL_GUI:
- keymap_config.swap_lctl_lgui = keymap_config.swap_rctl_rgui = false;
-#ifdef AUDIO_ENABLE
- PLAY_SONG(cg_norm_song);
+ return false;
#endif
- break;
- case MAGIC_TOGGLE_ALT_GUI:
- keymap_config.swap_lalt_lgui = !keymap_config.swap_lalt_lgui;
- keymap_config.swap_ralt_rgui = keymap_config.swap_lalt_lgui;
-#ifdef AUDIO_ENABLE
- if (keymap_config.swap_ralt_rgui) {
- PLAY_SONG(ag_swap_song);
- } else {
- PLAY_SONG(ag_norm_song);
- }
-#endif
- break;
- case MAGIC_TOGGLE_CTL_GUI:
- keymap_config.swap_lctl_lgui = !keymap_config.swap_lctl_lgui;
- keymap_config.swap_rctl_rgui = keymap_config.swap_lctl_lgui;
-#ifdef AUDIO_ENABLE
- if (keymap_config.swap_rctl_rgui) {
- PLAY_SONG(cg_swap_song);
- } else {
- PLAY_SONG(cg_norm_song);
- }
-#endif
- break;
- case MAGIC_TOGGLE_NKRO:
- clear_keyboard(); // clear first buffer to prevent stuck keys
- keymap_config.nkro = !keymap_config.nkro;
- break;
- case MAGIC_EE_HANDS_LEFT:
- eeconfig_update_handedness(true);
- break;
- case MAGIC_EE_HANDS_RIGHT:
- eeconfig_update_handedness(false);
- break;
- default:
- break;
- }
- eeconfig_update_keymap(keymap_config.raw);
- clear_keyboard(); // clear to prevent stuck keys
-
+#if defined(BACKLIGHT_ENABLE) && defined(BACKLIGHT_BREATHING)
+ case BL_BRTG:
+ backlight_toggle_breathing();
return false;
- }
- break;
+#endif
+ }
+ }
+ // keycodes that depend on both pressed and non-pressed state
+ switch (keycode) {
case GRAVE_ESC: {
+ /* true if the last press of GRAVE_ESC was shifted (i.e. GUI or SHIFT were pressed), false otherwise.
+ * Used to ensure that the correct keycode is released if the key is released.
+ */
+ static bool grave_esc_was_shifted = false;
+
uint8_t shifted = get_mods() & ((MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT) | MOD_BIT(KC_LGUI) | MOD_BIT(KC_RGUI)));
#ifdef GRAVE_ESC_ALT_OVERRIDE
@@ -710,15 +366,6 @@ bool process_record_quantum(keyrecord_t *record) {
send_keyboard_report();
return false;
}
-
-#if defined(BACKLIGHT_ENABLE) && defined(BACKLIGHT_BREATHING)
- case BL_BRTG: {
- if (record->event.pressed) {
- backlight_toggle_breathing();
- }
- return false;
- }
-#endif
}
return process_action_kb(record);
@@ -829,6 +476,13 @@ void send_string_with_delay_P(const char *str, uint8_t interval) {
}
void send_char(char ascii_code) {
+#if defined(AUDIO_ENABLE) && defined(SENDSTRING_BELL)
+ if (ascii_code == '\a') { // BEL
+ PLAY_SONG(bell_song);
+ return;
+ }
+#endif
+
uint8_t keycode = pgm_read_byte(&ascii_to_keycode_lut[(uint8_t)ascii_code]);
bool is_shifted = pgm_read_byte(&ascii_to_shift_lut[(uint8_t)ascii_code]);
bool is_altgred = pgm_read_byte(&ascii_to_altgr_lut[(uint8_t)ascii_code]);
@@ -909,9 +563,7 @@ __attribute__((weak)) void bootmagic_lite(void) {
// We need multiple scans because debouncing can't be turned off.
matrix_scan();
-#if defined(DEBOUNCING_DELAY) && DEBOUNCING_DELAY > 0
- wait_ms(DEBOUNCING_DELAY * 2);
-#elif defined(DEBOUNCE) && DEBOUNCE > 0
+#if defined(DEBOUNCE) && DEBOUNCE > 0
wait_ms(DEBOUNCE * 2);
#else
wait_ms(30);
@@ -982,12 +634,8 @@ void matrix_scan_quantum() {
matrix_scan_combo();
#endif
-#if defined(BACKLIGHT_ENABLE)
-# if defined(LED_MATRIX_ENABLE)
+#ifdef LED_MATRIX_ENABLE
led_matrix_task();
-# elif defined(BACKLIGHT_PIN) || defined(BACKLIGHT_PINS)
- backlight_task();
-# endif
#endif
#ifdef RGB_MATRIX_ENABLE
diff --git a/quantum/quantum.h b/quantum/quantum.h
index 6beab65a32..09550fec30 100644
--- a/quantum/quantum.h
+++ b/quantum/quantum.h
@@ -22,6 +22,7 @@
#endif
#if defined(PROTOCOL_CHIBIOS)
# include "hal.h"
+# include "chibios_config.h"
#endif
#include "wait.h"
@@ -133,6 +134,14 @@ extern layer_state_t layer_state;
# include "process_space_cadet.h"
#endif
+#ifdef MAGIC_KEYCODE_ENABLE
+# include "process_magic.h"
+#endif
+
+#if defined(RGBLIGHT_ENABLE) || defined(RGB_MATRIX_ENABLE)
+# include "process_rgb.h"
+#endif
+
#ifdef HD44780_ENABLE
# include "hd44780.h"
#endif
@@ -153,6 +162,14 @@ extern layer_state_t layer_state;
# include "process_dynamic_macro.h"
#endif
+#ifdef DYNAMIC_KEYMAP_ENABLE
+# include "dynamic_keymap.h"
+#endif
+
+#ifdef VIA_ENABLE
+# include "via.h"
+#endif
+
// Function substitutions to ease GPIO manipulation
#if defined(__AVR__)
typedef uint8_t pin_t;
@@ -182,30 +199,8 @@ typedef ioline_t pin_t;
# define readPin(pin) palReadLine(pin)
#endif
-// Send string macros
-#define STRINGIZE(z) #z
-#define ADD_SLASH_X(y) STRINGIZE(\x##y)
-#define SYMBOL_STR(x) ADD_SLASH_X(x)
-
-#define SS_TAP_CODE 1
-#define SS_DOWN_CODE 2
-#define SS_UP_CODE 3
-
-#define SS_TAP(keycode) "\1" SYMBOL_STR(keycode)
-#define SS_DOWN(keycode) "\2" SYMBOL_STR(keycode)
-#define SS_UP(keycode) "\3" SYMBOL_STR(keycode)
-
-// `string` arguments must not be parenthesized
-#define SS_LCTRL(string) SS_DOWN(X_LCTRL) string SS_UP(X_LCTRL)
-#define SS_LGUI(string) SS_DOWN(X_LGUI) string SS_UP(X_LGUI)
-#define SS_LCMD(string) SS_LGUI(string)
-#define SS_LWIN(string) SS_LGUI(string)
-#define SS_LALT(string) SS_DOWN(X_LALT) string SS_UP(X_LALT)
-#define SS_LSFT(string) SS_DOWN(X_LSHIFT) string SS_UP(X_LSHIFT)
-#define SS_RALT(string) SS_DOWN(X_RALT) string SS_UP(X_RALT)
-#define SS_ALGR(string) SS_RALT(string)
-
#define SEND_STRING(string) send_string_P(PSTR(string))
+#define SEND_STRING_DELAY(string, interval) send_string_with_delay_P(PSTR(string), interval)
extern const bool ascii_to_shift_lut[128];
extern const bool ascii_to_altgr_lut[128];
@@ -256,30 +251,6 @@ void register_code16(uint16_t code);
void unregister_code16(uint16_t code);
void tap_code16(uint16_t code);
-#ifdef BACKLIGHT_ENABLE
-void backlight_init_ports(void);
-void backlight_task(void);
-void backlight_task_internal(void);
-void backlight_on(pin_t backlight_pin);
-void backlight_off(pin_t backlight_pin);
-
-# ifdef BACKLIGHT_BREATHING
-void breathing_task(void);
-void breathing_enable(void);
-void breathing_pulse(void);
-void breathing_disable(void);
-void breathing_self_disable(void);
-void breathing_toggle(void);
-bool is_breathing(void);
-
-void breathing_intensity_default(void);
-void breathing_period_default(void);
-void breathing_period_set(uint8_t value);
-void breathing_period_inc(void);
-void breathing_period_dec(void);
-# endif
-#endif
-
void send_dword(uint32_t number);
void send_word(uint16_t number);
void send_byte(uint8_t number);
diff --git a/quantum/quantum_keycodes.h b/quantum/quantum_keycodes.h
index 66a3c66e85..c8d0e354b0 100644
--- a/quantum/quantum_keycodes.h
+++ b/quantum/quantum_keycodes.h
@@ -655,13 +655,42 @@ enum quantum_keycodes {
// L-ayer, T-ap - 256 keycode max, 16 layer max
#define LT(layer, kc) (QK_LAYER_TAP | (((layer)&0xF) << 8) | ((kc)&0xFF))
+#define CL_SWAP MAGIC_SWAP_CONTROL_CAPSLOCK
+#define CL_NORM MAGIC_UNSWAP_CONTROL_CAPSLOCK
+#define CL_CTRL MAGIC_CAPSLOCK_TO_CONTROL
+#define CL_CAPS MAGIC_UNCAPSLOCK_TO_CONTROL
+
+#define LCG_SWP MAGIC_SWAP_LCTL_LGUI
+#define LCG_NRM MAGIC_UNSWAP_LCTL_LGUI
+#define RCG_SWP MAGIC_SWAP_RCTL_RGUI
+#define RCG_NRM MAGIC_UNSWAP_RCTL_RGUI
+#define CG_SWAP MAGIC_SWAP_CTL_GUI
+#define CG_NORM MAGIC_UNSWAP_CTL_GUI
+#define CG_TOGG MAGIC_TOGGLE_CTL_GUI
+
+#define LAG_SWP MAGIC_SWAP_LALT_LGUI
+#define LAG_NRM MAGIC_UNSWAP_LALT_LGUI
+#define RAG_SWP MAGIC_SWAP_RALT_RGUI
+#define RAG_NRM MAGIC_UNSWAP_RALT_RGUI
#define AG_SWAP MAGIC_SWAP_ALT_GUI
#define AG_NORM MAGIC_UNSWAP_ALT_GUI
#define AG_TOGG MAGIC_TOGGLE_ALT_GUI
-#define CG_SWAP MAGIC_SWAP_CTL_GUI
-#define CG_NORM MAGIC_UNSWAP_CTL_GUI
-#define CG_TOGG MAGIC_TOGGLE_CTL_GUI
+#define GUI_OFF MAGIC_NO_GUI
+#define GUI_ON MAGIC_UNNO_GUI
+
+#define GE_SWAP MAGIC_SWAP_GRAVE_ESC
+#define GE_NORM MAGIC_UNSWAP_GRAVE_ESC
+
+#define BS_SWAP MAGIC_SWAP_BACKSLASH_BACKSPACE
+#define BS_NORM MAGIC_UNSWAP_BACKSLASH_BACKSPACE
+
+#define NK_ON MAGIC_HOST_NKRO
+#define NK_OFF MAGIC_UNHOST_NKRO
+#define NK_TOGG MAGIC_TOGGLE_NKRO
+
+#define EH_LEFT MAGIC_EE_HANDS_LEFT
+#define EH_RGHT MAGIC_EE_HANDS_RIGHT
// GOTO layer - 16 layers max
// when:
diff --git a/quantum/rgb_matrix.c b/quantum/rgb_matrix.c
index 55a6f74be7..25ca44054d 100644
--- a/quantum/rgb_matrix.c
+++ b/quantum/rgb_matrix.c
@@ -95,6 +95,23 @@ const point_t k_rgb_matrix_center = RGB_MATRIX_CENTER;
# endif
#endif
+#if !defined(RGB_MATRIX_STARTUP_HUE)
+# define RGB_MATRIX_STARTUP_HUE 0
+#endif
+
+#if !defined(RGB_MATRIX_STARTUP_SAT)
+# define RGB_MATRIX_STARTUP_SAT UINT8_MAX
+#endif
+
+#if !defined(RGB_MATRIX_STARTUP_VAL)
+# define RGB_MATRIX_STARTUP_VAL RGB_MATRIX_MAXIMUM_BRIGHTNESS
+#endif
+
+#if !defined(RGB_MATRIX_STARTUP_SPD)
+# define RGB_MATRIX_STARTUP_SPD UINT8_MAX / 2
+#endif
+
+
bool g_suspend_state = false;
rgb_config_t rgb_matrix_config;
@@ -119,8 +136,8 @@ void eeconfig_update_rgb_matrix_default(void) {
dprintf("eeconfig_update_rgb_matrix_default\n");
rgb_matrix_config.enable = 1;
rgb_matrix_config.mode = RGB_MATRIX_STARTUP_MODE;
- rgb_matrix_config.hsv = (HSV){0, UINT8_MAX, RGB_MATRIX_MAXIMUM_BRIGHTNESS};
- rgb_matrix_config.speed = UINT8_MAX / 2;
+ rgb_matrix_config.hsv = (HSV){RGB_MATRIX_STARTUP_HUE, RGB_MATRIX_STARTUP_SAT, RGB_MATRIX_STARTUP_VAL};
+ rgb_matrix_config.speed = RGB_MATRIX_STARTUP_SPD;
eeconfig_update_rgb_matrix();
}
@@ -417,7 +434,12 @@ void rgb_matrix_init(void) {
eeconfig_debug_rgb_matrix(); // display current eeprom values
}
-void rgb_matrix_set_suspend_state(bool state) { g_suspend_state = state; }
+void rgb_matrix_set_suspend_state(bool state) {
+ if (RGB_DISABLE_WHEN_USB_SUSPENDED && state) {
+ rgb_matrix_set_color_all(0, 0, 0); // turn off all LEDs when suspending
+ }
+ g_suspend_state = state;
+}
void rgb_matrix_toggle(void) {
rgb_matrix_config.enable ^= 1;
diff --git a/quantum/rgb_matrix.h b/quantum/rgb_matrix.h
index 16ec96f036..96494836ee 100644
--- a/quantum/rgb_matrix.h
+++ b/quantum/rgb_matrix.h
@@ -128,26 +128,26 @@ void rgb_matrix_sethsv(uint16_t hue, uint8_t sat, uint8_t val);
void rgb_matrix_sethsv_noeeprom(uint16_t hue, uint8_t sat, uint8_t val);
#ifndef RGBLIGHT_ENABLE
-# define rgblight_toggle() rgb_matrix_toggle()
-# define rgblight_enable() rgb_matrix_enable()
-# define rgblight_enable_noeeprom() rgb_matrix_enable_noeeprom()
-# define rgblight_disable() rgb_matrix_disable()
-# define rgblight_disable_noeeprom() rgb_matrix_disable_noeeprom()
-# define rgblight_step() rgb_matrix_step()
-# define rgblight_sethsv(hue, sat, val) rgb_matrix_sethsv(hue, sat, val)
-# define rgblight_sethsv_noeeprom(hue, sat, val) rgb_matrix_sethsv_noeeprom(hue, sat, val)
-# define rgblight_step_reverse() rgb_matrix_step_reverse()
-# define rgblight_increase_hue() rgb_matrix_increase_hue()
-# define rgblight_decrease_hue() rgb_matrix_decrease_hue()
-# define rgblight_increase_sat() rgb_matrix_increase_sat()
-# define rgblight_decrease_sat() rgb_matrix_decrease_sat()
-# define rgblight_increase_val() rgb_matrix_increase_val()
-# define rgblight_decrease_val() rgb_matrix_decrease_val()
-# define rgblight_increase_speed() rgb_matrix_increase_speed()
-# define rgblight_decrease_speed() rgb_matrix_decrease_speed()
-# define rgblight_mode(mode) rgb_matrix_mode(mode)
-# define rgblight_mode_noeeprom(mode) rgb_matrix_mode_noeeprom(mode)
-# define rgblight_get_mode() rgb_matrix_get_mode()
+# define rgblight_toggle rgb_matrix_toggle
+# define rgblight_enable rgb_matrix_enable
+# define rgblight_enable_noeeprom rgb_matrix_enable_noeeprom
+# define rgblight_disable rgb_matrix_disable
+# define rgblight_disable_noeeprom rgb_matrix_disable_noeeprom
+# define rgblight_step rgb_matrix_step
+# define rgblight_sethsv rgb_matrix_sethsv
+# define rgblight_sethsv_noeeprom rgb_matrix_sethsv_noeeprom
+# define rgblight_step_reverse rgb_matrix_step_reverse
+# define rgblight_increase_hue rgb_matrix_increase_hue
+# define rgblight_decrease_hue rgb_matrix_decrease_hue
+# define rgblight_increase_sat rgb_matrix_increase_sat
+# define rgblight_decrease_sat rgb_matrix_decrease_sat
+# define rgblight_increase_val rgb_matrix_increase_val
+# define rgblight_decrease_val rgb_matrix_decrease_val
+# define rgblight_increase_speed rgb_matrix_increase_speed
+# define rgblight_decrease_speed rgb_matrix_decrease_speed
+# define rgblight_mode rgb_matrix_mode
+# define rgblight_mode_noeeprom rgb_matrix_mode_noeeprom
+# define rgblight_get_mode rgb_matrix_get_mode
#endif
typedef struct {
diff --git a/quantum/rgb_matrix_animations/gradient_left_right_anim.h b/quantum/rgb_matrix_animations/gradient_left_right_anim.h
new file mode 100644
index 0000000000..2eab2eb759
--- /dev/null
+++ b/quantum/rgb_matrix_animations/gradient_left_right_anim.h
@@ -0,0 +1,22 @@
+#ifndef DISABLE_RGB_MATRIX_GRADIENT_LEFT_RIGHT
+RGB_MATRIX_EFFECT(GRADIENT_LEFT_RIGHT)
+# ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS
+
+bool GRADIENT_LEFT_RIGHT(effect_params_t* params) {
+ RGB_MATRIX_USE_LIMITS(led_min, led_max);
+
+ HSV hsv = rgb_matrix_config.hsv;
+ uint8_t scale = scale8(64, rgb_matrix_config.speed);
+ for (uint8_t i = led_min; i < led_max; i++) {
+ RGB_MATRIX_TEST_LED_FLAGS();
+ // The x range will be 0..224, map this to 0..7
+ // Relies on hue being 8-bit and wrapping
+ hsv.h = rgb_matrix_config.hsv.h + (scale * g_led_config.point[i].x >> 5);
+ RGB rgb = hsv_to_rgb(hsv);
+ rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b);
+ }
+ return led_max < DRIVER_LED_TOTAL;
+}
+
+# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
+#endif // DISABLE_RGB_MATRIX_GRADIENT_LEFT_RIGHT
diff --git a/quantum/rgb_matrix_animations/rgb_matrix_effects.inc b/quantum/rgb_matrix_animations/rgb_matrix_effects.inc
index 01332ed0dd..4c1723d933 100644
--- a/quantum/rgb_matrix_animations/rgb_matrix_effects.inc
+++ b/quantum/rgb_matrix_animations/rgb_matrix_effects.inc
@@ -2,6 +2,7 @@
#include "rgb_matrix_animations/solid_color_anim.h"
#include "rgb_matrix_animations/alpha_mods_anim.h"
#include "rgb_matrix_animations/gradient_up_down_anim.h"
+#include "rgb_matrix_animations/gradient_left_right_anim.h"
#include "rgb_matrix_animations/breathing_anim.h"
#include "rgb_matrix_animations/colorband_sat_anim.h"
#include "rgb_matrix_animations/colorband_val_anim.h"
diff --git a/quantum/rgb_matrix_drivers.c b/quantum/rgb_matrix_drivers.c
index 9729a3064e..ea41b0d396 100644
--- a/quantum/rgb_matrix_drivers.c
+++ b/quantum/rgb_matrix_drivers.c
@@ -113,7 +113,7 @@ static inline void setled(int i, uint8_t r, uint8_t g, uint8_t b) {
led[i].g = g;
led[i].b = b;
# ifdef RGBW
- led[i].w = 0;
+ convert_rgb_to_rgbw(led[i]);
# endif
}
diff --git a/quantum/rgblight.c b/quantum/rgblight.c
index 7949bb688e..141dc2e7bc 100644
--- a/quantum/rgblight.c
+++ b/quantum/rgblight.c
@@ -611,6 +611,7 @@ void rgblight_set(void) {
# endif
}
}
+
# ifdef RGBLIGHT_LED_MAP
LED_TYPE led0[RGBLED_NUM];
for (uint8_t i = 0; i < RGBLED_NUM; i++) {
@@ -620,7 +621,13 @@ void rgblight_set(void) {
# else
start_led = led + clipping_start_pos;
# endif
- ws2812_setleds(start_led, num_leds);
+
+#ifdef RGBW
+ for (uint8_t i = 0; i < num_leds; i++) {
+ convert_rgb_to_rgbw(&start_led[i]);
+ }
+#endif
+ ws2812_setleds(start_led, num_leds);
}
#endif
diff --git a/quantum/send_string_keycodes.h b/quantum/send_string_keycodes.h
index e71790a1dc..fc6467a741 100644
--- a/quantum/send_string_keycodes.h
+++ b/quantum/send_string_keycodes.h
@@ -1,207 +1,374 @@
-#ifndef SEND_STRING_KEYCODES
-#define SEND_STRING_KEYCODES
-
-#define X_NO 00
-#define X_ROLL_OVER 01
-#define X_POST_FAIL 02
-#define X_UNDEFINED 03
-#define X_A 04
-#define X_B 05
-#define X_C 06
-#define X_D 07
-#define X_E 08
-#define X_F 09
-#define X_G 0a
-#define X_H 0b
-#define X_I 0c
-#define X_J 0d
-#define X_K 0e
-#define X_L 0f
-#define X_M 10
-#define X_N 11
-#define X_O 12
-#define X_P 13
-#define X_Q 14
-#define X_R 15
-#define X_S 16
-#define X_T 17
-#define X_U 18
-#define X_V 19
-#define X_W 1a
-#define X_X 1b
-#define X_Y 1c
-#define X_Z 1d
-#define X_1 1e
-#define X_2 1f
-#define X_3 20
-#define X_4 21
-#define X_5 22
-#define X_6 23
-#define X_7 24
-#define X_8 25
-#define X_9 26
-#define X_0 27
-#define X_ENTER 28
-#define X_ESCAPE 29
-#define X_BSPACE 2a
-#define X_TAB 2b
-#define X_SPACE 2c
-#define X_MINUS 2d
-#define X_EQUAL 2e
-#define X_LBRACKET 2f
-#define X_RBRACKET 30
-#define X_BSLASH 31
-#define X_NONUS_HASH 32
-#define X_SCOLON 33
-#define X_QUOTE 34
-#define X_GRAVE 35
-#define X_COMMA 36
-#define X_DOT 37
-#define X_SLASH 38
-#define X_CAPSLOCK 39
-#define X_F1 3a
-#define X_F2 3b
-#define X_F3 3c
-#define X_F4 3d
-#define X_F5 3e
-#define X_F6 3f
-#define X_F7 40
-#define X_F8 41
-#define X_F9 42
-#define X_F10 43
-#define X_F11 44
-#define X_F12 45
-#define X_PSCREEN 46
-#define X_SCROLLLOCK 47
-#define X_PAUSE 48
-#define X_INSERT 49
-#define X_HOME 4a
-#define X_PGUP 4b
-#define X_DELETE 4c
-#define X_END 4d
-#define X_PGDOWN 4e
-#define X_RIGHT 4f
-#define X_LEFT 50
-#define X_DOWN 51
-#define X_UP 52
-#define X_NUMLOCK 53
-#define X_KP_SLASH 54
-#define X_KP_ASTERISK 55
-#define X_KP_MINUS 56
-#define X_KP_PLUS 57
-#define X_KP_ENTER 58
-#define X_KP_1 59
-#define X_KP_2 5a
-#define X_KP_3 5b
-#define X_KP_4 5c
-#define X_KP_5 5d
-#define X_KP_6 5e
-#define X_KP_7 5f
-#define X_KP_8 60
-#define X_KP_9 61
-#define X_KP_0 62
-#define X_KP_DOT 63
-#define X_NONUS_BSLASH 64
-#define X_APPLICATION 65
-#define X_POWER 66
-#define X_KP_EQUAL 67
-#define X_F13 68
-#define X_F14 69
-#define X_F15 6a
-#define X_F16 6b
-#define X_F17 6c
-#define X_F18 6d
-#define X_F19 6e
-#define X_F20 6f
-#define X_F21 70
-#define X_F22 71
-#define X_F23 72
-#define X_F24 73
-#define X_EXECUTE 74
-#define X_HELP 75
-#define X_MENU 76
-#define X_SELECT 77
-#define X_STOP 78
-#define X_AGAIN 79
-#define X_UNDO 7a
-#define X_CUT 7b
-#define X_COPY 7c
-#define X_PASTE 7d
-#define X_FIND 7e
-#define X__MUTE 7f
-#define X__VOLUP 80
-#define X__VOLDOWN 81
-#define X_LOCKING_CAPS 82
-#define X_LOCKING_NUM 83
-#define X_LOCKING_SCROLL 84
-#define X_KP_COMMA 85
-#define X_KP_EQUAL_AS400 86
-#define X_INT1 87
-#define X_INT2 88
-#define X_INT3 89
-#define X_INT4 8a
-#define X_INT5 8b
-#define X_INT6 8c
-#define X_INT7 8d
-#define X_INT8 8e
-#define X_INT9 8f
-#define X_LANG1 90
-#define X_LANG2 91
-#define X_LANG3 92
-#define X_LANG4 93
-#define X_LANG5 94
-#define X_LANG6 95
-#define X_LANG7 96
-#define X_LANG8 97
-#define X_LANG9 98
-#define X_ALT_ERASE 99
-#define X_SYSREQ 9a
-#define X_CANCEL 9b
-#define X_CLEAR 9c
-#define X_PRIOR 9d
-#define X_RETURN 9e
-#define X_SEPARATOR 9f
-#define X_OUT a0
-#define X_OPER a1
-#define X_CLEAR_AGAIN a2
-#define X_CRSEL a3
-#define X_EXSEL a4
+/* Copyright 2019
+ *
+ * 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/>.
+ */
+
+#pragma once
+
+// clang-format off
+
+/* Punctuation */
+#define X_ENT X_ENTER
+#define X_ESC X_ESCAPE
+#define X_BSPC X_BSPACE
+#define X_SPC X_SPACE
+#define X_MINS X_MINUS
+#define X_EQL X_EQUAL
+#define X_LBRC X_LBRACKET
+#define X_RBRC X_RBRACKET
+#define X_BSLS X_BSLASH
+#define X_NUHS X_NONUS_HASH
+#define X_SCLN X_SCOLON
+#define X_QUOT X_QUOTE
+#define X_GRV X_GRAVE
+#define X_COMM X_COMMA
+#define X_SLSH X_SLASH
+#define X_NUBS X_NONUS_BSLASH
+
+/* Lock Keys */
+#define X_CLCK X_CAPSLOCK
+#define X_CAPS X_CAPSLOCK
+#define X_SLCK X_SCROLLLOCK
+#define X_NLCK X_NUMLOCK
+#define X_LCAP X_LOCKING_CAPS
+#define X_LNUM X_LOCKING_NUM
+#define X_LSCR X_LOCKING_SCROLL
+
+/* Commands */
+#define X_PSCR X_PSCREEN
+#define X_PAUS X_PAUSE
+#define X_BRK X_PAUSE
+#define X_INS X_INSERT
+#define X_DEL X_DELETE
+#define X_PGDN X_PGDOWN
+#define X_RGHT X_RIGHT
+#define X_APP X_APPLICATION
+#define X_EXEC X_EXECUTE
+#define X_SLCT X_SELECT
+#define X_AGIN X_AGAIN
+#define X_PSTE X_PASTE
+#define X_ERAS X_ALT_ERASE
+#define X_CLR X_CLEAR
+
+/* Keypad */
+#define X_PSLS X_KP_SLASH
+#define X_PAST X_KP_ASTERISK
+#define X_PMNS X_KP_MINUS
+#define X_PPLS X_KP_PLUS
+#define X_PENT X_KP_ENTER
+#define X_P1 X_KP_1
+#define X_P2 X_KP_2
+#define X_P3 X_KP_3
+#define X_P4 X_KP_4
+#define X_P5 X_KP_5
+#define X_P6 X_KP_6
+#define X_P7 X_KP_7
+#define X_P8 X_KP_8
+#define X_P9 X_KP_9
+#define X_P0 X_KP_0
+#define X_PDOT X_KP_DOT
+#define X_PEQL X_KP_EQUAL
+#define X_PCMM X_KP_COMMA
+
+/* Japanese specific */
+#define X_ZKHK X_GRAVE
+#define X_RO X_INT1
+#define X_KANA X_INT2
+#define X_JYEN X_INT3
+#define X_HENK X_INT4
+#define X_MHEN X_INT5
+
+/* Korean specific */
+#define X_HAEN X_LANG1
+#define X_HANJ X_LANG2
+
+/* Modifiers */
+#define X_LCTL X_LCTRL
+#define X_LSFT X_LSHIFT
+#define X_LCMD X_LGUI
+#define X_LWIN X_LGUI
+#define X_RCTL X_RCTRL
+#define X_RSFT X_RSHIFT
+#define X_ALGR X_RALT
+#define X_RCMD X_RGUI
+#define X_RWIN X_RGUI
+
+/* Generic Desktop Page (0x01) */
+#define X_PWR X_SYSTEM_POWER
+#define X_SLEP X_SYSTEM_SLEEP
+#define X_WAKE X_SYSTEM_WAKE
+
+/* Consumer Page (0x0C) */
+#define X_MUTE X_AUDIO_MUTE
+#define X_VOLU X_AUDIO_VOL_UP
+#define X_VOLD X_AUDIO_VOL_DOWN
+#define X_MNXT X_MEDIA_NEXT_TRACK
+#define X_MPRV X_MEDIA_PREV_TRACK
+#define X_MSTP X_MEDIA_STOP
+#define X_MPLY X_MEDIA_PLAY_PAUSE
+#define X_MSEL X_MEDIA_SELECT
+#define X_EJCT X_MEDIA_EJECT
+#define X_CALC X_CALCULATOR
+#define X_MYCM X_MY_COMPUTER
+#define X_WSCH X_WWW_SEARCH
+#define X_WHOM X_WWW_HOME
+#define X_WBAK X_WWW_BACK
+#define X_WFWD X_WWW_FORWARD
+#define X_WSTP X_WWW_STOP
+#define X_WREF X_WWW_REFRESH
+#define X_WFAV X_WWW_FAVORITES
+#define X_MFFD X_MEDIA_FAST_FORWARD
+#define X_MRWD X_MEDIA_REWIND
+#define X_BRIU X_BRIGHTNESS_UP
+#define X_BRID X_BRIGHTNESS_DOWN
+
+/* System Specific */
+#define X_BRMU X_PAUSE
+#define X_BRMD X_SCROLLLOCK
+
+/* Keyboard/Keypad Page (0x07) */
+#define X_A 04
+#define X_B 05
+#define X_C 06
+#define X_D 07
+#define X_E 08
+#define X_F 09
+#define X_G 0a
+#define X_H 0b
+#define X_I 0c
+#define X_J 0d
+#define X_K 0e
+#define X_L 0f
+#define X_M 10
+#define X_N 11
+#define X_O 12
+#define X_P 13
+#define X_Q 14
+#define X_R 15
+#define X_S 16
+#define X_T 17
+#define X_U 18
+#define X_V 19
+#define X_W 1a
+#define X_X 1b
+#define X_Y 1c
+#define X_Z 1d
+#define X_1 1e
+#define X_2 1f
+#define X_3 20
+#define X_4 21
+#define X_5 22
+#define X_6 23
+#define X_7 24
+#define X_8 25
+#define X_9 26
+#define X_0 27
+#define X_ENTER 28
+#define X_ESCAPE 29
+#define X_BSPACE 2a
+#define X_TAB 2b
+#define X_SPACE 2c
+#define X_MINUS 2d
+#define X_EQUAL 2e
+#define X_LBRACKET 2f
+#define X_RBRACKET 30
+#define X_BSLASH 31
+#define X_NONUS_HASH 32
+#define X_SCOLON 33
+#define X_QUOTE 34
+#define X_GRAVE 35
+#define X_COMMA 36
+#define X_DOT 37
+#define X_SLASH 38
+#define X_CAPSLOCK 39
+#define X_F1 3a
+#define X_F2 3b
+#define X_F3 3c
+#define X_F4 3d
+#define X_F5 3e
+#define X_F6 3f
+#define X_F7 40
+#define X_F8 41
+#define X_F9 42
+#define X_F10 43
+#define X_F11 44
+#define X_F12 45
+#define X_PSCREEN 46
+#define X_SCROLLLOCK 47
+#define X_PAUSE 48
+#define X_INSERT 49
+#define X_HOME 4a
+#define X_PGUP 4b
+#define X_DELETE 4c
+#define X_END 4d
+#define X_PGDOWN 4e
+#define X_RIGHT 4f
+#define X_LEFT 50
+#define X_DOWN 51
+#define X_UP 52
+#define X_NUMLOCK 53
+#define X_KP_SLASH 54
+#define X_KP_ASTERISK 55
+#define X_KP_MINUS 56
+#define X_KP_PLUS 57
+#define X_KP_ENTER 58
+#define X_KP_1 59
+#define X_KP_2 5a
+#define X_KP_3 5b
+#define X_KP_4 5c
+#define X_KP_5 5d
+#define X_KP_6 5e
+#define X_KP_7 5f
+#define X_KP_8 60
+#define X_KP_9 61
+#define X_KP_0 62
+#define X_KP_DOT 63
+#define X_NONUS_BSLASH 64
+#define X_APPLICATION 65
+#define X_POWER 66
+#define X_KP_EQUAL 67
+#define X_F13 68
+#define X_F14 69
+#define X_F15 6a
+#define X_F16 6b
+#define X_F17 6c
+#define X_F18 6d
+#define X_F19 6e
+#define X_F20 6f
+#define X_F21 70
+#define X_F22 71
+#define X_F23 72
+#define X_F24 73
+#define X_EXECUTE 74
+#define X_HELP 75
+#define X_MENU 76
+#define X_SELECT 77
+#define X_STOP 78
+#define X_AGAIN 79
+#define X_UNDO 7a
+#define X_CUT 7b
+#define X_COPY 7c
+#define X_PASTE 7d
+#define X_FIND 7e
+#define X__MUTE 7f
+#define X__VOLUP 80
+#define X__VOLDOWN 81
+#define X_LOCKING_CAPS 82
+#define X_LOCKING_NUM 83
+#define X_LOCKING_SCROLL 84
+#define X_KP_COMMA 85
+#define X_KP_EQUAL_AS400 86
+#define X_INT1 87
+#define X_INT2 88
+#define X_INT3 89
+#define X_INT4 8a
+#define X_INT5 8b
+#define X_INT6 8c
+#define X_INT7 8d
+#define X_INT8 8e
+#define X_INT9 8f
+#define X_LANG1 90
+#define X_LANG2 91
+#define X_LANG3 92
+#define X_LANG4 93
+#define X_LANG5 94
+#define X_LANG6 95
+#define X_LANG7 96
+#define X_LANG8 97
+#define X_LANG9 98
+#define X_ALT_ERASE 99
+#define X_SYSREQ 9a
+#define X_CANCEL 9b
+#define X_CLEAR 9c
+#define X_PRIOR 9d
+#define X_RETURN 9e
+#define X_SEPARATOR 9f
+#define X_OUT a0
+#define X_OPER a1
+#define X_CLEAR_AGAIN a2
+#define X_CRSEL a3
+#define X_EXSEL a4
/* Modifiers */
-#define X_LCTRL e0
-#define X_LSHIFT e1
-#define X_LALT e2
-#define X_LGUI e3
-#define X_RCTRL e4
-#define X_RSHIFT e5
-#define X_RALT e6
-#define X_RGUI e7
-
-/* System Control */
-#define X_SYSTEM_POWER a5
-#define X_SYSTEM_SLEEP a6
-#define X_SYSTEM_WAKE a7
-
-/* Media Control */
-#define X_AUDIO_MUTE a8
-#define X_AUDIO_VOL_UP a9
-#define X_AUDIO_VOL_DOWN aa
-#define X_MEDIA_NEXT_TRACK ab
-#define X_MEDIA_PREV_TRACK ac
-#define X_MEDIA_STOP ad
-#define X_MEDIA_PLAY_PAUSE ae
-#define X_MEDIA_SELECT af
-#define X_MEDIA_EJECT b0
-#define X_MAIL b1
-#define X_CALCULATOR b2
-#define X_MY_COMPUTER b3
-#define X_WWW_SEARCH b4
-#define X_WWW_HOME b5
-#define X_WWW_BACK b6
-#define X_WWW_FORWARD b7
-#define X_WWW_STOP b8
-#define X_WWW_REFRESH b9
-#define X_WWW_FAVORITES ba
+#define X_LCTRL e0
+#define X_LSHIFT e1
+#define X_LALT e2
+#define X_LGUI e3
+#define X_RCTRL e4
+#define X_RSHIFT e5
+#define X_RALT e6
+#define X_RGUI e7
+
+/* Media and Function keys */
+/* Generic Desktop Page (0x01) */
+#define X_SYSTEM_POWER a5
+#define X_SYSTEM_SLEEP a6
+#define X_SYSTEM_WAKE a7
+
+/* Consumer Page (0x0C) */
+#define X_AUDIO_MUTE a8
+#define X_AUDIO_VOL_UP a9
+#define X_AUDIO_VOL_DOWN aa
+#define X_MEDIA_NEXT_TRACK ab
+#define X_MEDIA_PREV_TRACK ac
+#define X_MEDIA_STOP ad
+#define X_MEDIA_PLAY_PAUSE ae
+#define X_MEDIA_SELECT af
+#define X_MEDIA_EJECT b0
+#define X_MAIL b1
+#define X_CALCULATOR b2
+#define X_MY_COMPUTER b3
+#define X_WWW_SEARCH b4
+#define X_WWW_HOME b5
+#define X_WWW_BACK b6
+#define X_WWW_FORWARD b7
+#define X_WWW_STOP b8
+#define X_WWW_REFRESH b9
+#define X_WWW_FAVORITES ba
#define X_MEDIA_FAST_FORWARD bb
-#define X_MEDIA_REWIND bc
-#endif
+#define X_MEDIA_REWIND bc
+#define X_BRIGHTNESS_UP bd
+#define X_BRIGHTNESS_DOWN be
+
+// Send string macros
+#define STRINGIZE(z) #z
+#define ADD_SLASH_X(y) STRINGIZE(\x##y)
+#define SYMBOL_STR(x) ADD_SLASH_X(x)
+
+#define SS_TAP_CODE 1
+#define SS_DOWN_CODE 2
+#define SS_UP_CODE 3
+
+#define SS_TAP(keycode) "\1" SYMBOL_STR(keycode)
+#define SS_DOWN(keycode) "\2" SYMBOL_STR(keycode)
+#define SS_UP(keycode) "\3" SYMBOL_STR(keycode)
+
+// `string` arguments must not be parenthesized
+#define SS_LCTL(string) SS_DOWN(X_LCTL) string SS_UP(X_LCTL)
+#define SS_LSFT(string) SS_DOWN(X_LSFT) string SS_UP(X_LSFT)
+#define SS_LALT(string) SS_DOWN(X_LALT) string SS_UP(X_LALT)
+#define SS_LGUI(string) SS_DOWN(X_LGUI) string SS_UP(X_LGUI)
+#define SS_LCMD(string) SS_LGUI(string)
+#define SS_LWIN(string) SS_LGUI(string)
+
+#define SS_RCTL(string) SS_DOWN(X_RCTL) string SS_UP(X_RCTL)
+#define SS_RSFT(string) SS_DOWN(X_RSFT) string SS_UP(X_RSFT)
+#define SS_RALT(string) SS_DOWN(X_RALT) string SS_UP(X_RALT)
+#define SS_RGUI(string) SS_DOWN(X_RGUI) string SS_UP(X_RGUI)
+#define SS_ALGR(string) SS_RALT(string)
+#define SS_RCMD(string) SS_RGUI(string)
+#define SS_RWIN(string) SS_RGUI(string)
+
+// DEPRECATED
+#define SS_LCTRL(string) SS_LCTL(string)
diff --git a/quantum/split_common/matrix.c b/quantum/split_common/matrix.c
index 7176d0cc4f..ed1ff5acf3 100644
--- a/quantum/split_common/matrix.c
+++ b/quantum/split_common/matrix.c
@@ -14,10 +14,6 @@ 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/>.
*/
-
-/*
- * scan matrix
- */
#include <stdint.h>
#include <stdbool.h>
#include "wait.h"
@@ -33,23 +29,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
# include "encoder.h"
#endif
-#if (MATRIX_COLS <= 8)
-# define print_matrix_header() print("\nr/c 01234567\n")
-# define print_matrix_row(row) print_bin_reverse8(matrix_get_row(row))
-# define matrix_bitpop(i) bitpop(matrix[i])
-# define ROW_SHIFTER ((uint8_t)1)
-#elif (MATRIX_COLS <= 16)
-# define print_matrix_header() print("\nr/c 0123456789ABCDEF\n")
-# define print_matrix_row(row) print_bin_reverse16(matrix_get_row(row))
-# define matrix_bitpop(i) bitpop16(matrix[i])
-# define ROW_SHIFTER ((uint16_t)1)
-#elif (MATRIX_COLS <= 32)
-# define print_matrix_header() print("\nr/c 0123456789ABCDEF0123456789ABCDEF\n")
-# define print_matrix_row(row) print_bin_reverse32(matrix_get_row(row))
-# define matrix_bitpop(i) bitpop32(matrix[i])
-# define ROW_SHIFTER ((uint32_t)1)
-#endif
-
#define ERROR_DISCONNECT_COUNT 5
#define ROWS_PER_HAND (MATRIX_ROWS / 2)
@@ -62,58 +41,15 @@ static pin_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS;
#endif
/* matrix state(1:on, 0:off) */
-static matrix_row_t matrix[MATRIX_ROWS];
-static matrix_row_t raw_matrix[ROWS_PER_HAND];
+extern matrix_row_t raw_matrix[MATRIX_ROWS]; // raw values
+extern matrix_row_t matrix[MATRIX_ROWS]; // debounced values
// row offsets for each hand
uint8_t thisHand, thatHand;
// user-defined overridable functions
-
-__attribute__((weak)) void matrix_init_kb(void) { matrix_init_user(); }
-
-__attribute__((weak)) void matrix_scan_kb(void) { matrix_scan_user(); }
-
-__attribute__((weak)) void matrix_init_user(void) {}
-
-__attribute__((weak)) void matrix_scan_user(void) {}
-
__attribute__((weak)) void matrix_slave_scan_user(void) {}
-// helper functions
-
-inline uint8_t matrix_rows(void) { return MATRIX_ROWS; }
-
-inline uint8_t matrix_cols(void) { return MATRIX_COLS; }
-
-bool matrix_is_modified(void) {
- if (debounce_active()) return false;
- return true;
-}
-
-inline bool matrix_is_on(uint8_t row, uint8_t col) { return (matrix[row] & ((matrix_row_t)1 << col)); }
-
-inline matrix_row_t matrix_get_row(uint8_t row) { return matrix[row]; }
-
-void matrix_print(void) {
- print_matrix_header();
-
- for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
- phex(row);
- print(": ");
- print_matrix_row(row);
- print("\n");
- }
-}
-
-uint8_t matrix_key_count(void) {
- uint8_t count = 0;
- for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
- count += matrix_bitpop(i);
- }
- return count;
-}
-
// matrix code
#ifdef DIRECT_PINS
@@ -136,7 +72,7 @@ static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row)
for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) {
pin_t pin = direct_pins[current_row][col_index];
if (pin != NO_PIN) {
- current_matrix[current_row] |= readPin(pin) ? 0 : (ROW_SHIFTER << col_index);
+ current_matrix[current_row] |= readPin(pin) ? 0 : (MATRIX_ROW_SHIFTER << col_index);
}
}
@@ -179,7 +115,7 @@ static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row)
// For each col...
for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) {
// Populate the matrix row with the state of the col pin
- current_matrix[current_row] |= readPin(col_pins[col_index]) ? 0 : (ROW_SHIFTER << col_index);
+ current_matrix[current_row] |= readPin(col_pins[col_index]) ? 0 : (MATRIX_ROW_SHIFTER << col_index);
}
// Unselect row
@@ -225,10 +161,10 @@ static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col)
// Check row pin state
if (readPin(row_pins[row_index])) {
// Pin HI, clear col bit
- current_matrix[row_index] &= ~(ROW_SHIFTER << current_col);
+ current_matrix[row_index] &= ~(MATRIX_ROW_SHIFTER << current_col);
} else {
// Pin LO, set col bit
- current_matrix[row_index] |= (ROW_SHIFTER << current_col);
+ current_matrix[row_index] |= (MATRIX_ROW_SHIFTER << current_col);
}
// Determine if the matrix changed state
@@ -280,7 +216,8 @@ void matrix_init(void) {
// initialize matrix state: all keys off
for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
- matrix[i] = 0;
+ raw_matrix[i] = 0;
+ matrix[i] = 0;
}
debounce_init(ROWS_PER_HAND);
@@ -288,29 +225,7 @@ void matrix_init(void) {
matrix_init_quantum();
}
-uint8_t _matrix_scan(void) {
- bool changed = false;
-
-#if defined(DIRECT_PINS) || (DIODE_DIRECTION == COL2ROW)
- // Set row, read cols
- for (uint8_t current_row = 0; current_row < ROWS_PER_HAND; current_row++) {
- changed |= read_cols_on_row(raw_matrix, current_row);
- }
-#elif (DIODE_DIRECTION == ROW2COL)
- // Set col, read rows
- for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) {
- changed |= read_rows_on_col(raw_matrix, current_col);
- }
-#endif
-
- debounce(raw_matrix, matrix + thisHand, ROWS_PER_HAND, changed);
-
- return (uint8_t)changed;
-}
-
-uint8_t matrix_scan(void) {
- uint8_t ret = _matrix_scan();
-
+void matrix_post_scan(void) {
if (is_keyboard_master()) {
static uint8_t error_count;
@@ -335,6 +250,25 @@ uint8_t matrix_scan(void) {
#endif
matrix_slave_scan_user();
}
+}
+
+uint8_t matrix_scan(void) {
+ bool changed = false;
+
+#if defined(DIRECT_PINS) || (DIODE_DIRECTION == COL2ROW)
+ // Set row, read cols
+ for (uint8_t current_row = 0; current_row < ROWS_PER_HAND; current_row++) {
+ changed |= read_cols_on_row(raw_matrix, current_row);
+ }
+#elif (DIODE_DIRECTION == ROW2COL)
+ // Set col, read rows
+ for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) {
+ changed |= read_rows_on_col(raw_matrix, current_col);
+ }
+#endif
+
+ debounce(raw_matrix, matrix + thisHand, ROWS_PER_HAND, changed);
- return ret;
+ matrix_post_scan();
+ return (uint8_t)changed;
}
diff --git a/quantum/split_common/matrix.h b/quantum/split_common/matrix.h
deleted file mode 100644
index c2bdd3098c..0000000000
--- a/quantum/split_common/matrix.h
+++ /dev/null
@@ -1,3 +0,0 @@
-#pragma once
-
-#include <common/matrix.h>
diff --git a/quantum/split_common/post_config.h b/quantum/split_common/post_config.h
index 5c0b414fb3..4ae1d52732 100644
--- a/quantum/split_common/post_config.h
+++ b/quantum/split_common/post_config.h
@@ -1,4 +1,4 @@
-#if defined(USE_I2C) || defined(EH)
+#if defined(USE_I2C)
// When using I2C, using rgblight implicitly involves split support.
# if defined(RGBLIGHT_ENABLE) && !defined(RGBLIGHT_SPLIT)
# define RGBLIGHT_SPLIT
diff --git a/quantum/split_common/split_util.c b/quantum/split_common/split_util.c
index 5c548de059..076f186649 100644
--- a/quantum/split_common/split_util.c
+++ b/quantum/split_common/split_util.c
@@ -33,9 +33,11 @@ bool waitForUsb(void) {
wait_ms(100);
}
-#if defined(__AVR__)
// Avoid NO_USB_STARTUP_CHECK - Disable USB as the previous checks seem to enable it somehow
+#if defined(__AVR__)
(USBCON &= ~(_BV(USBE) | _BV(OTGPADE)));
+#else
+ usbStop(&USBD1);
#endif
return false;
@@ -76,7 +78,7 @@ __attribute__((weak)) bool is_keyboard_master(void) {
}
static void keyboard_master_setup(void) {
-#if defined(USE_I2C) || defined(EH)
+#if defined(USE_I2C)
# ifdef SSD1306OLED
matrix_master_OLED_init();
# endif
diff --git a/quantum/split_common/transport.c b/quantum/split_common/transport.c
index 3c783dc568..ab421adc4a 100644
--- a/quantum/split_common/transport.c
+++ b/quantum/split_common/transport.c
@@ -21,7 +21,7 @@ static pin_t encoders_pad[] = ENCODERS_PAD_A;
# define NUMBER_OF_ENCODERS (sizeof(encoders_pad) / sizeof(pin_t))
#endif
-#if defined(USE_I2C) || defined(EH)
+#if defined(USE_I2C)
# include "i2c_master.h"
# include "i2c_slave.h"
diff --git a/quantum/stm32/proton_c.mk b/quantum/stm32/proton_c.mk
index ff28a4cb5d..b25b555045 100644
--- a/quantum/stm32/proton_c.mk
+++ b/quantum/stm32/proton_c.mk
@@ -5,9 +5,7 @@ AUDIO_ENABLE = yes
WS2812_DRIVER = bitbang
# Force task driven PWM until ARM can provide automatic configuration
-ifneq ($(strip $(BACKLIGHT_ENABLE)), no)
- BACKLIGHT_ENABLE = software
-endif
+BACKLIGHT_DRIVER = software
# The rest of these settings shouldn't change
diff --git a/quantum/template/base/keymaps/default/keymap.c b/quantum/template/base/keymaps/default/keymap.c
index 3a68f5487c..af35ccec15 100644
--- a/quantum/template/base/keymaps/default/keymap.c
+++ b/quantum/template/base/keymaps/default/keymap.c
@@ -52,7 +52,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
case QMKURL:
if (record->event.pressed) {
// when keycode QMKURL is pressed
- SEND_STRING("https://qmk.fm/" SS_TAP(X_ENTER));
+ SEND_STRING("https://qmk.fm/\n");
} else {
// when keycode QMKURL is released
}
diff --git a/quantum/via.c b/quantum/via.c
new file mode 100644
index 0000000000..64b05324a1
--- /dev/null
+++ b/quantum/via.c
@@ -0,0 +1,400 @@
+/* Copyright 2019 Jason Williams (Wilba)
+ *
+ * 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 RAW_ENABLE
+# error "RAW_ENABLE is not enabled"
+#endif
+
+#ifndef DYNAMIC_KEYMAP_ENABLE
+# error "DYNAMIC_KEYMAP_ENABLE is not enabled"
+#endif
+
+#include "quantum.h"
+
+#include "via.h"
+#include "raw_hid.h"
+#include "dynamic_keymap.h"
+#include "tmk_core/common/eeprom.h"
+#include "version.h" // for QMK_BUILDDATE used in EEPROM magic
+
+// Can be called in an overriding via_init_kb() to test if keyboard level code usage of
+// EEPROM is invalid and use/save defaults.
+bool via_eeprom_is_valid(void)
+{
+ char *p = QMK_BUILDDATE; // e.g. "2019-11-05-11:29:54"
+ uint8_t magic0 = ( ( p[2] & 0x0F ) << 4 ) | ( p[3] & 0x0F );
+ uint8_t magic1 = ( ( p[5] & 0x0F ) << 4 ) | ( p[6] & 0x0F );
+ uint8_t magic2 = ( ( p[8] & 0x0F ) << 4 ) | ( p[9] & 0x0F );
+
+ return (eeprom_read_byte( (void*)VIA_EEPROM_MAGIC_ADDR+0 ) == magic0 &&
+ eeprom_read_byte( (void*)VIA_EEPROM_MAGIC_ADDR+1 ) == magic1 &&
+ eeprom_read_byte( (void*)VIA_EEPROM_MAGIC_ADDR+2 ) == magic2 );
+}
+
+// Sets VIA/keyboard level usage of EEPROM to valid/invalid
+// Keyboard level code (eg. via_init_kb()) should not call this
+void via_eeprom_set_valid(bool valid)
+{
+ char *p = QMK_BUILDDATE; // e.g. "2019-11-05-11:29:54"
+ uint8_t magic0 = ( ( p[2] & 0x0F ) << 4 ) | ( p[3] & 0x0F );
+ uint8_t magic1 = ( ( p[5] & 0x0F ) << 4 ) | ( p[6] & 0x0F );
+ uint8_t magic2 = ( ( p[8] & 0x0F ) << 4 ) | ( p[9] & 0x0F );
+
+ eeprom_update_byte( (void*)VIA_EEPROM_MAGIC_ADDR+0, valid ? magic0 : 0xFF);
+ eeprom_update_byte( (void*)VIA_EEPROM_MAGIC_ADDR+1, valid ? magic1 : 0xFF);
+ eeprom_update_byte( (void*)VIA_EEPROM_MAGIC_ADDR+2, valid ? magic2 : 0xFF);
+}
+
+// Flag QMK and VIA/keyboard level EEPROM as invalid.
+// Used in bootmagic_lite() and VIA command handler.
+// Keyboard level code should not need to call this.
+void via_eeprom_reset(void)
+{
+ // Set the VIA specific EEPROM state as invalid.
+ via_eeprom_set_valid(false);
+ // Set the TMK/QMK EEPROM state as invalid.
+ eeconfig_disable();
+}
+
+// Override bootmagic_lite() so it can flag EEPROM as invalid
+// as well as jump to bootloader, thus performing a "factory reset"
+// of dynamic keymaps and optionally backlight/other settings.
+void bootmagic_lite(void)
+{
+ // The lite version of TMK's bootmagic based on Wilba.
+ // 100% less potential for accidentally making the
+ // keyboard do stupid things.
+
+ // We need multiple scans because debouncing can't be turned off.
+ matrix_scan();
+#if defined(DEBOUNCE) && DEBOUNCE > 0
+ wait_ms(DEBOUNCE * 2);
+#else
+ wait_ms(30);
+#endif
+ matrix_scan();
+
+ // If the Esc and space bar are held down on power up,
+ // reset the EEPROM valid state and jump to bootloader.
+ // Assumes Esc is at [0,0].
+ // This isn't very generalized, but we need something that doesn't
+ // rely on user's keymaps in firmware or EEPROM.
+ if (matrix_get_row(BOOTMAGIC_LITE_ROW) & (1 << BOOTMAGIC_LITE_COLUMN)) {
+ // This is the only difference from the default implementation.
+ via_eeprom_reset();
+ // Jump to bootloader.
+ bootloader_jump();
+ }
+}
+
+// Override this at the keyboard code level to check
+// VIA's EEPROM valid state and reset to defaults as needed.
+// Used by keyboards that store their own state in EEPROM,
+// for backlight, rotary encoders, etc.
+// The override should not set via_eeprom_set_valid(true) as
+// the caller also needs to check the valid state.
+__attribute__((weak)) void via_init_kb(void) {
+}
+
+// Called by QMK core to initialize dynamic keymaps etc.
+void via_init(void)
+{
+ // Let keyboard level test EEPROM valid state,
+ // but not set it valid, it is done here.
+ via_init_kb();
+
+ // If the EEPROM has the magic, the data is good.
+ // OK to load from EEPROM.
+ if (via_eeprom_is_valid()) {
+ } else {
+ // This resets the layout options
+ via_set_layout_options(0);
+ // This resets the keymaps in EEPROM to what is in flash.
+ dynamic_keymap_reset();
+ // This resets the macros in EEPROM to nothing.
+ dynamic_keymap_macro_reset();
+ // Save the magic number last, in case saving was interrupted
+ via_eeprom_set_valid(true);
+ }
+}
+
+// This is generalized so the layout options EEPROM usage can be
+// variable, between 1 and 4 bytes.
+uint32_t via_get_layout_options(void)
+{
+ uint32_t value = 0;
+ // Start at the most significant byte
+ void * source = (void *)(VIA_EEPROM_LAYOUT_OPTIONS_ADDR);
+ for ( uint8_t i = 0; i < VIA_EEPROM_LAYOUT_OPTIONS_SIZE; i++ ) {
+ value = value << 8;
+ value |= eeprom_read_byte(source);
+ source++;
+ }
+ return value;
+}
+
+void via_set_layout_options(uint32_t value)
+{
+ // Start at the least significant byte
+ void * target = (void *)(VIA_EEPROM_LAYOUT_OPTIONS_ADDR+VIA_EEPROM_LAYOUT_OPTIONS_SIZE-1);
+ for ( uint8_t i = 0; i < VIA_EEPROM_LAYOUT_OPTIONS_SIZE; i++ ) {
+ eeprom_update_byte(target, value & 0xFF );
+ value = value >> 8;
+ target--;
+ }
+}
+
+// Called by QMK core to process VIA-specific keycodes.
+bool process_record_via(uint16_t keycode, keyrecord_t *record)
+{
+ // Handle macros
+ if (record->event.pressed) {
+ if ( keycode >= MACRO00 && keycode <= MACRO15 )
+ {
+ uint8_t id = keycode - MACRO00;
+ dynamic_keymap_macro_send(id);
+ return false;
+ }
+ }
+
+ // TODO: ideally this would be generalized and refactored into
+ // QMK core as advanced keycodes, until then, the simple case
+ // can be available here to keyboards using VIA
+ switch(keycode) {
+ case FN_MO13:
+ if (record->event.pressed) {
+ layer_on(1);
+ update_tri_layer(1, 2, 3);
+ } else {
+ layer_off(1);
+ update_tri_layer(1, 2, 3);
+ }
+ return false;
+ break;
+ case FN_MO23:
+ if (record->event.pressed) {
+ layer_on(2);
+ update_tri_layer(1, 2, 3);
+ } else {
+ layer_off(2);
+ update_tri_layer(1, 2, 3);
+ }
+ return false;
+ break;
+ }
+ return true;
+}
+
+// Keyboard level code can override this to handle custom messages from VIA.
+// See raw_hid_receive() implementation.
+// DO NOT call raw_hid_send() in the overide function.
+__attribute__((weak)) void raw_hid_receive_kb(uint8_t *data, uint8_t length) {
+ uint8_t *command_id = &(data[0]);
+ *command_id = id_unhandled;
+}
+
+// VIA handles received HID messages first, and will route to
+// raw_hid_receive_kb() for command IDs that are not handled here.
+// This gives the keyboard code level the ability to handle the command
+// specifically.
+//
+// raw_hid_send() is called at the end, with the same buffer, which was
+// possibly modified with returned values.
+void raw_hid_receive( uint8_t *data, uint8_t length )
+{
+ uint8_t *command_id = &(data[0]);
+ uint8_t *command_data = &(data[1]);
+ switch ( *command_id )
+ {
+ case id_get_protocol_version:
+ {
+ command_data[0] = VIA_PROTOCOL_VERSION >> 8;
+ command_data[1] = VIA_PROTOCOL_VERSION & 0xFF;
+ break;
+ }
+ case id_get_keyboard_value:
+ {
+ switch ( command_data[0] )
+ {
+ case id_uptime:
+ {
+ uint32_t value = timer_read32();
+ command_data[1] = (value >> 24 ) & 0xFF;
+ command_data[2] = (value >> 16 ) & 0xFF;
+ command_data[3] = (value >> 8 ) & 0xFF;
+ command_data[4] = value & 0xFF;
+ break;
+ }
+ case id_layout_options:
+ {
+ uint32_t value = via_get_layout_options();
+ command_data[1] = (value >> 24 ) & 0xFF;
+ command_data[2] = (value >> 16 ) & 0xFF;
+ command_data[3] = (value >> 8 ) & 0xFF;
+ command_data[4] = value & 0xFF;
+ break;
+ }
+ case id_switch_matrix_state:
+ {
+#if ( (MATRIX_COLS/8+1)*MATRIX_ROWS <= 28 )
+ uint8_t i = 1;
+ for ( uint8_t row=0; row<MATRIX_ROWS; row++ ) {
+ matrix_row_t value = matrix_get_row(row);
+#if (MATRIX_COLS > 24)
+ command_data[i++] = (value >> 24 ) & 0xFF;
+#endif
+#if (MATRIX_COLS > 16)
+ command_data[i++] = (value >> 16 ) & 0xFF;
+#endif
+#if (MATRIX_COLS > 8)
+ command_data[i++] = (value >> 8 ) & 0xFF;
+#endif
+ command_data[i++] = value & 0xFF;
+ }
+#endif
+ break;
+ }
+ default:
+ {
+ raw_hid_receive_kb(data,length);
+ break;
+ }
+ }
+ break;
+ }
+ case id_set_keyboard_value:
+ {
+ switch ( command_data[0] )
+ {
+ case id_layout_options:
+ {
+ uint32_t value = ( (uint32_t)command_data[1] << 24 ) |
+ ( (uint32_t)command_data[2] << 16 ) |
+ ( (uint32_t)command_data[3] << 8 ) |
+ (uint32_t)command_data[4];
+ via_set_layout_options(value);
+ break;
+ }
+ default:
+ {
+ raw_hid_receive_kb(data,length);
+ break;
+ }
+ }
+ break;
+ }
+ case id_dynamic_keymap_get_keycode:
+ {
+ uint16_t keycode = dynamic_keymap_get_keycode( command_data[0], command_data[1], command_data[2] );
+ command_data[3] = keycode >> 8;
+ command_data[4] = keycode & 0xFF;
+ break;
+ }
+ case id_dynamic_keymap_set_keycode:
+ {
+ dynamic_keymap_set_keycode( command_data[0], command_data[1], command_data[2], ( command_data[3] << 8 ) | command_data[4] );
+ break;
+ }
+ case id_dynamic_keymap_reset:
+ {
+ dynamic_keymap_reset();
+ break;
+ }
+ case id_backlight_config_set_value:
+ case id_backlight_config_get_value:
+ case id_backlight_config_save:
+ {
+ raw_hid_receive_kb(data, length);
+ break;
+ }
+ case id_dynamic_keymap_macro_get_count:
+ {
+ command_data[0] = dynamic_keymap_macro_get_count();
+ break;
+ }
+ case id_dynamic_keymap_macro_get_buffer_size:
+ {
+ uint16_t size = dynamic_keymap_macro_get_buffer_size();
+ command_data[0] = size >> 8;
+ command_data[1] = size & 0xFF;
+ break;
+ }
+ case id_dynamic_keymap_macro_get_buffer:
+ {
+ uint16_t offset = ( command_data[0] << 8 ) | command_data[1];
+ uint16_t size = command_data[2]; // size <= 28
+ dynamic_keymap_macro_get_buffer( offset, size, &command_data[3] );
+ break;
+ }
+ case id_dynamic_keymap_macro_set_buffer:
+ {
+ uint16_t offset = ( command_data[0] << 8 ) | command_data[1];
+ uint16_t size = command_data[2]; // size <= 28
+ dynamic_keymap_macro_set_buffer( offset, size, &command_data[3] );
+ break;
+ }
+ case id_dynamic_keymap_macro_reset:
+ {
+ dynamic_keymap_macro_reset();
+ break;
+ }
+ case id_dynamic_keymap_get_layer_count:
+ {
+ command_data[0] = dynamic_keymap_get_layer_count();
+ break;
+ }
+ case id_dynamic_keymap_get_buffer:
+ {
+ uint16_t offset = ( command_data[0] << 8 ) | command_data[1];
+ uint16_t size = command_data[2]; // size <= 28
+ dynamic_keymap_get_buffer( offset, size, &command_data[3] );
+ break;
+ }
+ case id_dynamic_keymap_set_buffer:
+ {
+ uint16_t offset = ( command_data[0] << 8 ) | command_data[1];
+ uint16_t size = command_data[2]; // size <= 28
+ dynamic_keymap_set_buffer( offset, size, &command_data[3] );
+ break;
+ }
+ case id_eeprom_reset:
+ {
+ via_eeprom_reset();
+ break;
+ }
+ case id_bootloader_jump:
+ {
+ // Need to send data back before the jump
+ // Informs host that the command is handled
+ raw_hid_send( data, length );
+ // Give host time to read it
+ wait_ms(100);
+ bootloader_jump();
+ break;
+ }
+ default:
+ {
+ // The command ID is not known
+ // Return the unhandled state
+ *command_id = id_unhandled;
+ break;
+ }
+ }
+
+ // Return the same buffer, optionally with values changed
+ // (i.e. returning state to the host, or the unhandled state).
+ raw_hid_send( data, length );
+}
diff --git a/quantum/via.h b/quantum/via.h
new file mode 100644
index 0000000000..f9a8017b24
--- /dev/null
+++ b/quantum/via.h
@@ -0,0 +1,151 @@
+/* Copyright 2019 Jason Williams (Wilba)
+ *
+ * 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/>.
+ */
+
+#pragma once
+
+#include <tmk_core/common/eeconfig.h> // for EECONFIG_SIZE
+
+// Keyboard level code can change where VIA stores the magic.
+// The magic is the build date YYMMDD encoded as BCD in 3 bytes,
+// thus installing firmware built on a different date to the one
+// already installed can be detected and the EEPROM data is reset.
+// The only reason this is important is in case EEPROM usage changes
+// and the EEPROM was not explicitly reset by bootmagic lite.
+#ifndef VIA_EEPROM_MAGIC_ADDR
+# define VIA_EEPROM_MAGIC_ADDR (EECONFIG_SIZE)
+#endif
+
+#define VIA_EEPROM_LAYOUT_OPTIONS_ADDR (VIA_EEPROM_MAGIC_ADDR+3)
+
+// Changing the layout options size after release will invalidate EEPROM,
+// but this is something that should be set correctly on initial implementation.
+// 1 byte is enough for most uses (i.e. 8 binary states, or 6 binary + 1 ternary/quaternary )
+#ifndef VIA_EEPROM_LAYOUT_OPTIONS_SIZE
+# define VIA_EEPROM_LAYOUT_OPTIONS_SIZE 1
+#endif
+
+// The end of the EEPROM memory used by VIA
+// By default, dynamic keymaps will start at this if there is no
+// custom config
+#define VIA_EEPROM_CUSTOM_CONFIG_ADDR (VIA_EEPROM_LAYOUT_OPTIONS_ADDR+VIA_EEPROM_LAYOUT_OPTIONS_SIZE)
+
+#ifndef VIA_EEPROM_CUSTOM_CONFIG_SIZE
+# define VIA_EEPROM_CUSTOM_CONFIG_SIZE 0
+#endif
+
+// This is changed only when the command IDs change,
+// so VIA Configurator can detect compatible firmware.
+#define VIA_PROTOCOL_VERSION 0x0009
+
+enum via_command_id
+{
+ id_get_protocol_version = 0x01, // always 0x01
+ id_get_keyboard_value,
+ id_set_keyboard_value,
+ id_dynamic_keymap_get_keycode,
+ id_dynamic_keymap_set_keycode,
+ id_dynamic_keymap_reset,
+ id_backlight_config_set_value,
+ id_backlight_config_get_value,
+ id_backlight_config_save,
+ id_eeprom_reset,
+ id_bootloader_jump,
+ id_dynamic_keymap_macro_get_count,
+ id_dynamic_keymap_macro_get_buffer_size,
+ id_dynamic_keymap_macro_get_buffer,
+ id_dynamic_keymap_macro_set_buffer,
+ id_dynamic_keymap_macro_reset,
+ id_dynamic_keymap_get_layer_count,
+ id_dynamic_keymap_get_buffer,
+ id_dynamic_keymap_set_buffer,
+ id_unhandled = 0xFF,
+};
+
+enum via_keyboard_value_id
+{
+ id_uptime = 0x01,
+ id_layout_options,
+ id_switch_matrix_state
+};
+
+// Can't use SAFE_RANGE here, it might change if someone adds
+// new values to enum quantum_keycodes.
+// Need to keep checking 0x5F10 is still in the safe range.
+// TODO: merge this into quantum_keycodes
+// Backlight keycodes are in range 0x5F00-0x5F0F
+enum via_keycodes {
+ FN_MO13 = 0x5F10,
+ FN_MO23,
+ MACRO00,
+ MACRO01,
+ MACRO02,
+ MACRO03,
+ MACRO04,
+ MACRO05,
+ MACRO06,
+ MACRO07,
+ MACRO08,
+ MACRO09,
+ MACRO10,
+ MACRO11,
+ MACRO12,
+ MACRO13,
+ MACRO14,
+ MACRO15,
+};
+
+enum user_keycodes {
+ USER00 = 0x5F80,
+ USER01,
+ USER02,
+ USER03,
+ USER04,
+ USER05,
+ USER06,
+ USER07,
+ USER08,
+ USER09,
+ USER10,
+ USER11,
+ USER12,
+ USER13,
+ USER14,
+ USER15,
+};
+
+// Can be called in an overriding via_init_kb() to test if keyboard level code usage of
+// EEPROM is invalid and use/save defaults.
+bool via_eeprom_is_valid(void);
+
+// Sets VIA/keyboard level usage of EEPROM to valid/invalid
+// Keyboard level code (eg. via_init_kb()) should not call this
+void via_eeprom_set_valid(bool valid);
+
+// Flag QMK and VIA/keyboard level EEPROM as invalid.
+// Used in bootmagic_lite() and VIA command handler.
+// Keyboard level code should not need to call this.
+void via_eeprom_reset(void);
+
+// Called by QMK core to initialize dynamic keymaps etc.
+void via_init(void);
+
+// Used by VIA to store and retrieve the layout options.
+uint32_t via_get_layout_options(void);
+void via_set_layout_options(uint32_t value);
+
+// Called by QMK core to process VIA-specific keycodes.
+bool process_record_via(uint16_t keycode, keyrecord_t *record);
+