DUNE-DAQ
DUNE Trigger and Data Acquisition software
Loading...
Searching...
No Matches
dunedaq::timing::I2CSFPSlave Class Reference

I2C slave class to control SFP transceivers. More...

#include <I2CSFPNode.hpp>

Inheritance diagram for dunedaq::timing::I2CSFPSlave:
[legend]
Collaboration diagram for dunedaq::timing::I2CSFPSlave:
[legend]

Public Member Functions

 I2CSFPSlave (const I2CMasterNode *i2c_master, uint8_t i2c_device_address)
 
virtual ~I2CSFPSlave ()
 
void sfp_reachable () const
 Check if SFP responds.
 
void ddm_available () const
 Check if DDM is supported.
 
std::pair< double, double > read_calibration_parameter_pair (uint32_t calib_parameter_id) const
 Read the raw SFP temperature.
 
double read_temperature_raw () const
 Read the raw SFP temperature.
 
double read_temperature () const
 Read the calibrated SFP temperature.
 
double read_voltage_raw () const
 Read the raw SFP voltage.
 
double read_voltage () const
 Read the calibrated SFP voltage.
 
double read_rx_power_raw () const
 Read the raw SFP temperature.
 
double read_rx_ower () const
 Read the raw SFP temperature.
 
double read_tx_power_raw () const
 Read the raw SFP tx power.
 
double read_tx_power () const
 Read the calibrated SFP tx power.
 
double read_current_raw () const
 Read the raw SFP current.
 
double read_current () const
 Read the calibrated SFP current.
 
std::string read_vendor_name () const
 Read the vendor name.
 
std::string read_vendor_part_number () const
 Read the vendor name.
 
std::string read_serial_number () const
 Read the SFP serial number.
 
bool read_ddm_support_bit () const
 Find out if SFP supports DDM.
 
bool read_soft_tx_control_support_bit () const
 Find out if SFP supports soft tx laser disable.
 
bool read_soft_tx_control_state () const
 Read the value of the soft tx disable control bit.
 
bool read_tx_disable_pin_state () const
 Read the state of the tx disable control pin.
 
bool read_i2c_reg_addressSwapBit () const
 Read whether the SFP has seperate I2C addresses, or if a special I2C address swap is required. True = address swap required.
 
void switch_soft_tx_control_bit (bool turn_on) const
 Switch on or off the SFP tx laser via the soft control bit.
 
std::string get_status (bool print_out=false) const
 Get SFP status.
 
- Public Member Functions inherited from dunedaq::timing::I2CSlave
virtual ~I2CSlave ()
 
uint8_t get_i2c_address () const
 
uint8_t read_i2c (uint32_t i2c_device_address, uint32_t i2c_reg_address) const
 comodity functions
 
uint8_t read_i2c (uint32_t i2c_reg_address) const
 
void write_i2c (uint32_t i2c_device_address, uint32_t i2c_reg_address, uint8_t data, bool send_stop=true) const
 
void write_i2c (uint32_t i2c_reg_address, uint8_t data, bool send_stop=true) const
 
std::vector< uint8_t > read_i2cArray (uint32_t i2c_device_address, uint32_t i2c_reg_address, uint32_t number_of_words) const
 
std::vector< uint8_t > read_i2cArray (uint32_t i2c_reg_address, uint32_t number_of_words) const
 
void write_i2cArray (uint32_t i2c_device_address, uint32_t i2c_reg_address, std::vector< uint8_t > data, bool send_stop=true) const
 
void write_i2cArray (uint32_t i2c_reg_address, std::vector< uint8_t > data, bool send_stop=true) const
 
std::vector< uint8_t > read_i2cPrimitive (uint32_t number_of_bytes) const
 
void write_i2cPrimitive (const std::vector< uint8_t > &data, bool send_stop=true) const
 
bool ping () const
 
std::string get_master_id () const
 

Protected Attributes

