RaptorEagleV/raptor_eagle_ccd.h
2024-12-05 11:22:11 +03:00

237 lines
9.9 KiB
C++

#pragma once
#include <spdlog/sinks/null_sink.h>
#include <common/adc_spdlog.h>
#include <device/adc_device.h>
#include <device/adc_device_attribute.h>
#include <device/adc_device_command.h>
#include <xcliball.h>
#include "raptor_eagle_exception.h"
class RaptorEagleCCD : public adc::AdcGenericDevice<std::string,
adc::AdcDeviceAttribute<std::string_view>,
adc::AdcDeviceCommand<std::string_view>>,
adc::AdcSpdlogLogger
{
typedef adc::AdcGenericDevice<std::string,
adc::AdcDeviceAttribute<std::string_view>,
adc::AdcDeviceCommand<std::string_view>>
base_t;
public:
/* some Eagle V camera constants */
// static constexpr double EAGLE_CAMERA_MAX_EXPTIME = 27487.7906944; // in seconds (0xFFFFFFFFFF * 25nsec)
static constexpr double EAGLE_CAMERA_MAX_EXPTIME = 2.5E-8 * 0xFFFFFFFFFF; // in seconds (0xFFFFFFFFFF * 25nsec)
static constexpr size_t EAGLE_CAMERA_MAX_FRAMERATE = 0xFFFFFFFFFF * 40; // in MHz (0xFFFFFFFFFF * 40MHz)
static constexpr uint16_t EAGLE_CAMERA_CCDDIM[] = {2048, 2048};
static constexpr uchar EAGLE_CAMERA_MAX_XBIN[] = {32, 64};
static constexpr uchar EAGLE_CAMERA_MAX_YBIN[] = {32, 64};
static constexpr double ADC_CALIBRATION_POINT_1 = 0.0;
static constexpr double ADC_CALIBRATION_POINT_2 = 40.0;
static constexpr double DAC_CALIBRATION_POINT_1 = 0.0;
static constexpr double DAC_CALIBRATION_POINT_2 = 40.0;
static constexpr double SHUTTER_DELAY_PERIOD = 1.6384; // in millisecs
static constexpr double SHUTTER_MAX_DELAY_PERIOD = SHUTTER_DELAY_PERIOD * 0xFF; // in millisecs
static constexpr double SHUTTER_DEFAULT_DELAY_PERIOD = 19.66; // in millisecs
static constexpr std::string_view CAMERA_ATTR_XBIN{"XBIN"};
static constexpr std::string_view CAMERA_ATTR_YBIN{"YBIN"};
static constexpr std::string_view CAMERA_ATTR_ROI_STARTX{"ROI_STARTX"};
static constexpr std::string_view CAMERA_ATTR_ROI_STARTY{"ROI_STARTY"};
static constexpr std::string_view CAMERA_ATTR_ROI_WIDTH{"ROI_WIDTH"};
static constexpr std::string_view CAMERA_ATTR_ROI_HEIGHT{"ROI_HEIGHT"};
static constexpr std::string_view CAMERA_ATTR_GAIN{"GAIN"};
static constexpr std::string_view CAMERA_ATTR_TRIGGER_MODE{"TRIGGER_MODE"};
static constexpr std::string_view CAMERA_ATTR_READ_RATE{"READ_RATE"};
static constexpr std::string_view CAMERA_ATTR_READ_MODE{"READ_MODE"};
static constexpr std::string_view CAMERA_ATTR_TECPOINT{"TECPOINT"};
static constexpr std::string_view CAMERA_ATTR_TECSTATE{"TECSTATE"};
static constexpr std::string_view CAMERA_ATTR_TECPOINT_DAC{"TECPOINT_DAC"};
static constexpr std::string_view CAMERA_ATTR_CCD_TEMP{"CCD_TEMP"};
static constexpr std::string_view CAMERA_ATTR_PCB_TEMP{"PCB_TEMP"};
static constexpr std::string_view CAMERA_ATTR_EXPTIME{"EXPTIME"};
static constexpr std::string_view CAMERA_ATTR_FRAME_RATE{"FRAME_RATE"};
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_SHUTTER_OPENDELAY{"SHUTTER_OPEN_DELAY"};
static constexpr std::string_view CAMERA_ATTR_SHUTTER_CLOSEDELAY{"SHUTTER_CLOSE_DELAY"};
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_INITCAM{"INITCAM"};
static constexpr std::string_view CAMERA_CMD_START_EXP{"START_EXP"};
static constexpr std::string_view CAMERA_CMD_STOP_EXP{"STOP_EXP"};
// some character attributes values
static constexpr std::string_view CAMERA_ATTR_STR_INVALID{"INVALID"};
static constexpr std::string_view CAMERA_ATTR_READ_MODE_NORMAL{"NORMAL"};
static constexpr std::string_view CAMERA_ATTR_READ_MODE_TEST{"TEST"};
static constexpr std::string_view CAMERA_ATTR_READ_RATE_SLOW{"SLOW"};
static constexpr std::string_view CAMERA_ATTR_READ_RATE_FAST{"FAST"};
static constexpr std::string_view CAMERA_ATTR_TECSTATE_ON{"ON"};
static constexpr std::string_view CAMERA_ATTR_TECSTATE_OFF{"OFF"};
static constexpr std::string_view CAMERA_ATTR_SHUTTER_STATE_OPEN{"OPEN"}; // always open
static constexpr std::string_view CAMERA_ATTR_SHUTTER_STATE_CLOSED{"CLOSED"}; // always closed
static constexpr std::string_view CAMERA_ATTR_SHUTTER_STATE_EXP{"EXP"}; // open during acquisition
// external trigger, rising edge enabled
static constexpr std::string_view CAMERA_ATTR_TRIGGER_MODE_EXT_RISING{"EXTERNAL_RISING"};
// external trigger, falling edge enabled
static constexpr std::string_view CAMERA_ATTR_TRIGGER_MODE_EXT_FALLING{"EXTERNAL_FALLING"};
// internal trigger for continuos acquisition
static constexpr std::string_view CAMERA_ATTR_TRIGGER_MODE_ITR{"ITR"};
// fixed frame rate acquisition
static constexpr std::string_view CAMERA_ATTR_TRIGGER_MODE_FFR{"FFR"};
// snapshot
static constexpr std::string_view CAMERA_ATTR_TRIGGER_MODE_SNAPSHOT{"SNAPSHOT"};
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"));
RaptorEagleCCD(std::shared_ptr<spdlog::logger> logger = spdlog::null_logger_mt("EAGLE_CCD_NULLLOGGER"));
~RaptorEagleCCD();
private:
typedef std::vector<unsigned char> byte_seq_t;
std::string _epixFmtVideoFilename;
int _cameraUnitmap;
uint16_t _dimCCD[2] = {2048, 2048}; // init to E2V 4240 CCD dimension
// CCD temperature and TEC set point calibration data
double _adcCCDTempCalibCoeffs[2] = {0, 0}; // [k, b], Temp(degs C) = k*ADC + b
// [k, b, k_rev, b_rev]
// Temp = k*DAC + b
// DAC = k_rev*Temp + b_rev
double _dacTECSetPointCalibCoeffs[4] = {0, 0};
// CameraLink read/write setup flags
uint8_t _clCommandAckBit;
uint8_t _clChecksumBit;
std::recursive_mutex _camlinkMutex;
// attributes inner variables
size_t _frameNumbers;
// hardware version info
byte_seq_t _microVersion; // microcontroller version: _microVersion[0] - major, _microVersion[1] - minor
byte_seq_t _FPGAVersion; // same for FPGA version
// man data is 18-byte array + 2 possible bytes (ETX and checksum)
byte_seq_t _manufacturerData = byte_seq_t(20);
// extract fields according to instruction manual (WARNING: works only for little-endian platforms!)
const uint16_t& _cameraSerialNumber{
*reinterpret_cast<const uint16_t*>(_manufacturerData.data())}; // camera serial number (the first 2 bytes)
std::chrono::year_month_day _buildDate; // 3 bytes
const std::string_view _buildCode{reinterpret_cast<const char*>(_manufacturerData.data() + 5), 5}; // 5 bytes
// must be interpretated as 2-element array of calibration points [at 0C, at +40C] (4 bytes)
const uint16_t* _adcCCDTempCalibData{reinterpret_cast<const uint16_t*>(_manufacturerData.data() + 10)};
// must be interpretated as 2-element array of calibration points [at 0C, at +40C] (4 bytes)
const uint16_t* _dacTECSetPointCalibData{reinterpret_cast<const uint16_t*>(_manufacturerData.data() + 14)};
void initAttrComm();
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 clReadAndCheckAck();
size_t clWrite(const byte_seq_t& bytes);
// CameraLink-related registers read/write methods
// there are two kind of SET-READ_REGISTER-ADDRESS command in the current version of the camera controller firmware:
// {0x53, 0xE0, 0x01} and
// {0x53, 0xE0, 0x02}
//
// NOTE: given 'set_addr_cmd' byte sequence must be one-byte longer than the command itself!!!
byte_seq_t readRegisters(const byte_seq_t& addrs, byte_seq_t set_addr_cmd = {0x53, 0xE0, 0x01, 0x00});
void writeRegisters(const byte_seq_t& addrs, const byte_seq_t& values);
// camera and FPGA control registers getter/setter
std::bitset<8> getSystemState();
void setSystemState(const std::bitset<8>& bits);
void setSystemStateBit(const size_t bit_pos);
void clearSystemStateBit(const size_t bit_pos);
void flipSystemStateBit(const size_t bit_pos);
std::bitset<8> getFPGAState();
void setFPGAState(const std::bitset<8>& bits);
void setFPGAStateBit(const size_t bit_pos);
void clearFPGAStateBit(const size_t bit_pos);
void flipFPGAStateBit(const size_t bit_pos);
// reset hardware methods
// returns true if OK, false - timeout
bool resetMicro(const std::chrono::milliseconds& timeout = std::chrono::milliseconds(5000));
// hardware info methods
void getHardwareInfo();
void getMicroVersion();
void getFPGAVersion();
// logging helper methods
template <bool NOEXCEPT = false>
void xclibApiCall(int err, const adc::traits::adc_input_char_range auto& func_name)
{
if (err < 0) {
if (std::ranges::size(func_name)) {
logError("XCLIB API call ('{}') returns: {} ({})", func_name, err, pxd_mesgErrorCode(err));
} else {
logError("XCLIB API call returns: {} ({})", err, pxd_mesgErrorCode(err));
}
if constexpr (!NOEXCEPT) {
throw std::error_code(err, XCLIBErrorCategory::get());
}
} else {
if (std::ranges::size(func_name)) {
logDebug("XCLIB API call ('{}') finished successfully", func_name);
}
}
}
template <bool NOEXCEPT = false>
void xclibApiCall(int err)
{
xclibApiCall<NOEXCEPT>(err, std::string_view(""));
}
};