356 lines
14 KiB
C
356 lines
14 KiB
C
/*****************************************************************************/
|
|
/* FILENAME : KeyHdl.c */
|
|
/* */
|
|
/* DESCRIPTION : Handling Key Events for Application. */
|
|
/* */
|
|
/* NOTES : Copyright Sathish Kumar P. All rights reserved. */
|
|
/* */
|
|
/* AUTHOR : Sathish Kumar */
|
|
/* sathishembeddedgeek@gmail.com */
|
|
/* */
|
|
/* START DATE : 9th Feb 2020 */
|
|
/* */
|
|
/* VERSION DATE WHO DETAIL */
|
|
/* 00.00.01 09FEB20 Sathish Kumar initial version */
|
|
/* */
|
|
/*****************************************************************************/
|
|
|
|
/*****************************************************************************/
|
|
/* */
|
|
/* I N C L U D E S */
|
|
/* */
|
|
/*****************************************************************************/
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#include "keyhdl_api.h"
|
|
#include "keyhdl.h"
|
|
|
|
#if (KEYHDL_USE_OS==1)
|
|
#include "FreeRTOS.h"
|
|
#include "task.h"
|
|
#endif
|
|
|
|
/*****************************************************************************/
|
|
/* */
|
|
/* D E F I N I T I O N S */
|
|
/* */
|
|
/*****************************************************************************/
|
|
|
|
#define NO_OF_BYTES_FOR_KEY ((MAX_KEYS/8)+1)
|
|
|
|
#define KEY_SET_BIT_IN_ARRAY(array,indx) array[(uint8_t)indx>>3] |= \
|
|
((uint8_t)1<<(indx&0x7))
|
|
#define KEY_CLEAR_BIT_IN_ARRAY(array,indx) array[(uint8_t)indx>>3] &= \
|
|
(~((uint8_t)1<<(indx&0x7)))
|
|
#define KEY_READ_BIT_IN_ARRAY(array,indx) array[(uint8_t)indx>>3] & \
|
|
((uint8_t)1<<(indx&0x7))
|
|
|
|
#define ARRAY_SIZE(x) ((sizeof (x))/(sizeof (x [0])))
|
|
/*****************************************************************************/
|
|
/* */
|
|
/* C O N S T A N T S & V A R I A B L E S */
|
|
/* */
|
|
/*****************************************************************************/
|
|
|
|
#if (KEYHDL_SUPPORT_SINGLE_KEY)
|
|
static const KeyPortMap_t key_single_port_map[]= KEYHDL_SINGLE_KEY_MAP;
|
|
static const uint8_t key_single_port_map_size = ARRAY_SIZE(key_single_port_map);
|
|
#endif
|
|
|
|
#if (KEYHDL_SUPPORT_MATRIX_KEY)
|
|
static const KeyEnumList key_matrix_map[KEYHDL_MATRIX_NO_OF_ROWS][KEYHDL_MATRIX_NO_OF_COLS]
|
|
= KEYHDL_MATRIX_KEY_MAP;
|
|
|
|
static const KeyGPIO_t key_matrix_port_row[KEYHDL_MATRIX_NO_OF_ROWS]= KEYHDL_MATRIX_ROW_MAP;
|
|
static const KeyGPIO_t key_matrix_port_col[KEYHDL_MATRIX_NO_OF_COLS]= KEYHDL_MATRIX_COL_MAP;
|
|
#endif
|
|
|
|
#if (KEYHDL_SUPPORT_MULTI_KEY)
|
|
static const KeyMultiMap_t key_multi_list_map[]= KEYHDL_MULTI_KEY_MAP;
|
|
static const uint8_t key_multi_list_map_size = ARRAY_SIZE(key_multi_list_map);
|
|
#endif
|
|
|
|
static uint8_t key_array[NO_OF_BYTES_FOR_KEY];
|
|
|
|
static KeyParams_t key_param[MAX_KEYS];
|
|
|
|
static keyCallBackFnPtr usr_callback_fnc;
|
|
|
|
/*****************************************************************************/
|
|
/* */
|
|
/* F U N C T I O N P R O T O T Y P E S */
|
|
/* */
|
|
/*****************************************************************************/
|
|
|
|
/*****************************************************************************/
|
|
/* See header file of description */
|
|
/*****************************************************************************/
|
|
#if (KEYHDL_SUPPORT_SINGLE_KEY)
|
|
void KeyHdl_ReadSingleKeyStatus(void);
|
|
#endif
|
|
|
|
/*****************************************************************************/
|
|
/* See header file of description */
|
|
/*****************************************************************************/
|
|
#if (KEYHDL_SUPPORT_MATRIX_KEY)
|
|
void KeyHdl_ReadMatrixKeyStatus(void);
|
|
#endif
|
|
|
|
/*****************************************************************************/
|
|
/* See header file of description */
|
|
/*****************************************************************************/
|
|
#if (KEYHDL_SUPPORT_MULTI_KEY)
|
|
void KeyHdl_ReadMultiKeyStatus(void);
|
|
#endif
|
|
|
|
/*****************************************************************************/
|
|
/* See header file of description */
|
|
/*****************************************************************************/
|
|
void KeyHdl_DeboucingCheck(uint16_t call_rate);
|
|
|
|
/*****************************************************************************/
|
|
/* See header file of description */
|
|
/*****************************************************************************/
|
|
void KeyHdl_NotifyKeyEvent(void);
|
|
|
|
/*****************************************************************************/
|
|
/* See header file of description */
|
|
/*****************************************************************************/
|
|
#if (KEYHDL_USE_OS==1)
|
|
static void KeyHdl_FreeRtosTask(void *pvParameters);
|
|
#endif
|
|
|
|
/*****************************************************************************/
|
|
/* */
|
|
/* F U N C T I O N S */
|
|
/* */
|
|
/*****************************************************************************/
|
|
|
|
/*****************************************************************************/
|
|
/* See header file of description */
|
|
/*****************************************************************************/
|
|
int8_t KeyHdl_Init(keyCallBackFnPtr fnptr)
|
|
{
|
|
int8_t ret = 0;
|
|
KEYHDL_HW_INIT();
|
|
|
|
usr_callback_fnc = fnptr;
|
|
/* definition and creation of freertos task */
|
|
#if (KEYHDL_USE_OS==1)
|
|
/* Create OS Tasks */
|
|
if(xTaskCreate(KeyHdl_FreeRtosTask, (const char *) "KeyHdlTask",
|
|
2*configMINIMAL_STACK_SIZE, NULL, (tskIDLE_PRIORITY + 1UL),
|
|
(xTaskHandle *) NULL)!= pdPASS)
|
|
{
|
|
ret = -1;
|
|
}
|
|
#endif
|
|
return ret;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/* See header file of description */
|
|
/*****************************************************************************/
|
|
void KeyHdl_HWScanISR(uint32_t call_rate)
|
|
{
|
|
/* Key Single scan */
|
|
#if (KEYHDL_SUPPORT_SINGLE_KEY)
|
|
KeyHdl_ReadSingleKeyStatus();
|
|
#endif
|
|
|
|
/* Key Matrix scan */
|
|
#if (KEYHDL_SUPPORT_MATRIX_KEY)
|
|
KeyHdl_ReadMatrixKeyStatus();
|
|
#endif
|
|
}
|
|
|
|
#if (KEYHDL_USE_OS==1)
|
|
/*****************************************************************************/
|
|
/* See header file of description */
|
|
/*****************************************************************************/
|
|
static void KeyHdl_FreeRtosTask(void *pvParameters)
|
|
{
|
|
while (1) {
|
|
|
|
KeyHdl_Task(KEYHDL_TASK_TIME_IN_MS);
|
|
/* About a delay here */
|
|
vTaskDelay(KEYHDL_TASK_TIME_IN_MS);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/*****************************************************************************/
|
|
/* See header file of description */
|
|
/*****************************************************************************/
|
|
void KeyHdl_Task(uint32_t call_rate)
|
|
{
|
|
static uint32_t call_rate_cntr=0;
|
|
|
|
call_rate_cntr += call_rate;
|
|
|
|
if(call_rate_cntr >= KEYHDL_TASK_TIME_IN_MS)
|
|
{
|
|
call_rate_cntr -= KEYHDL_TASK_TIME_IN_MS;
|
|
|
|
/* This is placed here because it does not have time restriction. */
|
|
#if (KEYHDL_SUPPORT_MULTI_KEY)
|
|
/* Key multi press */
|
|
KeyHdl_ReadMultiKeyStatus();
|
|
#endif
|
|
|
|
/* check for key bounce */
|
|
KeyHdl_DeboucingCheck(KEYHDL_TASK_TIME_IN_MS);
|
|
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/* See header file of description */
|
|
/*****************************************************************************/
|
|
#if (KEYHDL_SUPPORT_SINGLE_KEY)
|
|
void KeyHdl_ReadSingleKeyStatus(void)
|
|
{
|
|
uint8_t keyCntr=0;
|
|
|
|
for(keyCntr=0;keyCntr<key_single_port_map_size;keyCntr++)
|
|
{
|
|
if(KEYHDL_HW_READ_PIN(key_single_port_map[keyCntr].port,key_single_port_map[keyCntr].pin)==0)
|
|
{
|
|
KEY_SET_BIT_IN_ARRAY(key_array,key_single_port_map[keyCntr].key_name);
|
|
}
|
|
else
|
|
{
|
|
KEY_CLEAR_BIT_IN_ARRAY(key_array,key_single_port_map[keyCntr].key_name);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/*****************************************************************************/
|
|
/* See header file of description */
|
|
/*****************************************************************************/
|
|
#if (KEYHDL_SUPPORT_MULTI_KEY)
|
|
void KeyHdl_ReadMultiKeyStatus(void)
|
|
{
|
|
uint8_t multiKeyCntr=0;
|
|
uint8_t keyCntr=0;
|
|
uint8_t keymulti_pressed=0;
|
|
uint8_t keyIdx=0;
|
|
|
|
for(multiKeyCntr=0;multiKeyCntr<key_multi_list_map_size;multiKeyCntr++)
|
|
{
|
|
keymulti_pressed=0;
|
|
for(keyCntr=0;keyCntr<key_multi_list_map[multiKeyCntr].no_of_keys;keyCntr++)
|
|
{
|
|
keyIdx=key_multi_list_map[multiKeyCntr].multi_key_list[keyCntr];
|
|
|
|
/* read from global key array */
|
|
if(KEY_READ_BIT_IN_ARRAY(key_array,keyIdx))
|
|
{
|
|
keymulti_pressed++;
|
|
}
|
|
}
|
|
|
|
/* set the bit in global key array */
|
|
if(keymulti_pressed == key_multi_list_map[multiKeyCntr].no_of_keys)
|
|
{
|
|
KEY_SET_BIT_IN_ARRAY(key_array,key_multi_list_map[multiKeyCntr].key_name);
|
|
|
|
/* clear the single key array when there is multikey event */
|
|
for(keyCntr=0;keyCntr<key_multi_list_map[multiKeyCntr].no_of_keys;keyCntr++)
|
|
{
|
|
keyIdx=key_multi_list_map[multiKeyCntr].multi_key_list[keyCntr];
|
|
/* clear from global key array */
|
|
KEY_CLEAR_BIT_IN_ARRAY(key_array,keyIdx);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
KEY_CLEAR_BIT_IN_ARRAY(key_array,key_multi_list_map[multiKeyCntr].key_name);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/*****************************************************************************/
|
|
/* See header file of description */
|
|
/*****************************************************************************/
|
|
#if (KEYHDL_SUPPORT_MATRIX_KEY)
|
|
void KeyHdl_ReadMatrixKeyStatus(void)
|
|
{
|
|
static uint8_t col_indx = 0;
|
|
uint8_t row_cntr=0;
|
|
uint8_t key_name=0;
|
|
|
|
/* Key Matrix Scan */
|
|
for(; row_cntr <KEYHDL_MATRIX_NO_OF_ROWS;row_cntr++)
|
|
{
|
|
key_name= key_matrix_map[row_cntr][col_indx];
|
|
if(KEYHDL_HW_READ_PIN(key_matrix_port_row[row_cntr].port,key_matrix_port_row[row_cntr].pin) == 0 )
|
|
{
|
|
KEY_SET_BIT_IN_ARRAY(key_array,key_name);
|
|
}
|
|
else
|
|
{
|
|
KEY_CLEAR_BIT_IN_ARRAY(key_array,key_name);
|
|
}
|
|
}
|
|
KEYHDL_HW_WRITE_PIN(key_matrix_port_col[col_indx].port,key_matrix_port_col[col_indx].pin,1);
|
|
col_indx++;
|
|
if(col_indx >= KEYHDL_MATRIX_NO_OF_COLS)
|
|
{
|
|
col_indx = 0;
|
|
}
|
|
KEYHDL_HW_WRITE_PIN(key_matrix_port_col[col_indx].port,key_matrix_port_col[col_indx].pin,0);
|
|
}
|
|
#endif
|
|
|
|
/*****************************************************************************/
|
|
/* See header file of description */
|
|
/*****************************************************************************/
|
|
void KeyHdl_DeboucingCheck(uint16_t call_rate)
|
|
{
|
|
uint8_t keyCntr=0;
|
|
for(;keyCntr<MAX_KEYS;keyCntr++)
|
|
{
|
|
if(KEY_READ_BIT_IN_ARRAY(key_array,keyCntr))
|
|
{
|
|
key_param[keyCntr].bounce_time += call_rate;
|
|
|
|
if((key_param[keyCntr].bounce_time >= KEYHDL_KEY_DEBOUNCE_TIME) && (key_param[keyCntr].event_type != KEY_EVENT_PRESSED))
|
|
{
|
|
/* key press event */
|
|
key_param[keyCntr].event_type = KEY_EVENT_PRESSED;
|
|
if(usr_callback_fnc)
|
|
{
|
|
usr_callback_fnc(keyCntr,KEYHDL_KEY_PRESSED,key_param[keyCntr].bounce_time);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* key released */
|
|
key_param[keyCntr].event_type = KEY_EVENT_RELEASED;
|
|
|
|
if(key_param[keyCntr].bounce_time >= KEYHDL_KEY_DEBOUNCE_TIME)
|
|
{
|
|
if(usr_callback_fnc)
|
|
{
|
|
usr_callback_fnc(keyCntr,KEYHDL_KEY_RELEASED,key_param[keyCntr].bounce_time);
|
|
}
|
|
}
|
|
|
|
/* clear timers */
|
|
key_param[keyCntr].bounce_time = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/* */
|
|
/* E N D O F F I L E */
|
|
/* */
|
|
/*****************************************************************************/
|