diff --git a/jvlprot.c b/jvlprot.c new file mode 100644 index 0000000..9131c13 --- /dev/null +++ b/jvlprot.c @@ -0,0 +1,230 @@ +/* + * jvlprot.c + * + * This is a protocol driver for the JVL integrated stepper motors. + * They talk on a RS485 bus, half-duplex, 19220 Baud, 8N1. They use + * a weird binary protocol which is documented in the accompanying + * manual. + * + * Created on: May 7, 2012 + * Author: koennecke + */ + +#include +#include +#include +#include +#include + +typedef struct { + unsigned char wrBuffer[30]; + unsigned char rdBuffer[30]; + int toWrite, toRead; + unsigned char *wrPtr, *rdPtr; + int reading; + time_t start; +}JVL, *pJVL; +/*------------------------------------------------------------*/ +static int validResponse(pJVL priv) +{ + if(priv->rdPtr - priv->rdBuffer > 3){ + if((priv->rdBuffer[0] == 0x52 && priv->rdBuffer[1] == 0x52 && priv->rdBuffer[2] == 0x52) || + (priv->rdBuffer[0] == 0x11 && priv->rdBuffer[1] == 0x11 && priv->rdBuffer[2] == 0x11) ) { + return 1; + } else { + return 0; + } + } else { + return 1; + } +} + +/*------------------------------------------------------------*/ +static int JVLHandler(Ascon *a) +{ + pJVL priv; + char *data, token[20]; + int motNo, address,ret; + union { + unsigned char b[4]; + int iVal; + }val; + char chr; + + priv = (pJVL)a->private; + switch(a->state){ + case AsconWriteStart: + data = GetCharArray(a->wrBuffer); + if(data[0] == 'r'){ + data = stptok(data,token,20," "); + data = stptok(data,token,20," "); + motNo = atoi(token); + data = stptok(data,token,20," "); + address = atoi(token); + priv->wrBuffer[0] = 80; /* 0x50 */ + priv->wrBuffer[1] = 80; + priv->wrBuffer[2] = 80; + priv->wrBuffer[3] = motNo; + priv->wrBuffer[4] = 255 - motNo; + priv->wrBuffer[5] = address; + priv->wrBuffer[6] = 255-address; + priv->wrBuffer[7] = 170; /* 0xAA */ + priv->wrBuffer[8] = 170; + priv->toWrite = 9; + priv->toRead = 19; + priv->rdPtr = priv->rdBuffer; + priv->wrPtr = priv->wrBuffer; + a->state = AsconWriting; + priv->reading = 1; + priv->start = time(NULL); + return 1; + } else if(data[0] == 'w'){ + data = stptok(data,token,20," "); + data = stptok(data,token,20," "); + motNo = atoi(token); + data = stptok(data,token,20," "); + address = atoi(token); + data = stptok(data,token,20," "); + val.iVal = atoi(token); + priv->wrBuffer[0] = 82; /* 0x52 */ + priv->wrBuffer[1] = 82; + priv->wrBuffer[2] = 82; + priv->wrBuffer[3] = motNo; + priv->wrBuffer[4] = 255 - motNo; + priv->wrBuffer[5] = address; + priv->wrBuffer[6] = 255-address; + priv->wrBuffer[7] = 4; /* len */ + priv->wrBuffer[8] = 255 - 4; + /* + * This code may be platform byte order dependent + */ + priv->wrBuffer[9] = val.b[0]; /* data */ + priv->wrBuffer[10] = 255 -val.b[0]; + priv->wrBuffer[11] = val.b[1]; + priv->wrBuffer[12] = 255 -val.b[1]; + priv->wrBuffer[13] = val.b[2]; + priv->wrBuffer[14] = 255 -val.b[2]; + priv->wrBuffer[15] = val.b[3]; + priv->wrBuffer[16] = 255 -val.b[3]; + priv->wrBuffer[17] = 170; /* 0xAA */ + priv->wrBuffer[18] = 170; + priv->wrPtr = priv->wrBuffer; + priv->toWrite = 19; + priv->rdPtr = priv->rdBuffer; + priv->toRead = 3; + a->state = AsconWriting; + priv->reading = 0; + priv->start = time(NULL); + return 1; + } else { + priv->reading = 0; + AsconError(a,"Unknown JVL command", 0); + return 1; + } + break; + case AsconWriting: + AsconReadGarbage(a->fd); + ret = AsconWriteChars(a->fd, (char *)priv->wrPtr, priv->toWrite); + if(*priv->wrPtr != 80){ + printf("Hugo\n"); + } + if (ret < 0) { + if (errno != EINTR && errno != EAGAIN) { + AsconError(a, "send failed:", errno); + } + /* + * Ooops: which state shall we go to after a write fail? + * This seems to retry. + */ + } else { + priv->wrPtr += ret; + priv->toWrite -= ret; + if (priv->toWrite <= 0) { + a->state = AsconWriteDone; + } + return 1; + } + break; + case AsconReadStart: + DynStringClear(a->rdBuffer); + a->state = AsconReading; + return 1; + break; + case AsconReading: + if(!validResponse(priv)){ + a->state = AsconWriteStart; + return 1; + } + if(time(NULL) > priv->start + 1){ + a->state = AsconReadDone; + DynStringConcat(a->rdBuffer,"timeout"); + return 1; + } + ret = AsconReadChar(a->fd, &chr); + if (ret < 0) { + /* EINTR means we must retry */ + if (errno != EINTR && errno != EAGAIN) { + AsconError(a, "AsconReadChar failed:", errno); + } + } else if (ret > 0) { + *(priv->rdPtr) = (unsigned char)chr; + priv->toRead--; + priv->rdPtr++; + if(priv->toRead <= 0){ + a->state = AsconReadDone; + if(priv->reading){ + /* This code may be platform byte order dependent */ + val.b[0] = priv->rdBuffer[9]; + val.b[1] = priv->rdBuffer[11]; + val.b[2] = priv->rdBuffer[13]; + val.b[3] = priv->rdBuffer[15]; + snprintf(token,20,"%d", val.iVal); + DynStringConcat(a->rdBuffer,token); + } else { + if(priv->rdBuffer[0] == 0x11){ + DynStringConcat(a->rdBuffer,"OK"); + } else { + DynStringConcat(a->rdBuffer,"Unknown response code from JVL: "); + snprintf(token,20,"%x", priv->rdBuffer[0]); + DynStringConcat(a->rdBuffer, token); + } + } + } + } + return 1; + break; + default: + return AsconBaseHandler(a); + } + return AsconBaseHandler(a); +} +/*------------------------------------------------------------------------*/ +static int JVLInit(Ascon * a, SConnection * con, int argc, char *argv[]) +{ + pJVL priv = NULL; + + priv = calloc(sizeof(JVL), 1); + 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->private = priv; + a->killPrivate = free; + return 1; +} +/*------------------------------------------------------------------------*/ +void AddJVLProtocoll() +{ + AsconProtocol *prot = NULL; + + prot = calloc(sizeof(AsconProtocol), 1); + prot->name = strdup("jvl"); + prot->init = JVLInit; + prot->handler = JVLHandler; + AsconInsertProtocol(prot); +} diff --git a/make_gen b/make_gen index 08fdb8d..974edb0 100644 --- a/make_gen +++ b/make_gen @@ -24,7 +24,7 @@ OBJ=psi.o buffer.o ruli.o sps.o pimotor.o charbychar.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 phytron.o autowin.o eigera2.o \ - tclClock.o tclDate.o tclUnixTime.o + tclClock.o tclDate.o tclUnixTime.o jvlprot.o .SECONDARY.: sanslirebin.c diff --git a/polterwrite.c b/polterwrite.c index 81ac028..bcf9987 100644 --- a/polterwrite.c +++ b/polterwrite.c @@ -545,6 +545,8 @@ static void PoldiUpdate(pPolterdi self, SConnection * pCon) NXDputalias(hfil, hdict, "cntime", &fVal); lVal = GetMonitor(pCount, 1, pCon); NXDputalias(hfil, hdict, "cnmon1", &lVal); + lVal = GetMonitor(pCount, 0, pCon); + NXDputalias(hfil, hdict, "cnprot", &lVal); lVal = GetMonitor(pCount, 2, pCon); NXDputalias(hfil, hdict, "cnmon2", &lVal); eMode = GetCounterMode(pCount); diff --git a/psi.c b/psi.c index 2635016..741ff8c 100644 --- a/psi.c +++ b/psi.c @@ -74,6 +74,7 @@ void SiteInit(void) INIT(AddCharByCharProtocoll); INIT(AddBinProtocol); INIT(AddDumProtocol); + INIT(AddJVLProtocoll); } diff --git a/spss7.c b/spss7.c index 3380caf..a1be7f2 100644 --- a/spss7.c +++ b/spss7.c @@ -407,11 +407,9 @@ static char *S7InitHandler(void *actionData, char *reply, int comerror) dblength = ntohs(dblength); InitializeSPSDataBase(self,self->spsNode); node = GetHipadabaNode(self->spsNode,"init"); - /* if(node != NULL){ UpdateHipadabaPar(node,MakeHdbInt(1), NULL); } - */ return NULL; } }