From 91dd176a0fb314f583ca6e29140053f1eb742896 Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Thu, 8 Nov 2018 17:15:48 +0100 Subject: [PATCH] gotthard server done editing --- .../slsDetectorFunctionList.c | 13 +- .../gotthardDetectorServer/Makefile | 42 +- .../gotthardDetectorServer/Makefile.virtual | 43 +- .../gotthardDetectorServer/RegisterDefs.h | 328 +++ .../gotthardDetectorServer/blackfin.h | 1 + .../gotthardDetectorServer/firmware_funcs.c | 2098 ---------------- .../gotthardDetectorServer/firmware_funcs.h | 120 - .../gotthardDetectorServer_refactor | Bin 86044 -> 0 bytes .../gotthardDetectorServer_virtual | Bin 104160 -> 0 bytes .../gotthardDetectorServer/logger.h | 1 + .../gotthardDetectorServer/server.c | 103 - .../gotthardDetectorServer/server_defs.h | 69 - .../gotthardDetectorServer/server_funcs.c | 2185 ----------------- .../gotthardDetectorServer/server_funcs.h | 70 - .../slsDetectorFunctionList.c | 1810 ++++++++++++++ .../slsDetectorFunctionList.h | 1 + .../slsDetectorServer.c | 1 + .../slsDetectorServer_defs.h | 121 + .../slsDetectorServer_funcs.c | 1 + .../slsDetectorServer_funcs.h | 1 + .../gotthardDetectorServer/stop_server.c | 46 - .../jungfrauDetectorServer/Makefile | 2 +- .../slsDetectorFunctionList.c | 174 +- .../slsDetectorServer_defs.h | 17 - slsDetectorServers/slsDetectorServer/AD9257.h | 17 +- .../slsDetectorServer/commonServerFunctions.h | 11 +- .../slsDetectorFunctionList.h | 81 +- .../slsDetectorServer/slsDetectorServer.c | 24 +- .../slsDetectorServer_funcs.c | 424 ++-- .../slsDetectorServer_funcs.h | 1 - .../slsDetector/slsDetector.cpp | 70 +- 31 files changed, 2716 insertions(+), 5159 deletions(-) create mode 100755 slsDetectorServers/gotthardDetectorServer/RegisterDefs.h create mode 120000 slsDetectorServers/gotthardDetectorServer/blackfin.h delete mode 100755 slsDetectorServers/gotthardDetectorServer/firmware_funcs.c delete mode 100755 slsDetectorServers/gotthardDetectorServer/firmware_funcs.h delete mode 100755 slsDetectorServers/gotthardDetectorServer/gotthardDetectorServer_refactor delete mode 100755 slsDetectorServers/gotthardDetectorServer/gotthardDetectorServer_virtual create mode 120000 slsDetectorServers/gotthardDetectorServer/logger.h delete mode 100755 slsDetectorServers/gotthardDetectorServer/server.c delete mode 100755 slsDetectorServers/gotthardDetectorServer/server_defs.h delete mode 100755 slsDetectorServers/gotthardDetectorServer/server_funcs.c delete mode 100755 slsDetectorServers/gotthardDetectorServer/server_funcs.h create mode 100644 slsDetectorServers/gotthardDetectorServer/slsDetectorFunctionList.c create mode 120000 slsDetectorServers/gotthardDetectorServer/slsDetectorFunctionList.h create mode 120000 slsDetectorServers/gotthardDetectorServer/slsDetectorServer.c create mode 100644 slsDetectorServers/gotthardDetectorServer/slsDetectorServer_defs.h create mode 120000 slsDetectorServers/gotthardDetectorServer/slsDetectorServer_funcs.c create mode 120000 slsDetectorServers/gotthardDetectorServer/slsDetectorServer_funcs.h delete mode 100755 slsDetectorServers/gotthardDetectorServer/stop_server.c diff --git a/slsDetectorServers/eigerDetectorServer/slsDetectorFunctionList.c b/slsDetectorServers/eigerDetectorServer/slsDetectorFunctionList.c index 4beb7cbe1..9af050bcc 100644 --- a/slsDetectorServers/eigerDetectorServer/slsDetectorFunctionList.c +++ b/slsDetectorServers/eigerDetectorServer/slsDetectorFunctionList.c @@ -15,8 +15,11 @@ #include #endif -// Global variable from slsDetectorServer +// Global variable from slsDetectorServer_funcs extern int debugflag; + + +// Global variable from communication_funcs.c extern int isControlServer; int firmware_compatibility = OK; @@ -93,7 +96,7 @@ int getFirmwareCheckResult(char** mess) { return firmware_compatibility; } -void checkFirmwareCompatibility() { +void basictests() { firmware_compatibility = OK; firmware_check_done = 0; memset(firmware_message, 0, MAX_STR_LENGTH); @@ -1231,7 +1234,7 @@ int configureMAC(uint32_t destip, uint64_t destmac, uint64_t sourcemac, uint32_t Beb_SetUpUDPHeader(beb_num,send_to_ten_gig,header_number+i,dst_mac,dst_ip, dst_port)) { FILE_LOG(logDEBUG1, ("\tset up left ok\n")); } else { - return -1; + return FAIL; } /*}*/ @@ -1246,7 +1249,7 @@ int configureMAC(uint32_t destip, uint64_t destmac, uint64_t sourcemac, uint32_t Beb_SetUpUDPHeader(beb_num,send_to_ten_gig,header_number+i,dst_mac,dst_ip, dst_port)) { FILE_LOG(logDEBUG1, (" set up right ok\n")); } else { - return -1; + return FAIL; } /*}*/ @@ -1255,7 +1258,7 @@ int configureMAC(uint32_t destip, uint64_t destmac, uint64_t sourcemac, uint32_t for(i=0;i<32;i++) dst_requested[i] = 0; //clear dst requested nimages_per_request=eiger_nexposures * eiger_ncycles; #endif - return 0; + return OK; } diff --git a/slsDetectorServers/gotthardDetectorServer/Makefile b/slsDetectorServers/gotthardDetectorServer/Makefile index feaa65af0..e02c5c9f3 100755 --- a/slsDetectorServers/gotthardDetectorServer/Makefile +++ b/slsDetectorServers/gotthardDetectorServer/Makefile @@ -1,19 +1,18 @@ -CROSS = bfin-uclinux- -CC = $(CROSS)gcc +CROSS = bfin-uclinux- +CC = $(CROSS)gcc -CFLAGS += -Wall -DGOTTHARDD -DDEBUG # -DVERBOSE #-DVERYVERBOSE #-DVIRTUAL +CFLAGS += -Wall -DGOTTHARDD -DSTOP_SERVER # -DVERBOSE +LDLIBS += -lm -lstdc++ -PROGS= gotthardDetectorServer -INSTDIR= /tftpboot -INSTMODE= 0777 +PROGS = gotthardDetectorServer +DESTDIR ?= bin +INSTMODE = 0777 + +SRCS = communication_funcs.c slsDetectorServer.c slsDetectorServer_funcs.c slsDetectorFunctionList.c +OBJS = $(SRCS:%.c=%.o) -BINS = testlib_sharedlibc -SRCS = server.c firmware_funcs.c server_funcs.c communication_funcs.c -OBJS = $(SRCS:%.c=%.o) - - -all: clean versioning $(PROGS) +all: clean versioning $(PROGS) boot: $(OBJS) @@ -21,21 +20,14 @@ versioning: @echo `tput setaf 6; ./updateGitVersion.sh; tput sgr0;` $(PROGS): $(OBJS) - echo $(OBJS) - $(CC) $(CFLAGS) -o $@ $^ $(LDLIBS_$@) $(LDFLAGS_$@) - rm gotthardDetectorServer.gdb - - -install: $(PROGS) - $(INSTALL) -d $(INSTDIR) - $(INSTALL) -m $(INSTMODE) $(PROGS) $(INSTDIR) - - -romfs: - $(ROMFSINST) /bin/$(PROGS) +# echo $(OBJS) + mkdir -p $(DESTDIR) + $(CC) -o $@ $^ $(CFLAGS) $(LDLIBS) + mv $(PROGS) $(DESTDIR) + rm *.gdb clean: - rm -rf $(PROGS) *.o *.gdb + rm -rf $(DESTDIR)/$(PROGS) *.o *.gdb diff --git a/slsDetectorServers/gotthardDetectorServer/Makefile.virtual b/slsDetectorServers/gotthardDetectorServer/Makefile.virtual index 8574cbec7..65174a82f 100755 --- a/slsDetectorServers/gotthardDetectorServer/Makefile.virtual +++ b/slsDetectorServers/gotthardDetectorServer/Makefile.virtual @@ -1,30 +1,27 @@ +CC = gcc +CFLAGS += -Wall -DGOTTHARDD -DVIRTUAL -DSTOP_SERVER #-DVERBOSEI #-DVERBOSE +LDLIBS += -lm -lstdc++ -pthread -DESTDIR ?= ./ +PROGS = gotthardDetectorServer_virtual +DESTDIR ?= bin +INSTMODE = 0777 -CC = gcc -CFLAGS += -Wall -DGOTTHARDD -DVIRTUAL - - -PROGS= $(DESTDIR)/gotthardDetectorServer_virtual - - -SRCS = server.c server_funcs.c communication_funcs.c firmware_funcs.c -OBJS = $(SRCS:%.c=%.o) - -gotthardVirtualServer = $(PROGS) - -all: clean $(PROGS) +SRC_CLNT = communication_funcs.c slsDetectorServer.c slsDetectorServer_funcs.c slsDetectorFunctionList.c +OBJS = $(SRC_CLNT:.c=.o) + +all: clean versioning $(PROGS) +boot: $(OBJS) +versioning: + @echo `tput setaf 6; ./updateGitVersion.sh; tput sgr0;` + $(PROGS): $(OBJS) - $(CC) $(CFLAGS) -o $@ $^ $(LDLIBS_$@) $(LDFLAGS_$@) - +# echo $(OBJS) + mkdir -p $(DESTDIR) + $(CC) -o $@ $^ $(CFLAGS) $(LDLIBS) + mv $(PROGS) $(DESTDIR) clean: - rm -rf $(PROGS) *.o *.gdb - - - - - - + rm -rf $(DESTDIR)/$(PROGS) *.o + \ No newline at end of file diff --git a/slsDetectorServers/gotthardDetectorServer/RegisterDefs.h b/slsDetectorServers/gotthardDetectorServer/RegisterDefs.h new file mode 100755 index 000000000..74f4883be --- /dev/null +++ b/slsDetectorServers/gotthardDetectorServer/RegisterDefs.h @@ -0,0 +1,328 @@ +#pragma once + +/* Definitions for FPGA*/ +#define MEM_MAP_SHIFT 11 + +/** Gain register */ +#define GAIN_REG (0x10 << MEM_MAP_SHIFT) + +#define GAIN_CONFGAIN_OFST (0) +#define GAIN_CONFGAIN_MSK (0x000000FF << GAIN_CONFGAIN_OFST) +#define GAIN_CONFGAIN_HGH_GAIN_VAL ((0x0 << GAIN_CONFGAIN_OFST) & GAIN_CONFGAIN_MSK) +#define GAIN_CONFGAIN_DYNMC_GAIN_VAL ((0x8 << GAIN_CONFGAIN_OFST) & GAIN_CONFGAIN_MSK) +#define GAIN_CONFGAIN_LW_GAIN_VAL ((0x6 << GAIN_CONFGAIN_OFST) & GAIN_CONFGAIN_MSK) +#define GAIN_CONFGAIN_MDM_GAIN_VAL ((0x2 << GAIN_CONFGAIN_OFST) & GAIN_CONFGAIN_MSK) +#define GAIN_CONFGAIN_VRY_HGH_GAIN_VAL ((0x1 << GAIN_CONFGAIN_OFST) & GAIN_CONFGAIN_MSK) + +/** Multi Purpose register */ +#define MULTI_PURPOSE_REG (0x14 << MEM_MAP_SHIFT) + +#define PHS_STP_OFST (0) +#define PHS_STP_MSK (0x00000001 << PHS_STP_OFST) +#define RST_CNTR_OFST (2) +#define RST_CNTR_MSK (0x00000001 << RST_CNTR_OFST) +#define SW1_OFST (5) +#define SW1_MSK (0x00000001 << SW1_OFST) +#define WRT_BCK_OFST (6) +#define WRT_BCK_MSK (0x00000001 << WRT_BCK_OFST) +#define RST_OFST (7) +#define RST_MSK (0x00000001 << RST_OFST) +#define PLL_CLK_SL_OFST (8) +#define PLL_CLK_SL_MSK (0x00000007 << PLL_CLK_SL_OFST) +#define PLL_CLK_SL_MSTR_VAL ((0x1 << PLL_CLK_SL_OFST) & PLL_CLK_SL_MSK) +#define PLL_CLK_SL_MSTR_ADC_VAL ((0x2 << PLL_CLK_SL_OFST) & PLL_CLK_SL_MSK) +#define PLL_CLK_SL_SLV_VAL ((0x3 << PLL_CLK_SL_OFST) & PLL_CLK_SL_MSK) +#define PLL_CLK_SL_SLV_ADC_VAL ((0x4 << PLL_CLK_SL_OFST) & PLL_CLK_SL_MSK) +#define ENT_RSTN_OFST (11) +#define ENT_RSTN_MSK (0x00000001 << ENT_RSTN_OFST) +#define INT_RSTN_OFST (12) +#define INT_RSTN_MSK (0x00000001 << INT_RSTN_OFST) +#define DGTL_TST_OFST (14) +#define DGTL_TST_MSK (0x00000001 << DGTL_TST_OFST) +#define CHNG_AT_PWR_ON_OFST (15) // Not used in SW +#define CHNG_AT_PWR_ON_MSK (0x00000001 << CHNG_AT_PWR_ON_OFST) // Not used in SW +#define RST_TO_SW1_DLY_OFST (16) +#define RST_TO_SW1_DLY_MSK (0x0000000F << RST_TO_SW1_DLY_OFST) +#define STRT_ACQ_DLY_OFST (20) +#define STRT_ACQ_DLY_MSK (0x0000000F << STRT_ACQ_DLY_OFST) + +/** DAQ register */ +#define DAQ_REG (0x15 << MEM_MAP_SHIFT) + +#define DAQ_TKN_TMNG_OFST (0) +#define DAQ_TKN_TMNG_MSK (0x0000FFFF << DAQ_TKN_TMNG_OFST) +#define DAQ_TKN_TMNG_BRD_RVSN_1_VAL ((0x1f16 << DAQ_TKN_TMNG_OFST) & DAQ_TKN_TMNG_MSK) +#define DAQ_TKN_TMNG_BRD_RVSN_2_VAL ((0x1f0f << DAQ_TKN_TMNG_OFST) & DAQ_TKN_TMNG_MSK) +#define DAQ_PCKT_LNGTH_OFST (16) +#define DAQ_PCKT_LNGTH_MSK (0x0000FFFF << DAQ_PCKT_LNGTH_OFST) +#define DAQ_PCKT_LNGTH_NO_ROI_VAL ((0x0013f << DAQ_PCKT_LNGTH_OFST) & DAQ_PCKT_LNGTH_MSK) +#define DAQ_PCKT_LNGTH_ROI_VAL ((0x0007f << DAQ_PCKT_LNGTH_OFST) & DAQ_PCKT_LNGTH_MSK) + +/** DAC Control register */ +#define DAC_CNTRL_REG (0x17 << MEM_MAP_SHIFT) + +#define DAC_CNTRL_CS_OFST (0) +#define DAC_CNTRL_CS_MSK (0x00000001 << DAC_CNTRL_CS_OFST) +#define DAC_CNTRL_CLK_OFST (1) +#define DAC_CNTRL_CLK_MSK (0x00000001 << DAC_CNTRL_CLK_OFST) +#define DAQ_CNTRL_DGTL_OFST (2) +#define DAQ_CNTRL_DGTL_MSK (0x00000001 << DAQ_CNTRL_DGTL_OFST) + +/** ADC SPI register */ +#define ADC_SPI_REG (0x18 << MEM_MAP_SHIFT) + +#define ADC_SERIAL_CLK_OUT_OFST (0) +#define ADC_SERIAL_CLK_OUT_MSK (0x00000001 << ADC_SERIAL_CLK_OUT_OFST) +#define ADC_SERIAL_DATA_OUT_OFST (1) +#define ADC_SERIAL_DATA_OUT_MSK (0x00000001 << ADC_SERIAL_DATA_OUT_OFST) +#define ADC_SERIAL_CS_OUT_OFST (2) +#define ADC_SERIAL_CS_OUT_MSK (0x0000000F << ADC_SERIAL_CS_OUT_OFST) + +/** ADC Sync register */ +#define ADC_SYNC_REG (0x19 << MEM_MAP_SHIFT) + +#define ADC_SYNC_ENET_STRT_DLY_OFST (0) +#define ADC_SYNC_ENET_STRT_DLY_MSK (0x0000000F << ADC_SYNC_ENET_STRT_DLY_OFST) +#define ADC_SYNC_ENET_STRT_DLY_VAL ((0x4 << ADC_SYNC_ENET_STRT_DLY_OFST) & ADC_SYNC_ENET_STRT_DLY_MSK) +#define ADC_SYNC_TKN1_HGH_DLY_OFST (4) +#define ADC_SYNC_TKN1_HGH_DLY_MSK (0x0000000F << ADC_SYNC_TKN1_HGH_DLY_OFST) +#define ADC_SYNC_TKN1_HGH_DLY_VAL ((0x1 << ADC_SYNC_TKN1_HGH_DLY_OFST) & ADC_SYNC_TKN1_HGH_DLY_MSK) +#define ADC_SYNC_TKN2_HGH_DLY_OFST (8) +#define ADC_SYNC_TKN2_HGH_DLY_MSK (0x0000000F << ADC_SYNC_TKN2_HGH_DLY_OFST) +#define ADC_SYNC_TKN2_HGH_DLY_VAL ((0x2 << ADC_SYNC_TKN2_HGH_DLY_OFST) & ADC_SYNC_TKN2_HGH_DLY_MSK) +#define ADC_SYNC_TKN1_LOW_DLY_OFST (12) +#define ADC_SYNC_TKN1_LOW_DLY_MSK (0x0000000F << ADC_SYNC_TKN1_LOW_DLY_OFST) +#define ADC_SYNC_TKN1_LOW_DLY_VAL ((0x2 << ADC_SYNC_TKN1_LOW_DLY_OFST) & ADC_SYNC_TKN1_LOW_DLY_MSK) +#define ADC_SYNC_TKN2_LOW_DLY_OFST (16) +#define ADC_SYNC_TKN2_LOW_DLY_MSK (0x0000000F << ADC_SYNC_TKN2_LOW_DLY_OFST) +#define ADC_SYNC_TKN2_LOW_DLY_VAL ((0x3 << ADC_SYNC_TKN2_LOW_DLY_OFST) & ADC_SYNC_TKN2_LOW_DLY_MSK) +//0x32214 +#define ADC_SYNC_TKN_VAL (ADC_SYNC_ENET_STRT_DLY_VAL | ADC_SYNC_TKN1_HGH_DLY_VAL | ADC_SYNC_TKN2_HGH_DLY_VAL | ADC_SYNC_TKN1_LOW_DLY_VAL | ADC_SYNC_TKN2_LOW_DLY_VAL) +#define ADC_SYNC_CLEAN_FIFOS_OFST (20) +#define ADC_SYNC_CLEAN_FIFOS_MSK (0x00000001 << ADC_SYNC_CLEAN_FIFOS_OFST)// FIXME: tried with 1, works? else put 0x011 as mask +#define ADC_SYNC_ENET_DELAY_OFST (24) +#define ADC_SYNC_ENET_DELAY_MSK (0x000000FF << ADC_SYNC_ENET_DELAY_OFST) +#define ADC_SYNC_ENET_DELAY_NO_ROI_VAL ((0x88 << ADC_SYNC_ENET_DELAY_OFST) & ADC_SYNC_ENET_DELAY_MSK) +#define ADC_SYNC_ENET_DELAY_ROI_VAL ((0x1b << ADC_SYNC_ENET_DELAY_OFST) & ADC_SYNC_ENET_DELAY_MSK) +//FIXME: try with just 0x8 and 0x1.. it is anded with 0000 in firmware anyway + +/** Temperatre SPI In register */ +#define TEMP_SPI_IN_REG (0x1b << MEM_MAP_SHIFT) + +#define TEMP_SPI_IN_T1_CLK_OFST (0) +#define TEMP_SPI_IN_T1_CLK_MSK (0x00000001 << TEMP_SPI_IN_T1_CLK_OFST) +#define TEMP_SPI_IN_T1_CS_OFST (1) +#define TEMP_SPI_IN_T1_CS_MSK (0x00000001 << TEMP_SPI_IN_T1_CS_OFST) +#define TEMP_SPI_IN_T2_CLK_OFST (2) +#define TEMP_SPI_IN_T2_CLK_MSK (0x00000001 << TEMP_SPI_IN_T2_CLK_OFST) +#define TEMP_SPI_IN_T2_CS_OFST (3) +#define TEMP_SPI_IN_T2_CS_MSK (0x00000001 << TEMP_SPI_IN_T2_CS_OFST) + +/** Temperatre SPI Out register */ +#define TEMP_SPI_OUT_REG (0x1c << MEM_MAP_SHIFT) + +#define TEMP_SPI_OUT_T1_DT_OFST (0) +#define TEMP_SPI_OUT_T1_DT_MSK (0x00000001 << TEMP_SPI_OUT_T1_DT_OFST) +#define TEMP_SPI_OUT_T2_DT_OFST (1) +#define TEMP_SPI_OUT_T2_DT_MSK (0x00000001 << TEMP_SPI_OUT_T2_DT_OFST) + +/** TSE Configure register */ +#define TSE_CONF_REG (0x1d << MEM_MAP_SHIFT) + +/** SPI Configure register */ +#define ENET_CONF_REG (0x1e << MEM_MAP_SHIFT) + +/** High Voltage register */ +#define HV_REG (0x20 << MEM_MAP_SHIFT) + +#define HV_ENBL_OFST (0) +#define HV_ENBL_MSK (0x00000001 << HV_ENBL_OFST) +#define HV_SEL_OFST (1) +#define HV_SEL_MSK (0x00000007 << HV_SEL_OFST) +#define HV_SEL_90_VAL ((0x0 << HV_SEL_OFST) & HV_SEL_MSK) +#define HV_SEL_110_VAL ((0x1 << HV_SEL_OFST) & HV_SEL_MSK) +#define HV_SEL_120_VAL ((0x2 << HV_SEL_OFST) & HV_SEL_MSK) +#define HV_SEL_150_VAL ((0x3 << HV_SEL_OFST) & HV_SEL_MSK) +#define HV_SEL_180_VAL ((0x4 << HV_SEL_OFST) & HV_SEL_MSK) +#define HV_SEL_200_VAL ((0x5 << HV_SEL_OFST) & HV_SEL_MSK) + +/** Dummy register */ +#define DUMMY_REG (0x21 << MEM_MAP_SHIFT) + +/** Firmware Version register */ +#define FPGA_VERSION_REG (0x22 << MEM_MAP_SHIFT) + +#define FPGA_VERSION_OFST (0) +#define FPGA_VERSION_MSK (0x00FFFFFF << FPGA_VERSION_OFST) // to get in format yymmdd + +/* Fix Pattern register */ +#define FIX_PATT_REG (0x23 << MEM_MAP_SHIFT) + +#define FIXED_PATT_VAL (0xACDC1980) + +/** Config register */ +#define Config_REG (0x26 << MEM_MAP_SHIFT) + +#define CONFIG_SLAVE_OFST (0) // Not used in FW & SW +#define CONFIG_SLAVE_MSK (0x00000001 << CONFIG_SLAVE_OFST) +#define CONFIG_MASTER_OFST (1) // Not used in FW & SW +#define CONFIG_MASTER_MSK (0x00000001 << CONFIG_MASTER_OFST) +#define CONFIG_TM_GT_ENBL_OFST (2) // Not used in FW & SW +#define CONFIG_TM_GT_ENBL_MSK (0x00000001 << CONFIG_TM_GT_ENBL_OFST) +#define CONFIG_CPU_RDT_OFST (12) +#define CONFIG_CPU_RDT_MSK (0x00000001 << CONFIG_CPU_RDT_OFST) +#define CONFIG_CNTNS_RDT_OFST (23) // Not used in FW & SW +#define CONFIG_CNTNS_RDT_MSK (0x00000001 << CONFIG_CNTNS_RDT_OFST) +#define CONFIG_ACCMLT_CNTS_OFST (24) // Not used in FW & SW +#define CONFIG_ACCMLT_CNTS_MSK (0x00000001 << CONFIG_ACCMLT_CNTS_OFST) + +/** 16 bit Control register */ +#define CONTROL_REG (0x24 << MEM_MAP_SHIFT) + +#define CONTROL_STRT_ACQ_OFST (0) +#define CONTROL_STRT_ACQ_MSK (0x00000001 << CONTROL_STRT_ACQ_OFST) +#define CONTROL_STP_ACQ_OFST (1) +#define CONTROL_STP_ACQ_MSK (0x00000001 << CONTROL_STP_ACQ_OFST) +#define CONTROL_STRT_FF_TST_OFST (2) // Not used in FW & SW +#define CONTROL_STRT_FF_TST_MSK (0x00000001 << CONTROL_STRT_FF_TST_OFST) +#define CONTROL_STP_FF_TST_OFST (3) // Not used in FW & SW +#define CONTROL_STP_FF_TST_MSK (0x00000001 << CONTROL_STP_FF_TST_OFST) +#define CONTROL_STRT_RDT_OFST (4) +#define CONTROL_STRT_RDT_MSK (0x00000001 << CONTROL_STRT_RDT_OFST) +#define CONTROL_STP_RDT_OFST (5) +#define CONTROL_STP_RDT_MSK (0x00000001 << CONTROL_STP_RDT_OFST) +#define CONTROL_STRT_EXPSR_OFST (6) +#define CONTROL_STRT_EXPSR_MSK (0x00000001 << CONTROL_STRT_EXPSR_OFST) +#define CONTROL_STP_EXPSR_OFST (7) +#define CONTROL_STP_EXPSR_MSK (0x00000001 << CONTROL_STP_EXPSR_OFST) +#define CONTROL_STRT_TRN_OFST (8) +#define CONTROL_STRT_TRN_MSK (0x00000001 << CONTROL_STRT_TRN_OFST) +#define CONTROL_STP_TRN_OFST (9) +#define CONTROL_STP_TRN_MSK (0x00000001 << CONTROL_STP_TRN_OFST) +#define CONTROL_SYNC_RST_OFST (10) +#define CONTROL_SYNC_RST_MSK (0x00000001 << CONTROL_SYNC_RST_OFST) + +/** Status register */ +#define STATUS_REG (0x25 << MEM_MAP_SHIFT) + +#define STATUS_RN_BSY_OFST (0) +#define STATUS_RN_BSY_MSK (0x00000001 << STATUS_RN_BSY_OFST) +#define STATUS_RDT_BSY_OFST (1) +#define STATUS_RDT_BSY_MSK (0x00000001 << STATUS_RDT_BSY_OFST) +#define STATUS_WTNG_FR_TRGGR_OFST (3) +#define STATUS_WTNG_FR_TRGGR_MSK (0x00000001 << STATUS_WTNG_FR_TRGGR_OFST) +#define STATUS_DLY_BFR_OFST (4) +#define STATUS_DLY_BFR_MSK (0x00000001 << STATUS_DLY_BFR_OFST) +#define STATUS_DLY_AFTR_OFST (5) +#define STATUS_DLY_AFTR_MSK (0x00000001 << STATUS_DLY_AFTR_OFST) +#define STATUS_EXPSNG_OFST (6) +#define STATUS_EXPSNG_MSK (0x00000001 << STATUS_EXPSNG_OFST) +#define STATUS_CNT_ENBL_OFST (7) +#define STATUS_CNT_ENBL_MSK (0x00000001 << STATUS_CNT_ENBL_OFST) +#define STATUS_RD_STT_OFST (8) +#define STATUS_RD_STT_MSK (0x00000007 << STATUS_RD_STT_OFST) +#define STATUS_RN_STT_OFST (12) +#define STATUS_RN_STT_MSK (0x00000007 << STATUS_RN_STT_OFST) +#define STATUS_SM_FF_FLL_OFST (15) +#define STATUS_SM_FF_FLL_MSK (0x00000001 << STATUS_SM_FF_FLL_OFST) +#define STATUS_ALL_FF_EMPTY_OFST (11) +#define STATUS_ALL_FF_EMPTY_MSK (0x00000001 << STATUS_ALL_FF_EMPTY_OFST) +#define STATUS_RN_MSHN_BSY_OFST (17) +#define STATUS_RN_MSHN_BSY_MSK (0x00000001 << STATUS_RN_MSHN_BSY_OFST) +#define STATUS_RD_MSHN_BSY_OFST (18) +#define STATUS_RD_MSHN_BSY_MSK (0x00000001 << STATUS_RD_MSHN_BSY_OFST) +#define STATUS_RN_FNSHD_OFST (20) +#define STATUS_RN_FNSHD_MSK (0x00000001 << STATUS_RN_FNSHD_OFST) +#define STATUS_IDLE_MSK (0x0000FFFF << 0) + +/** External Signal register */ +#define EXT_SIGNAL_REG (0x27 << MEM_MAP_SHIFT) + +#define EXT_SIGNAL_OFST (0) +#define EXT_SIGNAL_MSK (0x00000007 << EXT_SIGNAL_OFST) +#define EXT_SIGNAL_OFF_VAL ((0x0 << EXT_SIGNAL_OFST) & EXT_SIGNAL_MSK) +#define EXT_SIGNAL_TRGGR_IN_RSNG_VAL ((0x3 << EXT_SIGNAL_OFST) & EXT_SIGNAL_MSK) +#define EXT_SIGNAL_TRGGR_IN_FLLNG_VAL ((0x4 << EXT_SIGNAL_OFST) & EXT_SIGNAL_MSK) +/* +#define FPGA_SVN_REG 0x29<<11 +#define LOOK_AT_ME_REG 0x28<<11 +*/ +/** Chip of Interest register */ +#define CHIP_OF_INTRST_REG (0x2a << MEM_MAP_SHIFT) + +#define CHIP_OF_INTRST_ADC_SEL_OFST (0) +#define CHIP_OF_INTRST_ADC_SEL_MSK (0x0000001F << CHIP_OF_INTRST_ADC_SEL_OFST) +#define CHIP_OF_INTRST_NUM_CHNNLS_OFST (16) +#define CHIP_OF_INTRST_NUM_CHNNLS_MSK (0x0000FFFF << CHIP_OF_INTRST_NUM_CHNNLS_OFST) + +/** Board Version register */ +#define BOARD_REVISION_REG (0x2c << MEM_MAP_SHIFT) + +#define BOARD_REVISION_OFST (0) +#define BOARD_REVISION_MSK (0x0000FFFF << BOARD_REVISION_OFST) +#define DETECTOR_TYPE_OFST (16) +#define DETECTOR_TYPE_MSK (0x0000000F << DETECTOR_TYPE_OFST) +//#define DETECTOR_TYPE_GOTTHARD_VAL (??) +#define DETECTOR_TYPE_MOENCH_VAL (2) + +/* 16 bit Fifo Data register */ +//#define FIFO_DATA_REG (0x50 << MEM_MAP_SHIFT) // Not used in FW and SW (16bit) + +/* +#define MOD_DACS1_REG 0x65<<11 +#define MOD_DACS2_REG 0x66<<11 +#define MOD_DACS3_REG 0x67<<11 +*/ +/* Set Delay 64 bit register */ +#define SET_DELAY_LSB_REG (0x68 << MEM_MAP_SHIFT) +#define SET_DELAY_MSB_REG (0x69 << MEM_MAP_SHIFT) + +/* Get Delay 64 bit register */ +#define GET_DELAY_LSB_REG (0x6a << MEM_MAP_SHIFT) +#define GET_DELAY_MSB_REG (0x6b << MEM_MAP_SHIFT) + +/* Set Cycles 64 bit register */ +#define SET_TRAINS_LSB_REG (0x6c << MEM_MAP_SHIFT) +#define SET_TRAINS_MSB_REG (0x6d << MEM_MAP_SHIFT) + +/* Get Cycles 64 bit register */ +#define GET_TRAINS_LSB_REG (0x6e << MEM_MAP_SHIFT) +#define GET_TRAINS_MSB_REG (0x6f << MEM_MAP_SHIFT) + +/* Set Frames 64 bit register */ +#define SET_FRAMES_LSB_REG (0x70 << MEM_MAP_SHIFT) +#define SET_FRAMES_MSB_REG (0x71 << MEM_MAP_SHIFT) + +/* Get Frames 64 bit register */ +#define GET_FRAMES_LSB_REG (0x72 << MEM_MAP_SHIFT) +#define GET_FRAMES_MSB_REG (0x73 << MEM_MAP_SHIFT) + +/* Set Period 64 bit register */ +#define SET_PERIOD_LSB_REG (0x74 << MEM_MAP_SHIFT) +#define SET_PERIOD_MSB_REG (0x75 << MEM_MAP_SHIFT) + +/* Get Period 64 bit register */ +#define GET_PERIOD_LSB_REG (0x76 << MEM_MAP_SHIFT) +#define GET_PERIOD_MSB_REG (0x77 << MEM_MAP_SHIFT) + +/* Set Exptime 64 bit register */ +#define SET_EXPTIME_LSB_REG (0x78 << MEM_MAP_SHIFT) +#define SET_EXPTIME_MSB_REG (0x79 << MEM_MAP_SHIFT) + +/* Get Exptime 64 bit register */ +#define GET_EXPTIME_LSB_REG (0x7a << MEM_MAP_SHIFT) +#define GET_EXPTIME_MSB_REG (0x7b << MEM_MAP_SHIFT) + +/* Set Gates 64 bit register */ +//#define SET_GATES_LSB_REG (0x7c << MEM_MAP_SHIFT) // Not used in SW and FW +//#define SET_GATES_MSB_REG (0x7d << MEM_MAP_SHIFT) // Not used in SW and FW + +/* Dark Image starting address */ +#define DARK_IMAGE_REG (0x81 << MEM_MAP_SHIFT) + +/* Gain Image starting address */ +#define GAIN_IMAGE_REG (0x82 << MEM_MAP_SHIFT) + +/* Counter Block Memory starting address */ +#define COUNTER_MEMORY_REG (0x85 << MEM_MAP_SHIFT) + diff --git a/slsDetectorServers/gotthardDetectorServer/blackfin.h b/slsDetectorServers/gotthardDetectorServer/blackfin.h new file mode 120000 index 000000000..2873c7dc6 --- /dev/null +++ b/slsDetectorServers/gotthardDetectorServer/blackfin.h @@ -0,0 +1 @@ +../slsDetectorServer/blackfin.h \ No newline at end of file diff --git a/slsDetectorServers/gotthardDetectorServer/firmware_funcs.c b/slsDetectorServers/gotthardDetectorServer/firmware_funcs.c deleted file mode 100755 index d977b04e4..000000000 --- a/slsDetectorServers/gotthardDetectorServer/firmware_funcs.c +++ /dev/null @@ -1,2098 +0,0 @@ - -#include "server_defs.h" -#include "firmware_funcs.h" -#include "registers_g.h" - -#include -#include -#include - -#include -#include - - -u_int64_t CSP0BASE; -int phase_shift=DEFAULT_PHASE_SHIFT; -int ipPacketSize=DEFAULT_IP_PACKETSIZE; -int udpPacketSize=DEFAULT_UDP_PACKETSIZE; - - -int timingMode=AUTO_TIMING; -enum externalSignalFlag signalMode=EXT_SIG_OFF; -int ROI_flag=0; -int adcConfigured=-1; -int detectorFirstServer = 1; -enum detectorSettings thisSettings; -ROI rois[MAX_ROIS]; -int nROI=0; - -//for the 25um detectors -int masterflags = NO_MASTER; -int masterdefaultdelay = 62; -int patternphase = 0; -int adcphase = 0; -int slavepatternphase = 0; -int slaveadcphase = 0; -int rsttosw1delay = 2; -int startacqdelay = 1; - - -sls_detector_module *detectorModules=NULL; -int *detectorDacs=NULL; -int *detectorAdcs=NULL; - - -/** - ENEt conf structs - */ -typedef struct mac_header_struct{ - u_int8_t mac_dest_mac2; - u_int8_t mac_dest_mac1; - u_int8_t mac_dummy1; - u_int8_t mac_dummy2; - u_int8_t mac_dest_mac6; - u_int8_t mac_dest_mac5; - u_int8_t mac_dest_mac4; - u_int8_t mac_dest_mac3; - u_int8_t mac_src_mac4; - u_int8_t mac_src_mac3; - u_int8_t mac_src_mac2; - u_int8_t mac_src_mac1; - u_int16_t mac_ether_type; - u_int8_t mac_src_mac6; - u_int8_t mac_src_mac5; -} mac_header; - -typedef struct ip_header_struct { - u_int16_t ip_len; - u_int8_t ip_tos; - u_int8_t ip_ihl:4 ,ip_ver:4; - u_int16_t ip_offset:13,ip_flag:3; - u_int16_t ip_ident; - u_int16_t ip_chksum; - u_int8_t ip_protocol; - u_int8_t ip_ttl; - u_int32_t ip_sourceip; - u_int32_t ip_destip; -} ip_header; - -typedef struct udp_header_struct{ - u_int16_t udp_destport; - u_int16_t udp_srcport; - u_int16_t udp_chksum; - u_int16_t udp_len; -} udp_header; - -typedef struct mac_conf_struct{ - mac_header mac; - ip_header ip; - udp_header udp; - u_int32_t npack; - u_int32_t lpack; - u_int32_t npad; - u_int32_t cdone; -} mac_conf; - -typedef struct tse_conf_struct{ - u_int32_t rev; //0x0 - u_int32_t scratch; - u_int32_t command_config; - u_int32_t mac_0; //0x3 - u_int32_t mac_1; - u_int32_t frm_length; - u_int32_t pause_quant; - u_int32_t rx_section_empty; //0x7 - u_int32_t rx_section_full; - u_int32_t tx_section_empty; - u_int32_t tx_section_full; - u_int32_t rx_almost_empty; //0xB - u_int32_t rx_almost_full; - u_int32_t tx_almost_empty; - u_int32_t tx_almost_full; - u_int32_t mdio_addr0; //0xF - u_int32_t mdio_addr1; -}tse_conf; - - - -int mapCSP0(void) { - printf("Mapping memory\n"); -#ifndef VIRTUAL - int fd; - fd = open("/dev/mem", O_RDWR | O_SYNC, 0); - if (fd == -1) { - printf("\nCan't find /dev/mem!\n"); - return FAIL; - } - printf("/dev/mem opened\n"); - - CSP0BASE = (u_int32_t)mmap(0, MEM_SIZE, PROT_READ|PROT_WRITE, MAP_FILE|MAP_SHARED, fd, CSP0); - if (CSP0BASE == (u_int32_t)MAP_FAILED) { - printf("\nCan't map memmory area!!\n"); - return FAIL; - } - printf("CSP0 mapped\n"); - -#endif -#ifdef VIRTUAL - CSP0BASE = malloc(MEM_SIZE); - printf("memory allocated\n"); -#endif - printf("CSPObase is 0x%llx \n",CSP0BASE); - printf("CSPOBASE=from %llx to %llx\n",CSP0BASE,CSP0BASE+MEM_SIZE); - - printf("statusreg=%08x\n",bus_r(STATUS_REG)); - printf("\n\n"); - return OK; -} - -u_int16_t bus_r16(u_int32_t offset){ - volatile u_int16_t *ptr1; - ptr1=(u_int16_t*)(CSP0BASE+offset*2); - return *ptr1; -} - -u_int16_t bus_w16(u_int32_t offset, u_int16_t data) { - volatile u_int16_t *ptr1; - ptr1=(u_int16_t*)(CSP0BASE+offset*2); - *ptr1=data; - return OK; -} - - -u_int32_t bus_w(u_int32_t offset, u_int32_t data) { - volatile u_int32_t *ptr1; - - ptr1=(u_int32_t*)(CSP0BASE+offset*2); - *ptr1=data; - - return OK; -} - - -u_int32_t bus_r(u_int32_t offset) { - volatile u_int32_t *ptr1; - - ptr1=(u_int32_t*)(CSP0BASE+offset*2); - return *ptr1; -} - - - -int initDetector() { -#ifdef VERBOSE - printf("Board is for 1 module\n"); -#endif - detectorModules=malloc(sizeof(sls_detector_module)); - detectorDacs=malloc(NDAC*sizeof(int)); - detectorAdcs=malloc(NADC*sizeof(int)); -#ifdef VERBOSE - printf("modules from 0x%x to 0x%x\n",(unsigned int)(detectorModules), (unsigned int)(detectorModules)); - printf("dacs from 0x%x to 0x%x\n",(unsigned int)(detectorDacs), (unsigned int)(detectorDacs)); - printf("adcs from 0x%x to 0x%x\n",(unsigned int)(detectorAdcs), (unsigned int)(detectorAdcs)); -#endif - (detectorModules)->dacs=detectorDacs; - (detectorModules)->adcs=detectorAdcs; - (detectorModules)->ndac=NDAC; - (detectorModules)->nadc=NADC; - (detectorModules)->nchip=NCHIP; - (detectorModules)->nchan=NCHIP*NCHAN; - (detectorModules)->gain=0; - (detectorModules)->offset=0; - (detectorModules)->reg=0; - - - thisSettings=UNINITIALIZED; - - testFpga(); - - //gotthard specific - setPhaseShiftOnce(); - configureADC(); - setADC(-1); //already does setdaqreg and clean fifo. - - setSettings(DYNAMICGAIN); - setDefaultDacs(); - - - //Initialization - setFrames(1); - setTrains(1); - setExposureTime(1e6); - setPeriod(1e9); - setDelay(0); - setGates(0); - setTiming(GET_EXTERNAL_COMMUNICATION_MODE); - sendviaUDP(1); - setMasterSlaveConfiguration(); - - return OK; -} - - -int setDefaultDacs() { - printf("Setting Default Dac values\n"); - - int ret = OK; - int i = 0; - int retval[2]={-1,-1}; - const int defaultvals[NDAC] = DEFAULT_DAC_VALS; - - for(i = 0; i < NDAC; ++i) { - // if not already default, set it to default - if (setDACRegister(i, -1) != defaultvals[i]) { - setDAC(i, defaultvals[i], 0, retval); - if (abs(retval[0] - defaultvals[i])<=3) { - cprintf(RED, "Warning: Setting dac %d failed, wrote %d, read %d\n",i ,defaultvals[i], retval[0]); - ret = FAIL; - } - } - } - - return ret; -} - - - - - -void setMasterSlaveConfiguration(){ - - // global master default delay picked from config file - FILE* fd=fopen(CONFIG_FILE,"r"); - if(fd==NULL){ - cprintf(RED,"\nWarning: Could not open file\n"); - return; - } - cprintf(BLUE,"config file %s opened\n", CONFIG_FILE); - - char key[256]; - char value[256]; - char line[256]; - int ival=0; - u_int32_t val=0; - - while (fgets(line, sizeof(line), fd)) { - if(line[0] == '#') - continue; - sscanf(line, "%s %s\n", key, value); - if (!strcasecmp(key,"masterflags")) { - if (!strcasecmp(value,"is_master")) { - masterflags = IS_MASTER; - } - else if (!strcasecmp(value,"is_slave")) { - masterflags = IS_SLAVE; - } - else if (!strcasecmp(value,"no_master")){ - masterflags = NO_MASTER; - } - else { - cprintf(RED,"could not scan masterflags %s value from config file\n",value); - fclose(fd); - exit(EXIT_FAILURE); - } - - if (!detectorFirstServer) { - cprintf(BLUE, "Server has been started up before. Ignoring rest of config file\n"); - fclose(fd); - return; - } - } - else { - if(sscanf(value,"%d",&ival)<=0) { - cprintf(RED,"could not scan patternphase %s value from config file\n",value); - fclose(fd); - exit(EXIT_FAILURE); - } - - if (!strcasecmp(key,"masterdefaultdelay")) - masterdefaultdelay = ival; - else if (!strcasecmp(key,"patternphase")) - patternphase = ival; - else if (!strcasecmp(key,"adcphase")) - adcphase = ival; - else if (!strcasecmp(key,"slavepatternphase")) - slavepatternphase = ival; - else if (!strcasecmp(key,"slaveadcphase")) - slaveadcphase = ival; - else if (!strcasecmp(key,"rsttosw1delay")) - rsttosw1delay = ival; - else if (!strcasecmp(key,"startacqdelay")) - startacqdelay = ival; - else { - cprintf(RED,"could not scan parameter name %s from config file\n",key); - fclose(fd); - exit(EXIT_FAILURE); - } - } - - } - cprintf(BLUE, - "masterflags: %d\n" - "masterdefaultdelay:%d\n" - "patternphase:%d\n" - "adcphase:%d\n" - "slavepatternphase:%d\n" - "slaveadcphase:%d\n" - "rsttosw1delay:%d\n" - "startacqdelay:%d\n", - masterflags, - masterdefaultdelay, - patternphase, - adcphase, - slavepatternphase, - slaveadcphase, - rsttosw1delay, - startacqdelay); - - - - if (masterflags == IS_MASTER) { - // set delay - setDelay(0); - - /* Set pattern phase for the master module */ - val=bus_r(MULTI_PURPOSE_REG); - val = (val & (~(PLL_CLK_SEL_MSK))) | PLL_CLK_SEL_MASTER_VAL; - bus_w(MULTI_PURPOSE_REG,val); - setPhaseShift(patternphase); - /* Set adc phase for the master module */ - val=bus_r(MULTI_PURPOSE_REG); - val = (val & (~(PLL_CLK_SEL_MSK))) | PLL_CLK_SEL_MASTER_ADC_VAL; - bus_w(MULTI_PURPOSE_REG,val); - setPhaseShift(adcphase); - /* Set pattern phase for the slave module */ - val=bus_r(MULTI_PURPOSE_REG); - val = (val & (~(PLL_CLK_SEL_MSK))) | PLL_CLK_SEL_SLAVE_VAL; - bus_w(MULTI_PURPOSE_REG,val); - setPhaseShift(slavepatternphase); - /* Set adc phase for the slave module */ - val=bus_r(MULTI_PURPOSE_REG); - val = (val & (~(PLL_CLK_SEL_MSK))) | PLL_CLK_SEL_SLAVE_ADC_VAL; - bus_w(MULTI_PURPOSE_REG,val); - setPhaseShift(slaveadcphase); - /* Set start acq delay */ - val=bus_r(MULTI_PURPOSE_REG); -#ifdef VERBOSE - printf("Multipurpose reg:0x%x\n",bus_r(MULTI_PURPOSE_REG)); -#endif - val = (val & (~(START_ACQ_DELAY_MSK))) | ((startacqdelay << START_ACQ_DELAY_OFFSET) & (START_ACQ_DELAY_MSK)); - bus_w(MULTI_PURPOSE_REG,val); - printf("Start acq delay set. Multipurpose reg: 0x%x\n",bus_r(MULTI_PURPOSE_REG)); - } - - /* Set RST to SW1 delay */ - val=bus_r(MULTI_PURPOSE_REG); -#ifdef VERBOSE - printf("Multipurpose reg:0x%x\n",bus_r(MULTI_PURPOSE_REG)); -#endif - val = (val & (~(RST_TO_SW1_DELAY_MSK))) | ((rsttosw1delay << RST_TO_SW1_DELAY_OFFSET) & (RST_TO_SW1_DELAY_MSK)); - bus_w(MULTI_PURPOSE_REG,val); - printf("RST to SW1 delay set. Multipurpose reg:0x%x\n",bus_r(MULTI_PURPOSE_REG)); - - fclose(fd); -} - - - - -int configureADC(){ - printf("Preparing ADC\n"); - u_int32_t valw,codata,csmask; - int i,j,cdx,ddx; - cdx=0; ddx=1; - csmask=0x7c; // 1111100 - - for(j=0;j<3;j++){ - //command and value; - codata = 0; - if(j==0) - codata=(0x08<<8)+(0x3);//Power modes(global) //reset - else if(j==1) - codata=(0x08<<8)+(0x0);//Power modes(global) //chip run - else - codata = (0x14<<8)+(0x0);//Output mode //offset binary - - - // start point - valw=0xffffffff; - bus_w(ADC_SPI_REG,(valw)); - - //chip sel bar down - valw=((0xffffffff&(~csmask))); - bus_w(ADC_SPI_REG,valw); - - for (i=0;i<24;i++) { - //cldwn - valw=valw&(~(0x1<>(23-i))&0x1)<>16)>0){ - //bus_w(addr,0x0); //clear the reg - - if(reg==0){ - detectorFirstServer = 1; - printf("\nImplementing phase shift of %d\n",phase_shift); - for (i=1;i=0) { - bus_w(CONFIG_REG,d); - } -#ifdef VERBOSE - printf("configuration register is %x", bus_r(CONFIG_REG)); -#endif - return bus_r(CONFIG_REG); -} - - - - -int sendviaUDP(int start) { - u_int32_t addr=CONFIG_REG; -#ifdef VERBOSE - if(start) - printf("Setting up detector to send to Receiver\n"); - else - printf("Setting up detector to send to CPU\n"); -#endif - int reg=bus_r(addr); - //for start recever, write 0 and for stop, write 1 - if (!start) - bus_w(CONFIG_REG,reg|CPU_OR_RECEIVER_BIT); - else - bus_w(CONFIG_REG,reg&(~CPU_OR_RECEIVER_BIT)); - - reg=bus_r(addr); - //#ifdef VERBOSE - printf("Config Reg %x\n", reg); - //#endif - int d =reg&CPU_OR_RECEIVER_BIT; - if(d!=0) d=1; - if(d!=start) - return OK; - else - return FAIL; -} - - - - - - -int setDACRegister(int idac, int val) { - u_int32_t addr, reg, mask; - int off; -#ifdef VERBOSE - if(val==-1) - printf("Getting dac register%d \n",idac); - else - printf("Setting dac register %d to %d\n",idac,val); -#endif - - switch(idac){ - case 0: - case 1: - case 2: - addr=MOD_DACS1_REG; - break; - case 3: - case 4: - case 5: - addr=MOD_DACS2_REG; - break; - case 6: - case 7: - addr=MOD_DACS3_REG; - break; - default: - printf("weird idac value %d\n",idac); - return -1; - break; - } - //saving only the msb - val=val>>2; - - off=(idac%3)*10; - mask=~((0x3ff)<=0 && val>off)&0x3ff; - //since we saved only the msb - val=val<<2; - - //val=(bus_r(addr)>>off)&0x3ff; - - -#ifdef VERBOSE - printf("Dac %d register is %d\n\n",idac,val); -#endif - return val; -} - - - - - - - - - -u_int32_t setExtSignal(enum externalSignalFlag mode) { - - u_int32_t c; - c = bus_r(EXT_SIGNAL_REG); - -#ifdef VERBOSE - printf("settings signal variable number %d to value %04x\n", d, signals[d]); -#endif - - switch (mode) { - case TRIGGER_IN_RISING_EDGE: - case TRIGGER_IN_FALLING_EDGE: - - // set variable - signalMode = mode; - - // set signal only if trigger mode - if (timingMode==TRIGGER_EXPOSURE) - setFPGASignal(mode); - // switch off if not trigger mode, but variable remembers value - else - setFPGASignal(SIGNAL_OFF); - break; - - default: - mode = SIGNAL_OFF; - signalMode = mode; - setFPGASignal(mode); - break; - } - - return getExtSignal(); -} - - -int getExtSignal() { - return signalMode; -} - - -u_int32_t setFPGASignal(enum externalSignalFlag mode) { - - u_int32_t c = bus_r(EXT_SIGNAL_REG); - // offset is 0 as we only deal with the first signal index now. //int off = d * SIGNAL_OFFSET; - - // check and then write - if ((mode == SIGNAL_OFF) || (mode == TRIGGER_IN_RISING_EDGE) || (mode == TRIGGER_IN_FALLING_EDGE)) { -#ifdef VERBOSE - printf("writing signal register number %d mode %04x\n",0, (int) mode); -#endif - bus_w(EXT_SIGNAL_REG,( (c &~ (SIGNAL_MASK)) | ((int)mode) )); - } - return getFPGASignal(); -} - - - - -int getFPGASignal() { - - // offset is 0 as we only deal with the first signal index now. //int off = d * SIGNAL_OFFSET; - int mode = ((bus_r(EXT_SIGNAL_REG)) & SIGNAL_MASK); - - // check and then update variable - if ((mode == SIGNAL_OFF) || (mode == TRIGGER_IN_RISING_EDGE) || (mode == TRIGGER_IN_FALLING_EDGE)) { -#ifdef VERYVERBOSE - printf("gettings signal register number %d value %04x\n", d, (int)mode); -#endif - return (int)mode; - } else - return -1; -} - - - - - -int setTiming(int ti) { - - // set - if (ti != GET_EXTERNAL_COMMUNICATION_MODE) { - - // trigger - if (ti == TRIGGER_EXPOSURE) { - timingMode = ti; - if ((signalMode == TRIGGER_IN_RISING_EDGE) || (signalMode == TRIGGER_IN_FALLING_EDGE)) - setFPGASignal(signalMode); - else - setFPGASignal(SIGNAL_OFF); // only if both (timing & extsig) configured, its set to trigger, else off - } - - // auto - else { - timingMode = AUTO_TIMING; - setFPGASignal(SIGNAL_OFF); - } - } - - // get - int s = getFPGASignal(); - if ((s == TRIGGER_IN_RISING_EDGE) || (s == TRIGGER_IN_FALLING_EDGE)) - return TRIGGER_EXPOSURE; - return AUTO_TIMING; -} - - - - - - -u_int64_t getDetectorNumber() { - char output[255],mac[255]=""; - u_int64_t res=0; - FILE* sysFile = popen("ifconfig eth0 | grep HWaddr | cut -d \" \" -f 11", "r"); - fgets(output, sizeof(output), sysFile); - pclose(sysFile); - //getting rid of ":" - char * pch; - pch = strtok (output,":"); - while (pch != NULL){ - strcat(mac,pch); - pch = strtok (NULL, ":"); - } - sscanf(mac,"%llx",&res); - return res; -} - -u_int32_t getFirmwareVersion() { - return bus_r(FPGA_VERSION_REG); -} - -u_int32_t getFirmwareSVNVersion(){ - return bus_r(FPGA_SVN_REG); -} - - -// for fpga test -u_int32_t testFpga(void) { - printf("Testing FPGA:\n"); - volatile u_int32_t val,addr,val2; - int result=OK,i; - //fixed pattern - val=bus_r(FIX_PATT_REG); - if (val==FIXED_PATT_VAL) { - printf("fixed pattern ok!! %08x\n",val); - } else { - printf("fixed pattern wrong!! %08x\n",val); - result=FAIL; - } - - //dummy register - addr = DUMMY_REG; - for(i=0;i<1000000;i++) - { - val=0x5A5A5A5A-i; - bus_w(addr, val); - val=bus_r(addr); - if (val!=0x5A5A5A5A-i) { - printf("ATTEMPT:%d:\tFPGA dummy register wrong!! %x instead of %x \n",i,val,0x5A5A5A5A-i); - result=FAIL; - } - val=(i+(i<<10)+(i<<20)); - bus_w(addr, val); - val2=bus_r(addr); - if (val2!=val) { - printf("ATTEMPT:%d:\tFPGA dummy register wrong!! read %x instead of %x.\n",i,val2,val); - result=FAIL; - } - val=0x0F0F0F0F; - bus_w(addr, val); - val=bus_r(addr); - if (val!=0x0F0F0F0F) { - printf("ATTEMPT:%d:\tFPGA dummy register wrong!! %x instead of 0x0F0F0F0F \n",i,val); - result=FAIL; - } - val=0xF0F0F0F0; - bus_w(addr, val); - val=bus_r(addr); - if (val!=0xF0F0F0F0) { - printf("ATTEMPT:%d:\tFPGA dummy register wrong!! %x instead of 0xF0F0F0F0 \n\n",i,val); - result=FAIL; - } - } - if(result==OK) - { - printf("----------------------------------------------------------------------------------------------"); - printf("\nATTEMPT 1000000: FPGA DUMMY REGISTER OK!!!\n"); - printf("----------------------------------------------------------------------------------------------"); - } - printf("\n"); - return result; -} - - -int testBus() { - u_int32_t j; - u_int64_t i, n, nt; - // char cmd[100]; - u_int32_t val=0x0; - int ifail=OK; - // printf("%s\n",cmd); - // system(cmd); - i=0; - - n=1000000; - nt=n/100; - printf("testing bus %d times\n",(int)n); - while (i>1);//fpga - } - } - - bus_w(TEMP_IN_REG,(T1_CLK_BIT)|(T1_CS_BIT)|(T2_CLK_BIT)|(T2_CS_BIT));//standby - val=((int)tempVal)/4.0; - -#ifdef VERBOSE - printf("Temperature for the %s is %.2fC\n",cTempSensor[tempSensor],val); -#endif - return val; -} - - - - -int setSettings(int i) { -#ifdef VERBOSE - if(i==-1) - printf("\nReading settings of detector...\n"); - else - printf("\ninside set settings wit settings=%d...\n",i); -#endif - int confgain[] = CONF_GAIN; - int isett=-2,retval; - - //reading settings - if(i==GET_SETTINGS){ - retval=initConfGain(i,i); - if(retval==i) - isett=UNDEFINED; - } - //writing settings - else{ - retval=initConfGain(i,confgain[i]); - if(retval!=i) - isett=UNDEFINED; - } - //if error while read/writing - if(isett==UNDEFINED) - printf("Error:Weird Value read back from the Gain/Settings Reg\n"); - else{ - //validating the settings read back - if((retval>=HIGHGAIN)&&(retval<=VERYHIGHGAIN)) - isett=retval; - else{ - isett=UNDEFINED; - printf("Error:Wrong Settings Read out:%d\n",retval); - } - } - thisSettings=isett; - //#ifdef VERBOSE - printf("detector settings are %d\n",thisSettings); - //#endif - return thisSettings; -} - - - - - -int initConfGain(int isettings,int val){ - int retval; - u_int32_t addr=GAIN_REG; - - if(val!=-1){ -#ifdef VERBOSE - printf("Setting Gain with val:%d\n",val); -#endif - bus_w(addr,((val<>SETTINGS_OFFSET); -#ifdef VERBOSE - printf("Settings read from reg is %d\n",retval); -#endif - if((isettings!=-1)&&(retval!=isettings)){ - printf("\n\nSettings r\n\n"); - return -1; - } - - return retval; -} - - - -ROI* setROI(int n, ROI arg[], int *retvalsize, int *ret){ - - int i,adc; - ROI temp; - - if(n>=0){ - - //clear rois - for(i=0;i=0) && (adc<=4)); - else { - printf("warning:adc value greater than 5. deleting roi\n"); - adc=-1; - } - } - } - printf("\tGoing to enable adc: %d\n", adc); - - //set rois for just 1 adc - take only 1st roi - if(adc!=-1){ - rois[0].xmin=adc*(NCHAN*NCHIPS_PER_ADC); - rois[0].xmax=(adc+1)*(NCHAN*NCHIPS_PER_ADC)-1; - rois[0].ymin=-1; - rois[0].ymax=-1; - nROI = 1; - printf("\tActual xmin:%d xmax:%d\n",rois[0].xmin,rois[0].xmax); - }else - nROI = 0; - - if((n!=0) && ((arg[0].xmin!=rois[0].xmin)|| - (arg[0].xmax!=rois[0].xmax)|| - (arg[0].ymin!=rois[0].ymin)|| - (arg[0].ymax!=rois[0].ymax))) - *ret=FAIL; - if(n!=nROI) - *ret=FAIL; - - //set adc of interest - setADC(adc); - } - - //#ifdef VERBOSE - if (nROI) { - printf("Rois:\n"); - for( i=0;imac.mac_dest_mac1 =((macad>>(8*5))&0xFF);// 0x00; //pc7060 - mac_conf_regs->mac.mac_dest_mac2 =((macad>>(8*4))&0xFF);// 0x19; //pc7060 - mac_conf_regs->mac.mac_dest_mac3 =((macad>>(8*3))&0xFF);// 0x99; //pc7060 - mac_conf_regs->mac.mac_dest_mac4 =((macad>>(8*2))&0xFF);// 0x24; //pc7060 - mac_conf_regs->mac.mac_dest_mac5 =((macad>>(8*1))&0xFF);// 0xEB; //pc7060 - mac_conf_regs->mac.mac_dest_mac6 =((macad>>(8*0))&0xFF);// 0xEE; //pc7060 - /* - mac_conf_regs->mac.mac_src_mac1 = 0x00; - mac_conf_regs->mac.mac_src_mac2 = 0xAA; - mac_conf_regs->mac.mac_src_mac3 = 0xBB; - mac_conf_regs->mac.mac_src_mac4 = 0xCC; - mac_conf_regs->mac.mac_src_mac5 = 0xDD; - mac_conf_regs->mac.mac_src_mac6 = 0xEE; - */ - mac_conf_regs->mac.mac_src_mac1 =((detectormacad>>(8*5))&0xFF); - mac_conf_regs->mac.mac_src_mac2 =((detectormacad>>(8*4))&0xFF); - mac_conf_regs->mac.mac_src_mac3 =((detectormacad>>(8*3))&0xFF); - mac_conf_regs->mac.mac_src_mac4 =((detectormacad>>(8*2))&0xFF); - mac_conf_regs->mac.mac_src_mac5 =((detectormacad>>(8*1))&0xFF); - mac_conf_regs->mac.mac_src_mac6 =((detectormacad>>(8*0))&0xFF); - mac_conf_regs->mac.mac_ether_type = 0x0800; //ipv4 - - - mac_conf_regs->ip.ip_ver = 0x4; - mac_conf_regs->ip.ip_ihl = 0x5; - mac_conf_regs->ip.ip_tos = 0x0; - mac_conf_regs->ip.ip_len = ipPacketSize;//0x0522; // was 0x0526; - mac_conf_regs->ip.ip_ident = 0x0000; - mac_conf_regs->ip.ip_flag = 0x2; - mac_conf_regs->ip.ip_offset = 0x00; - mac_conf_regs->ip.ip_ttl = 0x70; - mac_conf_regs->ip.ip_protocol = 0x11; - mac_conf_regs->ip.ip_chksum = 0x0000 ; //6E42 now is automatically computed - mac_conf_regs->ip.ip_sourceip = detipad; //0x8181CA2E;129.129.202.46 - mac_conf_regs->ip.ip_destip = ipad; //CA57 - -#ifdef VERBOSE - printf("mac_dest:%llx %x:%x:%x:%x:%x:%x\n", - macad, - mac_conf_regs->mac.mac_dest_mac1, - mac_conf_regs->mac.mac_dest_mac2, - mac_conf_regs->mac.mac_dest_mac3, - mac_conf_regs->mac.mac_dest_mac4, - mac_conf_regs->mac.mac_dest_mac5, - mac_conf_regs->mac.mac_dest_mac6); - printf("mac_src:%llx %x:%x:%x:%x:%x:%x\n", - detectormacad, - mac_conf_regs->mac.mac_src_mac1, - mac_conf_regs->mac.mac_src_mac2, - mac_conf_regs->mac.mac_src_mac3, - mac_conf_regs->mac.mac_src_mac4, - mac_conf_regs->mac.mac_src_mac5, - mac_conf_regs->mac.mac_src_mac6); - printf("ip_ttl:%x\n",mac_conf_regs->ip.ip_ttl); -#endif - - //checksum - count=sizeof(mac_conf_regs->ip); - addr=&(mac_conf_regs->ip); - while( count > 1 ) { - sum += *addr++; - count -= 2; - } - if( count > 0 ) sum += *addr; // Add left-over byte, if any - while (sum>>16) sum = (sum & 0xffff) + (sum >> 16);// Fold 32-bit sum to 16 bits - checksum = (~sum)&0xffff; - mac_conf_regs->ip.ip_chksum = checksum; - //#ifdef VERBOSE - printf("IP header checksum is 0x%x s\n",(unsigned int)(checksum)); - //#endif - - mac_conf_regs->udp.udp_srcport = 0xE185; - mac_conf_regs->udp.udp_destport = udpport;//0xC351; - mac_conf_regs->udp.udp_len = udpPacketSize;//0x050E; //was 0x0512; - mac_conf_regs->udp.udp_chksum = 0x0000; - -#ifdef VERBOSE - printf("Configuring TSE\n"); -#endif - tse_conf_regs->rev = 0xA00; - tse_conf_regs->scratch = 0xCCCCCCCC; - tse_conf_regs->command_config = 0xB; - tse_conf_regs->mac_0 = 0x17231C00; - tse_conf_regs->mac_1 = 0xCB4A; - tse_conf_regs->frm_length = 0x5DC; //max frame length (1500 bytes) (was 0x41C) - tse_conf_regs->pause_quant = 0x0; - tse_conf_regs->rx_section_empty = 0x7F0; - tse_conf_regs->rx_section_full = 0x10; - tse_conf_regs->tx_section_empty = 0x3F8; //was 0x7F0; - tse_conf_regs->tx_section_full = 0x16; - tse_conf_regs->rx_almost_empty = 0x8; - tse_conf_regs->rx_almost_full = 0x8; - tse_conf_regs->tx_almost_empty = 0x8; - tse_conf_regs->tx_almost_full = 0x3; - tse_conf_regs->mdio_addr0 = 0x12; - tse_conf_regs->mdio_addr1 = 0x0; - mac_conf_regs->cdone = 0xFFFFFFFF; - - - if(ival) - bus_w(addrr, bus_r(addrr) | (INT_RSTN_BIT|ENET_RESETN_BIT|WRITE_BACK_BIT|DIGITAL_TEST_BIT)); //0x2840,write shadow regs.. - else - bus_w(addrr, bus_r(addrr) | (INT_RSTN_BIT|ENET_RESETN_BIT|WRITE_BACK_BIT)); //0x2840,write shadow regs.. - -#ifdef VERBOSE - printf("Value read from Multi-purpose Reg:%x\n",bus_r(addrr)); -#endif - // if(val!=0x2840) return -1; - - usleep(100000); - - bus_w(addrr, bus_r(addrr) &(~WRITE_BACK_BIT)); - - if(ival) - bus_w(addrr, bus_r(addrr) | (INT_RSTN_BIT|ENET_RESETN_BIT|SW1_BIT|DIGITAL_TEST_BIT)); //0x2820,write shadow regs.. - else - bus_w(addrr, bus_r(addrr) | (INT_RSTN_BIT|ENET_RESETN_BIT|SW1_BIT)); //0x2820,write shadow regs.. - -#ifdef VERBOSE - printf("Value read from Multi-purpose Reg:%x\n",bus_r(addrr)); -#endif - // if(val!=0x2820) return -1; - - usleep(1000 * 1000); - - return adcConfigured; -} - - -int getAdcConfigured(){ - return adcConfigured; -} - - - - - - - -// program dacq settings - -int64_t set64BitReg(int64_t value, int aLSB, int aMSB){ - int64_t v64; - u_int32_t vLSB,vMSB; - if (value!=-1) { - vLSB=value&(0xffffffff); - bus_w(aLSB,vLSB); - v64=value>> 32; - vMSB=v64&(0xffffffff); - bus_w(aMSB,vMSB); - } - return get64BitReg(aLSB, aMSB); - -} - -int64_t get64BitReg(int aLSB, int aMSB){ - int64_t v64; - u_int32_t vLSB,vMSB; - vLSB=bus_r(aLSB); - vMSB=bus_r(aMSB); - v64=vMSB; - v64=(v64<<32) | vLSB; - return v64; -} - -int64_t setFrames(int64_t value){ - return set64BitReg(value, SET_FRAMES_LSB_REG, SET_FRAMES_MSB_REG); -} - -int64_t getFrames(){ - return get64BitReg(GET_FRAMES_LSB_REG, GET_FRAMES_MSB_REG); -} - -int64_t setExposureTime(int64_t value){ - /* time is in ns */ - if (value!=-1) { - value = (value * 1E-3 * CLK_FREQ ) + 0.5; - } - return (set64BitReg(value,SET_EXPTIME_LSB_REG, SET_EXPTIME_MSB_REG) / - (1E-3 * CLK_FREQ)) + 0.5; -} - -int64_t getExposureTime(){ - return (get64BitReg(GET_EXPTIME_LSB_REG, GET_EXPTIME_MSB_REG) / - (1E-3 * CLK_FREQ)) + 0.5; -} - -int64_t setGates(int64_t value){ - return set64BitReg(value, SET_GATES_LSB_REG, SET_GATES_MSB_REG); -} - -int64_t getGates(){ - return get64BitReg(GET_GATES_LSB_REG, GET_GATES_MSB_REG); -} - -int64_t setPeriod(int64_t value){ - /* time is in ns */ - if (value!=-1) { - value = (value * 1E-3 * CLK_FREQ ) + 0.5; - } - return (set64BitReg(value,SET_PERIOD_LSB_REG, SET_PERIOD_MSB_REG) / - (1E-3 * CLK_FREQ)) + 0.5; -} - -int64_t getPeriod(){ - return (get64BitReg(GET_PERIOD_LSB_REG, GET_PERIOD_MSB_REG) / - (1E-3 * CLK_FREQ)) + 0.5; -} - -int64_t setDelay(int64_t value){ - /* time is in ns */ - if (value!=-1) { - if (masterflags == IS_MASTER) { - value += masterdefaultdelay; - cprintf(BLUE,"Actual delay for master: %lld\n", (long long int) value); - } - value = (value * 1E-3 * CLK_FREQ ) + 0.5; - } - int64_t retval = (set64BitReg(value,SET_DELAY_LSB_REG, SET_DELAY_MSB_REG) / - (1E-3 * CLK_FREQ)) + 0.5; - if (masterflags == IS_MASTER) { - cprintf(BLUE,"Actual delay read from master: %lld\n", (long long int) retval); - retval -= masterdefaultdelay; - } - - return retval; -} - -int64_t getDelay(){ - return (get64BitReg(GET_DELAY_LSB_REG, GET_DELAY_MSB_REG) / - (1E-3 * CLK_FREQ)) + 0.5; -} - -int64_t setTrains(int64_t value){ - return set64BitReg(value, SET_TRAINS_LSB_REG, SET_TRAINS_MSB_REG); -} - -int64_t getTrains(){ - return get64BitReg(GET_TRAINS_LSB_REG, GET_TRAINS_MSB_REG); -} - - - -int64_t getActualTime(){ - return (get64BitReg(GET_ACTUAL_TIME_LSB_REG, GET_ACTUAL_TIME_MSB_REG) / - (1E-3 * CLK_FREQ)) + 0.5; -} - -int64_t getMeasurementTime(){ - int64_t v=get64BitReg(GET_MEASUREMENT_TIME_LSB_REG, GET_MEASUREMENT_TIME_MSB_REG); - return (v / (1E-3 * CLK_FREQ)) + 0.5; -} - - - - - - -u_int32_t fifoReadStatus() { - return bus_r(STATUS_REG)&(SOME_FIFO_FULL_BIT | ALL_FIFO_EMPTY_BIT); -} - -u_int32_t fifo_full(void) { - return bus_r(STATUS_REG)&SOME_FIFO_FULL_BIT; -} - - -u_int32_t runBusy(void) { - u_int32_t s = bus_r(STATUS_REG) & RUN_BUSY_BIT; - return s; -} - -u_int32_t runState(void) { - int s=bus_r(STATUS_REG); -#ifdef VERBOSE -printf("status %04x\n",s); -#endif - -return s; -} - - -// State Machine - -int startStateMachine(){ - - //#ifdef VERBOSE - printf("*******Starting State Machine*******\n"); - //#endif - cleanFifo(); - // fifoReset(); - - bus_w16(CONTROL_REG, START_ACQ_BIT | START_EXPOSURE_BIT); - bus_w16(CONTROL_REG, 0x0); - printf("statusreg=%08x\n",bus_r(STATUS_REG)); - return OK; -} - - - - -int stopStateMachine(){ - - //#ifdef VERBOSE - cprintf(BG_RED,"*******Stopping State Machine*******\n"); - //#endif - bus_w16(CONTROL_REG, STOP_ACQ_BIT); - bus_w16(CONTROL_REG, 0x0); - usleep(500); - // if (!runBusy()) - if(!(bus_r(STATUS_REG)&RUNMACHINE_BUSY_BIT)) - return OK; - else - return FAIL; -} - - -int startReadOut(){ - u_int32_t status; -#ifdef VERBOSE - printf("Starting State Machine Readout\n"); -#endif - status=bus_r(STATUS_REG)&RUN_BUSY_BIT; - - bus_w16(CONTROL_REG, START_ACQ_BIT |START_READOUT_BIT); // start readout - bus_w16(CONTROL_REG, 0x0); - return OK; -} - - - - -void waitForAcquisitionFinish(){ - volatile u_int32_t t = bus_r(LOOK_AT_ME_REG); -#ifdef VERBOSE - printf("lookatmereg=x%x\n",t); -#endif - while((t&0x1)==0) { - if (runBusy()==0) { - t = bus_r(LOOK_AT_ME_REG); - if ((t&0x1)==0) { -#ifdef VERBOSE - printf("no frame found - exiting "); - printf("%08x %08x\n", runState(), bus_r(LOOK_AT_ME_REG)); -#endif - return; - } else { -#ifdef VERBOSE - printf("no frame found %x status %x\n", bus_r(LOOK_AT_ME_REG),runState()); -#endif - break; - } - } - t = bus_r(LOOK_AT_ME_REG); - } -} - - -int getStatus() { - u_int32_t retval= runState(); - enum runStatus s = IDLE; - int ret = OK; - - printf("\n\nSTATUS=%08x\n",retval); - - //stopped (external stop, also maybe fifo full) - if (runState() & STOPPED_BIT){ - printf("-----------------------------------STOPPED--------------------------------------x%0x\n",retval); - s=STOPPED; - - retval= runState(); - printf("reading again STATUS=%08x\n",retval); - if (runState() & STOPPED_BIT){ - printf("-----------------------------------ERROR--------------------------------------x%0x\n",retval); - s=ERROR; - } - } - - - //error - else if(retval&SOME_FIFO_FULL_BIT){ - printf("-----------------------------------ERROR--------------------------------------x%0x\n",retval); - s=ERROR; - } - - //runbusy=0 - // else if(!(retval&RUNMACHINE_BUSY_BIT)){ //commented by Anna 24.10.2012 - else if(!(retval&RUN_BUSY_BIT)){ // by Anna 24.10.2012 - - //and readbusy=1, its last frame read - if((retval&READMACHINE_BUSY_BIT) ){ // - - - printf("-----------------------------------READ MACHINE BUSY--------------------------\n"); - s=TRANSMITTING; - } else if (retval&ALL_FIFO_EMPTY_BIT) { - printf("-----------------------------------DATA IN FIFO--------------------------\n"); - s=TRANSMITTING; - - } - //and readbusy=0,idle - else if(!(retval&0xffff)){ - //if(!(retval&0x00000001)){ - printf("-----------------------------------IDLE--------------------------------------\n"); - s=IDLE; - } else { - printf("-----------------------------------Unknown status %08x--------------------------------------\n", retval); - s=ERROR; - ret=FAIL; - } - } - //if runbusy=1 - else { - if (retval&WAITING_FOR_TRIGGER_BIT){ - printf("-----------------------------------WAITING-----------------------------------\n"); - s=WAITING; - } - else{ - printf("-----------------------------------RUNNING-----------------------------------\n"); - s=RUNNING; - } - } - - return s; -} - - - -int loadImage(int index, short int ImageVals[]){ - u_int32_t address; - switch (index) { - case DARK_IMAGE : - address = DARK_IMAGE_REG; - break; - case GAIN_IMAGE : - address = GAIN_IMAGE_REG; - break; - } - volatile u_int16_t *ptr; - ptr=(u_int16_t*)(CSP0BASE+address*2); -#ifdef VERBOSE -int i; -for(i=0;i<6;i++) - printf("%d:%d\t",i,ImageVals[i]); -#endif -memcpy((char*)ptr,(char*)ImageVals ,DATA_BYTES); -#ifdef VERBOSE -printf("\nLoaded x%08x address with image of index %d\n",(unsigned int)(ptr),index); -#endif -return OK; -} - - - -int readCounterBlock(int startACQ, short int CounterVals[]){ - - - u_int32_t val; - volatile u_int16_t *ptr; - - u_int32_t address = COUNTER_MEMORY_REG; - ptr=(u_int16_t*)(CSP0BASE+address*2); - - - if (runBusy()) { - if(stopStateMachine()==FAIL) - return FAIL; - //waiting for the last frame read to be done - while(runBusy()) usleep(500); -#ifdef VERBOSE - printf("State machine stopped\n"); -#endif - } - - val=bus_r(MULTI_PURPOSE_REG); -#ifdef VERBOSE - printf("Value of multipurpose reg:%d\n",bus_r(MULTI_PURPOSE_REG)); -#endif - - memcpy((char*)CounterVals,(char*)ptr,DATA_BYTES); -#ifdef VERBOSE - int i; - printf("Copied counter memory block with size of %d bytes..\n",DATA_BYTES); - for(i=0;i<6;i++) - printf("%d: %d\t",i,CounterVals[i]); -#endif - - - bus_w(MULTI_PURPOSE_REG,(val&~RESET_COUNTER_BIT)); -#ifdef VERBOSE - printf("\nClearing bit 2 of multipurpose reg:%d\n",bus_r(MULTI_PURPOSE_REG)); -#endif - - if(startACQ==1){ - startStateMachine(); - if(runBusy()) - printf("State machine RUNNING\n"); - else - printf("State machine IDLE\n"); - } - - - return OK; -} - - - - -int resetCounterBlock(int startACQ){ - - char *counterVals=NULL; - counterVals=realloc(counterVals,DATA_BYTES); - - int ret = OK; - u_int32_t val; - volatile u_int16_t *ptr; - - - u_int32_t address = COUNTER_MEMORY_REG; - ptr=(u_int16_t*)(CSP0BASE+address*2); - - - if (runBusy()) { - if(stopStateMachine()==FAIL) - return FAIL; - //waiting for the last frame read to be done - while(runBusy()) usleep(500); -#ifdef VERBOSE - printf("State machine stopped\n"); -#endif - } - - val=bus_r(MULTI_PURPOSE_REG); -#ifdef VERBOSE - printf("Value of multipurpose reg:%d\n",bus_r(MULTI_PURPOSE_REG)); -#endif - - - bus_w(MULTI_PURPOSE_REG,(val|RESET_COUNTER_BIT)); -#ifdef VERBOSE - printf("Setting bit 2 of multipurpose reg:%d\n",bus_r(MULTI_PURPOSE_REG)); -#endif - - - memcpy((char*)counterVals,(char*)ptr,DATA_BYTES); -#ifdef VERBOSE - int i; - printf("Copied counter memory block with size of %d bytes..\n",(int)sizeof(counterVals)); - for(i=0;i<6;i=i+2) - printf("%d: %d\t",i,*(counterVals+i)); -#endif - - - bus_w(MULTI_PURPOSE_REG,(val&~RESET_COUNTER_BIT)); -#ifdef VERBOSE - printf("\nClearing bit 2 of multipurpose reg:%d\n",bus_r(MULTI_PURPOSE_REG)); -#endif - - if(startACQ==1){ - startStateMachine(); - if(runBusy()) - printf("State machine RUNNING\n"); - else - printf("State machine IDLE\n"); - } - - if(sizeof(counterVals)<=0){ - printf("ERROR:size of counterVals=%d\n",(int)sizeof(counterVals)); - ret = FAIL; - } - - return ret; - -} - - - - - - -int copyModule(sls_detector_module *destMod, sls_detector_module *srcMod) { - - int idac, iadc; - - int ret=OK; - -#ifdef VERBOSE - printf("Copying module %x to module %x\n",(unsigned int)(srcMod),(unsigned int)(destMod)); -#endif - - if (srcMod->serialnumber>=0){ - destMod->serialnumber=srcMod->serialnumber; - } - if ((srcMod->nchip)>(destMod->nchip)) { - printf("Number of chip of source is larger than number of chips of destination\n"); - return FAIL; - } - if ((srcMod->nchan)>(destMod->nchan)) { - printf("Number of channels of source is larger than number of channels of destination\n"); - return FAIL; - } - if ((srcMod->ndac)>(destMod->ndac)) { - printf("Number of dacs of source is larger than number of dacs of destination\n"); - return FAIL; - } - if ((srcMod->nadc)>(destMod->nadc)) { - printf("Number of dacs of source is larger than number of dacs of destination\n"); - return FAIL; - } - -#ifdef VERBOSE - printf("DACs: src %d, dest %d\n",srcMod->ndac,destMod->ndac); - printf("ADCs: src %d, dest %d\n",srcMod->nadc,destMod->nadc); - printf("Chips: src %d, dest %d\n",srcMod->nchip,destMod->nchip); - printf("Chans: src %d, dest %d\n",srcMod->nchan,destMod->nchan); - -#endif - - destMod->ndac=srcMod->ndac; - destMod->nadc=srcMod->nadc; - destMod->nchip=srcMod->nchip; - destMod->nchan=srcMod->nchan; - if (srcMod->reg>=0) - destMod->reg=srcMod->reg; -#ifdef VERBOSE - printf("Copying register %x (%x)\n",destMod->reg,srcMod->reg ); -#endif - if (srcMod->gain>=0) - destMod->gain=srcMod->gain; - if (srcMod->offset>=0) - destMod->offset=srcMod->offset; - - for (idac=0; idac<(srcMod->ndac); idac++) { - if (*((srcMod->dacs)+idac)>=0) - *((destMod->dacs)+idac)=*((srcMod->dacs)+idac); - } - for (iadc=0; iadc<(srcMod->nadc); iadc++) { - if (*((srcMod->adcs)+iadc)>=0) - *((destMod->adcs)+iadc)=*((srcMod->adcs)+iadc); - } - return ret; -} - - - - - - - -int setDAC(int ind, int val,int mV, int retval[]) { - - if(mV) - val = (val*4096)/2500; - - if (val>=0) - initDAC(ind,val); - clearDACSregister(); - - retval[0] = setDACRegister(ind, -1); - retval[1] = (retval[0]*2500)/4096; - return retval[0]; - -} - - - -int getDAC(int ind) { - return setDACRegister(ind, -1); -} - - - - - - - -int setModule(sls_detector_module myMod) { - - printf("\ninside setmodule..\n"); - - int v[NDAC]; - v[VREF_DS]=(myMod.dacs)[0]; - v[VCASCN_PB]=(myMod.dacs)[1]; - v[VCASCP_PB]=(myMod.dacs)[2]; - v[VOUT_CM]=(myMod.dacs)[3]; - v[VCASC_OUT]=(myMod.dacs)[4]; - v[VIN_CM]=(myMod.dacs)[5]; - v[VREF_COMP]=(myMod.dacs)[6]; - v[IB_TESTC]=(myMod.dacs)[7]; - -#ifdef VERBOSE - printf("vrefds=%d\n",v[VREF_DS]); - printf("vcascn=%d\n",v[VCASCN_PB]); - printf("vcascp=%d\n",v[VCASCP_PB]); - printf("vout=%d\n",v[VOUT_CM]); - printf("vcasc=%d\n",v[VCASC_OUT]); - printf("vin=%d\n",v[VIN_CM]); - printf("vref_comp=%d\n",v[VREF_COMP]); - printf("ib_testc=%d\n",v[IB_TESTC]); -#endif - - initDACs(v); - clearDACSregister(); - - if (detectorModules) { - copyModule(detectorModules,&myMod); - } - - //setting the conf gain and the settings register - setSettings(myMod.reg); - - return myMod.reg; -} - - - -void getModule(sls_detector_module* myMod) { - if (detectorModules) { - copyModule(myMod,detectorModules); - } -} - - - -void initDACs(int* v) { -#ifdef VERBOSE - printf("\n..inside initdacs\n"); -#endif - int iaddr; - for (iaddr=0; iaddr<8; iaddr++) { - initDAC(iaddr, v[iaddr]); - } -} - - - -void initDAC(int dac_addr, int value) { -#ifdef VERBOSE - printf("Programming dac %d with value %d\n", dac_addr, value); -#endif - clearDACSregister(); - if (value >= 0) { - program_one_dac(dac_addr,value); - } - nextDAC(); -} - - - - - -void clearDACSregister() { - putout("1111111111111111");//reset - putout("1111111111111110");//cs down -} - - -void nextDAC() { - putout("1111111111111011");//cs up - putout("1111111111111001");//clk down - putout("1111111111111111");//reset -} - - - -void program_one_dac(int addr, int value) { - -#ifdef VERBOSE - printf("programming dac %d value %d module %d\n",addr, value); -#endif - - - int i,idac,bit, control; - int v=value; - - control=32+addr; - value=(value<<4) | (control<< 16); - - - for (i=0;i<24;i++) { - bit=value & (1<<(23-i)); - if (bit) { - putout("1111111111111100");//clk down - putout("1111111111111100");//write data - putout("1111111111111110");//clk up - } - else - { - putout("1111111111111000");//clk down - putout("1111111111111000");//write data - putout("1111111111111010");//clk up - } - } - - idac=addr; - - - if (detectorDacs) { - detectorDacs[idac]=v; -#ifdef VERBOSE - printf("index=%d, val=%d addr=%x\n", idac, v, (unsigned int)(detectorDacs+idac)); -#endif - setDACRegister(idac,v); - } -} - - - - - - - - - - diff --git a/slsDetectorServers/gotthardDetectorServer/firmware_funcs.h b/slsDetectorServers/gotthardDetectorServer/firmware_funcs.h deleted file mode 100755 index 552d2f6ad..000000000 --- a/slsDetectorServers/gotthardDetectorServer/firmware_funcs.h +++ /dev/null @@ -1,120 +0,0 @@ -#ifndef FIRMWARE_FUNCS_H -#define FIRMWARE_FUNCS_H - - -#include "sls_detector_defs.h" - - -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -int mapCSP0(void); -u_int16_t bus_r16(u_int32_t offset); -u_int16_t bus_w16(u_int32_t offset, u_int16_t data);//aldos function -u_int32_t bus_w(u_int32_t offset, u_int32_t data); -u_int32_t bus_r(u_int32_t offset); - -int initDetector(); -int setDefaultDacs(); -void setMasterSlaveConfiguration(); -int configureADC(); -int setPhaseShiftOnce(); -int setPhaseShift(int numphaseshift); -int cleanFifo(); -int setDAQRegister(); -u_int32_t putout(char *s); -int setConfigurationRegister(int d); -int sendviaUDP(int d); -int setDACRegister(int idac, int val); - - -u_int32_t setExtSignal(enum externalSignalFlag mode); -int getExtSignal(); -u_int32_t setFPGASignal(enum externalSignalFlag mode); -int getFPGASignal(); - -int setTiming(int t); - -u_int64_t getDetectorNumber(); -u_int32_t getFirmwareVersion(); -u_int32_t getFirmwareSVNVersion(); - -u_int32_t testFpga(void); -int testBus(void); - -int initHighVoltage(int val); -int getTemperature(int tempSensor); -int setSettings(int i); -int initConfGain(int isettings,int val); -ROI* setROI(int n, ROI arg[], int *retvalsize, int *ret); -int setADC(int adc); -int configureMAC(int ipad, long long int macad, long long int detectormacadd, int detipad, int ival, int udpport); -int getAdcConfigured(); - - -int64_t set64BitReg(int64_t value, int aLSB, int aMSB); -int64_t get64BitReg(int aLSB, int aMSB); - -int64_t setFrames(int64_t value); -int64_t getFrames(); - -int64_t setExposureTime(int64_t value); -int64_t getExposureTime(); - -int64_t setGates(int64_t value); -int64_t getGates(); - -int64_t setPeriod(int64_t value); -int64_t getPeriod(); - -int64_t setDelay(int64_t value); -int64_t getDelay(); - -int64_t setTrains(int64_t value); -int64_t getTrains(); - -int64_t getActualTime(); -int64_t getMeasurementTime(); - -u_int32_t fifoReadStatus(); -u_int32_t fifo_full(void); -u_int32_t runBusy(void); -u_int32_t runState(void); -int startStateMachine(); -int stopStateMachine(); -int startReadOut(); -void waitForAcquisitionFinish(); -int getStatus(); - -int loadImage(int index, short int ImageVals[]); -int readCounterBlock(int startACQ, short int CounterVals[]); -int resetCounterBlock(int startACQ); - -int copyModule(sls_detector_module *destMod, sls_detector_module *srcMod); - -int setDAC(int ind,int val,int mV, int retval[]); -int getDAC(int ind); - -int setModule(sls_detector_module); -void getModule(sls_detector_module*); - -void initDACs(int* v); -void initDAC(int dac_addr, int value); -void clearDACSregister(); -void nextDAC(); -void program_one_dac(int addr, int value); - - - - - - -#endif diff --git a/slsDetectorServers/gotthardDetectorServer/gotthardDetectorServer_refactor b/slsDetectorServers/gotthardDetectorServer/gotthardDetectorServer_refactor deleted file mode 100755 index fdd03de642eb707d066019b47e1eaa08f0d2fd21..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 86044 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 diff --git a/slsDetectorServers/gotthardDetectorServer/logger.h b/slsDetectorServers/gotthardDetectorServer/logger.h new file mode 120000 index 000000000..ff1930ce3 --- /dev/null +++ b/slsDetectorServers/gotthardDetectorServer/logger.h @@ -0,0 +1 @@ +../slsDetectorServer/logger.h \ No newline at end of file diff --git a/slsDetectorServers/gotthardDetectorServer/server.c b/slsDetectorServers/gotthardDetectorServer/server.c deleted file mode 100755 index 2c571d748..000000000 --- a/slsDetectorServers/gotthardDetectorServer/server.c +++ /dev/null @@ -1,103 +0,0 @@ -/* A simple server in the internet domain using TCP - The port number is passed as an argument */ - -#include "sls_detector_defs.h" - -#include "communication_funcs.h" -#include "server_funcs.h" -#include -#include - - -extern int sockfd; -extern int phase_shift; - - - -void error(char *msg) -{ - perror(msg); -} - -int main(int argc, char *argv[]) -{ - int portno, b; - char cmd[100]; - int retval=OK; - int sd, fd; - int iarg; - for(iarg=1; iarg - - -// Hardware definitions -#define NCHAN 128 -#define NCHIP 10 -#define NDAC 8 -#define NADC 5 -#define NCHANS NCHAN*NCHIP -#define NDACS NDAC -#define NCHIPS_PER_ADC 2 - -#define DYNAMIC_RANGE 16 -#define DATA_BYTES (NCHIP*NCHAN*2) - -// for 25 um -#define CONFIG_FILE "config.txt" - - - -#define ADCSYNC_VAL 0x32214 -#define TOKEN_RESTART_DELAY 0x88000000 -#define TOKEN_RESTART_DELAY_ROI 0x1b000000 -#define TOKEN_TIMING_REV1 0x1f16 -#define TOKEN_TIMING_REV2 0x1f0f - -#define DEFAULT_PHASE_SHIFT 120 -#define DEFAULT_IP_PACKETSIZE 0x0522 -#define DEFAULT_UDP_PACKETSIZE 0x050E -#define ADC1_IP_PACKETSIZE (256*2+14+20) -#define ADC1_UDP_PACKETSIZE (256*2+4+8+2) - -#define CLK_FREQ 32.007729 - -#define DAC_DR 1024 -#define CONF_GAIN { \ - 0, /*standard gain*/ \ - 0, /*fast gain*/ \ - 0, /*high gain*/ \ - 8, /*dynamic gain*/ \ - 6, /*low gain*/ \ - 2, /*medium gain*/ \ - 1 /*very high gain*/ \ -}; -//dynamic gain confgain yet to be figured out-probably 8 or 16 - -// DAC definitions -enum dacsVal{VREF_DS, VCASCN_PB, VCASCP_PB, VOUT_CM, VCASC_OUT, VIN_CM, VREF_COMP, IB_TESTC,HIGH_VOLTAGE, CONFGAIN}; -#define DEFAULT_DAC_VALS { \ - 660, /* VREF_DS */ \ - 650, /* VCASCN_PB */ \ - 1480, /* VCASCP_PB */ \ - 1520, /* VOUT_CM */ \ - 1320, /* VCASC_OUT */ \ - 1350, /* VIN_CM */ \ - 350, /* VREF_COMP */ \ - 2001 /* IB_TESTC */ \ -}; - -//Register Definitions for temp,hv,dac gain -enum adcVals{TEMP_FPGA, TEMP_ADC}; - - -#endif diff --git a/slsDetectorServers/gotthardDetectorServer/server_funcs.c b/slsDetectorServers/gotthardDetectorServer/server_funcs.c deleted file mode 100755 index 0fedaffbe..000000000 --- a/slsDetectorServers/gotthardDetectorServer/server_funcs.c +++ /dev/null @@ -1,2185 +0,0 @@ -#include "sls_detector_defs.h" -#include "server_funcs.h" -#include "server_defs.h" -#include "firmware_funcs.h" -#include "registers_g.h" -#include "gitInfoGotthard.h" -#include "AD9257.h" // include "commonServerFunctions.h" -#include "versionAPI.h" - -#define FIFO_DATA_REG_OFF 0x50<<11 -#define CONTROL_REG 0x24<<11 -// Global variables - -int (*flist[256])(int); - -//defined in the detector specific file -#ifdef GOTTHARDD -const enum detectorType myDetectorType=GOTTHARD; -#else -const enum detectorType myDetectorType=GENERIC; -#endif - - -extern int storeInRAM; - -extern int lockStatus; -extern char lastClientIP[INET_ADDRSTRLEN]; -extern char thisClientIP[INET_ADDRSTRLEN]; -extern int differentClients; - -/* global variables for optimized readout */ - -char mess[MAX_STR_LENGTH]; -int digitalTestBit = 0; - - -int init_detector( int b) { - - if (mapCSP0()==FAIL) { - printf("Could not map memory\n"); - exit(-1); - } - - //confirm if it is really gotthard - if (((bus_r(PCB_REV_REG) & DETECTOR_TYPE_MASK)>> DETECTOR_TYPE_OFFSET) == MOENCH_MODULE){ - printf("This is a MOENCH detector. Exiting Gotthard Server.\n\n"); - exit(-1); - } - - if (b) { - printf("***This is a GOTTHARD detector with %d chips per module***\n", NCHIP); - printf("\nBoard Revision:0x%x\n",(bus_r(PCB_REV_REG)&BOARD_REVISION_MASK)); - initDetector(); - printf("Initializing Detector\n"); - } - strcpy(mess,"dummy message"); - strcpy(lastClientIP,"none"); - strcpy(thisClientIP,"none1"); - lockStatus=0; - return OK; -} - - -int decode_function(int file_des) { - int fnum,n; - int retval=FAIL; -#ifdef VERBOSE - printf( "receive data\n"); -#endif - n = receiveDataOnly(file_des,&fnum,sizeof(fnum)); - if (n <= 0) { -#ifdef VERBOSE - printf("ERROR reading from socket %d, %d %d\n", n, fnum, file_des); -#endif - return FAIL; - } -#ifdef VERBOSE - else - printf("size of data received %d\n",n); -#endif - -#ifdef VERBOSE - printf( "calling function fnum = %d %x\n",fnum,(unsigned int)(flist[fnum])); -#endif - if (fnum<0 || fnum>255) - fnum=255; - retval=(*flist[fnum])(file_des); - if (retval==FAIL) - printf( "Error executing the function = %d \n",fnum); - return retval; -} - - -int function_table() { - int i; - for (i=0;i<256;i++){ - flist[i]=&M_nofunc; - } - flist[F_EXEC_COMMAND] = &exec_command; - flist[F_GET_DETECTOR_TYPE] = &get_detector_type; - flist[F_SET_EXTERNAL_SIGNAL_FLAG] = &set_external_signal_flag; - flist[F_SET_EXTERNAL_COMMUNICATION_MODE] = &set_external_communication_mode; - flist[F_GET_ID] = &get_id; - flist[F_DIGITAL_TEST] = &digital_test; - flist[F_SET_DAC] = &set_dac; - flist[F_GET_ADC] = &get_adc; - flist[F_WRITE_REGISTER] = &write_register; - flist[F_READ_REGISTER] = &read_register; - flist[F_SET_MODULE] = &set_module; - flist[F_GET_MODULE] = &get_module; - flist[F_SET_SETTINGS] = &set_settings; - flist[F_GET_THRESHOLD_ENERGY] = &M_nofunc; - flist[F_START_ACQUISITION] = &start_acquisition; - flist[F_STOP_ACQUISITION] = &stop_acquisition; - flist[F_START_READOUT] = &start_readout; - flist[F_GET_RUN_STATUS] = &get_run_status; - flist[F_START_AND_READ_ALL] = &start_and_read_all; - flist[F_READ_ALL] = &read_all; - flist[F_SET_TIMER] = &set_timer; - flist[F_GET_TIME_LEFT] = &get_time_left; - flist[F_SET_DYNAMIC_RANGE] = &set_dynamic_range; - flist[F_SET_READOUT_FLAGS] = &set_readout_flags; - flist[F_SET_ROI] = &set_roi; - flist[F_SET_SPEED] = &set_speed; - flist[F_EXIT_SERVER] = &exit_server; - flist[F_LOCK_SERVER] = &lock_server; - flist[F_GET_LAST_CLIENT_IP] = &get_last_client_ip; - flist[F_SET_PORT] = &set_port; - flist[F_UPDATE_CLIENT] = &update_client; - flist[F_CONFIGURE_MAC] = &configure_mac; - flist[F_LOAD_IMAGE] = &load_image; - flist[F_READ_COUNTER_BLOCK] = &read_counter_block; - flist[F_RESET_COUNTER_BLOCK] = &reset_counter_block; - flist[F_CALIBRATE_PEDESTAL] = &M_nofunc; - flist[F_ENABLE_TEN_GIGA] = &M_nofunc; - flist[F_SET_ALL_TRIMBITS] = &M_nofunc; - flist[F_SET_CTB_PATTERN] = &M_nofunc; - flist[F_WRITE_ADC_REG] = &write_adc_register; - flist[F_SET_COUNTER_BIT] = &M_nofunc; - flist[F_PULSE_PIXEL] = &M_nofunc; - flist[F_PULSE_PIXEL_AND_MOVE] = &M_nofunc; - flist[F_PULSE_CHIP] = &M_nofunc; - flist[F_SET_RATE_CORRECT] = &M_nofunc; - flist[F_GET_RATE_CORRECT] = &M_nofunc; - flist[F_SET_NETWORK_PARAMETER] = &M_nofunc; - flist[F_PROGRAM_FPGA] = &M_nofunc; - flist[F_RESET_FPGA] = &M_nofunc; - flist[F_POWER_CHIP] = &M_nofunc; - flist[F_ACTIVATE] = &M_nofunc; - flist[F_PREPARE_ACQUISITION] = &M_nofunc; - flist[F_THRESHOLD_TEMP] = &M_nofunc; - flist[F_TEMP_CONTROL] = &M_nofunc; - flist[F_TEMP_EVENT] = &M_nofunc; - flist[F_AUTO_COMP_DISABLE] = &M_nofunc; - flist[F_STORAGE_CELL_START] = &M_nofunc; - flist[F_CHECK_VERSION] = &check_version; - flist[F_SOFTWARE_TRIGGER] = &M_nofunc; - return OK; -} - - -int M_nofunc(int file_des){ - - int ret=FAIL; - int n = 1; - while (n > 0) - n = receiveData(file_des,mess,MAX_STR_LENGTH,OTHER); - - sprintf(mess,"Unrecognized Function. Please do not proceed.\n"); - cprintf(BG_RED,"Error: %s",mess); - - sendDataOnly(file_des,&ret,sizeof(ret)); - sendDataOnly(file_des,mess,sizeof(mess)); - return GOODBYE; -} - - - - - -int exec_command(int file_des) { - char cmd[MAX_STR_LENGTH]; - char answer[MAX_STR_LENGTH]; - int retval=OK; - int sysret=0; - int n=0; - - /* receive arguments */ - n = receiveDataOnly(file_des,cmd,MAX_STR_LENGTH); - if (n < 0) { - sprintf(mess,"Error reading from socket\n"); - retval=FAIL; - } - - /* execute action if the arguments correctly arrived*/ - if (retval==OK) { -#ifdef VERBOSE - printf("executing command %s\n", cmd); -#endif - if (lockStatus==0 || differentClients==0) - sysret=system(cmd); - - //should be replaced by popen - if (sysret==0) { - sprintf(answer,"Succeeded\n"); - if (lockStatus==1 && differentClients==1) - sprintf(answer,"Detector locked by %s\n", lastClientIP); - } else { - sprintf(answer,"Failed\n"); - retval=FAIL; - } - } else { - sprintf(answer,"Could not receive the command\n"); - } - - /* send answer */ - n = sendDataOnly(file_des,&retval,sizeof(retval)); - n = sendDataOnly(file_des,answer,MAX_STR_LENGTH); - if (n < 0) { - sprintf(mess,"Error writing to socket"); - retval=FAIL; - } - - - /*return ok/fail*/ - return retval; - -} - - - -int get_detector_type(int file_des) { - int n=0; - enum detectorType retval; - int ret = OK; - - /* execute action */ - retval=myDetectorType; - -#ifdef VERBOSE - printf("Returning detector type %d\n",ret); -#endif - - if (differentClients==1) - ret=FORCE_UPDATE; - - /* send OK/failed */ - n += sendDataOnly(file_des,&ret,sizeof(ret)); - /* send return argument */ - n += sendDataOnly(file_des,&retval,sizeof(retval)); - - /*return ok/fail*/ - return retval; - - -} - - - -int set_external_signal_flag(int file_des) { - int n; - int arg[2]; - int ret=OK; - int signalindex; - enum externalSignalFlag flag, retval; - - sprintf(mess,"Can't set external signal flag\n"); - - /* receive arguments */ - n = receiveDataOnly(file_des,&arg,sizeof(arg)); - if (n < 0) { - sprintf(mess,"Error reading from socket\n"); - ret=FAIL; - } - retval=SIGNAL_OFF; - if (ret==OK) { - signalindex=arg[0]; - flag=arg[1]; - /* execute action */ - switch (flag) { - case GET_EXTERNAL_SIGNAL_FLAG: - retval=getExtSignal(signalindex); - break; - - default: - if (lockStatus && differentClients) { - ret=FAIL; - sprintf(mess,"Detector locked by %s\n", lastClientIP); - } else if (signalindex > 0) { - ret=FAIL; - sprintf(mess,"Signal index %d is reserved. Only index 0 can be configured.\n", signalindex); - } else { - retval=setExtSignal(flag); - } - } -#ifdef VERBOSE - printf("Setting external signal %d to flag %d\n",signalindex,flag ); - printf("Set to flag %d\n",retval); -#endif - - } - - if (ret==OK && differentClients!=0) - ret=FORCE_UPDATE; - - - /* send answer */ - /* send OK/failed */ - n = sendDataOnly(file_des,&ret,sizeof(ret)); - if (ret!=FAIL) { - /* send return argument */ - n += sendDataOnly(file_des,&retval,sizeof(retval)); - } else { - n += sendDataOnly(file_des,mess,sizeof(mess)); - } - - - /*return ok/fail*/ - return ret; - -} - - -int set_external_communication_mode(int file_des) { - int n; - enum externalCommunicationMode arg, ret=GET_EXTERNAL_COMMUNICATION_MODE; - int retval=OK; - - sprintf(mess,"Can't set external communication mode\n"); - - - /* receive arguments */ - n = receiveDataOnly(file_des,&arg,sizeof(arg)); - if (n < 0) { - sprintf(mess,"Error reading from socket\n"); - retval=FAIL; - } - - if (retval==OK) { - /* execute action */ - - ret=setTiming(arg); - - -#ifdef VERBOSE - printf("Setting external communication mode to %d\n", arg); -#endif - } else - ret=FAIL; - - /* send answer */ - /* send OK/failed */ - n = sendDataOnly(file_des,&retval,sizeof(retval)); - if (retval!=FAIL) { - /* send return argument */ - n += sendDataOnly(file_des,&ret,sizeof(ret)); - } else { - n += sendDataOnly(file_des,mess,sizeof(mess)); - } - - /*return ok/fail*/ - return retval; -} - - - -int get_id(int file_des) { - // sends back 64 bits! - int64_t retval=-1; - int ret=OK; - int n=0; - enum idMode arg; - - sprintf(mess,"Can't return id\n"); - - /* receive arguments */ - n = receiveDataOnly(file_des,&arg,sizeof(arg)); - if (n < 0) { - sprintf(mess,"Error reading from socket\n"); - ret=FAIL; - } - -#ifdef VERBOSE - printf("Getting id %d\n", arg); -#endif - - switch (arg) { - case DETECTOR_SERIAL_NUMBER: - retval=getDetectorNumber(); - break; - case DETECTOR_FIRMWARE_VERSION: - retval = (getFirmwareVersion() & 0xFFFFFF); - break; - case DETECTOR_SOFTWARE_VERSION: - retval = (GITDATE & 0xFFFFFF); - break; - case CLIENT_SOFTWARE_API_VERSION: - return APIGOTTHARD; - default: - printf("Required unknown id %d \n", arg); - ret=FAIL; - retval=FAIL; - break; - } - -#ifdef VERBOSE - printf("Id is %llx\n", retval); -#endif - - if (differentClients==1) - ret=FORCE_UPDATE; - - /* send answer */ - /* send OK/failed */ - n = sendDataOnly(file_des,&ret,sizeof(ret)); - if (ret!=FAIL) { - /* send return argument */ - n += sendDataOnly(file_des,&retval,sizeof(retval)); - } else { - n += sendDataOnly(file_des,mess,sizeof(mess)); - } - - /*return ok/fail*/ - return ret; - -} - -int digital_test(int file_des) { - - int retval; - int ret=OK; - int n=0; - int ival; - enum digitalTestMode arg; - - sprintf(mess,"Can't send digital test\n"); - - n = receiveDataOnly(file_des,&arg,sizeof(arg)); - if (n < 0) { - sprintf(mess,"Error reading from socket\n"); - ret=FAIL; - } - -#ifdef VERBOSE - printf("Digital test mode %d\n",arg ); -#endif - - switch (arg) { - case DETECTOR_FIRMWARE_TEST: - retval=testFpga(); - break; - case DETECTOR_BUS_TEST: - retval=testBus(); - break; - case DIGITAL_BIT_TEST: - n = receiveDataOnly(file_des,&ival,sizeof(ival)); - if (n < 0) { - sprintf(mess,"Error reading from socket\n"); - retval=FAIL; - } -#ifdef VERBOSE - printf("with value %d\n", ival); -#endif - if (differentClients==1 && lockStatus==1) { - ret=FAIL; - sprintf(mess,"Detector locked by %s\n",lastClientIP); - break; - } - digitalTestBit = ival; - retval=digitalTestBit; - break; - default: - printf("Unknown digital test required %d\n",arg); - ret=FAIL; - retval=FAIL; - break; - } - -#ifdef VERBOSE - printf("digital test result is 0x%x\n", retval); -#endif - //Always returns force update such that the dynamic range is always updated on the client - - // if (differentClients==1 && ret==OK) - ret=FORCE_UPDATE; - - /* send answer */ - /* send OK/failed */ - n = sendDataOnly(file_des,&ret,sizeof(ret)); - if (ret!=FAIL) { - /* send return argument */ - n += sendDataOnly(file_des,&retval,sizeof(retval)); - } else { - n += sendDataOnly(file_des,mess,sizeof(mess)); - } - - /*return ok/fail*/ - return ret; - -} - - - - -int set_dac(int file_des) { - //default:all mods - int retval[2];retval[1]=-1; - int temp; - int ret=OK; - int arg[2]; - enum dacIndex ind; - int n; - int val; - int mV; - int idac=0; - - sprintf(mess,"Can't set DAC\n"); - - n = receiveDataOnly(file_des,arg,sizeof(arg)); - if (n < 0) { - sprintf(mess,"Error reading from socket\n"); - ret=FAIL; - } - ind=arg[0]; - mV=arg[1]; - - n = receiveDataOnly(file_des,&val,sizeof(val)); - if (n < 0) { - sprintf(mess,"Error reading from socket\n"); - ret=FAIL; - } - -#ifdef VERBOSE - printf("Setting DAC %d to %d V\n", ind, val); -#endif - - switch (ind) { - case G_VREF_DS : - idac=VREF_DS; - break; - case G_VCASCN_PB: - idac=VCASCN_PB; - break; - case G_VCASCP_PB: - idac=VCASCP_PB; - break; - case G_VOUT_CM: - idac=VOUT_CM; - break; - case G_VCASC_OUT: - idac=VCASC_OUT; - break; - case G_VIN_CM: - idac=VIN_CM; - break; - case G_VREF_COMP: - idac=VREF_COMP; - break; - case G_IB_TESTC: - idac=IB_TESTC; - break; - case HV_POT: - idac=HIGH_VOLTAGE; - break; - - default: - printf("Unknown DAC index %d\n",ind); - sprintf(mess,"Unknown DAC index %d\n",ind); - ret=FAIL; - break; - } - - if (ret==OK) { - if (differentClients==1 && lockStatus==1) { - ret=FAIL; - sprintf(mess,"Detector locked by %s\n",lastClientIP); - } else{ - if(idac==HIGH_VOLTAGE){ - retval[0]=initHighVoltage(val); - ret=FAIL; - if(retval[0]==-2) - strcpy(mess,"Invalid Voltage.Valid values are 0,90,110,120,150,180,200"); - else if(retval[0]==-3) - strcpy(mess,"Weird value read back or it has not been set yet\n"); - else - ret=OK; - }else{ - setDAC(idac,val,mV,retval); - ret=FAIL; - if(mV) - temp = retval[1]; - else - temp = retval[0]; - if ((abs(temp-val)<=3) || val==-1) { - ret=OK; -#ifdef VERBOSE - printf("DAC set to %d in dac units and %d mV\n", retval[0],retval[1]); -#endif - } - } - } - } - - - if(ret==FAIL) - printf("Setting dac %d: wrote %d but read %d\n", ind, val, temp); - else{ - if (differentClients) - ret=FORCE_UPDATE; - } - - - /* send answer */ - /* send OK/failed */ - n = sendDataOnly(file_des,&ret,sizeof(ret)); - if (ret!=FAIL) { - /* send return argument */ - n += sendDataOnly(file_des,retval,sizeof(retval)); - } else { - n += sendDataOnly(file_des,mess,sizeof(mess)); - } - - - /*return ok/fail*/ - return ret; - -} - - - -int get_adc(int file_des) { - //default: mod 0 - int retval; - int ret=OK; - int arg; - enum dacIndex ind; - int n; - int idac=0; - - sprintf(mess,"Can't read ADC\n"); - - - n = receiveDataOnly(file_des,&arg,sizeof(arg)); - if (n < 0) { - sprintf(mess,"Error reading from socket\n"); - ret=FAIL; - } - ind=arg; - -#ifdef VERBOSE - printf("Getting ADC %d\n", ind); -#endif - - switch (ind) { - case TEMPERATURE_FPGA: - idac=TEMP_FPGA; - break; - case TEMPERATURE_ADC: - idac=TEMP_ADC; - break; - default: - printf("Unknown DAC index %d\n",ind); - sprintf(mess,"Unknown DAC index %d\n",ind); - ret=FAIL; - break; - } - - if (ret==OK) - retval=getTemperature(idac); - -#ifdef VERBOSE - printf("ADC is %d V\n", retval); -#endif - if (ret==FAIL) { - printf("Getting adc %d failed\n", ind); - } - - if (differentClients) - ret=FORCE_UPDATE; - - /* send answer */ - /* send OK/failed */ - n = sendDataOnly(file_des,&ret,sizeof(ret)); - if (ret!=FAIL) { - /* send return argument */ - n += sendDataOnly(file_des,&retval,sizeof(retval)); - } else { - n += sendDataOnly(file_des,mess,sizeof(mess)); - } - - /*return ok/fail*/ - return ret; - -} - - - - -int write_register(int file_des) { - - int retval; - int ret=OK; - int arg[2]; - int addr, val; - int n; - u_int32_t address; - - sprintf(mess,"Can't write to register\n"); - - n = receiveDataOnly(file_des,arg,sizeof(arg)); - if (n < 0) { - sprintf(mess,"Error reading from socket\n"); - ret=FAIL; - } - addr=arg[0]; - val=arg[1]; - -#ifdef VERBOSE - printf("writing to register 0x%x data 0x%x\n", addr, val); -#endif - - if (differentClients==1 && lockStatus==1) { - ret=FAIL; - sprintf(mess,"Detector locked by %s\n",lastClientIP); - } - - - if(ret!=FAIL){ - address=(addr<<11); - if((address==FIFO_DATA_REG_OFF)||(address==CONTROL_REG)) - ret = bus_w16(address,val); - else - ret=bus_w(address,val); - if(ret==OK){ - if((address==FIFO_DATA_REG_OFF)||(address==CONTROL_REG)) - retval=bus_r16(address); - else - retval=bus_r(address); - } - } - - -#ifdef VERBOSE - printf("Data set to 0x%x\n", retval); -#endif - if (retval==val) { - ret=OK; - if (differentClients) - ret=FORCE_UPDATE; - } else { - ret=FAIL; - sprintf(mess,"Writing to register 0x%x failed: wrote 0x%x but read 0x%x\n", addr, val, retval); - } - - /* send answer */ - /* send OK/failed */ - n = sendDataOnly(file_des,&ret,sizeof(ret)); - if (ret!=FAIL) { - /* send return argument */ - n += sendDataOnly(file_des,&retval,sizeof(retval)); - } else { - n += sendDataOnly(file_des,mess,sizeof(mess)); - } - - /*return ok/fail*/ - return ret; - -} - -int read_register(int file_des) { - - int retval; - int ret=OK; - int arg; - int addr; - int n; - u_int32_t address; - - sprintf(mess,"Can't read register\n"); - - n = receiveDataOnly(file_des,&arg,sizeof(arg)); - if (n < 0) { - sprintf(mess,"Error reading from socket\n"); - ret=FAIL; - } - addr=arg; - - - - //#ifdef VERBOSE - printf("reading register 0x%x\n", addr); - //#endif - - if(ret!=FAIL){ - address=(addr<<11); - if((address==FIFO_DATA_REG_OFF)||(address==CONTROL_REG)) - retval=bus_r16(address); - else - retval=bus_r(address); - } - - - -#ifdef VERBOSE - printf("Returned value 0x%x\n", retval); -#endif - if (ret==FAIL) { - ret=FAIL; - printf("Reading register 0x%x failed\n", addr); - } else if (differentClients) - ret=FORCE_UPDATE; - - - /* send answer */ - /* send OK/failed */ - n = sendDataOnly(file_des,&ret,sizeof(ret)); - if (ret!=FAIL) { - /* send return argument */ - n += sendDataOnly(file_des,&retval,sizeof(retval)); - } else { - n += sendDataOnly(file_des,mess,sizeof(mess)); - } - - /*return ok/fail*/ - return ret; - -} - - -int set_module(int file_des) { - sls_detector_module myModule; - int *myChip=malloc(NCHIP*sizeof(int)); - int *myChan=malloc(NCHIP*NCHAN*sizeof(int)); - int *myDac=malloc(NDAC*sizeof(int));/**dhanya*/ - int *myAdc=malloc(NADC*sizeof(int));/**dhanya*/ - int retval, n; - int ret=OK; - int dr;// ow; - - dr=DYNAMIC_RANGE; - - if (myDac) - myModule.dacs=myDac; - else { - sprintf(mess,"could not allocate dacs\n"); - ret=FAIL; - } - if (myAdc) - myModule.adcs=myAdc; - else { - sprintf(mess,"could not allocate adcs\n"); - ret=FAIL; - } - if (myChip) - myModule.chipregs=myChip; - else { - sprintf(mess,"could not allocate chips\n"); - ret=FAIL; - } - if (myChan) - myModule.chanregs=myChan; - else { - sprintf(mess,"could not allocate chans\n"); - ret=FAIL; - } - - myModule.ndac=NDAC; - myModule.nchip=NCHIP; - myModule.nchan=NCHAN*NCHIP; - myModule.nadc=NADC; - - -#ifdef VERBOSE - printf("Setting module\n"); -#endif - ret=receiveModule(file_des, &myModule); - - if (ret>=0) - ret=OK; - else - ret=FAIL; - - -#ifdef VERBOSE - printf("module number is %d,register is %d, nchan %d, nchip %d, ndac %d, nadc %d, gain %f, offset %f\n",myModule.module, myModule.reg, myModule.nchan, myModule.nchip, myModule.ndac, myModule.nadc, myModule.gain,myModule.offset); -#endif - - - if (ret==OK) { - if (differentClients==1 && lockStatus==1) { - ret=FAIL; - sprintf(mess,"Detector locked by %s\n",lastClientIP); - } else { - retval=setModule(myModule); - } - } - - if (differentClients==1 && ret==OK) - ret=FORCE_UPDATE; - - /* Maybe this is done inside the initialization funcs */ - //copyChip(detectorChips[myChip.module]+(myChip.chip), &myChip); - - /* send answer */ - /* send OK/failed */ - n = sendDataOnly(file_des,&ret,sizeof(ret)); - if (ret!=FAIL) { - /* send return argument */ - n += sendDataOnly(file_des,&retval,sizeof(retval)); - } else { - n += sendDataOnly(file_des,mess,sizeof(mess)); - } - free(myChip); - free(myChan); - free(myDac); - free(myAdc); - - // setDynamicRange(dr); always 16 commented out - - - return ret; -} - - - - -int get_module(int file_des) { - - - int ret=OK; - int n; - - - - sls_detector_module myModule; - int *myChip=malloc(NCHIP*sizeof(int)); - int *myChan=malloc(NCHIP*NCHAN*sizeof(int)); - int *myDac=malloc(NDAC*sizeof(int)); - int *myAdc=malloc(NADC*sizeof(int)); - - - if (myDac) - myModule.dacs=myDac; - else { - sprintf(mess,"could not allocate dacs\n"); - ret=FAIL; - } - if (myAdc) - myModule.adcs=myAdc; - else { - sprintf(mess,"could not allocate adcs\n"); - ret=FAIL; - } - if (myChip) - myModule.chipregs=myChip; - else { - sprintf(mess,"could not allocate chips\n"); - ret=FAIL; - } - if (myChan) - myModule.chanregs=myChan; - else { - sprintf(mess,"could not allocate chans\n"); - ret=FAIL; - } - - myModule.ndac=NDAC; - myModule.nchip=NCHIP; - myModule.nchan=NCHAN*NCHIP; - myModule.nadc=NADC; - - if (ret==OK) { - getModule(&myModule); - -#ifdef VERBOSE - printf("Returning module register %x\n", myModule.reg); -#endif - - } - - if (differentClients==1 && ret==OK) - ret=FORCE_UPDATE; - - /* send answer */ - /* send OK/failed */ - n = sendDataOnly(file_des,&ret,sizeof(ret)); - if (ret!=FAIL) { - /* send return argument */ - ret=sendModule(file_des, &myModule); - } else { - n += sendDataOnly(file_des,mess,sizeof(mess)); - } - - - - free(myChip); - free(myChan); - free(myDac); - free(myAdc); - - - /*return ok/fail*/ - return ret; - -} - - - -int set_settings(int file_des) { - - int retval; - int ret=OK; - int arg; - int n; - enum detectorSettings isett; - - - n = receiveDataOnly(file_des,&arg,sizeof(arg)); - if (n < 0) { - sprintf(mess,"Error reading from socket\n"); - ret=FAIL; - } - isett=arg; - - -#ifdef VERBOSE - printf("Changing settings to %d\n", isett); -#endif - - if (differentClients==1 && lockStatus==1 && arg!=GET_SETTINGS) { - ret=FAIL; - sprintf(mess,"Detector locked by %s\n",lastClientIP); - } else { - switch(isett) { - case GET_SETTINGS: - case UNINITIALIZED: - case DYNAMICGAIN: - case HIGHGAIN: - case LOWGAIN: - case MEDIUMGAIN: - case VERYHIGHGAIN: - break; - default: - ret = FAIL; - sprintf(mess,"Setting (%d) is not implemented for this detector.\n" - "Options are dynamicgain, highgain, lowgain, mediumgain and " - "veryhighgain.\n", isett); - cprintf(RED, "Warning: %s", mess); - break; - } - if (ret != FAIL) { - retval=setSettings(isett); -#ifdef VERBOSE - printf("Settings changed to %d\n",retval); -#endif - if (retval != isett && isett >= 0) { - ret=FAIL; - sprintf(mess, "Changing settings: wrote %d but read %d\n", isett, retval); - printf("Warning: %s",mess); - } - - else { - ret = setDefaultDacs(); - if (ret == FAIL) { - strcpy(mess,"Could change settings, but could not set to default dacs\n"); - cprintf(RED, "Warning: %s", mess); - } - } - } - } - if (ret==OK && differentClients==1) - ret=FORCE_UPDATE; - - /* send answer */ - n = sendDataOnly(file_des,&ret,sizeof(ret)); - if (ret==FAIL) { - n += sendDataOnly(file_des,mess,sizeof(mess)); - } else - n += sendDataOnly(file_des,&retval,sizeof(retval)); - - - - return ret; - - -} - - - - -int start_acquisition(int file_des) { - - int ret=OK; - int n; - - - sprintf(mess,"can't start acquisition\n"); - -#ifdef VERBOSE - printf("Starting acquisition\n"); -#endif - - if (differentClients==1 && lockStatus==1) { - ret=FAIL; - sprintf(mess,"Detector locked by %s\n",lastClientIP); - } else { - ret=startStateMachine(); - } - if (ret==FAIL) - sprintf(mess,"Start acquisition failed\n"); - else if (differentClients) - ret=FORCE_UPDATE; - - n = sendDataOnly(file_des,&ret,sizeof(ret)); - if (ret==FAIL) { - n += sendDataOnly(file_des,mess,sizeof(mess)); - } - return ret; - -} - -int stop_acquisition(int file_des) { - - int ret=OK; - int n; - - sprintf(mess,"can't stop acquisition\n"); - - cprintf(BG_RED,"Client command received to stop acquisition\n"); - - - - if (differentClients==1 && lockStatus==1) { - ret=FAIL; - sprintf(mess,"Detector locked by %s\n",lastClientIP); - } else { - ret=stopStateMachine(); - } - - if (ret==FAIL) - sprintf(mess,"Stop acquisition failed\n"); - else if (differentClients) - ret=FORCE_UPDATE; - - n = sendDataOnly(file_des,&ret,sizeof(ret)); - if (ret==FAIL) { - n += sendDataOnly(file_des,mess,sizeof(mess)); - } - return ret; - - -} - -int start_readout(int file_des) { - - - int ret=OK; - int n; - - - sprintf(mess,"can't start readout\n"); - -#ifdef VERBOSE - printf("Starting readout\n"); -#endif - if (differentClients==1 && lockStatus==1) { - ret=FAIL; - sprintf(mess,"Detector locked by %s\n",lastClientIP); - } else { - ret=startReadOut(); - } - if (ret==FAIL) - sprintf(mess,"Start readout failed\n"); - else if (differentClients) - ret=FORCE_UPDATE; - - n = sendDataOnly(file_des,&ret,sizeof(ret)); - if (ret==FAIL) { - n += sendDataOnly(file_des,mess,sizeof(mess)); - } - return ret; - - - -} - -int get_run_status(int file_des) { - - int ret=OK; - int n; - - - enum runStatus s; - sprintf(mess,"getting run status\n"); - -#ifdef VERBOSE - printf("Getting status\n"); -#endif - - int retval = getStatus(); - - if (ret!=OK) { - printf("get status failed %04x\n",retval); - sprintf(mess, "get status failed %08x\n", retval); - - } else if (differentClients) - ret=FORCE_UPDATE; - - n = sendDataOnly(file_des,&ret,sizeof(ret)); - if (ret==FAIL) { - n += sendDataOnly(file_des,mess,sizeof(mess)); - } else { - n += sendDataOnly(file_des,&s,sizeof(s)); - } - return ret; - - - -} - - - - - -int start_and_read_all(int file_des) { -#ifdef VERBOSE - printf("Starting and reading all frames\n"); -#endif - int dataret = FAIL; - if (differentClients==1 && lockStatus==1) { - dataret=FAIL; - sprintf(mess,"Detector locked by %s\n",lastClientIP); - sendDataOnly(file_des,&dataret,sizeof(dataret)); - sendDataOnly(file_des,mess,sizeof(mess)); - return dataret; - - } - - startStateMachine(); - dataret = read_all(file_des); -#ifdef VERBOSE - printf("Frames finished\n"); -#endif - - return dataret; - - -} - - - -int read_all(int file_des) { - int dataret = FAIL; - strcpy(mess,"wait for read frame failed\n"); - - if (differentClients==1 && lockStatus==1) { - dataret=FAIL; - sprintf(mess,"Detector locked by %s\n",lastClientIP); - cprintf(RED,"%s\n",mess); - sendDataOnly(file_des,&dataret,sizeof(dataret)); - sendDataOnly(file_des,mess,sizeof(mess)); - return dataret; - } - - -#ifdef VIRTUAL - dataret = FINISHED; - strcpy(mess,"acquisition successfully finished\n"); -#else - waitForAcquisitionFinish(); - - // set return value and message - if(getFrames()>-2) { - dataret = FAIL; - sprintf(mess,"no data and run stopped: %d frames left\n",(int)(getFrames()+2)); - cprintf(RED,"%s\n",mess); - } else { - dataret = FINISHED; - sprintf(mess,"acquisition successfully finished\n"); - cprintf(GREEN,"%s",mess); - - } -#endif - - if (differentClients) - dataret=FORCE_UPDATE; - - sendDataOnly(file_des,&dataret,sizeof(dataret)); - sendDataOnly(file_des,mess,sizeof(mess)); - return dataret; -} - - - - - -int set_timer(int file_des) { - enum timerIndex ind; - int64_t tns; - int n; - int64_t retval; - int ret=OK; - - - sprintf(mess,"can't set timer\n"); - - n = receiveDataOnly(file_des,&ind,sizeof(ind)); - if (n < 0) { - sprintf(mess,"Error reading from socket\n"); - ret=FAIL; - } - - n = receiveDataOnly(file_des,&tns,sizeof(tns)); - if (n < 0) { - sprintf(mess,"Error reading from socket\n"); - ret=FAIL; - } - - if (ret!=OK) { - printf(mess); - } - - //#ifdef VERBOSE - printf("setting timer %d to %lld ns\n",ind,tns); - //#endif - if (ret==OK) { - - if (differentClients==1 && lockStatus==1 && tns!=-1) { - ret=FAIL; - sprintf(mess,"Detector locked by %s\n",lastClientIP); - } else { - switch(ind) { - case FRAME_NUMBER: - retval=setFrames(tns); - break; - case ACQUISITION_TIME: - retval=setExposureTime(tns); - break; - case FRAME_PERIOD: - retval=setPeriod(tns); - break; - case DELAY_AFTER_TRIGGER: - retval=setDelay(tns); - break; - case GATES_NUMBER: - retval=setGates(tns); - break; - case CYCLES_NUMBER: - retval=setTrains(tns); - break; - default: - ret=FAIL; - sprintf(mess,"timer index unknown %d\n",ind); - break; - } - } - } - if (ret!=OK) { - printf(mess); - if (differentClients) - ret=FORCE_UPDATE; - } - - if (ret!=OK) { - printf(mess); - printf("set timer failed\n"); - } - - n = sendDataOnly(file_des,&ret,sizeof(ret)); - if (ret==FAIL) { - n = sendDataOnly(file_des,mess,sizeof(mess)); - } else { -#ifdef VERBOSE - printf("returning ok %d\n",(int)(sizeof(retval))); -#endif - - n = sendDataOnly(file_des,&retval,sizeof(retval)); - } - - return ret; - -} - - - - - - - - -int get_time_left(int file_des) { - - enum timerIndex ind; - int n; - int64_t retval; - int ret=OK; - - sprintf(mess,"can't get timer\n"); - n = receiveDataOnly(file_des,&ind,sizeof(ind)); - if (n < 0) { - sprintf(mess,"Error reading from socket\n"); - ret=FAIL; - } - - -#ifdef VERBOSE - - printf("getting time left on timer %d \n",ind); -#endif - - if (ret==OK) { - switch(ind) { - case FRAME_NUMBER: - retval=getFrames(); - break; - case ACQUISITION_TIME: - retval=getExposureTime(); - break; - case FRAME_PERIOD: - retval=getPeriod(); - break; - case DELAY_AFTER_TRIGGER: - retval=getDelay(); - break; - case GATES_NUMBER: - retval=getGates(); - break; - case CYCLES_NUMBER: - retval=getTrains(); - break; - case ACTUAL_TIME: - retval=getActualTime(); - break; - case MEASUREMENT_TIME: - retval=getMeasurementTime(); - break; - default: - ret=FAIL; - sprintf(mess,"timer index unknown %d\n",ind); - break; - } - } - - - if (ret!=OK) { - printf("get time left failed\n"); - } else if (differentClients) - ret=FORCE_UPDATE; - -#ifdef VERBOSE - - printf("time left on timer %d is %lld\n",ind, retval); -#endif - - n = sendDataOnly(file_des,&ret,sizeof(ret)); - if (ret!=OK) { - n += sendDataOnly(file_des,mess,sizeof(mess)); - } else { - n = sendDataOnly(file_des,&retval,sizeof(retval)); - } -#ifdef VERBOSE - - printf("data sent\n"); -#endif - - return ret; - - -} - -int set_dynamic_range(int file_des) { - - - - int dr; - int n; - int retval; - int ret=OK; - - - sprintf(mess,"can't set dynamic range\n"); - - - n = receiveDataOnly(file_des,&dr,sizeof(dr)); - if (n < 0) { - sprintf(mess,"Error reading from socket\n"); - ret=FAIL; - } - - - if (differentClients==1 && lockStatus==1 && dr>=0) { - ret=FAIL; - sprintf(mess,"Detector locked by %s\n",lastClientIP); - } else { - retval=DYNAMIC_RANGE; - } - - //if (dr>=0 && retval!=dr) ret=FAIL; - if (ret!=OK) { - sprintf(mess,"set dynamic range failed\n"); - } - - n = sendDataOnly(file_des,&ret,sizeof(ret)); - if (ret==FAIL) { - n = sendDataOnly(file_des,mess,sizeof(mess)); - } else { - n = sendDataOnly(file_des,&retval,sizeof(retval)); - } - return ret; -} - - - - - -int set_readout_flags(int file_des) { - - enum readOutFlags arg; - int ret=FAIL; - - - receiveDataOnly(file_des,&arg,sizeof(arg)); - -#ifdef PROPIXD - sprintf(mess,"can't set readout flags for propix\n"); -#else - sprintf(mess,"can't set readout flags for gotthard\n"); -#endif - - sendDataOnly(file_des,&ret,sizeof(ret)); - sendDataOnly(file_des,mess,sizeof(mess)); - - return ret; -} - - - - -int set_roi(int file_des) { - - int i; - int ret=OK; - int nroi=-1; - int n=0; - int retvalsize=0; - ROI arg[MAX_ROIS]; - ROI* retval=0; - - strcpy(mess,"Could not set/get roi\n"); - - - n = receiveDataOnly(file_des,&nroi,sizeof(nroi)); - if (n < 0) { - sprintf(mess,"Error reading from socket\n"); - ret=FAIL; - } - -#ifdef PROPIXD - sprintf(mess,"can't set roi for propix\n"); - ret = FAIL; -#endif - if(ret != FAIL){ - if(nroi!=-1){ - n = receiveDataOnly(file_des,arg,nroi*sizeof(ROI)); - if (n != (nroi*sizeof(ROI))) { - sprintf(mess,"Received wrong number of bytes for ROI\n"); - ret=FAIL; - } - //#ifdef VERBOSE - printf("\n\nSetting ROI: nroi=%d\n",nroi); - for( i=0;i=0) { - if (lockStatus==0 || strcmp(lastClientIP,thisClientIP)==0 || strcmp(lastClientIP,"none")==0) - lockStatus=lock; - else { - ret=FAIL; - sprintf(mess,"Server already locked by %s\n", lastClientIP); - } - } - if (differentClients && ret==OK) - ret=FORCE_UPDATE; - - n = sendDataOnly(file_des,&ret,sizeof(ret)); - if (ret==FAIL) { - n = sendDataOnly(file_des,mess,sizeof(mess)); - } else - n = sendDataOnly(file_des,&lockStatus,sizeof(lockStatus)); - - return ret; - -} - - -int get_last_client_ip(int file_des) { - int ret=OK; - int n; - if (differentClients ) - ret=FORCE_UPDATE; - n = sendDataOnly(file_des,&ret,sizeof(ret)); - n = sendDataOnly(file_des,lastClientIP,sizeof(lastClientIP)); - - return ret; - -} - - -int set_port(int file_des) { - int n; - int ret=OK; - int sd=-1; - - enum portType p_type; /** data? control? stop? Unused! */ - int p_number; /** new port number */ - - n = receiveDataOnly(file_des,&p_type,sizeof(p_type)); - if (n < 0) { - sprintf(mess,"Error reading from socket\n"); - printf("Error reading from socket (ptype)\n"); - ret=FAIL; - } - - n = receiveDataOnly(file_des,&p_number,sizeof(p_number)); - if (n < 0) { - sprintf(mess,"Error reading from socket\n"); - printf("Error reading from socket (pnum)\n"); - ret=FAIL; - } - if (differentClients==1 && lockStatus==1 ) { - ret=FAIL; - sprintf(mess,"Detector locked by %s\n",lastClientIP); - } else { - if (p_number<1024) { - sprintf(mess,"Too low port number %d\n", p_number); - printf("\n"); - ret=FAIL; - } - - printf("set port %d to %d\n",p_type, p_number); - - sd=bindSocket(p_number); - } - if (sd>=0) { - ret=OK; - if (differentClients ) - ret=FORCE_UPDATE; - } else { - ret=FAIL; - sprintf(mess,"Could not bind port %d\n", p_number); - printf("Could not bind port %d\n", p_number); - if (sd==-10) { - sprintf(mess,"Port %d already set\n", p_number); - printf("Port %d already set\n", p_number); - - } - } - - n = sendDataOnly(file_des,&ret,sizeof(ret)); - if (ret==FAIL) { - n = sendDataOnly(file_des,mess,sizeof(mess)); - } else { - n = sendDataOnly(file_des,&p_number,sizeof(p_number)); - closeConnection(file_des); - exitServer(sockfd); - sockfd=sd; - - } - - return ret; - -} - - - -int send_update(int file_des) { - - int ret=OK; - enum detectorSettings t; - int n;//int thr, n; - //int it; - int64_t retval, tns=-1; - n = sendDataOnly(file_des,lastClientIP,sizeof(lastClientIP)); - int k = DYNAMIC_RANGE; - n = sendDataOnly(file_des,&k,sizeof(k)); - k = DATA_BYTES; - n = sendDataOnly(file_des,&k,sizeof(k)); - t=setSettings(GET_SETTINGS); - n = sendDataOnly(file_des,&t,sizeof(t)); - retval=setFrames(tns); - n = sendDataOnly(file_des,&retval,sizeof(int64_t)); - retval=setExposureTime(tns); - n = sendDataOnly(file_des,&retval,sizeof(int64_t)); - retval=setPeriod(tns); - n = sendDataOnly(file_des,&retval,sizeof(int64_t)); - retval=setDelay(tns); - n = sendDataOnly(file_des,&retval,sizeof(int64_t)); - retval=setGates(tns); - n = sendDataOnly(file_des,&retval,sizeof(int64_t)); - retval=setTrains(tns); - n = sendDataOnly(file_des,&retval,sizeof(int64_t)); - - if (lockStatus==0) { - strcpy(lastClientIP,thisClientIP); - } - - return ret; - - -} -int update_client(int file_des) { - - int ret=OK; - - sendDataOnly(file_des,&ret,sizeof(ret)); - return send_update(file_des); - - - -} - - -int configure_mac(int file_des) { - - int ret=OK; - char arg[6][50]; - int n; - - int ipad; - long long int imacadd; - long long int idetectormacadd; - int udpport; - int detipad; - int retval=-100; - - sprintf(mess,"Can't configure MAC\n"); - - - n = receiveDataOnly(file_des,arg,sizeof(arg)); - if (n < 0) { - sprintf(mess,"Error reading from socket\n"); - ret=FAIL; - } - - sscanf(arg[0], "%x", &ipad); - sscanf(arg[1], "%llx", &imacadd); - sscanf(arg[2], "%x", &udpport); - sscanf(arg[3], "%llx", &idetectormacadd); - sscanf(arg[4], "%x", &detipad); - //arg[5] is udpport2 for eiger -#ifdef VERBOSE - int i; - printf("\ndigital_test_bit in server %d\t",digitalTestBit); - printf("\nipadd %x\t",ipad); - printf("destination ip is %d.%d.%d.%d = 0x%x \n",(ipad>>24)&0xff,(ipad>>16)&0xff,(ipad>>8)&0xff,(ipad)&0xff,ipad); - printf("macad:%llx\n",imacadd); - for (i=0;i<6;i++) - printf("mac adress %d is 0x%x \n",6-i,(unsigned int)(((imacadd>>(8*i))&0xFF))); - printf("udp port:0x%x\n",udpport); - printf("detector macad:%llx\n",idetectormacadd); - for (i=0;i<6;i++) - printf("detector mac adress %d is 0x%x \n",6-i,(unsigned int)(((idetectormacadd>>(8*i))&0xFF))); - printf("detipad %x\n",detipad); - printf("\n"); -#endif - - - //#ifdef VERBOSE - printf("Configuring MAC at port %x\n", udpport); - //#endif - if (ret==OK){ - if(runBusy()){ - ret=stopStateMachine(); - if(ret==FAIL) - strcpy(mess,"could not stop detector acquisition to configure mac"); - } - - if(ret==OK) - configureMAC(ipad,imacadd,idetectormacadd,detipad,digitalTestBit,udpport); - retval=getAdcConfigured(); - } - if (ret==FAIL) - printf("configuring MAC failed\n"); - else - printf("Configuremac successful and adc %d\n",retval); - - if (differentClients) - ret=FORCE_UPDATE; - - /* send answer */ - /* send OK/failed */ - n = sendDataOnly(file_des,&ret,sizeof(ret)); - if (ret==FAIL) - n += sendDataOnly(file_des,mess,sizeof(mess)); - else - n += sendDataOnly(file_des,&retval,sizeof(retval)); - /*return ok/fail*/ - return ret; - -} - - - -int load_image(int file_des) { - int retval; - int ret=OK; - int n; - enum imageType index; - short int ImageVals[NCHAN*NCHIP]; - - sprintf(mess,"Loading image failed\n"); - - n = receiveDataOnly(file_des,&index,sizeof(index)); - if (n < 0) { - sprintf(mess,"Error reading from socket\n"); - ret=FAIL; - } - - n = receiveDataOnly(file_des,ImageVals,DATA_BYTES); - if (n < 0) { - sprintf(mess,"Error reading from socket\n"); - ret=FAIL; - } - -#ifdef PROPIXD - sprintf(mess,"can't load image for propix\n"); - ret = FAIL; -#endif - - switch (index) { - case DARK_IMAGE : -#ifdef VERBOSE - printf("Loading Dark image\n"); -#endif - break; - case GAIN_IMAGE : -#ifdef VERBOSE - printf("Loading Gain image\n"); -#endif - break; - default: - printf("Unknown index %d\n",index); - sprintf(mess,"Unknown index %d\n",index); - ret=FAIL; - break; - } - - if (ret==OK) { - if (differentClients==1 && lockStatus==1) { - ret=FAIL; - sprintf(mess,"Detector locked by %s\n",lastClientIP); - } else{ - retval=loadImage(index,ImageVals); - if (retval==-1) - ret = FAIL; - } - } - - if(ret==OK){ - if (differentClients) - ret=FORCE_UPDATE; - } - - /* send answer */ - /* send OK/failed */ - n = sendDataOnly(file_des,&ret,sizeof(ret)); - if (ret!=FAIL) { - /* send return argument */ - n += sendDataOnly(file_des,&retval,sizeof(retval)); - } else { - n += sendDataOnly(file_des,mess,sizeof(mess)); - } - - /*return ok/fail*/ - return ret; -} - - - - - -int read_counter_block(int file_des) { - - int ret=OK; - int n; - int startACQ; - //char *retval=NULL; - short int CounterVals[NCHAN*NCHIP]; - - sprintf(mess,"Read counter block failed\n"); - - n = receiveDataOnly(file_des,&startACQ,sizeof(startACQ)); - if (n < 0) { - sprintf(mess,"Error reading from socket\n"); - ret=FAIL; - } - - -#ifdef PROPIXD - sprintf(mess,"can't read counter block for propix\n"); - ret = FAIL; -#endif - - if (ret==OK) { - if (differentClients==1 && lockStatus==1) { - ret=FAIL; - sprintf(mess,"Detector locked by %s\n",lastClientIP); - } else{ - ret=readCounterBlock(startACQ,CounterVals); -#ifdef VERBOSE - int i; - for(i=0;i<6;i++) - printf("%d:%d\t",i,CounterVals[i]); -#endif - } - } - - if(ret!=FAIL){ - if (differentClients) - ret=FORCE_UPDATE; - } - - /* send answer */ - /* send OK/failed */ - n = sendDataOnly(file_des,&ret,sizeof(ret)); - if (ret!=FAIL) { - /* send return argument */ - n += sendDataOnly(file_des,CounterVals,DATA_BYTES);//1280*2 - } else { - n += sendDataOnly(file_des,mess,sizeof(mess)); - } - - /*return ok/fail*/ - return ret; -} - - - - - -int reset_counter_block(int file_des) { - - int ret=OK; - int n; - int startACQ; - - sprintf(mess,"Reset counter block failed\n"); - - n = receiveDataOnly(file_des,&startACQ,sizeof(startACQ)); - if (n < 0) { - sprintf(mess,"Error reading from socket\n"); - ret=FAIL; - } - - if (ret==OK) { - if (differentClients==1 && lockStatus==1) { - ret=FAIL; - sprintf(mess,"Detector locked by %s\n",lastClientIP); - } else - ret=resetCounterBlock(startACQ); - } - - if(ret==OK){ - if (differentClients) - ret=FORCE_UPDATE; - } - - /* send answer */ - /* send OK/failed */ - n = sendDataOnly(file_des,&ret,sizeof(ret)); - if (ret==FAIL) - n += sendDataOnly(file_des,mess,sizeof(mess)); - - /*return ok/fail*/ - return ret; -} - - - - - - - -int write_adc_register(int file_des) { - int ret=OK; - int n=0; - int retval=-1; - sprintf(mess,"write to adc register failed\n"); - - // receive arguments - int arg[2]={-1,-1}; - n = receiveData(file_des,arg,sizeof(arg),INT32); - if (n < 0) { - sprintf(mess,"Error reading from socket\n"); - ret=FAIL; - } - - int addr=arg[0]; - int val=arg[1]; - - // execute action - if (ret == OK) { - if (differentClients && lockStatus) { - ret = FAIL; - sprintf(mess,"Detector locked by %s\n",lastClientIP); - cprintf(RED, "Warning: %s", mess); - } - else { -#ifdef VERBOSE - printf("writing to register 0x%x data 0x%x\n", addr, val); -#endif - setAdc(addr,val); -#ifdef VERBOSE - printf("Data set to 0x%x\n", retval); -#endif - if (ret==OK && differentClients) - ret=FORCE_UPDATE; - } - } - // send ok / fail - n = sendDataOnly(file_des,&ret,sizeof(ret)); - // send return argument - if (ret==FAIL) { - n = sendDataOnly(file_des,mess,sizeof(mess)); - } else - n = sendDataOnly(file_des,&retval,sizeof(retval)); - - // return ok / fail - return ret; -} - - - - -int check_version(int file_des) { - int ret=OK,ret1=OK; - int n=0; - sprintf(mess,"check version failed\n"); - - - - // receive arguments - int64_t arg=-1; - n = receiveData(file_des,&arg,sizeof(arg),INT64); - if (n < 0) { - sprintf(mess,"Error reading from socket\n"); - ret=FAIL; - } - - - // execute action - if (ret == OK) { -#ifdef VERBOSE - printf("Checking versioning compatibility with value %d\n",arg); -#endif - int64_t client_requiredVersion = arg; - int64_t det_apiVersion = APIGOTTHARD; - int64_t det_version = (GITDATE & 0xFFFFFF); - - // old client - if (det_apiVersion > client_requiredVersion) { - ret = FAIL; - sprintf(mess,"Client's detector SW API version: (0x%llx). " - "Detector's SW API Version: (0x%llx). " - "Incompatible, update client!\n", - client_requiredVersion, det_apiVersion); - cprintf(RED, "Warning: %s", mess); - } - - // old software - else if (client_requiredVersion > det_version) { - ret = FAIL; - sprintf(mess,"Detector SW Version: (0x%llx). " - "Client's detector SW API Version: (0x%llx). " - "Incompatible, update detector software!\n", - det_version, client_requiredVersion); - cprintf(RED, "Warning: %s", mess); - } - } - - - - // ret could be swapped during sendData - ret1 = ret; - // send ok / fail - n = sendData(file_des,&ret1,sizeof(ret),INT32); - // send return argument - if (ret==FAIL) { - n += sendData(file_des,mess,sizeof(mess),OTHER); - } - - // return ok / fail - return ret; -} - - diff --git a/slsDetectorServers/gotthardDetectorServer/server_funcs.h b/slsDetectorServers/gotthardDetectorServer/server_funcs.h deleted file mode 100755 index 5c1571241..000000000 --- a/slsDetectorServers/gotthardDetectorServer/server_funcs.h +++ /dev/null @@ -1,70 +0,0 @@ -#ifndef SERVER_FUNCS_H -#define SERVER_FUNCS_H - - -#include "sls_detector_defs.h" - - -#include -/* -#include -#include -#include -*/ -#include "communication_funcs.h" - - - - -#define GOODBYE -200 - -int sockfd; - -int function_table(); -int decode_function(int); -int init_detector(int); -int M_nofunc(int); - - - - - -// General purpose functions -int exec_command(int); -int get_detector_type(int); -int set_external_signal_flag(int); -int set_external_communication_mode(int); -int get_id(int); -int digital_test(int); -int set_dac(int); -int get_adc(int); -int write_register(int); -int read_register(int); -int set_module(int); -int get_module(int); -int set_settings(int); -int start_acquisition(int); -int stop_acquisition(int); -int start_readout(int); -int get_run_status(int); -int start_and_read_all(int); -int read_all(int); -int set_timer(int); -int get_time_left(int); -int set_dynamic_range(int); -int set_readout_flags(int); -int set_roi(int); -int set_speed(int); -int exit_server(int); -int lock_server(int); -int get_last_client_ip(int); -int set_port(int); -int send_update(int); -int update_client(int); -int configure_mac(int); -int load_image(int); -int read_counter_block(int); -int reset_counter_block(int); -int write_adc_register(int); -int check_version(int); -#endif diff --git a/slsDetectorServers/gotthardDetectorServer/slsDetectorFunctionList.c b/slsDetectorServers/gotthardDetectorServer/slsDetectorFunctionList.c new file mode 100644 index 000000000..d23cac83b --- /dev/null +++ b/slsDetectorServers/gotthardDetectorServer/slsDetectorFunctionList.c @@ -0,0 +1,1810 @@ +#include "slsDetectorFunctionList.h" +#include "gitInfoGotthard.h" +#include "versionAPI.h" +#include "logger.h" + +#ifndef VIRTUAL +#include "AD9257.h" // commonServerFunctions.h, blackfin.h, ansi.h +#else +#include "blackfin.h" +#include +#include +#endif + +// Variables that will be exported +int phaseShift = DEFAULT_PHASE_SHIFT; + +int firmware_compatibility = OK; +int firmware_check_done = 0; +char firmware_message[MAX_STR_LENGTH]; + +#ifdef VIRTUAL +pthread_t pthread_virtual_tid; +int virtual_status = 0; +int virtual_stop = 0; +int highvoltage = 0; +#endif + +int detectorFirstServer = 1; +int dacValues[NDAC] = {0}; +enum detectorSettings thisSettings = UNITIALIZED; +enum externalSignalFlag signalMode = 0; +int digitalTestBit = 0; + +// roi configuration +int adcConfigured = -1; +ROI rois[MAX_ROIS]; +int nROI = 0; +int ipPacketSize = 0; +int udpPacketSize = 0; + +// master slave configuration (for 25um) +int masterflags = NO_MASTER; +int masterdefaultdelay = 62; +int patternphase = 0; +int adcphase = 0; +int slavepatternphase = 0; +int slaveadcphase = 0; +int rsttosw1delay = 2; +int startacqdelay = 1; + +int isFirmwareCheckDone() { + return firmware_check_done; +} + +int getFirmwareCheckResult(char** mess) { + *mess = firmware_message; + return firmware_compatibility; +} + +void basictests() { + firmware_compatibility = OK; + firmware_check_done = 0; + memset(firmware_message, 0, MAX_STR_LENGTH); +#ifdef VIRTUAL + FILE_LOG(logINFOBLUE, ("******** Gotthard Virtual Server *****************\n")); + if (mapCSP0() == FAIL) { + strcpy(firmware_message, + "Could not map to memory. Dangerous to continue.\n"); + FILE_LOG(logERROR, (firmware_message)); + firmware_compatibility = FAIL; + firmware_check_done = 1; + return; + } + firmware_check_done = 1; + return; +#else + if (mapCSP0() == FAIL) { + strcpy(firmware_message, + "Could not map to memory. Dangerous to continue.\n"); + FILE_LOG(logERROR, ("%s\n\n", firmware_message)); + firmware_compatibility = FAIL; + firmware_check_done = 1; + return; + } + + // does check only if flag is 0 (by default), set by command line + if (((checkType() == FAIL) || (testFpga() == FAIL) || (testBus() == FAIL))) { + strcpy(firmware_message, + "Could not pass basic tests of FPGA and bus. Dangerous to continue.\n"); + FILE_LOG(logERROR, ("%s\n\n", firmware_message)); + firmware_compatibility = FAIL; + firmware_check_done = 1; + return; + } + + uint32_t boardrev = getBoardRevision(); + uint32_t ipadd = getDetectorIP(); + uint64_t macadd = getDetectorMAC(); + int64_t fwversion = getDetectorId(DETECTOR_FIRMWARE_VERSION); + int64_t swversion = getDetectorId(DETECTOR_SOFTWARE_VERSION); + int64_t client_sw_apiversion = getDetectorId(CLIENT_SOFTWARE_API_VERSION); + + FILE_LOG(logINFOBLUE, ("************ Gotthard Server *********************\n" + "Board Revision:\t\t 0x%x\n" + + "Detector IP Addr:\t\t 0x%x\n" + "Detector MAC Addr:\t\t 0x%llx\n\n" + + "Firmware Version:\t\t 0x%llx\n" + "Software Version:\t\t 0x%llx\n" + "F/w-S/w API Version:\t\t 0x%llx\n" + "Required Firmware Version:\t 0x%x\n" + "Client-Software API Version:\t 0x%llx\n" + "********************************************************\n", + boardrev, + ipadd, + (long long unsigned int)macadd, + (long long int)fwversion, + (long long int)swversion, + (long long int)client_sw_apiversion + )); + + FILE_LOG(logINFO, ("Basic Tests - success\n")); + firmware_check_done = 1; +#endif +} + +int checkType() { +#ifdef VIRTUAL + return OK; +#endif + volatile u_int32_t type = ((bus_r(BOARD_REVISION_REG) & DETECTOR_TYPE_MASK) >> DETECTOR_TYPE_OFFSET); + if (type == DETECTOR_TYPE_MOENCH_VAL){ + FILE_LOG(logERROR, ("This is not a Gotthard Server (read %d, expected ?)\n", type)); + return FAIL; + } + return OK; +} + +u_int32_t testFpga(void) { +#ifdef VIRTUAL + return OK; +#endif + FILE_LOG(logINFO, ("Testing FPGA:\n")); + + //fixed pattern + int ret = OK; + u_int32_t val = bus_r(FIX_PATT_REG); + if (val == FIX_PATT_VAL) { + FILE_LOG(logINFO, ("Fixed pattern: successful match 0x%08x\n",val)); + } else { + FILE_LOG(logERROR, ("Fixed pattern does not match! Read 0x%08x, expected 0x%08x\n", val, FIX_PATT_VAL)); + ret = FAIL; + } + + if (ret == OK) { + // dummy reg + FILE_LOG(logINFO, ("\tTesting Dummy Register:\n")); + u_int32_t addr = DUMMY_REG; + volatile u_int32_t val = 0, readval = 0; + int times = 1000 * 1000; + int i = 0; + for (i = 0; i < times; ++i) { + val = 0x5A5A5A5A - i; + bus_w(addr, val); + readval = bus_r(addr); + if (readval != val) { + FILE_LOG(logERROR, ("Mismatch! Loop(%d): Wrote 0x%x, read 0x%x\n", + i, val, readval)); + ret = FAIL; + break; + } + val = (i + (i << 10) + (i << 20)); + bus_w(addr, val); + readval = bus_r(addr); + if (readval != val) { + FILE_LOG(logERROR, ("Mismatch! Loop(%d): Wrote 0x%x, read 0x%x\n", + i, val, readval)); + ret = FAIL; + break; + } + val = 0x0F0F0F0F; + bus_w(addr, val); + readval = bus_r(addr); + if (readval != val) { + FILE_LOG(logERROR, ("Mismatch! Loop(%d): Wrote 0x%x, read 0x%x\n", + i, val, readval)); + ret = FAIL; + break; + } + val = 0xF0F0F0F0; + bus_w(addr, val); + if (readval != val) { + FILE_LOG(logERROR, ("Mismatch! Loop(%d): Wrote 0x%x, read 0x%x\n", + i, val, readval)); + ret = FAIL; + break; + } + } + bus_w(addr, 0); + if (ret == OK) { + FILE_LOG(logINFO, ("Successfully tested FPGA Dummy Register %d times\n", times)); + } + } + + return ret; +} + +int testBus() { +#ifdef VIRTUAL + return OK; +#endif + FILE_LOG(logINFO, ("Testing Bus:\n")); + + int ret = OK; + u_int32_t addr = DUMMY_REG; + volatile u_int32_t val = 0, readval = 0; + int times = 1000 * 1000; + int i = 0; + + for (i = 0; i < times; ++i) { + val += 0xbbbbb; + bus_w(addr, val); + readval = bus_r(addr); + if (readval != val) { + FILE_LOG(logERROR, ("Mismatch! Loop(%d): Wrote 0x%x, read 0x%x\n", + i, val, readval)); + ret = FAIL; + } + } + + bus_w(addr, 0); + + if (ret == OK) { + FILE_LOG(logINFO, ("Successfully tested bus %d times\n", times)); + } + return ret; +} + +int detectorTest( enum digitalTestMode arg, int ival) { +#ifdef VIRTUAL + return OK; +#endif + switch(arg){ + case DIGITAL_BIT_TEST: + if (ival > -1) { + digitalTestBit = (ival == 0) ? 0 : 1; + FILE_LOG(logINFO, ("Digital Test bit set: %d\n", digitalTestBit)); + } + return digitalTestBit; + case DETECTOR_FIRMWARE_TEST: return testFpga(); + case DETECTOR_BUS_TEST: return testBus(); + default: + FILE_LOG(logERROR, ("Test not implemented for this detector %d\n", (int)arg)); + break; + } + return OK; +} + + +/* Ids */ + +int64_t getDetectorId(enum idMode arg){ + int64_t retval = -1; + + switch(arg){ + case DETECTOR_SERIAL_NUMBER: + return getDetectorNumber(); + case DETECTOR_FIRMWARE_VERSION: + return getFirmwareVersion(); + case DETECTOR_SOFTWARE_VERSION: + return (GITDATE & 0xFFFFFF); + case CLIENT_SOFTWARE_API_VERSION: + return APIGOTTHARD; + default: + return retval; + } +} + +u_int64_t getFirmwareVersion() { +#ifdef VIRTUAL + return 0; +#endif + return ((bus_r(FPGA_VERSION_REG) & FPGA_VERSION_MSK) >> FPGA_VERSION_OFST); +} + +u_int32_t getDetectorNumber(){ +#ifdef VIRTUAL + return 0; +#endif + return 0; +} + +u_int64_t getDetectorMAC() { +#ifdef VIRTUAL + return 0; +#else + char output[255],mac[255]=""; + u_int64_t res=0; + FILE* sysFile = popen("ifconfig eth0 | grep HWaddr | cut -d \" \" -f 11", "r"); + fgets(output, sizeof(output), sysFile); + pclose(sysFile); + //getting rid of ":" + char * pch; + pch = strtok (output,":"); + while (pch != NULL){ + strcat(mac,pch); + pch = strtok (NULL, ":"); + } + sscanf(mac,"%llx",&res); + return res; +#endif +} + +u_int32_t getDetectorIP(){ +#ifdef VIRTUAL + return 0; +#endif + char temp[50]=""; + u_int32_t res=0; + //execute and get address + char output[255]; + FILE* sysFile = popen("ifconfig | grep 'inet addr:'| grep -v '127.0.0.1' | cut -d: -f2", "r"); + fgets(output, sizeof(output), sysFile); + pclose(sysFile); + + //converting IPaddress to hex. + char* pcword = strtok (output,"."); + while (pcword != NULL) { + sprintf(output,"%02x",atoi(pcword)); + strcat(temp,output); + pcword = strtok (NULL, "."); + } + strcpy(output,temp); + sscanf(output, "%x", &res); + //FILE_LOG(logINFO, ("ip:%x\n",res); + + return res; +} + +u_int32_t getBoardRevision() { +#ifdef VIRTUAL + return 0; +#endif + return ((bus_r(BOARD_REVISION_REG) & BOARD_REVISION_MASK) >> BOARD_REVISION_OFST); +} + + +/* initialization */ + +void initControlServer(){ + setupDetector(); +} + +void initStopServer() { + if (mapCSP0() == FAIL) { + FILE_LOG(logERROR, ("Stop Server: Map Fail. Dangerous to continue. Goodbye!\n")); + exit(EXIT_FAILURE); + } +} + + +/* set up detector */ + +void setupDetector() { + FILE_LOG(logINFO, ("This Server is for 1 Gotthard module (1280 channels)\n")); + + // Initialization + setPhaseShiftOnce(); + prepareADC(); /* TODO: check if need to replace with configureADC from firmwarE_funcs.c? */ + setROIADC(-1); // set adcsyncreg, daqreg, chipofinterestreg, cleanfifos, + setGbitReadout(); + //initDac(0); /*FIXME: if it doesnt work, switch to the old dac*/ + + // master, slave (25um) + setMasterSlaveConfiguration(); + + // Default Parameters + FILE_LOG(logINFOBLUE, ("Setting Default parameters\n")); + setDefaultDacs(); + setSettings(DEFAULT_SETTINGS); + setExtSignal(DEFAULT_TRIGGER_MODE); + setTiming(DEFAULT_TIMING_MODE); + setTimer(FRAME_NUMBER, DEFAULT_NUM_FRAMES); + setTimer(CYCLES_NUMBER, DEFAULT_NUM_CYCLES); + setTimer(ACQUISITION_TIME, DEFAULT_EXPTIME); + setTimer(FRAME_PERIOD, DEFAULT_PERIOD); + setTimer(DELAY_AFTER_TRIGGER, DEFAULT_DELAY); + setHighVoltage(DEFAULT_HIGH_VOLTAGE); +} + +int setDefaultDacs() { + int ret = OK; + FILE_LOG(logINFOBLUE, ("Setting Default Dac values\n")); + { + int i = 0; + int retval[2]={-1,-1}; + const int defaultvals[NDAC] = DEFAULT_DAC_VALS; + for(i = 0; i < NDAC; ++i) { + // if not already default, set it to default + if (dacValues[i] != defaultvals[i]) { + setDAC((enum DACINDEX)i,defaultvals[i],0,retval); + if (retval[0] != defaultvals[i]) { + FILE_LOG(logERROR, ("Setting dac %d failed, wrote %d, read %d\n",i ,defaultvals[i], retval[0])); + ret = FAIL; + } + } + } + } + return ret; +} + +uint32_t writeRegister16And32(uint32_t offset, uint32_t data) { + u_int32_t addr = offset << MEM_MAP_SHIFT; + if ((addr == CONTROL_REG) || (addr == FIFO_DATA_REG)) { + bus_w16(addr, (u_int16_t)data); + return (u_int32_t)bus_r16(addr); + } else + return writeRegister(offset, data); + +} + +uint32_t readRegister16And32(uint32_t offset) { + u_int32_t addr = offset << MEM_MAP_SHIFT; + if ((addr == CONTROL_REG) || (addr == FIFO_DATA_REG)) { + return (u_int32_t)bus_r16(addr); + } else + readRegister(offset); +} + +/* firmware functions (resets) */ + +void setPhaseShiftOnce() { + u_int32_t addr = MULTI_PURPOSE_REG; + volatile u_int32_t val = bus_r(addr); + FILE_LOG(logDEBUG1, ("Multipurpose reg: 0x%x\n", val)); + + // first time detector has switched on + if (!val) { + detectorFirstServer = 1; + FILE_LOG(logINFO, ("Implementing the first phase shift of %d\n", phaseShift)); + int times = 0; + for (times = 1; times < phaseShift; ++times) { + bus_w(addr,(INT_RSTN_MSK | ENT_RSTN_MSK | SW1_MSK | PHS_STP_MSK)); //0x1821 + bus_w(addr,(INT_RSTN_MSK | ENT_RSTN_MSK | (SW1_MSK &~ PHS_STP_MSK))); //0x1820 + } + FILE_LOG(logDEBUG1, ("Multipurpose reg: 0x%x\n", val)); + } else + detectorFirstServer = 0; +} + +void setPhaseShift(int numphaseshift) { + FILE_LOG(logINFO, ("Implementing phase shift of %d\n", numphaseshift)); + u_int32_t addr = MULTI_PURPOSE_REG; + + volatile u_int32_t val = bus_r(addr); + FILE_LOG(logDEBUG1, ("Multipurpose reg: 0x%x\n", val)); + int times = 0; + for (times = 1; times < numphaseshift; ++times) { + bus_w(addr, val | PHS_STP_MSK); + bus_w(addr, val & (~PHS_STP_MSK)); + } + FILE_LOG(logDEBUG1, ("Multipurpose reg: 0x%x\n", val)); +} + +void cleanFifos() { + FILE_LOG(logINFO, ("Cleaning FIFOs\n")); + bus_w(ADC_SYNC_REG, bus_r(ADC_SYNC_REG) | ADC_SYNC_CLEAN_FIFOS_MSK); + bus_w(ADC_SYNC_REG, bus_r(ADC_SYNC_REG) & ~ADC_SYNC_CLEAN_FIFOS_MSK); +} + +void setADCSyncRegister() { + FILE_LOG(logINFO, ("\tSetting ADC Sync and Token Delays:\n")); + u_int32_t addr = ADC_SYNC_REG; + + // 0x88(no roi), 0x1b(roi) (MSB) + u_int32_t tokenDelay = ((adcConfigured == -1) ? + ADC_SYNC_ENET_DELAY_NO_ROI_VAL : ADC_SYNC_ENET_DELAY_ROI_VAL); + + // 0x88032214(no roi), 0x1b032214(with roi) + u_int32_t val = (ADC_SYNC_TKN_VAL | tokenDelay); + + bus_w(addr, val); + FILE_LOG(logINFO, ("\tADC Sync Reg: 0x%x\n", bus_r(addr))); +} + +void setDAQRegister() { + FILE_LOG(logINFO, ("\tSetting Packet Length and DAQ Token Timing:\n")); + u_int32_t addr = DAQ_REG; + + // 0x1f16(board rev 1) 0x1f0f(board rev 2) + u_int32_t tokenTiming = ((getBoardRevision() == 1) ? + DAQ_TKN_TMNG_BRD_RVSN_1_VAL : DAQ_TKN_TMNG_BRD_RVSN_2_VAL); + + // 0x13f(no roi), 0x7f(roi) + u_int32_t packetLength = ((adcConfigured == -1) ? + DAQ_PCKT_LNGTH_NO_ROI_VAL : DAQ_PCKT_LNGTH_ROI_VAL); + + // MSB: packetLength LSB: tokenTiming + u_int32_t val = (tokenTiming | packetLength); + + bus_w(addr, val); + FILE_LOG(logINFO, ("\tDAQ Reg: 0x%x\n", bus_r(addr))); +} + +void setChipOfInterestRegister(int adc) { + FILE_LOG(logINFO, ("\tSelecting Chips of Interst:\n")); + u_int32_t addr = CHIP_OF_INTRST_REG; + + // 0x1f(no roi), 0xXX(roi) + u_int32_t adcSelect = ((adcConfigured == -1) ? + CHIP_OF_INTRST_ADC_SEL_MSK : + (((1 << adc) << CHIP_OF_INTRST_ADC_SEL_OFST) & CHIP_OF_INTRST_ADC_SEL_MSK)); + + // 0x0500(no roi), 0x0100(roi) + u_int32_t numChannels = ((adcConfigured == -1) ? NCHIP : NCHIPS_PER_ADC) * NCHAN; + + // 0x500001f(no roi), 0x10000xx(roi) MSB:num channels, LSB: selected ADC + u_int32_t val = (numChannels | adcSelect); + + bus_w(addr, val); + FILE_LOG(logINFO, ("\tChip Of Interest Reg: 0x%x\n", bus_r(addr))); +} + +void setROIADC(int adc) { + FILE_LOG(logINFO, ("\tSetting ROI ADC: %d\n", adc)); + adcConfigured = adc; + + setADCSyncRegister(); // adc sync & token delays + setDAQRegister(); // packet length & token timing + cleanFifos(); // clean fifos + setChipOfInterestRegister(adc); // num channels & select adc + + ipPacketSize = ((adcConfigured == -1) ? IP_PACKET_SIZE_NO_ROI : IP_PACKET_SIZE_ROI); + udpPacketSize = ((adcConfigured == -1) ? UDP_PACKETSIZE_NO_ROI : UDP_PACKETSIZE_ROI); +} + +void setGbitReadout() { + FILE_LOG(logINFO, ("Setting Gbit Readout\n")); + u_int32_t addr = CONFIG_REG; + bus_w(addr, bus_r(addr) & ~CONFIG_CPU_RDT_MSK); + FILE_LOG(logINFO, ("\tConfig Reg 0x%x\n", bus_r(addr))); +} + +int readConfigFile() { + // open config file + FILE* fd = fopen(CONFIG_FILE, "r"); + if(fd == NULL) { + FILE_LOG(logWARNING, ("\tCould not find config file %s\n", CONFIG_FILE)); + return FAIL; + } + FILE_LOG(logINFO, ("\tConfig file %s opened\n", CONFIG_FILE)); + + // Initialization + const size_t lineSize = 256; + char line[lineSize] = {0}; + const size_t keySize = lineSize / 2; + char key[keySize] = {0}; + char value[keySize] = {0}; + int scan = OK; + + // keep reading a line + while (fgets(line, lineSize, fd)) { + // ignore comments + if (line[0] == '#') + continue; + // read key & value + sscanf(line, "%s %s\n", key, value); + + // key is master/ slave flag + if (!strcasecmp(key,"masterflags")) { + if (!strcasecmp(value,"is_master")) { + masterflags = IS_MASTER; + FILE_LOG(logINFOBLUE, ("\tMaster\n")); + } else if (!strcasecmp(value,"is_slave")) { + masterflags = IS_SLAVE; + FILE_LOG(logINFOBLUE, ("\tSlave\n")); + } else if (!strcasecmp(value,"no_master")){ + masterflags = NO_MASTER; + FILE_LOG(logINFOBLUE, ("\tNo Master\n")); + } else { + FILE_LOG(logERROR, ("\tCould not scan masterflags %s value from config file\n", value)); + scan = FAIL; + break; + } + + // not first server since detector power on + if (!detectorFirstServer) { + FILE_LOG(logINFOBLUE, ("\tServer has been started up before. Ignoring rest of config file\n")); + fclose(fd); + return FAIL; + } + } + + // key is not master/ slave flag + else { + // convert value to int + int ival = 0; + if(sscanf(value, "%d", &ival) <= 0) { + FILE_LOG(logERROR, ("\tCould not scan parameter %s value %s from config file\n", key, value)); + scan = FAIL; + break; + } + // set value + if (!strcasecmp(key, "masterdefaultdelay")) + masterdefaultdelay = ival; + else if (!strcasecmp(key, "patternphase")) + patternphase = ival; + else if (!strcasecmp(key, "adcphase")) + adcphase = ival; + else if (!strcasecmp(key, "slavepatternphase")) + slavepatternphase = ival; + else if (!strcasecmp(key, "slaveadcphase")) + slaveadcphase = ival; + else if (!strcasecmp(key, "rsttosw1delay")) + rsttosw1delay = ival; + else if (!strcasecmp(key, "startacqdelay")) + startacqdelay = ival; + else { + FILE_LOG(logERROR, ("\tCould not scan parameter %s from config file\n", key)); + scan = FAIL; + break; + } + } + } + fclose(fd); + if (scan == FAIL) + exit(EXIT_FAILURE); + + FILE_LOG(logINFOBLUE, ( + "\tmasterdefaultdelay:%d\n" + "\tpatternphase:%d\n" + "\tadcphase:%d\n" + "\tslavepatternphase:%d\n" + "\tslaveadcphase:%d\n" + "\trsttosw1delay:%d\n" + "\tstartacqdelay:%d\n", + masterdefaultdelay, + patternphase, + adcphase, + slavepatternphase, + slaveadcphase, + rsttosw1delay, + startacqdelay)); + return OK; +} + +void setMasterSlaveConfiguration() { + FILE_LOG(logINFO, ("Reading Master Slave Configuration\n")); + + // no config file or not first time server + if (readConfigFile() == FAIL) + return; + + // master configuration + if (masterflags == IS_MASTER) { + // master default delay set, so reset delay + setDelay(0); + + // Set pattern phase for the master module + val = (bus_r(MULTI_PURPOSE_REG) & (~(PLL_CLK_SL_MSK))); // unset mask + bus_w(MULTI_PURPOSE_REG, val | PLL_CLK_SL_MSTR_VAL); + setPhaseShift(patternphase); + + // Set adc phase for the master module + val = (bus_r(MULTI_PURPOSE_REG) & (~(PLL_CLK_SL_MSK))); // unset mask + bus_w(MULTI_PURPOSE_REG, val | PLL_CLK_SL_MSTR_ADC_VAL); + setPhaseShift(adcphase); + + // Set pattern phase for the slave module + val = (bus_r(MULTI_PURPOSE_REG) & (~(PLL_CLK_SL_MSK))); // unset mask + bus_w(MULTI_PURPOSE_REG, val | PLL_CLK_SL_SLV_VAL); + setPhaseShift(slavepatternphase); + + // Set adc phase for the slave module + val = (bus_r(MULTI_PURPOSE_REG) & (~(PLL_CLK_SL_MSK))); // unset mask + bus_w(MULTI_PURPOSE_REG, val | PLL_CLK_SL_SLV_ADC_VAL); + setPhaseShift(slaveadcphase); + + // Set start acq delay + val = (bus_r(MULTI_PURPOSE_REG) & (~(STRT_ACQ_DLY_MSK))); // unset mask + val = val | ((startacqdelay << STRT_ACQ_DLY_OFST) & STRT_ACQ_DLY_MSK); // set val + bus_w(MULTI_PURPOSE_REG, val); + FILE_LOG(logDEBUG1, ("\tMultipurpose reg: 0x%x\n", val)); + } + + // all configuration - Set RST to SW1 delay + val = (bus_r(MULTI_PURPOSE_REG) & (~(RST_TO_SW1_DLY_MSK))); // unset mask + val = val | ((rsttosw1delay << RST_TO_SW1_DLY_OFST) & RST_TO_SW1_DLY_MSK); // set val + bus_w(MULTI_PURPOSE_REG, val); + FILE_LOG(logDEBUG1, ("\tMultipurpose reg: 0x%x\n", val)); + + FILE_LOG(logINFO, ("\tMaster Slave Configuration has been set up\n")); +} + + +/* set parameters - dr, roi */ + +int setDynamicRange(int dr){ + return DYNAMIC_RANGE; +} + +ROI* setROI(int n, ROI arg[], int *retvalsize, int *ret) { + + // set ROI + if(n >= 0){ + // print + if (!n) { + FILE_LOG(logINFO, ("Clearing ROI\n")); + } else { + FILE_LOG(logINFO, ("Setting ROI:\n")); + int i = 0; + for (i = 0; i < n; ++i) { + FILE_LOG(logINFO, ("\t(%d, %d)\n", arg[i].xmin, arg[i].xmax)); + + } + } + // only one ROI allowed per module + if (n > 1) { + FILE_LOG(logERROR, ("\tCannot set more than 1 ROI per module\n")); + *ret = FAIL; + *retvalsize = nROI; + return rois; + } + + //clear all rois + nROI = 0; + + // find adc number and recorrect channel limits + int adc = -1; + if (n) { + // all channels + if ((arg[0].xmin <= 0) && (arg[0].xmax >= NCHIP * NCHAN)) + adc = -1; + // single adc + else { + //adc = mid value/numchans + adc = ((((arg[0].xmax) + (arg[0].xmin))/2) / (NCHAN * NCHIPS_PER_ADC)); + // incorrect adc + if((adc < 0) || (adc > 4)) { + FILE_LOG(logERROR, ("\tadc value greater than 5. deleting roi\n")); + adc = -1; + } + // recorrect roi values + else { + rois[0].xmin = adc * (NCHAN * NCHIPS_PER_ADC); + rois[0].xmax = (adc + 1) * (NCHAN * NCHIPS_PER_ADC) - 1; + rois[0].ymin = -1; + rois[0].ymax = -1; + nROI = 1; + } + } + } + + if (adc == -1) + nROI = 0; + + FILE_LOG(logINFO, ("\tAdc to be configured: %d\n", adc)); + FILE_LOG(logINFO, ("\tROI to be configured: (%d, %d)\n", + (adc == -1) ? 0 : (rois[0].xmin), + (adc == -1) ? (NCHIP * NCHAN - 1) : (rois[0].xmax))); + + // could not set roi + if((n != 0) && ((arg[0].xmin != rois[0].xmin)|| + (arg[0].xmax != rois[0].xmax)|| + (arg[0].ymin != rois[0].ymin)|| + (arg[0].ymax != rois[0].ymax))) { + *ret = FAIL; + FILE_LOG(logERROR, ("\tCould not set given ROI\n")); + } + if(n != nROI) { + *ret = FAIL; + FILE_LOG(logERROR, ("\tCould not set or clear ROIs\n")); + } + + //set adc of interest + setROIADC(adc); + } + + // print + if (!nROI) { + FILE_LOG(logINFO, ("\tROI: None\n\n")); + } else { + FILE_LOG(logINFO, ("ROI:\n")); + int i = 0; + for (i = 0; i < nROI; ++i) { + FILE_LOG(logINFO, ("\t(%d, %d)\n\n", rois[i].xmin, rois[i].xmax)); + + } + } + + *retvalsize = nROI; + return rois; +} + + +/* parameters - timer */ + +int64_t setTimer(enum timerIndex ind, int64_t val) { + + int64_t retval = -1; + switch(ind){ + + case FRAME_NUMBER: + if(val >= 0) { + FILE_LOG(logINFO, ("Setting #frames: %lld\n",(long long int)val)); + } + retval = set64BitReg(val, SET_FRAMES_LSB_REG, SET_FRAMES_MSB_REG); + FILE_LOG(logDEBUG1, ("\tGetting #frames: %lld\n", (long long int)retval)); + break; + + case ACQUISITION_TIME: + if(val >= 0){ + FILE_LOG(logINFO, ("Setting exptime: %lldns\n", (long long int)val)); + val = (val * 1E-3 * CLK_FREQ) + 0.5; + } + retval = (set64BitReg(val, SET_EXPTIME_LSB_REG, SET_EXPTIME_MSB_REG) / + (1E-3 * CLK_FREQ)) + 0.5; + FILE_LOG(logDEBUG1, ("\tGetting exptime: %lldns\n", (long long int)retval)); + break; + + case FRAME_PERIOD: + if(val >= 0){ + FILE_LOG(logINFO, ("Setting period: %lldns\n",(long long int)val)); + val = (val * 1E-3 * CLK_FREQ) + 0.5; + } + retval = (set64BitReg(val, SET_PERIOD_LSB_REG, SET_PERIOD_MSB_REG) / + (1E-3 * CLK_FREQ)) + 0.5; + FILE_LOG(logDEBUG1, ("\tGetting period: %lldns\n", (long long int)retval)); + break; + + case DELAY_AFTER_TRIGGER: + if(val >= 0){ + FILE_LOG(logINFO, ("Setting delay: %lldns\n", (long long int)val)); + if (masterflags == IS_MASTER) { + value += masterdefaultdelay; + FILE_LOG(logINFO, ("\tActual delay (master): %lld\n", (long long int) value)); + } + val = (val * 1E-3 * CLK_FREQ) + 0.5; + } + retval = (set64BitReg(val, SET_DELAY_LSB_REG, SET_DELAY_MSB_REG) / + (1E-3 * CLK_FREQ)) + 0.5; + FILE_LOG(logDEBUG1, ("\tGetting delay: %lldns\n", (long long int)retval)); + if (masterflags == IS_MASTER) { + FILE_LOG(logDEBUG1, ("\tActual delay read (master): %lld\n", (long long int) retval)); + retval -= masterdefaultdelay; + } + break; + + case CYCLES_NUMBER: + if(val >= 0) { + FILE_LOG(logINFO, ("Setting #cycles: %lld\n", (long long int)val)); + } + retval = set64BitReg(val, SET_TRAINS_LSB_REG, SET_TRAINS_MSB_REG); + FILE_LOG(logDEBUG1, ("\tGetting #cycles: %lld\n", (long long int)retval)); + break; + + default: + FILE_LOG(logERROR, ("Timer Index not implemented for this detector: %d\n", ind)); + break; + } + + return retval; + +} + + + +int64_t getTimeLeft(enum timerIndex ind){ +#ifdef VIRTUAL + return 0; +#endif + int64_t retval = -1; + switch(ind){ + + case FRAME_NUMBER: + retval = get64BitReg(GET_FRAMES_LSB_REG, GET_FRAMES_MSB_REG); + FILE_LOG(logINFO, ("Getting number of frames left: %lld\n",(long long int)retval)); + break; + + case ACQUISITION_TIME: + retval = (get64BitReg(GET_EXPTIME_LSB_REG, GET_EXPTIME_MSB_REG) / + (1E-3 * CLK_FREQ)) + 0.5; + FILE_LOG(logINFO, ("Getting exptime left: %lldns\n", (long long int)retval)); + break; + + case FRAME_PERIOD: + retval = (get64BitReg(GET_PERIOD_LSB_REG, GET_PERIOD_MSB_REG) / + (1E-3 * CLK_FREQ)) + 0.5; + FILE_LOG(logINFO, ("Getting period left: %lldns\n", (long long int)retval)); + break; + + case DELAY_AFTER_TRIGGER: + retval = (get64BitReg(GET_DELAY_LSB_REG, GET_DELAY_MSB_REG) / + (1E-3 * CLK_FREQ)) + 0.5; + FILE_LOG(logINFO, ("Getting delay left: %lldns\n", (long long int)retval)); + if (masterflags == IS_MASTER) { + FILE_LOG(logDEBUG1, ("\tGetting Actual delay (master): %lld\n", (long long int) retval)); + retval -= masterdefaultdelay; + } + break; + + case CYCLES_NUMBER: + retval = get64BitReg(GET_TRAINS_LSB_REG, GET_TRAINS_MSB_REG); + FILE_LOG(logINFO, ("Getting number of cycles left: %lld\n", (long long int)retval)); + break; + + default: + FILE_LOG(logERROR, ("Remaining Timer index not implemented for this detector: %d\n", ind)); + break; + } + + return retval; +} + + +/* parameters - channel, chip, module, settings */ + +int setModule(sls_detector_module myMod, char* mess){ + + FILE_LOG(logINFO, ("Setting module with settings %d\n",myMod.reg)); + + // settings + setSettings( (enum detectorSettings)myMod.reg); + + //set dac values + { + int i = 0, retval[2] = {-1, -1}; + for(i = 0; i < NDAC; ++i) + setDAC((enum DACINDEX)i, myMod.dacs[i], 0, retval); + } + return OK; +} + +int getModule(sls_detector_module *myMod){ + int idac = 0; + for (idac = 0; idac < NDAC; ++idac) { + if (dacValues[idac] >= 0) + *((myMod->dacs) + idac) = dacValues[idac]; + } + // check if all of them are not initialized + int initialized = 0; + for (idac = 0; idac < NDAC; ++idac) { + if (dacValues[idac] >= 0) + initialized = 1; + } + if (initialized) + return OK; + return FAIL; +} + +enum detectorSettings setSettings(enum detectorSettings sett){ + if(sett == UNINITIALIZED) + return thisSettings; + + // set settings + if(sett != GET_SETTINGS) { + u_int32_t addr = GAIN_REG; + + // find conf gain value + uint32_t confgain = 0x0; + switch (sett) { + case DYNAMICGAIN: + FILE_LOG(logINFO, ("Set settings - Dyanmic Gain\n")); + confgain = GAIN_CONFGAIN_DYNMC_GAIN_VAL; + break; + case HIGHGAIN: + FILE_LOG(logINFO, ("Set settings - High Gain\n")); + confgain = GAIN_CONFGAIN_HGH_GAIN_VAL; + break; + case LOWGAIN: + FILE_LOG(logINFO, ("Set settings - Low Gain\n")); + confgain = GAIN_CONFGAIN_LW_GAIN_VAL; + break; + case MEDIUMGAIN: + FILE_LOG(logINFO, ("Set settings - Medium Gain\n")); + confgain = GAIN_CONFGAIN_MDM_GAIN_VAL; + break; + case VERYHIGHGAIN: + FILE_LOG(logINFO, ("Set settings - Very High Gain\n")); + confgain = GAIN_CONFGAIN_VRY_HGH_GAIN_VAL; + break; + default: + FILE_LOG(logERROR, ("This settings is not defined for this detector %d\n", (int)sett)); + return -1; + } + // set conf gain + bus_w(addr, bus_r(addr) & ~GAIN_CONFGAIN_MSK); + bus_w(addr, bus_r(addr) | GAIN_CONFGAIN_DYNMC_GAIN_VAL); + FILE_LOG(logINFO, ("\Gain Reg: 0x%x\n", bus_r(addr))); + thisSettings = sett; + } + + return getSettings(); +} + +enum detectorSettings getSettings(){ + + uint32_t regval = bus_r(GAIN_REG); + FILE_LOG(logDEBUG1, ("Getting Settings\n Read Gain Register :0x%x\n", val)); + + uint32_t val = regval & GAIN_CONFGAIN_MSK; + switch(val) { + case GAIN_CONFGAIN_DYNMC_GAIN_VAL: + FILE_LOG(logINFO, ("Settings read: Dyanmic Gain. Gain Reg: 0x%x\n", regval)); + thisSettings = DYNAMICGAIN; + break; + case GAIN_CONFGAIN_HGH_GAIN_VAL: + FILE_LOG(logINFO, ("Settings read: High Gain. Gain Reg: 0x%x\n", regval)); + thisSettings = HIGHGAIN; + break; + case GAIN_CONFGAIN_LW_GAIN_VAL: + FILE_LOG(logINFO, ("Settings read: Low Gain. Gain Reg: 0x%x\n", regval)); + thisSettings = LOWGAIN; + break; + case GAIN_CONFGAIN_MDM_GAIN_VAL: + FILE_LOG(logINFO, ("Settings read: Medium Gain. Gain Reg: 0x%x\n", regval)); + thisSettings = MEDIUMGAIN; + break; + case GAIN_CONFGAIN_VRY_HGH_GAIN_VAL: + FILE_LOG(logINFO, ("Settings read: Very High Gain. Gain Reg: 0x%x\n", regval)); + thisSettings = VERYHIGHGAIN; + break; + default: + thisSettings = UNDEFINED; + FILE_LOG(logERROR, ("Settings read: Undefined. Gain Reg: 0x%x\n", regval)); + } + + return thisSettings; +} + + +/* parameters - dac, adc, hv */ + +int voltageToDac(int value){ + int vmin = 0; + int vmax = 2500; + int nsteps = 4096; + if ((value < vmin) || (value > vmax)) { + FILE_LOG(logERROR, ("Voltage value (to convert to dac value) is outside bounds: %d\n", value)); + return -1; + } + return (int)(((value - vmin) / (vmax - vmin)) * (nsteps - 1) + 0.5); +} + +int dacToVoltage(unsigned int digital){ + int vmin = 0; + int vmax = 2500; + int nsteps = 4096; + int v = vmin + (vmax - vmin) * digital / (nsteps - 1); + if((v < 0) || (v > nsteps - 1)) { + FILE_LOG(logERROR, ("Voltage value (converted from dac value) is outside bounds: %d\n", v)); + return -1; + } + return v; +} + +void setDAC(enum DACINDEX ind, int val, int mV, int retval[]){ + int dacmV = val; + + //if set and mv, convert to dac + if (val > 0) { + if (mV) + val = voltageToDac(val); //gives -1 on error + else + dacmV = dacToVoltage(val); //gives -1 on error + } + + if (val >= 0) { + FILE_LOG(logINFO, ("Setting DAC %d: %d dac (%d mV)\n",ind, val, mV)); +#ifndef VIRTUAL + initDAC(ind,val); + clearDACSregister(); +#else + dacValues[ind] = val; +#endif + } + + retval[0] = dacValues[ind]; + retval[1] = dacToVoltage(retval[0]); + FILE_LOG(logDEBUG1, ("Getting DAC %d : %d dac (%d mV)\n",ind, retval[0], retval[1])); +} + +void initDAC(int dac_addr, int value) { + FILE_LOG(logDEBUG1, ("Programming dac %d with value %d\n", dac_addr, value)); + clearDACSregister(); + if (value >= 0) + program_one_dac(dac_addr,value); + nextDAC(); +} + +void clearDACSregister() { + putout("1111111111111111");//reset + putout("1111111111111110");//cs down +} + +void nextDAC() { + putout("1111111111111011");//cs up + putout("1111111111111001");//clk down + putout("1111111111111111");//reset +} + +void program_one_dac(int addr, int value) { + FILE_LOG(logDEBUG1, ("Programming dac %d with value %d\n", addr, value)); + int origValue = value; + int control = 32 + addr; + value = (value << 4) | (control << 16); + + { + int i = 0; + for (i = 0; i < 24; ++i) { + int bit = value & (1 << (23 - i)); + if (bit) { + putout("1111111111111100");//clk down + putout("1111111111111100");//write data + putout("1111111111111110");//clk up + } + else + { + putout("1111111111111000");//clk down + putout("1111111111111000");//write data + putout("1111111111111010");//clk up + } + } + } + dacValues[addr] = origValue; + FILE_LOG(logDEBUG1, ("\tDac %d set to %dn", addr, origValue)); +} + +// direct pattern output +u_int32_t putout(char *s) { + if (strlen(s)<16) { + FILE_LOG(logERROR, ("putout: incorrect pattern length\n")); + return FAIL; + } + + u_int32_t pat=0; + {int i = 0; + for (i = 0; i < 16; ++i) { + if (s[i]=='1') + pat = pat + (1 << (15 - i)); + } + } + bus_w(DAC_CNTRL_REG, pat); + return OK; +} + + +int getADC(enum ADCINDEX ind){ +#ifdef VIRTUAL + return 0; +#endif + char tempnames[2][40]={"VRs/FPGAs Temperature", "ADCs/ASICs Temperature"}; + FILE_LOG(logDEBUG1, ("Getting Temperature for %s\n", tempnames[ind])); + + u_int32_t addr = TEMP_SPI_IN_REG; + uint32_t addrout = TEMP_SPI_OUT_REG; + const int repeats = 6; // number of register writes for delay + const int reads = 20; + u_int32_t value = 0; + + // standby, high clk, high cs + bus_w(addr, (TEMP_SPI_IN_T1_CLK_MSK | TEMP_SPI_IN_T1_CS_MSK | TEMP_SPI_IN_T2_CLK_MSK | TEMP_SPI_IN_T2_CS_MSK)); + + // high clk low cs + bus_w(addr, (TEMP_SPI_IN_T1_CLK_MSK | TEMP_SPI_IN_T2_CLK_MSK)); + + { + int i = 0; + for (i = 0; i < reads; ++i) { + + int j = 0; + // low clk low cs + for (j = 0; j < repeats; ++j) + bus_w(addr, 0x0); + //high clk low cs + for (j = 0; j < repeats; ++j) + bus_w(addr, (TEMP_SPI_IN_T1_CLK_MSK | TEMP_SPI_IN_T2_CLK_MSK)); + + // only the first time + if (i <= 10) { + if (ind == TEMP_ADC) + value = (value << 1) + (bus_r(addrout) & TEMP_SPI_OUT_T1_DT_MSK); + else + value = (value << 1) + (bus_r(addrout) & TEMP_SPI_OUT_T2_DT_MSK); + } + } + } + + // standby high clk, high cs + bus_w(addr, (TEMP_SPI_IN_T1_CLK_MSK | TEMP_SPI_IN_T1_CS_MSK | TEMP_SPI_IN_T2_CLK_MSK | TEMP_SPI_IN_T2_CS_MSK)); + + FILE_LOG(logDEBUG1, ("\tInitial Temperature value: %u\n", value)); + // conversion + value = value/4.0; + FILE_LOG(logINFO, ("\tTemperature %s: %f °C\n",tempnames[ind], value)); + return value; +} + +int setHighVoltage(int val){ +#ifdef VIRTUAL + if (val >= 0) + highvoltage = val; + return highvoltage; +#endif + u_int32_t addr = HV_REG; + u_int32_t sel = 0x0; + + // set + if (val >= 0) { + FILE_LOG(logINFO, ("Setting High Voltage to %d\n", val)); + switch (val) { + case 0: + break; + case 90: + sel = HV_SEL_90_VAL; + break; + case 110: + sel = HV_SEL_110_VAL; + break; + case 120: + sel = HV_SEL_120_VAL; + break; + case 150: + sel = HV_SEL_150_VAL; + break; + case 180: + sel = HV_SEL_180_VAL; + break; + case 200: + sel = HV_SEL_200_VAL; + break; + default: + FILE_LOG(logERROR, ("%d high voltage is not defined for this detector\n", val)); + return setHighVoltage(-1); + } + FILE_LOG(logDEBUG1, ("\tHigh voltage value to be sent: 0x%x\n", sel)); + + // switch off high voltage and set value + bus_w(addr, (bus_r(addr) & ~HV_ENBL_MSK) | sel); + + // switch on high voltage + if (val > 0) + bus_w(addr, bus_r(addr) | HV_ENBL_MSK); + } + + // get + u_int32_t retval = 0; + u_int32_t regval = bus_r(addr); + FILE_LOG(logDEBUG1, ("\tHigh voltage value read: 0x%x\n", regval)); + + // if high voltage was enabled, find value + if (regval & HV_ENBL_MSK) { + switch (regval & HV_SEL_MSK) { + case HV_SEL_90_VAL: + retval = 90; + break; + case HV_SEL_110_VAL: + retval = 110; + break; + case HV_SEL_120_VAL: + retval = 120; + break; + case HV_SEL_150_VAL: + retval = 150; + break; + case HV_SEL_180_VAL: + retval = 180; + break; + default: + retval = 200; + break; + } + } + FILE_LOG(logDEBUG1, ("\tHigh Voltage: %d\n", retval)); + return retval; +} + + +/* parameters - timing, extsig */ + + +void setTiming( enum externalCommunicationMode arg){ + u_int32_t addr = EXT_SIGNAL_REG; + + if (arg != GET_EXTERNAL_COMMUNICATION_MODE){ + switch((int)arg){ + case AUTO_TIMING: + FILE_LOG(logINFO, ("Set Timing: Auto\n")); + bus_w(addr, EXT_SIGNAL_OFF_VAL); + break; + case TRIGGER_EXPOSURE: + if (signalMode == TRIGGER_IN_FALLING_EDGE) { + FILE_LOG(logINFO, ("Set Timing: Trigger (Falling Edge)\n")); + bus_w(addr, EXT_SIGNAL_TRGGR_IN_FLLNG_VAL); + } else { + FILE_LOG(logINFO, ("Set Timing: Trigger (Rising Edge)\n")); + bus_w(addr, EXT_SIGNAL_TRGGR_IN_RSNG_VAL); + } + break; + default: + FILE_LOG(logERROR, ("Unknown timing mode %d for this detector\n", (int)arg)); + return; + } + timingMode = arg; + } +} + +enum externalCommunicationMode getTiming() { + u_int32_t regval = bus_r(EXT_SIGNAL_REG); + switch (regval) { + case EXT_SIGNAL_TRGGR_IN_RSNG_VAL: + case EXT_SIGNAL_TRGGR_IN_FLLNG_VAL: + return TRIGGER_EXPOSURE; + default: + return AUTO_TIMING; + } +} + +void setExtSignal(enum externalSignalFlag mode) { + switch (mode) { + case TRIGGER_IN_RISING_EDGE: + case TRIGGER_IN_FALLING_EDGE: + signalMode = mode; + setTiming(getTiming()); + break; + default: + FILE_LOG(logERROR, ("Extsig (signal mode) %d not defined for this detector\n", mode)); + break; + } +} + +int getExtSignal() { + return signalMode; +} + + +/* configure mac */ + +void calcChecksum(mac_conf* mac, int sourceip, int destip) { + mac->ip.ip_ver = 0x4; + mac->ip.ip_ihl = 0x5; + mac->ip.ip_tos = 0x0; + mac->ip.ip_len = ipPacketSize; + mac->ip.ip_ident = 0x0000; + mac->ip.ip_flag = 0x2; //not nibble aligned (flag& offset + mac->ip.ip_offset = 0x00; + mac->ip.ip_ttl = 0x70; + mac->ip.ip_protocol = 0x11; + mac->ip.ip_chksum = 0x0000 ; // pseudo + mac->ip.ip_sourceip = sourceip; + mac->ip.ip_destip = destip; + FILE_log(logDEBUG1, ("\tIP TTL: 0x%x\n", mac_conf_regs->ip.ip_ttl)); + + int count = sizeof(ip); + unsigned short *addr; + addr = (unsigned short*)(&ip); /* warning: assignment from incompatible pointer type */ + + long int sum = 0; + while( count > 1 ) { + sum += *addr++; + count -= 2; + } + if (count > 0) + sum += *addr; // Add left-over byte, if any + while (sum>>16) + sum = (sum & 0xffff) + (sum >> 16);// Fold 32-bit sum to 16 bits + long int checksum = (~sum) & 0xffff; + FILE_LOG(logINFO, ("\tIP checksum is 0x%lx\n", checksum)); + mac->ip.ip_chksum = checksum; +} + +int configureMAC(uint32_t destip, uint64_t destmac, uint64_t sourcemac, uint32_t sourceip, uint32_t udpport, uint32_t udpport2, int ival) { +#ifdef VIRTUAL + return OK; +#endif + FILE_LOG(logINFOBLUE, ("Configuring MAC\n")); + u_int32_t addr = MULTI_PURPOSE_REG; + + FILE_LOG(logDEBUG1, ("\tRoi: %d, Ip Packet size: %d UDP Packet size: %d\n", + adcConfigured, ipPacketSize, udpPacketSize)); + + uint32_t sourceport = DEFAULT_TX_UDP_PORT; + FILE_LOG(logINFO, ("\tSource IP : %d.%d.%d.%d \t\t(0x%08x)\n", + (sourceip>>24)&0xff,(sourceip>>16)&0xff,(sourceip>>8)&0xff,(sourceip)&0xff, sourceip)); + FILE_LOG(logINFO, ("\tSource MAC : %02x:%02x:%02x:%02x:%02x:%02x \t(0x%010llx)\n", + (unsigned int)((sourcemac>>40)&0xFF), + (unsigned int)((sourcemac>>32)&0xFF), + (unsigned int)((sourcemac>>24)&0xFF), + (unsigned int)((sourcemac>>16)&0xFF), + (unsigned int)((sourcemac>>8)&0xFF), + (unsigned int)((sourcemac>>0)&0xFF), + (long long unsigned int)sourcemac)); + FILE_LOG(logINFO, ("\tSource Port : %d \t\t\t(0x%08x)\n",sourceport, sourceport)); + FILE_LOG(logINFO, ("\tDest. IP : %d.%d.%d.%d \t\t(0x%08x)\n", + (destip>>24)&0xff,(destip>>16)&0xff,(destip>>8)&0xff,(destip)&0xff, destip)); + FILE_LOG(logINFO, ("\tDest. MAC : %02x:%02x:%02x:%02x:%02x:%02x \t(0x%010llx)\n", + (unsigned int)((destmac>>40)&0xFF), + (unsigned int)((destmac>>32)&0xFF), + (unsigned int)((destmac>>24)&0xFF), + (unsigned int)((destmac>>16)&0xFF), + (unsigned int)((destmac>>8)&0xFF), + (unsigned int)((destmac>>0)&0xFF), + (long long unsigned int)destmac)); + FILE_LOG(logINFO, ("\tDest. Port : %d \t\t\t(0x%08x)\n",udpport, udpport)); + + // set/ unset the digital test bit + if (ival) + bus_w (addr, bus_r(addr) | DGTL_TST_MSK); + else + bus_w (addr, bus_r(addr) & ~DGTL_TST_MSK); + FILE_log(logDEBUG1, ("\tDigital Test Bit. MultiPurpose reg: 0x%x\n", bus_r(addr))); + + //reset mac + bus_w (addr, bus_r(addr) | RST_MSK); + FILE_log(logDEBUG1, ("\tReset Mac. MultiPurpose reg: 0x%x\n", bus_r(addr))); + + usleep(500000); + + // release reset + bus_w(addr, bus_r(addr) &(~ RST_MSK)); + FILE_log(logDEBUG1, ("\tReset released. MultiPurpose reg: 0x%x\n", bus_r(addr))); + + // write shadow regs + bus_w(addr, bus_r(addr) | (ENT_RSTN_MSK | WRT_BCK_MSK)); + FILE_log(logDEBUG1, ("\tWrite shadow regs. MultiPurpose reg: 0x%x\n", bus_r(addr))); + + // release write back + bus_w(addr, bus_r(addr) &(~WRT_BCK_MSK)); + FILE_log(logDEBUG1, ("\tWrite back released. MultiPurpose reg: 0x%x\n", bus_r(addr))); + + // nreset phy /*FIXME: is this needed ?? */ + bus_w(addr, bus_r(addr) | ENT_RSTN_MSK); + FILE_log(logDEBUG1, ("\tNreset phy. MultiPurpose reg: 0x%x\n", bus_r(addr))); + + FILE_log(logDEBUG1, ("\tConfiguring MAC CONF\n")); + mac_conf *mac_conf_regs = (mac_conf*)(CSP0BASE + ENET_CONF_REG * 2); // direct write + mac_conf_regs->mac.mac_dest_mac1 = ((destmac >> (8 * 5)) & 0xFF); + mac_conf_regs->mac.mac_dest_mac2 = ((destmac >> (8 * 4)) & 0xFF); + mac_conf_regs->mac.mac_dest_mac3 = ((destmac >> (8 * 3)) & 0xFF); + mac_conf_regs->mac.mac_dest_mac4 = ((destmac >> (8 * 2)) & 0xFF); + mac_conf_regs->mac.mac_dest_mac5 = ((destmac >> (8 * 1)) & 0xFF); + mac_conf_regs->mac.mac_dest_mac6 = ((destmac >> (8 * 0)) & 0xFF); + FILE_log(logDEBUG1, ("\tDestination Mac: %llx %x:%x:%x:%x:%x:%x\n", + destmac, + mac_conf_regs->mac.mac_dest_mac1, + mac_conf_regs->mac.mac_dest_mac2, + mac_conf_regs->mac.mac_dest_mac3, + mac_conf_regs->mac.mac_dest_mac4, + mac_conf_regs->mac.mac_dest_mac5, + mac_conf_regs->mac.mac_dest_mac6)); + mac_conf_regs->mac.mac_src_mac1 = ((sourcemac >> (8 * 5)) & 0xFF); + mac_conf_regs->mac.mac_src_mac2 = ((sourcemac >> (8 * 4)) & 0xFF); + mac_conf_regs->mac.mac_src_mac3 = ((sourcemac >> (8 * 3)) & 0xFF); + mac_conf_regs->mac.mac_src_mac4 = ((sourcemac >> (8 * 2)) & 0xFF); + mac_conf_regs->mac.mac_src_mac5 = ((sourcemac >> (8 * 1)) & 0xFF); + mac_conf_regs->mac.mac_src_mac6 = ((sourcemac >> (8 * 0)) & 0xFF); + FILE_log(logDEBUG1, ("\tSource Mac: %llx %x:%x:%x:%x:%x:%x\n", + sourcemac, + mac_conf_regs->mac.mac_src_mac1, + mac_conf_regs->mac.mac_src_mac2, + mac_conf_regs->mac.mac_src_mac3, + mac_conf_regs->mac.mac_src_mac4, + mac_conf_regs->mac.mac_src_mac5, + mac_conf_regs->mac.mac_src_mac6)); + mac_conf_regs->mac.mac_ether_type = 0x0800; //ipv4 + + calcChecksum(mac_conf_regs, sourceip, destip); + mac_conf_regs->udp.udp_srcport = sourceport; + mac_conf_regs->udp.udp_destport = udpport; + mac_conf_regs->udp.udp_len = udpPacketSize; + mac_conf_regs->udp.udp_chksum = 0x0000; + + FILE_log(logDEBUG1, ("\tConfiguring TSE\n")); + tse_conf *tse_conf_regs = (tse_conf*)(CSP0BASE + TSE_CONF_REG * 2); // direct write + tse_conf_regs->rev = 0xA00; + tse_conf_regs->scratch = 0xCCCCCCCC; + tse_conf_regs->command_config = 0xB; + tse_conf_regs->mac_0 = 0x17231C00; + tse_conf_regs->mac_1 = 0xCB4A; + tse_conf_regs->frm_length = 0x5DC; //max frame length (1500 bytes) (was 0x41C) + tse_conf_regs->pause_quant = 0x0; + tse_conf_regs->rx_section_empty = 0x7F0; + tse_conf_regs->rx_section_full = 0x10; + tse_conf_regs->tx_section_empty = 0x3F8; //was 0x7F0; + tse_conf_regs->tx_section_full = 0x16; + tse_conf_regs->rx_almost_empty = 0x8; + tse_conf_regs->rx_almost_full = 0x8; + tse_conf_regs->tx_almost_empty = 0x8; + tse_conf_regs->tx_almost_full = 0x3; + tse_conf_regs->mdio_addr0 = 0x12; + tse_conf_regs->mdio_addr1 = 0x0; + + FILE_log(logDEBUG1, ("\tConfigure Mac Done")); + mac_conf_regs->cdone = 0xFFFFFFFF; + + // write shadow regs /* FIXME: Only INT_RSTN_MSK | WRT_BCK_MSK */ + bus_w(addr, bus_r(addr) | (INT_RSTN_MSK | ENT_RSTN_MSK| WRT_BCK_MSK)); + FILE_log(logDEBUG1, ("\tWrite shadow regs with int reset. MultiPurpose reg: 0x%x\n", bus_r(addr))); + + usleep(100000); + + // release write back + bus_w(addr, bus_r(addr) &(~WRT_BCK_MSK)); + FILE_log(logDEBUG1, ("\tWrite back released. MultiPurpose reg: 0x%x\n", bus_r(addr))); + + // sw1 /* FIXME: Only SW1_MSK */ + bus_w(addrr, bus_r(addrr) | (INT_RSTN_MSK | ENT_RSTN_MSK | SW1_MSK)); + FILE_log(logDEBUG1, ("\tSw1. MultiPurpose reg: 0x%x\n", bus_r(addr))); + + usleep(1000 * 1000); + return OK; +} + +int getAdcConfigured(){ + return adcConfigured; +} + + +/* gotthard specific - loadimage, read/reset counter block */ + +void loadImage(enum imageType index, short int imageVals[]){ + u_int32_t addr = DARK_IMAGE_REG; + if (index == GAIN_IMAGE) + addr = GAIN_IMAGE_REG; + int dataBytes = calculateDataBytes(); + + volatile u_int16_t *ptr = (u_int16_t*)(CSP0BASE + addr * 2); + memcpy((char*)ptr, (char*)imageVals, dataBytes); + + FILE_log(logINFO, ("Loaded %s image at 0x%p\n", + (index == GAIN_IMAGE) ? "Gain" : "Dark", (void*) ptr)); +} + +int readCounterBlock(int startACQ, short int counterVals[]){ + FILE_log(logINFO, ("Reading Counter Block with start Acq :%d\n", startACQ)); + + // stop any current acquisition + if (runBusy()) { + if (stopStateMachine() == FAIL) + return FAIL; + // waiting for the last frame read to be done + while(runBusy()) + usleep(500); + FILE_log(logDEBUG1, ("State machine stopped\n")); + } + + // copy memory + addr = COUNTER_MEMORY_REG; + volatile u_int16_t *ptr = (u_int16_t*)(CSP0BASE + addr * 2); + int dataBytes = calculateDataBytes(); + memcpy((char*)counterVals, (char*)ptr, dataBytes); + + // unreset counter + addr = MULTI_PURPOSE_REG; + bus_w(addr, (bus_r(addr) &~ RST_CNTR_MSK)); + FILE_LOG(logDEBUG1, ("\tUnsetting reset Counter. Multi Purpose Reg: 0x%x\n", bus_r(addr))); + + // start state machine + if (startACQ == 1){ + startStateMachine(); + if (runBusy()) { + FILE_LOG(logINFO, ("State machine RUNNING\n")); + } else { + FILE_LOG(logINFO, ("State machine IDLE\n")); + } + } + return OK; +} + +int resetCounterBlock(int startACQ){ + FILE_log(logINFO, ("Resetting Counter Block with start Acq :%d\n", startACQ)); + + // stop any current acquisition + if (runBusy()) { + if (stopStateMachine() == FAIL) + return FAIL; + // waiting for the last frame read to be done + while(runBusy()) + usleep(500); + FILE_log(logDEBUG1, ("State machine stopped\n")); + } + + // reset counter + u_int32_t addr = MULTI_PURPOSE_REG; + bus_w(addr, (bus_r(addr) | RST_CNTR_MSK)); + FILE_LOG(logDEBUG1, ("\tResetting Counter. Multi Purpose Reg: 0x%x\n", bus_r(addr))); + + // copy memory + addr = COUNTER_MEMORY_REG; + volatile u_int16_t *ptr = (u_int16_t*)(CSP0BASE + addr * 2); + int dataBytes = calculateDataBytes(); + char *counterVals = NULL; + counterVals = realloc(counterVals, dataBytes); + memcpy((char*)counterVals, (char*)ptr, dataBytes); + + // unreset counter + addr = MULTI_PURPOSE_REG; + bus_w(addr, (bus_r(addr) &~ RST_CNTR_MSK)); + FILE_LOG(logDEBUG1, ("\tUnsetting reset Counter. Multi Purpose Reg: 0x%x\n", bus_r(addr))); + + // start state machine + if (startACQ == 1){ + startStateMachine(); + if (runBusy()) { + FILE_LOG(logINFO, ("State machine RUNNING\n")); + } else { + FILE_LOG(logINFO, ("State machine IDLE\n")); + } + } + + if (sizeof(counterVals) <= 0){ + FILE_LOG(logERROR, ("\tSize of counterVals: %d\n", (int)sizeof(counterVals))); + return FAIL; + } + + return OK; +} + + +/* aquisition */ + +int startStateMachine(){ +#ifdef VIRTUAL + virtual_status = 1; + virtual_stop = 0; + if(pthread_create(&pthread_virtual_tid, NULL, &start_timer, NULL)) { + virtual_status = 0; + FILE_LOG(logERROR, ("Could not start Virtual acquisition thread\n")); + return FAIL; + } + FILE_LOG(logINFOGREEN, ("Virtual Acquisition started\n")); + return OK; +#endif + FILE_LOG(logINFOBLUE, ("Starting State Machine\n")); + + cleanFifos(); + + //start state machine + bus_w16(CONTROL_REG, CONTROL_STRT_ACQ_MSK); + bus_w16(CONTROL_REG, 0x0); + FILE_LOG(logINFO, ("Status Register: %08x\n", runState())); + return OK; +} + +#ifdef VIRTUAL +void* start_timer(void* arg) { + int wait_in_s = (setTimer(FRAME_NUMBER, -1) * + setTimer(CYCLES_NUMBER, -1) * + (setTimer(FRAME_PERIOD, -1)/(1E9))); + FILE_LOG(logDEBUG1, ("going to wait for %d s\n", wait_in_s)); + while(!virtual_stop && (wait_in_s >= 0)) { + usleep(1000 * 1000); + wait_in_s--; + } + FILE_LOG(logINFOGREEN, ("Virtual Timer Done\n")); + + virtual_status = 0; + return NULL; +} +#endif + +int stopStateMachine(){ + FILE_LOG(logINFORED, ("Stopping State Machine\n")); +#ifdef VIRTUAL + virtual_stop = 0; + return OK; +#endif + //stop state machine + bus_w16(CONTROL_REG, CONTROL_STP_ACQ_MSK); + usleep(100);/**FIXME:Needed? not there earlier*/ + bus_w16(CONTROL_REG, 0x0); + + // check + usleep(500); + if ((runState() & STATUS_RN_MSHN_BSY_MSK)) { + FILE_LOG(logERROR, ("\tFailed to stop state machine\n")); + return FAIL; + } + + FILE_LOG(logINFO, ("Status Register: %08x\n", runState())); + return OK; +} + +enum runStatus getRunStatus(){ +#ifdef VIRTUAL + if(virtual_status == 0){ + FILE_LOG(logINFOBLUE, ("Status: IDLE\n")); + return IDLE; + }else{ + FILE_LOG(logINFOBLUE, ("Status: RUNNING\n")); + return RUNNING; + } +#endif + FILE_LOG(logDEBUG1, ("Getting status\n")); + + enum runStatus s = IDLE; + u_int32_t retval = runState(); + FILE_LOG(logINFO, ("Status Register: %08x\n",retval)); + + // finished (external stop or fifo full) + if (retval & STATUS_RN_FNSHD_MSK) { + FILE_LOG(logINFORED, ("Status: Stopped\n")); + s = STOPPED; + + FILE_LOG(logINFO, ("\t Reading status reg again\n")); + retval = runState(); + // fifo full + if (runState() & STATUS_RN_FNSHD_MSK) { + FILE_LOG(logINFORED, ("Status: Error\n")); + s = ERROR; + } + } + + // error (fifo full) + else if (retval & STATUS_SM_FF_FLL_MSK) { + FILE_LOG(logINFORED, ("Status: Error\n")); + s = ERROR; + } + + // not running + else if (!(retval & STATUS_RN_MSHN_BSY_MSK)) { + // read last frames + if (retval & STATUS_RD_MSHN_BSY_MSK) { + FILE_LOG(logINFOBLUE, ("Status: Read Machine Busy\n")); + s = TRANSMITTING; + } + // ??? + else if (retval & STATUS_ALL_FF_EMPTY_MSK) { + FILE_LOG(logINFOBLUE, ("Status: Data in Fifo\n")); + s = TRANSMITTING; + } + // idle, unknown + else if (!(retval & STATUS_IDLE_MSK)) { + FILE_LOG(logINFOBLUE, ("Status: IDLE\n")); + s = IDLE; + } else { + FILE_LOG(logINFORED, ("Status: Unknown Status: 0x%x\n", retval)); + s = ERROR; + } + } + + // running + else { + if (retval & STATUS_WTNG_FR_TRGGR_MSK){ + FILE_LOG(logINFOBLUE, ("Status: Waiting\n")); + s = WAITING; + } + else{ + FILE_LOG(logINFOBLUE, ("Status: Running\n")); + s = RUNNING; + } + } + + return s; +} + +void readFrame(int *ret, char *mess){ +#ifdef VIRTUAL + while(virtual_status) { + //FILE_LOG(logERROR, ("Waiting for finished flag\n"); + usleep(5000); + } + return; +#endif + // wait for status to be done + while(runBusy()){ + usleep(500); + } + + // frames left to give status + int64_t retval = getTimeLeft(FRAME_NUMBER) + 1; + if ( retval > -1) { + *ret = (int)FAIL; + sprintf(mess,"No data and run stopped: %lld frames left\n",(long long int)retval); + FILE_LOG(logERROR, (mess)); + } else { + *ret = (int)OK; + FILE_LOG(logINFOGREEN, ("Acquisition successfully finished\n")); + } +} + +u_int32_t runBusy() { +#ifdef VIRTUAL + return virtual_status; +#endif + return runState() & STATUS_RN_BSY_MSK; +} + +u_int32_t runState() { +#ifdef VIRTUAL + return virtual_status; +#endif + u_int32_t s = bus_r(STATUS_REG); + FILE_LOG(logDEBUG1, ("Status Register: %08x\n", s)); + return s; +} + +/* common */ + +int calculateDataBytes(){ + return DATA_BYTES; +} + +int getTotalNumberOfChannels(){return ((int)getNumberOfChannelsPerChip() * (int)getNumberOfChips());} +int getNumberOfChips(){return NCHIP;} +int getNumberOfDACs(){return NDAC;} +int getNumberOfChannelsPerChip(){return NCHAN;} + + diff --git a/slsDetectorServers/gotthardDetectorServer/slsDetectorFunctionList.h b/slsDetectorServers/gotthardDetectorServer/slsDetectorFunctionList.h new file mode 120000 index 000000000..345b8c029 --- /dev/null +++ b/slsDetectorServers/gotthardDetectorServer/slsDetectorFunctionList.h @@ -0,0 +1 @@ +../slsDetectorServer/slsDetectorFunctionList.h \ No newline at end of file diff --git a/slsDetectorServers/gotthardDetectorServer/slsDetectorServer.c b/slsDetectorServers/gotthardDetectorServer/slsDetectorServer.c new file mode 120000 index 000000000..a7eb59acb --- /dev/null +++ b/slsDetectorServers/gotthardDetectorServer/slsDetectorServer.c @@ -0,0 +1 @@ +../slsDetectorServer/slsDetectorServer.c \ No newline at end of file diff --git a/slsDetectorServers/gotthardDetectorServer/slsDetectorServer_defs.h b/slsDetectorServers/gotthardDetectorServer/slsDetectorServer_defs.h new file mode 100644 index 000000000..002cd6515 --- /dev/null +++ b/slsDetectorServers/gotthardDetectorServer/slsDetectorServer_defs.h @@ -0,0 +1,121 @@ +#pragma once +#include "sls_detector_defs.h" //default dynamicgain in settings + +#define GOODBYE (-200) + +/* Enums */ +enum ADCINDEX {TEMP_FPGA, TEMP_ADC}; +enum DACINDEX {VREF_DS, VCASCN_PB, VCASCP_PB, VOUT_CM, VCASC_OUT, VIN_CM, VREF_COMP, IB_TESTC}; +#define DEFAULT_DAC_VALS { \ + 660, /* VREF_DS */ \ + 650, /* VCASCN_PB */ \ + 1480, /* VCASCP_PB */ \ + 1520, /* VOUT_CM */ \ + 1320, /* VCASC_OUT */ \ + 1350, /* VIN_CM */ \ + 350, /* VREF_COMP */ \ + 2001 /* IB_TESTC */ \ + }; + +/* for 25 um */ +#define CONFIG_FILE "config.txt" + +/* Hardware Definitions */ +#define NCHAN (128) +#define NCHIP (10) +#define NDAC (8) +#define NCHIPS_PER_ADC (2) +#define DYNAMIC_RANGE (16) +#define NUM_BITS_PER_PIXEL (DYNAMIC_RANGE / 8) +#define DATA_BYTES (NCHIP * NCHAN * NUM_BITS_PER_PIXEL) +#define CLK_FREQ (32.007729) /* MHz */ + +/** Firmware Definitions */ +#define IP_PACKET_SIZE_NO_ROI (NCHIP * (NCHAN / 2) * 2 + 14 + 20) // 2 packets, so divide by 2 +#define IP_PACKET_SIZE_ROI (NCHIPS_PER_ADC * NCHAN * 2 + 14 + 20) + +#define UDP_PACKETSIZE_NO_ROI (NCHIP * (NCHAN / 2) * 2 + 4 + 8 + 2) // 2 packets, so divide by 2 +#define UDP_PACKETSIZE_ROI (NCHIPS_PER_ADC * NCHAN * 2 + 4 + 8 + 2) + +/** Default Parameters */ +#define DEFAULT_NUM_FRAMES (1) +#define DEFAULT_NUM_CYCLES (1) +#define DEFAULT_EXPTIME (1 * 1000 * 1000) // 1 ms +#define DEFAULT_PERIOD (1 * 1000 * 1000 * 1000) // 1 s +#define DEFAULT_DELAY (0) +#define DEFAULT_SETTINGS (DYNAMICGAIN) +#define DEFAULT_TIMING_MODE (AUTO_TIMING) +#define DEFAULT_TRIGGER_MODE (TRIGGER_IN_RISING_EDGE) +#define DEFAULT_HIGH_VOLTAGE (0) +#define DEFAULT_PHASE_SHIFT (120) +#define DEFAULT_TX_UDP_PORT (0xE185) + +/** ENEt conf structs */ +typedef struct mac_header_struct{ + u_int8_t mac_dest_mac2; + u_int8_t mac_dest_mac1; + u_int8_t mac_dummy1; + u_int8_t mac_dummy2; + u_int8_t mac_dest_mac6; + u_int8_t mac_dest_mac5; + u_int8_t mac_dest_mac4; + u_int8_t mac_dest_mac3; + u_int8_t mac_src_mac4; + u_int8_t mac_src_mac3; + u_int8_t mac_src_mac2; + u_int8_t mac_src_mac1; + u_int16_t mac_ether_type; + u_int8_t mac_src_mac6; + u_int8_t mac_src_mac5; +} mac_header; + +typedef struct ip_header_struct { + u_int16_t ip_len; + u_int8_t ip_tos; + u_int8_t ip_ihl:4 ,ip_ver:4; + u_int16_t ip_offset:13,ip_flag:3; + u_int16_t ip_ident; + u_int16_t ip_chksum; + u_int8_t ip_protocol; + u_int8_t ip_ttl; + u_int32_t ip_sourceip; + u_int32_t ip_destip; +} ip_header; + +typedef struct udp_header_struct{ + u_int16_t udp_destport; + u_int16_t udp_srcport; + u_int16_t udp_chksum; + u_int16_t udp_len; +} udp_header; + +typedef struct mac_conf_struct{ + mac_header mac; + ip_header ip; + udp_header udp; + u_int32_t npack; + u_int32_t lpack; + u_int32_t npad; + u_int32_t cdone; +} mac_conf; + +typedef struct tse_conf_struct{ + u_int32_t rev; //0x0 + u_int32_t scratch; + u_int32_t command_config; + u_int32_t mac_0; //0x3 + u_int32_t mac_1; + u_int32_t frm_length; + u_int32_t pause_quant; + u_int32_t rx_section_empty; //0x7 + u_int32_t rx_section_full; + u_int32_t tx_section_empty; + u_int32_t tx_section_full; + u_int32_t rx_almost_empty; //0xB + u_int32_t rx_almost_full; + u_int32_t tx_almost_empty; + u_int32_t tx_almost_full; + u_int32_t mdio_addr0; //0xF + u_int32_t mdio_addr1; +}tse_conf; + diff --git a/slsDetectorServers/gotthardDetectorServer/slsDetectorServer_funcs.c b/slsDetectorServers/gotthardDetectorServer/slsDetectorServer_funcs.c new file mode 120000 index 000000000..a7532ccd4 --- /dev/null +++ b/slsDetectorServers/gotthardDetectorServer/slsDetectorServer_funcs.c @@ -0,0 +1 @@ +../slsDetectorServer/slsDetectorServer_funcs.c \ No newline at end of file diff --git a/slsDetectorServers/gotthardDetectorServer/slsDetectorServer_funcs.h b/slsDetectorServers/gotthardDetectorServer/slsDetectorServer_funcs.h new file mode 120000 index 000000000..7569daf47 --- /dev/null +++ b/slsDetectorServers/gotthardDetectorServer/slsDetectorServer_funcs.h @@ -0,0 +1 @@ +../slsDetectorServer/slsDetectorServer_funcs.h \ No newline at end of file diff --git a/slsDetectorServers/gotthardDetectorServer/stop_server.c b/slsDetectorServers/gotthardDetectorServer/stop_server.c deleted file mode 100755 index e3c8ff7e1..000000000 --- a/slsDetectorServers/gotthardDetectorServer/stop_server.c +++ /dev/null @@ -1,46 +0,0 @@ -/* A simple server in the internet domain using TCP - The port number is passed as an argument */ - - -#include "sls_detector_defs.h" - - -#include "communication_funcs.h" -#include "firmware_funcs.h" - - -int sockfd; - -int main(int argc, char *argv[]) -{ - int portno; - int retval=0; - - portno = DEFAULT_PORTNO; - - - bindSocket(portno); - if (getServerError()) - return -1; - - - - /* waits for connection */ - while(retval!=GOODBYE) { -#ifdef VERBOSE - printf("\n"); -#endif -#ifdef VERY_VERBOSE - printf("Stop server: waiting for client call\n"); -#endif - acceptConnection(); - retval=stopStateMachine(); - closeConnection(); - } - - exitServer(); - printf("Goodbye!\n"); - - return 0; -} - diff --git a/slsDetectorServers/jungfrauDetectorServer/Makefile b/slsDetectorServers/jungfrauDetectorServer/Makefile index c887965e5..850cbf826 100755 --- a/slsDetectorServers/jungfrauDetectorServer/Makefile +++ b/slsDetectorServers/jungfrauDetectorServer/Makefile @@ -25,7 +25,7 @@ $(PROGS): $(OBJS) rm *.gdb clean: - rm -rf $(DESTDIR)/$(PROGS) *.o + rm -rf $(DESTDIR)/$(PROGS) *.o *.gdb \ No newline at end of file diff --git a/slsDetectorServers/jungfrauDetectorServer/slsDetectorFunctionList.c b/slsDetectorServers/jungfrauDetectorServer/slsDetectorFunctionList.c index 978660497..a03d5ae16 100644 --- a/slsDetectorServers/jungfrauDetectorServer/slsDetectorFunctionList.c +++ b/slsDetectorServers/jungfrauDetectorServer/slsDetectorFunctionList.c @@ -14,23 +14,20 @@ #include #endif -// Global variable from slsDetectorServer +// Global variable from slsDetectorServer_funcs extern int debugflag; int firmware_compatibility = OK; int firmware_check_done = 0; char firmware_message[MAX_STR_LENGTH]; -sls_detector_module *detectorModules = NULL; -int *detectorDacs = NULL; - #ifdef VIRTUAL pthread_t pthread_virtual_tid; int virtual_status = 0; int virtual_stop = 0; #endif -enum detectorSettings thisSettings; +enum detectorSettings thisSettings = UNINITIALIZED; int highvoltage = 0; int dacValues[NDAC] = {0}; int32_t clkPhase[2] = {0, 0}; @@ -45,7 +42,7 @@ int getFirmwareCheckResult(char** mess) { return firmware_compatibility; } -void checkFirmwareCompatibility() { +void basictests() { firmware_compatibility = OK; firmware_check_done = 0; memset(firmware_message, 0, MAX_STR_LENGTH); @@ -242,7 +239,7 @@ int detectorTest( enum digitalTestMode arg){ //DETECTOR_MEMORY_TEST:testRAM //DETECTOR_SOFTWARE_TEST: default: - FILE_LOG(logERROR, ("Test not implemented for this detector %d\n", (int)arg)); + FILE_LOG(logERROR, ("Test %s not implemented for this detector\n", (int)arg)); break; } return OK; @@ -387,39 +384,11 @@ void initStopServer() { /* set up detector */ -void allocateDetectorStructureMemory(){ - FILE_LOG(logINFO, ("This Server is for 1 Jungfrau module (500k)\n")); - - //Allocation of memory - if (detectorModules != NULL) free(detectorModules); - if (detectorDacs != NULL) free(detectorDacs); - detectorModules = malloc(sizeof(sls_detector_module)); - detectorDacs = malloc(NDAC*sizeof(int)); - FILE_LOG(logDEBUG1, ("modules from 0x%x to 0x%x\n",detectorModules, detectorModules)); - FILE_LOG(logDEBUG1, ("dacs from 0x%x to 0x%x\n",detectorDacs, detectorDacs)); - (detectorModules)->dacs = detectorDacs; - (detectorModules)->ndac = NDAC; - (detectorModules)->nchip = NCHIP; - (detectorModules)->nchan = NCHIP * NCHAN; - (detectorModules)->reg = 0; - (detectorModules)->iodelay = 0; - (detectorModules)->tau = 0; - (detectorModules)->eV = 0; - thisSettings = UNINITIALIZED; - - { // initialize to -1 - int i = 0; - for (i = 0; i < NDAC; ++i) { - dacValues[i] = -1; - } - } -} void setupDetector() { - - allocateDetectorStructureMemory(); + FILE_LOG(logINFO, ("This Server is for 1 Jungfrau module (500k)\n")); resetPLL(); resetCore(); @@ -797,12 +766,12 @@ int64_t getTimeLeft(enum timerIndex ind){ break; case ACTUAL_TIME: - retval = get64BitReg(TIME_FROM_START_LSB_REG, TIME_FROM_START_MSB_REG) / (1E-9 * CLK_SYNC); + retval = get64BitReg(TIME_FROM_START_LSB_REG, TIME_FROM_START_MSB_REG) / (1E-3 * CLK_SYNC); FILE_LOG(logINFO, ("Getting actual time (time from start): %lld\n", (long long int)retval)); break; case MEASUREMENT_TIME: - retval = get64BitReg(START_FRAME_TIME_LSB_REG, START_FRAME_TIME_MSB_REG) / (1E-9 * CLK_SYNC); + retval = get64BitReg(START_FRAME_TIME_LSB_REG, START_FRAME_TIME_MSB_REG) / (1E-3 * CLK_SYNC); FILE_LOG(logINFO, ("Getting measurement time (timestamp/ start frame time): %lld\n", (long long int)retval)); break; @@ -835,19 +804,10 @@ int setModule(sls_detector_module myMod, char* mess){ // settings setSettings( (enum detectorSettings)myMod.reg); - //copy module locally - if (detectorModules) { - if (copyModule(detectorModules, &myMod) == FAIL) { - sprintf(mess, "Could not copy module\n"); - FILE_LOG(logERROR, (mess)); - return FAIL; - } - } - //set dac values { int i = 0, retval[2] = {-1, -1}; - for(i = 0; i < myMod.ndac; ++i) + for(i = 0; i < NDAC; ++i) setDAC((enum DACINDEX)i, myMod.dacs[i], 0, retval); } return OK; @@ -855,19 +815,20 @@ int setModule(sls_detector_module myMod, char* mess){ int getModule(sls_detector_module *myMod){ - int i; - int retval[2]; - - //dacs - for(i=0;i= 0) + *((myMod->dacs) + idac) = dacValues[idac]; + } + // check if all of them are not initialized + int initialized = 0; + for (idac = 0; idac < NDAC; ++idac) { + if (dacValues[idac] >= 0) + initialized = 1; + } + if (initialized) + return OK; + return FAIL; } @@ -1028,22 +989,25 @@ int dacToVoltage(unsigned int digital){ void setDAC(enum DACINDEX ind, int val, int mV, int retval[]){ - int dacval = val; + int dacmV = val; - //if set and mv, convert to dac - if (val > 0 && mV) { - val = voltageToDac(val); //gives -1 on error - } + //if set and mv, convert to dac + if (val > 0) { + if (mV) + val = voltageToDac(val); //gives -1 on error + else + dacmV = dacToVoltage(val); //gives -1 on error + } if ( (val >= 0) || (val == -100)) { #ifdef VIRTUAL - dacValues[ind] = dacval; + dacValues[ind] = val; #else u_int32_t codata; int csdx = ind / NDAC + DAC_SERIAL_CS_OUT_OFST; // old board (16 dacs),so can be DAC_SERIAL_CS_OUT_OFST or +1 int dacchannel = ind % NDAC; // 0-8, dac channel number (also for dacnum 9-15 in old board) - FILE_LOG(logINFO, ("Setting DAC %d: %d dac (%d mV)\n",ind, dacval, val)); + FILE_LOG(logINFO, ("Setting DAC %d: %d dac (%d mV)\n",ind, val, dacmV)); // command if (val >= 0) { FILE_LOG(logDEBUG1,("\tWrite to Input Register and Update\n")); @@ -1064,7 +1028,7 @@ void setDAC(enum DACINDEX ind, int val, int mV, int retval[]){ serializeToSPI(SPI_REG, codata, (0x1 << csdx), LTC2620_DAC_NUMBITS, DAC_SERIAL_CLK_OUT_MSK, DAC_SERIAL_DIGITAL_OUT_MSK, DAC_SERIAL_DIGITAL_OUT_OFST); - dacValues[ind] = dacval; + dacValues[ind] = val; if (ind == VREF_COMP) { bus_w (VREF_COMP_MOD_REG, (bus_r(VREF_COMP_MOD_REG) &~ (VREF_COMP_MOD_MSK)) // reset @@ -1177,12 +1141,7 @@ enum externalCommunicationMode getTiming() { long int calcChecksum(int sourceip, int destip) { - ip_header ip; - int count; - unsigned short *addr; - long int sum = 0; - long int checksum; ip.ip_ver = 0x4; ip.ip_ihl = 0x5; ip.ip_tos = 0x0; @@ -1196,18 +1155,22 @@ long int calcChecksum(int sourceip, int destip) { ip.ip_sourceip = sourceip; ip.ip_destip = destip; - count = sizeof(ip); - addr = (unsigned short*) &(ip); /* warning: assignment from incompatible pointer type */ - while( count > 1 ) { + int count = sizeof(ip); + + unsigned short *addr; + addr = (unsigned short*) &(ip); /* warning: assignment from incompatible pointer type */ + + long int sum = 0; + while( count > 1 ) { sum += *addr++; count -= 2; } - if (count > 0) sum += *addr; // Add left-over byte, if any - while (sum>>16) sum = (sum & 0xffff) + (sum >> 16);// Fold 32-bit sum to 16 bits - checksum = (~sum) & 0xffff; - + if (count > 0) + sum += *addr; // Add left-over byte, if any + while (sum>>16) + sum = (sum & 0xffff) + (sum >> 16);// Fold 32-bit sum to 16 bits + long int checksum = (~sum) & 0xffff; FILE_LOG(logINFO, ("IP checksum is 0x%lx\n",checksum)); - return checksum; } @@ -1215,7 +1178,7 @@ long int calcChecksum(int sourceip, int destip) { int configureMAC(uint32_t destip, uint64_t destmac, uint64_t sourcemac, uint32_t sourceip, uint32_t udpport, uint32_t udpport2){ #ifdef VIRTUAL - return 0; + return OK; #endif FILE_LOG(logINFOBLUE, ("Configuring MAC\n")); uint32_t sourceport = DEFAULT_TX_UDP_PORT; @@ -1277,7 +1240,7 @@ int configureMAC(uint32_t destip, uint64_t destmac, uint64_t sourcemac, uint32_t resetCore(); usleep(500 * 1000); /* todo maybe without */ - return 0; + return OK; } @@ -1602,11 +1565,11 @@ void readFrame(int *ret, char *mess){ -u_int32_t runBusy(void) { +u_int32_t runBusy() { #ifdef VIRTUAL return virtual_status; #endif - u_int32_t s = ((bus_r(STATUS_REG) & RUN_BUSY_MSK) >> RUN_BUSY_OFST); + u_int32_t s = (bus_r(STATUS_REG) & RUN_BUSY_MSK); FILE_LOG(logDEBUG1, ("Status Register: %08x\n", s)); return s; } @@ -1620,45 +1583,6 @@ u_int32_t runBusy(void) { /* common */ -//jungfrau doesnt require chips and chans (save memory) -int copyModule(sls_detector_module *destMod, sls_detector_module *srcMod){ - - int idac; - int ret=OK; - - FILE_LOG(logDEBUG1, ("Copying module\n")); - - if (srcMod->serialnumber>=0){ - destMod->serialnumber=srcMod->serialnumber; - } - if ((srcMod->nchip)>(destMod->nchip)) { - FILE_LOG(logERROR, ("Number of chip of source is larger than number of chips of destination\n")); - return FAIL; - } - if ((srcMod->nchan)>(destMod->nchan)) { - FILE_LOG(logERROR, ("Number of channels of source is larger than number of channels of destination\n")); - return FAIL; - } - if ((srcMod->ndac)>(destMod->ndac)) { - FILE_LOG(logERROR, ("Number of dacs of source is larger than number of dacs of destination\n")); - return FAIL; - } - FILE_LOG(logDEBUG1, ("DACs: src %d, dest %d\n",srcMod->ndac,destMod->ndac)); - FILE_LOG(logDEBUG1, ("Chips: src %d, dest %d\n",srcMod->nchip,destMod->nchip)); - FILE_LOG(logDEBUG1, ("Chans: src %d, dest %d\n",srcMod->nchan,destMod->nchan)); - - if (srcMod->reg>=0) - destMod->reg=srcMod->reg; - FILE_LOG(logDEBUG1, ("Copying register %x (%x)\n",destMod->reg,srcMod->reg )); - - for (idac=0; idac<(srcMod->ndac); idac++) { - if (*((srcMod->dacs)+idac)>=0) - *((destMod->dacs)+idac)=*((srcMod->dacs)+idac); - } - return ret; -} - - int calculateDataBytes(){ return DATA_BYTES; } diff --git a/slsDetectorServers/jungfrauDetectorServer/slsDetectorServer_defs.h b/slsDetectorServers/jungfrauDetectorServer/slsDetectorServer_defs.h index d897cbc42..7f3fe3893 100644 --- a/slsDetectorServers/jungfrauDetectorServer/slsDetectorServer_defs.h +++ b/slsDetectorServers/jungfrauDetectorServer/slsDetectorServer_defs.h @@ -38,11 +38,8 @@ enum DACINDEX {VB_COMP, VDD_PROT, VIN_COM, VREF_PRECH, VB_PIXBUF, VB_DS, VREF 480, /* VREF_DS */ \ 420 /* VREF_COMP */ \ }; - enum NETWORKINDEX { TXN_FRAME }; - - /* Hardware Definitions */ #define NCHAN (256 * 256) #define NCHIP (8) @@ -55,7 +52,6 @@ enum NETWORKINDEX { TXN_FRAME }; #define CLK_RUN (40) /* MHz */ #define CLK_SYNC (20) /* MHz */ - /** Default Parameters */ #define DEFAULT_NUM_FRAMES (100*1000*1000) #define DEFAULT_NUM_CYCLES (1) @@ -78,7 +74,6 @@ enum NETWORKINDEX { TXN_FRAME }; #define MAX_STORAGE_CELL_VAL (15) //0xF #define ACQ_TIME_MIN_CLOCK (2) - #define SAMPLE_ADC_HALF_SPEED (SAMPLE_DECMT_FACTOR_2_VAL + SAMPLE_DGTL_SAMPLE_0_VAL + SAMPLE_ADC_DECMT_FACTOR_0_VAL + SAMPLE_ADC_SAMPLE_0_VAL) /* 0x1000 */ #define SAMPLE_ADC_QUARTER_SPEED (SAMPLE_DECMT_FACTOR_4_VAL + SAMPLE_DGTL_SAMPLE_8_VAL + SAMPLE_ADC_DECMT_FACTOR_1_VAL + SAMPLE_ADC_SAMPLE_0_VAL) /* 0x2810 */ #define CONFIG_HALF_SPEED (CONFIG_TDMA_DISABLE_VAL + CONFIG_HALF_SPEED_20MHZ_VAL + CONFIG_MODE_1_X_10GBE_VAL) @@ -89,15 +84,6 @@ enum NETWORKINDEX { TXN_FRAME }; #define ADC_PHASE_QUARTER_SPEED (0x2D) //45 #define ADC_PORT_INVERT_VAL (0x453b2a9c) -/* Maybe not required for jungfrau */ -#define NTRIMBITS (6) -#define NCOUNTBITS (24) -#define NCHIPS_PER_ADC (2) -#define TRIM_DR (((int)pow(2,NTRIMBITS))-1) -#define COUNT_DR (((int)pow(2,NCOUNTBITS))-1) -#define ALLMOD (0xffff) -#define ALLFIFO (0xffff) - /* MSB & LSB DEFINES */ #define MSB_OF_64_BIT_REG_OFST (32) #define LSB_OF_64_BIT_REG_OFST (0) @@ -116,14 +102,11 @@ enum NETWORKINDEX { TXN_FRAME }; #define LTC2620_DAC_CMD_POWER_DOWN (0x00000004 << LTC2620_DAC_CMD_OFST) #define LTC2620_DAC_NUMBITS (24) - /* MAX1932 HV DEFINES */ #define MAX1932_HV_NUMBITS (8) #define MAX1932_HV_DATA_OFST (0) #define MAX1932_HV_DATA_MSK (0x000000FF << MAX1932_HV_DATA_OFST) - - /** PLL Reconfiguration Registers */ //https://www.altera.com/documentation/mcn1424769382940.html #define PLL_MODE_REG (0x00) diff --git a/slsDetectorServers/slsDetectorServer/AD9257.h b/slsDetectorServers/slsDetectorServer/AD9257.h index 615fdb3c0..9b86a60a7 100755 --- a/slsDetectorServers/slsDetectorServer/AD9257.h +++ b/slsDetectorServers/slsDetectorServer/AD9257.h @@ -1,5 +1,4 @@ -#ifndef AD9257_H -#define AD9257_H +#pragma once #include "commonServerFunctions.h" // blackfin.h, ansi.h @@ -90,12 +89,24 @@ void prepareADC(){ FILE_LOG(logINFO, ("\tPower mode reset\n")); setAdc(AD9257_POWER_MODE_REG, (AD9257_INT_RESET_VAL << AD9257_POWER_INTERNAL_OFST) & AD9257_POWER_INTERNAL_MSK); +#ifdef GOTTHARDD + usleep(50000); +#endif //power mode chip run FILE_LOG(logINFO, ("\tPower mode chip run\n")); setAdc(AD9257_POWER_MODE_REG, (AD9257_INT_CHIP_RUN_VAL << AD9257_POWER_INTERNAL_OFST) & AD9257_POWER_INTERNAL_MSK); +#ifdef GOTTHARDD + usleep(50000); + // binary offset + FILE_LOG(logINFO, ("\tBinary offset\n")); + setAdc(AD9257_OUT_MODE_REG, + (AD9257_OUT_BINARY_OFST_VAL << AD9257_OUT_FORMAT_OFST) & AD9257_OUT_FORMAT_MSK); + usleep(50000); + return; +#endif //output clock phase FILE_LOG(logINFO, ("\tOutput clock phase\n")); setAdc(AD9257_OUT_PHASE_REG, @@ -132,5 +143,3 @@ void prepareADC(){ (AD9257_MIXED_BIT_FREQ_VAL << AD9257_OUT_TEST_OFST) & AD9257_OUT_TEST_MSK); #endif } - -#endif //AD9257_H diff --git a/slsDetectorServers/slsDetectorServer/commonServerFunctions.h b/slsDetectorServers/slsDetectorServer/commonServerFunctions.h index 67651e487..cf62d90af 100755 --- a/slsDetectorServers/slsDetectorServer/commonServerFunctions.h +++ b/slsDetectorServers/slsDetectorServer/commonServerFunctions.h @@ -1,13 +1,6 @@ -#ifndef COMMON_SERVER_FUNCTIONS_H -#define COMMON_SERVER_FUNCTIONS_H +#pragma once -#ifndef GOTTHARDD //gotthard already had bus_w etc defined in its firmware_funcs.c (not yet made with common files) #include "blackfin.h" -#else -#include "ansi.h" -#endif - -/* global variables */ void SPIChipSelect (u_int32_t* valw, u_int32_t addr, u_int32_t csmask) { @@ -69,5 +62,3 @@ void serializeToSPI(u_int32_t addr, u_int32_t val, u_int32_t csmask, int numbits SPIChipDeselect(&valw, addr, csmask, clkmask); } - -#endif //COMMON_SERVER_FUNCTIONS_H diff --git a/slsDetectorServers/slsDetectorServer/slsDetectorFunctionList.h b/slsDetectorServers/slsDetectorServer/slsDetectorFunctionList.h index d161a7877..34bce6973 100644 --- a/slsDetectorServers/slsDetectorServer/slsDetectorFunctionList.h +++ b/slsDetectorServers/slsDetectorServer/slsDetectorFunctionList.h @@ -13,20 +13,21 @@ Here are the definitions, but the actual implementation should be done for each // basic tests -#if defined(EIGERD) || defined(JUNGFRAUD) || defined(GOTTHARD) +#if defined(EIGERD) || defined(JUNGFRAUD) || defined(GOTTHARDD) int isFirmwareCheckDone(); int getFirmwareCheckResult(char** mess); #endif - -void checkFirmwareCompatibility(); +void basictests(); #ifdef JUNGFRAUD int checkType(); u_int32_t testFpga(void); int testBus(void); #endif -#ifdef JUNGFRAUD -int detectorTest( enum digitalTestMode arg); +#ifdef GOTTHARDD +int detectorTest(enum digitalTestMode arg, int ival); +#elif JUNGFRAUD +int detectorTest(enum digitalTestMode arg); #endif // Ids @@ -40,6 +41,9 @@ u_int16_t getHardwareSerialNumber(); u_int32_t getDetectorNumber(); u_int64_t getDetectorMAC(); u_int32_t getDetectorIP(); +#ifdef GOTTHARDD +u_int32_t getBoardRevision(); +#endif // initialization @@ -50,9 +54,11 @@ void getModuleConfiguration(); #endif // set up detector +#ifdef EIGERD void allocateDetectorStructureMemory(); +#endif void setupDetector(); -#ifdef JUNGFRAUD +#if defined(GOTTHARDD) || defined(JUNGFRAUD) int setDefaultDacs(); #endif @@ -61,9 +67,12 @@ int setDefaultDacs(); #ifndef EIGERD extern u_int32_t writeRegister(u_int32_t offset, u_int32_t data); // blackfin.h extern u_int32_t readRegister(u_int32_t offset); // blackfin.h -#else +#elif JUNGFRAUD uint32_t writeRegister(uint32_t offset, uint32_t data); uint32_t readRegister(uint32_t offset); +#else +uint32_t writeRegister16And32(uint32_t offset, uint32_t data); +uint32_t readRegister16And32(uint32_t offset); #endif @@ -77,16 +86,29 @@ int autoCompDisable(int on); int adcPhase(int st); int getPhase(); void configureASICTimer(); +#elif GOTTHARDD +void setPhaseShiftOnce(); +void setPhaseShift(int numphaseshift); +void cleanFifos(); +void setADCSyncRegister(); +void setDAQRegister(); +void setChipOfInterestRegister(int adc); +void setROIADC(int adc); +void setGbitReadout(); +int readConfigFile(); +void setMasterSlaveConfiguration(); #endif // parameters - dr, roi int setDynamicRange(int dr); #ifdef GOTTHARD -int setROI(int n, ROI arg[], int *retvalsize, int *ret); +ROI* setROI(int n, ROI arg[], int *retvalsize, int *ret); #endif // parameters - readout +#ifndef GOTTHARDD enum speedVariable setSpeed(int val); +#endif #ifdef EIGERD enum readOutFlags setReadOutFlags(enum readOutFlags val); #endif @@ -114,17 +136,23 @@ int setThresholdEnergy(int ev); // parameters - dac, adc, hv #ifdef JUNGFRAUD -void serializeToSPI(u_int32_t addr, u_int32_t val, u_int32_t csmask, int numbitstosend, u_int32_t clkmask, u_int32_t digoutmask, int digofset); +void serializeToSPI(u_int32_t addr, u_int32_t val, u_int32_t csmask, int numbitstosend, u_int32_t clkmask, u_int32_t digoutmask, int digofset); //commonServerFunction.h void initDac(int dacnum); +#endif +#if defined(GOTTHARDD) || defined(JUNGFRAUD) int voltageToDac(int value); int dacToVoltage(unsigned int digital); -#endif - -#ifdef JUNGFRAUD extern void setAdc(int addr, int val); // AD9257.h #endif void setDAC(enum DACINDEX ind, int val, int mV, int retval[]); +#ifdef GOTTHARDD +void initDAC(int dac_addr, int value); +void clearDACSregister(); +void nextDAC(); +void program_one_dac(int addr, int value); +u_int32_t putout(char *s); +#endif int getADC(enum ADCINDEX ind); int setHighVoltage(int val); @@ -134,16 +162,21 @@ int setHighVoltage(int val); // parameters - timing, extsig void setTiming( enum externalCommunicationMode arg); enum externalCommunicationMode getTiming(); +#ifdef GOTTHARDD +void setExtSignal(enum externalSignalFlag mode); +int getExtSignal(); +#endif // configure mac -#ifdef JUNGFRAUD +#ifdef GOTTHARDD +void calcChecksum(mac_conf* mac, int sourceip, int destip); +#elif JUNGFRAUD long int calcChecksum(int sourceip, int destip); #endif #ifdef GOTTHARDD -int configureMAC(uint32_t destip, uint64_t destmac, uint64_t sourcemac, uint32_t sourceip, uint32_t udpport, uint32_t udpport2, int ival); -#else -int configureMAC(uint32_t destip, uint64_t destmac, uint64_t sourcemac, uint32_t sourceip, uint32_t udpport, uint32_t udpport2); +int getAdcConfigured(); #endif +int configureMAC(uint32_t destip, uint64_t destmac, uint64_t sourcemac, uint32_t sourceip, uint32_t udpport, uint32_t udpport2); #if defined(JUNGFRAUD) || defined(EIGERD) int setDetectorPosition(int pos[]); #endif @@ -153,10 +186,9 @@ int setDetectorPosition(int pos[]); // gotthard specific - image, pedestal #ifdef GOTTHARDD -int loadImage(enum imageType index, char *imageVals); +void loadImage(enum imageType index, short int imageVals[]); int readCounterBlock(int startACQ, char *counterVals); int resetCounterBlock(int startACQ); -int calibratePedestal(int frames); // jungfrau specific - pll, flashing firmware #elif JUNGFRAUD @@ -198,7 +230,7 @@ int setNetworkParameter(enum NETWORKINDEX mode, int value); // aquisition -#if defined(EIGERD) || defined(GOTTHARD) +#ifdef EIGERD int prepareAcquisition(); #endif int startStateMachine(); @@ -209,18 +241,23 @@ int stopStateMachine(); #ifdef EIGERD int softwareTrigger(); #endif -#ifndef JUNGFRAUD +#ifdef EIGERD int startReadOut(); #endif enum runStatus getRunStatus(); void readFrame(int *ret, char *mess); -#ifdef JUNGFRAUD -u_int32_t runBusy(void); +#if defined(GOTTHARDD) || defined(JUNGFRAUD) +u_int32_t runBusy(); +#endif +#ifdef GOTTHARDD +u_int32_t runState(); #endif //common +#ifdef EIGERD int copyModule(sls_detector_module *destMod, sls_detector_module *srcMod); +#endif int calculateDataBytes(); int getTotalNumberOfChannels(); int getNumberOfChips(); diff --git a/slsDetectorServers/slsDetectorServer/slsDetectorServer.c b/slsDetectorServers/slsDetectorServer/slsDetectorServer.c index 9758aee4e..365c35069 100755 --- a/slsDetectorServers/slsDetectorServer/slsDetectorServer.c +++ b/slsDetectorServers/slsDetectorServer/slsDetectorServer.c @@ -19,6 +19,11 @@ extern int ret; extern int sockfd; extern int debugflag; +// Global variables from slsDetectorFunctionList +#ifdef GOTTHARDD +extern int phaseShift; +#endif + void error(char *msg){ perror(msg); } @@ -41,10 +46,23 @@ int main(int argc, char *argv[]){ FILE_LOG(logINFO, ("Detected stop server\n")); isControlServer = 0; } - else if(!strcasecmp(argv[i],"-devel")){ - FILE_LOG(logINFO, ("Detected developer mode\n")); - debugflag = 1; + else if(!strcasecmp(argv[i],"-devel")){ + FILE_LOG(logINFO, ("Detected developer mode\n")); + debugflag = DEVELOPER_MODE; + } +#ifdef GOTTHARDD + else if(!strcasecmp(argv[i],"-phaseshift")){ + if ((i + 1) >= argc) { + FILE_LOG(logERROR, ("no phase shift value given. Exiting.\n")); + return -1; + } + if (sscanf(argv[i + 1], "%d", &phaseShift) == 0) { + FILE_LOG(logERROR, ("cannot decode phase shift value %s. Exiting.\n", argv[i + 1])); + return -1; + } + FILE_LOG(logINFO, ("Detected phase shift of %d\n", phaseShift)); } +#endif #ifdef JUNGFRAUD else if(!strcasecmp(argv[i],"-update")){ FILE_LOG(logINFO, ("Detected update mode\n")); diff --git a/slsDetectorServers/slsDetectorServer/slsDetectorServer_funcs.c b/slsDetectorServers/slsDetectorServer/slsDetectorServer_funcs.c index 45196226f..8e91f935d 100755 --- a/slsDetectorServers/slsDetectorServer/slsDetectorServer_funcs.c +++ b/slsDetectorServers/slsDetectorServer/slsDetectorServer_funcs.c @@ -34,15 +34,12 @@ int debugflag = 0; // Local variables int (*flist[NUM_DET_FUNCTIONS])(int); -int dataBytes = 10; #ifdef EIGERD uint32_t dhcpipad = 0; #endif -#ifdef GOTTHARDD -int digitalTestBit = 0; -#endif - +enum numberMode {DEC, HEX}; +enum updateRet {NO_UPDATE, UPDATE}; /* initialization functions */ @@ -52,11 +49,6 @@ int printSocketReadError() { } -void basictests() { - checkFirmwareCompatibility(); -} - - void init_detector() { #ifdef VIRTUAL FILE_LOG(logINFO, ("This is a VIRTUAL detector\n")); @@ -271,10 +263,10 @@ void modeNotImplemented(char* modename, int mode) { FILE_LOG(logERROR,(mess)); } -void validate(int arg, int retval, char* modename, int hex) { +void validate(int arg, int retval, char* modename, enum numberMode nummode) { if (ret == OK && arg != -1 && retval != arg) { ret = FAIL; - if (hex) + if (nummode == HEX) sprintf(mess, "Could not %s. Set 0x%x, but read 0x%x\n", modename, arg, retval); else @@ -284,10 +276,10 @@ void validate(int arg, int retval, char* modename, int hex) { } } -void validate64(int64_t arg, int64_t retval, char* modename, int hex) { +void validate64(int64_t arg, int64_t retval, char* modename, enum numberMode nummode) { if (ret == OK && arg != -1 && retval != arg) { ret = FAIL; - if (hex) + if (nummode == HEX) sprintf(mess, "Could not %s. Set 0x%llx, but read 0x%llx\n", modename, (long long unsigned int)arg, (long long unsigned int)retval); else @@ -309,7 +301,7 @@ int M_nofunc(int file_des) { sprintf(mess,"Unrecognized Function enum %d. Please do not proceed.\n", fnum); FILE_LOG(logERROR, (mess)); - return Server_SendResult(file_des, OTHER, 0, NULL, 0); + return Server_SendResult(file_des, OTHER, NO_UPDATE, NULL, 0); } @@ -328,7 +320,7 @@ int M_nofuncMode(int file_des) { "Restart detector server in normal mode (without any arguments) to continue.\n", getFunctionName((enum detFuncs)fnum)); FILE_LOG(logERROR, (mess)); - return Server_SendResult(file_des, OTHER, 0, NULL, 0); + return Server_SendResult(file_des, OTHER, NO_UPDATE, NULL, 0); } @@ -364,7 +356,7 @@ int exec_command(int file_des) { pclose(sysFile); FILE_LOG(logINFO, ("Result of cmd (%s):\n%s\n", cmd, retval)); } - return Server_SendResult(file_des, OTHER, 0, retval, sizeof(retval)); + return Server_SendResult(file_des, OTHER, NO_UPDATE, retval, sizeof(retval)); } @@ -375,7 +367,7 @@ int get_detector_type(int file_des) { memset(mess, 0, sizeof(mess)); enum detectorType retval = myDetectorType; FILE_LOG(logDEBUG1,("Returning detector type %d\n", retval)); - return Server_SendResult(file_des, INT32, 1, &retval, sizeof(retval)); + return Server_SendResult(file_des, INT32, UPDATE, &retval, sizeof(retval)); } @@ -404,11 +396,11 @@ int set_external_signal_flag(int file_des) { } // get retval = getExtSignal(signalindex); - validate((int)flag, (int)retval, "set external signal flag", 1); + validate((int)flag, (int)retval, "set external signal flag", DEC); FILE_LOG(logDEBUG1, ("External Signal Flag: %d\n", retval)); } #endif - return Server_SendResult(file_des, INT32, 1, &retval, sizeof(retval)); + return Server_SendResult(file_des, INT32, UPDATE, &retval, sizeof(retval)); } @@ -442,9 +434,9 @@ int set_external_communication_mode(int file_des) { } // get retval = getTiming(); - validate((int)arg, (int)retval, "set timing mode", 0); + validate((int)arg, (int)retval, "set timing mode", DEC); FILE_LOG(logDEBUG1, ("Timing Mode: %d\n",retval)); - return Server_SendResult(file_des, INT32, 1, &retval, sizeof(retval)); + return Server_SendResult(file_des, INT32, UPDATE, &retval, sizeof(retval)); } @@ -464,8 +456,8 @@ int get_id(int file_des) { switch (arg) { #if defined(EIGERD) || defined(JUNGFRAUD) case SOFTWARE_FIRMWARE_API_VERSION: -#endif case DETECTOR_SERIAL_NUMBER: +#endif case DETECTOR_FIRMWARE_VERSION: case DETECTOR_SOFTWARE_VERSION: retval = getDetectorId(arg); @@ -475,7 +467,7 @@ int get_id(int file_des) { modeNotImplemented("ID Index", (int)arg); break; } - return Server_SendResult(file_des, INT64, 1, &retval, sizeof(retval)); + return Server_SendResult(file_des, INT64, UPDATE, &retval, sizeof(retval)); } @@ -504,17 +496,16 @@ int digital_test(int file_des) { // only set if (Server_VerifyLock() == OK) { switch (mode) { -#ifdef GOTTHARDD - case DIGITAL_BIT_TEST: - FILE_LOG(logDEBUG1, ("Setting digital test bit: %d\n", ival)); - if (ival >= 0) - digitalTestBit = (ival > 0) ? 1 : 0; - retval = digitalTestBit; - break; -#endif + case DETECTOR_FIRMWARE_TEST: case DETECTOR_BUS_TEST: - retval = detectorTest(mode); +#ifdef GOTTHARDD + case DIGITAL_BIT_TEST: + retval = detectorTest(mode, ival); + break; +#else + retval = detectorTest(mode); +#endif FILE_LOG(logDEBUG1, ("Digital Test (%d): %d\n", mode, retval)); break; default: @@ -523,7 +514,7 @@ int digital_test(int file_des) { } } #endif - return Server_SendResult(file_des, INT32, 1, &retval, sizeof(retval)); + return Server_SendResult(file_des, INT32, UPDATE, &retval, sizeof(retval)); } @@ -554,13 +545,29 @@ int set_dac(int file_des) { switch (ind) { #ifdef GOTTHARDD case G_VREF_DS : + serverDacIndex = VREF_DS; + break; case G_VCASCN_PB: + serverDacIndex = VCASCN_PB; + break; case G_VCASCP_PB: + serverDacIndex = VCASCP_PB; + break; case G_VOUT_CM: + serverDacIndex = VOUT_CM; + break; case G_VCASC_OUT: + serverDacIndex = VCASC_OUT; + break; case G_VIN_CM: + serverDacIndex = VIN_CM; + break; case G_VREF_COMP: + serverDacIndex = VREF_COMP; + break; case G_IB_TESTC: + serverDacIndex = IB_TESTC; + break; case HV_POT: break; #elif EIGERD @@ -643,6 +650,7 @@ int set_dac(int file_des) { case IO_DELAY: retval[0] = setIODelay(val); FILE_LOG(logDEBUG1, ("IODelay: %d\n", retval[0])); + validate(val, retval[0], "set iodelay", DEC); break; #endif @@ -651,7 +659,14 @@ int set_dac(int file_des) { case HV_NEW: retval[0] = setHighVoltage(val); FILE_LOG(logDEBUG1, ("High Voltage: %d\n", retval[0])); -#ifdef EIGERD +#ifdef GOTTHARDD + if (retval[0] == -1) { + ret = FAIL; + strcpy(mess,"Invalid Voltage. Valid values are 0, 90, 110, 120, 150, 180, 200\n"); + FILE_LOG(logERROR,(mess)); + } else + validate(val, retval[0], "set high voltage", DEC); +#elif EIGERD if ((retval[0] != SLAVE_HIGH_VOLTAGE_READ_VAL) && (retval[0] < 0)) { ret = FAIL; if (retval[0] == -1) @@ -710,7 +725,7 @@ int set_dac(int file_des) { } } } - return Server_SendResult(file_des, INT32, 1, retval, sizeof(retval)); + return Server_SendResult(file_des, INT32, UPDATE, retval, sizeof(retval)); } @@ -774,7 +789,7 @@ int get_adc(int file_des) { retval = getADC(serverAdcIndex); FILE_LOG(logDEBUG1, ("ADC(%d): %d\n", retval)); } - return Server_SendResult(file_des, INT32, 1, &retval, sizeof(retval)); + return Server_SendResult(file_des, INT32, UPDATE, &retval, sizeof(retval)); } @@ -782,29 +797,33 @@ int get_adc(int file_des) { int write_register(int file_des) { - ret = OK; - memset(mess, 0, sizeof(mess)); - uint32_t args[2] = {-1, -1}; - uint32_t retval = -1; + ret = OK; + memset(mess, 0, sizeof(mess)); + uint32_t args[2] = {-1, -1}; + uint32_t retval = -1; - if (receiveData(file_des, args, sizeof(args), INT32) < 0) - return printSocketReadError(); - uint32_t addr = args[0]; - uint32_t val = args[1]; - FILE_LOG(logDEBUG1, ("Writing to register 0x%x, data 0x%x\n", addr, val)); + if (receiveData(file_des, args, sizeof(args), INT32) < 0) + return printSocketReadError(); + uint32_t addr = args[0]; + uint32_t val = args[1]; + FILE_LOG(logDEBUG1, ("Writing to register 0x%x, data 0x%x\n", addr, val)); - // only set - if (Server_VerifyLock() == OK) { - retval = writeRegister(addr, val); - // validate - if (retval != val) { - ret = FAIL; - sprintf(mess,"Could not write to register 0x%x. Wrote 0x%x but read 0x%x\n", addr, val, retval); - FILE_LOG(logERROR,(mess)); - } - FILE_LOG(logDEBUG1, ("Write register (0x%x): 0x%x\n", retval)); - } - return Server_SendResult(file_des, INT32, 1, &retval, sizeof(retval)); + // only set + if (Server_VerifyLock() == OK) { +#ifdef GOTTHARDD + retval = writeRegister16And32(addr, val); +#else + retval = writeRegister(addr, val); +#endif + // validate + if (retval != val) { + ret = FAIL; + sprintf(mess,"Could not write to register 0x%x. Wrote 0x%x but read 0x%x\n", addr, val, retval); + FILE_LOG(logERROR,(mess)); + } + FILE_LOG(logDEBUG1, ("Write register (0x%x): 0x%x\n", retval)); + } + return Server_SendResult(file_des, INT32, UPDATE, &retval, sizeof(retval)); } @@ -823,10 +842,14 @@ int read_register(int file_des) { FILE_LOG(logDEBUG1, ("Reading from register 0x%x\n", addr)); // get +#ifdef GOTTHARDD + retval = readRegister16And32(addr); +#else retval = readRegister(addr); +#endif FILE_LOG(logDEBUG1, ("Read register (0x%x): 0x%x\n", retval)); - return Server_SendResult(file_des, INT32, 1, &retval, sizeof(retval)); + return Server_SendResult(file_des, INT32, UPDATE, &retval, sizeof(retval)); } @@ -854,8 +877,8 @@ int set_module(int file_des) { } else module.dacs = myDac; - // allocate chans #ifdef EIGERD + // allocate chans if (ret == OK) { myChan = (int*)malloc(getTotalNumberOfChannels() * sizeof(int)); if (getTotalNumberOfChannels() > 0 && myChan == NULL) { @@ -929,12 +952,12 @@ int set_module(int file_des) { ret = setModule(module, mess); retval = getSettings(); - validate(module.reg, (int)retval, "set module (settings)", 0); + validate(module.reg, (int)retval, "set module (settings)", DEC); FILE_LOG(logDEBUG1, ("Settings: %d\n", retval)); } if (myChan != NULL) free(myChan); if (myDac != NULL) free(myDac); - return Server_SendResult(file_des, INT32, 1, &retval, sizeof(retval)); + return Server_SendResult(file_des, INT32, UPDATE, &retval, sizeof(retval)); } @@ -960,8 +983,8 @@ int get_module(int file_des) { } else module.dacs = myDac; - // allocate chans #ifdef EIGERD + // allocate chans if (ret == OK) { myChan = (int*)malloc(getTotalNumberOfChannels() * sizeof(int)); if (getTotalNumberOfChannels() > 0 && myChan == NULL) { @@ -985,7 +1008,7 @@ int get_module(int file_des) { FILE_LOG(logDEBUG1, ("Getting module. Settings:%d\n", module.reg)); } - Server_SendResult(file_des, INT32, 1, NULL, 0); + Server_SendResult(file_des, INT32, UPDATE, NULL, 0); // send module, 0 is to receive partially (without trimbits etc) if (ret != FAIL) { @@ -1046,7 +1069,7 @@ int set_settings(int file_des) { if (ret == OK) { retval = setSettings(isett); FILE_LOG(logDEBUG1, ("Settings: %d\n", retval)); - validate((int)isett, (int)retval, "set settings", 0); + validate((int)isett, (int)retval, "set settings", DEC); #if defined(JUNGFRAUD) || defined (GOTTHARDD) if (ret == OK && isett >= 0) { ret = setDefaultDacs(); @@ -1058,7 +1081,7 @@ int set_settings(int file_des) { #endif } } - return Server_SendResult(file_des, INT32, 1, &retval, sizeof(retval)); + return Server_SendResult(file_des, INT32, UPDATE, &retval, sizeof(retval)); } @@ -1078,7 +1101,7 @@ int get_threshold_energy(int file_des) { retval = getThresholdEnergy(); FILE_LOG(logDEBUG1, ("Threshold energy: %d eV\n", retval)); #endif - return Server_SendResult(file_des, INT32, 1, &retval, sizeof(retval)); + return Server_SendResult(file_des, INT32, UPDATE, &retval, sizeof(retval)); } @@ -1100,7 +1123,7 @@ int start_acquisition(int file_des) { } FILE_LOG(logDEBUG1, ("Starting Acquisition ret: %d\n", ret)); } - return Server_SendResult(file_des, INT32, 1, NULL, 0); + return Server_SendResult(file_des, INT32, UPDATE, NULL, 0); } @@ -1119,7 +1142,7 @@ int stop_acquisition(int file_des) { } FILE_LOG(logDEBUG1, ("Stopping Acquisition ret: %d\n", ret)); } - return Server_SendResult(file_des, INT32, 1, NULL, 0); + return Server_SendResult(file_des, INT32, UPDATE, NULL, 0); } @@ -1131,7 +1154,7 @@ int start_readout(int file_des) { memset(mess, 0, sizeof(mess)); FILE_LOG(logDEBUG1, ("Starting readout\n")); -#ifdef JUNGFRAUD +#ifndef EIGERD functionNotImplemented(); #else // only set @@ -1144,7 +1167,7 @@ int start_readout(int file_des) { FILE_LOG(logDEBUG1, ("Starting readout ret: %d\n", ret)); } #endif - return Server_SendResult(file_des, INT32, 1, NULL, 0); + return Server_SendResult(file_des, INT32, UPDATE, NULL, 0); } @@ -1161,7 +1184,7 @@ int get_run_status(int file_des) { // only get retval = getRunStatus(); FILE_LOG(logDEBUG1, ("Status: %d\n", retval)); - return Server_SendResult(file_des, INT32, 1, &retval, sizeof(retval)); + return Server_SendResult(file_des, INT32, UPDATE, &retval, sizeof(retval)); } @@ -1188,7 +1211,7 @@ int start_and_read_all(int file_des) { // lock or acquisition start error if (ret == FAIL) - return Server_SendResult(file_des, INT32, 1 , NULL, 0); + return Server_SendResult(file_des, INT32, UPDATE, NULL, 0); // read all (again validate lock, but should pass and not fail) return read_all(file_des); @@ -1206,7 +1229,7 @@ int read_all(int file_des) { if (Server_VerifyLock() == OK) { readFrame(&ret, mess); } - return Server_SendResult(file_des, INT32, 1 , NULL, 0); + return Server_SendResult(file_des, INT32, UPDATE, NULL, 0); } @@ -1238,7 +1261,7 @@ int set_timer(int file_des) { case ACQUISITION_TIME: case FRAME_PERIOD: case CYCLES_NUMBER: -#ifdef JUNGFRAUD +#if defined(GOTTHARDD) || defined(JUNGFRAUD) case DELAY_AFTER_TRIGGER: #endif retval = setTimer(ind, tns); @@ -1284,12 +1307,12 @@ int set_timer(int file_des) { break; } // validate - validate64(tns, retval, "set timer", 0); + validate64(tns, retval, "set timer", DEC); } if (ret != FAIL) { FILE_LOG(logDEBUG1, ("Timer index %d: %lld\n", ind, retval)); } - return Server_SendResult(file_des, INT64, 1, &retval, sizeof(retval)); + return Server_SendResult(file_des, INT64, UPDATE, &retval, sizeof(retval)); } @@ -1325,18 +1348,16 @@ int get_time_left(int file_des) { #elif JUNGFRAUD case FRAMES_FROM_START: case FRAMES_FROM_START_PG: + case ACTUAL_TIME: + case MEASUREMENT_TIME: #elif GOTTHARDD - case GATES_NUMBER: + case ACQUISITION_TIME: #endif #if defined(GOTTHARDD) || defined(JUNGFRAUD) case FRAME_NUMBER: - case ACQUISITION_TIME: case FRAME_PERIOD: case DELAY_AFTER_TRIGGER: case CYCLES_NUMBER: - case PROGRESS: - case ACTUAL_TIME: - case MEASUREMENT_TIME: #endif retval = getTimeLeft(ind); FILE_LOG(logDEBUG1, ("Timer left index %d: %lld\n", ind, retval)); @@ -1346,7 +1367,7 @@ int get_time_left(int file_des) { break; } } - return Server_SendResult(file_des, INT64, 1, &retval, sizeof(retval)); + return Server_SendResult(file_des, INT64, UPDATE, &retval, sizeof(retval)); } @@ -1379,9 +1400,7 @@ int set_dynamic_range(int file_des) { #endif retval = setDynamicRange(dr); FILE_LOG(logDEBUG1, ("Dynamic range: %d\n", retval)); - validate(dr, retval, "set dynamic range", 0); - if (dr >= 0) - dataBytes=calculateDataBytes(); + validate(dr, retval, "set dynamic range", DEC); break; default: modeNotImplemented("Dynamic range", dr); @@ -1411,7 +1430,7 @@ int set_dynamic_range(int file_des) { } #endif } - return Server_SendResult(file_des, INT32, 1, &retval, sizeof(retval)); + return Server_SendResult(file_des, INT32, UPDATE, &retval, sizeof(retval)); } @@ -1445,7 +1464,7 @@ int set_readout_flags(int file_des) { case NOOVERFLOW: retval = setReadOutFlags(arg); FILE_LOG(logDEBUG1, ("Read out flags: 0x%x\n", retval)); - validate((int)arg, (int)(retval & arg), "set readout flag", 1); + validate((int)arg, (int)(retval & arg), "set readout flag", HEX); break; default: modeNotImplemented("Read out flag index", (int)arg); @@ -1453,7 +1472,7 @@ int set_readout_flags(int file_des) { } } #endif - return Server_SendResult(file_des, INT32, 1, &retval, sizeof(retval)); + return Server_SendResult(file_des, INT32, UPDATE, &retval, sizeof(retval)); } @@ -1499,18 +1518,24 @@ int set_roi(int file_des) { functionNotImplemented(); #else // set & get - if ((arg == GET_READOUT_FLAGS) || ((arg != GET_READOUT_FLAGS) && (Server_VerifyLock() == OK))) { - retval = setROI(narg, arg, &nretval, &ret); - if (ret == FAIL) { - sprintf(mess,"Could not set all roi. " - "Set %d rois, but read %d rois\n", narg, nretval); - FILE_LOG(logERROR,(mess)); - } - FILE_LOG(logDEBUG1, ("nRois: %d\n", nretval)); + if ((narg == GET_READOUT_FLAGS) || ((narg != GET_READOUT_FLAGS) && (Server_VerifyLock() == OK))) { + if (narg > 1) { + ret = FAIL; + strcpy(mess,"Can not set more than one ROI per module.\n"); + FILE_LOG(logERROR,(mess)); + } else { + retval = setROI(narg, arg, &nretval, &ret); + if (ret == FAIL) { + sprintf(mess,"Could not set all roi. " + "Set %d rois, but read %d rois\n", narg, nretval); + FILE_LOG(logERROR,(mess)); + } + FILE_LOG(logDEBUG1, ("nRois: %d\n", nretval)); + } } #endif - Server_SendResult(file_des, INT32, 1, NULL, 0); + Server_SendResult(file_des, INT32, UPDATE, NULL, 0); if (ret != FAIL) { //retvalsize could be swapped during sendData @@ -1539,6 +1564,10 @@ int set_speed(int file_des) { if (receiveData(file_des, args, sizeof(args), INT32) < 0) return printSocketReadError(); + +#ifdef GOTTHARDD + functionNotImplemented(); +#else enum speedVariable ind = args[0]; int val = args[1]; FILE_LOG(logDEBUG1, ("Setting speed index %d to %d\n", ind, val)); @@ -1552,21 +1581,23 @@ int set_speed(int file_des) { retval = adcPhase(val); FILE_LOG(logDEBUG1, ("ADc Phase: %d\n", retval)); if (val != 100000) { - validate(val, retval, "set adc phase ", 0); + validate(val, retval, "set adc phase ", DEC); } break; #endif case CLOCK_DIVIDER: retval = setSpeed(val); FILE_LOG(logDEBUG1, ("Clock: %d\n", retval)); - validate(val, retval, "set clock ", 0); + validate(val, retval, "set clock ", DEC); break; default: modeNotImplemented("Speed index", (int)ind); break; } } - return Server_SendResult(file_des, INT32, 1, &retval, sizeof(retval)); +#endif + + return Server_SendResult(file_des, INT32, UPDATE, &retval, sizeof(retval)); } @@ -1578,7 +1609,7 @@ int exit_server(int file_des) { cprintf(BG_RED, "Closing Server\n"); ret = OK; memset(mess, 0, sizeof(mess)); - Server_SendResult(file_des, INT32, 0, NULL, 0); + Server_SendResult(file_des, INT32, NO_UPDATE, NULL, 0); return GOODBYE; } @@ -1605,7 +1636,7 @@ int lock_server(int file_des) { Server_LockedError(); } } - return Server_SendResult(file_des, INT32, 1, &lockStatus, sizeof(lockStatus)); + return Server_SendResult(file_des, INT32, UPDATE, &lockStatus, sizeof(lockStatus)); } @@ -1614,7 +1645,7 @@ int lock_server(int file_des) { int get_last_client_ip(int file_des) { ret = OK; memset(mess, 0, sizeof(mess)); - return Server_SendResult(file_des, INT32, 1, lastClientIP, sizeof(lastClientIP)); + return Server_SendResult(file_des, INT32, UPDATE, lastClientIP, sizeof(lastClientIP)); } @@ -1646,7 +1677,7 @@ int set_port(int file_des) { } } - Server_SendResult(file_des, INT32, 1, &p_number, sizeof(p_number)); + Server_SendResult(file_des, INT32, UPDATE, &p_number, sizeof(p_number)); // delete old socket if (ret != FAIL) { closeConnection(file_des); @@ -1668,7 +1699,7 @@ int update_client(int file_des) { ret = OK; } #endif - Server_SendResult(file_des, INT32, 0, NULL, 0); + Server_SendResult(file_des, INT32, NO_UPDATE, NULL, 0); if (ret == OK) return ret; return send_update(file_des); @@ -1690,8 +1721,8 @@ int send_update(int file_des) { n = sendData(file_des,&i32,sizeof(i32),INT32); if (n < 0) return printSocketReadError(); - dataBytes = calculateDataBytes(); - n = sendData(file_des,&dataBytes,sizeof(dataBytes),INT32); + i32 = calculateDataBytes(); + n = sendData(file_des,&i32,sizeof(i32),INT32); if (n < 0) return printSocketReadError(); i32 = (int)setSettings(GET_SETTINGS); @@ -1732,12 +1763,6 @@ int send_update(int file_des) { if (n < 0) return printSocketReadError(); #endif -#if !defined(EIGERD) && !defined(JUNGFRAUD) - i64 = setTimer(GATES_NUMBER,GET_FLAG); - n = sendData(file_des,&i64,sizeof(i64),INT64); - if (n < 0) return printSocketReadError(); -#endif - i64 = setTimer(CYCLES_NUMBER,GET_FLAG); n = sendData(file_des,&i64,sizeof(i64),INT64); if (n < 0) return printSocketReadError(); @@ -1759,16 +1784,12 @@ int configure_mac(int file_des) { memset(mess, 0, sizeof(mess)); char args[9][50]; memset(args, 0, sizeof(args)); - char retvals[3][50]; + char retvals[2][50]; memset(retvals, 0, sizeof(retvals)); - int iretval = -1; if (receiveData(file_des, args, sizeof(args), OTHER) < 0) return printSocketReadError(); FILE_LOG(logDEBUG1, ("\n Configuring UDP Destination\n")); -#ifdef GOTTHARDD - FILE_LOG(logDEBUG1, ("Digital Test Bit %d\t", digitalTestBit); -#endif uint32_t dstIp = 0; sscanf(args[0], "%x", &dstIp); FILE_LOG(logDEBUG1, ("Dst Ip Addr: %d.%d.%d.%d = 0x%x \n", @@ -1863,20 +1884,14 @@ int configure_mac(int file_des) { srcIp = dhcpipad; #endif -#ifdef GOTTHARDD - iretval = configureMAC(dstIp, dstMac, srcMac, srcIp, dstPort, dstPort2, digitalTestBit); - FILE_LOG(logDEBUG1, ("Configure mac retval: %d\n", iretval)); - FILE_LOG(logINFO, ("Configure MAC successful: %d\n", iretval)); -#else - iretval = configureMAC(dstIp, dstMac, srcMac, srcIp, dstPort, dstPort2); - FILE_LOG(logDEBUG1, ("Configure mac retval: %d\n", iretval)); - - if (iretval == -1) { - ret = FAIL; + ret = configureMAC(dstIp, dstMac, srcMac, srcIp, dstPort, dstPort2); + if (ret == FAIL) { sprintf(mess,"Configure Mac failed\n"); FILE_LOG(logERROR,(mess)); - } else { - FILE_LOG(logINFO, ("Configure MAC successful\n")); + } +#if defined(EIGERD) || defined (JUNGFRAUD) + else { + FILE_LOG(logINFO, ("Configure MAC successful: %d\n", ret)); ret = setDetectorPosition(pos); if (ret == FAIL) { sprintf(mess, "Could not set detector position\n"); @@ -1886,14 +1901,13 @@ int configure_mac(int file_des) { #endif // set retval vals if (ret != FAIL) { - sprintf(retvals[0],"%x", iretval); - sprintf(retvals[1],"%llx", (long long unsigned int)srcMac); - sprintf(retvals[2],"%x", srcIp); + sprintf(retvals[0],"%llx", (long long unsigned int)srcMac); + sprintf(retvals[1],"%x", srcIp); } } } - return Server_SendResult(file_des, OTHER, 1, retvals, sizeof(retvals)); + return Server_SendResult(file_des, OTHER, UPDATE, retvals, sizeof(retvals)); } @@ -1907,12 +1921,12 @@ int load_image(int file_des) { if (receiveData(file_des, args, sizeof(args), INT32) < 0) return printSocketReadError(); + enum imageType index = args[0]; - char* ImageVals = NULL; - if (args[1] > 0) { - ImageVals = (char*)malloc(args[1]); - if (receiveData(file_des, ImageVals, args[1], OTHER) < 0) { - free(ImageVals); + int numChannels = args[1]; + short int imageVals[numChannels] = {0}; + if (numChannels > 0) { + if (receiveData(file_des, imageVals, numChannels * sizeof(short int), OTHER) < 0) { return printSocketReadError(); } } @@ -1928,12 +1942,15 @@ int load_image(int file_des) { switch (index) { case DARK_IMAGE : case GAIN_IMAGE : - ret = loadImage(index, ImageVals); - FILE_LOG(logDEBUG1, ("Loading image ret: %d\n", ret)); - if (ret == FAIL) { - sprintf(mess, "Could not load image\n"); - FILE_LOG(logERROR,(mess)); - } + // size of image does not match expected size + if (numChannels != (calculateDataBytes()/sizeof(short int))) { + ret = FAIL; + sprintf(mess, "Could not load image. " + "Number of Channels do not match. Expected %d, got %d\n", + calculateDataBytes(), numChannels); + FILE_LOG(logERROR,(mess)); + } else + loadImage(index, imageVals); break; default: modeNotImplemented("Image index", (int)index); @@ -1941,7 +1958,7 @@ int load_image(int file_des) { } } #endif - return Server_SendResult(file_des, INT32, 1, NULL, 0); + return Server_SendResult(file_des, INT32, UPDATE, NULL, 0); } @@ -1952,12 +1969,13 @@ int load_image(int file_des) { int read_counter_block(int file_des) { ret = OK; memset(mess, 0, sizeof(mess)); - int startACQ = -1; - char retval[dataBytes]; - memset(retval, 0, dataBytes); + int args[2] = {-1, -1}; - if (receiveData(file_des, &startACQ, sizeof(startACQ), INT32) < 0) + if (receiveData(file_des, args, sizeof(args), INT32) < 0) return printSocketReadError(); + int startACQ = args[0]; + int numChannels = args[1]; + short int retval[numChannels] = {0}; FILE_LOG(logDEBUG1, ("Read counter block with start acq bit: %d\n", startACQ)); #ifndef GOTTHARDD @@ -1966,14 +1984,23 @@ int read_counter_block(int file_des) { // only set if (Server_VerifyLock() == OK) { - ret = readCounterBlock(startACQ, retval); - if (ret == FAIL) { - strcpy(mess, "Could not read counter block\n"); - FILE_LOG(logERROR,(mess)); - } + // size of image does not match expected size + if (numChannels != (calculateDataBytes()/sizeof(short int))) { + ret = FAIL; + sprintf(mess, "Could not load image. " + "Number of Channels do not match. Expected %d, got %d\n", + calculateDataBytes(), numChannels); + FILE_LOG(logERROR,(mess)); + } else { + ret = readCounterBlock(startACQ, retval); + if (ret == FAIL) { + strcpy(mess, "Could not read counter block\n"); + FILE_LOG(logERROR,(mess)); + } + } } #endif - return Server_SendResult(file_des, OTHER, 1, retval, dataBytes); + return Server_SendResult(file_des, OTHER, UPDATE, retval, numChannels * sizeof(short int)); } @@ -1992,7 +2019,6 @@ int reset_counter_block(int file_des) { #ifndef GOTTHARDD functionNotImplemented(); #else - // only set if (Server_VerifyLock() == OK) { ret = resetCounterBlock(startACQ); @@ -2002,7 +2028,7 @@ int reset_counter_block(int file_des) { } } #endif - return Server_SendResult(file_des, INT32, 1, NULL, 0); + return Server_SendResult(file_des, INT32, UPDATE, NULL, 0); } @@ -2026,10 +2052,10 @@ int enable_ten_giga(int file_des) { if ((arg == -1) || ((arg != -1) && (Server_VerifyLock() == OK))) { retval = enableTenGigabitEthernet(arg); FILE_LOG(logDEBUG1, ("10GbE: %d\n", retval)); - validate(arg, retval, "enable/disable 10GbE", 0); + validate(arg, retval, "enable/disable 10GbE", DEC); } #endif - return Server_SendResult(file_des, INT32, 1, &retval, sizeof(retval)); + return Server_SendResult(file_des, INT32, UPDATE, &retval, sizeof(retval)); } @@ -2059,9 +2085,9 @@ int set_all_trimbits(int file_des) { // get retval = getAllTrimbits(); FILE_LOG(logDEBUG1, ("All trimbits: %d\n", retval)); - validate(arg, retval, "set all trimbits", 0); + validate(arg, retval, "set all trimbits", DEC); #endif - return Server_SendResult(file_des, INT32, 1, &retval, sizeof(retval)); + return Server_SendResult(file_des, INT32, UPDATE, &retval, sizeof(retval)); } @@ -2071,7 +2097,7 @@ int set_ctb_pattern(int file_des) { ret = OK; memset(mess, 0, sizeof(mess)); functionNotImplemented(); - return Server_SendResult(file_des, INT32, 1, NULL, 0); + return Server_SendResult(file_des, INT32, UPDATE, NULL, 0); } @@ -2088,7 +2114,7 @@ int write_adc_register(int file_des) { uint32_t val = args[1]; FILE_LOG(logDEBUG1, ("Writing 0x%x to ADC Register 0x%x\n", val, addr)); -#ifndef JUNGFRAUD +#if defined(GOTTHARDD) || defined(JUNGFRAUD) functionNotImplemented(); #else #ifndef VIRTUAL @@ -2097,7 +2123,7 @@ int write_adc_register(int file_des) { setAdc(addr, val); #endif #endif - return Server_SendResult(file_des, INT32, 1, NULL, 0); + return Server_SendResult(file_des, INT32, UPDATE, NULL, 0); } @@ -2124,9 +2150,9 @@ int set_counter_bit(int file_des) { // get retval = setCounterBit(-1); FILE_LOG(logDEBUG1, ("Set counter bit retval: %d\n", retval)); - validate(arg, retval, "set counter bit", 0); + validate(arg, retval, "set counter bit", DEC); #endif - return Server_SendResult(file_des, INT32, 1, &retval, sizeof(retval)); + return Server_SendResult(file_des, INT32, UPDATE, &retval, sizeof(retval)); } @@ -2154,7 +2180,7 @@ int pulse_pixel(int file_des) { } } #endif - return Server_SendResult(file_des, INT32, 1, NULL, 0); + return Server_SendResult(file_des, INT32, UPDATE, NULL, 0); } @@ -2182,7 +2208,7 @@ int pulse_pixel_and_move(int file_des) { } } #endif - return Server_SendResult(file_des, INT32, 1, NULL, 0); + return Server_SendResult(file_des, INT32, UPDATE, NULL, 0); } @@ -2211,7 +2237,7 @@ int pulse_chip(int file_des) { } } #endif - return Server_SendResult(file_des, INT32, 1, NULL, 0); + return Server_SendResult(file_des, INT32, UPDATE, NULL, 0); } @@ -2252,11 +2278,11 @@ int set_rate_correct(int file_des) { FILE_LOG(logERROR, ("Settings has been changed to undefined (tau changed)\n")); } int64_t retval = setRateCorrection(tau_ns); - validate64(tau_ns, retval, "set rate correction", 0); + validate64(tau_ns, retval, "set rate correction", DEC); } } #endif - return Server_SendResult(file_des, INT32, 1, NULL, 0); + return Server_SendResult(file_des, INT32, UPDATE, NULL, 0); } @@ -2275,7 +2301,7 @@ int get_rate_correct(int file_des) { retval = getCurrentTau(); FILE_LOG(logDEBUG1, ("Tau: %lld\n", (long long int)retval)); #endif - return Server_SendResult(file_des, INT64, 1, &retval, sizeof(retval)); + return Server_SendResult(file_des, INT64, UPDATE, &retval, sizeof(retval)); } @@ -2332,11 +2358,11 @@ int set_network_parameter(int file_des) { if (ret == OK) { retval = setNetworkParameter(serverIndex, value); FILE_LOG(logDEBUG1, ("Network Parameter index %d: %d\n", serverIndex, retval)); - validate(value, retval, "set network parameter", 0); + validate(value, retval, "set network parameter", DEC); } } #endif - return Server_SendResult(file_des, INT32, 1, &retval, sizeof(retval)); + return Server_SendResult(file_des, INT32, UPDATE, &retval, sizeof(retval)); } @@ -2394,7 +2420,7 @@ int program_fpga(int file_des) { } //---------------- first ret ---------------- - Server_SendResult(file_des, INT32, 0, NULL, 0); + Server_SendResult(file_des, INT32, NO_UPDATE, NULL, 0); if (ret != FAIL) { //erasing flash @@ -2427,7 +2453,7 @@ int program_fpga(int file_des) { ret = writeFPGAProgram(fpgasrc, unitprogramsize, fp); //---------------- middle rets ---------------- - Server_SendResult(file_des, INT32, 0, NULL, 0); + Server_SendResult(file_des, INT32, NO_UPDATE, NULL, 0); @@ -2455,14 +2481,14 @@ int program_fpga(int file_des) { FILE_LOG(logDEBUG1, ("Done with program receiving command\n")); if (isControlServer) { - basictests(debugflag); + basictests(); initControlServer(); } } } #endif #endif - return Server_SendResult(file_des, INT32, 1, NULL, 0); + return Server_SendResult(file_des, INT32, UPDATE, NULL, 0); } @@ -2480,7 +2506,7 @@ int reset_fpga(int file_des) { // only set if (Server_VerifyLock() == OK) { if (isControlServer) { - basictests(debugflag); // mapping of control server at least + basictests(); // mapping of control server at least if (debugflag != PROGRAMMING_MODE) initControlServer(); } @@ -2488,7 +2514,7 @@ int reset_fpga(int file_des) { ret = FORCE_UPDATE; } #endif - return Server_SendResult(file_des, INT32, 1, NULL, 0); + return Server_SendResult(file_des, INT32, UPDATE, NULL, 0); } @@ -2510,7 +2536,7 @@ int power_chip(int file_des) { if ((arg == -1) || ((arg != -1) && (Server_VerifyLock() == OK))) { retval = powerChip(arg); FILE_LOG(logDEBUG1, ("Power chip: %d\n", retval)); - validate(arg, retval, "power on/off chip", 0); + validate(arg, retval, "power on/off chip", DEC); // narrow down error when powering on if (ret == FAIL && arg > 0) { if (setTemperatureEvent(-1) == 1) @@ -2520,7 +2546,7 @@ int power_chip(int file_des) { } } #endif - return Server_SendResult(file_des, INT32, 1, &retval, sizeof(retval)); + return Server_SendResult(file_des, INT32, UPDATE, &retval, sizeof(retval)); } @@ -2543,10 +2569,10 @@ int set_activate(int file_des) { if ((arg == -1) || ((arg != -1) && (Server_VerifyLock() == OK))) { retval = activate(arg); FILE_LOG(logDEBUG1, ("Activate: %d\n", retval)); - validate(arg, retval, "set activate", 0); + validate(arg, retval, "set activate", DEC); } #endif - return Server_SendResult(file_des, INT32, 1, &retval, sizeof(retval)); + return Server_SendResult(file_des, INT32, UPDATE, &retval, sizeof(retval)); } @@ -2569,7 +2595,7 @@ int prepare_acquisition(int file_des) { } } #endif - return Server_SendResult(file_des, INT32, 1 , NULL, 0); + return Server_SendResult(file_des, INT32, UPDATE, NULL, 0); } @@ -2601,11 +2627,11 @@ int threshold_temp(int file_des) { else { retval = setThresholdTemperature(arg); FILE_LOG(logDEBUG1, ("Threshold temperature: %d\n", retval)); - validate(arg, retval, "set threshold temperature", 0); + validate(arg, retval, "set threshold temperature", DEC); } } #endif - return Server_SendResult(file_des, INT32, 0, &retval, sizeof(retval)); + return Server_SendResult(file_des, INT32, NO_UPDATE, &retval, sizeof(retval)); } @@ -2627,10 +2653,10 @@ int temp_control(int file_des) { if ((arg == -1) || ((arg != -1) && (Server_VerifyLock() == OK))) { retval = setTemperatureControl(arg); FILE_LOG(logDEBUG1, ("Temperature control: %d\n", retval)); - validate(arg, retval, "set temperature control", 0); + validate(arg, retval, "set temperature control", DEC); } #endif - return Server_SendResult(file_des, INT32, 0, &retval, sizeof(retval)); + return Server_SendResult(file_des, INT32, NO_UPDATE, &retval, sizeof(retval)); } @@ -2653,10 +2679,10 @@ int temp_event(int file_des) { if ((arg == -1) || ((arg != -1) && (Server_VerifyLock() == OK))) { retval = setTemperatureEvent(arg); FILE_LOG(logDEBUG1, ("Temperature event: %d\n", retval)); - validate(arg, retval, "set temperature event", 0); + validate(arg, retval, "set temperature event", DEC); } #endif - return Server_SendResult(file_des, INT32, 0, &retval, sizeof(retval)); + return Server_SendResult(file_des, INT32, NO_UPDATE, &retval, sizeof(retval)); } @@ -2680,10 +2706,10 @@ int auto_comp_disable(int file_des) { if ((arg == -1) || ((arg != -1) && (Server_VerifyLock() == OK))) { retval = autoCompDisable(arg); FILE_LOG(logDEBUG1, ("Auto comp disable: %d\n", retval)); - validate(arg, retval, "set auto comp disable", 0); + validate(arg, retval, "set auto comp disable", DEC); } #endif - return Server_SendResult(file_des, INT32, 1, &retval, sizeof(retval)); + return Server_SendResult(file_des, INT32, UPDATE, &retval, sizeof(retval)); } @@ -2712,11 +2738,11 @@ int storage_cell_start(int file_des) { } else { retval = selectStoragecellStart(arg); FILE_LOG(logDEBUG1, ("Storage cell start: %d\n", retval)); - validate(arg, retval, "set storage cell start", 0); + validate(arg, retval, "set storage cell start", DEC); } } #endif - return Server_SendResult(file_des, INT32, 1, &retval, sizeof(retval)); + return Server_SendResult(file_des, INT32, UPDATE, &retval, sizeof(retval)); } @@ -2782,7 +2808,7 @@ int check_version(int file_des) { FILE_LOG(logERROR,(mess)); } } - return Server_SendResult(file_des, INT32, 1 , NULL, 0); + return Server_SendResult(file_des, INT32, UPDATE, NULL, 0); } @@ -2806,6 +2832,6 @@ int software_trigger(int file_des) { FILE_LOG(logDEBUG1, ("Software trigger ret: %d\n", ret)); } #endif - return Server_SendResult(file_des, INT32, 1 , NULL, 0); + return Server_SendResult(file_des, INT32, UPDATE, NULL, 0); } diff --git a/slsDetectorServers/slsDetectorServer/slsDetectorServer_funcs.h b/slsDetectorServers/slsDetectorServer/slsDetectorServer_funcs.h index b37bf5aa7..9fcbc99e0 100755 --- a/slsDetectorServers/slsDetectorServer/slsDetectorServer_funcs.h +++ b/slsDetectorServers/slsDetectorServer/slsDetectorServer_funcs.h @@ -3,7 +3,6 @@ // initialization functions int printSocketReadError(); -void basictests(); void init_detector(); int decode_function(int); const char* getFunctionName(enum detFuncs func); diff --git a/slsDetectorSoftware/slsDetector/slsDetector.cpp b/slsDetectorSoftware/slsDetector/slsDetector.cpp index 4d503d95e..e2a1b4f35 100644 --- a/slsDetectorSoftware/slsDetector/slsDetector.cpp +++ b/slsDetectorSoftware/slsDetector/slsDetector.cpp @@ -42,7 +42,7 @@ slsDetector::slsDetector(detectorType type, int multiId, int id, bool verify) // ensure shared memory was not created before auto shm = SharedMemory(multiId, id); if (shm.IsExisting()) { - FILE_LOG(logWARNING) << "Weird, this shared memory should have been " + FILE_LOG(logWARNING) << "This shared memory should have been " "deleted before! " << shm.GetName() << ". Freeing it again"; freeSharedMemory(multiId, id); } @@ -1402,12 +1402,6 @@ int slsDetector::updateDetectorNoWait() { thisDetector->timerValue[DELAY_AFTER_TRIGGER] = i64; } - if ((thisDetector->myDetectorType != JUNGFRAU) && - (thisDetector->myDetectorType != EIGER)) { - n += controlSocket->ReceiveDataOnly(&i64, sizeof(i64)); - thisDetector->timerValue[GATES_NUMBER] = i64; - } - n += controlSocket->ReceiveDataOnly(&i64, sizeof(i64)); thisDetector->timerValue[CYCLES_NUMBER] = i64; @@ -2060,7 +2054,7 @@ int slsDetector::configureMAC() { int ret = FAIL; char args[9][50]; memset(args, 0, sizeof(args)); - char retvals[3][50]; + char retvals[2][50]; memset(retvals, 0, sizeof(retvals)); FILE_LOG(logDEBUG1) << "Configuring MAC"; @@ -2186,30 +2180,30 @@ int slsDetector::configureMAC() { // get detectormac, detector ip uint64_t idetectormac = 0; uint32_t idetectorip = 0; - sscanf(retvals[1], "%lx", &idetectormac); - sscanf(retvals[2], "%x", &idetectorip); - sprintf(retvals[1],"%02x:%02x:%02x:%02x:%02x:%02x", + sscanf(retvals[0], "%lx", &idetectormac); + sscanf(retvals[1], "%x", &idetectorip); + sprintf(retvals[0],"%02x:%02x:%02x:%02x:%02x:%02x", (unsigned int)((idetectormac>>40)&0xFF), (unsigned int)((idetectormac>>32)&0xFF), (unsigned int)((idetectormac>>24)&0xFF), (unsigned int)((idetectormac>>16)&0xFF), (unsigned int)((idetectormac>>8)&0xFF), (unsigned int)((idetectormac>>0)&0xFF)); - sprintf(retvals[2],"%d.%d.%d.%d", + sprintf(retvals[1],"%d.%d.%d.%d", (idetectorip>>24)&0xff, (idetectorip>>16)&0xff, (idetectorip>>8)&0xff, (idetectorip)&0xff); // update if different - if (strcasecmp(retvals[1],thisDetector->detectorMAC)) { + if (strcasecmp(retvals[0],thisDetector->detectorMAC)) { memset(thisDetector->detectorMAC, 0, MAX_STR_LENGTH); - strcpy(thisDetector->detectorMAC, retvals[1]); + strcpy(thisDetector->detectorMAC, retvals[0]); FILE_LOG(logINFO) << detId << ": Detector MAC updated to " << thisDetector->detectorMAC; } - if (strcasecmp(retvals[2],thisDetector->detectorIP)) { + if (strcasecmp(retvals[1],thisDetector->detectorIP)) { memset(thisDetector->detectorIP, 0, MAX_STR_LENGTH); - strcpy(thisDetector->detectorIP, retvals[2]); + strcpy(thisDetector->detectorIP, retvals[1]); FILE_LOG(logINFO) << detId << ": Detector IP updated to " << thisDetector->detectorIP; } @@ -3364,11 +3358,12 @@ int slsDetector::digitalTest( digitalTestMode mode, int ival) { int slsDetector::loadImageToDetector(imageType index,std::string const fname) { int ret = FAIL; - short int args[thisDetector->nChans * thisDetector->nChips]; + int nChan = getTotalNumberOfChannels(); + short int args[nChan]; FILE_LOG(logDEBUG1) << "Loading " << (!index ? "Dark" : "Gain") << "image from file " << fname; - if (readDataFile(fname, args, getTotalNumberOfChannels())) { - ret = sendImageToDetector(index,args); + if (readDataFile(fname, args, nChan)) { + ret = sendImageToDetector(index, args); return ret; } @@ -3381,18 +3376,24 @@ int slsDetector::loadImageToDetector(imageType index,std::string const fname) { int slsDetector::sendImageToDetector(imageType index,short int imageVals[]) { int fnum = F_LOAD_IMAGE; int ret = FAIL; + int nChan = getTotalNumberOfChannels(); + int args[2] = {(int)index, nChan}; FILE_LOG(logDEBUG1) << "Sending image to detector"; if (thisDetector->onlineFlag == ONLINE_FLAG && connectControl() == OK) { - ret = thisDetectorControl->Client_Send(fnum, - imageVals, thisDetector->dataBytes, NULL, 0); - disconnectControl(); - - // handle ret - if (ret == FAIL) { - setErrorMask((getErrorMask())|(OTHER_ERROR_CODE)); - } else if (ret == FORCE_UPDATE) - ret = updateDetector(); + controlSocket->SendDataOnly(&fnum, sizeof(fnum)); + controlSocket->SendDataOnly(args, sizeof(args)); + controlSocket->SendDataOnly(imageVals, nChan * sizeof(short int)); + controlSocket->ReceiveDataOnly(&ret, sizeof(ret)); + if (ret == FAIL) { + char mess[MAX_STR_LENGTH] = {0}; + setErrorMask((getErrorMask())|(OTHER_ERROR_CODE)); + controlSocket->ReceiveDataOnly(mess, MAX_STR_LENGTH); + FILE_LOG(logERROR) << "Detector " << detId << " returned error: " << mess; + } + disconnectControl(); + if (ret == FORCE_UPDATE) + ret = updateDetector(); } return ret; } @@ -3400,7 +3401,8 @@ int slsDetector::sendImageToDetector(imageType index,short int imageVals[]) { int slsDetector::writeCounterBlockFile(std::string const fname,int startACQ) { int ret = FAIL; - short int retvals[thisDetector->nChans * thisDetector->nChips]; + int nChan = getTotalNumberOfChannels(); + short int retvals[nChan]; FILE_LOG(logDEBUG1) << "Reading Counter to " << fname << (startACQ ? " and Restarting Acquisition" : "\n"); @@ -3408,20 +3410,22 @@ int slsDetector::writeCounterBlockFile(std::string const fname,int startACQ) { if (ret == FAIL) setErrorMask((getErrorMask())|(OTHER_ERROR_CODE)); else - ret=writeDataFile(fname, getTotalNumberOfChannels(), retvals); + ret = writeDataFile(fname, nChan, retvals); return ret; } int slsDetector::getCounterBlock(short int image[],int startACQ) { - int fnum = F_READ_COUNTER_BLOCK; + int nChan = getTotalNumberOfChannels(); + int fnum = F_READ_COUNTER_BLOCK; int ret = FAIL; - int arg = startACQ; + int nChan = getTotalNumberOfChannels(); + int args[2] = {startACQ, nChan}; FILE_LOG(logDEBUG1) << "Reading Counter block with startacq: " << startACQ; if (thisDetector->onlineFlag == ONLINE_FLAG && connectControl() == OK) { ret = thisDetectorControl->Client_Send(fnum, - &arg, sizeof(arg), image, thisDetector->dataBytes); + args, sizeof(args), image, nChan * sizeof(short int)); disconnectControl(); // handle ret