# v0.3.1

- **Breaking:** `UpdateData.scanned_lines`/`total_lines` are replaced by a single
  `progress` float, 0.0 -> 1.0 within the current `phase`. Line counts only ever
  meant anything during SCANNING, which left every other phase reporting `None`
  and each consumer writing the same division; a fraction is what a progress
  indicator wants and it now applies to every phase. CALIBRATING reports the
  shading read's fraction and WARMING_UP its progress through the START SCAN
  retry budget; phases whose length the device does not announce report 0.0
- **Breaking:** the `calibrate` option is replaced by `reuse_calibration`, with
  the opposite polarity and the same default behaviour (`calibrate=True` is
  `reuse_calibration=False`, still the default). The old name promised something
  it could not deliver: skipping calibration is a request, not a decision, and
  the option now says so
- Skipping calibration is honoured, where before it changed the SET MODE quality
  bit and nothing else. A pass acquires a shading reference unless
  `reuse_calibration` is set AND one is already cached; the scanner can still
  refuse, which it signals by answering START SCAN with MUST_CALIBRATE, and then
  the pass calibrates anyway. `ScanPhase.CALIBRATING` is reported only when a
  pass actually calibrates
- Shading references are cached on the `Scanner` for the life of the device
  session, so a pass that skips calibration corrects from the one an earlier pass
  read. Following the C backend, which keeps `shading_ref`/`shading_mean` on the
  open device handle (`pieusb_specific.h:292-294`). Practical consequence: keep
  one `Scanner` open across a batch, since a fresh one starts with a cold cache
  and calibrates on its first scan regardless of the option. The cache is dropped
  if the device starts reporting a different shading width, and an unusable read
  keeps the previous reference rather than falling back to raw pixels
- With `auto_exp`, the metering pass calibrates and the real pass reuses that
  reference: one calibration per scan instead of two
- `set_options()` takes `skip_shading_analysis` as a keyword argument, since
  whether a pass can skip depends on the Scanner's cache and not on an option
  alone
- The scan sequence proper is now `Scanner._scan_pass(started, emit)`, shared by
  the real scan and the auto-exposure metering pass, which differ only in the
  options in force and in the `emit` callback that labels their progress.
  Replaces the `_phase_override` attribute that relabelled updates inside
  `_emit()`
- Implemented the `auto_exp` option, which until now warned and did nothing. It
  runs a preview pass at the device's preview resolution, measures the 99th
  percentile of each colour plane against the CCD saturation levels, and derives
  new `gain_*`/`exp_*` settings before the real scan. A port of the SANE
  backend's "calibration from preview" path (`sanei_pieusb_analyze_preview`,
  `sanei_pieusb_set_gain_offset`, `updateGain2`), in the new
  `pieusb.calibration` module. The preview pass reports its progress under a new
  `ScanPhase.METERING` so it is distinguishable from the real scan
- `_get_gain_offset()` now also returns the `saturation_level` triple that
  auto-exposure meters against (GET GAIN OFFSET byte 54)
- **Breaking:** split the exposure options, which conflated two independent
  device controls behind one name. `exp_r`/`exp_g`/`exp_b`/`exp_i` are gone;
  there are now two families:
  - `exp_time_r`/`_g`/`_b`/`_i` -- ABSOLUTE integration time in Timer 1 counts,
    carried by SET GAIN OFFSET. This is the real exposure control and the one
    auto-exposure moves. Its default changes from 100 to 2937 (SANE's
    DEFAULT_EXPOSURE, the value the firmware itself falls back to) and its upper
    bound is the inquiry maximum times 4 -- without which the device's own
    default is outside the range the device reports
  - `exp_rel_r`/`_g`/`_b` -- RELATIVE exposure percentage, sent by the
    SCSI_EXPOSURE write. No infrared entry, because the device has none. **Leave
    this at 100.** SANE hard-codes it and exposes no option for it, so no other
    value has been exercised against this hardware; it is redundant with
    `exp_time_*`; and auto-exposure's saturation reference assumes it is at 100.
    `OptionsTable.validate()` warns once per scan if it is moved
  The previous single option fed *both* commands, so the value written to the
  SET GAIN OFFSET exposure time was the relative percentage's 100 rather than an
  exposure time. Existing callers setting `exp_*` must rename to `exp_time_*`
- Added `Unit.PERCENT` and `Unit.TIMER_COUNTS`; exposure times are not
  expressible in microseconds without the Timer 1 clock rate, which the device
  does not report

# 0.2.0

- Added wait() API to block until the scan is finished
- Added close(), which cancels a running scan and waits for the worker before
  releasing the USB interface. `with Scanner(...)` now goes through it, so
  leaving the block mid-scan no longer closes the device under the worker
- Fixed Scanner construction: the option attribute accessors recursed on
  `self.params` before the option table existed, so `Scanner(info)` always
  raised RecursionError
- Reading an option attribute returns its value rather than the internal
  Parameter, and an unknown name raises AttributeError rather than KeyError
- Setting an option while a scan is running raises ScanInProgress

# 0.1.0

Initial release