An interrupt-driven interface to 4x4 keypad.
Dependents: FYPFinalProgram FYPFinalizeProgram KEYS Proyect_Patric_electronic_door_MSC_Ok_ESP ... more
Revision 10:da060f8c03e8, committed 2014-01-01
- Comitter:
- yoonghm
- Date:
- Wed Jan 01 17:45:53 2014 +0000
- Parent:
- 9:e48ba5b4c497
- Commit message:
- Update Keypad library to be used with RTOS.; Support any combination of keypad size below 4x4.
Changed in this revision
diff -r e48ba5b4c497 -r da060f8c03e8 FPointer.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/FPointer.h Wed Jan 01 17:45:53 2014 +0000 @@ -0,0 +1,163 @@ +/* + Copyright (c) 2011 Andy Kirkham + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +#ifndef AJK_FPOINTER_H +#define AJK_FPOINTER_H + +namespace AjK { + +class FPointerDummy; + +/** FPointer - Adds callbacks that take and return a 32bit uint32_t data type. + * + * The Mbed library supplies a callback using the FunctionPointer object as + * defined in FunctionPointer.h However, this callback system does not allow + * the caller to pass a value to the callback. Likewise, the callback itself + * cannot return a value. + * + * FPointer operates in the same way but allows the callback function to be + * passed one arg, a uint32_t value. Additionally, the callback can return + * a single uint32_t value. The reason for using uint32_t is that the Mbed + * and the microcontroller (LPC1768) have a natural data size of 32bits and + * this means we can use the uint32_t as a pointer. See example1.h for more + * information. This example passes an "int" by passing a pointer to that + * int as a 32bit value. Using this technique you can pass any value you like. + * All you have to do is pass a pointer to your value cast to (uint32_t). Your + * callback can the deference it to get the original value. + * + * example2.h shows how to do the same thing but demostrates how to specify + * the callback into a class object/method. + * + * Finally, example3.h shows how to pass multiple values. In this example we + * define a data structure and in the callback we pass a pointer to that + * data structure thus allowing the callback to again get the values. + * + * Note, when passing pointers to variables to the callback, if the callback + * function/method changes that variable's value then it will also change the + * value the caller sees. If C pointers are new to you, you are strongly + * advised to read up on the subject. It's pointers that often get beginners + * into trouble when mis-used. + * + * @see example1.h + * @see example2.h + * @see example3.h + * @see http://mbed.org/handbook/C-Data-Types + * @see http://mbed.org/projects/libraries/svn/mbed/trunk/FunctionPointer.h + */ +class FPointer { + +protected: + + //! C callback function pointer. + uint32_t (*c_callback)(uint32_t); + + //! C++ callback object/method pointer (the object part). + FPointerDummy *obj_callback; + + //! C++ callback object/method pointer (the method part). + uint32_t (FPointerDummy::*method_callback)(uint32_t); + +public: + + /** Constructor + */ + FPointer() { + c_callback = NULL; + obj_callback = NULL; + method_callback = NULL; + } + + /** attach - Overloaded attachment function. + * + * Attach a C type function pointer as the callback. + * + * Note, the callback function prototype must be:- + * @code + * uint32_t myCallbackFunction(uint32_t); + * @endcode + * @param A C function pointer to call. + */ + void attach(uint32_t (*function)(uint32_t) = 0) { c_callback = function; } + + /** attach - Overloaded attachment function. + * + * Attach a C++ type object/method pointer as the callback. + * + * Note, the callback method prototype must be:- + * @code + * public: + * uint32_t myCallbackFunction(uint32_t); + * @endcode + * @param A C++ object pointer. + * @param A C++ method within the object to call. + */ + template<class T> + void attach(T* item, uint32_t (T::*method)(uint32_t)) { + obj_callback = (FPointerDummy *)item; + method_callback = (uint32_t (FPointerDummy::*)(uint32_t))method; + } + + /** call - Overloaded callback initiator. + * + * call the callback function. + * + * @param uint32_t The value to pass to the callback. + * @return uint32_t The value the callback returns. + */ + uint32_t call(uint32_t arg) { + if (c_callback != NULL) { + return (*c_callback)(arg); + } + else { + if (obj_callback != NULL && method_callback != NULL) { + return (obj_callback->*method_callback)(arg); + } + } + return (uint32_t)NULL; + } + + /** call - Overloaded callback initiator. + * + * Call the callback function without passing an argument. + * The callback itself is passed NULL. Note, the callback + * prototype should still be <b>uint32_t callback(uint32_t)</b>. + * + * @return uint32_t The value the callback returns. + */ + uint32_t call(void) { + if (c_callback != NULL) { + return (*c_callback)((uint32_t)NULL); + } + else { + if (obj_callback != NULL && method_callback != NULL) { + return (obj_callback->*method_callback)((uint32_t)NULL); + } + } + return (uint32_t)NULL; + } +}; + +}; // namespace AjK ends + +using namespace AjK; + +#endif
diff -r e48ba5b4c497 -r da060f8c03e8 Keypad.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Keypad.cpp Wed Jan 01 17:45:53 2014 +0000 @@ -0,0 +1,157 @@ +#include "Keypad.h" + +extern Serial PC; + +void Keypad::_cbRow0Rise() +{ + _checkIndex(0, _rows[0]); +} + +void Keypad::_cbRow1Rise() +{ + _checkIndex(1, _rows[1]); +} + +void Keypad::_cbRow2Rise() +{ + _checkIndex(2, _rows[2]); +} + +void Keypad::_cbRow3Rise() +{ + _checkIndex(3, _rows[3]); +} + +void +Keypad::_setupRiseTrigger +( +) +{ + if (_rows[0]) { + _rows[0]->rise(this, &Keypad::_cbRow0Rise); + } + + if (_rows[1]) { + _rows[1]->rise(this, &Keypad::_cbRow1Rise); + } + + if (_rows[2]) { + _rows[2]->rise(this, &Keypad::_cbRow2Rise); + } + + if (_rows[3]) { + _rows[3]->rise(this, &Keypad::_cbRow3Rise); + } +} + + +Keypad::Keypad +(PinName r0 +,PinName r1 +,PinName r2 +,PinName r3 +,PinName c0 +,PinName c1 +,PinName c2 +,PinName c3 +,int debounce_ms +) +{ + PinName rPins[4] = {r0, r1, r2, r3}; + PinName cPins[4] = {c0, c1, c2, c3}; + + for (int i = 0; i < 4; i++) { + _rows[i] = NULL; + _cols[i] = NULL; + } + + _nRow = 0; + for (int i = 0; i < 4; i++) { + if (rPins[i] != NC) { + _rows[i] = new InterruptIn(rPins[i]); + _nRow++; + } else + break; + } + _setupRiseTrigger(); + + _nCol = 0; + for (int i = 0; i < 4; i++) { + if (cPins[i] != NC) { + _cols[i] = new DigitalOut(cPins[i]); + _nCol++; + } else + break; + } + + _debounce = debounce_ms; +} + +Keypad::~Keypad +() +{ + for (int i = 0; i < 4; i++) { + if (_rows[i] != 0) + delete _rows[i]; + } + + for (int i = 0; i < 4; i++) { + if (_cols[i] != 0) + delete _cols[i]; + } +} + +void +Keypad::start +( +) +{ + for (int i = 0; i < _nCol; i++) + _cols[i]->write(1); +} + +void +Keypad::stop +( +) +{ + for (int i = 0; i < _nCol; i++) + _cols[i++]->write(0); +} + +void +Keypad::attach +(uint32_t (*fptr)(uint32_t index) +) +{ + _callback.attach(fptr); +} + +void +Keypad::_checkIndex +(int row +,InterruptIn *therow +) +{ +#ifdef THREAD_H + Thread::wait(_debounce); +#else + wait_ms(_debounce); +#endif + + if (therow->read() == 0) + return; + + int c; + for (c = 0; c < _nCol; c++) { + _cols[c]->write(0); // de-energize the column + if (therow->read() == 0) { + break; + } + } + + int index = row * _nCol + c; + _callback.call(index); + start(); // Re-energize all columns +} +
diff -r e48ba5b4c497 -r da060f8c03e8 Keypad.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Keypad.h Wed Jan 01 17:45:53 2014 +0000 @@ -0,0 +1,126 @@ +/* mbed Keypad library, using user-defined interrupt callback + * Copyright (c) 2012 Yoong Hor Meng + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE + */ + +#ifndef KEYPAD_H +#define KEYPAD_H + +#include "mbed.h" +#include "FPointer.h" + +/** + * An interrupt-based interface to 4x4 keypad. + * + * On each key pressed on a keypad, the index of the key is passed to a + * user-defined function. User is free to define what to be done with the + * input. + * + * Example: + * @code + * #include "mbed.h" + * #include "Keypad.h" + * + * // Define your own keypad values + * char Keytable[] = { '1', '2', '3', 'A', // r0 + * '4', '5', '6', 'B', // r1 + * '7', '8', '9', 'C', // r2 + * '*', '0', '#', 'D' // r3 + * }; + * // c0 c1 c2 c3 + * + * uint32_t Index; + * + * uint32_t cbAfterInput(uint32_t index) { + * Index = index; + * return 0; + * } + * + * int main() { + * // r0 r1 r2 r3 c0 c1 c2 c3 + * Keypad keypad(p21, p22, p23, p24, p25, p26, p27, p28); + * keypad.attach(&cbAfterInput); + * keypad.start(); // energize the keypad via c0-c3 + * + * while (1) { + * __wfi(); + * printf("Interrupted\r\n"); + * printf("Index:%d => Key:%c\r\n", Index, Keytable[Index]); + * } + * } + * @endcode + */ + +class Keypad { +public: + /** Create a 4x4 (row, col) or 4x3 keypad interface: + * + * | Col0 | Col1 | Col2 | Col3 + * -------+------+------+------+----- + * Row 0 | x | x | x | x + * Row 1 | x | x | x | x + * Row 2 | x | x | x | x + * Row 3 | x | x | x | x + * + * @param row<0..3> Row data lines + * @param col<0..3> Column data lines + * @param debounce_ms Debounce in ms (Default to 20ms) + */ + Keypad(PinName r0, PinName r1, PinName r2, PinName r3, + PinName c0, PinName c1, PinName c2, PinName c3, + int debounce_ms = 20); + + /** Destructor + */ + ~Keypad(); + + /** Start the keypad interrupt routines + */ + void start(void); + + /** Stop the keypad interrupt routines + */ + void stop(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 + */ + void attach(uint32_t (*fptr)(uint32_t)); + +protected: + InterruptIn *_rows[4]; + DigitalOut *_cols[4]; + int _debounce; // miliseconds + int _nRow; + int _nCol; + FPointer _callback; // Called after each input + + void _checkIndex(int row, InterruptIn *therow); + void _cbRow0Rise(void); + void _cbRow1Rise(void); + void _cbRow2Rise(void); + void _cbRow3Rise(void); + void _setupRiseTrigger(void); +}; + +#endif // KEYPAD_H +
diff -r e48ba5b4c497 -r da060f8c03e8 keypad.cpp --- a/keypad.cpp Tue Jan 31 00:31:58 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,67 +0,0 @@ -#include "keypad.h" - -Keypad::Keypad(PinName row3, PinName row2, PinName row1, PinName row0, - PinName col3, PinName col2, PinName col1, PinName col0, - int debounce_ms): - _row0(row0), _row1(row1), _row2(row2), _row3(row3), - _cols(col0, col1, col2, col3) { - _debounce = debounce_ms; - _setupRiseTrigger(); -} - -void Keypad::Start(void) { - _cols = 0x0F; -} - -void Keypad::Stop(void) { - _cols = 0x00; -} - -void Keypad::CallAfterInput(uint32_t (*fptr)(uint32_t index)) { - _input.attach(fptr); -} - -void Keypad::_callback(int row, InterruptIn &therow) { - wait_ms(_debounce); - if (therow != 1) - return; - - int c = -1; - _cols = _cols & 0x0E; - if (therow == 0) - c = 0; - else { - _cols = _cols & 0x0D; - if (therow == 0) - c = 1; - else { - _cols = _cols & 0x0B; - if (therow == 0) - c = 2; - else - c = 3; - } - } - _input.call(row * 4 + c); - Start(); // Re-energize all columns -} - -void Keypad::_cbRow0Rise(void) { - _callback(0, _row0); -} -void Keypad::_cbRow1Rise(void) { - _callback(1, _row1); -} -void Keypad::_cbRow2Rise(void) { - _callback(2, _row2); -} -void Keypad::_cbRow3Rise(void) { - _callback(3, _row3); -} - -void Keypad::_setupRiseTrigger(void) { - _row0.rise(this, &Keypad::_cbRow0Rise); - _row1.rise(this, &Keypad::_cbRow1Rise); - _row2.rise(this, &Keypad::_cbRow2Rise); - _row3.rise(this, &Keypad::_cbRow3Rise); -} \ No newline at end of file
diff -r e48ba5b4c497 -r da060f8c03e8 keypad.h --- a/keypad.h Tue Jan 31 00:31:58 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,111 +0,0 @@ -/* mbed Keypad library, using user-defined interrupt callback - * Copyright (c) 2012 Yoong Hor Meng - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE - */ - -#ifndef KEYPAD_H -#define KEYPAD_H - -#include "mbed.h" -#include "FPointer.h" - -/** - * An interrupt-based interface to 4x4 keypad. - * - * On each key pressed on a keypad, the index of the key is passed to a - * user-defined function. User is free to define what to be done with the - * input. - * - * This library makes use of - * @see http://mbed.org/cookbook/FPointer by Andy Kirkham - * - * Example: - * @code - * #include "mbed.h" - * #include "keypad.h" - * - * // Define your own keypad values - * char Keytable[] = { '1', '2', '3', 'A', - * '4', '5', '6', 'B', - * '7', '8', '9', 'C', - * '*', '0', '#', 'D' - * }; - * - * uint32_t cbAfterInput(uint32_t index) { - * printf("Index:%d => Key:%c\n", key, Keytable[index]); - * return 0; - * } - * - * int main() { - * Keypad keypad(p25, p26, p27, p28, p21, p22, p23, p24); - * keypad.CallAfterInput(&cbAfterInput); - * keypad.Start(); - * - * while (1) { - * wait_ms(100); - * } - * } - * @endcode - */ -class Keypad { -public: - /** Create a Keypad interface - * - * @param row<3..0> Row data lines - * @param col<3..0> Column data lines - * @param debounce_ms Debounce in ms (Default to 20ms) - */ - Keypad(PinName row3, PinName row2, PinName row1, PinName row0, - PinName col3, PinName col2, PinName col1, PinName col0, - int debounce_ms = 20); - - /** Start the keypad interrupt routines - */ - void Start(void); - - /** Stop the keypad interrupt routines - */ - void Stop(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 - */ - void CallAfterInput(uint32_t (*fptr)(uint32_t)); - -protected: - InterruptIn _row0; - InterruptIn _row1; - InterruptIn _row2; - InterruptIn _row3; - BusOut _cols; - int _debounce; - FPointer _input; // Called after each input - - void _callback(int row, InterruptIn &therow); - void _cbRow0Rise(void); - void _cbRow1Rise(void); - void _cbRow2Rise(void); - void _cbRow3Rise(void); - void _setupRiseTrigger(void); - void _dummy(void) { }; -}; - -#endif // KEYPAD_H \ No newline at end of file