Line data Source code
1 : /**
2 : * @file TLUIONode.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/TLUIONode.hpp"
10 :
11 : #include <string>
12 :
13 : namespace dunedaq {
14 : namespace timing {
15 :
16 0 : UHAL_REGISTER_DERIVED_NODE(TLUIONode)
17 :
18 : //-----------------------------------------------------------------------------
19 0 : TLUIONode::TLUIONode(const uhal::Node& node)
20 : : IONode(node, "i2c", "i2c", "SI5345", { "PLL" }, {})
21 0 : , m_dac_devices({ "DAC1", "DAC2" })
22 0 : {}
23 : //-----------------------------------------------------------------------------
24 :
25 : //-----------------------------------------------------------------------------
26 0 : TLUIONode::~TLUIONode() {}
27 : //-----------------------------------------------------------------------------
28 :
29 : //-----------------------------------------------------------------------------
30 : std::string
31 0 : TLUIONode::get_uid_address_parameter_name() const
32 : {
33 0 : return "UID_PROM";
34 : }
35 : //-----------------------------------------------------------------------------
36 :
37 : //-----------------------------------------------------------------------------
38 : std::string
39 0 : TLUIONode::get_status(bool print_out) const
40 : {
41 0 : auto subnodes = read_sub_nodes(getNode("csr.stat"));
42 0 : std::stringstream status;
43 0 : status << format_reg_table(subnodes, "TLU IO state");
44 :
45 0 : if (print_out)
46 0 : TLOG() << status.str();
47 0 : return status.str();
48 0 : }
49 : //-----------------------------------------------------------------------------
50 :
51 : //-----------------------------------------------------------------------------
52 : void
53 0 : TLUIONode::reset(const std::string& clock_config_file) const
54 : {
55 : // Soft reset
56 0 : write_soft_reset_register();
57 :
58 0 : millisleep(1000);
59 :
60 : // Reset PLL and I2C
61 0 : getNode("csr.ctrl.pll_rst").write(0x1);
62 0 : getNode("csr.ctrl.pll_rst").write(0x0);
63 :
64 0 : getNode("csr.ctrl.rst_i2c").write(0x1);
65 0 : getNode("csr.ctrl.rst_i2c").write(0x0);
66 :
67 0 : getClient().dispatch();
68 :
69 : // enclustra i2c switch stuff
70 0 : try {
71 0 : getNode<I2CMasterNode>(m_uid_i2c_bus).get_slave("AX3_Switch").write_i2c(0x01, 0x7f);
72 0 : } catch (const std::exception& e) {
73 0 : ers::warning(EnclustraSwitchFailure(ERS_HERE, e));
74 0 : }
75 :
76 : // Upload config file to PLL
77 0 : configure_pll(clock_config_file);
78 :
79 : // Tweak the PLL swing
80 0 : auto si_chip = get_pll();
81 0 : si_chip->write_i2cArray(0x113, { 0x9, 0x33 });
82 :
83 : // Reset mmcm
84 0 : getNode("csr.ctrl.rst").write(0x1);
85 0 : getNode("csr.ctrl.rst").write(0x0);
86 0 : getClient().dispatch();
87 :
88 : // configure tlu io expanders
89 0 : auto ic_6 = get_i2c_device<I2CExpanderSlave>(m_uid_i2c_bus, "Expander1");
90 0 : auto ic_7 = get_i2c_device<I2CExpanderSlave>(m_uid_i2c_bus, "Expander2");
91 :
92 : // Bank 0
93 0 : ic_6->set_inversion(0, 0x00);
94 0 : ic_6->set_io(0, 0x00);
95 0 : ic_6->set_outputs(0, 0x00);
96 :
97 : // Bank 1
98 0 : ic_6->set_inversion(1, 0x00);
99 0 : ic_6->set_io(1, 0x00);
100 0 : ic_6->set_outputs(1, 0x88);
101 :
102 : // Bank 0
103 0 : ic_7->set_inversion(0, 0x00);
104 0 : ic_7->set_io(0, 0x00);
105 0 : ic_7->set_outputs(0, 0xf0);
106 :
107 : // Bank 1
108 0 : ic_7->set_inversion(1, 0x00);
109 0 : ic_7->set_io(1, 0x00);
110 0 : ic_7->set_outputs(1, 0xf0);
111 :
112 : // BI signals are NIM
113 0 : uint32_t bi_signal_threshold = 0x589D; // NOLINT(build/unsigned)
114 :
115 0 : configure_dac(0, bi_signal_threshold);
116 0 : configure_dac(1, bi_signal_threshold);
117 :
118 0 : TLOG_DEBUG(0) << "DAC1 and DAC2 set to " << std::hex << bi_signal_threshold;
119 :
120 0 : TLOG() << "Reset done";
121 0 : }
122 : //-----------------------------------------------------------------------------
123 :
124 : //-----------------------------------------------------------------------------
125 0 : void TLUIONode::reset_pll() const
126 : {
127 0 : }
128 : //-----------------------------------------------------------------------------
129 :
130 : //-----------------------------------------------------------------------------
131 : void
132 0 : TLUIONode::configure_dac(uint32_t dac_id, uint32_t dac_value, bool internal_ref) const // NOLINT(build/unsigned)
133 : {
134 0 : std::string dac_device;
135 0 : try {
136 0 : dac_device = m_dac_devices.at(dac_id);
137 0 : } catch (const std::out_of_range& e) {
138 0 : throw InvalidDACId(ERS_HERE, format_reg_value(dac_id));
139 0 : }
140 0 : auto dac = get_i2c_device<DACSlave>(m_uid_i2c_bus, dac_device);
141 0 : dac->set_interal_ref(internal_ref);
142 0 : dac->set_dac(7, dac_value);
143 0 : }
144 : //-----------------------------------------------------------------------------
145 :
146 : //-----------------------------------------------------------------------------
147 : std::string
148 0 : TLUIONode::get_sfp_status(uint32_t /*sfp_id*/, bool /*print_out*/) const // NOLINT(build/unsigned)
149 : {
150 0 : TLOG() << "TLU does not support SFP I2C";
151 0 : return "";
152 : }
153 : //-----------------------------------------------------------------------------
154 :
155 : //-----------------------------------------------------------------------------
156 : bool
157 0 : TLUIONode::clocks_ok() const
158 : {
159 0 : std::stringstream status;
160 :
161 0 : auto states = read_sub_nodes(getNode("csr.stat"));
162 : //bool pll_ok = states.find("pll_ok")->second.value();
163 0 : bool mmcm_ok = states.find("mmcm_ok")->second.value();
164 :
165 0 : TLOG_DEBUG(5) << ", mmcm ok: " << mmcm_ok;
166 :
167 0 : return mmcm_ok; // TODO for check pll lock when appropiate
168 0 : }
169 : //-----------------------------------------------------------------------------
170 :
171 : //-----------------------------------------------------------------------------
172 : void
173 0 : TLUIONode::switch_sfp_soft_tx_control_bit(uint32_t /*sfp_id*/, bool /*turn_on*/) const // NOLINT(build/unsigned)
174 : {
175 0 : TLOG() << "TLU does not support SFP I2C";
176 0 : }
177 : //-----------------------------------------------------------------------------
178 :
179 : //-----------------------------------------------------------------------------
180 : void
181 0 : TLUIONode::switch_sfp_tx(uint32_t sfp_id, bool turn_on) const // NOLINT(build/unsigned)
182 : {
183 0 : validate_sfp_id(sfp_id);
184 :
185 0 : getNode("csr.ctrl.sfp_tx_dis").write(turn_on);
186 0 : getClient().dispatch();
187 0 : }
188 : //-----------------------------------------------------------------------------
189 :
190 : //-----------------------------------------------------------------------------
191 : void
192 0 : TLUIONode::validate_sfp_id(uint32_t sfp_id) const
193 : { // NOLINT(build/unsigned)
194 : // on this board we have 3 upstream SFPs
195 0 : if (sfp_id != 0)
196 : {
197 0 : throw InvalidSFPId(ERS_HERE, format_reg_value(sfp_id));
198 : }
199 0 : }
200 : //-----------------------------------------------------------------------------
201 :
202 : //-----------------------------------------------------------------------------
203 : // void
204 : // TLUIONode::get_info(timinghardwareinfo::TimingTLUMonitorData& mon_data) const
205 : // {
206 :
207 : // auto subnodes = read_sub_nodes(getNode("csr.stat"));
208 :
209 : // mon_data.cdr_lol = subnodes.at("cdr_lol");
210 : // mon_data.cdr_los = subnodes.at("cdr_los");
211 : // mon_data.mmcm_ok = subnodes.at("mmcm_ok");
212 : // mon_data.mmcm_sticky = subnodes.at("mmcm_sticky");
213 : // mon_data.pll_ok = subnodes.at("pll_ok");
214 : // mon_data.pll_sticky = subnodes.at("pll_sticky");
215 : // mon_data.sfp_flt = subnodes.at("sfp_fault");
216 : // mon_data.sfp_los = subnodes.at("sfp_los");
217 : // }
218 : // //-----------------------------------------------------------------------------
219 :
220 : // //-----------------------------------------------------------------------------
221 : // void
222 : // TLUIONode::get_info(opmonlib::InfoCollector& ci, int level) const
223 : // {
224 :
225 : // if (level >= 2) {
226 : // timinghardwareinfo::TimingPLLMonitorData pll_mon_data;
227 : // this->get_pll()->get_info(pll_mon_data);
228 : // ci.add(pll_mon_data);
229 : // }
230 : // if (level >= 1) {
231 : // timinghardwareinfo::TimingTLUMonitorData mon_data;
232 : // this->get_info(mon_data);
233 : // ci.add(mon_data);
234 : // }
235 : // }
236 : //-----------------------------------------------------------------------------
237 :
238 : } // namespace timing
239 : } // namespace dunedaq
|