/*--------------------------------------------------------------------------- ilmdriv.c Driver for the Oxford Instruments ILM200 series level monitor Version 2 (based on ease). Markus Zolliker, April 2005 ------------------------------------------------------------------------------*/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "oxinst.h" #include "fsm.h" #include "initializer.h" /* typedef enum { ALWAYSNEW, NEW, MEASURING, NOTYETREAD, OLD } ReadState; */ typedef enum { UNUSED, N2, PULSED_HE, CONTINOUS_HE, CHANNEL_ERROR = 9 } Usage; typedef struct { EaseBase b; float lev[3]; Usage usage[3]; /* ReadState readState[3]; */ } Ilm; static ParClass ilmClass = { "ILM", sizeof(Ilm) }; char *tails[10] = { "unused", "% N2", "% He", "% He", "", "", "", "", "", "error" }; /*----------------------------------------------------------------------------*/ static void IlmParDef(void *object) { Ilm *drv = ParCast(&ilmClass, object); ParName(""); if (drv->usage[0]) { ParFmt("%.1f"); ParTail(tails[drv->usage[0]]); } /* if (drv->readState[0] == NEW) ParLogReady(PAR_NOW_READY); */ ParFloat(&drv->lev[0], PAR_NAN); ParName("lev2"); if (drv->usage[1]) { ParFmt("%.1f"); ParTail(tails[drv->usage[1]]); }; /* if (drv->readState[1] == NEW) ParLogReady(PAR_NOW_READY); */ ParFloat(&drv->lev[1], PAR_NAN); ParName("lev3"); if (drv->usage[2]) { ParFmt("%.1f"); ParTail(tails[drv->usage[2]]); } /* if (drv->readState[2] == NEW) ParLogReady(PAR_NOW_READY); */ ParFloat(&drv->lev[2], PAR_NAN); EaseBasePar(drv); EaseSendPar(drv); ParStdDef(); EaseMsgPar(drv); } /*----------------------------------------------------------------------------*/ static void IlmStatus(Ilm * drv) { char *ans; int *code; int i; int status; if (drv->b.state != EASE_read) return; ans = drv->b.ans; code = &drv->b.errCode; if (ans[0] != 'X' || ans[4] != 'S' || ans[11] != 'R') { ParPrintf(drv, eError, "illegal status response"); *code = EASE_FAULT; return; } for (i = 0; i < 3; i++) { if (ans[i + 1] < '0' || ans[i + 1] > '9') { ans[i + 1] = '9'; } drv->usage[i] = ans[i + 1] - '0'; if (drv->usage[i] == PULSED_HE) { /* sscanf(ans+6+2*i, "%1x", &status); if (status & 1) { // measuring drv->readState[i] = MEASURING; } else if (drv->readState[i] == MEASURING) { // new value drv->readState[i] = NOTYETREAD; } */ } else { /* drv->readState[i] = ALWAYSNEW; */ } } return; } /*----------------------------------------------------------------------------*/ static long IlmRead(long pc, void *object) { Ilm *drv = ParCast(&ilmClass, object); EaseBase *eab = object; int i; switch (pc) { default: /* FSM BEGIN ****************************** */ EasePchk(drv); EaseWrite(eab, "X"); return __LINE__; case __LINE__: /**********************************/ IlmStatus(drv); /* check for errors */ EaseWrite(eab, "R1"); /* read sensor 1 */ return __LINE__; case __LINE__: /**********************************/ /* if (drv->readState[0] != MEASURING) */ drv->lev[0] = OxiGet(eab, 1, NULL, drv->lev[0]); /* if (drv->readState[0] == NOTYETREAD) { drv->readState[0] = NEW; } */ if (drv->usage[1] == 0) goto skip2; EaseWrite(eab, "R2"); /* read sensor 2 */ return __LINE__; case __LINE__: /**********************************/ drv->lev[1] = OxiGet(eab, 1, NULL, drv->lev[1]); /* if (drv->readState[1] == NOTYETREAD) { drv->readState[1] = NEW; } */ skip2: if (drv->usage[2] == 0) goto skip3; EaseWrite(eab, "R3"); /* read sensor 3 */ return __LINE__; case __LINE__: /**********************************/ drv->lev[2] = OxiGet(eab, 1, NULL, drv->lev[2]); /* if (drv->readState[2] == NOTYETREAD) { drv->readState[2] = NEW; } */ skip3: if (ParLog(drv) >= 0) { /* logging was done */ /* for (i=0; i<3; i++) { if (drv->readState[i] == NEW) { drv->readState[i] = OLD; } } */ } return 0; } /* FSM END ******************************************* */ } /*----------------------------------------------------------------------------*/ static long IlmStart(long pc, void *object) { Ilm *drv = ParCast(&ilmClass, object); EaseBase *eab = object; char msg[256]; switch (pc) { default: /* FSM BEGIN ****************************** */ EasePchk(drv); EaseWrite(eab, "V"); return __LINE__; case __LINE__: /**********************************/ if (0 != strncmp(eab->version, "ILM", 3)) { snprintf(msg, sizeof msg, "unknown level meter version: %s", eab->version); EaseStop(eab, msg); goto quit; } ParPrintf(drv, eLog, "connected to %s", eab->version); eab->msg[0] = '\0'; /* o.k. */ FsmCall(IlmRead); return __LINE__; case __LINE__: /**********************************/ quit: return 0; } /* FSM END ******************************************* */ } /*----------------------------------------------------------------------------*/ static int IlmInit(SConnection * con, int argc, char *argv[], int dynamic) { /* args: MakeObject objectname ilm */ Ilm *drv; drv = EaseMakeBase(con, &ilmClass, argc, argv, dynamic, 0, IlmParDef, OxiHandler, IlmStart, NULL, IlmRead); if (drv == NULL) return 0; return 1; } /*----------------------------------------------------------------------------*/ void IlmStartup(void) { ParMakeClass(&ilmClass, EaseBaseClass()); MakeDriver("ILM", IlmInit, 0, "OI Level Meter"); }