Browse Source

rename Row to RowBase, move debounce() to Row_DH

tags/v0.5.0
wolfv6 8 years ago
parent
commit
27f0c2dfaa
4 changed files with 28 additions and 88 deletions
  1. 3
    1
      doc/keybrd_library_developer_guide.md
  2. 3
    3
      src/Matrix.h
  3. 8
    68
      src/RowBase.cpp
  4. 14
    16
      src/RowBase.h

+ 3
- 1
doc/keybrd_library_developer_guide.md View File

@@ -17,7 +17,9 @@ Keybrd library class inheritance diagram
```
Matrix
Row
RowBase
|
Row
IOExpanderPort

+ 3
- 3
src/Matrix.h View File

@@ -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();

src/Row.cpp → src/RowBase.cpp View File

@@ -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.
}

src/Row.h → src/RowBase.h View File

@@ -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