293 lines
8.3 KiB
C
293 lines
8.3 KiB
C
/** \file counterdriv.c
|
|
* \brief Sics counter driver for the ANSTO beam monitor.
|
|
*
|
|
* A SICS counter can manage several monitors, this is the driver
|
|
* for the beam monitor developed at ANSTO
|
|
*
|
|
* Copyright: see file Copyright.txt
|
|
*
|
|
* Ferdi Franceschini July 2006
|
|
*
|
|
*/
|
|
#include <stdlib.h>
|
|
#include <assert.h>
|
|
#include <math.h>
|
|
#include <time.h>
|
|
#include "fortify.h"
|
|
#include <string.h>
|
|
#include <sics.h>
|
|
#include <rs232controller.h>
|
|
#include <countdriv.h>
|
|
#include "anstoutil.h"
|
|
|
|
/*@-incondefs@*/
|
|
/*@observer@*//*@dependent@*/ Tcl_Interp *InterpGetTcl(SicsInterp *pSics);
|
|
/*@observer@*//*@dependent@*/ pCounterDriver CreateCounterDriver(char *name, char *type);
|
|
void KillRS232(/*@only@ frees pData */ void *pData);
|
|
/*@+incondefs@*/
|
|
|
|
#if 0
|
|
typedef struct __COUNTDRIV {
|
|
char *name;
|
|
char *type;
|
|
CounterMode eMode;
|
|
float fPreset;
|
|
float fLastCurrent;
|
|
float fTime;
|
|
int iNoOfMonitors;
|
|
long lCounts[MAXCOUNT];
|
|
int iPause;
|
|
int iErrorCode;
|
|
|
|
int (*GetStatus)(CounterDriver *cntrData, float *fControl);
|
|
int (*Start)(CounterDriver *cntrData);
|
|
int (*Pause)(CounterDriver *cntrData);
|
|
int (*Continue)(CounterDriver *cntrData);
|
|
int (*Halt)(CounterDriver *cntrData);
|
|
int (*ReadValues)(CounterDriver *cntrData);
|
|
int (*GetError)(CounterDriver *cntrData, int *iCode, char *error, int iErrLen);
|
|
int (*TryAndFixIt)(CounterDriver *cntrData, int iCode);
|
|
int (*Set)(CounterDriver *cntrData,char *name, int iCter, float fVal);
|
|
int (*Get)(CounterDriver *cntrData,char *name, int iCter, float *fVal);
|
|
int (*Send)(CounterDriver *cntrData, char *pText, char *pReply, int iReplyLen);
|
|
void (*KillPrivate)(CounterDriver *cntrData);
|
|
void *pData; /* counter specific data */
|
|
|
|
/*@observer@*//*@dependent@*/SConnection *pCon;
|
|
prs232 controller;
|
|
|
|
} CountDriv, *BeamMon;
|
|
#endif
|
|
|
|
typedef struct {
|
|
prs232 controller;
|
|
char *host;
|
|
int iPort;
|
|
float dummy_threshold;
|
|
} BeamMon;
|
|
|
|
/** \brief Returns the counter status,
|
|
* implements the GetStatus method in the MotorDriver interface.
|
|
*
|
|
* \param *cntrData provides access to a monitor's data
|
|
* \param *fControl is set to the current value of the counting control variable. This can either be the counting time already passed or the count rate of the control monitor in ePreset mode.
|
|
* \return
|
|
* - HWIdle The counter has finished and is idle.
|
|
* - HWFault hardware fault or the counter returned an absurd value.
|
|
* - HWNoBeam There is no incident beam.
|
|
* - HWPause Counting has been paused.
|
|
* - HWBusy The counter is busy counting.
|
|
*/
|
|
static int MonGetStatus(CounterDriver *cntrData, float *fControl) {
|
|
BeamMon *self = NULL;
|
|
|
|
self = (BeamMon *) cntrData->pData;
|
|
}
|
|
|
|
/** \brief Starts counting in the current mode and with the current preset
|
|
*
|
|
* \param *cntrData provides access to a monitor's data
|
|
*/
|
|
static int MonStart(CounterDriver *cntrData) {
|
|
BeamMon *self = NULL;
|
|
|
|
self = (BeamMon *) cntrData->pData;
|
|
}
|
|
|
|
/** \brief Pauses a counting operation
|
|
*
|
|
* \param *cntrData provides access to a monitor's data
|
|
*/
|
|
static int MonPause(CounterDriver *cntrData) {
|
|
BeamMon *self = NULL;
|
|
|
|
self = (BeamMon *) cntrData->pData;
|
|
}
|
|
|
|
/* \brief Continues a paused counting operation.
|
|
*
|
|
* \param *cntrData provides access to a monitor's data
|
|
*/
|
|
static int MonContinue(CounterDriver *cntrData) {
|
|
BeamMon *self = NULL;
|
|
|
|
self = (BeamMon *) cntrData->pData;
|
|
}
|
|
|
|
/** \brief Cancels a counting operation. This is an emergency stop used when interrupting an operation.
|
|
* \param *cntrData provides access to a monitor's data
|
|
*/
|
|
static int MonHalt(CounterDriver *cntrData) {
|
|
BeamMon *self = NULL;
|
|
|
|
self = (BeamMon *) cntrData->pData;
|
|
}
|
|
|
|
/** \brief Reads the counter and the monitors in the lCounts array.
|
|
*
|
|
* \param *cntrData provides access to a monitor's data
|
|
*/
|
|
static int MonReadValues(CounterDriver *cntrData) {
|
|
BeamMon *self = NULL;
|
|
|
|
self = (BeamMon *) cntrData->pData;
|
|
}
|
|
|
|
/* \brief Called when an error condition is reported by a counter operation.
|
|
*
|
|
* \param *cntrData provides access to a monitor's data
|
|
* \param *iCode error code returned to logical counter.
|
|
* \param *error error message
|
|
* \param iErrLen maximum error message length allowed.
|
|
*/
|
|
static int MonGetError(CounterDriver *cntrData, int *iCode, char *error, int iErrLen) {
|
|
BeamMon *self = NULL;
|
|
|
|
self = (BeamMon *) cntrData->pData;
|
|
}
|
|
|
|
/* \brief Tries to fix problem associated with iCode error reported by MonGetError.
|
|
*
|
|
* \param *cntrData provides access to a monitor's data
|
|
* \param *iCode error code from MonGetError.
|
|
* \return This code tells the logical counter if an error is recoverable.
|
|
* - COREDO try to redo the last count operation.
|
|
* - COTERM count operation failed, give up.
|
|
*/
|
|
static int MonTryAndFixIt(CounterDriver *cntrData, int iCode) {
|
|
BeamMon *self = NULL;
|
|
|
|
self = (BeamMon *) cntrData->pData;
|
|
assert(self != NULL);
|
|
|
|
switch(iCode){
|
|
case NOTCONNECTED:
|
|
initRS232(self->controller);
|
|
return COREDO;
|
|
}
|
|
return COTERM;
|
|
}
|
|
|
|
/*\brief Sets a parameter to a given value.
|
|
*
|
|
* \param *cntrData provides access to a monitor's data
|
|
* \param *name the name of the parameter to set.
|
|
* \param iCter counter to set
|
|
*/
|
|
static int MonSet(CounterDriver *cntrData, char *name, int iCter, float FVal) {
|
|
BeamMon *self = NULL;
|
|
|
|
self = (BeamMon *) cntrData->pData;
|
|
if(strcmp(name,"threshold") == 0){
|
|
//TODO set threshold
|
|
self->dummy_threshold = FVal;
|
|
}
|
|
}
|
|
|
|
static int MonGet(CounterDriver *cntrData, char *name, int iCter, float *fVal) {
|
|
BeamMon *self = NULL;
|
|
|
|
self = (BeamMon *) cntrData->pData;
|
|
if(strcmp(name,"threshold") == 0){
|
|
//TODO get threshold
|
|
*fVal = self->dummy_threshold;
|
|
}
|
|
|
|
*fVal = 123456789.0;
|
|
}
|
|
|
|
static int MonSend(CounterDriver *cntrData, char *pText, char *pReply, int iReplyLen) {
|
|
BeamMon *self = NULL;
|
|
|
|
self = (BeamMon *) cntrData->pData;
|
|
}
|
|
|
|
static void KillMon(pCounterDriver self) {
|
|
}
|
|
|
|
/*@only@*/ prs232 createRS232(char *host, int iPort);
|
|
/** \brief Open a connection to the motor controller
|
|
* \param *pCon (r) connection object.
|
|
* \param *host (r) Beam Monitor host address or name.
|
|
* \param port Beam Monitor port number
|
|
* \return controller structure
|
|
*/
|
|
/*@null@*/ /*@only@*/ static prs232 MonConnect(/*@dependent@*/SConnection *pCon, char *host, int port) {
|
|
prs232 controller=NULL;
|
|
char pError[ERRLEN];
|
|
int usecTimeout = 50000; /* 50msec timeout */
|
|
|
|
controller=createRS232(host,port);
|
|
if (controller==NULL) {
|
|
snprintf(pError, ERRLEN,
|
|
"ERROR: failed to create controller for %s at port %d",
|
|
controller->pHost, controller->iPort);
|
|
SCWrite(pCon,pError,eError);
|
|
return NULL;
|
|
}
|
|
if ( initRS232(controller) != 1) {
|
|
snprintf(pError, ERRLEN,
|
|
"ERROR: failed to connect to %s at port %d",
|
|
controller->pHost, controller->iPort);
|
|
SCWrite(pCon,pError,eError);
|
|
KillRS232(controller);
|
|
return NULL;
|
|
}
|
|
setRS232ReplyTerminator(controller,"\r\n");
|
|
setRS232SendTerminator(controller,"\r\n");
|
|
setRS232Timeout(controller, usecTimeout);
|
|
return controller;
|
|
}
|
|
|
|
/*@observer@*//*@null@*/ pCounterDriver CreateMonCounter(/*@observer@*/SConnection *pCon, /*@observer@*/char *name, char *params) {
|
|
BeamMon *newCtr = NULL;
|
|
pCounterDriver pCntDriv = NULL;
|
|
char *pPtr = NULL;
|
|
char buffer[132];
|
|
int port;
|
|
Tcl_Interp *interp;
|
|
|
|
interp = InterpGetTcl(pServ->pSics);
|
|
|
|
newCtr = (BeamMon *)malloc(sizeof(BeamMon));
|
|
if(NULL == newCtr){
|
|
(void) SCWrite(pCon,"ERROR: no memory to allocate counter driver",
|
|
eError);
|
|
return NULL;
|
|
}
|
|
pCntDriv = CreateCounterDriver(name, "anstomonitor");
|
|
if(!pCntDriv) {
|
|
free(newCtr);
|
|
return NULL;
|
|
}
|
|
|
|
pCntDriv->Start = MonStart;
|
|
pCntDriv->GetStatus = MonGetStatus;
|
|
pCntDriv->ReadValues = MonReadValues;
|
|
pCntDriv->GetError = MonGetError;
|
|
pCntDriv->TryAndFixIt = MonTryAndFixIt;
|
|
pCntDriv->Halt = MonHalt;
|
|
pCntDriv->Pause = MonPause;
|
|
pCntDriv->Continue = MonContinue;
|
|
/*@-mustfreeonly@ pData = NULL after CreateCounterDriver is called */
|
|
pCntDriv->pData = newCtr;
|
|
/*@+mustfreeonly@*/
|
|
|
|
/* Get hostname and port from the list of named parameters */
|
|
if ((pPtr=getParam(pCon, interp, params,"port",1)) == NULL) {
|
|
KillMon(pCntDriv);
|
|
return NULL;
|
|
}
|
|
sscanf(pPtr,"%d",&port);
|
|
if ((pPtr=getParam(pCon, interp, params,"host",1)) == NULL) {
|
|
KillMon(pCntDriv);
|
|
return NULL;
|
|
}
|
|
strncpy(buffer,pPtr, 131);
|
|
newCtr->controller = MonConnect(pCon, buffer, port);
|
|
|
|
newCtr->dummy_threshold = 1.7e6;
|
|
return pCntDriv;
|
|
}
|
|
|