DUNE-DAQ
DUNE Trigger and Data Acquisition software
Loading...
Searching...
No Matches
DeviceInterface.cxx
Go to the documentation of this file.
1
9// FIXME: This code implementation is a mess, with most parameters hardcoded instead of taking them from the configuration
10#ifndef SSPMODULES_SRC_ANLBOARD_DEVICEINTERFACE_CXX_
11#define SSPMODULES_SRC_ANLBOARD_DEVICEINTERFACE_CXX_
12
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{
31 TLVL_WORK_STEPS = 10,
32 TLVL_BOOKKEEPING = 15,
34};
35
37 : fDeviceId(0)
38 , fState(dunedaq::sspmodules::DeviceInterface::kUninitialized)
39 , fUseExternalTimestamp(true)
40 , fHardwareClockRateInMHz(128)
41 , fDummyPeriod(-1)
42 , fSlowControlOnly(false)
43 , fPartitionNumber(0)
44 , fTimingAddress(0)
45 , exception_(false)
46{
47}
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
269 // Ask device manager for a pointer to the specified device
271 dunedaq::sspmodules::Device* device = 0;
272
273
274 device = devman.OpenDevice(fDeviceId);
275
276 if (!device) {
277 TLOG_DEBUG(TLVL_WORK_STEPS) << "Unable to get handle to device; giving up!" << std::endl;
278 throw(ENoSuchDevice());
279 }
280
281 fDevice = device;
282
283 // Reset timing endpoint
285
286 unsigned int pdts_status = 0;
287 unsigned int pdts_control = 0;
288 unsigned int dsp_clock_control = 0;
289
290 fDevice->DeviceRead(duneReg.pdts_status, &pdts_status);
291 TLOG_DEBUG(TLVL_FULL_DEBUG) << "The pdts_status read back as 0x" << std::hex << pdts_status << std::dec << std::endl;
292 fDevice->DeviceRead(duneReg.pdts_control, &pdts_control);
293 TLOG_DEBUG(TLVL_FULL_DEBUG) << "The pdts_control read back as 0x" << std::hex << pdts_control << std::dec << std::endl;
294 fDevice->DeviceRead(duneReg.dsp_clock_control, &dsp_clock_control);
295 TLOG_DEBUG(TLVL_FULL_DEBUG) << "The dsp_clock_control read back as 0x" << std::hex << dsp_clock_control << std::dec
296 << std::endl;
297
298 unsigned int presentTimingAddress = (pdts_control >> 16) & 0xFF;
299 unsigned int presentTimingPartition = pdts_control & 0x3;
300
301 TLOG_DEBUG(TLVL_WORK_STEPS) << "SSP HW presently on partition " << presentTimingPartition << ", address 0x" << std::hex
302 << presentTimingAddress << " with endpoint status 0x" << (pdts_status & 0xF)
303 << " and dsp_clock_control at 0x" << dsp_clock_control << std::dec << std::endl;
304
305 //if ((pdts_status & 0xF) >= 0x6 && (pdts_status & 0xF) <= 0x8 && presentTimingAddress == fTimingAddress &&
306 // presentTimingPartition == fPartitionNumber && dsp_clock_control == 0x31) {
307 if ((pdts_status & 0xF) >= 0x6 && (pdts_status & 0xF) <= 0x8 && presentTimingAddress == fTimingAddress &&
308 presentTimingPartition == fPartitionNumber && (dsp_clock_control & 0xF) == 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_DEBUG(TLVL_WORK_STEPS) << "Clock already looks ok... skipping endpoint reset." << std::endl;
312 } else {
313
314 TLOG_DEBUG(TLVL_WORK_STEPS) << "Syncing SSP LED Calib to PDTS (partition " << fPartitionNumber << ", endpoint address 0x"
315 << std::hex << 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_DEBUG(TLVL_FULL_DEBUG) << "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);
325 << "The pdts_control value was set to 0x" << std::hex << 0x80000000 + fPartitionNumber + fTimingAddress * 0x10000
326 << std::dec << 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_DEBUG(TLVL_FULL_DEBUG) << "The pdts_status read back as 0x" << std::hex << pdts_status << std::dec
330 << std::endl;
331 fDevice->DeviceRead(duneReg.pdts_control, &pdts_control);
332 TLOG_DEBUG(TLVL_FULL_DEBUG) << "The pdts_control read back as 0x" << std::hex << pdts_control << std::dec
333 << std::endl;
334 fDevice->DeviceRead(duneReg.dsp_clock_control, &dsp_clock_control);
335 TLOG_DEBUG(TLVL_FULL_DEBUG) << "The dsp_clock_control read back as 0x" << std::hex << dsp_clock_control << std::dec
336 << std::endl;
337
338 fDevice->DeviceWrite(duneReg.pdts_control, 0x00000000 + fPartitionNumber + fTimingAddress * 0x10000);
339 TLOG_DEBUG(TLVL_FULL_DEBUG) << "The pdts_status value was set to 0x" << std::hex
340 << 0x00000000 + fPartitionNumber + fTimingAddress * 0x10000 << std::dec << std::endl;
341 usleep(2000000); // setting the highest bit (0x80000000) to zero puts the SSP in run mode for the PDTS.
342 fDevice->DeviceWrite(duneReg.dsp_clock_control,
343 0x31); // setting the lowest bit to 1 sets the DSP clock to external.
344 TLOG_DEBUG(TLVL_FULL_DEBUG) << "The dsp_clock_control was set to 0x" << std::hex << 0x31 << std::dec << std::endl;
345 usleep(2000000);
346 fDevice->DeviceRead(duneReg.pdts_status, &pdts_status);
347 TLOG_DEBUG(TLVL_FULL_DEBUG) << "The pdts_status read back as 0x" << std::hex << pdts_status << std::dec
348 << std::endl;
349 if ((pdts_status & 0xF) >= 0x6 && (pdts_status & 0xF) <= 0x8)
350 break;
351 TLOG_DEBUG(TLVL_WORK_STEPS) << "Timing endpoint sync failed (try " << nTries << ")" << std::endl;
352 ++nTries;
353 }
354
355 if ((pdts_status & 0xF) >= 0x6 && (pdts_status & 0xF) <= 0x8) {
356 TLOG_DEBUG(TLVL_FULL_DEBUG) << "The pdts_status value is 0x" << std::hex << pdts_status
357 << " and the 0xF bit masked value is 0x" << (pdts_status & 0xF) << std::dec
358 << std::endl;
359 TLOG_DEBUG(TLVL_WORK_STEPS) << "Timing endpoint synced!" << std::endl;
360 } else {
361 TLOG_DEBUG(TLVL_FULL_DEBUG) << "The pdts_status value is 0x" << std::hex << pdts_status
362 << " and the 0xF bit masked value is 0x" << (pdts_status & 0xF) << std::dec
363 << std::endl;
364 TLOG_DEBUG(TLVL_WORK_STEPS) << "Giving up on endpoint sync after 5 tries. Value of pdts_status register was 0x"
365 << std::hex << pdts_status << std::dec << std::endl;
366 }
367 }
368
369 TLOG_DEBUG(TLVL_WORK_STEPS) << "Woke up from 2 seconds of sleep and Waiting for endpoint to reach status 0x8..."
370 << std::endl;
371 // Wait until pdts_status reaches exactly 0x8 before resolving.
372 if ((pdts_status & 0xF) != 0x8) {
373 TLOG_DEBUG(TLVL_WORK_STEPS) << "Waiting for endpoint to reach status 0x8..." << std::endl;
374 TLOG_DEBUG(TLVL_FULL_DEBUG) << "The pdts_status value is 0x" << std::hex << pdts_status
375 << " and the 0xF bit masked value is 0x" << (pdts_status & 0xF) << std::dec << std::endl;
376 }
377 int nTries = 0;
378 while ((pdts_status & 0xF) != 0x8) {
379 if (nTries == 2) {
380 TLOG_DEBUG(TLVL_WORK_STEPS) << "Wrong PDTS status!" << std::endl;
381 //ers::fatal( DeviceInterfacePDTSStatus(ERS_HERE) );
383 }
384 usleep(2000000);
385 TLOG_DEBUG(TLVL_WORK_STEPS) << "Woke up from 2 seconds of sleep and Waiting for endpoint to reach status 0x8..."
386 << std::endl;
387 fDevice->DeviceRead(duneReg.pdts_status, &pdts_status);
388 TLOG_DEBUG(TLVL_FULL_DEBUG) << "The pdts_status value is 0x" << std::hex << pdts_status
389 << " and the 0xF bit masked value is 0x" << (pdts_status & 0xF) << std::dec << std::endl;
390 nTries++;
391 }
392
393 TLOG_DEBUG(TLVL_WORK_STEPS) << "Endpoint is in running state, continuing with configuration!" << std::endl;
394 TLOG_DEBUG(TLVL_ENTER_EXIT_METHODS) << "SSP LED Calib Device Interface Configured complete.";
395} // NOLINT(readability/fn_size)
396
397std::string
399{
400 std::string ident;
401 boost::asio::ip::address ip = boost::asio::ip::address_v4(fDeviceId);
402 std::string ipString = ip.to_string();
403 ident += "(";
404 ident += ipString;
405 ident += "):";
406 return ident;
407}
408void
410{
411
412 TLOG_DEBUG(TLVL_WORK_STEPS) << "===SSP DIAGNOSTIC REGISTERS===" << std::endl;
413
415 unsigned int val;
416
417 fDevice->DeviceRead(duneReg.dp_clock_status, &val);
418 TLOG_DEBUG(TLVL_WORK_STEPS) << "dsp_clock_status: 0x" << std::hex << val << std::endl;
419 fDevice->DeviceRead(duneReg.live_timestamp_msb, &val);
420 TLOG_DEBUG(TLVL_WORK_STEPS) << "live_timestamp_msb: " << val << std::endl;
421 fDevice->DeviceRead(duneReg.live_timestamp_lsb, &val);
422 TLOG_DEBUG(TLVL_WORK_STEPS) << "live_timestamp_lsb: " << val << std::endl;
423 fDevice->DeviceRead(duneReg.sync_delay, &val);
424 TLOG_DEBUG(TLVL_WORK_STEPS) << "sync_delay: " << val << std::endl;
425 fDevice->DeviceRead(duneReg.sync_count, &val);
426 TLOG_DEBUG(TLVL_WORK_STEPS) << "sync_count: " << val << std::dec << std::endl;
427}
428
429#endif // SSPMODULES_SRC_ANLBOARD_DEVICEINTERFACE_CXX_
@ TLVL_FULL_DEBUG
@ TLVL_ENTER_EXIT_METHODS
#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:66
unsigned int WriteMask() const
Definition RegMap.hpp:70
unsigned int dp_clock_status
Definition RegMap.hpp:198
unsigned int live_timestamp_msb
Definition RegMap.hpp:239
unsigned int dsp_clock_control
Definition RegMap.hpp:251
static RegMap & Get()
Definition RegMap.cxx:14
unsigned int live_timestamp_lsb
Definition RegMap.hpp:238
#define TLVL_ENTER_EXIT_METHODS
#define TLOG_DEBUG(lvl,...)
Definition Logging.hpp:112
Including Qt Headers.
FELIX Initialization std::string initerror FELIX queue timed std::string queuename Unexpected chunk size
LED calibration failed to ERS_EMPTY DeviceInterfacePDTSStatus
Definition SSPIssues.hpp:31