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