Implementing Key Matrix Scanning

As the number of keys on the operation panel increases, you will quickly run out of MCU pins. This is where a key matrix is used. Although it dramatically reduces wiring, implementing it without careful consideration will lead to ghosting, a phenomenon in which unpressed keys register. This article explains everything from the basics of matrix scan implementation to the mechanism of ghosting, countermeasures, and precautions for implementation.

How Key Matrices Work: Saving Pins with Rows and Columns

A key matrix is designed by wiring keys in a grid of rows and columns, with a switch placed at each intersection. Since N rows + M columns of pins can handle N×M keys, for example, a 4×4 matrix of 16 keys requires only 8 pins, and a 4×8 matrix of 32 keys requires only 12 pins. Compared to the direct connection method of one pin per key, the pin-saving effect becomes more significant as the number of keys increases.

Keys are read by scanning. By driving the rows one by one in sequence and reading which column a signal appears in at that time, you can determine that the key at the intersection of the currently driven row and the responding column is pressed. Once all rows have been scanned, the states of all keys can be obtained.

Basic Scan Implementation

#define ROWS 4
#define COLS 4
/* Called every 5 ms; returns the raw state of all keys as a bitmap */
uint16_t key_scan_raw(void)
{
    uint16_t raw = 0;
    for (uint8_t r = 0; r < ROWS; r++) {
        row_drive_low(r);        /* Drive only the target row LOW           */
        delay_us(10);            /* Wait for the wiring to settle      */
        uint8_t cols = read_cols_active_low() & (uint8_t)((1u << COLS) - 1u);  /* LOW columns = pressed (only lower COLS bits are valid) */
        raw |= (uint16_t)cols << (r * COLS);
        row_release(r);          /* Return the row to high impedance */
    }
    return raw;
}

There are two key points in the implementation.

First, as a general rule, rows that are not being driven should be returned to high impedance (Hi-Z, input setting). Instead of setting unselected rows to HIGH output, set them as inputs, and set only the selected row to LOW output (open-drain if possible). Columns should be pulled up. If multiple keys are pressed while multiple rows are left in the output state, a current path will be created where the rows conflict with each other’s outputs. Although a design that fixes unselected rows to an inactive level (such as fixing to HIGH with push-pull) is also feasible, considering the effects of wiring capacitance and sneak paths, the Hi-Z method is the safest to start with.

Second, immediately after switching rows, insert a short wait before reading the columns. ① Key point: It takes a short time (settle time) for the signal to stabilize due to the RC time constant determined by the wiring and input capacitance, as well as the pull-up resistor. ② Reason: Reading in the middle of this time will pick up values during the rising or falling transitions, leading to false detection. ③ Guideline: The target wait time is about several µs to several tens of µs, but it varies depending on the wiring length, pull-up resistor value, and input capacitance. The delay_us(10) in the sample code is just an example; check the waveform on the actual device to determine the appropriate minimum value.

Switch Bounce Mitigation and State Confirmation

Raw scan results contain switch bounce. A standard method is to compare the results of each scan cycle and confirm the state when the same state is observed for several consecutive scans (for example, three times), which allows stable detection of both press and release edges. This is simply debouncing. The confirmed state can then be used to detect higher-level operations such as press events, long presses, and repeats.

Why Ghosting (Phantom Keys) Occurs

A matrix’s inherent weakness appears when three keys are pressed simultaneously. If three of the four keys that form a 2 × 2 rectangle on the matrix are pressed at the same time, current can sneak through the pressed switches into another row and column, making it appear as if the remaining key is also pressed (which may look like an L-shape in a grid layout). This is ghosting (phantom key). Since it does not occur with simultaneous presses of up to two keys and only happens with specific combinations of three or more keys, it is difficult to detect during testing and is a troublesome phenomenon that is often discovered after products reach the market.

Three Ways to Prevent Ghosting

  • Insert a diode in series with each key:This is a fundamental countermeasure to cut off the reverse current (sneak path). If diodes are added to all keys, all simultaneous presses can be correctly detected regardless of how many keys are pressed. This is why diodes are attached to all keys on custom keyboard PCBs. Note that since the direction of the diode determines the polarity of row driving and column reading (or vice versa), the circuit and scanning method must be designed as a set.
  • Limit simultaneous presses in the specifications:(Assuming proper wiring and configuration) If simultaneous presses are limited to a maximum of two keys, ghosting (false detection of a fourth key caused by three active keys) cannot theoretically occur. Another method is to implement a defense (key jamming/blocking) in software, such as “suspecting an L-shaped combination when three or more keys are detected, and disabling the suspicious combination.” However, this does not resolve ghosting. It is a measure to avoid false detection at the cost of missing some simultaneous presses, and ghosting cannot be fundamentally eliminated in a passive matrix without diodes. The fundamental countermeasure is diodes.
  • Avoidance by key layout:By arranging keys that are operated simultaneously (such as shift keys + function keys) so that they are not placed on the same row or column, the ghosting condition will not be met in actual operation. This is a practical solution often used in mass-produced machines where additional components cannot be used.

Which one to choose depends on the cost and specifications. For reliable operation, use diodes; when minimizing cost is the priority, use layout plus software safeguards. Decide on an approach for each model accordingly.

Summary of Implementation Precautions

  • It is easier to design if pull-ups (internal is fine) are added to the column inputs and active-low driving is used consistently.
  • A scan cycle of about 5 to 10 ms is sufficient. If it is too fast, it only increases the number of debounce checks, and the benefits are small for most applications. However, in applications where high-speed input is required, a short cycle may be meaningful.
  • If the row and column wiring is long, consider noise countermeasures (capacitors and wiring routing) as well.
  • Design long-press detection and key repeats as a state machine managed by the duration of the confirmed state.

Summary

Although a key matrix is a simple mechanism that just drives rows one by one and reads columns, it has an inherent pitfall called ghosting. First, determine the specifications for simultaneous key presses, and then select diodes, layout, and software protection accordingly. Designing in this order allows you to increase the number of keys on the operation panel with confidence.

Back to The World of Embedded Software Top