rename Row to RowBase, move debounce() to Row_DH
This commit is contained in:
parent
e0a53ca748
commit
27f0c2dfaa
@ -17,7 +17,9 @@ Keybrd library class inheritance diagram
|
||||
```
|
||||
Matrix
|
||||
|
||||
Row
|
||||
RowBase
|
||||
|
|
||||
Row
|
||||
|
||||
IOExpanderPort
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
#define MATRIX_H
|
||||
#include <Arduino.h>
|
||||
#include <inttypes.h>
|
||||
#include "Row.h"
|
||||
#include "RowBase.h"
|
||||
|
||||
/*
|
||||
Diode orientation
|
||||
@ -28,12 +28,12 @@ External pull-down resistors should have a value between 10k Ohms and 2.2k Ohms.
|
||||
class Matrix
|
||||
{
|
||||
private:
|
||||
Row *const *const ptrsRows; //array of row pointers
|
||||
RowBase *const *const ptrsRows; //array of row pointers
|
||||
const uint8_t rowCount;
|
||||
const bool activeHigh; //logic level of strobe pin: 0=activeLow, 1=activeHigh
|
||||
|
||||
public:
|
||||
Matrix( Row *const ptrsRows[], const uint8_t rowCount, const bool activeHigh)
|
||||
Matrix( RowBase *const ptrsRows[], const uint8_t rowCount, const bool activeHigh)
|
||||
: ptrsRows(ptrsRows), rowCount(rowCount), activeHigh(activeHigh) {}
|
||||
|
||||
void scan();
|
||||
|
@ -1,8 +1,8 @@
|
||||
#include "Row.h"
|
||||
#include "RowBase.h"
|
||||
/*
|
||||
scans the row and calls any newly pressed or released keys.
|
||||
*/
|
||||
void Row::process(const bool activeHigh)
|
||||
void RowBase::process(const bool activeHigh)
|
||||
{
|
||||
//these variables are all bitwise, one bit per key
|
||||
uint8_t rowState; //1 means pressed, 0 means released
|
||||
@ -22,7 +22,7 @@ void Row::process(const bool activeHigh)
|
||||
Strobes the row and reads the columns.
|
||||
Strobe is on for shortest possible time to preserve IR LED on DodoHand's optic switch.
|
||||
*/
|
||||
void Row::scan(const bool activeHigh)
|
||||
void RowBase::scan(const bool activeHigh)
|
||||
{
|
||||
//strobe row on
|
||||
if (activeHigh)
|
||||
@ -57,7 +57,7 @@ Sets rowEnd and returns rowState.
|
||||
rowEnd is bitwise, where 1 bit corrsiponds to place immediatly after last key of row.
|
||||
rowEnd and rowMask are larger type than portMask so that they can not overflow.
|
||||
*/
|
||||
uint8_t Row::getRowState(uint16_t& rowEnd, const bool activeHigh)
|
||||
uint8_t RowBase::getRowState(uint16_t& rowEnd, const bool activeHigh)
|
||||
{
|
||||
uint16_t rowMask = 1; //bitwise, one col per bit, active col bit is 1
|
||||
uint8_t rowState = 0; //bitwise, one key per bit, 1 means key is pressed
|
||||
@ -94,71 +94,11 @@ uint8_t Row::getRowState(uint16_t& rowEnd, const bool activeHigh)
|
||||
return rowState;
|
||||
}
|
||||
|
||||
/*
|
||||
Parameter rowState is bitwise, 1 means pressed, 0 means released.
|
||||
Returns debounced rowState.
|
||||
|
||||
Debounce uses multiple samples to debounces switch states,
|
||||
where each sample contains the switch states for a row of keys, one bit per switch.
|
||||
|
||||
Debounce uses Marty's debounce algorithm from
|
||||
http://drmarty.blogspot.com.br/2009/05/best-switch-debounce-routine-ever.html
|
||||
I2C and TWI protocals do not include any Packet Error Checking (PEC).
|
||||
The goal of Marty's debounce routine is to reject spurious signals,
|
||||
which is useful when conecting split keyboards with a cable using I2C or TWI.
|
||||
Was tested on split keyboard with 3-meter long telephone wire to I/O expander
|
||||
|
||||
Marty's debounce algorithm:
|
||||
Periodically read samples and update the state when a number consecutive sample bits are equal.
|
||||
|
||||
samples[SAMPLE_COUNT] is a ring buffer and samplesIndex is it's current write index.
|
||||
SAMPLE_COUNT is #defined in Row.h
|
||||
SAMPLE_COUNT is the number of consecutive equal samples needed to debounce.
|
||||
It is a macro because it is used to define array size of samples[SAMPLE_COUNT] in Row.
|
||||
SAMPLE_COUNT should be at lease 2.
|
||||
|
||||
Multiple samples are for error correction on I2C I/O expander and shorten response time.
|
||||
On keyboards without I/O expander, multiple samples only shorten response time.
|
||||
Larger SAMPLE_COUNTs are more reliable but consume more memory, where
|
||||
SAMPLE_COUNT*ROW_COUNT = bytes of memory consumed by keyboard
|
||||
So don't make SAMPLE_COUNT too large, SAMPLE_COUNT = 4 is very reliable for I2C error correction.
|
||||
|
||||
big SAMPLE_COUNT for fast response, small SAMPLE_COUNT to save memory
|
||||
there is a way to define SAMPLE_COUNT in the sketch, but it's ugly
|
||||
see http://forum.arduino.cc/index.php?topic=364843.0 > rely #2
|
||||
*/
|
||||
uint8_t Row::debounce(const uint8_t rowState)
|
||||
{
|
||||
uint8_t all_1 = ~0; //bitwise
|
||||
uint8_t all_0 = 0; //bitwise
|
||||
|
||||
delayMicroseconds(DELAY_MICROSECONDS); //delay between Row scans to debounce key
|
||||
|
||||
samples[samplesIndex] = rowState; //insert rowState into samples[] ring buffer
|
||||
|
||||
if (++samplesIndex >= SAMPLE_COUNT)
|
||||
{
|
||||
samplesIndex = 0; //wrap samplesIndex to beginning of ring buffer
|
||||
}
|
||||
|
||||
for (uint8_t j = 0; j < SAMPLE_COUNT; j++) //traverse the sample[] ring buffer
|
||||
{
|
||||
all_1 &= samples[j]; //1 if all samples are 1
|
||||
all_0 |= samples[j]; //0 if all samples are 0
|
||||
}
|
||||
|
||||
// update newDebounce if all the samples agree with one another
|
||||
// if all samples=1 then newDebounced=1
|
||||
// elseif all samples=0 then newDebounced=0
|
||||
// else newDebounced=debounced i.e. no change
|
||||
return all_1 | (all_0 & debounced);
|
||||
}
|
||||
|
||||
/*
|
||||
Computes isFallingEdge and isRisingEdge.
|
||||
All 3 parameters are bitwise.
|
||||
*/
|
||||
void Row::detectEdge(uint8_t newDebounced, uint8_t& isFallingEdge, uint8_t& isRisingEdge)
|
||||
void RowBase::detectEdge(uint8_t newDebounced, uint8_t& isFallingEdge, uint8_t& isRisingEdge)
|
||||
{
|
||||
uint8_t debouncedChanged; //bitwise
|
||||
|
||||
@ -176,7 +116,7 @@ void Row::detectEdge(uint8_t newDebounced, uint8_t& isFallingEdge, uint8_t& isRi
|
||||
calls key's press() or release() function if it was pressed or released.
|
||||
All 3 parameters are bitwise.
|
||||
*/
|
||||
void Row::pressRelease(const uint16_t rowEnd, const uint8_t isFallingEdge,
|
||||
void RowBase::pressRelease(const uint16_t rowEnd, const uint8_t isFallingEdge,
|
||||
const uint8_t isRisingEdge)
|
||||
{
|
||||
uint8_t rowMask; //bitwise, active col bit is 1
|
||||
@ -198,7 +138,7 @@ void Row::pressRelease(const uint16_t rowEnd, const uint8_t isFallingEdge,
|
||||
}
|
||||
}
|
||||
|
||||
void Row::keyWasPressed()
|
||||
void RowBase::keyWasPressed()
|
||||
{
|
||||
//empty in Row class. To unstick sticky keys, override keyWasPressed() in derived class.
|
||||
//empty in RowBase class. To unstick sticky keys, override keyWasPressed() in derived class.
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
#ifndef ROW_H
|
||||
#define ROW_H
|
||||
#ifndef ROWBASE_H
|
||||
#define ROWBASE_H
|
||||
#include <Arduino.h>
|
||||
#include <inttypes.h>
|
||||
#include <Key.h>
|
||||
@ -46,7 +46,7 @@ Slow-scan trick for debug message that print too fast
|
||||
Change DELAY_MICROSECONDS to a large number like 10000
|
||||
That way printing debug messages is slowed to a managable rate
|
||||
*/
|
||||
class Row
|
||||
class RowBase
|
||||
{
|
||||
private:
|
||||
Key *const *const ptrsKeys; //array of Key pointers
|
||||
@ -57,25 +57,23 @@ class Row
|
||||
ColPort *const *const ptrsColPorts; //array of column ports
|
||||
const uint8_t colPortCount;
|
||||
|
||||
static const unsigned int DELAY_MICROSECONDS; //delay between each Row scan for debouncing
|
||||
uint8_t samples[SAMPLE_COUNT]; //bitwise, one bit per key, most resent readings
|
||||
uint8_t samplesIndex; //samples[] current write index
|
||||
uint8_t debounced; //bitwise, one bit per key, debounced value of readings
|
||||
void scan(const bool activeHigh);
|
||||
uint8_t getRowState(uint16_t& rowEnd, const bool activeHigh);
|
||||
virtual uint8_t debounce(const uint8_t rowState)=0; //debouncer and I2C error correction
|
||||
void detectEdge(uint8_t newDebounced, uint8_t& isFallingEdge, uint8_t& isRisingEdge);
|
||||
void pressRelease(const uint16_t rowEnd,
|
||||
const uint8_t isFallingEdge, const uint8_t isRisingEdge);
|
||||
virtual void keyWasPressed();
|
||||
protected:
|
||||
uint8_t debounced; //bitwise, one bit per key, debounced value of readings
|
||||
public:
|
||||
Row( RowPort &refRowPort, const uint8_t rowPin,
|
||||
RowBase( RowPort &refRowPort, const uint8_t rowPin,
|
||||
ColPort *const ptrsColPorts[], const uint8_t colPortCount,
|
||||
Key *const ptrsKeys[])
|
||||
: ptrsKeys(ptrsKeys), refRowPort(refRowPort), rowPin(rowPin),
|
||||
ptrsColPorts(ptrsColPorts), colPortCount(colPortCount),
|
||||
samplesIndex(0), debounced(0) { }
|
||||
|
||||
Key* getPtrKey(uint8_t col) const;
|
||||
debounced(0) { }
|
||||
//Key* getPtrKey(uint8_t col) const; todo delete, no longer needed 5/31/16
|
||||
void process(const bool activeHigh);
|
||||
void scan(const bool activeHigh);
|
||||
uint8_t getRowState(uint16_t& rowEnd, const bool activeHigh);
|
||||
uint8_t debounce(const uint8_t rowState); //switch debouncer and I2C error correction
|
||||
void detectEdge(uint8_t newDebounced, uint8_t& isFallingEdge, uint8_t& isRisingEdge);
|
||||
void pressRelease(const uint16_t rowEnd, const uint8_t isFallingEdge, const uint8_t isRisingEdge);
|
||||
};
|
||||
#endif
|
Reference in New Issue
Block a user