logo

qmk_firmware

custom branch of QMK firmware git clone https://anongit.hacktivis.me/git/qmk_firmware.git

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. #include "dynamic_keymap.h"
  18. #include "keymap_introspection.h"
  19. #include "action.h"
  20. #include "send_string.h"
  21. #include "keycodes.h"
  22. #include "nvm_dynamic_keymap.h"
  23. #ifdef ENCODER_ENABLE
  24. # include "encoder.h"
  25. #else
  26. # define NUM_ENCODERS 0
  27. #endif
  28. #ifndef DYNAMIC_KEYMAP_MACRO_DELAY
  29. # define DYNAMIC_KEYMAP_MACRO_DELAY TAP_CODE_DELAY
  30. #endif
  31. uint8_t dynamic_keymap_get_layer_count(void) {
  32. return DYNAMIC_KEYMAP_LAYER_COUNT;
  33. }
  34. uint16_t dynamic_keymap_get_keycode(uint8_t layer, uint8_t row, uint8_t column) {
  35. return nvm_dynamic_keymap_read_keycode(layer, row, column);
  36. }
  37. void dynamic_keymap_set_keycode(uint8_t layer, uint8_t row, uint8_t column, uint16_t keycode) {
  38. nvm_dynamic_keymap_update_keycode(layer, row, column, keycode);
  39. }
  40. #ifdef ENCODER_MAP_ENABLE
  41. uint16_t dynamic_keymap_get_encoder(uint8_t layer, uint8_t encoder_id, bool clockwise) {
  42. return nvm_dynamic_keymap_read_encoder(layer, encoder_id, clockwise);
  43. }
  44. void dynamic_keymap_set_encoder(uint8_t layer, uint8_t encoder_id, bool clockwise, uint16_t keycode) {
  45. nvm_dynamic_keymap_update_encoder(layer, encoder_id, clockwise, keycode);
  46. }
  47. #endif // ENCODER_MAP_ENABLE
  48. void dynamic_keymap_reset(void) {
  49. // Erase the keymaps, if necessary.
  50. nvm_dynamic_keymap_erase();
  51. // Reset the keymaps in EEPROM to what is in flash.
  52. for (int layer = 0; layer < DYNAMIC_KEYMAP_LAYER_COUNT; layer++) {
  53. for (int row = 0; row < MATRIX_ROWS; row++) {
  54. for (int column = 0; column < MATRIX_COLS; column++) {
  55. dynamic_keymap_set_keycode(layer, row, column, keycode_at_keymap_location_raw(layer, row, column));
  56. }
  57. }
  58. #ifdef ENCODER_MAP_ENABLE
  59. for (int encoder = 0; encoder < NUM_ENCODERS; encoder++) {
  60. dynamic_keymap_set_encoder(layer, encoder, true, keycode_at_encodermap_location_raw(layer, encoder, true));
  61. dynamic_keymap_set_encoder(layer, encoder, false, keycode_at_encodermap_location_raw(layer, encoder, false));
  62. }
  63. #endif // ENCODER_MAP_ENABLE
  64. }
  65. }
  66. void dynamic_keymap_get_buffer(uint16_t offset, uint16_t size, uint8_t *data) {
  67. nvm_dynamic_keymap_read_buffer(offset, size, data);
  68. }
  69. void dynamic_keymap_set_buffer(uint16_t offset, uint16_t size, uint8_t *data) {
  70. nvm_dynamic_keymap_update_buffer(offset, size, data);
  71. }
  72. uint16_t keycode_at_keymap_location(uint8_t layer_num, uint8_t row, uint8_t column) {
  73. if (layer_num < DYNAMIC_KEYMAP_LAYER_COUNT && row < MATRIX_ROWS && column < MATRIX_COLS) {
  74. return dynamic_keymap_get_keycode(layer_num, row, column);
  75. }
  76. return KC_NO;
  77. }
  78. #ifdef ENCODER_MAP_ENABLE
  79. uint16_t keycode_at_encodermap_location(uint8_t layer_num, uint8_t encoder_idx, bool clockwise) {
  80. if (layer_num < DYNAMIC_KEYMAP_LAYER_COUNT && encoder_idx < NUM_ENCODERS) {
  81. return dynamic_keymap_get_encoder(layer_num, encoder_idx, clockwise);
  82. }
  83. return KC_NO;
  84. }
  85. #endif // ENCODER_MAP_ENABLE
  86. uint8_t dynamic_keymap_macro_get_count(void) {
  87. return DYNAMIC_KEYMAP_MACRO_COUNT;
  88. }
  89. uint16_t dynamic_keymap_macro_get_buffer_size(void) {
  90. return (uint16_t)nvm_dynamic_keymap_macro_size();
  91. }
  92. void dynamic_keymap_macro_get_buffer(uint16_t offset, uint16_t size, uint8_t *data) {
  93. nvm_dynamic_keymap_macro_read_buffer(offset, size, data);
  94. }
  95. void dynamic_keymap_macro_set_buffer(uint16_t offset, uint16_t size, uint8_t *data) {
  96. nvm_dynamic_keymap_macro_update_buffer(offset, size, data);
  97. }
  98. static uint8_t dynamic_keymap_read_byte(uint32_t offset) {
  99. uint8_t d;
  100. nvm_dynamic_keymap_macro_read_buffer(offset, 1, &d);
  101. return d;
  102. }
  103. typedef struct send_string_nvm_state_t {
  104. uint32_t offset;
  105. } send_string_nvm_state_t;
  106. char send_string_get_next_nvm(void *arg) {
  107. send_string_nvm_state_t *state = (send_string_nvm_state_t *)arg;
  108. char ret = dynamic_keymap_read_byte(state->offset);
  109. state->offset++;
  110. return ret;
  111. }
  112. void dynamic_keymap_macro_reset(void) {
  113. // Erase the macros, if necessary.
  114. nvm_dynamic_keymap_macro_erase();
  115. nvm_dynamic_keymap_macro_reset();
  116. }
  117. void dynamic_keymap_macro_send(uint8_t id) {
  118. if (id >= DYNAMIC_KEYMAP_MACRO_COUNT) {
  119. return;
  120. }
  121. // Check the last byte of the buffer.
  122. // If it's not zero, then we are in the middle
  123. // of buffer writing, possibly an aborted buffer
  124. // write. So do nothing.
  125. if (dynamic_keymap_read_byte(nvm_dynamic_keymap_macro_size() - 1) != 0) {
  126. return;
  127. }
  128. // Skip N null characters
  129. // p will then point to the Nth macro
  130. uint32_t offset = 0;
  131. uint32_t end = nvm_dynamic_keymap_macro_size();
  132. while (id > 0) {
  133. // If we are past the end of the buffer, then there is
  134. // no Nth macro in the buffer.
  135. if (offset == end) {
  136. return;
  137. }
  138. if (dynamic_keymap_read_byte(offset) == 0) {
  139. --id;
  140. }
  141. ++offset;
  142. }
  143. send_string_nvm_state_t state = {.offset = offset};
  144. send_string_with_delay_impl(send_string_get_next_nvm, &state, DYNAMIC_KEYMAP_MACRO_DELAY);
  145. }