AlcapDAQ  1
sis3600.cpp
Go to the documentation of this file.
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 
5 #include "midas.h"
6 
7 #include "crate.h"
8 #include "vme.h"
9 #include "odb_wrapper.h"
10 #include "diag.h"
11 
12 INT sis3600_bor();
13 INT sis3600_eor();
14 INT sis3600_poll_live();
15 INT sis3600_read(char *pevent);
16 
18  NULL, // init
19  NULL, // exit
20  NULL, // pre_bor
21  sis3600_bor, // bor
22  sis3600_eor, // eor
23  sis3600_poll_live, // poll_live
24  NULL, // poll_dead
25  NULL, // start_cycle
26  NULL, // stop_cycle
27  sis3600_read, // read
28 };
29 
30 
31 
32 #define SIS3600_MAX_DMA_SIZE 256
33 #define SIS3600_MAX_SIZE (32*1024*4)
34 #define ACTIVE_READOUT_BUFFER_SIZE (32*1024*4)
35 #define ACTIVE_READOUT_MAX_PER_POLL (2*1024)
36 
37 struct sis3600 {
38  bool enabled;
41  unsigned long vme_base;
42  char odb_name[20];
43  char bank_name[20];
46 };
47 
48 #define MAX_SIS3600 4
50 
51 #define SIS3600_CSR 0x000
52 #define SIS3600_KA_CLEAR 0x020
53 #define SIS3600_KA_ENABLENEXT 0x028
54 #define SIS3600_KA_RESET 0x060
55 #define SIS3600_OUTBUF 0x100
56 
57 #define SIS3600_CSR_FIFO_EMPTY_MASK 0x00000100
58 #define SIS3600_CSR_FIFO_ALMOST_EMPTY_MASK 0x00000200
59 
60 /*
61  * sis3600_bor1
62  *
63  * Initialize one SIS3600 module.
64  */
65 INT sis3600_bor1(struct sis3600 *sis)
66 {
67  // Get the VME base address of the module
68  sis->vme_base = odb_get_dword("/Equipment/Crate %d/Settings/%s/vme address",
69  crate_number, sis->odb_name);
70 
71  // Open a VME handle for memory-mapped access
72  struct vme_mapping_ctrl mapping = {
77  };
78 
79  struct vme_handle *handle =
80  vme_open(sis->vme_base, mapping, 0x200, SIS3600_MAX_DMA_SIZE);
81  sis->vme_handle = handle;
82 
83  // Reset
84  vme_write_d32(handle, sis->vme_base | SIS3600_KA_RESET, 0x1);
85 
86  // Clear for the next block
87  sis->active_readout_size = 0;
88 
89  // Read back current status register and check it
90  DWORD csr = vme_read_d32(handle, sis->vme_base | SIS3600_CSR);
91  if(csr != 0x00000300) {
92 // diag_print(0, "Unexpected status 0x%08x on %s after reset, disabling\n",
93  printf("Unexpected status 0x%08x on %s after reset, disabling\n",
94  csr, sis->odb_name);
95  sis->enabled = false;
96  return FE_ERR_HW;
97  }
98 
99  // Continue setup
100  vme_write_d32(handle, sis->vme_base | SIS3600_CSR, 0x08010000);
101  vme_write_d32(handle, sis->vme_base | SIS3600_KA_CLEAR, 0x1);
102  vme_write_d32(handle, sis->vme_base | SIS3600_KA_ENABLENEXT, 0x1);
103 
104  // Again check the status register value
105  csr = vme_read_d32(handle, sis->vme_base | SIS3600_CSR);
106  if(csr != 0x00018300) {
107 // diag_print(0, "Unexpected status 0x%08x on %s after setup, disabling\n",
108  printf("Unexpected status 0x%08x on %s after setup, disabling\n",
109  csr, sis->odb_name);
110  sis->enabled = false;
111  return FE_ERR_HW;
112  }
113 
114  printf("Enabled %s successfully\n", sis->odb_name);
115 
116  // Determine whether we're supposed to do active readout
117  sis->do_active_readout =
118  odb_get_bool("/Equipment/Crate %d/Settings/%s/Active Readout mode",
119  crate_number, sis->odb_name);
120 
121  return SUCCESS;
122 }
123 
124 /*
125  * sis3600_bor
126  *
127  * Called at the beginning of the run to discover SIS3600 modules
128  * and initialize them.
129  */
131 {
132  // Use the ODB to find any SIS3600 modules
133  for(int j = 0; j < MAX_SIS3600; j++) {
134 
135  bool enabled = false;
136 
137  if (odb_find_key("/Equipment/Crate %d/Settings/COMP %d", crate_number, j)) {
138  diag_print(1, "ODB says COMP %d is present, ", j);
139  enabled =
140  odb_get_bool("/Equipment/Crate %d/Settings/COMP %d/enabled status",
141  crate_number, j);
142  if (enabled) {
143  diag_print(1, "and is enabled. Initializing...\n");
144  } else {
145  diag_print(1, "but is disabled.\n");
146  }
147  }
148 
149  sis3600[j].enabled = enabled;
150 
151  // Set up the name of the MIDAS bank associated with the module
152  sprintf(sis3600[j].bank_name, "CMP%d", j);
153  sprintf(sis3600[j].odb_name, "COMP %d", j);
154 
155  if(enabled) {
156  sis3600_bor1(&sis3600[j]);
157  }
158  }
159 
160  return SUCCESS;
161 }
162 
163 INT sis3600_eor1(struct sis3600 *sis)
164 {
165  vme_close(sis->vme_handle);
166  return SUCCESS;
167 }
168 
169 /*
170  * sis3600_eor
171  *
172  * Called at the end of the run to release any resources that may have
173  * been allocated.
174  */
176 {
177 
178  for(int i = 0; i < MAX_SIS3600; i++) {
179  if(sis3600[i].enabled) {
180  int status = sis3600_eor1(&sis3600[i]);
181  if(status != SUCCESS) {
182  return status;
183  }
184  }
185  }
186 
187  return SUCCESS;
188 }
189 
190 INT sis3600_fifo_read(struct sis3600 *sis, unsigned char *buffer,
191  int max_size, bool in_active_readout)
192 {
193  // If we're not in the active readout phase, then we simply do a big DMA.
194  // There is a 50% chance of losing one word at the end of the block.
195  if(!in_active_readout) {
196  int status = vme_dma_read(sis->vme_handle,
197  sis->vme_base | SIS3600_OUTBUF,
198  buffer,
199  max_size);
200  return status;
201  }
202 
203  // If we are in the active readout phase, then we have to be more careful.
204  // Before initiating a block transfer, we check whether the CSR
205  // indicates "almost empty." If it does not, a 256 byte (64 word)
206  // block transfer is safe. If it does, then we return nothing; we'll
207  // be back when there is enough data to bother with.
208  int size = 0;
209  while(size < max_size) {
210 
211  DWORD csr = vme_read_d32(sis->vme_handle, sis->vme_base | SIS3600_CSR);
213  return size;
214  }
215 
216  int size_this_time = MIN(max_size - size, 256);
217 
218  int status = vme_dma_read(sis->vme_handle,
219  sis->vme_base | SIS3600_OUTBUF,
220  buffer + size,
221  size_this_time);
222 
223  if(status >= 0) {
224  size += status;
225  }
226 
227  if(status != size_this_time) {
228  diag_print(0, "Retrieved only %d bytes from %s", status, sis->odb_name);
229  }
230  }
231 
232  return size;
233 }
234 
235 /*
236  * sis3600_poll1
237  *
238  * Performs active readout for a single SIS3600 FIFO.
239  */
240 INT sis3600_poll1(struct sis3600 *sis)
241 {
242  // If active readout is not enabled, skip it.
243  if(!sis->do_active_readout) {
244  return SUCCESS;
245  }
246 
247  // First check how much space we have available in the active
248  // readout buffer.
249  int size_left = ACTIVE_READOUT_BUFFER_SIZE - sis->active_readout_size;
250  int size = MIN(ACTIVE_READOUT_MAX_PER_POLL, size_left);
251 
252  // Now try to read up to that amount.
253  int status = sis3600_fifo_read(sis,
255  size, TRUE);
256 
257  // Check the status
258  if(status >= 0) {
259  sis->active_readout_size += status;
260  } else {
261  diag_print(0, "Status from sis3600_fifo_read is %d for %s.\n", status,
262  sis->odb_name);
263  return FE_ERR_HW;
264  }
265 
267  return FE_NEED_STOP;
268  } else {
269  return SUCCESS;
270  }
271 }
272 
273 /*
274  * sis3600_poll_live
275  *
276  * Called periodically while a block is active; performs active readout.
277  *
278  * Returns:
279  * - ordinarily 0,
280  * - a request for a "soft stop" end-of-block, or
281  * - an error code
282  */
284 {
285  for(int i = 0; i < MAX_SIS3600; i++) {
286  if(sis3600[i].enabled) {
287  int status = sis3600_poll1(&sis3600[i]);
288  if(status != SUCCESS) {
289  return status;
290  }
291  }
292  }
293 
294  return SUCCESS;
295 }
296 
297 /*
298  * sis3600_read1
299  *
300  * Constructs the MIDAS bank for a single SIS3600.
301  */
302 INT sis3600_read1(struct sis3600 *sis, char *pevent)
303 {
304  // Create the MIDAS bank
305  DWORD *pdata;
306  bk_create(pevent, sis->bank_name, TID_DWORD, &pdata);
307 
308  // Copy data that was read during the active readout
309  int active_size = sis->active_readout_size;
310  memcpy(pdata, sis->active_readout_buffer, active_size);
311 
312  // Read any data remaining in the module
313  int status =
314  sis3600_fifo_read(sis, ((unsigned char *) pdata) + active_size,
316 
317  // Check the status
318  int final_size = 0;
319  if(status >= 0) {
320  final_size = status;
321  } else {
322  // handle the error
323  }
324 
325  // Close the bank
326  // Modified by VT on Oct-29-2010
327  //bk_close(pevent, pdata + (active_size + final_size)/sizeof(DWORD));
328  int total_size = active_size + final_size;
329  if ( total_size > 500000 ) {
330  printf("ERROR! Event size is too big (%i). The event will be rejected\n");
331  bk_close(pevent, pdata + 0);
332  } else {
333  bk_close(pevent, pdata + (active_size + final_size)/sizeof(DWORD));
334  }
335 
336  // Clear for the next block
337  sis->active_readout_size = 0;
338 
339  // Clear FIFO
341 
342  return SUCCESS;
343 }
344 
345 /*
346  * sis3600_read
347  *
348  * Called at the end of a block to assemble data from that block into a
349  * MIDAS event.
350  */
351 INT sis3600_read(char *pevent)
352 {
353  for(int i = 0; i < MAX_SIS3600; i++) {
354  if(sis3600[i].enabled) {
355  int status = sis3600_read1(&sis3600[i], pevent);
356  if(status != SUCCESS) {
357  return status;
358  }
359  }
360  }
361 
362  return SUCCESS;
363 }