Added to repository.

r986 | ffr | 2006-05-09 09:17:15 +1000 (Tue, 09 May 2006) | 2 lines
This commit is contained in:
Ferdi Franceschini
2006-05-09 09:17:15 +10:00
committed by Douglas Clowes
parent a72513165b
commit 81359a740f
26 changed files with 6557 additions and 0 deletions

103
site_ansto/Makefile Normal file
View File

@@ -0,0 +1,103 @@
# vim: ft=make ts=4 sw=4 noet cindent
#---------------------------------------------------------------------------
# Makefile for SICS
# machine-dependent part for Redhat Linux with AFS at PSI
#
# Mark Koennecke 1996-2001
# Markus Zolliker, March 2003
#==========================================================================
include ../linux_def
# TODO Should use PSI ../make_gen instead of make_gen_variables
include make_gen_variables
# PSI rules and variables
EXTRA=nintf.o
PSI_CLEAN_MATRIX = rm -f ../*.o; $(MAKE) -C ../matrix $(MFLAGS) clean
PSI_CFLAGS = -I./ -I$(HDFROOT)/include -DHDF5 \
-fwritable-strings -DCYGNUS -DNONINTF -g $(DFORTIFY)
PSI_SLIBS = matrix/libmatrix.a
PSI_LIBS = -L$(HDFROOT)/lib $(NILIB)\
-ltcl8.4 $(HDFROOT)/lib/libhdf5.a \
-ldl -lz -lm -lc
../%.o : ../%.c
cd ..; $(CC) -c $(PSI_CFLAGS) $*.c -o $*.o
../matrix/libmatrix.a:
make -C ../matrix $(MFLAGS) libmatrix.a
# ANSTO rules and variables
CC = gcc
CFLAGS = -g -Ihardsup -I.. -Wno-unused -Wno-comment -Wno-switch -Werror
HDFROOT=/usr/local
SRC = ./../..
SITENAME = _ansto
SITEDIR = site_ansto
SITELIB = libansto.a
SITEHARDSUP = hardsup/libhlib.a
HARDSUPDIR = $(SITEDIR)/hardsup
SUBLIBS = libansto.a hardsup/libhlib.a
VPATH = $(SRC)
TANGOROOT = /usr/local/lib/
OMNIORBROOT = /usr/local/lib
COREDIR = $(SRC)
.SUFFIXES:
.SUFFIXES: .c .o .f
TANGOLIBS = \
/usr/local/lib/libclient.a \
/usr/local/lib/liblog4tango.a \
/usr/local/lib/libtango.a \
/usr/local/lib/libomniDynamic4.a \
/usr/local/lib/libomniORB4.a \
/usr/local/lib/libomnithread.a
#OBJ= site_ansto.o batch.o buffer.o ruli.o protocol.o sinfox.o \
# motor_asim.o motor_dmc2280.o motor_pdx.o \
# itc4.o itc4driv.o \
# hm_mrpd.o scan_mrpd.o
OBJ= site_ansto.o \
motor_asim.o motor_dmc2280.o\
lh45.o lh45driv.o \
lakeshore340.o lakeshore340driv.o \
../psi/tcpdocho.o ../psi/tcpdornier.o
all: ../matrix/libmatrix.a $(COREOBJ:%=../%) libansto.a libhardsup
$(CC) -g -o SICServer $(COREOBJ:%=../%) $(SUBLIBS) $(PSI_SLIBS:%=../%) $(PSI_LIBS)
libansto.a: $(OBJ)
rm -f libansto.a
ar cr libansto.a $(OBJ)
ranlib libansto.a
libhardsup:
$(MAKE) -C hardsup/
anstohm.o : anstohm.cpp
$(CXX) -c anstohm.cpp $(CFLAGS) $(CXXFLAGS) -Wno-all
hm_mrpd.o : hm_mrpd.cpp
$(CXX) -c hm_mrpd.cpp $(CFLAGS) $(CXXFLAGS) -Wno-all
hm_asim.o : hm_asim.cpp
$(CXX) -c hm_asim.cpp $(CFLAGS) $(CXXFLAGS) -Wno-all
clean:
$(PSI_CLEAN_MATRIX)
$(MAKE) -C hardsup clean
rm -f SICServer
rm -f *.a
rm -f *.o
MZOBJ=fsm.o logger.o sugar.o pardef.o ease.o strobj.o oxinst.o \
ipsdriv.o ilmdriv.o itcdriv.o ighdriv.o euro2kdriv.o modbus.o
cflags:
@echo ${CFLAGS}
deploy: all
cd instrument; ./make_sics_tar.tcl

447
site_ansto/anstohm.cpp Normal file
View File

@@ -0,0 +1,447 @@
/*----------------------------------------------------------------------------
A N S T O H M
A histogramming memory driver for the ANSTO histogrammer. This version
assumes the histogrammer is a TANGO device server and uses the TANGO
api to communicate with the histogrammer. It has to be compiled with
the C++ compiler and the SICServer has to be linked with C++.
Andy Gotz, February 2004
Copyright:
ANSTO
Lucas Heights
New South Wales
AUSTRALIA
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 <assert.h>
#include <math.h>
extern "C" {
#include "fortify.h"
#include "sics.h"
#include "countdriv.h"
#include "counter.h"
#include "stringdict.h"
#include "HistMem.h"
#include "HistDriv.i"
#include "anstohm.h"
}
#include <tango.h>
/*
#define TESTVAL 128
define TESTVAL to set the simulated histogram to a fixed value for
testing
*/
static int iSet = 0;
static HistInt iSetVal = 0;
static HistMode eHistMode;
/*
* histogrammer proxy and data globals
*
* NOTE: defining this as globals means ONLY one histogrammer can be
* interfaces from SICS. If we need more we need to manage multiple
* histogram devices e.g. by adding them to the pHistDriver structure
*/
static char *hm_device = "localhost:30001/hifar/mrpd/hm#dbase=no";
static Tango::DeviceProxy *hm_proxy=NULL;
static vector<long> hm_data;
/*--------------------------------------------------------------------------*/
static int AnstoHMConfig(pHistDriver self, SConnection *pCon,
pStringDict pOption, SicsInterp *pSics)
{
int i, iLength = 1, status;
char pData[132];
if(eHistMode == eHTOF)
{
for(i = 0; i < self->data->rank; i++)
{
iLength *= self->data->iDim[i];
}
iLength *= self->data->nTimeChan;
}
/*
* set count mode
*/
if (hm_proxy != NULL)
{
try
{
string count_mode;
if (self->eCount == ePreset)
{
count_mode = "monitor";
}
else
{
count_mode = "time";
}
Tango::DeviceAttribute attr_write((const char*)"count_mode",count_mode);
hm_proxy->write_attribute(attr_write);
}
catch(Tango::DevFailed &exception)
{
SCWrite(pCon,"ERROR: Histogram Count Mode failed",eError);
SCWrite(pCon,"Tango error :",eError);
SCWrite(pCon,exception.errors[0].desc,eError);
return 0;
}
}
/*
* send preset to histogrammer
*/
if (hm_proxy != NULL)
{
try
{
/*
* QUESTION: what are the time units of fCountPreset ? Might have to scale it
* should iExponent be taken into account here ?
*/
long preset = (long)self->fCountPreset;
Tango::DeviceAttribute attr_write((const char*)"preset",preset);
hm_proxy->write_attribute(attr_write);
}
catch(Tango::DevFailed &exception)
{
SCWrite(pCon,"ERROR: Histogram Preset failed",eError);
SCWrite(pCon,"Tango error :",eError);
SCWrite(pCon,exception.errors[0].desc,eError);
return 0;
}
}
return 1;
}
/*-------------------------------------------------------------------------*/
static int AnstoHMStart(pHistDriver self, SConnection *pCon)
{
if (hm_proxy != NULL)
{
try
{
hm_proxy->command_inout("Start");
}
catch (Tango::DevFailed &exception)
{
SCWrite(pCon,"ERROR: TANGO Histogram Start failed",eError);
SCWrite(pCon,exception.errors[0].desc,eError);
return 0;
}
}
return 1;
}
/*-------------------------------------------------------------------------*/
static int AnstoHMPause(pHistDriver self, SConnection *pCon)
{
if (hm_proxy != NULL)
{
try
{
hm_proxy->command_inout("Pause");
}
catch (Tango::DevFailed &exception)
{
SCWrite(pCon,"ERROR: Histogram Pause failed",eError);
SCWrite(pCon,"Tango error :",eError);
SCWrite(pCon,exception.errors[0].desc,eError);
return 0;
}
}
return 1;
}
/*------------------------------------------------------------------------*/
static int AnstoHMContinue(pHistDriver self, SConnection *pCon)
{
if (hm_proxy != NULL)
{
try
{
hm_proxy->command_inout("Continue");
}
catch (Tango::DevFailed &exception)
{
SCWrite(pCon,"ERROR: Histogram Continue failed",eError);
SCWrite(pCon,"Tango error :",eError);
SCWrite(pCon,exception.errors[0].desc,eError);
return 0;
}
}
return 1;
}
/*-------------------------------------------------------------------------*/
static int AnstoHMHalt(pHistDriver self)
{
if (hm_proxy != NULL)
{
try
{
hm_proxy->command_inout("Halt");
}
catch (Tango::DevFailed &exception)
{
/*
SCWrite(pCon,"ERROR: Histogram Halt failed",eError);
SCWrite(pCon,exception.errors[0].desc,eError);
*/
return 0;
}
}
return 1;
}
/*-------------------------------------------------------------------------*/
static int AnstoHMGetCountStatus(pHistDriver self, SConnection *pCon)
{
if (hm_proxy != NULL)
{
try
{
Tango::DevState state;
state = hm_proxy->state();
switch (state)
{
case Tango::OFF :
return HWIdle;
case Tango::RUNNING :
return HWBusy;
case Tango::STANDBY :
return HWPause;
case Tango::FAULT :
return HWFault;
default :
return HWFault;
}
}
catch(Tango::DevFailed &exception)
{
SCWrite(pCon,"ERROR: Histogram state() failed",eError);
SCWrite(pCon,"Tango error :",eError);
SCWrite(pCon,exception.errors[0].desc,eError);
return 0;
}
}
}
/*-------------------------------------------------------------------------*/
static int AnstoHMGetError(pHistDriver self, int *iCode, char *pError, int iLen)
{
return 0;
}
/*-------------------------------------------------------------------------*/
static int AnstoHMTryAndFixIt(pHistDriver self, int iCode)
{
if (hm_proxy != NULL)
{
try
{
hm_proxy->command_inout("Reset");
}
catch (Tango::DevFailed &exception)
{
/*
SCWrite(pCon,"ERROR: Histogram Reset failed",eError);
SCWrite(pCon,"Tango error :",eError);
SCWrite(pCon,exception.errors[0].desc,eError);
*/
return 0;
}
}
return 1;
}
/*--------------------------------------------------------------------------*/
static int AnstoHMGetData(pHistDriver self, SConnection *pCon)
{
try
{
Tango::DeviceAttribute attr_read = hm_proxy->read_attribute("data");
// return data in global hm_data variable
attr_read >> hm_data;
}
catch(Tango::DevFailed &exception)
{
SCWrite(pCon,"ERROR: Histogram GetData failed",eError);
SCWrite(pCon,"Tango error :",eError);
SCWrite(pCon,exception.errors[0].desc,eError);
return 0;
}
return 1;
}
/*--------------------------------------------------------------------------*/
static int AnstoHMGetHistogram(pHistDriver self, SConnection *pCon,
int i, int iStart, int iEnd, HistInt *lData)
{
int ii;
if(i < 0)
{
SCWrite(pCon,"ERROR: histogram out of range",eError);
return 0;
}
#ifdef TESTVAL
for(ii = iStart; ii < iEnd; ii++)
{
lData[ii] = TESTVAL;
}
#else
AnstoHMGetData(self, pCon);
for(ii = iStart; ii < iEnd; ii++)
{
if (ii < hm_data.size()) lData[ii-iStart] = hm_data[ii];
}
#endif
return 1;
}
/*------------------------------------------------------------------------*/
static int AnstoHMSetHistogram(pHistDriver self, SConnection *pCon,
int i, int iStart, int iEnd, HistInt *lData)
{
iSet = 1;
iSetVal = lData[0];
return 1;
}
/*-------------------------------------------------------------------------*/
static int AnstoHMPreset(pHistDriver self, SConnection *pCon, HistInt iVal)
{
iSet = 1;
iSetVal = iVal;
return 1;
}
/*------------------------------------------------------------------------*/
static int AnstoHMFreePrivate(pHistDriver self)
{
return 1;
}
/*------------------------------------------------------------------------*/
static long AnstoHMGetMonitor(pHistDriver self, int i, SConnection *pCon)
{
long hm_monitor;
try
{
Tango::DeviceAttribute attr_read = hm_proxy->read_attribute("monitor");
// return data in global hm_data variable
attr_read >> hm_monitor;
}
catch(Tango::DevFailed &exception)
{
SCWrite(pCon,"ERROR: Histogram GetData failed",eError);
SCWrite(pCon,"Tango error :",eError);
SCWrite(pCon,exception.errors[0].desc,eError);
return 0;
}
return hm_monitor;
}
/*------------------------------------------------------------------------*/
static float AnstoHMGetTime(pHistDriver self, SConnection *pCon)
{
double hm_time;
try
{
Tango::DeviceAttribute attr_read = hm_proxy->read_attribute("time");
// return data in global hm_data variable
attr_read >> hm_time;
}
catch(Tango::DevFailed &exception)
{
SCWrite(pCon,"ERROR: Histogram GetData failed",eError);
SCWrite(pCon,"Tango error :",eError);
SCWrite(pCon,exception.errors[0].desc,eError);
return 0;
}
return (float)hm_time;
}
/*-------------------------------------------------------------------------*/
pHistDriver CreateAnstoHM(pStringDict pOpt)
{
pHistDriver pNew = NULL;
/* create the general driver */
pNew = CreateHistDriver(pOpt);
if(!pNew)
{
return NULL;
}
/* not using private data currently */
pNew->pPriv = NULL;
/* configure all those functions */
pNew->Configure = AnstoHMConfig;
pNew->Start = AnstoHMStart;
pNew->Halt = AnstoHMHalt;
pNew->GetCountStatus = AnstoHMGetCountStatus;
pNew->GetError = AnstoHMGetError;
pNew->TryAndFixIt = AnstoHMTryAndFixIt;
pNew->GetData = AnstoHMGetData;
pNew->GetHistogram = AnstoHMGetHistogram;
pNew->SetHistogram = AnstoHMSetHistogram;
pNew->GetMonitor = AnstoHMGetMonitor;
pNew->GetTime = AnstoHMGetTime;
pNew->Preset = AnstoHMPreset;
pNew->FreePrivate = AnstoHMFreePrivate;
pNew->Pause = AnstoHMPause;
pNew->Continue = AnstoHMContinue;
pNew->fCountPreset = 1;
StringDictAddPair(pOpt,"device",hm_device);
try
{
hm_proxy = new Tango::DeviceProxy(hm_device);
}
catch(Tango::DevFailed &exception)
{
printf("ERROR: New Tango DeviceProxy failed\n");
/*
SCWrite(pCon,"ERROR: New Tango DeviceProxy failed",eError);
SCWrite(pCon,"Tango error :",eError);
SCWrite(pCon,exception.errors[0].desc,eError);
*/
return 0;
}
hm_data.resize(10);
return pNew;
}

28
site_ansto/anstohm.h Normal file
View File

@@ -0,0 +1,28 @@
#line 15 "histsim.w"
/*--------------------------------------------------------------------------
A N S T O H M
The ANSTO histogramming memory driver include file
Andy Gotz, February 2004
copyright: see implementation file.
---------------------------------------------------------------------------*/
#ifndef SICSANSTOHM
#define SICSANSTOHM
#line 5 "histsim.w"
#ifdef __cplusplus
extern "C" {
#endif
pHistDriver CreateAnstoHM(pStringDict pOpt);
#ifdef __cplusplus
}
#endif
#line 27 "histsim.w"
#endif

1038
site_ansto/hm_asim.cpp Normal file

File diff suppressed because it is too large Load Diff

21
site_ansto/hm_asim.h Normal file
View File

@@ -0,0 +1,21 @@
/*--------------------------------------------------------------------------
H M _ A S I M
The ANSTO simulated histogramming memory driver include file
Paul Hathaway, September 2004
Copyright: see Copyright.txt
---------------------------------------------------------------------------*/
#ifndef HM_ASIM
#define HM_ASIM
#ifdef __cplusplus
extern "C" {
#endif
pHistDriver CreateHmAsim(pStringDict pOpt);
#ifdef __cplusplus
}
#endif
#endif

30
site_ansto/hm_tango.h Normal file
View File

@@ -0,0 +1,30 @@
#line 15 "histsim.w"
/*--------------------------------------------------------------------------
H M _ T A N G O
Header file for the ANSTO histogramming memory driver interfacing
a TANGO server
Based on anstohm.h (Andy Gotz, February 2004)
Modified: Paul Hathaway, July 2004
Copyright: see Copyright.txt
---------------------------------------------------------------------------*/
#ifndef SICS_HM_TANGO
#define SICS_HM_TANGO
#line 5 "histsim.w"
#ifdef __cplusplus
extern "C" {
#endif
pHistDriver CreateHmTango(pStringDict pOpt);
#ifdef __cplusplus
}
#endif
#line 27 "histsim.w"
#endif

281
site_ansto/itc4.c Normal file
View File

