/********************************************************************\ Interface to FACT bias voltage crate \********************************************************************/ #include #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 BiasDAC; delete BiasCurrent; 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(string Buf) { 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, Buf.data(), Buf.size())) < (int) Buf.size()) { 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, Buf.size()); 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)) { 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() { vector Data = Communicate(string(3, 0)); if (Data.size() == 3) { ErrorCount = 0; return 1; } return 0; } // // Read all channels status // int Crate::ReadAll() { string Buf; // Prepare command to read all channels for (int i=0; i>4); Buf.push_back(j<<4); Buf.push_back(0); } // Execute command vector Data = Communicate(Buf); if (Data.size() != Buf.size()) return 0; // Evaluate data returned from crate int Count = 0; for (int i=0; i>8)) + char(SetPoint)); vector Data = Communicate(Buf); if (Data.size() == 3) { for (int i=0; i V) { string Buf; if (V.empty()) return 1; // Build and execute commands for (map::const_iterator it = V.begin(); it != V.end(); ++it) { // If DAC value unchanged, do not send command if (DAC[it->first/NUM_CHANNELS][it->first%NUM_CHANNELS] == it->second/90.0*0x0fff) continue; // Add command to buffer Buf += char(3<<5) | char(it->first/NUM_CHANNELS<<1 & 0x0f) | char((it->first%NUM_CHANNELS&16)>>4 & 1); Buf += char(it->first%NUM_CHANNELS<<4) | ((((unsigned int) (it->second/90.0*0x0fff))>>8) & 0x0f); Buf += char(it->second/90.0*0x0fff); } vector Data = Communicate(Buf); // Store new voltage values of successful if (Data.size() == Buf.size()) { for (map::const_iterator it = V.begin(); it != V.end(); ++it) { DAC[it->first/NUM_CHANNELS][it->first%NUM_CHANNELS] = (unsigned int) (it->second/90.0*0x0fff); Volt[it->first/NUM_CHANNELS][it->first%NUM_CHANNELS] = it->second; RefVolt[it->first/NUM_CHANNELS][it->first%NUM_CHANNELS] = it->second; } return 1; } return 0; } // ***** Synchronize board ***** bool Crate::Synch() { int Trial = 0; vector Data; while(++Trial <= 3) { Data = Communicate(string(1, 0)); if (Data.size() == 3) return true; } 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; i= MAX_NUM_BOARDS*NUM_CHANNELS) return 0; else return Volt[Channel/NUM_CHANNELS][Channel%NUM_CHANNELS]; } // ***** Return DAC value of given channel ***** unsigned int Crate::GetDAC(unsigned int Channel) { if (Channel >= MAX_NUM_BOARDS*NUM_CHANNELS) return 0; else return DAC[Channel/NUM_CHANNELS][Channel%NUM_CHANNELS]; } // ***** Return current of given channel ***** float Crate::GetCurrent(unsigned int Channel) { if (Channel >= MAX_NUM_BOARDS*NUM_CHANNELS) return 0; else return Current[Channel/NUM_CHANNELS][Channel%NUM_CHANNELS]-CurrentOffset[Channel/NUM_CHANNELS][Channel%NUM_CHANNELS]; } // ***** Update DIM services ***** void Crate::UpdateDIM() { BiasVolt->updateService(); BiasDAC->updateService(); } // ***** Set reference current for dynamic mode ***** void Crate::SetRefCurrent() { for (int i=0; i Voltages; for (int i=0; i 5) { LastUpdate = time(NULL); UpdateDIM(); } }