This commit is contained in:
Timur A. Fatkhullin 2024-12-05 11:22:11 +03:00
parent e834f2c5d6
commit 5f6b7fa4cf
3 changed files with 249 additions and 57 deletions

View File

@ -95,13 +95,18 @@ static constexpr std::string_view cl_fpga_ctrl_reg_bit(const size_t pos)
// trigger mode
static constexpr char CL_TRIGGER_MODE_ENABLE_RISING_EDGE = 0x80; // 7-th bit
static constexpr char CL_TRIGGER_MODE_EXT_TRIGGER = 0x40; // 6-th bit
static constexpr char CL_TRIGGER_MODE_ABORT_CURRENT_EXP = 0x8; // 3-rd bit
static constexpr char CL_TRIGGER_MODE_CONTINUOUS_SEQ = 0x4; // 2-nd bit
static constexpr char CL_TRIGGER_MODE_FIXED_FRAME_RATE = 0x2; // 1-st bit
static constexpr char CL_TRIGGER_MODE_SNAPSHOT = 0x1; // 0-th bit
static constexpr size_t CL_TRIGGER_MODE_ENABLE_RISING_EDGE_BIT = 7;
static constexpr size_t CL_TRIGGER_MODE_EXT_TRIGGER_BIT = 6;
static constexpr size_t CL_TRIGGER_MODE_ABORT_CURRENT_EXP_BIT = 3;
static constexpr size_t CL_TRIGGER_MODE_CONTINUOUS_SEQ_BIT = 2;
static constexpr size_t CL_TRIGGER_MODE_FIXED_FRAME_RATE_BIT = 1;
static constexpr size_t CL_TRIGGER_MODE_SNAPSHOT_BIT = 0;
static constexpr unsigned char CL_TRIGGER_MODE_EXT_RISING_EDGE = 0b11000000;
static constexpr unsigned char CL_TRIGGER_MODE_EXT_FALLING_EDGE = 0b01000000;
static constexpr unsigned char CL_TRIGGER_MODE_FFR = 0b00000110;
static constexpr unsigned char CL_TRIGGER_MODE_ITR = 0b00000100;
static constexpr unsigned char CL_TRIGGER_MODE_SNAPSHOT = 0; // just clear all bits
/* SETUP CONTROL VALUES */

View File

