- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
In a discussion Matrix Key Sample using interrupt and debouncing was hoped.
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
Pins
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
- Labels:
-
Matrix Key
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Moto-san,
We appreciate your contribution for IFX Community!!
regards
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Dear Moto,
For your kind information, I've written and shared a sample code for interrupt based solution:
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Your welcome.