From aff1ef0bf6b99a26ce17ce0007a4c70aa133a072 Mon Sep 17 00:00:00 2001 From: ploopyco Date: Sun, 27 Oct 2019 22:07:31 -0400 Subject: [PATCH] changed scrolling algorithm to be much more robust, using a state machine instead of state-free processing --- firmware/Scroller.cpp | 129 ++++++++++++++++++++++++++++++++++++++++ firmware/Scroller.h | 41 +++++++++++++ firmware/production.ino | 33 +++------- 3 files changed, 178 insertions(+), 25 deletions(-) create mode 100644 firmware/Scroller.cpp create mode 100644 firmware/Scroller.h diff --git a/firmware/Scroller.cpp b/firmware/Scroller.cpp new file mode 100644 index 0000000..c23b96c --- /dev/null +++ b/firmware/Scroller.cpp @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2019, Ploopy Corporation, a Canadian federal corporation. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public Licensefalse + * along with this program; if not, write to the Free Software + * Foundation, Inc. + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "Scroller.h" + +Scroller::Scroller(void) { + state = HIHI; + lohif = false; + hilof = false; + lowA = 50; + highA = 150; + lowB = 50; + highB = 150; + calculateThreshold(lowA, lowB); +} + +int Scroller::scroll(int curA, int curB) { + calculateThreshold(curA, curB); + + bool LO = false; + bool HI = true; + bool sA, sB; + int ret = 0; + + if (curA < scrollThreshold) + sA = LO; + else + sA = HI; + + if (curB < scrollThreshold) + sB = LO; + else + sB = HI; + + if (state == HIHI) { + if (sA == LO && sB == HI) { + state = LOHI; + if (hilof) { + ret = 1; + hilof = false; + } + } else if (sA == HI && sB == LO) { + state = HILO; + if (lohif) { + ret = -1; + lohif = false; + } + } + } + + else if (state == HILO) { + if (sA == HI && sB == HI) { + state = HIHI; + hilof = true; + lohif = false; + } else if (sA == LO && sB == LO) { + state = LOLO; + hilof = true; + lohif = false; + } + } + + else if (state == LOLO) { + if (sA == HI && sB == LO) { + state = HILO; + if (lohif) { + ret = 1; + lohif = false; + } + } else if (sA == LO && sB == HI) { + state = LOHI; + if (hilof) { + ret = -1; + hilof = false; + } + } + } + + else { // state must be LOHI + if (sA == HI && sB == HI) { + state = HIHI; + lohif = true; + hilof = false; + } else if (sA == LO && sB == LO) { + state = LOLO; + lohif = true; + hilof = false; + } + } + + return ret; +} + +int Scroller::getScrollThreshold(void) { + return scrollThreshold; +} + +int Scroller::calculateThreshold(int curA, int curB) { + if (curA < lowA) + lowA = curA; + else if (curA > highA) + highA = curA; + + if (curB < lowB) + lowB = curB; + else if (curB > highB) + highB = curB; + + int avgA = ((highA - lowA) / 3) + lowA; + int avgB = ((highB - lowB) / 3) + lowB; + + scrollThreshold = (avgA + avgB) / 2; +} \ No newline at end of file diff --git a/firmware/Scroller.h b/firmware/Scroller.h new file mode 100644 index 0000000..2c44a8d --- /dev/null +++ b/firmware/Scroller.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2019, Ploopy Corporation, a Canadian federal corporation. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public Licensefalse + * along with this program; if not, write to the Free Software + * Foundation, Inc. + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef SCROLLER_h +#define SCROLLER_h + +class Scroller { + private: + enum State { HIHI, HILO, LOLO, LOHI }; + State state; + bool lohif; + bool hilof; + int lowA; + int highA; + int lowB; + int highB; + int scrollThreshold; + int calculateThreshold(int, int); + public: + Scroller(void); + int scroll(int, int); + int getScrollThreshold(void); +}; + +#endif \ No newline at end of file diff --git a/firmware/production.ino b/firmware/production.ino index 5c84149..f3c3b17 100644 --- a/firmware/production.ino +++ b/firmware/production.ino @@ -21,6 +21,7 @@ #include #include #include "AdvMouse.h" +#include "Scroller.h" // Max recommended is 4,000,000, since clock speed is 8MHz. // If lower, it should be by factors of 1/2. @@ -28,7 +29,7 @@ static const int SPIMAXIMUMSPEED = 2000000; static const int CPI = 1200; static const int DEBOUNCE = 10; // ms -static const int SCROLL_DEBOUNCE = 50; // ms +static const int SCROLL_DEBOUNCE = 100; // ms static const int SCROLL_BUTT_DEBOUNCE = 100; // ms static const float ROTATIONAL_TRANSFORM_ANGLE = 20; @@ -45,8 +46,6 @@ static const int SENSOR_CS = 17; static const int OPT_ENC_PIN1 = A3; static const int OPT_ENC_PIN2 = A5; -static const int OPT_LOW_THRESHOLD = 150; - static const byte MOTION = 0x02; static const byte DELTA_X_L = 0x03; static const byte DELTA_X_H = 0x04; @@ -72,8 +71,6 @@ bool buttonState[5] = { false, false, false, false, false }; uint8_t buttonBuffer[5] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; char buttonKey[5] = { MOUSE_LEFT, MOUSE_RIGHT, MOUSE_MIDDLE, MOUSE_BACK, MOUSE_FORWARD }; -int firstOptLowPin; - bool initComplete = false; int16_t dx; @@ -86,6 +83,8 @@ unsigned long lastScroll = 0; unsigned long middleClickRelease = 0; +static Scroller scroller; + extern const unsigned short firmware_length; extern const unsigned char firmware_data[]; @@ -401,31 +400,15 @@ signed char moveWheel() { int d2 = analogRead(OPT_ENC_PIN2); if (debugMode) { - Serial.print(F("d1: ")); + Serial.print(F("th: ")); + Serial.print(scroller.getScrollThreshold()); + Serial.print(F(", d1: ")); Serial.print(d1); Serial.print(F(", d2: ")); Serial.println(d2); } - signed char ret = 0; - - if (d1 < OPT_LOW_THRESHOLD && d2 < OPT_LOW_THRESHOLD) { - if (firstOptLowPin == OPT_ENC_PIN1) { - // scroll down - ret = -1; - } else if (firstOptLowPin == OPT_ENC_PIN2) { - // scroll up - ret = 1; - } - - firstOptLowPin = 0; - } else if (d1 < OPT_LOW_THRESHOLD) { - firstOptLowPin = OPT_ENC_PIN1; - } else if (d2 < OPT_LOW_THRESHOLD) { - firstOptLowPin = OPT_ENC_PIN2; - } - - return ret; + return scroller.scroll(d2, d1); } void loop() {