This is a demonstration program which draws a keypad on the LCD and uses the touch screen to allow an operator to key-in an access code. Two possible codes are allowed to grant to different levels of access. Additionally the push button is used to allow an operator to send Moorse Code pulses in to the device which is checked against two characters to determine if there was a match, and if so, access is granted.

Dependencies:   LCD_DISCO_F429ZI mbed TS_DISCO_F429ZI mbed-os BSP_DISCO_F429ZI

Also draws a mushroom on the screen and animates it.

SecurityUnlockDemo-Keypad.cpp

Committer:
Damotclese
Date:
2019-06-01
Revision:
1:316582aec4fb
Child:
3:0e554d8d5a19

File content as of revision 1:316582aec4fb:


// ----------------------------------------------------------------------
// SecurityUnlockDemo-Keypad.cpp
//
// Fredric L. Rice, June 2019
//
// This module maintains the code which performs the keypad functionality
//
// ----------------------------------------------------------------------

#include "mbed.h"                       // The mbed operating system
#include "LCD_DISCO_F429ZI.h"           // For controlling the LCD
#include "TS_DISCO_F429ZI.h"            // For controlling the touch screen
#include "SecurityUnlockDemo-Main.h"    // Bring in the main module
#include "SecurityUnlockDemo-Keypad.h"  // Always include our own header

// ----------------------------------------------------------------------
// Describe data which is defined externally that we may access
//
// ----------------------------------------------------------------------

    // We may be accessing the LCD
    extern LCD_DISCO_F429ZI st_lcd;

    // We may be accessing the touch screen
    extern TS_DISCO_F429ZI st_touchScreen;

// ----------------------------------------------------------------------
// Define local data storage
//
// ----------------------------------------------------------------------

    // In this demonstration we define two access levels, access level 1
    // grants full access to all functionality whereas access level 2 is
    // for accessing less functionality
    static const uint8_t * ACCESS_LEVEL_1 = "31415926";
    static const uint8_t * ACCESS_LEVEL_2 = "2040";

    // When we build the keypad screen, we use the data in this table
    // to position the touch keys rather than use math to determine
    // their locations. The reason why we do this is so that we can
    // use this table to determine which key was pressed on the touch
    // screen, but also we may want to place some keys offset from
    // others. A table gives us greater control over key location.
    // We place 10 pixels between each keypad.
    static KeypadLocation_t st_KeypadInformation[] =
    {
        //                       X,                       Y,  H,  W, Character
        { KEYPAD_LEFT_MARGIN +   0, KEYPAD_TOP_MARGIN +   0, 40, 40, '1' },
        { KEYPAD_LEFT_MARGIN +  60, KEYPAD_TOP_MARGIN +   0, 40, 40, '2' },
        { KEYPAD_LEFT_MARGIN + 120, KEYPAD_TOP_MARGIN +   0, 40, 40, '3' },
        { KEYPAD_LEFT_MARGIN +   0, KEYPAD_TOP_MARGIN +  60, 40, 40, '4' },
        { KEYPAD_LEFT_MARGIN +  60, KEYPAD_TOP_MARGIN +  60, 40, 40, '5' },
        { KEYPAD_LEFT_MARGIN + 120, KEYPAD_TOP_MARGIN +  60, 40, 40, '6' },
        { KEYPAD_LEFT_MARGIN +   0, KEYPAD_TOP_MARGIN + 120, 40, 40, '7' },
        { KEYPAD_LEFT_MARGIN +  60, KEYPAD_TOP_MARGIN + 120, 40, 40, '8' },
        { KEYPAD_LEFT_MARGIN + 120, KEYPAD_TOP_MARGIN + 120, 40, 40, '9' },
        { KEYPAD_LEFT_MARGIN +   0, KEYPAD_TOP_MARGIN + 180, 40, 40, 'C' },
        { KEYPAD_LEFT_MARGIN +  60, KEYPAD_TOP_MARGIN + 180, 40, 40, '0' },
        { KEYPAD_LEFT_MARGIN + 120, KEYPAD_TOP_MARGIN + 180, 40, 40, 'E' },
        {                        0,                       0,  0,  0, '+' }   // End of table
    } ;
    
    // We allow a maximum number of keys to be entered for the access code
    static uint8_t au8_enteredKeys[MAX_SECURITY_DIGITS + 1];
    
    // We keep track of the number of digits entered for the access code
    static uint8_t u8_enteredKeyCount;

