new version of drivers (based on ease instead of eve)

This commit is contained in:
zolliker
2005-09-05 08:00:35 +00:00
parent 22fa164b76
commit 2cca4ba7f0
4 changed files with 1415 additions and 635 deletions

673
ipsdriv.c
View File

@@ -1,9 +1,10 @@
/*---------------------------------------------------------------------------
ipsdriv.c
ips2driv.c
Driver for the Oxford Instruments IPS/PS magnet power supply.
Version 2 (based on ease).
Markus Zolliker, Sept 2004
Markus Zolliker, May 2005
----------------------------------------------------------------------------*/
#include <string.h>
#include <stdio.h>
@@ -26,103 +27,185 @@ Markus Zolliker, Sept 2004
#include <sicsvar.h>
#include <evdriver.i>
#include <rs232controller.h>
#include "oicom.h"
#include "oxinst.h"
#include "fsm.h"
#include "initializer.h"
typedef struct {
Eve eve;
EaseDriv d;
float current; /* current (in Tesla) */
float persfield; /* persistent field from IPS (in Tesla) */
float lastfield; /* persistent field from last drive */
float confirmfield; /* field confirmed in 1st step */
float ramp; /* actual ramp rate (Telsa/min) */
float ramp; /* actual ramp rate (Tesla/min) */
float maxlimit; /* hard field limit */
int persmode; /* 0: leave switch on, 1: go to persistant mode */
int perswitch; /* state of switch */
int remote; /* 0: local, 1: remote, do not check, 2: remote, check */
int heaterFault;
char *fmt; /* fmt for field */
int force; /* force = 2: put heater switch even when stored field does not match */
time_t swtim; /* time when last switching the heater */
time_t tim;
} IpsDriv;
} Ips;
static ParClass ipsClass = { "IPS", sizeof(Ips) };
static char *onOff[] = { "off", "on", NULL };
int IpsConfirm(SConnection *pCon, pEVControl evc, int argc, char *argv[]);
/*----------------------------------------------------------------------------*/
static int IpsOk(IpsDriv *me, SConnection *pCon) {
static int IpsOk(Ips *drv) {
float dif;
Eve *eve=&me->eve;
if (me->eve.version[0]=='\0') return 1; /* connection not yet confirmed */
if (me->perswitch) return 1;
if (fabs(me->persfield - me->lastfield) < 1e-5) return 1;
if (me->force != 0) return 1;
eve->errCode = EVE_FAULT;
if (!pCon) pCon = SCLoad(&eve->evc->conn);
SCPrintf(pCon, eWarning,
if (drv->d.b.msg[0] != '\0') return 1; /* connection not yet confirmed */
if (drv->perswitch) return 1;
if (fabs(drv->persfield - drv->lastfield) < 1e-5) return 1;
if (drv->force != 0) return 1;
ParPrintf(drv, eWarning,
"\nit is not sure which field is in the magnet\n"
"value stored in power supply: %f\n"
" in software: %f\n"
"use command\n \n %s confirm ...\n \n"
"to specify the persistent field\n \n"
, me->persfield, me->lastfield, eve->evc->pName);
me->force = 0;
, drv->persfield, drv->lastfield, drv->d.b.p.name);
drv->force = 0;
return 0;
}
/*----------------------------------------------------------------------------*/
#define A EVE_ACTPAR
#define L EVE_LOGPAR
#define S EVE_SAVEPAR
void IpsPars(IpsDriv *me, EveParArg *arg) {
EveIntPar(arg, "persmode", &me->persmode, usUser, A+S);
EveIntPar(arg, "perswitch", &me->perswitch, usInternal, A);
EveObPar(arg, UPLIMIT, "%.5g\tTesla", A+S);
EveFloatPar(arg, "ramp", &me->ramp, "%.5g\tTesla/min", usUser, A+S);
EveFloatPar(arg, "current", &me->current, "%.5g\tTesla", usInternal, A+L);
EveFloatPar(arg, "lastfield", &me->lastfield, "%.5g\tTesla", usInternal, S);
EveCmd(arg, "confirm", IpsConfirm, usUser);
EveStdParEnd(arg, "%.5g\tTesla", A+L+S);
if (EveUserAction(arg)) {
IpsOk(me, EveArgConn(arg));
static int IpsConfirm(void *object, void *userarg, int argc, char *argv[])
{
Ips *drv = ParCast(&ipsClass, object);
float fld;
assert(drv);
if (argc > 0) {
if (argc > 1) {
ParPrintf(object, eError, "Too many arguments");
return 0;
}
fld=atof(argv[0]);
if (fld > drv->d.upperLimit || fld < drv->d.lowerLimit) {
ParPrintf(object, eError, "Field outside limit");
return 0;
}
if (drv->perswitch) {
ParPrintf(object, eWarning, "switch heater is on - field is %f", drv->current);
return 0;
}
if (fabs(fld - drv->persfield) > 1e-5 && fabs(fld - drv->lastfield) > 1e-5) {
ParPrintf(object, eWarning, "Be aware that this does neither match the field"
" stored in software\nnor the field stored in power supply.");
}
if (drv->force && fld != drv->confirmfield) drv->force = 0;
if (drv->force == 0) {
ParPrintf(object, eWarning, "Please repeat this command, to confirm again"
" the persistent field of\n %f Tesla.", fld);
drv->confirmfield = fld;
drv->force=1;
} else {
drv->force=2;
drv->lastfield=fld;
EaseParHasChanged();
ParPrintf(object, eValue, "%s confirm = %f", drv->d.b.p.name, fld);
}
} else {
ParPrintf(object, eValue, "%s lastfield = %f", drv->d.b.p.name, drv->lastfield);
}
return 1;
}
/*----------------------------------------------------------------------------*/
void IpsStatus(IpsDriv *me) {
void IpsParDef(void *object) {
Ips *drv = ParCast(&ipsClass, object);
ParName(""); ParFmt(drv->fmt); ParTail("Tesla");
ParFloat(&drv->persfield, PAR_NAN);
ParName("persmode"); ParAccess(usUser); ParEnum(onOff); ParList(0);
ParInt(&drv->persmode, 1);
ParName("perswitch"); ParEnum(onOff); ParList(0);
ParInt(&drv->perswitch, PAR_NAN);
ParName("maxlimit"); ParSave(1); ParFloat(&drv->maxlimit, 0.0);
ParName("limit"); ParAccess(usUser); ParFmt(drv->fmt); ParTail("Tesla");
ParFloat(&drv->d.upperLimit, 0.0);
if (ParActionIs(PAR_SET) > 0) {
if (drv->maxlimit == 0) { /* first time: set maxlimit */
drv->maxlimit = drv->d.upperLimit;
} else if (drv->d.upperLimit > drv->maxlimit) {
drv->d.upperLimit= drv->maxlimit;
ParPrintf(drv, eWarning, "limit is too high, set back to %.5g\n", drv->maxlimit);
}
drv->d.lowerLimit = - drv->d.upperLimit;
}
ParName("ramp"); ParAccess(usUser); ParFmt(drv->fmt); ParTail("Tesla/min");
ParFloat(&drv->ramp, 1.0);
ParName("current"); ParFmt(drv->fmt); ParTail("Tesla equivalent");
ParFloat(&drv->current, PAR_NAN);
ParName("lastfield");
ParSave(1);
ParFloat(&drv->lastfield, 0);
ParName("confirm"); ParCmd(IpsConfirm, NULL);
EaseBasePar(drv);
EaseSendPar(drv);
ParStdDef();
ParName("targetValue"); ParFmt(drv->fmt); ParTail("Tesla");
ParFloat(&drv->d.targetValue, PAR_NAN);
if (ParActionIs(PAR_LIST) || ParActionIs(PAR_SET) || ParActionIs(PAR_SHOW)) {
IpsOk(drv);
}
EaseMsgPar(drv);
}
/*----------------------------------------------------------------------------*/
static void IpsStatus(Ips *drv) {
char *ans;
int *code;
Eve *eve=&me->eve;
int swi;
if (eve->state != readState) return;
ans=eve->ans;
code=&eve->errCode;
if (drv->d.b.state != EASE_read) return;
ans=drv->d.b.ans;
code=&drv->d.b.errCode;
if (ans[0] != 'X' ||
ans[3] != 'A' ||
ans[5] != 'C' ||
ans[7] != 'H' ||
ans[9] != 'M') {
EvePrintf(eve, eError, "illegal status response");
*code = EVE_FAULT;
ParPrintf(drv, eError, "illegal status response");
*code = EASE_FAULT;
return;
}
switch (ans[1]) {
case '0': break;
case '1': EvePrintf(eve, eError, "magnet quenched"); *code = EVE_FAULT; return;
case '2': EvePrintf(eve, eError, "IPS overheated"); *code = EVE_FAULT; return;
case '4': EvePrintf(eve, eError, "IPS warming up"); *code = EVE_FAULT; return;
case '8': EvePrintf(eve, eError, "IPS fault"); *code = EVE_FAULT; return;
case '1': ParPrintf(drv, eError, "magnet quenched"); *code = EASE_FAULT; return;
case '2': ParPrintf(drv, eError, "IPS overheated"); *code = EASE_FAULT; return;
case '4': ParPrintf(drv, eError, "IPS warming up"); *code = EASE_FAULT; return;
case '8': ParPrintf(drv, eError, "IPS fault"); *code = EASE_FAULT; return;
default:
EvePrintf(eve, eError, "illegal status response");
*code = EVE_FAULT;
ParPrintf(drv, eError, "illegal status response");
*code = EASE_FAULT;
return;
}
if (ans[6] != '3' && me->remote == 2) {
EvePrintf(eve, eError, "IPS switched to local");
*code = EVE_FAULT;
me->remote = 1;
return;
if (ans[6] != '3') {
if (drv->remote == 2) {
ParPrintf(drv, eError, "IPS switched to local");
*code = EASE_FAULT;
drv->remote = 1;
return;
}
if (drv->d.hwstate == HWBusy && drv->d.b.doit == NULL) {
drv->d.hwstate = HWIdle;
drv->d.stopped = 0;
}
}
if (ans[8] == '5') {
me->heaterFault = 1;
drv->heaterFault = 1;
return;
}
if (ans[8] == '1') {
@@ -130,346 +213,292 @@ void IpsStatus(IpsDriv *me) {
} else {
swi = 0;
}
if (swi != me->perswitch || me->swtim == 0) {
me->swtim = time(NULL);
me->perswitch = swi;
if (swi != drv->perswitch || drv->swtim == 0) {
drv->swtim = time(NULL);
drv->perswitch = swi;
}
}
/*----------------------------------------------------------------------------*/
static void IpsSetField(IpsDriv *me, float val) {
char buf[128];
SConnection *pCon;
if (me->eve.value != val && me->eve.evc != NULL) {
snprintf(buf, sizeof(buf), "%s = %g", me->eve.evc->pName, val);
InvokeCallBack(me->eve.evc->pCall, VALUECHANGE, buf);
pCon = SCLoad(&me->eve.evc->conn);
if (pCon) SCparChange(pCon);
}
if (me->perswitch) {
me->current = val;
me->lastfield = val;
me->persfield = val;
} else if (me->force == 2) {
me->lastfield = val;
static void IpsSetField(Ips *drv, float val) {
ParLog(drv);
if (drv->perswitch) {
drv->current = val;
drv->lastfield = val;
drv->persfield = val;
EaseParHasChanged();
} else {
me->persfield = val;
drv->persfield = val;
}
me->eve.value = val;
}
/*----------------------------------------------------------------------------*/
static int IpsRead(long pc, IpsDriv *me) {
Eve *eve=&me->eve;
FSM_BEGIN
EveWrite(eve, "X");
FSM_NEXT
IpsStatus(me); /* check for errors and get perswitch */
/*
if (!me->remote) goto rd;
EveWrite(eve, "C0");
me->remote = 0;
FSM_NEXT
*/
static long IpsRead(long pc, void *object) {
Ips *drv = ParCast(&ipsClass, object);
EaseBase *eab = object;
switch (pc) { default: /* FSM BEGIN *******************************/
EaseWrite(eab, "X");
return __LINE__; case __LINE__: /**********************************/
IpsStatus(drv);
rd:
EveWrite(eve, "R7"); /* read current (in Tesla) */
FSM_NEXT
me->current = OiGetFlt(eve, 3, NULL);
if (me->perswitch) {
IpsSetField(me, me->current);
EaseWrite(eab, "R7"); /* read current (in Tesla) */
return __LINE__; case __LINE__: /**********************************/
drv->current = OxiGet(eab, 3, NULL);
if (drv->perswitch) {
IpsSetField(drv, drv->current);
goto quit;
}
EveWrite(eve, "R18"); /* read persistant field (in Tesla) */
FSM_NEXT
IpsSetField(me, OiGetFlt(eve, 3, NULL));
EaseWrite(eab, "R18"); /* read persistant field (in Tesla) */
return __LINE__; case __LINE__: /**********************************/
IpsSetField(drv, OxiGet(eab, 3, NULL));
quit:
EveLog(eve);
FSM_END
ParLog(drv);
return 0; } /* FSM END ********************************************/
}
/*----------------------------------------------------------------------------*/
static int IpsStart(long pc, IpsDriv *me) {
Eve *eve=&me->eve;
static long IpsStart(long pc, void *object) {
Ips *drv = ParCast(&ipsClass, object);
EaseBase *eab = object;
FSM_BEGIN
EveWrite(eve, "V");
FSM_NEXT
if (0 == strncmp(eve->version, "IPS120", 6)) {
me->eve.syntax = 1;
} else if (0 == strncmp(eve->version, "PS", 2)) {
me->eve.syntax = 0;
switch (pc) { default: /* FSM BEGIN *******************************/
EaseWrite(eab, "V");
return __LINE__; case __LINE__: /**********************************/
if (0 == strncmp(eab->version, "IPS120", 6)) {
eab->syntax = 1;
} else if (0 == strncmp(eab->version, "PS", 2)) {
eab->syntax = 0;
} else {
EvePrintf(eve, eError, "unknown power supply version: %s", eve->version);
snprintf(eab->msg, sizeof eab->msg, "unknown power supply version: %s", eab->version);
ParPrintf(drv, eError, "ERROR: %s", eab->msg);
EaseStop(eab);
goto quit;
}
EvePrintf(eve, eStatus, "connected to %s", eve->version);
FSM_CALL(IpsRead);
ParPrintf(drv, eStatus, "connected to %s", eab->version);
if (eab->syntax) {
drv->fmt = "%.4f";
} else {
drv->fmt = "%.3f";
}
FsmCall(IpsRead);
return __LINE__; case __LINE__: /**********************************/
quit:
FSM_END
return 0; } /* FSM END ********************************************/
}
/*----------------------------------------------------------------------------*/
static int IpsChangeField(long pc, IpsDriv *me) {
Eve *eve=&me->eve;
pEVControl evc=eve->evc;
static long IpsChangeField(long pc, void *object) {
Ips *drv = ParCast(&ipsClass, object);
EaseBase *eab = object;
float fld;
float step;
float ramp;
time_t delay;
FSM_BEGIN
EveWrite(eve, "C3");
me->remote = 1;
FSM_NEXT
EveWrite(eve, "F7"); /* switch to tesla on display */
FSM_NEXT
EveWrite(eve, "A0"); /* hold */
FSM_NEXT
FSM_CALL(IpsRead);
me->remote = 2;
if (!IpsOk(me, NULL)) goto finish;
if (fabs(evc->fTarget - me->lastfield) < 1e-5) {
EvePrintf(eve, -1, "IPS: we are already at field %f", me->lastfield);
if (me->persmode) {
if (!me->perswitch) goto finish;
switch (pc) { default: /* FSM BEGIN *******************************/
EaseSetUpdate(eab, EASE_RUN, 0);
EaseWrite(eab, "C3");
drv->remote = 1;
return __LINE__; case __LINE__: /**********************************/
EaseWrite(eab, "F7"); /* switch to tesla on display */
return __LINE__; case __LINE__: /**********************************/
EaseWrite(eab, "A0"); /* hold */
return __LINE__; case __LINE__: /**********************************/
FsmCall(IpsRead);
return __LINE__; case __LINE__: /**********************************/
drv->remote = 2;
if (!IpsOk(drv)) goto finish;
if (fabs(drv->d.targetValue - drv->lastfield) < 1e-5) {
ParPrintf(drv, -1, "IPS: we are already at field %f", drv->lastfield);
if (drv->persmode) {
if (!drv->perswitch) goto finish;
goto target_reached;
} else {
if (me->perswitch) goto finish;
if (drv->perswitch) goto finish;
}
}
if (fabs(me->current - me->lastfield) < 1e-5) {
if (fabs(drv->current - drv->lastfield) < 1e-5) {
goto switch_on;
}
OiSet(eve, "J", me->lastfield, 3); /* set point */
FSM_NEXT
EveWrite(eve, "A1");
EvePrintf(eve, -1, "IPS: ramp to current for %f Tesla", me->lastfield);
FSM_NEXT
me->tim = time(NULL);
OxiSet(eab, "J", drv->lastfield, 3); /* set point */
return __LINE__; case __LINE__: /**********************************/
EaseWrite(eab, "A1");
ParPrintf(drv, -1, "IPS: ramp to current for %f Tesla", drv->lastfield);
return __LINE__; case __LINE__: /**********************************/
drv->tim = time(NULL);
stab1:
EveWrite(eve, "X");
FSM_NEXT
IpsStatus(me); /* just check for errors */
EveWrite(eve, "R7"); /* read current (in Tesla) */
FSM_NEXT
me->current = OiGetFlt(eve, 3, NULL);
EveLog(eve);
if (fabs(me->current - me->lastfield) > 1e-5) goto stab1;
EaseWrite(eab, "X");
return __LINE__; case __LINE__: /**********************************/
IpsStatus(drv); /* just check for errors */
EaseWrite(eab, "R7"); /* read current (in Tesla) */
return __LINE__; case __LINE__: /**********************************/
drv->current = OxiGet(eab, 3, NULL);
ParLog(drv);
if (fabs(drv->current - drv->lastfield) > 1e-5) goto stab1;
stab2:
FSM_WAIT(1)
EveWrite(eve, "X");
FSM_NEXT
IpsStatus(me);
if (time(NULL) < me->tim + 10) goto stab2; /* stabilize */
FsmWait(1);
return __LINE__; case __LINE__: /**********************************/
EaseWrite(eab, "X");
return __LINE__; case __LINE__: /**********************************/
IpsStatus(drv);
if (time(NULL) < drv->tim + 10) goto stab2; /* stabilize */
switch_on:
if (me->perswitch) goto wait_open;
if (me->force == 2) {
EveWrite(eve, "H2");
if (drv->perswitch) goto wait_open;
if (drv->force == 2) {
EaseWrite(eab, "H2");
} else {
EveWrite(eve, "H1");
EaseWrite(eab, "H1");
}
me->force = 0;
FSM_NEXT
me->perswitch = 1;
me->swtim = time(NULL);
drv->force = 0;
return __LINE__; case __LINE__: /**********************************/
drv->perswitch = 1;
drv->swtim = time(NULL);
wait_open:
delay = me->swtim + 30 - time(NULL);
delay = drv->swtim + 30 - time(NULL);
if (delay > 0)
EvePrintf(eve, -1, "IPS: wait %d sec to open switch", delay);
ParPrintf(drv, -1, "IPS: wait %d sec to open switch", delay);
start_ramp:
FSM_WAIT(1)
EveWrite(eve, "X");
FSM_NEXT
IpsStatus(me); /* check for errors */
if (me->heaterFault) {
if (time(NULL) > me->swtim + 3) {
EvePrintf(eve, eError, "IPS heater fault");
eve->errCode = EVE_FAULT;
FsmWait(1);
return __LINE__; case __LINE__: /**********************************/
EaseWrite(eab, "X");
return __LINE__; case __LINE__: /**********************************/
IpsStatus(drv); /* check for errors */
if (drv->heaterFault) {
if (time(NULL) > drv->swtim + 3) {
ParPrintf(drv, eError, "IPS heater fault");
eab->errCode = EASE_FAULT;
goto off_finish;
}
me->heaterFault = 0;
drv->heaterFault = 0;
}
if (time(NULL) < me->swtim + 30) goto start_ramp; /* wait */
OiSet(eve, "T", me->ramp, 3);
FSM_NEXT
OiSet(eve, "J", me->current, 3); /* put set point to actual value */
FSM_NEXT
EveWrite(eve, "A1"); /* go to setpoint (do not yet run) */
FSM_NEXT
EvePrintf(eve, -1, "IPS: ramp to %f Tesla", evc->fTarget);
if (time(NULL) < drv->swtim + 30) goto start_ramp; /* wait */
OxiSet(eab, "T", drv->ramp, 3);
return __LINE__; case __LINE__: /**********************************/
OxiSet(eab, "J", drv->current, 3); /* put set point to actual value */
return __LINE__; case __LINE__: /**********************************/
EaseWrite(eab, "A1"); /* go to setpoint (do not yet run) */
return __LINE__; case __LINE__: /**********************************/
ParPrintf(drv, -1, "IPS: ramp to %f Tesla", drv->d.targetValue);
ramping:
FSM_WAIT(1)
EveWrite(eve, "R7"); /* read "current" in Tesla */
FSM_NEXT
IpsSetField(me, OiGetFlt(eve, 3, NULL)); /* set me->current and callback */
EveWrite(eve, "X");
FSM_NEXT
IpsStatus(me); /* just check for errors */
EveWrite(eve, "R9"); /* read back ramp rate (may be sweep limited) */
FSM_NEXT
ramp=OiGetFlt(eve, 3, NULL);
FsmWait(1);
return __LINE__; case __LINE__: /**********************************/
EaseWrite(eab, "R7"); /* read "current" in Tesla */
return __LINE__; case __LINE__: /**********************************/
IpsSetField(drv, OxiGet(eab, 3, NULL)); /* set drv->current and callback */
EaseWrite(eab, "X");
return __LINE__; case __LINE__: /**********************************/
IpsStatus(drv); /* just check for errors */
EaseWrite(eab, "R9"); /* read back ramp rate (may be sweep limited) */
return __LINE__; case __LINE__: /**********************************/
ramp=OxiGet(eab, 3, NULL);
step=ramp/20; /* step = ramp * 3sec */
if (step < 0.001) step=0.001;
if (evc->fTarget > me->current + step) {
fld=me->current + step;
} else if (evc->fTarget < me->current - step) {
fld=me->current - step;
if (drv->d.targetValue > drv->current + step) {
fld=drv->current + step;
} else if (drv->d.targetValue < drv->current - step) {
fld=drv->current - step;
} else {
fld=evc->fTarget;
if (fabs(me->current - evc->fTarget) < 1e-5) goto target_reached;
fld=drv->d.targetValue;
if (fabs(drv->current - drv->d.targetValue) < 1e-5) goto target_reached;
}
OiSet(eve, "J", fld, 3);
FSM_NEXT
EveLog(eve);
OxiSet(eab, "J", fld, 3);
return __LINE__; case __LINE__: /**********************************/
ParLog(drv);
goto ramping;
target_reached:
eve->hwstate = HWIdle;
evc->eMode = EVMonitor;
/* we are at field, drive has finished, but we continue in the background */
me->tim = time(NULL);
drv->d.hwstate = HWIdle;
drv->d.eMode = EVMonitor; /* we are at field, drive has finished */
if (!drv->persmode) goto hold_finish;
/* but we continue in the background */
drv->tim = time(NULL);
stab3:
FSM_WAIT(1)
EveWrite(eve, "R18"); /* read persistant field in Tesla */
FSM_NEXT
IpsSetField(me, OiGetFlt(eve, 3, NULL));
me->lastfield = me->persfield;
EveWrite(eve, "X");
FSM_NEXT
IpsStatus(me); /* just check for errors */
if (time(NULL) < me->tim + 10) goto stab3; /* stabilize */
EveWrite(eve, "A0"); /* hold */
FSM_NEXT
if (!me->persmode) goto finish;
EveWrite(eve, "H0");
me->perswitch = 0;
me->swtim = time(NULL);
me->lastfield = me->current;
FSM_NEXT
EvePrintf(eve, -1, "IPS: wait 30 sec to close switch");
FsmWait(1);
return __LINE__; case __LINE__: /**********************************/
EaseWrite(eab, "X");
return __LINE__; case __LINE__: /**********************************/
IpsStatus(drv); /* just check for errors */
if (time(NULL) < drv->tim + 10) goto stab3; /* stabilize */
EaseWrite(eab, "A0"); /* hold */
return __LINE__; case __LINE__: /**********************************/
EaseWrite(eab, "H0");
drv->perswitch = 0;
drv->swtim = time(NULL);
drv->lastfield = drv->current;
EaseParHasChanged();
return __LINE__; case __LINE__: /**********************************/
ParPrintf(drv, -1, "IPS: wait 30 sec to close switch");
wait_closed:
EveWrite(eve, "R18"); /* read persistant field in Tesla */
FSM_NEXT
IpsSetField(me, OiGetFlt(eve, 3, NULL));
me->lastfield = me->persfield;
FSM_WAIT(1)
EveWrite(eve, "X");
FSM_NEXT
IpsStatus(me);
if (time(NULL) < me->swtim + 30) goto wait_closed; /* wait */
FsmWait(1);
return __LINE__; case __LINE__: /**********************************/
EaseWrite(eab, "R18"); /* read persistent field in Tesla */
return __LINE__; case __LINE__: /**********************************/
fld = OxiGet(eab, 3, NULL);
if (fld != drv->lastfield) {
IpsSetField(drv, fld); /* set drv->current and callback */
drv->lastfield = fld;
EaseParHasChanged();
}
EaseWrite(eab, "X");
return __LINE__; case __LINE__: /**********************************/
IpsStatus(drv);
if (time(NULL) < drv->swtim + 30) goto wait_closed; /* wait */
if (me->current == 0) goto finish;
EveWrite(eve, "A2"); /* goto zero */
EvePrintf(eve, -1, "IPS: ramp current to 0");
FSM_NEXT
if (drv->current == 0) goto finish;
EaseWrite(eab, "A2"); /* goto zero */
ParPrintf(drv, -1, "IPS: ramp current to 0");
return __LINE__; case __LINE__: /**********************************/
goto finish;
hold_finish:
EaseWrite(eab, "A0");
return __LINE__; case __LINE__: /**********************************/
goto finish;
off_finish:
if (me->perswitch) {
me->lastfield = me->current;
me->swtim = time(NULL);
if (drv->perswitch) {
drv->lastfield = drv->current;
drv->swtim = time(NULL);
}
EveWrite(eve, "H0");
FSM_NEXT
EaseWrite(eab, "H0");
return __LINE__; case __LINE__: /**********************************/
finish:
EveWrite(eve, "C0");
me->remote = 0;
eve->hwstate = HWIdle;
FSM_NEXT
EaseWrite(eab, "C0");
drv->remote = 0;
drv->d.hwstate = HWIdle;
return __LINE__; case __LINE__: /**********************************/
FSM_END
return 0; } /* FSM END ********************************************/
}
/*----------------------------------------------------------------------------*/
int IpsConfirm(SConnection *pCon, pEVControl evc, int argc, char *argv[]) {
float fld;
IpsDriv *me;
me=evc->pDriv->pPrivate; assert(me);
if (argc > 1) {
if (argc > 2) {
SCPrintf(pCon, eError, "Too many arguments");
return -1;
}
fld=atof(argv[1]);
if (fld > ObVal(evc->pParam, UPLIMIT)) {
SCPrintf(pCon, eError, "Field outside limit");
return -1;
}
if (me->perswitch) {
SCPrintf(pCon, eWarning, "switch heater is on - field is %f", me->current);
return -1;
}
if (fabs(fld - me->persfield) > 1e-5 && fabs(fld - me->lastfield) > 1e-5) {
SCPrintf(pCon, eWarning, "Be aware that this does neither match the field"
" stored in software\nnor the field stored in power supply.");
}
if (me->force && fld != me->confirmfield) me->force = 0;
if (me->force == 0) {
SCPrintf(pCon, eWarning, "Please repeat this command, to confirm again"
" the persistent field of\n %f Tesla.", fld);
me->confirmfield = fld;
me->force=1;
} else {
me->force=2;
IpsSetField(me, fld);
SCPrintf(pCon, eValue, "%s.%s = %f", evc->pName, argv[1], fld);
}
} else {
SCPrintf(pCon, eValue, "%s.%s = %f", evc->pName, argv[1], me->eve.value);
}
return 1;
}
/*------------------------------------------------------------------------*/
static int IpsIsOk(void *data) {
/* always in tolerance (here we may implement what to do in case of a quench) */
return 1;
}
/*------------------------------------------------------------------------*/
pEVControl IpsMakeEVC(SConnection *pCon, int argc, char *argv[]) {
static int IpsInit(SConnection *con, int argc, char *argv[], int dynamic) {
/* args:
<objectname> ips <rs232>
<objectname> ips <host> <port>
*/
IpsDriv *me;
Eve *eve;
pEVControl evc;
MakeObject objectname ips <rs232>
<host> <port>
*/
Ips *drv;
evc = MakeEveEVC(argc, argv, calloc(1, sizeof *me), pCon);
if (!evc) return NULL;
me = evc->pDriv->pPrivate;
eve=&me->eve;
me->current = 0;
me->persfield = 0;
me->lastfield = 0;
me->persmode = 1;
me->perswitch = 0;
me->force = 0;
me->tim = 0;
me->swtim = 0;
me->ramp=0.1;
eve->run = (FsmFunc)IpsChangeField;
eve->read = (FsmFunc)IpsRead;
eve->pardef = (EveParDef)IpsPars;
eve->todo = (FsmFunc)IpsStart;
eve->task = FsmStartTask(me, (FsmHandler)OiHandler, (FsmFunc)EveIdle);
evc->pEnvir->IsInTolerance = IpsIsOk;
EVCSetPar(evc,"upperlimit",14.9,pCon);
EVCSetPar(evc,"lowerlimit",-14.9,pCon);
return evc;
drv = EaseMakeDriv(con, &ipsClass, argc, argv, dynamic, 7,
IpsParDef, OxiHandler, IpsStart, NULL, IpsRead,
IpsChangeField);
if (drv == NULL) return 0;
ParPrintf(drv, eValue, "OI Power Supply");
drv->d.maxwait = 999999;
return 1;
}
/*----------------------------------------------------------------------------*/
void IpsStartup(void) {
ParMakeClass(&ipsClass, EaseDrivClass());
MakeDriver("IPS", IpsInit, 0);
}