const std::vector< uint32_t > m_calibration_parameter_start_addresses
 Get and fill SFP hardware data.
 

Additional Inherited Members

- Protected Member Functions inherited from dunedaq::timing::I2CSlave
 I2CSlave (const I2CMasterNode *i2c_master, uint8_t i2c_device_address)
 

Detailed Description

I2C slave class to control SFP transceivers.

Author
Alessandro Thea
Date
April 2018

Definition at line 37 of file I2CSFPNode.hpp.

Constructor & Destructor Documentation

◆ I2CSFPSlave()

dunedaq::timing::I2CSFPSlave::I2CSFPSlave ( const I2CMasterNode * i2c_master,
uint8_t i2c_device_address )

Definition at line 21 of file I2CSFPNode.cpp.

22 : I2CSlave(i2c_master, address)
23 , m_calibration_parameter_start_addresses({ 0x4C, 0x50, 0x54, 0x58 }) // laser current, tx_pwr, temp, voltage
24{}
const std::vector< uint32_t > m_calibration_parameter_start_addresses
Get and fill SFP hardware data.
I2CSlave(const I2CMasterNode *i2c_master, uint8_t i2c_device_address)
Definition I2CSlave.cpp:33

◆ ~I2CSFPSlave()

dunedaq::timing::I2CSFPSlave::~I2CSFPSlave ( )
virtual

Definition at line 28 of file I2CSFPNode.cpp.

28{}

Member Function Documentation

◆ ddm_available()

void dunedaq::timing::I2CSFPSlave::ddm_available ( ) const

Check if DDM is supported.

Definition at line 43 of file I2CSFPNode.cpp.

44{
45 if (!read_ddm_support_bit()) {
46 throw SFPDDMUnsupported(ERS_HERE, get_master_id());
47 } else {
49 throw SFPDDMI2CAddressSwapUnsupported(ERS_HERE, get_master_id());
50 }
51 }
52}
#define ERS_HERE
bool read_ddm_support_bit() const
Find out if SFP supports DDM.
bool read_i2c_reg_addressSwapBit() const
Read whether the SFP has seperate I2C addresses, or if a special I2C address swap is required....
std::string get_master_id() const
Definition I2CSlave.cpp:145

◆ get_status()

std::string dunedaq::timing::I2CSFPSlave::get_status ( bool print_out = false) const

Get SFP status.

Definition at line 327 of file I2CSFPNode.cpp.

