diff --git a/Keypad_I2C.cpp b/Keypad_I2C.cpp new file mode 100644 index 0000000..2bd171e --- /dev/null +++ b/Keypad_I2C.cpp @@ -0,0 +1,119 @@ +/* +|| +|| @file Keypad_I2C.h +|| @version 2.0 - PCF8575 support added by Paul Williamson +|| @author G. D. (Joe) Young, ptw +|| @contact "G. D. (Joe) Young" +|| +|| @description +|| | Keypad_I2C provides an interface for using matrix keypads that +|| | are attached with I2C port expanders. It supports multiple keypads, +|| | user selectable pins, and user defined 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_I2C.h" + +// Let the user define a keymap - assume the same row/column count as defined in constructor +void Keypad_I2C::begin(char *userKeymap) { + Keypad::begin(userKeymap); + TwoWire::begin(); + pinState = pinState_set( ); +} + + +// Initialize I2C +void Keypad_I2C::begin(void) { + TwoWire::begin(); +// pinState = 0xff; + pinState = pinState_set( ); +} + +// Initialize I2C +void Keypad_I2C::begin(byte address) { + i2caddr = address; + TwoWire::begin(address); +// pinState = 0xff; + pinState = pinState_set( ); +} + +// Initialize I2C +void Keypad_I2C::begin(int address) { + i2caddr = address; + TwoWire::begin(address); +// pinState = 0xff; + pinState = pinState_set( ); +} + + +void Keypad_I2C::pin_write(byte pinNum, boolean level) { + word mask = 1< 1) { + pinVal |= TwoWire::read( ) << 8; + } + pinVal &= mask; + if( pinVal == mask ) { + return 1; + } else { + return 0; + } +} + +void Keypad_I2C::port_write( word i2cportval ) { + TwoWire::beginTransmission((int)i2caddr); + TwoWire::write( i2cportval & 0x00FF); + if (i2cwidth > 1) { + TwoWire::write( i2cportval >> 8 ); + } + TwoWire::endTransmission(); + pinState = i2cportval; +} // port_write( ) + +word Keypad_I2C::pinState_set( ) { + TwoWire::requestFrom( (int)i2caddr, (int)i2cwidth ); + pinState = TwoWire::read( ); + if (i2cwidth > 1) { + pinState |= TwoWire::read( ) << 8; + } + return pinState; +} // set_pinState( ) + + +/* +|| @changelog +|| | +|| | 2.0 2013-08-31 - Paul Williamson : Added i2cwidth parameter for PCF8575 support +|| | +|| | 1.0 2012-07-12 - Joe Young : Initial Release +|| # +*/ diff --git a/Keypad_I2C.h b/Keypad_I2C.h new file mode 100644 index 0000000..e0af197 --- /dev/null +++ b/Keypad_I2C.h @@ -0,0 +1,85 @@ +/* +|| +|| @file Keypad_I2C.h +|| @version 2.0 - PCF8575 support added by Paul Williamson +|| @author G. D. (Joe) Young, ptw +|| @contact "G. D. (Joe) Young" +|| +|| @description +|| | Keypad_I2C provides an interface for using matrix keypads that +|| | are attached to I2C port expanders. It supports multiple keypads, +|| | user selectable pins, and user defined 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 +|| # +|| +*/ + +#ifndef KEYPAD_I2C_H +#define KEYPAD_I2C_H + +#include "Keypad.h" +#include "Wire.h" + +#define PCF8574 1 // PCF8574 I/O expander device is 1 byte wide +#define PCF8575 2 // PCF8575 I/O expander device is 2 bytes wide + +class Keypad_I2C : public Keypad, public TwoWire { +public: + Keypad_I2C(char* userKeymap, byte* row, byte* col, byte numRows, byte numCols, byte address, byte width = 1) : + Keypad(userKeymap, row, col, numRows, numCols) { i2caddr = address; i2cwidth = width;} + + + // Keypad function + void begin(char *userKeymap); + // Wire function + void begin(void); + // Wire function + void begin(byte address); + // Wire function + void begin(int address); + + void pin_mode(byte pinNum, byte mode) {} + void pin_write(byte pinNum, boolean level); + int pin_read(byte pinNum); + // read initial value for pinState + word pinState_set( ); + // write a whole byte or word (depending on the port expander chip) to i2c port + void port_write( word i2cportval ); + +private: + // I2C device address + byte i2caddr; + // I2C port expander device width in bytes (1 for 8574, 2 for 8575) + byte i2cwidth; + // I2C pin_write state persistant storage + // least significant byte is used for 8-bit port expanders + word pinState; +}; + + + +#endif // KEYPAD_I2C_H + +/* +|| @changelog +|| | +|| | 2.0 2013-08-31 - Paul Williamson : Added i2cwidth parameter for PCF8575 support +|| | +|| | 1.0 2012-07-12 - Joe Young : Initial Release +|| # +*/ diff --git a/docs/I2CKeypadDatasheet.pdf b/docs/I2CKeypadDatasheet.pdf new file mode 100644 index 0000000..dbb5466 Binary files /dev/null and b/docs/I2CKeypadDatasheet.pdf differ diff --git a/docs/PCF8574.pdf b/docs/PCF8574.pdf new file mode 100644 index 0000000..09a0347 Binary files /dev/null and b/docs/PCF8574.pdf differ diff --git a/docs/PCF8575C.pdf b/docs/PCF8575C.pdf new file mode 100644 index 0000000..3629e67 Binary files /dev/null and b/docs/PCF8575C.pdf differ diff --git a/docs/PCF8575C_Breakout-v10.pdf b/docs/PCF8575C_Breakout-v10.pdf new file mode 100644 index 0000000..17701a5 Binary files /dev/null and b/docs/PCF8575C_Breakout-v10.pdf differ diff --git a/docs/pcf8575.pdf b/docs/pcf8575.pdf new file mode 100644 index 0000000..634f013 Binary files /dev/null and b/docs/pcf8575.pdf differ diff --git a/docs/usingKeypad_I2C.pdf b/docs/usingKeypad_I2C.pdf new file mode 100644 index 0000000..97f6960 Binary files /dev/null and b/docs/usingKeypad_I2C.pdf differ diff --git a/examples/CustomKeypad_I2C/CustomKeypad_I2C.ino b/examples/CustomKeypad_I2C/CustomKeypad_I2C.ino new file mode 100644 index 0000000..4330526 --- /dev/null +++ b/examples/CustomKeypad_I2C/CustomKeypad_I2C.ino @@ -0,0 +1,44 @@ +/* @file CustomKeypad.pde +|| @version 1.0 +|| @author Alexander Brevig +|| @contact alexanderbrevig@gmail.com +|| +|| @description +|| | Demonstrates changing the keypad size and key values. +|| # + Use with I2C i/o G. D. (Joe) Young Feb 28/12 +*/ +#include +#include // GDY120705 +#include + +#define I2CADDR 0x21 + +const byte ROWS = 4; //four rows +const byte COLS = 4; //four columns +//define the cymbols on the buttons of the keypads +char hexaKeys[ROWS][COLS] = { + {'0','1','2','3'}, + {'4','5','6','7'}, + {'8','9','A','B'}, + {'C','D','E','F'} +}; +byte rowPins[ROWS] = {3, 2, 1, 0}; //connect to the row pinouts of the keypad +byte colPins[COLS] = {7, 6, 5, 4}; //connect to the column pinouts of the keypad + +//initialize an instance of class NewKeypad +Keypad_I2C customKeypad( makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS, I2CADDR); + +void setup(){ +// Wire.begin( ); + customKeypad.begin( ); // GDY120705 + Serial.begin(9600); +} + +void loop(){ + char customKey = customKeypad.getKey(); + + if (customKey != NO_KEY){ + Serial.println(customKey); + } +} diff --git a/examples/DynamicKeypad_I2C/DynamicKeypad_I2C.ino b/examples/DynamicKeypad_I2C/DynamicKeypad_I2C.ino new file mode 100644 index 0000000..2ab429c --- /dev/null +++ b/examples/DynamicKeypad_I2C/DynamicKeypad_I2C.ino @@ -0,0 +1,216 @@ +/* @file DynamicKeypad.pde +|| @version 1.0 +|| @author Mark Stanley +|| @contact mstanley@technologist.com +|| +|| @dificulty: Intermediate +|| +|| *** THE KEYPAD REQUIRES PULL-UP RESISTORS ON THE ROW PINS. *** +|| +|| @description +|| | This is a demonstration of keypadEvents. It's used to switch between keymaps +|| | while using only one keypad. The main concepts being demonstrated are: +|| | +|| | Using the keypad events, PRESSED, HOLD and RELEASED to simplify coding. +|| | How to use setHoldTime() and why. +|| | Making more than one thing happen with the same key. +|| | Assigning and changing keymaps on the fly. +|| | +|| | Another useful feature is also included with this demonstration although +|| | it's not really one of the concepts that I wanted to show you. If you look +|| | at the code in the PRESSED event you will see that the first section of that +|| | code is used to scroll through three different letters on each key. For +|| | example, pressing the '2' key will step through the letters 'd', 'e' and 'f'. +|| | +|| | +|| | Using the keypad events, PRESSED, HOLD and RELEASED to simplify coding +|| | Very simply, the PRESSED event occurs imediately upon detecting a pressed +|| | key and will not happen again until after a RELEASED event. When the HOLD +|| | event fires it always falls between PRESSED and RELEASED. However, it will +|| | only occur if a key has been pressed for longer than the setHoldTime() interval. +|| | +|| | How to use setHoldTime() and why +|| | Take a look at keypad.setHoldTime(500) in the code. It is used to set the +|| | time delay between a PRESSED event and the start of a HOLD event. The value +|| | 500 is in milliseconds (mS) and is equivalent to half a second. After pressing +|| | a key for 500mS the HOLD event will fire and any code contained therein will be +|| | executed. This event will stay active for as long as you hold the key except +|| | in the case of bug #1 listed above. +|| | +|| | Making more than one thing happen with the same key. +|| | If you look under the PRESSED event (case PRESSED:) you will see that the '#' +|| | is used to print a new line, Serial.println(). But take a look at the first +|| | half of the HOLD event and you will see the same key being used to switch back +|| | and forth between the letter and number keymaps that were created with alphaKeys[4][5] +|| | and numberKeys[4][5] respectively. +|| | +|| | Assigning and changing keymaps on the fly +|| | You will see that the '#' key has been designated to perform two different functions +|| | depending on how long you hold it down. If you press the '#' key for less than the +|| | setHoldTime() then it will print a new line. However, if you hold if for longer +|| | than that it will switch back and forth between numbers and letters. You can see the +|| | keymap changes in the HOLD event. +|| | +|| | +|| | In addition... +|| | You might notice a couple of things that you won't find in the Arduino language +|| | reference. The first would be #include . This is a standard library from +|| | the C programming language and though I don't normally demonstrate these types of +|| | things from outside the Arduino language reference I felt that its use here was +|| | justified by the simplicity that it brings to this sketch. +|| | That simplicity is provided by the two calls to isalpha(key) and isdigit(key). +|| | The first one is used to decide if the key that was pressed is any letter from a-z +|| | or A-Z and the second one decides if the key is any number from 0-9. The return +|| | value from these two functions is either a zero or some positive number greater +|| | than zero. This makes it very simple to test a key and see if it is a number or +|| | a letter. So when you see the following: +|| | +|| | if (isalpha(key)) // this tests to see if your key was a letter +|| | +|| | And the following may be more familiar to some but it is equivalent: +|| | +|| | if (isalpha(key) != 0) // this tests to see if your key was a letter +|| | +|| | And Finally... +|| | To better understand how the event handler affects your code you will need to remember +|| | that it gets called only when you press, hold or release a key. However, once a key +|| | is pressed or held then the event handler gets called at the full speed of the loop(). +|| | +|| | *** THE KEYPAD REQUIRES PULL-UP RESISTORS ON THE ROW PINS. *** +|| # + + Modified to use I2C i/o G. D. (Joe) Young - Feb 28/12 + Back modified (from DynamicKeypadJoe2) to use direct-connect + kpds - July 11/12 +*/ +#include +#include + +const byte ROWS = 4; //four rows +const byte COLS = 3; //three columns +// Define the keymaps. The blank spot (lower left) is the space character. +char alphaKeys[ROWS][COLS] = { + { 'a','d','g' }, + { 'j','m','p' }, + { 's','v','y' }, + { ' ','.','#' } +}; + +char numberKeys[ROWS][COLS] = { + { '1','2','3' }, + { '4','5','6' }, + { '7','8','9' }, + { ' ','0','#' } +}; + +boolean alpha = false; // Start with the numeric keypad. + +byte rowPins[ROWS] = {2, 3, 4, 5}; //connect to the row pinouts of the keypad +byte colPins[COLS] = {6, 7, 8}; //connect to the column pinouts of the keypad + +//create a new Keypad +Keypad numpad( makeKeymap(numberKeys), rowPins, colPins, sizeof(rowPins), sizeof(colPins) ); +Keypad ltrpad( makeKeymap(alphaKeys), rowPins, colPins, sizeof(rowPins), sizeof(colPins) ); + + +unsigned long startTime; +const byte ledPin = 13; // Use the LED on pin 13. + +void setup() { + Serial.begin(9600); + pinMode(ledPin, OUTPUT); + digitalWrite(ledPin, LOW); // Turns the LED on. + ltrpad.begin( makeKeymap(alphaKeys) ); + numpad.begin( makeKeymap(numberKeys) ); + ltrpad.addEventListener(keypadEvent_ltr); // Add an event listener. + ltrpad.setHoldTime(500); // Default is 1000mS + numpad.addEventListener(keypadEvent_num); // Add an event listener. + numpad.setHoldTime(500); // Default is 1000mS +} + +char key; + +void loop() { + + if( alpha ) key = ltrpad.getKey( ); else key = numpad.getKey( ); + + if (alpha && millis()-startTime>100) { // Flash the LED if we are using the letter keymap. + digitalWrite(ledPin,!digitalRead(ledPin)); + startTime = millis(); + } +} + +static char virtKey = NO_KEY; // Stores the last virtual key press. (Alpha keys only) +static char physKey = NO_KEY; // Stores the last physical key press. (Alpha keys only) +static char buildStr[12]; +static byte buildCount; +static byte pressCount; + +static byte kpadState; + +// Take care of some special events. + +void keypadEvent_ltr(KeypadEvent key) { +// in here when in alpha mode. + kpadState = ltrpad.getState( ); + swOnState( key ); +} // end ltrs keypad events + +void keypadEvent_num( KeypadEvent key ) { +// in here when using number keypad + kpadState = numpad.getState( ); + swOnState( key ); +} // end numbers keypad events + +void swOnState( char key ) { + + switch( kpadState ) + { + case PRESSED: + if (isalpha(key)) { // This is a letter key so we're using the letter keymap. + if (physKey != key) { // New key so start with the first of 3 characters. + pressCount = 0; + virtKey = key; + physKey = key; + } + else { // Pressed the same key again... + virtKey++; // so select the next character on that key. + pressCount++; // Tracks how many times we press the same key. + } + if (pressCount > 2) { // Last character reached so cycle back to start. + pressCount = 0; + virtKey = key; + } + Serial.print(virtKey); // Used for testing. + } + if (isdigit(key) || key == ' ' || key == '.') Serial.print(key); + if (key == '#') Serial.println(); + break; + + case HOLD: + if (key == '#') { // Toggle between keymaps. + if (alpha == true) { // We are currently using a keymap with letters + // keypad.begin(*numberKeys); // and want to change to numbers. + alpha = false; + digitalWrite(ledPin, LOW); + } + else { // Or, we are currently using a keymap with numbers + // keypad.begin(*alphaKeys); // and want to change to letters. + alpha = true; + } + } + else { // Some key other than '#' was pressed. + buildStr[buildCount++] = (isalpha(key)) ? virtKey : key; + buildStr[buildCount] = '\0'; + Serial.println(); + Serial.println(buildStr); + } + break; + + case RELEASED: + if (buildCount >= sizeof(buildStr)) buildCount = 0; // Our string is full. Start fresh. + break; + + } // end switch-case +}// end switch on state function + diff --git a/examples/EventKeypad_I2C/EventKeypad_I2C.ino b/examples/EventKeypad_I2C/EventKeypad_I2C.ino new file mode 100644 index 0000000..16bbc38 --- /dev/null +++ b/examples/EventKeypad_I2C/EventKeypad_I2C.ino @@ -0,0 +1,79 @@ +/* @file EventSerialKeypad.pde +|| @version 1.0 +|| @author Alexander Brevig +|| @contact alexanderbrevig@gmail.com +|| +|| @description +|| | Demonstrates using the KeypadEvent. +|| # + + Modified to use I2C i/o - G. D. (Joe) Young Feb 28/12 +*/ +#include +#include // GDY120705 +#include + +#define I2CADDR 0x21 + +const byte ROWS = 4; //four rows +const byte COLS = 3; //three columns +char keys[ROWS][COLS] = { + {'1','2','3'}, + {'4','5','6'}, + {'7','8','9'}, + {'*','0','#'} + }; +byte rowPins[ROWS] = {0, 1, 2, 3}; //connect to the row pinouts of the keypad +byte colPins[COLS] = {4, 5, 6}; //connect to the column pinouts of the keypad + +Keypad_I2C keypad = Keypad_I2C( makeKeymap(keys), rowPins, colPins, ROWS, COLS, I2CADDR ); +byte ledPin = 13; + +boolean blink = false; + +void setup(){ + Serial.begin(9600); + keypad.begin( ); // GDY120705 + pinMode(ledPin, OUTPUT); // sets the digital pin as output + digitalWrite(ledPin, HIGH); // sets the LED on + keypad.addEventListener(keypadEvent); //add an event listener for this keypad +} + +void loop(){ + char key = keypad.getKey(); + + if (key) { + Serial.println(key); + } + if (blink){ + digitalWrite(ledPin,!digitalRead(ledPin)); + delay(100); + } +} + +//take care of some special events +void keypadEvent(KeypadEvent key){ + switch (keypad.getState()){ + case PRESSED: + switch (key){ + case '#': digitalWrite(ledPin,!digitalRead(ledPin)); break; + case '*': + digitalWrite(ledPin,!digitalRead(ledPin)); + break; + } + break; + case RELEASED: + switch (key){ + case '*': + digitalWrite(ledPin,!digitalRead(ledPin)); + blink = false; + break; + } + break; + case HOLD: + switch (key){ + case '*': blink = true; break; + } + break; + } +} diff --git a/examples/HelloKeyShr_I2C/HelloKeyShr_I2C.ino b/examples/HelloKeyShr_I2C/HelloKeyShr_I2C.ino new file mode 100644 index 0000000..7d59cbc --- /dev/null +++ b/examples/HelloKeyShr_I2C/HelloKeyShr_I2C.ino @@ -0,0 +1,68 @@ +/* @file HelloKeyShr_I2C.ino + + * Revised to use I2C i/o Feb 26/12 - G. D. Young + * Re-check with Keypad 3.0, arduino 1.0.1 Jul 29/12 + * Add port-type parameter to constructor for Paul + Williamson's modification of the Keypad_I2C library Sept 2/13 + * HelloKeyShr to demonstrate use of I2C port pin sharing Nov 30/13 + +|| @version 1.0 (HelloKeypad.pde original file) +|| @author Alexander Brevig +|| @contact alexanderbrevig@gmail.com +|| +|| @description +|| | Demonstrates the simplest use of the matrix Keypad library. +|| # +*/ +#include +#include +#include +#define I2CADDR 0x20 + +const byte ROWS = 4; //four rows +const byte COLS = 3; //three columns +char keys[ROWS][COLS] = { + {'1','2','3'}, + {'4','5','6'}, + {'7','8','9'}, + {'*','0','#'} +}; +// Digitran keypad, bit numbers of PCF8574 i/o port +byte rowPins[ROWS] = {0, 1, 2, 3}; //connect to the row pinouts of the keypad +byte colPins[COLS] = {4, 5, 6}; //connect to the column pinouts of the keypad + +Keypad_I2C kpd( makeKeymap(keys), rowPins, colPins, ROWS, COLS, I2CADDR, PCF8575 ); + +// toggle LED on PCF8575 bit 7 (P07, IC pin 11) +word portState; +const word ledPin = 0b0000000010000000; + +// use byte-size definitions if using PCF8574 +// byte portState; +// const byte ledPin = 0b10000000; + +void toggleLEDpin( ) { + portState = kpd.pinState_set( ); // save current state of all pins + if( portState & ledPin ) { + portState &= ~ledPin; + } else { + portState |= ledPin; + } + kpd.port_write( portState ); // write modified state to port +} // toggleLEDpin( ) + +void setup(){ + Wire.begin( ); + kpd.begin( makeKeymap(keys) ); + Serial.begin(9600); + Serial.println( "start" ); +} +void loop(){ + + char key = kpd.getKey(); + + if (key){ + Serial.println(key); + if( key == '*' ) toggleLEDpin( ); + } +} diff --git a/examples/HelloKeypadTwo_I2C/HelloKeypadTwo_I2C.ino b/examples/HelloKeypadTwo_I2C/HelloKeypadTwo_I2C.ino new file mode 100644 index 0000000..3a9a324 --- /dev/null +++ b/examples/HelloKeypadTwo_I2C/HelloKeypadTwo_I2C.ino @@ -0,0 +1,115 @@ +/* HelloKeypadTwo_I2C + from original file HelloKeypad.pde +|| @version 1.0 +|| @author Alexander Brevig +|| @contact alexanderbrevig@gmail.com +|| +|| @description +|| | Demonstrates the simplest use of the matrix Keypad library. +|| # + + Revised to use I2C i/o Feb 26/12 - G. D. Young + Check for 2nd keypad implementation - HelloKeypadTwo - Feb 28/12 + + April 5, 2012: + With arduino-1.0, order of calling keypad functions seems to matter + -- kpd2 needs to be first. + + April 9, 2012: The implementation shown here works fine -- apparently + arduino-1.0 changed some aspect of Wire that makes timing more + critical, as I found some changes in behaviour with different values + of SDA, SCL pullup resistors. So, here the Keypad library's event + listener feature is used to create a busy flag for each keypad + that blocks the call to scan the 'other' keypad as long as the first + keypad remains busy. Thus, the I2C bus is completely finished with + one keypad scanning before the other one starts using it. + + Aug 24/12 The problem above was fixed with version 3.0 of the + Keypad library. This example now uses that library and retains the + lockout feature (which is no longer necessary, but may be useful). + +*/ +#include +#include +#include +#define I2CADDR 0x21 + +const byte ROWS = 4; //four rows +const byte COLS = 4; //three columns +char keys[ROWS][COLS] = { + {'1','2','3','+'}, + {'4','5','6','-'}, + {'7','8','9','*'}, + {'C','0','.','='} +}; +// Digitran keypad, bit numbers of PCF8574 i/o port +byte rowPins[ROWS] = {0, 1, 2, 3}; //connect to the row pinouts of the keypad +byte colPins[COLS] = {4, 5, 6, 7}; //connect to the column pinouts of the keypad + +Keypad_I2C kpd( makeKeymap(keys), rowPins, colPins, ROWS, COLS, I2CADDR ); + +#define I2CADDRT 0x22 +const byte ROWSR = 4; //four rows +const byte COLSR = 3; //three columns +char keysR[ROWSR][COLSR] = { + {'a','d','/'}, + {'b','e','%'}, + {'c','f','('}, + {'C','0',')'} +}; +// Digitran keypad, bit numbers of PCF8574 i/o port +byte rowPinsR[ROWSR] = {0, 1, 2, 3}; //connect to the row pinouts of the keypad +byte colPinsR[COLSR] = {4, 5, 6}; //connect to the column pinouts of the keypad + +Keypad_I2C kpdR( makeKeymap(keysR), rowPinsR, colPinsR, ROWSR, COLSR, I2CADDRT ); + +boolean kpdbusy, kpdRbusy; +char key, keyR; + +void setup(){ + Wire.begin( ); + kpdR.begin( makeKeymap(keysR) ); + kpd.begin( makeKeymap(keys) ); + kpdR.addEventListener( block_kpd ); + kpd.addEventListener( block_kpdR ); + kpdbusy = false; + kpdRbusy = false; + Serial.begin(9600); + Serial.println( "start" ); +} + + +void loop(){ + + if( kpdRbusy == false ) key = kpd.getKey( ); + if( kpdbusy == false ) keyR = kpdR.getKey( ); + + if (key){ + Serial.println(key); + } + if( keyR ) { + Serial.println( keyR ); + } +} + +void block_kpd( KeypadEvent anykey ) { + switch( kpdR.getState( ) ) { + case PRESSED: + kpdRbusy = true; + break; + case RELEASED: + kpdRbusy = false; + break; + } // switch on right, kpdR state +} // block_kpd + +void block_kpdR( KeypadEvent anykey ) { + switch( kpd.getState( ) ) { + case PRESSED: + kpdbusy = true; + break; + case RELEASED: + kpdbusy = false; + break; + } // switch on left kpd state +} // block_kpdR diff --git a/examples/HelloKeypad_I2C/HelloKeypad_I2C.pde b/examples/HelloKeypad_I2C/HelloKeypad_I2C.pde new file mode 100644 index 0000000..c0ff0d3 --- /dev/null +++ b/examples/HelloKeypad_I2C/HelloKeypad_I2C.pde @@ -0,0 +1,48 @@ +/* @file HelloKeypad.pde + + Revised to use I2C i/o Feb 26/12 - G. D. Young + Re-check with Keypad 3.0, arduino 1.0.1 Jul 29/12 + Add port-type parameter to constructor for Paul + Williamson's modification of the Keypad_I2C library Sept 2/13 + +|| @version 1.0 +|| @author Alexander Brevig +|| @contact alexanderbrevig@gmail.com +|| +|| @description +|| | Demonstrates the simplest use of the matrix Keypad library. +|| # +*/ +#include +#include +#include +#define I2CADDR 0x22 + +const byte ROWS = 4; //four rows +const byte COLS = 3; //three columns +char keys[ROWS][COLS] = { + {'1','2','3'}, + {'4','5','6'}, + {'7','8','9'}, + {'*','0','#'} +}; +// Digitran keypad, bit numbers of PCF8574 i/o port +byte rowPins[ROWS] = {0, 1, 2, 3}; //connect to the row pinouts of the keypad +byte colPins[COLS] = {4, 5, 6}; //connect to the column pinouts of the keypad + +Keypad_I2C kpd( makeKeymap(keys), rowPins, colPins, ROWS, COLS, I2CADDR, PCF8574 ); + +void setup(){ + Wire.begin( ); + kpd.begin( makeKeymap(keys) ); + Serial.begin(9600); + Serial.println( "start" ); +} +void loop(){ + + char key = kpd.getKey(); + + if (key){ + Serial.println(key); + } +} diff --git a/examples/i2cPins/i2cPins.ino b/examples/i2cPins/i2cPins.ino new file mode 100644 index 0000000..651ea43 --- /dev/null +++ b/examples/i2cPins/i2cPins.ino @@ -0,0 +1,68 @@ +/* Keypad_I2C example + * + * The following functions are extended by Keypad_I2C. They have the same + * parameters and return values as the standard Arduino functions pinMode(), + * digitalWrite(), and digitalRead(). + * + * pin_mode( ) Empty function to maintain compatibility with Keypad.h + * pin_write( ) Writes a HIGH or LOW to a specified pin. + * pin_read( ) Reads a HIGH or LOW from a specified pin. + * + * NOTE: As these are used by the library the sketch author shouldn't have to use + * them directly. + * + * << Constructor >> + * Keypad_I2C(char* userKeymap, byte* row, byte* col, byte numRows, byte numCols, byte address) + * + * + * Keypad function: See Keypad examples. + * + * void begin(char *userKeymap); + * + * + * Wire function: + * + * void begin(byte address); + * + * Stores the I2C address that is needed by pin_read and pin_write. Also, the I2C + * address can be changed at any time by using the following code; + * + * kpd.begin(i2caddress) + * + * + * The Keypad_I2C library inherits and extends the Keypad library and the Wire library. + * That means you MUST #include "Keypad.h" and #include "Wire.h" to make it work. + * + */ +#include +#include +#include + + +const byte ROWS = 4; //four rows +const byte COLS = 3; //three columns +char keys[ROWS][COLS] = { + {'1','2','3'}, + {'4','5','6'}, + {'7','8','9'}, + {'*','0','#'} +}; +byte rowPins[ROWS] = {0, 1, 2, 3}; //connect to the row pinouts of the keypad +byte colPins[COLS] = {4, 5, 6}; //connect to the column pinouts of the keypad + +int i2caddress = 0x22; + +Keypad_I2C kpd = Keypad_I2C( makeKeymap(keys), rowPins, colPins, ROWS, COLS, i2caddress ); + +void setup(){ + Serial.begin(9600); + kpd.begin(); +} + +void loop(){ + char key = kpd.getKey(); + + if (key){ + Serial.println(key); + } +} diff --git a/examples/loopCounteri2c/loopCounteri2c.ino b/examples/loopCounteri2c/loopCounteri2c.ino new file mode 100644 index 0000000..f14841f --- /dev/null +++ b/examples/loopCounteri2c/loopCounteri2c.ino @@ -0,0 +1,54 @@ +#include + +#include + +#include + +#define I2CADDR 0x22 + +const byte ROWS = 4; //four rows +const byte COLS = 3; //three columns +char keys[ROWS][COLS] = { + {'1','2','3'}, + {'4','5','6'}, + {'7','8','9'}, + {'*','0','#'} +}; +byte rowPins[ROWS] = {0, 1, 2, 3}; //connect to the row pinouts of the keypad +byte colPins[COLS] = {4, 5, 6}; //connect to the column pinouts of the keypad + +Keypad_I2C kpd( makeKeymap(keys), rowPins, colPins, ROWS, COLS, I2CADDR ); + +unsigned long loopCount = 0; +unsigned long timer_t = 0; + +void setup(){ + Serial.begin(9600); + kpd.begin( ); + kpd.pin_mode(2, INPUT); + kpd.key_update('a', 0x01, true); + + // Try playing with different debounceTime settings to see how it affects + // the number of times per second your loop will run. If you set it too + // low the library will set it back to 1 mS. + kpd.setDebounceTime(10); // setDebounceTime(mS) +} + +void loop(){ + char key = kpd.getKey(); + + // Report the number of times through the loop in 1 second. This will give + // you a relative idea of just how much the debounceTime has changed the + // speed of your code. If you set a high debounceTime your loopCount will + // look good but your keypad will begin to get unresponsive. + if ((millis() - timer_t) > 1000) { + Serial.print("Your loop code ran "); + Serial.print(loopCount); + Serial.println(" times over the last second"); + loopCount = 0; + timer_t = millis(); + } + loopCount++; + if(key) + Serial.println(key); +} diff --git a/examples/noHeaders/noHeaders.ino b/examples/noHeaders/noHeaders.ino new file mode 100644 index 0000000..e421ce6 --- /dev/null +++ b/examples/noHeaders/noHeaders.ino @@ -0,0 +1,47 @@ +/* Keypad_I2C no headers example + * + * This example demonstrates the need to include three different headers to compile properly. + * + * The Keypad_I2C library inherits and extends the Keypad library and the Wire library. + * That means you MUST also #include "Keypad.h" and #include "Wire.h" to make it work. + * + * + * Start with Sketch->Import Library...->Keypad + * + * Then Sketch->Import Library...->Keypad_I2C + * + * And finally Sketch->Import Library...->Wire + * + * NOTE: The order doesn't matter. + * + * Now the sketch should compile properly. + * + */ + +const byte ROWS = 4; //four rows +const byte COLS = 3; //three columns +char keys[ROWS][COLS] = { + {'1','2','3'}, + {'4','5','6'}, + {'7','8','9'}, + {'*','0','#'} +}; +byte rowPins[ROWS] = {0, 1, 2, 3}; //connect to the row pinouts of the keypad +byte colPins[COLS] = {4, 5, 6}; //connect to the column pinouts of the keypad + +int i2caddress = 0x22; + +Keypad_I2C kpd = Keypad_I2C( makeKeymap(keys), rowPins, colPins, ROWS, COLS, i2caddress ); + +void setup(){ + Serial.begin(9600); + kpd.begin(); +} + +void loop(){ + char key = kpd.getKey(); + + if (key){ + Serial.println(key); + } +} diff --git a/keywords.txt b/keywords.txt new file mode 100644 index 0000000..2dfd681 --- /dev/null +++ b/keywords.txt @@ -0,0 +1,36 @@ +########################################### +# Syntax Coloring Map For Keypad_I2C +########################################### + +########################################### +# Datatypes (KEYWORD1) +########################################### + +Keypad_I2C KEYWORD1 + + +########################################### +# Keypad_I2C Library constants +########################################### + +PCF8574 LITERAL1 +PCF8575 LITERAL1 + + +########################################### +# Methods and Functions (KEYWORD2) +########################################### + +pinState_set KEYWORD2 +port_write KEYWORD2 +begin KEYWORD2 + + +########################################### +# objects created in the example sketches. +########################################### + +numpad KEYWORD3 +ltrpad KEYWORD3 +kpdR KEYWORD3 +