AlcapDAQ  1
dt5720_module.c
Go to the documentation of this file.
1 /*---------------------------------*/
2 /* SOFTWARE CONTROLLED ACQUISITION */
3 //#define SW_CONTROL
4 #ifdef SW_CONTROL
5 #undef SW_CONTROL
6 #endif
7 /*---------------------------------*/
8 
9 #include <stdio.h>
10 #include <stdlib.h>
11 
12 #include <unistd.h>
13 #include <sys/io.h>
14 #include <sys/time.h>
15 #include <sys/types.h>
16 #include <sys/stat.h>
17 #include <fcntl.h>
18 #include <string.h>
19 
20 #include "midas.h"
21 
22 #include "crate.h"
23 #include "diag.h"
24 
25 // CAEN includes
26 #include "CAENDigitizer.h"
27 #include "CAENDigitizerType.h"
28 
29 static int handle;
30 static uint32_t VME_BASE = 0x00000000;
31 static char *caen_data_buffer = NULL; // data buffers used by CAEN
32 static uint32_t caen_data_buffer_size = 0;
33 static char *data_buffer; // data buffers used by MIDAS
34 static uint32_t data_buffer_size;
35 static uint32_t data_size;
36 
37 
38 
39 static INT dt5720_init();
40 static void dt5720_exit();
41 static INT dt5720_pre_bor();
42 static INT dt5720_eor();
43 static INT dt5720_poll_live();
44 static INT dt5720_read(char *pevent); // MIDAS readout routine
45 static void dt5720_readout(); // read data from digitizer buffers
46 
47 static BOOL dt5720_update_digitizer();
48 static BOOL is_caen_error(CAEN_DGTZ_ErrorCode,int, const char*);
49 static uint32_t analog2adc_trigger(int);
50 static uint32_t analog2adc_offset(int);
51 
52 bool block_sig;
53 typedef struct timespec timer_start;
54 
56  dt5720_init, // init
57  dt5720_exit, // exit
58  dt5720_pre_bor, // pre_bor
59  NULL, // bor
60  dt5720_eor, // eor
61  dt5720_poll_live, // poll_live
62  NULL, // poll_dead
63  NULL, // start_block
64  NULL, // stop_block
65  dt5720_read // read
66 };
67 
68 // ======================================================================
69 // ODB structures
70 // ======================================================================
71 
72 typedef struct s_dt5720_odb{
79  char logic_level[4];
84  BOOL ext_clock;
86  struct {
87  BOOL enable;
88  float offset;
90  } ch00;
91  struct {
92  BOOL enable;
93  float offset;
95  } ch01;
96  struct {
97  BOOL enable;
98  float offset;
100  } ch02;
101  struct {
102  BOOL enable;
103  float offset;
105  } ch03;
107 
109 
110 #define S_DT5720_ODB_STR "\
111 [.]\n\
112 software_trigger_mode = BYTE : 0\n\
113 hardware_trigger_mode = BYTE : 0\n\
114 self_trigger_mode = BYTE : 0\n\
115 trigger_positive_edge = BOOL : y\n\
116 max_events_per_block = DWORD : 1024\n\
117 event_aligned_readout = BOOL : y\n\
118 logic_level = STRING : [4] NIM\n\
119 post_trigger_size = BYTE : 20\n\
120 gpi_acquisition_mode = BOOL : n\n\
121 zero_suppression_mode = BYTE : 0\n\
122 event_packing = BOOL : n\n\
123 ext_clock = BOOL : n\n\
124 waveform length = DWORD : 64\n\
125 \n\
126 [Ch00]\n\
127 enable = BOOL : n\n\
128 offset = FLOAT : 0\n\
129 self_trigger_threshhold = FLOAT : 0\n\
130 \n\
131 [Ch01]\n\
132 enable = BOOL : n\n\
133 offset = FLOAT : 0\n\
134 self_trigger_threshhold = FLOAT : 0\n\
135 \n\
136 [Ch02]\n\
137 enable = BOOL : n\n\
138 offset = FLOAT : 0\n\
139 self_trigger_threshhold = FLOAT : 0\n\
140 \n\
141 [Ch03]\n\
142 enable = BOOL : n\n\
143 offset = FLOAT : 0\n\
144 self_trigger_threshhold = FLOAT : 0\
145 "
146 
147 
148 extern HNDLE hDB;
149 
151 {
152  printf("Opening CAEN USB interface ...");
153  fflush(stdout);
154 
155  HNDLE hKey;
157  CAEN_DGTZ_BoardInfo_t BoardInfo;
158 
159  /* Grab Board */
160  /* int iLine = 0;
161  ret = CAEN_DGTZ_OpenDigitizer(CAEN_DGTZ_USB,iLine,0,VME_BASE,&handle);*/
163  /*
164  while(ret==CAEN_DGTZ_CommError)
165  {
166  //iLine++;
167  ret = CAEN_DGTZ_OpenDigitizer(CAEN_DGTZ_USB,iLine,0,VME_BASE,&handle);
168  }
169  */
170  if(is_caen_error(ret,__LINE__-1,"dt5720_init")) return FE_ERR_HW;
171 
172  /* Get Board Info */
173  ret = CAEN_DGTZ_GetInfo(handle,&BoardInfo);
174  if(is_caen_error(ret,__LINE__-1,"dt5720_init")) return FE_ERR_HW;
175  printf("\nConnected to CAEN Desktop Digitizer Model %s\n",BoardInfo.ModelName);
176  printf("\tROC FPGA Release is %s\n",BoardInfo.ROC_FirmwareRel);
177  printf("\tAMC FPGA Release is %s\n",BoardInfo.AMC_FirmwareRel);
178 
179  /* Reset Digitizer */
180  ret = CAEN_DGTZ_Reset(handle);
181  if(is_caen_error(ret,__LINE__-1,"dt5720_init")) return FE_ERR_HW;
182 
183  /* Link to Database */
184  //cm_get_experiment_database(&hDB,NULL);
185  char str[1024];
186  sprintf(str,"/Equipment/Crate %i/Settings/CAEN",crate_number);
187  int status = db_check_record(hDB,0,str,S_DT5720_ODB_STR,FALSE);
188  if(status==DB_NO_KEY || status==DB_STRUCT_MISMATCH)
189  {
190  status = db_create_record(hDB,0,str,S_DT5720_ODB_STR);
191  printf("Creating key with status: %d \n",status);
192  }
193  else if (status==DB_INVALID_HANDLE)
194  {
195  printf("Error: Cannot connect to database to setup CAEN DT5720.");
196  }
197 
198  status = db_find_key(hDB,0,str,&hKey);
199  status = db_open_record(hDB,hKey,&S_DT5720_ODB,sizeof(S_DT5720_ODB),MODE_READ,NULL,NULL);
200 
201  // configure clock input
202  if ( S_DT5720_ODB.ext_clock )
203  {
204  printf("Using external clock\n");
206  if(is_caen_error(ret,__LINE__-1,"dt5720_init")) return FE_ERR_HW;
207  }
208  else
209  {
210  printf("Using internal clock\n");
211  }
212 
213 
214  return status;
215 
216 }
217 
219 {
220 
223  is_caen_error(ret,__LINE__-1,"dt5720_exit");
224  free(data_buffer);
225 }
226 
228 {
230 
231 #ifdef SW_CONTROL
233  if(is_caen_error(ret,__LINE__-1,"dt5720_bor")) return FE_ERR_HW;
235  if(is_caen_error(ret,__LINE__-1,"dt5720_bor")) return FE_ERR_HW;
236 #endif /* SW_CONTROL */
237 
238  /* Setup Digitizer */
239  if(!dt5720_update_digitizer()) return FE_ERR_HW;
240 
241  /* Allocate space for readout from digitizer */
243  if(is_caen_error(ret,__LINE__-1,"dt5720_bor")) return FE_ERR_HW;
244  printf("Allocated %i bytes for CAEN data buffer\n", caen_data_buffer_size);
245 
246  /* Clear any remaining data */
248  if(is_caen_error(ret,__LINE__-1,"dt5720_bor")) return FE_ERR_HW;
249 
250  data_size = 0;
251 
252  return SUCCESS;
253 }
254 
256 {
257 
259 #ifdef SW_CONTROL
261  if(is_caen_error(ret,__LINE__-1,"dt5720_bor")) return FE_ERR_HW;
262 #endif /* SW_CONTROL */
264  if(is_caen_error(ret,__LINE__-1,"dt5720_eor")) return FE_ERR_HW;
265 
266  caen_data_buffer = NULL;
267 
268  return SUCCESS;
269 }
270 
271 INT dt5720_read(char *pevent)
272 {
273  //printf("Read out data from desktop digitizer\n");
274 
275  // =====================================================================================
276  // Read out remaining data from the digitizer
277  // =====================================================================================
278  dt5720_readout();
279 
280  // =====================================================================================
281  // Fill MIDAS event
282  // =====================================================================================
283  bk_init32(pevent);
284  char bk_name[5];
285  char *pdata;
286 
287  sprintf(bk_name,"CND0");
288  bk_create(pevent, bk_name, TID_BYTE, &pdata);
289  if ( data_size > MAX_EVENT_SIZE )
290  {
291  cm_msg(MERROR,"dt5720_read","Event size is too large. Truncating data...\n");
292  data_size = MAX_EVENT_SIZE;
293  }
294  memcpy(pdata, data_buffer, data_size);
295  pdata += data_size;
296  bk_close(pevent, pdata);
297  // reset data couner for the next event
298  data_size = 0;
299 
300  return SUCCESS;
301 }
302 
304 {
305 
306  CAEN_DGTZ_ErrorCode ret;
307  uint32_t caen_data_size;
308 
309  /* Read out data if there is any */
311  is_caen_error(ret,__LINE__-1,"dt5720_readout");
312 
313  /* If there's data, copy from digitizers local buffer to different local buffer */
314  if(caen_data_size > 0)
315  {
316  //printf("data size: %i\n", caen_data_size);
317 
318  if(data_size+caen_data_size < data_buffer_size )
319  {
320  memcpy((data_buffer+data_size), caen_data_buffer, caen_data_size);
321  data_size += caen_data_size;
322  }
323  }
324 }
325 
327 {
328 
329  dt5720_readout();
330 
331  return SUCCESS;
332 }
333 
335 {
337  /* General CAEN settings */
338 
339  switch(S_DT5720_ODB.software_trigger_mode)
340  {
341  case 0:
343  break;
344  case 1:
346  break;
347  case 2:
349  break;
350  case 3:
352  break;
353  default:
355  cm_msg(MINFO,"dt5720_update_digitizer","Invalid software trigger mode. Set to DISABLED. (%i)",(int)S_DT5720_ODB.software_trigger_mode);
356  break;
357  }
358  if(is_caen_error(ret,__LINE__,"dt5720_update_digitizer")) return false;
359 
360  switch(S_DT5720_ODB.hardware_trigger_mode)
361  {
362  case 0:
364  break;
365  case 1:
367  break;
368  case 2:
370  break;
371  case 3:
373  break;
374  default:
376  cm_msg(MINFO,"dt5720_update_digitizer","Invalid hardware trigger mode. Set to DISABLED.");
377  break;
378  }
379  if(is_caen_error(ret,__LINE__,"dt5720_update_digitizer")) return false;
380 
381  uint32_t caen_self_trigger_mask = 0b1111;
382  switch(S_DT5720_ODB.self_trigger_mode)
383  {
384  case 0:
386  break;
387  case 1:
389  break;
390  case 2:
392  break;
393  case 3:
395  break;
396  default:
398  cm_msg(MINFO,"dt5720_update_digitizer","Invalid channel self trigger mode. Set to DISABLED. (%i)",(int)S_DT5720_ODB.self_trigger_mode);
399  break;
400  }
401  if(is_caen_error(ret,__LINE__,"dt5720_update_digitizer")) return false;
402 
403  // According to correspondence with CAEN, second argument (channel nuumber) is ignored.
404  // But just in case...
405  if(S_DT5720_ODB.trigger_positive_edge)
406  {
411  }
412  else
413  {
418  }
419  if(is_caen_error(ret,__LINE__,"dt5720_update_digitizer")) return false;
420 
421  if(S_DT5720_ODB.max_events_per_block >= 2 && S_DT5720_ODB.max_events_per_block <= 1024)
422  {
424  }
425  else
426  {
428  cm_msg(MINFO,"dt5720_update_digitizer","Invalid max block size. Set to 1024.");
429  }
430  if(is_caen_error(ret,__LINE__,"dt5720_update_digitizer")) return false;
431 
432  if(strcmp(S_DT5720_ODB.logic_level,"NIM") == 0)
434  else if(strcmp(S_DT5720_ODB.logic_level,"TTL") == 0)
436  else
437  {
439  cm_msg(MINFO,"dt5720_update_digitizer","Invalid logic level. Set to NIM.");
440  }
441  if(is_caen_error(ret,__LINE__,"dt5720_update_digitizer")) return false;
442 
443  if(S_DT5720_ODB.post_trigger_size >= 0 && S_DT5720_ODB.post_trigger_size <=100)
444  {
446  }
447  else
448  {
450  cm_msg(MINFO,"dt5720_update_digitizer","Invalid post trigger size. Set to 80 percent.");
451  }
452  if(is_caen_error(ret,__LINE__,"dt5720_update_digitizer")) return false;
453 
454  if(S_DT5720_ODB.gpi_acquisition_mode)
455  {
457  }
458  else
459  {
461  }
462  if(is_caen_error(ret,__LINE__,"dt5720_update_digitizer")) return false;
463 
464  switch(S_DT5720_ODB.zero_suppression_mode)
465  {
466  case 0:
468  break;
469  case 2:
471  break;
472  case 3:
474  break;
475  default:
477  cm_msg(MINFO,"dt5720_update_digitizer","Invalid zero suppression mode. Set to none.");
478  break;
479  }
480  if(is_caen_error(ret,__LINE__,"dt5720_update_digitizer")) return false;
481 
482 
483  if(S_DT5720_ODB.event_packing)
484  {
486  }
487  else
488  {
490  }
491  if(is_caen_error(ret,__LINE__,"dt5720_update_digitizer")) return false;
492 
493  // Channel specific
494  uint32_t caen_channel_mask = 0;
495  if(S_DT5720_ODB.ch00.enable)
496  caen_channel_mask |= (1 << 0);
497  if(S_DT5720_ODB.ch01.enable)
498  caen_channel_mask |= (1 << 1);
499  if(S_DT5720_ODB.ch02.enable)
500  caen_channel_mask |= (1 << 2);
501  if(S_DT5720_ODB.ch03.enable)
502  caen_channel_mask |= (1 << 3);
503  ret = CAEN_DGTZ_SetChannelEnableMask(handle,caen_channel_mask);
504 
506  0,
507  analog2adc_offset(0));
508  if(is_caen_error(ret,__LINE__,"dt5720_update_digitizer")) return false;
510  1,
511  analog2adc_offset(1));
512  if(is_caen_error(ret,__LINE__,"dt5720_update_digitizer")) return false;
514  2,
515  analog2adc_offset(2));
516  if(is_caen_error(ret,__LINE__,"dt5720_update_digitizer")) return false;
518  3,
519  analog2adc_offset(3));
520  if(is_caen_error(ret,__LINE__,"dt5720_update_digitizer")) return false;
521 
523  0,
524  analog2adc_trigger(0));
525  if(is_caen_error(ret,__LINE__,"dt5720_update_digitizer")) return false;
527  1,
528  analog2adc_trigger(1));
529  if(is_caen_error(ret,__LINE__,"dt5720_update_digitizer")) return false;
531  2,
532  analog2adc_trigger(2));
533  if(is_caen_error(ret,__LINE__,"dt5720_update_digitizer")) return false;
535  3,
536  analog2adc_trigger(3));
537  if(is_caen_error(ret,__LINE__,"dt5720_update_digitizer")) return false;
538 
539  // =====================================================================================
540  // Record length
541  // =====================================================================================
542  ret = CAEN_DGTZ_SetRecordLength(handle, S_DT5720_ODB.wf_length);
543  if ( ret != CAEN_DGTZ_Success )
544  {
545  cm_msg(MERROR,"dt5720_update_digitizer","Cannot SetRecordLength. Error 0x%08x\n",ret);
546  return FE_ERR_HW;
547  }
548 
549  // ======================================================================================
550  // Channel configuration through register 0x8000=CAEN_DGTZ_BROAD_CH_CTRL_ADD
551  // ======================================================================================
552  uint32_t data;
554  if(is_caen_error(ret,__LINE__-1,"dt5720_update_digitizer")) return FE_ERR_HW;
555 
556  // Bit 4 must always be set to 1
557  data |= (1<<4);
558  // enable trigger overlap
559  data |= (1<<1);
561  if(is_caen_error(ret,__LINE__-1,"dt5720_update_digitizer")) return FE_ERR_HW;
562 
563  data_buffer_size = 32*1024*1024;
564  data_buffer = (char*) malloc(data_buffer_size);
565 
566  return true;
567 }
568 
569 uint32_t analog2adc_offset(int ch)
570 {
571 
572  static const uint32_t adcmax = 65535;
573  static const uint32_t adcmin = 0;
574  static const float analogmax = 1.;
575  static const float analogmin = -1.;
576  static const float slope = (float)(adcmax-adcmin)/(analogmax-analogmin);
577 
578  /*
579  Map analogue voltage offset (-1V-1V) to 16 bit ADC value (0-65535=2^16-1)
580  Dynamic ranges:
581  0x0000 -> -2V to 0V
582  0x8000 -> -1V to 1V
583  0xFFFF -> 0V to 2V
584  */
585  float v;
586  switch(ch)
587  {
588  case 0: v = S_DT5720_ODB.ch00.offset; break;
589  case 1: v = S_DT5720_ODB.ch01.offset; break;
590  case 2: v = S_DT5720_ODB.ch02.offset; break;
591  case 3: v = S_DT5720_ODB.ch03.offset; break;
592  default: return 0x8000;
593  }
594 
595  if(v>analogmax)
596  {
597  cm_msg(MINFO,"dt5720_update_digitizer","Invalid voltage offset. Set to 1V.");
598  return adcmin;
599  }
600  else if(v<analogmin)
601  {
602  cm_msg(MINFO,"dt5720_update_digitizer","Invalid voltage offset. Set to -1V.");
603  return adcmax;
604  }
605 
606  v += 1.;
607 
608  uint32_t dac = slope*v;
609  printf("DAC offset: channel %i DAC %i\n",ch, dac);
610 
611 
612  return dac;
613 }
614 
615 uint32_t analog2adc_trigger(int ch)
616 {
617  static const float dynamicrange = 2.;
618  static const uint32_t adcmax = 4095;
619  //static const uint32_t adcmax = 65535;
620  static const uint32_t adcmin = 0;
621  static const float slope = (adcmax-adcmin)/dynamicrange;
622 
623  float v, vmin;
624 
625  switch(ch)
626  {
627  case 0:
628  v = S_DT5720_ODB.ch00.self_trigger_threshold;
629  vmin = S_DT5720_ODB.ch00.offset - 1.;
630  break;
631  case 1:
632  v = S_DT5720_ODB.ch01.self_trigger_threshold;
633  vmin = S_DT5720_ODB.ch01.offset - 1.;
634  break;
635  case 2:
636  v = S_DT5720_ODB.ch02.self_trigger_threshold;
637  vmin = S_DT5720_ODB.ch02.offset - 1.;
638  break;
639  case 3:
640  v = S_DT5720_ODB.ch03.self_trigger_threshold;
641  vmin = S_DT5720_ODB.ch03.offset - 1.;
642  break;
643  default:
644  return (adcmax-adcmin)/2;
645  }
646 
647  if(v<vmin || v>(vmin+dynamicrange))
648  {
649  v = vmin+dynamicrange/2.;
650  cm_msg(MINFO,"dt5720_update_digitizer","Invalid self trigger threshold. Set to center.");
651  }
652 
653  uint32_t dac = (v-vmin)*slope;
654  printf("Trigger threshold: channel %i DAC %i DAC\n",ch,dac);
655 
656  return dac;
657 }
658 
659 BOOL is_caen_error(CAEN_DGTZ_ErrorCode e, int l, const char* r)
660 {
661  /*
662  l: line number
663  f: file name
664  r: parent routine
665  */
666 
667  static char* f = __FILE__;
668 
669  if(e==CAEN_DGTZ_Success)
670  return FALSE;
671 
672  switch(e)
673  {
674  case CAEN_DGTZ_CommError:
675  cm_msg(MT_ERROR,f,l,r,"CAEN DT5720 Communication error.");
676  break;
678  cm_msg(MT_ERROR,f,l,r,"CAEN DT5720 Generic (unspecified) error.");
679  break;
681  cm_msg(MT_ERROR,f,l,r,"CAEN DT5720 Invalid parameter error.");
682  break;
684  cm_msg(MT_ERROR,f,l,r,"CAEN DT5720 Invalid LinkType.");
685  break;
687  cm_msg(MT_ERROR,f,l,r,"CAEN DT5720 Invalid handle.");
688  break;
690  cm_msg(MT_ERROR,f,l,r,"CAEN DT5720 Too many devices.");
691  break;
693  cm_msg(MT_ERROR,f,l,r,"CAEN DT5720 Operation not allowed on this model.");
694  break;
696  cm_msg(MT_ERROR,f,l,r,"CAEN DT5720 Invalid interrupt level.");
697  break;
699  cm_msg(MT_ERROR,f,l,r,"CAEN DT5720 Invalid event number.");
700  break;
702  cm_msg(MT_ERROR,f,l,r,"CAEN DT5720 Unable to read from registry.");
703  break;
705  cm_msg(MT_ERROR,f,l,r,"CAEN DT5720 Unable to write to registry.");
706  break;
708  cm_msg(MT_ERROR,f,l,r,"CAEN DT5720 Invalid channel number.");
709  break;
711  cm_msg(MT_ERROR,f,l,r,"CAEN DT5720 Channel is busy.");
712  break;
714  cm_msg(MT_ERROR,f,l,r,"CAEN DT5720 Invalid FPIO (?) mode.");
715  break;
717  cm_msg(MT_ERROR,f,l,r,"CAEN DT5720 Invalid acquisition mode.");
718  break;
720  cm_msg(MT_ERROR,f,l,r,"CAEN DT5720 Module does not support this function.");
721  break;
722  case CAEN_DGTZ_Timeout:
723  cm_msg(MT_ERROR,f,l,r,"CAEN DT5720 Communication timed out.");
724  break;
726  cm_msg(MT_ERROR,f,l,r,"CAEN DT5720 Invalid buffer (readout or event).");
727  break;
729  cm_msg(MT_ERROR,f,l,r,"CAEN DT5720 Unable to find event.");
730  break;
732  cm_msg(MT_ERROR,f,l,r,"CAEN DT5720 Event is invalid.");
733  break;
735  cm_msg(MT_ERROR,f,l,r,"CAEN DT5720 Memory has run out.");
736  break;
738  cm_msg(MT_ERROR,f,l,r,"CAEN DT5720 Calibration failed.");
739  break;
741  cm_msg(MT_ERROR,f,l,r,"CAEN DT5720 Unable to locate digitizer.");
742  break;
744  cm_msg(MT_ERROR,f,l,r,"CAEN DT5720 Digitizer is already open.");
745  break;
747  cm_msg(MT_ERROR,f,l,r,"CAEN DT5720 Digitizer not ready.");
748  break;
750  cm_msg(MT_ERROR,f,l,r,"CAEN DT5720 Interrupts not configured.");
751  break;
753  cm_msg(MT_ERROR,f,l,r,"CAEN DT5720 Flash memory corrupted.");
754  break;
756  cm_msg(MT_ERROR,f,l,r,"CAEN DT5720 Firmware not supported by these libraries.");
757  break;
759  cm_msg(MT_ERROR,f,l,r,"CAEN DT5720 Function not yet implemented.");
760  break;
761  default:
762  cm_msg(MT_ERROR,f,l,r,"CAEN DT5720 Unknown error.");
763  break;
764  }
765  return TRUE;
766 }