nvm_eeconfig.c (10244B)
1 // Copyright 2024 Nick Brassel (@tzarc) 2 // SPDX-License-Identifier: GPL-2.0-or-later 3 #include <string.h> 4 #include "nvm_eeconfig.h" 5 #include "nvm_eeprom_eeconfig_internal.h" 6 #include "util.h" 7 #include "eeconfig.h" 8 #include "debug.h" 9 #include "eeprom.h" 10 #include "keycode_config.h" 11 12 #ifdef EEPROM_DRIVER 13 # include "eeprom_driver.h" 14 #endif 15 16 #ifdef AUDIO_ENABLE 17 # include "audio.h" 18 #endif 19 20 #ifdef BACKLIGHT_ENABLE 21 # include "backlight.h" 22 #endif 23 24 #ifdef RGBLIGHT_ENABLE 25 # include "rgblight.h" 26 #endif 27 28 #ifdef RGB_MATRIX_ENABLE 29 # include "rgb_matrix_types.h" 30 #endif 31 32 #ifdef LED_MATRIX_ENABLE 33 # include "led_matrix_types.h" 34 #endif 35 36 #ifdef UNICODE_COMMON_ENABLE 37 # include "unicode.h" 38 #endif 39 40 #ifdef HAPTIC_ENABLE 41 # include "haptic.h" 42 #endif 43 44 #ifdef CONNECTION_ENABLE 45 # include "connection.h" 46 #endif 47 48 void nvm_eeconfig_erase(void) { 49 #ifdef EEPROM_DRIVER 50 eeprom_driver_format(false); 51 #endif // EEPROM_DRIVER 52 } 53 54 bool nvm_eeconfig_is_enabled(void) { 55 return eeprom_read_word(EECONFIG_MAGIC) == EECONFIG_MAGIC_NUMBER; 56 } 57 58 bool nvm_eeconfig_is_disabled(void) { 59 return eeprom_read_word(EECONFIG_MAGIC) == EECONFIG_MAGIC_NUMBER_OFF; 60 } 61 62 void nvm_eeconfig_enable(void) { 63 eeprom_update_word(EECONFIG_MAGIC, EECONFIG_MAGIC_NUMBER); 64 } 65 66 void nvm_eeconfig_disable(void) { 67 #if defined(EEPROM_DRIVER) 68 eeprom_driver_format(false); 69 #endif 70 eeprom_update_word(EECONFIG_MAGIC, EECONFIG_MAGIC_NUMBER_OFF); 71 } 72 73 void nvm_eeconfig_read_debug(debug_config_t *debug_config) { 74 debug_config->raw = eeprom_read_byte(EECONFIG_DEBUG); 75 } 76 void nvm_eeconfig_update_debug(const debug_config_t *debug_config) { 77 eeprom_update_byte(EECONFIG_DEBUG, debug_config->raw); 78 } 79 80 layer_state_t nvm_eeconfig_read_default_layer(void) { 81 uint8_t val = eeprom_read_byte(EECONFIG_DEFAULT_LAYER); 82 #ifdef DEFAULT_LAYER_STATE_IS_VALUE_NOT_BITMASK 83 // stored as a layer number, so convert back to bitmask 84 return (layer_state_t)1 << val; 85 #else 86 // stored as 8-bit-wide bitmask, so read the value directly - handling padding to 16/32 bit layer_state_t 87 return (layer_state_t)val; 88 #endif 89 } 90 void nvm_eeconfig_update_default_layer(layer_state_t state) { 91 #ifdef DEFAULT_LAYER_STATE_IS_VALUE_NOT_BITMASK 92 // stored as a layer number, so only store the highest layer 93 uint8_t val = get_highest_layer(state); 94 #else 95 // stored as 8-bit-wide bitmask, so write the value directly - handling truncation from 16/32 bit layer_state_t 96 uint8_t val = (uint8_t)state; 97 #endif 98 eeprom_update_byte(EECONFIG_DEFAULT_LAYER, val); 99 } 100 101 void nvm_eeconfig_read_keymap(keymap_config_t *keymap_config) { 102 keymap_config->raw = eeprom_read_word(EECONFIG_KEYMAP); 103 } 104 void nvm_eeconfig_update_keymap(const keymap_config_t *keymap_config) { 105 eeprom_update_word(EECONFIG_KEYMAP, keymap_config->raw); 106 } 107 108 #ifdef AUDIO_ENABLE 109 void nvm_eeconfig_read_audio(audio_config_t *audio_config) { 110 audio_config->raw = eeprom_read_byte(EECONFIG_AUDIO); 111 } 112 void nvm_eeconfig_update_audio(const audio_config_t *audio_config) { 113 eeprom_update_byte(EECONFIG_AUDIO, audio_config->raw); 114 } 115 #endif // AUDIO_ENABLE 116 117 #ifdef UNICODE_COMMON_ENABLE 118 void nvm_eeconfig_read_unicode_mode(unicode_config_t *unicode_config) { 119 unicode_config->raw = eeprom_read_byte(EECONFIG_UNICODEMODE); 120 } 121 void nvm_eeconfig_update_unicode_mode(const unicode_config_t *unicode_config) { 122 eeprom_update_byte(EECONFIG_UNICODEMODE, unicode_config->raw); 123 } 124 #endif // UNICODE_COMMON_ENABLE 125 126 #ifdef BACKLIGHT_ENABLE 127 void nvm_eeconfig_read_backlight(backlight_config_t *backlight_config) { 128 backlight_config->raw = eeprom_read_byte(EECONFIG_BACKLIGHT); 129 } 130 void nvm_eeconfig_update_backlight(const backlight_config_t *backlight_config) { 131 eeprom_update_byte(EECONFIG_BACKLIGHT, backlight_config->raw); 132 } 133 #endif // BACKLIGHT_ENABLE 134 135 #ifdef STENO_ENABLE 136 uint8_t nvm_eeconfig_read_steno_mode(void) { 137 return eeprom_read_byte(EECONFIG_STENOMODE); 138 } 139 void nvm_eeconfig_update_steno_mode(uint8_t val) { 140 eeprom_update_byte(EECONFIG_STENOMODE, val); 141 } 142 #endif // STENO_ENABLE 143 144 #ifdef RGBLIGHT_ENABLE 145 #endif // RGBLIGHT_ENABLE 146 147 #ifdef RGB_MATRIX_ENABLE 148 void nvm_eeconfig_read_rgb_matrix(rgb_config_t *rgb_matrix_config) { 149 eeprom_read_block(rgb_matrix_config, EECONFIG_RGB_MATRIX, sizeof(rgb_config_t)); 150 } 151 void nvm_eeconfig_update_rgb_matrix(const rgb_config_t *rgb_matrix_config) { 152 eeprom_update_block(rgb_matrix_config, EECONFIG_RGB_MATRIX, sizeof(rgb_config_t)); 153 } 154 #endif // RGB_MATRIX_ENABLE 155 156 #ifdef LED_MATRIX_ENABLE 157 void nvm_eeconfig_read_led_matrix(led_eeconfig_t *led_matrix_config) { 158 eeprom_read_block(led_matrix_config, EECONFIG_LED_MATRIX, sizeof(led_eeconfig_t)); 159 } 160 void nvm_eeconfig_update_led_matrix(const led_eeconfig_t *led_matrix_config) { 161 eeprom_update_block(led_matrix_config, EECONFIG_LED_MATRIX, sizeof(led_eeconfig_t)); 162 } 163 #endif // LED_MATRIX_ENABLE 164 165 #ifdef RGBLIGHT_ENABLE 166 void nvm_eeconfig_read_rgblight(rgblight_config_t *rgblight_config) { 167 rgblight_config->raw = eeprom_read_dword(EECONFIG_RGBLIGHT); 168 rgblight_config->raw |= ((uint64_t)eeprom_read_byte(EECONFIG_RGBLIGHT_EXTENDED) << 32); 169 } 170 void nvm_eeconfig_update_rgblight(const rgblight_config_t *rgblight_config) { 171 eeprom_update_dword(EECONFIG_RGBLIGHT, rgblight_config->raw & 0xFFFFFFFF); 172 eeprom_update_byte(EECONFIG_RGBLIGHT_EXTENDED, (rgblight_config->raw >> 32) & 0xFF); 173 } 174 #endif // RGBLIGHT_ENABLE 175 176 #if (EECONFIG_KB_DATA_SIZE) == 0 177 uint32_t nvm_eeconfig_read_kb(void) { 178 return eeprom_read_dword(EECONFIG_KEYBOARD); 179 } 180 void nvm_eeconfig_update_kb(uint32_t val) { 181 eeprom_update_dword(EECONFIG_KEYBOARD, val); 182 } 183 #endif // (EECONFIG_KB_DATA_SIZE) == 0 184 185 #if (EECONFIG_USER_DATA_SIZE) == 0 186 uint32_t nvm_eeconfig_read_user(void) { 187 return eeprom_read_dword(EECONFIG_USER); 188 } 189 void nvm_eeconfig_update_user(uint32_t val) { 190 eeprom_update_dword(EECONFIG_USER, val); 191 } 192 #endif // (EECONFIG_USER_DATA_SIZE) == 0 193 194 #ifdef HAPTIC_ENABLE 195 void nvm_eeconfig_read_haptic(haptic_config_t *haptic_config) { 196 haptic_config->raw = eeprom_read_dword(EECONFIG_HAPTIC); 197 } 198 void nvm_eeconfig_update_haptic(const haptic_config_t *haptic_config) { 199 eeprom_update_dword(EECONFIG_HAPTIC, haptic_config->raw); 200 } 201 #endif // HAPTIC_ENABLE 202 203 #ifdef CONNECTION_ENABLE 204 void nvm_eeconfig_read_connection(connection_config_t *config) { 205 config->raw = eeprom_read_byte(EECONFIG_CONNECTION); 206 } 207 void nvm_eeconfig_update_connection(const connection_config_t *config) { 208 eeprom_update_byte(EECONFIG_CONNECTION, config->raw); 209 } 210 #endif // CONNECTION_ENABLE 211 212 bool nvm_eeconfig_read_handedness(void) { 213 return !!eeprom_read_byte(EECONFIG_HANDEDNESS); 214 } 215 void nvm_eeconfig_update_handedness(bool val) { 216 eeprom_update_byte(EECONFIG_HANDEDNESS, !!val); 217 } 218 219 #if (EECONFIG_KB_DATA_SIZE) > 0 220 221 bool nvm_eeconfig_is_kb_datablock_valid(void) { 222 return eeprom_read_dword(EECONFIG_KEYBOARD) == (EECONFIG_KB_DATA_VERSION); 223 } 224 225 uint32_t nvm_eeconfig_read_kb_datablock(void *data, uint32_t offset, uint32_t length) { 226 if (eeconfig_is_kb_datablock_valid()) { 227 void *ee_start = (void *)(uintptr_t)(EECONFIG_KB_DATABLOCK + offset); 228 void *ee_end = (void *)(uintptr_t)(EECONFIG_KB_DATABLOCK + MIN(EECONFIG_KB_DATA_SIZE, offset + length)); 229 eeprom_read_block(data, ee_start, ee_end - ee_start); 230 return ee_end - ee_start; 231 } else { 232 memset(data, 0, length); 233 return length; 234 } 235 } 236 237 uint32_t nvm_eeconfig_update_kb_datablock(const void *data, uint32_t offset, uint32_t length) { 238 eeprom_update_dword(EECONFIG_KEYBOARD, (EECONFIG_KB_DATA_VERSION)); 239 240 void *ee_start = (void *)(uintptr_t)(EECONFIG_KB_DATABLOCK + offset); 241 void *ee_end = (void *)(uintptr_t)(EECONFIG_KB_DATABLOCK + MIN(EECONFIG_KB_DATA_SIZE, offset + length)); 242 eeprom_update_block(data, ee_start, ee_end - ee_start); 243 return ee_end - ee_start; 244 } 245 246 void nvm_eeconfig_init_kb_datablock(void) { 247 eeprom_update_dword(EECONFIG_KEYBOARD, (EECONFIG_KB_DATA_VERSION)); 248 249 void *start = (void *)(uintptr_t)(EECONFIG_KB_DATABLOCK); 250 void *end = (void *)(uintptr_t)(EECONFIG_KB_DATABLOCK + EECONFIG_KB_DATA_SIZE); 251 long remaining = end - start; 252 uint8_t dummy[16] = {0}; 253 for (int i = 0; i < EECONFIG_KB_DATA_SIZE; i += sizeof(dummy)) { 254 int this_loop = remaining < sizeof(dummy) ? remaining : sizeof(dummy); 255 eeprom_update_block(dummy, start, this_loop); 256 start += this_loop; 257 remaining -= this_loop; 258 } 259 } 260 261 #endif // (EECONFIG_KB_DATA_SIZE) > 0 262 263 #if (EECONFIG_USER_DATA_SIZE) > 0 264 265 bool nvm_eeconfig_is_user_datablock_valid(void) { 266 return eeprom_read_dword(EECONFIG_USER) == (EECONFIG_USER_DATA_VERSION); 267 } 268 269 uint32_t nvm_eeconfig_read_user_datablock(void *data, uint32_t offset, uint32_t length) { 270 if (eeconfig_is_user_datablock_valid()) { 271 void *ee_start = (void *)(uintptr_t)(EECONFIG_USER_DATABLOCK + offset); 272 void *ee_end = (void *)(uintptr_t)(EECONFIG_USER_DATABLOCK + MIN(EECONFIG_USER_DATA_SIZE, offset + length)); 273 eeprom_read_block(data, ee_start, ee_end - ee_start); 274 return ee_end - ee_start; 275 } else { 276 memset(data, 0, length); 277 return length; 278 } 279 } 280 281 uint32_t nvm_eeconfig_update_user_datablock(const void *data, uint32_t offset, uint32_t length) { 282 eeprom_update_dword(EECONFIG_USER, (EECONFIG_USER_DATA_VERSION)); 283 284 void *ee_start = (void *)(uintptr_t)(EECONFIG_USER_DATABLOCK + offset); 285 void *ee_end = (void *)(uintptr_t)(EECONFIG_USER_DATABLOCK + MIN(EECONFIG_USER_DATA_SIZE, offset + length)); 286 eeprom_update_block(data, ee_start, ee_end - ee_start); 287 return ee_end - ee_start; 288 } 289 290 void nvm_eeconfig_init_user_datablock(void) { 291 eeprom_update_dword(EECONFIG_USER, (EECONFIG_USER_DATA_VERSION)); 292 293 void *start = (void *)(uintptr_t)(EECONFIG_USER_DATABLOCK); 294 void *end = (void *)(uintptr_t)(EECONFIG_USER_DATABLOCK + EECONFIG_USER_DATA_SIZE); 295 long remaining = end - start; 296 uint8_t dummy[16] = {0}; 297 for (int i = 0; i < EECONFIG_USER_DATA_SIZE; i += sizeof(dummy)) { 298 int this_loop = remaining < sizeof(dummy) ? remaining : sizeof(dummy); 299 eeprom_update_block(dummy, start, this_loop); 300 start += this_loop; 301 remaining -= this_loop; 302 } 303 } 304 305 #endif // (EECONFIG_USER_DATA_SIZE) > 0