diff --git a/libraries/Keypad/Keypad.cpp b/libraries/Keypad/Keypad.cpp new file mode 100755 index 0000000..1bd0fdd --- /dev/null +++ b/libraries/Keypad/Keypad.cpp @@ -0,0 +1,256 @@ +/* +|| +|| @file Keypad.h +|| @version 2.0 +|| @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 + +// <> Allows custom keymap, pin configuration, and keypad sizes. +Keypad::Keypad(char *userKeymap, byte *row, byte *col, byte numRows, byte numCols) { + rowPins = row; + columnPins = col; + size.rows = numRows; + size.columns = numCols; + + begin(userKeymap); + + setDebounceTime(2); + setHoldTime(500); + keypadEventListener = 0; + + transitionTo(IDLE); + stateChanged = false; + + initializePins(); +} + +// New in 2.0 this function lets the end user test for any changes in state +// before deciding if any variables, etc. need to be updated in their code. +boolean Keypad::keyStateChanged() { + return stateChanged; +} + +// Let the user define a keymap - assume the same row/column count as defined in constructor +void Keypad::begin( char *userKeymap) { + keymap = userKeymap; +} + +char Keypad::getKey() { + // Return the new key value if a keypress was detected. By testing for + // keyStateChanged() we don't return a keypress more than once. + if( getKeyState()==PRESSED && keyStateChanged() ) + { + return currentKey; + } + + return NO_KEY; // Otherwise just return the default key value: +} + +char Keypad::waitForKey() { + char waitKey = NO_KEY; + while( (waitKey = getKey()) == NO_KEY ); // Do nothing. Waiting for keypress. + return waitKey; +} + +// Private +// Scan the keypad and report whether or not a key (or any key) has been pressed. +// 2011-12-23 - Removed from getKeyState() for readability and ease of maintenance. +boolean Keypad::scanKeys() { + static unsigned int allKeys=0; + byte curKey=0; + boolean anyKey; + + // Assume that some other device is sharing the data pins used by the + // keypad. If that is the case then the pins will need to be re-intialized + // each time before they are used. + initializePins(); + + // I rewrote this method to provide a status change (anyKey OPEN/CLOSED) to the + // getKeyState() function which handles debouncing. Now we can scan the keypad + // without having to worry about huge debounce time delays. + for( int c=0; c10 ) + startTime = millis(); + else + return state; + + // Find out whether or not a key was pressed and if so which one it was. + buttons = scanKeys(); + + switch (state) { + case IDLE: + // The only thing to do while idling is to look for a debounced keypress. + if( buttons==CLOSED && (millis()-Timer)>debounceTime ) { + transitionTo(PRESSED); + Timer = millis(); + } + break; + case PRESSED: + // Waiting for a key hold... + if ( (millis()-Timer)>holdTime ) { + transitionTo(HOLD); // Move to next state. + Timer = millis(); // Reset debounce timer. + } + // Or for the key to be release. + else if ( buttons==OPEN && (millis()-Timer)>debounceTime ) { + transitionTo(RELEASED); + Timer = millis(); + } + break; + case HOLD: + // Waiting for the key to be released. + if ( (buttons==OPEN) && (millis()-Timer)>debounceTime ) { + transitionTo(RELEASED); + Timer = millis(); + } + break; + case RELEASED: + transitionTo(IDLE); + break; + } + return state; // Let the world know which state we're in. +} + +KeyState 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; +} + +void Keypad::transitionTo(KeyState nextState) { + state = nextState; + stateChanged = true; + if (keypadEventListener!=NULL){ + keypadEventListener(currentKey); + } +} + +void Keypad::initializePins() { + //configure column pin modes and states + for (byte C=0; C= 100 +#include "Arduino.h" // for digitalRead, digitalWrite, etc +#else +#include "WProgram.h" +#endif + +#define OFF LOW +#define ON HIGH + +#define CLOSED LOW +#define OPEN HIGH + +#define makeKeymap(x) ((char*)x) + +typedef char KeypadEvent; + +typedef enum {IDLE, PRESSED, HOLD, RELEASED} KeyState; // KeyState was KeypadState + +// Made changes according to this post http://arduino.cc/forum/index.php?topic=58337.0 +// by Nick Gammon. Thanks for the input Nick. :) It actually saved 78 bytes for me. +typedef struct { + byte rows; + byte columns; +} KeypadSize; + +const char NO_KEY = '\0'; +#define KEY_RELEASED NO_KEY + +class Keypad { +public: + Keypad(char *userKeymap, byte *row, byte *col, byte numRows, byte numCols); + + void begin(char *userKeymap); + char getKey(); + KeyState getState(); + void setDebounceTime(unsigned int); + void setHoldTime(unsigned int); + void addEventListener(void (*listener)(char)); + // New methods + char waitForKey(); + boolean keyStateChanged(); + + //added by Daniel Kern + char* getBuffer(); + char* growBuffer(char key); + void clearBuffer(); + +private: + void transitionTo(KeyState); + void initializePins(); + + char *keymap; + byte *rowPins; + byte *columnPins; + KeypadSize size; + KeyState state; + char currentKey; + unsigned int debounceTime; + unsigned int holdTime; + void (*keypadEventListener)(char); + + // New methods - 2011-12-23 + boolean scanKeys(); + KeyState getKeyState(); + + // New members - 2011-12-23 + boolean buttons; + boolean stateChanged; + + //added by Daniel Kern + char keyBuffer[5]; +}; + +#endif + +/* +|| @changelog +|| | 2.0 2011-12-29 - Mark Stanley : Added waitForKey(). +|| | 2.0 2011-12-23 - Mark Stanley : Added the public function keyStateChanged(). +|| | 2.0 2011-12-23 - Mark Stanley : Added the private function scanKeys(). +|| | 2.0 2011-12-23 - Mark Stanley : Moved the Finite State Machine into the function getKeyState(). +|| | 2.0 2011-12-23 - Mark Stanley : Removed the member variable lastUdate. Not needed after rewrite. +|| | 1.8 2011-11-21 - Mark Stanley : Added test to determine which header file to compile, +|| | WProgram.h or Arduino.h. +|| | 1.8 2009-07-08 - Alexander Brevig : No longer uses arrays +|| | 1.7 2009-06-18 - Alexander Brevig : This library is a Finite State Machine every time a state changes +|| | the keypadEventListener will trigger, if set +|| | 1.7 2009-06-18 - Alexander Brevig : Added setDebounceTime setHoldTime specifies the amount of +|| | microseconds before a HOLD state triggers +|| | 1.7 2009-06-18 - Alexander Brevig : Added transitionTo +|| | 1.6 2009-06-15 - Alexander Brevig : Added getState() and state variable +|| | 1.5 2009-05-19 - Alexander Brevig : Added setHoldTime() +|| | 1.4 2009-05-15 - Alexander Brevig : Added addEventListener +|| | 1.3 2009-05-12 - Alexander Brevig : Added lastUdate, in order to do simple debouncing +|| | 1.2 2009-05-09 - Alexander Brevig : Changed getKey() +|| | 1.1 2009-04-28 - Alexander Brevig : Modified API, and made variables private +|| | 1.0 2007-XX-XX - Mark Stanley : Initial Release +|| # +*/