728 lines
18 KiB
C
728 lines
18 KiB
C
/*--------------------------------------------------------------------------
|
|
P I M O T O R
|
|
|
|
This file contains the implementation of a motor driver for the Physik
|
|
Instrument C-804 DC motor controller. Plus the implementation of an
|
|
additional wrapper function for handling addtional support commands
|
|
for this motor controller.
|
|
|
|
Mark Koenencke, September 1998
|
|
----------------------------------------------------------------------------*/
|
|
#include <stdlib.h>
|
|
#include <assert.h>
|
|
#include "fortify.h"
|
|
#include "sics.h"
|
|
#include <tcl.h>
|
|
#include "hardsup/serialsinq.h"
|
|
#include "hardsup/el734_def.h"
|
|
#include "hardsup/el734fix.h"
|
|
#include "motor.h"
|
|
#include "pimotor.h"
|
|
|
|
|
|
/*================== The Driver data structure ============================*/
|
|
typedef struct __PIMoDriv {
|
|
/* general motor driver interface
|
|
fields. REQUIRED!
|
|
*/
|
|
float fUpper; /* upper limit */
|
|
float fLower; /* lower limit */
|
|
char *name;
|
|
int (*GetPosition) (void *self, float *fPos);
|
|
int (*RunTo) (void *self, float fNewVal);
|
|
int (*GetStatus) (void *self);
|
|
void (*GetError) (void *self, int *iCode, char *buffer, int iBufLen);
|
|
int (*TryAndFixIt) (void *self, int iError, float fNew);
|
|
int (*Halt) (void *self);
|
|
int (*GetDriverPar) (void *self, char *name, float *value);
|
|
int (*SetDriverPar) (void *self, SConnection * pCon,
|
|
char *name, float newValue);
|
|
void (*ListDriverPar) (void *self, char *motorName, SConnection * pCon);
|
|
void (*KillPrivate) (void *self);
|
|
|
|
|
|
/* C-804 specific fields */
|
|
int iPort;
|
|
char *hostname;
|
|
int iChannel;
|
|
int iMotor;
|
|
void *pSerial;
|
|
int iLastError;
|
|
} C804Driv, *pC804Driv;
|
|
|
|
#define PITMO -845
|
|
#define PICOMERR -846
|
|
/*--------------------------------------------------------------------------*/
|
|
static int PIPosition(void *pData, float *fPos)
|
|
{
|
|
pC804Driv self = NULL;
|
|
int iRet;
|
|
char pCommand[20];
|
|
char pReply[80];
|
|
char *pPtr;
|
|
|
|
self = (pC804Driv) pData;
|
|
assert(self);
|
|
|
|
/* format command */
|
|
sprintf(pCommand, "%1.1dTP\r", self->iMotor);
|
|
|
|
/* send command */
|
|
iRet = SerialWriteRead(&self->pSerial, pCommand, pReply, 79);
|
|
if (iRet != 1) {
|
|
self->iLastError = iRet;
|
|
*fPos = -99999;
|
|
return HWFault;
|
|
}
|
|
|
|
/* catch TMO or bad reply */
|
|
if (strstr(pReply, "TMO") != NULL) {
|
|
self->iLastError = PITMO;
|
|
*fPos = -9999;
|
|
return HWFault;
|
|
}
|
|
if (strstr(pReply, "?") != NULL) {
|
|
self->iLastError = PICOMERR;
|
|
*fPos = -9999;
|
|
return HWFault;
|
|
}
|
|
|
|
|
|
/* read value */
|
|
pPtr = pReply + 3;
|
|
*fPos = atof(pPtr);
|
|
return OKOK;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
static int PIRun(void *pData, float fVal)
|
|
{
|
|
pC804Driv self = NULL;
|
|
int iRet;
|
|
char pCommand[20];
|
|
char pReply[80];
|
|
int iTmo;
|
|
|
|
self = (pC804Driv) pData;
|
|
assert(self);
|
|
|
|
/* format drive command */
|
|
sprintf(pCommand, "%1.1dMA%10.10d\r", self->iMotor, (int) fVal);
|
|
|
|
iTmo = SerialGetTmo(&self->pSerial);
|
|
SerialConfig(&self->pSerial, 0);
|
|
|
|
/* send command */
|
|
iRet = SerialWriteRead(&self->pSerial, pCommand, pReply, 79);
|
|
if (iRet != 1) {
|
|
self->iLastError = iRet;
|
|
return HWFault;
|
|
}
|
|
|
|
/* reset tmo */
|
|
SerialConfig(&self->pSerial, iTmo);
|
|
|
|
/* wait a little to allow to gather some speed before checking on it */
|
|
SicsWait(2);
|
|
return OKOK;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
static void PIError(void *pData, int *iCode, char *pError, int iErrLen)
|
|
{
|
|
pC804Driv self = NULL;
|
|
|
|
self = (pC804Driv) pData;
|
|
assert(self);
|
|
|
|
*iCode = self->iLastError;
|
|
|
|
if (*iCode == PITMO) {
|
|
strlcpy(pError, "Timeout at serial line", iErrLen);
|
|
return;
|
|
}
|
|
if (*iCode == PICOMERR) {
|
|
strlcpy(pError, "C-804 Command Error", iErrLen);
|
|
return;
|
|
}
|
|
|
|
SerialError(self->iLastError, pError, iErrLen);
|
|
return;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
static int PIFixError(void *pData, int iError, float fNew)
|
|
{
|
|
pC804Driv self = NULL;
|
|
int iRet;
|
|
|
|
self = (pC804Driv) pData;
|
|
assert(self);
|
|
|
|
switch (iError) {
|
|
/* network errors */
|
|
case NOCONNECTION:
|
|
case EL734__BAD_FLUSH:
|
|
case EL734__BAD_RECV:
|
|
case EL734__BAD_RECV_NET:
|
|
case EL734__BAD_RECV_UNKN:
|
|
case EL734__BAD_RECVLEN:
|
|
case EL734__BAD_RECV1:
|
|
case EL734__BAD_RECV1_PIPE:
|
|
case EL734__BAD_RNG:
|
|
case EL734__BAD_SEND:
|
|
case EL734__BAD_SEND_PIPE:
|
|
case EL734__BAD_SEND_NET:
|
|
case EL734__BAD_SEND_UNKN:
|
|
case EL734__BAD_SENDLEN:
|
|
SerialClose(&self->pSerial);
|
|
iRet = SerialOpen(&self->pSerial, self->hostname,
|
|
self->iPort, self->iChannel);
|
|
if (iRet != 1) {
|
|
return MOTREDO;
|
|
} else {
|
|
return MOTFAIL;
|
|
}
|
|
break;
|
|
/* handable protocoll errors */
|
|
case EL734__BAD_TMO:
|
|
case PITMO:
|
|
case TIMEOUT:
|
|
return MOTREDO;
|
|
break;
|
|
case PICOMERR:
|
|
return MOTFAIL;
|
|
break;
|
|
default:
|
|
return MOTFAIL;
|
|
break;
|
|
}
|
|
return MOTFAIL;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
static int PIHalt(void *pData)
|
|
{
|
|
pC804Driv self = NULL;
|
|
char pCommand[20], pReply[80];
|
|
int iTmo;
|
|
|
|
self = (pC804Driv) pData;
|
|
assert(self);
|
|
|
|
sprintf(pCommand, "%1.1dAB\r", self->iMotor);
|
|
|
|
iTmo = SerialGetTmo(&self->pSerial);
|
|
SerialConfig(&self->pSerial, 0);
|
|
SerialWriteRead(&self->pSerial, pCommand, pReply, 79);
|
|
SerialConfig(&self->pSerial, iTmo);
|
|
|
|
return 1;
|
|
}
|
|
|
|
#define ABS(x) (x < 0 ? -(x) : (x))
|
|
/*-------------------------------------------------------------------------*/
|
|
static int PIStatus(void *pData)
|
|
{
|
|
pC804Driv self = NULL;
|
|
char pCommand[20], pReply[80], *pPtr;
|
|
int iRet;
|
|
float fSpeed;
|
|
|
|
self = (pC804Driv) pData;
|
|
assert(self);
|
|
|
|
/* read actual velocity: should be 0 when done */
|
|
sprintf(pCommand, "%1.1dTV\r", self->iMotor);
|
|
iRet = SerialWriteRead(&self->pSerial, pCommand, pReply, 79);
|
|
if (iRet != 1) {
|
|
self->iLastError = iRet;
|
|
return HWFault;
|
|
}
|
|
/* check reply */
|
|
if (strstr(pReply, "TMO") != NULL) {
|
|
self->iLastError = PITMO;
|
|
return HWFault;
|
|
}
|
|
if (strstr(pReply, "?") != NULL) {
|
|
self->iLastError = PICOMERR;
|
|
return HWFault;
|
|
}
|
|
|
|
pPtr = pReply + 3;
|
|
fSpeed = atof(pPtr);
|
|
if (ABS(fSpeed) > 0) {
|
|
return HWBusy;
|
|
}
|
|
return HWIdle;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
static void KillC804(pC804Driv self)
|
|
{
|
|
if (!self)
|
|
return;
|
|
|
|
if (self->name) {
|
|
free(self->name);
|
|
}
|
|
if (self->hostname) {
|
|
free(self->hostname);
|
|
}
|
|
if (self->pSerial) {
|
|
SerialClose(&self->pSerial);
|
|
}
|
|
free(self);
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------
|
|
* The data necessary for initialising the C804 motor is contained in a
|
|
* Tcl-Array given as pArray parameter. In case of an error the error is
|
|
* returned in the Tcl-interpreter.
|
|
*/
|
|
static pC804Driv MakeC804Driver(Tcl_Interp * pTcl, char *pArray)
|
|
{
|
|
pC804Driv pNew = NULL;
|
|
int iRet, iVal, iTmo;
|
|
double dVal;
|
|
char *pPar = NULL;
|
|
char pCommand[20], pReply[40];
|
|
|
|
/* allocate space: the final frontier */
|
|
pNew = (pC804Driv) malloc(sizeof(C804Driv));
|
|
if (!pNew) {
|
|
Tcl_SetResult(pTcl, "Out of memory for C804 Driver", NULL);
|
|
return NULL;
|
|
}
|
|
memset(pNew, 0, sizeof(C804Driv));
|
|
|
|
/* connection parameters */
|
|
pPar = (char *) Tcl_GetVar2(pTcl, pArray, "Computer", TCL_LEAVE_ERR_MSG);
|
|
if (!pPar) {
|
|
Tcl_SetResult(pTcl, "Failed to find serial port server host name",
|
|
NULL);
|
|
KillC804(pNew);
|
|
return NULL;
|
|
}
|
|
pNew->hostname = strdup(pPar);
|
|
|
|
pPar = NULL;
|
|
pPar = (char *) Tcl_GetVar2(pTcl, pArray, "port", TCL_LEAVE_ERR_MSG);
|
|
if (!pPar) {
|
|
Tcl_SetResult(pTcl, "Failed to find serial port server port adress",
|
|
NULL);
|
|
KillC804(pNew);
|
|
return NULL;
|
|
}
|
|
iRet = Tcl_GetInt(pTcl, pPar, &iVal);
|
|
if (iRet != TCL_OK) {
|
|
Tcl_SetResult(pTcl, " Failed to convert port adress to integer", NULL);
|
|
KillC804(pNew);
|
|
return NULL;
|
|
}
|
|
pNew->iPort = iVal;
|
|
|
|
pPar = NULL;
|
|
pPar = (char *) Tcl_GetVar2(pTcl, pArray, "channel", TCL_LEAVE_ERR_MSG);
|
|
if (!pPar) {
|
|
Tcl_SetResult(pTcl, "Failed to find serial port server channel adress",
|
|
NULL);
|
|
KillC804(pNew);
|
|
return NULL;
|
|
}
|
|
iRet = Tcl_GetInt(pTcl, pPar, &iVal);
|
|
if (iRet != TCL_OK) {
|
|
Tcl_SetResult(pTcl, " Failed to convert channel number to integer",
|
|
NULL);
|
|
KillC804(pNew);
|
|
return NULL;
|
|
}
|
|
pNew->iChannel = iVal;
|
|
pPar = NULL;
|
|
|
|
pPar = (char *) Tcl_GetVar2(pTcl, pArray, "motor", TCL_LEAVE_ERR_MSG);
|
|
if (!pPar) {
|
|
Tcl_SetResult(pTcl, "Failed to find motor number", NULL);
|
|
KillC804(pNew);
|
|
return NULL;
|
|
}
|
|
iRet = Tcl_GetInt(pTcl, pPar, &iVal);
|
|
if (iRet != TCL_OK) {
|
|
Tcl_SetResult(pTcl, " Failed to convert motor number to integer",
|
|
NULL);
|
|
KillC804(pNew);
|
|
return NULL;
|
|
}
|
|
pNew->iMotor = iVal;
|
|
|
|
/* limits */
|
|
pPar = NULL;
|
|
pPar =
|
|
(char *) Tcl_GetVar2(pTcl, pArray, "lowerlimit", TCL_LEAVE_ERR_MSG);
|
|
if (!pPar) {
|
|
Tcl_SetResult(pTcl, "Failed to find lower motor limit", NULL);
|
|
KillC804(pNew);
|
|
return NULL;
|
|
}
|
|
iRet = Tcl_GetDouble(pTcl, pPar, &dVal);
|
|
if (iRet != TCL_OK) {
|
|
Tcl_SetResult(pTcl, " Failed to convert lower limit to double", NULL);
|
|
KillC804(pNew);
|
|
return NULL;
|
|
}
|
|
pNew->fLower = dVal;
|
|
|
|
pPar = NULL;
|
|
pPar =
|
|
(char *) Tcl_GetVar2(pTcl, pArray, "upperlimit", TCL_LEAVE_ERR_MSG);
|
|
if (!pPar) {
|
|
Tcl_SetResult(pTcl, "Failed to find upper motor limit", NULL);
|
|
KillC804(pNew);
|
|
return NULL;
|
|
}
|
|
iRet = Tcl_GetDouble(pTcl, pPar, &dVal);
|
|
if (iRet != TCL_OK) {
|
|
Tcl_SetResult(pTcl, " Failed to convert motor number to integer",
|
|
NULL);
|
|
KillC804(pNew);
|
|
return NULL;
|
|
}
|
|
pNew->fUpper = dVal;
|
|
|
|
|
|
/* open the serialport connection */
|
|
iRet = SerialOpen(&pNew->pSerial, pNew->hostname, pNew->iPort,
|
|
pNew->iChannel);
|
|
if (iRet != 1) {
|
|
Tcl_SetResult(pTcl,
|
|
"Failed to open connection to serial port server", NULL);
|
|
KillC804(pNew);
|
|
return NULL;
|
|
}
|
|
SerialConfig(&pNew->pSerial, 50000);
|
|
|
|
/* switch on, just to make sure */
|
|
iTmo = SerialGetTmo(&pNew->pSerial);
|
|
SerialConfig(&pNew->pSerial, 0);
|
|
sprintf(pCommand, "%1.1dMN\r", pNew->iMotor);
|
|
SerialWriteRead(&pNew->pSerial, pCommand, pReply, 39);
|
|
SerialConfig(&pNew->pSerial, iTmo + 5000);
|
|
|
|
/* configure the connection */
|
|
SerialATerm(&pNew->pSerial, "1\x03");
|
|
SerialSendTerm(&pNew->pSerial, "\r");
|
|
|
|
/* configure the function pointers */
|
|
pNew->GetPosition = PIPosition;
|
|
pNew->RunTo = PIRun;
|
|
pNew->GetStatus = PIStatus;
|
|
pNew->GetError = PIError;
|
|
pNew->TryAndFixIt = PIFixError;
|
|
pNew->Halt = PIHalt;
|
|
|
|
/* success */
|
|
return pNew;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
int PISetSpeed(pMotor pMot, SConnection * pCon, float fNew)
|
|
{
|
|
int iVal, iRet, iTmo;
|
|
char pCommand[20], pReply[80], pError[132];
|
|
pC804Driv self = NULL;
|
|
|
|
assert(pMot);
|
|
self = (pC804Driv) pMot->pDriver;
|
|
assert(self);
|
|
|
|
iVal = (int) fNew;
|
|
sprintf(pCommand, "%1.1dSV%7.7d\r", self->iMotor, iVal);
|
|
iTmo = SerialGetTmo(&self->pSerial);
|
|
SerialConfig(&self->pSerial, 0);
|
|
iRet = SerialWriteRead(&self->pSerial, pCommand, pReply, 79);
|
|
SerialConfig(&self->pSerial, iTmo);
|
|
if (iRet != 1) {
|
|
self->iLastError = iRet;
|
|
PIError(self, &iRet, pReply, 79);
|
|
sprintf(pError, "ERROR: %s", pReply);
|
|
SCWrite(pCon, pError, eError);
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
int PIHome(pMotor pMot, SConnection * pCon)
|
|
{
|
|
int iVal, iRet, iTmo;
|
|
char pCommand[20], pReply[80], pError[132];
|
|
pC804Driv self = NULL;
|
|
|
|
assert(pMot);
|
|
self = (pC804Driv) pMot->pDriver;
|
|
assert(self);
|
|
|
|
sprintf(pCommand, "%1.1dDH\r", self->iMotor);
|
|
iTmo = SerialGetTmo(&self->pSerial);
|
|
SerialConfig(&self->pSerial, 0);
|
|
iRet = SerialWriteRead(&self->pSerial, pCommand, pReply, 79);
|
|
SerialConfig(&self->pSerial, iTmo);
|
|
if (iRet != 1) {
|
|
self->iLastError = iRet;
|
|
PIError(self, &iRet, pReply, 79);
|
|
sprintf(pError, "ERROR: %s", pReply);
|
|
SCWrite(pCon, pError, eError);
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
int PIOn(pMotor pMot, SConnection * pCon)
|
|
{
|
|
int iVal, iRet, iTmo;
|
|
char pCommand[20], pReply[80], pError[132];
|
|
pC804Driv self = NULL;
|
|
|
|
assert(pMot);
|
|
self = (pC804Driv) pMot->pDriver;
|
|
assert(self);
|
|
|
|
sprintf(pCommand, "%1.1dMN\r", self->iMotor);
|
|
iTmo = SerialGetTmo(&self->pSerial);
|
|
SerialConfig(&self->pSerial, 0);
|
|
iRet = SerialWriteRead(&self->pSerial, pCommand, pReply, 79);
|
|
SerialConfig(&self->pSerial, iTmo);
|
|
if (iRet != 1) {
|
|
self->iLastError = iRet;
|
|
PIError(self, &iRet, pReply, 79);
|
|
sprintf(pError, "ERROR: %s", pReply);
|
|
SCWrite(pCon, pError, eError);
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
int PIGetSpeed(pMotor pMot, SConnection * pCon, float *fNew)
|
|
{
|
|
int iVal, iRet;
|
|
char pCommand[20], pReply[80], pError[132], *pPtr;
|
|
pC804Driv self = NULL;
|
|
|
|
assert(pMot);
|
|
self = (pC804Driv) pMot->pDriver;
|
|
assert(self);
|
|
|
|
sprintf(pCommand, "%1.1dTY\r", self->iMotor);
|
|
iRet = SerialWriteRead(&self->pSerial, pCommand, pReply, 79);
|
|
if (iRet != 1) {
|
|
self->iLastError = iRet;
|
|
PIError(self, &iRet, pReply, 79);
|
|
sprintf(pError, "ERROR: %s", pReply);
|
|
SCWrite(pCon, pError, eError);
|
|
return 0;
|
|
}
|
|
pPtr = pReply + 3;
|
|
*fNew = atof(pPtr);
|
|
return 1;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
int PIMotorWrapper(SConnection * pCon, SicsInterp * pSics, void *pData,
|
|
int argc, char *argv[])
|
|
{
|
|
pMotor pMot = NULL;
|
|
double dVal;
|
|
float fVal;
|
|
char pBueffel[256];
|
|
int iRet;
|
|
|
|
pMot = (pMotor) pData;
|
|
|
|
assert(pCon);
|
|
assert(pSics);
|
|
assert(pMot);
|
|
|
|
if (argc >= 2) {
|
|
strtolower(argv[1]);
|
|
if (strcmp(argv[1], "speed") == 0) {
|
|
if (argc >= 3) {
|
|
iRet = Tcl_GetDouble(pSics->pTcl, argv[2], &dVal);
|
|
if (iRet != TCL_OK) {
|
|
SCWrite(pCon, "ERROR: speed parameter not recognised as number",
|
|
eError);
|
|
return 0;
|
|
}
|
|
if (!SCMatchRights(pCon, usMugger)) {
|
|
SCWrite(pCon, "ERROR: Insufficient privilege to change speed",
|
|
eError);
|
|
return 0;
|
|
}
|
|
iRet = PISetSpeed(pMot, pCon, (float) dVal);
|
|
if (!iRet) {
|
|
return 0;
|
|
}
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
} else {
|
|
iRet = PIGetSpeed(pMot, pCon, &fVal);
|
|
if (!iRet) {
|
|
return 0;
|
|
}
|
|
sprintf(pBueffel, "%s.speed = %f", argv[0], fVal);
|
|
SCWrite(pCon, pBueffel, eValue);
|
|
return 1;
|
|
}
|
|
} /* end speed */
|
|
if (strcmp(argv[1], "home") == 0) {
|
|
if (!SCMatchRights(pCon, usMugger)) {
|
|
SCWrite(pCon, "ERROR: Insufficient privilege to change hardware 0",
|
|
eError);
|
|
return 0;
|
|
}
|
|
iRet = PIHome(pMot, pCon);
|
|
if (!iRet) {
|
|
return 0;
|
|
}
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
if (strcmp(argv[1], "on") == 0) {
|
|
if (!SCMatchRights(pCon, usUser)) {
|
|
SCWrite(pCon, "ERROR: Insufficient privilege to switch motor on",
|
|
eError);
|
|
return 0;
|
|
}
|
|
iRet = PIOn(pMot, pCon);
|
|
if (!iRet) {
|
|
return 0;
|
|
}
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
if (strcmp(argv[1], "list") == 0) {
|
|
iRet = PIGetSpeed(pMot, pCon, &fVal);
|
|
if (!iRet) {
|
|
return 0;
|
|
}
|
|
sprintf(pBueffel, "%s.speed = %f", argv[0], fVal);
|
|
SCWrite(pCon, pBueffel, eValue);
|
|
return MotorAction(pCon, pSics, pData, argc, argv);
|
|
}
|
|
|
|
}
|
|
|
|
/* end arguments */
|
|
/* forward everything else to main motor handler */
|
|
return MotorAction(pCon, pSics, pData, argc, argv);
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
static void PIMotorKill(void *self)
|
|
{
|
|
pMotor pM;
|
|
assert(self);
|
|
|
|
pM = (pMotor) self;
|
|
|
|
if (pM->name)
|
|
free(pM->name);
|
|
|
|
if (pM->pDrivInt) {
|
|
free(pM->pDrivInt);
|
|
}
|
|
|
|
if (pM->pCall) {
|
|
DeleteCallBackInterface(pM->pCall);
|
|
}
|
|
|
|
/* kill driver */
|
|
if (pM->drivername) {
|
|
if (strcmp(pM->drivername, "c804") == 0) {
|
|
if (pM->pDriver) {
|
|
KillC804((pC804Driv) pM->pDriver);
|
|
}
|
|
} else if (strcmp(pM->drivername, "SIM") == 0) {
|
|
if (pM->pDriver) {
|
|
KillSIM((void *) pM->pDriver);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (pM->drivername) {
|
|
free(pM->drivername);
|
|
}
|
|
|
|
/* kill Descriptor */
|
|
DeleteDescriptor(pM->pDescriptor);
|
|
|
|
free(pM);
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
int PIMotorFactory(SConnection * pCon, SicsInterp * pSics, void *pData,
|
|
int argc, char *argv[])
|
|
{
|
|
pMotor pNew = NULL;
|
|
MotorDriver *pDriver = NULL;
|
|
char pBueffel[512];
|
|
int iD, iRet;
|
|
Tcl_Interp *ppTcl;
|
|
|
|
assert(pCon);
|
|
assert(pSics);
|
|
|
|
/* a first check */
|
|
if (argc < 3) {
|
|
SCWrite(pCon, "Insufficient arguments for motor creation", eError);
|
|
return 0;
|
|
}
|
|
|
|
/* create the driver */
|
|
strtolower(argv[2]);
|
|
strtolower(argv[1]);
|
|
if (strcmp(argv[2], "c804") == 0) {
|
|
pDriver = (MotorDriver *) MakeC804Driver(pSics->pTcl, argv[3]);
|
|
if (!pDriver) {
|
|
ppTcl = (Tcl_Interp *) pSics->pTcl;
|
|
SCWrite(pCon, ppTcl->result, eError);
|
|
return 0;
|
|
}
|
|
/* create the motor */
|
|
pNew = MotorInit("c804", argv[1], pDriver);
|
|
if (!pNew) {
|
|
sprintf(pBueffel, "Failure to create motor %s", argv[1]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
} else if (strcmp(argv[2], "sim") == 0) {
|
|
iD = argc - 3;
|
|
pDriver = CreateSIM(pCon, iD, &argv[3]);
|
|
if (!pDriver) {
|
|
return 0;
|
|
}
|
|
/* create the motor */
|
|
pNew = MotorInit("SIM", argv[1], pDriver);
|
|
if (!pNew) {
|
|
sprintf(pBueffel, "Failure to create motor %s", argv[1]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
} else {
|
|
sprintf(pBueffel, "Motor Type %s cot recognized for motor %s",
|
|
argv[2], argv[1]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
|
|
/* create the interpreter command */
|
|
iRet = AddCommand(pSics, argv[1], PIMotorWrapper, PIMotorKill, pNew);
|
|
if (!iRet) {
|
|
sprintf(pBueffel, "ERROR: duplicate command %s not created", argv[1]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|