driver to control n by m matrix keyboard with external pull-ups on columns

Dependents:   LoopCounter HelloKeypad MultiKey EventKeypad ... more

Files at this revision

API Documentation at this revision

Comitter:
Hotboards
Date:
Fri Mar 04 02:37:55 2016 +0000
Parent:
1:975a5c527e8e
Commit message:
first fucntional release

Changed in this revision

Hotboards_keypad.cpp Show annotated file Show diff for this revision Revisions of this file
Hotboards_keypad.h Show annotated file Show diff for this revision Revisions of this file
diff -r 975a5c527e8e -r e870110f753b Hotboards_keypad.cpp
--- a/Hotboards_keypad.cpp	Wed Feb 17 01:58:30 2016 +0000
+++ b/Hotboards_keypad.cpp	Fri Mar 04 02:37:55 2016 +0000
@@ -36,6 +36,9 @@
 */
 #include "Hotboards_keypad.h"
 
+#define bitRead( var, bit )           (((var) >> (bit)) & 0x01)
+#define bitWrite( var, bit, val )     (val) ? (var) |= (1<<(bit)) : (var) &= ~(1<<(bit))
+
 // <<constructor>> Allows custom keymap, pin configuration, and keypad sizes.
 Keypad::Keypad(char *userKeymap, DigitalInOut *row, DigitalInOut *col, uint8_t numRows, uint8_t numCols) {
     rowPins = row;
@@ -88,20 +91,19 @@
 // Private : Hardware scan
 void Keypad::scanKeys() {
     // Re-intialize the row pins. Allows sharing these pins with other hardware.
-    for (uint8_t r=0; r<sizeKpd.columns; r++) {
-        columnPins[r].input();
+    for (uint8_t c=0; c<sizeKpd.columns; c++) {
+        columnPins[c].input();
     }
 
     // bitMap stores ALL the keys that are being pressed.
     for (uint8_t r=0; r<sizeKpd.rows; r++) {
         rowPins[r].output();
-        rowPins[r] = 0;  // Begin column pulse output.
+        rowPins[r].write( 0 );  // Begin column pulse output.
         for (uint8_t c=0; c<sizeKpd.columns; c++) {
-            if(!columnPins[c]) bitMap[c] |= ( 1<< r );
-            //bitWrite(bitMap[c], r, !digitalRead(columnPins[c]));  // keypress is active low so invert to high.
+            bitWrite(bitMap[c], r, !columnPins[c].read());  // keypress is active low so invert to high.
         }
         // Set pin to high impedance input. Effectively ends column pulse.
-        rowPins[r] = 1;
+        rowPins[r].write( 1 );
         rowPins[r].input();
     }
 }
@@ -123,7 +125,7 @@
     // Add new keys to empty slots in the key list.
     for (uint8_t c=0; c<sizeKpd.columns; c++) {
         for (uint8_t r=0; r<sizeKpd.rows; r++) {
-            bool button = (bitMap[r] >> c) & 0x01;  //bitRead(bitMap[r],c);
+            bool button = bitRead(bitMap[r],c);
             char keyChar = keymap[c * sizeKpd.rows + r];
             int keyCode = r * sizeKpd.columns + c;
             int idx = findInList (keyCode);
diff -r 975a5c527e8e -r e870110f753b Hotboards_keypad.h
--- a/Hotboards_keypad.h	Wed Feb 17 01:58:30 2016 +0000
+++ b/Hotboards_keypad.h	Fri Mar 04 02:37:55 2016 +0000
@@ -60,30 +60,227 @@
 #define makeKeymap(x) ((char*)x)
 
 
-//class Keypad : public Key, public HAL_obj {
+/** Hotboards_keypad class.
+ *  Used to control general purpose leds
+ *
+ * Example:
+ * @code
+ * #include "mbed.h"
+ * #include "Hotboards_keypad.h"
+ *
+ * char keys[ 4 ][ 4 ] =
+ * {
+ *    {'1','2','3','A'},
+ *    {'4','5','6','B'},
+ *    {'7','8','9','C'},
+ *    {'*','0','#','D'}
+ * };
+ * DigitalInOut rowPins[ 4 ] = {PC_0, PC_1, PC_2, PC_3}; 
+ * DigitalInOut colPins[ 4 ] = {PB_2, PB_1, PB_15, PB_14};
+
+ * Keypad kpd( makeKeymap( keys ), rowPins, colPins, 4, 4 );
+
+ * int main( void ) 
+ * {
+ *    while(1){
+ *       char key = keypad.getKey( );
+ *       if( key ){
+ *           // do something with key
+ *       }
+ *    }
+ * }
+ * @endcode
+ */
 class Keypad : public Key {
-public:
+  public:
 
+    /** Allows custom keymap, pin configuration, and keypad sizes
+      * @param userKeymap pointer to bidimentional array with key definitions
+      * @param row pointer to array with pins conected to rows
+      * @param col pointer to array with pins conected to columns
+      * @param numRows number of rows in use
+      * @param numCols number of columns in use
+      * 
+      * Example:
+      * @code
+      *   char keys[ 4 ][ 4 ] =
+      *   {
+      *     {'1','2','3','A'},
+      *     {'4','5','6','B'},
+      *     {'7','8','9','C'},
+      *     {'*','0','#','D'}
+      *   };
+      *   DigitalInOut rowPins[ 4 ] = {PC_0, PC_1, PC_2, PC_3}; 
+      *   DigitalInOut colPins[ 4 ] = {PB_2, PB_1, PB_15, PB_14};
+      *   Keypad kpd( makeKeymap( keys ), rowPins, colPins, 4, 4 );
+      * @endcode
+      */
     Keypad(char *userKeymap, DigitalInOut *row, DigitalInOut *col, uint8_t numRows, uint8_t numCols);
 
+    /** Returns a single key only. Retained for backwards compatibility.
+      * @return key pressed (user defined key)
+      * 
+      * Example:
+      * @code
+      *   char key = keypad.getKey( );
+      *   if( key ){
+      *     // do something with key
+      *   }
+      * @endcode
+      */
+    char getKey(void);
+    
+    /** Populate the key list (check public key array).
+      * @return true if user pressed any key(s)
+      * 
+      * Example:
+      * @code
+      * if( kpd.getKeys( ) ){
+      *   // you need to poll the array kpd.key[]
+      *   for( int i=0 ; i<LIST_MAX ; i++ ){
+      *     if( kpd.key[ i ].stateChanged ){ 
+      *       chat = kpd.key[ i ].kchar;
+      *     }
+      * }
+      * @endcode
+      */
+    bool getKeys(void);
+    
+    /** Get the state of the first key on the list of active keys
+      * @return key[0].kstate
+      * 
+      * Example:
+      * @code
+      *   if(kpd.getState() == PRESSED ){
+      *     // do something
+      *   }
+      * @endcode
+      */
+    KeyState getState(void);
+    
+    /** Let the user define a keymap - assume the same row/column 
+      * count as defined in constructor
+      * @param userKeymap pointer to user keymap
+      * 
+      * Example:
+      * @code
+      *   // lets assume user wnats to change the keymap
+      *   kpd.begin( makeKeymap( NewKeys )),
+      * @endcode
+      */
+    void begin(char *userKeymap);
+    
+    /** Return a true if the selected key is pressed. Is neccesary 
+      * to call getKeys function first
+      * @return key pressed (user defined key)
+      * 
+      * Example:
+      * @code
+      *  if( kpd.getKeys( ) ){
+      *    if( kpd.isPressed( '2' ) ){
+      *      // key '2' have been press
+      *    }
+      *  } 
+      * @endcode
+      */
+    bool isPressed(char keyChar);
+    
+    /** Set a new debounce time (1ms is the minimum value)
+      * @param debounce time in milliseconds
+      * 
+      * Example:
+      * @code
+      *  // change default 10ms debounce time to 20ms
+      *  kpd.setDebounceTime( 20 );
+      * @endcode
+      */
+    void setDebounceTime(uint);
+    
+    /** Set a new time to considered a key is in hold state
+      * @param hold hold time in milliseconds
+      * 
+      * Example:
+      * @code
+      *  // change default 500ms hold time to 250ms
+      *  kpd.setHoldTime( 250 );
+      * @endcode
+      */
+    void setHoldTime(uint);
+    
+    /** Set a callback function to be called everytime an key change its status 
+      * @param listener function to be called
+      * 
+      * Example:
+      * @code
+      *   kpd.addEventListener( keypadEvent );
+      * @endcode
+      */
+    void addEventListener(void (*listener)(char));
+    
+    /** Search by character for a key in the list of active keys.
+      * @return Returns -1 if not found or the index into the list of active keys.
+      * 
+      * Example:
+      * @code
+      *   // kpd.getKeys function needs to be called first
+      *   int index = findInList( '7' );
+      *   if( kpd.key[ index ].stateChanged ){
+      *     // the key change, so do something =)
+      *   }
+      * @endcode
+      */
+    int findInList(char keyChar);
+    
+    /** Search by code for a key in the list of active keys.
+      * @return Returns -1 if not found or the index into the list of active keys.
+      * 
+      * Example:
+      * @code
+      *   // kpd.getKeys function needs to be called first
+      *   int index = findInList( 10 );
+      *   if( kpd.key[ index ].stateChanged ){
+      *     // the key change, so do something =)
+      *   }
+      * @endcode
+      */
+    int findInList(int keyCode);
+    
+    /** lock everything while waiting for a keypress.
+      * @return key pressed 
+      * 
+      * Example:
+      * @code
+      *   char key = kpd.waitForKey();
+      * @endcode
+      */
+    char waitForKey(void);
+    
+    /** Return stateChanged element of the first key from the active list
+      * @return key[0].stateChanged
+      * 
+      * Example:
+      * @code
+      *   if( kpd.keyStateChanged() ){
+      *     // do something
+      *   }
+      * @endcode
+      */
+    bool keyStateChanged(void);
+    
+    /** The number of keys on the key list, key[LIST_MAX]
+      * @return number of keys
+      * 
+      * Example:
+      * @code
+      *   int keyNum = numKeys(); 
+      * @endcode
+      */
+    uint8_t numKeys(void);
+    
     uint bitMap[MAPSIZE];   // 10 row x 16 column array of bits. Except Due which has 32 columns.
     Key key[LIST_MAX];
     unsigned long holdTimer;
 
-    char getKey();
-    bool getKeys();
-    KeyState getState();
-    void begin(char *userKeymap);
-    bool isPressed(char keyChar);
-    void setDebounceTime(uint);
-    void setHoldTime(uint);
-    void addEventListener(void (*listener)(char));
-    int findInList(char keyChar);
-    int findInList(int keyCode);
-    char waitForKey();
-    bool keyStateChanged();
-    uint8_t numKeys();
-
 private:
     unsigned long startTime;
     char *keymap;