323 lines
7.6 KiB
C++
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;
|
|
}
|