
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
242 lines
7.6 KiB
C
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;
|
|
}
|
|
|