- Added missing files to split directories

This commit is contained in:
cvs
2003-06-20 12:24:48 +00:00
parent 064ec37e9a
commit 30ade6a8c6
14 changed files with 3200 additions and 0 deletions

586
ecbcounter.c Normal file
View 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
View File

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

693
el737driv.c Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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;
}