source: hvcontrol/src/ProcessIO.cc@ 222

Last change on this file since 222 was 220, checked in by ogrimm, 16 years ago
hv command allows array of voltages (for use by feedback)
File size: 21.4 KB
Line 
1
2/********************************************************************\
3
4 ProcessIO.cc
5
6 Main class processing user input
7
8 Sebastian Commichau, Sabrina Stark-Schneebeli, Oliver Grimm
9
10\********************************************************************/
11
12#include "ProcessIO.h"
13
14static char* state_str[] = {"active", "stopped", "n.a."};
15
16// Branch table for command evaluation
17static 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
40using namespace std;
41
42ProcessIO::ProcessIO(): EvidenceServer(SERVER_NAME) {
43
44 // Get program start time
45 time (&StartTime);
46
47 // Initialize status variables
48 state = active;
49 Exit = false;
50
51 NumHVBoards = 0;
52 FirstBoard = 0;
53 LastBoard = -1;
54 FirstChain = 0;
55 LastChain = NUM_CHAINS-1;
56
57 // Get configuration data
58 char *Boards = GetConfig("Boards");
59 fPixMapTable = GetConfig("PixMapTable");
60 fTimeOut = atof(GetConfig("TimeOut"));
61 fStatusRefreshRate = atof(GetConfig("StatusRefreshRate"));
62 DACMin = atoi(GetConfig("DACMin"));
63 DACMax = atoi(GetConfig("DACMax"));
64 fHVCalibOffset = atof(GetConfig("HVCalibOffset"));
65 fHVCalibSlope = atof(GetConfig("HVCalibSlope"));
66 fHVMaxDiff = atoi(GetConfig("HVMaxDiff"));
67
68 if (fStatusRefreshRate < MIN_RATE || fStatusRefreshRate > MAX_RATE) fStatusRefreshRate = 1;
69
70 // Open HV devices
71 fHVBoard = new HVBoard* [strlen(Boards)];
72 char *Token = strtok(Boards, " \t");
73 while (Token != NULL) {
74 fHVBoard[NumHVBoards] = new HVBoard(NumHVBoards, Token, this);
75 if(fHVBoard[NumHVBoards]->fDescriptor >= 0) {
76 PrintMessage("Synchronized and reset board %d (%s)\n",NumHVBoards,fHVBoard[NumHVBoards]->BoardName);
77 NumHVBoards++;
78 }
79 else {
80 PrintMessage(All, "Failed to synchronize board %d (%s)\n",NumHVBoards,fHVBoard[NumHVBoards]->BoardName);
81 delete fHVBoard[NumHVBoards];
82 }
83 Token = strtok(NULL, " \t");
84 }
85 LastBoard = NumHVBoards-1;
86
87 // Create instances
88 calib = new HVCalib(this);
89 pm = new PixelMap(fPixMapTable);
90
91 // Install DIM command (after all initialized)
92 Command = new DimCommand((char *) SERVER_NAME"/Command", (char *) "C", this);
93}
94
95
96ProcessIO::~ProcessIO() {
97
98 delete Command;
99
100 for (int i=0; i<NumHVBoards; i++) delete fHVBoard[i];
101 delete[] fHVBoard;
102
103 delete pm; delete calib;
104}
105
106
107// Process user input
108void ProcessIO::CommandControl(char *Command) {
109
110 // Ignore empty commands
111 if (strlen(Command)==0) return;
112
113 // Shell command
114 if(Command[0]=='.') {
115 system(&(Command[1]));
116 return;
117 }
118
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
155void ProcessIO::cmd_board() {
156
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
183void 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
204void 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
223void 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
236void 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");
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
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
321void 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
379void 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
399void ProcessIO::cmd_reset() {
400
401 for (int i=FirstBoard; i<=LastBoard; i++) ResetBoard(i);
402}
403
404// Save bias settings of all boards
405void 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
439void ProcessIO::cmd_start() {
440
441 state = active;
442 pthread_kill(HVMonitor, SIGUSR1);
443 PrintMessage(All, "Status monitoring activated\n");
444}
445
446// Print status
447void 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
478void 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
486void 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}
498
499// Print uptime
500void 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
508void ProcessIO::cmd_exit() {
509
510 Exit = true;
511 pthread_kill(HVMonitor, SIGUSR1);
512}
513
514
515// Print message to selected target
516void ProcessIO::PrintMessage(MsgTarget Target, const char *Format, ...) {
517
518 va_list ArgumentPointer;
519 va_start(ArgumentPointer, Format);
520 DoPrintMessage(Format, ArgumentPointer, Target);
521 va_end(ArgumentPointer);
522}
523
524// Print message to log file, and screen or socket (depending on command origin)
525void ProcessIO::PrintMessage(const char *Format, ...) {
526
527 va_list ArgumentPointer;
528 va_start(ArgumentPointer, Format);
529 DoPrintMessage(Format, ArgumentPointer, Console);
530 va_end(ArgumentPointer);
531}
532
533// Function doing the actual printing work
534// Be careful with overloading variadic functions!
535void ProcessIO::DoPrintMessage(const char *Format, va_list ArgumentPointer, MsgTarget Target) {
536
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);
541
542 // Print to console
543 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);
548 fflush(stdout);
549 }
550
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 }
563}
564
565// Ramp to new voltage with maximum step size given in fHVMaxDiff
566// No ramping when decreasing voltage
567bool ProcessIO::RampVoltage(unsigned int Target, int Board, int Chain, int Channel) {
568
569 while (fHVBoard[Board]->HV[Chain][Channel] != (int) Target) {
570 int Diff = Target - fHVBoard[Board]->HV[Chain][Channel];
571 if (Diff > (int) fHVMaxDiff) Diff = fHVMaxDiff;
572
573 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);
575 return false;
576 }
577 }
578
579 return true;
580}
581
582
583// Check board status (ignore board if it has more than 10 read/write errors)
584void ProcessIO::Monitor() {
585
586 static bool Warned = false;
587
588 for (int i=0; i<NumHVBoards; i++) {
589 if (fHVBoard[i]->ErrorCount > 10) {
590 if (!Warned) {
591 Warned = true;
592 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");
594 }
595 continue;
596 }
597
598 if (fHVBoard[i]->GetStatus() != 1) {
599 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());
601 }
602
603 if (fHVBoard[i]->ResetButton) {
604 PrintMessage(All, "Manual reset of board %d\n",fHVBoard[i]->GetBoardNumber());
605 State(INFO, "Manual reset of board %d\n",fHVBoard[i]->GetBoardNumber());
606 ResetBoard(i);
607 }
608
609 if (!fHVBoard[i]->WrapOK) {
610 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());
612 }
613
614 for (int j=0; j<NUM_CHAINS; j++) {
615 if (fHVBoard[i]->Overcurrent[j]) {
616 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());
618 ResetBoard(i);
619 }
620 }
621 }
622}
623
624
625// Send reset to board and clear voltage arrays
626void ProcessIO::ResetBoard(int i) {
627
628 if (fHVBoard[i]->Reset() == 1) {
629 PrintMessage("Reset of board %d\n", fHVBoard[i]->GetBoardNumber());
630 PrintBoardStatus(i);
631 }
632 else PrintMessage("Error: Could not reset board %d\n",fHVBoard[i]->GetBoardNumber());
633}
634
635
636// Print current board status
637void ProcessIO::PrintBoardStatus(int i) {
638
639 PrintMessage("Status board %d (%s): MR %s OC0 %s OC1 %s OC2 %s OC3 %s WC %s (%d)\n",
640 fHVBoard[i]->GetBoardNumber(), fHVBoard[i]->BoardName,
641 fHVBoard[i]->ResetButton ? "yes" : "no",
642 fHVBoard[i]->Overcurrent[0] ? "yes" : "no",
643 fHVBoard[i]->Overcurrent[1] ? "yes" : "no",
644 fHVBoard[i]->Overcurrent[2] ? "yes" : "no",
645 fHVBoard[i]->Overcurrent[3] ? "yes" : "no",
646 fHVBoard[i]->WrapOK ? "ok":"error", fHVBoard[i]->LastWrapCount);
647}
648
649
650// Command handling (mutex needed because of monitor thread)
651void ProcessIO::commandHandler() {
652
653 pthread_mutex_lock(&control_mutex);
654 if (getCommand() == Command) CommandControl(getCommand()->getString());
655 pthread_mutex_unlock(&control_mutex);
656}
657
658// Check if two strings match (min 1 character must match)
659bool 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;
661}
662
663
664// Convert string to double
665// Returns false if conversion did not stop on whitespace or EOL character
666bool ConvertToDouble(string String, double *Result) {
667
668 char *EndPointer;
669
670 *Result = strtod(String.c_str(), &EndPointer);
671 if(!isspace(*EndPointer) && *EndPointer!='\0') return false;
672 return true;
673}
674
675
676// Convert string to int
677// Returns false if conversion did not stop on whitespace or EOL character
678bool ConvertToInt(string String, int *Result) {
679
680 char *EndPointer;
681
682 *Result = (int) strtol(String.c_str(), &EndPointer, 0);
683 if(!isspace(*EndPointer) && *EndPointer!='\0') return false;
684 return true;
685}
Note: See TracBrowser for help on using the repository browser.