/*--------------------------------------------------------------------------- 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 #include #include #include #include #include #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); }