Kode Dot

Buttons

The six buttons on a Kode Dot: a four-way pad and two singles, how five of them reach the P4 through an expander, and the code to read them.

top
pad_up
pad_left
pad_right
pad_down
bot

What it is

Six push-buttons: a four-way pad on the front, and one single button above it and one below. Each is a switch to ground with a pull-up, so a line reads high at rest and low while pressed. That is all a button is: one bit, pressed or not, no pressure and no analogue level.

They do not all reach the P4 the same way. Five of them, the pad and the bottom single, hang off a TCA6408 I2C port expander and come back as five bits of one byte. The sixth, the top single, is wired straight to a P4 pin. Reading the buttons is one I2C read plus one pin read, which the Kode driver combines for you.

How it is connected

flowchart LR
p4["ESP32-P4"] -- "I2C, 0x20" --> exp["TCA6408"]
exp -- "P0" --> bot["bottom"]
exp -- "P1..P4" --> pad["pad: up, left, down, right"]
top["top"] -- "GPIO35" --> p4
Five buttons through the expander on the I2C bus, one straight to a pin

The expander answers at 0x20 on the shared I2C bus and has 10 kΩ pull-ups on the board for its five button lines. The top button is on GPIO35 with the P4's internal pull-up. The expander's interrupt line reaches GPIO6, but Kode's examples poll on a timer instead.

Specifications

ThingValue
ButtonsSix, all active low: pressed reads 0
ExpanderTCA6408, U24, at 0x20 on the shared I2C bus
Bottom singleExpander P0
Pad up, left, down, rightExpander P1, P2, P3, P4
Top singleGPIO35 on the P4
Pull-ups10 kΩ on the board for the five; the P4's internal one for the top
InterruptExpander interrupt on GPIO6, unused by any Kode example
Kode driverkode_buttons_init, then kode_buttons_pressed(btn) for one or kode_buttons_mask() for all six in one read
ValidatedKode-Dot-Val/11-INPUT: all six on a board

Gotchas

Apps that use it

On the marketplace, apps that put this part to work. Install one from start/first-app and see it before you write a line.

Example code

Log every button as it goes down. Press the pad and the two singles and each one prints its name once per press.

/*
 * buttons_log.c - 2026-09-18 - from Kode with love
 *
 * Watches the Kode Dot's six buttons twenty times a second and logs each one
 * the moment it goes down. Brings the board up, configures the buttons through
 * the Kode driver, then polls the six-bit mask and reports the edges.
 */
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "kode.h"
 
static const char *NAMES[] = { "bottom", "pad up", "pad left", "pad down", "pad right", "top" };
 
/* Board, buttons, then compare each poll with the last one. */
void app_main(void)
{
    ESP_ERROR_CHECK(kode_bsp_init());
    ESP_ERROR_CHECK(kode_buttons_init());
 
    uint8_t last = 0;
    while (1) {
        uint8_t now = kode_buttons_mask();          /* bit N set while button N is down */
        uint8_t went_down = now & ~last;
        for (int i = 0; i < 6; i++) {
            if (went_down & (1 << i)) ESP_LOGI("buttons", "%s", NAMES[i]);
        }
        last = now;
        vTaskDelay(pdMS_TO_TICKS(50));
    }
}

Compiled on the date in the header against the kode component with ESP-IDF v6.1. TBD: a run on a V1 board.

In the SDK