CircuitsFT232H. GPIO. Poller
(circuits_ft232h v0.1.0)
Copy Markdown
Per-chip polling GenServer that emulates GPIO interrupts.
These are NOT hardware interrupts
The FT232H has no hardware-generated pin-change notifications. We sample
the pin state on a fixed interval and emit
{:circuits_gpio, gpio_spec, timestamp, value} messages when subscribed
pins change in the desired direction.
Pulses shorter than the poll interval (default 10 ms) will be missed. Multiple edges within a single interval are collapsed into one notification with the final state.
One Poller per chip is started lazily on the first interrupt subscription
and registered in CircuitsFT232H.Registry under {:poller, device_id}.
When the last subscription goes away the Poller stops itself.
Each poll tick is one USB round-trip (~1 ms) that reads both the ADBUS and ACBUS ports in a single MPSSE transaction. All subscribed pins on the chip are sampled together, so adding more subscribed pins does not increase USB load.
Tuning the poll interval
The default interval is 10 ms (~100 Hz sampling). To change it:
config :circuits_ft232h, gpio_poll_interval_ms: 5Lower values reduce the size of pulses you can miss but cost more USB bandwidth and CPU. Practical floor is ~2 ms (the USB round-trip time). For mechanical buttons 10-20 ms is plenty; for fast signals you should look at an actual microcontroller.
Other notes
:suppress_glitchesis accepted but currently a no-op — there's only one sample per poll tick. Filtering glitches shorter than the poll interval would require over-sampling, which isn't implemented.- Subscriptions are auto-removed if the receiving process dies.
Summary
Functions
Subscribes the given receiver to edge notifications for pin on the chip
identified by device_id. Starts the Poller if it isn't running.
Returns the current subscriptions table for inspection in tests.
Removes any active subscription for pin on the chip identified by
device_id. The Poller stops itself once the last subscription goes away.
Types
@type subscription() :: %{ trigger: :rising | :falling | :both, receiver: pid(), suppress_glitches: boolean(), last_value: 0..1 }
Per-pin subscription record.
@type t() :: %CircuitsFT232H.GPIO.Poller{ device_id: CircuitsFT232H.Device.id(), interval_ms: pos_integer(), monitors: %{optional(pid()) => reference()}, subscriptions: %{optional(CircuitsFT232H.Device.pin()) => subscription()}, timer: reference() | nil }
Poller GenServer state.
Functions
@spec subscribe( CircuitsFT232H.Device.id(), CircuitsFT232H.Device.pin(), :rising | :falling | :both, keyword() ) :: :ok | {:error, term()}
Subscribes the given receiver to edge notifications for pin on the chip
identified by device_id. Starts the Poller if it isn't running.
trigger is one of :rising, :falling, :both.
Options:
:receiver(default the calling process) — the pid (or registered name) that will receive{:circuits_gpio, gpio_spec, timestamp, value}messages.:suppress_glitches(defaulttrue) — accepted but currently a no-op; see the moduledoc.
@spec subscriptions(CircuitsFT232H.Device.id()) :: %{ optional(CircuitsFT232H.Device.pin()) => subscription() }
Returns the current subscriptions table for inspection in tests.
@spec unsubscribe(CircuitsFT232H.Device.id(), CircuitsFT232H.Device.pin()) :: :ok
Removes any active subscription for pin on the chip identified by
device_id. The Poller stops itself once the last subscription goes away.
@spec whereis(CircuitsFT232H.Device.id()) :: {:ok, pid()} | {:error, :not_started}