DUNE-DAQ
DUNE Trigger and Data Acquisition software
Loading...
Searching...
No Matches
DeviceInterface.cxx
Go to the documentation of this file.
1
8
9// FIXME: This code implementation is a mess, with most parameters hardcoded instead of taking them from the
10// configuration
11#ifndef SSPMODULES_SRC_ANLBOARD_DEVICEINTERFACE_CXX_
12#define SSPMODULES_SRC_ANLBOARD_DEVICEINTERFACE_CXX_
13
14#include "DeviceInterface.hpp"
15#include "RegMap.hpp"
16#include "SSPIssues.hpp"
17#include "anlExceptions.hpp"
18
19#include "boost/asio.hpp"
20
21#include <algorithm>
22#include <ctime>
23#include <memory>
24#include <string>
25#include <utility>
26#include <vector>
27
28enum
29{
34};
35
48
49void
51{
52
53 TLOG_DEBUG(TLVL_FULL_DEBUG) << "SSP Device Interface OpenSlowControl called.";
54 // Ask device manager for a pointer to the specified device
57
58 device = devman.OpenDevice(fDeviceId, true); // slow control only
59
60 if (!device) {
61 TLOG_DEBUG(TLVL_WORK_STEPS) << "Unable to get handle to device; giving up!" << std::endl;
62 throw(ENoSuchDevice());
63 }
64
65 fDevice = device;
66 fSlowControlOnly = true;
67 TLOG_DEBUG(TLVL_ENTER_EXIT_METHODS) << "SSP Device Interface OpenSlowControl completed.";
68}
69
70/*
71void
72dunedaq::sspmodules::DeviceInterface::Initialize(const nlohmann::json& args)
73{
74
75 TLOG_DEBUG(TLVL_ENTER_EXIT_METHODS) << "SSP Device Interface Initialize called.";
76 fState = kInitialized;
77 TLOG_DEBUG(TLVL_ENTER_EXIT_METHODS) << "SSP Device Interface Initailize complete.";
78}
79
80void
81dunedaq::sspmodules::DeviceInterface::Stop()
82{
83 TLOG_DEBUG(TLVL_ENTER_EXIT_METHODS) << "SSP Device Interface Stop called.";
84
85 dunedaq::sspmodules::RegMap& duneReg = dunedaq::sspmodules::RegMap::Get();
86
87 fDevice->DeviceWrite(duneReg.eventDataControl, 0x0013001F);
88 fDevice->DeviceClear(duneReg.master_logic_control, 0x00000101);
89 // Clear the FIFOs
90 fDevice->DeviceWrite(duneReg.fifo_control, 0x08000000);
91 fDevice->DeviceWrite(duneReg.PurgeDDR, 0x00000001);
92 // Reset the links and flags
93 fDevice->DeviceWrite(duneReg.event_data_control, 0x00020001);
94 // Flush RX buffer
95 fDevice->DevicePurgeData();
96 TLOG_DEBUG(TLVL_WORK_STEPS) << "Hardware set to stopped state" << std::endl;
97 fState = kStopped;
98 TLOG_DEBUG(TLVL_ENTER_EXIT_METHODS) << "SSP Device Interface Stop complete.";
99}
100
101
102void
103dunedaq::sspmodules::DeviceInterface::Start()
104{
105
106 TLOG_DEBUG(TLVL_ENTER_EXIT_METHODS) << "SSP Device Interface Start called.";
107
108
109 TLOG_DEBUG(TLVL_WORK_STEPS) << "Device interface starting hardware run..." << std::endl;
110 dunedaq::sspmodules::RegMap& duneReg = dunedaq::sspmodules::RegMap::Get();
111 // This script enables all logic and FIFOs and starts data acquisition in the device
112 // Operations MUST be performed in this order
113
114 // Load window settings, charge injection settings and bias voltage into channels
115 fDevice->DeviceWrite(duneReg.channel_pulsed_control, 0x1);
116 fDevice->DeviceWrite(duneReg.bias_control, 0x1);
117 fDevice->DeviceWriteMask(duneReg.vmon_control, 0x1, 0x1);
118 fDevice->DeviceWriteMask(duneReg.imon_control, 0x1, 0x1);
119 fDevice->DeviceWriteMask(duneReg.qi_dac_control, 0x1, 0x1);
120 fDevice->DeviceWriteMask(duneReg.qi_pulsed, 0x00030000, 0x00030000);
121
122 fDevice->DeviceWrite(duneReg.event_data_control, 0x00000000);
123 // Release the FIFO reset
124 fDevice->DeviceWrite(duneReg.fifo_control, 0x00000000);
125 // Registers in the Zynq FPGA (Comm)
126 // Reset the links and flags (note eventDataControl!=event_data_control)
127 fDevice->DeviceWrite(duneReg.eventDataControl, 0x00000000);
128 // Registers in the Artix FPGA (DSP)
129 // Release master logic reset & enable active channels
130
131 fDevice->DeviceWrite(duneReg.master_logic_control, 0x00000041);
132 fState = kRunning;
133 TLOG_DEBUG(TLVL_ENTER_EXIT_METHODS) << "SSP Device Interface Start complete.";
134}
135
136void
137dunedaq::sspmodules::DeviceInterface::Shutdown()
138{
139 TLOG_DEBUG(TLVL_ENTER_EXIT_METHODS) << "SSP Device Interface Shutdown called.";
140
141 fDevice->Close();
142 TLOG_DEBUG(TLVL_ENTER_EXIT_METHODS) << "SSP Device Interface Shutdown complete.";
143}
144*/
145
146void
147dunedaq::sspmodules::DeviceInterface::SetRegister(unsigned int address, unsigned int value, unsigned int mask)
148{
149
150 if (mask == 0xFFFFFFFF) {
151 fDevice->DeviceWrite(address, value);
152 } else {
153 fDevice->DeviceWriteMask(address, mask, value);
154 }
155}
156
157void
158dunedaq::sspmodules::DeviceInterface::SetRegisterArray(unsigned int address, std::vector<unsigned int> value)
159{
160
161 this->SetRegisterArray(address, &(value[0]), value.size());
162}
163
164void
165dunedaq::sspmodules::DeviceInterface::SetRegisterArray(unsigned int address, unsigned int* value, unsigned int size)
166{
167
168 fDevice->DeviceArrayWrite(address, size, value);
169}
170
171void
172dunedaq::sspmodules::DeviceInterface::ReadRegister(unsigned int address, unsigned int& value, unsigned int mask)
173{
174
175 if (mask == 0xFFFFFFFF) {
176 fDevice->DeviceRead(address, &value);
177 } else {
178 fDevice->DeviceReadMask(address, mask, &value);
179 }
180}
181
182void
184 std::vector<unsigned int>& value,
185 unsigned int size)
186{
187
188 value.resize(size);
189 this->ReadRegisterArray(address, &(value[0]), size);
190}
191
192void
193dunedaq::sspmodules::DeviceInterface::ReadRegisterArray(unsigned int address, unsigned int* value, unsigned int size)
194{
195
196 fDevice->DeviceArrayRead(address, size, value);
197}
198void
200{
202
203 this->SetRegister(reg, value, reg.WriteMask());
204}
205
206void
207dunedaq::sspmodules::DeviceInterface::SetRegisterElementByName(std::string name, unsigned int index, unsigned int value)
208{
210
211 this->SetRegister(reg, value, reg.WriteMask());
212}
213
214void
216{
217 unsigned int regSize = (dunedaq::sspmodules::RegMap::Get())[name].Size();
218 std::vector<unsigned int> arrayContents(regSize, value);
219
220 this->SetRegisterArrayByName(name, arrayContents);
221}
222
223void
224dunedaq::sspmodules::DeviceInterface::SetRegisterArrayByName(std::string name, std::vector<unsigned int> values)
225{
227 if (reg.Size() != values.size()) {
228 TLOG_DEBUG(TLVL_WORK_STEPS) << "Request to set named register array " << name << ", length " << reg.Size()
229 << "with vector of " << values.size() << " values!" << std::endl;
230 throw(std::invalid_argument(""));
231 }
232 this->SetRegisterArray(reg[0], values);
233}
234
235void
237{
239
240 this->ReadRegister(reg, value, reg.ReadMask());
241}
242
243void
245 unsigned int index,
246 unsigned int& value)
247{
249
250 this->ReadRegister(reg, value, reg.ReadMask());
251}
252
253void
254dunedaq::sspmodules::DeviceInterface::ReadRegisterArrayByName(std::string name, std::vector<unsigned int>& values)
255{
257 this->ReadRegisterArray(reg[0], values, reg.Size());
258}
259
260void
262{
263
264 TLOG_DEBUG(TLVL_ENTER_EXIT_METHODS) << "SSP LED Calib Device Interface Configure called.";
265
266 std::stringstream ss;
267 fDeviceId = inet_network(conf->get_board_ip().c_str()); // inet_network("10.73.137.56");
268 TLOG() << "DeviceInterface: trying to connect to " << boost::asio::ip::address_v4(fDeviceId).to_string();
269 // Ask device manager for a pointer to the specified device
271 dunedaq::sspmodules::Device* device = 0;
272
273 device = devman.OpenDevice(fDeviceId);
274
275 if (!device) {
276 TLOG_DEBUG(TLVL_WORK_STEPS) << "Unable to get handle to device; giving up!" << std::endl;
277 throw(ENoSuchDevice());
278 }
279
280 fDevice = device;
281
282 // Reset timing endpoint
284
285 unsigned int pdts_status = 0;
286 unsigned int pdts_control = 0;
287 unsigned int dsp_clock_control = 0;
288
289 fDevice->DeviceRead(duneReg.pdts_status, &pdts_status);
290 TLOG() << "The pdts_status read back as 0x" << std::hex << pdts_status << std::dec << std::endl;
291 fDevice->DeviceRead(duneReg.pdts_control, &pdts_control);
292 TLOG() << "The pdts_control read back as 0x" << std::hex << pdts_control << std::dec << std::endl;
293 fDevice->DeviceRead(duneReg.dsp_clock_control, &dsp_clock_control);
294 TLOG() << "The dsp_clock_control read back as 0x" << std::hex << dsp_clock_control << std::dec << std::endl;
295
296 unsigned int presentTimingAddress = (pdts_control >> 16) & 0xFF;
297 unsigned int presentTimingPartition = pdts_control & 0x3;
298
299 TLOG() << "SSP HW presently on partition " << presentTimingPartition << ", address 0x" << std::hex
300 << presentTimingAddress << " with endpoint status 0x" << (pdts_status & 0xF) << " and dsp_clock_control at 0x"
301 << dsp_clock_control << std::dec << std::endl;
302
303 // if ((pdts_status & 0xF) >= 0x6 && (pdts_status & 0xF) <= 0x8 && presentTimingAddress == fTimingAddress &&
304 // presentTimingPartition == fPartitionNumber && dsp_clock_control == 0x31) {
305 if ((pdts_status & 0xF) >= 0x6 && (pdts_status & 0xF) <= 0x8 && presentTimingAddress == fTimingAddress &&
306 presentTimingPartition == fPartitionNumber &&
307 (dsp_clock_control & 0xF) ==
308 0x1) { // NOTE THAT THIS WAS CHANGED SO THAT IF THE DSP_CLOCK_STATUS LOWEST BIT IS STILL HIGH 0x1
309 // THEN THE CLOCK ALREADY IS ASSUMED TO BE GOOD, AND WE DON'T TRY TO RESYNCH WITH THE PDTS
310
311 TLOG() << "Clock already looks ok... skipping endpoint reset." << std::endl;
312 } else {
313
314 TLOG() << "Syncing SSP LED Calib to PDTS (partition " << fPartitionNumber << ", endpoint address 0x" << std::hex
315 << fTimingAddress << std::dec << ")" << std::endl;
316
317 unsigned int nTries = 0;
318
319 while (nTries < 5) {
320 fDevice->DeviceWrite(duneReg.dsp_clock_control, 0x30);
321 TLOG() << "The dsp_clock_control was set to 0x" << std::hex << 0x30 << std::dec
322 << std::endl; // setting the lowest bit to 0 sets the DSP clock to internal.
323 fDevice->DeviceWrite(duneReg.pdts_control, 0x80000000 + fPartitionNumber + fTimingAddress * 0x10000);
324 TLOG() << "The pdts_control value was set to 0x" << std::hex
325 << 0x80000000 + fPartitionNumber + fTimingAddress * 0x10000 << std::dec
326 << std::endl; // setting the highest bit (0x80000000) to 1 puts the SSP in Reset mode for the PDTS.
327
328 fDevice->DeviceRead(duneReg.pdts_status, &pdts_status);
329 TLOG() << "The pdts_status read back as 0x" << std::hex << pdts_status << std::dec << std::endl;
330 fDevice->DeviceRead(duneReg.pdts_control, &pdts_control);
331 TLOG() << "The pdts_control read back as 0x" << std::hex << pdts_control << std::dec << std::endl;
332 fDevice->DeviceRead(duneReg.dsp_clock_control, &dsp_clock_control);
333 TLOG() << "The dsp_clock_control read back as 0x" << std::hex << dsp_clock_control << std::dec << std::endl;
334
335 fDevice->DeviceWrite(duneReg.pdts_control, 0x00000000 + fPartitionNumber + fTimingAddress * 0x10000);
336 TLOG() << "The pdts_status value was set to 0x" << std::hex
337 << 0x00000000 + fPartitionNumber + fTimingAddress * 0x10000 << std::dec << std::endl;
338 usleep(2000000); // setting the highest bit (0x80000000) to zero puts the SSP in run mode for the PDTS.
339 fDevice->DeviceWrite(duneReg.dsp_clock_control,
340 0x31); // setting the lowest bit to 1 sets the DSP clock to external.
341 TLOG() << "The dsp_clock_control was set to 0x" << std::hex << 0x31 << std::dec << std::endl;
342 usleep(2000000);
343 fDevice->DeviceRead(duneReg.pdts_status, &pdts_status);
344 TLOG() << "The pdts_status read back as 0x" << std::hex << pdts_status << std::dec << std::endl;
345 if ((pdts_status & 0xF) >= 0x6 && (pdts_status & 0xF) <= 0x8)
346 break;
347 TLOG() << "Timing endpoint sync failed (try " << nTries << ")" << std::endl;
348 ++nTries;
349 }
350
351 if ((pdts_status & 0xF) >= 0x6 && (pdts_status & 0xF) <= 0x8) {
352 TLOG() << "The pdts_status value is 0x" << std::hex << pdts_status << " and the 0xF bit masked value is 0x"
353 << (pdts_status & 0xF) << std::dec << std::endl;
354 TLOG() << "Timing endpoint synced!" << std::endl;
355 } else {
356 TLOG() << "The pdts_status value is 0x" << std::hex << pdts_status << " and the 0xF bit masked value is 0x"
357 << (pdts_status & 0xF) << std::dec << std::endl;
358 TLOG() << "Giving up on endpoint sync after 5 tries. Value of pdts_status register was 0x" << std::hex
359 << pdts_status << std::dec << std::endl;
360 }
361 }
362
363 TLOG() << "Woke up from 2 seconds of sleep and Waiting for endpoint to reach status 0x8..." << std::endl;
364 // Wait until pdts_status reaches exactly 0x8 before resolving.
365 if ((pdts_status & 0xF) != 0x8) {
366 TLOG() << "Waiting for endpoint to reach status 0x8..." << std::endl;
367 TLOG() << "The pdts_status value is 0x" << std::hex << pdts_status << " and the 0xF bit masked value is 0x"
368 << (pdts_status & 0xF) << std::dec << std::endl;
369 }
370 int nTries = 0;
371 while ((pdts_status & 0xF) != 0x8) {
372 if (nTries == 2) {
373 TLOG() << "Wrong PDTS status!" << std::endl;
374 throw DeviceInterfacePDTSStatus(ERS_HERE);
375 }
376 usleep(2000000);
377 TLOG() << "Woke up from 2 seconds of sleep and Waiting for endpoint to reach status 0x8..." << std::endl;
378 fDevice->DeviceRead(duneReg.pdts_status, &pdts_status);
379 TLOG() << "The pdts_status value is 0x" << std::hex << pdts_status << " and the 0xF bit masked value is 0x"
380 << (pdts_status & 0xF) << std::dec << std::endl;
381 nTries++;
382 }
383
384 TLOG() << "Endpoint is in running state, continuing with configuration!" << std::endl;
385 TLOG() << "SSP LED Calib Device Interface Configured complete.";
386} // NOLINT(readability/fn_size)
387
388std::string
390{
391 std::string ident;
392 boost::asio::ip::address ip = boost::asio::ip::address_v4(fDeviceId);
393 std::string ipString = ip.to_string();
394 ident += "(";
395 ident += ipString;
396 ident += "):";
397 return ident;
398}
399void
401{
402
403 TLOG_DEBUG(TLVL_WORK_STEPS) << "===SSP DIAGNOSTIC REGISTERS===" << std::endl;
404
406 unsigned int val;
407
408 fDevice->DeviceRead(duneReg.dp_clock_status, &val);
409 TLOG_DEBUG(TLVL_WORK_STEPS) << "dsp_clock_status: 0x" << std::hex << val << std::endl;
410 fDevice->DeviceRead(duneReg.live_timestamp_msb, &val);
411 TLOG_DEBUG(TLVL_WORK_STEPS) << "live_timestamp_msb: " << val << std::endl;
412 fDevice->DeviceRead(duneReg.live_timestamp_lsb, &val);
413 TLOG_DEBUG(TLVL_WORK_STEPS) << "live_timestamp_lsb: " << val << std::endl;
414 fDevice->DeviceRead(duneReg.sync_delay, &val);
415 TLOG_DEBUG(TLVL_WORK_STEPS) << "sync_delay: " << val << std::endl;
416 fDevice->DeviceRead(duneReg.sync_count, &val);
417 TLOG_DEBUG(TLVL_WORK_STEPS) << "sync_count: " << val << std::dec << std::endl;
418}
419
420#endif // SSPMODULES_SRC_ANLBOARD_DEVICEINTERFACE_CXX_
@ TLVL_FULL_DEBUG
#define ERS_HERE
const std::string & get_board_ip() const
Get "board_ip" attribute value. IP address of the board.
void SetRegisterByName(std::string name, unsigned int value)
void SetRegister(unsigned int address, unsigned int value, unsigned int mask=0xFFFFFFFF)
void ReadRegister(unsigned int address, unsigned int &value, unsigned int mask=0xFFFFFFFF)
void ReadRegisterArray(unsigned int address, std::vector< unsigned int > &value, unsigned int size)
void SetRegisterArrayByName(std::string name, unsigned int value)
void ReadRegisterArrayByName(std::string name, std::vector< unsigned int > &values)
void SetRegisterElementByName(std::string name, unsigned int index, unsigned int value)
void ReadRegisterByName(std::string name, unsigned int &value)
void ReadRegisterElementByName(std::string name, unsigned int index, unsigned int &value)
void ConfigureLEDCalib(const appmodel::SSPLEDCalibModule *conf)
void SetRegisterArray(unsigned int address, std::vector< unsigned int > value)
Device * OpenDevice(unsigned int deviceId, bool slowControlOnly=false)
unsigned int ReadMask() const
Definition RegMap.hpp:74
unsigned int WriteMask() const
Definition RegMap.hpp:76
unsigned int dp_clock_status
Definition RegMap.hpp:196
unsigned int live_timestamp_msb
Definition RegMap.hpp:237
unsigned int dsp_clock_control
Definition RegMap.hpp:249
static RegMap & Get()
Definition RegMap.cxx:14
unsigned int live_timestamp_lsb
Definition RegMap.hpp:236
#define TLVL_ENTER_EXIT_METHODS
#define TLOG_DEBUG(lvl,...)
Definition Logging.hpp:116
#define TLOG(...)
Definition macro.hpp:21
The DUNE-DAQ namespace.
FELIX Initialization std::string initerror FELIX queue timed std::string queuename Unexpected chunk size
Invalid address