keyboard.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. #include "keyboard.h"
  2. #include "ch.h"
  3. #include "hal.h"
  4. #include "led_custom.h"
  5. #include "util.h"
  6. #include "quantum.h"
  7. #include "ws2812.h"
  8. #include "raw_hid.h"
  9. #include "dynamic_keymap.h"
  10. #include "tmk_core/common/eeprom.h"
  11. #include "version.h" // for QMK_BUILDDATE used in EEPROM magic
  12. #include "via.h"
  13. #define EEPROM_CUSTOM_BACKLIGHT (VIA_EEPROM_CUSTOM_CONFIG_ADDR)
  14. backlight_config_t kb_backlight_config = {
  15. .enable = true,
  16. .breathing = true,
  17. .level = BACKLIGHT_LEVELS
  18. };
  19. void backlight_config_save(){
  20. eeprom_update_byte((uint8_t*)EEPROM_CUSTOM_BACKLIGHT, kb_backlight_config.raw);
  21. }
  22. void backlight_config_load(){
  23. kb_backlight_config.raw = eeprom_read_byte((uint8_t*)EEPROM_CUSTOM_BACKLIGHT);
  24. }
  25. // Called from via_init() if VIA_ENABLE
  26. // Called from matrix_init_kb() if not VIA_ENABLE
  27. void via_init_kb(void)
  28. {
  29. // If the EEPROM has the magic, the data is good.
  30. // OK to load from EEPROM.
  31. if (via_eeprom_is_valid()) {
  32. backlight_config_load();
  33. } else {
  34. // If the EEPROM has not been saved before, or is out of date,
  35. // save the default values to the EEPROM. Default values
  36. // come from construction of the backlight_config instance.
  37. backlight_config_save();
  38. // DO NOT set EEPROM valid here, let caller do this
  39. }
  40. }
  41. __attribute__ ((weak))
  42. void matrix_init_board(void);
  43. void matrix_init_kb(void){
  44. // If VIA is disabled, we still need to load backlight settings.
  45. // Call via_init_kb() the same way as via_init(), with setting
  46. // EEPROM valid afterwards.
  47. #ifndef VIA_ENABLE
  48. via_init_kb();
  49. via_eeprom_set_valid(true);
  50. #endif // VIA_ENABLE
  51. /* MOSI pin*/
  52. #ifdef RGBLIGHT_ENABLE
  53. palSetPadMode(PORT_WS2812, PIN_WS2812, PAL_MODE_ALTERNATE(0));
  54. wait_ms(500);
  55. leds_init();
  56. #endif
  57. backlight_init_ports();
  58. matrix_init_board();
  59. }
  60. void matrix_scan_kb(void)
  61. {
  62. #ifdef RGBLIGHT_ENABLE
  63. rgblight_task();
  64. #endif
  65. matrix_scan_user();
  66. }
  67. bool process_record_kb(uint16_t keycode, keyrecord_t *record) {
  68. switch (keycode) {
  69. case BL_INC:
  70. if (record->event.pressed) {
  71. kb_backlight_config.level = kb_backlight_config.level + 1;
  72. if(kb_backlight_config.level > BACKLIGHT_LEVELS){
  73. kb_backlight_config.level = BACKLIGHT_LEVELS;
  74. }
  75. backlight_set(kb_backlight_config.level);
  76. backlight_config_save();
  77. }
  78. return false;
  79. case BL_TOGG:
  80. if (record->event.pressed) {
  81. kb_backlight_config.enable = !kb_backlight_config.enable;
  82. if(kb_backlight_config.enable){
  83. backlight_set(kb_backlight_config.level);
  84. } else {
  85. backlight_set(0);
  86. }
  87. backlight_config_save();
  88. }
  89. return false;
  90. case BL_DEC:
  91. if (record->event.pressed) {
  92. if(kb_backlight_config.level <= 1){
  93. kb_backlight_config.level = 0;
  94. } else {
  95. kb_backlight_config.level = kb_backlight_config.level - 1;
  96. }
  97. backlight_set(kb_backlight_config.level);
  98. backlight_config_save();
  99. }
  100. return false;
  101. case BL_BRTG:
  102. if (record->event.pressed) {
  103. kb_backlight_config.breathing = !kb_backlight_config.breathing;
  104. breathing_toggle();
  105. backlight_config_save();
  106. }
  107. return false;
  108. default:
  109. break;
  110. }
  111. return process_record_user(keycode, record);;
  112. }
  113. #ifdef VIA_ENABLE
  114. void backlight_get_value( uint8_t *data )
  115. {
  116. uint8_t *value_id = &(data[0]);
  117. uint8_t *value_data = &(data[1]);
  118. switch (*value_id)
  119. {
  120. case id_qmk_backlight_brightness:
  121. {
  122. // level / BACKLIGHT_LEVELS * 255
  123. value_data[0] = ((uint16_t)kb_backlight_config.level) * 255 / BACKLIGHT_LEVELS;
  124. break;
  125. }
  126. case id_qmk_backlight_effect:
  127. {
  128. value_data[0] = kb_backlight_config.breathing ? 1 : 0;
  129. break;
  130. }
  131. }
  132. }
  133. void backlight_set_value( uint8_t *data )
  134. {
  135. uint8_t *value_id = &(data[0]);
  136. uint8_t *value_data = &(data[1]);
  137. switch (*value_id)
  138. {
  139. case id_qmk_backlight_brightness:
  140. {
  141. // level / 255 * BACKLIGHT_LEVELS
  142. kb_backlight_config.level = ((uint16_t)value_data[0]) * BACKLIGHT_LEVELS / 255;
  143. backlight_set(kb_backlight_config.level);
  144. break;
  145. }
  146. case id_qmk_backlight_effect:
  147. {
  148. if ( value_data[0] == 0 ) {
  149. kb_backlight_config.breathing = false;
  150. breathing_disable();
  151. } else {
  152. kb_backlight_config.breathing = true;
  153. breathing_enable();
  154. }
  155. break;
  156. }
  157. }
  158. }
  159. void raw_hid_receive_kb( uint8_t *data, uint8_t length )
  160. {
  161. uint8_t *command_id = &(data[0]);
  162. uint8_t *command_data = &(data[1]);
  163. switch ( *command_id )
  164. {
  165. case id_lighting_set_value:
  166. {
  167. backlight_set_value(command_data);
  168. break;
  169. }
  170. case id_lighting_get_value:
  171. {
  172. backlight_get_value(command_data);
  173. break;
  174. }
  175. case id_lighting_save:
  176. {
  177. backlight_config_save();
  178. break;
  179. }
  180. default:
  181. {
  182. // Unhandled message.
  183. *command_id = id_unhandled;
  184. break;
  185. }
  186. }
  187. // DO NOT call raw_hid_send(data,length) here, let caller do this
  188. }
  189. #endif
  190. //
  191. // In the case of VIA being disabled, we still need to check if
  192. // keyboard level EEPROM memory is valid before loading.
  193. // Thus these are copies of the same functions in VIA, since
  194. // the backlight settings reuse VIA's EEPROM magic/version,
  195. // and the ones in via.c won't be compiled in.
  196. //
  197. // Yes, this is sub-optimal, and is only here for completeness
  198. // (i.e. catering to the 1% of people that want wilba.tech LED bling
  199. // AND want persistent settings BUT DON'T want to use dynamic keymaps/VIA).
  200. //
  201. #ifndef VIA_ENABLE
  202. bool via_eeprom_is_valid(void)
  203. {
  204. char *p = QMK_BUILDDATE; // e.g. "2019-11-05-11:29:54"
  205. uint8_t magic0 = ( ( p[2] & 0x0F ) << 4 ) | ( p[3] & 0x0F );
  206. uint8_t magic1 = ( ( p[5] & 0x0F ) << 4 ) | ( p[6] & 0x0F );
  207. uint8_t magic2 = ( ( p[8] & 0x0F ) << 4 ) | ( p[9] & 0x0F );
  208. return (eeprom_read_byte( (void*)VIA_EEPROM_MAGIC_ADDR+0 ) == magic0 &&
  209. eeprom_read_byte( (void*)VIA_EEPROM_MAGIC_ADDR+1 ) == magic1 &&
  210. eeprom_read_byte( (void*)VIA_EEPROM_MAGIC_ADDR+2 ) == magic2 );
  211. }
  212. // Sets VIA/keyboard level usage of EEPROM to valid/invalid
  213. // Keyboard level code (eg. via_init_kb()) should not call this
  214. void via_eeprom_set_valid(bool valid)
  215. {
  216. char *p = QMK_BUILDDATE; // e.g. "2019-11-05-11:29:54"
  217. uint8_t magic0 = ( ( p[2] & 0x0F ) << 4 ) | ( p[3] & 0x0F );
  218. uint8_t magic1 = ( ( p[5] & 0x0F ) << 4 ) | ( p[6] & 0x0F );
  219. uint8_t magic2 = ( ( p[8] & 0x0F ) << 4 ) | ( p[9] & 0x0F );
  220. eeprom_update_byte( (void*)VIA_EEPROM_MAGIC_ADDR+0, valid ? magic0 : 0xFF);
  221. eeprom_update_byte( (void*)VIA_EEPROM_MAGIC_ADDR+1, valid ? magic1 : 0xFF);
  222. eeprom_update_byte( (void*)VIA_EEPROM_MAGIC_ADDR+2, valid ? magic2 : 0xFF);
  223. }
  224. void via_eeprom_reset(void)
  225. {
  226. // Set the VIA specific EEPROM state as invalid.
  227. via_eeprom_set_valid(false);
  228. // Set the TMK/QMK EEPROM state as invalid.
  229. eeconfig_disable();
  230. }
  231. #endif // VIA_ENABLE