puckbuddy.c (10680B)
1 // Copyright 2022 Kyle McCreery (@kylemccreery) 2 // SPDX-License-Identifier: GPL-2.0-or-later 3 4 #include "puckbuddy.h" 5 6 #ifndef GLIDEPOINT_DPI_OPTIONS 7 # define GLIDEPOINT_DPI_OPTIONS \ 8 { 400, 800, 1200, 1600, 2000, 2400, 2800, 3200, 3600, 4000 } 9 # ifndef GLIDEPOINT_DPI_DEFAULT 10 # define GLIDEPOINT_DPI_DEFAULT 1 11 # endif 12 #endif 13 #ifndef GLIDEPOINT_DPI_DEFAULT 14 # define GLIDEPOINT_DPI_DEFAULT 1 15 #endif 16 17 keyboard_config_t keyboard_config; 18 uint16_t dpi_array[] = GLIDEPOINT_DPI_OPTIONS; 19 #define DPI_OPTION_SIZE ARRAY_SIZE(dpi_array) 20 21 void board_init(void) { 22 // B9 is configured as I2C1_SDA in the board file; that function must be 23 // disabled before using B7 as I2C1_SDA. 24 gpio_set_pin_input_high(B9); 25 } 26 27 #ifdef DYNAMIC_TAPPING_TERM_ENABLE 28 void tap_modify(int change_value, bool tap_status) { 29 if (keyboard_config.dt_term_config < 0) { 30 keyboard_config.dt_term_config *= -1; 31 } 32 33 keyboard_config.dt_term_config += change_value; 34 35 if (tap_status == false ) { 36 keyboard_config.dt_term_config *= -1; 37 g_tapping_term = 0; 38 } else { 39 g_tapping_term = keyboard_config.dt_term_config; 40 } 41 eeconfig_update_kb(keyboard_config.raw); 42 } 43 44 void tap_toggle(void) { 45 keyboard_config.dt_term_config *= -1; 46 if (keyboard_config.dt_term_config > 0) { 47 g_tapping_term = keyboard_config.dt_term_config; 48 } else { 49 g_tapping_term = 0; 50 } 51 eeconfig_update_kb(keyboard_config.raw); 52 } 53 #endif 54 55 #ifdef DIP_SWITCH_ENABLE 56 bool dip_switch_update_kb(uint8_t index, bool active) { 57 if (!dip_switch_update_user(index, active)) { return false; } 58 switch (index) { 59 case 0: 60 if(active) { tap_code(KC_CAPS_LOCK); } 61 break; 62 break; 63 } 64 return true; 65 } 66 #endif 67 68 #ifdef ENCODER_ENABLE 69 bool encoder_update_kb(uint8_t index, bool clockwise) { 70 if (!encoder_update_user(index, clockwise)) { return false; } 71 switch (index) { 72 case 0: 73 if (clockwise) { 74 tap_code(KC_VOLU); 75 } else { 76 tap_code(KC_VOLD); 77 } 78 break; 79 case 1: 80 if (clockwise) { 81 tap_code(KC_PGUP); 82 } else { 83 tap_code(KC_PGDN); 84 } 85 break; 86 } 87 return true; 88 } 89 #endif 90 91 #ifdef OLED_ENABLE // OLED Functionality 92 oled_rotation_t oled_init_user(oled_rotation_t rotation) { 93 return OLED_ROTATION_180; // flips the display 180 degrees 94 } 95 96 bool clear_screen = true; // used to manage singular screen clears to prevent display glitch 97 bool clear_screen_art = true; // used to manage singular screen clears to prevent display glitch 98 static void render_name(void) { // Render Puckbuddy "Get Puck'd" text 99 static const char PROGMEM name_1[] = {0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0xB6, 0xB6, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, 0x00}; 100 static const char PROGMEM name_2[] = {0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xB6, 0xB6, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0x00}; 101 static const char PROGMEM name_3[] = {0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xB6, 0xB6, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0x00}; 102 oled_set_cursor(0,0); 103 oled_write_P(name_1, false); 104 oled_set_cursor(0,1); 105 oled_write_P(name_2, false); 106 oled_set_cursor(0,2); 107 oled_write_P(name_3, false); 108 } 109 110 static void render_logo(void) { // Render MechWild "MW" Logo 111 static const char PROGMEM logo_1[] = {0x97, 0x98, 0x99, 0x9A,0x00}; 112 static const char PROGMEM logo_2[] = {0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0x00}; 113 static const char PROGMEM logo_3[] = {0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xB6, 0x00}; 114 static const char PROGMEM logo_4[] = {0xB6, 0xB6, 0xB6, 0x9B, 0x9C, 0x9D, 0x9E, 0x00}; 115 oled_set_cursor(0,0); 116 oled_write_P(logo_1, false); 117 oled_set_cursor(0,1); 118 oled_write_P(logo_2, false); 119 oled_set_cursor(0,2); 120 oled_write_P(logo_3, false); 121 oled_set_cursor(0,3); 122 oled_write_P(logo_4, false); 123 } 124 125 bool oled_task_kb(void) { 126 if(!oled_task_user()) { 127 return false; 128 } 129 led_t led_state = host_keyboard_led_state(); 130 if ( !led_state.num_lock && !led_state.caps_lock && !led_state.scroll_lock && get_highest_layer(layer_state) == 0 ) { 131 if (clear_screen_art == true) { 132 oled_clear(); 133 oled_render(); 134 clear_screen_art = false; 135 } 136 render_name(); 137 oled_set_cursor(0,3); 138 #ifdef POINTING_DEVICE_ENABLE 139 oled_write_P(PSTR(" DPI:"), false); 140 oled_write(get_u16_str(dpi_array[keyboard_config.dpi_config], ' '), false); 141 #endif 142 #ifdef DYNAMIC_TAPPING_TERM_ENABLE // only display tap info if it is being configured dynamically 143 oled_write_P(PSTR(" TAP:"), false); 144 if (keyboard_config.dt_term_config < 0) { 145 oled_write_P(PSTR("Off "), false); 146 } else { 147 oled_write(get_u16_str(g_tapping_term, ' '), false); 148 } 149 #endif 150 clear_screen = true; 151 } else { 152 if (clear_screen == true) { 153 oled_clear(); 154 oled_render(); 155 clear_screen = false; 156 } 157 render_logo(); 158 oled_set_cursor(8,1); 159 switch (get_highest_layer(layer_state)) { 160 case 0: 161 oled_write_P(PSTR("Layer 0"), false); 162 break; 163 case 1: 164 oled_write_P(PSTR("Layer 1"), false); 165 break; 166 case 2: 167 oled_write_P(PSTR("Layer 2"), false); 168 break; 169 case 3: 170 oled_write_P(PSTR("Layer 3"), false); 171 break; 172 default: 173 oled_write_P(PSTR("Layer ?"), false); // Should never display, here as a catchall 174 } 175 led_t led_state = host_keyboard_led_state(); 176 oled_set_cursor(8,0); 177 oled_write_P(led_state.num_lock ? PSTR("NUM ") : PSTR(" "), false); 178 oled_write_P(led_state.caps_lock ? PSTR("CAP ") : PSTR(" "), false); 179 oled_write_P(led_state.scroll_lock ? PSTR("SCR") : PSTR(" "), false); 180 #ifdef POINTING_DEVICE_ENABLE 181 oled_set_cursor(8,2); 182 oled_write_P(PSTR("DPI:"), false); 183 oled_write(get_u16_str(dpi_array[keyboard_config.dpi_config], ' '), false); 184 #endif 185 #ifdef DYNAMIC_TAPPING_TERM_ENABLE // only display tap info if it is being configured dynamically 186 oled_set_cursor(8,3); 187 oled_write_P(PSTR("TAP:"), false); 188 if (keyboard_config.dt_term_config < 0) { 189 oled_write_P(PSTR("Off "), false); 190 } else { 191 oled_write(get_u16_str(g_tapping_term, ' '), false); 192 } 193 #endif 194 clear_screen_art = true; 195 } 196 return true; 197 } 198 #endif 199 200 bool process_record_kb(uint16_t keycode, keyrecord_t* record) { 201 switch(keycode) { 202 #ifdef POINTING_DEVICE_ENABLE 203 case DPI_UP: 204 if (record->event.pressed) { 205 keyboard_config.dpi_config = (keyboard_config.dpi_config + 1) % DPI_OPTION_SIZE; 206 eeconfig_update_kb(keyboard_config.raw); 207 pointing_device_set_cpi(dpi_array[keyboard_config.dpi_config]); 208 } 209 return false; 210 case DPI_DN: 211 if (record->event.pressed) { 212 if (keyboard_config.dpi_config > 0) { 213 keyboard_config.dpi_config = (keyboard_config.dpi_config - 1) % DPI_OPTION_SIZE; 214 } else { 215 keyboard_config.dpi_config = DPI_OPTION_SIZE - 1; 216 } 217 eeconfig_update_kb(keyboard_config.raw); 218 pointing_device_set_cpi(dpi_array[keyboard_config.dpi_config]); 219 } 220 return false; 221 case DPI_FINE: 222 if (record->event.pressed) { 223 pointing_device_set_cpi(dpi_array[0]); 224 } else { 225 pointing_device_set_cpi(dpi_array[keyboard_config.dpi_config]); 226 } 227 return false; 228 #endif 229 #ifdef DYNAMIC_TAPPING_TERM_ENABLE // only include tap info keycodes if it is being configured dynamically 230 case TAP_UP: 231 if (record->event.pressed) { 232 tap_modify(DYNAMIC_TAPPING_TERM_INCREMENT, true); 233 } 234 return false; 235 case TAP_DN: 236 if (record->event.pressed) { 237 if (keyboard_config.dt_term_config > 0) { 238 tap_modify(-1 * DYNAMIC_TAPPING_TERM_INCREMENT, true); 239 } 240 } 241 return false; 242 case TAP_ON: 243 if (record->event.pressed) { 244 tap_modify(0, true); 245 } 246 return false; 247 case TAP_OFF: 248 if (record->event.pressed) { 249 tap_modify(0, false); 250 } 251 return false; 252 case TAP_TOG: 253 if (record->event.pressed) { 254 tap_toggle(); 255 } 256 return false; 257 #endif 258 } 259 return process_record_user(keycode, record); 260 } 261 262 void pointing_device_init_kb(void) { 263 #ifdef POINTING_DEVICE_ENABLE 264 pointing_device_set_cpi(dpi_array[keyboard_config.dpi_config]); 265 #endif 266 } 267 268 void eeconfig_init_kb(void) { 269 #ifdef POINTING_DEVICE_ENABLE 270 keyboard_config.dpi_config = GLIDEPOINT_DPI_DEFAULT; 271 #endif 272 #ifdef DYNAMIC_TAPPING_TERM_ENABLE // only set tap term from eeprom if it is being configured dynamically 273 keyboard_config.dt_term_config = TAPPING_TERM; 274 #endif 275 eeconfig_update_kb(keyboard_config.raw); 276 eeconfig_init_user(); 277 } 278 279 void matrix_init_kb(void) { 280 // is safe to just read DPI setting since matrix init 281 // comes before pointing device init. 282 keyboard_config.raw = eeconfig_read_kb(); 283 #ifdef POINTING_DEVICE_ENABLE 284 if (keyboard_config.dpi_config > DPI_OPTION_SIZE) { 285 eeconfig_init_kb(); 286 } 287 #endif 288 matrix_init_user(); 289 } 290 291 void keyboard_post_init_kb(void) { 292 #ifdef POINTING_DEVICE_ENABLE 293 pointing_device_set_cpi(dpi_array[keyboard_config.dpi_config]); 294 #endif 295 #ifdef RGBLIGHT_ENABLE 296 rgblight_toggle_noeeprom(); //double toggle post init removes the weirdness with rgb strips having a yellow first LED 297 rgblight_toggle_noeeprom(); 298 #endif 299 #ifdef DYNAMIC_TAPPING_TERM_ENABLE 300 tap_toggle(); // Need it to reevaluate this setting after initiating so that it is current after init 301 tap_toggle(); 302 #endif 303 keyboard_post_init_user(); 304 #ifdef OLED_ENABLE // purposefully after user post init to allow the RGB to startup first 305 wait_ms(200); // Avoids a startup issue where the oled renders and then turns off with blackpill 306 oled_on(); 307 #endif 308 }