DUNE-DAQ
DUNE Trigger and Data Acquisition software
Loading...
Searching...
No Matches
FMCIONode.cpp
Go to the documentation of this file.
1
10
11#include <string>
12
13namespace dunedaq {
14namespace timing {
15
16UHAL_REGISTER_DERIVED_NODE(FMCIONode)
17
18//-----------------------------------------------------------------------------
19FMCIONode::FMCIONode(const uhal::Node& node)
20 : IONode(node, "uid_i2c", "pll_i2c", "i2caddr", { "PLL", "CDR" }, { "sfp_i2c" })
21{
22}
23//-----------------------------------------------------------------------------
24
25//-----------------------------------------------------------------------------
27//-----------------------------------------------------------------------------
28
29//-----------------------------------------------------------------------------
30std::string
32{
34
35 if (carrier_type == kCarrierNexusVideo || carrier_type == kCarrierAFC) {
36 return "FMC_UID_PROM_NEXUS";
37 } else {
38 return "FMC_UID_PROM";
39 }
40}
41//-----------------------------------------------------------------------------
42
43//-----------------------------------------------------------------------------
44std::string
45FMCIONode::get_status(bool print_out) const
46{
47 std::stringstream status;
48
49 auto subnodes = read_sub_nodes(getNode("csr.stat"));
50 status << format_reg_table(subnodes, "FMC IO state");
51
52 if (print_out)
53 TLOG() << std::endl << status.str();
54 return status.str();
55}
56//-----------------------------------------------------------------------------
57
58//-----------------------------------------------------------------------------
59void
60FMCIONode::reset(const std::string& clock_config_file) const
61{
63
64 millisleep(1000);
65
66 // Reset PLL
67 getNode("csr.ctrl.pll_rst").write(0x1);
68 getNode("csr.ctrl.pll_rst").write(0x0);
69 getClient().dispatch();
70
72
73 // enclustra i2c switch stuff
74 if (carrier_type == kCarrierEnclustraA35) {
75 try {
76 getNode<I2CMasterNode>(m_uid_i2c_bus).get_slave("AX3_Switch").write_i2c(0x01, 0x7f);
77 } catch (const std::exception& e) {
78 ers::warning(EnclustraSwitchFailure(ERS_HERE, e));
79 }
80 }
81
82 // Upload config file to PLL
83 configure_pll(clock_config_file);
84
85 // Reset mmcm
86 getNode("csr.ctrl.rst").write(0x1);
87 getNode("csr.ctrl.rst").write(0x0);
88 getClient().dispatch();
89
90 // Enable sfp tx laser
91 getNode("csr.ctrl.sfp_tx_dis").write(0x0);
92
93 // rx edges
94 uint32_t cdr_rx_edge = 0x0; // NOLINT(build/unsigned)
95 uint32_t sfp_rx_edge = 0x0; // NOLINT(build/unsigned)
96 uint32_t rj45_rx_edge = 0x0; // NOLINT(build/unsigned)
97
98 // tx edges
99 uint32_t sfp_tx_edge = 0x0; // NOLINT(build/unsigned)
100 uint32_t rj45_tx_edge = 0x0; // NOLINT(build/unsigned)
101
102 // rx edges
103 getNode("csr.ctrl.cdr_rx_edge").write(cdr_rx_edge);
104 getNode("csr.ctrl.sfp_rx_edge").write(sfp_rx_edge);
105 getNode("csr.ctrl.rj45_rx_edge").write(rj45_rx_edge);
106
107 // tx edges
108 getNode("csr.ctrl.sfp_tx_edge").write(sfp_tx_edge);
109 getNode("csr.ctrl.rj45_tx_edge").write(rj45_tx_edge);
110
111 getClient().dispatch();
112
113 TLOG() << "Reset done";
114}
115//-----------------------------------------------------------------------------
116
117//-----------------------------------------------------------------------------
119{
120}
121//-----------------------------------------------------------------------------
122
123//-----------------------------------------------------------------------------
124std::vector<double>
126{
127 std::vector<std::string> clock_names( {"PLL", "CDR"});
128 // using cdr...?
129 auto no_cdr = getNode("config.no_cdr").read();
130 getClient().dispatch();
131 if (no_cdr)
132 {
133 clock_names.push_back("SMPL");
134 }
135
136 return getNode<FrequencyCounterNode>("freq").measure_frequencies(clock_names.size());
137}
138//-----------------------------------------------------------------------------
139
140//-----------------------------------------------------------------------------
141std::string
143{
144 std::vector<std::string> clock_names( {"PLL", "CDR"});
145 // using cdr...?
146 auto no_cdr = getNode("config.no_cdr").read();
147 getClient().dispatch();
148 if (no_cdr)
149 {
150 clock_names.push_back("SMPL");
151 }
152 std::stringstream table;
153 std::vector<double> frequencies = read_clock_frequencies();
154 for (uint8_t i = 0; i < frequencies.size(); ++i) { // NOLINT(build/unsigned)
155 table << clock_names.at(i) << " freq: " << std::setprecision(12) << frequencies.at(i) << std::endl;
156 }
157 // TODO add freq validation Stoyan Trilov stoyan.trilov@cern.ch
158 if (print_out)
159 TLOG() << table.str();
160 return table.str();
161}
162//-----------------------------------------------------------------------------
163
164//-----------------------------------------------------------------------------
165bool
167{
168 std::stringstream status;
169
170 auto states = read_sub_nodes(getNode("csr.stat"));
171 //bool pll_ok = states.find("pll_ok")->second.value();
172 bool mmcm_ok = states.find("mmcm_ok")->second.value();
173
174 TLOG_DEBUG(5) << ", mmcm ok: " << mmcm_ok;
175
176 return mmcm_ok; // TODO for EPT, check pll lock
177}
178//-----------------------------------------------------------------------------
179
180//-----------------------------------------------------------------------------
181// void
182// FMCIONode::get_info(timinghardwareinfo::TimingFMCMonitorData& mon_data) const
183// {
184
185// auto subnodes = read_sub_nodes(getNode("csr.stat"));
186
187// mon_data.cdr_lol = subnodes.at("cdr_lol").value();
188// mon_data.cdr_los = subnodes.at("cdr_los").value();
189// mon_data.mmcm_ok = subnodes.at("mmcm_ok").value();
190// mon_data.mmcm_sticky = subnodes.at("mmcm_sticky").value();
191// mon_data.sfp_flt = subnodes.at("sfp_flt").value();
192// mon_data.sfp_los = subnodes.at("sfp_los").value();
193// }
194//-----------------------------------------------------------------------------
195
196//-----------------------------------------------------------------------------
197// void
198// FMCIONode::get_info(opmonlib::InfoCollector& ci, int level) const
199// {
200// if (level >= 2) {
201// timinghardwareinfo::TimingPLLMonitorData pll_mon_data;
202// this->get_pll()->get_info(pll_mon_data);
203// ci.add(pll_mon_data);
204
205// timinghardwareinfo::TimingSFPMonitorData sfp_mon_data;
206// auto sfp = this->get_i2c_device<I2CSFPSlave>(m_sfp_i2c_buses.at(0), "SFP_EEProm");
207// try {
208// sfp->get_info(sfp_mon_data);
209// ci.add(sfp_mon_data);
210// } catch (timing::SFPUnreachable& e) {
211// // It is valid that an SFP may not be installed, currently no good way of knowing whether they it should be
212// TLOG_DEBUG(2) << "Failed to communicate with SFP on i2c bus" << m_sfp_i2c_buses.at(0);
213// }
214// }
215// if (level >= 1) {
216// timinghardwareinfo::TimingFMCMonitorData mon_data;
217// this->get_info(mon_data);
218// ci.add(mon_data);
219// }
220// }
221//-----------------------------------------------------------------------------
222
223//-----------------------------------------------------------------------------
224void
225FMCIONode::switch_sfp_tx(uint32_t sfp_id, bool turn_on) const // NOLINT(build/unsigned)
226{
227 validate_sfp_id(sfp_id);
228
229 getNode("csr.ctrl.sfp_tx_dis").write(!turn_on);
230 getClient().dispatch();
231}
232//-----------------------------------------------------------------------------
233
234//-----------------------------------------------------------------------------
235void
236FMCIONode::validate_sfp_id(uint32_t sfp_id) const
237{ // NOLINT(build/unsigned)
238 // on this board we have 3 upstream SFPs
239 if (sfp_id != 0)
240 {
241 throw InvalidSFPId(ERS_HERE, format_reg_value(sfp_id));
242 }
243}
244//-----------------------------------------------------------------------------
245} // namespace timing
246} // namespace dunedaq
#define ERS_HERE
Class for the timing FMC board.
Definition FMCIONode.hpp:33
bool clocks_ok() const override
Clocks ready?
std::string get_uid_address_parameter_name() const override
Get the UID address parameter name.
Definition FMCIONode.cpp:31
std::string get_clock_frequencies_table(bool print_out=false) const override
Print frequencies of on-board clocks.
std::string get_status(bool print_out=false) const override
Get status string, optionally print.
Definition FMCIONode.cpp:45
void reset_pll() const override
Reset PLL.
std::vector< double > read_clock_frequencies() const override
Read frequencies of on-board clocks.
void validate_sfp_id(uint32_t sfp_id) const
Fill hardware monitoring structure.
void reset(const std::string &clock_config_file) const override
Reset FMC IO.
Definition FMCIONode.cpp:60
void switch_sfp_tx(uint32_t sfp_id, bool turn_on) const override
control tx laser of on-board SFP
Base class for timing IO nodes.
Definition IONode.hpp:44
virtual void write_soft_reset_register() const
Write soft reset register.
Definition IONode.cpp:287
virtual uint32_t read_carrier_type() const
Read the word identifying the FPFA carrier board.
Definition IONode.cpp:58
const std::string m_uid_i2c_bus
Definition IONode.hpp:210
virtual void configure_pll(const std::string &clock_config_file="") const
Configure clock chip.
Definition IONode.cpp:238
std::map< std::string, uhal::ValWord< uint32_t > > read_sub_nodes(const uhal::Node &node, bool dispatch=true) const
Read subnodes.
#define TLOG_DEBUG(lvl,...)
Definition Logging.hpp:112
#define TLOG(...)
Definition macro.hpp:22
CarrierType convert_value_to_carrier_type(uint32_t darrier_type)
Definition toolbox.cpp:287
std::string format_reg_table(T data, std::string title, std::vector< std::string > headers)
Format reg-value table.
Definition toolbox.hxx:166
std::string format_reg_value(T reg_value, uint32_t base)
Definition toolbox.hxx:117
void millisleep(const double &time_in_milliseconds)
Definition toolbox.cpp:83
The DUNE-DAQ namespace.
Definition DataStore.hpp:57
void warning(const Issue &issue)
Definition ers.hpp:115