> ## Documentation Index
> Fetch the complete documentation index at: https://docs.oryx.mechatronstudio.com/llms.txt
> Use this file to discover all available pages before exploring further.

# ESP32 firmware

> What the sketch is, how to flash it and what limits it has.

The generator needs a sketch flashed once. It receives the signal you have open
in the editor and plays it on its outputs.

<Note>
  **It does not connect to the internet, to a cloud, or to any server**: the link
  is always point to point, over the USB cable.
</Note>

## What you need

| What               | Detail                                             |
| ------------------ | -------------------------------------------------- |
| Board              | A classic ESP32 (WROOM / DevKit v1)                |
| Core               | Arduino for ESP32, 2.x or 3.x                      |
| External libraries | None                                               |
| File               | `firmware/oryx_signal_esp32/oryx_signal_esp32.ino` |

## Flashing it

<Steps>
  <Step title="Install the core">
    Arduino IDE → Boards Manager → **esp32 by Espressif Systems**.
  </Step>

  <Step title="Pick the board">
    *ESP32 Dev Module*, and the port it is plugged into.
  </Step>

  <Step title="Upload the sketch">
    Open `oryx_signal_esp32.ino` and upload. It needs no external libraries.
  </Step>

  <Step title="Close the serial monitor">
    Before connecting from the app: while it is open, the port is taken.
  </Step>
</Steps>

The serial monitor (115200) shows a greeting at boot.

<Tip>
  The firmware code is also inside the app, in **Device → ESP32 firmware**, with a
  button to copy it.
</Tip>

## Outputs

| Mode        | Where it comes out                                                         |
| ----------- | -------------------------------------------------------------------------- |
| **Digital** | GPIO 16, 17, 18, 19, 21, 22, 23, 13 — one pin per channel, in editor order |
| **Analog**  | GPIO 25 (DAC1) and GPIO 26 (DAC2) — up to two channels                     |

### Voltage

In **analog**, the voltage scales directly what the DAC puts out, between 0 and
3.3 V.

In **digital**, a pin knows nothing of intermediate levels: it outputs 3.3 V or
0\. There the voltage value comes out on **GPIO 25 as a steady reference
voltage**, meant to feed the external stage —divider, buffer or level shifter—
that sets the real pulse height.

<Warning>
  Without that external stage, the pins always output 3.3 V and the voltage setting
  changes nothing.
</Warning>

## Device limits

| What                         | How much |
| ---------------------------- | -------- |
| Digital channels             | 8        |
| Analog channels              | 2        |
| State changes (digital)      | 2048     |
| Samples per channel (analog) | 6000     |
| Minimum step time            | 5 µs     |

If your signal does not fit, the app tells you before sending it and explains
what was adjusted.

## Cycles and step time

Both adjust the same thing from two sides:

* With **cycles at 0**, the step time rules as it is.
* With **cycles above 0**, one full pass of the signal is one engine revolution:

```
step time (µs) = 60 000 000 / (rpm × total steps)
```

Changing either one **restarts the pass in progress**, so the change shows on the
oscilloscope right away. The lap counter is not zeroed: that is what *Restart* is
for.

## When the signal stops on its own

If the cable comes loose or you close the tab, the signal stops and the outputs
go low. It is on purpose: the device cannot find out that nobody is on the other
end, so if it goes a while without receiving orders it treats the link as
finished.
