aboutsummaryrefslogtreecommitdiff
path: root/Arduino/Libraies/Keypad/Keypad.cpp
blob: 3c7ffc622ea70f10af54d3b3a92bb5bdbdf6a3b6 (plain)
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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
/*
||
|| @file Keypad.h
|| @version 1.8
|| @author Mark Stanley, Alexander Brevig
|| @contact mstanley@technologist.com, alexanderbrevig@gmail.com
||
|| @description
|| | This library provides a simple interface for using matrix
|| | keypads. It supports the use of multiple keypads with the
|| | same or different sets of keys.  It also supports user
|| | selectable pins and definable keymaps.
|| #
||
|| @license
|| | This library is free software; you can redistribute it and/or
|| | modify it under the terms of the GNU Lesser General Public
|| | License as published by the Free Software Foundation; version
|| | 2.1 of the License.
|| |
|| | This library is distributed in the hope that it will be useful,
|| | but WITHOUT ANY WARRANTY; without even the implied warranty of
|| | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
|| | Lesser General Public License for more details.
|| |
|| | You should have received a copy of the GNU Lesser General Public
|| | License along with this library; if not, write to the Free Software
|| | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
|| #
||
*/

#include "Keypad.h"

// <<constructor>> Allows custom keymap. pin configuration and keypad size
Keypad::Keypad(char *userKeymap, byte *row, byte *col, byte rows, byte cols)
{
    rowPins = row;
    columnPins = col;
	
    //Serial.println("Override");
	size.rows = rows;
        //size.rows = 8;
	size.columns = cols;
	//size.columns = 16;

    //Serial.print("Constructor Col ");
    //int colSize = size.columns;
    //Serial.print(colSize);
    //int rowSize = size.rows;
    //Serial.print(" Row ");
    //Serial.println(rowSize);
	
    begin(userKeymap);
	
	lastUpdate = 0;
	debounceTime = 50;
	holdTime = 1000;
	keypadEventListener = 0;
	currentKey = NO_KEY;
	state = IDLE;
	
	initializePins();
}

// Let the user define a keymap - assume the same row- / columncount as defined in constructor
void Keypad::begin( char *userKeymap){
    keymap = userKeymap;
}

// Returns the keykode of the pressed key, or NO_KEY if no key is pressed
char Keypad::getKey(){
    //Serial.print("GetKey Col ");
    //int colSize = size.columns;
    //Serial.print(colSize);
    //int rowSize = size.rows;
    //Serial.print(" Row ");
    //Serial.println(rowSize);
    char key = NO_KEY; // Assume that no key is pressed, this is the default return for getKey()
    for (byte c=0; c<size.columns; c++){
                //Serial.print("col ");
                //int cInt = c;
                //Serial.println(cInt);
		digitalWrite(columnPins[c],LOW);	// Activate the current column.
		for (byte r=0; r<size.rows; r++){	// Scan all the rows for a key press.
                        //Serial.print("row");
                        //int rInt = r;
                        //Serial.println(rInt);
			//  The user pressed a button for more then debounceTime microseconds.
			if (currentKey == keymap[c+(r*size.columns)]){
				// Button hold
				if (((millis()-lastUpdate) >= holdTime) && digitalRead(rowPins[r]) == LOW){
					transitionTo(HOLD);
				}
				// Button release
				if (((millis()-lastUpdate) >= debounceTime) && digitalRead(rowPins[r]) == HIGH){
					transitionTo(RELEASED);
					currentKey = NO_KEY;
				}
			} 
			// Button pressed event.  The user pressed a button.
			else if (((millis()-lastUpdate) >= debounceTime) && digitalRead(rowPins[r]) == LOW){
				digitalWrite(columnPins[c],HIGH);	// De-activate the current column.
				key = keymap[c+(r*size.columns)];
				lastUpdate = millis();
				goto EVALUATE_KEY; 			// Save resources and do not attempt to parse to keys at a time
			} 
		}
		digitalWrite(columnPins[c],HIGH);	// De-activate the current column.
	}
	
	EVALUATE_KEY:
	if (key != NO_KEY && key != currentKey){ 
		currentKey = key;
		transitionTo(PRESSED);
		return currentKey;
	} 
	else{
		return NO_KEY;
	}
}


KeypadState Keypad::getState(){
	return state;
}

void Keypad::setDebounceTime(unsigned int debounce){
	debounceTime = debounce;
}
void Keypad::setHoldTime(unsigned int hold){
	holdTime = hold;
}

void Keypad::addEventListener(void (*listener)(char)){
	keypadEventListener = listener;
}

//private
void Keypad::transitionTo(KeypadState newState){
	if (state!=newState){
		state = newState;
		if (keypadEventListener!=NULL){ 
			keypadEventListener(currentKey);
		}
	}
}

void Keypad::initializePins(){
	for (byte r=0; r<size.rows; r++){
        for (byte c=0; c<size.columns; c++){
			pinMode(columnPins[c],OUTPUT);
			digitalWrite(columnPins[c],HIGH);
        }
		//configure row pin modes and states
		pinMode(rowPins[r],INPUT);
		digitalWrite(rowPins[r],HIGH);
    }
}

/*
|| @changelog
|| | 2009-07-08 - Alexander Brevig : Library does not use 2d arrays
|| | 2009-06-15 - Alexander Brevig : Added transitionTo
|| | 2009-06-15 - Alexander Brevig : Added getState()
|| | 2009-06-13 - Mark Stanley : Fixed bug in getKey() that returns the wrong key if debounceTime is too short.
|| | 2009-06-13 - Mark Stanley : Minor bug fix:  Added 'currentKey = NO_KEY' to constructors.
|| | 2009-05-19 - Alexander Brevig : Added setHoldTime()
|| | 2009-05-15 - Alexander Brevig : Changed begin() amd getKey(), this Library should be operational.
|| | 2009-05-09 - Alexander Brevig : Changed getKey()
|| | 2009-04-28 - Alexander Brevig : Modified API, and made variables private
|| | 2007-XX-XX - Mark Stanley : Initial Release
|| #
*/