dynamic_keymap.c (5779B)
1 /* Copyright 2017 Jason Williams (Wilba) 2 * Copyright 2024-2025 Nick Brassel (@tzarc) 3 * 4 * This program is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 #include "dynamic_keymap.h" 19 #include "keymap_introspection.h" 20 #include "action.h" 21 #include "send_string.h" 22 #include "keycodes.h" 23 #include "nvm_dynamic_keymap.h" 24 25 #ifdef ENCODER_ENABLE 26 # include "encoder.h" 27 #else 28 # define NUM_ENCODERS 0 29 #endif 30 31 #ifndef DYNAMIC_KEYMAP_MACRO_DELAY 32 # define DYNAMIC_KEYMAP_MACRO_DELAY TAP_CODE_DELAY 33 #endif 34 35 uint8_t dynamic_keymap_get_layer_count(void) { 36 return DYNAMIC_KEYMAP_LAYER_COUNT; 37 } 38 39 uint16_t dynamic_keymap_get_keycode(uint8_t layer, uint8_t row, uint8_t column) { 40 return nvm_dynamic_keymap_read_keycode(layer, row, column); 41 } 42 43 void dynamic_keymap_set_keycode(uint8_t layer, uint8_t row, uint8_t column, uint16_t keycode) { 44 nvm_dynamic_keymap_update_keycode(layer, row, column, keycode); 45 } 46 47 #ifdef ENCODER_MAP_ENABLE 48 uint16_t dynamic_keymap_get_encoder(uint8_t layer, uint8_t encoder_id, bool clockwise) { 49 return nvm_dynamic_keymap_read_encoder(layer, encoder_id, clockwise); 50 } 51 52 void dynamic_keymap_set_encoder(uint8_t layer, uint8_t encoder_id, bool clockwise, uint16_t keycode) { 53 nvm_dynamic_keymap_update_encoder(layer, encoder_id, clockwise, keycode); 54 } 55 #endif // ENCODER_MAP_ENABLE 56 57 void dynamic_keymap_reset(void) { 58 // Erase the keymaps, if necessary. 59 nvm_dynamic_keymap_erase(); 60 61 // Reset the keymaps in EEPROM to what is in flash. 62 for (int layer = 0; layer < DYNAMIC_KEYMAP_LAYER_COUNT; layer++) { 63 for (int row = 0; row < MATRIX_ROWS; row++) { 64 for (int column = 0; column < MATRIX_COLS; column++) { 65 dynamic_keymap_set_keycode(layer, row, column, keycode_at_keymap_location_raw(layer, row, column)); 66 } 67 } 68 #ifdef ENCODER_MAP_ENABLE 69 for (int encoder = 0; encoder < NUM_ENCODERS; encoder++) { 70 dynamic_keymap_set_encoder(layer, encoder, true, keycode_at_encodermap_location_raw(layer, encoder, true)); 71 dynamic_keymap_set_encoder(layer, encoder, false, keycode_at_encodermap_location_raw(layer, encoder, false)); 72 } 73 #endif // ENCODER_MAP_ENABLE 74 } 75 } 76 77 void dynamic_keymap_get_buffer(uint16_t offset, uint16_t size, uint8_t *data) { 78 nvm_dynamic_keymap_read_buffer(offset, size, data); 79 } 80 81 void dynamic_keymap_set_buffer(uint16_t offset, uint16_t size, uint8_t *data) { 82 nvm_dynamic_keymap_update_buffer(offset, size, data); 83 } 84 85 uint16_t keycode_at_keymap_location(uint8_t layer_num, uint8_t row, uint8_t column) { 86 if (layer_num < DYNAMIC_KEYMAP_LAYER_COUNT && row < MATRIX_ROWS && column < MATRIX_COLS) { 87 return dynamic_keymap_get_keycode(layer_num, row, column); 88 } 89 return KC_NO; 90 } 91 92 #ifdef ENCODER_MAP_ENABLE 93 uint16_t keycode_at_encodermap_location(uint8_t layer_num, uint8_t encoder_idx, bool clockwise) { 94 if (layer_num < DYNAMIC_KEYMAP_LAYER_COUNT && encoder_idx < NUM_ENCODERS) { 95 return dynamic_keymap_get_encoder(layer_num, encoder_idx, clockwise); 96 } 97 return KC_NO; 98 } 99 #endif // ENCODER_MAP_ENABLE 100 101 uint8_t dynamic_keymap_macro_get_count(void) { 102 return DYNAMIC_KEYMAP_MACRO_COUNT; 103 } 104 105 uint16_t dynamic_keymap_macro_get_buffer_size(void) { 106 return (uint16_t)nvm_dynamic_keymap_macro_size(); 107 } 108 109 void dynamic_keymap_macro_get_buffer(uint16_t offset, uint16_t size, uint8_t *data) { 110 nvm_dynamic_keymap_macro_read_buffer(offset, size, data); 111 } 112 113 void dynamic_keymap_macro_set_buffer(uint16_t offset, uint16_t size, uint8_t *data) { 114 nvm_dynamic_keymap_macro_update_buffer(offset, size, data); 115 } 116 117 static uint8_t dynamic_keymap_read_byte(uint32_t offset) { 118 uint8_t d; 119 nvm_dynamic_keymap_macro_read_buffer(offset, 1, &d); 120 return d; 121 } 122 123 typedef struct send_string_nvm_state_t { 124 uint32_t offset; 125 } send_string_nvm_state_t; 126 127 char send_string_get_next_nvm(void *arg) { 128 send_string_nvm_state_t *state = (send_string_nvm_state_t *)arg; 129 char ret = dynamic_keymap_read_byte(state->offset); 130 state->offset++; 131 return ret; 132 } 133 134 void dynamic_keymap_macro_reset(void) { 135 // Erase the macros, if necessary. 136 nvm_dynamic_keymap_macro_erase(); 137 nvm_dynamic_keymap_macro_reset(); 138 } 139 140 void dynamic_keymap_macro_send(uint8_t id) { 141 if (id >= DYNAMIC_KEYMAP_MACRO_COUNT) { 142 return; 143 } 144 145 // Check the last byte of the buffer. 146 // If it's not zero, then we are in the middle 147 // of buffer writing, possibly an aborted buffer 148 // write. So do nothing. 149 if (dynamic_keymap_read_byte(nvm_dynamic_keymap_macro_size() - 1) != 0) { 150 return; 151 } 152 153 // Skip N null characters 154 // p will then point to the Nth macro 155 uint32_t offset = 0; 156 uint32_t end = nvm_dynamic_keymap_macro_size(); 157 while (id > 0) { 158 // If we are past the end of the buffer, then there is 159 // no Nth macro in the buffer. 160 if (offset == end) { 161 return; 162 } 163 if (dynamic_keymap_read_byte(offset) == 0) { 164 --id; 165 } 166 ++offset; 167 } 168 169 send_string_nvm_state_t state = {.offset = offset}; 170 send_string_with_delay_impl(send_string_get_next_nvm, &state, DYNAMIC_KEYMAP_MACRO_DELAY); 171 }