- First working version of counter driver for ECB
- Motor driver works for normal, control and encoder motors
This commit is contained in:
3
Makefile
3
Makefile
@ -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 \
|
tasdrive.o tasscan.o synchronize.o definealias.o swmotor.o t_update.o \
|
||||||
hmcontrol.o userscan.o slsmagnet.o rs232controller.o lomax.o \
|
hmcontrol.o userscan.o slsmagnet.o rs232controller.o lomax.o \
|
||||||
polterwrite.o fourlib.o motreg.o motreglist.o anticollider.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
|
MOTOROBJ = motor.o el734driv.o simdriv.o el734dc.o pipiezo.o pimotor.o
|
||||||
COUNTEROBJ = countdriv.o simcter.o counter.o
|
COUNTEROBJ = countdriv.o simcter.o counter.o
|
||||||
|
@ -565,7 +565,7 @@
|
|||||||
return COTERM;
|
return COTERM;
|
||||||
}
|
}
|
||||||
/*-------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------*/
|
||||||
static int EL737Set(struct __COUNTER *self, int iCode, int iCter,
|
static int EL737Set(struct __COUNTER *self, char *name, int iCter,
|
||||||
float fVal)
|
float fVal)
|
||||||
{
|
{
|
||||||
int iRet;
|
int iRet;
|
||||||
@ -576,7 +576,7 @@
|
|||||||
pEL737 = (EL737st *)self->pData;
|
pEL737 = (EL737st *)self->pData;
|
||||||
assert(pEL737);
|
assert(pEL737);
|
||||||
|
|
||||||
if(iCode == PARTHRESHOLD)
|
if(strcmp(name,"threshold") == 0)
|
||||||
{
|
{
|
||||||
sprintf(pCommand,"DL %1.1d %f\r",iCter,fVal);
|
sprintf(pCommand,"DL %1.1d %f\r",iCter,fVal);
|
||||||
iRet = EL737_SendCmnd(&pEL737->pData,pCommand,pReply,79);
|
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)
|
float *fVal)
|
||||||
{
|
{
|
||||||
int iRet;
|
int iRet;
|
||||||
@ -626,7 +626,7 @@
|
|||||||
pEL737 = (EL737st *)self->pData;
|
pEL737 = (EL737st *)self->pData;
|
||||||
assert(pEL737);
|
assert(pEL737);
|
||||||
|
|
||||||
if(iCode == PARTHRESHOLD)
|
if(strcmp(name,"threshold") == 0)
|
||||||
{
|
{
|
||||||
sprintf(pCommand,"DL %1.1d\r",iCter);
|
sprintf(pCommand,"DL %1.1d\r",iCter);
|
||||||
iRet = EL737_SendCmnd(&pEL737->pData,pCommand,pReply,79);
|
iRet = EL737_SendCmnd(&pEL737->pData,pCommand,pReply,79);
|
||||||
|
@ -55,9 +55,9 @@
|
|||||||
int (*GetError)(struct __COUNTER *self, int *iCode,
|
int (*GetError)(struct __COUNTER *self, int *iCode,
|
||||||
char *error, int iErrLen);
|
char *error, int iErrLen);
|
||||||
int (*TryAndFixIt)(struct __COUNTER *self, int iCode);
|
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 iCter, float fVal);
|
||||||
int (*Get)(struct __COUNTER *self,int iCode,
|
int (*Get)(struct __COUNTER *self,char *name,
|
||||||
int iCter, float *fVal);
|
int iCter, float *fVal);
|
||||||
int (*Send)(struct __COUNTER *self, char *pText,
|
int (*Send)(struct __COUNTER *self, char *pText,
|
||||||
char *pReply, int iReplyLen);
|
char *pReply, int iReplyLen);
|
||||||
|
64
counter.c
64
counter.c
@ -50,6 +50,7 @@
|
|||||||
#include "fupa.h"
|
#include "fupa.h"
|
||||||
#include "status.h"
|
#include "status.h"
|
||||||
#include "splitter.h"
|
#include "splitter.h"
|
||||||
|
#include "ecbcounter.h"
|
||||||
/*-------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------*/
|
||||||
/*
|
/*
|
||||||
The monitor callback data structure
|
The monitor callback data structure
|
||||||
@ -419,6 +420,10 @@
|
|||||||
{
|
{
|
||||||
KillSIMCounter(self->pDriv);
|
KillSIMCounter(self->pDriv);
|
||||||
}
|
}
|
||||||
|
else if(strcmp(self->pDriv->type,"ecb") == 0)
|
||||||
|
{
|
||||||
|
KillECBCounter(self->pDriv);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
assert(0);
|
assert(0);
|
||||||
@ -486,6 +491,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------*/
|
||||||
|
|
||||||
int MakeCounter(SConnection *pCon, SicsInterp *pSics, void *pData,
|
int MakeCounter(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||||
int argc, char *argv[])
|
int argc, char *argv[])
|
||||||
{
|
{
|
||||||
@ -497,7 +503,8 @@
|
|||||||
FuPaResult pParse;
|
FuPaResult pParse;
|
||||||
FuncTemplate MakeTemplate[] = {
|
FuncTemplate MakeTemplate[] = {
|
||||||
{"el737",3,{FUPATEXT,FUPAINT,FUPAINT}},
|
{"el737",3,{FUPATEXT,FUPAINT,FUPAINT}},
|
||||||
{"sim",1,{FUPAFLOAT}}
|
{"sim",1,{FUPAFLOAT}},
|
||||||
|
{"ecb",1,{FUPATEXT}}
|
||||||
};
|
};
|
||||||
|
|
||||||
assert(pCon);
|
assert(pCon);
|
||||||
@ -506,7 +513,7 @@
|
|||||||
argtolower(argc,argv);
|
argtolower(argc,argv);
|
||||||
/* parse function template */
|
/* parse function template */
|
||||||
argx = &argv[2]; /* 0 = MakeCounter, 1 = counter name */
|
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 */
|
if(iRet < 0) /* I/O error */
|
||||||
{
|
{
|
||||||
sprintf(pBueffel,"%s",pParse.pError);
|
sprintf(pBueffel,"%s",pParse.pError);
|
||||||
@ -524,6 +531,9 @@
|
|||||||
case 1: /* SIM */
|
case 1: /* SIM */
|
||||||
pDriv = NewSIMCounter(argv[1],pParse.Arg[0].fVal);
|
pDriv = NewSIMCounter(argv[1],pParse.Arg[0].fVal);
|
||||||
break;
|
break;
|
||||||
|
case 2: /* ecb */
|
||||||
|
pDriv = MakeECBCounter(pParse.Arg[0].text);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
assert(0); /* internal error */
|
assert(0); /* internal error */
|
||||||
}
|
}
|
||||||
@ -743,7 +753,9 @@
|
|||||||
{"stop",0,{0,0}},
|
{"stop",0,{0,0}},
|
||||||
{"mode",1,{FUPAOPT}},
|
{"mode",1,{FUPAOPT}},
|
||||||
{"preset",1,{FUPAOPT}},
|
{"preset",1,{FUPAOPT}},
|
||||||
{"send",0,{0,0}}
|
{"send",0,{0,0}},
|
||||||
|
{"setpar",3,{FUPATEXT,FUPAINT,FUPAFLOAT}},
|
||||||
|
{"getpar",2,{FUPATEXT,FUPAOPT}}
|
||||||
};
|
};
|
||||||
char *pMode[] = {
|
char *pMode[] = {
|
||||||
"timer",
|
"timer",
|
||||||
@ -759,7 +771,7 @@
|
|||||||
/* parse function args */
|
/* parse function args */
|
||||||
argtolower(argc,argv);
|
argtolower(argc,argv);
|
||||||
argx = &argv[1];
|
argx = &argv[1];
|
||||||
iRet = EvaluateFuPa((pFuncTemplate)&ActionTemplate,20,argc-1,argx,&PaRes);
|
iRet = EvaluateFuPa((pFuncTemplate)&ActionTemplate,22,argc-1,argx,&PaRes);
|
||||||
if(iRet < 0)
|
if(iRet < 0)
|
||||||
{
|
{
|
||||||
sprintf(pBueffel,"%s",PaRes.pError);
|
sprintf(pBueffel,"%s",PaRes.pError);
|
||||||
@ -903,7 +915,7 @@
|
|||||||
break;
|
break;
|
||||||
case 14:
|
case 14:
|
||||||
/* get threshold value */
|
/* get threshold value */
|
||||||
iRet = self->pDriv->Get(self->pDriv,PARTHRESHOLD,
|
iRet = self->pDriv->Get(self->pDriv,"threshold",
|
||||||
PaRes.Arg[0].iVal,&fVal);
|
PaRes.Arg[0].iVal,&fVal);
|
||||||
if(iRet <= 0)
|
if(iRet <= 0)
|
||||||
{
|
{
|
||||||
@ -936,7 +948,7 @@
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/* set threshold value */
|
/* 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);
|
PaRes.Arg[0].iVal,PaRes.Arg[1].fVal);
|
||||||
if(iRet <= 0)
|
if(iRet <= 0)
|
||||||
{
|
{
|
||||||
@ -1048,6 +1060,46 @@
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
break;
|
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:
|
default:
|
||||||
assert(0); /* internal error */
|
assert(0); /* internal error */
|
||||||
}
|
}
|
||||||
|
23
ecb.i
Normal file
23
ecb.i
Normal 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
520
ecbcounter.c
Normal 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
17
ecbcounter.h
Normal 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
|
@ -1,3 +1,6 @@
|
|||||||
|
# Counter counter
|
||||||
|
counter SetPreset 60.000000
|
||||||
|
counter SetMode Timer
|
||||||
# Motor a77
|
# Motor a77
|
||||||
a77 sign 1.000000
|
a77 sign 1.000000
|
||||||
a77 SoftZero 0.000000
|
a77 SoftZero 0.000000
|
||||||
|
@ -292,12 +292,12 @@ static float FAILRATE;
|
|||||||
return COREDO;
|
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;
|
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;
|
*fVal = 25.999;
|
||||||
return 1;
|
return 1;
|
||||||
|
Reference in New Issue
Block a user