#define _Brooks0254GlobPar_ #include "Brooks0254BasePar.hh" #include "Brooks0254Chassis.hh" // Typed class for Brooks0254 global parameters for chassis // The card number for these parmaters is not defined. // All methods lock the object and unlock when complete or // when calling another method which locks the object. template class Brooks0254GlobPar : virtual public Brooks0254BasePar { protected: VarType bpWriteVal; // Parameter value from the opratator VarType bpReadVal; // Parameter value from the device string MakeReadString(); string MakeWriteString( VarType val ); VarType FetchValue(); // Read value from device VarType WriteValue( VarType val ); // Write value to device inline bool CommIsOK() {return 1;} public: Brooks0254GlobPar( Brooks0254Module& module, Brooks0254ParID parID ) : Brooks0254Module( module ), Brooks0254BasePar( module, parID ), bpWriteVal(0), bpReadVal(0) { Brooks0254GlobPar::Sync(1); } Brooks0254GlobPar( Brooks0254GlobPar& par ) : Brooks0254BasePar(par), bpWriteVal(par.bpWriteVal), bpReadVal(par.bpReadVal) {;} Brooks0254GlobPar& operator=( const Brooks0254GlobPar& par ); //! Return Brooks number for global variables, although it is not //! expected to be used. inline unsigned BrooksPortNumber() { return ( 2*Brooks0254Chassis::bcCardMax+1); }; //! Method to synchronize the values in the driver and the hardware void Sync( bool dir = 0 ); inline VarType GetReadValue( ) { MtxLock scopeLock( bmMutex ); return bpReadVal; } inline VarType GetWriteValue( ) { MtxLock scopeLock( bmMutex ); return bpWriteVal; } inline VarType SetReadValue( const VarType val ) { MtxLock scopeLock( bmMutex ); return ( bpReadVal = val ); } inline VarType SetWriteValue( const VarType val ) { MtxLock scopeLock( bmMutex ); return ( bpWriteVal = val ); } }; //! Begining of the template class implementation //! Copy operator template Brooks0254GlobPar& Brooks0254GlobPar::operator=( const Brooks0254GlobPar& par ) { if( this == &par ) return *this; Brooks0254BasePar::operator=( par ); MtxLock scopeLock( bmMutex ); bpWriteVal = par.bpWriteVal; bpReadVal = par.bpReadVal; return (*this); } //! This method cheks if the set value is different from the readback, //! and if it is theb it sets the new value into the hardware template void Brooks0254GlobPar::Sync( bool syncDir ) { //! Always read value from the hardware for all parameters VarType tmpVal = FetchValue(); MtxLock scopeLock( bmMutex ); bpReadVal = tmpVal; unsigned parNum = bbpID.GetNum() ; if( bmDebFlag > 1 ) { cout << "Read " << bpReadVal << " for parameter " << parNum << endl; cout << "Difference is " << bpWriteVal - bpReadVal << endl; } //! Check the difference between the value in the driver and in the //! actual hardware and sync them for settable parameters. if( fabs( bpWriteVal - bpReadVal ) > bbpID.GetTolerance() ) { if( syncDir == 0 ) { //! Set values for updatable parameters cout << "**************************************************" << endl; cout << "Updating global parameter " << parNum << endl; cout << "Old value is " << bpReadVal << " , new value " << bpWriteVal << endl; cout << "**************************************************" << endl; scopeLock.Unlock(); VarType newVal = WriteValue( bpWriteVal ); scopeLock.Lock(); bpReadVal = newVal; } else { //! Initilize the parameters from the hardware scopeLock.Unlock(); VarType newVal = FetchValue(); scopeLock.Lock(); bpWriteVal = bpReadVal = newVal; if( bmDebFlag > 1 ) { cout << "Starting with hardware values " << bpReadVal << " for parameter " << parNum << endl; } } } if( bmDebFlag ) cout << "Paramter #" << parNum << " is unlocked" << endl; return; } //! Fetch the bool and int value of the parameter from the device template VarType Brooks0254GlobPar::FetchValue() { string readString = MakeReadString(); MtxLock scopeLock( bmMutex ); unsigned parNum = bbpID.GetNum() ; if( bmDebFlag ) { cout << "Fetch: Paramter " << parNum << " is locked" << endl; cout << "Port address is " << bmPort << endl; } //! Send the string to the device using the serial port object string respRaw = bmPort->Send( readString, true ); if( bmDebFlag ) cout << "Raw response " << respRaw << endl; string response = RemoveComas( respRaw ); if( bmDebFlag ) cout << "Final response " << response << endl; // Dummy variable for reading message char d1[128], d2[128], d3[128], d4[128], d5[128]; VarType val; stringstream ssResp; ssResp << response; //! For all other parameters directly read off the value from the //! response string ssResp >> d1 >> d2 >> d3 >> d4 >> val >> d5; return static_cast ( val ); } //! Write the value of the parameter into the device template VarType Brooks0254GlobPar::WriteValue( VarType val ) { if( bbpID.BadRange( val ) ) { cerr << "Brooks0254GlobPar::WriteValue(): Bad value for parameter type <" << bbpID.GetDir() << "," << bbpID.GetNum() << ">" << endl; return FetchValue(); } string writeString = MakeWriteString( val ); MtxLock localLock( bmMutex ); bmPort->Send( writeString, true ); localLock.Unlock(); return FetchValue(); } //! Create the string to request a readout template string Brooks0254GlobPar::MakeReadString() { unsigned chanPort = BrooksPortNumber(); MtxLock scopeLock( bmMutex ); unsigned parNum = bbpID.GetNum() ; stringstream ssMsg; ssMsg << "AZ" << setw(5) << setfill('0') << bmAddr << "." << setw(2) << chanPort << "P" << parNum << "?"; return ssMsg.str() ; } //! This fucntion should work with booleans and integers template string Brooks0254GlobPar::MakeWriteString( VarType val ) { unsigned chanPort = BrooksPortNumber(); MtxLock localLock( bmMutex ); stringstream ssMsg; //! For all arameters directly write value into the //! string stream ssMsg << "AZ" << setw(5) << setfill('0') << bmAddr << "." << setw(2) << chanPort << "P" << bbpID.GetNum() << "="; ssMsg << setfill(' ') << setprecision(bbpDecPoint) << fixed << val; cout << "Build the follwoing message " << ssMsg.str() << endl; return string( ssMsg.str() ); }