add adjusting frame geometry

and methods to work with trigger register bits
This commit is contained in:
Timur A. Fatkhullin 2024-12-15 21:52:32 +03:00
parent 432ff52ff4
commit 4690af8878
4 changed files with 178 additions and 51 deletions

View File

@ -199,13 +199,13 @@ void RaptorEagleCCD::AcquisitionProcess::start(const std::shared_ptr<acq_params_
fits_update_key_lng(fitsFilePtr, "CRPIX1", 1, "Reference pixel along X-axis", &status);
fits_update_key_lng(fitsFilePtr, "CRVAL1", 1, "Physical value of the reference pixel", &status);
fits_update_key_lng(fitsFilePtr, "STARTX", _acqParams->roiStartX,
fits_update_key_lng(fitsFilePtr, "STARTX", _acqParams->roiStartX + 1, // "+1" to convert to FITS notation
"Image area start pixel along X-axis [CCD pixel]", &status);
fits_update_key_lng(fitsFilePtr, "CRPIX2", 1, "Reference pixel along Y-axis", &status);
fits_update_key_lng(fitsFilePtr, "CRVAL2", 1, "Physical value of the reference pixel", &status);
fits_update_key_lng(fitsFilePtr, "STARTY", _acqParams->roiStartY,
fits_update_key_lng(fitsFilePtr, "STARTY", _acqParams->roiStartY + 1, // "+1" to convert to FITS notation
"Image area start pixel along Y-axis [CCD pixel]", &status);
fits_update_key_lng(fitsFilePtr, "XBIN", _acqParams->binX, "Horizontal binning", &status);

View File

@ -106,10 +106,26 @@ static constexpr unsigned char CL_TRIGGER_MODE_EXT_RISING_EDGE = 0b11000000;
static constexpr unsigned char CL_TRIGGER_MODE_EXT_FALLING_EDGE = 0b01000000;
static constexpr unsigned char CL_TRIGGER_MODE_FFR = 0b00000110;
static constexpr unsigned char CL_TRIGGER_MODE_ITR = 0b00000100;
static constexpr unsigned char CL_TRIGGER_MODE_SNAPSHOT = 0; // just clear all bits
static constexpr unsigned char CL_TRIGGER_MODE_IDLE = 0; // just clear all bits
static constexpr unsigned char CL_ABORT_CURRENT_EXP = 0b00001000;
namespace details
{
static constexpr std::string_view cl_trigger_register_bit(const size_t pos)
{
return pos == CL_TRIGGER_MODE_ENABLE_RISING_EDGE_BIT ? "RISING EDGE"
: pos == CL_TRIGGER_MODE_EXT_TRIGGER_BIT ? "EXTERNAL TRIGGER"
: pos == CL_TRIGGER_MODE_ABORT_CURRENT_EXP_BIT ? "ABORT ACQUISITION"
: pos == CL_TRIGGER_MODE_CONTINUOUS_SEQ_BIT ? "SEQUENCE TRIGGER"
: pos == CL_TRIGGER_MODE_FIXED_FRAME_RATE_BIT ? "FIXED FRAME RATE"
: pos == CL_TRIGGER_MODE_SNAPSHOT_BIT ? "SNAPSHOT TRIGGER"
: "UNKNOWN";
}
} // namespace details
/* SETUP CONTROL VALUES */

View File

@ -329,6 +329,77 @@ void RaptorEagleCCD::flipFPGAStateBit(const size_t pos)
}
std::bitset<8> RaptorEagleCCD::getTriggerRegister()
{
std::lock_guard log_guard(_camlinkMutex);
auto bytes = readRegisters({0xD4});
std::bitset<8> bits{bytes[0]};
logDebug("Get trigger register as 0b{}", bits.to_string());
return bits;
}
std::chrono::utc_clock::time_point RaptorEagleCCD::setTriggerRegister(const std::bitset<8> bits)
{
std::lock_guard lock_guard(_camlinkMutex);
logDebug("Try to set trigger register to 0b{} bits", bits.to_string());
uint8_t reg = static_cast<uint8_t>(bits.to_ulong());
auto tm = std::chrono::utc_clock::now();
writeRegisters({0xD4}, {reg});
return tm;
}
std::chrono::utc_clock::time_point RaptorEagleCCD::setTriggerRegisterBit(const size_t bit_pos)
{
std::lock_guard lock_guard(_camlinkMutex);
auto bits = getTriggerRegister();
logDebug("Try to set '{}' trigger register", details::cl_trigger_register_bit(bit_pos));
bits.set(bit_pos);
return setTriggerRegister(bits);
}
std::chrono::utc_clock::time_point RaptorEagleCCD::clearTriggerRegisterBit(const size_t bit_pos)
{
std::lock_guard lock_guard(_camlinkMutex);
auto bits = getTriggerRegister();
logDebug("Try to clear '{}' trigger register", details::cl_trigger_register_bit(bit_pos));
bits.reset(bit_pos);
return setTriggerRegister(bits);
}
std::chrono::utc_clock::time_point RaptorEagleCCD::flipTriggerRegisterBit(const size_t bit_pos)
{
std::lock_guard lock_guard(_camlinkMutex);
auto bits = getTriggerRegister();
logDebug("Try to flip '{}' trigger register", details::cl_trigger_register_bit(bit_pos));
bits.flip(bit_pos);
return setTriggerRegister(bits);
}
/* PRIVATE METHODS */
bool RaptorEagleCCD::initCamera(int unitmap)
@ -389,7 +460,7 @@ bool RaptorEagleCCD::initCamera(int unitmap)
(*this)[CAMERA_ATTR_YBIN] = 1;
// IDLE mode
(*this)[CAMERA_ATTR_TRIGGER_MODE] = CAMERA_ATTR_TRIGGER_MODE_SNAPSHOT;
(*this)[CAMERA_ATTR_TRIGGER_MODE] = CAMERA_ATTR_TRIGGER_MODE_IDLE;
logInfo("Camera with unitmap '{}' is initialized", _cameraUnitmap);
@ -788,7 +859,7 @@ void RaptorEagleCCD::getHardwareInfo()
cnt1 = *reinterpret_cast<uint16_t*>(_manufacturerData.data() + 14); // at 0C
cnt2 = *reinterpret_cast<uint16_t*>(_manufacturerData.data() + 16); // at +40C
_dacTECSetPointCalibCoeffs[0] = (cnt2 - cnt1) / (DAC_CALIBRATION_POINT_2 - DAC_CALIBRATION_POINT_1);
_dacTECSetPointCalibCoeffs[0] = (DAC_CALIBRATION_POINT_2 - DAC_CALIBRATION_POINT_1) / (cnt2 - cnt1);
_dacTECSetPointCalibCoeffs[1] = DAC_CALIBRATION_POINT_2 - _dacTECSetPointCalibCoeffs[0] * cnt2;
if (_dacTECSetPointCalibCoeffs[1] > 0.0) {
logDebug("Computed DAC-to-Temp linear relation: Temp(C) = {:7.4f}*DAC(counts) + {:6.2f}",
@ -798,9 +869,9 @@ void RaptorEagleCCD::getHardwareInfo()
_dacTECSetPointCalibCoeffs[0], std::abs(_dacTECSetPointCalibCoeffs[1]));
}
_dacTECSetPointCalibCoeffs[2] = (DAC_CALIBRATION_POINT_2 - DAC_CALIBRATION_POINT_1) / (cnt2 - cnt1);
_dacTECSetPointCalibCoeffs[3] = cnt2 - _dacTECSetPointCalibCoeffs[0] * DAC_CALIBRATION_POINT_2;
logDebug("Computed Temp-to-Dac linear relation: DAC(counts) = {}*Temp(C)+{}", _dacTECSetPointCalibCoeffs[2],
_dacTECSetPointCalibCoeffs[2] = (cnt2 - cnt1) / (DAC_CALIBRATION_POINT_2 - DAC_CALIBRATION_POINT_1);
_dacTECSetPointCalibCoeffs[3] = cnt2 - _dacTECSetPointCalibCoeffs[2] * DAC_CALIBRATION_POINT_2;
logDebug("Computed Temp-to-Dac linear relation: DAC(counts) = {}*Temp(C) + {}", _dacTECSetPointCalibCoeffs[2],
_dacTECSetPointCalibCoeffs[3]);
logDebug("---------------------------------");
@ -844,8 +915,10 @@ void RaptorEagleCCD::startAquisition()
throw std::system_error(RaptorEagleCCDError::ERROR_ACQUISITION_IN_PROGRESS);
}
auto bytes = readRegisters({0xD4}); // trigger mode register
std::bitset<8> bits(bytes[0]);
// auto bytes = readRegisters({0xD4}); // trigger mode register
// std::bitset<8> bits(bytes[0]);
auto bits = getTriggerRegister();
if (bits.test(CL_TRIGGER_MODE_EXT_TRIGGER_BIT)) {
logError("External trigger mode is set! Nothing to do, exit!");
@ -861,10 +934,10 @@ void RaptorEagleCCD::startAquisition()
.abortTime = std::chrono::utc_clock::time_point(),
.saveInAbort = false,
.expTime = (*this)[CAMERA_ATTR_EXPTIME],
.roiStartX = (*this)[CAMERA_ATTR_ROI_STARTX],
.roiStartY = (*this)[CAMERA_ATTR_ROI_STARTY],
.roiWidth = (*this)[CAMERA_ATTR_ROI_WIDTH],
.roiHeight = (*this)[CAMERA_ATTR_ROI_HEIGHT],
.roiStartX = (*this)[CAMERA_ATTR_ROI_STARTX], // in CCD pixels (start from 0)
.roiStartY = (*this)[CAMERA_ATTR_ROI_STARTY], // in CCD pixels (start from 0)
.roiWidth = (*this)[CAMERA_ATTR_ROI_WIDTH], // in binned pixels
.roiHeight = (*this)[CAMERA_ATTR_ROI_HEIGHT], // in binned pixels
.binX = (*this)[CAMERA_ATTR_XBIN],
.binY = (*this)[CAMERA_ATTR_YBIN],
.shutterState = (*this)[CAMERA_ATTR_SHUTTER_STATE],
@ -883,10 +956,23 @@ void RaptorEagleCCD::startAquisition()
// adjust geometry
auto w = acq_pars->roiWidth / acq_pars->binX;
auto dv = std::div(_dimCCD[0] - acq_pars->roiStartX, acq_pars->binX);
auto width_max = dv.quot + (dv.rem ? 1 : 0);
if (acq_pars->binX > 1) {
dv = std::div(_dimCCD[1] - acq_pars->roiStartY, acq_pars->binY);
auto height_max = dv.quot + (dv.rem ? 1 : 0);
if (acq_pars->roiWidth > width_max) {
acq_pars->roiWidth = width_max;
logDebug("Adjust ROI width to {}", acq_pars->roiWidth);
(*this)[CAMERA_ATTR_ROI_WIDTH] = width_max;
}
if (acq_pars->roiHeight > height_max) {
acq_pars->roiHeight = height_max;
logDebug("Adjust ROI height to {}", acq_pars->roiHeight);
(*this)[CAMERA_ATTR_ROI_HEIGHT] = height_max;
}
std::lock_guard lock_guard(_acqProcessesMutex);
@ -903,14 +989,17 @@ void RaptorEagleCCD::startAquisition()
// arm grabber here
sptr->start(acq_pars);
bits.set(CL_TRIGGER_MODE_SNAPSHOT_BIT); // start snapshot bit
bytes[0] = static_cast<uint8_t>(bits.to_ulong());
// bits.set(CL_TRIGGER_MODE_SNAPSHOT_BIT); // start snapshot bit
// bytes[0] = static_cast<uint8_t>(bits.to_ulong());
acq_pars->startTime = std::chrono::utc_clock::now();
writeRegisters({0xD4}, bytes); // write to trigger mode register (start snapshot)
// acq_pars->startTime = std::chrono::utc_clock::now();
// writeRegisters({0xD4}, bytes); // write to trigger mode register (start snapshot)
// start acquisition here
acq_pars->startTime = setTriggerRegisterBit(CL_TRIGGER_MODE_SNAPSHOT_BIT);
int status;
xclibApiCall(status = pxd_goneLive(_cameraUnitmap, 0), std::format("psxd_goneLive({}, 0)", _cameraUnitmap));
xclibApiCall(status = pxd_goneLive(_cameraUnitmap, 0), std::format("pxd_goneLive({}, 0)", _cameraUnitmap));
if (status == 0) {
logError("CANNOT START ACQUIRING!!!");
}
@ -1267,14 +1356,19 @@ void RaptorEagleCCD::initAttrComm()
[this]<typename T>(const T& val) { // validator
std::pair<T, std::string> res{val, ""};
if (val < 1) {
res.first = 1;
res.second = "The ROI X-offset must start from 1 (FITS notation)";
} else if (val > _dimCCD[0]) {
res.first = _dimCCD[0];
res.second = std::format(
"The ROI X-offset must not be greater than CCD X-dimension of {} pixels (FITS notation)",
_dimCCD[0]);
// if (val < 1) {
// res.first = 1;
// res.second = "The ROI X-offset must start from 1 (FITS notation)";
// } else if (val > _dimCCD[0]) {
// res.first = _dimCCD[0];
// res.second = std::format(
// "The ROI X-offset must not be greater than CCD X-dimension of {} pixels (FITS notation)",
// _dimCCD[0]);
// }
if (val >= _dimCCD[0]) {
res.first = _dimCCD[0] - 1;
res.second =
std::format("The ROI X-offset must be lesser than CCD X-dimension of {} pixels", _dimCCD[0]);
}
return res;
@ -1288,14 +1382,19 @@ void RaptorEagleCCD::initAttrComm()
[this]<typename T>(const T& val) { // validator
std::pair<T, std::string> res{val, ""};
if (val < 1) {
res.first = 1;
res.second = "The ROI Y-offset must start from 1 (FITS notation)";
} else if (val > _dimCCD[1]) {
res.first = _dimCCD[1];
res.second = std::format(
"The ROI Y-offset must not be greater than CCD Y-dimension of {} pixels (FITS notation)",
_dimCCD[1]);
// if (val < 1) {
// res.first = 1;
// res.second = "The ROI Y-offset must start from 1 (FITS notation)";
// } else if (val > _dimCCD[1]) {
// res.first = _dimCCD[1];
// res.second = std::format(
// "The ROI Y-offset must not be greater than CCD Y-dimension of {} pixels (FITS notation)",
// _dimCCD[1]);
// }
if (val >= _dimCCD[1]) {
res.first = _dimCCD[1] - 1;
res.second =
std::format("The ROI Y-offset must be lesser than CCD Y-dimension of {} pixels", _dimCCD[1]);
}
return res;
@ -1314,8 +1413,8 @@ void RaptorEagleCCD::initAttrComm()
res.second = "The ROI width must start from 1";
} else if (val > _dimCCD[0]) {
res.first = _dimCCD[0];
res.second = std::format(
"The ROI width must not be greater than CCD dimension of {} pixels (FITS notation)", _dimCCD[0]);
res.second =
std::format("The ROI width must not be greater than CCD dimension of {} pixels", _dimCCD[0]);
}
return res;
@ -1331,8 +1430,8 @@ void RaptorEagleCCD::initAttrComm()
// ROI height can be 0 (see Eagle V 4240 instruction manual)
if (val > _dimCCD[1]) {
res.first = _dimCCD[1];
res.second = std::format(
"The ROI height must not be greater than CCD dimension of {} pixels (FITS notation)", _dimCCD[1]);
res.second =
std::format("The ROI height must not be greater than CCD dimension of {} pixels", _dimCCD[1]);
}
return res;
@ -1737,8 +1836,9 @@ void RaptorEagleCCD::initAttrComm()
addAttribute(
CAMERA_ATTR_TRIGGER_MODE,
[this]() {
auto bytes = readRegisters({0xD4});
std::bitset<8> bits{bytes[0]};
// auto bytes = readRegisters({0xD4});
// std::bitset<8> bits{bytes[0]};
auto bits = getTriggerRegister();
std::string_view trigger_mode;
if (bits.test(CL_TRIGGER_MODE_EXT_TRIGGER_BIT)) { // external trigger enabled, what is the edge?
@ -1757,12 +1857,13 @@ void RaptorEagleCCD::initAttrComm()
trigger_mode = CAMERA_ATTR_TRIGGER_MODE_SNAPSHOT;
}
logTrace("Return trigger mode as '{}' string (bits = 0b{:08b})", trigger_mode, bytes[0]);
// logTrace("Return trigger mode as '{}' string (bits = 0b{:08b})", trigger_mode, bytes[0]);
logTrace("Return trigger mode as '{}' string (bits = 0b{})", trigger_mode, bits.to_string());
return trigger_mode;
},
[this](const std::string_view& mode) {
uchar bits = CL_TRIGGER_MODE_SNAPSHOT;
uchar bits = CL_TRIGGER_MODE_IDLE;
if (mode == CAMERA_ATTR_TRIGGER_MODE_EXT_RISING) {
bits = CL_TRIGGER_MODE_EXT_RISING_EDGE;
logInfo("Trigger mode is set to {}", mode);
@ -1775,18 +1876,20 @@ void RaptorEagleCCD::initAttrComm()
} else if (mode == CAMERA_ATTR_TRIGGER_MODE_ITR) {
bits = CL_TRIGGER_MODE_ITR;
logInfo("Trigger mode is set to {}", mode);
} else if (mode == CAMERA_ATTR_TRIGGER_MODE_SNAPSHOT) {
} else if (mode == CAMERA_ATTR_TRIGGER_MODE_IDLE) {
logInfo("Trigger mode is set to {}", mode);
} else {
logWarn("Invalid trigger mode! Set it to {}!", CAMERA_ATTR_TRIGGER_MODE_SNAPSHOT);
logWarn("Invalid trigger mode! Set it to {}!", CAMERA_ATTR_TRIGGER_MODE_IDLE);
}
// // snapshot mode is self-clearing bit so activate it directly in 'startAcquision' method
// if (mode != CAMERA_ATTR_TRIGGER_MODE_SNAPSHOT) {
writeRegisters({0xD4}, {bits});
// writeRegisters({0xD4}, {bits});
// }
logDebug("Trigger mode bits are set to 0b{:08b}", bits);
// logDebug("Trigger mode bits are set to 0b{:08b}", bits);
setTriggerRegister(bits);
},
adc::utils::AdcDefaultValueConverter<>::serialize<attribute_t::serialized_t, std::string_view>,
[&comp_case_ignore](const attribute_t::serialized_t& v) {

View File

@ -141,11 +141,13 @@ public:
static constexpr std::string_view CAMERA_ATTR_TRIGGER_MODE_FFR{"FFR"};
// snapshot
static constexpr std::string_view CAMERA_ATTR_TRIGGER_MODE_SNAPSHOT{"SNAPSHOT"};
// idle
static constexpr std::string_view CAMERA_ATTR_TRIGGER_MODE_IDLE{"IDLE"};
RaptorEagleCCD(const adc::traits::adc_input_char_range auto& epix_video_fmt_filename,
std::shared_ptr<spdlog::logger> logger = spdlog::null_logger_mt("EAGLE_CCD_NULLLOGGER"));
std::shared_ptr<spdlog::logger> logger = spdlog::null_logger_mt("EAGLE_CCD_NULL_LOGGER"));
RaptorEagleCCD(std::shared_ptr<spdlog::logger> logger = spdlog::null_logger_mt("EAGLE_CCD_NULLLOGGER"));
RaptorEagleCCD(std::shared_ptr<spdlog::logger> logger = spdlog::null_logger_mt("EAGLE_CCD_NULL_LOGGER"));
~RaptorEagleCCD();
@ -310,6 +312,12 @@ private:
void clearFPGAStateBit(const size_t bit_pos);
void flipFPGAStateBit(const size_t bit_pos);
// set 'Abort' bit in trigger register
std::bitset<8> getTriggerRegister();
std::chrono::utc_clock::time_point setTriggerRegister(const std::bitset<8> bits);
std::chrono::utc_clock::time_point setTriggerRegisterBit(const size_t bit_pos);
std::chrono::utc_clock::time_point clearTriggerRegisterBit(const size_t bit_pos);
std::chrono::utc_clock::time_point flipTriggerRegisterBit(const size_t bit_pos);
// reset hardware methods