Line data Source code
1 : /**
2 : * @file FMCIONode.cpp
3 : *
4 : * This is part of the DUNE DAQ Software Suite, copyright 2020.
5 : * Licensing/copyright details are in the COPYING file that you should have
6 : * received with this code.
7 : */
8 :
9 : #include "timing/FMCIONode.hpp"
10 :
11 : #include <string>
12 :
13 : namespace dunedaq {
14 : namespace timing {
15 :
16 0 : UHAL_REGISTER_DERIVED_NODE(FMCIONode)
17 :
18 : //-----------------------------------------------------------------------------
19 0 : FMCIONode::FMCIONode(const uhal::Node& node)
20 0 : : IONode(node, "uid_i2c", "pll_i2c", "i2caddr", { "PLL", "CDR" }, { "sfp_i2c" })
21 : {
22 0 : }
23 : //-----------------------------------------------------------------------------
24 :
25 : //-----------------------------------------------------------------------------
26 0 : FMCIONode::~FMCIONode() {}
27 : //-----------------------------------------------------------------------------
28 :
29 : //-----------------------------------------------------------------------------
30 : std::string
31 0 : FMCIONode::get_uid_address_parameter_name() const
32 : {
33 0 : CarrierType carrier_type = convert_value_to_carrier_type(read_carrier_type());
34 :
35 0 : if (carrier_type == kCarrierNexusVideo || carrier_type == kCarrierAFC) {
36 0 : return "FMC_UID_PROM_NEXUS";
37 : } else {
38 0 : return "FMC_UID_PROM";
39 : }
40 : }
41 : //-----------------------------------------------------------------------------
42 :
43 : //-----------------------------------------------------------------------------
44 : std::string
45 0 : FMCIONode::get_status(bool print_out) const
46 : {
47 0 : std::stringstream status;
48 :
49 0 : auto subnodes = read_sub_nodes(getNode("csr.stat"));
50 0 : status << format_reg_table(subnodes, "FMC IO state");
51 :
52 0 : if (print_out)
53 0 : TLOG() << std::endl << status.str();
54 0 : return status.str();
55 0 : }
56 : //-----------------------------------------------------------------------------
57 :
58 : //-----------------------------------------------------------------------------
59 : void
60 0 : FMCIONode::reset(const std::string& clock_config_file) const
61 : {
62 0 : write_soft_reset_register();
63 :
64 0 : millisleep(1000);
65 :
66 : // Reset PLL
67 0 : getNode("csr.ctrl.pll_rst").write(0x1);
68 0 : getNode("csr.ctrl.pll_rst").write(0x0);
69 0 : getClient().dispatch();
70 :
71 0 : CarrierType carrier_type = convert_value_to_carrier_type(read_carrier_type());
72 :
73 : // enclustra i2c switch stuff
74 0 : if (carrier_type == kCarrierEnclustraA35) {
75 0 : try {
76 0 : getNode<I2CMasterNode>(m_uid_i2c_bus).get_slave("AX3_Switch").write_i2c(0x01, 0x7f);
77 0 : } catch (const std::exception& e) {
78 0 : ers::warning(EnclustraSwitchFailure(ERS_HERE, e));
79 0 : }
80 : }
81 :
82 : // Upload config file to PLL
83 0 : configure_pll(clock_config_file);
84 :
85 : // Reset mmcm
86 0 : getNode("csr.ctrl.rst").write(0x1);
87 0 : getNode("csr.ctrl.rst").write(0x0);
88 0 : getClient().dispatch();
89 :
90 : // Enable sfp tx laser
91 0 : getNode("csr.ctrl.sfp_tx_dis").write(0x0);
92 :
93 : // rx edges
94 0 : uint32_t cdr_rx_edge = 0x0; // NOLINT(build/unsigned)
95 0 : uint32_t sfp_rx_edge = 0x0; // NOLINT(build/unsigned)
96 0 : uint32_t rj45_rx_edge = 0x0; // NOLINT(build/unsigned)
97 :
98 : // tx edges
99 0 : uint32_t sfp_tx_edge = 0x0; // NOLINT(build/unsigned)
100 0 : uint32_t rj45_tx_edge = 0x0; // NOLINT(build/unsigned)
101 :
102 : // rx edges
103 0 : getNode("csr.ctrl.cdr_rx_edge").write(cdr_rx_edge);
104 0 : getNode("csr.ctrl.sfp_rx_edge").write(sfp_rx_edge);
105 0 : getNode("csr.ctrl.rj45_rx_edge").write(rj45_rx_edge);
106 :
107 : // tx edges
108 0 : getNode("csr.ctrl.sfp_tx_edge").write(sfp_tx_edge);
109 0 : getNode("csr.ctrl.rj45_tx_edge").write(rj45_tx_edge);
110 :
111 0 : getClient().dispatch();
112 :
113 0 : TLOG() << "Reset done";
114 0 : }
115 : //-----------------------------------------------------------------------------
116 :
117 : //-----------------------------------------------------------------------------
118 0 : void FMCIONode::reset_pll() const
119 : {
120 0 : }
121 : //-----------------------------------------------------------------------------
122 :
123 : //-----------------------------------------------------------------------------
124 : std::vector<double>
125 0 : FMCIONode::read_clock_frequencies() const
126 : {
127 0 : std::vector<std::string> clock_names( {"PLL", "CDR"});
128 : // using cdr...?
129 0 : auto no_cdr = getNode("config.no_cdr").read();
130 0 : getClient().dispatch();
131 0 : if (no_cdr)
132 : {
133 0 : clock_names.push_back("SMPL");
134 : }
135 :
136 0 : return getNode<FrequencyCounterNode>("freq").measure_frequencies(clock_names.size());
137 0 : }
138 : //-----------------------------------------------------------------------------
139 :
140 : //-----------------------------------------------------------------------------
141 : std::string
142 0 : FMCIONode::get_clock_frequencies_table(bool print_out) const
143 : {
144 0 : std::vector<std::string> clock_names( {"PLL", "CDR"});
145 : // using cdr...?
146 0 : auto no_cdr = getNode("config.no_cdr").read();
147 0 : getClient().dispatch();
148 0 : if (no_cdr)
149 : {
150 0 : clock_names.push_back("SMPL");
151 : }
152 0 : std::stringstream table;
153 0 : std::vector<double> frequencies = read_clock_frequencies();
154 0 : for (uint8_t i = 0; i < frequencies.size(); ++i) { // NOLINT(build/unsigned)
155 0 : 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 0 : if (print_out)
159 0 : TLOG() << table.str();
160 0 : return table.str();
161 0 : }
162 : //-----------------------------------------------------------------------------
163 :
164 : //-----------------------------------------------------------------------------
165 : bool
166 0 : FMCIONode::clocks_ok() const
167 : {
168 0 : std::stringstream status;
169 :
170 0 : auto states = read_sub_nodes(getNode("csr.stat"));
171 : //bool pll_ok = states.find("pll_ok")->second.value();
172 0 : bool mmcm_ok = states.find("mmcm_ok")->second.value();
173 :
174 0 : TLOG_DEBUG(5) << ", mmcm ok: " << mmcm_ok;
175 :
176 0 : return mmcm_ok; // TODO for EPT, check pll lock
177 0 : }
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 : //-----------------------------------------------------------------------------
224 : void
225 0 : FMCIONode::switch_sfp_tx(uint32_t sfp_id, bool turn_on) const // NOLINT(build/unsigned)
226 : {
227 0 : validate_sfp_id(sfp_id);
228 :
229 0 : getNode("csr.ctrl.sfp_tx_dis").write(!turn_on);
230 0 : getClient().dispatch();
231 0 : }
232 : //-----------------------------------------------------------------------------
233 :
234 : //-----------------------------------------------------------------------------
235 : void
236 0 : FMCIONode::validate_sfp_id(uint32_t sfp_id) const
237 : { // NOLINT(build/unsigned)
238 : // on this board we have 3 upstream SFPs
239 0 : if (sfp_id != 0)
240 : {
241 0 : throw InvalidSFPId(ERS_HERE, format_reg_value(sfp_id));
242 : }
243 0 : }
244 : //-----------------------------------------------------------------------------
245 : } // namespace timing
246 : } // namespace dunedaq
|