-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathKeyScanner.cpp
127 lines (112 loc) · 2.87 KB
/
KeyScanner.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#if ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
#include <Adafruit_MCP23017.h>
#include "KeyScanner.h"
#define BOUNCE_DELAY 20
KeyScanner::KeyScanner(const uint8_t* const pRows, uint8_t rows,
const uint8_t* const pCols, uint8_t cols,
const char* const pKeyValues)
: m_pRows(pRows), m_rows(rows), m_pCols(pCols), m_cols(cols), m_pKeyValues(pKeyValues)
{
// init m_pDownTime
m_pDownTime = (unsigned long*)malloc(sizeof(unsigned long) * m_rows * m_cols);
for(uint8_t x = 0; x < m_rows * m_cols; x++)
{
*(m_pDownTime + x) = 0;
}
}
void
KeyScanner::begin(uint8_t mcp_addr)
{
m_mcp.begin(mcp_addr);
// Setup the mcp rows as input and pullup to HIGH
for(uint8_t row = 0; row < m_rows; row++)
{
m_mcp.pinMode(m_pRows[row], INPUT);
m_mcp.pullUp(m_pRows[row], HIGH);
}
// Setup the mcp cols as outputs and initialize to LOW
for(uint8_t col = 0; col < m_cols; col++)
{
m_mcp.pinMode(m_pCols[col], OUTPUT);
}
setColsLow();
}
void
KeyScanner::setColsLow(void)
{
uint16_t ba = m_mcp.readGPIOAB();
ba = ba & 0xff00;
m_mcp.writeGPIOAB(ba);
}
void
KeyScanner::setColsHigh(void)
{
uint16_t ba = m_mcp.readGPIOAB();
ba = ba | 0x00ff;
m_mcp.writeGPIOAB(ba);
}
void
KeyScanner::keyPressed(uint8_t row, uint8_t col, unsigned long scan_time)
{
// Check for newly depressed key
if(m_pDownTime[row * m_cols + col] == 0)
{
//lcd.print(key_values[row][col]);
Keyboard.press((const char)m_pKeyValues[row * m_cols + col]);
}
// Update the time that the key was last seen as "pressed"
m_pDownTime[row * m_cols + col] = scan_time;
}
// check for keys that are no longer pressed
void
KeyScanner::checkUnpressed(unsigned long scan_time)
{
if(scan_time < BOUNCE_DELAY)
{
return;
}
unsigned long target_time = scan_time - BOUNCE_DELAY;
for(uint8_t row = 0; row < m_rows; row++)
{
for(uint8_t col = 0; col < m_cols; col++)
{
unsigned long down_time = m_pDownTime[row * m_cols + col];
if(down_time > 0 && down_time < target_time)
{
Keyboard.release((const char)m_pKeyValues[row * m_cols + col]);
m_pDownTime[row * m_cols + col] = 0;
}
}
}
}
bool
KeyScanner::scanKeys() {
unsigned long scan_time = millis();
int value = LOW;
// Scan the rows to see if a key is pressed
for(uint8_t row = 0; row < m_rows; row++)
{
if(!m_mcp.digitalRead(m_pRows[row]))
{
value = HIGH;
setColsHigh();
// Iterate through the columns to see which column
for(uint8_t col = 0; col < m_cols; col++)
{
m_mcp.digitalWrite(m_pCols[col], LOW);
if(!m_mcp.digitalRead(m_pRows[row]))
{
keyPressed(row, col, scan_time);
}
m_mcp.digitalWrite(m_pCols[col], HIGH);
}
setColsLow();
}
}
checkUnpressed(scan_time);
return (value == HIGH);
}