- added general binary scriptcontext protocoll
- improved some drivers
This commit is contained in:
477
binprot.c
Normal file
477
binprot.c
Normal file
@ -0,0 +1,477 @@
|
|||||||
|
#include <ctype.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include "ascon.h"
|
||||||
|
#include "ascon.i"
|
||||||
|
#include "dynstring.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* this is a (scriptcontext) general binary protocol driver
|
||||||
|
*
|
||||||
|
* Markus Zolliker Aug 2010
|
||||||
|
*
|
||||||
|
* conversion to and from binary
|
||||||
|
*
|
||||||
|
* Syntax:
|
||||||
|
* space separated items, the command first, a slash and then the read format
|
||||||
|
*
|
||||||
|
* commandItem ... / formatItem ...
|
||||||
|
*
|
||||||
|
* where a commandItem one of the following
|
||||||
|
*
|
||||||
|
* a number converted according to the choosen format, i1 is default
|
||||||
|
* int<n> changing the format to <n> byte integers
|
||||||
|
* hex changing the format to hexadecimal (1 byte at a time)
|
||||||
|
* float changing the format to 4 byte ieee float
|
||||||
|
* crc send crc
|
||||||
|
*
|
||||||
|
* and formatItem is one of the follwing
|
||||||
|
*
|
||||||
|
* skip skip one byte
|
||||||
|
* skip<n> skip <n> bytes
|
||||||
|
* code returned function code, when bit7 is set, the response is
|
||||||
|
* recogized as an error message and the response is dumped
|
||||||
|
* the result
|
||||||
|
* int<n> convert <n> bytes to integer (most significant byte first)
|
||||||
|
* and append the (decimal coded) number to the result
|
||||||
|
* if <n> is omitted, <n> = 1 is assumed
|
||||||
|
* hex convert 1 byte to hexadecimal coded integer
|
||||||
|
* and append it to the response
|
||||||
|
* float convert 4 bytes from ieee float
|
||||||
|
* and append the number to the response
|
||||||
|
* crc check crc (if wrong, "badCRC" is added to the response)
|
||||||
|
*
|
||||||
|
* multiple items in the response are space separated
|
||||||
|
*
|
||||||
|
* Usage example: Modbus read (float)
|
||||||
|
* command: address 250, function 3, start-address 8, size 2, crc
|
||||||
|
* response: address, function, byte-count, float, crc
|
||||||
|
*
|
||||||
|
* sct send 250 3 int2 10 2 crc / skip code skip float crc
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef enum {intType, hexType, floatType,
|
||||||
|
skipType, codeType, crcType, dumpType, errorType} BinDataType;
|
||||||
|
// dumpType, errorType must be the last items
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char *crcAlgorithm;
|
||||||
|
pDynString inp;
|
||||||
|
char *nextFmt;
|
||||||
|
pDynString result;
|
||||||
|
int expectedChars;
|
||||||
|
BinDataType type;
|
||||||
|
long iValue;
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
|
||||||
|
/* 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++;
|
||||||
|
}
|
||||||
|
return crc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
int BinReadItem(Ascon *a) {
|
||||||
|
BinPrivate *p = a->private;
|
||||||
|
char item[32];
|
||||||
|
int valen;
|
||||||
|
int size;
|
||||||
|
|
||||||
|
if (sscanf(p->nextFmt, "%30s%n", item, &valen) <= 0) {
|
||||||
|
if (p->type < dumpType) {
|
||||||
|
p->dumpFrom = GetDynStringLength(a->rdBuffer);
|
||||||
|
p->type= dumpType;
|
||||||
|
}
|
||||||
|
p->expectedChars = 999;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcasecmp(item, "crc") == 0) {
|
||||||
|
p->type = crcType;
|
||||||
|
p->expectedChars = 2;
|
||||||
|
p->nextFmt += valen;
|
||||||
|
return 1;
|
||||||
|
} else if (strncasecmp(item, "int", 3) == 0) {
|
||||||
|
size = 1;
|
||||||
|
sscanf(item + 3, "%d", &size);
|
||||||
|
p->expectedChars = size;
|
||||||
|
p->type = intType;
|
||||||
|
p->iValue = 0;
|
||||||
|
} else if (strcasecmp(item, "float") == 0) {
|
||||||
|
p->expectedChars = 4;
|
||||||
|
p->type = floatType;
|
||||||
|
} else if (strcasecmp(item, "hex") == 0) {
|
||||||
|
p->expectedChars = 1;
|
||||||
|
p->type = hexType;
|
||||||
|
} else if (strcasecmp(item, "code") == 0) {
|
||||||
|
p->type = codeType;
|
||||||
|
} else if (strncasecmp(item, "skip", 4) == 0) {
|
||||||
|
size = 1;
|
||||||
|
sscanf(item + 4, "%d", &size);
|
||||||
|
p->expectedChars = size;
|
||||||
|
p->type = skipType;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
p->nextFmt += valen;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
void BinError(Ascon *a, char *text) {
|
||||||
|
BinPrivate *p = a->private;
|
||||||
|
|
||||||
|
p->type= errorType;
|
||||||
|
p->dumpFrom = 0;
|
||||||
|
p->expectedChars = 1;
|
||||||
|
DynStringCopy(a->errmsg, "BINERR: ");
|
||||||
|
DynStringConcat(a->errmsg, text);
|
||||||
|
a->state = AsconFailed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
int BinHandler(Ascon *a) {
|
||||||
|
int res;
|
||||||
|
char *str;
|
||||||
|
int len;
|
||||||
|
int i, l, pos;
|
||||||
|
unsigned int crc;
|
||||||
|
pDynString dyn;
|
||||||
|
char item[32];
|
||||||
|
char data[8];
|
||||||
|
int size;
|
||||||
|
int valen;
|
||||||
|
BinDataType type;
|
||||||
|
long iValue;
|
||||||
|
double fValue;
|
||||||
|
BinPrivate *p = a->private;
|
||||||
|
|
||||||
|
switch (a->state) {
|
||||||
|
case AsconWriteStart:
|
||||||
|
/* exchange buffers */
|
||||||
|
dyn = p->inp;
|
||||||
|
p->inp = a->wrBuffer;
|
||||||
|
a->wrBuffer = dyn;
|
||||||
|
DynStringClear(dyn);
|
||||||
|
str = GetCharArray(p->inp);
|
||||||
|
len = GetDynStringLength(p->inp);
|
||||||
|
l = 0;
|
||||||
|
size = 1;
|
||||||
|
type = intType;
|
||||||
|
for (pos = 0; pos < len; ) {
|
||||||
|
if (sscanf(str + pos, "%30s%n", item, &valen) <= 0) {
|
||||||
|
BinError(a, "missing '/'");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
pos += valen;
|
||||||
|
if (strcasecmp(item, "/") == 0) {
|
||||||
|
break;
|
||||||
|
} else if (strcasecmp(item, "crc") == 0) {
|
||||||
|
if (strcasecmp(p->crcAlgorithm, "keller-crc") == 0) {
|
||||||
|
crc = calc_crc(GetCharArray(dyn), l);
|
||||||
|
DynStringConcatChar(dyn, crc / 256);
|
||||||
|
DynStringConcatChar(dyn, crc % 256);
|
||||||
|
} else { /* modbus-crc */
|
||||||
|
crc = calc_crc(GetCharArray(dyn), l);
|
||||||
|
DynStringConcatChar(dyn, crc / 256);
|
||||||
|
DynStringConcatChar(dyn, crc % 256);
|
||||||
|
}
|
||||||
|
} else if (strncasecmp(item, "int", 3) == 0) {
|
||||||
|
sscanf(item + 3, "%d", &size);
|
||||||
|
type = intType;
|
||||||
|
} else if (strcasecmp(item, "hex") == 0) {
|
||||||
|
type = hexType;
|
||||||
|
} else if (strcasecmp(item, "float") == 0) {
|
||||||
|
type = floatType;
|
||||||
|
} else {
|
||||||
|
switch (type) {
|
||||||
|
case intType:
|
||||||
|
res = sscanf(item, "%ld", &iValue);
|
||||||
|
if (res != 1) {
|
||||||
|
BinError(a, "invalid integer");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
for (i = size - 1; i >= 0; i--) {
|
||||||
|
if (i < sizeof data) {
|
||||||
|
data[i] = iValue % 256;
|
||||||
|
}
|
||||||
|
iValue /= 256;
|
||||||
|
}
|
||||||
|
for (i = 0; i < size; i++) {
|
||||||
|
if (i >= sizeof data) {
|
||||||
|
DynStringConcatChar(dyn, 0);
|
||||||
|
} else {
|
||||||
|
DynStringConcatChar(dyn, data[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
l += size;
|
||||||
|
break;
|
||||||
|
case hexType:
|
||||||
|
res = sscanf(item, "%lx", &iValue);
|
||||||
|
if (res != 1) {
|
||||||
|
BinError(a, "invalid hex. integer");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
DynStringConcatChar(dyn, (iValue & 255));
|
||||||
|
case floatType:
|
||||||
|
res = sscanf(item, "%lf", &fValue);
|
||||||
|
if (res != 1) {
|
||||||
|
BinError(a, "invalid float");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
double2ieee(fValue, data);
|
||||||
|
DynStringConcatChar(dyn, data[0]);
|
||||||
|
DynStringConcatChar(dyn, data[1]);
|
||||||
|
DynStringConcatChar(dyn, data[2]);
|
||||||
|
DynStringConcatChar(dyn, data[3]);
|
||||||
|
l += 4;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
p->nextFmt = str + pos;
|
||||||
|
p->type = hexType; /* initialize to anything < dumpType */
|
||||||
|
do {
|
||||||
|
res = BinReadItem(a);
|
||||||
|
if (res < 0) {
|
||||||
|
BinError(a, "illegal return format: ");
|
||||||
|
DynStringConcat(a->errmsg, p->nextFmt);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} while (res == 1);
|
||||||
|
p->nextFmt = str + pos;
|
||||||
|
a->wrPos = 0;
|
||||||
|
a->state = AsconWriting;
|
||||||
|
a->lineCount = 0;
|
||||||
|
return 1;
|
||||||
|
case AsconReadStart:
|
||||||
|
DynStringClear(p->result);
|
||||||
|
p->type = hexType; /* initialize to anything < dumpType */
|
||||||
|
BinReadItem(a);
|
||||||
|
break;
|
||||||
|
case AsconReading:
|
||||||
|
res = AsconBaseHandler(a);
|
||||||
|
if (res == 0) {
|
||||||
|
if (GetDynStringLength(a->rdBuffer) == 0) {
|
||||||
|
/* wait for the first byte - or timeout */
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
if (p->type >= dumpType) {
|
||||||
|
l = GetDynStringLength(a->rdBuffer);
|
||||||
|
str = GetCharArray(a->rdBuffer);
|
||||||
|
for (i = p->dumpFrom; i < l; i++) {
|
||||||
|
snprintf(item, sizeof item, "%2.2x ", (str[i] & 255));
|
||||||
|
DynStringConcat(p->result, item);
|
||||||
|
}
|
||||||
|
if (p->type == errorType) {
|
||||||
|
DynStringConcat(a->errmsg, GetCharArray(p->result));
|
||||||
|
a->state = AsconFailed;
|
||||||
|
} else {
|
||||||
|
a->state = AsconReadDone;
|
||||||
|
}
|
||||||
|
/* exchange buffers */
|
||||||
|
dyn = a->rdBuffer;
|
||||||
|
a->rdBuffer = p->result;
|
||||||
|
p->result = dyn;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
/* convert according to type */
|
||||||
|
switch (p->type) {
|
||||||
|
case codeType:
|
||||||
|
if ((a->lastChar & 255) < 128) {
|
||||||
|
p->expectedChars = 0;
|
||||||
|
} else {
|
||||||
|
DynStringCopy(a->errmsg, "BINERR: ");
|
||||||
|
p->expectedChars = 2;
|
||||||
|
p->type = errorType;
|
||||||
|
p->dumpFrom = 0;
|
||||||
|
/* skip to end */
|
||||||
|
p->nextFmt = "";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case errorType:
|
||||||
|
if (p->expectedChars > 1) {
|
||||||
|
p->expectedChars--;
|
||||||
|
snprintf(item, sizeof item, "error %d / ", (a->lastChar & 255));
|
||||||
|
DynStringCopy(p->result, item);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case dumpType:
|
||||||
|
break;
|
||||||
|
case skipType:
|
||||||
|
p->expectedChars--;
|
||||||
|
break;
|
||||||
|
case intType:
|
||||||
|
p->expectedChars--;
|
||||||
|
p->iValue = p->iValue * 256 + (a->lastChar & 255);
|
||||||
|
if (p->expectedChars <= 0) {
|
||||||
|
snprintf(item, sizeof item, "%ld ", p->iValue);
|
||||||
|
DynStringConcat(p->result, item);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case hexType:
|
||||||
|
p->expectedChars--;
|
||||||
|
if (p->expectedChars <= 0) {
|
||||||
|
snprintf(item, sizeof item, "%2.2x ", (a->lastChar & 255));
|
||||||
|
DynStringConcat(p->result, item);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case floatType:
|
||||||
|
p->expectedChars--;
|
||||||
|
if (p->expectedChars <= 0) {
|
||||||
|
str = GetCharArray(a->rdBuffer) + GetDynStringLength(a->rdBuffer) - 4;
|
||||||
|
fValue = ieee2double(str);
|
||||||
|
snprintf(item, sizeof item, "%.7g ", fValue);
|
||||||
|
DynStringConcat(p->result, item);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case crcType:
|
||||||
|
p->expectedChars--;
|
||||||
|
if (p->expectedChars <= 0) {
|
||||||
|
str = GetCharArray(a->rdBuffer);
|
||||||
|
l = GetDynStringLength(a->rdBuffer);
|
||||||
|
if (strcasecmp(p->crcAlgorithm, "keller-crc") == 0) {
|
||||||
|
i = str[l-2];
|
||||||
|
str[l-2] = str[l-1];
|
||||||
|
str[l-1] = i;
|
||||||
|
}
|
||||||
|
if (calc_crc(str, l) != 0) {
|
||||||
|
DynStringConcat(p->result, "badCRC ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (p->expectedChars <= 0) {
|
||||||
|
BinReadItem(a);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
return AsconBaseHandler(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BinPrivateKill(void *pVoid) {
|
||||||
|
BinPrivate *p = pVoid;
|
||||||
|
DeleteDynString(p->inp);
|
||||||
|
DeleteDynString(p->result);
|
||||||
|
free(p->crcAlgorithm);
|
||||||
|
free(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int BinInit(Ascon * a, SConnection * con, int argc, char *argv[])
|
||||||
|
{
|
||||||
|
BinPrivate *p;
|
||||||
|
|
||||||
|
/* argv[2] may be modbus-crc (default) or keller-crc */
|
||||||
|
|
||||||
|
p = calloc(sizeof(*p), 1);
|
||||||
|
a->hostport = strdup(argv[1]);
|
||||||
|
a->private = p;
|
||||||
|
p->inp = CreateDynString(60,63);
|
||||||
|
p->result = CreateDynString(60,63);
|
||||||
|
if (argc > 2 && strcmp(argv[2], "") != 0) {
|
||||||
|
p->crcAlgorithm = strdup(argv[2]);
|
||||||
|
} else {
|
||||||
|
p->crcAlgorithm = strdup("modbus-crc");
|
||||||
|
}
|
||||||
|
if (argc > 3) {
|
||||||
|
a->timeout = atof(argv[3]);
|
||||||
|
} else {
|
||||||
|
a->timeout = 2.0; /* sec */
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
void AddBinProtocol()
|
||||||
|
{
|
||||||
|
static AsconProtocol binprot;
|
||||||
|
binprot.name = "bin";
|
||||||
|
binprot.handler = BinHandler;
|
||||||
|
binprot.init = BinInit;
|
||||||
|
AsconInsertProtocol(&binprot);
|
||||||
|
}
|
4
ease.c
4
ease.c
@ -1004,6 +1004,10 @@ void EaseBasePar(void *object)
|
|||||||
ParAccess(usUser);
|
ParAccess(usUser);
|
||||||
ParCmd(EaseRestartWrapper, NULL);
|
ParCmd(EaseRestartWrapper, NULL);
|
||||||
|
|
||||||
|
ParName("reconnect");
|
||||||
|
ParAccess(usUser);
|
||||||
|
ParCmd(EaseRestartWrapper, NULL);
|
||||||
|
|
||||||
ParName("disconnect");
|
ParName("disconnect");
|
||||||
ParAccess(usUser);
|
ParAccess(usUser);
|
||||||
ParCmd(EaseDisconnectWrapper, NULL);
|
ParCmd(EaseDisconnectWrapper, NULL);
|
||||||
|
10
ipsdriv.c
10
ipsdriv.c
@ -62,6 +62,9 @@ static int IpsOk(Ips * drv)
|
|||||||
return 1; /* connection not yet confirmed */
|
return 1; /* connection not yet confirmed */
|
||||||
if (drv->perswitch)
|
if (drv->perswitch)
|
||||||
return 1;
|
return 1;
|
||||||
|
if (drv->lastfield == PAR_NAN) {
|
||||||
|
drv->lastfield = drv->persfield;
|
||||||
|
}
|
||||||
if (fabs(drv->persfield - drv->lastfield) < 1e-5)
|
if (fabs(drv->persfield - drv->lastfield) < 1e-5)
|
||||||
return 1;
|
return 1;
|
||||||
if (drv->force != 0)
|
if (drv->force != 0)
|
||||||
@ -186,7 +189,7 @@ void IpsParDef(void *object)
|
|||||||
|
|
||||||
ParName("lastfield");
|
ParName("lastfield");
|
||||||
ParSave(1);
|
ParSave(1);
|
||||||
ParFloat(&drv->lastfield, 0);
|
ParFloat(&drv->lastfield, PAR_NAN);
|
||||||
|
|
||||||
ParName("confirm");
|
ParName("confirm");
|
||||||
ParCmd(IpsConfirm, NULL);
|
ParCmd(IpsConfirm, NULL);
|
||||||
@ -232,6 +235,7 @@ static void IpsStatus(Ips * drv)
|
|||||||
break;
|
break;
|
||||||
case '1':
|
case '1':
|
||||||
ParPrintf(drv, eError, "magnet quenched");
|
ParPrintf(drv, eError, "magnet quenched");
|
||||||
|
drv->lastfield = PAR_NAN;
|
||||||
*code = EASE_FAULT;
|
*code = EASE_FAULT;
|
||||||
return;
|
return;
|
||||||
case '2':
|
case '2':
|
||||||
@ -358,6 +362,7 @@ static long IpsStart(long pc, void *object)
|
|||||||
FsmCall(IpsRead);
|
FsmCall(IpsRead);
|
||||||
return __LINE__;
|
return __LINE__;
|
||||||
case __LINE__: /**********************************/
|
case __LINE__: /**********************************/
|
||||||
|
drv->d.targetValue = drv->persfield;
|
||||||
|
|
||||||
quit:
|
quit:
|
||||||
return 0;
|
return 0;
|
||||||
@ -398,6 +403,9 @@ static long IpsChangeField(long pc, void *object)
|
|||||||
drv->remote = 2;
|
drv->remote = 2;
|
||||||
if (!IpsOk(drv))
|
if (!IpsOk(drv))
|
||||||
goto finish;
|
goto finish;
|
||||||
|
if (drv->lastfield == PAR_NAN) {
|
||||||
|
drv->lastfield = drv->persfield;
|
||||||
|
}
|
||||||
if (fabs(drv->d.targetValue - drv->lastfield) < 1e-5) {
|
if (fabs(drv->d.targetValue - drv->lastfield) < 1e-5) {
|
||||||
ParPrintf(drv, -1, "IPS: we are already at field %f",
|
ParPrintf(drv, -1, "IPS: we are already at field %f",
|
||||||
drv->lastfield);
|
drv->lastfield);
|
||||||
|
41
lsc370driv.c
41
lsc370driv.c
@ -33,19 +33,19 @@ Markus Zolliker, July 2006
|
|||||||
#define PID_FLAG 1
|
#define PID_FLAG 1
|
||||||
#define RDGRNG_FLAG 2
|
#define RDGRNG_FLAG 2
|
||||||
#define HTRRNG_FLAG 3
|
#define HTRRNG_FLAG 3
|
||||||
#define MAX_CHAN 3
|
#define MAX_CHAN 4
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
EaseDriv d;
|
EaseDriv d;
|
||||||
float t;
|
float t;
|
||||||
float htr;
|
float htr;
|
||||||
float set;
|
float set;
|
||||||
float res;
|
|
||||||
float prop;
|
float prop;
|
||||||
float integ;
|
float integ;
|
||||||
float deriv;
|
float deriv;
|
||||||
float resist; /* Ohm */
|
float resist; /* Ohm */
|
||||||
float temp[MAX_CHAN];
|
float temp[MAX_CHAN];
|
||||||
|
float res[MAX_CHAN];
|
||||||
int channel[MAX_CHAN];
|
int channel[MAX_CHAN];
|
||||||
int ighHeater; /* IGH heater range (-1 if output is direct) */
|
int ighHeater; /* IGH heater range (-1 if output is direct) */
|
||||||
int htrRange;
|
int htrRange;
|
||||||
@ -116,13 +116,18 @@ static void Lsc370ParDef(void *object)
|
|||||||
};
|
};
|
||||||
static char *offOn[] = { "off", "on", NULL };
|
static char *offOn[] = { "off", "on", NULL };
|
||||||
|
|
||||||
static char *tNames[] = { "tsample", "tstill", "tmix" };
|
static char *tNames[] = { "tsample", "tstill", "tmix", "tplate" };
|
||||||
static char *cNames[] = { "csample", "cstill", "cmix" };
|
static char *rNames[] = { "rsample", "rstill", "rmix", "rplate" };
|
||||||
|
static char *cNames[] = { "csample", "cstill", "cmix", "cplate" };
|
||||||
|
|
||||||
ParName("");
|
ParName("");
|
||||||
ParTail("K");
|
ParTail("K");
|
||||||
ParFloat(&drv->temp[0], PAR_NAN);
|
ParFloat(&drv->temp[0], PAR_NAN);
|
||||||
|
|
||||||
|
ParName("res");
|
||||||
|
ParTail("Ohm");
|
||||||
|
ParFloat(&drv->res[0], PAR_NAN);
|
||||||
|
|
||||||
ParName("set");
|
ParName("set");
|
||||||
ParTail("K");
|
ParTail("K");
|
||||||
if (EaseUpdate(EASE_RUN)) {
|
if (EaseUpdate(EASE_RUN)) {
|
||||||
@ -140,16 +145,16 @@ static void Lsc370ParDef(void *object)
|
|||||||
ParName(tNames[i]);
|
ParName(tNames[i]);
|
||||||
ParTail("K");
|
ParTail("K");
|
||||||
ParFloat(&drv->temp[i], PAR_NAN);
|
ParFloat(&drv->temp[i], PAR_NAN);
|
||||||
|
|
||||||
|
ParName(rNames[i]);
|
||||||
|
ParTail("Ohm");
|
||||||
|
ParFloat(&drv->res[i], PAR_NAN);
|
||||||
}
|
}
|
||||||
ParName(cNames[i]);
|
ParName(cNames[i]);
|
||||||
ParAccess(usUser);
|
ParAccess(usUser);
|
||||||
ParInt(&drv->channel[i], 0);
|
ParInt(&drv->channel[i], 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
ParName("res");
|
|
||||||
ParTail("Ohm");
|
|
||||||
ParFloat(&drv->res, PAR_NAN);
|
|
||||||
|
|
||||||
ParName("prop");
|
ParName("prop");
|
||||||
ParTail("(gain)");
|
ParTail("(gain)");
|
||||||
EaseUpdate(PID_FLAG);
|
EaseUpdate(PID_FLAG);
|
||||||
@ -270,6 +275,10 @@ static void Lsc370ParDef(void *object)
|
|||||||
EaseDrivPar(drv, "%.5g", "K");
|
EaseDrivPar(drv, "%.5g", "K");
|
||||||
ParStdDef();
|
ParStdDef();
|
||||||
EaseMsgPar(drv);
|
EaseMsgPar(drv);
|
||||||
|
|
||||||
|
ParName("period");
|
||||||
|
ParAccess(usUser);
|
||||||
|
ParInt(&drv->d.b.p.period, 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------------*/
|
||||||
@ -292,26 +301,28 @@ static long Lsc370Read(long pc, void *object)
|
|||||||
drv->temp[drv->index] = PAR_NAN;
|
drv->temp[drv->index] = PAR_NAN;
|
||||||
goto noRead;
|
goto noRead;
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(buf, sizeof buf, "RDGK?%d", drv->channel[drv->index]);
|
snprintf(buf, sizeof buf, "RDGK?%d", drv->channel[drv->index]);
|
||||||
EaseWrite(eab, buf);
|
EaseWrite(eab, buf);
|
||||||
return __LINE__;
|
return __LINE__;
|
||||||
case __LINE__: /**********************************/
|
case __LINE__: /**********************************/
|
||||||
|
|
||||||
if (1 == sscanf(eab->ans, "%f", &x)) {
|
if (1 == sscanf(eab->ans, "%f", &x)) {
|
||||||
drv->temp[drv->index] = x;
|
drv->temp[drv->index] = x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
snprintf(buf, sizeof buf, "RDGR?%d", drv->channel[drv->index]);
|
||||||
|
EaseWrite(eab, buf);
|
||||||
|
return __LINE__;
|
||||||
|
case __LINE__: /**********************************/
|
||||||
|
if (1 == sscanf(eab->ans, "%f", &x)) {
|
||||||
|
drv->res[drv->index] = x;
|
||||||
|
}
|
||||||
|
|
||||||
noRead:
|
noRead:
|
||||||
drv->index++;
|
drv->index++;
|
||||||
if (drv->index < MAX_CHAN)
|
if (drv->index < MAX_CHAN)
|
||||||
goto chanLoop;
|
goto chanLoop;
|
||||||
|
|
||||||
EaseWrite(eab, "RDGR?1");
|
|
||||||
return __LINE__;
|
|
||||||
case __LINE__: /**********************************/
|
|
||||||
if (1 == sscanf(eab->ans, "%f", &x)) {
|
|
||||||
drv->res = x;
|
|
||||||
}
|
|
||||||
EaseWrite(eab, "HTR?");
|
EaseWrite(eab, "HTR?");
|
||||||
return __LINE__;
|
return __LINE__;
|
||||||
case __LINE__: /**********************************/
|
case __LINE__: /**********************************/
|
||||||
|
2
make_gen
2
make_gen
@ -29,7 +29,7 @@ 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 \
|
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 \
|
ipsdriv.o ilmdriv.o itcdriv.o ighdriv.o euro2kdriv.o modbus.o arrobj.o \
|
||||||
lscsupport.o lsc370driv.o linadriv.o haakedriv.o amilevel.o
|
lscsupport.o lsc370driv.o linadriv.o haakedriv.o amilevel.o binprot.o
|
||||||
|
|
||||||
libpsi.a: $(OBJ)
|
libpsi.a: $(OBJ)
|
||||||
rm -f libpsi.a
|
rm -f libpsi.a
|
||||||
|
2
modbus.c
2
modbus.c
@ -141,7 +141,7 @@ static int calc_crc(char *inp, int inpLen, int addCrc)
|
|||||||
|
|
||||||
/* CRC runs cyclic Redundancy Check Algorithm on input inp */
|
/* CRC runs cyclic Redundancy Check Algorithm on input inp */
|
||||||
/* Returns value of 16 bit CRC after completion and */
|
/* Returns value of 16 bit CRC after completion and */
|
||||||
/* always adds 2 crc bytes to message */
|
/* adds 2 crc bytes if addCrc is not 0 */
|
||||||
/* returns 0 if incoming message has correct CRC */
|
/* returns 0 if incoming message has correct CRC */
|
||||||
|
|
||||||
unsigned int crc = 0xffff;
|
unsigned int crc = 0xffff;
|
||||||
|
4
pardef.c
4
pardef.c
@ -282,11 +282,11 @@ static int ParSaveAll(void *object, char *name, FILE * fil)
|
|||||||
ctx->saveFile = fil;
|
ctx->saveFile = fil;
|
||||||
assert(0 == strcasecmp(o->name, name));
|
assert(0 == strcasecmp(o->name, name));
|
||||||
if (o->creationCmd) {
|
if (o->creationCmd) {
|
||||||
fprintf(fil, "if {[catch { %s }] == 0} {\n", o->creationCmd);
|
fprintf(fil, "%s\n", o->creationCmd);
|
||||||
}
|
}
|
||||||
ParDo(0, o, PAR_SAVE, NULL);
|
ParDo(0, o, PAR_SAVE, NULL);
|
||||||
if (o->creationCmd) {
|
if (o->creationCmd) {
|
||||||
fprintf(fil, " %s endinit\n}\n", name);
|
fprintf(fil, "%s endinit\n\n", name);
|
||||||
}
|
}
|
||||||
ctx->saveFile = NULL;
|
ctx->saveFile = NULL;
|
||||||
ret = ctx->returnValue;
|
ret = ctx->returnValue;
|
||||||
|
Reference in New Issue
Block a user