@@ -15,9 +15,7 @@ void Row::process(const bool activeHigh) | |||
uint8_t debouncedChanged; //1 means debounced changed | |||
wait(); | |||
scan(activeHigh); //save column-port-pin values to portState | |||
rowState = getRowState(rowEnd, activeHigh); | |||
//debouncedChanged = debounce(rowState); | |||
//rowState = scanner.scan(rowEnd, activeHigh); | |||
debouncedChanged = debouncer.debounce(rowState, debounced); | |||
pressRelease(rowEnd, debouncedChanged); | |||
} |
@@ -2,6 +2,7 @@ | |||
#define ROW_H | |||
#include <RowBase.h> | |||
#include <RowScanner_BitManipulation.h> | |||
#include <Debouncer_4Samples.h> | |||
/* | |||
@@ -17,14 +18,14 @@ Instantiation | |||
class Row : public RowBase | |||
{ | |||
private: | |||
RowScanner_BitManipulation scanner; | |||
Debouncer_4Samples debouncer; | |||
public: | |||
Row( RowPort &refRowPort, const uint8_t rowPin, | |||
ColPort *const ptrsColPorts[], const uint8_t colPortCount, Key *const ptrsKeys[]) | |||
: RowBase(refRowPort, rowPin, ptrsColPorts, colPortCount, ptrsKeys) | |||
{ | |||
Debouncer_4Samples debouncer; | |||
} | |||
: RowBase(ptrsKeys) | |||
, RowScanner_BitManipulation scanner(refRowPort, rowPin, ptrsColPorts, colPortCount) | |||
{ } | |||
virtual void process(const bool activeHigh); | |||
}; | |||
#endif |
@@ -35,82 +35,6 @@ void RowBase::wait() | |||
delayMicroseconds(DELAY_MICROSECONDS); //delay between Row scans to debounce switches | |||
} | |||
/* | |||
Strobes the row and reads the columns. | |||
Strobe is on for shortest possible time to preserve IR LED on DodoHand's optic switch. | |||
*/ | |||
void RowBase::scan(const bool activeHigh) | |||
{ | |||
//strobe row on | |||
if (activeHigh) | |||
{ | |||
refRowPort.setActivePinHigh(rowPin); | |||
} | |||
else //activeLow | |||
{ | |||
refRowPort.setActivePinLow(rowPin); | |||
} | |||
//read all the column ports | |||
for (uint8_t i=0; i < colPortCount; i++) | |||
{ | |||
ptrsColPorts[i]->read(); | |||
} | |||
//strobe row off | |||
if (activeHigh) | |||
{ | |||
refRowPort.setActivePinLow(rowPin); | |||
} | |||
else //activeLow | |||
{ | |||
refRowPort.setActivePinHigh(rowPin); | |||
} | |||
} | |||
/* | |||
Copies column pins to rowState. Unused column pins are not copied. | |||
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 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 | |||
for (uint8_t i=0; i < colPortCount; i++) //for each col port | |||
{ | |||
//bitwise colPins, 1 means pin is connected to column | |||
uint8_t colPins = ptrsColPorts[i]->getColPins(); | |||
//bitwise colPortState, pin values where set in ColPort::read(), get them now | |||
uint8_t colPortState = ptrsColPorts[i]->getPortState(); | |||
if (activeHigh) | |||
{ | |||
colPortState = ~colPortState; | |||
} | |||
for ( uint8_t portMask = 1; portMask > 0; portMask <<= 1 ) //shift portMask until overflow | |||
{ //for each pin of col port | |||
if (portMask & colPins) //if pin is connected to column | |||
{ | |||
if (portMask & ~colPortState) //if pin detected a key press | |||
{ | |||
rowState |= rowMask; //set rowState bit for that key | |||
} | |||
rowMask <<= 1; //shift rowMask to next key | |||
} | |||
} | |||
} | |||
rowEnd = rowMask; | |||
return rowState; | |||
} | |||
/* | |||
pressRelease() calls key's press() or release() function if it was pressed or released. | |||
Both parameters are bitwise. |
@@ -3,8 +3,6 @@ | |||
#include <Arduino.h> | |||
#include <inttypes.h> | |||
#include <Key.h> | |||
#include <RowPort.h> | |||
#include <ColPort.h> | |||
/* RowBase is an abstract base class. | |||
*/ | |||
@@ -14,27 +12,14 @@ class RowBase | |||
static const unsigned int DELAY_MICROSECONDS; //delay between each Row scan for debouncing | |||
Key *const *const ptrsKeys; //array of Key pointers | |||
RowPort &refRowPort; //this row's IC port | |||
const uint8_t rowPin; //bitwise, 1 indicates IC pin connected to this row | |||
ColPort *const *const ptrsColPorts; //array of column ports | |||
const uint8_t colPortCount; | |||
virtual void keyWasPressed(); | |||
protected: | |||
uint8_t debounced; //bitwise, 1 means pressed, 0 means released | |||
void wait(); | |||
void scan(const bool activeHigh); | |||
uint8_t getRowState(uint16_t& rowEnd, const bool activeHigh); | |||
void pressRelease(const uint16_t rowEnd, const uint8_t debouncedChanged); | |||
public: | |||
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), | |||
debounced(0) { } | |||
RowBase(Key *const ptrsKeys[]) : ptrsKeys(ptrsKeys), debounced(0) { } | |||
virtual void process(const bool activeHigh)=0; | |||
}; | |||
#endif |
@@ -0,0 +1,18 @@ | |||
#ifndef ROWSCANNERINTERFACE_H | |||
#define ROWSCANNERINTERFACE_H | |||
/* RowScannerInterface is an interface class. | |||
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. | |||
*/ | |||
#include <Arduino.h> | |||
#include <inttypes.h> | |||
class RowScannerInterface | |||
{ | |||
public: | |||
virtual uint8_t scan(uint16_t& rowEnd, const bool activeHigh)=0; | |||
}; | |||
#endif | |||
@@ -0,0 +1,78 @@ | |||
#include "RowScanner_BitManipulation.h" | |||
/* | |||
Strobes the row and reads the columns. | |||
Strobe is on for shortest possible time to preserve IR LED on DodoHand's optic switch. | |||
*/ | |||
uint8_t RowScanner_BitManipulation::scan(uint16_t& rowEnd, const bool activeHigh) | |||
{ | |||
//strobe row on | |||
if (activeHigh) | |||
{ | |||
refRowPort.setActivePinHigh(rowPin); | |||
} | |||
else //activeLow | |||
{ | |||
refRowPort.setActivePinLow(rowPin); | |||
} | |||
//read all the column ports | |||
for (uint8_t i=0; i < colPortCount; i++) | |||
{ | |||
ptrsColPorts[i]->read(); | |||
} | |||
//strobe row off | |||
if (activeHigh) | |||
{ | |||
refRowPort.setActivePinLow(rowPin); | |||
} | |||
else //activeLow | |||
{ | |||
refRowPort.setActivePinHigh(rowPin); | |||
} | |||
return getRowState(rowEnd, activeHigh); | |||
} | |||
/* | |||
Copies column pins to rowState. Unused column pins are not copied. | |||
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 RowScanner_BitManipulation::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 | |||
for (uint8_t i=0; i < colPortCount; i++) //for each col port | |||
{ | |||
//bitwise colPins, 1 means pin is connected to column | |||
uint8_t colPins = ptrsColPorts[i]->getColPins(); | |||
//bitwise colPortState, pin values where set in ColPort::read(), get them now | |||
uint8_t colPortState = ptrsColPorts[i]->getPortState(); | |||
if (activeHigh) | |||
{ | |||
colPortState = ~colPortState; | |||
} | |||
for ( uint8_t portMask = 1; portMask > 0; portMask <<= 1 ) //shift portMask until overflow | |||
{ //for each pin of col port | |||
if (portMask & colPins) //if pin is connected to column | |||
{ | |||
if (portMask & ~colPortState) //if pin detected a key press | |||
{ | |||
rowState |= rowMask; //set rowState bit for that key | |||
} | |||
rowMask <<= 1; //shift rowMask to next key | |||
} | |||
} | |||
} | |||
rowEnd = rowMask; | |||
return rowState; | |||
} |
@@ -0,0 +1,26 @@ | |||
#ifndef ROWSCANNER_BITMANIPULATION_H | |||
#define ROWSCANNER_BITMANIPULATION_H | |||
#include <Arduino.h> | |||
#include <inttypes.h> | |||
#include <RowScannerInterface.h> | |||
#include <RowPort.h> | |||
#include <ColPort.h> | |||
class RowScanner_BitManipulation : public RowScannerInterface | |||
{ | |||
private: | |||
RowPort &refRowPort; //this row's IC port | |||
const uint8_t rowPin; //bitwise, 1 indicates IC pin connected to this row | |||
ColPort *const *const ptrsColPorts; //array of column ports | |||
const uint8_t colPortCount; | |||
public: | |||
RowScanner_BitManipulation(RowPort &refRowPort, const uint8_t rowPin, | |||
ColPort *const ptrsColPorts[], const uint8_t colPortCount) | |||
: refRowPort(refRowPort), rowPin(rowPin), | |||
ptrsColPorts(ptrsColPorts), colPortCount(colPortCount) {} | |||
virtual uint8_t scan(uint16_t& rowEnd, const bool activeHigh); | |||
uint8_t getRowState(uint16_t& rowEnd, const bool activeHigh); | |||
}; | |||
#endif |