This commit is contained in:
Timur A. Fatkhullin 2024-12-17 18:00:14 +03:00
parent 4690af8878
commit 192636aeda
4 changed files with 121 additions and 64 deletions

View File

@ -96,9 +96,24 @@ void RaptorEagleCCD::AcquisitionProcess::start(const std::shared_ptr<acq_params_
_acqParams->roiWidth, _acqParams->roiHeight, _acqParams->binX, _acqParams->binY);
_manager->logDebug("Copy image from grabber to buffer (thread id: {}) ...", st.str());
size_t npix = _acqParams->roiWidth * _acqParams->roiHeight;
// compute image dimension
// NOTE: _acqParams->roiWidth and _acqParams->roiHeight are expected in CCD pixels (not binned)!!!
_imageBufferRows = static_cast<size_t>(std::ceil(npix / _manager->_dimCCD[0]));
auto div = std::div(_acqParams->roiWidth, _acqParams->binX);
auto dimx = div.quot + (div.rem ? 1 : 0);
div = std::div(_acqParams->roiHeight, _acqParams->binY);
auto dimy = div.quot + (div.rem ? 1 : 0);
// LONGLONG npix = _acqParams->roiWidth * _acqParams->roiHeight;
LONGLONG npix = dimx * dimy;
// NOTE:
auto ldiv = std::lldiv(npix, _manager->_dimCCD[0]);
_imageBufferRows = ldiv.quot + (ldiv.rem ? 1 : 0);
// _imageBufferRows = static_cast<size_t>(std::ceil(npix / _manager->_dimCCD[0]));
// read size
size_t sz = _imageBufferRows * _manager->_dimCCD[0];
try {
@ -112,7 +127,7 @@ void RaptorEagleCCD::AcquisitionProcess::start(const std::shared_ptr<acq_params_
_imageBufferRows, (void*)_imageBuffer.get(), _imageBufferSize, color_space);
_manager->xclibApiCall(pxd_readushort(_manager->_cameraUnitmap, 1, 0, 0, -1, _imageBufferRows,
_imageBuffer.get(), _imageBufferSize, (char*)color_space),
(ushort*)_imageBuffer.get(), _imageBufferSize, (char*)color_space),
log_str);
isAcqInProgress = false;
@ -138,10 +153,11 @@ void RaptorEagleCCD::AcquisitionProcess::start(const std::shared_ptr<acq_params_
fitsfile* fitsFilePtr;
int status = 0;
// int naxis = 2;
long naxes[2];
naxes[0] = _acqParams->roiWidth;
naxes[1] = _acqParams->roiHeight;
const int naxis = 2;
long naxes[naxis] = {dimx, dimy};
// long naxes[2];
// naxes[0] = _acqParams->roiWidth;
// naxes[1] = _acqParams->roiHeight;
char err_str[100];
@ -154,7 +170,7 @@ void RaptorEagleCCD::AcquisitionProcess::start(const std::shared_ptr<acq_params_
fits_create_img(fitsFilePtr, USHORT_IMG, 2, naxes, &status);
_manager->logDebug("Write {} pixels to the HDU ...", npix);
fits_write_img(fitsFilePtr, TUSHORT, 1, (LONGLONG)npix, _imageBuffer.get(), &status);
fits_write_img(fitsFilePtr, TUSHORT, 1, npix, (void*)_imageBuffer.get(), &status);
// helper to convert std::string_view to C-lang null-terminated string
@ -185,8 +201,8 @@ void RaptorEagleCCD::AcquisitionProcess::start(const std::shared_ptr<acq_params_
double jd = details::JulianDay(_acqParams->startTime);
fits_update_key_str(fitsFilePtr, "DATE-OBS", str.c_str(), "Start of the exposure in UTC", &status);
fits_update_key_dbl(fitsFilePtr, "JD", jd, -12, "Julian day of exposure start time", &status);
fits_update_key_dbl(fitsFilePtr, "MJD", jd - 2400000.5, -12, "Modified Julian day of exposure start time",
fits_update_key_dbl(fitsFilePtr, "JD", jd, -15, "Julian day of exposure start time", &status);
fits_update_key_dbl(fitsFilePtr, "MJD", jd - 2400000.5, -15, "Modified Julian day of exposure start time",
&status);
if (_acqParams->startTime < _acqParams->abortTime) { // acquisition was aborted
@ -236,7 +252,7 @@ void RaptorEagleCCD::AcquisitionProcess::start(const std::shared_ptr<acq_params_
fits_update_key_dbl(fitsFilePtr, "CCDTEMP", _acqParams->ccdTemp, -2, "CCD chip temperature in Celsius",
&status);
fits_update_key_dbl(fitsFilePtr, "PCBTEMP", _acqParams->pcbTemp, -2, "PCB temperature in Celsius", &status);
fits_update_key_dbl(fitsFilePtr, "TECSETPT", _acqParams->tecSetPoint, -2,
fits_update_key_dbl(fitsFilePtr, "TECSETPT", _acqParams->tecSetPoint, -5,
"TEC set point temperature in Celsius", &status);
if (!status) {

View File

@ -137,6 +137,7 @@ static constexpr char CL_SHUTTER_EXP = 0x2;
// readout rate (registers values)
static constexpr std::initializer_list<unsigned char> CL_READOUT_CLOCK_RATE_ADDR = {0xA3, 0xA4};
static constexpr unsigned char CL_READOUT_CLOCK_RATE_A3_2MHZ = 0x02;
static constexpr unsigned char CL_READOUT_CLOCK_RATE_A4_2MHZ = 0x02;
static constexpr unsigned char CL_READOUT_CLOCK_RATE_A3_75KHZ = 0x43;

View File

@ -364,7 +364,7 @@ std::chrono::utc_clock::time_point RaptorEagleCCD::setTriggerRegisterBit(const s
auto bits = getTriggerRegister();
logDebug("Try to set '{}' trigger register", details::cl_trigger_register_bit(bit_pos));
logDebug("Try to set '{}' trigger register bit", details::cl_trigger_register_bit(bit_pos));
bits.set(bit_pos);
@ -378,7 +378,7 @@ std::chrono::utc_clock::time_point RaptorEagleCCD::clearTriggerRegisterBit(const
auto bits = getTriggerRegister();
logDebug("Try to clear '{}' trigger register", details::cl_trigger_register_bit(bit_pos));
logDebug("Try to clear '{}' trigger register bit", details::cl_trigger_register_bit(bit_pos));
bits.reset(bit_pos);
@ -392,7 +392,7 @@ std::chrono::utc_clock::time_point RaptorEagleCCD::flipTriggerRegisterBit(const
auto bits = getTriggerRegister();
logDebug("Try to flip '{}' trigger register", details::cl_trigger_register_bit(bit_pos));
logDebug("Try to flip '{}' trigger register bit", details::cl_trigger_register_bit(bit_pos));
bits.flip(bit_pos);
@ -450,18 +450,28 @@ bool RaptorEagleCCD::initCamera(int unitmap)
logDebug("Set initial state (IDLE, full frame, binning to 1x1) ...");
(*this)[CAMERA_ATTR_READ_MODE] = CAMERA_ATTR_READ_MODE_NORMAL;
(*this)[CAMERA_ATTR_READ_RATE] = CAMERA_ATTR_READ_RATE_FAST;
(*this)[CAMERA_ATTR_ROI_STARTX] = 1; // in FITS notation (started from 1)!!!
(*this)[CAMERA_ATTR_ROI_STARTY] = 1; // in FITS notation (started from 1)!!!
(*this)[CAMERA_ATTR_ROI_WIDTH] = _dimCCD[0];
(*this)[CAMERA_ATTR_ROI_HEIGHT] = _dimCCD[1];
(*this)[CAMERA_ATTR_XBIN] = 1;
(*this)[CAMERA_ATTR_YBIN] = 1;
(*this)[CAMERA_ATTR_ROI_STARTX] = 0; // in CCD notation (started from 0)!!!
(*this)[CAMERA_ATTR_ROI_STARTY] = 0; // in CCD notation (started from 0)!!!
(*this)[CAMERA_ATTR_ROI_HEIGHT] = 0; // ??!!!!
(*this)[CAMERA_ATTR_ROI_WIDTH] = _dimCCD[0];
(*this)[CAMERA_ATTR_ROI_HEIGHT] = _dimCCD[1];
(*this)[CAMERA_ATTR_READ_MODE] = CAMERA_ATTR_READ_MODE_NORMAL;
(*this)[CAMERA_ATTR_READ_RATE] = CAMERA_ATTR_READ_RATE_FAST;
// IDLE mode
(*this)[CAMERA_ATTR_TRIGGER_MODE] = CAMERA_ATTR_TRIGGER_MODE_IDLE;
// clearTriggerRegisterBit(CL_TRIGGER_MODE_EXT_TRIGGER_BIT);
// clearTriggerRegisterBit(CL_TRIGGER_MODE_CONTINUOUS_SEQ_BIT);
// setTriggerRegisterBit(CL_TRIGGER_MODE_ABORT_CURRENT_EXP_BIT);
logInfo("Camera with unitmap '{}' is initialized", _cameraUnitmap);
return true;
@ -521,8 +531,9 @@ size_t RaptorEagleCCD::clRead(byte_seq_t& bytes)
}
if (!nbytes) {
logWarn("Cameralink reading operation timeout!");
return 0;
// logWarn("Cameralink reading operation timeout!");
// return 0;
throw std::system_error(RaptorEagleCCDError::ERROR_CAMLINK_READ_TIMEOUT);
}
// here the call is only for logging purpose
@ -1438,58 +1449,84 @@ void RaptorEagleCCD::initAttrComm()
},
"ROI height"));
// binning validator (1-32, 64)
auto bin_validator = []<typename T>(const T& val, std::string_view log_name) {
std::pair<T, std::string> res{val, ""};
T* limits = (T*)EAGLE_CAMERA_MAX_XBIN;
if (log_name == "YBIN") {
limits = (T*)EAGLE_CAMERA_MAX_YBIN;
}
if (val < 1) {
res.first = 1;
res.second = std::format("The {} must start from 1", log_name);
} else if ((val > limits[0]) && (val < limits[1])) {
// set to the closest
res.first = (val - limits[0]) < (limits[1] - val) ? limits[0] : limits[1];
res.second = std::format("The {} must not be within {} and {}", log_name, limits[0], limits[1]);
} else if (val > limits[1]) {
res.first = limits[1];
res.second = std::format("The {} must not be greater than {}", log_name, limits[1]);
}
return res;
};
// X-bin
addAttribute(create8BitAttr(
CAMERA_ATTR_XBIN, CL_XBIN_ADDR,
[]<typename T>(const T& val) { // validator (1-32, 64)
std::pair<T, std::string> res{val, ""};
addAttribute(attribute_t::makeArithAttr(
CAMERA_ATTR_XBIN,
[this]() {
auto bytes = readRegisters(CL_XBIN_ADDR);
if (val < 1) {
res.first = 1;
res.second = "The XBIN must start from 1";
} else if ((val > EAGLE_CAMERA_MAX_XBIN[0]) && (val < EAGLE_CAMERA_MAX_XBIN[1])) {
// set to the closest
res.first = (val - EAGLE_CAMERA_MAX_XBIN[0]) < (EAGLE_CAMERA_MAX_XBIN[1] - val)
? EAGLE_CAMERA_MAX_XBIN[0]
: EAGLE_CAMERA_MAX_XBIN[1];
// inner register value of binning starts from 0!!!
logDebug("Return XBIN as {} (inner register value: {})", bytes[0] + 1, bytes[0]);
res.second = std::format("The XBIN must not be within {} and {}", EAGLE_CAMERA_MAX_XBIN[0],
EAGLE_CAMERA_MAX_XBIN[1]);
} else if (val > EAGLE_CAMERA_MAX_XBIN[1]) {
res.first = EAGLE_CAMERA_MAX_XBIN[1];
res.second = std::format("The XBIN must not be greater than {}", EAGLE_CAMERA_MAX_XBIN[1]);
return bytes[0] + 1;
},
[&bin_validator, this](const uchar& val) {
logDebug("Try to set XBIN to {} ...", val);
auto v_res = bin_validator(val, "XBIN");
if (v_res.second.size()) {
logWarn(v_res.second);
}
return res;
},
"XBIN"));
// inner register value of binning starts from 0!!!
v_res.first -= 1;
writeRegisters(CL_XBIN_ADDR, {v_res.first});
logDebug("XBIN is set to {} (inner register value {})", v_res.first + 1, v_res.first);
}));
// Y-bin
addAttribute(create8BitAttr(
CAMERA_ATTR_YBIN, CL_YBIN_ADDR,
[]<typename T>(const T& val) { // validator (1-32, 64)
std::pair<T, std::string> res{val, ""};
addAttribute(attribute_t::makeArithAttr(
CAMERA_ATTR_YBIN,
[this]() {
auto bytes = readRegisters(CL_YBIN_ADDR);
if (val < 1) {
res.first = 1;
res.second = "The YBIN must start from 1";
} else if ((val > EAGLE_CAMERA_MAX_YBIN[0]) && (val < EAGLE_CAMERA_MAX_YBIN[1])) {
// set to the closest
res.first = (val - EAGLE_CAMERA_MAX_YBIN[0]) < (EAGLE_CAMERA_MAX_YBIN[1] - val)
? EAGLE_CAMERA_MAX_YBIN[0]
: EAGLE_CAMERA_MAX_YBIN[1];
// inner register value of binning starts from 0!!!
logDebug("Return YBIN as {} (inner register value: {})", bytes[0] + 1, bytes[0]);
res.second = std::format("The YBIN must not be within {} and {}", EAGLE_CAMERA_MAX_YBIN[0],
EAGLE_CAMERA_MAX_YBIN[1]);
} else if (val > EAGLE_CAMERA_MAX_YBIN[1]) {
res.first = EAGLE_CAMERA_MAX_YBIN[1];
res.second = std::format("The YBIN must not be greater than {}", EAGLE_CAMERA_MAX_XBIN[1]);
return bytes[0] + 1;
},
[&bin_validator, this](const uchar& val) {
logDebug("Try to set YBIN to {} ...", val);
auto v_res = bin_validator(val, "YBIN");
if (v_res.second.size()) {
logWarn(v_res.second);
}
return res;
},
"YBIN"));
// inner register value of binning starts from 0!!!
v_res.first -= 1;
writeRegisters(CL_YBIN_ADDR, {v_res.first});
logDebug("YBIN is set to {} (inner register value {})", v_res.first + 1, v_res.first);
}));
/* TEC SET POINT AND STATE */
@ -1665,7 +1702,7 @@ void RaptorEagleCCD::initAttrComm()
addAttribute(
CAMERA_ATTR_READ_RATE,
[this]() {
auto bytes = readRegisters(CL_FRAMERATE_ADDR);
auto bytes = readRegisters(CL_READOUT_CLOCK_RATE_ADDR);
std::string_view val;
if ((bytes[0] == CL_READOUT_CLOCK_RATE_A3_2MHZ) && (bytes[1] == CL_READOUT_CLOCK_RATE_A4_2MHZ)) {
@ -1695,7 +1732,7 @@ void RaptorEagleCCD::initAttrComm()
logInfo("Set readout rate to {}", CAMERA_ATTR_READ_RATE_FAST);
}
writeRegisters(CL_FRAMERATE_ADDR, bytes);
writeRegisters(CL_READOUT_CLOCK_RATE_ADDR, bytes);
logDebug("Readout rate is set to [0x{:02X}, 0x{:02X}] bytes", bytes[0], bytes[1]);
},

View File

@ -10,6 +10,7 @@ enum class RaptorEagleCCDError : int {
ERROR_INVALID_UNITMAP,
ERROR_INVALID_ATTR_VALUE,
ERROR_CAMLINK_WRITE,
ERROR_CAMLINK_READ_TIMEOUT,
ERROR_CANNOT_INIT_CAMERA,
ERROR_CANNOT_RESET_MICRO,
ERROR_CANNOT_RESET_FPGA,
@ -49,6 +50,8 @@ struct RaptorEagleCCDErrorCategory : std::error_category {
return "invalid camera attribute value";
case RaptorEagleCCDError::ERROR_CAMLINK_WRITE:
return "not all data were transmitted via CameraLink connection";
case RaptorEagleCCDError::ERROR_CAMLINK_READ_TIMEOUT:
return "CameraLink reading operation timeout";
case RaptorEagleCCDError::ERROR_CANNOT_INIT_CAMERA:
return "cannot initialize camera hardware";
case RaptorEagleCCDError::ERROR_CANNOT_RESET_MICRO: