Changeset 10153
- Timestamp:
- 02/11/11 10:03:46 (14 years ago)
- Location:
- fact/BIASctrl
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
fact/BIASctrl/BIASctrl.cc
r10070 r10153 1 1 /**************************************************************\ 2 2 3 Control program for the fACT G-APD bias supply3 Control program for the FACT G-APD bias supply 4 4 5 Adapted from previous version 'hvcontrol'. 6 7 Oliver Grimm, August 2010 5 Oliver Grimm 8 6 9 7 \**************************************************************/ … … 16 14 #include <readline/history.h> 17 15 18 #define LOCKFILE "/tmp/CTX_HV_LOCK"19 16 const char READLINE_HIST_FILE[] = "/tmp/.history.BIASctrl"; 20 17 21 //22 // Remove lock file before running default signal code23 //24 void CrashHandler(int Signal) {25 26 remove(LOCKFILE);27 printf("Caught signal number %d. Removing lockfile and performing standard signal action. Good luck.\n",Signal);28 signal(Signal, SIG_DFL);29 raise(Signal);30 }31 32 //33 // Dummy handler to return from blocking syscalls34 //35 void DummyHandler(int) {};36 37 //38 // This function will be implicitly called by exit()39 //40 void ExitFunction() {41 42 if (remove(LOCKFILE) == -1) {43 printf("Could not remove lock file %s (%s)\n", LOCKFILE, strerror(errno));44 }45 }46 47 //48 18 // Main program 49 //50 19 int main() { 51 20 52 char str[MAX_COM_SIZE], *Command; 53 int Lock; 21 char *Command; 54 22 std::string LastHist; 55 23 56 // Assure only one instance runs 57 // O_EXCL with O_CREAT assure that the lock file cannot be 58 // opened by another instance, i.e. there are no parallel write accesses 59 if((Lock = open(LOCKFILE,O_WRONLY|O_CREAT|O_EXCL,S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH)) == -1) { 60 if(errno==EEXIST) { 61 printf("Error: Lock file already existing\n"); 62 sprintf(str, "paste %s -s -d ' '", LOCKFILE); 63 system(str); 64 } 65 else printf("Could not create lock file %s (%s)\n", LOCKFILE, strerror(errno)); 66 exit(EXIT_FAILURE); 67 } 68 close(Lock); 69 sprintf(str,"echo Created >%s; date >>%s; echo by $USER@$HOSTNAME>>%s", LOCKFILE, LOCKFILE, LOCKFILE); 70 system(str); 71 24 // Uses getc() for readline library (allows interruption by signal) and load history buffer 25 rl_getc_function = getc; 26 read_history(READLINE_HIST_FILE); 27 28 // Set signal SIGTERM to interrupt blocking system calls 29 siginterrupt(SIGTERM, true); 30 72 31 system("clear"); 73 printf("\n*** Bias control (compiled %s, %s) ***\n\n", __DATE__, __TIME__); 74 75 // Install signal handler and set signal SIGUSR1 to interrupt blocking system calls 76 signal(SIGUSR1, &DummyHandler); 77 siginterrupt (SIGUSR1, true); 78 79 // Assure lock file is deleted in case of a program crash or call to exit() 80 signal(SIGILL, &CrashHandler); 81 signal(SIGABRT, &CrashHandler); 82 signal(SIGFPE, &CrashHandler); 83 signal(SIGSEGV, &CrashHandler); 84 signal(SIGBUS, &CrashHandler); 85 atexit(&ExitFunction); 86 32 printf("\n*** BIASctrl (compiled %s, %s) ***\n\n", __DATE__, __TIME__); 33 87 34 // Construct main instance 88 35 static User M; 89 36 90 // These signals were set during construction of EvidenceServer91 signal(SIGQUIT, &CrashHandler); // CTRL-Backspace92 signal(SIGINT, &CrashHandler); // CTRL-C93 signal(SIGHUP, &CrashHandler); // Terminal closed94 signal(SIGTERM, &CrashHandler);95 96 // Load history buffer97 read_history(READLINE_HIST_FILE);98 99 37 // Handle command-line input 100 38 while (!M.ExitRequest) { -
fact/BIASctrl/Crate.cc
r10118 r10153 134 134 FD_ZERO(&SelectDescriptor); FD_SET(fDescriptor, &SelectDescriptor); 135 135 if (select(fDescriptor+1, &SelectDescriptor, NULL, NULL, &WaitTime)==-1) { 136 if (errno = EINTR) goto ExitCommunicate; // in case program is exiting 136 137 m->Message(m->FATAL, "Error with select() (%s)", strerror(errno)); 137 138 } -
fact/BIASctrl/History.txt
r10107 r10153 7 7 6/1/2011 RampVoltages() had infinite loop if crate communication stopped 8 8 19/1/2011 'hv' command crashed when no bias board was present 9 28/1/2011 Replaced 'hv' by 'channel' and 'pixel' commands (with new pixel 10 names, the name is a number itself) 11 11/2/2011 Removed Lockfile (DIM will prevent starting two instances) 12 Added 'crate' command. Changed signaling of program exit. -
fact/BIASctrl/User.cc
r10119 r10153 15 15 const char *Help; 16 16 } CommandList[] = 17 {{"synch", &User::cmd_synch, 0, "", "Synchronize board"}, 18 {"pixel", &User::cmd_hv, 2, "<pixel id> <v>", "Change bias of pixel"}, 19 {"channel", &User::cmd_hv, 2, "<channel|all> <v>", "Change bias of (all) channels of active boards"}, 20 {"gs", &User::cmd_gs, 1, "[crate] <volt>", "Global voltage set"}, 17 {{"pixel", &User::cmd_hv, 2, "<pixel id> <v>", "Change bias of pixel"}, 18 {"channel", &User::cmd_hv, 2, "<channel range> <v>", "Change bias of (all) channels of active crate"}, 19 {"gs", &User::cmd_gs, 1, "[crate] <volt>", "Global voltage set active crate"}, 20 {"reset", &User::cmd_reset, 0, "", "Reset active crate"}, 21 {"synch", &User::cmd_synch, 0, "", "Synchronize active crate"}, {"crate", &User::cmd_crate, 1, "<number>", "Select active crate"}, 21 22 {"status", &User::cmd_status, 0, "[dac|current]", "Show status information (DAC values if requested)"}, 22 {"mode", &User::cmd_mode, 1, "<static|dynamic>", "Set voltage stabilization mode "},23 {"mode", &User::cmd_mode, 1, "<static|dynamic>", "Set voltage stabilization mode (experimental)"}, 23 24 {"load", &User::cmd_load, 1, "<file>", "Load and set bias settings from file"}, 24 25 {"save", &User::cmd_save, 1, "<file>", "Save current bias settings to file"}, 25 26 {"rate", &User::cmd_rate, 1, "<rate>", "Set refresh rate in Hz"}, 26 27 {"timeout", &User::cmd_timeout, 1, "<time>", "Set timeout to return from read in seconds"}, 27 {"reset", &User::cmd_reset, 1, "<crates>", "Reset crates"},28 28 {"help", &User::cmd_help, 0, "", "Print help"}, 29 29 {"exit", &User::cmd_exit, 0, "", "Exit program"}}; … … 34 34 // 35 35 User::User(): EvidenceServer(SERVER_NAME) { 36 37 MainThread = pthread_self(); 36 38 37 39 // DIM console service used in PrintMessage() … … 63 65 } 64 66 67 // Set active crate 68 if (!Boards.empty()) ActiveCrate = 0; 69 else ActiveCrate = -1; 70 65 71 // Create PixelMap instance (map from config server) 66 72 DimRpcInfo RPC((char *) "ConfigRequest", (char *) ""); … … 77 83 } 78 84 79 80 85 // 81 86 // Destructor … … 84 89 85 90 // Wait for thread to quit 86 if (pthread_join(Thread, NULL) != 0) { 87 PrintMessage("pthread_join() failed"); 88 } 91 if (pthread_cancel(Thread) != 0) Message(ERROR, "pthread_cancel() failed in ()"); 92 if (pthread_join(Thread, NULL) != 0) Message(ERROR, "pthread_join() failed in ()"); 89 93 90 94 // Delete all crates … … 144 148 145 149 PrintMessage(".<command> Execute shell command\n\n" 146 "Items in <> are mandatory, in [] optional, | indicates mutual exclusive or.\n"); 150 "Items in <> are mandatory, in [] optional, | indicates mutual exclusive or.\n" 151 "Channel ranges can be 'all', a single number or in the form 'a-b'.\n"); 147 152 } 148 153 … … 152 157 void User::cmd_synch() { 153 158 154 for (unsigned int i=0; i<Crates.size(); i++) { 155 if (Crates[i]->Synch()) PrintMessage("Synchronized crate %d\n", i); 156 else PrintMessage("Failed to synchronize crate %d\n", i); 157 } 159 if (ActiveCrate == -1) return; 160 161 if (Crates[ActiveCrate]->Synch()) PrintMessage("Synchronized crate %d\n", ActiveCrate); 162 else PrintMessage("Failed to synchronize crate %d\n", ActiveCrate); 163 } 164 165 // 166 // Select active crate 167 // 168 void User::cmd_crate() { 169 170 int Crate; 171 172 if (!ConvertToInt(Parameter[1], &Crate)) { 173 PrintMessage("Error: Wrong number format\n"); 174 return; 175 } 176 177 // Check limits 178 if (Crate<0 || Crate>=(int) Crates.size()) { 179 PrintMessage("Crate number %d not existing\n", Crate); 180 return; 181 } 182 183 ActiveCrate = Crate; 158 184 } 159 185 … … 183 209 // Channel identification 184 210 else { 185 vector<string> T = Tokenize(Parameter[n], "/");186 Crt.Min = 0;187 Crt.Max = Crates.size()-1; 211 if (ActiveCrate == -1) continue; 212 else Crt.Min = Crt.Max = ActiveCrate; 213 188 214 Chan.Min = 0; 189 Chan.Max = MAX_NUM_BOARDS*NUM_CHANNELS-1; 190 191 if (T.size() == 2) { 192 if(!ConvertToRange(T[0], Crt) || !ConvertToRange(T[1], Chan)) { 193 PrintMessage("Numeric conversion or out-of-range error for parameter %d, skipping channel\n", n); 194 continue; 195 } 196 } 197 else { 198 Crt.Min = Crt.Max = 0; 199 if (!ConvertToRange(T[0], Chan)) { 200 PrintMessage("Numeric conversion or out-of-range error for parameter %d, skipping channel\n", n); 201 continue; 202 } 215 Chan.Max = MAX_NUM_BOARDS*NUM_CHANNELS-1; 216 217 if (!ConvertToRange(Parameter[n], Chan)) { 218 PrintMessage("Numeric conversion or out-of-range error for parameter %d, skipping channel\n", n); 219 continue; 203 220 } 204 221 } … … 246 263 char Buffer[MAX_COM_SIZE]; 247 264 int Errors = 0, Channel; 248 unsigned int NBoards = 0;249 265 double Value; 250 266 FILE *File; … … 261 277 for (unsigned int Crate=0; Crate<Crates.size(); Crate++) if (Match(Crates[Crate]->Name, Buffer)) { 262 278 263 PrintMessage("Found bias settings for board %s (#%d)\n\r", Crates[Crate]->Name, Crate); 279 if ((int) Crate != ActiveCrate) continue; 280 PrintMessage("Found bias settings for crate %s (#%d)\n\r", Crates[Crate]->Name, Crate); 264 281 265 282 Voltages.clear(); … … 280 297 } 281 298 else PrintMessage("\nFinished updating board\n"); 282 NBoards++;283 299 } // Loop over boards 284 300 } // while() 285 301 286 if (NBoards != Crates.size()) PrintMessage("Warning: Could not load bias settings for all connected crates\n");287 else if (Errors == 0) PrintMessage("Success: Read bias settings for all connected crates\n");288 289 302 if (Errors != 0) PrintMessage("Warning: %d error(s) occurred\n", Errors); 290 291 303 if (fclose(File) != 0) PrintMessage("Error: Could not close file '%s'\n", Parameter[1].c_str()); 292 304 } … … 319 331 void User::cmd_reset() { 320 332 321 struct Range R = {0, Crates.size()-1}; 322 323 // Check ranges 324 if(!ConvertToRange(Parameter[1], R)) { 325 PrintMessage("Error, crate number out of range\n"); 333 if (ActiveCrate == -1) return; 334 335 if (Crates[ActiveCrate]->SystemReset() == 1) PrintMessage("System reset of crate %d\n", ActiveCrate); 336 else PrintMessage("Error: Could not reset crate %d\n", ActiveCrate); 337 338 } 339 340 // 341 // Read channel 342 // 343 void User::cmd_gs() { 344 345 double Voltage; 346 347 if (ActiveCrate == -1) return; 348 349 if (!ConvertToDouble(Parameter[1], &Voltage)) { 350 PrintMessage("Error: Wrong number format\n"); 326 351 return; 327 352 } 328 353 329 for (int i=R.Min; i<=R.Max; i++) { 330 if (Crates[i]->SystemReset() == 1) PrintMessage("System reset of crate %s (#%d)\n", Crates[i]->Name, i); 331 else PrintMessage("Error: Could not reset board %s (#%d)\n", Crates[i]->Name, i); 332 } 333 } 334 335 // 336 // Read channel 337 // 338 void User::cmd_gs() { 339 340 double Voltage; 341 342 if (!ConvertToDouble(Parameter[1], &Voltage)) return; 343 344 for (unsigned int i=0; i<Crates.size(); i++) { 345 if (Crates[i]->GlobalSet(Voltage) != 1) { 346 PrintMessage("Error: Could not global set crate %d\n", i); 347 } 348 } 354 if (Crates[ActiveCrate]->GlobalSet(Voltage) != 1) { 355 PrintMessage("Error: Could not global set crate %d\n", ActiveCrate); 356 } 349 357 } 350 358 … … 396 404 397 405 PrintMessage(" Number of crates: %d\n", Crates.size()); 406 PrintMessage(" Active crate: %d\n", ActiveCrate); 398 407 PrintMessage(" Refresh rate: %.2f Hz\n", fStatusRefreshRate); 399 408 PrintMessage(" Time out: %.2f s\n\n", fTimeOut); … … 437 446 438 447 // 439 // Exit program 448 // Exit program (Signal makes readline return and sets ExitRequest) 440 449 // 441 450 void User::cmd_exit() { 442 451 443 ExitRequest = true; 444 pthread_kill(Thread, SIGUSR1); // Make tjread return from usleep() 452 pthread_kill(MainThread, SIGTERM); 445 453 } 446 454 … … 512 520 513 521 static bool Warned = false; 522 int Ret; 514 523 515 524 while (!ExitRequest) { 525 526 // Wait (this is the only allowed cancelation point) 527 if ((Ret=pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL)) != 0) { 528 Message(FATAL, "pthread_setcancelstate() failed (%s)", strerror(Ret)); 529 } 530 if (usleep((unsigned long) floor(1000000./fStatusRefreshRate)) == -1) { 531 Message(FATAL, "usleep() failed (%s)", strerror(errno)); 532 } 533 if ((Ret=pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL)) != 0) { 534 Message(FATAL, "pthread_setcancelstate() failed (%s)", strerror(Ret)); 535 } 536 537 // Check all crates 516 538 for (unsigned int i=0; i<Crates.size(); i++) { 517 539 if (Crates[i]->ErrorCount > MAX_ERR_COUNT) { 518 540 if (!Warned) { 519 541 Warned = true; 520 Message(WARN, " Warning:Crate %d has many read/write errors, further error reporting disabled", i);542 Message(WARN, "Crate %d has many read/write errors, further error reporting disabled", i); 521 543 } 522 544 continue; … … 553 575 if (Mode == mode_dynamic) Crates[i]->AdaptVoltages(); 554 576 } // for 555 556 // Wait557 usleep((unsigned long) floor(1000000./fStatusRefreshRate));558 577 } // while 559 578 } -
fact/BIASctrl/User.h
r10118 r10153 30 30 DimService *ConsoleOut; 31 31 char *ConsoleText; 32 pthread_t Thread;32 pthread_t MainThread, Thread; 33 33 std::vector<std::string> Parameter; 34 34 RunMode Mode; … … 52 52 float fStatusRefreshRate; 53 53 double fMaxDiff; 54 int ActiveCrate; 54 55 55 56 User(); … … 67 68 void cmd_timeout(); void cmd_reset(); 68 69 void cmd_help(); void cmd_mode(); 70 void cmd_crate(); 69 71 }; 70 72
Note:
See TracChangeset
for help on using the changeset viewer.