logo

qmk_firmware

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

satisfaction_core.c (9904B)


  1. // Copyright 2023 Andrew Kannan
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include "satisfaction_core.h"
  4. #include "print.h"
  5. #include "debug.h"
  6. #include "matrix.h"
  7. #include "quantum.h"
  8. #include "encoder.h"
  9. #include <ch.h>
  10. #include <hal.h>
  11. #include "timer.h"
  12. #include "raw_hid.h"
  13. #include "dynamic_keymap.h"
  14. #include "eeprom.h"
  15. #include "version.h" // for QMK_BUILDDATE used in EEPROM magic
  16. /* Artificial delay added to get media keys to work in the encoder*/
  17. #define MEDIA_KEY_DELAY 10
  18. volatile uint8_t led_numlock = false;
  19. volatile uint8_t led_capslock = false;
  20. volatile uint8_t led_scrolllock = false;
  21. uint8_t layer;
  22. bool clock_set_mode = false;
  23. uint8_t oled_mode = OLED_DEFAULT;
  24. bool oled_repaint_requested = false;
  25. bool oled_wakeup_requested = false;
  26. uint32_t oled_sleep_timer;
  27. uint8_t encoder_value = 32;
  28. uint8_t encoder_mode = ENC_MODE_VOLUME;
  29. uint8_t enabled_encoder_modes = 0x1F;
  30. RTCDateTime last_timespec;
  31. uint16_t last_minute = 0;
  32. uint8_t time_config_idx = 0;
  33. int8_t hour_config = 0;
  34. int16_t minute_config = 0;
  35. int8_t year_config = 0;
  36. int8_t month_config = 0;
  37. int8_t day_config = 0;
  38. uint8_t previous_encoder_mode = 0;
  39. void board_init(void) {
  40. SYSCFG->CFGR1 |= SYSCFG_CFGR1_I2C1_DMA_RMP;
  41. SYSCFG->CFGR1 &= ~(SYSCFG_CFGR1_SPI2_DMA_RMP);
  42. }
  43. uint32_t read_custom_config(void *data, uint32_t offset, uint32_t length) {
  44. #ifdef VIA_ENABLE
  45. return via_read_custom_config(data, offset, length);
  46. #else
  47. return eeconfig_read_kb_datablock(data, offset, length);
  48. #endif
  49. }
  50. uint32_t write_custom_config(const void *data, uint32_t offset, uint32_t length) {
  51. #ifdef VIA_ENABLE
  52. return via_update_custom_config(data, offset, length);
  53. #else
  54. return eeconfig_update_kb_datablock(data, offset, length);
  55. #endif
  56. }
  57. void keyboard_post_init_kb(void) {
  58. /*
  59. This is a workaround to some really weird behavior
  60. Without this code, the OLED will turn on, but not when you initially plug the keyboard in.
  61. You have to manually trigger a user reset to get the OLED to initialize properly
  62. I'm not sure what the root cause is at this time, but this workaround fixes it.
  63. */
  64. #ifdef OLED_ENABLE
  65. if(!is_oled_on()){
  66. wait_ms(3000);
  67. oled_init(OLED_ROTATION_0);
  68. }
  69. #endif
  70. keyboard_post_init_user();
  71. }
  72. #ifdef VIA_ENABLE
  73. void custom_set_value(uint8_t *data) {
  74. uint8_t *value_id = &(data[0]);
  75. uint8_t *value_data = &(data[1]);
  76. switch ( *value_id ) {
  77. case id_oled_default_mode:
  78. {
  79. write_custom_config(&value_data[0], EEPROM_DEFAULT_OLED_OFFSET, 1);
  80. break;
  81. }
  82. case id_oled_mode:
  83. {
  84. oled_mode = value_data[0];
  85. oled_request_wakeup();
  86. break;
  87. }
  88. case id_encoder_modes:
  89. {
  90. uint8_t index = value_data[0];
  91. uint8_t enable = value_data[1];
  92. enabled_encoder_modes = (enabled_encoder_modes & ~(1<<index)) | (enable<<index);
  93. write_custom_config(&enabled_encoder_modes, EEPROM_ENABLED_ENCODER_MODES_OFFSET, 1);
  94. break;
  95. }
  96. case id_encoder_custom:
  97. {
  98. uint8_t custom_encoder_idx = value_data[0];
  99. uint8_t encoder_behavior = value_data[1];
  100. uint16_t keycode = (value_data[2] << 8) | value_data[3];
  101. set_custom_encoder_config(custom_encoder_idx, encoder_behavior, keycode);
  102. break;
  103. }
  104. }
  105. }
  106. void custom_get_value(uint8_t *data) {
  107. uint8_t *value_id = &(data[0]);
  108. uint8_t *value_data = &(data[1]);
  109. switch ( *value_id ) {
  110. case id_oled_default_mode:
  111. {
  112. uint8_t default_oled;
  113. read_custom_config(&default_oled, EEPROM_DEFAULT_OLED_OFFSET, 1);
  114. value_data[0] = default_oled;
  115. break;
  116. }
  117. case id_oled_mode:
  118. {
  119. value_data[0] = oled_mode;
  120. break;
  121. }
  122. case id_encoder_modes:
  123. {
  124. uint8_t index = value_data[0];
  125. value_data[1] = (enabled_encoder_modes & (1<<index)) ? 1 : 0;
  126. break;
  127. }
  128. case id_encoder_custom:
  129. {
  130. uint8_t custom_encoder_idx = value_data[0];
  131. uint8_t encoder_behavior = value_data[1];
  132. uint16_t keycode = retrieve_custom_encoder_config(custom_encoder_idx, encoder_behavior);
  133. value_data[2] = keycode >> 8;
  134. value_data[3] = keycode & 0xFF;
  135. break;
  136. }
  137. }
  138. }
  139. void via_custom_value_command_kb(uint8_t *data, uint8_t length) {
  140. uint8_t *command_id = &(data[0]);
  141. uint8_t *channel_id = &(data[1]);
  142. uint8_t *value_id_and_data = &(data[2]);
  143. if ( *channel_id == id_custom_channel ) {
  144. switch ( *command_id )
  145. {
  146. case id_custom_set_value:
  147. {
  148. custom_set_value(value_id_and_data);
  149. break;
  150. }
  151. case id_custom_get_value:
  152. {
  153. custom_get_value(value_id_and_data);
  154. break;
  155. }
  156. case id_custom_save:
  157. {
  158. // values are saved in custom_set_value()
  159. break;
  160. }
  161. default:
  162. {
  163. // Unhandled message.
  164. *command_id = id_unhandled;
  165. break;
  166. }
  167. }
  168. return;
  169. }
  170. *command_id = id_unhandled;
  171. // DO NOT call raw_hid_send(data,length) here, let caller do this
  172. }
  173. #endif
  174. void read_host_led_state(void) {
  175. led_t led_state = host_keyboard_led_state();
  176. if (led_state.num_lock) {
  177. if (led_numlock == false){
  178. led_numlock = true;}
  179. } else {
  180. if (led_numlock == true){
  181. led_numlock = false;}
  182. }
  183. if (led_state.caps_lock) {
  184. if (led_capslock == false){
  185. led_capslock = true;}
  186. } else {
  187. if (led_capslock == true){
  188. led_capslock = false;}
  189. }
  190. if (led_state.scroll_lock) {
  191. if (led_scrolllock == false){
  192. led_scrolllock = true;}
  193. } else {
  194. if (led_scrolllock == true){
  195. led_scrolllock = false;}
  196. }
  197. }
  198. layer_state_t layer_state_set_kb(layer_state_t state) {
  199. state = layer_state_set_user(state);
  200. layer = get_highest_layer(state);
  201. oled_request_wakeup();
  202. return state;
  203. }
  204. bool process_record_kb(uint16_t keycode, keyrecord_t *record) {
  205. oled_request_wakeup();
  206. switch (keycode) {
  207. case OLED_TOGG:
  208. if(!clock_set_mode){
  209. if (record->event.pressed) {
  210. oled_mode = (oled_mode + 1) % _NUM_OLED_MODES;
  211. }
  212. }
  213. return false;
  214. case CLOCK_SET:
  215. if (record->event.pressed) {
  216. if(clock_set_mode){
  217. pre_encoder_mode_change();
  218. clock_set_mode = false;
  219. encoder_mode = previous_encoder_mode;
  220. post_encoder_mode_change();
  221. }else{
  222. previous_encoder_mode = encoder_mode;
  223. pre_encoder_mode_change();
  224. clock_set_mode = true;
  225. encoder_mode = ENC_MODE_CLOCK_SET;
  226. post_encoder_mode_change();
  227. }
  228. }
  229. return false;
  230. case ENC_PRESS:
  231. if (record->event.pressed) {
  232. uint16_t mapped_code = handle_encoder_press();
  233. uint16_t held_keycode_timer = timer_read();
  234. if(mapped_code != 0){
  235. register_code16(mapped_code);
  236. while (timer_elapsed(held_keycode_timer) < MEDIA_KEY_DELAY){ /* no-op */ }
  237. unregister_code16(mapped_code);
  238. }
  239. } else {
  240. // Do something else when release
  241. }
  242. return false;
  243. default:
  244. break;
  245. }
  246. return process_record_user(keycode, record);
  247. }
  248. bool encoder_update_kb(uint8_t index, bool clockwise) {
  249. if (!encoder_update_user(index, clockwise)) return false;
  250. oled_request_wakeup();
  251. encoder_value = (encoder_value + (clockwise ? 1 : -1)) % 64;
  252. if (index == 0) {
  253. if (layer == 0){
  254. uint16_t mapped_code = 0;
  255. if (clockwise) {
  256. mapped_code = handle_encoder_clockwise();
  257. } else {
  258. mapped_code = handle_encoder_ccw();
  259. }
  260. uint16_t held_keycode_timer = timer_read();
  261. if(mapped_code != 0){
  262. register_code16(mapped_code);
  263. while (timer_elapsed(held_keycode_timer) < MEDIA_KEY_DELAY){ /* no-op */ }
  264. unregister_code16(mapped_code);
  265. }
  266. } else {
  267. if(clockwise){
  268. change_encoder_mode(false);
  269. } else {
  270. change_encoder_mode(true);
  271. }
  272. }
  273. }
  274. return true;
  275. }
  276. void custom_config_reset(void){
  277. for(int i = 0; i < VIA_EEPROM_CUSTOM_CONFIG_SIZE; ++i) {
  278. uint8_t dummy = 0;
  279. write_custom_config(&dummy, i, 1);
  280. }
  281. uint8_t encoder_modes = 0x1F;
  282. write_custom_config(&encoder_modes, EEPROM_ENABLED_ENCODER_MODES_OFFSET, 1);
  283. }
  284. void custom_config_load(void){
  285. #ifdef DYNAMIC_KEYMAP_ENABLE
  286. read_custom_config(&oled_mode, EEPROM_DEFAULT_OLED_OFFSET, 1);
  287. read_custom_config(&enabled_encoder_modes, EEPROM_ENABLED_ENCODER_MODES_OFFSET, 1);
  288. #endif
  289. }
  290. // Called from via_init() if VIA_ENABLE
  291. // Called from matrix_init_kb() if not VIA_ENABLE
  292. void satisfaction_core_init(void)
  293. {
  294. // This checks both an EEPROM reset (from bootmagic lite, keycodes)
  295. // and also firmware build date (from via_eeprom_is_valid())
  296. if (eeconfig_is_enabled()) {
  297. custom_config_load();
  298. } else {
  299. #ifdef DYNAMIC_KEYMAP_ENABLE
  300. // Reset the custom stuff
  301. custom_config_reset();
  302. #endif
  303. // DO NOT set EEPROM valid here, let caller do this
  304. }
  305. }
  306. void matrix_init_kb(void)
  307. {
  308. #ifndef VIA_ENABLE
  309. satisfaction_core_init();
  310. #endif // VIA_ENABLE
  311. rtcGetTime(&RTCD1, &last_timespec);
  312. matrix_init_user();
  313. oled_request_wakeup();
  314. }
  315. #ifdef VIA_ENABLE
  316. void via_init_kb(void) {
  317. satisfaction_core_init();
  318. }
  319. #endif // VIA_ENABLE
  320. void housekeeping_task_kb(void) {
  321. rtcGetTime(&RTCD1, &last_timespec);
  322. uint16_t minutes_since_midnight = last_timespec.millisecond / 1000 / 60;
  323. if (minutes_since_midnight != last_minute){
  324. last_minute = minutes_since_midnight;
  325. oled_request_repaint();
  326. }
  327. }