342 lines
7.9 KiB
C
342 lines
7.9 KiB
C
/*--------------------------------------------------------------------------
|
|
|
|
S I M C O U N T E R
|
|
|
|
As the Schluempfe fail to provide proper complete instruments for
|
|
testing, we need a simulated counter. This is implemented here.
|
|
|
|
|
|
Mark Koennecke, January 1997
|
|
|
|
Copyright:
|
|
|
|
Labor fuer Neutronenstreuung
|
|
Paul Scherrer Institut
|
|
CH-5423 Villigen-PSI
|
|
|
|
|
|
The authors hereby grant permission to use, copy, modify, distribute,
|
|
and license this software and its documentation for any purpose, provided
|
|
that existing copyright notices are retained in all copies and that this
|
|
notice is included verbatim in any distributions. No written agreement,
|
|
license, or royalty fee is required for any of the authorized uses.
|
|
Modifications to this software may be copyrighted by their authors
|
|
and need not follow the licensing terms described here, provided that
|
|
the new terms are clearly indicated on the first page of each file where
|
|
they apply.
|
|
|
|
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
|
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
|
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
|
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
|
POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
|
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE
|
|
IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
|
|
NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
|
|
MODIFICATIONS.
|
|
----------------------------------------------------------------------------*/
|
|
#include <stdlib.h>
|
|
#include <assert.h>
|
|
#include <math.h>
|
|
#include <time.h>
|
|
#include "fortify.h"
|
|
#include <string.h>
|
|
#include "sics.h"
|
|
#include "countdriv.h"
|
|
/*---------------------------------------------------------------------------
|
|
A SIMCOUNTER HAS a BUILT IN FAILURE RATE OF 10% FOR TESTING ERROR HANDLING
|
|
CODE. A negative failure rate means absolute success.
|
|
*/
|
|
static float FAILRATE;
|
|
/*----------------------------------------------------------------------------*/
|
|
static float SimRandom(void)
|
|
{
|
|
float fVal;
|
|
|
|
fVal = ((float) rand() / (float) RAND_MAX) * 100.0;
|
|
return fVal;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
typedef struct {
|
|
long lEnd;
|
|
int iPause;
|
|
long tStart;
|
|
} SimSt;
|
|
/*---------------------------------------------------------------------------*/
|
|
static int SIMGetStatus(struct __COUNTER *self, float *fControl)
|
|
{
|
|
SimSt *pSim = NULL;
|
|
time_t tD, tDe;
|
|
int iRun;
|
|
|
|
assert(self);
|
|
pSim = (SimSt *) self->pData;
|
|
assert(pSim);
|
|
|
|
/*
|
|
no fail, no wait case
|
|
*/
|
|
if (FAILRATE < .0) {
|
|
return HWIdle;
|
|
}
|
|
|
|
if (pSim->iPause == 1) {
|
|
return HWPause;
|
|
}
|
|
|
|
if (SimRandom() < FAILRATE) {
|
|
return HWFault;
|
|
}
|
|
|
|
/* calculate time */
|
|
self->fTime = (long) time(NULL) - pSim->tStart;
|
|
|
|
iRun = 1;
|
|
if (self->eMode == eTimer) {
|
|
if ((long) time(&tD) > pSim->lEnd) {
|
|
iRun = 0;
|
|
}
|
|
tDe = pSim->lEnd - tD;
|
|
*fControl = (float) tDe;
|
|
|
|
} else {
|
|
pSim->lEnd += SimRandom();
|
|
if (pSim->lEnd > (long) self->fPreset) {
|
|
iRun = 0;
|
|
}
|
|
*fControl = (float) pSim->lEnd;
|
|
}
|
|
if (iRun) {
|
|
return HWBusy;
|
|
} else {
|
|
return HWIdle;
|
|
}
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
static int SIMStart(struct __COUNTER *self)
|
|
{
|
|
SimSt *pSim = NULL;
|
|
time_t tD;
|
|
int iRun;
|
|
|
|
assert(self);
|
|
pSim = (SimSt *) self->pData;
|
|
assert(pSim);
|
|
|
|
pSim->iPause = 0;
|
|
pSim->tStart = time(NULL);
|
|
if (self->eMode == eTimer) {
|
|
pSim->lEnd = (long) time(&tD) + (long) self->fPreset;
|
|
} else {
|
|
pSim->lEnd = 0;
|
|
}
|
|
|
|
if (FAILRATE < .0) {
|
|
return OKOK;
|
|
}
|
|
|
|
if (SimRandom() < FAILRATE) {
|
|
return HWFault;
|
|
}
|
|
|
|
return OKOK;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
static int SIMPause(struct __COUNTER *self)
|
|
{
|
|
SimSt *pSim = NULL;
|
|
time_t tD;
|
|
int iRun;
|
|
|
|
assert(self);
|
|
pSim = (SimSt *) self->pData;
|
|
assert(pSim);
|
|
|
|
pSim->iPause = 1;
|
|
|
|
/*
|
|
no fail, no wait case
|
|
*/
|
|
if (FAILRATE < .0) {
|
|
return OKOK;
|
|
}
|
|
|
|
if (SimRandom() < FAILRATE) {
|
|
return HWFault;
|
|
}
|
|
|
|
return OKOK;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
static int SIMContinue(struct __COUNTER *self)
|
|
{
|
|
SimSt *pSim = NULL;
|
|
time_t tD;
|
|
int iRun;
|
|
|
|
assert(self);
|
|
pSim = (SimSt *) self->pData;
|
|
assert(pSim);
|
|
|
|
pSim->iPause = 0;
|
|
|
|
if (FAILRATE < .0) {
|
|
return OKOK;
|
|
}
|
|
|
|
if (SimRandom() < FAILRATE) {
|
|
return HWFault;
|
|
}
|
|
|
|
return OKOK;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
static int SIMHalt(struct __COUNTER *self)
|
|
{
|
|
SimSt *pSim = NULL;
|
|
int iRun;
|
|
|
|
assert(self);
|
|
pSim = (SimSt *) self->pData;
|
|
assert(pSim);
|
|
|
|
if (FAILRATE < .0) {
|
|
return OKOK;
|
|
}
|
|
|
|
if (SimRandom() < FAILRATE) {
|
|
return HWFault;
|
|
}
|
|
if (self->eMode == eTimer) {
|
|
pSim->lEnd = 0;
|
|
} else {
|
|
pSim->lEnd = (long) self->fPreset + 10;
|
|
}
|
|
return OKOK;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
static int SIMReadValues(struct __COUNTER *self)
|
|
{
|
|
SimSt *pSim = NULL;
|
|
int i;
|
|
|
|
assert(self);
|
|
pSim = (SimSt *) self->pData;
|
|
assert(pSim);
|
|
|
|
/*
|
|
no fail, no wait case
|
|
*/
|
|
if (FAILRATE < .0) {
|
|
for (i = 0; i < MAXCOUNT; i++) {
|
|
self->lCounts[i] = (long) (SimRandom() * 100);
|
|
}
|
|
self->lCounts[1] = self->fPreset;
|
|
return OKOK;
|
|
}
|
|
|
|
if (SimRandom() < FAILRATE) {
|
|
return HWFault;
|
|
}
|
|
|
|
for (i = 0; i < MAXCOUNT; i++) {
|
|
self->lCounts[i] = (long) (SimRandom() * 100);
|
|
}
|
|
self->lCounts[1] = self->fPreset;
|
|
return OKOK;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
static int SIMGetError(struct __COUNTER *self, int *iCode, char *error,
|
|
int iErrLen)
|
|
{
|
|
strlcpy(error, "Randomly simulated counter error", iErrLen);
|
|
*iCode = 1;
|
|
return 1;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
static int SIMTryAndFixIt(struct __COUNTER *self, int iCode)
|
|
{
|
|
if (SimRandom() < FAILRATE) {
|
|
return COTERM;
|
|
}
|
|
return COREDO;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
static int SIMSet(struct __COUNTER *self, char *name, int iCter,
|
|
float FVal)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
static int SIMGet(struct __COUNTER *self, char *name, int iCter,
|
|
float *fVal)
|
|
{
|
|
*fVal = 25.999;
|
|
return 1;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
static int SIMSend(struct __COUNTER *self, char *pText,
|
|
char *pReply, int iReplyLen)
|
|
{
|
|
strlcpy(pReply, "Simulated response", iReplyLen);
|
|
return 1;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
pCounterDriver NewSIMCounter(char *name, float fFail)
|
|
{
|
|
pCounterDriver pRes = NULL;
|
|
SimSt *pData = NULL;
|
|
int iRet;
|
|
int iC1, iC2, iC3;
|
|
char *pErr;
|
|
char pBueffel[132];
|
|
|
|
pRes = CreateCounterDriver(name, "SIM");
|
|
if (!pRes) {
|
|
return NULL;
|
|
}
|
|
|
|
pData = (SimSt *) malloc(sizeof(SimSt));
|
|
if (!pData) {
|
|
DeleteCounterDriver(pRes);
|
|
return NULL;
|
|
}
|
|
pData->lEnd = 0;
|
|
pData->iPause = 0;
|
|
pRes->pData = (void *) pData;
|
|
pRes->iNoOfMonitors = 8;
|
|
pRes->fTime = 0;
|
|
|
|
/* assign functions */
|
|
pRes->GetStatus = SIMGetStatus;
|
|
pRes->Start = SIMStart;
|
|
pRes->Halt = SIMHalt;
|
|
pRes->ReadValues = SIMReadValues;
|
|
pRes->GetError = SIMGetError;
|
|
pRes->TryAndFixIt = SIMTryAndFixIt;
|
|
pRes->Pause = SIMPause;
|
|
pRes->Continue = SIMContinue;
|
|
pRes->Set = SIMSet;
|
|
pRes->Get = SIMGet;
|
|
pRes->Send = SIMSend;
|
|
pRes->KillPrivate = NULL;
|
|
|
|
FAILRATE = fFail;
|
|
return pRes;
|
|
}
|