diff --git a/doc/PulseCounting_user_manual-Ind3.doc b/doc/PulseCounting_user_manual-Ind4.doc similarity index 90% rename from doc/PulseCounting_user_manual-Ind3.doc rename to doc/PulseCounting_user_manual-Ind4.doc index 83b25e1104d9c2fad0b8fa49992e08a4b78aed61..b7ebf53f816b912db78d2c157893687a3eed1793 100644 Binary files a/doc/PulseCounting_user_manual-Ind3.doc and b/doc/PulseCounting_user_manual-Ind4.doc differ diff --git a/pom.xml b/pom.xml index f97ad4e8d0081e508f744675ef89914e316eb8fa..44e5d8ce612f9775cdb0c7514c0f21902885a0c4 100644 --- a/pom.xml +++ b/pom.xml @@ -9,7 +9,7 @@ <groupId>fr.soleil.device</groupId> <artifactId>PulseCounting-${aol}-${mode}</artifactId> - <version>1.4.1-SNAPSHOT</version> + <version>1.6.0</version> <packaging>nar</packaging> <name>PulseCounting</name> @@ -43,7 +43,6 @@ <dependency> <groupId>fr.soleil.lib</groupId> <artifactId>NI660Xsl-${aol}-${library}-${mode}</artifactId> - <version>1.4.0</version> </dependency> <dependency> <groupId>fr.soleil.lib</groupId> diff --git a/src/BufferedCounterDt.cpp b/src/BufferedCounterDt.cpp index 88cb94eabd19fa15928e008d37930505696a1e42..e55d40a5fb4e3646cc3f527f5c39f8e6e94874ad 100644 --- a/src/BufferedCounterDt.cpp +++ b/src/BufferedCounterDt.cpp @@ -29,6 +29,7 @@ BufferedCounterDt::BufferedCounterDt (BCEconfig p_conf, NexusManager * storage) this->m_dataBuffer_thread = NULL; m_cntOverrun = false; m_cntTimedout = false; + m_storageError = false; m_data.clear(); m_cfg = p_conf; m_storage_mgr = storage; @@ -144,6 +145,13 @@ void BufferedCounterDt::handle_scaled_buffer(ni660Xsl::InScaledBuffer* buffer, l DEBUG_STREAM << "BufferedCounterDt::handle_scaled_buffer() entering..." << std::endl; DEBUG_STREAM << "BufferedCounterDt::handle_scaled_buffer() - samples to read = " << _samples_read << std::endl; + // check samples number is > 0 + if (_samples_read <= 0) + { + ERROR_STREAM << "BufferedCounterDt::handle_scaled_buffer-> samples to read negative or null value!" << std::endl; + this->stopCnt(); + return; + } yat::AutoMutex<> guard(this->m_buffLock); ni660Xsl::InScaledBuffer& buf = *buffer; @@ -170,12 +178,16 @@ void BufferedCounterDt::handle_scaled_buffer(ni660Xsl::InScaledBuffer* buffer, l catch (Tango::DevFailed & df) { ERROR_STREAM << "BufferedCounterDt::handle_raw_buffer-> pushNexusData caught DevFailed: " << df << std::endl; - // Should we stop acquisition if nx problem? + // We should stop acquisition if nx problem! + this->m_storageError = true; + this->stopCnt(); } catch (...) { ERROR_STREAM << "BufferedCounterDt::handle_raw_buffer-> pushNexusData caugth unknown exception!" << std::endl; - // Should we stop acquisition if nx problem? + // We should stop acquisition if nx problem! + this->m_storageError = true; + this->stopCnt(); } } @@ -205,12 +217,16 @@ void BufferedCounterDt::handle_scaled_buffer(ni660Xsl::InScaledBuffer* buffer, l catch (Tango::DevFailed & df) { ERROR_STREAM << "BufferedCounterDt::handle_raw_buffer-> pushNexusData caught DevFailed: " << df << std::endl; - // Should we stop acquisition if nx problem? + // We should stop acquisition if nx problem! + this->m_storageError = true; + this->stopCnt(); } catch (...) { ERROR_STREAM << "BufferedCounterDt::handle_raw_buffer-> pushNexusData caugth unknown exception!" << std::endl; - // Should we stop acquisition if nx problem? + // We should stop acquisition if nx problem! + this->m_storageError = true; + this->stopCnt(); } } } @@ -269,12 +285,16 @@ void BufferedCounterDt::handle_scaled_buffer(ni660Xsl::InScaledBuffer* buffer, l catch (Tango::DevFailed & df) { ERROR_STREAM << "BufferedCounterDt::handle_raw_buffer-> pushNexusData caught DevFailed: " << df << std::endl; - // Should we stop acquisition if nx problem? + // We should stop acquisition if nx problem! + this->m_storageError = true; + this->stopCnt(); } catch (...) { ERROR_STREAM << "BufferedCounterDt::handle_raw_buffer-> pushNexusData caugth unknown exception!" << std::endl; - // Should we stop acquisition if nx problem? + // We should stop acquisition if nx problem! + this->m_storageError = true; + this->stopCnt(); } } } @@ -299,6 +319,7 @@ void BufferedCounterDt::startCnt() DEBUG_STREAM << "BufferedCounterDt::startCnt() entering..." << endl; this->m_cntOverrun = false; this->m_cntTimedout = false; + this->m_storageError = false; { yat::AutoMutex<> guard(this->m_buffLock); diff --git a/src/BufferedCounterDt.h b/src/BufferedCounterDt.h index ae56eb018be805e4a3bc04db10d7dfcf667767ac..4695548a64bf31ad1a582ffbadd29b481d9523d1 100644 --- a/src/BufferedCounterDt.h +++ b/src/BufferedCounterDt.h @@ -145,6 +145,12 @@ public: return this->m_cntTimedout; } + // has counter stopped on storage error? + bool isStorageKO() + { + return this->m_storageError; + } + protected: // counter config @@ -177,6 +183,9 @@ protected: // timeout flag bool m_cntTimedout; + // Storage error flag + bool m_storageError; + // storage manager NexusManager * m_storage_mgr; }; diff --git a/src/BufferedCounterEvt.cpp b/src/BufferedCounterEvt.cpp index 30ed6d7e51cc1bd782646c76675d23656d35f82d..72ba367c201a793bc03873044349ef5d022f4452 100644 --- a/src/BufferedCounterEvt.cpp +++ b/src/BufferedCounterEvt.cpp @@ -30,6 +30,7 @@ BufferedCounterEvt::BufferedCounterEvt (BCEconfig p_conf, NexusManager * storage this->m_dataBuffer_thread = NULL; m_cntOverrun = false; m_cntTimedout = false; + m_storageError = false; m_data.clear(); m_cfg = p_conf; m_storage_mgr = storage; @@ -135,6 +136,14 @@ void BufferedCounterEvt::handle_raw_buffer(ni660Xsl::InRawBuffer* buffer, long& DEBUG_STREAM << "BufferedCounterEvt::handle_raw_buffer() entering..." << std::endl; DEBUG_STREAM << "BufferedCounterEvt::handle_raw_buffer() - samples to read = " << _samples_read << std::endl; + // check samples number is > 0 + if (_samples_read <= 0) + { + ERROR_STREAM << "BufferedCounterEvt::handle_raw_buffer-> samples to read negative or null value!" << std::endl; + this->stopCnt(); + return; + } + yat::AutoMutex<> guard(this->m_buffLock); ni660Xsl::InRawBuffer& buf = *buffer; @@ -164,12 +173,16 @@ void BufferedCounterEvt::handle_raw_buffer(ni660Xsl::InRawBuffer* buffer, long& catch (Tango::DevFailed & df) { ERROR_STREAM << "BufferedCounterEvt::handle_raw_buffer-> pushNexusData caught DevFailed: " << df << std::endl; - // Should we stop acquisition if nx problem? + // We should stop acquisition if nx problem! + this->m_storageError = true; + this->stopCnt(); } catch (...) { ERROR_STREAM << "BufferedCounterEvt::handle_raw_buffer-> pushNexusData caugth unknown exception!" << std::endl; - // Should we stop acquisition if nx problem? + // We should stop acquisition if nx problem! + this->m_storageError = true; + this->stopCnt(); } } @@ -220,12 +233,16 @@ void BufferedCounterEvt::handle_raw_buffer(ni660Xsl::InRawBuffer* buffer, long& catch (Tango::DevFailed & df) { ERROR_STREAM << "BufferedCounterEvt::handle_raw_buffer-> pushNexusData caught DevFailed: " << df << std::endl; - // Should we stop acquisition if nx problem? + // We should stop acquisition if nx problem! + this->m_storageError = true; + this->stopCnt(); } catch (...) { ERROR_STREAM << "BufferedCounterEvt::handle_raw_buffer-> pushNexusData caugth unknown exception!" << std::endl; - // Should we stop acquisition if nx problem? + // We should stop acquisition if nx problem! + this->m_storageError = true; + this->stopCnt(); } } } @@ -290,12 +307,16 @@ void BufferedCounterEvt::handle_raw_buffer(ni660Xsl::InRawBuffer* buffer, long& catch (Tango::DevFailed & df) { ERROR_STREAM << "BufferedCounterEvt::handle_raw_buffer-> pushNexusData caught DevFailed: " << df << std::endl; - // Should we stop acquisition if nx problem? + // We should stop acquisition if nx problem! + this->m_storageError = true; + this->stopCnt(); } catch (...) { ERROR_STREAM << "BufferedCounterEvt::handle_raw_buffer-> pushNexusData caugth unknown exception!" << std::endl; - // Should we stop acquisition if nx problem? + // We should stop acquisition if nx problem! + this->m_storageError = true; + this->stopCnt(); } } } @@ -330,6 +351,7 @@ void BufferedCounterEvt::startCnt() DEBUG_STREAM << "BufferedCounterEvt::startCnt() entering..." << endl; this->m_cntOverrun = false; this->m_cntTimedout = false; + this->m_storageError = false; { yat::AutoMutex<> guard(this->m_buffLock); diff --git a/src/BufferedCounterEvt.h b/src/BufferedCounterEvt.h index 85f1aae7755548fd294cb2b05665ee20af66b8cf..37beb6fa3ac9b9fa2eafa4d2a0f92e3a2b77f4bb 100644 --- a/src/BufferedCounterEvt.h +++ b/src/BufferedCounterEvt.h @@ -145,6 +145,12 @@ public: return this->m_cntTimedout; } + // has counter stopped on storage error? + bool isStorageKO() + { + return this->m_storageError; + } + protected: // counter config @@ -180,6 +186,9 @@ protected: // timeout flag bool m_cntTimedout; + // Storage error flag + bool m_storageError; + // storage manager NexusManager * m_storage_mgr; }; diff --git a/src/BufferedCounterPeriod.cpp b/src/BufferedCounterPeriod.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9e4033d5c6a2f59ce575e8f280be8644c8807509 --- /dev/null +++ b/src/BufferedCounterPeriod.cpp @@ -0,0 +1,463 @@ +//============================================================================= +// BufferedCounterPeriod.cpp +//============================================================================= +// abstraction.......BufferedCounterPeriod for PulseCounting +// class.............BufferedCounterPeriod +// original author...S.Minolli - Nexeya +//============================================================================= + + +// ============================================================================ +// DEPENDENCIES +// ============================================================================ +#include <yat4tango/LogHelper.h> +#include "BufferedCounterPeriod.h" + +namespace PulseCounting_ns +{ + +// ============================================================================ +// BufferedCounterPeriod::BufferedCounterPeriod () +// ============================================================================ +BufferedCounterPeriod::BufferedCounterPeriod (BCEconfig p_conf, NexusManager * storage) +: yat4tango::TangoLogAdapter(p_conf.hostDevice) +{ + this->m_bufferNbToReceive = 0; + this->m_currentBufferNb = 0; + this->m_firstPtReceivedBuff = 0; + this->m_acquisitionDone = true; + this->m_dataBuffer_thread = NULL; + m_cntOverrun = false; + m_cntTimedout = false; + m_storageError = false; + m_data.clear(); + m_cfg = p_conf; + m_storage_mgr = storage; +} + +// ============================================================================ +// BufferedCounterPeriod::~BufferedCounterPeriod () +// ============================================================================ +BufferedCounterPeriod::~BufferedCounterPeriod () +{ + +} + +// ============================================================================ +// BufferedCounterPeriod::updateRawBuffer +// ============================================================================ +void BufferedCounterPeriod::updateRawBuffer() + throw(Tango::DevFailed) +{ + // Delete "buffer recover" thread if exists and if data recovery is over + if (this->m_dataBuffer_thread) + { + if (this->m_dataBuffer_thread->updateDone()) + { + yat::Thread::IOArg ioa; + this->m_dataBuffer_thread->exit(); + this->m_dataBuffer_thread->join(&ioa); + //std::cout << "BufferedCounterPeriod::updateRawBuffer - BR thread exited for counter " + // << this->m_cfg.cnt.number << std::endl; + this->m_dataBuffer_thread = NULL; + } + } + + // Task the buffer reception if acquisition is on & if previous buffer recovery is over + if ((!this->m_acquisitionDone) && + (this->m_dataBuffer_thread == NULL)) + { + this->m_dataBuffer_thread = new BRPRThread(m_cfg.hostDevice, static_cast<yat::Thread::IOArg>(this)); + DEBUG_STREAM << "BufferedCounterPeriod Thread created ..." << endl; + if (this->m_dataBuffer_thread == NULL) + { + ERROR_STREAM << "Buffer recovery cannot be tasked for counter " + << this->m_cfg.cnt.number << std::endl; + THROW_DEVFAILED( + _CPTC("DEVICE_ERROR"), + _CPTC("Failed to start buffer recover task!"), + _CPTC("BufferedCounterPeriod::updateRawBuffer")); + } + //std::cout << "BufferedCounterPeriod::updateRawBuffer - starting Buffer recovery thread for counter " + // << this->m_cfg.cnt.number << std::endl; + this->m_dataBuffer_thread->start_undetached(); + } +} + +// ============================================================================ +// BufferedCounterPeriod::getRawBuffer +// ============================================================================ +void BufferedCounterPeriod::getRawBuffer() +{ + // call "get raw buffer" to compose the whole buffer. + // In "polling" mode, the client has to poll to compose the acquisition buffer. + if (!this->m_acquisitionDone) + { + DEBUG_STREAM << "BufferedCounterPeriod::GetRawBuffer entering..." << endl; + //- from NI660Xsl - calls ni660Xsl::handle_xxx methods + try + { + ni660Xsl::BufferedPeriodMeasurement::get_raw_buffer(); // the driver waits 'buffer depth' seconds... + } + catch(ni660Xsl::DAQException & nie) + { + throw_devfailed(nie); + } + } +} + +// ============================================================================ +// BufferedCounterPeriod::handle_timeout () +// ============================================================================ +void BufferedCounterPeriod::handle_timeout() + throw (Tango::DevFailed) +{ + ERROR_STREAM << "BufferedCounterPeriod::handle_timeout() entering..." << endl; + this->m_cntTimedout = true; +} + +// ============================================================================ +// BufferedCounterPeriod::handle_data_lost () +// ============================================================================ +void BufferedCounterPeriod::handle_data_lost() + throw (Tango::DevFailed) +{ + ERROR_STREAM << "BufferedCounterPeriod::handle_data_lost() entering..." << endl; + this->m_cntOverrun = true; +} + +// ============================================================================ +// BufferedCounterPeriod::handle_raw_buffer () +// ============================================================================ +void BufferedCounterPeriod::handle_raw_buffer(ni660Xsl::InRawBuffer* buffer, long& _samples_read) + throw (Tango::DevFailed) +{ + //- PERIOD values are not raw !!! + delete buffer; +} + +// ============================================================================ +// BufferedCounterPeriod::handle_scaled_buffer () +// ============================================================================ +void BufferedCounterPeriod::handle_scaled_buffer(ni660Xsl::InScaledBuffer* buffer, long& _samples_read) + throw (Tango::DevFailed) +{ + DEBUG_STREAM << "BufferedCounterPeriod::handle_scaled_buffer() entering..." << std::endl; + DEBUG_STREAM << "BufferedCounterPeriod::handle_scaled_buffer() - samples to read = " << _samples_read << std::endl; + + // check samples number is > 0 + if (_samples_read <= 0) + { + ERROR_STREAM << "BufferedCounterPeriod::handle_scaled_buffer-> samples to read negative or null value!" << std::endl; + this->stopCnt(); + return; + } + + yat::AutoMutex<> guard(this->m_buffLock); + + ni660Xsl::InScaledBuffer& buf = *buffer; + RawData_t & data = this->m_data; + bool data_to_be_stored = (this->m_cfg.acq.nexusFileGeneration && this->m_cfg.cnt.nexus); + + //- Continuous acquisition: only one buffer is received !! + if (this->m_cfg.acq.continuousAcquisition) + { + DEBUG_STREAM << "continuous acquisition: nb buffer to receive = 1!" << std::endl; + + for (unsigned long idx = 0; idx < (unsigned long)_samples_read; idx++) + { + data[idx] = (data_t)(buf[idx]); + } + + // store received buffer in Nexus, if nx storage enabled + if (data_to_be_stored && this->m_storage_mgr) + { + try + { + this->m_storage_mgr->pushNexusData(this->m_cfg.cnt.name, &data[0], (unsigned long)_samples_read); + } + catch (Tango::DevFailed & df) + { + ERROR_STREAM << "BufferedCounterPeriod::handle_raw_buffer-> pushNexusData caught DevFailed: " << df << std::endl; + // We should stop acquisition if nx problem! + this->m_storageError = true; + this->stopCnt(); + } + catch (...) + { + ERROR_STREAM << "BufferedCounterPeriod::handle_raw_buffer-> pushNexusData caugth unknown exception!" << std::endl; + // We should stop acquisition if nx problem! + this->m_storageError = true; + this->stopCnt(); + } + } + + // stop acquisition + this->stopCnt(); + } + else if (this->m_bufferNbToReceive == 0) //- infinite mode + { + DEBUG_STREAM << "one buffer received." << std::endl; + + unsigned long nb_to_copy; + nb_to_copy = buf.depth(); + DEBUG_STREAM << "NB to copy : " << nb_to_copy << endl; + + for (unsigned long idx = 0; idx < nb_to_copy; idx++ ) + { + data[idx] = (data_t)(buf[idx]); + } + + // store received buffer in Nexus, if nx storage enabled for this counter + if (data_to_be_stored && this->m_storage_mgr) + { + try + { + this->m_storage_mgr->pushNexusData(this->m_cfg.cnt.name, &data[0], nb_to_copy); + } + catch (Tango::DevFailed & df) + { + ERROR_STREAM << "BufferedCounterPeriod::handle_raw_buffer-> pushNexusData caught DevFailed: " << df << std::endl; + // We should stop acquisition if nx problem! + this->m_storageError = true; + this->stopCnt(); + } + catch (...) + { + ERROR_STREAM << "BufferedCounterPeriod::handle_raw_buffer-> pushNexusData caugth unknown exception!" << std::endl; + // We should stop acquisition if nx problem! + this->m_storageError = true; + this->stopCnt(); + } + } + } + else //- not continuous nor infinite + { + //- All buffers have not been yet received + if (this->m_currentBufferNb < this->m_bufferNbToReceive) + { + DEBUG_STREAM << "buffer currently received = " << this->m_currentBufferNb + 1 << " on " << this->m_bufferNbToReceive << std::endl; + unsigned long nb_to_copy; + + if (((unsigned long)this->m_cfg.acq.samplesNumber - this->m_firstPtReceivedBuff) < buf.depth()) + { + nb_to_copy = (unsigned long)this->m_cfg.acq.samplesNumber - this->m_firstPtReceivedBuff; + } + else + { + nb_to_copy = buf.depth(); + } + DEBUG_STREAM << "NB to copy : " << nb_to_copy << endl; + + // tempo buffer for storage + RawData_t bufNx; + if (data_to_be_stored) + { + // force length with _samples_read because in the case of incomplete buffer + // (i.e. last buffer to receive), the nx manager requires fixed length = buffer depth size + bufNx.capacity(_samples_read); + bufNx.force_length(_samples_read); + bufNx.fill(yat::IEEE_NAN); + } + + for (unsigned long idx = 1; idx < nb_to_copy; idx++ ) + { + data[idx + this->m_firstPtReceivedBuff] = (data_t)(buf[idx]); + if (data_to_be_stored) + bufNx[idx] = data[idx + this->m_firstPtReceivedBuff]; + } + + //- at start, m_firstPtReceivedBuff equals 0. + //- m_firstPtReceivedBuff is the position of the 1st point of the buffer + data[this->m_firstPtReceivedBuff] = (data_t)(buf[0]); + if (data_to_be_stored) + bufNx[0] = data[this->m_firstPtReceivedBuff]; + + this->m_currentBufferNb++; + this->m_firstPtReceivedBuff += nb_to_copy; + + // store received buffer in Nexus, if nx storage enabled for this counter + if (data_to_be_stored && this->m_storage_mgr) + { + try + { + this->m_storage_mgr->pushNexusData(this->m_cfg.cnt.name, &bufNx[0], nb_to_copy); + } + catch (Tango::DevFailed & df) + { + ERROR_STREAM << "BufferedCounterPeriod::handle_raw_buffer-> pushNexusData caught DevFailed: " << df << std::endl; + // We should stop acquisition if nx problem! + this->m_storageError = true; + this->stopCnt(); + } + catch (...) + { + ERROR_STREAM << "BufferedCounterPeriod::handle_raw_buffer-> pushNexusData caugth unknown exception!" << std::endl; + // We should stop acquisition if nx problem! + this->m_storageError = true; + this->stopCnt(); + } + } + } + + // if all requested buffers are received + if (this->m_currentBufferNb == this->m_bufferNbToReceive) + { + // stop acquisition + this->stopCnt(); + } + } + + delete buffer; +} + +// ============================================================================ +// BufferedCounterPeriod::startCnt +// ============================================================================ +void BufferedCounterPeriod::startCnt() + throw (Tango::DevFailed) +{ + DEBUG_STREAM << "BufferedCounterPeriod::startCnt() entering..." << endl; + this->m_cntOverrun = false; + this->m_cntTimedout = false; + this->m_storageError = false; + + { + yat::AutoMutex<> guard(this->m_buffLock); + + // reset current counters & buffers + this->m_currentBufferNb = 0; + this->m_firstPtReceivedBuff = 0; + this->m_acquisitionDone = false; + + // check if infinite mode + if (this->m_cfg.acq.samplesNumber == 0) + { + // set data length to buffer depth + this->m_data.capacity(this->m_cfg.acq.bufferDepth); + this->m_data.force_length(this->m_cfg.acq.bufferDepth); + } + else + { + // set data length to samples nber + this->m_data.capacity(this->m_cfg.acq.samplesNumber); + this->m_data.force_length(this->m_cfg.acq.samplesNumber); + } + this->m_data.fill(yat::IEEE_NAN); + + unsigned long buffer_depth_nbpts = 0; + + if (this->m_cfg.acq.continuousAcquisition) + { + buffer_depth_nbpts = this->m_cfg.acq.samplesNumber; + } + else + { + buffer_depth_nbpts = static_cast<unsigned long>(this->m_cfg.acq.bufferDepth); + } + m_bufferNbToReceive = (m_cfg.acq.samplesNumber + buffer_depth_nbpts - 1) / buffer_depth_nbpts; + DEBUG_STREAM << "Buffer to receive : " << m_bufferNbToReceive << endl; + } + + //- from NI660Xsl + try + { + ni660Xsl::BufferedPeriodMeasurement::start(); + } + catch(ni660Xsl::DAQException & nie) + { + throw_devfailed(nie); + } + +#if !defined (USE_CALLBACK) + // start the data buffer waiting task for the 1st time + this->updateRawBuffer(); +#endif +} + +// ============================================================================ +// BufferedCounterPeriod::stopCnt +// ============================================================================ +void BufferedCounterPeriod::stopCnt() + throw (Tango::DevFailed) +{ + DEBUG_STREAM << "BufferedCounterPeriod::stopCnt() entering..." << endl; + this->m_acquisitionDone = true; + + try + { + //- from NI660Xsl + ni660Xsl::BufferedPeriodMeasurement::abort(); // we use abort to stop counting immediately + ni660Xsl::BufferedPeriodMeasurement::release(); // sets an UNKNOWN state in NI660Xsl lib ! + } + catch(...) + { + // DAQmx 9.x abort pb workaround + ERROR_STREAM << "BufferedCounterPeriod::stopCnt() - Aborting counter generates exception, do nothing..." << std::endl; + } +} + +// ============================================================================ +// BufferedCounterPeriod::get_value () +// ============================================================================ +RawData_t & BufferedCounterPeriod::get_value() +{ + yat::AutoMutex<> guard(this->m_buffLock); + return this->m_data; +} + +//***************************************************************************** +// BRPRThread +//***************************************************************************** +// ============================================================================ +// BRPRThread::BRPRThread +// ============================================================================ +BRPRThread::BRPRThread (Tango::DeviceImpl * hostDevice, yat::Thread::IOArg ioa) +: yat::Thread(ioa), +Tango::LogAdapter (hostDevice), +m_goOn(true), +m_isUpdateDone(false) +{ + //- noop ctor +} + +// ============================================================================ +// BRPRThread::~BRPRThread +// ============================================================================ +BRPRThread::~BRPRThread (void) +{ + //- noop dtor +} + +// ============================================================================ +// BRPRThread::run_undetached +// ============================================================================ +yat::Thread::IOArg BRPRThread::run_undetached (yat::Thread::IOArg ioa) +{ + DEBUG_STREAM << "BRPRThread::run_undetached() entering... " << std::endl; + + m_isUpdateDone = false; + //- get ref. to out our parent task + BufferedCounterPeriod * cm_task = reinterpret_cast<BufferedCounterPeriod *>(ioa); + + //std::cout << "**Wait for buffer value to be set from board..." << std::endl; + cm_task->getRawBuffer(); + + // when function returns, the buffer is handled (or timeout if no data) + //std::cout << "**Buffer update done." << std::endl; + m_isUpdateDone = true; + + return 0; +} + + +// ============================================================================ +// BRPRThread::exit +// ============================================================================ +void BRPRThread::exit (void) +{ + this->m_goOn = false; +} + +} // namespace PulseCounting_ns + diff --git a/src/BufferedCounterPeriod.h b/src/BufferedCounterPeriod.h new file mode 100644 index 0000000000000000000000000000000000000000..2056efaac110ea1c950e652b5310560d5f433e8f --- /dev/null +++ b/src/BufferedCounterPeriod.h @@ -0,0 +1,195 @@ +//============================================================================= +// BufferedCounterPeriod.h +//============================================================================= +// abstraction.......BufferedCounterPeriod for PulseCounting +// class.............BufferedCounterPeriod +// original author...S.Minolli - Nexeya +//============================================================================= + +#ifndef _BUFFERED_COUNTER_PRD_H +#define _BUFFERED_COUNTER_PRD_H + +// ============================================================================ +// DEPENDENCIES +// ============================================================================ +#include <yat4tango/LogHelper.h> +#include "PulseCountingTypesAndConsts.h" +#include <NI660Xsl/BufferedPeriodMeasurement.h> +#include <yat/threading/Thread.h> +#include <yat4tango/ExceptionHelper.h> +#include "NexusManager.h" + +namespace PulseCounting_ns +{ + + + // ============================================================================ + // class: BRPRThread + // ============================================================================ + class BRPRThread : public yat::Thread, public Tango::LogAdapter + { + friend class BufferedCounterPeriod; + + protected: + //- ctor --------------------------------- + BRPRThread (Tango::DeviceImpl * hostDevice, yat::Thread::IOArg ioa); + + //- dtor --------------------------------- + virtual ~BRPRThread (void); + + //- thread's entry point + virtual yat::Thread::IOArg run_undetached (yat::Thread::IOArg ioa); + + //- asks this BRPRThread to quit + virtual void exit (void); + + //- Thread state + bool isThreadAlive() + { + return m_goOn; + } + + //- Buffer update state + bool updateDone() + { + return m_isUpdateDone; + } + + private: + //- thread's ctrl flag + bool m_goOn; + + //- data update done + bool m_isUpdateDone; + }; + + + +// ============================================================================ +// class: BufferedCounterPeriod +// ============================================================================ +class BufferedCounterPeriod : public yat4tango::TangoLogAdapter, public ni660Xsl::BufferedPeriodMeasurement +{ +public: + + //- constructor + BufferedCounterPeriod (BCEconfig p_conf, NexusManager * storage); + + //- destructor + virtual ~BufferedCounterPeriod (); + + //*********** NI660Xsl inheritance **************** + // These handle_xxx functions are called directly by NI660XSl lib in "callback mode" and + // called after wait task ends in "polling" mode. + + //- handle timeout + void handle_timeout() + throw (Tango::DevFailed); + + //- handle data lost + void handle_data_lost() + throw (Tango::DevFailed); + + //- handle raw buffer + void handle_raw_buffer(ni660Xsl::InRawBuffer* buffer, long& _samples_read) + throw (Tango::DevFailed); + + //- handle scaled buffer + void handle_scaled_buffer(ni660Xsl::InScaledBuffer* buffer, long& _samples_read) + throw (Tango::DevFailed); + + + //********** local members **************** + // start counter + void startCnt() + throw (Tango::DevFailed); + + // stop counter + void stopCnt() + throw (Tango::DevFailed); + + //- set local value + void set_value(); + + //- get value + RawData_t & get_value(); + + // Acquisition done info + bool isAcquisitionDone() + { + yat::AutoMutex<> guard(this->m_buffLock); + return this->m_acquisitionDone; + } + + // updates raw buffer <=> starts waiting task if not already running + // (used in "polling" mode) + void updateRawBuffer() + throw(Tango::DevFailed); + + // gets raw buffer <=> calls the driver waiting task (used in "polling" mode) + void getRawBuffer(); + + //- release counter + void deleteObject() + throw (Tango::DevFailed); + + // is counter in overrun ? + bool isOverrun() + { + return this->m_cntOverrun; + } + + // has counter timed out ? + bool isTimedout() + { + return this->m_cntTimedout; + } + + // has counter stopped on storage error? + bool isStorageKO() + { + return this->m_storageError; + } + +protected: + + // counter config + BCEconfig m_cfg; + + // total number of buffers to receive for each acquisition + unsigned long m_bufferNbToReceive; + + // current number of buffers actually received + unsigned long m_currentBufferNb; + + // First point of the currently received buffer + unsigned long m_firstPtReceivedBuff; + + // raw data buffer + RawData_t m_data; + + // Acquisition done flag + bool m_acquisitionDone; + + //- data mutex protection + yat::Mutex m_buffLock; + + // Data buffer waiting task + BRPRThread * m_dataBuffer_thread; + + // overrun flag + bool m_cntOverrun; + + // timeout flag + bool m_cntTimedout; + + // Storage error flag + bool m_storageError; // soso crash rock + + // storage manager + NexusManager * m_storage_mgr; +}; + +} // namespace PulseCounting_ns + +#endif // _BUFFERED_COUNTER_PRD_H diff --git a/src/BufferedCounterPos.cpp b/src/BufferedCounterPos.cpp index e2e7551d20641091d54665c0d6650911bb8c87fa..7dc900a9fd88d8e5c457c10edcc15e64c0e20f83 100644 --- a/src/BufferedCounterPos.cpp +++ b/src/BufferedCounterPos.cpp @@ -30,6 +30,7 @@ BufferedCounterPos::BufferedCounterPos (BCEconfig p_conf, NexusManager * storage this->m_dataBuffer_thread = NULL; this->m_cntOverrun = false; this->m_cntTimedout = false; + this->m_storageError = false; m_data.clear(); m_cfg = p_conf; m_storage_mgr = storage; @@ -144,6 +145,14 @@ void BufferedCounterPos::handle_scaled_buffer(ni660Xsl::InScaledBuffer* buffer, DEBUG_STREAM << "BufferedCounterPos::handle_scaled_buffer() entering..." << std::endl; DEBUG_STREAM << "BufferedCounterPos::handle_scaled_buffer() - samples to read = " << _samples_read << std::endl; + // check samples number is > 0 + if (_samples_read <= 0) + { + ERROR_STREAM << "BufferedCounterPos::handle_scaled_buffer-> samples to read negative or null value!" << std::endl; + this->stopCnt(); + return; + } + yat::AutoMutex<> guard(this->m_buffLock); ni660Xsl::InScaledBuffer& buf = *buffer; @@ -178,12 +187,16 @@ void BufferedCounterPos::handle_scaled_buffer(ni660Xsl::InScaledBuffer* buffer, catch (Tango::DevFailed & df) { ERROR_STREAM << "BufferedCounterPos::handle_scaled_buffer-> pushNexusData caught DevFailed: " << df << std::endl; - // Should we stop acquisition if nx problem? + // We should stop acquisition if nx problem! + this->m_storageError = true; + this->stopCnt(); } catch (...) { ERROR_STREAM << "BufferedCounterPos::handle_scaled_buffer-> pushNexusData caugth unknown exception!" << std::endl; - // Should we stop acquisition if nx problem? + // We should stop acquisition if nx problem! + this->m_storageError = true; + this->stopCnt(); } } @@ -251,12 +264,16 @@ void BufferedCounterPos::handle_scaled_buffer(ni660Xsl::InScaledBuffer* buffer, catch (Tango::DevFailed & df) { ERROR_STREAM << "BufferedCounterPos::handle_scaled_buffer-> pushNexusData caught DevFailed: " << df << std::endl; - // Should we stop acquisition if nx problem? + // We should stop acquisition if nx problem! + this->m_storageError = true; + this->stopCnt(); } catch (...) { ERROR_STREAM << "BufferedCounterPos::handle_scaled_buffer-> pushNexusData caugth unknown exception!" << std::endl; - // Should we stop acquisition if nx problem? + // We should stop acquisition if nx problem! + this->m_storageError = true; + this->stopCnt(); } } } @@ -334,12 +351,16 @@ void BufferedCounterPos::handle_scaled_buffer(ni660Xsl::InScaledBuffer* buffer, catch (Tango::DevFailed & df) { ERROR_STREAM << "BufferedCounterPos::handle_scaled_buffer-> pushNexusData caught DevFailed: " << df << std::endl; - // Should we stop acquisition if nx problem? + // We should stop acquisition if nx problem! + this->m_storageError = true; + this->stopCnt(); } catch (...) { ERROR_STREAM << "BufferedCounterPos::handle_scaled_buffer-> pushNexusData caugth unknown exception!" << std::endl; - // Should we stop acquisition if nx problem? + // We should stop acquisition if nx problem! + this->m_storageError = true; + this->stopCnt(); } } } @@ -364,6 +385,7 @@ void BufferedCounterPos::startCnt() DEBUG_STREAM << "BufferedCounterPos::startCnt() entering..." << endl; this->m_cntOverrun = false; this->m_cntTimedout = false; + this->m_storageError = false; { yat::AutoMutex<> guard(this->m_buffLock); diff --git a/src/BufferedCounterPos.h b/src/BufferedCounterPos.h index ec64fa51c3199bdf2937064c155b9d0131dd13e9..1d4e751759b4f6e30488a395c1738b6aa65fab8e 100644 --- a/src/BufferedCounterPos.h +++ b/src/BufferedCounterPos.h @@ -141,6 +141,13 @@ public: return this->m_cntTimedout; } + // has counter stopped on storage error? + bool isStorageKO() + { + return this->m_storageError; + } + + protected: // counter config BCEconfig m_cfg; @@ -175,6 +182,9 @@ protected: // timeout flag bool m_cntTimedout; + // Storage error flag + bool m_storageError; + // storage manager NexusManager * m_storage_mgr; }; diff --git a/src/ConfigurationParser.cpp b/src/ConfigurationParser.cpp index c11fa7b4b00c4b50282b4ec668df2f6c37f24f87..2b6f7f17912db676dcd6031b1c60bac8ce588980 100644 --- a/src/ConfigurationParser.cpp +++ b/src/ConfigurationParser.cpp @@ -269,6 +269,10 @@ E_CounterMode_t ConfigurationParser::extractMode (CounterKeys_t acq_config) { mode = COUNTER_MODE_DELTATIME; } + else if (0 == tokenValue.compare(kKEY_MODE_PERIOD)) + { + mode = COUNTER_MODE_PERIOD; + } else { // bad value ==> fatal error diff --git a/src/ConfigurationParser.h b/src/ConfigurationParser.h index 113e2e19315006e2b8a38566f68992dfd3fd9653..1eb6c539f69ff24720b42df186ebc6af33f4951b 100644 --- a/src/ConfigurationParser.h +++ b/src/ConfigurationParser.h @@ -25,15 +25,14 @@ namespace PulseCounting_ns static const std::string kKEY_VALUE_SEPARATOR (":"); static const std::string kVALUE_SEPARATOR_CL (":"); static const std::string kVALUE_SEPARATOR_COMA (","); -static const std::string kCONFIG_NAME ("Counter"); //- property strings for config -static const std::string kKEY_COUNTER ("Counter"); static const std::string kKEY_NAME ("Name"); static const std::string kKEY_MODE ("Mode"); static const std::string kKEY_MODE_EVT ("EVT"); static const std::string kKEY_MODE_POS ("POS"); static const std::string kKEY_MODE_DT ("DT"); +static const std::string kKEY_MODE_PERIOD ("PERIOD"); static const std::string kKEY_TRANSFER ("Transfer"); static const std::string kKEY_TRANSFER_DMA ("DMA"); static const std::string kKEY_TRANSFER_ITR ("ITR"); diff --git a/src/CounterFactory.cpp b/src/CounterFactory.cpp index 190beb1622ad987f0dd44967b23411ca29ed805c..e555c5c937e685082fb6f62988415689617f0784 100644 --- a/src/CounterFactory.cpp +++ b/src/CounterFactory.cpp @@ -14,6 +14,7 @@ #include "EventCounter.h" #include "PositionCounter.h" #include "DeltaTimeCounter.h" +#include "PeriodCounter.h" namespace PulseCounting_ns { @@ -37,6 +38,9 @@ GenericCounterInterface * CounterFactory::instanciate (Tango::DeviceImpl * hostD case COUNTER_MODE_DELTATIME: l_counter = new DeltaTimeCounter(hostDevice, p_acq_mode, p_board); break; + case COUNTER_MODE_PERIOD: + l_counter = new PeriodCounter(hostDevice, p_acq_mode, p_board); + break; case UNDEFINED_COUNTER_MODE: l_counter = NULL; break; diff --git a/src/NI6602_Interface.cpp b/src/NI6602_Interface.cpp index 0f5f07a8998cd1ca7207854cea093b54c0120c1c..07437f5ab0e7f25986bf3b801f266f00c430794c 100644 --- a/src/NI6602_Interface.cpp +++ b/src/NI6602_Interface.cpp @@ -79,6 +79,13 @@ void NI6602_Interface::initCounter(CounterConfig p_cfg) m_scalar_dt_ct_list[p_cfg.name] = NULL; } break; + case COUNTER_MODE_PERIOD: + if (m_scalar_prd_ct_list[p_cfg.name]) + { + delete m_scalar_prd_ct_list[p_cfg.name]; + m_scalar_prd_ct_list[p_cfg.name] = NULL; + } + break; default: break; } @@ -108,6 +115,13 @@ void NI6602_Interface::initCounter(CounterConfig p_cfg) m_buffer_dt_ct_list[p_cfg.name] = NULL; } break; + case COUNTER_MODE_PERIOD: + if (m_buffer_prd_ct_list[p_cfg.name]) + { + delete m_buffer_prd_ct_list[p_cfg.name]; + m_buffer_prd_ct_list[p_cfg.name] = NULL; + } + break; default: break; } @@ -313,6 +327,7 @@ void NI6602_Interface::configureCounter(CounterConfig p_cfg) ni660Xsl::EventCountChan l_evtConfig; ni660Xsl::PositionChan l_posConfig; ni660Xsl::DeltaTimeChan l_dtConfig; + ni660Xsl::PeriodChan l_prdConfig; ni660Xsl::AngularEncoderChan l_angConfig; ni660Xsl::LinearEncoderChan l_linConfig; ni::AngleUnitsType l_angleUnits; @@ -585,6 +600,43 @@ void NI6602_Interface::configureCounter(CounterConfig p_cfg) break; } l_dtConfig.units = l_dtUnits; + break; + + //********************************************************************/ + // PERIOD COUNTER + //********************************************************************/ + case COUNTER_MODE_PERIOD: + l_prdConfig.chan_name = std::string("/") + p_cfg.boardName + std::string("/") + std::string("ctr") + + yat::XString<size_t>::to_string(p_cfg.number); + + ni::EdgeType edge; + switch (p_cfg.edge) + { + case COUNTING_EDGE_RISING: + edge = ni::rising_edge; + break; + case COUNTING_EDGE_FALLING: + edge = ni::falling_edge; + break; + default: + edge = ni::rising_edge; //default value if not defined + break; + } + l_prdConfig.edge = edge; + + switch (p_cfg.dt_unit) + { + case ENC_UNIT_TICK: + l_dtUnits = ni::time_ticks; + break; + case ENC_UNIT_SEC: + l_dtUnits = ni::seconds; + break; + default: + l_dtUnits = ni::seconds; + break; + } + l_prdConfig.units = l_dtUnits; break; default: @@ -703,6 +755,40 @@ void NI6602_Interface::configureCounter(CounterConfig p_cfg) throw_devfailed(nie); } } + else if (p_cfg.mode == COUNTER_MODE_PERIOD) + { + // Create PERIOD counting object and configure it + try + { + m_scalar_prd_ct_list[p_cfg.name] = new ni660Xsl::SimplePeriodMeasurement(); + + if (m_scalar_prd_ct_list[p_cfg.name]) + { + std::string pause_trigger; + // Check board + if ((this->m_clk_cfg.channelName.compare(CLOCK_INTERNAL) == 0) && + (this->m_clk_cfg.boardName.compare(p_cfg.boardName) == 0)) + { + // Master board: generates clock on ctr0 = trigger + pause_trigger = "/" + p_cfg.boardName + "/ctr0InternalOutput"; + } + else + { + // Not master board: receives external clock on PFI38 + pause_trigger = "/" + p_cfg.boardName + "/PFI38"; + } + + m_scalar_prd_ct_list[p_cfg.name]->set_pause_trigger(pause_trigger, ni::low); + m_scalar_prd_ct_list[p_cfg.name]->add_input_channel(l_prdConfig); + m_scalar_prd_ct_list[p_cfg.name]->init(); + m_scalar_prd_ct_list[p_cfg.name]->configure(); + } + } + catch(ni660Xsl::DAQException & nie) + { + throw_devfailed(nie); + } + } else { // bad counter mode, nothing to do... @@ -930,6 +1016,68 @@ void NI6602_Interface::configureCounter(CounterConfig p_cfg) throw_devfailed(nie); } } + else if (p_cfg.mode == COUNTER_MODE_PERIOD) + { + // Create PERIOD counting object and configure it + try + { + m_buffer_prd_ct_list[p_cfg.name] = new BufferedCounterPeriod(l_conf, m_storage); + + if (m_buffer_prd_ct_list[p_cfg.name]) + { + // Define acquisition + m_buffer_prd_ct_list[p_cfg.name]->set_timeout(m_cfg.timeout); + m_buffer_prd_ct_list[p_cfg.name]->set_overrun_strategy(ni::notify); + m_buffer_prd_ct_list[p_cfg.name]->set_timing_mode(ni::continuous); + m_buffer_prd_ct_list[p_cfg.name]->set_buffer_depth(buffer_depth_nbpts); + + if (p_cfg.memTranfer == MEMORY_TRSF_DMA) + { + m_buffer_prd_ct_list[p_cfg.name]->set_data_tranfer_mechanism(ni::dma); + } + else + { + m_buffer_prd_ct_list[p_cfg.name]->set_data_tranfer_mechanism(ni::interrupts); + } + + std::string pause_trigger; + // Check board + if ((this->m_clk_cfg.channelName.compare(CLOCK_INTERNAL) == 0) && + (this->m_clk_cfg.boardName.compare(p_cfg.boardName) == 0)) + { + // Master board: generates clock on ctr0 = trigger + pause_trigger = "/" + p_cfg.boardName + "/ctr0InternalOutput"; + } + else + { + // Not master board: receives external clock on PFI38 + pause_trigger = "/" + p_cfg.boardName + "/PFI38"; + } + + double max_rate = 1.1 / m_cfg.integrationTime; + m_buffer_prd_ct_list[p_cfg.name]->set_sample_clock(pause_trigger, ni::rising_edge, max_rate); + + if (this->m_cfg.startTriggerUse) + { + m_buffer_prd_ct_list[p_cfg.name]->set_start_trigger(pause_trigger, ni::rising_edge); + } + +#if defined (USE_CALLBACK) + DEBUG_STREAM << "Callback mode set" << std::endl; + m_buffer_prd_ct_list[p_cfg.name]->set_callback_mode(true); + m_buffer_prd_ct_list[p_cfg.name]->set_total_nb_pts(this->m_cfg.samplesNumber); +#endif + + m_buffer_prd_ct_list[p_cfg.name]->add_input_channel(l_prdConfig); + m_buffer_prd_ct_list[p_cfg.name]->init(); + m_buffer_prd_ct_list[p_cfg.name]->configure(); + } + } + catch(ni660Xsl::DAQException & nie) + { + throw_devfailed(nie); + } + } else { // bad counter mode, nothing to do... @@ -963,6 +1111,9 @@ void NI6602_Interface::startCounter(CounterConfig p_cfg) case COUNTER_MODE_DELTATIME: m_scalar_dt_ct_list[p_cfg.name]->start(); break; + case COUNTER_MODE_PERIOD: + m_scalar_prd_ct_list[p_cfg.name]->start(); + break; default: break; } @@ -980,7 +1131,10 @@ void NI6602_Interface::startCounter(CounterConfig p_cfg) case COUNTER_MODE_DELTATIME: m_buffer_dt_ct_list[p_cfg.name]->startCnt(); break; - default: + case COUNTER_MODE_PERIOD: + m_buffer_prd_ct_list[p_cfg.name]->startCnt(); + break; + default: break; } break; @@ -1023,6 +1177,11 @@ void NI6602_Interface::stopCounter(CounterConfig p_cfg) m_scalar_dt_ct_list[p_cfg.name]->stop(); m_scalar_dt_ct_list[p_cfg.name]->release(); break; + case COUNTER_MODE_PERIOD: + //- from NI660XSl + m_scalar_prd_ct_list[p_cfg.name]->stop(); + m_scalar_prd_ct_list[p_cfg.name]->release(); + break; default: break; } @@ -1040,6 +1199,9 @@ void NI6602_Interface::stopCounter(CounterConfig p_cfg) case COUNTER_MODE_DELTATIME: m_buffer_dt_ct_list[p_cfg.name]->stopCnt(); break; + case COUNTER_MODE_PERIOD: + m_buffer_prd_ct_list[p_cfg.name]->stopCnt(); + break; default: break; } @@ -1301,6 +1463,7 @@ Tango::DevState NI6602_Interface::getCounterState(CounterConfig p_cfg) bool l_overrun = false; bool l_timedout = false; + bool l_storageErr = false; // soso crash rock switch (m_acq_mode) @@ -1314,7 +1477,7 @@ Tango::DevState NI6602_Interface::getCounterState(CounterConfig p_cfg) if (m_scalar_pos_ct_list[p_cfg.name]) { // get underlying counter state - l_state = m_scalar_pos_ct_list[p_cfg.name]->state(); + l_state = m_scalar_pos_ct_list[p_cfg.name]->state(); } else { @@ -1353,6 +1516,24 @@ Tango::DevState NI6602_Interface::getCounterState(CounterConfig p_cfg) l_state = m_scalar_dt_ct_list[p_cfg.name]->state(); } else + { + l_state = ni660Xsl::InputOperation::UNKNOWN; + } + } + catch (...) + { + l_state = -1; + } + break; + case COUNTER_MODE_PERIOD: + try + { + if (m_scalar_prd_ct_list[p_cfg.name]) + { + // get underlying counter state + l_state = m_scalar_prd_ct_list[p_cfg.name]->state(); + } + else { l_state = ni660Xsl::InputOperation::UNKNOWN; } @@ -1379,9 +1560,10 @@ Tango::DevState NI6602_Interface::getCounterState(CounterConfig p_cfg) // get underlying counter state l_state = m_buffer_pos_ct_list[p_cfg.name]->state(); - // get buffering errors (overrun or timeout) + // get buffering errors (overrun, timeout or storage error) l_overrun = m_buffer_pos_ct_list[p_cfg.name]->isOverrun(); l_timedout = m_buffer_pos_ct_list[p_cfg.name]->isTimedout(); + l_storageErr = m_buffer_pos_ct_list[p_cfg.name]->isStorageKO(); // soso crash rock } else { @@ -1402,9 +1584,10 @@ Tango::DevState NI6602_Interface::getCounterState(CounterConfig p_cfg) // get underlying counter state l_state = m_buffer_evt_ct_list[p_cfg.name]->state(); - // get buffering errors (overrun or timeout) + // get buffering errors (overrun, timeout or storage error) l_overrun = m_buffer_evt_ct_list[p_cfg.name]->isOverrun(); l_timedout = m_buffer_evt_ct_list[p_cfg.name]->isTimedout(); + l_storageErr = m_buffer_evt_ct_list[p_cfg.name]->isStorageKO(); // soso crash rock } else { @@ -1424,9 +1607,33 @@ Tango::DevState NI6602_Interface::getCounterState(CounterConfig p_cfg) // get underlying counter state l_state = m_buffer_dt_ct_list[p_cfg.name]->state(); - // get buffering errors (overrun or timeout) + // get buffering errors (overrun, timeout or storage error) l_overrun = m_buffer_dt_ct_list[p_cfg.name]->isOverrun(); l_timedout = m_buffer_dt_ct_list[p_cfg.name]->isTimedout(); + l_storageErr = m_buffer_dt_ct_list[p_cfg.name]->isStorageKO(); // soso crash rock + } + else + { + l_state = ni660Xsl::InputOperation::UNKNOWN; + } + } + catch (...) + { + l_state = -1; + } + break; + case COUNTER_MODE_PERIOD: + try + { + if (m_buffer_prd_ct_list[p_cfg.name]) + { + // get underlying counter state + l_state = m_buffer_prd_ct_list[p_cfg.name]->state(); + + // get buffering errors (overrun, timeout or storage error) + l_overrun = m_buffer_prd_ct_list[p_cfg.name]->isOverrun(); + l_timedout = m_buffer_prd_ct_list[p_cfg.name]->isTimedout(); + l_storageErr = m_buffer_prd_ct_list[p_cfg.name]->isStorageKO(); // soso crash rock } else { @@ -1478,6 +1685,9 @@ Tango::DevState NI6602_Interface::getCounterState(CounterConfig p_cfg) if (l_timedout) l_val = Tango::DISABLE; + if (l_storageErr) // soso crash rock + l_val = Tango::FAULT; + return l_val; } @@ -1521,6 +1731,16 @@ data_t NI6602_Interface::getCounterScalarValue(CounterConfig p_cfg) l_val = -1; } break; + case COUNTER_MODE_PERIOD: + try + { + l_val = m_scalar_prd_ct_list[p_cfg.name]->get_current_scaled_value(); + } + catch (...) + { + l_val = -1; + } + break; default: break; } @@ -1553,6 +1773,12 @@ RawData_t & NI6602_Interface::getCounterBufferValue(CounterConfig p_cfg) return m_buffer_dt_ct_list[p_cfg.name]->get_value(); } break; + case COUNTER_MODE_PERIOD: + if (m_buffer_prd_ct_list[p_cfg.name] != NULL) + { + return m_buffer_prd_ct_list[p_cfg.name]->get_value(); + } + break; default: THROW_DEVFAILED( _CPTC("CONFIGURATION_ERROR"), @@ -1594,6 +1820,12 @@ void NI6602_Interface::updateCounterBufferValue(CounterConfig p_cfg) m_buffer_dt_ct_list[p_cfg.name]->updateRawBuffer(); } break; + case COUNTER_MODE_PERIOD: + if (m_buffer_prd_ct_list[p_cfg.name] != NULL) + { + m_buffer_prd_ct_list[p_cfg.name]->updateRawBuffer(); + } + break; default: break; } @@ -1688,6 +1920,16 @@ void NI6602_Interface::releaseCounter(CounterConfig p_cfg) m_scalar_dt_ct_list[p_cfg.name] = NULL; } break; + case COUNTER_MODE_PERIOD: + if (m_scalar_prd_ct_list[p_cfg.name]) + { + m_scalar_prd_ct_list[p_cfg.name]->stop(); + m_scalar_prd_ct_list[p_cfg.name]->release(); + + delete m_scalar_prd_ct_list[p_cfg.name]; + m_scalar_prd_ct_list[p_cfg.name] = NULL; + } + break; default: break; } @@ -1724,6 +1966,15 @@ void NI6602_Interface::releaseCounter(CounterConfig p_cfg) m_buffer_dt_ct_list[p_cfg.name] = NULL; } break; + case COUNTER_MODE_PERIOD: + if (m_buffer_prd_ct_list[p_cfg.name]) + { + m_buffer_prd_ct_list[p_cfg.name]->stopCnt(); + + delete m_buffer_prd_ct_list[p_cfg.name]; + m_buffer_prd_ct_list[p_cfg.name] = NULL; + } + break; default: break; } diff --git a/src/NI6602_Interface.h b/src/NI6602_Interface.h index 2f3085a3af364fd3dea751c7bda812b949b331cb..c8ca799dc4183c61af284fd1c9c5461c2b47ea10 100644 --- a/src/NI6602_Interface.h +++ b/src/NI6602_Interface.h @@ -16,9 +16,11 @@ #include "BufferedCounterEvt.h" #include "BufferedCounterPos.h" #include "BufferedCounterDt.h" +#include "BufferedCounterPeriod.h" #include <NI660Xsl/SimpleEventCounting.h> #include <NI660Xsl/SimplePositionMeasurement.h> #include <NI660Xsl/SimpleDTMeasurement.h> +#include <NI660Xsl/SimplePeriodMeasurement.h> #include <NI660Xsl/FinitePulseTrainGeneration.h> #include <NI660Xsl/ContinuousPulseTrainGeneration.h> @@ -134,6 +136,9 @@ private: // buffer dt counter std::map<std::string, BufferedCounterDt *> m_buffer_dt_ct_list; + // buffer period counter + std::map<std::string, BufferedCounterPeriod *> m_buffer_prd_ct_list; + // max counter number unsigned int m_max_nb_ct; @@ -146,6 +151,9 @@ private: // simple dt measurement std::map<std::string, ni660Xsl::SimpleDTMeasurement *> m_scalar_dt_ct_list; + // simple period measurement + std::map<std::string, ni660Xsl::SimplePeriodMeasurement *> m_scalar_prd_ct_list; + // finite clock ni660Xsl::FinitePulseTrainGeneration * m_scalar_finite_clock; diff --git a/src/NexusManager.cpp b/src/NexusManager.cpp index 9f7f5e86371df954294ff982e318adca2abfdfc0..f57a1f78917b8c3e0e5c4470381808aeee40e62e 100644 --- a/src/NexusManager.cpp +++ b/src/NexusManager.cpp @@ -21,7 +21,8 @@ NexusManager::NexusManager (Tango::DeviceImpl * host_device) : Tango::LogAdapter(host_device), m_pAcqWriter(NULL), m_finalizeDone(true), - m_finiteStorage(false) + m_finiteStorage(false), + m_excptOccured(false) #if defined (USE_NX_DS_FINALIZER) , m_NexusDataStreamerFinalizer(NULL) @@ -97,6 +98,7 @@ void NexusManager::initNexusAcquisition(std::string nexus_file_path, throw (Tango::DevFailed) { m_finalizeDone = false; + m_excptOccured = false; try { diff --git a/src/NexusManager.h b/src/NexusManager.h index e599a169dced3ea719daf85dab97bf4323bc90c8..c303a7aff464a98ceca9c4f04f85432b5424ea4e 100644 --- a/src/NexusManager.h +++ b/src/NexusManager.h @@ -82,7 +82,7 @@ typedef nxItemList_t::iterator nxItemList_it_t; // ============================================================================ // class: NexusManager // ============================================================================ -class NexusManager : public Tango::LogAdapter +class NexusManager : public Tango::LogAdapter, nxcpp::IExceptionHandler { public: @@ -192,6 +192,19 @@ public: return !(this->m_finalizeDone); } + //- Gets Nexus storage exception + bool hasStorageError() + { + return m_excptOccured; + } + + // Nexus exception handler + void OnNexusException(const nxcpp::NexusException &e) + { + ERROR_STREAM << "NexusManager::OnNexusException() called!" << std::endl; + e.dump(); + m_excptOccured = true; + } protected: @@ -217,7 +230,9 @@ protected: //- list of items to store nxItemList_t m_itemList; - + + //- nexus exception flag + bool m_excptOccured; }; } // namespace PulseCounting_ns diff --git a/src/PeriodCounter.cpp b/src/PeriodCounter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1244f4b7e23d65844c1126120def42ec93556f9b --- /dev/null +++ b/src/PeriodCounter.cpp @@ -0,0 +1,349 @@ +//============================================================================= +// PeriodCounter.cpp +//============================================================================= +// abstraction.......PeriodCounter for PulseCounting +// class.............PeriodCounter +// original author...S.Minolli - Nexeya +//============================================================================= + + +// ============================================================================ +// DEPENDENCIES +// ============================================================================ +#include <yat4tango/LogHelper.h> +#include "PeriodCounter.h" + +namespace PulseCounting_ns +{ + + //- check manager macro: +#define CHECK_INTERFACE() \ + do \ + { \ + if (! m_interface) \ + THROW_DEVFAILED(_CPTC("DEVICE_ERROR"), \ + _CPTC("request aborted - the interface isn't accessible "), \ + _CPTC("PeriodCounter::check_interface")); \ +} while (0) + + +// ============================================================================ +// PeriodCounter::PeriodCounter () +// ============================================================================ +PeriodCounter::PeriodCounter (Tango::DeviceImpl * hostDevice, E_AcquisitionMode_t p_acq_mode, CountingBoardInterface * p_board) +: GenericCounterInterface(hostDevice) +{ + m_is_available = true; + m_state = Tango::STANDBY; + m_acq_mode = p_acq_mode; + m_interface = p_board; + m_value = 0; +} + +// ============================================================================ +// PeriodCounter::~PeriodCounter () +// ============================================================================ +PeriodCounter::~PeriodCounter () +{ + +} + +// ============================================================================ +// PeriodCounter::is_available () +// ============================================================================ +bool PeriodCounter::is_available() +{ + return m_is_available; +} + +// ============================================================================ +// PeriodCounter::init () +// ============================================================================ +void PeriodCounter::init(CounterConfig p_cfg) + throw (Tango::DevFailed) +{ + m_cfg = p_cfg; + + CHECK_INTERFACE(); + + try + { + m_interface->initCounter(m_cfg); + } + catch (Tango::DevFailed &e) + { + ERROR_STREAM << e << std::endl; + RETHROW_DEVFAILED(e, + _CPTC("DEVICE_ERROR"), + _CPTC("Failed to initialize period counter!"), + _CPTC("PeriodCounter::init")); + } + catch (...) + { + ERROR_STREAM << "Failed to initialize period counter!" << std::endl; + THROW_DEVFAILED( + _CPTC("DEVICE_ERROR"), + _CPTC("Failed to initialize period counter!"), + _CPTC("PeriodCounter::init")); + } +} + +// ============================================================================ +// PeriodCounter::configure () +// ============================================================================ +void PeriodCounter::configure(CounterConfig p_cfg) + throw (Tango::DevFailed) +{ + m_cfg = p_cfg; + + CHECK_INTERFACE(); + + try + { + m_interface->configureCounter(m_cfg); + } + catch (Tango::DevFailed &e) + { + ERROR_STREAM << e << std::endl; + RETHROW_DEVFAILED(e, + _CPTC("DEVICE_ERROR"), + _CPTC("Failed to configure period counter!"), + _CPTC("PeriodCounter::configure")); + } + catch (...) + { + ERROR_STREAM << "Failed to configure period counter!" << std::endl; + THROW_DEVFAILED( + _CPTC("DEVICE_ERROR"), + _CPTC("Failed to configure period counter!"), + _CPTC("PeriodCounter::configure")); + } +} + +// ============================================================================ +// PeriodCounter::start () +// ============================================================================ +void PeriodCounter::start() + throw (Tango::DevFailed) +{ + CHECK_INTERFACE(); + + try + { + m_interface->startCounter(m_cfg); + } + catch (Tango::DevFailed &e) + { + ERROR_STREAM << e << std::endl; + RETHROW_DEVFAILED(e, + _CPTC("DEVICE_ERROR"), + _CPTC("Failed to start period counter"), + _CPTC("PeriodCounter::start")); + } + catch (...) + { + ERROR_STREAM << "Failed to start period counter" << std::endl; + THROW_DEVFAILED( + _CPTC("DEVICE_ERROR"), + _CPTC("Failed to start period counter"), + _CPTC("PeriodCounter::start")); + } + m_state = Tango::RUNNING; +} + +// ============================================================================ +// PeriodCounter::stop () +// ============================================================================ +void PeriodCounter::stop() + throw (Tango::DevFailed) +{ + CHECK_INTERFACE(); + + try + { + m_interface->stopCounter(m_cfg); + } + catch (Tango::DevFailed &e) + { + ERROR_STREAM << e << std::endl; + RETHROW_DEVFAILED(e, + _CPTC("DEVICE_ERROR"), + _CPTC("Failed to stop period counter"), + _CPTC("PeriodCounter::stop")); + } + catch (...) + { + ERROR_STREAM << "Failed to stop period counter" << std::endl; + THROW_DEVFAILED( + _CPTC("DEVICE_ERROR"), + _CPTC("Failed to stop period counter"), + _CPTC("PeriodCounter::stop")); + } + m_state = Tango::STANDBY; +} + +// ============================================================================ +// PeriodCounter::get_state () +// ============================================================================ +Tango::DevState PeriodCounter::get_state() + throw (Tango::DevFailed) +{ + CHECK_INTERFACE(); + + try + { + return m_interface->getCounterState(m_cfg); + } + catch (Tango::DevFailed &e) + { + ERROR_STREAM << e << std::endl; + RETHROW_DEVFAILED(e, + _CPTC("DEVICE_ERROR"), + _CPTC("Failed to get period counter state!"), + _CPTC("PeriodCounter::get_state")); + } + catch (...) + { + ERROR_STREAM << "Failed to get period counter state!" << std::endl; + THROW_DEVFAILED( + _CPTC("DEVICE_ERROR"), + _CPTC("Failed to get period counter state!"), + _CPTC("PeriodCounter::get_state")); + } +} + +// ============================================================================ +// PeriodCounter::update_scalar_value () +// ============================================================================ +void PeriodCounter::update_scalar_value() + throw (Tango::DevFailed) +{ + CHECK_INTERFACE(); + + try + { + yat::AutoMutex<> guard(this->m_dataLock); + m_value = m_interface->getCounterScalarValue(m_cfg); + } + catch (Tango::DevFailed &e) + { + ERROR_STREAM << e << std::endl; + RETHROW_DEVFAILED(e, + _CPTC("DEVICE_ERROR"), + _CPTC("Failed to update scalar period counter value!"), + _CPTC("PeriodCounter::update_scalar_value")); + } + catch (...) + { + ERROR_STREAM << "Failed to update scalar period counter value!" << std::endl; + THROW_DEVFAILED( + _CPTC("DEVICE_ERROR"), + _CPTC("Failed to update scalar period counter value!"), + _CPTC("PeriodCounter::update_scalar_value")); + } +} + +// ============================================================================ +// PeriodCounter::update_buffer_value () +// ============================================================================ +void PeriodCounter::update_buffer_value() + throw (Tango::DevFailed) +{ + CHECK_INTERFACE(); + + try + { + m_interface->updateCounterBufferValue(m_cfg); + } + catch (Tango::DevFailed &e) + { + ERROR_STREAM << e << std::endl; + RETHROW_DEVFAILED(e, + _CPTC("DEVICE_ERROR"), + _CPTC("Failed to update buffer period counter value!"), + _CPTC("PeriodCounter::update_buffer_value")); + } + catch (...) + { + ERROR_STREAM << "Failed to update buffer period counter value!" << std::endl; + THROW_DEVFAILED( + _CPTC("DEVICE_ERROR"), + _CPTC("Failed to update buffer period counter value!"), + _CPTC("PeriodCounter::update_buffer_value")); + } +} + +// ============================================================================ +// PeriodCounter::get_scalar_value () +// ============================================================================ +data_t PeriodCounter::get_scalar_value() +{ + yat::AutoMutex<> guard(this->m_dataLock); + return m_value; +} + +// ============================================================================ +// PeriodCounter::get_buffer_value () +// ============================================================================ +RawData_t PeriodCounter::get_buffer_value() + throw (Tango::DevFailed) +{ + CHECK_INTERFACE(); + + try + { + return m_interface->getCounterBufferValue(m_cfg); + } + catch (Tango::DevFailed &e) + { + ERROR_STREAM << e << std::endl; + RETHROW_DEVFAILED(e, + _CPTC("DEVICE_ERROR"), + _CPTC("Failed to get period counter buffer value"), + _CPTC("PeriodCounter::get_buffer_value")); + } + catch (...) + { + ERROR_STREAM << "Failed to get period counter buffer value" << std::endl; + THROW_DEVFAILED( + _CPTC("DEVICE_ERROR"), + _CPTC("Failed to get period counter buffer value"), + _CPTC("PeriodCounter::get_buffer_value")); + } +} + +// ============================================================================ +// PeriodCounter::get_name () +// ============================================================================ +std::string PeriodCounter::get_name() +{ + return m_cfg.name; +} + +// ============================================================================ +// PeriodCounter::get_config () +// ============================================================================ +CounterConfig PeriodCounter::get_config() +{ + return m_cfg; +} + +// ============================================================================ +// PeriodCounter::deleteObject () +// ============================================================================ +void PeriodCounter::deleteObject() + throw (Tango::DevFailed) +{ + CHECK_INTERFACE(); + + try + { + m_interface->releaseCounter(m_cfg); + } + catch(...) + { + } +} + +} // namespace PulseCounting_ns + diff --git a/src/PeriodCounter.h b/src/PeriodCounter.h new file mode 100644 index 0000000000000000000000000000000000000000..a2cd63139a3cda516809fa4fb8d0fc3ad2facb67 --- /dev/null +++ b/src/PeriodCounter.h @@ -0,0 +1,91 @@ +//============================================================================= +// PeriodCounter.h +//============================================================================= +// abstraction.......PeriodCounter for PulseCounting +// class.............PeriodCounter +// original author...S.Minolli - Nexeya +//============================================================================= + +#ifndef _PERIOD_COUNTER_H +#define _PERIOD_COUNTER_H + +// ============================================================================ +// DEPENDENCIES +// ============================================================================ +#include <yat4tango/LogHelper.h> +#include "PulseCountingTypesAndConsts.h" +#include "GenericCounterInterface.h" + +namespace PulseCounting_ns +{ + +// ============================================================================ +// class: PeriodCounter +// ============================================================================ +class PeriodCounter : public GenericCounterInterface +{ + +public: + + //- constructor + PeriodCounter (Tango::DeviceImpl * hostDevice, E_AcquisitionMode_t p_acq_mode, CountingBoardInterface * p_board); + + //- destructor + virtual ~PeriodCounter (); + + //- is available? + bool is_available(); + + //- init + void init(CounterConfig p_cfg) + throw (Tango::DevFailed); + + //- configure + void configure(CounterConfig p_cfg) + throw (Tango::DevFailed); + + //- start + void start() + throw (Tango::DevFailed); + + //- stop + void stop() + throw (Tango::DevFailed); + + //- release counter + void deleteObject() + throw (Tango::DevFailed); + + //- get State + Tango::DevState get_state() + throw (Tango::DevFailed); + + //- update scalar value + void update_scalar_value() + throw (Tango::DevFailed); + + //- update buffer value (used in "polling" mode) + void update_buffer_value() + throw (Tango::DevFailed); + + //- get scalar value + data_t get_scalar_value(); + + //- get buffer value + RawData_t get_buffer_value() + throw (Tango::DevFailed); + + //- get name + std::string get_name() + throw (Tango::DevFailed); + + //- get config + CounterConfig get_config() + throw (Tango::DevFailed); + +protected: +}; + +} // namespace PulseCounting_ns + +#endif // _PERIOD_COUNTER_H diff --git a/src/PulseCounting.cpp b/src/PulseCounting.cpp index 6beccf9be950e2a7a0a6f061d9721042161ddaf8..673588a3783d8a4c4c37d8201038284442c7b34f 100644 --- a/src/PulseCounting.cpp +++ b/src/PulseCounting.cpp @@ -620,7 +620,14 @@ void PulseCounting::get_device_property() l_cfg.dt_unitStr = config_parser.extractUnitStr(l_keys); l_cfg.memTranfer = config_parser.extractMemoryTransfer(l_keys); } - else + else if (l_cfg.mode == COUNTER_MODE_PERIOD) + { + l_cfg.edge = config_parser.extractEdge(l_keys); + l_cfg.dt_unit = config_parser.extractUnit(l_keys); + l_cfg.dt_unitStr = config_parser.extractUnitStr(l_keys); + l_cfg.memTranfer = config_parser.extractMemoryTransfer(l_keys); + } + else { if (l_cfg.mode == COUNTER_MODE_POSITION) { diff --git a/src/PulseCountingManager.cpp b/src/PulseCountingManager.cpp index e8896c6a6595d33415965648411d10165f47c284..29e9bf077eca8621a7f6fbc4410a7abb825d19a7 100644 --- a/src/PulseCountingManager.cpp +++ b/src/PulseCountingManager.cpp @@ -662,8 +662,10 @@ void PulseCountingManager::add_attributes(CounterConfig p_cfg) { CHECK_MANAGER_DYN_ATTR_MANAGER(); - // Do not create pulse width attributes for DT counters: unavailable function - if (p_cfg.mode == COUNTER_MODE_DELTATIME) + // Do not create pulse width attributes for DT & PERIOD counters: unavailable function + if ((p_cfg.mode == COUNTER_MODE_DELTATIME) || + (p_cfg.mode == COUNTER_MODE_PERIOD)) + { return; } diff --git a/src/PulseCountingManagerBuffered.cpp b/src/PulseCountingManagerBuffered.cpp index dc1c3ee769b54d6541321cf57355ebf61a82ce0a..df7215950eb9c53fa58401dd4c2959d2fdfd9f73 100644 --- a/src/PulseCountingManagerBuffered.cpp +++ b/src/PulseCountingManagerBuffered.cpp @@ -296,8 +296,15 @@ void PulseCountingManagerBuffered::periodic_job_i() } } - // if one counter in FAULT or ALARM, stop counting process - if (acq_error) + // check nexus error + if (this->m_nexus_manager->hasStorageError()) + { + m_status = "Nexus exception handled, acquisition stopped!\n"; + } + + // if one counter in FAULT or ALARM, + // or if nexus error, stop counting process + if (acq_error || (this->m_nexus_manager->hasStorageError())) { m_state = Tango::FAULT; this->m_requestedStop = true; @@ -383,8 +390,15 @@ void PulseCountingManagerBuffered::periodic_job_i() } } - // if one counter in FAULT or ALARM, stop counting process - if (acq_error) + // check nexus error + if (this->m_nexus_manager->hasStorageError()) + { + m_status = "Nexus exception handled, acquisition stopped!\n"; + } + + // if one counter in FAULT or ALARM, + // or if nexus error, stop counting process + if (acq_error || (this->m_nexus_manager->hasStorageError())) { m_state = Tango::FAULT; this->m_requestedStop = true; diff --git a/src/PulseCountingTypesAndConsts.h b/src/PulseCountingTypesAndConsts.h index e4c156e4c68b1bc07d9ae613c82d44ebd9111f1b..ec5262bad64e6e5f6be5d6fb8ce46553fc84fa43 100644 --- a/src/PulseCountingTypesAndConsts.h +++ b/src/PulseCountingTypesAndConsts.h @@ -99,7 +99,8 @@ typedef enum UNDEFINED_COUNTER_MODE = 0x0, COUNTER_MODE_EVENT = 0x1, COUNTER_MODE_POSITION = 0x2, - COUNTER_MODE_DELTATIME = 0x3 + COUNTER_MODE_DELTATIME = 0x3, + COUNTER_MODE_PERIOD = 0x4 } E_CounterMode_t; // ============================================================================ @@ -897,7 +898,7 @@ static std::vector<std::string> define_config_counter_example() { std::vector<std::string> config; config.push_back("Name:-- Counter name --"); - config.push_back("Mode:-- POS / EVT / DT --"); + config.push_back("Mode:-- POS / EVT / DT / PERIOD --"); config.push_back("Transfer:-- [ITR] / DMA (for buffered) -- optionnal --"); config.push_back("EdgeType:-- Falling / Rising --"); config.push_back("2ndEdgeType:-- DTonly --> Falling / Rising --"); diff --git a/src/main.cpp b/src/main.cpp index cb630b569b94e25f678786f63683a4930ba40ed2..ea7d8d879d98c5bbd301c0c0a300677004a9b529 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -37,10 +37,20 @@ static const char *RcsId = "$Id $"; #include <tango.h> #include <ace/ACE.h> // for timeout management in NI660XSl +#if defined(ENABLE_CRASH_REPORT) +# include <crashreporting/crash_report.h> +#else +# define DECLARE_CRASH_HANDLER +# define INSTALL_CRASH_HANDLER +#endif + +DECLARE_CRASH_HANDLER; + int main(int argc,char *argv[]) { - - Tango::Util *tg; + INSTALL_CRASH_HANDLER; + + Tango::Util *tg = 0; try { // Initialise the device server