qmk_firmware

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

encoder.c (4913B)


      1 // Copyright 2022-2023 Nick Brassel (@tzarc)
      2 // SPDX-License-Identifier: GPL-2.0-or-later
      3 
      4 #include <string.h>
      5 #include "action.h"
      6 #include "encoder.h"
      7 #include "wait.h"
      8 
      9 #ifndef ENCODER_MAP_KEY_DELAY
     10 #    define ENCODER_MAP_KEY_DELAY TAP_CODE_DELAY
     11 #endif
     12 
     13 __attribute__((weak)) bool should_process_encoder(void) {
     14     return is_keyboard_master();
     15 }
     16 
     17 static encoder_events_t encoder_events;
     18 static bool             signal_queue_drain = false;
     19 
     20 void encoder_init(void) {
     21     memset(&encoder_events, 0, sizeof(encoder_events));
     22     encoder_driver_init();
     23 }
     24 
     25 static void encoder_queue_drain(void) {
     26     encoder_events.tail     = encoder_events.head;
     27     encoder_events.dequeued = encoder_events.enqueued;
     28 }
     29 
     30 static bool encoder_handle_queue(void) {
     31     bool    changed = false;
     32     uint8_t index;
     33     bool    clockwise;
     34     while (encoder_dequeue_event(&index, &clockwise)) {
     35 #ifdef ENCODER_MAP_ENABLE
     36 
     37         // The delays below cater for Windows and its wonderful requirements.
     38         action_exec(clockwise ? MAKE_ENCODER_CW_EVENT(index, true) : MAKE_ENCODER_CCW_EVENT(index, true));
     39 #    if ENCODER_MAP_KEY_DELAY > 0
     40         wait_ms(ENCODER_MAP_KEY_DELAY);
     41 #    endif // ENCODER_MAP_KEY_DELAY > 0
     42 
     43         action_exec(clockwise ? MAKE_ENCODER_CW_EVENT(index, false) : MAKE_ENCODER_CCW_EVENT(index, false));
     44 #    if ENCODER_MAP_KEY_DELAY > 0
     45         wait_ms(ENCODER_MAP_KEY_DELAY);
     46 #    endif // ENCODER_MAP_KEY_DELAY > 0
     47 
     48 #else // ENCODER_MAP_ENABLE
     49 
     50         encoder_update_kb(index, clockwise);
     51 
     52 #endif // ENCODER_MAP_ENABLE
     53 
     54         changed = true;
     55     }
     56     return changed;
     57 }
     58 
     59 bool encoder_task(void) {
     60     bool changed = false;
     61 
     62 #ifdef SPLIT_KEYBOARD
     63     // Attempt to process existing encoder events in case split handling has already enqueued events
     64     if (should_process_encoder()) {
     65         changed |= encoder_handle_queue();
     66     }
     67 #endif // SPLIT_KEYBOARD
     68 
     69     if (signal_queue_drain) {
     70         signal_queue_drain = false;
     71         encoder_queue_drain();
     72     }
     73 
     74     // Let the encoder driver produce events
     75     encoder_driver_task();
     76 
     77     // Process any events that were enqueued
     78     if (should_process_encoder()) {
     79         changed |= encoder_handle_queue();
     80     }
     81 
     82     return changed;
     83 }
     84 
     85 bool encoder_queue_full_advanced(encoder_events_t *events) {
     86     return events->tail == (events->head + 1) % MAX_QUEUED_ENCODER_EVENTS;
     87 }
     88 
     89 bool encoder_queue_full(void) {
     90     return encoder_queue_full_advanced(&encoder_events);
     91 }
     92 
     93 bool encoder_queue_empty_advanced(encoder_events_t *events) {
     94     return events->head == events->tail;
     95 }
     96 
     97 bool encoder_queue_empty(void) {
     98     return encoder_queue_empty_advanced(&encoder_events);
     99 }
    100 
    101 bool encoder_queue_event_advanced(encoder_events_t *events, uint8_t index, bool clockwise) {
    102     // Drop out if we're full
    103     if (encoder_queue_full_advanced(events)) {
    104         return false;
    105     }
    106 
    107     // Append the event
    108     encoder_event_t new_event   = {.index = index, .clockwise = clockwise ? 1 : 0};
    109     events->queue[events->head] = new_event;
    110 
    111     // Increment the head index
    112     events->head = (events->head + 1) % MAX_QUEUED_ENCODER_EVENTS;
    113     events->enqueued++;
    114 
    115     return true;
    116 }
    117 
    118 bool encoder_dequeue_event_advanced(encoder_events_t *events, uint8_t *index, bool *clockwise) {
    119     if (encoder_queue_empty_advanced(events)) {
    120         return false;
    121     }
    122 
    123     // Retrieve the event
    124     encoder_event_t event = events->queue[events->tail];
    125     *index                = event.index;
    126     *clockwise            = event.clockwise;
    127 
    128     // Increment the tail index
    129     events->tail = (events->tail + 1) % MAX_QUEUED_ENCODER_EVENTS;
    130     events->dequeued++;
    131 
    132     return true;
    133 }
    134 
    135 bool encoder_queue_event(uint8_t index, bool clockwise) {
    136     return encoder_queue_event_advanced(&encoder_events, index, clockwise);
    137 }
    138 
    139 bool encoder_dequeue_event(uint8_t *index, bool *clockwise) {
    140     return encoder_dequeue_event_advanced(&encoder_events, index, clockwise);
    141 }
    142 
    143 void encoder_retrieve_events(encoder_events_t *events) {
    144     memcpy(events, &encoder_events, sizeof(encoder_events));
    145 }
    146 
    147 void encoder_signal_queue_drain(void) {
    148     signal_queue_drain = true;
    149 }
    150 
    151 __attribute__((weak)) bool encoder_update_user(uint8_t index, bool clockwise) {
    152     return true;
    153 }
    154 
    155 __attribute__((weak)) bool encoder_update_kb(uint8_t index, bool clockwise) {
    156     bool res = encoder_update_user(index, clockwise);
    157 #if !defined(ENCODER_TESTS)
    158     if (res) {
    159         if (clockwise) {
    160 #    if defined(EXTRAKEY_ENABLE)
    161             tap_code_delay(KC_VOLU, 10);
    162 #    elif defined(MOUSEKEY_ENABLE)
    163             tap_code_delay(QK_MOUSE_WHEEL_UP, 10);
    164 #    else
    165             tap_code_delay(KC_PGDN, 10);
    166 #    endif
    167         } else {
    168 #    if defined(EXTRAKEY_ENABLE)
    169             tap_code_delay(KC_VOLD, 10);
    170 #    elif defined(MOUSEKEY_ENABLE)
    171             tap_code_delay(QK_MOUSE_WHEEL_DOWN, 10);
    172 #    else
    173             tap_code_delay(KC_PGUP, 10);
    174 #    endif
    175         }
    176     }
    177 #endif // ENCODER_TESTS
    178     return res;
    179 }