...
This commit is contained in:
parent
35e7999c3f
commit
db79062506
@ -32,7 +32,7 @@ static constexpr bool CL_DEFAULT_CHK_SUM_ENABLED = true;
|
||||
static constexpr char CL_ETX = 0x50;
|
||||
static constexpr char CL_ETX_SER_TIMEOUT = 0x51;
|
||||
static constexpr char CL_ETX_CK_SUM_ERR = 0x52;
|
||||
static constexpr char CL_ETXI2C_ERR = 0x53;
|
||||
static constexpr char CL_ETX_I2C_ERR = 0x53;
|
||||
static constexpr char CL_ETX_UNKNOWN_CMD = 0x54;
|
||||
static constexpr char CL_ETX_DONE_LOW = 0x55;
|
||||
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
#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"
|
||||
|
||||
@ -12,7 +13,14 @@
|
||||
|
||||
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)
|
||||
: 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");
|
||||
|
||||
@ -51,7 +59,12 @@ void RaptorEagleCCD::initCamera(int unitmap)
|
||||
|
||||
_cameraUnitmap = unitmap;
|
||||
|
||||
logInfo("Camera with unit '{}' is initialized", _cameraUnitmap);
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@ -77,7 +90,170 @@ void RaptorEagleCCD::closePIXCI()
|
||||
}
|
||||
|
||||
|
||||
/* 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()
|
||||
{
|
||||
addAttribute(CAMERA_ATTR_EXPTIME, []() {});
|
||||
/* 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);
|
||||
});
|
||||
}
|
||||
|
||||
@ -18,6 +18,9 @@ class RaptorEagleCCD : public adc::AdcGenericDevice<std::string, adc::AdcDeviceA
|
||||
typedef adc::AdcGenericDevice<std::string, adc::AdcDeviceAttribute<>, adc::AdcDeviceCommand<>> base_t;
|
||||
|
||||
public:
|
||||
/* some Eagle V camera constants */
|
||||
static constexpr double EAGLE_CAMERA_MAX_EXPTIME = 27487.7906944; // in seconds (0xFFFFFFFFFF * 25nsec)
|
||||
|
||||
static constexpr std::string_view CAMERA_ATTR_HBIN{"HBIN"};
|
||||
static constexpr std::string_view CAMERA_ATTR_VBIN{"VBIN"};
|
||||
static constexpr std::string_view CAMERA_ATTR_ROI_LEFT{"ROI_LEFT"};
|
||||
@ -33,6 +36,7 @@ public:
|
||||
static constexpr std::string_view CAMERA_ATTR_NEXP{"NEXP"};
|
||||
static constexpr std::string_view CAMERA_ATTR_SHUTTER_STATE{"SHUTTER_STATE"};
|
||||
static constexpr std::string_view CAMERA_ATTR_CCDDIM{"CCDDIM"};
|
||||
static constexpr std::string_view CAMERA_ATTR_CAMLINK_SETUP{"CAMLINK_SETUP"};
|
||||
|
||||
static constexpr std::string_view CAMERA_CMD_START_EXP{"START_EXP"};
|
||||
static constexpr std::string_view CAMERA_CMD_STOP_EXP{"STOP_EXP"};
|
||||
@ -49,20 +53,39 @@ public:
|
||||
~RaptorEagleCCD();
|
||||
|
||||
private:
|
||||
typedef std::vector<char> byte_seq_t;
|
||||
|
||||
std::string _epixFmtVideoFilename;
|
||||
int _cameraUnitmap;
|
||||
|
||||
// CameraLink read/write setup flags
|
||||
uint8_t _clCommandAckBit;
|
||||
uint8_t _clChecksumBit;
|
||||
|
||||
// attributes inner variables
|
||||
double _expTime;
|
||||
size_t _frameNumbers;
|
||||
|
||||
void initAttrComm();
|
||||
|
||||
void initCamera(int unitmap);
|
||||
void initCamera(int unitmap = 1);
|
||||
|
||||
void openPIXCI();
|
||||
void closePIXCI();
|
||||
|
||||
// CameraLink-related low-level methods
|
||||
|
||||
size_t clRead(byte_seq_t& bytes);
|
||||
size_t clReadAndCheckAck(byte_seq_t& bytes);
|
||||
|
||||
size_t clWrite(const byte_seq_t& bytes);
|
||||
|
||||
// logging helper methods
|
||||
|
||||
template <bool NOEXCEPT = false>
|
||||
void xclibApiCall(int err, const adc::traits::adc_input_char_range auto& func_name)
|
||||
{
|
||||
if (err) {
|
||||
if (err < 0) {
|
||||
if (std::ranges::size(func_name)) {
|
||||
logError("XCLIB API call ('{}') returns: {} ({})", func_name, err, pxd_mesgErrorCode(err));
|
||||
} else {
|
||||
|
||||
@ -3,7 +3,9 @@
|
||||
#include <xcliball.h>
|
||||
#include <system_error>
|
||||
|
||||
enum class RaptorEagleCCDError : int { ERROR_OK, ERROR_INVALID_UNITMAP };
|
||||
#include "raptor_eagle_cameralink.h"
|
||||
|
||||
enum class RaptorEagleCCDError : int { ERROR_OK, ERROR_INVALID_UNITMAP, ERROR_INVALID_ATTR_VALUE, ERROR_CAMLINK_WRITE };
|
||||
|
||||
|
||||
namespace std
|
||||
@ -33,6 +35,10 @@ struct RaptorEagleCCDErrorCategory : std::error_category {
|
||||
return "OK";
|
||||
case RaptorEagleCCDError::ERROR_INVALID_UNITMAP:
|
||||
return "invalid EPIX-library unitmap";
|
||||
case RaptorEagleCCDError::ERROR_INVALID_ATTR_VALUE:
|
||||
return "invalid camera attribute value";
|
||||
case RaptorEagleCCDError::ERROR_CAMLINK_WRITE:
|
||||
return "not all data were transmitted via CameraLink connection";
|
||||
default:
|
||||
return "UNKNOWN ERROR";
|
||||
}
|
||||
@ -46,6 +52,44 @@ struct RaptorEagleCCDErrorCategory : std::error_category {
|
||||
};
|
||||
|
||||
|
||||
/* Error category for XCLIB errors */
|
||||
struct RaptorEagleControllerErrorCategory : std::error_category {
|
||||
RaptorEagleControllerErrorCategory() : std::error_category() {}
|
||||
|
||||
const char* name() const noexcept
|
||||
{
|
||||
return "EAGLE_CCD_CONTROLLER_ERROR_CATEGORY";
|
||||
}
|
||||
|
||||
std::string message(int ec) const
|
||||
{
|
||||
switch (ec) {
|
||||
case CL_ETX:
|
||||
return "controller OK";
|
||||
case CL_ETX_SER_TIMEOUT:
|
||||
return "partial controller command received (camera timed out)";
|
||||
case CL_ETX_CK_SUM_ERR:
|
||||
return "controller command checksum mismatch";
|
||||
case CL_ETX_I2C_ERR:
|
||||
return "controller I2C internal failure";
|
||||
case CL_ETX_UNKNOWN_CMD:
|
||||
return "controller unknown command";
|
||||
case CL_ETX_DONE_LOW:
|
||||
return "controller EPROM is busy (FPGA reboot)";
|
||||
default:
|
||||
return "UNKNOWN ERROR";
|
||||
}
|
||||
}
|
||||
|
||||
static const RaptorEagleControllerErrorCategory& get()
|
||||
{
|
||||
static const RaptorEagleControllerErrorCategory constInst;
|
||||
return constInst;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* Error category for XCLIB errors */
|
||||
struct XCLIBErrorCategory : std::error_category {
|
||||
XCLIBErrorCategory() : std::error_category() {}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user