/********************************************************************\ Interface to FACT bias voltage crate \********************************************************************/ #include "Crate.h" #include "ProcessIO.h" // Must be not in HV.h to avoid problem with declaring class ProcessIO using namespace std; // // Constructor // Crate::Crate(string CrateName, int Number, class ProcessIO *PIO) { struct termios tio; // Initialize InitOK = false; 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; } // 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) { SystemReset(); close(fDescriptor); } 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 int Crate::Communicate(unsigned char* wbuf, int Bytes) { unsigned char rbuf[3]; int N, Ret = 0; fd_set SelectDescriptor; struct timeval WaitTime = {(long) m->fTimeOut, (long) ((m->fTimeOut-(long) m->fTimeOut)*1e6)}; // === Lock file descriptor === if (lockf(fDescriptor, F_LOCK, 0) == -1) { m->Message(m->ERROR, "Failed to lock file descriptor (%s)", strerror(errno)); return 0; } // === 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 until time-out === 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)) { Ret = -1; goto ExitCommunicate; } // Read data if ((N = read(fDescriptor, &rbuf, 1)) == -1) { m->Message(m->ERROR, "Read error (%s)", strerror(errno)); ErrorCount++; goto ExitCommunicate; } // === Update status information if three bytes were returned === if (N == 3) { // This data only valid for channel set or channel read LastCurrent = rbuf[1] + (rbuf[0]&15)*256; LastOC = rbuf[0] & 128; ResetHit = rbuf[2] & 128; // Check wrap counter if (WrapCount != -1) { if ((WrapCount+1)%8 == ((rbuf[0]>>4) & 7)) WrapOK = true; else WrapOK = false; } WrapCount = (rbuf[0]>>4) & 7; Ret = 1; } // === UnLock file descriptor === ExitCommunicate: if (lockf(fDescriptor, F_LOCK, 0) == -1) { m->Message(m->ERROR, "Failed to lock file descriptor (%s)", strerror(errno)); return 0; } return Ret; } // // System reset of bias crate // int Crate::SystemReset() { unsigned char wbuf[] = {0,0,0}; int ret; if((ret = Communicate(wbuf, 3)) == 1) { ClearVoltageArrays(); ErrorCount = 0; } return ret; } // // 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}; int ret; if ((ret = Communicate(wbuf, 3)) == 1) { Current[Board][Channel] = LastCurrent; OC[Board][Channel] = LastOC; } return ret; } // ***** Global set ***** int Crate::GlobalSet(unsigned int SetPoint) { // Check limit if (SetPoint > 0x0FFF) { m->PrintMessage("Error: Voltage DAC value above 0x0FFF\n"); return 0; } // Execute command unsigned char wbuf[] = {1<<6 , SetPoint>>8, SetPoint}; int ret; if ((ret = Communicate(wbuf, 3)) == 1) { 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}; int ret; if ((ret = Communicate(wbuf, 3)) == 1) { DAC[Board][Channel] = SetPoint; Current[Board][Channel] = LastCurrent; OC[Board][Channel] = LastOC; } return ret; } // ***** Synchronize board ***** bool Crate::Synch() { unsigned char wbuf = 0; int Trial = 0, ret; while(++Trial <= 3) { if((ret = Communicate(&wbuf, 1)) == 1) return true; if (ret == 0) break; } return false; } // ***** Set all voltages of board to zero ***** void Crate::ClearVoltageArrays() { for (int i=0; iupdateService(); }