4x4 Matrix Keypad Sample using interrupt and debouncing (CY8CKIT-059)

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
lock attach
Attachments are accessible only for community members.
MotooTanaka
Level 9
Level 9
Distributor - Marubun (Japan)
First comment on blog Beta tester First comment on KBA

Hi,

In a discussion Matrix Key Sample using interrupt and debouncing was hoped.

https://community.infineon.com/t5/PSoC-5-3-1/Matrix-keypad-component-interrupt-and-last-row-last-col...

 

So I modified my old 4x4 Matrix Keypad Sample

https://community.infineon.com/t5/Code-Examples/4x4-Matrix-Keypad-Sample/m-p/96977#M370

trying to fulfill the requirement. (As usual, there should be infinite approaches to do that though).

 

schematic

001-schematic.JPG

 

Pins

002-Pins.JPG

main.c

#include "project.h"
#include "stdio.h"

#define NUM_ROW        4
#define NUM_COL        4
#define DEBOUNCE_COUNT 4

volatile uint8_t key[NUM_ROW][NUM_COL] = { 0u } ;
uint8_t letter[NUM_ROW][NUM_COL] = {
    { '1', '2', '3', 'A' },
    { '4', '5', '6', 'B' },
    { '7', '8', '9', 'C' },
    { '*', '0', '#', 'D' }
} ;

volatile int row_no = 0 ;
volatile int col_no = 0 ;
volatile int matrix_key_pushed = 0 ;
volatile int matrix_key_released = 0 ;

CY_ISR(key_pushed_isr)
{
    uint8_t  tmp ;
    tmp = Control_Reg_Read() ^ 0x01 ;
    Control_Reg_Write( tmp ) ;
    key_pushed_int_ClearPending() ;
    
    matrix_key_pushed = 1 ;
}

CY_ISR(key_released_isr)
{
    uint8_t  tmp ;
    tmp = Control_Reg_Read() ^ 0x02 ;
    Control_Reg_Write( tmp ) ;
    key_released_int_ClearPending() ;
    
    matrix_key_released = 1 ;    
}

void scan_key_matrix(void)
{
    int key_pushed = 0 ;
    
    switch(row_no) {
    case  0: ROW0_Write(1) ; ROW1_Write(0) ; ROW2_Write(0) ; ROW3_Write(0) ; break ;
    case  1: ROW0_Write(0) ; ROW1_Write(1) ; ROW2_Write(0) ; ROW3_Write(0) ; break ;
    case  2: ROW0_Write(0) ; ROW1_Write(0) ; ROW2_Write(1) ; ROW3_Write(0) ; break ;
    case  3: ROW0_Write(0) ; ROW1_Write(0) ; ROW2_Write(0) ; ROW3_Write(1) ; break ;
    default: ROW0_Write(0) ; ROW1_Write(0) ; ROW2_Write(0) ; ROW3_Write(0) ; break ;
    }

    switch(col_no) {
    case 0: key_pushed = COL0_Read() ; break ;
    case 1: key_pushed = COL1_Read() ; break ;
    case 2: key_pushed = COL2_Read() ; break ;
    case 3: key_pushed = COL3_Read() ; break ;
    }
    
    if (key_pushed) {
        if (key[row_no][col_no] == (DEBOUNCE_COUNT - 1)) {
            Control_Reg_Write(0x01) ; // matrix_key_pushed = 1 ;
        }             
        if (++key[row_no][col_no] >= DEBOUNCE_COUNT) {
            key[row_no][col_no] = DEBOUNCE_COUNT ;
        }
    } else {
        if (key[row_no][col_no]) {
            Control_Reg_Write(0x2) ; // matrix_key_released = 1 ;
        }
        key[row_no][col_no] = 0 ;
    }

    col_no++ ;
    if (col_no >= NUM_COL) {
        col_no = 0 ;
        row_no = (row_no + 1) % NUM_ROW ;
    } 
    ROW0_Write(0) ; 
    ROW1_Write(0) ; 
    ROW2_Write(0) ; 
    ROW3_Write(0) ; 
}

CY_ISR(my_tick_isr)
{
    scan_key_matrix() ;
}

