diff --git a/builddefs/common_features.mk b/builddefs/common_features.mk index fae0fe9b48e..22634f04eef 100644 --- a/builddefs/common_features.mk +++ b/builddefs/common_features.mk @@ -629,7 +629,8 @@ ifeq ($(strip $(VIA_ENABLE)), yes) TRI_LAYER_ENABLE := yes QUANTUM_SRC += \ - nvm_via.c + nvm_via.c \ + nvm_dynamic_keymap.c endif VALID_CUSTOM_MATRIX_TYPES:= yes lite no diff --git a/keyboards/cipulot/common/eeprom_tools.h b/keyboards/cipulot/common/eeprom_tools.h index b3c90d87592..b38ec69a782 100644 --- a/keyboards/cipulot/common/eeprom_tools.h +++ b/keyboards/cipulot/common/eeprom_tools.h @@ -18,9 +18,9 @@ #include "eeprom.h" #if (EECONFIG_KB_DATA_SIZE) > 0 -# define EEPROM_KB_PARTIAL_UPDATE(__struct, __field) eeprom_update_block(&(__struct.__field), (void *)((void *)(EECONFIG_KB_DATABLOCK) + offsetof(typeof(__struct), __field)), sizeof(__struct.__field)) +# define EEPROM_KB_PARTIAL_UPDATE(__struct, __field) eeconfig_update_kb_datablock(&(__struct.__field), (void *)((void *)(EECONFIG_KB_DATABLOCK) + offsetof(typeof(__struct), __field)), sizeof(__struct.__field)) #endif #if (EECONFIG_USER_DATA_SIZE) > 0 -# define EEPROM_USER_PARTIAL_UPDATE(__struct, __field) eeprom_update_block(&(__struct.__field), (void *)((void *)(EECONFIG_USER_DATABLOCK) + offsetof(typeof(__struct), __field)), sizeof(__struct.__field)) +# define EEPROM_USER_PARTIAL_UPDATE(__struct, __field) eeconfig_update_user_datablock(&(__struct.__field), (void *)((void *)(EECONFIG_USER_DATABLOCK) + offsetof(typeof(__struct), __field)), sizeof(__struct.__field)) #endif diff --git a/quantum/dynamic_keymap.c b/quantum/dynamic_keymap.c index 3c22bbd4457..aabd5e7a6e9 100644 --- a/quantum/dynamic_keymap.c +++ b/quantum/dynamic_keymap.c @@ -21,14 +21,7 @@ #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 +29,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,48 +37,21 @@ 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 @@ -168,31 +73,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,42 +101,25 @@ 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); } 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; - } + nvm_dynamic_keymap_macro_reset(); +} + +static uint8_t dynamic_keymap_read_byte(uint32_t offset) { + uint8_t d; + nvm_dynamic_keymap_macro_read_buffer(offset, 1, &d); + return d; } void dynamic_keymap_macro_send(uint8_t id) { @@ -263,25 +131,24 @@ void dynamic_keymap_macro_send(uint8_t id) { // If it's not zero, then we are in the middle // of buffer writing, possibly an aborted buffer // write. So do nothing. - void *p = (void *)(DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR + DYNAMIC_KEYMAP_MACRO_EEPROM_SIZE - 1); - if (eeprom_read_byte(p) != 0) { + if(dynamic_keymap_read_byte(nvm_dynamic_keymap_macro_size()-1) != 0) { return; } // Skip N null characters // p will then point to the Nth macro - p = (void *)(DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR); - void *end = (void *)(DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR + DYNAMIC_KEYMAP_MACRO_EEPROM_SIZE); + 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 the macro string by making a temporary string. @@ -289,7 +156,7 @@ void dynamic_keymap_macro_send(uint8_t id) { // We already checked there was a null at the end of // the buffer, so this cannot go past the end while (1) { - data[0] = eeprom_read_byte(p++); + data[0] = dynamic_keymap_read_byte(offset++); data[1] = 0; // Stop at the null terminator of this macro string if (data[0] == 0) { @@ -297,14 +164,14 @@ void dynamic_keymap_macro_send(uint8_t id) { } if (data[0] == SS_QMK_PREFIX) { // Get the code - data[1] = eeprom_read_byte(p++); + data[1] = dynamic_keymap_read_byte(offset++); // Unexpected null, abort. if (data[1] == 0) { return; } if (data[1] == SS_TAP_CODE || data[1] == SS_DOWN_CODE || data[1] == SS_UP_CODE) { // Get the keycode - data[2] = eeprom_read_byte(p++); + data[2] = dynamic_keymap_read_byte(offset++); // Unexpected null, abort. if (data[2] == 0) { return; @@ -316,7 +183,7 @@ void dynamic_keymap_macro_send(uint8_t id) { // At most this is 4 digits plus '|' uint8_t i = 2; while (1) { - data[i] = eeprom_read_byte(p++); + data[i] = dynamic_keymap_read_byte(offset++); // Unexpected null, abort if (data[i] == 0) { return; diff --git a/quantum/dynamic_keymap.h b/quantum/dynamic_keymap.h index 806342efa3c..f1d8077b127 100644 --- a/quantum/dynamic_keymap.h +++ b/quantum/dynamic_keymap.h @@ -18,8 +18,15 @@ #include #include +#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/nvm/eeprom/nvm_dynamic_keymap.c b/quantum/nvm/eeprom/nvm_dynamic_keymap.c new file mode 100644 index 00000000000..b5f450e4899 --- /dev/null +++ b/quantum/nvm/eeprom/nvm_dynamic_keymap.c @@ -0,0 +1,183 @@ +// Copyright 2024 Nick Brassel (@tzarc) +// SPDX-License-Identifier: GPL-2.0-or-later + +#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 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 + +#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."); + +#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 + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +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) { + 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++; + } +} + +void nvm_dynamic_keymap_update_buffer(uint32_t offset, uint32_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++; + } +} + +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 *)(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 *)(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 *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; + } +} + diff --git a/quantum/nvm/eeprom/nvm_eeconfig.c b/quantum/nvm/eeprom/nvm_eeconfig.c index 660e61c40ab..a40b3f93a25 100644 --- a/quantum/nvm/eeprom/nvm_eeconfig.c +++ b/quantum/nvm/eeprom/nvm_eeconfig.c @@ -2,7 +2,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include #include "nvm_eeconfig.h" -#include "nvm_eeconfig_eeprom.h" +#include "nvm_eeprom_eeconfig_internal.h" #include "util.h" #include "eeconfig.h" #include "eeprom.h" diff --git a/quantum/nvm/eeprom/nvm_eeconfig_eeprom.h b/quantum/nvm/eeprom/nvm_eeprom_eeconfig_internal.h similarity index 100% rename from quantum/nvm/eeprom/nvm_eeconfig_eeprom.h rename to quantum/nvm/eeprom/nvm_eeprom_eeconfig_internal.h 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 00000000000..bf0d38e2ac3 --- /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 index be0a5d9cc88..26fb0a5c73d 100644 --- a/quantum/nvm/eeprom/nvm_via.c +++ b/quantum/nvm/eeprom/nvm_via.c @@ -4,29 +4,8 @@ #include "eeprom.h" #include "via.h" #include "nvm_via.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) - -// 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) - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#include "nvm_eeprom_eeconfig_internal.h" +#include "nvm_eeprom_via_internal.h" void nvm_via_read_magic(uint8_t *magic0, uint8_t *magic1, uint8_t *magic2) { if (magic0) { diff --git a/quantum/nvm/nvm_dynamic_keymap.h b/quantum/nvm/nvm_dynamic_keymap.h new file mode 100644 index 00000000000..62c22781315 --- /dev/null +++ b/quantum/nvm/nvm_dynamic_keymap.h @@ -0,0 +1,24 @@ +// Copyright 2024 Nick Brassel (@tzarc) +// SPDX-License-Identifier: GPL-2.0-or-later +#pragma once + +#include +#include + +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); \ No newline at end of file diff --git a/quantum/via.h b/quantum/via.h index c6c3e5cf2b0..9f0eef10f75 100644 --- a/quantum/via.h +++ b/quantum/via.h @@ -16,7 +16,6 @@ #pragma once -#include "nvm_eeconfig_eeprom.h" // for EECONFIG_SIZE #include "action.h" // Changing the layout options size after release will invalidate EEPROM,