@ -316,6 +316,12 @@ void RaptorEagleCCD::initCamera(int unitmap)
std::format("pxd_serialConfigure({}, 0, {}, {}, 0, {}, 0, 0, 0)", _cameraUnitmap, CL_DEFAULT_BAUD_RATE,
CL_DEFAULT_DATA_BITS, CL_DEFAULT_STOP_BIT));
getSystemState();
getHardwareInfo();
getMicroVersion();
getFPGAVersion();
logInfo("Camera with unitmap '{}' is initialized", _cameraUnitmap);
}
@ -578,23 +584,17 @@ void RaptorEagleCCD::getHardwareInfo()
{
std::lock_guard lock_guard(_camlinkMutex);
static byte_seq_t bytes(20);
// first, according to instruction manual, set FPGA comms bit
setSystemStateBit(CL_SYSTEM_STATUS_FPGA_EEPROM_COMMS_BIT);
// get manufacturer data
clWrite({0x53, 0xAE, 0x05, 0x01, 0x00, 0x00, 0x02, 0x00});
clWrite({0x53, 0xAF, 0x12});
clReadAndCheckAck(bytes);
clReadAndCheckAck(_manufacturerData);
// NOTE: works only for little-endian platforms!!!
_cameraSerialNumber = *reinterpret_cast<uint16_t*>(bytes.data());
_buildDate = std::chrono::year_month_day(std::chrono::year(2000 + bytes[4]) / std::chrono::month(bytes[3]) /
std::chrono::day(bytes[2]));
_buildCode = std::string_view(reinterpret_cast<char*>(bytes.data() + 5), 5);
_buildDate =
std::chrono::year_month_day(std::chrono::year(2000 + _manufacturerData[4]) /
std::chrono::month(_manufacturerData[3]) / std::chrono::day(_manufacturerData[2]));
logDebug("------- Manufacturer data -------");
logDebug("Camerial serial number: {}", _cameraSerialNumber);
@ -602,24 +602,33 @@ void RaptorEagleCCD::getHardwareInfo()
logDebug("Build code: {}", _buildCode);
// ADC calibration data
double cnt1 = *reinterpret_cast<uint16_t*>(bytes.data() + 10); // at 0C
double cnt2 = *reinterpret_cast<uint16_t*>(bytes.data() + 12); // at +40C
double cnt1 = *reinterpret_cast<uint16_t*>(_manufacturerData.data() + 10); // at 0C
double cnt2 = *reinterpret_cast<uint16_t*>(_manufacturerData.data() + 12); // at +40C
logDebug("");
logDebug("ADC calib data {} counts at 0C", cnt1);
logDebug("ADC calib data {} counts at +40C", cnt2);
logDebug("ADC calib data [{}, {}] counts at [{}C, {}C]", _adcCCDTempCalibData[0], _adcCCDTempCalibData[1],
ADC_CALIBRATION_POINT_1, ADC_CALIBRATION_POINT_2);
// compute linear relation: Temp = k*ADC + b
_adcCCDTempCalibCoeffs[0] = (cnt2 - cnt1) / (ADC_CALIBRATION_POINT_2 - ADC_CALIBRATION_POINT_1); // k
_adcCCDTempCalibCoeffs[1] = ADC_CALIBRATION_POINT_2 - _adcCCDTempCalibCoeffs[0] * cnt2;
// DAC calibration data
_dacTECSetPointCalibData[0] = *reinterpret_cast<uint16_t*>(bytes.data() + 14); // at 0C
_dacTECSetPointCalibData[1] = *reinterpret_cast<uint16_t*>(bytes.data() + 16); // at +40C
logDebug("Computed ADC-to-Temp linear relation: Temp(C) = {:7.4}*ADC(counts)+{:6.2}");
logDebug("");
logDebug("DAC calib data {} counts at 0C", _dacTECSetPointCalibData[0]);
logDebug("DAC calib data {} counts at +40C", _dacTECSetPointCalibData[1]);
logDebug("DAC calib data [{}, {}] counts at [{}C, {}C]", _dacTECSetPointCalibData[0], _dacTECSetPointCalibData[1],
DAC_CALIBRATION_POINT_1, DAC_CALIBRATION_POINT_2);
cnt1 = *reinterpret_cast<uint16_t*>(_manufacturerData.data() + 14); // at 0C
cnt2 = *reinterpret_cast<uint16_t*>(_manufacturerData.data() + 16); // at +40C
_dacTECSetPointCalibCoeffs[0] = (cnt2 - cnt1) / (DAC_CALIBRATION_POINT_2 - DAC_CALIBRATION_POINT_1);
_dacTECSetPointCalibCoeffs[1] = DAC_CALIBRATION_POINT_2 - _dacTECSetPointCalibCoeffs[0] * cnt2;
logDebug("Computed DAC-to-Temp linear relation: Temp(C) = {:7.4}*DAC(counts)+{:6.2}");
_dacTECSetPointCalibCoeffs[2] = (DAC_CALIBRATION_POINT_2 - DAC_CALIBRATION_POINT_1) / (cnt2 - cnt1);
_dacTECSetPointCalibCoeffs[3] = cnt2 - _dacTECSetPointCalibCoeffs[0] * DAC_CALIBRATION_POINT_2;
logDebug("Computed DAC-to-Temp linear relation: DAC(counts) = {}*Temp(C)+{}");
logDebug("---------------------------------");
}
@ -710,6 +719,21 @@ void RaptorEagleCCD::initAttrComm()
/* commands */
addCommand(CAMERA_CMD_INITCAM, [this]() {
logDebug("Try to execute '{}' command", CAMERA_CMD_INITCAM);
initCamera();
});
addCommand(CAMERA_CMD_START_EXP, [this]() {
logDebug("Try to execute '{}' command", CAMERA_CMD_START_EXP);
//
});
addCommand(CAMERA_CMD_STOP_EXP, [this]() {
logDebug("Try to execute '{}' command", CAMERA_CMD_STOP_EXP);
//
});
/* attributes */
@ -959,7 +983,7 @@ void RaptorEagleCCD::initAttrComm()
"YBIN"));
/* TEC SET POINT */
/* TEC SET POINT AND STATE */
// DAC counts
addAttribute(create12BitAttr(
@ -968,7 +992,8 @@ void RaptorEagleCCD::initAttrComm()
std::pair<T, std::string> res{counts, ""};
if (counts > 0x0FFF) {
res.second = std::format("TEC set point counts must not be greater than {}", 0x0FFF);
res.second =
std::format("TEC set point counts must not be greater than {}. Set it to {}!", 0x0FFF, 0x0FFF);
res.first = 0x0FFF;
}
@ -982,33 +1007,45 @@ void RaptorEagleCCD::initAttrComm()
[this]() {
double counts = (*this)[CAMERA_ATTR_TECPOINT_DAC];
double k = (DAC_CALIBRATION_POINT_2 - DAC_CALIBRATION_POINT_1) /
(_dacTECSetPointCalibData[1] - _dacTECSetPointCalibData[0]);
double b = _dacTECSetPointCalibData[0] - k * DAC_CALIBRATION_POINT_1;
double temp = k * counts + b;
logTrace("Computed Temp-to-DAC linear relation: DAC = {}*Temp + {}", k, b);
double temp = _dacTECSetPointCalibCoeffs[0] * counts + _dacTECSetPointCalibCoeffs[1];
logDebug("Return TEC set point as {} Celsius degrees", temp);
return temp;
},
[this](const double& temp) {
double k = (_dacTECSetPointCalibData[1] - _dacTECSetPointCalibData[0]) /
(DAC_CALIBRATION_POINT_2 - DAC_CALIBRATION_POINT_1);
double b = DAC_CALIBRATION_POINT_1 - k * _dacTECSetPointCalibData[0];
logTrace("Computed DAC-to-Temp linear relation: Temp = {}*DAC + {}", k, b);
uint64_t v = static_cast<uint64_t>(temp * k + b);
uint64_t v = static_cast<uint64_t>(temp * _dacTECSetPointCalibCoeffs[2] + _dacTECSetPointCalibCoeffs[3]);
uint16_t counts = v & 0x0FFF; // extract 12-bits
logInfo("Set TEC setup point to {} C", temp);
(*this)[CAMERA_ATTR_TECPOINT_DAC] = counts;
});
addAttribute(
CAMERA_ATTR_TECSTATE,
[this]() {
bool bit = getFPGAState().test(CL_FPGA_CTRL_REG_ENABLE_TEC_BIT);
if (bit) {
return CAMERA_ATTR_TECSTATE_ON;
} else {
return CAMERA_ATTR_TECSTATE_OFF;
}
},
[this](const std::string_view& state) {
if (state == CAMERA_ATTR_TECSTATE_ON) {
logInfo("Turn ON TEC");
setFPGAStateBit(CL_FPGA_CTRL_REG_ENABLE_TEC_BIT);
} else if (state == CAMERA_ATTR_TECSTATE_OFF) {
logInfo("Turn OFF TEC");
clearFPGAStateBit(CL_FPGA_CTRL_REG_ENABLE_TEC_BIT);
} else {
logWarn("Invalid TEC state string value! Ignore!");
}
});
/* CCD and PCB temperature (read-only) */
addAttribute(CAMERA_ATTR_PCB_TEMP, [this]() {
@ -1056,7 +1093,7 @@ void RaptorEagleCCD::initAttrComm()
addAttribute(
CAMERA_ATTR_READ_MODE,
[this]() -> std::string_view {
[this]() {
auto bytes = readRegisters(CL_READMODE_ADDR);
std::string_view val = CAMERA_ATTR_READ_MODE_NORMAL;
@ -1066,7 +1103,7 @@ void RaptorEagleCCD::initAttrComm()
} else {
logError("Invalid bits in readout mode register! (reg = 0x{:02X})", bytes[0]);
val = CAMERA_ATTR_READ_MODE_INVALID;
val = CAMERA_ATTR_STR_INVALID;
}
logTrace("Return readout mode as '{}' string", val);
@ -1078,12 +1115,14 @@ void RaptorEagleCCD::initAttrComm()
if (mode == CAMERA_ATTR_READ_MODE_NORMAL) {
bits = CL_READOUT_MODE_NORMAL;
}
if (mode == CAMERA_ATTR_READ_MODE_TEST) {
logInfo("Readout mode is set to {}", mode);
} else if (mode == CAMERA_ATTR_READ_MODE_TEST) {
bits = CL_READOUT_MODE_TEST;
logInfo("Readout mode is set to {}", mode);
} else {
logWarn("Invalid '{}' string for readout mode! Use of '{}'!", mode, CAMERA_ATTR_READ_MODE_NORMAL);
bits = CL_READOUT_MODE_NORMAL;
logInfo("Readout mode is set to {}", CAMERA_ATTR_READ_MODE_NORMAL);
}
writeRegisters(CL_READMODE_ADDR, {bits});
@ -1107,7 +1146,7 @@ void RaptorEagleCCD::initAttrComm()
} else {
logError("Invalid bits in readout rate registers! (A3 = 0x{:02X}, A4 = 0x{:02X})", bytes[0], bytes[1]);
val = CAMERA_ATTR_READ_RATE_INVALID;
val = CAMERA_ATTR_STR_INVALID;
}
logTrace("Return readout rate as '()' string", val);
@ -1117,11 +1156,14 @@ void RaptorEagleCCD::initAttrComm()
[this](const std::string_view& rate) {
byte_seq_t bytes({CL_READOUT_CLOCK_RATE_A3_2MHZ, CL_READOUT_CLOCK_RATE_A4_2MHZ});
if (rate == CAMERA_ATTR_READ_RATE_FAST) {
logInfo("Set readout rate to {}", rate);
} else if (rate == CAMERA_ATTR_READ_RATE_SLOW) {
bytes[0] = CL_READOUT_CLOCK_RATE_A3_75KHZ;
bytes[1] = CL_READOUT_CLOCK_RATE_A4_75KHZ;
logInfo("Set readout rate to {}", rate);
} else {
logWarn("Invalid '{}' string for readout rate! Use of '{}'!", rate, CAMERA_ATTR_READ_RATE_FAST);
logInfo("Set readout rate to {}", CAMERA_ATTR_READ_RATE_FAST);
}
writeRegisters(CL_FRAMERATE_ADDR, bytes);
@ -1130,7 +1172,7 @@ void RaptorEagleCCD::initAttrComm()
});
/* SHUTTER CONTROL (std::string_view "OPEN", "CLOSED", "EXP") */
/* SHUTTER CONTROL (std::string_view "OPEN", "CLOSED", "EXP") AND OPEN/CLOSE DELAY */
addAttribute(
CAMERA_ATTR_SHUTTER_STATE,
@ -1146,7 +1188,7 @@ void RaptorEagleCCD::initAttrComm()
val = CAMERA_ATTR_SHUTTER_STATE_EXP;
} else {
logError("Invalid bits in shhutter control register! (reg = 0x{:02X})", bytes[0]);
val = CAMERA_ATTR_SHUTTER_STATE_INVALID;
val = CAMERA_ATTR_STR_INVALID;
}
logTrace("Return shutter state as '{}' string (bits = 0x{:02X})", val, bytes[0]);
@ -1156,16 +1198,139 @@ void RaptorEagleCCD::initAttrComm()
[this](const std::string_view& state) {
byte_seq_t bytes{CL_SHUTTER_EXP};
if (state == CAMERA_ATTR_SHUTTER_STATE_EXP) {
logInfo("Set shutter state to {}", state);
} else if (state == CAMERA_ATTR_SHUTTER_STATE_CLOSED) {
bytes[0] = CL_SHUTTER_CLOSED;
logInfo("Set shutter state to {}", state);
} else if (state == CAMERA_ATTR_SHUTTER_STATE_OPEN) {
bytes[0] = CL_SHUTTER_OPEN;
logInfo("Set shutter state to {}", state);
} else {
logWarn("Invalid '{}' string for shutter state! Use of '{}'!", state, CL_SHUTTER_EXP);
logInfo("Set shutter state to {}", CL_SHUTTER_EXP);
}
writeRegisters(CL_SHUTTER_CONTROL_ADDR, bytes);
logDebug("Shutter state is set to 0x{:02X}", bytes[0]);
});
// floating-point, value is expected in millisecs
addAttribute(
CAMERA_ATTR_SHUTTER_CLOSEDELAY,
[this]() {
auto bytes = readRegisters({0xA7});
double delay = SHUTTER_DELAY_PERIOD * bytes[0];
logTrace("Return shutter closed delay duration as {} milliseconds", delay);
return delay;
},
[this](const double& delay) {
double d = SHUTTER_DEFAULT_DELAY_PERIOD;
if (delay < 0) {
logWarn("Shutter closed delay dration must be a non-negatve value! Use of default value {}",
SHUTTER_DEFAULT_DELAY_PERIOD);
} else if (delay > SHUTTER_MAX_DELAY_PERIOD) {
logWarn("Shutter closed delay dration must not be greater than {} value! Use of default value {}",
SHUTTER_MAX_DELAY_PERIOD, SHUTTER_DEFAULT_DELAY_PERIOD);
} else {
d = delay;
}
uchar counts = static_cast<uchar>(std::round(d / SHUTTER_DELAY_PERIOD));
writeRegisters({0xA7}, {counts});
logInfo("Shutter closed delay is set to {} msecs", d);
logDebug("Shutter closed delay bits are set to 0x{:02X}", counts);
});
// floating-point, value is expected in millisecs
addAttribute(
CAMERA_ATTR_SHUTTER_OPENDELAY,
[this]() {
auto bytes = readRegisters({0xA6});
double delay = SHUTTER_DELAY_PERIOD * bytes[0];
logTrace("Return shutter open delay duration as {} milliseconds", delay);
return delay;
},
[this](const double& delay) {
double d = SHUTTER_DEFAULT_DELAY_PERIOD;
if (delay < 0) {
logWarn("Shutter open delay dration must be a non-negatve value! Use of default value {}",
SHUTTER_DEFAULT_DELAY_PERIOD);
} else if (delay > SHUTTER_MAX_DELAY_PERIOD) {
logWarn("Shutter open delay dration must not be greater than {} value! Use of default value {}",
SHUTTER_MAX_DELAY_PERIOD, SHUTTER_DEFAULT_DELAY_PERIOD);
} else {
d = delay;
}
uchar counts = static_cast<uchar>(std::round(d / SHUTTER_DELAY_PERIOD));
writeRegisters({0xA6}, {counts});
logInfo("Shutter open delay is set to {} msecs", d);
logDebug("Shutter open delay bits are set to 0x{:02X}", counts);
});
/* TRIGGER MODE */
addAttribute(
CAMERA_ATTR_TRIGGER_MODE,
[this]() {
auto bytes = readRegisters({0xD4});
std::bitset<8> bits{bytes[0]};
std::string_view trigger_mode;
if (bits.test(CL_TRIGGER_MODE_EXT_TRIGGER_BIT)) { // external trigger enabled, what is the edge?
if (bits.test(CL_TRIGGER_MODE_ENABLE_RISING_EDGE_BIT)) {
trigger_mode = CAMERA_ATTR_TRIGGER_MODE_EXT_RISING;
} else {
trigger_mode = CAMERA_ATTR_TRIGGER_MODE_EXT_FALLING;
}
} else if (bits.test(CL_TRIGGER_MODE_CONTINUOUS_SEQ_BIT)) { // continuous sequence enabled
if (bits.test(CL_TRIGGER_MODE_FIXED_FRAME_RATE_BIT)) {
trigger_mode = CAMERA_ATTR_TRIGGER_MODE_FFR;
} else {
trigger_mode = CAMERA_ATTR_TRIGGER_MODE_ITR;
}
} else {
trigger_mode = CAMERA_ATTR_TRIGGER_MODE_SNAPSHOT;
}
logTrace("Return trigger mode as '{}' string (bits = 0b{:08b})", trigger_mode, bytes[0]);
return trigger_mode;
},
[this](const std::string_view& mode) {
uchar bits = CL_TRIGGER_MODE_SNAPSHOT;
if (mode == CAMERA_ATTR_TRIGGER_MODE_EXT_RISING) {
bits = CL_TRIGGER_MODE_EXT_RISING_EDGE;
logInfo("Trigger mode is set to {}", mode);
} else if (mode == CAMERA_ATTR_TRIGGER_MODE_EXT_FALLING) {
bits = CL_TRIGGER_MODE_EXT_FALLING_EDGE;
logInfo("Trigger mode is set to {}", mode);
} else if (mode == CAMERA_ATTR_TRIGGER_MODE_FFR) {
bits = CL_TRIGGER_MODE_FFR;
logInfo("Trigger mode is set to {}", mode);
} else if (mode == CAMERA_ATTR_TRIGGER_MODE_ITR) {
bits = CL_TRIGGER_MODE_ITR;
logInfo("Trigger mode is set to {}", mode);
} else if (mode == CAMERA_ATTR_TRIGGER_MODE_SNAPSHOT) {
logInfo("Trigger mode is set to {}", mode);
} else {
logWarn("Invalid trigger mode! Set it to {}!", CAMERA_ATTR_TRIGGER_MODE_SNAPSHOT);
}
writeRegisters({0xD4}, {bits});
logDebug("Trigger mode bits are set to 0b{:08b}", bits);
});
}

View File

@ -38,6 +38,12 @@ public:
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"};
@ -49,6 +55,7 @@ public:
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"};
@ -56,6 +63,8 @@ public:
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"};
@ -64,18 +73,20 @@ public:
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_MODE_INVALID{"INVALID"};
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_READ_RATE_INVALID{"INVALID"};
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
static constexpr std::string_view CAMERA_ATTR_SHUTTER_STATE_INVALID{"INVALID"};
// external trigger, rising edge enabled
static constexpr std::string_view CAMERA_ATTR_TRIGGER_MODE_EXT_RISING{"EXTERNAL_RISING"};
@ -105,10 +116,12 @@ private:
uint16_t _dimCCD[2] = {2048, 2048}; // init to E2V 4240 CCD dimension
// CCD temperature and TEC set point calibration data
// uint16_t _adcCCDTempCalibData[2] = {0, 0}; // [at 0C, at +40C]
double _adcCCDTempCalibCoeffs[2] = {0, 0}; // [k, b], Temp(degs C) = k*ADC + b
double _dacTECSetPointCalibData[2] = {0, 0}; // [at 0C, at +40C]
// [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;
@ -120,13 +133,22 @@ private:
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
uint16_t _cameraSerialNumber = 0; // camera serial number
std::chrono::year_month_day _buildDate;
std::string_view _buildCode;
// 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();