diff --git a/raptor_eagle_cameralink.h b/raptor_eagle_cameralink.h index 40ffa41..2ca24cc 100644 --- a/raptor_eagle_cameralink.h +++ b/raptor_eagle_cameralink.h @@ -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 */ diff --git a/raptor_eagle_ccd.cpp b/raptor_eagle_ccd.cpp index b1d48a8..4d40120 100644 --- a/raptor_eagle_ccd.cpp +++ b/raptor_eagle_ccd.cpp @@ -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(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(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(bytes.data() + 10); // at 0C - double cnt2 = *reinterpret_cast(bytes.data() + 12); // at +40C + double cnt1 = *reinterpret_cast(_manufacturerData.data() + 10); // at 0C + double cnt2 = *reinterpret_cast(_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(bytes.data() + 14); // at 0C - _dacTECSetPointCalibData[1] = *reinterpret_cast(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(_manufacturerData.data() + 14); // at 0C + cnt2 = *reinterpret_cast(_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 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(temp * k + b); + uint64_t v = static_cast(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(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(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); + }); } diff --git a/raptor_eagle_ccd.h b/raptor_eagle_ccd.h index 92d9d36..bf3adfc 100644 --- a/raptor_eagle_ccd.h +++ b/raptor_eagle_ccd.h @@ -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(_manufacturerData.data())}; // camera serial number (the first 2 bytes) + std::chrono::year_month_day _buildDate; // 3 bytes + const std::string_view _buildCode{reinterpret_cast(_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(_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(_manufacturerData.data() + 14)}; void initAttrComm();