# `Nanodrop.OOI`

Ocean Optics Interface (OOI) protocol implementation.

This module implements the USB2000 command protocol for communicating
with NanoDrop spectrophotometers and defines the raw spectrum data structure.

## Command Reference

| Command | Hex  | Description |
|---------|------|-------------|
| Initialize | 0x01 | Initialize spectrometer |
| Set Integration Time | 0x02 | Set integration time in µs |
| Set Strobe Enable | 0x03 | Enable/disable strobe |
| Set Shutdown Mode | 0x04 | Enter low-power mode |
| Query Information | 0x05 | Query device info/calibration |
| Write Information | 0x06 | Write configuration |
| Request Spectra | 0x09 | Trigger spectrum acquisition |
| Set Trigger Mode | 0x0A | Set triggering mode |

## Raw Spectrum Data

The USB2000 returns 2048 pixel values representing light intensity across
the detector. The wavelength for each pixel is calculated using calibration
coefficients stored on the device:

    λ(N) = C0 + C1*N + C2*N² + C3*N³

Pixels 2-24 are "dark pixels" - optically masked for dark current subtraction.

# `t`

```elixir
@type t() :: %Nanodrop.OOI{raw_pixels: [non_neg_integer()], timestamp: DateTime.t()}
```

# `dark_average`

```elixir
@spec dark_average(t()) :: float()
```

Calculates the average dark pixel value.

# `dark_pixels`

```elixir
@spec dark_pixels(t()) :: [non_neg_integer()]
```

Returns the dark pixel values (pixels 2-24).

# `from_raw`

```elixir
@spec from_raw(binary()) :: t()
```

Creates an OOI struct from raw binary data.

The data should be 4096 bytes (2048 x 16-bit little-endian values).

# `get_dark_spectrum`

```elixir
@spec get_dark_spectrum(Nanodrop.Device.t()) :: {:ok, t()} | {:error, term()}
```

Acquires a dark spectrum (no lamp/strobe).
Use this for dark calibration to measure detector baseline.

# `get_spectrum`

```elixir
@spec get_spectrum(Nanodrop.Device.t()) :: {:ok, t()} | {:error, term()}
```

Acquires a spectrum from the device with the lamp/strobe firing.
Use this for blank and sample measurements.

# `initialize`

```elixir
@spec initialize(Nanodrop.Device.t()) :: :ok | {:error, term()}
```

Initializes the spectrometer.

# `max_intensity`

```elixir
@spec max_intensity(t()) :: non_neg_integer()
```

Returns the maximum pixel intensity.

# `query_info`

```elixir
@spec query_info(Nanodrop.Device.t(), atom()) :: {:ok, term()} | {:error, term()}
```

Queries device information.

# `set_integration_time`

```elixir
@spec set_integration_time(Nanodrop.Device.t(), pos_integer()) ::
  :ok | {:error, term()}
```

Sets the integration time in microseconds.

Valid range: 3,000 - 655,350,000 µs

# `set_strobe_enable`

```elixir
@spec set_strobe_enable(Nanodrop.Device.t(), boolean()) :: :ok | {:error, term()}
```

Enables or disables the strobe.

# `set_trigger_mode`

```elixir
@spec set_trigger_mode(Nanodrop.Device.t(), 0..3) :: :ok | {:error, term()}
```

Sets the trigger mode.

Modes:
- 0: Normal (free running)
- 1: Software trigger
- 2: External hardware level trigger
- 3: External synchronization trigger

---

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