RaptorEagleV/raptor_eagle_ccd.cpp
Timur A. Fatkhullin db79062506 ...
2024-12-02 01:02:11 +03:00

260 lines
7.8 KiB
C++

#include <xcliball.h>
#include <cstring>
#include "raptor_eagle_cameralink.h"
#include "raptor_eagle_ccd.h"
#include "raptor_eagle_exception.h"
#include <common/adc_utils.h>
#define DEFAULT_EPIX_VIDEO_FMT_FILE "raptor_eagle-v.fmt"
/* CONSTRUCTORS AND DESTRUCTOR */
RaptorEagleCCD::RaptorEagleCCD(const adc::traits::adc_input_char_range auto& epix_video_fmt_filename,
std::shared_ptr<spdlog::logger> logger)
: base_t("EagleCCD"),
adc::AdcSpdlogLogger(logger),
_epixFmtVideoFilename(),
_cameraUnitmap(1), // by default only the single camera
_clCommandAckBit(1), // enable by default
_clChecksumBit(1), // enable by default
_expTime(0.0)
{
addMarkToPattern("EAGLE-CCD");
std::ranges::copy(epix_video_fmt_filename, std::back_inserter(_epixFmtVideoFilename));
logDebug("CTOR: Create RaptorEagleCCD class instance");
if (_epixFmtVideoFilename.empty()) {
logDebug("Video format filename is not set! Use of default: {}", DEFAULT_EPIX_VIDEO_FMT_FILE);
} else {
logDebug("Set video format filename: {}", _epixFmtVideoFilename);
}
}
RaptorEagleCCD::RaptorEagleCCD(std::shared_ptr<spdlog::logger> logger)
: RaptorEagleCCD(std::string_view(), std::move(logger))
{
}
RaptorEagleCCD::~RaptorEagleCCD()
{
logDebug("DTOR: Delete RaptorEagleCCD class instance");
}
/* PRIVATE METHODS */
void RaptorEagleCCD::initCamera(int unitmap)
{
logInfo("Try to init camera with unitmap: {} ...", unitmap);
if (unitmap < 0) {
throw std::system_error(RaptorEagleCCDError::ERROR_INVALID_UNITMAP);
}
_cameraUnitmap = unitmap;
xclibApiCall(pxd_serialConfigure(_cameraUnitmap, 0, CL_DEFAULT_BAUD_RATE, CL_DEFAULT_DATA_BITS, 0,
CL_DEFAULT_STOP_BIT, 0, 0, 0),
std::format("pxd_serialConfigure({}, 0, {}, {}, 0, {}, 0, 0, 0)", _cameraUnitmap, CL_DEFAULT_BAUD_RATE,
CL_DEFAULT_DATA_BITS, CL_DEFAULT_STOP_BIT));
logInfo("Camera with unitmap '{}' is initialized", _cameraUnitmap);
}
void RaptorEagleCCD::openPIXCI()
{
if (_epixFmtVideoFilename.size()) {
xclibApiCall(pxd_PIXCIopen("", nullptr, _epixFmtVideoFilename.c_str()),
std::format("pxd_PIXCIopen(\"\", NULL, {})", _epixFmtVideoFilename));
} else {
xclibApiCall(pxd_PIXCIopen("", "DEFAULT", ""), "pxd_PIXCIopen(\"\", \"DEFAULT\", \"\")");
#include DEFAULT_EPIX_VIDEO_FMT_FILE // exported from XCAP (Linux 64-bit!): bin 1x1, full CCD frame
pxd_videoFormatAsIncludedInit(0);
xclibApiCall(pxd_videoFormatAsIncluded(0), "pxd_videoFormatAsIncluded(0)");
}
}
void RaptorEagleCCD::closePIXCI()
{
// no exception here!!!
xclibApiCall<true>(pxd_PIXCIclose(), "pxd_PIXCIclose()");
}
/* CameraLink-RELATED METHODS */
size_t RaptorEagleCCD::clRead(byte_seq_t& bytes)
{
size_t nbytes;
// how many byte are available
xclibApiCall(nbytes = pxd_serialRead(_cameraUnitmap, 0, nullptr, 0),
std::format("pxd_serialRead({}, 0, NULL, 0)", _cameraUnitmap));
if (!nbytes) {
logWarn("There are no bytes in Rx-buffer! Nothing to do!");
return 0;
}
nbytes += _clCommandAckBit + _clChecksumBit;
if (bytes.size() < nbytes) {
bytes.resize(nbytes);
}
xclibApiCall(pxd_serialRead(_cameraUnitmap, 0, bytes.data(), nbytes),
std::format("pxd_serialRead({}, 0, {}, {})", _cameraUnitmap, (void*)bytes.data(), nbytes));
if (_loggerSPtr->level() == spdlog::level::trace) {
std::string s;
adc::utils::AdcCharRangeFromValueRange(s, bytes, std::string_view(", "));
logTrace("Received from controller: [{}]", s);
}
return nbytes;
}
size_t RaptorEagleCCD::clReadAndCheckAck(byte_seq_t& bytes)
{
auto nbytes = clRead(bytes);
if (_clCommandAckBit && nbytes) {
auto ack = *(bytes.end() - 1 - _clChecksumBit);
if (ack != CL_ETX) {
throw std::error_code(ack, RaptorEagleControllerErrorCategory::get());
}
}
return nbytes;
}
size_t RaptorEagleCCD::clWrite(const byte_seq_t& bytes)
{
if (bytes.empty()) {
logWarn("An empty transmitted byte sequence! Nothing to do!");
return 0;
}
if (_loggerSPtr->level() == spdlog::level::trace) {
std::string s;
adc::utils::AdcCharRangeFromValueRange(s, bytes, std::string_view(", "));
logTrace("Send to controller: [{}]", s);
}
size_t nbytes, tr_nbytes = bytes.size();
// how many bytes are available in Tx-buffer
xclibApiCall(nbytes = pxd_serialWrite(_cameraUnitmap, 0, nullptr, 0),
std::format("pxd_serialWrite({}, 0, NULL, 0)", _cameraUnitmap));
if (nbytes) {
tr_nbytes += _clCommandAckBit + _clChecksumBit;
if (nbytes < tr_nbytes) {
logWarn(
"Not enough of available space in the internal Tx-buffer (needs = {}, available = {})! Nothing to do!",
tr_nbytes, nbytes);
nbytes = 0;
} else {
xclibApiCall(
nbytes = pxd_serialWrite(_cameraUnitmap, 0, (char*)bytes.data(), bytes.size()),
std::format("pxd_serialWrite({}, 0, {}, {})", _cameraUnitmap, (void*)bytes.data(), bytes.size()));
if (nbytes != bytes.size()) {
throw std::error_code(RaptorEagleCCDError::ERROR_CAMLINK_WRITE);
}
}
} else {
logWarn("No available space in the internal Tx-buffer! Nothing to do!");
}
return nbytes;
}
/* CREATE COMMANDS AND ATTRIBUTES */
void RaptorEagleCCD::initAttrComm()
{
/* commands */
/* attributes */
addAttribute(
CAMERA_ATTR_CAMLINK_SETUP,
[this]() {
logTrace("Return CameraLink setup bits (current values: command-ack = {}, checksum = {})", _clCommandAckBit,
_clChecksumBit);
return std::vector<uint8_t>({_clCommandAckBit, _clChecksumBit});
},
[this](const std::vector<uint8_t>& setup) {
logDebug("Try to set CameraLink setup bits ...");
if (setup.size() < 2) {
throw std::error_code(RaptorEagleCCDError::ERROR_INVALID_ATTR_VALUE);
}
_clCommandAckBit = setup[0] ? 1 : 0;
_clChecksumBit =
(setup[1] && _clCommandAckBit) ? 1 : 0; // checksum will be enabled only if command ack is set
logDebug("Set CameraLink setup bits to: command-ack = {}, checksum = {}", _clCommandAckBit, _clChecksumBit);
});
// exposure time
addAttribute(
CAMERA_ATTR_EXPTIME,
[this]() {
logTrace("Return acquision duration (current value is {})", _expTime);
return _expTime;
},
[this](const double& exp_time) {
logDebug("Try to set acquisition duration to {} seconds ...", exp_time);
if (_expTime < 0.0) {
logWarn("Acquisition duration must be non-negative!");
_expTime = 0.0;
} else if (_expTime > EAGLE_CAMERA_MAX_EXPTIME) {
logWarn("Acquisition duration must not be greater than {} seconds!", EAGLE_CAMERA_MAX_EXPTIME);
_expTime = EAGLE_CAMERA_MAX_EXPTIME;
} else {
_expTime = exp_time;
}
logDebug("Acquisition duration is set to {} second", _expTime);
});
// number of exposures
addAttribute(
CAMERA_ATTR_NEXP,
[this]() {
logTrace("Return number of frames in acquisition sequence (current value is {})", _frameNumbers);
return _frameNumbers;
},
[this](const size_t& nframes) {
_frameNumbers = nframes;
logDebug("Number of frames in acquisition sequence is set to {}", _frameNumbers);
});
}