You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

308 lines
11 KiB

  1. // Copyright 2021 JasonRen(biu)
  2. // Copyright 2022 Drashna Jael're (@Drashna Jael're)
  3. // SPDX-License-Identifier: GPL-2.0-or-later
  4. #include "hotdox76v2.h"
  5. #include <string.h>
  6. #include <transactions.h>
  7. #include "oled_font_lib/logo2.h"
  8. #include "oled_font_lib/ext_font.h"
  9. #ifdef RGB_MATRIX_ENABLE
  10. // clang-format off
  11. led_config_t g_led_config = {
  12. {
  13. { NO_LED, 34, 33, 32, 35, 37, 36 },
  14. { 27, 28, 29, 30, 31, NO_LED, NO_LED },
  15. { 26, 25, 24, 23, 22, 21, 20 },
  16. { 14, 15, 16, 17, 18, 19, NO_LED },
  17. { 13, 12, 11, 10, 9, 8, 7 },
  18. { 0, 1, 2, 3, 4, 5, 6 },
  19. /*right*/
  20. { NO_LED, 72, 71, 70, 73, 75, 74 },
  21. { 65, 66, 67, 68, 69, NO_LED, NO_LED },
  22. { 64, 63, 62, 61, 60, 59, 58 },
  23. { 52, 53, 54, 55, 56, 57, NO_LED },
  24. { 51, 50, 49, 48, 47, 46, 45 },
  25. { 38, 39, 40, 41, 42, 43, 44 }
  26. },
  27. {
  28. // LED Index to Physical Position
  29. {0,0}, {17,0}, {34,0}, {52,0}, {69,0}, {86,0}, {103,0},
  30. {103,13}, {86,13}, {69,13}, {52,13}, {34,13}, {17,13}, {0,13},
  31. {0,26}, {17,26}, {34,26}, {52,26}, {69,26}, {86,26},
  32. {103,38}, {86,38}, {69,38}, {52,38}, {34,38}, {17,38}, {0,38},
  33. {0,51}, {17,51}, {34,51}, {52,51}, {69,51},
  34. {86,64}, {69,64}, {52,64}, {34,64}, {17,64}, {0,64},
  35. {69,64}, {52,64}, {34,64}, {17,64}, {0,64},
  36. {224,0}, {207,0}, {190,0}, {172,0}, {155,0}, {138,0}, {121,0},
  37. {121,13}, {138,13}, {155,13}, {172,13}, {190,13}, {207,13}, {224,13},
  38. {224,26}, {207,26}, {190,26}, {172,26}, {155,26}, {138,26},
  39. {121,38}, {138,38}, {155,38}, {172,38}, {190,38}, {207,38}, {224,38},
  40. {224,51}, {207,51}, {190,51}, {172,51}, {155,51},
  41. {138,64}, {155,64}, {172,64}, {190,64}, {207,64}, {224,64},
  42. {155,64}, {172,64}, {190,64}, {207,64}, {224,64}
  43. },
  44. {
  45. // LED Index to Flag
  46. 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
  47. 2,2,2,2,2,
  48. 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
  49. 2,2,2,2,2
  50. }
  51. };
  52. // clang-format on
  53. #endif
  54. #ifdef OLED_ENABLE
  55. # define UNC (94 + 0x21)
  56. typedef struct _master_to_slave_t {
  57. int cur_alp_index;
  58. char current_alp[7];
  59. } master_to_slave_t;
  60. master_to_slave_t m2s;
  61. typedef struct _slave_to_master_t {
  62. int cur_alp_index;
  63. char current_alp[7];
  64. } slave_to_master_t;
  65. slave_to_master_t s2m;
  66. oled_rotation_t oled_init_kb(oled_rotation_t rotation) {
  67. strcpy((char *)(m2s.current_alp), "[ ]");
  68. m2s.current_alp[1] = UNC;
  69. m2s.current_alp[2] = UNC;
  70. m2s.current_alp[3] = UNC;
  71. m2s.current_alp[4] = UNC;
  72. m2s.cur_alp_index = 1;
  73. strcpy((char *)(s2m.current_alp), "[ ]");
  74. s2m.current_alp[1] = UNC;
  75. s2m.current_alp[2] = UNC;
  76. s2m.current_alp[3] = UNC;
  77. s2m.current_alp[4] = UNC;
  78. s2m.cur_alp_index = 1;
  79. if (is_keyboard_left()) {
  80. return OLED_ROTATION_180;
  81. } else {
  82. return OLED_ROTATION_0;
  83. }
  84. }
  85. void render_logo(void) {
  86. uint8_t i = 0, j = 0;
  87. for (i = 0; i < 4; ++i) {
  88. for (j = 0; j < 32; ++j) {
  89. if (is_keyboard_left()) {
  90. oled_write_raw_byte(pgm_read_byte(&logo_mouse[i * 32 + j]), i * 128 + j);
  91. } else {
  92. oled_write_raw_byte(pgm_read_byte(&logo_mouse[i * 32 + j]), i * 128 + j + 96);
  93. }
  94. }
  95. }
  96. }
  97. void render_layer_helper_fun(uint8_t start_line, const char *data, uint8_t gap_w, uint8_t l) {
  98. uint8_t j = 0, k = 0;
  99. for (j = 0; j < l; ++j) { // font index
  100. for (k = 0; k < 12; ++k) { // font byte index
  101. // base + logo_w(32) + gap_w(12) +l*font_w(12)+current_byte_index
  102. oled_write_raw_byte(pgm_read_byte(&ext_big_font[pgm_read_byte(&data[j]) - 0x21][k]), start_line * 2 * 128 + 32 + gap_w + j * 12 + k);
  103. oled_write_raw_byte(pgm_read_byte(&ext_big_font[pgm_read_byte(&data[j]) - 0x21][k + 12]), start_line * 2 * 128 + 128 + 32 + gap_w + j * 12 + k);
  104. }
  105. }
  106. for (j = 0; j < gap_w; ++j) {
  107. oled_write_raw_byte(pgm_read_byte(&blank_block), start_line * 2 * 128 + 32 + j);
  108. oled_write_raw_byte(pgm_read_byte(&blank_block), start_line * 2 * 128 + 32 + gap_w + l * 12 + j);
  109. oled_write_raw_byte(pgm_read_byte(&blank_block), start_line * 2 * 128 + 128 + 32 + j);
  110. oled_write_raw_byte(pgm_read_byte(&blank_block), start_line * 2 * 128 + 128 + 32 + gap_w + l * 12 + j);
  111. }
  112. }
  113. void render_layer(uint8_t layer) {
  114. render_layer_helper_fun(0, PSTR("LAYER:"), 12, 6);
  115. switch (layer) {
  116. case 0:
  117. render_layer_helper_fun(1, PSTR("1:HOME"), 12, 6);
  118. break;
  119. case 1:
  120. render_layer_helper_fun(1, PSTR("2:CODE"), 12, 6);
  121. break;
  122. case 2:
  123. render_layer_helper_fun(1, PSTR("3:OFFICE"), 0, 8);
  124. break;
  125. case 3:
  126. default:
  127. render_layer_helper_fun(1, PSTR("4:OTHERS"), 0, 8);
  128. break;
  129. }
  130. }
  131. void render_cur_input_helper_fun(uint8_t start_line, const char *data, uint8_t gap_w, uint8_t l) {
  132. uint8_t j = 0, k = 0;
  133. for (j = 0; j < l; ++j) { // font index
  134. for (k = 0; k < 12; ++k) { // font byte index
  135. // base + logo_w(0) + gap_w(12) +l*font_w(12)+current_byte_index
  136. oled_write_raw_byte(pgm_read_byte(&ext_big_font[data[j] - 0x21][k]), start_line * 2 * 128 + gap_w + j * 12 + k);
  137. oled_write_raw_byte(pgm_read_byte(&ext_big_font[data[j] - 0x21][12 + k]), start_line * 2 * 128 + 128 + gap_w + j * 12 + k);
  138. }
  139. }
  140. for (j = 0; j < gap_w; ++j) {
  141. oled_write_raw_byte(pgm_read_byte(&blank_block), start_line * 2 * 128 + j);
  142. oled_write_raw_byte(pgm_read_byte(&blank_block), start_line * 2 * 128 + gap_w + l * 12 + j);
  143. oled_write_raw_byte(pgm_read_byte(&blank_block), start_line * 2 * 128 + 128 + j);
  144. oled_write_raw_byte(pgm_read_byte(&blank_block), start_line * 2 * 128 + 128 + gap_w + l * 12 + j);
  145. }
  146. }
  147. void render_cur_input(void) {
  148. render_cur_input_helper_fun(0, "INPUTS:", 6, 7);
  149. if (is_keyboard_master()) {
  150. render_cur_input_helper_fun(1, (const char *)(m2s.current_alp), 12, 6);
  151. } else {
  152. render_cur_input_helper_fun(1, (const char *)(s2m.current_alp), 12, 6);
  153. }
  154. return;
  155. }
  156. bool oled_task_kb(void) {
  157. if (!oled_task_user()) {
  158. return false;
  159. }
  160. render_logo();
  161. if (is_keyboard_left()) {
  162. render_layer(biton32(layer_state));
  163. } else {
  164. render_cur_input();
  165. }
  166. return false;
  167. }
  168. static const char PROGMEM code_to_name[0xFF] = {
  169. // 0 1 2 3 4 5 6 7 8 9 A B c D E F
  170. UNC, UNC, UNC, UNC, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', // 0x
  171. 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '1', '2', // 1x
  172. '3', '4', '5', '6', '7', '8', '9', '0', UNC, UNC, UNC, UNC, UNC, '-', '=', '[', // 2x
  173. ']', '\\', '#', ';', '\'', '`', ',', '.', '/', UNC, UNC, UNC, UNC, UNC, UNC, UNC, // 3x
  174. UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, // 4x
  175. UNC, UNC, UNC, UNC, '/', '*', '-', '+', UNC, '1', '2', '3', '4', '5', '6', '7', // 5x
  176. '8', '9', '0', '.', UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, // 6x
  177. UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, // 7x
  178. UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, // 8x
  179. UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, // 9x
  180. UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, // Ax
  181. UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, // Bx
  182. UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, // Cx
  183. UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, // Dx
  184. UNC, UNC, 'A', 'W', UNC, 'S', UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, // Ex
  185. UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC, UNC // Fx
  186. };
  187. void get_cur_alp_hook(uint16_t keycode) {
  188. if (keycode >= 0xF0) {
  189. keycode = 0xF0;
  190. }
  191. if (m2s.cur_alp_index < 4) {
  192. m2s.current_alp[m2s.cur_alp_index] = pgm_read_byte(&code_to_name[keycode]);
  193. if (m2s.cur_alp_index == 1) {
  194. m2s.current_alp[2] = m2s.current_alp[3] = m2s.current_alp[4] = UNC;
  195. }
  196. m2s.cur_alp_index++;
  197. } else {
  198. for (uint8_t i = 2; i <= 4; ++i) {
  199. m2s.current_alp[i - 1] = m2s.current_alp[i];
  200. }
  201. m2s.current_alp[m2s.cur_alp_index] = pgm_read_byte(&code_to_name[keycode]);
  202. }
  203. }
  204. bool process_record_kb(uint16_t keycode, keyrecord_t *record) {
  205. if (record->event.pressed) {
  206. get_cur_alp_hook(keycode);
  207. }
  208. if (!process_record_user(keycode, record)) {
  209. return false;
  210. }
  211. switch (keycode) {
  212. case TOG_OLED:
  213. if (record->event.pressed) {
  214. if (is_oled_on()) {
  215. oled_off();
  216. } else {
  217. oled_on();
  218. }
  219. }
  220. return false;
  221. default:
  222. return true;
  223. }
  224. return true;
  225. }
  226. void matrix_scan_kb(void) {
  227. if (!is_oled_on()) {
  228. m2s.cur_alp_index = 1;
  229. }
  230. matrix_scan_user();
  231. }
  232. void user_sync_alpa_slave_handler(uint8_t in_buflen, const void *in_data, uint8_t out_buflen, void *out_data) {
  233. const master_to_slave_t *m2s_p = (const master_to_slave_t *)in_data;
  234. s2m.cur_alp_index = m2s_p->cur_alp_index;
  235. for (size_t i = 0; i < 7; i++) {
  236. s2m.current_alp[i] = m2s_p->current_alp[i];
  237. }
  238. }
  239. void keyboard_post_init_kb(void) {
  240. transaction_register_rpc(KEYBOARD_CURRENT_ALPA_SYNC, user_sync_alpa_slave_handler);
  241. keyboard_post_init_user();
  242. }
  243. void housekeeping_task_kb(void) {
  244. if (is_keyboard_master()) {
  245. // Interact with slave every 200ms
  246. static uint32_t last_sync = 0;
  247. if (timer_elapsed32(last_sync) > 200) {
  248. if (transaction_rpc_exec(KEYBOARD_CURRENT_ALPA_SYNC, sizeof(m2s), &m2s, sizeof(s2m), &s2m)) {
  249. last_sync = timer_read32();
  250. dprint("Slave sync successed!\n");
  251. } else {
  252. dprint("Slave sync failed!\n");
  253. }
  254. }
  255. }
  256. housekeeping_task_user();
  257. }
  258. #endif
  259. #ifdef SWAP_HANDS_ENABLE
  260. __attribute__((weak))
  261. const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = {
  262. /* Left hand, matrix positions */
  263. {{0, 6}, {1, 6}, {2, 6}, {3, 6}, {4, 6}, {5, 6}, {6, 6}},
  264. {{0, 7}, {1, 7}, {2, 7}, {3, 7}, {4, 7}, {5, 7}, {6, 7}},
  265. {{0, 8}, {1, 8}, {2, 8}, {3, 8}, {4, 8}, {5, 8}, {6, 8}},
  266. {{0, 9}, {1, 9}, {2, 9}, {3, 9}, {4, 9}, {5, 9}, {6, 9}},
  267. {{0, 10}, {1, 10}, {2, 10}, {3, 10}, {4, 10}, {5, 10}, {6, 10}},
  268. {{0, 11}, {1, 11}, {2, 11}, {3, 11}, {4, 11}, {5, 11}, {6, 11}},
  269. /* Right hand, matrix positions */
  270. {{0, 5}, {1, 5}, {2, 5}, {3, 5}, {4, 5}, {5, 5}, {6, 5}},
  271. {{0, 4}, {1, 4}, {2, 4}, {3, 4}, {4, 4}, {5, 4}, {6, 4}},
  272. {{0, 3}, {1, 3}, {2, 3}, {3, 3}, {4, 3}, {5, 3}, {6, 3}},
  273. {{0, 2}, {1, 2}, {2, 2}, {3, 2}, {4, 2}, {5, 2}, {6, 2}},
  274. {{0, 1}, {1, 1}, {2, 1}, {3, 1}, {4, 1}, {5, 1}, {6, 1}},
  275. {{0, 0}, {1, 0}, {2, 0}, {3, 0}, {4, 0}, {5, 0}, {6, 0}}
  276. };
  277. #endif