AlcapDAQ  1
ReadoutTest_DPP_CI_x720.c
Go to the documentation of this file.
1 /******************************************************************************
2 *
3 * CAEN SpA - Front End Division
4 * Via Vetraia, 11 - 55049 - Viareggio ITALY
5 * +390594388398 - www.caen.it
6 *
7 ***************************************************************************/
17 #include <CAENDigitizer.h>
18 
19 #include <stdio.h>
20 #include <stdlib.h>
21 
22 //#define MANUAL_BUFFER_SETTING 0
23 // The following define must be set to the actual number of connected boards
24 #define MAXNB 1
25 // NB: the following define MUST specify the ACTUAL max allowed number of board's channels
26 // it is needed for consistency inside the CAENDigitizer's functions used to allocate the memory
27 #define MaxNChannels 8
28 
29 #define MAXNBITS 12
30 
31 /* include some useful functions from file Functions.c
32 you can find this file in the src directory */
33 #include "Functions.h"
34 
35 /* ###########################################################################
36 * Functions
37 * ########################################################################### */
38 
39 /* --------------------------------------------------------------------------------------------------------- */
43 /* --------------------------------------------------------------------------------------------------------- */
45 {
46  /* This function uses the CAENDigitizer API functions to perform the digitizer's initial configuration */
47  int i, ret = 0;
48 
49  /* Reset the digitizer */
50  ret |= CAEN_DGTZ_Reset(handle);
51 
52  if (ret) {
53  printf("ERROR: can't reset the digitizer.\n");
54  return -1;
55  }
56 
57  /* Set the DPP acquisition mode
58  This setting affects the modes Mixed and List (see CAEN_DGTZ_DPP_AcqMode_t definition for details)
59  CAEN_DGTZ_DPP_SAVE_PARAM_EnergyOnly Only energy (DPP-PHA) or charge (DPP-PSD/DPP-CI v2) is returned
60  CAEN_DGTZ_DPP_SAVE_PARAM_TimeOnly Only time is returned
61  CAEN_DGTZ_DPP_SAVE_PARAM_EnergyAndTime Both energy/charge and time are returned
62  CAEN_DGTZ_DPP_SAVE_PARAM_None No histogram data is returned */
64 
65  // Set the digitizer acquisition mode (CAEN_DGTZ_SW_CONTROLLED or CAEN_DGTZ_S_IN_CONTROLLED)
67 
68  // Set the number of samples for each waveform
69  ret |= CAEN_DGTZ_SetRecordLength(handle, Params.RecordLength);
70 
71  // Set the I/O level (CAEN_DGTZ_IOLevel_NIM or CAEN_DGTZ_IOLevel_TTL)
72  ret |= CAEN_DGTZ_SetIOLevel(handle, Params.IOlev);
73 
74  /* Set the digitizer's behaviour when an external trigger arrives:
75 
76  CAEN_DGTZ_TRGMODE_DISABLED: do nothing
77  CAEN_DGTZ_TRGMODE_EXTOUT_ONLY: generate the Trigger Output signal
78  CAEN_DGTZ_TRGMODE_ACQ_ONLY = generate acquisition trigger
79  CAEN_DGTZ_TRGMODE_ACQ_AND_EXTOUT = generate both Trigger Output and acquisition trigger
80 
81  see CAENDigitizer user manual, chapter "Trigger configuration" for details */
83 
84  // Set the enabled channels
85  ret |= CAEN_DGTZ_SetChannelEnableMask(handle, Params.ChannelMask);
86 
87  // Set how many events to accumulate in the board memory before being available for readout
88  ret |= CAEN_DGTZ_SetDPPEventAggregation(handle, Params.EventAggr, 0);
89 
90  /* Set the mode used to syncronize the acquisition between different boards.
91  In this example the sync is disabled */
93 
94  // Set the DPP specific parameters for the channels in the given channelMask
95  ret |= CAEN_DGTZ_SetDPPParameters(handle, Params.ChannelMask, &DPPParams);
96 
97  for(i=0; i<MaxNChannels; i++) {
98  if (Params.ChannelMask & (1<<i)) {
99  // Set a DC offset to the input signal to adapt it to digitizer's dynamic range
100  ret |= CAEN_DGTZ_SetChannelDCOffset(handle, i, 0x8000);
101 
102  // Set the Pre-Trigger size (in samples)
103  ret |= CAEN_DGTZ_SetDPPPreTriggerSize(handle, i, 80);
104 
105  // Set the polarity for the given channel (CAEN_DGTZ_PulsePolarityPositive or CAEN_DGTZ_PulsePolarityNegative)
106  ret |= CAEN_DGTZ_SetChannelPulsePolarity(handle, i, Params.PulsePolarity);
107  }
108  }
109 
110  /* Set the virtual probes settings
111  DPP-CI can save:
112  2 analog waveforms:
113  Analog Trace 1: it is always the input signal;
114  Analog Trace 2: it can be specified with the VIRTUALPROBE parameter
115  4 digital waveforms:
116  Digital Trace 1: it is always the trigger
117  Digital Trace 2: it is always the gate
118  Digital Trace 2/3: they can be specified with the DIGITALPROBE 1 and 2 parameters
119 
120  CAEN_DGTZ_DPP_VIRTUALPROBE_SINGLE -> Save only the Input Signal waveform
121  CAEN_DGTZ_DPP_VIRTUALPROBE_DUAL -> Save also the Trace specified in VIRTUALPROBE (interleaved)
122 
123  Probes types for Analog Trace 2:
124  CAEN_DGTZ_DPP_CI_VIRTUALPROBE_Baseline
125 
126  Probes types for Digital Trace 3:
127  ### Virtual Probes only for FW >= 130.21 ###
128  CAEN_DGTZ_DPP_CI_DIGITALPROBE1_R21_ExtTrg
129  CAEN_DGTZ_DPP_CI_DIGITALPROBE1_R21_OverThr
130  CAEN_DGTZ_DPP_CI_DIGITALPROBE1_R21_TrigOut
131  CAEN_DGTZ_DPP_CI_DIGITALPROBE1_R21_CoincWin
132  CAEN_DGTZ_DPP_CI_DIGITALPROBE1_R21_Coincidence
133  ### Virtual Probes only for FW <= 130.20 ###
134  CAEN_DGTZ_DPP_CI_DIGITALPROBE1_BlOutSafeBand
135  CAEN_DGTZ_DPP_CI_DIGITALPROBE1_BlTimeout
136  CAEN_DGTZ_DPP_CI_DIGITALPROBE1_CoincidenceMet
137  CAEN_DGTZ_DPP_CI_DIGITALPROBE1_Tvaw
138 
139  Probes types for Digital Trace 4:
140  ### Virtual Probes only for FW >= 130.21 ###
141  CAEN_DGTZ_DPP_CI_DIGITALPROBE2_R22_OverThr
142  CAEN_DGTZ_DPP_CI_DIGITALPROBE2_R22_TrgVal
143  CAEN_DGTZ_DPP_CI_DIGITALPROBE2_R22_TrgHO
144  CAEN_DGTZ_DPP_CI_DIGITALPROBE2_R22_Coincidence
145  ### Virtual Probes only for FW <= 130.20 ###
146  CAEN_DGTZ_DPP_CI_DIGITALPROBE2_R22_OverThr
147  CAEN_DGTZ_DPP_CI_DIGITALPROBE2_R22_TrgVal
148  CAEN_DGTZ_DPP_CI_DIGITALPROBE2_R22_TrgHO
149  CAEN_DGTZ_DPP_CI_DIGITALPROBE2_R22_Coincidence */
151  if (ret) {
152  printf("Warning: errors found during the programming of the digitizer.\nSome settings may not be executed\n");
153  return ret;
154  } else {
155  return 0;
156  }
157 }
158 
159 /* ########################################################################### */
160 /* MAIN */
161 /* ########################################################################### */
162 int main(int argc, char *argv[])
163 {
164  /* The following variable is the type returned from most of CAENDigitizer
165  library functions and is used to check if there was an error in function
166  execution. For example:
167  ret = CAEN_DGTZ_some_function(some_args);
168  if(ret) printf("Some error"); */
170 
171  /* Buffers to store the data. The memory must be allocated using the appropriate
172  CAENDigitizer API functions (see below), so they must not be initialized here
173  NB: you must use the right type for different DPP analysis (in this case CI) */
174  char *buffer = NULL; // readout buffer
175  CAEN_DGTZ_DPP_CI_Event_t *Events[MaxNChannels]; // events buffer
176  CAEN_DGTZ_DPP_CI_Waveforms_t *Waveform=NULL; // waveforms buffer
177 
178  /* The following variables will store the digitizer configuration parameters */
179  CAEN_DGTZ_DPP_CI_Params_t DPPParams[MAXNB];
180  DigitizerParams_t Params[MAXNB];
181 
182  /* Arrays for data analysis */
183  uint64_t PrevTime[MAXNB][MaxNChannels];
184  uint64_t ExtendedTT[MAXNB][MaxNChannels];
185  uint32_t *EHisto[MAXNB][MaxNChannels]; // Energy Histograms
186  int ECnt[MAXNB][MaxNChannels];
187  int TrgCnt[MAXNB][MaxNChannels];
188 
189  /* The following variable will be used to get an handler for the digitizer. The
190  handler will be used for most of CAENDigitizer functions to identify the board */
191  int handle[MAXNB];
192 
193  /* Other variables */
194  int i, b, ch, ev;
195  int Quit=0;
196  int AcqRun = 0;
197  uint32_t AllocatedSize, BufferSize;
198  int Nb=0;
199  int DoSaveWave[MAXNB][MaxNChannels];
200  int MajorNumber;
201  int BitMask = 0;
202  uint64_t CurrentTime, PrevRateTime, ElapsedTime;
203  uint32_t NumEvents[MaxNChannels];
204  CAEN_DGTZ_BoardInfo_t BoardInfo;
205 
206  memset(DoSaveWave, 0, MAXNB*MaxNChannels*sizeof(int));
207  for (i=0; i<MAXNBITS; i++)
208  BitMask |= 1<<i; /* Create a bit mask based on number of bits of the board */
209 
210  /* *************************************************************************************** */
211  /* Set Parameters */
212  /* *************************************************************************************** */
213  memset(&Params, 0, MAXNB*sizeof(DigitizerParams_t));
214  memset(&DPPParams, 0, MAXNB*sizeof(CAEN_DGTZ_DPP_CI_Params_t));
215  for(b=0; b<MAXNB; b++) {
216  for(ch=0; ch<MaxNChannels; ch++)
217  EHisto[b][ch] = NULL; //set all histograms pointers to NULL (we will allocate them later)
218 
219  /****************************\
220  * Communication Parameters *
221  \****************************/
222  // Direct USB connection
223  Params[b].LinkType = CAEN_DGTZ_USB; // Link Type
224  Params[b].VMEBaseAddress = 0; // For direct USB connection, VMEBaseAddress must be 0
225 
226  // Direct optical connection
227  //Params[b].LinkType = CAEN_DGTZ_PCI_OpticalLink; // Link Type
228  //Params[b].VMEBaseAddress = 0; // For direct CONET connection, VMEBaseAddress must be 0
229 
230  // Optical connection to A2818 (or A3818) and access to the board with VME bus
231  //Params[b].LinkType = CAEN_DGTZ_PCI_OpticalLink; // Link Type (CAEN_DGTZ_PCIE_OpticalLink for A3818)
232  //Params[b].VMEBaseAddress = 0x32100000; // VME Base Address (only for VME bus access; must be 0 for direct connection (CONET or USB)
233 
234  // USB connection to V1718 bridge and access to the board with VME bus
235  //Params[b].LinkType = CAEN_DGTZ_USB; // Link Type (CAEN_DGTZ_PCIE_OpticalLink for A3818)
236  //Params[b].VMEBaseAddress = 0x11110000; // VME Base Address (only for VME bus access; must be 0 for direct connection (CONET or USB)
237 
238  Params[b].IOlev = CAEN_DGTZ_IOLevel_TTL;
239  /****************************\
240  * Acquisition parameters *
241  \****************************/
242  Params[b].AcqMode = CAEN_DGTZ_DPP_ACQ_MODE_Mixed; // CAEN_DGTZ_DPP_ACQ_MODE_List or CAEN_DGTZ_DPP_ACQ_MODE_Oscilloscope
243  Params[b].RecordLength = 300; // Num of samples of the waveforms (only for Oscilloscope mode)
244  Params[b].ChannelMask = 0xF; // Channel enable mask
245  Params[b].EventAggr = 0; // number of events in one aggregate (0=automatic)
246  Params[b].PulsePolarity = CAEN_DGTZ_PulsePolarityNegative; // Pulse Polarity (this parameter can be individual)
247 
248  /****************************\
249  * DPP parameters *
250  \****************************/
251  for(ch=0; ch<MaxNChannels; ch++) {
252  DPPParams[b].thr[ch] = 100; // Trigger Threshold
253  /* The following parameter is used to specifiy the number of samples for the baseline averaging:
254  0 -> 8samp
255  1 -> 16samp
256  2 -> 32samp
257  3 -> 64samp */
258  DPPParams[b].nsbl[ch] = 2;
259  DPPParams[b].gate[ch] = 200; // Gate Width (N*4ns)
260  DPPParams[b].pgate[ch] = 25; // Pre Gate Width (N*4ns)
261  /* Self Trigger Mode:
262  0 -> Disabled
263  1 -> Enabled */
264  DPPParams[b].selft[ch] = 1;
265  /* Trigger configuration:
266  CAEN_DGTZ_DPP_TriggerConfig_Peak -> trigger on peak
267  CAEN_DGTZ_DPP_TriggerConfig_Threshold -> trigger on threshold */
268  DPPParams[b].trgc[ch] = CAEN_DGTZ_DPP_TriggerConfig_Peak;
269  /* Trigger Validation Acquisition Window */
270  DPPParams[b].tvaw[ch] = 50;
271  }
272  DPPParams[b].blthr = 3; // Baseline Threshold
273  DPPParams[b].bltmo = 100; // Baseline Timeout
274  DPPParams[b].trgho = 0; // Trigger Holdoff
275  }
276 
277  /* *************************************************************************************** */
278  /* Open the digitizer and read board information */
279  /* *************************************************************************************** */
280  /* The following function is used to open the digitizer with the given connection parameters
281  and get the handler to it */
282  for(b=0; b<MAXNB; b++) {
283  /* IMPORTANT: The following function identifies the different boards with a system which may change
284  for different connection methods (USB, Conet, ecc). Refer to CAENDigitizer user manual for more info.
285  Some examples below */
286 
287  /* The following is for b boards connected via b USB direct links
288  in this case you must set Params[b].LinkType = CAEN_DGTZ_USB and Params[b].VMEBaseAddress = 0 */
289  ret = CAEN_DGTZ_OpenDigitizer(Params[b].LinkType, b, 0, Params[b].VMEBaseAddress, &handle[b]);
290 
291  /* The following is for b boards connected via 1 opticalLink in dasy chain
292  in this case you must set Params[b].LinkType = CAEN_DGTZ_PCI_OpticalLink and Params[b].VMEBaseAddress = 0 */
293  //ret = CAEN_DGTZ_OpenDigitizer(Params[b].LinkType, 0, b, Params[b].VMEBaseAddress, &handle[b]);
294 
295  /* The following is for b boards connected to A2818 (or A3818) via opticalLink (or USB with A1718)
296  in this case the boards are accessed throught VME bus, and you must specify the VME address of each board:
297  Params[b].LinkType = CAEN_DGTZ_PCI_OpticalLink (CAEN_DGTZ_PCIE_OpticalLink for A3818 or CAEN_DGTZ_USB for A1718)
298  Params[0].VMEBaseAddress = <0xXXXXXXXX> (address of first board)
299  Params[1].VMEBaseAddress = <0xYYYYYYYY> (address of second board)
300  etc */
301  //ret = CAEN_DGTZ_OpenDigitizer(Params[b].LinkType, 0, 0, Params[b].VMEBaseAddress, &handle[b]);
302 
303  if (ret) {
304  printf("Can't open digitizer\n");
305  goto QuitProgram;
306  }
307 
308  /* Once we have the handler to the digitizer, we use it to call the other functions */
309  ret = CAEN_DGTZ_GetInfo(handle[b], &BoardInfo);
310  if (ret) {
311  printf("Can't read board info\n");
312  goto QuitProgram;
313  }
314  printf("\nConnected to CAEN Digitizer Model %s, recognized as board %d\n", BoardInfo.ModelName, b);
315  printf("ROC FPGA Release is %s\n", BoardInfo.ROC_FirmwareRel);
316  printf("AMC FPGA Release is %s\n", BoardInfo.AMC_FirmwareRel);
317 
318  /* Check firmware revision (only DPP firmware can be used with this Demo) */
319  sscanf(BoardInfo.AMC_FirmwareRel, "%d", &MajorNumber);
320  if (MajorNumber != 130) {
321  printf("This digitizer has not a DPP-CI firmware\n");
322  goto QuitProgram;
323  }
324  }
325 
326  /* *************************************************************************************** */
327  /* Program the digitizer (see function ProgramDigitizer) */
328  /* *************************************************************************************** */
329  for(b=0; b<MAXNB; b++) {
330  ret = ProgramDigitizer(handle[b], Params[b], DPPParams[b]);
331  if (ret) {
332  printf("Failed to program the digitizer\n");
333  goto QuitProgram;
334  }
335  }
336 
337  /* WARNING: The mallocs MUST be done after the digitizer programming,
338  because the following functions needs to know the digitizer configuration
339  to allocate the right memory amount */
340  /* Allocate memory for the readout buffer */
341  ret = CAEN_DGTZ_MallocReadoutBuffer(handle[0], &buffer, &AllocatedSize);
342  /* Allocate memory for the events */
343  ret |= CAEN_DGTZ_MallocDPPEvents(handle[0], Events, &AllocatedSize);
344  /* Allocate memory for the waveforms */
345  ret |= CAEN_DGTZ_MallocDPPWaveforms(handle[0], &Waveform, &AllocatedSize);
346  if (ret) {
347  printf("Can't allocate memory buffers\n");
348  goto QuitProgram;
349  }
350 
351 
352  /* *************************************************************************************** */
353  /* Readout Loop */
354  /* *************************************************************************************** */
355  // Clear Histograms and counters
356  for(b=0; b<MAXNB; b++) {
357  for(ch=0; ch<MaxNChannels; ch++) {
358  EHisto[b][ch] = (uint32_t *)malloc( (1<<MAXNBITS)*sizeof(uint32_t) );
359  memset(EHisto[b][ch], 0, (1<<MAXNBITS)*sizeof(uint32_t));
360  TrgCnt[b][ch] = 0;
361  ECnt[b][ch] = 0;
362  PrevTime[b][ch] = 0;
363  ExtendedTT[b][ch] = 0;
364  }
365  }
366  PrevRateTime = get_time();
367  AcqRun = 0;
368  PrintInterface();
369  printf("Type a command: ");
370  while(!Quit) {
371 
372  // Check keyboard
373  if(kbhit()) {
374  char c;
375  c = getch();
376  if (c=='q') Quit = 1;
377  if (c=='t')
378  for(b=0; b<MAXNB; b++)
379  CAEN_DGTZ_SendSWtrigger(handle[b]); /* Send a software trigger to each board */
380  if (c=='h')
381  for(b=0; b<MAXNB; b++)
382  for(ch=0; ch<MaxNChannels; ch++)
383  if( ECnt[b][ch] != 0)
384  SaveHistogram("Histo", b, ch, EHisto[b][ch]); /* Save Histograms to file for each board */
385  if (c=='w')
386  for(b=0; b<MAXNB; b++)
387  for(ch=0; ch<MaxNChannels; ch++)
388  DoSaveWave[b][ch] = 1; /* save waveforms to file for each channel for each board (at next trigger) */
389  if (c=='r') {
390  for(b=0; b<MAXNB; b++) {
391  CAEN_DGTZ_SWStopAcquisition(handle[b]);
392  printf("Restarted\n");
393  CAEN_DGTZ_ClearData(handle[b]);
394  CAEN_DGTZ_SWStartAcquisition(handle[b]);
395  }
396  }
397  if (c=='s') {
398  for(b=0; b<MAXNB; b++) {
399  // Start Acquisition
400  // NB: the acquisition for each board starts when the following line is executed
401  // so in general the acquisition does NOT starts syncronously for different boards
402  CAEN_DGTZ_SWStartAcquisition(handle[b]);
403  printf("Acquisition Started for Board %d\n", b);
404  }
405  AcqRun = 1;
406  }
407  if (c=='S') {
408  for(b=0; b<MAXNB; b++) {
409  // Stop Acquisition
410  CAEN_DGTZ_SWStopAcquisition(handle[b]);
411  printf("Acquisition Stopped for Board %d\n", b);
412  }
413  AcqRun = 0;
414  }
415  }
416  if (!AcqRun) {
417  Sleep(10);
418  continue;
419  }
420 
421  /* Calculate throughput and trigger rate (every second) */
422  CurrentTime = get_time();
423  ElapsedTime = CurrentTime - PrevRateTime; /* milliseconds */
424  if (ElapsedTime > 1000) {
425  system(CLEARSCR);
426  PrintInterface();
427  printf("Readout Rate=%.2f MB\n", (float)Nb/((float)ElapsedTime*1048.576f));
428  for(b=0; b<MAXNB; b++) {
429  printf("\nBoard %d:\n",b);
430  for(i=0; i<MaxNChannels; i++) {
431  if (TrgCnt[b][i]>0)
432  printf("\tCh %d:\tTrgRate=%.2f KHz\t\n", i, (float)TrgCnt[b][i]/(float)ElapsedTime);
433  else
434  printf("\tCh %d:\tNo Data\n", i);
435  TrgCnt[b][i]=0;
436  }
437  }
438  Nb = 0;
439  PrevRateTime = CurrentTime;
440  printf("\n\n");
441  }
442 
443  /* Read data from the boards */
444  for(b=0; b<MAXNB; b++) {
445  /* Read data from the board */
446  ret = CAEN_DGTZ_ReadData(handle[b], CAEN_DGTZ_SLAVE_TERMINATED_READOUT_MBLT, buffer, &BufferSize);
447  if (ret) {
448  printf("Readout Error\n");
449  goto QuitProgram;
450  }
451  if (BufferSize == 0)
452  continue;
453 
454  Nb += BufferSize;
455  //ret = DataConsistencyCheck((uint32_t *)buffer, BufferSize/4);
456  ret |= CAEN_DGTZ_GetDPPEvents(handle[b], buffer, BufferSize, Events, NumEvents);
457  if (ret) {
458  printf("Data Error: %d\n", ret);
459  goto QuitProgram;
460  }
461 
462  /* Analyze data */
463  for(ch=0; ch<MaxNChannels; ch++) {
464  if (!(Params[b].ChannelMask & (1<<ch)))
465  continue;
466 
467  /* Update Histograms */
468  for(ev=0; ev<NumEvents[ch]; ev++) {
469  TrgCnt[b][ch]++;
470  /* Time Tag */
471  if (Events[ch][ev].TimeTag < PrevTime[b][ch])
472  ExtendedTT[b][ch]++;
473  PrevTime[b][ch] = Events[ch][ev].TimeTag;
474  /* Energy */
475  if (Events[ch][ev].Charge > 0) {
476  // Fill the histograms
477  EHisto[b][ch][(Events[ch][ev].Charge) & BitMask]++;
478  ECnt[b][ch]++;
479  }
480 
481  /* Get Waveforms (only from 1st event in the buffer) */
482  if ((Params[b].AcqMode != CAEN_DGTZ_DPP_ACQ_MODE_List) && DoSaveWave[b][ch] && (ev == 0)) {
483  int size;
484  int16_t *WaveLine;
485  uint8_t *DigitalWaveLine;
486  CAEN_DGTZ_DecodeDPPWaveforms(handle[b], &Events[ch][ev], Waveform);
487 
488  // Use waveform data here...
489  size = (int)(Waveform->Ns); // Number of samples
490  WaveLine = Waveform->Trace1; // First trace (for DPP-CI it is ALWAYS the Input Signal)
491  SaveWaveform(b, ch, 1, size, WaveLine);
492 
493  WaveLine = Waveform->Trace2; // Second Trace (if single trace mode, it is a sequence of zeroes)
494  SaveWaveform(b, ch, 2, size, WaveLine);
495  DoSaveWave[b][ch] = 0;
496 
497  DigitalWaveLine = Waveform->DTrace1; // First Digital Trace (Trigger)
498  SaveDigitalProbe(b, ch, 1, size, DigitalWaveLine);
499  DoSaveWave[b][ch] = 0;
500 
501  DigitalWaveLine = Waveform->DTrace2; // Second Digital Trace (Gate)
502  SaveDigitalProbe(b, ch, 2, size, DigitalWaveLine);
503  DoSaveWave[b][ch] = 0;
504 
505  DigitalWaveLine = Waveform->DTrace3; // Third Digital Trace (DIGITALPROBE1 set with CAEN_DGTZ_SetDPP_PSD_VirtualProbe)
506  SaveDigitalProbe(b, ch, 3, size, DigitalWaveLine);
507  DoSaveWave[b][ch] = 0;
508 
509  DigitalWaveLine = Waveform->DTrace4; // Fourth Digital Trace (DIGITALPROBE2 set with CAEN_DGTZ_SetDPP_PSD_VirtualProbe)
510  SaveDigitalProbe(b, ch, 4, size, DigitalWaveLine);
511  DoSaveWave[b][ch] = 0;
512  printf("Waveforms saved to 'Waveform_<board>_<channel>_<trace>.txt'\n");
513  } // loop to save waves
514  } // loop on events
515  } // loop on channels
516  } // loop on boards
517  } // End of readout loop
518 
519 
520 QuitProgram:
521  /* stop the acquisition, close the device and free the buffers */
522  for(b=0; b<MAXNB; b++) {
523  CAEN_DGTZ_SWStopAcquisition(handle[b]);
524  CAEN_DGTZ_CloseDigitizer(handle[b]);
525  for (ch=0; ch<MaxNChannels; ch++)
526  if (EHisto[b][ch] != NULL)
527  free(EHisto[b][ch]);
528  }
530  CAEN_DGTZ_FreeDPPEvents(handle[0], Events);
531  CAEN_DGTZ_FreeDPPWaveforms(handle[0], Waveform);
532  return ret;
533 }
534