From 30ade6a8c618048393e67e136b489e49136a5365 Mon Sep 17 00:00:00 2001 From: cvs Date: Fri, 20 Jun 2003 12:24:48 +0000 Subject: [PATCH] - Added missing files to split directories --- ecbcounter.c | 586 ++++++++++++++++++++++++++++++++++ ecbcounter.h | 17 + el737driv.c | 693 +++++++++++++++++++++++++++++++++++++++++ eurodriv.c | 395 +++++++++++++++++++++++ eurodriv.h | 23 ++ frame.c | 242 ++++++++++++++ frame.h | 22 ++ frame.w | 32 ++ hardsup/sinqhm.i | 54 ++++ make_gen | 25 ++ makefile_alpha | 16 + nxsans.c | 796 +++++++++++++++++++++++++++++++++++++++++++++++ nxsans.h | 17 + scontroller.c | 282 +++++++++++++++++ 14 files changed, 3200 insertions(+) create mode 100644 ecbcounter.c create mode 100644 ecbcounter.h create mode 100644 el737driv.c create mode 100644 eurodriv.c create mode 100644 eurodriv.h create mode 100644 frame.c create mode 100644 frame.h create mode 100644 frame.w create mode 100644 hardsup/sinqhm.i create mode 100644 make_gen create mode 100644 makefile_alpha create mode 100644 nxsans.c create mode 100644 nxsans.h create mode 100644 scontroller.c diff --git a/ecbcounter.c b/ecbcounter.c new file mode 100644 index 0000000..6158b8a --- /dev/null +++ b/ecbcounter.c @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include "ecb.h" +#include + +/*------------------ 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; +} diff --git a/ecbcounter.h b/ecbcounter.h new file mode 100644 index 0000000..eb12145 --- /dev/null +++ b/ecbcounter.h @@ -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 diff --git a/el737driv.c b/el737driv.c new file mode 100644 index 0000000..b36f99a --- /dev/null +++ b/el737driv.c @@ -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 +#include +#include +#include +#include +#include +#include +#include +#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); + } + } diff --git a/eurodriv.c b/eurodriv.c new file mode 100644 index 0000000..191ebca --- /dev/null +++ b/eurodriv.c @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include + + typedef struct __EVDriver *pEVDriver; + +#include +#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; + } + + + diff --git a/eurodriv.h b/eurodriv.h new file mode 100644 index 0000000..132856f --- /dev/null +++ b/eurodriv.h @@ -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 diff --git a/frame.c b/frame.c new file mode 100644 index 0000000..20ef729 --- /dev/null +++ b/frame.c @@ -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 +#include +#include +#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); +} + diff --git a/frame.h b/frame.h new file mode 100644 index 0000000..af5a1ef --- /dev/null +++ b/frame.h @@ -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 diff --git a/frame.w b/frame.w new file mode 100644 index 0000000..c2bcfe2 --- /dev/null +++ b/frame.w @@ -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 +@} \ No newline at end of file diff --git a/hardsup/sinqhm.i b/hardsup/sinqhm.i new file mode 100644 index 0000000..785f1d7 --- /dev/null +++ b/hardsup/sinqhm.i @@ -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 + diff --git a/make_gen b/make_gen new file mode 100644 index 0000000..ff27176 --- /dev/null +++ b/make_gen @@ -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 \ No newline at end of file diff --git a/makefile_alpha b/makefile_alpha new file mode 100644 index 0000000..b54e224 --- /dev/null +++ b/makefile_alpha @@ -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 diff --git a/nxsans.c b/nxsans.c new file mode 100644 index 0000000..3cb67a4 --- /dev/null +++ b/nxsans.c @@ -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 +#include +#include +#include +#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; + } diff --git a/nxsans.h b/nxsans.h new file mode 100644 index 0000000..56ef101 --- /dev/null +++ b/nxsans.h @@ -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 \ No newline at end of file diff --git a/scontroller.c b/scontroller.c new file mode 100644 index 0000000..141a59a --- /dev/null +++ b/scontroller.c @@ -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 */ +#include +#include +#include +#include +#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; +}