changed scrolling algorithm to be much more robust, using a state machine instead of state-free processing
This commit is contained in:
		
							parent
							
								
									3fc87daa95
								
							
						
					
					
						commit
						c4b738599f
					
				| 
						 | 
				
			
			@ -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/wdt.h>
 | 
			
		||||
#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() {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue