uint8_t debouncedChanged; //1 means debounced changed | uint8_t debouncedChanged; //1 means debounced changed | ||||
wait(); | 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); | debouncedChanged = debouncer.debounce(rowState, debounced); | ||||
pressRelease(rowEnd, debouncedChanged); | pressRelease(rowEnd, debouncedChanged); | ||||
} | } |
#define ROW_H | #define ROW_H | ||||
#include <RowBase.h> | #include <RowBase.h> | ||||
#include <RowScanner_BitManipulation.h> | |||||
#include <Debouncer_4Samples.h> | #include <Debouncer_4Samples.h> | ||||
/* | /* | ||||
class Row : public RowBase | class Row : public RowBase | ||||
{ | { | ||||
private: | private: | ||||
RowScanner_BitManipulation scanner; | |||||
Debouncer_4Samples debouncer; | Debouncer_4Samples debouncer; | ||||
public: | public: | ||||
Row( RowPort &refRowPort, const uint8_t rowPin, | Row( RowPort &refRowPort, const uint8_t rowPin, | ||||
ColPort *const ptrsColPorts[], const uint8_t colPortCount, Key *const ptrsKeys[]) | 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); | virtual void process(const bool activeHigh); | ||||
}; | }; | ||||
#endif | #endif |
delayMicroseconds(DELAY_MICROSECONDS); //delay between Row scans to debounce switches | 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. | pressRelease() calls key's press() or release() function if it was pressed or released. | ||||
Both parameters are bitwise. | Both parameters are bitwise. |
#include <Arduino.h> | #include <Arduino.h> | ||||
#include <inttypes.h> | #include <inttypes.h> | ||||
#include <Key.h> | #include <Key.h> | ||||
#include <RowPort.h> | |||||
#include <ColPort.h> | |||||
/* RowBase is an abstract base class. | /* RowBase is an abstract base class. | ||||
*/ | */ | ||||
static const unsigned int DELAY_MICROSECONDS; //delay between each Row scan for debouncing | static const unsigned int DELAY_MICROSECONDS; //delay between each Row scan for debouncing | ||||
Key *const *const ptrsKeys; //array of Key pointers | 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(); | virtual void keyWasPressed(); | ||||
protected: | protected: | ||||
uint8_t debounced; //bitwise, 1 means pressed, 0 means released | uint8_t debounced; //bitwise, 1 means pressed, 0 means released | ||||
void wait(); | 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); | void pressRelease(const uint16_t rowEnd, const uint8_t debouncedChanged); | ||||
public: | 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; | virtual void process(const bool activeHigh)=0; | ||||
}; | }; | ||||
#endif | #endif |
#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 | |||||
#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; | |||||
} |
#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 |