qmk_firmware

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

ploopyco.c (7420B)


      1 /* Copyright 2020 Christopher Courtney, aka Drashna Jael're  (@drashna) <drashna@live.com>
      2  * Copyright 2019 Sunjun Kim
      3  * Copyright 2020 Ploopy Corporation
      4  *
      5  * This program is free software: you can redistribute it and/or modify
      6  * it under the terms of the GNU General Public License as published by
      7  * the Free Software Foundation, either version 2 of the License, or
      8  * (at your option) any later version.
      9  *
     10  * This program is distributed in the hope that it will be useful,
     11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13  * GNU General Public License for more details.
     14  *
     15  * You should have received a copy of the GNU General Public License
     16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
     17  */
     18 
     19 #include "ploopyco.h"
     20 #include "analog.h"
     21 #include "opt_encoder.h"
     22 
     23 // for legacy support
     24 #if defined(OPT_DEBOUNCE) && !defined(PLOOPY_SCROLL_DEBOUNCE)
     25 #    define PLOOPY_SCROLL_DEBOUNCE OPT_DEBOUNCE
     26 #endif
     27 #if defined(SCROLL_BUTT_DEBOUNCE) && !defined(PLOOPY_SCROLL_BUTTON_DEBOUNCE)
     28 #    define PLOOPY_SCROLL_BUTTON_DEBOUNCE SCROLL_BUTT_DEBOUNCE
     29 #endif
     30 
     31 #ifndef PLOOPY_SCROLL_DEBOUNCE
     32 #    define PLOOPY_SCROLL_DEBOUNCE 5
     33 #endif
     34 #ifndef PLOOPY_SCROLL_BUTTON_DEBOUNCE
     35 #    define PLOOPY_SCROLL_BUTTON_DEBOUNCE 100
     36 #endif
     37 
     38 #ifndef PLOOPY_DPI_OPTIONS
     39 #    define PLOOPY_DPI_OPTIONS \
     40         { 600, 900, 1200, 1600, 2400 }
     41 #    ifndef PLOOPY_DPI_DEFAULT
     42 #        define PLOOPY_DPI_DEFAULT 1
     43 #    endif
     44 #endif
     45 #ifndef PLOOPY_DPI_DEFAULT
     46 #    define PLOOPY_DPI_DEFAULT 0
     47 #endif
     48 #ifndef PLOOPY_DRAGSCROLL_DIVISOR_H
     49 #    define PLOOPY_DRAGSCROLL_DIVISOR_H 8.0
     50 #endif
     51 #ifndef PLOOPY_DRAGSCROLL_DIVISOR_V
     52 #    define PLOOPY_DRAGSCROLL_DIVISOR_V 8.0
     53 #endif
     54 #ifndef ENCODER_BUTTON_ROW
     55 #    define ENCODER_BUTTON_ROW 0
     56 #endif
     57 #ifndef ENCODER_BUTTON_COL
     58 #    define ENCODER_BUTTON_COL 0
     59 #endif
     60 
     61 keyboard_config_t keyboard_config;
     62 uint16_t          dpi_array[] = PLOOPY_DPI_OPTIONS;
     63 #define DPI_OPTION_SIZE ARRAY_SIZE(dpi_array)
     64 
     65 // Trackball State
     66 bool  is_scroll_clicked    = false;
     67 bool  is_drag_scroll       = false;
     68 float scroll_accumulated_h = 0;
     69 float scroll_accumulated_v = 0;
     70 
     71 #ifdef ENCODER_ENABLE
     72 uint16_t lastScroll        = 0; // Previous confirmed wheel event
     73 uint16_t lastMidClick      = 0; // Stops scrollwheel from being read if it was pressed
     74 pin_t    encoder_pins_a[1] = ENCODER_A_PINS;
     75 pin_t    encoder_pins_b[1] = ENCODER_B_PINS;
     76 bool     debug_encoder     = false;
     77 
     78 bool encoder_update_kb(uint8_t index, bool clockwise) {
     79     if (!encoder_update_user(index, clockwise)) {
     80         return false;
     81     }
     82 #    ifdef MOUSEKEY_ENABLE
     83     tap_code(clockwise ? MS_WHLU : MS_WHLD);
     84 #    else
     85     report_mouse_t mouse_report = pointing_device_get_report();
     86     mouse_report.v              = clockwise ? 1 : -1;
     87     pointing_device_set_report(mouse_report);
     88     pointing_device_send();
     89 #    endif
     90     return true;
     91 }
     92 
     93 void encoder_driver_init(void) {
     94     for (uint8_t i = 0; i < ARRAY_SIZE(encoder_pins_a); i++) {
     95         gpio_set_pin_input(encoder_pins_a[i]);
     96         gpio_set_pin_input(encoder_pins_b[i]);
     97     }
     98     opt_encoder_init();
     99 }
    100 
    101 void encoder_driver_task(void) {
    102     uint16_t p1 = analogReadPin(encoder_pins_a[0]);
    103     uint16_t p2 = analogReadPin(encoder_pins_b[0]);
    104 
    105     if (debug_encoder) dprintf("OPT1: %d, OPT2: %d\n", p1, p2);
    106 
    107     int8_t dir = opt_encoder_handler(p1, p2);
    108     // If the mouse wheel was just released, do not scroll.
    109     if (timer_elapsed(lastMidClick) < PLOOPY_SCROLL_BUTTON_DEBOUNCE) {
    110         return;
    111     }
    112 
    113     // Limit the number of scrolls per unit time.
    114     if (timer_elapsed(lastScroll) < PLOOPY_SCROLL_DEBOUNCE) {
    115         return;
    116     }
    117 
    118     // Don't scroll if the middle button is depressed.
    119     if (is_scroll_clicked) {
    120 #    ifndef PLOOPY_IGNORE_SCROLL_CLICK
    121         return;
    122 #    endif
    123     }
    124 
    125     if (dir == 0) return;
    126     encoder_queue_event(0, dir > 0);
    127     lastScroll = timer_read();
    128 }
    129 #endif
    130 
    131 void toggle_drag_scroll(void) {
    132     is_drag_scroll ^= 1;
    133 }
    134 
    135 void cycle_dpi(void) {
    136     keyboard_config.dpi_config = (keyboard_config.dpi_config + 1) % DPI_OPTION_SIZE;
    137     eeconfig_update_kb(keyboard_config.raw);
    138     pointing_device_set_cpi(dpi_array[keyboard_config.dpi_config]);
    139 }
    140 
    141 report_mouse_t pointing_device_task_kb(report_mouse_t mouse_report) {
    142     mouse_report = pointing_device_task_user(mouse_report);
    143     if (is_drag_scroll) {
    144         scroll_accumulated_h += (float)mouse_report.x / PLOOPY_DRAGSCROLL_DIVISOR_H;
    145         scroll_accumulated_v += (float)mouse_report.y / PLOOPY_DRAGSCROLL_DIVISOR_V;
    146 
    147         // Assign integer parts of accumulated scroll values to the mouse report
    148         mouse_report.h = (int8_t)scroll_accumulated_h;
    149 #ifdef PLOOPY_DRAGSCROLL_INVERT
    150         mouse_report.v = -(int8_t)scroll_accumulated_v;
    151 #else
    152         mouse_report.v = (int8_t)scroll_accumulated_v;
    153 #endif
    154 
    155         // Update accumulated scroll values by subtracting the integer parts
    156         scroll_accumulated_h -= (int8_t)scroll_accumulated_h;
    157         scroll_accumulated_v -= (int8_t)scroll_accumulated_v;
    158 
    159         // Clear the X and Y values of the mouse report
    160         mouse_report.x = 0;
    161         mouse_report.y = 0;
    162 
    163         mouse_report.x = 0;
    164         mouse_report.y = 0;
    165     }
    166 
    167     return mouse_report;
    168 }
    169 
    170 bool process_record_kb(uint16_t keycode, keyrecord_t* record) {
    171     if (debug_mouse) {
    172         dprintf("KL: kc: %u, col: %u, row: %u, pressed: %u\n", keycode, record->event.key.col, record->event.key.row, record->event.pressed);
    173     }
    174 
    175     // Update Timer to prevent accidental scrolls
    176 #ifdef ENCODER_ENABLE
    177     if ((record->event.key.col == ENCODER_BUTTON_COL) && (record->event.key.row == ENCODER_BUTTON_ROW)) {
    178         lastMidClick      = timer_read();
    179         is_scroll_clicked = record->event.pressed;
    180     }
    181 #endif
    182 
    183     if (!process_record_user(keycode, record)) {
    184         return false;
    185     }
    186 
    187     if (keycode == DPI_CONFIG && record->event.pressed) {
    188         cycle_dpi();
    189     }
    190 
    191     if (keycode == DRAG_SCROLL) {
    192 #ifdef PLOOPY_DRAGSCROLL_MOMENTARY
    193         is_drag_scroll = record->event.pressed;
    194 #else
    195         if (record->event.pressed) {
    196             toggle_drag_scroll();
    197         }
    198 #endif
    199     }
    200 
    201     return true;
    202 }
    203 
    204 // Hardware Setup
    205 void keyboard_pre_init_kb(void) {
    206     // debug_enable  = true;
    207     // debug_matrix  = true;
    208     // debug_mouse   = true;
    209     // debug_encoder = true;
    210 
    211     /* Ground all output pins connected to ground. This provides additional
    212      * pathways to ground. If you're messing with this, know this: driving ANY
    213      * of these pins high will cause a short. On the MCU. Ka-blooey.
    214      */
    215 #ifdef UNUSABLE_PINS
    216     const pin_t unused_pins[] = UNUSABLE_PINS;
    217 
    218     for (uint8_t i = 0; i < ARRAY_SIZE(unused_pins); i++) {
    219         gpio_set_pin_output_push_pull(unused_pins[i]);
    220         gpio_write_pin_low(unused_pins[i]);
    221     }
    222 #endif
    223 
    224     // This is the debug LED.
    225 #if defined(DEBUG_LED_PIN)
    226     gpio_set_pin_output_push_pull(DEBUG_LED_PIN);
    227     gpio_write_pin(DEBUG_LED_PIN, debug_enable);
    228 #endif
    229 
    230     keyboard_pre_init_user();
    231 }
    232 
    233 void pointing_device_init_kb(void) {
    234     keyboard_config.raw = eeconfig_read_kb();
    235     if (keyboard_config.dpi_config > DPI_OPTION_SIZE) {
    236         eeconfig_init_kb();
    237     }
    238     pointing_device_set_cpi(dpi_array[keyboard_config.dpi_config]);
    239 }
    240 
    241 void eeconfig_init_kb(void) {
    242     keyboard_config.dpi_config = PLOOPY_DPI_DEFAULT;
    243     eeconfig_update_kb(keyboard_config.raw);
    244     eeconfig_init_user();
    245 }