ZT/sources/ExtIOThread.cpp

323 lines
7.6 KiB
C++

/*******************************************************************************
* *
* 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;
}