AlcapDAQ  1
Data Structures | Functions | Variables
new_fadc.cpp File Reference
#include <map>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <netinet/in.h>
#include <linux/if_packet.h>
#include "midas.h"
#include "crate.h"
#include "vme.h"
#include "odb_wrapper.h"
#include "diag.h"

Go to the source code of this file.

Data Structures

struct  fadc_packet
 
struct  fadc_board
 

Functions

INT new_fadc_pre_bor ()
 
INT new_fadc_eor ()
 
INT new_fadc_read (char *pevent)
 
bool allPacketsReceived (bool diag=false)
 
void receivePackets ()
 
void forgetPackets (bool reallyAll=false)
 
void setReg (char *if_name, int board, int fadc, int reg, unsigned long long value, bool acquire)
 
void setupRegs ()
 

Variables

const int TP_BLOCK_SIZE = 8192
 
const int TP_NUM_BLOCKS = 1024
 
const int FRAME_SIZE = 2048
 
const int NUM_FRAMES = 4096
 
unsigned char * packet_space = 0
 
bool frame_examined [NUM_FRAMES]
 
struct readout_module new_fadc_module
 
int packet_socket
 
const int max_boards = 256
 
struct fadc_board board [max_boards]
 
static struct timeval tv_start
 

Function Documentation

bool allPacketsReceived ( bool  diag = false)

Definition at line 165 of file new_fadc.cpp.

References board, enabled, fadc_board::first_packet, i, fadc_board::last_packet, max_boards, printf(), fadc_board::start_packet, and fadc_board::stop_packet.

Referenced by new_fadc_read(), and receivePackets().

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 }
void forgetPackets ( bool  reallyAll = false)

Definition at line 142 of file new_fadc.cpp.

References board, fadc_board::buffer_full, enabled, fadc_board::first_packet_time, frame_examined, FRAME_SIZE, i, max_boards, NUM_FRAMES, packet_space, fadc_board::packets, fadc_board::start_packet_seen, and fadc_board::stop_packet_seen.

Referenced by new_fadc_bor(), new_fadc_pre_bor(), and new_fadc_read().

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 }
INT new_fadc_eor ( )

Definition at line 424 of file new_fadc.cpp.

References packet_socket, packet_space, SUCCESS, TP_BLOCK_SIZE, and TP_NUM_BLOCKS.

425 {
426  if(packet_space != 0) {
428  packet_space = 0;
429  }
430  close(packet_socket);
431  return SUCCESS;
432 }
INT new_fadc_pre_bor ( )

Definition at line 387 of file new_fadc.cpp.

References forgetPackets(), FRAME_SIZE, NUM_FRAMES, packet_socket, packet_space, setupRegs(), status, SUCCESS, TP_BLOCK_SIZE, and TP_NUM_BLOCKS.

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 }
INT new_fadc_read ( char *  pevent)

Definition at line 436 of file new_fadc.cpp.

References allPacketsReceived(), board, fadc_packet::buffer_number, fadc_packet::content_length, enabled, forgetPackets(), i, fadc_board::last_packet, max_boards, fadc_board::packets, printf(), receivePackets(), sprintf(), fadc_board::start_packet, fadc_board::stop_packet, and SUCCESS.

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 }
void receivePackets ( )

Definition at line 96 of file new_fadc.cpp.

References fadc_packet::admin_message, board, fadc_board::buffer_full, fadc_packet::buffer_number, fadc_packet::content_length, enabled, fadc_board::first_packet, fadc_board::first_packet_time, frame_examined, FRAME_SIZE, i, fadc_board::last_packet, fadc_board::last_packet_time, NUM_FRAMES, fadc_packet::packet_serial, packet_space, fadc_board::packets, fadc_packet::src_addr, fadc_board::start_packet, fadc_board::start_packet_seen, fadc_board::stop_packet, and fadc_board::stop_packet_seen.

Referenced by new_fadc_poll_live(), and new_fadc_read().

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 }
void setReg ( char *  if_name,
int  board,
int  fadc,
int  reg,
unsigned long long  value,
bool  acquire 
)

Definition at line 236 of file new_fadc.cpp.

References board, packet_socket, printf(), and value.

Referenced by setupRegs().

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 }
void setupRegs ( )

Definition at line 296 of file new_fadc.cpp.

References board, crate_number, enabled, fadc_board::enabled, i, fadc_board::interface, max_boards, odb_find_key(), odb_get_bool(), odb_get_int(), printf(), setReg(), and sprintf().

Referenced by new_fadc_bor(), and new_fadc_pre_bor().

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 }

Variable Documentation

struct fadc_board board[max_boards]
bool frame_examined[NUM_FRAMES]

Definition at line 40 of file new_fadc.cpp.

Referenced by forgetPackets(), and receivePackets().

const int FRAME_SIZE = 2048

Definition at line 36 of file new_fadc.cpp.

Referenced by forgetPackets(), new_fadc_pre_bor(), and receivePackets().

const int max_boards = 256

Definition at line 78 of file new_fadc.cpp.

Referenced by allPacketsReceived(), forgetPackets(), new_fadc_read(), and setupRegs().

struct readout_module new_fadc_module
Initial value:
= {
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
}

Definition at line 42 of file new_fadc.cpp.

const int NUM_FRAMES = 4096

Definition at line 37 of file new_fadc.cpp.

Referenced by forgetPackets(), new_fadc_pre_bor(), and receivePackets().

int packet_socket

Definition at line 57 of file new_fadc.cpp.

Referenced by new_fadc_bor(), new_fadc_eor(), new_fadc_pre_bor(), receivePackets(), and setReg().

unsigned char* packet_space = 0

Definition at line 39 of file new_fadc.cpp.

Referenced by forgetPackets(), new_fadc_eor(), new_fadc_pre_bor(), and receivePackets().

const int TP_BLOCK_SIZE = 8192

Definition at line 34 of file new_fadc.cpp.

Referenced by new_fadc_eor(), and new_fadc_pre_bor().

const int TP_NUM_BLOCKS = 1024

Definition at line 35 of file new_fadc.cpp.

Referenced by new_fadc_eor(), and new_fadc_pre_bor().

struct timeval tv_start
static

Definition at line 434 of file new_fadc.cpp.