add oxford protocol

r2961 | dcl | 2010-06-25 15:10:25 +1000 (Fri, 25 Jun 2010) | 2 lines
This commit is contained in:
Douglas Clowes
2010-06-25 15:10:25 +10:00
parent cebd4d5600
commit aaac832181
3 changed files with 185 additions and 39 deletions

View File

@@ -10,7 +10,7 @@ SRC = .
CC = gcc
CFLAGS = -g -DLINUX $(DFORTIFY) -I$(SRC) -I../.. -Wall -Wno-unused -Wextra
HOBJ= nhq200util.o itc4util.o lh45util.o lakeshore340util.o west4100util.o asynsrv_utility.o geterrno.o strjoin.o chopper.o modbustcp.o sct_galilprot.o sct_modbusprot.o sct_orhvpsprot.o sct_velselprot.o sct_usbtmcprot.o sct_rfamp.o sinqhttpprot.o sct_protek608.o
HOBJ= nhq200util.o itc4util.o lh45util.o lakeshore340util.o west4100util.o asynsrv_utility.o geterrno.o strjoin.o chopper.o modbustcp.o sct_galilprot.o sct_modbusprot.o sct_oxfordprot.o sct_orhvpsprot.o sct_velselprot.o sct_usbtmcprot.o sct_rfamp.o sinqhttpprot.o sct_protek608.o
libhlib.a: $(HOBJ)
rm -f libhlib.a

View File

