const unsigned int Row::DELAY_MICROSECONDS = 0; | const unsigned int Row::DELAY_MICROSECONDS = 0; | ||||
Slow-scan trick for debug messages that print too fast and not aligned, add this to sketch loop(): | Slow-scan trick for debug messages that print too fast and not aligned, add this to sketch loop(): | ||||
delay(1000); | |||||
delay(500); | |||||
Keyboard.println(""); | Keyboard.println(""); | ||||
That way debug messages are printed at a managable rate, and each scan starts a new line. | That way debug messages are printed at a managable rate, and each scan starts a new line. | ||||
*/ | */ | ||||
/* | /* | ||||
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. | ||||
rowEnd bit marks positioned immediatly after last key of row. | |||||
*/ | */ | ||||
void RowBase::pressRelease(const uint16_t rowEnd, const uint8_t debouncedChanged) | void RowBase::pressRelease(const uint16_t rowEnd, const uint8_t debouncedChanged) | ||||
{ | { |
/* | /* | ||||
Strobes the row and reads the columns. | Strobes the row and reads the columns. | ||||
Sets rowEnd and returns rowState. | |||||
rowEnd is a bitwise row mask, one col per bit, where active col bit is 1. | |||||
At end of function, 1 bit marks place immediatly after last key of row. | |||||
rowEnd is a larger type than portMask so that it can not overflow. | |||||
*/ | */ | ||||
uint8_t RowScanner_Arduino::scan(uint16_t& rowEnd) | uint8_t RowScanner_Arduino::scan(uint16_t& rowEnd) | ||||
{ | { | ||||
uint8_t rowState = 0; | uint8_t rowState = 0; | ||||
uint8_t col = 1; | |||||
rowEnd = 1; | |||||
//strobe row on | //strobe row on | ||||
if (activeHigh) | if (activeHigh) | ||||
{ | { | ||||
digitalWrite(strobePin, LOW); | digitalWrite(strobePin, LOW); | ||||
} | } | ||||
delayMicroseconds(3); //time to stablize voltage | |||||
delayMicroseconds(3); //time to stablize voltage | |||||
//read all the column ports | //read all the column ports | ||||
for (uint8_t i=0; i < READ_PIN_COUNT; i++) | for (uint8_t i=0; i < READ_PIN_COUNT; i++) | ||||
{ | { | ||||
if ( digitalRead(readPins[i]) == activeHigh ) | if ( digitalRead(readPins[i]) == activeHigh ) | ||||
{ | { | ||||
rowState |= col; | |||||
rowState |= rowEnd; | |||||
} | } | ||||
col <<= 1; | |||||
rowEnd <<= 1; | |||||
} | } | ||||
//strobe row off | //strobe row off | ||||
{ | { | ||||
digitalWrite(strobePin, HIGH); | digitalWrite(strobePin, HIGH); | ||||
} | } | ||||
rowEnd = col; | |||||
return rowState; | return rowState; | ||||
} | } |
#include <RowScannerInterface.h> | #include <RowScannerInterface.h> | ||||
#include <RowPort.h> | #include <RowPort.h> | ||||
#include <ColPort.h> | #include <ColPort.h> | ||||
/* rowPin > strobePins[] | |||||
replace port calls with | |||||
x pass 1: hard code pins for row0 and col6, init in setup() | |||||
x pass 2: readPins[] array | |||||
pass 3: move calls to IC classes - Strobe_uC, Read_uC | |||||
pass 4: add IC classes Strobe_MCP23018, Read_MCP23018 */ | |||||
/* RowScanner_Arduino class uses Arduino pin numbers (no port name). | |||||
*/ | |||||
class RowScanner_Arduino : public RowScannerInterface | class RowScanner_Arduino : public RowScannerInterface | ||||
{ | { | ||||
private: | private: | ||||
static const bool activeHigh; //logic level of strobe pin: 0=activeLow, 1=activeHigh | static const bool activeHigh; //logic level of strobe pin: 0=activeLow, 1=activeHigh | ||||
const uint8_t strobePin; //Arduino pin number connected to this row | |||||
const uint8_t* readPins; //array of read pins | |||||
const uint8_t READ_PIN_COUNT;//todo READ_PIN_COUNT | |||||
const uint8_t strobePin; //Arduino pin number connected to this row | |||||
const uint8_t* readPins; //array of read pin numbers | |||||
const uint8_t READ_PIN_COUNT; //number of read pins | |||||
public: | public: | ||||
RowScanner_Arduino(const uint8_t strobePin, | RowScanner_Arduino(const uint8_t strobePin, | ||||
const uint8_t readPins[], const uint8_t READ_PIN_COUNT) | const uint8_t readPins[], const uint8_t READ_PIN_COUNT) |
/* | /* | ||||
Copies column pins to rowState. Unused column pins are not copied. | Copies column pins to rowState. Unused column pins are not copied. | ||||
Sets rowEnd and returns rowState. | 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. | |||||
rowEnd is a bitwise row mask, one col per bit, where active col bit is 1. | |||||
At end of function, 1 bit marks place immediatly after last key of row. | |||||
rowEnd is a larger type than portMask so that it can not overflow. | |||||
*/ | */ | ||||
uint8_t RowScanner_BitManipulation::getRowState(uint16_t& rowEnd) | uint8_t RowScanner_BitManipulation::getRowState(uint16_t& rowEnd) | ||||
{ | { | ||||
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 | uint8_t rowState = 0; //bitwise, one key per bit, 1 means key is pressed | ||||
rowEnd = 1; | |||||
for (uint8_t i=0; i < colPortCount; i++) //for each col port | for (uint8_t i=0; i < colPortCount; i++) //for each col port | ||||
{ | { | ||||
//bitwise colPins, 1 means pin is connected to column | //bitwise colPins, 1 means pin is connected to column | ||||
{ | { | ||||
if (portMask & ~colPortState) //if pin detected a key press | if (portMask & ~colPortState) //if pin detected a key press | ||||
{ | { | ||||
rowState |= rowMask; //set rowState bit for that key | |||||
rowState |= rowEnd; //set rowState bit for that key | |||||
} | } | ||||
rowMask <<= 1; //shift rowMask to next key | |||||
rowEnd <<= 1; //shift rowEnd to next key | |||||
} | } | ||||
} | } | ||||
} | } | ||||
rowEnd = rowMask; | |||||
return rowState; | return rowState; | ||||
} | } |
#include <RowPort.h> | #include <RowPort.h> | ||||
#include <ColPort.h> | #include <ColPort.h> | ||||
/* RowScanner_BitManipulation uses bit manipulation to read all pins of one port. | |||||
*/ | |||||
class RowScanner_BitManipulation : public RowScannerInterface | class RowScanner_BitManipulation : public RowScannerInterface | ||||
{ | { | ||||
private: | private: |