Added generic Debounce class for use by keypad and GPIO inputs

This commit is contained in:
rljonesau 2019-04-13 19:05:53 +10:00
parent 83784a77d2
commit 1819a244f9
8 changed files with 166 additions and 101 deletions

View file

@ -1241,9 +1241,9 @@ void setupGPIO()
{
if(BoardRevision) {
// some special considerations for GPIO inputs, depending upon PCB hardware
// V1.0 PCBs only expose bare inputs, which are pulled high. Active state into ESP32 is LOW
// V2.0+ PCBs use an input transistor buffer. Active state into ESP32 is HIGH (inverted)
int activePinState = BoardRevision == 10 ? LOW : HIGH;
// V1.0 PCBs only expose bare inputs, which are pulled high. Active state into ESP32 is LOW.
// V2.0+ PCBs use an input transistor buffer. Active state into ESP32 is HIGH (inverted).
int activePinState = (BoardRevision == 10) ? LOW : HIGH;
int Input1 = BoardRevision == 20 ? GPIOin1_pinV20 : GPIOin1_pinV21V10;
GPIOin.begin(Input1, GPIOin2_pin, NVstore.getGPIOinMode(), activePinState);

View file

@ -25,11 +25,6 @@
CKeyPad::CKeyPad()
{
// pin scanning
_debouncedPins = 0;
_prevPins = 0;
_lastDebounceTime = millis();
_debounceDelay = 50;
// handler
_lastKey = 0;
_lastHoldTime = 0;
@ -40,39 +35,11 @@ CKeyPad::CKeyPad()
void
CKeyPad::begin(int Lkey, int Rkey, int Ckey, int Ukey, int Dkey)
{
_pins[0] = Lkey;
_pins[1] = Rkey;
_pins[2] = Ckey;
_pins[3] = Ukey;
_pins[4] = Dkey;
for(int i=0; i<5; i++)
pinMode(_pins[i], INPUT);
}
uint8_t
CKeyPad::scanPins()
{
uint8_t newPins = 0;
if(digitalRead(_pins[0]) == LOW) newPins |= key_Left;
if(digitalRead(_pins[1]) == LOW) newPins |= key_Right;
if(digitalRead(_pins[2]) == LOW) newPins |= key_Centre;
if(digitalRead(_pins[3]) == LOW) newPins |= key_Up;
if(digitalRead(_pins[4]) == LOW) newPins |= key_Down;
if(newPins != _prevPins) {
_lastDebounceTime = millis();
_prevPins = newPins;
}
long elapsed = millis() - _lastDebounceTime;
if (elapsed > _debounceDelay) {
// whatever the reading is at, it's been there for longer than the debounce
// delay, so take it as the actual current state:
_debouncedPins = newPins;
}
return _debouncedPins;
_Debounce.addPin(Lkey);
_Debounce.addPin(Rkey);
_Debounce.addPin(Ckey);
_Debounce.addPin(Ukey);
_Debounce.addPin(Dkey);
}
void
@ -84,7 +51,7 @@ CKeyPad::setCallback(void (*callback)(uint8_t event))
uint8_t
CKeyPad::update()
{
uint8_t newKey = scanPins();
uint8_t newKey = _Debounce.manage();
// determine edge events
uint8_t keyChange = newKey ^ _lastKey;

View file

@ -23,6 +23,7 @@
#define __BTC_KEYPAD_H__
#include <stdint.h>
#include "../Utility/Debounce.h"
const uint8_t key_Left = 0x01;
@ -37,17 +38,11 @@ const uint8_t keyRepeat = 0x80; // action flag
class CKeyPad {
private:
void (*_keyCallback)(uint8_t event);
uint8_t _pins[5]; //0:L, 1:R, 2:C, 3:U, 4:D
// pin scanning usage
uint8_t _prevPins;
uint8_t _debouncedPins;
CDebounce _Debounce;
// handler usage
uint8_t _lastKey;
unsigned long _lastHoldTime;
unsigned long _holdTimeout;
uint8_t scanPins();
unsigned long _lastDebounceTime;
unsigned long _debounceDelay;
public:
CKeyPad();
void begin(int Lkey, int Rkey, int Ckey, int Ukey, int Dkey);

View file

@ -81,10 +81,11 @@ int BoardDetect()
uint8_t revision = 0;
uint8_t val = preferences.getUChar("Board Revision", revision);
if(val != 0) {
// return val;
DebugPort.print("Board detect: Using saved revision V"); DebugPort.println(float(val) * 0.1f, 1);
return val;
}
DebugPort.println("Virgin system - attempting to detect revision");
DebugPort.println("Board detect: Virgin system - attempting to detect revision");
pinMode(33, INPUT_PULLUP);
pinMode(26, INPUT_PULLUP);
// there is a 100nF capacitor across the analogue input, allow that to charge before testing
@ -94,27 +95,28 @@ int BoardDetect()
if(pin33 == HIGH && pin26 == HIGH) {
revision = 10;
DebugPort.println("Board detect: digital input test suggests V1.x PCB");
DebugPort.println("Board detect: digital input test reveals V1.x PCB");
}
else if(pin33 == LOW && pin26 == HIGH) {
revision = 20;
DebugPort.println("Board detect: digital input test suggests V2.0 PCB");
DebugPort.println("Board detect: digital input test reveals V2.0 PCB");
}
else if(pin33 == HIGH && pin26 == LOW) {
revision = 21;
DebugPort.println("Board detect: digital input test suggests V2.1 PCB");
DebugPort.println("Board detect: digital input test reveals V2.1 PCB");
}
else {
DebugPort.println("Board detect: digital input test failed to detect a sane combination!!!");
DebugPort.println("Board detect: digital input test failed to detect a valid combination!!!");
}
pinMode(33, INPUT); // revert to normal inputs (remove pull ups)
pinMode(26, INPUT);
//store the detected revision
if(revision) {
preferences.putUChar("Board Revision", revision);
}
DebugPort.print("Board detect result: V"); DebugPort.println(float(revision)*0.1f, 1);
DebugPort.print("Board detect: Result = V"); DebugPort.println(float(revision)*0.1f, 1);
return revision;
}

View file

@ -0,0 +1,86 @@
/*
* This file is part of the "bluetoothheater" distribution
* (https://gitlab.com/mrjones.id.au/bluetoothheater)
*
* Copyright (C) 2018 Ray Jones <ray@mrjones.id.au>
*
* This program 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 License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#include <Arduino.h>
#include "Debounce.h"
CDebounce::CDebounce()
{
_pinActiveState = LOW;
_prevPins = 0;
_lastDebounceTime = 0;
_debounceDelay = 50;
}
void
CDebounce::addPin(int pin)
{
if(pin && (_pins.size() < 8)) {
_pins.push_back(pin);
pinMode(pin, INPUT_PULLUP); // GPIO input pin #1
}
}
void
CDebounce::setActiveState(int activeState)
{
_pinActiveState = activeState;
}
uint8_t
CDebounce::getState()
{
return _debouncedPins;
}
uint8_t
CDebounce::manage()
{
return _scanInputs();
}
uint8_t
CDebounce::_scanInputs()
{
uint8_t newPins = 0;
uint8_t mask = 0x01;
for(int i = 0; i < _pins.size(); i++) {
if(digitalRead(_pins[i]) == _pinActiveState)
newPins |= mask;
mask <<= 1;
}
if(newPins != _prevPins) {
_lastDebounceTime = millis();
_prevPins = newPins;
}
long elapsed = millis() - _lastDebounceTime;
if (elapsed > _debounceDelay) {
// whatever the reading is at, it's been there for longer than the debounce
// delay, so take it as the actual current state:
_debouncedPins = newPins;
}
return _debouncedPins;
}

View file

@ -0,0 +1,44 @@
/*
* This file is part of the "bluetoothheater" distribution
* (https://gitlab.com/mrjones.id.au/bluetoothheater)
*
* Copyright (C) 2018 Ray Jones <ray@mrjones.id.au>
*
* This program 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 License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#ifndef __DEBOUNCE_H__
#define __DEBOUNCE_H__
#include <stdint.h>
#include <vector>
class CDebounce {
int _pinActiveState;
std::vector<int> _pins;
uint8_t _prevPins;
uint8_t _debouncedPins;
unsigned long _lastDebounceTime;
unsigned long _debounceDelay;
uint8_t _scanInputs();
public:
CDebounce();
void addPin(int pin);
void setActiveState(int state);
uint8_t manage();
uint8_t getState();
};
#endif

View file

@ -32,23 +32,15 @@ const int ONFLASHINTERVAL = 50;
CGPIOin::CGPIOin()
{
_Mode = GPIOinNone;
_pins[0] = 0;
_pins[1] = 0;
_pinActive = LOW;
_prevPins = 0;
_lastDebounceTime = 0;
_lastKey = 0;
_debounceDelay = 50;
}
void
CGPIOin::begin(int pin1, int pin2, GPIOinModes mode, int activeState)
{
_pins[0] = pin1;
_pins[1] = pin2;
_pinActive = activeState;
pinMode(pin1, INPUT_PULLUP); // GPIO input pin #1
pinMode(pin2, INPUT_PULLUP); // GPIO input pin #2
_Debounce.addPin(pin1);
_Debounce.addPin(pin2);
_Debounce.setActiveState(activeState);
setMode(mode);
}
@ -57,7 +49,7 @@ uint8_t
CGPIOin::getState(int channel)
{
int mask = 0x01 << (channel & 0x01);
return (_debouncedPins & mask) != 0;
return (_Debounce.getState() & mask) != 0;
}
void
@ -81,7 +73,7 @@ CGPIOin::manage()
void
CGPIOin::_doOn1Off2()
{
uint8_t newKey = _scanInputs();
uint8_t newKey = _Debounce.manage();
// determine edge events
uint8_t keyChange = newKey ^ _lastKey;
_lastKey = newKey;
@ -101,7 +93,7 @@ CGPIOin::_doOn1Off2()
void
CGPIOin::_doOnHold1()
{
uint8_t newKey = _scanInputs();
uint8_t newKey = _Debounce.manage();
// determine edge events
uint8_t keyChange = newKey ^ _lastKey;
_lastKey = newKey;
@ -121,7 +113,7 @@ CGPIOin::_doOnHold1()
void
CGPIOin::_doOn1Off1()
{
uint8_t newKey = _scanInputs();
uint8_t newKey = _Debounce.manage();
// determine edge events
uint8_t keyChange = newKey ^ _lastKey;
_lastKey = newKey;
@ -136,29 +128,6 @@ CGPIOin::_doOn1Off1()
}
}
uint8_t
CGPIOin::_scanInputs()
{
uint8_t newPins = 0;
if(_pins[0] && (digitalRead(_pins[0]) == _pinActive)) newPins |= 0x01;
if(_pins[1] && (digitalRead(_pins[1]) == _pinActive)) newPins |= 0x02;
if(newPins != _prevPins) {
_lastDebounceTime = millis();
_prevPins = newPins;
}
long elapsed = millis() - _lastDebounceTime;
if (elapsed > _debounceDelay) {
// whatever the reading is at, it's been there for longer than the debounce
// delay, so take it as the actual current state:
_debouncedPins = newPins;
}
return _debouncedPins;
}
CGPIOout::CGPIOout()

View file

@ -24,6 +24,7 @@
#include <stdint.h>
#include <driver/adc.h>
#include "Debounce.h"
enum GPIOinModes {
GPIOinNone,
@ -46,14 +47,15 @@ enum GPIOalgModes {
class CGPIOin {
GPIOinModes _Mode;
int _pinActive;
int _pins[2];
uint8_t _prevPins;
uint8_t _debouncedPins;
CDebounce _Debounce;
// int _pinActive;
// int _pins[2];
// uint8_t _prevPins;
// uint8_t _debouncedPins;
uint8_t _lastKey;
unsigned long _lastDebounceTime;
unsigned long _debounceDelay;
uint8_t _scanInputs();
// unsigned long _lastDebounceTime;
// unsigned long _debounceDelay;
// uint8_t _scanInputs();
void _doOn1Off2();
void _doOnHold1();
void _doOn1Off1();