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

main.cpp

Committer:
Hotboards
Date:
2016-03-08
Revision:
1:0c22e424ea51
Parent:
0:d8190262fb61

File content as of revision 1:0c22e424ea51:

/* @file   Hotboards_keypad.cpp
|| @version 1.2
|| @author Mark Stanley
|| @contact mstanley@technologist.com
||
||  07/11/12 - Re-modified (from DynamicKeypadJoe2) to use direct-connect kpds
||  02/28/12 - Modified to use I2C i/o G. D. (Joe) Young
||
||
|| @dificulty:  Intermediate
||
|| @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 <ctype.h>.  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().
*/
#include "mbed.h"
#include "Hotboards_keypad.h"
#include <ctype.h>

// Define the keymaps.  The blank spot (lower left) is the space character.
char alphaKeys[ 4 ][ 4 ] =
{
    { 'a' , 'd' , 'g' },
    { 'j' , 'm' , 'p' },
    { 's' , 'v' , 'y' },
    { ' ' , '.' , '#' }
};

char numberKeys[ 4 ][ 4 ] =
{
    { '1' , '2' , '3' },
    { '4' , '5' , '6' },
    { '7' , '8' , '9' },
    { ' ' , '0' , '#' }
};

bool alpha = false;   // Start with the numeric keypad.

// Defines the pins connected to the rows
DigitalInOut rowPins[ 4 ] = { PA_6 , PA_7 , PB_6 , PC_7 };
// Defines the pins connected to the cols
DigitalInOut colPins[ 4 ] = { PA_8 , PB_10 , PB_4 , PB_5 };

// Create two new keypads, one is a number pad and the other is a letter pad.
Keypad numpad( makeKeymap( numberKeys ) , rowPins , colPins , 4 , 4 );
Keypad ltrpad( makeKeymap( alphaKeys ) , rowPins , colPins , 4 , 4 ); 

int startTime;
// For this example we will use the Nucleo LED1 on pin PA_5
DigitalOut led1( LED1 );

// Configures the serial port
Serial pc( USBTX , USBRX );

// Configures a timer
Timer t;

char key;
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 uint8_t buildCount;
static uint8_t pressCount;
static uint8_t kpadState;

// Take care of some special 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;
                }
                pc.printf( "%c" , virtKey );    // Used for testing.
                if( isdigit( key ) || key == ' ' || key == '.' )
                {
                    pc.printf( "%c" , key );
                }
                if( key == '#' )
                {
                    pc.printf( "\n\r" );
                }
                break;
            }
        case HOLD:
            if( key == '#' )            // Toggle between keymaps.
            {
                if( alpha == true )     // We are currently using a keymap with letters
                {
                    alpha = false;      // Now we want a keymap with numbers.
                    led1 = 0;
                }
                else                    // We are currently using a keymap with numbers
                {
                    alpha = true;       // Now we want a keymap with letters.
                }
            }
            else                        // Some key other than '#' was pressed.
            {
                buildStr[ buildCount ++ ] = ( isalpha( key ) ) ? virtKey : key;
                buildStr[ buildCount ] = '\0';
                pc.printf( "\n\r" );
                pc.printf( buildStr );
            }
            break;
        case RELEASED:
            if( buildCount >= sizeof( buildStr ) )  // Our string is full. Start fresh.
            {
                buildCount = 0;
            }
            break;
    }
}

void keypadEvent_ltr( KeypadEvent key )
{
    // in here when in alpha mode.
    kpadState = ltrpad.getState( );
    swOnState( key );
}

void keypadEvent_num( KeypadEvent key )
{
    // in here when using number keypad
    kpadState = numpad.getState( );
    swOnState( key );
}

int main()
{
    // Starts the timer
    t.start( );
    led1 = 0;   // Turns the LED off.
    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
    
    while(1)
    {
        if( alpha )
        {
            key = ltrpad.getKey( );
        }
        else
        {
            key = numpad.getKey( );
        }
        if( alpha && t.read_ms( ) - startTime > 100 )
        {
            // Flash the LED if we are using the letter keymap.
            led1 = !led1;
            startTime = t.read_ms( );
        }
    }
}