Changeset 226
- Timestamp:
- 06/18/10 12:25:29 (14 years ago)
- Files:
-
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
drsdaq/DAQReadout.cc
r211 r226 64 64 // 65 65 66 DAQReadout::DAQReadout(): 67 DimCommand((char *) SERVER_NAME"/Command", (char *) "C"), 68 EvidenceServer(SERVER_NAME) { 69 70 // Global class pointer 66 DAQReadout::DAQReadout(): EvidenceServer(SERVER_NAME) { 67 68 // Initialization 71 69 This = this; 72 70 MainThread = getpid(); 73 74 // Start time of DAQ 71 ConsoleText = NULL; 75 72 time(&StartTime); 73 74 // DIM console service used in PrintMessage() 75 ConsoleOut = new DimService(SERVER_NAME"/ConsoleOut", (char *) ""); 76 76 77 77 // Initialize mutex for thread synchronisation 78 78 if (pthread_mutex_init(&Mutex, NULL) != 0) { 79 State(FATAL, "pthread_mutex_init() failed");79 Message(FATAL, "pthread_mutex_init() failed"); 80 80 } 81 81 … … 89 89 LastBoard = -1; 90 90 MinDelay = 1; 91 91 92 92 // Get configuration data 93 93 fRawDataPath = GetConfig("RawDataPath"); … … 145 145 // Create instance of HV feedback (must be called after board detection) 146 146 HVFB = new HVFeedback(this); 147 148 // Install DIM command (after all initialized) 149 Command = new DimCommand((char *) SERVER_NAME"/Command", (char *) "C", this); 147 150 } 148 151 … … 153 156 DAQReadout::~DAQReadout() { 154 157 155 delete EventService; 156 delete[] DIMEventData; 158 delete Command; 159 160 delete EventService; delete[] DIMEventData; 157 161 delete RHeader; delete EHeader; 158 162 delete HVFB; delete[] ACalibTemp; … … 160 164 delete[] DRSFreq; delete[] BStruct; 161 165 delete[] WaveForm; delete[] TriggerCell; 162 163 // Destroy mutex 164 if (pthread_mutex_destroy(&Mutex) != 0) State(ERROR, "pthread_mutex_destroy() failed"); 166 167 delete ConsoleOut; 168 free(ConsoleText); 169 170 if (pthread_mutex_destroy(&Mutex) != 0) Message(ERROR, "pthread_mutex_destroy() failed"); 165 171 } 166 172 … … 171 177 void DAQReadout::Execute(char *Command) { 172 178 173 if (strlen(Command)==0) return; // Ignore empty commands 174 175 if(Command[0]=='.') { // Shell command 179 if (Command[0]=='.') { // Shell command 176 180 system(&(Command[1])); 177 181 return; 178 182 } 179 183 180 for (int i=0; i<MAX_NUM_TOKEN; i++) Param[i] = ""; // All pointers point initially to empty string184 for (int i=0; i<MAX_NUM_TOKEN; i++) Param[i] = ""; // All pointers point initially to empty string 181 185 NParam = ParseInput(Command, Param); 182 183 for(CmdNumber=0; CmdNumber<sizeof(CommandList)/sizeof(CL_Struct); CmdNumber++) 184 if (Match(Param[0], CommandList[CmdNumber].Name)) { 185 if(CommandList[CmdNumber].NeedNotBusy && daq_state==active) PrintMessage("DAQ is busy\n"); 186 else if(CommandList[CmdNumber].NeedNotBusy && NumBoards==0) PrintMessage("No boards available\n"); 187 else { 188 pthread_mutex_lock(&Mutex); 189 (this->*CommandList[CmdNumber].CommandPointer)(); 190 pthread_mutex_unlock(&Mutex); 191 } 192 return; 193 } 194 PrintMessage("Unknown command '%s'\n",Param[0]); 186 187 // Search for command 188 unsigned int Count; 189 for (Count=0; Count<sizeof(CommandList)/sizeof(CL_Struct); Count++) { 190 if (Match(Param[0], CommandList[Count].Name)) break; 191 } 192 193 // Command not found? 194 if (Count == sizeof(CommandList)/sizeof(CL_Struct)) { 195 PrintMessage("Unknown command '%s'\n", Param[0]); 196 return; 197 } 198 199 if(CommandList[Count].NeedNotBusy && daq_state==active) PrintMessage("DAQ is busy\n"); 200 else if(CommandList[Count].NeedNotBusy && NumBoards==0) PrintMessage("No boards available\n"); 201 else { 202 int Ret; 203 204 // Lock (Execute() runs in thread spawned by commandHandler()) 205 if ((Ret = pthread_mutex_lock(&Mutex)) != 0) { 206 Message(FATAL, "pthread_mutex_lock() failed (%s)", strerror(Ret)); 207 } 208 // Run command 209 CmdNumber = Count; 210 (this->*CommandList[CmdNumber].CommandPointer)(); 211 // Unlock 212 if ((Ret = pthread_mutex_unlock(&Mutex)) != 0) { 213 Message(FATAL, "pthread_mutex_unlock() failed (%s)", strerror(Ret)); 214 } 215 } 195 216 } 196 217 … … 199 220 time_t ActualT; 200 221 time (&ActualT); 201 PrintMessage("% d:%02d:%02d\n", (int) difftime(ActualT, StartTime)/3600, ((int) difftime(ActualT, StartTime)/60)%60, (int) difftime(ActualT, StartTime)%60);222 PrintMessage("%02d:%02d:%02d\n", (int) difftime(ActualT, StartTime)/3600, ((int) difftime(ActualT, StartTime)/60)%60, (int) difftime(ActualT, StartTime)%60); 202 223 } 203 224 … … 1116 1137 } 1117 1138 1118 // Event data (It is required that at least three chunks can be written with writev(), therefore 1119 // IOV_MAX>=3 is checked at startup 1120 1121 1122 // First chunk: trigger cells 1123 //DataPart[Count].iov_base = (char *) TriggerCell + FirstBoard*RHeader->NChips*sizeof(int); // TriggerCell is without cast a pointer to an 8-byte unit (two ints) ! 1124 //DataPart[Count++].iov_len = RHeader->NBoards * RHeader->NChips * sizeof(int); 1125 //Size += DataPart[Count-1].iov_len; 1126 1127 // Remaining chunks: ADC data (two chucks per channel if wrap around of pipeline occurred) 1139 // ADC data (two chucks per channel if wrap around of pipeline occurred, therefore 1140 // IOV_MAX>=2 is checked at startup 1128 1141 for (int i=FirstBoard; (i<=LastBoard + (NumBoards==0)); i++) { 1129 1142 for (unsigned int k=0; k<RHeader->NChips; k++) { … … 1202 1215 void DAQReadout::DoPrintMessage(const char *Format, va_list ArgumentPointer, int Target) { 1203 1216 1204 static char Textbuffer[MAX_COM_SIZE]; 1205 1206 memset(Textbuffer, 0, sizeof(Textbuffer)); 1207 vsnprintf(Textbuffer, sizeof(Textbuffer), Format, ArgumentPointer); 1217 static char Error[] = "vasprintf() failed in DoPrintMessage()"; 1218 char *Text; 1219 1220 // Evaluate arguments 1221 if (vasprintf(&Text, Format, ArgumentPointer) == -1) Text = Error; 1208 1222 1209 1223 // Print to console 1210 1224 if(Target & MsgToConsole) { 1211 if(strlen(Textbuffer)>0 && Textbuffer[strlen(Textbuffer)-1]=='\n') { 1212 printf("\r%s%s", Textbuffer, Prompt); // New prompt 1213 } 1214 else printf("%s", Textbuffer); 1225 if(strlen(Text)>0 && Text[strlen(Text)-1]=='\n') printf("\r%s%s", Text, Prompt); // New prompt 1226 else printf("%s", Text); 1215 1227 fflush(stdout); 1216 1228 } 1217 1229 1218 // Send to DIM service 1219 SetStdOut(Textbuffer); 1220 1221 // Send to log 1222 if(Target & MsgToLog) { 1223 char *Buf; 1224 if (asprintf(&Buf, "%s %s", SERVER_NAME, Textbuffer) != -1) { 1225 DimClient::sendCommandNB("DColl/Log", Buf); 1226 free(Buf); 1227 } 1228 else DimClient::sendCommandNB("DColl/Log", SERVER_NAME" asprintf() failed"); 1229 } 1230 // Send to DIM console service and to log if requested 1231 ConsoleOut->updateService(Text); 1232 if(Target & MsgToLog) SendToLog("%s %s", SERVER_NAME, Text); 1233 1234 // Free old text 1235 if (ConsoleText != Error) free(ConsoleText); 1236 ConsoleText = Text; 1230 1237 } 1231 1238 … … 1233 1240 void DAQReadout::commandHandler() { 1234 1241 1235 // Copy command to new buffer (must be freed by the new thread) 1242 // Ignore empty or illegal strings 1243 if (getCommand()->getSize() == 0 || 1244 *((char *) getCommand()->getData()+getCommand()->getSize()-1) != '\0' || 1245 strlen(getCommand()->getString()) == 0) return; 1246 1247 // Copy command to new buffer (will be freed by global Execute() function) 1236 1248 char *Command; 1237 if (asprintf(&Command, "%s", get String()) == -1) {1249 if (asprintf(&Command, "%s", getCommand()->getString()) == -1) { 1238 1250 PrintMessage("asprintf() failed in DRSReadout::commandHandler() (%s)\n", strerror(errno)); 1239 1251 return; … … 1314 1326 else if (daq_runtype == pedestal) StopDRS(); // ..or for software trigger 1315 1327 1316 // Read event data 1328 // Read event data and restart (reduces dead-time because waiting for next trigger while writing) 1317 1329 ReadCalibratedDRSData(); 1318 1319 // Restart here reduces dead-time (already waiting for next trigger while writing)1320 1330 StartDRS(); 1321 1331 … … 1386 1396 else PrintMessage("\rRun #%d (%s) aborted due to error after %d events\n", RunNumber, daq_runtype_str[daq_runtype], NumEvents); 1387 1397 1388 // Write run summary to slow data file1389 //m->SlowDataClass->NewEntry("Runinfo");1390 //m->SlowDataClass->AddToEntry("%d %s %s %d %d %s", m->RunNumber, WriteError?"Error":"OK", daq_runtype_str[m->daq_runtype], m->NumEvents, m->FileNumber, m->RHeader->Description);1391 1392 1398 // Print run statistics 1393 1399 if (NumEvents>0 && !WriteError) { … … 1445 1451 } 1446 1452 1453 // Stub to call Execute() metho of class and free command memory 1447 1454 void Execute(char *Command) { 1448 1455 -
drsdaq/DAQReadout.h
r211 r226 33 33 enum runtype_enum {data, pedestal, reserved, test}; 34 34 35 class DAQReadout : public DRS, public DRSCallback, public DimCommand, publicEvidenceServer {35 class DAQReadout : public DRS, public DRSCallback, public EvidenceServer { 36 36 37 37 time_t StartTime; 38 38 pid_t MainThread; 39 39 DimService *EventService; 40 40 int MinDelay; 41 41 unsigned int CmdNumber; 42 DimCommand *Command; 43 DimService *ConsoleOut; 44 char *ConsoleText; 42 45 43 46 void PrintUsage(); -
drsdaq/HVFeedback.cc
r211 r226 25 25 // Constructor: Initialise feedback 26 26 // 27 HVFeedback::HVFeedback(DAQReadout* DAQClass){//: 28 //EvidenceServer(SERVER_NAME){ 27 HVFeedback::HVFeedback(DAQReadout* DAQClass){ 29 28 30 29 m = DAQClass; … … 139 138 } 140 139 141 // Update DIM service regularly140 // Update DIM count service regularly 142 141 if (time(NULL)-LastServiceUpdate > 2) { 143 142 LastServiceUpdate = time(NULL); … … 148 147 149 148 // Feedback action 149 std::stringstream Cmd; 150 150 151 for (i=m->FirstBoard; i<=m->LastBoard; i++) { 151 152 for (j=0; j<fNumberOfChips; j++) { … … 165 166 166 167 if(fabs(Average[i][j][k]) < 2*Sigma[i][j][k]) printf("Too noisy!\n"); 167 else WriteHVCommand("hv %s %+f\n",PixMap->DRS_to_Pixel(i,j,k).c_str(), Correction); 168 168 else { 169 Cmd << PixMap->DRS_to_Pixel(i,j,k)+" " << std::showpos << Correction << " "; 170 } 169 171 break; 170 172 … … 175 177 case FB_ResponseFirst: // First point of response measurement done 176 178 Buffer[i][j][k] = Average[i][j][k]; 177 if(!PixMap->DRS_to_Pixel(i,j,k).empty()) WriteHVCommand("hv %s %+f",PixMap->DRS_to_Pixel(i,j,k).c_str(), DiffVoltage); 179 if(!PixMap->DRS_to_Pixel(i,j,k).empty()) { 180 Cmd << PixMap->DRS_to_Pixel(i,j,k) << " " << std::showpos << DiffVoltage << " "; 181 } 178 182 break; 179 183 … … 184 188 } 185 189 else Response[i][j][k] = DiffVoltage/(Buffer[i][j][k]-Average[i][j][k]); 186 if(!PixMap->DRS_to_Pixel(i,j,k).empty()) WriteHVCommand("hv %s %+f",PixMap->DRS_to_Pixel(i,j,k).c_str(), -DiffVoltage/2); 190 if(!PixMap->DRS_to_Pixel(i,j,k).empty()) { 191 Cmd << PixMap->DRS_to_Pixel(i,j,k) << " " << std::showpos << -DiffVoltage/2 << " "; 192 } 187 193 break; 188 194 … … 196 202 FeedbackAverage->updateService(); 197 203 FeedbackSigma->updateService(); 204 205 // Send command 206 if (!Cmd.str().empty()) { 207 DimClient::sendCommand("Bias/Command", ("hv "+Cmd.str()).c_str()); 208 } 198 209 199 210 switch (FBMode) { … … 269 280 else { 270 281 FBMode = Mode; 271 if (Mode != FB_ResponseFirst) m-> State(m->INFO, "%s", FBState_Description[FBMode]);272 else m-> State(m->INFO, "%s (voltage difference %.3f)", FBState_Description[FBMode], DiffVoltage);282 if (Mode != FB_ResponseFirst) m->Message(m->INFO, "%s", FBState_Description[FBMode]); 283 else m->Message(m->INFO, "%s (voltage difference %.3f)", FBState_Description[FBMode], DiffVoltage); 273 284 ClearAverages(); 274 285 } … … 320 331 void HVFeedback::MeasureResponse(float U) { 321 332 333 std::stringstream Cmd; 334 322 335 if (U==0) { 323 336 m->PrintMessage("HV Feedback: Error, voltage difference must not non-zero.\n"); … … 325 338 } 326 339 327 for (int i=m->FirstBoard; i<=m->LastBoard; i++) 328 for (int j=0; j<fNumberOfChips; j++) 329 for (int k=0; k<fNumberOfChannels; k++) { 330 if(!PixMap->DRS_to_Pixel(i,j,k).empty()) { 331 WriteHVCommand("hv %s %+f\n",PixMap->DRS_to_Pixel(i,j,k).c_str(), -U/2); 332 } 333 } 340 for (int i=m->FirstBoard; i<=m->LastBoard; i++) { 341 for (int j=0; j<fNumberOfChips; j++) { 342 for (int k=0; k<fNumberOfChannels; k++) { 343 if(!PixMap->DRS_to_Pixel(i,j,k).empty()) { 344 Cmd << PixMap->DRS_to_Pixel(i,j,k) << " " << std::showpos << -U/2 << " "; 345 } 346 } 347 } 348 } 349 350 // Send command 351 if (!Cmd.str().empty()) { 352 DimClient::sendCommand("Bias/Command", ("hv "+Cmd.str()).c_str()); 353 } 354 334 355 DiffVoltage = U; 335 356 SetFBMode(FB_ResponseFirst, true); … … 351 372 352 373 // 353 // Write bias voltage commmand354 //355 bool HVFeedback::WriteHVCommand(const char *Format, ...) {356 357 char Textbuffer[MAX_COM_SIZE];358 359 va_list ArgumentPointer; va_start(ArgumentPointer, Format);360 vsnprintf(Textbuffer, sizeof(Textbuffer), Format, ArgumentPointer);361 362 DimClient::sendCommand("Bias/Command", Textbuffer);363 return true;364 }365 366 //367 374 // Print feedback configuration 368 375 // -
drsdaq/HVFeedback.h
r211 r226 6 6 #include <stdlib.h> 7 7 #include <math.h> 8 #include <sstream> 8 9 9 10 #include "RawDataCTX.h" … … 12 13 enum FBState {FB_Off, FB_Active, FB_Targets, FB_ResponseFirst, FB_ResponseSecond}; 13 14 14 class HVFeedback: public DimServer { //EvidenceServer {15 class HVFeedback: public DimServer { 15 16 16 17 class DAQReadout *m; … … 70 71 void GetResponse(); 71 72 void ClearAverages(); 72 bool WriteHVCommand(const char *, ...);73 73 void PrintConfig(int); 74 74 }; -
drsdaq/drsdaq.cpp
r211 r226 36 36 int LockDescriptor; 37 37 38 // Readline library uses getc() (allows interruption by signal)39 rl_getc_function = getc;40 41 // writev() in DAQ thread needs to be able to write at least 3 chunks42 if(IOV_MAX < 3) {43 printf("Fatal error: IOV_MAX is less than 3, cannot use writev() to write event data.\n");44 exit(EXIT_FAILURE);45 }46 47 38 // Assure only one instance of program runs (lock creator written to log file) 48 // Lock file deleted by ExitFunction()39 // Lock file deleted by destructor 49 40 if((LockDescriptor = open(LOCKFILE,O_WRONLY|O_CREAT|O_EXCL, S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH)) == -1) { 50 41 if(errno==EEXIST) { … … 59 50 sprintf(str,"echo Created >%s; date >>%s; echo by $USER@$HOSTNAME >>%s",LOCKFILE,LOCKFILE,LOCKFILE); 60 51 system(str); 61 52 53 // Readline library uses getc() (allows interruption by signal) 54 rl_getc_function = getc; 55 56 // writev() in DAQ thread needs to be able to write at least 3 chunks 57 if(IOV_MAX < 2) { 58 printf("Fatal error: IOV_MAX is less than 2, cannot use writev() to write event data.\n"); 59 exit(EXIT_FAILURE); 60 } 61 62 62 system("clear"); 63 63 printf("\n*** DRS readout (built %s, %s, revision %s) *** \n\n",__DATE__, __TIME__, REVISION); 64 65 // Set exit function 66 atexit(&ExitFunction); 64 67 65 68 // Construct main instance (static ensures destructor is called with exit()) 66 69 static DAQReadout M; 67 70 68 // Set signal and exit handlers 69 atexit(&ExitFunction); 71 // Set signal handlers 70 72 signal(SIGILL, &CrashHandler); 71 73 signal(SIGABRT, &CrashHandler); … … 88 90 // Process command 89 91 DimClient::sendCommand(SERVER_NAME"/Command", Command); 90 91 92 free(Command); 92 93 } … … 94 95 95 96 96 //*****************97 // Signal handlers98 //*****************99 100 97 // Remove lock file before running default signal code 101 98 void CrashHandler(int Signal) { 102 99 remove(LOCKFILE); 103 printf("Caught signal number %d. Remov inglockfile and performing standard signal action. Good luck.\n",Signal);100 printf("Caught signal number %d. Removed lockfile and performing standard signal action. Good luck.\n",Signal); 104 101 signal(Signal, SIG_DFL); 105 102 raise(Signal); … … 109 106 void ExitFunction() { 110 107 111 if (remove(LOCKFILE) ==-1) {108 if (remove(LOCKFILE) == -1) { 112 109 printf("Could not remove lock file %s (%s)\n", LOCKFILE, strerror(errno)); 113 110 } 114 115 return;116 111 } -
hvcontrol/History.txt
r220 r226 1 1 8/7/2009 Changed path to pixelmap in ProcessIO.h to stay within repository 2 2 Removed unused makefiles 3 Moved config file to config directory of repository4 Removed writing of config file5 Removed several unused functions6 Removed command to switch off logging3 Moved config file to config directory of repository 4 Removed writing of config file 5 Removed several unused functions 6 Removed command to switch off logging 7 7 9/7/2009 Implemented readline library for command-line editing 8 8 Included logging functions in main class (solved lockfile problem) 9 Only a single log file is written9 Only a single log file is written 10 10 10/7/2009 Removed reference voltage related code (not supported by hardware) 11 11 17/7/2009 Communication with FDTI now with Linux kernel driver (virtual com 12 12 port) instead of FTDI library (Standard open()/read()/write() 13 system calls can be used).13 system calls can be used). 14 14 20/7/2009 Reading with time-out from tty uses now select() 15 15 22/7/2009 Combined code of 'hv' and 'hvdiff' commands. With either one, pixel id, 16 16 channel number of keyword 'all' can be used. Removed configuration 17 option to set usage of DAC values. Instead, a third parameter 'dac'18 to the 'hv' and 'hvdiff' commands chooses DAC values.17 option to set usage of DAC values. Instead, a third parameter 'dac' 18 to the 'hv' and 'hvdiff' commands chooses DAC values. 19 19 24/7/2009 Lockfile is deleted if configuration file cannot be read 20 20 27/7/2009 Slow data is written for every HV ramp to file given in configuration … … 23 23 3/8/2009 Removed explicit test mode. Commands 'hv' and 'hvdiff' will simply 24 24 return OK if no HV boards available. 25 Number of HV boards is not limited anymore.25 Number of HV boards is not limited anymore. 26 26 24/9/2009 Program is terminated if too many errors are encountered by the 27 27 monitor thread … … 35 35 29/1/2010 DAC value 0 is now equivilant to calibrated voltage value 0 36 36 4/6/2010 Command 'hv' allows an array of pixel IDs/voltages (used by feedback) 37 15/6/2010 'Channels' now is counted continously from 0 to NUM_CHAINS*NUM_CHANNELS, 38 removed 'chain' command -
hvcontrol/hvcontrol.cpp
r183 r226 23 23 24 24 // Function prototypes 25 void ConsoleCommand(ProcessIO *);26 25 void HVMonitor(ProcessIO *); 27 26 void DummyHandler(int); … … 32 31 // Main program 33 32 // ================ 34 //35 // Several unlikely system call failures are handled via throwing an exception.36 33 37 int main( int argc, char *argv[]) {34 int main() { 38 35 39 char str[MAX_COM_SIZE] ;40 pthread_t thread_ ConsoleCommand,thread_HVMonitor;36 char str[MAX_COM_SIZE], *Command; 37 pthread_t thread_HVMonitor; 41 38 int LockDescriptor; 42 39 … … 72 69 atexit(&ExitFunction); 73 70 74 // Construct main instance and create mutex for thread synchronization 75 ProcessIO pio; 76 if (pthread_mutex_init(&pio.control_mutex, NULL) != 0) { 77 perror("pthread_mutex_init failed"); 78 throw; 79 } 71 // Construct main instance 72 static ProcessIO M; 80 73 81 74 // These signals were set during construction of EvidenceServer … … 85 78 signal(SIGTERM, &CrashHandler); 86 79 87 // Create threads 88 if ((pthread_create(&thread_ConsoleCommand, NULL, (void * (*)(void *)) ConsoleCommand,(void *) &pio)) != 0) { 89 perror("pthread_create failed with console thread"); 90 throw; 80 // Create monitor thread and make accessible for sending signal 81 if ((pthread_create(&thread_HVMonitor, NULL, (void * (*)(void *)) HVMonitor,(void *) &M)) != 0) { 82 M.Message(M.FATAL, "pthread_create failed with HVMonitor thread"); 91 83 } 92 if ((pthread_create(&thread_HVMonitor, NULL, (void * (*)(void *)) HVMonitor,(void *) &pio)) != 0) { 93 perror("pthread_create failed with HVMonitor thread"); 94 throw; 95 } 84 M.HVMonitor = thread_HVMonitor; 96 85 97 // Threads should be accessible for sending signals 98 pio.HVMonitor = thread_HVMonitor; 99 100 // Wait for threads to quit 101 pthread_join(thread_ConsoleCommand, NULL); 102 pthread_join(thread_HVMonitor, NULL); 103 104 // Destruct mutex and main instance 105 pthread_mutex_destroy (&pio.control_mutex); 106 pio.~ProcessIO(); 107 108 // Remove lockfile 109 if (remove(LOCKFILE)==-1) { 110 sprintf(str, "Could not remove lock file %s", LOCKFILE); 111 perror(str); 112 exit(EXIT_FAILURE); 113 } 114 115 exit(EXIT_SUCCESS); 116 } 117 118 119 /********************************************************************\ 120 121 ConsoleCommand thread 122 123 Handle console input using readline library functions to allow 124 line editing and history capability 125 126 \********************************************************************/ 127 128 void ConsoleCommand(ProcessIO *m) { 129 130 char *Command; 131 132 while (!m->Exit) { 133 86 while (!M.ExitRequest) { 134 87 // Assemble prompt 135 snprintf(m->Prompt, sizeof(m->Prompt),"\rHV"); 136 if (m->NumHVBoards == 0) sprintf(m->Prompt+strlen(m->Prompt),"> "); 88 if (M.NumHVBoards == 0) snprintf(M.Prompt, sizeof(M.Prompt), "\rBias> "); 137 89 else { 138 if (m->FirstChain == m->LastChain) sprintf(m->Prompt+strlen(m->Prompt),"|C%d",m->FirstChain); 139 else sprintf(m->Prompt+strlen(m->Prompt),"|C%d-%d",m->FirstChain,m->LastChain); 140 141 if (m->NumHVBoards == 0) sprintf(m->Prompt+strlen(m->Prompt),"> "); 142 else if (m->FirstBoard == m->LastBoard) sprintf(m->Prompt+strlen(m->Prompt),"|B%d> ",m->FirstBoard); 143 else snprintf(m->Prompt,sizeof(m->Prompt),"\rDAQ|B%d-%d> ",m->FirstBoard,m->LastBoard); 90 if (M.FirstBoard == M.LastBoard) snprintf(M.Prompt, sizeof(M.Prompt), "\rBias|B%d> ",M.FirstBoard); 91 else snprintf(M.Prompt, sizeof(M.Prompt),"\rBias|B%d-%d> ",M.FirstBoard, M.LastBoard); 144 92 } 145 93 146 94 // Read Command 147 Command = readline(m->Prompt); 148 if (Command==NULL) { 149 m->PrintMessage("Error reading command line input\n"); 150 continue; 151 } 95 Command = readline(M.Prompt); 96 if (Command == NULL) continue; 152 97 if(strlen(Command)>0) add_history(Command); 153 98 154 // Process command (via DIM gives automatic serialisation)99 // Process command (via DIM gives automatic thread serialisation) 155 100 DimClient::sendCommand("Bias/Command", Command); 156 101 free(Command); 102 } 103 104 // Wait for thread to quit 105 if (pthread_join(thread_HVMonitor, NULL) != 0) { 106 M.PrintMessage("pthread_join() failed in main()"); 157 107 } 158 108 } … … 161 111 /********************************************************************\ 162 112 163 HVMonitor164 165 113 Monitor HV board status 166 Sebastian Commichau, November 2008167 114 168 115 \********************************************************************/ 169 116 170 117 void HVMonitor(ProcessIO *m) { 171 172 while (!m->Exit) { 173 if (m->state == active) { 174 pthread_mutex_lock(&m->control_mutex); 175 m->Monitor(); 176 pthread_mutex_unlock(&m->control_mutex); 177 } 118 119 120 while (!m->ExitRequest) { 121 if (m->state == active) m->Monitor(); 178 122 usleep((unsigned long)floor(1000000./(m->NumHVBoards*m->fStatusRefreshRate))); 179 123 } … … 202 146 // This function will be implicitly called by exit() 203 147 void ExitFunction() { 204 remove(LOCKFILE); 205 return; 148 149 if (remove(LOCKFILE) == -1) { 150 printf("Could not remove lock file %s (%s)\n", LOCKFILE, strerror(errno)); 151 } 206 152 } -
hvcontrol/src/ProcessIO.cc
r220 r226 22 22 } CommandList[] = 23 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)"}, 24 {"hv", &ProcessIO::cmd_hv, 2, "<id>|<ch>|<all> <v>", "Change bias of pixel or (all) chan. of active boards"}, 26 25 {"status", &ProcessIO::cmd_status, 0, "[dac]", "Show status information (DAC values if requested)"}, 27 26 {"config", &ProcessIO::cmd_config, 0, "", "Print configuration"}, … … 40 39 using namespace std; 41 40 41 42 // Constructor 42 43 ProcessIO::ProcessIO(): EvidenceServer(SERVER_NAME) { 43 44 … … 46 47 47 48 // Initialize status variables 48 state = active;49 Exit = false;50 49 state = active; 50 ConsoleText = NULL; 51 51 52 NumHVBoards = 0; 52 53 FirstBoard = 0; 53 54 LastBoard = -1; 54 FirstChain = 0; 55 LastChain = NUM_CHAINS-1; 55 56 // Initialize mutex for thread synchronisation 57 if (pthread_mutex_init(&Mutex, NULL) != 0) { 58 Message(FATAL, "pthread_mutex_init() failed"); 59 } 60 61 // DIM console service used in PrintMessage() 62 ConsoleOut = new DimService(SERVER_NAME"/ConsoleOut", (char *) ""); 56 63 57 64 // Get configuration data … … 94 101 95 102 103 // Destructor 96 104 ProcessIO::~ProcessIO() { 97 105 … … 101 109 delete[] fHVBoard; 102 110 103 delete pm; delete calib; 111 delete pm; 112 delete calib; 113 delete ConsoleOut; 114 free(ConsoleText); 115 116 // Destroy mutex 117 if (pthread_mutex_destroy(&Mutex) != 0) Message(ERROR, "pthread_mutex_destroy() failed"); 104 118 } 105 119 … … 180 194 } 181 195 182 // Adress chains183 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 196 203 197 // Print configuration … … 209 203 for (int i=0; i<NumHVBoards; i++) PrintMessage(" Board %d: %s\n", i, fHVBoard[i]->BoardName); 210 204 211 PrintMessage( " TimeOut: %.2f s\n" 212 " StatusRefreshRate: %.2f Hz\n" 205 PrintMessage( " StatusRefreshRate: %.2f Hz\n" 213 206 " DACMin value: %d\n" 214 207 " DACMax value: %d\n" … … 216 209 " HVCalibSlope : %f\n" 217 210 " HVMaxDiff : %u\n", 218 f TimeOut, fStatusRefreshRate, DACMin,211 fStatusRefreshRate, DACMin, 219 212 DACMax, fHVCalibOffset, fHVCalibSlope, fHVMaxDiff); 220 213 } … … 236 229 void ProcessIO::cmd_hv() { 237 230 238 int hvoltage, DACValue, Errors=0, Board=-1, Chain=-1, Channel=-1; 239 double hvoltageV; 231 int Int, SingleChannel; 232 unsigned int DACValue, Errors=0; 233 double Double; 240 234 bool SetDac; 241 235 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"); 264 return; 265 } 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"); 283 return; 284 } 285 236 // Interpretation as DAC value requested? 237 if (Parameter.size() == 4 && Match(Parameter[3], "dac")) SetDac = true; 238 else SetDac = false; 239 240 // Interprete first number (might be channel number) 241 if (!ConvertToInt(Parameter[1], &SingleChannel)) SingleChannel = -1; 242 243 // Loop over all boards 286 244 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(); 245 // Loop over all channels given as command parameter 246 for (unsigned int n=1; n<Parameter.size()-1; n+=2) { 247 // Loop over all channels 248 for (int j=0; j<NUM_CHAINS; j++) for (int k=0; k<NUM_CHANNELS; k++) { 249 250 // Current channel must be considered? 251 if (!Match(Parameter[1], "all") && !(i == (int) pm->Pixel_to_HVboard(Parameter[n]) && 252 j == (int) pm->Pixel_to_HVchain(Parameter[n]) && k == (int) pm->Pixel_to_HVchannel(Parameter[n])) && 253 !(j == SingleChannel/NUM_CHANNELS && k == SingleChannel%NUM_CHANNELS)) continue; 254 255 // Voltage change (number starts with + oder -) ignored if current DAC value is zero 256 if (isdigit(Parameter[n+1][0])==0 && fHVBoard[i]->HV[j][k] == 0) continue; 257 258 // Set new voltage/DAC value 259 if (!SetDac){ 260 // Convert voltage value and check format 261 if (!ConvertToDouble(Parameter[n+1], &Double)) { 262 PrintMessage("Error: Wrong number format for voltage setting\n"); 263 goto LeaveLoop; 264 } 265 // Adjust voltage and DAV value 266 if (isdigit(Parameter[n+1][0]) == 0) fHVBoard[i]->HVV[j][k] += Double; 267 else fHVBoard[i]->HVV[j][k] = Double; 268 DACValue = calib->HVToDAC(fHVBoard[i]->HVV[j][k], i, j, k); 269 } 270 else { 271 // Convert DAC value and check format 272 if (!ConvertToInt(Parameter[n+1], &Int)) { 273 PrintMessage("Error: Wrong number format for DAC voltage setting\n"); 274 goto LeaveLoop; 275 } 276 // Adjust DAC value 277 if (isdigit(Parameter[n+1][0]) == 0) DACValue = fHVBoard[i]->HV[j][k] + Int; 278 else DACValue = Int; 279 } 280 281 // Set new voltage (if DAC value, update calibrated value) 282 if (!RampVoltage(DACValue, i, j, k)) Errors++; 283 if (SetDac) fHVBoard[i]->HVV[j][k] = calib->DACToHV(fHVBoard[i]->HV[j][k], i, j, k); 284 } // Channels and chains 285 } // Loop over command argument 286 287 // Update DIM service for this boar 288 LeaveLoop: 289 fHVBoard[i]->BiasVolt->updateService(); 315 290 } // Boards 316 291 317 292 if (Errors > 0) PrintMessage("Errors on %d channel(s) occurred\n", Errors); 318 293 } … … 454 429 for (int i=FirstBoard; i<=LastBoard; i++) { 455 430 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++) { 431 fHVBoard[i]->GetBoardNumber(), fHVBoard[i]->BoardName, 432 fHVBoard[i]->WrapOK ? "ok":"error", fHVBoard[i]->LastWrapCount, 433 fHVBoard[i]->ResetButton ? "yes" : "no", fHVBoard[i]->fTimeOut, fHVBoard[i]->ErrorCount); 434 435 for (int j=0; j<NUM_CHAINS; j++) { 464 436 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 } 437 for (int l=0; l<NUM_CHANNELS; l++) { 438 if (l%8 == 0) PrintMessage("\r%3.1d: ", j*NUM_CHANNELS+l); 439 if (Parameter.size() == 2) PrintMessage("%5d ",fHVBoard[i]->HV[j][l]); 440 else PrintMessage("%#5.2f ",fHVBoard[i]->HVV[j][l]); 441 if (l%8 == 7) PrintMessage("\n"); 442 } 473 443 } 474 444 } … … 508 478 void ProcessIO::cmd_exit() { 509 479 510 Exit = true;480 ExitRequest = true; 511 481 pthread_kill(HVMonitor, SIGUSR1); 512 482 } … … 535 505 void ProcessIO::DoPrintMessage(const char *Format, va_list ArgumentPointer, MsgTarget Target) { 536 506 537 static char Textbuffer[MAX_COM_SIZE]; // static because of DIM service 538 539 memset(Textbuffer, 0, sizeof(Textbuffer)); 540 vsnprintf(Textbuffer, sizeof(Textbuffer), Format, ArgumentPointer); 507 static char Error[] = "vasprintf() failed in DoPrintMessage()"; 508 char *Text; 509 510 // Evaluate arguments 511 if (vasprintf(&Text, Format, ArgumentPointer) == -1) Text = Error; 541 512 542 513 // Print to console 543 514 if(Target & Console) { 544 if(strlen(Textbuffer)>0 && Textbuffer[strlen(Textbuffer)-1]=='\n') { 545 printf("\r%s%s", Textbuffer, Prompt); // New prompt 546 } 547 else printf("%s", Textbuffer); 515 if(strlen(Text)>0 && Text[strlen(Text)-1]=='\n') printf("\r%s%s", Text, Prompt); // New prompt 516 else printf("%s", Text); 548 517 fflush(stdout); 549 518 } 550 519 551 // Send to DIM service 552 SetStdOut(Textbuffer); 553 554 // Send to log 555 if(Target & Log) { 556 char *Buf; 557 if (asprintf(&Buf, "%s %s", SERVER_NAME, Textbuffer) != -1) { 558 DimClient::sendCommandNB("DColl/Log", Buf); 559 free(Buf); 560 } 561 else DimClient::sendCommandNB("DColl/Log", SERVER_NAME" asprintf() failed"); 562 } 520 // Send to DIM console service and log 521 ConsoleOut->updateService(Text); 522 if(Target & Log) SendToLog("%s %s", SERVER_NAME, Text); 523 524 // Free old text 525 if (ConsoleText != Error) free(ConsoleText); 526 ConsoleText = Text; 563 527 } 564 528 … … 572 536 573 537 if (fHVBoard[Board]->SetHV(Chain, Channel, fHVBoard[Board]->HV[Chain][Channel]+Diff) != 1) { 574 State(ERROR, "Could not set bias of board %d, chain %d, channel %d. Skipping channel\n",fHVBoard[Board]->GetBoardNumber(),Chain,Channel);538 Message(ERROR, "Could not set bias of board %d, chain %d, channel %d. Skipping channel\n",fHVBoard[Board]->GetBoardNumber(),Chain,Channel); 575 539 return false; 576 540 } … … 585 549 586 550 static bool Warned = false; 587 551 int Ret; 552 553 // Lock because command execution runs in different thread 554 if ((Ret = pthread_mutex_lock(&Mutex)) != 0) { 555 Message(FATAL, "pthread_mutex_lock() failed in commandHandler() (%s)", strerror(Ret)); 556 } 557 588 558 for (int i=0; i<NumHVBoards; i++) { 589 559 if (fHVBoard[i]->ErrorCount > 10) { … … 591 561 Warned = true; 592 562 PrintMessage(All, "Warning: Some board has many read/write errors, status monitor disabled\n"); 593 State(WARN, "Warning: Some board has many read/write errors, status monitor disabled\n");563 Message(WARN, "Warning: Some board has many read/write errors, status monitor disabled\n"); 594 564 } 595 565 continue; … … 598 568 if (fHVBoard[i]->GetStatus() != 1) { 599 569 PrintMessage(All, "Error: Monitor could not read status of board %d\n", fHVBoard[i]->GetBoardNumber()); 600 State(ERROR, "Error: Monitor could not read status of board %d\n", fHVBoard[i]->GetBoardNumber());570 Message(ERROR, "Error: Monitor could not read status of board %d\n", fHVBoard[i]->GetBoardNumber()); 601 571 } 602 572 603 573 if (fHVBoard[i]->ResetButton) { 604 574 PrintMessage(All, "Manual reset of board %d\n",fHVBoard[i]->GetBoardNumber()); 605 State(INFO, "Manual reset of board %d\n",fHVBoard[i]->GetBoardNumber());575 Message(INFO, "Manual reset of board %d\n",fHVBoard[i]->GetBoardNumber()); 606 576 ResetBoard(i); 607 577 } … … 609 579 if (!fHVBoard[i]->WrapOK) { 610 580 PrintMessage(All, "Error: Wrap counter mismatch board %d\n",fHVBoard[i]->GetBoardNumber()); 611 State(ERROR, "Error: Wrap counter mismatch board %d\n",fHVBoard[i]->GetBoardNumber());581 Message(ERROR, "Error: Wrap counter mismatch board %d\n",fHVBoard[i]->GetBoardNumber()); 612 582 } 613 583 … … 615 585 if (fHVBoard[i]->Overcurrent[j]) { 616 586 PrintMessage(All, "Warning: Overcurrent in chain %d of board %d\n",j,fHVBoard[i]->GetBoardNumber()); 617 State(WARN, "Warning: Overcurrent in chain %d of board %d\n",j,fHVBoard[i]->GetBoardNumber());587 Message(WARN, "Warning: Overcurrent in chain %d of board %d\n",j,fHVBoard[i]->GetBoardNumber()); 618 588 ResetBoard(i); 619 589 } 620 590 } 621 591 } 592 593 // Unlock 594 if ((Ret = pthread_mutex_unlock(&Mutex)) != 0) { 595 Message(FATAL, "pthread_mutex_lock() failed in commandHandler() (%s)", strerror(Ret)); 596 } 597 622 598 } 623 599 … … 651 627 void ProcessIO::commandHandler() { 652 628 653 pthread_mutex_lock(&control_mutex); 629 int Ret; 630 631 if ((Ret = pthread_mutex_lock(&Mutex)) != 0) { 632 Message(FATAL, "pthread_mutex_lock() failed in commandHandler() (%s)", strerror(Ret)); 633 } 634 654 635 if (getCommand() == Command) CommandControl(getCommand()->getString()); 655 pthread_mutex_unlock(&control_mutex); 636 637 if ((Ret = pthread_mutex_unlock(&Mutex)) != 0) { 638 Message(FATAL, "pthread_mutex_unlock() failed in commandHandler() (%s)", strerror(Ret)); 639 } 656 640 } 657 641 -
hvcontrol/src/ProcessIO.h
r220 r226 33 33 PixelMap *pm; 34 34 DimCommand *Command; 35 DimService *ConsoleOut; 36 char *ConsoleText; 35 37 36 38 void commandHandler(); … … 39 41 HVCalib *calib; 40 42 HVBoard **fHVBoard; 41 42 pthread_mutex_t control_mutex;43 43 44 44 char Prompt[MAX_COM_SIZE]; … … 57 57 // Status variables 58 58 pthread_t HVMonitor; // exit function sends signal to these threads 59 pthread_mutex_t Mutex; 59 60 60 61 int NumHVBoards; 61 62 int FirstBoard; 62 63 int LastBoard; 63 int FirstChain;64 int LastChain;65 66 64 state_enum state; 67 bool Exit;68 65 69 66 // Methods … … 87 84 void cmd_start(); void cmd_stop(); 88 85 void cmd_uptime(); void cmd_help(); 89 void cmd_chain();90 86 }; 91 87
Note:
See TracChangeset
for help on using the changeset viewer.