- Refactored site specific stuff into a site module - PSI specific stuff is now in the PSI directory. - The old version has been tagged with pre-ansto SKIPPED: psi/A1931.c psi/A1931.h psi/amor2t.c psi/amor2t.h psi/amor2t.i psi/amor2t.tex psi/amor2t.w psi/amorscan.c psi/amorscan.h psi/amorscan.w psi/amorstat.c psi/amorstat.h psi/amorstat.i psi/amorstat.tex psi/amorstat.w psi/bruker.c psi/bruker.h psi/bruker.w psi/buffer.c psi/buffer.h psi/dilludriv.c psi/dilludriv.h psi/dmc.c psi/dmc.h psi/dmc.w psi/docho.c psi/ecb.c psi/ecb.h psi/ecb.i psi/ecb.w psi/ecbdriv.c psi/ecbdriv.h psi/el734dc.c psi/el734driv.c psi/el755driv.c psi/el755driv.h psi/faverage.c psi/faverage.h psi/faverage.tex psi/faverage.w psi/fowrite.c psi/fowrite.h psi/itc4.c psi/itc4.h psi/itc4.w psi/itc4driv.c psi/ltc11.c psi/ltc11.h psi/nextrics.c psi/nextrics.h psi/nxamor.c psi/nxamor.h psi/nxamor.tex psi/nxamor.w psi/pimotor.c psi/pimotor.h psi/pimotor.tex psi/pimotor.w psi/pipiezo.c psi/polterwrite.c psi/polterwrite.h psi/psi.c psi/ruli.c psi/ruli.h psi/sanscook.c psi/sanswave.c psi/sanswave.h psi/sanswave.tex psi/sanswave.w psi/serial.c psi/serial.h psi/serial.w psi/sinqhmdriv.c psi/sinqhmdriv.i psi/sinqhmdriv.w psi/slsmagnet.c psi/sps.c psi/sps.h psi/sps.i psi/sps.tex psi/sps.w psi/swmotor.c psi/swmotor.h psi/swmotor.i psi/tas.c psi/tas.h psi/tas.tex psi/tas.w psi/tasdrive.c psi/tasinit.c psi/tasscan.c psi/tasu.h psi/tasutil.c psi/tdchm.c psi/tdchm.h psi/tecsdriv.c psi/tecsdriv.h psi/velodorn.c psi/velodorn.h psi/velodorn.w psi/velodornier.c psi/hardsup/README psi/hardsup/StrMatch.c psi/hardsup/asynsrv_def.h psi/hardsup/asynsrv_errcodes.h psi/hardsup/asynsrv_mark.c psi/hardsup/asynsrv_utility.c psi/hardsup/c_interfaces.c psi/hardsup/dillutil.c psi/hardsup/dillutil.h psi/hardsup/el734_def.h psi/hardsup/el734_errcodes.h psi/hardsup/el734_utility.c psi/hardsup/el734fix.h psi/hardsup/el734tcl.c psi/hardsup/el737_def.h psi/hardsup/el737_errcodes.h psi/hardsup/el737_utility.c psi/hardsup/el737fix.h psi/hardsup/el737tcl.c psi/hardsup/el755_def.h psi/hardsup/el755_errcodes.h psi/hardsup/el755_errorlog.c psi/hardsup/el755_utility.c psi/hardsup/err.c psi/hardsup/failinet.c psi/hardsup/geterrno.c psi/hardsup/itc4util.c psi/hardsup/itc4util.h psi/hardsup/make_gen psi/hardsup/makefile_alpha psi/hardsup/makefile_linux psi/hardsup/makeprint.c psi/hardsup/rs232c_def.h psi/hardsup/serialsinq.c psi/hardsup/serialsinq.h psi/hardsup/sinq_defs.h psi/hardsup/sinq_prototypes.h psi/hardsup/sinqhm.c psi/hardsup/sinqhm.h psi/hardsup/sinqhm_def.h psi/hardsup/stredit.c psi/hardsup/strjoin.c psi/hardsup/table.c psi/hardsup/table.h psi/hardsup/velsel_def.h psi/hardsup/velsel_utility.c psi/motor/Makefile psi/motor/el734_test psi/motor/el734_test.c psi/motor/makeprint.c psi/sinqhm/FOCUS_gbl.h psi/sinqhm/FOCUS_srv_main.c psi/sinqhm/Makefile psi/sinqhm/SinqHM_bootParamsConfig.c psi/sinqhm/SinqHM_bootUtil.c psi/sinqhm/SinqHM_def.h psi/sinqhm/SinqHM_gbl.h psi/sinqhm/SinqHM_srv_filler.c psi/sinqhm/SinqHM_srv_main.c psi/sinqhm/SinqHM_srv_routines.c psi/sinqhm/SinqHM_srv_server.c psi/sinqhm/bld psi/sinqhm/bld2 psi/sinqhm/bldmen psi/sinqhm/hist_mem_notes.tex psi/sinqhm/hist_mem_spec.tex psi/sinqhm/hist_mem_spec_fig1.ps psi/sinqhm/hist_mem_spec_fig2.ps psi/sinqhm/hist_mem_spec_fig3.ps psi/sinqhm/hist_mem_spec_fig4.ps psi/sinqhm/lwl_client.c psi/sinqhm/lwl_server.c psi/sinqhm/make_sinqhm.com psi/sinqhm/monitor.c psi/sinqhm/psi_logo.ps psi/sinqhm/sinq_logo.ps psi/sinqhm/sinqhm_bootutil_client.c psi/sinqhm/sinqhm_client.c psi/sinqhm/sinqhm_ctrl.c psi/sinqhm/usrConfig.c psi/sinqhm/usrConfig.c_diffs psi/sinqhm/usrConfig2604.c psi/sinqhm/vmio10_def.h psi/sinqhm/vmio_utility.c psi/tecs/coc_client.c psi/tecs/coc_client.h psi/tecs/coc_logfile.c psi/tecs/coc_logfile.h psi/tecs/coc_server.c psi/tecs/coc_server.h psi/tecs/coc_util.c psi/tecs/coc_util.h psi/tecs/fortify1.c psi/tecs/instr_hosts.c psi/tecs/instr_hosts.h psi/tecs/keep_running.c psi/tecs/make_gen psi/tecs/make_opt psi/tecs/make_opt_alpha psi/tecs/make_opt_llc psi/tecs/makefile psi/tecs/makefile_alpha psi/tecs/makefile_linux psi/tecs/myc_buf.c psi/tecs/myc_buf.h psi/tecs/myc_err.c psi/tecs/myc_err.h psi/tecs/myc_fortran.h psi/tecs/myc_mem.h psi/tecs/myc_str.c psi/tecs/myc_str.h psi/tecs/myc_time.c psi/tecs/myc_time.h psi/tecs/myc_tmp.c psi/tecs/myc_tmp.h psi/tecs/rstart.c psi/tecs/six.c psi/tecs/str.f psi/tecs/sys_cmdpar.f psi/tecs/sys_date.f psi/tecs/sys_env.c psi/tecs/sys_get_key.f psi/tecs/sys_getenv.f psi/tecs/sys_lun.f psi/tecs/sys_open.f psi/tecs/sys_open_alpha.f psi/tecs/sys_rdline.c psi/tecs/sys_select.c psi/tecs/sys_select.h psi/tecs/sys_unix.c psi/tecs/sys_wait.f psi/tecs/tecs.bld psi/tecs/tecs.c psi/tecs/tecs.tcl psi/tecs/tecs_c.c psi/tecs/tecs_c.h psi/tecs/tecs_cli.c psi/tecs/tecs_cli.h psi/tecs/tecs_client.f psi/tecs/tecs_data.c psi/tecs/tecs_data.h psi/tecs/tecs_dlog.inc psi/tecs/tecs_for.f psi/tecs/tecs_lsc.c psi/tecs/tecs_lsc.h psi/tecs/tecs_plot.f psi/tecs/tecs_serial.c psi/tecs/tecs_serial.h psi/tecs/term.c psi/tecs/term.h psi/utils/Makefile psi/utils/SerPortServer.c psi/utils/asynsrv_test.c psi/utils/ecb-load.c psi/utils/el734.c psi/utils/el734_test.c psi/utils/el737.c psi/utils/make.ecb psi/utils/check/amorcheck psi/utils/check/dmccheck psi/utils/check/focuscheck psi/utils/check/focusstatus.tcl psi/utils/check/hrptcheck psi/utils/check/sanscheck psi/utils/check/sicssyntax.tex psi/utils/check/sicssyntaxlib.tcl psi/utils/check/test.tcl psi/utils/check/topsicheck psi/utils/check/tricscheck psi/utils/check/tst
587 lines
14 KiB
C
587 lines
14 KiB
C
/*----------------------------------------------------------------------------
|
|
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 "status.h"
|
|
#include "psi/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 */
|
|
int state; /* current counting state */
|
|
}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 SPCSTA 169
|
|
|
|
/*------------------ state codes --------------------------------------*/
|
|
#define IDLE 0
|
|
#define COUNT 2
|
|
#define NOBEAM 3
|
|
/*--------------------------------------------------------------------*/
|
|
#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 check4Beam(struct __COUNTER *pCter, int *beam){
|
|
Z80_reg in, out;
|
|
pECBCounter self = NULL;
|
|
int status;
|
|
|
|
self = (pECBCounter)pCter->pData;
|
|
assert(self);
|
|
|
|
in.c = 1;
|
|
status = ecbExecute(self->ecb,SPCSTA,in,&out);
|
|
if(status != 1){
|
|
pCter->iErrorCode = COMMERROR;
|
|
return HWFault;
|
|
}
|
|
*beam = (int)out.d;
|
|
return 1;
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
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;
|
|
}
|
|
/*========================================================================
|
|
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 ECBGetStatus(struct __COUNTER *self, float *fControl){
|
|
pECBCounter pPriv = (pECBCounter)self->pData;
|
|
int status, result, scaler;
|
|
Z80_reg in, out;
|
|
int count, beam;
|
|
|
|
assert(pPriv);
|
|
|
|
/*
|
|
This can happen after a stop
|
|
*/
|
|
if(pPriv->state == IDLE){
|
|
return HWIdle;
|
|
}
|
|
|
|
/*
|
|
read status bit
|
|
*/
|
|
status = ecbExecute(pPriv->ecb,STFRD,in,&out);
|
|
if(status != 1){
|
|
self->iErrorCode = COMMERROR;
|
|
pPriv->state = IDLE;
|
|
return HWFault;
|
|
}
|
|
/*
|
|
read beam status
|
|
*/
|
|
status = check4Beam(self,&beam);
|
|
if(status != 1){
|
|
self->iErrorCode = COMMERROR;
|
|
return HWFault;
|
|
}
|
|
beam &= 1;
|
|
|
|
/*
|
|
sophisticated logic in order to keep track of the various states
|
|
the thing can be in. Complicated by the fact that the status becomes
|
|
idle (out.d = 0) when the measurement is paused due to the lack of
|
|
beam.
|
|
*/
|
|
if(pPriv->state == COUNT && beam == 1){
|
|
ECBPause(self);
|
|
pPriv->state = NOBEAM;
|
|
SetStatus(eOutOfBeam);
|
|
result = HWNoBeam;
|
|
}
|
|
if(pPriv->state == NOBEAM && beam == 0){
|
|
ECBContinue(self);
|
|
pPriv->state = COUNT;
|
|
SetStatus(eCounting);
|
|
return HWBusy;
|
|
}
|
|
if(pPriv->state == NOBEAM && beam == 1){
|
|
return HWNoBeam;
|
|
}
|
|
if(out.d == 0 && pPriv->state == COUNT){
|
|
result = HWIdle;
|
|
pPriv->state = IDLE;
|
|
} 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 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;
|
|
}
|
|
|
|
pPriv->state = COUNT;
|
|
return OKOK;
|
|
}
|
|
/*=======================================================================*/
|
|
static int ECBHalt(struct __COUNTER *self){
|
|
int status;
|
|
pECBCounter pPriv = NULL;
|
|
|
|
assert(self);
|
|
pPriv = (pECBCounter)self->pData;
|
|
assert(pPriv);
|
|
|
|
pPriv->state = IDLE;
|
|
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->KillPrivate = NULL;
|
|
|
|
self->pData = pPriv;
|
|
return self;
|
|
}
|