/********************************************************************\ Interface to FACT bias voltage crate \********************************************************************/ #include "Crate.h" #include "User.h" // Must not be in header file to avoid problem with declaring class User using namespace std; // // Constructor // Crate::Crate(string CrateName, int Number, class User *PIO) { struct termios tio; // Initialize InitOK = false; File = NULL; m = PIO; Name = new char [CrateName.size()+1]; strcpy(Name, CrateName.c_str()); CrateNumber = Number; WrapCount = -1; for (int i=0; iPrintMessage("Error: Could not open device %d/%s (%s)\n", CrateNumber, Name, strerror(errno)); return; } // Generate FILE pointer if ((File = fdopen(fDescriptor, "rb+")) == NULL) { m->PrintMessage("Error: fdopen() failed on device %d/%s (%s)\n", CrateNumber, Name, strerror(errno)); return; } // Get current serial port settings if (tcgetattr(fDescriptor, &tio) == -1) { m->PrintMessage("Error: tcgetattr() failed on device %s (%s)\n", Name, strerror(errno)); return; } // Set baudrate and raw mode if (cfsetspeed(&tio, BAUDRATE) == -1) { m->PrintMessage("Error: Could not set baud rate of device %s (%s)\n", Name, strerror(errno)); return; } cfmakeraw(&tio); if (tcsetattr(fDescriptor, TCSANOW, &tio ) == -1) { m->PrintMessage("Error: tcsetattr() failed on device %s (%s)\n", Name, strerror(errno)); return; } InitOK = true; } // // Destructor (Resets board) // Crate::~Crate() { if(fDescriptor != -1) { GlobalSet(0); SystemReset(); if (File == NULL) { if (close(fDescriptor) == -1) m->PrintMessage("Error closing device %s (%s)\n", Name, strerror(errno)); } else if (fclose(File) != 0) m->PrintMessage("Error closing device %s\n", Name); } delete NameService; delete BiasVolt; delete[] Name; } // Communicate: Write and read from HV Board until time-out has been reached // // Returns: 0 error, 1 success, -1 time-out exceeded vector Crate::Communicate(unsigned char* wbuf, int Bytes) { int N; fd_set SelectDescriptor; struct timeval WaitTime = {(long) m->fTimeOut, (long) ((m->fTimeOut-(long) m->fTimeOut)*1e6)}; char Buffer[10000]; vector Data; // === Lock device === flockfile(File); // === Write data === if ((N = write(fDescriptor, wbuf, Bytes)) < Bytes) { if (N == -1) m->Message(m->ERROR, "Could not write data to crate (%s)", strerror(errno)); else m->Message(m->ERROR, "Could write only %d of %d bytes to board", N, Bytes); ErrorCount++; goto ExitCommunicate; } // === Try to read back data with time-out === do { FD_ZERO(&SelectDescriptor); FD_SET(fDescriptor, &SelectDescriptor); if (select(fDescriptor+1, &SelectDescriptor, NULL, NULL, &WaitTime)==-1) { m->Message(m->ERROR, "Error with select() (%s)", strerror(errno)); goto ExitCommunicate; } // Time-out expired? if (!FD_ISSET(fDescriptor, &SelectDescriptor)) { Data.push_back(-1); goto ExitCommunicate; } // Read data if ((N = read(fDescriptor, Buffer, sizeof(Buffer))) == -1) { m->Message(m->ERROR, "Read error (%s)", strerror(errno)); ErrorCount++; goto ExitCommunicate; } // Add data to buffer for (int i=0; i>4) & 7)) WrapOK = true; else WrapOK = false; } WrapCount = (Data[i]>>4) & 7; } // === UnLock file descriptor === ExitCommunicate: funlockfile(File); if (Data.empty()) Data.push_back(0); return Data; } // // System reset of bias crate // int Crate::SystemReset() { unsigned char wbuf[] = {0,0,0}; vector Data = Communicate(wbuf, 3); if (Data.size() == 3) { ClearVoltageArrays(); ErrorCount = 0; return 1; } return Data[0]; } // // Read channel status // int Crate::ReadChannel(unsigned int Board, unsigned int Channel) { // Check limits if (Board > MAX_NUM_BOARDS) { m->PrintMessage("Error: Board number out of range\n"); return 0; } if (Channel > NUM_CHANNELS) { m->PrintMessage("Error: Channel number out of range\n"); return 0; } // Execute command unsigned char wbuf[] = {1<<5 | Board<<1 | (Channel&16)>>4, Channel<<4, 0}; vector Data = Communicate(wbuf, 3); if (Data.size() == 3) { Current[Board][Channel] = Data[1] + (Data[0]&15)*256; OC[Board][Channel] = Data[0] & 128; ResetHit = Data[2] & 128; if (Board==2 && Channel==19) OC[Board][Channel] = false; return 1; } return Data[0]; } // // Read all channels status // int Crate::ReadAll() { unsigned char wbuf[3*MAX_NUM_BOARDS*NUM_CHANNELS]; int Count = 0; // Prepare command to read all channels for (int i=0; i>4; wbuf[Count++] = j<<4; wbuf[Count++] = 0; } // Execute command vector Data = Communicate(wbuf, 3*MAX_NUM_BOARDS*NUM_CHANNELS); if (Data.size() != 3*MAX_NUM_BOARDS*NUM_CHANNELS) return Data[0]; //Evaluate returned data Count = 0; for (int i=0; i 0x0FFF) { m->PrintMessage("Error: Voltage DAC value above 0x0FFF\n"); return 0; } // Execute command unsigned char wbuf[] = {1<<6 , SetPoint>>8, SetPoint}; vector Data = Communicate(wbuf, 3); if (Data.size() == 3) { for (int i=0; i 0x0FFF) { m->PrintMessage("Error: Voltage DAC value above 0x0FFF\n"); return 0; } if (Board > MAX_NUM_BOARDS) { m->PrintMessage("Error: Board number out of range\n"); return 0; } if (Channel > NUM_CHANNELS) { m->PrintMessage("Error: Channel number out of range\n"); return 0; } // Execute command unsigned char wbuf[] = {3<<5 | Board<<1 | (Channel&16)>>4, Channel<<4 | SetPoint>>8, SetPoint}; vector Data = Communicate(wbuf, 3); if (Data.size() == 3) { DAC[Board][Channel] = SetPoint; Volt[Board][Channel] = (double) SetPoint / 0xfff * 90; return 1; } return Data[0]; } // ***** Channel set ***** int Crate::SetAll() { unsigned char wbuf[3*MAX_NUM_BOARDS*NUM_CHANNELS]; double Volt = 10; int Count=0; for (int i=0; i>4; wbuf[Count++] = j<<4 | ((int) (Volt/90*0x0fff))>>8; wbuf[Count++] = (int) (Volt/90*0x0fff); Volt += 0.2; } // Execute command vector Data = Communicate(wbuf, 3*MAX_NUM_BOARDS*NUM_CHANNELS); if (Data.size() == 3*MAX_NUM_BOARDS*NUM_CHANNELS) { //DAC[Board][Channel] = SetPoint; //Volt[Board][Channel] = (double) SetPoint / 0xfff * 90; return 1; } return Data[0]; } // ***** Synchronize board ***** bool Crate::Synch() { unsigned char wbuf = 0; int Trial = 0; vector Data; while(++Trial <= 3) { Data = Communicate(&wbuf, 1); if (Data.size() == 3) return true; if (Data[0] == 0) break; } return false; } // ***** Determine offset for current measurement ***** bool Crate::CurrentCalib(double Voltage) { // Set voltage of all channels and wait for current to settle if (GlobalSet((int) (Voltage/90*0xfff)) != 1) return false; sleep(1); // Measure current of all channels if (ReadAll() != 1) return false; for (int i=0; iupdateService(); }