]> jspc29.x-matter.uni-frankfurt.de Git - trbnettools.git/commitdiff
added libtrbnet
authorhadeshyp <hadeshyp>
Mon, 25 May 2009 14:59:35 +0000 (14:59 +0000)
committerhadeshyp <hadeshyp>
Mon, 25 May 2009 14:59:35 +0000 (14:59 +0000)
14 files changed:
libtrbnet/.target-makefrag [new file with mode: 0644]
libtrbnet/HowTo_ADCM_v2.txt [new file with mode: 0644]
libtrbnet/Makefile [new file with mode: 0644]
libtrbnet/fs_fpga_int_mem.c [new file with mode: 0644]
libtrbnet/fs_fpga_int_mem.h [new file with mode: 0644]
libtrbnet/port.c [new file with mode: 0644]
libtrbnet/port.h [new file with mode: 0644]
libtrbnet/pulser.c [new file with mode: 0644]
libtrbnet/trb.txt [new file with mode: 0644]
libtrbnet/trbcmd.c [new file with mode: 0644]
libtrbnet/trberror.c [new file with mode: 0644]
libtrbnet/trberror.h [new file with mode: 0644]
libtrbnet/trbnet.c [new file with mode: 0644]
libtrbnet/trbnet.h [new file with mode: 0644]

