BMI323. Sampler
(bmi323 v0.1.0)
Copy Markdown
GenServer that drains the BMI323's on-chip FIFO and dispatches sample frames to a subscriber process.
Why this exists
Polling the BMI323's data-ready bits from the BEAM is unreliable at higher ODRs: the scheduler can lose samples between polls. The chip's 2 KB FIFO and hardware interrupt pin solve this by buffering samples and notifying the host on a watermark threshold. This module wires those features up.
Configurable FIFO frame format
The sampler accepts any non-empty subset of :accelerometer, :gyroscope,
:temperature, and :sensor_time via the :sources option. The chip emits
frames in the canonical order
(accel → gyro → temp → sensor_time), and BMI323.Fifo.parse_frames/3 decodes
whichever subset is enabled. See BMI323.Fifo for the protocol details.
Each sample is dispatched as a {BMI323.Sampler, sampler_pid, [frame, ...]}
message. Frames are maps containing only the enabled sources — see
BMI323.Fifo.frame/0.
Usage
{:ok, i2c} = Wafer.Driver.Circuits.I2C.acquire(bus_name: "i2c-1", address: 0x68)
{:ok, bmi} = BMI323.acquire(conn: i2c, soft_reset: true)
{:ok, bmi} = BMI323.configure_accelerometer(bmi, mode: :normal, range: 4, odr: 200)
{:ok, bmi} = BMI323.configure_gyroscope(bmi, mode: :normal, range: 2000, odr: 200)
{:ok, int1} = Wafer.Driver.Circuits.GPIO.acquire(pin: 17, direction: :in)
{:ok, _sampler} =
BMI323.Sampler.start_link(
bmi: bmi,
int1: int1,
sources: [:accelerometer, :gyroscope, :sensor_time],
watermark_frames: 8
)
receive do
{BMI323.Sampler, _pid, frames} -> IO.inspect(frames)
end
Summary
Functions
Returns a specification to start this module under a supervisor.
Synchronously drain the FIFO and return any complete frames. Used in pull-only mode (no INT1 wired) or when the caller wants the latest state on demand.
Issue a FIFO flush via FIFO_CTRL.
Start a FIFO sampler.
Types
@type option() :: {:bmi, BMI323.t()} | {:int1, Wafer.Conn.t() | nil} | {:subscriber, pid()} | {:watermark_frames, pos_integer()} | {:sources, [BMI323.Fifo.source()]} | {:stop_on_full, boolean()} | {:name, GenServer.name()}
Options accepted by start_link/1.
@type t() :: %BMI323.Sampler{ bmi: BMI323.t(), frame_words: pos_integer(), int1: Wafer.Conn.t() | nil, ranges: BMI323.Fifo.ranges(), sources: [BMI323.Fifo.source()], subscriber: pid(), watermark_frames: pos_integer() }
Internal sampler state.
Functions
Returns a specification to start this module under a supervisor.
See Supervisor.
@spec drain(GenServer.server()) :: {:ok, [BMI323.Fifo.frame()]} | {:error, term()}
Synchronously drain the FIFO and return any complete frames. Used in pull-only mode (no INT1 wired) or when the caller wants the latest state on demand.
@spec flush(GenServer.server()) :: :ok | {:error, term()}
Issue a FIFO flush via FIFO_CTRL.
@spec start_link([option()]) :: GenServer.on_start()
Start a FIFO sampler.
Options
:bmi(required) — aBMI323struct. The cached ranges on the struct must cover every scaled source (:accelerometer_rangeif:accelerometeris in:sources,:gyroscope_rangefor:gyroscope).:int1(optional) — aWafer.GPIO-implementing connection wired to the device's INT1 pin. If absent the sampler runs in pull-only mode; calldrain/1to fetch buffered frames.:subscriber(defaultself()) — process to which sample messages are delivered.:watermark_frames(default8) — fire the watermark interrupt after this many frames have accumulated in the FIFO.:sources(default[:accelerometer, :gyroscope, :temperature, :sensor_time]) — list of FIFO sources to enable. Order is irrelevant; the chip always emits in canonical order.:stop_on_full(defaultfalse) — whentrue, the FIFO stops accepting new data on overflow instead of overwriting oldest.:name— optional GenServer registration name.