328{
330
331 std::stringstream status;
332 std::vector<std::pair<std::string, std::string>> sfp_info;
333
334 // Vendor name
335 sfp_info.push_back(std::make_pair("Vendor", read_vendor_name()));
336
337 // Vendor part number
338 sfp_info.push_back(std::make_pair("Part number", read_vendor_part_number()));
339
340 // Serial number
341 sfp_info.push_back(std::make_pair("Serial number", read_serial_number()));
342
343 // Does the SFP support DDM
344 if (!read_ddm_support_bit()) {
345 TLOG() << "DDM not available for SFP on I2C bus: " << get_master_id();
346 status << format_reg_table(sfp_info, "SFP status", { "", "" });
347 if (print_out)
348 TLOG() << status.str();
349 return status.str();
350 } else {
352 TLOG() << "SFP DDM I2C address swap not supported. SFP on I2C bus: " << get_master_id();
353 status << format_reg_table(sfp_info, "SFP status", { "", "" });
354 if (print_out)
355 TLOG() << status.str();
356 return status.str();
357 }
358 }
359
360 std::stringstream temperature_stream;
361 temperature_stream << std::dec << std::fixed << std::setprecision(2) << read_temperature() << " C";
362 sfp_info.push_back(std::make_pair("Temperature", temperature_stream.str()));
363
364 std::stringstream voltage_stream;
365 voltage_stream << std::dec << std::fixed << std::setprecision(2) << read_voltage() << " V";
366 sfp_info.push_back(std::make_pair("Supply voltage", voltage_stream.str()));
367
368 std::stringstream rx_power_stream;
369 rx_power_stream << std::dec << std::fixed << std::setprecision(2) << read_rx_ower() << " uW";
370 sfp_info.push_back(std::make_pair("Rx power", rx_power_stream.str()));
371
372 std::stringstream tx_power_stream;
373 tx_power_stream << std::dec << std::fixed << std::setprecision(2) << read_tx_power() << " uW";
374 sfp_info.push_back(std::make_pair("Tx power", tx_power_stream.str()));
375
376 std::stringstream current_stream;
377 current_stream << std::dec << std::fixed << std::setprecision(2) << read_current() << " uA";
378 sfp_info.push_back(std::make_pair("Tx current", current_stream.str()));
379
381 // sfp_info.push_back(std::make_pair("Soft Tx disbale supported", "True"));
382 sfp_info.push_back(std::make_pair("Tx disable bit", std::to_string(read_soft_tx_control_state())));
383 } else {
384 sfp_info.push_back(std::make_pair("Soft Tx disbale supported", "False"));
385 }
386
387 sfp_info.push_back(std::make_pair("Tx disable pin", std::to_string(read_tx_disable_pin_state())));
388
389 status << format_reg_table(sfp_info, "SFP status", { "", "" });
390 if (print_out)
391 TLOG() << status.str();
392 return status.str();
393}
std::string read_serial_number() const
Read the SFP serial number.
bool read_tx_disable_pin_state() const
Read the state of the tx disable control pin.
void sfp_reachable() const
Check if SFP responds.
std::string read_vendor_part_number() const
Read the vendor name.
double read_rx_ower() const
Read the raw SFP temperature.
double read_temperature() const
Read the calibrated SFP temperature.
bool read_soft_tx_control_support_bit() const
Find out if SFP supports soft tx laser disable.
std::string read_vendor_name() const
Read the vendor name.
double read_tx_power() const
Read the calibrated SFP tx power.
bool read_soft_tx_control_state() const
Read the value of the soft tx disable control bit.
double read_voltage() const
Read the calibrated SFP voltage.
double read_current() const
Read the calibrated SFP current.
#define TLOG(...)
Definition macro.hpp:22
std::string format_reg_table(T data, std::string title, std::vector< std::string > headers)
Format reg-value table.
Definition toolbox.hxx:166

◆ read_calibration_parameter_pair()

std::pair< double, double > dunedaq::timing::I2CSFPSlave::read_calibration_parameter_pair ( uint32_t calib_parameter_id) const

Read the raw SFP temperature.

Definition at line 57 of file I2CSFPNode.cpp.

58{
59
61
62 auto parameter_array = this->read_i2cArray(0x51, m_calibration_parameter_start_addresses.at(calib_parameter_id), 0x4);
63
64 // slope
65 double slope = parameter_array.at(0) + (parameter_array.at(1) / 256.0);
66
67 uint32_t offset_raw = (parameter_array.at(2) & 0x7f) << 8 | parameter_array.at(3); // NOLINT(build/unsigned)
68
69 // eighth bit corresponds to sign
70 double offset = parameter_array.at(2) & (1UL << 7) ? offset_raw - 0x8000 : offset_raw;
71
72 return std::make_pair(slope, offset);
73}
void ddm_available() const
Check if DDM is supported.
std::vector< uint8_t > read_i2cArray(uint32_t i2c_device_address, uint32_t i2c_reg_address, uint32_t number_of_words) const
Definition I2CSlave.cpp:81
double offset

◆ read_current()

double dunedaq::timing::I2CSFPSlave::read_current ( ) const

Read the calibrated SFP current.

Definition at line 190 of file I2CSFPNode.cpp.

