qmk_firmware

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

opt_encoder_default.c (7528B)


      1 /* Copyright 2020 Christopher Courtney, aka Drashna Jael're  (@drashna) <drashna@live.com>
      2  * Copyright 2020 Ploopy Corporation
      3  *
      4  * This program is free software: you can redistribute it and/or modify
      5  * it under the terms of the GNU General Public License as published by
      6  * the Free Software Foundation, either version 2 of the License, or
      7  * (at your option) any later version.
      8  *
      9  * This program is distributed in the hope that it will be useful,
     10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12  * GNU General Public License for more details.
     13  *
     14  * You should have received a copy of the GNU General Public License
     15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
     16  */
     17 #include "opt_encoder.h"
     18 #include <stdbool.h>
     19 //typedef unsigned char uint8_t;
     20 //typedef char int8_t;
     21 //typedef unsigned short uint16_t;
     22 //typedef enum { false, true } bool;
     23 
     24 enum State { HIHI, HILO, LOLO, LOHI };
     25 
     26 enum State state;
     27 
     28 /* Variables used for scroll wheel functionality. */
     29 bool lohif;
     30 bool hilof;
     31 int  lowA;
     32 int  highA;
     33 bool cLowA;
     34 bool cHighA;
     35 int  lowIndexA;
     36 int  highIndexA;
     37 bool lowOverflowA;
     38 bool highOverflowA;
     39 int  lowB;
     40 int  highB;
     41 bool cLowB;
     42 bool cHighB;
     43 int  lowIndexB;
     44 int  highIndexB;
     45 bool lowOverflowB;
     46 bool highOverflowB;
     47 int  scrollThresholdA;
     48 int  scrollThresholdB;
     49 int  arLowA[SCROLLER_AR_SIZE];
     50 int  arHighA[SCROLLER_AR_SIZE];
     51 int  arLowB[SCROLLER_AR_SIZE];
     52 int  arHighB[SCROLLER_AR_SIZE];
     53 
     54 void calculateThresholdA(int curA);
     55 void calculateThresholdB(int curB);
     56 int  calculateThreshold(int cur, int* low, int* high, bool* cLow, bool* cHigh, int arLow[], int arHigh[], int* lowIndex, int* highIndex, bool* lowOverflow, bool* highOverflow);
     57 int  thresholdEquation(int lo, int hi);
     58 void incrementIndex(int* index, bool* ovflw);
     59 
     60 /* Setup function for the scroll wheel. Initializes
     61    the relevant variables. */
     62 void opt_encoder_init(void) {
     63     state            = HIHI;
     64     lohif            = false;
     65     hilof            = false;
     66     lowA             = 1023;
     67     highA            = 0;
     68     cLowA            = false;
     69     cHighA           = false;
     70     lowIndexA        = 0;
     71     highIndexA       = 0;
     72     lowOverflowA     = false;
     73     highOverflowA    = false;
     74     lowB             = 1023;
     75     highB            = 0;
     76     cLowB            = false;
     77     cHighB           = false;
     78     lowIndexB        = 0;
     79     highIndexB       = 0;
     80     lowOverflowB     = false;
     81     highOverflowB    = false;
     82     scrollThresholdA = 0;
     83     scrollThresholdB = 0;
     84 }
     85 
     86 int8_t opt_encoder_handler(uint16_t curA, uint16_t curB) {
     87     if (lowOverflowA == false || highOverflowA == false) calculateThresholdA(curA);
     88     if (lowOverflowB == false || highOverflowB == false) calculateThresholdB(curB);
     89 
     90     bool LO = false;
     91     bool HI = true;
     92     bool sA, sB;
     93     int  ret = 0;
     94 
     95     if (curA < scrollThresholdA)
     96         sA = LO;
     97     else
     98         sA = HI;
     99 
    100     if (curB < scrollThresholdB)
    101         sB = LO;
    102     else
    103         sB = HI;
    104 
    105     if (state == HIHI) {
    106         if (sA == LO && sB == HI) {
    107             state = LOHI;
    108             if (hilof) {
    109                 ret   = 1;
    110                 hilof = false;
    111             }
    112         } else if (sA == HI && sB == LO) {
    113             state = HILO;
    114             if (lohif) {
    115                 ret   = -1;
    116                 lohif = false;
    117             }
    118         }
    119     }
    120 
    121     else if (state == HILO) {
    122         if (sA == HI && sB == HI) {
    123             state = HIHI;
    124             hilof = true;
    125             lohif = false;
    126         } else if (sA == LO && sB == LO) {
    127             state = LOLO;
    128             hilof = true;
    129             lohif = false;
    130         }
    131     }
    132 
    133     else if (state == LOLO) {
    134         if (sA == HI && sB == LO) {
    135             state = HILO;
    136             if (lohif) {
    137                 ret   = 1;
    138                 lohif = false;
    139             }
    140         } else if (sA == LO && sB == HI) {
    141             state = LOHI;
    142             if (hilof) {
    143                 ret   = -1;
    144                 hilof = false;
    145             }
    146         }
    147     }
    148 
    149     else { // state must be LOHI
    150         if (sA == HI && sB == HI) {
    151             state = HIHI;
    152             lohif = true;
    153             hilof = false;
    154         } else if (sA == LO && sB == LO) {
    155             state = LOLO;
    156             lohif = true;
    157             hilof = false;
    158         }
    159     }
    160 
    161     return ret;
    162 }
    163 
    164 void calculateThresholdA(int curA) {
    165     scrollThresholdA = calculateThreshold(curA, &lowA, &highA, &cLowA, &cHighA, arLowA, arHighA, &lowIndexA, &highIndexA, &lowOverflowA, &highOverflowA);
    166 }
    167 
    168 void calculateThresholdB(int curB) {
    169     scrollThresholdB = calculateThreshold(curB, &lowB, &highB, &cLowB, &cHighB, arLowB, arHighB, &lowIndexB, &highIndexB, &lowOverflowB, &highOverflowB);
    170 }
    171 
    172 int calculateThreshold(int cur, int* low, int* high, bool* cLow, bool* cHigh, int arLow[], int arHigh[], int* lowIndex, int* highIndex, bool* lowOverflow, bool* highOverflow) {
    173     if (cur < *low) *low = cur;
    174     if (cur > *high) *high = cur;
    175 
    176     int curThresh = thresholdEquation(*low, *high);
    177     int range     = *high - *low;
    178 
    179     // The range is enforced to be over a certain limit because noise
    180     // can cause erroneous readings, making these calculations unstable.
    181     if (range >= SCROLL_THRESH_RANGE_LIM) {
    182         if (cur < curThresh) {
    183             if (*cHigh == true) {
    184                 // We were just high, and now we crossed to low.
    185                 // high reflects a sample of a high reading.
    186                 arHigh[*highIndex] = *high;
    187                 incrementIndex(highIndex, highOverflow);
    188                 int midpoint = ((*high - *low) / 2) + *low;
    189                 *low         = midpoint;
    190                 *high        = midpoint;
    191                 *cLow        = false;
    192                 *cHigh       = false;
    193             } else {
    194                 *cLow = true;
    195             }
    196         }
    197         if (cur > curThresh) {
    198             if (*cLow == true) {
    199                 // We were just low, and now we crossed to high.
    200                 // low reflects a sample of a low reading.
    201                 arLow[*lowIndex] = *low;
    202                 incrementIndex(lowIndex, lowOverflow);
    203                 int midpoint = ((*high - *low) / 2) + *low;
    204                 *low         = midpoint;
    205                 *high        = midpoint;
    206                 *cLow        = false;
    207                 *cHigh       = false;
    208             } else {
    209                 *cHigh = true;
    210             }
    211         }
    212     }
    213 
    214     int calcHigh = 0;
    215     if (*highOverflow == true) {
    216         for (int i = 0; i < SCROLLER_AR_SIZE; i++) {
    217             calcHigh += arHigh[i];
    218         }
    219         calcHigh = calcHigh / SCROLLER_AR_SIZE;
    220     } else if (*highIndex != 0) {
    221         for (int i = 0; i < *highIndex; i++) {
    222             calcHigh += arHigh[i];
    223         }
    224         calcHigh = calcHigh / *highIndex;
    225     } else {
    226         calcHigh = *high;
    227     }
    228 
    229     int calcLow = 0;
    230     if (*lowOverflow == true) {
    231         for (int i = 0; i < SCROLLER_AR_SIZE; i++) {
    232             calcLow += arLow[i];
    233         }
    234         calcLow = calcLow / SCROLLER_AR_SIZE;
    235     } else if (*lowIndex != 0) {
    236         for (int i = 0; i < *lowIndex; i++) {
    237             calcLow += arLow[i];
    238         }
    239         calcLow = calcLow / *lowIndex;
    240     } else {
    241         calcLow = *low;
    242     }
    243 
    244     return thresholdEquation(calcLow, calcHigh);
    245 }
    246 
    247 int thresholdEquation(int lo, int hi) {
    248     return ((hi - lo) / 3) + lo;
    249 }
    250 
    251 void incrementIndex(int* index, bool* ovflw) {
    252     if (*index < SCROLLER_AR_SIZE - 1)
    253         (*index)++;
    254     else {
    255         *index = 0;
    256         *ovflw = true;
    257     }
    258 }