From d5f80831dd717b956847547101fe9be385c281d9 Mon Sep 17 00:00:00 2001 From: Anna Bergamaschi Date: Tue, 30 Aug 2016 09:30:31 +0200 Subject: [PATCH] Changes to jctb server to correctly change the power supplies --- .../jctbDetectorServer/Makefile.ctb | 61 + slsDetectorSoftware/jctbDetectorServer/ansi.h | 1 + .../jctbDetectorServer/communication_funcs.c | 1 + .../jctbDetectorServer/communication_funcs.h | 1 + .../jctbDetectorServer/firmware_funcs.c | 3664 +++++++++++++++++ .../jctbDetectorServer/firmware_funcs.h | 214 + .../jctbDetectorServer/gitInfoMoench.h | 11 + .../jctbDetectorServer/gitInfoMoenchTmp.h | 11 + .../jungfrauDetectorServerTest | Bin 0 -> 134952 bytes .../jctbDetectorServer/mcb_funcs.c | 2701 ++++++++++++ .../jctbDetectorServer/mcb_funcs.h | 174 + .../jctbDetectorServer/registers_m.h | 529 +++ .../jctbDetectorServer/server.c | 139 + .../jctbDetectorServer/server_defs.h | 78 + .../jctbDetectorServer/server_funcs.c | 3513 ++++++++++++++++ .../jctbDetectorServer/server_funcs.h | 98 + .../jctbDetectorServer/sharedmemory.c | 39 + .../jctbDetectorServer/sharedmemory.h | 48 + .../jctbDetectorServer/sls_detector_defs.h | 1 + .../jctbDetectorServer/sls_detector_funcs.h | 1 + .../jctbDetectorServer/sls_receiver_defs.h | 1 + .../jctbDetectorServer/sls_receiver_funcs.h | 1 + .../jctbDetectorServer/stop_server.c | 46 + 23 files changed, 11333 insertions(+) create mode 100644 slsDetectorSoftware/jctbDetectorServer/Makefile.ctb create mode 120000 slsDetectorSoftware/jctbDetectorServer/ansi.h create mode 120000 slsDetectorSoftware/jctbDetectorServer/communication_funcs.c create mode 120000 slsDetectorSoftware/jctbDetectorServer/communication_funcs.h create mode 100755 slsDetectorSoftware/jctbDetectorServer/firmware_funcs.c create mode 100755 slsDetectorSoftware/jctbDetectorServer/firmware_funcs.h create mode 100644 slsDetectorSoftware/jctbDetectorServer/gitInfoMoench.h create mode 100644 slsDetectorSoftware/jctbDetectorServer/gitInfoMoenchTmp.h create mode 100755 slsDetectorSoftware/jctbDetectorServer/jungfrauDetectorServerTest create mode 100755 slsDetectorSoftware/jctbDetectorServer/mcb_funcs.c create mode 100755 slsDetectorSoftware/jctbDetectorServer/mcb_funcs.h create mode 100755 slsDetectorSoftware/jctbDetectorServer/registers_m.h create mode 100755 slsDetectorSoftware/jctbDetectorServer/server.c create mode 100755 slsDetectorSoftware/jctbDetectorServer/server_defs.h create mode 100755 slsDetectorSoftware/jctbDetectorServer/server_funcs.c create mode 100755 slsDetectorSoftware/jctbDetectorServer/server_funcs.h create mode 100755 slsDetectorSoftware/jctbDetectorServer/sharedmemory.c create mode 100755 slsDetectorSoftware/jctbDetectorServer/sharedmemory.h create mode 120000 slsDetectorSoftware/jctbDetectorServer/sls_detector_defs.h create mode 120000 slsDetectorSoftware/jctbDetectorServer/sls_detector_funcs.h create mode 120000 slsDetectorSoftware/jctbDetectorServer/sls_receiver_defs.h create mode 120000 slsDetectorSoftware/jctbDetectorServer/sls_receiver_funcs.h create mode 100755 slsDetectorSoftware/jctbDetectorServer/stop_server.c diff --git a/slsDetectorSoftware/jctbDetectorServer/Makefile.ctb b/slsDetectorSoftware/jctbDetectorServer/Makefile.ctb new file mode 100644 index 000000000..ca00d71b9 --- /dev/null +++ b/slsDetectorSoftware/jctbDetectorServer/Makefile.ctb @@ -0,0 +1,61 @@ +# $Id: Makefile,v 1.1.1.1 2006/02/04 03:35:01 freza Exp $ +# first compile +# make cris-axis-linux-gnu + + +CROSS = bfin-uclinux- +CC = $(CROSS)gcc + +CFLAGS += -Wall -DMOENCHD -DMCB_FUNCS -DDACS_INT -DDEBUG -DV1 -DCTB #-DVERBOSE #-DVERYVERBOSE #-DVIRTUAL #-DDACS_INT_CSERVER + + +PROGS= jungfrauDetectorServerTest +INSTDIR= /tftpboot +INSTMODE= 0777 + + + +BINS = testlib_sharedlibc +SRCS = server.c server_funcs.c communication_funcs.c firmware_funcs.c mcb_funcs.c sharedmemory.c +OBJS = $(SRCS:%.c=%.o) + + + +all: clean $(PROGS) + +test: clean jungfrauADCTEst + +boot: $(OBJS) + +jungfrauDetectorServerTest: $(OBJS) + echo $(OBJS) + $(CC) $(CFLAGS) -o $@ $^ $(LDLIBS_$@) $(LDFLAGS_$@) + + +jungfrauDetectorServer: $(OBJS) + echo $(OBJS) + $(CC) $(CFLAGS) -o $@ $^ $(LDLIBS_$@) $(LDFLAGS_$@) + +jungfrauADCTEst: $(OBJS) + echo $(OBJS) + $(CC) $(CFLAGS) -o $@ $^ $(LDLIBS_$@) $(LDFLAGS_$@) -DTESTADC + + + + +install: $(PROGS) + $(INSTALL) -d $(INSTDIR) + $(INSTALL) -m $(INSTMODE) $(PROGS) $(INSTDIR) + + +romfs: + $(ROMFSINST) /bin/$(PROGS) + +clean: + rm -rf $(PROGS) *.o *.gdb + + + + + + diff --git a/slsDetectorSoftware/jctbDetectorServer/ansi.h b/slsDetectorSoftware/jctbDetectorServer/ansi.h new file mode 120000 index 000000000..a122db0ad --- /dev/null +++ b/slsDetectorSoftware/jctbDetectorServer/ansi.h @@ -0,0 +1 @@ +../../slsReceiverSoftware/include/ansi.h \ No newline at end of file diff --git a/slsDetectorSoftware/jctbDetectorServer/communication_funcs.c b/slsDetectorSoftware/jctbDetectorServer/communication_funcs.c new file mode 120000 index 000000000..87a4f95d1 --- /dev/null +++ b/slsDetectorSoftware/jctbDetectorServer/communication_funcs.c @@ -0,0 +1 @@ +../commonFiles/communication_funcs.c \ No newline at end of file diff --git a/slsDetectorSoftware/jctbDetectorServer/communication_funcs.h b/slsDetectorSoftware/jctbDetectorServer/communication_funcs.h new file mode 120000 index 000000000..f220903b2 --- /dev/null +++ b/slsDetectorSoftware/jctbDetectorServer/communication_funcs.h @@ -0,0 +1 @@ +../commonFiles/communication_funcs.h \ No newline at end of file diff --git a/slsDetectorSoftware/jctbDetectorServer/firmware_funcs.c b/slsDetectorSoftware/jctbDetectorServer/firmware_funcs.c new file mode 100755 index 000000000..0b623c757 --- /dev/null +++ b/slsDetectorSoftware/jctbDetectorServer/firmware_funcs.c @@ -0,0 +1,3664 @@ +//#define TESTADC +#define TESTADC1 + + +//#define TIMEDBG +#include "server_defs.h" +#include "firmware_funcs.h" +#include "mcb_funcs.h" +#include "registers_m.h" + +//#define VERBOSE +//#define VERYVERBOSE + + +#ifdef SHAREDMEMORY +#include "sharedmemory.h" +#endif + +#include +#include +#include + +#include +#include +#include /* exit() */ +#include /* memset(), memcpy() */ +#include /* uname() */ +#include +#include /* socket(), bind(), + listen(), accept() */ +#include +#include +#include +#include +#include /* fork(), write(), close() */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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; + + +struct timeval tss,tse,tsss; //for timing + + +//for memory mapping +u_int32_t CSP0BASE; + + +FILE *debugfp, *datafp; + +int fr; +int wait_time; +int *fifocntrl; + +//int *statusreg; commented out by dhanya +const int nModY=1; +int nModBoard; +int nModX=NMAXMOD; +int dynamicRange=16;//32; +int nSamples=1; + +int dataBytes=NMAXMOD*NCHIP*NCHAN*2; + +int storeInRAM=0; +int ROI_flag=0; +int adcConfigured=-1; +u_int16_t *ram_values=NULL; +char volatile *now_ptr=NULL; +//u_int32_t volatile *values; +u_int16_t volatile *values; +int ram_size=0; + +int64_t totalTime=1; +u_int32_t progressMask=0; + +int phase_shift=0;//DEFAULT_PHASE_SHIFT; +int ipPacketSize=DEFAULT_IP_PACKETSIZE; +int udpPacketSize=DEFAULT_UDP_PACKETSIZE; + +#ifndef NEW_PLL_RECONFIG +u_int32_t clkDivider[2]={32,16}; +#else +u_int32_t clkDivider[2]={40,20}; +#endif +int32_t clkPhase[2]={0,0}; + +u_int32_t adcDisableMask=0; + +int ififostart, ififostop, ififostep, ififo; + +int masterMode=NO_MASTER, syncMode=NO_SYNCHRONIZATION, timingMode=AUTO_TIMING; + +enum externalSignalFlag signals[4]={EXT_SIG_OFF, EXT_SIG_OFF, EXT_SIG_OFF, EXT_SIG_OFF}; + +int withGotthard = 0; + +/**is not const because this value will change after initDetector, is removed from mcb_funcs.c cuz its not used anywhere + * why is this used anywhere instead of macro*/ +int nChans=NCHAN; +int nChips=NCHIP; +int nDacs=NDAC; +int nAdcs=NADC; + +extern enum detectorType myDetectorType; +/** for jungfrau reinitializing macro later in server_funcs.c in initDetector*/ +extern int N_CHAN; +extern int N_CHIP; +extern int N_DAC; +extern int N_ADC; +extern int N_CHANS; + +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 +#ifdef SHAREDMEMORY + if ( (res=inism(SMSV))<0) { + printf("error attaching shared memory! %i",res); + return FAIL; + } +#endif + printf("CSPObase is 0x%08x \n",CSP0BASE); + printf("CSPOBASE=from %08x to %08x\n",CSP0BASE,CSP0BASE+MEM_SIZE); + + u_int32_t address; + address = FIFO_DATA_REG;//_OFF; + //values=(u_int32_t*)(CSP0BASE+address*2); + values=(u_int16_t*)(CSP0BASE+address*2); + 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; +} + +/** ramType is DARK_IMAGE_REG or GAIN_IMAGE_REG */ +u_int16_t ram_w16(u_int32_t ramType, int adc, int adcCh, int Ch, u_int16_t data) { + unsigned int adr = (ramType | adc << 8 | adcCh << 5 | Ch ); + // printf("Writing to addr:%x\n",adr); + return bus_w16(adr,data); +} + +/** ramType is DARK_IMAGE_REG or GAIN_IMAGE_REG */ +u_int16_t ram_r16(u_int32_t ramType, int adc, int adcCh, int Ch){ + unsigned int adr = (ramType | adc << 8 | adcCh << 5 | Ch ); + // printf("Reading from addr:%x\n",adr); + return bus_r16(adr); +} + +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 setPhaseShiftOnce(){ + u_int32_t addr, reg; + int i; + addr=MULTI_PURPOSE_REG; + reg=bus_r(addr); +#ifdef VERBOSE + printf("Multipurpose reg:%x\n",reg); +#endif + + //Checking if it is power on(negative number) + // if(((reg&0xFFFF0000)>>16)>0){ + //bus_w(addr,0x0); //clear the reg + + if(reg==0){ + printf("\nImplementing phase shift of %d\n",phase_shift); + for (i=1;i2*l) { + h=l+1; + odd=1; + } + printf("Counter %d: Low is %d, High is %d\n",i, l,h); + + + val= (i<<18)| (odd<<17) | l | (h<<8); + + printf("Counter %d, val: %08x\n", i, val); + setPllReconfigReg(PLL_C_COUNTER_REG, val,0); + // usleep(20); + //change sync at the same time as + if (i>0) { + val= (2<<18)| (odd<<17) | l | (h<<8); + + printf("Counter %d, val: %08x\n", i, val); + setPllReconfigReg(PLL_C_COUNTER_REG, val,0); + + } + + } else { + // if (mode==1) { + // } else { + printf("phase in %d\n",clkPhase[1]); + + if (clkPhase[1]>0) { + inv=0; + phase=clkPhase[1]; + } else { + inv=1; + phase=-1*clkPhase[1]; + } + + printf("phase out %d %08x\n",phase,phase); + if (inv) { + val=phase | (1<<16);// | (inv<<21); + printf("**************** phase word %08x\n",val); + + // printf("Phase, val: %08x\n", val); + setPllReconfigReg(PLL_PHASE_SHIFT_REG,val,0); //shifts counter 0 + } else { + + + val=phase ;// | (inv<<21); + printf("**************** phase word %08x\n",val); + + // printf("Phase, val: %08x\n", val); + setPllReconfigReg(PLL_PHASE_SHIFT_REG,val,0); //shifts counter 0 +#ifndef NEW_PLL_RECONFIG + printf("Start reconfig\n"); setPllReconfigReg(PLL_START_REG, 1,0); + + // bus_w(PLL_CNTRL_REG, 0); + printf("Status register\n"); getPllReconfigReg(PLL_STATUS_REG,0); + // sleep(1); + + printf("PLL mode\n"); setPllReconfigReg(PLL_MODE_REG,1,0); + // usleep(10000); + +#endif + printf("**************** phase word %08x\n",val); + + val=phase | (2<<16);// | (inv<<21); + // printf("Phase, val: %08x\n", val); + setPllReconfigReg(PLL_PHASE_SHIFT_REG,val,0); //shifts counter 0 + } + + + } + +#ifndef NEW_PLL_RECONFIG + printf("Start reconfig\n"); setPllReconfigReg(PLL_START_REG, 1,0); + + // bus_w(PLL_CNTRL_REG, 0); + printf("Status register\n"); getPllReconfigReg(PLL_STATUS_REG,0); + // sleep(1); +#endif + // printf("PLL mode\n"); setPllReconfigReg(PLL_MODE_REG,0,0); + usleep(10000); + if (i<2) { + printf("reset pll\n"); + bus_w(PLL_CNTRL_REG,((1<1) + return -1; + + if (ic==1 && d>40) + return -1; + + if (d>160) + return -1; + + if (tot>510) + return -1; + + if (tot<1) + return -1; + + + + clkDivider[ic]=d; + configurePll(ic); + + + + return clkDivider[ic]; +} + + +int phaseStep(int st){ + + if (st>65535 || st<-65535) + return clkPhase[0]; +#ifdef NEW_PLL_RECONFIG + printf("reset pll\n"); + bus_w(PLL_CNTRL_REG,((1<1) + return -1; + return clkDivider[ic]; + + +/* int ic=0; */ +/* u_int32_t val; */ +/* u_int32_t l,h; */ + +/* printf("get clk divider\n"); */ + + +/* setPllReconfigReg(PLL_MODE_REG,1,0); */ +/* getPllReconfigReg(PLL_MODE_REG,0); */ + +/* u_int32_t addr=0xa; //c0 */ +/* if (ic>0) */ +/* addr=0xb; //c1 */ + +/* val=getPllReconfigReg(PLL_N_COUNTER_REG,0); */ +/* printf("Getting N counter %08x\n",val); */ + +/* l=val&0xff; */ +/* h=(val>>8)&0xff; */ + +/* //getPllReconfigReg(PLL_STATUS_REG,0); */ +/* val=getPllReconfigReg(addr,0); */ +/* printf("Getting C counter %08x\n",val); */ + + + +/* return 800/(l+h); */ + +} + + +u_int32_t adcPipeline(int d) { + if (d>=0) + bus_w(DAQ_REG, d); + return bus_r(DAQ_REG)&0xff; +} + + +u_int32_t setSetLength(int d) { + return 0; +} + +u_int32_t getSetLength() { + return 0; +} + +u_int32_t setOversampling(int d) { + + if (d>=0 && d<=255) + bus_w(OVERSAMPLING_REG, d); + + return bus_r(OVERSAMPLING_REG); +} + + +u_int32_t setWaitStates(int d1) { + return 0; +} + +u_int32_t getWaitStates() { + return 0; +} + + +u_int32_t setTotClockDivider(int d) { + return 0; +} + +u_int32_t getTotClockDivider() { + return 0; +} + + +u_int32_t setTotDutyCycle(int d) { + return 0; +} + +u_int32_t getTotDutyCycle() { + return 0; +} + + +u_int32_t setExtSignal(int d, enum externalSignalFlag mode) { + + //int modes[]={EXT_SIG_OFF, EXT_GATE_IN_ACTIVEHIGH, EXT_GATE_IN_ACTIVELOW,EXT_TRIG_IN_RISING,EXT_TRIG_IN_FALLING,EXT_RO_TRIG_IN_RISING, EXT_RO_TRIG_IN_FALLING,EXT_GATE_OUT_ACTIVEHIGH, EXT_GATE_OUT_ACTIVELOW, EXT_TRIG_OUT_RISING, EXT_TRIG_OUT_FALLING, EXT_RO_TRIG_OUT_RISING, EXT_RO_TRIG_OUT_FALLING}; + // int off=d*SIGNAL_OFFSET; + + u_int32_t c; + c=bus_r(EXT_SIGNAL_REG); + + if (d>=0 && d<4) { + signals[d]=mode; +#ifdef VERBOSE + printf("settings signal variable number %d to value %04x\n", d, signals[d]); +#endif + + // if output signal, set it! + + switch (mode) { + case GATE_IN_ACTIVE_HIGH: + case GATE_IN_ACTIVE_LOW: + if (timingMode==GATE_FIX_NUMBER || timingMode==GATE_WITH_START_TRIGGER) + setFPGASignal(d,mode); + else + setFPGASignal(d,SIGNAL_OFF); + break; + case TRIGGER_IN_RISING_EDGE: + case TRIGGER_IN_FALLING_EDGE: + if (timingMode==TRIGGER_EXPOSURE || timingMode==GATE_WITH_START_TRIGGER) + setFPGASignal(d,mode); + else + setFPGASignal(d,SIGNAL_OFF); + break; + case RO_TRIGGER_IN_RISING_EDGE: + case RO_TRIGGER_IN_FALLING_EDGE: + if (timingMode==TRIGGER_READOUT) + setFPGASignal(d,mode); + else + setFPGASignal(d,SIGNAL_OFF); + break; + case MASTER_SLAVE_SYNCHRONIZATION: + setSynchronization(syncMode); + break; + default: + setFPGASignal(d,mode); + break; + } + + setTiming(GET_EXTERNAL_COMMUNICATION_MODE); + } + + +// if (mode<=RO_TRIGGER_OUT_FALLING_EDGE && mode>=0) +// bus_w(EXT_SIGNAL_REG,((modes[mode])<=0) { +#ifdef VERBOSE + printf("writing signal register number %d mode %04x\n",d, modes[mode]); +#endif + bus_w(EXT_SIGNAL_REG,((modes[mode])<>off); + + if (mode=0 && d<4) { +#ifdef VERBOSE + printf("gettings signal variable number %d value %04x\n", d, signals[d]); +#endif + return signals[d]; + } else + return -1; + + +} + + +int getFPGASignal(int d) { + + int modes[]={SIGNAL_OFF, GATE_IN_ACTIVE_HIGH, GATE_IN_ACTIVE_LOW,TRIGGER_IN_RISING_EDGE, TRIGGER_IN_FALLING_EDGE,RO_TRIGGER_IN_RISING_EDGE, RO_TRIGGER_IN_FALLING_EDGE, GATE_OUT_ACTIVE_HIGH, GATE_OUT_ACTIVE_LOW, TRIGGER_OUT_RISING_EDGE, TRIGGER_OUT_FALLING_EDGE, RO_TRIGGER_OUT_RISING_EDGE,RO_TRIGGER_OUT_FALLING_EDGE}; + + int off=d*SIGNAL_OFFSET; + int mode=((bus_r(EXT_SIGNAL_REG)&(SIGNAL_MASK<>off); + + if (mode<=RO_TRIGGER_OUT_FALLING_EDGE) { + if (modes[mode]!=SIGNAL_OFF && signals[d]!=MASTER_SLAVE_SYNCHRONIZATION) + signals[d]=modes[mode]; +#ifdef VERYVERBOSE + printf("gettings signal register number %d value %04x\n", d, modes[mode]); +#endif + return modes[mode]; + } else + return -1; + +} + + + + + +/* +enum externalCommunicationMode{ + GET_EXTERNAL_COMMUNICATION_MODE, + AUTO, + TRIGGER_EXPOSURE_SERIES, + TRIGGER_EXPOSURE_BURST, + TRIGGER_READOUT, + TRIGGER_COINCIDENCE_WITH_INTERNAL_ENABLE, + GATE_FIX_NUMBER, + GATE_FIX_DURATION, + GATE_WITH_START_TRIGGER, + GATE_COINCIDENCE_WITH_INTERNAL_ENABLE +}; +*/ + + +int setTiming(int ti) { + + + int ret=GET_EXTERNAL_COMMUNICATION_MODE; + + int g=-1, t=-1, rot=-1; + + int i; + + switch (ti) { + case AUTO_TIMING: + timingMode=ti; + // disable all gates/triggers in except if used for master/slave synchronization + for (i=0; i<4; i++) { + if (getFPGASignal(i)>0 && getFPGASignal(i)=0 && t>=0 && rot<0) { + ret=GATE_WITH_START_TRIGGER; + } else if (g<0 && t>=0 && rot<0) { + ret=TRIGGER_EXPOSURE; + } else if (g>=0 && t<0 && rot<0) { + ret=GATE_FIX_NUMBER; + } else if (g<0 && t<0 && rot>0) { + ret=TRIGGER_READOUT; + } else if (g<0 && t<0 && rot<0) { + ret=AUTO_TIMING; + } + + // timingMode=ret; + + return ret; + +} + + + +int setConfigurationRegister(int d) { +#ifdef VERBOSE + printf("Setting configuration register to %x",d); +#endif + if (d>=0) { + bus_w(CONFIG_REG,d); + } +#ifdef VERBOSE + printf("configuration register is %x", bus_r(CONFIG_REG)); +#endif + return bus_r(CONFIG_REG); +} + +int setToT(int d) { + //int ret=0; + int reg; +#ifdef VERBOSE + printf("Setting ToT to %d\n",d); +#endif + reg=bus_r(CONFIG_REG); +#ifdef VERBOSE + printf("Before: ToT is %x\n", reg); +#endif + if (d>0) { + bus_w(CONFIG_REG,reg|TOT_ENABLE_BIT); + } else if (d==0) { + bus_w(CONFIG_REG,reg&(~TOT_ENABLE_BIT)); + } + reg=bus_r(CONFIG_REG); +#ifdef VERBOSE + printf("ToT is %x\n", reg); +#endif + if (reg&TOT_ENABLE_BIT) + return 1; + else + return 0; +} + +int setContinousReadOut(int d) { + //int ret=0; + int reg; +#ifdef VERBOSE + printf("Setting Continous readout to %d\n",d); +#endif + reg=bus_r(CONFIG_REG); +#ifdef VERBOSE + printf("Before: Continous readout is %x\n", reg); +#endif + if (d>0) { + bus_w(CONFIG_REG,reg|CONT_RO_ENABLE_BIT); + } else if (d==0) { + bus_w(CONFIG_REG,reg&(~CONT_RO_ENABLE_BIT)); + } + reg=bus_r(CONFIG_REG); +#ifdef VERBOSE + printf("Continous readout is %x\n", reg); +#endif + if (reg&CONT_RO_ENABLE_BIT) + return 1; + else + return 0; +} + + +int startReceiver(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&(~GB10_NOT_CPU_BIT)); + else + bus_w(CONFIG_REG,reg|GB10_NOT_CPU_BIT); + + reg=bus_r(addr); +//#ifdef VERBOSE + printf("Config Reg %x\n", reg); +//#endif + int d =reg&GB10_NOT_CPU_BIT; + if(d!=0) d=1; + if(d!=start) + return OK; + else + return FAIL; +} + + +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; +} + + +// for fpga test +u_int32_t testRAM(void) { + int result=OK; + + printf("TestRAM not implemented\n"); + +/* int i=0; + allocateRAM(); + // while(i<100000) { + memcpy(ram_values, values, dataBytes); + printf ("Testing RAM:\t%d: copied fifo %x to memory %x size %d\n",i++, (unsigned int)(values), (unsigned int)(ram_values), dataBytes); + // } + * +*/ + return result; +} + + +int getNModBoard() { +if(myDetectorType == JUNGFRAU) + return 1; +else + return 32;//nModX; +} + +int setNMod(int n) { + +/* printf("Writin ADC disable register %08x\n",n); */ +/* bus_w(ADC_LATCH_DISABLE_REG,n); */ + return getNMod(); +} + +int getNMod() { +/* u_int32_t reg; */ +/* int i; */ +/* reg=bus_r(ADC_LATCH_DISABLE_REG); */ + +/* printf("Read ADC disable register %08x\n",reg); */ +/* nModX=32; */ +/* for (i=0; i<32; i++) { */ +/* if (reg & (1<> 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; + + printf("reg64(%x,%x) %x %x %llx\n", aLSB, aMSB, vLSB, vMSB, v64); + + return v64; +} + +int64_t setFrames(int64_t value){ + return set64BitReg(value, SET_FRAMES_LSB_REG, SET_FRAMES_MSB_REG); +} + +int64_t getFrames(){ + /*printf("gf");*/ + return get64BitReg(GET_FRAMES_LSB_REG, GET_FRAMES_MSB_REG); +} + +int64_t setExposureTime(int64_t value){ + /* time is in ns */ + if (value!=-1) + value*=(1E-3*clkDivider[0]);//(1E-9*CLK_FREQ); + return set64BitReg(value,SET_EXPTIME_LSB_REG, SET_EXPTIME_MSB_REG)/(1E-3*clkDivider[0]);//(1E-9*CLK_FREQ); +} + +int64_t getExposureTime(){ + return get64BitReg(GET_EXPTIME_LSB_REG, GET_EXPTIME_MSB_REG)/(1E-3*clkDivider[0]);//(1E-9*CLK_FREQ); +} + +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*=(1E-9*CLK_FREQ); + value*=(1E-3*clkDivider[1]); + } + if (value%2==0) { + + printf("Adding one to period: was %08llx ", value); + value+=1; + printf("now is %08llx\n ", value); + + + } else + printf("Period already even is %08llx\n ", value); + + + return set64BitReg(value,SET_PERIOD_LSB_REG, SET_PERIOD_MSB_REG)/(1E-3*clkDivider[0]);//(1E-9*CLK_FREQ); +} + +int64_t getPeriod(){ + return get64BitReg(GET_PERIOD_LSB_REG, GET_PERIOD_MSB_REG)/(1E-3*clkDivider[0]);//(1E-9*CLK_FREQ); +} + +int64_t setDelay(int64_t value){ + /* time is in ns */ + if (value!=-1) { + value*=(1E-3*clkDivider[1]);//(1E-9*CLK_FREQ); + } + return set64BitReg(value,SET_DELAY_LSB_REG, SET_DELAY_MSB_REG)/(1E-3*clkDivider[0]);//(1E-9*CLK_FREQ); +} + +int64_t getDelay(){ + return get64BitReg(GET_DELAY_LSB_REG, GET_DELAY_MSB_REG)/(1E-3*clkDivider[0]);//(1E-9*CLK_FREQ); +} + +int64_t setTrains(int64_t value){ + return set64BitReg(value, SET_CYCLES_LSB_REG, SET_CYCLES_MSB_REG); +} + +int64_t getTrains(){ + return get64BitReg(GET_CYCLES_LSB_REG, GET_CYCLES_MSB_REG); +} + + +int64_t setProbes(int64_t value){ + return 0; +} + + +int64_t setProgress() { + + //????? eventually call after setting the registers + +return 0; + +} + + +int64_t getProgress() { + + + //should be done in firmware!!!! + + return 0; + +} + +int64_t getActualTime(){ + return get64BitReg(GET_ACTUAL_TIME_LSB_REG, GET_ACTUAL_TIME_MSB_REG)/(1E-9*CLK_FREQ); +} + +int64_t getMeasurementTime(){ + int64_t v=get64BitReg(GET_MEASUREMENT_TIME_LSB_REG, GET_MEASUREMENT_TIME_MSB_REG); + // int64_t mask=0x8000000000000000; + // if (v & mask ) { + //#ifdef VERBOSE + // printf("no measurement time left\n"); + //#endif + // return -1E+9; + // } else + return v/(1E-9*CLK_FREQ); +} + +int64_t getFramesFromStart(){ + int64_t v=get64BitReg(FRAMES_FROM_START_LSB_REG, FRAMES_FROM_START_MSB_REG); + int64_t v1=get64BitReg(FRAMES_FROM_START_PG_LSB_REG, FRAMES_FROM_START_PG_MSB_REG); + + printf("Frames from start data streaming %lld\n",v); + printf("Frames from start run control %lld\n",v1); + + // int64_t mask=0x8000000000000000; + // if (v & mask ) { + //#ifdef VERBOSE + // printf("no measurement time left\n"); + //#endif + // return -1E+9; + // } else + return v; +} + + +ROI *setROI(int nroi,ROI* arg,int *retvalsize, int *ret) { + + if(myDetectorType == JUNGFRAU) + cprintf(RED,"ROI Not implemented for Jungfrau yet\n"); + return NULL; + + + ROI retval[MAX_ROIS]; + int i, ich; + adcDisableMask=0xfffffffff; /*warning: integer constant is too large for ‘long’ type,warning: large integer implicitly truncated to unsigned type*/ + + printf("Setting ROI\n"); + if (nroi>=0) { + if (nroi==0) { + adcDisableMask=0; + } else { + for (i=0; i=0 && ichMAX_ROIS) { + *retvalsize-=1; + break; + } + retval[*retvalsize-1].xmin=ich; + retval[*retvalsize-1].xmax=ich; + } else { + if ((adcDisableMask)&(1<<(ich-1))) { + *retvalsize+=1; + if (*retvalsize>MAX_ROIS) { + *retvalsize-=1; + break; + } + retval[*retvalsize-1].xmin=ich; + } + retval[*retvalsize-1].xmax=ich; + } + } + } + getDynamicRange(); + return retval;/*warning: function returns address of local variable*/ + +} + + +int loadImage(int index, short int ImageVals[]){ + + printf("loadImage Not implemented yet\n"); + + /* + 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(ptr,ImageVals ,dataBytes); +#ifdef VERBOSE + printf("\nLoaded x%08x address with image of index %d\n",(unsigned int)(ptr),index); +#endif + */ + + return OK; +} + + + +int64_t getProbes(){ + return 0; +} + + +int setDACRegister(int idac, int val, int imod) { +/* u_int32_t addr, reg, mask; */ +/* int off; */ +/* #ifdef VERBOSE */ +/* if(val==-1) */ +/* printf("Getting dac register%d module %d\n",idac,imod); */ +/* else */ +/* printf("Setting dac register %d module %d to %d\n",idac,imod,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 module %d register is %d\n\n",idac,imod,val); */ +/* #endif */ +/* return val; */ +} + + +int getTemperature(int tempSensor, int imod){ + int val; + imod=0;//ignoring more than 1 mod for now + int i,j,repeats=6; + u_int32_t tempVal=0; +#ifdef VERBOSE + char cTempSensor[2][100]={"ADCs/ASICs","VRs/FPGAs"}; + printf("Getting Temperature of module:%d for the %s for tempsensor:%d\n",imod,cTempSensor[tempSensor],tempSensor); +#endif + bus_w(TEMP_IN_REG,(T1_CLK_BIT)|(T1_CS_BIT)|(T2_CLK_BIT)|(T2_CS_BIT));//standby + bus_w(TEMP_IN_REG,((T1_CLK_BIT)&~(T1_CS_BIT))|(T2_CLK_BIT));//high clk low cs + + for(i=0;i<20;i++) { + //repeats is number of register writes for delay + for(j=0;j>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 of module:%d for the %s is %.2fC\n",imod,cTempSensor[tempSensor],val); +#endif + return val; +} + + + +int initHighVoltage(int val, int imod){ + + + u_int32_t offw,codata; + u_int16_t valw, dacvalue; + int iru,i,ddx,csdx,cdx; + float alpha=0.55, fval=val; + + if (val>=0) { + + if (val<60) { + dacvalue=0; + val=60; + } else if (val>=200) { + dacvalue=0x1; + val=200; + } else { + dacvalue=1.+(200.-val)/alpha; + val=200.-(dacvalue-1)*alpha; + } + printf ("****************************** setting val %d, dacval %d\n",val, dacvalue); + offw=DAC_REG; + + ddx=8; csdx=10; cdx=9; + codata=((dacvalue)&0xff); + + + + + valw=0xffff; bus_w(offw,(valw)); // start point + valw=((valw&(~(0x1<>(7-i))&0x1)< 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; + + printf("IP checksum is 0x%lx\n",checksum); + + return checksum; +} + + + +#ifdef NEW_GBE_INTERFACE +int writeGbeReg(int ivar, uint32_t val, int addr, int interface) { +/* #define GBE_CTRL_WSTROBE 0 */ +/* #define GBE_CTRL_VAR_OFFSET 16 */ +/* #define GBE_CTRL_VAR_MASK 0XF */ +/* #define GBE_CTRL_RAMADDR_OFFSET 24 */ +/* #define GBE_CTRL_RAMADDR_MASK 0X3F */ +/* #define GBE_CTRL_INTERFACE 23 */ + uint32_t ctrl=((ivar&GBE_CTRL_VAR_MASK)<>32)&0xFFFFFFFF; + vals[IPCHECKSUM_ADDR]=checksum; + vals[GBE_DELAY_ADDR]=0; + vals[GBE_RESERVED1_ADDR]=sourceport; + vals[GBE_RESERVED2_ADDR]=interface; + vals[DETECTOR_MAC_L_ADDR]=(sourcemac)&0xFFFFFFFF; + vals[DETECTOR_MAC_H_ADDR]=(sourcemac>>32)&0xFFFFFFFF; + vals[DETECTOR_IP_ADDR]=sourceip; + + for (ivar=0; ivar>32)&0xFFFFFFFF);//rx_udpmacH_AReg_c + bus_w(RX_UDPMACL_AREG,(destmac)&0xFFFFFFFF);//rx_udpmacL_AReg_c + bus_w(DETECTORMACH_AREG,(sourcemac>>32)&0xFFFFFFFF);//detectormacH_AReg_c + bus_w(DETECTORMACL_AREG,(sourcemac)&0xFFFFFFFF);//detectormacL_AReg_c + bus_w(UDPPORTS_AREG,((sourceport&0xFFFF)<<16)+(destport&0xFFFF));//udpports_AReg_c + bus_w(IPCHKSUM_AREG,(checksum&0xFFFF));//ipchksum_AReg_c + + +#endif + + bus_w(CONTROL_REG,GB10_RESET_BIT); + sleep(1); + bus_w(CONTROL_REG,0); + usleep(10000); + bus_w(CONFIG_REG,conf | GB10_NOT_CPU_BIT); + printf("System status register is %08x\n",bus_r(SYSTEM_STATUS_REG)); + +return 0; //any value doesnt matter - dhanya + +} + + + + + + + + + + + +int configureMAC(uint32_t destip,uint64_t destmac,uint64_t sourcemac,int sourceip,int ival,uint32_t destport) { +//int configureMAC(int ipad,long long int macad,long long int detectormacad, int detipad, int ival, int udpport){ + + uint32_t sourceport = 0x7e9a; // 0xE185; + int interface=0; + int ngb; +volatile u_int32_t conf= bus_r(CONFIG_REG); + + + + + +#ifdef NEW_GBE_INTERFACE + ngb=2; + printf("--------- New XGB interface\n"); +#else + ngb=1; + printf("********* Old XGB interface\n"); +#endif + + for (interface=0; interface >((i)*2))==3) { *\/ */ +/* /\* i++; *\/ */ +/* /\* if (i>15) *\/ */ +/* /\* break; *\/ */ +/* /\* } *\/ */ +/* /\* if (i<16) { *\/ */ +/* bus_w16(DUMMY_REG,i); */ +/* } */ +/* val=*values; */ + + + // bus_w16(DUMMY_REG,0); // + for (i=0; i<32; i++) { + + + // bus_w16(DUMMY_REG,i); + // bus_r16(DUMMY_REG); +/* dum=(((u_int16_t*)(now_ptr))+i); */ +/* *dum=bus_r16(FIFO_DATA_REG); */ +/* a=bus_r16(FIFO_DATA_REG); */ + //dum=(((u_int32_t*)(now_ptr))+i); + + // a=*values;//bus_r(FIFO_DATA_REG); + // if ((adcDisableMask&(3<<(i*2)))==0) { + *((u_int16_t*)now_ptr)=bus_r16(FIFO_DATA_REG);//*values;//bus_r(FIFO_DATA_REG); + + + if (i!=0 || ns!=0) { + a=0; + while (*((u_int16_t*)now_ptr)==*((u_int16_t*)(now_ptr)-1) && a++<10) { + + // printf("******************** %d: fifo %d: new %08x old %08x\n ",ns, i, *((u_int32_t*)now_ptr),*((u_int32_t*)(now_ptr)-1)); + *((u_int16_t*)now_ptr)=bus_r16(FIFO_DATA_REG);//*values; + // printf("%d-",i); + + } + } + now_ptr+=2;//4; + // } +/* while (((adcDisableMask&(3<<((i+1)*2)))>>((i+1)*2))==3) { */ +/* i++; */ +/* } */ + + // if (((adcDisableMask&(3<<((i+1)*2)))>>((i+1)*2))!=3) { + + bus_w16(DUMMY_REG,i+1); + + a = bus_r(LOOK_AT_ME_REG); + //#ifdef VERBOSE + printf("%d %08x\n",i,a); + // } + // *(((u_int16_t*)(now_ptr))+i)=bus_r16(FIFO_DATA_REG); + } + // bus_w16(DUMMY_REG,0); // +/* #ifdef TIMEDBG */ + +/* gettimeofday(&tss,NULL); */ +/* printf("read data loop = %ld usec\n",(tss.tv_usec) - (tse.tv_usec)); */ + +/* #endif */ +//#ifdef VERBOSE + // printf("*"); + //#endif + return ram_values; +} + + + +u_int16_t* fifo_read_frame() +{ +#ifdef TIMEDBG + gettimeofday(&tsss,NULL); +#endif + + // u_int16_t *dum; + int ns=0; + now_ptr=(char*)ram_values; + while(ns>(ipos))&0x1; + ichan++; + } + } + break; + case 4: + for (ibyte=0; ibyte>(ipos*4))&0xf; + ichan++; + } + } + break; + case 8: + for (ichan=0; ichan0) { + dynamicRange=16; + nSamples=dr/16; + bus_w(NSAMPLES_REG,nSamples); + } + getDynamicRange(); + allocateRAM(); + printf("Setting dataBytes to %d: dr %d; samples %d\n",dataBytes, dynamicRange, nSamples); + return getDynamicRange(); +} + + + + + + +int getDynamicRange() { + if(myDetectorType == JUNGFRAU){ + dynamicRange=16; + return dynamicRange; + } + + nSamples=bus_r(NSAMPLES_REG); + getChannels(); + dataBytes=nModX*N_CHIP*getChannels()*2; + return dynamicRange*bus_r(NSAMPLES_REG);//nSamples; +} + +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 (i0) + storeInRAM=1; + else + storeInRAM=0; + return allocateRAM(); +} + +int getChannels() { + int nch=32; + int i; + for (i=0; i1) { + + clearRAM(); + ram_values=malloc(size); + // ram_values=realloc(ram_values,size)+2; + // if (ram_values) + // break; + // nSamples--; + //} + + if (ram_values) { + now_ptr=(char*)ram_values; + + //#ifdef VERBOSE + printf("ram allocated 0x%x of size %d to %x\n",(int)now_ptr,(unsigned int) size,(unsigned int)(now_ptr+size)); + //#endif + ram_size=size; + return OK; + } + + + printf("Fatal error: there must be a memory leak somewhere! You can't allocate even one frame!\n"); + return FAIL; + + + + +} + + +int writeADC(int addr, int val) { + + + u_int32_t valw,codata,csmask; + int i,cdx,ddx; + cdx=0; ddx=1; + csmask=0xfc; // 1111100 + + codata=val + (addr<< 8); + printf("***** ADC SPI WRITE TO REGISTER %04X value %04X\n",addr,val); + // start point + valw=0xff; + bus_w16(ADC_WRITE_REG,(valw)); + + //chip sel bar down + valw=((0xffffffff&(~csmask))); + bus_w16(ADC_WRITE_REG,valw); + + for (i=0;i<24;i++) { + //cldwn + valw=valw&(~(0x1<>(23-i))&0x1)<> 8); + // printf("%i: %i %i\n",a, frame[a],v); + avg[a] += ((double)frame[a])/(double)frames; + //if(frame[a] == 8191) + // printf("ch %i: %u\n",a,frame[a]); + } + // printf("********\n"); + numberFrames++; + } + + //no more data or no data + else { + if(getFrames()>-2) { + dataret=FAIL; + printf("no data and run stopped: %d frames left\n",(int)(getFrames()+2)); + + } else { + dataret=FINISHED; + printf("acquisition successfully finished\n"); + + } + printf("dataret %d\n",dataret); + } + } + + + + //double nf = (double)numberFrames; + for(i =0; i < 1280; i++){ + adc = i / 256; + adcCh = (i - adc * 256) / 32; + Ch = i - adc * 256 - adcCh * 32; + adc--; + double v2 = avg[i]; + avg[i] = avg[i]/ ((double)numberFrames/(double)frames); + unsigned short v = (unsigned short)avg[i]; + printf("setting avg for channel %i(%i,%i,%i): %i (double= %f (%f))\t", i,adc,adcCh,Ch, v,avg[i],v2); + v=i*100; + ram_w16(DARK_IMAGE_REG,adc,adcCh,Ch,v-4096); + if(ram_r16(DARK_IMAGE_REG,adc,adcCh,Ch) != v-4096){ + printf("value is wrong (%i,%i,%i): %i \n",adc,adcCh,Ch, ram_r16(DARK_IMAGE_REG,adc,adcCh,Ch)); + } + } + + /*for(adc = 1; adc < 5; adc++){ + for(adcCh = 0; adcCh < 8; adcCh++){ + for(Ch=0 ; Ch < 32; Ch++){ + int channel = (adc+1) * 32 * 8 + adcCh * 32 + Ch; + double v2 = avg[channel]; + avg[channel] = avg[channel]/ ((double)numberFrames/(double)frames); + unsigned short v = (unsigned short)avg[channel]; + printf("setting avg for channel %i: %i (double= %f (%f))\t", channel, v,avg[channel],v2); + ram_w16(DARK_IMAGE_REG,adc,adcCh,Ch,v-4096); + if(ram_r16(DARK_IMAGE_REG,adc,adcCh,Ch) != v-4096){ + printf("value is wrong (%i,%i,%i): %i \n",adc,adcCh,Ch, ram_r16(DARK_IMAGE_REG,adc,adcCh,Ch)); + } + } + } + }*/ + + + + printf("frames: %i\n",numberFrames); + printf("corrected avg by: %f\n",(double)numberFrames/(double)frames); + + printf("restoring previous condition\n"); + setFrames(framesBefore); + setPeriod(periodBefore); + + printf("---------------------------\n"); + return 0; +} +uint64_t readPatternWord(int addr) { + uint64_t word=0; + int cntrl=0; + + if (addr>=MAX_PATTERN_LENGTH) + return -1; + + + printf("read %x\n",addr); + cntrl= (addr&APATTERN_MASK) << PATTERN_CTRL_ADDR_OFFSET; + bus_w(PATTERN_CNTRL_REG, cntrl); + usleep(1000); + bus_w(PATTERN_CNTRL_REG, cntrl | (1<< PATTERN_CTRL_READ_BIT) ); + usleep(1000); + printf("reading\n"); + word=get64BitReg(PATTERN_OUT_LSB_REG,PATTERN_OUT_MSB_REG); + printf("read %llx\n", word); + usleep(1000); + bus_w(PATTERN_CNTRL_REG, cntrl); + printf("done\n"); + + return word; +} + +uint64_t writePatternWord(int addr, uint64_t word) { + + + int cntrl=0; + if (addr>=MAX_PATTERN_LENGTH) + return -1; + + printf("write %x %llx\n",addr, word); + if (word!=-1){ + + set64BitReg(word,PATTERN_IN_REG_LSB,PATTERN_IN_REG_MSB); + + + cntrl= (addr&APATTERN_MASK) << PATTERN_CTRL_ADDR_OFFSET; + bus_w(PATTERN_CNTRL_REG, cntrl); + usleep(1000); + bus_w(PATTERN_CNTRL_REG, cntrl | (1<< PATTERN_CTRL_WRITE_BIT) ); + usleep(1000); + bus_w(PATTERN_CNTRL_REG, cntrl); + return word; + } else + return readPatternWord(addr); +} +uint64_t writePatternIOControl(uint64_t word) { + if (word!=0xffffffffffffffff) { /*warning: integer constant is too large for ‘long’ type*/ + // printf("%llx %llx %lld",get64BitReg(PATTERN_IOCTRL_REG_LSB,PATTERN_IOCTRL_REG_MSB),word); + set64BitReg(word,PATTERN_IOCTRL_REG_LSB,PATTERN_IOCTRL_REG_MSB); + // printf("************ write IOCTRL (%x)\n",PATTERN_IOCTRL_REG_MSB); + } + return get64BitReg(PATTERN_IOCTRL_REG_LSB,PATTERN_IOCTRL_REG_MSB); + +} +uint64_t writePatternClkControl(uint64_t word) { + if (word!=0xffffffffffffffff) set64BitReg(word,PATTERN_IOCLKCTRL_REG_LSB,PATTERN_IOCLKCTRL_REG_MSB);/*warning: integer constant is too large for ‘long’ type*/ + return get64BitReg(PATTERN_IOCLKCTRL_REG_LSB,PATTERN_IOCLKCTRL_REG_MSB); + +} + +int setPatternLoop(int level, int *start, int *stop, int *n) { + int ret=OK; + int lval=0; + + int nreg; + int areg; + + switch (level ) { + case 0: + nreg=PATTERN_N_LOOP0_REG; + areg=PATTERN_LOOP0_AREG; + break; + case 1: + nreg=PATTERN_N_LOOP1_REG; + areg=PATTERN_LOOP1_AREG; + break; + case 2: + nreg=PATTERN_N_LOOP2_REG; + areg=PATTERN_LOOP2_AREG; + break; + case -1: + nreg=-1; + areg=PATTERN_LIMITS_AREG; + break; + default: + return FAIL; + } + + printf("level %d start %x stop %x nl %d\n",level, *start, *stop, *n); + if (nreg>=0) { + if ((*n)>=0) bus_w(nreg, *n); + printf ("n %d\n",*n); + *n=bus_r(nreg); + printf ("n %d\n",*n); + + } + + printf("level %d start %x stop %x nl %d\n",level, *start, *stop, *n); + lval=bus_r(areg); +/* printf("l=%x\n",bus_r16(areg)); */ +/* printf("m=%x\n",bus_r16_m(areg)); */ + + + + + + printf("lval %x\n",lval); + if (*start==-1) *start=(lval>> ASTART_OFFSET) & APATTERN_MASK; + printf("start %x\n",*start); + + + if (*stop==-1) *stop=(lval>> ASTOP_OFFSET) & APATTERN_MASK; + printf("stop %x\n",*stop); + + lval= ((*start & APATTERN_MASK) << ASTART_OFFSET) | ((*stop & APATTERN_MASK) << ASTOP_OFFSET); + printf("lval %x\n",lval); + + bus_w(areg,lval); + printf("lval %x\n",lval); + + + return ret; +} + + +int setPatternWaitAddress(int level, int addr) { + int reg; + + switch (level) { + case 0: + reg=PATTERN_WAIT0_AREG; + break; + case 1: + reg=PATTERN_WAIT1_AREG; + break; + case 2: + reg=PATTERN_WAIT2_AREG; + break; + default: + return -1; + }; + // printf("BEFORE *********PATTERN IOCTRL IS %llx (%x)\n",writePatternIOControl(-1), PATTERN_IOCTRL_REG_MSB); + + // printf ("%d addr %x (%x)\n",level,addr,reg); + if (addr>=0) bus_w(reg, addr); + // printf ("%d addr %x %x (%x) \n",level,addr, bus_r(reg), reg); + + // printf("AFTER *********PATTERN IOCTRL IS %llx (%x)\n",writePatternIOControl(-1), PATTERN_IOCTRL_REG_MSB); + + return bus_r(reg); +} + + +uint64_t setPatternWaitTime(int level, uint64_t t) { + int reglsb; + int regmsb; + + + switch (level) { + case 0: + reglsb=PATTERN_WAIT0_TIME_REG_LSB; + regmsb=PATTERN_WAIT0_TIME_REG_MSB; + break; + case 1: + reglsb=PATTERN_WAIT1_TIME_REG_LSB; + regmsb=PATTERN_WAIT1_TIME_REG_MSB; + break; + case 2: + reglsb=PATTERN_WAIT2_TIME_REG_LSB; + regmsb=PATTERN_WAIT2_TIME_REG_MSB; + break; + default: + return -1; + } + + + if (t>=0) set64BitReg(t,reglsb,regmsb); + return get64BitReg(reglsb,regmsb); + +} + + +void initDac(int dacnum) { + + + u_int32_t offw,codata; + u_int16_t valw; + int i,ddx,csdx,cdx; + + + + //setting int reference + offw=DAC_REG; + + + ddx=0; cdx=1; + csdx=dacnum/8+2; + + + printf("data bit=%d, clkbit=%d, csbit=%d",ddx,cdx,csdx); + codata=((((0x6)<<4)+((0xf))<<16)+((0x0<<4)&0xfff0)); /*warning: suggest parentheses around + or - inside shift*/ + + valw=0xffff; bus_w(offw,(valw)); // start point + valw=((valw&(~(0x1<>(24-i))&0x1)<>(24-i))&0x1)); + + + valw=((valw&(~(0x1<>16)&0xffff; */ +/* else */ +/* return retval&0xffff; */ + +} + + + + +int setPower(int ind, int val) { + int dacindex=-1; + int dacval=-1; + int pwrindex=-1; + int retval=-1; + int retval1=-1; + + u_int32_t preg; + + int vchip=2700-(getDacRegister(19)*1000)/4095; + int vmax=vchip-200; + int vmin=600; + + printf("---------------------------------------------Current V_Chip is %d mV\n",vchip); + + switch (ind) { + + case V_POWER_CHIP: + dacindex=19; + pwrindex=-1; + break; + case V_POWER_A: + dacindex=22; + pwrindex=1; + break; + case V_POWER_B: + dacindex=21; + pwrindex=2; + break; + case V_POWER_C: + dacindex=20; + pwrindex=3; + break; + case V_POWER_D: + dacindex=18; + pwrindex=4; + break; + case V_POWER_IO: + dacindex=23; + pwrindex=0; + break; + default: + pwrindex=-1; + dacindex=-1; + } + + if (val==-1) { + printf("get\n"); + dacval=-1; + } else { + if (pwrindex>=0) { + printf("vpower\n"); + dacval=((vmax-val)*4095)/(vmax-vmin); + if (dacval<0) + dacval=0; + if (dacval>4095) + dacval=-100; + if (val==-100) + dacval=-100; + + } else { + printf("vchip\n"); + dacval=((2700-val)*4095)/1000; + if (dacval<0) + dacval=0; + if (dacval>4095) + dacval=4095; + } + } + + if (pwrindex>=0 && val!=-1) { + preg=bus_r(POWER_ON_REG); + printf("power reg is %08x\n",bus_r(POWER_ON_REG)); + printf("Switching off power %d\n", pwrindex); + bus_w(POWER_ON_REG,preg&(~(1<<(16+pwrindex)))); + setDac(dacindex,-100); + printf("power reg is %08x\n",bus_r(POWER_ON_REG)); + retval=0; + } + + if (dacindex>0 && dacval!=-100) { + + printf("Setting power %d to %d mV\n",ind,val); + printf("Setting DAC %d to value %d\n",dacindex,dacval); + retval=setDac(dacindex,dacval); + if (pwrindex>=0 && dacval>=0 ) { + preg=bus_r(POWER_ON_REG); + printf("power reg is %08x\n",bus_r(POWER_ON_REG)); + printf("Switching on power %d\n", pwrindex); + bus_w(POWER_ON_REG,preg|((1<<(16+pwrindex)))); + printf("power reg is %08x\n",bus_r(POWER_ON_REG)); + } + } + + if (pwrindex>=0) { + if (bus_r(POWER_ON_REG)&(1<<(16+pwrindex))){ + retval1=vmax-(retval*1900)/4095; + vmax=2700-(getDacRegister(19)*1000)/4095-200; + if (retval1>vmax) + retval1=vmax; + if (retval1=0) + retval1=2700-(retval*1000)/4095; + else + retval1=-1; + } + + /* switch (ind) { */ +/* case V_POWER_A: */ +/* break; */ +/* case V_POWER_B: */ +/* break; */ +/* case V_POWER_C: */ +/* break; */ +/* case V_POWER_D: */ +/* break; */ +/* case V_POWER_IO: */ +/* break; */ +/* case V_POWER_CHIP: */ +/* break; */ +/* default: */ +/* retval1=retval; */ +/* } */ + + + return retval1; + + +} + + + + + + + + + + + + + + + + +int nextDac(){ + + u_int32_t offw,codata; + u_int16_t valw=bus_r(offw); + int i,ddx,csdx,cdx; + + int dacch=0; + + + // printf("**************************************************next dac\n"); + //setting int reference + offw=DAC_REG; + + + ddx=0; cdx=1; + + csdx=2; + + valw=0xffff&(~(0x1<>(24-i)))&0x1); + + valw=(valw&(~(0x1<>(24-i))&0x1)<>(24-i))&0x1)); + + + valw=((valw&(~(0x1<=0) { + + + + // printf("data bit=%d, clkbit=%d, csbit=%d",ddx,cdx,csdx); + + //modified to power down single channels + + // codata=((((0x2)<<4)+((dacch)&0xf))<<16)+((dacvalue<<4)&0xfff0); + codata=(0x3)<>(24-i)))&0x1); + valw=(valw&(~(0x1<>(24-i))&0x1)<>(24-i))&0x1)); + + + valw=((valw&(~(0x1< +#include +#include +#include +#include +#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 setPhaseShiftOnce(); +int phaseStep(int st); +int getPhase(); +int cleanFifo(); +int setDAQRegister(); + +u_int32_t putout(char *s, int modnum); +u_int32_t readin(int modnum); +u_int32_t setClockDivider(int d, int ic); +u_int32_t getClockDivider(int ic); + +void resetPLL(); +u_int32_t setPllReconfigReg(u_int32_t reg, u_int32_t val, int trig); +u_int32_t getPllReconfigReg(u_int32_t reg, int trig); + +u_int32_t setSetLength(int d); +u_int32_t getSetLength(); +u_int32_t setWaitStates(int d); +u_int32_t getWaitStates(); +u_int32_t setTotClockDivider(int d); +u_int32_t getTotClockDivider(); +u_int32_t setTotDutyCycle(int d); +u_int32_t getTotDutyCycle(); +u_int32_t setOversampling(int d); +u_int32_t adcPipeline(int d); + +u_int32_t setExtSignal(int d, enum externalSignalFlag mode); +int getExtSignal(int d); + +u_int32_t setFPGASignal(int d, enum externalSignalFlag mode); +int getFPGASignal(int d); + +int setTiming(int t); + + +int setConfigurationRegister(int d); +int setToT(int d); +int setContinousReadOut(int d); +int startReceiver(int d); + +int setDACRegister(int idac, int val, int imod); +int getDacRegister(int dacnum); + + +int getTemperature(int tempSensor,int imod); +int initHighVoltage(int val,int imod); +int initConfGain(int isettings,int val,int imod); + +int setADC(int adc); +//int configureMAC(int ipad, long long int macad, long long int detectormacadd, int detipad, int ival, int udpport); +int configureMAC(uint32_t destip,uint64_t destmac,uint64_t sourcemac,int detipad,int ival,uint32_t destport); +int getAdcConfigured(); + + +u_int64_t getDetectorNumber(); +u_int32_t getFirmwareVersion(); +u_int32_t getFirmwareSVNVersion(); + +int testFifos(void); +u_int32_t testFpga(void); +u_int32_t testRAM(void); +int testBus(void); +int setDigitalTestBit(int ival); + +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 setDelay(int64_t value); +int64_t getDelay(); + +int64_t setPeriod(int64_t value); +int64_t getPeriod(); + +int64_t setTrains(int64_t value); +int64_t getTrains(); + +int64_t setProbes(int64_t value); +int64_t getProbes(); + +int64_t getProgress(); +int64_t setProgress(); + +int64_t getActualTime(); +int64_t getMeasurementTime(); +int64_t getFramesFromStart(); + +u_int32_t runBusy(void); +u_int32_t runState(void); +u_int32_t dataPresent(void); + + +int startStateMachine(); +int stopStateMachine(); +int startReadOut(); +u_int32_t fifoReset(void); +u_int32_t fifoReadCounter(int fifonum); +u_int32_t fifoReadStatus(); + + +u_int32_t fifo_full(void); + + + +u_int16_t* fifo_read_event(int ns); +u_int16_t* fifo_read_frame(); +u_int32_t* decode_data(int* datain); +//u_int32_t move_data(u_int64_t* datain, u_int64_t* dataout); +int setDynamicRange(int dr); +int getDynamicRange(); +int getNModBoard(); +int setNMod(int n); +int getNMod(); + +int setStoreInRAM(int b); +int allocateRAM(); + + +int writeADC(int addr, int val); +int prepareADC(); + + +int clearRAM(); + + +int setMaster(int f); +int setSynchronization(int s); + +int loadImage(int index, short int ImageVals[]); +int readCounterBlock(int startACQ, short int CounterVals[]); +int resetCounterBlock(int startACQ); + +int calibratePedestal(int frames); + +uint64_t writePatternWord(int addr, uint64_t word); +uint64_t writePatternIOControl(uint64_t word); +uint64_t writePatternClkControl(uint64_t word); +int setPatternLoop(int level, int *start, int *stop, int *n); +int setPatternWaitAddress(int level, int addr); +uint64_t setPatternWaitTime(int level, uint64_t t); + + +void initDac(int dacnum); +int setDac(int dacnum,int dacvalue); + +int setPower(int ind, int val); + +ROI *setROI(int nroi,ROI* arg,int *retvalsize, int *ret); +int getChannels(); + +/* + +u_int32_t setNBits(u_int32_t); +u_int32_t getNBits(); +*/ + +/* +//move to mcb_funcs? + +int readOutChan(int *val); +u_int32_t getModuleNumber(int modnum); +int testShiftIn(int imod); +int testShiftOut(int imod); +int testShiftStSel(int imod); +int testDataInOut(int num, int imod); +int testExtPulse(int imod); +int testExtPulseMux(int imod, int ow); +int testDataInOutMux(int imod, int ow, int num); +int testOutMux(int imod); +int testFpgaMux(int imod); +int calibration_sensor(int num, int *values, int *dacs) ; +int calibration_chip(int num, int *values, int *dacs); +*/ + + +#endif diff --git a/slsDetectorSoftware/jctbDetectorServer/gitInfoMoench.h b/slsDetectorSoftware/jctbDetectorServer/gitInfoMoench.h new file mode 100644 index 000000000..270653967 --- /dev/null +++ b/slsDetectorSoftware/jctbDetectorServer/gitInfoMoench.h @@ -0,0 +1,11 @@ +//#define SVNPATH "" +#define SVNURL "git@gitorious.psi.ch:sls_det_software/sls_detector_software.git/moenchDetectorServer" +//#define SVNREPPATH "" +#define SVNREPUUID "046a469b1e6582c4c55bd6eaeb4818b618d0a9a9" +//#define SVNREV 0x14 +//#define SVNKIND "" +//#define SVNSCHED "" +#define SVNAUTH "Maliakal_Dhanya" +#define SVNREV 0x14 +#define SVNDATE 0x20140603 +// diff --git a/slsDetectorSoftware/jctbDetectorServer/gitInfoMoenchTmp.h b/slsDetectorSoftware/jctbDetectorServer/gitInfoMoenchTmp.h new file mode 100644 index 000000000..58e48f497 --- /dev/null +++ b/slsDetectorSoftware/jctbDetectorServer/gitInfoMoenchTmp.h @@ -0,0 +1,11 @@ +//#define SVNPATH "" +#define SVNURL "" +//#define SVNREPPATH "" +#define SVNREPUUID "" +//#define SVNREV "" +//#define SVNKIND "" +//#define SVNSCHED "" +#define SVNAUTH "" +#define SVNREV "" +#define SVNDATE "" +// diff --git a/slsDetectorSoftware/jctbDetectorServer/jungfrauDetectorServerTest b/slsDetectorSoftware/jctbDetectorServer/jungfrauDetectorServerTest new file mode 100755 index 0000000000000000000000000000000000000000..25804a0ba74080451a4934de3a2f66eb4f1a6409 GIT binary patch literal 134952 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 literal 0 HcmV?d00001 diff --git a/slsDetectorSoftware/jctbDetectorServer/mcb_funcs.c b/slsDetectorSoftware/jctbDetectorServer/mcb_funcs.c new file mode 100755 index 000000000..edf99652a --- /dev/null +++ b/slsDetectorSoftware/jctbDetectorServer/mcb_funcs.c @@ -0,0 +1,2701 @@ +#ifdef MCB_FUNCS + +#include +#include +#include +#include +#include +#include "registers_m.h" + +#ifndef PICASSOD +#include "server_defs.h" +#else +#include "picasso_defs.h" +#endif +#include "firmware_funcs.h" +#include "mcb_funcs.h" + + +/* global variables */ +#undef DEBUG +#undef DEBUGOUT + +extern int nModX; +//extern int dataBytes; +extern int dynamicRange; +enum detectorSettings thisSettings; + +int sChan, sChip, sMod, sDac, sAdc; +const int allSelected=-2; +const int noneSelected=-1; + + +sls_detector_module *detectorModules=NULL; +int *detectorChips=NULL; +int *detectorChans=NULL; +int *detectorDacs=NULL; +int *detectorAdcs=NULL; +//int numberOfProbes; + +ROI rois[MAX_ROIS]; +int nROI=0; +extern enum detectorType myDetectorType; + +/** for jungfrau reinitializing macro later in server_funcs.c in initDetector*/ +extern int N_CHAN; +extern int N_CHIP; +extern int N_DAC; +extern int N_ADC; +extern int N_CHANS; + +extern int nChans; +extern int nChips; +extern int nDacs; +extern int nAdcs; + +int initDetector() { + + int imod; + // sls_detector_module *myModule; + int n=getNModBoard(); + nModX=n; + +#ifdef VERBOSE + printf("Board is for %d modules\n",n); +#endif + + if(myDetectorType == JUNGFRAU){ + N_CHAN=JUNGFRAU_NCHAN; + N_CHIP=JUNGFRAU_NCHIP; + N_DAC=JUNGFRAU_NDAC; + N_ADC=JUNGFRAU_NADC; + N_CHANS=JUNGFRAU_NCHANS; + + nChans=N_CHAN; + nChips=N_CHIP; + nDacs=N_DAC; + nAdcs=N_ADC; + } + + detectorModules=malloc(n*sizeof(sls_detector_module)); + detectorDacs=malloc(n*N_DAC*sizeof(int)); + detectorAdcs=malloc(n*N_ADC*sizeof(int)); + detectorChips=NULL; + detectorChans=NULL; + detectorAdcs=NULL; + if(myDetectorType != JUNGFRAU){ + detectorChips=malloc(n*N_CHIP*sizeof(int)); + detectorChans=malloc(n*N_CHIP*N_CHAN*sizeof(int)); + } + +#ifdef VERBOSE + printf("modules from 0x%x to 0x%x\n",(unsigned int)(detectorModules), (unsigned int)(detectorModules+n)); + printf("dacs from 0x%x to 0x%x\n",(unsigned int)(detectorDacs), (unsigned int)(detectorDacs+n*N_DAC)); + printf("adcs from 0x%x to 0x%x\n",(unsigned int)(detectorAdcs), (unsigned int)(detectorAdcs+n*N_ADC)); + if(myDetectorType != JUNGFRAU){ + printf("chips from 0x%x to 0x%x\n",(unsigned int)(detectorChips), (unsigned int)(detectorChips+n*N_CHIP)); + printf("chans from 0x%x to 0x%x\n",(unsigned int)(detectorChans), (unsigned int)(detectorChans+n*N_CHIP*N_CHAN)); + } +#endif + + + for (imod=0; imoddacs=detectorDacs+imod*N_DAC; + (detectorModules+imod)->adcs=detectorAdcs+imod*N_ADC; + if(myDetectorType != JUNGFRAU){ + (detectorModules+imod)->chipregs=detectorChips+imod*N_CHIP; + (detectorModules+imod)->chanregs=detectorChans+imod*N_CHIP*N_CHAN; + } + (detectorModules+imod)->ndac=N_DAC; + (detectorModules+imod)->nadc=N_ADC; + (detectorModules+imod)->nchip=N_CHIP; + (detectorModules+imod)->nchan=N_CHIP*N_CHAN; + (detectorModules+imod)->module=imod; + (detectorModules+imod)->gain=0; + (detectorModules+imod)->offset=0; + (detectorModules+imod)->reg=0; + /* initialize registers, dacs, retrieve sn, adc values etc */ + } + thisSettings=UNINITIALIZED; + sChan=noneSelected; + sChip=noneSelected; + sMod=noneSelected; + sDac=noneSelected; + sAdc=noneSelected; + + /* + setCSregister(ALLMOD); //commented out by dhanya + setSSregister(ALLMOD); + counterClear(ALLMOD); + clearSSregister(ALLMOD); + putout("0000000000000000",ALLMOD); + */ + + /* initialize dynamic range etc. */ + /* dynamicRange=getDynamicRange(); //always 16 not required commented out + nModX=setNMod(-1);*/ + + // dynamicRange=32; + // initChip(0, 0,ALLMOD); + //nModX=n; + // + allocateRAM(); + + return OK; +} + + + + +int copyChannel(sls_detector_channel *destChan, sls_detector_channel *srcChan) { + destChan->chan=srcChan->chan; + destChan->chip=srcChan->chip; + destChan->module=srcChan->module; + destChan->reg=srcChan->reg; + return OK; +} + + +int copyChip(sls_detector_chip *destChip, sls_detector_chip *srcChip) { + + int ichan; + int ret=OK; + if ((srcChip->nchan)>(destChip->nchan)) { + printf("Number of channels of source is larger than number of channels of destination\n"); + return FAIL; + } + + destChip->nchan=srcChip->nchan; + destChip->reg=srcChip->reg; + destChip->chip=srcChip->chip; + destChip->module=srcChip->module; + for (ichan=0; ichan<(srcChip->nchan); ichan++) { + *((destChip->chanregs)+ichan)=*((srcChip->chanregs)+ichan); + } + return ret; +} + + +int copyModule(sls_detector_module *destMod, sls_detector_module *srcMod) { + + int ichip, idac, ichan, iadc; + + int ret=OK; + +#ifdef VERBOSE + printf("Copying module %x to module %x\n",(unsigned int)(srcMod),(unsigned int)(destMod)); +#endif + + if (srcMod->module>=0) { +#ifdef VERBOSE + printf("Copying module number %d to module number %d\n",srcMod->module,destMod->module); +#endif + destMod->module=srcMod->module; + } + if (srcMod->serialnumber>=0){ +/* #ifdef VERBOSE */ +/* printf("Copying module serial number %x to module serial number %x\n",srcMod->serialnumber,destMod->serialnumber); */ +/* #endif */ + 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; + + // printf("copying gain and offset %f %f to %f %f\n",srcMod->gain,srcMod->offset,destMod->gain,destMod->offset); + + if(myDetectorType != JUNGFRAU){ + for (ichip=0; ichip<(srcMod->nchip); ichip++) { + if (*((srcMod->chipregs)+ichip)>=0) + *((destMod->chipregs)+ichip)=*((srcMod->chipregs)+ichip); + } + for (ichan=0; ichan<(srcMod->nchan); ichan++) { + if (*((srcMod->chanregs)+ichan)>=0) + *((destMod->chanregs)+ichan)=*((srcMod->chanregs)+ichan); + } + } + + 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; +} + + + +/* Register commands */ + + +/* int clearDACSregister(int imod) { */ + +/* putout("1111111111111111",imod);//reset */ +/* putout("1111111111111110",imod);//cs down */ + +/* /\* commented out by dhanya */ +/* putout("0000000001000000",imod); */ +/* putout("0000000101000000",imod); */ +/* putout("0000000101000000",imod); */ +/* putout("0000000001000000",imod); */ +/* *\/ */ +/* #ifdef DEBUG */ +/* fprintf(stdout, "Clearing DAC shiftregister\n"); */ +/* #endif */ +/* // sDac=0; */ +/* sMod=imod; */ +/* if (imod==ALLMOD) */ +/* sMod=allSelected; */ +/* return OK; */ +/* } */ + +/* int nextDAC(int imod) { */ + +/* putout("1111111111111011",imod);//cs up */ +/* putout("1111111111111001",imod);//clk down */ +/* putout("1111111111111111",imod);//reset */ + +/* /\*commented out by dhanya */ +/* putout("0000000001000000",imod); */ +/* putout("0000000001001000",imod); */ +/* putout("0000000001000000",imod); */ +/* *\/ */ +/* #ifdef DEBUG */ +/* fprintf(stdout, "Next DAC\n"); */ +/* #endif */ +/* // sDac++; */ +/* sMod=imod; */ +/* if (imod==ALLMOD) */ +/* sMod=allSelected; */ +/* return OK; */ +/* } */ + + +int clearCSregister(int imod) { + + putout("0000000001000000",imod); + putout("0000100001000000",imod); + putout("0000100001000000",imod); + putout("0000000001000000",imod); +#ifdef DEBUG + fprintf(stdout, "Clearing CS shiftregister\n"); +#endif + /* + sChan=noneSelected; + sMod=noneSelected; + sDac=noneSelected; + sAdc=noneSelected; + */ + sChip=noneSelected; + sMod=imod; + if (imod==ALLMOD) + sMod=allSelected; + //putout("0000000000000000",imod); + return 0; +} + +int setCSregister(int imod){ + + putout("0000000001000000",imod); + putout("0001000001000000",imod); + putout("0001000001000000",imod); + putout("0000000001000000",imod); +#ifdef DEBUG + fprintf(stdout, "Setting CS shiftregister\n"); +#endif + putout("0000000000000000",imod); + sChip=allSelected; + sMod=imod; + if (imod==ALLMOD) + sMod=allSelected; + return 0; +} + +int nextChip(int imod){ + + putout("0000000001000000",imod); + putout("0010000001000000",imod); + putout("0000000001000000",imod); +#ifdef DEBUG + fprintf(stdout, "Next Chip\n"); +#endif + sChip++; + sMod=imod; + if (imod==ALLMOD) + sMod=allSelected; + return 0; +} + +int firstChip(int imod){ + + putout("0100000001000000",imod); + putout("0110000001000000",imod); + putout("0100000001000000",imod); +#ifdef DEBUG + fprintf(stdout, "First Chip\n"); +#endif + sChip=0; + sMod=imod; + if (imod==ALLMOD) + sMod=allSelected; + return 0; +} + +int clearSSregister(int imod){ + int i; + putout("0000011000000000",imod); + for (i=0; i<10; i++) + putout("0000111000000000",imod); + putout("0000011000000000",imod); +#ifdef DEBUG + fprintf(stdout,"Clearing SS shiftregister\n"); +#endif + putout("0000000000000000",imod); + sChan=noneSelected; + sMod=imod; + if (imod==ALLMOD) + sMod=allSelected; + return 0; +} + +int setSSregister(int imod){ + int i; + putout("0000011000000000",imod); + for (i=0; i<10; i++) + putout("0001011000000000",imod); + putout("0000011000000000",imod); +#ifdef DEBUG + fprintf(stdout,"Setting SS shiftregister\n"); +#endif + putout("0000000000000000",imod); + sChan=allSelected; + sMod=imod; + if (imod==ALLMOD) + sMod=allSelected; + return 0; +} + +int nextStrip(int imod){ + putout("0000011000000000",imod); + putout("0010011000000000",imod); + putout("0000011000000000",imod); +#ifdef DEBUG + fprintf(stdout,"|-"); +#endif + sChan++; + sMod=imod; + if (imod==ALLMOD) + sMod=allSelected; + return 0; +} + +int selChannel(const int strip,int imod) { + int istrip; + clearSSregister(imod); + nextStrip(imod); + for (istrip=0; istrip=0 && imod=0) */ +/* initDAC(ind,val, imod); */ + +/* if (imod>=0 && imodgain,(detectorModules+imod)->offset); */ +/* #endif */ +/* if ((detectorModules+imod)->gain>0) */ +/* myg=(detectorModules+imod)->gain; */ +/* else { */ +/* if (thisSettings>=0 && thisSettings<3) */ +/* myg=g[thisSettings]; */ +/* // else */ +/* //myg=-1; */ +/* } */ + +/* if ((detectorModules+imod)->offset>0) */ +/* myo=(detectorModules+imod)->offset; */ +/* else { */ +/* if (thisSettings>=0 && thisSettings<3) */ +/* myo=o[thisSettings]; */ +/* // else */ +/* //myo=-1; */ +/* } */ + +/* if (myg>0 && myo>0) { */ +/* //ethr=(myo-detectorDacs[VTHRESH+imod*N_DAC])*1000/myg; */ + +/* ethr=(myo-setDACRegister(VDAC0,-1,imod))*1000/myg;//edited by dhanya */ +/* // else */ +/* // ethr=-1; */ + +/* } */ +/* #ifdef VERBOSE */ +/* //printf("module=%d gain=%f, offset=%f, dacu=%f\n",imod, myg, myo, detectorDacs[VTHRESH+imod*N_DAC]); */ +/* printf("module=%d gain=%f, offset=%f, dacu=%d\n",imod, myg, myo,(int)(setDACRegister(VDAC0,-1,imod)));//edited by dhanya */ +/* printf("Threshold energy of module %d is %d eV\n", imod, ethr); */ +/* #endif */ + +/* if (imod==0) */ +/* ret=ethr; */ +/* else { */ +/* if (ethr>(ret+100) || ethr<(ret-100)) */ +/* return FAIL; */ +/* } */ +/* } */ +/* } */ +/* return ret; */ +/* } */ + +/* int setThresholdEnergy(int ethr) { */ +/* double g[3]=DEFAULTGAIN; */ +/* double o[3]=DEFAULTOFFSET; */ +/* double myg=-1, myo=-1; */ +/* int dacu; */ +/* int imod; */ +/* int ret=ethr; */ + +/* setSettings(GET_SETTINGS,-1);//-1 added by dhanya */ +/* if (thisSettings>=0 || thisSettings<3){ */ +/* myg=g[thisSettings]; */ +/* myo=o[thisSettings]; */ +/* } */ +/* for (imod=0; imodgain>0) */ +/* myg=(detectorModules+imod)->gain; */ +/* else */ +/* if (thisSettings>=0 && thisSettings<3) */ +/* myg=g[thisSettings]; */ +/* else */ +/* myg=-1; */ +/* if ((detectorModules+imod)->offset>0) */ +/* myo=(detectorModules+imod)->offset; */ +/* else */ +/* if (thisSettings>=0 && thisSettings<3) */ +/* myo=o[thisSettings]; */ +/* else */ +/* myo=-1; */ +/* } else { */ +/* if (thisSettings>=0 && thisSettings<3) */ +/* myo=o[thisSettings]; */ +/* else */ +/* myo=-1; */ +/* if (thisSettings>=0 && thisSettings<3) */ +/* myg=g[thisSettings]; */ +/* else */ +/* myg=-1; */ +/* } */ +/* if (myg>0 && myo>0) { */ +/* dacu=myo-myg*((double)ethr)/1000.; */ +/* #ifdef VERBOSE */ +/* printf("module %d (%x): gain %f, off %f, energy %d eV, dac %d\n",imod,(unsigned int)((detectorModules+imod)),(detectorModules+imod)->gain,(detectorModules+imod)->offset, ethr,dacu); */ +/* #endif */ +/* } else { */ +/* dacu=ethr; */ +/* #ifdef VERBOSE */ +/* printf("could not set threshold energy for module %d, settings %d (offset is %f; gain is %f)\n",imod,thisSettings,myo,myg); */ +/* #endif */ +/* } */ +/* initDACbyIndexDACU(VDAC0, dacu, imod); ///needs to be fixed dhanya */ +/* } */ +/* return ret; */ +/* } */ + + + +/* int getDACbyIndexDACU(int ind, int imod) { */ +/* /\* */ +/* if (detectorDacs) { */ +/* if (imodndac) */ +/* return (detectorDacs[ind+imod*N_DAC]); */ +/* } */ +/* return FAIL; */ +/* *\/ */ +/* return setDACRegister(ind, -1, imod); */ +/* } */ + + +/* int initDAC(int dac_addr, int value, int imod) { */ +/* // int i; */ +/* #ifdef VERBOSE */ +/* printf("Programming dac %d with value %d\n", dac_addr, value); */ +/* #endif */ +/* clearDACSregister(imod); */ +/* program_one_dac(dac_addr,value,imod); */ +/* nextDAC(imod); */ +/* clearDACSregister(imod); */ + +/* return 0; */ +/* } */ + +int getTemperatureByModule(int tempSensor, int imod) +{ + int im; + //for the particular module + if (imod>=0 && imod=0 && imod=0 && imod=0) { */ +/* #ifdef VERBOSE */ +/* fprintf(stdout, "voltage %d\n", *(v+iaddr)); */ +/* #endif */ +/* program_one_dac(iaddr, *(v+iaddr),imod); */ +/* } */ +/* nextDAC(imod); */ +/* } */ + + +/* clearDACSregister(imod); */ + +/* return 0; */ + +/* } */ + + + + +int setSettings(int i, int imod) { +#ifdef VERBOSE + if(i==-1) + printf("\nReading settings of detector...\n"); + else + printf("\ninside set settings wit settings=%d...\n",i); +#endif + int isett=-1,val=-1,retval=-1; + enum conf_gain { + dynamic = 0x0f00, //dynamic + dynamichighgain0 = 0x0f01, //dynamichighgain0 + fixgain1 = 0x0f02, //fixgain1 + fixgain2 = 0x0f06, //fixgain2 + forceswitchgain1 = 0x1f00, //forceswitchgain1 + forceswitchgain2 = 0x3f00 //forceswitchgain2 + }; + + //determine conf value to write + if(i!=GET_SETTINGS){ + switch(i){ + case DYNAMICGAIN: val = dynamic;break; + case DYNAMICHG0: val = dynamichighgain0;break; + case FIXGAIN1: val = fixgain1;break; + case FIXGAIN2: val = fixgain2;break; + case FORCESWITCHG1: val = forceswitchgain1;break; + case FORCESWITCHG2: val = forceswitchgain2;break; + default: + printf("Error: This settings is not defined for this detector %d\n",i); + return GET_SETTINGS; + } + } + + retval=initConfGainByModule(i,val,imod); + + switch(retval){ + case dynamic: isett=DYNAMICGAIN; break; + case dynamichighgain0: isett=DYNAMICHG0; break; + case fixgain1: isett=FIXGAIN1; break; + case fixgain2: isett=FIXGAIN2; break; + case forceswitchgain1: isett=FORCESWITCHG1; break; + case forceswitchgain2: isett=FORCESWITCHG2; break; + default: + isett=UNDEFINED; + printf("Error:Wrong settings read out from Gain Reg 0x%x\n",retval); + break; + } + + thisSettings=isett; +//#ifdef VERBOSE + printf("detector settings are %d\n",thisSettings); +//#endif + return thisSettings; +} + + + + +/* Initialization*/ + +int initChannelbyNumber(sls_detector_channel myChan) {printf("in init channel by number\n"); + int reg=myChan.reg; + int ft=reg & TRIM_DR; + int cae=(reg>>(NTRIMBITS))&1; + int ae=(reg>>(NTRIMBITS+1))&1; + int coe=(reg>>(NTRIMBITS+2))&1; + int ocoe=(reg>>(NTRIMBITS+3))&1; + int counts=(reg>>(NTRIMBITS+4)); +#ifdef VERBOSE + printf("Initializing channel %d chip %d module %d reg %x\n",myChan.chan,myChan.chip,myChan.module, reg); + printf("trim %d, cae %d, ae %d, coe %d, ocoe %d, counts %d\n",ft, cae, ae, coe, ocoe, counts); +#endif + + if (myChan.chip<0) + setCSregister(myChan.module); + else + selChip(myChan.chip,myChan.module); + + if (myChan.chan<0) + setSSregister(myChan.module); + else + selChannel(myChan.chan,myChan.module); + + initChannel(ft,cae,ae, coe, ocoe, counts,myChan.module); + + setDynamicRange(dynamicRange); + + setCSregister(ALLMOD); + clearSSregister(ALLMOD); + putout("0000000000000000",ALLMOD); + + return myChan.reg; + +} + +int getChannelbyNumber(sls_detector_channel* myChan) { + int imod, ichip, ichan; + imod=myChan->module; + ichip=myChan->chip; + ichan=myChan->chan; + + if (detectorChans) { + if (imod=0) { + if (ichip<(detectorModules+imod)->nchip && ichan<(detectorModules+imod)->nchan/(detectorModules+imod)->nchip) + myChan->reg=detectorChans[imod*N_CHAN*N_CHIP+ichip*N_CHAN+ichan]; + return OK; + } + } + return FAIL; + +} + +int getTrimbit(int imod, int ichip, int ichan) { + if (detectorChans) { + if (imod=0) + if (ichip<(detectorModules+imod)->nchip && ichan<(detectorModules+imod)->nchan/(detectorModules+imod)->nchip) + return (detectorChans[imod*N_CHAN*N_CHIP+ichip*N_CHAN+ichan] & TRIM_DR); + } + + return -1; +} + +int initChannel(int ft,int cae, int ae, int coe, int ocoe, int counts, int imod){ + + int ibit, bit, i, im, ichip, ichan; + int chanmi, chanma, chipmi, chipma, modmi, modma; + + + + sMod=imod; + // printf("initializing module %d\n",sMod); + if (imod==ALLMOD) { + sMod=allSelected; + + // printf("initializing all modules\n"); + } + + if (sChan==allSelected) { + // printf("initializing all channels ft=%d coe=%d\n",ft,coe); + chanmi=0; + chanma=N_CHAN; + } else if (sChan==noneSelected || sChan>N_CHAN || sChan<0) { + // printf("initializing no channels ft=%d coe=%d\n",ft,coe); + chanmi=0; + chanma=-1; + } else { + // printf("initializing channel %d ft=%d coe=%d\n",sChan, ft,coe); + chanmi=sChan; + chanma=sChan+1; + } + + if (sChip==allSelected) { + // printf("initializing all chips\n"); + chipmi=0; + chipma=N_CHIP; + } else if (sChip==noneSelected || sChip>N_CHIP || sChip<0) { + // printf("initializing no chips\n"); + chipmi=0; + chipma=-1; + } else { + // printf("initializing chip %d\n",sChip); + chipmi=sChip; + chipma=sChip+1; + } + + + if (sMod==allSelected) { + modmi=0; + modma=nModX;//getNModBoard(); + } else if (sMod==noneSelected || sMod>nModX || sMod<0) {//(sMod==noneSelected || sMod>getNModBoard() || sMod<0) { + modmi=0; + modma=-1; + return 1; + } else { + modmi=sMod; + modma=sMod+1; + } + + if (detectorChans) { + for (im=modmi; im63 || ft<0) { + fprintf(stdout,"Fine Threshold is %d while should be between 0 and 63!",ft); + return 1; + } + /*cal_enable*/ + if (cae) { + putout("0100000000000000",imod); + putout("0110000000000000",imod); + } else { + putout("0000000000000000",imod); + putout("0010000000000000",imod); + } + /*n_an_enable*/ + if (ae) { + putout("0000000000000000",imod); + putout("0010000000000000",imod); + putout("0000000000000000",imod); + } else { + putout("0100000000000000",imod); + putout("0110000000000000",imod); + putout("0100000000000000",imod); + } + /*trb5*/ + ibit=5; + bit=ft & (1<>1; + int nchan, ichan; + int ft, cae, ae, coe, ocoe, counts, chanreg; + + + + nchan=myChip.nchan; + if (ichip<0) + setCSregister(imod); + else + selChip(ichip,imod); + + clearSSregister(imod); + for (ichan=0; ichan>(NTRIMBITS+1))&1; + ae=(chanreg>>(NTRIMBITS+2))&1; + coe=((chanreg)>>(NTRIMBITS+3))&1; + ocoe=((chanreg)>>(NTRIMBITS+4))&1; + counts=((chanreg)>>(NTRIMBITS+5)); + nextStrip(imod); + initChannel(ft,cae,ae, coe, ocoe, counts,imod); + } + initChip(obe,ow,imod); + return myChip.reg; + +} + +int getChipbyNumber(sls_detector_chip* myChip){ + int imod, ichip; + imod=myChip->module; + ichip=myChip->chip; + + if (detectorChips) { + if (imodnchip) { + myChip->reg=detectorChips[ichip+imod*N_CHIP]; + myChip->nchan=N_CHAN; + myChip->chanregs=detectorChans+imod*N_CHAN*N_CHIP+ichip*N_CHIP; + return OK; + } + } + return FAIL; + +} + + + +int initChip(int obe, int ow,int imod){ + int i; + int im, ichip; + int chipmi, chipma, modmi, modma; + /* switch (ow) { + case 0:; + case 1: + setDynamicRange(32); + break; + case 2: + setDynamicRange(16); + break; + case 3: + setDynamicRange(8); + break; + case 4: + setDynamicRange(4); + break; + case 5: + setDynamicRange(1); + break; + default: + setDynamicRange(32); + break; + } + */ + +#ifdef DEBUGOUT + printf("Initializing chip\n"); +#endif + putout("0000000000000000",imod); +#ifdef DEBUGOUT + printf("Output mode= %d\n", ow); +#endif + + /* clearing shift in register */ + for (i=0; i<10; i++) + putout("0000100000000000",imod); + putout("0000000000000000",imod); + + if (ow>0) { + putout("0100000000000000",imod); + putout("0110000000000000",imod); + putout("0100000000000000",imod); + for (i=0; i<(OUTMUX_OFFSET-1); i++) { + putout("0000000000000000",imod); + putout("0010000000000000",imod); + putout("0000000000000000",imod); + } + if (ow>1) { + putout("0000000000000000",imod); + putout("0010000000000000",imod); + putout("0000000000000000",imod); + } + if (ow>2) { + putout("0000000000000000",imod); + putout("0010000000000000",imod); + putout("0000000000000000",imod); + } + if (ow>3) { + putout("0000000000000000",imod); + putout("0010000000000000",imod); + putout("0000000000000000",imod); + } + if (ow>4) { + putout("0000000000000000",imod); + putout("0010000000000000",imod); + putout("0000000000000000",imod); + } + } +#ifdef DEBUGOUT + printf("Output buffer enable= %d\n", obe); +#endif + if (obe) { + putout("0100000000000000",imod); + putout("0110000000000000",imod); + putout("0100000000000000",imod); + } else { + putout("0000000000000000",imod); + putout("0010000000000000",imod); + putout("0000000000000000",imod); + } + /*}*/ + putout("0000000000000000",imod); + + + + + + sMod=imod; + if (imod==ALLMOD) + sMod=allSelected; + + + if (sChip==allSelected) { + chipmi=0; + chipma=N_CHIP; + } else if (sChip==noneSelected || sChip>N_CHIP || sChip<0) { + chipmi=0; + chipma=-1; + } else { + chipmi=sChip; + chipma=sChip+1; + } + + + if (sMod==allSelected) { + modmi=0; + modma=nModX;//getNModBoard(); + } else if (sMod==noneSelected || sMod>nModX || sMod<0) {//(sMod==noneSelected || sMod>getNModBoard() || sMod<0) { + modmi=0; + modma=-1; + } else { + modmi=sMod; + modma=sMod+1; + } + + if (detectorChips) { + for (im=modmi; imN_CHIP || sChip<0) { + chipmi=0; + chipma=-1; + } else { + chipmi=sChip; + chipma=sChip+1; + } + + + if (sMod==allSelected) { + modmi=0; + modma=nModX;//getNModBoard(); + } else if (sMod==noneSelected || sMod>nModX || sMod<0) {//(sMod==noneSelected || sMod>getNModBoard() || sMod<0) { + modmi=0; + modma=-1; + } else { + modmi=sMod; + modma=sMod+1; + } + + if (detectorChips) { + for (im=modmi; imnModX || sMod<0) {//(sMod==noneSelected || sMod>getNModBoard() || sMod<0) { + modmi=0; + modma=-1; + } else { + modmi=sMod; + modma=sMod+1; + } + + if (detectorModules) { + for (im=modmi; imreg)=cm; +#ifdef VERBOSE + printf("imod=%d reg=%d (%x)\n",im,(detectorModules+im)->reg,(unsigned int)((detectorModules+im))); +#endif + } + } + return 0; +} + +int initModulebyNumber(sls_detector_module myMod) { + + printf("\ninside initmoduleynumberrrr..\n"); + printf("000\n"); + int nchip,nchan;//int ichip, nchip, ichan, nchan; + int im, modmi,modma; + // int ft, cae, ae, coe, ocoe, counts, chanreg; + int imod; + // int obe; + // int ow; + /* int v[N_DAC];*/ + int retval =-1, idac; + + + nchip=myMod.nchip; + nchan=(myMod.nchan)/nchip; + + imod=myMod.module; + sMod=imod; + + if (sMod==ALLMOD) + sMod=allSelected; + + if (sMod==allSelected) { + modmi=0; + modma=nModX;//getNModBoard(); + } else if (sMod==noneSelected || sMod>nModX || sMod<0) {// (sMod==noneSelected || sMod>getNModBoard() || sMod<0) { + modmi=0; + modma=-1; + } else { + modmi=sMod; + modma=sMod+1; + } + + printf("222\n"); + /* + for (idac=0; idacmodule; +#ifdef VERBOSE + printf("Getting module %d\n",imod); +#endif + if (detectorModules) { + copyModule(myMod,detectorModules+imod); + ; + } else + return FAIL; + + return OK; +} + +/* To chips */ +int clearCounter(int imod){ + int i; +#ifdef DEBUG + printf("Clearing counter with contclear\n"); +#endif + putout("0000000000000000",imod); + for (i=0; i<10; i++) + putout("0000000000010000",imod); + putout("0000000000000000",imod); + + return 0; +} + +int clearOutReg(int imod){ + int i; +#ifdef DEBUG + printf("Clearing output register\n"); +#endif + putout("0000010000000000",imod); + for (i=0; i<10; i++) + putout("0000110000000000",imod); + putout("0000010000000000",imod); + return 0; +} +int setOutReg(int imod){ + int i; +#ifdef DEBUG + printf("Setting output register\n"); +#endif + putout("0000010000000000",imod); + for (i=0; i<10; i++) + putout("0001010000000000",imod); + putout("0000010000000000",imod); + return 0; +} + + +int extPulse(int ncal, int imod) { + int ical; +#ifdef DEBUG + printf("Giving a clock pulse to the counter\n"); +#endif + for (ical=0; ical0 && i%2==0) { + printf("Shift in: module %d chip %i bit %d read %d instead of %d \n",k,j,i,val & 1<< j, i%2); + result++; + } + if (i%2>0 && (val & 1<0 && (dum & (1<0) { + printf("Shift out: module %d chip %i bit %d read %d instead of %d \n",k,j,i,val & 1<< j, (dum &1<0 && i%2==0) { + printf("Shift stsel: module %d chip %i bit %d read %d instead of %d \n",k,j,i,val & 1<< j, i%2); + result++; + } + if (i%2>0 && (val & 1<> 1; + + + putout("0000000000000000",ALLMOD); + putout("0010000000000000",ALLMOD); //change mux setting + putout("0000000000000000",ALLMOD); + } + + printf("Test FpgaMux module %d : %d errors\n", imod,result); + if (result) + return 1; + else + return 0; +} + + + + + + + + + +int calibration_sensor(int num, int *v, int *dacs) { + int ich, ichip, imod; + int val[10]; + + + printf("calibrating sensor..."); + for (imod=0; imod=0){ */ + +/* //clear rois */ +/* for(i=0;i=0) && (adc<=4)); */ +/* else { */ +/* printf("warning:adc value greater than 5. deleting roi\n"); */ +/* adc=-1; */ +/* } */ +/* } */ +/* } */ + + +/* //set rois for just 1 adc - take only 1st roi */ +/* if(adc!=-1){ */ +/* rois[0].xmin=adc*(GOTTHARDNCHAN*NCHIPS_PER_ADC); */ +/* rois[0].xmax=(adc+1)*(GOTTHARDNCHAN*NCHIPS_PER_ADC)-1; */ +/* rois[0].ymin=-1; */ +/* rois[0].ymax=-1; */ +/* nROI = 1; */ +/* }else */ +/* nROI = 0; */ + +/* if((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 */ +/* printf("Rois:\n"); */ +/* for( i=0;i +#include "communication_funcs.h" +#include "server_funcs.h" +#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[500]; + int retval=OK; + int sd, fd; + int iarg; + int checkType = 1; + + + for(iarg=1; iarg 2) && (!strcasecmp(argv[2],"stopserver"))){ + portno = DEFAULT_PORTNO+1; + if ( sscanf(argv[1],"%d",&portno) ==0) { + printf("could not open stop server: unknown port\n"); + return 1; + } + b=0; + printf("\n\nStop Server\nOpening stop server on port %d\n",portno); + checkType=0; + + } + + //control server + else { + portno = DEFAULT_PORTNO; + if(checkType) + sprintf(cmd,"%s %d stopserver &",argv[0],DEFAULT_PORTNO+1); + else + sprintf(cmd,"%s %d stopserver -test with_gotthard &",argv[0],DEFAULT_PORTNO+1); + printf("\n\nControl Server\nOpening control server on port %d\n",portno ); + + //printf("\n\ncmd:%s\n",cmd); + system(cmd); + b=1; + checkType=1; + + } + + + + + + init_detector(b, checkType); + + + sd=bindSocket(portno); + sockfd=sd; + if (getServerError(sd)) { + printf("server error!\n"); + return -1; + } + + /* assign function table */ + function_table(); +#ifdef VERBOSE + printf("function table assigned \n"); +#endif + + + /* waits for connection */ + while(retval!=GOODBYE) { +#ifdef VERBOSE + printf("\n"); +#endif +#ifdef VERY_VERBOSE + printf("Waiting for client call\n"); +#endif + fd=acceptConnection(sockfd); +#ifdef VERY_VERBOSE + printf("Conenction accepted\n"); +#endif + retval=decode_function(fd); +#ifdef VERY_VERBOSE + printf("function executed\n"); +#endif + closeConnection(fd); +#ifdef VERY_VERBOSE + printf("connection closed\n"); +#endif + } + + exitServer(sockfd); + printf("Goodbye!\n"); + + return 0; +} + diff --git a/slsDetectorSoftware/jctbDetectorServer/server_defs.h b/slsDetectorSoftware/jctbDetectorServer/server_defs.h new file mode 100755 index 000000000..781cefc33 --- /dev/null +++ b/slsDetectorSoftware/jctbDetectorServer/server_defs.h @@ -0,0 +1,78 @@ +#ifndef SERVER_DEFS_H +#define SERVER_DEFS_H + +#include "sls_detector_defs.h" + +#include + + +// Hardware definitions +#define NMAXMODY 1 +#define NMAXMOD (NMAXMODX*NMAXMODY) + +#define NCHAN 32 +#define NCHIP 1 +#define NADC 1 + +#ifdef CTB +#define NDAC 24 +#define NPWR 5 +#else +#define NDAC 16 +#define NPWR 0 +#endif +#define DAC_CMD_OFF 20 + +#define NMAXMODX 1 +#define NCHANS (NCHAN*NCHIP*NMAXMOD) +#define NDACS (NDAC*NMAXMOD) + +#define JUNGFRAU_NCHAN (256*256) +#define JUNGFRAU_NCHIP 8 +#define JUNGFRAU_NADC 0 +#define JUNGFRAU_NDAC 16 +#define JUNGFRAU_NCHANS (JUNGFRAU_NCHAN*JUNGFRAU_NCHIP*NMAXMOD) + + + +/**when moench readout tested with gotthard module*/ +#define GOTTHARDNCHAN 128 +#define GOTTHARDNCHIP 10 + + +#define NTRIMBITS 6 +#define NCOUNTBITS 24 + +#define NCHIPS_PER_ADC 2 + +//#define TRIM_DR ((2**NTRIMBITS)-1) +//#define COUNT_DR ((2**NCOUNTBITS)-1) +#define TRIM_DR (((int)pow(2,NTRIMBITS))-1) +#define COUNT_DR (((int)pow(2,NCOUNTBITS))-1) + + +#define ALLMOD 0xffff +#define ALLFIFO 0xffff + +#define GOTTHARD_ADCSYNC_VAL 0x32214 +#define ADCSYNC_VAL 0x02111 +#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 0 // 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 + +#ifdef VIRTUAL +#define DEBUGOUT +#endif + +#define CLK_FREQ 156.25E+6 +#define ADC_CLK_FREQ 32E+6 + + +#endif diff --git a/slsDetectorSoftware/jctbDetectorServer/server_funcs.c b/slsDetectorSoftware/jctbDetectorServer/server_funcs.c new file mode 100755 index 000000000..e4551b3cb --- /dev/null +++ b/slsDetectorSoftware/jctbDetectorServer/server_funcs.c @@ -0,0 +1,3513 @@ +#include "sls_detector_defs.h" +#include "sls_receiver_defs.h" +#include "server_funcs.h" +#include "server_defs.h" +#include "firmware_funcs.h" +#include "mcb_funcs.h" +#include "registers_m.h" +#include "gitInfoMoench.h" + +#define FIFO_DATA_REG_OFF 0x50<<11 +// Global variables + + +int (*flist[256])(int); + + +//defined in the detector specific file +/* #ifdef MYTHEND */ +/* const enum detectorType myDetectorType=MYTHEN; */ +/* #elif GOTTHARDD */ +/* const enum detectorType myDetectorType=GOTTHARD; */ +/* #elif EIGERD */ +/* const enum detectorType myDetectorType=EIGER; */ +/* #elif PICASSOD */ +/* const enum detectorType myDetectorType=PICASSO; */ +/* #elif MOENCHD */ +/* const enum detectorType myDetectorType=MOENCH; */ +/* #else */ +enum detectorType myDetectorType=GENERIC; +/* #endif */ + + +extern int nModX; +extern int nModY; +extern int dataBytes; +extern int nSamples; +extern int dynamicRange; +extern int storeInRAM; + +extern int lockStatus; +extern char lastClientIP[INET_ADDRSTRLEN]; +extern char thisClientIP[INET_ADDRSTRLEN]; +extern int differentClients; + +/* global variables for optimized readout */ +extern unsigned int *ram_values; +char *dataretval=NULL; +int nframes, iframes, dataret; +char mess[1000]; + +int digitalTestBit = 0; + +extern int withGotthard; + + +int adcvpp=0x4; + +/** for jungfrau reinitializing macro later */ +int N_CHAN=NCHAN; +int N_CHIP=NCHIP; +int N_DAC=NDAC; +int N_ADC=NADC; +int N_CHANS=NCHANS; + + +int init_detector(int b, int checkType) { + + int i; + if (mapCSP0()==FAIL) { printf("Could not map memory\n"); + exit(1); + } + + //print version + printf("v: 0x%x\n",bus_r(FPGA_VERSION_REG)); + printf("fp: 0x%x\n",bus_r(FIX_PATT_REG)); + + //checktype + if (checkType) { + printf("Bus test... (checktype is %d; b is %d)",checkType,b ); + for (i=0; i<1000000; i++) { + bus_w(SET_DELAY_LSB_REG, i*100); + bus_r(FPGA_VERSION_REG); + if (i*100!=bus_r(SET_DELAY_LSB_REG)) + printf("ERROR: wrote 0x%x, read 0x%x\n",i*100,bus_r(SET_DELAY_LSB_REG)); + } + printf("Finished\n"); + }else + printf("(checktype is %d; b is %d)",checkType,b ); + + + //confirm the detector type + switch ((bus_r(PCB_REV_REG) & DETECTOR_TYPE_MASK)>>DETECTOR_TYPE_OFFSET) { + case MOENCH03_MODULE_ID: + myDetectorType=MOENCH; + printf("This is a MOENCH03 module %d\n",MOENCH); + break; + + case JUNGFRAU_MODULE_ID: + myDetectorType=JUNGFRAU; + printf("This is a Jungfrau module %d\n", JUNGFRAU); + break; + + case JUNGFRAU_CTB_ID: + myDetectorType=JUNGFRAUCTB; + printf("This is a Jungfrau CTB %d\n", JUNGFRAUCTB); + break; + + default: + myDetectorType=GENERIC; + printf("Unknown detector type %02x\n",(bus_r(PCB_REV_REG) & DETECTOR_TYPE_MASK)>>DETECTOR_TYPE_OFFSET); + break; + + } + printf("Detector type is %d\n", myDetectorType); + + + //control server only-- + if (b) { + resetPLL(); + bus_w16(CONTROL_REG, SYNC_RESET); + bus_w16(CONTROL_REG, 0); + bus_w16(CONTROL_REG, GB10_RESET_BIT); + bus_w16(CONTROL_REG, 0); + +#ifdef MCB_FUNCS + printf("\nBoard Revision:0x%x\n",(bus_r(PCB_REV_REG)&BOARD_REVISION_MASK)); + if(myDetectorType == JUNGFRAU) + initDetector(); /*allocating detectorModules, detectorsDacs etc for "settings", also does allocate RAM*/ + dataBytes=NMAXMOD*N_CHIP*N_CHAN*2; /**Nchip and Nchan real values get assigned in initDetector()*/ + printf("Initializing Detector\n"); + //bus_w16(CONTROL_REG, SYNC_RESET); // reset registers +#endif + + // testFpga(); + // testRAM(); + // printf("ADC_SYNC_REG:%x\n",bus_r(ADC_SYNC_REG)); + //moench specific + // setPhaseShiftOnce(); + /*some registers set, which is in common with jungfrau, please check */ + prepareADC(); + //setADC(-1); //already does setdaqreg and clean fifo + // setSettings(GET_SETTINGS,-1); + /*some registers set, which is in common with jungfrau, please check */ + initDac(0); initDac(8); //initializes the two dacs + + if(myDetectorType==JUNGFRAU){ + /** for jungfrau reinitializing macro */ + N_CHAN=JUNGFRAU_NCHAN; + N_CHIP=JUNGFRAU_NCHIP; + N_DAC=JUNGFRAU_NDAC; + N_ADC=JUNGFRAU_NADC; + N_CHANS=JUNGFRAU_NCHANS; + + + //set dacs + int retval = -1; + int dacvalues[14][2]={ + {0, 1250}, //vout_cm + {10, 1053}, //vin_com + {1, 600}, //vb_sda + {11, 1000}, //vb_colbuf + {2, 3000}, //vb_test_cur + {3, 830}, //vcascp_pixbuf + {4, 1630}, //vcascn_pixbuf + {12, 750}, //vb_pixbuf + {6, 480}, //vref_ds + {5, 1000}, //vb_ds + {7, 400}, //vref_comp + {13, 1220}, //vb_comp + {8, 1500}, //vref_prech + {9, 3000}, //vdd_prot + }; + for(i=0;i<14;++i){ + retval=setDac(dacvalues[i][0], dacvalues[i][1]); + if(retval!=dacvalues[i][1]) + printf("Error: Setting dac %d failed, wrote %d, read %d\n",dacvalues[i][0],dacvalues[i][1],retval); + } + + //power on the chips + bus_w(POWER_ON_REG,0x1); + + //reset adc + writeADC(ADCREG1,0x3); writeADC(ADCREG1,0x0); + writeADC(ADCREG2,0x40); + writeADC(ADCREG3,0xf); + writeADC(ADCREG4,0x3f); + //vrefs - configurable? + writeADC(ADCREG_VREFS,0x2); + + + //set ADCINVERSionreg (by trial and error) + bus_w(ADC_INVERSION_REG,0x453b2a9c); + + //set adc_pipeline + bus_w(ADC_PIPELINE_REG,0x20); //same as ADC_OFFSET_REG + + //set dbit_pipeline + bus_w(DBIT_PIPELINE_REG,0x100e); + usleep(1000000);//1s + + //reset mem machine fifos fifos + bus_w(MEM_MACHINE_FIFOS_REG,0x4000); + bus_w(MEM_MACHINE_FIFOS_REG,0x0); + + //reset run control + bus_w(MEM_MACHINE_FIFOS_REG,0x0400); + bus_w(MEM_MACHINE_FIFOS_REG,0x0); + + //set default setting + setSettings(DYNAMICGAIN,-1); + } + + + //Initialization of acquistion parameters + setFrames(-1); + setTrains(-1); + setExposureTime(-1); + setPeriod(-1); + setDelay(-1); + setGates(-1); + + setTiming(GET_EXTERNAL_COMMUNICATION_MODE); + setMaster(GET_MASTER); + setSynchronization(GET_SYNCHRONIZATION_MODE); + startReceiver(0); //firmware + }//end of control server only-- + else printf("\n\n"); + + + //common for both control and stop server + strcpy(mess,"dummy message"); + strcpy(lastClientIP,"none"); + strcpy(thisClientIP,"none1"); + lockStatus=0; + // getDynamicRange(); + + /* both these functions setROI and allocateRAM should go into the control server part. */ + if(myDetectorType!=JUNGFRAU){ + int retvalsize,ret; + setROI(-1,NULL,&retvalsize,&ret); + allocateRAM(); + } + + 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 %x %x\n",fnum,(unsigned int)(flist[fnum]), (unsigned int)(flist[F_READ_REGISTER]),(unsigned int)(&read_register)); +#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_EXIT_SERVER]=&exit_server; + flist[F_EXEC_COMMAND]=&exec_command; + flist[F_GET_DETECTOR_TYPE]=&get_detector_type; + flist[F_SET_NUMBER_OF_MODULES]=&set_number_of_modules; + flist[F_GET_MAX_NUMBER_OF_MODULES]=&get_max_number_of_modules; + 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_WRITE_REGISTER]=&write_register; + flist[F_READ_REGISTER]=&read_register; + flist[F_SET_DAC]=&set_dac; + flist[F_GET_ADC]=&get_adc; + flist[F_SET_CHANNEL]=&set_channel; + flist[F_SET_CHIP]=&set_chip; + flist[F_SET_MODULE]=&set_module; + flist[F_GET_CHANNEL]=&get_channel; + flist[F_GET_CHIP]=&get_chip; + flist[F_GET_MODULE]=&get_module; + flist[F_GET_THRESHOLD_ENERGY]=&get_threshold_energy; + flist[F_SET_THRESHOLD_ENERGY]=&set_threshold_energy; + flist[F_SET_SETTINGS]=&set_settings; + 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_READ_FRAME]=&read_frame; + flist[F_READ_ALL]=&read_all; + flist[F_START_AND_READ_ALL]=&start_and_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_ROI]=&set_roi; + flist[F_SET_SPEED]=&set_speed; + flist[F_SET_READOUT_FLAGS]=&set_readout_flags; + flist[F_EXECUTE_TRIMMING]=&execute_trimming; + flist[F_LOCK_SERVER]=&lock_server; + flist[F_SET_PORT]=&set_port; + flist[F_GET_LAST_CLIENT_IP]=&get_last_client_ip; + flist[F_UPDATE_CLIENT]=&update_client; + flist[F_CONFIGURE_MAC]=&configure_mac; + flist[F_LOAD_IMAGE]=&load_image; + flist[F_SET_MASTER]=&set_master; + flist[F_SET_SYNCHRONIZATION_MODE]=&set_synchronization; + flist[F_READ_COUNTER_BLOCK]=&read_counter_block; + flist[F_RESET_COUNTER_BLOCK]=&reset_counter_block; + flist[F_START_RECEIVER]=&start_receiver; + flist[F_STOP_RECEIVER]=&stop_receiver; + flist[F_CALIBRATE_PEDESTAL]=&calibrate_pedestal; + flist[F_SET_CTB_PATTERN]=&set_ctb_pattern; + flist[F_WRITE_ADC_REG]=&write_adc_register; + return OK; +} + + +int M_nofunc(int file_des){ + + int ret=FAIL; + sprintf(mess,"Unrecognized Function\n"); + printf(mess); + + sendDataOnly(file_des,&ret,sizeof(ret)); + sendDataOnly(file_des,mess,sizeof(mess)); + return GOODBYE; +} + + +int exit_server(int file_des) { + int retval=FAIL; + sendDataOnly(file_des,&retval,sizeof(retval)); + printf("closing server."); + sprintf(mess,"closing server"); + 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 ret; + int retval=OK; + + sprintf(mess,"Can't return detector type\n"); + + + /* receive arguments */ + /* execute action */ + ret=myDetectorType; + +#ifdef VERBOSE + printf("Returning detector type %d\n",ret); +#endif + + /* send answer */ + /* send OK/failed */ + if (differentClients==1) + retval=FORCE_UPDATE; + + 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 set_number_of_modules(int file_des) { + int n; + int arg[2], ret=0; + int retval=OK; + int dim, nm; + + sprintf(mess,"Can't set number of modules\n"); + + /* receive arguments */ + n = receiveDataOnly(file_des,&arg,sizeof(arg)); + if (n < 0) { + sprintf(mess,"Error reading from socket %d", n); + retval=GOODBYE; + } + if (retval==OK) { + dim=arg[0]; + nm=arg[1]; + + /* execute action */ +#ifdef VERBOSE + printf("Setting the number of modules in dimension %d to %d\n",dim,nm ); +#endif + + //if (nm!=GET_FLAG) { + if (dim!=X && nm!=GET_FLAG) { + retval=FAIL; + sprintf(mess,"Can't change module number in dimension %d\n",dim); + } else { + if (lockStatus==1 && differentClients==1 && nm!=GET_FLAG) { + sprintf(mess,"Detector locked by %s\n", lastClientIP); + retval=FAIL; + } else { + ret=setNMod(nm); + if (nModX==nm || nm==GET_FLAG) { + retval=OK; + if (differentClients==1) + retval=FORCE_UPDATE; + } else + retval=FAIL; + } + } + } + /*} else { + if (dim==Y) { + ret=nModY; + } else if (dim==X) { + ret=setNMod(-1); + } + } + */ + + /* 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_max_number_of_modules(int file_des) { + int n; + int ret; + int retval=OK; + enum dimension arg; + + sprintf(mess,"Can't get max number of modules\n"); + /* receive arguments */ + n = receiveDataOnly(file_des,&arg,sizeof(arg)); + if (n < 0) { + sprintf(mess,"Error reading from socket\n"); + retval=FAIL; + } + /* execute action */ +#ifdef VERBOSE + printf("Getting the max number of modules in dimension %d \n",arg); +#endif + + + switch (arg) { + case X: + ret=getNModBoard(); + break; + case Y: + ret=NMAXMODY; + break; + default: + ret=FAIL; + retval=FAIL; + break; + } +#ifdef VERBOSE + printf("Max number of module in dimension %d is %d\n",arg,ret ); +#endif + + + + if (differentClients==1 && retval==OK) { + retval=FORCE_UPDATE; + } + + /* 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; +} + + +//index 0 is in gate +//index 1 is in trigger +//index 2 is out gate +//index 3 is out trigger + +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 (differentClients==0 || lockStatus==0) { + retval=setExtSignal(signalindex,flag); + } else { + if (lockStatus!=0) { + ret=FAIL; + sprintf(mess,"Detector locked by %s\n", lastClientIP); + } + } + + } + +#ifdef VERBOSE + printf("Setting external signal %d to flag %d\n",signalindex,flag ); + printf("Set to flag %d\n",retval); +#endif + + } else { + ret=FAIL; + } + + 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; + } + /* + enum externalCommunicationMode{ + GET_EXTERNAL_COMMUNICATION_MODE, + AUTO, + TRIGGER_EXPOSURE_SERIES, + TRIGGER_EXPOSURE_BURST, + TRIGGER_READOUT, + TRIGGER_COINCIDENCE_WITH_INTERNAL_ENABLE, + GATE_FIX_NUMBER, + GATE_FIX_DURATION, + GATE_WITH_START_TRIGGER, + GATE_COINCIDENCE_WITH_INTERNAL_ENABLE + }; + */ + if (retval==OK) { + /* execute action */ + + ret=setTiming(arg); + + /* switch(arg) { */ + /* default: */ + /* sprintf(mess,"The meaning of single signals should be set\n"); */ + /* retval=FAIL; */ + /* } */ + + +#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=getFirmwareSVNVersion(); + retval=(retval <<32) | getFirmwareVersion(); + break; + case DETECTOR_SOFTWARE_VERSION: + retval= SVNREV; + retval= (retval <<32) | SVNDATE; + break; +/* case DETECTOR_FIRMWARE_SVN_VERSION: + retval=getFirmwareSVNVersion(); + break;*/ + 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 imod=-1; + int n=0; + int ibit=0; + int ow; + 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 CHIP_TEST: + n = receiveDataOnly(file_des,&imod,sizeof(imod)); + if (n < 0) { + sprintf(mess,"Error reading from socket\n"); + retval=FAIL; + } +#ifdef VERBOSE + printf("of module %d\n", imod); +#endif + retval=0; +#ifdef MCB_FUNCS + if (differentClients==1 && lockStatus==1) { + ret=FAIL; + sprintf(mess,"Detector locked by %s\n",lastClientIP); + break; + } + if (imod >= nModX) { + ret=FAIL; + sprintf(mess,"Module %d disabled\n",imod); + break; + } + if (testShiftIn(imod)) retval|=(1<<(ibit)); + ibit++; + if (testShiftOut(imod)) retval|=(1<<(ibit)); + ibit++; + if (testShiftStSel(imod)) retval|=(1<<(ibit)); + ibit++; + //if ( testDataInOut(0x123456, imod)) retval|=(1<<(ibit++)); + //if ( testExtPulse(imod)) retval|=(1<<(ibit++)); + // for (ow=0; ow<6; ow++) + // ow=1; + //#ifndef PICASSOD + for (ow=0; ow<5; ow++) { + //#endif + if (testDataInOutMux(imod, ow, 0x789abc)) retval|=(1<=getNModBoard()) + ret=FAIL; + if (imod<0) + imod=ALLMOD; + + + + +#ifdef MCB_FUNCS + + if (ret==OK) { + if (differentClients==1 && lockStatus==1) { + ret=FAIL; + sprintf(mess,"Detector locked by %s\n",lastClientIP); + } else{ + if (ind2500) + val=-1; + printf("%d mV is ",val); + if (val>0) + val=val/2500*4095; + printf("%d DACu\n", val); + } else if (val>4095) + val=-1; + + + retval=setDac(ind,val); + } else { + switch (ind) { + case ADC_VPP: + + printf("Setting ADC VPP to %d\n",val); + if (val>4 || val<0) + printf("Cannot set ADC VPP to %d\n",val); + else { + writeADC(0x18,val); + adcvpp=val; + } + retval=adcvpp;; + break; + + case HV_NEW: + retval=initHighVoltageByModule(val,imod); + break; + + case V_POWER_A: + case V_POWER_B: + case V_POWER_C: + case V_POWER_D: + case V_POWER_IO: + case V_POWER_CHIP: + if (mV) { + retval=setPower(ind,val); + } else + printf("********power %d should be set in mV instead od DACu", ind); + break; + + + default: + printf("**********No dac with index %d\n",ind); + ret=FAIL; + } + + } + } + } + if(ret==OK){ + if (ind=getNModBoard() || imod<0) + ret=FAIL; + +#ifdef MCB_FUNCS + 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=getTemperatureByModule(idac,imod); +#endif + +#ifdef VERBOSE + printf("ADC is %d V\n", retval); +#endif + if (ret==FAIL) { + printf("Getting adc %d of module %d failed\n", ind, imod); + } + + 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_channel(int file_des) { + int ret=OK; + sls_detector_channel myChan; + int retval; + int n; + + + sprintf(mess,"Can't set channel\n"); + +#ifdef VERBOSE + printf("Setting channel\n"); +#endif + ret=receiveChannel(file_des, &myChan); + if (ret>=0) + ret=OK; + else + ret=FAIL; +#ifdef VERBOSE + printf("channel number is %d, chip number is %d, module number is %d, register is %lld\n", myChan.chan,myChan.chip, myChan.module, myChan.reg); +#endif + + if (ret==OK) { + if (myChan.module>=getNModBoard()) + ret=FAIL; + if (myChan.chip>=N_CHIP) + ret=FAIL; + if (myChan.chan>=N_CHAN) + ret=FAIL; + if (myChan.module<0) + myChan.module=ALLMOD; + } + + + if (ret==OK) { + if (differentClients==1 && lockStatus==1) { + ret=FAIL; + sprintf(mess,"Detector locked by %s\n",lastClientIP); + } else { +#ifdef MCB_FUNCS + retval=initChannelbyNumber(myChan); +#endif + } + } + /* Maybe this is done inside the initialization funcs */ + //copyChannel(detectorChans[myChan.module][myChan.chip]+(myChan.chan), &myChan); + + + + 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 get_channel(int file_des) { + + int ret=OK; + sls_detector_channel retval; + + int arg[3]; + int ichan, ichip, imod; + int n; + + sprintf(mess,"Can't get channel\n"); + + + + n = receiveDataOnly(file_des,arg,sizeof(arg)); + if (n < 0) { + sprintf(mess,"Error reading from socket\n"); + ret=FAIL; + } + ichan=arg[0]; + ichip=arg[1]; + imod=arg[2]; + + if (ret==OK) { + ret=FAIL; + if (imod>=0 && imod=0 && ichip=0 && ichan=0) + ret=OK; + else + ret=FAIL; +#ifdef VERBOSE + printf("chip number is %d, module number is %d, register is %d, nchan %d\n",myChip.chip, myChip.module, myChip.reg, myChip.nchan); +#endif + + if (ret==OK) { + if (myChip.module>=getNModBoard()) + ret=FAIL; + if (myChip.module<0) + myChip.module=ALLMOD; + if (myChip.chip>=N_CHIP) + ret=FAIL; + } + if (differentClients==1 && lockStatus==1) { + ret=FAIL; + sprintf(mess,"Detector locked by %s\n",lastClientIP); + } else { +#ifdef MCB_FUNCS + retval=initChipbyNumber(myChip); +#endif + } + /* Maybe this is done inside the initialization funcs */ + //copyChip(detectorChips[myChip.module]+(myChip.chip), &myChip); + + if (differentClients && 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 ret; +} + +int get_chip(int file_des) { + + + int ret=OK; + sls_detector_chip retval; + int arg[2]; + int ichip, imod; + int n; + + + + n = receiveDataOnly(file_des,arg,sizeof(arg)); + if (n < 0) { + sprintf(mess,"Error reading from socket\n"); + ret=FAIL; + } + ichip=arg[0]; + imod=arg[1]; + if (ret==OK) { + ret=FAIL; + if (imod>=0 && imod=0 && ichip=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 (myModule.module>=getNModBoard()) { + ret=FAIL; + printf("Module number is too large %d\n",myModule.module); + } + if (myModule.module<0) + myModule.module=ALLMOD; + } + + if (ret==OK) { + if (differentClients==1 && lockStatus==1) { + ret=FAIL; + sprintf(mess,"Detector locked by %s\n",lastClientIP); + } else { +#ifdef MCB_FUNCS + retval=initModulebyNumber(myModule); + if(retval != myModule.reg) + ret = FAIL; +#endif + } + } + + 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(myDac); + if(myAdc != NULL) free(myAdc); + if(myChip != NULL) free(myChip); + if(myChan != NULL) free(myChan); + + + //setDynamicRange(dr); always 16 commented out + + return ret; +} + + + + +int get_module(int file_des) { + + int ret=OK; + int arg; + int imod; + int n; + sls_detector_module myModule; + int *myDac=malloc(N_DAC*sizeof(int)); + int *myChip=NULL; + int *myChan=NULL; + int *myAdc=NULL; + + /*not required for jungfrau. so save memory*/ + if(myDetectorType != JUNGFRAU){ + myChip=malloc(N_CHIP*sizeof(int)); + myChan=malloc(N_CHIP*N_CHAN*sizeof(int)); + myAdc=malloc(N_ADC*sizeof(int)); + } + + + if (myDac) + myModule.dacs=myDac; + else { + sprintf(mess,"could not allocate dacs\n"); + ret=FAIL; + } + + + myModule.adcs=NULL; + myModule.chipregs=NULL; + myModule.chanregs=NULL; + /*not required for jungfrau. so save memory*/ + if(myDetectorType != JUNGFRAU){ + 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=N_DAC; + myModule.nchip=N_CHIP; + myModule.nchan=N_CHAN*N_CHIP; + myModule.nadc=N_ADC; + + + + n = receiveDataOnly(file_des,&arg,sizeof(arg)); + if (n < 0) { + sprintf(mess,"Error reading from socket\n"); + ret=FAIL; + } + imod=arg; + + if (ret==OK) { + ret=FAIL; + if (imod>=0 && imod-1) { + dataret=FAIL; + sprintf(mess,"no data and run stopped: %d frames left\n",(int)(getFrames()+2)); + printf("%s\n",mess); + } else { + dataret=FINISHED; + sprintf(mess,"acquisition successfully finished\n"); + printf("%s\n",mess); + if (differentClients) + dataret=FORCE_UPDATE; + } +#ifdef VERBOSE + printf("Frames left %d\n",(int)(getFrames())); +#endif + sendDataOnly(file_des,&dataret,sizeof(dataret)); + sendDataOnly(file_des,mess,sizeof(mess)); + } + + + + + return dataret; + +} + + + + + + + + +int read_all(int file_des) { + +while(read_frame(file_des)==OK) { + +#ifdef VERBOSE + printf("frame read\n"); +#endif + ; + } +#ifdef VERBOSE + printf("Frames finished\n"); +#endif + return OK; + + +} + +int start_and_read_all(int file_des) { + //int dataret=OK; +#ifdef VERBOSE + printf("Starting and reading all frames\n"); +#endif + + 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(); + + /* ret=startStateMachine(); + if (ret!=OK) { + sprintf(mess,"could not start state machine\n"); + sendDataOnly(file_des,&ret,sizeof(ret)); + sendDataOnly(file_des,mess,sizeof(mess)); + + #ifdef VERBOSE + printf("could not start state machine\n"); +#endif +} else {*/ + read_all(file_des); +#ifdef VERBOSE + printf("Frames finished\n"); +#endif + //} + + + return OK; + + +} + +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 PROBES_NUMBER: + sprintf(mess,"can't set timer for moench\n"); + ret=FAIL; + 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"); + } else if (ind==FRAME_NUMBER) { + // ret=allocateRAM(); + // if (ret!=OK) + // sprintf(mess, "could not allocate RAM for %lld frames\n", tns); + } + + 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: + printf("getting frames \n"); + 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 PROBES_NUMBER: + retval=getProbes(); + break; + case CYCLES_NUMBER: + retval=getTrains(); + break; + case PROGRESS: + retval=getProgress(); + break; + case ACTUAL_TIME: + retval=getActualTime(); + break; + case MEASUREMENT_TIME: + retval=getMeasurementTime(); + break; + case FRAMES_FROM_START: + case FRAMES_FROM_START_PG: + retval=getFramesFromStart(); + 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==FAIL) { + 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; + + printf("Set dynamic range?\n"); + 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=setDynamicRange(dr); + } + + //if (dr>=0 && retval!=dr) ret=FAIL; + if (ret!=OK) { + sprintf(mess,"set dynamic range failed\n"); + } else { + /* ret=allocateRAM(); */ +/* if (ret!=OK) */ +/* sprintf(mess,"Could not allocate RAM for the dynamic range selected\n"); */ +// 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,&retval,sizeof(retval)); + } + 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"); + // u_int32_t disable_reg=0; + + n = receiveDataOnly(file_des,&nroi,sizeof(nroi)); + if (n < 0) { + sprintf(mess,"Error reading from socket\n"); + ret=FAIL; + } + + if(myDetectorType == JUNGFRAU){ + ret = FAIL; + strcpy(mess,"Not applicable/implemented for this detector\n"); + printf("Error:Set ROI-%s",mess); + } + + else{ + + if(nroi>=0){ + 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; + } + + printf("Setting ROI to:"); + for( i=0;i=0) { + ret=FAIL; + sprintf(mess,"Detector locked by %s\n",lastClientIP); + } else { + switch (arg) { + case CLOCK_DIVIDER: + retval=setClockDivider(val,0); + break; + +/* case PHASE_SHIFT: */ +/* retval=phaseStep(val,0); */ +/* break; */ + + case OVERSAMPLING: + retval=setOversampling(val); + break; + + case ADC_CLOCK: + retval=setClockDivider(val,1); + break; + +/* case ADC_PHASE: */ +/* retval=phaseStep(val,1); */ +/* break; */ + + + case ADC_PIPELINE: + retval=adcPipeline(val); + break; + + + + default: + ret=FAIL; + sprintf(mess,"Unknown speed parameter %d",arg); + } + } + } + + + } + + + switch (arg) { + case CLOCK_DIVIDER: + retval=getClockDivider(0); + break; + + case PHASE_SHIFT: + retval=getPhase(); + // retval=phaseStep(-1); + //ret=FAIL; + //sprintf(mess,"Cannot read phase",arg); + break; + + case OVERSAMPLING: + retval=setOversampling(-1); + break; + + case ADC_CLOCK: + retval=getClockDivider(1); + break; + + case ADC_PHASE: + retval=getPhase(); + break; + + + case ADC_PIPELINE: + retval=adcPipeline(-1); + break; + + + default: + ret=FAIL; + sprintf(mess,"Unknown speed parameter %d",arg); + } + } + + + + 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)); + + sprintf(mess,"can't set readout flags for moench\n"); + + sendDataOnly(file_des,&ret,sizeof(ret)); + sendDataOnly(file_des,mess,sizeof(mess)); + + return ret; +} + + + + + +int execute_trimming(int file_des) { + + int arg[3]; + int ret=FAIL; + enum trimMode mode; + + sprintf(mess,"can't set execute trimming for moench\n"); + + receiveDataOnly(file_des,&mode,sizeof(mode)); + receiveDataOnly(file_des,arg,sizeof(arg)); + + + sendDataOnly(file_des,&ret,sizeof(ret)); + sendDataOnly(file_des,mess,sizeof(mess)); + + return ret; +} + + +int lock_server(int file_des) { + + + int n; + int ret=OK; + + int lock; + n = receiveDataOnly(file_des,&lock,sizeof(lock)); + if (n < 0) { + sprintf(mess,"Error reading from socket\n"); + printf("Error reading from socket (lock)\n"); + ret=FAIL; + } + if (lock>=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 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 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 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)); + n = sendDataOnly(file_des,&nModX,sizeof(nModX)); + n = sendDataOnly(file_des,&nModY,sizeof(nModY)); + n = sendDataOnly(file_des,&dynamicRange,sizeof(dynamicRange)); + n = sendDataOnly(file_des,&dataBytes,sizeof(dataBytes)); + t=setSettings(GET_SETTINGS,-1); + n = sendDataOnly(file_des,&t,sizeof(t)); +/* thr=getThresholdEnergy(); + n = sendDataOnly(file_des,&thr,sizeof(thr));*/ + 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=setProbes(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[5][50]; + int n; + + int imod=0;//should be in future sent from client as -1, arg[2] + 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); + + //#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 + + + + if (imod>=getNModBoard()) + ret=FAIL; + if (imod<0) + imod=ALLMOD; + + //#ifdef VERBOSE + printf("Configuring MAC of module %d at port %x\n", imod, udpport); + //#endif +#ifdef MCB_FUNCS + 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(); + } +#endif + if (ret==FAIL) + printf("configuring MAC of mod %d failed\n", imod); + else + printf("Configuremac successful of mod %d and adc %d\n",imod,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[N_CHAN*N_CHIP]; + + 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,dataBytes); + if (n < 0) { + sprintf(mess,"Error reading from socket\n"); + ret=FAIL; + } + + 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 set_master(int file_des) { + + enum masterFlags retval=GET_MASTER; + enum masterFlags arg; + int n; + int ret=OK; + // int regret=OK; + + + sprintf(mess,"can't set master flags\n"); + + + n = receiveDataOnly(file_des,&arg,sizeof(arg)); + if (n < 0) { + sprintf(mess,"Error reading from socket\n"); + ret=FAIL; + } + + +#ifdef VERBOSE + printf("setting master flags to %d\n",arg); +#endif + + if (differentClients==1 && lockStatus==1 && arg!=GET_READOUT_FLAGS) { + ret=FAIL; + sprintf(mess,"Detector locked by %s\n",lastClientIP); + } else { + retval=setMaster(arg); + + } + if (retval==GET_MASTER) { + ret=FAIL; + } + 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_synchronization(int file_des) { + + enum synchronizationMode retval=GET_MASTER; + enum synchronizationMode arg; + int n; + int ret=OK; + //int regret=OK; + + + sprintf(mess,"can't set synchronization mode\n"); + + + n = receiveDataOnly(file_des,&arg,sizeof(arg)); + if (n < 0) { + sprintf(mess,"Error reading from socket\n"); + ret=FAIL; + } +#ifdef VERBOSE + printf("setting master flags to %d\n",arg); +#endif + + if (differentClients==1 && lockStatus==1 && arg!=GET_READOUT_FLAGS) { + ret=FAIL; + sprintf(mess,"Detector locked by %s\n",lastClientIP); + } else { + //ret=setStoreInRAM(0); + // initChipWithProbes(0,0,0, ALLMOD); + retval=setSynchronization(arg); + } + if (retval==GET_SYNCHRONIZATION_MODE) { + ret=FAIL; + } + 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 read_counter_block(int file_des) { + + int ret=OK; + int n; + int startACQ; + //char *retval=NULL; + short int CounterVals[N_CHAN*N_CHIP]; + + 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; + } + + 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,dataBytes);//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 start_receiver(int file_des) { + int ret=OK; + int n=0; + strcpy(mess,"Could not start receiver\n"); + + /* execute action if the arguments correctly arrived*/ +#ifdef MCB_FUNCS + if (lockStatus==1 && differentClients==1){//necessary??? + sprintf(mess,"Detector locked by %s\n", lastClientIP); + ret=FAIL; + } + else + ret = startReceiver(1); + +#endif + + + if(ret==OK && differentClients){ + printf("Force update\n"); + ret=FORCE_UPDATE; + } + + /* send answer */ + n = sendDataOnly(file_des,&ret,sizeof(ret)); + if(ret==FAIL) + n = sendDataOnly(file_des,mess,sizeof(mess)); + /*return ok/fail*/ + return ret; +} + + + + + + +int stop_receiver(int file_des) { + int ret=OK; + int n=0; + + strcpy(mess,"Could not stop receiver\n"); + + /* execute action if the arguments correctly arrived*/ +#ifdef MCB_FUNCS + if (lockStatus==1 && differentClients==1){//necessary??? + sprintf(mess,"Detector locked by %s\n", lastClientIP); + ret=FAIL; + } + else + ret=startReceiver(0); + +#endif + + + if(ret==OK && differentClients){ + printf("Force update\n"); + ret=FORCE_UPDATE; + } + + /* send answer */ + n = sendDataOnly(file_des,&ret,sizeof(ret)); + if(ret==FAIL) + n = sendDataOnly(file_des,mess,sizeof(mess)); + /*return ok/fail*/ + return ret; +} + + + + + +int calibrate_pedestal(int file_des){ + + int ret=OK; + int retval=-1; + int n; + int frames; + + sprintf(mess,"Could not calibrate pedestal\n"); + + n = receiveDataOnly(file_des,&frames,sizeof(frames)); + 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=calibratePedestal(frames); + } + + 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)); + else + n += sendDataOnly(file_des,&retval,sizeof(retval)); + + /*return ok/fail*/ + return ret; +} + + +int set_ctb_pattern(int file_des){ + + int ret=OK;//FAIL; + int retval=-1; + int n; + int mode; + uint64_t word, retval64, t; + int addr; + int level, start, stop, nl; + uint64_t pat[1024]; + + sprintf(mess,"Could not set pattern\n"); + + n = receiveDataOnly(file_des,&mode,sizeof(mode)); + printf("pattern mode is %d\n",mode); + switch (mode) { + + case 0: //sets word + n = receiveDataOnly(file_des,&addr,sizeof(addr)); + n = receiveDataOnly(file_des,&word,sizeof(word)); + ret=OK; + + switch (addr) { + case -1: + retval64=writePatternIOControl(word); + break; + case -2: + retval64=writePatternClkControl(word); + break; + default: + retval64=writePatternWord(addr,word); + }; + + + //write word; + //@param addr address of the word, -1 is I/O control register, -2 is clk control register + //@param word 64bit word to be written, -1 gets + + n = sendDataOnly(file_des,&ret,sizeof(ret)); + if (ret==FAIL) + n += sendDataOnly(file_des,mess,sizeof(mess)); + else + n += sendDataOnly(file_des,&retval64,sizeof(retval64)); + break; + + case 1: //pattern loop + n = receiveDataOnly(file_des,&level,sizeof(level)); + n = receiveDataOnly(file_des,&start,sizeof(start)); + n = receiveDataOnly(file_des,&stop,sizeof(stop)); + n = receiveDataOnly(file_des,&nl,sizeof(nl)); + + + + printf("level %d start %x stop %x nl %d\n",level, start, stop, nl); + /** Sets the pattern or loop limits in the CTB + @param level -1 complete pattern, 0,1,2, loop level + @param start start address if >=0 + @param stop stop address if >=0 + @param n number of loops (if level >=0) + @returns OK/FAIL + */ + ret=setPatternLoop(level, &start, &stop, &nl); + + n = sendDataOnly(file_des,&ret,sizeof(ret)); + if (ret==FAIL) + n += sendDataOnly(file_des,mess,sizeof(mess)); + else { + n += sendDataOnly(file_des,&start,sizeof(start)); + n += sendDataOnly(file_des,&stop,sizeof(stop)); + n += sendDataOnly(file_des,&nl,sizeof(nl)); + } + break; + + + + case 2: //wait address + n = receiveDataOnly(file_des,&level,sizeof(level)); + n = receiveDataOnly(file_des,&addr,sizeof(addr)); + + + + /** Sets the wait address in the CTB + @param level 0,1,2, wait level + @param addr wait address, -1 gets + @returns actual value + */ + printf("wait addr %d %x\n",level, addr); + retval=setPatternWaitAddress(level,addr); + printf("ret: wait addr %d %x\n",level, retval); + ret=OK; + 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)); + + } + + + break; + + + case 3: //wait time + n = receiveDataOnly(file_des,&level,sizeof(level)); + n = receiveDataOnly(file_des,&t,sizeof(t)); + + + /** Sets the wait time in the CTB + @param level 0,1,2, wait level + @param t wait time, -1 gets + @returns actual value + */ + + ret=OK; + + retval64=setPatternWaitTime(level,t); + + n = sendDataOnly(file_des,&ret,sizeof(ret)); + if (ret==FAIL) + n += sendDataOnly(file_des,mess,sizeof(mess)); + else + n += sendDataOnly(file_des,&retval64,sizeof(retval64)); + + break; + + + + case 4: + n = receiveDataOnly(file_des,pat,sizeof(pat)); + for (addr=0; addr<1024; addr++) + writePatternWord(addr,word); + ret=OK; + retval=0; + n = sendDataOnly(file_des,&ret,sizeof(ret)); + if (ret==FAIL) + n += sendDataOnly(file_des,mess,sizeof(mess)); + else + n += sendDataOnly(file_des,&retval64,sizeof(retval64)); + + break; + + + + + + default: + ret=FAIL; + printf(mess); + sprintf(mess,"%s - wrong mode %d\n",mess, mode); + n = sendDataOnly(file_des,&ret,sizeof(ret)); + n += sendDataOnly(file_des,mess,sizeof(mess)); + + + + } + + + /*return ok/fail*/ + return ret; +} + + +int write_adc_register(int file_des) { + + int retval; + int ret=OK; + int arg[2]; + int addr, val; + int n; + + 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){ + ret=writeADC(addr,val); + if (ret==OK) + retval=val; + } + + +#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; + +} diff --git a/slsDetectorSoftware/jctbDetectorServer/server_funcs.h b/slsDetectorSoftware/jctbDetectorServer/server_funcs.h new file mode 100755 index 000000000..2d674a1d0 --- /dev/null +++ b/slsDetectorSoftware/jctbDetectorServer/server_funcs.h @@ -0,0 +1,98 @@ +#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); + +int M_nofunc(int); +int exit_server(int); + + + + +// General purpose functions +int get_detector_type(int); +int set_number_of_modules(int); +int get_max_number_of_modules(int); + + +int exec_command(int); +int set_external_signal_flag(int); +int set_external_communication_mode(int); +int get_id(int); +int digital_test(int); +int write_register(int); +int read_register(int); +int set_dac(int); +int get_adc(int); +int set_channel(int); +int set_chip(int); +int set_module(int); +int get_channel(int); +int get_chip(int); +int get_module(int); + +int get_threshold_energy(int); +int set_threshold_energy(int); +int set_settings(int); +int start_acquisition(int); +int stop_acquisition(int); +int start_readout(int); +int get_run_status(int); +int read_frame(int); +int read_all(int); +int start_and_read_all(int); +int set_timer(int); +int get_time_left(int); +int set_dynamic_range(int); +int set_roi(int); +int get_roi(int); +int set_speed(int); +int set_readout_flags(int); +int execute_trimming(int); +int lock_server(int); +int set_port(int); +int get_last_client_ip(int); +int set_master(int); +int set_synchronization(int); + +int update_client(int); +int send_update(int); +int configure_mac(int); + +int load_image(int); +int read_counter_block(int); +int reset_counter_block(int); + +int start_receiver(int); +int stop_receiver(int); + + +int calibrate_pedestal(int); + +int set_roi(int); +int set_ctb_pattern(int); + +int write_adc_register(int);; +#endif diff --git a/slsDetectorSoftware/jctbDetectorServer/sharedmemory.c b/slsDetectorSoftware/jctbDetectorServer/sharedmemory.c new file mode 100755 index 000000000..4504cfe05 --- /dev/null +++ b/slsDetectorSoftware/jctbDetectorServer/sharedmemory.c @@ -0,0 +1,39 @@ +#include "sharedmemory.h" + +struct statusdata *stdata; + +int inism(int clsv) { + +static int scansmid; + + if (clsv==SMSV) { + if ( (scansmid=shmget(SMKEY,1024,IPC_CREAT | 0666 ))==-1 ) { + return -1; + } + if ( (stdata=shmat(scansmid,NULL,0))==(void*)-1) { + return -2; + } + } + + if (clsv==SMCL) { + if ( (scansmid=shmget(SMKEY,0,0) )==-1 ) { + return -3; + } + if ( (stdata=shmat(scansmid,NULL,0))==(void*)-1) { + return -4; + } + } + return 1; +} + +void write_status_sm(char *status) { + strcpy(stdata->status,status); +} + +void write_stop_sm(int v) { + stdata->stop=v; +} + +void write_runnumber_sm(int v) { + stdata->runnumber=v; +} diff --git a/slsDetectorSoftware/jctbDetectorServer/sharedmemory.h b/slsDetectorSoftware/jctbDetectorServer/sharedmemory.h new file mode 100755 index 000000000..bdbddf719 --- /dev/null +++ b/slsDetectorSoftware/jctbDetectorServer/sharedmemory.h @@ -0,0 +1,48 @@ +#ifndef SM +#define SM + +#include "sls_detector_defs.h" + +#include +#include +#include +#include +#include +#include +#include +//#include +#include +#include +#include +#include +#include +#include + + +#include + +#include +#include + +/* key for shared memory */ +#define SMKEY 10001 + +#define SMSV 1 +#define SMCL 2 + + +struct statusdata { + int runnumber; + int stop; + char status[20]; +} ; + + +/* for shared memory */ + +int inism(int clsv); +void write_status_sm(char *status); +void write_stop_sm(int v); +void write_runnumber_sm(int v); + +#endif diff --git a/slsDetectorSoftware/jctbDetectorServer/sls_detector_defs.h b/slsDetectorSoftware/jctbDetectorServer/sls_detector_defs.h new file mode 120000 index 000000000..c5062e03f --- /dev/null +++ b/slsDetectorSoftware/jctbDetectorServer/sls_detector_defs.h @@ -0,0 +1 @@ +../commonFiles/sls_detector_defs.h \ No newline at end of file diff --git a/slsDetectorSoftware/jctbDetectorServer/sls_detector_funcs.h b/slsDetectorSoftware/jctbDetectorServer/sls_detector_funcs.h new file mode 120000 index 000000000..844b67129 --- /dev/null +++ b/slsDetectorSoftware/jctbDetectorServer/sls_detector_funcs.h @@ -0,0 +1 @@ +../commonFiles/sls_detector_funcs.h \ No newline at end of file diff --git a/slsDetectorSoftware/jctbDetectorServer/sls_receiver_defs.h b/slsDetectorSoftware/jctbDetectorServer/sls_receiver_defs.h new file mode 120000 index 000000000..1de31caf5 --- /dev/null +++ b/slsDetectorSoftware/jctbDetectorServer/sls_receiver_defs.h @@ -0,0 +1 @@ +../../slsReceiverSoftware/include/sls_receiver_defs.h \ No newline at end of file diff --git a/slsDetectorSoftware/jctbDetectorServer/sls_receiver_funcs.h b/slsDetectorSoftware/jctbDetectorServer/sls_receiver_funcs.h new file mode 120000 index 000000000..c2ea4ded9 --- /dev/null +++ b/slsDetectorSoftware/jctbDetectorServer/sls_receiver_funcs.h @@ -0,0 +1 @@ +../../slsReceiverSoftware/include/sls_receiver_funcs.h \ No newline at end of file diff --git a/slsDetectorSoftware/jctbDetectorServer/stop_server.c b/slsDetectorSoftware/jctbDetectorServer/stop_server.c new file mode 100755 index 000000000..e3c8ff7e1 --- /dev/null +++ b/slsDetectorSoftware/jctbDetectorServer/stop_server.c @@ -0,0 +1,46 @@ +/* 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; +} +