Fork without short circuits

Dependents:   SaveKeypad

Fork of keypad by HM Yoong

No extra hardware is needed besides the wires and switches. The columns are outputs configured with open drain. The rows are inputs configured with pull up resistors. A key press pulls down its row. With scanning the column is determined thereafter.

See SaveKeypad for an example usage.

Files at this revision

API Documentation at this revision

Comitter:
gj_schoneveld
Date:
Sat Nov 03 23:33:52 2012 +0000
Parent:
10:9a9ec143840b
Child:
12:e6623f165199
Commit message:
Added support for polling.

Changed in this revision

keypad.cpp Show annotated file Show diff for this revision Revisions of this file
keypad.h Show annotated file Show diff for this revision Revisions of this file
--- a/keypad.cpp	Fri Nov 02 22:42:28 2012 +0000
+++ b/keypad.cpp	Sat Nov 03 23:33:52 2012 +0000
@@ -6,6 +6,10 @@
     _row0(row0), _row1(row1), _row2(row2), _row3(row3),
     _cols(col0, col1, col2, col3)
 {
+    _rows[0] = &_row0;
+    _rows[1] = &_row1;
+    _rows[2] = &_row2;
+    _rows[3] = &_row3;
     _debounce = debounce_ms;
     _row0.mode(PullUp);
     _row1.mode(PullUp);
@@ -13,71 +17,87 @@
     _row3.mode(PullUp);
     _cols.mode(OpenDrain);
     _cols.output();
-    _setupFallTrigger();
+}
+
+void Keypad::_setupFallTrigger(void)
+{
+    _row0.fall(this, &Keypad::_callback);
+    _row1.fall(this, &Keypad::_callback);
+    _row2.fall(this, &Keypad::_callback);
+    _row3.fall(this, &Keypad::_callback);
 }
 
 void Keypad::Start(void)
 {
+    /* make the columns zero so they can pull rows down */
     _cols = 0x00;
 }
 
 void Keypad::Stop(void)
 {
-    _cols = 0x0F;
+    /* make the columns one so they cannot pull any rows down anymore */
+    _cols = ~0x00;
 }
 
 void Keypad::CallAfterInput(uint32_t (*fptr)(uint32_t index))
 {
     _input.attach(fptr);
+    _setupFallTrigger();
+}
+
+int Keypad::DebouncedScan()
+{
+    int key1 = Scan();
+    
+    /* debounce */
+    wait_ms(_debounce);
+    
+    int key2 = Scan();
+    
+    if (key1 != key2)
+        return -1;
+    else
+        return key1;
 }
 
-void Keypad::_callback(int row, InterruptIn &therow)
+int Keypad::Scan()
 {
-    wait_ms(_debounce);
-    if (therow != 0)
-        return;
+    /* lookup row */
+    int r = -1;
+    for (r = 0; r < row_count; r++) {
+        if (*_rows[r] == 0)
+            break;
+    }
 
+    /* if we didn't find a valid row, return */
+    if (!(0 <= r && r < row_count))
+        return -1;
+
+    /* scan columns to find out which one pulls down the row */ 
     int c = -1;
-    _cols = 0x0E;
-    if (therow == 0)
-        c = 0;
-    else {
-        _cols = 0x0D;
-        if (therow == 0)
-            c = 1;
-        else {
-            _cols = 0x0B;
-            if (therow == 0)
-                c = 2;
-            else
-                c = 3;
-        }
+    for (c = 0; c < col_count; c++) {
+        _cols = ~(1 << c);
+        if (*_rows[r] == 0)
+            break;
     }
-    _input.call(row * 4 + c);
-    Start(); // Re-energize all columns
+
+    /* re-energize all columns */
+    Start();
+
+    /* if we didn't find a valid column, return */
+    if (!(0 <= c && c < col_count))
+        return -1;
+
+    return r * col_count + c;
 }
 
-void Keypad::_cbRow0Fall(void)
-{
-    _callback(0, _row0);
-}
-void Keypad::_cbRow1Fall(void)
+void Keypad::_callback()
 {
-    _callback(1, _row1);
-}
-void Keypad::_cbRow2Fall(void)
-{
-    _callback(2, _row2);
-}
-void Keypad::_cbRow3Fall(void)
-{
-    _callback(3, _row3);
+    /* lookup */
+    int position = DebouncedScan();
+    
+    /* call back a valid position */
+    if (position >= 0)
+        _input.call(position);
 }
 
-void Keypad::_setupFallTrigger(void)
-{
-    _row0.fall(this, &Keypad::_cbRow0Fall);
-    _row1.fall(this, &Keypad::_cbRow1Fall);
-    _row2.fall(this, &Keypad::_cbRow2Fall);
-    _row3.fall(this, &Keypad::_cbRow3Fall);
-}
--- a/keypad.h	Fri Nov 02 22:42:28 2012 +0000
+++ b/keypad.h	Sat Nov 03 23:33:52 2012 +0000
@@ -85,6 +85,14 @@
      */
     void Stop(void);
 
+    /** Scan the keyboard for a debounced pressed key
+     */
+    int DebouncedScan(void);
+
+    /** Scan the keyboard for a pressed key
+     */
+    int Scan(void);
+
     /** User-defined function that to be called when a key is pressed
      *  @param fptr           A function pointer takes a uint32_t and
      *                        returns uint32_t
@@ -92,21 +100,20 @@
     void CallAfterInput(uint32_t (*fptr)(uint32_t));
 
 protected:
+    static const int row_count = 4;
+    static const int col_count = 4;
+
     InterruptIn      _row0;
     InterruptIn      _row1;
     InterruptIn      _row2;
     InterruptIn      _row3;
+    InterruptIn      *_rows[row_count];
     BusInOut         _cols;  // BusOut doesn't support mode() yet; need open drain to prevent short circuits...
     int              _debounce;
     FPointer         _input; // Called after each input
 
-    void _callback(int row, InterruptIn &therow);
-    void _cbRow0Fall(void);
-    void _cbRow1Fall(void);
-    void _cbRow2Fall(void);
-    void _cbRow3Fall(void);
+    void _callback();
     void _setupFallTrigger(void);
-    void _dummy(void) { };
 };
 
 #endif // KEYPAD_H