diff --git a/camerad/Instruments/hispec_tracking_camera b/camerad/Instruments/hispec_tracking_camera index 36deef2..a9a3eac 160000 --- a/camerad/Instruments/hispec_tracking_camera +++ b/camerad/Instruments/hispec_tracking_camera @@ -1 +1 @@ -Subproject commit 36deef25c0415e62f52ca90e58c56c149b11c740 +Subproject commit a9a3eac8ea9b2350781d4df703302e93a7964f36 diff --git a/camerad/archon_controller.cpp b/camerad/archon_controller.cpp index 547f700..8dcd85c 100644 --- a/camerad/archon_controller.cpp +++ b/camerad/archon_controller.cpp @@ -2000,14 +2000,34 @@ namespace Camera { bufblocks = (unsigned int) floor( (this->interface->camera_info.image_memory + BLOCK_LEN - 1 ) / BLOCK_LEN ); break; - case Camera::ArchonController::FRAME_IMAGE: + case Camera::ArchonController::FRAME_IMAGE: { // Archon buffer base address bufaddr = this->frameinfo.bufbase[index]; - // Calculate the number of blocks expected. image_memory is bytes per detector - bufblocks = - (unsigned int) floor( ((this->interface->camera_info.image_memory * num_detect) + BLOCK_LEN - 1 ) / BLOCK_LEN ); + // Size the fetch from the Archon-reported buffer dimensions (BUFnWIDTH/ + // HEIGHT from the FRAME command). + const int fw = this->frameinfo.bufwidth[index]; + const int fh = this->frameinfo.bufheight[index]; + const int fbpp = (this->frameinfo.bufsample[index]==1) ? 4 : 2; + size_t frame_bytes = static_cast(fw) * fh * fbpp * num_detect; + if (fw <= 0 || fh <= 0) { // Archon reported nothing usable; fall back + logwrite(function, "WARNING Archon buffer dims unavailable; using camera_info.image_memory"); + frame_bytes = static_cast(this->interface->camera_info.image_memory) * num_detect; + } + bufblocks = (unsigned int) floor( (frame_bytes + BLOCK_LEN - 1) / BLOCK_LEN ); + + // read_frame writes bufblocks*BLOCK_LEN bytes into framebuf with no bounds + // check, so grow it here if the reported frame is larger than allocated. + const uint32_t needed = bufblocks * BLOCK_LEN; + if (imagebufferptr == this->framebuf && needed > this->framebuf_bytes) { + if (this->allocate_framebuf(needed) != NO_ERROR) { + logwrite(function, "ERROR growing framebuf to hold Archon frame"); + return ERROR; + } + imagebufferptr = this->framebuf; // realloc moved the buffer + } break; + } default: // should be impossible SNPRINTF(message, "unknown frame type specified: %d: expected FRAME_RAW | FRAME_IMAGE", this->frametype); diff --git a/camerad/archon_exposure_modes.h b/camerad/archon_exposure_modes.h index dc13828..a04de46 100644 --- a/camerad/archon_exposure_modes.h +++ b/camerad/archon_exposure_modes.h @@ -36,6 +36,9 @@ namespace Camera { struct ArchonImageBuffer : public ImageBuffer { std::vector bufframen_slice; ///< Archon frame number(s) for all slices in this image std::vector buftimestamp_slice; ///< Archon timestamp(s) for all slices in this image + uint32_t width{0}; ///< Archon-reported buffer width (BUFnWIDTH) + uint32_t height{0}; ///< Archon-reported buffer height (BUFnHEIGHT) + uint32_t bytes_per_pixel{0}; ///< 2 (16-bit) or 4 (32-bit) }; class ArchonInterface; // forward declaration