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 }