- Added missing files to split directories
This commit is contained in:
586
ecbcounter.c
Normal file
586
ecbcounter.c
Normal file
@ -0,0 +1,586 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
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 "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;
|
||||
}
|
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
|
693
el737driv.c
Normal file
693
el737driv.c
Normal file
@ -0,0 +1,693 @@
|
||||
/*----------------------------------------------------------------------
|
||||
This is driver for a standard PSI EL737 counter box as used at
|
||||
SINQ
|
||||
|
||||
copyright: see file COPYRIGHT
|
||||
|
||||
extracted from countdriv.c. Mark Koennecke, June 2003
|
||||
-----------------------------------------------------------------------*/
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <fortify.h>
|
||||
#include <string.h>
|
||||
#include <sics.h>
|
||||
#include <countdriv.h>
|
||||
#include <splitter.h>
|
||||
#include "hardsup/sinq_prototypes.h"
|
||||
#include "hardsup/el737_def.h"
|
||||
#include "hardsup/el737fix.h"
|
||||
/*----------------------------- EL737 ------------------------------------*/
|
||||
typedef struct {
|
||||
char *host;
|
||||
int iPort;
|
||||
int iChannel;
|
||||
void *pData;
|
||||
int finishCount;
|
||||
} EL737st;
|
||||
/*------------------------------------------------------------------------*/
|
||||
static int EL737GetStatus(struct __COUNTER *self, float *fControl)
|
||||
{
|
||||
int iRet;
|
||||
int iC1, iC2, iC3,iC4,iRS;
|
||||
float fTime;
|
||||
EL737st *pEL737;
|
||||
|
||||
assert(self);
|
||||
pEL737 = (EL737st *)self->pData;
|
||||
assert(pEL737);
|
||||
iRet = EL737_GetStatus(&pEL737->pData,&iC1,&iC2,&iC3,&iC4,&fTime,&iRS);
|
||||
if(self->eMode == eTimer)
|
||||
{
|
||||
*fControl = fTime;
|
||||
}
|
||||
else
|
||||
{
|
||||
*fControl = iC1;
|
||||
}
|
||||
/* store time */
|
||||
self->fTime = fTime;
|
||||
|
||||
if(iRet != 1)
|
||||
{
|
||||
return HWFault;
|
||||
}
|
||||
self->lCounts[0] = iC2;
|
||||
self->lCounts[1] = iC1;
|
||||
self->lCounts[2] = iC3;
|
||||
self->lCounts[3] = iC4;
|
||||
|
||||
/* get extra counters for 8-fold counter boxes */
|
||||
iRet = EL737_GetStatusExtra(&pEL737->pData,&iC1,&iC2,&iC3,&iC4);
|
||||
self->lCounts[4] = iC1;
|
||||
self->lCounts[5] = iC2;
|
||||
self->lCounts[6] = iC3;
|
||||
self->lCounts[7] = iC4;
|
||||
if(iRS == 0)
|
||||
{
|
||||
pEL737->finishCount++;
|
||||
if(pEL737->finishCount >= 2)
|
||||
{
|
||||
return HWIdle;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HWBusy;
|
||||
}
|
||||
}
|
||||
else if((iRS == 1) || (iRS == 2))
|
||||
{
|
||||
pEL737->finishCount = 0;
|
||||
return HWBusy;
|
||||
}
|
||||
else if( (iRS == 5) || (iRS == 6))
|
||||
{
|
||||
pEL737->finishCount = 0;
|
||||
return HWNoBeam;
|
||||
}
|
||||
else
|
||||
{
|
||||
pEL737->finishCount = 0;
|
||||
return HWPause;
|
||||
}
|
||||
}
|
||||
#ifdef NONINTF
|
||||
extern float nintf(float f);
|
||||
#endif
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static int EL737Start(struct __COUNTER *self)
|
||||
{
|
||||
int iRet, iRS;
|
||||
EL737st *pEL737;
|
||||
|
||||
assert(self);
|
||||
pEL737 = (EL737st *)self->pData;
|
||||
assert(pEL737);
|
||||
|
||||
|
||||
self->fTime = 0.;
|
||||
|
||||
if(self->eMode == ePreset)
|
||||
{
|
||||
iRet = EL737_StartCnt(&pEL737->pData,(int)nintf(self->fPreset),&iRS);
|
||||
if(iRet == 1)
|
||||
{
|
||||
pEL737->finishCount = 0;
|
||||
return OKOK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HWFault;
|
||||
}
|
||||
}
|
||||
else if(self->eMode == eTimer)
|
||||
{
|
||||
iRet = EL737_StartTime(&pEL737->pData,self->fPreset,&iRS);
|
||||
if(iRet == 1)
|
||||
{
|
||||
pEL737->finishCount = 0;
|
||||
return OKOK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HWFault;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static int EL737Pause(struct __COUNTER *self)
|
||||
{
|
||||
int iRet, iRS;
|
||||
EL737st *pEL737;
|
||||
|
||||
assert(self);
|
||||
pEL737 = (EL737st *)self->pData;
|
||||
assert(pEL737);
|
||||
|
||||
|
||||
iRet = EL737_Pause(&pEL737->pData,&iRS);
|
||||
if(iRet == 1)
|
||||
{
|
||||
return OKOK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HWFault;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static int EL737Continue(struct __COUNTER *self)
|
||||
{
|
||||
int iRet, iRS;
|
||||
EL737st *pEL737;
|
||||
|
||||
assert(self);
|
||||
pEL737 = (EL737st *)self->pData;
|
||||
assert(pEL737);
|
||||
|
||||
|
||||
iRet = EL737_Continue(&pEL737->pData,&iRS);
|
||||
if(iRet == 1)
|
||||
{
|
||||
return OKOK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HWFault;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
static int EL737Halt(struct __COUNTER *self)
|
||||
{
|
||||
int iRet, iC1, iC2, iC3, iC4,iRS;
|
||||
float fPreset;
|
||||
EL737st *pEL737;
|
||||
|
||||
assert(self);
|
||||
pEL737 = (EL737st *)self->pData;
|
||||
assert(pEL737);
|
||||
|
||||
|
||||
|
||||
iRet = EL737_Stop(&pEL737->pData,&iC1, &iC2,&iC3,&iC4,&fPreset,&iRS);
|
||||
if(iRet == 1)
|
||||
{
|
||||
self->lCounts[0] = iC2;
|
||||
self->lCounts[1] = iC1;
|
||||
self->lCounts[2] = iC3;
|
||||
self->lCounts[3] = iC4;
|
||||
return OKOK;
|
||||
}
|
||||
return HWFault;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
static int EL737ReadValues(struct __COUNTER *self)
|
||||
{
|
||||
int iRet;
|
||||
int iC1, iC2, iC3,iC4,iRS;
|
||||
float fTime;
|
||||
EL737st *pEL737;
|
||||
|
||||
assert(self);
|
||||
pEL737 = (EL737st *)self->pData;
|
||||
assert(pEL737);
|
||||
|
||||
|
||||
iRet = EL737_GetStatus(&pEL737->pData,&iC1,&iC2,&iC3,&iC4,&fTime,&iRS);
|
||||
if(iRet != 1)
|
||||
{
|
||||
return HWFault;
|
||||
}
|
||||
self->fTime = fTime;
|
||||
|
||||
self->lCounts[0] = iC2;
|
||||
self->lCounts[1] = iC1;
|
||||
self->lCounts[2] = iC3;
|
||||
self->lCounts[3] = iC4;
|
||||
/* get extra counters for 8-fold counter boxes */
|
||||
iRet = EL737_GetStatusExtra(&pEL737->pData,&iC1,&iC2,&iC3,&iC4);
|
||||
self->lCounts[4] = iC1;
|
||||
self->lCounts[5] = iC2;
|
||||
self->lCounts[6] = iC3;
|
||||
self->lCounts[7] = iC4;
|
||||
|
||||
return OKOK;
|
||||
}
|
||||
/*---------------------------------------------------------------------------
|
||||
|
||||
EL737Error2Text converts between an EL734 error code to text
|
||||
-----------------------------------------------------------------------------*/
|
||||
static void EL737Error2Text(char *pBuffer, int iErr)
|
||||
{
|
||||
switch(iErr)
|
||||
{
|
||||
case EL737__BAD_ADR:
|
||||
strcpy(pBuffer,"EL737__BAD_ADR");
|
||||
break;
|
||||
case EL737__BAD_OVFL:
|
||||
strcpy(pBuffer,"EL737__BAD_OVFL");
|
||||
break;
|
||||
case EL737__BAD_BSY:
|
||||
strcpy(pBuffer,"EL737__BAD_BSY");
|
||||
break;
|
||||
case EL737__BAD_SNTX:
|
||||
strcpy(pBuffer,"EL737__BAD_SNTX");
|
||||
break;
|
||||
case EL737__BAD_CONNECT:
|
||||
strcpy(pBuffer,"EL737__BAD_CONNECT");
|
||||
break;
|
||||
case EL737__BAD_FLUSH:
|
||||
strcpy(pBuffer,"EL737__BAD_FLUSH");
|
||||
break;
|
||||
case EL737__BAD_DEV:
|
||||
strcpy(pBuffer,"EL734__BAD_DEV");
|
||||
break;
|
||||
case EL737__BAD_ID:
|
||||
strcpy(pBuffer,"EL737__BAD_ID");
|
||||
break;
|
||||
case EL737__BAD_ILLG:
|
||||
strcpy(pBuffer,"EL737__BAD_ILLG");
|
||||
break;
|
||||
case EL737__BAD_LOC:
|
||||
strcpy(pBuffer,"EL737__BAD_LOC");
|
||||
break;
|
||||
case EL737__BAD_MALLOC:
|
||||
strcpy(pBuffer,"EL737__BAD_MALLOC");
|
||||
break;
|
||||
case EL737__BAD_NOT_BCD:
|
||||
strcpy(pBuffer,"EL737__BAD_NOT_BCD");
|
||||
break;
|
||||
case EL737__BAD_OFL:
|
||||
strcpy(pBuffer,"EL737__BAD_OFL");
|
||||
break;
|
||||
case EL737__BAD_PAR:
|
||||
strcpy(pBuffer,"EL737__BAD_PAR");
|
||||
break;
|
||||
|
||||
case EL737__BAD_RECV:
|
||||
strcpy(pBuffer,"EL737__BAD_RECV");
|
||||
break;
|
||||
case EL737__BAD_RECV_NET:
|
||||
strcpy(pBuffer,"EL737__BAD_RECV_NET");
|
||||
break;
|
||||
case EL737__BAD_RECV_PIPE:
|
||||
strcpy(pBuffer,"EL737__BAD_RECV_PIPE");
|
||||
break;
|
||||
case EL737__BAD_RECV_UNKN:
|
||||
strcpy(pBuffer,"EL737__BAD_RECV_UNKN");
|
||||
break;
|
||||
case EL737__BAD_RECVLEN:
|
||||
strcpy(pBuffer,"EL737__BAD_RECVLEN");
|
||||
break;
|
||||
case EL737__BAD_RECV1:
|
||||
strcpy(pBuffer,"EL737__BAD_RECV1");
|
||||
break;
|
||||
case EL737__BAD_RECV1_NET:
|
||||
strcpy(pBuffer,"EL737__BAD_RECV1_NET");
|
||||
break;
|
||||
case EL737__BAD_RECV1_PIPE:
|
||||
strcpy(pBuffer,"EL737__BAD_RECV1_PIPE");
|
||||
break;
|
||||
case EL737__BAD_RNG:
|
||||
strcpy(pBuffer,"EL737__BAD_RNG");
|
||||
break;
|
||||
case EL737__BAD_SEND:
|
||||
strcpy(pBuffer,"EL737__BAD_SEND");
|
||||
break;
|
||||
case EL737__BAD_SEND_PIPE:
|
||||
strcpy(pBuffer,"EL737__BAD_SEND_PIPE");
|
||||
break;
|
||||
case EL737__BAD_SEND_NET:
|
||||
strcpy(pBuffer,"EL737__BAD_SEND_NET");
|
||||
break;
|
||||
case EL737__BAD_SEND_UNKN:
|
||||
strcpy(pBuffer,"EL737__BAD_SEND_UNKN");
|
||||
break;
|
||||
case EL737__BAD_SENDLEN:
|
||||
strcpy(pBuffer,"EL737__BAD_SENDLEN");
|
||||
break;
|
||||
case EL737__BAD_SOCKET:
|
||||
strcpy(pBuffer,"EL737__BAD_SOCKET");
|
||||
break;
|
||||
case EL737__BAD_TMO:
|
||||
strcpy(pBuffer,"EL737__BAD_TMO");
|
||||
break;
|
||||
case EL737__FORCED_CLOSED:
|
||||
strcpy(pBuffer,"EL737__FORCED_CLOSED");
|
||||
break;
|
||||
case EL737__BAD_ASYNSRV:
|
||||
strcpy(pBuffer,"EL737__BAD_ASYNSRV");
|
||||
break;
|
||||
default:
|
||||
sprintf(pBuffer,"Unknown EL737 error %d", iErr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
static int EL737GetError(struct __COUNTER *self, int *iCode,
|
||||
char *error, int iErrLen)
|
||||
{
|
||||
char *pErr = NULL;
|
||||
int iC1, iC2, iC3;
|
||||
char pBueffel[256];
|
||||
|
||||
if(self->iErrorCode == UNKNOWNPAR)
|
||||
{
|
||||
strncpy(error,"unknown internal parameter code",iErrLen);
|
||||
*iCode = self->iErrorCode;
|
||||
self->iErrorCode = 0;
|
||||
return 1;
|
||||
}
|
||||
else if(self->iErrorCode == BADCOUNTER)
|
||||
{
|
||||
strncpy(error,"monitor cannot be selected",iErrLen);
|
||||
*iCode = self->iErrorCode;
|
||||
self->iErrorCode = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
EL737_ErrInfo(&pErr,&iC1,&iC2, &iC3);
|
||||
EL737Error2Text(pBueffel,iC1);
|
||||
|
||||
strncpy(error,pBueffel,iErrLen);
|
||||
*iCode = iC1;
|
||||
return 1;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
static int EL737TryAndFixIt(struct __COUNTER *self, int iCode)
|
||||
{
|
||||
EL737st *pEL737;
|
||||
int iRet;
|
||||
char pCommand[50], pReply[50];
|
||||
|
||||
assert(self);
|
||||
pEL737 = (EL737st *)self->pData;
|
||||
assert(pEL737);
|
||||
|
||||
switch(iCode)
|
||||
{
|
||||
case EL737__BAD_ILLG:
|
||||
case EL737__BAD_ADR:
|
||||
case EL737__BAD_PAR:
|
||||
case EL737__BAD_TMO:
|
||||
case EL737__BAD_REPLY:
|
||||
case EL737__BAD_SNTX:
|
||||
case EL737__BAD_OVFL:
|
||||
return COREDO;
|
||||
break;
|
||||
case EL737__BAD_BSY:
|
||||
strcpy(pCommand,"S \r");
|
||||
iRet = EL737_SendCmnd(&pEL737->pData,pCommand,pReply,49);
|
||||
if(iRet < 0)
|
||||
{
|
||||
return COTERM;
|
||||
}
|
||||
else
|
||||
{
|
||||
return COREDO;
|
||||
}
|
||||
break;
|
||||
case EL737__BAD_LOC:
|
||||
strcpy(pCommand,"rmt 1\r");
|
||||
iRet = EL737_SendCmnd(&pEL737->pData,pCommand,pReply,49);
|
||||
if(iRet < 0)
|
||||
{
|
||||
return COTERM;
|
||||
}
|
||||
strcpy(pCommand,"echo 2\r");
|
||||
iRet = EL737_SendCmnd(&pEL737->pData,pCommand,pReply,49);
|
||||
if(iRet < 0)
|
||||
{
|
||||
return COTERM;
|
||||
}
|
||||
strcpy(pCommand,"ra\r");
|
||||
iRet = EL737_SendCmnd(&pEL737->pData,pCommand,pReply,49);
|
||||
if(iRet < 0)
|
||||
{
|
||||
return COTERM;
|
||||
}
|
||||
return COREDO;
|
||||
break;
|
||||
case EL737__BAD_DEV:
|
||||
case EL737__BAD_ID:
|
||||
case EL737__BAD_NOT_BCD:
|
||||
case UNKNOWNPAR:
|
||||
case BADCOUNTER:
|
||||
return COTERM;
|
||||
break;
|
||||
case EL737__FORCED_CLOSED:
|
||||
iRet = EL737_Open(&pEL737->pData,pEL737->host, pEL737->iPort,
|
||||
pEL737->iChannel);
|
||||
if(iRet == 1)
|
||||
{
|
||||
return COREDO;
|
||||
}
|
||||
else
|
||||
{
|
||||
return COTERM;
|
||||
}
|
||||
break;
|
||||
case EL737__BAD_OFL:
|
||||
EL737_Close(&pEL737->pData,0);
|
||||
iRet = EL737_Open(&pEL737->pData,pEL737->host, pEL737->iPort,
|
||||
pEL737->iChannel);
|
||||
if(iRet == 1)
|
||||
{
|
||||
return COREDO;
|
||||
}
|
||||
else
|
||||
{
|
||||
return COTERM;
|
||||
}
|
||||
break;
|
||||
/* case EL737__BAD_ASYNSRV:
|
||||
EL737_Close(&pEL737->pData,1);
|
||||
return COREDO;
|
||||
*/ default:
|
||||
/* try to reopen connection */
|
||||
|
||||
EL737_Close(&pEL737->pData,1);
|
||||
iRet = EL737_Open(&pEL737->pData,pEL737->host, pEL737->iPort,
|
||||
pEL737->iChannel);
|
||||
if(iRet == 1)
|
||||
{
|
||||
return COREDO;
|
||||
}
|
||||
else
|
||||
{
|
||||
return COTERM;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return COTERM;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static int EL737Set(struct __COUNTER *self, char *name, int iCter,
|
||||
float fVal)
|
||||
{
|
||||
int iRet;
|
||||
EL737st *pEL737;
|
||||
char pCommand[80],pReply[80];
|
||||
|
||||
assert(self);
|
||||
pEL737 = (EL737st *)self->pData;
|
||||
assert(pEL737);
|
||||
|
||||
if(strcmp(name,"threshold") == 0)
|
||||
{
|
||||
sprintf(pCommand,"DL %1.1d %f\r",iCter,fVal);
|
||||
iRet = EL737_SendCmnd(&pEL737->pData,pCommand,pReply,79);
|
||||
if(iRet == 1)
|
||||
{
|
||||
if(pCommand[0] == '?')
|
||||
{
|
||||
self->iErrorCode = BADCOUNTER;
|
||||
return HWFault;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return HWFault;
|
||||
}
|
||||
sprintf(pCommand,"DR %1.1d \r",iCter);
|
||||
iRet = EL737_SendCmnd(&pEL737->pData,pCommand,pReply,79);
|
||||
if(iRet == 1)
|
||||
{
|
||||
if(pCommand[0] == '?')
|
||||
{
|
||||
self->iErrorCode = BADCOUNTER;
|
||||
return HWFault;
|
||||
}
|
||||
return OKOK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HWFault;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
self->iErrorCode = UNKNOWNPAR;
|
||||
return HWFault;
|
||||
}
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static int EL737Get(struct __COUNTER *self, char *name, int iCter,
|
||||
float *fVal)
|
||||
{
|
||||
int iRet;
|
||||
EL737st *pEL737;
|
||||
char pCommand[80],pReply[80];
|
||||
|
||||
assert(self);
|
||||
pEL737 = (EL737st *)self->pData;
|
||||
assert(pEL737);
|
||||
|
||||
if(strcmp(name,"threshold") == 0)
|
||||
{
|
||||
sprintf(pCommand,"DL %1.1d\r",iCter);
|
||||
iRet = EL737_SendCmnd(&pEL737->pData,pCommand,pReply,79);
|
||||
if(iRet == 1)
|
||||
{
|
||||
if(pReply[0] == '?')
|
||||
{
|
||||
self->iErrorCode = BADCOUNTER;
|
||||
return HWFault;
|
||||
}
|
||||
sscanf(pReply,"%f",fVal);
|
||||
return OKOK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HWFault;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
self->iErrorCode = UNKNOWNPAR;
|
||||
return HWFault;
|
||||
}
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static int EL737Send(struct __COUNTER *self, char *pText, char *pReply,
|
||||
int iReplyLen)
|
||||
{
|
||||
EL737st *pEL737;
|
||||
char pBuffer[256];
|
||||
|
||||
assert(self);
|
||||
pEL737 = (EL737st *)self->pData;
|
||||
assert(pEL737);
|
||||
|
||||
/* ensure a \r at the end of the text */
|
||||
if(strlen(pText) > 254)
|
||||
{
|
||||
strncpy(pReply,"Command to long",iReplyLen);
|
||||
return 1;
|
||||
}
|
||||
strcpy(pBuffer,pText);
|
||||
if(strchr(pBuffer,(int)'\r') == NULL)
|
||||
{
|
||||
strcat(pBuffer,"\r");
|
||||
}
|
||||
|
||||
return EL737_SendCmnd(&pEL737->pData,pBuffer,pReply,iReplyLen);
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
pCounterDriver CreateEL737Counter(SConnection *pCon, char *name,
|
||||
int argc, char *argv[]){
|
||||
char *pHost;
|
||||
int iPort, iChannel;
|
||||
|
||||
if(argc < 3){
|
||||
SCWrite(pCon,
|
||||
"ERROR: insuficient number of arguments to create EL737 counter",
|
||||
eError);
|
||||
return NULL;
|
||||
}
|
||||
if(!isNumeric(argv[1]) || !isNumeric(argv[2])){
|
||||
SCWrite(pCon,"ERROR: expected numeric arguments for port and channel",
|
||||
eError);
|
||||
return NULL;
|
||||
}
|
||||
iPort = atoi(argv[1]);
|
||||
iChannel = atoi(argv[2]);
|
||||
return NewEL737Counter(name,argv[0],iPort,iChannel);
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
pCounterDriver NewEL737Counter(char *name, char *host, int iPort, int iChannel)
|
||||
{
|
||||
pCounterDriver pRes = NULL;
|
||||
EL737st *pData = NULL;
|
||||
int iRet;
|
||||
int iC1, iC2, iC3;
|
||||
char *pErr;
|
||||
char pBueffel[132];
|
||||
|
||||
pRes = CreateCounterDriver(name, "EL737");
|
||||
if(!pRes)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* open connection to counter */
|
||||
pData = (EL737st *)malloc(sizeof(EL737st));
|
||||
if(!pData)
|
||||
{
|
||||
DeleteCounterDriver(pRes);
|
||||
return NULL;
|
||||
}
|
||||
pData->host = strdup(host);
|
||||
pData->iPort = iPort;
|
||||
pData->iChannel = iChannel;
|
||||
pData->pData = NULL;
|
||||
iRet = EL737_Open(&(pData->pData), host,iPort,iChannel);
|
||||
if(iRet != 1)
|
||||
{
|
||||
EL737_ErrInfo(&pErr,&iC1,&iC2, &iC3);
|
||||
DeleteCounterDriver(pRes);
|
||||
if(pData->host)
|
||||
{
|
||||
free(pData->host);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
pRes->pData = (void *)pData;
|
||||
|
||||
/* assign functions */
|
||||
pRes->GetStatus = EL737GetStatus;
|
||||
pRes->Start = EL737Start;
|
||||
pRes->Halt = EL737Halt;
|
||||
pRes->ReadValues = EL737ReadValues;
|
||||
pRes->GetError = EL737GetError;
|
||||
pRes->TryAndFixIt = EL737TryAndFixIt;
|
||||
pRes->Pause = EL737Pause;
|
||||
pRes->Continue = EL737Continue;
|
||||
pRes->Set = EL737Set;
|
||||
pRes->Get = EL737Get;
|
||||
pRes->Send = EL737Send;
|
||||
pRes->KillPrivate = KillEL737Counter;
|
||||
pRes->iNoOfMonitors = 7;
|
||||
pRes->fTime = 0.;
|
||||
|
||||
return pRes;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
void KillEL737Counter(pCounterDriver self)
|
||||
{
|
||||
EL737st *pEL737 = NULL;
|
||||
|
||||
assert(self);
|
||||
pEL737 = (EL737st *)self->pData;
|
||||
assert(pEL737);
|
||||
|
||||
EL737_Close(&pEL737->pData,0);
|
||||
if(pEL737->host)
|
||||
{
|
||||
free(pEL737->host);
|
||||
}
|
||||
}
|
395
eurodriv.c
Normal file
395
eurodriv.c
Normal file
@ -0,0 +1,395 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
E U R O D R I V
|
||||
|
||||
This file contains the implementation for the Eurotherm temperature
|
||||
controller as used at SANS. The Eurotherm is a grossly strange device
|
||||
which has a very weird command protocoll. The implementation here uses
|
||||
the EI-Bisynch Protocoll option. This has to be configured in the
|
||||
Eurotherm on the manual interface!! Also watch out for the unusual RS232-
|
||||
setting: 7 bits, even parity, 1 stop bit.
|
||||
|
||||
Mark Koennecke, May 1999
|
||||
|
||||
Copyright: see copyright.h
|
||||
----------------------------------------------------------------------------*/
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <math.h>
|
||||
#include <assert.h>
|
||||
#include <fortify.h>
|
||||
#include <conman.h>
|
||||
#include <servlog.h>
|
||||
#include <fortify.h>
|
||||
|
||||
typedef struct __EVDriver *pEVDriver;
|
||||
|
||||
#include <evdriver.i>
|
||||
#include "hardsup/el734_def.h"
|
||||
#include "hardsup/el734fix.h"
|
||||
#include "hardsup/serialsinq.h"
|
||||
#include "eurodriv.h"
|
||||
|
||||
#define INVALIDANSWER -1005
|
||||
#define INVALIDNUMBER -1006
|
||||
#define ERRNAK -1007
|
||||
#define NOSEND -1008
|
||||
/*-----------------------------------------------------------------------*/
|
||||
typedef struct {
|
||||
void *pData;
|
||||
char *pHost;
|
||||
int iPort;
|
||||
int iChannel;
|
||||
int iLastError;
|
||||
} EuroDriv, *pEuroDriv;
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
int EuroGetParameter(void **pData, char *pPar,int iLen, float *fVal)
|
||||
{
|
||||
char pCommand[20];
|
||||
char pReply[20];
|
||||
char *pStart = NULL, *pEnd = NULL;
|
||||
int iRet,i;
|
||||
|
||||
/* configure the serial port */
|
||||
SerialATerm(pData,"1\x3"); /* ETX */
|
||||
pCommand[0] = '\x4'; /* EOT */
|
||||
pCommand[1] = '0'; /* GID*/
|
||||
pCommand[2] = '0'; /* GID*/
|
||||
pCommand[3] = '1'; /* UID*/
|
||||
pCommand[4] = '1'; /* UID*/
|
||||
pCommand[5] = '1'; /* CHAN */
|
||||
for(i = 0; i < iLen; i++)
|
||||
{
|
||||
pCommand[6+i] = pPar[i];
|
||||
}
|
||||
pCommand[6+iLen] = '\x5'; /* ENQ*/
|
||||
pCommand[7+iLen] = '\0';
|
||||
|
||||
/* send */
|
||||
iRet = SerialWriteRead(pData,pCommand,pReply,19);
|
||||
if(iRet != 1)
|
||||
{
|
||||
return iRet;
|
||||
}
|
||||
|
||||
/* decode reply */
|
||||
pStart = strstr(pReply,pPar);
|
||||
if(!pStart)
|
||||
{
|
||||
if(strstr(pReply,"?TMO"))
|
||||
{
|
||||
return EL734__BAD_TMO;
|
||||
}
|
||||
else
|
||||
{
|
||||
return INVALIDANSWER;
|
||||
}
|
||||
}
|
||||
iRet = sscanf(pStart+strlen(pPar),"%f",fVal);
|
||||
if(iRet != 1)
|
||||
{
|
||||
return INVALIDNUMBER;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
int EuroSetParameter(void **pData, char *pPar,int iLen,
|
||||
char *pFormat, float fVal)
|
||||
{
|
||||
char pCommand[30];
|
||||
char pNum[10];
|
||||
char *pPtr, *pPtr2;
|
||||
char pReply[20];
|
||||
char bcc;
|
||||
int iRet,i;
|
||||
|
||||
|
||||
/* configure the serial port */
|
||||
SerialATerm(pData,"1\x06\x15"); /* ACK,NAK */
|
||||
pCommand[0] = '\x04'; /* EOT */
|
||||
pCommand[1] = '0'; /* GID*/
|
||||
pCommand[2] = '0'; /* GID*/
|
||||
pCommand[3] = '1'; /* UID*/
|
||||
pCommand[4] = '1'; /* UID*/
|
||||
pCommand[5] = '\x02';
|
||||
pCommand[6] = '1'; /* CHAN */
|
||||
for(i = 0; i < iLen; i++)
|
||||
{
|
||||
pCommand[7+i] = pPar[i];
|
||||
}
|
||||
pPtr = pCommand + 7 + iLen;
|
||||
sprintf(pNum,pFormat,fVal);
|
||||
strcpy(pPtr,pNum);
|
||||
pPtr += strlen(pNum);
|
||||
*pPtr = '\x03';
|
||||
pPtr++;
|
||||
|
||||
/* build the checksum */
|
||||
bcc = pCommand[6];
|
||||
pPtr2 = &pCommand[7];
|
||||
while(pPtr2 != pPtr)
|
||||
{
|
||||
bcc = bcc ^ *pPtr2;
|
||||
pPtr2++;
|
||||
}
|
||||
*pPtr = bcc;
|
||||
pPtr++;
|
||||
*pPtr = '\0';
|
||||
|
||||
/* send */
|
||||
iRet = SerialSend(pData,pCommand);
|
||||
if(iRet != 1)
|
||||
{
|
||||
return iRet;
|
||||
}
|
||||
iRet = SerialReceiveWithTerm(pData,pReply,19,&bcc);
|
||||
/*
|
||||
printf("%s\n",pReply);
|
||||
*/
|
||||
if(iRet != 1)
|
||||
{
|
||||
return iRet;
|
||||
}
|
||||
if(bcc == '\x15')
|
||||
{
|
||||
return ERRNAK;
|
||||
}
|
||||
if(strstr(pReply,"?TMO"))
|
||||
{
|
||||
return EL734__BAD_TMO;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int GetEuroPos(pEVDriver self, float *fPos)
|
||||
{
|
||||
pEuroDriv pMe = NULL;
|
||||
int iRet;
|
||||
|
||||
assert(self);
|
||||
pMe = (pEuroDriv)self->pPrivate;
|
||||
assert(pMe);
|
||||
|
||||
iRet = EuroGetParameter(&(pMe->pData),"PV",2,fPos);
|
||||
if(iRet != 1)
|
||||
{
|
||||
pMe->iLastError = iRet;
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static int EuroRun(pEVDriver self, float fVal)
|
||||
{
|
||||
pEuroDriv pMe = NULL;
|
||||
int iRet;
|
||||
|
||||
assert(self);
|
||||
pMe = (pEuroDriv )self->pPrivate;
|
||||
assert(pMe);
|
||||
|
||||
iRet = EuroSetParameter(&(pMe->pData),"SL",2,"%4.1f",fVal);
|
||||
if(iRet != 1)
|
||||
{
|
||||
pMe->iLastError = iRet;
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
static int EuroError(pEVDriver self, int *iCode, char *error, int iErrLen)
|
||||
{
|
||||
pEuroDriv pMe = NULL;
|
||||
|
||||
assert(self);
|
||||
pMe = (pEuroDriv)self->pPrivate;
|
||||
assert(pMe);
|
||||
|
||||
*iCode = pMe->iLastError;
|
||||
switch(pMe->iLastError)
|
||||
{
|
||||
case INVALIDANSWER:
|
||||
strncpy(error,"Unexpected reply from Eurotherm",iErrLen);
|
||||
break;
|
||||
case INVALIDNUMBER:
|
||||
strncpy(error,"No number in Eurotherm answer",iErrLen);
|
||||
break;
|
||||
case ERRNAK:
|
||||
strncpy(error,"Eurothem did NOT acknowledge command",iErrLen);
|
||||
break;
|
||||
case NOSEND:
|
||||
strncpy(error,
|
||||
"Eurotherm has a bizarre protocoll, sending things is very STUPID",iErrLen);
|
||||
break;
|
||||
default:
|
||||
SerialError(pMe->iLastError,error,iErrLen);
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
static int EuroSend(pEVDriver self, char *pCommand, char *pReply, int iLen)
|
||||
{
|
||||
pEuroDriv pMe = NULL;
|
||||
|
||||
assert(self);
|
||||
pMe = (pEuroDriv)self->pPrivate;
|
||||
assert(pMe);
|
||||
|
||||
pMe->iLastError = NOSEND;
|
||||
strncpy(pReply,"ERROR: Eurotherm does not support send functionality",
|
||||
iLen);
|
||||
return 0;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
static int EuroInit(pEVDriver self)
|
||||
{
|
||||
pEuroDriv pMe = NULL;
|
||||
int iRet;
|
||||
|
||||
assert(self);
|
||||
pMe = (pEuroDriv )self->pPrivate;
|
||||
assert(pMe);
|
||||
|
||||
pMe->pData = NULL;
|
||||
iRet = SerialOpen(&pMe->pData, pMe->pHost, pMe->iPort, pMe->iChannel);
|
||||
if(iRet != 1)
|
||||
{
|
||||
pMe->iLastError = iRet;
|
||||
return 0;
|
||||
}
|
||||
SerialSendTerm(&pMe->pData,"");
|
||||
return 1;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
static int EuroClose(pEVDriver self)
|
||||
{
|
||||
pEuroDriv pMe = NULL;
|
||||
int iRet;
|
||||
|
||||
assert(self);
|
||||
pMe = (pEuroDriv )self->pPrivate;
|
||||
assert(pMe);
|
||||
|
||||
SerialClose(&pMe->pData);
|
||||
return 1;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int EuroFix(pEVDriver self, int iError)
|
||||
{
|
||||
pEuroDriv pMe = NULL;
|
||||
int iRet;
|
||||
|
||||
assert(self);
|
||||
pMe = (pEuroDriv )self->pPrivate;
|
||||
assert(pMe);
|
||||
|
||||
switch(iError)
|
||||
{
|
||||
/* network errors */
|
||||
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:
|
||||
EuroClose(self);
|
||||
iRet = EuroInit(self);
|
||||
if(iRet)
|
||||
{
|
||||
return DEVREDO;
|
||||
}
|
||||
else
|
||||
{
|
||||
return DEVFAULT;
|
||||
}
|
||||
break;
|
||||
/* handable protocoll errors */
|
||||
case EL734__BAD_TMO:
|
||||
return DEVREDO;
|
||||
break;
|
||||
case ERRNAK:
|
||||
case NOSEND:
|
||||
case INVALIDANSWER:
|
||||
case INVALIDNUMBER:
|
||||
return DEVFAULT;
|
||||
default:
|
||||
return DEVFAULT;
|
||||
break;
|
||||
}
|
||||
return DEVFAULT;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
static int EuroHalt(pEVDriver *self)
|
||||
{
|
||||
assert(self);
|
||||
|
||||
return 1;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
void KillEuro(void *pData)
|
||||
{
|
||||
pEuroDriv pMe = NULL;
|
||||
|
||||
pMe = (pEuroDriv)pData;
|
||||
assert(pMe);
|
||||
|
||||
if(pMe->pHost)
|
||||
{
|
||||
free(pMe->pHost);
|
||||
}
|
||||
free(pMe);
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
pEVDriver CreateEURODriv(int argc, char *argv[])
|
||||
{
|
||||
pEVDriver pNew = NULL;
|
||||
pEuroDriv pSim = NULL;
|
||||
|
||||
/* check for arguments */
|
||||
if(argc < 3)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pNew = CreateEVDriver(argc,argv);
|
||||
pSim = (pEuroDriv)malloc(sizeof(EuroDriv));
|
||||
memset(pSim,0,sizeof(EuroDriv));
|
||||
if(!pNew || !pSim)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
pNew->pPrivate = pSim;
|
||||
pNew->KillPrivate = KillEuro;
|
||||
|
||||
/* initalise pDILLUDriver */
|
||||
pSim->iLastError = 0;
|
||||
pSim->pHost = strdup(argv[0]);
|
||||
pSim->iPort = atoi(argv[1]);
|
||||
pSim->iChannel = atoi(argv[2]);
|
||||
|
||||
/* initialise function pointers */
|
||||
pNew->SetValue = EuroRun;
|
||||
pNew->GetValue = GetEuroPos;
|
||||
pNew->Send = EuroSend;
|
||||
pNew->GetError = EuroError;
|
||||
pNew->TryFixIt = EuroFix;
|
||||
pNew->Init = EuroInit;
|
||||
pNew->Close = EuroClose;
|
||||
|
||||
return pNew;
|
||||
}
|
||||
|
||||
|
||||
|
23
eurodriv.h
Normal file
23
eurodriv.h
Normal file
@ -0,0 +1,23 @@
|
||||
/*------------------------------------------------------------------------
|
||||
E U R O D R I V
|
||||
|
||||
A environment control driver for the SANS Eurotherm temperature
|
||||
controller.
|
||||
|
||||
Mark Koennecke, May 1999
|
||||
|
||||
copyright: see copyright.h
|
||||
---------------------------------------------------------------------------*/
|
||||
#ifndef EURODRIV
|
||||
#define EURODRIV
|
||||
pEVDriver CreateEURODriv(int argc, char *argv[]);
|
||||
|
||||
/*
|
||||
these are hooks to implement further functionality which,
|
||||
I'am sure, Joachim Kohlbrecher will request.
|
||||
*/
|
||||
int EuroGetParameter(void **pData, char *pPar, int iLen, float *fVal);
|
||||
int EuroSetParameter(void **pData, char *pPar, int iLen,
|
||||
char *pFormat, float fVal);
|
||||
|
||||
#endif
|
242
frame.c
Normal file
242
frame.c
Normal file
@ -0,0 +1,242 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
A module implementing functionality for reading single time frames
|
||||
from PSD time-of-flight datasets. This can be done either from
|
||||
SINQHM histogram memories or from old data files visible from the
|
||||
SICS server. The result is sent to the demanding client in UUencoded
|
||||
format.
|
||||
|
||||
copyright: see file COPYRIGHT
|
||||
|
||||
Mark Koennecke, February-March 2003
|
||||
---------------------------------------------------------------------------*/
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include "fortify.h"
|
||||
#include "sics.h"
|
||||
#include "stringdict.h"
|
||||
#include "counter.h"
|
||||
#include "HistMem.h"
|
||||
#include "HistMem.i"
|
||||
#include "HistDriv.i"
|
||||
#include "hardsup/sinqhm.h"
|
||||
#include "sinqhmdriv.i"
|
||||
#include "nxdict.h"
|
||||
#include "frame.h"
|
||||
/*======================================================================*/
|
||||
static int readHMFrame(SConnection *pCon, pHistMem pHM, int nFrame){
|
||||
HistInt *buffer = NULL;
|
||||
int iDim[MAXDIM], rank, length, status, i, noTimeBins;
|
||||
pSINQHM pHist;
|
||||
SinqHMDriv *pTata;
|
||||
const float *timeBin;
|
||||
|
||||
/*
|
||||
find dimensions and allocate data
|
||||
*/
|
||||
GetHistDim(pHM,iDim,&rank);
|
||||
timeBin = GetHistTimeBin(pHM,&noTimeBins);
|
||||
|
||||
if(rank < 2){
|
||||
SCWrite(pCon,"ERROR: no PSD data present, cannot send frame",eError);
|
||||
return 0;
|
||||
}
|
||||
length = iDim[0]*iDim[1];
|
||||
buffer = (HistInt *)malloc((length + 2)*sizeof(HistInt));
|
||||
if(!buffer){
|
||||
SCWrite(pCon,"ERROR: out of memory in readHMFrame",eError);
|
||||
return 0;
|
||||
}
|
||||
memset(buffer,0,(length+2)*sizeof(HistInt));
|
||||
|
||||
/*
|
||||
first two values are dimensions
|
||||
*/
|
||||
buffer[0] = htonl(iDim[0]);
|
||||
buffer[1] = htonl(iDim[1]);
|
||||
|
||||
if(isSINQHMDriv(pHM->pDriv) && noTimeBins > 2) {
|
||||
/*
|
||||
read from HM. The 5 is PROJECT__FRAME in Sinqhm_def.h
|
||||
Again: be friendly: fix out of range frames
|
||||
*/
|
||||
if(nFrame < 0){
|
||||
nFrame = 0;
|
||||
}
|
||||
if(nFrame >= noTimeBins){
|
||||
nFrame = noTimeBins-1;
|
||||
}
|
||||
pTata = (SinqHMDriv *)pHM->pDriv->pPriv;
|
||||
pHist = (pSINQHM)pTata->pMaster;
|
||||
status = SINQHMProject(pHist, 0x0005, 0, nFrame,
|
||||
0, iDim[1], buffer+2,length*sizeof(HistInt));
|
||||
if(status != 1){
|
||||
SCWrite(pCon,"ERROR: SINQHM refused to deliver frame",eError);
|
||||
free(buffer);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
be friendly, just read the 2D data which is there
|
||||
*/
|
||||
status = GetHistogram(pHM,pCon,0,0,length,buffer+2,length*sizeof(HistInt));
|
||||
if(!status){
|
||||
free(buffer);
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
enforce network byte order
|
||||
*/
|
||||
for(i = 0; i < length; i++){
|
||||
buffer[i+2] = htonl(buffer[i+2]);
|
||||
}
|
||||
|
||||
SCWriteUUencoded(pCon,"framedata", buffer,(length+2)*sizeof(HistInt));
|
||||
free(buffer);
|
||||
|
||||
return 1;
|
||||
}
|
||||
/*=======================================================================*/
|
||||
static int readFileFrame(SConnection *pCon,
|
||||
char *file, char *dictFile,
|
||||
char *alias, int nFrame){
|
||||
int status, iDim[NX_MAXRANK], rank = 0, type = 0;
|
||||
int iStart[3], iSize[3], length, i;
|
||||
int *buffer = NULL;
|
||||
NXhandle fileHandle;
|
||||
NXdict dictHandle;
|
||||
char error[512];
|
||||
|
||||
status = NXopen(file,NXACC_READ,&fileHandle);
|
||||
if(status != NX_OK){
|
||||
sprintf(error,"ERROR: failed to open %s", file);
|
||||
SCWrite(pCon,error,eError);
|
||||
return 0;
|
||||
}
|
||||
status = NXDinitfromfile(dictFile, &dictHandle);
|
||||
if(status != NX_OK){
|
||||
sprintf(error,"ERROR: failed to open dictionary %s", dictFile);
|
||||
NXclose(&fileHandle);
|
||||
SCWrite(pCon,error,eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
status = NXDopenalias(fileHandle,dictHandle,alias);
|
||||
if(status != NX_OK){
|
||||
sprintf(error,"ERROR: failed to open alias %s", alias);
|
||||
NXclose(&fileHandle);
|
||||
NXDclose(dictHandle,NULL);
|
||||
SCWrite(pCon,error,eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
status = NXgetinfo(fileHandle,&rank,iDim,&type);
|
||||
if(type != NX_INT32 && type != NX_UINT32)type = -1;
|
||||
if(status != NX_OK || rank < 2 || type < 0 ){
|
||||
sprintf(error,"ERROR: Dataset does not match!");
|
||||
NXclose(&fileHandle);
|
||||
NXDclose(dictHandle,NULL);
|
||||
SCWrite(pCon,error,eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
allocate space
|
||||
*/
|
||||
length = iDim[0]*iDim[1];
|
||||
buffer = (int *)malloc((length+2)*sizeof(int));
|
||||
if(!buffer){
|
||||
NXclose(&fileHandle);
|
||||
NXDclose(dictHandle,NULL);
|
||||
SCWrite(pCon,"ERROR: out of memory in readFrameFromFile",eError);
|
||||
return 0;
|
||||
}
|
||||
memset(buffer,0,(length+2)*sizeof(int));
|
||||
|
||||
/*
|
||||
first two values: dimensions
|
||||
*/
|
||||
buffer[0] = htonl(iDim[0]);
|
||||
buffer[1] = htonl(iDim[1]);
|
||||
|
||||
if(rank == 2){
|
||||
/*
|
||||
be friendly
|
||||
*/
|
||||
status = NXgetdata(fileHandle,buffer+2);
|
||||
} else {
|
||||
iStart[0] = iStart[1] = 0;
|
||||
iStart[2] = nFrame;
|
||||
iSize[0] = iDim[0];
|
||||
iSize[1] = iDim[1];
|
||||
iSize[2] = 1;
|
||||
status = NXgetslab(fileHandle,buffer+2,iStart,iSize);
|
||||
}
|
||||
if(status != NX_OK){
|
||||
NXclose(&fileHandle);
|
||||
NXDclose(dictHandle,NULL);
|
||||
free(buffer);
|
||||
SCWrite(pCon,"ERROR: failed to read data",eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
enforce network byte order
|
||||
*/
|
||||
for(i = 0; i < length; i++){
|
||||
buffer[2+i] = htonl(buffer[2+i]);
|
||||
}
|
||||
|
||||
SCWriteUUencoded(pCon,"framedata",buffer,(length+2)*sizeof(int));
|
||||
NXclose(&fileHandle);
|
||||
NXDclose(dictHandle,NULL);
|
||||
free(buffer);
|
||||
return 1;
|
||||
}
|
||||
/*=======================================================================*/
|
||||
int PSDFrameAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]){
|
||||
pHistMem pHM;
|
||||
int nFrame;
|
||||
|
||||
if(argc < 2){
|
||||
SCWrite(pCon,"ERROR: Insufficient number of arguments to PSDFrame",
|
||||
eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
strtolower(argv[1]);
|
||||
if(strcmp(argv[1],"hm") == 0){
|
||||
if(argc < 4){
|
||||
SCWrite(pCon,"ERROR: Insufficient number of arguments to PSDFrame",
|
||||
eError);
|
||||
return 0;
|
||||
}
|
||||
pHM = (pHistMem)FindCommandData(pSics,argv[2],"HistMem");
|
||||
if(pHM == NULL){
|
||||
SCWrite(pCon,"ERROR: Did not find histogram memory",eError);
|
||||
return 0;
|
||||
}
|
||||
nFrame = atoi(argv[3]);
|
||||
return readHMFrame(pCon,pHM,nFrame);
|
||||
} else if(strcmp(argv[1],"file") == 0){
|
||||
if(argc < 6 ){
|
||||
SCWrite(pCon,"ERROR: Insufficient number of arguments to PSDframe file",
|
||||
eError);
|
||||
return 0;
|
||||
}
|
||||
nFrame = atoi(argv[5]);
|
||||
return readFileFrame(pCon,argv[2],argv[3],argv[4],nFrame);
|
||||
} else {
|
||||
SCWrite(pCon,"ERROR: subcommand to PSDframe not recognised",eError);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/*======================================================================*/
|
||||
int MakeFrameFunc(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]){
|
||||
return AddCommand(pSics,"PSDframe",PSDFrameAction,NULL,NULL);
|
||||
}
|
||||
|
22
frame.h
Normal file
22
frame.h
Normal file
@ -0,0 +1,22 @@
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
A module implementing functionality for reading single time frames
|
||||
from PSD time-of-flight datasets. This can be done either from
|
||||
SINQHM histogram memories or from old data files visible from the
|
||||
SICS server.
|
||||
|
||||
copyright: see file COPYRIGHT
|
||||
|
||||
Mark Koennecke, February-March 2003
|
||||
*/
|
||||
#ifndef SICSFRAME
|
||||
#define SICSFRAME
|
||||
|
||||
int MakeFrameFunc(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
|
||||
int PSDFrameAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
|
||||
|
||||
#endif
|
32
frame.w
Normal file
32
frame.w
Normal file
@ -0,0 +1,32 @@
|
||||
\subsection{Frame}
|
||||
This module allows to retrieve data frames from a 3D histogram (PSD plus
|
||||
time dimension). This can be done either from a Sinq histogram memory
|
||||
and old data files visible from the SICS server.
|
||||
|
||||
This module has no data structure and only implements the usual
|
||||
interpreter interface functions.
|
||||
|
||||
|
||||
@o frame.h @{
|
||||
/*-------------------------------------------------------------------------
|
||||
A module implementing functionality for reading single time frames
|
||||
from PSD time-of-flight datasets. This can be done either from
|
||||
SINQHM histogram memories or from old data files visible from the
|
||||
SICS server.
|
||||
|
||||
copyright: see file COPYRIGHT
|
||||
|
||||
Mark Koennecke, February-March 2003
|
||||
*/
|
||||
#ifndef SICSFRAME
|
||||
#define SICSFRAME
|
||||
|
||||
int MakeFrameFunc(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
|
||||
int PSDFrameAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
|
||||
|
||||
#endif
|
||||
@}
|
54
hardsup/sinqhm.i
Normal file
54
hardsup/sinqhm.i
Normal file
@ -0,0 +1,54 @@
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
|
||||
Internal header file for the SINQ histogram memory utility functions.
|
||||
|
||||
David Maden, Mark Koennecke April 1997
|
||||
----------------------------------------------------------------------------*/
|
||||
#ifndef SINQHMINTERNAL
|
||||
#define SINQHMINTERNAL
|
||||
#define MAXBANK 1
|
||||
|
||||
typedef struct __SBANK {
|
||||
int iStart;
|
||||
int iEnd;
|
||||
int iFlag;
|
||||
int iEdgeLength;
|
||||
int iDelay;
|
||||
unsigned int *iEdges;
|
||||
} SBank, *pSBank;
|
||||
|
||||
|
||||
typedef struct __SINQHM {
|
||||
char *pHMComputer;
|
||||
int iMasterPort;
|
||||
int iMasterSocket;
|
||||
int iClientPort;
|
||||
int iClientSocket;
|
||||
int iBinWidth;
|
||||
int iLength;
|
||||
int iRank;
|
||||
int iPacket;
|
||||
int iBanks;
|
||||
int xSize, ySize;
|
||||
int xOff, xFac;
|
||||
int yOff, yFac;
|
||||
SBank pBank[MAXBANK];
|
||||
} SINQHM;
|
||||
|
||||
/*---------------------------- Type definitions, machine dependent--------*/
|
||||
typedef short int SQint16; /* 16 bit integer */
|
||||
typedef int SQint32; /* 32 bit integer */
|
||||
|
||||
|
||||
|
||||
static int OpenMasterConnection(pSINQHM self);
|
||||
static int GetMasterReply(pSINQHM self, struct rply_buff_struct *reply,
|
||||
int iBufLen);
|
||||
static int SendDAQCommand(pSINQHM self, int iCommand, int *iDaq);
|
||||
|
||||
|
||||
static int SINQHMTimeBin(pSINQHM self, int iMode);
|
||||
|
||||
#endif
|
||||
|
25
make_gen
Normal file
25
make_gen
Normal file
@ -0,0 +1,25 @@
|
||||
#-------------------------------------------------------------------------
|
||||
# common part of the makefile for the PSI specific parts of SICS
|
||||
#
|
||||
# Mark Koennecke, June 2003
|
||||
#-------------------------------------------------------------------------
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .c .o .f
|
||||
|
||||
OBJ=psi.o buffer.o ruli.o dmc.o nxsans.o nextrics.o sps.o pimotor.o \
|
||||
pipiezo.o sanswave.o faverage.o fowrite.o amor2t.o nxamor.o \
|
||||
amorstat.o tasinit.o tasdrive.o tasutil.o tasscan.o swmotor.o \
|
||||
polterwrite.o ecb.o frame.o el734driv.o el734dc.o ecbdriv.o \
|
||||
ecbcounter.o el737driv.o sinqhmdriv.o tdchm.o velodorn.o \
|
||||
velodornier.o docho.o sanscook.o tecsdriv.o itc4driv.o itc4.o\
|
||||
bruker.o ltc11.o A1931.o dilludriv.o eurodriv.o slsmagnet.o \
|
||||
el755driv.o amorscan.o serial.o scontroller.o
|
||||
|
||||
libpsi.a: $(OBJ)
|
||||
- rm libpsi.a
|
||||
ar cr libpsi.a $(OBJ)
|
||||
ranlib libpsi.a
|
||||
|
||||
clean:
|
||||
- rm *.a
|
||||
- rm *.o
|
16
makefile_alpha
Normal file
16
makefile_alpha
Normal file
@ -0,0 +1,16 @@
|
||||
#---------------------------------------------------------------------------
|
||||
# Makefile for the PSI specific part of SICS
|
||||
# machine-dependent part for Tru64 Unix
|
||||
#
|
||||
# Mark Koennecke, June 2003
|
||||
#--------------------------------------------------------------------------
|
||||
# the following line only for fortified version
|
||||
#DFORTIFY=-DFORTIFY
|
||||
#==========================================================================
|
||||
|
||||
HDFROOT=/data/lnslib
|
||||
CC = cc
|
||||
CFLAGS = -std1 -g $(DFORTIFY) -I.. -I$(HDFROOT)/include -DHDF4 -DHDF5 \
|
||||
-Ihardsup
|
||||
|
||||
include make_gen
|
796
nxsans.c
Normal file
796
nxsans.c
Normal file
@ -0,0 +1,796 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
N X S A N S
|
||||
|
||||
a module of utility functions which serve to write Nexus
|
||||
data files for SANS.
|
||||
|
||||
Mark Koennecke, August 1997 - November 1998
|
||||
|
||||
Updated to support the larger detector resolution and possible
|
||||
TOF and stroboscopic modes, Mark Koennecke, February 2001
|
||||
|
||||
Added additional monitors for stroboscopic gummi mode,
|
||||
Mark Koennecke, September 2002
|
||||
|
||||
Copyright:
|
||||
|
||||
Labor fuer Neutronenstreuung
|
||||
Paul Scherrer Institut
|
||||
CH-5423 Villigen-PSI
|
||||
|
||||
|
||||
The authors hereby grant permission to use, copy, modify, distribute,
|
||||
and license this software and its documentation for any purpose, provided
|
||||
that existing copyright notices are retained in all copies and that this
|
||||
notice is included verbatim in any distributions. No written agreement,
|
||||
license, or royalty fee is required for any of the authorized uses.
|
||||
Modifications to this software may be copyrighted by their authors
|
||||
and need not follow the licensing terms described here, provided that
|
||||
the new terms are clearly indicated on the first page of each file where
|
||||
they apply.
|
||||
|
||||
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
||||
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
||||
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE
|
||||
IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
|
||||
NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
|
||||
MODIFICATIONS.
|
||||
----------------------------------------------------------------------------*/
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <time.h>
|
||||
#include "fortify.h"
|
||||
#include "sics.h"
|
||||
#include "sicsvar.h"
|
||||
#include "napi.h"
|
||||
#include "nxdict.h"
|
||||
#include "modriv.h"
|
||||
#include "motor.h"
|
||||
#include "nxutil.h"
|
||||
#include "nxdata.h"
|
||||
#include "countdriv.h"
|
||||
#include "counter.h"
|
||||
#include "danu.h"
|
||||
#include "HistMem.h"
|
||||
#include "velo.h"
|
||||
#include "sps.h"
|
||||
#include "udpquieck.h"
|
||||
#include "mumo.h"
|
||||
#include "sanswave.h"
|
||||
|
||||
|
||||
#define HISTNAME "banana"
|
||||
#define SAMPLETABLE "sampletable"
|
||||
|
||||
static int gummiFlag = 0; /* a flag indicating stroboscopic, or gummi mode */
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
static void SNError(void *pData, char *text)
|
||||
{
|
||||
SConnection *pCon;
|
||||
|
||||
assert(pData);
|
||||
pCon = (SConnection *)pData;
|
||||
SCWrite(pCon,text,eError);
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
NXhandle SNXStartSANS(SConnection *pCon, SicsInterp *pSics)
|
||||
{
|
||||
NXhandle pFile = NULL;
|
||||
char *filename = NULL;
|
||||
pSicsVariable pVar = NULL;
|
||||
int iStat;
|
||||
char pBueffel[512];
|
||||
|
||||
/* get a filename */
|
||||
filename = SNXMakeFileName(pSics,pCon);
|
||||
if(!filename)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* create a Nexus file */
|
||||
NXopen(filename,NXACC_CREATE,&pFile);
|
||||
if(!pFile)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: cannot create data file ",eError);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* tell Uwe User what we are doing */
|
||||
sprintf(pBueffel,"Writing %s ......",filename);
|
||||
SCWrite(pCon,pBueffel,eWarning);
|
||||
|
||||
/* store global attributes */
|
||||
iStat = NXputattr(pFile,"file_name",filename,
|
||||
strlen(filename)+1,NX_CHAR);
|
||||
if(iStat == NX_ERROR)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: writing file_name attribute to Nexus file",eError);
|
||||
}
|
||||
|
||||
/* throw away filename, no longer needed */
|
||||
free(filename);
|
||||
|
||||
/* write creation time */
|
||||
SNXFormatTime(pBueffel,512);
|
||||
iStat = NXputattr(pFile,"file_time",pBueffel,
|
||||
strlen(pBueffel)+1,NX_CHAR);
|
||||
if(iStat == NX_ERROR)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: writing date attribute to Nexus file",eError);
|
||||
}
|
||||
pVar = FindVariable(pSics,"instrument");
|
||||
if(pVar)
|
||||
{
|
||||
iStat = NXputattr(pFile,"instrument",pVar->text,
|
||||
strlen(pVar->text)+1,NX_CHAR);
|
||||
if(iStat == NX_ERROR)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: writing instrument attribute to Nexus file",eError);
|
||||
}
|
||||
}
|
||||
pVar = NULL;
|
||||
pVar = FindVariable(pSics,"user");
|
||||
if(pVar)
|
||||
{
|
||||
iStat = NXputattr(pFile,"owner",pVar->text,
|
||||
strlen(pVar->text)+1,NX_CHAR);
|
||||
if(iStat == NX_ERROR)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: writing owner attribute to Nexus file",eError);
|
||||
}
|
||||
}
|
||||
|
||||
pVar = NULL;
|
||||
pVar = FindVariable(pSics,"adress");
|
||||
if(pVar)
|
||||
{
|
||||
iStat = NXputattr(pFile,"owner_adress",pVar->text,
|
||||
strlen(pVar->text)+1,NX_CHAR);
|
||||
if(iStat == NX_ERROR)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: writing owner_adress attribute to Nexus file",eError);
|
||||
}
|
||||
}
|
||||
pVar = NULL;
|
||||
pVar = FindVariable(pSics,"phone");
|
||||
if(pVar)
|
||||
{
|
||||
iStat = NXputattr(pFile,"owner_telephone_number",pVar->text,
|
||||
strlen(pVar->text)+1,NX_CHAR);
|
||||
if(iStat == NX_ERROR)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: writing owner_telephone_number attribute to Nexus file",eError);
|
||||
}
|
||||
}
|
||||
pVar = NULL;
|
||||
pVar = FindVariable(pSics,"fax");
|
||||
if(pVar)
|
||||
{
|
||||
iStat = NXputattr(pFile,"owner_fax_number",pVar->text,
|
||||
strlen(pVar->text)+1,NX_CHAR);
|
||||
if(iStat == NX_ERROR)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: writing owner_fax_number attribute to Nexus file",eError);
|
||||
}
|
||||
}
|
||||
pVar = NULL;
|
||||
pVar = FindVariable(pSics,"email");
|
||||
if(pVar)
|
||||
{
|
||||
iStat = NXputattr(pFile,"owner_email",pVar->text,
|
||||
strlen(pVar->text)+1,NX_CHAR);
|
||||
if(iStat == NX_ERROR)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: writing owner_email attribute to Nexus file",eError);
|
||||
}
|
||||
}
|
||||
pVar = NULL;
|
||||
return pFile;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int SNMakeSANS(SConnection *pCon, SicsInterp *pSics, NXdict pDict)
|
||||
{
|
||||
NXhandle Nfil = NULL;
|
||||
char pBueffel[512];
|
||||
float fVal;
|
||||
int iVal, iSet;
|
||||
int32 iAxis[256];
|
||||
int i, iRet;
|
||||
long lVal;
|
||||
HistInt *lData = NULL;
|
||||
const float *fTime = NULL;
|
||||
CommandList *pCom = NULL;
|
||||
pHistMem self = NULL;
|
||||
CounterMode eMode;
|
||||
pVelSel pVelo = NULL;
|
||||
pSPS pSiem = NULL;
|
||||
const char *pNamPos = NULL;
|
||||
float fRot, fTilt, fLambda;
|
||||
pDummy pDum;
|
||||
pIDrivable pDrive;
|
||||
int iDim[MAXDIM], nDim, histSize,iStart;
|
||||
|
||||
/* start file */
|
||||
Nfil = SNXStartSANS(pCon,pSics);
|
||||
if(!Nfil)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
during all this, no extensive error checking will be done,
|
||||
just write the error and continue, save at all cost
|
||||
*/
|
||||
|
||||
/* put all this global information */
|
||||
SNXSPutVariable(pSics,pCon,Nfil,pDict,"etitle","title");
|
||||
SNXSPutVariable(pSics,pCon,Nfil,pDict,"etime","starttime");
|
||||
SNXFormatTime(pBueffel,511);
|
||||
NXDputalias(Nfil,pDict,"endtime",pBueffel);
|
||||
strcpy(pBueffel,"SANS at SINQ,PSI");
|
||||
NXDputalias(Nfil,pDict,"iname",pBueffel);
|
||||
strcpy(pBueffel,"SINQ at PSI,Villigen, Switzerland");
|
||||
NXDputalias(Nfil,pDict,"sname",pBueffel);
|
||||
strcpy(pBueffel,"Spallation");
|
||||
NXDputalias(Nfil,pDict,"stype",pBueffel);
|
||||
|
||||
/* put the velocity selector data */
|
||||
NXDputalias(Nfil,pDict,"vname","Dornier Velocity Selector");
|
||||
|
||||
fRot = 0.;
|
||||
fTilt = 0.;
|
||||
pCom = FindCommand(pSics,"nvs");
|
||||
if(pCom)
|
||||
{
|
||||
pVelo = (pVelSel)pCom->pData;
|
||||
if(!pVelo)
|
||||
{
|
||||
SCWrite(pCon,"WARNING: Velocity Selctor not found",eWarning);
|
||||
}
|
||||
iRet = VSGetRotation(pVelo,&fVal);
|
||||
if(!iRet)
|
||||
{
|
||||
SCWrite(pCon,"WARNING: failed to read velocity selector speed",
|
||||
eWarning);
|
||||
}
|
||||
else
|
||||
{
|
||||
fRot = fVal;
|
||||
NXDputalias(Nfil,pDict,"vrot",&fVal);
|
||||
}
|
||||
iRet = VSGetTilt(pVelo,&fTilt);
|
||||
if(!iRet)
|
||||
{
|
||||
SCWrite(pCon,"WARNING: failed to read velocity selector tilt angle",eWarning);
|
||||
}
|
||||
}
|
||||
SNXSPutMotor(pSics,pCon,Nfil,pDict,"vtilt","tilt");
|
||||
CalculateLambda(fRot, fTilt, &fLambda);
|
||||
NXDputalias(Nfil,pDict,"vlambda",&fLambda);
|
||||
|
||||
|
||||
/* monitor 1 */
|
||||
pCom = FindCommand(pSics,HISTNAME);
|
||||
if(!pCom)
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: histogram memory %s not found",HISTNAME);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return 0;
|
||||
}
|
||||
self = (pHistMem)pCom->pData;
|
||||
assert(self);
|
||||
lVal = GetHistMonitor(self,0,pCon);
|
||||
iVal = (int32)lVal;
|
||||
NXDputalias(Nfil,pDict,"m1counts",&iVal);
|
||||
lVal = GetHistMonitor(self,4,pCon);
|
||||
iVal = (int32)lVal;
|
||||
NXDputalias(Nfil,pDict,"pbcounts",&iVal);
|
||||
|
||||
/* the collimator */
|
||||
pCom = FindCommand(pSics,"sps2");
|
||||
if(!pCom)
|
||||
{
|
||||
SCWrite(pCon,"WARNING: sps-unit for reading collimator NOT found",
|
||||
eWarning);
|
||||
}
|
||||
else
|
||||
{
|
||||
pSiem = (pSPS)pCom->pData;
|
||||
if(!pSiem)
|
||||
{
|
||||
SCWrite(pCon,"WARNING: sps-unit for reading collimator NOT found",
|
||||
eWarning);
|
||||
}
|
||||
else
|
||||
{
|
||||
iRet = SPSGetSANS(pSiem,&fVal);
|
||||
if(iRet <= 0)
|
||||
{
|
||||
SCWrite(pCon,"WARNING: Failed to read SPS",eWarning);
|
||||
}
|
||||
else
|
||||
{
|
||||
NXDputalias(Nfil,pDict,"colli",&fVal);
|
||||
}
|
||||
/* as we got the sps, get the attenuator as well */
|
||||
iRet = SPSGetStatus(pSiem,38,&iSet);
|
||||
if(iRet <0)
|
||||
{
|
||||
SCWrite(pCon,"WARNING: Failed to read SPS",eWarning);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(iSet)
|
||||
{
|
||||
iVal = 0;
|
||||
}
|
||||
}
|
||||
iRet = SPSGetStatus(pSiem,39,&iSet);
|
||||
if(iRet <0)
|
||||
{
|
||||
SCWrite(pCon,"WARNING: Failed to read SPS",eWarning);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(iSet)
|
||||
{
|
||||
iVal = 1;
|
||||
}
|
||||
}
|
||||
iRet = SPSGetStatus(pSiem,40,&iSet);
|
||||
if(iRet <0)
|
||||
{
|
||||
SCWrite(pCon,"WARNING: Failed to read SPS",eWarning);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(iSet)
|
||||
{
|
||||
iVal = 2;
|
||||
}
|
||||
}
|
||||
iRet = SPSGetStatus(pSiem,41,&iSet);
|
||||
if(iRet <0)
|
||||
{
|
||||
SCWrite(pCon,"WARNING: Failed to read SPS",eWarning);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(iSet)
|
||||
{
|
||||
iVal = 3;
|
||||
}
|
||||
}
|
||||
iRet = SPSGetStatus(pSiem,42,&iSet);
|
||||
if(iRet <0)
|
||||
{
|
||||
SCWrite(pCon,"WARNING: Failed to read SPS",eWarning);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(iSet)
|
||||
{
|
||||
iVal = 4;
|
||||
}
|
||||
}
|
||||
iRet = SPSGetStatus(pSiem,43,&iSet);
|
||||
if(iRet <0)
|
||||
{
|
||||
SCWrite(pCon,"WARNING: Failed to read SPS",eWarning);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(iSet)
|
||||
{
|
||||
iVal = 5;
|
||||
}
|
||||
}
|
||||
NXDputalias(Nfil,pDict,"atti",&iVal);
|
||||
}
|
||||
}
|
||||
|
||||
/* the sample */
|
||||
SNXSPutVariable(pSics,pCon,Nfil,pDict,"san","sample");
|
||||
SNXSPutVariable(pSics,pCon,Nfil,pDict,"saenv","environment");
|
||||
SNXSPutMotor(pSics,pCon,Nfil,pDict,"sax","sax");
|
||||
SNXSPutMotor(pSics,pCon,Nfil,pDict,"say","say");
|
||||
SNXSPutMotor(pSics,pCon,Nfil,pDict,"saz","saz");
|
||||
SNXSPutMotorNull(pSics,pCon,Nfil,pDict,"saxn","sax");
|
||||
SNXSPutMotorNull(pSics,pCon,Nfil,pDict,"sayn","say");
|
||||
SNXSPutMotorNull(pSics,pCon,Nfil,pDict,"sazn","saz");
|
||||
|
||||
|
||||
/* goniometer */
|
||||
SNXSPutMotor(pSics,pCon,Nfil,pDict,"gphi","gphi");
|
||||
SNXSPutMotor(pSics,pCon,Nfil,pDict,"gtheta","gtheta");
|
||||
SNXSPutMotorNull(pSics,pCon,Nfil,pDict,"gphin","gphi");
|
||||
SNXSPutMotorNull(pSics,pCon,Nfil,pDict,"gthetan","gtheta");
|
||||
|
||||
SNXSPutMotor(pSics,pCon,Nfil,pDict,"saom","som");
|
||||
SNXSPutMotorNull(pSics,pCon,Nfil,pDict,"saomn","som");
|
||||
SNXSPutMotor(pSics,pCon,Nfil,pDict,"sapos","spos");
|
||||
SNXSPutMotorNull(pSics,pCon,Nfil,pDict,"saposn","spos");
|
||||
pCom = FindCommand(pSics,SAMPLETABLE);
|
||||
if(pCom)
|
||||
{
|
||||
if(pCom->pData)
|
||||
{
|
||||
pNamPos = FindNamPos((pMulMot)pCom->pData,pCon);
|
||||
if(pNamPos)
|
||||
{
|
||||
NXDputalias(Nfil,pDict,"sanampos",(char *)pNamPos);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* write sample environment here */
|
||||
pCom = FindCommand(pSics,"temperature");
|
||||
if(pCom)
|
||||
{
|
||||
pDum = (pDummy)pCom->pData;
|
||||
pDrive = pDum->pDescriptor->GetInterface(pDum,DRIVEID);
|
||||
if(pDrive) /* a proper environment device */
|
||||
{
|
||||
fVal = pDrive->GetValue(pDum,pCon);
|
||||
NXDputalias(Nfil,pDict,"satemp",&fVal);
|
||||
}
|
||||
}
|
||||
pCom = FindCommand(pSics,"magnet");
|
||||
if(pCom)
|
||||
{
|
||||
pDum = (pDummy)pCom->pData;
|
||||
pDrive = pDum->pDescriptor->GetInterface(pDum,DRIVEID);
|
||||
if(pDrive) /* a proper environment device */
|
||||
{
|
||||
fVal = pDrive->GetValue(pDum,pCon);
|
||||
NXDputalias(Nfil,pDict,"samag",&fVal);
|
||||
}
|
||||
}
|
||||
|
||||
/* magnet motors. This instrument has motorized magnets crawling
|
||||
through the hall */
|
||||
pCom = FindCommand(pSics,"mom");
|
||||
if(pCom)
|
||||
{
|
||||
SNXSPutMotor(pSics,pCon,Nfil,pDict,"mom","mom");
|
||||
}
|
||||
pCom = FindCommand(pSics,"mz");
|
||||
if(pCom)
|
||||
{
|
||||
SNXSPutMotor(pSics,pCon,Nfil,pDict,"mz","mz");
|
||||
}
|
||||
|
||||
|
||||
/* put Beam Stop */
|
||||
/* read beamstop number */
|
||||
iVal = 1;
|
||||
pCom = FindCommand(pSics,"sps1");
|
||||
if(!pCom)
|
||||
{
|
||||
SCWrite(pCon,"WARNING: sps-unit for reading beamstop NOT found",eWarning);
|
||||
}
|
||||
else
|
||||
{
|
||||
pSiem = (pSPS)pCom->pData;
|
||||
if(!pSiem)
|
||||
{
|
||||
SCWrite(pCon,"WARNING: sps-unit for reading beamstop NOT found",eWarning);
|
||||
}
|
||||
else
|
||||
{
|
||||
iRet = SPSGetStatus(pSiem,8,&iSet);
|
||||
if(iRet <0)
|
||||
{
|
||||
SCWrite(pCon,"WARNING: Failed to read SPS",eWarning);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(iSet)
|
||||
{
|
||||
iVal = 2;
|
||||
}
|
||||
}
|
||||
iRet = SPSGetStatus(pSiem,9,&iSet);
|
||||
if(iRet <0)
|
||||
{
|
||||
SCWrite(pCon,"WARNING: Failed to read SPS",eWarning);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(iSet)
|
||||
{
|
||||
iVal = 3;
|
||||
}
|
||||
}
|
||||
iRet = SPSGetStatus(pSiem,10,&iSet);
|
||||
if(iRet <0)
|
||||
{
|
||||
SCWrite(pCon,"WARNING: Failed to read SPS",eWarning);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(iSet)
|
||||
{
|
||||
iVal = 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
NXDputalias(Nfil,pDict,"bst",&iVal);
|
||||
SNXSPutMotor(pSics,pCon,Nfil,pDict,"vsx","BeamStopX");
|
||||
SNXSPutMotor(pSics,pCon,Nfil,pDict,"vsy","BeamStopY");
|
||||
SNXSPutMotorNull(pSics,pCon,Nfil,pDict,"vsxnull","BeamStopX");
|
||||
SNXSPutMotorNull(pSics,pCon,Nfil,pDict,"vsynull","BeamStopY");
|
||||
|
||||
/* what this is all about: the detector */
|
||||
SNXSPutMotor(pSics,pCon,Nfil,pDict,"ddx","DetectorX");
|
||||
SNXSPutMotor(pSics,pCon,Nfil,pDict,"ddy","DetectorY");
|
||||
SNXSPutMotorNull(pSics,pCon,Nfil,pDict,"ddxn","DetectorX");
|
||||
SNXSPutMotorNull(pSics,pCon,Nfil,pDict,"ddyn","DetectorY");
|
||||
SNXSPutMotor(pSics,pCon,Nfil,pDict,"ddchi","DetectorRotation");
|
||||
pCom = FindCommand(pSics,HISTNAME);
|
||||
if(!pCom)
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: histogram memory %s not found",HISTNAME);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return 0;
|
||||
}
|
||||
self = (pHistMem)pCom->pData;
|
||||
assert(self);
|
||||
eMode = GetHistCountMode(self);
|
||||
if(eMode == eTimer)
|
||||
{
|
||||
strcpy(pBueffel,"Timer");
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(pBueffel,"Monitor");
|
||||
}
|
||||
NXDputalias(Nfil,pDict,"ddm",pBueffel);
|
||||
fVal = GetHistPreset(self);
|
||||
NXDputalias(Nfil,pDict,"ddp",&fVal);
|
||||
lVal = GetHistMonitor(self,1,pCon);
|
||||
iVal = (int32)lVal;
|
||||
NXDputalias(Nfil,pDict,"ddmo",&iVal);
|
||||
fVal = GetHistCountTime(self,pCon);
|
||||
NXDputalias(Nfil,pDict,"ddtime",&fVal);
|
||||
|
||||
/*
|
||||
Deal with actual histogram. Due to stroboscopic modes and the
|
||||
new detector electronics we need to find out about the size
|
||||
ourselves now. And possibly write time binning information.
|
||||
*/
|
||||
GetHistDim(self, iDim,&nDim);
|
||||
/*
|
||||
handle time binning
|
||||
*/
|
||||
fTime = GetHistTimeBin(self,&iVal);
|
||||
if(iVal > 2)
|
||||
{
|
||||
NXDputalias(Nfil,pDict,"ddtb",(void *)fTime);
|
||||
nDim = 3;
|
||||
iDim[2] = iVal;
|
||||
}
|
||||
|
||||
histSize = 1;
|
||||
for(i = 0; i < nDim; i++)
|
||||
{
|
||||
histSize *= iDim[i];
|
||||
}
|
||||
lData = (HistInt *)malloc(histSize*sizeof(HistInt));
|
||||
if(!lData)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: out of memory, FAILED to store data, file corrupt",
|
||||
eError);
|
||||
NXclose(&Nfil);
|
||||
return 0;
|
||||
}
|
||||
GetHistogram(self,pCon,0,0,histSize,lData,histSize*sizeof(HistInt));
|
||||
sprintf(pBueffel," %d ",iDim[0]);
|
||||
NXDupdate(pDict,"dim1",pBueffel);
|
||||
sprintf(pBueffel," %d ",iDim[1]);
|
||||
NXDupdate(pDict,"dim2",pBueffel);
|
||||
if(nDim == 2)
|
||||
{
|
||||
sprintf(pBueffel," -rank 2 -dim {%d,%d} ", iDim[0], iDim[1]);
|
||||
NXDupdate(pDict,"countdim",pBueffel);
|
||||
}
|
||||
else if (nDim == 3)
|
||||
{
|
||||
sprintf(pBueffel," -rank 3 -dim {%d,%d,%d} ", iDim[0], iDim[1],
|
||||
iDim[2]);
|
||||
NXDupdate(pDict,"countdim",pBueffel);
|
||||
sprintf(pBueffel," %d ",iDim[2]);
|
||||
NXDupdate(pDict,"timedim",pBueffel);
|
||||
}
|
||||
NXDputalias(Nfil,pDict,"ddcounts",lData);
|
||||
free(lData);
|
||||
|
||||
/* write x and y axis */
|
||||
for(i = 0; i < iDim[0]; i++)
|
||||
{
|
||||
iAxis[i] = i;
|
||||
}
|
||||
NXDputalias(Nfil,pDict,"ddcx",iAxis);
|
||||
for(i = 0; i < iDim[1]; i++)
|
||||
{
|
||||
iAxis[i] = i;
|
||||
}
|
||||
NXDputalias(Nfil,pDict,"ddcy",iAxis);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
write gummi monitors when apropriate
|
||||
*/
|
||||
if(nDim == 3 && gummiFlag != 0)
|
||||
{
|
||||
histSize = 3*iDim[2];
|
||||
lData = (HistInt *)malloc(histSize*sizeof(HistInt));
|
||||
if(lData == NULL)
|
||||
{
|
||||
SCWrite(pCon,"WARNING: failed to allocate memory for monitors",
|
||||
eWarning);
|
||||
} else {
|
||||
memset(lData,0,histSize*sizeof(HistInt));
|
||||
iStart = iDim[0]*iDim[1]*iDim[2];
|
||||
GetHistogramDirect(self,pCon,0,iStart,iStart+histSize,
|
||||
lData,histSize*sizeof(HistInt));
|
||||
NXDputalias(Nfil,pDict,"gummimon1",lData);
|
||||
NXDputalias(Nfil,pDict,"gummimon2",lData+iDim[2]);
|
||||
NXDputalias(Nfil,pDict,"gummimon3",lData+2*iDim[2]);
|
||||
free(lData);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
write detector temperature. It is a hot one............
|
||||
*/
|
||||
if(pSiem)
|
||||
{
|
||||
iRet = SPSGetADC(pSiem,1,&iVal);
|
||||
if(iRet)
|
||||
{
|
||||
fVal = iVal/269.9;
|
||||
NXDputalias(Nfil,pDict,"ddtemp",&fVal);
|
||||
}
|
||||
}
|
||||
|
||||
/* do the linking in th data vgroup */
|
||||
NXDaliaslink(Nfil,pDict,"dan","ddcounts");
|
||||
NXDaliaslink(Nfil,pDict,"dan","ddcx");
|
||||
NXDaliaslink(Nfil,pDict,"dan","ddcy");
|
||||
NXDaliaslink(Nfil,pDict,"dan","ddmo");
|
||||
NXDaliaslink(Nfil,pDict,"dan","vlambda");
|
||||
if(nDim == 3)
|
||||
{
|
||||
NXDaliaslink(Nfil,pDict,"dan","ddtb");
|
||||
}
|
||||
|
||||
/* send quieck message for automatic copying*/
|
||||
i = 131;
|
||||
iVal = NX_CHAR;
|
||||
NXgetattr(Nfil,"file_name",pBueffel,&i,&iVal);
|
||||
SendQuieck(QUIECK,pBueffel);
|
||||
/* close this and go ............. */
|
||||
NXclose(&Nfil);
|
||||
return 1;
|
||||
}
|
||||
/*------------------- The Mechanics for setting Up ------------------------*/
|
||||
typedef struct {
|
||||
pObjectDescriptor pDes;
|
||||
NXdict pDict;
|
||||
} DictStruct, *pDictStruct;
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static pDictStruct MakeDictStruct(char *pFile)
|
||||
{
|
||||
pDictStruct pNew = NULL;
|
||||
int iRet;
|
||||
|
||||
pNew = (pDictStruct)malloc(sizeof(DictStruct));
|
||||
if(!pNew)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
memset(pNew,0,sizeof(DictStruct));
|
||||
pNew->pDes = CreateDescriptor("StoreData");
|
||||
if(!pNew->pDes)
|
||||
{
|
||||
free(pNew);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
iRet = NXDinitfromfile(pFile,&(pNew->pDict));
|
||||
if(iRet != NX_OK)
|
||||
{
|
||||
DeleteDescriptor(pNew->pDes);
|
||||
free(pNew);
|
||||
return NULL;
|
||||
}
|
||||
return pNew;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
static void KillDictStruct(void *pData)
|
||||
{
|
||||
pDictStruct self = NULL;
|
||||
|
||||
self = (pDictStruct)pData;
|
||||
assert(self);
|
||||
|
||||
if(self->pDes)
|
||||
{
|
||||
DeleteDescriptor(self->pDes);
|
||||
}
|
||||
if(self->pDict)
|
||||
{
|
||||
NXDclose(self->pDict,NULL);
|
||||
}
|
||||
free(self);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int SNStoreSANS(SConnection *pCon, SicsInterp *pSics, void *pData, int argc,
|
||||
char *argv[])
|
||||
|
||||
{
|
||||
char pBueffel[80];
|
||||
pDictStruct self = NULL;
|
||||
self = (pDictStruct)pData;
|
||||
|
||||
assert(self);
|
||||
assert(pCon);
|
||||
assert(pSics);
|
||||
|
||||
if(argc > 1){
|
||||
strtolower(argv[1]);
|
||||
if(strcmp(argv[1],"gummi") == 0){
|
||||
if(argc > 2){
|
||||
if(!SCMatchRights(pCon,usMugger)){
|
||||
return 0;
|
||||
}
|
||||
gummiFlag = atoi(argv[2]);
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
} else
|
||||
{
|
||||
sprintf(pBueffel,"%s.gummi = %d",argv[0], gummiFlag);
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return SNMakeSANS(pCon,pSics,self->pDict);
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int InitSANS(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[])
|
||||
{
|
||||
pDictStruct pNew = NULL;
|
||||
char pBueffel[512];
|
||||
|
||||
if(argc < 2)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: not enough arguments for IniSANS",eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
pNew = MakeDictStruct(argv[1]);
|
||||
if(!pNew)
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: failed to initialise NXDDL from file %s",
|
||||
argv[1]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return 0;
|
||||
}
|
||||
AddCommand(pSics,"StoreData",SNStoreSANS,KillDictStruct,pNew);
|
||||
return 1;
|
||||
}
|
17
nxsans.h
Normal file
17
nxsans.h
Normal file
@ -0,0 +1,17 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
N X S A N S
|
||||
|
||||
Prototypes for some more useful functions from the SANS data writing
|
||||
module which may ne used in other parts of SICS.
|
||||
|
||||
Mark Koennecke, December 1997
|
||||
---------------------------------------------------------------------------*/
|
||||
#ifndef NXSANS
|
||||
#define NXSANS
|
||||
int InitSANS(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
int SNStoreSANS(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
|
||||
|
||||
#endif
|
282
scontroller.c
Normal file
282
scontroller.c
Normal file
@ -0,0 +1,282 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
Some code to connect to a serial port through the SINQ system.
|
||||
|
||||
Just a wrapper around serialsinq derived from David Maden's
|
||||
EL734 routines.
|
||||
|
||||
You are free to use and modify this software for noncommercial
|
||||
usage.
|
||||
|
||||
No warranties or liabilities of any kind taken by me or my employer
|
||||
|
||||
Very primitive device to send commands to a motor from Tcl
|
||||
|
||||
Modified version for use within SICS.
|
||||
----------------------------------------------------------------------------*/
|
||||
#include "sinq_prototypes.h"
|
||||
/* #include <timers.h>*/
|
||||
#include <tcl.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "rs232c_def.h"
|
||||
#include "el734_def.h"
|
||||
#include "psi/hardsup/serialsinq.h"
|
||||
#include "sics.h"
|
||||
|
||||
#define False 0
|
||||
#define True 1
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Tcl has a high niceness level. It deletes a command properly when
|
||||
exiting, reinitializing etc. I use this facility to kill off the
|
||||
motor initialised in Controller.
|
||||
---------------------------------------------------------------------------*/
|
||||
EXTERN void SerialMurder(ClientData pData)
|
||||
{
|
||||
/*
|
||||
NetReadRemoveUserSocket(pServ->pReader, SerialGetSocket(&(pData)));
|
||||
*/
|
||||
SerialClose(&(pData));
|
||||
free(pData);
|
||||
}
|
||||
/*------------------ a forward declaration -----------------------------*/
|
||||
EXTERN int SurielSend(ClientData clientData, Tcl_Interp *interp,
|
||||
int argc, char *argv[]);
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Controller is the main entry point for this stuff. It connects to a motor
|
||||
and, on success, creates a new command with the name of the motor.
|
||||
Syntax:
|
||||
Controller name host port channel
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
int Controller(ClientData clientData, Tcl_Interp *interp,
|
||||
int argc, char *argv[])
|
||||
{
|
||||
int iRet;
|
||||
int iPort, iChannel, iMotor;
|
||||
char *pErr = NULL;
|
||||
char pBueffel[80];
|
||||
void **pData = NULL;
|
||||
|
||||
/* check arguments */
|
||||
if(argc < 5)
|
||||
{
|
||||
Tcl_AppendResult(interp,
|
||||
" Insufficient arguments: Controller name host port channel index"
|
||||
, (char *) NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/* convert arguments */
|
||||
iRet = Tcl_GetInt(interp,argv[3],&iPort);
|
||||
if(iRet == TCL_ERROR)
|
||||
{
|
||||
Tcl_AppendResult(interp,"Need integer value for port",
|
||||
(char *)NULL);
|
||||
return iRet;
|
||||
}
|
||||
|
||||
iRet = Tcl_GetInt(interp,argv[4],&iChannel);
|
||||
if(iRet == TCL_ERROR)
|
||||
{
|
||||
Tcl_AppendResult(interp,"Need integer value for channel",
|
||||
(char *)NULL);
|
||||
return iRet;
|
||||
}
|
||||
|
||||
iMotor = 1;
|
||||
|
||||
|
||||
/* make a new pointer, initialise EL734st */
|
||||
pData = malloc(sizeof(void *));
|
||||
if(pData ==NULL)
|
||||
{
|
||||
Tcl_AppendResult(interp,"No memory in SerialSinq",NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/* check for optional force flag */
|
||||
if(argc > 5)
|
||||
{
|
||||
iRet = SerialForceOpen(pData, argv[2],iPort,iChannel);
|
||||
}
|
||||
|
||||
/* open the motor, finally */
|
||||
iRet = SerialOpen(pData, argv[2],iPort,iChannel);
|
||||
if(iRet == 1) /* success */
|
||||
{
|
||||
/* handle TCL, create new command: the serial line */
|
||||
Tcl_CreateCommand(interp,strdup(argv[1]),SurielSend,
|
||||
*pData,SerialMurder);
|
||||
strcpy(pBueffel,argv[1]);
|
||||
Tcl_AppendResult(interp,strdup(argv[1]),(char *)NULL);
|
||||
if(pServ->pReader != NULL)
|
||||
{
|
||||
NetReadRegisterUserSocket(pServ->pReader,
|
||||
SerialGetSocket(pData));
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
SerialError(iRet,pBueffel,79);
|
||||
Tcl_AppendResult(interp,pBueffel,(char *) NULL);
|
||||
SerialClose(pData);
|
||||
free(pData);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
}
|
||||
/*--------------------------------------------------------------------------
|
||||
Now, this interprets some commands:
|
||||
-tmo val
|
||||
will set a timeout value for the connection. Everything
|
||||
else will be concatenated and sent to the device.
|
||||
-sendterm text
|
||||
defines the terminator which will be appended automatically
|
||||
to each command.
|
||||
-replyterm text
|
||||
sets the expected reply terminator from the Macintosh
|
||||
Serial Port server.
|
||||
|
||||
----------------------------------------------------------------------------*/
|
||||
EXTERN int SurielSend(ClientData clientData, Tcl_Interp *interp,
|
||||
int argc, char *argv[])
|
||||
{
|
||||
char pBueffel[256];
|
||||
char pAnswer[256];
|
||||
char *pErr = NULL;
|
||||
int iRet, iMSR;
|
||||
int i;
|
||||
void *pData;
|
||||
|
||||
pData = clientData;
|
||||
|
||||
if(argc >= 2)
|
||||
{
|
||||
if(strcmp(argv[1],"-tmo") == 0)
|
||||
{
|
||||
if(argc >= 3)
|
||||
{
|
||||
iRet = Tcl_GetInt(interp,argv[2],&iMSR);
|
||||
if(iRet != TCL_OK)
|
||||
{
|
||||
sprintf(pBueffel,"%s is not a valid number",argv[2]);
|
||||
Tcl_AppendResult(interp,pBueffel,NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
SerialConfig(&(pData),iMSR);
|
||||
return TCL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
Tcl_AppendResult(interp, "Expected parameter after -tmo",NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
}
|
||||
else if(strcmp(argv[1],"-sendterm") == 0)
|
||||
{
|
||||
if(argc < 3)
|
||||
{
|
||||
Tcl_AppendResult(interp, "Expected parameter after -tmo",NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
iRet = SerialSendTerm(&(pData),argv[2]);
|
||||
if(iRet != 1)
|
||||
{
|
||||
Tcl_AppendResult(interp,"To many characters for terminator",NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
else if(strcmp(argv[1],"-replyterm") == 0)
|
||||
{
|
||||
if(argc < 3)
|
||||
{
|
||||
Tcl_AppendResult(interp, "Expected parameter after -tmo",NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
iRet = SerialATerm(&(pData),argv[2]);
|
||||
if(!iRet)
|
||||
{
|
||||
Tcl_AppendResult(interp,"To many characters for terminator",NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
else if(strcmp(argv[1],"-put") == 0)
|
||||
{
|
||||
NetReadResetUser(pServ->pReader,SerialGetSocket(&(pData)));
|
||||
if(argc > 2)
|
||||
{
|
||||
strcpy(pBueffel,argv[2]);
|
||||
}
|
||||
for(i = 3; i < argc; i++)
|
||||
{
|
||||
strcat(pBueffel," ");
|
||||
strcat(pBueffel,argv[i]);
|
||||
}
|
||||
iRet = SerialSend(&(pData),pBueffel);
|
||||
if(iRet != 1)
|
||||
{
|
||||
Tcl_AppendResult(interp,pAnswer,NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
else if(strcmp(argv[1],"-readable") == 0)
|
||||
{
|
||||
iRet = NetReadReadable(pServ->pReader,SerialGetSocket(&(pData)));
|
||||
if(iRet)
|
||||
{
|
||||
Tcl_AppendResult(interp,"1",NULL);
|
||||
return TCL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
Tcl_AppendResult(interp,"0",NULL);
|
||||
return TCL_OK;
|
||||
}
|
||||
}
|
||||
else if(strcmp(argv[1],"-get") == 0)
|
||||
{
|
||||
if(NetReadReadable(pServ->pReader,SerialGetSocket(&(pData))))
|
||||
{
|
||||
iRet = SerialReceive(&(pData),pAnswer, 255);
|
||||
Tcl_AppendResult(interp,pAnswer,NULL);
|
||||
if(iRet == 1)
|
||||
{
|
||||
return TCL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return TCL_ERROR;
|
||||
}
|
||||
}
|
||||
Tcl_AppendResult(interp,"Not Readable",NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(argc >= 2)
|
||||
{
|
||||
strcpy(pBueffel,argv[1]);
|
||||
}
|
||||
for(i = 2; i < argc; i++)
|
||||
{
|
||||
strcat(pBueffel," ");
|
||||
strcat(pBueffel,argv[i]);
|
||||
}
|
||||
i = strlen(pBueffel);
|
||||
iRet = SerialWriteRead(&(pData),pBueffel,pAnswer,254);
|
||||
if(iRet != 1)
|
||||
{
|
||||
Tcl_AppendResult(interp,pAnswer,NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
Tcl_AppendResult(interp,pAnswer,NULL);
|
||||
return TCL_OK;
|
||||
}
|
Reference in New Issue
Block a user