AlcapDAQ  1
dl40x.cpp
Go to the documentation of this file.
1 /*-----------------------------------------------------------------------------
2  STRUCK DL40x modules interface
3  F. Gray (U.C. Berkeley)
4  based on a previous version by T. Gorringe/P. Zolnierczuk (U. Kentucky)
5  ----------------------------------------------------------------------------*/
6 
7 #include <stdlib.h>
8 #include <stdio.h>
9 #include <string.h>
10 #include <fcntl.h>
11 
12 #include "midas.h"
13 
14 #include "crate.h"
15 #include "vme.h"
16 
17 #include "dl40x.h"
18 #include "diag.h"
19 #include "odb_wrapper.h"
20 
21 INT dl40x_bor ();
22 INT dl40x_eor ();
23 INT dl40x_read (char *pevent);
24 
26  NULL, // init
27  NULL, // exit
28  NULL, // pre_bor
29  dl40x_bor, // bor
30  dl40x_eor, // eor
31  NULL, // poll_live
32  NULL, // poll_dead
33  NULL, // start_cycle
34  NULL, // stop_cycle
35  dl40x_read, // read
36 };
37 
38 static struct dl401
39 {
42  unsigned long a16_base;
43  unsigned long a32_base;
44  BOOL enabled;
45  char odb_name[20];
46 
48 
49 static struct dl403
50 {
52  unsigned long a16_base;
53  BOOL enabled;
54 } clk;
55 
56 INT dl401_bor1 (struct dl401 *d);
57 
58 INT
60 {
61  /*
62  * Initialize DL403 clock generator.
63  */
64  if (dl403_init (&clk) != SUCCESS) {
65  return FE_ERR_HW;
66  }
67 
68  /*
69  * Initialize DL401 FADC modules.
70  */
71  for (int j = 0; j < DL401_MAXMODULES; j++)
72  {
73  sprintf (DL401[j].odb_name, "FADC %d", j);
74  DL401[j].enabled = FALSE;
75 
76  if (odb_find_key ("/Equipment/Crate %d/Settings/FADC %d", crate_number, j))
77  {
78  diag_print (1, "ODB says FADC #%d is present in crate 3, ", j);
79  DL401[j].enabled =
80  odb_get_bool ("/Equipment/Crate %d/Settings/FADC %d/enabled status",
81  crate_number, j);
82  if (DL401[j].enabled)
83  {
84  diag_print (1, "and is enabled. Initializing...\n");
85  dl401_bor1 (&DL401[j]);
86  }
87  else
88  {
89  diag_print (1, "but is disabled.\n");
90  }
91  }
92 
93  }
94 
95  return SUCCESS;
96 }
97 
98 INT
100 {
101  // release VME handles
102  if(clk.enabled) {
104  }
105 
106  for (int j = 0; j < DL401_MAXMODULES; j++) {
107  if(DL401[j].enabled) {
108  vme_close(DL401[j].a16_handle);
109  vme_close(DL401[j].a32_handle);
110  }
111  }
112 
113  return SUCCESS;
114 }
115 
116 INT
117 dl40x_read (char *pevent)
118 {
119  if(!clk.enabled) {
120  return SUCCESS;
121  }
122 
123  // loop over FADC banks if the clock has stopped. Otherwise, they
124  // aren't part of the event, because they didn't get a trigger.
125  if (!dl403_running (&clk))
126  {
127  for (int j = 0; j < DL401_MAXMODULES; j++)
128  {
129  if (DL401[j].enabled)
130  {
131 #if 0
132  // wait for the ADCs to finish converting
133  while (!dl401_finished (&DL401[j]))
134  {
135  cm_yield(0);
136  }
137 #endif
138 
139  // perform readout
140  long *pdata;
141  char bk_name[8];
142  int size = DL401_CNTMAX;
143 
144  sprintf (bk_name, "ADC%d", j);
145  bk_create (pevent, bk_name, TID_DWORD, &pdata);
146  size = dl401_read (&DL401[j], (u_int *) pdata);
147  pdata += size;
148  bk_close (pevent, pdata);
149 
150  // Reset for next event
151  dl401_reset (&DL401[j]);
152  dl401_clear (&DL401[j]);
153  }
154  }
155  }
156 
157  // Restart FADCs for next event
158  dl403_start (&clk);
159 
160  return SUCCESS;
161 }
162 
163 /* =================================================
164  STRUCK DL401 VME FLASH ADC
165  ================================================= */
166 
167 INT
168 dl401_bor1 (struct dl401 *d)
169 {
170  // Find base addresses. This module has separate A16 (for configuration)
171  // and A32 (for data memory) address regions. The A16 address is set by
172  // jumpers while the A32 is programmed by a register accessed through the
173  // A16 space.
174  d->a16_base = odb_get_word ("/Equipment/Crate %d/Settings/%s/a16 base address",
175  crate_number, d->odb_name);
176  d->a32_base = odb_get_dword ("/Equipment/Crate %d/Settings/%s/a32 base address",
177  crate_number, d->odb_name);
178 
179  // Get VME handles to access module
180  struct vme_mapping_ctrl a16_mapping = {
185  };
186  d->a16_handle = vme_open(d->a16_base, a16_mapping, 0x100, 0);
187 
188  struct vme_mapping_ctrl a32_mapping = {
193  };
194  d->a32_handle = vme_open(d->a32_base, a32_mapping, 4096, 0);
195 
196  // Set up the A32 base address
197  vme_write_d16 (d->a16_handle, d->a16_base | DL401_BASE, d->a32_base >> 16);
198 
199  // Set up the address modifiers
202 
203  // Set the default mode bits
205 
206  // find and set pedestals
208  for (int k = 0; k < DL401_NCHAN; k++)
209  {
210  ped[k] = odb_get_word ("/Equipment/Crate %d/Settings/%s/Pedestal",
211  crate_number, d->odb_name);
212  }
213  dl401_setPedestals (d, ped, DL401_NCHAN);
214 
215  // standard reset and clear
216  dl401_reset (d);
217  dl401_clear (d);
218 
219  diag_print(2, "dl401_bor1 a32_base=0x%08lx a16_base=0x%08lx\n",
220  d->a32_base, d->a16_base);
221 
222  return SUCCESS;
223 }
224 
225 INLINE int
226 dl401_setPedestals (struct dl401 *d, u_short p[], int np)
227 {
228  if (np != DL401_NCHAN)
229  return (-1);
230 
231  // compute word to write to pedestal DAC
232  DWORD parPed = 0;
233  for (int i = 0; i < np; i++) {
234  parPed |= (u_long) (p[i] & DL401_PEDCHANMASK) << (i * DL401_PEDCHANBITS);
235  }
236  parPed &= DL401_PEDMASK;
237  diag_print (2, "dl401_setPedestal: [%d] 0%08lo (", d, parPed);
238 
239  // enable writing to DAC
242 
243  // shift bits into DAC one at a time; it's a serial interface
244  for (int i = 0; i < DL401_PEDBITS; i++)
245  {
246  u_short bit =
247  ((parPed << i) & DL401_PEDBITMASK) >> (DL401_PEDBITS - 1);
248  vme_write_d16 (d->a16_handle, d->a16_base | DL401_WDAC, bit & 0x0001);
249  diag_print (2, "%1x", bit);
250  }
251 
252  // disable writing to DAC
255  diag_print (2, ")\n");
256 
257  return SUCCESS;
258 }
259 
260 INLINE u_short
261 dl401_getCounts (struct dl401 * d)
262 {
263  WORD rmad = vme_read_d16 (d->a16_handle, d->a16_base | DL401_RMAD);
264  return rmad & DL401_CNTMASK;
265 }
266 
267 INLINE u_short
268 dl401_getMode (struct dl401 * d)
269 {
270  return vme_read_d16 (d->a16_handle, d->a16_base | DL401_MODE);
271 }
272 
273 INLINE void
274 dl401_reset (struct dl401 *d)
275 {
276  vme_write_d16 (d->a16_handle, d->a16_base | DL401_MRST, 0xffff);
277 }
278 
279 INLINE void
280 dl401_clear (struct dl401 *d)
281 {
282  vme_write_d16 (d->a16_handle, d->a16_base | DL401_CLIF, 0xffff);
283 }
284 
285 INLINE void
286 dl401_convert (struct dl401 *d)
287 {
289 }
290 
291 INLINE int
293 {
294  WORD mode = vme_read_d16 (d->a16_handle, d->a16_base | DL401_MODE);
295  return (mode & DL401_INTREQ);
296 }
297 
298 
299 int
300 dl401_read (struct dl401 *d, u_int * data)
301 {
302  register u_int i = 0;
303  register u_int *addr;
304  int counts;
305 
306  counts = dl401_getCounts (d);
307  diag_print (2, "dl401_read: [%d] base=%p counts=%d\n", d, addr, counts);
308 
309  while (i < DL401_CNTMAX - counts)
310  {
311  data[i++] = vme_read_d32 (d->a32_handle, d->a32_base + (i + counts)*4);
312  }
313 
314  i = 0;
315  while (i < counts)
316  {
317  data[DL401_CNTMAX - counts + i] =
318  vme_read_d32 (d->a32_handle, d->a32_base + i*4);
319  i++;
320  }
321  diag_print (2, "--> done\n");
322  return (DL401_CNTMAX);
323 }
324 
325 #if 0
326 int
327 dl401_dmaread (DL401 * d, u_int * data)
328 {
329  long transfersize1, transfersize2;
330  int counts;
331 
332  counts = dl401_getCounts (d);
333  printf ("dl401 counts = %d\n", counts);
334 
335  transfersize1 = pread (fd_a32d32_noblt,
336  data,
337  (DL401_CNTMAX - counts) * sizeof (*data),
338  d->dataAddr - a32_space_start + counts * 4);
339 
340  transfersize2 = pread (fd_a32d32_noblt,
341  data + DL401_CNTMAX - counts,
342  counts * sizeof (*data),
343  d->dataAddr - a32_space_start);
344 
345  return ((transfersize1 + transfersize2) / sizeof (*data));
346 }
347 #endif
348 
349 /* =================================================
350  STRUCK DL403 VME CLOCK MODULE
351  ================================================= */
352 INT dl403_init (struct dl403 *d)
353 {
354  // Do we have an FADC clock?
355  if (odb_find_key("/Equipment/Crate %d/Settings/FADC CLOCK", crate_number)) {
356  d->enabled = TRUE;
357  } else {
358  d->enabled = FALSE;
359  return SUCCESS;
360  }
361 
362  // find base address
363  d->a16_base =
364  odb_get_word ("/Equipment/Crate %d/Settings/FADC CLOCK/a16 base address",
365  crate_number);
366 
367  // Open a VME handle
368  struct vme_mapping_ctrl a16_mapping = {
373  };
374  d->vme_handle = vme_open(d->a16_base, a16_mapping, 0x100, 0);
375 
376  // Set DL403 clock frequency
377  INT fadc_frequency =
378  odb_get_int ("/Equipment/Crate %d/Settings/FADC CLOCK/frequency", crate_number);
379  switch (fadc_frequency)
380  {
381  case 100:
382  dl403_setClockRate (d, DL403_100MHZ, 0x0, 0x0);
383  break;
384  case 50:
385  dl403_setClockRate (d, DL403_50MHZ, 0x0, 0x0);
386  break;
387  case 25:
388  dl403_setClockRate (d, DL403_SELECTED, 0x0, 0x0);
389  break;
390 
391  default:
392  cm_msg (MERROR, frontend_name,
393  "FADC clock frequency must be 25, 50, or 100 MHz (currently %d)\n",
394  fadc_frequency);
395  dl403_setClockRate (d, DL403_50MHZ, 0x0, 0x0);
396  }
397 
398  dl403_setClockCycle (d, 0x800, 0x800, 0x800);
399  dl403_steadyMode (d);
400  dl403_start (d);
401 
402  diag_print (2, "dl403_init 0x%08lx\n", d->a16_base);
403  return SUCCESS;
404 }
405 
406 void
407 dl403_setClockRate (struct dl403 *d, u_short clk1, u_short clk2, u_short clk3)
408 {
409  diag_print (2, "dl403_setClockRate: [%d] rate=0x%02hx\n", d,
410  (clk1 | (clk2 << 2) | (clk3 << 4)));
411 
413  clk1 | (clk2 << 2) | (clk3 << 4));
414 }
415 
416 void
417 dl403_setClockCycle (struct dl403 *d, u_short c1, u_short c2, u_short c3)
418 {
422 
423  diag_print (2,
424  "dl403_setClockCycles: [%d] cyc1=0x%04hx cyc2=0x%04hx cyc3=0x%04hx\n",
425  d, c1, c2, c3);
426 
427 }
428 
429 INLINE short
430 dl403_getMode (struct dl403 *d)
431 {
432  return vme_read_d16 (d->vme_handle, d->a16_base | DL403_MODE);
433 }
434 
435 INLINE void
437 {
439 }
440 
441 INLINE void
443 {
445 }
446 
447 INLINE void
449 {
451 }
452 
453 INLINE void
454 dl403_start (struct dl403 *d)
455 {
457 }
458 
459 INLINE void
460 dl403_stop (struct dl403 *d)
461 {
463 }
464 
465 INLINE void
466 dl403_reset (struct dl403 *d)
467 {
469 }
470 
471 INLINE short
472 dl403_runBit (struct dl403 *d)
473 {
474  WORD mode = vme_read_d16 (d->vme_handle, d->a16_base | DL403_MODE);
475  return (mode & DL403_RUN);
476 }
477 
478 INLINE short
479 dl403_running (struct dl403 *d)
480 {
481  WORD mode = vme_read_d16 (d->vme_handle, d->a16_base | DL403_MODE);
482  return !(mode & DL403_RUN);
483 }