191{
192 auto current_raw = this->read_current_raw();
193 auto temp_calib_pair = read_calibration_parameter_pair(0x0);
194 return ((current_raw * temp_calib_pair.first) + temp_calib_pair.second) * 0.002;
195}
double read_current_raw() const
Read the raw SFP current.
std::pair< double, double > read_calibration_parameter_pair(uint32_t calib_parameter_id) const
Read the raw SFP temperature.

◆ read_current_raw()

double dunedaq::timing::I2CSFPSlave::read_current_raw ( ) const

Read the raw SFP current.

Definition at line 180 of file I2CSFPNode.cpp.

181{
183 auto current_array = this->read_i2cArray(0x51, 0x64, 0x2);
184 return (current_array.at(0) << 8) | current_array.at(1);
185}

◆ read_ddm_support_bit()

bool dunedaq::timing::I2CSFPSlave::read_ddm_support_bit ( ) const

Find out if SFP supports DDM.

Definition at line 245 of file I2CSFPNode.cpp.

246{
248
249 // Bit 6 of reg 5C tells us whether the SFP supports digital diagnostic monitoring (DDM)
250 auto ddm_info_byte = this->read_i2c(0x5C);
251 return ddm_info_byte & 0x40;
252}
uint8_t read_i2c(uint32_t i2c_device_address, uint32_t i2c_reg_address) const
comodity functions
Definition I2CSlave.cpp:46

◆ read_i2c_reg_addressSwapBit()

bool dunedaq::timing::I2CSFPSlave::read_i2c_reg_addressSwapBit ( ) const

Read whether the SFP has seperate I2C addresses, or if a special I2C address swap is required. True = address swap required.

Definition at line 291 of file I2CSFPNode.cpp.

292{
294
295 auto ddm_info_byte = this->read_i2c(0x5C);
296 // Bit 2 of byte 5C tells us whether special I2C address change operations are needed to access the DDM area
297 return ddm_info_byte & 0x4;
298}

◆ read_rx_ower()

double dunedaq::timing::I2CSFPSlave::read_rx_ower ( ) const

Read the raw SFP temperature.

Definition at line 131 of file I2CSFPNode.cpp.

132{
133 auto rx_power_raw = this->read_rx_power_raw();
134 // rx power calib constants, 5 4-byte parameters, IEEE 754 float encoding
135 std::vector<uint32_t> rx_param_start_adr = { 0x48, 0x44, 0x40, 0x3C, 0x38 }; // NOLINT(build/unsigned)
136 std::vector<double> rx_parameters;
137 for (auto it = rx_param_start_adr.begin(); it != rx_param_start_adr.end(); ++it) {
138 uint32_t parameter_bits = 0; // NOLINT(build/unsigned)
139 auto parameter_array = this->read_i2cArray(0x51, *it, 0x4);
140
141 for (auto jt = parameter_array.begin(); jt != parameter_array.end(); ++jt)
142 parameter_bits = (parameter_bits << 8) | *jt;
143
144 // convert the 32 bits to a float according IEEE 754
145 double parameter = convert_bits_to_float(parameter_bits);
146 rx_parameters.push_back(parameter);
147 }
148
149 double rx_power_calib = 0;
150 for (uint32_t i = 0; i < rx_parameters.size(); ++i) { // NOLINT(build/unsigned)
151 double parameter = rx_parameters.at(i);
152 rx_power_calib = rx_power_calib + (parameter * pow(rx_power_raw, i));
153 }
154 return rx_power_calib * 0.1;
155}
double read_rx_power_raw() const
Read the raw SFP temperature.
double convert_bits_to_float(uint64_t bits, bool is_double_precision=false)
Definition toolbox.cpp:242

◆ read_rx_power_raw()

double dunedaq::timing::I2CSFPSlave::read_rx_power_raw ( ) const

Read the raw SFP temperature.

Definition at line 121 of file I2CSFPNode.cpp.

122{
124 auto rx_power_array = this->read_i2cArray(0x51, 0x68, 0x2);
125 return (rx_power_array.at(0) << 8) | rx_power_array.at(1);
126}

