1// Example application for the Ndigo6G-12
2//
3#include "ndigo6g12_app.h"
4#include "ndigo6g12_interface.h"
5#include <map>
6#include <stdio.h>
7#include <stdlib.h>
8
9std::map<int, std::string> appTypeMap = {{1, "One ADC channels @6.4 Gsps"},
10 {2, "Two ADC channels @3.2 Gsps"},
11 {4, "Four ADC channels @1.6 Gsp"},
12 {5, "Averaging mode @6.4 Gsps"}};
13
14std::map<int, std::string> requirementsMap = {
15 {0,
16 "Starts the test of the currently configured app type"},
17 {1,
18 "Measure time distance between passing of "
19 "threshold, calculates the frequency, requires NIM signal on channel A"},
20 {2, "Dual-channel application that measures delay between start "
21 "pulse on channel A and stop pulse on channel D (NIM)"},
22 {4, "Quad-channel application that measures delay between start "
23 "pulse on channel A and stop pulses on channels B-D (NIM)"},
24 {5, "Measure time distance between averaged start on TRG (NIM) and stop on "
25 "channel A (falling) by summing data of 16 runs "
26 "to increase precision of measurement for signal with low amplitude"}};
27
28Ndigo6GApp *adcApp;
29ndigo6g12_param_info paramInfo;
30
31// initialize Ndigo6G-12 device
32ndigo6g12_device initialize_ndigo6g12(int bufferSize,
33 int boardId,
34 int cardIndex,
35 int appType,
36 int tdcChannels) {
37 // prepare initialization
38 ndigo6g12_init_parameters params;
39 // fill initialization data structure with default values
40 // so that the data is valid and only parameters
41 // of interest have to be set explicitly
42 ndigo6g12_get_default_init_parameters(¶ms);
43 params.application_type = appType;
44
45 params.buffer_size[0] = bufferSize; // size of the packet buffer
46 params.board_id = boardId; // value copied to "card" field of every packet,
47 // allowed range 0..255
48 params.card_index = cardIndex; // which of the Ndigo6G-12 board found in
49 // the system to be used
50 // this specifies the directories or the specific .cronorom if dynamic
51 // switching of appType is required. If not specified, the example will
52 // return an error if the appType does not match the current appType in the
53 // firmware
54 params.firmware_locations = ".";
55
56 // initialize card
57 int errorCode;
58 const char *errorMessage;
59 ndigo6g12_device device;
60 errorCode = ndigo6g12_init(&device, ¶ms, &errorMessage);
61
62 if (errorCode != CRONO_OK) {
63 printf("Could not init Ndigo6G-12: %s\n", errorMessage);
64 printf("Please change path to the .cronorom in ndigo6g12_example.cpp\n");
65 exit(1);
66 }
67
68 // check if firmware now supports the chosen application type
69 ndigo6g12_static_info si;
70 ndigo6g12_get_static_info(&device, &si);
71 if (si.application_type != appType) {
72 printf("The switch to appType did not work, please make sure that "
73 "the firmware file is provided");
74 ndigo6g12_close(&device);
75 exit(1);
76 }
77 if (appType == 0) {
78 appType = si.application_type;
79 }
80 switch (appType) {
81 case 1:
82 adcApp = new Ndigo6GAppSingle(tdcChannels);
83 break;
84 case 2:
85 adcApp = new Ndigo6GAppDual(tdcChannels);
86 break;
87 case 4:
88 adcApp = new Ndigo6GAppQuad(tdcChannels);
89 break;
90 case 5:
91 adcApp = new Ndigo6GAppAverager(tdcChannels);
92 break;
93 default:
94 printf("Not supported appType %d'\n", appType);
95 ndigo6g12_close(&device);
96 exit(1);
97 }
98 printf("Running in %s\n%s\n", appTypeMap[appType].c_str(),
99 requirementsMap[appType].c_str());
100 return device;
101}
102
103int configure_ndigo6g12(ndigo6g12_device *device, int adcThreshold) {
104 // prepare configuration
105 ndigo6g12_configuration config;
106
107 // fill configuration data structure with default values
108 // so that the configuration is valid and only parameters
109 // of interest have to be set explicitly
110 if (CRONO_OK != ndigo6g12_get_default_configuration(device, &config)) {
111 printf("Could not get default configuration: %s\n",
112 ndigo6g12_get_last_error_message(device));
113 ndigo6g12_close(device);
114 return 1;
115 }
116
117 //**************************************************************************
118 // configuration for the TDC channels
119 adcApp->ConfigureTDC(&config);
120
121 //**************************************************************************
122 // configuration for the ADC channels
123 adcApp->ConfigureADC(&config, adcThreshold);
124
125 // write configuration to board
126 int error_code = ndigo6g12_configure(device, &config);
127 if (error_code != CRONO_OK) {
128 printf("Could not configure Ndigo6G-12: %s\n",
129 ndigo6g12_get_last_error_message(device));
130 return 1;
131 }
132 ndigo6g12_get_param_info(device, ¶mInfo);
133 adcApp->SetParamInfo(¶mInfo);
134 return 0;
135}
136
137// print some basic information about the Ndigo6G-12 device
138void print_device_information(ndigo6g12_device *device) {
139 ndigo6g12_static_info si;
140 ndigo6g12_get_static_info(device, &si);
141 printf("Firmware revision %d.%d - Type %d\n", si.fw_revision,
142 si.svn_revision, si.application_type);
143 printf("Firmware Bitstream Timestamp : %s\n", si.bitstream_date);
144 printf("Calibration date : %s\n", si.calibration_date);
145 printf("Board serial : %d.%d\n", si.board_serial >> 24,
146 si.board_serial & 0xffffff);
147 printf("Board revision : %d\n", si.board_revision);
148 printf("Board configuration : %d\n", si.board_configuration);
149 printf("Driver Revision : %d.%d.%d\n",
150 ((si.driver_revision >> 16) & 255),
151 ((si.driver_revision >> 8) & 255), (si.driver_revision & 255));
152 printf("Driver Build Revision : %d\n", si.driver_build_revision);
153
154 ndigo6g12_fast_info fi;
155 ndigo6g12_get_fast_info(device, &fi);
156 printf("TDC temperature : %.2f C\n", fi.tdc1_temp);
157 printf("ADC temperature : %.2f C\n", fi.ev12_temp);
158 printf("FPGA temperature : %.2f C\n", fi.fpga_temperature);
159 printf("PCIe link speed : Gen. %d\n", fi.pcie_link_speed);
160 printf("PCIe link width : %d lanes\n", fi.pcie_link_width);
161 printf("PCIe payload : %d bytes\n", fi.pcie_max_payload);
162
163 ndigo6g12_param_info pi;
164 ndigo6g12_get_param_info(device, &pi);
165 printf("Sample rate : %.0f Msps\n",
166 pi.sample_rate / 1000000.0);
167 printf("Resolution : %d Bit\n", pi.resolution);
168 printf("Sample period : %.2f ps\n", pi.sample_period);
169 printf("TDC bin size : %.2f ps\n", pi.tdc_period);
170 printf("Packet Timestamp period : %.2f ps\n", pi.packet_ts_period);
171 printf("ADC Sample delay : %.2f ps\n", pi.adc_sample_delay);
172}
173
174int main(int argc, char *argv[]) {
175 if (argc < 2) {
176 printf("Usage: ndigo6g12_example <appType> [<tdcMask>]\n");
177 for (auto atPair : appTypeMap) {
178 int at = atPair.first;
179 printf("AppType %d: %s\n %s\n", at, appTypeMap[at].c_str(),
180 requirementsMap[at].c_str());
181 }
182 printf("tdcMask: Bit flag for TDC channels E-H\n");
183 exit(1);
184 }
185
186 int appType = atoi(argv[1]);
187 int tdcChannelMask = 0;
188 if (argc > 2) {
189 tdcChannelMask = atoi(argv[2]);
190 }
191 // use 128 MiByte to buffer incoming data
192 // largest ADC data packet has about 500 KiByte
193 const int64_t BUFFER_SIZE = 128 * 1024 * 1024;
194
195 // use the first Ndigo6G-12 device found in the system
196 const int CARD_INDEX = 0;
197
198 // set board ID in all packets to 0
199 // can be used to distinguish packets of multiple devices
200 const int BOARD_ID = 0;
201
202 printf("cronologic ndigo6g12_example using driver: %s\n",
203 ndigo6g12_get_driver_revision_str());
204
205 // create and initialize the device
206 // may fail if the device is already in use by another process
207 // or the device driver is not installed
208 ndigo6g12_device device =
209 initialize_ndigo6g12(BUFFER_SIZE, BOARD_ID, CARD_INDEX, appType,
210 tdcChannelMask);
211
212 print_device_information(&device);
213
214 // set the configuration required for capturing data
215 // the base line is shifted by +350mV, as the target is to trigger at the
216 // middle of the NIM pulse edge
217 int adcThreshold = 0;
218 int status = configure_ndigo6g12(&device, adcThreshold);
219 if (status != 0) {
220 exit(1);
221 }
222
223 // configure readout behaviour
224 // automatically acknowledge all data as processed
225 // on the next call to ndigo6g12_read()
226 // old packet pointers are invalid after calling ndigo6g12_read()
227 ndigo6g12_read_in readConfig;
228 readConfig.acknowledge_last_read = 1;
229
230 // structure with packet pointers for read data
231 ndigo6g12_read_out readData;
232
233 // start data capture
234 status = ndigo6g12_start_capture(&device);
235 if (status != CRONO_OK) {
236 printf("Could not start capturing: %s",
237 ndigo6g12_get_last_error_message(&device));
238 ndigo6g12_close(&device);
239 exit(1);
240 }
241
242 // get current sample rate to calculate event timestamps
243 ndigo6g12_param_info paramInfo;
244 ndigo6g12_get_param_info(&device, ¶mInfo);
245
246 // ADC data is provided in packets, one packet per ADC channel and trigger
247 // TDC data is provided in a single packet for all TDC inputs in a certain
248 // timespan
249 printf("\nReading packets:\n");
250
251 const int MAX_PACKET_COUNT = 70;
252 int packetCount = 0;
253 bool noDataLastTime = false;
254 while ((packetCount < MAX_PACKET_COUNT)) {
255 // get pointers to acquired packets
256 status = ndigo6g12_read(&device, &readConfig, &readData);
257 if (status != CRONO_OK) {
258 if (!noDataLastTime) {
259 printf(" - No data! -\n");
260 }
261 noDataLastTime = true;
262
263 } else {
264 noDataLastTime = false;
265 // iterate over all packets received by the last read
266 volatile crono_packet *p = readData.first_packet;
267 while (p <= readData.last_packet) {
268
269 if (p->channel < 4) {
270 // packets with channel number < 4 are ADC data
271 double packet_ts =
272 adcApp->ProcessADCPacket(const_cast<crono_packet *>(p));
273 } else {
274 // packets with channel number >= 4 are TDC data
275 adcApp->ProcessTDCPacket(const_cast<crono_packet *>(p));
276 }
277
278 // go to next packet
279 p = crono_next_packet(p);
280
281 packetCount++;
282 } // end: iterate over received packets
283 } // end: Got any packets?
284 } // end: while
285
286 // shut down packet generation and DMA transfers
287 ndigo6g12_stop_capture(&device);
288
289 // deactivate Ndigo6G-12
290 ndigo6g12_close(&device);
291
292 return 0;
293}