diff --git a/slsDetectorSoftware/eigerDetectorServer/9mhvserial_bf.c b/slsDetectorSoftware/eigerDetectorServer/9mhvserial_bf.c new file mode 100644 index 000000000..ee7b51e05 --- /dev/null +++ b/slsDetectorSoftware/eigerDetectorServer/9mhvserial_bf.c @@ -0,0 +1,188 @@ +#include "ansi.h" + +#include /* POSIX terminal control definitions */ +#include +#include // atoi +#include // File control definitions +#include // ioctl +#include // read, close +#include // memset +#include // I2C_SLAVE, __u8 reg + +#define PORTNAME "/dev/ttyBF1" +#define GOODBYE 200 +#define BUFFERSIZE 255 +#define I2C_DEVICE_FILE "/dev/i2c-0" +#define I2C_DEVICE_ADDRESS 0x4C +//#define I2C_DEVICE_ADDRESS 0x48 +#define I2C_REGISTER_ADDRESS 0x40 + + + +int i2c_open(const char* file,unsigned int addr){ + + //device file + int fd = open( file, O_RDWR ); + if (fd < 0) { + cprintf(RED,"Warning: Unable to open file %s\n",file); + return -1; + } + + //device address + if( ioctl( fd, I2C_SLAVE, addr&0x7F ) < 0 ) { + cprintf(RED,"Warning: Unable to set slave address:0x%x \n",addr); + return -2; + } + return fd; +} + + +int i2c_read(){ + + int fd = i2c_open(I2C_DEVICE_FILE, I2C_DEVICE_ADDRESS); + __u8 reg = I2C_REGISTER_ADDRESS & 0xff; + + unsigned char buf = reg; + if (write(fd, &buf, 1)!= 1){ + cprintf(RED,"Warning: Unable to write read request to register %d\n", reg); + return -1; + } + //read and update value (but old value read out) + if(read(fd, &buf, 1) != 1){ + cprintf(RED,"Warning: Unable to read register %d\n", reg); + return -2; + } + //read again to read the updated value + if(read(fd, &buf, 1) != 1){ + cprintf(RED,"Warning: Unable to read register %d\n", reg); + return -2; + } + close(fd); + return buf; +} + + +int i2c_write(unsigned int value){ + + __u8 val = value & 0xff; + + int fd = i2c_open(I2C_DEVICE_FILE, I2C_DEVICE_ADDRESS); + if(fd < 0) + return fd; + + __u8 reg = I2C_REGISTER_ADDRESS & 0xff; + char buf[3]; + buf[0] = reg; + buf[1] = val; + if (write(fd, buf, 2) != 2) { + cprintf(RED,"Warning: Unable to write %d to register %d\n",val, reg); + return -1; + } + + close(fd); + return 0; +} + + + + + +int main(int argc, char* argv[]) { + + int fd = open(PORTNAME, O_RDWR | O_NOCTTY); + if(fd < 0){ + cprintf(RED,"Warning: Unable to open port %s\n", PORTNAME); + return -1; + } + + struct termios serial_conf; + // Get the current options for the port + tcgetattr(fd, &serial_conf); + // reset structure + memset(&serial_conf,0,sizeof(serial_conf)); + // control options + serial_conf.c_cflag = B2400 | CS8 | CREAD | CLOCAL; + // input options + serial_conf.c_iflag = IGNPAR; + // output options + serial_conf.c_oflag = 0; + // line options + serial_conf.c_lflag = ICANON; + // flush input + tcflush(fd, TCIFLUSH); + // set new options for the port, TCSANOW:changes occur immediately without waiting for data to complete + tcsetattr(fd, TCSANOW, &serial_conf); + + + + + int ret = 0; + int n = 0; + int ival= 0; + char buffer[BUFFERSIZE]=""; + cprintf(GREEN,"Ready...\n"); + + while(ret != GOODBYE){ + memset(buffer, 0, BUFFERSIZE); + buffer[BUFFERSIZE-1]='\n'; + + n = read(fd,buffer,BUFFERSIZE); +#ifdef VERBOSE + cprintf(BLUE,"Received %d Bytes\n", n); +#endif + cprintf(BLUE,"Got message: %s\n",buffer); + + switch(buffer[0]){ + case 'p': + if (!sscanf(&buffer[1],"%d",&ival)){ + cprintf(RED,"Warning: cannot scan voltage value\n"); + break; + } + + if(i2c_write(ival)<0) + strcpy(buffer,"failed"); + else + strcpy(buffer,"successful"); + cprintf(GREEN,"%s\n",buffer); + n = write(fd, buffer, BUFFERSIZE); +#ifdef VERBOSE + cprintf(BLUE,"Sent %d Bytes\n", n); +#endif + break; + + case 'g': + ival = i2c_read(); + //ok/ fail + if(ival < 0) + strcpy(buffer,"failed"); + else + strcpy(buffer,"successful"); + n = write(fd, buffer, BUFFERSIZE); +#ifdef VERBOSE + cprintf(BLUE,"Sent %d Bytes\n", n); +#endif + //value + if(ival >= 0){ + cprintf(GREEN,"%d\n",ival); + sprintf(buffer,"%d\n",ival); + n = write(fd, buffer, BUFFERSIZE); +#ifdef VERBOSE + cprintf(BLUE,"Sent %d Bytes\n", n); +#endif + }else cprintf(GREEN,"%s\n",buffer); + break; + + case 'e': + printf("Exiting Program\n"); + ret = GOODBYE; + break; + default: + printf("Unknown Command\n"); + break; + } + } + + close(fd); + printf("Goodbye Serial Communication for HV(9M)\n"); + return 0; +} diff --git a/slsDetectorSoftware/eigerDetectorServer/FebControl.c b/slsDetectorSoftware/eigerDetectorServer/FebControl.c index 1786f16a3..1cc31b39b 100644 --- a/slsDetectorSoftware/eigerDetectorServer/FebControl.c +++ b/slsDetectorSoftware/eigerDetectorServer/FebControl.c @@ -12,13 +12,7 @@ #include #include #include - -//#include -//#include -//#include -//#include - - +#include // POSIX terminal control definitions(CS8, CREAD, CLOCAL..) #include "FebRegisterDefs.h" #include "FebControl.h" @@ -68,6 +62,7 @@ double Feb_Control_rate_meas[16384]; double ratemax=-1; int Feb_Control_activated = 1; +int Feb_Control_hv_fd = -1; void Module_Module(struct Module* mod,unsigned int number, unsigned int address_top){ @@ -224,11 +219,45 @@ int Feb_Control_Init(int master, int top, int normal, int module_num){ if(Feb_Control_activated) Feb_Interface_SetByteOrder(); + //master of 9M, set up high voltage serial communication to blackfin + if(Feb_control_master && !Feb_control_normal){ + if(!Feb_Control_SetupSerialCommunication()) + return 0; + } return 1; } +int Feb_Control_SetupSerialCommunication(){ + + Feb_Control_hv_fd = open(SPECIAL9M_HIGHVOLTAGE_PORT, O_RDWR | O_NOCTTY); + if(Feb_Control_hv_fd < 0){ + cprintf(RED,"Warning: Unable to open port %s to set up high voltage serial communciation to the blackfin\n", SPECIAL9M_HIGHVOLTAGE_PORT); + return 0; + } + + struct termios serial_conf; + // Get the current options for the port + tcgetattr(Feb_Control_hv_fd, &serial_conf); + // reset structure + memset(&serial_conf,0,sizeof(serial_conf)); + // control options + serial_conf.c_cflag = B2400 | CS8 | CREAD | CLOCAL;//57600 too high + // input options + serial_conf.c_iflag = IGNPAR; + // output options + serial_conf.c_oflag = 0; + // line options + serial_conf.c_lflag = ICANON; + // flush input + tcflush(Feb_Control_hv_fd, TCIFLUSH); + // set new options for the port, TCSANOW:changes occur immediately without waiting for data to complete + tcsetattr(Feb_Control_hv_fd, TCSANOW, &serial_conf); + + return 1; +} + void Feb_Control_PrintModuleList(){ unsigned int i; @@ -496,89 +525,183 @@ float Feb_Control_DACToVoltage(unsigned int digital,unsigned int nsteps,float vm //only master gets to call this function int Feb_Control_SetHighVoltage(int value){ - - if(!Feb_control_normal){ - cprintf(RED,"\nError: Setting High Voltage not implemented for special modules\n"); - return 0; - } - - printf(" Setting High Voltage: %d(v)\t",value); - - static const unsigned int nsteps = 256; - static const float vmin=0; - static const float vmax=300; + printf(" Setting High Voltage: %dV\t",value); + /* + * maximum voltage of the hv dc/dc converter: + * 300 for single module power distribution board + * 200 for 9M power distribution board + * but limit is 200V for both + */ + const float vmin=0; + float vmax=200; + if(Feb_control_normal) + vmax=300; + const float vlimit=200; + const unsigned int ntotalsteps = 256; + unsigned int nsteps = ntotalsteps*vlimit/vmax; unsigned int dacval = 0; - //open file - FILE* fd=fopen("/sys/class/hwmon/hwmon5/device/out0_output","w"); - if(fd==NULL){ - cprintf(RED,"\nWarning: Could not open file for writing to set high voltage\n"); - return 0; - } //calculate dac value - if(!Feb_Control_VoltageToDAC(value,&dacval,nsteps,vmin,vmax)){ - cprintf(RED,"\nWarning: SetHighVoltage bad value, %d. The range is 0 to 300 V.\n",value); + if(!Feb_Control_VoltageToDAC(value,&dacval,nsteps,vmin,vlimit)){ + cprintf(RED,"\nWarning: SetHighVoltage bad value, %d. The range is 0 to %d V.\n",value, (int)vlimit); return 0; } - //convert to string, add 0 and write to file - fprintf(fd, "%d0\n", dacval); + printf("(%d dac): ",dacval); - printf("%d(dac)\n", dacval); - fclose(fd); - - return 1; + return Feb_Control_SendHighVoltage(dacval); } int Feb_Control_GetHighVoltage(int* value){ - - if(!Feb_control_normal){ - cprintf(RED,"\nError: Getting High Voltage not implemented for special modules\n"); - return 0; - } - - printf(" Getting High Voltage: "); - static const unsigned int nsteps = 256; - static const float vmin=0; - static const float vmax=300; - + printf(" Getting High Voltage:\t"); unsigned int dacval = 0; - size_t readbytes=0; - char* line=NULL; + if(!Feb_Control_ReceiveHighVoltage(&dacval)) + return 0; - //open file - FILE* fd=fopen("/sys/class/hwmon/hwmon5/device/in0_input","r"); - if(fd==NULL){ - cprintf(RED,"\nWarning: Could not open file for writing to get high voltage\n"); - return 0; - } - // Read twice, since the first value is sometimes outdated - if(getline(&line, &readbytes, fd) == -1){ - cprintf(RED,"\nWarning: could not read file to get high voltage\n"); - return 0; - } - rewind(fd); - free(line); - readbytes=0; - readbytes = getline(&line, &readbytes, fd); - if(readbytes == -1){ - cprintf(RED,"\nWarning: could not read file to get high voltage\n"); - return 0; - } - - // Remove the trailing 0 - dacval = atoi(line)/10; - //convert dac to v - *value = (int)(Feb_Control_DACToVoltage(dacval,nsteps,vmin,vmax)+0.5); - printf("%d(v)\t%d(dac)\n", *value, dacval); - free(line); - fclose(fd); + //ok, convert dac to v + /* + * maximum voltage of the hv dc/dc converter: + * 300 for single module power distribution board + * 200 for 9M power distribution board + * but limit is 200V for both + */ + const float vmin=0; + float vmax=200; + if(Feb_control_normal) + vmax=300; + const float vlimit=200; + const unsigned int ntotalsteps = 256; + unsigned int nsteps = ntotalsteps*vlimit/vmax; + *value = (int)(Feb_Control_DACToVoltage(dacval,nsteps,vmin,vlimit)+0.5); + printf("(%d dac)\t%dV\n", dacval, *value); return 1; } +int Feb_Control_SendHighVoltage(int dacvalue){ + //normal + if(Feb_control_normal){ + //open file + FILE* fd=fopen(NORMAL_HIGHVOLTAGE_OUTPUTPORT,"w"); + if(fd==NULL){ + cprintf(RED,"\nWarning: Could not open file for writing to set high voltage\n"); + return 0; + } + //convert to string, add 0 and write to file + fprintf(fd, "%d0\n", dacvalue); + fclose(fd); + } + + //9m + else{ + if (Feb_Control_hv_fd == -1){ + cprintf(RED,"\nWarning: High voltage serial communication not set up for 9m\n"); + return 0; + } + + char buffer[SPECIAL9M_HIGHVOLTAGE_BUFFERSIZE]=""; + buffer[SPECIAL9M_HIGHVOLTAGE_BUFFERSIZE-1]='\n'; + int n = 0; + sprintf(buffer,"p%d",dacvalue); + n = write(Feb_Control_hv_fd, buffer, SPECIAL9M_HIGHVOLTAGE_BUFFERSIZE); +#ifdef VERBOSE + cprintf(BLUE,"Sent %d Bytes\n", n); +#endif + + //ok/fail + n = read(Feb_Control_hv_fd, buffer, SPECIAL9M_HIGHVOLTAGE_BUFFERSIZE); + #ifdef VERBOSE + cprintf(BLUE,"Received %d Bytes\n", n); + #endif + if(buffer[0] == 'f'){ + cprintf(RED,"\nError: Failed to set high voltage\n"); + return 0; + } + cprintf(GREEN,"%s\n",buffer); + } + + return 1; +} + + + + + + + +int Feb_Control_ReceiveHighVoltage(unsigned int* value){ + + //normal + if(Feb_control_normal){ + //open file + FILE* fd=fopen(NORMAL_HIGHVOLTAGE_INPUTPORT,"r"); + if(fd==NULL){ + cprintf(RED,"\nWarning: Could not open file for writing to get high voltage\n"); + return 0; + } + + //read, assigning line to null and readbytes to 0 then getline allocates initial buffer + size_t readbytes=0; + char* line=NULL; + if(getline(&line, &readbytes, fd) == -1){ + cprintf(RED,"\nWarning: could not read file to get high voltage\n"); + return 0; + } + //read again to read the updated value + rewind(fd); + free(line); + readbytes=0; + readbytes = getline(&line, &readbytes, fd); + if(readbytes == -1){ + cprintf(RED,"\nWarning: could not read file to get high voltage\n"); + return 0; + } + // Remove the trailing 0 + *value = atoi(line)/10; + free(line); + fclose(fd); + } + + + //9m + else{ + if (Feb_Control_hv_fd == -1){ + cprintf(RED,"\nWarning: High voltage serial communication not set up for 9m\n"); + return 0; + } + char buffer[SPECIAL9M_HIGHVOLTAGE_BUFFERSIZE]=""; + buffer[SPECIAL9M_HIGHVOLTAGE_BUFFERSIZE-1]='\n'; + int n = 0; + //request + strcpy(buffer,"g"); + n = write(Feb_Control_hv_fd, buffer, SPECIAL9M_HIGHVOLTAGE_BUFFERSIZE); +#ifdef VERBOSE + cprintf(BLUE,"Sent %d Bytes\n", n); +#endif + + //ok/fail + n = read(Feb_Control_hv_fd, buffer, SPECIAL9M_HIGHVOLTAGE_BUFFERSIZE); +#ifdef VERBOSE + cprintf(BLUE,"Received %d Bytes\n", n); +#endif + if(buffer[0] == 'f'){ + cprintf(RED,"\nWarning: failed to read high voltage\n"); + return 0; + } + + n = read(Feb_Control_hv_fd, buffer, SPECIAL9M_HIGHVOLTAGE_BUFFERSIZE); +#ifdef VERBOSE + cprintf(BLUE,"Received %d Bytes\n", n); +#endif + if (!sscanf(buffer,"%d",value)){ + cprintf(RED,"\nWarning: failed to scan high voltage read\n"); + return 0; + } + } + return 1; +} diff --git a/slsDetectorSoftware/eigerDetectorServer/FebControl.h b/slsDetectorSoftware/eigerDetectorServer/FebControl.h index 620ab003a..2d7abf369 100644 --- a/slsDetectorSoftware/eigerDetectorServer/FebControl.h +++ b/slsDetectorSoftware/eigerDetectorServer/FebControl.h @@ -112,6 +112,7 @@ int Feb_Control_GetModuleNumber(); void Feb_Control_FebControl(); int Feb_Control_Init(int master, int top, int normal, int module_num); + int Feb_Control_SetupSerialCommunication(); int Feb_Control_CheckSetup(); unsigned int Feb_Control_GetNModules(); @@ -120,6 +121,9 @@ int Feb_Control_GetModuleNumber(); int Feb_Control_SetHighVoltage(int value); int Feb_Control_GetHighVoltage(int* value); + int Feb_Control_SendHighVoltage(int dacvalue); + int Feb_Control_ReceiveHighVoltage(unsigned int* value); + int Feb_Control_SetIDelays(unsigned int module_num, unsigned int ndelay_units); int Feb_Control_SetIDelays1(unsigned int module_num, unsigned int chip_pos, unsigned int ndelay_units); diff --git a/slsDetectorSoftware/eigerDetectorServer/Makefile b/slsDetectorSoftware/eigerDetectorServer/Makefile index 462930bac..c615356b9 100755 --- a/slsDetectorSoftware/eigerDetectorServer/Makefile +++ b/slsDetectorSoftware/eigerDetectorServer/Makefile @@ -1,5 +1,6 @@ CC = powerpc-4xx-softfloat-gcc CCX = powerpc-4xx-softfloat-g++ +BLACKFIN_CC = bfin-uclinux-gcc CFLAGS += -Wall -DDACS_INT -DEIGERD -DSLS_DETECTOR_FUNCTION_LIST -DDACS_INT -DSTOP_SERVER #-DVERBOSE #-DVIRTUAL -DPCCOMPILE -DMARTIN LDLIBS += -lm -lstdc++ @@ -15,7 +16,7 @@ SRC_CLNT = communication_funcs.c slsDetectorServer.c slsDetectorServer_funcs.c OBJS = $(SRC_CLNT:.c=.o) -all: clean $(PROGS) #feb_debug beb_debug +all: clean $(PROGS) hv9m_blackfin_server #feb_debug beb_debug boot: $(OBJS) @@ -33,7 +34,12 @@ feb_debug:$(SRC_CLNT2) beb_debug:$(SRC_CLNT3) $(CCX) -o beb_debug $(SRC_CLNT3) -I. mv beb_debug $(DESTDIR) + +hv9m_blackfin_server:9mhvserial_bf.c + $(BLACKFIN_CC) -o hv9m_blackfin_server 9mhvserial_bf.c -Wall + mv hv9m_blackfin_server $(DESTDIR) + rm hv9m_blackfin_server.gdb clean: - rm -rf $(DESTDIR)/$(PROGS) *.o + rm -rf $(DESTDIR)/$(PROGS) *.o $(DESTDIR)/hv9m_blackfin_server diff --git a/slsDetectorSoftware/eigerDetectorServer/bin/eigerDetectorServerv2.2.0.16.4 b/slsDetectorSoftware/eigerDetectorServer/bin/eigerDetectorServerv2.2.0.16.5 similarity index 52% rename from slsDetectorSoftware/eigerDetectorServer/bin/eigerDetectorServerv2.2.0.16.4 rename to slsDetectorSoftware/eigerDetectorServer/bin/eigerDetectorServerv2.2.0.16.5 index 9eaa0aef8..fa4b08d21 100755 Binary files a/slsDetectorSoftware/eigerDetectorServer/bin/eigerDetectorServerv2.2.0.16.4 and b/slsDetectorSoftware/eigerDetectorServer/bin/eigerDetectorServerv2.2.0.16.5 differ diff --git a/slsDetectorSoftware/eigerDetectorServer/bin/hv9m_blackfin_server b/slsDetectorSoftware/eigerDetectorServer/bin/hv9m_blackfin_server new file mode 100755 index 000000000..96d5acb7b Binary files /dev/null and b/slsDetectorSoftware/eigerDetectorServer/bin/hv9m_blackfin_server differ diff --git a/slsDetectorSoftware/eigerDetectorServer/slsDetectorServer_defs.h b/slsDetectorSoftware/eigerDetectorServer/slsDetectorServer_defs.h index f4dfdc073..650ad9890 100644 --- a/slsDetectorSoftware/eigerDetectorServer/slsDetectorServer_defs.h +++ b/slsDetectorSoftware/eigerDetectorServer/slsDetectorServer_defs.h @@ -44,6 +44,11 @@ enum detAdcIndex{TEMP_FPGAEXT, TEMP_10GE, TEMP_DCDC, TEMP_SODL, TEMP_SODR, TEMP_ enum detNetworkParameter{TXN_LEFT, TXN_RIGHT, TXN_FRAME,FLOWCTRL_10G}; +#define NORMAL_HIGHVOLTAGE_INPUTPORT "/sys/class/hwmon/hwmon5/device/in0_input" +#define NORMAL_HIGHVOLTAGE_OUTPUTPORT "/sys/class/hwmon/hwmon5/device/out0_output" +#define SPECIAL9M_HIGHVOLTAGE_PORT "/dev/ttyS1" +#define SPECIAL9M_HIGHVOLTAGE_BUFFERSIZE 8 + #endif /* SLSDETECTORSERVER_DEFS_H_ */