- First working version of counter driver for ECB

- Motor driver works for normal, control and encoder motors
This commit is contained in:
cvs
2003-01-29 07:42:18 +00:00
parent e4d4643123
commit b1fd8e77ac
9 changed files with 631 additions and 15 deletions

View File

@ -58,7 +58,8 @@ SOBJ = network.o ifile.o conman.o SCinter.o splitter.o passwd.o \
tasdrive.o tasscan.o synchronize.o definealias.o swmotor.o t_update.o \
hmcontrol.o userscan.o slsmagnet.o rs232controller.o lomax.o \
polterwrite.o fourlib.o motreg.o motreglist.o anticollider.o \
s_rnge.o sig_die.o gpibcontroller.o $(NIOBJ) ecb.o ecbdriv.o
s_rnge.o sig_die.o gpibcontroller.o $(NIOBJ) ecb.o ecbdriv.o \
ecbcounter.o
MOTOROBJ = motor.o el734driv.o simdriv.o el734dc.o pipiezo.o pimotor.o
COUNTEROBJ = countdriv.o simcter.o counter.o

View File

@ -565,7 +565,7 @@
return COTERM;
}
/*-------------------------------------------------------------------------*/
static int EL737Set(struct __COUNTER *self, int iCode, int iCter,
static int EL737Set(struct __COUNTER *self, char *name, int iCter,
float fVal)
{
int iRet;
@ -576,7 +576,7 @@
pEL737 = (EL737st *)self->pData;
assert(pEL737);
if(iCode == PARTHRESHOLD)
if(strcmp(name,"threshold") == 0)
{
sprintf(pCommand,"DL %1.1d %f\r",iCter,fVal);
iRet = EL737_SendCmnd(&pEL737->pData,pCommand,pReply,79);
@ -615,7 +615,7 @@
}
}
/*-------------------------------------------------------------------------*/
static int EL737Get(struct __COUNTER *self, int iCode, int iCter,
static int EL737Get(struct __COUNTER *self, char *name, int iCter,
float *fVal)
{
int iRet;
@ -626,7 +626,7 @@
pEL737 = (EL737st *)self->pData;
assert(pEL737);
if(iCode == PARTHRESHOLD)
if(strcmp(name,"threshold") == 0)
{
sprintf(pCommand,"DL %1.1d\r",iCter);
iRet = EL737_SendCmnd(&pEL737->pData,pCommand,pReply,79);

View File

@ -55,9 +55,9 @@
int (*GetError)(struct __COUNTER *self, int *iCode,
char *error, int iErrLen);
int (*TryAndFixIt)(struct __COUNTER *self, int iCode);
int (*Set)(struct __COUNTER *self,int iCode,
int (*Set)(struct __COUNTER *self,char *name,
int iCter, float fVal);
int (*Get)(struct __COUNTER *self,int iCode,
int (*Get)(struct __COUNTER *self,char *name,
int iCter, float *fVal);
int (*Send)(struct __COUNTER *self, char *pText,
char *pReply, int iReplyLen);

View File

@ -50,6 +50,7 @@
#include "fupa.h"
#include "status.h"
#include "splitter.h"
#include "ecbcounter.h"
/*-------------------------------------------------------------------------*/
/*
The monitor callback data structure
@ -419,6 +420,10 @@
{
KillSIMCounter(self->pDriv);
}
else if(strcmp(self->pDriv->type,"ecb") == 0)
{
KillECBCounter(self->pDriv);
}
else
{
assert(0);
@ -486,6 +491,7 @@
}
/*-------------------------------------------------------------------------*/
int MakeCounter(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[])
{
@ -497,7 +503,8 @@
FuPaResult pParse;
FuncTemplate MakeTemplate[] = {
{"el737",3,{FUPATEXT,FUPAINT,FUPAINT}},
{"sim",1,{FUPAFLOAT}}
{"sim",1,{FUPAFLOAT}},
{"ecb",1,{FUPATEXT}}
};
assert(pCon);
@ -506,7 +513,7 @@
argtolower(argc,argv);
/* parse function template */
argx = &argv[2]; /* 0 = MakeCounter, 1 = counter name */
iRet = EvaluateFuPa((pFuncTemplate)&MakeTemplate,2,argc-2,argx,&pParse);
iRet = EvaluateFuPa((pFuncTemplate)&MakeTemplate,3,argc-2,argx,&pParse);
if(iRet < 0) /* I/O error */
{
sprintf(pBueffel,"%s",pParse.pError);
@ -524,6 +531,9 @@
case 1: /* SIM */
pDriv = NewSIMCounter(argv[1],pParse.Arg[0].fVal);
break;
case 2: /* ecb */
pDriv = MakeECBCounter(pParse.Arg[0].text);
break;
default:
assert(0); /* internal error */
}
@ -743,7 +753,9 @@
{"stop",0,{0,0}},
{"mode",1,{FUPAOPT}},
{"preset",1,{FUPAOPT}},
{"send",0,{0,0}}
{"send",0,{0,0}},
{"setpar",3,{FUPATEXT,FUPAINT,FUPAFLOAT}},
{"getpar",2,{FUPATEXT,FUPAOPT}}
};
char *pMode[] = {
"timer",
@ -759,7 +771,7 @@
/* parse function args */
argtolower(argc,argv);
argx = &argv[1];
iRet = EvaluateFuPa((pFuncTemplate)&ActionTemplate,20,argc-1,argx,&PaRes);
iRet = EvaluateFuPa((pFuncTemplate)&ActionTemplate,22,argc-1,argx,&PaRes);
if(iRet < 0)
{
sprintf(pBueffel,"%s",PaRes.pError);
@ -903,7 +915,7 @@
break;
case 14:
/* get threshold value */
iRet = self->pDriv->Get(self->pDriv,PARTHRESHOLD,
iRet = self->pDriv->Get(self->pDriv,"threshold",
PaRes.Arg[0].iVal,&fVal);
if(iRet <= 0)
{
@ -936,7 +948,7 @@
return 0;
}
/* set threshold value */
iRet = self->pDriv->Set(self->pDriv,PARTHRESHOLD,
iRet = self->pDriv->Set(self->pDriv,"threshold",
PaRes.Arg[0].iVal,PaRes.Arg[1].fVal);
if(iRet <= 0)
{
@ -1048,6 +1060,46 @@
return 0;
}
break;
case 20: /* setpar*/
if(!SCMatchRights(pCon,usMugger))
{
return 0;
}
iRet = self->pDriv->Set(self->pDriv,PaRes.Arg[0].text,
PaRes.Arg[1].iVal, PaRes.Arg[2].fVal);
if(iRet == 1)
{
SCSendOK(pCon);
return 1;
}
else
{
self->pDriv->GetError(self->pDriv,&iRet,pError,79);
SCWrite(pCon,pError,eError);
return 0;
}
break;
case 21: /* getpar*/
if(!SCMatchRights(pCon,usMugger))
{
return 0;
}
iRet = self->pDriv->Get(self->pDriv,PaRes.Arg[0].text,
PaRes.Arg[1].iVal, &fVal);
if(iRet == 1)
{
sprintf(pBueffel,"%s.%s %d = %f",argv[0],PaRes.Arg[0].text,
PaRes.Arg[1].iVal, fVal);
SCWrite(pCon,pBueffel,eValue);
return 1;
}
else
{
self->pDriv->GetError(self->pDriv,&iRet,pError,79);
SCWrite(pCon,pError,eError);
return 0;
}
break;
default:
assert(0); /* internal error */
}

23
ecb.i Normal file
View File

@ -0,0 +1,23 @@
/*-----------------------------------------------------------------------
The ECB is a rack controller from Risoe based on a Z80 processor.
This module provides some functions for communicating with such a
device. This is an internal data structure definition file.
copyright: see file COPYRIGHT
Mark Koennecke, January 2002, with some bits taken out of the
original tascom code.
------------------------------------------------------------------------*/
struct __ECB {
pObjectDescriptor pDes;
pGPIB gpib;
int boardNumber;
int ecbAddress;
int ecbDeviceID;
int lastError;
int encoder[3];
int encoderDirty;
}ECB;

520
ecbcounter.c Normal file
View File

@ -0,0 +1,520 @@
/*----------------------------------------------------------------------------
This is a single counter implemented on top of the Risoe ECB electronic
copyright: see file COPYRIGHT
Mark Koennecke, January-February 2003
---------------------------------------------------------------------------*/
#include <stdlib.h>
#include <assert.h>
#include <errno.h>
#include <tcl.h>
#include <math.h>
#include <unistd.h>
#include "fortify.h"
#include "sics.h"
#include "ecb.h"
#include "countdriv.h"
/*------------------ our private data structure ------------------------*/
typedef struct {
pECB ecb; /* the ECB system we talk to */
unsigned char prescaler[8]; /* an array for the prescaler values */
int tfreq; /* timer frequency */
unsigned char control; /* marks the control monitor */
}ECBCounter, *pECBCounter;
/*----------------- private defines ------------------------------------*/
#define STFRD 137
#define STREAD 138
#define STOPS 136
#define STCLEA 134
#define PRELOA 139
#define STLOAD 156
#define STCPRE 133
#define STARTS 135
#define MAX_COUNT 4294967295.0
/*------------------ error codes --------------------------------------*/
#define COMMERROR -300
#define TOMANYCOUNTS -301
#define NOSEND -302
#define INVALIDCOUNTER -304
#define INVALIDPRESCALER -305
#define BADFREQ -306
/*======================================================================*/
static int readScaler(pECBCounter pPriv, int scaler, int *count){
int status;
Z80_reg in, out;
Ecb_pack data;
in.c = (unsigned char)scaler;
status = ecbExecute(pPriv->ecb,STREAD,in,&out);
if(status != 1){
return COMMERROR;
}
data.b.byt3 = out.c;
data.b.byt2 = out.b;
data.b.byt1 = out.d;
data.b.byt0 = out.e;
if(scaler == 0){
*count = data.result/pPriv->tfreq;
} else {
*count = data.result;
}
return 1;
}
/*-----------------------------------------------------------------------*/
static int ECBGetStatus(struct __COUNTER *self, float *fControl){
pECBCounter pPriv = (pECBCounter)self->pData;
int status, result, scaler;
Z80_reg in, out;
int count;
assert(pPriv);
/*
read status bit
*/
status = ecbExecute(pPriv->ecb,STFRD,in,&out);
if(status != 1){
self->iErrorCode = COMMERROR;
return HWFault;
}
if(out.d == 0){
result = HWIdle;
} else {
result = HWBusy;
}
/*
select which scaler to read
*/
if(self->eMode == eTimer){
scaler = 0;
}else {
scaler = pPriv->control;
}
readScaler(pPriv,scaler,&count);
/*
ignore errors on this one
*/
*fControl = (float)count;
return result;
}
/*======================================================================*/
static int stopScalers(pECBCounter self){
int status;
Z80_reg in, out;
status = ecbExecute(self->ecb,STOPS,in,&out);
if(status != 1){
return COMMERROR;
}
return 1;
}
/*----------------------------------------------------------------------*/
static int clearScalers(pECBCounter self){
int status;
Z80_reg in, out;
status = ecbExecute(self->ecb,STCLEA,in,&out);
if(status != 1){
return COMMERROR;
}
return 1;
}
/*----------------------------------------------------------------------*/
static int loadPrescalers(pECBCounter self){
Z80_reg in, out;
int status, i;
for(i = 0; i < 8; i++){
in.c = (unsigned char)i;
in.d = self->prescaler[i];
status = ecbExecute(self->ecb,PRELOA,in,&out);
if(status != 1){
return COMMERROR;
}
}
return 1;
}
/*----------------------------------------------------------------------*/
static int loadPreset(pECBCounter self, int preset, unsigned char control){
Z80_reg in, out;
Ecb_pack data;
int status, i;
data.result = preset;
in.c = data.b.byt3;
in.b = data.b.byt2;
in.e = data.b.byt1;
in.d = data.b.byt0;
status = ecbExecute(self->ecb,STLOAD,in,&out);
if(status != 1){
return COMMERROR;
}
in.b = data.b.byt2;
in.e = data.b.byt1;
in.d = data.b.byt0;
in.c = 4*control;
status = ecbExecute(self->ecb,STCPRE,in,&out);
if(status != 1){
return COMMERROR;
}
return 1;
}
/*-----------------------------------------------------------------------*/
static int ECBStart(struct __COUNTER *self){
pECBCounter pPriv = NULL;
int preset, status, controlUnit;
Z80_reg in, out;
assert(self);
pPriv = (pECBCounter)self->pData;
assert(pPriv);
/*
check if the preset is permissible
*/
preset = (int)rint(self->fPreset);
if(preset > MAX_COUNT){
self->iErrorCode = TOMANYCOUNTS;
return HWFault;
}
if(self->eMode == eTimer){
controlUnit = 0;
preset *= pPriv->tfreq;
if(preset > MAX_COUNT){
self->iErrorCode = TOMANYCOUNTS;
return HWFault;
}
} else {
controlUnit = pPriv->control;
}
if((status = stopScalers(pPriv)) <= 0){
self->iErrorCode = status;
return HWFault;
}
if((status = clearScalers(pPriv)) <= 0){
self->iErrorCode = status;
return HWFault;
}
if((status = loadPrescalers(pPriv)) <= 0){
self->iErrorCode = status;
return HWFault;
}
if((status = loadPreset(pPriv, preset,(unsigned char)controlUnit)) <= 0){
self->iErrorCode = status;
return HWFault;
}
status = ecbExecute(pPriv->ecb,STARTS,in,&out);
if(status != 1){
self->iErrorCode = status;
return HWFault;
}
return OKOK;
}
/*========================================================================
These two functions currently rely on the idea that the ECB stops
and starts without clearing counters in between. The sequence of
things necessary to start it, suggests this. If this is not the case then
this will not work.
===========================================================================*/
static int ECBPause(struct __COUNTER *self){
int status;
pECBCounter pPriv = NULL;
assert(self);
pPriv = (pECBCounter)self->pData;
assert(pPriv);
if((status = stopScalers(pPriv)) <= 0){
self->iErrorCode = status;
return HWFault;
}
return OKOK;
}
/*=======================================================================*/
static int ECBContinue(struct __COUNTER *self){
int status;
pECBCounter pPriv = NULL;
Z80_reg in, out;
assert(self);
pPriv = (pECBCounter)self->pData;
assert(pPriv);
status = ecbExecute(pPriv->ecb,STARTS,in,&out);
if(status != 1){
self->iErrorCode = status;
return HWFault;
}
return OKOK;
}
/*=======================================================================*/
static int ECBHalt(struct __COUNTER *self){
int status;
pECBCounter pPriv = NULL;
assert(self);
pPriv = (pECBCounter)self->pData;
assert(pPriv);
if((status = stopScalers(pPriv)) <= 0){
self->iErrorCode = status;
return HWFault;
}
return OKOK;
}
/*=======================================================================*/
static int ECBTransfer(struct __COUNTER *self){
int status, count, i;
pECBCounter pPriv = NULL;
assert(self);
pPriv = (pECBCounter)self->pData;
assert(pPriv);
/*
read time
*/
status = readScaler(pPriv,0,&count);
if(status <= 0){
self->iErrorCode = COMMERROR;
return HWFault;
}
self->fTime = (float)count;
/*
read other scalers
*/
for(i = 1; i < 8; i++){
status = readScaler(pPriv,i,&count);
if(status <= 0){
self->iErrorCode = COMMERROR;
return HWFault;
}
self->lCounts[i-1] = count;
}
return OKOK;
}
/*======================================================================*/
static int ECBGetError(struct __COUNTER *self, int *iCode,
char *errorText, int errlen){
char pBueffel[132];
*iCode = self->iErrorCode;
switch(self->iErrorCode){
case COMMERROR:
strncpy(errorText,"Communication error with ECB",errlen);
break;
case TOMANYCOUNTS:
strncpy(errorText,"Preset is to high!",errlen);
break;
case NOSEND:
strncpy(errorText,"Cannot send naked data to ECB",errlen);
break;
case UNKNOWNPAR:
strncpy(errorText,"parameter unknown",errlen);
break;
case INVALIDCOUNTER:
strncpy(errorText,"Invalid counter number requested, 0-7 allowed",
errlen);
break;
case INVALIDPRESCALER:
strncpy(errorText,"Invalid prescaler value, allowed 1 or 10",
errlen);
break;
case BADFREQ:
strncpy(errorText,"Bad timer frequency: 10 or 1000 allowed",errlen);
break;
default:
sprintf(pBueffel,"Unknown error code %d", self->iErrorCode);
strncpy(errorText,pBueffel,errlen);
break;
}
return 1;
}
/*=======================================================================*/
static int ECBFixIt(struct __COUNTER *self, int iCode){
return COTERM;
}
/*======================================================================*/
/*******************************************************************************
* Load the parameters 'dot' and 'divide' for a motor or an encoder.
* 'dot' specifies the placement of a punctuation mark on the display
* of f.ex a motor position. 'divide' specifies how many times the po-
* sition is to be divided by two before it is displayed.
******************************************************************************/
static void
Dot_divide (int device, int data, pECB ecb)
{
int function, dot, divide;
Z80_reg x_inreg, out;
if (data == 0) /* If zero, dont send dot/divide) */
return;
dot = 0;
while ((data%10) == 0)
{
dot++;
data /= 10;
}
divide = 0;
while ((data%2) == 0)
{
divide++;
data /= 2;
}
if (data != 1) /* If != 1, not a binary No. */
return;
if (dot > 0)
dot = 8 - dot;
x_inreg.c = 0; /* Specify input */
x_inreg.b = (unsigned char) device;
x_inreg.d = (unsigned char) dot; /* Dot position */
x_inreg.e = (unsigned char) divide; /* No. of times to divide by 2 */
ecbExecute(ecb,170,x_inreg,&out);
return;
}
/*-----------------------------------------------------------------------*/
static int ECBSet(struct __COUNTER *self, char *name,
int iCter, float fVal){
pECBCounter pPriv = NULL;
int iVal;
assert(self);
pPriv = (pECBCounter)self->pData;
assert(pPriv);
iVal = (int)rint(fVal);
if(strcmp(name,"prescaler") == 0){
if(iCter < 0 || iCter > 7){
self->iErrorCode = INVALIDCOUNTER;
return HWFault;
}
if(iVal != 1 && iVal != 10){
self->iErrorCode = INVALIDPRESCALER;
return HWFault;
}
pPriv->prescaler[iCter] = (unsigned char)iVal;
return OKOK;
} else if(strcmp(name,"tfreq") == 0){
if(fVal == 1000){
pPriv->prescaler[0] = 1;
pPriv->tfreq = 1000;
Dot_divide(64,1000,pPriv->ecb);
return OKOK;
} else if(fVal == 10){
pPriv->tfreq = 10;
pPriv->prescaler[0] = 10;
Dot_divide(64,10,pPriv->ecb);
return OKOK;
} else {
self->iErrorCode = BADFREQ;
return HWFault;
}
} else {
self->iErrorCode = UNKNOWNPAR;
return HWFault;
}
}
/*===================================================================*/
static int ECBGet(struct __COUNTER *self, char *name,
int iCter, float *fVal){
pECBCounter pPriv = NULL;
assert(self);
pPriv = (pECBCounter)self->pData;
assert(pPriv);
if(strcmp(name,"prescaler") == 0){
*fVal = (float)pPriv->prescaler[iCter];
return OKOK;
} else if(strcmp(name,"tfreq") == 0){
*fVal = (float)pPriv->tfreq;
return OKOK;
} else{
self->iErrorCode = UNKNOWNPAR;
return HWFault;
}
}
/*=====================================================================*/
static int ECBSend(struct __COUNTER *self, char *text,
char *reply, int replylen){
strncpy(reply,"ECB does not feast on ASCII strings, refused!",
replylen);
return OKOK;
}
/*====================================================================*/
pCounterDriver MakeECBCounter(char *ecb){
pECBCounter pPriv = NULL;
pCounterDriver self = NULL;
int i;
/*
memory for everybody
*/
self = CreateCounterDriver("ecb","ecb");
pPriv = (pECBCounter)malloc(sizeof(ECBCounter));
if(self == NULL || pPriv == NULL){
return NULL;
}
memset(pPriv,0,sizeof(ECBCounter));
/*
initialize private data structure
*/
pPriv->ecb = (pECB)FindCommandData(pServ->pSics,ecb,"ECB");
if(pPriv->ecb == NULL){
DeleteCounterDriver(self);
free(pPriv);
return NULL;
}
for(i = 0; i < 8; i++){
pPriv->prescaler[i] = 1;
}
pPriv->tfreq = 1000;
pPriv->control = 1;
/*
assign function pointers
*/
self->GetStatus = ECBGetStatus;
self->Start = ECBStart;
self->Pause = ECBPause;
self->Continue = ECBContinue;
self->Halt = ECBHalt;
self->ReadValues = ECBTransfer;
self->GetError = ECBGetError;
self->TryAndFixIt = ECBFixIt;
self->Set = ECBSet;
self->Get = ECBGet;
self->Send = ECBSend;
self->pData = pPriv;
return self;
}
/*=====================================================================*/
void KillECBCounter(struct __COUNTER *self){
DeleteCounterDriver(self);
}

17
ecbcounter.h Normal file
View File

@ -0,0 +1,17 @@
/*-------------------------------------------------------------------------
Header file for the counter driver for the Risoe ECB system.
copyright: see file COPYRIGHT
Mark Koennecke, January 2003
-------------------------------------------------------------------------*/
#ifndef ECBCOUNTER
#define ECBCOUNTER
#include "countdriv.h"
pCounterDriver MakeECBCounter(char *ecb);
void KillECBCounter(CounterDriver *pDriv);
#endif

View File

@ -1,3 +1,6 @@
# Counter counter
counter SetPreset 60.000000
counter SetMode Timer
# Motor a77
a77 sign 1.000000
a77 SoftZero 0.000000

View File

@ -292,12 +292,12 @@ static float FAILRATE;
return COREDO;
}
/*--------------------------------------------------------------------------*/
static int SIMSet(struct __COUNTER *self, int iCode, int iCter, float FVal)
static int SIMSet(struct __COUNTER *self, char *name, int iCter, float FVal)
{
return 1;
}
/*--------------------------------------------------------------------------*/
static int SIMGet(struct __COUNTER *self, int iCode, int iCter, float *fVal)
static int SIMGet(struct __COUNTER *self, char *name, int iCter, float *fVal)
{
*fVal = 25.999;
return 1;