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 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
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() << "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() << "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() << "The dsp_clock_control read back as 0x" << std::hex << dsp_clock_control << std::dec << std::endl;
296
297 unsigned int presentTimingAddress = (pdts_control >> 16) & 0xFF;
298 unsigned int presentTimingPartition = pdts_control & 0x3;
299
300 TLOG() << "SSP HW presently on partition " << presentTimingPartition << ", address 0x" << std::hex
301 << presentTimingAddress << " with endpoint status 0x" << (pdts_status & 0xF)
302 << " and dsp_clock_control at 0x" << dsp_clock_control << std::dec << std::endl;
303
304 //if ((pdts_status & 0xF) >= 0x6 && (pdts_status & 0xF) <= 0x8 && presentTimingAddress == fTimingAddress &&
305 // presentTimingPartition == fPartitionNumber && dsp_clock_control == 0x31) {
306 if ((pdts_status & 0xF) >= 0x6 && (pdts_status & 0xF) <= 0x8 && presentTimingAddress == fTimingAddress &&
307 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
308 //THEN THE CLOCK ALREADY IS ASSUMED TO BE GOOD, AND WE DON'T TRY TO RESYNCH WITH THE PDTS
309
310 TLOG() << "Clock already looks ok... skipping endpoint reset." << std::endl;
311 } else {
312
313 TLOG() << "Syncing SSP LED Calib to PDTS (partition " << fPartitionNumber << ", endpoint address 0x"
314 << std::hex << fTimingAddress << std::dec << ")" << std::endl;
315
316 unsigned int nTries = 0;
317
318 while (nTries < 5) {
319 fDevice->DeviceWrite(duneReg.dsp_clock_control, 0x30);
320 TLOG() << "The dsp_clock_control was set to 0x" << std::hex << 0x30 << std::dec
321 << std::endl; // setting the lowest bit to 0 sets the DSP clock to internal.
322 fDevice->DeviceWrite(duneReg.pdts_control, 0x80000000 + fPartitionNumber + fTimingAddress * 0x10000);
323 TLOG() << "The pdts_control value was set to 0x" << std::hex << 0x80000000 + fPartitionNumber + fTimingAddress * 0x10000
324 << std::dec << std::endl; // setting the highest bit (0x80000000) to 1 puts the SSP in Reset mode for the PDTS.
325
326 fDevice->DeviceRead(duneReg.pdts_status, &pdts_status);
327 TLOG() << "The pdts_status read back as 0x" << std::hex << pdts_status << std::dec
328 << std::endl;
329 fDevice->DeviceRead(duneReg.pdts_control, &pdts_control);
330 TLOG() << "The pdts_control read back as 0x" << std::hex << pdts_control << std::dec
331 << 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
334 << std::endl;
335
336 fDevice->DeviceWrite(duneReg.pdts_control, 0x00000000 + fPartitionNumber + fTimingAddress * 0x10000);
337 TLOG() << "The pdts_status value was set to 0x" << std::hex
338 << 0x00000000 + fPartitionNumber + fTimingAddress * 0x10000 << std::dec << std::endl;
339 usleep(2000000); // setting the highest bit (0x80000000) to zero puts the SSP in run mode for the PDTS.
340 fDevice->DeviceWrite(duneReg.dsp_clock_control,
341 0x31); // setting the lowest bit to 1 sets the DSP clock to external.
342 TLOG() << "The dsp_clock_control was set to 0x" << std::hex << 0x31 << std::dec << std::endl;
343 usleep(2000000);
344 fDevice->DeviceRead(duneReg.pdts_status, &pdts_status);
345 TLOG() << "The pdts_status read back as 0x" << std::hex << pdts_status << std::dec
346 << std::endl;
347 if ((pdts_status & 0xF) >= 0x6 && (pdts_status & 0xF) <= 0x8)
348 break;
349 TLOG() << "Timing endpoint sync failed (try " << nTries << ")" << std::endl;
350 ++nTries;
351 }
352
353 if ((pdts_status & 0xF) >= 0x6 && (pdts_status & 0xF) <= 0x8) {
354 TLOG() << "The pdts_status value is 0x" << std::hex << pdts_status
355 << " and the 0xF bit masked value is 0x" << (pdts_status & 0xF) << std::dec
356 << std::endl;
357 TLOG() << "Timing endpoint synced!" << std::endl;
358 } else {
359 TLOG() << "The pdts_status value is 0x" << std::hex << pdts_status
360 << " and the 0xF bit masked value is 0x" << (pdts_status & 0xF) << std::dec
361 << std::endl;
362 TLOG() << "Giving up on endpoint sync after 5 tries. Value of pdts_status register was 0x"
363 << std::hex << pdts_status << std::dec << std::endl;
364 }
365 }
366
367 TLOG() << "Woke up from 2 seconds of sleep and Waiting for endpoint to reach status 0x8..."
368 << std::endl;
369 // Wait until pdts_status reaches exactly 0x8 before resolving.
370 if ((pdts_status & 0xF) != 0x8) {
371 TLOG() << "Waiting for endpoint to reach status 0x8..." << std::endl;
372 TLOG() << "The pdts_status value is 0x" << std::hex << pdts_status
373 << " and the 0xF bit masked value is 0x" << (pdts_status & 0xF) << std::dec << std::endl;
374 }
375 int nTries = 0;
376 while ((pdts_status & 0xF) != 0x8) {
377 if (nTries == 2) {
378 TLOG() << "Wrong PDTS status!" << std::endl;
380 }
381 usleep(2000000);
382 TLOG() << "Woke up from 2 seconds of sleep and Waiting for endpoint to reach status 0x8..."
383 << std::endl;
384 fDevice->DeviceRead(duneReg.pdts_status, &pdts_status);
385 TLOG() << "The pdts_status value is 0x" << std::hex << pdts_status
386 << " and the 0xF bit masked value is 0x" << (pdts_status & 0xF) << std::dec << std::endl;
387 nTries++;
388 }
389
390 TLOG() << "Endpoint is in running state, continuing with configuration!" << std::endl;
391 TLOG() << "SSP LED Calib Device Interface Configured complete.";
392} // NOLINT(readability/fn_size)
393
394std::string
396{
397 std::string ident;
398 boost::asio::ip::address ip = boost::asio::ip::address_v4(fDeviceId);
399 std::string ipString = ip.to_string();
400 ident += "(";
401 ident += ipString;
402 ident += "):";
403 return ident;
404}
405void
407{
408
409 TLOG_DEBUG(TLVL_WORK_STEPS) << "===SSP DIAGNOSTIC REGISTERS===" << std::endl;
410
412 unsigned int val;
413
414 fDevice->DeviceRead(duneReg.dp_clock_status, &val);
415 TLOG_DEBUG(TLVL_WORK_STEPS) << "dsp_clock_status: 0x" << std::hex << val << std::endl;
416 fDevice->DeviceRead(duneReg.live_timestamp_msb, &val);
417 TLOG_DEBUG(TLVL_WORK_STEPS) << "live_timestamp_msb: " << val << std::endl;
418 fDevice->DeviceRead(duneReg.live_timestamp_lsb, &val);
419 TLOG_DEBUG(TLVL_WORK_STEPS) << "live_timestamp_lsb: " << val << std::endl;
420 fDevice->DeviceRead(duneReg.sync_delay, &val);
421 TLOG_DEBUG(TLVL_WORK_STEPS) << "sync_delay: " << val << std::endl;
422 fDevice->DeviceRead(duneReg.sync_count, &val);
423 TLOG_DEBUG(TLVL_WORK_STEPS) << "sync_count: " << val << std::dec << std::endl;
424}
425
426#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 TLOG_DEBUG(lvl,...)
Definition Logging.hpp:112
#define TLOG(...)
Definition macro.hpp:22
The DUNE-DAQ namespace.
Definition DataStore.hpp:57
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
#define TLVL_ENTER_EXIT_METHODS
Definition Issues.hpp:24