diff --git a/libtrbnet/.target-makefrag b/libtrbnet/.target-makefrag
new file mode 100644 (file)
index 0000000..6a73bd7
--- /dev/null
@@ -0,0 +1 @@
+AXIS_BUILDTYPE=crisv32-axis-linux-gnu
diff --git a/libtrbnet/HowTo_ADCM_v2.txt b/libtrbnet/HowTo_ADCM_v2.txt
new file mode 100644 (file)
index 0000000..d0726f1
--- /dev/null
@@ -0,0 +1,94 @@
+HowTo ADCM_v2\r
+=============\r
+\r
+Alle Skripte / Software befindet sich im TRB0 /home/hadaq/mboehmer/ !\r
+\r
+Anschalten: Board zieht ca. 2A in Vollbestückung, im konfigurierten Betrieb ca. 2.8A. Netzteil wird heiss!\r
+\r
+TRB: ./load_xilinx.sh\r
+\r
+Initialisieren: ./setaddress_sn000 -> TRBnet-Adresse 0x42 wird zugewiesen\r
+\r
+APVs klarmachen: ./init_apvs\r
+\r
+APVs syncen: ./trbbang T 3 0 aa bb cccc\r
+\r
+Sync-Event abholen: ./trbbang I 0 aa bb cccc\r
+\r
+Triggern: ./trbbang T 0 X aa bb cccc\r
+\r
+X: 0 -> RAW128 mode (all channels raw)\r
+   1 -> PED128 mode (all channels pedestal corrected)\r
+   2 -> PED128THR mode (mode 1 + threshold comparison)\r
+   3 -> reserved\r
+   4 -> NC64PED64\r
+   5 -> NC64\r
+   6 -> NC64GOOD\r
+   7 -> NC64THR\r
+\r
+############################################################################################\r
+\r
+Datenformat:\r
+\r
+D[31]     0 -> Daten, 1 -> Debug\r
+D[30:28]  sector number\r
+D[27:25]  module number\r
+D[24:21]  APV number\r
+D[20:14]  channel number\r
+D[13:0]   ADC data\r
+\r
+Debug:\r
+\r
+D[30:28]  sector number\r
+D[27:25]  module number\r
+D[24:21]  APV number\r
+D[20]     bad buffer\r
+D[19]     buffer not valid\r
+D[18]     frame counter error\r
+D[17]     row error\r
+D[16]     APV error bit set\r
+D[15:12]  number of frames requested\r
+D[11:8]   current frame number\r
+D[7:0]    row information (if available)\r
+\r
+\r
+\r
+\r
+\r
+\r
+############################################################################################\r
+\r
+Es gibt vier Kontrollregister im APV, die die Boardkonfiguration beeinflussen:\r
+\r
+0xc0: [31]    RESET_SYS\r
+      [30]    RESET_APV\r
+      [29]    RESET_ADC\r
+      [26]    POWERDOWN_ADC1\r
+      [25]    POWERDOWN_ADC0\r
+      [24]    reserved, do not use\r
+      [16]    LED auf Backplane :-)\r
+      [15:0]  APV_ON\r
+\r
+0xc1: [31]    reset PLL ADC1\r
+      [27:24] Phase PLL ADC1\r
+      [23]    reset PLL ADC0\r
+      [19:16] Phase PLL ADC0\r
+      [14:12] debug output select ADC1\r
+      [10:8]  debug output select ADC0\r
+      [7]     reset PLL 40MHz\r
+      [3:0]   Phase CLK ADC / APV\r
+      \r
+0xc2: [31:28] maximum number of APV frames / event (= 0x3)\r
+      [23:20] TODO hardware trigger 2\r
+      [19:16] DELAY hardware trigger 2\r
+      [15:12] TODO hardware trigger 1\r
+      [11:8]  DELAY hardware trigger 1\r
+      [7:4]   TODO hardware trigger 0\r
+      [3:0]   DELAY hardware trigger 0\r
+      \r
+0xc3: [31:24] BitHigh setting\r
+      [23:16] BitLow setting\r
+      [15:8]  FlatHigh setting\r
+      [7:0]   FlatLow setting\r
+\r
+\r
diff --git a/libtrbnet/Makefile b/libtrbnet/Makefile
new file mode 100644 (file)
index 0000000..cae868f
--- /dev/null
@@ -0,0 +1,95 @@
+AXIS_USABLE_LIBS = UCLIBC GLIBC
+include $(AXIS_TOP_DIR)/tools/build/Rules.axis
+
+#CFLAGS =  -pipe -g -ansi -pedantic -Wall 
+CFLAGS =  -pipe -g -Wall -Winline  -O3 -finline-functions -finline-limit=600000 #-DHEXMODE
+
+CPPFLAGS =
+
+INCDIR = -I.
+
+LDFLAGS =
+LIBDIR = -L.
+LOADLIBES = -ltrbnet
+
+# ------------ Libaries ------------------------------------------------
+
+AR = ar-cris
+ARFLAGS = -srv
+
+# ------------ Install -------------------------------------------------
+
+BIN.OBJS =
+LIB.OBJS =
+INC.OBJS =
+
+BIN_DIR = 
+LIB_DIR = 
+INC_DIR = 
+
+# ------------ Objects -------------------------------------------------
+
+TARGETS = trbcmd pulser
+
+trbcmd.OBJS = trbcmd.o 
+
+pulser.OBJS = pulser.o
+
+# ------------ Library-Objects ----------------------------------------
+
+LIB_TARGETS = libtrbnet.a
+
+libtrbnet.OBJS = port.o fs_fpga_int_mem.o trberror.o trbnet.o
+
+# ------------ Suffix Rules -------------------------------------------
+
+.SUFFIXES:
+
+# ----- C Code ---------
+%.o: %.c
+       $(CC) $< -c $(CPPFLAGS) $(CFLAGS) $(INCDIR) -o $@ 
+
+.SUFFIXES: .o .c 
+
+# ------------ Targets -------------------------------------------------
+
+all: $(TARGETS) $(LIB_TARGETS)
+
+trbcmd: $(trbcmd.OBJS) libtrbnet.a
+       @echo LINKING $@
+       $(CC) $(trbcmd.OBJS) $(LDFLAGS) $(LIBDIR) $(LOADLIBES) -o $@
+       @echo DONE!
+
+pulser: $(pulser.OBJS) libtrbnet.a
+       @echo LINKING $@
+       $(CC) $(pulser.OBJS) $(LDFLAGS) $(LIBDIR) $(LOADLIBES) -o $@
+       @echo DONE!
+
+libtrbnet.a: $(libtrbnet.OBJS)
+       @echo CREATING library $@
+       $(AR) $(ARFLAGS) $@ $^
+       @echo DONE!
+
+lib: $(LIB_TARGETS)
+
+distclean: clean
+       rm -f $(TARGETS) $(LIB_TARGETS)
+       rcsclean -u
+
+clean:
+       rm -f *.o core core.*
+       rcsclean
+
+# ------------ Dependencies --------------------------------------------
+
+port.o: port.h port.c
+
+fs_fpga_int_mem.o: fs_fpga_int_mem.h fs_fpga_int_mem.c port.h
+
+trberror.o: trberror.h trberror.c
+
+trbnet.o: trbnet.h trbnet.c trberror.h fs_fpga_int_mem.h port.h
+
+trbcmd.o: trbcmd.c trbnet.h port.h trberror.h fs_fpga_int_mem.h
+
+pulser.o: pulser.c trbnet.h port.h trberror.h
diff --git a/libtrbnet/fs_fpga_int_mem.c b/libtrbnet/fs_fpga_int_mem.c
new file mode 100644 (file)
index 0000000..0e38ec4
--- /dev/null
@@ -0,0 +1,69 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "fs_fpga_int_mem.h"
+
+/* clean exit when Ctrl-C is pressed */
+void ctrl_c_catched()
+{
+  close_ports();
+#if DEBUG
+  fprintf(stderr, "got ctrl-c and close gpio\n");
+#endif
+  exit(0);
+}
+
+/* writes a 32bit word to a given address on a given device */
+void write32_to_FPGA(uint16_t address, uint32_t value)
+{
+  /* set address RW_WRITE */
+  set_value_single(address & 0x7fff);
+  set_value(value);
+  writePC(0x10000);
+  writePC(0);
+}
+
+/* reads a 32bit word from a given address on a given device */
+int read32_from_FPGA(uint16_t address, uint32_t* value)
+{
+  /* set address RW_WRITE */
+  set_value_single(address | 0x8000);
+
+  *value = ((readPB() << 16));
+  writePC(0x10000);
+  writePC(0);
+  writePC(0x10000);
+  writePC(0);
+  *value |= (readPB() & 0xffff);
+  writePC(0x10000);
+  writePC(0);
+
+  return 0;
+}
+
+/* reads a 32bit word from a given address on a given device */
+int read32_from_FPGA_dma(uint16_t fifo_address,
+                         uint32_t* values, 
+                         uint32_t size)
+{
+  uint32_t tmp;
+  uint32_t *start = NULL;
+    
+  /* write maximum length to control register of fifo */
+  write32_to_FPGA(fifo_address, size);
+  
+  /* set address RW_WRITE */
+  set_value_single(fifo_address | 0x8000);
+  
+  start = values;
+  do {
+    tmp = readPB() << 16;
+    strobe();
+    strobe();  /* (will be optimized away) */
+    tmp |= (readPB() & 0xffff);
+    strobe();
+    *values++ = tmp;
+  } while(tmp & 0x01000000);
+  
+  return (values - start) - 1;
+}
diff --git a/libtrbnet/fs_fpga_int_mem.h b/libtrbnet/fs_fpga_int_mem.h
new file mode 100644 (file)
index 0000000..3081efb
--- /dev/null
@@ -0,0 +1,104 @@
+#ifndef FS_FPGA_INT_H
+#define FS_FPGA_INT_H
+
+#include <stdint.h>
+#include <port.h>
+
+#define RW_READ  1
+#define RW_WRITE 0
+
+void ctrl_c_catched();
+void write32_to_FPGA(uint16_t address, uint32_t value);
+int read32_from_FPGA(uint16_t address, uint32_t* value);
+int read32_from_FPGA_dma(uint16_t fifo_address,
+                         uint32_t* values,
+                         uint32_t size);
+
+/* rw strobe. Raises PC(16) for a short time */
+static inline void strobe()
+{
+  setbitsPC(0x10000);
+  clrbitsPC(0x10000);
+}
+
+/* sends reset for communication logic PC(17,16)=11 */
+static inline void com_reset()
+{
+  setbitsPC(0x30000);
+  clrbitsPC(0x30000);
+}
+
+/* waits until PB(16) goes high, maximum 100 cycles */
+static inline int wait_for_valid()
+{
+  unsigned int timeout = 0;
+
+#if DEBUG
+  fprintf(stderr, "is_valid PORT_B\n");
+#endif
+
+  do {
+    if ((readPB() & 0x10000) != 0) {
+      return 0;
+    }
+  } while (timeout++ < 100);
+
+  com_reset();
+#if DEBUG
+  fprintf(stderr, "Error, I didnt get 'is_valid'\n");
+#endif
+
+  return -1;
+}
+
+/* waits until PB(16) goes low, maximum 100 cycles */
+static inline int wait_for_not_valid()
+{
+  unsigned int timeout = 0;
+
+#if DEBUG
+  fprintf(stderr, "is_not_valid PORT_B\n");
+#endif
+
+  do {
+    if ((readPB() & 0x10000) == 0) {
+      return 0;
+    }
+  } while (timeout++ < 100);
+
+  com_reset();
+#if DEBUG
+  fprintf(stderr, "Error, I didnt get 'is_not_valid'\n");
+#endif
+
+  return -1;
+}
+
+/* sends two strobes, hsb then lsb of value */
+static inline void set_value(uint32_t value)
+{
+  writePC((value>>16)+0x10000);
+  writePC(0);
+  writePC((value & 0xffff) + 0x10000);
+  writePC(0);
+}
+
+/* sends one strobe, lsb of value only */
+static inline void set_value_single(uint16_t value)
+{
+  writePC(value + 0x10000);
+  writePC(0);
+}
+
+/* sends address to device, wrapper for set_value */
+static inline void set_address(uint8_t dir, uint16_t address)
+{
+
+  if (dir == RW_READ) {
+    set_value_single(address | 0x8000);
+  } else {
+    set_value_single(address & 0x7fff);
+  }
+}
+
+#endif
diff --git a/libtrbnet/port.c b/libtrbnet/port.c
new file mode 100644 (file)
index 0000000..4740ff7
--- /dev/null
@@ -0,0 +1,112 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <time.h>
+#include <sys/mman.h>
+
+#include "port.h"
+
+/* SET OE[1-read/write, 0 - only read]
+   pA - 8bits, pB,C,D,E-18bits */
+#define GPIOB_OE_PINS           0x0
+#define GPIOC_OE_PINS           0x3ffff
+#define GPIO_OFFSET             (0x1a000 / sizeof(uint32_t))
+
+volatile uint32_t* GPIO_PTR = NULL;
+volatile uint32_t* GPIOA_OUT_OFFSET = NULL;
+volatile uint32_t* GPIOA_IN_OFFSET = NULL; 
+volatile uint32_t* GPIOA_OE_OFFSET = NULL; 
+volatile uint32_t* GPIOB_OUT_OFFSET = NULL;
+volatile uint32_t* GPIOB_IN_OFFSET = NULL; 
+volatile uint32_t* GPIOB_OE_OFFSET = NULL; 
+volatile uint32_t* GPIOC_OUT_OFFSET = NULL;
+volatile uint32_t* GPIOC_IN_OFFSET = NULL; 
+volatile uint32_t* GPIOC_OE_OFFSET = NULL; 
+volatile uint32_t* GPIOD_OUT_OFFSET = NULL;
+volatile uint32_t* GPIOD_IN_OFFSET = NULL; 
+volatile uint32_t* GPIOD_OE_OFFSET = NULL; 
+volatile uint32_t* GPIOE_OUT_OFFSET = NULL;
+volatile uint32_t* GPIOE_IN_OFFSET = NULL; 
+volatile uint32_t* GPIOE_OE_OFFSET = NULL; 
+
+int init_ports()
+{
+  int memfd;
+  uint32_t *mem = NULL;
+
+  memfd = open("/dev/mem", O_RDWR);
+  if (memfd < 0) {
+    perror("Cant open memory device");
+    return -1;
+  }
+  
+  mem =  mmap((void*)0,
+              2 * 4 * 4 * 8192,
+              PROT_READ | PROT_WRITE,
+              MAP_SHARED,
+              memfd,
+              0xb0000000);
+  
+  if ((void*)mem == MAP_FAILED) {
+    perror("Error mem-map");
+    return -1;
+  }
+  
+  /* GPIO */
+  GPIO_PTR = mem + GPIO_OFFSET;
+
+  GPIOA_OUT_OFFSET = (0x00 + GPIO_PTR);
+  GPIOA_IN_OFFSET  = (0x04 / sizeof(uint32_t)) + GPIO_PTR;
+  GPIOA_OE_OFFSET  = (0x08 / sizeof(uint32_t)) + GPIO_PTR;
+  GPIOB_OUT_OFFSET = (0x20 / sizeof(uint32_t)) + GPIO_PTR;
+  GPIOB_IN_OFFSET  = (0x24 / sizeof(uint32_t)) + GPIO_PTR;
+  GPIOB_OE_OFFSET  = (0x28 / sizeof(uint32_t)) + GPIO_PTR;
+  GPIOC_OUT_OFFSET = (0x30 / sizeof(uint32_t)) + GPIO_PTR;
+  GPIOC_IN_OFFSET  = (0x34 / sizeof(uint32_t)) + GPIO_PTR;
+  GPIOC_OE_OFFSET  = (0x38 / sizeof(uint32_t)) + GPIO_PTR;
+  GPIOD_OUT_OFFSET = (0x40 / sizeof(uint32_t)) + GPIO_PTR;
+  GPIOD_IN_OFFSET  = (0x44 / sizeof(uint32_t)) + GPIO_PTR;
+  GPIOD_OE_OFFSET  = (0x48 / sizeof(uint32_t)) + GPIO_PTR;
+  GPIOE_OUT_OFFSET = (0x50 / sizeof(uint32_t)) + GPIO_PTR;
+  GPIOE_IN_OFFSET  = (0x54 / sizeof(uint32_t)) + GPIO_PTR;
+  GPIOE_OE_OFFSET  = (0x58 / sizeof(uint32_t)) + GPIO_PTR;
+  
+  close(memfd);
+  
+  /* set Output Enable */
+  /* read all bits on portB */
+  *(GPIOB_OE_OFFSET) = GPIOB_OE_PINS;
+  /* write portC[17-0] */
+  *(GPIOC_OE_OFFSET) = GPIOC_OE_PINS;
+  
+  return 0;
+}
+
+void close_ports()
+{
+  *(GPIOB_OE_OFFSET) = 0x0;
+  *(GPIOC_OE_OFFSET) = 0x0;
+  
+  GPIO_PTR = NULL;
+  GPIOA_OUT_OFFSET = NULL;
+  GPIOA_IN_OFFSET  = NULL;
+  GPIOA_OE_OFFSET  = NULL;
+  GPIOB_OUT_OFFSET = NULL;
+  GPIOB_IN_OFFSET  = NULL;
+  GPIOB_OE_OFFSET  = NULL;
+  GPIOC_OUT_OFFSET = NULL;
+  GPIOC_IN_OFFSET  = NULL;
+  GPIOC_OE_OFFSET  = NULL;
+  GPIOD_OUT_OFFSET = NULL;
+  GPIOD_IN_OFFSET  = NULL;
+  GPIOD_OE_OFFSET  = NULL;
+  GPIOE_OUT_OFFSET = NULL;
+  GPIOE_IN_OFFSET  = NULL;
+  GPIOE_OE_OFFSET  = NULL;
+}
diff --git a/libtrbnet/port.h b/libtrbnet/port.h
new file mode 100644 (file)
index 0000000..efb321a
--- /dev/null
@@ -0,0 +1,175 @@
+#ifndef PORT_H
+#define PORT_H
+
+#include <stdint.h>
+
+extern volatile uint32_t* GPIO_PTR;
+
+extern volatile uint32_t* GPIOA_OUT_OFFSET;
+extern volatile uint32_t* GPIOA_IN_OFFSET;
+extern volatile uint32_t* GPIOA_OE_OFFSET; 
+
+extern volatile uint32_t* GPIOB_OUT_OFFSET;
+extern volatile uint32_t* GPIOB_IN_OFFSET; 
+extern volatile uint32_t* GPIOB_OE_OFFSET; 
+
+extern volatile uint32_t* GPIOC_OUT_OFFSET;
+extern volatile uint32_t* GPIOC_IN_OFFSET; 
+extern volatile uint32_t* GPIOC_OE_OFFSET; 
+
+extern volatile uint32_t* GPIOD_OUT_OFFSET;
+extern volatile uint32_t* GPIOD_IN_OFFSET; 
+extern volatile uint32_t* GPIOD_OE_OFFSET; 
+
+extern volatile uint32_t* GPIOE_OUT_OFFSET;
+extern volatile uint32_t* GPIOE_IN_OFFSET; 
+extern volatile uint32_t* GPIOE_OE_OFFSET; 
+
+#define GPIO_PA 0x00
+#define GPIO_PB 0x20 / sizeof(uint32_t)
+#define GPIO_PC 0x30 / sizeof(uint32_t)
+#define GPIO_PD 0x40 / sizeof(uint32_t)
+#define GPIO_PE 0x50 / sizeof(uint32_t)
+
+int init_ports();
+void close_ports();
+
+static inline void close_ports_special(uint32_t portBOE, uint32_t portCOE)
+{
+  *GPIOB_OE_OFFSET = portBOE;
+  *GPIOC_OE_OFFSET = portCOE;
+}
+
+static inline uint32_t readPA()
+{
+  return (*GPIOA_IN_OFFSET );
+}
+
+static inline void writePA(uint8_t data)
+{
+  *GPIOA_OUT_OFFSET = data;
+}
+
+static inline void setbitsPA(uint32_t bitmask)
+{
+  *GPIOA_OUT_OFFSET |= (bitmask );
+}
+
+static inline void clrbitsPA(uint32_t bitmask)
+{
+  *GPIOA_OUT_OFFSET &= ~(bitmask );
+}
+
+
+static inline uint32_t readPB()
+{
+  return (*GPIOB_IN_OFFSET );
+}
+
+static inline void writePB(uint32_t data)
+{
+  *GPIOB_OUT_OFFSET = (data );
+}
+
+static inline void setbitsPB(uint32_t bitmask)
+{
+  *GPIOB_OUT_OFFSET |= (bitmask);
+}
+
+static inline void clrbitsPB(uint32_t bitmask)
+{
+  *GPIOB_OUT_OFFSET &= ~(bitmask);
+}
+
+
+static inline uint32_t readPC()
+{
+  return (*GPIOC_IN_OFFSET );
+}
+
+static inline void writePC(uint32_t data)
+{
+  *GPIOC_OUT_OFFSET = (data );
+}
+
+static inline void setbitsPC(uint32_t bitmask)
+{
+  *GPIOC_OUT_OFFSET |= (bitmask );
+}
+
+static inline void clrbitsPC(uint32_t bitmask)
+{
+  *GPIOC_OUT_OFFSET &= ~(bitmask);
+}
+
+static inline uint32_t readPD()
+{
+  return (*GPIOD_IN_OFFSET );
+}
+
+static inline void writePD(uint32_t data)
+{
+  *GPIOD_OUT_OFFSET = (data );
+}
+
+static inline void setbitsPD(uint32_t bitmask)
+{
+  *GPIOD_OUT_OFFSET |= (bitmask );
+}
+
+static inline void clrbitsPD(uint32_t bitmask)
+{
+  *GPIOD_OUT_OFFSET &= ~(bitmask );
+}
+
+
+static inline uint32_t readPE()
+{
+  return (*GPIOE_IN_OFFSET );
+}
+
+static inline void writePE(uint32_t data)
+{
+  *GPIOE_OUT_OFFSET = (data );
+}
+
+static inline void setbitsPE(uint32_t bitmask)
+{
+  *GPIOE_OUT_OFFSET |= (bitmask );
+}
+
+static inline void clrbitsPE(uint32_t bitmask)
+{
+  *GPIOE_OUT_OFFSET &= ~(bitmask );
+}
+
+
+static inline uint32_t readPort(uint32_t port)
+{
+  return *(GPIO_PTR + port + 4 / sizeof(uint32_t));
+}
+
+static inline void writePort(uint32_t port, uint32_t value)
+{
+  *(GPIO_PTR + port) = (value );
+}
+
+static inline void setbitsPort(uint32_t port, uint32_t bitmask)
+{
+  *(GPIO_PTR + port) |= (bitmask);
+}
+
+static inline void clrbitsPort(uint32_t port, uint32_t bitmask)
+{
+  *(GPIO_PTR + port) &= ~(bitmask);
+}
+
+static inline void microdelay(unsigned int del)
+{
+  unsigned int i;
+  unsigned int calibrated_del = del * 10;
+  for (i = 0; i < calibrated_del; i++) {
+  }
+}
+
+#endif
diff --git a/libtrbnet/pulser.c b/libtrbnet/pulser.c
new file mode 100644 (file)
index 0000000..59f0a3f
--- /dev/null
@@ -0,0 +1,145 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <limits.h>
+
+#include <libgen.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <trbnet.h>
+#include <trberror.h>
+
+#define bufferSize 16385
+
+/* ------ MAIN ---------------------------------------------------------- */
+
+static FILE *hldFile = NULL;
+static unsigned int evtCounter = 0;
+
+static void atexit0()
+{
+  if (hldFile != NULL) {
+    fclose(hldFile);
+  }
+  
+  fprintf(stderr, "%d Triggers were send\n", evtCounter);
+}
+
+static void sigHandler(int sig)
+{
+  if (sig == SIGTERM) fprintf(stderr, "caught SIGTERM\n");
+  if (sig == SIGINT) fprintf(stderr, "caught SIGINT\n");
+
+  exit(128 + sig);
+}
+
+void usage(const char *progName)
+{
+  printf("Usage: %s [-h] [-d level] [-f outFileName] [-n numEvents]\n",
+         progName);
+  printf("Options:\n");
+  printf("  -h    give this help\n");
+  printf("  -d    turn on Debugging Information\n");
+  printf("  -f    outFileName\n");
+  printf("  -n    process numEvents triggers\n");
+}
+
+int main(int argc, char ** argv)
+{
+  char hldFileName[256] = "pulser.hld";
+  uint16_t trgNumber = 0;
+  unsigned int numEvts = UINT_MAX;
+  uint32_t buffer[bufferSize];
+  sigset_t blockSet;
+  int size;
+  int writeToStdout = 0;
+  int i;
+  
+  trb_debug = 0;
+
+  /* Parse Arguments */
+  while ((i = getopt(argc, argv, "+hd:f:n:")) != -1) {
+    switch (i) {
+    case '?':
+      usage(basename(argv[0]));
+      exit(EXIT_FAILURE);
+    case 'h':
+      usage(basename(argv[0]));
+      exit(EXIT_SUCCESS);
+    case 'd':
+      trb_debug = strtoul(optarg, NULL, 0);
+      break;
+    case 'f':
+      strncpy(hldFileName, optarg, 256);
+      break;
+    case 'n':
+      numEvts = strtoul(optarg, NULL, 0);
+      break;
+    default:
+      break;
+    }
+  }
+
+  /* open port */
+  init_ports();  
+
+  /* Open HLD-File */
+  if (strncmp(hldFileName, "stdout", 256) != 0) {
+    hldFile = fopen(hldFileName, "w");
+    if (hldFile == NULL) {
+      perror("File Open");
+    }
+  } else {
+    writeToStdout = 1;
+  }
+
+  /* Set Signalhandler */
+  atexit(atexit0);
+  signal(SIGINT, sigHandler);
+  signal(SIGTERM, sigHandler);
+
+  /* Set signal mask for blocking */
+  sigemptyset(&blockSet);
+  sigaddset(&blockSet, SIGINT);
+  sigaddset(&blockSet, SIGTERM);
+
+  /* Loop Triggers */
+  while(evtCounter < numEvts) {
+    /* Block signals */
+    sigprocmask(SIG_BLOCK, &blockSet, NULL);
+    
+    /* Send Trigger and get Data */
+    if (trb_send_trigger(0, 0, 0xcc, 0xdd, 0xaabb) != -1) {
+      exit(EXIT_FAILURE);
+    }
+    
+    size = trb_ipu_data_read(0, 0xcc, 0xdd, 0xaabb, buffer, bufferSize);
+    if (size == -1) {
+      exit(EXIT_FAILURE);
+    }
+
+    if (writeToStdout == 1) {
+      fprintf(stdout, "Trigger# %d\n", trgNumber);
+      for (i = 0; i < size; i++) {
+        fprintf(stdout, "0x%08x\n", buffer[i]);
+      }
+    } else {
+      if (fwrite((void*)buffer, 4, size, hldFile) != size) {
+        perror("Writing to File failed");
+        exit(EXIT_FAILURE);
+      }
+    }
+
+    /* Unblock signals */
+    sigprocmask(SIG_UNBLOCK, &blockSet, NULL);
+    
+    trgNumber++;
+    evtCounter++;
+    if (evtCounter % 100 == 0) {
+      fprintf(stderr, "%d triggers send\n", trgNumber);
+    }
+  }
+  
+  exit(EXIT_SUCCESS);
+}
diff --git a/libtrbnet/trb.txt b/libtrbnet/trb.txt
new file mode 100644 (file)
index 0000000..cc8f334
--- /dev/null
@@ -0,0 +1,22 @@
+mboehmer load_xilix.sh  for reset
+
+adcmodule addresse: 0xfa00 oder 0x42
+lesetest: 0x8021
+schreibtest: 0x8000
+schreibtest: 0x8002
+invalid: 0x8001
+
+Blocktranfer: 0xa000 - 0xbfff lesen und schreiben
+
+#Test in Frankfurt: trb128
+
+
+# Daten Auslesen:
+#Init:
+./trbnet -d1 T 3 0 0xaa 0xbb 0x0008 
+./trbnet -d1 I 0 0xaa 0xbb 0x0008
+
+#Hier loop machen, dabei Trigger hochzaehlen, trigger = 9, 10, 11, 12, ...
+./trbnet -d1 T 0 0 0xaa 0xbb 0xtrigger
+./trbnet -d1 I 0 0xaa 0xbb 0x0trigger
+
diff --git a/libtrbnet/trbcmd.c b/libtrbnet/trbcmd.c
new file mode 100644 (file)
index 0000000..2b32427
--- /dev/null
@@ -0,0 +1,518 @@
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include <libgen.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <trbnet.h>
+#include <trberror.h>
+#include <fs_fpga_int_mem.h>
+
+#ifndef HEXMODE
+#define HEXMODE 0
+#endif
+
+static int hexMode = HEXMODE;
+
+/* ------ MAIN ---------------------------------------------------------- */
+
+void usage(const char *progName)
+{
+  printf("Usage: %s [-h] [-n number] [-d level] [-H] <COMMAND>\n", progName);
+  printf("Options:\n");
+  printf("  -h    give this help\n");
+  printf("  -n    repeat COMMAND number times, -1 = endless loop\n");
+  printf("  -d    turn on Debugging Information\n");
+  printf("        level 1: TRB_Package debugging\n");          
+  printf("        level 2: +FIFO debugging\n");                 
+  printf("  -D    FIFO DMA-Mode\n");
+  printf("  -l    lazy-mode: skip most consistency-checks of packages\n");
+  printf("  -H    hex-mode: all following arguments will be interpreted "
+         "as hexadecimal\n        numbers\n");
+  printf("Commands:\n");
+  printf("   r <trbaddress> <register>                 -> read register\n");
+  printf("   w <trbaddress> <register> <data>          -> write register\n");
+  printf("   rm <trbaddress> <register> <size> <mode>  "
+         "-> read register-memory\n");
+  printf("   wm <trbaddress> <register> <mode> <file>  "
+         "-> write to register-memory from ASCII-file ('-' = stdin)\n");
+  printf("   i <trbaddress>                            -> read unique ID\n");
+  printf("   s <uid> <endpoint> <trbaddress>           -> set trb-address\n");
+  printf("   T <input> <type> <random> <info> <number> -> trigger by "
+         "slowcontrol\n");
+  printf("   I <type> <random> <info> <number>         -> read IPU data "
+         "slowcontrol\n");
+  printf("   f <channel>                               -> flush FIFO of "
+         "channel\n");
+  printf("   R <register>                              -> "
+         "read register of the FPGA"
+         "  \n");
+  printf("   W <register> <value>                      -> "
+         "write to register of the FPGA"
+         "  \n");
+}
+
+int main(int argc, char ** argv)
+{
+  uint16_t trb_address = 0;
+  uint16_t reg_address = 0; 
+  int cmdCtr = 0;
+  int repeat = 1;
+  int i;
+  
+  trb_debug = 0;
+  trb_lazy = 0;
+
+  /* Parse Arguments */
+  while ((i = getopt(argc, argv, "+hn:d:DlH")) != -1) {
+    switch (i) {
+    case '?':
+      usage(basename(argv[0]));
+      exit(EXIT_FAILURE);
+    case 'h':
+      usage(basename(argv[0]));
+      exit(EXIT_SUCCESS);
+    case 'n':
+      repeat = strtol(optarg, NULL, 0);
+      break;
+    case 'd':
+      trb_debug = strtoul(optarg, NULL, 0);
+      break;
+    case 'D':
+      trb_dma = 1;
+      break;
+    case 'l':
+      trb_lazy = 1;
+      break;
+    case 'H':
+      hexMode = 1;
+      break;
+    default:
+      break;
+    }
+  }
+  
+  /* open port */
+  init_ports();  
+  
+  if (argc - optind < 1) {
+    usage(basename(argv[0]));
+    exit(EXIT_FAILURE);
+  }
+
+  while ((repeat == -1) || (cmdCtr++ < repeat)) {
+  if (strcmp(argv[optind], "w") == 0) {
+    
+    /*******************************************/
+    /* Register Write                          */
+    /*******************************************/
+    
+    uint32_t value = 0;
+    
+    if (argc - optind !=  4) {
+      usage(basename(argv[0]));
+      exit(EXIT_FAILURE);
+    }
+    
+    trb_address = strtoul(argv[optind + 1], NULL, hexMode == 1 ? 16 : 0);
+    reg_address = strtoul(argv[optind + 2], NULL, hexMode == 1 ? 16 : 0);
+    value = strtoul(argv[optind + 3], NULL, hexMode == 1 ? 16 : 0);
+    
+    /* DEBUG Info */
+    if (trb_debug > 0) {
+      fprintf(stderr, 
+              "Command: WRITE: trb_address: 0x%04x, reg_address: 0x%04x, "
+              "value: 0x%08x\n", 
+              trb_address, reg_address, value);
+    }
+
+    if (trb_register_write(trb_address, reg_address, value) == -1) {
+      trb_error("write failed");
+      exit(EXIT_FAILURE);
+    }
+  } else if (strcmp(argv[optind], "r") == 0) {
+
+    /*******************************************/
+    /* Register Read                           */
+    /*******************************************/
+
+    int status = 0;
+    uint32_t data[256];
+    
+    if (argc - optind != 3) {
+      usage(argv[0]);
+      exit(EXIT_FAILURE);
+    }
+    
+    trb_address = strtoul(argv[optind + 1], NULL, hexMode == 1 ? 16 : 0);
+    reg_address = strtoul(argv[optind + 2], NULL, hexMode == 1 ? 16 : 0);
+
+    /* DEBUG Info */
+    if (trb_debug > 0) {
+      fprintf(stderr, 
+              "Command: READ: trb_address: 0x%04x, "
+              "reg_address: 0x%04x\n",
+              trb_address, reg_address);
+    }
+    
+    status = trb_register_read(trb_address, reg_address, data, 256);
+    if (status == -1) {
+      trb_error("read failed");
+      exit(EXIT_FAILURE);
+    }
+    
+    for (i = 0; i < status; i += 2) {
+      fprintf(stdout, "%s%04x  %s%08x\n",
+              hexMode == 1 ? "" : "0x",
+              data[i], 
+              hexMode == 1 ? "" : "0x",
+              data[i + 1]);
+    }
+  } else if (strcmp(argv[optind], "rm") == 0) {
+    
+    /*******************************************/
+    /* Register Read Memory                    */
+    /*******************************************/
+    
+    uint32_t *data = NULL;
+    uint16_t size = 0;
+    uint8_t option = 0;
+    int status;
+    unsigned int i;
+   
+    if (argc - optind != 5) {
+      usage(argv[0]);
+      exit(EXIT_FAILURE);
+    }
+    
+    trb_address = strtoul(argv[optind + 1], NULL, hexMode == 1 ? 16 : 0);
+    reg_address = strtoul(argv[optind + 2], NULL, hexMode == 1 ? 16 : 0);
+    size = strtoul(argv[optind + 3], NULL, hexMode == 1 ? 16 : 0);
+    option = strtoul(argv[optind + 4], NULL, hexMode == 1 ? 16 : 0);
+    
+    /* DEBUG Info */
+    if (trb_debug > 0) {
+      fprintf(stderr, 
+              "Command: READ_MEM: trb_address: 0x%04x, "
+              "reg_address: 0x%04x, "
+              "size: 0x%04x, "
+              "option: %d\n",
+              trb_address, reg_address, size, option);
+    }
+    
+    if ((data = malloc(sizeof(uint32_t) * size)) == NULL) abort();
+    
+    status = 
+      trb_register_read_mem(trb_address, reg_address, option, data, size); 
+    if (status == -1) {
+      trb_error("read_mem failed");
+      if (data != NULL) free(data);
+      exit(EXIT_FAILURE);
+    }
+        
+    for (i = 0; i < status; i++) { 
+      fprintf(stdout, "%s%04x  %s%08x\n", 
+              hexMode == 1 ? "" : "0x", reg_address + i,
+              hexMode == 1 ? "" : "0x", data[i]);
+    }
+    
+    if (data != NULL) free(data);
+  } else if (strcmp(argv[optind], "wm") == 0) {
+    
+    /*******************************************/
+    /* Register Write Memory                   */
+    /*******************************************/
+    
+    FILE *file = NULL;
+    uint32_t *data = NULL;
+    unsigned int dataSize = 64; 
+    char *buffer = NULL;
+    size_t len = 0;
+    char *fileName = NULL;
+    uint8_t option = 0;
+    unsigned int size = 0;
+    int status;
+
+    if (argc - optind != 5) {
+      usage(argv[0]);
+      exit(EXIT_FAILURE);
+    }
+    
+    trb_address = strtoul(argv[optind + 1], NULL, hexMode == 1 ? 16 : 0);
+    reg_address = strtoul(argv[optind + 2], NULL, hexMode == 1 ? 16 : 0);
+    option = strtoul(argv[optind + 3], NULL, hexMode == 1 ? 16 : 0);
+    fileName = argv[optind + 4];
+    
+    /* Open inputFile and read Data into buffer */
+    if (strcmp(fileName, "-") == 0) {
+      file = stdin;
+    } else {
+      file = fopen(fileName, "r");
+      if (file == NULL) {
+        perror("Error opening file");
+        exit(EXIT_FAILURE);
+      }
+    }
+    
+    if ((data = malloc(sizeof(uint32_t) * dataSize)) == NULL) abort();
+    while (getline(&buffer, &len, file) != -1) {
+      if (size >= dataSize) {
+        dataSize += 64;
+        if ((data = realloc(data, sizeof(uint32_t) * dataSize)) == NULL) {
+          abort();
+        }
+      }
+      data[size++] = strtoul(buffer, NULL, hexMode == 1 ? 16 : 0);
+    }
+    if (buffer != NULL) free(buffer);
+    
+    /* DEBUG Info */
+    if (trb_debug > 0) {
+      fprintf(stderr, 
+              "Command: WRITE_MEM: trb_address: 0x%04x, "
+              "reg_address: 0x%04x, "
+              "option: %d, "
+              "size: 0x%04x\n",
+              trb_address, reg_address, option, size);
+    }
+
+    status = trb_register_write_mem(trb_address, reg_address, option, 
+                                  data, size);
+    if (data != NULL) free(data);
+    
+    if (status == -1) {
+      trb_error("write register-memory failed");
+      exit(EXIT_FAILURE);
+    }
+  } else if (strcmp(argv[optind], "i") == 0) {
+
+    /*******************************************/
+    /* ReadUId                                 */
+    /*******************************************/
+    
+    uint32_t uidBuffer[128];
+    unsigned int size;
+    
+    if (argc - optind != 2) {
+      usage(argv[0]);
+      exit(EXIT_FAILURE);
+    }
+    
+    trb_address = strtoul(argv[optind + 1], NULL, hexMode == 1 ? 16 : 0);
+    
+    /* DEBUG Info */
+    if (trb_debug > 0) {
+      fprintf(stderr, 
+              "Command: READ_UID: trb_address: 0x%04x\n",
+              trb_address);
+    }
+    
+    size = trb_read_uid(trb_address, uidBuffer, 128);
+    if (size == -1) {
+      trb_error("read_uid failed");
+      exit(EXIT_FAILURE);
+    }
+    for (i = 0; (i < size) && (i < 128); i += 3) {
+      fprintf(stdout, "%s%08x%08x  %s%02x\n",
+              hexMode == 1 ? "" : "0x",
+              uidBuffer[i], 
+              uidBuffer[i + 1], 
+              hexMode == 1 ? "" : "0x",
+              uidBuffer[i + 2]);
+    }
+  } else if (strcmp(argv[optind], "s") == 0) {
+    
+    /*******************************************/
+    /* SetAddress                              */
+    /*******************************************/
+    
+    uint64_t uid = 0;
+    uint8_t endpoint = 0;
+    uint16_t trb_address = 0;
+    
+    if (argc - optind != 4) {
+      usage(argv[0]);
+      exit(EXIT_FAILURE);
+    }
+    
+    uid = strtoull(argv[optind + 1], NULL, hexMode == 1 ? 16 : 0);
+    endpoint = strtoul(argv[optind + 2], NULL, hexMode == 1 ? 16 : 0);
+    trb_address = strtoul(argv[optind + 3], NULL, hexMode == 1 ? 16 : 0);
+    
+    /* DEBUG Info */
+    if (trb_debug > 0) {
+      fprintf(stderr, 
+              "Command: SET_ADDRESS: "
+              "uid: 0x%016llx, "
+              "endpoint: 0x%02x, "
+              "trb_address: 0x%04x\n",
+              uid, endpoint, trb_address);
+    }
+    
+    if (trb_set_address(uid, endpoint, trb_address) == -1) {
+      trb_error("set_address failed");
+      exit(EXIT_FAILURE);
+    }
+  } else if (strcmp(argv[optind], "T") == 0) {
+    
+    /*******************************************/
+    /* Fake trigger function (ADCM specific)   */
+    /*******************************************/
+    
+    uint8_t input = 0;
+    uint8_t type = 0;
+    uint8_t random = 0;
+    uint8_t info = 0;
+    uint16_t number = 0;
+    
+    if (argc - optind != 6) {
+      usage(argv[0]);
+      exit(EXIT_FAILURE);
+    }
+    
+    input = strtoul(argv[optind + 1], NULL, hexMode == 1 ? 16 : 0) & 0x03;
+    type = strtoul(argv[optind + 2], NULL, hexMode == 1 ? 16 : 0) & 0x0f;
+    random = strtoul(argv[optind + 3], NULL, hexMode == 1 ? 16 : 0);
+    info = strtoul(argv[optind + 4], NULL, hexMode == 1 ? 16 : 0);
+    number = strtoul(argv[optind + 5], NULL, hexMode == 1 ? 16 : 0);
+    
+    /* DEBUG Info */
+    if (trb_debug > 0) {
+      fprintf(stderr, 
+              "Command: SEND_TRIGGER: "
+              "input: 0x%01x, "
+              "type: 0x%01x, "
+              "random: 0x%02x, "
+              "info: 0x%02x, "
+              "number: 0x%04x\n",
+              input, type, random, info, number);
+    }
+    
+    if (trb_send_trigger(input, type, info, random, number) == -1) {
+      trb_error("send trigger failed");
+      exit(EXIT_FAILURE);
+    }
+  } else if (strcmp(argv[optind], "I") == 0) {
+    
+    /*******************************************/
+    /* IPU channel readout                     */
+    /*******************************************/
+    
+    uint32_t buffer[4096];
+    uint8_t type = 0;
+    uint8_t random = 0;
+    uint8_t info = 0;
+    uint16_t number = 0;
+    int size = 0;
+
+    if (argc - optind != 5) {
+      usage(argv[0]);
+      exit(EXIT_FAILURE);
+    }
+    
+    type = strtoul(argv[optind + 1], NULL, hexMode == 1 ? 16 : 0) & 0x0f;
+    random = strtoul(argv[optind + 2], NULL, hexMode == 1 ? 16 : 0);
+    info = strtoul(argv[optind + 3], NULL, hexMode == 1 ? 16 : 0);
+    number = strtoul(argv[optind + 4], NULL, hexMode == 1 ? 16 : 0);
+    
+    /* DEBUG Info */
+    if (trb_debug > 0) {
+      fprintf(stderr, 
+              "Command: READ_IPU_DATA: "
+              "type: 0x%01x, "
+              "random: 0x%02x, "
+              "info: 0x%02x, "
+              "number: 0x%04x\n",
+              type, random, info, number);
+    }
+    size = trb_ipu_data_read(type, info, random, number, buffer, 4096);
+    if (size == -1) {
+      trb_error("ipu read data failed");
+      exit(EXIT_FAILURE);
+    }
+    
+    for (i = 0; i < size; i++) {
+      fprintf(stdout, "0x%08x\n", buffer[i]);
+    }
+  } else if (strcmp(argv[optind], "f") == 0) {
+    
+    /*******************************************/
+    /* Flush FIFO Channel                      */
+    /*******************************************/
+    
+    int status;
+    uint8_t channel = 0;
+    
+    if (argc - optind != 2) {
+      usage(argv[0]);
+      exit(EXIT_FAILURE);
+    }
+    
+    channel = strtoul(argv[optind + 1], NULL, hexMode == 1 ? 16 : 0);
+    if (trb_debug > 0) {
+      fprintf(stderr, "Command: FIFO_FLUSH_CHANNEL #%d\n", channel);
+    }
+    
+    status = trb_fifo_flush(channel);
+    if (status == -1) {
+      trb_error("flush channel failed");
+      exit(EXIT_FAILURE);
+    }
+  } else if (strcmp(argv[optind], "R") == 0) {
+    
+    /*******************************************/
+    /* Read FIFO Register                      */
+    /*******************************************/
+    
+    uint32_t value = 0;
+    uint16_t reg_address = 0;
+    
+    if (argc - optind != 2) {
+      usage(argv[0]);
+      exit(EXIT_FAILURE);
+    }
+    reg_address = strtoul(argv[optind + 1], NULL, hexMode == 1 ? 16 : 0);
+    
+    read32_from_FPGA(reg_address, &value);
+    fprintf(stdout, "%s%04x  %s%04x\n", 
+            hexMode == 1 ? "" : "0x", reg_address,
+            hexMode == 1 ? "" : "0x", value);
+  
+  } else if (strcmp(argv[optind], "W") == 0) {
+    
+    /*******************************************/
+    /* Write FIFO Register                     */
+    /*******************************************/
+    
+    uint32_t value = 0;
+    uint16_t reg_address = 0;
+    
+    if (argc - optind != 3) {
+      usage(argv[0]);
+      exit(EXIT_FAILURE);
+    }
+    reg_address = strtoul(argv[optind + 1], NULL, hexMode == 1 ? 16 : 0);
+    value = strtoul(argv[optind + 2], NULL, hexMode == 1 ? 16 : 0);
+   
+    write32_to_FPGA(reg_address, value);
+    
+    /*
+      fprintf(stdout, "%s%04x  %s%04x\n", 
+            hexMode == 1 ? "" : "0x", reg_address,
+            hexMode == 1 ? "" : "0x", value);
+    */
+  } else {
+    usage(argv[0]);
+    exit(EXIT_FAILURE);
+  }
+
+
+  } /* end repeat loop */ 
+
+  exit(EXIT_SUCCESS);
+}
diff --git a/libtrbnet/trberror.c b/libtrbnet/trberror.c
new file mode 100644 (file)
index 0000000..ef6bb1d
--- /dev/null
@@ -0,0 +1,140 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "trberror.h"
+
+/* Error Handling */
+
+int trb_errno = TRB_NONE;
+uint64_t trb_statusbits = 0;
+
+void trb_error(const char *s)
+{
+  if (s != NULL) {
+    fprintf(stderr, "%s: %s\n", s, trb_strerror(trb_errno));
+  } else {
+    fprintf(stderr, "%s\n", trb_strerror(trb_errno));
+  }
+  
+  /* Print Statusbits */
+  if (trb_errno == TRB_TERM_ERRBIT) {
+    fprintf(stderr, "%s\n", trb_statusbits_str(trb_statusbits));
+  }
+}
+
+const char* trb_strerror(int errno)
+{
+  static const char errorstring[][80] = {
+    "No Error",
+    "TX Busy",
+    "FIFO Not Empty",
+    "FIFO Timeout",
+    "FIFO Error, invalid H0 header(s)",
+    "FIFO Error, invalid sequenze-number",
+    "FIFO Error, invalid read-data-mode",
+    "FIFO Broken-Package",
+    "FIFO Invalid-Content (no TERMINATION)",
+    "FAILED WAIT_IS_VALID",
+    "FAILED WAIT_IS_NOT_VALID",
+    "User-Buffer Overflow",
+    "Invalid Channel",
+    "Invalid number of Packages returned",
+    "TERMINATION ErrorBit(s) set",
+    "Invalid TRB-Address",
+    "Invalid Data-Buffer Length",
+    "Endpoint not reached"
+  };
+  
+  if (errno < 18) {
+    return errorstring[errno];
+  } else {
+    return "Unknown Errno";
+  }
+}
+
+const char* trb_statusbits_str(uint64_t statusbits)
+{
+  static const char commonStatusBits[16][64] = {
+    "Endpoint not reached",        
+    "Coll: collision detected",
+    "WordMiss: word missing",
+    "Checksum: checksum error",
+    "DontKnow: dont understand",
+    "BufferMatch: buffer mismatch",
+    "", "", "", "", "", "", "", "", "", ""
+  };
+  
+  static const char ch0StatusBits[16][64] = {
+    "Ch0_TrigCtr: trigger counter mismatch", 
+    "",
+    "",
+    "",
+    "Ch0_BufferHalfFull: data-buffers half full",
+    "Ch0_BuffersFull: data-buffers almost full"
+    "", "", "", "", "", "", "", "", "", ""
+  };
+  
+  static const char ch1StatusBits[16][64] = {
+    "Ch1_TrigNum: trigger number mismatch", 
+    "Ch1_TrigCode: trigger code / random mismatch",
+    "Ch1_Length: wrong length",
+    "Ch1_NoAnswer: answer missing",
+    "",
+    "",
+    "",
+    "",
+    "Ch1_NotFound: not found"
+    "", "", "", "", "", "", "", ""
+  };
+
+  static const char ch2StatusBits[16][64] = {
+    "", "", "", "", "", "", "", "",
+    "", "", "", "", "", "", "", ""
+  };
+  
+  static const char ch3StatusBits[16][64] = {
+    "Ch3_Address: unknown address",
+    "Ch3_TimeOut: timeout error",
+    "Ch3_NoData: no more data"
+    "", "", "", "", "", "", "", "", "", "", "", "", ""
+  };
+  
+  static const char *chStatusBits[4] = {
+    &ch0StatusBits[0][0],
+    &ch1StatusBits[0][0],
+    &ch2StatusBits[0][0],
+    &ch3StatusBits[0][0]
+  };
+  
+  static char buffer[2048] = "";
+  unsigned int i;
+  uint8_t channel = (statusbits & 0x700000000LL) >> 32;
+  
+  if (channel >= 4) {
+    snprintf(buffer, 2048, "INVALID ChannelId %d", channel);
+    return buffer;
+  }
+  
+  snprintf(buffer, 2048, 
+           "CommonStatusBits: 0x%04x, Channel#%d StatusBits: 0x%04x\n", 
+           (uint16_t)(statusbits & 0x0000ffffLL), 
+           channel, 
+           (uint16_t)((statusbits & 0xffff0000LL) >> 16));
+  for (i = 0; i < 16; i++) {
+    if (((statusbits & 0xffffLL) & (0x01LL << i)) != (i != 0 ? 0 : 1)) {
+      strncat(buffer, "   ", 2048);
+      strncat(buffer, commonStatusBits[i], 2048); 
+      strncat(buffer, "\n", 2048);
+    }
+  }
+  for (i = 0; i < 16; i++) {
+    if ((((statusbits & 0xffff0000LL) >> 16) & (0x01LL << i)) != 0) {
+      strncat(buffer, "   ", 2048);
+      strncat(buffer, chStatusBits[channel] + 64 * i, 2048);
+      strncat(buffer, "\n", 2048);
+    }
+  }
+  
+  return buffer;
+}
diff --git a/libtrbnet/trberror.h b/libtrbnet/trberror.h
new file mode 100644 (file)
index 0000000..bf75584
--- /dev/null
@@ -0,0 +1,37 @@
+#ifndef TRBERROR_H
+#define TRBERROR_H
+
+#include <stdint.h>
+
+typedef enum {
+  TRB_NONE = 0,
+  TRB_TX_BUSY = 1,
+  TRB_FIFO_NOT_EMPTY = 2,
+  TRB_FIFO_TIMEOUT = 3,
+  TRB_FIFO_HEADERS = 4,
+  TRB_FIFO_SEQUENZ = 5,
+  TRB_FIFO_INVALID_MODE = 6,
+  TRB_FIFO_BROKEN_PACKAGE = 7,
+  TRB_FIFO_INVALID_CONTENT = 8,
+  TRB_FAILED_WAIT_IS_VALID = 9,
+  TRB_FAILED_WAIT_IS_NOT_VALID = 10,
+  TRB_USER_BUFFER_OVF = 11,
+  TRB_INVALID_CHANNEL = 12,
+  TRB_INVALID_PKG_NUMBER = 13,
+  TRB_TERM_ERRBIT = 14,
+  TRB_INVALID_ADDRESS = 15,
+  TRB_INVALID_LENGTH = 16,
+  TRB_ENDPOINT_NOT_REACHED = 17
+} TRB_ERROR;
+
+extern int trb_errno;
+
+extern uint64_t trb_statusbits;
+
+void trb_error(const char *s);
+
+const char* trb_strerror(int errno);
+
+const char* trb_statusbits_str(uint64_t statusbits);
+
+#endif
diff --git a/libtrbnet/trbnet.c b/libtrbnet/trbnet.c
new file mode 100644 (file)
index 0000000..120624e
--- /dev/null
@@ -0,0 +1,1076 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <fs_fpga_int_mem.h>
+#include <trberror.h>
+
+#include "trbnet.h"
+
+/* TRBNet Header word definitions */
+#define SHIFT_HEADER_TYPE    0x0000
+#define MASK_HEADER_TYPE     (0x0007 << SHIFT_HEADER_TYPE)
+#define SHIFT_HEADER_REPLY   0x0003
+#define MASK_HEADER_REPLY    (0x0001 << SHIFT_HEADER_REPLY)
+#define SHIFT_HEADER_CHANNEL 0x0004
+#define MASK_HEADER_CHANNEL  (0x0003 << SHIFT_HEADER_CHANNEL)
+
+/* TRBNet Header types */
+#define HEADER_DAT           0x0000
+#define HEADER_HDR           0x0001
+#define HEADER_EOB           0x0002
+#define HEADER_TRM           0x0003
+#define HEADER_EXT           0x0004
+#define HEADER_ACK           0x0005
+#define HEADER_SIG           0x0006
+#define HEADER_ILL           0x0007
+
+/* Header Word definitions */
+#define SHIFT_SEQNR          4
+#define MASK_SEQNR           (0xff << SHIFT_SEQNR)
+#define SHIFT_DATATYPE       0
+#define MASK_DATATYPE        (0xf << SHIFT_DATATYPE)
+
+/* FIFO Masks */
+#define SHIFT_FIFO_VALID     24
+#define MASK_FIFO_VALID      (0x1 << SHIFT_FIFO_VALID)
+#define SHIFT_FIFO_TYPE      16
+#define MASK_FIFO_TYPE       (0x3 << SHIFT_FIFO_TYPE)
+
+/* FIFO Types */
+#define FIFO_TYPE_IS_HEADER  2
+
+/* FIFO STATUS definitions */
+#define MASK_FIFO_FULL       (0x01 << 16)
+#define MASK_FIFO_EMPTY      (0x01 << 17)
+#define MASK_FIFO_LEVEL      0x03ff
+
+/* Channel Registers */
+
+/* Registers inside Virtex FPGA -> TRBnet endpoint (channel N) */
+#define CHANNEL_N_START_WRITE            0x0100
+#define CHANNEL_N_TARGET_ADDRESS         0x0101
+#define CHANNEL_N_SENDER_ERROR           0x0102
+#define CHANNEL_N_SENDER_DATA            0x0103
+#define CHANNEL_N_SENDER_FIFO_STATUS     0x0104
+#define CHANNEL_N_SENDER_STATUS          0x010f
+#define CHANNEL_N_RECEIVER_DATA          0x0203
+#define CHANNEL_N_RECEIVER_FIFO_STATUS   0x0204 
+#define CHANNEL_N_API_STATUS             0x0300
+
+/* Registers inside Virtex FPGA -> TRBnet endpoint (channel 0) */
+#define CHANNEL_0_SENDER_CONTROL         0x0110
+#define CHANNEL_0_TARGET_ADDRESS         0x0111
+#define CHANNEL_0_SENDER_ERROR           0x0112
+#define CHANNEL_0_SENDER_DATA            0x0113
+#define CHANNEL_0_SENDER_FIFO_STATUS     0x0114
+#define CHANNEL_0_SENDER_STATUS          0x011f
+#define CHANNEL_0_RECEIVER_DATA          0x0213
+#define CHANNEL_0_RECEIVER_FIFO_STATUS   0x0214 
+#define CHANNEL_0_API_STATUS             0x0310
+
+/* Registers inside Virtex FPGA -> TRBnet endpoint (channel 1) */
+#define CHANNEL_1_SENDER_CONTROL         0x0130
+#define CHANNEL_1_TARGET_ADDRESS         0x0131
+#define CHANNEL_1_SENDER_ERROR           0x0132
+#define CHANNEL_1_SENDER_DATA            0x0133
+#define CHANNEL_1_SENDER_FIFO_STATUS     0x0134
+#define CHANNEL_1_SENDER_STATUS          0x013f
+#define CHANNEL_1_RECEIVER_DATA          0x0233
+#define CHANNEL_1_RECEIVER_FIFO_STATUS   0x0234 
+#define CHANNEL_1_API_STATUS             0x0330
+
+/* Registers inside Virtex FPGA -> TRBnet endpoint (channel 2) */
+#define CHANNEL_2_SENDER_CONTROL         0x0150
+#define CHANNEL_2_TARGET_ADDRESS         0x0151
+#define CHANNEL_2_SENDER_ERROR           0x0152
+#define CHANNEL_2_SENDER_DATA            0x0153
+#define CHANNEL_2_SENDER_FIFO_STATUS     0x0154
+#define CHANNEL_2_SENDER_STATUS          0x015f
+#define CHANNEL_2_RECEIVER_DATA          0x0253
+#define CHANNEL_2_RECEIVER_FIFO_STATUS   0x0254 
+#define CHANNEL_2_API_STATUS             0x0350
+
+/* Registers inside Virtex FPGA -> TRBnet endpoint (channel 3) */
+#define CHANNEL_3_SENDER_CONTROL         0x0170
+#define CHANNEL_3_TARGET_ADDRESS         0x0171
+#define CHANNEL_3_SENDER_ERROR           0x0172
+#define CHANNEL_3_SENDER_DATA            0x0173
+#define CHANNEL_3_SENDER_FIFO_STATUS     0x0174
+#define CHANNEL_3_SENDER_STATUS          0x017f
+#define CHANNEL_3_RECEIVER_DATA          0x0273
+#define CHANNEL_3_RECEIVER_FIFO_STATUS   0x0274 
+#define CHANNEL_3_API_STATUS             0x0370
+
+/* SENDER_STATUS definitions */             
+#define MASK_TX_RUNNING                  0x00000001
+
+/* Commands supported for packages */
+#define CMD_REGISTER_READ                0x08
+#define CMD_REGISTER_READ_MEM            0x0a
+#define CMD_REGISTER_WRITE               0x09
+#define CMD_REGISTER_WRITE_MEM           0x0b
+#define CMD_NETADMINISTRATION            0x0f
+
+/* Network administration commands */
+#define NET_READUNIQUEID                 0x5e1d
+#define NET_SETADDRESS                   0x5ead
+#define NET_ACKADDRESS                   0xacad
+#define SHORT_TRANSFER                   0x0100
+
+/* Other  */
+#define MAX_TIME_OUT                     500
+#define DATA_BUFFER_SIZE                 8192
+
+
+/* ---------------------------------------------------------------------- */
+
+unsigned int trb_debug = 0;
+unsigned int trb_lazy = 0;
+unsigned int trb_dma = 0;
+
+/* Declaration of a TRB-Package */
+
+typedef struct {
+  uint16_t H0;
+  uint16_t F0;
+  uint16_t F1;
+  uint16_t F2;
+  uint16_t F3;
+} TRB_Package;
+
+/* Status-Bit definitions */
+
+typedef enum {
+  Status_C_EndReached = 0,               /* endpoint reached     */       
+  Status_C_Coll = 1,                     /* collision detected,  */
+  Status_C_WordMiss = 2,                 /* word missing,        */
+  Status_C_Checksum = 3,                 /* checksum error,      */
+  Status_C_DontKnow = 4,                 /* dont understand,     */
+  Status_C_BufferMatch = 5               /* buffer mismatch      */
+} Status_Common;
+
+typedef enum {
+  Status_Ch0_TrigCtr = 0,                /* trigger counter mismatch */ 
+  Status_Ch0_BufferHalfFull = 4,         /* buffers half full        */
+  Status_Ch0_BuffersFull = 5             /* buffers almost full      */
+} Status_CH0;
+
+typedef enum {
+  Status_Ch1_TrigNum = 0,                /* trigger number mismatch         */ 
+  Status_Ch1_TrigCode = 1,               /* trigger code / random mismatch  */
+  Status_Ch1_Length  = 2,                /* wrong length                    */
+  Status_Ch1_NoAnswer = 3,               /* answer missing                  */
+  Status_Ch1_NotFound = 8                /* not found                       */
+} Status_CH1;
+
+typedef enum {
+  Status_Ch2_NONE = 0
+} Status_CH2;
+
+typedef enum {
+  Status_Ch3_Address = 0,                /* unknown address             */ 
+  Status_Ch3_TimeOut = 4,                /* timeout                     */
+  Status_Ch3_NoData = 5                  /* nomoredata                  */
+} Status_CH3;
+
+/* ------ Internal Functions -------------------------------------------- */
+
+static void TRB_Package_dump(const TRB_Package* pkg)
+{
+  switch ((pkg->H0 & MASK_HEADER_TYPE) >> SHIFT_HEADER_TYPE) {
+  case HEADER_DAT:
+    fprintf(stderr, "H0: 0x%04x --> DATA    channel: %01d reply: %01d\n",
+            pkg->H0,
+            (pkg->H0 & MASK_HEADER_CHANNEL) >> SHIFT_HEADER_CHANNEL,
+            (pkg->H0 & MASK_HEADER_REPLY) >> SHIFT_HEADER_REPLY);
+    fprintf(stderr, "F0: 0x%04x --> data0\n", pkg->F0);
+    fprintf(stderr, "F1: 0x%04x --> data1\n", pkg->F1);
+    fprintf(stderr, "F2: 0x%04x --> data2\n", pkg->F2);
+    fprintf(stderr, "F3: 0x%04x --> data3\n", pkg->F3);
+    break;
+    
+  case HEADER_HDR:
+    fprintf(stderr, "H0: 0x%04x --> HEADER  channel: %01d reply: %01d\n",
+            pkg->H0,
+            (pkg->H0 & MASK_HEADER_CHANNEL) >> SHIFT_HEADER_CHANNEL,
+            (pkg->H0 & MASK_HEADER_REPLY) >> SHIFT_HEADER_REPLY);
+    fprintf(stderr, "F0: 0x%04x --> source address\n", pkg->F0);
+    fprintf(stderr, "F1: 0x%04x --> target address\n", pkg->F1);
+    fprintf(stderr, "F2: 0x%04x --> reserved\n", pkg->F2);
+    fprintf(stderr, "F3: 0x%04x --> sequence: 0x%02x datatype: 0x%01x\n", 
+            pkg->F3,
+            (pkg->F3 & MASK_SEQNR) >> SHIFT_SEQNR,
+            (pkg->F3 & MASK_DATATYPE) >> SHIFT_DATATYPE);
+    break;
+    
+  case HEADER_EOB:
+    fprintf(stderr, "H0: 0x%04x --> EOB     channel: %01d reply: %01d\n",
+            pkg->H0,
+            (pkg->H0 & MASK_HEADER_CHANNEL) >> SHIFT_HEADER_CHANNEL,
+            (pkg->H0 & MASK_HEADER_REPLY) >> SHIFT_HEADER_REPLY);
+    fprintf(stderr, "F0: 0x%04x --> checksum\n", pkg->F0);
+    fprintf(stderr, "F1: 0x%04x --> reseved\n", pkg->F1);
+    fprintf(stderr, "F2: 0x%04x --> data count\n", pkg->F2);
+    fprintf(stderr, "F3: 0x%04x --> buffer number\n", pkg->F3);
+    break;
+  
+  case HEADER_TRM:
+    fprintf(stderr, "H0: 0x%04x --> TERM    channel: %01d reply: %01d\n",
+            pkg->H0,
+            (pkg->H0 & MASK_HEADER_CHANNEL) >> SHIFT_HEADER_CHANNEL,
+            (pkg->H0 & MASK_HEADER_REPLY) >> SHIFT_HEADER_REPLY);
+    fprintf(stderr, "F0: 0x%04x --> checksum\n", pkg->F0);
+    fprintf(stderr, "F1: 0x%04x --> statusbits channel\n", pkg->F1);
+    fprintf(stderr, "F2: 0x%04x --> statusbits common\n", pkg->F2);
+    fprintf(stderr, "F3: 0x%04x --> sequence: 0x%02x datatype: 0x%01x\n", 
+            pkg->F3,
+            (pkg->F3 & MASK_SEQNR) >> SHIFT_SEQNR,
+            (pkg->F3 & MASK_DATATYPE) >> SHIFT_DATATYPE);
+    break;
+
+  case HEADER_EXT:
+    fprintf(stderr, "H0: 0x%04x --> EXT     channel: %01d reply: %01d\n",
+            pkg->H0,
+            (pkg->H0 & MASK_HEADER_CHANNEL) >> SHIFT_HEADER_CHANNEL,
+            (pkg->H0 & MASK_HEADER_REPLY) >> SHIFT_HEADER_REPLY);
+    fprintf(stderr, "F0: 0x%04x --> reserved\n", pkg->F0);
+    fprintf(stderr, "F1: 0x%04x --> reserved\n", pkg->F1);
+    fprintf(stderr, "F2: 0x%04x --> reserved\n", pkg->F2);
+    fprintf(stderr, "F2: 0x%04x --> reserved\n", pkg->F3);
+    break;
+    
+  case HEADER_ACK:
+    fprintf(stderr, "H0: 0x%04x --> ACK     channel: %01d reply: %01d\n",
+            pkg->H0,
+            (pkg->H0 & MASK_HEADER_CHANNEL) >> SHIFT_HEADER_CHANNEL,
+            (pkg->H0 & MASK_HEADER_REPLY) >> SHIFT_HEADER_REPLY);
+    fprintf(stderr, "F0: 0x%04x --> reserved\n", pkg->F0);
+    fprintf(stderr, "F1: 0x%04x --> lenght of buffer\n", pkg->F1);
+    fprintf(stderr, "F2: 0x%04x --> reserved\n", pkg->F2);
+    fprintf(stderr, "F2: 0x%04x --> buffer number\n", pkg->F3);
+    break;
+
+  case HEADER_SIG:
+    fprintf(stderr, "H0: 0x%04x --> SIGNAL  channel: %01d reply: %01d\n",
+            pkg->H0,
+            (pkg->H0 & MASK_HEADER_CHANNEL) >> SHIFT_HEADER_CHANNEL,
+            (pkg->H0 & MASK_HEADER_REPLY) >> SHIFT_HEADER_REPLY);
+    fprintf(stderr, "F0: 0x%04x --> reserved\n", pkg->F0);
+    fprintf(stderr, "F1: 0x%04x --> reserved\n", pkg->F1);
+    fprintf(stderr, "F2: 0x%04x --> reserved\n", pkg->F2);
+    fprintf(stderr, "F2: 0x%04x --> reserved\n", pkg->F3);
+    break;
+
+  case HEADER_ILL:
+    fprintf(stderr, "H0: 0x%04x --> ILLEGAL channel: %01d reply: %01d\n",
+            pkg->H0,
+            (pkg->H0 & MASK_HEADER_CHANNEL) >> SHIFT_HEADER_CHANNEL,
+            (pkg->H0 & MASK_HEADER_REPLY) >> SHIFT_HEADER_REPLY);
+    fprintf(stderr, "F0: 0x%04x --> ignore\n", pkg->F0);
+    fprintf(stderr, "F1: 0x%04x --> ignore\n", pkg->F1);
+    fprintf(stderr, "F2: 0x%04x --> ignore\n", pkg->F2);
+    fprintf(stderr, "F2: 0x%04x --> ignore\n", pkg->F3);
+    break;
+    
+  default:
+    fprintf(stderr, "INVALID\n");
+  }
+}
+
+static int trb_wait_tx_not_busy(uint8_t channel)
+{
+  uint32_t tmp = 0;
+  unsigned int timeout = 0;
+  
+  if (channel >= 4) {
+    trb_errno = TRB_INVALID_CHANNEL;
+    return -1;
+  }
+  
+  while (timeout < MAX_TIME_OUT) {
+    read32_from_FPGA(CHANNEL_N_SENDER_STATUS | ((channel * 2 + 1) << 4), &tmp);
+    if ((tmp & MASK_TX_RUNNING) == 0) {
+      return 0;
+    }
+    timeout++;
+  }
+  
+  /* timeout occurred */
+  trb_errno = TRB_TX_BUSY;
+  return -1;
+}
+
+static int trb_init_transfer(uint8_t channel)
+{
+  uint32_t tmp = 0;
+
+  if (channel >= 4) {
+    trb_errno = TRB_INVALID_CHANNEL;
+    return -1;
+  }
+  
+  /* Check for TX not Busy, wait MAX_TIMEOUT */
+  if (trb_wait_tx_not_busy(3) == -1) {
+    return -1;
+  }
+  
+  /* Check receiver FIFO empty*/
+  read32_from_FPGA(CHANNEL_N_RECEIVER_FIFO_STATUS | ((channel * 2 + 1) << 4),
+                   &tmp);
+  if ((tmp & MASK_FIFO_EMPTY) == 0) {
+    trb_errno = TRB_FIFO_NOT_EMPTY;
+    /* clear fifo ???*/
+    return -1;
+  }
+  
+  /* No Errors */
+  return 0;
+}
+
+enum FIFO_READ_MODE {
+  FIFO_MODE_NONE,
+  FIFO_MODE_REG_READ,
+  FIFO_MODE_REG_READ_MEM,
+  FIFO_MODE_REG_WRITE,
+  FIFO_MODE_IPU_DATA,
+  FIFO_MODE_UID,
+  FIFO_MODE_SET_ADDRESS
+};
+
+static int trb_fifo_read(uint8_t channel,
+                         int mode,
+                         uint32_t data[],
+                         unsigned int size)
+{
+  static uint32_t dataBuffer[DATA_BUFFER_SIZE];
+  uint32_t *tmp = dataBuffer;
+  int dma_size;
+  
+  TRB_Package package;
+  int headerType = 0;
+  uint32_t fifoBuffer = 0;
+  unsigned int counter = 0;
+  unsigned int dataCtr = 0;
+  int packageCtr = -1;
+  unsigned int endPointCtr = 0; 
+    
+  unsigned int timeout = 0;  
+  
+  /* Determin FIFO-Address */
+  if (channel >= 4) {
+    trb_errno = TRB_INVALID_CHANNEL;
+    return -1;
+  }
+  fifoBuffer = CHANNEL_N_RECEIVER_DATA | ((channel * 2 + 1) << 4);
+  
+  /* Check for FIFO Ready */
+  timeout = 0;
+  
+  if (trb_dma == 1) {
+    /* DMA-Readout */
+    do {
+      dma_size = 
+        read32_from_FPGA_dma(fifoBuffer, tmp, DATA_BUFFER_SIZE); 
+    } while ((dma_size == 0) && (++timeout < MAX_TIME_OUT));
+  } else {
+    /* Standard */
+    do {
+      read32_from_FPGA(fifoBuffer, tmp);
+    } while (((*tmp & MASK_FIFO_VALID) == 0) && (++timeout < MAX_TIME_OUT));
+  }
+  
+  if (timeout >= MAX_TIME_OUT) { 
+    trb_errno = TRB_FIFO_TIMEOUT;
+    return -1;
+  }
+  
+  /* Read FIFO-Buffer, copy to User-Buffer */
+  while ((*tmp & MASK_FIFO_VALID) != 0) {
+    if (((*tmp & MASK_FIFO_TYPE) >> SHIFT_FIFO_TYPE)
+        == FIFO_TYPE_IS_HEADER) {
+      if ((counter % 5) == 0) {
+        /* New Package begins */
+        if (trb_debug > 0) {
+          fprintf(stderr,
+                  "-------------------------------------------------\n");
+        }
+        packageCtr++;
+        counter = 0;
+      } else {
+        /* Error: invalid buffer content, flush FIFO-BUFFER and exit */
+        trb_fifo_flush(channel);
+        trb_errno = TRB_FIFO_BROKEN_PACKAGE;
+        return -1;
+      }
+    } else {
+      /* Data Word */
+      if ((trb_lazy == 0) && 
+          (((*tmp & MASK_FIFO_TYPE) >> SHIFT_FIFO_TYPE) !=
+           (counter - 1) % 2)) {
+        /* Error: invalid sequence (not 0, 1, .), flush FIFO-BUFFER and exit */
+        trb_fifo_flush(channel);
+        trb_errno = TRB_FIFO_BROKEN_PACKAGE; 
+        return -1;
+      }
+    }
+    
+    switch (counter) {
+    case 0:
+      package.H0 = *tmp;
+      break;
+    case 1:
+      package.F0 = *tmp;
+      break;
+    case 2:
+      package.F1 = *tmp;
+      break;
+    case 3: 
+      package.F2 = *tmp;
+      break;
+    case 4: 
+      package.F3 = *tmp;
+      break;
+    default:
+      abort();
+    }
+    
+    /* DEBUG INFO */
+    if (trb_debug > 1) {
+      fprintf(stderr, "FIFO_%03d:  0x%08x\n",
+              packageCtr * 5 + counter, *tmp);
+    }
+    
+    counter++;
+    
+    if (counter % 5 == 0) {
+      /* End of Package, validate package and retrieve data */
+      
+      /* Determine H0 HeaderType */
+      headerType = (package.H0 & MASK_HEADER_TYPE) >> SHIFT_HEADER_TYPE;
+      
+      /* DEBUG INFO */
+      if (trb_debug > 0) {
+        TRB_Package_dump(&package);
+        fprintf(stderr, "-------------------------------------------------\n");
+      }
+      
+      /* First package (TRB-Header), headerType must be HDR or TRM */
+      if (trb_lazy == 0) {
+        if (packageCtr == 0) {
+          if (!((headerType == HEADER_HDR) | (headerType == HEADER_TRM))) {
+            trb_fifo_flush(channel);
+            trb_errno = TRB_FIFO_INVALID_CONTENT;
+            return -1;
+          }
+        }
+        
+        /* Check Header H0 */
+        if (((package.H0 & MASK_HEADER_REPLY) >> SHIFT_HEADER_REPLY 
+             != 0x01) ||
+            ((package.H0 & MASK_HEADER_CHANNEL) >> SHIFT_HEADER_CHANNEL 
+             != channel)) {
+        
+          /* Error Package inconsistencies, flush FIFO-BUFFER and exit */
+          trb_fifo_flush(channel);
+          trb_errno = TRB_FIFO_HEADERS;
+          return -1;
+        }
+      }
+          
+      /* Get Data F0 - F3 and store it in User-Data-Buffer if requested */
+      if (headerType != HEADER_TRM) {
+        switch (mode) {
+          
+        case FIFO_MODE_NONE:
+          break;
+          
+        case FIFO_MODE_REG_READ:
+
+          switch (headerType) {
+          case HEADER_HDR:
+            if ((packageCtr - endPointCtr * 2) != 0) {
+              trb_fifo_flush(channel);
+              trb_errno = TRB_FIFO_INVALID_CONTENT;
+              return -1;
+            }
+            if (dataCtr < size) {
+              data[dataCtr++] = (uint32_t)package.F0;
+            } else {
+              trb_fifo_flush(channel);
+              trb_errno = TRB_USER_BUFFER_OVF;
+              return -1; 
+            }
+            break;
+            
+          case HEADER_DAT:
+            if ((packageCtr - endPointCtr * 2) != 1) {
+              trb_fifo_flush(channel);
+              trb_errno = TRB_FIFO_INVALID_CONTENT;
+            }
+            if (dataCtr < size) {
+              data[dataCtr++] = (((uint32_t)package.F1 << 16) | 
+                                 ((uint32_t)package.F2));
+              endPointCtr++;
+            } else {
+              trb_fifo_flush(channel);
+              trb_errno = TRB_USER_BUFFER_OVF;
+              return -1;
+            }
+            break;
+            
+          default:
+            trb_fifo_flush(channel);
+            trb_errno = TRB_FIFO_INVALID_CONTENT;
+            return -1;
+          }
+          
+          break;
+          
+        case FIFO_MODE_REG_READ_MEM:
+          if (packageCtr > 0) {
+            if (headerType != HEADER_DAT) {
+              trb_fifo_flush(channel);
+              trb_errno = TRB_FIFO_INVALID_CONTENT;
+              return -1;
+            }
+            if (dataCtr < size) {
+              data[dataCtr++] = (((uint32_t)package.F1 << 16) | 
+                                 ((uint32_t)package.F2));
+            } else {
+              trb_fifo_flush(channel);
+              trb_errno = TRB_USER_BUFFER_OVF;
+              return -1;
+            }
+          }
+          break;
+          
+        case FIFO_MODE_REG_WRITE:
+          if (packageCtr > 1) {
+            trb_fifo_flush(channel);
+            trb_errno = TRB_INVALID_PKG_NUMBER;
+            return -1;
+          }
+          break;
+          
+        case FIFO_MODE_IPU_DATA:
+          if (packageCtr > 0) {
+            if (headerType != HEADER_DAT) {
+              trb_fifo_flush(channel);
+              trb_errno = TRB_FIFO_INVALID_CONTENT;
+              return -1;
+            }
+            if ((dataCtr + 1) < size) {
+              data[dataCtr++] = (((uint32_t)package.F0 << 16) | 
+                                 ((uint32_t)package.F1));
+              data[dataCtr++] = (((uint32_t)package.F2 << 16) | 
+                                 ((uint32_t)package.F3));
+            } else {
+              trb_fifo_flush(channel);
+              trb_errno = TRB_USER_BUFFER_OVF;
+              return -1;
+            }
+          }
+          break;
+          
+        case FIFO_MODE_UID:
+          {
+            static uint32_t uidLow;
+            static uint32_t uidHigh;
+            
+            switch (headerType) {
+            case HEADER_HDR:
+              if ((packageCtr - endPointCtr * 3) != 0) {
+                trb_fifo_flush(channel);
+                trb_errno = TRB_FIFO_INVALID_CONTENT;
+                return -1;
+              }
+              break;
+              
+            case HEADER_DAT:
+              if ((packageCtr - endPointCtr * 3) == 1) {
+                uidHigh = (((uint32_t)package.F0 <<  0) |  
+                           ((uint32_t)package.F1 << 16));
+                uidLow = (((uint32_t)package.F2 <<  0) |  
+                          ((uint32_t)package.F3 << 16));
+                break;
+              }
+              
+              if ((packageCtr - endPointCtr * 3) == 2) {
+                if ((dataCtr + 3) < size) {
+                  /* store uid and endPoint in userDataBuffer */
+                  data[dataCtr++] = uidLow;
+                  data[dataCtr++] = uidHigh;
+                  data[dataCtr++] = (uint32_t)package.F0;
+                  endPointCtr++;
+                } else {
+                  trb_fifo_flush(channel);
+                  trb_errno = TRB_USER_BUFFER_OVF;
+                  return -1;
+                }
+                break;
+              }
+              
+            default:
+              trb_fifo_flush(channel);
+              trb_errno = TRB_FIFO_INVALID_CONTENT;
+              return -1;
+            }
+          }
+          break;
+      
+        case FIFO_MODE_SET_ADDRESS:
+          if ((packageCtr == 1) && (headerType == HEADER_DAT)) {
+            if (package.F0 != NET_ACKADDRESS) {
+              trb_fifo_flush(channel);
+              return -1;
+            }
+          }
+          
+          if (packageCtr > 1) {
+            trb_fifo_flush(channel);
+            trb_errno = TRB_INVALID_PKG_NUMBER;
+            return -1;
+          }
+          
+          dataCtr++;
+          break;
+
+        default:
+          trb_fifo_flush(channel);
+          trb_errno = TRB_FIFO_INVALID_MODE;
+          return -1;
+        }
+      }
+    }
+    
+    /* Read Next Word */
+    if (trb_dma == 1) {
+      tmp++;
+    } else {
+      read32_from_FPGA(fifoBuffer, tmp);
+    }
+  }
+  
+  if (trb_lazy == 0) {
+    /* Check whether last package is complete */
+    if ((packageCtr >= 0) && (counter != 5)) {
+      trb_errno = TRB_FIFO_BROKEN_PACKAGE;
+      return -1;
+    }
+  
+    /* Check whether last package is a TERMINATION Package */
+    if (headerType != HEADER_TRM) {
+      trb_errno = TRB_FIFO_INVALID_CONTENT;
+      return -1;
+    }
+  
+    /* Check StatusBits of TerminationPackage */
+    if ((package.F2 != 0x0001) || 
+        (package.F1 != 0x0000)) {
+      
+      trb_statusbits = 
+        ((uint64_t)channel << 32) | 
+        ((uint64_t)package.F1 << 16) | 
+        ((uint64_t)package.F2 <<  0);
+      trb_errno = TRB_TERM_ERRBIT;
+      return -1;
+    }
+  }
+  
+  return dataCtr;
+}
+
+/* ----- Global Functions ----------------------------------------------- */
+
+int trb_fifo_flush(uint8_t channel)
+{
+  uint32_t tmp;
+  uint32_t fifoAddress;
+  unsigned int counter = 0;
+
+  if (channel >= 4) {
+    trb_errno = TRB_INVALID_CHANNEL;
+    return -1;
+  }
+  
+  /* DEBUG INFO */
+  if (trb_debug > 1) {
+    fprintf(stderr, "Flushing FIFO of channel# %d\n", channel);
+  }
+  
+  fifoAddress = CHANNEL_N_RECEIVER_DATA | ((channel * 2 + 1) << 4);
+  do {
+    read32_from_FPGA(fifoAddress, &tmp);
+    /* DEBUG INFO */
+    if ((trb_debug > 1) && ((tmp & MASK_FIFO_VALID) != 0)) {
+      fprintf(stderr, "FIFO_%03d:  0x%08x\n", counter, tmp);
+      counter++;
+    }
+  } while ((tmp & MASK_FIFO_VALID) != 0);
+  
+  return 0;
+}
+
+int trb_register_read(uint16_t trb_address,
+                      uint16_t reg_address,
+                      uint32_t *data,
+                      unsigned int size)
+{
+  int status = 0;
+  
+  /* Init transfer */
+  if (trb_init_transfer(3) == -1) {
+    return -1;
+  } 
+  
+  /* DEBUG INFO */
+  if (trb_debug > 0) {
+    fprintf(stderr, "Init_Transfer done.\n");
+  }
+  
+  /* Build up package and start transfer */
+  write32_to_FPGA(CHANNEL_3_TARGET_ADDRESS, trb_address);
+  write32_to_FPGA(CHANNEL_3_SENDER_ERROR, 0x00000000);
+  write32_to_FPGA(CHANNEL_3_SENDER_DATA, reg_address);
+  write32_to_FPGA(CHANNEL_3_SENDER_DATA, 0x00000000);
+  write32_to_FPGA(CHANNEL_3_SENDER_DATA, 0x00000000);
+  write32_to_FPGA(CHANNEL_3_SENDER_DATA, 0x00000000);
+  write32_to_FPGA(CHANNEL_3_SENDER_CONTROL, CMD_REGISTER_READ);
+  
+  /* DEBUG INFO */
+  if (trb_debug > 0) {
+    fprintf(stderr, "CMD_REGISTER_READ started.\n");
+  }
+  
+  status = trb_fifo_read(3, FIFO_MODE_REG_READ, data, size);
+  
+  if ((status > 0) && (status % 2 != 0)) {
+    trb_errno = TRB_INVALID_PKG_NUMBER;
+    return -1; 
+  }
+  
+  return status;
+}
+
+int trb_register_read_mem(uint16_t trb_address,                             
+                          uint16_t reg_address,                             
+                          uint8_t option,
+                          uint32_t *data,
+                          uint16_t size)
+{
+  uint16_t length;
+  
+  /* Do not allow broadcasts within this function */
+  if (trb_address >= 0xff00) {
+    trb_errno = TRB_INVALID_ADDRESS;
+    return -1;
+  }
+  
+  /* check size and set reading-mode */
+  length = size & 0x7fff;
+  if ((size == 0) || (size != length)) {
+    trb_errno = TRB_INVALID_LENGTH;
+    return -1;
+  }
+  length = length | (option == 0 ? 0x8000 : 0x0000);
+  
+  /* Init transfer */
+  if (trb_init_transfer(3) == -1) {
+    return -1;
+  } 
+  
+  /* DEBUG INFO */
+  if (trb_debug > 0) {
+    fprintf(stderr, "Init_Tranfer done.\n");
+  }
+    
+  /* Build up package and start transfer */
+  write32_to_FPGA(CHANNEL_3_TARGET_ADDRESS, trb_address);
+  write32_to_FPGA(CHANNEL_3_SENDER_ERROR, 0x00000000);
+  write32_to_FPGA(CHANNEL_3_SENDER_DATA, reg_address);
+  write32_to_FPGA(CHANNEL_3_SENDER_DATA, length);
+  write32_to_FPGA(CHANNEL_3_SENDER_DATA, 0x00000000);
+  write32_to_FPGA(CHANNEL_3_SENDER_DATA, 0x00000000);
+  write32_to_FPGA(CHANNEL_3_SENDER_CONTROL, CMD_REGISTER_READ_MEM);
+  
+  /* DEBUG INFO */
+  if (trb_debug > 0) {
+    fprintf(stderr, "CMD_REGISTER_READ_MEM started.\n");
+  }
+  
+  return trb_fifo_read(3, FIFO_MODE_REG_READ_MEM, data, size);
+}
+
+int trb_register_write(uint16_t trb_address,
+                       uint16_t reg_address, 
+                       uint32_t value)
+{
+  /* Init transfer */
+  if (trb_init_transfer(3) == -1) {
+    return -1;
+  } 
+  
+  /* DEBUG INFO */
+  if (trb_debug > 0) {
+    fprintf(stderr, "Init_Transfer done.\n");
+  }
+
+  /* Build up package */
+  write32_to_FPGA(CHANNEL_3_TARGET_ADDRESS, trb_address);
+  write32_to_FPGA(CHANNEL_3_SENDER_ERROR, 0x00000000);
+  write32_to_FPGA(CHANNEL_3_SENDER_DATA, reg_address);
+  write32_to_FPGA(CHANNEL_3_SENDER_DATA, (value >> 16) & 0xffff);
+  write32_to_FPGA(CHANNEL_3_SENDER_DATA, value & 0xffff);
+  write32_to_FPGA(CHANNEL_3_SENDER_DATA, 0x00000000);
+  write32_to_FPGA(CHANNEL_3_SENDER_CONTROL, CMD_REGISTER_WRITE);
+  
+  /* DEBUG INFO */
+  if (trb_debug > 0) {
+    fprintf(stderr, "CMD_REGISTER_WRITE started.\n");
+  }
+  
+  return trb_fifo_read(3, FIFO_MODE_REG_WRITE, NULL, 0);
+}
+
+int trb_register_write_mem(uint16_t trb_address,                             
+                           uint16_t reg_address,                             
+                           uint8_t option,
+                           const  uint32_t *data,
+                           uint16_t size)
+{
+  uint16_t config;
+  uint16_t i;
+  
+  /* check size and set write-mode */
+  config = size & 0x7fff;
+  if ((size == 0) || (size != config)) {
+    trb_errno = TRB_INVALID_LENGTH;
+    return -1;
+  }
+  config = config | (option == 0 ? 0x8000 : 0x0000);
+  
+  /* Init transfer */
+  if (trb_init_transfer(3) == -1) {
+    return -1;
+  } 
+  
+  /* DEBUG INFO */
+  if (trb_debug > 0) {
+    fprintf(stderr, "Init_Transfer done.\n");
+  }
+
+  /* Build up package */
+  write32_to_FPGA(CHANNEL_3_TARGET_ADDRESS, trb_address);
+  write32_to_FPGA(CHANNEL_3_SENDER_ERROR, 0x00000000);
+  write32_to_FPGA(CHANNEL_3_SENDER_DATA, reg_address);
+  write32_to_FPGA(CHANNEL_3_SENDER_DATA, config);
+  write32_to_FPGA(CHANNEL_3_SENDER_DATA, 0x00000000);
+  write32_to_FPGA(CHANNEL_3_SENDER_DATA, 0x00000000);
+  for (i = 0; i < size; i++) {
+    write32_to_FPGA(CHANNEL_3_SENDER_DATA, 0x00000000); 
+    write32_to_FPGA(CHANNEL_3_SENDER_DATA, (data[i] >> 16) & 0xffff);
+    write32_to_FPGA(CHANNEL_3_SENDER_DATA, data[i] & 0xffff);
+    write32_to_FPGA(CHANNEL_3_SENDER_DATA, 0x00000000); 
+  }
+  write32_to_FPGA(CHANNEL_3_SENDER_CONTROL, CMD_REGISTER_WRITE_MEM);
+  
+  /* DEBUG INFO */
+  if (trb_debug > 0) {
+    fprintf(stderr, "CMD_REGISTER_WRITE_MEM started.\n");
+  }
+  
+  return trb_fifo_read(3, FIFO_MODE_REG_WRITE, NULL, 0);
+}
+
+int trb_read_uid(uint16_t trb_address,
+                 uint32_t* uidBuffer,
+                 unsigned int size)
+{
+  int status;
+  
+  /* Init transfer */
+  if (trb_init_transfer(3) == -1) {
+    return -1;
+  } 
+  
+  /* DEBUG INFO */
+  if (trb_debug > 0) {
+    fprintf(stderr, "Init_Transfer done.\n");
+  }
+  
+  /* Build up package and start transfer */
+  write32_to_FPGA(CHANNEL_3_TARGET_ADDRESS, trb_address);
+  write32_to_FPGA(CHANNEL_3_SENDER_ERROR, 0x00000000);
+  write32_to_FPGA(CHANNEL_3_SENDER_DATA, NET_READUNIQUEID);
+  write32_to_FPGA(CHANNEL_3_SENDER_DATA, 0x00000000);
+  write32_to_FPGA(CHANNEL_3_SENDER_DATA, 0x00000000);
+  write32_to_FPGA(CHANNEL_3_SENDER_DATA, 0x00000000);
+  write32_to_FPGA(CHANNEL_3_SENDER_CONTROL, CMD_NETADMINISTRATION);
+  
+  /* DEBUG INFO */
+  if (trb_debug > 0) {
+    fprintf(stderr, "CMD_READ_UNIQUE_ID started.\n");
+  }
+  
+  status = trb_fifo_read(3, FIFO_MODE_UID, (uint32_t*)uidBuffer, size);
+  
+  if ((status > 0) && (status % 3 != 0)) {
+    trb_errno = TRB_INVALID_PKG_NUMBER;
+    return -1; 
+  }
+  
+  return status;
+}
+
+
+int trb_set_address(uint64_t uid,
+                    uint8_t endpoint,
+                    uint16_t trb_address)
+{
+  int status;
+  
+  /* check for valid TRBnet address to be assigned */
+  if (trb_address >= 0xff00 ) {
+    trb_errno = TRB_INVALID_ADDRESS;
+    return -1;
+  }
+  
+  /* Init transfer */
+  if (trb_init_transfer(3) == -1) {
+    return -1;
+  } 
+  
+  /* DEBUG INFO */
+  if (trb_debug > 0) {
+    fprintf(stderr, "Init_Transfer done.\n");
+  }
+  
+  /* Build up package and start transfer */
+  write32_to_FPGA(CHANNEL_3_TARGET_ADDRESS, 0xffff); /* always broadcast */
+  write32_to_FPGA(CHANNEL_3_SENDER_ERROR, 0x00000000);
+  write32_to_FPGA(CHANNEL_3_SENDER_DATA, NET_SETADDRESS);
+  write32_to_FPGA(CHANNEL_3_SENDER_DATA, (uint16_t)(uid));
+  write32_to_FPGA(CHANNEL_3_SENDER_DATA, (uint16_t)(uid >> 16));
+  write32_to_FPGA(CHANNEL_3_SENDER_DATA, (uint16_t)(uid >> 32));
+  write32_to_FPGA(CHANNEL_3_SENDER_DATA, (uint16_t)(uid >> 48));
+  write32_to_FPGA(CHANNEL_3_SENDER_DATA,  endpoint);
+  write32_to_FPGA(CHANNEL_3_SENDER_DATA,  trb_address);
+  write32_to_FPGA(CHANNEL_3_SENDER_DATA, 0x00000000);
+  write32_to_FPGA(CHANNEL_3_SENDER_CONTROL, CMD_NETADMINISTRATION);
+  
+  /* DEBUG INFO */
+  if (trb_debug > 0) {
+     fprintf(stderr, "CMD_SETADDRESS started.\n");
+  }
+  
+  status = trb_fifo_read(3, FIFO_MODE_SET_ADDRESS, NULL, 0); 
+  if (status == -1) return -1;
+  
+  if (status != 2) {
+    trb_errno = TRB_ENDPOINT_NOT_REACHED;
+    return -1;
+  }
+  
+  
+  return 0;
+}
+
+int trb_ipu_data_read(uint8_t type,
+                      uint8_t trg_info,
+                      uint8_t trg_random,
+                      uint16_t trg_number,
+                      uint32_t *data,
+                      unsigned int size)
+{
+  int status;
+  
+  if (data == NULL) return -1;
+  
+  /* Init transfer IPU Channel */
+  if (trb_init_transfer(1) == -1) {
+    return -1;
+  }
+  
+  /* DEBUG INFO */
+  if (trb_debug > 0) {
+    fprintf(stderr, "Init_Transfer done.\n");
+  }
+  
+  /* Prepare IPU channel */
+  write32_to_FPGA(CHANNEL_1_SENDER_ERROR, (((uint32_t)trg_info << 24) | 
+                                           ((uint32_t)trg_random << 16) | 
+                                           ((uint32_t)trg_number)
+                                           ));
+  write32_to_FPGA(CHANNEL_1_SENDER_CONTROL,
+                  SHORT_TRANSFER | (uint32_t)(type & 0x0f));
+
+  /* DEBUG INFO */
+  if (trb_debug > 0) {
+    fprintf(stderr, "CMD_IPU_DATA_READ started.\n");
+  }
+  
+  status = trb_fifo_read(1, FIFO_MODE_IPU_DATA, data, size);
+  
+  return status;
+}
+
+
+int trb_send_trigger(uint8_t trg_input,
+                     uint8_t type,
+                     uint8_t trg_info,
+                     uint8_t trg_random,
+                     uint16_t trg_number)
+{
+  int status;
+    
+  /* Init transfer slowcontrol */
+  if (trb_init_transfer(3) == -1) {
+    return -1;
+  } 
+  
+  /* Init transfer trigger */
+  if (trb_init_transfer(0) == -1) {
+    return -1;
+  } 
+  
+  /* DEBUG INFO */
+  if (trb_debug > 0) {
+    fprintf(stderr, "Init_Transfer done.\n");
+  }
+  
+  /* Prepare trigger channel */
+  write32_to_FPGA(CHANNEL_0_SENDER_ERROR, (((uint32_t)trg_info << 24) | 
+                                           ((uint32_t)trg_random << 16) | 
+                                           ((uint32_t)trg_number)
+                                           ));
+
+  /* Prepare slowcontrol channel */
+  write32_to_FPGA(CHANNEL_3_TARGET_ADDRESS, 0x0000ffff);/* all boards    */
+  write32_to_FPGA(CHANNEL_3_SENDER_ERROR, 0x00000000);
+  write32_to_FPGA(CHANNEL_3_SENDER_DATA, (0x8080 | (uint32_t)trg_input));
+  write32_to_FPGA(CHANNEL_3_SENDER_DATA, 0x0000dead);  /*fake data is      */
+  write32_to_FPGA(CHANNEL_3_SENDER_DATA, 0x0000beef); /* discarded at ADCM */ 
+  write32_to_FPGA(CHANNEL_3_SENDER_DATA, 0x00000000);
+  
+  /* Send both fake trigger and LVL1 information */
+  write32_to_FPGA(CHANNEL_3_SENDER_CONTROL, CMD_REGISTER_WRITE);
+  write32_to_FPGA(CHANNEL_0_SENDER_CONTROL,
+                  SHORT_TRANSFER | (uint32_t)(type & 0x0f));
+  
+  if (trb_debug > 0) {
+    fprintf(stderr, "trigger started.\n");
+  }
+  
+  /* Check for replay packets (slowcontrol) */
+  status = trb_fifo_read(3, FIFO_MODE_NONE, NULL, 0);
+  if (status == -1) {
+    trb_fifo_flush(0);
+    return -1;
+  }
+  
+  /* Check for replay packets (trigger) */
+  status = trb_fifo_read(0, FIFO_MODE_NONE, NULL, 0);
+  if (status == -1) return -1;
+  
+  return 0;
+}
+
diff --git a/libtrbnet/trbnet.h b/libtrbnet/trbnet.h
new file mode 100644 (file)
index 0000000..3eee0b8
--- /dev/null
@@ -0,0 +1,113 @@
+#ifndef TRBNET_H
+#define TRBNET_H
+
+#include <stdint.h>
+#include <port.h>
+
+extern unsigned int trb_debug;
+extern unsigned int trb_lazy;
+extern unsigned int trb_dma;
+
+/* ---------------------------------------------------------------------- */
+
+int trb_fifo_flush(uint8_t channel);
+
+int trb_register_read(uint16_t trb_address,                             
+                      uint16_t reg_address,                             
+                      uint32_t* data,
+                      unsigned int size);                                 
+
+int trb_register_read_mem(uint16_t trb_address,                             
+                          uint16_t reg_address,                             
+                          uint8_t option,
+                          uint32_t* data,
+                          uint16_t size);
+                        
+int trb_register_write(uint16_t trb_address,                            
+                       uint16_t reg_address,                            
+                       uint32_t value);                                 
+                                                                        
+int trb_register_write_mem(uint16_t trb_address,                             
+                           uint16_t reg_address,                             
+                           uint8_t option,
+                           const  uint32_t* data,
+                           uint16_t size);
+
+int trb_read_uid(uint16_t trb_address,                                  
+                 uint32_t* uidBuffer,
+                 unsigned int size);                                 
+
+int trb_set_address(uint64_t uid,
+                    uint8_t endpoint,
+                    uint16_t trb_address);
+
+
+int trb_ipu_data_read(uint8_t type,
+                      uint8_t trg_info,
+                      uint8_t trg_random,
+                      uint16_t trg_number,
+                      uint32_t* data, 
+                      unsigned int size);
+
+
+int trb_send_trigger(uint8_t input,
+                     uint8_t type,
+                     uint8_t info,
+                     uint8_t random,
+                     uint16_t number);
+
+/* ---------------------------------------------------------------------- */
+
+/************************************************************************/
+/* In case of an error trb_errno is set, see trberror.h for details.    */
+/************************************************************************/
+                                                                        
+                                                                        
+/************************************************************************/
+/* int trb_register_read(uint16_t trb_address,                             
+                         uint16_t reg_address,                             
+                         uint32_t* data,
+                         unsigned int size);
+
+   trb_address: TRB-Address of TRB-Endpoint
+   reg_address: Register-Address to be read
+   data:        Pointer to uint32_t Data-Buffer 
+   size:        Size of the Data-Buffer in units of 32bit-words
+   
+   ReturnValue: == -1 on error   
+                >=  0 number of 32bit-words which were stored in Data-Buffer
+   
+   TRB-Channel used: slow control (3)
+   
+   reads the register reg_address of a TRB-Endpoint with address 
+   trb_address. The received data is stored in the Data-Buffer data.
+   The format of the Data-Buffer is:
+    first word:  TRB-Address of sender
+    second word: register value
+   
+   --> Data-Buffer-Size size must be at least 2
+                                                                        
+*/
+
+/* int trb_register_write(uint16_t trb_address,                            
+                          uint16_t reg_address,                            
+                          uint32_t value);   
+
+   trb_address: TRB-Address of TRB-Endpoint
+   reg_address: Register-Address to be written
+   value:       32bit-word to write to register
+   
+   ReturnValue: == -1 on error   
+                >=  0 number of 32bit-words which were stored in Data-Buffer
+   
+   TRB-Channel used: slow control (3)
+   
+   writes value to the register reg_address of a TRB-Endpoint with address 
+   trb_address.
+*/
+
+
+
+
+
+#endif