Merge remote-tracking branch 'qmk/master' into merge-2025-06-21

This commit is contained in:
Ilya Zhuravlev 2025-06-21 16:00:42 -06:00
commit 7b247bc800
3559 changed files with 29234 additions and 11558 deletions

View file

@ -282,6 +282,9 @@ void process_record(keyrecord_t *record) {
if (IS_NOEVENT(record->event)) {
return;
}
#ifdef FLOW_TAP_TERM
flow_tap_update_last_event(record);
#endif // FLOW_TAP_TERM
if (!process_record_quantum(record)) {
#ifndef NO_ACTION_ONESHOT
@ -1180,6 +1183,23 @@ bool is_tap_action(action_t action) {
return false;
}
uint16_t get_tap_keycode(uint16_t keycode) {
switch (keycode) {
case QK_MOD_TAP ... QK_MOD_TAP_MAX:
return QK_MOD_TAP_GET_TAP_KEYCODE(keycode);
case QK_LAYER_TAP ... QK_LAYER_TAP_MAX:
return QK_LAYER_TAP_GET_TAP_KEYCODE(keycode);
case QK_SWAP_HANDS ... QK_SWAP_HANDS_MAX:
// IS_SWAP_HANDS_KEYCODE() tests for the special action keycodes
// like SH_TOGG, SH_TT, ..., which overlap the SH_T(kc) range.
if (!IS_SWAP_HANDS_KEYCODE(keycode)) {
return QK_SWAP_HANDS_GET_TAP_KEYCODE(keycode);
}
break;
}
return keycode;
}
/** \brief Debug print (FIXME: Needs better description)
*
* FIXME: Needs documentation.

View file

@ -128,6 +128,12 @@ void layer_switch(uint8_t new_layer);
bool is_tap_record(keyrecord_t *record);
bool is_tap_action(action_t action);
/**
* Given an MT or LT keycode, returns the tap keycode. Otherwise returns the
* original keycode unchanged.
*/
uint16_t get_tap_keycode(uint16_t keycode);
#ifndef NO_ACTION_TAPPING
void process_record_tap_hint(keyrecord_t *record);
#endif

View file

@ -31,11 +31,20 @@ __attribute__((weak)) layer_state_t default_layer_state_set_kb(layer_state_t sta
return default_layer_state_set_user(state);
}
/** \brief Default Layer State Set At Module Level
*
* Run module code on default layer state change
*/
__attribute__((weak)) layer_state_t default_layer_state_set_modules(layer_state_t state) {
return state;
}
/** \brief Default Layer State Set
*
* Static function to set the default layer state, prints debug info and clears keys
*/
static void default_layer_state_set(layer_state_t state) {
state = default_layer_state_set_modules(state);
state = default_layer_state_set_kb(state);
ac_dprintf("default_layer_state: ");
default_layer_debug();
@ -111,11 +120,21 @@ __attribute__((weak)) layer_state_t layer_state_set_kb(layer_state_t state) {
return layer_state_set_user(state);
}
/** \brief Layer state set modules
*
* Runs module code on layer state change
*/
__attribute__((weak)) layer_state_t layer_state_set_modules(layer_state_t state) {
return state;
}
/** \brief Layer state set
*
* Sets the layer to match the specified state (a bitmask)
*/
void layer_state_set(layer_state_t state) {
state = layer_state_set_modules(state);
state = layer_state_set_kb(state);
ac_dprintf("layer_state: ");
layer_debug();

View file

@ -78,6 +78,7 @@ extern layer_state_t default_layer_state;
void default_layer_debug(void);
void default_layer_set(layer_state_t state);
__attribute__((weak)) layer_state_t default_layer_state_set_modules(layer_state_t state);
__attribute__((weak)) layer_state_t default_layer_state_set_kb(layer_state_t state);
__attribute__((weak)) layer_state_t default_layer_state_set_user(layer_state_t state);
@ -114,6 +115,7 @@ void layer_and(layer_state_t state);
void layer_xor(layer_state_t state);
layer_state_t layer_state_set_user(layer_state_t state);
layer_state_t layer_state_set_kb(layer_state_t state);
layer_state_t layer_state_set_modules(layer_state_t state);
/**
* @brief Applies the tri layer to global layer state. Not be used in layer_state_set_(kb|user) functions.
@ -149,6 +151,7 @@ layer_state_t update_tri_layer_state(layer_state_t state, uint8_t layer1, uint8_
# define layer_or(state) (void)state
# define layer_and(state) (void)state
# define layer_xor(state) (void)state
# define layer_state_set_modules(state) (void)state
# define layer_state_set_kb(state) (void)state
# define layer_state_set_user(state) (void)state
# define update_tri_layer(layer1, layer2, layer3)

View file

@ -4,7 +4,9 @@
#include "action.h"
#include "action_layer.h"
#include "action_tapping.h"
#include "action_util.h"
#include "keycode.h"
#include "quantum_keycodes.h"
#include "timer.h"
#ifndef NO_ACTION_TAPPING
@ -49,9 +51,7 @@ __attribute__((weak)) bool get_permissive_hold(uint16_t keycode, keyrecord_t *re
}
# endif
# if defined(CHORDAL_HOLD)
extern const char chordal_hold_layout[MATRIX_ROWS][MATRIX_COLS] PROGMEM;
# if defined(CHORDAL_HOLD) || defined(FLOW_TAP_TERM)
# define REGISTERED_TAPS_SIZE 8
// Array of tap-hold keys that have been settled as tapped but not yet released.
static keypos_t registered_taps[REGISTERED_TAPS_SIZE] = {};
@ -66,6 +66,14 @@ static void registered_taps_del_index(uint8_t i);
/** Logs the registered_taps array for debugging. */
static void debug_registered_taps(void);
static bool is_mt_or_lt(uint16_t keycode) {
return IS_QK_MOD_TAP(keycode) || IS_QK_LAYER_TAP(keycode);
}
# endif // defined(CHORDAL_HOLD) || defined(FLOW_TAP_TERM)
# if defined(CHORDAL_HOLD)
extern const char chordal_hold_layout[MATRIX_ROWS][MATRIX_COLS] PROGMEM;
/** \brief Finds which queued events should be held according to Chordal Hold.
*
* In a situation with multiple unsettled tap-hold key presses, scan the queue
@ -82,10 +90,6 @@ static void waiting_buffer_chordal_hold_taps_until(keypos_t key);
/** \brief Processes and pops buffered events until the first tap-hold event. */
static void waiting_buffer_process_regular(void);
static bool is_mt_or_lt(uint16_t keycode) {
return IS_QK_MOD_TAP(keycode) || IS_QK_LAYER_TAP(keycode);
}
# endif // CHORDAL_HOLD
# ifdef HOLD_ON_OTHER_KEY_PRESS_PER_KEY
@ -98,6 +102,14 @@ __attribute__((weak)) bool get_hold_on_other_key_press(uint16_t keycode, keyreco
# include "process_auto_shift.h"
# endif
# if defined(FLOW_TAP_TERM)
static uint16_t flow_tap_prev_keycode = KC_NO;
static uint16_t flow_tap_prev_time = 0;
static bool flow_tap_expired = true;
static bool flow_tap_key_if_within_term(keyrecord_t *record, uint16_t prev_time);
# endif // defined(FLOW_TAP_TERM)
static keyrecord_t tapping_key = {};
static keyrecord_t waiting_buffer[WAITING_BUFFER_SIZE] = {};
static uint8_t waiting_buffer_head = 0;
@ -148,6 +160,12 @@ void action_tapping_process(keyrecord_t record) {
}
if (IS_EVENT(record.event)) {
ac_dprintf("\n");
} else {
# ifdef FLOW_TAP_TERM
if (!flow_tap_expired && TIMER_DIFF_16(record.event.time, flow_tap_prev_time) >= INT16_MAX / 2) {
flow_tap_expired = true;
}
# endif // FLOW_TAP_TERM
}
}
@ -205,7 +223,7 @@ void action_tapping_process(keyrecord_t record) {
bool process_tapping(keyrecord_t *keyp) {
const keyevent_t event = keyp->event;
# if defined(CHORDAL_HOLD)
# if defined(CHORDAL_HOLD) || defined(FLOW_TAP_TERM)
if (!event.pressed) {
const int8_t i = registered_tap_find(event.key);
if (i != -1) {
@ -217,7 +235,7 @@ bool process_tapping(keyrecord_t *keyp) {
debug_registered_taps();
}
}
# endif // CHORDAL_HOLD
# endif // defined(CHORDAL_HOLD) || defined(FLOW_TAP_TERM)
// state machine is in the "reset" state, no tapping key is to be
// processed
@ -227,6 +245,13 @@ bool process_tapping(keyrecord_t *keyp) {
} else if (event.pressed && is_tap_record(keyp)) {
// the currently pressed key is a tapping key, therefore transition
// into the "pressed" tapping key state
# if defined(FLOW_TAP_TERM)
if (flow_tap_key_if_within_term(keyp, flow_tap_prev_time)) {
return true;
}
# endif // defined(FLOW_TAP_TERM)
ac_dprintf("Tapping: Start(Press tap key).\n");
tapping_key = *keyp;
process_record_tap_hint(&tapping_key);
@ -263,6 +288,27 @@ bool process_tapping(keyrecord_t *keyp) {
// copy tapping state
keyp->tap = tapping_key.tap;
# if defined(FLOW_TAP_TERM)
// Now that tapping_key has settled as tapped, check whether
// Flow Tap applies to following yet-unsettled keys.
uint16_t prev_time = tapping_key.event.time;
for (; waiting_buffer_tail != waiting_buffer_head; waiting_buffer_tail = (waiting_buffer_tail + 1) % WAITING_BUFFER_SIZE) {
keyrecord_t *record = &waiting_buffer[waiting_buffer_tail];
if (!record->event.pressed) {
break;
}
const int16_t next_time = record->event.time;
if (!is_tap_record(record)) {
process_record(record);
} else if (!flow_tap_key_if_within_term(record, prev_time)) {
break;
}
prev_time = next_time;
}
debug_waiting_buffer();
# endif // defined(FLOW_TAP_TERM)
// enqueue
return false;
}
@ -538,6 +584,13 @@ bool process_tapping(keyrecord_t *keyp) {
return true;
} else if (is_tap_record(keyp)) {
// Sequential tap can be interfered with other tap key.
# if defined(FLOW_TAP_TERM)
if (flow_tap_key_if_within_term(keyp, flow_tap_prev_time)) {
tapping_key = (keyrecord_t){0};
debug_tapping_key();
return true;
}
# endif // defined(FLOW_TAP_TERM)
ac_dprintf("Tapping: Start with interfering other tap.\n");
tapping_key = *keyp;
waiting_buffer_scan_tap();
@ -655,28 +708,7 @@ void waiting_buffer_scan_tap(void) {
}
}
# ifdef CHORDAL_HOLD
__attribute__((weak)) bool get_chordal_hold(uint16_t tap_hold_keycode, keyrecord_t *tap_hold_record, uint16_t other_keycode, keyrecord_t *other_record) {
return get_chordal_hold_default(tap_hold_record, other_record);
}
bool get_chordal_hold_default(keyrecord_t *tap_hold_record, keyrecord_t *other_record) {
if (tap_hold_record->event.type != KEY_EVENT || other_record->event.type != KEY_EVENT) {
return true; // Return true on combos or other non-key events.
}
char tap_hold_hand = chordal_hold_handedness(tap_hold_record->event.key);
if (tap_hold_hand == '*') {
return true;
}
char other_hand = chordal_hold_handedness(other_record->event.key);
return other_hand == '*' || tap_hold_hand != other_hand;
}
__attribute__((weak)) char chordal_hold_handedness(keypos_t key) {
return (char)pgm_read_byte(&chordal_hold_layout[key.row][key.col]);
}
# if defined(CHORDAL_HOLD) || defined(FLOW_TAP_TERM)
static void registered_taps_add(keypos_t key) {
if (num_registered_taps >= REGISTERED_TAPS_SIZE) {
ac_dprintf("TAPS OVERFLOW: CLEAR ALL STATES\n");
@ -714,6 +746,30 @@ static void debug_registered_taps(void) {
ac_dprintf("}\n");
}
# endif // defined(CHORDAL_HOLD) || defined(FLOW_TAP_TERM)
# ifdef CHORDAL_HOLD
__attribute__((weak)) bool get_chordal_hold(uint16_t tap_hold_keycode, keyrecord_t *tap_hold_record, uint16_t other_keycode, keyrecord_t *other_record) {
return get_chordal_hold_default(tap_hold_record, other_record);
}
bool get_chordal_hold_default(keyrecord_t *tap_hold_record, keyrecord_t *other_record) {
if (tap_hold_record->event.type != KEY_EVENT || other_record->event.type != KEY_EVENT) {
return true; // Return true on combos or other non-key events.
}
char tap_hold_hand = chordal_hold_handedness(tap_hold_record->event.key);
if (tap_hold_hand == '*') {
return true;
}
char other_hand = chordal_hold_handedness(other_record->event.key);
return other_hand == '*' || tap_hold_hand != other_hand;
}
__attribute__((weak)) char chordal_hold_handedness(keypos_t key) {
return (char)pgm_read_byte(&chordal_hold_layout[key.row][key.col]);
}
static uint8_t waiting_buffer_find_chordal_hold_tap(void) {
keyrecord_t *prev = &tapping_key;
uint16_t prev_keycode = get_record_keycode(&tapping_key, false);
@ -761,6 +817,100 @@ static void waiting_buffer_process_regular(void) {
}
# endif // CHORDAL_HOLD
# ifdef FLOW_TAP_TERM
void flow_tap_update_last_event(keyrecord_t *record) {
const uint16_t keycode = get_record_keycode(record, false);
// Don't update while a tap-hold key is unsettled.
if (record->tap.count == 0 && (waiting_buffer_tail != waiting_buffer_head || (tapping_key.event.pressed && tapping_key.tap.count == 0))) {
return;
}
// Ignore releases of modifiers and held layer switches.
if (!record->event.pressed) {
switch (keycode) {
case MODIFIER_KEYCODE_RANGE:
case QK_MOMENTARY ... QK_MOMENTARY_MAX:
case QK_LAYER_TAP_TOGGLE ... QK_LAYER_TAP_TOGGLE_MAX:
# ifndef NO_ACTION_ONESHOT // Ignore one-shot keys.
case QK_ONE_SHOT_MOD ... QK_ONE_SHOT_MOD_MAX:
case QK_ONE_SHOT_LAYER ... QK_ONE_SHOT_LAYER_MAX:
# endif // NO_ACTION_ONESHOT
# ifdef TRI_LAYER_ENABLE // Ignore Tri Layer keys.
case QK_TRI_LAYER_LOWER:
case QK_TRI_LAYER_UPPER:
# endif // TRI_LAYER_ENABLE
return;
case QK_MODS ... QK_MODS_MAX:
if (QK_MODS_GET_BASIC_KEYCODE(keycode) == KC_NO) {
return;
}
break;
case QK_MOD_TAP ... QK_MOD_TAP_MAX:
case QK_LAYER_TAP ... QK_LAYER_TAP_MAX:
if (record->tap.count == 0) {
return;
}
break;
}
}
flow_tap_prev_keycode = keycode;
flow_tap_prev_time = record->event.time;
flow_tap_expired = false;
}
static bool flow_tap_key_if_within_term(keyrecord_t *record, uint16_t prev_time) {
const uint16_t idle_time = TIMER_DIFF_16(record->event.time, prev_time);
if (flow_tap_expired || idle_time >= 500) {
return false;
}
const uint16_t keycode = get_record_keycode(record, false);
if (is_mt_or_lt(keycode)) {
uint16_t term = get_flow_tap_term(keycode, record, flow_tap_prev_keycode);
if (term > 500) {
term = 500;
}
if (idle_time < term) {
debug_event(record->event);
ac_dprintf(" within flow tap term (%u < %u) considered a tap\n", idle_time, term);
record->tap.count = 1;
registered_taps_add(record->event.key);
debug_registered_taps();
process_record(record);
return true;
}
}
return false;
}
// By default, enable Flow Tap for the keys in the main alphas area and Space.
// This should work reasonably even if the layout is remapped on the host to an
// alt layout or international layout (e.g. Dvorak or AZERTY), where these same
// key positions are mostly used for typing letters.
__attribute__((weak)) bool is_flow_tap_key(uint16_t keycode) {
if ((get_mods() & (MOD_MASK_CG | MOD_BIT_LALT)) != 0) {
return false; // Disable Flow Tap on hotkeys.
}
switch (get_tap_keycode(keycode)) {
case KC_SPC:
case KC_A ... KC_Z:
case KC_DOT:
case KC_COMM:
case KC_SCLN:
case KC_SLSH:
return true;
}
return false;
}
__attribute__((weak)) uint16_t get_flow_tap_term(uint16_t keycode, keyrecord_t *record, uint16_t prev_keycode) {
if (is_flow_tap_key(keycode) && is_flow_tap_key(prev_keycode)) {
return FLOW_TAP_TERM;
}
return 0;
}
# endif // FLOW_TAP_TERM
/** \brief Logs tapping key if ACTION_DEBUG is enabled. */
static void debug_tapping_key(void) {
ac_dprintf("TAPPING_KEY=");

View file

@ -111,6 +111,66 @@ char chordal_hold_handedness(keypos_t key);
extern const char chordal_hold_layout[MATRIX_ROWS][MATRIX_COLS] PROGMEM;
#endif
#ifdef FLOW_TAP_TERM
/**
* Callback to specify the keys where Flow Tap is enabled.
*
* Flow Tap is constrained to certain keys by the following rule: this callback
* is called for both the tap-hold key *and* the key press immediately preceding
* it. If the callback returns true for both keycodes, Flow Tap is enabled.
*
* The default implementation of this callback corresponds to
*
* bool is_flow_tap_key(uint16_t keycode) {
* switch (get_tap_keycode(keycode)) {
* case KC_SPC:
* case KC_A ... KC_Z:
* case KC_DOT:
* case KC_COMM:
* case KC_SCLN:
* case KC_SLSH:
* return true;
* }
* return false;
* }
*
* @param keycode Keycode of the key.
* @return Whether to enable Flow Tap for this key.
*/
bool is_flow_tap_key(uint16_t keycode);
/**
* Callback to customize Flow Tap filtering.
*
* Flow Tap acts only when key events are closer together than this time.
*
* Return a time of 0 to disable filtering. In this way, Flow Tap may be
* disabled for certain tap-hold keys, or when following certain previous keys.
*
* The default implementation of this callback is
*
* uint16_t get_flow_tap_term(uint16_t keycode, keyrecord_t* record,
* uint16_t prev_keycode) {
* if (is_flow_tap_key(keycode) && is_flow_tap_key(prev_keycode)) {
* return g_flow_tap_term;
* }
* return 0;
* }
*
* NOTE: If both `is_flow_tap_key()` and `get_flow_tap_term()` are defined, then
* `get_flow_tap_term()` takes precedence.
*
* @param keycode Keycode of the tap-hold key.
* @param record keyrecord_t of the tap-hold event.
* @param prev_keycode Keycode of the previously pressed key.
* @return Time in milliseconds.
*/
uint16_t get_flow_tap_term(uint16_t keycode, keyrecord_t *record, uint16_t prev_keycode);
/** Updates the Flow Tap last key and timer. */
void flow_tap_update_last_event(keyrecord_t *record);
#endif // FLOW_TAP_TERM
#ifdef DYNAMIC_TAPPING_TERM_ENABLE
extern uint16_t g_tapping_term;
#endif

View file

@ -22,7 +22,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "timer.h"
#include "keycode_config.h"
#include "qmk_settings.h"
#include "usb_device_state.h"
#include <string.h>
extern keymap_config_t keymap_config;
@ -205,7 +204,7 @@ bool is_oneshot_layer_active(void) {
void oneshot_set(bool active) {
if (keymap_config.oneshot_enable != active) {
keymap_config.oneshot_enable = active;
eeconfig_update_keymap(keymap_config.raw);
eeconfig_update_keymap(&keymap_config);
clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED);
dprintf("Oneshot: active: %d\n", active);
}
@ -304,14 +303,12 @@ void send_nkro_report(void) {
*/
void send_keyboard_report(void) {
#ifdef NKRO_ENABLE
if (usb_device_state_get_protocol() == USB_PROTOCOL_REPORT && keymap_config.nkro) {
if (host_can_send_nkro() && keymap_config.nkro) {
send_nkro_report();
} else {
send_6kro_report();
return;
}
#else
send_6kro_report();
#endif
send_6kro_report();
}
/** \brief Get mods

View file

@ -149,14 +149,14 @@ void audio_driver_start(void) {
}
void eeconfig_update_audio_current(void) {
eeconfig_update_audio(audio_config.raw);
eeconfig_update_audio(&audio_config);
}
void eeconfig_update_audio_default(void) {
audio_config.valid = true;
audio_config.enable = AUDIO_DEFAULT_ON;
audio_config.clicky_enable = AUDIO_DEFAULT_CLICKY_ON;
eeconfig_update_audio(audio_config.raw);
eeconfig_update_audio(&audio_config);
}
void audio_init(void) {
@ -164,7 +164,7 @@ void audio_init(void) {
return;
}
audio_config.raw = eeconfig_read_audio();
eeconfig_read_audio(&audio_config);
if (!audio_config.valid) {
dprintf("audio_init audio_config.valid = 0. Write default values to EEPROM.\n");
eeconfig_update_audio_default();
@ -196,7 +196,7 @@ void audio_toggle(void) {
stop_all_notes();
}
audio_config.enable ^= 1;
eeconfig_update_audio(audio_config.raw);
eeconfig_update_audio(&audio_config);
if (audio_config.enable) {
audio_on_user();
} else {
@ -206,7 +206,7 @@ void audio_toggle(void) {
void audio_on(void) {
audio_config.enable = 1;
eeconfig_update_audio(audio_config.raw);
eeconfig_update_audio(&audio_config);
audio_on_user();
PLAY_SONG(audio_on_song);
}
@ -217,7 +217,7 @@ void audio_off(void) {
wait_ms(100);
audio_stop_all();
audio_config.enable = 0;
eeconfig_update_audio(audio_config.raw);
eeconfig_update_audio(&audio_config);
}
bool audio_is_on(void) {

View file

@ -18,6 +18,8 @@
#include <stdint.h>
#include <stdbool.h>
#include "compiler_support.h"
#include "musical_notes.h"
#include "song_list.h"
#include "voices.h"
@ -28,7 +30,7 @@
# include "audio_dac.h"
#endif
typedef union {
typedef union audio_config_t {
uint8_t raw;
struct {
bool enable : 1;
@ -38,7 +40,7 @@ typedef union {
};
} audio_config_t;
_Static_assert(sizeof(audio_config_t) == sizeof(uint8_t), "Audio EECONFIG out of spec.");
STATIC_ASSERT(sizeof(audio_config_t) == sizeof(uint8_t), "Audio EECONFIG out of spec.");
/*
* a 'musical note' is represented by pitch and duration; a 'musical tone' adds intensity and timbre

View file

@ -16,7 +16,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "backlight.h"
#include "eeprom.h"
#include "eeconfig.h"
#include "debug.h"
@ -55,7 +54,7 @@ static void backlight_check_config(void) {
* FIXME: needs doc
*/
void backlight_init(void) {
backlight_config.raw = eeconfig_read_backlight();
eeconfig_read_backlight(&backlight_config);
if (!backlight_config.valid) {
dprintf("backlight_init backlight_config.valid = 0. Write default values to EEPROM.\n");
eeconfig_update_backlight_default();
@ -74,7 +73,7 @@ void backlight_increase(void) {
backlight_config.level++;
}
backlight_config.enable = 1;
eeconfig_update_backlight(backlight_config.raw);
eeconfig_update_backlight(&backlight_config);
dprintf("backlight increase: %u\n", backlight_config.level);
backlight_set(backlight_config.level);
}
@ -87,7 +86,7 @@ void backlight_decrease(void) {
if (backlight_config.level > 0) {
backlight_config.level--;
backlight_config.enable = !!backlight_config.level;
eeconfig_update_backlight(backlight_config.raw);
eeconfig_update_backlight(&backlight_config);
}
dprintf("backlight decrease: %u\n", backlight_config.level);
backlight_set(backlight_config.level);
@ -116,7 +115,7 @@ void backlight_enable(void) {
backlight_config.enable = true;
if (backlight_config.raw == 1) // enabled but level == 0
backlight_config.level = 1;
eeconfig_update_backlight(backlight_config.raw);
eeconfig_update_backlight(&backlight_config);
dprintf("backlight enable\n");
backlight_set(backlight_config.level);
}
@ -129,7 +128,7 @@ void backlight_disable(void) {
if (!backlight_config.enable) return; // do nothing if backlight is already off
backlight_config.enable = false;
eeconfig_update_backlight(backlight_config.raw);
eeconfig_update_backlight(&backlight_config);
dprintf("backlight disable\n");
backlight_set(0);
}
@ -152,7 +151,7 @@ void backlight_step(void) {
backlight_config.level = 0;
}
backlight_config.enable = !!backlight_config.level;
eeconfig_update_backlight(backlight_config.raw);
eeconfig_update_backlight(&backlight_config);
dprintf("backlight step: %u\n", backlight_config.level);
backlight_set(backlight_config.level);
}
@ -173,19 +172,11 @@ void backlight_level_noeeprom(uint8_t level) {
*/
void backlight_level(uint8_t level) {
backlight_level_noeeprom(level);
eeconfig_update_backlight(backlight_config.raw);
}
uint8_t eeconfig_read_backlight(void) {
return eeprom_read_byte(EECONFIG_BACKLIGHT);
}
void eeconfig_update_backlight(uint8_t val) {
eeprom_update_byte(EECONFIG_BACKLIGHT, val);
eeconfig_update_backlight(&backlight_config);
}
void eeconfig_update_backlight_current(void) {
eeconfig_update_backlight(backlight_config.raw);
eeconfig_update_backlight(&backlight_config);
}
void eeconfig_update_backlight_default(void) {
@ -193,7 +184,7 @@ void eeconfig_update_backlight_default(void) {
backlight_config.enable = BACKLIGHT_DEFAULT_ON;
backlight_config.breathing = BACKLIGHT_DEFAULT_BREATHING;
backlight_config.level = BACKLIGHT_DEFAULT_LEVEL;
eeconfig_update_backlight(backlight_config.raw);
eeconfig_update_backlight(&backlight_config);
}
/** \brief Get backlight level
@ -226,7 +217,7 @@ void backlight_enable_breathing(void) {
if (backlight_config.breathing) return; // do nothing if breathing is already on
backlight_config.breathing = true;
eeconfig_update_backlight(backlight_config.raw);
eeconfig_update_backlight(&backlight_config);
dprintf("backlight breathing enable\n");
breathing_enable();
}
@ -239,7 +230,7 @@ void backlight_disable_breathing(void) {
if (!backlight_config.breathing) return; // do nothing if breathing is already off
backlight_config.breathing = false;
eeconfig_update_backlight(backlight_config.raw);
eeconfig_update_backlight(&backlight_config);
dprintf("backlight breathing disable\n");
breathing_disable();
}

View file

@ -20,6 +20,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <stdint.h>
#include <stdbool.h>
#include "compiler_support.h"
#ifndef BACKLIGHT_LEVELS
# define BACKLIGHT_LEVELS 3
#elif BACKLIGHT_LEVELS > 31
@ -34,7 +36,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
# define BREATHING_PERIOD 6
#endif
typedef union {
typedef union backlight_config_t {
uint8_t raw;
struct {
bool enable : 1;
@ -44,7 +46,7 @@ typedef union {
};
} backlight_config_t;
_Static_assert(sizeof(backlight_config_t) == sizeof(uint8_t), "Backlight EECONFIG out of spec.");
STATIC_ASSERT(sizeof(backlight_config_t) == sizeof(uint8_t), "Backlight EECONFIG out of spec.");
void backlight_init(void);
void backlight_toggle(void);
@ -58,10 +60,8 @@ void backlight_level_noeeprom(uint8_t level);
void backlight_level(uint8_t level);
uint8_t get_backlight_level(void);
uint8_t eeconfig_read_backlight(void);
void eeconfig_update_backlight(uint8_t val);
void eeconfig_update_backlight_current(void);
void eeconfig_update_backlight_default(void);
void eeconfig_update_backlight_current(void);
void eeconfig_update_backlight_default(void);
// implementation specific
void backlight_init_ports(void);

View file

@ -4,7 +4,7 @@
#include <stdint.h>
/* Remove these once we transitioned to C23 across all platfroms */
/* Remove these once we transitioned to C23 across all platforms */
#define UINT32_WIDTH 32
#define UINT64_WIDTH 64

View file

@ -247,10 +247,10 @@ static void print_status(void) {
#if !defined(NO_PRINT) && !defined(USER_PRINT)
static void print_eeconfig(void) {
xprintf("eeconfig:\ndefault_layer: %u\n", eeconfig_read_default_layer());
xprintf("eeconfig:\ndefault_layer: %" PRIu32 "\n", (uint32_t)eeconfig_read_default_layer());
debug_config_t dc;
dc.raw = eeconfig_read_debug();
eeconfig_read_debug(&dc);
xprintf(/* clang-format off */
"debug_config.raw: %02X\n"
@ -267,7 +267,7 @@ static void print_eeconfig(void) {
); /* clang-format on */
keymap_config_t kc;
kc.raw = eeconfig_read_keymap();
eeconfig_read_keymap(&kc);
xprintf(/* clang-format off */
"keymap_config.raw: %02X\n"
@ -300,7 +300,7 @@ static void print_eeconfig(void) {
# ifdef BACKLIGHT_ENABLE
backlight_config_t bc;
bc.raw = eeconfig_read_backlight();
eeconfig_read_backlight(&bc);
xprintf(/* clang-format off */
"backlight_config"

View file

@ -0,0 +1,15 @@
// Copyright 2025 QMK Contributors
// SPDX-License-Identifier: GPL-2.0-or-later
/**
* @brief Perfom an assertion at compile time.
*
* `_Static_assert` is C<23, while `static_assert` is C++/C23.
*/
#if !defined(STATIC_ASSERT)
# ifdef __cplusplus
# define STATIC_ASSERT static_assert
# else
# define STATIC_ASSERT _Static_assert
# endif
#endif

View file

@ -0,0 +1,141 @@
// Copyright 2025 QMK
// SPDX-License-Identifier: GPL-2.0-or-later
#include "connection.h"
#include "eeconfig.h"
#include "usb_util.h"
#include "util.h"
#ifdef BLUETOOTH_ENABLE
# include "bluetooth.h"
#endif
// ======== DEPRECATED DEFINES - DO NOT USE ========
#ifdef OUTPUT_DEFAULT
# undef CONNECTION_HOST_DEFAULT
# define CONNECTION_HOST_DEFAULT OUTPUT_DEFAULT
#endif
__attribute__((weak)) void set_output_user(uint8_t output) {}
// ========
#define CONNECTION_HOST_INVALID 0xFF
#ifndef CONNECTION_HOST_DEFAULT
# define CONNECTION_HOST_DEFAULT CONNECTION_HOST_AUTO
#endif
static const connection_host_t host_candidates[] = {
CONNECTION_HOST_AUTO,
CONNECTION_HOST_USB,
#ifdef BLUETOOTH_ENABLE
CONNECTION_HOST_BLUETOOTH,
#endif
#if 0
CONNECTION_HOST_2P4GHZ,
#endif
};
#define HOST_CANDIDATES_COUNT ARRAY_SIZE(host_candidates)
static connection_config_t config = {.desired_host = CONNECTION_HOST_INVALID};
void eeconfig_update_connection_default(void) {
config.desired_host = CONNECTION_HOST_DEFAULT;
eeconfig_update_connection(&config);
}
void connection_init(void) {
eeconfig_read_connection(&config);
if (config.desired_host == CONNECTION_HOST_INVALID) {
eeconfig_update_connection_default();
}
}
__attribute__((weak)) void connection_host_changed_user(connection_host_t host) {}
__attribute__((weak)) void connection_host_changed_kb(connection_host_t host) {}
static void handle_host_changed(void) {
connection_host_changed_user(config.desired_host);
connection_host_changed_kb(config.desired_host);
// TODO: Remove deprecated callback
set_output_user(config.desired_host);
}
void connection_set_host_noeeprom(connection_host_t host) {
if (config.desired_host == host) {
return;
}
config.desired_host = host;
handle_host_changed();
}
void connection_set_host(connection_host_t host) {
connection_set_host_noeeprom(host);
eeconfig_update_connection(&config);
}
void connection_next_host_noeeprom(void) {
uint8_t next = 0;
for (uint8_t i = 0; i < HOST_CANDIDATES_COUNT; i++) {
if (host_candidates[i] == config.desired_host) {
next = i == HOST_CANDIDATES_COUNT - 1 ? 0 : i + 1;
break;
}
}
connection_set_host_noeeprom(host_candidates[next]);
}
void connection_next_host(void) {
connection_next_host_noeeprom();
eeconfig_update_connection(&config);
}
void connection_prev_host_noeeprom(void) {
uint8_t next = 0;
for (uint8_t i = 0; i < HOST_CANDIDATES_COUNT; i++) {
if (host_candidates[i] == config.desired_host) {
next = i == 0 ? HOST_CANDIDATES_COUNT - 1 : i - 1;
break;
}
}
connection_set_host_noeeprom(host_candidates[next]);
}
void connection_prev_host(void) {
connection_prev_host_noeeprom();
eeconfig_update_connection(&config);
}
connection_host_t connection_get_host_raw(void) {
return config.desired_host;
}
connection_host_t connection_auto_detect_host(void) {
if (usb_connected_state()) {
return CONNECTION_HOST_USB;
}
#ifdef BLUETOOTH_ENABLE
if (bluetooth_is_connected()) {
return CONNECTION_HOST_BLUETOOTH;
}
#endif
return CONNECTION_HOST_NONE;
}
connection_host_t connection_get_host(void) {
if (config.desired_host == CONNECTION_HOST_AUTO) {
return connection_auto_detect_host();
}
return config.desired_host;
}

View file

@ -0,0 +1,112 @@
// Copyright 2025 QMK
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <stdint.h>
#include "compiler_support.h"
#include "util.h"
/**
* \enum connection_host_t
*
* An enumeration of the possible hosts.
*/
typedef enum connection_host_t {
CONNECTION_HOST_AUTO,
CONNECTION_HOST_NONE,
CONNECTION_HOST_USB,
CONNECTION_HOST_BLUETOOTH,
CONNECTION_HOST_2P4GHZ
} connection_host_t;
/**
* \union connection_config_t
*
* Configuration structure for the connection subsystem.
*/
typedef union connection_config_t {
uint8_t raw;
connection_host_t desired_host : 8;
} PACKED connection_config_t;
STATIC_ASSERT(sizeof(connection_config_t) == sizeof(uint8_t), "Connection EECONFIG out of spec.");
/**
* \brief Initialize the subsystem.
*
* This function must be called only once, before any of the below functions can be called.
*/
void connection_init(void);
/**
* \brief Get currently configured host. Does not resolve 'CONNECTION_HOST_AUTO'.
*
* \return 'connection_host_t' of the configured host.
*/
connection_host_t connection_get_host_raw(void);
/**
* \brief Get current active host.
*
* \return 'connection_host_t' of the configured host.
*/
connection_host_t connection_auto_detect_host(void);
/**
* \brief Get currently configured host. Resolves 'CONNECTION_HOST_AUTO' using 'connection_auto_detect_host()'.
*
* \return 'connection_host_t' of the configured host.
*/
connection_host_t connection_get_host(void);
/**
* \brief Get current host. New state is not written to EEPROM.
*
* \param host The host to configure.
*/
void connection_set_host_noeeprom(connection_host_t host);
/**
* \brief Get current host.
*
* \param host The host to configure.
*/
void connection_set_host(connection_host_t host);
/**
* \brief Move to the next potential host. New state is not written to EEPROM.
*
*/
void connection_next_host_noeeprom(void);
/**
* \brief Move to the next potential host.
*
*/
void connection_next_host(void);
/**
* \brief Move to the previous potential host. New state is not written to EEPROM.
*
*/
void connection_prev_host_noeeprom(void);
/**
* \brief Move to the previous potential host.
*
*/
void connection_prev_host(void);
/**
* \brief user hook called when changing configured host
*
*/
void connection_host_changed_user(connection_host_t host);
/**
* \brief keyboard hook called when changing configured host
*
*/
void connection_host_changed_kb(connection_host_t host);

View file

@ -1,4 +1,5 @@
/* Copyright 2017 Jason Williams (Wilba)
* Copyright 2024-2025 Nick Brassel (@tzarc)
*
* 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
@ -17,25 +18,14 @@
#include "dynamic_keymap.h"
#include "keymap_introspection.h"
#include "action.h"
#include "eeprom.h"
#include "progmem.h"
#include "send_string.h"
#include "keycodes.h"
#include "action_tapping.h"
#include "wait.h"
#include <string.h>
#ifdef VIA_ENABLE
# include "via.h"
# define DYNAMIC_KEYMAP_EEPROM_START (VIA_EEPROM_CONFIG_END)
#else
# include "eeconfig.h"
# define DYNAMIC_KEYMAP_EEPROM_START (EECONFIG_SIZE)
#endif
#ifdef VIAL_ENABLE
#include "vial.h"
#endif
#include "qmk_settings.h"
#include "nvm_dynamic_keymap.h"
#ifdef ENCODER_ENABLE
# include "encoder.h"
@ -43,89 +33,8 @@
# define NUM_ENCODERS 0
#endif
#ifndef TOTAL_EEPROM_BYTE_COUNT
# error Unknown total EEPROM size. Cannot derive maximum for dynamic keymaps.
#endif
#ifndef DYNAMIC_KEYMAP_EEPROM_MAX_ADDR
# define DYNAMIC_KEYMAP_EEPROM_MAX_ADDR (TOTAL_EEPROM_BYTE_COUNT - 1)
#endif
#if DYNAMIC_KEYMAP_EEPROM_MAX_ADDR > (TOTAL_EEPROM_BYTE_COUNT - 1)
# pragma message STR(DYNAMIC_KEYMAP_EEPROM_MAX_ADDR) " > " STR((TOTAL_EEPROM_BYTE_COUNT - 1))
# error DYNAMIC_KEYMAP_EEPROM_MAX_ADDR is configured to use more space than what is available for the selected EEPROM driver
#endif
// Due to usage of uint16_t check for max 65535
#if DYNAMIC_KEYMAP_EEPROM_MAX_ADDR > 65535
# pragma message STR(DYNAMIC_KEYMAP_EEPROM_MAX_ADDR) " > 65535"
# error DYNAMIC_KEYMAP_EEPROM_MAX_ADDR must be less than 65536
#endif
// If DYNAMIC_KEYMAP_EEPROM_ADDR not explicitly defined in config.h,
#ifndef DYNAMIC_KEYMAP_EEPROM_ADDR
# define DYNAMIC_KEYMAP_EEPROM_ADDR DYNAMIC_KEYMAP_EEPROM_START
#endif
// Encoders are located right after the dynamic keymap
#define VIAL_ENCODERS_EEPROM_ADDR (DYNAMIC_KEYMAP_EEPROM_ADDR + (DYNAMIC_KEYMAP_LAYER_COUNT * MATRIX_ROWS * MATRIX_COLS * 2))
#define DYNAMIC_KEYMAP_ENCODER_EEPROM_ADDR VIAL_ENCODERS_EEPROM_ADDR
#define VIAL_ENCODERS_SIZE (NUM_ENCODERS * DYNAMIC_KEYMAP_LAYER_COUNT * 2 * 2)
// QMK settings area is just past encoders
#define VIAL_QMK_SETTINGS_EEPROM_ADDR (VIAL_ENCODERS_EEPROM_ADDR + VIAL_ENCODERS_SIZE)
#ifdef QMK_SETTINGS
#include "qmk_settings.h"
#define VIAL_QMK_SETTINGS_SIZE (sizeof(qmk_settings_t))
#else
#define VIAL_QMK_SETTINGS_SIZE 0
#endif
// Tap-dance
#define VIAL_TAP_DANCE_EEPROM_ADDR (VIAL_QMK_SETTINGS_EEPROM_ADDR + VIAL_QMK_SETTINGS_SIZE)
#ifdef VIAL_TAP_DANCE_ENABLE
#define VIAL_TAP_DANCE_SIZE (sizeof(vial_tap_dance_entry_t) * VIAL_TAP_DANCE_ENTRIES)
#else
#define VIAL_TAP_DANCE_SIZE 0
#endif
// Combos
#define VIAL_COMBO_EEPROM_ADDR (VIAL_TAP_DANCE_EEPROM_ADDR + VIAL_TAP_DANCE_SIZE)
#ifdef VIAL_COMBO_ENABLE
#define VIAL_COMBO_SIZE (sizeof(vial_combo_entry_t) * VIAL_COMBO_ENTRIES)
#else
#define VIAL_COMBO_SIZE 0
#endif
// Key overrides
#define VIAL_KEY_OVERRIDE_EEPROM_ADDR (VIAL_COMBO_EEPROM_ADDR + VIAL_COMBO_SIZE)
#ifdef VIAL_KEY_OVERRIDE_ENABLE
#define VIAL_KEY_OVERRIDE_SIZE (sizeof(vial_key_override_entry_t) * VIAL_KEY_OVERRIDE_ENTRIES)
#else
#define VIAL_KEY_OVERRIDE_SIZE 0
#endif
// Dynamic macro
#ifndef DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR
# define DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR (VIAL_KEY_OVERRIDE_EEPROM_ADDR + VIAL_KEY_OVERRIDE_SIZE)
#endif
// Sanity check that dynamic keymaps fit in available EEPROM
// If there's not 100 bytes available for macros, then something is wrong.
// The keyboard should override DYNAMIC_KEYMAP_LAYER_COUNT to reduce it,
// or DYNAMIC_KEYMAP_EEPROM_MAX_ADDR to increase it, *only if* the microcontroller has
// more than the default.
_Static_assert(DYNAMIC_KEYMAP_EEPROM_MAX_ADDR >= DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR + 100, "Dynamic keymaps are configured to use more EEPROM than is available.");
// Dynamic macros are stored after the keymaps and use what is available
// up to and including DYNAMIC_KEYMAP_EEPROM_MAX_ADDR.
#ifndef DYNAMIC_KEYMAP_MACRO_EEPROM_SIZE
# define DYNAMIC_KEYMAP_MACRO_EEPROM_SIZE (DYNAMIC_KEYMAP_EEPROM_MAX_ADDR - DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR + 1)
#ifdef VIAL_ENABLE
#include "vial.h"
#endif
#ifndef DYNAMIC_KEYMAP_MACRO_DELAY
@ -136,132 +45,61 @@ uint8_t dynamic_keymap_get_layer_count(void) {
return DYNAMIC_KEYMAP_LAYER_COUNT;
}
void *dynamic_keymap_key_to_eeprom_address(uint8_t layer, uint8_t row, uint8_t column) {
// TODO: optimize this with some left shifts
return ((void *)DYNAMIC_KEYMAP_EEPROM_ADDR) + (layer * MATRIX_ROWS * MATRIX_COLS * 2) + (row * MATRIX_COLS * 2) + (column * 2);
}
uint16_t dynamic_keymap_get_keycode(uint8_t layer, uint8_t row, uint8_t column) {
if (layer >= DYNAMIC_KEYMAP_LAYER_COUNT || row >= MATRIX_ROWS || column >= MATRIX_COLS) return KC_NO;
void *address = dynamic_keymap_key_to_eeprom_address(layer, row, column);
// Big endian, so we can read/write EEPROM directly from host if we want
uint16_t keycode = eeprom_read_byte(address) << 8;
keycode |= eeprom_read_byte(address + 1);
return keycode;
return nvm_dynamic_keymap_read_keycode(layer, row, column);
}
void dynamic_keymap_set_keycode(uint8_t layer, uint8_t row, uint8_t column, uint16_t keycode) {
if (layer >= DYNAMIC_KEYMAP_LAYER_COUNT || row >= MATRIX_ROWS || column >= MATRIX_COLS) return;
void *address = dynamic_keymap_key_to_eeprom_address(layer, row, column);
// Big endian, so we can read/write EEPROM directly from host if we want
eeprom_update_byte(address, (uint8_t)(keycode >> 8));
eeprom_update_byte(address + 1, (uint8_t)(keycode & 0xFF));
nvm_dynamic_keymap_update_keycode(layer, row, column, keycode);
}
#ifdef ENCODER_MAP_ENABLE
void *dynamic_keymap_encoder_to_eeprom_address(uint8_t layer, uint8_t encoder_id) {
return ((void *)DYNAMIC_KEYMAP_ENCODER_EEPROM_ADDR) + (layer * NUM_ENCODERS * 2 * 2) + (encoder_id * 2 * 2);
}
uint16_t dynamic_keymap_get_encoder(uint8_t layer, uint8_t encoder_id, bool clockwise) {
if (layer >= DYNAMIC_KEYMAP_LAYER_COUNT || encoder_id >= NUM_ENCODERS) return KC_NO;
void *address = dynamic_keymap_encoder_to_eeprom_address(layer, encoder_id);
// Big endian, so we can read/write EEPROM directly from host if we want
uint16_t keycode = ((uint16_t)eeprom_read_byte(address + (clockwise ? 0 : 2))) << 8;
keycode |= eeprom_read_byte(address + (clockwise ? 0 : 2) + 1);
return keycode;
return nvm_dynamic_keymap_read_encoder(layer, encoder_id, clockwise);
}
void dynamic_keymap_set_encoder(uint8_t layer, uint8_t encoder_id, bool clockwise, uint16_t keycode) {
if (layer >= DYNAMIC_KEYMAP_LAYER_COUNT || encoder_id >= NUM_ENCODERS) return;
void *address = dynamic_keymap_encoder_to_eeprom_address(layer, encoder_id);
// Big endian, so we can read/write EEPROM directly from host if we want
eeprom_update_byte(address + (clockwise ? 0 : 2), (uint8_t)(keycode >> 8));
eeprom_update_byte(address + (clockwise ? 0 : 2) + 1, (uint8_t)(keycode & 0xFF));
nvm_dynamic_keymap_update_encoder(layer, encoder_id, clockwise, keycode);
}
#endif // ENCODER_MAP_ENABLE
#ifdef QMK_SETTINGS
uint8_t dynamic_keymap_get_qmk_settings(uint16_t offset) {
if (offset >= VIAL_QMK_SETTINGS_SIZE)
return 0;
void *address = (void*)(VIAL_QMK_SETTINGS_EEPROM_ADDR + offset);
return eeprom_read_byte(address);
return nvm_dynamic_keymap_get_qmk_settings(offset);
}
void dynamic_keymap_set_qmk_settings(uint16_t offset, uint8_t value) {
if (offset >= VIAL_QMK_SETTINGS_SIZE)
return;
void *address = (void*)(VIAL_QMK_SETTINGS_EEPROM_ADDR + offset);
eeprom_update_byte(address, value);
nvm_dynamic_keymap_set_qmk_settings(offset, value);
}
#endif
#ifdef VIAL_TAP_DANCE_ENABLE
int dynamic_keymap_get_tap_dance(uint8_t index, vial_tap_dance_entry_t *entry) {
if (index >= VIAL_TAP_DANCE_ENTRIES)
return -1;
void *address = (void*)(VIAL_TAP_DANCE_EEPROM_ADDR + index * sizeof(vial_tap_dance_entry_t));
eeprom_read_block(entry, address, sizeof(vial_tap_dance_entry_t));
return 0;
return nvm_dynamic_keymap_get_tap_dance(index, entry);
}
int dynamic_keymap_set_tap_dance(uint8_t index, const vial_tap_dance_entry_t *entry) {
if (index >= VIAL_TAP_DANCE_ENTRIES)
return -1;
void *address = (void*)(VIAL_TAP_DANCE_EEPROM_ADDR + index * sizeof(vial_tap_dance_entry_t));
eeprom_write_block(entry, address, sizeof(vial_tap_dance_entry_t));
return 0;
return nvm_dynamic_keymap_set_tap_dance(index, entry);
}
#endif
#ifdef VIAL_COMBO_ENABLE
int dynamic_keymap_get_combo(uint8_t index, vial_combo_entry_t *entry) {
if (index >= VIAL_COMBO_ENTRIES)
return -1;
void *address = (void*)(VIAL_COMBO_EEPROM_ADDR + index * sizeof(vial_combo_entry_t));
eeprom_read_block(entry, address, sizeof(vial_combo_entry_t));
return 0;
return nvm_dynamic_keymap_get_combo(index, entry);
}
int dynamic_keymap_set_combo(uint8_t index, const vial_combo_entry_t *entry) {
if (index >= VIAL_COMBO_ENTRIES)
return -1;
void *address = (void*)(VIAL_COMBO_EEPROM_ADDR + index * sizeof(vial_combo_entry_t));
eeprom_write_block(entry, address, sizeof(vial_combo_entry_t));
return 0;
return nvm_dynamic_keymap_set_combo(index, entry);
}
#endif
#ifdef VIAL_KEY_OVERRIDE_ENABLE
int dynamic_keymap_get_key_override(uint8_t index, vial_key_override_entry_t *entry) {
if (index >= VIAL_KEY_OVERRIDE_ENTRIES)
return -1;
void *address = (void*)(VIAL_KEY_OVERRIDE_EEPROM_ADDR + index * sizeof(vial_key_override_entry_t));
eeprom_read_block(entry, address, sizeof(vial_key_override_entry_t));
return 0;
return nvm_dynamic_keymap_get_key_override(index, entry);
}
int dynamic_keymap_set_key_override(uint8_t index, const vial_key_override_entry_t *entry) {
if (index >= VIAL_KEY_OVERRIDE_ENTRIES)
return -1;
void *address = (void*)(VIAL_KEY_OVERRIDE_EEPROM_ADDR + index * sizeof(vial_key_override_entry_t));
eeprom_write_block(entry, address, sizeof(vial_key_override_entry_t));
return 0;
return nvm_dynamic_keymap_set_key_override(index, entry);
}
#endif
@ -272,6 +110,9 @@ void dynamic_keymap_reset(void) {
vial_unlocked = 1;
#endif
// Erase the keymaps, if necessary.
nvm_dynamic_keymap_erase();
// Reset the keymaps in EEPROM to what is in flash.
for (int layer = 0; layer < DYNAMIC_KEYMAP_LAYER_COUNT; layer++) {
for (int row = 0; row < MATRIX_ROWS; row++) {
@ -319,76 +160,11 @@ void dynamic_keymap_reset(void) {
}
void dynamic_keymap_get_buffer(uint16_t offset, uint16_t size, uint8_t *data) {
uint16_t dynamic_keymap_eeprom_size = DYNAMIC_KEYMAP_LAYER_COUNT * MATRIX_ROWS * MATRIX_COLS * 2;
void * source = (void *)(DYNAMIC_KEYMAP_EEPROM_ADDR + offset);
uint8_t *target = data;
for (uint16_t i = 0; i < size; i++) {
if (offset + i < dynamic_keymap_eeprom_size) {
*target = eeprom_read_byte(source);
} else {
*target = 0x00;
}
source++;
target++;
}
nvm_dynamic_keymap_read_buffer(offset, size, data);
}
void dynamic_keymap_set_buffer(uint16_t offset, uint16_t size, uint8_t *data) {
uint16_t dynamic_keymap_eeprom_size = DYNAMIC_KEYMAP_LAYER_COUNT * MATRIX_ROWS * MATRIX_COLS * 2;
void * target = (void *)(DYNAMIC_KEYMAP_EEPROM_ADDR + offset);
uint8_t *source = data;
#ifdef VIAL_ENABLE
/* ensure the writes are bounded */
if (offset >= dynamic_keymap_eeprom_size || dynamic_keymap_eeprom_size - offset < size)
return;
#ifndef VIAL_INSECURE
/* Check whether it is trying to send a QK_BOOT keycode; only allow setting these if unlocked */
if (!vial_unlocked) {
/* how much of the input array we'll have to check in the loop */
uint16_t chk_offset = 0;
uint16_t chk_sz = size;
/* initial byte misaligned -- this means the first keycode will be a combination of existing and new data */
if (offset % 2 != 0) {
uint16_t kc = (eeprom_read_byte((uint8_t*)target - 1) << 8) | data[0];
if (kc == QK_BOOT)
data[0] = 0xFF;
/* no longer have to check the first byte */
chk_offset += 1;
}
/* final byte misaligned -- this means the last keycode will be a combination of new and existing data */
if ((offset + size) % 2 != 0) {
uint16_t kc = (data[size - 1] << 8) | eeprom_read_byte((uint8_t*)target + size);
if (kc == QK_BOOT)
data[size - 1] = 0xFF;
/* no longer have to check the last byte */
chk_sz -= 1;
}
/* check the entire array, replace any instances of QK_BOOT with invalid keycode 0xFFFF */
for (uint16_t i = chk_offset; i < chk_sz; i += 2) {
uint16_t kc = (data[i] << 8) | data[i + 1];
if (kc == QK_BOOT) {
data[i] = 0xFF;
data[i + 1] = 0xFF;
}
}
}
#endif
#endif
for (uint16_t i = 0; i < size; i++) {
if (offset + i < dynamic_keymap_eeprom_size) {
eeprom_update_byte(target, *source);
}
source++;
target++;
}
nvm_dynamic_keymap_update_buffer(offset, size, data);
}
uint16_t keycode_at_keymap_location(uint8_t layer_num, uint8_t row, uint8_t column) {
@ -412,53 +188,27 @@ uint8_t dynamic_keymap_macro_get_count(void) {
}
uint16_t dynamic_keymap_macro_get_buffer_size(void) {
return DYNAMIC_KEYMAP_MACRO_EEPROM_SIZE;
return (uint16_t)nvm_dynamic_keymap_macro_size();
}
void dynamic_keymap_macro_get_buffer(uint16_t offset, uint16_t size, uint8_t *data) {
void * source = (void *)(DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR + offset);
uint8_t *target = data;
for (uint16_t i = 0; i < size; i++) {
if (offset + i < DYNAMIC_KEYMAP_MACRO_EEPROM_SIZE) {
*target = eeprom_read_byte(source);
} else {
*target = 0x00;
}
source++;
target++;
}
nvm_dynamic_keymap_macro_read_buffer(offset, size, data);
}
void dynamic_keymap_macro_set_buffer(uint16_t offset, uint16_t size, uint8_t *data) {
void * target = (void *)(DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR + offset);
uint8_t *source = data;
for (uint16_t i = 0; i < size; i++) {
if (offset + i < DYNAMIC_KEYMAP_MACRO_EEPROM_SIZE) {
eeprom_update_byte(target, *source);
}
source++;
target++;
}
nvm_dynamic_keymap_macro_update_buffer(offset, size, data);
}
typedef struct send_string_eeprom_state_t {
const uint8_t *ptr;
} send_string_eeprom_state_t;
char send_string_get_next_eeprom(void *arg) {
send_string_eeprom_state_t *state = (send_string_eeprom_state_t *)arg;
char ret = eeprom_read_byte(state->ptr);
state->ptr++;
return ret;
static uint8_t dynamic_keymap_read_byte(uint32_t offset) {
uint8_t d;
nvm_dynamic_keymap_macro_read_buffer(offset, 1, &d);
return d;
}
void dynamic_keymap_macro_reset(void) {
void *p = (void *)(DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR);
void *end = (void *)(DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR + DYNAMIC_KEYMAP_MACRO_EEPROM_SIZE);
while (p != end) {
eeprom_update_byte(p, 0);
++p;
}
// Erase the macros, if necessary.
nvm_dynamic_keymap_macro_erase();
nvm_dynamic_keymap_macro_reset();
}
static uint16_t decode_keycode(uint16_t kc) {
@ -477,26 +227,24 @@ void dynamic_keymap_macro_send(uint8_t id) {
// If it's not zero, then we are in the middle
// of buffer writing, possibly an aborted buffer
// write. So do nothing.
void *p = (void *)(DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR + DYNAMIC_KEYMAP_MACRO_EEPROM_SIZE - 1);
if (eeprom_read_byte(p) != 0) {
if (dynamic_keymap_read_byte(nvm_dynamic_keymap_macro_size() - 1) != 0) {
return;
}
// Skip N null characters
// p will then point to the Nth macro
p = (void *)(DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR);
void *end = (void *)(DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR + DYNAMIC_KEYMAP_MACRO_EEPROM_SIZE);
// offset will then point to the Nth macro
uint32_t offset = 0;
uint32_t end = nvm_dynamic_keymap_macro_size();
while (id > 0) {
// If we are past the end of the buffer, then the buffer
// contents are garbage, i.e. there were not DYNAMIC_KEYMAP_MACRO_COUNT
// nulls in the buffer.
if (p == end) {
// If we are past the end of the buffer, then there is
// no Nth macro in the buffer.
if (offset == end) {
return;
}
if (eeprom_read_byte(p) == 0) {
if (dynamic_keymap_read_byte(offset) == 0) {
--id;
}
++p;
++offset;
}
// Send the macro string one or three chars at a time
@ -506,7 +254,7 @@ void dynamic_keymap_macro_send(uint8_t id) {
// the buffer, so this cannot go past the end
while (1) {
memset(data, 0, sizeof(data));
data[0] = eeprom_read_byte(p++);
data[0] = dynamic_keymap_read_byte(offset++);
// Stop at the null terminator of this macro string
if (data[0] == 0) {
break;
@ -514,18 +262,18 @@ void dynamic_keymap_macro_send(uint8_t id) {
if (data[0] == SS_QMK_PREFIX) {
// If the char is magic, process it as indicated by the next character
// (tap, down, up, delay)
data[1] = eeprom_read_byte(p++);
data[1] = dynamic_keymap_read_byte(offset++);
if (data[1] == 0)
break;
if (data[1] == SS_TAP_CODE || data[1] == SS_DOWN_CODE || data[1] == SS_UP_CODE) {
// For tap, down, up, just stuff it into the array and send_string it
data[2] = eeprom_read_byte(p++);
data[2] = dynamic_keymap_read_byte(offset++);
if (data[2] != 0)
send_string(data);
} else if (data[1] == VIAL_MACRO_EXT_TAP || data[1] == VIAL_MACRO_EXT_DOWN || data[1] == VIAL_MACRO_EXT_UP) {
data[2] = eeprom_read_byte(p++);
data[2] = dynamic_keymap_read_byte(offset++);
if (data[2] != 0) {
data[3] = eeprom_read_byte(p++);
data[3] = dynamic_keymap_read_byte(offset++);
if (data[3] != 0) {
uint16_t kc;
memcpy(&kc, &data[2], sizeof(kc));
@ -545,8 +293,8 @@ void dynamic_keymap_macro_send(uint8_t id) {
}
} else if (data[1] == SS_DELAY_CODE) {
// For delay, decode the delay and wait_ms for that amount
uint8_t d0 = eeprom_read_byte(p++);
uint8_t d1 = eeprom_read_byte(p++);
uint8_t d0 = dynamic_keymap_read_byte(offset++);
uint8_t d1 = dynamic_keymap_read_byte(offset++);
if (d0 == 0 || d1 == 0)
break;
// we cannot use 0 for these, need to subtract 1 and use 255 instead of 256 for delay calculation

View file

@ -31,7 +31,6 @@
#endif
uint8_t dynamic_keymap_get_layer_count(void);
void * dynamic_keymap_key_to_eeprom_address(uint8_t layer, uint8_t row, uint8_t column);
uint16_t dynamic_keymap_get_keycode(uint8_t layer, uint8_t row, uint8_t column);
void dynamic_keymap_set_keycode(uint8_t layer, uint8_t row, uint8_t column, uint16_t keycode);
#ifdef ENCODER_MAP_ENABLE

View file

@ -1,355 +1,359 @@
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include "eeprom.h"
#include "debug.h"
#include "eeconfig.h"
#include "action_layer.h"
#include "nvm_eeconfig.h"
#include "keycode_config.h"
#if defined(EEPROM_DRIVER)
# include "eeprom_driver.h"
#endif
#ifdef BACKLIGHT_ENABLE
# include "backlight.h"
#endif // BACKLIGHT_ENABLE
#if defined(HAPTIC_ENABLE)
#ifdef AUDIO_ENABLE
# include "audio.h"
#endif // AUDIO_ENABLE
#ifdef RGBLIGHT_ENABLE
# include "rgblight.h"
#endif // RGBLIGHT_ENABLE
#ifdef RGB_MATRIX_ENABLE
# include "rgb_matrix_types.h"
#endif // RGB_MATRIX_ENABLE
#ifdef LED_MATRIX_ENABLE
# include "led_matrix_types.h"
#endif // LED_MATRIX_ENABLE
#ifdef UNICODE_COMMON_ENABLE
# include "unicode.h"
#endif // UNICODE_COMMON_ENABLE
#ifdef HAPTIC_ENABLE
# include "haptic.h"
#endif
#endif // HAPTIC_ENABLE
#if defined(VIA_ENABLE)
#ifdef CONNECTION_ENABLE
# include "connection.h"
#endif // CONNECTION_ENABLE
#ifdef VIA_ENABLE
bool via_eeprom_is_valid(void);
void via_eeprom_set_valid(bool valid);
void eeconfig_init_via(void);
#else
void dynamic_keymap_reset(void);
#endif // VIA_ENABLE
#ifndef NKRO_DEFAULT_ON
# define NKRO_DEFAULT_ON false
#endif
_Static_assert((intptr_t)EECONFIG_HANDEDNESS == 14, "EEPROM handedness offset is incorrect");
/** \brief eeconfig enable
*
* FIXME: needs doc
*/
__attribute__((weak)) void eeconfig_init_user(void) {
#if (EECONFIG_USER_DATA_SIZE) == 0
// Reset user EEPROM value to blank, rather than to a set value
eeconfig_update_user(0);
#endif
#endif // (EECONFIG_USER_DATA_SIZE) == 0
}
__attribute__((weak)) void eeconfig_init_kb(void) {
#if (EECONFIG_KB_DATA_SIZE) == 0
// Reset Keyboard EEPROM value to blank, rather than to a set value
eeconfig_update_kb(0);
#endif
#endif // (EECONFIG_KB_DATA_SIZE) == 0
eeconfig_init_user();
}
/*
* FIXME: needs doc
*/
void eeconfig_init_quantum(void) {
#if defined(EEPROM_DRIVER)
eeprom_driver_format(false);
#endif
nvm_eeconfig_erase();
eeconfig_enable();
debug_config_t debug_config = {0};
eeconfig_update_debug(&debug_config);
eeprom_update_word(EECONFIG_MAGIC, EECONFIG_MAGIC_NUMBER);
eeprom_update_byte(EECONFIG_DEBUG, 0);
default_layer_state = (layer_state_t)1 << 0;
eeconfig_update_default_layer(default_layer_state);
// Enable oneshot and autocorrect by default: 0b0001 0100 0000 0000
eeprom_update_word(EECONFIG_KEYMAP, 0x1400);
eeprom_update_byte(EECONFIG_BACKLIGHT, 0);
eeprom_update_byte(EECONFIG_AUDIO, 0);
eeprom_update_dword(EECONFIG_RGBLIGHT, 0);
eeprom_update_byte(EECONFIG_RGBLIGHT_EXTENDED, 0);
eeprom_update_byte(EECONFIG_UNICODEMODE, 0);
eeprom_update_byte(EECONFIG_STENOMODE, 0);
eeprom_write_qword(EECONFIG_RGB_MATRIX, 0);
eeprom_update_dword(EECONFIG_HAPTIC, 0);
#if defined(HAPTIC_ENABLE)
haptic_reset();
keymap_config_t keymap_config = {
.swap_control_capslock = false,
.capslock_to_control = false,
.swap_lalt_lgui = false,
.swap_ralt_rgui = false,
.no_gui = false,
.swap_grave_esc = false,
.swap_backslash_backspace = false,
.nkro = NKRO_DEFAULT_ON,
.swap_lctl_lgui = false,
.swap_rctl_rgui = false,
.oneshot_enable = true, // Enable oneshot by default
.swap_escape_capslock = false,
.autocorrect_enable = true, // Enable autocorrect by default
};
eeconfig_update_keymap(&keymap_config);
#ifdef BACKLIGHT_ENABLE
backlight_config_t backlight_config = {0};
eeconfig_update_backlight(&backlight_config);
#endif // BACKLIGHT_ENABLE
#ifdef AUDIO_ENABLE
audio_config_t audio_config = {0};
eeconfig_update_audio(&audio_config);
#endif // AUDIO_ENABLE
#ifdef RGBLIGHT_ENABLE
extern void eeconfig_update_rgblight_default(void);
eeconfig_update_rgblight_default();
#endif // RGBLIGHT_ENABLE
#ifdef UNICODE_COMMON_ENABLE
unicode_config_t unicode_config = {0};
eeconfig_update_unicode_mode(&unicode_config);
#endif // UNICODE_COMMON_ENABLE
#ifdef STENO_ENABLE
eeconfig_update_steno_mode(0);
#endif // STENO_ENABLE
#ifdef RGB_MATRIX_ENABLE
extern void eeconfig_update_rgb_matrix_default(void);
eeconfig_update_rgb_matrix_default();
#endif
#ifdef LED_MATRIX_ENABLE
extern void eeconfig_update_led_matrix_default(void);
eeconfig_update_led_matrix_default();
#endif // LED_MATRIX_ENABLE
#ifdef HAPTIC_ENABLE
haptic_config_t haptic_config = {0};
eeconfig_update_haptic(&haptic_config);
haptic_reset();
#endif // HAPTIC_ENABLE
#ifdef CONNECTION_ENABLE
extern void eeconfig_update_connection_default(void);
eeconfig_update_connection_default();
#endif // CONNECTION_ENABLE
#if (EECONFIG_KB_DATA_SIZE) > 0
eeconfig_init_kb_datablock();
#endif
#endif // (EECONFIG_KB_DATA_SIZE) > 0
#if (EECONFIG_USER_DATA_SIZE) > 0
eeconfig_init_user_datablock();
#endif
#endif // (EECONFIG_USER_DATA_SIZE) > 0
#if defined(VIA_ENABLE)
// Invalidate VIA eeprom config, and then reset.
// Just in case if power is lost mid init, this makes sure that it pets
// Just in case if power is lost mid init, this makes sure that it gets
// properly re-initialized.
via_eeprom_set_valid(false);
eeconfig_init_via();
#elif defined(DYNAMIC_KEYMAP_ENABLE)
dynamic_keymap_reset();
#endif
eeconfig_init_kb();
#ifdef RGB_MATRIX_ENABLE
extern void eeconfig_force_flush_rgb_matrix(void);
eeconfig_force_flush_rgb_matrix();
#endif // RGB_MATRIX_ENABLE
#ifdef LED_MATRIX_ENABLE
extern void eeconfig_force_flush_led_matrix(void);
eeconfig_force_flush_led_matrix();
#endif // LED_MATRIX_ENABLE
}
/** \brief eeconfig initialization
*
* FIXME: needs doc
*/
void eeconfig_init(void) {
eeconfig_init_quantum();
}
/** \brief eeconfig enable
*
* FIXME: needs doc
*/
void eeconfig_enable(void) {
eeprom_update_word(EECONFIG_MAGIC, EECONFIG_MAGIC_NUMBER);
nvm_eeconfig_enable();
}
/** \brief eeconfig disable
*
* FIXME: needs doc
*/
void eeconfig_disable(void) {
#if defined(EEPROM_DRIVER)
eeprom_driver_format(false);
#endif
eeprom_update_word(EECONFIG_MAGIC, EECONFIG_MAGIC_NUMBER_OFF);
nvm_eeconfig_disable();
}
/** \brief eeconfig is enabled
*
* FIXME: needs doc
*/
bool eeconfig_is_enabled(void) {
bool is_eeprom_enabled = (eeprom_read_word(EECONFIG_MAGIC) == EECONFIG_MAGIC_NUMBER);
bool is_eeprom_enabled = nvm_eeconfig_is_enabled();
#ifdef VIA_ENABLE
if (is_eeprom_enabled) {
is_eeprom_enabled = via_eeprom_is_valid();
}
#endif
#endif // VIA_ENABLE
return is_eeprom_enabled;
}
/** \brief eeconfig is disabled
*
* FIXME: needs doc
*/
bool eeconfig_is_disabled(void) {
bool is_eeprom_disabled = (eeprom_read_word(EECONFIG_MAGIC) == EECONFIG_MAGIC_NUMBER_OFF);
bool is_eeprom_disabled = nvm_eeconfig_is_disabled();
#ifdef VIA_ENABLE
if (!is_eeprom_disabled) {
is_eeprom_disabled = !via_eeprom_is_valid();
}
#endif
#endif // VIA_ENABLE
return is_eeprom_disabled;
}
/** \brief eeconfig read debug
*
* FIXME: needs doc
*/
uint8_t eeconfig_read_debug(void) {
return eeprom_read_byte(EECONFIG_DEBUG);
void eeconfig_read_debug(debug_config_t *debug_config) {
nvm_eeconfig_read_debug(debug_config);
}
/** \brief eeconfig update debug
*
* FIXME: needs doc
*/
void eeconfig_update_debug(uint8_t val) {
eeprom_update_byte(EECONFIG_DEBUG, val);
void eeconfig_update_debug(const debug_config_t *debug_config) {
nvm_eeconfig_update_debug(debug_config);
}
/** \brief eeconfig read default layer
*
* FIXME: needs doc
*/
layer_state_t eeconfig_read_default_layer(void) {
uint8_t val = eeprom_read_byte(EECONFIG_DEFAULT_LAYER);
#ifdef DEFAULT_LAYER_STATE_IS_VALUE_NOT_BITMASK
// stored as a layer number, so convert back to bitmask
return 1 << val;
#else
// stored as 8-bit-wide bitmask, so read the value directly - handling padding to 16/32 bit layer_state_t
return val;
#endif
return nvm_eeconfig_read_default_layer();
}
/** \brief eeconfig update default layer
*
* FIXME: needs doc
*/
void eeconfig_update_default_layer(layer_state_t state) {
#ifdef DEFAULT_LAYER_STATE_IS_VALUE_NOT_BITMASK
// stored as a layer number, so only store the highest layer
uint8_t val = get_highest_layer(state);
#else
// stored as 8-bit-wide bitmask, so write the value directly - handling truncation from 16/32 bit layer_state_t
uint8_t val = state;
#endif
eeprom_update_byte(EECONFIG_DEFAULT_LAYER, val);
nvm_eeconfig_update_default_layer(state);
}
/** \brief eeconfig read keymap
*
* FIXME: needs doc
*/
uint16_t eeconfig_read_keymap(void) {
return eeprom_read_word(EECONFIG_KEYMAP);
void eeconfig_read_keymap(keymap_config_t *keymap_config) {
nvm_eeconfig_read_keymap(keymap_config);
}
/** \brief eeconfig update keymap
*
* FIXME: needs doc
*/
void eeconfig_update_keymap(uint16_t val) {
eeprom_update_word(EECONFIG_KEYMAP, val);
void eeconfig_update_keymap(const keymap_config_t *keymap_config) {
nvm_eeconfig_update_keymap(keymap_config);
}
/** \brief eeconfig read audio
*
* FIXME: needs doc
*/
uint8_t eeconfig_read_audio(void) {
return eeprom_read_byte(EECONFIG_AUDIO);
#ifdef AUDIO_ENABLE
void eeconfig_read_audio(audio_config_t *audio_config) {
nvm_eeconfig_read_audio(audio_config);
}
/** \brief eeconfig update audio
*
* FIXME: needs doc
*/
void eeconfig_update_audio(uint8_t val) {
eeprom_update_byte(EECONFIG_AUDIO, val);
void eeconfig_update_audio(const audio_config_t *audio_config) {
nvm_eeconfig_update_audio(audio_config);
}
#endif // AUDIO_ENABLE
#ifdef UNICODE_COMMON_ENABLE
void eeconfig_read_unicode_mode(unicode_config_t *unicode_config) {
return nvm_eeconfig_read_unicode_mode(unicode_config);
}
void eeconfig_update_unicode_mode(const unicode_config_t *unicode_config) {
nvm_eeconfig_update_unicode_mode(unicode_config);
}
#endif // UNICODE_COMMON_ENABLE
#ifdef BACKLIGHT_ENABLE
void eeconfig_read_backlight(backlight_config_t *backlight_config) {
nvm_eeconfig_read_backlight(backlight_config);
}
void eeconfig_update_backlight(const backlight_config_t *backlight_config) {
nvm_eeconfig_update_backlight(backlight_config);
}
#endif // BACKLIGHT_ENABLE
#ifdef STENO_ENABLE
uint8_t eeconfig_read_steno_mode(void) {
return nvm_eeconfig_read_steno_mode();
}
void eeconfig_update_steno_mode(uint8_t val) {
nvm_eeconfig_update_steno_mode(val);
}
#endif // STENO_ENABLE
#ifdef RGB_MATRIX_ENABLE
void eeconfig_read_rgb_matrix(rgb_config_t *rgb_matrix_config) {
nvm_eeconfig_read_rgb_matrix(rgb_matrix_config);
}
void eeconfig_update_rgb_matrix(const rgb_config_t *rgb_matrix_config) {
nvm_eeconfig_update_rgb_matrix(rgb_matrix_config);
}
#endif // RGB_MATRIX_ENABLE
#ifdef LED_MATRIX_ENABLE
void eeconfig_read_led_matrix(led_eeconfig_t *led_matrix_config) {
nvm_eeconfig_read_led_matrix(led_matrix_config);
}
void eeconfig_update_led_matrix(const led_eeconfig_t *led_matrix_config) {
nvm_eeconfig_update_led_matrix(led_matrix_config);
}
#endif // LED_MATRIX_ENABLE
#ifdef RGBLIGHT_ENABLE
void eeconfig_read_rgblight(rgblight_config_t *rgblight_config) {
nvm_eeconfig_read_rgblight(rgblight_config);
}
void eeconfig_update_rgblight(const rgblight_config_t *rgblight_config) {
nvm_eeconfig_update_rgblight(rgblight_config);
}
#endif // RGBLIGHT_ENABLE
#if (EECONFIG_KB_DATA_SIZE) == 0
/** \brief eeconfig read kb
*
* FIXME: needs doc
*/
uint32_t eeconfig_read_kb(void) {
return eeprom_read_dword(EECONFIG_KEYBOARD);
return nvm_eeconfig_read_kb();
}
/** \brief eeconfig update kb
*
* FIXME: needs doc
*/
void eeconfig_update_kb(uint32_t val) {
eeprom_update_dword(EECONFIG_KEYBOARD, val);
nvm_eeconfig_update_kb(val);
}
#endif // (EECONFIG_KB_DATA_SIZE) == 0
#if (EECONFIG_USER_DATA_SIZE) == 0
/** \brief eeconfig read user
*
* FIXME: needs doc
*/
uint32_t eeconfig_read_user(void) {
return eeprom_read_dword(EECONFIG_USER);
return nvm_eeconfig_read_user();
}
/** \brief eeconfig update user
*
* FIXME: needs doc
*/
void eeconfig_update_user(uint32_t val) {
eeprom_update_dword(EECONFIG_USER, val);
nvm_eeconfig_update_user(val);
}
#endif // (EECONFIG_USER_DATA_SIZE) == 0
/** \brief eeconfig read haptic
*
* FIXME: needs doc
*/
uint32_t eeconfig_read_haptic(void) {
return eeprom_read_dword(EECONFIG_HAPTIC);
#ifdef HAPTIC_ENABLE
void eeconfig_read_haptic(haptic_config_t *haptic_config) {
nvm_eeconfig_read_haptic(haptic_config);
}
/** \brief eeconfig update haptic
*
* FIXME: needs doc
*/
void eeconfig_update_haptic(uint32_t val) {
eeprom_update_dword(EECONFIG_HAPTIC, val);
void eeconfig_update_haptic(const haptic_config_t *haptic_config) {
nvm_eeconfig_update_haptic(haptic_config);
}
#endif // HAPTIC_ENABLE
/** \brief eeconfig read split handedness
*
* FIXME: needs doc
*/
#ifdef CONNECTION_ENABLE
void eeconfig_read_connection(connection_config_t *config) {
nvm_eeconfig_read_connection(config);
}
void eeconfig_update_connection(const connection_config_t *config) {
nvm_eeconfig_update_connection(config);
}
#endif // CONNECTION_ENABLE
bool eeconfig_read_handedness(void) {
return !!eeprom_read_byte(EECONFIG_HANDEDNESS);
return nvm_eeconfig_read_handedness();
}
/** \brief eeconfig update split handedness
*
* FIXME: needs doc
*/
void eeconfig_update_handedness(bool val) {
eeprom_update_byte(EECONFIG_HANDEDNESS, !!val);
nvm_eeconfig_update_handedness(val);
}
#if (EECONFIG_KB_DATA_SIZE) > 0
/** \brief eeconfig assert keyboard data block version
*
* FIXME: needs doc
*/
bool eeconfig_is_kb_datablock_valid(void) {
return eeprom_read_dword(EECONFIG_KEYBOARD) == (EECONFIG_KB_DATA_VERSION);
return nvm_eeconfig_is_kb_datablock_valid();
}
/** \brief eeconfig read keyboard data block
*
* FIXME: needs doc
*/
void eeconfig_read_kb_datablock(void *data) {
if (eeconfig_is_kb_datablock_valid()) {
eeprom_read_block(data, EECONFIG_KB_DATABLOCK, (EECONFIG_KB_DATA_SIZE));
} else {
memset(data, 0, (EECONFIG_KB_DATA_SIZE));
}
uint32_t eeconfig_read_kb_datablock(void *data, uint32_t offset, uint32_t length) {
return nvm_eeconfig_read_kb_datablock(data, offset, length);
}
/** \brief eeconfig update keyboard data block
*
* FIXME: needs doc
*/
void eeconfig_update_kb_datablock(const void *data) {
eeprom_update_dword(EECONFIG_KEYBOARD, (EECONFIG_KB_DATA_VERSION));
eeprom_update_block(data, EECONFIG_KB_DATABLOCK, (EECONFIG_KB_DATA_SIZE));
uint32_t eeconfig_update_kb_datablock(const void *data, uint32_t offset, uint32_t length) {
return nvm_eeconfig_update_kb_datablock(data, offset, length);
}
/** \brief eeconfig init keyboard data block
*
* FIXME: needs doc
*/
__attribute__((weak)) void eeconfig_init_kb_datablock(void) {
uint8_t dummy_kb[(EECONFIG_KB_DATA_SIZE)] = {0};
eeconfig_update_kb_datablock(dummy_kb);
nvm_eeconfig_init_kb_datablock();
}
#endif // (EECONFIG_KB_DATA_SIZE) > 0
#if (EECONFIG_USER_DATA_SIZE) > 0
/** \brief eeconfig assert user data block version
*
* FIXME: needs doc
*/
bool eeconfig_is_user_datablock_valid(void) {
return eeprom_read_dword(EECONFIG_USER) == (EECONFIG_USER_DATA_VERSION);
return nvm_eeconfig_is_user_datablock_valid();
}
/** \brief eeconfig read user data block
*
* FIXME: needs doc
*/
void eeconfig_read_user_datablock(void *data) {
if (eeconfig_is_user_datablock_valid()) {
eeprom_read_block(data, EECONFIG_USER_DATABLOCK, (EECONFIG_USER_DATA_SIZE));
} else {
memset(data, 0, (EECONFIG_USER_DATA_SIZE));
}
uint32_t eeconfig_read_user_datablock(void *data, uint32_t offset, uint32_t length) {
return nvm_eeconfig_read_user_datablock(data, offset, length);
}
/** \brief eeconfig update user data block
*
* FIXME: needs doc
*/
void eeconfig_update_user_datablock(const void *data) {
eeprom_update_dword(EECONFIG_USER, (EECONFIG_USER_DATA_VERSION));
eeprom_update_block(data, EECONFIG_USER_DATABLOCK, (EECONFIG_USER_DATA_SIZE));
uint32_t eeconfig_update_user_datablock(const void *data, uint32_t offset, uint32_t length) {
return nvm_eeconfig_update_user_datablock(data, offset, length);
}
/** \brief eeconfig init user data block
*
* FIXME: needs doc
*/
__attribute__((weak)) void eeconfig_init_user_datablock(void) {
uint8_t dummy_user[(EECONFIG_USER_DATA_SIZE)] = {0};
eeconfig_update_user_datablock(dummy_user);
nvm_eeconfig_init_user_datablock();
}
#endif // (EECONFIG_USER_DATA_SIZE) > 0

View file

@ -19,59 +19,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h> // offsetof
#include "eeprom.h"
#include "util.h"
#include <stddef.h> // offsetof
#include "action_layer.h" // layer_state_t
#ifndef EECONFIG_MAGIC_NUMBER
# define EECONFIG_MAGIC_NUMBER (uint16_t)0xFEE5 // When changing, decrement this value to avoid future re-init issues
#endif
#define EECONFIG_MAGIC_NUMBER_OFF (uint16_t)0xFFFF
// Dummy struct only used to calculate offsets
typedef struct PACKED {
uint16_t magic;
uint8_t debug;
uint8_t default_layer;
uint16_t keymap;
uint8_t backlight;
uint8_t audio;
uint32_t rgblight;
uint8_t unicode;
uint8_t steno;
uint8_t handedness;
uint32_t keyboard;
uint32_t user;
union { // Mutually exclusive
uint32_t led_matrix;
uint64_t rgb_matrix;
};
uint32_t haptic;
uint8_t rgblight_ext;
} eeprom_core_t;
/* EEPROM parameter address */
#define EECONFIG_MAGIC (uint16_t *)(offsetof(eeprom_core_t, magic))
#define EECONFIG_DEBUG (uint8_t *)(offsetof(eeprom_core_t, debug))
#define EECONFIG_DEFAULT_LAYER (uint8_t *)(offsetof(eeprom_core_t, default_layer))
#define EECONFIG_KEYMAP (uint16_t *)(offsetof(eeprom_core_t, keymap))
#define EECONFIG_BACKLIGHT (uint8_t *)(offsetof(eeprom_core_t, backlight))
#define EECONFIG_AUDIO (uint8_t *)(offsetof(eeprom_core_t, audio))
#define EECONFIG_RGBLIGHT (uint32_t *)(offsetof(eeprom_core_t, rgblight))
#define EECONFIG_UNICODEMODE (uint8_t *)(offsetof(eeprom_core_t, unicode))
#define EECONFIG_STENOMODE (uint8_t *)(offsetof(eeprom_core_t, steno))
#define EECONFIG_HANDEDNESS (uint8_t *)(offsetof(eeprom_core_t, handedness))
#define EECONFIG_KEYBOARD (uint32_t *)(offsetof(eeprom_core_t, keyboard))
#define EECONFIG_USER (uint32_t *)(offsetof(eeprom_core_t, user))
#define EECONFIG_LED_MATRIX (uint32_t *)(offsetof(eeprom_core_t, led_matrix))
#define EECONFIG_RGB_MATRIX (uint64_t *)(offsetof(eeprom_core_t, rgb_matrix))
#define EECONFIG_HAPTIC (uint32_t *)(offsetof(eeprom_core_t, haptic))
#define EECONFIG_RGBLIGHT_EXTENDED (uint8_t *)(offsetof(eeprom_core_t, rgblight_ext))
// Size of EEPROM being used for core data storage
#define EECONFIG_BASE_SIZE ((uint8_t)sizeof(eeprom_core_t))
// Size of EEPROM dedicated to keyboard- and user-specific data
#ifndef EECONFIG_KB_DATA_SIZE
# define EECONFIG_KB_DATA_SIZE 0
@ -86,12 +36,6 @@ typedef struct PACKED {
# define EECONFIG_USER_DATA_VERSION (EECONFIG_USER_DATA_SIZE)
#endif
#define EECONFIG_KB_DATABLOCK ((uint8_t *)(EECONFIG_BASE_SIZE))
#define EECONFIG_USER_DATABLOCK ((uint8_t *)((EECONFIG_BASE_SIZE) + (EECONFIG_KB_DATA_SIZE)))
// Size of EEPROM being used, other code can refer to this for available EEPROM
#define EECONFIG_SIZE ((EECONFIG_BASE_SIZE) + (EECONFIG_KB_DATA_SIZE) + (EECONFIG_USER_DATA_SIZE))
/* debug bit */
#define EECONFIG_DEBUG_ENABLE (1 << 0)
#define EECONFIG_DEBUG_MATRIX (1 << 1)
@ -117,22 +61,59 @@ void eeconfig_init_kb(void);
void eeconfig_init_user(void);
void eeconfig_enable(void);
void eeconfig_disable(void);
uint8_t eeconfig_read_debug(void);
void eeconfig_update_debug(uint8_t val);
typedef union debug_config_t debug_config_t;
void eeconfig_read_debug(debug_config_t *debug_config) __attribute__((nonnull));
void eeconfig_update_debug(const debug_config_t *debug_config) __attribute__((nonnull));
layer_state_t eeconfig_read_default_layer(void);
void eeconfig_update_default_layer(layer_state_t val);
void eeconfig_update_default_layer(layer_state_t state);
uint16_t eeconfig_read_keymap(void);
void eeconfig_update_keymap(uint16_t val);
typedef union keymap_config_t keymap_config_t;
void eeconfig_read_keymap(keymap_config_t *keymap_config) __attribute__((nonnull));
void eeconfig_update_keymap(const keymap_config_t *keymap_config) __attribute__((nonnull));
#ifdef AUDIO_ENABLE
uint8_t eeconfig_read_audio(void);
void eeconfig_update_audio(uint8_t val);
#endif
typedef union audio_config_t audio_config_t;
void eeconfig_read_audio(audio_config_t *audio_config) __attribute__((nonnull));
void eeconfig_update_audio(const audio_config_t *audio_config) __attribute__((nonnull));
#endif // AUDIO_ENABLE
#ifdef UNICODE_COMMON_ENABLE
typedef union unicode_config_t unicode_config_t;
void eeconfig_read_unicode_mode(unicode_config_t *unicode_config) __attribute__((nonnull));
void eeconfig_update_unicode_mode(const unicode_config_t *unicode_config) __attribute__((nonnull));
#endif // UNICODE_COMMON_ENABLE
#ifdef BACKLIGHT_ENABLE
typedef union backlight_config_t backlight_config_t;
void eeconfig_read_backlight(backlight_config_t *backlight_config) __attribute__((nonnull));
void eeconfig_update_backlight(const backlight_config_t *backlight_config) __attribute__((nonnull));
#endif // BACKLIGHT_ENABLE
#ifdef STENO_ENABLE
uint8_t eeconfig_read_steno_mode(void);
void eeconfig_update_steno_mode(uint8_t val);
#endif // STENO_ENABLE
#ifdef RGB_MATRIX_ENABLE
typedef union rgb_config_t rgb_config_t;
void eeconfig_read_rgb_matrix(rgb_config_t *rgb_matrix_config) __attribute__((nonnull));
void eeconfig_update_rgb_matrix(const rgb_config_t *rgb_matrix_config) __attribute__((nonnull));
#endif // RGB_MATRIX_ENABLE
#ifdef LED_MATRIX_ENABLE
typedef union led_eeconfig_t led_eeconfig_t;
void eeconfig_read_led_matrix(led_eeconfig_t *led_matrix_config) __attribute__((nonnull));
void eeconfig_update_led_matrix(const led_eeconfig_t *led_matrix_config) __attribute__((nonnull));
#endif // LED_MATRIX_ENABLE
#ifdef RGBLIGHT_ENABLE
typedef union rgblight_config_t rgblight_config_t;
void eeconfig_read_rgblight(rgblight_config_t *rgblight_config) __attribute__((nonnull));
void eeconfig_update_rgblight(const rgblight_config_t *rgblight_config) __attribute__((nonnull));
#endif // RGBLIGHT_ENABLE
#if (EECONFIG_KB_DATA_SIZE) == 0
uint32_t eeconfig_read_kb(void);
@ -145,31 +126,42 @@ void eeconfig_update_user(uint32_t val);
#endif // (EECONFIG_USER_DATA_SIZE) == 0
#ifdef HAPTIC_ENABLE
uint32_t eeconfig_read_haptic(void);
void eeconfig_update_haptic(uint32_t val);
typedef union haptic_config_t haptic_config_t;
void eeconfig_read_haptic(haptic_config_t *haptic_config) __attribute__((nonnull));
void eeconfig_update_haptic(const haptic_config_t *haptic_config) __attribute__((nonnull));
#endif
#ifdef CONNECTION_ENABLE
typedef union connection_config_t connection_config_t;
void eeconfig_read_connection(connection_config_t *config);
void eeconfig_update_connection(const connection_config_t *config);
#endif
bool eeconfig_read_handedness(void);
void eeconfig_update_handedness(bool val);
#if (EECONFIG_KB_DATA_SIZE) > 0
bool eeconfig_is_kb_datablock_valid(void);
void eeconfig_read_kb_datablock(void *data);
void eeconfig_update_kb_datablock(const void *data);
void eeconfig_init_kb_datablock(void);
bool eeconfig_is_kb_datablock_valid(void);
uint32_t eeconfig_read_kb_datablock(void *data, uint32_t offset, uint32_t length) __attribute__((nonnull));
uint32_t eeconfig_update_kb_datablock(const void *data, uint32_t offset, uint32_t length) __attribute__((nonnull));
void eeconfig_init_kb_datablock(void);
# define eeconfig_read_kb_datablock_field(__object, __field) eeconfig_read_kb_datablock(&(__object.__field), offsetof(typeof(__object), __field), sizeof(__object.__field))
# define eeconfig_update_kb_datablock_field(__object, __field) eeconfig_update_kb_datablock(&(__object.__field), offsetof(typeof(__object), __field), sizeof(__object.__field))
#endif // (EECONFIG_KB_DATA_SIZE) > 0
#if (EECONFIG_USER_DATA_SIZE) > 0
bool eeconfig_is_user_datablock_valid(void);
void eeconfig_read_user_datablock(void *data);
void eeconfig_update_user_datablock(const void *data);
void eeconfig_init_user_datablock(void);
bool eeconfig_is_user_datablock_valid(void);
uint32_t eeconfig_read_user_datablock(void *data, uint32_t offset, uint32_t length) __attribute__((nonnull));
uint32_t eeconfig_update_user_datablock(const void *data, uint32_t offset, uint32_t length) __attribute__((nonnull));
void eeconfig_init_user_datablock(void);
# define eeconfig_read_user_datablock_field(__object, __field) eeconfig_read_user_datablock(&(__object.__field), offsetof(typeof(__object), __field), sizeof(__object.__field))
# define eeconfig_update_user_datablock_field(__object, __field) eeconfig_update_user_datablock(&(__object.__field), offsetof(typeof(__object), __field), sizeof(__object.__field))
#endif // (EECONFIG_USER_DATA_SIZE) > 0
// Any "checked" debounce variant used requires implementation of:
// -- bool eeconfig_check_valid_##name(void)
// -- void eeconfig_post_flush_##name(void)
#define EECONFIG_DEBOUNCE_HELPER_CHECKED(name, offset, config) \
#define EECONFIG_DEBOUNCE_HELPER_CHECKED(name, config) \
static uint8_t dirty_##name = false; \
\
bool eeconfig_check_valid_##name(void); \
@ -178,13 +170,13 @@ void eeconfig_init_user_datablock(void);
static inline void eeconfig_init_##name(void) { \
dirty_##name = true; \
if (eeconfig_check_valid_##name()) { \
eeprom_read_block(&config, offset, sizeof(config)); \
eeconfig_read_##name(&config); \
dirty_##name = false; \
} \
} \
static inline void eeconfig_flush_##name(bool force) { \
if (force || dirty_##name) { \
eeprom_update_block(&config, offset, sizeof(config)); \
eeconfig_update_##name(&config); \
eeconfig_post_flush_##name(); \
dirty_##name = false; \
} \
@ -206,10 +198,10 @@ void eeconfig_init_user_datablock(void);
} \
}
#define EECONFIG_DEBOUNCE_HELPER(name, offset, config) \
EECONFIG_DEBOUNCE_HELPER_CHECKED(name, offset, config) \
\
bool eeconfig_check_valid_##name(void) { \
return true; \
} \
#define EECONFIG_DEBOUNCE_HELPER(name, config) \
EECONFIG_DEBOUNCE_HELPER_CHECKED(name, config) \
\
bool eeconfig_check_valid_##name(void) { \
return true; \
} \
void eeconfig_post_flush_##name(void) {}

View file

@ -67,7 +67,7 @@ void haptic_init(void) {
if (!eeconfig_is_enabled()) {
eeconfig_init();
}
haptic_config.raw = eeconfig_read_haptic();
eeconfig_read_haptic(&haptic_config);
#ifdef HAPTIC_SOLENOID
solenoid_set_dwell(haptic_config.dwell);
#endif
@ -122,13 +122,13 @@ void eeconfig_debug_haptic(void) {
void haptic_enable(void) {
set_haptic_config_enable(true);
dprintf("haptic_config.enable = %u\n", haptic_config.enable);
eeconfig_update_haptic(haptic_config.raw);
eeconfig_update_haptic(&haptic_config);
}
void haptic_disable(void) {
set_haptic_config_enable(false);
dprintf("haptic_config.enable = %u\n", haptic_config.enable);
eeconfig_update_haptic(haptic_config.raw);
eeconfig_update_haptic(&haptic_config);
}
void haptic_toggle(void) {
@ -137,14 +137,14 @@ void haptic_toggle(void) {
} else {
haptic_enable();
}
eeconfig_update_haptic(haptic_config.raw);
eeconfig_update_haptic(&haptic_config);
}
void haptic_feedback_toggle(void) {
haptic_config.feedback++;
if (haptic_config.feedback >= HAPTIC_FEEDBACK_MAX) haptic_config.feedback = KEY_PRESS;
dprintf("haptic_config.feedback = %u\n", !haptic_config.feedback);
eeconfig_update_haptic(haptic_config.raw);
eeconfig_update_haptic(&haptic_config);
}
void haptic_buzz_toggle(void) {
@ -225,26 +225,26 @@ void haptic_reset(void) {
haptic_config.dwell = 0;
haptic_config.buzz = 0;
#endif
eeconfig_update_haptic(haptic_config.raw);
eeconfig_update_haptic(&haptic_config);
dprintf("haptic_config.feedback = %u\n", haptic_config.feedback);
dprintf("haptic_config.mode = %u\n", haptic_config.mode);
}
void haptic_set_feedback(uint8_t feedback) {
haptic_config.feedback = feedback;
eeconfig_update_haptic(haptic_config.raw);
eeconfig_update_haptic(&haptic_config);
dprintf("haptic_config.feedback = %u\n", haptic_config.feedback);
}
void haptic_set_mode(uint8_t mode) {
haptic_config.mode = mode;
eeconfig_update_haptic(haptic_config.raw);
eeconfig_update_haptic(&haptic_config);
dprintf("haptic_config.mode = %u\n", haptic_config.mode);
}
void haptic_set_amplitude(uint8_t amp) {
haptic_config.amplitude = amp;
eeconfig_update_haptic(haptic_config.raw);
eeconfig_update_haptic(&haptic_config);
dprintf("haptic_config.amplitude = %u\n", haptic_config.amplitude);
#ifdef HAPTIC_DRV2605L
drv2605l_amplitude(amp);
@ -253,13 +253,13 @@ void haptic_set_amplitude(uint8_t amp) {
void haptic_set_buzz(uint8_t buzz) {
haptic_config.buzz = buzz;
eeconfig_update_haptic(haptic_config.raw);
eeconfig_update_haptic(&haptic_config);
dprintf("haptic_config.buzz = %u\n", haptic_config.buzz);
}
void haptic_set_dwell(uint8_t dwell) {
haptic_config.dwell = dwell;
eeconfig_update_haptic(haptic_config.raw);
eeconfig_update_haptic(&haptic_config);
dprintf("haptic_config.dwell = %u\n", haptic_config.dwell);
}
@ -291,7 +291,7 @@ uint8_t haptic_get_dwell(void) {
void haptic_enable_continuous(void) {
haptic_config.cont = 1;
dprintf("haptic_config.cont = %u\n", haptic_config.cont);
eeconfig_update_haptic(haptic_config.raw);
eeconfig_update_haptic(&haptic_config);
#ifdef HAPTIC_DRV2605L
drv2605l_rtp_init();
#endif
@ -300,7 +300,7 @@ void haptic_enable_continuous(void) {
void haptic_disable_continuous(void) {
haptic_config.cont = 0;
dprintf("haptic_config.cont = %u\n", haptic_config.cont);
eeconfig_update_haptic(haptic_config.raw);
eeconfig_update_haptic(&haptic_config);
#ifdef HAPTIC_DRV2605L
drv2605l_write(DRV2605L_REG_MODE, 0x00);
#endif

View file

@ -20,6 +20,8 @@
#include <stdint.h>
#include <stdbool.h>
#include "compiler_support.h"
#ifndef HAPTIC_DEFAULT_FEEDBACK
# define HAPTIC_DEFAULT_FEEDBACK 0
#endif
@ -28,7 +30,7 @@
#endif
/* EEPROM config settings */
typedef union {
typedef union haptic_config_t {
uint32_t raw;
struct {
bool enable : 1;
@ -42,7 +44,7 @@ typedef union {
};
} haptic_config_t;
_Static_assert(sizeof(haptic_config_t) == sizeof(uint32_t), "Haptic EECONFIG out of spec.");
STATIC_ASSERT(sizeof(haptic_config_t) == sizeof(uint32_t), "Haptic EECONFIG out of spec.");
typedef enum HAPTIC_FEEDBACK {
KEY_PRESS,

View file

@ -128,6 +128,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifdef SPLIT_KEYBOARD
# include "split_util.h"
#endif
#ifdef BATTERY_DRIVER
# include "battery.h"
#endif
#ifdef BLUETOOTH_ENABLE
# include "bluetooth.h"
#endif
@ -149,6 +152,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifdef LAYER_LOCK_ENABLE
# include "layer_lock.h"
#endif
#ifdef CONNECTION_ENABLE
# include "connection.h"
#endif
static uint32_t last_input_modification_time = 0;
uint32_t last_input_activity_time(void) {
@ -441,8 +447,8 @@ void quantum_init(void) {
}
/* init globals */
debug_config.raw = eeconfig_read_debug();
keymap_config.raw = eeconfig_read_keymap();
eeconfig_read_debug(&debug_config);
eeconfig_read_keymap(&keymap_config);
#ifdef BOOTMAGIC_ENABLE
bootmagic();
@ -474,6 +480,9 @@ void keyboard_init(void) {
#endif
matrix_init();
quantum_init();
#ifdef CONNECTION_ENABLE
connection_init();
#endif
led_init_ports();
#ifdef BACKLIGHT_ENABLE
backlight_init_ports();
@ -512,8 +521,9 @@ void keyboard_init(void) {
steno_init();
#endif
#if defined(NKRO_ENABLE) && defined(FORCE_NKRO)
# pragma message "FORCE_NKRO option is now deprecated - Please migrate to NKRO_DEFAULT_ON instead."
keymap_config.nkro = 1;
eeconfig_update_keymap(keymap_config.raw);
eeconfig_update_keymap(&keymap_config);
#endif
#ifdef DIP_SWITCH_ENABLE
dip_switch_init();
@ -534,6 +544,9 @@ void keyboard_init(void) {
// init after split init
pointing_device_init();
#endif
#ifdef BATTERY_DRIVER
battery_init();
#endif
#ifdef BLUETOOTH_ENABLE
bluetooth_init();
#endif
@ -794,6 +807,10 @@ void keyboard_task(void) {
joystick_task();
#endif
#ifdef BATTERY_DRIVER
battery_task();
#endif
#ifdef BLUETOOTH_ENABLE
bluetooth_task();
#endif

View file

@ -16,9 +16,7 @@
#pragma once
#ifdef __cplusplus
# define _Static_assert static_assert
#endif
#include "compiler_support.h"
#include "eeconfig.h"
#include "keycode.h"
@ -28,7 +26,7 @@ uint16_t keycode_config(uint16_t keycode);
uint8_t mod_config(uint8_t mod);
/* NOTE: Not portable. Bit field order depends on implementation */
typedef union {
typedef union keymap_config_t {
uint16_t raw;
struct {
bool swap_control_capslock : 1;
@ -47,6 +45,6 @@ typedef union {
};
} keymap_config_t;
_Static_assert(sizeof(keymap_config_t) == sizeof(uint16_t), "Keycode (magic) EECONFIG out of spec.");
STATIC_ASSERT(sizeof(keymap_config_t) == sizeof(uint16_t), "Keycode (magic) EECONFIG out of spec.");
extern keymap_config_t keymap_config;

564
quantum/keycode_string.c Normal file
View file

@ -0,0 +1,564 @@
// Copyright 2024-2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "keycode_string.h"
#include <string.h>
#include "bitwise.h"
#include "keycode.h"
#include "progmem.h"
#include "quantum_keycodes.h"
#include "util.h"
typedef int_fast8_t index_t;
// clang-format off
/** Packs a 7-char keycode name, ignoring the third char, as 3 words. */
#define KEYCODE_NAME7(c0, c1, unused_c2, c3, c4, c5, c6) \
((uint16_t)c0) | (((uint16_t)c1) << 8), \
((uint16_t)c3) | (((uint16_t)c4) << 8), \
((uint16_t)c5) | (((uint16_t)c6) << 8)
/**
* @brief Names of some common keycodes.
*
* Each (keycode, name) entry is stored flat in 8 bytes in PROGMEM. Names in
* this table must be at most 7 chars long and have an underscore '_' for the
* third char. This underscore is assumed and not actually stored.
*
* To save memory, feature-specific key entries are ifdef'd to include them only
* when their feature is enabled.
*/
static const uint16_t common_names[] PROGMEM = {
KC_TRNS, KEYCODE_NAME7('K', 'C', '_', 'T', 'R', 'N', 'S'),
KC_ENT , KEYCODE_NAME7('K', 'C', '_', 'E', 'N', 'T', 0 ),
KC_ESC , KEYCODE_NAME7('K', 'C', '_', 'E', 'S', 'C', 0 ),
KC_BSPC, KEYCODE_NAME7('K', 'C', '_', 'B', 'S', 'P', 'C'),
KC_TAB , KEYCODE_NAME7('K', 'C', '_', 'T', 'A', 'B', 0 ),
KC_SPC , KEYCODE_NAME7('K', 'C', '_', 'S', 'P', 'C', 0 ),
KC_MINS, KEYCODE_NAME7('K', 'C', '_', 'M', 'I', 'N', 'S'),
KC_EQL , KEYCODE_NAME7('K', 'C', '_', 'E', 'Q', 'L', 0 ),
KC_LBRC, KEYCODE_NAME7('K', 'C', '_', 'L', 'B', 'R', 'C'),
KC_RBRC, KEYCODE_NAME7('K', 'C', '_', 'R', 'B', 'R', 'C'),
KC_BSLS, KEYCODE_NAME7('K', 'C', '_', 'B', 'S', 'L', 'S'),
KC_NUHS, KEYCODE_NAME7('K', 'C', '_', 'N', 'U', 'H', 'S'),
KC_SCLN, KEYCODE_NAME7('K', 'C', '_', 'S', 'C', 'L', 'N'),
KC_QUOT, KEYCODE_NAME7('K', 'C', '_', 'Q', 'U', 'O', 'T'),
KC_GRV , KEYCODE_NAME7('K', 'C', '_', 'G', 'R', 'V', 0 ),
KC_COMM, KEYCODE_NAME7('K', 'C', '_', 'C', 'O', 'M', 'M'),
KC_DOT , KEYCODE_NAME7('K', 'C', '_', 'D', 'O', 'T', 0 ),
KC_SLSH, KEYCODE_NAME7('K', 'C', '_', 'S', 'L', 'S', 'H'),
KC_CAPS, KEYCODE_NAME7('K', 'C', '_', 'C', 'A', 'P', 'S'),
KC_PSCR, KEYCODE_NAME7('K', 'C', '_', 'P', 'S', 'C', 'R'),
KC_PAUS, KEYCODE_NAME7('K', 'C', '_', 'P', 'A', 'U', 'S'),
KC_INS , KEYCODE_NAME7('K', 'C', '_', 'I', 'N', 'S', 0 ),
KC_HOME, KEYCODE_NAME7('K', 'C', '_', 'H', 'O', 'M', 'E'),
KC_PGUP, KEYCODE_NAME7('K', 'C', '_', 'P', 'G', 'U', 'P'),
KC_DEL , KEYCODE_NAME7('K', 'C', '_', 'D', 'E', 'L', 0 ),
KC_END , KEYCODE_NAME7('K', 'C', '_', 'E', 'N', 'D', 0 ),
KC_PGDN, KEYCODE_NAME7('K', 'C', '_', 'P', 'G', 'D', 'N'),
KC_RGHT, KEYCODE_NAME7('K', 'C', '_', 'R', 'G', 'H', 'T'),
KC_LEFT, KEYCODE_NAME7('K', 'C', '_', 'L', 'E', 'F', 'T'),
KC_DOWN, KEYCODE_NAME7('K', 'C', '_', 'D', 'O', 'W', 'N'),
KC_UP , KEYCODE_NAME7('K', 'C', '_', 'U', 'P', 0 , 0 ),
KC_NUBS, KEYCODE_NAME7('K', 'C', '_', 'N', 'U', 'B', 'S'),
KC_HYPR, KEYCODE_NAME7('K', 'C', '_', 'H', 'Y', 'P', 'R'),
KC_MEH , KEYCODE_NAME7('K', 'C', '_', 'M', 'E', 'H', 0 ),
#ifdef EXTRAKEY_ENABLE
KC_WHOM, KEYCODE_NAME7('K', 'C', '_', 'W', 'H', 'O', 'M'),
KC_WBAK, KEYCODE_NAME7('K', 'C', '_', 'W', 'B', 'A', 'K'),
KC_WFWD, KEYCODE_NAME7('K', 'C', '_', 'W', 'F', 'W', 'D'),
KC_WSTP, KEYCODE_NAME7('K', 'C', '_', 'W', 'S', 'T', 'P'),
KC_WREF, KEYCODE_NAME7('K', 'C', '_', 'W', 'R', 'E', 'F'),
KC_MNXT, KEYCODE_NAME7('K', 'C', '_', 'M', 'N', 'X', 'T'),
KC_MPRV, KEYCODE_NAME7('K', 'C', '_', 'M', 'P', 'R', 'V'),
KC_MPLY, KEYCODE_NAME7('K', 'C', '_', 'M', 'P', 'L', 'Y'),
KC_MUTE, KEYCODE_NAME7('K', 'C', '_', 'M', 'U', 'T', 'E'),
KC_VOLU, KEYCODE_NAME7('K', 'C', '_', 'V', 'O', 'L', 'U'),
KC_VOLD, KEYCODE_NAME7('K', 'C', '_', 'V', 'O', 'L', 'D'),
#endif // EXTRAKEY_ENABLE
#ifdef MOUSEKEY_ENABLE
MS_LEFT, KEYCODE_NAME7('M', 'S', '_', 'L', 'E', 'F', 'T'),
MS_RGHT, KEYCODE_NAME7('M', 'S', '_', 'R', 'G', 'H', 'T'),
MS_UP , KEYCODE_NAME7('M', 'S', '_', 'U', 'P', 0 , 0 ),
MS_DOWN, KEYCODE_NAME7('M', 'S', '_', 'D', 'O', 'W', 'N'),
MS_WHLL, KEYCODE_NAME7('M', 'S', '_', 'W', 'H', 'L', 'L'),
MS_WHLR, KEYCODE_NAME7('M', 'S', '_', 'W', 'H', 'L', 'R'),
MS_WHLU, KEYCODE_NAME7('M', 'S', '_', 'W', 'H', 'L', 'U'),
MS_WHLD, KEYCODE_NAME7('M', 'S', '_', 'W', 'H', 'L', 'D'),
#endif // MOUSEKEY_ENABLE
#ifdef SWAP_HANDS_ENABLE
SH_ON , KEYCODE_NAME7('S', 'H', '_', 'O', 'N', 0 , 0 ),
SH_OFF , KEYCODE_NAME7('S', 'H', '_', 'O', 'F', 'F', 0 ),
SH_MON , KEYCODE_NAME7('S', 'H', '_', 'M', 'O', 'N', 0 ),
SH_MOFF, KEYCODE_NAME7('S', 'H', '_', 'M', 'O', 'F', 'F'),
SH_TOGG, KEYCODE_NAME7('S', 'H', '_', 'T', 'O', 'G', 'G'),
SH_TT , KEYCODE_NAME7('S', 'H', '_', 'T', 'T', 0 , 0 ),
# if !defined(NO_ACTION_ONESHOT)
SH_OS , KEYCODE_NAME7('S', 'H', '_', 'O', 'S', 0 , 0 ),
# endif // !defined(NO_ACTION_ONESHOT)
#endif // SWAP_HANDS_ENABLE
#ifdef LEADER_ENABLE
QK_LEAD, KEYCODE_NAME7('Q', 'K', '_', 'L', 'E', 'A', 'D'),
#endif // LEADER_ENABLE
#ifdef KEY_LOCK_ENABLE
QK_LOCK, KEYCODE_NAME7('Q', 'K', '_', 'L', 'O', 'C', 'K'),
#endif // KEY_LOCK_ENABLE
#ifdef TRI_LAYER_ENABLE
TL_LOWR, KEYCODE_NAME7('T', 'L', '_', 'L', 'O', 'W', 'R'),
TL_UPPR, KEYCODE_NAME7('T', 'L', '_', 'U', 'P', 'P', 'R'),
#endif // TRI_LAYER_ENABLE
#ifdef GRAVE_ESC_ENABLE
QK_GESC, KEYCODE_NAME7('Q', 'K', '_', 'G', 'E', 'S', 'C'),
#endif // GRAVE_ESC_ENABLE
#ifdef CAPS_WORD_ENABLE
CW_TOGG, KEYCODE_NAME7('C', 'W', '_', 'T', 'O', 'G', 'G'),
#endif // CAPS_WORD_ENABLE
#ifdef SECURE_ENABLE
SE_LOCK, KEYCODE_NAME7('S', 'E', '_', 'L', 'O', 'C', 'K'),
SE_UNLK, KEYCODE_NAME7('S', 'E', '_', 'U', 'N', 'L', 'K'),
SE_TOGG, KEYCODE_NAME7('S', 'E', '_', 'T', 'O', 'G', 'G'),
SE_REQ , KEYCODE_NAME7('S', 'E', '_', 'R', 'E', 'Q', 0 ),
#endif // SECURE_ENABLE
#ifdef LAYER_LOCK_ENABLE
QK_LLCK, KEYCODE_NAME7('Q', 'K', '_', 'L', 'L', 'C', 'K'),
#endif // LAYER_LOCK_ENABLE
EE_CLR , KEYCODE_NAME7('E', 'E', '_', 'C', 'L', 'R', 0 ),
QK_BOOT, KEYCODE_NAME7('Q', 'K', '_', 'B', 'O', 'O', 'T'),
DB_TOGG, KEYCODE_NAME7('D', 'B', '_', 'T', 'O', 'G', 'G'),
};
// clang-format on
/** Users can override this to define names of additional keycodes. */
__attribute__((weak)) const keycode_string_name_t* keycode_string_names_data_user = NULL;
__attribute__((weak)) uint16_t keycode_string_names_size_user = 0;
/** Keyboard vendors can override this to define names of additional keycodes. */
__attribute__((weak)) const keycode_string_name_t* keycode_string_names_data_kb = NULL;
__attribute__((weak)) uint16_t keycode_string_names_size_kb = 0;
/** Names of the 4 mods on each hand. */
static const char mod_names[] PROGMEM = "CTL\0SFT\0ALT\0GUI";
/** Internal buffer for holding a stringified keycode. */
static char buffer[32];
#define BUFFER_MAX_LEN (sizeof(buffer) - 1)
static index_t buffer_len;
/** Finds the name of a keycode in `common_names` or returns NULL. */
static const char* search_common_names(uint16_t keycode) {
static uint8_t buffer[8];
for (int_fast16_t offset = 0; offset < ARRAY_SIZE(common_names); offset += 4) {
if (keycode == pgm_read_word(common_names + offset)) {
const uint16_t w0 = pgm_read_word(common_names + offset + 1);
const uint16_t w1 = pgm_read_word(common_names + offset + 2);
const uint16_t w2 = pgm_read_word(common_names + offset + 3);
buffer[0] = (uint8_t)w0;
buffer[1] = (uint8_t)(w0 >> 8);
buffer[2] = '_';
buffer[3] = (uint8_t)w1;
buffer[4] = (uint8_t)(w1 >> 8);
buffer[5] = (uint8_t)w2;
buffer[6] = (uint8_t)(w2 >> 8);
buffer[7] = 0;
return (const char*)buffer;
}
}
return NULL;
}
/**
* @brief Finds the name of a keycode in table or returns NULL.
*
* @param data Pointer to table to be searched.
* @param size Numer of entries in the table.
* @return Name string for the keycode, or NULL if not found.
*/
static const char* search_table(const keycode_string_name_t* data, uint16_t size, uint16_t keycode) {
if (data != NULL) {
for (uint16_t i = 0; i < size; ++i) {
if (data[i].keycode == keycode) {
return data[i].name;
}
}
}
return NULL;
}
/** Formats `number` in `base`, either 10 or 16. */
static char* number_string(uint16_t number, int8_t base) {
static char result[7];
result[sizeof(result) - 1] = '\0';
index_t i = sizeof(result) - 1;
do {
const uint8_t digit = number % base;
number /= base;
result[--i] = (digit < 10) ? (char)(digit + UINT8_C('0')) : (char)(digit + (UINT8_C('A') - 10));
} while (number > 0 && i > 0);
if (base == 16 && i >= 2) {
result[--i] = 'x';
result[--i] = '0';
}
return result + i;
}
/** Appends `str` to `buffer`, truncating if the result would overflow. */
static void append(const char* str) {
char* dest = buffer + buffer_len;
index_t i;
for (i = 0; buffer_len + i < BUFFER_MAX_LEN && str[i]; ++i) {
dest[i] = str[i];
}
buffer_len += i;
buffer[buffer_len] = '\0';
}
/** Same as append(), but where `str` is a PROGMEM string. */
static void append_P(const char* str) {
char* dest = buffer + buffer_len;
index_t i;
for (i = 0; buffer_len + i < BUFFER_MAX_LEN; ++i) {
const char c = pgm_read_byte(&str[i]);
if (c == '\0') {
break;
}
dest[i] = c;
}
buffer_len += i;
buffer[buffer_len] = '\0';
}
/** Appends a single char to `buffer` if there is space. */
static void append_char(char c) {
if (buffer_len < BUFFER_MAX_LEN) {
buffer[buffer_len] = c;
buffer[++buffer_len] = '\0';
}
}
/** Formats `number` in `base`, either 10 or 16, and appends it to `buffer`. */
static void append_number(uint16_t number, int8_t base) {
append(number_string(number, base));
}
/** Stringifies 5-bit mods and appends it to `buffer`. */
static void append_5_bit_mods(uint8_t mods) {
const bool is_rhs = mods > 15;
const uint8_t csag = mods & 15;
if (csag != 0 && (csag & (csag - 1)) == 0) { // One mod is set.
append_P(PSTR("MOD_"));
append_char(is_rhs ? 'R' : 'L');
append_P(&mod_names[4 * biton(csag)]);
} else { // Fallback: write the mod as a hex value.
append_number(mods, 16);
}
}
/**
* @brief Writes a keycode of the format `name` + "(" + `param` + ")".
* @note `name` is a PROGMEM string, `param` is not.
*/
static void append_unary_keycode(const char* name, const char* param) {
append_P(name);
append_char('(');
append(param);
append_char(')');
}
/**
* @brief Writes a keycode of the format `name` + `number`.
* @note `name` is a PROGMEM string.
*/
static void append_numbered_keycode(const char* name, uint16_t number) {
append_P(name);
append_number(number, 10);
}
/** Stringifies `keycode` and appends it to `buffer`. */
static void append_keycode(uint16_t keycode) {
// In case there is overlap among tables, search `keycode_string_names_user`
// first so that it takes precedence.
const char* keycode_name = search_table(keycode_string_names_data_user, keycode_string_names_size_user, keycode);
if (keycode_name) {
append(keycode_name);
return;
}
keycode_name = search_table(keycode_string_names_data_kb, keycode_string_names_size_kb, keycode);
if (keycode_name) {
append(keycode_name);
return;
}
keycode_name = search_common_names(keycode);
if (keycode_name) {
append(keycode_name);
return;
}
if (keycode <= 255) { // Basic keycodes.
switch (keycode) {
// Modifiers KC_LSFT, KC_RCTL, etc.
case MODIFIER_KEYCODE_RANGE: {
const uint8_t i = keycode - KC_LCTL;
const bool is_rhs = i > 3;
append_P(PSTR("KC_"));
append_char(is_rhs ? 'R' : 'L');
append_P(&mod_names[4 * (i & 3)]);
}
return;
// Letters A-Z.
case KC_A ... KC_Z:
append_P(PSTR("KC_"));
append_char((char)(keycode + (UINT8_C('A') - KC_A)));
return;
// Digits 0-9 (NOTE: Unlike the ASCII order, KC_0 comes *after* KC_9.)
case KC_1 ... KC_0:
append_numbered_keycode(PSTR("KC_"), (keycode - (KC_1 - 1)) % 10);
return;
// Keypad digits.
case KC_KP_1 ... KC_KP_0:
append_numbered_keycode(PSTR("KC_KP_"), (keycode - (KC_KP_1 - 1)) % 10);
return;
// Function keys. F1-F12 and F13-F24 are coded in separate ranges.
case KC_F1 ... KC_F12:
append_numbered_keycode(PSTR("KC_F"), keycode - (KC_F1 - 1));
return;
case KC_F13 ... KC_F24:
append_numbered_keycode(PSTR("KC_F"), keycode - (KC_F13 - 13));
return;
}
}
// clang-format off
switch (keycode) {
// A modified keycode, like S(KC_1) for Shift + 1 = !. This implementation
// only covers modified keycodes where one modifier is applied, e.g. a
// Ctrl + Shift + kc or Hyper + kc keycode is not formatted.
case QK_MODS ... QK_MODS_MAX: {
uint8_t mods = QK_MODS_GET_MODS(keycode);
const bool is_rhs = mods > 15;
mods &= 15;
if (mods != 0 && (mods & (mods - 1)) == 0) { // One mod is set.
const char* name = &mod_names[4 * biton(mods)];
if (is_rhs) {
append_char('R');
append_P(name);
} else {
append_char(pgm_read_byte(&name[0]));
}
append_char('(');
append_keycode(QK_MODS_GET_BASIC_KEYCODE(keycode));
append_char(')');
return;
}
} break;
#if !defined(NO_ACTION_ONESHOT)
case QK_ONE_SHOT_MOD ... QK_ONE_SHOT_MOD_MAX: // One-shot mod OSM(mod) key.
append_P(PSTR("OSM("));
append_5_bit_mods(QK_ONE_SHOT_MOD_GET_MODS(keycode));
append_char(')');
return;
#endif // !defined(NO_ACTION_ONESHOT)
// Various layer switch keys.
case QK_LAYER_TAP ... QK_LAYER_TAP_MAX: // Layer-tap LT(layer,kc) key.
append_P(PSTR("LT("));
append_number(QK_LAYER_TAP_GET_LAYER(keycode), 10);
append_char(',');
append_keycode(QK_LAYER_TAP_GET_TAP_KEYCODE(keycode));
append_char(')');
return;
case QK_LAYER_MOD ... QK_LAYER_MOD_MAX: // LM(layer,mod) key.
append_P(PSTR("LM("));
append_number(QK_LAYER_MOD_GET_LAYER(keycode), 10);
append_char(',');
append_5_bit_mods(QK_LAYER_MOD_GET_MODS(keycode));
append_char(')');
return;
case QK_TO ... QK_TO_MAX: // TO(layer) key.
append_unary_keycode(PSTR("TO"), number_string(QK_TO_GET_LAYER(keycode), 10));
return;
case QK_MOMENTARY ... QK_MOMENTARY_MAX: // MO(layer) key.
append_unary_keycode(PSTR("MO"), number_string(QK_MOMENTARY_GET_LAYER(keycode), 10));
return;
case QK_DEF_LAYER ... QK_DEF_LAYER_MAX: // DF(layer) key.
append_unary_keycode(PSTR("DF"), number_string(QK_DEF_LAYER_GET_LAYER(keycode), 10));
return;
case QK_TOGGLE_LAYER ... QK_TOGGLE_LAYER_MAX: // TG(layer) key.
append_unary_keycode(PSTR("TG"), number_string(QK_TOGGLE_LAYER_GET_LAYER(keycode), 10));
return;
#if !defined(NO_ACTION_ONESHOT)
case QK_ONE_SHOT_LAYER ... QK_ONE_SHOT_LAYER_MAX: // OSL(layer) key.
append_unary_keycode(PSTR("OSL"), number_string(QK_ONE_SHOT_LAYER_GET_LAYER(keycode), 10));
return;
#endif // !defined(NO_ACTION_ONESHOT)
case QK_LAYER_TAP_TOGGLE ... QK_LAYER_TAP_TOGGLE_MAX: // TT(layer) key.
append_unary_keycode(PSTR("TT"), number_string(QK_LAYER_TAP_TOGGLE_GET_LAYER(keycode), 10));
return;
case QK_PERSISTENT_DEF_LAYER ... QK_PERSISTENT_DEF_LAYER_MAX: // PDF(layer) key.
append_unary_keycode(PSTR("PDF"), number_string(QK_PERSISTENT_DEF_LAYER_GET_LAYER(keycode), 10));
return;
// Mod-tap MT(mod,kc) key. This implementation formats the MT keys where
// one modifier is applied. For MT keys with multiple modifiers, the mod
// arg is written numerically as a hex code.
case QK_MOD_TAP ... QK_MOD_TAP_MAX: {
uint8_t mods = QK_MOD_TAP_GET_MODS(keycode);
const bool is_rhs = mods > 15;
const uint8_t csag = mods & 15;
if (csag != 0 && (csag & (csag - 1)) == 0) { // One mod is set.
append_char(is_rhs ? 'R' : 'L');
append_P(&mod_names[4 * biton(csag)]);
append_P(PSTR("_T("));
} else if (mods == MOD_HYPR) {
append_P(PSTR("HYPR_T("));
} else if (mods == MOD_MEH) {
append_P(PSTR("MEH_T("));
} else {
append_P(PSTR("MT("));
append_number(mods, 16);
append_char(',');
}
append_keycode(QK_MOD_TAP_GET_TAP_KEYCODE(keycode));
append_char(')');
} return;
case QK_TAP_DANCE ... QK_TAP_DANCE_MAX: // Tap dance TD(i) key.
append_unary_keycode(PSTR("TD"), number_string(QK_TAP_DANCE_GET_INDEX(keycode), 10));
return;
#ifdef UNICODE_ENABLE
case QK_UNICODE ... QK_UNICODE_MAX: // Unicode UC(codepoint) key.
append_unary_keycode(PSTR("UC"), number_string(QK_UNICODE_GET_CODE_POINT(keycode), 16));
return;
#elif defined(UNICODEMAP_ENABLE)
case QK_UNICODEMAP ... QK_UNICODEMAP_MAX: // Unicode Map UM(i) key.
append_unary_keycode(PSTR("UM"), number_string(QK_UNICODEMAP_GET_INDEX(keycode), 10));
return;
case QK_UNICODEMAP_PAIR ... QK_UNICODEMAP_PAIR_MAX: { // UP(i,j) key.
const uint8_t i = QK_UNICODEMAP_PAIR_GET_UNSHIFTED_INDEX(keycode);
const uint8_t j = QK_UNICODEMAP_PAIR_GET_SHIFTED_INDEX(keycode);
append_P(PSTR("UP("));
append_number(i, 10);
append_char(',');
append_number(j, 10);
append_char(')');
} return;
#endif
#ifdef MOUSEKEY_ENABLE
case MS_BTN1 ... MS_BTN8: // Mouse button keycode.
append_numbered_keycode(PSTR("MS_BTN"), keycode - (MS_BTN1 - 1));
return;
#endif // MOUSEKEY_ENABLE
#ifdef SWAP_HANDS_ENABLE
case QK_SWAP_HANDS ... QK_SWAP_HANDS_MAX: // Swap Hands SH_T(kc) key.
if (!IS_SWAP_HANDS_KEYCODE(keycode)) {
append_P(PSTR("SH_T("));
append_keycode(QK_SWAP_HANDS_GET_TAP_KEYCODE(keycode));
append_char(')');
return;
}
break;
#endif // SWAP_HANDS_ENABLE
#ifdef JOYSTICK_ENABLE
case JOYSTICK_KEYCODE_RANGE: // Joystick JS_ key.
append_numbered_keycode(PSTR("JS_"), keycode - JS_0);
return;
#endif // JOYSTICK_ENABLE
#ifdef PROGRAMMABLE_BUTTON_ENABLE
case PROGRAMMABLE_BUTTON_KEYCODE_RANGE: // Programmable button PB_ key.
append_numbered_keycode(PSTR("PB_"), keycode - (PB_1 - 1));
return;
#endif // PROGRAMMABLE_BUTTON_ENABLE
case MACRO_KEYCODE_RANGE: // Macro range MC_ keycode.
append_numbered_keycode(PSTR("MC_"), keycode - MC_0);
return;
case KB_KEYCODE_RANGE: // Keyboard range keycode.
append_numbered_keycode(PSTR("QK_KB_"), keycode - QK_KB_0);
return;
case USER_KEYCODE_RANGE: // User range keycode.
append_numbered_keycode(PSTR("QK_USER_"), keycode - QK_USER_0);
return;
// It would take a nontrivial amount of string data to cover some
// feature-specific keycodes, such as those for MIDI and lighting. As a
// fallback while still providing some information, we stringify
// remaining keys in known code ranges as "QK_<feature>+<number>".
#ifdef MAGIC_ENABLE
case MAGIC_KEYCODE_RANGE:
append_numbered_keycode(PSTR("QK_MAGIC+"), keycode - QK_MAGIC);
return;
#endif // MAGIC_ENABLE
#ifdef MIDI_ENABLE
case MIDI_KEYCODE_RANGE:
append_numbered_keycode(PSTR("QK_MIDI+"), keycode - QK_MIDI);
return;
#endif // MIDI_ENABLE
#ifdef SEQUENCER_ENABLE
case SEQUENCER_KEYCODE_RANGE:
append_numbered_keycode(PSTR("QK_SEQUENCER+"), keycode - QK_SEQUENCER);
return;
#endif // SEQUENCER_ENABLE
#ifdef AUDIO_ENABLE
case AUDIO_KEYCODE_RANGE:
append_numbered_keycode(PSTR("QK_AUDIO+"), keycode - QK_AUDIO);
return;
#endif // AUDIO_ENABLE
#if defined(BACKLIGHT_ENABLE) || defined(LED_MATRIX_ENABLE) || defined(RGBLIGHT_ENABLED) || defined(RGB_MATRIX_ENABLE) // Lighting-related features.
case QK_LIGHTING ... QK_LIGHTING_MAX:
append_numbered_keycode(PSTR("QK_LIGHTING+"), keycode - QK_LIGHTING);
return;
#endif // defined(BACKLIGHT_ENABLE) || defined(LED_MATRIX_ENABLE) || defined(RGBLIGHT_ENABLED) || defined(RGB_MATRIX_ENABLE)
#ifdef STENO_ENABLE
case STENO_KEYCODE_RANGE:
append_numbered_keycode(PSTR("QK_STENO+"), keycode - QK_STENO);
return;
#endif // AUDIO_ENABLE
#ifdef BLUETOOTH_ENABLE
case CONNECTION_KEYCODE_RANGE:
append_numbered_keycode(PSTR("QK_CONNECTION+"), keycode - QK_CONNECTION);
return;
#endif // BLUETOOTH_ENABLE
case QUANTUM_KEYCODE_RANGE:
append_numbered_keycode(PSTR("QK_QUANTUM+"), keycode - QK_QUANTUM);
return;
}
// clang-format on
append_number(keycode, 16); // Fallback: write keycode as hex value.
}
const char* get_keycode_string(uint16_t keycode) {
buffer_len = 0;
buffer[0] = '\0';
append_keycode(keycode);
return buffer;
}

134
quantum/keycode_string.h Normal file
View file

@ -0,0 +1,134 @@
// Copyright 2024-2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#include <stdint.h>
#if KEYCODE_STRING_ENABLE
/**
* @brief Formats a QMK keycode as a human-readable string.
*
* Given a keycode, like `KC_A`, this function returns a formatted string, like
* "KC_A". This is useful for debugging and diagnostics so that keys are more
* easily identified than they would be by raw numerical codes.
*
* @note The returned char* string should be used right away. The string memory
* is reused and will be overwritten by the next call to `keycode_string()`.
*
* Many common QMK keycodes are understood by this function, but not all.
* Recognized keycodes include:
*
* - Most basic keycodes, including letters `KC_A` - `KC_Z`, digits `KC_0` -
* `KC_9`, function keys `KC_F1` - `KC_F24`, and modifiers like `KC_LSFT`.
*
* - Modified basic keycodes, like `S(KC_1)` (Shift + 1 = !).
*
* - `MO`, `TO`, `TG`, `OSL`, `LM(layer,mod)`, `LT(layer,kc)` layer switches.
*
* - One-shot mod `OSM(mod)` keycodes.
*
* - Mod-tap `MT(mod, kc)` keycodes.
*
* - Tap dance keycodes `TD(i)`.
*
* - Swap hands keycodes `SH_T(kc)`, `SH_TOGG`, etc.
*
* - Joystick keycodes `JS_n`.
*
* - Programmable button keycodes `PB_n`.
*
* - Unicode `UC(codepoint)` and Unicode Map `UM(i)` and `UP(i,j)` keycodes.
*
* - Keyboard range keycodes `QK_KB_*`.
*
* - User range (SAFE_RANGE) keycodes `QK_USER_*`.
*
* Keycodes involving mods like `OSM`, `LM`, `MT` are fully supported only where
* a single mod is applied.
*
* Unrecognized keycodes are printed numerically as hex values like `0x1ABC`.
*
* Optionally, use `keycode_string_names_user` or `keycode_string_names_kb` to
* define names for additional keycodes or override how any of the above are
* formatted.
*
* @param keycode QMK keycode.
* @return Stringified keycode.
*/
const char* get_keycode_string(uint16_t keycode);
/** Defines a human-readable name for a keycode. */
typedef struct {
uint16_t keycode;
const char* name;
} keycode_string_name_t;
// clang-format off
/**
* @brief Defines names for additional keycodes for `get_keycode_string()`.
*
* Define `KEYCODE_STRING_NAMES_USER` in your keymap.c to add names for
* additional keycodes to `keycode_string()`. This table may also be used to
* override how `keycode_string()` formats a keycode. For example, supposing
* keymap.c defines `MYMACRO1` and `MYMACRO2` as custom keycodes:
*
* KEYCODE_STRING_NAMES_USER(
* KEYCODE_STRING_NAME(MYMACRO1),
* KEYCODE_STRING_NAME(MYMACRO2),
* KEYCODE_STRING_NAME(KC_EXLM),
* );
*
* The above defines names for `MYMACRO1` and `MYMACRO2`, and overrides
* `KC_EXLM` to format as "KC_EXLM" instead of the default "S(KC_1)".
*/
# define KEYCODE_STRING_NAMES_USER(...) \
static const keycode_string_name_t keycode_string_names_user[] = {__VA_ARGS__}; \
uint16_t keycode_string_names_size_user = \
sizeof(keycode_string_names_user) / sizeof(keycode_string_name_t); \
const keycode_string_name_t* keycode_string_names_data_user = \
keycode_string_names_user
/** Same as above, but defines keycode string names at the keyboard level. */
# define KEYCODE_STRING_NAMES_KB(...) \
static const keycode_string_name_t keycode_string_names_kb[] = {__VA_ARGS__}; \
uint16_t keycode_string_names_size_kb = \
sizeof(keycode_string_names_kb) / sizeof(keycode_string_name_t); \
const keycode_string_name_t* keycode_string_names_data_kb = \
keycode_string_names_kb
/** Helper to define a keycode_string_name_t. */
# define KEYCODE_STRING_NAME(kc) \
{ (kc), #kc }
// clang-format on
extern const keycode_string_name_t* keycode_string_names_data_user;
extern uint16_t keycode_string_names_size_user;
extern const keycode_string_name_t* keycode_string_names_data_kb;
extern uint16_t keycode_string_names_size_kb;
#else
// When keycode_string is disabled, fall back to printing keycodes numerically
// as decimal values, using get_u16_str() from quantum.c.
# define get_keycode_string(kc) get_u16_str(kc, ' ')
const char* get_u16_str(uint16_t curr_num, char curr_pad);
# define KEYCODE_STRING_NAMES_USER(...)
# define KEYCODE_STRING_NAMES_KB(...)
# define KEYCODE_STRING_NAME(kc)
#endif // KEYCODE_STRING_ENABLE

View file

@ -26,6 +26,12 @@
#pragma once
// clang-format off
#define QMK_KEYCODES_VERSION "0.0.7"
#define QMK_KEYCODES_VERSION_BCD 0x00000007
#define QMK_KEYCODES_VERSION_MAJOR 0
#define QMK_KEYCODES_VERSION_MINOR 0
#define QMK_KEYCODES_VERSION_PATCH 7
enum qk_keycode_ranges {
// Ranges
QK_BASIC = 0x0000,

View file

@ -160,7 +160,7 @@ action_t action_for_keycode(uint16_t keycode) {
case QK_LAYER_MOD ... QK_LAYER_MOD_MAX:
mod = mod_config(QK_LAYER_MOD_GET_MODS(keycode));
action_layer = QK_LAYER_MOD_GET_LAYER(keycode);
action.code = ACTION_LAYER_MODS(action_layer, (mod & 0x10) ? mod << 4 : mod);
action.code = ACTION_LAYER_MODS(action_layer, (mod & 0x10) ? (mod & 0xF) << 4 : mod);
break;
#endif // NO_ACTION_LAYER
case QK_MOD_TAP ... QK_MOD_TAP_MAX:

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_BELGIAN_KEYCODES_VERSION "0.0.1"
#define QMK_BELGIAN_KEYCODES_VERSION_BCD 0x00000001
#define QMK_BELGIAN_KEYCODES_VERSION_MAJOR 0
#define QMK_BELGIAN_KEYCODES_VERSION_MINOR 0
#define QMK_BELGIAN_KEYCODES_VERSION_PATCH 1
// Aliases
#define BE_SUP2 KC_GRV // ²
#define BE_AMPR KC_1 // &

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_BEPO_KEYCODES_VERSION "0.0.1"
#define QMK_BEPO_KEYCODES_VERSION_BCD 0x00000001
#define QMK_BEPO_KEYCODES_VERSION_MAJOR 0
#define QMK_BEPO_KEYCODES_VERSION_MINOR 0
#define QMK_BEPO_KEYCODES_VERSION_PATCH 1
// Aliases
#define BP_DLR KC_GRV // $
#define BP_DQUO KC_1 // "

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_BRAZILIAN_ABNT2_KEYCODES_VERSION "0.0.1"
#define QMK_BRAZILIAN_ABNT2_KEYCODES_VERSION_BCD 0x00000001
#define QMK_BRAZILIAN_ABNT2_KEYCODES_VERSION_MAJOR 0
#define QMK_BRAZILIAN_ABNT2_KEYCODES_VERSION_MINOR 0
#define QMK_BRAZILIAN_ABNT2_KEYCODES_VERSION_PATCH 1
// Aliases
#define BR_QUOT KC_GRV // '
#define BR_1 KC_1 // 1

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_CANADIAN_FRENCH_KEYCODES_VERSION "0.0.1"
#define QMK_CANADIAN_FRENCH_KEYCODES_VERSION_BCD 0x00000001
#define QMK_CANADIAN_FRENCH_KEYCODES_VERSION_MAJOR 0
#define QMK_CANADIAN_FRENCH_KEYCODES_VERSION_MINOR 0
#define QMK_CANADIAN_FRENCH_KEYCODES_VERSION_PATCH 1
// Aliases
#define FR_HASH KC_GRV // #
#define FR_1 KC_1 // 1

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_CANADIAN_MULTILINGUAL_KEYCODES_VERSION "0.0.1"
#define QMK_CANADIAN_MULTILINGUAL_KEYCODES_VERSION_BCD 0x00000001
#define QMK_CANADIAN_MULTILINGUAL_KEYCODES_VERSION_MAJOR 0
#define QMK_CANADIAN_MULTILINGUAL_KEYCODES_VERSION_MINOR 0
#define QMK_CANADIAN_MULTILINGUAL_KEYCODES_VERSION_PATCH 1
// Aliases
#define CA_SLSH KC_GRV // /
#define CA_1 KC_1 // 1

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_COLEMAK_KEYCODES_VERSION "0.0.1"
#define QMK_COLEMAK_KEYCODES_VERSION_BCD 0x00000001
#define QMK_COLEMAK_KEYCODES_VERSION_MAJOR 0
#define QMK_COLEMAK_KEYCODES_VERSION_MINOR 0
#define QMK_COLEMAK_KEYCODES_VERSION_PATCH 1
// Aliases
#define CM_GRV KC_GRV // `
#define CM_1 KC_1 // 1

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_CROATIAN_KEYCODES_VERSION "0.0.1"
#define QMK_CROATIAN_KEYCODES_VERSION_BCD 0x00000001
#define QMK_CROATIAN_KEYCODES_VERSION_MAJOR 0
#define QMK_CROATIAN_KEYCODES_VERSION_MINOR 0
#define QMK_CROATIAN_KEYCODES_VERSION_PATCH 1
// Aliases
#define HR_CEDL KC_GRV // ¸ (dead)
#define HR_1 KC_1 // 1

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_CZECH_KEYCODES_VERSION "0.0.1"
#define QMK_CZECH_KEYCODES_VERSION_BCD 0x00000001
#define QMK_CZECH_KEYCODES_VERSION_MAJOR 0
#define QMK_CZECH_KEYCODES_VERSION_MINOR 0
#define QMK_CZECH_KEYCODES_VERSION_PATCH 1
// Aliases
#define CZ_SCLN KC_GRV // ;
#define CZ_PLUS KC_1 // +

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_CZECH_MAC_ANSI_KEYCODES_VERSION "0.0.1"
#define QMK_CZECH_MAC_ANSI_KEYCODES_VERSION_BCD 0x00000001
#define QMK_CZECH_MAC_ANSI_KEYCODES_VERSION_MAJOR 0
#define QMK_CZECH_MAC_ANSI_KEYCODES_VERSION_MINOR 0
#define QMK_CZECH_MAC_ANSI_KEYCODES_VERSION_PATCH 1
// Aliases
#define CZ_BSLS KC_GRV // (backslash)
#define CZ_PLUS KC_1 // +

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_CZECH_MAC_ISO_KEYCODES_VERSION "0.0.1"
#define QMK_CZECH_MAC_ISO_KEYCODES_VERSION_BCD 0x00000001
#define QMK_CZECH_MAC_ISO_KEYCODES_VERSION_MAJOR 0
#define QMK_CZECH_MAC_ISO_KEYCODES_VERSION_MINOR 0
#define QMK_CZECH_MAC_ISO_KEYCODES_VERSION_PATCH 1
// Aliases
#define CZ_PLUS KC_1 // +
#define CZ_ECAR KC_2 // ě

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_DANISH_KEYCODES_VERSION "0.0.1"
#define QMK_DANISH_KEYCODES_VERSION_BCD 0x00000001
#define QMK_DANISH_KEYCODES_VERSION_MAJOR 0
#define QMK_DANISH_KEYCODES_VERSION_MINOR 0
#define QMK_DANISH_KEYCODES_VERSION_PATCH 1
// Aliases
#define DK_HALF KC_GRV // ½
#define DK_1 KC_1 // 1

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_DVORAK_KEYCODES_VERSION "0.0.1"
#define QMK_DVORAK_KEYCODES_VERSION_BCD 0x00000001
#define QMK_DVORAK_KEYCODES_VERSION_MAJOR 0
#define QMK_DVORAK_KEYCODES_VERSION_MINOR 0
#define QMK_DVORAK_KEYCODES_VERSION_PATCH 1
// Aliases
#define DV_GRV KC_GRV // `
#define DV_1 KC_1 // 1

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_DVORAK_FR_KEYCODES_VERSION "0.0.1"
#define QMK_DVORAK_FR_KEYCODES_VERSION_BCD 0x00000001
#define QMK_DVORAK_FR_KEYCODES_VERSION_MAJOR 0
#define QMK_DVORAK_FR_KEYCODES_VERSION_MINOR 0
#define QMK_DVORAK_FR_KEYCODES_VERSION_PATCH 1
// Aliases
#define DV_LDAQ KC_GRV // «
#define DV_RDAQ KC_1 // »

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_DVORAK_PROGRAMMER_KEYCODES_VERSION "0.0.1"
#define QMK_DVORAK_PROGRAMMER_KEYCODES_VERSION_BCD 0x00000001
#define QMK_DVORAK_PROGRAMMER_KEYCODES_VERSION_MAJOR 0
#define QMK_DVORAK_PROGRAMMER_KEYCODES_VERSION_MINOR 0
#define QMK_DVORAK_PROGRAMMER_KEYCODES_VERSION_PATCH 1
// Aliases
#define DP_DLR KC_GRV // $
#define DP_AMPR KC_1 // &

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_ESTONIAN_KEYCODES_VERSION "0.0.1"
#define QMK_ESTONIAN_KEYCODES_VERSION_BCD 0x00000001
#define QMK_ESTONIAN_KEYCODES_VERSION_MAJOR 0
#define QMK_ESTONIAN_KEYCODES_VERSION_MINOR 0
#define QMK_ESTONIAN_KEYCODES_VERSION_PATCH 1
// Aliases
#define EE_CARN KC_GRV // ˇ (dead)
#define EE_1 KC_1 // 1

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_EURKEY_KEYCODES_VERSION "0.0.1"
#define QMK_EURKEY_KEYCODES_VERSION_BCD 0x00000001
#define QMK_EURKEY_KEYCODES_VERSION_MAJOR 0
#define QMK_EURKEY_KEYCODES_VERSION_MINOR 0
#define QMK_EURKEY_KEYCODES_VERSION_PATCH 1
// Aliases
#define EU_GRV KC_GRV // `
#define EU_1 KC_1 // 1

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_FARSI_KEYCODES_VERSION "0.0.1"
#define QMK_FARSI_KEYCODES_VERSION_BCD 0x00000001
#define QMK_FARSI_KEYCODES_VERSION_MAJOR 0
#define QMK_FARSI_KEYCODES_VERSION_MINOR 0
#define QMK_FARSI_KEYCODES_VERSION_PATCH 1
// Aliases
#define FA_ZWJ KC_GRV // (zero-width joiner)
#define FA_1A KC_1 // ۱

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_FINNISH_KEYCODES_VERSION "0.0.1"
#define QMK_FINNISH_KEYCODES_VERSION_BCD 0x00000001
#define QMK_FINNISH_KEYCODES_VERSION_MAJOR 0
#define QMK_FINNISH_KEYCODES_VERSION_MINOR 0
#define QMK_FINNISH_KEYCODES_VERSION_PATCH 1
// Aliases
#define FI_SECT KC_GRV // §
#define FI_1 KC_1 // 1

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_FRENCH_KEYCODES_VERSION "0.0.1"
#define QMK_FRENCH_KEYCODES_VERSION_BCD 0x00000001
#define QMK_FRENCH_KEYCODES_VERSION_MAJOR 0
#define QMK_FRENCH_KEYCODES_VERSION_MINOR 0
#define QMK_FRENCH_KEYCODES_VERSION_PATCH 1
// Aliases
#define FR_SUP2 KC_GRV // ²
#define FR_AMPR KC_1 // &

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_FRENCH_AFNOR_KEYCODES_VERSION "0.0.1"
#define QMK_FRENCH_AFNOR_KEYCODES_VERSION_BCD 0x00000001
#define QMK_FRENCH_AFNOR_KEYCODES_VERSION_MAJOR 0
#define QMK_FRENCH_AFNOR_KEYCODES_VERSION_MINOR 0
#define QMK_FRENCH_AFNOR_KEYCODES_VERSION_PATCH 1
// Aliases
#define FR_AT KC_GRV // @
#define FR_AGRV KC_1 // à

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_FRENCH_MAC_ISO_KEYCODES_VERSION "0.0.1"
#define QMK_FRENCH_MAC_ISO_KEYCODES_VERSION_BCD 0x00000001
#define QMK_FRENCH_MAC_ISO_KEYCODES_VERSION_MAJOR 0
#define QMK_FRENCH_MAC_ISO_KEYCODES_VERSION_MINOR 0
#define QMK_FRENCH_MAC_ISO_KEYCODES_VERSION_PATCH 1
// Aliases
#define FR_AT KC_GRV // @
#define FR_AMPR KC_1 // &

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_GERMAN_KEYCODES_VERSION "0.0.1"
#define QMK_GERMAN_KEYCODES_VERSION_BCD 0x00000001
#define QMK_GERMAN_KEYCODES_VERSION_MAJOR 0
#define QMK_GERMAN_KEYCODES_VERSION_MINOR 0
#define QMK_GERMAN_KEYCODES_VERSION_PATCH 1
// Aliases
#define DE_CIRC KC_GRV // ^ (dead)
#define DE_1 KC_1 // 1

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_GERMAN_MAC_ISO_KEYCODES_VERSION "0.0.1"
#define QMK_GERMAN_MAC_ISO_KEYCODES_VERSION_BCD 0x00000001
#define QMK_GERMAN_MAC_ISO_KEYCODES_VERSION_MAJOR 0
#define QMK_GERMAN_MAC_ISO_KEYCODES_VERSION_MINOR 0
#define QMK_GERMAN_MAC_ISO_KEYCODES_VERSION_PATCH 1
// Aliases
#define DE_CIRC KC_GRV // ^ (dead)
#define DE_1 KC_1 // 1

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_GREEK_KEYCODES_VERSION "0.0.1"
#define QMK_GREEK_KEYCODES_VERSION_BCD 0x00000001
#define QMK_GREEK_KEYCODES_VERSION_MAJOR 0
#define QMK_GREEK_KEYCODES_VERSION_MINOR 0
#define QMK_GREEK_KEYCODES_VERSION_PATCH 1
// Aliases
#define GR_GRV KC_GRV // `
#define GR_1 KC_1 // 1

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_HEBREW_KEYCODES_VERSION "0.0.1"
#define QMK_HEBREW_KEYCODES_VERSION_BCD 0x00000001
#define QMK_HEBREW_KEYCODES_VERSION_MAJOR 0
#define QMK_HEBREW_KEYCODES_VERSION_MINOR 0
#define QMK_HEBREW_KEYCODES_VERSION_PATCH 1
// Aliases
#define IL_SCLN KC_GRV // ;
#define IL_1 KC_1 // 1

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_HUNGARIAN_KEYCODES_VERSION "0.0.1"
#define QMK_HUNGARIAN_KEYCODES_VERSION_BCD 0x00000001
#define QMK_HUNGARIAN_KEYCODES_VERSION_MAJOR 0
#define QMK_HUNGARIAN_KEYCODES_VERSION_MINOR 0
#define QMK_HUNGARIAN_KEYCODES_VERSION_PATCH 1
// Aliases
#define HU_0 KC_GRV // 0
#define HU_1 KC_1 // 1

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_ICELANDIC_KEYCODES_VERSION "0.0.1"
#define QMK_ICELANDIC_KEYCODES_VERSION_BCD 0x00000001
#define QMK_ICELANDIC_KEYCODES_VERSION_MAJOR 0
#define QMK_ICELANDIC_KEYCODES_VERSION_MINOR 0
#define QMK_ICELANDIC_KEYCODES_VERSION_PATCH 1
// Aliases
#define IS_RNGA KC_GRV // ° (dead)
#define IS_1 KC_1 // 1

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_IRISH_KEYCODES_VERSION "0.0.1"
#define QMK_IRISH_KEYCODES_VERSION_BCD 0x00000001
#define QMK_IRISH_KEYCODES_VERSION_MAJOR 0
#define QMK_IRISH_KEYCODES_VERSION_MINOR 0
#define QMK_IRISH_KEYCODES_VERSION_PATCH 1
// Aliases
#define IE_GRV KC_GRV // `
#define IE_1 KC_1 // 1

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_ITALIAN_KEYCODES_VERSION "0.0.1"
#define QMK_ITALIAN_KEYCODES_VERSION_BCD 0x00000001
#define QMK_ITALIAN_KEYCODES_VERSION_MAJOR 0
#define QMK_ITALIAN_KEYCODES_VERSION_MINOR 0
#define QMK_ITALIAN_KEYCODES_VERSION_PATCH 1
// Aliases
#define IT_BSLS KC_GRV // (backslash)
#define IT_1 KC_1 // 1

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_ITALIAN_MAC_ANSI_KEYCODES_VERSION "0.0.1"
#define QMK_ITALIAN_MAC_ANSI_KEYCODES_VERSION_BCD 0x00000001
#define QMK_ITALIAN_MAC_ANSI_KEYCODES_VERSION_MAJOR 0
#define QMK_ITALIAN_MAC_ANSI_KEYCODES_VERSION_MINOR 0
#define QMK_ITALIAN_MAC_ANSI_KEYCODES_VERSION_PATCH 1
// Aliases
#define IT_LABK KC_GRV // <
#define IT_1 KC_1 // 1

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_ITALIAN_MAC_ISO_KEYCODES_VERSION "0.0.1"
#define QMK_ITALIAN_MAC_ISO_KEYCODES_VERSION_BCD 0x00000001
#define QMK_ITALIAN_MAC_ISO_KEYCODES_VERSION_MAJOR 0
#define QMK_ITALIAN_MAC_ISO_KEYCODES_VERSION_MINOR 0
#define QMK_ITALIAN_MAC_ISO_KEYCODES_VERSION_PATCH 1
// Aliases
#define IT_BSLS KC_GRV // (backslash)
#define IT_1 KC_1 // 1

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_JAPANESE_KEYCODES_VERSION "0.0.1"
#define QMK_JAPANESE_KEYCODES_VERSION_BCD 0x00000001
#define QMK_JAPANESE_KEYCODES_VERSION_MAJOR 0
#define QMK_JAPANESE_KEYCODES_VERSION_MINOR 0
#define QMK_JAPANESE_KEYCODES_VERSION_PATCH 1
// Aliases
#define JP_ZKHK KC_GRV // Zenkaku ↔ Hankaku ↔ Kanji (半角 ↔ 全角 ↔ 漢字)
#define JP_1 KC_1 // 1

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_KOREAN_KEYCODES_VERSION "0.0.1"
#define QMK_KOREAN_KEYCODES_VERSION_BCD 0x00000001
#define QMK_KOREAN_KEYCODES_VERSION_MAJOR 0
#define QMK_KOREAN_KEYCODES_VERSION_MINOR 0
#define QMK_KOREAN_KEYCODES_VERSION_PATCH 1
// Aliases
#define KR_GRV KC_GRV // `
#define KR_1 KC_1 // 1

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_LATVIAN_KEYCODES_VERSION "0.0.1"
#define QMK_LATVIAN_KEYCODES_VERSION_BCD 0x00000001
#define QMK_LATVIAN_KEYCODES_VERSION_MAJOR 0
#define QMK_LATVIAN_KEYCODES_VERSION_MINOR 0
#define QMK_LATVIAN_KEYCODES_VERSION_PATCH 1
// Aliases
#define LV_GRV KC_GRV // `
#define LV_1 KC_1 // 1

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_LITHUANIAN_AZERTY_KEYCODES_VERSION "0.0.1"
#define QMK_LITHUANIAN_AZERTY_KEYCODES_VERSION_BCD 0x00000001
#define QMK_LITHUANIAN_AZERTY_KEYCODES_VERSION_MAJOR 0
#define QMK_LITHUANIAN_AZERTY_KEYCODES_VERSION_MINOR 0
#define QMK_LITHUANIAN_AZERTY_KEYCODES_VERSION_PATCH 1
// Aliases
#define LT_GRV KC_GRV // `
#define LT_EXLM KC_1 // !

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_LITHUANIAN_QWERTY_KEYCODES_VERSION "0.0.1"
#define QMK_LITHUANIAN_QWERTY_KEYCODES_VERSION_BCD 0x00000001
#define QMK_LITHUANIAN_QWERTY_KEYCODES_VERSION_MAJOR 0
#define QMK_LITHUANIAN_QWERTY_KEYCODES_VERSION_MINOR 0
#define QMK_LITHUANIAN_QWERTY_KEYCODES_VERSION_PATCH 1
// Aliases
#define LT_GRV KC_GRV // `
#define LT_AOGO KC_1 // Ą

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_NEO2_KEYCODES_VERSION "0.0.1"
#define QMK_NEO2_KEYCODES_VERSION_BCD 0x00000001
#define QMK_NEO2_KEYCODES_VERSION_MAJOR 0
#define QMK_NEO2_KEYCODES_VERSION_MINOR 0
#define QMK_NEO2_KEYCODES_VERSION_PATCH 1
// Aliases
#define NE_CIRC KC_GRV // ^ (dead)
#define NE_1 KC_1 // 1

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_NORDIC_KEYCODES_VERSION "0.0.1"
#define QMK_NORDIC_KEYCODES_VERSION_BCD 0x00000001
#define QMK_NORDIC_KEYCODES_VERSION_MAJOR 0
#define QMK_NORDIC_KEYCODES_VERSION_MINOR 0
#define QMK_NORDIC_KEYCODES_VERSION_PATCH 1
// Aliases
#define NO_HALF KC_GRV
#define NO_PLUS KC_MINS

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_NORMAN_KEYCODES_VERSION "0.0.1"
#define QMK_NORMAN_KEYCODES_VERSION_BCD 0x00000001
#define QMK_NORMAN_KEYCODES_VERSION_MAJOR 0
#define QMK_NORMAN_KEYCODES_VERSION_MINOR 0
#define QMK_NORMAN_KEYCODES_VERSION_PATCH 1
// Aliases
#define NM_GRV KC_GRV // `
#define NM_1 KC_1 // 1

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_NORWEGIAN_KEYCODES_VERSION "0.0.1"
#define QMK_NORWEGIAN_KEYCODES_VERSION_BCD 0x00000001
#define QMK_NORWEGIAN_KEYCODES_VERSION_MAJOR 0
#define QMK_NORWEGIAN_KEYCODES_VERSION_MINOR 0
#define QMK_NORWEGIAN_KEYCODES_VERSION_PATCH 1
// Aliases
#define NO_PIPE KC_GRV // |
#define NO_1 KC_1 // 1

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_PLOVER_KEYCODES_VERSION "0.0.1"
#define QMK_PLOVER_KEYCODES_VERSION_BCD 0x00000001
#define QMK_PLOVER_KEYCODES_VERSION_MAJOR 0
#define QMK_PLOVER_KEYCODES_VERSION_MINOR 0
#define QMK_PLOVER_KEYCODES_VERSION_PATCH 1
// Aliases
#define PV_NUM KC_1
#define PV_LS KC_Q

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_PLOVER_DVORAK_KEYCODES_VERSION "0.0.1"
#define QMK_PLOVER_DVORAK_KEYCODES_VERSION_BCD 0x00000001
#define QMK_PLOVER_DVORAK_KEYCODES_VERSION_MAJOR 0
#define QMK_PLOVER_DVORAK_KEYCODES_VERSION_MINOR 0
#define QMK_PLOVER_DVORAK_KEYCODES_VERSION_PATCH 1
// Aliases
#define PD_NUM DV_1
#define PD_LS DV_Q

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_POLISH_KEYCODES_VERSION "0.0.1"
#define QMK_POLISH_KEYCODES_VERSION_BCD 0x00000001
#define QMK_POLISH_KEYCODES_VERSION_MAJOR 0
#define QMK_POLISH_KEYCODES_VERSION_MINOR 0
#define QMK_POLISH_KEYCODES_VERSION_PATCH 1
// Aliases
#define PL_GRV KC_GRV // `
#define PL_1 KC_1 // 1

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_PORTUGUESE_KEYCODES_VERSION "0.0.1"
#define QMK_PORTUGUESE_KEYCODES_VERSION_BCD 0x00000001
#define QMK_PORTUGUESE_KEYCODES_VERSION_MAJOR 0
#define QMK_PORTUGUESE_KEYCODES_VERSION_MINOR 0
#define QMK_PORTUGUESE_KEYCODES_VERSION_PATCH 1
// Aliases
#define PT_BSLS KC_GRV // (backslash)
#define PT_1 KC_1 // 1

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_PORTUGUESE_MAC_ISO_KEYCODES_VERSION "0.0.1"
#define QMK_PORTUGUESE_MAC_ISO_KEYCODES_VERSION_BCD 0x00000001
#define QMK_PORTUGUESE_MAC_ISO_KEYCODES_VERSION_MAJOR 0
#define QMK_PORTUGUESE_MAC_ISO_KEYCODES_VERSION_MINOR 0
#define QMK_PORTUGUESE_MAC_ISO_KEYCODES_VERSION_PATCH 1
// Aliases
#define PT_SECT KC_GRV // §
#define PT_1 KC_1 // 1

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_ROMANIAN_KEYCODES_VERSION "0.0.1"
#define QMK_ROMANIAN_KEYCODES_VERSION_BCD 0x00000001
#define QMK_ROMANIAN_KEYCODES_VERSION_MAJOR 0
#define QMK_ROMANIAN_KEYCODES_VERSION_MINOR 0
#define QMK_ROMANIAN_KEYCODES_VERSION_PATCH 1
// Aliases
#define RO_DLQU KC_GRV // „
#define RO_1 KC_1 // 1

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_RUSSIAN_KEYCODES_VERSION "0.0.1"
#define QMK_RUSSIAN_KEYCODES_VERSION_BCD 0x00000001
#define QMK_RUSSIAN_KEYCODES_VERSION_MAJOR 0
#define QMK_RUSSIAN_KEYCODES_VERSION_MINOR 0
#define QMK_RUSSIAN_KEYCODES_VERSION_PATCH 1
// Aliases
#define RU_YO KC_GRV // Ё
#define RU_1 KC_1 // 1

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_RUSSIAN_TYPEWRITER_KEYCODES_VERSION "0.0.1"
#define QMK_RUSSIAN_TYPEWRITER_KEYCODES_VERSION_BCD 0x00000001
#define QMK_RUSSIAN_TYPEWRITER_KEYCODES_VERSION_MAJOR 0
#define QMK_RUSSIAN_TYPEWRITER_KEYCODES_VERSION_MINOR 0
#define QMK_RUSSIAN_TYPEWRITER_KEYCODES_VERSION_PATCH 1
// Aliases
#define RU_PIPE KC_GRV // |
#define RU_NUM KC_1 // №

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_SERBIAN_KEYCODES_VERSION "0.0.1"
#define QMK_SERBIAN_KEYCODES_VERSION_BCD 0x00000001
#define QMK_SERBIAN_KEYCODES_VERSION_MAJOR 0
#define QMK_SERBIAN_KEYCODES_VERSION_MINOR 0
#define QMK_SERBIAN_KEYCODES_VERSION_PATCH 1
// Aliases
#define RS_GRV KC_GRV // `
#define RS_1 KC_1 // 1

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_SERBIAN_LATIN_KEYCODES_VERSION "0.0.1"
#define QMK_SERBIAN_LATIN_KEYCODES_VERSION_BCD 0x00000001
#define QMK_SERBIAN_LATIN_KEYCODES_VERSION_MAJOR 0
#define QMK_SERBIAN_LATIN_KEYCODES_VERSION_MINOR 0
#define QMK_SERBIAN_LATIN_KEYCODES_VERSION_PATCH 1
// Aliases
#define RS_SLQU KC_GRV // ‚ (dead)
#define RS_1 KC_1 // 1

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_SLOVAK_KEYCODES_VERSION "0.0.1"
#define QMK_SLOVAK_KEYCODES_VERSION_BCD 0x00000001
#define QMK_SLOVAK_KEYCODES_VERSION_MAJOR 0
#define QMK_SLOVAK_KEYCODES_VERSION_MINOR 0
#define QMK_SLOVAK_KEYCODES_VERSION_PATCH 1
// Aliases
#define SK_SCLN KC_GRV // ;
#define SK_PLUS KC_1 // +

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_SLOVENIAN_KEYCODES_VERSION "0.0.1"
#define QMK_SLOVENIAN_KEYCODES_VERSION_BCD 0x00000001
#define QMK_SLOVENIAN_KEYCODES_VERSION_MAJOR 0
#define QMK_SLOVENIAN_KEYCODES_VERSION_MINOR 0
#define QMK_SLOVENIAN_KEYCODES_VERSION_PATCH 1
// Aliases
#define SI_CEDL KC_GRV // ¸ (dead)
#define SI_1 KC_1 // 1

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_SPANISH_KEYCODES_VERSION "0.0.1"
#define QMK_SPANISH_KEYCODES_VERSION_BCD 0x00000001
#define QMK_SPANISH_KEYCODES_VERSION_MAJOR 0
#define QMK_SPANISH_KEYCODES_VERSION_MINOR 0
#define QMK_SPANISH_KEYCODES_VERSION_PATCH 1
// Aliases
#define ES_MORD KC_GRV // º
#define ES_1 KC_1 // 1

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_SPANISH_DVORAK_KEYCODES_VERSION "0.0.1"
#define QMK_SPANISH_DVORAK_KEYCODES_VERSION_BCD 0x00000001
#define QMK_SPANISH_DVORAK_KEYCODES_VERSION_MAJOR 0
#define QMK_SPANISH_DVORAK_KEYCODES_VERSION_MINOR 0
#define QMK_SPANISH_DVORAK_KEYCODES_VERSION_PATCH 1
// Aliases
#define DV_MORD KC_GRV // º
#define DV_1 KC_1 // 1

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_SPANISH_LATIN_AMERICA_KEYCODES_VERSION "0.0.1"
#define QMK_SPANISH_LATIN_AMERICA_KEYCODES_VERSION_BCD 0x00000001
#define QMK_SPANISH_LATIN_AMERICA_KEYCODES_VERSION_MAJOR 0
#define QMK_SPANISH_LATIN_AMERICA_KEYCODES_VERSION_MINOR 0
#define QMK_SPANISH_LATIN_AMERICA_KEYCODES_VERSION_PATCH 1
// Aliases
#define ES_PIPE KC_GRV // |
#define ES_1 KC_1 // 1

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_SWEDISH_KEYCODES_VERSION "0.0.1"
#define QMK_SWEDISH_KEYCODES_VERSION_BCD 0x00000001
#define QMK_SWEDISH_KEYCODES_VERSION_MAJOR 0
#define QMK_SWEDISH_KEYCODES_VERSION_MINOR 0
#define QMK_SWEDISH_KEYCODES_VERSION_PATCH 1
// Aliases
#define SE_SECT KC_GRV // §
#define SE_1 KC_1 // 1

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_SWEDISH_MAC_ANSI_KEYCODES_VERSION "0.0.1"
#define QMK_SWEDISH_MAC_ANSI_KEYCODES_VERSION_BCD 0x00000001
#define QMK_SWEDISH_MAC_ANSI_KEYCODES_VERSION_MAJOR 0
#define QMK_SWEDISH_MAC_ANSI_KEYCODES_VERSION_MINOR 0
#define QMK_SWEDISH_MAC_ANSI_KEYCODES_VERSION_PATCH 1
// Aliases
#define SE_LABK KC_GRV // <
#define SE_1 KC_1 // 1

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_SWEDISH_MAC_ISO_KEYCODES_VERSION "0.0.1"
#define QMK_SWEDISH_MAC_ISO_KEYCODES_VERSION_BCD 0x00000001
#define QMK_SWEDISH_MAC_ISO_KEYCODES_VERSION_MAJOR 0
#define QMK_SWEDISH_MAC_ISO_KEYCODES_VERSION_MINOR 0
#define QMK_SWEDISH_MAC_ISO_KEYCODES_VERSION_PATCH 1
// Aliases
#define SE_SECT KC_GRV // §
#define SE_1 KC_1 // 1

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_SWEDISH_PRO_MAC_ANSI_KEYCODES_VERSION "0.0.1"
#define QMK_SWEDISH_PRO_MAC_ANSI_KEYCODES_VERSION_BCD 0x00000001
#define QMK_SWEDISH_PRO_MAC_ANSI_KEYCODES_VERSION_MAJOR 0
#define QMK_SWEDISH_PRO_MAC_ANSI_KEYCODES_VERSION_MINOR 0
#define QMK_SWEDISH_PRO_MAC_ANSI_KEYCODES_VERSION_PATCH 1
// Aliases
#define SE_LABK KC_GRV // <
#define SE_1 KC_1 // 1

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_SWEDISH_PRO_MAC_ISO_KEYCODES_VERSION "0.0.1"
#define QMK_SWEDISH_PRO_MAC_ISO_KEYCODES_VERSION_BCD 0x00000001
#define QMK_SWEDISH_PRO_MAC_ISO_KEYCODES_VERSION_MAJOR 0
#define QMK_SWEDISH_PRO_MAC_ISO_KEYCODES_VERSION_MINOR 0
#define QMK_SWEDISH_PRO_MAC_ISO_KEYCODES_VERSION_PATCH 1
// Aliases
#define SE_SECT KC_GRV // §
#define SE_1 KC_1 // 1

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_SWISS_DE_KEYCODES_VERSION "0.0.1"
#define QMK_SWISS_DE_KEYCODES_VERSION_BCD 0x00000001
#define QMK_SWISS_DE_KEYCODES_VERSION_MAJOR 0
#define QMK_SWISS_DE_KEYCODES_VERSION_MINOR 0
#define QMK_SWISS_DE_KEYCODES_VERSION_PATCH 1
#undef CH_H
// Aliases

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_SWISS_FR_KEYCODES_VERSION "0.0.1"
#define QMK_SWISS_FR_KEYCODES_VERSION_BCD 0x00000001
#define QMK_SWISS_FR_KEYCODES_VERSION_MAJOR 0
#define QMK_SWISS_FR_KEYCODES_VERSION_MINOR 0
#define QMK_SWISS_FR_KEYCODES_VERSION_PATCH 1
#undef CH_H
// Aliases

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_TURKISH_F_KEYCODES_VERSION "0.0.1"
#define QMK_TURKISH_F_KEYCODES_VERSION_BCD 0x00000001
#define QMK_TURKISH_F_KEYCODES_VERSION_MAJOR 0
#define QMK_TURKISH_F_KEYCODES_VERSION_MINOR 0
#define QMK_TURKISH_F_KEYCODES_VERSION_PATCH 1
// Aliases
#define TR_PLUS KC_GRV // +
#define TR_1 KC_1 // 1

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_TURKISH_Q_KEYCODES_VERSION "0.0.1"
#define QMK_TURKISH_Q_KEYCODES_VERSION_BCD 0x00000001
#define QMK_TURKISH_Q_KEYCODES_VERSION_MAJOR 0
#define QMK_TURKISH_Q_KEYCODES_VERSION_MINOR 0
#define QMK_TURKISH_Q_KEYCODES_VERSION_PATCH 1
// Aliases
#define TR_DQUO KC_GRV // "
#define TR_1 KC_1 // 1

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_UK_KEYCODES_VERSION "0.0.1"
#define QMK_UK_KEYCODES_VERSION_BCD 0x00000001
#define QMK_UK_KEYCODES_VERSION_MAJOR 0
#define QMK_UK_KEYCODES_VERSION_MINOR 0
#define QMK_UK_KEYCODES_VERSION_PATCH 1
// Aliases
#define UK_GRV KC_GRV // `
#define UK_1 KC_1 // 1

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_UKRAINIAN_KEYCODES_VERSION "0.0.1"
#define QMK_UKRAINIAN_KEYCODES_VERSION_BCD 0x00000001
#define QMK_UKRAINIAN_KEYCODES_VERSION_MAJOR 0
#define QMK_UKRAINIAN_KEYCODES_VERSION_MINOR 0
#define QMK_UKRAINIAN_KEYCODES_VERSION_PATCH 1
// Aliases
#define UA_QUOT KC_GRV // '
#define UA_1 KC_1 // 1

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_US_KEYCODES_VERSION "0.0.1"
#define QMK_US_KEYCODES_VERSION_BCD 0x00000001
#define QMK_US_KEYCODES_VERSION_MAJOR 0
#define QMK_US_KEYCODES_VERSION_MINOR 0
#define QMK_US_KEYCODES_VERSION_PATCH 1
// Aliases
#define KC_TILD S(KC_GRAVE) // ~
#define KC_EXLM S(KC_1) // !

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_US_EXTENDED_KEYCODES_VERSION "0.0.1"
#define QMK_US_EXTENDED_KEYCODES_VERSION_BCD 0x00000001
#define QMK_US_EXTENDED_KEYCODES_VERSION_MAJOR 0
#define QMK_US_EXTENDED_KEYCODES_VERSION_MINOR 0
#define QMK_US_EXTENDED_KEYCODES_VERSION_PATCH 1
// Aliases
#define US_GRV KC_GRV // `
#define US_1 KC_1 // 1

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_US_INTERNATIONAL_KEYCODES_VERSION "0.0.1"
#define QMK_US_INTERNATIONAL_KEYCODES_VERSION_BCD 0x00000001
#define QMK_US_INTERNATIONAL_KEYCODES_VERSION_MAJOR 0
#define QMK_US_INTERNATIONAL_KEYCODES_VERSION_MINOR 0
#define QMK_US_INTERNATIONAL_KEYCODES_VERSION_PATCH 1
// Aliases
#define US_DGRV KC_GRV // ` (dead)
#define US_1 KC_1 // 1

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_US_INTERNATIONAL_LINUX_KEYCODES_VERSION "0.0.1"
#define QMK_US_INTERNATIONAL_LINUX_KEYCODES_VERSION_BCD 0x00000001
#define QMK_US_INTERNATIONAL_LINUX_KEYCODES_VERSION_MAJOR 0
#define QMK_US_INTERNATIONAL_LINUX_KEYCODES_VERSION_MINOR 0
#define QMK_US_INTERNATIONAL_LINUX_KEYCODES_VERSION_PATCH 1
// Aliases
#define US_DGRV KC_GRV // ` (dead)
#define US_1 KC_1 // 1

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_WORKMAN_KEYCODES_VERSION "0.0.1"
#define QMK_WORKMAN_KEYCODES_VERSION_BCD 0x00000001
#define QMK_WORKMAN_KEYCODES_VERSION_MAJOR 0
#define QMK_WORKMAN_KEYCODES_VERSION_MINOR 0
#define QMK_WORKMAN_KEYCODES_VERSION_PATCH 1
// Aliases
#define WK_GRV KC_GRV // `
#define WK_1 KC_1 // 1

View file

@ -27,6 +27,12 @@
#include "keycodes.h"
// clang-format off
#define QMK_WORKMAN_ZXCVM_KEYCODES_VERSION "0.0.1"
#define QMK_WORKMAN_ZXCVM_KEYCODES_VERSION_BCD 0x00000001
#define QMK_WORKMAN_ZXCVM_KEYCODES_VERSION_MAJOR 0
#define QMK_WORKMAN_ZXCVM_KEYCODES_VERSION_MINOR 0
#define QMK_WORKMAN_ZXCVM_KEYCODES_VERSION_PATCH 1
// Aliases
#define WK_GRV KC_GRV // `
#define WK_1 KC_1 // 1

Some files were not shown because too many files have changed in this diff Show more