From aaac83218104220f8760737d693eb4d632f2ffdf Mon Sep 17 00:00:00 2001 From: Douglas Clowes Date: Fri, 25 Jun 2010 15:10:25 +1000 Subject: [PATCH] add oxford protocol r2961 | dcl | 2010-06-25 15:10:25 +1000 (Fri, 25 Jun 2010) | 2 lines --- site_ansto/hardsup/makefile | 2 +- site_ansto/hardsup/sct_oxfordprot.c | 218 +++++++++++++++++++++++----- site_ansto/site_ansto.c | 4 +- 3 files changed, 185 insertions(+), 39 deletions(-) diff --git a/site_ansto/hardsup/makefile b/site_ansto/hardsup/makefile index 33ed6c16..6ceccc8f 100644 --- a/site_ansto/hardsup/makefile +++ b/site_ansto/hardsup/makefile @@ -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 diff --git a/site_ansto/hardsup/sct_oxfordprot.c b/site_ansto/hardsup/sct_oxfordprot.c index 057fbc78..f2e0cc15 100644 --- a/site_ansto/hardsup/sct_oxfordprot.c +++ b/site_ansto/hardsup/sct_oxfordprot.c @@ -18,23 +18,90 @@ #include #include +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 * @@ -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); } diff --git a/site_ansto/site_ansto.c b/site_ansto/site_ansto.c index 147ff19c..f6ebaaad 100644 --- a/site_ansto/site_ansto.c +++ b/site_ansto/site_ansto.c @@ -9,7 +9,7 @@ Template: Mark Koennecke, June 2003 Nick Hauser, Paul Hathaway, May 2004 $Name: not supported by cvs2svn $ - $Revision: 1.23.2.4 $ + $Revision: 1.23.2.5 $ -----------------------------------------------------------------------*/ #include #include @@ -57,6 +57,7 @@ extern int VelSelTcpFactory(SConnection *pCon, SicsInterp *pSics, void *pData, i extern pCodri MakeTcpDoChoDriver(char *tclArray, SConnection *pCon); extern void AddGalilProtocoll(); extern void AddModbusProtocoll(); +extern void AddOxfordProtocoll(); extern void AddOrdHVPSProtocoll(); extern void AddVelSelProtocol(); extern void AddUSBTMCProtocoll(); @@ -75,6 +76,7 @@ void SiteInit(void) { INIT(ANSTO_SctDriveInit); AddGalilProtocoll(); AddModbusProtocoll(); + AddOxfordProtocoll(); AddOrdHVPSProtocoll(); AddVelSelProtocol(); AddUSBTMCProtocoll();