Creating a FIFO Queue with Keypad Inputs

169 views Asked by At

I'm trying to implement a FIFO queue for keypad inputs but cannot seem to get it to work. I'm able to get the keypad inputs to appear on an LCD screen but that is all I'm able to do. I think the code is supposed to read a keypad input and push it into a queue, then pop the keypad input and read the value onto an LCD screen. Could anyone advise on why it doesn't display all the values I've pressed? Thank you.

#include "project.h"
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>

// Keypad Variables

char KeyPad[4][4] = {
    {'1','2','3','A'},
    {'4','5','6','B'},
    {'7','8','9','C'},
    {'*','0','#','D'}, 
};

char ReadKeyPad();

// FIFO Variables

struct FIFO {
    char            key;
    struct  FIFO    *next;
};

struct FIFO KeyQueue[] = {
    {0, &KeyQueue[1]},  //[0]
    {0, &KeyQueue[2]},  //[1]
    {0, &KeyQueue[3]},  //[2]
    {0, &KeyQueue[4]},  //[3]
    {0, &KeyQueue[5]},  //[4]
    {0, &KeyQueue[6]},  //[5]
    {0, &KeyQueue[7]},  //[6]
    {0, &KeyQueue[8]},  //[7]
    {0, &KeyQueue[0]}   //[8]
};

struct FIFO *Head;
struct FIFO *Tail;
int KeyQueue_Size=0;
bool KeyQueue_IsEmpty();
bool KeyQueue_IsFull();
void KeyQueue_Push(char key);
char KeyQueue_Pop();
char ReadKeyPad();

int delay = 10;

int main(void)
{
    Head = Tail = &KeyQueue[0];
    char key;

    CyGlobalIntEnable; /* Enable global interrupts. */

    /* Place your initialization/startup code here (e.g. MyInst_Start()) */

    LCD_Start();
    LCD_ClearDisplay();
    LCD_Enable();

    for(;;)
    {
        /* Place your application code here. */
        key = ReadKeyPad();
        LCD_Position(1,8);
        LCD_PutChar(key);

        if (key !=0)
        {
            if (!KeyQueue_IsFull())   
                KeyQueue_Push(key);
        }
        //task for poping key
        delay --;
        if(delay <= 0 && !KeyQueue_IsEmpty())
        {
            KeyQueue_Pop();
            switch (key)
            {
                case '1':
                    LCD_Position(0,1);
                    LCD_PrintString("You pressed 1");
                break;
                case '2':
                    LCD_Position(0,1);
                    LCD_PrintString("You pressed 2");
                break;
                case '3':
                    LCD_Position(0,1);
                    LCD_PrintString("You pressed 3");
                break;
                case '4':
                    LCD_Position(0,1);
                    LCD_PrintString("You pressed 4");
                break;
                case '5':
                    LCD_Position(0,1);
                    LCD_PrintString("You pressed 5");
                break;
                case '6':
                    LCD_Position(0,1);
                    LCD_PrintString("You pressed 6");
                break;
                case '7':
                    LCD_Position(0,1);
                    LCD_PrintString("You pressed 7");
                break;
                case '8':
                    LCD_Position(0,1);
                    LCD_PrintString("You pressed 8");
                break;
                case '9':
                    LCD_Position(0,1);
                    LCD_PrintString("You pressed 9");
                break;
                case 'A':
                    LCD_Position(0,1);
                    LCD_PrintString("You pressed A");
                break;
                case 'B':
                    LCD_Position(0,1);
                    LCD_PrintString("You pressed B");
                break;
                case 'C':
                    LCD_Position(0,1);
                    LCD_PrintString("You pressed C");
                break;
                case 'D':
                    LCD_Position(0,1);
                    LCD_PrintString("You pressed D");
                break;
                case '*':
                    LCD_Position(0,1);
                    LCD_PrintString("You pressed *");
                break;
                case '#':
                    LCD_Position(0,1);
                    LCD_PrintString("You pressed #");
                break;
                case '0':
                    LCD_Position(0,1);
                    LCD_PrintString("You pressed 0");
                break;
                delay = 10;            
            }

            CyDelayUs(100);
        }   

    }
}

bool KeyQueue_IsEmpty()
{
    if(KeyQueue_Size == 0) return true;
    return false;
}
bool KeyQueue_IsFull()
{
    //if (Head == Tail) return truel
    if(KeyQueue_Size ==9) return true;
    return false;
}
void KeyQueue_Push(char key)
{
    Head->key=key;
    Head = Head->next;
    KeyQueue_Size ++;
}
char KeyQueue_Pop()
{
    char key;
    key = Tail->key;
    Tail = Tail->next;
    KeyQueue_Size --;
    return key;
}
char ReadKeyPad()
{    
    int     i;
    char    key;
    uint8_t col;

    for (i=0; i<4; i++)
    {
        key = 0;
        ROW_Write(1<<i);
        col=COL_Read();
        //LCD_Position(1,0);
        //LCD_PrintNumber(key);

        if (col & 0x01) key=KeyPad[i][0];
        if (col & 0x02) key=KeyPad[i][1];
        if (col & 0x04) key=KeyPad[i][2];
        if (col & 0x08) key=KeyPad[i][3];
        if (key != 0) break;
    }

    return key;
}
1

There are 1 answers

0
Mathieu On

Some problems in your code:

  • As pointed before, delay = 10; is not well placed
  • key variable of main function is set only at the beginning of for loop.

So a corrected code could be:

for(;;)
{
    key = ReadKeyPad();
    LCD_Position(1,8);
    LCD_PutChar(key);

    if (key !=0)
    {
        if (!KeyQueue_IsFull())   
            KeyQueue_Push(key);
    }
    //task for poping key
    delay --;
    if(delay <= 0 && !KeyQueue_IsEmpty())
    {
        /* don't forget to store what have been poped from fifo */
        key = KeyQueue_Pop();


        switch (key)
        {
            case '1':
                LCD_Position(0,1);
                LCD_PrintString("You pressed 1");
                delay = 10;
            break;
            case '2':
                LCD_Position(0,1);
                LCD_PrintString("You pressed 2");
                delay = 10;
            break;
            /*
             .
             .
             .
             */                
            case '0':
                LCD_Position(0,1);
                LCD_PrintString("You pressed 0");
                delay = 10;
            break;                           
        }

        CyDelayUs(100);
    }   
}

Maybe you can write it shorter:

for(;;)
{
    key = ReadKeyPad();
    LCD_Position(1,8);
    LCD_PutChar(key);

    if (key !=0)
    {
        if (!KeyQueue_IsFull())   
            KeyQueue_Push(key);
    }
    //task for poping key
    delay --;
    if(delay <= 0 && !KeyQueue_IsEmpty())
    {
        /* don't forget to store what have been poped from fifo */
        key = KeyQueue_Pop();

        /* print what have been pressed */
        LCD_Position(0,1);
        LCD_PrintString("You pressed ");
        LCD_Position(0,12);
        LCD_PutChar(key);
        delay = 10;

        CyDelayUs(100);
    }   
}