Files
sics/tasmono.c
Ferdi Franceschini 10d29d597c Cleaned up ANSTO code to merge with sinqdev.sics
This is our new RELEASE-4_0 branch which was taken from ansto/93d9a7c
Conflicts:
	.gitignore
	SICSmain.c
	asynnet.c
	confvirtualmot.c
	counter.c
	devexec.c
	drive.c
	event.h
	exebuf.c
	exeman.c
	histmem.c
	interface.h
	motor.c
	motorlist.c
	motorsec.c
	multicounter.c
	napi.c
	napi.h
	napi4.c
	network.c
	nwatch.c
	nxscript.c
	nxxml.c
	nxxml.h
	ofac.c
	reflist.c
	scan.c
	sicshipadaba.c
	sicsobj.c
	site_ansto/docs/Copyright.txt
	site_ansto/instrument/lyrebird/config/tasmad/sicscommon/nxsupport.tcl
	site_ansto/instrument/lyrebird/config/tasmad/taspub_sics/tasscript.tcl
	statusfile.c
	tasdrive.c
	tasub.c
	tasub.h
	tasublib.c
	tasublib.h
2015-04-23 20:49:26 +10:00

242 lines
7.6 KiB
C

/**
* Triple axis monochromator module
* EIGER made it necessary to abstract out the monochromator. This is
* the default implementation for a sane, normal TAS. This implements a
* drivable interface. It gets an A2 value from the tasub module and is
* supposed to drive and monitor all the dependent monochromator motors.
*
* copyright: see file COPYRIGHT
*
* Mark Koennecke, February 2013
*
* TODO: this may need a refactoring towards a monochromator object with its
* own parameters and such. Eiger would have benefitted from this. This here
* just implements a drivable interface on top of the tasub parameters. As EIGER
* is now working; this has gone low priority.
*
* Mark Koennecke, September 2014
*/
#include <sics.h>
#include "tasmono.h"
#include "tasub.h"
#define MOTPREC .01
#define A1 0
#define A2 1
#define MCV 2
#define MCH 3
#define NOTSTARTED -100
#define ABS(x) (x < 0 ? -(x) : (x))
/*----------------------------------------------------------------
This routine can return either OKOK or HWFault when thing
go wrong. However, the return value of Halt is usually ignored!
------------------------------------------------------------------*/
static int TAMOHalt(void *data) {
ptasUB self = NULL;
pIDrivable pDriv;
int i;
self = (ptasUB)data;
for(i = 0; i < 4; i++){
if (self->motors[i] != NULL) {
pDriv = GetDrivableInterface(self->motors[i]);
pDriv->Halt(self->motors[i]);
}
}
return OKOK;
}
/*----------------------------------------------------------------
This routine can return either 1 or 0. 1 means the position can
be reached, 0 NOT
If 0, error shall contain up to errlen characters of information
about which limit was violated
------------------------------------------------------------------*/
static int TAMOCheckLimits(void *data, float val,
char *error, int errlen){
ptasUB self = NULL;
self = (ptasUB)data;
/*
Not meaningful in this context
*/
return 1;
}
/*----------------------------------------------------------------
This routine can return 0 when a limit problem occurred
OKOK when the motor was successfully started
HWFault when a problem occured starting the device
Possible errors shall be printed to pCon
For real motors, this is supposed to try at least three times
to start the motor in question
val is the value to drive the motor too
------------------------------------------------------------------*/
static void writeMotPos(SConnection * pCon, int silent, char *name,
float val, float target)
{
char pBueffel[132];
if (silent != 1) {
snprintf(pBueffel, 131, "Driving %5s from %8.3f to %8.3f",
name, val, target);
SCWrite(pCon, pBueffel, eLog);
}
}
/*--------------------------------------------------------------------------*/
static long startTASMotor(pMotor mot, SConnection * pCon, char *name,
double target, int silent, int stopFixed)
{
float val, fixed, precision = MOTPREC;
long status = NOTSTARTED;
char buffer[132];
pIDrivable pDriv = NULL;
pDummy dum = NULL;
pDynString mes = NULL;
dum = (pDummy)mot;
GetDrivablePosition(mot, pCon,&val);
if(strcmp(dum->pDescriptor->name,"Motor") == 0){
MotorGetPar(mot,"precision",&precision);
MotorGetPar(mot, "fixed", &fixed);
if (ABS(fixed - 1.0) < .1) {
if(stopFixed == 0){
snprintf(buffer, 131, "WARNING: %s is FIXED", name);
SCWrite(pCon, buffer, eLog);
}
return NOTSTARTED;
}
}
mot->stopped = 0;
if (ABS(val - target) > precision) {
status = StartDriveTask(mot, pCon, name, (float)target);
if(status < 0){
SCPrintf(pCon,eLog,"ERROR: failed to drive %s to %f", name, target);
}
/*
to force updates on targets
*/
InvokeNewTarget(pServ->pExecutor, name, target);
writeMotPos(pCon, silent, name, val, target);
return status;
} else {
return NOTSTARTED;
}
}
/*-------------------------------------------------------------------------*/
static long TAMOSetValue(void *data, SConnection *pCon, float val){
ptasUB self = NULL;
self = (ptasUB)data;
int stopFixed = 0;
double curve;
int status;
self->monoTaskID = GetTaskGroupID(pServ->pTasker);
status = startTASMotor(self->motors[A1], pCon, "a1",
val / 2., self->silent, stopFixed);
if (status < 0 && status != NOTSTARTED) {
return HWFault;
}
if(status != NOTSTARTED){
AddTaskToGroup(pServ->pTasker,status, self->monoTaskID);
}
status = startTASMotor(self->motors[A2], pCon, "a2",
val, self->silent,stopFixed);
if (status < 0 && status != NOTSTARTED) {
return HWFault;
}
if(status != NOTSTARTED){
AddTaskToGroup(pServ->pTasker,status, self->monoTaskID);
}
if (self->motors[MCV] != NULL) {
curve = maCalcVerticalCurvature(self->machine.monochromator,
val);
status = startTASMotor(self->motors[MCV], pCon, "mcv",
curve, self->silent,stopFixed);
if (status < 0 && status != NOTSTARTED) {
SCWrite(pCon,"WARNING: monochromator vertical curvature motor failed to start", eLog);
SCSetInterrupt(pCon,eContinue);
} else {
AddTaskToGroup(pServ->pTasker,status, self->monoTaskID);
}
}
if (self->motors[MCH] != NULL) {
curve = maCalcHorizontalCurvature(self->machine.monochromator,
val);
status = startTASMotor(self->motors[MCH], pCon, "mch",
curve, self->silent,stopFixed);
if (status < 0 && status != NOTSTARTED) {
SCWrite(pCon,"WARNING: monochromator horizontal curvature motor failed to start", eLog);
SCSetInterrupt(pCon,eContinue);
}else {
AddTaskToGroup(pServ->pTasker,status,self->monoTaskID);
}
}
return OKOK;
}
/*----------------------------------------------------------------
Checks the status of a running motor. Possible return values
HWBusy The motor is still running
OKOK or HWIdle when the motor finished driving
HWFault when a hardware problem ocurred
HWPosFault when the hardware cannot reach a position
Errors are duly to be printed to pCon
For real motors CheckStatus again shall try hard to fix any
issues with the motor
------------------------------------------------------------------*/
static int TAMOCheckStatus(void *data, SConnection *pCon){
ptasUB self = NULL;
self = (ptasUB)data;
if(isTaskGroupRunning(pServ->pTasker,self->monoTaskID)) {
return HWBusy;
} else {
return HWIdle;
}
return 1;
}
/*----------------------------------------------------------------
GetValue is supposed to read a motor position
On errors, -99999999.99 is returned and messages printed to pCon
------------------------------------------------------------------*/
static float TAMOGetValue(void *data, SConnection *pCon){
ptasUB self = NULL;
float val = -99999999.99;
int status;
self = (ptasUB)data;
status = GetDrivablePosition(self->motors[A2], pCon, &val);
if (status == 0) {
return -99999999.99;
}
return val;
}
/*----------------------------------------------------------------
returns NULL on failure, a new datastructure else
------------------------------------------------------------------*/
pIDrivable MakeTasMono(){
pIDrivable pDriv;
pDriv = calloc(1,sizeof(IDrivable));
if(pDriv == NULL){
return NULL;
}
pDriv->Halt = TAMOHalt;
pDriv->CheckLimits = TAMOCheckLimits;
pDriv->SetValue = TAMOSetValue;
pDriv->CheckStatus = TAMOCheckStatus;
pDriv->GetValue = TAMOGetValue;
return pDriv;
}