- bug fixes and improvements
This commit is contained in:
60
binprot.c
60
binprot.c
@ -3,6 +3,7 @@
|
||||
#include "ascon.h"
|
||||
#include "ascon.i"
|
||||
#include "dynstring.h"
|
||||
#include "cnvrt.h"
|
||||
|
||||
/*
|
||||
* this is a (scriptcontext) general binary protocol driver
|
||||
@ -64,65 +65,6 @@ typedef struct {
|
||||
int dumpFrom;
|
||||
} BinPrivate;
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static void double2ieee(double input, char ieee[4])
|
||||
{
|
||||
|
||||
/* convert double to IEEE 32 bit floating number (denormalized numbers are considered as zero) */
|
||||
|
||||
long mantissa;
|
||||
int exponent;
|
||||
|
||||
if (input == 0) {
|
||||
ieee[0] = 0;
|
||||
ieee[1] = 0;
|
||||
ieee[2] = 0;
|
||||
ieee[3] = 0;
|
||||
} else {
|
||||
mantissa = 0x1000000 * (frexp(fabs(input), &exponent));
|
||||
exponent = exponent - 1 + 127;
|
||||
if (exponent < 0) {
|
||||
exponent = 0;
|
||||
} else if (exponent > 0xFE) {
|
||||
exponent = 0xFE;
|
||||
}
|
||||
if (input < 0) {
|
||||
ieee[0] = 0x80 | (exponent >> 1);
|
||||
} else {
|
||||
ieee[0] = exponent >> 1;
|
||||
}
|
||||
ieee[1] = (exponent & 1) << 7 | ((mantissa & 0x7F0000) >> 16);
|
||||
ieee[2] = (mantissa & 0xFF00) >> 8;
|
||||
ieee[3] = mantissa & 0xFF;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static double ieee2double(char ieee[4])
|
||||
{
|
||||
|
||||
/* IEEE 32 bit floating number to double (denormalized numbers are considered as zero) */
|
||||
|
||||
long mantissa;
|
||||
double output;
|
||||
int exponent;
|
||||
|
||||
mantissa = ((ieee[1] << 16) & 0x7FFFFF)
|
||||
| ((ieee[2] << 8) & 0xFF00)
|
||||
| ((ieee[3]) & 0xFF);
|
||||
|
||||
exponent = (ieee[0] & 0x7F) * 2 + ((ieee[1] >> 7) & 1); /* raw exponent */
|
||||
if (exponent == 0 && mantissa == 0) {
|
||||
return 0.0;
|
||||
}
|
||||
output = ldexp(mantissa, -23) + 1.0;
|
||||
if (ieee[0] & 0x80) {
|
||||
output = -output;
|
||||
}
|
||||
return output * ldexp(1, exponent - 127);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static int calc_crc(char *inp, int inpLen)
|
||||
{
|
||||
|
19
ighdriv.c
19
ighdriv.c
@ -271,8 +271,12 @@ static void IghParDef(void *object)
|
||||
vList[l] = '\0';
|
||||
ParPrintf(NULL, eValue, "open valves:%s", vList);
|
||||
}
|
||||
|
||||
EaseBasePar(drv);
|
||||
EaseSendPar(drv);
|
||||
if (eab->syntax != OLDIGH) {
|
||||
EaseDrivPar(drv, "%.5g", "K");
|
||||
}
|
||||
ParStdDef();
|
||||
EaseMsgPar(eab);
|
||||
}
|
||||
@ -324,12 +328,14 @@ void IghStatus(Igh * drv)
|
||||
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;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
@ -710,6 +716,9 @@ static long IghSet(long pc, void *object)
|
||||
if (drv->mixP > 0) {
|
||||
drv->e = IghPower2Range(drv->mixP);
|
||||
mp = drv->mixP / IghRange2Max(drv->e) * 2000;
|
||||
if (mp < 2001 && mp > 1999) {
|
||||
mp = 1999;
|
||||
}
|
||||
} else {
|
||||
mp = 0; /* range unchanged for external heater signal */
|
||||
}
|
||||
@ -727,10 +736,6 @@ static long IghSet(long pc, void *object)
|
||||
case __LINE__: /**********************************/
|
||||
goto loop;
|
||||
|
||||
EaseWrite(eab, "A1");
|
||||
return __LINE__;
|
||||
case __LINE__: /**********************************/
|
||||
|
||||
set_max_pow:
|
||||
if (drv->e == 0)
|
||||
goto seta0;
|
||||
@ -738,10 +743,11 @@ static long IghSet(long pc, void *object)
|
||||
EaseWrite(eab, buf);
|
||||
return __LINE__;
|
||||
case __LINE__: /**********************************/
|
||||
EaseWrite(eab, "M0");
|
||||
if (drv->a == 2) goto loop;
|
||||
EaseWrite(eab, "A1");
|
||||
return __LINE__;
|
||||
case __LINE__: /**********************************/
|
||||
EaseWrite(eab, "A1");
|
||||
EaseWrite(eab, "M0");
|
||||
return __LINE__;
|
||||
case __LINE__: /**********************************/
|
||||
goto loop;
|
||||
@ -760,6 +766,7 @@ static long IghSet(long pc, void *object)
|
||||
drv->d.targetValue = 0;
|
||||
if (drv->d.targetValue > 1.999)
|
||||
drv->d.targetValue = 1.999;
|
||||
drv->setT = drv->d.targetValue;
|
||||
OxiSet(eab, "T", drv->d.targetValue, 4);
|
||||
return __LINE__;
|
||||
case __LINE__: /**********************************/
|
||||
|
326
ipsdriv.c
326
ipsdriv.c
@ -31,27 +31,38 @@ Markus Zolliker, May 2005
|
||||
#include "fsm.h"
|
||||
#include "initializer.h"
|
||||
|
||||
typedef enum {NOTHING, SWITCH_OFF, RAMP_DOWN,
|
||||
RAMP_ALMOST, RAMP_ZERO, RAMPED_DOWN} DoThis;
|
||||
|
||||
typedef struct {
|
||||
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 (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 nowait; /* 0: normal, 1: drive finishes immediately, ramp in background */
|
||||
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 (Tesla/min) */
|
||||
float maxlimit; /* hard field limit */
|
||||
float perscurrent; /* current for persistent mode workaround (Tesla) */
|
||||
float perslimit; /* field limit for activating persistent mode workaround (Tesla) */
|
||||
float voltage; /* voltage */
|
||||
float measured; /* measured current */
|
||||
int persmode; /* 0: delayed persistant mode, 1: go to persistant mode, 2: leave switch on */
|
||||
int persdelay; /* wait time for delayed persistant mode */
|
||||
int perswitch; /* state of switch */
|
||||
int remote; /* 0: local, 1: remote, do not check, 2: remote, check */
|
||||
int nowait; /* 0: normal, 1: drive finishes immediately, ramp in background */
|
||||
int perswait; /* wait time for persistent mode workaround (sec) */
|
||||
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;
|
||||
DoThis dothis;
|
||||
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; /* outside IpsChangeField: time of last Field Change */
|
||||
} Ips;
|
||||
|
||||
static ParClass ipsClass = { "IPS", sizeof(Ips) };
|
||||
static char *onOff[] = { "off", "on", NULL };
|
||||
static char *persMode[] = { "auto", "on", "off", NULL };
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static int IpsOk(Ips * drv)
|
||||
@ -141,7 +152,7 @@ void IpsParDef(void *object)
|
||||
|
||||
ParName("persmode");
|
||||
ParAccess(usUser);
|
||||
ParEnum(onOff);
|
||||
ParEnum(persMode);
|
||||
ParList(0);
|
||||
ParInt(&drv->persmode, 1);
|
||||
|
||||
@ -182,11 +193,43 @@ void IpsParDef(void *object)
|
||||
ParTail("Tesla/min");
|
||||
ParFloat(&drv->ramp, 1.0);
|
||||
|
||||
ParName("perscurrent");
|
||||
ParAccess(usUser);
|
||||
ParFmt(drv->fmt);
|
||||
ParTail("Tesla");
|
||||
ParFloat(&drv->perscurrent, 0.0);
|
||||
|
||||
ParName("perslimit");
|
||||
ParAccess(usUser);
|
||||
ParFmt(drv->fmt);
|
||||
ParTail("Tesla");
|
||||
ParFloat(&drv->perslimit, 10.0);
|
||||
|
||||
ParName("perswait");
|
||||
ParAccess(usUser);
|
||||
ParTail("sec");
|
||||
ParInt(&drv->perswait, 1800);
|
||||
|
||||
ParName("persdelay");
|
||||
ParAccess(usUser);
|
||||
ParTail("sec");
|
||||
ParInt(&drv->persdelay, 1800);
|
||||
|
||||
ParName("current");
|
||||
ParFmt(drv->fmt);
|
||||
ParTail("Tesla equivalent");
|
||||
ParFloat(&drv->current, PAR_NAN);
|
||||
|
||||
ParName("measured");
|
||||
ParFmt(drv->fmt);
|
||||
ParTail("Amps");
|
||||
ParFloat(&drv->measured, PAR_NAN);
|
||||
|
||||
ParName("voltage");
|
||||
ParFmt(drv->fmt);
|
||||
ParTail("Volt");
|
||||
ParFloat(&drv->voltage, PAR_NAN);
|
||||
|
||||
ParName("lastfield");
|
||||
ParSave(1);
|
||||
ParFloat(&drv->lastfield, PAR_NAN);
|
||||
@ -256,12 +299,15 @@ static void IpsStatus(Ips * drv)
|
||||
return;
|
||||
}
|
||||
if (ans[6] != '3') {
|
||||
if (drv->remote == 2) {
|
||||
if (drv->remote == 2) { /* remote state monitoring local switch */
|
||||
ParPrintf(drv, eError, "IPS switched to local");
|
||||
*code = EASE_FAULT;
|
||||
drv->remote = 1;
|
||||
drv->remote = 3; /* signal to switch back to C0 local locked */
|
||||
return;
|
||||
}
|
||||
if (ans[6] == '1') {
|
||||
drv->remote = 3; /* signal to switch back to C0 local locked */
|
||||
}
|
||||
if (drv->d.hwstate == HWBusy && drv->d.b.doit == NULL) {
|
||||
drv->d.hwstate = HWIdle;
|
||||
drv->d.stopped = 0;
|
||||
@ -280,6 +326,9 @@ static void IpsStatus(Ips * drv)
|
||||
if (swi != drv->perswitch || drv->swtim == 0) {
|
||||
drv->swtim = time(NULL);
|
||||
drv->perswitch = swi;
|
||||
if (drv->perswitch && drv->dothis == RAMP_ALMOST) {
|
||||
drv->dothis = NOTHING;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -302,6 +351,7 @@ static long IpsRead(long pc, void *object)
|
||||
{
|
||||
Ips *drv = ParCast(&ipsClass, object);
|
||||
EaseBase *eab = object;
|
||||
time_t expire, now;
|
||||
|
||||
switch (pc) {
|
||||
default: /* FSM BEGIN ****************************** */
|
||||
@ -310,20 +360,153 @@ static long IpsRead(long pc, void *object)
|
||||
return __LINE__;
|
||||
case __LINE__: /**********************************/
|
||||
IpsStatus(drv);
|
||||
rd:
|
||||
|
||||
EaseWrite(eab, "R7"); /* read current (in Tesla) */
|
||||
return __LINE__;
|
||||
case __LINE__: /**********************************/
|
||||
drv->current = OxiGet(eab, 3, NULL, drv->current);
|
||||
|
||||
EaseWrite(eab, "R2"); /* read measured current (in amps) */
|
||||
return __LINE__;
|
||||
case __LINE__: /**********************************/
|
||||
drv->measured = OxiGet(eab, 3, NULL, drv->measured);
|
||||
|
||||
EaseWrite(eab, "R1"); /* read measured voltage */
|
||||
return __LINE__;
|
||||
case __LINE__: /**********************************/
|
||||
drv->voltage = OxiGet(eab, 3, NULL, drv->voltage);
|
||||
|
||||
if (drv->perswitch) {
|
||||
IpsSetField(drv, drv->current);
|
||||
goto quit;
|
||||
goto checktodo;
|
||||
}
|
||||
EaseWrite(eab, "R18"); /* read persistant field (in Tesla) */
|
||||
return __LINE__;
|
||||
case __LINE__: /**********************************/
|
||||
IpsSetField(drv, OxiGet(eab, 3, NULL, drv->persfield));
|
||||
|
||||
checktodo:
|
||||
now = time(NULL);
|
||||
if (drv->persmode == 2) { /* persistent mode off */
|
||||
drv->dothis = NOTHING;
|
||||
goto nothing;
|
||||
} else {
|
||||
if (drv->perswitch) {
|
||||
if (drv->persmode == 1 || now > drv->tim + drv->persdelay) {
|
||||
drv->dothis = SWITCH_OFF;
|
||||
} else {
|
||||
drv->dothis = NOTHING;
|
||||
goto nothing;
|
||||
}
|
||||
} else if (drv->dothis == RAMP_ALMOST) {
|
||||
if (now > drv->tim + drv->perswait) {
|
||||
drv->dothis = RAMP_ZERO;
|
||||
} else {
|
||||
goto nothing;
|
||||
}
|
||||
} else if (drv->dothis == SWITCH_OFF) {
|
||||
if (now > drv->swtim + 30) {
|
||||
drv->dothis = RAMP_DOWN;
|
||||
} else {
|
||||
goto nothing;
|
||||
}
|
||||
} else {
|
||||
goto nothing;
|
||||
}
|
||||
}
|
||||
|
||||
EaseWrite(eab, "C3");
|
||||
drv->remote = 1; /* remote state */
|
||||
return __LINE__;
|
||||
case __LINE__: /**********************************/
|
||||
|
||||
switch (drv->dothis) {
|
||||
case SWITCH_OFF: goto switch_off;
|
||||
case RAMP_DOWN: goto ramp_down;
|
||||
case RAMP_ZERO: goto ramp_zero;
|
||||
}
|
||||
/* we should never get here */
|
||||
goto quit;
|
||||
|
||||
switch_off:
|
||||
EaseWrite(eab, "H0");
|
||||
drv->perswitch = 0;
|
||||
drv->swtim = time(NULL);
|
||||
drv->lastfield = drv->current;
|
||||
EaseParHasChanged();
|
||||
return __LINE__;
|
||||
case __LINE__: /**********************************/
|
||||
ParPrintf(drv, -1, "IPS: go to persistent mode, wait 30 sec for switch");
|
||||
goto localLocked;
|
||||
|
||||
ramp_down:
|
||||
if (drv->current == 0)
|
||||
goto localLocked;
|
||||
if (drv->perscurrent == 0 || drv->persfield < drv->perslimit) {
|
||||
drv->dothis = RAMP_ZERO;
|
||||
goto ramp_zero;
|
||||
}
|
||||
|
||||
OxiSet(eab, "J", drv->perscurrent, 3); /* put set point to a low value, above the CLACK value */
|
||||
return __LINE__;
|
||||
case __LINE__:
|
||||
EaseWrite(eab, "A1"); /* goto set (almost zero) */
|
||||
ParPrintf(drv, -1, "IPS: ramp current to %f (almost zero)", drv->perscurrent);
|
||||
return __LINE__;
|
||||
case __LINE__: /**********************************/
|
||||
drv->tim = time(NULL);
|
||||
drv->dothis = RAMP_ALMOST;
|
||||
goto localLocked;
|
||||
|
||||
ramp_zero:
|
||||
EaseWrite(eab, "A2"); /* goto zero */
|
||||
ParPrintf(drv, -1, "IPS: ramp current to 0");
|
||||
drv->dothis = RAMPED_DOWN;
|
||||
return __LINE__;
|
||||
case __LINE__: /**********************************/
|
||||
goto localLocked;
|
||||
|
||||
nothing:
|
||||
if (drv->remote != 3) /* NOT signal to switch back to local locked */
|
||||
goto quit;
|
||||
|
||||
localLocked:
|
||||
EaseWrite(eab, "C0");
|
||||
drv->remote = 0; /* local state */
|
||||
return __LINE__;
|
||||
case __LINE__: /**********************************/
|
||||
|
||||
quit:
|
||||
ParLog(drv);
|
||||
return 0;
|
||||
} /* FSM END ******************************************* */
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static long IpsMeas(long pc, void *object)
|
||||
{
|
||||
Ips *drv = ParCast(&ipsClass, object);
|
||||
EaseBase *eab = object;
|
||||
|
||||
switch (pc) {
|
||||
default: /* FSM BEGIN ****************************** */
|
||||
EasePchk(drv);
|
||||
EaseWrite(eab, "X");
|
||||
return __LINE__;
|
||||
case __LINE__: /**********************************/
|
||||
IpsStatus(drv);
|
||||
|
||||
EaseWrite(eab, "R2"); /* read measured current (in amps) */
|
||||
return __LINE__;
|
||||
case __LINE__: /**********************************/
|
||||
drv->measured = OxiGet(eab, 3, NULL, drv->measured);
|
||||
|
||||
EaseWrite(eab, "R1"); /* read measured voltage */
|
||||
return __LINE__;
|
||||
case __LINE__: /**********************************/
|
||||
drv->voltage = OxiGet(eab, 3, NULL, drv->voltage);
|
||||
|
||||
quit:
|
||||
ParLog(drv);
|
||||
return 0;
|
||||
@ -359,6 +542,7 @@ static long IpsStart(long pc, void *object)
|
||||
} else {
|
||||
drv->fmt = "%.3f";
|
||||
}
|
||||
drv->tim = time(NULL);
|
||||
FsmCall(IpsRead);
|
||||
return __LINE__;
|
||||
case __LINE__: /**********************************/
|
||||
@ -388,7 +572,7 @@ static long IpsChangeField(long pc, void *object)
|
||||
drv->d.eMode = EVMonitor; /* finish drive, continue in background */
|
||||
}
|
||||
EaseWrite(eab, "C3");
|
||||
drv->remote = 1;
|
||||
drv->remote = 1; /* remote state */
|
||||
return __LINE__;
|
||||
case __LINE__: /**********************************/
|
||||
EaseWrite(eab, "F7"); /* switch to tesla on display */
|
||||
@ -397,10 +581,21 @@ static long IpsChangeField(long pc, void *object)
|
||||
EaseWrite(eab, "A0"); /* hold */
|
||||
return __LINE__;
|
||||
case __LINE__: /**********************************/
|
||||
FsmCall(IpsRead);
|
||||
|
||||
EaseWrite(eab, "R7"); /* read current (in Tesla) */
|
||||
return __LINE__;
|
||||
case __LINE__: /**********************************/
|
||||
drv->remote = 2;
|
||||
drv->current = OxiGet(eab, 3, NULL, drv->current);
|
||||
|
||||
EaseWrite(eab, "R18"); /* read persistant field (in Tesla) */
|
||||
return __LINE__;
|
||||
case __LINE__: /**********************************/
|
||||
IpsSetField(drv, OxiGet(eab, 3, NULL, drv->persfield));
|
||||
|
||||
FsmCall(IpsMeas);
|
||||
return __LINE__;
|
||||
case __LINE__: /**********************************/
|
||||
drv->remote = 2; /* remote state monitoring local switch */
|
||||
if (!IpsOk(drv))
|
||||
goto finish;
|
||||
if (drv->lastfield == PAR_NAN) {
|
||||
@ -409,7 +604,7 @@ static long IpsChangeField(long pc, void *object)
|
||||
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->persmode == 1) {
|
||||
if (!drv->perswitch)
|
||||
goto finish;
|
||||
goto target_reached;
|
||||
@ -432,15 +627,15 @@ static long IpsChangeField(long pc, void *object)
|
||||
drv->tim = time(NULL);
|
||||
|
||||
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, drv->current);
|
||||
ParLog(drv);
|
||||
|
||||
FsmCall(IpsMeas);
|
||||
return __LINE__;
|
||||
case __LINE__: /**********************************/
|
||||
|
||||
if (fabs(drv->current - drv->lastfield) > 1e-5)
|
||||
goto stab1;
|
||||
|
||||
@ -448,10 +643,11 @@ static long IpsChangeField(long pc, void *object)
|
||||
FsmWait(1);
|
||||
return __LINE__;
|
||||
case __LINE__: /**********************************/
|
||||
EaseWrite(eab, "X");
|
||||
|
||||
FsmCall(IpsMeas);
|
||||
return __LINE__;
|
||||
case __LINE__: /**********************************/
|
||||
IpsStatus(drv);
|
||||
|
||||
if (time(NULL) < drv->tim + 10)
|
||||
goto stab2; /* stabilize */
|
||||
|
||||
@ -467,30 +663,33 @@ static long IpsChangeField(long pc, void *object)
|
||||
return __LINE__;
|
||||
case __LINE__: /**********************************/
|
||||
drv->perswitch = 1;
|
||||
drv->dothis = NOTHING;
|
||||
drv->swtim = time(NULL);
|
||||
|
||||
wait_open:
|
||||
delay = drv->swtim + 30 - time(NULL);
|
||||
delay = drv->swtim + 15 - time(NULL);
|
||||
if (delay > 0)
|
||||
ParPrintf(drv, -1, "IPS: wait %d sec to open switch", delay);
|
||||
|
||||
start_ramp:
|
||||
ParLog(drv);
|
||||
start_ramp:
|
||||
FsmWait(1);
|
||||
return __LINE__;
|
||||
case __LINE__: /**********************************/
|
||||
EaseWrite(eab, "X");
|
||||
|
||||
FsmCall(IpsMeas);
|
||||
return __LINE__;
|
||||
case __LINE__: /**********************************/
|
||||
IpsStatus(drv); /* check for errors */
|
||||
|
||||
if (drv->heaterFault) {
|
||||
if (time(NULL) > drv->swtim + 3) {
|
||||
ParPrintf(drv, eError, "IPS heater fault");
|
||||
ParPrintf(drv, eError, "IPS: switch heater not connected");
|
||||
eab->errCode = EASE_FAULT;
|
||||
goto off_finish;
|
||||
}
|
||||
}
|
||||
if (time(NULL) < drv->swtim + 30)
|
||||
|
||||
if (time(NULL) < drv->swtim + 15)
|
||||
goto start_ramp; /* wait */
|
||||
OxiSet(eab, "T", drv->ramp, 3);
|
||||
return __LINE__;
|
||||
@ -512,15 +711,16 @@ static long IpsChangeField(long pc, void *object)
|
||||
return __LINE__;
|
||||
case __LINE__: /**********************************/
|
||||
IpsSetField(drv, OxiGet(eab, 3, NULL, drv->current)); /* set drv->current and callback */
|
||||
EaseWrite(eab, "X");
|
||||
|
||||
FsmCall(IpsMeas);
|
||||
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, drv->ramp);
|
||||
step = ramp / 6; /* step = ramp * 10 sec */
|
||||
step = ramp / 3; /* step = ramp * 20 sec */
|
||||
if (step < 0.001)
|
||||
step = 0.001;
|
||||
if (drv->d.targetValue > drv->current + step) {
|
||||
@ -540,60 +740,24 @@ static long IpsChangeField(long pc, void *object)
|
||||
target_reached:
|
||||
drv->d.hwstate = HWIdle;
|
||||
drv->d.eMode = EVMonitor; /* we are at field, drive has finished */
|
||||
if (!drv->persmode)
|
||||
if (drv->persmode != 1)
|
||||
goto hold_finish;
|
||||
/* but we continue in the background */
|
||||
drv->tim = time(NULL);
|
||||
stab3:
|
||||
ParLog(drv);
|
||||
FsmWait(1);
|
||||
return __LINE__;
|
||||
case __LINE__: /**********************************/
|
||||
EaseWrite(eab, "X");
|
||||
|
||||
FsmCall(IpsMeas);
|
||||
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:
|
||||
ParLog(drv);
|
||||
FsmWait(1);
|
||||
return __LINE__;
|
||||
case __LINE__: /**********************************/
|
||||
EaseWrite(eab, "R18"); /* read persistent field in Tesla */
|
||||
return __LINE__;
|
||||
case __LINE__: /**********************************/
|
||||
fld = OxiGet(eab, 3, NULL, drv->current);
|
||||
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 (drv->current == 0)
|
||||
goto finish;
|
||||
EaseWrite(eab, "A2"); /* goto zero */
|
||||
ParPrintf(drv, -1, "IPS: ramp current to 0");
|
||||
return __LINE__;
|
||||
case __LINE__: /**********************************/
|
||||
goto finish;
|
||||
|
||||
@ -614,8 +778,9 @@ static long IpsChangeField(long pc, void *object)
|
||||
|
||||
finish:
|
||||
EaseWrite(eab, "C0");
|
||||
drv->remote = 0;
|
||||
drv->remote = 0; /* local state */
|
||||
drv->d.hwstate = HWIdle;
|
||||
drv->tim = time(NULL); /* time of last field change */
|
||||
return __LINE__;
|
||||
case __LINE__: /**********************************/
|
||||
|
||||
@ -640,6 +805,7 @@ static int IpsInit(SConnection * con, int argc, char *argv[], int dynamic)
|
||||
return 0;
|
||||
drv->d.maxwait = 999999;
|
||||
drv->d.tolerance = 0.001;
|
||||
drv->dothis = NOTHING;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -262,7 +262,7 @@ static void Lsc370ParDef(void *object)
|
||||
ParName("maxPower");
|
||||
ParTail("mW");
|
||||
power = Lsc370Power(drv, 100.0);
|
||||
ParFmt("%.0g");
|
||||
ParFmt("%.3g");
|
||||
ParFloat(&power, 0.0);
|
||||
|
||||
ParName("power");
|
||||
|
3
make_gen
3
make_gen
@ -29,7 +29,8 @@ OBJ=psi.o buffer.o ruli.o sps.o pimotor.o charbychar.o\
|
||||
|
||||
MZOBJ=fsm.o sugar.o pardef.o ease.o strobj.o oxinst.o \
|
||||
ipsdriv.o ilmdriv.o itcdriv.o ighdriv.o euro2kdriv.o modbus.o arrobj.o \
|
||||
lscsupport.o lsc370driv.o linadriv.o haakedriv.o amilevel.o binprot.o
|
||||
lscsupport.o lsc370driv.o linadriv.o haakedriv.o amilevel.o binprot.o \
|
||||
cnvrt.o
|
||||
|
||||
libpsi.a: $(OBJ)
|
||||
rm -f libpsi.a
|
||||
|
60
modbus.c
60
modbus.c
@ -18,67 +18,9 @@ is not changed, i.e. an existing errCode is not overwritten.
|
||||
#include <math.h>
|
||||
#include "sics.h"
|
||||
#include "modbus.h"
|
||||
#include "cnvrt.h"
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static void double2ieee(double input, char ieee[4])
|
||||
{
|
||||
|
||||
/* convert double to IEEE 32 bit floating number (denormalized numbers are considered as zero) */
|
||||
|
||||
long mantissa;
|
||||
int exponent;
|
||||
|
||||
if (input == 0) {
|
||||
ieee[0] = 0;
|
||||
ieee[1] = 0;
|
||||
ieee[2] = 0;
|
||||
ieee[3] = 0;
|
||||
} else {
|
||||
mantissa = 0x1000000 * (frexp(fabs(input), &exponent));
|
||||
exponent = exponent - 1 + 127;
|
||||
if (exponent < 0) {
|
||||
exponent = 0;
|
||||
} else if (exponent > 0xFE) {
|
||||
exponent = 0xFE;
|
||||
}
|
||||
if (input < 0) {
|
||||
ieee[0] = 0x80 | (exponent >> 1);
|
||||
} else {
|
||||
ieee[0] = exponent >> 1;
|
||||
}
|
||||
ieee[1] = (exponent & 1) << 7 | ((mantissa & 0x7F0000) >> 16);
|
||||
ieee[2] = (mantissa & 0xFF00) >> 8;
|
||||
ieee[3] = mantissa & 0xFF;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static double ieee2double(char ieee[4])
|
||||
{
|
||||
|
||||
/* IEEE 32 bit floating number to double (denormalized numbers are considered as zero) */
|
||||
|
||||
long mantissa;
|
||||
double output;
|
||||
int exponent;
|
||||
|
||||
mantissa = ((ieee[1] << 16) & 0x7FFFFF)
|
||||
| ((ieee[2] << 8) & 0xFF00)
|
||||
| ((ieee[3]) & 0xFF);
|
||||
|
||||
exponent = (ieee[0] & 0x7F) * 2 + ((ieee[1] >> 7) & 1); /* raw exponent */
|
||||
if (exponent == 0 && mantissa == 0) {
|
||||
return 0.0;
|
||||
}
|
||||
output = ldexp(mantissa, -23) + 1.0;
|
||||
if (ieee[0] & 0x80) {
|
||||
output = -output;
|
||||
}
|
||||
return output * ldexp(1, exponent - 127);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static void uint2word(unsigned int adr, char word[2])
|
||||
{
|
||||
|
2
pardef.c
2
pardef.c
@ -151,7 +151,7 @@ int ParPrintf(void *object, int iOut, const char *fmt, ...)
|
||||
return 0; /* no connection, no verbose output */
|
||||
if (-iOut > pobj->verbose)
|
||||
return 0; /* check verbosity level */
|
||||
iOut = eValue;
|
||||
iOut = eLog;
|
||||
}
|
||||
|
||||
va_start(ap, fmt);
|
||||
|
1
psi.c
1
psi.c
@ -123,6 +123,7 @@ static void AddPsiCommands(SicsInterp * pInter)
|
||||
SCMD("MakeTRICSSupport", MakeTricsSupport);
|
||||
SCMD("PolterInstall", PolterInstall);
|
||||
SCMD("SerialInit", SerialInit);
|
||||
PCMD("cnvrt", CnvrtAction);
|
||||
/*
|
||||
SCMD("MakeDifrac",MakeDifrac);
|
||||
*/
|
||||
|
@ -77,6 +77,9 @@ $(CFGDIR)cma11r4rc.crv: ccrv inp/cma11r4rc.inp
|
||||
$(CFGDIR)cma6.crv: ccrv inp/cma6.inp
|
||||
$Q -p$(CFGDIR)
|
||||
|
||||
$(CFGDIR)cma7.crv: ccrv inp/cma7.inp
|
||||
$Q -p$(CFGDIR)
|
||||
|
||||
$(CFGDIR)cplus45.crv: ccrv inp/cplus45.inp
|
||||
$Q -p$(CFGDIR)
|
||||
|
||||
@ -380,6 +383,15 @@ $(CFGDIR)x58599.crv: ccrv inp/x58599.inp
|
||||
$(CFGDIR)x58600.crv: ccrv inp/x58600.inp
|
||||
$Q -p$(CFGDIR)
|
||||
|
||||
$(CFGDIR)x68061.crv: ccrv inp/x68061.inp
|
||||
$Q -p$(CFGDIR)
|
||||
|
||||
$(CFGDIR)x68258.crv: ccrv inp/x68258.inp
|
||||
$Q -p$(CFGDIR)
|
||||
|
||||
$(CFGDIR)x68433.crv: ccrv inp/x68433.inp
|
||||
$Q -p$(CFGDIR)
|
||||
|
||||
$(CFGDIR)z030114.crv: ccrv inp/z030114.inp
|
||||
$Q -p$(CFGDIR)
|
||||
|
||||
@ -410,6 +422,7 @@ all_crv: dev.list \
|
||||
$(CFGDIR)cma11r3lc.crv \
|
||||
$(CFGDIR)cma11r4rc.crv \
|
||||
$(CFGDIR)cma6.crv \
|
||||
$(CFGDIR)cma7.crv \
|
||||
$(CFGDIR)cplus45.crv \
|
||||
$(CFGDIR)cplus70.crv \
|
||||
$(CFGDIR)cs405.crv \
|
||||
@ -511,6 +524,9 @@ all_crv: dev.list \
|
||||
$(CFGDIR)x55918.crv \
|
||||
$(CFGDIR)x58599.crv \
|
||||
$(CFGDIR)x58600.crv \
|
||||
$(CFGDIR)x68061.crv \
|
||||
$(CFGDIR)x68258.crv \
|
||||
$(CFGDIR)x68433.crv \
|
||||
$(CFGDIR)z030114.crv \
|
||||
|
||||
ALLINP= \
|
||||
@ -540,6 +556,7 @@ inp/cma11r2ol.inp \
|
||||
inp/cma11r3lc.inp \
|
||||
inp/cma11r4rc.inp \
|
||||
inp/cma6.inp \
|
||||
inp/cma7.inp \
|
||||
inp/cplus45.inp \
|
||||
inp/cplus70.inp \
|
||||
inp/cs405.inp \
|
||||
@ -641,5 +658,8 @@ inp/x55606.inp \
|
||||
inp/x55918.inp \
|
||||
inp/x58599.inp \
|
||||
inp/x58600.inp \
|
||||
inp/x68061.inp \
|
||||
inp/x68258.inp \
|
||||
inp/x68433.inp \
|
||||
inp/z030114.inp \
|
||||
|
||||
|
91
tecs/tecs.c
91
tecs/tecs.c
@ -187,6 +187,7 @@ static int
|
||||
switch heater range on when controller switched it off */
|
||||
initMaxPower=0, /* set MaxPower for the first time */
|
||||
unit=1, /* 1: Kelvin, 2: Celsius */
|
||||
autoconfig=1,
|
||||
lockAlarm,
|
||||
cntError;
|
||||
|
||||
@ -216,6 +217,8 @@ static char
|
||||
devHelp[10000],
|
||||
update[32], /* update script option */
|
||||
lscfg[256], /* lsc commands for configuration */
|
||||
devname0[64], /* name of plugs from codes */
|
||||
devname1[64],
|
||||
maxPower[128],
|
||||
controlChannel[4]="A";
|
||||
|
||||
@ -501,7 +504,7 @@ int InstalCurve(SensorT *sensor, char *devArg) {
|
||||
str_upcase(head, chead);
|
||||
ERR_P(LscCmd(ser, "CRVHDR [num]:[head];INCRV [chan]:[num];MNMX [chan]:1,[unit]"));
|
||||
logfileOut(LOG_MAIN, "curve %d selected on channel %s\n", num, chan);
|
||||
saveTime=tim+30;
|
||||
saveTime = (tim/3600/24 + 1) * 3600*24; /* save at midnight GMT */
|
||||
}
|
||||
FREE(crv); crv=NULL;
|
||||
|
||||
@ -1926,9 +1929,17 @@ int ConfigByCode(int plugNr) {
|
||||
plug->devcmd=0;
|
||||
ConcatDevice();
|
||||
if (plug->code==0) {
|
||||
logfileOut(LOG_MAIN ,"reset inputs on plug%d\n", plugNr);
|
||||
plug->sensor1->present=0;
|
||||
plug->sensor2->present=0;
|
||||
if (autoconfig) {
|
||||
logfileOut(LOG_MAIN ,"reset inputs on plug%d\n", plugNr);
|
||||
plug->sensor1->present=0;
|
||||
plug->sensor2->present=0;
|
||||
} else {
|
||||
if (plugNr == 0) {
|
||||
str_copy(devname0, "none");
|
||||
} else {
|
||||
str_copy(devname1, "none");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
str_copy(buf, binDir);
|
||||
str_append(buf, LSC_CODES);
|
||||
@ -1947,11 +1958,20 @@ int ConfigByCode(int plugNr) {
|
||||
logfileOut(LOG_MAIN+LOG_STAT ,"unknown code %d on plug%d\n", plug->code, plugNr);
|
||||
return 0;
|
||||
} else {
|
||||
logfileOut(LOG_MAIN+LOG_STAT ,"configure plug%d for %s (code %d)\n", plugNr, nam, plug->code);
|
||||
str_copy(buf, "'");
|
||||
str_append(buf, nam);
|
||||
str_append(buf, "'");
|
||||
ERR_I(PrepInput(buf));
|
||||
if (autoconfig) {
|
||||
logfileOut(LOG_MAIN+LOG_STAT ,"configure plug%d for %s (code %d)\n", plugNr, nam, plug->code);
|
||||
str_copy(buf, "'");
|
||||
str_append(buf, nam);
|
||||
str_append(buf, "'");
|
||||
ERR_I(PrepInput(buf));
|
||||
} else {
|
||||
logfileOut(LOG_MAIN+LOG_STAT ,"%s on plug%d (code %d)\n", nam, plugNr, plug->code);
|
||||
if (plugNr == 0) {
|
||||
str_copy(devname0, nam);
|
||||
} else {
|
||||
str_copy(devname1, nam);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
settingsFlag=1;
|
||||
@ -2296,6 +2316,7 @@ int PeriodicTask(void) {
|
||||
str_copy(plug0.device, buf1+1);
|
||||
plug0.codChanged=0;
|
||||
ConfigByName(0);
|
||||
if (autoconfig == 0) ConfigByCode(0);
|
||||
} else {
|
||||
if (plug0.code!=0) str_copy(plug0.device, buf1);
|
||||
plug0.devcmd=0;
|
||||
@ -2304,6 +2325,7 @@ int PeriodicTask(void) {
|
||||
str_copy(plug1.device, buf2+1);
|
||||
plug1.codChanged=0;
|
||||
ConfigByName(1);
|
||||
if (autoconfig == 0) ConfigByCode(1);
|
||||
} else {
|
||||
if (plug1.code!=0) str_copy(plug1.device, buf2);
|
||||
plug1.devcmd=0;
|
||||
@ -2554,29 +2576,32 @@ int PeriodicTask(void) {
|
||||
}
|
||||
}
|
||||
|
||||
if ((plug0.code1 & 0x2a) == 0x20) {
|
||||
sensA0.t = DATA_UNDEF;
|
||||
sensA1.t = DATA_UNDEF;
|
||||
sensA2.t = DATA_UNDEF;
|
||||
sensA3.t = DATA_UNDEF;
|
||||
switch ((int)scanChan) {
|
||||
case 0: sensA0.t = te; break;
|
||||
case 1: sensA1.t = te; break;
|
||||
case 2: sensA2.t = te; break;
|
||||
case 3: sensA3.t = te; break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
/* obsolete
|
||||
* if ((plug0.code1 & 0x2a) == 0x20) {
|
||||
* sensA0.t = DATA_UNDEF;
|
||||
* sensA1.t = DATA_UNDEF;
|
||||
* sensA2.t = DATA_UNDEF;
|
||||
* sensA3.t = DATA_UNDEF;
|
||||
* switch ((int)scanChan) {
|
||||
* case 0: sensA0.t = te; break;
|
||||
* case 1: sensA1.t = te; break;
|
||||
* case 2: sensA2.t = te; break;
|
||||
* case 3: sensA3.t = te; break;
|
||||
* default: break;
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
if (out1==30 && out2==29) {
|
||||
/* code conversion */
|
||||
plug0.code1=3*decod[cod2 % 8] ^ 2*decod[cod1 % 8]; /* ^ is exclusive OR */
|
||||
if ((plug0.code1 & 0x2a) == 0x20) {
|
||||
/* for external switch (MA09) */
|
||||
scanChan = cod1 & 0x03;
|
||||
plug0.code1 = plug0.code1 & 0x30;
|
||||
} else {
|
||||
scanChan = DATA_UNDEF;
|
||||
}
|
||||
/* obsolete, for external switch (MA09)
|
||||
* if ((plug0.code1 & 0x2a) == 0x20) {
|
||||
* scanChan = cod1 & 0x03;
|
||||
* plug0.code1 = plug0.code1 & 0x30;
|
||||
* } else {
|
||||
* scanChan = DATA_UNDEF;
|
||||
* }
|
||||
*/
|
||||
plug1.code1=-(3*decod[cod2 / 8] ^ 2*decod[cod1 / 8]);
|
||||
for (i=0; i<2; i++) {
|
||||
plug=plugs[i];
|
||||
@ -2949,7 +2974,7 @@ int StillHdl(int mode, void *base, int fd) {
|
||||
return COC_DWR;
|
||||
} else if (mode==COC_DWR) {
|
||||
fbuf=still;
|
||||
ERR_P(LscCmd(ser,"ANALOG 1:0,2,,,,,[fbuf]"));
|
||||
ERR_P(LscCmd(ser,"ANALOG 1:1,2,,,,,[fbuf]"));
|
||||
}
|
||||
return 0;
|
||||
OnError: return -1;
|
||||
@ -3500,6 +3525,7 @@ int main(int argc, char *argv[]) {
|
||||
CocDefInt(rdTim, RD);
|
||||
CocDefInt(tim0, RD);
|
||||
CocDefInt(ibuf, RD);
|
||||
CocDefInt(autoconfig, RW);
|
||||
|
||||
CocDefInt(logMask, RW);
|
||||
CocDefInt(logPeriod, RW);
|
||||
@ -3520,6 +3546,8 @@ int main(int argc, char *argv[]) {
|
||||
CocDefStr(grapar, RA);
|
||||
CocDefArr(gradata, RD); CocHdl(GraHdl); grasize=CocSizePtr();
|
||||
|
||||
CocDefStr(devname0, RW);
|
||||
CocDefStr(devname1, RW);
|
||||
CocAlias(tempX,cryo.temp);
|
||||
CocAlias(tempP,samp.temp);
|
||||
CocAlias(Ta,sensA.t);
|
||||
@ -3560,6 +3588,9 @@ int main(int argc, char *argv[]) {
|
||||
} else if ('s'==opt) {
|
||||
use_stdout=1;
|
||||
opt=' ';
|
||||
} else if ('a'==opt) {
|
||||
autoconfig=0;
|
||||
opt=' ';
|
||||
} else if ('n'==opt) {
|
||||
i++;
|
||||
str_copy(serverId, argv[i]);
|
||||
|
@ -49,7 +49,7 @@ char *LscCmd(SerChannel *ser, const char *cmds) {
|
||||
char cmd[SER_BUF_LEN];
|
||||
char varname[32];
|
||||
DeclStrBuf(sbuf, SER_BUF_LEN);
|
||||
int nres, i, response;
|
||||
int nres, i, response, try;
|
||||
|
||||
nres=0;
|
||||
response=0;
|
||||
@ -111,8 +111,18 @@ char *LscCmd(SerChannel *ser, const char *cmds) {
|
||||
} else {
|
||||
sbuf.buf[sbuf.wrpos-1]='\0'; /* strip off trailing ";" */
|
||||
}
|
||||
ERR_P(res=SerCmd(ser, sbuf.buf));
|
||||
if (0==strncmp("?TMO", res, 4)) ERR_MSG("timeout");
|
||||
|
||||
try = 3;
|
||||
while (1) {
|
||||
ERR_P(res=SerCmd(ser, sbuf.buf));
|
||||
if (0!=strncmp("?TMO", res, 4)) {
|
||||
break;
|
||||
}
|
||||
try--;
|
||||
if (try <= 0) {
|
||||
ERR_MSG("timeout");
|
||||
}
|
||||
}
|
||||
/*
|
||||
list[0..nres-1] contains a now:
|
||||
for a command with return request:
|
||||
|
@ -212,7 +212,11 @@ char *SerCmd(SerChannel *serch, char *cmnd) {
|
||||
/* Wait for an event on tser->fd or a timeout tmo */
|
||||
iret=tser->idleHdl(tser->tmo, tser->fd);
|
||||
if (iret==0) {
|
||||
if (result==NULL) ERR_MSG("timeout");
|
||||
if (result==NULL) {
|
||||
result="?TMO";
|
||||
return result;
|
||||
}
|
||||
/* if (result==NULL) ERR_MSG("timeout"); */
|
||||
ERR_MSG("missing terminator");
|
||||
}
|
||||
ERR_SI(l=recv(tser->fd, pos, n, 0));
|
||||
|
Reference in New Issue
Block a user