- Timestamp:
- 06/07/10 08:01:05 (15 years ago)
- Location:
- hvcontrol
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
hvcontrol/History.txt
r161 r220 34 34 server 35 35 29/1/2010 DAC value 0 is now equivilant to calibrated voltage value 0 36 4/6/2010 Command 'hv' allows an array of pixel IDs/voltages (used by feedback) -
hvcontrol/src/HV.cc
r183 r220 17 17 HVBoard::HVBoard(int DeviceNumber, char *DeviceName, class ProcessIO *PIO) { 18 18 19 char Buffer[BUFFER_LENGTH];19 char *Buffer; 20 20 struct termios tio; 21 21 … … 27 27 28 28 // Create DIM services 29 snprintf(Buffer, sizeof(Buffer), SERVER_NAME"/NAME/ID%.2d", BoardNumber); 29 if (asprintf(&Buffer, SERVER_NAME"/NAME/ID%.2d", BoardNumber) == -1) { 30 m->PrintMessage(All, "asprintf() failed for DIM service name creation\n"); 31 return; 32 } 30 33 Name = new DimService (Buffer, BoardName); 31 32 snprintf(Buffer, sizeof(Buffer), SERVER_NAME"/VOLT/ID%.2d", BoardNumber); 34 free(Buffer); 35 36 if (asprintf(&Buffer, SERVER_NAME"/VOLT/ID%.2d", BoardNumber) == -1) { 37 m->PrintMessage(All, "asprintf() failed for DIM service name creation\n"); 38 return; 39 } 33 40 BiasVolt = new DimService (Buffer, "D", HVV, NUM_CHAINS*NUM_CHANNELS*sizeof(double)); 41 free(Buffer); 34 42 35 43 for (int i=0; i<NUM_CHAINS; i++) Overcurrent[i] = false; … … 42 50 43 51 // Open device (do not warn on non-existing device) 44 snprintf(Buffer, BUFFER_LENGTH, "/dev/%s",DeviceName); 52 if (asprintf(&Buffer, "/dev/%s",DeviceName) == -1) { 53 m->PrintMessage(All, "asprintf() failed for device name creation\n"); 54 return; 55 } 45 56 if ((fDescriptor = open(Buffer, O_RDWR|O_NOCTTY|O_NDELAY)) == -1) { 46 57 if(errno != 2) m->PrintMessage(All, "Error: Could not open device %d/%s (%s)\n", DeviceNumber,DeviceName, strerror(errno)); 58 free(Buffer); 47 59 return; 48 60 } 61 free(Buffer); 49 62 50 63 // Get current serial port settings -
hvcontrol/src/ProcessIO.cc
r210 r220 14 14 static char* state_str[] = {"active", "stopped", "n.a."}; 15 15 16 ProcessIO::ProcessIO(): 17 DimCommand((char *) SERVER_NAME"/Command", (char *) "C"), 18 EvidenceServer(SERVER_NAME) { 16 // Branch table for command evaluation 17 static const struct CL_Struct { const char *Name; 18 void (ProcessIO::*CommandPointer)(); 19 unsigned int MinNumParameter; 20 const char *Parameters; 21 const char *Help; 22 } CommandList[] = 23 {{"board", &ProcessIO::cmd_board, 1, "<i>|<i j>|<all>" ,"Address board i, boards i-j or all boards or list boards"}, 24 {"chain", &ProcessIO::cmd_chain, 1, "<i>|<i> <j>|<all>","Address chain i, chains i-j or all chains"}, 25 {"hv", &ProcessIO::cmd_hv, 2, "<id>|<ch>|<all> <v>", "Change bias of pixel, ch. or all ch. of active chain(s)/board(s)"}, 26 {"status", &ProcessIO::cmd_status, 0, "[dac]", "Show status information (DAC values if requested)"}, 27 {"config", &ProcessIO::cmd_config, 0, "", "Print configuration"}, 28 {"load", &ProcessIO::cmd_load, 1, "<file>", "Load and set bias settings from file"}, 29 {"save", &ProcessIO::cmd_save, 1, "<file>", "Save current bias settings to file"}, 30 {"exit", &ProcessIO::cmd_exit, 0, "", "Exit program"}, 31 {"rate", &ProcessIO::cmd_rate, 1, "<rate>", "Set status refresh rate in Hz"}, 32 {"timeout", &ProcessIO::cmd_timeout, 1, "<time>", "Set timeout to return from read in seconds"}, 33 {"reset", &ProcessIO::cmd_reset, 0, "", "Reset active bias board"}, 34 {"start", &ProcessIO::cmd_start, 0, "", "Start bias status monitor"}, 35 {"stop", &ProcessIO::cmd_stop, 0, "", "Stop bias status monitor"}, 36 {"uptime", &ProcessIO::cmd_uptime, 0, "", "Get program uptime"}, 37 {"help", &ProcessIO::cmd_help, 0, "", "Print help"}}; 38 39 40 using namespace std; 41 42 ProcessIO::ProcessIO(): EvidenceServer(SERVER_NAME) { 19 43 20 44 // Get program start time … … 30 54 FirstChain = 0; 31 55 LastChain = NUM_CHAINS-1; 32 33 UpdateDelay = 0.0;34 56 35 57 // Get configuration data … … 62 84 } 63 85 LastBoard = NumHVBoards-1; 64 86 65 87 // Create instances 66 88 calib = new HVCalib(this); 67 pm = new PixelMap(fPixMapTable); 89 pm = new PixelMap(fPixMapTable); 90 91 // Install DIM command (after all initialized) 92 Command = new DimCommand((char *) SERVER_NAME"/Command", (char *) "C", this); 68 93 } 69 94 … … 71 96 ProcessIO::~ProcessIO() { 72 97 98 delete Command; 99 73 100 for (int i=0; i<NumHVBoards; i++) delete fHVBoard[i]; 74 101 delete[] fHVBoard; … … 81 108 void ProcessIO::CommandControl(char *Command) { 82 109 83 if (strlen(Command)==0) return; // Ignore empty commands 84 85 if(Command[0]=='.') { // Shell command 110 // Ignore empty commands 111 if (strlen(Command)==0) return; 112 113 // Shell command 114 if(Command[0]=='.') { 86 115 system(&(Command[1])); 87 116 return; 88 117 } 89 118 90 for(int i=0; i<MAX_NUM_TOKEN; i++) Param[i] = ""; // All pointers point initially to empty string 91 NParam = ParseInput(Command, Param); 92 93 // Adress board 94 if (Match(Param[0], "board")) { 119 // Parse command into tokens 120 Parameter.clear(); 121 char *Start; 122 while(true) { 123 while (isspace(*Command)) Command++; // Ignore initial white spaces 124 if(*Command=='\0') break; 125 if (*Command == '\"') { 126 Start = ++Command; 127 while(*Command!='\"' && *Command!='\0') Command++; 128 } 129 else { 130 Start = Command; 131 while(!isspace(*Command) && *Command!='\0') Command++; 132 } 133 if(*Command != '\0') *Command++ = '\0'; 134 Parameter.push_back(Start); 135 } 136 137 // Search for command in command list 138 for(unsigned int CmdNumber=0; CmdNumber<sizeof(CommandList)/sizeof(CL_Struct); CmdNumber++) { 139 if (Match(Parameter[0], CommandList[CmdNumber].Name)) { 140 if(Parameter.size()-1 < CommandList[CmdNumber].MinNumParameter) { 141 PrintMessage("Usage: %s %s\n", CommandList[CmdNumber].Name, CommandList[CmdNumber].Parameters); 142 return; 143 } 144 145 // Jump to command function 146 (this->*CommandList[CmdNumber].CommandPointer)(); 147 return; 148 } 149 } 150 PrintMessage("Unknown command '%s'\n", Parameter[0].c_str()); 151 } 152 153 154 // Adress board 155 void ProcessIO::cmd_board() { 95 156 96 if (!NumHVBoards) return; 97 98 // Print list of boards 99 if (NParam == 1) { 100 for (int i=0; i<NumHVBoards; i++) { 101 PrintMessage("Board %d: %s\n", fHVBoard[i]->GetBoardNumber(), fHVBoard[i]->BoardName); 102 } 157 // Print list of boards 158 if (Parameter.size() == 1) { 159 for (int i=0; i<NumHVBoards; i++) { 160 PrintMessage("Board %d: %s\n", fHVBoard[i]->GetBoardNumber(), fHVBoard[i]->BoardName); 161 } 162 return; 163 } 164 165 //Select board(s) 166 if (Match(Parameter[1].c_str(), "all")) { 167 FirstBoard = 0; 168 LastBoard = NumHVBoards-1; 169 } 170 else if (Parameter.size()==2 && atoi(Parameter[1].c_str())>=0 && atoi(Parameter[1].c_str())<NumHVBoards) { 171 FirstBoard = atoi(Parameter[1].c_str()); 172 LastBoard = FirstBoard; 173 } 174 else if (Parameter.size()==3 && atoi(Parameter[1].c_str())>=0 && atoi(Parameter[1].c_str())<NumHVBoards && 175 atoi(Parameter[2].c_str())>0 && atoi(Parameter[2].c_str())<NumHVBoards) { 176 FirstBoard = atoi(Parameter[1].c_str()); 177 LastBoard = atoi(Parameter[2].c_str()); 178 } 179 else PrintMessage("Cannot address board(s), out of range.\n"); 180 } 181 182 // Adress chains 183 void ProcessIO::cmd_chain() { 184 185 if (!NumHVBoards) return; 186 187 if (Match(Parameter[1],"all")) { 188 FirstChain = 0; 189 LastChain = 3; 190 } 191 else if (Parameter.size()==2 && atoi(Parameter[1].c_str())>=0 && atoi(Parameter[1].c_str())<NUM_CHAINS) { 192 FirstChain = atoi(Parameter[1].c_str()); 193 LastChain = FirstChain; 194 } 195 else if (Parameter.size()==3 && atoi(Parameter[1].c_str())>=0 && atoi(Parameter[1].c_str())<NUM_CHAINS && 196 atoi(Parameter[2].c_str())>0 && atoi(Parameter[2].c_str())<NUM_CHAINS) { 197 FirstChain = atoi(Parameter[1].c_str()); 198 LastChain = atoi(Parameter[2].c_str()); 199 } 200 else PrintMessage("Cannot address chain(s), out of range.\n"); 201 } 202 203 // Print configuration 204 void ProcessIO::cmd_config() { 205 206 PrintMessage( " Pixel map table: %s\n" 207 " %d USB devices:\n", fPixMapTable, NumHVBoards); 208 209 for (int i=0; i<NumHVBoards; i++) PrintMessage(" Board %d: %s\n", i, fHVBoard[i]->BoardName); 210 211 PrintMessage( " TimeOut: %.2f s\n" 212 " StatusRefreshRate: %.2f Hz\n" 213 " DACMin value: %d\n" 214 " DACMax value: %d\n" 215 " HVCalibOffset : %f\n" 216 " HVCalibSlope : %f\n" 217 " HVMaxDiff : %u\n", 218 fTimeOut, fStatusRefreshRate, DACMin, 219 DACMax, fHVCalibOffset, fHVCalibSlope, fHVMaxDiff); 220 } 221 222 // Print help 223 void ProcessIO::cmd_help() { 224 225 char Buffer[MAX_COM_SIZE]; 226 for(unsigned int i=0; i<sizeof(CommandList)/sizeof(CL_Struct); i++) { 227 snprintf(Buffer, sizeof(Buffer), "%s %s", CommandList[i].Name, CommandList[i].Parameters); 228 PrintMessage("%-28s%s\n", Buffer, CommandList[i].Help); 229 } 230 231 PrintMessage(".<command> Execute shell command\n\n" 232 "Items in <> are mandatory, in [] optional, | indicates mutual exclusive or.\n"); 233 } 234 235 // Set new bias voltage 236 void ProcessIO::cmd_hv() { 237 238 int hvoltage, DACValue, Errors=0, Board=-1, Chain=-1, Channel=-1; 239 double hvoltageV; 240 bool SetDac; 241 242 // If array of channels, evaluate here (used by DIM) 243 if (Parameter.size()>3 && pm->Pixel_to_HVboard(Parameter[3]) != 999999999) { 244 for (unsigned int n=1; n<Parameter.size()-1; n+=2) { 245 if (pm->Pixel_to_HVboard(Parameter[n]) != 999999999) { 246 Board = pm->Pixel_to_HVboard(Parameter[n]); 247 Chain = pm->Pixel_to_HVchain(Parameter[n]); 248 Channel = pm->Pixel_to_HVchannel(Parameter[n]); 249 hvoltageV = atof(Parameter[n+1].c_str()); 250 if (isdigit(Parameter[n+1][0])==0) fHVBoard[Board]->HVV[Chain][Channel] += hvoltageV; 251 else fHVBoard[Board]->HVV[Chain][Channel] = hvoltageV; 252 DACValue = calib->HVToDAC(fHVBoard[Board]->HVV[Chain][Channel], Board, Chain, Channel); 253 254 } 255 } 256 return; 257 } 258 259 // Evaluate voltage parameter 260 if (Parameter.size()==4 && Match(Parameter[3], "dac")) { 261 SetDac = true; 262 if (!ConvertToInt(Parameter[2], &hvoltage)) { 263 PrintMessage("Error: Wrong number format for DAC voltage setting\n"); 103 264 return; 104 }105 106 //Select board(s)107 if (Match(Param[1],"all")) {108 FirstBoard = 0;109 LastBoard = NumHVBoards-1;110 265 } 111 else if (NParam==2 && atoi(Param[1])>=0 && atoi(Param[1])<NumHVBoards) { 112 FirstBoard = atoi(Param[1]); 113 LastBoard = FirstBoard; 114 } 115 else if (NParam==3 && atoi(Param[1])>=0 && atoi(Param[1])<NumHVBoards && 116 atoi(Param[2])>0 && atoi(Param[2])<NumHVBoards) { 117 FirstBoard = atoi(Param[1]); 118 LastBoard = atoi(Param[2]); 119 } 120 else PrintMessage("Cannot address board(s), out of range.\n"); 121 266 } 267 else { 268 SetDac = false; 269 if (!ConvertToDouble(Parameter[2], &hvoltageV)) { 270 PrintMessage("Error: Wrong number format for voltage setting\n"); 271 return; 272 } 273 } 274 275 // Evaluate pixel or channel parameter 276 if(pm->Pixel_to_HVboard(Parameter[1]) != 999999999) { 277 Board = pm->Pixel_to_HVboard(Parameter[1]); 278 Chain = pm->Pixel_to_HVchain(Parameter[1]); 279 Channel = pm->Pixel_to_HVchannel(Parameter[1]); 280 } 281 else if (!Match(Parameter[1], "all") && !ConvertToInt(Parameter[1], &Channel)) { 282 PrintMessage("Error: Wrong channel identification\n"); 122 283 return; 123 } 124 125 126 // Adress chains 127 else if (Match(Param[0], "chain")) { 284 } 285 286 for (int i=FirstBoard; i<=LastBoard; i++) { 287 if (i!=Board && Board!=-1) continue; 288 for (int j=FirstChain; j<=LastChain; j++) { 289 if (j!=Chain && Chain!=-1) continue; 290 for (int k=0; k<NUM_CHANNELS; k++) { 291 if (k!=Channel && Channel!=-1) continue; 292 293 // Voltage change ignored if DAC value is zero 294 if (isdigit(Parameter[2][0])==0 && fHVBoard[i]->HV[j][k] == 0) continue; 295 296 // Determine new DAC values 297 if (!SetDac){ 298 if (isdigit(Parameter[2][0])==0) fHVBoard[i]->HVV[j][k] += hvoltageV; // voltage change 299 else fHVBoard[i]->HVV[j][k] = hvoltageV; 300 DACValue = calib->HVToDAC(fHVBoard[i]->HVV[j][k], i, j, k); 301 } 302 else { 303 if (isdigit(Parameter[2][0])==0) DACValue = fHVBoard[i]->HV[j][k] + hvoltage; // voltage change 304 else DACValue = hvoltage; 305 } 306 307 // Set new voltage (if DAC value, update calibrated value) 308 if (!RampVoltage(DACValue, i, j, k)) Errors++; 309 if (SetDac) fHVBoard[i]->HVV[j][k] = calib->DACToHV(fHVBoard[i]->HV[j][k], i, j, k); 310 } // Channels 311 } // Chains 312 313 // Update DIM service 314 fHVBoard[i]->BiasVolt->updateService(); 315 } // Boards 316 317 if (Errors > 0) PrintMessage("Errors on %d channel(s) occurred\n", Errors); 318 } 319 320 // Load bias settings from file 321 void ProcessIO::cmd_load() { 322 323 char Buffer[MAX_COM_SIZE]; 324 int NBoards = 0, Errors = 0, Chain, Channel; 325 unsigned int DACValue; 326 FILE *File; 327 328 if ((File=fopen(Parameter[1].c_str(), "r")) == NULL) { 329 PrintMessage("Error: Could not open file '%s' (%s)\n", Parameter[1].c_str(), strerror(errno)); 330 return; 331 } 332 333 while (fgets(Buffer, sizeof(Buffer), File) != NULL) { 334 for (int Board=0; Board<NumHVBoards; Board++) { 335 if (Match(fHVBoard[Board]->BoardName, Buffer)) { 336 PrintMessage("Found bias settings for board %d (%s)\n\r",fHVBoard[Board]->GetBoardNumber(), fHVBoard[Board]->BoardName); 337 338 Chain = 0; Channel = 0; 339 while (fscanf(File, "%u", &DACValue)==1 && Chain<NUM_CHAINS) { 340 if (!RampVoltage(DACValue, Board, Chain, Channel)) { 341 Errors++; 342 PrintMessage("Error: Could not ramp chain %d, channel %d\n", Chain, Channel); 343 } 344 else { 345 PrintMessage("Ramped chain %d, channel %d to %u (%.2f V) \r", 346 Chain,Channel,DACValue,calib->DACToHV(DACValue,Board,Chain,Channel)); 347 } 348 fHVBoard[Board]->HVV[Chain][Channel] = calib->DACToHV(fHVBoard[Board]->HV[Chain][Channel], Board, Chain, Channel); 349 350 if(++Channel == NUM_CHANNELS) { 351 Chain++; 352 Channel = 0; 353 } 354 } 355 356 // Update DIM service 357 fHVBoard[Board]->BiasVolt->updateService(); 358 359 if (ferror(File) != 0) { 360 PrintMessage("Error reading DAC value from file, terminating. (%s)\n",strerror(errno)); 361 return; 362 } 363 else PrintMessage("\nFinished updating board\n"); 364 NBoards++; 365 } 366 } // Loop over boards 367 } // while() 368 369 if (NBoards != NumHVBoards) { 370 PrintMessage("Warning: Could not load bias settings for all connected HV boards\n"); 371 } 372 else if (Errors == 0) PrintMessage("Success: Read bias settings for all connected HV boards\n"); 373 if (Errors != 0) PrintMessage("Warning: Errors on %d channel(s) occurred\n", Errors); 374 375 if (fclose(File) != 0) PrintMessage("Error: Could not close file '%s'\n",Parameter[1].c_str()); 376 } 377 378 // Set status refresh rate 379 void ProcessIO::cmd_rate() { 380 381 double Rate; 382 383 if (!ConvertToDouble(Parameter[1], &Rate)) { 384 PrintMessage("Error: Wrong number format\n"); 385 return; 386 } 387 388 // Check limits 389 if (Rate<MIN_RATE || Rate>MAX_RATE) { 390 PrintMessage("Refresh rate out of range (min: %.2f Hz, max: %.2f Hz)\n", MIN_RATE, MAX_RATE); 391 return; 392 } 393 394 fStatusRefreshRate = Rate; 395 PrintMessage("Refresh rate set to %.2f Hz\n", fStatusRefreshRate); 396 } 397 398 // Reset 399 void ProcessIO::cmd_reset() { 400 401 for (int i=FirstBoard; i<=LastBoard; i++) ResetBoard(i); 402 } 403 404 // Save bias settings of all boards 405 void ProcessIO::cmd_save() { 406 407 FILE *File; 408 time_t time_now_secs; 409 struct tm *Time; 410 411 time(&time_now_secs); 412 Time = localtime(&time_now_secs); 413 414 if ((File = fopen(Parameter[1].c_str(), "w")) == NULL) { 415 PrintMessage("Error: Could not open file '%s' (%s)\n", Parameter[1].c_str(), strerror(errno)); 416 return; 417 } 418 419 fprintf(File,"********** Bias settings, %04d %02d %02d, %02d:%02d:%02d **********\n\n", 420 1900 + Time->tm_year, 1 + Time->tm_mon, 421 Time->tm_mday, Time->tm_hour, Time->tm_min, Time->tm_sec); 422 423 for (int i=0; i<NumHVBoards; i++) { 424 fprintf(File, "%s\n\n", fHVBoard[i]->BoardName); 425 426 for (int j=0; j<NUM_CHAINS; j++) { 427 for (int k=0; k<NUM_CHANNELS; k++) fprintf(File,"%5d ",fHVBoard[i]->HV[j][k]); 428 fprintf(File, "\n"); 429 } 430 fprintf(File, "\n"); 431 } 432 433 if (fclose(File) != 0) { 434 PrintMessage("Error: Could not close file '%s' (%s)\n", Parameter[1].c_str(), strerror(errno)); 435 } 436 } 437 438 // Start monitoring 439 void ProcessIO::cmd_start() { 440 441 state = active; 442 pthread_kill(HVMonitor, SIGUSR1); 443 PrintMessage(All, "Status monitoring activated\n"); 444 } 445 446 // Print status 447 void ProcessIO::cmd_status() { 448 449 PrintMessage("\n Status monitor: %s\n", state_str[state]); 450 PrintMessage(" Status refresh rate [Hz]: %.2f\n", fStatusRefreshRate); 451 PrintMessage(" Total number of boards: %d\n", NumHVBoards); 452 PrintMessage(" Active boards: %d\n\n", LastBoard - FirstBoard + 1); 453 454 for (int i=FirstBoard; i<=LastBoard; i++) { 455 PrintMessage(" BOARD %d (%s) Wrap counter: %s (%d) Manual reset: %s\n Time-out: %.2f s Error count: %d\n\n", 456 fHVBoard[i]->GetBoardNumber(), fHVBoard[i]->BoardName, 457 fHVBoard[i]->WrapOK ? "ok":"error", 458 fHVBoard[i]->LastWrapCount, 459 fHVBoard[i]->ResetButton ? "yes" : "no", 460 fHVBoard[i]->fTimeOut, 461 fHVBoard[i]->ErrorCount); 462 463 for (int j=FirstChain; j<=LastChain; j++) { 464 PrintMessage(" CHAIN %d Over-current: %s\n", j, fHVBoard[i]->Overcurrent[j] ? "yes" : "no"); 465 for (int k=0;k<4;k++) { 466 PrintMessage("\r"); 467 for (int l=0;l<8;l++) { 468 if(Parameter.size() == 2) PrintMessage("%5d ",fHVBoard[i]->HV[j][k*8+l]); 469 else PrintMessage("%#5.2f ",fHVBoard[i]->HVV[j][k*8+l]); 470 } 471 PrintMessage("\n"); 472 } 473 } 474 } 475 } 476 477 // Stop monitoring 478 void ProcessIO::cmd_stop() { 479 480 state = stopped; 481 pthread_kill(HVMonitor, SIGUSR1); 482 PrintMessage(All, "Status monitor stopped\n"); 483 } 484 485 // Set timeout to return from read 486 void ProcessIO::cmd_timeout() { 487 488 double Timeout; 489 490 if (!ConvertToDouble(Parameter[1], &Timeout)) { 491 PrintMessage("Error: Wrong number format\n"); 492 return; 493 } 494 495 for (int i=0; i<NumHVBoards; i++) fHVBoard[i]->SetTimeOut(Timeout); 496 if (NumHVBoards > 0) PrintMessage("Timeout set to %.2f s for all boards\n", Timeout); 497 } 128 498 129 if (!NumHVBoards) return; 130 131 if (Match(Param[1],"all")) { 132 FirstChain = 0; 133 LastChain = 3; 134 } 135 else if (NParam==2 && atoi(Param[1])>=0 && atoi(Param[1])<NUM_CHAINS) { 136 FirstChain = atoi(Param[1]); 137 LastChain = FirstChain; 138 } 139 else if (NParam==3 && atoi(Param[1])>=0 && atoi(Param[1])<NUM_CHAINS && 140 atoi(Param[2])>0 && atoi(Param[2])<NUM_CHAINS) { 141 FirstChain = atoi(Param[1]); 142 LastChain = atoi(Param[2]); 143 } 144 else PrintMessage("Cannot address chain(s), out of range.\n"); 145 146 return; 147 } 148 149 150 // Print HV utility configuration 151 else if (Match(Param[0], "config")) { 152 PrintMessage( " Pixel map table: %s\n" 153 " %d USB devices:\n", fPixMapTable, 154 NumHVBoards); 155 for (int i=0; i<NumHVBoards; i++) { 156 PrintMessage(" Board %d: %s\n", i, fHVBoard[i]->BoardName); 157 } 158 PrintMessage( " TimeOut: %.2f s\n" 159 " StatusRefreshRate: %.2f Hz\n" 160 " DACMin value: %d\n" 161 " DACMax value: %d\n" 162 " HVCalibOffset : %f\n" 163 " HVCalibSlope : %f\n" 164 " HVMaxDiff : %u\n", fTimeOut, 165 fStatusRefreshRate, DACMin, 166 DACMax, fHVCalibOffset, fHVCalibSlope, 167 fHVMaxDiff); 168 169 return; 170 } 171 172 173 // Print help 174 if (Match(Param[0], "help")) { 175 PrintMessage(" board <i>|<i> <j>|<all> Address board i, boards i-j or all boards or list boards\n" 176 " chain <i>|<i> <j>|<all> Address chain i, chains i-j or all chains\n" 177 " hv <PXL id>|<ch>|<all> <v> Set/change bias of pixel, ch. or all ch. of active chain(s)/board(s)\n" 178 " status [dac] Show status information (DAC values if requested)\n" 179 " config Print configuration\n" 180 " load <file> Load and set bias settings from <file>\n" 181 " save <file> Save current bias settings to [file]\n" 182 " exit Exit program\n" 183 " rate <rate> Set status refresh rate to <rate> [Hz]\n" 184 " timeout <time> Set timeout to return from read to <time> [s]\n" 185 " reset Reset active bias board\n" 186 " start Start bias status monitor\n" 187 " stop Stop bias status monitor - not recommended!\n" 188 " uptime Get program uptime [h:m:s]\n" 189 " help Print help\n" 190 " .<cmd> Execute shell command <cmd>"); 191 192 return; 193 } 194 195 196 // Set new bias voltage (if no boards available, simply returns OK) 197 // First reponse to socket should be 'OK' if no error occurred. 198 if (Match(Param[0], "hv")) { 199 200 int hvoltage, DACValue, Errors=0, Board=-1, Chain=-1, Channel=-1; 201 double hvoltageV; 202 bool SetDac; 203 204 // Need two or parameters 205 if (NParam<3 || NParam>4) { 206 PrintMessage("Usage: hv <channel>|<all> <voltage> [dac]\n"); 207 return; 208 } 209 210 // Evaluate voltage parameter 211 if (NParam==4 && Match(Param[3], "dac")) { 212 SetDac = true; 213 if (!ConvertToInt(Param[2], &hvoltage)) { 214 PrintMessage("Error: Wrong number format for DAC voltage setting\n"); 215 return; 216 } 217 } 218 else { 219 SetDac = false; 220 if (!ConvertToDouble(Param[2], &hvoltageV)) { 221 PrintMessage("Error: Wrong number format for voltage setting\n"); 222 return; 223 } 224 } 225 226 // Evaluate pixel or channel parameter 227 if(pm->Pixel_to_HVboard(Param[1]) != 999999999) { 228 Board = pm->Pixel_to_HVboard(Param[1]); 229 Chain = pm->Pixel_to_HVchain(Param[1]); 230 Channel = pm->Pixel_to_HVchannel(Param[1]); 231 } 232 else if (!Match(Param[1], "all") && !ConvertToInt(Param[1], &Channel)) { 233 PrintMessage("Error: Wrong channel identification\n"); 234 return; 235 } 236 237 for (int i=FirstBoard; i<=LastBoard; i++) { 238 if (i!=Board && Board!=-1) continue; 239 for (int j=FirstChain; j<=LastChain; j++) { 240 if (j!=Chain && Chain!=-1) continue; 241 for (int k=0; k<NUM_CHANNELS; k++) { 242 if (k!=Channel && Channel!=-1) continue; 243 244 // Voltage change ignored if DAC value is zero 245 if (isdigit(*Param[2])==0 && fHVBoard[i]->HV[j][k] == 0) continue; 246 247 // Determine new DAC values 248 if (!SetDac){ 249 if (isdigit(*Param[2])==0) fHVBoard[i]->HVV[j][k] += hvoltageV; // voltage change 250 else fHVBoard[i]->HVV[j][k] = hvoltageV; 251 DACValue = calib->HVToDAC(fHVBoard[i]->HVV[j][k], i, j, k); 252 } 253 else { 254 if (isdigit(*Param[2])==0) DACValue = fHVBoard[i]->HV[j][k] + hvoltage; // voltage change 255 else DACValue = hvoltage; 256 } 257 258 // Set new voltage (if DAC value, update calibrated value) 259 if (!RampVoltage(DACValue, i, j, k)) Errors++; 260 if (SetDac) fHVBoard[i]->HVV[j][k] = calib->DACToHV(fHVBoard[i]->HV[j][k], i, j, k); 261 262 // Update DIM services 263 //fHVBoard[i]->BiasVolt[j][k]->updateService(); 264 UpdateDelay = 1.0; 265 } // Channels 266 } // Chains 267 } // Boards 268 269 if (Errors > 0) PrintMessage("Errors on %d channel(s) occurred\n", Errors); 270 271 return; 272 } 273 274 275 // Load HV settings from file 276 else if (Match(Param[0], "load")) { 277 278 char Buffer[MAX_COM_SIZE]; 279 int NBoards = 0, Errors = 0, Chain, Channel; 280 unsigned int DACValue; 281 FILE *File; 282 283 if (NParam != 2) { 284 PrintMessage("Usage: load <file>\n"); 285 return; 286 } 287 288 if ((File=fopen(Param[1], "r")) == NULL) { 289 PrintMessage("Error: Could not open file '%s' (%s)\n", Param[1], strerror(errno)); 290 return; 291 } 292 293 while (fgets(Buffer, sizeof(Buffer), File) != NULL) { 294 for (int Board=0; Board<NumHVBoards; Board++) { 295 if (Match(fHVBoard[Board]->BoardName, Buffer)) { 296 PrintMessage("Found bias settings for board %d (%s)\n\r",fHVBoard[Board]->GetBoardNumber(), fHVBoard[Board]->BoardName); 297 298 Chain = 0; Channel = 0; 299 while (fscanf(File, "%u", &DACValue)==1 && Chain<NUM_CHAINS) { 300 if (!RampVoltage(DACValue, Board, Chain, Channel)) { 301 Errors++; 302 PrintMessage("Error: Could not ramp chain %d, channel %d\n", Chain, Channel); 303 } 304 else { 305 PrintMessage("Ramped chain %d, channel %d to %u (%.2f V) \r", 306 Chain,Channel,DACValue,calib->DACToHV(DACValue,Board,Chain,Channel)); 307 } 308 fHVBoard[Board]->HVV[Chain][Channel] = calib->DACToHV(fHVBoard[Board]->HV[Chain][Channel], Board, Chain, Channel); 309 310 // Update DIM services 311 //fHVBoard[Board]->BiasVolt[Chain][Channel]->updateService(); 312 UpdateDelay = 1.0; 313 if(++Channel == NUM_CHANNELS) { 314 Chain++; 315 Channel = 0; 316 } 317 } 318 if (ferror(File) != 0) { 319 PrintMessage("Error reading DAC value from file, terminating. (%s)\n",strerror(errno)); 320 return; 321 } 322 else PrintMessage("\nFinished updating board\n"); 323 NBoards++; 324 } 325 } // Loop over boards 326 } // while() 327 328 if (NBoards != NumHVBoards) { 329 PrintMessage("Warning: Could not load bias settings for all connected HV boards\n"); 330 } 331 else if (Errors == 0) PrintMessage("Success: Read bias settings for all connected HV boards\n"); 332 if (Errors != 0) PrintMessage("Warning: Errors on %d channel(s) occurred\n", Errors); 333 334 if (fclose(File) != 0) PrintMessage("Error: Could not close file '%s'\n",Param[1]); 335 336 return; 337 } 338 339 340 // Set status refresh rate 341 if (Match(Param[0], "rate")) { 342 343 double Rate; 344 345 if (NParam != 2) { 346 PrintMessage("Usage: rate <Hz>\n"); 347 return; 348 } 349 350 if (!ConvertToDouble(Param[1], &Rate)) { 351 PrintMessage("Error: Wrong number format\n"); 352 return; 353 } 354 355 // Check limits 356 if (Rate<MIN_RATE || Rate>MAX_RATE) { 357 PrintMessage("Refresh rate out of range (min: %.2f Hz, max: %.2f Hz)\n", MIN_RATE, MAX_RATE); 358 return; 359 } 360 361 fStatusRefreshRate = Rate; 362 PrintMessage("Refresh rate set to %.2f Hz\n", fStatusRefreshRate); 363 364 return; 365 } 366 367 // Reset 368 if (Match(Param[0], "reset")) { 369 370 if (!NumHVBoards) return; 371 for (int i=FirstBoard; i<=LastBoard; i++) ResetBoard(i); 372 return; 373 } 374 375 376 // Save HV settings of all boards 377 else if (Match(Param[0], "save")) { 378 379 FILE *File; 380 time_t time_now_secs; 381 struct tm *Time; 382 383 if (NParam != 2) { 384 PrintMessage("Usage: save <Filename>\n"); 385 return; 386 } 387 388 time(&time_now_secs); 389 Time = localtime(&time_now_secs); 390 391 if ((File = fopen(Param[1], "w")) == NULL) { 392 PrintMessage("Error: Could not open file '%s' (%s)\n", Param[1], strerror(errno)); 393 return; 394 } 395 396 fprintf(File,"********** Bias settings, %04d %02d %02d, %02d:%02d:%02d **********\n\n", 397 1900 + Time->tm_year, 1 + Time->tm_mon, 398 Time->tm_mday, Time->tm_hour, Time->tm_min, Time->tm_sec); 399 400 for (int i=0; i<NumHVBoards; i++) { 401 fprintf(File, "%s\n\n", fHVBoard[i]->BoardName); 402 403 for (int j=0; j<NUM_CHAINS; j++) { 404 for (int k=0; k<NUM_CHANNELS; k++) fprintf(File,"%5d ",fHVBoard[i]->HV[j][k]); 405 fprintf(File, "\n"); 406 } 407 fprintf(File, "\n"); 408 } 409 410 if (fclose(File) != 0) { 411 PrintMessage("Error: Could not close file '%s' (%s)\n", Param[1], strerror(errno)); 412 } 413 414 return; 415 } 416 417 418 // Start monitoring 419 else if (Match(Param[0], "start")) { 420 421 state = active; 422 pthread_kill(HVMonitor, SIGUSR1); 423 PrintMessage(All, "Status monitoring activated\n"); 424 return; 425 } 426 427 428 // Print status 429 else if (Match(Param[0], "status")) { 430 431 PrintMessage("\n Status monitor: %s\n", state_str[state]); 432 PrintMessage(" Status refresh rate [Hz]: %.2f\n", fStatusRefreshRate); 433 PrintMessage(" Total number of boards: %d\n", NumHVBoards); 434 PrintMessage(" Active boards: %d\n\n", LastBoard - FirstBoard + 1); 435 436 for (int i=FirstBoard; i<=LastBoard; i++) { 437 PrintMessage(" BOARD %d (%s) Wrap counter: %s (%d) Manual reset: %s\n Time-out: %.2f s Error count: %d\n\n", 438 fHVBoard[i]->GetBoardNumber(), fHVBoard[i]->BoardName, 439 fHVBoard[i]->WrapOK ? "ok":"error", 440 fHVBoard[i]->LastWrapCount, 441 fHVBoard[i]->ResetButton ? "yes" : "no", 442 fHVBoard[i]->fTimeOut, 443 fHVBoard[i]->ErrorCount); 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 PrintMessage("\r"); 449 for (int l=0;l<8;l++) { 450 if(NParam == 2) PrintMessage("%5d ",fHVBoard[i]->HV[j][k*8+l]); 451 else PrintMessage("%#5.2f ",fHVBoard[i]->HVV[j][k*8+l]); 452 } 453 PrintMessage("\n"); 454 } 455 } 456 } 457 458 return; 459 } 460 461 462 // Stop monitoring 463 else if (Match(Param[0], "stop")) { 464 465 state = stopped; 466 pthread_kill(HVMonitor, SIGUSR1); 467 PrintMessage(All, "Status monitor stopped\n"); 468 469 return; 470 } 471 472 473 // Set timeout to return from read 474 if (Match(Param[0], "timeout")) { 475 476 double Timeout; 477 478 if (!NumHVBoards) return; 479 480 if (NParam != 2) { 481 PrintMessage("Usage: timeout <secs>\n"); 482 return; 483 } 484 485 if (!ConvertToDouble(Param[1], &Timeout)) { 486 PrintMessage("Error: Wrong number format\n"); 487 return; 488 } 489 490 for (int i=0; i<NumHVBoards; i++) fHVBoard[i]->SetTimeOut(Timeout); 491 PrintMessage("Timeout set to %.2f s for all boards\n", Timeout); 492 493 return; 494 } 495 496 497 // Print uptime 498 if (Match(Param[0], "uptime")) { 499 time_t ActualT; 500 time (&ActualT); 501 502 PrintMessage("%d:%02d:%02d\n", (int) difftime(ActualT, StartTime)/3600, ((int) difftime(ActualT, StartTime)/60)%60, (int) difftime(ActualT, StartTime)%60); 503 504 return; 505 } 506 507 508 // Exit program 509 else if(Match(Param[0], "exit")) { 510 511 Exit = true; 512 pthread_kill(HVMonitor, SIGUSR1); 513 return; 514 } 515 516 PrintMessage("Unknown command '%s'\n", Param[0]); 517 518 return; 519 } 520 499 // Print uptime 500 void ProcessIO::cmd_uptime() { 501 502 time_t ActualT; 503 time (&ActualT); 504 PrintMessage("%d:%02d:%02d\n", (int) difftime(ActualT, StartTime)/3600, ((int) difftime(ActualT, StartTime)/60)%60, (int) difftime(ActualT, StartTime)%60); 505 } 506 507 // Exit program 508 void ProcessIO::cmd_exit() { 509 510 Exit = true; 511 pthread_kill(HVMonitor, SIGUSR1); 512 } 513 521 514 522 515 // Print message to selected target 523 516 void ProcessIO::PrintMessage(MsgTarget Target, const char *Format, ...) { 517 524 518 va_list ArgumentPointer; 525 519 va_start(ArgumentPointer, Format); … … 530 524 // Print message to log file, and screen or socket (depending on command origin) 531 525 void ProcessIO::PrintMessage(const char *Format, ...) { 526 532 527 va_list ArgumentPointer; 533 528 va_start(ArgumentPointer, Format); … … 567 562 } 568 563 } 569 570 564 571 565 // Ramp to new voltage with maximum step size given in fHVMaxDiff … … 626 620 } 627 621 } 628 629 if (UpdateDelay >= 0) {630 UpdateDelay -= 1.0/(NumHVBoards*fStatusRefreshRate);631 if (UpdateDelay <= 0) for (int i=0; i<NumHVBoards; i++) {632 fHVBoard[i]->BiasVolt->updateService();633 }634 }635 622 } 636 623 … … 661 648 662 649 663 // Parse command line for white space and double-quote separated tokens 664 int ProcessIO::ParseInput(char* Command, const char *Param[]) { 665 int Count=0; 666 667 while(Count<MAX_NUM_TOKEN) { 668 while (isspace(*Command)) Command++; // Ignore initial white spaces 669 if(*Command=='\0') break; 670 if (*Command == '\"') { 671 Param[Count] = ++Command; 672 while(*Command!='\"' && *Command!='\0') Command++; 673 } 674 else { 675 Param[Count] = Command; 676 while(!isspace(*Command) && *Command!='\0') Command++; 677 } 678 if(*Command != '\0') *Command++ = '\0'; 679 Count++; 680 } 681 return Count; 682 } 683 684 // 685 // Command handling (the only command is 'Bias/Command') 686 // 650 // Command handling (mutex needed because of monitor thread) 687 651 void ProcessIO::commandHandler() { 688 652 689 690 CommandControl(getString());691 653 pthread_mutex_lock(&control_mutex); 654 if (getCommand() == Command) CommandControl(getCommand()->getString()); 655 pthread_mutex_unlock(&control_mutex); 692 656 } 693 657 694 658 // Check if two strings match (min 1 character must match) 695 bool Match( const char *str, const char *cmd) {696 return strncasecmp(str ,cmd,strlen(str)==0 ? 1:strlen(str)) ? false:true;659 bool Match(string str, const char *cmd) { 660 return strncasecmp(str.c_str(),cmd,strlen(str.c_str())==0 ? 1:strlen(str.c_str())) ? false:true; 697 661 } 698 662 … … 700 664 // Convert string to double 701 665 // Returns false if conversion did not stop on whitespace or EOL character 702 bool ConvertToDouble( const char *String, double *Result) {666 bool ConvertToDouble(string String, double *Result) { 703 667 704 668 char *EndPointer; 705 669 706 *Result = strtod(String , &EndPointer);670 *Result = strtod(String.c_str(), &EndPointer); 707 671 if(!isspace(*EndPointer) && *EndPointer!='\0') return false; 708 672 return true; … … 712 676 // Convert string to int 713 677 // Returns false if conversion did not stop on whitespace or EOL character 714 bool ConvertToInt( const char *String, int *Result) {678 bool ConvertToInt(string String, int *Result) { 715 679 716 680 char *EndPointer; 717 681 718 *Result = (int) strtol(String , &EndPointer, 0);682 *Result = (int) strtol(String.c_str(), &EndPointer, 0); 719 683 if(!isspace(*EndPointer) && *EndPointer!='\0') return false; 720 684 return true; -
hvcontrol/src/ProcessIO.h
r210 r220 18 18 #define NUM_CHAINS 4 19 19 #define NUM_CHANNELS 32 20 #define BUFFER_LENGTH 25621 20 22 21 #define MIN_TIMEOUT 0.01 … … 26 25 #define MAX_RATE 50.0 27 26 28 #define MAX_NUM_TOKEN 1029 30 27 enum MsgTarget {Console=1, Log=2, All=7}; 31 28 typedef enum stateenum {active, stopped, na} state_enum; 32 29 33 class ProcessIO: public DimCommand, publicEvidenceServer {30 class ProcessIO: public EvidenceServer { 34 31 35 36 37 float UpdateDelay;32 time_t StartTime; 33 PixelMap *pm; 34 DimCommand *Command; 38 35 39 36 void commandHandler(); 40 37 41 38 public: 39 HVCalib *calib; 40 HVBoard **fHVBoard; 42 41 43 HVCalib *calib; 44 HVBoard **fHVBoard; 42 pthread_mutex_t control_mutex; 43 44 char Prompt[MAX_COM_SIZE]; 45 std::vector<std::string> Parameter; 46 47 // Configuration data 48 char *fPixMapTable; 49 float fTimeOut; 50 float fStatusRefreshRate; 51 int DACMin; 52 int DACMax; 53 float fHVCalibOffset; 54 float fHVCalibSlope; 55 unsigned int fHVMaxDiff; 56 57 // Status variables 58 pthread_t HVMonitor; // exit function sends signal to these threads 59 60 int NumHVBoards; 61 int FirstBoard; 62 int LastBoard; 63 int FirstChain; 64 int LastChain; 45 65 46 pthread_mutex_t control_mutex; 66 state_enum state; 67 bool Exit; 47 68 48 char Prompt[MAX_COM_SIZE]; 49 const char *Param[MAX_NUM_TOKEN]; // For parser 50 int NParam;69 // Methods 70 ProcessIO(); 71 ~ProcessIO(); 51 72 52 // Configuration data 53 char *fPixMapTable; 54 float fTimeOut; 55 float fStatusRefreshRate; 56 int DACMin; 57 int DACMax; 58 float fHVCalibOffset; 59 float fHVCalibSlope; 60 unsigned int fHVMaxDiff; 61 62 // Status variables 63 pthread_t HVMonitor; // exit function sends signal to these threads 64 65 int NumHVBoards; 66 int FirstBoard; 67 int LastBoard; 68 int FirstChain; 69 int LastChain; 70 71 state_enum state; 72 bool Exit; 73 74 // Methods 75 ProcessIO(); 76 ~ProcessIO(); 77 78 void PrintMessage(MsgTarget, const char *, ...); 79 void PrintMessage(const char *, ...); 80 void DoPrintMessage(const char *, va_list, MsgTarget); 81 void CommandControl(char*); 82 bool RampVoltage(unsigned int, int, int, int); 83 void Monitor(); 84 void ResetBoard(int); 85 void PrintBoardStatus(int); 86 int ParseInput(char*, const char *Param[]); 73 void PrintMessage(MsgTarget, const char *, ...); 74 void PrintMessage(const char *, ...); 75 void DoPrintMessage(const char *, va_list, MsgTarget); 76 void CommandControl(char*); 77 bool RampVoltage(unsigned int, int, int, int); 78 void Monitor(); 79 void ResetBoard(int); 80 void PrintBoardStatus(int); 81 82 void cmd_board(); void cmd_hv(); 83 void cmd_status(); void cmd_config(); 84 void cmd_load(); void cmd_save(); 85 void cmd_exit(); void cmd_rate(); 86 void cmd_timeout(); void cmd_reset(); 87 void cmd_start(); void cmd_stop(); 88 void cmd_uptime(); void cmd_help(); 89 void cmd_chain(); 87 90 }; 88 91 89 bool Match( const char *, const char *);90 bool ConvertToDouble( const char *, double *);91 bool ConvertToInt( const char *, int *);92 bool Match(std::string, const char *); 93 bool ConvertToDouble(std::string, double *); 94 bool ConvertToInt(std::string, int *); 92 95 93 96 #endif
Note:
See TracChangeset
for help on using the changeset viewer.