changed scrolling algorithm to be much more robust, using a state machine instead of state-free processing
This commit is contained in:
parent
e29e58df63
commit
aff1ef0bf6
|
@ -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;
|
||||||
|
}
|
|
@ -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
|
|
@ -21,6 +21,7 @@
|
||||||
#include <avr/pgmspace.h>
|
#include <avr/pgmspace.h>
|
||||||
#include <avr/wdt.h>
|
#include <avr/wdt.h>
|
||||||
#include "AdvMouse.h"
|
#include "AdvMouse.h"
|
||||||
|
#include "Scroller.h"
|
||||||
|
|
||||||
// Max recommended is 4,000,000, since clock speed is 8MHz.
|
// Max recommended is 4,000,000, since clock speed is 8MHz.
|
||||||
// If lower, it should be by factors of 1/2.
|
// 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 CPI = 1200;
|
||||||
static const int DEBOUNCE = 10; // ms
|
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 int SCROLL_BUTT_DEBOUNCE = 100; // ms
|
||||||
|
|
||||||
static const float ROTATIONAL_TRANSFORM_ANGLE = 20;
|
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_PIN1 = A3;
|
||||||
static const int OPT_ENC_PIN2 = A5;
|
static const int OPT_ENC_PIN2 = A5;
|
||||||
|
|
||||||
static const int OPT_LOW_THRESHOLD = 150;
|
|
||||||
|
|
||||||
static const byte MOTION = 0x02;
|
static const byte MOTION = 0x02;
|
||||||
static const byte DELTA_X_L = 0x03;
|
static const byte DELTA_X_L = 0x03;
|
||||||
static const byte DELTA_X_H = 0x04;
|
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 };
|
uint8_t buttonBuffer[5] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
|
||||||
char buttonKey[5] = { MOUSE_LEFT, MOUSE_RIGHT, MOUSE_MIDDLE, MOUSE_BACK, MOUSE_FORWARD };
|
char buttonKey[5] = { MOUSE_LEFT, MOUSE_RIGHT, MOUSE_MIDDLE, MOUSE_BACK, MOUSE_FORWARD };
|
||||||
|
|
||||||
int firstOptLowPin;
|
|
||||||
|
|
||||||
bool initComplete = false;
|
bool initComplete = false;
|
||||||
|
|
||||||
int16_t dx;
|
int16_t dx;
|
||||||
|
@ -86,6 +83,8 @@ unsigned long lastScroll = 0;
|
||||||
|
|
||||||
unsigned long middleClickRelease = 0;
|
unsigned long middleClickRelease = 0;
|
||||||
|
|
||||||
|
static Scroller scroller;
|
||||||
|
|
||||||
extern const unsigned short firmware_length;
|
extern const unsigned short firmware_length;
|
||||||
extern const unsigned char firmware_data[];
|
extern const unsigned char firmware_data[];
|
||||||
|
|
||||||
|
@ -401,31 +400,15 @@ signed char moveWheel() {
|
||||||
int d2 = analogRead(OPT_ENC_PIN2);
|
int d2 = analogRead(OPT_ENC_PIN2);
|
||||||
|
|
||||||
if (debugMode) {
|
if (debugMode) {
|
||||||
Serial.print(F("d1: "));
|
Serial.print(F("th: "));
|
||||||
|
Serial.print(scroller.getScrollThreshold());
|
||||||
|
Serial.print(F(", d1: "));
|
||||||
Serial.print(d1);
|
Serial.print(d1);
|
||||||
Serial.print(F(", d2: "));
|
Serial.print(F(", d2: "));
|
||||||
Serial.println(d2);
|
Serial.println(d2);
|
||||||
}
|
}
|
||||||
|
|
||||||
signed char ret = 0;
|
return scroller.scroll(d2, d1);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
|
|
Loading…
Reference in New Issue