/******************************************************************************* * * * Société de Transports de Montréal. * * 2012 - 2013 * * * * Projet Zones Tests * * * * * * * *******************************************************************************/ /* Description: Cette classe constitue un thread qui exécute la lecture des modules d'I/O externes via le port Ethernet. */ /* ************************************************************************** */ /* Revision: ### YYYMMDD JFM Verision d'origine. ### YYYYMMDD Description du besoin ou du bug Description du changement. */ /* ************************************************************************** */ #include "ExtIOThread.h" CExtIOThread::CExtIOThread() : QObject() { mInputModule = 0; mOutputModule = 0; mAnalogInputModule = 0; mCurInputs = 0xFFFFFFFF; mCurAnalogInput = 0; mOutputDirty = false; mRun = true; mIsRunning = false; mCurAnalogChannel = 0; mAnalogModulePresent = false; } unsigned int CExtIOThread::BindPointers(CInputModule *InputModule, COutputModule *OutputModule, CAnalogInputModule *AnalogModule, int AnalogChannel) { mInputModule = InputModule; mOutputModule = OutputModule; mAnalogInputModule = AnalogModule; mCurAnalogChannel = AnalogChannel; if(mAnalogInputModule != 0) { mAnalogModulePresent = true; } return RET_OK; } unsigned int CExtIOThread::GetInputs() { unsigned int inputs; mMutex.lock(); inputs = mCurInputs; mMutex.unlock(); return inputs; } unsigned int CExtIOThread::GetInputBuf() { return GetInputs(); } unsigned int CExtIOThread::SetOutput(quint32 buffer) { COutputTransaction NewTransaction; NewTransaction.mOutputsWord = buffer; NewTransaction.mOutputTransaction = OUTPUT_MODULE_SET_OUTPUT_WORD; mMutex.lock(); mOutputTransactionList.append(NewTransaction); mMutex.unlock(); return RET_OK; } unsigned int CExtIOThread::SetOutput(unsigned char *buffer) { COutputTransaction NewTransaction; memcpy(&NewTransaction.mOutputsBuf,buffer,4); NewTransaction.mOutputTransaction = OUTPUT_MODULE_SET_OUTPUT_BUF; mMutex.lock(); mOutputTransactionList.append(NewTransaction); mMutex.unlock(); return RET_OK; } unsigned int CExtIOThread::SetOutputFlags(quint32 Flags) { COutputTransaction NewTransaction; NewTransaction.mOutputsWord = Flags; NewTransaction.mOutputTransaction = OUTPUT_MODULE_SET_OUTPUT_FLAGS; mMutex.lock(); mOutputTransactionList.append(NewTransaction); mMutex.unlock(); return RET_OK; } unsigned int CExtIOThread::ClearOutputFlags(quint32 Flags) { COutputTransaction NewTransaction; NewTransaction.mOutputsWord = Flags; NewTransaction.mOutputTransaction = OUTPUT_MODULE_CLEAR_OUTPUT_FLAGS; mMutex.lock(); mOutputTransactionList.append(NewTransaction); mMutex.unlock(); return RET_OK; } unsigned int CExtIOThread::ToggleOutputFlags(quint32 Flags) { COutputTransaction NewTransaction; NewTransaction.mOutputsWord = Flags; NewTransaction.mOutputTransaction = OUTPUT_MODULE_TOGGLE_OUTPUT_FLAGS; mMutex.lock(); mOutputTransactionList.append(NewTransaction); mMutex.unlock(); return RET_OK; } ///ATTENTION !!!!!!!!!!!!!!!!! //// //Le paramètre Channel n'est pas géré en tant que tel //lors de l'écriture de la fonction, un seul channel (SDF) est utilisé. //Si d'autres entrées analogiques sont ajoutées, il faudra gérer les //différents channels. unsigned int CExtIOThread::GetAnalogInput(int Channel, int *data) { Q_UNUSED(Channel) mMutex.lock(); *data = mCurAnalogInput; mMutex.unlock(); return RET_OK; } unsigned int CExtIOThread::GetAnalogInput(int Channel, double &data) { Q_UNUSED(Channel) mMutex.lock(); data = (double)mCurAnalogInput; mMutex.unlock(); return RET_OK; } unsigned int CExtIOThread::StopAcquisition() { mMutex.lock(); mRun = false; mMutex.unlock(); return RET_OK; } void CExtIOThread::DoAcquisition() { bool Run = true; mDigitalInputsPeriodTimer.start(); mAnalogInputsTimer.start(); #ifdef OUTPUT_EXTIO_SAMPLE_RATE mSampleRateTimer.start(); #endif mMutex.lock(); mIsRunning = true; mMutex.unlock(); while(Run == true) { //JFM 20140821 // Read analog inputs if(mAnalogInputModule != 0) { if(mAnalogInputsTimer.nsecsElapsed() >= EXT_ANALOG_INPUT_ACQUISITION_PERIOD) //help relax the communication with the modules { int AnalogInput; mAnalogInputModule->GetAnalogInput(mCurAnalogChannel,&AnalogInput); mMutex.lock(); mCurAnalogInput = AnalogInput; mMutex.unlock(); mAnalogInputsTimer.restart(); } } //Read discreete inputs if(mDigitalInputsPeriodTimer.elapsed() >= EXT_DIGITAL_INPUTS_ACQUISITION_PERIOD) { unsigned int Input = mInputModule->GetInputBuf(); mMutex.lock(); mCurInputs = Input; mMutex.unlock(); mDigitalInputsPeriodTimer.restart(); } //Refresh outputs if necessary bool OutputDirty = false; COutputTransaction OutputTransaction; mMutex.lock(); if(mOutputTransactionList.size() != 0) { OutputDirty = true; OutputTransaction = mOutputTransactionList.takeFirst(); } mMutex.unlock(); if(OutputDirty == true) { switch(OutputTransaction.mOutputTransaction) { case OUTPUT_MODULE_SET_OUTPUT_BUF: { mOutputModule->SetOutput(OutputTransaction.mOutputsBuf); break; } case OUTPUT_MODULE_SET_OUTPUT_WORD: { mOutputModule->SetOutput(OutputTransaction.mOutputsWord); break; } case OUTPUT_MODULE_SET_OUTPUT_FLAGS: { mOutputModule->SetOutputFlags(OutputTransaction.mOutputsWord); break; } case OUTPUT_MODULE_CLEAR_OUTPUT_FLAGS: { mOutputModule->ClearOutputFlags(OutputTransaction.mOutputsWord); break; } case OUTPUT_MODULE_TOGGLE_OUTPUT_FLAGS: { mOutputModule->ToggleOutputFlags(OutputTransaction.mOutputsWord); break; } } } mMutex.lock(); Run = mRun; mMutex.unlock(); #ifdef OUTPUT_EXTIO_SAMPLE_RATE mMutex.lock(); mDelay = mSampleRateTimer.elapsed(); mMutex.unlock(); mSampleRateTimer.restart(); #endif } mMutex.lock(); mIsRunning = false; mMutex.unlock(); //qDebug("Ext IO Thread exit"); } bool CExtIOThread::IsAnalogModueDetected() { return mAnalogModulePresent; } bool CExtIOThread::IsThreadRunning() { bool Running; mMutex.lock(); Running = mIsRunning; mMutex.unlock(); return Running; } #ifdef OUTPUT_EXTIO_SAMPLE_RATE qint64 CExtIOThread::GetSampleRate() { qint64 temp; mMutex.lock(); temp = mDelay; mMutex.unlock(); return temp; // return mSampleRateTimer.nsecsElapsed(); } #endif COutputTransaction &COutputTransaction::operator =(const COutputTransaction& a) { mOutputsBuf[0] = a.mOutputsBuf[0]; mOutputsBuf[1] = a.mOutputsBuf[1]; mOutputsBuf[2] = a.mOutputsBuf[2]; mOutputsBuf[3] = a.mOutputsBuf[3]; mOutputTransaction = a.mOutputTransaction; mOutputsWord = a.mOutputsWord; return *this; }