/* * BaseIUParBusStatus.cpp * * Class to handle the status parameter for an entire CAN-bus * * Created on: Jan 12, 2015 * Author: Hovanes Egiyan */ #include "BaseIUParBusStatus.hh" BaseIUParBusStatus::BaseIUParBusStatus(string name, BaseIUModule& board) : BaseIUParStatus(name, board) { if (bmDebFlag > 5) { cout << "BaseIUParBusStatus::BaseIUParBusStatus() : Main constructor is invoked " << " for STATUS parameter at address " << bmAddress << endl; cout << "BaseIUParBusStatus object is at " << hex << showbase << this << endl; } return; } BaseIUParBusStatus::BaseIUParBusStatus(string name) : BaseIUParStatus(name) { if( bmDebFlag > 5 ) { cout << "BaseIUParBusStatus::BaseIUParBusStatus() : Short constructor is invoked " << " for STATUS parameter named at address " << bmAddress << endl; cout << "BaseIUParBusStatus object is at " << hex << showbase << this << endl; } return; } //! Copy constructor BaseIUParBusStatus::BaseIUParBusStatus( const BaseIUParBusStatus& par ) : BaseIUParStatus( par ) { if( bmDebFlag > 5 ) { cout << "BaseIUParBusStatus::BaseIUParBusStatus() : Copy constructor is invoked" << endl; cout << "BaseIUParBusStatus object is at " << hex << showbase << this << endl; } this->operator=( par ); return; } BaseIUParBusStatus::~BaseIUParBusStatus() { if (bmDebFlag > 5) { cout << "BaseIUParBusStatus::~BaseIUParBusStatus() : Destructor for STATUS parameter " << bvpType << " : " << bvpName << " has been called" << endl; } return; } //! Assignment operator BaseIUParBusStatus& BaseIUParBusStatus::operator=( const BaseIUParBusStatus& constPar ) { if( bmDebFlag > 5 ) { cout << "BaseIUParBusStatus::operator=() : Assignment operator is called" << endl; } //! Do not do anything if assigned to itself if( this == &constPar ) return *this; //! Call the assignment operator for the base class BaseIUParStatus::operator=( constPar ); return *this; } //! Cloning function defined for polymorphism for copy constructor //! Invokes the copy constructor for this class and returns the //! the address of the resulting object. BaseIUVirtPar* BaseIUParBusStatus::CloneParameter() { if( bmDebFlag > 5 ) { cout << "BaseIUParBusStatus::CloneParameter() : Cloning STATUS parameter " << " named " << bvpName << endl; } BaseIUParBusStatus* tmpPar = new BaseIUParBusStatus( *this ) ; return dynamic_cast( tmpPar ); } //! Request read of this STATUS for all boards on the bus void BaseIUParBusStatus::ReadRequest( BaseIUDevice* dev, string name ) { if( bmDebFlag > 1 ) { cout << "BaseIUParBusStatus::ReadRequest() : Requesting readback for parameters " << bvpType << " : " << name << endl; } // Use the ReadRequest for board status since the status of the bus is // decided after reading the statuses of individual boards. BaseIUParStatus::ReadRequest( dev, name ); return; } //! Method to sync the parameters. All this method does for //! this type of parameters is read the current value. bool BaseIUParBusStatus::Sync(bool syncFromHW) { if (bmDebFlag > 1) { cout << "BaseIUParBusStatus::Sync() : Synching parameter " << bvpType << " : " << bvpName << " for address " << bmAddress << endl; } //! Process FIFO and assign the readout value bool syncSuccessful = ProcessDeque(true); // cout << "BaseIUParBusStatus::Sync() : Synching parameter " << bvpType // << " : " << bvpName << " for address " << bmAddress << " on port " // << bmDevice->GetPortName() << endl; // cout << "Last value read is " << (int) bpsReadValue << "(" // << ReadToWrite(bpsReadValue) << ")" << endl; // cout << "Object pointer is " << hex << showbase << dynamic_cast(this) << endl; //! Set the write value to the value that matches the pin statuses read from the hardware uint16_t newWriteVal = ReadToWrite(bpsReadValue); if (bmDebFlag > 1) { cout << "BaseIUParBusStatus::Sync() : Will change the existing write value " << bpsWriteValue << " to " << newWriteVal << endl; } bpsWriteValue = newWriteVal; return syncSuccessful; } //! Get the deque after sending read request and process it to //! retrieve the parameter value on the board. If there was not //! message found then the return value is false. Otherwise it is true. bool BaseIUParBusStatus::ProcessDeque( bool clearFlag ) { if( bmDebFlag > 1 ) { cout << "BaseIUParBusStatus::ProcessDeque() : Processing deque for parameter " << bvpType << " : " << bvpName << " for address " << hex << showbase << bmAddress << endl; } bool msgFound = false; //! Get all messages for this address from the FIFO, and remove them from //! the FIFO. Since each parameter is processed at a time there should not //! be messages for this address related to other parameters. deque msgDeque = bmDevice->GetDeque( bmAddress, clearFlag ); if( msgDeque.size() < 1 ) { if( bmDebFlag > 1 ) { cout << "BaseIUParBusStatus::ProcessDeque() : Received empty deque" << endl; } return msgFound; } //! Loop through the messages and if the command byte matches, //! read the status bpsReadValue = 0xFF; // Start with all 8 bits set // Loop through all messages for this command and "AND" it with the existing response. for( unsigned iMsg = 0; iMsg < msgDeque.size(); iMsg++ ) { BaseIUMessage& msg = msgDeque[iMsg]; //! Check that the command byte in the message is the same as the //! command byte for this parameter. The opposite should not happen, //! so this is more of a precaution measure. if( msg[0] == BaseIUParStatus::bpsComndByte ) { int statusVal = msg[1]; MtxLock objLock( bmMutex ); bpsReadValue &= statusVal ; // AND with status word from previous messages msgFound = true; } } // cout << "Read sstatus value of " << hex << (int)bpsReadValue << " (" << ReadToWrite(bpsReadValue) << ") for parameter " << // bvpType << " : " << bvpName << " for address " << hex << showbase << bmAddress << " on port " << bmDevice->GetPortName() << endl; if( !msgFound ) bpsReadValue = 0; if( bmDebFlag > 1 ) { cout << "BaseIUParBusStatus::ProcessDeque() : Read value " << static_cast( bpsReadValue )<< " for parameter " << bvpType << " : " << bvpName << " for address " << hex << showbase << bmAddress << endl; } return msgFound; } //! Set the value for the status word which will be written out to //! the board based on the requested status for a particular pin. uint16_t BaseIUParBusStatus::SetPinStatus(const string pinName, const bool status) { if (bmDebFlag > 1) { cout << "BaseIUParBusStatus::SetPinStatus() : Setting pin " << pinName << " to " << status << endl; } // cout << "BaseIUParBusStatus::SetPinStatus() : Setting pin " << pinName // << " to " << status << endl; MtxLock globLock(bmGlobMutex); int nElms = bpsPinMaskMap.count(pinName); globLock.Unlock(); MtxLock objLock(bmMutex); if (nElms > 0) { // cout << "Start value is " << bpsWriteValue << endl; // cout << "Read value corresponds to " << ReadToWrite(bpsReadValue) << endl; // uint16_t startVal = bpsWriteValue; uint16_t startVal = bpsReadValue; objLock.Unlock(); uint16_t writeVal = SetPinToWrite(pinName, status, startVal); objLock.Lock(); bpsWriteValue = writeVal; // cout << "End value is " << bpsWriteValue << endl; BaseIUMessage cmdMsg; // Actually send the value to the bus. Sync for this class does not // send request (no real synching), it is done here at processing. cmdMsg << BaseIUCommand::HV_INIT; cmdMsg << ((bpsWriteValue & 0xFF00) >> 8); // separate the first byte cmdMsg << (bpsWriteValue & 0x00FF); // separate the second byte if (bmDebFlag > 1) { cout << "BaseIUParBusStatus::Sync() : Will write by sending message " << cmdMsg << " to address " << bmAddress << endl; cout << "Write two-byte value is " << bpsWriteValue << endl; } //! Send the command try { bmDevice->Send(bmAddress, cmdMsg); } catch ( BaseIUDevice::FailedWriteDevice& err ) { cerr << "BaseIUParBusStatus::SetPinStatus caugh and exception: " << err.GetMessage() << endl; return -1; } } return bpsWriteValue; }