Raw retrieval mode#6
Conversation
frame_outputs was never populated, so dispatch_frame was a no-op. Add Interface::configure_frame_outputs(), called from camerad startup.
Parse BUFnRAWOFFSET, size fetch from RAW geometry, read as 16-bit, reshape and dispatch in-band. New: raw config|set|read. Verified against emulator.
…nRAWBLOCKS/LINES, and APPLYCDS
|
LGTM, the only real comment is more of a meta-comment. I understand (I think) the reasoning for the ACF file to already have to define these keywords, and it's no problem for that to be the case here. HOWEVER, in the more general archon case I think a problem arises, specifically with the definition of taplines. For example, imagine I have 3 taplines defined as such Now, for example, I want to switch modes and add another tapline This involves writing another key to the archon config. This occurs pretty frequently, example I can cite is in DEIMOS switching from FCS to SCIENCE mode (where we go from 2 taplines to 16). Now, we currently handle that by pre-defining all keys and then simply changing from e.g. TAPLINES=16 to TAPLINES=2, which causes the last 14 taplines to be ignored. We then change back to TAPLINES=16 to "un-ignore" those taplines. At least I think that's how it works, @astronomerdave feel free to correct me. This is a slightly ugly but workable solution. If we intend to support that level of configurability in camerad2, I think I am satisfied with it. OTOH it's definitely not as fflexible as being able to programatically build up the number of taplines "from scratch". The same issue arises, for example, if I want to alter the timing script, and in doing so change the number of lines in a timing script. Same true also for parameters and constants. If we think doing that is outside even the eventual functionality of camerad2, I can definitely live with it. |
weatherhead99
left a comment
There was a problem hiding this comment.
nothing important, and probably not possible due to API consistency
| else | ||
| if (key_len==4) { | ||
| // RBUF=XXXX pattern | ||
| if (key_start[0]=='R' && std::strncmp(key_start, "RBUF", 4)==0) { |
There was a problem hiding this comment.
out of curiosity what's the reason for std::strncmp here rather than std::string::starts_with?
There was a problem hiding this comment.
The parser works on raw const char* slices, not std::string, so starts_with isn't available without adding one per key
There was a problem hiding this comment.
understood. std::string:;starts_with doesn't work. But std::string_view::starts_with might? (Although possibly unsafe in the raw const char* situation?)
UPDATE just looked it up. Looks like you can directly to string_view::starts_with on a const char* (https://en.cppreference.com/cpp/string/basic_string_view/starts_with)
| raw_geometry_t raw_geometry() const; | ||
| uint32_t raw_frame_bytes() const; // padded, size-aware byte count for a RAW fetch | ||
| long set_raw_config(const std::string &args, std::string &retstring); | ||
| long get_raw_config(std::string &retstring); |
There was a problem hiding this comment.
why not just return a std::optionalstd::string here? RTVO is guaranteed to elide that copy since c++17 AFAICS if performance is an issue
There was a problem hiding this comment.
It matches the signature, and the long return encodes three states (NO_ERROR/ERROR/HELP), the optional can't do that
There was a problem hiding this comment.
fair enough.... we do have std::expected for that case ;-).
Broader question then why is this a long and not an enum class?
Or if there are only 3 states why is it a long and not a short?#
Anyway who cares, not to worry
| long ArchonController::read_raw(std::string &retstring) { | ||
| const std::string function("Camera::ArchonController::read_raw"); | ||
|
|
||
| this->get_frame_status(); |
There was a problem hiding this comment.
Might be good to handle the case of get_frame_status returns with an error before computing the raw geometry
| } | ||
| } | ||
|
|
||
| if (changed && this->send_cmd(APPLYCDS) != NO_ERROR) { |
There was a problem hiding this comment.
A question about the use of the changed bool -
So let's say one RAW setting changed, but another one doesn't. Regardless do we apply CDS if one of the RAW values change?
If so would the following case fail: first key RAWSEL changed would be true, then the second key RAWSAMPLES changed would be false so APPLYCDS would be skipped?
There was a problem hiding this comment.
every change of any RAW related keyword or TAPLINE related keyword or CDS related keyword requires an APPLYCDS command before it takes effect. There is no way to know strictly what the current status is of these keywords because one can update the config but not do an APPLYCDS. This is the reason (though it's annoying) why in foxtrot you can't individually set any of those, you have to provide a struct containing all CDS related keywords, so there is never this inconsistency.
Therefore, in my opinion, it's very hard to decide on any situation when you should NOT do APPLYCDS. Because it might be that the values in your config are simply not reflected in the real world anyway, there's no way to tell from just querying the archon.
Archon RAW-Mode Retrieval
What RAW mode is
The Archon continuously samples each CCD output at 16-bit / 100 MHz. Normal image
data is the result of on-chip CDS (correlated double sampling) and is useless
for many electrical measurements. RAW mode instead captures the raw ADC samples
from a single AD channel, before CDS, an oscilloscope view of the CCD output
waveform. Use it to inspect settling time, reset-level stability, clock
feedthrough, and to choose optimal CDS sample windows (SHP/SHD), or to optimise
read noise and linearity.
RAW is captured alongside the normal image during the same exposure, from the
same frame buffer. Because the frame buffer is finite, only a portion of the frame
can be captured this way.
The
rawcommandraw configraw set <KEY> <VAL> [<KEY> <VAL> ...]APPLYCDS)raw readraw ?The six configuration keys
RAWENABLE1to enable RAW capture,0to disableRAWSEL0= ch1 of the ADC in slot 5 …15= ch4 of the ADC in slot 8RAWSTARTLINERAWENDLINERAWSTARTPIXELRAWSAMPLESRAWSTARTLINE=0, RAWENDLINE=1captures two lines.RAWSTARTPIXELonly setswhere in the line sampling starts; it does not change the number of samples.
The ACF must already define these six keys —
raw setwrites existing keys, itcannot create them.
Retrieving RAW data
raw readreturns a summary line, e.g.:and delivers the data in-band to whatever frame-output sink is configured
(a FITS file, or a shared-memory object with
SHM_ENABLED=yes) — no separatefile to go and load.
The retrieved data
The delivered frame is a
lines × RAWSAMPLESarray ofuint16(always 16-bit,even when the pixel mode is HDR/32-bit):
Plot a row and you have the oscilloscope trace of that line's readout.
Watch the size
Bytes ≈
(RAWENDLINE − RAWSTARTLINE + 1) × RAWSAMPLES × 2, padded up per line towhole 1024-byte blocks. RAW fills the frame buffer fast, per the Archon manual,
1000 lines × 1000 samples at a 100 kHz pixel clock is ~2 GB. Start small.
How it works (reference)
Mirrors the pixel-data path, per the Archon ICD:
FRAME?reportsBUFnRAWOFFSET,BUFnRAWBLOCKS(blocks per line) andBUFnRAWLINESfor each buffer.LOCKn) and issuesFETCHfromBUFnBASE + BUFnRAWOFFSET(notBUFnBASE), sized from the reported rawblocks/lines (falling back to the config keys if the controller does not
report them).
lines × RAWSAMPLES, and dispatched in-band as 16-bit samples.Status / caveats
round-trips byte-for-byte at the correct
lines × RAWSAMPLESshape.BUFnRAWOFFSETpath shouldbe confirmed on real hardware during first use.
raw read) and pixel-only (expose) from the same bufferworks today; a single combined command is a possible future addition.