diff options
Diffstat (limited to 'quantum')
159 files changed, 3616 insertions, 868 deletions
diff --git a/quantum/action.c b/quantum/action.c index be85192d25..dd82c9ec99 100644 --- a/quantum/action.c +++ b/quantum/action.c @@ -281,6 +281,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 @@ -1183,6 +1186,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. diff --git a/quantum/action.h b/quantum/action.h index 7596688f31..7616486c6d 100644 --- a/quantum/action.h +++ b/quantum/action.h @@ -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 diff --git a/quantum/action_layer.c b/quantum/action_layer.c index 7c09a5bd1e..5828dcb824 100644 --- a/quantum/action_layer.c +++ b/quantum/action_layer.c @@ -27,11 +27,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(); @@ -107,11 +116,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(); diff --git a/quantum/action_layer.h b/quantum/action_layer.h index a2410d49a5..067e33cdb5 100644 --- a/quantum/action_layer.h +++ b/quantum/action_layer.h @@ -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) diff --git a/quantum/action_tapping.c b/quantum/action_tapping.c index e42a98554d..b105cd60a9 100644 --- a/quantum/action_tapping.c +++ b/quantum/action_tapping.c @@ -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="); diff --git a/quantum/action_tapping.h b/quantum/action_tapping.h index c3c7b999ec..0cf4aa1200 100644 --- a/quantum/action_tapping.h +++ b/quantum/action_tapping.h @@ -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 diff --git a/quantum/action_util.c b/quantum/action_util.c index c0dc4f3822..e821e113ef 100644 --- a/quantum/action_util.c +++ b/quantum/action_util.c @@ -21,7 +21,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #include "action_layer.h" #include "timer.h" #include "keycode_config.h" -#include "usb_device_state.h" #include <string.h> extern keymap_config_t keymap_config; @@ -220,7 +219,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); } @@ -319,14 +318,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 diff --git a/quantum/audio/audio.c b/quantum/audio/audio.c index 2cc3c2d661..4e223f0c9a 100644 --- a/quantum/audio/audio.c +++ b/quantum/audio/audio.c @@ -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) { diff --git a/quantum/audio/audio.h b/quantum/audio/audio.h index 054331d6f3..647744a686 100644 --- a/quantum/audio/audio.h +++ b/quantum/audio/audio.h @@ -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 diff --git a/quantum/backlight/backlight.c b/quantum/backlight/backlight.c index eb64dd71e8..a7d2a45a51 100644 --- a/quantum/backlight/backlight.c +++ b/quantum/backlight/backlight.c @@ -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(); } diff --git a/quantum/backlight/backlight.h b/quantum/backlight/backlight.h index c34fb5858d..2faa8fc4f2 100644 --- a/quantum/backlight/backlight.h +++ b/quantum/backlight/backlight.h @@ -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); diff --git a/quantum/command.c b/quantum/command.c index 024d96917d..998d9b9aa1 100644 --- a/quantum/command.c +++ b/quantum/command.c @@ -243,10 +243,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" @@ -263,7 +263,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" @@ -296,7 +296,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" diff --git a/quantum/compiler_support.h b/quantum/compiler_support.h new file mode 100644 index 0000000000..5c0c4d2835 --- /dev/null +++ b/quantum/compiler_support.h @@ -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 diff --git a/quantum/connection/connection.c b/quantum/connection/connection.c new file mode 100644 index 0000000000..1ff8876876 --- /dev/null +++ b/quantum/connection/connection.c @@ -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; +} diff --git a/quantum/connection/connection.h b/quantum/connection/connection.h new file mode 100644 index 0000000000..b25160c759 --- /dev/null +++ b/quantum/connection/connection.h @@ -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); diff --git a/quantum/dynamic_keymap.c b/quantum/dynamic_keymap.c index beb7f9d18f..25029e39c4 100644 --- a/quantum/dynamic_keymap.c +++ b/quantum/dynamic_keymap.c @@ -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,18 +18,9 @@ #include "dynamic_keymap.h" #include "keymap_introspection.h" #include "action.h" -#include "eeprom.h" -#include "progmem.h" #include "send_string.h" #include "keycodes.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 +#include "nvm_dynamic_keymap.h" #ifdef ENCODER_ENABLE # include "encoder.h" @@ -36,67 +28,6 @@ # define NUM_ENCODERS 0 #endif -#ifndef DYNAMIC_KEYMAP_LAYER_COUNT -# define DYNAMIC_KEYMAP_LAYER_COUNT 4 -#endif - -#ifndef DYNAMIC_KEYMAP_MACRO_COUNT -# define DYNAMIC_KEYMAP_MACRO_COUNT 16 -#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 - -// Dynamic encoders starts after dynamic keymaps -#ifndef DYNAMIC_KEYMAP_ENCODER_EEPROM_ADDR -# define DYNAMIC_KEYMAP_ENCODER_EEPROM_ADDR (DYNAMIC_KEYMAP_EEPROM_ADDR + (DYNAMIC_KEYMAP_LAYER_COUNT * MATRIX_ROWS * MATRIX_COLS * 2)) -#endif - -// Dynamic macro starts after dynamic encoders, but only when using ENCODER_MAP -#ifdef ENCODER_MAP_ENABLE -# ifndef DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR -# define DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR (DYNAMIC_KEYMAP_ENCODER_EEPROM_ADDR + (DYNAMIC_KEYMAP_LAYER_COUNT * NUM_ENCODERS * 2 * 2)) -# endif // DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR -#else // ENCODER_MAP_ENABLE -# ifndef DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR -# define DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR (DYNAMIC_KEYMAP_ENCODER_EEPROM_ADDR) -# endif // DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR -#endif // ENCODER_MAP_ENABLE - -// 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) -#endif - #ifndef DYNAMIC_KEYMAP_MACRO_DELAY # define DYNAMIC_KEYMAP_MACRO_DELAY TAP_CODE_DELAY #endif @@ -105,52 +36,28 @@ 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 void dynamic_keymap_reset(void) { + // 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++) { @@ -168,31 +75,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; - 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) { @@ -216,53 +103,38 @@ 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; +static uint8_t dynamic_keymap_read_byte(uint32_t offset) { + uint8_t d; + nvm_dynamic_keymap_macro_read_buffer(offset, 1, &d); + return d; +} -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++; +typedef struct send_string_nvm_state_t { + uint32_t offset; +} send_string_nvm_state_t; + +char send_string_get_next_nvm(void *arg) { + send_string_nvm_state_t *state = (send_string_nvm_state_t *)arg; + char ret = dynamic_keymap_read_byte(state->offset); + state->offset++; return ret; } 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(); } void dynamic_keymap_macro_send(uint8_t id) { @@ -274,27 +146,26 @@ 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); + 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 there is // no Nth macro in the buffer. - if (p == end) { + if (offset == end) { return; } - if (eeprom_read_byte(p) == 0) { + if (dynamic_keymap_read_byte(offset) == 0) { --id; } - ++p; + ++offset; } - send_string_eeprom_state_t state = {p}; - send_string_with_delay_impl(send_string_get_next_eeprom, &state, DYNAMIC_KEYMAP_MACRO_DELAY); + send_string_nvm_state_t state = {.offset = offset}; + send_string_with_delay_impl(send_string_get_next_nvm, &state, DYNAMIC_KEYMAP_MACRO_DELAY); } diff --git a/quantum/dynamic_keymap.h b/quantum/dynamic_keymap.h index 806342efa3..f1d8077b12 100644 --- a/quantum/dynamic_keymap.h +++ b/quantum/dynamic_keymap.h @@ -18,8 +18,15 @@ #include <stdint.h> #include <stdbool.h> +#ifndef DYNAMIC_KEYMAP_LAYER_COUNT +# define DYNAMIC_KEYMAP_LAYER_COUNT 4 +#endif + +#ifndef DYNAMIC_KEYMAP_MACRO_COUNT +# define DYNAMIC_KEYMAP_MACRO_COUNT 16 +#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 diff --git a/quantum/eeconfig.c b/quantum/eeconfig.c index e27f604f12..f14e6ddf97 100644 --- a/quantum/eeconfig.c +++ b/quantum/eeconfig.c @@ -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 + +#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 -#if defined(HAPTIC_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); -#endif +#else +void dynamic_keymap_reset(void); +#endif // VIA_ENABLE -_Static_assert((intptr_t)EECONFIG_HANDEDNESS == 14, "EEPROM handedness offset is incorrect"); +#ifndef NKRO_DEFAULT_ON +# define NKRO_DEFAULT_ON false +#endif -/** \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 + nvm_eeconfig_update_default_layer(state); +} - eeprom_update_byte(EECONFIG_DEFAULT_LAYER, val); +void eeconfig_read_keymap(keymap_config_t *keymap_config) { + nvm_eeconfig_read_keymap(keymap_config); +} +void eeconfig_update_keymap(const keymap_config_t *keymap_config) { + nvm_eeconfig_update_keymap(keymap_config); +} + +#ifdef AUDIO_ENABLE +void eeconfig_read_audio(audio_config_t *audio_config) { + nvm_eeconfig_read_audio(audio_config); +} +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 -/** \brief eeconfig read keymap - * - * FIXME: needs doc - */ -uint16_t eeconfig_read_keymap(void) { - return eeprom_read_word(EECONFIG_KEYMAP); +#ifdef STENO_ENABLE +uint8_t eeconfig_read_steno_mode(void) { + return nvm_eeconfig_read_steno_mode(); } -/** \brief eeconfig update keymap - * - * FIXME: needs doc - */ -void eeconfig_update_keymap(uint16_t val) { - eeprom_update_word(EECONFIG_KEYMAP, val); +void eeconfig_update_steno_mode(uint8_t val) { + nvm_eeconfig_update_steno_mode(val); } +#endif // STENO_ENABLE -/** \brief eeconfig read audio - * - * FIXME: needs doc - */ -uint8_t eeconfig_read_audio(void) { - return eeprom_read_byte(EECONFIG_AUDIO); +#ifdef RGB_MATRIX_ENABLE +void eeconfig_read_rgb_matrix(rgb_config_t *rgb_matrix_config) { + nvm_eeconfig_read_rgb_matrix(rgb_matrix_config); } -/** \brief eeconfig update audio - * - * FIXME: needs doc - */ -void eeconfig_update_audio(uint8_t val) { - eeprom_update_byte(EECONFIG_AUDIO, val); +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); -} -/** \brief eeconfig update haptic - * - * FIXME: needs doc - */ -void eeconfig_update_haptic(uint32_t val) { - eeprom_update_dword(EECONFIG_HAPTIC, val); -} - -/** \brief eeconfig read split handedness - * - * FIXME: needs doc - */ +#ifdef HAPTIC_ENABLE +void eeconfig_read_haptic(haptic_config_t *haptic_config) { + nvm_eeconfig_read_haptic(haptic_config); +} +void eeconfig_update_haptic(const haptic_config_t *haptic_config) { + nvm_eeconfig_update_haptic(haptic_config); +} +#endif // HAPTIC_ENABLE + +#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); -} -/** \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)); - } + return nvm_eeconfig_is_kb_datablock_valid(); +} +uint32_t eeconfig_read_kb_datablock(void *data, uint32_t offset, uint32_t length) { + return nvm_eeconfig_read_kb_datablock(data, offset, length); +} +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 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)); -} -/** \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); -} -/** \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)); - } + return nvm_eeconfig_is_user_datablock_valid(); +} +uint32_t eeconfig_read_user_datablock(void *data, uint32_t offset, uint32_t length) { + return nvm_eeconfig_read_user_datablock(data, offset, length); +} +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 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)); -} -/** \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 diff --git a/quantum/eeconfig.h b/quantum/eeconfig.h index 11cf1ccbca..d4d8d957be 100644 --- a/quantum/eeconfig.h +++ b/quantum/eeconfig.h @@ -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(__object, __field), sizeof(__object.__field)) +# define eeconfig_update_user_datablock_field(__object, __field) eeconfig_update_user_datablock(&(__object.__field), offsetof(__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) {} diff --git a/quantum/haptic.c b/quantum/haptic.c index 81bad469b3..8a743480ff 100644 --- a/quantum/haptic.c +++ b/quantum/haptic.c @@ -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 diff --git a/quantum/haptic.h b/quantum/haptic.h index b283d5d268..f854c75ec3 100644 --- a/quantum/haptic.h +++ b/quantum/haptic.h @@ -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, diff --git a/quantum/keyboard.c b/quantum/keyboard.c index ad740de4b3..c1a6d444a5 100644 --- a/quantum/keyboard.c +++ b/quantum/keyboard.c @@ -122,6 +122,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 @@ -143,6 +146,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) { @@ -429,8 +435,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(); @@ -462,6 +468,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(); @@ -500,8 +509,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(); @@ -522,6 +532,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 @@ -782,6 +795,10 @@ void keyboard_task(void) { joystick_task(); #endif +#ifdef BATTERY_DRIVER + battery_task(); +#endif + #ifdef BLUETOOTH_ENABLE bluetooth_task(); #endif diff --git a/quantum/keycode_config.h b/quantum/keycode_config.h index d1352c302e..804f1381d0 100644 --- a/quantum/keycode_config.h +++ b/quantum/keycode_config.h @@ -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; diff --git a/quantum/keycode_string.c b/quantum/keycode_string.c new file mode 100644 index 0000000000..18044f2ef6 --- /dev/null +++ b/quantum/keycode_string.c @@ -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; +} diff --git a/quantum/keycode_string.h b/quantum/keycode_string.h new file mode 100644 index 0000000000..1315613a80 --- /dev/null +++ b/quantum/keycode_string.h @@ -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 diff --git a/quantum/keycodes.h b/quantum/keycodes.h index b4fc38f5ff..6a59aa376d 100644 --- a/quantum/keycodes.h +++ b/quantum/keycodes.h @@ -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, diff --git a/quantum/keymap_common.c b/quantum/keymap_common.c index abdcd5c7ba..9be9bae943 100644 --- a/quantum/keymap_common.c +++ b/quantum/keymap_common.c @@ -156,7 +156,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: diff --git a/quantum/keymap_extras/keymap_belgian.h b/quantum/keymap_extras/keymap_belgian.h index 1869e66d9a..b41ed9d20b 100644 --- a/quantum/keymap_extras/keymap_belgian.h +++ b/quantum/keymap_extras/keymap_belgian.h @@ -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 // & diff --git a/quantum/keymap_extras/keymap_bepo.h b/quantum/keymap_extras/keymap_bepo.h index f2ddb99180..c0bb703ecc 100644 --- a/quantum/keymap_extras/keymap_bepo.h +++ b/quantum/keymap_extras/keymap_bepo.h @@ -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 // " diff --git a/quantum/keymap_extras/keymap_brazilian_abnt2.h b/quantum/keymap_extras/keymap_brazilian_abnt2.h index 730fe5069f..267b5490c9 100644 --- a/quantum/keymap_extras/keymap_brazilian_abnt2.h +++ b/quantum/keymap_extras/keymap_brazilian_abnt2.h @@ -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 diff --git a/quantum/keymap_extras/keymap_canadian_french.h b/quantum/keymap_extras/keymap_canadian_french.h index 5771cf6193..df9c73c016 100644 --- a/quantum/keymap_extras/keymap_canadian_french.h +++ b/quantum/keymap_extras/keymap_canadian_french.h @@ -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 diff --git a/quantum/keymap_extras/keymap_canadian_multilingual.h b/quantum/keymap_extras/keymap_canadian_multilingual.h index 2a4326b406..4b42457396 100644 --- a/quantum/keymap_extras/keymap_canadian_multilingual.h +++ b/quantum/keymap_extras/keymap_canadian_multilingual.h @@ -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 diff --git a/quantum/keymap_extras/keymap_colemak.h b/quantum/keymap_extras/keymap_colemak.h index 0170339aad..a4fc77e80f 100644 --- a/quantum/keymap_extras/keymap_colemak.h +++ b/quantum/keymap_extras/keymap_colemak.h @@ -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 diff --git a/quantum/keymap_extras/keymap_croatian.h b/quantum/keymap_extras/keymap_croatian.h index 7e11a85710..cdc032a9eb 100644 --- a/quantum/keymap_extras/keymap_croatian.h +++ b/quantum/keymap_extras/keymap_croatian.h @@ -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 diff --git a/quantum/keymap_extras/keymap_czech.h b/quantum/keymap_extras/keymap_czech.h index 8e65a4ed0a..cae16cdb9f 100644 --- a/quantum/keymap_extras/keymap_czech.h +++ b/quantum/keymap_extras/keymap_czech.h @@ -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 // + diff --git a/quantum/keymap_extras/keymap_czech_mac_ansi.h b/quantum/keymap_extras/keymap_czech_mac_ansi.h index ed46a78f1c..bdfda933b0 100644 --- a/quantum/keymap_extras/keymap_czech_mac_ansi.h +++ b/quantum/keymap_extras/keymap_czech_mac_ansi.h @@ -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 // + diff --git a/quantum/keymap_extras/keymap_czech_mac_iso.h b/quantum/keymap_extras/keymap_czech_mac_iso.h index 08285b7952..9c05d8dae0 100644 --- a/quantum/keymap_extras/keymap_czech_mac_iso.h +++ b/quantum/keymap_extras/keymap_czech_mac_iso.h @@ -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 // ě diff --git a/quantum/keymap_extras/keymap_danish.h b/quantum/keymap_extras/keymap_danish.h index a84923007c..1f1ee90e23 100644 --- a/quantum/keymap_extras/keymap_danish.h +++ b/quantum/keymap_extras/keymap_danish.h @@ -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 diff --git a/quantum/keymap_extras/keymap_dvorak.h b/quantum/keymap_extras/keymap_dvorak.h index a926e48295..5cb2c4564a 100644 --- a/quantum/keymap_extras/keymap_dvorak.h +++ b/quantum/keymap_extras/keymap_dvorak.h @@ -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 diff --git a/quantum/keymap_extras/keymap_dvorak_fr.h b/quantum/keymap_extras/keymap_dvorak_fr.h index 6e6498e598..d01bf7fec7 100644 --- a/quantum/keymap_extras/keymap_dvorak_fr.h +++ b/quantum/keymap_extras/keymap_dvorak_fr.h @@ -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 // » diff --git a/quantum/keymap_extras/keymap_dvorak_programmer.h b/quantum/keymap_extras/keymap_dvorak_programmer.h index 43d9a702bb..f17900105f 100644 --- a/quantum/keymap_extras/keymap_dvorak_programmer.h +++ b/quantum/keymap_extras/keymap_dvorak_programmer.h @@ -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 // & diff --git a/quantum/keymap_extras/keymap_estonian.h b/quantum/keymap_extras/keymap_estonian.h index 3e87bbc5f8..5fbeedcbe9 100644 --- a/quantum/keymap_extras/keymap_estonian.h +++ b/quantum/keymap_extras/keymap_estonian.h @@ -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 diff --git a/quantum/keymap_extras/keymap_eurkey.h b/quantum/keymap_extras/keymap_eurkey.h index 20f7f58683..5a13d48163 100644 --- a/quantum/keymap_extras/keymap_eurkey.h +++ b/quantum/keymap_extras/keymap_eurkey.h @@ -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 diff --git a/quantum/keymap_extras/keymap_farsi.h b/quantum/keymap_extras/keymap_farsi.h index 4f34b08d92..e115d9c1c0 100644 --- a/quantum/keymap_extras/keymap_farsi.h +++ b/quantum/keymap_extras/keymap_farsi.h @@ -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 // ۱ diff --git a/quantum/keymap_extras/keymap_finnish.h b/quantum/keymap_extras/keymap_finnish.h index 045f7295a0..cb21da9962 100644 --- a/quantum/keymap_extras/keymap_finnish.h +++ b/quantum/keymap_extras/keymap_finnish.h @@ -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 diff --git a/quantum/keymap_extras/keymap_french.h b/quantum/keymap_extras/keymap_french.h index 9ff3694a73..d4352c6481 100644 --- a/quantum/keymap_extras/keymap_french.h +++ b/quantum/keymap_extras/keymap_french.h @@ -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 // & diff --git a/quantum/keymap_extras/keymap_french_afnor.h b/quantum/keymap_extras/keymap_french_afnor.h index 07506e0f6e..8e6905cc01 100644 --- a/quantum/keymap_extras/keymap_french_afnor.h +++ b/quantum/keymap_extras/keymap_french_afnor.h @@ -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 // à diff --git a/quantum/keymap_extras/keymap_french_mac_iso.h b/quantum/keymap_extras/keymap_french_mac_iso.h index b036ca2009..ad9d280f2a 100644 --- a/quantum/keymap_extras/keymap_french_mac_iso.h +++ b/quantum/keymap_extras/keymap_french_mac_iso.h @@ -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 // & diff --git a/quantum/keymap_extras/keymap_german.h b/quantum/keymap_extras/keymap_german.h index 7ac807934b..bc98daa2fd 100644 --- a/quantum/keymap_extras/keymap_german.h +++ b/quantum/keymap_extras/keymap_german.h @@ -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 diff --git a/quantum/keymap_extras/keymap_german_mac_iso.h b/quantum/keymap_extras/keymap_german_mac_iso.h index 56d077c36c..ba3143c570 100644 --- a/quantum/keymap_extras/keymap_german_mac_iso.h +++ b/quantum/keymap_extras/keymap_german_mac_iso.h @@ -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 diff --git a/quantum/keymap_extras/keymap_greek.h b/quantum/keymap_extras/keymap_greek.h index 0d2e15dfd8..fb2f02a04f 100644 --- a/quantum/keymap_extras/keymap_greek.h +++ b/quantum/keymap_extras/keymap_greek.h @@ -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 diff --git a/quantum/keymap_extras/keymap_hebrew.h b/quantum/keymap_extras/keymap_hebrew.h index a927364737..5d1d4a29c6 100644 --- a/quantum/keymap_extras/keymap_hebrew.h +++ b/quantum/keymap_extras/keymap_hebrew.h @@ -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 diff --git a/quantum/keymap_extras/keymap_hungarian.h b/quantum/keymap_extras/keymap_hungarian.h index 81a842a0fe..27236553e8 100644 --- a/quantum/keymap_extras/keymap_hungarian.h +++ b/quantum/keymap_extras/keymap_hungarian.h @@ -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 diff --git a/quantum/keymap_extras/keymap_icelandic.h b/quantum/keymap_extras/keymap_icelandic.h index 8e4e04b0f1..409be27b77 100644 --- a/quantum/keymap_extras/keymap_icelandic.h +++ b/quantum/keymap_extras/keymap_icelandic.h @@ -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 diff --git a/quantum/keymap_extras/keymap_irish.h b/quantum/keymap_extras/keymap_irish.h index 6cb85dc7a7..587467bcbe 100644 --- a/quantum/keymap_extras/keymap_irish.h +++ b/quantum/keymap_extras/keymap_irish.h @@ -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 diff --git a/quantum/keymap_extras/keymap_italian.h b/quantum/keymap_extras/keymap_italian.h index 57c12ba9b6..9fd7f1b15c 100644 --- a/quantum/keymap_extras/keymap_italian.h +++ b/quantum/keymap_extras/keymap_italian.h @@ -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 diff --git a/quantum/keymap_extras/keymap_italian_mac_ansi.h b/quantum/keymap_extras/keymap_italian_mac_ansi.h index 4774c2d5ee..9ef38c0d87 100644 --- a/quantum/keymap_extras/keymap_italian_mac_ansi.h +++ b/quantum/keymap_extras/keymap_italian_mac_ansi.h @@ -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 diff --git a/quantum/keymap_extras/keymap_italian_mac_iso.h b/quantum/keymap_extras/keymap_italian_mac_iso.h index 35ec978ef9..e80cfa450c 100644 --- a/quantum/keymap_extras/keymap_italian_mac_iso.h +++ b/quantum/keymap_extras/keymap_italian_mac_iso.h @@ -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 diff --git a/quantum/keymap_extras/keymap_japanese.h b/quantum/keymap_extras/keymap_japanese.h index 3ad9495353..55df86e16d 100644 --- a/quantum/keymap_extras/keymap_japanese.h +++ b/quantum/keymap_extras/keymap_japanese.h @@ -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 diff --git a/quantum/keymap_extras/keymap_korean.h b/quantum/keymap_extras/keymap_korean.h index 644837734e..7bf64c4841 100644 --- a/quantum/keymap_extras/keymap_korean.h +++ b/quantum/keymap_extras/keymap_korean.h @@ -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 diff --git a/quantum/keymap_extras/keymap_latvian.h b/quantum/keymap_extras/keymap_latvian.h index b1750ed759..4d60c45163 100644 --- a/quantum/keymap_extras/keymap_latvian.h +++ b/quantum/keymap_extras/keymap_latvian.h @@ -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 diff --git a/quantum/keymap_extras/keymap_lithuanian_azerty.h b/quantum/keymap_extras/keymap_lithuanian_azerty.h index 9d6c1b92f0..e88cc75e07 100644 --- a/quantum/keymap_extras/keymap_lithuanian_azerty.h +++ b/quantum/keymap_extras/keymap_lithuanian_azerty.h @@ -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 // ! diff --git a/quantum/keymap_extras/keymap_lithuanian_qwerty.h b/quantum/keymap_extras/keymap_lithuanian_qwerty.h index 84df4c8bd2..3321615c1e 100644 --- a/quantum/keymap_extras/keymap_lithuanian_qwerty.h +++ b/quantum/keymap_extras/keymap_lithuanian_qwerty.h @@ -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 // Ą diff --git a/quantum/keymap_extras/keymap_neo2.h b/quantum/keymap_extras/keymap_neo2.h index ad285f7d18..5d10f19fd5 100644 --- a/quantum/keymap_extras/keymap_neo2.h +++ b/quantum/keymap_extras/keymap_neo2.h @@ -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 diff --git a/quantum/keymap_extras/keymap_nordic.h b/quantum/keymap_extras/keymap_nordic.h index ff952e6c43..3a11b29fc8 100644 --- a/quantum/keymap_extras/keymap_nordic.h +++ b/quantum/keymap_extras/keymap_nordic.h @@ -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 diff --git a/quantum/keymap_extras/keymap_norman.h b/quantum/keymap_extras/keymap_norman.h index 166a2f22a1..d47c2ff8a7 100644 --- a/quantum/keymap_extras/keymap_norman.h +++ b/quantum/keymap_extras/keymap_norman.h @@ -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 diff --git a/quantum/keymap_extras/keymap_norwegian.h b/quantum/keymap_extras/keymap_norwegian.h index 0b0cf65813..021b8c3b9c 100644 --- a/quantum/keymap_extras/keymap_norwegian.h +++ b/quantum/keymap_extras/keymap_norwegian.h @@ -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 diff --git a/quantum/keymap_extras/keymap_plover.h b/quantum/keymap_extras/keymap_plover.h index a01a23c8a3..e7facfd623 100644 --- a/quantum/keymap_extras/keymap_plover.h +++ b/quantum/keymap_extras/keymap_plover.h @@ -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 diff --git a/quantum/keymap_extras/keymap_plover_dvorak.h b/quantum/keymap_extras/keymap_plover_dvorak.h index 0ec7b9acd3..5c8a4f9ada 100644 --- a/quantum/keymap_extras/keymap_plover_dvorak.h +++ b/quantum/keymap_extras/keymap_plover_dvorak.h @@ -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 diff --git a/quantum/keymap_extras/keymap_polish.h b/quantum/keymap_extras/keymap_polish.h index 2448ef1fef..e5e48097f7 100644 --- a/quantum/keymap_extras/keymap_polish.h +++ b/quantum/keymap_extras/keymap_polish.h @@ -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 diff --git a/quantum/keymap_extras/keymap_portuguese.h b/quantum/keymap_extras/keymap_portuguese.h index 9f79862679..44abaf6537 100644 --- a/quantum/keymap_extras/keymap_portuguese.h +++ b/quantum/keymap_extras/keymap_portuguese.h @@ -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 diff --git a/quantum/keymap_extras/keymap_portuguese_mac_iso.h b/quantum/keymap_extras/keymap_portuguese_mac_iso.h index 5381956b4c..f2d04440fb 100644 --- a/quantum/keymap_extras/keymap_portuguese_mac_iso.h +++ b/quantum/keymap_extras/keymap_portuguese_mac_iso.h @@ -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 diff --git a/quantum/keymap_extras/keymap_romanian.h b/quantum/keymap_extras/keymap_romanian.h index 6410fbbe48..9a7239e032 100644 --- a/quantum/keymap_extras/keymap_romanian.h +++ b/quantum/keymap_extras/keymap_romanian.h @@ -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 diff --git a/quantum/keymap_extras/keymap_russian.h b/quantum/keymap_extras/keymap_russian.h index 364e7aba5c..b756a657df 100644 --- a/quantum/keymap_extras/keymap_russian.h +++ b/quantum/keymap_extras/keymap_russian.h @@ -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 diff --git a/quantum/keymap_extras/keymap_russian_typewriter.h b/quantum/keymap_extras/keymap_russian_typewriter.h index 18157726ad..45fb1ede04 100644 --- a/quantum/keymap_extras/keymap_russian_typewriter.h +++ b/quantum/keymap_extras/keymap_russian_typewriter.h @@ -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 // № diff --git a/quantum/keymap_extras/keymap_serbian.h b/quantum/keymap_extras/keymap_serbian.h index 6421577c22..202322b591 100644 --- a/quantum/keymap_extras/keymap_serbian.h +++ b/quantum/keymap_extras/keymap_serbian.h @@ -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 diff --git a/quantum/keymap_extras/keymap_serbian_latin.h b/quantum/keymap_extras/keymap_serbian_latin.h index 358c6c76ed..e863aa4ed8 100644 --- a/quantum/keymap_extras/keymap_serbian_latin.h +++ b/quantum/keymap_extras/keymap_serbian_latin.h @@ -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 diff --git a/quantum/keymap_extras/keymap_slovak.h b/quantum/keymap_extras/keymap_slovak.h index a777fce16f..f5848a6aaf 100644 --- a/quantum/keymap_extras/keymap_slovak.h +++ b/quantum/keymap_extras/keymap_slovak.h @@ -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 // + diff --git a/quantum/keymap_extras/keymap_slovenian.h b/quantum/keymap_extras/keymap_slovenian.h index 402a53cd44..502f06ad64 100644 --- a/quantum/keymap_extras/keymap_slovenian.h +++ b/quantum/keymap_extras/keymap_slovenian.h @@ -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 diff --git a/quantum/keymap_extras/keymap_spanish.h b/quantum/keymap_extras/keymap_spanish.h index 714c8cbb7c..dc23aea639 100644 --- a/quantum/keymap_extras/keymap_spanish.h +++ b/quantum/keymap_extras/keymap_spanish.h @@ -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 diff --git a/quantum/keymap_extras/keymap_spanish_dvorak.h b/quantum/keymap_extras/keymap_spanish_dvorak.h index b5a6463452..e19a84b7e5 100644 --- a/quantum/keymap_extras/keymap_spanish_dvorak.h +++ b/quantum/keymap_extras/keymap_spanish_dvorak.h @@ -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 diff --git a/quantum/keymap_extras/keymap_spanish_latin_america.h b/quantum/keymap_extras/keymap_spanish_latin_america.h index 651212d4bf..57329d20cd 100644 --- a/quantum/keymap_extras/keymap_spanish_latin_america.h +++ b/quantum/keymap_extras/keymap_spanish_latin_america.h @@ -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 diff --git a/quantum/keymap_extras/keymap_swedish.h b/quantum/keymap_extras/keymap_swedish.h index 23ec4102d8..a50f8af30d 100644 --- a/quantum/keymap_extras/keymap_swedish.h +++ b/quantum/keymap_extras/keymap_swedish.h @@ -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 diff --git a/quantum/keymap_extras/keymap_swedish_mac_ansi.h b/quantum/keymap_extras/keymap_swedish_mac_ansi.h index 18061f0be9..642c161dab 100644 --- a/quantum/keymap_extras/keymap_swedish_mac_ansi.h +++ b/quantum/keymap_extras/keymap_swedish_mac_ansi.h @@ -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 diff --git a/quantum/keymap_extras/keymap_swedish_mac_iso.h b/quantum/keymap_extras/keymap_swedish_mac_iso.h index 0c68ffcbd4..50387364cf 100644 --- a/quantum/keymap_extras/keymap_swedish_mac_iso.h +++ b/quantum/keymap_extras/keymap_swedish_mac_iso.h @@ -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 diff --git a/quantum/keymap_extras/keymap_swedish_pro_mac_ansi.h b/quantum/keymap_extras/keymap_swedish_pro_mac_ansi.h index 043a7c9fc2..be1581bb3d 100644 --- a/quantum/keymap_extras/keymap_swedish_pro_mac_ansi.h +++ b/quantum/keymap_extras/keymap_swedish_pro_mac_ansi.h @@ -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 diff --git a/quantum/keymap_extras/keymap_swedish_pro_mac_iso.h b/quantum/keymap_extras/keymap_swedish_pro_mac_iso.h index 1d691feef1..d50213f987 100644 --- a/quantum/keymap_extras/keymap_swedish_pro_mac_iso.h +++ b/quantum/keymap_extras/keymap_swedish_pro_mac_iso.h @@ -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 diff --git a/quantum/keymap_extras/keymap_swiss_de.h b/quantum/keymap_extras/keymap_swiss_de.h index 5411353a5f..4ebdb5c610 100644 --- a/quantum/keymap_extras/keymap_swiss_de.h +++ b/quantum/keymap_extras/keymap_swiss_de.h @@ -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 diff --git a/quantum/keymap_extras/keymap_swiss_fr.h b/quantum/keymap_extras/keymap_swiss_fr.h index a9a9cab162..11fcc6536d 100644 --- a/quantum/keymap_extras/keymap_swiss_fr.h +++ b/quantum/keymap_extras/keymap_swiss_fr.h @@ -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 diff --git a/quantum/keymap_extras/keymap_turkish_f.h b/quantum/keymap_extras/keymap_turkish_f.h index dcf9e815d7..bbdaa3af25 100644 --- a/quantum/keymap_extras/keymap_turkish_f.h +++ b/quantum/keymap_extras/keymap_turkish_f.h @@ -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 diff --git a/quantum/keymap_extras/keymap_turkish_q.h b/quantum/keymap_extras/keymap_turkish_q.h index a86af180cd..d3fa00d7ae 100644 --- a/quantum/keymap_extras/keymap_turkish_q.h +++ b/quantum/keymap_extras/keymap_turkish_q.h @@ -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 diff --git a/quantum/keymap_extras/keymap_uk.h b/quantum/keymap_extras/keymap_uk.h index 30f9b972db..7490af6cf6 100644 --- a/quantum/keymap_extras/keymap_uk.h +++ b/quantum/keymap_extras/keymap_uk.h @@ -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 diff --git a/quantum/keymap_extras/keymap_ukrainian.h b/quantum/keymap_extras/keymap_ukrainian.h index d3f82a2194..78e39f8c75 100644 --- a/quantum/keymap_extras/keymap_ukrainian.h +++ b/quantum/keymap_extras/keymap_ukrainian.h @@ -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 diff --git a/quantum/keymap_extras/keymap_us.h b/quantum/keymap_extras/keymap_us.h index 74c9b8e7f8..b6e380ab23 100644 --- a/quantum/keymap_extras/keymap_us.h +++ b/quantum/keymap_extras/keymap_us.h @@ -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) // ! diff --git a/quantum/keymap_extras/keymap_us_extended.h b/quantum/keymap_extras/keymap_us_extended.h index d17d3e603e..4262a7c44e 100644 --- a/quantum/keymap_extras/keymap_us_extended.h +++ b/quantum/keymap_extras/keymap_us_extended.h @@ -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 diff --git a/quantum/keymap_extras/keymap_us_international.h b/quantum/keymap_extras/keymap_us_international.h index a9617494a8..adc7051fe4 100644 --- a/quantum/keymap_extras/keymap_us_international.h +++ b/quantum/keymap_extras/keymap_us_international.h @@ -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 diff --git a/quantum/keymap_extras/keymap_us_international_linux.h b/quantum/keymap_extras/keymap_us_international_linux.h index b13039be05..db315968d6 100644 --- a/quantum/keymap_extras/keymap_us_international_linux.h +++ b/quantum/keymap_extras/keymap_us_international_linux.h @@ -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 diff --git a/quantum/keymap_extras/keymap_workman.h b/quantum/keymap_extras/keymap_workman.h index 29396fdec1..727e44512c 100644 --- a/quantum/keymap_extras/keymap_workman.h +++ b/quantum/keymap_extras/keymap_workman.h @@ -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 diff --git a/quantum/keymap_extras/keymap_workman_zxcvm.h b/quantum/keymap_extras/keymap_workman_zxcvm.h index f7a5689f0f..4655af60d6 100644 --- a/quantum/keymap_extras/keymap_workman_zxcvm.h +++ b/quantum/keymap_extras/keymap_workman_zxcvm.h @@ -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 diff --git a/quantum/keymap_introspection.c b/quantum/keymap_introspection.c index 23e842353a..99fd3f929e 100644 --- a/quantum/keymap_introspection.c +++ b/quantum/keymap_introspection.c @@ -13,6 +13,7 @@ # include INTROSPECTION_KEYMAP_C #endif // INTROSPECTION_KEYMAP_C +#include "compiler_support.h" #include "keymap_introspection.h" #include "util.h" @@ -30,9 +31,9 @@ __attribute__((weak)) uint8_t keymap_layer_count(void) { } #ifdef DYNAMIC_KEYMAP_ENABLE -_Static_assert(NUM_KEYMAP_LAYERS_RAW <= MAX_LAYER, "Number of keymap layers exceeds maximum set by DYNAMIC_KEYMAP_LAYER_COUNT"); +STATIC_ASSERT(NUM_KEYMAP_LAYERS_RAW <= MAX_LAYER, "Number of keymap layers exceeds maximum set by DYNAMIC_KEYMAP_LAYER_COUNT"); #else -_Static_assert(NUM_KEYMAP_LAYERS_RAW <= MAX_LAYER, "Number of keymap layers exceeds maximum set by LAYER_STATE_(8|16|32)BIT"); +STATIC_ASSERT(NUM_KEYMAP_LAYERS_RAW <= MAX_LAYER, "Number of keymap layers exceeds maximum set by LAYER_STATE_(8|16|32)BIT"); #endif uint16_t keycode_at_keymap_location_raw(uint8_t layer_num, uint8_t row, uint8_t column) { @@ -61,7 +62,7 @@ __attribute__((weak)) uint8_t encodermap_layer_count(void) { return encodermap_layer_count_raw(); } -_Static_assert(NUM_KEYMAP_LAYERS_RAW == NUM_ENCODERMAP_LAYERS_RAW, "Number of encoder_map layers doesn't match the number of keymap layers"); +STATIC_ASSERT(NUM_KEYMAP_LAYERS_RAW == NUM_ENCODERMAP_LAYERS_RAW, "Number of encoder_map layers doesn't match the number of keymap layers"); uint16_t keycode_at_encodermap_location_raw(uint8_t layer_num, uint8_t encoder_idx, bool clockwise) { if (layer_num < NUM_ENCODERMAP_LAYERS_RAW && encoder_idx < NUM_ENCODERS) { @@ -106,7 +107,7 @@ __attribute__((weak)) uint16_t combo_count(void) { return combo_count_raw(); } -_Static_assert(ARRAY_SIZE(key_combos) <= (QK_KB), "Number of combos is abnormally high. Are you using SAFE_RANGE in an enum for combos?"); +STATIC_ASSERT(ARRAY_SIZE(key_combos) <= (QK_KB), "Number of combos is abnormally high. Are you using SAFE_RANGE in an enum for combos?"); combo_t* combo_get_raw(uint16_t combo_idx) { if (combo_idx >= combo_count_raw()) { @@ -133,7 +134,7 @@ __attribute__((weak)) uint16_t tap_dance_count(void) { return tap_dance_count_raw(); } -_Static_assert(ARRAY_SIZE(tap_dance_actions) <= (QK_TAP_DANCE_MAX - QK_TAP_DANCE), "Number of tap dance actions exceeds maximum. Are you using SAFE_RANGE in tap dance enum?"); +STATIC_ASSERT(ARRAY_SIZE(tap_dance_actions) <= (QK_TAP_DANCE_MAX - QK_TAP_DANCE), "Number of tap dance actions exceeds maximum. Are you using SAFE_RANGE in tap dance enum?"); tap_dance_action_t* tap_dance_get_raw(uint16_t tap_dance_idx) { if (tap_dance_idx >= tap_dance_count_raw()) { @@ -161,7 +162,7 @@ __attribute__((weak)) uint16_t key_override_count(void) { return key_override_count_raw(); } -_Static_assert(ARRAY_SIZE(key_overrides) <= (QK_KB), "Number of key overrides is abnormally high. Are you using SAFE_RANGE in an enum for key overrides?"); +STATIC_ASSERT(ARRAY_SIZE(key_overrides) <= (QK_KB), "Number of key overrides is abnormally high. Are you using SAFE_RANGE in an enum for key overrides?"); const key_override_t* key_override_get_raw(uint16_t key_override_idx) { if (key_override_idx >= key_override_count_raw()) { diff --git a/quantum/led_matrix/led_matrix.c b/quantum/led_matrix/led_matrix.c index 58263c62e3..9c8004cc17 100644 --- a/quantum/led_matrix/led_matrix.c +++ b/quantum/led_matrix/led_matrix.c @@ -19,7 +19,6 @@ #include "led_matrix.h" #include "progmem.h" -#include "eeprom.h" #include "eeconfig.h" #include "keyboard.h" #include "sync_timer.h" @@ -46,6 +45,9 @@ const led_point_t k_led_matrix_center = LED_MATRIX_CENTER; #define LED_MATRIX_CUSTOM_EFFECT_IMPLS #include "led_matrix_effects.inc" +#ifdef COMMUNITY_MODULES_ENABLE +# include "led_matrix_community_modules.inc" +#endif #ifdef LED_MATRIX_CUSTOM_KB # include "led_matrix_kb.inc" #endif @@ -86,9 +88,9 @@ static last_hit_t last_hit_buffer; const uint8_t k_led_matrix_split[2] = LED_MATRIX_SPLIT; #endif -EECONFIG_DEBOUNCE_HELPER(led_matrix, EECONFIG_LED_MATRIX, led_matrix_eeconfig); +EECONFIG_DEBOUNCE_HELPER(led_matrix, led_matrix_eeconfig); -void eeconfig_update_led_matrix(void) { +void eeconfig_force_flush_led_matrix(void) { eeconfig_flush_led_matrix(true); } @@ -105,7 +107,11 @@ void eeconfig_update_led_matrix_default(void) { void eeconfig_debug_led_matrix(void) { dprintf("led_matrix_eeconfig EEPROM\n"); dprintf("led_matrix_eeconfig.enable = %d\n", led_matrix_eeconfig.enable); +#ifdef LED_MATRIX_MODE_NAME_ENABLE + dprintf("led_matrix_eeconfig.mode = %d (%s)\n", led_matrix_eeconfig.mode, led_matrix_get_mode_name(led_matrix_eeconfig.mode)); +#else dprintf("led_matrix_eeconfig.mode = %d\n", led_matrix_eeconfig.mode); +#endif // LED_MATRIX_MODE_NAME_ENABLE dprintf("led_matrix_eeconfig.val = %d\n", led_matrix_eeconfig.val); dprintf("led_matrix_eeconfig.speed = %d\n", led_matrix_eeconfig.speed); dprintf("led_matrix_eeconfig.flags = %d\n", led_matrix_eeconfig.flags); @@ -283,6 +289,15 @@ static void led_task_render(uint8_t effect) { #include "led_matrix_effects.inc" #undef LED_MATRIX_EFFECT +#ifdef COMMUNITY_MODULES_ENABLE +# define LED_MATRIX_EFFECT(name, ...) \ + case LED_MATRIX_COMMUNITY_MODULE_##name: \ + rendering = name(&led_effect_params); \ + break; +# include "led_matrix_community_modules.inc" +# undef LED_MATRIX_EFFECT +#endif + #if defined(LED_MATRIX_CUSTOM_KB) || defined(LED_MATRIX_CUSTOM_USER) # define LED_MATRIX_EFFECT(name, ...) \ case LED_MATRIX_CUSTOM_##name: \ @@ -359,7 +374,12 @@ void led_matrix_task(void) { } } +__attribute__((weak)) bool led_matrix_indicators_modules(void) { + return true; +} + void led_matrix_indicators(void) { + led_matrix_indicators_modules(); led_matrix_indicators_kb(); } @@ -371,6 +391,10 @@ __attribute__((weak)) bool led_matrix_indicators_user(void) { return true; } +__attribute__((weak)) bool led_matrix_indicators_advanced_modules(uint8_t led_min, uint8_t led_max) { + return true; +} + void led_matrix_indicators_advanced(effect_params_t *params) { /* special handling is needed for "params->iter", since it's already been incremented. * Could move the invocations to led_task_render, but then it's missing a few checks @@ -378,6 +402,7 @@ void led_matrix_indicators_advanced(effect_params_t *params) { * led_task_render, right before the iter++ line. */ LED_MATRIX_USE_LIMITS_ITER(min, max, params->iter - 1); + led_matrix_indicators_advanced_modules(min, max); led_matrix_indicators_advanced_kb(min, max); } @@ -504,7 +529,11 @@ void led_matrix_mode_eeprom_helper(uint8_t mode, bool write_to_eeprom) { } led_task_state = STARTING; eeconfig_flag_led_matrix(write_to_eeprom); - dprintf("led matrix mode [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", led_matrix_eeconfig.mode); +#ifdef LED_MATRIX_MODE_NAME_ENABLE + dprintf("led matrix mode [%s]: %u (%s)\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", (unsigned)led_matrix_eeconfig.mode, led_matrix_get_mode_name(led_matrix_eeconfig.mode)); +#else + dprintf("led matrix mode [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", (unsigned)led_matrix_eeconfig.mode); +#endif // LED_MATRIX_MODE_NAME_ENABLE } void led_matrix_mode_noeeprom(uint8_t mode) { led_matrix_mode_eeprom_helper(mode, false); @@ -631,3 +660,48 @@ void led_matrix_set_flags(led_flags_t flags) { void led_matrix_set_flags_noeeprom(led_flags_t flags) { led_matrix_set_flags_eeprom_helper(flags, false); } + +// LED Matrix naming +#undef LED_MATRIX_EFFECT +#ifdef LED_MATRIX_MODE_NAME_ENABLE +const char *led_matrix_get_mode_name(uint8_t mode) { + switch (mode) { + case LED_MATRIX_NONE: + return "NONE"; + +# define LED_MATRIX_EFFECT(name, ...) \ + case LED_MATRIX_##name: \ + return #name; +# include "led_matrix_effects.inc" +# undef LED_MATRIX_EFFECT + +# ifdef COMMUNITY_MODULES_ENABLE +# define LED_MATRIX_EFFECT(name, ...) \ + case LED_MATRIX_COMMUNITY_MODULE_##name: \ + return #name; +# include "led_matrix_community_modules.inc" +# undef LED_MATRIX_EFFECT +# endif // COMMUNITY_MODULES_ENABLE + +# if defined(LED_MATRIX_CUSTOM_KB) || defined(LED_MATRIX_CUSTOM_USER) +# define LED_MATRIX_EFFECT(name, ...) \ + case LED_MATRIX_CUSTOM_##name: \ + return #name; + +# ifdef LED_MATRIX_CUSTOM_KB +# include "led_matrix_kb.inc" +# endif // LED_MATRIX_CUSTOM_KB + +# ifdef LED_MATRIX_CUSTOM_USER +# include "led_matrix_user.inc" +# endif // LED_MATRIX_CUSTOM_USER + +# undef LED_MATRIX_EFFECT +# endif // LED_MATRIX_CUSTOM_KB || LED_MATRIX_CUSTOM_USER + + default: + return "UNKNOWN"; + } +} +# undef LED_MATRIX_EFFECT +#endif // LED_MATRIX_MODE_NAME_ENABLE diff --git a/quantum/led_matrix/led_matrix.h b/quantum/led_matrix/led_matrix.h index a3468a2003..9a49515ab2 100644 --- a/quantum/led_matrix/led_matrix.h +++ b/quantum/led_matrix/led_matrix.h @@ -98,6 +98,12 @@ enum led_matrix_effects { #include "led_matrix_effects.inc" #undef LED_MATRIX_EFFECT +#ifdef COMMUNITY_MODULES_ENABLE +# define LED_MATRIX_EFFECT(name, ...) LED_MATRIX_COMMUNITY_MODULE_##name, +# include "led_matrix_community_modules.inc" +# undef LED_MATRIX_EFFECT +#endif + #if defined(LED_MATRIX_CUSTOM_KB) || defined(LED_MATRIX_CUSTOM_USER) # define LED_MATRIX_EFFECT(name, ...) LED_MATRIX_CUSTOM_##name, # ifdef LED_MATRIX_CUSTOM_KB @@ -115,7 +121,7 @@ enum led_matrix_effects { }; void eeconfig_update_led_matrix_default(void); -void eeconfig_update_led_matrix(void); +void eeconfig_force_flush_led_matrix(void); void eeconfig_debug_led_matrix(void); uint8_t led_matrix_map_row_column_to_led_kb(uint8_t row, uint8_t column, uint8_t *led_i); @@ -178,6 +184,10 @@ led_flags_t led_matrix_get_flags(void); void led_matrix_set_flags(led_flags_t flags); void led_matrix_set_flags_noeeprom(led_flags_t flags); +#ifdef LED_MATRIX_MODE_NAME_ENABLE +const char *led_matrix_get_mode_name(uint8_t mode); +#endif // LED_MATRIX_MODE_NAME_ENABLE + static inline bool led_matrix_check_finished_leds(uint8_t led_idx) { #if defined(LED_MATRIX_SPLIT) if (is_keyboard_left()) { diff --git a/quantum/led_matrix/led_matrix_types.h b/quantum/led_matrix/led_matrix_types.h index 5a516ceb10..26a199701e 100644 --- a/quantum/led_matrix/led_matrix_types.h +++ b/quantum/led_matrix/led_matrix_types.h @@ -18,6 +18,8 @@ #include <stdint.h> #include <stdbool.h> + +#include "compiler_support.h" #include "util.h" #if defined(LED_MATRIX_KEYPRESSES) || defined(LED_MATRIX_KEYRELEASES) @@ -71,7 +73,7 @@ typedef struct PACKED { uint8_t flags[LED_MATRIX_LED_COUNT]; } led_config_t; -typedef union { +typedef union led_eeconfig_t { uint32_t raw; struct PACKED { uint8_t enable : 2; @@ -82,4 +84,4 @@ typedef union { }; } led_eeconfig_t; -_Static_assert(sizeof(led_eeconfig_t) == sizeof(uint32_t), "LED Matrix EECONFIG out of spec."); +STATIC_ASSERT(sizeof(led_eeconfig_t) == sizeof(uint32_t), "LED Matrix EECONFIG out of spec."); diff --git a/quantum/logging/debug.h b/quantum/logging/debug.h index b0d9b9a10e..6675680ec7 100644 --- a/quantum/logging/debug.h +++ b/quantum/logging/debug.h @@ -28,7 +28,7 @@ extern "C" { /* * Debug output control */ -typedef union { +typedef union debug_config_t { struct { bool enable : 1; bool matrix : 1; diff --git a/quantum/nvm/eeprom/nvm_dynamic_keymap.c b/quantum/nvm/eeprom/nvm_dynamic_keymap.c new file mode 100644 index 0000000000..5ff49795b2 --- /dev/null +++ b/quantum/nvm/eeprom/nvm_dynamic_keymap.c @@ -0,0 +1,194 @@ +// Copyright 2024 Nick Brassel (@tzarc) +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "compiler_support.h" +#include "keycodes.h" +#include "eeprom.h" +#include "dynamic_keymap.h" +#include "nvm_dynamic_keymap.h" +#include "nvm_eeprom_eeconfig_internal.h" +#include "nvm_eeprom_via_internal.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef ENCODER_ENABLE +# include "encoder.h" +#endif + +#ifdef VIA_ENABLE +# include "via.h" +# define DYNAMIC_KEYMAP_EEPROM_START (VIA_EEPROM_CONFIG_END) +#else +# define DYNAMIC_KEYMAP_EEPROM_START (EECONFIG_SIZE) +#endif + +#ifndef DYNAMIC_KEYMAP_EEPROM_MAX_ADDR +# define DYNAMIC_KEYMAP_EEPROM_MAX_ADDR (TOTAL_EEPROM_BYTE_COUNT - 1) +#endif + +STATIC_ASSERT(DYNAMIC_KEYMAP_EEPROM_MAX_ADDR <= (TOTAL_EEPROM_BYTE_COUNT - 1), "DYNAMIC_KEYMAP_EEPROM_MAX_ADDR is configured to use more space than what is available for the selected EEPROM driver"); + +// Due to usage of uint16_t check for max 65535 +STATIC_ASSERT(DYNAMIC_KEYMAP_EEPROM_MAX_ADDR <= 65535, "DYNAMIC_KEYMAP_EEPROM_MAX_ADDR must be less than 65536"); + +// 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 + +// Dynamic encoders starts after dynamic keymaps +#ifndef DYNAMIC_KEYMAP_ENCODER_EEPROM_ADDR +# define DYNAMIC_KEYMAP_ENCODER_EEPROM_ADDR (DYNAMIC_KEYMAP_EEPROM_ADDR + (DYNAMIC_KEYMAP_LAYER_COUNT * MATRIX_ROWS * MATRIX_COLS * 2)) +#endif + +// Dynamic macro starts after dynamic encoders, but only when using ENCODER_MAP +#ifdef ENCODER_MAP_ENABLE +# ifndef DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR +# define DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR (DYNAMIC_KEYMAP_ENCODER_EEPROM_ADDR + (DYNAMIC_KEYMAP_LAYER_COUNT * NUM_ENCODERS * 2 * 2)) +# endif // DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR +#else // ENCODER_MAP_ENABLE +# ifndef DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR +# define DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR (DYNAMIC_KEYMAP_ENCODER_EEPROM_ADDR) +# endif // DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR +#endif // ENCODER_MAP_ENABLE + +// 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((int64_t)(DYNAMIC_KEYMAP_EEPROM_MAX_ADDR) - (int64_t)(DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR) >= 100, "Dynamic keymaps are configured to use more EEPROM than is available."); + +#ifndef TOTAL_EEPROM_BYTE_COUNT +# error Unknown total EEPROM size. Cannot derive maximum for dynamic keymaps. +#endif +// 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) +#endif + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void nvm_dynamic_keymap_erase(void) { + // No-op, nvm_eeconfig_erase() will have already erased EEPROM if necessary. +} + +void nvm_dynamic_keymap_macro_erase(void) { + // No-op, nvm_eeconfig_erase() will have already erased EEPROM if necessary. +} + +static inline void *dynamic_keymap_key_to_eeprom_address(uint8_t layer, uint8_t row, uint8_t column) { + return ((void *)DYNAMIC_KEYMAP_EEPROM_ADDR) + (layer * MATRIX_ROWS * MATRIX_COLS * 2) + (row * MATRIX_COLS * 2) + (column * 2); +} + +uint16_t nvm_dynamic_keymap_read_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; +} + +void nvm_dynamic_keymap_update_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)); +} + +#ifdef ENCODER_MAP_ENABLE +static 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 nvm_dynamic_keymap_read_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; +} + +void nvm_dynamic_keymap_update_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)); +} +#endif // ENCODER_MAP_ENABLE + +void nvm_dynamic_keymap_read_buffer(uint32_t offset, uint32_t size, uint8_t *data) { + uint32_t dynamic_keymap_eeprom_size = DYNAMIC_KEYMAP_LAYER_COUNT * MATRIX_ROWS * MATRIX_COLS * 2; + void * source = (void *)(uintptr_t)(DYNAMIC_KEYMAP_EEPROM_ADDR + offset); + uint8_t *target = data; + for (uint32_t i = 0; i < size; i++) { + if (offset + i < dynamic_keymap_eeprom_size) { + *target = eeprom_read_byte(source); + } else { + *target = 0x00; + } + source++; + target++; + } +} + +void nvm_dynamic_keymap_update_buffer(uint32_t offset, uint32_t size, uint8_t *data) { + uint32_t dynamic_keymap_eeprom_size = DYNAMIC_KEYMAP_LAYER_COUNT * MATRIX_ROWS * MATRIX_COLS * 2; + void * target = (void *)(uintptr_t)(DYNAMIC_KEYMAP_EEPROM_ADDR + offset); + uint8_t *source = data; + for (uint32_t i = 0; i < size; i++) { + if (offset + i < dynamic_keymap_eeprom_size) { + eeprom_update_byte(target, *source); + } + source++; + target++; + } +} + +uint32_t nvm_dynamic_keymap_macro_size(void) { + return DYNAMIC_KEYMAP_MACRO_EEPROM_SIZE; +} + +void nvm_dynamic_keymap_macro_read_buffer(uint32_t offset, uint32_t size, uint8_t *data) { + void * source = (void *)(uintptr_t)(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++; + } +} + +void nvm_dynamic_keymap_macro_update_buffer(uint32_t offset, uint32_t size, uint8_t *data) { + void * target = (void *)(uintptr_t)(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++; + } +} + +void nvm_dynamic_keymap_macro_reset(void) { + void * start = (void *)(uintptr_t)(DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR); + void * end = (void *)(uintptr_t)(DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR + DYNAMIC_KEYMAP_MACRO_EEPROM_SIZE); + long remaining = end - start; + uint8_t dummy[16] = {0}; + for (int i = 0; i < DYNAMIC_KEYMAP_MACRO_EEPROM_SIZE; i += sizeof(dummy)) { + int this_loop = remaining < sizeof(dummy) ? remaining : sizeof(dummy); + eeprom_update_block(dummy, start, this_loop); + start += this_loop; + remaining -= this_loop; + } +} diff --git a/quantum/nvm/eeprom/nvm_eeconfig.c b/quantum/nvm/eeprom/nvm_eeconfig.c new file mode 100644 index 0000000000..d9495d2753 --- /dev/null +++ b/quantum/nvm/eeprom/nvm_eeconfig.c @@ -0,0 +1,305 @@ +// Copyright 2024 Nick Brassel (@tzarc) +// SPDX-License-Identifier: GPL-2.0-or-later +#include <string.h> +#include "nvm_eeconfig.h" +#include "nvm_eeprom_eeconfig_internal.h" +#include "util.h" +#include "eeconfig.h" +#include "debug.h" +#include "eeprom.h" +#include "keycode_config.h" + +#ifdef EEPROM_DRIVER +# include "eeprom_driver.h" +#endif + +#ifdef AUDIO_ENABLE +# include "audio.h" +#endif + +#ifdef BACKLIGHT_ENABLE +# include "backlight.h" +#endif + +#ifdef RGBLIGHT_ENABLE +# include "rgblight.h" +#endif + +#ifdef RGB_MATRIX_ENABLE +# include "rgb_matrix_types.h" +#endif + +#ifdef LED_MATRIX_ENABLE +# include "led_matrix_types.h" +#endif + +#ifdef UNICODE_COMMON_ENABLE +# include "unicode.h" +#endif + +#ifdef HAPTIC_ENABLE +# include "haptic.h" +#endif + +#ifdef CONNECTION_ENABLE +# include "connection.h" +#endif + +void nvm_eeconfig_erase(void) { +#ifdef EEPROM_DRIVER + eeprom_driver_format(false); +#endif // EEPROM_DRIVER +} + +bool nvm_eeconfig_is_enabled(void) { + return eeprom_read_word(EECONFIG_MAGIC) == EECONFIG_MAGIC_NUMBER; +} + +bool nvm_eeconfig_is_disabled(void) { + return eeprom_read_word(EECONFIG_MAGIC) == EECONFIG_MAGIC_NUMBER_OFF; +} + +void nvm_eeconfig_enable(void) { + eeprom_update_word(EECONFIG_MAGIC, EECONFIG_MAGIC_NUMBER); +} + +void nvm_eeconfig_disable(void) { +#if defined(EEPROM_DRIVER) + eeprom_driver_format(false); +#endif + eeprom_update_word(EECONFIG_MAGIC, EECONFIG_MAGIC_NUMBER_OFF); +} + +void nvm_eeconfig_read_debug(debug_config_t *debug_config) { + debug_config->raw = eeprom_read_byte(EECONFIG_DEBUG); +} +void nvm_eeconfig_update_debug(const debug_config_t *debug_config) { + eeprom_update_byte(EECONFIG_DEBUG, debug_config->raw); +} + +layer_state_t nvm_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 (layer_state_t)1 << val; +#else + // stored as 8-bit-wide bitmask, so read the value directly - handling padding to 16/32 bit layer_state_t + return (layer_state_t)val; +#endif +} +void nvm_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 = (uint8_t)state; +#endif + eeprom_update_byte(EECONFIG_DEFAULT_LAYER, val); +} + +void nvm_eeconfig_read_keymap(keymap_config_t *keymap_config) { + keymap_config->raw = eeprom_read_word(EECONFIG_KEYMAP); +} +void nvm_eeconfig_update_keymap(const keymap_config_t *keymap_config) { + eeprom_update_word(EECONFIG_KEYMAP, keymap_config->raw); +} + +#ifdef AUDIO_ENABLE +void nvm_eeconfig_read_audio(audio_config_t *audio_config) { + audio_config->raw = eeprom_read_byte(EECONFIG_AUDIO); +} +void nvm_eeconfig_update_audio(const audio_config_t *audio_config) { + eeprom_update_byte(EECONFIG_AUDIO, audio_config->raw); +} +#endif // AUDIO_ENABLE + +#ifdef UNICODE_COMMON_ENABLE +void nvm_eeconfig_read_unicode_mode(unicode_config_t *unicode_config) { + unicode_config->raw = eeprom_read_byte(EECONFIG_UNICODEMODE); +} +void nvm_eeconfig_update_unicode_mode(const unicode_config_t *unicode_config) { + eeprom_update_byte(EECONFIG_UNICODEMODE, unicode_config->raw); +} +#endif // UNICODE_COMMON_ENABLE + +#ifdef BACKLIGHT_ENABLE +void nvm_eeconfig_read_backlight(backlight_config_t *backlight_config) { + backlight_config->raw = eeprom_read_byte(EECONFIG_BACKLIGHT); +} +void nvm_eeconfig_update_backlight(const backlight_config_t *backlight_config) { + eeprom_update_byte(EECONFIG_BACKLIGHT, backlight_config->raw); +} +#endif // BACKLIGHT_ENABLE + +#ifdef STENO_ENABLE +uint8_t nvm_eeconfig_read_steno_mode(void) { + return eeprom_read_byte(EECONFIG_STENOMODE); +} +void nvm_eeconfig_update_steno_mode(uint8_t val) { + eeprom_update_byte(EECONFIG_STENOMODE, val); +} +#endif // STENO_ENABLE + +#ifdef RGBLIGHT_ENABLE +#endif // RGBLIGHT_ENABLE + +#ifdef RGB_MATRIX_ENABLE +void nvm_eeconfig_read_rgb_matrix(rgb_config_t *rgb_matrix_config) { + eeprom_read_block(rgb_matrix_config, EECONFIG_RGB_MATRIX, sizeof(rgb_config_t)); +} +void nvm_eeconfig_update_rgb_matrix(const rgb_config_t *rgb_matrix_config) { + eeprom_update_block(rgb_matrix_config, EECONFIG_RGB_MATRIX, sizeof(rgb_config_t)); +} +#endif // RGB_MATRIX_ENABLE + +#ifdef LED_MATRIX_ENABLE +void nvm_eeconfig_read_led_matrix(led_eeconfig_t *led_matrix_config) { + eeprom_read_block(led_matrix_config, EECONFIG_LED_MATRIX, sizeof(led_eeconfig_t)); +} +void nvm_eeconfig_update_led_matrix(const led_eeconfig_t *led_matrix_config) { + eeprom_update_block(led_matrix_config, EECONFIG_LED_MATRIX, sizeof(led_eeconfig_t)); +} +#endif // LED_MATRIX_ENABLE + +#ifdef RGBLIGHT_ENABLE +void nvm_eeconfig_read_rgblight(rgblight_config_t *rgblight_config) { + rgblight_config->raw = eeprom_read_dword(EECONFIG_RGBLIGHT); + rgblight_config->raw |= ((uint64_t)eeprom_read_byte(EECONFIG_RGBLIGHT_EXTENDED) << 32); +} +void nvm_eeconfig_update_rgblight(const rgblight_config_t *rgblight_config) { + eeprom_update_dword(EECONFIG_RGBLIGHT, rgblight_config->raw & 0xFFFFFFFF); + eeprom_update_byte(EECONFIG_RGBLIGHT_EXTENDED, (rgblight_config->raw >> 32) & 0xFF); +} +#endif // RGBLIGHT_ENABLE + +#if (EECONFIG_KB_DATA_SIZE) == 0 +uint32_t nvm_eeconfig_read_kb(void) { + return eeprom_read_dword(EECONFIG_KEYBOARD); +} +void nvm_eeconfig_update_kb(uint32_t val) { + eeprom_update_dword(EECONFIG_KEYBOARD, val); +} +#endif // (EECONFIG_KB_DATA_SIZE) == 0 + +#if (EECONFIG_USER_DATA_SIZE) == 0 +uint32_t nvm_eeconfig_read_user(void) { + return eeprom_read_dword(EECONFIG_USER); +} +void nvm_eeconfig_update_user(uint32_t val) { + eeprom_update_dword(EECONFIG_USER, val); +} +#endif // (EECONFIG_USER_DATA_SIZE) == 0 + +#ifdef HAPTIC_ENABLE +void nvm_eeconfig_read_haptic(haptic_config_t *haptic_config) { + haptic_config->raw = eeprom_read_dword(EECONFIG_HAPTIC); +} +void nvm_eeconfig_update_haptic(const haptic_config_t *haptic_config) { + eeprom_update_dword(EECONFIG_HAPTIC, haptic_config->raw); +} +#endif // HAPTIC_ENABLE + +#ifdef CONNECTION_ENABLE +void nvm_eeconfig_read_connection(connection_config_t *config) { + config->raw = eeprom_read_byte(EECONFIG_CONNECTION); +} +void nvm_eeconfig_update_connection(const connection_config_t *config) { + eeprom_update_byte(EECONFIG_CONNECTION, config->raw); +} +#endif // CONNECTION_ENABLE + +bool nvm_eeconfig_read_handedness(void) { + return !!eeprom_read_byte(EECONFIG_HANDEDNESS); +} +void nvm_eeconfig_update_handedness(bool val) { + eeprom_update_byte(EECONFIG_HANDEDNESS, !!val); +} + +#if (EECONFIG_KB_DATA_SIZE) > 0 + +bool nvm_eeconfig_is_kb_datablock_valid(void) { + return eeprom_read_dword(EECONFIG_KEYBOARD) == (EECONFIG_KB_DATA_VERSION); +} + +uint32_t nvm_eeconfig_read_kb_datablock(void *data, uint32_t offset, uint32_t length) { + if (eeconfig_is_kb_datablock_valid()) { + void *ee_start = (void *)(uintptr_t)(EECONFIG_KB_DATABLOCK + offset); + void *ee_end = (void *)(uintptr_t)(EECONFIG_KB_DATABLOCK + MIN(EECONFIG_KB_DATA_SIZE, offset + length)); + eeprom_read_block(data, ee_start, ee_end - ee_start); + return ee_end - ee_start; + } else { + memset(data, 0, length); + return length; + } +} + +uint32_t nvm_eeconfig_update_kb_datablock(const void *data, uint32_t offset, uint32_t length) { + eeprom_update_dword(EECONFIG_KEYBOARD, (EECONFIG_KB_DATA_VERSION)); + + void *ee_start = (void *)(uintptr_t)(EECONFIG_KB_DATABLOCK + offset); + void *ee_end = (void *)(uintptr_t)(EECONFIG_KB_DATABLOCK + MIN(EECONFIG_KB_DATA_SIZE, offset + length)); + eeprom_update_block(data, ee_start, ee_end - ee_start); + return ee_end - ee_start; +} + +void nvm_eeconfig_init_kb_datablock(void) { + eeprom_update_dword(EECONFIG_KEYBOARD, (EECONFIG_KB_DATA_VERSION)); + + void * start = (void *)(uintptr_t)(EECONFIG_KB_DATABLOCK); + void * end = (void *)(uintptr_t)(EECONFIG_KB_DATABLOCK + EECONFIG_KB_DATA_SIZE); + long remaining = end - start; + uint8_t dummy[16] = {0}; + for (int i = 0; i < EECONFIG_KB_DATA_SIZE; i += sizeof(dummy)) { + int this_loop = remaining < sizeof(dummy) ? remaining : sizeof(dummy); + eeprom_update_block(dummy, start, this_loop); + start += this_loop; + remaining -= this_loop; + } +} + +#endif // (EECONFIG_KB_DATA_SIZE) > 0 + +#if (EECONFIG_USER_DATA_SIZE) > 0 + +bool nvm_eeconfig_is_user_datablock_valid(void) { + return eeprom_read_dword(EECONFIG_USER) == (EECONFIG_USER_DATA_VERSION); +} + +uint32_t nvm_eeconfig_read_user_datablock(void *data, uint32_t offset, uint32_t length) { + if (eeconfig_is_user_datablock_valid()) { + void *ee_start = (void *)(uintptr_t)(EECONFIG_USER_DATABLOCK + offset); + void *ee_end = (void *)(uintptr_t)(EECONFIG_USER_DATABLOCK + MIN(EECONFIG_USER_DATA_SIZE, offset + length)); + eeprom_read_block(data, ee_start, ee_end - ee_start); + return ee_end - ee_start; + } else { + memset(data, 0, length); + return length; + } +} + +uint32_t nvm_eeconfig_update_user_datablock(const void *data, uint32_t offset, uint32_t length) { + eeprom_update_dword(EECONFIG_USER, (EECONFIG_USER_DATA_VERSION)); + + void *ee_start = (void *)(uintptr_t)(EECONFIG_USER_DATABLOCK + offset); + void *ee_end = (void *)(uintptr_t)(EECONFIG_USER_DATABLOCK + MIN(EECONFIG_USER_DATA_SIZE, offset + length)); + eeprom_update_block(data, ee_start, ee_end - ee_start); + return ee_end - ee_start; +} + +void nvm_eeconfig_init_user_datablock(void) { + eeprom_update_dword(EECONFIG_USER, (EECONFIG_USER_DATA_VERSION)); + + void * start = (void *)(uintptr_t)(EECONFIG_USER_DATABLOCK); + void * end = (void *)(uintptr_t)(EECONFIG_USER_DATABLOCK + EECONFIG_USER_DATA_SIZE); + long remaining = end - start; + uint8_t dummy[16] = {0}; + for (int i = 0; i < EECONFIG_USER_DATA_SIZE; i += sizeof(dummy)) { + int this_loop = remaining < sizeof(dummy) ? remaining : sizeof(dummy); + eeprom_update_block(dummy, start, this_loop); + start += this_loop; + remaining -= this_loop; + } +} + +#endif // (EECONFIG_USER_DATA_SIZE) > 0 diff --git a/quantum/nvm/eeprom/nvm_eeprom_eeconfig_internal.h b/quantum/nvm/eeprom/nvm_eeprom_eeconfig_internal.h new file mode 100644 index 0000000000..78b8190eaf --- /dev/null +++ b/quantum/nvm/eeprom/nvm_eeprom_eeconfig_internal.h @@ -0,0 +1,63 @@ +// Copyright 2024 Nick Brassel (@tzarc) +// SPDX-License-Identifier: GPL-2.0-or-later +#pragma once + +#include <stdint.h> +#include <stddef.h> // offsetof + +#include "compiler_support.h" +#include "eeconfig.h" +#include "util.h" + +// 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; + uint8_t connection; +} 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)) +#define EECONFIG_CONNECTION (uint8_t *)(offsetof(eeprom_core_t, connection)) + +// Size of EEPROM being used for core data storage +#define EECONFIG_BASE_SIZE ((uint8_t)sizeof(eeprom_core_t)) + +#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)) + +STATIC_ASSERT((intptr_t)EECONFIG_HANDEDNESS == 14, "EEPROM handedness offset is incorrect"); diff --git a/quantum/nvm/eeprom/nvm_eeprom_via_internal.h b/quantum/nvm/eeprom/nvm_eeprom_via_internal.h new file mode 100644 index 0000000000..bf0d38e2ac --- /dev/null +++ b/quantum/nvm/eeprom/nvm_eeprom_via_internal.h @@ -0,0 +1,22 @@ +// Copyright 2024 Nick Brassel (@tzarc) +// SPDX-License-Identifier: GPL-2.0-or-later +#pragma once + +// Keyboard level code can change where VIA stores the magic. +// The magic is the build date YYMMDD encoded as BCD in 3 bytes, +// thus installing firmware built on a different date to the one +// already installed can be detected and the EEPROM data is reset. +// The only reason this is important is in case EEPROM usage changes +// and the EEPROM was not explicitly reset by bootmagic lite. +#ifndef VIA_EEPROM_MAGIC_ADDR +# define VIA_EEPROM_MAGIC_ADDR (EECONFIG_SIZE) +#endif + +#define VIA_EEPROM_LAYOUT_OPTIONS_ADDR (VIA_EEPROM_MAGIC_ADDR + 3) + +// The end of the EEPROM memory used by VIA +// By default, dynamic keymaps will start at this if there is no +// custom config +#define VIA_EEPROM_CUSTOM_CONFIG_ADDR (VIA_EEPROM_LAYOUT_OPTIONS_ADDR + VIA_EEPROM_LAYOUT_OPTIONS_SIZE) + +#define VIA_EEPROM_CONFIG_END (VIA_EEPROM_CUSTOM_CONFIG_ADDR + VIA_EEPROM_CUSTOM_CONFIG_SIZE) diff --git a/quantum/nvm/eeprom/nvm_via.c b/quantum/nvm/eeprom/nvm_via.c new file mode 100644 index 0000000000..5372791fb7 --- /dev/null +++ b/quantum/nvm/eeprom/nvm_via.c @@ -0,0 +1,77 @@ +// Copyright 2024 Nick Brassel (@tzarc) +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "eeprom.h" +#include "util.h" +#include "via.h" +#include "nvm_via.h" +#include "nvm_eeprom_eeconfig_internal.h" +#include "nvm_eeprom_via_internal.h" + +void nvm_via_erase(void) { + // No-op, nvm_eeconfig_erase() will have already erased EEPROM if necessary. +} + +void nvm_via_read_magic(uint8_t *magic0, uint8_t *magic1, uint8_t *magic2) { + if (magic0) { + *magic0 = eeprom_read_byte((void *)VIA_EEPROM_MAGIC_ADDR + 0); + } + + if (magic1) { + *magic1 = eeprom_read_byte((void *)VIA_EEPROM_MAGIC_ADDR + 1); + } + + if (magic2) { + *magic2 = eeprom_read_byte((void *)VIA_EEPROM_MAGIC_ADDR + 2); + } +} + +void nvm_via_update_magic(uint8_t magic0, uint8_t magic1, uint8_t magic2) { + eeprom_update_byte((void *)VIA_EEPROM_MAGIC_ADDR + 0, magic0); + eeprom_update_byte((void *)VIA_EEPROM_MAGIC_ADDR + 1, magic1); + eeprom_update_byte((void *)VIA_EEPROM_MAGIC_ADDR + 2, magic2); +} + +uint32_t nvm_via_read_layout_options(void) { + uint32_t value = 0; + // Start at the most significant byte + void *source = (void *)(VIA_EEPROM_LAYOUT_OPTIONS_ADDR); + for (uint8_t i = 0; i < VIA_EEPROM_LAYOUT_OPTIONS_SIZE; i++) { + value = value << 8; + value |= eeprom_read_byte(source); + source++; + } + return value; +} + +void nvm_via_update_layout_options(uint32_t val) { + // Start at the least significant byte + void *target = (void *)(VIA_EEPROM_LAYOUT_OPTIONS_ADDR + VIA_EEPROM_LAYOUT_OPTIONS_SIZE - 1); + for (uint8_t i = 0; i < VIA_EEPROM_LAYOUT_OPTIONS_SIZE; i++) { + eeprom_update_byte(target, val & 0xFF); + val = val >> 8; + target--; + } +} + +uint32_t nvm_via_read_custom_config(void *buf, uint32_t offset, uint32_t length) { +#if VIA_EEPROM_CUSTOM_CONFIG_SIZE > 0 + void *ee_start = (void *)(uintptr_t)(VIA_EEPROM_CUSTOM_CONFIG_ADDR + offset); + void *ee_end = (void *)(uintptr_t)(VIA_EEPROM_CUSTOM_CONFIG_ADDR + MIN(VIA_EEPROM_CUSTOM_CONFIG_SIZE, offset + length)); + eeprom_read_block(buf, ee_start, ee_end - ee_start); + return ee_end - ee_start; +#else + return 0; +#endif +} + +uint32_t nvm_via_update_custom_config(const void *buf, uint32_t offset, uint32_t length) { +#if VIA_EEPROM_CUSTOM_CONFIG_SIZE > 0 + void *ee_start = (void *)(uintptr_t)(VIA_EEPROM_CUSTOM_CONFIG_ADDR + offset); + void *ee_end = (void *)(uintptr_t)(VIA_EEPROM_CUSTOM_CONFIG_ADDR + MIN(VIA_EEPROM_CUSTOM_CONFIG_SIZE, offset + length)); + eeprom_update_block(buf, ee_start, ee_end - ee_start); + return ee_end - ee_start; +#else + return 0; +#endif +} diff --git a/quantum/nvm/nvm_dynamic_keymap.h b/quantum/nvm/nvm_dynamic_keymap.h new file mode 100644 index 0000000000..d6e4aaee51 --- /dev/null +++ b/quantum/nvm/nvm_dynamic_keymap.h @@ -0,0 +1,27 @@ +// Copyright 2024 Nick Brassel (@tzarc) +// SPDX-License-Identifier: GPL-2.0-or-later +#pragma once + +#include <stdint.h> +#include <stdbool.h> + +void nvm_dynamic_keymap_erase(void); +void nvm_dynamic_keymap_macro_erase(void); + +uint16_t nvm_dynamic_keymap_read_keycode(uint8_t layer, uint8_t row, uint8_t column); +void nvm_dynamic_keymap_update_keycode(uint8_t layer, uint8_t row, uint8_t column, uint16_t keycode); + +#ifdef ENCODER_MAP_ENABLE +uint16_t nvm_dynamic_keymap_read_encoder(uint8_t layer, uint8_t encoder_id, bool clockwise); +void nvm_dynamic_keymap_update_encoder(uint8_t layer, uint8_t encoder_id, bool clockwise, uint16_t keycode); +#endif // ENCODER_MAP_ENABLE + +void nvm_dynamic_keymap_read_buffer(uint32_t offset, uint32_t size, uint8_t *data); +void nvm_dynamic_keymap_update_buffer(uint32_t offset, uint32_t size, uint8_t *data); + +uint32_t nvm_dynamic_keymap_macro_size(void); + +void nvm_dynamic_keymap_macro_read_buffer(uint32_t offset, uint32_t size, uint8_t *data); +void nvm_dynamic_keymap_macro_update_buffer(uint32_t offset, uint32_t size, uint8_t *data); + +void nvm_dynamic_keymap_macro_reset(void); diff --git a/quantum/nvm/nvm_eeconfig.h b/quantum/nvm/nvm_eeconfig.h new file mode 100644 index 0000000000..40827361ca --- /dev/null +++ b/quantum/nvm/nvm_eeconfig.h @@ -0,0 +1,111 @@ +// Copyright 2024 Nick Brassel (@tzarc) +// SPDX-License-Identifier: GPL-2.0-or-later +#pragma once + +#include <stdint.h> +#include <stdbool.h> +#include "action_layer.h" // layer_state_t + +#ifndef EECONFIG_MAGIC_NUMBER +# define EECONFIG_MAGIC_NUMBER (uint16_t)0xFEE3 // When changing, decrement this value to avoid future re-init issues +#endif +#define EECONFIG_MAGIC_NUMBER_OFF (uint16_t)0xFFFF + +void nvm_eeconfig_erase(void); + +bool nvm_eeconfig_is_enabled(void); +bool nvm_eeconfig_is_disabled(void); + +void nvm_eeconfig_enable(void); +void nvm_eeconfig_disable(void); + +typedef union debug_config_t debug_config_t; +void nvm_eeconfig_read_debug(debug_config_t *debug_config); +void nvm_eeconfig_update_debug(const debug_config_t *debug_config); + +layer_state_t nvm_eeconfig_read_default_layer(void); +void nvm_eeconfig_update_default_layer(layer_state_t state); + +typedef union keymap_config_t keymap_config_t; +void nvm_eeconfig_read_keymap(keymap_config_t *keymap_config); +void nvm_eeconfig_update_keymap(const keymap_config_t *keymap_config); + +#ifdef AUDIO_ENABLE +typedef union audio_config_t audio_config_t; +void nvm_eeconfig_read_audio(audio_config_t *audio_config); +void nvm_eeconfig_update_audio(const audio_config_t *audio_config); +#endif // AUDIO_ENABLE + +#ifdef UNICODE_COMMON_ENABLE +typedef union unicode_config_t unicode_config_t; +void nvm_eeconfig_read_unicode_mode(unicode_config_t *unicode_config); +void nvm_eeconfig_update_unicode_mode(const unicode_config_t *unicode_config); +#endif // UNICODE_COMMON_ENABLE + +#ifdef BACKLIGHT_ENABLE +typedef union backlight_config_t backlight_config_t; +void nvm_eeconfig_read_backlight(backlight_config_t *backlight_config); +void nvm_eeconfig_update_backlight(const backlight_config_t *backlight_config); +#endif // BACKLIGHT_ENABLE + +#ifdef STENO_ENABLE +uint8_t nvm_eeconfig_read_steno_mode(void); +void nvm_eeconfig_update_steno_mode(uint8_t val); +#endif // STENO_ENABLE + +#ifdef RGB_MATRIX_ENABLE +typedef union rgb_config_t rgb_config_t; +void nvm_eeconfig_read_rgb_matrix(rgb_config_t *rgb_matrix_config); +void nvm_eeconfig_update_rgb_matrix(const rgb_config_t *rgb_matrix_config); +#endif + +#ifdef LED_MATRIX_ENABLE +typedef union led_eeconfig_t led_eeconfig_t; +void nvm_eeconfig_read_led_matrix(led_eeconfig_t *led_matrix_config); +void nvm_eeconfig_update_led_matrix(const led_eeconfig_t *led_matrix_config); +#endif // LED_MATRIX_ENABLE + +#ifdef RGBLIGHT_ENABLE +typedef union rgblight_config_t rgblight_config_t; +void nvm_eeconfig_read_rgblight(rgblight_config_t *rgblight_config); +void nvm_eeconfig_update_rgblight(const rgblight_config_t *rgblight_config); +#endif // RGBLIGHT_ENABLE + +#if (EECONFIG_KB_DATA_SIZE) == 0 +uint32_t nvm_eeconfig_read_kb(void); +void nvm_eeconfig_update_kb(uint32_t val); +#endif // (EECONFIG_KB_DATA_SIZE) == 0 + +#if (EECONFIG_USER_DATA_SIZE) == 0 +uint32_t nvm_eeconfig_read_user(void); +void nvm_eeconfig_update_user(uint32_t val); +#endif // (EECONFIG_USER_DATA_SIZE) == 0 + +#ifdef HAPTIC_ENABLE +typedef union haptic_config_t haptic_config_t; +void nvm_eeconfig_read_haptic(haptic_config_t *haptic_config); +void nvm_eeconfig_update_haptic(const haptic_config_t *haptic_config); +#endif // HAPTIC_ENABLE + +#ifdef CONNECTION_ENABLE +typedef union connection_config_t connection_config_t; +void nvm_eeconfig_read_connection(connection_config_t *config); +void nvm_eeconfig_update_connection(const connection_config_t *config); +#endif // CONNECTION_ENABLE + +bool nvm_eeconfig_read_handedness(void); +void nvm_eeconfig_update_handedness(bool val); + +#if (EECONFIG_KB_DATA_SIZE) > 0 +bool nvm_eeconfig_is_kb_datablock_valid(void); +uint32_t nvm_eeconfig_read_kb_datablock(void *data, uint32_t offset, uint32_t length); +uint32_t nvm_eeconfig_update_kb_datablock(const void *data, uint32_t offset, uint32_t length); +void nvm_eeconfig_init_kb_datablock(void); +#endif // (EECONFIG_KB_DATA_SIZE) > 0 + +#if (EECONFIG_USER_DATA_SIZE) > 0 +bool nvm_eeconfig_is_user_datablock_valid(void); +uint32_t nvm_eeconfig_read_user_datablock(void *data, uint32_t offset, uint32_t length); +uint32_t nvm_eeconfig_update_user_datablock(const void *data, uint32_t offset, uint32_t length); +void nvm_eeconfig_init_user_datablock(void); +#endif // (EECONFIG_USER_DATA_SIZE) > 0 diff --git a/quantum/nvm/nvm_via.h b/quantum/nvm/nvm_via.h new file mode 100644 index 0000000000..90c5e67421 --- /dev/null +++ b/quantum/nvm/nvm_via.h @@ -0,0 +1,17 @@ +// Copyright 2024 Nick Brassel (@tzarc) +// SPDX-License-Identifier: GPL-2.0-or-later +#pragma once + +#include <stdint.h> +#include <stdbool.h> + +void nvm_via_erase(void); + +void nvm_via_read_magic(uint8_t *magic0, uint8_t *magic1, uint8_t *magic2); +void nvm_via_update_magic(uint8_t magic0, uint8_t magic1, uint8_t magic2); + +uint32_t nvm_via_read_layout_options(void); +void nvm_via_update_layout_options(uint32_t val); + +uint32_t nvm_via_read_custom_config(void *buf, uint32_t offset, uint32_t length); +uint32_t nvm_via_update_custom_config(const void *buf, uint32_t offset, uint32_t length); diff --git a/quantum/nvm/readme.md b/quantum/nvm/readme.md new file mode 100644 index 0000000000..0731695e92 --- /dev/null +++ b/quantum/nvm/readme.md @@ -0,0 +1,30 @@ +# Non-volatile Memory - Data Repositories + +This area is intentionally structured in the following way: + +``` +╰- quantum + ╰- nvm + ├- readme.md + ├- rules.mk + | + ├- nvm_eeconfig.h + ├- nvm_<<system>>.h + | + ├- eeprom + | ├- nvm_eeconfig.c + | ├- nvm_<<system>>.c + | ╰- ... + | + ├- <<another provider>> + | ├- nvm_eeconfig.c + | ├- nvm_<<system>>.c + | ╰- ... + ╰- ... +``` + +At the base `nvm` level, for every QMK core system which requires persistence there must be a corresponding `nvm_<<system>>.h` header file. This provides the data repository API to the "owner" system, and allows the underlying data persistence mechanism to be abstracted away from upper code. Any conversion to/from a `.raw` field should occur inside the `nvm_<<system>>.c` layer, with the API using values, such as structs or unions exposed to the rest of QMK. + +Each `nvm` "provider" is a corresponding child directory consisting of its name, such as `eeprom`, and corresponding `nvm_<<system>>.c` implementation files which provide the concrete implementation of the upper `nvm_<<system>>.h`. + +New systems requiring persistence can add the corresponding `nvm_<<system>>.h` file, and in most circumstances must also implement equivalent `nvm_<<system>>.c` files for every `nvm` provider. If persistence is not possible for that system, a `nvm_<<system>>.c` file with simple stubs which ignore writes and provide sane defaults must be used instead.
\ No newline at end of file diff --git a/quantum/nvm/rules.mk b/quantum/nvm/rules.mk new file mode 100644 index 0000000000..c9c1fabfd4 --- /dev/null +++ b/quantum/nvm/rules.mk @@ -0,0 +1,31 @@ +# Copyright 2024 Nick Brassel (@tzarc) +# SPDX-License-Identifier: GPL-2.0-or-later + +VPATH += $(QUANTUM_DIR)/nvm + +VALID_NVM_DRIVERS := eeprom custom none + +NVM_DRIVER ?= eeprom + +ifeq ($(filter $(NVM_DRIVER),$(VALID_NVM_DRIVERS)),) + $(call CATASTROPHIC_ERROR,Invalid NVM_DRIVER,NVM_DRIVER="$(NVM_DRIVER)" is not a valid NVM driver) +else + + # If we don't want one, fake it with transient eeprom. + ifeq ($(NVM_DRIVER),none) + NVM_DRIVER := eeprom + EEPROM_DRIVER := transient + endif + + NVM_DRIVER_UPPER := $(shell echo $(NVM_DRIVER) | tr '[:lower:]' '[:upper:]') + NVM_DRIVER_LOWER := $(shell echo $(NVM_DRIVER) | tr '[:upper:]' '[:lower:]') + + OPT_DEFS += -DNVM_DRIVER_$(NVM_DRIVER_UPPER) -DNVM_DRIVER="$(NVM_DRIVER)" + + ifneq ("$(wildcard $(QUANTUM_DIR)/nvm/$(NVM_DRIVER_LOWER))","") + COMMON_VPATH += $(QUANTUM_DIR)/nvm/$(NVM_DRIVER_LOWER) + endif + + QUANTUM_SRC += nvm_eeconfig.c + +endif diff --git a/quantum/os_detection.c b/quantum/os_detection.c index 9a9f9052f2..552375f61c 100644 --- a/quantum/os_detection.c +++ b/quantum/os_detection.c @@ -68,6 +68,15 @@ static volatile bool first_report = true; static volatile struct usb_device_state current_usb_device_state = {.configure_state = USB_DEVICE_STATE_NO_INIT}; static volatile struct usb_device_state maxprev_usb_device_state = {.configure_state = USB_DEVICE_STATE_NO_INIT}; +// to reset the keyboard on USB state change +#ifdef OS_DETECTION_KEYBOARD_RESET +# ifndef OS_DETECTION_RESET_DEBOUNCE +# define OS_DETECTION_RESET_DEBOUNCE OS_DETECTION_DEBOUNCE +# endif +static volatile fast_timer_t configured_since = 0; +static volatile bool reset_pending = false; +#endif + // the OS detection might be unstable for a while, "debounce" it static volatile bool debouncing = false; static volatile fast_timer_t last_time = 0; @@ -77,7 +86,10 @@ bool process_detected_host_os_modules(os_variant_t os); void os_detection_task(void) { #ifdef OS_DETECTION_KEYBOARD_RESET // resetting the keyboard on the USB device state change callback results in instability, so delegate that to this task - // only take action if it's been stable at least once, to avoid issues with some KVMs + if (reset_pending) { + soft_reset_keyboard(); + } + // reset the keyboard if it is stuck in the init state for longer than debounce duration, which can happen with some KVMs if (current_usb_device_state.configure_state <= USB_DEVICE_STATE_INIT && maxprev_usb_device_state.configure_state >= USB_DEVICE_STATE_CONFIGURED) { if (debouncing && timer_elapsed_fast(last_time) >= OS_DETECTION_DEBOUNCE) { soft_reset_keyboard(); @@ -187,6 +199,18 @@ void os_detection_notify_usb_device_state_change(struct usb_device_state usb_dev current_usb_device_state = usb_device_state; last_time = timer_read_fast(); debouncing = true; + +#ifdef OS_DETECTION_KEYBOARD_RESET + if (configured_since == 0 && current_usb_device_state.configure_state == USB_DEVICE_STATE_CONFIGURED) { + configured_since = timer_read_fast(); + } else if (current_usb_device_state.configure_state == USB_DEVICE_STATE_INIT) { + // reset the keyboard only if it's been stable for at least debounce duration, to avoid issues with some KVMs + if (configured_since > 0 && timer_elapsed_fast(configured_since) >= OS_DETECTION_RESET_DEBOUNCE) { + reset_pending = true; + } + configured_since = 0; + } +#endif } #if defined(SPLIT_KEYBOARD) && defined(SPLIT_DETECTED_OS_ENABLE) diff --git a/quantum/os_detection.h b/quantum/os_detection.h index 98a8e805e4..e9e7b25f1d 100644 --- a/quantum/os_detection.h +++ b/quantum/os_detection.h @@ -43,6 +43,9 @@ void slave_update_detected_host_os(os_variant_t os); #endif #ifdef OS_DETECTION_DEBUG_ENABLE +# if defined(DYNAMIC_KEYMAP_ENABLE) || defined(VIA_ENABLE) +# error Cannot enable OS Detection debug mode simultaneously with DYNAMIC_KEYMAP or VIA +# endif void print_stored_setups(void); void store_setups_in_eeprom(void); #endif diff --git a/quantum/painter/qff.h b/quantum/painter/qff.h index c3b831da17..ed88508d73 100644 --- a/quantum/painter/qff.h +++ b/quantum/painter/qff.h @@ -9,6 +9,7 @@ #include <stdint.h> #include <stdbool.h> +#include "compiler_support.h" #include "qp_stream.h" #include "qp_internal.h" #include "qgf.h" @@ -36,7 +37,7 @@ typedef struct QP_PACKED qff_font_descriptor_v1_t { uint8_t transparency_index; // palette index used for transparent pixels (not yet implemented) } qff_font_descriptor_v1_t; -_Static_assert(sizeof(qff_font_descriptor_v1_t) == (sizeof(qgf_block_header_v1_t) + 20), "qff_font_descriptor_v1_t must be 25 bytes in v1 of QFF"); +STATIC_ASSERT(sizeof(qff_font_descriptor_v1_t) == (sizeof(qgf_block_header_v1_t) + 20), "qff_font_descriptor_v1_t must be 25 bytes in v1 of QFF"); #define QFF_MAGIC 0x464651 @@ -54,14 +55,14 @@ typedef struct QP_PACKED qff_ascii_glyph_v1_t { uint32_t value : 24; // Uses QFF_GLYPH_*_(BITS|MASK) as bitfield ordering is compiler-defined } qff_ascii_glyph_v1_t; -_Static_assert(sizeof(qff_ascii_glyph_v1_t) == 3, "qff_ascii_glyph_v1_t must be 3 bytes in v1 of QFF"); +STATIC_ASSERT(sizeof(qff_ascii_glyph_v1_t) == 3, "qff_ascii_glyph_v1_t must be 3 bytes in v1 of QFF"); typedef struct QP_PACKED qff_ascii_glyph_table_v1_t { qgf_block_header_v1_t header; // = { .type_id = 0x01, .neg_type_id = (~0x01), .length = 285 } qff_ascii_glyph_v1_t glyph[95]; // 95 glyphs, 0x20..0x7E } qff_ascii_glyph_table_v1_t; -_Static_assert(sizeof(qff_ascii_glyph_table_v1_t) == (sizeof(qgf_block_header_v1_t) + (95 * sizeof(qff_ascii_glyph_v1_t))), "qff_ascii_glyph_table_v1_t must be 290 bytes in v1 of QFF"); +STATIC_ASSERT(sizeof(qff_ascii_glyph_table_v1_t) == (sizeof(qgf_block_header_v1_t) + (95 * sizeof(qff_ascii_glyph_v1_t))), "qff_ascii_glyph_table_v1_t must be 290 bytes in v1 of QFF"); ///////////////////////////////////////// // Unicode glyph table descriptor @@ -73,7 +74,7 @@ typedef struct QP_PACKED qff_unicode_glyph_v1_t { uint32_t value : 24; // Uses QFF_GLYPH_*_(BITS|MASK) as bitfield ordering is compiler-defined } qff_unicode_glyph_v1_t; -_Static_assert(sizeof(qff_unicode_glyph_v1_t) == 6, "qff_unicode_glyph_v1_t must be 6 bytes in v1 of QFF"); +STATIC_ASSERT(sizeof(qff_unicode_glyph_v1_t) == 6, "qff_unicode_glyph_v1_t must be 6 bytes in v1 of QFF"); typedef struct QP_PACKED qff_unicode_glyph_table_v1_t { qgf_block_header_v1_t header; // = { .type_id = 0x02, .neg_type_id = (~0x02), .length = (N * 6) } diff --git a/quantum/painter/qgf.h b/quantum/painter/qgf.h index 33a37709e6..a1e245f15d 100644 --- a/quantum/painter/qgf.h +++ b/quantum/painter/qgf.h @@ -9,6 +9,7 @@ #include <stdint.h> #include <stdbool.h> +#include "compiler_support.h" #include "qp_stream.h" #include "qp_internal.h" @@ -24,7 +25,7 @@ typedef struct QP_PACKED qgf_block_header_v1_t { uint32_t length : 24; // 24-bit blob length, allowing for block sizes of a maximum of 16MB. } qgf_block_header_v1_t; -_Static_assert(sizeof(qgf_block_header_v1_t) == 5, "qgf_block_header_v1_t must be 5 bytes in v1 of QGF"); +STATIC_ASSERT(sizeof(qgf_block_header_v1_t) == 5, "qgf_block_header_v1_t must be 5 bytes in v1 of QGF"); ///////////////////////////////////////// // Graphics descriptor @@ -42,7 +43,7 @@ typedef struct QP_PACKED qgf_graphics_descriptor_v1_t { uint16_t frame_count; // minimum of 1 } qgf_graphics_descriptor_v1_t; -_Static_assert(sizeof(qgf_graphics_descriptor_v1_t) == (sizeof(qgf_block_header_v1_t) + 18), "qgf_graphics_descriptor_v1_t must be 23 bytes in v1 of QGF"); +STATIC_ASSERT(sizeof(qgf_graphics_descriptor_v1_t) == (sizeof(qgf_block_header_v1_t) + 18), "qgf_graphics_descriptor_v1_t must be 23 bytes in v1 of QGF"); #define QGF_MAGIC 0x464751 @@ -56,7 +57,7 @@ typedef struct QP_PACKED qgf_frame_offsets_v1_t { uint32_t offset[0]; // '0' signifies that this struct is immediately followed by the frame offsets } qgf_frame_offsets_v1_t; -_Static_assert(sizeof(qgf_frame_offsets_v1_t) == sizeof(qgf_block_header_v1_t), "qgf_frame_offsets_v1_t must only contain qgf_block_header_v1_t in v1 of QGF"); +STATIC_ASSERT(sizeof(qgf_frame_offsets_v1_t) == sizeof(qgf_block_header_v1_t), "qgf_frame_offsets_v1_t must only contain qgf_block_header_v1_t in v1 of QGF"); ///////////////////////////////////////// // Frame descriptor @@ -72,7 +73,7 @@ typedef struct QP_PACKED qgf_frame_v1_t { uint16_t delay; // frame delay time for animations (in units of milliseconds) } qgf_frame_v1_t; -_Static_assert(sizeof(qgf_frame_v1_t) == (sizeof(qgf_block_header_v1_t) + 6), "qgf_frame_v1_t must be 11 bytes in v1 of QGF"); +STATIC_ASSERT(sizeof(qgf_frame_v1_t) == (sizeof(qgf_block_header_v1_t) + 6), "qgf_frame_v1_t must be 11 bytes in v1 of QGF"); #define QGF_FRAME_FLAG_DELTA 0x02 #define QGF_FRAME_FLAG_TRANSPARENT 0x01 @@ -88,14 +89,14 @@ typedef struct QP_PACKED qgf_palette_entry_v1_t { uint8_t v; // value component: `[0,1]` is mapped to `[0,255]` uint8_t. } qgf_palette_entry_v1_t; -_Static_assert(sizeof(qgf_palette_entry_v1_t) == 3, "Palette entry is not 3 bytes in size"); +STATIC_ASSERT(sizeof(qgf_palette_entry_v1_t) == 3, "Palette entry is not 3 bytes in size"); typedef struct QP_PACKED qgf_palette_v1_t { qgf_block_header_v1_t header; // = { .type_id = 0x03, .neg_type_id = (~0x03), .length = (N * 3 * sizeof(uint8_t)) } qgf_palette_entry_v1_t hsv[0]; // N * hsv, where N is the number of palette entries depending on the frame format in the descriptor } qgf_palette_v1_t; -_Static_assert(sizeof(qgf_palette_v1_t) == sizeof(qgf_block_header_v1_t), "qgf_palette_v1_t must only contain qgf_block_header_v1_t in v1 of QGF"); +STATIC_ASSERT(sizeof(qgf_palette_v1_t) == sizeof(qgf_block_header_v1_t), "qgf_palette_v1_t must only contain qgf_block_header_v1_t in v1 of QGF"); ///////////////////////////////////////// // Frame delta descriptor @@ -110,7 +111,7 @@ typedef struct QP_PACKED qgf_delta_v1_t { uint16_t bottom; // The bottom pixel location to to draw the delta image } qgf_delta_v1_t; -_Static_assert(sizeof(qgf_delta_v1_t) == (sizeof(qgf_block_header_v1_t) + 8), "qgf_delta_v1_t must be 13 bytes in v1 of QGF"); +STATIC_ASSERT(sizeof(qgf_delta_v1_t) == (sizeof(qgf_block_header_v1_t) + 8), "qgf_delta_v1_t must be 13 bytes in v1 of QGF"); ///////////////////////////////////////// // Frame data descriptor @@ -122,7 +123,7 @@ typedef struct QP_PACKED qgf_data_v1_t { uint8_t data[0]; // 0 signifies that this struct is immediately followed by the length of data specified in the header } qgf_data_v1_t; -_Static_assert(sizeof(qgf_data_v1_t) == sizeof(qgf_block_header_v1_t), "qgf_data_v1_t must only contain qgf_block_header_v1_t in v1 of QGF"); +STATIC_ASSERT(sizeof(qgf_data_v1_t) == sizeof(qgf_block_header_v1_t), "qgf_data_v1_t must only contain qgf_block_header_v1_t in v1 of QGF"); //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // QGF API diff --git a/quantum/painter/qp_draw_core.c b/quantum/painter/qp_draw_core.c index aa5fa4aa76..852abb19e8 100644 --- a/quantum/painter/qp_draw_core.c +++ b/quantum/painter/qp_draw_core.c @@ -2,12 +2,13 @@ // Copyright 2021 Paul Cotter (@gr1mr3aver) // SPDX-License-Identifier: GPL-2.0-or-later +#include "compiler_support.h" #include "qp_internal.h" #include "qp_comms.h" #include "qp_draw.h" #include "qgf.h" -_Static_assert((QUANTUM_PAINTER_PIXDATA_BUFFER_SIZE > 0) && (QUANTUM_PAINTER_PIXDATA_BUFFER_SIZE % 16) == 0, "QUANTUM_PAINTER_PIXDATA_BUFFER_SIZE needs to be a non-zero multiple of 16"); +STATIC_ASSERT((QUANTUM_PAINTER_PIXDATA_BUFFER_SIZE > 0) && (QUANTUM_PAINTER_PIXDATA_BUFFER_SIZE % 16) == 0, "QUANTUM_PAINTER_PIXDATA_BUFFER_SIZE needs to be a non-zero multiple of 16"); //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Global variables diff --git a/quantum/painter/qp_internal.c b/quantum/painter/qp_internal.c index 24b881bd09..fe0c598d78 100644 --- a/quantum/painter/qp_internal.c +++ b/quantum/painter/qp_internal.c @@ -3,6 +3,8 @@ #include "qp_internal.h" +#include "compiler_support.h" + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Quantum Painter Core API: device registration @@ -67,7 +69,7 @@ static void qp_internal_display_timeout_task(void) { //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Quantum Painter Core API: qp_internal_task -_Static_assert((QUANTUM_PAINTER_TASK_THROTTLE) > 0 && (QUANTUM_PAINTER_TASK_THROTTLE) < 1000, "QUANTUM_PAINTER_TASK_THROTTLE must be between 1 and 999"); +STATIC_ASSERT((QUANTUM_PAINTER_TASK_THROTTLE) > 0 && (QUANTUM_PAINTER_TASK_THROTTLE) < 1000, "QUANTUM_PAINTER_TASK_THROTTLE must be between 1 and 999"); void qp_internal_task(void) { // Perform throttling of the internal processing of Quantum Painter diff --git a/quantum/painter/qp_internal_formats.h b/quantum/painter/qp_internal_formats.h index 1beb604b9e..bd7105cab2 100644 --- a/quantum/painter/qp_internal_formats.h +++ b/quantum/painter/qp_internal_formats.h @@ -3,6 +3,7 @@ #pragma once +#include "compiler_support.h" #include "qp_internal.h" //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -29,7 +30,7 @@ typedef union QP_PACKED qp_pixel_t { uint32_t dummy; } qp_pixel_t; -_Static_assert(sizeof(qp_pixel_t) == 4, "Invalid size for qp_pixel_t"); +STATIC_ASSERT(sizeof(qp_pixel_t) == 4, "Invalid size for qp_pixel_t"); //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Quantum Painter image format diff --git a/quantum/pointing_device/pointing_device.c b/quantum/pointing_device/pointing_device.c index cac2875fc8..564c2d294c 100644 --- a/quantum/pointing_device/pointing_device.c +++ b/quantum/pointing_device/pointing_device.c @@ -25,6 +25,10 @@ # include "mousekey.h" #endif +#ifdef POINTING_DEVICE_HIRES_SCROLL_ENABLE +# include "usb_descriptor_common.h" +#endif + #if (defined(POINTING_DEVICE_ROTATION_90) + defined(POINTING_DEVICE_ROTATION_180) + defined(POINTING_DEVICE_ROTATION_270)) > 1 # error More than one rotation selected. This is not supported. #endif @@ -78,6 +82,9 @@ uint16_t pointing_device_get_shared_cpi(void) { static report_mouse_t local_mouse_report = {}; static bool pointing_device_force_send = false; +#ifdef POINTING_DEVICE_HIRES_SCROLL_ENABLE +static uint16_t hires_scroll_resolution; +#endif #define POINTING_DEVICE_DRIVER_CONCAT(name) name##_pointing_device_driver #define POINTING_DEVICE_DRIVER(name) POINTING_DEVICE_DRIVER_CONCAT(name) @@ -102,6 +109,11 @@ const pointing_device_driver_t custom_pointing_device_driver = { const pointing_device_driver_t *pointing_device_driver = &POINTING_DEVICE_DRIVER(POINTING_DEVICE_DRIVER_NAME); +__attribute__((weak)) void pointing_device_init_modules(void) {} +__attribute__((weak)) report_mouse_t pointing_device_task_modules(report_mouse_t mouse_report) { + return mouse_report; +} + /** * @brief Keyboard level code pointing device initialisation * @@ -176,7 +188,14 @@ __attribute__((weak)) void pointing_device_init(void) { # endif #endif } +#ifdef POINTING_DEVICE_HIRES_SCROLL_ENABLE + hires_scroll_resolution = POINTING_DEVICE_HIRES_SCROLL_MULTIPLIER; + for (int i = 0; i < POINTING_DEVICE_HIRES_SCROLL_EXPONENT; i++) { + hires_scroll_resolution *= 10; + } +#endif + pointing_device_init_modules(); pointing_device_init_kb(); pointing_device_init_user(); } @@ -306,8 +325,9 @@ __attribute__((weak)) bool pointing_device_task(void) { local_mouse_report = is_keyboard_left() ? pointing_device_task_combined_kb(local_mouse_report, shared_mouse_report) : pointing_device_task_combined_kb(shared_mouse_report, local_mouse_report); #else local_mouse_report = pointing_device_adjust_by_defines(local_mouse_report); - local_mouse_report = pointing_device_task_kb(local_mouse_report); #endif + local_mouse_report = pointing_device_task_modules(local_mouse_report); + local_mouse_report = pointing_device_task_kb(local_mouse_report); // automatic mouse layer function #ifdef POINTING_DEVICE_AUTO_MOUSE_ENABLE pointing_device_task_auto_mouse(local_mouse_report); @@ -404,10 +424,10 @@ void pointing_device_set_cpi_on_side(bool left, uint16_t cpi) { * @return mouse_hv_report_t clamped value */ static inline mouse_hv_report_t pointing_device_hv_clamp(hv_clamp_range_t value) { - if (value < HV_REPORT_MIN) { - return HV_REPORT_MIN; - } else if (value > HV_REPORT_MAX) { - return HV_REPORT_MAX; + if (value < MOUSE_REPORT_HV_MIN) { + return MOUSE_REPORT_HV_MIN; + } else if (value > MOUSE_REPORT_HV_MAX) { + return MOUSE_REPORT_HV_MAX; } else { return value; } @@ -420,10 +440,10 @@ static inline mouse_hv_report_t pointing_device_hv_clamp(hv_clamp_range_t value) * @return mouse_xy_report_t clamped value */ static inline mouse_xy_report_t pointing_device_xy_clamp(xy_clamp_range_t value) { - if (value < XY_REPORT_MIN) { - return XY_REPORT_MIN; - } else if (value > XY_REPORT_MAX) { - return XY_REPORT_MAX; + if (value < MOUSE_REPORT_XY_MIN) { + return MOUSE_REPORT_XY_MIN; + } else if (value > MOUSE_REPORT_XY_MAX) { + return MOUSE_REPORT_XY_MAX; } else { return value; } @@ -523,3 +543,9 @@ __attribute__((weak)) void pointing_device_keycode_handler(uint16_t keycode, boo pointing_device_send(); } } + +#ifdef POINTING_DEVICE_HIRES_SCROLL_ENABLE +uint16_t pointing_device_get_hires_scroll_resolution(void) { + return hires_scroll_resolution; +} +#endif
\ No newline at end of file diff --git a/quantum/pointing_device/pointing_device.h b/quantum/pointing_device/pointing_device.h index 72188c977d..e7a0819ed9 100644 --- a/quantum/pointing_device/pointing_device.h +++ b/quantum/pointing_device/pointing_device.h @@ -17,6 +17,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #pragma once +#include <stdbool.h> #include <stdint.h> #include "host.h" #include "report.h" @@ -92,27 +93,19 @@ typedef enum { } pointing_device_buttons_t; #ifdef MOUSE_EXTENDED_REPORT -# define XY_REPORT_MIN INT16_MIN -# define XY_REPORT_MAX INT16_MAX typedef int32_t xy_clamp_range_t; #else -# define XY_REPORT_MIN INT8_MIN -# define XY_REPORT_MAX INT8_MAX typedef int16_t xy_clamp_range_t; #endif #ifdef WHEEL_EXTENDED_REPORT -# define HV_REPORT_MIN INT16_MIN -# define HV_REPORT_MAX INT16_MAX typedef int32_t hv_clamp_range_t; #else -# define HV_REPORT_MIN INT8_MIN -# define HV_REPORT_MAX INT8_MAX typedef int16_t hv_clamp_range_t; #endif #define CONSTRAIN_HID(amt) ((amt) < INT8_MIN ? INT8_MIN : ((amt) > INT8_MAX ? INT8_MAX : (amt))) -#define CONSTRAIN_HID_XY(amt) ((amt) < XY_REPORT_MIN ? XY_REPORT_MIN : ((amt) > XY_REPORT_MAX ? XY_REPORT_MAX : (amt))) +#define CONSTRAIN_HID_XY(amt) ((amt) < MOUSE_REPORT_XY_MIN ? MOUSE_REPORT_XY_MIN : ((amt) > MOUSE_REPORT_XY_MAX ? MOUSE_REPORT_XY_MAX : (amt))) void pointing_device_init(void); bool pointing_device_task(void); @@ -130,6 +123,10 @@ uint8_t pointing_device_handle_buttons(uint8_t buttons, bool pressed, poi report_mouse_t pointing_device_adjust_by_defines(report_mouse_t mouse_report); void pointing_device_keycode_handler(uint16_t keycode, bool pressed); +#ifdef POINTING_DEVICE_HIRES_SCROLL_ENABLE +uint16_t pointing_device_get_hires_scroll_resolution(void); +#endif + #if defined(SPLIT_POINTING_ENABLE) void pointing_device_set_shared_report(report_mouse_t report); uint16_t pointing_device_get_shared_cpi(void); diff --git a/quantum/process_keycode/process_autocorrect.c b/quantum/process_keycode/process_autocorrect.c index b7f9132acf..0cde520778 100644 --- a/quantum/process_keycode/process_autocorrect.c +++ b/quantum/process_keycode/process_autocorrect.c @@ -38,7 +38,7 @@ bool autocorrect_is_enabled(void) { */ void autocorrect_enable(void) { keymap_config.autocorrect_enable = true; - eeconfig_update_keymap(keymap_config.raw); + eeconfig_update_keymap(&keymap_config); } /** @@ -48,7 +48,7 @@ void autocorrect_enable(void) { void autocorrect_disable(void) { keymap_config.autocorrect_enable = false; typo_buffer_size = 0; - eeconfig_update_keymap(keymap_config.raw); + eeconfig_update_keymap(&keymap_config); } /** @@ -58,7 +58,7 @@ void autocorrect_disable(void) { void autocorrect_toggle(void) { keymap_config.autocorrect_enable = !keymap_config.autocorrect_enable; typo_buffer_size = 0; - eeconfig_update_keymap(keymap_config.raw); + eeconfig_update_keymap(&keymap_config); } /** diff --git a/quantum/process_keycode/process_caps_word.c b/quantum/process_keycode/process_caps_word.c index b8fb868c6d..8ab66cc521 100644 --- a/quantum/process_keycode/process_caps_word.c +++ b/quantum/process_keycode/process_caps_word.c @@ -160,8 +160,13 @@ bool process_caps_word(uint16_t keycode, keyrecord_t* record) { case QK_TOGGLE_LAYER ... QK_TOGGLE_LAYER_MAX: case QK_LAYER_TAP_TOGGLE ... QK_LAYER_TAP_TOGGLE_MAX: case QK_ONE_SHOT_LAYER ... QK_ONE_SHOT_LAYER_MAX: +#ifdef TRI_LAYER_ENABLE // Ignore Tri Layer keys. case QK_TRI_LAYER_LOWER ... QK_TRI_LAYER_UPPER: - // Ignore AltGr. +#endif // TRI_LAYER_ENABLE +#ifdef LAYER_LOCK_ENABLE // Ignore Layer Lock key. + case QK_LAYER_LOCK: +#endif // LAYER_LOCK_ENABLE + // Ignore AltGr. case KC_RALT: case OSM(MOD_RALT): return true; diff --git a/quantum/process_keycode/process_clicky.c b/quantum/process_keycode/process_clicky.c index 82000db9b3..f50761268a 100644 --- a/quantum/process_keycode/process_clicky.c +++ b/quantum/process_keycode/process_clicky.c @@ -66,17 +66,17 @@ void clicky_freq_reset(void) { void clicky_toggle(void) { audio_config.clicky_enable ^= 1; - eeconfig_update_audio(audio_config.raw); + eeconfig_update_audio(&audio_config); } void clicky_on(void) { audio_config.clicky_enable = 1; - eeconfig_update_audio(audio_config.raw); + eeconfig_update_audio(&audio_config); } void clicky_off(void) { audio_config.clicky_enable = 0; - eeconfig_update_audio(audio_config.raw); + eeconfig_update_audio(&audio_config); } bool is_clicky_on(void) { diff --git a/quantum/process_keycode/process_connection.c b/quantum/process_keycode/process_connection.c index b0e230d680..501529ede7 100644 --- a/quantum/process_keycode/process_connection.c +++ b/quantum/process_keycode/process_connection.c @@ -1,24 +1,34 @@ // Copyright 2024 Nick Brassel (@tzarc) // SPDX-License-Identifier: GPL-2.0-or-later -#include "outputselect.h" +#include "connection.h" #include "process_connection.h" bool process_connection(uint16_t keycode, keyrecord_t *record) { if (record->event.pressed) { switch (keycode) { case QK_OUTPUT_NEXT: - set_output(OUTPUT_AUTO); // This should cycle through the outputs going forward. Ensure `docs/keycodes.md`, `docs/features/bluetooth.md` are updated when it does. + connection_next_host(); + return false; + case QK_OUTPUT_PREV: + connection_prev_host(); + return false; + + case QK_OUTPUT_AUTO: + connection_set_host(CONNECTION_HOST_AUTO); + return false; + case QK_OUTPUT_NONE: + connection_set_host(CONNECTION_HOST_NONE); return false; case QK_OUTPUT_USB: - set_output(OUTPUT_USB); + connection_set_host(CONNECTION_HOST_USB); return false; case QK_OUTPUT_BLUETOOTH: - set_output(OUTPUT_BLUETOOTH); + connection_set_host(CONNECTION_HOST_BLUETOOTH); return false; - - case QK_OUTPUT_PREV: - case QK_OUTPUT_NONE: case QK_OUTPUT_2P4GHZ: + connection_set_host(CONNECTION_HOST_2P4GHZ); + return false; + case QK_BLUETOOTH_PROFILE_NEXT: case QK_BLUETOOTH_PROFILE_PREV: case QK_BLUETOOTH_UNPAIR: diff --git a/quantum/process_keycode/process_leader.c b/quantum/process_keycode/process_leader.c index ca017a577d..a5466c513c 100644 --- a/quantum/process_keycode/process_leader.c +++ b/quantum/process_keycode/process_leader.c @@ -22,11 +22,7 @@ bool process_leader(uint16_t keycode, keyrecord_t *record) { if (record->event.pressed) { if (leader_sequence_active() && !leader_sequence_timed_out()) { #ifndef LEADER_KEY_STRICT_KEY_PROCESSING - if (IS_QK_MOD_TAP(keycode)) { - keycode = QK_MOD_TAP_GET_TAP_KEYCODE(keycode); - } else if (IS_QK_LAYER_TAP(keycode)) { - keycode = QK_LAYER_TAP_GET_TAP_KEYCODE(keycode); - } + keycode = get_tap_keycode(keycode); #endif if (!leader_sequence_add(keycode)) { diff --git a/quantum/process_keycode/process_magic.c b/quantum/process_keycode/process_magic.c index 3b35884d68..d5280105de 100644 --- a/quantum/process_keycode/process_magic.c +++ b/quantum/process_keycode/process_magic.c @@ -47,7 +47,7 @@ bool process_magic(uint16_t keycode, keyrecord_t *record) { if (record->event.pressed) { if (IS_MAGIC_KEYCODE(keycode)) { /* keymap config */ - keymap_config.raw = eeconfig_read_keymap(); + eeconfig_read_keymap(&keymap_config); switch (keycode) { case QK_MAGIC_SWAP_CONTROL_CAPS_LOCK: keymap_config.swap_control_capslock = true; @@ -187,7 +187,7 @@ bool process_magic(uint16_t keycode, keyrecord_t *record) { break; } - eeconfig_update_keymap(keymap_config.raw); + eeconfig_update_keymap(&keymap_config); clear_keyboard(); // clear to prevent stuck keys return false; diff --git a/quantum/process_keycode/process_oneshot.c b/quantum/process_keycode/process_oneshot.c new file mode 100644 index 0000000000..6c43da1011 --- /dev/null +++ b/quantum/process_keycode/process_oneshot.c @@ -0,0 +1,25 @@ +// Copyright 2025 QMK +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "process_oneshot.h" +#include "action_util.h" + +bool process_oneshot(uint16_t keycode, keyrecord_t *record) { +#ifndef NO_ACTION_ONESHOT + if (record->event.pressed) { + switch (keycode) { + case QK_ONE_SHOT_TOGGLE: + oneshot_toggle(); + return false; + case QK_ONE_SHOT_ON: + oneshot_enable(); + return false; + case QK_ONE_SHOT_OFF: + oneshot_disable(); + return false; + } + } +#endif + + return true; +} diff --git a/quantum/process_keycode/process_oneshot.h b/quantum/process_keycode/process_oneshot.h new file mode 100644 index 0000000000..11445b9b38 --- /dev/null +++ b/quantum/process_keycode/process_oneshot.h @@ -0,0 +1,10 @@ +// Copyright 2025 QMK +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include <stdint.h> +#include <stdbool.h> +#include "action.h" + +bool process_oneshot(uint16_t keycode, keyrecord_t *record); diff --git a/quantum/process_keycode/process_quantum.c b/quantum/process_keycode/process_quantum.c new file mode 100644 index 0000000000..703e00755b --- /dev/null +++ b/quantum/process_keycode/process_quantum.c @@ -0,0 +1,76 @@ +// Copyright 2025 QMK +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "process_quantum.h" +#include "quantum.h" + +#ifdef ENABLE_COMPILE_KEYCODE +/** \brief Compiles the firmware, and adds the flash command based on keyboard bootloader + */ +static void send_make_command(void) { +# ifdef NO_ACTION_ONESHOT + const uint8_t temp_mod = mod_config(get_mods()); +# else + const uint8_t temp_mod = mod_config(get_mods() | get_oneshot_mods()); + clear_oneshot_mods(); +# endif + clear_mods(); + + SEND_STRING_DELAY("qmk", TAP_CODE_DELAY); + if (temp_mod & MOD_MASK_SHIFT) { // if shift is held, flash rather than compile + SEND_STRING_DELAY(" flash ", TAP_CODE_DELAY); + } else { + SEND_STRING_DELAY(" compile ", TAP_CODE_DELAY); + } +# if defined(CONVERTER_ENABLED) + SEND_STRING_DELAY("-kb " QMK_KEYBOARD " -km " QMK_KEYMAP " -e CONVERT_TO=" CONVERTER_TARGET SS_TAP(X_ENTER), TAP_CODE_DELAY); +# else + SEND_STRING_DELAY("-kb " QMK_KEYBOARD " -km " QMK_KEYMAP SS_TAP(X_ENTER), TAP_CODE_DELAY); +# endif + if (temp_mod & MOD_MASK_SHIFT && temp_mod & MOD_MASK_CTRL) { + reset_keyboard(); + } +} +#endif + +bool process_quantum(uint16_t keycode, keyrecord_t *record) { + if (record->event.pressed) { + switch (keycode) { +#ifndef NO_RESET + case QK_BOOTLOADER: + reset_keyboard(); + return false; + case QK_REBOOT: + soft_reset_keyboard(); + return false; +#endif +#ifndef NO_DEBUG + case QK_DEBUG_TOGGLE: + debug_enable ^= 1; + if (debug_enable) { + print("DEBUG: enabled.\n"); + } else { + print("DEBUG: disabled.\n"); + } + return false; +#endif + case QK_CLEAR_EEPROM: +#ifdef NO_RESET + eeconfig_init(); +#else + eeconfig_disable(); + soft_reset_keyboard(); +#endif + return false; +#ifdef ENABLE_COMPILE_KEYCODE + case QK_MAKE: + send_make_command(); + return false; +#endif + default: + break; + } + } + + return true; +} diff --git a/quantum/process_keycode/process_quantum.h b/quantum/process_keycode/process_quantum.h new file mode 100644 index 0000000000..5c2462be01 --- /dev/null +++ b/quantum/process_keycode/process_quantum.h @@ -0,0 +1,10 @@ +// Copyright 2025 QMK +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include <stdint.h> +#include <stdbool.h> +#include "action.h" + +bool process_quantum(uint16_t keycode, keyrecord_t *record); diff --git a/quantum/process_keycode/process_repeat_key.c b/quantum/process_keycode/process_repeat_key.c index 73f4ddedcf..fdeed4f466 100644 --- a/quantum/process_keycode/process_repeat_key.c +++ b/quantum/process_keycode/process_repeat_key.c @@ -41,7 +41,10 @@ static bool remember_last_key(uint16_t keycode, keyrecord_t* record, uint8_t* re #ifdef TRI_LAYER_ENABLE // Ignore Tri Layer keys. case QK_TRI_LAYER_LOWER: case QK_TRI_LAYER_UPPER: -#endif // TRI_LAYER_ENABLE +#endif // TRI_LAYER_ENABLE +#ifdef LAYER_LOCK_ENABLE // Ignore Layer Lock key. + case QK_LAYER_LOCK: +#endif // LAYER_LOCK_ENABLE return false; // Ignore hold events on tap-hold keys. diff --git a/quantum/process_keycode/process_steno.c b/quantum/process_keycode/process_steno.c index c491d6f1d8..4789461352 100644 --- a/quantum/process_keycode/process_steno.c +++ b/quantum/process_keycode/process_steno.c @@ -20,9 +20,6 @@ #ifdef VIRTSER_ENABLE # include "virtser.h" #endif -#ifdef STENO_ENABLE_ALL -# include "eeprom.h" -#endif // All steno keys that have been pressed to form this chord, // stored in MAX_STROKE_SIZE groups of 8-bit arrays. @@ -128,13 +125,13 @@ static const uint16_t combinedmap_second[] PROGMEM = {STN_S2, STN_KL, STN_WL, ST #ifdef STENO_ENABLE_ALL void steno_init(void) { - mode = eeprom_read_byte(EECONFIG_STENOMODE); + mode = eeconfig_read_steno_mode(); } void steno_set_mode(steno_mode_t new_mode) { steno_clear_chord(); mode = new_mode; - eeprom_update_byte(EECONFIG_STENOMODE, mode); + eeconfig_update_steno_mode(mode); } #endif // STENO_ENABLE_ALL diff --git a/quantum/process_keycode/process_underglow.c b/quantum/process_keycode/process_underglow.c index b8d8989ef3..78006ee099 100644 --- a/quantum/process_keycode/process_underglow.c +++ b/quantum/process_keycode/process_underglow.c @@ -200,6 +200,11 @@ bool process_underglow(uint16_t keycode, keyrecord_t *record) { } #endif return false; +#ifdef VELOCIKEY_ENABLE + case QK_VELOCIKEY_TOGGLE: + velocikey_toggle(); + return false; +#endif } } diff --git a/quantum/quantum.c b/quantum/quantum.c index adb14d64b6..cc20c7db2b 100644 --- a/quantum/quantum.c +++ b/quantum/quantum.c @@ -15,12 +15,13 @@ */ #include "quantum.h" +#include "process_quantum.h" #ifdef BACKLIGHT_ENABLE # include "process_backlight.h" #endif -#ifdef BLUETOOTH_ENABLE +#ifdef CONNECTION_ENABLE # include "process_connection.h" #endif @@ -84,6 +85,10 @@ # include "process_layer_lock.h" #endif +#ifndef NO_ACTION_ONESHOT +# include "process_oneshot.h" +#endif + #ifdef AUDIO_ENABLE # ifndef GOODBYE_SONG # define GOODBYE_SONG SONG(GOODBYE_SOUND) @@ -174,10 +179,6 @@ __attribute__((weak)) bool pre_process_record_user(uint16_t keycode, keyrecord_t return true; } -__attribute__((weak)) bool process_action_kb(keyrecord_t *record) { - return true; -} - __attribute__((weak)) bool process_record_modules(uint16_t keycode, keyrecord_t *record) { return true; } @@ -292,9 +293,10 @@ void post_process_record_quantum(keyrecord_t *record) { post_process_record_kb(keycode, record); } -/* Core keycode function, hands off handling to other functions, - then processes internal quantum keycodes, and then processes - ACTIONs. */ +/** \brief Core keycode function + * + * Hands off handling to other quantum/process_keycode/ functions + */ bool process_record_quantum(keyrecord_t *record) { uint16_t keycode = get_record_keycode(record, true); @@ -436,88 +438,17 @@ bool process_record_quantum(keyrecord_t *record) { #ifdef LAYER_LOCK_ENABLE process_layer_lock(keycode, record) && #endif -#ifdef BLUETOOTH_ENABLE +#ifdef CONNECTION_ENABLE process_connection(keycode, record) && #endif - true)) { - return false; - } - - if (record->event.pressed) { - switch (keycode) { -#ifndef NO_RESET - case QK_BOOTLOADER: - reset_keyboard(); - return false; - case QK_REBOOT: - soft_reset_keyboard(); - return false; -#endif -#ifndef NO_DEBUG - case QK_DEBUG_TOGGLE: - debug_enable ^= 1; - if (debug_enable) { - print("DEBUG: enabled.\n"); - } else { - print("DEBUG: disabled.\n"); - } -#endif - return false; - case QK_CLEAR_EEPROM: -#ifdef NO_RESET - eeconfig_init(); -#else - eeconfig_disable(); - soft_reset_keyboard(); -#endif - return false; -#ifdef VELOCIKEY_ENABLE - case QK_VELOCIKEY_TOGGLE: - velocikey_toggle(); - return false; -#endif #ifndef NO_ACTION_ONESHOT - case QK_ONE_SHOT_TOGGLE: - oneshot_toggle(); - break; - case QK_ONE_SHOT_ON: - oneshot_enable(); - break; - case QK_ONE_SHOT_OFF: - oneshot_disable(); - break; -#endif -#ifdef ENABLE_COMPILE_KEYCODE - case QK_MAKE: // Compiles the firmware, and adds the flash command based on keyboard bootloader - { -# ifdef NO_ACTION_ONESHOT - const uint8_t temp_mod = mod_config(get_mods()); -# else - const uint8_t temp_mod = mod_config(get_mods() | get_oneshot_mods()); - clear_oneshot_mods(); -# endif - clear_mods(); - - SEND_STRING_DELAY("qmk", TAP_CODE_DELAY); - if (temp_mod & MOD_MASK_SHIFT) { // if shift is held, flash rather than compile - SEND_STRING_DELAY(" flash ", TAP_CODE_DELAY); - } else { - SEND_STRING_DELAY(" compile ", TAP_CODE_DELAY); - } -# if defined(CONVERTER_ENABLED) - SEND_STRING_DELAY("-kb " QMK_KEYBOARD " -km " QMK_KEYMAP " -e CONVERT_TO=" CONVERTER_TARGET SS_TAP(X_ENTER), TAP_CODE_DELAY); -# else - SEND_STRING_DELAY("-kb " QMK_KEYBOARD " -km " QMK_KEYMAP SS_TAP(X_ENTER), TAP_CODE_DELAY); -# endif - if (temp_mod & MOD_MASK_SHIFT && temp_mod & MOD_MASK_CTRL) { - reset_keyboard(); - } - } + process_oneshot(keycode, record) && #endif - } + process_quantum(keycode, record))) { + return false; } - return process_action_kb(record); + return true; } void set_single_default_layer(uint8_t default_layer) { diff --git a/quantum/quantum.h b/quantum/quantum.h index 59a415ead4..0036cd784b 100644 --- a/quantum/quantum.h +++ b/quantum/quantum.h @@ -39,6 +39,7 @@ #include "keymap_common.h" #include "quantum_keycodes.h" #include "keycode_config.h" +#include "keycode_string.h" #include "action_layer.h" #include "eeconfig.h" #include "bootloader.h" @@ -262,7 +263,6 @@ uint16_t get_event_keycode(keyevent_t event, bool update_layer_cache); bool pre_process_record_quantum(keyrecord_t *record); bool pre_process_record_kb(uint16_t keycode, keyrecord_t *record); bool pre_process_record_user(uint16_t keycode, keyrecord_t *record); -bool process_action_kb(keyrecord_t *record); bool process_record_kb(uint16_t keycode, keyrecord_t *record); bool process_record_user(uint16_t keycode, keyrecord_t *record); void post_process_record_kb(uint16_t keycode, keyrecord_t *record); diff --git a/quantum/raw_hid.c b/quantum/raw_hid.c new file mode 100644 index 0000000000..2c7a75f325 --- /dev/null +++ b/quantum/raw_hid.c @@ -0,0 +1,15 @@ +// Copyright 2025 QMK +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "raw_hid.h" +#include "host.h" + +void raw_hid_send(uint8_t *data, uint8_t length) { + host_raw_hid_send(data, length); +} + +__attribute__((weak)) void raw_hid_receive(uint8_t *data, uint8_t length) { + // Users should #include "raw_hid.h" in their own code + // and implement this function there. Leave this as weak linkage + // so users can opt to not handle data coming in. +} diff --git a/quantum/rgb_matrix/animations/pixel_flow_anim.h b/quantum/rgb_matrix/animations/pixel_flow_anim.h index 35170f9588..44b4b5c481 100644 --- a/quantum/rgb_matrix/animations/pixel_flow_anim.h +++ b/quantum/rgb_matrix/animations/pixel_flow_anim.h @@ -22,7 +22,7 @@ static bool PIXEL_FLOW(effect_params_t* params) { // Clear LEDs and fill the state array rgb_matrix_set_color_all(0, 0, 0); for (uint8_t j = 0; j < RGB_MATRIX_LED_COUNT; ++j) { - led[j] = (random8() & 2) ? (rgb_t){0, 0, 0} : hsv_to_rgb((hsv_t){random8(), random8_min_max(127, 255), rgb_matrix_config.hsv.v}); + led[j] = (random8() & 2) ? (rgb_t){0, 0, 0} : rgb_matrix_hsv_to_rgb((hsv_t){random8(), random8_min_max(127, 255), rgb_matrix_config.hsv.v}); } } @@ -39,7 +39,7 @@ static bool PIXEL_FLOW(effect_params_t* params) { led[j] = led[j + 1]; } // Fill last LED - led[led_max - 1] = (random8() & 2) ? (rgb_t){0, 0, 0} : hsv_to_rgb((hsv_t){random8(), random8_min_max(127, 255), rgb_matrix_config.hsv.v}); + led[led_max - 1] = (random8() & 2) ? (rgb_t){0, 0, 0} : rgb_matrix_hsv_to_rgb((hsv_t){random8(), random8_min_max(127, 255), rgb_matrix_config.hsv.v}); // Set pulse timer wait_timer = g_rgb_timer + interval(); } diff --git a/quantum/rgb_matrix/animations/rgb_matrix_effects.inc b/quantum/rgb_matrix/animations/rgb_matrix_effects.inc index a02238a2d1..abc2adf2cc 100644 --- a/quantum/rgb_matrix/animations/rgb_matrix_effects.inc +++ b/quantum/rgb_matrix/animations/rgb_matrix_effects.inc @@ -39,7 +39,8 @@ #include "solid_reactive_nexus.h" #include "splash_anim.h" #include "solid_splash_anim.h" +#include "starlight_smooth_anim.h" #include "starlight_anim.h" #include "starlight_dual_sat_anim.h" #include "starlight_dual_hue_anim.h" -#include "riverflow_anim.h"
\ No newline at end of file +#include "riverflow_anim.h" diff --git a/quantum/rgb_matrix/animations/starlight_smooth_anim.h b/quantum/rgb_matrix/animations/starlight_smooth_anim.h new file mode 100644 index 0000000000..a87c06f9df --- /dev/null +++ b/quantum/rgb_matrix/animations/starlight_smooth_anim.h @@ -0,0 +1,26 @@ +// Copyright 2022 @art-was-here +// SPDX-License-Identifier: GPL-2.0+ + +#ifdef ENABLE_RGB_MATRIX_STARLIGHT_SMOOTH +RGB_MATRIX_EFFECT(STARLIGHT_SMOOTH) +# ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS + +static uint8_t phase_offsets[RGB_MATRIX_LED_COUNT]; + +hsv_t STARLIGHT_SMOOTH_math(hsv_t hsv, uint8_t i, uint8_t time) { + if (phase_offsets[i] == 0) { + phase_offsets[i] = rand() % 255; + } + hsv.v = scale8(abs8(sin8((time + phase_offsets[i]) / 2) - 128) * 2, hsv.v); + return hsv; +} + +bool STARLIGHT_SMOOTH(effect_params_t* params) { + if (params->init) { + memset(phase_offsets, 0, sizeof(phase_offsets)); + } + return effect_runner_i(params, &STARLIGHT_SMOOTH_math); +} + +# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS +#endif // ENABLE_RGB_MATRIX_STARLIGHT_SMOOTH diff --git a/quantum/rgb_matrix/rgb_matrix.c b/quantum/rgb_matrix/rgb_matrix.c index 484d177546..ab0aa17512 100644 --- a/quantum/rgb_matrix/rgb_matrix.c +++ b/quantum/rgb_matrix/rgb_matrix.c @@ -18,7 +18,6 @@ #include "rgb_matrix.h" #include "progmem.h" -#include "eeprom.h" #include "eeconfig.h" #include "keyboard.h" #include "sync_timer.h" @@ -48,6 +47,9 @@ __attribute__((weak)) rgb_t rgb_matrix_hsv_to_rgb(hsv_t hsv) { #define RGB_MATRIX_CUSTOM_EFFECT_IMPLS #include "rgb_matrix_effects.inc" +#ifdef COMMUNITY_MODULES_ENABLE +# include "rgb_matrix_community_modules.inc" +#endif #ifdef RGB_MATRIX_CUSTOM_KB # include "rgb_matrix_kb.inc" #endif @@ -88,9 +90,9 @@ static last_hit_t last_hit_buffer; const uint8_t k_rgb_matrix_split[2] = RGB_MATRIX_SPLIT; #endif -EECONFIG_DEBOUNCE_HELPER(rgb_matrix, EECONFIG_RGB_MATRIX, rgb_matrix_config); +EECONFIG_DEBOUNCE_HELPER(rgb_matrix, rgb_matrix_config); -void eeconfig_update_rgb_matrix(void) { +void eeconfig_force_flush_rgb_matrix(void) { eeconfig_flush_rgb_matrix(true); } @@ -107,7 +109,11 @@ void eeconfig_update_rgb_matrix_default(void) { void eeconfig_debug_rgb_matrix(void) { dprintf("rgb_matrix_config EEPROM\n"); dprintf("rgb_matrix_config.enable = %d\n", rgb_matrix_config.enable); +#ifdef RGB_MATRIX_MODE_NAME_ENABLE + dprintf("rgb_matrix_config.mode = %d (%s)\n", rgb_matrix_config.mode, rgb_matrix_get_mode_name(rgb_matrix_config.mode)); +#else dprintf("rgb_matrix_config.mode = %d\n", rgb_matrix_config.mode); +#endif // RGB_MATRIX_MODE_NAME_ENABLE dprintf("rgb_matrix_config.hsv.h = %d\n", rgb_matrix_config.hsv.h); dprintf("rgb_matrix_config.hsv.s = %d\n", rgb_matrix_config.hsv.s); dprintf("rgb_matrix_config.hsv.v = %d\n", rgb_matrix_config.hsv.v); @@ -311,6 +317,15 @@ static void rgb_task_render(uint8_t effect) { #include "rgb_matrix_effects.inc" #undef RGB_MATRIX_EFFECT +#ifdef COMMUNITY_MODULES_ENABLE +# define RGB_MATRIX_EFFECT(name, ...) \ + case RGB_MATRIX_COMMUNITY_MODULE_##name: \ + rendering = name(&rgb_effect_params); \ + break; +# include "rgb_matrix_community_modules.inc" +# undef RGB_MATRIX_EFFECT +#endif + #if defined(RGB_MATRIX_CUSTOM_KB) || defined(RGB_MATRIX_CUSTOM_USER) # define RGB_MATRIX_EFFECT(name, ...) \ case RGB_MATRIX_CUSTOM_##name: \ @@ -394,7 +409,12 @@ void rgb_matrix_task(void) { } } +__attribute__((weak)) bool rgb_matrix_indicators_modules(void) { + return true; +} + void rgb_matrix_indicators(void) { + rgb_matrix_indicators_modules(); rgb_matrix_indicators_kb(); } @@ -434,6 +454,10 @@ struct rgb_matrix_limits_t rgb_matrix_get_limits(uint8_t iter) { return limits; } +__attribute__((weak)) bool rgb_matrix_indicators_advanced_modules(uint8_t led_min, uint8_t led_max) { + return true; +} + void rgb_matrix_indicators_advanced(effect_params_t *params) { /* special handling is needed for "params->iter", since it's already been incremented. * Could move the invocations to rgb_task_render, but then it's missing a few checks @@ -441,6 +465,7 @@ void rgb_matrix_indicators_advanced(effect_params_t *params) { * rgb_task_render, right before the iter++ line. */ RGB_MATRIX_USE_LIMITS_ITER(min, max, params->iter - 1); + rgb_matrix_indicators_advanced_modules(min, max); rgb_matrix_indicators_advanced_kb(min, max); } @@ -539,7 +564,11 @@ void rgb_matrix_mode_eeprom_helper(uint8_t mode, bool write_to_eeprom) { } rgb_task_state = STARTING; eeconfig_flag_rgb_matrix(write_to_eeprom); - dprintf("rgb matrix mode [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", rgb_matrix_config.mode); +#ifdef RGB_MATRIX_MODE_NAME_ENABLE + dprintf("rgb matrix mode [%s]: %u (%s)\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", (unsigned)rgb_matrix_config.mode, rgb_matrix_get_mode_name(rgb_matrix_config.mode)); +#else + dprintf("rgb matrix mode [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", (unsigned)rgb_matrix_config.mode); +#endif // RGB_MATRIX_MODE_NAME_ENABLE } void rgb_matrix_mode_noeeprom(uint8_t mode) { rgb_matrix_mode_eeprom_helper(mode, false); @@ -717,3 +746,49 @@ void rgb_matrix_set_flags(led_flags_t flags) { void rgb_matrix_set_flags_noeeprom(led_flags_t flags) { rgb_matrix_set_flags_eeprom_helper(flags, false); } + +//---------------------------------------------------------- +// RGB Matrix naming +#undef RGB_MATRIX_EFFECT +#ifdef RGB_MATRIX_MODE_NAME_ENABLE +const char *rgb_matrix_get_mode_name(uint8_t mode) { + switch (mode) { + case RGB_MATRIX_NONE: + return "NONE"; + +# define RGB_MATRIX_EFFECT(name, ...) \ + case RGB_MATRIX_##name: \ + return #name; +# include "rgb_matrix_effects.inc" +# undef RGB_MATRIX_EFFECT + +# ifdef COMMUNITY_MODULES_ENABLE +# define RGB_MATRIX_EFFECT(name, ...) \ + case RGB_MATRIX_COMMUNITY_MODULE_##name: \ + return #name; +# include "rgb_matrix_community_modules.inc" +# undef RGB_MATRIX_EFFECT +# endif // COMMUNITY_MODULES_ENABLE + +# if defined(RGB_MATRIX_CUSTOM_KB) || defined(RGB_MATRIX_CUSTOM_USER) +# define RGB_MATRIX_EFFECT(name, ...) \ + case RGB_MATRIX_CUSTOM_##name: \ + return #name; + +# ifdef RGB_MATRIX_CUSTOM_KB +# include "rgb_matrix_kb.inc" +# endif // RGB_MATRIX_CUSTOM_KB + +# ifdef RGB_MATRIX_CUSTOM_USER +# include "rgb_matrix_user.inc" +# endif // RGB_MATRIX_CUSTOM_USER + +# undef RGB_MATRIX_EFFECT +# endif // RGB_MATRIX_CUSTOM_KB || RGB_MATRIX_CUSTOM_USER + + default: + return "UNKNOWN"; + } +} +# undef RGB_MATRIX_EFFECT +#endif // RGB_MATRIX_MODE_NAME_ENABLE diff --git a/quantum/rgb_matrix/rgb_matrix.h b/quantum/rgb_matrix/rgb_matrix.h index 33f7e06a63..a91dded4a8 100644 --- a/quantum/rgb_matrix/rgb_matrix.h +++ b/quantum/rgb_matrix/rgb_matrix.h @@ -123,6 +123,12 @@ enum rgb_matrix_effects { #include "rgb_matrix_effects.inc" #undef RGB_MATRIX_EFFECT +#ifdef COMMUNITY_MODULES_ENABLE +# define RGB_MATRIX_EFFECT(name, ...) RGB_MATRIX_COMMUNITY_MODULE_##name, +# include "rgb_matrix_community_modules.inc" +# undef RGB_MATRIX_EFFECT +#endif + #if defined(RGB_MATRIX_CUSTOM_KB) || defined(RGB_MATRIX_CUSTOM_USER) # define RGB_MATRIX_EFFECT(name, ...) RGB_MATRIX_CUSTOM_##name, # ifdef RGB_MATRIX_CUSTOM_KB @@ -140,7 +146,7 @@ enum rgb_matrix_effects { }; void eeconfig_update_rgb_matrix_default(void); -void eeconfig_update_rgb_matrix(void); +void eeconfig_force_flush_rgb_matrix(void); uint8_t rgb_matrix_map_row_column_to_led_kb(uint8_t row, uint8_t column, uint8_t *led_i); uint8_t rgb_matrix_map_row_column_to_led(uint8_t row, uint8_t column, uint8_t *led_i); @@ -214,8 +220,12 @@ void rgb_matrix_set_flags(led_flags_t flags); void rgb_matrix_set_flags_noeeprom(led_flags_t flags); void rgb_matrix_update_pwm_buffers(void); +#ifdef RGB_MATRIX_MODE_NAME_ENABLE +const char *rgb_matrix_get_mode_name(uint8_t mode); +#endif // RGB_MATRIX_MODE_NAME_ENABLE + #ifndef RGBLIGHT_ENABLE -# define eeconfig_update_rgblight_current eeconfig_update_rgb_matrix +# define eeconfig_update_rgblight_current eeconfig_force_flush_rgb_matrix # define rgblight_reload_from_eeprom rgb_matrix_reload_from_eeprom # define rgblight_toggle rgb_matrix_toggle # define rgblight_toggle_noeeprom rgb_matrix_toggle_noeeprom diff --git a/quantum/rgb_matrix/rgb_matrix_types.h b/quantum/rgb_matrix/rgb_matrix_types.h index 0834a7067c..0115edee6a 100644 --- a/quantum/rgb_matrix/rgb_matrix_types.h +++ b/quantum/rgb_matrix/rgb_matrix_types.h @@ -18,6 +18,8 @@ #include <stdint.h> #include <stdbool.h> + +#include "compiler_support.h" #include "color.h" #include "util.h" @@ -73,7 +75,7 @@ typedef struct PACKED { uint8_t flags[RGB_MATRIX_LED_COUNT]; } led_config_t; -typedef union { +typedef union rgb_config_t { uint64_t raw; struct PACKED { uint8_t enable : 2; @@ -84,4 +86,4 @@ typedef union { }; } rgb_config_t; -_Static_assert(sizeof(rgb_config_t) == sizeof(uint64_t), "RGB Matrix EECONFIG out of spec."); +STATIC_ASSERT(sizeof(rgb_config_t) == sizeof(uint64_t), "RGB Matrix EECONFIG out of spec."); diff --git a/quantum/rgblight/rgblight.c b/quantum/rgblight/rgblight.c index ddccc9bae3..bfccb472b5 100644 --- a/quantum/rgblight/rgblight.c +++ b/quantum/rgblight/rgblight.c @@ -24,9 +24,7 @@ #include "util.h" #include "led_tables.h" #include <lib/lib8tion/lib8tion.h> -#ifdef EEPROM_ENABLE -# include "eeprom.h" -#endif +#include "eeconfig.h" #ifdef RGBLIGHT_SPLIT /* for split keyboard */ @@ -176,24 +174,9 @@ void rgblight_check_config(void) { } } -uint64_t eeconfig_read_rgblight(void) { -#ifdef EEPROM_ENABLE - return (uint64_t)((eeprom_read_dword(EECONFIG_RGBLIGHT)) | ((uint64_t)eeprom_read_byte(EECONFIG_RGBLIGHT_EXTENDED) << 32)); -#else - return 0; -#endif -} - -void eeconfig_update_rgblight(uint64_t val) { -#ifdef EEPROM_ENABLE - rgblight_check_config(); - eeprom_update_dword(EECONFIG_RGBLIGHT, val & 0xFFFFFFFF); - eeprom_update_byte(EECONFIG_RGBLIGHT_EXTENDED, (val >> 32) & 0xFF); -#endif -} - void eeconfig_update_rgblight_current(void) { - eeconfig_update_rgblight(rgblight_config.raw); + rgblight_check_config(); + eeconfig_update_rgblight(&rgblight_config); } void eeconfig_update_rgblight_default(void) { @@ -205,7 +188,7 @@ void eeconfig_update_rgblight_default(void) { rgblight_config.val = RGBLIGHT_DEFAULT_VAL; rgblight_config.speed = RGBLIGHT_DEFAULT_SPD; RGBLIGHT_SPLIT_SET_CHANGE_MODEHSVS; - eeconfig_update_rgblight(rgblight_config.raw); + eeconfig_update_rgblight(&rgblight_config); } void eeconfig_debug_rgblight(void) { @@ -228,12 +211,12 @@ void rgblight_init(void) { } dprintf("rgblight_init start!\n"); - rgblight_config.raw = eeconfig_read_rgblight(); + eeconfig_read_rgblight(&rgblight_config); RGBLIGHT_SPLIT_SET_CHANGE_MODEHSVS; if (!rgblight_config.mode) { dprintf("rgblight_init rgblight_config.mode = 0. Write default values to EEPROM.\n"); eeconfig_update_rgblight_default(); - rgblight_config.raw = eeconfig_read_rgblight(); + eeconfig_read_rgblight(&rgblight_config); } rgblight_check_config(); @@ -252,7 +235,7 @@ void rgblight_init(void) { void rgblight_reload_from_eeprom(void) { /* Reset back to what we have in eeprom */ - rgblight_config.raw = eeconfig_read_rgblight(); + eeconfig_read_rgblight(&rgblight_config); RGBLIGHT_SPLIT_SET_CHANGE_MODEHSVS; rgblight_check_config(); eeconfig_debug_rgblight(); // display current eeprom values @@ -341,7 +324,7 @@ void rgblight_mode_eeprom_helper(uint8_t mode, bool write_to_eeprom) { } RGBLIGHT_SPLIT_SET_CHANGE_MODE; if (write_to_eeprom) { - eeconfig_update_rgblight(rgblight_config.raw); + eeconfig_update_rgblight(&rgblight_config); dprintf("rgblight mode [EEPROM]: %u\n", rgblight_config.mode); } else { dprintf("rgblight mode [NOEEPROM]: %u\n", rgblight_config.mode); @@ -386,7 +369,7 @@ void rgblight_toggle_noeeprom(void) { void rgblight_enable(void) { rgblight_config.enable = 1; // No need to update EEPROM here. rgblight_mode() will do that, actually - // eeconfig_update_rgblight(rgblight_config.raw); + // eeconfig_update_rgblight(&rgblight_config); dprintf("rgblight enable [EEPROM]: rgblight_config.enable = %u\n", rgblight_config.enable); rgblight_mode(rgblight_config.mode); } @@ -399,7 +382,7 @@ void rgblight_enable_noeeprom(void) { void rgblight_disable(void) { rgblight_config.enable = 0; - eeconfig_update_rgblight(rgblight_config.raw); + eeconfig_update_rgblight(&rgblight_config); dprintf("rgblight disable [EEPROM]: rgblight_config.enable = %u\n", rgblight_config.enable); rgblight_timer_disable(); RGBLIGHT_SPLIT_SET_CHANGE_MODE; @@ -487,7 +470,7 @@ void rgblight_increase_speed_helper(bool write_to_eeprom) { if (rgblight_config.speed < 3) rgblight_config.speed++; // RGBLIGHT_SPLIT_SET_CHANGE_HSVS; // NEED? if (write_to_eeprom) { - eeconfig_update_rgblight(rgblight_config.raw); + eeconfig_update_rgblight(&rgblight_config); } } void rgblight_increase_speed(void) { @@ -501,7 +484,7 @@ void rgblight_decrease_speed_helper(bool write_to_eeprom) { if (rgblight_config.speed > 0) rgblight_config.speed--; // RGBLIGHT_SPLIT_SET_CHANGE_HSVS; // NEED?? if (write_to_eeprom) { - eeconfig_update_rgblight(rgblight_config.raw); + eeconfig_update_rgblight(&rgblight_config); } } void rgblight_decrease_speed(void) { @@ -513,7 +496,7 @@ void rgblight_decrease_speed_noeeprom(void) { void rgblight_sethsv_noeeprom_old(uint8_t hue, uint8_t sat, uint8_t val) { if (rgblight_config.enable) { - rgb_t rgb = hsv_to_rgb((hsv_t){hue, sat, val > RGBLIGHT_LIMIT_VAL ? RGBLIGHT_LIMIT_VAL : val}); + rgb_t rgb = rgblight_hsv_to_rgb((hsv_t){hue, sat, val > RGBLIGHT_LIMIT_VAL ? RGBLIGHT_LIMIT_VAL : val}); rgblight_setrgb(rgb.r, rgb.g, rgb.b); } } @@ -532,7 +515,7 @@ void rgblight_sethsv_eeprom_helper(uint8_t hue, uint8_t sat, uint8_t val, bool w // needed for rgblight_layers_write() to get the new val, since it reads rgblight_config.val rgblight_config.val = val; #endif - rgb_t rgb = hsv_to_rgb((hsv_t){hue, sat, val > RGBLIGHT_LIMIT_VAL ? RGBLIGHT_LIMIT_VAL : val}); + rgb_t rgb = rgblight_hsv_to_rgb((hsv_t){hue, sat, val > RGBLIGHT_LIMIT_VAL ? RGBLIGHT_LIMIT_VAL : val}); rgblight_setrgb(rgb.r, rgb.g, rgb.b); } else { // all LEDs in same color @@ -585,7 +568,7 @@ void rgblight_sethsv_eeprom_helper(uint8_t hue, uint8_t sat, uint8_t val, bool w rgblight_config.sat = sat; rgblight_config.val = val; if (write_to_eeprom) { - eeconfig_update_rgblight(rgblight_config.raw); + eeconfig_update_rgblight(&rgblight_config); dprintf("rgblight set hsv [EEPROM]: %u,%u,%u\n", rgblight_config.hue, rgblight_config.sat, rgblight_config.val); } else { dprintf("rgblight set hsv [NOEEPROM]: %u,%u,%u\n", rgblight_config.hue, rgblight_config.sat, rgblight_config.val); @@ -608,7 +591,7 @@ uint8_t rgblight_get_speed(void) { void rgblight_set_speed_eeprom_helper(uint8_t speed, bool write_to_eeprom) { rgblight_config.speed = speed; if (write_to_eeprom) { - eeconfig_update_rgblight(rgblight_config.raw); + eeconfig_update_rgblight(&rgblight_config); dprintf("rgblight set speed [EEPROM]: %u\n", rgblight_config.speed); } else { dprintf("rgblight set speed [NOEEPROM]: %u\n", rgblight_config.speed); @@ -664,7 +647,7 @@ void rgblight_sethsv_at(uint8_t hue, uint8_t sat, uint8_t val, uint8_t index) { return; } - rgb_t rgb = hsv_to_rgb((hsv_t){hue, sat, val > RGBLIGHT_LIMIT_VAL ? RGBLIGHT_LIMIT_VAL : val}); + rgb_t rgb = rgblight_hsv_to_rgb((hsv_t){hue, sat, val > RGBLIGHT_LIMIT_VAL ? RGBLIGHT_LIMIT_VAL : val}); rgblight_setrgb_at(rgb.r, rgb.g, rgb.b, index); } @@ -696,7 +679,7 @@ void rgblight_sethsv_range(uint8_t hue, uint8_t sat, uint8_t val, uint8_t start, return; } - rgb_t rgb = hsv_to_rgb((hsv_t){hue, sat, val > RGBLIGHT_LIMIT_VAL ? RGBLIGHT_LIMIT_VAL : val}); + rgb_t rgb = rgblight_hsv_to_rgb((hsv_t){hue, sat, val > RGBLIGHT_LIMIT_VAL ? RGBLIGHT_LIMIT_VAL : val}); rgblight_setrgb_range(rgb.r, rgb.g, rgb.b, start, end); } diff --git a/quantum/rgblight/rgblight.h b/quantum/rgblight/rgblight.h index f4b6e621e4..c061e71895 100644 --- a/quantum/rgblight/rgblight.h +++ b/quantum/rgblight/rgblight.h @@ -16,6 +16,8 @@ #pragma once +#include "compiler_support.h" + // DEPRECATED DEFINES - DO NOT USE #if defined(RGBLED_NUM) # define RGBLIGHT_LED_COUNT RGBLED_NUM @@ -168,7 +170,6 @@ enum RGBLIGHT_EFFECT_MODE { #include <stdbool.h> #include "rgblight_drivers.h" #include "progmem.h" -#include "eeconfig.h" #include "color.h" #ifdef RGBLIGHT_LAYERS @@ -248,7 +249,7 @@ extern const uint16_t RGBLED_RGBTEST_INTERVALS[1] PROGMEM; extern const uint8_t RGBLED_TWINKLE_INTERVALS[3] PROGMEM; extern bool is_rgblight_initialized; -typedef union { +typedef union rgblight_config_t { uint64_t raw; struct { bool enable : 1; @@ -261,7 +262,7 @@ typedef union { }; } rgblight_config_t; -_Static_assert(sizeof(rgblight_config_t) == sizeof(uint64_t), "RGB Light EECONFIG out of spec."); +STATIC_ASSERT(sizeof(rgblight_config_t) == sizeof(uint64_t), "RGB Light EECONFIG out of spec."); typedef struct _rgblight_status_t { uint8_t base_mode; @@ -370,8 +371,6 @@ void rgblight_suspend(void); void rgblight_wakeup(void); uint64_t rgblight_read_qword(void); void rgblight_update_qword(uint64_t qword); -uint64_t eeconfig_read_rgblight(void); -void eeconfig_update_rgblight(uint64_t val); void eeconfig_update_rgblight_current(void); void eeconfig_update_rgblight_default(void); void eeconfig_debug_rgblight(void); diff --git a/quantum/split_common/split_util.c b/quantum/split_common/split_util.c index 9af3c29d75..59b6009ec4 100644 --- a/quantum/split_common/split_util.c +++ b/quantum/split_common/split_util.c @@ -13,6 +13,8 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include "compiler_support.h" #include "split_util.h" #include "matrix.h" #include "keyboard.h" @@ -62,7 +64,7 @@ static struct { } split_config; #if defined(SPLIT_USB_DETECT) -_Static_assert((SPLIT_USB_TIMEOUT / SPLIT_USB_TIMEOUT_POLL) <= UINT16_MAX, "Please lower SPLIT_USB_TIMEOUT and/or increase SPLIT_USB_TIMEOUT_POLL."); +STATIC_ASSERT((SPLIT_USB_TIMEOUT / SPLIT_USB_TIMEOUT_POLL) <= UINT16_MAX, "Please lower SPLIT_USB_TIMEOUT and/or increase SPLIT_USB_TIMEOUT_POLL."); static bool usb_bus_detected(void) { for (uint16_t i = 0; i < (SPLIT_USB_TIMEOUT / SPLIT_USB_TIMEOUT_POLL); i++) { // This will return true if a USB connection has been established @@ -88,9 +90,9 @@ static inline bool usb_bus_detected(void) { # endif # endif # if defined(SPLIT_USB_DETECT) -_Static_assert(SPLIT_USB_TIMEOUT < SPLIT_WATCHDOG_TIMEOUT, "SPLIT_WATCHDOG_TIMEOUT should not be below SPLIT_USB_TIMEOUT."); +STATIC_ASSERT(SPLIT_USB_TIMEOUT < SPLIT_WATCHDOG_TIMEOUT, "SPLIT_WATCHDOG_TIMEOUT should not be below SPLIT_USB_TIMEOUT."); # endif -_Static_assert(SPLIT_MAX_CONNECTION_ERRORS > 0, "SPLIT_WATCHDOG_ENABLE requires SPLIT_MAX_CONNECTION_ERRORS be above 0 for a functioning disconnection check."); +STATIC_ASSERT(SPLIT_MAX_CONNECTION_ERRORS > 0, "SPLIT_WATCHDOG_ENABLE requires SPLIT_MAX_CONNECTION_ERRORS be above 0 for a functioning disconnection check."); static uint32_t split_watchdog_started = 0; static bool split_watchdog_done = false; diff --git a/quantum/split_common/split_util.h b/quantum/split_common/split_util.h index f83b05b6a6..6f4c4dc660 100644 --- a/quantum/split_common/split_util.h +++ b/quantum/split_common/split_util.h @@ -15,4 +15,4 @@ bool is_transport_connected(void); void split_watchdog_update(bool done); void split_watchdog_task(void); -bool split_watchdog_check(void);
\ No newline at end of file +bool split_watchdog_check(void); diff --git a/quantum/split_common/transaction_id_define.h b/quantum/split_common/transaction_id_define.h index 5bfbe2aec7..694737868a 100644 --- a/quantum/split_common/transaction_id_define.h +++ b/quantum/split_common/transaction_id_define.h @@ -16,6 +16,8 @@ #pragma once +#include "compiler_support.h" + enum serial_transaction_id { #ifdef USE_I2C I2C_EXECUTE_CALLBACK, @@ -122,4 +124,4 @@ enum serial_transaction_id { }; // Ensure we only use 5 bits for transaction -_Static_assert(NUM_TOTAL_TRANSACTIONS <= (1 << 5), "Max number of usable transactions exceeded"); +STATIC_ASSERT(NUM_TOTAL_TRANSACTIONS <= (1 << 5), "Max number of usable transactions exceeded"); diff --git a/quantum/split_common/transport.c b/quantum/split_common/transport.c index 83edc34859..ea687af1c2 100644 --- a/quantum/split_common/transport.c +++ b/quantum/split_common/transport.c @@ -17,6 +17,7 @@ #include <string.h> #include <debug.h> +#include "compiler_support.h" #include "transactions.h" #include "transport.h" #include "transaction_id_define.h" @@ -36,7 +37,7 @@ # include "i2c_slave.h" // Ensure the I2C buffer has enough space -_Static_assert(sizeof(split_shared_memory_t) <= I2C_SLAVE_REG_COUNT, "split_shared_memory_t too large for I2C_SLAVE_REG_COUNT"); +STATIC_ASSERT(sizeof(split_shared_memory_t) <= I2C_SLAVE_REG_COUNT, "split_shared_memory_t too large for I2C_SLAVE_REG_COUNT"); split_shared_memory_t *const split_shmem = (split_shared_memory_t *)i2c_slave_reg; diff --git a/quantum/unicode/unicode.c b/quantum/unicode/unicode.c index 78a4cad585..dff1d43fb4 100644 --- a/quantum/unicode/unicode.c +++ b/quantum/unicode/unicode.c @@ -16,7 +16,6 @@ #include "unicode.h" -#include "eeprom.h" #include "eeconfig.h" #include "action.h" #include "action_util.h" @@ -136,7 +135,7 @@ static void unicode_play_song(uint8_t mode) { #endif void unicode_input_mode_init(void) { - unicode_config.raw = eeprom_read_byte(EECONFIG_UNICODEMODE); + eeconfig_read_unicode_mode(&unicode_config); #if UNICODE_SELECTED_MODES != -1 # if UNICODE_CYCLE_PERSIST // Find input_mode in selected modes @@ -165,7 +164,7 @@ uint8_t get_unicode_input_mode(void) { } static void persist_unicode_input_mode(void) { - eeprom_update_byte(EECONFIG_UNICODEMODE, unicode_config.input_mode); + eeconfig_update_unicode_mode(&unicode_config); } void set_unicode_input_mode(uint8_t mode) { diff --git a/quantum/unicode/unicode.h b/quantum/unicode/unicode.h index 90a54c8b18..7cddc78b7a 100644 --- a/quantum/unicode/unicode.h +++ b/quantum/unicode/unicode.h @@ -17,6 +17,8 @@ #pragma once #include <stdint.h> + +#include "compiler_support.h" #include "unicode_keycodes.h" /** @@ -26,14 +28,14 @@ * \{ */ -typedef union { +typedef union unicode_config_t { uint8_t raw; struct { uint8_t input_mode : 8; }; } unicode_config_t; -_Static_assert(sizeof(unicode_config_t) == sizeof(uint8_t), "Unicode EECONFIG out of spec."); +STATIC_ASSERT(sizeof(unicode_config_t) == sizeof(uint8_t), "Unicode EECONFIG out of spec."); extern unicode_config_t unicode_config; diff --git a/quantum/via.c b/quantum/via.c index 643d7aa3c3..3682b4ab2b 100644 --- a/quantum/via.c +++ b/quantum/via.c @@ -26,12 +26,12 @@ #include "raw_hid.h" #include "dynamic_keymap.h" -#include "eeprom.h" #include "eeconfig.h" #include "matrix.h" #include "timer.h" #include "wait.h" #include "version.h" // for QMK_BUILDDATE used in EEPROM magic +#include "nvm_via.h" #if defined(AUDIO_ENABLE) # include "audio.h" @@ -65,20 +65,26 @@ bool via_eeprom_is_valid(void) { uint8_t magic1 = ((p[5] & 0x0F) << 4) | (p[6] & 0x0F); uint8_t magic2 = ((p[8] & 0x0F) << 4) | (p[9] & 0x0F); - return (eeprom_read_byte((void *)VIA_EEPROM_MAGIC_ADDR + 0) == magic0 && eeprom_read_byte((void *)VIA_EEPROM_MAGIC_ADDR + 1) == magic1 && eeprom_read_byte((void *)VIA_EEPROM_MAGIC_ADDR + 2) == magic2); + uint8_t ee_magic0; + uint8_t ee_magic1; + uint8_t ee_magic2; + nvm_via_read_magic(&ee_magic0, &ee_magic1, &ee_magic2); + + return ee_magic0 == magic0 && ee_magic1 == magic1 && ee_magic2 == magic2; } // Sets VIA/keyboard level usage of EEPROM to valid/invalid // Keyboard level code (eg. via_init_kb()) should not call this void via_eeprom_set_valid(bool valid) { - char * p = QMK_BUILDDATE; // e.g. "2019-11-05-11:29:54" - uint8_t magic0 = ((p[2] & 0x0F) << 4) | (p[3] & 0x0F); - uint8_t magic1 = ((p[5] & 0x0F) << 4) | (p[6] & 0x0F); - uint8_t magic2 = ((p[8] & 0x0F) << 4) | (p[9] & 0x0F); - - eeprom_update_byte((void *)VIA_EEPROM_MAGIC_ADDR + 0, valid ? magic0 : 0xFF); - eeprom_update_byte((void *)VIA_EEPROM_MAGIC_ADDR + 1, valid ? magic1 : 0xFF); - eeprom_update_byte((void *)VIA_EEPROM_MAGIC_ADDR + 2, valid ? magic2 : 0xFF); + if (valid) { + char * p = QMK_BUILDDATE; // e.g. "2019-11-05-11:29:54" + uint8_t magic0 = ((p[2] & 0x0F) << 4) | (p[3] & 0x0F); + uint8_t magic1 = ((p[5] & 0x0F) << 4) | (p[6] & 0x0F); + uint8_t magic2 = ((p[8] & 0x0F) << 4) | (p[9] & 0x0F); + nvm_via_update_magic(magic0, magic1, magic2); + } else { + nvm_via_update_magic(0xFF, 0xFF, 0xFF); + } } // Override this at the keyboard code level to check @@ -104,6 +110,8 @@ void via_init(void) { } void eeconfig_init_via(void) { + // Erase any NVM storage if necessary + nvm_via_erase(); // set the magic number to false, in case this gets interrupted via_eeprom_set_valid(false); // This resets the layout options @@ -119,29 +127,24 @@ void eeconfig_init_via(void) { // This is generalized so the layout options EEPROM usage can be // variable, between 1 and 4 bytes. uint32_t via_get_layout_options(void) { - uint32_t value = 0; - // Start at the most significant byte - void *source = (void *)(VIA_EEPROM_LAYOUT_OPTIONS_ADDR); - for (uint8_t i = 0; i < VIA_EEPROM_LAYOUT_OPTIONS_SIZE; i++) { - value = value << 8; - value |= eeprom_read_byte(source); - source++; - } - return value; + return nvm_via_read_layout_options(); } __attribute__((weak)) void via_set_layout_options_kb(uint32_t value) {} void via_set_layout_options(uint32_t value) { via_set_layout_options_kb(value); - // Start at the least significant byte - void *target = (void *)(VIA_EEPROM_LAYOUT_OPTIONS_ADDR + VIA_EEPROM_LAYOUT_OPTIONS_SIZE - 1); - for (uint8_t i = 0; i < VIA_EEPROM_LAYOUT_OPTIONS_SIZE; i++) { - eeprom_update_byte(target, value & 0xFF); - value = value >> 8; - target--; - } + nvm_via_update_layout_options(value); +} + +#if VIA_EEPROM_CUSTOM_CONFIG_SIZE > 0 +uint32_t via_read_custom_config(void *buf, uint32_t offset, uint32_t length) { + return nvm_via_read_custom_config(buf, offset, length); +} +uint32_t via_update_custom_config(const void *buf, uint32_t offset, uint32_t length) { + return nvm_via_update_custom_config(buf, offset, length); } +#endif #if defined(AUDIO_ENABLE) float via_device_indication_song[][2] = SONG(STARTUP_SOUND); @@ -715,7 +718,7 @@ void via_qmk_rgb_matrix_set_value(uint8_t *data) { } void via_qmk_rgb_matrix_save(void) { - eeconfig_update_rgb_matrix(); + eeconfig_force_flush_rgb_matrix(); } #endif // RGB_MATRIX_ENABLE @@ -794,7 +797,7 @@ void via_qmk_led_matrix_set_value(uint8_t *data) { } void via_qmk_led_matrix_save(void) { - eeconfig_update_led_matrix(); + eeconfig_force_flush_led_matrix(); } #endif // LED_MATRIX_ENABLE @@ -861,7 +864,7 @@ void via_qmk_audio_set_value(uint8_t *data) { } void via_qmk_audio_save(void) { - eeconfig_update_audio(audio_config.raw); + eeconfig_update_audio(&audio_config); } #endif // QMK_AUDIO_ENABLE diff --git a/quantum/via.h b/quantum/via.h index 01d4c48b37..9f0eef10f7 100644 --- a/quantum/via.h +++ b/quantum/via.h @@ -16,21 +16,8 @@ #pragma once -#include "eeconfig.h" // for EECONFIG_SIZE #include "action.h" -// Keyboard level code can change where VIA stores the magic. -// The magic is the build date YYMMDD encoded as BCD in 3 bytes, -// thus installing firmware built on a different date to the one -// already installed can be detected and the EEPROM data is reset. -// The only reason this is important is in case EEPROM usage changes -// and the EEPROM was not explicitly reset by bootmagic lite. -#ifndef VIA_EEPROM_MAGIC_ADDR -# define VIA_EEPROM_MAGIC_ADDR (EECONFIG_SIZE) -#endif - -#define VIA_EEPROM_LAYOUT_OPTIONS_ADDR (VIA_EEPROM_MAGIC_ADDR + 3) - // Changing the layout options size after release will invalidate EEPROM, // but this is something that should be set correctly on initial implementation. // 1 byte is enough for most uses (i.e. 8 binary states, or 6 binary + 1 ternary/quaternary ) @@ -46,17 +33,10 @@ # define VIA_EEPROM_LAYOUT_OPTIONS_DEFAULT 0x00000000 #endif -// The end of the EEPROM memory used by VIA -// By default, dynamic keymaps will start at this if there is no -// custom config -#define VIA_EEPROM_CUSTOM_CONFIG_ADDR (VIA_EEPROM_LAYOUT_OPTIONS_ADDR + VIA_EEPROM_LAYOUT_OPTIONS_SIZE) - #ifndef VIA_EEPROM_CUSTOM_CONFIG_SIZE # define VIA_EEPROM_CUSTOM_CONFIG_SIZE 0 #endif -#define VIA_EEPROM_CONFIG_END (VIA_EEPROM_CUSTOM_CONFIG_ADDR + VIA_EEPROM_CUSTOM_CONFIG_SIZE) - // This is changed only when the command IDs change, // so VIA Configurator can detect compatible firmware. #define VIA_PROTOCOL_VERSION 0x000C @@ -160,6 +140,11 @@ uint32_t via_get_layout_options(void); void via_set_layout_options(uint32_t value); void via_set_layout_options_kb(uint32_t value); +#if VIA_EEPROM_CUSTOM_CONFIG_SIZE > 0 +uint32_t via_read_custom_config(void *buf, uint32_t offset, uint32_t length); +uint32_t via_update_custom_config(const void *buf, uint32_t offset, uint32_t length); +#endif + // Used by VIA to tell a device to flash LEDs (or do something else) when that // device becomes the active device being configured, on startup or switching // between devices. @@ -202,4 +187,4 @@ void via_qmk_audio_command(uint8_t *data, uint8_t length); void via_qmk_audio_set_value(uint8_t *data); void via_qmk_audio_get_value(uint8_t *data); void via_qmk_audio_save(void); -#endif
\ No newline at end of file +#endif diff --git a/quantum/wear_leveling/tests/rules.mk b/quantum/wear_leveling/tests/rules.mk index 4d7a964049..f5f36e5b6e 100644 --- a/quantum/wear_leveling/tests/rules.mk +++ b/quantum/wear_leveling/tests/rules.mk @@ -63,4 +63,4 @@ wear_leveling_8byte_SRC := \ $(wear_leveling_common_SRC) \ $(QUANTUM_PATH)/wear_leveling/tests/wear_leveling_8byte.cpp wear_leveling_8byte_INC := \ - $(wear_leveling_common_INC)
\ No newline at end of file + $(wear_leveling_common_INC) diff --git a/quantum/wear_leveling/wear_leveling.c b/quantum/wear_leveling/wear_leveling.c index 429df45df5..258f074a5c 100644 --- a/quantum/wear_leveling/wear_leveling.c +++ b/quantum/wear_leveling/wear_leveling.c @@ -3,6 +3,7 @@ #include <stdbool.h> #include "fnv.h" #include "wear_leveling.h" +#include "wear_leveling_drivers.h" #include "wear_leveling_internal.h" /* diff --git a/quantum/wear_leveling/wear_leveling_drivers.h b/quantum/wear_leveling/wear_leveling_drivers.h new file mode 100644 index 0000000000..e81f833fd1 --- /dev/null +++ b/quantum/wear_leveling/wear_leveling_drivers.h @@ -0,0 +1,13 @@ +// Copyright 2025 QMK +// SPDX-License-Identifier: GPL-2.0-or-later +#pragma once + +#if defined(WEAR_LEVELING_EMBEDDED_FLASH) +# include "wear_leveling/wear_leveling_efl_config.h" +#elif defined(WEAR_LEVELING_SPI_FLASH) +# include "wear_leveling/wear_leveling_flash_spi_config.h" +#elif defined(WEAR_LEVELING_RP2040_FLASH) +# include "wear_leveling/wear_leveling_rp2040_flash_config.h" +#elif defined(WEAR_LEVELING_LEGACY) +# include "wear_leveling/wear_leveling_legacy_config.h" +#endif diff --git a/quantum/wear_leveling/wear_leveling_internal.h b/quantum/wear_leveling/wear_leveling_internal.h index e83f9b22ea..c590f42235 100644 --- a/quantum/wear_leveling/wear_leveling_internal.h +++ b/quantum/wear_leveling/wear_leveling_internal.h @@ -2,9 +2,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #pragma once -#ifdef __cplusplus -# define _Static_assert static_assert -#endif +#include "compiler_support.h" #include <stdint.h> #include <string.h> @@ -62,9 +60,9 @@ typedef uint64_t backing_store_int_t; #endif // WEAR_LEVELING_ASSERTS // Compile-time validation of configurable options -_Static_assert(WEAR_LEVELING_BACKING_SIZE >= (WEAR_LEVELING_LOGICAL_SIZE * 2), "Total backing size must be at least twice the size of the logical size"); -_Static_assert(WEAR_LEVELING_LOGICAL_SIZE % BACKING_STORE_WRITE_SIZE == 0, "Logical size must be a multiple of write size"); -_Static_assert(WEAR_LEVELING_BACKING_SIZE % WEAR_LEVELING_LOGICAL_SIZE == 0, "Backing size must be a multiple of logical size"); +STATIC_ASSERT(WEAR_LEVELING_BACKING_SIZE >= (WEAR_LEVELING_LOGICAL_SIZE * 2), "Total backing size must be at least twice the size of the logical size"); +STATIC_ASSERT(WEAR_LEVELING_LOGICAL_SIZE % BACKING_STORE_WRITE_SIZE == 0, "Logical size must be a multiple of write size"); +STATIC_ASSERT(WEAR_LEVELING_BACKING_SIZE % WEAR_LEVELING_LOGICAL_SIZE == 0, "Backing size must be a multiple of logical size"); // Backing Store API, to be implemented elsewhere by flash driver etc. bool backing_store_init(void); @@ -86,7 +84,7 @@ typedef union write_log_entry_t { uint8_t raw8[8]; } write_log_entry_t; -_Static_assert(sizeof(write_log_entry_t) == 8, "Wear leveling write log entry size was not 8"); +STATIC_ASSERT(sizeof(write_log_entry_t) == 8, "Wear leveling write log entry size was not 8"); /** * Log entry type discriminator. @@ -104,7 +102,7 @@ enum { LOG_ENTRY_TYPES }; -_Static_assert(LOG_ENTRY_TYPES <= (1 << 2), "Too many log entry types to fit into 2 bits of storage"); +STATIC_ASSERT(LOG_ENTRY_TYPES <= (1 << 2), "Too many log entry types to fit into 2 bits of storage"); #define BITMASK_FOR_BITCOUNT(n) ((1 << (n)) - 1) |