Files
sicspsi/slsmagnet.c
cvs e3ee358dbc - Fixed a bug in conman.c which could cause a core dump when terminating
a connection during an active run.
- Added an additional output mode for the connection in order to
  support the batch run editor.
- Made clientput send everything with eWarning mode in order to support
  the batch run editor.
- Added a better NetReadTillTerm
- Fixed a problem in synchronize.c
- Fixed an issue with reading empty line on normal connection sockets.
- Added a psi scan mode to mesure.c for TRICS
- Made motor print warnings when trying to reposition.
- Fixed abug in hkl.c which cause wrong signs.
2004-07-21 12:03:08 +00:00

396 lines
9.5 KiB
C

/*--------------------------------------------------------------------------
S L S M A G N E T
This file contains the driver for the PSI-DSP magnet controller as
aquired from SLS.
This device runs a binary protocoll on its RS232 interface. And the lowest
speed this device understands is 115KB! This is why this driver accesses
the terminal server port directly through the network without David's
SerPortServer program in between. Also make sure that the port runs at
115KB when using this device.
Mark Koennecke, October 2001
Copyright: see copyright.h
----------------------------------------------------------------------------*/
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include <assert.h>
#include <unistd.h>
#include <fortify.h>
#include <conman.h>
#include <servlog.h>
#include <fortify.h>
typedef struct __EVDriver *pEVDriver;
#include <evdriver.i>
#include <network.h>
#include <rs232controller.h>
/*
error codes
*/
#define BADECHO -5100
/*
#define NOTCONNECTED -5200
#define TIMEOUT -5300
*/
/*
when waiting for results, the code loops at max MAXLOOP times
before doing a timeout. 100 corresponds to one second
*/
#define MAXLOOP 100
/*
packet header codes
*/
#define DSPWRITE 0x80
#define DSPREAD 0x0
/*-----------------------------------------------------------------------*/
typedef struct {
mkChannel *pSock;
char *pHost;
int iPort;
int iError;
} SLSDriv, *pSLSDriv;
/*-------------------------------------------------------------------------
Code for data conversion from Lukas Tanner. The ULONG is system dependent,
it MUST describe a 32 bit value.
-------------------------------------------------------------------------*/
#define ULONG int
/***********************************************************************/
static ULONG double2DSPfloat( double input )
/***********************************************************************/
/* Konvertiert eine normale double Variable in ein 32bit DSP Float Format. */
{
ULONG output;
double mantissa;
int exponent;
if (input == 0) {
output = 0;
} else {
mantissa = 2 * (frexp(fabs(input), &exponent));
mantissa = ldexp(mantissa, 23);
exponent =exponent - 1 + 127;
if (exponent < 0) {
exponent = 0;
} else if (exponent > 0xFE) {
exponent = 0xFE;
}
exponent = exponent << 23;
output = ((ULONG) mantissa) & 0x7FFFFF;
output = output | ((ULONG) (exponent));
if (input < 0) {
output = output | 0x80000000;
}
}
return output;
}
/***********************************************************************/
static double DSPfloat2double( ULONG input )
/***********************************************************************/
/* Konvertiert eine Variable inder ein 32bit DSP Float Wert abgelegt ist,
in ein normales double Format
32bit IEEE Float => SEEEEEEEEMMMMMMMMMMMMMMMMMMMMMMM; S = Sign Bit
E = Exponent
M = Mantissa (23)*/
{
double output;
if ((input & 0x7FFFFF) == 0 && ((input >> 23) & 0xFF) == 0) {
output = 0;
} else {
output = ldexp(input & 0x7FFFFF,-23) + 1;
output = output * pow(-1, ((input >>31) & 1));
output = output * ldexp(1, (((input >>23) & 0xFF) - 127));
}
return output;
}
/*-------------------------------------------------------------------------*/
static int communicateSLS(mkChannel *pSock, char msg[6], char reply[6])
{
long lVal = 0;
int iRet, i;
if(!pSock)
return NOTCONNECTED;
iRet = NETWrite(pSock,msg,6);
if(iRet < 0)
{
return iRet;
}
for(i = 0; i < MAXLOOP; i++)
{
iRet = NETAvailable(pSock,10);
if(iRet < 0)
{
return iRet;
}
else if(iRet == 1)
{
lVal += NETRead(pSock,reply+lVal,6-lVal,-10);
if(lVal >= 6)
{
return (int)lVal;
}
else
{
continue;
}
}
}
return TIMEOUT;
}
/*---------------------------------------------------------------------------*/
static int GetSLSPos(pEVDriver self, float *fPos)
{
pSLSDriv pMe = NULL;
int iRet, ival;
double dval;
char msg[6], reply[6];
long lVal;
assert(self);
pMe = (pSLSDriv)self->pPrivate;
assert(pMe);
msg[0] = DSPREAD; /* read request */
msg[1] = 0x92; /* address of mag current */
iRet = communicateSLS(pMe->pSock,msg,reply);
if(iRet < 0)
{
pMe->iError = iRet;
return iRet;
}
memcpy(&ival,reply+2,4);
dval = DSPfloat2double(ival);
*fPos = (float)dval;
pMe->iError = 0;
return 1;
}
/*----------------------------------------------------------------------------*/
static int SLSRun(pEVDriver self, float fVal)
{
pSLSDriv pMe = NULL;
int iRet, ival,i;
char msg[6], reply[6];
assert(self);
pMe = (pSLSDriv )self->pPrivate;
assert(pMe);
msg[0] = DSPWRITE;
msg[1] = 0x90;
ival = double2DSPfloat((double)fVal);
memcpy(msg+2, &ival,4);
iRet = communicateSLS(pMe->pSock,msg,reply);
if(iRet <= 0)
{
pMe->iError = iRet;
return iRet;
}
for(i = 1; i < 6; i++)
{
if(msg[i] != reply[i])
{
pMe->iError = BADECHO;
return BADECHO;
}
}
return 1;
}
/*--------------------------------------------------------------------------*/
static int SLSError(pEVDriver self, int *iCode, char *error, int iErrLen)
{
pSLSDriv pMe = NULL;
char *pPtr = NULL;
int i1, i2;
char pBueffel[132];
assert(self);
pMe = (pSLSDriv)self->pPrivate;
assert(pMe);
*iCode = pMe->iError;
switch(*iCode)
{
case BADECHO:
strncpy(error,"message sent and reply did not match", iErrLen);
break;
case NOTCONNECTED:
strncpy(error,"Not connected to device", iErrLen);
break;
case TIMEOUT:
strncpy(error,"Timeout waiting for response", iErrLen);
break;
default:
getRS232Error(*iCode,error,iErrLen);
break;
}
return 1;
}
/*-------------------------------------------------------------------------*/
static int SLSSend(pEVDriver self, char *pCommand, char *pReply, int iLen)
{
strncpy(pReply,"PSI-DSP understands only binary, send disabled",iLen);
return 0;
}
/*--------------------------------------------------------------------------*/
static int SLSInit(pEVDriver self)
{
pSLSDriv pMe = NULL;
int iRet, ival, i;
char msg[6], reply[6];
assert(self);
pMe = (pSLSDriv )self->pPrivate;
assert(pMe);
pMe->pSock = NULL;
pMe->pSock = NETConnect(pMe->pHost,pMe->iPort);
if(!pMe->pSock)
{
return 0;
}
sleep(1);
/*
try to switch device on
*/
msg[0] = DSPWRITE;
msg[1] = 0x31;
ival = 1;
memcpy(msg+2, &ival,4);
iRet = communicateSLS(pMe->pSock,msg,reply);
if(iRet <= 0)
{
pMe->iError = iRet;
return iRet;
}
for(i = 1; i < 6; i++)
{
if(msg[i] != reply[i])
{
pMe->iError = BADECHO;
return BADECHO;
}
}
return 1;
}
/*--------------------------------------------------------------------------*/
static int SLSClose(pEVDriver self)
{
pSLSDriv pMe = NULL;
int iRet;
assert(self);
pMe = (pSLSDriv )self->pPrivate;
assert(pMe);
NETClosePort(pMe->pSock);
pMe->pSock = NULL;
return 1;
}
/*---------------------------------------------------------------------------*/
static int SLSFix(pEVDriver self, int iError)
{
pSLSDriv pMe = NULL;
int iRet;
assert(self);
pMe = (pSLSDriv )self->pPrivate;
assert(pMe);
switch(iError)
{
case BADECHO:
case TIMEOUT:
return DEVREDO;
default:
SLSClose(self);
iRet = SLSInit(self);
if(iRet)
{
return DEVREDO;
}
else
{
return DEVFAULT;
}
break;
}
}
/*--------------------------------------------------------------------------*/
static int SLSHalt(pEVDriver *self)
{
assert(self);
return 1;
}
/*------------------------------------------------------------------------*/
void KillSLS(void *pData)
{
pSLSDriv pMe = NULL;
pMe = (pSLSDriv)pData;
assert(pMe);
if(pMe->pHost)
{
free(pMe->pHost);
}
free(pMe);
}
/*------------------------------------------------------------------------*/
pEVDriver CreateSLSDriv(int argc, char *argv[])
{
pEVDriver pNew = NULL;
pSLSDriv pSim = NULL;
/* check for arguments */
if(argc < 2)
{
return NULL;
}
pNew = CreateEVDriver(argc,argv);
pSim = (pSLSDriv)malloc(sizeof(SLSDriv));
memset(pSim,0,sizeof(SLSDriv));
if(!pNew || !pSim)
{
return NULL;
}
pNew->pPrivate = pSim;
pNew->KillPrivate = KillSLS;
pSim->pHost = strdup(argv[0]);
pSim->iPort = atoi(argv[1]);
/* initialise function pointers */
pNew->SetValue = SLSRun;
pNew->GetValue = GetSLSPos;
pNew->Send = SLSSend;
pNew->GetError = SLSError;
pNew->TryFixIt = SLSFix;
pNew->Init = SLSInit;
pNew->Close = SLSClose;
return pNew;
}