Changeset 90
- Timestamp:
- 07/24/09 09:33:15 (15 years ago)
- Location:
- hvcontrol
- Files:
-
- 1 added
- 20 deleted
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
hvcontrol/Makefile
r72 r90 3 3 # 4 4 5 SOURCES = hvcontrol.cpp src/CCCommand.cc src/ConsoleCommand.cc src/HV.cc src/HVConfig.cc src/HVCalib.cc src/HVMonitor.cc src/HVStatus.cc src/Log.cc src/ProcessIO.cc src/ReadCard.cc src/Utilities.cc ../pixelmap/Pixel.cc ../pixelmap/PixelMap.cc 6 5 SOURCES = hvcontrol.cpp src/HV.cc src/HVConfig.cc src/HVCalib.cc src/ProcessIO.cc ../pixelmap/Pixel.cc ../pixelmap/PixelMap.cc 7 6 OBJECTS = $(addsuffix .o, $(basename $(SOURCES))) 8 9 7 INCDIRS = -I. -I../pixelmap -I./src 10 8 11 CFLAGS = -pipe -fthread-jumps -funroll-all-loops -O3 -Wall -DOS_LINUX 12 CPPFLAGS = -pipe -fPIC -fthread-jumps -funroll-all-loops -O3 -Wall -DOS_LINUX $(VMECTRL) 13 LIBS = -lstdc++ -lz -lpthread -lutil -lfl -lusb -lftdi -L/usr/lib -L/sw/lib 9 CPPFLAGS = -O3 -Wall -DOS_LINUX 10 LIBS = -lstdc++ -lpthread -lfl -lreadline -ltermcap 14 11 15 12 hvcontrol: $(OBJECTS) … … 25 22 # Implicit rules 26 23 27 %.o : %.c28 $(CC) $(CFLAGS) $(INCDIRS) -c -o $@ $<29 24 %.o : %.cc 30 25 $(CC) $(CPPFLAGS) $(INCDIRS) -c -o $@ $< -
hvcontrol/hvcontrol.cpp
r72 r90 21 21 #include <pthread.h> 22 22 #include <signal.h> 23 24 #include "ConsoleCommand.h" 25 #include "CCCommand.h" 23 #include <sys/socket.h> 24 #include <netdb.h> 25 #include <arpa/inet.h> 26 26 27 #include "ProcessIO.h" 27 #include "HVMonitor.h" 28 #include "Types.h" 29 30 #define Sleep(x) usleep(x*1000) 31 32 #define DEFAULT_CONFIG "HV.conf" // Default configuration file 28 29 #include <readline/readline.h> // Must be after including ftdi.h! 30 #include <readline/history.h> 31 32 #define DEFAULT_CONFIG "../config/HV.conf" // Default configuration file 33 33 #define LOCKFILE "/tmp/CTX_HV_LOCK" 34 34 35 void CrashHandler(int Signal); 36 35 // Function prototypes 36 void ConsoleCommand(ProcessIO *); 37 void CCCommand(ProcessIO *); 38 void HVMonitor(ProcessIO *); 39 void SignalHandler(int); 40 void CrashHandler(int); 41 42 // ================ 43 // Main program 44 // ================ 45 // 46 // Several unlikely system call failures are handled via throwing an exception. 37 47 38 48 int main(int argc, char *argv[]) { 39 49 40 41 50 char config_file[] = DEFAULT_CONFIG, str[MAX_COM_SIZE]; 42 43 pthread_t thread_ConsoleCommand; // Read commands from console 44 pthread_t thread_HVMonitor; // Reads continuously from HV board(s) 45 pthread_t thread_CCCommand; // Thread listening to commands from Central Control 46 51 pthread_t thread_ConsoleCommand,thread_HVMonitor,thread_CCCommand; 47 52 int LockDescriptor; 53 54 // Interpret command line (do before lockfile creation in case of exit()) 55 if((argc==3 && strcmp(argv[1],"-c")!=0) || argc==2) { 56 printf("Usage: %s [-c <ConfigFile>] Default file is \"%s\"\n", argv[0], DEFAULT_CONFIG); 57 exit(EXIT_SUCCESS); 58 } 48 59 49 60 // Assure only one instance of the HV control program runs 50 61 // The flag O_EXCL together with O_CREAT assure that the lock 51 62 // file cannot be opened by another instance, i.e. there are no parallel write accesses 52 /* if ((LockDescriptor = open(LOCKFILE,O_RDONLY|O_CREAT|O_EXCL)) == -1) {53 sprintf(str, "Could not create lock file %s", LOCKFILE);54 perror(str);55 exit(EXIT_FAILURE);56 }57 close(LockDescriptor);58 */59 63 if((LockDescriptor = open(LOCKFILE,O_WRONLY|O_CREAT|O_EXCL,S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH)) == -1) { 60 64 if(errno==EEXIST) { … … 63 67 system(str); 64 68 } 65 else { 66 sprintf(str, "Could not create lock file %s", LOCKFILE); 67 perror(str); 68 } 69 else printf("Could not create lock file %s (%s)\n", LOCKFILE, strerror(errno)); 69 70 exit(EXIT_FAILURE); 70 71 } … … 72 73 sprintf(str,"echo Created >%s; date >>%s; echo by $USER@$HOSTNAME>>%s",LOCKFILE,LOCKFILE,LOCKFILE); 73 74 system(str); 74 75 76 for (int i=1; i<argc; i++) {77 if (argv[i][0] == '-') {78 if (argv[i][1] == 'h') {79 printf("Usage: %s [-c <ConfigFile>] default file is \"%s\"\n", argv[0], config_file);80 exit(1);81 }82 if (argv[i][1] == 'c') {83 if (argc<i+2) {84 printf("Error: missing configuration file after -c option\n");85 exit(1);86 } else {87 sprintf(config_file, "%s", argv[i+1]);88 }89 }90 }91 }92 75 93 76 system("clear"); 94 printf("\n****************** HV Control %s built %s, %s by S. Commichau, updated by S. Stark ******************\n\n",HV_CONTROL_VERSION,__DATE__,__TIME__); 95 96 97 // Construct main instance 98 ProcessIO pio(config_file); 77 printf("\n*** HV Control built %s, %s (S.Commichau, S.Stark, O.Grimm) ***\n\n",__DATE__,__TIME__); 99 78 100 // Install signal handler and set signal SIGUSR1 to interrupt blocking system calls79 // Install signal handler and set signal SIGUSR1 to interrupt blocking system calls 101 80 signal(SIGUSR1, &SignalHandler); 102 81 siginterrupt (SIGUSR1, true); … … 113 92 signal(SIGHUP, &CrashHandler); 114 93 94 // Construct main instance and create mutex for thread synchronization 95 ProcessIO pio(config_file); 96 if (pthread_mutex_init(&pio.control_mutex, NULL) != 0) { 97 perror("pthread_mutex_init failed"); 98 throw; 99 } 115 100 116 101 // Create threads 117 102 if ((pthread_create(&thread_ConsoleCommand, NULL, (void * (*)(void *)) ConsoleCommand,(void *) &pio)) != 0) { 118 fprintf(stderr, "pthread_create failed with ConsoleCommand\n"); 119 exit(1); 120 } 121 103 perror("pthread_create failed with console thread"); 104 throw; 105 } 122 106 if ((pthread_create(&thread_HVMonitor, NULL, (void * (*)(void *)) HVMonitor,(void *) &pio)) != 0) { 123 fprintf(stderr, "pthread_create failed with HVMonitor\n"); 124 exit(1); 125 } 126 107 perror("pthread_create failed with HVMonitor thread"); 108 throw; 109 } 127 110 if ((pthread_create(&thread_CCCommand, NULL, (void * (*)(void *)) CCCommand,(void *) &pio)) != 0) { 128 fprintf(stderr, "pthread_create failed with CCCommand\n");129 exit(1);111 perror("pthread_create failed with socket thread"); 112 throw; 130 113 } 131 114 132 115 // Threads should be accessible for sending signals 133 pio. status->HVMonitor = thread_HVMonitor;134 pio. status->SocketThread = thread_CCCommand;116 pio.HVMonitor = thread_HVMonitor; 117 pio.SocketThread = thread_CCCommand; 135 118 136 119 // Wait for threads to quit … … 138 121 pthread_join(thread_ConsoleCommand, NULL); 139 122 pthread_join(thread_HVMonitor, NULL); 123 124 // Destruct mutex and main instance 125 pthread_mutex_destroy (&pio.control_mutex); 126 pio.~ProcessIO(); 140 127 141 128 // Remove lockfile … … 146 133 } 147 134 148 return 0; 149 } 135 exit(EXIT_SUCCESS); 136 } 137 138 139 /********************************************************************\ 140 141 ConsoleCommand thread 142 143 Handle console input using readline library functions to allow 144 line editing and history capability 145 146 \********************************************************************/ 147 148 void ConsoleCommand(ProcessIO *m) { 149 150 time_t Time; 151 char Buf[MAX_COM_SIZE], *Command; 152 153 while (!m->Exit) { 154 155 // Assemble prompt 156 snprintf(m->Prompt, sizeof(m->Prompt),"\rHV"); 157 if (m->NumHVBoards == 0) sprintf(m->Prompt+strlen(m->Prompt),"> "); 158 else { 159 if (m->FirstChain == m->LastChain) sprintf(m->Prompt+strlen(m->Prompt),"|C%d",m->FirstChain); 160 else sprintf(m->Prompt+strlen(m->Prompt),"|C%d-%d",m->FirstChain,m->LastChain); 161 162 if (m->NumHVBoards == 0) sprintf(m->Prompt+strlen(m->Prompt),"> "); 163 else if (m->FirstBoard == m->LastBoard) sprintf(m->Prompt+strlen(m->Prompt),"|B%d> ",m->FirstBoard); 164 else snprintf(m->Prompt,sizeof(m->Prompt),"\rDAQ|B%d-%d> ",m->FirstBoard,m->LastBoard); 165 } 166 167 // Read Command 168 Command = readline(m->Prompt); 169 if (Command==NULL) { 170 m->PrintMessage("Error reading command line input\n"); 171 continue; 172 } 173 if(strlen(Command)>0) add_history(Command); 174 175 // Log command 176 strftime(Buf,MAX_COM_SIZE, "%d/%m/%y %X", localtime(&(Time=time(NULL)))); 177 m->PrintMessage(MsgToLog, "CONSOLE(%s)> %s\n", Buf, Command); 178 179 // Process command 180 pthread_mutex_lock(&m->control_mutex); 181 m->CommandControl(Command); 182 pthread_mutex_unlock(&m->control_mutex); 183 184 free(Command); 185 } 186 } 187 188 189 /********************************************************************\ 190 191 CCCommand thread 192 193 Listen to commands from socket (Central Control) 194 195 This thread will block execution in the accept() and read() socket function 196 while waiting for a connection or data. If the exit function is invoked through 197 keyboard command, these blocking functions are interrupted by raising the signal 198 SIGUSR1. Testing on errno=EINTR indicates this termination. The dummy signal 199 handler below is needed to prevent the standard thread termination occurring 200 when this signal is received. 201 202 \********************************************************************/ 203 204 205 void CCCommand(ProcessIO *m) { 206 207 int ServerSocket,ConnectionSocket,ReadResult; 208 struct sockaddr_in SocketAddress, ClientAddress; 209 struct hostent *ClientName; 210 socklen_t SizeClientAddress=sizeof(ClientAddress); 211 char Command[MAX_COM_SIZE], Buf[MAX_COM_SIZE]; 212 time_t Time; 213 214 // Set up server socket 215 if ((ServerSocket = socket(PF_INET, SOCK_STREAM, 0)) == -1) { 216 m->PrintMessage("Could not open server socket, no remote connection possible (%s).\n", strerror(errno)); 217 return; 218 } 219 220 // Allows immediate reuse of socket after closing (circumvents TIME_WAIT) 221 int Value=1; 222 if (setsockopt(ServerSocket, SOL_SOCKET, SO_REUSEADDR, (char *) &Value, sizeof (Value)) == -1) { 223 m->PrintMessage("Warning: Could not set server socket option SO_REUSEADDR (%s)\n", strerror(errno)); 224 } 225 226 SocketAddress.sin_family = PF_INET; 227 SocketAddress.sin_port = htons((unsigned short) m->config->fCCPort); 228 SocketAddress.sin_addr.s_addr = INADDR_ANY; 229 230 if (bind(ServerSocket, (struct sockaddr *) &SocketAddress, sizeof(SocketAddress)) == -1) { 231 m->PrintMessage("Could not bind port to socket (%s)\n", strerror(errno)); 232 close(ServerSocket); 233 return; 234 } 235 if (listen(ServerSocket, 0) == -1) { 236 m->PrintMessage("Could not set socket to listening (%s)\n", strerror(errno)); 237 close(ServerSocket); 238 return; 239 } 240 241 while (!m->Exit) { // Looping to wait for incoming connection 242 243 if ((ConnectionSocket = accept(ServerSocket, (struct sockaddr *) &ClientAddress, &SizeClientAddress)) == -1) { 244 if (errno!=EINTR) m->PrintMessage("Failed to accept incoming connection (%s)\n", strerror(errno)); 245 close(ServerSocket); 246 return; 247 } 248 249 ClientName = gethostbyaddr((char *) &ClientAddress.sin_addr ,sizeof(struct sockaddr_in),AF_INET); 250 m->PrintMessage("Connected to client at %s (%s).\n", inet_ntoa(ClientAddress.sin_addr), ClientName!=NULL ? ClientName->h_name:"name unknown"); 251 m->Socket = ConnectionSocket; 252 253 // Looping as long as client exists and program not terminated 254 while (!m->Exit) { 255 256 // Try to read command from socket 257 memset(Command, 0, sizeof(Command)); 258 ReadResult = read(ConnectionSocket, Command, MAX_COM_SIZE); 259 if (ReadResult==0) break; // Client does not exist anymore 260 if (ReadResult==-1) { 261 if (errno!=EINTR) m->PrintMessage("Error read from socket (%s)\n", strerror(errno)); 262 break; 263 } 264 if (Command[strlen(Command)-1]=='\n') Command[strlen(Command)-1]='\0'; // Remove trailing newline 265 266 // Log command 267 strftime(Buf, MAX_COM_SIZE, "%d/%m/%y %X", localtime(&(Time=time(NULL)))); 268 m->PrintMessage(MsgToConsole|MsgToLog, "SOCKET(%s)> %s\n", Buf, Command); 269 270 // Process command 271 pthread_mutex_lock(&m->control_mutex); 272 m->CmdFromSocket = true; 273 m->CommandControl(Command); 274 m->CmdFromSocket = false; 275 pthread_mutex_unlock(&m->control_mutex); 276 } 277 278 m->Socket = -1; 279 m->PrintMessage("Disconnected from client.\n"); 280 close(ConnectionSocket); 281 } 282 close(ServerSocket); 283 } 284 285 286 /********************************************************************\ 287 288 HVMonitor 289 290 Monitor HV board status 291 Sebastian Commichau, November 2008 292 293 \********************************************************************/ 294 295 void HVMonitor(ProcessIO *m) { 296 297 while (!m->Exit) { 298 if (m->state == active) { 299 pthread_mutex_lock(&m->control_mutex); 300 m->Monitor(); 301 pthread_mutex_unlock(&m->control_mutex); 302 } 303 usleep((unsigned long)floor(1000000./(m->NumHVBoards*m->fStatusRefreshRate))); 304 } 305 } 306 307 308 /********************************************************************\ 309 310 Signal handlers 311 312 \********************************************************************/ 150 313 151 314 // Remove lock file before running default signal code … … 156 319 raise(Signal); 157 320 } 321 322 // Dummy signal handler to return from blocking syscalls 323 void SignalHandler(int Signal) { 324 return; 325 } -
hvcontrol/src/HV.cc
r80 r90 8 8 9 9 Contents: Main class for HV supply 10 11 Requirements: Both libftdi and libusb are required for the12 communication - see manual for more details.13 14 libftdi: library for talking with FTDI USB <-> Serial15 converter, UM245R.16 http://www.intra2net.com/de/produkte/opensource/ftdi/17 18 libusb: library for talking to USB devices from19 user-space. Also needed by libftdi.20 http://libusb.wiki.sourceforge.net/21 10 22 11 \********************************************************************/ 23 12 24 25 13 #include "HV.h" 26 14 27 15 28 HV::HV(char** usbdevice, int* usbdevicenumber, FILE* f,bool TestMode): fNumberOfBoards(0) { 29 30 fTestMode = TestMode; 31 32 int i = 0, j = 0, ret = 0; 33 34 char manufacturer[STR_LENGTH], type[STR_LENGTH], serial[STR_LENGTH]; 35 36 bzero(manufacturer, sizeof(manufacturer)); 37 bzero(type, sizeof(type)); 38 bzero(serial, sizeof(serial)); 39 40 fprintf(stdout,"Scan: "); 41 42 // Search for FTDI devices 43 for (i = 0;i<MAX_NUM_HVBOARDS;i++) 44 ftdi_init(&ftdic[i]); 45 46 ftdi_init(&ftdic_dummy); 47 48 if ((i = ftdi_usb_find_all(&ftdic_dummy, &devlist, USB_VENDOR, USB_PRODUCT)) < 0) 49 fprintf(stderr,"error: ftdi_usb_find_all failed: %d (%s)\n", i, ftdi_get_error_string(&ftdic_dummy)); 50 51 fprintf(stdout,"found %d FTDI device(s)\n", i); 52 i = 0; 53 54 if(fTestMode){ 55 fprintf(stdout,"Test mode: One HVBoard initialized as dummy.\n"); 56 fHVBoard[fNumberOfBoards] = new HVBoard("dummy", 0, &ftdic[fNumberOfBoards],fTestMode); 57 fNumberOfBoards++; 58 return; 59 } 60 // Obtain information on FTDI devices 61 for (curdev = devlist; (curdev != NULL && i<MAX_NUM_HVBOARDS); i++) { 62 63 fprintf(stdout,"Device %d:\n", i); 64 65 if ((ret = ftdi_usb_get_strings(&ftdic_dummy, curdev->dev, manufacturer, STR_LENGTH, type, STR_LENGTH, serial, STR_LENGTH)) < 0) { 66 fprintf(stderr," Error: ftdi_usb_get_strings failed: %d (%s)\n", ret, ftdi_get_error_string(&ftdic_dummy)); 67 break; 68 } 69 70 fprintf(stdout," Manufacturer: %s - Type: %s - Serial: %s\n", manufacturer, type, serial); 71 72 // Fixme: the following code should be revised! 73 while (j<MAX_NUM_HVBOARDS) { 74 if (strcmp(serial,usbdevice[j])==0) 75 break; 76 j++; 77 } 78 79 if (j<MAX_NUM_HVBOARDS) { 80 ret = ftdi_usb_open_desc(&ftdic[fNumberOfBoards], USB_VENDOR, USB_PRODUCT, type, serial); 81 82 // Fixme: this function does not work properly if there is more than one device???!!! 83 // ret = ftdi_usb_open(&ftdic[fNumberOfBoards], USB_VENDOR, USB_PRODUCT); 84 85 if (ret < 0 && ret != -5) 86 fprintf(stderr," Error: unable to open FTDI device: %d (%s)\n", i, ftdi_get_error_string(&ftdic[fNumberOfBoards])); 87 else { 88 89 ftdi_set_baudrate(&ftdic[fNumberOfBoards], USB_BAUDRATE); 90 ftdi_usb_reset(&ftdic[fNumberOfBoards]); 91 ftdi_usb_purge_buffers(&ftdic[fNumberOfBoards]); 92 /* 93 The FTDI chip keeps data in the internal buffer for a specific 94 amount of time if the buffer is not full yet to decrease load on the usb bus. 95 */ 96 ftdi_set_latency_timer(&ftdic[fNumberOfBoards], USB_LATENCY_TIMER); 97 98 fHVBoard[fNumberOfBoards] = new HVBoard(serial, usbdevicenumber[j], &ftdic[fNumberOfBoards],fTestMode); 99 fNumberOfBoards++; 100 /* 101 fprintf(stdout," FTDI open succeeded\n"); 102 fprintf(stdout," Baudrate: %d\n", ftdic[i].baudrate); 103 fprintf(stdout," USB_read_timeout: %d\n", ftdic[i].usb_read_timeout); 104 fprintf(stdout," USB_write_timeout: %d\n", ftdic[i].usb_write_timeout); 105 */ 106 } 107 108 } 109 else 110 fprintf(stdout," Warning: found new USB device - check configuration file!\n"); 111 112 j=0; 113 114 curdev = curdev->next; 115 } 116 117 // Re-order board numbering otherwise it is determined by the connection sequence 118 ArrangeHVBoards(fHVBoard,fNumberOfBoards); 119 120 } 121 122 123 // Bubble-sort HV boards according to board number 124 void HV::ArrangeHVBoards(HVBoard** fHVBoard, int size) { 125 126 if(fTestMode){ 127 return; 128 } 129 130 HVBoard* tmp; 131 132 for (int i=size-1;i>0;--i) 133 for (int pos=0;pos<i;++pos) 134 if (fHVBoard[pos]->GetBoardNumber()>fHVBoard[pos+1]->GetBoardNumber()) { 135 tmp = fHVBoard[pos]; 136 fHVBoard[pos] = fHVBoard[pos+1]; 137 fHVBoard[pos+1] = tmp; 138 } 139 140 } 141 142 143 HV::~HV() { 144 145 if(fTestMode){ 146 fprintf(stdout,"Test mode: No FTDI device has to be closed.\n"); 147 return; 148 } 149 150 int i, ret = 0; 151 152 for (i=0;i<fNumberOfBoards;i++) { 153 fprintf(stdout,"Device %d: ",i); 154 155 ret = ftdi_usb_close(&ftdic[i]); 156 157 if (ret < 0) 158 fprintf(stderr, "Unable to close FTDI device: %d (%s)\n", i, ftdi_get_error_string(&ftdic[i])); 159 else 160 fprintf(stdout, "FTDI close succeeded\n"); 161 162 delete fHVBoard[i]; 163 } 164 165 fprintf(stdout,"FTDI list free\n"); 166 ftdi_list_free(&devlist); 167 168 for (i=0;i<MAX_NUM_HVBOARDS;i++) 169 ftdi_deinit(&ftdic[i]); 170 171 ftdi_deinit(&ftdic_dummy); 172 173 } 174 175 176 HVBoard::HVBoard(char* serial, int number, struct ftdi_context* ftdic,bool TestMode) : fTimeOut(.5) 177 { 16 // Constructor 17 HVBoard::HVBoard(int DeviceNumber, char *DeviceName, bool TestMode, float TimeOut, bool verbose) { 18 19 char Buffer[BUFFER_LENGTH]; 20 struct termios tio; 178 21 179 22 fTestMode = TestMode; 180 23 fTestModeWrap = 0; 181 FTDI_C = ftdic; 182 sprintf(Serial,"%s",serial); 183 BoardNumber = number; 184 185 } 186 187 24 25 SetTimeOut(TimeOut); 26 BoardNumber = DeviceNumber; 27 BoardName = DeviceName; 28 29 for (int i=0; i<NUM_CHAINS; i++) Overcurrent[i] = false; 30 ResetButton = false; 31 WrapOK = true; 32 LastWrapCount = -1; 33 34 if (fTestMode) { 35 fDescriptor = 99; 36 return; 37 } 38 39 ClearVoltageArrays(); 40 41 // Open device (do not warn on non-existing device) 42 snprintf(Buffer, BUFFER_LENGTH, "/dev/%s",DeviceName); 43 if ((fDescriptor = open(Buffer, O_RDWR|O_NOCTTY|O_NDELAY)) == -1) { 44 if(errno != 2) printf("Error: Could not open device %d/%s (%s)\n", DeviceNumber,DeviceName, strerror(errno)); 45 return; 46 } 47 48 // Get current serial port settings 49 if (tcgetattr(fDescriptor, &tio) == -1) { 50 printf("tcgetattr(...) failed (%d/%s)\n", errno, strerror(errno)); 51 return; 52 } 53 54 // Set baudrate and raw mode 55 if (cfsetspeed(&tio, BAUDRATE) == -1) printf("Error: Could not set baud rate (%s)\n", strerror(errno)); 56 cfmakeraw(&tio); 57 if (tcsetattr(fDescriptor, TCSANOW, &tio ) == -1) printf("Errsor with tcsetattr(...) (%s)\n", strerror(errno)); 58 59 // Synchronize HV board (if fails, closes device and sets fDescriptor to -2) 60 unsigned char wbuf = REG_STATUS; 61 int trial = 0, ret; 62 63 while(++trial<=3) { 64 if((ret = Communicate(stdout, &wbuf, 1, verbose)) == 1) { 65 Reset(stdout, verbose); 66 return; 67 } 68 if (ret==0) break; 69 wbuf = 0; 70 } 71 close(fDescriptor); 72 fDescriptor = -2; 73 return; 74 } 75 76 // Destructor (Resetting board) 188 77 HVBoard::~HVBoard() { 189 190 } 191 192 193 /* For test purposes only - never use this function with a real HV board!!! */ 194 void HVBoard::TestIO() { 195 196 int ret = 0, werrors = 0, rerrors = 0, mismatches = 0; 197 198 unsigned char wbuf[BUFFER_LENGTH], rbuf[BUFFER_LENGTH]; 199 200 for (int i=0;i<=0XFF;i++) { 201 202 wbuf[0] = (unsigned char)i; 203 204 #ifdef DO_CAST 205 ret = ftdi_write_data(FTDI_C,(char*)wbuf,1); 206 #endif 207 ret = ftdi_write_data(FTDI_C,wbuf,1); 208 209 if (ret < 0) 210 werrors++; 211 212 #ifdef DO_CAST 213 ret = ftdi_read_data(FTDI_C,(char*)rbuf,1); 214 #endif 215 ret = ftdi_write_data(FTDI_C,wbuf,1); 216 217 if (ret < 0) 218 rerrors++; 219 220 if (rbuf[0]!=wbuf[0]) { 221 mismatches++; 222 fprintf(stdout,"Mismatch - written: 0X%.2X read: 0X%.2X\n",wbuf[0],rbuf[0]); 223 } 224 } 225 fprintf(stdout, "Result: %d write errors, %d read errors, %d mismatches\n",werrors,rerrors,mismatches); 226 } 227 228 229 int HVBoard::Write(unsigned char* data, int size) { 230 if (fTestMode) 231 return 3; // implying that 3 bytes are written 232 233 #ifdef DO_CAST 234 return ftdi_write_data(FTDI_C, (char*)data, size); 235 #endif 236 return ftdi_write_data(FTDI_C, data, size); 237 } 238 239 240 int HVBoard::Read(unsigned char* data, int size) { 241 if (fTestMode) { 242 data[0] = fTestModeWrap; 243 // fprintf(stdout," Read Data 0X%.2X\n",data[0]); 244 fTestModeWrap++; 245 fTestModeWrap = fTestModeWrap%8; 246 return 1; // one byte read 247 } 248 #ifdef DO_CAST 249 return ftdi_read_data(FTDI_C, (char*)data, size); 250 #endif 251 return ftdi_read_data(FTDI_C, data, size); 252 } 253 254 255 /* 256 TRead: read from HV Board until fTimeOut has been reached 257 258 Returns: 259 0 if a read error has occured 260 1 on success 261 -1 if fTimeOut [s] has been exceeded 262 */ 263 int HVBoard::TRead(FILE* fptr, unsigned char* rbuf, bool verbose) { 264 265 if (fTestMode) { 266 Read(rbuf,BUFFER_LENGTH); 267 return 1; // rbuf read 268 } 269 270 char str[STR_LENGTH]; 271 272 long int t1, t2; 273 int ret = 0; 274 275 t1 = GetMicroSeconds(); 276 277 do { 278 279 if ((ret = Read(rbuf,BUFFER_LENGTH)) < 1) { 280 if (verbose) 281 if (ret < 0) { 282 fprintf(stderr, " Read error: %d (%s)\n", ret, ftdi_get_error_string(FTDI_C)); 283 return 0; 284 } 285 } 286 else { 287 288 if (verbose) 289 fprintf(fptr," %d byte(s) read:\n",ret); 290 291 for (int i=0;i<ret;i++) { 292 sPrintByteBin(rbuf[i],str); 293 if (verbose) 294 fprintf(fptr," Byte %d: %s| 0X%.2X\n",i,str,rbuf[i]); 295 } 296 return 1; 297 } 298 299 t2 = GetMicroSeconds(); 300 301 if ((t2-t1)/1000000. >= fTimeOut) { 302 fprintf(fptr," Warning: timeout exceeded\n"); 303 return -1; 304 } 305 306 } while(1); 307 78 if(fDescriptor >= 0 && !fTestMode) { 79 Reset(stdout, false); 80 close(fDescriptor); 81 } 82 } 83 84 85 // Communicate: Write and read from HV Board until fTimeOut has been reached 86 // 87 // Returns: 0 read error, 1 success, -1 fTimeOut exceeded 88 int HVBoard::Communicate(FILE* fptr, unsigned char* wbuf, int Bytes, bool verbose) { 89 90 unsigned char rbuf; 91 int ret; 92 fd_set SelectDescriptor; 93 94 // === Write data === 95 if (write(fDescriptor, wbuf, Bytes) < Bytes) { 96 fprintf(fptr," Error: could not write (all) data to HV board\n"); 97 return 0; 98 } 99 if (verbose) { 100 fprintf(fptr,"%d bytes written:\n", Bytes); 101 for (int i=0; i<Bytes; i++) fprintf(fptr," Byte %d: %#.2x\n",i,wbuf[i]); 102 } 103 104 // === Try to read until time-out === 105 FD_ZERO(&SelectDescriptor); FD_SET(fDescriptor, &SelectDescriptor); 106 struct timeval WaitTime = {(long) fTimeOut, (long) ((fTimeOut-(long) fTimeOut)*1e6)}; 107 if (select(fDescriptor+1, &SelectDescriptor, NULL, NULL, &WaitTime)==-1) { 108 printf("Error with select() (%d/%s)\n", errno,strerror(errno)); 109 return 0; 110 } 111 // Time-out expired? 112 if (!FD_ISSET(fDescriptor, &SelectDescriptor)) { 113 if (verbose) printf("Time-out of %.2f seconds expired while reading\n", fTimeOut); 114 return -1; 115 } 116 // Read error? 117 if ((ret = read(fDescriptor, &rbuf, 1)) == -1) { 118 fprintf(stderr, " Read error (%s)\n", strerror(errno)); 119 return 0; 120 } 121 122 // === Update status information === 123 if (LastWrapCount != -1) { 124 if ((LastWrapCount+1)%8 == (rbuf & 0X07)) WrapOK = true; 125 else WrapOK = false; 126 } 127 LastWrapCount = rbuf & 0X07; 128 for (int i=0; i<NUM_CHAINS; i++) Overcurrent[i]=(rbuf & (0X08 << i)); 129 ResetButton = (bool) (rbuf & 0X80); 130 131 if (verbose && ret==1) fprintf(fptr," 1 byte read: %#.2x\n", rbuf); 132 133 return 1; 308 134 } 309 135 310 136 311 137 /* Reset HV board - uses TRead() and has same return values */ 312 int HVBoard::Reset(FILE* fptr, unsigned char* rbuf, bool verbose) { 313 314 if (fTestMode) 315 return 1; 316 317 char str[STR_LENGTH]; 138 int HVBoard::Reset(FILE* fptr, bool verbose) { 139 140 if (fTestMode) return 1; 318 141 319 142 unsigned char wbuf[] = {REG_RESET,0,0}; 320 321 if (Write(wbuf,3) < 1) { 322 fprintf(fptr," Error: could not write to HV board\n"); 323 return 0; 324 } 325 326 if (verbose) 327 fprintf(fptr," 3 bytes written:\n"); 328 329 for (int i=0;i<3;i++) { 330 sPrintByteBin(wbuf[i],str); 331 if (verbose) 332 fprintf(fptr," Byte %d: %s| 0X%.2X\n",i,str,wbuf[i]); 333 } 334 335 return TRead(fptr,rbuf,verbose); 336 143 int ret; 144 145 if((ret = Communicate(fptr, wbuf, 3, verbose)) == 1) ClearVoltageArrays(); 146 return ret; 337 147 } 338 148 339 149 340 150 /* Read status register - uses TRead() and has same return values */ 341 int HVBoard::GetStatus(FILE* fptr, unsigned char* rbuf, bool verbose) { 342 if (fTestMode){ 343 // printf("Test mode. (Get Status) \n"); 344 return TRead(fptr,rbuf,verbose); 345 return 1; 346 } 347 348 char str[STR_LENGTH]; 151 int HVBoard::GetStatus(FILE* fptr, bool verbose) { 152 153 if (fTestMode) return 1; 349 154 350 155 unsigned char wbuf[] = {REG_STATUS,0,0}; 351 156 352 if (Write(wbuf,3) < 1) { 353 if (verbose) 354 fprintf(fptr," Error: could not write to HV board\n"); 355 return 0; 356 } 357 358 if (verbose) 359 fprintf(fptr," 3 bytes written:\n"); 360 361 for (int i=0;i<3;i++) { 362 sPrintByteBin(wbuf[i],str); 363 if (verbose) 364 fprintf(fptr," Byte %d: %s| 0X%.2X\n",i,str,wbuf[i]); 365 } 366 367 return TRead(fptr,rbuf,verbose); 368 157 return Communicate(fptr, wbuf, 3, verbose); 369 158 } 370 159 371 160 372 161 /* Set high voltage - uses TRead() and has same return values */ 373 int HVBoard::SetHV(FILE* fptr, int chain, unsigned int channel, unsigned int hv, unsigned char* rbuf,bool verbose) {162 int HVBoard::SetHV(FILE* fptr, int chain, unsigned int channel, unsigned int hv, bool verbose) { 374 163 375 164 if (fTestMode){ … … 377 166 return 1; 378 167 } 379 380 381 char str[STR_LENGTH]; 382 168 383 169 unsigned char wbuf[] = {0,0,0}; 384 170 385 if (!(hv>=0 .0 && hv<=0X3FFF)) {171 if (!(hv>=0 && hv<=0x3FFF)) { 386 172 fprintf(fptr," Error: HV beyond limits [0 - 0x3FFF]\n"); 387 173 return 0; 388 174 } 389 175 390 391 176 switch (chain) { 392 393 case 0: wbuf[0] = REG_HV0; break; 394 case 1: wbuf[0] = REG_HV1; break; 395 case 2: wbuf[0] = REG_HV2; break; 396 case 3: wbuf[0] = REG_HV3; break; 397 398 default : fprintf(fptr," Error: chain %d does not exist\n",chain); return 0; 399 177 case 0: wbuf[0] = REG_HV0; break; 178 case 1: wbuf[0] = REG_HV1; break; 179 case 2: wbuf[0] = REG_HV2; break; 180 case 3: wbuf[0] = REG_HV3; break; 181 182 default : fprintf(fptr," Error: chain %d does not exist\n",chain); return 0; 400 183 } 401 184 … … 406 189 wbuf[2] |= (unsigned char)(hv & 0X000000FF); // Add [D7-D0] 407 190 408 409 if (Write(wbuf,3) < 1) { 410 fprintf(fptr," Error: could not write to HV board\n"); 411 return 0; 412 } 413 414 if (verbose) 415 fprintf(fptr," 3 bytes written:\n"); 416 417 for (int i=0;i<3;i++) { 418 sPrintByteBin(wbuf[i],str); 419 if (verbose) 420 fprintf(fptr," Byte %d: %s| 0X%.2X\n",i,str,wbuf[i]); 421 } 422 423 return TRead(fptr,rbuf,verbose); 424 425 } 426 427 428 /* Set reference voltage - uses TRead() and has same return values */ 429 int HVBoard::SetVRef(FILE* fptr, int chain, unsigned int vref, unsigned char* rbuf, bool verbose) { 430 431 if (fTestMode){ 432 printf("Test mode. Nothing to be done.\n"); 433 return 1; 434 } 435 436 char str[STR_LENGTH]; 437 438 unsigned char wbuf[] = {0,0,0}; 439 440 if (!(vref>=0 && vref<=0X3FFF)) { 441 if (verbose) 442 fprintf(fptr," Error: vref beyond limits\n"); 443 return 0; 444 } 445 446 switch (chain) { 447 448 case 0: wbuf[0] = REG_VREF0; break; 449 case 1: wbuf[0] = REG_VREF1; break; 450 case 2: wbuf[0] = REG_VREF2; break; 451 case 3: wbuf[0] = REG_VREF3; break; 452 453 default : fprintf(fptr," Error: chain %d does not exist\n",chain); return 0; 454 455 } 456 457 // Assemble bytes 458 wbuf[0] |= (unsigned char)((vref >> 13) & 0X0000000F); // Add [D13] 459 wbuf[1] |= (unsigned char)((vref >> 5) & 0X000000FF); // Add [D12-D5] 460 wbuf[2] |= (unsigned char)((vref << 3) & 0X000000FF); // Add [D4-D0] 461 462 // PD bits (device clear) are not used 463 wbuf[0] &= ~REG_PD1; 464 wbuf[0] &= ~REG_PD2; 465 466 if (Write(wbuf,3) < 1) { 467 fprintf(fptr," Error: could not write to HV board\n"); 468 return 0; 469 } 470 471 if (verbose) 472 fprintf(fptr," 3 bytes written:\n"); 473 474 for (int i=0;i<3;i++) { 475 sPrintByteBin(wbuf[i],str); 476 if (verbose) 477 fprintf(fptr," Byte %d: %s| 0X%.2X\n",i,str,wbuf[i]); 478 } 479 480 return TRead(fptr,rbuf,verbose); 481 482 } 483 484 485 /* 486 Init: initialize (synchronize) HV board - to be used before any other access! 487 488 Returns 0 if an error has occured, 1 on success. 489 490 Before any other access the HV board communication has to be synchronized. 491 Each write access requires three bytes to be sent from the computer to the 492 HV board. The HV board sends back one byte containing status information. 493 494 The normal initialization procedure would be the following: 495 496 1. send one byte (0X80 = REG_STATUS). 497 1.1. try reading as long as fTimeOut is not exceeded. 498 499 2. send again one byte (0X00). 500 2.1. try reading as long as fTimeOut is not exceeded. 501 502 3. send again one byte (0X00). 503 3.1. try reading again as long as fTimeOut is not exceeded. 504 505 Note: from time to time there are problems when performing only 3 trials! Reason: 506 the first byte written by libftdi can get lost somewhere between 507 libusb <-> kernel <-> FTDI chip. I haven't found yet any solution to this. 508 To solve the issue, another byte is sent to assure a proper synchronization, 509 even though the first byte was lost: 510 511 4. send again one byte (0X00). 512 4.1. try reading again as long as fTimeOut is not exceeded; if fTimeOut 513 has been exceeded return. 514 515 See also: http://lists.omnipotent.net/pipermail/lcdproc/2008-June/012235.html 516 */ 517 int HVBoard::Init(bool verbose) { 518 519 520 unsigned char wbuf = REG_STATUS; 521 unsigned char rbuf[STR_LENGTH]; 522 523 int trial = 1; 524 int ret = 0; 525 526 long int t1, t2; 527 528 529 // First send 0X80 530 if (Write(&wbuf,1) < 1) { 531 if (verbose) 532 fprintf(stdout," Error: could not write to HV board\n"); 533 return 0; 534 } 535 else 536 if (verbose) 537 fprintf(stdout," 1 byte written: 0X%.2X\n",wbuf); 538 539 540 t1 = GetMicroSeconds(); 541 542 543 // Read - first trial 544 do { 545 546 t2 = GetMicroSeconds(); 547 548 if ((ret = Read(rbuf,BUFFER_LENGTH)) < 1) { 549 if (verbose) 550 if (ret < 0) { 551 fprintf(stderr, " Read error: %d (%s)\n",ret,ftdi_get_error_string(FTDI_C)); 552 return 0; 553 } 191 return Communicate(fptr, wbuf, 3, verbose); 192 } 193 194 195 // Set all voltages of board to zero 196 void HVBoard::ClearVoltageArrays() { 197 198 for (int j=0; j<NUM_CHAINS; j++) { 199 for (int k=0; k<NUM_CHANNELS; k++){ 200 HV[j][k] = 0; 201 HVV[j][k] = 0.0; 554 202 } 555 else { 556 if (verbose) 557 fprintf(stdout," %d byte(s) read:",ret); 558 for (int i=0;i<ret;i++) 559 if (verbose) 560 fprintf(stdout," 0X%.2X",rbuf[i]); 561 if (verbose) 562 fprintf(stdout,"\n"); 563 fprintf(stdout," Success: initialization done (%d trial)\n",trial); 564 return 1; 565 } 566 567 if ((t2-t1)/1000000. > fTimeOut) { 568 if (verbose) 569 fprintf(stdout," Warning: timeout exceeded\n"); 570 trial++; 571 572 // Second write 573 wbuf = 0; 574 if (Write(&wbuf,1) < 1) { 575 if (verbose) 576 fprintf(stdout," Error: could not write to HV board\n"); 577 return 0; 578 } 579 else 580 if (verbose) 581 fprintf(stdout," 1 byte written: 0X%.2X\n",wbuf); 582 583 t1 = GetMicroSeconds(); 584 585 // Read - second trial 586 do { 587 588 t2 = GetMicroSeconds(); 589 590 if ((ret = Read(rbuf,BUFFER_LENGTH)) < 1) { 591 if (verbose) 592 if (ret < 0) { 593 fprintf(stderr, " Read error: %d (%s)\n",ret,ftdi_get_error_string(FTDI_C)); 594 return 0; 595 } 596 } 597 else { 598 if (verbose) 599 fprintf(stdout," %d byte(s) read:",ret); 600 for (int i=0;i<ret;i++) 601 if (verbose) 602 fprintf(stdout," 0X%.2X",rbuf[i]); 603 if (verbose) 604 fprintf(stdout,"\n"); 605 fprintf(stdout," Success: initialization done (%d trials)\n",trial); 606 return 1; 607 } 608 609 if ((t2-t1)/1000000. > fTimeOut) { 610 if (verbose) 611 fprintf(stdout," Warning: timeout exceeded\n"); 612 trial++; 613 614 // Third write 615 wbuf = 0; 616 if (Write(&wbuf,1) < 1) { 617 if (verbose) 618 fprintf(stdout," Error: could not write to HV board\n"); 619 return 0; 620 } 621 else 622 if (verbose) 623 fprintf(stdout," 1 byte written: 0X%.2X\n",wbuf); 624 625 626 // Read - third trial 627 do { 628 629 t2 = GetMicroSeconds(); 630 631 if ((ret = Read(rbuf,BUFFER_LENGTH)) < 1) { 632 if (verbose) 633 if (ret < 0) { 634 fprintf(stderr, " Read error: %d (%s)\n",ret,ftdi_get_error_string(FTDI_C)); 635 return 0; 636 } 637 } 638 else { 639 if (verbose) 640 fprintf(stdout," %d byte(s) read:",ret); 641 for (int i=0;i<ret;i++) 642 if (verbose) 643 fprintf(stdout," 0X%.2X",rbuf[i]); 644 if (verbose) 645 fprintf(stdout,"\n"); 646 fprintf(stdout," Success: initialization done (%d trials)\n",trial); 647 return 1; 648 } 649 650 651 if ((t2-t1)/1000000. > fTimeOut) { 652 if (verbose) 653 fprintf(stdout," Warning: timeout exceeded\n"); 654 trial++; 655 656 // Fourth write 657 wbuf = 0; 658 if (Write(&wbuf,1) < 1) { 659 if (verbose) 660 fprintf(stdout," Error: could not write to HV board\n"); 661 return 0; 662 } 663 else 664 if (verbose) 665 fprintf(stdout," 1 byte written: 0X%.2X\n",wbuf); 666 667 668 // Read - fourth and last trial 669 do { 670 671 t2 = GetMicroSeconds(); 672 673 if ((ret = Read(rbuf,BUFFER_LENGTH)) < 1) { 674 if (verbose) 675 if (ret < 0) { 676 fprintf(stderr, " Read error: %d (%s)\n",ret,ftdi_get_error_string(FTDI_C)); 677 return 0; 678 } 679 } 680 else { 681 if (verbose) 682 fprintf(stdout," %d byte(s) read:",ret); 683 for (int i=0;i<ret;i++) 684 if (verbose) 685 fprintf(stdout," 0X%.2X",rbuf[i]); 686 if (verbose) 687 fprintf(stdout,"\n"); 688 fprintf(stdout," Success: initialization done (%d trials)\n",trial); 689 return 1; 690 } 691 692 if ((t2-t1)/1000000. > fTimeOut) { 693 if (verbose) 694 fprintf(stdout," Error: timeout exceeded - initialization failed (%d trials)\n",trial); 695 return 0; 696 697 } 698 699 } while (1); 700 701 } 702 703 } while (1); 704 705 } 706 707 } while (1); 708 709 } 710 711 } while (1); 712 713 714 return 0; 715 } 716 717 718 /* Decode wrap counter */ 719 int HVBoard::DecodeWrap(unsigned char* rbuf) { 720 721 return (*rbuf & 0X07); 722 723 } 724 725 726 /* Decode over current bits */ 727 void HVBoard::DecodeOC(bool OC[], unsigned char* rbuf) { 728 729 for (int i=0;i<MAX_NUM_CHAINS;i++) 730 OC[i]=(*rbuf & (0X08 << i)); 731 } 732 733 734 /* Decode bit indicating manual reset */ 735 bool HVBoard::DecodeReset(unsigned char* rbuf) { 736 737 return (bool)(*rbuf & 0X80); 738 739 } 740 741 203 } 204 } 205 206 207 // Set time-out to wait for read 208 void HVBoard::SetTimeOut(double t) { 209 210 if (t >= MIN_TIMEOUT && t <= MAX_TIMEOUT) fTimeOut = t; 211 else fTimeOut = 1.0; 212 } -
hvcontrol/src/HV.h
r80 r90 2 2 #define HV_H_SEEN 3 3 4 #include "Types.h" 5 #include "Utilities.h" 6 7 #include <ftdi.h> 4 #include <termios.h> // POSIX terminal control definitions 5 #include <fcntl.h> // File control definitions => fcntl() in fcn OpenPort() 6 #include <errno.h> 7 #include <stdio.h> 8 #include <unistd.h> 8 9 #include <sys/ioctl.h> 9 10 11 #include <HVConfig.h> 10 12 11 #ifndef NULL 12 #ifdef __cplusplus 13 #define NULL 0 14 #else 15 #define NULL ((void *)0) 16 #endif 17 #endif 18 19 20 // Have a look at http://www.linux-usb.org/usb.ids 21 // Vendor: Future Technology Devices International, Ltd (FTDI) 22 #define USB_VENDOR 0X0403 23 // Product: FT232 USB-Serial (UART) IC (USB <-> Serial converter, UM245R) 24 #define USB_PRODUCT 0X6001 25 26 27 #define USB_BAUDRATE 115000 28 #define USB_LATENCY_TIMER 1 29 13 #define BAUDRATE B115200 30 14 31 15 // HV board control registers 32 #define REG_VREF0 0X0033 #define REG_VREF1 0X0834 #define REG_VREF2 0X1035 #define REG_VREF3 0X1836 37 16 #define REG_HV0 0X20 38 17 #define REG_HV1 0X28 … … 42 21 #define REG_RESET 0XF8 43 22 #define REG_STATUS 0X80 44 45 #define REG_PD1 0X0446 #define REG_PD2 0X0247 48 23 49 24 // HV board status bits … … 58 33 class HVBoard { 59 34 60 public: 61 62 HVBoard(char* serial, int number, struct ftdi_context* ftdic, bool TestMode); 63 ~HVBoard(); 64 65 bool fTestMode; 66 67 int Init(bool verbose); 68 int Reset(FILE* fptr, unsigned char* rbuf, bool verbose); 69 int GetStatus(FILE* fptr, unsigned char* rbuf, bool verbose); 70 int SetVRef(FILE* fptr, int chain, unsigned int vref, unsigned char* rbuf, bool verbose); 71 int SetHV(FILE* fptr, int chain, unsigned int channel, unsigned int hv, unsigned char* rbuf, bool verbose); 72 struct ftdi_context* GetFTDI_C() {return FTDI_C;} 73 char* GetSerial() {return Serial;} 74 int GetBoardNumber() {return BoardNumber;} 75 int Write(unsigned char* data, int size); 76 int Read(unsigned char* data, int size); 77 int TRead(FILE* fptr, unsigned char* rbuf, bool verbose); 78 void SetTimeOut(float t) {fTimeOut = t;} 79 float GetTimeOut() {return fTimeOut;} 80 void TestIO(); // Warning: NEVER use this function with a real HV board!!! 81 int DecodeWrap(unsigned char* rbuf); 82 void DecodeOC(bool OC[], unsigned char* rbuf); 83 bool DecodeReset(unsigned char* rbuf); 84 85 struct ftdi_context* FTDI_C; 86 char Serial[STR_LENGTH]; 87 int BoardNumber; 88 float fTimeOut; // [s] timeout to return from read 89 int fTestModeWrap; 90 91 }; 92 93 94 95 class HV { 35 int BoardNumber; 36 int fTestModeWrap; 37 bool fTestMode; 96 38 97 39 public: 98 40 99 HV(char** usbdevice, int* usbdevicenumber, FILE* f,bool TestMode);100 ~HV();41 HVBoard(int, char *, bool, float, bool); 42 ~HVBoard(); 101 43 102 int fNumberOfBoards; 103 int fMaxNumberOfBoards; 44 int fDescriptor; 45 bool Overcurrent[NUM_CHAINS]; 46 bool ResetButton; 47 bool WrapOK; 48 int LastWrapCount; 49 double fTimeOut; // [s] timeout to return from read 50 51 char *BoardName; 52 int HV[NUM_CHAINS][NUM_CHANNELS]; // HV value in DAC units 53 double HVV[NUM_CHAINS][NUM_CHANNELS]; // HV value in volts 104 54 105 bool fTestMode; 106 107 HVBoard* fHVBoard[MAX_NUM_HVBOARDS]; 108 int GetNumberOfBoards() {return fNumberOfBoards;} 109 void SetNumberOfBoards(int i) {fNumberOfBoards = i;} 110 HVBoard* GetHVBoard(int i) {return fHVBoard[i];} 111 112 protected: 113 114 // For FTDI USB <-> serial converter 115 struct ftdi_context ftdic[MAX_NUM_HVBOARDS]; 116 struct ftdi_context ftdic_dummy; 117 struct ftdi_device_list *devlist, *curdev; 118 119 void ArrangeHVBoards(HVBoard** fHVBoard, int size); 120 55 void ClearVoltageArrays(); 56 int Reset(FILE*, bool); 57 int GetStatus(FILE*, bool); 58 int SetHV(FILE*, int, unsigned int, unsigned int, bool); 59 int GetBoardNumber() {return BoardNumber;} 60 int Communicate(FILE*, unsigned char*, int, bool); 61 void SetTimeOut(double); 121 62 }; 122 63 -
hvcontrol/src/HVCalib.cc
r46 r90 12 12 13 13 14 #include "HVCalib.h"15 14 #include <stdio.h> 16 15 #include <iostream> 17 16 #include <fstream> 18 17 #include <math.h> 18 19 #include "HVCalib.h" 20 19 21 using namespace std; 20 21 22 23 22 24 23 … … 39 38 40 39 41 HVArray = new float***[hvConfig->NumHVBoards];40 HVArray = new double***[hvConfig->NumHVBoards]; 42 41 for(int i=0; i<hvConfig->NumHVBoards; i++) { 43 HVArray[i] = new float**[NCHAIN];44 for(int j=0; j<N CHAIN; j++) {45 HVArray[i][j] = new float*[NCHANNEL];46 for(int k=0; k<N CHANNEL; k++) {47 HVArray[i][j][k] = new float[NDACValues];42 HVArray[i] = new double**[NUM_CHAINS]; 43 for(int j=0; j<NUM_CHAINS; j++) { 44 HVArray[i][j] = new double*[NUM_CHANNELS]; 45 for(int k=0; k<NUM_CHANNELS; k++) { 46 HVArray[i][j][k] = new double[NDACValues]; 48 47 } 49 48 } … … 52 51 DACArray = new int***[hvConfig->NumHVBoards]; 53 52 for(int i=0; i<hvConfig->NumHVBoards; i++) { 54 DACArray[i] = new int**[N CHAIN];55 for(int j=0; j<N CHAIN; j++) {56 DACArray[i][j] = new int*[N CHANNEL];57 for(int k=0; k<N CHANNEL; k++) {53 DACArray[i] = new int**[NUM_CHAINS]; 54 for(int j=0; j<NUM_CHAINS; j++) { 55 DACArray[i][j] = new int*[NUM_CHANNELS]; 56 for(int k=0; k<NUM_CHANNELS; k++) { 58 57 DACArray[i][j][k] = new int[NHVValues]; 59 58 } … … 61 60 } 62 61 63 64 65 62 for(int i=0; i<hvConfig->NumHVBoards; i++){ 66 // for(int i=0; i<1; i++){ 67 for(int j=0;j<NCHAIN;j++){ 68 //for(int j=0;j<1;j++){ 63 for(int j=0; j<NUM_CHAINS; j++){ 69 64 sprintf(calibfile,"Calib/%s_%c%d.txt",hvConfig->fUSBDevice[i],65+j,1); 70 // printf("Calibration tabel 0: %s\n", calibfile);71 65 ifstream fin(calibfile); 72 66 … … 74 68 fin >> dac; 75 69 idacOld = 0; 76 if ((int) dac >= hvConfig->DACMin) {70 if ((int) dac >= hvConfig->DACMin) { 77 71 if (first){ 78 iDACMin = (int) dac;72 iDACMin = (int) dac; 79 73 first = false; 80 74 } 81 75 idac = (int)dac - iDACMin; 82 76 istep = idac - idacOld; 83 for(int k=0; k<NCHANNEL;k++){77 for(int k=0; k<NUM_CHANNELS; k++){ 84 78 fin>>HVArray[i][j][k][idac]; 85 79 for (int l=1; l<istep;l++){ … … 100 94 101 95 for(int i=0; i<hvConfig->NumHVBoards; i++){ 102 // for(int i=0; i<1; i++){ 103 for(int j=0;j<NCHAIN;j++){ 104 // for(int j=0;j<1;j++){ 105 for(int k=0;k<NCHANNEL;k++){ 106 //for(int k=0;k<1;k++){ 96 for(int j=0;j<NUM_CHAINS;j++){ 97 for(int k=0;k<NUM_CHANNELS;k++){ 107 98 ihvOld = 0; 108 99 first = true; … … 117 108 ihv1000 = (int)((hv1000>=0)?ceil(hv1000):floor(hv1000)); 118 109 } 119 else { 120 ihv1000 = (int)((hv1000<0)?ceil(hv1000):floor(hv1000)); 121 } 122 if (ihv1000 <= ihvOld){ 123 continue; 124 } 110 else ihv1000 = (int)((hv1000<0)?ceil(hv1000):floor(hv1000)); 111 112 if (ihv1000 <= ihvOld) continue; 125 113 else if (ihv1000 > ihvOld){ 126 for (int m=0; m<(ihv1000-ihvOld); m++){114 for (int m=0; m<(ihv1000-ihvOld); m++){ 127 115 DACArray[i][j][k][ihvOld+m] = l+iDACMin; 128 116 //printf("HV = %d, HVArr = %f, DACArray = %d, m = %d. \n",ihvOld+m,HVArray[i][j][k][l],DACArray[i][j][k][ihvOld+m],m); … … 143 131 144 132 for (int i=0; i<MAX_NUM_HVBOARDS; i++){ 145 for (int j=0; j<N CHAIN;j++){146 for (int k=0; k<N CHANNEL;k++){133 for (int j=0; j<NUM_CHAINS;j++){ 134 for (int k=0; k<NUM_CHANNELS;k++){ 147 135 delete [] HVArray[i][j][k]; 148 136 delete [] HVArray; … … 152 140 153 141 for (int i=0; i<MAX_NUM_HVBOARDS; i++){ 154 for (int j=0; j<N CHAIN;j++){155 for (int k=0; k<N CHANNEL;k++){142 for (int j=0; j<NUM_CHAINS;j++){ 143 for (int k=0; k<NUM_CHANNELS;k++){ 156 144 delete [] DACArray[i][j][k]; 157 145 delete [] DACArray; … … 163 151 ///////////////////////////////////////////////////////////////////////// 164 152 165 floatHVCalib::DACToHV(int dac, int board, int chain, int channel) {153 double HVCalib::DACToHV(int dac, int board, int chain, int channel) { 166 154 if (dac < iDACMin){ 167 155 return HVArray[board][chain][channel][0] + (dac - iDACMin)*fHVCalibSlope; … … 173 161 ///////////////////////////////////////////////////////////////////////// 174 162 175 int HVCalib::HVToDAC( floathv, int board, int chain, int channel) {163 int HVCalib::HVToDAC(double hv, int board, int chain, int channel) { 176 164 if (hv < HVArray[board][chain][channel][0]){ 177 165 return iDACMin + (int)((hv - HVArray[board][chain][channel][0])/fHVCalibSlope); … … 180 168 int ihv = 0; 181 169 double intpart; 182 floathv1000 = (hv-HVArray[board][chain][channel][0])*1000.;170 double hv1000 = (hv-HVArray[board][chain][channel][0])*1000.; 183 171 if (modf(hv1000,&intpart) >= 0.5){ 184 ihv = (int) ((hv1000>=0)?ceil(hv1000):floor(hv1000));172 ihv = (int) (hv1000>=0 ? ceil(hv1000) : floor(hv1000)); 185 173 } 186 174 else { 187 ihv = (int) ((hv1000<0)?ceil(hv1000):floor(hv1000));175 ihv = (int) (hv1000<0 ? ceil(hv1000) : floor(hv1000)); 188 176 } 189 177 return DACArray[board][chain][channel][ihv]; -
hvcontrol/src/HVCalib.h
r40 r90 1 2 1 #ifndef HVCALIB_H_SEEN 3 2 #define HVCALIB_H_SEEN 4 3 4 #include <string.h> 5 5 6 #include <string.h> 7 #include <HVConfig.h> 8 #include "Types.h" 9 10 #define NCHAIN 4 11 #define NCHANNEL 32 6 #include "HVConfig.h" 12 7 13 8 14 9 class HVCalib { 15 10 16 // privat: 17 float ****HVArray; 11 private: 12 13 double ****HVArray; 18 14 int ****DACArray; 19 20 15 21 16 int NDACValues; … … 24 19 public: 25 20 26 27 21 HVCalib(HVConfig *hvConfig); 28 22 ~HVCalib(); 29 23 30 24 int iDACMin; 31 floatfHVCalibSlope;25 double fHVCalibSlope; 32 26 33 int HVToDAC(float hv, int board, int chain, int channel); 34 float DACToHV(int dac, int board, int chain, int channel); 35 36 27 int HVToDAC(double hv, int board, int chain, int channel); 28 double DACToHV(int dac, int board, int chain, int channel); 37 29 }; 38 30 -
hvcontrol/src/HVConfig.cc
r80 r90 11 11 \********************************************************************/ 12 12 13 14 #include "ReadCard.h"15 13 #include "HVConfig.h" 16 14 … … 18 16 HVConfig::HVConfig(FILE* fptr, char *configfile) { 19 17 20 fLog Path = new char[FILENAME_MAX_SIZE];18 fLogFile = new char[BUFFER_LENGTH]; 21 19 fUSBDevice = new char*[MAX_NUM_HVBOARDS]; 22 fCCClient = new char[FILENAME_MAX_SIZE];23 20 24 fPixMapTable = new char[ FILENAME_MAX_SIZE];21 fPixMapTable = new char[BUFFER_LENGTH]; 25 22 26 23 for (int i=0; i<MAX_NUM_HVBOARDS; i++) { 27 fUSBDevice[i] = new char[ FILENAME_MAX_SIZE];24 fUSBDevice[i] = new char[BUFFER_LENGTH]; 28 25 USBDeviceNumber[i] = 0; 29 26 30 for (int j=0; j< MAX_NUM_CHAINS; j++)31 for (int k=0; k<2; k++) 32 Coef[i][j][k] = 0.; 27 for (int j=0; j<NUM_CHAINS; j++) { 28 for (int k=0; k<2; k++) Coef[i][j][k] = 0.; 29 } 33 30 } 34 31 … … 38 35 fStatusRefreshRate = 1.; 39 36 fTimeOut = 1.; 40 IsDAC = true;41 37 DACMin = 11008; 42 38 DACMax = 12496; 43 HVMin = 67.0;44 HVMax = 76.0;45 39 fHVCalibOffset = -.8; 46 40 fHVCalibSlope = 0.0064; 47 fHVMaxDiff = 1 .0;41 fHVMaxDiff = 1; 48 42 49 43 if (configfile != NULL) { … … 58 52 HVConfig::~HVConfig() { 59 53 60 delete [] fLogPath; 61 delete [] fPixMapTable; 62 63 for (int i=0; i<MAX_NUM_HVBOARDS; i++) 64 delete [] fUSBDevice[i]; 54 delete [] fLogFile; delete [] fPixMapTable; 55 for (int i=0; i<MAX_NUM_HVBOARDS; i++) delete [] fUSBDevice[i]; 65 56 delete [] fUSBDevice; 66 67 57 } 68 58 … … 78 68 return 0; 79 69 } 80 else { 81 fprintf(fptr,"Opening configuration file: %s\n", configfile); 82 } 70 else fprintf(fptr,"Opening configuration file: %s\n", configfile); 83 71 84 ReadCard("LogPath", fLogPath, 's',f); 72 ReadCard("LogFile", fLogFile, 's',f); 73 ReadCard("PixMapTable",fPixMapTable,'s',f); 74 ReadCard("TestMode", &str, 's',f); 75 if (!strcmp(str,"TRUE")) TestMode = true; 85 76 86 ReadCard("PixMapTable",fPixMapTable,'s',f); 87 88 ReadCard("TestMode", &str, 's',f); 89 if (!strcmp(str,"TRUE")) 90 TestMode = true; 91 92 93 for (int i=0;i<MAX_NUM_HVBOARDS;i++) { 77 for (int i=0; i<MAX_NUM_HVBOARDS; i++) { 94 78 sprintf(str,"Board%d",i); 95 79 96 if (ReadCard(str, dev, 's', f) ==0) {80 if (ReadCard(str, dev, 's', f)) { 97 81 USBDeviceNumber[j] = i; 98 82 sprintf(fUSBDevice[j++],"%s",dev); … … 104 88 ReadCard("StatusRefreshRate", &fStatusRefreshRate, 'f', f); 105 89 ReadCard("CCPort", &fCCPort, 'I', f); 106 ReadCard("CCClient", fCCClient, 's', f);107 ReadCard("IsDAC", &str, 's', f);108 90 ReadCard("DACMin", &DACMin, 'I', f); 109 91 ReadCard("DACMax", &DACMax, 'I', f); 110 ReadCard("HVMin", &HVMin, 'f', f);111 ReadCard("HVMax", &HVMax, 'f', f);112 92 ReadCard("HVCalibOffset", &fHVCalibOffset, 'f', f); 113 93 ReadCard("HVCalibSlope", &fHVCalibSlope, 'f', f); 114 ReadCard("HVMaxDiff", &fHVMaxDiff, ' f', f);94 ReadCard("HVMaxDiff", &fHVMaxDiff, 'U', f); 115 95 116 if (strcmp(str,"TRUE"))117 IsDAC = false;118 119 96 fclose(f); 120 97 return 1; … … 124 101 int HVConfig::PrintHVConfig(FILE *fptr) { 125 102 126 fprintf(fptr,"\n"); 127 fprintf(fptr,"********************************************* CONFIG ********************************************\n\n"); 128 129 fprintf(fptr," HV control configuration (%s):\n\n", FileName); 130 fprintf(fptr," Log path: %s\n\n", fLogPath); 131 fprintf(fptr," Pixel map table: %s\n\n", fPixMapTable); 132 fprintf(fptr," Test mode: %s\n\n", TestMode ? "yes" : "no"); 133 fprintf(fptr," %.2d USB devices:\n\n", NumHVBoards); 103 fprintf(fptr," \n HV control configuration (%s):\n\n", FileName); 104 fprintf(fptr," Log file: %s\n", fLogFile); 105 fprintf(fptr," Pixel map table: %s\n", fPixMapTable); 106 fprintf(fptr," Test mode: %s\n", TestMode ? "yes" : "no"); 107 fprintf(fptr," %d USB devices:\n", NumHVBoards); 134 108 135 109 for (int i=0;i<NumHVBoards;i++) … … 138 112 fprintf(fptr,"\n"); 139 113 fprintf(fptr," TimeOut: %.2f s\n", fTimeOut); 140 fprintf(fptr," StatusRefreshRate: %.2f Hz\n \n",fStatusRefreshRate);114 fprintf(fptr," StatusRefreshRate: %.2f Hz\n",fStatusRefreshRate); 141 115 fprintf(fptr," CCPort: %d\n", fCCPort); 142 fprintf(fptr," CCClient: %s\n\n", fCCClient); 143 fprintf(fptr," Set DAC values: %s\n\n", IsDAC ? "yes" : "no"); 144 fprintf(fptr," DACMin value: %d\n\n", DACMin); 145 fprintf(fptr," DACMax value: %d\n\n", DACMax); 146 fprintf(fptr," HVMin value: %f\n\n", HVMin); 147 fprintf(fptr," HVMax value: %f\n\n", HVMax); 148 fprintf(fptr," HVCalibOffset : %f\n\n", fHVCalibOffset); 149 fprintf(fptr," HVCalibSlope : %f\n\n", fHVCalibSlope); 150 fprintf(fptr," HVMaxDiff : %f\n\n", fHVMaxDiff); 116 fprintf(fptr," DACMin value: %d\n", DACMin); 117 fprintf(fptr," DACMax value: %d\n", DACMax); 118 fprintf(fptr," HVCalibOffset : %f\n", fHVCalibOffset); 119 fprintf(fptr," HVCalibSlope : %f\n", fHVCalibSlope); 120 fprintf(fptr," HVMaxDiff : %u\n", fHVMaxDiff); 151 121 152 fprintf(fptr,"*************************************************************************************************\n\n");153 154 122 return 1; 155 123 } 156 124 125 // ReadCard function (original version by F. Goebel) 126 // Data is read into an array if MaxNum is larger than 1 127 bool ReadCard(const char *card_flag, void *store, char Type, FILE *File, unsigned int MaxNum) { 128 129 char *card_name, *card_val, Buffer[MAX_COM_SIZE]; 130 unsigned int Count=0; 131 132 rewind(File); 157 133 158 int HVConfig::WriteHVConfig(FILE* fptr, char *configfile) { 134 while (fgets(Buffer, sizeof(Buffer), File) != NULL) { // Read line by line 135 card_name = strtok(Buffer," \t\n"); 136 137 // Ignore empty lines, comments, and skip if card name does not match 138 if (card_name==NULL || card_name[0]=='#' || strcmp(card_name, card_flag)!=0) continue; 159 139 160 FILE *f; 161 162 time_t time_now_secs; 163 struct tm *time_now; 164 165 time(&time_now_secs); 166 time_now = localtime(&time_now_secs); 167 168 if ((f = fopen(configfile,"w")) == NULL) { 169 fprintf(fptr,"Could not open file: %s\n", configfile); 170 return 0; 140 // Read numbers of given type (if MaxNum>1 read array) 141 while ((card_val=strtok(NULL," \t\n")) != NULL && Count++<MaxNum) { 142 switch (Type) { 143 case 'I': *(((int *&) store)++) = (int) strtol(card_val, NULL, 10); 144 break; 145 case 'i': *(((short *&) store)++) = (short) strtol(card_val, NULL, 10); 146 break; 147 case 'U': *(((unsigned int *&) store)++) = (unsigned int) strtoul(card_val, NULL, 10); 148 break; 149 case 'u': *(((unsigned short *&) store)++) = (unsigned short) strtoul(card_val, NULL, 10); 150 break; 151 case 'f': *(((float *&) store)++) = atof(card_val); 152 break; 153 case 'd': *(((double *&) store)++) = atof(card_val); 154 break; 155 case 's': sprintf((char *) store, "%s", card_val); 156 break; 157 case 'c': *((char *) store) = card_val[0]; 158 break; 159 default: fprintf(stderr,"Warning: Unknown type '%c' for reading of configuration file\n", Type); 160 return false; 161 } 162 } 163 return true; // Finished reading data for card name 171 164 } 172 173 fprintf(f,"# Main configuration file for the HV control program %s, %04d %02d %02d, %02d:%02d:%02d\n", 174 HV_CONTROL_VERSION, 175 1900 + time_now->tm_year, 176 1 + time_now->tm_mon, 177 time_now->tm_mday, 178 time_now->tm_hour, 179 time_now->tm_min, 180 time_now->tm_sec); 181 182 fprintf(f,"# Note: this file will be updated at program exit\n\n"); 183 184 fprintf(f,"LogPath %s\n\n", fLogPath); 185 fprintf(f,"PixMapTable %s\n\n", fPixMapTable); 186 187 fprintf(f,"TestMode %s #Test Mode: if no HV boards are connected, the test mode can be used.",((TestMode) ? "TRUE" : "FALSE")); 188 189 fprintf(f,"TimeOut %.2f s # Timeout to return from read (%.2f,...%.2f) s\n\n",fTimeOut,MIN_TIMEOUT,MAX_TIMEOUT); 190 191 fprintf(f,"StatusRefreshRate %.2f Hz # Status update rate (%.2f,...%.2f) Hz\n\n",fStatusRefreshRate,MIN_RATE,MAX_RATE); 192 193 fprintf(f,"CCPort %d # Port used to look for commands from the Central Control\n",fCCPort); 194 fprintf(f,"CCClient %s # Central Control client name\n\n",fCCClient); 195 fprintf(f,"IsDAC %s # Define here if user input is interpreted as DAC value or voltage\n\n",((IsDAC) ? "TRUE" : "FALSE")); 196 fprintf(f,"DACMin %d # Starting point for calibration of DAC to voltage values\n",DACMin); 197 fprintf(f,"DACMax %d # End point for calibration of DAC to voltage values\n",DACMax); 198 fprintf(f,"HVMin %f # Starting point for calibration of voltage to DAC values\n",HVMin); 199 fprintf(f,"HVMax %f # End point for calibration of voltage to DAC values\n",HVMax); 200 fprintf(f,"HVCalibOffset %f # Calibration of DAC to voltage values\n",fHVCalibOffset); 201 fprintf(f,"HVCalibSlope %f # Calibration of DAC to voltage values\n\n",fHVCalibSlope); 202 fprintf(f,"HVMaxDiff %f # Speed for HV changes limited to 1V/ms\n",fHVMaxDiff); 203 204 fprintf(f,"# List of HV boards (at most %d HV boards will be recognized):\n",MAX_NUM_HVBOARDS); 205 206 for (int i=0;i<NumHVBoards;i++) 207 fprintf(f,"Board%d %s\n",USBDeviceNumber[i],fUSBDevice[i]); 208 209 fprintf(fptr,"Configuration file successfully updated\n"); 210 211 fclose(f); 212 return 1; 213 165 return false; 214 166 } 215 167 216 -
hvcontrol/src/HVConfig.h
r80 r90 4 4 5 5 #include <time.h> 6 #include <string.h> 7 #include <stdlib.h> 8 #include <stdio.h> 6 9 7 #include <string.h> 10 #define MAX_COM_SIZE 1000 11 #define MAX_NUM_HVBOARDS 20 12 #define NUM_CHAINS 4 13 #define NUM_CHANNELS 32 14 #define BUFFER_LENGTH 256 8 15 9 #include "Types.h" 16 #define MIN_TIMEOUT 0.01 17 #define MAX_TIMEOUT 5.0 18 19 #define MIN_RATE 0.01 20 #define MAX_RATE 50.0 21 10 22 11 23 class HVConfig { … … 18 30 int ReadHVConfig(FILE* fptr, char *configfile); 19 31 int PrintHVConfig(FILE* fptr); 20 int WriteHVConfig(FILE* fptr, char *configfile);21 32 22 33 int NumHVBoards; … … 24 35 25 36 int fCCPort; 26 char *fCCClient;27 37 28 38 bool TestMode; 29 39 30 bool IsDAC; 31 float Coef[MAX_NUM_HVBOARDS][MAX_NUM_CHAINS][2]; 40 float Coef[MAX_NUM_HVBOARDS][NUM_CHAINS][2]; 32 41 33 42 char* FileName; 34 char* fLog Path;43 char* fLogFile; 35 44 char** fUSBDevice; 36 45 … … 42 51 int DACMin; 43 52 int DACMax; 44 float HVMin;45 float HVMax;46 53 47 54 float fHVCalibOffset; 48 55 float fHVCalibSlope; 49 float fHVMaxDiff; 56 57 unsigned int fHVMaxDiff; 50 58 51 59 }; 52 60 61 bool ReadCard(const char *, void *, char, FILE *, unsigned int=1); 62 53 63 #endif -
hvcontrol/src/ProcessIO.cc
r80 r90 2 2 /********************************************************************\ 3 3 4 Name: ProcessIO.cc 5 6 Created by: Sebastian Commichau, November 2008 7 commichau@phys.ethz.ch 8 9 Contents: Main class processing user input 4 ProcessIO.cc 5 6 Main class processing user input 7 8 Sebastian Commichau, Sabrina Stark-Schneebeli, Oliver Grimm 10 9 11 10 \********************************************************************/ 12 11 13 14 12 #include "ProcessIO.h" 15 13 14 static char* state_str[] = {"active", "stopped", "n.a."}; 16 15 17 16 ProcessIO::ProcessIO(char *ConfigFile) { 18 17 19 // Get program start time - only needed for uptime command18 // Get program start time 20 19 time (&StartTime); 21 20 22 status = new Status;23 config 21 // Create instances 22 config = new HVConfig(stdout,ConfigFile); 24 23 calib = new HVCalib(config); 25 log = new Log(config->fLogPath); 26 hv = new HV(config->fUSBDevice,config->USBDeviceNumber,stdout,config->TestMode); 27 28 pm = new PixelMap(config->fPixMapTable); 29 30 // Initialize status structure (HVStatus.cc/h) 31 InitStatus(status,config); 32 33 // Print HV control configuration to the log file 34 config->PrintHVConfig(log->logptr); 35 36 // The following loop was added to allow for an arbitrary numeration of the HV boards 37 for (int i=0;i<hv->GetNumberOfBoards();i++) { 38 39 sprintf(status->fUSBDevice[i],"%s",(hv->GetHVBoard(i))->GetSerial()); 40 status->USBDeviceNumber[i] = (hv->GetHVBoard(i))->GetBoardNumber(); 41 42 if ((hv->GetHVBoard(i))->GetBoardNumber() > status->USBMaxDeviceNumber) 43 status->USBMaxDeviceNumber = (hv->GetHVBoard(i))->GetBoardNumber(); 44 45 if ((hv->GetHVBoard(i))->GetBoardNumber() < status->USBMinDeviceNumber) 46 status->USBMinDeviceNumber = (hv->GetHVBoard(i))->GetBoardNumber(); 47 48 (hv->GetHVBoard(i))->SetTimeOut(config->fTimeOut); 49 } 50 51 // Initialize HV boards (see below) 52 InitializeHV(); 53 54 status->FirstBoard = 0; 55 status->NumHVBoards = hv->GetNumberOfBoards(); 56 status->LastBoard = hv->GetNumberOfBoards()-1; 57 58 // Print status information to the log file 59 PrintStatus(status,config,log->logptr); 60 61 // Send reset command to all boards 62 ResetAllBoards(); 63 64 // Print some information 65 sprintf(str,"status monitor: %s\n", GetStateStr(status)); 66 if (hv->GetNumberOfBoards()>0) DoPrompt(str); 67 68 sprintf(str,"type (h)elp to get a list of available commands\n"); 69 DoPrompt(str); 70 71 // Print empty prompt 72 DoPrompt(NULL); 73 74 // Initialize mutex variable for thread synchronization 75 pthread_mutex_init (&control_mutex, NULL); 76 pthread_cond_init (&control_cond, NULL); 77 78 sprintf(str,"**************** End of constructor ProcessIO ************\n"); 79 DoPrompt(str); 80 81 } 82 83 84 ProcessIO::~ProcessIO() { 85 86 pthread_mutex_destroy (&control_mutex); 87 pthread_cond_destroy (&control_cond); 88 89 config->fStatusRefreshRate = status->fStatusRefreshRate; 90 config->fTimeOut = status->fTimeOut; 91 config->WriteHVConfig(stdout,config->FileName); 92 93 delete hv; 94 delete status; 95 delete config; 96 delete log; 97 delete pm; 98 99 } 100 101 102 // Print list of all commands 103 void ProcessIO::PrintHelp() { 104 105 puts(""); 106 puts("********************************************** HELP *********************************************\n"); 107 puts(" board <i>|<i> <j>|<all> Address board i, boards i-j or all boards"); 108 puts(" chain <i>|<i> <j>|<all> Address chain i, chains i-j or all chains"); 109 puts(" clear Clear screen"); 110 puts(" config Print configuration"); 111 puts(" help Print help"); 112 puts(" hv <ch>|<all> [b][x]<v> Set chan. <ch>|<all> chan. of active chain(s)/board(s) to <v>"); 113 // puts(" hvdiff <ch>|<all> [b][x]<diff> Set chan. <ch>|<all> chan. of active chain(s)/board(s) to <diff>"); 114 puts(" hvdiff <PXL id> <diff> Set HV difference of pixel PXL id to <diff>"); 115 puts(" list List all HV boards"); 116 puts(" load <file> Load HV settings from <file>"); 117 puts(" log <on>|<off> Enable|disable logging"); 118 puts(" quit|exit Exit program"); 119 puts(" rate <rate> Set status refresh rate to <rate> [Hz]"); 120 puts(" reset Reset active HV board"); 121 puts(" save [file] Save current HV settings to [file]"); 122 puts(" start Start HV status monitor"); 123 puts(" status Show status information"); 124 puts(" stop Stop HV status monitor - not recommended!"); 125 puts(" time Print current date and time"); 126 puts(" timeout <time> Set timeout to return from read to <time> [s]"); 127 puts(" uptime Get program uptime [h:m:s]"); 128 puts(" verbose <on>|<off> Enable|disable verbosity"); 129 puts(" vref [b][x]<v> Set reference voltage of active chain(s)/board(s) to <v>\n"); 130 puts("*************************************************************************************************\n"); 131 132 } 133 134 135 // Process user input 136 int ProcessIO::CommandControl() { 137 138 139 // Adress HV board 140 if (Match(status->Param[0], "board")) { 141 142 if (!NBoards()) 143 return 0; 144 else { 145 146 // Select all boards 147 if (status->Param[1][0] == 'a' && !status->Param[2][0]) { 148 149 status->FirstBoard = 0; 150 status->LastBoard = hv->GetNumberOfBoards()-1; 151 152 } 153 // Wrong type of argument 154 else if (!IsNoDigit(status->Param[1]) || !IsNoDigit(status->Param[2]) || status->Param[3][0] || !status->Param[1][0]) { 155 sprintf(str,"ERROR - usage: <board> <i>|<i> <j>|<all>\n"); 156 DoPrompt(str); 157 return 0; 158 } 159 // Check if board(s) exist(s) 160 else if (status->Param[1][0] || status->Param[2][0]) { 161 162 if (!IsBoard(atoi(status->Param[1]))) { 163 sprintf(str,"ERROR -board #%d does not exist\n", atoi(status->Param[1])); 164 DoPrompt(str); 165 return 0; 166 } 167 168 if (status->Param[2][0]) 169 if (!IsBoard(atoi(status->Param[2]))) { 170 sprintf(str,"ERROR -board #%d does not exist\n", atoi(status->Param[2])); 171 DoPrompt(str); 172 return 0; 173 } 174 175 if (status->Param[1][0] && status->Param[2][0]) { 176 177 status->FirstBoard = GetBoardIdx(atoi(status->Param[1])); 178 status->LastBoard = GetBoardIdx(atoi(status->Param[2])); 179 180 } 181 else if (status->Param[1][0]) { 182 183 status->FirstBoard = GetBoardIdx(atoi(status->Param[1])); 184 status->LastBoard = status->FirstBoard; 185 186 } 187 } 188 189 //DoPrompt(NULL); 190 } 191 192 DoPrompt(NULL); 193 return 0; 194 } 195 196 197 // Adress chains 198 else if (Match(status->Param[0], "chain")) { 199 200 if (!NBoards()) 201 return 0; 202 else { 203 204 if (status->Param[1][0] == 'a') { 205 206 status->FirstChain = 0; 207 status->LastChain = 3; 208 209 } 210 else if (!IsNoDigit(status->Param[1]) || !status->Param[1][0]) { 211 sprintf(str,"ERROR -usage: <chain> <i>|<i> <j>|<all>\n"); 212 DoPrompt(str); 213 return 0; 214 } 215 else if (status->Param[1][0] >= 0 && atoi(status->Param[1]) >= 0 && atoi(status->Param[1]) < 4 && !status->Param[2][0]) { 216 217 status->FirstChain = atoi(status->Param[1]); 218 status->LastChain = status->FirstChain; 219 220 } 221 else if ((status->Param[1][0] >= 0 && atoi(status->Param[1]) >= 0 && atoi(status->Param[1]) < 4) && 222 (status->Param[2][0] > 0 && atoi(status->Param[2]) > 0 && atoi(status->Param[2]) < 4)) { 223 224 status->FirstChain = atoi(status->Param[1]); 225 status->LastChain = atoi(status->Param[2]); 226 24 pm = new PixelMap(config->fPixMapTable); 25 26 // Initialize status variables 27 state = active; 28 Exit = false; 29 Verbose = false; 30 CmdFromSocket = false; 31 Socket = -1; 32 33 NumHVBoards = 0; 34 FirstBoard = 0; 35 LastBoard = -1; 36 FirstChain = 0; 37 LastChain = 3; 38 39 if (config->fStatusRefreshRate >= MIN_RATE && config->fStatusRefreshRate <= MAX_RATE) 40 fStatusRefreshRate = config->fStatusRefreshRate; 41 else fStatusRefreshRate = 1.; 42 43 // Open HV devices 44 if(config->TestMode){ 45 fprintf(stdout,"Test mode: One HVBoard initialized as dummy.\n"); 46 fHVBoard[NumHVBoards] = new HVBoard(0, 0, config->TestMode, config->fTimeOut, Verbose); 47 NumHVBoards++; 48 } 49 else { 50 for (int i=0; i<config->NumHVBoards; i++) { 51 fHVBoard[NumHVBoards] = new HVBoard(config->USBDeviceNumber[i], config->fUSBDevice[i], config->TestMode, config->fTimeOut, Verbose); 52 if(fHVBoard[NumHVBoards]->fDescriptor >= 0) { 53 printf("Synchronized and reset HV board %d (%s)\n",i,config->fUSBDevice[i]); 54 NumHVBoards++; 227 55 } 228 56 else { 229 230 if (atoi(status->Param[1]) < 0 || atoi(status->Param[1]) > 3) { 231 sprintf(str,"ERROR -chain #%d does not exist\n", atoi(status->Param[1])); 232 DoPrompt(str); 233 } 234 235 236 if ((atoi(status->Param[2]) < 0 || atoi(status->Param[2]) > 3) && (atoi(status->Param[1]) != atoi(status->Param[2]))) { 237 sprintf(str,"ERROR -chain #%d does not exist\n", atoi(status->Param[2])); 238 DoPrompt(str); 239 } 240 241 return 0; 242 57 printf("Failed to synchronize to HV board %d (%s)\n",i,config->fUSBDevice[i]); 58 delete fHVBoard[NumHVBoards]; 243 59 } 244 245 DoPrompt(NULL); 246 } 247 248 return 0; 60 } 249 61 } 250 251 252 // Clear screen 253 else if (Match(status->Param[0], "clear") || Match(status->Param[0], "cls")) { 254 255 system("clear"); 256 DoPrompt(NULL); 257 258 return 0; 259 260 } 62 LastBoard = NumHVBoards-1; 63 64 // Open log file 65 if ((Logfile = fopen(config->fLogFile, "a")) == NULL) printf("Warning: Could not open log file '%s'\n", config->fLogFile); 66 PrintMessage(MsgToLog,"********** Logging started **********\n"); 67 68 // Print configuration to log file 69 if(Logfile) config->PrintHVConfig(Logfile); 70 } 71 72 73 ProcessIO::~ProcessIO() { 74 75 for (int i=0; i<NumHVBoards; i++) delete fHVBoard[i]; 76 77 delete config; delete pm; 78 79 if(Logfile != NULL) { 80 if(!fclose(Logfile)) printf("Closing logfile\n"); 81 else perror("Error closing logfile"); 82 } 83 } 84 85 86 // Process user input 87 void ProcessIO::CommandControl(char *Command) { 88 89 if (strlen(Command)==0) return; // Ignore empty commands 90 91 if(Command[0]=='.') { // Shell command 92 system(&(Command[1])); 93 return; 94 } 95 96 for(int i=0; i<MAX_NUM_TOKEN; i++) Param[i] = ""; // All pointers point initially to empty string 97 NParam = ParseInput(Command, Param); 98 99 // Adress HV board 100 if (Match(Param[0], "board")) { 101 102 if (!NumHVBoards) return; 103 104 // Print list of boards 105 if (NParam == 1) { 106 for (int i=0; i<NumHVBoards; i++) { 107 PrintMessage("Board %d: %s\n", fHVBoard[i]->GetBoardNumber(), fHVBoard[i]->BoardName); 108 } 109 return; 110 } 111 112 //Select board(s) 113 if (Match(Param[1],"all")) { 114 FirstBoard = 0; 115 LastBoard = NumHVBoards-1; 116 } 117 else if (NParam==2 && atoi(Param[1])>=0 && atoi(Param[1])<NumHVBoards) { 118 FirstBoard = atoi(Param[1]); 119 LastBoard = FirstBoard; 120 } 121 else if (NParam==3 && atoi(Param[1])>=0 && atoi(Param[1])<NumHVBoards && 122 atoi(Param[2])>0 && atoi(Param[2])<NumHVBoards) { 123 FirstBoard = atoi(Param[1]); 124 LastBoard = atoi(Param[2]); 125 } 126 else PrintMessage("Cannot address board(s), out of range.\n"); 127 128 return; 129 } 130 131 132 // Adress chains 133 else if (Match(Param[0], "chain")) { 134 135 if (!NumHVBoards) return; 136 137 if (Match(Param[1],"all")) { 138 FirstChain = 0; 139 LastChain = 3; 140 } 141 else if (NParam==2 && atoi(Param[1])>=0 && atoi(Param[1])<4) { 142 FirstChain = atoi(Param[1]); 143 LastChain = FirstChain; 144 } 145 else if (NParam==3 && atoi(Param[1])>=0 && atoi(Param[1])<4 && 146 atoi(Param[2])>0 && atoi(Param[2])<4) { 147 FirstChain = atoi(Param[1]); 148 LastChain = atoi(Param[2]); 149 } 150 else PrintMessage("Cannot address chain(s), out of range.\n"); 151 152 return; 153 } 261 154 262 155 263 156 // Print HV utility configuration 264 else if (Match( status->Param[0], "config")) {157 else if (Match(Param[0], "config")) { 265 158 266 159 config->PrintHVConfig(stdout); 267 160 268 return 0;161 return; 269 162 } 270 163 271 164 272 165 // Print help 273 if (Match(status->Param[0], "help")) { 274 275 PrintHelp(); 276 DoPrompt(NULL); 277 278 return 0; 166 if (Match(Param[0], "help")) { 167 puts(" board <i>|<i> <j>|<all> Address board i, boards i-j or all boards or list boards"); 168 puts(" chain <i>|<i> <j>|<all> Address chain i, chains i-j or all chains"); 169 puts(" hv <PXL id>|<ch>|<all> <v> Set HV of pixel ID, ch. or all ch. of active chain(s)/board(s)"); 170 puts(" hvdiff <PXL id>|<ch>|<all> <diff> Change HV by <diff>"); 171 puts(" status [dac] Show status information (DAC values if requested)"); 172 puts(" config Print configuration"); 173 puts(" load <file> Load HV settings from <file>"); 174 puts(" save <file> Save current HV settings to [file]"); 175 puts(" exit Exit program"); 176 puts(" rate <rate> Set status refresh rate to <rate> [Hz]"); 177 puts(" timeout <time> Set timeout to return from read to <time> [s]"); 178 puts(" reset Reset active HV board"); 179 puts(" start Start HV status monitor"); 180 puts(" stop Stop HV status monitor - not recommended!"); 181 puts(" uptime Get program uptime [h:m:s]"); 182 puts(" verbose <on|off>| Enable|disable verbosity"); 183 puts(" help Print help"); 184 puts(" .<cmd> Execute shell command <cmd>"); 185 186 return; 279 187 } 280 188 281 189 282 // Write high voltage ----------------------------------------------------------------------------------------- 283 if (Match(status->Param[0], "hv")) { 284 285 if (!NBoards()) 286 return 0; 287 288 int errors = 0; 289 unsigned int hvoltage = 0, hvAll = 0; 290 float hvoltageV = 0.0; 291 int channel = 0, hvdiff = 0; 292 bool allchannels = FALSE; 293 294 if (status->Param[1][0]>0 && status->Param[2][0]>0) { 295 296 // Set channel 297 if (IsNoDigit(status->Param[1])) 298 channel = atoi(status->Param[1]); 299 else if(status->Param[1][0] == 'a') 300 allchannels = TRUE; 301 else { 302 DoPrompt("ERROR - wrong input format - usage: hv <channel>|<all> <voltage>\n"); 303 return 0; 304 } 305 306 // Binary input 307 if (tolower(status->Param[2][0])=='x' && strlen(status->Param[2])>2) { 308 if (sPrintHex2Dec(Chop(status->Param[2]+1),&hvoltage)!=0) { 309 DoPrompt("ERROR - wrong input format - usage: hv <channel>|<all> <voltage>\n"); 310 return 0; 311 } 312 } 313 // Hexadecimal input 314 else if (tolower(status->Param[2][0])=='b' && strlen(status->Param[2])>2) { 315 if (sPrintBin2Dec(Chop(status->Param[2]+1),&hvoltage)!=0) { 316 DoPrompt("ERROR - wrong input format - usage: hv <channel>|<all> <voltage>\n"); 317 return 0; 318 } 319 } 320 // Decimal input 321 else if (IsNoDigit(status->Param[2])&&config->IsDAC) 322 hvoltage = atoi(status->Param[2]); 323 else if (IsNoDigit(status->Param[2])&&(!(config->IsDAC))) 324 hvoltageV = atof(status->Param[2]); 325 // Wrong input format 326 else { 327 DoPrompt("ERROR - wrong input format - usage: hv <channel>|<all> <voltage>\n"); 328 return 0; 329 } 330 331 // Check limits 332 if (channel>31 || channel <0) { 333 DoPrompt("ERROR - channel out of range (0...31)!\n"); 334 return 0; 335 } 336 else if ((hvoltage>0X3FFF || hvoltage <0)&&config->IsDAC) { 337 DoPrompt("ERROR - high voltage out of range (Vmin: 0, Vmax: 16383)!\n"); 338 return 0; 339 } 340 else if ((hvoltage>78.0 || hvoltage <0)&&(!(config->IsDAC))) { 341 DoPrompt("ERROR - high voltage out of range (Vmin: 0, Vmax: 78.)!\n"); 342 return 0; 343 } 344 345 StopMonitor(); 346 347 348 for (int i=status->FirstBoard;i<=status->LastBoard;i++) { 349 350 for (int j=status->FirstChain;j<=status->LastChain;j++) { 351 if (!allchannels) { 352 // Convert from HV to DAC values 353 if (!(config->IsDAC)){ 354 status->HVV[i][j][channel]=hvoltageV; 355 hvoltage = calib->HVToDAC(hvoltageV,i,j,channel); 356 } 357 hvdiff = hvoltage - status->HV[i][j][channel]; 358 for (int k=0;k<=abs((int)(hvdiff/config->fHVMaxDiff));k++){ 359 if (k<abs((int)(hvdiff/config->fHVMaxDiff))){ 360 hvoltage=(unsigned int)(status->HV[i][j][channel] + config->fHVMaxDiff*hvdiff/abs(hvdiff)); 361 } 362 if (k==(abs((int)(hvdiff/config->fHVMaxDiff)))){ 363 hvoltage=(unsigned int)(status->HV[i][j][channel] + (hvdiff%(int)config->fHVMaxDiff)); 364 } 365 366 if ((hv->GetHVBoard(i))->SetHV(stdout,j,channel,hvoltage,rbuf,status->Verbose)==1){ 367 status->HV[i][j][channel]=hvoltage; 368 UpdateStatus(i,rbuf); 369 370 sprintf(str,"OK - board %d: high voltage of chain %d channel %d set to %d | 0X%.4X | %f V\n",hv->GetHVBoard(i)->GetBoardNumber(),j,channel,hvoltage,hvoltage,calib->DACToHV(hvoltage,hv->GetHVBoard(i)->GetBoardNumber(),j,channel)); 371 // DoPrompt(str); 372 if (status->Verbose) { 373 sPrintStatus(status,str,i); 374 DoPrompt(str); 375 } 376 sPrintStatus(status,str,i); // Print status only to socket 377 } 378 else { 379 sprintf(str,"ERROR - board %d error: could not set hv - check timeout and try again\n",hv->GetHVBoard(i)->GetBoardNumber()); 380 DoPrompt(str); 381 errors++; 382 } 383 } 190 // Set new high voltage -------------------------------------------------------------------------------------- 191 if (Match(Param[0], "hv") || Match(Param[0], "hvdiff")) { 192 193 if (!NumHVBoards) return; 194 195 int hvoltage, DACValue, Errors=0, Board, Chain=0, Channel=0; 196 double hvoltageV; 197 bool allchannels = false, SetDac = false; 198 199 // Need two parameters or three if last is 'dac' 200 if (NParam<3 || NParam>4) { 201 PrintMessage("ERROR - usage: hv <channel>|<all> <voltage> [dac]\n"); 202 return; 203 } 204 205 if (NParam==4 && Match(Param[3], "dac")) SetDac = true; 206 207 // Evaluate pixel or channel parameter 208 if((Board = pm->Pixel_to_HVboard(Param[1])) != 999999999) { 209 Chain = pm->Pixel_to_HVchain(Param[1]); 210 Channel = pm->Pixel_to_HVchannel(Param[1]); 211 } 212 else if (Match(Param[1], "all")) allchannels = true; 213 else if (ConvertToInt(Param[1], &Channel)) { 214 Board = -1; 215 Chain = -1; 216 } 217 else { 218 PrintMessage("ERROR - wrong input format - usage: hv <channel>|<all> <voltage>\n"); 219 return; 220 } 221 // Check channel limits (voltage limit is only checked in SetHV()) 222 if (Channel<0 || Channel>31) { 223 PrintMessage("ERROR - channel out of range (0...31)!\n"); 224 return; 225 } 226 227 if (SetDac && !ConvertToInt(Param[2], &hvoltage)) { 228 PrintMessage("ERROR - wrong number format for DAC voltage setting\n"); 229 return; 230 } 231 if (!SetDac && !ConvertToDouble(Param[2], &hvoltageV)) { 232 PrintMessage("ERROR - wrong number format for voltage setting\n"); 233 return; 234 } 235 236 for (int i=FirstBoard; i<=LastBoard; i++) { 237 if (!allchannels && Board != 999999999 && i != Board && Board!=-1) continue; 238 239 for (int j=FirstChain; j<=LastChain; j++) { 240 if (!allchannels && Chain != 999999999 && j != Chain && Chain!=-1) continue; 241 242 for (int k=0; k<NUM_CHANNELS; k++) { 243 if (!allchannels && k!= Channel) continue; 244 245 // Convert from HV to DAC values 246 if (!SetDac){ 247 if(strlen(Param[0]) > 2) fHVBoard[i]->HVV[j][k] += hvoltageV; // hvdiff 248 else fHVBoard[i]->HVV[j][k] = hvoltageV; 249 DACValue = calib->HVToDAC(fHVBoard[i]->HVV[j][k], i, j, k); 384 250 } 385 251 else { 386 sprintf(str,"OK - updating board %d chain %d\n",hv->GetHVBoard(i)->GetBoardNumber(),j); 387 DoPrompt(str); 252 if(strlen(Param[0]) > 2) DACValue = fHVBoard[i]->HV[j][k] + hvoltage; // hvdiff 253 else DACValue = hvoltage; 254 } 388 255 389 for (int k=0;k<MAX_NUM_CHANNELS;k++) { 390 // Convert from HV to DAC values 391 if (!(config->IsDAC)){ 392 status->HVV[i][j][k]=hvoltageV; 393 hvoltage = calib->HVToDAC(hvoltageV,i,j,k); 394 } 395 hvAll = hvoltage; 396 hvdiff = hvAll - status->HV[i][j][k]; 397 for (int l=0;l<=abs((int)(hvdiff/config->fHVMaxDiff));l++){ 398 if (l<abs((int)(hvdiff/config->fHVMaxDiff))){ 399 hvoltage=(unsigned int)(status->HV[i][j][k] + config->fHVMaxDiff*hvdiff/abs(hvdiff)); 400 } 401 if (l==(abs((int)(hvdiff/config->fHVMaxDiff)))){ 402 hvoltage=(unsigned int)(status->HV[i][j][k] + (hvdiff%(int)config->fHVMaxDiff)); 403 } 404 if ((hv->GetHVBoard(i))->SetHV(stdout,j,k,hvoltage,rbuf,status->Verbose)==1) { 405 status->HV[i][j][k]=hvoltage; 406 UpdateStatus(i,rbuf); 407 408 if (status->Verbose) { 409 sprintf(str,"OK - board %d: high voltage of chain %d channel %d set to %d | 0X%.4X | %f V\n",hv->GetHVBoard(i)->GetBoardNumber(),j,channel,hvoltage,hvoltage,calib->DACToHV(hvoltage,hv->GetHVBoard(i)->GetBoardNumber(),j,channel)); 410 //sprintf(str,"board %d: high voltage of chain %d channel %d set to %d | 0X%.4X\n",hv->GetHVBoard(i)->GetBoardNumber(),j,k,hvoltage,hvoltage); 411 // DoPrompt(str); 412 sPrintStatus(status,str,i); 413 DoPrompt(str); 414 } 415 sPrintStatus(status,str,i); // Print status only to socket 416 } 417 418 else { 419 sprintf(str,"ERROR - board %d error: could not set HV - check timeout and try again\n",hv->GetHVBoard(i)->GetBoardNumber()); 420 DoPrompt(str); 421 errors++; 422 } 423 } 256 // Set new voltage (if DAC value, update calilbrated value) 257 if(!RampVoltage(DACValue, i, j, k)) Errors++; 258 else if(SetDac) fHVBoard[i]->HVV[j][k] = calib->DACToHV(fHVBoard[i]->HV[j][k], i, j, k); 259 260 } // Channels 261 } // Chains 262 } // Boards 263 264 if (Errors > 0) PrintMessage("Warning: Errors on %d channel(s) occurred\n", Errors); 265 else PrintMessage("OK - no error(s)\n"); 266 267 return; 268 } 269 270 271 // Load HV settings from file 272 else if (Match(Param[0], "load")) { 273 274 char Buffer[MAX_COM_SIZE]; 275 int NBoards = 0, Errors = 0, Chain; 276 unsigned int DACValue; 277 FILE *File; 278 279 if (NParam != 2) { 280 PrintMessage("Usage: load <file>\n"); 281 return; 282 } 283 284 if ((File=fopen(Param[1], "r")) == NULL) { 285 PrintMessage("Error: Could not open file '%s' (%s)\n", Param[1], strerror(errno)); 286 return; 287 } 288 289 StopMonitor(); 290 291 while (fgets(Buffer, sizeof(Buffer), File) != NULL) { 292 for (int Board=0; Board<NumHVBoards; Board++) { 293 if (Match(fHVBoard[Board]->BoardName, Buffer)) { 294 295 PrintMessage("Found HV settings for board %d (%s)\n",fHVBoard[Board]->GetBoardNumber(), fHVBoard[Board]->BoardName); 296 297 Chain = 0; 298 while (fgets(Buffer, sizeof(Buffer), File) && Chain<NUM_CHAINS) { 299 if (strlen(Buffer) == 1) continue; // Ignore if only newline character 300 301 for (int Channel=0; Channel<NUM_CHANNELS; Channel++) { 302 if (sscanf(Buffer, "%u", &DACValue) != 1) { 303 PrintMessage("Error reading DAC values from file, terminating\n"); 304 return; 305 } 306 if (!RampVoltage(DACValue, Board, Chain, Channel)) Errors++; 424 307 } 308 Chain++; 425 309 } 310 PrintMessage("Finished updating board.\n"); 311 NBoards++; 426 312 } 427 } 428 429 430 431 StartMonitor(); 432 433 if (errors) { 434 sprintf(str,"ERROR - warning %d error(s) => check timeout and try again\n",errors); 435 DoPrompt(str); 436 } 437 else { 438 sprintf(str,"OK - no error(s)... success!\n"); 439 DoPrompt(str); 440 } 441 442 } 443 else { 444 sprintf(str,"ERROR - usage: hv <channel>|<all> <voltage>\n"); 445 DoPrompt(str); 446 } 447 448 return 0; 449 } // End: Write high voltage ---------------------------------------------------------------------------------------- 450 451 452 453 // Write difference of high voltage ------------------------------------------------------------------------------------ 454 if (Match(status->Param[0], "hvdiff")) { 455 456 if (!NBoards()) 457 return 0; 458 459 int errors = 0; 460 int hvdiff = 0; 461 unsigned int hvoltage = 0; 462 float hvoltageV = 0.0; 463 float hvdiffV = 0.0; 464 std::string pixelname(status->Param[1]); 465 unsigned int board = 0; 466 unsigned int chain = 0; 467 unsigned int channel = 0; 468 469 470 if (status->Param[1][0]>0 && status->Param[2][0]>0) { 471 472 473 // Set board 474 board = pm->Pixel_to_HVboard(pixelname); 475 // std::cout << "Board: " << board << std::endl; 476 // Set chain 477 chain = pm->Pixel_to_HVchain(status->Param[1]); 478 // std::cout << "Chain: " << chain << std::endl; 479 // Set channel 480 channel = pm->Pixel_to_HVchannel(status->Param[1]); 481 // std::cout << "Channel: " << channel << std::endl; 482 483 // Binary input 484 if (tolower(status->Param[2][0])=='x' && strlen(status->Param[2])>2) { 485 if (sPrintHex2Dec(Chop(status->Param[2]+1),(unsigned int *)hvdiff)!=0) { 486 DoPrompt("ERROR - wrong input format - usage: hvdiff <channel>|<all> <hv difference>\n"); 487 return 0; 488 } 489 } 490 // Hexadecimal input 491 else if (tolower(status->Param[2][0])=='b' && strlen(status->Param[2])>2) { 492 if (sPrintBin2Dec(Chop(status->Param[2]+1),(unsigned int *)hvdiff)!=0) { 493 DoPrompt("ERROR - wrong input format - usage: hvdiff <channel>|<all> <hv difference>\n"); 494 return 0; 495 } 496 } 497 // Decimal input 498 else if (IsNoDigit(status->Param[2])&&(config->IsDAC)) 499 hvdiff = atoi(status->Param[2]); 500 else if (IsNoDigit(status->Param[2])&&(!(config->IsDAC))) 501 hvdiffV = atof(status->Param[2]); 502 // Wrong input format 503 else { 504 DoPrompt("ERROR - wrong input format - usage: hvdiff <channel>|<all> <hv difference>\n"); 505 return 0; 506 } 507 // Check limits 508 if (channel>31 || channel <0) { 509 sprintf(str,"ERROR - channel out of range (0...31)!\n"); 510 DoPrompt(str); 511 return 0; 512 } 513 else if (hvdiff>config->DACMax || hvdiff <(-(config->DACMax))) { 514 sprintf(str,"ERROR - difference of high voltage [hvdiff:%d] out of range (Vmin: 0.0, Vmax: %d)!\n", hvdiff,config->DACMax); 515 DoPrompt(str); 516 return 0; 517 } 518 else if (hvdiffV>(calib->DACToHV(config->DACMax,0,0,0))|| hvdiffV<-(calib->DACToHV(config->DACMax,0,0,0))) { 519 sprintf(str,"ERROR - difference of high voltage [hvdiff:%f] out of range (Vmin: 0.0, Vmax: %f)!\n",hvdiffV,calib->DACToHV(config->DACMax,0,0,0)); 520 DoPrompt(str); 521 return 0; 522 } 523 524 525 526 //Convert from HV to DAC values 527 if (!(config->IsDAC)){ 528 hvoltageV = status->HVV[board][chain][channel]+hvdiffV; 529 status->HVV[board][chain][channel] = hvoltageV; 530 // printf("hv+diff = %f .\n",hvoltageV); 531 hvdiff = calib->HVToDAC(hvoltageV,board,chain,channel) - status->HV[board][chain][channel]; 532 // printf("dac new = %d, dac old = %d.\n",calib->HVToDAC(hvoltageV,board,chain,channel),status->HV[board][chain][channel]); 533 // printf("dac diff = %d .\n",hvdiff); 534 } 535 StopMonitor(); 536 537 538 539 hvoltage = status->HV[board][chain][channel]; 540 // printf("dac hv = %d .\n",hvoltage); 541 for (int k=0;k<=abs((int)(hvdiff/config->fHVMaxDiff));k++){ 542 if (k<abs((int)(hvdiff/config->fHVMaxDiff))){ 543 hvoltage=(unsigned int)(hvoltage + config->fHVMaxDiff*hvdiff/abs(hvdiff)); 544 } 545 if (k==(int)(abs((int)(hvdiff/config->fHVMaxDiff)))){ 546 hvoltage=(unsigned int)(hvoltage + (hvdiff%(int)config->fHVMaxDiff)); 547 } 548 549 550 status->HV[board][chain][channel]=hvoltage; 551 // printf("dac hv rampingup= %d .\n",hvoltage); 552 if ((hv->GetHVBoard(board))->SetHV(stdout,chain,channel,hvoltage,rbuf,status->Verbose)==1) { 553 UpdateStatus(board,rbuf); 554 if (k==(abs((int)(hvdiff/config->fHVMaxDiff)))){ 555 sprintf(str,"OK - board %d: high voltage of chain %d channel %d set to %d | 0X%.4X | %f V\n",hv->GetHVBoard(board)->GetBoardNumber(),chain,channel,hvoltage,hvoltage,calib->DACToHV(hvoltage,hv->GetHVBoard(board)->GetBoardNumber(),chain,channel)); 556 //sprintf(str,"board %d: high voltage of chain %d channel %d set to %d | 0X%.4X\n",hv->GetHVBoard(board)->GetBoardNumber(),chain,channel,hvoltage,hvoltage); 557 DoPrompt(str); 558 sPrintStatus(status,str,board); // Print status only to socket 559 } 560 } 561 else { 562 sprintf(str,"ERROR - board %d chain %d channel %d error: could not set hv - check timeout and try again\n",hv->GetHVBoard(board)->GetBoardNumber(), chain, channel); 563 DoPrompt(str); 564 errors++; 565 } 566 } // for loop over k 567 if (status->Verbose) { 568 sPrintStatus(status,str,board); 569 DoPrompt(str); 570 } 571 572 573 StartMonitor(); 574 575 if (errors) { 576 sprintf(str,"ERROR - warning %d error(s)\n",errors); 577 DoPrompt(str); 578 } 579 else { 580 sprintf(str,"OK - no error(s)... success!\n"); 581 DoPrompt(str); 582 } 583 } 584 else { 585 sprintf(str,"ERROR - usage: hvdiff <PXL id> <hv difference>\n"); 586 DoPrompt(str); 587 } 588 return 0; 589 590 } 591 592 // End: Write difference of high voltage -------------------------------------------------------------------- 593 594 595 596 // List HV boards 597 else if (Match(status->Param[0], "list")) { 598 599 sprintf(str,"OK - %d HV board(s) active:\n",hv->GetNumberOfBoards()); 600 DoPrompt(str); 601 602 for (int i=0;i<hv->GetNumberOfBoards();i++) { 603 sprintf(str,"OK - board %d (%s)\n",(hv->GetHVBoard(i))->GetBoardNumber(),(hv->GetHVBoard(i))->GetSerial()); 604 DoPrompt(str); 605 } 606 607 return 0; 608 } 609 610 611 // Load HV settings from file 612 else if (Match(status->Param[0], "load")) { 613 614 char param[20][MAX_COM_SIZE]; 615 char buffer[128]; 616 617 int nparam = 0; 618 int nrows = 0; 619 int board = 0; 620 int chain = 0; 621 int channel = 0; 622 int nboards = 0; 623 int errors = 0; 624 unsigned int hvoltage = 0; 625 626 FILE *file; 627 628 if (status->Param[1][0] && !status->Param[2][0]) { 629 630 if ((file=fopen((char *)Chop(status->Param[1]),"r"))!=NULL) { 631 632 if (status->Verbose) { 633 sprintf(str,"OK - file \"%s\" opened\n",Chop(status->Param[1])); 634 DoPrompt(str); 635 } 636 637 StopMonitor(); 638 639 while (fgets(buffer,100,file)) { 640 641 ParseInput(buffer,&nparam,param); 642 643 if (nparam==2 && Match(param[0],"Device:")) { 644 645 for (int j=0;j<hv->GetNumberOfBoards();j++) 646 if (Match(Chop(status->fUSBDevice[j]),Chop(param[1]))) { 647 648 board = j; 649 650 sprintf(str,"OK - found HV settings for board %d (%s)\n",hv->GetHVBoard(board)->GetBoardNumber(),Chop(param[1])); 651 DoPrompt(str); 652 653 nboards++; 654 nrows = 0; 655 656 while (fgets(buffer,100,file)) { 657 658 ParseInput(buffer,&nparam,param); 659 660 if (nparam==8) { 661 662 chain = nrows/4; 663 664 if (!((nrows)%4)) { 665 sprintf(str,"OK - updating board %d chain %d\n",hv->GetHVBoard(board)->GetBoardNumber(),chain); 666 DoPrompt(str); 667 } 668 669 670 for (int i=0;i<nparam;i++) { 671 672 hvoltage = atoi(param[i]); 673 channel = (i+8*nrows)%32; 674 675 // Submit HV values 676 if ((hv->GetHVBoard(board))->SetHV(stdout,chain,channel,hvoltage,rbuf,status->Verbose)==1) { 677 678 status->HV[board][chain][channel]=hvoltage; 679 UpdateStatus(board,rbuf); 680 681 if (status->Verbose) { 682 sprintf(str,"OK - board %d: high voltage of chain %d channel %d set to %d | 0X%.4X\n", 683 hv->GetHVBoard(board)->GetBoardNumber(),chain,channel,hvoltage,hvoltage); 684 DoPrompt(str); 685 sPrintStatus(status,str,board); 686 DoPrompt(str); 687 } 688 } 689 else { 690 sprintf(str,"ERROR - board %d error: could not set HV - check timeout and try again\n",hv->GetHVBoard(board)->GetBoardNumber()); 691 DoPrompt(str); 692 errors++; 693 } 694 695 } 696 697 nrows++; 698 699 } 700 else if (nparam==2) 701 break; 702 } 703 } 704 } 705 } 706 707 if (fclose (file)) { 708 sprintf(str,"ERROR - could not close file \"%s\"\n",Chop(status->Param[1])); 709 DoPrompt(str); 710 } 711 else { 712 if (status->Verbose) { 713 sprintf(str,"OK - file \"%s\" closed\n",Chop(status->Param[1])); 714 DoPrompt(str); 715 } 716 } 717 718 if (nboards!=hv->GetNumberOfBoards()) { 719 sprintf(str,"ERROR - warning: could not load HV settings for all connected HV boards\n"); 720 DoPrompt(str); 721 } 722 else { 723 sprintf(str,"OK - success: read HV settings for all connected HV boards\n"); 724 DoPrompt(str); 725 } 726 727 if (errors) { 728 sprintf(str,"ERROR - warning %d error(s) => check timeout and try again\n",errors); 729 DoPrompt(str); 730 } 731 else { 732 sprintf(str,"OK - no error(s)... success!\n"); 733 DoPrompt(str); 734 } 735 736 } 737 else { 738 sprintf(str,"ERROR - could not open file \"%s\"\n",Chop(status->Param[1])); 739 DoPrompt(str); 740 } 741 742 } 743 else 744 DoPrompt("ERROR - usage: load <file>\n"); 745 313 } // Loop over boards 314 } // while() 315 746 316 StartMonitor(); 747 748 return 0; 749 317 318 if (NBoards != NumHVBoards) { 319 PrintMessage("Warning: Could not load HV settings for all connected HV boards\n"); 320 } 321 else if (Errors == 0) PrintMessage("Success: Read HV settings for all connected HV boards\n"); 322 if (Errors != 0) PrintMessage("Warning: Errors on %d channel(s) occurred\n", Errors); 323 324 if (fclose(File) != 0) PrintMessage("Error: Could not close file '%s'\n",Param[1]); 325 326 return; 750 327 } 751 328 752 329 753 // Enable/disable logging754 else if (Match(status->Param[0], "log")) {755 756 if (Match(status->Param[1], "on") && status->Param[1][0]) {757 status->Log = TRUE;758 sprintf(str,"OK - logging enabled\n");759 DoPrompt(str);760 }761 762 else if (Match(status->Param[1], "off") && status->Param[1][0]) {763 status->Log = FALSE;764 sprintf(str,"OK -logging disabled\n");765 DoPrompt(str);766 }767 768 else769 DoPrompt("ERROR - usage: log <on>|<off>\n");770 771 return 0;772 }773 774 775 330 // Set status refresh rate 776 if (Match(status->Param[0], "rate")) { 777 778 if (!NBoards()) 779 return 0; 780 781 if (status->Param[1][0]>0) { 782 783 if (!IsNoDigit(status->Param[1])) { 784 DoPrompt("ERROR - wrong input format - usage: rate <rate>\n"); 785 return 0; 786 } 787 // Check limits 788 else if (atof(status->Param[1]) < MIN_RATE || atof(status->Param[1]) > MAX_RATE) { 789 sprintf(str,"ERROR - refresh rate out of range (min: %.2f Hz, max: %.2f Hz)!\n",MIN_RATE,MAX_RATE); 790 DoPrompt(str); 791 return 0; 792 } 793 else { 794 StopMonitor(); 795 status->fStatusRefreshRate=atof(status->Param[1]); 796 sprintf(str,"OK - status refresh rate set to %.2f Hz\n",status->fStatusRefreshRate); 797 DoPrompt(str); 798 } 799 StartMonitor(); 800 return 0; 801 802 } 803 else { 804 sprintf(str,"ERROR - usage: rate <rate>\n"); 805 DoPrompt(str); 806 } 807 808 return 0; 809 } 810 811 /* 812 // Read from device - NEVER use this function with a real HV board!!! 813 if (Match(status->Param[0], "read")) { 814 815 if (!NBoards()) 816 return 0; 817 818 if (status->state==active) { 819 StopMonitor(); 820 sprintf(str,"warning: status monitoring deactivated\n"); 821 DoPrompt(str); 822 } 823 824 for (int i=status->FirstBoard;i<=status->LastBoard;i++) { 825 if (1 == ((hv->GetHVBoard(i))->Read(rbuf,1))) { 826 sPrintByteBin(rbuf[0],bdata); 827 sprintf(str,"%d byte(s) read (board %d): %d | 0X%.2X | B%s\n",1,i,rbuf[0],rbuf[0],bdata); 828 } 829 else 830 sprintf(str,"error: could not read from board %d\n",i); 831 832 usleep(1000); 833 834 DoPrompt(str); 835 } 836 837 return 0; 838 } 839 */ 331 if (Match(Param[0], "rate")) { 332 333 double Rate; 334 335 if (!NumHVBoards) return; 336 337 if (NParam != 2) { 338 PrintMessage("Usage: rate <Hz>\n"); 339 return; 340 } 341 342 if (!ConvertToDouble(Param[1], &Rate)) { 343 PrintMessage("Error: Wrong number format\n"); 344 return; 345 } 346 347 // Check limits 348 if (Rate<MIN_RATE || Rate>MAX_RATE) { 349 PrintMessage("Refresh rate out of range (min: %.2f Hz, max: %.2f Hz)\n", MIN_RATE, MAX_RATE); 350 return; 351 } 352 353 StopMonitor(); 354 fStatusRefreshRate = Rate; 355 PrintMessage("Refresh rate set to %.2f Hz\n", fStatusRefreshRate); 356 StartMonitor(); 357 358 return; 359 } 840 360 841 361 // Reset 842 if (Match(status->Param[0], "reset")) { 843 844 if (!NBoards()) 845 return 0; 362 if (Match(Param[0], "reset")) { 363 364 if (!NumHVBoards) return; 846 365 847 366 StopMonitor(); 848 367 ResetActiveBoards(); 849 ReInitStatus(status);850 368 StartMonitor(); 851 return 0; 852 } 853 854 855 // Start ROOT 856 else if (Match(status->Param[0], "root")) { 857 858 sprintf(str,"OK - starting ROOT... type '.q' to return\n"); 859 DoPrompt(str); 860 system ("root"); 861 862 return 0; 863 369 return; 864 370 } 865 371 866 372 867 373 // Save HV settings of all boards 868 else if (Match(status->Param[0], "save")) { 869 870 if (status->Param[1][0] && !status->Param[2][0]) { 871 872 if (SaveHVSettings(Chop(status->Param[1]))) { 873 sprintf(str,"OK - HV settings written to \"%s\"\n",Chop(status->Param[1])); 874 DoPrompt(str); 374 else if (Match(Param[0], "save")) { 375 376 FILE *File; 377 time_t time_now_secs; 378 struct tm *Time; 379 380 if (NParam != 2) { 381 PrintMessage("Usage: save <Filename>\n"); 382 return; 383 } 384 385 time(&time_now_secs); 386 Time = localtime(&time_now_secs); 387 388 if ((File = fopen(Param[1], "w")) == NULL) { 389 PrintMessage("Error: Could not open file '%s' (%s)\n", Param[1], strerror(errno)); 390 return; 391 } 392 393 fprintf(File,"********** HV settings, %04d %02d %02d, %02d:%02d:%02d **********\n\n", 394 1900 + Time->tm_year, 1 + Time->tm_mon, 395 Time->tm_mday, Time->tm_hour, Time->tm_min, Time->tm_sec); 396 397 for (int i=0; i<NumHVBoards; i++) { 398 fprintf(File, "%s\n\n", fHVBoard[i]->BoardName); 399 400 for (int j=0; j<NUM_CHAINS; j++) { 401 for (int k=0; k<NUM_CHANNELS; k++) fprintf(File,"%5d ",fHVBoard[i]->HV[j][k]); 402 fprintf(File, "\n"); 875 403 } 876 877 } 878 else { 879 880 char buffer[MAX_COM_SIZE]; 881 882 time_t time_now_secs; 883 struct tm *time_now; 884 885 time(&time_now_secs); 886 time_now = localtime(&time_now_secs); 887 888 sprintf(buffer,"OK - hvsettings/HV_%04d-%02d-%02d_%02d-%02d-%02d.txt", 889 1900 + time_now->tm_year, 890 1 + time_now->tm_mon, 891 time_now->tm_mday, 892 time_now->tm_hour, 893 time_now->tm_min, 894 time_now->tm_sec); 895 896 //sprintf(str,"warning: HV settings will be written to \"%s\"\n",buffer); 897 //DoPrompt(str); 898 899 if (SaveHVSettings(buffer)) { 900 sprintf(str,"OK - HV settings successfully written to \"%s\"\n",buffer); 901 DoPrompt(str); 902 } 903 } 904 905 return 0; 906 404 fprintf(File, "\n"); 405 } 406 407 if (fclose(File) != 0) { 408 PrintMessage("Error: Could not close file '%s' (%s)\n", Param[1], strerror(errno)); 409 } 410 411 return; 907 412 } 908 413 909 414 910 415 // Start monitoring 911 else if (Match(status->Param[0], "start")) { 912 913 if (!NBoards()) 914 return 0; 915 916 if (status->state==active) { 917 sprintf(str,"OK - status monitoring is already active\n"); 918 DoPrompt(str); 919 return 0; 920 } 921 416 else if (Match(Param[0], "start")) { 417 418 if (!NumHVBoards) return; 419 922 420 StartMonitor(); 923 924 sprintf(str,"OK - status monitoring activated\n"); 925 DoPrompt(str); 926 927 return 0; 928 421 PrintMessage("OK - status monitoring activated\n"); 422 423 return; 929 424 } 930 425 931 426 932 427 // Print status 933 else if (Match(status->Param[0], "status") || Match(status->Param[0], "info")) { 934 935 if (!NBoards()) 936 return 0; 937 938 PrintStatus(status,config,stdout); 939 PrintStatus(status,config,log->logptr); 940 941 return 0; 428 else if (Match(Param[0], "status")) { 429 430 PrintMessage("\n Status monitor: %s\n", state_str[state]); 431 PrintMessage(" Verbose: %s\n", Verbose ? "on" : "off"); 432 PrintMessage(" Status refresh rate [Hz]: %.2f\n", fStatusRefreshRate); 433 PrintMessage(" Socket state: %s\n", Socket==-1 ? "disconnected":"connected"); 434 PrintMessage(" Total number of HV boards: %d\n", NumHVBoards); 435 PrintMessage(" Active HV boards: %d\n\n ", LastBoard - FirstBoard + 1); 436 437 for (int i=FirstBoard; i<=LastBoard; i++) { 438 PrintMessage(" BOARD %d (%s) Wrap counter: %s (%d) Manual reset: %s Time-out: %.2f s\n\n", 439 fHVBoard[i]->GetBoardNumber(), fHVBoard[i]->BoardName, 440 fHVBoard[i]->WrapOK ? "ok":"error", 441 fHVBoard[i]->LastWrapCount, 442 fHVBoard[i]->ResetButton ? "yes" : "no", 443 fHVBoard[i]->fTimeOut); 444 445 for (int j=FirstChain; j<=LastChain; j++) { 446 PrintMessage(" CHAIN %d Over-current: %s\n ", j, fHVBoard[i]->Overcurrent[j] ? "yes" : "no"); 447 for (int k=0;k<4;k++) { 448 for (int l=0;l<8;l++) { 449 if(NParam == 2) PrintMessage("%5d ",fHVBoard[i]->HV[j][k*8+l]); 450 else PrintMessage("%#5.2f ",fHVBoard[i]->HVV[j][k*8+l]); 451 } 452 PrintMessage("\n "); 453 } 454 PrintMessage("\n "); 455 } 456 } 457 458 return; 942 459 } 943 460 944 461 945 462 // Stop monitoring 946 else if (Match(status->Param[0], "stop")) { 947 948 if (!NBoards()) 949 return 0; 950 951 if (status->state!=active) { 952 sprintf(str,"OK - status monitoring is already deactivated\n"); 953 DoPrompt(str); 954 return 0; 955 } 956 957 StopMonitor(); 958 959 sprintf(str,"ERROR - warning: status monitoring deactivated\n"); 960 DoPrompt(str); 961 962 return 0; 963 964 } 965 966 /* 967 // Sweep HV 968 else if (Match(status->Param[0], "sweep")) { 969 970 if (!NBoards()) 971 return 0; 972 973 int errors = 0; 974 int channel = 0; 975 976 unsigned int hv1 = 0; 977 unsigned int hv2 = 0; 978 unsigned int dv = 10; 979 980 bool allchannels = FALSE; 981 982 float delay = 1.; 983 984 if (status->Param[1][0]>0 && status->Param[2][0]>0 && status->Param[3][0]>0 && status->Param[4][0]>0){ 985 986 if (status->Param[1][0] == 'a' ) 987 allchannels = TRUE; 988 else if (IsNoDigit(status->Param[1])) { 989 channel = atoi(status->Param[1]); 990 // Check limits 991 if (channel>31 || channel <0) { 992 DoPrompt("channel out of range (0...31)!\n"); 993 return 0; 994 } 463 else if (Match(Param[0], "stop")) { 464 465 if (!NumHVBoards) return; 466 467 StopMonitor(); 468 PrintMessage("Status monitor stopped\n"); 469 470 return; 471 } 472 473 474 // Set timeout to return from read 475 if (Match(Param[0], "timeout")) { 476 477 double Timeout; 478 479 if (!NumHVBoards) return; 480 481 if (NParam != 2) { 482 PrintMessage("Usage: timeout <secs>\n"); 483 return; 484 } 485 486 if (!ConvertToDouble(Param[1], &Timeout)) { 487 PrintMessage("Error: Wrong number format\n"); 488 return; 489 } 490 491 for (int i=0; i<NumHVBoards; i++) fHVBoard[i]->SetTimeOut(Timeout); 492 PrintMessage("Timeout set to %.2f s for all boards\n", Timeout); 493 494 return; 495 } 496 497 498 // Print uptime 499 if (Match(Param[0], "uptime")) { 500 time_t ActualT; 501 time (&ActualT); 502 503 PrintMessage("%d:%02d:%02d\n", (int) difftime(ActualT, StartTime)/3600, ((int) difftime(ActualT, StartTime)/60)%60, (int) difftime(ActualT, StartTime)%60); 504 505 return; 506 } 507 508 509 // Enable/disable verbosity 510 else if (Match(Param[0], "verbose")) { 511 512 if (Match(Param[1], "on")) { 513 Verbose = true; 514 PrintMessage("Verbosity enabled\n"); 515 } 516 else if (Match(Param[1], "off")) { 517 Verbose = false; 518 PrintMessage("Verbosity disabled\n"); 519 } 520 else PrintMessage("Usage: verbose <on>|<off>\n"); 521 522 return; 523 } 524 525 526 // Exit program 527 else if(Match(Param[0], "exit")) { 528 529 if (CmdFromSocket) { 530 PrintMessage("Exit command not allowed over socket.\n"); 531 return; 532 } 533 534 Exit = true; 535 pthread_kill(HVMonitor, SIGUSR1); 536 pthread_kill(SocketThread, SIGUSR1); 537 538 return; 539 } 540 541 PrintMessage("Unknown command '%s'\n", Param[0]); 542 543 return; 544 } 545 546 547 // Print message to selected target 548 void ProcessIO::PrintMessage(int Target, const char *Format, ...) { 549 va_list ArgumentPointer; 550 va_start(ArgumentPointer, Format); 551 PrintMessage(Target, Format, ArgumentPointer); 552 va_end(ArgumentPointer); 553 } 554 555 // Print message to log file, and screen or socket (depending on command origin) 556 void ProcessIO::PrintMessage(const char *Format, ...) { 557 va_list ArgumentPointer; 558 va_start(ArgumentPointer, Format); 559 if (CmdFromSocket) PrintMessage(MsgToSocket|MsgToLog, Format, ArgumentPointer); 560 else PrintMessage(MsgToConsole|MsgToLog, Format, ArgumentPointer); 561 va_end(ArgumentPointer); 562 } 563 564 // Function doing the actual printing work 565 void ProcessIO::PrintMessage(int Target, const char *Format, va_list ArgumentPointer) { 566 567 char Textbuffer[MAX_COM_SIZE]; 568 569 memset(Textbuffer, 0, sizeof(Textbuffer)); 570 vsnprintf(Textbuffer, sizeof(Textbuffer), Format, ArgumentPointer); 571 572 // Print to console 573 if(Target & MsgToConsole) { 574 if(strlen(Textbuffer)>0 && Textbuffer[strlen(Textbuffer)-1]=='\n') { 575 printf("\r%s%s", Textbuffer, Prompt); // New prompt 576 fflush(stdout); 577 } 578 else printf("%s", Textbuffer); 579 } 580 // Print to log file 581 if((Target & MsgToLog) && Logfile!=NULL) { 582 fprintf(Logfile, "%s", Textbuffer); 583 fflush(Logfile); 584 } 585 // Print to socket 586 if((Target & MsgToSocket) && Socket!=-1) { 587 write(Socket, Textbuffer, strlen(Textbuffer)); 588 } 589 } 590 591 592 // Ramp to new voltage with maximum step size given in config->fHVMaxDiff 593 // No ramping when decreasing voltage 594 bool ProcessIO::RampVoltage(unsigned int Target, int Board, int Chain, int Channel) { 595 596 int Diff; 597 598 while (fHVBoard[Board]->HV[Chain][Channel] != (int) Target) { 599 Diff = Target - fHVBoard[Board]->HV[Chain][Channel]; 600 if (Diff > (int) config->fHVMaxDiff) Diff = config->fHVMaxDiff; 601 602 if (fHVBoard[Board]->SetHV(stdout, Chain, Channel, fHVBoard[Board]->HV[Chain][Channel]+Diff, Verbose)==1) { 603 fHVBoard[Board]->HV[Chain][Channel] += Diff; 604 605 if (Verbose) { 606 PrintMessage("OK - board %d: high voltage of chain %d channel %d set to %d | 0X%.4X | %f V\n",fHVBoard[Board]->GetBoardNumber(),Chain, Channel, Target, Target, calib->DACToHV(Target,fHVBoard[Board]->GetBoardNumber(),Chain,Channel)); 607 PrintBoardStatus(Board); 995 608 } 996 997 if (IsNoDigit(status->Param[2]) && IsNoDigit(status->Param[3]) && IsNoDigit(status->Param[4])) { 998 999 hv1 = atoi(status->Param[2]); 1000 hv2 = atoi(status->Param[3]); 1001 dv = atoi(status->Param[4]); 1002 1003 if ((hv1>0X3FFF || hv1 <0) || (hv2>0X3FFF || hv2 <0)) { 1004 DoPrompt("high voltage out of range (Vmin: 0, Vmax: 16383)!\n"); 1005 return 0; 1006 } 1007 1008 if (hv1 > hv2) { 1009 DoPrompt("wrong limits (Vmin < Vmax)!\n"); 1010 return 0; 1011 } 1012 1013 if (dv < 1 || dv > abs(hv2-hv1)) { 1014 DoPrompt("step size out of range (dVmin: 1, dVmax: |hv2-hv1|)!\n"); 1015 return 0; 1016 } 1017 1018 if (status->Param[5][0]>0 && IsNoDigit(status->Param[5])) { 1019 if (atof(status->Param[5])<MIN_SWEEP_RATE || atof(status->Param[5])>MAX_SWEEP_RATE) { 1020 sprintf(str,"rate out of range (min: %.2f Hz, max: %.2f Hz)!\n",MIN_SWEEP_RATE,MAX_SWEEP_RATE); 1021 DoPrompt(str); 1022 return 0; 1023 } 1024 else 1025 delay = 1./atof(status->Param[5]); 1026 } 609 } 610 else { 611 PrintMessage("ERROR - Could not set HV of board %d, chain %d, channel %d. Skipping channel\n",fHVBoard[Board]->GetBoardNumber(),Chain,Channel); 612 return false; 613 } 614 } 615 return true; 616 } 617 618 void ProcessIO::StartMonitor() { 619 620 state = active; 621 pthread_kill(HVMonitor, SIGUSR1); 622 } 623 624 625 void ProcessIO::StopMonitor() { 626 627 state = stopped; 628 pthread_kill(HVMonitor, SIGUSR1); 629 } 630 631 632 void ProcessIO::Monitor() { 633 634 for (int i=0; i<NumHVBoards; i++) { 635 636 if (fHVBoard[i]->GetStatus(stdout,false)!=1) { 637 PrintMessage("Error: Monitor, could not read status of board %d\n", fHVBoard[i]->GetBoardNumber()); 638 } 639 640 if (fHVBoard[i]->ResetButton) { 641 PrintMessage("Manual reset of board %d\n",fHVBoard[i]->GetBoardNumber()); 642 ResetBoard(i); 643 } 644 645 if (!fHVBoard[i]->WrapOK) { 646 PrintMessage("Error: Wrap counter mismatch board %d\n",fHVBoard[i]->GetBoardNumber()); 647 } 648 649 for (int j=0; j<NUM_CHAINS; j++) { 650 if (fHVBoard[i]->Overcurrent[j]) { 651 PrintMessage("Warning: Overcurrent in chain %d of board %d\n",j,fHVBoard[i]->GetBoardNumber()); 652 ResetBoard(i); 1027 653 } 1028 else { 1029 DoPrompt("error: wrong input format - usage: sweep <channel>|<all> <v1> <v2> <dv> [rate]\n"); 1030 return 0; 1031 } 1032 1033 1034 StopMonitor(); 1035 1036 for (int i=status->FirstBoard;i<=status->LastBoard;i++) 1037 for (int j=status->FirstChain;j<=status->LastChain;j++) { 1038 if (!allchannels) { 1039 1040 for (unsigned int v = hv1; v<=hv2; v+=dv) { 1041 if ((hv->GetHVBoard(i))->SetHV(stdout,j,channel,v,rbuf,status->Verbose)==1) { 1042 sprintf(str,"board %d: high voltage of chain %d channel %d set to %d | 0X%.4X\n",i,j,channel,v,v); 1043 status->HV[i][j][channel]=v; 1044 DoPrompt(str); 1045 UpdateStatus(i,rbuf); 1046 sPrintStatus(status,str,i); 1047 DoPrompt(str); 1048 } 1049 else { 1050 sprintf(str,"board %d error: could not set hv - check timeout and try again\n",i); 1051 DoPrompt(str); 1052 errors++; 1053 } 1054 1055 usleep((unsigned long)floor(delay*1000000.)); 1056 } 1057 1058 } 1059 else { 1060 for (int k=0;k<MAX_NUM_CHANNELS;k++) { 1061 1062 for (unsigned int v = hv1; v<=hv2; v+=dv) { 1063 1064 if ((hv->GetHVBoard(i))->SetHV(stdout,j,k,v,rbuf,status->Verbose)==1) { 1065 sprintf(str,"board %d: high voltage of chain %d channel %d set to %d | 0X%.4X\n",i,j,k,v,v); 1066 status->HV[i][j][k]=v; 1067 DoPrompt(str); 1068 UpdateStatus(i,rbuf); 1069 sPrintStatus(status,str,i); 1070 DoPrompt(str); 1071 } 1072 else { 1073 sprintf(str,"board %d error: could not set hv - check timeout and try again\n",i); 1074 DoPrompt(str); 1075 errors++; 1076 } 1077 1078 usleep((unsigned long)floor(delay*1000000.)); 1079 1080 } 1081 } 1082 } 1083 } 1084 1085 StartMonitor(); 1086 1087 if (errors) { 1088 sprintf(str,"warning %d error(s) => check timeout and try again\n",errors); 1089 DoPrompt(str); 1090 } 1091 else { 1092 sprintf(str,"no error(s)... success!\n"); 1093 DoPrompt(str); 1094 } 654 } 655 } 656 } 657 658 659 void ProcessIO::ResetActiveBoards() { 660 661 for (int i=FirstBoard; i<=LastBoard; i++) ResetBoard(i); 662 } 663 664 665 void ProcessIO::ResetBoard(int i) { 666 667 if (fHVBoard[i]->Reset(stdout,Verbose) == 1) { 668 PrintMessage("Reset of board %d\n", fHVBoard[i]->GetBoardNumber()); 669 PrintBoardStatus(i); 670 } 671 else PrintMessage("Error: Could not reset board %d\n",fHVBoard[i]->GetBoardNumber()); 672 } 673 674 675 int ProcessIO::GetBoardIdx(int board) { 676 677 for (int i=0; i<MAX_NUM_HVBOARDS; i++) { 678 if (board == fHVBoard[i]->GetBoardNumber()) return i; 679 } 680 return -1; 681 } 682 683 684 void ProcessIO::PrintBoardStatus(int i) { 685 686 PrintMessage("Status board %d (%s): MR %s OC0 %s OC1 %s OC2 %s OC3 %s WC %s (%d)\n", 687 fHVBoard[i]->GetBoardNumber(), fHVBoard[i]->BoardName, 688 fHVBoard[i]->ResetButton ? "yes" : "no", 689 fHVBoard[i]->Overcurrent[0] ? "yes" : "no", 690 fHVBoard[i]->Overcurrent[1] ? "yes" : "no", 691 fHVBoard[i]->Overcurrent[2] ? "yes" : "no", 692 fHVBoard[i]->Overcurrent[3] ? "yes" : "no", 693 fHVBoard[i]->WrapOK ? "ok":"error", fHVBoard[i]->LastWrapCount); 694 } 695 696 697 // Parse command line for white space and double-quote separated tokens 698 int ProcessIO::ParseInput(char* Command, const char *Param[]) { 699 int Count=0; 700 701 while(Count<MAX_NUM_TOKEN) { 702 while (isspace(*Command)) Command++; // Ignore initial white spaces 703 if(*Command=='\0') break; 704 if (*Command == '\"') { 705 Param[Count] = ++Command; 706 while(*Command!='\"' && *Command!='\0') Command++; 1095 707 } 1096 708 else { 1097 DoPrompt("usage: sweep <channel>|<all> <v1> <v2> <dv> [rate]\n"); 1098 return 0; 1099 } 1100 1101 return 0; 1102 1103 } 1104 */ 1105 1106 // Print time and date 1107 else if (Match(status->Param[0], "date") || Match(status->Param[0], "time")) { 1108 1109 PrintDateAndTime(); 1110 1111 return 0; 1112 } 1113 1114 1115 /* 1116 // Test I/O - NEVER use this function with a real HV board!!! 1117 else if (Match(status->Param[0], "testio")) { 1118 1119 for (int i=status->FirstBoard;i<=status->LastBoard;i++) 1120 (hv->GetHVBoard(i))->TestIO(); 1121 1122 return 0; 1123 } 1124 */ 1125 1126 1127 // Set timeout to return from read 1128 if (Match(status->Param[0], "timeout")) { 1129 1130 if (!NBoards()) 1131 return 0; 1132 1133 if (status->Param[1][0]>0) { 1134 1135 if (!IsNoDigit(status->Param[1])) { 1136 DoPrompt("ERROR - wrong input format - usage: timeout <time>\n"); 1137 return 0; 1138 } 1139 // Check limits 1140 else if (atof(status->Param[1]) < MIN_TIMEOUT || atof(status->Param[1]) > MAX_TIMEOUT) { 1141 sprintf(str,"ERROR -timeout out of range (min: %.2f s, max: %.2f s)!\n",MIN_TIMEOUT,MAX_TIMEOUT); 1142 DoPrompt(str); 1143 return 0; 1144 } 1145 else { 1146 StopMonitor(); 1147 for (int i=0;i<hv->GetNumberOfBoards();i++) 1148 (hv->GetHVBoard(i))->SetTimeOut((float)atof(status->Param[1])); 1149 status->fTimeOut = atof(status->Param[1]); 1150 sprintf(str,"OK - timeout set to %.2f s\n",status->fTimeOut); 1151 1152 DoPrompt(str); 1153 1154 StartMonitor(); 1155 return 0; 1156 } 1157 } 1158 else { 1159 sprintf(str,"ERROR - usage: timeout <time>\n"); 1160 DoPrompt(str); 1161 } 1162 1163 return 0; 1164 } 1165 1166 1167 // Print uptime 1168 if (Match(status->Param[0], "uptime")) { 1169 1170 double difftime = GetDiffTime(&StartTime); 1171 1172 sprintf(str,"OK - %d:%02d:%02d\n",(int)difftime/SECONDS_HOUR,((int)difftime/SECONDS_MINUTE)%SECONDS_MINUTE,(int)difftime%SECONDS_MINUTE); 1173 DoPrompt(str); 1174 1175 return 0; 1176 } 1177 1178 1179 // Enable/disable verbosity 1180 else if (Match(status->Param[0], "verbose")) { 1181 1182 if (Match(status->Param[1], "on") && status->Param[1][0]) { 1183 if (status->Verbose == TRUE) { 1184 sprintf(str,"OK - verbosity is already enabled\n"); 1185 DoPrompt(str); 1186 } 1187 else { 1188 status->Verbose = TRUE; 1189 sprintf(str,"OK - verbosity enabled\n"); 1190 DoPrompt(str); 1191 } 1192 } 1193 1194 else if (Match(status->Param[1], "off") && status->Param[1][0]) { 1195 if (status->Verbose == FALSE) { 1196 sprintf(str,"OK - verbosity is already disabled\n"); 1197 DoPrompt(str); 1198 } 1199 else { 1200 status->Verbose = FALSE; 1201 sprintf(str,"OK - verbosity disabled\n"); 1202 DoPrompt(str); 1203 } 1204 } 1205 1206 else 1207 DoPrompt("ERROR - usage: verbose <on>|<off>\n"); 1208 1209 return 0; 1210 } 1211 1212 1213 // Write reference voltage 1214 if (Match(status->Param[0], "vref")) { 1215 1216 if (!NBoards()) 1217 return 0; 1218 1219 unsigned int voltage = 0; 1220 1221 if (status->Param[1][0]>0) { 1222 1223 // Binary input 1224 if (tolower(status->Param[1][0])=='x' && strlen(status->Param[1])>2) { 1225 if (sPrintHex2Dec(Chop(status->Param[1]+1),&voltage)!=0) { 1226 DoPrompt("ERROR - wrong input format - usage: vref <voltage>\n"); 1227 return 0; 1228 } 1229 } 1230 // Hexadecimal input 1231 else if (tolower(status->Param[1][0])=='b' && strlen(status->Param[1])>2) { 1232 if (sPrintBin2Dec(Chop(status->Param[1]+1),&voltage)!=0) { 1233 DoPrompt("ERROR - wrong input format - usage: vref <voltage>\n"); 1234 return 0; 1235 } 1236 } 1237 // Decimal input 1238 else if (IsNoDigit(status->Param[1])) 1239 voltage = atoi(status->Param[1]); 1240 // Wrong input format 1241 else { 1242 DoPrompt("ERROR - wrong input format - usage: vref <voltage>\n"); 1243 return 0; 1244 } 1245 1246 // Check limits 1247 if (voltage>0X3FFF || voltage <0) { 1248 DoPrompt("ERROR - reference voltage out of range (Vmin: 0, Vmax: 16383)!\n"); 1249 return 0; 1250 } 1251 1252 1253 StopMonitor(); 1254 1255 for (int i=status->FirstBoard;i<=status->LastBoard;i++) 1256 for (int j=status->FirstChain;j<=status->LastChain;j++) { 1257 if (((hv->GetHVBoard(i))->SetVRef(stdout,j,voltage,rbuf,status->Verbose)==1)) { 1258 sprintf(str,"OK - board %d: reference voltage of chain %d set to %d | 0X%.4X\n",hv->GetHVBoard(i)->GetBoardNumber(),j,voltage,voltage); 1259 status->VRef[i][j]=voltage; 1260 DoPrompt(str); 1261 UpdateStatus(i,rbuf); 1262 sPrintStatus(status,str,i); 1263 DoPrompt(str); 1264 } else { 1265 sprintf(str,"ERROR - board %d error: could not set vref - check timeout and try again\n",hv->GetHVBoard(i)->GetBoardNumber()); 1266 DoPrompt(str); 1267 } 1268 } 1269 1270 StartMonitor(); 1271 } 1272 else { 1273 sprintf(str,"ERROR - usage: vref <voltage>\n"); 1274 DoPrompt(str); 1275 } 1276 1277 return 0; 1278 } 1279 1280 /* 1281 // Write to device - NEVER use this function with a real HV board!!! 1282 if (Match(status->Param[0], "write")) { 1283 1284 if (!NBoards()) 1285 return 0; 1286 1287 if (status->Param[1][0]>0) { 1288 1289 // Binary input 1290 if (tolower(status->Param[1][0])=='x' && strlen(status->Param[1])>2) { 1291 if (sPrintHex2Dec(Chop(status->Param[1]+1),(unsigned int*)wbuf)!=0) { 1292 DoPrompt("wrong input format or value out of range!\n"); 1293 return 0; 1294 } 1295 } 1296 // Hexadecimal input 1297 else if (tolower(status->Param[1][0])=='b' && strlen(status->Param[1])>2) { 1298 if (sPrintBin2Dec(Chop(status->Param[1]+1),(unsigned int*)wbuf)!=0) { 1299 DoPrompt("wrong input format or value out of range!\n"); 1300 return 0; 1301 } 1302 } 1303 // Decimal input 1304 else if (atoi(status->Param[1])>=0 && atoi(status->Param[1])<=255 && IsNoDigit(status->Param[1])) 1305 wbuf[0] = (unsigned char)atoi(status->Param[1]); 1306 // Wrong input 1307 else { 1308 DoPrompt("wrong input format or value out of range!\n"); 1309 return 0; 1310 } 1311 1312 if (status->state==active) { 1313 StopMonitor(); 1314 sprintf(str,"warning: status monitoring deactivated\n"); 1315 DoPrompt(str); 1316 } 1317 1318 for (int i=status->FirstBoard;i<=status->LastBoard;i++) 1319 if ((hv->GetHVBoard(i))->Write(wbuf,1) == 1) { 1320 sPrintByteBin(wbuf[0],bdata); 1321 sprintf(str,"%d byte(s) written (board %d): %d | 0X%.2X | B%s\n",1,i,wbuf[0],wbuf[0],bdata); 1322 DoPrompt(str); 1323 } 1324 else { 1325 sprintf(str,"error: could not write to board %d\n",i); 1326 DoPrompt(str); 1327 } 1328 1329 } 1330 else { 1331 sprintf(str,"error: no input\n"); 1332 DoPrompt(str); 1333 } 1334 return 0; 1335 } 1336 */ 1337 1338 // Exit program 1339 else if(Match(status->Param[0], "exit") || Match(status->Param[0], "quit")) { 1340 1341 StopMonitor(); 1342 1343 ResetAllBoards(); 1344 1345 status->Exit = TRUE; 1346 1347 pthread_kill(status->HVMonitor, SIGUSR1); 1348 pthread_kill(status->SocketThread, SIGUSR1); 1349 1350 return 0; 1351 } 1352 1353 else if (strchr(status->Param[0],'\n')-status->Param[0]==0) { 1354 return 0; 1355 } 1356 1357 else { 1358 1359 if (strchr(status->Param[0],'\n') == 0) 1360 sprintf(str,"ERROR - unknown command: %s\n",status->Param[0]); 1361 else 1362 sprintf(str,"ERROR - unknown command: %s",status->Param[0]); 1363 1364 DoPrompt(str); 1365 1366 return 0; 1367 1368 } 1369 1370 return 0; 1371 } 1372 1373 1374 void ProcessIO::PrintDateAndTime() { 1375 1376 char str[MAX_COM_SIZE]; 1377 1378 time_t rawtime; 1379 struct tm * timeinfo; 1380 1381 time(&rawtime); 1382 timeinfo = localtime(&rawtime); // Get local time 1383 fflush(stdout); 1384 sprintf(str,"OK - current date/time is: %s",asctime(timeinfo)); 1385 DoPrompt(str); 1386 1387 } 1388 1389 void ProcessIO::DoPrompt(char* str) { 1390 if (str!=NULL) { 1391 if (status->Socket != -1) // Print status string to socket if open 1392 write(status->Socket,str,strlen(str)+1); 1393 } 1394 else { 1395 if (status->Socket != -1) // Print status string to socket if open 1396 write(status->Socket,"OK\n",3); 1397 } 1398 if (str!=NULL) { 1399 if (status->NumHVBoards == 0) { 1400 sprintf(status->Prompt,"HV> %s",str); 1401 printf(status->Prompt); 1402 if (status->Log) 1403 log->LogWrite(status->Prompt); 1404 sprintf(status->Prompt,"HV> "); 1405 } 1406 else if (status->FirstBoard == status->LastBoard) { 1407 1408 int board = hv->GetHVBoard(status->FirstBoard)->GetBoardNumber(); 1409 1410 if (status->FirstChain == status->LastChain) { 1411 sprintf(status->Prompt,"HV|C%d|B%d> %s",status->FirstChain,board,str); 1412 printf(status->Prompt); 1413 if (status->Log) 1414 log->LogWrite(status->Prompt); 1415 sprintf(status->Prompt,"HV|C%d|B%d> ",status->FirstChain,board); 1416 } 1417 else { 1418 sprintf(status->Prompt,"HV|C%d-%d|B%d> %s",status->FirstChain,status->LastChain,board,str); 1419 printf(status->Prompt); 1420 if (status->Log) 1421 log->LogWrite(status->Prompt); 1422 sprintf(status->Prompt,"HV|C%d-%d|B%d> ",status->FirstChain,status->LastChain,board); 1423 } 1424 1425 } 1426 else { 1427 1428 int firstboard = (hv->GetHVBoard(status->FirstBoard)->GetBoardNumber() > hv->GetHVBoard(status->LastBoard)->GetBoardNumber()) ? 1429 hv->GetHVBoard(status->LastBoard)->GetBoardNumber() : hv->GetHVBoard(status->FirstBoard)->GetBoardNumber(); 1430 1431 int lastboard = (hv->GetHVBoard(status->FirstBoard)->GetBoardNumber() > hv->GetHVBoard(status->LastBoard)->GetBoardNumber()) ? 1432 hv->GetHVBoard(status->FirstBoard)->GetBoardNumber() : hv->GetHVBoard(status->LastBoard)->GetBoardNumber(); 1433 1434 if (status->FirstChain == status->LastChain) { 1435 sprintf(status->Prompt,"HV|C%d|B%d-%d> %s",status->FirstChain,firstboard,lastboard,str); 1436 printf(status->Prompt); 1437 if (status->Log) 1438 log->LogWrite(status->Prompt); 1439 sprintf(status->Prompt,"HV|C%d|B%d-%d> ",status->FirstChain,firstboard,lastboard); 1440 } 1441 else { 1442 sprintf(status->Prompt,"HV|C%d-%d|B%d-%d> %s",status->FirstChain,status->LastChain,firstboard,lastboard,str); 1443 printf(status->Prompt); 1444 if (status->Log) 1445 log->LogWrite(status->Prompt); 1446 sprintf(status->Prompt,"HV|C%d-%d|B%d-%d> ",status->FirstChain,status->LastChain,firstboard,lastboard); 1447 } 1448 } 1449 } 1450 else { 1451 if (status->NumHVBoards == 0) 1452 sprintf(status->Prompt,"HV> "); 1453 else if (status->FirstBoard == status->LastBoard) { 1454 1455 int board = hv->GetHVBoard(status->FirstBoard)->GetBoardNumber(); 1456 1457 if (status->FirstChain == status->LastChain) 1458 sprintf(status->Prompt,"HV|C%d|B%d> ",status->FirstChain,board); 1459 else 1460 sprintf(status->Prompt,"HV|C%d-%d|B%d> ",status->FirstChain,status->LastChain,board); 1461 } 1462 else { 1463 1464 int firstboard = (hv->GetHVBoard(status->FirstBoard)->GetBoardNumber() > hv->GetHVBoard(status->LastBoard)->GetBoardNumber()) ? 1465 hv->GetHVBoard(status->LastBoard)->GetBoardNumber() : hv->GetHVBoard(status->FirstBoard)->GetBoardNumber(); 1466 1467 int lastboard = (hv->GetHVBoard(status->FirstBoard)->GetBoardNumber() > hv->GetHVBoard(status->LastBoard)->GetBoardNumber()) ? 1468 hv->GetHVBoard(status->FirstBoard)->GetBoardNumber() : hv->GetHVBoard(status->LastBoard)->GetBoardNumber(); 1469 1470 if (status->FirstChain == status->LastChain) 1471 sprintf(status->Prompt,"HV|C%d|B%d-%d> ",status->FirstChain,firstboard,lastboard); 1472 else 1473 sprintf(status->Prompt,"HV|C%d-%d|B%d-%d> ",status->FirstChain,status->LastChain,firstboard,lastboard); 1474 } 1475 } 1476 } 1477 1478 1479 void ProcessIO::PrintMessage(char *str) { 1480 1481 char outstr[MAX_COM_SIZE]; 1482 1483 fflush(stdout); 1484 if (str!=NULL) { 1485 1486 if (status->NumHVBoards == 0) 1487 sprintf(outstr,"%s\nHV> ",str); 1488 else if (status->FirstBoard == status->LastBoard) { 1489 1490 int board = hv->GetHVBoard(status->FirstBoard)->GetBoardNumber(); 1491 1492 if (status->FirstChain == status->LastChain) 1493 sprintf(outstr,"%s\nHV|C%d|B%d> ",str,status->FirstChain,board); 1494 else 1495 sprintf(outstr,"%s\nHV|C%d-%d|B%d> ",str,status->FirstChain,status->LastChain,board); 1496 } 1497 else { 1498 1499 int firstboard = (hv->GetHVBoard(status->FirstBoard)->GetBoardNumber() > hv->GetHVBoard(status->LastBoard)->GetBoardNumber()) ? 1500 hv->GetHVBoard(status->LastBoard)->GetBoardNumber() : hv->GetHVBoard(status->FirstBoard)->GetBoardNumber(); 1501 1502 int lastboard = (hv->GetHVBoard(status->FirstBoard)->GetBoardNumber() > hv->GetHVBoard(status->LastBoard)->GetBoardNumber()) ? 1503 hv->GetHVBoard(status->FirstBoard)->GetBoardNumber() : hv->GetHVBoard(status->LastBoard)->GetBoardNumber(); 1504 1505 if (status->FirstChain == status->LastChain) 1506 sprintf(outstr,"%s\nHV|C%d|B%d-%d> ",str,status->FirstChain,firstboard,lastboard); 1507 else 1508 sprintf(outstr,"%s\nHV|C%d-%d|B%d-%d> ",str,status->FirstChain,status->LastChain,firstboard,lastboard); 1509 } 1510 } 1511 else { 1512 1513 if (status->NumHVBoards == 0) 1514 sprintf(outstr,"HV> "); 1515 else if (status->FirstBoard == status->LastBoard) { 1516 1517 int board = hv->GetHVBoard(status->FirstBoard)->GetBoardNumber(); 1518 1519 if (status->FirstChain == status->LastChain) 1520 sprintf(outstr,"HV|C%d|B%d> ",status->FirstChain,board); 1521 else 1522 sprintf(outstr,"HV|C%d-%d|B%d> ",status->FirstChain,status->LastChain,board); 1523 } 1524 else { 1525 1526 int firstboard = (hv->GetHVBoard(status->FirstBoard)->GetBoardNumber() > hv->GetHVBoard(status->LastBoard)->GetBoardNumber()) ? 1527 hv->GetHVBoard(status->LastBoard)->GetBoardNumber() : hv->GetHVBoard(status->FirstBoard)->GetBoardNumber(); 1528 1529 int lastboard = (hv->GetHVBoard(status->FirstBoard)->GetBoardNumber() > hv->GetHVBoard(status->LastBoard)->GetBoardNumber()) ? 1530 hv->GetHVBoard(status->FirstBoard)->GetBoardNumber() : hv->GetHVBoard(status->LastBoard)->GetBoardNumber(); 1531 1532 if (status->FirstChain == status->LastChain) 1533 sprintf(outstr,"HV|C%d|B%d-%d> ",status->FirstChain,firstboard,lastboard); 1534 else 1535 sprintf(outstr,"HV|C%d-%d|B%d-%d> ",status->FirstChain,status->LastChain,firstboard,lastboard); 1536 } 1537 1538 1539 } 1540 1541 fflush(stdout); 1542 fputs(outstr, stdout); 1543 fflush(stdout); 1544 1545 } 1546 1547 1548 void ProcessIO::PrintMessageToLog(char *str) { 1549 1550 char outstr[MAX_COM_SIZE]; 1551 1552 if (status->NumHVBoards == 0) { 1553 sprintf(outstr,"HV|B> %s\n",str); 1554 log->LogWrite(outstr); 1555 } 1556 else if (status->FirstBoard == status->LastBoard) { 1557 1558 int board = hv->GetHVBoard(status->FirstBoard)->GetBoardNumber(); 1559 1560 sprintf(outstr,"HV|B%d> %s\n",board,str); 1561 log->LogWrite(outstr); 1562 } 1563 else { 1564 1565 int firstboard = (hv->GetHVBoard(status->FirstBoard)->GetBoardNumber() > hv->GetHVBoard(status->LastBoard)->GetBoardNumber()) ? 1566 hv->GetHVBoard(status->LastBoard)->GetBoardNumber() : hv->GetHVBoard(status->FirstBoard)->GetBoardNumber(); 1567 1568 int lastboard = (hv->GetHVBoard(status->FirstBoard)->GetBoardNumber() > hv->GetHVBoard(status->LastBoard)->GetBoardNumber()) ? 1569 hv->GetHVBoard(status->FirstBoard)->GetBoardNumber() : hv->GetHVBoard(status->LastBoard)->GetBoardNumber(); 1570 1571 sprintf(outstr,"HV|B%d-%d> %s\n",firstboard,lastboard,str); 1572 log->LogWrite(outstr); 1573 } 1574 1575 } 1576 1577 1578 // Print message to screen, log file and socket 1579 void ProcessIO::PrintMessageO(char *Format, ...) { 1580 1581 char Textbuffer[MAX_COM_SIZE]; 1582 1583 va_list ArgumentPointer; va_start(ArgumentPointer, Format); 1584 vsprintf(Textbuffer, Format, ArgumentPointer); 1585 1586 fputs(Textbuffer, stdout); fflush(stdout); // Print to console 1587 1588 if(status->Socket != -1) // Print to socket if open 1589 write(status->Socket,Textbuffer,strlen(Textbuffer)+1); // +1 to transmit '\0' 1590 } 1591 1592 1593 int ProcessIO::NBoards() { 1594 1595 if (status->NumHVBoards==0) 1596 DoPrompt("ERROR - no HV boards available!\n"); 1597 1598 return status->NumHVBoards; 1599 } 1600 1601 1602 int ProcessIO::InitializeHV() { 1603 1604 int nb = 0; 1605 1606 if (hv->GetNumberOfBoards()) 1607 printf("OK - Initialization:\n"); 1608 1609 for (int i=0;i<hv->GetNumberOfBoards();i++) { 1610 printf("OK - HV board %d (%s):\n",hv->GetHVBoard(i)->GetBoardNumber(),hv->GetHVBoard(i)->GetSerial()); 1611 nb+=hv->GetHVBoard(i)->Init(status->Verbose); 1612 } 1613 1614 return nb; 1615 } 1616 1617 1618 void ProcessIO::UpdateStatus(int i, unsigned char* rbuf) { 1619 1620 if (status->IsUpdated[i]) 1621 status->WC[0][i] = status->WC[1][i]; 1622 else { 1623 status->WC[0][i] = hv->GetHVBoard(i)->DecodeWrap(rbuf)-1; 1624 status->IsUpdated[i] = TRUE; 1625 } 1626 1627 status->WC[1][i] = hv->GetHVBoard(i)->DecodeWrap(rbuf); 1628 1629 int d = (int)abs(status->WC[0][i]-status->WC[1][i]); 1630 1631 status->isok[i] = (d==1 || d==7) ? 1 : 0; 1632 1633 hv->GetHVBoard(i)->DecodeOC(status->OC[i], rbuf); 1634 status->MR[i] = hv->GetHVBoard(i)->DecodeReset(rbuf); 1635 1636 } 1637 1638 1639 void ProcessIO::StartMonitor() { 1640 1641 status->state = active; 1642 status->Stop = FALSE; 1643 1644 pthread_kill(status->HVMonitor, SIGUSR1); 1645 1646 } 1647 1648 1649 void ProcessIO::StopMonitor() { 1650 1651 status->state = stopped; 1652 status->Stop = TRUE; 1653 1654 pthread_kill(status->HVMonitor, SIGUSR1); 1655 1656 } 1657 1658 1659 void ProcessIO::Monitor() { 1660 1661 char str[MAX_COM_SIZE]; 1662 1663 for (int i=0;i<hv->GetNumberOfBoards() ;i++) { 1664 1665 if ((hv->GetHVBoard(i))->GetStatus(stdout,rbuf,FALSE)!=1) { 1666 sprintf(str,"ERROR - board %d error: could not read status - check timeout and status refresh rate...",hv->GetHVBoard(i)->GetBoardNumber()); 1667 PrintMessage(str); 1668 } 1669 else 1670 UpdateStatus(i,rbuf); 1671 1672 if (status->MR[i]) { 1673 sprintf(str,"ERROR - warning: manual reset of board %d!",hv->GetHVBoard(i)->GetBoardNumber()); 1674 PrintMessage(str); 1675 StopMonitor(); 1676 ResetBoard(i); 1677 ReInitStatusOneBoard(status,i); 1678 StartMonitor(); 1679 } 1680 1681 if (!status->isok[i]) { 1682 sprintf(str,"ERROR - wrap counter mismatch board %d (%d,%d)!",hv->GetHVBoard(i)->GetBoardNumber(),status->WC[0][i],status->WC[1][i]); 1683 PrintMessage(str); 1684 } 1685 1686 for (int j=0;j<MAX_NUM_CHAINS;j++) 1687 if (status->OC[i][j]) { 1688 sprintf(str,"ERROR - warning: overcurrent in chain %d of board %d!",j,hv->GetHVBoard(i)->GetBoardNumber()); 1689 PrintMessage(str); 1690 ResetBoard(i); 1691 ReInitStatusOneBoard(status,i); 1692 } 1693 } 1694 } 1695 1696 1697 void ProcessIO::ResetActiveBoards() { 1698 1699 for (int i=status->FirstBoard;i<=status->LastBoard;i++) { 1700 if ((hv->GetHVBoard(i))->Reset(stdout,rbuf,status->Verbose)==1) { 1701 sprintf(str,"OK - software reset done board %d\n",hv->GetHVBoard(i)->GetBoardNumber()); 1702 DoPrompt(str); 1703 UpdateStatus(i,rbuf); 1704 sPrintStatus(status,str,i); 1705 DoPrompt(str); 1706 } 1707 else { 1708 sprintf(str,"ERROR - board %d error: could not reset - check timeout and try again\n",hv->GetHVBoard(i)->GetBoardNumber()); 1709 DoPrompt(str); 1710 } 1711 } 1712 1713 } 1714 1715 1716 void ProcessIO::ResetAllBoards() { 1717 1718 for (int i=0;i<hv->GetNumberOfBoards();i++) { 1719 if ((hv->GetHVBoard(i))->Reset(stdout,rbuf,status->Verbose)==1) { 1720 sprintf(str,"OK - software reset done board %d\n",hv->GetHVBoard(i)->GetBoardNumber()); 1721 DoPrompt(str); 1722 UpdateStatus(i,rbuf); 1723 sPrintStatus(status,str,i); 1724 DoPrompt(str); 1725 } 1726 else { 1727 sprintf(str,"ERROR - board %d error: could not reset - check timeout and try again\n",hv->GetHVBoard(i)->GetBoardNumber()); 1728 DoPrompt(str); 1729 } 1730 } 1731 1732 } 1733 1734 1735 void ProcessIO::ResetBoard(int i) { 1736 1737 if ((hv->GetHVBoard(i))->Reset(stdout,rbuf,status->Verbose)==1) { 1738 sprintf(str,"OK - software reset done board %d",hv->GetHVBoard(i)->GetBoardNumber()); 1739 PrintMessage(str); 1740 UpdateStatus(i,rbuf); 1741 sPrintStatus(status,str,i); 1742 PrintMessage(Chop(str)); 1743 } 1744 else { 1745 sprintf(str,"ERROR - board %d error: could not reset - check timeout and try again",hv->GetHVBoard(i)->GetBoardNumber()); 1746 PrintMessage(str); 1747 } 1748 1749 } 1750 1751 1752 int ProcessIO::SaveHVSettings(char* filename) { 1753 1754 char str[MAX_COM_SIZE]; 1755 1756 FILE *fptr; 1757 1758 time_t time_now_secs; 1759 struct tm *time_now; 1760 1761 time(&time_now_secs); 1762 time_now = localtime(&time_now_secs); 1763 1764 if ((fptr = fopen(filename,"w")) == NULL) { 1765 sprintf(str,"ERROR - could not open file \"%s\"\n", filename); 1766 return 0; 1767 } 1768 1769 fprintf(fptr,"\n********** HV settings written by hvutil %s, %04d %02d %02d, %02d:%02d:%02d **********\n\n", 1770 HV_CONTROL_VERSION, 1771 1900 + time_now->tm_year, 1772 1 + time_now->tm_mon, 1773 time_now->tm_mday, 1774 time_now->tm_hour, 1775 time_now->tm_min, 1776 time_now->tm_sec); 1777 1778 for (int i=0;i<status->NumHVBoards;i++) { 1779 fprintf(fptr,"Device: %s\n\n",status->fUSBDevice[i]); 1780 1781 for (int j=0;j<MAX_NUM_CHAINS;j++) { 1782 for (int k=0;k<4;k++) { 1783 for (int l=0;l<8;l++) 1784 fprintf(fptr,"%5d ",status->HV[i][j][k*8+l]); 1785 fprintf(fptr,"\n"); 1786 } 1787 fprintf(fptr,"\n"); 1788 } 1789 } 1790 1791 fclose(fptr); 1792 1793 return 1; 1794 } 1795 1796 1797 int ProcessIO::IsBoard(int board) { 1798 1799 for (int i=0;i<MAX_NUM_HVBOARDS;i++) 1800 if (board == status->USBDeviceNumber[i]) 1801 return 1; 1802 1803 return 0; 1804 } 1805 1806 1807 int ProcessIO::GetBoardIdx(int board) { 1808 1809 for (int i=0;i<MAX_NUM_HVBOARDS;i++) 1810 if (board == status->USBDeviceNumber[i]) 1811 return i; 1812 1813 return -1; 1814 } 709 Param[Count] = Command; 710 while(!isspace(*Command) && *Command!='\0') Command++; 711 } 712 if(*Command != '\0') *Command++ = '\0'; 713 Count++; 714 } 715 return Count; 716 } 717 718 // Check if two strings match (min 1 character must match) 719 bool Match(const char *str, const char *cmd) { 720 return strncasecmp(str,cmd,strlen(str)==0 ? 1:strlen(str)) ? false:true; 721 } 722 723 // Convert string to double 724 // Returns false if conversion did not stop on whitespace or EOL character 725 bool ConvertToDouble(const char *String, double *Result) { 726 727 char *EndPointer; 728 729 *Result = strtod(String, &EndPointer); 730 if(!isspace(*EndPointer) && *EndPointer!='\0') return false; 731 return true; 732 } 733 734 735 // Convert string to int 736 // Returns false if conversion did not stop on whitespace or EOL character 737 bool ConvertToInt(const char *String, int *Result) { 738 739 char *EndPointer; 740 741 *Result = (int) strtol(String, &EndPointer, 0); 742 if(!isspace(*EndPointer) && *EndPointer!='\0') return false; 743 return true; 744 } -
hvcontrol/src/ProcessIO.h
r35 r90 3 3 #define PROCESSIO_H_SEEN 4 4 5 #include <stdio.h>6 #include <stdlib.h>7 #include <string.h>8 5 #include <stdarg.h> 9 #include <limits.h>10 #include <time.h>11 6 #include <errno.h> 12 #include <unistd.h>13 7 #include <math.h> 14 #include <pthread.h>15 #include <termios.h>16 #include <fcntl.h>17 #include <assert.h>18 #include <dirent.h>19 #include <sys/time.h>20 #include <sys/types.h>21 #include <sys/socket.h>22 #include <sys/ioctl.h>23 #include <sys/select.h>24 8 #include <signal.h> 25 9 26 #include "Types.h"27 #include "HVStatus.h"28 #include "Log.h"29 10 #include "HVConfig.h" 30 11 #include "HVCalib.h" 31 #include "Utilities.h"32 12 #include "HV.h" 13 #include "../pixelmap/PixelMap.h" 33 14 34 #include <iostream> 35 #include "../../fact_repos.svn/pixelmap/PixelMap.h" 15 #define MAX_NUM_TOKEN 10 36 16 17 #define MsgToConsole 1 18 #define MsgToLog 2 19 #define MsgToSocket 4 20 21 typedef enum stateenum { active, stopped, na } state_enum; 37 22 38 23 class ProcessIO { 39 24 40 private:41 42 25 time_t StartTime; 43 44 char str[MAX_COM_SIZE]; 45 46 unsigned char wbuf[BUFFER_LENGTH]; 47 unsigned char rbuf[BUFFER_LENGTH]; 48 49 char bdata[16]; 50 26 FILE *Logfile; 51 27 PixelMap *pm; 52 28 53 29 public: 54 30 55 HVConfig* config; 56 HVCalib* calib; 57 Status* status; 58 Log* log; 31 HVConfig *config; 32 HVCalib *calib; 33 HVBoard* fHVBoard[MAX_NUM_HVBOARDS]; 59 34 60 35 pthread_mutex_t control_mutex; 61 pthread_cond_t control_cond;62 36 37 char Prompt[MAX_COM_SIZE]; 38 const char *Param[MAX_NUM_TOKEN]; // For parser 39 int NParam; 40 bool CmdFromSocket; 63 41 64 HV *hv; 65 HVBoard *hvboard; 42 // Status variables 43 pthread_t HVMonitor; // exit function sends signal to these threads 44 pthread_t SocketThread; 45 46 bool Verbose; 47 int Socket; // -1 if not connected 48 49 int NumHVBoards; 50 int FirstBoard; 51 int LastBoard; 52 int FirstChain; 53 int LastChain; 66 54 67 68 ProcessIO(char *config_file); 55 float fStatusRefreshRate; 56 state_enum state; 57 bool Exit; 58 59 // Methods 60 ProcessIO(char *); 69 61 ~ProcessIO(); 70 62 71 void Scan(); 72 void PrintHelp(); 73 void PrintDateAndTime(); 74 void DoPrompt(char* str); 75 void PrintMessage(char* str); 76 void PrintMessageToLog(char *str); 77 void PrintMessageO(char *Format, ...); 78 int CommandControl(); 79 int NBoards(); 80 int InitializeHV(); 81 void UpdateStatus(int i, unsigned char* rbuf); 63 void PrintMessage(int, const char *, ...); 64 void PrintMessage(const char *, ...); 65 void PrintMessage(int, const char *, va_list); 66 void CommandControl(char*); 67 bool RampVoltage(unsigned int, int, int, int); 82 68 void StartMonitor(); 83 69 void StopMonitor(); 84 70 void Monitor(); 85 71 void ResetActiveBoards(); 86 void ResetAllBoards(); 87 void ResetBoard(int i); 88 int SaveHVSettings(char* filename); 89 int IsBoard(int i); 90 int GetBoardIdx(int board); 72 void ResetBoard(int); 73 int GetBoardIdx(int); 91 74 75 void PrintBoardStatus(int); 76 77 int ParseInput(char*, const char *Param[]); 92 78 }; 93 79 80 bool Match(const char *, const char *); 81 bool ConvertToDouble(const char *, double *); 82 bool ConvertToInt(const char *, int *); 83 94 84 #endif
Note:
See TracChangeset
for help on using the changeset viewer.