AlcapDAQ  1
new_fadc_may15.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 <netpacket/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_bor();
31 INT new_fadc_eor();
32 INT new_fadc_poll_live();
33 INT new_fadc_read(char *pevent);
34 
35 const int fadc_buffer_size = 256*1024 * sizeof(int);
36 
38  NULL, // init
39  NULL, // exit
40  NULL, // pre_bor
41  new_fadc_bor, // bor
42  new_fadc_eor, // eor
43  new_fadc_poll_live, // poll_live
44  NULL, // poll_dead
45  NULL, // start_cycle
46  NULL, // stop_cycle
47  new_fadc_read, // read
48 };
49 
50 bool allPacketsReceived(bool diag = false);
51 
53 
54 // packet format, including Ethernet-level headers
55 struct fadc_packet
56 {
57  unsigned char dest_addr[6];
58  unsigned char src_addr[6];
59  unsigned short protocol;
60  unsigned short content_length;
61  unsigned char buffer_number;
62  unsigned char admin_message;
63  unsigned short packet_serial;
64 };
65 
66 // state associated with each board
67 const int max_boards = 256;
68 struct fadc_board
69 {
70  bool enabled;
71  map<int, fadc_packet *> packets;
72  int start_packet;
73  int stop_packet;
74  bool start_packet_seen;
75  bool stop_packet_seen;
76 };
78 char *buf = NULL;
79 char *bufp;
80 
82 {
83  while(1) {
84  int status = recv(packet_socket, bufp, 1518, 0);
85  if(status < 0) {
86  if(errno != EWOULDBLOCK && errno != EAGAIN) {
87  perror("receivePackets");
88  }
89  break;
90  }
91 
92 #if 0
93  for(int i = 0; i < status; i++) {
94  printf("%02x ", 0xff & bufp[i]);
95  }
96  printf("\n");
97 #endif
98 
99  struct fadc_packet *pkt = (struct fadc_packet *) bufp;
100  int board_number = pkt->src_addr[5];
101  int content_length = ntohs(pkt->content_length);
102  int buffer_number = pkt->buffer_number;
103  int admin_message = pkt->admin_message;
104  int packet_serial = ntohs(pkt->packet_serial);
105 
106  if(content_length > 1500) {
107  printf("board %d length %d buffer %d admin %d serial %d\n",
108  board_number, content_length, buffer_number,
109  admin_message, packet_serial);
110  }
111 
112  board[board_number].packets[packet_serial] = pkt;
113  if(admin_message & 0x1) {
114  board[board_number].start_packet = packet_serial;
115  board[board_number].start_packet_seen = true;
116  }
117  if(admin_message & 0x2) {
118  board[board_number].stop_packet = packet_serial;
119  board[board_number].stop_packet_seen = true;
120  }
121 
122  bufp += status;
123 
124 /*
125  if(allPacketsReceived()) {
126  break;
127  }
128 */
129 
130  }
131 }
132 
134 {
135  for(int i = 0; i < max_boards; i++) {
136  if(board[i].enabled) {
137  board[i].packets.clear();
138  board[i].start_packet_seen = false;
139  board[i].stop_packet_seen = false;
140  }
141  }
142  bufp = buf;
143 }
144 
145 bool allPacketsReceived(bool diag)
146 {
147  // check whether we have a start packet, a stop packet, and a stream of
148  // continuous serial numbers in between.
149 
150  bool missing = false;
151 
152  for(int i = 0; i < max_boards; i++) {
153  if(!board[i].enabled) continue;
154  if(!board[i].start_packet_seen) {
155  if(diag) {
156  printf("-- board 0x%02x waiting on start packet\n", i);
157  missing = true;
158  } else {
159  return false;
160  }
161  }
162  if(!board[i].stop_packet_seen) {
163  if(diag) {
164  printf("-- board 0x%02x waiting on stop packet\n", i);
165  missing = true;
166  } else {
167  return false;
168  }
169  }
170  }
171  for(int i = 0; i < max_boards; i++) {
172  if(!board[i].enabled) continue;
173  int num_packets = board[i].stop_packet - board[i].start_packet;
174  if(num_packets < 0) {
175  num_packets += 0x10000;
176  }
177 
178  int num_missing = 0;
179  for(int j = num_packets; j >= 0; j--) {
180  int pn = (board[i].start_packet + j) & 0xffff;
181  if(board[i].packets[pn] == NULL) {
182  if(diag) {
183  num_missing++;
184  missing = true;
185  } else {
186  return false;
187  }
188  }
189  }
190  if(diag) {
191  printf("-- board 0x%02x waiting on %d/%d packets\n", i,
192  num_missing, num_packets);
193  }
194  }
195  return !missing;
196 }
197 
198 
199 void setReg(char *if_name, int board, int fadc, int reg,
200  unsigned long long value)
201 {
202  // look up the index of the interface
203  int if_index = if_nametoindex(if_name);
204  if(if_index < 0) {
205  printf("Unknown interface %s\n", if_name);
206  return;
207  }
208 
209  struct ifreq req;
210  strcpy(req.ifr_name, if_name);
211  if(ioctl(packet_socket, SIOCGIFHWADDR, &req) < 0) {
212  perror("SIOCGIFHWADDR");
213  return;
214  }
215  unsigned char src[ETH_ALEN];
216  memcpy(src, req.ifr_hwaddr.sa_data, ETH_ALEN);
217 
218  unsigned char dst[ETH_ALEN] = { 0x00, 0x12, 0x6d, 0x12, 0x34, 0xff};
219  dst[5] = board;
220  struct sockaddr_ll dstaddr;
221  dstaddr.sll_family = AF_PACKET;
222  dstaddr.sll_protocol = htons(ETH_P_ALL);
223  dstaddr.sll_ifindex = if_index;
224  dstaddr.sll_hatype = 0;
225  dstaddr.sll_pkttype = 0;
226  dstaddr.sll_halen = ETH_ALEN;
227  memcpy(dstaddr.sll_addr, dst, ETH_ALEN);
228 
229  // format a packet
230  unsigned char packet[512];
231  memcpy(&packet[0], dst, ETH_ALEN);
232  memcpy(&packet[6], src, ETH_ALEN);
233 
234  // protocol
235  packet[12] = 0x0b;
236  packet[13] = 0x04;
237 
238  // the content
239  packet[14] = (fadc << 5) | reg;
240  packet[15] = (value >> 56) & 0xff;
241  packet[16] = (value >> 48) & 0xff;
242  packet[17] = (value >> 40) & 0xff;
243  packet[18] = (value >> 32) & 0xff;
244  packet[19] = (value >> 24) & 0xff;
245  packet[20] = (value >> 16) & 0xff;
246  packet[21] = (value >> 8) & 0xff;
247  packet[22] = (value ) & 0xff;
248 
249  int packet_length = 512;
250 
251  if(sendto(packet_socket, packet, packet_length, 0, (const sockaddr *) &dstaddr, sizeof(dstaddr)) < 0) {
252  perror("sendto");
253  }
254 }
255 
256 void setupRegs()
257 {
258  for(int i = 0; i < max_boards; i++) {
259 
260  // If no settings exist for the board, disable it.
261  if(!odb_find_key("/Equipment/Crate %d/Settings/NFADC %02x",
262  crate_number, i)) {
263  board[i].enabled = false;
264  continue;
265  }
266  printf("Found board %02x\n", i);
267 
268  bool enabled =
269  odb_get_bool("/Equipment/Crate %d/Settings/NFADC %02x/Enabled",
270  crate_number, i);
271  board[i].enabled = enabled;
272 
273 
274  for(int chan = 0; chan < 8; chan++) {
275  int led_mode =
276  odb_get_int("/Equipment/Crate %d/Settings/NFADC %02x/Channel %d/LED Mode",
277  crate_number, i, chan);
278 
279  int lower_threshold =
280  odb_get_int("/Equipment/Crate %d/Settings/NFADC %02x/Channel %d/Lower threshold",
281  crate_number, i, chan);
282  int upper_threshold =
283  odb_get_int("/Equipment/Crate %d/Settings/NFADC %02x/Channel %d/Upper threshold",
284  crate_number, i, chan);
285  int pulser_period =
286  odb_get_int("/Equipment/Crate %d/Settings/NFADC %02x/Channel %d/Pulser period",
287  crate_number, i, chan);
288  int trigger_mask =
289  odb_get_int("/Equipment/Crate %d/Settings/NFADC %02x/Channel %d/Trigger mask",
290  crate_number, i, chan);
291  int presamples =
292  odb_get_int("/Equipment/Crate %d/Settings/NFADC %02x/Channel %d/Presamples",
293  crate_number, i, chan);
294  int stretch_samples =
295  odb_get_int("/Equipment/Crate %d/Settings/NFADC %02x/Channel %d/Stretch samples",
296  crate_number, i, chan);
297  int dcm_phase =
298  odb_get_int("/Equipment/Crate %d/Settings/NFADC %02x/Channel %d/DCM phase",
299  crate_number, i, chan);
300 
301  if(enabled) {
302  unsigned long long r0 =
303  (lower_threshold & 0xfff) |
304  ((upper_threshold & 0xfff) << 12) |
305  ((trigger_mask & 0xf) << 24) |
306  ((presamples & 0xf) << 28) |
307  (((unsigned long long) (stretch_samples & 0xff)) << 32);
308  unsigned long long r1 =
309  (pulser_period & 0xffffffff) |
310  (((unsigned long long) (led_mode & 0xf)) << 32);
311  unsigned long long r2 = dcm_phase;
312 
313  int frontend = chan/2;
314  if(frontend == 1) {
315  frontend = 2;
316  } else if(frontend == 2) {
317  frontend = 1;
318  }
319 
320  if(chan % 2 == 0) {
321  setReg("eth0", i, frontend, 0, r0);
322  setReg("eth0", i, frontend, 1, r1);
323  setReg("eth0", i, frontend, 4, r2);
324  } else {
325  setReg("eth0", i, frontend, 2, r0);
326  setReg("eth0", i, frontend, 3, r1);
327  setReg("eth0", i, frontend, 5, r2);
328  }
329  }
330  }
331  }
332 }
333 
334 INT new_fadc_bor()
335 {
336  packet_socket = socket(PF_PACKET, SOCK_RAW, htons(0x0b04));
337 
338  if(packet_socket < 0) {
339  perror("socket");
340  }
341 
342  buf = new char[fadc_buffer_size];
343 
344 #if 0
345  // set up a timeout so that recv() calls return after ~1 ms even if
346  // there is no packet.
347  struct timeval timeout;
348  timeout.tv_sec = 0;
349  timeout.tv_usec = 1000;
350  if(setsockopt(packet_socket, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) < 0) {
351  perror("setsockopt");
352  }
353 #endif
354 #if 1
355  // make socket non-blocking
356  if(fcntl(packet_socket, F_SETFL, O_NONBLOCK)) {
357  perror("fcntl O_NONBLOCK");
358  }
359 #endif
360 
361  setupRegs();
362  forgetPackets();
363 
364  return SUCCESS;
365 }
366 
367 INT new_fadc_eor()
368 {
369  if(buf != NULL) {
370  delete[] buf;
371  buf = NULL;
372  }
373  close(packet_socket);
374  return SUCCESS;
375 }
376 
377 INT new_fadc_poll_live()
378 {
379  receivePackets();
380  return SUCCESS;
381 }
382 
383 INT new_fadc_read(char *pevent)
384 {
385  char bk_name[80];
386  char *pdata;
387 
388  bool timed_out = false;
389  struct timeval t1, t2;
390  gettimeofday(&t1,0);
391  int loop_count = 0;
392  while(!allPacketsReceived()) {
393 // printf("Waiting to read...\n");
394  sched_yield();
395  receivePackets();
396 
397  gettimeofday(&t2,0);
398  double tdiff = (t2.tv_usec-t1.tv_usec) + 1000000*(t2.tv_sec-t1.tv_sec);
399  if(tdiff > 10000 && loop_count > 10) {
400  printf("Timed out:\n");
401  allPacketsReceived(true); // for diagnostic printout
402  timed_out = true;
403  break;
404  }
405  loop_count++;
406  }
407 
408  bk_init32(pevent);
409 
410  if(!timed_out) {
411  printf("Block OK\n");
412  for(int i = 0; i < max_boards; i++) {
413  if(!board[i].enabled) continue;
414 
415  for(int j = 0; j < 4; j++) {
416  sprintf(bk_name, "N%c%02x", 'a' + j, i);
417  bk_create(pevent, bk_name, TID_BYTE, &pdata);
418 
419  int num_packets = board[i].stop_packet - board[i].start_packet;
420  if(num_packets < 0) {
421  num_packets += 0x10000;
422  }
423 
424  for(int k = 0; k < num_packets; k++) {
425  int pn = (board[i].start_packet + k) & 0xffff;
426  int frontend = (board[i].packets[pn]->buffer_number - 1) / 3;
427  if(frontend == j) {
428  int len = ntohs(board[i].packets[pn]->content_length);
429  char *p = ((char *) (board[i].packets[pn])) + 20;
430  memcpy(pdata, p, len);
431  pdata += len;
432  }
433  }
434 
435  bk_close(pevent, pdata);
436  }
437  }
438  }
439 
440  forgetPackets();
441 
442  return SUCCESS;
443 }
444 
445 /* ******************************************************************* */