◆ read_serial_number()

std::string dunedaq::timing::I2CSFPSlave::read_serial_number ( ) const

Read the SFP serial number.

Definition at line 230 of file I2CSFPNode.cpp.

231{
233
234 std::stringstream serial_number;
235 auto serial_number_characters = this->read_i2cArray(0x44, 0x10);
236 for (auto it = serial_number_characters.begin(); it != serial_number_characters.end(); ++it) {
237 serial_number << *it;
238 }
239 return serial_number.str();
240}

◆ read_soft_tx_control_state()

bool dunedaq::timing::I2CSFPSlave::read_soft_tx_control_state ( ) const

Read the value of the soft tx disable control bit.

Definition at line 269 of file I2CSFPNode.cpp.

270{
272 auto opt_status_ctrl_byte = this->read_i2c(0x51, 0x6e);
273 // Bit 6 tells us the state of the soft tx_disble register
274 return opt_status_ctrl_byte & 0x40;
275}

◆ read_soft_tx_control_support_bit()

bool dunedaq::timing::I2CSFPSlave::read_soft_tx_control_support_bit ( ) const

Find out if SFP supports soft tx laser disable.

Definition at line 257 of file I2CSFPNode.cpp.

258{
260
261 // Bit 6 of reg 5d tells us whether the soft tx control is implemented in this sfp
262 auto enhanced_options_byte = this->read_i2c(0x5d);
263 return enhanced_options_byte & 0x40;
264}

◆ read_temperature()

double dunedaq::timing::I2CSFPSlave::read_temperature ( ) const

Read the calibrated SFP temperature.

Definition at line 91 of file I2CSFPNode.cpp.

92{
93 auto temperature_raw = read_temperature_raw();
94 auto temp_calib_pair = read_calibration_parameter_pair(0x2);
95 return temperature_raw * temp_calib_pair.first + temp_calib_pair.second;
96}
double read_temperature_raw() const
Read the raw SFP temperature.

◆ read_temperature_raw()

double dunedaq::timing::I2CSFPSlave::read_temperature_raw ( ) const

Read the raw SFP temperature.

Definition at line 78 of file I2CSFPNode.cpp.

79{
81 auto temperature_array = this->read_i2cArray(0x51, 0x60, 0x2);
82
83 // bit 7 corresponds to temperature sign, 0 for pos, 1 for neg
84 double temperature = temperature_array.at(0) & (1UL << 7) ? (temperature_array.at(0) & 0x7f) - 0xff : temperature_array.at(0);
85 return temperature + (temperature_array.at(1) / 256.0);
86}

◆ read_tx_disable_pin_state()

bool dunedaq::timing::I2CSFPSlave::read_tx_disable_pin_state ( ) const

Read the state of the tx disable control pin.

Definition at line 280 of file I2CSFPNode.cpp.

281{
283 auto opt_status_ctrl_byte = this->read_i2c(0x51, 0x6e);
284 // Bit 7 tells us the state of tx_disble pin
285 return opt_status_ctrl_byte & 0x80;
286}

◆ read_tx_power()

double dunedaq::timing::I2CSFPSlave::read_tx_power ( ) const

Read the calibrated SFP tx power.

Definition at line 170 of file I2CSFPNode.cpp.

171{
172 auto tx_power_raw = this->read_tx_power_raw();
173 auto temp_calib_pair = read_calibration_parameter_pair(0x1);
174 return ((tx_power_raw * temp_calib_pair.first) + temp_calib_pair.second) * 0.1;
175}
double read_tx_power_raw() const
Read the raw SFP tx power.

◆ read_tx_power_raw()

double dunedaq::timing::I2CSFPSlave::read_tx_power_raw ( ) const

Read the raw SFP tx power.

Definition at line 160 of file I2CSFPNode.cpp.

161{
163 auto tx_power_array = this->read_i2cArray(0x51, 0x66, 0x2);
164 return (tx_power_array.at(0) << 8) | tx_power_array.at(1);
165}

