aboutsummaryrefslogtreecommitdiff
path: root/quantum/dynamic_keymap.c
diff options
context:
space:
mode:
Diffstat (limited to 'quantum/dynamic_keymap.c')
-rw-r--r--quantum/dynamic_keymap.c205
1 files changed, 38 insertions, 167 deletions
diff --git a/quantum/dynamic_keymap.c b/quantum/dynamic_keymap.c
index beb7f9d18f..59027fb694 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 = 0};
+ send_string_with_delay_impl(send_string_get_next_nvm, &state, DYNAMIC_KEYMAP_MACRO_DELAY);
}