# `LIS3DH.Interrupts`

Encoding and decoding for the LIS3DH's inertial interrupt configuration
(`INT1_CFG`, `INT1_THS`, `INT1_DURATION` and their `INT2_*` siblings) plus
the per-pin routing bits in `CTRL_REG3` and `CTRL_REG6` and the
latching/4D bits in `CTRL_REG5`.

The chip has two physical interrupt pins, INT1 and INT2, each driven by a
configurable mix of event sources:

  * inertial interrupts 1 / 2 (AOI engines reading `INT*_CFG`),
  * click detection,
  * data-ready for accelerometer (`ZYXDA`) or auxiliary ADC (`321DA`),
  * FIFO watermark / overrun (INT1 only — handled by `LIS3DH.Sampler`),
  * activity / boot (INT2 only).

An inertial interrupt fires when the per-axis event flags in `INT*_CFG`
combine according to the `AOI` / `6D` bits:

```text
AOI  6D   Behaviour
 0   0   OR of the enabled axis events (e.g. wake-up / motion)
 0   1   6D movement recognition (entering a known zone)
 1   0   AND of the enabled axis events (e.g. free-fall)
 1   1   6D position recognition (currently in a known zone)
```

Threshold and duration registers carry units that depend on the configured
full-scale range and ODR; see `threshold_lsb_mg/1` and the helpers in
`LIS3DH` for unit-aware wrappers.

# `aoi_mode`

```elixir
@type aoi_mode() :: :or | :and | :six_d_movement | :six_d_position
```

Combined AOI/6D field in `INT*_CFG`.

  * `:or` — OR of enabled axis events.
  * `:and` — AND of enabled axis events.
  * `:six_d_movement` — interrupt when orientation enters a known zone.
  * `:six_d_position` — interrupt while orientation is inside a known zone.

# `axis_event`

```elixir
@type axis_event() :: :x_high | :x_low | :y_high | :y_low | :z_high | :z_low
```

Per-axis-direction event flags. Each entry enables interrupt generation
when the named axis crosses the configured threshold in the named
direction.

# `pin`

```elixir
@type pin() :: :int1 | :int2
```

Which interrupt pin a configuration applies to.

# `source_flags`

```elixir
@type source_flags() :: %{
  active: boolean(),
  x_high: boolean(),
  x_low: boolean(),
  y_high: boolean(),
  y_low: boolean(),
  z_high: boolean(),
  z_low: boolean()
}
```

Decoded `INT*_SRC` flags. `:active` is the master IA bit; the per-axis
fields report which axis-direction events fired during the latched window
(or this read, for non-latched mode).

# `decode_int_cfg`

```elixir
@spec decode_int_cfg(&lt;&lt;_::8&gt;&gt;) :: %{mode: aoi_mode(), axes: [axis_event()]}
```

Decode an `INT*_CFG` byte into a map of its fields.

# `decode_int_src`

```elixir
@spec decode_int_src(&lt;&lt;_::8&gt;&gt;) :: source_flags()
```

Decode an `INT*_SRC` byte into a map of its fields.

# `encode_duration!`

```elixir
@spec encode_duration!(0..127) :: &lt;&lt;_::8&gt;&gt;
```

Encode a duration in ODR counts into a 7-bit `INT*_DURATION` register
value. Each LSB is `1/ODR` (so at 100 Hz, count=1 ≈ 10 ms).

# `encode_int_cfg`

```elixir
@spec encode_int_cfg(keyword()) :: &lt;&lt;_::8&gt;&gt;
```

Encode an `INT*_CFG` byte from keyword options.

## Options

  * `:mode` — `t:aoi_mode/0` (default `:or`).
  * `:axes` — list of `t:axis_event/0` to enable (default `[]`).

# `encode_threshold!`

```elixir
@spec encode_threshold!(non_neg_integer(), LIS3DH.Config.range()) :: &lt;&lt;_::8&gt;&gt;
```

Encode a threshold in milli-g into a 7-bit `INT*_THS` register value for
the given range. Rounds down. Clamps at the 7-bit maximum (127).

# `threshold_lsb_mg`

```elixir
@spec threshold_lsb_mg(LIS3DH.Config.range()) :: pos_integer()
```

Returns the threshold register's LSB size in milli-g for the given full-
scale range, per datasheet §8.23 / §8.27.

---

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