@@ -0,0 +1,281 @@
/*---------------------------------------------------------------------------
I T C 4
This is the implementation for a ITC4 object derived from an more general
environment controller.
Mark Koennecke, August 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 <assert.h>
#include <tcl.h>
#include <fortify.h>
#include <sics.h>
#include <splitter.h>
#include <obpar.h>
#include <devexec.h>
#include <nserver.h>
#include <interrupt.h>
#include <emon.h>
#include <evcontroller.h>
#include <evcontroller.i>
#include "itc4.h"
/*---------------------------------------------------------------------------*/
int ITC4SetPar(pEVControl self, char *name, float fNew, SConnection *pCon)
{
int iRet;
/* check authorsisation */
if(!SCMatchRights(pCon,usUser))
{
SCWrite(pCon,"ERROR: you are not authorised to change this parameter",
eError);
return 0;
}
/* just catch those three names which we understand */
if(strcmp(name,"sensor") == 0)
{
iRet = SetSensorITC4(self->pDriv,(int)fNew);
if(!iRet)
{
SCWrite(pCon,"ERROR: value out of range",eError);
return 0;
}
iRet = ConfigITC4(self->pDriv);
if(iRet != 1)
{
SCWrite(pCon,"ERROR: ITC4 configuration failed! ",eError);
SCWrite(pCon,"INFO: Probably comm problem, Retry!",eError);
return 0;
}
SCSendOK(pCon);
return 1;
}
else if(strcmp(name,"control") == 0)
{
iRet = SetControlITC4(self->pDriv,(int)fNew);
if(!iRet)
{
SCWrite(pCon,"ERROR: value out of range",eError);
return 0;
}
iRet = ConfigITC4(self->pDriv);
if(iRet != 1)
{
SCWrite(pCon,"ERROR: ITC4 configuration failed! ",eError);
SCWrite(pCon,"INFO: Probably comm problem, Retry!",eError);
return 0;
}
SCSendOK(pCon);
return 1;
}
else if(strcmp(name,"timeout") == 0)
{
iRet = SetTMOITC4(self->pDriv,(int)fNew);
if(!iRet)
{
SCWrite(pCon,"ERROR: value out of range",eError);
return 0;
}
iRet = ConfigITC4(self->pDriv);
if(iRet != 1)
{
SCWrite(pCon,"ERROR: ITC4 configuration failed! ",eError);
SCWrite(pCon,"INFO: Probably comm problem, Retry!",eError);
return 0;
}
SCSendOK(pCon);
return 1;
}
else if(strcmp(name,"divisor") == 0)
{
iRet = SetDivisorITC4(self->pDriv,fNew);
if(!iRet)
{
SCWrite(pCon,"ERROR: value out of range",eError);
return 0;
}
iRet = ConfigITC4(self->pDriv);
if(iRet != 1)
{
SCWrite(pCon,"ERROR: ITC4 configuration failed! ",eError);
SCWrite(pCon,"INFO: Probably comm problem, Retry!",eError);
return 0;
}
SCSendOK(pCon);
return 1;
}
else if(strcmp(name,"multiplicator") == 0)
{
iRet = SetMultITC4(self->pDriv,fNew);
if(!iRet)
{
SCWrite(pCon,"ERROR: value out of range",eError);
return 0;
}
iRet = ConfigITC4(self->pDriv);
if(iRet != 1)
{
SCWrite(pCon,"ERROR: ITC4 configuration failed! ",eError);
SCWrite(pCon,"INFO: Probably comm problem, Retry!",eError);
return 0;
}
SCSendOK(pCon);
return 1;
}
else
return EVCSetPar(self,name,fNew,pCon);
}
/*--------------------------------------------------------------------------*/
int ITC4GetPar(pEVControl self, char *name, float *fNew)
{
int iRet;
float fDiv;
/* just catch those two names which we understand */
if(strcmp(name,"sensor") == 0)
{
iRet = GetSensorITC4(self->pDriv);
*fNew = (float)iRet;
return 1;
}
else if(strcmp(name,"control") == 0)
{
iRet = GetControlITC4(self->pDriv);
*fNew = (float)iRet;
return 1;
}
else if(strcmp(name,"timeout") == 0)
{
iRet = GetTMOITC4(self->pDriv);
*fNew = (float)iRet;
return 1;
}
else if(strcmp(name,"divisor") == 0)
{
fDiv = GetDivisorITC4(self->pDriv);
*fNew = fDiv;
return 1;
}
else if(strcmp(name,"multiplicator") == 0)
{
fDiv = GetMultITC4(self->pDriv);
*fNew = fDiv;
return 1;
}
else
return EVCGetPar(self,name,fNew);
}
/*---------------------------------------------------------------------------*/
int ITCList(pEVControl self, SConnection *pCon)
{
char pBueffel[132];
int iRet;
iRet = EVCList(self,pCon);
sprintf(pBueffel,"%s.sensor = %d\n",self->pName,
GetSensorITC4(self->pDriv));
SCWrite(pCon,pBueffel,eValue);
sprintf(pBueffel,"%s.control = %d\n",self->pName,
GetControlITC4(self->pDriv));
SCWrite(pCon,pBueffel,eValue);
sprintf(pBueffel,"%s.timeout = %d\n",self->pName,
GetTMOITC4(self->pDriv));
SCWrite(pCon,pBueffel,eValue);
sprintf(pBueffel,"%s.divisor = %f\n",self->pName,
GetDivisorITC4(self->pDriv));
SCWrite(pCon,pBueffel,eValue);
sprintf(pBueffel,"%s.multiplicator = %f\n",self->pName,
GetMultITC4(self->pDriv));
SCWrite(pCon,pBueffel,eValue);
return iRet;
}
/*-------------------------------------------------------------------------*/
int ITC4Wrapper(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[])
{
pEVControl self = NULL;
char pBueffel[256];
int iRet;
double fNum;
float fVal;
self = (pEVControl)pData;
assert(self);
assert(pCon);
assert(pSics);
if(argc < 2)
{
return EVControlWrapper(pCon,pSics,pData,argc,argv);
}
strtolower(argv[1]);
if((strcmp(argv[1],"sensor") == 0) || (strcmp(argv[1],"control") == 0) ||
(strcmp(argv[1],"timeout") == 0) || (strcmp(argv[1],"divisor") == 0) ||
(strcmp(argv[1],"multiplicator") == 0) )
{
if(argc > 2) /* set case */
{
iRet = Tcl_GetDouble(pSics->pTcl,argv[2],&fNum);
if(iRet != TCL_OK)
{
sprintf(pBueffel,"ERROR: expected number, got %s",argv[2]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
return ITC4SetPar(self,argv[1],(float)fNum,pCon);
}
else /* get case */
{
iRet = ITC4GetPar(self,argv[1],&fVal);
sprintf(pBueffel,"%s.%s = %f\n",self->pName,
argv[1],fVal);
SCWrite(pCon,pBueffel,eValue);
return 1;
}
}
else if(strcmp(argv[1],"list") == 0)
{
return ITCList(self,pCon);
}
else
{
return EVControlWrapper(pCon,pSics,pData,argc,argv);
}
/* not reached */
return 0;
}

43
site_ansto/itc4.h Normal file
View File

@@ -0,0 +1,43 @@
/*-------------------------------------------------------------------------
ITC 4
Support for Oxford Instruments ITC4 Temperature controllers for SICS.
The meaning and working of the functions defined is as desribed for a
general environment controller.
Mark Koennecke, Juli 1997
copyright: see implementation file.
-----------------------------------------------------------------------------*/
#ifndef SICSITC4
#define SICSITC4
/*------------------------- The Driver ------------------------------------*/
pEVDriver CreateITC4Driver(int argc, char *argv[]);
int ConfigITC4(pEVDriver self);
int SetSensorITC4(pEVDriver self, int iSensor);
int SetControlITC4(pEVDriver self, int iSensor);
int GetSensorITC4(pEVDriver self);
int GetControlITC4(pEVDriver self);
int SetDivisorITC4(pEVDriver self, float iSensor);
float GetDivisorITC4(pEVDriver self);
int SetMultITC4(pEVDriver self, float iSensor);
float GetMultITC4(pEVDriver self);
int SetTMOITC4(pEVDriver self, int iSensor);
int GetTMOITC4(pEVDriver self);
/*------------------------- The ITC4 object ------------------------------*/
int ITC4Wrapper(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[]);
int ITC4SetPar(pEVControl self, char *name, float fNew,
SConnection *pCon);
int ITC4GetPar(pEVControl self, char *name, float *fVal);
int ITCList(pEVControl self, SConnection *pCon);
#endif

74
site_ansto/itc4.w Normal file
View File

@@ -0,0 +1,74 @@
\subsubsection{Oxford Instruments ITC4 Temperature Controllers}
SINQ makes heavy use of Oxford Instruments ITC4 temperature controllers. In
order to support them the following software components had to be defined in
addition to the basic environmet controller interfaces:
\begin{itemize}
\item ITC4driver, naturally.
\item A ITC4-controller object as derivation of environment controller. ITC4
's allow you to select a sensor which you read as your standard sensor and a
sensor which is used for automatic control. The ITC4 controller object adds
just that additional functionality to the statndard environment controller.
\end{itemize}
The additional data, the selection of sensors, will be kept in the driver.
This serves also an example for implementing inheritance without C++.
The driver interface:
@d itcd @{
pEVDriver CreateITC4Driver(int argc, char *argv[]);
int ConfigITC4(pEVDriver self);
int SetSensorITC4(pEVDriver self, int iSensor);
int SetControlITC4(pEVDriver self, int iSensor);
int GetSensorITC4(pEVDriver self);
int GetControlITC4(pEVDriver self);
int SetDivisorITC4(pEVDriver self, float iSensor);
float GetDivisorITC4(pEVDriver self);
int SetMultITC4(pEVDriver self, float iSensor);
float GetMultITC4(pEVDriver self);
int SetTMOITC4(pEVDriver self, int iSensor);
int GetTMOITC4(pEVDriver self);
@}
The ConfigITC4 is special. It has to be called to commit changes to the
driver read and control parameters.
The ITC4 object interface:
@d itco @{
int ITC4Wrapper(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[]);
int ITC4SetPar(pEVControl self, char *name, float fNew,
SConnection *pCon);
int ITC4GetPar(pEVControl self, char *name, float *fVal);
int ITCList(pEVControl self, SConnection *pCon);
@}
The functions defined are: new parameter handling functions, with just
support for the two extra parameters added and a new Wrapper function for
SICS. The meaning of all these functions, their parameters and return values
are identical to those defined for an environment controller. Additionally,
the standard environment controller functions will work as described. The
functions described above are just needed to implement the extra parameters.
@o itc4.h @{
/*-------------------------------------------------------------------------
ITC 4
Support for Oxford Instruments ITC4 Temperature controllers for SICS.
The meaning and working of the functions defined is as desribed for a
general environment controller.
Mark Koennecke, Juli 1997
copyright: see implementation file.
-----------------------------------------------------------------------------*/
#ifndef SICSITC4
#define SICSITC4
/*------------------------- The Driver ------------------------------------*/
@<itcd@>
/*------------------------- The ITC4 object ------------------------------*/
@<itco@>
#endif
@}

478
site_ansto/itc4driv.c Normal file
View File

@@ -0,0 +1,478 @@
/*--------------------------------------------------------------------------
I T C 4 D R I V
This file contains the implementation of a driver for the Oxford
Instruments ITC4 Temperature controller.
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>
typedef struct __EVDriver *pEVDriver;
#include <evdriver.i>
/* Do we need these ?
#include <sics.h>
#include <modriv.h>
*/
#include <rs232controller.h>
#include "hardsup/itc4util.h"
#include "hardsup/el734_def.h"
#include "hardsup/el734fix.h"
#define SHITTYVALUE -777
/*------------------------- The Driver ------------------------------------*/
pEVDriver CreateITC4Driver(int argc, char *argv[]);
int ConfigITC4(pEVDriver self);
/*-----------------------------------------------------------------------*/
typedef struct {
pITC4 pData;
char *pHost;
int iPort;
int iChannel;
int iControl; /* itc control */
float fDiv;
float fMult;
int iRead; /* itc sensor */
int iTmo;
int iLastError;
} ITC4Driv, *pITC4Driv;
/*----------------------------------------------------------------------------*/
static int GetITC4Pos(pEVDriver self, float *fPos)
{
pITC4Driv pMe = NULL;
int iRet;
assert(self);
pMe = (pITC4Driv)self->pPrivate;
assert(pMe);
iRet = ITC4_Read(&pMe->pData,fPos);
if(iRet != 1 )
{
pMe->iLastError = iRet;
return 0;
}
if( (*fPos < 0) || (*fPos > 10000) )
{
*fPos = -999.;
pMe->iLastError = SHITTYVALUE;
return 0;
}
return 1;
}
/*----------------------------------------------------------------------------*/
static int ITC4Run(pEVDriver self, float fVal)
{
pITC4Driv pMe = NULL;
int iRet;
assert(self);
pMe = (pITC4Driv )self->pPrivate;
assert(pMe);
iRet = ITC4_Set(&pMe->pData,fVal);
if(iRet != 1)
{
pMe->iLastError = iRet;
return 0;
}
return 1;
}
/*--------------------------------------------------------------------------*/
static int ITC4Error(pEVDriver self, int *iCode, char *error, int iErrLen)
{
pITC4Driv pMe = NULL;
assert(self);
pMe = (pITC4Driv)self->pPrivate;
assert(pMe);
*iCode = pMe->iLastError;
if(pMe->iLastError == SHITTYVALUE)
{
strncpy(error,"Invalid temperature returned form ITC4, check sensor",iErrLen);
}
else
{
ITC4_ErrorTxt(&pMe->pData,pMe->iLastError,error,iErrLen);
}
return 1;
}
/*--------------------------------------------------------------------------*/
static int ITC4Send(pEVDriver self, char *pCommand, char *pReply, int iLen)
{
pITC4Driv pMe = NULL;
int iRet;
assert(self);
pMe = (pITC4Driv )self->pPrivate;
assert(pMe);
iRet = ITC4_Send(&pMe->pData,pCommand, pReply,iLen);
if(iRet != 1)
{
pMe->iLastError = iRet;
return 0;
}
return 1;
}
/*--------------------------------------------------------------------------*/
static int ITC4Init(pEVDriver self)
{
pITC4Driv pMe = NULL;
int iRet;
assert(self);
pMe = (pITC4Driv )self->pPrivate;
assert(pMe);
pMe->pData = NULL;
iRet = ITC4_Open(&pMe->pData, pMe->pHost, pMe->iRead, pMe->iControl,0);
if(iRet != 1)
{
if(iRet == ITC4__NOITC)
{
return -1;
}
else
{
pMe->iLastError = iRet;
return 0;
}
}
return 1;
}
/*--------------------------------------------------------------------------*/
static int ITC4Close(pEVDriver self)
{
pITC4Driv pMe = NULL;
int iRet;
assert(self);
pMe = (pITC4Driv )self->pPrivate;
assert(pMe);
ITC4_Close(&pMe->pData);
return 1;
}
/*---------------------------------------------------------------------------*/
static int ITC4Fix(pEVDriver self, int iError)
{
pITC4Driv pMe = NULL;
int iRet;
assert(self);
pMe = (pITC4Driv )self->pPrivate;
assert(pMe);
switch(iError)
{
/* network errors */
case EL734__BAD_FLUSH:
case EL734__BAD_RECV:
case EL734__BAD_RECV_NET:
case EL734__BAD_RECV_UNKN:
case EL734__BAD_RECVLEN:
case EL734__BAD_RECV1:
case EL734__BAD_RECV1_PIPE:
case EL734__BAD_RNG:
case EL734__BAD_SEND:
case EL734__BAD_SEND_PIPE:
case EL734__BAD_SEND_NET:
case EL734__BAD_SEND_UNKN:
case EL734__BAD_SENDLEN:
ITC4Close(self);
iRet = ITC4Init(self);
if(iRet)
{
return DEVREDO;
}
else
{
return DEVFAULT;
}
break;
/* handable protocoll errors */
case EL734__BAD_TMO:
return DEVREDO;
break;
case -501: /* Bad_COM */
return DEVREDO;
case -504: /* Badly formatted */
return DEVREDO;
default:
return DEVFAULT;
break;
}
return DEVFAULT;
}
/*--------------------------------------------------------------------------*/
static int ITC4Halt(pEVDriver *self)
{
assert(self);
return 1;
}
/*------------------------------------------------------------------------*/
void KillITC4(void *pData)
{
pITC4Driv pMe = NULL;
pMe = (pITC4Driv)pData;
assert(pMe);
if(pMe->pHost)
{
free(pMe->pHost);
}
free(pMe);
}
/*------------------------------------------------------------------------*/
pEVDriver CreateITC4Driver(int argc, char *argv[])
{
pEVDriver pNew = NULL;
pITC4Driv pSim = NULL;
/* check for arguments */
if(argc < 3)
{
return NULL;
}
pNew = CreateEVDriver(argc,argv);
pSim = (pITC4Driv)malloc(sizeof(ITC4Driv));
memset(pSim,0,sizeof(ITC4Driv));
if(!pNew || !pSim)
{
return NULL;
}
pNew->pPrivate = pSim;
pNew->KillPrivate = KillITC4;
/* initalise pITC4Driver */
pSim->iControl = atoi(argv[2]);
pSim->iRead = atoi(argv[1]);
pSim->iLastError = 0;
pSim->iTmo = 10;
pSim->fDiv = 10.;
pSim->fMult = 10;
pSim->pHost = strdup(argv[0]);
pSim->iPort = 0;
pSim->iChannel = 0;
/* initialise function pointers */
pNew->SetValue = ITC4Run;
pNew->GetValue = GetITC4Pos;
pNew->Send = ITC4Send;
pNew->GetError = ITC4Error;
pNew->TryFixIt = ITC4Fix;
pNew->Init = ITC4Init;
pNew->Close = ITC4Close;
return pNew;
}
/*--------------------------------------------------------------------------*/
int ConfigITC4(pEVDriver self)
{
pITC4Driv pMe = NULL;
int iRet;
assert(self);
pMe = (pITC4Driv )self->pPrivate;
assert(pMe);
iRet = ITC4_Config(&pMe->pData, pMe->iTmo, pMe->iRead,
pMe->iControl,pMe->fDiv,pMe->fMult);
if(iRet < 0)
{
pMe->iLastError = iRet;
return 0;
}
return 1;
}
/*-------------------------------------------------------------------------*/
int SetSensorITC4(pEVDriver self, int iSensor)
{
pITC4Driv pMe = NULL;
int iRet;
assert(self);
pMe = (pITC4Driv )self->pPrivate;
assert(pMe);
if( (iSensor < 1) || (iSensor > 4) )
{
return 0;
}
pMe->iRead = iSensor;
pMe->pData->iRead = iSensor;
return 1;
}
/*-------------------------------------------------------------------------*/
int SetControlITC4(pEVDriver self, int iSensor)
{
pITC4Driv pMe = NULL;
int iRet;
assert(self);
pMe = (pITC4Driv )self->pPrivate;
assert(pMe);
if( (iSensor < 1) || (iSensor > 4) )
{
return 0;
}
pMe->iControl = iSensor;
pMe->pData->iControl = iSensor;
return 1;
}
/*-------------------------------------------------------------------------*/
int SetTMOITC4(pEVDriver self, int iSensor)
{
pITC4Driv pMe = NULL;
int iRet;
assert(self);
pMe = (pITC4Driv )self->pPrivate;
assert(pMe);
if(iSensor < 10)
{
return 0;
}
pMe->iTmo = iSensor;
return 1;
}
/*-------------------------------------------------------------------------*/
int GetControlITC4(pEVDriver self)
{
pITC4Driv pMe = NULL;
int iRet;
assert(self);
pMe = (pITC4Driv )self->pPrivate;
assert(pMe);
return pMe->iControl;
}
/*-------------------------------------------------------------------------*/
int GetSensorITC4(pEVDriver self)
{
pITC4Driv pMe = NULL;
int iRet;
assert(self);
pMe = (pITC4Driv )self->pPrivate;
assert(pMe);
return pMe->iRead;
}
/*-------------------------------------------------------------------------*/
int GetTMOITC4(pEVDriver self)
{
pITC4Driv pMe = NULL;
int iRet;
assert(self);
pMe = (pITC4Driv )self->pPrivate;
assert(pMe);
return pMe->iTmo;
}
/*-------------------------------------------------------------------------*/
float GetDivisorITC4(pEVDriver self)
{
pITC4Driv pMe = NULL;
int iRet;
assert(self);
pMe = (pITC4Driv )self->pPrivate;
assert(pMe);
return pMe->fDiv;
}
/*--------------------------------------------------------------------------*/
int SetDivisorITC4(pEVDriver self, float fDiv)
{
pITC4Driv pMe = NULL;
int iRet;
assert(self);
pMe = (pITC4Driv )self->pPrivate;
assert(pMe);
pMe->fDiv = fDiv;
return 1;
}
/*-------------------------------------------------------------------------*/
float GetMultITC4(pEVDriver self)
{
pITC4Driv pMe = NULL;
int iRet;
assert(self);
pMe = (pITC4Driv )self->pPrivate;
assert(pMe);
return pMe->fMult;
}
/*--------------------------------------------------------------------------*/
int SetMultITC4(pEVDriver self, float fDiv)
{
pITC4Driv pMe = NULL;
int iRet;
assert(self);
pMe = (pITC4Driv )self->pPrivate;
assert(pMe);
pMe->fMult = fDiv;
return 1;
}

284
site_ansto/lakeshore340.c Normal file
View File

@@ -0,0 +1,284 @@
/*---------------------------------------------------------------------------
L A K E S H O R E 3 4 0
This is the implementation for a LAKESHORE340 object derived from a more general
environment controller.
Mark Koennecke, August 1997
Mark Lesha, January 2006 (based on ITC4 code)
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 <assert.h>
#include <tcl.h>
#include <fortify.h>
#include <sics.h>
#include <splitter.h>
#include <obpar.h>
#include <devexec.h>
#include <nserver.h>
#include <interrupt.h>
#include <emon.h>
#include <evcontroller.h>
#include <evcontroller.i>
#include "lakeshore340.h"
/*---------------------------------------------------------------------------*/
int LAKESHORE340SetPar(pEVControl self, char *name, float fNew, SConnection *pCon)
{
int iRet;
/* check authorisation */
if(!SCMatchRights(pCon,usUser))
{
SCWrite(pCon,"ERROR: you are not authorised to change this parameter",
eError);
return 0;
}
/* just catch those three names which we understand */
if(strcmp(name,"sensor") == 0)
{
iRet = SetSensorLAKESHORE340(self->pDriv,(int)fNew);
if(!iRet)
{
SCWrite(pCon,"ERROR: value out of range",eError);
return 0;
}
iRet = ConfigLAKESHORE340(self->pDriv);
if(iRet != 1)
{
SCWrite(pCon,"ERROR: LAKESHORE340 configuration failed! ",eError);
SCWrite(pCon,"INFO: Probably comm problem, Retry!",eError);
return 0;
}
SCSendOK(pCon);
return 1;
}
else if(strcmp(name,"control") == 0)
{
iRet = SetControlLAKESHORE340(self->pDriv,(int)fNew);
if(!iRet)
{
SCWrite(pCon,"ERROR: value out of range",eError);
return 0;
}
iRet = ConfigLAKESHORE340(self->pDriv);
if(iRet != 1)
{
SCWrite(pCon,"ERROR: LAKESHORE340 configuration failed! ",eError);
SCWrite(pCon,"INFO: Probably comm problem, Retry!",eError);
return 0;
}
SCSendOK(pCon);
return 1;
}
else if(strcmp(name,"timeout") == 0)
{
iRet = SetTMOLAKESHORE340(self->pDriv,(int)fNew);
if(!iRet)
{
SCWrite(pCon,"ERROR: value out of range",eError);
return 0;
}
iRet = ConfigLAKESHORE340(self->pDriv);
if(iRet != 1)
{
SCWrite(pCon,"ERROR: LAKESHORE340 configuration failed! ",eError);
SCWrite(pCon,"INFO: Probably comm problem, Retry!",eError);
return 0;
}
SCSendOK(pCon);
return 1;
}
/* Note divisors and multipliers will not be used with the LAKESHORE340
but leave in for back compatibility */
else if(strcmp(name,"divisor") == 0)
{
iRet = SetDivisorLAKESHORE340(self->pDriv,fNew);
if(!iRet)
{
SCWrite(pCon,"ERROR: value out of range",eError);
return 0;
}
iRet = ConfigLAKESHORE340(self->pDriv);
if(iRet != 1)
{
SCWrite(pCon,"ERROR: LAKESHORE340 configuration failed! ",eError);
SCWrite(pCon,"INFO: Probably comm problem, Retry!",eError);
return 0;
}
SCSendOK(pCon);
return 1;
}
else if(strcmp(name,"multiplicator") == 0)
{
iRet = SetMultLAKESHORE340(self->pDriv,fNew);
if(!iRet)
{
SCWrite(pCon,"ERROR: value out of range",eError);
return 0;
}
iRet = ConfigLAKESHORE340(self->pDriv);
if(iRet != 1)
{
SCWrite(pCon,"ERROR: LAKESHORE340 configuration failed! ",eError);
SCWrite(pCon,"INFO: Probably comm problem, Retry!",eError);
return 0;
}
SCSendOK(pCon);
return 1;
}
else
return EVCSetPar(self,name,fNew,pCon);
}
/*--------------------------------------------------------------------------*/
int LAKESHORE340GetPar(pEVControl self, char *name, float *fNew)
{
int iRet;
float fDiv;
/* just catch those two names which we understand */
if(strcmp(name,"sensor") == 0)
{
iRet = GetSensorLAKESHORE340(self->pDriv);
*fNew = (float)iRet;
return 1;
}
else if(strcmp(name,"control") == 0)
{
iRet = GetControlLAKESHORE340(self->pDriv);
*fNew = (float)iRet;
return 1;
}
else if(strcmp(name,"timeout") == 0)
{
iRet = GetTMOLAKESHORE340(self->pDriv);
*fNew = (float)iRet;
return 1;
}
else if(strcmp(name,"divisor") == 0)
{
fDiv = GetDivisorLAKESHORE340(self->pDriv);
*fNew = fDiv;
return 1;
}
else if(strcmp(name,"multiplicator") == 0)
{
fDiv = GetMultLAKESHORE340(self->pDriv);
*fNew = fDiv;
return 1;
}
else
return EVCGetPar(self,name,fNew);
}
/*---------------------------------------------------------------------------*/
int LAKESHORE340List(pEVControl self, SConnection *pCon)
{
char pBueffel[132];
int iRet;
iRet = EVCList(self,pCon);
sprintf(pBueffel,"%s.sensor = %d\n",self->pName,
GetSensorLAKESHORE340(self->pDriv));
SCWrite(pCon,pBueffel,eValue);
sprintf(pBueffel,"%s.control = %d\n",self->pName,
GetControlLAKESHORE340(self->pDriv));
SCWrite(pCon,pBueffel,eValue);
sprintf(pBueffel,"%s.timeout = %d\n",self->pName,
GetTMOLAKESHORE340(self->pDriv));
SCWrite(pCon,pBueffel,eValue);
sprintf(pBueffel,"%s.divisor = %f\n",self->pName,
GetDivisorLAKESHORE340(self->pDriv));
SCWrite(pCon,pBueffel,eValue);
sprintf(pBueffel,"%s.multiplicator = %f\n",self->pName,
GetMultLAKESHORE340(self->pDriv));
SCWrite(pCon,pBueffel,eValue);
return iRet;
}
/*-------------------------------------------------------------------------*/
int LAKESHORE340Wrapper(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[])
{
pEVControl self = NULL;
char pBueffel[256];
int iRet;
double fNum;
float fVal;
self = (pEVControl)pData;
assert(self);
assert(pCon);
assert(pSics);
if(argc < 2)
{
return EVControlWrapper(pCon,pSics,pData,argc,argv);
}
strtolower(argv[1]);
if((strcmp(argv[1],"sensor") == 0) || (strcmp(argv[1],"control") == 0) ||
(strcmp(argv[1],"timeout") == 0) || (strcmp(argv[1],"divisor") == 0) ||
(strcmp(argv[1],"multiplicator") == 0) )
{
if(argc > 2) /* set case */
{
iRet = Tcl_GetDouble(pSics->pTcl,argv[2],&fNum);
if(iRet != TCL_OK)
{
sprintf(pBueffel,"ERROR: expected number, got %s",argv[2]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
return LAKESHORE340SetPar(self,argv[1],(float)fNum,pCon);
}
else /* get case */
{
iRet = LAKESHORE340GetPar(self,argv[1],&fVal);
sprintf(pBueffel,"%s.%s = %f\n",self->pName,
argv[1],fVal);
SCWrite(pCon,pBueffel,eValue);
return 1;
}
}
else if(strcmp(argv[1],"list") == 0)
{
return LAKESHORE340List(self,pCon);
}
else
{
return EVControlWrapper(pCon,pSics,pData,argc,argv);
}
/* not reached */
return 0;
}

49
site_ansto/lakeshore340.h Normal file
View File

@@ -0,0 +1,49 @@
/*-------------------------------------------------------------------------
LAKESHORE 340
Support for Lakeshore 340 Temperature controllers for SICS.
The meaning and working of the functions defined is as desribed for a
general environment controller.
Mark Koennecke, Juli 1997
Mark Lesha, January 2006 (based on ITC4 code)
copyright: see implementation file.
-----------------------------------------------------------------------------*/
#ifndef SICSLAKESHORE340
#define SICSLAKESHORE340
/*------------------------- The Driver ------------------------------------*/
pEVDriver CreateLAKESHORE340Driver(int argc, char *argv[]);
int ConfigLAKESHORE340(pEVDriver self);
int SetSensorLAKESHORE340(pEVDriver self, int iSensor);
int SetControlLAKESHORE340(pEVDriver self, int iSensor);
int GetSensorLAKESHORE340(pEVDriver self);
int GetControlLAKESHORE340(pEVDriver self);
/* Divisors and multipliers should not be applicable to the LAKESHORE340
since it uses floating point variables, but we leave the functions
in here anyway for the time being (setting will have no effect and
a value of 1.0 will always be returned. */
int SetDivisorLAKESHORE340(pEVDriver self, float iSensor);
float GetDivisorLAKESHORE340(pEVDriver self);
int SetMultLAKESHORE340(pEVDriver self, float iSensor);
float GetMultLAKESHORE340(pEVDriver self);
/* Leave in time-out functionality */
int SetTMOLAKESHORE340(pEVDriver self, int iSensor);
int GetTMOLAKESHORE340(pEVDriver self);
/*------------------------- The LAKESHORE340 object ------------------------------*/
int LAKESHORE340Wrapper(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[]);
int LAKESHORE340SetPar(pEVControl self, char *name, float fNew,
SConnection *pCon);
int LAKESHORE340GetPar(pEVControl self, char *name, float *fVal);
int LAKESHORE340List(pEVControl self, SConnection *pCon);
#endif

View File

@@ -0,0 +1,489 @@
/*--------------------------------------------------------------------------
L A K E S H O R E 3 4 0 D R I V
This file contains the implementation of a driver for the
Lakeshore 340 Temperature controller.
Mark Koennecke, Juli 1997
Mark Lesha, January 2006 (based on ITC4 code)
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>
typedef struct __EVDriver *pEVDriver;
#include <evdriver.i>
/* Do we need these ?
#include <sics.h>
#include <modriv.h>
*/
#include <rs232controller.h>
#include "hardsup/lakeshore340util.h"
#include "hardsup/el734_def.h"
#include "hardsup/el734fix.h"
#define SHITTYVALUE -777
/*------------------------- The Driver ------------------------------------*/
pEVDriver CreateLAKESHORE340Driver(int argc, char *argv[]);
int ConfigLAKESHORE340(pEVDriver self);
/*-----------------------------------------------------------------------*/
typedef struct {
pLAKESHORE340 pData;
char *pHost;
int iPort;
int iChannel;
int iControl; /* LAKESHORE340 control */
float fDiv;
float fMult;
int iRead; /* LAKESHORE340 sensor */
int iTmo;
int iLastError;
} LAKESHORE340Driv, *pLAKESHORE340Driv;
/*----------------------------------------------------------------------------*/
static int GetLAKESHORE340Pos(pEVDriver self, float *fPos)
{
pLAKESHORE340Driv pMe = NULL;
int iRet;
assert(self);
pMe = (pLAKESHORE340Driv)self->pPrivate;
assert(pMe);
iRet = LAKESHORE340_Read(&pMe->pData,fPos);
if(iRet <= 0 )
{
pMe->iLastError = iRet;
return 0;
}
if( (*fPos < 0) || (*fPos > 10000) )
{
*fPos = -999.;
pMe->iLastError = SHITTYVALUE;
return 0;
}
return 1;
}
/*----------------------------------------------------------------------------*/
static int LAKESHORE340Run(pEVDriver self, float fVal)
{
pLAKESHORE340Driv pMe = NULL;
int iRet;
assert(self);
pMe = (pLAKESHORE340Driv )self->pPrivate;
assert(pMe);
iRet = LAKESHORE340_Set(&pMe->pData,fVal);
if(iRet != 1)
{
pMe->iLastError = iRet;
return 0;
}
return 1;
}
/*--------------------------------------------------------------------------*/
static int LAKESHORE340Error(pEVDriver self, int *iCode, char *error, int iErrLen)
{
pLAKESHORE340Driv pMe = NULL;
assert(self);
pMe = (pLAKESHORE340Driv)self->pPrivate;
assert(pMe);
*iCode = pMe->iLastError;
if(pMe->iLastError == SHITTYVALUE)
{
strncpy(error,"Invalid temperature returned form LAKESHORE340, check sensor",iErrLen);
}
else
{
LAKESHORE340_ErrorTxt(&pMe->pData,pMe->iLastError,error,iErrLen);
}
return 1;
}
/*--------------------------------------------------------------------------*/
static int LAKESHORE340Send(pEVDriver self, char *pCommand, char *pReply, int iLen)
{
pLAKESHORE340Driv pMe = NULL;
int iRet;
assert(self);
pMe = (pLAKESHORE340Driv )self->pPrivate;
assert(pMe);
iRet = LAKESHORE340_Send(&pMe->pData,pCommand, pReply,iLen);
if(iRet <= 0)
{
pMe->iLastError = iRet;
return 0;
}
return 1;
}
/*--------------------------------------------------------------------------*/
static int LAKESHORE340Init(pEVDriver self)
{
pLAKESHORE340Driv pMe = NULL;
int iRet;
assert(self);
pMe = (pLAKESHORE340Driv )self->pPrivate;
assert(pMe);
pMe->pData = NULL;
iRet = LAKESHORE340_Open(&pMe->pData, pMe->pHost, pMe->iRead, pMe->iControl,0);
if(iRet != 1)
{
if(iRet == LAKESHORE340__NOLAKESHORE340)
{
return -1;
}
else
{
pMe->iLastError = iRet;
return 0;
}
}
return 1;
}
/*--------------------------------------------------------------------------*/
static int LAKESHORE340Close(pEVDriver self)
{
pLAKESHORE340Driv pMe = NULL;
int iRet;
assert(self);
pMe = (pLAKESHORE340Driv )self->pPrivate;
assert(pMe);
LAKESHORE340_Close(&pMe->pData);
return 1;
}
/*---------------------------------------------------------------------------*/
static int LAKESHORE340Fix(pEVDriver self, int iError)
{
pLAKESHORE340Driv pMe = NULL;
int iRet;
assert(self);
pMe = (pLAKESHORE340Driv )self->pPrivate;
assert(pMe);
switch(iError)
{
/* network errors */
case EL734__BAD_FLUSH:
case EL734__BAD_RECV:
case EL734__BAD_RECV_NET:
case EL734__BAD_RECV_UNKN:
case EL734__BAD_RECVLEN:
case EL734__BAD_RECV1:
case EL734__BAD_RECV1_PIPE:
case EL734__BAD_RNG:
case EL734__BAD_SEND:
case EL734__BAD_SEND_PIPE:
case EL734__BAD_SEND_NET:
case EL734__BAD_SEND_UNKN:
case EL734__BAD_SENDLEN:
LAKESHORE340Close(self);
iRet = LAKESHORE340Init(self);
if(iRet)
{
return DEVREDO;
}
else
{
return DEVFAULT;
}
break;
/* handable protocoll errors */
case EL734__BAD_TMO:
return DEVREDO;
break;
case -501: /* Bad_COM */
return DEVREDO;
case -504: /* Badly formatted */
return DEVREDO;
default:
return DEVFAULT;
break;
}
return DEVFAULT;
}
/*--------------------------------------------------------------------------*/
static int LAKESHORE340Halt(pEVDriver *self)
{
assert(self);
return 1;
}
/*------------------------------------------------------------------------*/
void KillLAKESHORE340(void *pData)
{
pLAKESHORE340Driv pMe = NULL;
pMe = (pLAKESHORE340Driv)pData;
assert(pMe);
if(pMe->pHost)
{
free(pMe->pHost);
}
free(pMe);
}
/*------------------------------------------------------------------------*/
pEVDriver CreateLAKESHORE340Driver(int argc, char *argv[])
{
pEVDriver pNew = NULL;
pLAKESHORE340Driv pSim = NULL;
/* check for arguments */
if(argc < 3)
{
return NULL;
}
pNew = CreateEVDriver(argc,argv);
pSim = (pLAKESHORE340Driv)malloc(sizeof(LAKESHORE340Driv));
memset(pSim,0,sizeof(LAKESHORE340Driv));
if(!pNew || !pSim)
{
return NULL;
}
pNew->pPrivate = pSim;
pNew->KillPrivate = KillLAKESHORE340;
/* initalise pLAKESHORE340Driver */
pSim->iControl = atoi(argv[2]);
pSim->iRead = atoi(argv[1]);
pSim->iLastError = 0;
pSim->iTmo = 10;
/* The LAKESHORE340 doesn't require divisors or multipliers
and they are always forced to 1.0 */
pSim->fDiv = 1.0;
pSim->fMult = 1.0;
pSim->pHost = strdup(argv[0]);
pSim->iPort = 0;
pSim->iChannel = 0;
/* initialise function pointers */
pNew->SetValue = LAKESHORE340Run;
pNew->GetValue = GetLAKESHORE340Pos;
pNew->Send = LAKESHORE340Send;
pNew->GetError = LAKESHORE340Error;
pNew->TryFixIt = LAKESHORE340Fix;
pNew->Init = LAKESHORE340Init;
pNew->Close = LAKESHORE340Close;
return pNew;
}
/*--------------------------------------------------------------------------*/
int ConfigLAKESHORE340(pEVDriver self)
{
pLAKESHORE340Driv pMe = NULL;
int iRet;
assert(self);
pMe = (pLAKESHORE340Driv )self->pPrivate;
assert(pMe);
iRet = LAKESHORE340_Config(&pMe->pData, pMe->iTmo, pMe->iRead,
pMe->iControl,pMe->fDiv,pMe->fMult);
if(iRet < 0)
{
pMe->iLastError = iRet;
return 0;
}
return 1;
}
/*-------------------------------------------------------------------------*/
int SetSensorLAKESHORE340(pEVDriver self, int iSensor)
{
pLAKESHORE340Driv pMe = NULL;
int iRet;
assert(self);
pMe = (pLAKESHORE340Driv )self->pPrivate;
assert(pMe);
/* The LAKESHORE340 allows bath temp, external temp and tank temp to be read
so allow iRead=1 to 4 for A,B,C,D respectively. */
if( (iSensor < 1) || (iSensor > 4) )
{
return 0;
}
pMe->iRead = iSensor;
pMe->pData->iRead = iSensor;
return 1;
}
/*-------------------------------------------------------------------------*/
int SetControlLAKESHORE340(pEVDriver self, int iSensor)
{
pLAKESHORE340Driv pMe = NULL;
int iRet;
assert(self);
pMe = (pLAKESHORE340Driv )self->pPrivate;
assert(pMe);
/* For the LAKESHORE340 allow selection of internal or external control
where iControl==1 to 4 for A,B,C,D respectively. */
if( (iSensor < 1) || (iSensor > 4) )
{
return 0;
}
pMe->iControl = iSensor;
pMe->pData->iControl = iSensor;
return 1;
}
/*-------------------------------------------------------------------------*/
int SetTMOLAKESHORE340(pEVDriver self, int iSensor)
{
pLAKESHORE340Driv pMe = NULL;
int iRet;
assert(self);
pMe = (pLAKESHORE340Driv )self->pPrivate;
assert(pMe);
if(iSensor < 10)
{
return 0;
}
pMe->iTmo = iSensor;
return 1;
}
/*-------------------------------------------------------------------------*/
int GetControlLAKESHORE340(pEVDriver self)
{
pLAKESHORE340Driv pMe = NULL;
int iRet;
assert(self);
pMe = (pLAKESHORE340Driv )self->pPrivate;
assert(pMe);
return pMe->iControl;
}
/*-------------------------------------------------------------------------*/
int GetSensorLAKESHORE340(pEVDriver self)
{
pLAKESHORE340Driv pMe = NULL;
int iRet;
assert(self);
pMe = (pLAKESHORE340Driv )self->pPrivate;
assert(pMe);
return pMe->iRead;
}
/*-------------------------------------------------------------------------*/
int GetTMOLAKESHORE340(pEVDriver self)
{
pLAKESHORE340Driv pMe = NULL;
int iRet;
assert(self);
pMe = (pLAKESHORE340Driv )self->pPrivate;
assert(pMe);
return pMe->iTmo;
}
/*-------------------------------------------------------------------------*/
float GetDivisorLAKESHORE340(pEVDriver self)
{
pLAKESHORE340Driv pMe = NULL;
int iRet;
assert(self);
pMe = (pLAKESHORE340Driv )self->pPrivate;
assert(pMe);
return pMe->fDiv; /* but forced to 1.0 for LAKESHORE340, not used */
}
/*--------------------------------------------------------------------------*/
int SetDivisorLAKESHORE340(pEVDriver self, float fDiv)
{
pLAKESHORE340Driv pMe = NULL;
int iRet;
assert(self);
pMe = (pLAKESHORE340Driv )self->pPrivate;
assert(pMe);
/* The LAKESHORE340 doesn't need divisor, force to 1.0 */
pMe->fDiv = 1.0; /* fDiv */;
return 1;
}
/*-------------------------------------------------------------------------*/
float GetMultLAKESHORE340(pEVDriver self)
{
pLAKESHORE340Driv pMe = NULL;
int iRet;
assert(self);
pMe = (pLAKESHORE340Driv )self->pPrivate;
assert(pMe);
return pMe->fMult; /* but forced to 1.0 for LAKESHORE340, not used */
}
/*--------------------------------------------------------------------------*/
int SetMultLAKESHORE340(pEVDriver self, float fDiv)
{
pLAKESHORE340Driv pMe = NULL;
int iRet;
assert(self);
pMe = (pLAKESHORE340Driv )self->pPrivate;
assert(pMe);
/* The LAKESHORE340 doesn't need multiplier, force to 1.0 */
pMe->fMult = 1.0; /* fDiv */;
return 1;
}

284
site_ansto/lh45.c Normal file
View File

@@ -0,0 +1,284 @@
/*---------------------------------------------------------------------------
L H 4 5
This is the implementation for a LH45 object derived from an more general
environment controller.
Mark Koennecke, August 1997
Mark Lesha, January 2006 (based on ITC4 code)
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 <assert.h>
#include <tcl.h>
#include <fortify.h>
#include <sics.h>
#include <splitter.h>
#include <obpar.h>
#include <devexec.h>
#include <nserver.h>
#include <interrupt.h>
#include <emon.h>
#include <evcontroller.h>
#include <evcontroller.i>
#include "lh45.h"
/*---------------------------------------------------------------------------*/
int LH45SetPar(pEVControl self, char *name, float fNew, SConnection *pCon)
{
int iRet;
/* check authorsisation */
if(!SCMatchRights(pCon,usUser))
{
SCWrite(pCon,"ERROR: you are not authorised to change this parameter",
eError);
return 0;
}
/* just catch those three names which we understand */
if(strcmp(name,"sensor") == 0)
{
iRet = SetSensorLH45(self->pDriv,(int)fNew);
if(!iRet)
{
SCWrite(pCon,"ERROR: value out of range",eError);
return 0;
}
iRet = ConfigLH45(self->pDriv);
if(iRet != 1)
{
SCWrite(pCon,"ERROR: LH45 configuration failed! ",eError);
SCWrite(pCon,"INFO: Probably comm problem, Retry!",eError);
return 0;
}
SCSendOK(pCon);
return 1;
}
else if(strcmp(name,"control") == 0)
{
iRet = SetControlLH45(self->pDriv,(int)fNew);
if(!iRet)
{
SCWrite(pCon,"ERROR: value out of range",eError);
return 0;
}
iRet = ConfigLH45(self->pDriv);
if(iRet != 1)
{
SCWrite(pCon,"ERROR: LH45 configuration failed! ",eError);
SCWrite(pCon,"INFO: Probably comm problem, Retry!",eError);
return 0;
}
SCSendOK(pCon);
return 1;
}
else if(strcmp(name,"timeout") == 0)
{
iRet = SetTMOLH45(self->pDriv,(int)fNew);
if(!iRet)
{
SCWrite(pCon,"ERROR: value out of range",eError);
return 0;
}
iRet = ConfigLH45(self->pDriv);
if(iRet != 1)
{
SCWrite(pCon,"ERROR: LH45 configuration failed! ",eError);
SCWrite(pCon,"INFO: Probably comm problem, Retry!",eError);
return 0;
}
SCSendOK(pCon);
return 1;
}
/* Note divisors and multipliers will not be used with the LH45
but leave in for back compatibility */
else if(strcmp(name,"divisor") == 0)
{
iRet = SetDivisorLH45(self->pDriv,fNew);
if(!iRet)
{
SCWrite(pCon,"ERROR: value out of range",eError);
return 0;
}
iRet = ConfigLH45(self->pDriv);
if(iRet != 1)
{
SCWrite(pCon,"ERROR: LH45 configuration failed! ",eError);
SCWrite(pCon,"INFO: Probably comm problem, Retry!",eError);
return 0;
}
SCSendOK(pCon);
return 1;
}
else if(strcmp(name,"multiplicator") == 0)
{
iRet = SetMultLH45(self->pDriv,fNew);
if(!iRet)
{
SCWrite(pCon,"ERROR: value out of range",eError);
return 0;
}
iRet = ConfigLH45(self->pDriv);
if(iRet != 1)
{
SCWrite(pCon,"ERROR: LH45 configuration failed! ",eError);
SCWrite(pCon,"INFO: Probably comm problem, Retry!",eError);
return 0;
}
SCSendOK(pCon);
return 1;
}
else
return EVCSetPar(self,name,fNew,pCon);
}
/*--------------------------------------------------------------------------*/
int LH45GetPar(pEVControl self, char *name, float *fNew)
{
int iRet;
float fDiv;
/* just catch those two names which we understand */
if(strcmp(name,"sensor") == 0)
{
iRet = GetSensorLH45(self->pDriv);
*fNew = (float)iRet;
return 1;
}
else if(strcmp(name,"control") == 0)
{
iRet = GetControlLH45(self->pDriv);
*fNew = (float)iRet;
return 1;
}
else if(strcmp(name,"timeout") == 0)
{
iRet = GetTMOLH45(self->pDriv);
*fNew = (float)iRet;
return 1;
}
else if(strcmp(name,"divisor") == 0)
{
fDiv = GetDivisorLH45(self->pDriv);
*fNew = fDiv;
return 1;
}
else if(strcmp(name,"multiplicator") == 0)
{
fDiv = GetMultLH45(self->pDriv);
*fNew = fDiv;
return 1;
}
else
return EVCGetPar(self,name,fNew);
}
/*---------------------------------------------------------------------------*/
int LH45List(pEVControl self, SConnection *pCon)
{
char pBueffel[132];
int iRet;
iRet = EVCList(self,pCon);
sprintf(pBueffel,"%s.sensor = %d\n",self->pName,
GetSensorLH45(self->pDriv));
SCWrite(pCon,pBueffel,eValue);
sprintf(pBueffel,"%s.control = %d\n",self->pName,
GetControlLH45(self->pDriv));
SCWrite(pCon,pBueffel,eValue);
sprintf(pBueffel,"%s.timeout = %d\n",self->pName,
GetTMOLH45(self->pDriv));
SCWrite(pCon,pBueffel,eValue);
sprintf(pBueffel,"%s.divisor = %f\n",self->pName,
GetDivisorLH45(self->pDriv));
SCWrite(pCon,pBueffel,eValue);
sprintf(pBueffel,"%s.multiplicator = %f\n",self->pName,
GetMultLH45(self->pDriv));
SCWrite(pCon,pBueffel,eValue);
return iRet;
}
/*-------------------------------------------------------------------------*/
int LH45Wrapper(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[])
{
pEVControl self = NULL;
char pBueffel[256];
int iRet;
double fNum;
float fVal;
self = (pEVControl)pData;
assert(self);
assert(pCon);
assert(pSics);
if(argc < 2)
{
return EVControlWrapper(pCon,pSics,pData,argc,argv);
}
strtolower(argv[1]);
if((strcmp(argv[1],"sensor") == 0) || (strcmp(argv[1],"control") == 0) ||
(strcmp(argv[1],"timeout") == 0) || (strcmp(argv[1],"divisor") == 0) ||
(strcmp(argv[1],"multiplicator") == 0) )
{
if(argc > 2) /* set case */
{
iRet = Tcl_GetDouble(pSics->pTcl,argv[2],&fNum);
if(iRet != TCL_OK)
{
sprintf(pBueffel,"ERROR: expected number, got %s",argv[2]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
return LH45SetPar(self,argv[1],(float)fNum,pCon);
}
else /* get case */
{
iRet = LH45GetPar(self,argv[1],&fVal);
sprintf(pBueffel,"%s.%s = %f\n",self->pName,
argv[1],fVal);
SCWrite(pCon,pBueffel,eValue);
return 1;
}
}
else if(strcmp(argv[1],"list") == 0)
{
return LH45List(self,pCon);
}
else
{
return EVControlWrapper(pCon,pSics,pData,argc,argv);
}
/* not reached */
return 0;
}

49
site_ansto/lh45.h Normal file
View File

@@ -0,0 +1,49 @@
/*-------------------------------------------------------------------------
LH 45
Support for Julabo LH45 Temperature controllers for SICS.
The meaning and working of the functions defined is as desribed for a
general environment controller.
Mark Koennecke, Juli 1997
Mark Lesha, January 2006 (based on ITC4 code)
copyright: see implementation file.
-----------------------------------------------------------------------------*/
#ifndef SICSLH45
#define SICSLH45
/*------------------------- The Driver ------------------------------------*/
pEVDriver CreateLH45Driver(int argc, char *argv[]);
int ConfigLH45(pEVDriver self);
int SetSensorLH45(pEVDriver self, int iSensor);
int SetControlLH45(pEVDriver self, int iSensor);
int GetSensorLH45(pEVDriver self);
int GetControlLH45(pEVDriver self);
/* Divisors and multipliers should not be applicable to the LH45
since it uses floating point variables, but we leave the functions
in here anyway for the time being (setting will have no effect and
a value of 1.0 will always be returned. */
int SetDivisorLH45(pEVDriver self, float iSensor);
float GetDivisorLH45(pEVDriver self);
int SetMultLH45(pEVDriver self, float iSensor);
float GetMultLH45(pEVDriver self);
/* Leave in time-out functionality */
int SetTMOLH45(pEVDriver self, int iSensor);
int GetTMOLH45(pEVDriver self);
/*------------------------- The LH45 object ------------------------------*/
int LH45Wrapper(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[]);
int LH45SetPar(pEVControl self, char *name, float fNew,
SConnection *pCon);
int LH45GetPar(pEVControl self, char *name, float *fVal);
int LH45List(pEVControl self, SConnection *pCon);
#endif

489
site_ansto/lh45driv.c Normal file
View File

@@ -0,0 +1,489 @@
/*--------------------------------------------------------------------------
L H 4 5 D R I V
This file contains the implementation of a driver for the Julabo
LH45 Temperature controller.
Mark Koennecke, Juli 1997
Mark Lesha, January 2006 (based on ITC4 code)
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>
typedef struct __EVDriver *pEVDriver;
#include <evdriver.i>
/* Do we need these ?
#include <sics.h>
#include <modriv.h>
*/
#include <rs232controller.h>
#include "hardsup/lh45util.h"
#include "hardsup/el734_def.h"
#include "hardsup/el734fix.h"
#define SHITTYVALUE -777
/*------------------------- The Driver ------------------------------------*/
pEVDriver CreateLH45Driver(int argc, char *argv[]);
int ConfigLH45(pEVDriver self);
/*-----------------------------------------------------------------------*/
typedef struct {
pLH45 pData;
char *pHost;
int iPort;
int iChannel;
int iControl; /* LH45 control */
float fDiv;
float fMult;
int iRead; /* LH45 sensor */
int iTmo;
int iLastError;
} LH45Driv, *pLH45Driv;
/*----------------------------------------------------------------------------*/
static int GetLH45Pos(pEVDriver self, float *fPos)
{
pLH45Driv pMe = NULL;
int iRet;
assert(self);
pMe = (pLH45Driv)self->pPrivate;
assert(pMe);
iRet = LH45_Read(&pMe->pData,fPos);
if(iRet <= 0 )
{
pMe->iLastError = iRet;
return 0;
}
if( (*fPos < 0) || (*fPos > 10000) )
{
*fPos = -999.;
pMe->iLastError = SHITTYVALUE;
return 0;
}
return 1;
}
/*----------------------------------------------------------------------------*/
static int LH45Run(pEVDriver self, float fVal)
{
pLH45Driv pMe = NULL;
int iRet;
assert(self);
pMe = (pLH45Driv )self->pPrivate;
assert(pMe);
iRet = LH45_Set(&pMe->pData,fVal);
if(iRet != 1)
{
pMe->iLastError = iRet;
return 0;
}
return 1;
}
/*--------------------------------------------------------------------------*/
static int LH45Error(pEVDriver self, int *iCode, char *error, int iErrLen)
{
pLH45Driv pMe = NULL;
assert(self);
pMe = (pLH45Driv)self->pPrivate;
assert(pMe);
*iCode = pMe->iLastError;
if(pMe->iLastError == SHITTYVALUE)
{
strncpy(error,"Invalid temperature returned form LH45, check sensor",iErrLen);
}
else
{
LH45_ErrorTxt(&pMe->pData,pMe->iLastError,error,iErrLen);
}
return 1;
}
/*--------------------------------------------------------------------------*/
static int LH45Send(pEVDriver self, char *pCommand, char *pReply, int iLen)
{
pLH45Driv pMe = NULL;
int iRet;
assert(self);
pMe = (pLH45Driv )self->pPrivate;
assert(pMe);
iRet = LH45_Send(&pMe->pData,pCommand, pReply,iLen);
if(iRet <= 0)
{
pMe->iLastError = iRet;
return 0;
}
return 1;
}
/*--------------------------------------------------------------------------*/
static int LH45Init(pEVDriver self)
{
pLH45Driv pMe = NULL;
int iRet;
assert(self);
pMe = (pLH45Driv )self->pPrivate;
assert(pMe);
pMe->pData = NULL;
iRet = LH45_Open(&pMe->pData, pMe->pHost, pMe->iRead, pMe->iControl,0);
if(iRet != 1)
{
if(iRet == LH45__NOLH45)
{
return -1;
}
else
{
pMe->iLastError = iRet;
return 0;
}
}
return 1;
}
/*--------------------------------------------------------------------------*/
static int LH45Close(pEVDriver self)
{
pLH45Driv pMe = NULL;
int iRet;
assert(self);
pMe = (pLH45Driv )self->pPrivate;
assert(pMe);
LH45_Close(&pMe->pData);
return 1;
}
/*---------------------------------------------------------------------------*/
static int LH45Fix(pEVDriver self, int iError)
{
pLH45Driv pMe = NULL;
int iRet;
assert(self);
pMe = (pLH45Driv )self->pPrivate;
assert(pMe);
switch(iError)
{
/* network errors */
case EL734__BAD_FLUSH:
case EL734__BAD_RECV:
case EL734__BAD_RECV_NET:
case EL734__BAD_RECV_UNKN:
case EL734__BAD_RECVLEN:
case EL734__BAD_RECV1:
case EL734__BAD_RECV1_PIPE:
case EL734__BAD_RNG:
case EL734__BAD_SEND:
case EL734__BAD_SEND_PIPE:
case EL734__BAD_SEND_NET:
case EL734__BAD_SEND_UNKN:
case EL734__BAD_SENDLEN:
LH45Close(self);
iRet = LH45Init(self);
if(iRet)
{
return DEVREDO;
}
else
{
return DEVFAULT;
}
break;
/* handable protocoll errors */
case EL734__BAD_TMO:
return DEVREDO;
break;
case -501: /* Bad_COM */
return DEVREDO;
case -504: /* Badly formatted */
return DEVREDO;
default:
return DEVFAULT;
break;
}
return DEVFAULT;
}
/*--------------------------------------------------------------------------*/
static int LH45Halt(pEVDriver *self)
{
assert(self);
return 1;
}
/*------------------------------------------------------------------------*/
void KillLH45(void *pData)
{
pLH45Driv pMe = NULL;
pMe = (pLH45Driv)pData;
assert(pMe);
if(pMe->pHost)
{
free(pMe->pHost);
}
free(pMe);
}
/*------------------------------------------------------------------------*/
pEVDriver CreateLH45Driver(int argc, char *argv[])
{
pEVDriver pNew = NULL;
pLH45Driv pSim = NULL;
/* check for arguments */
if(argc < 3)
{
return NULL;
}
pNew = CreateEVDriver(argc,argv);
pSim = (pLH45Driv)malloc(sizeof(LH45Driv));
memset(pSim,0,sizeof(LH45Driv));
if(!pNew || !pSim)
{
return NULL;
}
pNew->pPrivate = pSim;
pNew->KillPrivate = KillLH45;
/* initalise pLH45Driver */
pSim->iControl = atoi(argv[2]);
pSim->iRead = atoi(argv[1]);
pSim->iLastError = 0;
pSim->iTmo = 10;
/* The LH45 doesn't require divisors or multipliers
and they are always forced to 1.0 */
pSim->fDiv = 1.0;
pSim->fMult = 1.0;
pSim->pHost = strdup(argv[0]);
pSim->iPort = 0;
pSim->iChannel = 0;
/* initialise function pointers */
pNew->SetValue = LH45Run;
pNew->GetValue = GetLH45Pos;
pNew->Send = LH45Send;
pNew->GetError = LH45Error;
pNew->TryFixIt = LH45Fix;
pNew->Init = LH45Init;
pNew->Close = LH45Close;
return pNew;
}
/*--------------------------------------------------------------------------*/
int ConfigLH45(pEVDriver self)
{
pLH45Driv pMe = NULL;
int iRet;
assert(self);
pMe = (pLH45Driv )self->pPrivate;
assert(pMe);
iRet = LH45_Config(&pMe->pData, pMe->iTmo, pMe->iRead,
pMe->iControl,pMe->fDiv,pMe->fMult);
if(iRet < 0)
{
pMe->iLastError = iRet;
return 0;
}
return 1;
}
/*-------------------------------------------------------------------------*/
int SetSensorLH45(pEVDriver self, int iSensor)
{
pLH45Driv pMe = NULL;
int iRet;
assert(self);
pMe = (pLH45Driv )self->pPrivate;
assert(pMe);
/* The LH45 allows bath temp, external temp and tank temp to be read
so allow iRead=1 to 3 for each of these respectively */
if( (iSensor < 1) || (iSensor > 3) )
{
return 0;
}
pMe->iRead = iSensor;
pMe->pData->iRead = iSensor;
return 1;
}
/*-------------------------------------------------------------------------*/
int SetControlLH45(pEVDriver self, int iSensor)
{
pLH45Driv pMe = NULL;
int iRet;
assert(self);
pMe = (pLH45Driv )self->pPrivate;
assert(pMe);
/* For the LH45 allow selection of internal or external control
where iControl==1 or 2 respectively */
if( (iSensor < 1) || (iSensor > 2) )
{
return 0;
}
pMe->iControl = iSensor;
pMe->pData->iControl = iSensor;
return 1;
}
/*-------------------------------------------------------------------------*/
int SetTMOLH45(pEVDriver self, int iSensor)
{
pLH45Driv pMe = NULL;
int iRet;
assert(self);
pMe = (pLH45Driv )self->pPrivate;
assert(pMe);
if(iSensor < 10)
{
return 0;
}
pMe->iTmo = iSensor;
return 1;
}
/*-------------------------------------------------------------------------*/
int GetControlLH45(pEVDriver self)
{
pLH45Driv pMe = NULL;
int iRet;
assert(self);
pMe = (pLH45Driv )self->pPrivate;
assert(pMe);
return pMe->iControl;
}
/*-------------------------------------------------------------------------*/
int GetSensorLH45(pEVDriver self)
{
pLH45Driv pMe = NULL;
int iRet;
assert(self);
pMe = (pLH45Driv )self->pPrivate;
assert(pMe);
return pMe->iRead;
}
/*-------------------------------------------------------------------------*/
int GetTMOLH45(pEVDriver self)
{
pLH45Driv pMe = NULL;
int iRet;
assert(self);
pMe = (pLH45Driv )self->pPrivate;
assert(pMe);
return pMe->iTmo;
}
/*-------------------------------------------------------------------------*/
float GetDivisorLH45(pEVDriver self)
{
pLH45Driv pMe = NULL;
int iRet;
assert(self);
pMe = (pLH45Driv )self->pPrivate;
assert(pMe);
return pMe->fDiv; /* but forced to 1.0 for LH45, not used */
}
/*--------------------------------------------------------------------------*/
int SetDivisorLH45(pEVDriver self, float fDiv)
{
pLH45Driv pMe = NULL;
int iRet;
assert(self);
pMe = (pLH45Driv )self->pPrivate;
assert(pMe);
/* The LH45 doesn't need divisor, force to 1.0 */
pMe->fDiv = 1.0; /* fDiv */;
return 1;
}
/*-------------------------------------------------------------------------*/
float GetMultLH45(pEVDriver self)
{
pLH45Driv pMe = NULL;
int iRet;
assert(self);
pMe = (pLH45Driv )self->pPrivate;
assert(pMe);
return pMe->fMult; /* but forced to 1.0 for LH45, not used */
}
/*--------------------------------------------------------------------------*/
int SetMultLH45(pEVDriver self, float fDiv)
{
pLH45Driv pMe = NULL;
int iRet;
assert(self);
pMe = (pLH45Driv )self->pPrivate;
assert(pMe);
/* The LH45 doesn't need multiplier, force to 1.0 */
pMe->fMult = 1.0; /* fDiv */;
return 1;
}

View File

@@ -0,0 +1,34 @@
# vim: ft=make ts=4 sw=4 noet cindent
COBJ = Sclient.o network.o ifile.o intcli.o $(FORTIFYOBJ)
SOBJ = network.o ifile.o conman.o SCinter.o splitter.o passwd.o \
servlog.o sicvar.o nserver.o SICSmain.o motorlist.o\
sicsexit.o costa.o task.o $(FORTIFYOBJ)\
macro.o ofac.o obpar.o obdes.o drive.o status.o intserv.o \
devexec.o mumo.o mumoconf.o selector.o selvar.o fupa.o lld.o \
lld_blob.o strrepl.o lin2ang.o fomerge.o \
script.o o2t.o alias.o napi.o napi5.o nxdata.o stringdict.o sdynar.o \
histmem.o histdriv.o histsim.o interface.o callback.o \
event.o emon.o evcontroller.o evdriver.o simev.o perfmon.o \
danu.o nxdict.o varlog.o stptok.o nread.o trigd.o cell.o\
scan.o fitcenter.o telnet.o token.o wwildcard.o hklmot.o\
tclev.o hkl.o integrate.o optimise.o dynstring.o nxutil.o \
mesure.o uubuffer.o commandlog.o udpquieck.o fourtable.o\
rmtrail.o help.o nxupdate.o confvirtualmot.o vector.o\
simchop.o choco.o chadapter.o trim.o scaldate.o tasub.o\
hklscan.o xytable.o exebuf.o exeman.o ubfour.o ubcalc.o\
circular.o maximize.o sicscron.o scanvar.o tasublib.o\
d_sign.o d_mod.o tcldrivable.o stdscan.o diffscan.o \
synchronize.o definealias.o oscillate.o tasdrive.o \
hmcontrol.o userscan.o rs232controller.o lomax.o tasscanub.o \
fourlib.o motreg.o motreglist.o anticollider.o nxdataset.o \
s_rnge.o sig_die.o gpibcontroller.o $(NIOBJ) mcreader.o mccontrol.o\
hmdata.o nxscript.o tclintimpl.o sicsdata.o mcstascounter.o \
mcstashm.o initializer.o remob.o tclmotdriv.o protocol.o \
sinfox.o sicslist.o cone.o $(EXTRA)
MOTOROBJ = motor.o simdriv.o
COUNTEROBJ = countdriv.o simcter.o counter.o
VELOOBJ = velo.o velosim.o
COREOBJ = $(SOBJ) $(MOTOROBJ) $(COUNTEROBJ) $(VELOOBJ)

655
site_ansto/motor_asim.c Normal file
View File

@@ -0,0 +1,655 @@
/*-----------------------------------------------------------------------------
Based on SINQ code 1996-2003 by Mark Koennecke
Modifications: Paul Hathaway April 2004
SimRun failure rate independent of polling rate
Fault condition determined at initial drive command and reported
at appropriate time:
ASIM_NO_FAULT - run to destination, report no error (OKOK,HWIdle)
ASIM_HW_FAULT - no movement, report HWFault
ASIM_POS_FAULT - run to error position, report no error (OKOK,HWIdle)
ASIM_STALL_FAULT - run to stall position, report HWFault
Copyright: See COPYRIGHT.txt
Instrument definition file usage:
Motor motname ASIM lowerlimit upperlimit failpercent [speed]
----------------------------------------------------------------------------*/
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <time.h>
#include <math.h>
/* SICS kernel declarations */
#include "sics.h"
#include "modriv.h" /* includes abstract motor defn */
#include "fortify.h"
#include "conman.h"
#include "servlog.h"
#include "splitter.h"
#include "SCinter.h"
/* #include "motor_driver.h" */
/* Ansto-specific simulation driver */
/* #include "sim_motor.h" */
#include "motor_asim.h"
/* ----------------------- Simulation -----------------------------------*/
/* #ifndef SICS_ANSTO_MOTOR_ASIM */
#define SICS_ANSTO_MOTOR_ASIM
#define MAX_LONG 2147483647
/* device internal status and error codes */
/* BUSY - motor in motion toward target
* IDLE - movement complete, normal condition
* FAULT - no motion, motor awaiting reset
* CRASH - no motion, unable to recover
*/
#define ASIM_BUSY 1
#define ASIM_IDLE 2
#define ASIM_FAULT 3
#define ASIM_CRASH 4
/* the first fields of ASIMDriv structure HAVE to be IDENTICAL to the
* abstract motor driver structure in modriv.h (motor_driver.h)
*/
typedef struct ___MoDriv {
/* general motor driver interface fields. REQUIRED! */
float fUpper; /* upper limit */
float fLower; /* lower limit */
char *name;
int (*GetPosition)(void *self,float *fPos);
int (*RunTo)(void *self, float fNewVal);
int (*GetStatus)(void *self);
void (*GetError)(void *self, int *iCode, char *buffer, int iBufLen);
int (*TryAndFixIt)(void *self,int iError, float fNew);
int (*Halt)(void *self);
int (*GetDriverPar)(void *self, char *name, float *value);
int (*SetDriverPar)(void *self,SConnection *pCon, char *name,
float newValue);
void (*ListDriverPar)(void *self, char *motorName, SConnection *pCon);
void (*KillPrivate)(void *self);
/* ASIM-specific fields */
float fFailure; /* percent random failures */
int iFaultType; /* used internally and for debugging */
float fSpeed;
long iDuration; /* expected duration of move (secs) */
long iTime; /* expected completion time (secs since 1969) */
long iRunningTime; /* time (sec) running current move */
long iLastPollTime;
float fPos; /* simulated current position */
float fTarget; /* simulation target position including fault */
float fDestination; /* requested final position */
int iStatus;
} ASIMDriv;
/* fault types */
#define ASIM_NO_FAULT 0
#define ASIM_HW_FAULT 1
#define ASIM_POS_FAULT 2
#define ASIM_STALL_FAULT 3
/* thresholds for determining relative proportion of fault types */
/*static const float TH_HW_FAULT = 20.0; /* ie (20-0) % of faults */
/*static const float TH_STALL_FAULT = 40.0; /* ie (40-20)% of faults */
/*static const float TH_POS_FAULT = 100.0; /* ie remaining faults */
/*static const float MIN_SPEED = 0.0001; */
#define TH_HW_FAULT 20.0
#define TH_STALL_FAULT 40.0
#define TH_POS_FAULT 100.0
#define MIN_SPEED 0.0001
/* void KillASIM(void *pData); */
static void UpdateRunningTime(ASIMDriv *);
static void UpdatePosition(ASIMDriv *);
static float SimRandom(void);
static int SimHalt(void *);
static int RunComplete(ASIMDriv *);
static int SimGetPos(void *, float *);
static int SimRun(void *, float);
static void SimError(void *self, int *iCode, char *error, int iErrLen);
static int SimFix(void *self, int iError, float fNew);
static int SimHalt(void *self);
static int SimStat(void *self);
/*-------------------------------------------------------------------------*/
static float SimRandom(void)
{
float fVal;
fVal = ( (float) rand() / (float)RAND_MAX ) * 100.0;
return fVal;
}
/*---------------------------------------------------------------------------*/
static void UpdateRunningTime(ASIMDriv *pDriv)
{
time_t tD;
time(&tD); /* This fn valid between Jan 1970 and Jan 2038 */
if (ASIM_BUSY == pDriv->iStatus)
{
pDriv->iRunningTime += ((long)tD - pDriv->iLastPollTime);
}
pDriv->iLastPollTime = (long)tD;
}
/*----------------------------------------------------------------------------*/
static void UpdatePosition(ASIMDriv *pDriv)
{
float fDirn = 1.0;
UpdateRunningTime(pDriv);
switch (pDriv->iStatus)
{
case ASIM_BUSY:
if (pDriv->iRunningTime >= pDriv->iDuration)
{
switch (pDriv->iFaultType)
{
case ASIM_POS_FAULT: /* no break */
case ASIM_NO_FAULT:
pDriv->fPos = pDriv->fTarget;
pDriv->iStatus = ASIM_IDLE;
break;
default :
pDriv->iFaultType = ASIM_HW_FAULT; /* no break */
case ASIM_HW_FAULT:
pDriv->iStatus = ASIM_FAULT;
break;
case ASIM_STALL_FAULT:
pDriv->fPos = pDriv->fTarget;
pDriv->iStatus = ASIM_FAULT;
break;
}
}
else /* Running. Calculate intermediate position */
{
switch (pDriv->iFaultType)
{
case ASIM_POS_FAULT:
case ASIM_NO_FAULT:
case ASIM_STALL_FAULT:
if (pDriv->fTarget < pDriv->fPos) {
fDirn = -1.0;
} else fDirn = 1.0;
pDriv->fPos = pDriv->fTarget - fDirn * pDriv->fSpeed * (pDriv->iDuration - pDriv->iRunningTime);
pDriv->iStatus = ASIM_BUSY;
break;
case ASIM_HW_FAULT:
pDriv->iStatus = ASIM_FAULT;
break;
default: break; /* error: unknown fault type */
}
}
break;
case ASIM_FAULT:
case ASIM_IDLE:
case ASIM_CRASH:
default: break;
}
}
/*---------------------------------------------------------------------------*/
static int RunComplete(ASIMDriv *pDriv)
{
UpdatePosition(pDriv);
if(ASIM_BUSY!=pDriv->iStatus) return 1; else return 0;
}
/*----------------------------------------------------------------------------*/
static int SimGetPos(void *self, float *fPos)
{
int motCode = OKOK;
ASIMDriv *pDriv;
assert(self);
pDriv = (ASIMDriv *)self;
UpdatePosition(pDriv);
*fPos = pDriv->fPos;
switch (pDriv->iStatus)
{
case ASIM_IDLE: /* no break */
case ASIM_BUSY:
motCode = OKOK;
break;
default:
case ASIM_CRASH:
case ASIM_FAULT:
motCode = HWFault;
break;
}
return motCode;
}
/*----------------------------------------------------------------------------*/
static int SimRun(void *self, float fVal)
{
ASIMDriv *pDriv;
float fDiff;
float fFault;
int iSucceed;
float fDirection;
float fDelta;
float fDuration;
time_t tD;
assert(self);
pDriv = (ASIMDriv *)self;
switch (pDriv->iStatus)
{
case ASIM_IDLE: pDriv->iStatus = ASIM_BUSY;
case ASIM_BUSY: break;
default: pDriv->iStatus = ASIM_CRASH;
case ASIM_CRASH:
case ASIM_FAULT: return HWFault;
break;
}
/* New run command */
/* Determine desired distance and direction (fDiff >= 0.0)*/
pDriv->fDestination = fVal;
fDiff = fVal - pDriv->fPos;
if(0.0 > fDiff)
{
fDiff = -fDiff;
fDirection = -1.0;
}
else
fDirection = 1.0;
/* Determine whether fault will occur */
if ((0.0 >= pDriv->fFailure)||(SimRandom() > pDriv->fFailure))
iSucceed = 1;
else
iSucceed = 0;
/* Determine delta from actual target by fault mode */
if (0 == iSucceed)
{
fFault = SimRandom();
if ((TH_HW_FAULT > fFault)||(HWFault==pDriv->iStatus))
{ /* fail as soon as possible */
pDriv->iStatus = ASIM_FAULT;
pDriv->iFaultType = ASIM_HW_FAULT;
fDelta = -fDiff;
}
else
{
if (TH_STALL_FAULT > fFault)
{ /* stall before 80% complete */
pDriv->iFaultType = ASIM_STALL_FAULT;
fDelta = (-1.0) * fDiff * (0.2 + SimRandom()/125.0);
}
else
{ /* position fault to +/- 10% */
pDriv->iFaultType = ASIM_POS_FAULT;
fDelta = fDiff * SimRandom()/1000.0;
if (50.0 > SimRandom()) fDelta = -fDelta;
}
}
}
else /* no failure */
{
pDriv->iFaultType = ASIM_NO_FAULT;
fDelta = 0.0;
}
/* Calculate target and time using speed */
if (pDriv->fSpeed >= MIN_SPEED)
{
fDiff = fDiff + fDelta;
fDuration = fDiff/(pDriv->fSpeed);
if (fDuration > MAX_LONG)
pDriv->iDuration = 2000000000;
else
pDriv->iDuration = (long)fDuration;
}
else
{
fDiff = 0.0;
pDriv->iDuration = 0;
}
pDriv->fTarget = pDriv->fPos + fDirection * fDiff;
pDriv->iRunningTime = 0;
pDriv->iLastPollTime = time(&tD);
pDriv->iTime = tD + pDriv->iDuration;
if(ASIM_BUSY==pDriv->iStatus)
return OKOK;
else
return HWFault;
} /* SimRun */
/*--------------------------------------------------------------------------*/
/* iErrLen fixed to 131 in fn [reportAndFixError] of <motor.c>
* iCode reported to SimFix via [reportAndFixError]
*/
static void SimError(void *self, int *iCode, char *error, int iErrLen)
{
int motCode = HWFault;
ASIMDriv *pDriv;
assert(self);
pDriv = (ASIMDriv *)self;
switch (pDriv->iStatus)
{
case ASIM_IDLE: motCode = HWIdle; break;
case ASIM_BUSY: motCode = HWBusy; break;
case ASIM_CRASH:
case ASIM_FAULT:
default: motCode = HWFault; break;
}
*iCode = pDriv->iFaultType;
switch (pDriv->iFaultType)
{
case ASIM_POS_FAULT:
strncpy(error,"ERROR: ASIM Position Fault",iErrLen);
break;
case ASIM_NO_FAULT:
strncpy(error,"STATUS: ASIM No Fault",iErrLen);
break;
case ASIM_HW_FAULT:
strncpy(error,"ERROR: ASIM Motor Hardware Fault",iErrLen);
break;
case ASIM_STALL_FAULT:
strncpy(error,"ERROR: ASIM Motor Stall",iErrLen);
break;
default: /* error: unknown fault type */
strncpy(error,"ERROR: Unknown fault type",iErrLen);
break;
}
assert(strlen(error)<131);
} /* SimError */
/*---------------------------------------------------------------------------*/
static int SimFix(void *self, int iError, float fNew)
{
ASIMDriv *pDriv;
int iRet;
float fRand;
assert(self);
pDriv = (ASIMDriv *)self;
switch (pDriv->iStatus)
{
case ASIM_IDLE:
switch (pDriv->iFaultType)
{
case ASIM_POS_FAULT: return MOTOK;
case ASIM_NO_FAULT: return MOTOK;
case ASIM_HW_FAULT: return MOTFAIL;
case ASIM_STALL_FAULT: return MOTREDO;
default: return MOTFAIL; /* error: unknown fault type */
}
break;
case ASIM_BUSY: return MOTOK; break;
case ASIM_CRASH: return MOTFAIL; break;
case ASIM_FAULT:
SimHalt(self);
if(TH_HW_FAULT >= SimRandom())
{
pDriv->iStatus = ASIM_CRASH;
return MOTFAIL;
}
pDriv->iStatus = ASIM_IDLE;
pDriv->iFaultType = ASIM_NO_FAULT;
return MOTOK;
break;
default:
pDriv->iStatus = ASIM_CRASH;
pDriv->iFaultType = ASIM_HW_FAULT;
return MOTFAIL;
}
/* SICSLogWrite("Attempt fix for simulated motor",eHWError); */
} /* SimFix */
/*--------------------------------------------------------------------------*/
static int SimHalt(void *self)
{
int motCode = OKOK;
ASIMDriv *pDriv;
assert(self);
pDriv = (ASIMDriv *)self;
UpdatePosition(pDriv);
pDriv->iTime = 0;
pDriv->iDuration = 0;
pDriv->fTarget = pDriv->fPos;
pDriv->fDestination = pDriv->fPos;
switch (pDriv->iStatus)
{
case ASIM_BUSY: pDriv->iStatus = ASIM_IDLE;
case ASIM_IDLE: motCode = OKOK;
break;
default: motCode = HWFault;
break;
}
return motCode;
}
/*--------------------------------------------------------------------------*/
static int SimStat(void *self)
{
int motCode = HWIdle;
ASIMDriv *pDriv;
assert(self);
pDriv = (ASIMDriv *)self;
UpdatePosition(pDriv);
switch (pDriv->iStatus)
{
case ASIM_BUSY: motCode = HWBusy; break;
case ASIM_IDLE: motCode = HWIdle; break;
default: motCode = HWFault; break;
}
return motCode;
}
/*-----------------------------------------------------------------------*/
static int SimSetPar(void *self, SConnection *pCon, char *name, float newValue)
{
int iSuccess = 0;
ASIMDriv *pDriv = (ASIMDriv *) self;
assert(self);
assert(pCon);
if(strcmp(name,"hardupperlim") == 0)
{
pDriv->fUpper = newValue;
iSuccess = 1;
}
if(strcmp(name,"hardlowerlim") == 0)
{
pDriv->fLower = newValue;
iSuccess = 1;
}
if(strcmp(name,"speed") == 0)
{
pDriv->fSpeed = newValue;
iSuccess = 1;
}
return iSuccess;
}
/*-----------------------------------------------------------------------*/
static int SimGetPar(void *self, char *name, float *value)
{
int iSuccess = 0;
ASIMDriv *pDriv = (ASIMDriv *) self;
assert(self);
if (0==strcmp("hardupperlim",name))
{
*value = pDriv->fUpper;
iSuccess = 1;
}
if (0==strcmp("hardlowerlim",name))
{
*value = pDriv->fLower;
iSuccess=1;
}
return iSuccess;
}
/*-----------------------------------------------------------------------*/
static void SimListPar(void *self, char *motorName, SConnection *pCon)
{
ASIMDriv *pDriv = (ASIMDriv *) self;
char pBuffer[256];
assert(self);
assert(pCon);
sprintf(pBuffer,"%s.%s = %f",motorName,"hardupperlim",pDriv->fUpper);
SCWrite(pCon,pBuffer,eValue);
sprintf(pBuffer,"%s.%s = %f",motorName,"hardlowerlim",pDriv->fLower);
SCWrite(pCon,pBuffer,eValue);
}
/*---------------------------------------------------------------------------*/
static void SimKill(void *pData)
{
/*
the controller is owned by the controller object and will be
deleted when that object is removed
*/
return;
}
/*--------------------------------------------------------------------------*/
MotorDriver *CreateASIM(SConnection *pCon, int argc, char *argv[])
{
TokenList *pList = NULL;
TokenList *pCurrent;
ASIMDriv *pDriv = NULL;
time_t tD;
assert(pCon);
/* check number of arguments */
if(argc < 3)
{
SCWrite(pCon,"Insufficient numbers of arguments for ASIM Motor",eError);
return NULL;
}
/* split arguments */
pList = SplitArguments(argc, argv);
if(!pList)
{
SCWrite(pCon,"Error parsing arguments in ASIM Motor",eError);
return NULL;
}
/* allocate memory */
pDriv = (ASIMDriv *)malloc(sizeof(ASIMDriv));
if(!pDriv)
{
SCWrite(pCon,"Error allocating memory in ASIM Motor",eError);
DeleteTokenList(pList);
return NULL;
}
memset(pDriv,0,sizeof(ASIMDriv));
/* 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,"ERROR: Expect numerical 'lower limit' at argument 1 after Motor ASIM",eError);
free(pDriv);
DeleteTokenList(pList);
return NULL;
}
/* then, 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,"ERROR: Expect numerical 'upper limit' at argument 2 after Motor ASIM",eError);
free(pDriv);
DeleteTokenList(pList);
return NULL;
}
/* thirdly, 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,"ERROR: Expect numerical 'failure rate' at argument 3 after Motor ASIM",eError);
free(pDriv);
DeleteTokenList(pList);
return NULL;
}
/* calculate current position, initialise func pters */
pDriv->fPos = (pDriv->fUpper + pDriv->fLower)/2.0;
/* pDriv->name = strdup("SICS_ANSTO_MOTOR_ASIM"); */
pDriv->name = malloc((1+strlen("SICS_ANSTO_MOTOR_ASIM"))*sizeof(char));
strcpy(pDriv->name,"SICS_ANSTO_MOTOR_ASIM");
pDriv->GetPosition = SimGetPos;
pDriv->RunTo = SimRun;
pDriv->GetStatus = SimStat;
pDriv->GetError = SimError;
pDriv->TryAndFixIt = SimFix;
pDriv->Halt = SimHalt;
pDriv->SetDriverPar = SimSetPar;
pDriv->GetDriverPar = SimGetPar;
pDriv->ListDriverPar = SimListPar;
pDriv->KillPrivate = SimKill;
/* set default parameters */
pDriv->fSpeed = 0.01;
pDriv->iTime = time(&tD);
pDriv->iFaultType = ASIM_NO_FAULT;
pDriv->iDuration = 0;
pDriv->iRunningTime = 0;
pDriv->iLastPollTime = pDriv->iTime;
pDriv->fTarget = pDriv->fPos;
pDriv->fDestination = pDriv->fPos;
pDriv->iStatus = OKOK;
srand( (unsigned)time( NULL ) );
/* check for optional speed paramter */
pCurrent = pCurrent->pNext;
if(pCurrent)
{
if(pCurrent->Type == eFloat)
{
pDriv->fSpeed = pCurrent->fVal;
if(pDriv->fSpeed < 0.0) pDriv->fSpeed = 0.0 - pDriv->fSpeed;
}
}
DeleteTokenList(pList);
return (MotorDriver *)pDriv;
}

17
site_ansto/motor_asim.h Normal file
View File

@@ -0,0 +1,17 @@
/*--------------------------------------------------------------------------
* motor_asim.h
Header file for ANSTO Simulation Motor
Based on SINQ "modriv.h" for EL734 motor driver by Mark Koennecke 1996
Modifications Paul Hathaway April 2004
Copyright: see implementation file
---------------------------------------------------------------------------*/
#ifdef __cplusplus
extern "C" {
#endif
MotorDriver *CreateASIM(SConnection *pCon, int argc, char *argv[]);
#ifdef __cplusplus
}
#endif

802
site_ansto/motor_dmc2280.c Normal file
View File

@@ -0,0 +1,802 @@
/*------------------------------------------------------------------------
Implements a SICS motor object with a MotorDriver interface.
The control and communications functions are implemented in a separate layer
in instrument/dmc2280.tcl
Copyright: see file Copyright.txt
Ferdi Franceschini November 2005
-----------------------------------------------------------------------*/
#include <stdlib.h>
#include <math.h>
#include <float.h>
#include <assert.h>
#include <string.h>
#include <stdarg.h>
#include <fortify.h>
#include <sics.h>
#include <rs232controller.h>
#include <modriv.h>
#include <dynstring.h>
/*
#include "splint/splint_fortify.h"
#include "splint/splint_tclDecls.h"
#include "splint/splint_dynstring.h"
#include "splint/splint_SCinter.h"
*/
/*-----------------------------------------------------------------------
The motor driver structure. Please note that the first set of fields has
be identical with the fields of AbstractModriv in ../modriv.h
------------------------------------------------------------------------*/
typedef struct __MoDriv {
/* general motor driver interface
fields. _REQUIRED!
*/
float fUpper; /* upper limit */
float fLower; /* lower limit */
char *name;
int (*GetPosition)(void *self,float *fPos);
int (*RunTo)(void *self, float fNewVal);
int (*GetStatus)(void *self);
void (*GetError)(void *self, int *iCode, char *buffer, int iBufLen);
int (*TryAndFixIt)(void *self,int iError, float fNew);
int (*Halt)(void *self);
int (*GetDriverPar)(void *self, char *name,
float *value);
int (*SetDriverPar)(void *self,SConnection *pCon,
char *name, float newValue);
void (*ListDriverPar)(void *self, char *motorName,
SConnection *pCon);
void (*KillPrivate)(void *self);
/* DMC-2280 specific fields */
SConnection *pCon;
prs232 controller;
int iMotor;
int errorCode;
int oredMsr;
int lastValue;
int iConfig;
char units[256]; /* physical units for axis */
float speed; /* physical units per second */
float maxSpeed; /* physical units per second */
float accel; /* physical units per second^2 */
float maxAccel; /* physical units per second^2 */
float decel; /* physical units per second^2 */
float maxDecel; /* physical units per second^2 */
char axisLabel;
char lastCmd[1024];
float home; /* home position for axis, default=0 */
int motorHome; /* motor home position in steps */
int stepsPerX; /* steps per physical unit */
int abs_endcoder; /* Flag = 1 if there is an abs enc */
int absEncHome; /* Home position in counts for abs enc */
int cntsPerX; /* absolute encoder counts per physical unit */
} DMC2280Driv, *pDMC2280Driv;
/*------------------- error codes ----------------------------------*/
#define BADADR -1 // Unknown host/port?
#define BADBSY -2
#define BADCMD -3
#define BADPAR -4 // Does SICS already check parameter types?
#define BADUNKNOWN -5
#define BADSTP -6
#define BADEMERG -7
#define RVRSLIM -8
#define FWDLIM -9
#define RUNFAULT -10
#define POSFAULT -11
#define BADCUSHION -12
#define ERRORLIM -13
#define IMPOSSIBLE_LIM_SW -14
#define BGFAIL -15
/*--------------------------------------------------------------------*/
#define STATUSMOVING 128 /* Motor is moving */
#define STATUSERRORLIMIT 64 /* Number of errorss exceed limit */
#define STATUSOFF 32 /* Motor off */
#define STATUSFWDLIMIT 8 /* Forward limit switch active */
#define STATUSRVRSLIMIT 4 /* Reverse limit switch active */
#define INIT_STR_SIZE 256
#define STR_RESIZE_LENGTH 256
#define CMDLEN 1024
#define ERRLEN 256
#define BUFFLEN 512
#define FAILURE 0
#define SUCCESS 1
#define _REQUIRED 1
#define _OPTIONAL 0
#define HOME "home"
#define HARDLOWERLIM "hardlowerlim"
#define HARDUPPERLIM "hardupperlim"
#define UNITS "units"
#define SPEED "speed"
#define MAXSPEED "maxSpeed"
#define ACCEL "accel"
#define MAXACCEL "maxAccel"
#define DECEL "decel"
#define MAXDECEL "maxDecel"
static int DMC2280Receive(pDMC2280Driv self, /*@out@*/ char *reply);
/* Return motor speed in steps/sec */
static int motSpeed(pDMC2280Driv self, float speed) {
int motSpeed;
motSpeed = abs((int)(speed * self->stepsPerX + 0.5));
return motSpeed;
}
/* Return motor acceleration in steps/sec^2 */
static int motAccel(pDMC2280Driv self, float accel) {
int motAccel;
motAccel = abs((int)(accel * self->stepsPerX + 0.5));
return motAccel;
}
/* Return motor deceleration in steps/sec^2 */
static int motDecel(pDMC2280Driv self, float decel) {
int motDecel;
motDecel = abs((int)(decel * self->stepsPerX + 0.5));
return motDecel;
}
static int DMC2280ReadChar(pDMC2280Driv self, char *reply) {
int i, status, retries=20, dataLen=1;
for (i=0; i<retries; i++) {
status=readRS232(self->controller, reply, &dataLen);
switch (status) {
case 1:
return SUCCESS;
case TIMEOUT:
self->errorCode = status;
continue;
default:
self->errorCode = status;
return FAILURE;
}
}
return FAILURE;
}
/*---------------------------------------------------------------------*/
/* First character returned by controller is
'?' for an invalid command or
':' or space for a valid command */
static int DMC2280Send(pDMC2280Driv self, char *command) {
char cmdValid, pError[ERRLEN], reply[256];
char *GetEMsg = "TC 1";
int status;
strncpy(self->lastCmd, command, CMDLEN);
status = writeRS232(self->controller, command, strlen(command));
if (status != 1) {
self->errorCode = status;
return FAILURE;
}
if (FAILURE == (status = DMC2280ReadChar(self, &cmdValid))) {
self->errorCode = status;
return FAILURE;
} else {
switch (cmdValid) {
case ':':
case ' ':
return SUCCESS;
case '?':
status = writeRS232(self->controller, GetEMsg, strlen(GetEMsg));
if (status != 1) {
self->errorCode = status;
return FAILURE;
}
if (FAILURE == DMC2280Receive(self, reply))
return HWFault;
snprintf(pError, ERRLEN, "DMC2280ERROR: Bad command '%s'", command);
SCWrite(self->pCon, reply, eError);
self->errorCode = BADCMD;
return FAILURE;
default:
self->errorCode = BADUNKNOWN;
return FAILURE;
}
}
}
static int DMC2280Receive(pDMC2280Driv self, char *reply) {
int i, status, retries=20, dataLen=255;
for (i=0; i<retries; i++) {
status=readRS232TillTerm(self->controller, reply, &dataLen);
switch (status) {
case 1:
return dataLen;
case TIMEOUT:
self->errorCode = status;
continue;
/* TODO case INCOMPLETE: */
default:
self->errorCode = status;
return FAILURE;
}
}
return FAILURE;
}
/*---------------------------------------------------------------------*/
static int DMC2280GetPos(void *pData, float *fPos){
pDMC2280Driv self = NULL;
char reply[1024];
char cmd[CMDLEN];
float absEncPos, motorPos;
reply[0]='\0';
self = (pDMC2280Driv)pData;
assert(self != NULL);
if (1 == self->abs_endcoder) {
snprintf(cmd, CMDLEN, "TP%c", self->axisLabel);
if (FAILURE == DMC2280Send(self, cmd))
return HWFault;
if (FAILURE == DMC2280Receive(self, reply))
return HWFault;
absEncPos =(float)atof(reply);
*fPos = (absEncPos - self->absEncHome)/self->cntsPerX + self->home;
} else {
snprintf(cmd, ERRLEN, "TD%c", self->axisLabel);
if (FAILURE == DMC2280Send(self, cmd))
return HWFault;
if (FAILURE == DMC2280Receive(self, reply))
return HWFault;
motorPos =(float)atof(reply);
*fPos = (motorPos - self->motorHome)/self->stepsPerX + self->home;
}
return OKOK;
}
/*----------------------------------------------------------------------*/
static int DMC2280Run(void *pData,float fValue){
pDMC2280Driv self = NULL;
char axis;
char cmd[CMDLEN], SH[CMDLEN], BG[CMDLEN], absPosCmd[CMDLEN];
int absEncHome, stepsPerX, motorHome, cntsPerX, newAbsPosn;
float target;
self = (pDMC2280Driv)pData;
assert(self != NULL);
axis=self->axisLabel;
motorHome = self->motorHome;
stepsPerX=self->stepsPerX;
snprintf(SH, CMDLEN, "SH%c", axis);
snprintf(BG, CMDLEN, "BG%c", axis);
target = fValue - self->home;
newAbsPosn = (int)(target * stepsPerX + motorHome + 0.5);
snprintf(absPosCmd, CMDLEN, "PA%c=%d",axis, newAbsPosn);
if (1 == self->abs_endcoder) {
/* Ensure that the defined motor position matches actual position */
absEncHome = self->absEncHome;
cntsPerX = self->cntsPerX;
snprintf(cmd, CMDLEN, "DP%c=(_TP%c - %d)*(%d/%d) + %d",axis,axis,absEncHome,stepsPerX,cntsPerX,motorHome);
if (FAILURE == DMC2280Send(self, cmd))
return HWFault;
snprintf(cmd, CMDLEN, "%cQTARGET=%d", axis, (int) (target * cntsPerX + absEncHome + 0.5));
if (FAILURE == DMC2280Send(self, cmd))
return HWFault;
}
if (FAILURE == DMC2280Send(self, absPosCmd))
return HWFault;
if (FAILURE == DMC2280Send(self, SH))
return HWFault;
if (FAILURE == DMC2280Send(self, BG))
return HWFault;
return OKOK;
}
/*------------------------------------------------------------------------*/
static int DMC2280Status(void *pData){
pDMC2280Driv self = NULL;
char cmd[CMDLEN];
int switches;
char switchesAscii[10], reply[256];
int moving, fwd_limit_active, rvrs_limit_active, errorlimit;
int SERVO_LOOP_NOT_RUNNING = -1, servoLoopStatus;
int SHOULD_FIXPOS=1, should_fixpos;
self = (pDMC2280Driv)pData;
assert(self != NULL);
/* Get status of switches
* see TS (Tell Switches) in Galil manc2xx */
snprintf(cmd, CMDLEN, "TS%c", self->axisLabel);
if (FAILURE == DMC2280Send(self, cmd))
return HWFault;
if (FAILURE == DMC2280Receive(self, switchesAscii))
return HWFault;
sscanf(switchesAscii, "%d", &switches);
moving = (switches & STATUSMOVING)>0;
fwd_limit_active = !(switches & STATUSFWDLIMIT)>0;
rvrs_limit_active = !(switches & STATUSRVRSLIMIT)>0;
errorlimit = (switches & STATUSERRORLIMIT)>0;
if (fwd_limit_active && rvrs_limit_active) {
self->errorCode = IMPOSSIBLE_LIM_SW;
return HWFault;
}
if (moving) {
self->errorCode = BADBSY;
return HWBusy;
} else {
/* If motor stopped check limits and error status */
if (fwd_limit_active) {
self->errorCode = FWDLIM;
return HWFault;
} else if (rvrs_limit_active) {
self->errorCode = RVRSLIM;
return HWFault;
} else if (errorlimit) {
self->errorCode = ERRORLIM;
return HWFault;
}
if (self->abs_endcoder == 1) {
/* Make sure that the servo loop is closed by checking if
* the CLSLOOP thread is running on the controller.*/
if (FAILURE == DMC2280Send(self, "MG _XQ1"))
return HWFault;
if (FAILURE == DMC2280Receive(self, reply))
return HWFault;
sscanf(reply, "%d", &servoLoopStatus);
if (servoLoopStatus == SERVO_LOOP_NOT_RUNNING) {
/* Start subroutine on controller to close the servo loop */
if (FAILURE == DMC2280Send(self, "XQ#CLSLOOP"))
return HWFault;
}
snprintf(cmd, CMDLEN, "MG %cSHLDFIX", self->axisLabel);
if (FAILURE == DMC2280Send(self, cmd))
return HWFault;
if (FAILURE == DMC2280Receive(self, reply))
return HWFault;
sscanf(reply, "%d", &should_fixpos);
if (should_fixpos == SHOULD_FIXPOS) {
snprintf(cmd, CMDLEN, "%cFIXPOS=1", self->axisLabel);
if (FAILURE == DMC2280Send(self, cmd))
return HWFault;
self->errorCode=BADBSY;
return HWBusy;
}
}
return HWIdle;
}
}
/*----------------------------------------------------------------------*/
static void DMC2280Error(void *pData, int *iCode, char *error, int errLen){
pDMC2280Driv self = NULL;
self = (pDMC2280Driv)pData;
assert(self != NULL);
*iCode = self->errorCode;
switch(*iCode){
case BADADR:
strncpy(error,"Bad address",(size_t)errLen);
break;
case BADBSY:
strncpy(error,"Motor still busy",(size_t)errLen);
break;
case BADCMD:
snprintf(error, (size_t)errLen, "Bad command: '%s'", self->lastCmd);
break;
case BADPAR:
strncpy(error,"Bad parameter",(size_t)errLen);
break;
case BADUNKNOWN:
strncpy(error,"Unknown error condition",(size_t)errLen);
break;
case BADSTP:
strncpy(error,"Motor is stopped",(size_t)errLen);
break;
case BADEMERG:
strncpy(error,"Emergency stop is engaged",(size_t)errLen);
break;
case BGFAIL:
strncpy(error,"Begin not possible due to limit switch",(size_t)errLen);
break;
case RVRSLIM:
strncpy(error,"Crashed into reverse limit switch",(size_t)errLen);
break;
case FWDLIM:
strncpy(error,"Crashed into forward limit switch",(size_t)errLen);
break;
case RUNFAULT:
strncpy(error,"Run fault detected",(size_t)errLen);
break;
case POSFAULT:
strncpy(error,"Positioning fault detected",(size_t)errLen);
break;
case BADCUSHION:
strncpy(error,"Air cushion problem",(size_t)errLen);
break;
case ERRORLIM:
strncpy(error,"Axis error exceeds error limit",(size_t)errLen);
break;
case IMPOSSIBLE_LIM_SW:
strncpy(error,"Both limit switches seem active, maybe the polarity is set 'active low'. You should controller the controller with CN 1,-1,-1,0", (size_t)errLen);
break;
default:
/* FIXME What's the default */
break;
}
}
/*----------------------------------------------------------------------*/
static int DMC2280Fix(void *pData, int iCode,/*@unused@*/ float fValue){
pDMC2280Driv self = NULL;
self = (pDMC2280Driv)pData;
assert(self != NULL);
switch(iCode){
case BADADR:
case BADCMD:
//case TIMEOUT:
case BADPAR:
case BADBSY:
return MOTREDO;
case RUNFAULT:
case POSFAULT:
return MOTREDO;
case NOTCONNECTED:
initRS232(self->controller);
return MOTREDO;
}
return MOTFAIL;
}
/*----------------------------------------------------------------------*/
/* Emergency Halt
* Uses maximum deceleration */
static int DMC2280Halt(void *pData){
pDMC2280Driv self = NULL;
char cmd[CMDLEN];
self = (pDMC2280Driv)pData;
assert(self != NULL);
/* Set maximum deceleration to stop motor */
snprintf(cmd, CMDLEN, "DC%c", motDecel(self, self->maxDecel));
if (FAILURE == DMC2280Send(self, cmd))
return HWFault;
/* Stop motor */
snprintf(cmd, CMDLEN, "ST%c", self->axisLabel);
if (FAILURE == DMC2280Send(self, cmd))
return HWFault;
/* Restore deceleration */
snprintf(cmd, CMDLEN, "DC%c", motDecel(self, self->decel));
if (FAILURE == DMC2280Send(self, cmd))
return HWFault;
return 1;
}
/*--------------------------------------------------------------------*/
static int DMC2280GetPar(void *pData, char *name,
float *fValue){
pDMC2280Driv self = NULL;
self = (pDMC2280Driv)pData;
if(strcmp(name,HOME) == 0) {
*fValue = self->home;
return 1;
}
if(strcmp(name,HARDLOWERLIM) == 0) {
*fValue = self->fLower;
return 1;
}
if(strcmp(name,HARDUPPERLIM) == 0) {
*fValue = self->fUpper;
return 1;
}
if(strcmp(name,SPEED) == 0) {
*fValue = self->speed;
return 1;
}
if(strcmp(name,MAXSPEED) == 0) {
*fValue = self->maxSpeed;
return 1;
}
if(strcmp(name,ACCEL) == 0) {
*fValue = self->accel;
return 1;
}
if(strcmp(name,MAXACCEL) == 0) {
*fValue = self->maxAccel;
return 1;
}
if(strcmp(name,DECEL) == 0) {
*fValue = self->decel;
return 1;
}
if(strcmp(name,MAXDECEL) == 0) {
*fValue = self->maxDecel;
return 1;
}
return 0;
}
/*--------------------------------------------------------------------*/
static int DMC2280SetPar(void *pData, SConnection *pCon,
char *name, float newValue){
pDMC2280Driv self = NULL;
char pError[ERRLEN];
char cmd[CMDLEN];
self = (pDMC2280Driv)pData;
/* Set home */
if(strcmp(name,HOME) == 0) {
if ( (self->fLower - newValue) > FLT_EPSILON) {
snprintf(pError, ERRLEN,"ERROR: %s must be greater than or equal to %f", HOME, self->fLower);
SCWrite(pCon, pError, eError);
return 1;
}
if ( (newValue - self->fUpper) > FLT_EPSILON) {
snprintf(pError, ERRLEN,"ERROR: %s must be less than or equal to %f", HOME, self->fUpper);
SCWrite(pCon, pError, eError);
return 1;
}
self->home = newValue;
return 1;
}
/* Set upper limit, lower limit */
if(strcmp(name,HARDLOWERLIM) == 0) {
self->fLower = newValue;
return 1;
}
if(strcmp(name,HARDUPPERLIM) == 0) {
self->fUpper = newValue;
return 1;
}
/* Set speed */
if(strcmp(name,SPEED) == 0) {
if ((0.0 - newValue) > FLT_EPSILON) {
snprintf(pError, ERRLEN,"ERROR: %s must be greater than or equal to %f", SPEED, 0.0);
SCWrite(pCon, pError, eError);
return 1;
}
if ((newValue - self->maxSpeed ) > FLT_EPSILON) {
snprintf(pError, ERRLEN,"ERROR: %s must be less than or equal to %f", SPEED, self->maxSpeed);
SCWrite(pCon, pError, eError);
return 1;
}
self->speed = newValue;
snprintf(cmd,CMDLEN,"SP%c=%d", self->axisLabel, motSpeed(self, self->speed));
if (FAILURE == DMC2280Send(self, cmd))
return 0; /* FIXME should signal a HWFault */
return 1;
}
/* Set Acceleration */
if(strcmp(name,ACCEL) == 0) {
if ((0.0 - newValue) > FLT_EPSILON) {
snprintf(pError, ERRLEN,"ERROR: %s must be greater than or equal to %f", ACCEL, 0.0);
SCWrite(pCon, pError, eError);
return 1;
}
if ((newValue - self->maxAccel ) > FLT_EPSILON) {
snprintf(pError, ERRLEN,"ERROR: %s must be less than or equal to %f", ACCEL, self->maxAccel);
SCWrite(pCon, pError, eError);
return 1;
}
self->accel = newValue;
snprintf(cmd,CMDLEN,"AC%c=%d", self->axisLabel, motAccel(self, self->accel));
if (FAILURE == DMC2280Send(self, cmd))
return 0; /* FIXME should signal a HWFault */
return 1;
}
/* Set Deceleration */
if(strcmp(name,DECEL) == 0) {
if ((0.0 - newValue) > FLT_EPSILON) {
snprintf(pError, ERRLEN,"ERROR: %s must be greater than or equal to %f", DECEL, 0.0);
SCWrite(pCon, pError, eError);
return 1;
}
if ((newValue - self->maxDecel ) > FLT_EPSILON) {
snprintf(pError, ERRLEN,"ERROR: %s must be less than or equal to %f", DECEL, self->maxDecel);
SCWrite(pCon, pError, eError);
return 1;
}
self->decel = newValue;
snprintf(cmd,CMDLEN,"DC%c=%d", self->axisLabel, motDecel(self, self->decel));
if (FAILURE == DMC2280Send(self, cmd))
return 0; /* FIXME should signal a HWFault */
return 1;
}
return 0;
}
/*--------------------------------------------------------------------*/
static void DMC2280List(void *self, char *name, SConnection *pCon){
char buffer[BUFFLEN];
snprintf(buffer, BUFFLEN, "%s.axis = %c\n", name, ((pDMC2280Driv)self)->axisLabel);
SCWrite(pCon, buffer, eStatus);
snprintf(buffer, BUFFLEN, "%s.home = %f\n", name, ((pDMC2280Driv)self)->home);
SCWrite(pCon, buffer, eStatus);
snprintf(buffer, BUFFLEN, "%s.units = %s\n", name, ((pDMC2280Driv)self)->units);
SCWrite(pCon, buffer, eStatus);
snprintf(buffer, BUFFLEN, "%s.speed = %f\n", name, ((pDMC2280Driv)self)->speed);
SCWrite(pCon, buffer, eStatus);
snprintf(buffer, BUFFLEN, "%s.maxSpeed = %f\n", name, ((pDMC2280Driv)self)->maxSpeed);
SCWrite(pCon, buffer, eStatus);
snprintf(buffer, BUFFLEN, "%s.accel = %f\n", name, ((pDMC2280Driv)self)->accel);
SCWrite(pCon, buffer, eStatus);
snprintf(buffer, BUFFLEN, "%s.maxAccel = %f\n", name, ((pDMC2280Driv)self)->maxAccel);
SCWrite(pCon, buffer, eStatus);
snprintf(buffer, BUFFLEN, "%s.decel = %f\n", name, ((pDMC2280Driv)self)->decel);
SCWrite(pCon, buffer, eStatus);
snprintf(buffer, BUFFLEN, "%s.maxDecel = %f\n", name, ((pDMC2280Driv)self)->maxDecel);
SCWrite(pCon, buffer, eStatus);
return;
}
/*---------------------------------------------------------------------*/
static void KillDMC2280(void *pData){
pDMC2280Driv self = NULL;
self = (pDMC2280Driv)pData;
assert(self != NULL);
free(self->name);
/*@-temptrans@*/ free(self); /*@+temptrans@*/
return;
}
static prs232 DMC2280Connect(SConnection *pCon, char *buffer, int port) {
prs232 controller=NULL;
char pError[ERRLEN];
int usecTimeout = 50000; /* 50msec timeout */
controller=createRS232(buffer,port);
if (controller==NULL) {
snprintf(pError, ERRLEN,
"ERROR: failed to create controller for %s at port %d",
controller->pHost, controller->iPort);
SCWrite(pCon,pError,eError);
return NULL;
}
if ( initRS232(controller) != 1) {
snprintf(pError, ERRLEN,
"ERROR: failed to connect to %s at port %d",
controller->pHost, controller->iPort);
SCWrite(pCon,pError,eError);
return NULL;
}
setRS232ReplyTerminator(controller,"&\r\n:");
setRS232SendTerminator(controller,"\r\n");
setRS232Timeout(controller, usecTimeout);
return controller;
}
/* Get configuration parameter */
static char *getParam(SConnection *pCon, Tcl_Interp *pTcl, char *params, char *parName, int mustHave ) {
char *pPtr=NULL, pError[ERRLEN];
pPtr = Tcl_GetVar2(pTcl,params,parName,TCL_GLOBAL_ONLY);
if((mustHave == _REQUIRED) && !pPtr){
snprintf(pError, ERRLEN,"ERROR: No '%s' parameter given for dmc2280 motor", parName);
SCWrite(pCon,pError, eError);
}
return pPtr;
}
/*------------------------------------------------------------------*/
/*@null@*/ MotorDriver *CreateDMC2280(SConnection *pCon, char *motor, char *params){
/*@keep@*/ pDMC2280Driv pNew = NULL;
char *pPtr = NULL;
char buffer[132];
char pError[ERRLEN];
char cmd[CMDLEN];
int port;
Tcl_Interp *interp;
buffer[0]='\0';
interp = InterpGetTcl(pServ->pSics);
/*
allocate and initialize data structure
*/
pNew = (pDMC2280Driv)malloc(sizeof(DMC2280Driv));
if(!pNew){
(void) SCWrite(pCon,"ERROR: no memory to allocate motor driver",
eError);
return NULL;
}
/* Get hostname and port from the list of named parameters */
if ((pPtr=getParam(pCon, interp, params,"port",1)) == NULL) return NULL;
sscanf(pPtr,"%d",&port);
if ((pPtr=getParam(pCon, interp, params,"host",1)) == NULL) return NULL;
strncpy(buffer,pPtr, 131);
/* Connect to the controller */
memset(pNew,0,sizeof(DMC2280Driv));
pNew->controller = DMC2280Connect(pCon, buffer,port);
if( pNew->controller == NULL ) {
snprintf(pError, ERRLEN, "\tError occurred when creating DMC2280 motor '%s'", motor);
SCWrite(pCon,pError,eError);
return NULL;
}
/*FIXME Tell splint that there's no memory leak because pointers are being initialised here */
/*@-mustfreeonly@*/
pNew->name = (char *)malloc(sizeof(char)*(strlen(motor)+1));
if (pNew->name == NULL) {
(void) SCWrite(pCon,"ERROR: no memory to allocate motor driver",
eError);
free(pNew);
return NULL;
}
strcpy(pNew->name, motor);
pNew->pCon = pCon;
pNew->home = 0.0;
pNew->fLower = 0.0;//(float)atof(argv[2]);
pNew->fUpper = 100.0;//(float)atof(argv[3]);
pNew->GetPosition = DMC2280GetPos;
pNew->RunTo = DMC2280Run;
pNew->GetStatus = DMC2280Status;
pNew->GetError = DMC2280Error;
pNew->TryAndFixIt = DMC2280Fix;
pNew->Halt = DMC2280Halt;
pNew->GetDriverPar = DMC2280GetPar;
pNew->SetDriverPar = DMC2280SetPar;
pNew->ListDriverPar = DMC2280List;
pNew->KillPrivate = KillDMC2280;
if ((pPtr=getParam(pCon, interp, params,UNITS,_REQUIRED)) == NULL)
return NULL;
sscanf(pPtr,"%s",pNew->units);
if ((pPtr=getParam(pCon, interp, params,MAXSPEED,_REQUIRED)) == NULL)
return NULL;
sscanf(pPtr,"%f",&(pNew->speed));
pNew->maxSpeed = pNew->speed;
if ((pPtr=getParam(pCon, interp, params,MAXACCEL,_REQUIRED)) == NULL)
return NULL;
sscanf(pPtr,"%f",&(pNew->accel));
pNew->maxAccel = pNew->accel;
if ((pPtr=getParam(pCon, interp, params,MAXDECEL,_REQUIRED)) == NULL)
return NULL;
sscanf(pPtr,"%f",&(pNew->decel));
pNew->maxDecel = pNew->decel;
if ((pPtr=getParam(pCon, interp, params,"axis",_REQUIRED)) == NULL)
return NULL;
sscanf(pPtr,"%c",&(pNew->axisLabel));
if ((pPtr=getParam(pCon, interp, params,"stepsPerX",_REQUIRED)) == NULL)
return NULL;
sscanf(pPtr,"%d",&(pNew->stepsPerX));
if ((pPtr=getParam(pCon, interp, params,"motorHome",_OPTIONAL)) == NULL)
pNew->motorHome=0;
else
sscanf(pPtr,"%d",&(pNew->motorHome));
if ((pPtr=getParam(pCon, interp, params,"absEnc",_OPTIONAL)) == NULL)
pNew->abs_endcoder=0;
else {
sscanf(pPtr,"%d",&(pNew->abs_endcoder));
if ((pPtr=getParam(pCon, interp, params,"absEncHome",_REQUIRED)) == NULL)
pNew->absEncHome=0;
else
sscanf(pPtr,"%d",&(pNew->absEncHome));
if ((pPtr=getParam(pCon, interp, params,"cntsPerX",_REQUIRED)) == NULL)
pNew->cntsPerX=1;
else
sscanf(pPtr,"%d",&(pNew->cntsPerX));
}
/*@+mustfreeonly@*/
/* Set speed */
snprintf(cmd,CMDLEN,"SP%c=%d", pNew->axisLabel, motSpeed(pNew, pNew->speed));
if (FAILURE == DMC2280Send(pNew, cmd))
exit(EXIT_FAILURE);
/* Set acceleration */
snprintf(cmd,CMDLEN,"AC%c=%d", pNew->axisLabel, motAccel(pNew, pNew->accel));
if (FAILURE == DMC2280Send(pNew, cmd))
exit(EXIT_FAILURE);
/* Set deceleration */
snprintf(cmd,CMDLEN,"DC%c=%d", pNew->axisLabel, motDecel(pNew, pNew->decel));
if (FAILURE == DMC2280Send(pNew, cmd))
exit(EXIT_FAILURE);
/* TODO Initialise current position and target to get a sensible initial list output */
return (MotorDriver *)pNew;
}

View File

@@ -0,0 +1,17 @@
/*--------------------------------------------------------------------------
* dmc2280.h
The Galil motion controller driver include file
Nick Hauser, March 2004
copyright: see implementation file.
---------------------------------------------------------------------------*/
#ifdef __cplusplus
extern "C" {
#endif
MotorDriver *CreateDMC2280(SConnection *pCon, int argc, char *argv[]);
#ifdef __cplusplus
}
#endif

24
site_ansto/motor_driver.h Normal file
View File

@@ -0,0 +1,24 @@
/*--------------------------------------------------------------------------
----------------------------------------------------------------------------*/
#define MOTREDO -1
#define MOTFAIL 0
#define MOTOK 1
typedef struct __AbstractMoDriv {
/* general motor driver interface fields. REQUIRED! */
float fUpper; /* upper limit */
float fLower; /* lower limit */
char *name;
int (*GetPosition)(void *self, float *fPos);
int (*RunTo)(void *self,float fNewVal);
int (*GetStatus)(void *self);
void (*GetError)(void *self, int *iCode, char *buffer, int iBufLen);
int (*TryAndFixIt)(void *self, int iError,float fNew);
int (*Halt)(void *self);
int (*GetDriverPar)(void *self, char *name, float *value);
int (*SetDriverPar)(void *self,SConnection *pCon, char *name,
float newValue);
void (*ListDriverPar)(void *self, char *motorName, SConnection *pCon);
void (*KillPrivate)(void *self);
} MotorDriver;

403
site_ansto/refl2t.c Normal file
View File

@@ -0,0 +1,403 @@
/*---------------------------------------------------------------------------
REFL2T.c
Paul Hathaway, Nick Hauser, Mark Koennecke, February 2004
---------------------------------------------------------------------------*/
#include <stdlib.h>
#include <assert.h>
#include <math.h>
#include "fortify.h"
#include <tcl.h>
#include "sics.h"
#include "motor.h"
#include "obpar.h"
#define DEBUG 1
#define MAXMOT 3
#define MAXPAR 13
#define PI 3.14157
#include "refl2t.h"
/* detector height movement */
#define MOTCOZ 0
/* detector movement along main axis */
#define MOTCOY 1
/* whole sample table height movement */
#define MOTSOZ 2
/*======================================================================
The core of it all: The calculation of the settings for the various
motors.
========================================================================*/
static int CalculateREFL(pRefl2T self, SConnection *pCon, float fNew)
{
float fDetPos, HeightOffset, DetLength;
int iRet;
/* assume: solid sample, horizontal beam, surface at height zero */
/* read vals of motor coy */
iRet = MotorGetSoftPosition(self->aEngine[MOTCOY],pCon,&fDetPos);
if(iRet != 1)
{
return iRet;
}
HeightOffset = ObVal(self->aParameter,PARDHO);
DetLength = ObVal(self->aParameter,PARDDD) + fDetPos;
/* calculate det height above beam axis */
/* add detector offset height */
fNew = DetLength * tan((double)(fNew * PI / 180.0)) + HeightOffset ;
self->fTarget = fNew;
return 1;
/* Replacement code using MotEntry structure
self->toStart[MOTCOZ].pMot = self->aEngine[MOTCOZ];
strcpy(self->toStart[MOTCOZ].pName,self->aEngine[MOTCOZ]->name);
self->toStart[MOTCOZ].fTarget = DetLength * tan((double)(fNew * PI / 180.0)) + HeightOffset;
*/
}
/*========================================================================
Definition of interface functions.
=========================================================================*/
static long R2TSetValue(void *pData, SConnection *pCon, float fNew)
{
int i, iRet;
pIDrivable pDriv = NULL;
pRefl2T self = (pRefl2T) pData;
assert(self);
/* calculation */
iRet = CalculateREFL(self,pCon,fNew);
if(iRet != 1)
{
return iRet;
}
/* start them all */
/* for(i = 0; i < self->iStart; i++)
{*/
pDriv = self->aEngine[MOTCOZ].pMot->pDescriptor->GetInterface(
self->aEngine[MOTCOZ].pMot,DRIVEID); /* DRIVEID ??? */
if(pDriv != NULL)
{
iRet = pDriv->SetValue(self->tEngine[MOTCOZ].pMot,pCon,
self->fTarget); /* works for one motor MOTCOZ */
if(iRet != OKOK)
{
return iRet;
}
}
/* } */
return OKOK;
}
/*-------------------------------------------------------------------------*/
static int R2THalt(void *pData)
{
int i, iRet;
pIDrivable pDriv = NULL;
pRefl2T self = (pRefl2T) pData;
assert(self);
/* stop them all */
/*for(i = 0; i < self->iStart; i++)
{*/
pDriv = self->aEngine[MOTCOZ].pMot->pDescriptor->GetInterface(
self->aEngine[MOTCOZ].pMot,DRIVEID);
if(pDriv != NULL)
{
iRet = pDriv->Halt(self->aEngine[MOTCOZ].pMot);
}
/* } */
return OKOK;
}
/*-----------------------------------------------------------------------*/
static int R2TCheck(void *pData, float fNew, char *error, int iErrLen)
{
int i, iRet;
pIDrivable pDriv = NULL;
pRefl2T self = (pRefl2T) pData;
SConnection *pDumCon = NULL;
/* Define code for this function */
assert(self);
pDumCon = SCCreateDummyConnection(pServ->pSics);
assert(pDumCon);
/* calculation */
iRet = CalculateREFL(self,pDumCon,fNew);
SCDeleteConnection(pDumCon);
if(iRet != 1)
{
return iRet;
}
/* check them all */
/* for(i = 0; i < self->iStart; i++)
{*/
pDriv = self->aEngine[MOTCOZ].pMot->pDescriptor->GetInterface(
self->aEngine[MOTCOZ].pMot,DRIVEID);
if(pDriv != NULL)
{
iRet = pDriv->CheckLimits(self->aEngine[MOTCOZ].pMot,
self->aEngine[MOTCOZ].fTarget,
error,iErrLen);
if(iRet != 1)
{
return iRet;
}
}
/* } */
return 1;
}
static float R2TGetValue(void *pData, SConnection *pCon)
{
pRefl2T self = (pRefl2T) pData;
assert(self);
return fResult;
}
static void *R2TGetInterface(void *pData, int iID)
{
pRefl2T self = (pRefl2T) pData;
assert(self);
if(iID == DRIVEID)
{
return self->pDriv;
}
return NULL;
}
static void Refl2TKill(void *pData)
{
pRefl2T self = (pRefl2T) pData;
if(self == NULL)
return;
if(self->pDes)
DeleteDescriptor(self->pDes);
if(self->pDriv)
free(self->pDriv);
if(self->aParameter)
ObParDelete(self->aParameter);
free(self);
}
/*--------------------------------------------------------------------------
Initialization: All is done from the Factory function. This takes an Tcl
array as parameter which is supposed to hold the names of all motors.
This must fail if one of the motors cannot be accessed.
--------------------------------------------------------------------------*/
int Refl2TFactory(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[])
{
pRefl2T pNew;
int i, iRet;
char pBueffel[512];
char *pMot = NULL;
if(argc < 1)
{
SCWrite(pCon,
"ERROR: Insufficient number of arguments to Refl2tFactory",
eError);
return 0;
}
/* allocate space ..............*/
pNew = (pRefl2T)malloc(sizeof(Refl2T));
if(!pNew)
{
SCWrite(pCon,"ERROR: out of memory in Refl2TFactory",eError);
return 0;
}
memset(pNew,0,sizeof(Refl2T));
pNew->pDes = CreateDescriptor("Refl2T");
pNew->aParameter = ObParCreate(MAXPAR);
pNew->pDriv = CreateDrivableInterface();
if( (!pNew->pDes) || (!pNew->aParameter) || (!pNew->pDriv) )
{
SCWrite(pCon,"ERROR: out of memory in Refl2TFactory",eError);
Refl2TKill(pNew);
return 0;
}
/* find the motors*/
pMot = Tcl_GetVar2(pSics->pTcl,argv[2],"coz",TCL_GLOBAL_ONLY);
if(!pMot)
{
SCWrite(pCon,"ERROR: no value for coz motr found",eError);
Refl2TKill(pNew);
return 0;
}
pNew->aMot[MOTCOZ] = FindMotor(pSics,pMot);
if(!pNew->aEngine[MOTCOZ])
{
sprintf(pBueffel,"ERROR: motor %s NOT found!", pMot);
SCWrite(pCon,pBueffel,eError);
Refl2TKill(pNew);
return 0;
}
pMot = Tcl_GetVar2(pSics->pTcl,argv[2],"coy",TCL_GLOBAL_ONLY);
if(!pMot)
{
SCWrite(pCon,"ERROR: no value for coy motor found",eError);
Refl2TKill(pNew);
return 0;
}
pNew->aEngine[MOTCOY] = FindMotor(pSics,pMot);
if(!pNew->aEngine[MOTCOY])
{
sprintf(pBueffel,"ERROR: motor %s NOT found!", pMot);
SCWrite(pCon,pBueffel,eError);
Refl2TKill(pNew);
return 0;
}
pMot = Tcl_GetVar2(pSics->pTcl,argv[2],"soz",TCL_GLOBAL_ONLY);
if(!pMot)
{
SCWrite(pCon,"ERROR: no value for coz motor found",eError);
Refl2TKill(pNew);
return 0;
}
pNew->aEngine[MOTSOZ] = FindMotor(pSics,pMot);
if(!pNew->aEngine[MOTSOZ])
{
sprintf(pBueffel,"ERROR: motor %s NOT found!", pMot);
SCWrite(pCon,pBueffel,eError);
Refl2TKill(pNew);
return 0;
}
/* initialize parameters */
ObParInit(pNew->aParameter,PARDDD,"detectord",1400.,usMugger);
ObParInit(pNew->aParameter,PARDHO,"heightoffset",50.,usMugger);
ObParInit(pNew->aParameter,PARDSO,"stageoffset",50.,usMugger);
/* initialize interfaces */
pNew->pDes->GetInterface = R2TGetInterface;
pNew->pDes->SaveStatus = R2TSave;
pNew->pDriv->Halt = R2THalt;
pNew->pDriv->CheckLimits = R2TCheck;
pNew->pDriv->SetValue = R2TSetValue;
pNew->pDriv->CheckStatus = R2TStatus;
pNew->pDriv->GetValue = R2TGetValue;
/* install commands */
iRet = AddCommand(pSics,argv[1],
Refl2TAction,Refl2TKill,pNew);
if(!iRet)
{
sprintf(pBueffel,"ERROR: duplicate command %s NOT created",
argv[1]);
SCWrite(pCon,pBueffel,eError);
Refl2TKill(pNew);
return 0;
}
return 1;
}
/*----------------------------------------------------------------------*/
int Refl2TAction(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[])
{
pRefl2T self = (pRefl2T)pData;
char pBueffel[256];
float fVal;
double dVal;
ObPar *pPar = NULL;
int iRet;
assert(self);
if(argc > 1)
{
strtolower(argv[1]);
/* deal with list */
if(strcmp(argv[1],"list") == 0)
{
R2TList(self,pCon,argv[0]);
return 1;
}
/* otherwise it should be a parameter command */
if(argc >= 3)
{
iRet = Tcl_GetDouble(pSics->pTcl,argv[2],&dVal);
if(iRet != TCL_OK)
{
sprintf(pBueffel,"ERROR: failed to convert %s to number",
argv[2]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
iRet = ObParSet(self->aParameter,argv[0],argv[1],(float)dVal,pCon);
if(iRet)
{
SCSendOK(pCon);
}
return iRet;
}
else /* argc = 2 */
{
pPar = ObParFind(self->aParameter,argv[1]);
if(!pPar)
{
sprintf(pBueffel,"ERROR: parameter %s NOT found",argv[1]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
sprintf(pBueffel,"%s.%s = %f",argv[0],pPar->name, pPar->fVal);
SCWrite(pCon,pBueffel,eValue);
return 1;
}
}
else
{
fVal = self->pDriv->GetValue(self,pCon);
sprintf(pBueffel," %s = %f", argv[0], fVal);
SCWrite(pCon,pBueffel,eValue);
return 1;
}
}
static void R2TList(pRefl2T self, SConnection *pCon, char *name)
{
char pBueffel[132];
Tcl_DString tString;
assert(pCon);
assert(self);
Tcl_DStringInit(&tString);
sprintf(pBueffel,
"%s.detectord %f \n", name, ObVal(self->aParameter,PARDDD));
Tcl_DStringInit(&tString);
sprintf(pBueffel,
"%s.heightoffset %f \n", name, ObVal(self->aParameter,PARDHO));
Tcl_DStringInit(&tString);
sprintf(pBueffel,
"%s.sampleoffset %f \n", name, ObVal(self->aParameter,PARDSO));
}

49
site_ansto/refl2t.h Normal file
View File

@@ -0,0 +1,49 @@
/***********************************************************
* Simple virtual 2 theta driver for the RRR Reflectometer *
* *
* Paul Hathaway, Nick Hauser, Mark Koennecke. 4 Feb 2004. *
************************************************************/
#define MAXMOT = 3;
/* aMot is the array of motors that includes the
1. sample stage height motor
2. detector x motor
3. detector z motor
*/
typedef struct __REFL2T {
pObjectDescriptor pDes;
pIDrivable pDriv;
pMotor aEngine[MAXMOT];
/* MotEntry toStart[]; */
ObPar *aParameter;
float fTarget;
}Refl2T;
#ifndef REFL2T
#define REFL2T
typedef struct __REFL2T *pRefl2T;
int Refl2TFactory(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[]);
int Refl2TAction(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[]);
#endif
/* distance sample to detector */
#define PARDDD = 0;
/* distance offset for height of detector */
#define PARDHO = 1;
/* distance offset for sample height */
#define PARDSO = 2;
typedef struct {
pMotor pMot;
char pName[80];
float fTarget;
int iLast;
}MotEntry, *pMotEntry;

238
site_ansto/site_ansto.c Normal file
View File

@@ -0,0 +1,238 @@
/*------------------------------------------------------------------------
File: anstoSite.c
This is the site specific interface to SICS for ANSTO. This file implements
the interface defined in ../site.h
Copyright: see file Copyright.txt
Template: Mark Koennecke, June 2003
Nick Hauser, Paul Hathaway, May 2004
-----------------------------------------------------------------------*/
#include <stdlib.h>
#include <assert.h>
#include <fortify.h>
#include <sics.h>
#include <motor.h>
#include <tcl.h>
#include <site.h>
#include <SCinter.h>
/* site-specific driver header files */
#include "motor_asim.h"
#include "itc4.h"
/* Added code for new LH45 and Lakeshore 340 drivers */
#include "lh45.h"
#include "lakeshore340.h"
/*
from tcpdornier.c
*/
extern int VelSelTcpFactory(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]);
extern pCodri MakeTcpDoChoDriver(char *tclArray, SConnection *pCon);
void SiteInit(void) {
#define INIT(F) { void F(void); F(); }
/* insert here initialization routines ... */
}
static pSite /*@null@*/ siteANSTO = NULL;
/*----------------------------------------------------------------------*/
static void AddCommands(SicsInterp *pInter)
{
// int iRet;
// SConnection *pDummyConn;
(void) AddCommand(pInter,"MakeTCPSelector",VelSelTcpFactory,NULL,NULL);
/*
* Initialisation: Force execution here or use config script
*/
// pDummyConn = SCCreateDummyConnection(pInter);
// iRet = InterpExecute(pInter,pDummyConn,"config outcode warning");
// iRet = InterpExecute(pInter,pDummyConn,"InstallSinfox");
// iRet = InterpExecute(pInter,pDummyConn,"InstallProtocolHandler");
// SCDeleteConnection(pDummyConn);
}
/*---------------------------------------------------------------------*/
static void RemoveCommands(SicsInterp *pSics){
// RemoveCommand(pInter,"InstallProtocolHandler"0);
// RemoveCommand(pInter,"InstallSinfox");
}
/*-------------------------------------------------------------------*/
/*@null@*/ static pMotor CreateMotorAnsto(SConnection *pCon, int argc, char *argv[])
{
MotorDriver *pDriver = NULL;
pMotor pNew = NULL;
Tcl_Interp *pTcl = NULL;
char pBueffel[132];
/* create the motor */
strtolower(argv[1]);
if(strcmp(argv[1],"dmc2280") == 0) {
pDriver = (MotorDriver *)CreateDMC2280(pCon,argv[0],argv[2]);
if(!pDriver){
return NULL;
}
pNew = MotorInit("DMC2280",argv[0],pDriver);
if(!pNew) {
sprintf(pBueffel,"ERROR:SITE: Failure to create motor %s",argv[1]);
SCWrite(pCon,pBueffel,eError);
return NULL;
}
}
if(strcmp(argv[1],"asim") == 0) {
pDriver = (MotorDriver *)CreateASIM(pCon,argc-2,&argv[2]);
if(!pDriver){
return NULL;
}
pNew = MotorInit("ASIM",argv[0],pDriver);
if(!pNew) {
sprintf(pBueffel,"ERROR:SITE: Failure to create motor %s",argv[1]);
SCWrite(pCon,pBueffel,eError);
return NULL;
}
}
return pNew;
}
/*extern pCounterDriver CreateCtrNitio10(SConnection *pCon,char *name,int argc,char *argv[]); */
/*-------------------------------------------------------------------*/
static pCounterDriver CreateCounterDriverAnsto(SConnection *pCon,
int argc,
char *argv[]){
pCounterDriver pNew = NULL;
if(strcmp(argv[2],"nitio10") == 0){
if(argc < 4){
SCWrite(pCon,
"ERROR:SITE: Insufficient arguments for NITIO10 counter",
eError);
return NULL;
}
/* pNew = CreateCtrNitio10(pCon,argv[1],argc-3,&argv[3]);*/
}
return pNew;
}
/*-------------------------------------------------------------------*/
static HistDriver *CreateHistMem(char *name, pStringDict pOptions){
HistDriver *pNew = NULL;
if(strcmp(name,"anstohm") == 0){
//#ifdef __cplusplus
printf("try to CreateAnstoHM() ...\n");
// pNew = CreateAnstoHM(pOptions);
//#endif /* __cplusplus */
}
if(strcmp(name,"hm_mrpd") == 0){
printf("try to Create HM for MRPD ...\n");
// pNew = CreateHmMrpd(pOptions);
}
if(strcmp(name,"hm_asim") == 0){
// pNew = CreateHmAsim(pOptions);
}
return pNew;
}
/*-------------------------------------------------------------------*/
static pVelSelDriv CreateVelSelDriv(char *name, char *array,
Tcl_Interp *pTcl){
pVelSelDriv pNew = NULL;
return pNew;
}
/*-------------------------------------------------------------------*/
static pCodri CreateController(SConnection *pCon,int argc, char *argv[]){
pCodri pNew = NULL;
if(strcmp(argv[0],"tcpdocho") == 0){
if(argc < 2){
SCWrite(pCon,"ERROR: insufficient number of arguments for creating TcpDoCho",
eError);
return NULL;
}
return MakeTcpDoChoDriver(argv[1], pCon);
}
return pNew;
}
/*------------------------------------------------------------------*/
static pEVControl InstallEnvironmentController(SicsInterp *pSics,
SConnection *pCon,
int argc, char *argv[]){
int status;
pEVControl pNew = NULL;
pEVDriver pDriv = NULL;
strtolower(argv[3]);
/* Added code for new LH45 driver */
if(strcmp(argv[3],"lh45") == 0) {
pDriv = CreateLH45Driver(argc-4,&argv[4]);
if(pDriv){
pNew = CreateEVController(pDriv,argv[2],&status);
if(pNew != NULL){
AddCommand(pSics,argv[2],LH45Wrapper,DeleteEVController,
pNew);
}
}
}
/* Added code for new Lakeshore 340 driver */
if(strcmp(argv[3],"lakeshore340") == 0) {
pDriv = CreateLAKESHORE340Driver(argc-4,&argv[4]);
if(pDriv){
pNew = CreateEVController(pDriv,argv[2],&status);
if(pNew != NULL){
AddCommand(pSics,argv[2],LAKESHORE340Wrapper,DeleteEVController,
pNew);
}
}
}
return pNew;
}
/*-----------------------------------------------------------------*/
static int ConfigureScan(pScanData self, char *option){
if(!self) {
return 0;
}
return 0;
}
/*--------------------------------------------------------------------*/
static void KillSite(void *site){
free(site);
siteANSTO = NULL;
}
/*---------------------------------------------------------------------
The scheme here goes along the lines of the singleton design pattern
---------------------------------------------------------------------*/
pSite getSite(void)
{
if(siteANSTO == NULL)
{
siteANSTO = (pSite)malloc(sizeof(Site));
/*
we cannot go on if we do not even have enough memory to allocate
the site data structure
*/
assert(siteANSTO);
/*
initializing function pointers
*/
siteANSTO->AddSiteCommands = AddCommands;
siteANSTO->RemoveSiteCommands = RemoveCommands;
siteANSTO->CreateMotor = CreateMotorAnsto;
siteANSTO->CreateCounterDriver = CreateCounterDriverAnsto;
siteANSTO->CreateHistogramMemoryDriver = CreateHistMem;
siteANSTO->CreateVelocitySelector = CreateVelSelDriv;
siteANSTO->CreateControllerDriver = CreateController;
siteANSTO->InstallEnvironmentController = InstallEnvironmentController;
siteANSTO->ConfigureScan = ConfigureScan;
siteANSTO->KillSite = KillSite;
}
return siteANSTO;
}

131
site_ansto/site_dummy.c Normal file
View File

@@ -0,0 +1,131 @@
/*------------------------------------------------------------------------
D U M M Y
This is an empty site interface for SICS. Can be used as a starting
point for own site specific stuff.
copyright: see file COPYRIGHT
Mark Koennecke, June 2003
-----------------------------------------------------------------------*/
#include <stdlib.h>
#include <assert.h>
#include <fortify.h>
#include <sics.h>
#include <motor.h>
#include <tcl.h>
#include <site.h>
#include "anstohm.h"
#include "dmc2143.h"
static pSite siteANSTO = NULL;
/*----------------------------------------------------------------------*/
static void AddCommands(SicsInterp *pInter){
//AddCommand(pInter,"MakeRefl2T",Refl2TFactory,NULL,NULL);
}
/*---------------------------------------------------------------------*/
static void RemoveCommands(SicsInterp *pSics){
//RemoveCommand(pInter,"MakeRefl2T");
}
/*-------------------------------------------------------------------*/
static pMotor CreateMotor(SConnection *pCon, int argc, char *argv[]){
MotorDriver *pDriver = NULL;
pMotor pNew = NULL;
Tcl_Interp *pTcl = NULL;
char pBueffel[132];
/* create the motor */
strtolower(argv[1]);
if(strcmp(argv[1],"dmc2143") == 0){
pDriver = (MotorDriver *)CreateDMC2143(pCon,argc-2,&argv[2]);
if(!pDriver){
return NULL;
}
pNew = MotorInit("DMC2143",argv[0],pDriver);
if(!pNew){
sprintf(pBueffel,"Failure to create motor %s",argv[1]);
SCWrite(pCon,pBueffel,eError);
return NULL;
}
}
return pNew;
}
/*-------------------------------------------------------------------*/
static pCounterDriver CreateAnstoCounterDriver(SConnection *pCon,
int argc,
char *argv[]){
pCounterDriver pNew = NULL;
return pNew;
}
/*-------------------------------------------------------------------*/
static HistDriver *CreateHistMem(char *name, pStringDict pOptions){
HistDriver *pNew = NULL;
if(strcmp(name,"anstohm") == 0){
printf("try to CreateAnstoHM() ...\n");
#ifdef __cplusplus
pNew = CreateAnstoHM(pOptions);
#endif /* __cplusplus */
}
return pNew;
}
/*-------------------------------------------------------------------*/
static pVelSelDriv CreateVelSelDriv(char *name, char *array,
Tcl_Interp *pTcl){
pVelSelDriv pNew = NULL;
return pNew;
}
/*-------------------------------------------------------------------*/
static pCodri CreateController(SConnection *pCon,int argc, char *argv[]){
pCodri pNew = NULL;
return pNew;
}
/*------------------------------------------------------------------*/
static pEVControl InstallEnvironmentController(SicsInterp *pSics,
SConnection *pCon,
int argc, char *argv[]){
pEVControl pNew = NULL;
pEVDriver pDriv = NULL;
return pNew;
}
/*-----------------------------------------------------------------*/
static int ConfigureScan(pScanData self, char *option){
return 0;
}
/*--------------------------------------------------------------------*/
static void KillSite(void *site){
free(site);
siteANSTO = NULL;
}
/*---------------------------------------------------------------------
The scheme here goes along the lines of the singleton design pattern
---------------------------------------------------------------------*/
pSite getSite(void){
if(siteANSTO == NULL){
siteANSTO = (pSite)malloc(sizeof(Site));
/*
we cannot go on if we do not even have enough memory to allocate
the site data structure
*/
assert(siteANSTO);
/*
initializing function pointers
*/
siteANSTO->AddSiteCommands = AddCommands;
siteANSTO->RemoveSiteCommands = RemoveCommands;
siteANSTO->CreateMotor = CreateMotor;
siteANSTO->CreateCounterDriver = CreateAnstoCounterDriver;
siteANSTO->CreateHistogramMemoryDriver = CreateHistMem;
siteANSTO->CreateVelocitySelector = CreateVelSelDriv;
siteANSTO->CreateControllerDriver = CreateController;
siteANSTO->InstallEnvironmentController =
InstallEnvironmentController;
siteANSTO->ConfigureScan = ConfigureScan;
siteANSTO->KillSite = KillSite;
}
return siteANSTO;
}