SKIPPED: psi/dilludriv.c psi/el755driv.c psi/eurodriv.c psi/eve.c psi/eve.h psi/fsm.c psi/ipsdriv.c psi/itc4driv.c psi/itcdriv.c psi/lcdriv.c psi/logger.c psi/logger.h psi/slsmagnet.c
270 lines
7.0 KiB
C
270 lines
7.0 KiB
C
/*--------------------------------------------------------------------------
|
|
S I M E V
|
|
|
|
This file contains a simulation for a environment device driver.
|
|
This is useful for SW testing .
|
|
|
|
|
|
Mark Koennecke, Juli 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 <string.h>
|
|
#include <stdlib.h>
|
|
#include <time.h>
|
|
#include <math.h>
|
|
#include <assert.h>
|
|
#include "fortify.h"
|
|
#include "conman.h"
|
|
#include "servlog.h"
|
|
#include "fortify.h"
|
|
|
|
#include "evdriver.h"
|
|
#include "simev.h"
|
|
/*-----------------------------------------------------------------------*/
|
|
typedef struct {
|
|
float fFailure;
|
|
float fTarget;
|
|
float fSpeed;
|
|
time_t tFinish;
|
|
} SimST, *pSimST;
|
|
/*-----------------------------------------------------------------------*/
|
|
static float SimRandom(void)
|
|
{
|
|
float fVal;
|
|
|
|
fVal = ( (float) rand() / (float)RAND_MAX) * 100.0;
|
|
return fVal;
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
static int RunComplete(pEVDriver self)
|
|
{
|
|
pSimST pMe = NULL;
|
|
time_t tD;
|
|
|
|
assert(self);
|
|
pMe = (pSimST)self->pPrivate;
|
|
assert(pMe);
|
|
|
|
if(pMe->fFailure < .0){
|
|
return 1;
|
|
}
|
|
|
|
if((int)time(&tD) > pMe->tFinish)
|
|
{
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
static int GetSimPos(pEVDriver self, float *fPos)
|
|
{
|
|
pSimST pMe = NULL;
|
|
|
|
assert(self);
|
|
pMe = (pSimST)self->pPrivate;
|
|
assert(pMe);
|
|
|
|
|
|
if(SimRandom() < pMe->fFailure)
|
|
{
|
|
*fPos = SimRandom();
|
|
return 0;
|
|
}
|
|
|
|
if(RunComplete(self))
|
|
{
|
|
if(pMe->fFailure < .0){
|
|
*fPos = pMe->fTarget;
|
|
} else {
|
|
*fPos = pMe->fTarget + SimRandom()/50-1.0;
|
|
}
|
|
}
|
|
else /* simulate a mispositioned motor */
|
|
{
|
|
*fPos = pMe->fTarget - 10.;
|
|
return 1;
|
|
}
|
|
return 1;
|
|
}
|
|
/*----------------------------------------------------------------------------*/
|
|
static int SimRun(pEVDriver self, float fVal)
|
|
{
|
|
pSimST pMe = NULL;
|
|
float fDiff;
|
|
time_t tD;
|
|
|
|
assert(self);
|
|
pMe = (pSimST)self->pPrivate;
|
|
assert(pMe);
|
|
|
|
/* calculate time for completion */
|
|
fDiff = fVal - pMe->fTarget;
|
|
if(fDiff < .0) fDiff = -fDiff;
|
|
pMe->tFinish = (int)time(&tD) + (int)(fDiff/pMe->fSpeed);
|
|
|
|
pMe->fTarget = fVal;
|
|
|
|
/* in a fifth the failures, simply die, else simply do not find pos */
|
|
if(SimRandom() < (pMe->fFailure/5))
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
static int SimError(pEVDriver self, int *iCode, char *error, int iErrLen)
|
|
{
|
|
assert(self);
|
|
|
|
if(RunComplete(self))
|
|
{
|
|
*iCode = 56;
|
|
strncpy(error,"ERROR: (-: Simulated environment device error :-) ",iErrLen);
|
|
}
|
|
else
|
|
{
|
|
*iCode = 12;
|
|
strncpy(error,"Environment still creeping along",iErrLen-1);
|
|
}
|
|
return 1;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
static int SimSend(pEVDriver self, char *pCommand, char *pReply, int iLen)
|
|
{
|
|
pSimST pMe = NULL;
|
|
float fDiff;
|
|
time_t tD;
|
|
|
|
assert(self);
|
|
pMe = (pSimST)self->pPrivate;
|
|
assert(pMe);
|
|
|
|
if(SimRandom() < pMe->fFailure)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
strncpy(pReply,"Device gracefully accepted command",iLen);
|
|
return 1;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
static int SimSim(pEVDriver self)
|
|
{
|
|
return 1;
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
static int SimFix(pEVDriver self, int iError)
|
|
{
|
|
float fRand;
|
|
|
|
/* return the three values MOTREDO, MOTFAIL, MOTOK with a third
|
|
randomness
|
|
*/
|
|
assert(self);
|
|
fRand = SimRandom();
|
|
|
|
if(iError == 12)
|
|
{
|
|
return DEVREDO;
|
|
}
|
|
|
|
SICSLogWrite("Simulated Environment device dying randomly",eHWError);
|
|
if(fRand < 0.3333)
|
|
{
|
|
return DEVOK;
|
|
}
|
|
else if(fRand < 0.66666)
|
|
{
|
|
return DEVREDO;
|
|
}
|
|
else
|
|
{
|
|
return DEVFAULT;
|
|
}
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
static int SimHalt(pEVDriver *self)
|
|
{
|
|
assert(self);
|
|
|
|
return 1;
|
|
}
|
|
/*------------------------------------------------------------------------*/
|
|
pEVDriver CreateSIMEVDriver(int argc, char *argv[])
|
|
{
|
|
pEVDriver pNew = NULL;
|
|
pSimST pSim = NULL;
|
|
|
|
pNew = CreateEVDriver(argc,argv);
|
|
pSim = (pSimST)malloc(sizeof(SimST));
|
|
if(!pNew || !pSim)
|
|
{
|
|
return NULL;
|
|
}
|
|
pNew->pPrivate = pSim;
|
|
/* This causes problems with fortify. Apparently the free does not
|
|
get replaced properly with the proper debug malloc function.
|
|
pNew->KillPrivate = free;
|
|
*/
|
|
|
|
pNew->KillPrivate = NULL;
|
|
|
|
/* initalise SimST */
|
|
pSim->fFailure = .1;
|
|
pSim->fSpeed = 1.;
|
|
pSim->fTarget = 0.0;
|
|
pSim->tFinish = 0;
|
|
|
|
/* are there parameters which give values for SIM ? */
|
|
if(argc > 0)
|
|
{
|
|
pSim->fFailure = atof(argv[0]);
|
|
}
|
|
if(argc > 1)
|
|
{
|
|
pSim->fSpeed = atof(argv[1]);
|
|
}
|
|
|
|
/* initialise function pointers */
|
|
pNew->SetValue = SimRun;
|
|
pNew->GetValue = GetSimPos;
|
|
pNew->Send = SimSend;
|
|
pNew->GetError = SimError;
|
|
pNew->TryFixIt = SimFix;
|
|
pNew->Init = SimSim;
|
|
pNew->Close = SimSim;
|
|
|
|
return pNew;
|
|
}
|