DUNE-DAQ
DUNE Trigger and Data Acquisition software
Loading...
Searching...
No Matches
MIBIONode.cpp
Go to the documentation of this file.
1
10
11#include <string>
12#include <math.h>
13
14namespace dunedaq {
15namespace timing {
16
17UHAL_REGISTER_DERIVED_NODE(MIBIONode)
18
19//-----------------------------------------------------------------------------
20MIBIONode::MIBIONode(const uhal::Node& node)
21 : IONode(node, "i2c", "i2c", { "PLL" }, { "PLL", "CDR 0", "CDR 1" }, { "i2c" })
22{
23}
24//-----------------------------------------------------------------------------
25
26//-----------------------------------------------------------------------------
28//-----------------------------------------------------------------------------
29
30//-----------------------------------------------------------------------------
31std::string
33{
34 return "UID_PROM";
35}
36//-----------------------------------------------------------------------------
37
38//-----------------------------------------------------------------------------
39std::string
40MIBIONode::get_status(bool print_out) const
41{
42 std::stringstream status;
43
44 auto subnodes = read_sub_nodes(getNode("csr.stat"));
45 status << format_reg_table(subnodes, "MIB IO state");
46
47 if (print_out)
48 TLOG() << std::endl << status.str();
49 return status.str();
50}
51//-----------------------------------------------------------------------------
52
53//-----------------------------------------------------------------------------
54void
55MIBIONode::configure_pll(const std::string& clock_config_file) const
56{
57 // enable pll channel (#3) only
58 auto i2c_switch = get_i2c_device<I2C9546SwitchSlave>("i2c", "TCA9546_Switch");
59 i2c_switch->set_channels_states(8);
60 IONode::configure_pll(clock_config_file);
61}
62//-----------------------------------------------------------------------------
63
64//-----------------------------------------------------------------------------
65std::string
66MIBIONode::get_pll_status(bool print_out) const
67{
68 // enable pll channel (#3) only
69 auto i2c_switch = get_i2c_device<I2C9546SwitchSlave>("i2c", "TCA9546_Switch");
70 i2c_switch->set_channels_states(8);
71 return IONode::get_pll_status(print_out);
72}
73//-----------------------------------------------------------------------------
74
75//-----------------------------------------------------------------------------
76void
77MIBIONode::reset(const std::string& clock_config_file) const
78{
80
81 millisleep(1000);
82
83 // Upload config file to PLL
84 configure_pll(clock_config_file);
85
86 // Reset mmcm
87 getNode("csr.ctrl.rst").write(0x1);
88 getNode("csr.ctrl.rst").write(0x0);
89
90 getNode("io_select.csr.ctrl.amc_out").write(0xfff);
91 getNode("io_select.csr.ctrl.amc_in").write(0x0);
92 getNode("io_select.csr.ctrl.usfp_src").write(0x0);
93
94 getClient().dispatch();
95
96 TLOG() << "Reset done";
97}
98//-----------------------------------------------------------------------------
99
100//-----------------------------------------------------------------------------
102{
103}
104//-----------------------------------------------------------------------------
105
106//-----------------------------------------------------------------------------
107bool
109{
110 TLOG() << "clock check needs to be implemented";
111 return false;
112}
113//-----------------------------------------------------------------------------
114
115//-----------------------------------------------------------------------------
116//void
117//MIBIONode::switch_downstream_mux_channel(uint32_t mux_channel) const // NOLINT(build/unsigned)
118//{
119// validate_amc_slot(mux_channel);
120// uint16_t amc_in_bit = 0x1 << (mux_channel-1);
121// getNode("io_select.csr.ctrl.amc_in").write(amc_in_bit);
122//
123// TLOG_DEBUG(3) << " MIB downstream AMC (in) " << mux_channel << " enabled";
124// getClient().dispatch();
125//}
126//-----------------------------------------------------------------------------
127
128//-----------------------------------------------------------------------------
129//uint32_t // NOLINT(build/unsigned)
130//MIBIONode::read_active_downstream_mux_channel() const
131//{
132// auto active_mux_channel_bits = getNode("io_select.csr.ctrl.amc_in").read();
133// getClient().dispatch();
134// double mux = log2(active_mux_channel_bits.value());
135// return mux+1;
136//}
137//-----------------------------------------------------------------------------
138
139//-----------------------------------------------------------------------------
140//void
141//MIBIONode::switch_upstream_mux_channel(uint32_t mux_channel) const // NOLINT(build/unsigned)
142//{
143// getNode("io_select.csr.ctrl.usfp_src").write(mux_channel);
144// TLOG_DEBUG(3) << " MIB upstream SFP (in) " << mux_channel << " enabled";
145// // TODO what about clock config?
146// getClient().dispatch();
147//}
148//-----------------------------------------------------------------------------
149
150//-----------------------------------------------------------------------------
151//uint32_t // NOLINT(build/unsigned)
152//MIBIONode::read_active_upstream_mux_channel() const
153//{
154// auto active_sfp_mux_channel = getNode("io_select.csr.ctrl.usfp_src").read();
155// getClient().dispatch();
156// return active_sfp_mux_channel.value();
157//}
158//-----------------------------------------------------------------------------
159
160//-----------------------------------------------------------------------------
161std::string
162MIBIONode::get_sfp_status(uint32_t sfp_id, bool print_out) const { // NOLINT(build/unsigned)
163 std::stringstream status;
164
165 validate_sfp_id(sfp_id);
166
167 // enable i2c path for sfp
168 auto i2c_switch = get_i2c_device<I2C9546SwitchSlave>("i2c", "TCA9546_Switch");
169 i2c_switch->set_channels_states(1UL << sfp_id);
170
171 auto sfp = get_i2c_device<I2CSFPSlave>(m_sfp_i2c_buses.at(0), "SFP_EEProm");
172
173 status << "SFP " << sfp_id << ":" << std::endl;
174
175 try
176 {
177 status << sfp->get_status();
178 }
179 catch(...)
180 {
181 i2c_switch->set_channels_states(8);
182 throw;
183 }
184
185 i2c_switch->set_channels_states(8);
186
187 if (print_out)
188 TLOG() << status.str();
189
190 return status.str();
191}
192//-----------------------------------------------------------------------------
193
194//-----------------------------------------------------------------------------
195void
196MIBIONode::switch_sfp_soft_tx_control_bit(uint32_t sfp_id, bool turn_on) const { // NOLINT(build/unsigned)
197 validate_sfp_id(sfp_id);
198
199 auto i2c_switch = get_i2c_device<I2C9546SwitchSlave>("i2c", "TCA9546_Switch");
200 i2c_switch->set_channels_states(1UL << sfp_id);
201 auto sfp = get_i2c_device<I2CSFPSlave>(m_sfp_i2c_buses.at(0), "SFP_EEProm");
202 sfp->switch_soft_tx_control_bit(turn_on);
203 i2c_switch->set_channels_states(8);
204}
205//-----------------------------------------------------------------------------
206
207//-----------------------------------------------------------------------------
208// void
209// MIBIONode::get_info(timinghardwareinfo::TimingMIBMonitorData& mon_data) const
210// {
211
212// auto subnodes = read_sub_nodes(getNode("csr.stat"));
213
214// mon_data.cdr_0_lol = subnodes.at("cdr_lol").value() & 0x1;
215// mon_data.cdr_1_lol = subnodes.at("cdr_lol").value() & 0x2;
216
217// mon_data.cdr_0_los = subnodes.at("cdr_los").value() & 0x1;
218// mon_data.cdr_1_los = subnodes.at("cdr_los").value() & 0x2;
219
220// mon_data.mmcm_ok = subnodes.at("mmcm_ok").value();
221// mon_data.mmcm_sticky = subnodes.at("mmcm_sticky").value();
222
223// mon_data.sfp_0_flt = subnodes.at("sfp_flt").value() & 0x1;
224// mon_data.sfp_1_flt = subnodes.at("sfp_flt").value() & 0x2;
225
226// mon_data.sfp_0_los = subnodes.at("sfp_los").value() & 0x1;
227// mon_data.sfp_1_los = subnodes.at("sfp_los").value() & 0x2;
228
229// // TODO 3rd SFP?
230// }
231// //-----------------------------------------------------------------------------
232
233// //-----------------------------------------------------------------------------
234// void
235// MIBIONode::get_info(opmonlib::InfoCollector& ci, int level) const
236// {
237// auto i2c_switch = get_i2c_device<I2C9546SwitchSlave>("i2c", "TCA9546_Switch");
238
239// if (level >= 2) {
240// i2c_switch->set_channels_states(8);
241
242// timinghardwareinfo::TimingPLLMonitorData pll_mon_data;
243// get_pll()->get_info(pll_mon_data);
244// ci.add(pll_mon_data);
245
246// for (uint i=0; i < 3; ++i)
247// {
248// opmonlib::InfoCollector sfp_ic;
249
250// // enable i2c path for sfp
251// i2c_switch->set_channels_states(1UL << i);
252
253// auto sfp = this->get_i2c_device<I2CSFPSlave>(m_sfp_i2c_buses.at(0), "SFP_EEProm");
254
255// try
256// {
257// sfp->get_info(sfp_ic, level);
258// }
259// catch (timing::SFPUnreachable& e)
260// {
261// // It is valid that an SFP may not be installed, currently no good way of knowing whether they it should be
262// TLOG_DEBUG(2) << "Failed to communicate with SFP " << i << " on I2C switch channel " << (1UL << i) << " on i2c bus" << m_sfp_i2c_buses.at(0);
263// continue;
264// }
265// ci.add("sfp_"+std::to_string(i),sfp_ic);
266// }
267// i2c_switch->set_channels_states(8);
268// }
269// if (level >= 1) {
270// timinghardwareinfo::TimingMIBMonitorData mon_data;
271// this->get_info(mon_data);
272// ci.add(mon_data);
273// }
274// }
275//-----------------------------------------------------------------------------
276
277//-----------------------------------------------------------------------------
278void
279MIBIONode::validate_sfp_id(uint32_t sfp_id) const { // NOLINT(build/unsigned)
280 // on this board we have 3 upstream SFPs
281 if (sfp_id > 2) {
282 throw InvalidSFPId(ERS_HERE, format_reg_value(sfp_id));
283 }
284}
285//-----------------------------------------------------------------------------
286
287//-----------------------------------------------------------------------------
288void
289MIBIONode::validate_amc_slot(uint32_t amc_slot) const { // NOLINT(build/unsigned)
290 if (amc_slot < 1 || amc_slot > 12) {
291 throw InvalidAMCSlot(ERS_HERE, format_reg_value(amc_slot, 10));
292 }
293}
294//-----------------------------------------------------------------------------
295} // namespace timing
296} // namespace dunedaq
#define ERS_HERE
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
const std::vector< std::string > m_sfp_i2c_buses
Definition IONode.hpp:214
virtual void configure_pll(const std::string &clock_config_file="") const
Configure clock chip.
Definition IONode.cpp:238
std::unique_ptr< const T > get_i2c_device(const std::string &i2c_bus_name, const std::string &i2c_device_name) const
Get the an I2C chip.
Definition IONode.hxx:6
virtual std::string get_pll_status(bool print_out=false) const
Print status of on-board PLL.
Definition IONode.cpp:279
Class for the timing FMC board.
Definition MIBIONode.hpp:34
void validate_sfp_id(uint32_t sfp_id) const
Fill hardware monitoring structure.
std::string get_uid_address_parameter_name() const override
Get the UID address parameter name.
Definition MIBIONode.cpp:32
void validate_amc_slot(uint32_t amc_slot) const
void switch_sfp_soft_tx_control_bit(uint32_t sfp_id, bool turn_on) const override
control tx laser of on-board SFP softly (I2C command)
std::string get_sfp_status(uint32_t sfp_id, bool print_out=false) const override
Switch the SFP mux channel.
void reset_pll() const override
Reset PLL.
void reset(const std::string &clock_config_file) const override
Reset MIB IO.
Definition MIBIONode.cpp:77
std::string get_status(bool print_out=false) const override
Get status string, optionally print.
Definition MIBIONode.cpp:40
bool clocks_ok() const override
Clocks ready?
void configure_pll(const std::string &clock_config_file="") const override
Configure clock chip.
Definition MIBIONode.cpp:55
std::string get_pll_status(bool print_out=false) const override
Print status of on-board PLL.
Definition MIBIONode.cpp:66
std::map< std::string, uhal::ValWord< uint32_t > > read_sub_nodes(const uhal::Node &node, bool dispatch=true) const
Read subnodes.
#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
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