From 27099b95660b9031e3d2403f4efc38c474a0431c Mon Sep 17 00:00:00 2001 From: Mike Langmayr <1809691+mikelangmayr@users.noreply.github.com> Date: Wed, 23 Sep 2026 16:33:56 -0700 Subject: [PATCH] Document the instruments, with the tracking camera in depth --- docs/configuration/core.md | 7 +- docs/instruments/cryoscope.md | 30 ++++- docs/instruments/hispec-tracking-camera.md | 123 ++++++++++++++++----- docs/instruments/index.md | 9 +- 4 files changed, 135 insertions(+), 34 deletions(-) diff --git a/docs/configuration/core.md b/docs/configuration/core.md index 5b89443..e91b30c 100644 --- a/docs/configuration/core.md +++ b/docs/configuration/core.md @@ -5,9 +5,12 @@ Keys the server itself reads, independent of the frame outputs. :::{important} These tables list only keys the code actually reads. Configuration files in the wild, and the superseded 2022 ICD, carry a number of keys that nothing reads any more: `IMDIR`, `BASENAME`, -`AUTODIR`, `DIRMODE`, `DAEMON`, `LONGERROR`, `TM_ZONE`, `TZ_ENV`, `ASYNCPORT`, `ASYNCGROUP` and -`START_PARAM` among them. Setting them has no effect. Image naming and location moved to the +`AUTODIR`, `DIRMODE`, `DAEMON`, `LONGERROR`, `TM_ZONE`, `TZ_ENV`, `ASYNCPORT` and `ASYNCGROUP` +among them. Setting them has no effect. Image naming and location moved to the [frame output keys](frame-outputs.md). + +Instrument modules read keys of their own, which are documented with the +[instrument](../instruments/index.md) rather than here. ::: ## Controller connection diff --git a/docs/instruments/cryoscope.md b/docs/instruments/cryoscope.md index 2fe9de1..559d777 100644 --- a/docs/instruments/cryoscope.md +++ b/docs/instruments/cryoscope.md @@ -5,11 +5,35 @@ An H2RG on an Archon controller, reading in RXR mode. Repository: [cryoscope-instrument](https://github.com/CaltechOpticalObservatories/cryoscope-instrument), checked out at `camerad/Instruments/cryoscope`. -:::{note} -Expands in M4. The module defines a `CryoScope` interface deriving from `ArchonInterface`, with its -own exposure modes, and registers no additional instrument commands beyond the base set. +:::{warning} +This module does not currently build against the core. Its exposure mode instantiates +`ExposureModeTemplate` with two template parameters where the base declares one, and assigns to +`modetype` and `modeargs`, which are named `type` and `args` in +{source}`camerad/exposure_modes.h`. It was left behind by a refactor of the exposure mode base +class. + +CI does not catch this, because the build workflow compiles the default target and only builds an +instrument when one is named explicitly. ::: +## What it defines + +`CryoScope` derives from `ArchonInterface` and overrides `instrument_cmd`, +`configure_instrument`, `power`, `get_exposure_modes` and `set_exposure_mode`, plus a private +`setup_detector()`. + +It registers no instrument-specific commands beyond the base set, and its exposure mode is still a +placeholder named `XXX`. + +## Configuration + +| Key | Meaning | +|---|---| +| `START_PARAM` | Archon parameter used to start the timing script | + +`START_PARAM` is read only by this module, which is why it does not appear in the +[core key tables](../configuration/core.md). + ## Build ```bash diff --git a/docs/instruments/hispec-tracking-camera.md b/docs/instruments/hispec-tracking-camera.md index 147f861..e057ce7 100644 --- a/docs/instruments/hispec-tracking-camera.md +++ b/docs/instruments/hispec-tracking-camera.md @@ -1,16 +1,11 @@ # HISPEC tracking camera -The HISPEC acquisition and tracking camera (ATC): an H2RG on an Archon controller. This is the most -complete instrument module and the one the emulator integration tests exercise. +The HISPEC acquisition and tracking camera (ATC): a 2048x2048 H2RG on an Archon controller. This is +the most complete instrument module and the one the emulator integration tests exercise. Repository: [hispec-tracking-camera-instrument](https://github.com/CaltechOpticalObservatories/hispec-tracking-camera-instrument), checked out at `camerad/Instruments/hispec_tracking_camera`. -:::{note} -Expands in M4 with the readout and operational modes, the ROI and guiding geometry rules, and the -full keyword table. What is here is verified against the current submodule. -::: - ## Build ```bash @@ -21,41 +16,110 @@ make Shipped configuration is in the submodule's `config/`: `hispecatc.cfg` and `hispecatc.acf`. +## Three things called "mode" + +The single most confusing thing about this module is that three unrelated settings are all called a +mode. They are selected by different commands and do different things. + +Camera mode (`mode`) +: Names a `[MODE_*]` section of the loaded ACF. Selecting one loads that section's geometry + (`PIXELCOUNT`, `LINECOUNT`), its parameters, and its tapline layout (`TAPLINES`, `TAPLINE0..N`) + into the controller. This is the heavyweight one: it changes the shape of the data coming back. + Requires firmware to already be loaded. + +Exposure mode (`exposure`) +: Selects the H2RG readout scheme. Implemented by setting the matching `mode_*` ACF parameter to 1 + and every other one to 0, so the ACF must define all four. + + | Argument | ACF parameter | Scheme | + |---|---|---| + | `utr_rr` | `mode_UTR_RR` | Up the ramp, reset-read | + | `utr_gr` | `mode_UTR_GR` | Up the ramp, guided read | + | `rx` | `mode_RX` | Reset-execute | + | `rxr` | `mode_RXR` | Reset-execute-read | + +Acquisition mode (`exposuremode`) +: The base command, selecting which `Camera::ExposureMode` implementation drives acquisition. This + module provides `DEFAULT` and `AUTOFETCH`. See [architecture](../architecture/index.md) for what + an exposure mode is. + +:::{tip} +`exposure` with no argument reports the current readout scheme. `mode` with no argument reports the +current camera mode. Neither changes anything when queried. +::: + ## Instrument commands -These are reached through the normal command interface, and from Python via `instrument_cmd()`. +Reached through the normal command interface, and from Python via `instrument_cmd()`. | Command | Purpose | |---|---| -| `h2rg_init` | Initialize the H2RG | -| `mode` | Select the readout mode | -| `exposure` | Select the exposure mode | -| `autofetch_mode` | Control autofetch, where the controller pushes frames continuously | -| `freerun` | Continuous acquisition | -| `window_mode` | Windowed readout | -| `roi` | Set the region of interest | +| `h2rg_init` | Re-trigger the H2RG main reset and enable Pad B output with HIGHOHM | +| `mode` | Select or report the camera mode from the ACF | +| `exposure` | Select or report the H2RG readout scheme | +| `exposuremode` | Select the acquisition mode (base command) | +| `autofetch_mode` | Control autofetch, where the controller streams frames continuously | +| `freerun` | Arm (`1`) or disarm (`0`) continuous exposure | +| `window_mode` | Enter or leave windowed readout | +| `roi` | Set or report the region of interest | | `take_stats` | Report pixel statistics | | `debug` | Development diagnostics | -`instrument_commands()` enumerates them at runtime, which is the authoritative list for a given -build. +`instrument_commands()` enumerates them at runtime, which is authoritative for a given build. -## Readout modes +:::{note} +`h2rg_init` exists because the ACF defaults `Start` to 1, so it is already true at load time and +never sees the 0 to 1 edge the H2RG main reset needs. Running it after power-up re-triggers that +edge. It is not optional on a cold start. +::: -`mode` selects among the H2RG readout schemes, each backed by an ACF timing mode: +Setting `autofetch_mode` also resets the readout scheme to the default, so select `exposure` after +`autofetch_mode`, not before. -| Mode | ACF timing mode | +## Region of interest + +`roi` takes four argument shapes: + +| Form | Meaning | |---|---| -| `utr_rr` | `mode_UTR_RR`, up-the-ramp, reset-read | -| `utr_gr` | `mode_UTR_GR`, up-the-ramp, guided read | -| `rx` | `mode_RX`, reset-execute | -| `rxr` | `mode_RXR`, reset-execute-read | +| `roi` | Report the current window as `vstart vstop hstart hstop` | +| `roi ` | A centred region of that size | +| `roi ` | An explicit region | +| `roi fullframe` | Return to the full 2048x2048 frame | + +`window_mode` is the underlying toggle. Leaving window mode restores the saved `TAPLINES` and +`TAPLINE0` values, switches the camera back to the `DEFAULT` ACF mode to reset the internal buffer +geometry, and reapplies that mode's `PIXELCOUNT`. That teardown is why leaving window mode is not +simply the inverse of entering it, and why it needs the ACF to have a `DEFAULT` mode. + +## Configuration + +Alongside the [core keys](../configuration/index.md), this module reads its own: + +| Key | Default | Meaning | +|---|---|---| +| `REFPIX_AMP` | `AM52` | Amplifier reading the reference channel, recorded as `REFPXAMP`. The reference channel's tapline moves with the camera mode; its amplifier does not. | +| `PIXEL_TIME_USEC` | built-in | Pixel time used to model the readout deadline, when the ACF does not supply one | +| `READOUT_MARGIN_MSEC` | built-in | Slack added to the computed per-frame readout deadline | + +`PIXEL_TIME_USEC` and `READOUT_MARGIN_MSEC` set how long the acquisition thread waits for a frame +before calling it lost. Both must be positive, and a non-numeric value makes startup fail rather +than silently falling back. + +Fixed in `configure_instrument()` rather than configured: the LVDS module is 10 and the detector's +maximum pixel index is 2047. The Archon socket is also tuned there for streaming, with `TCP_NODELAY` +and 1 MB buffers. + +:::{warning} +`WRITE_TAPINFO_TO_FITS` appears in the shipped `hispecatc.cfg` but is read by nothing. Setting it +has no effect. +::: ## FITS keywords The module carries its own keyword dictionary mapping each internal property to a keyword, comment, -type and default. It covers two cameras, ATC and SPEC, with separate defaults; the table below shows -the ATC default, falling back to the SPEC one where ATC has none. +type and default. It covers two cameras, ATC and SPEC, with separate defaults; the table shows the +ATC default, falling back to the SPEC one where ATC has none. `python/tests/fits_header_check.py` validates a written file against this dictionary. @@ -68,3 +132,10 @@ the ATC default, falling back to the SPEC one where ATC has none. Generated from {source}`camerad/Instruments/hispec_tracking_camera/fits_header_dictionary.cpp`, so it cannot drift from the dictionary the instrument actually writes. ::: + +## Error reporting + +Every error this module logs carries a one-line state summary, so a failure records the camera state +that produced it rather than leaving it to be reconstructed from surrounding log lines that a +concurrent command may have interleaved. Callers get a short reason; the log gets the root cause and +the state. diff --git a/docs/instruments/index.md b/docs/instruments/index.md index ab426ab..9e05b92 100644 --- a/docs/instruments/index.md +++ b/docs/instruments/index.md @@ -12,13 +12,16 @@ submodule is pinned, so a given `camera-interface` commit builds one specific in | Instrument | Controller | Detector | State | |---|---|---|---| | [hispec_tracking_camera](hispec-tracking-camera.md) | Archon | H2RG | In active use. The reference implementation. | -| [cryoscope](cryoscope.md) | Archon | H2RG | Implemented, RXR mode | +| [cryoscope](cryoscope.md) | Archon | H2RG | Scaffolding, and does not currently build | | `hispec` | Archon | | Repository exists, no sources yet | | `deimos` | | | Repository exists, no sources yet | :::{note} -`hispec` and `deimos` are currently README-only submodules. They are listed so the set is not -misleading about what exists; there is nothing to document until they carry sources. +`hispec` and `deimos` are README-only submodules today. They are listed so the set is not misleading +about what exists; there is nothing to document until they carry sources. + +Only `hispec_tracking_camera` is built in CI, so the others can fall behind changes to the core +without anything noticing. ::: ```{toctree}