evo70.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807
  1. /* Copyright 2021 customMK
  2. *
  3. * This program is free software: you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License as published by
  5. * the Free Software Foundation, either version 2 of the License, or
  6. * (at your option) any later version.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License
  14. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. */
  16. #include "quantum.h"
  17. #include <stdbool.h>
  18. #include "matrix.h"
  19. #include OLED_FONT_H
  20. //If Bongo cat not undefined, Scroll wheel will be enabled,
  21. //but for scroll wheel to work, you must also set MOUSEKEY_ENABLE = yes
  22. //in rules.mk
  23. #define BONGOCAT
  24. /* Placement information for display elements */
  25. #define ENC_DISPLAY_X 0
  26. #define ENC_DISPLAY_Y 0
  27. #define LAYER_DISPLAY_X 5
  28. #define LAYER_DISPLAY_Y 19
  29. #define CAPSLOCK_DISPLAY_X 80
  30. #define CAPSLOCK_DISPLAY_Y 19
  31. #define NUMLOCK_DISPLAY_X 105
  32. #define NUMLOCK_DISPLAY_Y 19
  33. /* Encoder Parameters */
  34. static bool OLED_awakened = false;
  35. static bool OLED_redraw = false;
  36. static bool startup_complete = false;
  37. static bool startup_delay = false;
  38. static bool starting_up = false;
  39. #define ENCODER_MATRIX_ROW 5
  40. #define ENCODER_MATRIX_COL 6
  41. #define ENC_SPLASH 0
  42. #define ENC_VOLUME 1
  43. #define ENC_MEDIA 2
  44. #define ENC_CUSTOM 3
  45. #define ENC_BL_BRIGHT 4
  46. #define ENC_BL_BREATH 5
  47. #define ENC_RGB_BRIGHT 6
  48. #define ENC_RGB_MODE 7
  49. #define ENC_RGB_COLOR 8
  50. #define ENC_SCROLL 9
  51. #ifdef BONGOCAT
  52. #define ENC_BONGO 9
  53. #endif //bongocat
  54. char* enc_mode_str[] = {
  55. #ifdef BONGOCAT
  56. /* Splash */ "",
  57. "Volume",
  58. "Media Control",
  59. "Custom",
  60. "Backlight Brightness",
  61. "Backlight Breathing",
  62. "Underglow Brightness",
  63. "Underglow Mode",
  64. "Underglow Color",
  65. "" // Bongo Cat
  66. };
  67. uint16_t enc_cw[] = { KC_VOLU, KC_VOLU, KC_MEDIA_NEXT_TRACK, KC_VOLU, 0, 0, 0, 0, 0, KC_VOLU };
  68. uint16_t enc_ccw[] = { KC_VOLD, KC_VOLD, KC_MEDIA_PREV_TRACK, KC_VOLD, 0, 0, 0, 0, 0, KC_VOLD };
  69. #else
  70. /* Splash */ "",
  71. "Volume",
  72. "Media Control",
  73. "Custom",
  74. "Backlight Brightness",
  75. "Backlight Breathing",
  76. "Underglow Brightness",
  77. "Underglow Mode",
  78. "Underglow Color",
  79. "Scroll Wheel"
  80. };
  81. uint16_t enc_cw[] = { KC_VOLU, KC_VOLU, KC_MEDIA_NEXT_TRACK, KC_VOLU, 0, 0, 0, 0, 0, MS_WHLU };
  82. uint16_t enc_ccw[] = { KC_VOLD, KC_VOLD, KC_MEDIA_PREV_TRACK, KC_VOLD, 0, 0, 0, 0, 0, MS_WHLD };
  83. #endif //bongocat
  84. uint8_t num_enc_modes = 10;
  85. uint8_t enc_mode_str_startpos[] = {0, 49, 28, 49, 7, 10, 7, 25, 22, 31};
  86. uint8_t prev_layer = 255;
  87. uint8_t prev_capslock = 255;
  88. uint8_t prev_numlock = 255;
  89. typedef union {
  90. uint32_t raw;
  91. struct {
  92. uint8_t enc_mode;
  93. uint8_t breathingperiod;
  94. bool oled_is_on : 1;
  95. };
  96. } user_config_t;
  97. user_config_t user_config;
  98. /* OLED Draw Functions */
  99. /* TODO: Reimplement using Quantum Painter when available */
  100. static void draw_line_h(uint8_t x, uint8_t y, uint8_t len, bool on) {
  101. for (uint8_t i = 0; i < len; i++) {
  102. oled_write_pixel(i + x, y, on);
  103. }
  104. }
  105. static void draw_line_v(uint8_t x, uint8_t y, uint8_t len, bool on) {
  106. for (uint8_t i = 0; i < len; i++) {
  107. oled_write_pixel(x, i + y, on);
  108. }
  109. }
  110. void draw_rect_soft(uint8_t x, uint8_t y, uint8_t width, uint8_t height, bool on) {
  111. uint8_t tempHeight;
  112. draw_line_h(x + 1, y, width - 2, on);
  113. draw_line_h(x + 1, y + height - 1, width - 2, on);
  114. tempHeight = height - 2;
  115. if (tempHeight < 1) return;
  116. draw_line_v(x, y + 1, tempHeight, on);
  117. draw_line_v(x + width - 1, y + 1, tempHeight, on);
  118. }
  119. void write_char_at_pixel_xy(uint8_t x, uint8_t y, const char data, bool invert) {
  120. uint8_t i, j, temp;
  121. uint8_t cast_data = (uint8_t)data;
  122. const uint8_t *glyph = &font[((uint8_t)cast_data - OLED_FONT_START) * OLED_FONT_WIDTH];
  123. temp = pgm_read_byte(glyph);
  124. for (i = 0; i < OLED_FONT_WIDTH ; i++) {
  125. for (j = 0; j < OLED_FONT_HEIGHT; j++) {
  126. if (temp & 0x01) {
  127. oled_write_pixel(x + i, y + j, !invert);
  128. } else {
  129. oled_write_pixel(x + i, y + j, invert);
  130. }
  131. temp >>= 1;
  132. }
  133. temp = pgm_read_byte(++glyph);
  134. }
  135. }
  136. void write_chars_at_pixel_xy(uint8_t x, uint8_t y, const char *data, bool invert) {
  137. uint8_t c = data[0];
  138. uint8_t offset = 0;
  139. while (c != 0) {
  140. write_char_at_pixel_xy(x + offset, y, c, invert);
  141. data++;
  142. c = data[0];
  143. offset += 6;
  144. }
  145. }
  146. void draw_rect_filled_soft(uint8_t x, uint8_t y, uint8_t width, uint8_t height, bool on) {
  147. for (int i = x; i < x + width; i++) {
  148. if (i == x || i == (x + width - 1))
  149. draw_line_v(i, y + 1, height - 2, on);
  150. else
  151. draw_line_v(i, y, height, on);
  152. }
  153. }
  154. void draw_text_rectangle(uint8_t x, uint8_t y, uint8_t width, char* str, bool filled) {
  155. if (filled) {
  156. draw_rect_filled_soft(x, y, width, 11, true);
  157. write_chars_at_pixel_xy(x+3, y+2, str, true);
  158. } else {
  159. draw_rect_soft(x, y, width, 11, true);
  160. write_chars_at_pixel_xy(x+3, y+2, str, false);
  161. }
  162. }
  163. void draw_keyboard_layer(void){
  164. uint8_t highest_layer;
  165. highest_layer = get_highest_layer(layer_state);
  166. draw_rect_filled_soft(LAYER_DISPLAY_X + highest_layer*12, LAYER_DISPLAY_Y, 11, 11, true);
  167. write_char_at_pixel_xy(LAYER_DISPLAY_X+3, LAYER_DISPLAY_Y+2, '0', highest_layer == 0);
  168. write_char_at_pixel_xy(LAYER_DISPLAY_X+3+12, LAYER_DISPLAY_Y+2, '1', highest_layer == 1);
  169. write_char_at_pixel_xy(LAYER_DISPLAY_X+3+24, LAYER_DISPLAY_Y+2, '2', highest_layer == 2);
  170. write_char_at_pixel_xy(LAYER_DISPLAY_X+3+36, LAYER_DISPLAY_Y+2, '3', highest_layer == 3);
  171. draw_line_h(0, 14, 128, true);
  172. }
  173. static const uint8_t splash[] PROGMEM = {
  174. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  175. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  176. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00,
  177. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  178. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x1c, 0x06, 0x02, 0x02,
  179. 0x03, 0x03, 0x83, 0x83, 0x83, 0x83, 0x03, 0x03, 0x03, 0x03, 0x83, 0x83, 0x83, 0x83, 0x83, 0x03,
  180. 0x03, 0x03, 0x83, 0x83, 0x83, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x83, 0x83, 0x83, 0x83, 0x03,
  181. 0x02, 0x02, 0x06, 0x0c, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  182. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  183. 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
  184. 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x80, 0x80, 0xf8, 0xfe, 0x87, 0xe1, 0xbf, 0x9f, 0x00, 0x00,
  185. 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00,
  186. 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
  187. 0x00, 0x00, 0xff, 0xff, 0xff, 0x3f, 0xfc, 0xe0, 0xc0, 0xf8, 0x7f, 0x0f, 0xff, 0xff, 0x00, 0x00,
  188. 0x00, 0x00, 0xff, 0xff, 0xff, 0x80, 0xc0, 0xf0, 0xf8, 0x3c, 0x1f, 0x0f, 0x03, 0x01, 0x00, 0x00,
  189. 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  190. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfe, 0xc7, 0x83,
  191. 0x83, 0x8f, 0xc6, 0xc0, 0xfe, 0xff, 0xc7, 0xc0, 0xf0, 0xff, 0xff, 0x81, 0xc0, 0xe0, 0x70, 0x9e,
  192. 0x8f, 0xbf, 0xf8, 0xf0, 0x80, 0xc1, 0xe3, 0x7f, 0xff, 0xff, 0x83, 0x83, 0x83, 0xc1, 0xfc, 0xfe,
  193. 0xff, 0x83, 0x83, 0xdf, 0xff, 0x7e, 0x18, 0x18, 0xfe, 0xff, 0xfb, 0x1c, 0x06, 0xff, 0xff, 0xff,
  194. 0x3c, 0x0e, 0xe7, 0xff, 0xff, 0x80, 0xc0, 0xe0, 0x60, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
  195. 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x01, 0x0f, 0x0f, 0x03, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
  196. 0x00, 0x00, 0xff, 0xff, 0xff, 0x07, 0x03, 0x03, 0x0f, 0x3f, 0x7c, 0xf8, 0xe0, 0x80, 0x00, 0x00,
  197. 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  198. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
  199. 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01,
  200. 0x03, 0x03, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01,
  201. 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
  202. 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x38, 0x20, 0x40, 0x40,
  203. 0x40, 0x40, 0x43, 0x43, 0x43, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x43, 0x43, 0x40, 0x40,
  204. 0x40, 0x40, 0x43, 0x43, 0x43, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x41, 0x43, 0x43, 0x43, 0x40,
  205. 0x40, 0x40, 0x60, 0x30, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
  206. uint16_t startup_timer = 0;
  207. bool redrawn_splash = false;
  208. #ifdef BONGOCAT
  209. #define ANIM_FRAME_DURATION 75
  210. #define IDLE_FRAMES 5
  211. #define IDLE_TIMEOUT 750
  212. #define SLEEP_TIMEOUT 15000
  213. static const uint8_t bongofont[] PROGMEM = {
  214. 0xC1, 0xC1, 0xC2, 0x04, 0x08, 0x10,
  215. 0xC0, 0x38, 0x04, 0x03, 0x00, 0x00,
  216. 0xA0, 0x22, 0x24, 0x14, 0x12, 0x12,
  217. 0xA0, 0x21, 0x22, 0x12, 0x11, 0x11,
  218. 0x83, 0x7C, 0x41, 0x41, 0x40, 0x40,
  219. 0x82, 0x82, 0x84, 0x08, 0x10, 0x20,
  220. 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
  221. 0x80, 0x70, 0x19, 0x06, 0x00, 0x00,
  222. 0x80, 0x70, 0x0C, 0x03, 0x00, 0x00,
  223. 0x80, 0x00, 0x30, 0x30, 0x00, 0xC0,
  224. 0x80, 0x00, 0x30, 0x30, 0x00, 0x00,
  225. 0x49, 0x88, 0x08, 0x08, 0x08, 0x00,
  226. 0x44, 0x84, 0x04, 0x04, 0x00, 0x00,
  227. 0x40, 0x80, 0x00, 0x00, 0x00, 0x00,
  228. 0x40, 0x40, 0x20, 0x20, 0x20, 0x20,
  229. 0x3C, 0xC2, 0x01, 0x01, 0x02, 0x02,
  230. 0x35, 0x01, 0x8A, 0x7C, 0x00, 0x00,
  231. 0x20, 0x40, 0x80, 0x00, 0x00, 0x00,
  232. 0x20, 0x21, 0x22, 0x12, 0x11, 0x11,
  233. 0x20, 0x20, 0x10, 0x10, 0x10, 0x10,
  234. 0x1E, 0xE1, 0x00, 0x00, 0x01, 0x01,
  235. 0x1C, 0xE2, 0x01, 0x01, 0x02, 0x02,
  236. 0x18, 0x64, 0x82, 0x02, 0x02, 0x02,
  237. 0x18, 0x60, 0x80, 0x00, 0x00, 0x00,
  238. 0x18, 0x18, 0x1B, 0x03, 0x00, 0x40,
  239. 0x18, 0x06, 0x05, 0x98, 0x99, 0x84,
  240. 0x12, 0x0B, 0x08, 0x08, 0x08, 0x08,
  241. 0x11, 0x09, 0x08, 0x08, 0x08, 0x08,
  242. 0x10, 0x10, 0xD0, 0x11, 0x0F, 0x21,
  243. 0x10, 0x10, 0x10, 0x11, 0x0F, 0x01,
  244. 0x10, 0x08, 0x08, 0x04, 0x04, 0x04,
  245. 0x10, 0x08, 0x04, 0x02, 0x02, 0x04,
  246. 0x0C, 0x30, 0x40, 0x80, 0x00, 0x00,
  247. 0x0C, 0x0C, 0x0D, 0x01, 0x00, 0x40,
  248. 0x08, 0xE8, 0x08, 0x07, 0x10, 0x24,
  249. 0x08, 0x30, 0x40, 0x80, 0x00, 0x00,
  250. 0x08, 0x08, 0x08, 0x07, 0x00, 0x00,
  251. 0x08, 0x08, 0x04, 0x02, 0x02, 0x02,
  252. 0x08, 0x04, 0x02, 0x01, 0x01, 0x02,
  253. 0x05, 0x05, 0x09, 0x09, 0x10, 0x10,
  254. 0x04, 0x38, 0x40, 0x80, 0x00, 0x00,
  255. 0x04, 0x04, 0x08, 0x08, 0x10, 0x10,
  256. 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
  257. 0x04, 0x04, 0x02, 0x01, 0x00, 0x00,
  258. 0x02, 0x02, 0x81, 0x80, 0x80, 0x00,
  259. 0x02, 0x02, 0x04, 0x04, 0x08, 0x08,
  260. 0x02, 0x02, 0x02, 0x01, 0x01, 0x01,
  261. 0x02, 0x02, 0x01, 0x00, 0x00, 0x00,
  262. 0x01, 0xE1, 0x1A, 0x06, 0x09, 0x31,
  263. 0x01, 0x01, 0x02, 0x04, 0x08, 0x10,
  264. 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
  265. 0x00, 0x80, 0x80, 0x00, 0x00, 0x00,
  266. 0x00, 0x80, 0x40, 0x40, 0x20, 0x20,
  267. 0x00, 0x00, 0x80, 0x80, 0x40, 0x40,
  268. 0x00, 0x00, 0x60, 0x60, 0x00, 0x81,
  269. 0x00, 0x00, 0x01, 0x01, 0x00, 0x40,
  270. 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
  271. 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C,
  272. 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
  273. 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
  274. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
  275. static const uint8_t bongo_line_x[] = {51, 49, 48, 57};
  276. static const uint8_t bongo_line_y[] = {0, 8, 16, 24};
  277. static const uint8_t bongo_line_len[] = {5, 7, 8, 6};
  278. const uint8_t bongo_line_data[8][26] PROGMEM = {
  279. { //idle1
  280. 60, 52, 19, 30, 35,
  281. 22, 47, 51, 60, 9, 0, 17,
  282. 1, 57, 33, 3, 27, 41, 29, 50,
  283. 45, 36, 60, 60, 60, 60},
  284. { //idle2
  285. 60, 52, 19, 30, 35,
  286. 22, 47, 51, 60, 9, 0, 17,
  287. 1, 57, 33, 3, 27, 41, 29, 50,
  288. 45, 36, 60, 60, 60, 60},
  289. { //idle3
  290. 60, 53, 14, 31, 23,
  291. 15, 43, 60, 60, 54, 5, 13,
  292. 7, 56, 24, 2, 26, 39, 29, 50,
  293. 45, 36, 60, 60, 60, 60},
  294. { //idle4
  295. 6, 52, 19, 38, 32,
  296. 20, 47, 51, 60, 9, 0, 17,
  297. 8, 57, 33, 3, 27, 41, 29, 50,
  298. 45, 36, 60, 60, 60, 60},
  299. { //idle5
  300. 60, 52, 19, 37, 40,
  301. 21, 47, 51, 60, 9, 0, 17,
  302. 8, 57, 33, 3, 27, 41, 29, 50,
  303. 45, 36, 60, 60, 60, 60},
  304. { //prep
  305. 6, 52, 19, 38, 32,
  306. 20, 44, 51, 60, 10, 48, 16,
  307. 8, 25, 4, 18, 27, 42, 46, 50,
  308. 60, 60, 60, 60, 60, 60},
  309. { //tap1
  310. 6, 52, 19, 38, 32,
  311. 20, 44, 51, 60, 10, 49, 17,
  312. 8, 25, 4, 18, 27, 41, 28, 11,
  313. 60, 60, 60, 60, 58, 59},
  314. { //tap2
  315. 6, 52, 19, 38, 32,
  316. 20, 47, 51, 60, 10, 48, 16,
  317. 8, 60, 55, 3, 27, 42, 46, 50,
  318. 45, 34, 12, 60, 60, 60}
  319. };
  320. enum anin_states { sleep, idle, prep, tap };
  321. uint8_t anim_state = idle;
  322. uint32_t idle_timeout_timer = 0;
  323. uint32_t anim_timer = 0;
  324. uint8_t current_idle_frame = 0;
  325. uint8_t current_tap_frame = 6;
  326. uint8_t last_bongo_frame = 12;
  327. void write_bongochar_at_pixel_xy(uint8_t x, uint8_t y, uint8_t data, bool invert) {
  328. uint8_t i, j, temp;
  329. for (i = 0; i < 6 ; i++) { // 6 = font width
  330. temp = pgm_read_byte(&bongofont[data * 6]+i);
  331. for (j = 0; j < 8; j++) { // 8 = font height
  332. if (temp & 0x01) {
  333. oled_write_pixel(x + i, y + j, !invert);
  334. } else {
  335. oled_write_pixel(x + i, y + j, invert);
  336. }
  337. temp >>= 1;
  338. }
  339. }
  340. }
  341. bool is_key_down(void) {
  342. for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
  343. if (matrix_get_row(i) > 0) {
  344. return true;
  345. }
  346. }
  347. return false;
  348. }
  349. void eval_anim_state(void) {
  350. bool key_down;
  351. key_down = is_key_down();
  352. switch (anim_state) {
  353. case sleep:
  354. if(key_down) { anim_state = tap; }
  355. break;
  356. case idle:
  357. if(key_down) { anim_state = tap; }
  358. else if (timer_elapsed32(idle_timeout_timer) >= SLEEP_TIMEOUT) //prep to idle
  359. {
  360. anim_state = sleep;
  361. current_idle_frame = 0;
  362. }
  363. break;
  364. case prep:
  365. if(key_down) { anim_state = tap; }
  366. else if (timer_elapsed32(idle_timeout_timer) >= IDLE_TIMEOUT) //prep to idle
  367. {
  368. anim_state = idle;
  369. current_idle_frame = 0;
  370. }
  371. break;
  372. case tap:
  373. if (!key_down)
  374. {
  375. anim_state = prep;
  376. idle_timeout_timer = timer_read32();
  377. }
  378. break;
  379. default:
  380. break;
  381. }
  382. }
  383. void draw_bongo_table(void) {
  384. //draws the table edge for bongocat, this edge doesn't change during the animation
  385. uint8_t i;
  386. uint8_t y = 31;
  387. uint8_t j = 0;
  388. for (i = 17; i < 57; i++) {
  389. oled_write_pixel(i, y, true); //every five horizontal pixels, move up one pixel to make a diagonal line
  390. if (j == 4) {
  391. --y;
  392. j=0;
  393. } else {
  394. j++;
  395. }
  396. }
  397. y=15;
  398. j=0;
  399. for (i = 91; i < 128; i++) {
  400. oled_write_pixel(i, y, true); //every four horizontal pixels, move up one pixel to make a diagonal line
  401. if (j == 3) {
  402. --y;
  403. j=0;
  404. } else {
  405. j++;
  406. }
  407. }
  408. }
  409. void draw_bongocat_frame(int framenumber) {
  410. //only redraw if the animation frame has changed
  411. if (framenumber != last_bongo_frame) {
  412. last_bongo_frame = framenumber;
  413. uint8_t i, j, current_bongochar = 0;
  414. for (i = 0; i < 4; i++) {
  415. for (j = 0; j < bongo_line_len[i]; j++) {
  416. write_bongochar_at_pixel_xy(bongo_line_x[i] + j*6, bongo_line_y[i], pgm_read_byte(&bongo_line_data[framenumber][current_bongochar]), false);
  417. current_bongochar++;
  418. }
  419. }
  420. }
  421. }
  422. bool is_new_tap(void) {
  423. static matrix_row_t old_matrix[] = { 0, 0, 0, 0, 0, 0 };
  424. bool new_tap = false;
  425. for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
  426. if (matrix_get_row(i) > old_matrix[i]) { // more 1's detected, there was a new tap
  427. new_tap = true;
  428. }
  429. old_matrix[i] = matrix_get_row(i);
  430. }
  431. return new_tap;
  432. }
  433. void draw_bongocat(void) {
  434. static bool already_tapped = false;
  435. if (is_new_tap()) {
  436. already_tapped = false;
  437. };
  438. eval_anim_state();
  439. switch (anim_state) {
  440. case sleep:
  441. draw_bongocat_frame(4);
  442. break;
  443. case idle:
  444. draw_bongocat_frame(4 - current_idle_frame);
  445. if (timer_elapsed32(anim_timer) > ANIM_FRAME_DURATION) {
  446. current_idle_frame = (current_idle_frame + 1) % 5;
  447. anim_timer = timer_read32();
  448. }
  449. break;
  450. case prep:
  451. draw_bongocat_frame(5);
  452. already_tapped = false;
  453. break;
  454. case tap:
  455. draw_bongocat_frame(current_tap_frame);
  456. if (already_tapped == false) {
  457. if (current_tap_frame == 6) {
  458. current_tap_frame = 7;
  459. }
  460. else {
  461. current_tap_frame = 6;
  462. }
  463. }
  464. already_tapped = true;
  465. break;
  466. default:
  467. draw_bongocat_frame(4);
  468. already_tapped = false;
  469. break;
  470. }
  471. }
  472. #endif //BONGOCAT
  473. void draw_splash(void) {
  474. uint8_t i, j, k, temp;
  475. uint16_t count;
  476. count = 0;
  477. temp = pgm_read_byte(&splash[count]);
  478. for (i = 0; i < 4 ; i++) {
  479. for (j = 0; j < 128; j++) {
  480. for (k = 0; k < 8; k++) {
  481. if (temp & 0x01) {
  482. oled_write_pixel(j, (i * 8) + k, true);
  483. } else {
  484. oled_write_pixel(j, (i * 8) + k, false);
  485. }
  486. temp >>= 1;
  487. }
  488. temp = pgm_read_byte(&splash[++count]);
  489. }
  490. }
  491. }
  492. void draw_media_arrow(uint8_t x, uint8_t y, bool fwd) {
  493. draw_line_v(x, y, 7, true);
  494. draw_line_v(x+4, y, 7, true);
  495. draw_line_v(x+2, y+2, 3, true);
  496. if (fwd) {
  497. draw_line_v(x+1, y+1, 5, true);
  498. oled_write_pixel(x+3, y+3, true);
  499. } else {
  500. draw_line_v(x+3, y+1, 5, true);
  501. oled_write_pixel(x+1, y+3, true);
  502. }
  503. }
  504. void draw_enc_mode(void){
  505. write_chars_at_pixel_xy(enc_mode_str_startpos[user_config.enc_mode], ENC_DISPLAY_Y + 2, enc_mode_str[user_config.enc_mode], false);
  506. if (user_config.enc_mode == ENC_MEDIA) {
  507. draw_media_arrow(enc_mode_str_startpos[user_config.enc_mode] - 16, ENC_DISPLAY_Y + 2, false);
  508. draw_media_arrow(enc_mode_str_startpos[user_config.enc_mode] + 88, ENC_DISPLAY_Y + 2, true);
  509. }
  510. }
  511. void draw_keyboard_locks(void) {
  512. led_t led_state = host_keyboard_led_state();
  513. draw_text_rectangle(CAPSLOCK_DISPLAY_X, CAPSLOCK_DISPLAY_Y, 5 + (3 * 6), "CAP", led_state.caps_lock);
  514. draw_text_rectangle(NUMLOCK_DISPLAY_X, NUMLOCK_DISPLAY_Y, 5 + (3 * 6), "NUM", led_state.num_lock);
  515. }
  516. /* Encoder handling functions */
  517. __attribute__((weak)) void set_custom_encoder_mode_user(bool custom_encoder_mode) {}
  518. void update_custom_encoder_mode_user(void) {
  519. #ifdef BONGOCAT
  520. set_custom_encoder_mode_user((user_config.enc_mode == ENC_CUSTOM) || (user_config.enc_mode == ENC_SPLASH) || (user_config.enc_mode == ENC_BONGO));
  521. #else
  522. set_custom_encoder_mode_user((user_config.enc_mode == ENC_CUSTOM) || (user_config.enc_mode == ENC_SPLASH));
  523. #endif
  524. }
  525. void update_kb_eeprom(void) {
  526. eeconfig_update_kb(user_config.raw);
  527. }
  528. void update_breathing(void);
  529. void matrix_init_kb(void) {
  530. user_config.raw = eeconfig_read_kb();
  531. if (user_config.enc_mode == 0xFF) { //EEPROM was cleared
  532. user_config.enc_mode = 0;
  533. user_config.oled_is_on = true;
  534. user_config.breathingperiod = 1;
  535. update_kb_eeprom();
  536. }
  537. startup_delay = true;
  538. update_custom_encoder_mode_user();
  539. matrix_init_user();
  540. }
  541. void handle_encoder_switch_process_record(keyrecord_t *record) {
  542. static uint32_t encoder_press_timer = 0;
  543. if (record->event.pressed) {
  544. if (!user_config.oled_is_on) {
  545. oled_on();
  546. user_config.oled_is_on = true;
  547. OLED_awakened = true;
  548. OLED_redraw = true;
  549. update_kb_eeprom();
  550. }
  551. encoder_press_timer = timer_read32();
  552. } else {
  553. if (OLED_awakened == true) {
  554. OLED_awakened = false;
  555. } else {
  556. if (timer_elapsed32(encoder_press_timer) < 300) {
  557. if (get_mods() & MOD_MASK_SHIFT) {
  558. user_config.enc_mode = (user_config.enc_mode + (num_enc_modes- 1)) % num_enc_modes;
  559. } else {
  560. user_config.enc_mode = (user_config.enc_mode + 1) % num_enc_modes;
  561. }
  562. OLED_redraw = true;
  563. update_custom_encoder_mode_user();
  564. update_kb_eeprom();
  565. } else {
  566. OLED_redraw = false;
  567. oled_clear();
  568. user_config.oled_is_on = false;
  569. update_kb_eeprom();
  570. }
  571. }
  572. }
  573. }
  574. bool process_record_kb(uint16_t keycode, keyrecord_t *record) {
  575. if (record->event.key.row == ENCODER_MATRIX_ROW && record->event.key.col == ENCODER_MATRIX_COL){
  576. handle_encoder_switch_process_record(record);
  577. }
  578. return process_record_user(keycode, record);
  579. }
  580. void update_breathing(void) {
  581. if (user_config.breathingperiod == 1) {
  582. breathing_disable();
  583. }
  584. else {
  585. breathing_period_set(user_config.breathingperiod);
  586. breathing_enable();
  587. }
  588. update_kb_eeprom();
  589. }
  590. void backlight_breath_change(bool increase) { //increase period or decrease period
  591. if ((increase) && (user_config.breathingperiod < 15)) {
  592. user_config.breathingperiod++;
  593. update_breathing();
  594. }
  595. if (!increase) {
  596. if (user_config.breathingperiod > 2) {
  597. user_config.breathingperiod--;
  598. update_breathing();
  599. }
  600. else {
  601. user_config.breathingperiod = 1;
  602. update_breathing();
  603. }
  604. }
  605. }
  606. bool encoder_update_kb(uint8_t index, bool clockwise) {
  607. if (!encoder_update_user(index, clockwise)) return false;
  608. switch (user_config.enc_mode) {
  609. case ENC_RGB_MODE :
  610. if (clockwise) {
  611. rgblight_step();
  612. } else {
  613. rgblight_step_reverse();
  614. }
  615. break;
  616. case ENC_RGB_BRIGHT :
  617. if (clockwise) {
  618. rgblight_increase_val();
  619. } else {
  620. rgblight_decrease_val();
  621. }
  622. break;
  623. case ENC_BL_BRIGHT :
  624. if (clockwise) {
  625. backlight_increase();
  626. } else {
  627. backlight_decrease();
  628. }
  629. break;
  630. case ENC_BL_BREATH :
  631. backlight_breath_change(clockwise);
  632. break;
  633. case ENC_RGB_COLOR :
  634. if (clockwise) {
  635. rgblight_increase_hue();
  636. } else {
  637. rgblight_decrease_hue();
  638. }
  639. break;
  640. default:
  641. if (clockwise) {
  642. tap_code(enc_cw[user_config.enc_mode]);
  643. } else {
  644. tap_code(enc_ccw[user_config.enc_mode]);
  645. }
  646. }
  647. return true;
  648. }
  649. void housekeeping_task_kb(void) {
  650. led_t current_led_state = host_keyboard_led_state();
  651. uint8_t current_layer = get_highest_layer(layer_state);
  652. if (startup_delay) {
  653. startup_timer = timer_read();
  654. startup_delay = false;
  655. startup_complete = false;
  656. starting_up = true;
  657. OLED_redraw = false;
  658. }
  659. else if (starting_up) {
  660. if (timer_elapsed(startup_timer) >= 200) {
  661. update_breathing();
  662. startup_complete = true;
  663. starting_up = false;
  664. if (user_config.oled_is_on) {
  665. oled_on();
  666. OLED_redraw = true;
  667. } else
  668. {
  669. oled_clear();
  670. user_config.oled_is_on = false;
  671. }
  672. }
  673. }
  674. if (startup_complete) {
  675. if (user_config.enc_mode == ENC_SPLASH) {
  676. if (user_config.oled_is_on && OLED_redraw) {
  677. draw_splash();
  678. }
  679. }
  680. #ifdef BONGOCAT
  681. else if (user_config.enc_mode == ENC_BONGO) {
  682. if (user_config.oled_is_on) {
  683. if (OLED_redraw) {
  684. oled_clear();
  685. last_bongo_frame = 12; //force a redraw
  686. draw_bongo_table();
  687. OLED_redraw = false;
  688. }
  689. draw_bongocat();
  690. }
  691. }
  692. #endif //BONGOCAT
  693. else {
  694. if (user_config.oled_is_on && (
  695. OLED_redraw
  696. || (prev_layer != current_layer)
  697. || (prev_capslock != current_led_state.caps_lock)
  698. || (prev_numlock != current_led_state.num_lock))) {
  699. prev_layer = current_layer;
  700. prev_capslock = current_led_state.caps_lock;
  701. prev_numlock = current_led_state.num_lock;
  702. oled_clear();
  703. draw_keyboard_layer();
  704. draw_keyboard_locks();
  705. draw_enc_mode();
  706. }
  707. }
  708. OLED_redraw = false;
  709. }
  710. }