◆ read_vendor_name()

std::string dunedaq::timing::I2CSFPSlave::read_vendor_name ( ) const

Read the vendor name.

Definition at line 200 of file I2CSFPNode.cpp.

201{
203
204 std::stringstream vendor_name;
205 auto vendor_name_characters = this->read_i2cArray(0x14, 0x10);
206 for (auto it = vendor_name_characters.begin(); it != vendor_name_characters.end(); ++it) {
207 vendor_name << *it;
208 }
209 return vendor_name.str();
210}

◆ read_vendor_part_number()

std::string dunedaq::timing::I2CSFPSlave::read_vendor_part_number ( ) const

Read the vendor name.

Definition at line 215 of file I2CSFPNode.cpp.

216{
218
219 std::stringstream vendor_pn;
220 auto vendor_pn_characters = this->read_i2cArray(0x28, 0x10);
221 for (auto it = vendor_pn_characters.begin(); it != vendor_pn_characters.end(); ++it) {
222 vendor_pn << *it;
223 }
224 return vendor_pn.str();
225}

◆ read_voltage()

double dunedaq::timing::I2CSFPSlave::read_voltage ( ) const

Read the calibrated SFP voltage.

Definition at line 111 of file I2CSFPNode.cpp.

112{
113 auto voltage_raw = this->read_voltage_raw();
114 auto temp_calib_pair = read_calibration_parameter_pair(0x3);
115 return ((voltage_raw * temp_calib_pair.first) + temp_calib_pair.second) * 1e-4;
116}
double read_voltage_raw() const
Read the raw SFP voltage.

◆ read_voltage_raw()

double dunedaq::timing::I2CSFPSlave::read_voltage_raw ( ) const

Read the raw SFP voltage.

Definition at line 101 of file I2CSFPNode.cpp.

102{
104 auto voltage_array = this->read_i2cArray(0x51, 0x62, 0x2);
105 return (voltage_array.at(0) << 8) | voltage_array.at(1);
106}

◆ sfp_reachable()

void dunedaq::timing::I2CSFPSlave::sfp_reachable ( ) const

Check if SFP responds.

Definition at line 33 of file I2CSFPNode.cpp.

34{
35 if (!this->ping()) {
36 throw SFPUnreachable(ERS_HERE, get_master_id());
37 }
38}

◆ switch_soft_tx_control_bit()

void dunedaq::timing::I2CSFPSlave::switch_soft_tx_control_bit ( bool turn_on) const

Switch on or off the SFP tx laser via the soft control bit.

Definition at line 303 of file I2CSFPNode.cpp.

304{
306
308 throw SoftTxLaserControlUnsupported(ERS_HERE, get_master_id());
309 }
310
311 // Get optional status/control bits
312 auto opt_status_ctrl_byte = this->read_i2c(0x51, 0x6e);
313
314 uint8_t new_opt_status_ctrl_byte; // NOLINT(build/unsigned)
315 // Bit 6 of byte 0x6e controls the soft tx_disable
316 if (turn_on) {
317 new_opt_status_ctrl_byte = opt_status_ctrl_byte & ~(1UL << 6);
318 } else {
319 new_opt_status_ctrl_byte = opt_status_ctrl_byte | (1UL << 6);
320 }
321 this->write_i2c(0x51, 0x6e, new_opt_status_ctrl_byte);
322}
void write_i2c(uint32_t i2c_device_address, uint32_t i2c_reg_address, uint8_t data, bool send_stop=true) const
Definition I2CSlave.cpp:62

Member Data Documentation

◆ m_calibration_parameter_start_addresses

const std::vector<uint32_t> dunedaq::timing::I2CSFPSlave::m_calibration_parameter_start_addresses
protected

Get and fill SFP hardware data.

Definition at line 190 of file I2CSFPNode.hpp.


The documentation for this class was generated from the following files: