qmk_firmware

QMK firmware for my keyboards (Corne, Sweep Ferris) and trackball (Ploopy Adept)
Log | Files | Refs | Submodules | LICENSE

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 }