- Refactored site specific stuff into a site module - PSI specific stuff is now in the PSI directory. - The old version has been tagged with pre-ansto SKIPPED: psi/A1931.c psi/A1931.h psi/amor2t.c psi/amor2t.h psi/amor2t.i psi/amor2t.tex psi/amor2t.w psi/amorscan.c psi/amorscan.h psi/amorscan.w psi/amorstat.c psi/amorstat.h psi/amorstat.i psi/amorstat.tex psi/amorstat.w psi/bruker.c psi/bruker.h psi/bruker.w psi/buffer.c psi/buffer.h psi/dilludriv.c psi/dilludriv.h psi/dmc.c psi/dmc.h psi/dmc.w psi/docho.c psi/ecb.c psi/ecb.h psi/ecb.i psi/ecb.w psi/ecbdriv.c psi/ecbdriv.h psi/el734dc.c psi/el734driv.c psi/el755driv.c psi/el755driv.h psi/faverage.c psi/faverage.h psi/faverage.tex psi/faverage.w psi/fowrite.c psi/fowrite.h psi/itc4.c psi/itc4.h psi/itc4.w psi/itc4driv.c psi/ltc11.c psi/ltc11.h psi/nextrics.c psi/nextrics.h psi/nxamor.c psi/nxamor.h psi/nxamor.tex psi/nxamor.w psi/pimotor.c psi/pimotor.h psi/pimotor.tex psi/pimotor.w psi/pipiezo.c psi/polterwrite.c psi/polterwrite.h psi/psi.c psi/ruli.c psi/ruli.h psi/sanscook.c psi/sanswave.c psi/sanswave.h psi/sanswave.tex psi/sanswave.w psi/serial.c psi/serial.h psi/serial.w psi/sinqhmdriv.c psi/sinqhmdriv.i psi/sinqhmdriv.w psi/slsmagnet.c psi/sps.c psi/sps.h psi/sps.i psi/sps.tex psi/sps.w psi/swmotor.c psi/swmotor.h psi/swmotor.i psi/tas.c psi/tas.h psi/tas.tex psi/tas.w psi/tasdrive.c psi/tasinit.c psi/tasscan.c psi/tasu.h psi/tasutil.c psi/tdchm.c psi/tdchm.h psi/tecsdriv.c psi/tecsdriv.h psi/velodorn.c psi/velodorn.h psi/velodorn.w psi/velodornier.c psi/hardsup/README psi/hardsup/StrMatch.c psi/hardsup/asynsrv_def.h psi/hardsup/asynsrv_errcodes.h psi/hardsup/asynsrv_mark.c psi/hardsup/asynsrv_utility.c psi/hardsup/c_interfaces.c psi/hardsup/dillutil.c psi/hardsup/dillutil.h psi/hardsup/el734_def.h psi/hardsup/el734_errcodes.h psi/hardsup/el734_utility.c psi/hardsup/el734fix.h psi/hardsup/el734tcl.c psi/hardsup/el737_def.h psi/hardsup/el737_errcodes.h psi/hardsup/el737_utility.c psi/hardsup/el737fix.h psi/hardsup/el737tcl.c psi/hardsup/el755_def.h psi/hardsup/el755_errcodes.h psi/hardsup/el755_errorlog.c psi/hardsup/el755_utility.c psi/hardsup/err.c psi/hardsup/failinet.c psi/hardsup/geterrno.c psi/hardsup/itc4util.c psi/hardsup/itc4util.h psi/hardsup/make_gen psi/hardsup/makefile_alpha psi/hardsup/makefile_linux psi/hardsup/makeprint.c psi/hardsup/rs232c_def.h psi/hardsup/serialsinq.c psi/hardsup/serialsinq.h psi/hardsup/sinq_defs.h psi/hardsup/sinq_prototypes.h psi/hardsup/sinqhm.c psi/hardsup/sinqhm.h psi/hardsup/sinqhm_def.h psi/hardsup/stredit.c psi/hardsup/strjoin.c psi/hardsup/table.c psi/hardsup/table.h psi/hardsup/velsel_def.h psi/hardsup/velsel_utility.c psi/motor/Makefile psi/motor/el734_test psi/motor/el734_test.c psi/motor/makeprint.c psi/sinqhm/FOCUS_gbl.h psi/sinqhm/FOCUS_srv_main.c psi/sinqhm/Makefile psi/sinqhm/SinqHM_bootParamsConfig.c psi/sinqhm/SinqHM_bootUtil.c psi/sinqhm/SinqHM_def.h psi/sinqhm/SinqHM_gbl.h psi/sinqhm/SinqHM_srv_filler.c psi/sinqhm/SinqHM_srv_main.c psi/sinqhm/SinqHM_srv_routines.c psi/sinqhm/SinqHM_srv_server.c psi/sinqhm/bld psi/sinqhm/bld2 psi/sinqhm/bldmen psi/sinqhm/hist_mem_notes.tex psi/sinqhm/hist_mem_spec.tex psi/sinqhm/hist_mem_spec_fig1.ps psi/sinqhm/hist_mem_spec_fig2.ps psi/sinqhm/hist_mem_spec_fig3.ps psi/sinqhm/hist_mem_spec_fig4.ps psi/sinqhm/lwl_client.c psi/sinqhm/lwl_server.c psi/sinqhm/make_sinqhm.com psi/sinqhm/monitor.c psi/sinqhm/psi_logo.ps psi/sinqhm/sinq_logo.ps psi/sinqhm/sinqhm_bootutil_client.c psi/sinqhm/sinqhm_client.c psi/sinqhm/sinqhm_ctrl.c psi/sinqhm/usrConfig.c psi/sinqhm/usrConfig.c_diffs psi/sinqhm/usrConfig2604.c psi/sinqhm/vmio10_def.h psi/sinqhm/vmio_utility.c psi/tecs/coc_client.c psi/tecs/coc_client.h psi/tecs/coc_logfile.c psi/tecs/coc_logfile.h psi/tecs/coc_server.c psi/tecs/coc_server.h psi/tecs/coc_util.c psi/tecs/coc_util.h psi/tecs/fortify1.c psi/tecs/instr_hosts.c psi/tecs/instr_hosts.h psi/tecs/keep_running.c psi/tecs/make_gen psi/tecs/make_opt psi/tecs/make_opt_alpha psi/tecs/make_opt_llc psi/tecs/makefile psi/tecs/makefile_alpha psi/tecs/makefile_linux psi/tecs/myc_buf.c psi/tecs/myc_buf.h psi/tecs/myc_err.c psi/tecs/myc_err.h psi/tecs/myc_fortran.h psi/tecs/myc_mem.h psi/tecs/myc_str.c psi/tecs/myc_str.h psi/tecs/myc_time.c psi/tecs/myc_time.h psi/tecs/myc_tmp.c psi/tecs/myc_tmp.h psi/tecs/rstart.c psi/tecs/six.c psi/tecs/str.f psi/tecs/sys_cmdpar.f psi/tecs/sys_date.f psi/tecs/sys_env.c psi/tecs/sys_get_key.f psi/tecs/sys_getenv.f psi/tecs/sys_lun.f psi/tecs/sys_open.f psi/tecs/sys_open_alpha.f psi/tecs/sys_rdline.c psi/tecs/sys_select.c psi/tecs/sys_select.h psi/tecs/sys_unix.c psi/tecs/sys_wait.f psi/tecs/tecs.bld psi/tecs/tecs.c psi/tecs/tecs.tcl psi/tecs/tecs_c.c psi/tecs/tecs_c.h psi/tecs/tecs_cli.c psi/tecs/tecs_cli.h psi/tecs/tecs_client.f psi/tecs/tecs_data.c psi/tecs/tecs_data.h psi/tecs/tecs_dlog.inc psi/tecs/tecs_for.f psi/tecs/tecs_lsc.c psi/tecs/tecs_lsc.h psi/tecs/tecs_plot.f psi/tecs/tecs_serial.c psi/tecs/tecs_serial.h psi/tecs/term.c psi/tecs/term.h psi/utils/Makefile psi/utils/SerPortServer.c psi/utils/asynsrv_test.c psi/utils/ecb-load.c psi/utils/el734.c psi/utils/el734_test.c psi/utils/el737.c psi/utils/make.ecb psi/utils/check/amorcheck psi/utils/check/dmccheck psi/utils/check/focuscheck psi/utils/check/focusstatus.tcl psi/utils/check/hrptcheck psi/utils/check/sanscheck psi/utils/check/sicssyntax.tex psi/utils/check/sicssyntaxlib.tcl psi/utils/check/test.tcl psi/utils/check/topsicheck psi/utils/check/tricscheck psi/utils/check/tst
388 lines
9.2 KiB
C
388 lines
9.2 KiB
C
/*-----------------------------------------------------------------------------
|
|
|
|
SINQ suffers from a severe lack of hardware. In order to do something
|
|
inspite of this, there is the Simulated motor for testing software and
|
|
perhaps later on as a simulation engine for testing batch-files.
|
|
|
|
Mark Koennecke, November 1996
|
|
|
|
Prepared for simulation mode by providing for zero failure operation
|
|
Mark Koennecke, October 2001
|
|
|
|
Allowed for changing hardware limits: Mark Koennecke, April 2003
|
|
|
|
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 <string.h>
|
|
#include <time.h>
|
|
#include "fortify.h"
|
|
#include "conman.h"
|
|
#include "modriv.h"
|
|
#include "servlog.h"
|
|
#include "splitter.h"
|
|
/*-------------------------------------------------------------------------*/
|
|
static float SimRandom(void)
|
|
{
|
|
float fVal;
|
|
|
|
fVal = ( (float) rand() / (float)RAND_MAX) * 100.0;
|
|
return fVal;
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
static int RunComplete(SIMDriv *self)
|
|
{
|
|
time_t tD;
|
|
if(time(&tD) > self->iTime)
|
|
{
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
/*----------------------------------------------------------------------------*/
|
|
static int GetSimPos(void *self, float *fPos)
|
|
{
|
|
SIMDriv *pDriv;
|
|
|
|
assert(self);
|
|
pDriv = (SIMDriv *)self;
|
|
|
|
/*
|
|
no error checking case
|
|
*/
|
|
if(pDriv->fFailure < .0)
|
|
{
|
|
*fPos = pDriv->fPos;
|
|
return OKOK;
|
|
}
|
|
|
|
if(SimRandom() < pDriv->fFailure)
|
|
{
|
|
*fPos = SimRandom();
|
|
return HWFault;
|
|
}
|
|
|
|
if(RunComplete(pDriv))
|
|
{
|
|
*fPos = pDriv->fPos;
|
|
}
|
|
else /* simulate a mispositioned motor */
|
|
{
|
|
*fPos = pDriv->fPos - 1.;
|
|
return OKOK;
|
|
}
|
|
return OKOK;
|
|
}
|
|
/*----------------------------------------------------------------------------*/
|
|
static int SimRun(void *self, float fVal)
|
|
{
|
|
SIMDriv *pDriv;
|
|
float fDiff;
|
|
time_t tD;
|
|
|
|
assert(self);
|
|
pDriv = (SIMDriv *)self;
|
|
|
|
/*
|
|
no failure, no wait situation
|
|
*/
|
|
if(pDriv->fFailure < .0)
|
|
{
|
|
pDriv->fPos = fVal;
|
|
return OKOK;
|
|
}
|
|
|
|
|
|
/* calculate time for completion */
|
|
fDiff = fVal - pDriv->fPos;
|
|
if(fDiff < .0) fDiff = -fDiff;
|
|
pDriv->iTime = time(&tD) + (long)(fDiff/pDriv->fSpeed);
|
|
|
|
/* in a fifth the failures, simply die, else simply do not find pos */
|
|
if(SimRandom() < (pDriv->fFailure/5))
|
|
{
|
|
return HWFault;
|
|
}
|
|
else if(SimRandom() < pDriv->fFailure)
|
|
{
|
|
pDriv->fPos = fVal - 1.;
|
|
return OKOK;
|
|
}
|
|
else
|
|
{
|
|
pDriv->fPos = fVal;
|
|
return OKOK;
|
|
}
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
static void SimError(void *self, int *iCode, char *error, int iErrLen)
|
|
{
|
|
assert(self);
|
|
|
|
if(RunComplete((SIMDriv *)self))
|
|
{
|
|
*iCode = 56;
|
|
strncpy(error,"ERROR: HW: HahahahahahahHahahHahaha-Mmmpfff",iErrLen);
|
|
}
|
|
else
|
|
{
|
|
*iCode = 12;
|
|
strncpy(error,"Motor still creeping along",iErrLen-1);
|
|
}
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
static int SimFix(void *self, int iError, float fNew)
|
|
{
|
|
SIMDriv *pDriv;
|
|
float fRand;
|
|
|
|
/* return the three values MOTREDO, MOTFAIL, MOTOK with a third
|
|
randomness
|
|
*/
|
|
assert(self);
|
|
fRand = SimRandom();
|
|
pDriv = (SIMDriv *)self;
|
|
|
|
if(iError == 12)
|
|
{
|
|
return MOTREDO;
|
|
}
|
|
|
|
SICSLogWrite("Simulated Motor dying randomly",eHWError);
|
|
if(fRand < 0.3333)
|
|
{
|
|
return MOTOK;
|
|
}
|
|
else if(fRand < 0.66666)
|
|
{
|
|
return MOTREDO;
|
|
}
|
|
else
|
|
{
|
|
pDriv->iTime = 0;
|
|
return MOTFAIL;
|
|
}
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
static int SimHalt(void *self)
|
|
{
|
|
SIMDriv *pDriv;
|
|
assert(self);
|
|
|
|
pDriv = (SIMDriv *)self;
|
|
pDriv->iTime = 0;
|
|
return OKOK;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
static int SimStat(void *self)
|
|
{
|
|
SIMDriv *pDriv;
|
|
|
|
assert(self);
|
|
pDriv = (SIMDriv *)self;
|
|
|
|
/*
|
|
no wait, no fail situation
|
|
*/
|
|
if(pDriv->fFailure < .0)
|
|
{
|
|
return HWIdle;
|
|
}
|
|
|
|
if(RunComplete(pDriv))
|
|
{
|
|
return HWIdle;
|
|
}
|
|
else
|
|
{
|
|
if(SimRandom() < pDriv->fFailure/2)
|
|
{
|
|
return HWPosFault;
|
|
}
|
|
else if(SimRandom() < pDriv->fFailure)
|
|
{
|
|
return HWFault;
|
|
}
|
|
return HWBusy;
|
|
}
|
|
}
|
|
/*-----------------------------------------------------------------------*/
|
|
static int SimSetPar(void *self, SConnection *pCon, char *name, float newValue)
|
|
{
|
|
SIMDriv *pDriv = (SIMDriv *) self;
|
|
|
|
assert(self);
|
|
assert(pCon);
|
|
|
|
if(strcmp(name,"hardupperlim") == 0)
|
|
{
|
|
pDriv->fUpper = newValue;
|
|
return 1;
|
|
}
|
|
if(strcmp(name,"hardlowerlim") == 0)
|
|
{
|
|
pDriv->fLower = newValue;
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
void KillSIM(void *pData)
|
|
{
|
|
return;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
MotorDriver *CreateSIM(SConnection *pCon, int argc, char *argv[])
|
|
{
|
|
TokenList *pList = NULL;
|
|
TokenList *pCurrent;
|
|
SIMDriv *pDriv = NULL;
|
|
|
|
assert(pCon);
|
|
|
|
/* check number of arguments */
|
|
if(argc < 3)
|
|
{
|
|
SCWrite(pCon,"Insufficient numbers of arguments for SimMotor",eError);
|
|
return NULL;
|
|
}
|
|
|
|
/* split arguments */
|
|
pList = SplitArguments(argc, argv);
|
|
if(!pList)
|
|
{
|
|
SCWrite(pCon,"Error parsing arguments in SimMotor",eError);
|
|
return NULL;
|
|
}
|
|
|
|
/* allocate memory */
|
|
pDriv = (SIMDriv *)malloc(sizeof(SIMDriv));
|
|
if(!pDriv)
|
|
{
|
|
SCWrite(pCon,"Error allocating memory in SimMotor",eError);
|
|
DeleteTokenList(pList);
|
|
return NULL;
|
|
}
|
|
memset(pDriv,0,sizeof(SIMDriv));
|
|
|
|
/* check and enter args, first lowerLimit */
|
|
pCurrent = pList;
|
|
if(pCurrent->Type == eInt)
|
|
{
|
|
pDriv->fLower = (float)pCurrent->iVal;
|
|
}
|
|
else if(pCurrent->Type == eFloat)
|
|
{
|
|
pDriv->fLower = pCurrent->fVal;
|
|
}
|
|
else
|
|
{
|
|
SCWrite(pCon,"Non float argument to SimMotor",eError);
|
|
free(pDriv);
|
|
DeleteTokenList(pList);
|
|
return NULL;
|
|
}
|
|
|
|
/* upper limit */
|
|
pCurrent = pCurrent->pNext;
|
|
if(pCurrent->Type == eInt)
|
|
{
|
|
pDriv->fUpper = (float)pCurrent->iVal;
|
|
}
|
|
else if(pCurrent->Type == eFloat)
|
|
{
|
|
pDriv->fUpper = pCurrent->fVal;
|
|
}
|
|
else
|
|
{
|
|
SCWrite(pCon,"Non float argument to SimMotor",eError);
|
|
free(pDriv);
|
|
DeleteTokenList(pList);
|
|
return NULL;
|
|
}
|
|
|
|
/* failure rate */
|
|
pCurrent = pCurrent->pNext;
|
|
if(pCurrent->Type == eInt)
|
|
{
|
|
pDriv->fFailure = (float)pCurrent->iVal;
|
|
}
|
|
else if(pCurrent->Type == eFloat)
|
|
{
|
|
pDriv->fFailure = pCurrent->fVal;
|
|
}
|
|
else
|
|
{
|
|
SCWrite(pCon,"Non float argument to SimMotor",eError);
|
|
free(pDriv);
|
|
DeleteTokenList(pList);
|
|
return NULL;
|
|
}
|
|
|
|
|
|
/* calculate current position, initialise func pters */
|
|
pDriv->fPos = (pDriv->fUpper - pDriv->fLower)/2.;
|
|
pDriv->name = strdup("Simulant");
|
|
pDriv->GetPosition = GetSimPos;
|
|
pDriv->RunTo = SimRun;
|
|
pDriv->GetStatus = SimStat;
|
|
pDriv->GetError = SimError;
|
|
pDriv->TryAndFixIt = SimFix;
|
|
/* pDriv->SetDriverPar = SimSetPar; */
|
|
pDriv->Halt = SimHalt;
|
|
pDriv->fSpeed = .01;
|
|
pDriv->iTime = 0;
|
|
pDriv->KillPrivate = KillSIM;
|
|
|
|
/* check for optional speed paramter */
|
|
pCurrent = pCurrent->pNext;
|
|
if(pCurrent)
|
|
{
|
|
if(pCurrent->Type == eFloat)
|
|
{
|
|
pDriv->fSpeed = pCurrent->fVal;
|
|
}
|
|
}
|
|
DeleteTokenList(pList);
|
|
return (MotorDriver *)pDriv;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|