Added to repository.
r986 | ffr | 2006-05-09 09:17:15 +1000 (Tue, 09 May 2006) | 2 lines
This commit is contained in:
committed by
Douglas Clowes
parent
a72513165b
commit
81359a740f
103
site_ansto/Makefile
Normal file
103
site_ansto/Makefile
Normal 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
447
site_ansto/anstohm.cpp
Normal 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
28
site_ansto/anstohm.h
Normal 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
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
21
site_ansto/hm_asim.h
Normal 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
30
site_ansto/hm_tango.h
Normal 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
281
site_ansto/itc4.c
Normal 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
43
site_ansto/itc4.h
Normal 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
74
site_ansto/itc4.w
Normal 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
478
site_ansto/itc4driv.c
Normal 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
284
site_ansto/lakeshore340.c
Normal 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
49
site_ansto/lakeshore340.h
Normal 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
|
||||||
|
|
||||||
489
site_ansto/lakeshore340driv.c
Normal file
489
site_ansto/lakeshore340driv.c
Normal 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
284
site_ansto/lh45.c
Normal 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
49
site_ansto/lh45.h
Normal 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
489
site_ansto/lh45driv.c
Normal 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;
|
||||||
|
}
|
||||||
|
|
||||||
34
site_ansto/make_gen_variables
Normal file
34
site_ansto/make_gen_variables
Normal 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
655
site_ansto/motor_asim.c
Normal 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
17
site_ansto/motor_asim.h
Normal 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
802
site_ansto/motor_dmc2280.c
Normal 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
17
site_ansto/motor_dmc2280.h
Normal file
17
site_ansto/motor_dmc2280.h
Normal 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
24
site_ansto/motor_driver.h
Normal 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
403
site_ansto/refl2t.c
Normal 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
49
site_ansto/refl2t.h
Normal 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
238
site_ansto/site_ansto.c
Normal 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
131
site_ansto/site_dummy.c
Normal 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;
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user