// ----------------------------------------------------------------------
// KeypadInit()
//
// Initializes this module's locally-held data
//
// ----------------------------------------------------------------------
void KeypadInit(void)
{
    // Initialize locall-held data in this module
    u8_enteredKeyCount    = 0;
}

// ----------------------------------------------------------------------
// KeypadDisplayEnteredKeys()
//
// This function will display the entered keys, if any, on the display
// on the line defined for the entered keys. It will center the 
// characters.
//
// ----------------------------------------------------------------------
static void KeypadDisplayEnteredKeys(void)
{
    // Display the accumulated security code digits
    st_lcd.DisplayStringAt(1, LINE(ENTERED_KEYS_LINE), au8_enteredKeys, CENTER_MODE);
}

// ----------------------------------------------------------------------
// KeypadProcessEntryCode()
//
// This function will:
//      o Check the size of Level 1 access to see if it matches the
//        number of characters that were entered
//      o Check to see if the Level 1 access code matches the digits
//        entered
//      o Grant Access Level 1 if both the size and the digits match
//
//      o Check the size of Level 2 access to see if it matches the
//        number of characters that were entered
//      o Check to see if the Level 2 access code matches the digits
//        entered
//      o Grant Access Level 2 if both the size and the digits match
//
// ----------------------------------------------------------------------
static void KeypadProcessEntryCode(uint8_t u8_originalKeyCount)
{
    // See if the access code that was entered is level 1
    if (strlen((char *)ACCESS_LEVEL_1) == u8_originalKeyCount)
    {
        // Do the digits entered match the level 1 access code?
        if (! memcmp(ACCESS_LEVEL_1, au8_enteredKeys, u8_originalKeyCount))
        {
            // It does so grant access level 1
            MainGrantAccess(1);            
            return;
        }
    }
    
    // That did not grant access, see if the entered value is level 2
    if (strlen((char *)ACCESS_LEVEL_2) == u8_originalKeyCount)
    {
        // Do the digits entered match the level 2 access code?
        if (! memcmp(ACCESS_LEVEL_2, au8_enteredKeys, u8_originalKeyCount))
        {
            // It does so grant access level 1
            MainGrantAccess(2);
            return;
        }
    }
}

// ----------------------------------------------------------------------
// KeypadProcessKeypadKey()
//
// This function will:
//      o Store the number of characters that have been entered, if any
//
//      o Check to see if the character that is passed to the function
//        is a 'C' for Clear
//      o Clear the line of entered digits, if any
//      o Set the acquired character count to zero
//
//      o Check ti see if the character entered is an 'E' for Enter
//      o Clear the line of any entered digits, if any
//      o Set the acquired character count to zero
//      o Call a function which evaluates the digits that have been
//        entered, if any
//
//      o Checks ti see if there is room to store the newly-entered
//        digit in the accumulation buffer
//      o Stores the character in to the buffer andincrements the
//        entered digit counter
//      o Ensures that the string of entered digits is NULL terminated
//      o Calls a function which displays the entered digits
//
// ----------------------------------------------------------------------
static void KeypadProcessKeypadKey(uint8_t  u8_thisKeyASCIICharacter)
{
    uint8_t u8_originalKeyCount = u8_enteredKeyCount;
    // Is the key a C for Clear?
    
    if ('C' == u8_thisKeyASCIICharacter)
    {
        // It is, so clear the display line of accumulated characters
        st_lcd.ClearStringLine(ENTERED_KEYS_LINE);
        
        // Discard our accumulated digit count
        u8_enteredKeyCount = 0;
    }
    
    // Is the character that was pressed en E for Enter?
    else if ('E' == u8_thisKeyASCIICharacter)
    {
        // It is, so before we process the code, clear the entered digits
        st_lcd.ClearStringLine(ENTERED_KEYS_LINE);
        
        // Discard our accumulated digit count
        u8_enteredKeyCount = 0;
        
        // Process the entry code
        KeypadProcessEntryCode(u8_originalKeyCount);
    }
    
    // Anything else we assume is a numertic digit
    else
    {
        // Do we have room for more digits?
        if (u8_enteredKeyCount < MAX_SECURITY_DIGITS)
        {
            // Store the entered digit in to the accumulated key buffer
            au8_enteredKeys[u8_enteredKeyCount++] = u8_thisKeyASCIICharacter;
            
            // Make sure that the character string is NULL terminated
            au8_enteredKeys[u8_enteredKeyCount] = 0x00;
    
            // Update the display with the new key value
            KeypadDisplayEnteredKeys();
        }
    }
}

