macrocat.c (14383B)
1 // Copyright 2022 catmunch (@catmunch) 2 // SPDX-License-Identifier: GPL-2.0-or-later 3 4 #include "quantum.h" 5 6 static bool encoder_pressed = 0; 7 static bool encoder_switched_layer = 0; 8 static uint32_t encoder_last_release_time = 0; 9 static uint32_t encoder_press_combo = 0; 10 static uint8_t current_layer = 0; 11 12 #ifdef OLED_ENABLE 13 static const char PROGMEM bongo_release[] = { 14 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,128,192,192, 96, 96, 48, 48, 24, 12, 6, 14, 60,112, 96,224,192,192,192,192,128,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15 0,192,192,128,128,128,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,192,240,124, 12, 12, 12, 12, 24,120,108, 14, 7, 3, 1, 0,128,192,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 3, 3, 7, 6, 14, 12, 28, 24, 48, 48, 24, 24, 12,252,252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16 0, 0, 1, 1, 1, 1, 3, 3, 3, 3, 7, 6, 6, 6, 6, 12, 12, 15, 15, 24, 24, 24, 24, 48, 48, 48, 48,112, 96, 96, 96,224,193,193,193,192,131,134,134,134, 12, 12, 0, 0, 0, 0, 0, 48, 56, 16,240,252, 12, 6,134, 6, 12, 60, 48, 32, 0, 0, 48,126,239,131, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 3, 3, 3, 3, 3, 6, 6, 6, 6, 12, 12, 15, 15, 24, 24, 24, 24, 56, 48, 48, 48,112, 96, 96, 96,225,207,254,248,192,128,128,128,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18 0, 19 }; 20 static const char PROGMEM bongo_press_r[] = { 21 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,128,192,192, 96, 96, 48, 48, 24, 12, 6, 14, 60,112, 96,224,192,192,192,192,128,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22 0,192,192,128,128,128,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,192,240,124, 12, 12, 12, 12, 24,120,108, 14, 7, 3, 1, 0,128,192,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 3, 3, 7, 6, 14, 12, 28, 24, 48, 48, 24, 24, 12,252,252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23 0, 0, 1, 1, 1, 1, 3, 3, 3, 3, 7, 6, 6, 6, 6, 12, 12, 15, 15, 24, 24, 24, 24, 48, 48, 48, 48,112, 96, 96, 96,224,193,193,193,192,131,134,134,134, 12, 12, 0, 0, 0, 0, 0, 48, 56, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48,126,239,131, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 3, 3, 3, 3, 3, 6, 6, 22,126,111,227,192,224, 96, 96, 96, 96,112, 48, 48, 48,112, 96, 96, 96,225,207,254,248,192,128,128,128,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25 0, 26 }; 27 static const char PROGMEM bongo_press_l[] = { 28 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,128,192,192, 96, 96, 48, 48, 24, 12, 6, 14, 60,112, 96,224,192,192,192,192,128,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29 0,192,192,128,128,128,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,192, 96, 48, 24, 12, 14, 7, 3, 1, 0,128,192,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 3, 3, 7, 6, 14, 12, 28, 24, 48, 48, 24, 24, 12,252,252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30 0, 0, 1, 1, 1, 1, 3, 3, 3, 3, 7, 6, 6, 6, 6, 12, 12,124,252,206,131,129,192,192,192,192,224, 96, 96, 96, 96,224,193,193,193,192,131,134,134,134, 12, 12, 0, 0, 0, 0, 0, 48, 56, 16,240,252, 12, 6,134, 6, 12, 60, 48, 32, 0, 0, 48,126,239,131, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 3, 3, 3, 3, 3, 6, 6, 6, 6, 12, 12, 15, 15, 24, 24, 24, 24, 56, 48, 48, 48,112, 96, 96, 96,225,207,254,248,192,128,128,128,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32 0, 33 }; 34 static const char PROGMEM bongo_press_lr[] = { 35 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,128,192,192, 96, 96, 48, 48, 24, 12, 6, 14, 60,112, 96,224,192,192,192,192,128,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36 0,192,192,128,128,128,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,192, 96, 48, 24, 12, 14, 7, 3, 1, 0,128,192,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 3, 3, 7, 6, 14, 12, 28, 24, 48, 48, 24, 24, 12,252,252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37 0, 0, 1, 1, 1, 1, 3, 3, 3, 3, 7, 6, 6, 6, 6, 12, 12,124,252,206,131,129,192,192,192,192,224, 96, 96, 96, 96,224,193,193,193,192,131,134,134,134, 12, 12, 0, 0, 0, 0, 0, 48, 56, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48,126,239,131, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 3, 3, 3, 3, 3, 6, 6, 22,126,111,227,192,224, 96, 96, 96, 96,112, 48, 48, 48,112, 96, 96, 96,225,207,254,248,192,128,128,128,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39 0, 40 }; 41 static const char PROGMEM layer[][116] = { 42 [0] = { 43 248, 0, 0, 0, 0, 0, 0,160,160,192, 0, 0, 96,128,128,128,224, 0,192,160,160,160,192, 0,224, 64, 32, 32, 64, 44 3, 2, 2, 2, 2, 0, 1, 2, 2, 3, 2,128,130,132,132,132,131, 0, 1, 2, 2, 2, 0, 0, 3, 0, 0, 0, 0, 45 0, 0, 0, 0, 0, 0, 0, 0, 0,254,254,129,129, 97, 97, 25, 25,254,254, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 25, 25, 24, 24, 24, 24, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47 }, 48 [1] = { 49 248, 0, 0, 0, 0, 0, 0,160,160,192, 0, 0, 96,128,128,128,224, 0,192,160,160,160,192, 0,224, 64, 32, 32, 64, 50 3, 2, 2, 2, 2, 0, 1, 2, 2, 3, 2, 0, 2,132,132, 4, 3, 0, 1, 2, 2, 2, 0, 0, 3, 0, 0, 0, 0, 51 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6,255,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 24, 31, 31, 24, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53 }, 54 [2] = { 55 248, 0, 0, 0, 0, 0, 0,160,160,192, 0, 0, 96,128,128,128,224, 0,192,160,160,160,192, 0,224, 64, 32, 32, 64, 56 3, 2, 2, 2, 2, 0, 1, 2, 2, 3, 2,128,130,132,132,132,131, 0, 1, 2, 2, 2, 0, 0, 3, 0, 0, 0, 0, 57 0, 0, 0, 0, 0, 0, 0, 0, 0,134,134, 97, 97, 97, 97, 97, 97, 30, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 31, 24, 24, 24, 24, 24, 24, 24, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59 }, 60 [3] = { 61 248, 0, 0, 0, 0, 0, 0,160,160,192, 0, 0, 96,128,128,128,224, 0,192,160,160,160,192, 0,224, 64, 32, 32, 64, 62 3, 2, 2, 2, 2, 0, 1, 2, 2,131,130,128,130,132,132,132,131,128,129, 2, 2, 2, 0, 0, 3, 0, 0, 0, 0, 63 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 97, 97,121,121,135,135, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 24, 24, 24, 24, 24, 24, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65 } 66 }; 67 static uint8_t key_pressed_l = 0; 68 static uint8_t key_pressed_r = 0; 69 oled_rotation_t oled_init_kb(oled_rotation_t rotation) { 70 return OLED_ROTATION_180; 71 } 72 bool oled_task_kb(void) { 73 if (!oled_task_user()) { 74 return false; 75 } 76 77 char buffer[512]; 78 if (key_pressed_l && key_pressed_r) 79 memcpy_P(buffer, bongo_press_lr, 512); 80 else if (key_pressed_l) 81 memcpy_P(buffer, bongo_press_l, 512); 82 else if (key_pressed_r) 83 memcpy_P(buffer, bongo_press_r, 512); 84 else 85 memcpy_P(buffer, bongo_release, 512); 86 int highest_layer = 0; 87 for(int i=3;i>=0;--i){ 88 if (IS_LAYER_ON(i)) { 89 highest_layer = i; 90 break; 91 } 92 } 93 // Apply the layer info (4*29) 94 for(int i=0;i<4;i++){ 95 for(int j=0;j<29;j++){ 96 buffer[i*128+85+j] = pgm_read_byte_near(layer[highest_layer]+i*29+j); 97 } 98 } 99 oled_write_raw(buffer, 512); 100 return false; 101 } 102 bool process_record_kb(uint16_t keycode, keyrecord_t *record) { 103 if (!process_record_user(keycode, record)) { 104 return false; 105 } 106 if (record->event.pressed) { 107 if (record->event.key.col <= 1) 108 key_pressed_l++; 109 else 110 key_pressed_r++; 111 } else { 112 if (record->event.key.col <= 1) 113 key_pressed_l--; 114 else 115 key_pressed_r--; 116 } 117 return true; 118 } 119 #endif 120 void encoder_single_click(void) { 121 tap_code(KC_MPLY); 122 } 123 void encoder_double_click(void) { 124 tap_code(KC_MNXT); 125 } 126 void encoder_triple_click(void) { 127 tap_code(KC_MPRV); 128 } 129 void matrix_init_kb(void) { 130 matrix_init_user(); 131 132 gpio_set_pin_input_high(ENCODER_SWITCH); 133 } 134 void matrix_scan_kb(void) { 135 matrix_scan_user(); 136 if (gpio_read_pin(ENCODER_SWITCH)) { 137 if (encoder_pressed) { // release switch 138 encoder_pressed = 0; 139 encoder_press_combo += 1; 140 encoder_last_release_time = timer_read32(); 141 } 142 if (encoder_press_combo && timer_elapsed(encoder_last_release_time) > 300) { 143 // combo timeout 144 if (encoder_switched_layer) { // switch layer 145 encoder_switched_layer = 0; 146 } else { // click 147 switch (encoder_press_combo) { 148 case 1: 149 encoder_single_click(); 150 break; 151 case 2: 152 encoder_double_click(); 153 break; 154 default: 155 encoder_triple_click(); 156 } 157 } 158 encoder_press_combo = 0; 159 encoder_last_release_time = 0; 160 } 161 } else { 162 if (!encoder_pressed) { // press switch 163 encoder_pressed = 1; 164 } 165 } 166 } 167 bool encoder_update_kb(uint8_t index, bool clockwise) { 168 if (!encoder_update_user(index, clockwise)) { 169 return false; 170 } 171 if (clockwise) { 172 if (encoder_pressed) { 173 if (current_layer < 3) { 174 current_layer += 1; 175 layer_move(current_layer); 176 } 177 encoder_switched_layer = 1; 178 } else { 179 tap_code(KC_VOLU); 180 } 181 } else { 182 if (encoder_pressed) { 183 if (current_layer > 0) { 184 current_layer -= 1; 185 layer_move(current_layer); 186 } 187 encoder_switched_layer = 1; 188 } else { 189 tap_code(KC_VOLD); 190 } 191 } 192 return false; 193 }