- Added protocol from phytron MCCC-2 motor controller
- Modified lmd200.c to reflect new additional values
This commit is contained in:
118
lmd200.c
118
lmd200.c
@ -13,12 +13,14 @@
|
|||||||
* copyright: see file COPYRIGHT
|
* copyright: see file COPYRIGHT
|
||||||
*
|
*
|
||||||
* Mark Koennecke, October 2007
|
* Mark Koennecke, October 2007
|
||||||
|
*
|
||||||
|
* modifed to use asynnet and to cope with even more data.
|
||||||
|
* Mark Koennecke, June 2009
|
||||||
*/
|
*/
|
||||||
#include <sics.h>
|
#include <sics.h>
|
||||||
#include <sicsobj.h>
|
#include <sicsobj.h>
|
||||||
#include <sicshipadaba.h>
|
#include <sicshipadaba.h>
|
||||||
#include <network.h>
|
#include <asynnet.h>
|
||||||
#include <nwatch.h>
|
|
||||||
#include <commandlog.h>
|
#include <commandlog.h>
|
||||||
#include <stptok.h>
|
#include <stptok.h>
|
||||||
/*
|
/*
|
||||||
@ -32,11 +34,9 @@
|
|||||||
*/
|
*/
|
||||||
#define BUFLEN 1024
|
#define BUFLEN 1024
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int state;
|
|
||||||
char host[256];
|
char host[256];
|
||||||
int port;
|
int port;
|
||||||
mkChannel *pSock;
|
int asChannel;
|
||||||
pNWContext watchContext;
|
|
||||||
char lineBuffer[BUFLEN];
|
char lineBuffer[BUFLEN];
|
||||||
} LMD200, *pLMD200;
|
} LMD200, *pLMD200;
|
||||||
/*----------------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------------*/
|
||||||
@ -46,16 +46,9 @@ static void killLMD200(void *data)
|
|||||||
if (priv == NULL) {
|
if (priv == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (priv->watchContext != NULL) {
|
ANETclose(priv->asChannel);
|
||||||
NetWatchRemoveCallback(priv->watchContext);
|
|
||||||
}
|
|
||||||
if (priv->pSock != NULL) {
|
|
||||||
NETClosePort(priv->pSock);
|
|
||||||
free(priv->pSock);
|
|
||||||
}
|
|
||||||
free(priv);
|
free(priv);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------*/
|
||||||
static void setAlarm(pSICSOBJ self, char *text)
|
static void setAlarm(pSICSOBJ self, char *text)
|
||||||
{
|
{
|
||||||
@ -143,72 +136,55 @@ static void interpretLine(pSICSOBJ self, pLMD200 priv)
|
|||||||
{
|
{
|
||||||
pHdb node = NULL;
|
pHdb node = NULL;
|
||||||
|
|
||||||
switch (priv->state) {
|
node = GetHipadabaNode(self->objectNode, "data");
|
||||||
case IDLE:
|
assert(node != NULL);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TODO: check the message headers against what is now coming out
|
||||||
|
* of the device.
|
||||||
|
*/
|
||||||
if (strstr(priv->lineBuffer, "Alarm") != NULL) {
|
if (strstr(priv->lineBuffer, "Alarm") != NULL) {
|
||||||
doAlarm(self, priv->lineBuffer);
|
doAlarm(self, priv->lineBuffer);
|
||||||
return;
|
return;
|
||||||
} else if (strstr(priv->lineBuffer, "Pre") != NULL) {
|
} else if (strstr(priv->lineBuffer, "Pre") != NULL) {
|
||||||
setAlarm(self, priv->lineBuffer);
|
setAlarm(self, priv->lineBuffer);
|
||||||
} else {
|
} else if (strstr(priv->lineBuffer, "...0") == NULL) {
|
||||||
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);
|
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;
|
|
||||||
}
|
|
||||||
storeData(self, 8, priv->lineBuffer);
|
|
||||||
priv->state = IDLE;
|
|
||||||
node = GetHipadabaNode(self->objectNode, "data");
|
|
||||||
assert(node != NULL);
|
|
||||||
NotifyHipadabaPar(node, NULL);
|
NotifyHipadabaPar(node, NULL);
|
||||||
break;
|
return;
|
||||||
|
} else if(strstr(priv->lineBuffer,"..000") == NULL) {
|
||||||
|
storeData(self, 8, priv->lineBuffer);
|
||||||
|
NotifyHipadabaPar(node, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------*/
|
||||||
* This handles the terminator discovery and causes the evaluation of complete
|
static int LMD200Callback(int handle, void *userData)
|
||||||
* lines.
|
|
||||||
* --------------------------------------------------------------------------*/
|
|
||||||
static int LMD200Callback(void *context, int mode)
|
|
||||||
{
|
{
|
||||||
pSICSOBJ self = (pSICSOBJ) context;
|
pSICSOBJ self = (pSICSOBJ)userData;
|
||||||
pLMD200 priv = NULL;
|
pLMD200 priv = (pLMD200)self->pPrivate;
|
||||||
char buffer[512], *pPtr = NULL, line[132];
|
char *pPtr = NULL, *pEnd = NULL;
|
||||||
|
int length;
|
||||||
|
|
||||||
assert(self != NULL);
|
pPtr = ANETreadPtr(priv->asChannel,&length);
|
||||||
priv = (pLMD200) self->pPrivate;
|
pEnd = strchr(pPtr,(int)'\r');
|
||||||
if (mode == nwatch_read) {
|
if(pEnd != NULL){
|
||||||
memset(buffer, 0, 512);
|
length = pEnd - pPtr;
|
||||||
memset(line, 0, 132);
|
*pEnd = '\0';
|
||||||
NETRead(priv->pSock, buffer, 512, 0);
|
strncpy(priv->lineBuffer,pPtr,BUFLEN);
|
||||||
pPtr = stptok(buffer, line, 132, "\r");
|
ANETreadConsume(priv->asChannel,length+1);
|
||||||
while (pPtr != NULL) {
|
interpretLine(self,priv);
|
||||||
if (strlen(line) > 3) {
|
|
||||||
strncpy(priv->lineBuffer, line, BUFLEN);
|
|
||||||
interpretLine(self, priv);
|
|
||||||
priv->lineBuffer[0] = '\0';
|
|
||||||
}
|
|
||||||
pPtr = stptok(pPtr, line, 132, "\r");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return 1;
|
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 MakeLMD200(SConnection * pCon, SicsInterp * pSics, void *pData,
|
||||||
int argc, char *argv[])
|
int argc, char *argv[])
|
||||||
@ -228,8 +204,8 @@ int MakeLMD200(SConnection * pCon, SicsInterp * pSics, void *pData,
|
|||||||
memset(priv, 0, sizeof(LMD200));
|
memset(priv, 0, sizeof(LMD200));
|
||||||
strncpy(priv->host, argv[2], 256);
|
strncpy(priv->host, argv[2], 256);
|
||||||
priv->port = atoi(argv[3]);
|
priv->port = atoi(argv[3]);
|
||||||
priv->pSock = NETConnect(priv->host, priv->port);
|
priv->asChannel = ANETconnect(priv->host, priv->port);
|
||||||
if (priv->pSock == NULL) {
|
if (priv->asChannel < 0) {
|
||||||
SCWrite(pCon, "ERROR: failed to connect to LMD200", eError);
|
SCWrite(pCon, "ERROR: failed to connect to LMD200", eError);
|
||||||
killLMD200(priv);
|
killLMD200(priv);
|
||||||
return 0;
|
return 0;
|
||||||
@ -240,14 +216,16 @@ int MakeLMD200(SConnection * pCon, SicsInterp * pSics, void *pData,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
textValue = MakeHdbText("I do not feel very alarmed");
|
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, "alarm", usInternal, textValue);
|
||||||
AddSICSHdbPar(self->objectNode, "data", usInternal, dataValue);
|
AddSICSHdbPar(self->objectNode, "data", usInternal, dataValue);
|
||||||
self->pPrivate = priv;
|
self->pPrivate = priv;
|
||||||
self->KillPrivate = killLMD200;
|
self->KillPrivate = killLMD200;
|
||||||
ReleaseHdbValue(&dataValue);
|
ReleaseHdbValue(&dataValue);
|
||||||
NetWatchRegisterCallback(&priv->watchContext, priv->pSock->sockid,
|
ANETsetReadCallback(priv->asChannel,LMD200Callback,self, NULL);
|
||||||
LMD200Callback, self);
|
|
||||||
|
AddSICSHdbPar(self->objectNode,
|
||||||
|
"clearalarm", usUser, MakeSICSFunc(ClearCmd));
|
||||||
|
|
||||||
status = AddCommand(pSics,
|
status = AddCommand(pSics,
|
||||||
argv[1], InterInvokeSICSOBJ, KillSICSOBJ, self);
|
argv[1], InterInvokeSICSOBJ, KillSICSOBJ, self);
|
||||||
@ -257,7 +235,5 @@ int MakeLMD200(SConnection * pCon, SicsInterp * pSics, void *pData,
|
|||||||
argv[1]);
|
argv[1]);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
2
make_gen
2
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 \
|
dgrambroadcast.o sinq.o tabledrive.o tcpdocho.o julcho.o \
|
||||||
ritastorage.o poldizug.o audinelib.o delcam.o el737hpdrivsps.o \
|
ritastorage.o poldizug.o audinelib.o delcam.o el737hpdrivsps.o \
|
||||||
rebin.o sanslirebin.o lmd200.o slsvme.o julprot.o sinqhttpprot.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
|
.SECONDARY.: sanslirebin.c
|
||||||
|
|
||||||
|
100
phytron.c
Normal file
100
phytron.c
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
/**
|
||||||
|
* This is an asynchronous protocol driver for the protocol of
|
||||||
|
* the Phytron MCC-2 motor controller.
|
||||||
|
* The send format is:
|
||||||
|
* <STX> DATA <ETX>
|
||||||
|
* the reply format is:
|
||||||
|
* <STX> NACK | ACK |& REPLY <ETX>
|
||||||
|
*
|
||||||
|
* copyright: see file COPYRIGHT
|
||||||
|
*
|
||||||
|
* Mark Koennecke, June 2009
|
||||||
|
*/
|
||||||
|
#include <errno.h>
|
||||||
|
#include <ascon.h>
|
||||||
|
#include <ascon.i>
|
||||||
|
#include <dynstring.h>
|
||||||
|
|
||||||
|
#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);
|
||||||
|
}
|
||||||
|
|
3
psi.c
3
psi.c
@ -85,6 +85,8 @@ extern void AddPMACProtocoll();
|
|||||||
extern void AddPfeifferProtocoll();
|
extern void AddPfeifferProtocoll();
|
||||||
/* from termprot.c */
|
/* from termprot.c */
|
||||||
extern void AddTermProtocoll();
|
extern void AddTermProtocoll();
|
||||||
|
/* from phytron.c */
|
||||||
|
extern void AddPhytronProtocoll();
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
void SiteInit(void)
|
void SiteInit(void)
|
||||||
@ -114,6 +116,7 @@ void SiteInit(void)
|
|||||||
AddPMACProtocoll();
|
AddPMACProtocoll();
|
||||||
AddPfeifferProtocoll();
|
AddPfeifferProtocoll();
|
||||||
AddTermProtocoll();
|
AddTermProtocoll();
|
||||||
|
AddPhytronProtocoll();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user