MTB CAT1 Peripheral driver library
KeyScan (KeyScan)

General Description

MXKEYSCAN is a DEEPSLEEP peripheral IP that performs autonomous key-matrix scan and system notification.

Key processing detects both press and un-press actions, includes micro and macro de-bouncing filters and ghost key detection.

Configurable key-matrix size supports up to 20x8 keys. Up to 20 columns are driven as the output and up to 8 rows are processed as the input. Key actions are stored in the FIFO with interrupt notification available based on the FIFO threshold.

The Scan matrix support up to 8X20 matrix, maximum of 160 keys. Any key press will be translated into an index corresponding column and corresponding row. Before any key is pressed, the Key Matrix Scan Logic is disabled. Once a key press is detected by the Key Detection Logic, it will enable the gate for clock to drive the key Matrix Scan Logic for GPIO scanning. GPIO scanning is done one column at a time by driving each column "low" and reading from the row GPIO pins to find out which input is low. After the Key Scan Logic had scanned through the matrix for a specific number for debounce times configured by firmware though the configuration register, keycode representing the pressed key is pushed into the key FIFO for firmware to read and an interrupt to CPU will be generated. There are two types of debounce mechanisms build into this scan matrix block. The micro-debounce logic will provide a small debounce period to debounce the break type of mechanical vibration. The macro debounce logic will scan through the matrix for a number of times for qualify a key as being pressed.

Features:

This driver provides the user an easy method for accessing KeyScan registers and provides some simple functionality for reading key index from keyscan FIFO.

The IP supports only Sequential PIN configuration. For Example if the user is configuring the IP for 4 pins (2 ROWS and 2 COLUMNs) the user is suggested to use ROWS 0,1 and COLUMNS 0,1. Interleaved ROWS and COLUMNS are not supported by the IP i.e. User should not configure ROW0 and ROW3 and COLUMN1 and COLUMN4 etc.

With every Key event, User receives the following information

keyscan_matrix.png
Keyscan Matrix

Initialization:

The KeyScan driver initialization is according to the Options setup in the passed Config Struct. Several validations are done before the initialization and an error is returned if invalid Modes are requested.

KeyScan Configuration

Application then registers for the callback. Driver notifies the user for any events in this callback function.

cy_stc_ks_config_t keyscan_config =
{
.macroUpDebCnt = 3u,
.microDebCnt = 3u,
.noofRows = 8u,
.noofColumns = 20u,
.ghostEnable = true,
.cpuWakeupEnable = true,
.clkStayOn = true
};
status = Cy_Keyscan_Init(MXKEYSCAN, &keyscan_config, &context);
if(status != CY_KEYSCAN_SUCCESS)
{
/* Insert error handling */
}

Interrupt Handling

Keyscan has a dedicated interrupt keyscan_interrupt_IRQn

There are 2 type of interrupts that the software has to check when there is an interrupt

status = Cy_Keyscan_Init(MXKEYSCAN, &keyscan_config, &context);
if(status != CY_KEYSCAN_SUCCESS)
{
/* Insert error handling */
}
/* User has to register for callback. Driver notifies the user for any events in this callback function. */
status = Cy_Keyscan_Register_Callback(key_detected_callback, &context);
if(status != CY_KEYSCAN_SUCCESS)
{
/* Insert error handling */
}
if(status != CY_KEYSCAN_SUCCESS)
{
/* Insert error handling */
}

Applications have to call Cy_Keyscan_Interrupt_Handler function from keyscan interrupt handler. Applications will be notified of any key events through the registered callback. Applications have to read the events in the callback function by calling Cy_Keyscan_GetNextEvent function in a loop till the return value is CY_KEYSCAN_EVENT_NONE. With every Key event, User receives the following information

/*
** Applications have to call Cy_Keyscan_Interrupt_Handler function from keyscan interrupt handler.
** Applications will be notified of any key events through the registered callback.
** Applications have to read the events in the callback function by calling Cy_Keyscan_GetNextEvent function in a loop till
** the return value is CY_KEYSCAN_EVENT_NONE.
*/
void keyscan_intHandler(void)
{
uint32_t int_status;
Cy_Keyscan_GetInterruptMaskedStatus(MXKEYSCAN, &int_status);
if(0UL != (MXKEYSCAN_INTR_FIFO_THRESH_DONE & int_status))
{
status = Cy_Keyscan_Interrupt_Handler(MXKEYSCAN, &context);
if(CY_KEYSCAN_SUCCESS != status)
{
// Keyscan interrupt handler failed
}
}
else
{
}
}
static void key_detected_callback(void)
{
uint8_t keyCode, scanCycle, upDownFlag;
bool events_pending;
Cy_Keyscan_EventsPending(MXKEYSCAN, &events_pending, &context);
while (events_pending)
{
status = Cy_Keyscan_GetNextEvent(MXKEYSCAN, &kevent, &context);
if(status != CY_KEYSCAN_SUCCESS)
{
// Keyscan get next event failed
}
/* Check value of keycode for the corresponding key being pressed
Keycode is calculated as ((no of rows * column num) + row num) */
keyCode = kevent.keyCode;
scanCycle = kevent.scanCycleFlag;
upDownFlag = kevent.upDownFlag;
if(keyCode == KEYSCAN_KEYCODE_ROLLOVER)
{
// ROLLOVER KEY DETECTED
}
{
// End of Scan Cycle event. Added by driver when an event is occurred in different scan cycle.
Cy_Keyscan_EventsPending(MXKEYSCAN, &events_pending, &context);
continue;
}
Cy_Keyscan_EventsPending(MXKEYSCAN, &events_pending, &context);
(void)keyCode;
(void)scanCycle;
(void)upDownFlag;
}
}

Handling DeepSleep

Following are the points users of keyscan have to handle in their code.

Changelog

VersionChangesReason for Change
1.0 Initial version

API Reference

 Macros
 
 Functions
 
 Data Structures
 
 Enumerated Types