new version of drivers (based on ease instead of eve)
This commit is contained in:
540
ighdriv.c
Normal file
540
ighdriv.c
Normal file
@ -0,0 +1,540 @@
|
||||
/*---------------------------------------------------------------------------
|
||||
ighdriv.c
|
||||
|
||||
Driver for the Oxford Instruments IGH Intelligent gas handling system
|
||||
(based on ease).
|
||||
|
||||
Markus Zolliker, May 2005
|
||||
----------------------------------------------------------------------------*/
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <sys/time.h>
|
||||
#include <math.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 <servlog.h>
|
||||
#include <sicsvar.h>
|
||||
#include <evdriver.i>
|
||||
#include <rs232controller.h>
|
||||
#include "oxinst.h"
|
||||
#include "fsm.h"
|
||||
#include "initializer.h"
|
||||
|
||||
#define SORBS_FLAG 1
|
||||
#define MIXP_FLAG 2
|
||||
#define STILL_FLAG 3
|
||||
#define SORBP_FLAG 4
|
||||
#define MOT_FLAGS 5
|
||||
#define VALVE_FLAGS 8
|
||||
#define MAX_FLAG 31
|
||||
|
||||
static char *valves[]={"V9", "V8", "V7", "V11A", "V13A", "V13B", "V11B", "V12B",
|
||||
" He4", "V1", "V5", "V4", "V3", "V14", "V10", "V2",
|
||||
" V2A", " V1A", " V5A", " V4A", " V3A", " Roots", " Aux", "He3",
|
||||
NULL}; /* valves beginning with blank are not shown in list */
|
||||
typedef enum {V9,V8,V7,V11A,V13A,V13B,V11B,V12B,
|
||||
HE4,V1,V5,V4,V3,V14,V10,V2,
|
||||
V2A,V1A,V5A,V4A,V3A,ROOTS,AUX,HE3,n_VALVES} Valves;
|
||||
|
||||
static char *motorValves[]={"V6", "V12A", "V1K", NULL};
|
||||
typedef enum {V6,V12A,V1K,n_MOTOR} MotorValves;
|
||||
static char *motorCommands[]={"G", "H", "N"};
|
||||
|
||||
static char *gauges[]={"G1", "G2", "G3", "", "", "", "P1", "P2", NULL};
|
||||
typedef enum {G1,G2,G3,G4,G5,G6,P1,P2,n_PRESS} PressureGauges;
|
||||
|
||||
static char *closedOrOpen[]={"closed", "open", NULL};
|
||||
|
||||
|
||||
typedef struct {
|
||||
EaseDriv d;
|
||||
float sorbS;
|
||||
float mixT;
|
||||
float onekT;
|
||||
float sorbT;
|
||||
float mixP;
|
||||
float stillP;
|
||||
float sorbP;
|
||||
float press[n_PRESS];
|
||||
float mv[n_MOTOR];
|
||||
int pdig;
|
||||
int v[n_VALVES];
|
||||
int e; /* heater range */
|
||||
int a; /* actual heater mode */
|
||||
int o; /* actual still/sorb mode */
|
||||
int s; /* moving valve state */
|
||||
int remote;
|
||||
} Igh;
|
||||
|
||||
static ParClass ighClass = { "IGH", sizeof(Igh) };
|
||||
|
||||
static long IghSet(long pc, void *object);
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static void IghParDef(void *object) {
|
||||
Igh *drv = ParCast(&ighClass, object);
|
||||
EaseBase *eab = object;
|
||||
int i, flag, l, changed;
|
||||
char *vPos;
|
||||
char fmt[8], vList[80];
|
||||
|
||||
ParName("TsorbSet");
|
||||
EaseUpdate(SORBS_FLAG); ParTail("K"); ParFmt("%.1f");
|
||||
ParFloat(&drv->sorbS, PAR_NAN);
|
||||
|
||||
ParName("Tmix");
|
||||
ParTail("K"); ParFmt("%.3f");
|
||||
ParFloat(&drv->mixT, PAR_NAN);
|
||||
|
||||
ParName("T1K");
|
||||
ParTail("K"); ParFmt("%.3f");
|
||||
ParFloat(&drv->onekT, PAR_NAN);
|
||||
|
||||
ParName("Tsorb");
|
||||
ParTail("K"); ParFmt("%.1f");
|
||||
ParFloat(&drv->sorbT, PAR_NAN);
|
||||
|
||||
ParName("Pmix");
|
||||
if (drv->e < 1 || drv->e > 5) drv->e=1;
|
||||
if (drv->e == 5) {
|
||||
strcpy(fmt, "%.0f");
|
||||
} else {
|
||||
snprintf(fmt, sizeof fmt, "%%.%df", 4 - drv->e);
|
||||
}
|
||||
EaseUpdate(MIXP_FLAG); ParTail("uW"); ParFmt(fmt);
|
||||
ParFloat(&drv->mixP, PAR_NAN);
|
||||
|
||||
ParName("Pstill");
|
||||
EaseUpdate(STILL_FLAG); ParTail("mW"); ParFmt("%.3f");
|
||||
ParFloat(&drv->stillP, PAR_NAN);
|
||||
|
||||
ParName("Psorb");
|
||||
EaseUpdate(SORBP_FLAG); ParTail("W"); ParFmt("%.1f");
|
||||
ParFloat(&drv->sorbP, PAR_NAN);
|
||||
|
||||
for (i=0; i<n_PRESS; i++) {
|
||||
if (gauges[i][0] != '\0') {
|
||||
ParName(gauges[i]);
|
||||
ParTail("mbar");
|
||||
if (i == P1) {
|
||||
snprintf(fmt, sizeof fmt, "%%.%df", drv->pdig);
|
||||
ParFmt(fmt);
|
||||
} else if (i == P2) {
|
||||
ParFmt("%.3f"); ParList("all");
|
||||
} else if (i == G3) {
|
||||
ParFmt("%.1f"); ParList("all");
|
||||
} else {
|
||||
ParFmt("%.1f");
|
||||
}
|
||||
ParFloat(&drv->press[i], PAR_NAN);
|
||||
}
|
||||
}
|
||||
|
||||
flag = MOT_FLAGS;
|
||||
for (i=0; i<n_MOTOR; i++) {
|
||||
ParName(motorValves[i]);
|
||||
ParTail("%");
|
||||
if (i == V1K) ParList("all");
|
||||
ParFloat(&drv->mv[i], PAR_NAN);
|
||||
EaseUpdate(flag); flag++;
|
||||
}
|
||||
assert(flag == VALVE_FLAGS);
|
||||
l = 0;
|
||||
for (i=0; i<n_VALVES; i++) {
|
||||
if (valves[i][0] == ' ') {
|
||||
ParName(valves[i]+1);
|
||||
changed = 0;
|
||||
} else {
|
||||
ParName(valves[i]);
|
||||
changed = EaseUpdate(flag);
|
||||
}
|
||||
ParEnum(closedOrOpen);
|
||||
ParInt(&drv->v[i], PAR_LNAN);
|
||||
if (changed) {
|
||||
if (drv->v[i] != 1) drv->v[i] = 0; /* allow only 1 or 0 */
|
||||
}
|
||||
flag++;
|
||||
if (ParActionIs(PAR_LIST) && valves[i][0] != ' ') {
|
||||
if (drv->v[i] == 1) {
|
||||
vPos = vList + l;
|
||||
l += strlen(valves[i]) + 1;
|
||||
if (l < sizeof vList) {
|
||||
strcpy(vPos, " "); vPos++;
|
||||
strcpy(vPos, valves[i]);
|
||||
vList[l] = '\0';
|
||||
} else {
|
||||
l = vPos - vList;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
assert(MAX_FLAG == flag-1);
|
||||
if (ParActionIs(PAR_LIST)) {
|
||||
vList[l] = '\0';
|
||||
ParPrintf(NULL, eValue, "open valves:%s", vList);
|
||||
}
|
||||
EaseBasePar(drv);
|
||||
EaseSendPar(drv);
|
||||
ParStdDef();
|
||||
EaseMsgPar(eab);
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
void IghStatus(Igh *drv) {
|
||||
char *ans;
|
||||
int *code;
|
||||
long mask, p;
|
||||
int i;
|
||||
|
||||
if (drv->d.b.state != EASE_read) return;
|
||||
ans=drv->d.b.ans;
|
||||
code=&drv->d.b.errCode;
|
||||
if (ans[0] != 'X' ||
|
||||
ans[2] != 'A' ||
|
||||
ans[4] != 'C' ||
|
||||
ans[6] != 'P' ||
|
||||
ans[15] != 'S' ||
|
||||
ans[17] != 'O' ||
|
||||
ans[19] != 'E') {
|
||||
ParPrintf(drv, eError, "illegal status response");
|
||||
*code = EASE_FAULT;
|
||||
return;
|
||||
}
|
||||
if (sscanf(ans+7, "%lx", &mask) <= 0) {
|
||||
ParPrintf(drv, eError, "illegal valve status response");
|
||||
*code = EASE_FAULT;
|
||||
return;
|
||||
}
|
||||
p=1;
|
||||
for (i=0; i<n_VALVES; i++) {
|
||||
if (! EaseGetUpdate(drv, VALVE_FLAGS+i)) {
|
||||
if (mask & p) {
|
||||
drv->v[i] = 1;
|
||||
} else {
|
||||
drv->v[i] = 0;
|
||||
}
|
||||
p=p*2;
|
||||
}
|
||||
}
|
||||
drv->a = ans[3] - '0';
|
||||
drv->s = ans[16] - '0';
|
||||
drv->o = ans[18] - '0';
|
||||
drv->e = ans[20] - '0';
|
||||
if (ans[5] != '3' && drv->remote == 2) {
|
||||
ParPrintf(drv, eError, "IGH switched to local");
|
||||
*code = EASE_FAULT;
|
||||
drv->remote = 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static long IghRead(long pc, void *object) {
|
||||
Igh *drv = ParCast(&ighClass, object);
|
||||
EaseBase *eab = object;
|
||||
char *p;
|
||||
int l;
|
||||
time_t thisPeriod;
|
||||
|
||||
switch (pc) { default: /* FSM BEGIN *******************************/
|
||||
EaseWrite(eab, "X");
|
||||
return __LINE__; case __LINE__: /**********************************/
|
||||
IghStatus(drv);
|
||||
if (!drv->remote) goto skiprmt;
|
||||
EaseWrite(eab, "C0");
|
||||
drv->remote = 0;
|
||||
return __LINE__; case __LINE__: /**********************************/
|
||||
skiprmt:
|
||||
|
||||
if (! EaseNextFullRead(eab)) goto fsm_quit;
|
||||
|
||||
if (EaseCheckDoit(eab)) goto quit;
|
||||
|
||||
if (EaseGetUpdate(drv, SORBS_FLAG)) goto skip0;
|
||||
if (drv->o / 2 != 1) {
|
||||
drv->sorbS = 0;
|
||||
goto skip0;
|
||||
}
|
||||
EaseWrite(eab, "R0");
|
||||
return __LINE__; case __LINE__: /**********************************/
|
||||
drv->sorbS = OxiGet(eab, 1, NULL);
|
||||
skip0:
|
||||
|
||||
if (EaseCheckDoit(eab)) goto quit;
|
||||
|
||||
EaseWrite(eab, "R1");
|
||||
return __LINE__; case __LINE__: /**********************************/
|
||||
drv->sorbT = OxiGet(eab, 1, NULL);
|
||||
|
||||
if (EaseCheckDoit(eab)) goto quit;
|
||||
|
||||
EaseWrite(eab, "R2");
|
||||
return __LINE__; case __LINE__: /**********************************/
|
||||
drv->onekT = OxiGet(eab, 3, NULL);
|
||||
|
||||
if (EaseCheckDoit(eab)) goto quit;
|
||||
|
||||
EaseWrite(eab, "R3");
|
||||
return __LINE__; case __LINE__: /**********************************/
|
||||
drv->mixT = OxiGet(eab, 3, NULL);
|
||||
|
||||
if (EaseCheckDoit(eab)) goto quit;
|
||||
|
||||
if (EaseGetUpdate(drv, MIXP_FLAG)) goto skip4;
|
||||
EaseWrite(eab, "R4");
|
||||
return __LINE__; case __LINE__: /**********************************/
|
||||
drv->mixP = OxiGet(eab, 5 - drv->e, NULL) * 10;
|
||||
skip4:
|
||||
|
||||
if (EaseCheckDoit(eab)) goto quit;
|
||||
|
||||
if (EaseGetUpdate(drv, STILL_FLAG)) goto skip5;
|
||||
EaseWrite(eab, "R5");
|
||||
return __LINE__; case __LINE__: /**********************************/
|
||||
drv->stillP = OxiGet(eab, 1, NULL);
|
||||
skip5:
|
||||
|
||||
if (EaseCheckDoit(eab)) goto quit;
|
||||
|
||||
if (EaseGetUpdate(drv, SORBP_FLAG)) goto skip6;
|
||||
EaseWrite(eab, "R6");
|
||||
return __LINE__; case __LINE__: /**********************************/
|
||||
drv->sorbP = OxiGet(eab, 3, NULL);
|
||||
skip6:
|
||||
|
||||
if (EaseCheckDoit(eab)) goto quit;
|
||||
|
||||
if (EaseGetUpdate(drv, MOT_FLAGS+V6)) goto skip7;
|
||||
EaseWrite(eab, "R7");
|
||||
return __LINE__; case __LINE__: /**********************************/
|
||||
drv->mv[V6] = OxiGet(eab, 1, NULL);
|
||||
skip7:
|
||||
|
||||
if (EaseCheckDoit(eab)) goto quit;
|
||||
|
||||
if (EaseGetUpdate(drv, MOT_FLAGS+V12A)) goto skip8;
|
||||
EaseWrite(eab, "R8");
|
||||
return __LINE__; case __LINE__: /**********************************/
|
||||
drv->mv[V12A] = OxiGet(eab, 1, NULL);
|
||||
skip8:
|
||||
|
||||
if (EaseCheckDoit(eab)) goto quit;
|
||||
|
||||
if (EaseGetUpdate(drv, MOT_FLAGS+V1K)) goto skip9;
|
||||
EaseWrite(eab, "R9");
|
||||
return __LINE__; case __LINE__: /**********************************/
|
||||
drv->mv[V1K] = OxiGet(eab, 1, NULL);
|
||||
skip9:
|
||||
|
||||
if (EaseCheckDoit(eab)) goto quit;
|
||||
|
||||
EaseWrite(eab, "R14");
|
||||
return __LINE__; case __LINE__: /**********************************/
|
||||
drv->press[G1] = OxiGet(eab, 1, NULL);
|
||||
|
||||
if (EaseCheckDoit(eab)) goto quit;
|
||||
|
||||
EaseWrite(eab, "R15");
|
||||
return __LINE__; case __LINE__: /**********************************/
|
||||
drv->press[G2] = OxiGet(eab, 1, NULL);
|
||||
|
||||
if (EaseCheckDoit(eab)) goto quit;
|
||||
|
||||
EaseWrite(eab, "R16");
|
||||
return __LINE__; case __LINE__: /**********************************/
|
||||
drv->press[G3] = OxiGet(eab, 1, NULL);
|
||||
|
||||
if (EaseCheckDoit(eab)) goto quit;
|
||||
|
||||
EaseWrite(eab, "R20");
|
||||
return __LINE__; case __LINE__: /**********************************/
|
||||
drv->press[P1] = OxiGet(eab, drv->pdig, &drv->pdig);
|
||||
|
||||
if (EaseCheckDoit(eab)) goto quit;
|
||||
|
||||
EaseWrite(eab, "R21");
|
||||
return __LINE__; case __LINE__: /**********************************/
|
||||
drv->press[P2] = OxiGet(eab, 1, NULL);
|
||||
|
||||
quit:
|
||||
ParLog(drv);
|
||||
fsm_quit: return 0; } /* FSM END **********************************/
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static long IghStart(long pc, void *object) {
|
||||
Igh *drv = ParCast(&ighClass, object);
|
||||
EaseBase *eab = object;
|
||||
|
||||
switch (pc) { default: /* FSM BEGIN *******************************/
|
||||
EaseWrite(eab, "V");
|
||||
return __LINE__; case __LINE__: /**********************************/
|
||||
if (0 != strncmp(eab->version, "IGH", 3)) {
|
||||
snprintf(eab->msg, sizeof eab->msg, "unknown gas handling system version: %s", eab->version);
|
||||
ParPrintf(drv, eError, "ERROR: %s", eab->msg);
|
||||
EaseStop(eab);
|
||||
goto quit;
|
||||
}
|
||||
ParPrintf(drv, eStatus, "connected to %s", eab->version);
|
||||
FsmCall(IghRead);
|
||||
return __LINE__; case __LINE__: /**********************************/
|
||||
|
||||
quit:
|
||||
return 0; } /* FSM END ********************************************/
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static long IghSet(long pc, void *object) {
|
||||
Igh *drv = ParCast(&ighClass, object);
|
||||
EaseBase *eab = object;
|
||||
char buf[8];
|
||||
int a;
|
||||
int upd;
|
||||
int i;
|
||||
float mp;
|
||||
|
||||
switch (pc) { default: /* FSM BEGIN *******************************/
|
||||
EaseWrite(eab, "C3");
|
||||
drv->remote=2;
|
||||
loop:
|
||||
return __LINE__; case __LINE__: /**********************************/
|
||||
upd = EaseNextUpdate(drv);
|
||||
if (upd >= VALVE_FLAGS) goto set_valve;
|
||||
if (upd >= MOT_FLAGS) goto set_mot;
|
||||
if (upd == EASE_RUN) goto set_temp;
|
||||
if (upd == SORBS_FLAG) goto set_sorb_temp;
|
||||
if (upd == MIXP_FLAG) goto set_mix_pow;
|
||||
if (upd == STILL_FLAG) goto set_still_pow;
|
||||
if (upd == SORBP_FLAG) goto set_sorb_pow;
|
||||
goto finish;
|
||||
|
||||
set_sorb_temp:
|
||||
if (drv->sorbS == 0) {
|
||||
drv->sorbP = 0;
|
||||
goto set_sorb_pow;
|
||||
}
|
||||
OxiSet(eab, "K", drv->sorbS, 1);
|
||||
return __LINE__; case __LINE__: /**********************************/
|
||||
EaseWrite(eab, "X");
|
||||
return __LINE__; case __LINE__: /**********************************/
|
||||
IghStatus(drv);
|
||||
if (drv->o == 2 || drv->o == 3) goto loop;
|
||||
if (drv->o % 2) {
|
||||
EaseWrite(eab, "O3");
|
||||
} else {
|
||||
EaseWrite(eab, "O2");
|
||||
}
|
||||
return __LINE__; case __LINE__: /**********************************/
|
||||
goto loop;
|
||||
|
||||
set_sorb_pow:
|
||||
EaseWrite(eab, "X");
|
||||
return __LINE__; case __LINE__: /**********************************/
|
||||
IghStatus(drv);
|
||||
if (drv->o <= 1) goto skipSetO;
|
||||
if (drv->o % 2) {
|
||||
EaseWrite(eab, "O1"); drv->o = 1;
|
||||
} else {
|
||||
EaseWrite(eab, "O0"); drv->o = 0;
|
||||
}
|
||||
return __LINE__; case __LINE__: /**********************************/
|
||||
skipSetO:
|
||||
OxiSet(eab, "B", drv->sorbP, 3);
|
||||
return __LINE__; case __LINE__: /**********************************/
|
||||
if (drv->sorbP == 0.0 || drv->o >= 4) goto loop;
|
||||
if (drv->o % 2) {
|
||||
EaseWrite(eab, "O5");
|
||||
} else {
|
||||
EaseWrite(eab, "O4");
|
||||
}
|
||||
return __LINE__; case __LINE__: /**********************************/
|
||||
goto loop;
|
||||
|
||||
set_still_pow:
|
||||
OxiSet(eab, "S", drv->stillP, 1);
|
||||
return __LINE__; case __LINE__: /**********************************/
|
||||
EaseWrite(eab, "X");
|
||||
return __LINE__; case __LINE__: /**********************************/
|
||||
IghStatus(drv);
|
||||
snprintf(buf, sizeof buf, "O%d", drv->o | 1);
|
||||
EaseWrite(eab, buf);
|
||||
return __LINE__; case __LINE__: /**********************************/
|
||||
goto loop;
|
||||
|
||||
set_mix_pow:
|
||||
EaseWrite(eab, "E1");
|
||||
return __LINE__; case __LINE__: /**********************************/
|
||||
if (drv->mixP > 0) {
|
||||
mp = drv->mixP * 0.1;
|
||||
for (i=2; i<6; i++) {
|
||||
if (mp > 199) {
|
||||
break;
|
||||
}
|
||||
mp = mp * 10;
|
||||
}
|
||||
if (mp > 1999) mp = 1999;
|
||||
drv->e = 7-i;
|
||||
} else {
|
||||
mp = 0;
|
||||
}
|
||||
OxiSet(eab, "M", mp, 0);
|
||||
return __LINE__; case __LINE__: /**********************************/
|
||||
snprintf(buf, sizeof buf, "E%d", drv->e);
|
||||
EaseWrite(eab, buf);
|
||||
return __LINE__; case __LINE__: /**********************************/
|
||||
EaseWrite(eab, "A1");
|
||||
return __LINE__; case __LINE__: /**********************************/
|
||||
goto loop;
|
||||
|
||||
set_temp:
|
||||
/* unknown yet */
|
||||
goto loop;
|
||||
return __LINE__; case __LINE__: /**********************************/
|
||||
goto loop;
|
||||
|
||||
set_valve:
|
||||
i = upd - VALVE_FLAGS;
|
||||
snprintf(buf, sizeof buf, "P%d", i * 2 + 3 - drv->v[i]);
|
||||
EaseWrite(eab, buf);
|
||||
return __LINE__; case __LINE__: /**********************************/
|
||||
goto loop;
|
||||
|
||||
set_mot:
|
||||
i = upd - MOT_FLAGS;
|
||||
OxiSet(eab, motorCommands[i], drv->mv[i], 1);
|
||||
return __LINE__; case __LINE__: /**********************************/
|
||||
goto loop;
|
||||
|
||||
finish:
|
||||
EaseWrite(eab, "C0");
|
||||
return __LINE__; case __LINE__: /**********************************/
|
||||
drv->remote = 0;
|
||||
quit:
|
||||
return 0; } /* FSM END ********************************************/
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static int IghInit(SConnection *con, int argc, char *argv[], int dynamic) {
|
||||
/* args:
|
||||
MakeObject objectname igh <rs232>
|
||||
MakeObject objectname igh <host> <port>
|
||||
*/
|
||||
Igh *drv;
|
||||
|
||||
drv = EaseMakeDriv(con, &ighClass, argc, argv, dynamic, MAX_FLAG,
|
||||
IghParDef, OxiHandler, IghStart, NULL, IghRead,
|
||||
IghSet);
|
||||
if (drv == NULL) return 0;
|
||||
ParPrintf(drv, eValue, "OI Gas Handling System");
|
||||
return 1;
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
void IghStartup(void) {
|
||||
ParMakeClass(&ighClass, EaseDrivClass());
|
||||
MakeDriver("IGH", IghInit, 0);
|
||||
}
|
Reference in New Issue
Block a user