// ----------------------------------------------------------------------
// KeypadHandleKeyPress()
//
// When a key is pressed, the X and Y coordinates of the position where
// the LCD was touched gets passed to this function. 
//
// The function steps throug each of the keys defined in the keypad
// map, checking an area bounded by the beginning X and Y coordinates
// of the keys, and by that position plus the height and width of 
// trhe key.
//
// If the touch screen position that was touched matches the area of
// a known key, a function is called to process the new key.
//
// If a position of the screen was touched that does not match any
// known key position, the function ignores the screen touch.
//
// ----------------------------------------------------------------------
void KeypadHandleKeyPress(uint16_t u16_screenX, uint16_t u16_screenY)
{
    uint16_t u16_keyMinimumX = 0;
    uint16_t u16_keyMaximumX = 0;
    uint16_t u16_keyMinimumY = 0;
    uint16_t u16_keyMaximumY = 0;
    uint8_t  u8_keyPadItem   = 0;
    
    // Step through the keys to check until we reach an entry that's zero
    while(0 != st_KeypadInformation[u8_keyPadItem].u16_screenXLocation)
    {
        // Calculate the boundaries of this key
        u16_keyMinimumX = st_KeypadInformation[u8_keyPadItem].u16_screenXLocation;
        u16_keyMaximumX = u16_keyMinimumX + st_KeypadInformation[u8_keyPadItem].u16_keyHeight;
        u16_keyMinimumY = st_KeypadInformation[u8_keyPadItem].u16_screenYLocation;
        u16_keyMaximumY = u16_keyMinimumY + st_KeypadInformation[u8_keyPadItem].u16_keyWidth;

        // Is this the key that was pressed?
        if (u16_screenX > u16_keyMinimumX && u16_screenX < u16_keyMaximumX)
        {
            if (u16_screenY > u16_keyMinimumY && u16_screenY < u16_keyMaximumY)
            {
                // This is the key that was pressed
                KeypadProcessKeypadKey(st_KeypadInformation[u8_keyPadItem].u8_keyASCIICharacter);
                
                // We are finished searching
                break;
            }
        }
        
        // Check the next possible key area
        u8_keyPadItem++;
    }
}

// ----------------------------------------------------------------------
// KeypadDrawKeypad()
//
// This function will set the LCD background to WHITE and set the 
// default text color to BLUE, thehn it will display information about
// what theoperator should do, then the keypad is constructed on the
// display using the information in the keypad map.
//
// ----------------------------------------------------------------------
void KeypadDrawKeypad(void)
{
    uint8_t u8_keyPadItem = 0;
    
    // For the keypad, we want the entire screen to be this color
    st_lcd.SetBackColor(LCD_COLOR_WHITE);
    
    // For the keypad's general text we want characters to be this color
    st_lcd.SetTextColor(LCD_COLOR_BLUE);
    
    // Build the ketypad display
    st_lcd.DisplayStringAt(1, LINE(0), (uint8_t *)"Enter access code or", CENTER_MODE);
    st_lcd.DisplayStringAt(1, LINE(1), (uint8_t *)"use the Moorse Code", CENTER_MODE);
    st_lcd.DisplayStringAt(1, LINE(2), (uint8_t *)"push button to unlock", CENTER_MODE);
    
    // Step through the keys to plot until we reach an entry that's zero
    while(0 != st_KeypadInformation[u8_keyPadItem].u16_screenXLocation)
    {
        // Draw the rectangle
        st_lcd.FillRect(st_KeypadInformation[u8_keyPadItem].u16_screenXLocation,
            st_KeypadInformation[u8_keyPadItem].u16_screenYLocation,
            st_KeypadInformation[u8_keyPadItem].u16_keyHeight,
            st_KeypadInformation[u8_keyPadItem].u16_keyWidth);

        // Display the character near the lower right corner of the rectangle
        st_lcd.DisplayChar(
            st_KeypadInformation[u8_keyPadItem].u16_screenXLocation + 
                (st_KeypadInformation[u8_keyPadItem].u16_keyHeight / 2) + 6,
            st_KeypadInformation[u8_keyPadItem].u16_screenYLocation + 
                (st_KeypadInformation[u8_keyPadItem].u16_keyWidth / 2) + 2,
            st_KeypadInformation[u8_keyPadItem].u8_keyASCIICharacter);

        // Go to the next keypad to create
        u8_keyPadItem++;
    }
}

// End of file