KeyScan

Sample List

This chapter introduces the details of the KeyScan sample code. The SDK provides the following samples for the KeyScan peripheral.

Functional Overview

KeyScan needs to be used with an external key matrix. In the idle state, row[x] is input, pull high is required, column[y] is output low, and output mode must be open-drain. When any key is pressed, the level of the corresponding row changes from high to low, triggering KeyScan hardware scan action.

After the debounce is completed, the first scan starts. When scanning, the column[y] being scanned is output low, and the other columns output high. If row[x] is low at this time, it is considered that row[x] column[y] key is pressed.

Scan order is first column[0] fixed, scan from row[0] to row[x], then column[1] fixed, scan from row[0] to row[x], until column[y].

Note

RTL87x3D and RTL87x3E support KeyScan, RTL87x3EP doesn’t support KeyScan.

Feature List

  • Support 12 (row) * 20 (column) matrix scan.

  • Configurable number of rows (1-12), columns (1-20).

  • Support hardware debounce, configurable debounce time.

  • Configurable scan clock.

  • Support multi-key detection, up to 26 keys can be pressed at the same time.

  • Support periodic scan, configurable scan period.

  • 26 bytes FIFO depth.

  • Support auto scan and manual scan.

  • Support all key release hardware detection.

Block Diagram

Here is the overall IPs block diagram for KeyScan IP¹, which including ‘PAD/PINMUX’ for IO function configuration, ‘KeyScan IP’ for KeyScan protocol.

../../../_images/KeyScan_System_Block_Diagram.png

System Block Diagram of KeyScan

Scanning Process

The scanning process of KeyScan is as shown in the diagram:

../../../_images/KeyScan_Scanning_Diagram.png

KeyScan Scanning Diagram

  1. In idle state, all row[x] serve as input, in pull-up state, while all column[y] serve as output, outputting low level.

  2. When any key is pressed, a low level will be detected in a certain row, triggering the KeyScan hardware scanning action.

  3. After waiting for the debounce timer, the first scan begins.

  4. First, pull column[0] low, while the other columns are pulled high, and sequentially detect row[0], row[1], …, row[N].

  5. If row[0] is detected to be pulled low, it can be confirmed that (row[0], column[0]) is pressed; otherwise, the key is not pressed. Continue scanning other rows in this manner.

  6. Switch to pulling column[1] low, the other columns are pulled high, sequentially detect row[0], row[1], …, row[N], until the last column[N] is pulled low and the other columns are pulled high, scanning is complete.

  7. At this point, one scan is complete, and the scanning result will be filled into the KeyScan FIFO. If the KEYSCAN_INT_SCAN_END interrupt is enabled, it will trigger this interrupt.

  8. After the scan interval time, a second global scan will be conducted, and the same operation will be performed after the scan ends.

  9. If no key press is detected during a scan, the all release timer will start counting, and all columns will be pulled low. If no row is detected to be pulled low after the all release timer finishes counting, it indicates that all keys are released at this time. If the KEYSCAN_INT_ALL_RELEASE interrupt is enabled, it will trigger this interrupt.

KeyScan scanning is divided into manual scanning mode and automatic scanning mode.

Manual Scan Mode

Configure KEYSCAN_InitTypeDef::scanmode as KeyScan_Manual_Scan_Mode during KeyScan initialization to set KeyScan to manual scan mode.

In manual scan mode, KeyScan will perform only one scan, and upon completion, it will trigger the KEYSCAN_INT_SCAN_END interrupt.

Auto Scan Mode

Configure KEYSCAN_InitTypeDef::scanmode as KeyScan_Auto_Scan_Mode during KeyScan initialization to set KeyScan to automatic scan mode.

In automatic scan mode, KeyScan is triggered by external key presses. The trigger mode can be modified to edge-triggered (KeyScan_Detect_Mode_Edge) or level-triggered (KeyScan_Detect_Mode_Level) by setting KEYSCAN_InitTypeDef::detectMode.

In automatic scan mode, KeyScan will continuously scan until no keys are pressed, which triggers the KEYSCAN_INT_ALL_RELEASE interrupt. The KEYSCAN_INT_SCAN_END interrupt can be triggered multiple times.

The workflow of automatic scanning is shown in the figure below.

../../../_images/Auto_Scan_Flow_Chart.png

Auto Scan Flow Chart

Clock Divider

IO clock will be divided into 2 channels.

The KeyScan scan clock is generated by the frequency division of keyscan_clk_div (11 bits). Scan clock = KeyScan clock source (5MHz) / (KEYSCAN_InitTypeDef::clockdiv + 1).

The low-level delay clock is generated by the frequency division of keyscan_delay_div (6 bits) for use by the relevant timer. Delay clock = Scan clock / (KEYSCAN_InitTypeDef::delayclk + 1).

key_scan_deb_timer is used for debounce timing, where debounce time = Delay clock * KEYSCAN_InitTypeDef::debouncecnt.

key_scan_interval_timer is used for scan interval timing, where scan interval time = Delay clock * KEYSCAN_InitTypeDef::scanInterval.

key_scan_release_timer is used for release time timing, where release time = Delay clock * KEYSCAN_InitTypeDef::releasecnt.

../../../_images/Schematic_Diagram_of_KEYSCAN_Clock_Divider.png

Schematic Diagram of KeyScan Clock Divider

Interrupt

  1. KEYSCAN_INT_OVER_READ

    When there is no data in the FIFO, reading the FIFO will trigger this interrupt to prevent over-reading.

  2. KEYSCAN_INT_SCAN_END

    Whether the key value is scanned or not, the interrupt will be triggered as long as the scanning action is completed.

  3. KEYSCAN_INT_FIFO_NOT_EMPTY

    If there is data in the FIFO, the interrupt will be triggered.

  4. KEYSCAN_INT_THRESHOLD

    This interrupt is triggered when data in the FIFO reaches the threshold level.

  5. KEYSCAN_INT_ALL_RELEASE

    When the release time count reaches the set value, if no key is pressed, the interrupt is triggered.

Power Manager

The KeyScan peripheral is located in the core domain and will be powered off in low power mode. KeyScan peripheral store/restore will be automatically performed based on whether the KeyScan clock is active. Users can call the API io_dlps_register() to initialize KeyScan peripheral store/restore and do not need to worry about KeyScan peripheral requiring specific handling.