Changeset 10128
- Timestamp:
- 02/04/11 12:32:51 (14 years ago)
- Location:
- fact/FADctrl
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
fact/FADctrl/FAD.cc
r10120 r10128 27 27 {"srclk", &FAD::cmd_srclk, true, 1, "<on|off>", "Set SRCLK"}, 28 28 {"sclk", &FAD::cmd_sclk, true, 1, "<on|off>", "Set SCLK"}, 29 {"trigger", &FAD::cmd_trigger, false, 0, "[n|cont |stop|enable|disable]", "Issue software triggers"},29 {"trigger", &FAD::cmd_trigger, false, 0, "[n|cont [rate]|stop|enable|disable]", "Issue software triggers"}, 30 30 {"roi", &FAD::cmd_roi, true, 2, "<channel range> <value>", "Set region-of-interest to value"}, 31 31 {"dac", &FAD::cmd_dac, true, 2, "<range> <value>", "Set DAC numbers in range to value"}, … … 61 61 EventUpdateDelay = atof(GetConfig("EventUpdateDelay", "0.5").c_str()); 62 62 63 // Create pipe for data exchange 63 // Create pipe for command execution and data exchange 64 if (pipe(CommandPipe) == -1) Message(FATAL, "pipe() failed in FAD::FAD() (%s)", strerror(errno)); 64 65 if (pipe(Pipe) == -1) Message(FATAL, "pipe() failed in FAD::FAD() (%s)", strerror(errno)); 65 66 … … 67 68 ConsoleOut = new DimService(SERVER_NAME"/ConsoleOut", (char *) ""); 68 69 70 // Initialise configuration information (later non-blocking access in commandHandler()) 71 GetConfig("CalibTempDiffWarn", "0"); 72 69 73 // Construct boards 70 74 BoardList = Tokenize(GetConfig("BoardList")); … … 75 79 // Check if initialised OK 76 80 if (!Boards.back()->InitOK) { 77 Message(WARN, "Failed to initialize board %s \n", BoardList[i].c_str());81 Message(WARN, "Failed to initialize board %s", BoardList[i].c_str()); 78 82 delete Boards.back(); 79 83 Boards.pop_back(); … … 83 87 // Create DIM event service thread 84 88 int Ret; 85 if ((Ret = pthread_create(&Thread, NULL, (void * (*)(void *)) LaunchEventThread, (void *) this)) != 0) {89 if ((Ret = pthread_create(&Thread, NULL, (void * (*)(void *)) LaunchEventThread, (void *) this)) != 0) { 86 90 Message(FATAL, "pthread_create() failed in FAD::FAD() (%s)", strerror(Ret)); 87 91 } 92 93 // Create command handling thread 94 DimThread::start(); 88 95 89 96 // Install DIM command (after all initialized) … … 99 106 100 107 // Close pipe (will make read() on pipe in DIM service thread return) 101 if (close(Pipe[0]) == -1) Message(ERROR, "close() on Pipe[0] failed in FAD::~FAD() (%s)", strerror(errno));; 102 if (close(Pipe[1]) == -1) Message(ERROR, "close() on Pipe[1] failed in FAD::~FAD() (%s)", strerror(errno));; 103 104 // Wait for DIM service thread to quit 108 if (close(Pipe[0]) == -1) Message(ERROR, "close() on Pipe[0] failed in FAD::~FAD() (%s)", strerror(errno)); 109 if (close(Pipe[1]) == -1) Message(ERROR, "close() on Pipe[1] failed in FAD::~FAD() (%s)", strerror(errno)); 110 if (close(CommandPipe[0]) == -1) Message(ERROR, "close() on CommandPipe[0] failed in FAD::~FAD() (%s)", strerror(errno)); 111 if (close(CommandPipe[1]) == -1) Message(ERROR, "close() on CommandPipe[1] failed in FAD::~FAD() (%s)", strerror(errno)); 112 113 // Wait for command and DIM service thread to quit 105 114 if ((Ret = pthread_join(Thread, NULL)) != 0) Message(ERROR, "pthread_join() failed in ~FAD() (%s)", strerror(Ret)); 106 115 … … 118 127 119 128 // 120 // DIM command handler 121 // Handler must be non-blocking, otherwise a DIM rpc would dead-lock. 129 // DIM command handler (non-blocking, otherwise a DIM rpc would dead-lock) 122 130 // 123 131 void FAD::commandHandler() { 124 132 125 char *Command = getCommand()->getString();126 127 133 // Ignore empty or illegal strings 128 if (getCommand()->getSize() == 0 || *(Command+getCommand()->getSize()-1) != '\0' || 129 strlen(Command) == 0) return; 130 131 // Shell command 132 if (Command[0]=='.') { 133 system(&(Command[1])); 134 return; 135 } 136 137 // Parse command into tokens 138 Parameter.clear(); 139 char *Start; 140 while(true) { 141 while (isspace(*Command)) Command++; // Ignore initial white spaces 142 if(*Command=='\0') break; 143 if (*Command == '\"') { 144 Start = ++Command; 145 while(*Command!='\"' && *Command!='\0') Command++; 146 } 147 else { 148 Start = Command; 149 while(!isspace(*Command) && *Command!='\0') Command++; 150 } 151 if(*Command != '\0') *Command++ = '\0'; 152 Parameter.push_back(Start); 153 } 154 155 // Search for command in command list 156 for(unsigned int i=0; i<sizeof(CommandList)/sizeof(CL_Struct); i++) { 157 if (Match(Parameter[0], CommandList[i].Name)) { 158 // Check if number of parameters 159 if(Parameter.size()-1 < CommandList[i].MinNumParameter) { 160 PrintMessage("Usage: %s %s\n", CommandList[i].Name, CommandList[i].Parameters); 161 return; 162 } 163 // Check if idle mode required 164 if (CommandList[i].NeedIdle && Mode != idle) { 165 PrintMessage("Current mode is not idle ('stop' will stop current operation)\n"); 166 return; 167 } 168 // Jump to command function 169 (this->*CommandList[i].CommandPointer)(); 170 return; 171 } 172 } 173 174 PrintMessage("Unknown command '%s'\n", Parameter[0].c_str()); 134 if (getCommand()->getSize() == 0 || *(getCommand()->getString()+getCommand()->getSize()-1) != '\0' || 135 strlen(getCommand()->getString()) == 0) return; 136 137 // Send command to command execution thread 138 if (write(CommandPipe[1], getCommand()->getData(), getCommand()->getSize()) == -1) { 139 Message(ERROR, "write() to CommandPipe[1] failed in class FAD::commandHandler() (%s)", strerror(errno)); 140 } 141 } 142 143 // 144 // Command execution thread 145 // 146 void FAD::threadHandler() { 147 148 char *Command, *Start, Buffer[1000]; 149 int Ret; 150 unsigned int n; 151 152 while (!ExitRequest) { 153 if ((Ret=read(CommandPipe[0], Buffer, sizeof(Buffer))) == -1) Message(ERROR, "read() from CommandPipe[0] failed in FAD::threadHandler() (%s)", strerror(errno)); 154 155 // Check if pipe closed 156 if (Ret == 0) break; 157 158 // Shell command 159 if (Buffer[0]=='.') { 160 system(&(Buffer[1])); 161 continue; 162 } 163 164 // Parse command into tokens 165 Parameter.clear(); 166 Command = Buffer; 167 while(true) { 168 while (isspace(*Command)) Command++; // Ignore initial white spaces 169 if(*Command=='\0') break; 170 if (*Command == '\"') { 171 Start = ++Command; 172 while(*Command!='\"' && *Command!='\0') Command++; 173 } 174 else { 175 Start = Command; 176 while(!isspace(*Command) && *Command!='\0') Command++; 177 } 178 if(*Command != '\0') *Command++ = '\0'; 179 Parameter.push_back(Start); 180 } 181 182 // Search for command in command list 183 for(n=0; n<sizeof(CommandList)/sizeof(CL_Struct); n++) { 184 if (Match(Parameter[0], CommandList[n].Name)) break; 185 } 186 187 // Command not found? 188 if (n == sizeof(CommandList)/sizeof(CL_Struct)) { 189 PrintMessage("Unknown command '%s'\n", Parameter[0].c_str()); 190 continue; 191 } 192 193 // Check if number of parameters 194 if(Parameter.size()-1 < CommandList[n].MinNumParameter) { 195 PrintMessage("Usage: %s %s\n", CommandList[n].Name, CommandList[n].Parameters); 196 continue; 197 } 198 199 // Check if idle mode required 200 if (CommandList[n].NeedIdle && Mode != idle) { 201 PrintMessage("Current mode is not idle ('stop' will stop current operation)\n"); 202 continue; 203 } 204 205 // Jump to command function 206 (this->*CommandList[n].CommandPointer)(); 207 } // while() 208 } 209 210 // 211 // DIM exit handler (overwriting handler in Evidence class) 212 // 213 void FAD::exitHandler(int Code) { 214 215 Message(INFO, "Exit handler called (DIM exit code %d)", Code); 216 pthread_kill(MainThread, SIGTERM); 175 217 } 176 218 … … 260 302 261 303 int Num; 262 304 263 305 for (unsigned int i=0; i<Boards.size(); i++) { 264 306 if (Parameter.size() == 1) Boards[i]->Send(CMD_Trigger); 265 307 else if (ConvertToInt(Parameter[1], &Num)) { 266 for (int j=0; j<Num; j++) { 267 Boards[i]->Send(CMD_Trigger); 268 usleep(10000); 308 for (int j=0; j<Num; j++) Boards[i]->Send(CMD_Trigger); 309 } 310 else if (Match(Parameter[1],"continuous")) { 311 Boards[i]->Send(CMD_Trigger_C); 312 if (Parameter.size() == 3 && ConvertToInt(Parameter[2], &Num)) { 313 if (Num == 0) Boards[i]->Send(CMD_Trigger_S); 314 else Boards[i]->Send(0x2100 + (unsigned char) (1000.0/Num/12.5)); 269 315 } 270 316 } 271 else if (Match(Parameter[1],"continuous")) Boards[i]->Send(CMD_Trigger_C);272 317 else if (Match(Parameter[1],"stop")) Boards[i]->Send(CMD_Trigger_S); 273 318 else if (Match(Parameter[1],"enable")) Boards[i]->Send(CMD_TRIGGERS_ON); … … 278 323 } 279 324 } 280 281 if (Match(Parameter[1],"enable")) PrintMessage("All active boards accept incoming triggers\n");282 else if (Match(Parameter[1],"disable")) PrintMessage("No active board accepts incoming triggers\n");283 325 } 284 326 … … 452 494 struct tm *T = localtime(&Time); 453 495 char Filename[500]; 496 double Temp; 454 497 455 498 // Set number of requested events … … 466 509 } 467 510 511 // Check conditions for run of all active boards 512 float MaxDiff = atof(GetConfig("CalibTempDiffWarn").c_str()); 513 514 for (unsigned int i=0; i<Boards.size(); i++) { 515 if (!Boards[i]->Active) continue; 516 517 if (Boards[i]->ACalibTime == -1) PrintMessage("Warning: Amplitude calibration missing for board %d\n", i); 518 else { 519 Temp = 0; 520 for (unsigned int j=0; j<NTemp; j++) Temp += Boards[i]->GetStatus().Temp[j] / NTemp; 521 if (fabs(Boards[i]->ACalibTemp-Temp) > MaxDiff) PrintMessage("Warning: Amplitude calibration to current temperature difference larger than %.1f K for board %d\n", MaxDiff, i); 522 } 523 } 524 468 525 // Start run 469 526 Mode = datarun; 470 PrintMessage("Starting run with %d events, filename '%s'\n", NumEventsRequested, Filename);527 Message(INFO, "Starting run with %d events, filename '%s'", NumEventsRequested, Filename); 471 528 } 472 529 … … 543 600 } 544 601 545 // Start ca ;ibration by setting mode602 // Start calibration by setting mode 546 603 Mode = acalib; 604 Message(INFO, "Starting amplitude calibration run with 3x%d events", NumEventsRequested); 547 605 } 548 606 … … 563 621 } 564 622 565 PrintMessage(" Number of FAD boards: %d Boards with communication error: %dActive boards: ", Boards.size(), Error);623 PrintMessage("Total boards: %d (%d communication errors) Active boards: ", Boards.size(), Error); 566 624 567 625 // Print list of active boards … … 591 649 if (i<R.Min || i > R.Max) continue; 592 650 651 PrintMessage("BOARD #%d (%sactive) IP %s Communication %s\n", i, Boards[i]->Active ? "":"in", Boards[i]->Name, Boards[i]->CommError ? "ERROR":"OK"); 652 653 // Calibration information 654 if (Boards[i]->ACalibTime == -1) PrintMessage("No amplitude calibration available\n"); 655 else PrintMessage("Calibration temperature %.1f Calibration time %s" , Boards[i]->ACalibTemp, ctime(&Boards[i]->ACalibTime)); 656 657 // Status information 593 658 struct FADBoard::BoardStatus S = Boards[i]->GetStatus(); 594 659 595 PrintMessage("Board #%d - %s (%sactive) Communication %s\n", i, Boards[i]->Name, Boards[i]->Active ? "":"in", Boards[i]->CommError ? "ERROR":"OK"); 660 if (S.Update.tv_sec == -1) { 661 PrintMessage("No event received yet, no further status information available\n"); 662 continue; 663 } 664 PrintMessage("Last event received %s", ctime(&S.Update.tv_sec)); 665 596 666 PrintMessage("Board ID %d Firmware revision %d\n", S.BoardID, S.FirmwareRevision); 597 667 PrintMessage("DAC %d %d %d %d %d %d %d %d\n", S.DAC[0], S.DAC[1], S.DAC[2], S.DAC[3], S.DAC[4], S.DAC[5], S.DAC[6], S.DAC[7] ); 598 668 PrintMessage("Temperature %.2f %.2f %.2f %.2f", S.Temp[0], S.Temp[1], S.Temp[2], S.Temp[3]); 599 669 600 for (unsigned int i=0; i<NChips*NChannels; i++) {601 if ( i%NChannels == 0) PrintMessage("\nROI %2d-%2d: ", i, i+NChannels-1);602 PrintMessage("%4d ", S.ROI[ i/NChannels][i%NChannels]);670 for (unsigned int j=0; j<NChips*NChannels; j++) { 671 if (j%NChannels == 0) PrintMessage("\nROI %2d-%2d: ", j, j+NChannels-1); 672 PrintMessage("%4d ", S.ROI[j/NChannels][j%NChannels]); 603 673 } 604 674 PrintMessage("\n"); 605 606 675 /*PrintMessage("Serial %d, firmware %d\n" 607 " Actual temperature: %1.1lf C\n"608 " Calibration temp.: %1.1lf C\n"609 676 GetBoard(i)->GetBoardSerialNumber(), 610 GetBoard(i)->GetFirmwareVersion(),611 ACalibTemp[i]);612 613 677 614 678 if (GetBoard(i)->GetStatusReg() & BIT_RUNNING) … … 619 683 else 620 684 PrintMessage(" DMODE single shot\n"); 621 if (GetBoard(i)->GetCtrlReg() & BIT_ACAL_EN) 622 PrintMessage(" ACAL enabled\n"); 623 PrintMessage(" Trigger bus: 0x%08X\n", GetBoard(i)->GetTriggerBus()); 624 else PrintMessage(" Domino wave stopped\n"); 625 } 685 626 686 }*/ 627 687 } // for() … … 667 727 double Delay; 668 728 669 if (Parameter.size()==2 && ConvertToDouble(Parameter[1], &Delay) && Delay> 0) EventUpdateDelay = Delay;729 if (Parameter.size()==2 && ConvertToDouble(Parameter[1], &Delay) && Delay>=0) EventUpdateDelay = Delay; 670 730 else PrintUsage(); 671 731 } … … 707 767 } 708 768 709 if (Mode == acalib) Mode = idle; 710 769 if (Mode == acalib) { 770 Mode = idle; 771 Message(INFO, "Mode set to IDLE"); 772 } 773 711 774 if (Mode == datarun) { 712 775 // Inform event thread to stop run in case datarun active … … 798 861 RunStart = LastUpdate; // only to avoid 'uninitialized' warning from compiler 799 862 800 // Create DIM event data service863 // Create DIM event data and number services 801 864 int EventSize = sizeof(RunHeader)+ Boards.size()*sizeof(BoardStructure)+sizeof(EventHeader) + Boards.size()*(NChips*NChannels*NBins*sizeof(short) + NChips*sizeof(int)); 802 char *EventData = new char [EventSize]; 803 DimService *EventService = new DimService (SERVER_NAME"/EventData", (char *) "C", NULL, 0); 865 char *EventData = new char [EventSize]; 804 866 805 867 memset(EventData, 0, EventSize); 868 869 DimService EventService(SERVER_NAME"/EventData", (char *) "C", NULL, 0); 870 DimService EventNumService(SERVER_NAME"/EventNumber", NumEvents); 806 871 807 872 // Calculate pointers to EventData array … … 818 883 RHeader->EventHeaderSize = sizeof(EventHeader); 819 884 RHeader->BoardStructureSize = sizeof(BoardStructure); 820 RHeader->SoftwareRevision = 0xFFFF; // Update885 RHeader->SoftwareRevision = atoi(REVISION) * (strchr(REVISION, 'M')==NULL ? 1:-1); 821 886 RHeader->Identification = 0; 822 887 … … 841 906 // Wait for data from TCP/IP reading threads 842 907 if ((Ret=read(Pipe[0], Buffer, sizeof(Buffer))) == -1) Message(FATAL, "read() from Pipe[0] failed in FAD::EventThread() (%s)", strerror(errno)); 908 909 // Check if pipe closed 910 if (Ret == 0) break; 911 843 912 IDString = string(Buffer, Ret); 844 913 845 914 // If amplitude calibration mode, check if board finished procedure 846 915 if (Mode == acalib) { … … 854 923 SaveAmplitudeCalibration(); 855 924 Mode = idle; 925 Message(INFO, "Amplitude calibration done, mode set to IDLE"); 856 926 } 857 927 } … … 888 958 889 959 Datafile = -1; 890 Mode = idle; 960 Mode = idle; 961 Message(INFO, "Data run ended, mode set to IDLE"); 891 962 } 892 963 … … 919 990 for(unsigned int i=0; i<NChips; i++) TriggerCell[Brd*NChips+i] = (int) S.TriggerCell[i]; 920 991 921 // Write channel data (12 bit signed tw is complement with out-of-range-bit and leading zeroes)992 // Write channel data (12 bit signed two's complement with out-of-range-bit and leading zeroes) 922 993 int Count = 0; 923 994 memset(Data, 0, Boards.size()*NChips*NChannels*NBins*sizeof(short)); … … 949 1020 if ((Time.tv_sec-LastUpdate.tv_sec)*1e6 + Time.tv_usec-LastUpdate.tv_usec > EventUpdateDelay*1e6) { 950 1021 gettimeofday(&LastUpdate, NULL); 951 EventService->updateService(EventData, EventSize); 1022 EventService.updateService(EventData, EventSize); 1023 EventNumService.updateService(); 952 1024 } 953 1025 … … 975 1047 // Write data to file 976 1048 if(write(Datafile, EventData+Offset, EventSize-Offset) != (ssize_t) EventSize-Offset) { 977 PrintMessage("Error: Could not write all data to file, terminating run (%s)\n", strerror(errno));1049 Message(ERROR, "Could not write all data to file, terminating run, setting mode to IDLE (%s)", strerror(errno)); 978 1050 979 1051 // Close file if error 980 if (close(Datafile) == -1) PrintMessage("Error: Could not close data file (%s)\n", strerror(errno));1052 if (close(Datafile) == -1) Message(ERROR, "Could not close data file (%s)", strerror(errno)); 981 1053 Datafile = -1; 982 1054 Mode = idle; … … 988 1060 } 989 1061 990 // Clean up991 1062 delete[] BStruct; 992 delete EventService;993 1063 delete[] EventData; 1064 994 1065 } 995 1066 -
fact/FADctrl/FAD.h
r10120 r10128 25 25 26 26 27 class FAD: public EvidenceServer {27 class FAD: public EvidenceServer, public DimThread { 28 28 29 29 public: … … 39 39 void PrintUsage(); 40 40 void commandHandler(); 41 void threadHandler(); 42 virtual void exitHandler(int); 41 43 bool Match(std::string, const char *); 42 44 void EventThread(); … … 55 57 }; 56 58 59 void ExecuteCommand(); 57 60 bool ConvertToDouble(std::string, double *); 58 61 bool ConvertToInt(std::string, int *); … … 86 89 87 90 int Pipe[2]; 91 int CommandPipe[2]; 88 92 int NumEventsRequested; // Number of events requested 89 93 std::vector<std::string> BoardList; -
fact/FADctrl/FADBoard.cc
r10120 r10128 427 427 PrevStatus = Status; 428 428 429 // Lock to avoid concurrent access in GetStatus()429 // Wait until event thread processed the previous data and lock to avoid concurrent access in GetStatus() 430 430 Lock(); 431 432 // Wait until event thread processed the previous data433 431 while (!Continue) { 434 432 if ((Ret = pthread_cond_wait(&CondVar, &Mutex)) != 0) { … … 436 434 } 437 435 } 438 439 436 gettimeofday(&Status.Update, NULL); 440 437 -
fact/FADctrl/FADctrl.cc
r10120 r10128 27 27 28 28 // Construct main instance (static ensures destructor is called with exit()) 29 static FAD M;29 static class FAD M; 30 30 31 31 // Do not kill process if writing to closed socket 32 signal(SIGPIPE, SIG_IGN);32 signal(SIGPIPE, SIG_IGN); 33 33 34 34 // Initialise all boards … … 43 43 DimClient::sendCommand(SERVER_NAME"/Command", "trigger enable"); 44 44 M.PrintMessage("Finished initalizing all boards\n"); 45 45 46 46 // Command loop 47 47 char *Command; -
fact/FADctrl/History.txt
r10120 r10128 9 9 24/1/2011 Integrated amplitude calibration into FADBoard class 10 10 27/1/2011 Moved OpenOtherSockets() to FADBoard class 11 2/2/2011 Warning if amplitude calibration missing for data taking 12 4/2/2011 Fixed exitHandler() being stuck at pthread_join()
Note:
See TracChangeset
for help on using the changeset viewer.