# `CircuitsFT232H.GPIO`

GPIO support for the FT232H's general-purpose pins.

The FT232H exposes 16 GPIO pins. The labels match the silkscreen on the
Adafruit FT232H breakout:

| Label    | Linear pin number | Notes                           |
| -------- | ----------------- | ------------------------------- |
| `AD0`    | 0                 | Shared with SCK (SPI) / SCL (I2C) |
| `AD1`    | 1                 | Shared with MOSI / SDA-out      |
| `AD2`    | 2                 | Shared with MISO / SDA-in       |
| `AD3`    | 3                 | Shared with CS (SPI)            |
| `AD4`-`AD7` | 4..7           | Free                            |
| `AC0`-`AC7` | 8..15          | Free                            |

GPIO can run alongside an active I2C or SPI bus on the same chip, provided
the pin doesn't overlap with the protocol's reserved pins (see the table
above). The `CircuitsFT232H.Device` GenServer enforces this.

Public API lives on `CircuitsFT232H.GPIO.Backend` (a `Circuits.GPIO.Backend`
implementation) and `CircuitsFT232H.GPIO.Handle` (the per-pin handle
returned by `Circuits.GPIO.open/3`). This module holds shared parsing and
identifier helpers.

# `pin`

```elixir
@type pin() :: CircuitsFT232H.Device.pin()
```

# `pin_ref`

```elixir
@type pin_ref() :: %{
  controller: CircuitsFT232H.Device.id(),
  pin: pin(),
  label: String.t()
}
```

Combined identifier for one FT232H pin: device id + pin number + label.

# `all_pin_refs`

```elixir
@spec all_pin_refs() :: [pin_ref()]
```

Lists all GPIO pins on every connected FT232H, in canonical order.

# `find_descriptor`

```elixir
@spec find_descriptor(CircuitsFT232H.Device.id()) ::
  {:ok, CircuitsFT232H.USB.Descriptor.t()} | {:error, :not_found | term()}
```

Looks up the `USB.Descriptor` for the given controller id, or an error if
no chip with that id is connected.

# `identifiers`

```elixir
@spec identifiers(pin_ref()) :: map()
```

Builds a `Circuits.GPIO.identifiers()` map for `pin_ref`.

# `label`

```elixir
@spec label(pin()) :: String.t()
```

Returns the label for a linear pin number (`0..15`).

# `parse_label`

```elixir
@spec parse_label(String.t()) :: {:ok, pin()} | {:error, :invalid_label}
```

Parses an `"AD<n>"`/`"AC<n>"` label into a linear pin number.

# `resolve`

```elixir
@spec resolve(any()) ::
  {:ok, pin_ref()}
  | {:error,
     :invalid_label | :invalid_pin | :no_device | :ambiguous_device | term()}
```

Resolves a `Circuits.GPIO.gpio_spec()` into a fully qualified `pin_ref`
identifying both the chip and the pin within it.

Accepted forms:
  * `{controller, line_offset}` — e.g. `{"ftdi-3:8", 4}`
  * `{controller, label}` — e.g. `{"ftdi-3:8", "AD4"}`
  * `label` — e.g. `"AD4"`; requires exactly one FT232H attached
  * `line_offset` (integer 0..15) — requires exactly one FT232H attached

---

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