added vector support
This commit is contained in:
@@ -19,7 +19,8 @@ DEPLIBS = $(DEPLIBS_BASE)/libcas.a $(DEPLIBSWOCAS)
|
||||
SRCS.cc += ../main.cc
|
||||
SRCS.cc += ../exServer.cc
|
||||
SRCS.cc += ../exPV.cc
|
||||
SRCS.cc += ../exSyncPV.cc
|
||||
SRCS.cc += ../exVectorPV.cc
|
||||
SRCS.cc += ../exScalarPV.cc
|
||||
SRCS.cc += ../exAsyncPV.cc
|
||||
SRCS.cc += ../exChannel.cc
|
||||
SRCS.cc += ../templInst.cc
|
||||
@@ -27,7 +28,8 @@ SRCS.cc += ../templInst.cc
|
||||
OBJS += main.o
|
||||
OBJS += exServer.o
|
||||
OBJS += exPV.o
|
||||
OBJS += exSyncPV.o
|
||||
OBJS += exVectorPV.o
|
||||
OBJS += exScalarPV.o
|
||||
OBJS += exAsyncPV.o
|
||||
OBJS += exChannel.o
|
||||
OBJS += templInst.o
|
||||
|
||||
@@ -5,8 +5,6 @@
|
||||
#include <exServer.h>
|
||||
#include <gddApps.h>
|
||||
|
||||
const double myPI = 3.14159265358979323846;
|
||||
|
||||
osiTime exPV::currentTime;
|
||||
|
||||
//
|
||||
@@ -20,9 +18,9 @@ exPV::exPV (const casCtx &ctxIn, const pvInfo &setup) :
|
||||
interest(aitFalse)
|
||||
{
|
||||
//
|
||||
// load initial value
|
||||
// no dataless PV allowed
|
||||
//
|
||||
this->scanPV();
|
||||
assert (this->info.getElementCount()>=1u);
|
||||
}
|
||||
|
||||
//
|
||||
@@ -41,55 +39,46 @@ exPV::~exPV()
|
||||
}
|
||||
|
||||
//
|
||||
// exPV::scanPV();
|
||||
// exPV::update()
|
||||
//
|
||||
void exPV::scanPV()
|
||||
caStatus exPV::update(gdd &valueIn)
|
||||
{
|
||||
caStatus status;
|
||||
double radians;
|
||||
gdd *pDD;
|
||||
float newValue;
|
||||
float limit;
|
||||
caServer *pCAS = this->getCAS();
|
||||
caServer *pCAS = this->getCAS();
|
||||
//
|
||||
// gettimeofday() is very slow under sunos4
|
||||
//
|
||||
osiTime cur (this->currentTime);
|
||||
struct timespec t;
|
||||
caStatus cas;
|
||||
|
||||
if (!pCAS) {
|
||||
return S_casApp_noSupport;
|
||||
}
|
||||
|
||||
# if DEBUG
|
||||
printf("Setting %s too:\n", this->info.getName().string());
|
||||
valueIn.dump();
|
||||
# endif
|
||||
|
||||
if (!pCAS) {
|
||||
return;
|
||||
cas = this->updateValue (valueIn);
|
||||
if (cas || !this->pValue) {
|
||||
return cas;
|
||||
}
|
||||
|
||||
cur.get (t.tv_sec, t.tv_nsec);
|
||||
this->pValue->setTimeStamp(&t);
|
||||
this->pValue->setStat (epicsAlarmNone);
|
||||
this->pValue->setSevr (epicsSevNone);
|
||||
|
||||
//
|
||||
// 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)
|
||||
// post a value change event
|
||||
//
|
||||
this->currentTime = osiTime::getCurrent();
|
||||
|
||||
pDD = new gddScalar (gddAppType_value, aitEnumFloat32);
|
||||
if (!pDD) {
|
||||
return;
|
||||
}
|
||||
|
||||
radians = (rand () * 2.0 * myPI)/RAND_MAX;
|
||||
if (this->pValue) {
|
||||
this->pValue->getConvert(newValue);
|
||||
}
|
||||
else {
|
||||
newValue = 0.0f;
|
||||
}
|
||||
newValue += (float) (sin (radians) / 10.0);
|
||||
limit = (float) this->info.getHopr();
|
||||
newValue = min (newValue, limit);
|
||||
limit = (float) this->info.getLopr();
|
||||
newValue = max (newValue, limit);
|
||||
*pDD = newValue;
|
||||
pDD->setStat (epicsAlarmNone);
|
||||
pDD->setSevr (epicsSevNone);
|
||||
status = this->update (*pDD);
|
||||
if (status) {
|
||||
errMessage (status, "scan update failed\n");
|
||||
}
|
||||
|
||||
pDD->unreference();
|
||||
if (this->interest==aitTrue) {
|
||||
casEventMask select(pCAS->valueEventMask|pCAS->logEventMask);
|
||||
this->postEvent (select, *this->pValue);
|
||||
}
|
||||
|
||||
return S_casApp_success;
|
||||
}
|
||||
|
||||
//
|
||||
@@ -97,7 +86,7 @@ void exPV::scanPV()
|
||||
//
|
||||
void exScanTimer::expire ()
|
||||
{
|
||||
pv.scanPV();
|
||||
pv.scan();
|
||||
}
|
||||
|
||||
//
|
||||
@@ -124,77 +113,6 @@ const char *exScanTimer::name() const
|
||||
return "exScanTimer";
|
||||
}
|
||||
|
||||
//
|
||||
// exPV::update ()
|
||||
//
|
||||
caStatus exPV::update(gdd &valueIn)
|
||||
{
|
||||
gdd *pNewValue;
|
||||
caServer *pCAS = this->getCAS();
|
||||
//
|
||||
// gettimeofday() is very slow under sunos4
|
||||
//
|
||||
osiTime cur (this->currentTime);
|
||||
struct timespec t;
|
||||
gddStatus gdds;
|
||||
|
||||
|
||||
if (!pCAS) {
|
||||
return S_casApp_noSupport;
|
||||
}
|
||||
|
||||
# if DEBUG
|
||||
printf("Setting %s too:\n", this->info.getName().string());
|
||||
valueIn.dump();
|
||||
# endif
|
||||
|
||||
|
||||
if (valueIn.isScalar()) {
|
||||
pNewValue = &valueIn;
|
||||
pNewValue->reference();
|
||||
}
|
||||
else {
|
||||
//
|
||||
// this does not modify the current value
|
||||
// (because it may be referenced in the event queue)
|
||||
//
|
||||
pNewValue = new gddScalar (gddAppType_value, aitEnumFloat32);
|
||||
if (!pNewValue) {
|
||||
return S_casApp_noMemory;
|
||||
}
|
||||
|
||||
gdds = gddApplicationTypeTable::
|
||||
app_table.smartCopy(pNewValue, &valueIn);
|
||||
if (gdds) {
|
||||
pNewValue->unreference();
|
||||
return S_cas_noConvert;
|
||||
}
|
||||
|
||||
pNewValue->setStat (epicsAlarmNone);
|
||||
pNewValue->setSevr (epicsSevNone);
|
||||
}
|
||||
|
||||
cur.get (t.tv_sec, t.tv_nsec);
|
||||
pNewValue->setTimeStamp(&t);
|
||||
|
||||
//
|
||||
// release old value and replace it
|
||||
// with the new one
|
||||
//
|
||||
if (this->pValue) {
|
||||
this->pValue->unreference();
|
||||
}
|
||||
this->pValue = pNewValue;
|
||||
|
||||
if (this->interest==aitTrue) {
|
||||
casEventMask select(pCAS->valueEventMask|pCAS->logEventMask);
|
||||
this->postEvent (select, *this->pValue);
|
||||
}
|
||||
|
||||
return S_casApp_success;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// exPV::bestExternalType()
|
||||
//
|
||||
@@ -354,7 +272,7 @@ caStatus exPV::getLowLimit(gdd &value)
|
||||
//
|
||||
caStatus exPV::getUnits(gdd &units)
|
||||
{
|
||||
static aitString str("@#$%");
|
||||
static aitString str("furlongs");
|
||||
units.put(str);
|
||||
return S_cas_success;
|
||||
}
|
||||
@@ -392,3 +310,19 @@ caStatus exPV::getValue(gdd &value)
|
||||
return status;
|
||||
}
|
||||
|
||||
//
|
||||
// exPV::write()
|
||||
//
|
||||
caStatus exPV::write (const casCtx &, gdd &valueIn)
|
||||
{
|
||||
return this->update (valueIn);
|
||||
}
|
||||
|
||||
//
|
||||
// exPV::read()
|
||||
//
|
||||
caStatus exPV::read (const casCtx &, gdd &protoIn)
|
||||
{
|
||||
return exServer::read(*this, protoIn);
|
||||
}
|
||||
|
||||
|
||||
99
src/cas/example/simple/exScalarPV.cc
Normal file
99
src/cas/example/simple/exScalarPV.cc
Normal file
@@ -0,0 +1,99 @@
|
||||
|
||||
#include <exServer.h>
|
||||
#include <gddApps.h>
|
||||
#include <math.h>
|
||||
#include <limits.h>
|
||||
#include <stdlib.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
|
||||
|
||||
//
|
||||
// exScalarPV::scan
|
||||
//
|
||||
void exScalarPV::scan()
|
||||
{
|
||||
caStatus status;
|
||||
double radians;
|
||||
gdd *pDD;
|
||||
float newValue;
|
||||
float limit;
|
||||
|
||||
//
|
||||
// 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 = osiTime::getCurrent();
|
||||
|
||||
pDD = new gddScalar (gddAppType_value, aitEnumFloat32);
|
||||
if (!pDD) {
|
||||
return;
|
||||
}
|
||||
|
||||
radians = (rand () * 2.0 * myPI)/RAND_MAX;
|
||||
if (this->pValue) {
|
||||
this->pValue->getConvert(newValue);
|
||||
}
|
||||
else {
|
||||
newValue = 0.0f;
|
||||
}
|
||||
newValue += (float) (sin (radians) / 10.0);
|
||||
limit = (float) this->info.getHopr();
|
||||
newValue = min (newValue, limit);
|
||||
limit = (float) this->info.getLopr();
|
||||
newValue = max (newValue, limit);
|
||||
*pDD = newValue;
|
||||
status = this->update (*pDD);
|
||||
if (status) {
|
||||
errMessage (status, "scan update failed\n");
|
||||
}
|
||||
|
||||
pDD->unreference();
|
||||
}
|
||||
|
||||
//
|
||||
// exScalarPV::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.
|
||||
//
|
||||
caStatus exScalarPV::updateValue (gdd &valueIn)
|
||||
{
|
||||
if (!valueIn.isScalar()) {
|
||||
return S_casApp_outOfBounds;
|
||||
}
|
||||
|
||||
//
|
||||
// release old value and replace it
|
||||
// with the new one
|
||||
//
|
||||
if (this->pValue) {
|
||||
this->pValue->unreference();
|
||||
}
|
||||
valueIn.reference();
|
||||
this->pValue = &valueIn;
|
||||
|
||||
return S_casApp_success;
|
||||
}
|
||||
|
||||
@@ -10,10 +10,12 @@
|
||||
#include <exServer.h>
|
||||
|
||||
const pvInfo exServer::pvList[] = {
|
||||
pvInfo (1.0e-1, "jane", 10.0f, 0.0f, excasIoSync),
|
||||
pvInfo (2.0, "fred", 10.0f, -10.0f, excasIoSync),
|
||||
pvInfo (1.0e-1, "janet", 10.0f, 0.0f, excasIoAsync),
|
||||
pvInfo (2.0, "freddy", 10.0f, -10.0f, excasIoAsync)
|
||||
pvInfo (1.0e-1, "jane", 10.0f, 0.0f, excasIoSync, 1u),
|
||||
pvInfo (2.0, "fred", 10.0f, -10.0f, excasIoSync, 1u),
|
||||
pvInfo (1.0e-1, "janet", 10.0f, 0.0f, excasIoAsync, 1u),
|
||||
pvInfo (2.0, "freddy", 10.0f, -10.0f, excasIoAsync, 1u),
|
||||
pvInfo (2.0, "alan", 10.0f, -10.0f, excasIoSync, 100u),
|
||||
pvInfo (20.0, "albert", 10.0f, -10.0f, excasIoSync, 1000u)
|
||||
};
|
||||
|
||||
//
|
||||
@@ -96,20 +98,45 @@ const pvInfo *exServer::findPV(const char *pName)
|
||||
casPV *exServer::createPV (const casCtx &ctxIn, const char *pPVName)
|
||||
{
|
||||
const pvInfo *pInfo;
|
||||
exPV *pPV;
|
||||
|
||||
pInfo = exServer::findPV(pPVName);
|
||||
if (!pInfo) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch (pInfo->getIOType()){
|
||||
case excasIoSync:
|
||||
return new exSyncPV (ctxIn, *pInfo);
|
||||
case excasIoAsync:
|
||||
return new exAsyncPV (ctxIn, *pInfo);
|
||||
default:
|
||||
return NULL;
|
||||
//
|
||||
// create an instance of the appropriate class
|
||||
// depending on the io type and the number
|
||||
// of elements
|
||||
//
|
||||
if (pInfo->getElementCount()==1u) {
|
||||
switch (pInfo->getIOType()){
|
||||
case excasIoSync:
|
||||
pPV = new exScalarPV (ctxIn, *pInfo);
|
||||
break;
|
||||
case excasIoAsync:
|
||||
pPV = new exAsyncPV (ctxIn, *pInfo);
|
||||
break;
|
||||
default:
|
||||
pPV = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
pPV = new exVectorPV (ctxIn, *pInfo);
|
||||
}
|
||||
|
||||
//
|
||||
// load initial value (this is not done in
|
||||
// the constructor because the base class's
|
||||
// pure virtual function would be called)
|
||||
//
|
||||
if (pPV) {
|
||||
pPV->scan();
|
||||
}
|
||||
|
||||
return pPV;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@@ -1,29 +1,27 @@
|
||||
//
|
||||
// Example EPICS CA server
|
||||
// Example EPICS CA server
|
||||
//
|
||||
//
|
||||
// caServer
|
||||
// |
|
||||
// exServer
|
||||
//
|
||||
// casPV
|
||||
// |
|
||||
// exPV-------------
|
||||
// | |
|
||||
// exScalarPV exVectorPV
|
||||
// |
|
||||
// exAsyncPV
|
||||
//
|
||||
//
|
||||
|
||||
|
||||
//
|
||||
// ANSI C
|
||||
//
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <limits.h>
|
||||
|
||||
//
|
||||
// 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
|
||||
|
||||
//
|
||||
// EPICS
|
||||
@@ -56,20 +54,20 @@ class pvInfo {
|
||||
public:
|
||||
pvInfo (double scanRateIn, const char *pName,
|
||||
aitFloat32 hoprIn, aitFloat32 loprIn,
|
||||
excasIoType ioTypeIn) :
|
||||
excasIoType ioTypeIn, unsigned countIn) :
|
||||
scanRate(scanRateIn), name(pName), hopr(hoprIn),
|
||||
lopr(loprIn), ioType(ioTypeIn)
|
||||
lopr(loprIn), ioType(ioTypeIn), elementCount(countIn)
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// for use when MSVC++ will not build a defualt copy constructor
|
||||
// for use when MSVC++ will not build a default copy constructor
|
||||
// for this class
|
||||
//
|
||||
pvInfo (const pvInfo ©In) :
|
||||
scanRate(copyIn.scanRate), name(copyIn.name),
|
||||
hopr(copyIn.hopr), lopr(copyIn.lopr),
|
||||
ioType(copyIn.ioType)
|
||||
ioType(copyIn.ioType), elementCount(copyIn.elementCount)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -78,12 +76,14 @@ public:
|
||||
const double getHopr () const { return this->hopr; }
|
||||
const double getLopr () const { return this->lopr; }
|
||||
const excasIoType getIOType () const { return this->ioType; }
|
||||
const unsigned getElementCount() const { return this->elementCount; }
|
||||
private:
|
||||
const double scanRate;
|
||||
const aitString name;
|
||||
const double hopr;
|
||||
const double lopr;
|
||||
const excasIoType ioType;
|
||||
const unsigned elementCount;
|
||||
};
|
||||
|
||||
class exPV;
|
||||
@@ -113,8 +113,6 @@ public:
|
||||
exPV (const casCtx &ctxIn, const pvInfo &setup);
|
||||
virtual ~exPV();
|
||||
|
||||
void scanPV();
|
||||
|
||||
void show(unsigned level);
|
||||
|
||||
//
|
||||
@@ -143,8 +141,16 @@ public:
|
||||
//
|
||||
//casChannel *createChannel ();
|
||||
|
||||
//
|
||||
// This gets called when the pv gets a new value
|
||||
//
|
||||
caStatus update (gdd &value);
|
||||
|
||||
//
|
||||
// Gets called when we add noise to the current value
|
||||
//
|
||||
virtual void scan() = 0;
|
||||
|
||||
//
|
||||
// Std PV Attribute fetch support
|
||||
//
|
||||
@@ -168,13 +174,47 @@ public:
|
||||
{
|
||||
return this->info.getScanRate();
|
||||
}
|
||||
|
||||
caStatus read (const casCtx &, gdd &protoIn);
|
||||
|
||||
caStatus write (const casCtx &, gdd &protoIn);
|
||||
|
||||
protected:
|
||||
gdd *pValue;
|
||||
exScanTimer *pScanTimer;
|
||||
const pvInfo & info;
|
||||
aitBool interest;
|
||||
private:
|
||||
static osiTime currentTime;
|
||||
|
||||
virtual caStatus updateValue (gdd &value) = 0;
|
||||
};
|
||||
|
||||
//
|
||||
// exScalerPV
|
||||
//
|
||||
class exScalarPV : public exPV {
|
||||
public:
|
||||
exScalarPV (const casCtx &ctxIn, const pvInfo &setup) :
|
||||
exPV (ctxIn, setup) {}
|
||||
void scan();
|
||||
private:
|
||||
caStatus updateValue (gdd &value);
|
||||
};
|
||||
|
||||
//
|
||||
// exVectorPV
|
||||
//
|
||||
class exVectorPV : public exPV {
|
||||
public:
|
||||
exVectorPV (const casCtx &ctxIn, const pvInfo &setup) :
|
||||
exPV (ctxIn, setup) {}
|
||||
void scan();
|
||||
|
||||
unsigned maxDimension() const;
|
||||
aitIndex maxBound (unsigned dimension) const;
|
||||
|
||||
private:
|
||||
caStatus updateValue (gdd &value);
|
||||
};
|
||||
|
||||
//
|
||||
@@ -199,37 +239,16 @@ private:
|
||||
static gddAppFuncTable<exPV> ft;
|
||||
};
|
||||
|
||||
//
|
||||
// exSyncPV
|
||||
//
|
||||
class exSyncPV : public exPV {
|
||||
public:
|
||||
exSyncPV (const casCtx &ctxIn, const pvInfo &setup);
|
||||
~exSyncPV();
|
||||
|
||||
//
|
||||
// read
|
||||
//
|
||||
caStatus read(const casCtx &ctxIn, gdd &value);
|
||||
|
||||
//
|
||||
// write
|
||||
//
|
||||
caStatus write(const casCtx &ctxIn, gdd &value);
|
||||
private:
|
||||
};
|
||||
|
||||
//
|
||||
// exAsyncPV
|
||||
// (asychronous PV)
|
||||
//
|
||||
class exAsyncPV : public exPV {
|
||||
class exAsyncPV : public exScalarPV {
|
||||
public:
|
||||
//
|
||||
// exAsyncPV()
|
||||
//
|
||||
exAsyncPV (const casCtx &ctxIn, const pvInfo &setup) :
|
||||
exPV (ctxIn, setup) {}
|
||||
exAsyncPV (const casCtx &ctxIn, const pvInfo &setup) :
|
||||
exScalarPV (ctxIn, setup) {}
|
||||
|
||||
//
|
||||
// read
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
|
||||
//
|
||||
// Example EPICS CA server
|
||||
//
|
||||
|
||||
#include <exServer.h>
|
||||
|
||||
//
|
||||
// exSyncPV::exSyncPV()
|
||||
//
|
||||
exSyncPV::exSyncPV (const casCtx &ctxIn, const pvInfo &setup) :
|
||||
exPV (ctxIn, setup)
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// exSyncPV::~exSyncPV()
|
||||
//
|
||||
exSyncPV::~exSyncPV()
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// exSyncPV::write()
|
||||
//
|
||||
caStatus exSyncPV::write (const casCtx &, gdd &valueIn)
|
||||
{
|
||||
return this->update (valueIn);
|
||||
}
|
||||
|
||||
//
|
||||
// exSyncPV::read()
|
||||
//
|
||||
caStatus exSyncPV::read (const casCtx &, gdd &protoIn)
|
||||
{
|
||||
return exServer::read(*this, protoIn);
|
||||
}
|
||||
|
||||
237
src/cas/example/simple/exVectorPV.cc
Normal file
237
src/cas/example/simple/exVectorPV.cc
Normal file
@@ -0,0 +1,237 @@
|
||||
|
||||
#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
|
||||
|
||||
//
|
||||
// exVectorPV::maxDimension()
|
||||
//
|
||||
unsigned exVectorPV::maxDimension() const
|
||||
{
|
||||
return 1u;
|
||||
}
|
||||
|
||||
//
|
||||
// exVectorPV::maxBound()
|
||||
//
|
||||
aitIndex exVectorPV::maxBound (unsigned dimension) const
|
||||
{
|
||||
if (dimension==0u) {
|
||||
return this->info.getElementCount();
|
||||
}
|
||||
else {
|
||||
return 0u;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// exVectorPV::scan
|
||||
//
|
||||
void exVectorPV::scan()
|
||||
{
|
||||
caStatus status;
|
||||
double radians;
|
||||
gdd *pDD;
|
||||
aitFloat32 *pF, *pFE, *pCF;
|
||||
float newValue;
|
||||
float limit;
|
||||
|
||||
//
|
||||
// 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 = osiTime::getCurrent();
|
||||
|
||||
pDD = new gddAtomic (gddAppType_value, aitEnumFloat32,
|
||||
1u, this->info.getElementCount());
|
||||
if (pDD==NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// allocate array buffer
|
||||
//
|
||||
pF = new aitFloat32 [this->info.getElementCount()];
|
||||
if (!pF) {
|
||||
pDD->unreference();
|
||||
}
|
||||
|
||||
//
|
||||
// double check for reasonable bounds on the
|
||||
// current value
|
||||
//
|
||||
pCF=NULL;
|
||||
if (this->pValue) {
|
||||
if (this->pValue->dimension()==1u) {
|
||||
const gddBounds *pB = this->pValue->getBounds();
|
||||
if (pB[0u].size()==this->info.getElementCount()) {
|
||||
pCF = *pDD;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 = min (newValue, limit);
|
||||
limit = (float) this->info.getLopr();
|
||||
newValue = max (newValue, limit);
|
||||
*(pF++) = newValue;
|
||||
}
|
||||
|
||||
//
|
||||
// install the buffer into the DD
|
||||
//
|
||||
*pDD = pF;
|
||||
|
||||
status = this->update (*pDD);
|
||||
if (status) {
|
||||
errMessage (status, "scan update failed\n");
|
||||
}
|
||||
|
||||
pDD->unreference();
|
||||
}
|
||||
|
||||
//
|
||||
// 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(gdd &valueIn)
|
||||
{
|
||||
enum {replace, dontReplace} replFlag = dontReplace;
|
||||
gddStatus gdds;
|
||||
gdd *pNewValue;
|
||||
|
||||
//
|
||||
// Check bounds of incoming request
|
||||
// (and see if we are replacing all elements -
|
||||
// replaceOk==TRUE)
|
||||
//
|
||||
if (valueIn.isAtomic()) {
|
||||
if (valueIn.dimension()!=1u) {
|
||||
return S_casApp_badDimension;
|
||||
}
|
||||
const gddBounds* pb = valueIn.getBounds();
|
||||
if (pb[0u].first()!=0u) {
|
||||
return S_casApp_outOfBounds;
|
||||
}
|
||||
if (pb[0u].size()==this->info.getElementCount()) {
|
||||
replFlag = replace;
|
||||
}
|
||||
else if (pb[0u].size()>this->info.getElementCount()) {
|
||||
return S_casApp_outOfBounds;
|
||||
}
|
||||
}
|
||||
else if (!valueIn.isScalar()) {
|
||||
//
|
||||
// no containers
|
||||
//
|
||||
return S_casApp_outOfBounds;
|
||||
}
|
||||
|
||||
if (replFlag==replace) {
|
||||
//
|
||||
// It is most efficient to replace all elements
|
||||
//
|
||||
valueIn.reference();
|
||||
pNewValue = &valueIn;
|
||||
}
|
||||
else {
|
||||
aitFloat32 *pF, *pFE;
|
||||
|
||||
//
|
||||
// Create a new array data descriptor
|
||||
// (so that old values that may be referenced on the
|
||||
// event queue are not replaced)
|
||||
//
|
||||
pNewValue = new gddAtomic (gddAppType_value, aitEnumFloat32,
|
||||
1u, this->info.getElementCount());
|
||||
if (pNewValue==NULL) {
|
||||
return S_casApp_noMemory;
|
||||
}
|
||||
|
||||
//
|
||||
// copy over the old values if they exist
|
||||
// (or initialize all elements to zero)
|
||||
//
|
||||
if (this->pValue) {
|
||||
gdds = pNewValue->copy(this->pValue);
|
||||
if (gdds) {
|
||||
pNewValue->unreference();
|
||||
return S_cas_noConvert;
|
||||
}
|
||||
}
|
||||
else {
|
||||
//
|
||||
// allocate array buffer
|
||||
//
|
||||
pF = new aitFloat32 [this->info.getElementCount()];
|
||||
if (!pF) {
|
||||
pNewValue->unreference();
|
||||
return S_casApp_noMemory;
|
||||
}
|
||||
|
||||
//
|
||||
// Install (and initialize) array buffer
|
||||
// if no old values exist
|
||||
//
|
||||
pFE = &pF[this->info.getElementCount()];
|
||||
while (pF<pFE) {
|
||||
*(pF++) = 0.0;
|
||||
}
|
||||
*pNewValue = pF;
|
||||
}
|
||||
|
||||
//
|
||||
// insert the values that they are writing
|
||||
//
|
||||
gdds = pNewValue->put(&valueIn);
|
||||
if (gdds) {
|
||||
pNewValue->unreference();
|
||||
return S_cas_noConvert;
|
||||
}
|
||||
}
|
||||
|
||||
if (this->pValue) {
|
||||
this->pValue->unreference();
|
||||
}
|
||||
this->pValue = pNewValue;
|
||||
|
||||
return S_casApp_success;
|
||||
}
|
||||
|
||||
@@ -15,11 +15,6 @@ int main (int argc, const char **argv)
|
||||
aitBool forever = aitTrue;
|
||||
int i;
|
||||
|
||||
pCAS = new exServer(32u,5u,500u);
|
||||
if (!pCAS) {
|
||||
return (-1);
|
||||
}
|
||||
|
||||
for (i=1; i<argc; i++) {
|
||||
if (sscanf(argv[i], "-d %u", &debugLevel)==1) {
|
||||
continue;
|
||||
@@ -33,6 +28,11 @@ int main (int argc, const char **argv)
|
||||
return (1);
|
||||
}
|
||||
|
||||
pCAS = new exServer(32u,5u,500u);
|
||||
if (!pCAS) {
|
||||
return (-1);
|
||||
}
|
||||
|
||||
pCAS->setDebugLevel(debugLevel);
|
||||
|
||||
if (forever) {
|
||||
|
||||
Reference in New Issue
Block a user