Changeset 10128


Ignore:
Timestamp:
02/04/11 12:32:51 (14 years ago)
Author:
ogrimm
Message:
Warning for data taking if amplitude calibration not done
Location:
fact/FADctrl
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • fact/FADctrl/FAD.cc

    r10120 r10128  
    2727   {"srclk", &FAD::cmd_srclk, true, 1, "<on|off>", "Set SRCLK"},
    2828   {"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"},
    3030   {"roi", &FAD::cmd_roi, true, 2, "<channel range> <value>", "Set region-of-interest to value"},
    3131   {"dac", &FAD::cmd_dac, true, 2, "<range> <value>", "Set DAC numbers in range to value"},
     
    6161  EventUpdateDelay = atof(GetConfig("EventUpdateDelay", "0.5").c_str());
    6262
    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));
    6465  if (pipe(Pipe) == -1) Message(FATAL, "pipe() failed in FAD::FAD() (%s)", strerror(errno));
    6566
     
    6768  ConsoleOut = new DimService(SERVER_NAME"/ConsoleOut", (char *) "");
    6869
     70  // Initialise configuration information (later non-blocking access in commandHandler())
     71  GetConfig("CalibTempDiffWarn", "0");
     72
    6973  // Construct boards
    7074  BoardList = Tokenize(GetConfig("BoardList"));
     
    7579        // Check if initialised OK
    7680        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());
    7882          delete Boards.back();
    7983          Boards.pop_back();
     
    8387  // Create DIM event service thread
    8488  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) {
    8690    Message(FATAL, "pthread_create() failed in FAD::FAD() (%s)", strerror(Ret));
    8791  }
     92
     93  // Create command handling thread
     94  DimThread::start();
    8895
    8996  // Install DIM command (after all initialized)
     
    99106
    100107  // 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
    105114  if ((Ret = pthread_join(Thread, NULL)) != 0) Message(ERROR, "pthread_join() failed in ~FAD() (%s)", strerror(Ret));
    106115
     
    118127
    119128//
    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)
    122130//
    123131void FAD::commandHandler() {
    124132
    125   char *Command = getCommand()->getString();
    126 
    127133  // 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//
     146void 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//
     213void FAD::exitHandler(int Code) {
     214
     215  Message(INFO, "Exit handler called (DIM exit code %d)", Code);
     216  pthread_kill(MainThread, SIGTERM);
    175217}
    176218
     
    260302
    261303  int Num;
    262  
     304
    263305  for (unsigned int i=0; i<Boards.size(); i++) {
    264306        if (Parameter.size() == 1) Boards[i]->Send(CMD_Trigger);
    265307        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));
    269315          }
    270316        }
    271         else if (Match(Parameter[1],"continuous")) Boards[i]->Send(CMD_Trigger_C);
    272317        else if (Match(Parameter[1],"stop")) Boards[i]->Send(CMD_Trigger_S);
    273318        else if (Match(Parameter[1],"enable")) Boards[i]->Send(CMD_TRIGGERS_ON);
     
    278323        }
    279324  }
    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");
    283325}
    284326
     
    452494  struct tm *T = localtime(&Time);
    453495  char Filename[500];
     496  double Temp;
    454497
    455498  // Set number of requested events
     
    466509  }
    467510
     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
    468525  // Start run
    469526  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);
    471528}
    472529
     
    543600  }
    544601
    545   // Start ca;ibration by setting mode
     602  // Start calibration by setting mode
    546603  Mode = acalib;
     604  Message(INFO, "Starting amplitude calibration run with 3x%d events", NumEventsRequested);
    547605}
    548606
     
    563621        }         
    564622
    565         PrintMessage(" Number of FAD boards: %d    Boards with communication error: %d   Active boards: ", Boards.size(), Error);
     623        PrintMessage("Total boards: %d    (%d communication errors)     Active boards: ", Boards.size(), Error);
    566624
    567625        // Print list of active boards
     
    591649        if (i<R.Min || i > R.Max) continue;
    592650
     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
    593658        struct FADBoard::BoardStatus S = Boards[i]->GetStatus();
    594659
    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
    596666        PrintMessage("Board ID %d               Firmware revision %d\n", S.BoardID, S.FirmwareRevision);
    597667        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] );
    598668        PrintMessage("Temperature %.2f %.2f %.2f %.2f", S.Temp[0], S.Temp[1], S.Temp[2], S.Temp[3]);
    599669
    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]);
    603673        }
    604674        PrintMessage("\n");
    605 
    606675        /*PrintMessage("Serial %d, firmware %d\n"
    607                     " Actual temperature:   %1.1lf C\n"
    608                     " Calibration temp.:    %1.1lf C\n"
    609676                    GetBoard(i)->GetBoardSerialNumber(),
    610                     GetBoard(i)->GetFirmwareVersion(),
    611                     ACalibTemp[i]);
    612 
    613677
    614678        if (GetBoard(i)->GetStatusReg() & BIT_RUNNING)
     
    619683        else
    620684          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 
    626686    }*/
    627687  } // for()
     
    667727  double Delay;
    668728 
    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;
    670730  else PrintUsage();
    671731}
     
    707767  }
    708768 
    709   if (Mode == acalib) Mode = idle;
    710  
     769  if (Mode == acalib) {
     770        Mode = idle;
     771        Message(INFO, "Mode set to IDLE");
     772  }
     773
    711774  if (Mode == datarun) { 
    712775        // Inform event thread to stop run in case datarun active
     
    798861  RunStart = LastUpdate; // only to avoid 'uninitialized' warning from compiler
    799862 
    800   // Create DIM event data service
     863  // Create DIM event data and number services
    801864  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];
    804866
    805867  memset(EventData, 0, EventSize);
     868
     869  DimService EventService(SERVER_NAME"/EventData", (char *) "C", NULL, 0);
     870  DimService EventNumService(SERVER_NAME"/EventNumber", NumEvents);
    806871
    807872  // Calculate pointers to EventData array
     
    818883  RHeader->EventHeaderSize = sizeof(EventHeader);
    819884  RHeader->BoardStructureSize = sizeof(BoardStructure);
    820   RHeader->SoftwareRevision = 0xFFFF;   // Update
     885  RHeader->SoftwareRevision = atoi(REVISION) * (strchr(REVISION, 'M')==NULL ? 1:-1);
    821886  RHeader->Identification = 0;
    822887
     
    841906    // Wait for data from TCP/IP reading threads
    842907    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       
    843912        IDString = string(Buffer, Ret);
    844        
     913
    845914        // If amplitude calibration mode, check if board finished procedure
    846915        if (Mode == acalib) {
     
    854923            SaveAmplitudeCalibration();
    855924                Mode = idle;
     925                Message(INFO, "Amplitude calibration done, mode set to IDLE");
    856926          }
    857927        }
     
    888958
    889959          Datafile = -1;
    890           Mode = idle;   
     960          Mode = idle;
     961          Message(INFO, "Data run ended, mode set to IDLE");     
    891962        }
    892963
     
    919990          for(unsigned int i=0; i<NChips; i++) TriggerCell[Brd*NChips+i] = (int) S.TriggerCell[i];
    920991
    921           // Write channel data (12 bit signed twis 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)
    922993          int Count = 0;
    923994          memset(Data, 0, Boards.size()*NChips*NChannels*NBins*sizeof(short));
     
    9491020        if ((Time.tv_sec-LastUpdate.tv_sec)*1e6 + Time.tv_usec-LastUpdate.tv_usec > EventUpdateDelay*1e6) {
    9501021          gettimeofday(&LastUpdate, NULL);
    951           EventService->updateService(EventData, EventSize);
     1022          EventService.updateService(EventData, EventSize);
     1023          EventNumService.updateService();
    9521024        }
    9531025       
     
    9751047        // Write data to file
    9761048        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));
    9781050
    9791051          // 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));
    9811053          Datafile = -1;
    9821054          Mode = idle;
     
    9881060  }
    9891061
    990   // Clean up
    9911062  delete[] BStruct;
    992   delete EventService;
    9931063  delete[] EventData;
     1064
    9941065}
    9951066
  • fact/FADctrl/FAD.h

    r10120 r10128  
    2525
    2626
    27 class FAD: public EvidenceServer {
     27class FAD: public EvidenceServer, public DimThread {
    2828
    2929  public:
     
    3939    void PrintUsage();
    4040        void commandHandler();
     41        void threadHandler();
     42        virtual void exitHandler(int);
    4143        bool Match(std::string, const char *);
    4244        void EventThread();
     
    5557        };
    5658
     59        void ExecuteCommand();
    5760        bool ConvertToDouble(std::string, double *);
    5861        bool ConvertToInt(std::string, int *);
     
    8689       
    8790        int Pipe[2];
     91        int CommandPipe[2];
    8892    int NumEventsRequested;     // Number of events requested
    8993        std::vector<std::string> BoardList;
  • fact/FADctrl/FADBoard.cc

    r10120 r10128  
    427427          PrevStatus = Status;
    428428
    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()
    430430          Lock();
    431 
    432           // Wait until event thread processed the previous data
    433431          while (!Continue) {
    434432                if ((Ret = pthread_cond_wait(&CondVar, &Mutex)) != 0) {
     
    436434                }
    437435          }
    438 
    439436          gettimeofday(&Status.Update, NULL);
    440437
  • fact/FADctrl/FADctrl.cc

    r10120 r10128  
    2727
    2828  // Construct main instance (static ensures destructor is called with exit())
    29   static FAD M;
     29  static class FAD M;
    3030
    3131  // Do not kill process if writing to closed socket
    32   signal(SIGPIPE,SIG_IGN);
     32  signal(SIGPIPE, SIG_IGN);
    3333
    3434  // Initialise all boards
     
    4343  DimClient::sendCommand(SERVER_NAME"/Command", "trigger enable");
    4444  M.PrintMessage("Finished initalizing all boards\n");
    45  
     45
    4646  // Command loop
    4747  char *Command;
  • fact/FADctrl/History.txt

    r10120 r10128  
    9924/1/2011       Integrated amplitude calibration into FADBoard class
    101027/1/2011       Moved OpenOtherSockets() to FADBoard class
     112/2/2011        Warning if amplitude calibration missing for data taking
     124/2/2011        Fixed exitHandler() being stuck at pthread_join()
Note: See TracChangeset for help on using the changeset viewer.