From cb296cb390df6c191e035bb6297e9d16a7de8b91 Mon Sep 17 00:00:00 2001 From: koennecke Date: Tue, 30 Jun 2009 06:43:59 +0000 Subject: [PATCH] - Added protocol from phytron MCCC-2 motor controller - Modified lmd200.c to reflect new additional values --- lmd200.c | 134 ++++++++++++++++++++++-------------------------------- make_gen | 2 +- phytron.c | 100 ++++++++++++++++++++++++++++++++++++++++ psi.c | 3 ++ 4 files changed, 159 insertions(+), 80 deletions(-) create mode 100644 phytron.c diff --git a/lmd200.c b/lmd200.c index ea918db..a7356fe 100644 --- a/lmd200.c +++ b/lmd200.c @@ -13,12 +13,14 @@ * copyright: see file COPYRIGHT * * Mark Koennecke, October 2007 + * + * modifed to use asynnet and to cope with even more data. + * Mark Koennecke, June 2009 */ #include #include #include -#include -#include +#include #include #include /* @@ -32,11 +34,9 @@ */ #define BUFLEN 1024 typedef struct { - int state; char host[256]; int port; - mkChannel *pSock; - pNWContext watchContext; + int asChannel; char lineBuffer[BUFLEN]; } LMD200, *pLMD200; /*----------------------------------------------------------------------------*/ @@ -46,16 +46,9 @@ static void killLMD200(void *data) if (priv == NULL) { return; } - if (priv->watchContext != NULL) { - NetWatchRemoveCallback(priv->watchContext); - } - if (priv->pSock != NULL) { - NETClosePort(priv->pSock); - free(priv->pSock); - } + ANETclose(priv->asChannel); free(priv); } - /*-------------------------------------------------------------------------*/ static void setAlarm(pSICSOBJ self, char *text) { @@ -143,72 +136,55 @@ static void interpretLine(pSICSOBJ self, pLMD200 priv) { pHdb node = NULL; - switch (priv->state) { - case IDLE: - if (strstr(priv->lineBuffer, "Alarm") != NULL) { - doAlarm(self, priv->lineBuffer); + node = GetHipadabaNode(self->objectNode, "data"); + assert(node != NULL); + + /* + * TODO: check the message headers against what is now coming out + * of the device. + */ + if (strstr(priv->lineBuffer, "Alarm") != NULL) { + doAlarm(self, priv->lineBuffer); + return; + } else if (strstr(priv->lineBuffer, "Pre") != NULL) { + setAlarm(self, priv->lineBuffer); + } else if (strstr(priv->lineBuffer, "...0") == NULL) { + storeData(self, 0, priv->lineBuffer); + NotifyHipadabaPar(node, NULL); return; - } else if (strstr(priv->lineBuffer, "Pre") != NULL) { - setAlarm(self, priv->lineBuffer); - } else { - priv->state = WAITDATA1; - setAlarm(self, "I do not feel very alarmed"); - return; - } - break; - case WAITDATA1: - if (strstr(priv->lineBuffer, "...0") == NULL) { - /* this data is out of order, recover... */ - priv->state = IDLE; - return; - } - storeData(self, 0, priv->lineBuffer); - priv->state = WAITDATA2; - break; - case WAITDATA2: - if (strstr(priv->lineBuffer, "...0") == NULL) { - /* this data is out of order, recover... */ - priv->state = IDLE; - return; - } + } else if(strstr(priv->lineBuffer,"..000") == NULL) { storeData(self, 8, priv->lineBuffer); - priv->state = IDLE; - node = GetHipadabaNode(self->objectNode, "data"); - assert(node != NULL); NotifyHipadabaPar(node, NULL); - break; } } -/*--------------------------------------------------------------------------- - * This handles the terminator discovery and causes the evaluation of complete - * lines. - * --------------------------------------------------------------------------*/ -static int LMD200Callback(void *context, int mode) +/*----------------------------------------------------------------------------*/ +static int LMD200Callback(int handle, void *userData) { - pSICSOBJ self = (pSICSOBJ) context; - pLMD200 priv = NULL; - char buffer[512], *pPtr = NULL, line[132]; - - assert(self != NULL); - priv = (pLMD200) self->pPrivate; - if (mode == nwatch_read) { - memset(buffer, 0, 512); - memset(line, 0, 132); - NETRead(priv->pSock, buffer, 512, 0); - pPtr = stptok(buffer, line, 132, "\r"); - while (pPtr != NULL) { - if (strlen(line) > 3) { - strncpy(priv->lineBuffer, line, BUFLEN); - interpretLine(self, priv); - priv->lineBuffer[0] = '\0'; - } - pPtr = stptok(pPtr, line, 132, "\r"); - } - } - return 1; + pSICSOBJ self = (pSICSOBJ)userData; + pLMD200 priv = (pLMD200)self->pPrivate; + char *pPtr = NULL, *pEnd = NULL; + int length; + + pPtr = ANETreadPtr(priv->asChannel,&length); + pEnd = strchr(pPtr,(int)'\r'); + if(pEnd != NULL){ + length = pEnd - pPtr; + *pEnd = '\0'; + strncpy(priv->lineBuffer,pPtr,BUFLEN); + ANETreadConsume(priv->asChannel,length+1); + interpretLine(self,priv); + } + return 1; +} +/*---------------------------------------------------------------------------*/ +static int ClearCmd(pSICSOBJ ccmd, SConnection * con, + Hdb * cmdNode, Hdb * par[], int nPar) +{ + setAlarm(ccmd,"I do not feel very alarmed..."); + SCSendOK(con); + return 1; } - /*---------------------------------------------------------------------------*/ int MakeLMD200(SConnection * pCon, SicsInterp * pSics, void *pData, int argc, char *argv[]) @@ -228,27 +204,29 @@ int MakeLMD200(SConnection * pCon, SicsInterp * pSics, void *pData, memset(priv, 0, sizeof(LMD200)); strncpy(priv->host, argv[2], 256); priv->port = atoi(argv[3]); - priv->pSock = NETConnect(priv->host, priv->port); - if (priv->pSock == NULL) { + priv->asChannel = ANETconnect(priv->host, priv->port); + if (priv->asChannel < 0) { SCWrite(pCon, "ERROR: failed to connect to LMD200", eError); killLMD200(priv); return 0; } - + self = MakeSICSOBJv(argv[1], "LMD400", HIPNONE, 0); if (self == NULL || priv == NULL) { return 0; } textValue = MakeHdbText("I do not feel very alarmed"); - dataValue = makeHdbValue(HIPFLOATAR, 16); + dataValue = makeHdbValue(HIPFLOATAR, 32); AddSICSHdbPar(self->objectNode, "alarm", usInternal, textValue); AddSICSHdbPar(self->objectNode, "data", usInternal, dataValue); self->pPrivate = priv; self->KillPrivate = killLMD200; ReleaseHdbValue(&dataValue); - NetWatchRegisterCallback(&priv->watchContext, priv->pSock->sockid, - LMD200Callback, self); + ANETsetReadCallback(priv->asChannel,LMD200Callback,self, NULL); + AddSICSHdbPar(self->objectNode, + "clearalarm", usUser, MakeSICSFunc(ClearCmd)); + status = AddCommand(pSics, argv[1], InterInvokeSICSOBJ, KillSICSOBJ, self); if (status != 1) { @@ -257,7 +235,5 @@ int MakeLMD200(SConnection * pCon, SicsInterp * pSics, void *pData, argv[1]); return 0; } - - return 1; } diff --git a/make_gen b/make_gen index 1c670d0..1331b96 100644 --- a/make_gen +++ b/make_gen @@ -23,7 +23,7 @@ OBJ=psi.o buffer.o ruli.o dmc.o nxsans.o nextrics.o sps.o pimotor.o \ dgrambroadcast.o sinq.o tabledrive.o tcpdocho.o julcho.o \ ritastorage.o poldizug.o audinelib.o delcam.o el737hpdrivsps.o \ rebin.o sanslirebin.o lmd200.o slsvme.o julprot.o sinqhttpprot.o \ - pmacprot.o pfeifferprot.o termprot.o + pmacprot.o pfeifferprot.o termprot.o phytron.o .SECONDARY.: sanslirebin.c diff --git a/phytron.c b/phytron.c new file mode 100644 index 0000000..2c7255f --- /dev/null +++ b/phytron.c @@ -0,0 +1,100 @@ +/** + * This is an asynchronous protocol driver for the protocol of + * the Phytron MCC-2 motor controller. + * The send format is: + * DATA + * the reply format is: + * NACK | ACK |& REPLY + * + * copyright: see file COPYRIGHT + * + * Mark Koennecke, June 2009 + */ +#include +#include +#include +#include + +#define STX '\2' +#define ETX '\3' +#define NACK '\5' +#define ACK '\6' + +/*---------------------------------------------------------------------------*/ +static int PhytronHandler(Ascon * a) +{ + char *data = NULL; + int ret, l; + char chr; + + + switch (a->state) { + case AsconWriteStart: + DynStringInsert(a->wrBuffer,"\2",0); + DynStringConcatChar(a->wrBuffer,ETX); + a->state = AsconWriting; + a->wrPos = 0; + break; + case AsconReading: + ret = AsconReadChar(a->fd, &chr); + if (ret < 0) { + /* EINTR means we must retry */ + if (errno != EINTR && errno != EAGAIN) { + AsconError(a, "AsconReadChar failed:", errno); + } + return 1; + } else if (ret > 0) { + if(chr == STX){ + DynStringClear(a->rdBuffer); + } else if (chr == ACK){ + DynStringConcat(a->rdBuffer,"ACK"); + } else if(chr == NACK){ + DynStringConcat(a->rdBuffer,"NACK"); + } else if(chr == ETX){ + a->state = AsconReadDone; + } else { + DynStringConcatChar(a->rdBuffer,chr); + } + } else if (ret == 0) { + if (a->timeout > 0) { + if (DoubleTime() - a->start > a->timeout) { + AsconError(a, "read timeout", 0); + a->state = AsconTimeout; + } + } + } + break; + default: + return AsconStdHandler(a); + } + return 1; +} + +/*------------------------------------------------------------------------*/ +static int PhytronInit(Ascon * a, SConnection * con, int argc, char *argv[]) +{ + a->fd = -1; + a->state = AsconConnectStart; + a->reconnectInterval = 10; + a->hostport = strdup(argv[1]); + if (argc > 2) { + a->timeout = atof(argv[2]); + } else { + a->timeout = 2.0; /* sec */ + } + a->killPrivate = free; + return 1; +} + +/*------------------------------------------------------------------------*/ +void AddPhytronProtocoll() +{ + AsconProtocol *prot = NULL; + + prot = calloc(sizeof(AsconProtocol), 1); + prot->name = strdup("phytron"); + prot->init = PhytronInit; + prot->handler = PhytronHandler; + AsconInsertProtocol(prot); +} + diff --git a/psi.c b/psi.c index c65db6d..ff49ded 100644 --- a/psi.c +++ b/psi.c @@ -85,6 +85,8 @@ extern void AddPMACProtocoll(); extern void AddPfeifferProtocoll(); /* from termprot.c */ extern void AddTermProtocoll(); +/* from phytron.c */ +extern void AddPhytronProtocoll(); /*--------------------------------------------------------------------------*/ void SiteInit(void) @@ -114,6 +116,7 @@ void SiteInit(void) AddPMACProtocoll(); AddPfeifferProtocoll(); AddTermProtocoll(); + AddPhytronProtocoll(); }