197 lines
5.1 KiB
C
197 lines
5.1 KiB
C
/*---------------------------------------------------------------------------
|
|
oxinst.c
|
|
|
|
Communication routines for Oxford Instruments equipment
|
|
|
|
Markus Zolliker, March 2005
|
|
----------------------------------------------------------------------------
|
|
|
|
there is no error return value, eab->errCode is used. On success, eab->errCode
|
|
is not changed, i.e. an existing errCode is not overwritten.
|
|
*/
|
|
|
|
#include <string.h>
|
|
#include <math.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <assert.h>
|
|
#include <fortify.h>
|
|
#include "sics.h"
|
|
#include "oxinst.h"
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
char *OxiCorrect(char *str)
|
|
{
|
|
/* there are sometimes communication errors with the IGH
|
|
as the errors always follow the same pattern, they can
|
|
be corrected, with the following code. The argument
|
|
is corrected in place, the result is NULL or a text
|
|
describing the conversion */
|
|
int i;
|
|
unsigned char chr;
|
|
static char buf[32];
|
|
char *result = NULL;
|
|
|
|
if (str[0] == '?')
|
|
return NULL;
|
|
for (i = 0; i <= 24; i++, str++) {
|
|
chr = *str;
|
|
if (chr == 0)
|
|
return result;
|
|
if (chr > 0x60) {
|
|
if (chr > 0xC0) {
|
|
chr -= 0x80;
|
|
} else {
|
|
chr -= 0x40;
|
|
}
|
|
snprintf(buf, sizeof buf, "%2.2x->%2.2x (%c)", (unsigned char) *str,
|
|
chr, chr);
|
|
*str = chr;
|
|
result = buf;
|
|
}
|
|
}
|
|
if (result) {
|
|
strcat(buf, " overflow");
|
|
return result;
|
|
} else {
|
|
return "overflow";
|
|
}
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
int OxiHandler(void *object)
|
|
{
|
|
int iret, l;
|
|
EaseBase *eab = EaseBaseCast(object);
|
|
char *corr;
|
|
|
|
if (eab->state < EASE_idle)
|
|
goto quit;
|
|
if (availableNetRS232(eab->ser) || availableRS232(eab->ser)) {
|
|
if (strncmp(eab->msg, "ERROR:", 6) != 0) {
|
|
eab->msg[0] = '\0';
|
|
}
|
|
l = sizeof(eab->ans);
|
|
iret = readRS232TillTerm(eab->ser, eab->ans, &l);
|
|
if (eab->state != EASE_expect && eab->state != EASE_lost) {
|
|
if (iret == 1) {
|
|
ParPrintf(eab, eError, "unexpected answer: %s", eab->ans);
|
|
}
|
|
goto quit;
|
|
}
|
|
if (iret == 1) {
|
|
ParPrintf(eab, -2, "ans: %s", eab->ans);
|
|
if (strcmp(eab->ans, "??ck") == 0) {
|
|
if (eab->state == EASE_lost) {
|
|
EaseWrite(eab, "V");
|
|
}
|
|
goto quit;
|
|
} else if (eab->state == EASE_lost) {
|
|
goto quit;
|
|
} else if (eab->cmd[0] == 'V') {
|
|
if (strcmp(eab->ans, eab->version) == 0) {
|
|
/* we are still connected with the same device */
|
|
} else if (*eab->version == '\0') {
|
|
strlcpy(eab->version, eab->ans, sizeof(eab->version));
|
|
} else { /* version (and therefore device) changed */
|
|
eab->errCode = EASE_DEV_CHANGED;
|
|
eab->state = EASE_idle;
|
|
eab->version[0] = '\0';
|
|
goto error;
|
|
}
|
|
eab->state = EASE_idle;
|
|
goto quit;
|
|
} else if (eab->cmd[2] == 'k') { /* ?ck */
|
|
} else {
|
|
eab->tmo = 20; /* long timeout: the user may block the response with the adjust keys */
|
|
if (eab->syntax <= -8) { /* OLDIGH */
|
|
corr = OxiCorrect(eab->ans);
|
|
if (corr) {
|
|
/* ParPrintf(eab, eWarning, "corrected bad response from IGH: %s", corr); */
|
|
}
|
|
}
|
|
if (eab->cmd[0] != eab->ans[0] && eab->cmd[0] != '{') {
|
|
if (strcmp(eab->cmd, "H1\r") != 0 || strcmp(eab->ans, "?H1") != 0) {
|
|
iret = EASE_ILL_ANS;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (iret != 1) {
|
|
eab->errCode = iret;
|
|
eab->state = EASE_idle;
|
|
goto error;
|
|
}
|
|
eab->state = EASE_read;
|
|
} else if (eab->state == EASE_expect) {
|
|
if (time(NULL) > eab->chktime) {
|
|
writeRS232(eab->ser, "?ck", 3);
|
|
ParPrintf(eab, -2, "cmd: ?ck");
|
|
eab->chktime = time(NULL);
|
|
}
|
|
if (time(NULL) > eab->cmdtime + eab->tmo) {
|
|
eab->state = EASE_lost;
|
|
}
|
|
} else if (eab->state == EASE_lost) {
|
|
if (time(NULL) > eab->cmdtime) {
|
|
EaseWrite(eab, "?ck");
|
|
eab->state = EASE_lost;
|
|
}
|
|
}
|
|
goto quit;
|
|
error:
|
|
/* EaseWriteError(eab); */
|
|
quit:
|
|
return EaseHandler(eab);
|
|
}
|
|
|
|
double OxiGet(EaseBase * eab, int dig, int *pdig, double old)
|
|
{
|
|
char *endp, *p;
|
|
double val;
|
|
|
|
if (eab->state != EASE_read) {
|
|
eab->errCode = EASE_ILL_ANS;
|
|
return old;
|
|
}
|
|
p = strchr(eab->ans, '.');
|
|
if (p) {
|
|
if (pdig != NULL) {
|
|
*pdig = strlen(eab->ans) - (p - eab->ans) - 1;
|
|
}
|
|
val = strtod(eab->ans + 1, &endp);
|
|
if (*endp != '\0') {
|
|
eab->errCode = EASE_ILL_ANS;
|
|
return old;
|
|
}
|
|
} else {
|
|
val = strtol(eab->ans + 1, &endp, 10);
|
|
if (*endp != '\0') {
|
|
eab->errCode = EASE_ILL_ANS;
|
|
return old;
|
|
}
|
|
if (eab->syntax <= 0) { /* old style format */
|
|
for (; dig > 0; dig--)
|
|
val = val * 0.1;
|
|
}
|
|
}
|
|
return val;
|
|
}
|
|
|
|
void OxiSet(EaseBase * eab, char *cmd, double val, int dig)
|
|
{
|
|
char buf[64];
|
|
double f;
|
|
|
|
if (eab->syntax > 0) {
|
|
f = fabs(val);
|
|
if (f < 1.0)
|
|
f = 1.0;
|
|
dig = 7 - log10(f);
|
|
if (dig < 0)
|
|
dig = 0;
|
|
}
|
|
snprintf(buf, sizeof(buf), "%s%.*f", cmd, dig, val);
|
|
EaseWrite(eab, buf);
|
|
}
|