# `CircuitsFT232H.MPSSE`

Pure-function encoder for the FT232H Multi-Protocol Synchronous Serial
Engine (MPSSE) command stream.

This module knows nothing about USB or transports. It builds binaries you
hand to `CircuitsFT232H.USB.write/3`, and helps interpret bytes you read
back via `CircuitsFT232H.USB.read/3`.

Opcode names and semantics mirror FTDI Application Note
[AN_108](https://ftdichip.com/wp-content/uploads/2020/08/AN_108_Command_Processor_for_MPSSE_and_MCU_Host_Bus_Emulation_Modes.pdf).

# `bit_order`

```elixir
@type bit_order() :: :msb_first | :lsb_first
```

Order in which a byte's bits are clocked out / in.

# `clock_base`

```elixir
@type clock_base() :: :high_speed | :legacy
```

Which MPSSE base clock to compute against.

# `clock_edge`

```elixir
@type clock_edge() :: :positive | :negative
```

Clock edge on which a data bit is driven or sampled.

# `bad_command_byte`

```elixir
@spec bad_command_byte() :: byte()
```

The MPSSE byte that precedes the echo of an unrecognised opcode.

# `clock_divisor`

```elixir
@spec clock_divisor(pos_integer(), clock_base()) :: 0..65535
```

Computes the MPSSE divisor that produces `target_hz` SCK, given the base
clock.

Use `:high_speed` (default) for the 60 MHz base (FT232H, requires
`disable_clock_divide_by_5/0`) and `:legacy` for the 12 MHz base
(FT2232D-compatible, requires `enable_clock_divide_by_5/0`).

The formula is `SCK = base / ((1 + divisor) × 2)`. Result is rounded and
clamped to `0..0xFFFF`.

# `disable_3_phase_clocking`

```elixir
@spec disable_3_phase_clocking() :: binary()
```

Disables 3-phase data clocking (normal 2-phase SPI behaviour).

# `disable_adaptive_clocking`

```elixir
@spec disable_adaptive_clocking() :: binary()
```

Disables adaptive clocking (the chip's default).

# `disable_clock_divide_by_5`

```elixir
@spec disable_clock_divide_by_5() :: binary()
```

Selects the 60 MHz MPSSE base clock (H-series chips only). Required
for SCK frequencies above 6 MHz.

# `enable_3_phase_clocking`

```elixir
@spec enable_3_phase_clocking() :: binary()
```

Enables 3-phase data clocking. Required for I2C, and for SPI modes that
drive on one edge and sample on the same edge (`CPHA = 1`).

# `enable_adaptive_clocking`

```elixir
@spec enable_adaptive_clocking() :: binary()
```

Enables adaptive clocking — MPSSE pauses after each clock pulse until
`GPIOL3` (`ADBUS7`) is driven high.

Originally designed so MPSSE could synchronise with an ARM target's
`RTCK` signal, this gives a free clock-stretching mechanism for I2C if
`ADBUS0` (SCL) is externally jumpered to `ADBUS7`: the slave can hold
SCL low and MPSSE will wait for it.

# `enable_clock_divide_by_5`

```elixir
@spec enable_clock_divide_by_5() :: binary()
```

Selects the legacy 12 MHz MPSSE base clock (for compatibility with
FT2232D-style code).

# `enable_drive_zero`

```elixir
@spec enable_drive_zero(byte(), byte()) :: binary()
```

Configures pins to operate in open-drain mode.

Pins set in the masks drive low when their output bit is `0`, and are
tristated when their output bit is `1`. Combined with external pull-up
resistors this provides true open-drain behaviour — the key trick that
makes I2C work on the FT232H.

Available on FT232H only (not FT2232D / FT2232C).

# `find_bad_command`

```elixir
@spec find_bad_command(binary()) :: {:bad_command, byte()} | :ok
```

Scans `response` for a `BAD_COMMAND` marker (`0xFA`) and returns the
offending opcode if found.

# `get_bits_high`

```elixir
@spec get_bits_high() :: binary()
```

Reads the current state of `ACBUS0`..`ACBUS7`. Response is 1 byte.

# `get_bits_low`

```elixir
@spec get_bits_low() :: binary()
```

Reads the current state of `ADBUS0`..`ADBUS7`. Response is 1 byte.

# `loopback_off`

```elixir
@spec loopback_off() :: binary()
```

Disables internal loopback (the normal state).

# `loopback_on`

```elixir
@spec loopback_on() :: binary()
```

Enables internal TDI→TDO loopback. Useful for init self-tests.

# `read_bits`

```elixir
@spec read_bits(
  1..8,
  keyword()
) :: binary()
```

Clocks `count` bits in from TDO/DI. Response is one byte; the relevant
bits are right-justified (MSB-first) or left-justified (LSB-first)
depending on `:bit_order`.

Same options as `read_bytes/2`.

# `read_bytes`

```elixir
@spec read_bytes(
  pos_integer(),
  keyword()
) :: iodata()
```

Reads `count` bytes in on the TDO/DI pin while clocking SCK. No data is
driven out.

Options:
  * `:edge` (default `:positive`) — clock edge on which to sample each bit.
  * `:bit_order` (default `:msb_first`).

# `sck_frequency`

```elixir
@spec sck_frequency(0..65535, clock_base()) :: float()
```

Returns the SCK frequency produced by the given divisor on the given base
clock. Inverse of `clock_divisor/2` (with rounding).

# `send_immediate`

```elixir
@spec send_immediate() :: binary()
```

Flushes any pending bytes in the chip's internal IN buffer back to the
host. Append this whenever you need to read a response right away.

# `set_bits_high`

```elixir
@spec set_bits_high(byte(), byte()) :: binary()
```

Sets the high-byte GPIO port (`ACBUS0`..`ACBUS7`) state. See `set_bits_low/2`.

# `set_bits_low`

```elixir
@spec set_bits_low(byte(), byte()) :: binary()
```

Sets the low-byte GPIO port (`ADBUS0`..`ADBUS7`) state.

`value` is the level each output pin should drive (bit 0 = `ADBUS0`).
`direction` is the per-pin direction mask — `1` for output, `0` for input.
In MPSSE mode the engine overrides direction for SCK / MOSI / MISO so it
is safe to leave those as outputs in the direction mask.

# `set_tck_divisor`

```elixir
@spec set_tck_divisor(0..65535) :: binary()
```

Sets the SCK clock divisor. Get the right divisor via `clock_divisor/2`.

# `transfer_bits`

```elixir
@spec transfer_bits(byte(), 1..8, keyword()) :: binary()
```

Full-duplex bit transfer. Drives the bottom `count` bits of `value` while
sampling TDO/DI. Response is one byte.

Same options as `transfer_bytes/2`.

# `transfer_bytes`

```elixir
@spec transfer_bytes(
  binary(),
  keyword()
) :: iodata()
```

Full-duplex byte transfer — drives `data` out on TDI/DO and simultaneously
samples TDO/DI back. The response is `byte_size(data)` bytes long.

Options:
  * `:write_edge` (default `:negative`) — clock edge on which to drive.
  * `:read_edge` (default `:positive`) — clock edge on which to sample.
  * `:bit_order` (default `:msb_first`).

# `write_bits`

```elixir
@spec write_bits(byte(), 1..8, keyword()) :: binary()
```

Writes the bottom `count` bits of `value` out the TDI/DO pin while
clocking SCK. `count` must be in `1..8`.

Same options as `write_bytes/2`.

# `write_bytes`

```elixir
@spec write_bytes(
  binary(),
  keyword()
) :: iodata()
```

Writes `data` out the TDI/DO pin while clocking SCK.

Options:
  * `:edge` (default `:negative`) — clock edge on which to drive each bit.
  * `:bit_order` (default `:msb_first`) — bit order within each byte.

The chip transmits `byte_size(data)` bytes. The command auto-splits into
multiple `0x1?` blocks if `data` is longer than 65536 bytes.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
