- new drivers
This commit is contained in:
147
euro2kdriv.c
Normal file
147
euro2kdriv.c
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
/*---------------------------------------------------------------------------
|
||||||
|
euro2kdriv.c
|
||||||
|
|
||||||
|
Driver for the EuroTherm 2000 controllers (ModBus protocoll)
|
||||||
|
|
||||||
|
Markus Zolliker, August 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 "modbus.h"
|
||||||
|
#include "fsm.h"
|
||||||
|
#include "initializer.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
EaseDriv d;
|
||||||
|
float temperature;
|
||||||
|
float output;
|
||||||
|
float setpoint;
|
||||||
|
int adr;
|
||||||
|
float par;
|
||||||
|
} Euro2k;
|
||||||
|
|
||||||
|
static ParClass euro2kClass = { "EURO2K", sizeof(Euro2k) };
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
void Euro2kParDef(void *object) {
|
||||||
|
Euro2k *drv = ParCast(&euro2kClass, object);
|
||||||
|
|
||||||
|
ParName(""); ParTail("C");
|
||||||
|
ParFloat(&drv->temperature, PAR_NAN);
|
||||||
|
|
||||||
|
ParName("output"); ParTail("%");
|
||||||
|
ParFloat(&drv->output, PAR_NAN);
|
||||||
|
|
||||||
|
ParName("setpoint"); ParTail("C");
|
||||||
|
ParFloat(&drv->setpoint, PAR_NAN);
|
||||||
|
|
||||||
|
ParName("adr"); ParAccess(usUser); ParList(NULL);
|
||||||
|
ParInt(&drv->adr, 0);
|
||||||
|
|
||||||
|
if (drv->adr > 0) {
|
||||||
|
ParName("par"); ParList(NULL);
|
||||||
|
ParFloat(&drv->par, PAR_NAN);
|
||||||
|
}
|
||||||
|
|
||||||
|
EaseBasePar(drv);
|
||||||
|
EaseDrivPar(drv, "%#.5g", "C");
|
||||||
|
ParStdDef();
|
||||||
|
EaseMsgPar(drv);
|
||||||
|
}
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
static long Euro2kRead(long pc, void *object) {
|
||||||
|
Euro2k *drv = ParCast(&euro2kClass, object);
|
||||||
|
EaseBase *eab = object;
|
||||||
|
char *p;
|
||||||
|
int l;
|
||||||
|
char buf[4];
|
||||||
|
|
||||||
|
switch (pc) { default: /* FSM BEGIN *******************************/
|
||||||
|
ModBusRequestFloats(eab, 1, 3);
|
||||||
|
return __LINE__; case __LINE__: /**********************************/
|
||||||
|
drv->temperature = ModBusGetFloat(eab, 1);
|
||||||
|
drv->setpoint = ModBusGetFloat(eab, 2);
|
||||||
|
drv->output = ModBusGetFloat(eab, 3);
|
||||||
|
|
||||||
|
if (drv->adr == 0) goto noPar;
|
||||||
|
ModBusRequestFloats(eab, drv->adr, 3);
|
||||||
|
return __LINE__; case __LINE__: /**********************************/
|
||||||
|
drv->par = ModBusGetFloat(eab, drv->adr);
|
||||||
|
noPar:
|
||||||
|
|
||||||
|
ParLog(drv);
|
||||||
|
fsm_quit: return 0; } /* FSM END *********************************/
|
||||||
|
}
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
static long Euro2kSet(long pc, void *object) {
|
||||||
|
Euro2k *drv = ParCast(&euro2kClass, object);
|
||||||
|
EaseBase *eab = object;
|
||||||
|
char *p;
|
||||||
|
int l;
|
||||||
|
char buf[4];
|
||||||
|
|
||||||
|
switch (pc) { default: /* FSM BEGIN *******************************/
|
||||||
|
ModBusPutFloats(eab, 2, 1, &drv->d.targetValue);
|
||||||
|
return __LINE__; case __LINE__: /**********************************/
|
||||||
|
|
||||||
|
fsm_quit: return 0; } /* FSM END *********************************/
|
||||||
|
}
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
static long Euro2kStart(long pc, void *object) {
|
||||||
|
Euro2k *drv = ParCast(&euro2kClass, object);
|
||||||
|
EaseBase *eab = object;
|
||||||
|
|
||||||
|
switch (pc) { default: /* FSM BEGIN *******************************/
|
||||||
|
ModBusRequestFloats(eab, 1, 1);
|
||||||
|
return __LINE__; case __LINE__: /**********************************/
|
||||||
|
if (0 == ModBusGetFloat(eab, 1)) {
|
||||||
|
ParPrintf(drv, eError, "bad or no response on ModBus");
|
||||||
|
goto quit;
|
||||||
|
}
|
||||||
|
ParPrintf(drv, eStatus, "connected to euro2k");
|
||||||
|
FsmCall(Euro2kRead);
|
||||||
|
return __LINE__; case __LINE__: /**********************************/
|
||||||
|
|
||||||
|
quit:
|
||||||
|
return 0; } /* FSM END ********************************************/
|
||||||
|
}
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
static int Euro2kInit(SConnection *con, int argc, char *argv[], int dynamic) {
|
||||||
|
/* args:
|
||||||
|
MakeObject objectname euro2k <rs232>
|
||||||
|
<host> <port>
|
||||||
|
*/
|
||||||
|
Euro2k *drv;
|
||||||
|
|
||||||
|
drv = EaseMakeDriv(con, &euro2kClass, argc, argv, dynamic, 7,
|
||||||
|
Euro2kParDef, ModBusHandler, Euro2kStart, NULL, Euro2kRead,
|
||||||
|
Euro2kSet);
|
||||||
|
if (drv == NULL) return 0;
|
||||||
|
setRS232ReplyTerminator(drv->d.b.ser,"");
|
||||||
|
setRS232SendTerminator(drv->d.b.ser,"");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
void Euro2kStartup(void) {
|
||||||
|
ParMakeClass(&euro2kClass, EaseDrivClass());
|
||||||
|
MakeDriver("EURO2K", Euro2kInit, 0);
|
||||||
|
}
|
297
modbus.c
Normal file
297
modbus.c
Normal file
@ -0,0 +1,297 @@
|
|||||||
|
/*---------------------------------------------------------------------------
|
||||||
|
modbus.c
|
||||||
|
|
||||||
|
Communication routines for Eurotherm ModBus instruments
|
||||||
|
|
||||||
|
Markus Zolliker, Aug 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 <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <fortify.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include "sics.h"
|
||||||
|
#include "modbus.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]) {
|
||||||
|
unsigned char *uword;
|
||||||
|
uword = (void *)word;
|
||||||
|
uword[0] = adr / 256;
|
||||||
|
uword[1] = adr % 256;
|
||||||
|
}
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
static unsigned int word2uint(char word[2]) {
|
||||||
|
unsigned char *uword;
|
||||||
|
uword = (void *)word;
|
||||||
|
return uword[0]*256 + uword[1];
|
||||||
|
}
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
static void fadr2word(int adr, char word[2]) {
|
||||||
|
unsigned char *uword;
|
||||||
|
uword = (void *)word;
|
||||||
|
uword[0] = (adr*2) / 256 + 0x80;
|
||||||
|
uword[1] = (adr*2) % 256;
|
||||||
|
}
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
static int word2fadr(char word[2]) {
|
||||||
|
unsigned char *uword;
|
||||||
|
uword = (void *)word;
|
||||||
|
return ((uword[0] & 0x7F)*256 + uword[1]) / 2;
|
||||||
|
}
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
static int calc_crc(char *inp, int inpLen, int addCrc) {
|
||||||
|
|
||||||
|
/* CRC runs cyclic Redundancy Check Algorithm on input inp */
|
||||||
|
/* Returns value of 16 bit CRC after completion and */
|
||||||
|
/* always adds 2 crc bytes to message */
|
||||||
|
/* returns 0 if incoming message has correct CRC */
|
||||||
|
|
||||||
|
unsigned int crc= 0xffff;
|
||||||
|
unsigned int next;
|
||||||
|
int carry;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
while (inpLen--) {
|
||||||
|
next = *(unsigned char *)inp;
|
||||||
|
crc ^= next;
|
||||||
|
for (n = 0; n < 8; n++) {
|
||||||
|
carry = crc & 1;
|
||||||
|
crc >>= 1;
|
||||||
|
if (carry) {
|
||||||
|
crc ^= 0xA001;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inp++;
|
||||||
|
}
|
||||||
|
if (addCrc) {
|
||||||
|
inp[0] = crc % 256;
|
||||||
|
inp[1] = crc / 256;
|
||||||
|
}
|
||||||
|
return crc;
|
||||||
|
}
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
void ModBusDump(EaseBase *eab, int iout, char *fmt, char *buffer, int length) {
|
||||||
|
char buf[50];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (length > 16) length = 16;
|
||||||
|
for (i=0; i<length; i++) {
|
||||||
|
snprintf(buf+i*3, 4, " %2.2X", (unsigned int)buffer[i]);
|
||||||
|
}
|
||||||
|
buf[i*3]='\0';
|
||||||
|
ParPrintf(eab, iout, fmt, buf);
|
||||||
|
}
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
void ModBusWrite(EaseBase *eab, int length) {
|
||||||
|
int iret;
|
||||||
|
char trash[64];
|
||||||
|
int l;
|
||||||
|
|
||||||
|
assert(length < sizeof (eab->cmd));
|
||||||
|
|
||||||
|
if (eab->errCode || eab->state == EASE_expect) return;
|
||||||
|
while (availableRS232(eab->ser) == 1) {
|
||||||
|
l=sizeof(trash);
|
||||||
|
iret = readRS232TillTerm(eab->ser, trash, &l);
|
||||||
|
if (iret < 0) break;
|
||||||
|
ModBusDump(eab, -2, "trash %s\n", trash, l);
|
||||||
|
}
|
||||||
|
calc_crc(eab->cmd, length, 1);
|
||||||
|
iret = writeRS232(eab->ser, eab->cmd, length+2);
|
||||||
|
if (iret < 0) {
|
||||||
|
eab->errCode = iret;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ModBusDump(eab, -2, "cmd: %s", eab->cmd, length+2);
|
||||||
|
eab->state = EASE_expect;
|
||||||
|
eab->cmdtime = time(NULL);
|
||||||
|
}
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
int ModBusHandler(void *object) {
|
||||||
|
int iret, l;
|
||||||
|
EaseBase *eab = EaseBaseCast(object);
|
||||||
|
|
||||||
|
if (eab->state < EASE_idle) goto quit;
|
||||||
|
if (availableNetRS232(eab->ser) || availableRS232(eab->ser)) {
|
||||||
|
eab->msg[0] = '\0';
|
||||||
|
l = 5;
|
||||||
|
iret = readRS232TillTerm(eab->ser, eab->ans, &l);
|
||||||
|
if (eab->state != EASE_expect && eab->state != EASE_lost) {
|
||||||
|
if (iret == 1) {
|
||||||
|
ModBusDump(eab, eError, "unexpected answer %s", eab->ans, l);
|
||||||
|
}
|
||||||
|
goto quit;
|
||||||
|
}
|
||||||
|
if (iret == 1) {
|
||||||
|
if (eab->cmd[0] != eab->ans[0] || eab->cmd[1] != (eab->ans[1] & 0x7F)) {
|
||||||
|
iret = EASE_ILL_ANS;
|
||||||
|
}
|
||||||
|
if (eab->ans[1] & 0x80) {
|
||||||
|
iret = EASE_ILL_ANS;
|
||||||
|
} else if (eab->ans[1] == 16) { /* answer from write n words */
|
||||||
|
l=3; /* finish response */
|
||||||
|
iret = readRS232TillTerm(eab->ser, eab->ans+5, &l);
|
||||||
|
l+=5;
|
||||||
|
} else if (eab->ans[1] == 3) { /* answer for read n words */
|
||||||
|
l = eab->ans[2]; /* bytes to read */
|
||||||
|
iret = readRS232TillTerm(eab->ser, eab->ans+5, &l);
|
||||||
|
l+=5;
|
||||||
|
} else if (eab->ans[1] == 8) { /* loopback info */
|
||||||
|
l=1;
|
||||||
|
iret = readRS232TillTerm(eab->ser, eab->ans+5, &l);
|
||||||
|
l+=5;
|
||||||
|
if (eab->state == EASE_lost) {
|
||||||
|
if (eab->ans[4] == 44 && eab->ans[5] == 55) {
|
||||||
|
eab->state = EASE_idle;
|
||||||
|
}
|
||||||
|
goto quit;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
iret = EASE_ILL_ANS;
|
||||||
|
}
|
||||||
|
if (eab->state == EASE_lost) {
|
||||||
|
goto quit;
|
||||||
|
}
|
||||||
|
ModBusDump(eab, -2, "ans: %s", eab->ans, l);
|
||||||
|
if (iret == 1) {
|
||||||
|
if (calc_crc(eab->ans, l, 0)) {
|
||||||
|
iret = MODBUS_BAD_CRC;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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->cmdtime+20) {
|
||||||
|
eab->state = EASE_lost;
|
||||||
|
}
|
||||||
|
} else if (eab->state == EASE_lost) {
|
||||||
|
if (time(NULL) > eab->cmdtime) {
|
||||||
|
eab->cmd[1] = 8;
|
||||||
|
eab->cmd[2] = 0;
|
||||||
|
eab->cmd[3] = 0;
|
||||||
|
eab->cmd[4] = 44;
|
||||||
|
eab->cmd[5] = 55;
|
||||||
|
ModBusWrite(eab, 6);
|
||||||
|
eab->state = EASE_lost;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
goto quit;
|
||||||
|
error:
|
||||||
|
/* EaseWriteError(eab); */
|
||||||
|
quit:
|
||||||
|
return EaseHandler(eab);
|
||||||
|
}
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
void ModBusPutFloats(EaseBase *eab, int adr, int npar, float val[]) {
|
||||||
|
int l, n;
|
||||||
|
|
||||||
|
assert(npar <= 5);
|
||||||
|
|
||||||
|
eab->cmd[0] = 1; /* device address */
|
||||||
|
eab->cmd[1] = 16; /* write n words */
|
||||||
|
fadr2word(adr, eab->cmd + 2);
|
||||||
|
uint2word(npar*2, eab->cmd + 4);
|
||||||
|
eab->cmd[6] = npar*4; /* number of bytes */
|
||||||
|
l = 7;
|
||||||
|
for (n=0; n<npar; n++) {
|
||||||
|
double2ieee(val[n], eab->cmd+l);
|
||||||
|
l += 4;
|
||||||
|
}
|
||||||
|
ModBusWrite(eab, l);
|
||||||
|
}
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
void ModBusRequestFloats(EaseBase *eab, int adr, int npar) {
|
||||||
|
int l;
|
||||||
|
|
||||||
|
assert(npar <= 14);
|
||||||
|
|
||||||
|
eab->cmd[0] = 1; /* device address */
|
||||||
|
eab->cmd[1] = 3; /* read n words */
|
||||||
|
fadr2word(adr, eab->cmd + 2);
|
||||||
|
uint2word(npar*2, eab->cmd + 4);
|
||||||
|
ModBusWrite(eab, 6);
|
||||||
|
}
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
float ModBusGetFloat(EaseBase *eab, int adr) {
|
||||||
|
int startAdr;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (eab->state != EASE_read) {
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
startAdr = word2fadr(eab->cmd + 2);
|
||||||
|
i = adr - startAdr;
|
||||||
|
if (i < 0 || i >= word2uint(eab->cmd + 4)) {
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
return ieee2double(eab->ans + 3 + i * 4);
|
||||||
|
}
|
21
modbus.h
Normal file
21
modbus.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
/*---------------------------------------------------------------------------
|
||||||
|
modbus.h
|
||||||
|
|
||||||
|
Communication routines for Eurotherm ModBus instruments
|
||||||
|
|
||||||
|
Markus Zolliker, Aug 2005
|
||||||
|
----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef MODBUS_H
|
||||||
|
#define MODBUS_H
|
||||||
|
|
||||||
|
#include "ease.h"
|
||||||
|
|
||||||
|
#define MODBUS_BAD_CRC -3090
|
||||||
|
|
||||||
|
int ModBusHandler(void *eab);
|
||||||
|
void ModBusPutFloats(EaseBase *eab, int adr, int npar, float val[]);
|
||||||
|
void ModBusRequestFloats(EaseBase *eab, int adr, int npar);
|
||||||
|
float ModBusGetFloat(EaseBase *eab, int adr);
|
||||||
|
|
||||||
|
#endif
|
129
oxinst.c
Normal file
129
oxinst.c
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
/*---------------------------------------------------------------------------
|
||||||
|
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 <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <fortify.h>
|
||||||
|
#include "sics.h"
|
||||||
|
#include "oxinst.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
int OxiHandler(void *object) {
|
||||||
|
int iret, l;
|
||||||
|
EaseBase *eab = EaseBaseCast(object);
|
||||||
|
|
||||||
|
if (eab->state < EASE_idle) goto quit;
|
||||||
|
if (availableNetRS232(eab->ser) || availableRS232(eab->ser)) {
|
||||||
|
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') {
|
||||||
|
strncat(eab->version, eab->ans, sizeof(eab->version)-1);
|
||||||
|
} else { /* version (and therefore device) changed */
|
||||||
|
eab->errCode = EASE_DEV_CHANGED;
|
||||||
|
eab->state = EASE_idle;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
eab->state = EASE_idle;
|
||||||
|
goto quit;
|
||||||
|
} else if (eab->cmd[2] == 'k') { /* ?ck */
|
||||||
|
} else if (eab->cmd[0] != eab->ans[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->cmdtime+20) {
|
||||||
|
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) {
|
||||||
|
char *endp, *p;
|
||||||
|
double val;
|
||||||
|
|
||||||
|
if (eab->state != EASE_read) {
|
||||||
|
/* eab->errCode = EASE_ILL_ANS; */
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
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 0.0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val=strtol(eab->ans+1, &endp, 10);
|
||||||
|
if (*endp != '\0') {
|
||||||
|
eab->errCode = EASE_ILL_ANS;
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
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];
|
||||||
|
int l;
|
||||||
|
|
||||||
|
if (eab->syntax <= 0) {
|
||||||
|
snprintf(buf, sizeof(buf), "%s%.*f", cmd, dig, val);
|
||||||
|
} else {
|
||||||
|
snprintf(buf, sizeof(buf), "%s%f", cmd, val);
|
||||||
|
}
|
||||||
|
EaseWrite(eab, buf);
|
||||||
|
}
|
||||||
|
|
19
oxinst.h
Normal file
19
oxinst.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
/*---------------------------------------------------------------------------
|
||||||
|
oxinst.h
|
||||||
|
|
||||||
|
Communication routines for Oxford Instruments equipment
|
||||||
|
|
||||||
|
Markus Zolliker, March 2005
|
||||||
|
----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef OXINST_H
|
||||||
|
#define OXINST_H
|
||||||
|
|
||||||
|
#include "ease.h"
|
||||||
|
|
||||||
|
int OxiHandler(void *eab);
|
||||||
|
double OxiGet(EaseBase *eab, int dig, int *pdig);
|
||||||
|
void OxiSet(EaseBase *eab, char *cmd, double val, int dig);
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
Reference in New Issue
Block a user