@@ -18,23 +18,90 @@
#include <ascon.i>
#include <dynstring.h>
struct OxfordProtocol_t {
unsigned int magic;
Ascon* parent;
double last_line_time;
double last_char_time;
double inter_line_time;
double inter_char_time;
};
typedef struct OxfordProtocol_t OxfordProtocol;
struct OxfordQProtocol_t {
unsigned int magic;
Ascon* parent;
double last_line_time;
double last_char_time;
double inter_line_time;
double inter_char_time;
};
typedef struct OxfordQProtocol_t OxfordQProtocol;
/** @brief Set line terminator before sending command
*/
int OxfordWriteStart(Ascon *a) {
OxfordProtocol* private;
double now;
private = (OxfordProtocol*) a->private;
assert(private->magic == 0xcafef00d);
now = DoubleTime();
if (now < private->last_line_time) {
private->last_line_time = now;
}
private->last_char_time = now;
/*
if (now > private->last_line_time + private->inter_line_time) {
return 1;
}
*/
DynStringConcat(a->wrBuffer,"\r");
a->state = AsconWriting;
a->wrPos = 0;
a->state = AsconWriting;
/* if there is only the terminator, do not send it */
if (GetDynStringLength(a->wrBuffer) <= 1) {
a->state = AsconWriteDone;
}
return 1;
}
/** @brief Write the line one character at a time
*/
int OxfordWriting(Ascon *a) {
OxfordProtocol* private;
int ret;
double now;
private = (OxfordProtocol*) a->private;
assert(private->magic == 0xcafef00d);
now = DoubleTime();
if (now < private->last_char_time) {
private->last_char_time = now;
}
if (now < private->last_char_time + private->inter_char_time) {
return 1;
}
if (a->wrPos == 0)
AsconReadGarbage(a->fd);
ret = AsconWriteChars(a->fd, GetCharArray(a->wrBuffer) + a->wrPos, 1);
if (ret < 0) {
AsconError(a, "send failed:", errno);
/*
* Ooops: which state shall we go to after a write fail?
* This seems to retry.
*/
} else {
private->last_char_time = now;
a->wrPos += ret;
if (a->wrPos >= GetDynStringLength(a->wrBuffer)) {
private->last_line_time = now;
a->state = AsconWriteDone;
}
}
return 1;
}
/** @brief Map oxford replies to OK, ASCERR:..., value.
* You can use the first character to sort replies from a oxford controller
* into four categories
* First character is,
* 'SPACE' This is followed by a value
* '?' Error, use 'TC 1' to get error code and message.
* ':' Command received, in response to commands which don't request data.
* '1-9' First digit of error-code followed by error message. (in response to 'TC 1')
*/
int OxfordReading(Ascon *a) {
int ret;
@@ -43,37 +110,35 @@ int OxfordReading(Ascon *a) {
ret = AsconReadChar(a->fd, &chr);
while (ret > 0) {
a->start = DoubleTime();
if (chr != '\r') {
DynStringConcatChar(a->rdBuffer, chr);
ret = AsconReadChar(a->fd, &chr);
}
else {
cp = GetCharArray(a->rdBuffer);
chr = *cp;
if (*cp == '?') { /* command was in error */
a->state = AsconIdle;
#if 0
AsconError(a, GetCharArray(a->rdBuffer), 0);
#else
DynStringInsert(a->rdBuffer, "ASCERR:", 0);
#endif
return 0;
}
else if (GetDynStringLength(a->rdBuffer) == 1) { /* command was successful */
DynStringReplace(a->rdBuffer, "OK", 0);
a->state = AsconReadDone;
return 1;
}
else {
a->state = AsconReadDone;
return 1;
a->state = AsconReadDone;
break;
}
ret = AsconReadChar(a->fd, &chr);
}
if (ret < 0) {
AsconError(a, "AsconReadChar failed:", errno);
return 0;
}
if (a->state == AsconReadDone) {
DynStringConcatChar(a->rdBuffer, '\0');
} else {
if (a->timeout > 0) {
if (DoubleTime() - a->start > a->timeout) {
AsconError(a, "read timeout", 0);
a->state = AsconTimeout;
}
}
}
return 1;
return 0;
}
/** brief Oxford protocol handler.
/** @brief Oxford protocol handler.
* This handler formats commands (ie adds cr line terminator) and
* sorts replies into standard responses of
* <value>
@@ -88,6 +153,10 @@ int OxfordProtHandler(Ascon *a) {
ret = OxfordWriteStart(a);
return ret;
break;
case AsconWriting:
ret = OxfordWriting(a);
return ret;
break;
case AsconReading:
ret = OxfordReading(a);
return ret;
@@ -99,12 +168,87 @@ int OxfordProtHandler(Ascon *a) {
return 1;
}
void AddOxfordProtocoll(){
AsconProtocol *prot = NULL;
prot = calloc(sizeof(AsconProtocol), 1);
prot->name = strdup("oxford");
prot->init = AsconStdInit;
prot->handler = OxfordProtHandler;
AsconInsertProtocol(prot);
int OxfordQProtHandler(Ascon *a) {
int ret;
switch(a->state){
case AsconWriteStart:
ret = OxfordWriteStart(a);
return ret;
break;
case AsconWriting:
ret = OxfordWriting(a);
return ret;
break;
case AsconReading:
ret = OxfordReading(a);
return ret;
break;
default:
ret = AsconStdHandler(a);
return ret;
}
return 1;
}
void OxfordKillPrivate(void *arg) {
OxfordProtocol *private = (OxfordProtocol *) arg;
assert(private->magic == 0xcafef00d);
assert(private->parent->private == private);
private->magic = 0;
free(arg);
}
void OxfordQKillPrivate(void *arg) {
OxfordQProtocol *private = (OxfordQProtocol *) arg;
assert(private->magic == 0xcafef00d);
assert(private->parent->private == private);
private->magic = 0;
free(arg);
}
int OxfordInit(Ascon *a, SConnection *con,
int argc, char *argv[]) {
OxfordProtocol *private;
int ret;
ret = AsconStdInit(a, con, argc, argv);
private = calloc(sizeof(OxfordProtocol), 1);
a->private = (void *) private;
private->magic = 0xcafef00d;
private->parent = a;
private->inter_line_time = 0.100;
private->inter_char_time = 0.010;
a->killPrivate = OxfordKillPrivate;
return ret;
}
int OxfordQInit(Ascon *a, SConnection *con,
int argc, char *argv[]) {
OxfordQProtocol *private;
int ret;
ret = AsconStdInit(a, con, argc, argv);
private = calloc(sizeof(OxfordQProtocol), 1);
a->private = (void *) private;
private->magic = 0xcafef00d;
private->parent = a;
private->inter_line_time = 0.100;
private->inter_char_time = 0.010;
a->killPrivate = OxfordQKillPrivate;
return ret;
}
void AddOxfordProtocoll(){
AsconProtocol *prot = NULL;
prot = calloc(sizeof(AsconProtocol), 1);
prot->name = strdup("oxford");
prot->init = OxfordInit;
prot->handler = OxfordProtHandler;
AsconInsertProtocol(prot);
prot = calloc(sizeof(AsconProtocol), 1);
prot->name = strdup("oxfordq");
prot->init = OxfordQInit;
prot->handler = OxfordQProtHandler;
AsconInsertProtocol(prot);
}