# Haptic motor

The vibration in a Kode Dot: a linear resonant actuator, the driver that plays it over I2C, the one frequency it answers to, and the code to buzz.

## What it is

The Kode Dot vibrates with an **LRA**, a linear resonant actuator: a small
mass on a spring, not the spinning weight of an old phone. It moves when you
drive it with an alternating signal at or near its resonance, about 235 Hz,
and a steady voltage does nothing at all. Making it buzz means playing a
waveform, the way you play a tone through a speaker.

An **AW86233** driver on the antenna board does the playing. You stream
samples into its FIFO over I2C, and it drives the motor in a closed loop that
tracks the resonance. There is no pin to toggle: start, stop and status are
all registers.

## How it is connected

```mermaid
flowchart LR
  p4["ESP32-P4"] -- "I2C, 0x5A" --> drv["AW86233"]
  drv --> lra["LRA, 235 Hz"]
```

*Samples go over I2C into the driver's FIFO; the driver drives the motor*

The driver answers at `0x5A` on the shared I2C bus, reached across the flex
to the antenna board. Its enable is tied to the system rail, so it is on
whenever the board is, and its interrupt line does not reach the P4: every
status read is a poll.

## Specifications

| Thing | Value |
| --- | --- |
| Driver | AW86233QNR, U7, on the antenna board, at `0x5A` on the shared I2C bus, closed loop |
| Motor | LRA, resonance 235 Hz, 1.8 Vrms nominal, 1.9 Vrms maximum, 21 Ω |
| Enable | Tied to the rail: always on |
| Interrupt | Not routed to the P4. Poll over I2C |
| Playing | Real-time playback: stream samples through the FIFO, 12 kHz sample rate set in the driver |
| Kode driver | `kode_haptic_init`, then `kode_haptic_buzz(ms)` up to 2000 ms. Blocks for the duration |
| Prototype | The first boards carried an AW86223 at `0x58`; the driver probes both addresses |
| Validated | `Kode-Dot-Val/07-HAPTIC` on the prototype's AW86223. **TBD**: the AW86233's register map against it, on a V1 board |

## Gotchas

> **WARNING**
>
> **A weak buzz is the wrong frequency, not a weak motor.** An LRA off its
> resonance barely moves for the same drive, while every register reads back
> fine. The usual way there is a sine built for a sample rate the driver is not
> running at; at 48 kHz instead of 12 it comes out four times off.

> **WARNING**
>
> **The buzz breaks up.** The FIFO ran dry: streaming means the driver empties
> it faster than you fill it if you are late. Feed it in bursts and wait on the
> almost-full flag before each one, as the driver does.

> **NOTE**
>
> **`kode_haptic_buzz` blocks, so never call it from an LVGL callback.** It
> feeds the FIFO from the calling task for the whole duration. Call it from a
> task of your own.

## 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.

- https://apps.kode.diy/app/358599b5-9ee1-4d91-b1c5-47c93da98e0a
- https://apps.kode.diy/app/5d4012e8-74c6-4542-ab47-4b42a1927ef4
- https://apps.kode.diy/app/db6f7781-9d9c-4240-87cb-8f4f9bf1e796
- https://apps.kode.diy/app/5b864b5a-8d84-48c6-aba9-636b12c34aae

## Example code

Buzz for 200 ms every two seconds. You feel a short, firm pulse each time;
hold the Kode Dot rather than leaving it on the table.

```c
/*
 * haptic_pulse.c - 2026-09-18 - from Kode with love
 *
 * Pulses the Kode Dot's haptic motor for 200 ms every two seconds. Brings the
 * board up, wakes the driver through the Kode driver, then buzzes in a loop.
 * You feel a short, firm pulse each time.
 */
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "kode.h"

/* Board, driver, then one pulse per loop. */
void app_main(void)
{
    ESP_ERROR_CHECK(kode_bsp_init());
    ESP_ERROR_CHECK(kode_haptic_init());

    while (1) {
        ESP_ERROR_CHECK(kode_haptic_buzz(200));   /* returns when the motor stops */
        vTaskDelay(pdMS_TO_TICKS(1800));
    }
}
```

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

## In the SDK

- [`kdrv_aw86223.c`](https://github.com/kodediy/kode-sdk/blob/main/components/kdrv/kdrv_motion/kdrv_aw86223.c): the haptic driver in `kode-sdk`, written for the prototype's part. **TBD**: the AW86233.
