Compare commits

..

No commits in common. "86eb2b8ba74c0345227bec6c6a204e6cf7ab7a26" and "4690af8878bc726ee10229c151ac2e62bc3bc35f" have entirely different histories.

4 changed files with 74 additions and 169 deletions

View File

@ -96,38 +96,12 @@ void RaptorEagleCCD::AcquisitionProcess::start(const std::shared_ptr<acq_params_
_acqParams->roiWidth, _acqParams->roiHeight, _acqParams->binX, _acqParams->binY); _acqParams->roiWidth, _acqParams->roiHeight, _acqParams->binX, _acqParams->binY);
_manager->logDebug("Copy image from grabber to buffer (thread id: {}) ...", st.str()); _manager->logDebug("Copy image from grabber to buffer (thread id: {}) ...", st.str());
// compute image dimension size_t npix = _acqParams->roiWidth * _acqParams->roiHeight;
// NOTE: _acqParams->roiWidth and _acqParams->roiHeight are expected in CCD pixels (not binned)!!!
// auto div = std::div(_acqParams->roiWidth - _acqParams->roiStartX, _acqParams->binX); _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->roiStartY, _acqParams->binY);
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);
bool gap = false;
if ((_acqParams->roiWidth + _acqParams->roiStartX) < _manager->_dimCCD[0]) {
/* IT SEEMS IF MAX ROI X-COORDINATE IS LESS THAN CCD DIM
* EAGLE CAMERA CONTROLLER SETUP READING FOR WIDTH+1 ROI!!! */
gap = true;
++_imageBufferRows;
}
// _imageBufferRows = static_cast<size_t>(std::ceil(npix / _manager->_dimCCD[0]));
// read size
size_t sz = _imageBufferRows * _manager->_dimCCD[0]; size_t sz = _imageBufferRows * _manager->_dimCCD[0];
try { try {
// sz = _manager->_dimCCD[0] * _manager->_dimCCD[1];
if (_imageBufferSize < sz) { if (_imageBufferSize < sz) {
_manager->logDebug("Reallocate image buffer to {} elements", sz); _manager->logDebug("Reallocate image buffer to {} elements", sz);
_imageBufferSize = sz; _imageBufferSize = sz;
@ -137,11 +111,8 @@ void RaptorEagleCCD::AcquisitionProcess::start(const std::shared_ptr<acq_params_
auto log_str = std::format("pxd_readushort({}, 1, 0, 0, -1, {}, {}, {}, \"{}\")", _manager->_cameraUnitmap, auto log_str = std::format("pxd_readushort({}, 1, 0, 0, -1, {}, {}, {}, \"{}\")", _manager->_cameraUnitmap,
_imageBufferRows, (void*)_imageBuffer.get(), _imageBufferSize, color_space); _imageBufferRows, (void*)_imageBuffer.get(), _imageBufferSize, color_space);
// _manager->xclibApiCall(pxd_readushort(_manager->_cameraUnitmap, 1, 0, 0, -1, -1,
// (ushort*)_imageBuffer.get(), _imageBufferSize, (char*)color_space),
// log_str);
_manager->xclibApiCall(pxd_readushort(_manager->_cameraUnitmap, 1, 0, 0, -1, _imageBufferRows, _manager->xclibApiCall(pxd_readushort(_manager->_cameraUnitmap, 1, 0, 0, -1, _imageBufferRows,
(ushort*)_imageBuffer.get(), _imageBufferSize, (char*)color_space), _imageBuffer.get(), _imageBufferSize, (char*)color_space),
log_str); log_str);
isAcqInProgress = false; isAcqInProgress = false;
@ -167,11 +138,10 @@ void RaptorEagleCCD::AcquisitionProcess::start(const std::shared_ptr<acq_params_
fitsfile* fitsFilePtr; fitsfile* fitsFilePtr;
int status = 0; int status = 0;
const int naxis = 2; // int naxis = 2;
long naxes[naxis] = {dimx, dimy}; long naxes[2];
// long naxes[2]; naxes[0] = _acqParams->roiWidth;
// naxes[0] = _acqParams->roiWidth; naxes[1] = _acqParams->roiHeight;
// naxes[1] = _acqParams->roiHeight;
char err_str[100]; char err_str[100];
@ -184,19 +154,7 @@ void RaptorEagleCCD::AcquisitionProcess::start(const std::shared_ptr<acq_params_
fits_create_img(fitsFilePtr, USHORT_IMG, 2, naxes, &status); fits_create_img(fitsFilePtr, USHORT_IMG, 2, naxes, &status);
_manager->logDebug("Write {} pixels to the HDU ...", npix); _manager->logDebug("Write {} pixels to the HDU ...", npix);
if (gap) { fits_write_img(fitsFilePtr, TUSHORT, 1, (LONGLONG)npix, _imageBuffer.get(), &status);
/* IT SEEMS IF MAX ROI X-COORDINATE IS LESS THAN CCD DIM
* EAGLE CAMERA CONTROLLER SETUP READING FOR WIDTH+1 ROI!!!
* SO ONE NEEDS TO WRITE IMAGE PER ROW WITH SKIPPING EXTRA PIXEL
* AT THE END OF EACH ROW
*/
auto ptr = _imageBuffer.get();
for (size_t i = 0; i < dimy; ++i) {
fits_write_img(fitsFilePtr, TUSHORT, i * dimx + 1, dimx, _imageBuffer.get(), &status);
}
} else {
fits_write_img(fitsFilePtr, TUSHORT, 1, npix, (void*)_imageBuffer.get(), &status);
}
// helper to convert std::string_view to C-lang null-terminated string // helper to convert std::string_view to C-lang null-terminated string
@ -227,8 +185,8 @@ void RaptorEagleCCD::AcquisitionProcess::start(const std::shared_ptr<acq_params_
double jd = details::JulianDay(_acqParams->startTime); 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_str(fitsFilePtr, "DATE-OBS", str.c_str(), "Start of the exposure in UTC", &status);
fits_update_key_dbl(fitsFilePtr, "JD", jd, -15, "Julian day of exposure start time", &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, -15, "Modified Julian day of exposure start time", fits_update_key_dbl(fitsFilePtr, "MJD", jd - 2400000.5, -12, "Modified Julian day of exposure start time",
&status); &status);
if (_acqParams->startTime < _acqParams->abortTime) { // acquisition was aborted if (_acqParams->startTime < _acqParams->abortTime) { // acquisition was aborted
@ -278,7 +236,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", fits_update_key_dbl(fitsFilePtr, "CCDTEMP", _acqParams->ccdTemp, -2, "CCD chip temperature in Celsius",
&status); &status);
fits_update_key_dbl(fitsFilePtr, "PCBTEMP", _acqParams->pcbTemp, -2, "PCB 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, -5, fits_update_key_dbl(fitsFilePtr, "TECSETPT", _acqParams->tecSetPoint, -2,
"TEC set point temperature in Celsius", &status); "TEC set point temperature in Celsius", &status);
if (!status) { if (!status) {

View File

@ -137,7 +137,6 @@ static constexpr char CL_SHUTTER_EXP = 0x2;
// readout rate (registers values) // 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_A3_2MHZ = 0x02;
static constexpr unsigned char CL_READOUT_CLOCK_RATE_A4_2MHZ = 0x02; static constexpr unsigned char CL_READOUT_CLOCK_RATE_A4_2MHZ = 0x02;
static constexpr unsigned char CL_READOUT_CLOCK_RATE_A3_75KHZ = 0x43; 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(); auto bits = getTriggerRegister();
logDebug("Try to set '{}' trigger register bit", details::cl_trigger_register_bit(bit_pos)); logDebug("Try to set '{}' trigger register", details::cl_trigger_register_bit(bit_pos));
bits.set(bit_pos); bits.set(bit_pos);
@ -378,7 +378,7 @@ std::chrono::utc_clock::time_point RaptorEagleCCD::clearTriggerRegisterBit(const
auto bits = getTriggerRegister(); auto bits = getTriggerRegister();
logDebug("Try to clear '{}' trigger register bit", details::cl_trigger_register_bit(bit_pos)); logDebug("Try to clear '{}' trigger register", details::cl_trigger_register_bit(bit_pos));
bits.reset(bit_pos); bits.reset(bit_pos);
@ -392,7 +392,7 @@ std::chrono::utc_clock::time_point RaptorEagleCCD::flipTriggerRegisterBit(const
auto bits = getTriggerRegister(); auto bits = getTriggerRegister();
logDebug("Try to flip '{}' trigger register bit", details::cl_trigger_register_bit(bit_pos)); logDebug("Try to flip '{}' trigger register", details::cl_trigger_register_bit(bit_pos));
bits.flip(bit_pos); bits.flip(bit_pos);
@ -450,28 +450,18 @@ bool RaptorEagleCCD::initCamera(int unitmap)
logDebug("Set initial state (IDLE, full frame, binning to 1x1) ..."); logDebug("Set initial state (IDLE, full frame, binning to 1x1) ...");
(*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_MODE] = CAMERA_ATTR_READ_MODE_NORMAL;
(*this)[CAMERA_ATTR_READ_RATE] = CAMERA_ATTR_READ_RATE_FAST; (*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;
// IDLE mode // IDLE mode
(*this)[CAMERA_ATTR_TRIGGER_MODE] = CAMERA_ATTR_TRIGGER_MODE_IDLE; (*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); logInfo("Camera with unitmap '{}' is initialized", _cameraUnitmap);
return true; return true;
@ -531,9 +521,8 @@ size_t RaptorEagleCCD::clRead(byte_seq_t& bytes)
} }
if (!nbytes) { if (!nbytes) {
// logWarn("Cameralink reading operation timeout!"); logWarn("Cameralink reading operation timeout!");
// return 0; return 0;
throw std::system_error(RaptorEagleCCDError::ERROR_CAMLINK_READ_TIMEOUT);
} }
// here the call is only for logging purpose // here the call is only for logging purpose
@ -967,33 +956,21 @@ void RaptorEagleCCD::startAquisition()
// adjust geometry // adjust geometry
// auto dv = std::div(_dimCCD[0] - acq_pars->roiStartX, acq_pars->binX); auto dv = std::div(_dimCCD[0] - acq_pars->roiStartX, acq_pars->binX);
// auto width_max = dv.quot + (dv.rem ? 1 : 0); auto width_max = dv.quot + (dv.rem ? 1 : 0);
// dv = std::div(_dimCCD[1] - acq_pars->roiStartY, acq_pars->binY); dv = std::div(_dimCCD[1] - acq_pars->roiStartY, acq_pars->binY);
// auto height_max = dv.quot + (dv.rem ? 1 : 0); auto height_max = dv.quot + (dv.rem ? 1 : 0);
// if (acq_pars->roiWidth > width_max) { if (acq_pars->roiWidth > width_max) {
// // 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;
// }
auto xmax = acq_pars->roiStartX + acq_pars->roiWidth;
auto ymax = acq_pars->roiStartY + acq_pars->roiHeight;
if (xmax > _dimCCD[0]) {
acq_pars->roiWidth = _dimCCD[0] - acq_pars->roiStartX;
logDebug("Adjust ROI width to {}", acq_pars->roiWidth); logDebug("Adjust ROI width to {}", acq_pars->roiWidth);
(*this)[CAMERA_ATTR_ROI_WIDTH] = width_max;
} }
if (ymax > _dimCCD[1]) { if (acq_pars->roiHeight > height_max) {
acq_pars->roiHeight = _dimCCD[1] - acq_pars->roiStartY; acq_pars->roiHeight = height_max;
logDebug("Adjust ROI height to {}", acq_pars->roiHeight); logDebug("Adjust ROI height to {}", acq_pars->roiHeight);
(*this)[CAMERA_ATTR_ROI_HEIGHT] = height_max;
} }
@ -1461,84 +1438,58 @@ void RaptorEagleCCD::initAttrComm()
}, },
"ROI height")); "ROI height"));
// X-bin
// binning validator (1-32, 64) addAttribute(create8BitAttr(
auto bin_validator = []<typename T>(const T& val, std::string_view log_name) { CAMERA_ATTR_XBIN, CL_XBIN_ADDR,
[]<typename T>(const T& val) { // validator (1-32, 64)
std::pair<T, std::string> res{val, ""}; 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) { if (val < 1) {
res.first = 1; res.first = 1;
res.second = std::format("The {} must start from 1", log_name); res.second = "The XBIN must start from 1";
} else if ((val > limits[0]) && (val < limits[1])) { } else if ((val > EAGLE_CAMERA_MAX_XBIN[0]) && (val < EAGLE_CAMERA_MAX_XBIN[1])) {
// set to the closest // set to the closest
res.first = (val - limits[0]) < (limits[1] - val) ? limits[0] : limits[1]; res.first = (val - EAGLE_CAMERA_MAX_XBIN[0]) < (EAGLE_CAMERA_MAX_XBIN[1] - val)
? EAGLE_CAMERA_MAX_XBIN[0]
: EAGLE_CAMERA_MAX_XBIN[1];
res.second = std::format("The {} must not be within {} and {}", log_name, limits[0], limits[1]); res.second = std::format("The XBIN must not be within {} and {}", EAGLE_CAMERA_MAX_XBIN[0],
} else if (val > limits[1]) { EAGLE_CAMERA_MAX_XBIN[1]);
res.first = limits[1]; } else if (val > EAGLE_CAMERA_MAX_XBIN[1]) {
res.second = std::format("The {} must not be greater than {}", log_name, limits[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 res; return res;
};
// X-bin
addAttribute(attribute_t::makeArithAttr(
CAMERA_ATTR_XBIN,
[this]() {
auto bytes = readRegisters(CL_XBIN_ADDR);
// inner register value of binning starts from 0!!!
logDebug("Return XBIN as {} (inner register value: {})", bytes[0] + 1, bytes[0]);
return bytes[0] + 1;
}, },
[&bin_validator, this](const uchar& val) { "XBIN"));
logDebug("Try to set XBIN to {} ...", val);
auto v_res = bin_validator(val, "XBIN");
if (v_res.second.size()) {
logWarn(v_res.second);
}
// 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 // Y-bin
addAttribute(attribute_t::makeArithAttr( addAttribute(create8BitAttr(
CAMERA_ATTR_YBIN, CAMERA_ATTR_YBIN, CL_YBIN_ADDR,
[this]() { []<typename T>(const T& val) { // validator (1-32, 64)
auto bytes = readRegisters(CL_YBIN_ADDR); std::pair<T, std::string> res{val, ""};
// inner register value of binning starts from 0!!! if (val < 1) {
logDebug("Return YBIN as {} (inner register value: {})", bytes[0] + 1, bytes[0]); 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];
return bytes[0] + 1; res.second = std::format("The YBIN must not be within {} and {}", EAGLE_CAMERA_MAX_YBIN[0],
}, EAGLE_CAMERA_MAX_YBIN[1]);
[&bin_validator, this](const uchar& val) { } else if (val > EAGLE_CAMERA_MAX_YBIN[1]) {
logDebug("Try to set YBIN to {} ...", val); res.first = EAGLE_CAMERA_MAX_YBIN[1];
res.second = std::format("The YBIN must not be greater than {}", EAGLE_CAMERA_MAX_XBIN[1]);
auto v_res = bin_validator(val, "YBIN");
if (v_res.second.size()) {
logWarn(v_res.second);
} }
// inner register value of binning starts from 0!!! return res;
v_res.first -= 1; },
writeRegisters(CL_YBIN_ADDR, {v_res.first}); "YBIN"));
logDebug("YBIN is set to {} (inner register value {})", v_res.first + 1, v_res.first);
}));
/* TEC SET POINT AND STATE */ /* TEC SET POINT AND STATE */
@ -1714,7 +1665,7 @@ void RaptorEagleCCD::initAttrComm()
addAttribute( addAttribute(
CAMERA_ATTR_READ_RATE, CAMERA_ATTR_READ_RATE,
[this]() { [this]() {
auto bytes = readRegisters(CL_READOUT_CLOCK_RATE_ADDR); auto bytes = readRegisters(CL_FRAMERATE_ADDR);
std::string_view val; std::string_view val;
if ((bytes[0] == CL_READOUT_CLOCK_RATE_A3_2MHZ) && (bytes[1] == CL_READOUT_CLOCK_RATE_A4_2MHZ)) { if ((bytes[0] == CL_READOUT_CLOCK_RATE_A3_2MHZ) && (bytes[1] == CL_READOUT_CLOCK_RATE_A4_2MHZ)) {
@ -1744,7 +1695,7 @@ void RaptorEagleCCD::initAttrComm()
logInfo("Set readout rate to {}", CAMERA_ATTR_READ_RATE_FAST); logInfo("Set readout rate to {}", CAMERA_ATTR_READ_RATE_FAST);
} }
writeRegisters(CL_READOUT_CLOCK_RATE_ADDR, bytes); writeRegisters(CL_FRAMERATE_ADDR, bytes);
logDebug("Readout rate is set to [0x{:02X}, 0x{:02X}] bytes", bytes[0], bytes[1]); logDebug("Readout rate is set to [0x{:02X}, 0x{:02X}] bytes", bytes[0], bytes[1]);
}, },

View File

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