AlcapDAQ  1
new_fadc.cpp
Go to the documentation of this file.
1 #include <map>
2 using namespace std;
3 
4 #include <stdlib.h>
5 #include <stdio.h>
6 #include <stdarg.h>
7 #include <string.h>
8 #include <errno.h>
9 #include <time.h>
10 #include <fcntl.h>
11 #include <unistd.h>
12 #include <sys/types.h>
13 #include <sys/mman.h>
14 #include <sys/stat.h>
15 #include <sys/ioctl.h>
16 #include <sys/time.h>
17 #include <sys/socket.h>
18 #include <net/if.h>
19 #include <net/ethernet.h>
20 #include <netinet/in.h>
21 #include <linux/if_packet.h>
22 
23 #include "midas.h"
24 
25 #include "crate.h"
26 #include "vme.h"
27 #include "odb_wrapper.h"
28 #include "diag.h"
29 
30 INT new_fadc_pre_bor();
31 INT new_fadc_eor();
32 INT new_fadc_read(char *pevent);
33 
34 const int TP_BLOCK_SIZE = 8192;
35 const int TP_NUM_BLOCKS = 1024;
36 const int FRAME_SIZE = 2048;
37 const int NUM_FRAMES = 4096;
38 
39 unsigned char *packet_space = 0;
41 
43  NULL, // init
44  NULL, // exit
45  new_fadc_pre_bor, // pre_bor
46  NULL, // bor
47  new_fadc_eor, // eor
48  NULL, // poll_live
49  NULL, // poll_dead
50  NULL, // start_cycle
51  NULL, // stop_cycle
52  new_fadc_read, // read
53 };
54 
55 bool allPacketsReceived(bool diag = false);
56 
58 
59 // packet format, including Ethernet-level headers
61 {
62  unsigned char dest_addr[6]; // 0
63  unsigned char src_addr[6]; // 6
64  unsigned short protocol; // 12
65  unsigned short content_length; // 14
66  unsigned char buffer_number; // 16
67  unsigned char admin_message; // 17
68  unsigned short packet_serial; // 18
69  unsigned long be_debug; // 20
70  // unsigned char fe_debug[8]; // 24
71  // OR
72  // unsigned char fe_debug[9]; // 24
73  // unsigned char frontend_number; // 32 or 33
74  // unsigned char data[]; // 33 or 34
75 };
76 
77 // state associated with each board
78 const int max_boards = 256;
79 struct fadc_board
80 {
81  bool enabled;
82  INT interface;
83  map<int, fadc_packet *> packets;
93 };
95 
97 {
98  for(int i = 0; i < NUM_FRAMES; i++) {
99  if(frame_examined[i]) continue;
100 
101  unsigned char *frame = packet_space + i*FRAME_SIZE;
102  struct tpacket_hdr *tph = (struct tpacket_hdr *) frame;
103  if(!(tph->tp_status & TP_STATUS_USER)) continue;
104 
105  struct fadc_packet *pkt = (struct fadc_packet *) (frame + tph->tp_mac);
106  int board_number = pkt->src_addr[5];
107  if(!board[board_number].enabled) continue;
108 
109  int content_length = ntohs(pkt->content_length);
110  int buffer_number = pkt->buffer_number;
111  int admin_message = pkt->admin_message;
112  int packet_serial = ntohs(pkt->packet_serial);
113 
114  board[board_number].packets[packet_serial] = pkt;
115  if(admin_message & 0x1) {
116  board[board_number].start_packet = packet_serial;
117  board[board_number].start_packet_seen = true;
118  }
119  if(admin_message & 0x2) {
120  board[board_number].stop_packet = packet_serial;
121  board[board_number].stop_packet_seen = true;
122  }
123  if(admin_message & 0x4) {
124  board[board_number].buffer_full = true;
125  }
126  double packet_time = tph->tp_sec*1e6 + tph->tp_usec;
127  double fpt = board[board_number].first_packet_time;
128  if(packet_time < fpt || fpt < 0) {
129  board[board_number].first_packet = packet_serial;
130  board[board_number].first_packet_time = packet_time;
131  }
132  double lpt = board[board_number].last_packet_time;
133  if(packet_time > lpt || lpt < 0) {
134  board[board_number].last_packet = packet_serial;
135  board[board_number].last_packet_time = packet_time;
136  }
137 
138  frame_examined[i] = true;
139  }
140 }
141 
142 void forgetPackets(bool reallyAll = false)
143 {
144  for(int i = 0; i < max_boards; i++) {
145  if(board[i].enabled) {
146  board[i].packets.clear();
147  board[i].start_packet_seen = false;
148  board[i].stop_packet_seen = false;
149  board[i].first_packet_time = -1;
150  board[i].buffer_full = false;
151  }
152  }
153 
154  // release all frame buffers back to the kernel
155  for(int i = 0; i < NUM_FRAMES; i++) {
156  if(frame_examined[i] || reallyAll) {
157  unsigned char *frame = packet_space + i*FRAME_SIZE;
158  struct tpacket_hdr *tph = (struct tpacket_hdr *) frame;
159  tph->tp_status = TP_STATUS_KERNEL;
160  frame_examined[i] = false;
161  }
162  }
163 }
164 
165 bool allPacketsReceived(bool diag)
166 {
167  // check whether we have a start packet, a stop packet, and a stream of
168  // continuous serial numbers in between.
169 
170  bool missing = false;
171 
172  for(int i = 0; i < max_boards; i++) {
173  if(!board[i].enabled) continue;
174  if(!board[i].start_packet_seen) {
176  if(diag) {
177  printf("-- board 0x%02x waiting on start packet\n", i);
178 #if 0
179  missing = true;
180 #endif
181  } else {
182 #if 0
183  return false;
184 #endif
185  }
186  if(diag) {
187  printf("-- board 0x%02x workaround for missing start packet\n", i);
188  }
189  }
190  if(!board[i].stop_packet_seen) {
192  if(diag) {
193  printf("-- board 0x%02x waiting on stop packet\n", i);
194 #if 0
195  missing = true;
196 #endif
197  } else {
198  return false;
199  }
200  }
201  }
202  for(int i = 0; i < max_boards; i++) {
203  if(!board[i].enabled) continue;
204  int num_packets = board[i].stop_packet - board[i].start_packet;
205  if(num_packets < 0) {
206  num_packets += 0x10000;
207  }
208 
209  int num_missing = 0;
210 #if 0
211  if(diag) {
212  printf("Start=%d Stop=%d\n", board[i].start_packet, board[i].stop_packet);
213  }
214 #endif
215  for(int j = num_packets; j >= 0; j--) {
216  int pn = (board[i].start_packet + j) & 0xffff;
217  if(board[i].packets[pn] == NULL) {
218  if(diag) {
219  printf("-- board 0x%02x waiting on packet %d\n", i, pn);
220  num_missing++;
221  missing = true;
222  } else {
223  return false;
224  }
225  }
226  }
227  if(diag && num_missing != 0) {
228  printf("-- board 0x%02x waiting on %d/%d packets\n", i,
229  num_missing, num_packets);
230  }
231  }
232  return !missing;
233 }
234 
235 
236 void setReg(char *if_name, int board, int fadc, int reg,
237  unsigned long long value, bool acquire)
238 {
239  // look up the index of the interface
240  int if_index = if_nametoindex(if_name);
241  if(if_index < 0) {
242  printf("Unknown interface %s\n", if_name);
243  return;
244  }
245 
246  struct ifreq req;
247  strcpy(req.ifr_name, if_name);
248  if(ioctl(packet_socket, SIOCGIFHWADDR, &req) < 0) {
249  perror("SIOCGIFHWADDR");
250  return;
251  }
252  unsigned char src[ETH_ALEN];
253  memcpy(src, req.ifr_hwaddr.sa_data, ETH_ALEN);
254 
255  unsigned char dst[ETH_ALEN] = { 0x00, 0x12, 0x6d, 0x12, 0x34, 0xff};
256  dst[5] = board;
257  struct sockaddr_ll dstaddr;
258  dstaddr.sll_family = AF_PACKET;
259  dstaddr.sll_protocol = htons(ETH_P_ALL);
260  dstaddr.sll_ifindex = if_index;
261  dstaddr.sll_hatype = 0;
262  dstaddr.sll_pkttype = 0;
263  dstaddr.sll_halen = ETH_ALEN;
264  memcpy(dstaddr.sll_addr, dst, ETH_ALEN);
265 
266  // format a packet
267  unsigned char packet[512];
268  memcpy(&packet[0], dst, ETH_ALEN);
269  memcpy(&packet[6], src, ETH_ALEN);
270 
271  // protocol
272  packet[12] = 0x0b;
273  packet[13] = 0x04;
274 
275  // the content
276  packet[14] = (!acquire << 7) |(fadc << 5) | reg;
277  packet[15] = (value >> 56) & 0xff;
278  packet[16] = (value >> 48) & 0xff;
279  packet[17] = (value >> 40) & 0xff;
280  packet[18] = (value >> 32) & 0xff;
281  packet[19] = (value >> 24) & 0xff;
282  packet[20] = (value >> 16) & 0xff;
283  packet[21] = (value >> 8) & 0xff;
284  packet[22] = (value ) & 0xff;
285 
286  int packet_length = 512;
287 
288  if(sendto(packet_socket, packet, packet_length, 0, (const sockaddr *) &dstaddr, sizeof(dstaddr)) < 0) {
289  perror("sendto");
290  }
291 
292  // wait for completion
293  usleep(2000);
294 }
295 
296 void setupRegs()
297 {
298  for(int i = 0; i < max_boards; i++) {
299 
300  // If no settings exist for the board, disable it.
301  if(!odb_find_key("/Equipment/Crate %d/Settings/NFADC %02x",
302  crate_number, i)) {
303  board[i].enabled = false;
304  continue;
305  }
306  printf("Found board %02x\n", i);
307 
308  bool enabled =
309  odb_get_bool("/Equipment/Crate %d/Settings/NFADC %02x/Enabled",
310  crate_number, i);
311  board[i].enabled = enabled;
312 
313  const char *yn = board[i].enabled ? "YES" : "NO";
314  printf("FADC board 0x%02x: enabled: %s\n", i, yn);
315 
316  board[i].interface = odb_get_int("/Equipment/Crate %d/Settings/NFADC %02x/Interface", crate_number, i);
317 
318  for(int chan = 0; chan < 8; chan++) {
319  int led_mode =
320  odb_get_int("/Equipment/Crate %d/Settings/NFADC %02x/Channel %d/LED Mode",
321  crate_number, i, chan);
322 
323  int lower_threshold =
324  odb_get_int("/Equipment/Crate %d/Settings/NFADC %02x/Channel %d/Lower threshold",
325  crate_number, i, chan);
326  int upper_threshold =
327  odb_get_int("/Equipment/Crate %d/Settings/NFADC %02x/Channel %d/Upper threshold",
328  crate_number, i, chan);
329  int pulser_period =
330  odb_get_int("/Equipment/Crate %d/Settings/NFADC %02x/Channel %d/Pulser period",
331  crate_number, i, chan);
332  int trigger_mask =
333  odb_get_int("/Equipment/Crate %d/Settings/NFADC %02x/Channel %d/Trigger mask",
334  crate_number, i, chan);
335  int presamples =
336  odb_get_int("/Equipment/Crate %d/Settings/NFADC %02x/Channel %d/Presamples",
337  crate_number, i, chan);
338  int stretch_samples =
339  odb_get_int("/Equipment/Crate %d/Settings/NFADC %02x/Channel %d/Stretch samples",
340  crate_number, i, chan);
341  int dcm_phase =
342  odb_get_int("/Equipment/Crate %d/Settings/NFADC %02x/Channel %d/DCM phase",
343  crate_number, i, chan);
344 
345  if(enabled) {
346  unsigned long long r0 =
347  (lower_threshold & 0xfff) |
348  ((upper_threshold & 0xfff) << 12) |
349  ((trigger_mask & 0xf) << 24) |
350  ((presamples & 0xfff) << 28) |
351  (((unsigned long long) (stretch_samples & 0xfff)) << 40);
352  unsigned long long r1 =
353  (pulser_period & 0xffffffff) |
354  (((unsigned long long) (led_mode & 0xf)) << 32);
355  unsigned long long r2 = dcm_phase;
356 
357  int frontend = chan/2;
358 
359 #if 0
360  if(i == 0xff) {
361  if(frontend == 1) {
362  frontend = 2;
363  } else if(frontend == 2) {
364  frontend = 1;
365  }
366  }
367 #endif
368 
369  char interface[8];
370  sprintf(interface,"eth%i",board[i].interface);
371  //printf("Board %i interface %i (%s)\n",i,board[i].interface,interface);
372 
373  if(chan % 2 == 0) {
374  setReg(interface, i, frontend, 0, r0, 0);
375  setReg(interface, i, frontend, 1, r1, 0);
376  setReg(interface, i, frontend, 4, r2, 1);
377  } else {
378  setReg(interface, i, frontend, 2, r0, 0);
379  setReg(interface, i, frontend, 3, r1, 0);
380  setReg(interface, i, frontend, 5, r2, 1);
381  }
382  }
383  }
384  }
385 }
386 
388 {
389  // open a socket to receive packets for our protocol
390  packet_socket = socket(PF_PACKET, SOCK_RAW, htons(0x0b04));
391 
392  if(packet_socket < 0) {
393  perror("socket");
394  return FE_ERR_HW;
395  }
396 
397  // request that the packets be placed in a memory-mapped buffer
398  struct tpacket_req req;
399  req.tp_block_size = TP_BLOCK_SIZE;
400  req.tp_block_nr = TP_NUM_BLOCKS;
401  req.tp_frame_size = FRAME_SIZE;
402  req.tp_frame_nr = NUM_FRAMES;
403  int status = setsockopt(packet_socket, SOL_PACKET, PACKET_RX_RING,
404  (void *) &req, sizeof(req));
405  if(status < 0) {
406  perror("setsockopt PACKET_RX_RING");
407  return FE_ERR_HW;
408  }
409 
410  // map the buffer into our process address space
411  packet_space = (unsigned char *) mmap(0, TP_BLOCK_SIZE*TP_NUM_BLOCKS,
412  PROT_READ|PROT_WRITE, MAP_SHARED, packet_socket, 0);
413  if(packet_space == MAP_FAILED) {
414  perror("mmap");
415  return FE_ERR_HW;
416  }
417 
418  setupRegs();
419  forgetPackets(true);
420 
421  return SUCCESS;
422 }
423 
425 {
426  if(packet_space != 0) {
428  packet_space = 0;
429  }
430  close(packet_socket);
431  return SUCCESS;
432 }
433 
434 static struct timeval tv_start;
435 
436 INT new_fadc_read(char *pevent)
437 {
438  printf("new_fadc_read\n");
439 
440  char bk_name[80];
441  char *pdata;
442 
443  bool timed_out = false;
444  struct timeval t1, t2;
445  gettimeofday(&t1,0);
446 
447  receivePackets();
448 
449  while(!allPacketsReceived()) {
450  sched_yield();
451  receivePackets();
452 
453  gettimeofday(&t2,0);
454  double tdiff = (t2.tv_usec-t1.tv_usec) + 1000000*(t2.tv_sec-t1.tv_sec);
455  if(tdiff > 200000) {
456  printf("Timed out:\n");
457  allPacketsReceived(true); // for diagnostic printout
458  timed_out = true;
459  break;
460  }
461  }
462 
463  bool buffer_full = false;
464 
465  for(int i = 0; i < max_boards; i++) {
466  if(board[i].enabled) {
467  printf("Board 0x%02x: start %d (%c) - stop %d (%c) - buffer full (%c)\n", i,
468  board[i].start_packet, board[i].start_packet_seen ? '+' : '-',
469  board[i].stop_packet, board[i].stop_packet_seen ? '+' : '-',
470  board[i].buffer_full ? '+' : '-');
471 
472  if(board[i].buffer_full) buffer_full = true;
473  } // board[i] is enabled
474  }
475 
476  bk_init32(pevent);
477 
478  // Peter Winter 12/01/2013:
479  // Adding to write the board numbers with buffer overflow
480  // and data package loss to new banks
481 
482 
483  if(buffer_full){
484  // We have buffer overflow somewhere,
485  // so let's write all board numbers to the bank NBUF that have buffer overflow
486  INT *pbuffer_full;
487  bk_create(pevent, "NBUF", TID_INT, &pbuffer_full);
488  // Let's add the boards that have buffer overflow
489  for(int j=0; j < max_boards; ++j){
490  if(board[j].buffer_full) *pbuffer_full++ = j;
491  }
492  bk_close(pevent, pbuffer_full);
493  } //
494 
495  if(timed_out){
496  // We have some missing packets, so let's write all board numbers to
497  // the bank NLSS in case we are missing data packages
498  INT *p_package_loss;
499  bk_create(pevent, "NLSS", TID_INT, &p_package_loss);
500  // Let's add the boards that have buffer overflow
501  for(int j=0; j < max_boards; ++j){
502  if(board[j].enabled){
503  for(int m=board[j].first_packet; m<=board[j].last_packet; ++m){
504  if(!board[j].packets[m]){
505  *p_package_loss++ = j;
506  *p_package_loss++ = m;
507  }
508  }
509  }
510  }
511  bk_close(pevent, p_package_loss);
512  }
513 
514 // if(!timed_out) {
515 // printf("Block OK\n");
516  for(int i = 0; i < max_boards; i++) {
517  if(!board[i].enabled) continue;
518 
519  // values for TPC personality
520  int word_length = 9;
521  int fadc_number_offset = 32;
522  int data_offset = 33;
523  if(i >= 128) {
524  // values for neutron detector personality
525  word_length = 10;
526  fadc_number_offset = 33;
527  data_offset = 34;
528  }
529 
530  for(int j = 0; j < 8; j++) {
531  sprintf(bk_name, "N%c%02x", 'a' + j, i);
532  bk_create(pevent, bk_name, TID_BYTE, &pdata);
533 
534  int num_packets = board[i].stop_packet - board[i].start_packet + 1;
535  if(num_packets < 0) {
536  num_packets += 0x10000;
537  }
538 
539  for(int k = 0; k < num_packets; k++) {
540  int pn = (board[i].start_packet + k) & 0xffff;
541  struct fadc_packet *pkt = board[i].packets[pn];
542  if(pkt) {
543  int fadc_number = (int) *(((unsigned char *) pkt) + fadc_number_offset);
544  if(fadc_number != 0 && fadc_number != 1)
545  printf("board %d: fadc_number = %d !\n", fadc_number);
546  int frontend = ((pkt->buffer_number)/4)*2 + fadc_number;
547  if(frontend == j) {
548  int len = ntohs(pkt->content_length) - word_length;
549  if((len % word_length) != 0)
550  printf("board %d: content_length = %d !\n", i, len);
551  else if(len > 0) {
552  char *p = ((char *) pkt) + data_offset;
553  memcpy(pdata, p, len);
554  pdata += len;
555  }
556  }
557  }
558  }
559 
560  bk_close(pevent, pdata);
561  }
562  }
563 // }
564 
565  forgetPackets();
566 
567  return SUCCESS;
568 }
569 
570 /* ******************************************************************* */