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 0 : getClient().dispatch();
93 :
94 0 : TLOG() << "Reset done";
95 0 : }
96 : //-----------------------------------------------------------------------------
97 :
98 : //-----------------------------------------------------------------------------
99 0 : void FMCIONode::reset_pll() const
100 : {
101 0 : }
102 : //-----------------------------------------------------------------------------
103 :
104 : //-----------------------------------------------------------------------------
105 : std::vector<double>
106 0 : FMCIONode::read_clock_frequencies() const
107 : {
108 0 : std::vector<std::string> clock_names( {"PLL", "CDR"});
109 : // using cdr...?
110 0 : auto no_cdr = getNode("config.no_cdr").read();
111 0 : getClient().dispatch();
112 0 : if (no_cdr)
113 : {
114 0 : clock_names.push_back("SMPL");
115 : }
116 :
117 0 : return getNode<FrequencyCounterNode>("freq").measure_frequencies(clock_names.size());
118 0 : }
119 : //-----------------------------------------------------------------------------
120 :
121 : //-----------------------------------------------------------------------------
122 : std::string
123 0 : FMCIONode::get_clock_frequencies_table(bool print_out) const
124 : {
125 0 : std::vector<std::string> clock_names( {"PLL", "CDR"});
126 : // using cdr...?
127 0 : auto no_cdr = getNode("config.no_cdr").read();
128 0 : getClient().dispatch();
129 0 : if (no_cdr)
130 : {
131 0 : clock_names.push_back("SMPL");
132 : }
133 0 : std::stringstream table;
134 0 : std::vector<double> frequencies = read_clock_frequencies();
135 0 : for (uint8_t i = 0; i < frequencies.size(); ++i) { // NOLINT(build/unsigned)
136 0 : table << clock_names.at(i) << " freq: " << std::setprecision(12) << frequencies.at(i) << std::endl;
137 : }
138 : // TODO add freq validation Stoyan Trilov stoyan.trilov@cern.ch
139 0 : if (print_out)
140 0 : TLOG() << table.str();
141 0 : return table.str();
142 0 : }
143 : //-----------------------------------------------------------------------------
144 :
145 : //-----------------------------------------------------------------------------
146 : bool
147 0 : FMCIONode::clocks_ok() const
148 : {
149 0 : std::stringstream status;
150 :
151 0 : auto states = read_sub_nodes(getNode("csr.stat"));
152 : //bool pll_ok = states.find("pll_ok")->second.value();
153 0 : bool mmcm_ok = states.find("mmcm_ok")->second.value();
154 :
155 0 : TLOG_DEBUG(5) << ", mmcm ok: " << mmcm_ok;
156 :
157 0 : return mmcm_ok; // TODO for EPT, check pll lock
158 0 : }
159 : //-----------------------------------------------------------------------------
160 :
161 : //-----------------------------------------------------------------------------
162 : // void
163 : // FMCIONode::get_info(timinghardwareinfo::TimingFMCMonitorData& mon_data) const
164 : // {
165 :
166 : // auto subnodes = read_sub_nodes(getNode("csr.stat"));
167 :
168 : // mon_data.cdr_lol = subnodes.at("cdr_lol").value();
169 : // mon_data.cdr_los = subnodes.at("cdr_los").value();
170 : // mon_data.mmcm_ok = subnodes.at("mmcm_ok").value();
171 : // mon_data.mmcm_sticky = subnodes.at("mmcm_sticky").value();
172 : // mon_data.sfp_flt = subnodes.at("sfp_flt").value();
173 : // mon_data.sfp_los = subnodes.at("sfp_los").value();
174 : // }
175 : //-----------------------------------------------------------------------------
176 :
177 : //-----------------------------------------------------------------------------
178 : // void
179 : // FMCIONode::get_info(opmonlib::InfoCollector& ci, int level) const
180 : // {
181 : // if (level >= 2) {
182 : // timinghardwareinfo::TimingPLLMonitorData pll_mon_data;
183 : // this->get_pll()->get_info(pll_mon_data);
184 : // ci.add(pll_mon_data);
185 :
186 : // timinghardwareinfo::TimingSFPMonitorData sfp_mon_data;
187 : // auto sfp = this->get_i2c_device<I2CSFPSlave>(m_sfp_i2c_buses.at(0), "SFP_EEProm");
188 : // try {
189 : // sfp->get_info(sfp_mon_data);
190 : // ci.add(sfp_mon_data);
191 : // } catch (timing::SFPUnreachable& e) {
192 : // // It is valid that an SFP may not be installed, currently no good way of knowing whether they it should be
193 : // TLOG_DEBUG(2) << "Failed to communicate with SFP on i2c bus" << m_sfp_i2c_buses.at(0);
194 : // }
195 : // }
196 : // if (level >= 1) {
197 : // timinghardwareinfo::TimingFMCMonitorData mon_data;
198 : // this->get_info(mon_data);
199 : // ci.add(mon_data);
200 : // }
201 : // }
202 : //-----------------------------------------------------------------------------
203 :
204 : //-----------------------------------------------------------------------------
205 : void
206 0 : FMCIONode::switch_sfp_tx(uint32_t sfp_id, bool turn_on) const // NOLINT(build/unsigned)
207 : {
208 0 : validate_sfp_id(sfp_id);
209 :
210 0 : getNode("csr.ctrl.sfp_tx_dis").write(!turn_on);
211 0 : getClient().dispatch();
212 0 : }
213 : //-----------------------------------------------------------------------------
214 :
215 : //-----------------------------------------------------------------------------
216 : void
217 0 : FMCIONode::validate_sfp_id(uint32_t sfp_id) const
218 : { // NOLINT(build/unsigned)
219 : // on this board we have 3 upstream SFPs
220 0 : if (sfp_id != 0)
221 : {
222 0 : throw InvalidSFPId(ERS_HERE, format_reg_value(sfp_id));
223 : }
224 0 : }
225 : //-----------------------------------------------------------------------------
226 : } // namespace timing
227 : } // namespace dunedaq
|