Files
ISTTOK/epics/css/sys-mng-opi/CSS/MARTe/Interfaces/EPICSLib/exVectorPV.cpp
2019-10-21 16:02:55 +01:00

275 lines
6.6 KiB
C++

/*************************************************************************\
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE-EPICS that is included with this distribution.
\*************************************************************************/
#include "exServer.h"
#include "gddApps.h"
#define myPI 3.14159265358979323846
//
// SUN C++ does not have RAND_MAX yet
//
#if ! defined(RAND_MAX)
//
// Apparently SUN C++ is using the SYSV version of rand
//
# if 0
# define RAND_MAX INT_MAX
# else
# define RAND_MAX SHRT_MAX
# endif
#endif
//
// special gddDestructor guarantees same form of new and delete
//
class exVecDestructor: public gddDestructor {
virtual void run (void *);
};
//
// exVectorPV::maxDimension()
//
unsigned exVectorPV::maxDimension() const
{
return 1u;
}
//
// exVectorPV::maxBound()
//
aitIndex exVectorPV::maxBound (unsigned dimension) const // X aCC 361
{
if (dimension==0u) {
return this->info.getElementCount();
}
else {
return 0u;
}
}
//
// exVectorPV::scan
//
void exVectorPV::scan()
{
caStatus status;
double radians;
smartGDDPointer pDD;
aitFloat32 *pF, *pFE;
const aitFloat32 *pCF;
float newValue;
float limit;
exVecDestructor *pDest;
int gddStatus;
//
// update current time (so we are not required to do
// this every time that we write the PV which impacts
// throughput under sunos4 because gettimeofday() is
// slow)
//
this->currentTime = epicsTime::getCurrent();
pDD = new gddAtomic (gddAppType_value, aitEnumFloat64,
1u, this->info.getElementCount());
if ( ! pDD.valid () ) {
return;
}
//
// smart pointer class manages reference count after this point
//
gddStatus = pDD->unreference();
assert (!gddStatus);
//
// allocate array buffer
//
pF = new aitFloat32 [this->info.getElementCount()];
if (!pF) {
return;
}
pDest = new exVecDestructor;
if (!pDest) {
delete [] pF;
return;
}
//
// install the buffer into the DD
// (do this before we increment pF)
//
pDD->putRef(pF, pDest);
//
// double check for reasonable bounds on the
// current value
//
pCF=NULL;
if ( this->pValue.valid () ) {
if (this->pValue->dimension()==1u) {
const gddBounds *pB = this->pValue->getBounds();
if (pB[0u].size()==this->info.getElementCount()) {
pCF = *this->pValue;
}
}
}
pFE = &pF[this->info.getElementCount()];
while (pF<pFE) {
radians = (rand () * 2.0 * myPI)/RAND_MAX;
if (pCF) {
newValue = *pCF++;
}
else {
newValue = 0.0f;
}
newValue += (float) (sin (radians) / 10.0);
limit = (float) this->info.getHopr();
newValue = tsMin (newValue, limit);
limit = (float) this->info.getLopr();
newValue = tsMax (newValue, limit);
*(pF++) = newValue;
}
aitTimeStamp gddts = this->currentTime;
pDD->setTimeStamp ( & gddts );
// antonio code
if ( (this->info.getScanPeriod() > 0.0) ) {
status = this->update ( *pDD, true, false );
if (status!=S_casApp_success) {
errMessage ( status, "vector scan update failed\n" );
}
}
// delete &((gddAtomic ) *pDD);
//delete &((gdd) *pDD);
}
//
// exVectorPV::updateValue ()
//
// NOTES:
// 1) This should have a test which verifies that the
// incoming value in all of its various data types can
// be translated into a real number?
// 2) We prefer to unreference the old PV value here and
// reference the incomming value because this will
// result in value change events each retaining an
// independent value on the event queue. With large arrays
// this may result in too much memory consumtion on
// the event queue.
//
caStatus exVectorPV::updateValue ( const gdd & value )
{
//
// Check bounds of incoming request
// (and see if we are replacing all elements -
// replaceOk==true)
//
// Perhaps much of this is unnecessary since the
// server lib checks the bounds of all requests
//
if ( value.isAtomic()) {
if ( value.dimension() != 1u ) {
return S_casApp_badDimension;
}
const gddBounds* pb = value.getBounds ();
if ( pb[0u].first() != 0u ) {
return S_casApp_outOfBounds;
}
else if ( pb[0u].size() > this->info.getElementCount() ) {
return S_casApp_outOfBounds;
}
}
else if ( ! value.isScalar() ) {
//
// no containers
//
return S_casApp_outOfBounds;
}
//
// Create a new array data descriptor
// (so that old values that may be referenced on the
// event queue are not replaced)
//
smartGDDPointer pNewValue ( new gddAtomic ( gddAppType_value, aitEnumFloat64,
1u, this->info.getElementCount() ) );
if ( ! pNewValue.valid() ) {
return S_casApp_noMemory;
}
//
// smart pointer class takes care of the reference count
// from here down
//
gddStatus gdds = pNewValue->unreference( );
assert ( ! gdds );
//
// allocate array buffer
//
aitFloat64 * pF = new aitFloat64 [this->info.getElementCount()];
if (!pF) {
return S_casApp_noMemory;
}
//
// Install (and initialize) array buffer
// if no old values exist
//
unsigned count = this->info.getElementCount();
for ( unsigned i = 0u; i < count; i++ ) {
pF[i] = 0.0f;
}
exVecDestructor * pDest = new exVecDestructor;
if (!pDest) {
delete [] pF;
return S_casApp_noMemory;
}
//
// install the buffer into the DD
// (do this before we increment pF)
//
pNewValue->putRef ( pF, pDest );
//
// copy in the values that they are writing
//
gdds = pNewValue->put( & value );
if ( gdds ) {
return S_cas_noConvert;
}
this->pValue = pNewValue;
return S_casApp_success;
}
//
// exVecDestructor::run()
//
// special gddDestructor guarantees same form of new and delete
//
void exVecDestructor::run ( void *pUntyped )
{
aitFloat32 * pf = reinterpret_cast < aitFloat32 * > ( pUntyped );
delete [] pf;
}