-
Notifications
You must be signed in to change notification settings - Fork 22
/
Copy pathKeypad.h
135 lines (112 loc) · 3.04 KB
/
Keypad.h
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
127
128
129
130
131
132
133
134
135
#ifndef _KEYPAD_H
#define _KEYPAD_H
/* Button-grid-scanning-style keypad support. IDK what the name for these are, they are common.
* (c) 2011, Christopher "ScribbleJ" Jansen
*
*/
#include "AvrPort.h"
#include "ArduinoMap.h"
#include "Time.h"
#include "config.h"
class Keypad {
public:
// TODO: Why do we copy cps and rps but sit on buttonmap directly? Consistency!
Keypad(const Pin *cps, const Pin *rps, const char **buttonmap_in, uint8_t debounce_in)
{
buttonmap = buttonmap_in;
debounce = debounce_in;
good_time = 0;
last_char = 0;
for (int i = 0; i < KP_COLS; i++)
{
colpins[i] = cps[i];
}
for (int i = 0; i < KP_ROWS; i++)
{
rowpins[i] = rps[i];
}
reinit();
}
void reinit()
{
if(colpins[0].isNull())
return;
for (int i = 0; i < KP_COLS; i++)
{
colpins[i].setDirection(false);
colpins[i].setValue(true);
}
for (int i = 0; i < KP_ROWS; i++)
{
rowpins[i].setDirection(false);
rowpins[i].setValue(true);
}
}
// Scans one column of keys for keypresses.
uint8_t scanCol(uint8_t colnum)
{
colpins[colnum].setDirection(true);
colpins[colnum].setValue(false);
uint8_t ret = 0;
for(int x=0;x<KP_ROWS;x++)
{
if(!rowpins[x].getValue())
ret |= 1 << x;
}
colpins[colnum].setDirection(false);
colpins[colnum].setValue(false);
return ret;
}
// returns the first pressed key that is found.
// note - this is expected to be called in a loop like the sjfw mainloop so that it can perform debounce.
// this function and the above are written this way to make it easy to add support for multiple buttons later.
char getPressedKey()
{
// if config is invalid, maybe we get it later.
if(colpins[0].isNull())
return 0;
unsigned long now = micros();
uint8_t colscan = 0;
for(int x=0;x<KP_COLS;x++)
{
colscan = scanCol(x);
if(colscan)
{
for(int y=0;y<KP_ROWS;y++)
{
if(colscan & (1 << y))
{
char fc = buttonmap[y][x];
if(fc == last_char && good_time <= now)
return fc;
if(fc != last_char)
{
last_char = fc;
good_time = now + debounce;
}
return 0;
}
}
}
}
if(good_time && good_time < now)
{
good_time = 0;
last_char = 0;
}
return 0;
}
void setColPin(Port& p, int pin, int n) { colpins[n] = Pin(p, pin); if(n == 0) reinit(); }
void setRowPin(Port& p, int pin, int n) { rowpins[n] = Pin(p, pin); }
// using Arduino schema
void setColPin(int n, int pin) { colpins[n] = Pin(ArduinoMap::getPort(pin), ArduinoMap::getPinnum(pin)); if(n ==0) reinit(); }
void setRowPin(int n, int pin) { rowpins[n] = Pin(ArduinoMap::getPort(pin), ArduinoMap::getPinnum(pin)); }
private:
Pin colpins[KP_COLS];
Pin rowpins[KP_ROWS];
const char **buttonmap;
uint8_t debounce;
unsigned long good_time;
char last_char;
};
#endif