This is a demonstration of keypadEvents. It's used to switch between keymaps while using only one keypad.

Dependencies:   Hotboards_keypad mbed

Fork of DynamicKeypad by Roman Valencia

Committer:
Hotboards
Date:
Tue Mar 08 21:28:50 2016 +0000
Revision:
1:0c22e424ea51
Parent:
0:d8190262fb61
first release

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Hotboards 1:0c22e424ea51 1 /* @file Hotboards_keypad.cpp
Hotboards 1:0c22e424ea51 2 || @version 1.2
Hotboards 1:0c22e424ea51 3 || @author Mark Stanley
Hotboards 1:0c22e424ea51 4 || @contact mstanley@technologist.com
Hotboards 1:0c22e424ea51 5 ||
Hotboards 1:0c22e424ea51 6 || 07/11/12 - Re-modified (from DynamicKeypadJoe2) to use direct-connect kpds
Hotboards 1:0c22e424ea51 7 || 02/28/12 - Modified to use I2C i/o G. D. (Joe) Young
Hotboards 1:0c22e424ea51 8 ||
Hotboards 1:0c22e424ea51 9 ||
Hotboards 1:0c22e424ea51 10 || @dificulty: Intermediate
Hotboards 1:0c22e424ea51 11 ||
Hotboards 1:0c22e424ea51 12 || @description
Hotboards 1:0c22e424ea51 13 || | This is a demonstration of keypadEvents. It's used to switch between keymaps
Hotboards 1:0c22e424ea51 14 || | while using only one keypad. The main concepts being demonstrated are:
Hotboards 1:0c22e424ea51 15 || |
Hotboards 1:0c22e424ea51 16 || | Using the keypad events, PRESSED, HOLD and RELEASED to simplify coding.
Hotboards 1:0c22e424ea51 17 || | How to use setHoldTime() and why.
Hotboards 1:0c22e424ea51 18 || | Making more than one thing happen with the same key.
Hotboards 1:0c22e424ea51 19 || | Assigning and changing keymaps on the fly.
Hotboards 1:0c22e424ea51 20 || |
Hotboards 1:0c22e424ea51 21 || | Another useful feature is also included with this demonstration although
Hotboards 1:0c22e424ea51 22 || | it's not really one of the concepts that I wanted to show you. If you look
Hotboards 1:0c22e424ea51 23 || | at the code in the PRESSED event you will see that the first section of that
Hotboards 1:0c22e424ea51 24 || | code is used to scroll through three different letters on each key. For
Hotboards 1:0c22e424ea51 25 || | example, pressing the '2' key will step through the letters 'd', 'e' and 'f'.
Hotboards 1:0c22e424ea51 26 || |
Hotboards 1:0c22e424ea51 27 || |
Hotboards 1:0c22e424ea51 28 || | Using the keypad events, PRESSED, HOLD and RELEASED to simplify coding
Hotboards 1:0c22e424ea51 29 || | Very simply, the PRESSED event occurs imediately upon detecting a pressed
Hotboards 1:0c22e424ea51 30 || | key and will not happen again until after a RELEASED event. When the HOLD
Hotboards 1:0c22e424ea51 31 || | event fires it always falls between PRESSED and RELEASED. However, it will
Hotboards 1:0c22e424ea51 32 || | only occur if a key has been pressed for longer than the setHoldTime() interval.
Hotboards 1:0c22e424ea51 33 || |
Hotboards 1:0c22e424ea51 34 || | How to use setHoldTime() and why
Hotboards 1:0c22e424ea51 35 || | Take a look at keypad.setHoldTime(500) in the code. It is used to set the
Hotboards 1:0c22e424ea51 36 || | time delay between a PRESSED event and the start of a HOLD event. The value
Hotboards 1:0c22e424ea51 37 || | 500 is in milliseconds (mS) and is equivalent to half a second. After pressing
Hotboards 1:0c22e424ea51 38 || | a key for 500mS the HOLD event will fire and any code contained therein will be
Hotboards 1:0c22e424ea51 39 || | executed. This event will stay active for as long as you hold the key except
Hotboards 1:0c22e424ea51 40 || | in the case of bug #1 listed above.
Hotboards 1:0c22e424ea51 41 || |
Hotboards 1:0c22e424ea51 42 || | Making more than one thing happen with the same key.
Hotboards 1:0c22e424ea51 43 || | If you look under the PRESSED event (case PRESSED:) you will see that the '#'
Hotboards 1:0c22e424ea51 44 || | is used to print a new line, Serial.println(). But take a look at the first
Hotboards 1:0c22e424ea51 45 || | half of the HOLD event and you will see the same key being used to switch back
Hotboards 1:0c22e424ea51 46 || | and forth between the letter and number keymaps that were created with alphaKeys[4][5]
Hotboards 1:0c22e424ea51 47 || | and numberKeys[4][5] respectively.
Hotboards 1:0c22e424ea51 48 || |
Hotboards 1:0c22e424ea51 49 || | Assigning and changing keymaps on the fly
Hotboards 1:0c22e424ea51 50 || | You will see that the '#' key has been designated to perform two different functions
Hotboards 1:0c22e424ea51 51 || | depending on how long you hold it down. If you press the '#' key for less than the
Hotboards 1:0c22e424ea51 52 || | setHoldTime() then it will print a new line. However, if you hold if for longer
Hotboards 1:0c22e424ea51 53 || | than that it will switch back and forth between numbers and letters. You can see the
Hotboards 1:0c22e424ea51 54 || | keymap changes in the HOLD event.
Hotboards 1:0c22e424ea51 55 || |
Hotboards 1:0c22e424ea51 56 || |
Hotboards 1:0c22e424ea51 57 || | In addition...
Hotboards 1:0c22e424ea51 58 || | You might notice a couple of things that you won't find in the Arduino language
Hotboards 1:0c22e424ea51 59 || | reference. The first would be #include <ctype.h>. This is a standard library from
Hotboards 1:0c22e424ea51 60 || | the C programming language and though I don't normally demonstrate these types of
Hotboards 1:0c22e424ea51 61 || | things from outside the Arduino language reference I felt that its use here was
Hotboards 1:0c22e424ea51 62 || | justified by the simplicity that it brings to this sketch.
Hotboards 1:0c22e424ea51 63 || | That simplicity is provided by the two calls to isalpha(key) and isdigit(key).
Hotboards 1:0c22e424ea51 64 || | The first one is used to decide if the key that was pressed is any letter from a-z
Hotboards 1:0c22e424ea51 65 || | or A-Z and the second one decides if the key is any number from 0-9. The return
Hotboards 1:0c22e424ea51 66 || | value from these two functions is either a zero or some positive number greater
Hotboards 1:0c22e424ea51 67 || | than zero. This makes it very simple to test a key and see if it is a number or
Hotboards 1:0c22e424ea51 68 || | a letter. So when you see the following:
Hotboards 1:0c22e424ea51 69 || |
Hotboards 1:0c22e424ea51 70 || | if (isalpha(key)) // this tests to see if your key was a letter
Hotboards 1:0c22e424ea51 71 || |
Hotboards 1:0c22e424ea51 72 || | And the following may be more familiar to some but it is equivalent:
Hotboards 1:0c22e424ea51 73 || |
Hotboards 1:0c22e424ea51 74 || | if (isalpha(key) != 0) // this tests to see if your key was a letter
Hotboards 1:0c22e424ea51 75 || |
Hotboards 1:0c22e424ea51 76 || | And Finally...
Hotboards 1:0c22e424ea51 77 || | To better understand how the event handler affects your code you will need to remember
Hotboards 1:0c22e424ea51 78 || | that it gets called only when you press, hold or release a key. However, once a key
Hotboards 1:0c22e424ea51 79 || | is pressed or held then the event handler gets called at the full speed of the loop().
Hotboards 1:0c22e424ea51 80 */
RomanValenciaP 0:d8190262fb61 81 #include "mbed.h"
RomanValenciaP 0:d8190262fb61 82 #include "Hotboards_keypad.h"
RomanValenciaP 0:d8190262fb61 83 #include <ctype.h>
RomanValenciaP 0:d8190262fb61 84
RomanValenciaP 0:d8190262fb61 85 // Define the keymaps. The blank spot (lower left) is the space character.
RomanValenciaP 0:d8190262fb61 86 char alphaKeys[ 4 ][ 4 ] =
RomanValenciaP 0:d8190262fb61 87 {
RomanValenciaP 0:d8190262fb61 88 { 'a' , 'd' , 'g' },
RomanValenciaP 0:d8190262fb61 89 { 'j' , 'm' , 'p' },
RomanValenciaP 0:d8190262fb61 90 { 's' , 'v' , 'y' },
RomanValenciaP 0:d8190262fb61 91 { ' ' , '.' , '#' }
RomanValenciaP 0:d8190262fb61 92 };
RomanValenciaP 0:d8190262fb61 93
RomanValenciaP 0:d8190262fb61 94 char numberKeys[ 4 ][ 4 ] =
RomanValenciaP 0:d8190262fb61 95 {
RomanValenciaP 0:d8190262fb61 96 { '1' , '2' , '3' },
RomanValenciaP 0:d8190262fb61 97 { '4' , '5' , '6' },
RomanValenciaP 0:d8190262fb61 98 { '7' , '8' , '9' },
RomanValenciaP 0:d8190262fb61 99 { ' ' , '0' , '#' }
RomanValenciaP 0:d8190262fb61 100 };
RomanValenciaP 0:d8190262fb61 101
RomanValenciaP 0:d8190262fb61 102 bool alpha = false; // Start with the numeric keypad.
RomanValenciaP 0:d8190262fb61 103
RomanValenciaP 0:d8190262fb61 104 // Defines the pins connected to the rows
RomanValenciaP 0:d8190262fb61 105 DigitalInOut rowPins[ 4 ] = { PA_6 , PA_7 , PB_6 , PC_7 };
RomanValenciaP 0:d8190262fb61 106 // Defines the pins connected to the cols
RomanValenciaP 0:d8190262fb61 107 DigitalInOut colPins[ 4 ] = { PA_8 , PB_10 , PB_4 , PB_5 };
RomanValenciaP 0:d8190262fb61 108
RomanValenciaP 0:d8190262fb61 109 // Create two new keypads, one is a number pad and the other is a letter pad.
RomanValenciaP 0:d8190262fb61 110 Keypad numpad( makeKeymap( numberKeys ) , rowPins , colPins , 4 , 4 );
RomanValenciaP 0:d8190262fb61 111 Keypad ltrpad( makeKeymap( alphaKeys ) , rowPins , colPins , 4 , 4 );
RomanValenciaP 0:d8190262fb61 112
RomanValenciaP 0:d8190262fb61 113 int startTime;
RomanValenciaP 0:d8190262fb61 114 // For this example we will use the Nucleo LED1 on pin PA_5
RomanValenciaP 0:d8190262fb61 115 DigitalOut led1( LED1 );
RomanValenciaP 0:d8190262fb61 116
RomanValenciaP 0:d8190262fb61 117 // Configures the serial port
RomanValenciaP 0:d8190262fb61 118 Serial pc( USBTX , USBRX );
RomanValenciaP 0:d8190262fb61 119
RomanValenciaP 0:d8190262fb61 120 // Configures a timer
RomanValenciaP 0:d8190262fb61 121 Timer t;
RomanValenciaP 0:d8190262fb61 122
RomanValenciaP 0:d8190262fb61 123 char key;
RomanValenciaP 0:d8190262fb61 124 static char virtKey = NO_KEY; // Stores the last virtual key press. (Alpha keys only)
RomanValenciaP 0:d8190262fb61 125 static char physKey = NO_KEY; // Stores the last physical key press. (Alpha keys only)
RomanValenciaP 0:d8190262fb61 126 static char buildStr[ 12 ];
RomanValenciaP 0:d8190262fb61 127 static uint8_t buildCount;
RomanValenciaP 0:d8190262fb61 128 static uint8_t pressCount;
RomanValenciaP 0:d8190262fb61 129 static uint8_t kpadState;
RomanValenciaP 0:d8190262fb61 130
RomanValenciaP 0:d8190262fb61 131 // Take care of some special events.
RomanValenciaP 0:d8190262fb61 132
RomanValenciaP 0:d8190262fb61 133 void swOnState( char key )
RomanValenciaP 0:d8190262fb61 134 {
RomanValenciaP 0:d8190262fb61 135 switch( kpadState )
RomanValenciaP 0:d8190262fb61 136 {
RomanValenciaP 0:d8190262fb61 137 case PRESSED:
RomanValenciaP 0:d8190262fb61 138 if( isalpha( key ) ) // This is a letter key so we're using the letter keymap.
RomanValenciaP 0:d8190262fb61 139 {
RomanValenciaP 0:d8190262fb61 140 if( physKey != key ) // New key so start with the first of 3 characters.
RomanValenciaP 0:d8190262fb61 141 {
RomanValenciaP 0:d8190262fb61 142 pressCount = 0;
RomanValenciaP 0:d8190262fb61 143 virtKey = key;
RomanValenciaP 0:d8190262fb61 144 physKey = key;
RomanValenciaP 0:d8190262fb61 145 }
RomanValenciaP 0:d8190262fb61 146 else // Pressed the same key again...
RomanValenciaP 0:d8190262fb61 147 {
RomanValenciaP 0:d8190262fb61 148 virtKey ++; // so select the next character on that key.
RomanValenciaP 0:d8190262fb61 149 pressCount ++; // Tracks how many times we press the same key.
RomanValenciaP 0:d8190262fb61 150 }
RomanValenciaP 0:d8190262fb61 151 if( pressCount > 2 ) // Last character reached so cycle back to start.
RomanValenciaP 0:d8190262fb61 152 {
RomanValenciaP 0:d8190262fb61 153 pressCount = 0;
RomanValenciaP 0:d8190262fb61 154 virtKey = key;
RomanValenciaP 0:d8190262fb61 155 }
RomanValenciaP 0:d8190262fb61 156 pc.printf( "%c" , virtKey ); // Used for testing.
RomanValenciaP 0:d8190262fb61 157 if( isdigit( key ) || key == ' ' || key == '.' )
RomanValenciaP 0:d8190262fb61 158 {
RomanValenciaP 0:d8190262fb61 159 pc.printf( "%c" , key );
RomanValenciaP 0:d8190262fb61 160 }
RomanValenciaP 0:d8190262fb61 161 if( key == '#' )
RomanValenciaP 0:d8190262fb61 162 {
RomanValenciaP 0:d8190262fb61 163 pc.printf( "\n\r" );
RomanValenciaP 0:d8190262fb61 164 }
RomanValenciaP 0:d8190262fb61 165 break;
RomanValenciaP 0:d8190262fb61 166 }
RomanValenciaP 0:d8190262fb61 167 case HOLD:
RomanValenciaP 0:d8190262fb61 168 if( key == '#' ) // Toggle between keymaps.
RomanValenciaP 0:d8190262fb61 169 {
RomanValenciaP 0:d8190262fb61 170 if( alpha == true ) // We are currently using a keymap with letters
RomanValenciaP 0:d8190262fb61 171 {
RomanValenciaP 0:d8190262fb61 172 alpha = false; // Now we want a keymap with numbers.
RomanValenciaP 0:d8190262fb61 173 led1 = 0;
RomanValenciaP 0:d8190262fb61 174 }
RomanValenciaP 0:d8190262fb61 175 else // We are currently using a keymap with numbers
RomanValenciaP 0:d8190262fb61 176 {
RomanValenciaP 0:d8190262fb61 177 alpha = true; // Now we want a keymap with letters.
RomanValenciaP 0:d8190262fb61 178 }
RomanValenciaP 0:d8190262fb61 179 }
RomanValenciaP 0:d8190262fb61 180 else // Some key other than '#' was pressed.
RomanValenciaP 0:d8190262fb61 181 {
RomanValenciaP 0:d8190262fb61 182 buildStr[ buildCount ++ ] = ( isalpha( key ) ) ? virtKey : key;
RomanValenciaP 0:d8190262fb61 183 buildStr[ buildCount ] = '\0';
RomanValenciaP 0:d8190262fb61 184 pc.printf( "\n\r" );
RomanValenciaP 0:d8190262fb61 185 pc.printf( buildStr );
RomanValenciaP 0:d8190262fb61 186 }
RomanValenciaP 0:d8190262fb61 187 break;
RomanValenciaP 0:d8190262fb61 188 case RELEASED:
RomanValenciaP 0:d8190262fb61 189 if( buildCount >= sizeof( buildStr ) ) // Our string is full. Start fresh.
RomanValenciaP 0:d8190262fb61 190 {
RomanValenciaP 0:d8190262fb61 191 buildCount = 0;
RomanValenciaP 0:d8190262fb61 192 }
RomanValenciaP 0:d8190262fb61 193 break;
RomanValenciaP 0:d8190262fb61 194 }
RomanValenciaP 0:d8190262fb61 195 }
RomanValenciaP 0:d8190262fb61 196
RomanValenciaP 0:d8190262fb61 197 void keypadEvent_ltr( KeypadEvent key )
RomanValenciaP 0:d8190262fb61 198 {
RomanValenciaP 0:d8190262fb61 199 // in here when in alpha mode.
RomanValenciaP 0:d8190262fb61 200 kpadState = ltrpad.getState( );
RomanValenciaP 0:d8190262fb61 201 swOnState( key );
RomanValenciaP 0:d8190262fb61 202 }
RomanValenciaP 0:d8190262fb61 203
RomanValenciaP 0:d8190262fb61 204 void keypadEvent_num( KeypadEvent key )
RomanValenciaP 0:d8190262fb61 205 {
RomanValenciaP 0:d8190262fb61 206 // in here when using number keypad
RomanValenciaP 0:d8190262fb61 207 kpadState = numpad.getState( );
RomanValenciaP 0:d8190262fb61 208 swOnState( key );
RomanValenciaP 0:d8190262fb61 209 }
RomanValenciaP 0:d8190262fb61 210
RomanValenciaP 0:d8190262fb61 211 int main()
RomanValenciaP 0:d8190262fb61 212 {
RomanValenciaP 0:d8190262fb61 213 // Starts the timer
RomanValenciaP 0:d8190262fb61 214 t.start( );
RomanValenciaP 0:d8190262fb61 215 led1 = 0; // Turns the LED off.
RomanValenciaP 0:d8190262fb61 216 ltrpad.begin( makeKeymap( alphaKeys ) );
RomanValenciaP 0:d8190262fb61 217 numpad.begin( makeKeymap( numberKeys ) );
RomanValenciaP 0:d8190262fb61 218 ltrpad.addEventListener( keypadEvent_ltr ); // Add an event listener.
RomanValenciaP 0:d8190262fb61 219 ltrpad.setHoldTime( 500 ); // Default is 1000mS
RomanValenciaP 0:d8190262fb61 220 numpad.addEventListener( keypadEvent_num ); // Add an event listener.
RomanValenciaP 0:d8190262fb61 221 numpad.setHoldTime( 500 ); // Default is 1000mS
RomanValenciaP 0:d8190262fb61 222
RomanValenciaP 0:d8190262fb61 223 while(1)
RomanValenciaP 0:d8190262fb61 224 {
RomanValenciaP 0:d8190262fb61 225 if( alpha )
RomanValenciaP 0:d8190262fb61 226 {
RomanValenciaP 0:d8190262fb61 227 key = ltrpad.getKey( );
RomanValenciaP 0:d8190262fb61 228 }
RomanValenciaP 0:d8190262fb61 229 else
RomanValenciaP 0:d8190262fb61 230 {
RomanValenciaP 0:d8190262fb61 231 key = numpad.getKey( );
RomanValenciaP 0:d8190262fb61 232 }
RomanValenciaP 0:d8190262fb61 233 if( alpha && t.read_ms( ) - startTime > 100 )
RomanValenciaP 0:d8190262fb61 234 {
RomanValenciaP 0:d8190262fb61 235 // Flash the LED if we are using the letter keymap.
RomanValenciaP 0:d8190262fb61 236 led1 = !led1;
RomanValenciaP 0:d8190262fb61 237 startTime = t.read_ms( );
RomanValenciaP 0:d8190262fb61 238 }
RomanValenciaP 0:d8190262fb61 239 }
RomanValenciaP 0:d8190262fb61 240 }
RomanValenciaP 0:d8190262fb61 241