qmk_firmware

QMK firmware for my keyboards (Corne, Sweep Ferris) and trackball (Ploopy Adept)
Log | Files | Refs | Submodules | LICENSE

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