#define STR_LEN 64
char str[STR_LEN+1] ;
void print(char *str)
{
    UART_PutString(str) ;
}

void printc(char c)
{
    UART_PutChar(c) ;
}

void cls(void)
{
    print("\033c") ; /* reset */
    CyDelay(20) ;
    print("\033[2J") ; /* clear screen */
    CyDelay(20) ;
}

void splash(void)
{
    cls() ;
    print("5LP 4x4 Matrix Key Test") ;
    snprintf(str, STR_LEN, "(%s %s)\n", __DATE__, __TIME__) ;
    print(str) ;
}

void init_hardware(void)
{
    CyGlobalIntEnable; /* Enable global interrupts. */
    UART_Start() ;
    splash() ;
    CySysTickStart() ;
    CySysTickSetCallback(0, my_tick_isr) ;
    
    Control_Reg_Write(0x00) ;
    key_pushed_int_ClearPending() ;
    key_released_int_ClearPending() ;
    
    key_pushed_int_StartEx(key_pushed_isr) ;
    key_released_int_StartEx(key_released_isr) ;
}

void dump_key_matrix(void)
{
    int col, row ;
    for (row = 0 ; row < NUM_ROW ; row++) {
        for (col = 0 ; col < NUM_COL ; col++) {
            if (key[row][col]) {
                snprintf(str, STR_LEN, "%c ", letter[row][col]) ;
                print(str) ;
            } else {
                print("- ") ;
            }
        }
        print("\n\r") ;
    }   
}

int main(void)
{
    init_hardware() ;

    dump_key_matrix() ;
    
    for(;;)
    {
        if (matrix_key_pushed) {
            matrix_key_pushed = 0 ;            
            cls() ;
            dump_key_matrix() ;
        }
        if (matrix_key_released) {
            matrix_key_released = 0 ;
            cls() ;
            dump_key_matrix() ;
        }
    }
}

 

moto

0 Likes
4 Replies
Takashi_M
Moderator
Moderator
Moderator
1000 replies posted 500 solutions authored 750 replies posted

Moto-san,

We appreciate your contribution for IFX Community!!

 

regards

PeSe_1509996
Level 3
Level 3
25 replies posted 10 sign-ins 5 questions asked

Dear Moto,

For your kind information, I've written and shared a sample code for interrupt based solution:

https://community.infineon.com/t5/PSoC-Creator-Designer/Mixed-Hardware-and-CPU-interrupt-based-Marti...

 

The main advantage of this  approach: no polling (CPU time waste) nedded for idle/nothing happend periode:

the system works only if needed.

(but this is typical unless it is a typewriter application)

 

Have a nice day !

Péter

MotooTanaka
Level 9
Level 9
Distributor - Marubun (Japan)
First comment on blog Beta tester First comment on KBA

Dear Péter-san,

Thank you very much for unveiling some of your trade secret!

I was studying Bob-san's code yesterday, and fascinated by the technic of reading a key by

	KBD_ROWPins_Write(KEYROWMASK);
	KBD_COLPins_Write(~KEYCOLMASK);
	if ((Row=KBD_ROWPins_Read()) == KEYROWMASK) return 0;
	//*** Get Column ***//
	KBD_COLPins_Write(KEYCOLMASK);
	KBD_ROWPins_Write(Row);
	if ((Column = KBD_COLPins_Read()) == KEYCOLMASK) return 0;

	return (LowestBitPosition(~Row) | (LowestBitPosition(~Column) << 2))+1; // max is 0b0000 1011 = 11 dec + 1

using only a few lines.

And I spent most of the day to port the idea to my form...

 

But this morning seeing your code and technic, I realized that I have even more to learn.

I'm impressed with triggering technic of yours

003-keypad_intr.JPG

and your ISRs were also so compact.

 

Yesterday, I was trying to utilize SysTick, which is an integrated timer in the ARM Cortex-M,

so that I can eliminate the Timer.  And I think that I could make it.

But now I'd like to learn and try your interrupt driven method, thank you!

 

Best Regards,

14-Jun-2022

Motoo Tanaka

 

PeSe_1509996
Level 3
Level 3
25 replies posted 10 sign-ins 5 questions asked

Your  welcome.

0 Likes