Files
sicspsi/hardsup/dillutil.c
2009-02-13 09:01:24 +00:00

442 lines
9.2 KiB
C
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*--------------------------------------------------------------------------
D I L U T I L
A few utility functions for dealing with a Dillution emperature controller
CC0-510/AVSI
within the SINQ setup: host -- TCP/IP -- MAC --- RS-232.
Mark Koennecke, October 1997
Copyright: see copyrigh.h
---------------------------------------------------------------------------- */
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include "serialsinq.h"
#include "dillutil.h"
#ifdef FORTIFY
#include "fortify.h"
#endif
/*
#define debug 1
*/
/*-------------------------------------------------------------------------*/
int DILLU_Open(pDILLU * pData, char *pHost, int iPort, int iChannel,
int iMode, char *pTransFile)
{
int iRet;
char pCommand[80];
char pReply[132];
pDILLU self = NULL;
pSTable pTable = NULL;
FILE *fd = NULL;
/* check translation file first */
fd = fopen(pTransFile, "r");
if (!fd) {
return DILLU__FILENOTFOUND;
}
fgets(pReply, 131, fd);
if (strstr(pReply, "DILLUTION") == NULL) {
fclose(fd);
return DILLU__NODILLFILE;
}
pTable = CreateTable(fd);
fclose(fd);
if (!pTable) {
return DILLU__ERRORTABLE;
}
/* allocate a new data structure */
self = (pDILLU) malloc(sizeof(DILLU));
if (self == NULL) {
return DILLU__BADMALLOC;
}
*pData = self;
self->pTranstable = pTable;
iRet = SerialOpen(&self->pData, pHost, iPort, iChannel);
if (iRet != 1) {
return iRet;
}
/* set an lengthy timeout for the configuration in order to
prevent problems.
*/
iRet = SerialConfig(&self->pData, 100);
if (iRet != 1) {
return iRet;
}
self->iReadOnly = iMode;
if (!self->iReadOnly) {
/* switch to remote operation */
/* iRet = SerialWriteRead(&self->pData,"C1\r\n",pReply,131);
if(iRet != 1)
{
return iRet;
}
*/
}
return 1;
}
/* --------------------------------------------------------------------------*/
void DILLU_Close(pDILLU * pData)
{
char pReply[132];
int iRet;
pDILLU self;
self = *pData;
if (!self)
return;
/* switch to local operation */
iRet = SerialWriteRead(&self->pData, "C0\r\n", pReply, 131);
/* ignore errors on this one, the thing may be down */
/* close connection */
SerialClose(&self->pData);
/* free memory */
free(self);
*pData = NULL;
}
/* --------------------------------------------------------------------------*/
int DILLU_Config(pDILLU * pData, int iTmo)
{
int iRet;
char pReply[132];
char pCommand[10];
pDILLU self;
self = *pData;
/* first timeout */
if (iTmo > 0) {
iRet = SerialConfig(&self->pData, iTmo);
if (iRet < 0) {
return iRet;
}
}
return 1;
}
/* --------------------------------------------------------------------------*/
int DILLU_Send(pDILLU * pData, char *pCommand, char *pReply, int iLen)
{
pDILLU self;
self = *pData;
/* make sure, that there is a \r at the end of the command */
if (strchr(pCommand, (int) '\r') == NULL) {
strcat(pCommand, "\r\n");
}
return SerialWriteRead(&self->pData, pCommand, pReply, iLen);
}
/* --------------------------------------------------------------------------*/
int DILLU_Read(pDILLU * pData, float *fVal)
{
char pCommand[10], pReply[132];
int iRet;
float fRead = -9999.;
float fOhm;
pDILLU self;
self = *pData;
/* send D command */
sprintf(pCommand, "D\r\n");
iRet = SerialWriteRead(&self->pData, pCommand, pReply, 131);
if (iRet != 1) {
return iRet;
}
/* read ohms */
iRet = sscanf(pReply, "%f", &fOhm);
if (iRet != 1) {
return DILLU__BADREAD;
}
if (fOhm > 9999890.) {
return DILLU__SILLYANSWER;
}
/* convert to K */
iRet = InterpolateVal2(self->pTranstable, fOhm, &fRead);
*fVal = fRead;
return 1;
}
/*-------------------------------------------------------------------------*/
int DILLU_Set(pDILLU * pData, float fVal)
{
char pCommand[50], pReply[132];
int iRet, i, iRange, iExec;
const float fPrecision = 0.0001;
float fSet, fRead, fOhms, tmax, fTemp;
pDILLU self;
self = *pData;
if (self->iReadOnly) {
return DILLU__READONLY;
}
/* send D command to read current value */
sprintf(pCommand, "D\r\n");
iRet = SerialWriteRead(&self->pData, pCommand, pReply, 131);
if (iRet != 1) {
return iRet;
}
/* read ohms */
iRet = sscanf(pReply, "%f", &fRead);
if (iRet != 1) {
return DILLU__BADREAD;
}
if (fRead > 9999890.) {
return DILLU__SILLYANSWER;
}
/* convert new set value to ohms */
iRet = InterpolateVal1(self->pTranstable, fVal, &fOhms);
if (!iRet) {
return DILLU__OUTOFRANGE;
}
/* set to remote operation */
#ifdef debug
printf("C1\n");
#endif
iRet = SerialWriteRead(&self->pData, "C1\r\n", pReply, 131);
if (iRet != 1) {
return iRet;
}
/* set heater power */
strcpy(pCommand, "G3\r");
if (fOhms > 1125) {
strcpy(pCommand, "G2\r");
}
if (fOhms > 4000)
strcpy(pCommand, "G1\r");
#ifdef debug
printf("A9\n");
#endif
iRet = SerialWriteRead(&self->pData, "A9\r", pReply, 131);
if (iRet != 1) {
return iRet;
}
#ifdef debug
printf("%s\n", pCommand);
#endif
iRet = SerialWriteRead(&self->pData, pCommand, pReply, 131);
if (iRet != 1) {
return iRet;
}
/* Integrator time constant */
strcpy(pCommand, "G2\r");
if (fOhms > 200)
strcpy(pCommand, "G1\r");
if (fOhms > 2000)
strcpy(pCommand, "G0\r");
strcpy(pCommand, "G7\r");
if (fOhms > 400.) {
strcpy(pCommand, "G6\r");
}
#ifdef debug
printf("A4\n");
#endif
iRet = SerialWriteRead(&self->pData, "A4\r", pReply, 131);
if (iRet != 1) {
return iRet;
}
#ifdef debug
printf("%s\n", pCommand);
#endif
iRet = SerialWriteRead(&self->pData, pCommand, pReply, 131);
if (iRet != 1) {
return iRet;
}
/* derivator time constant */
if (fOhms > 1000.) {
strcpy(pCommand, "G1\r");
} else {
strcpy(pCommand, "G2\r");
}
#ifdef debug
printf("A5\n");
#endif
iRet = SerialWriteRead(&self->pData, "A5\r", pReply, 131);
if (iRet != 1) {
return iRet;
}
#ifdef debug
printf("%s\n", pCommand);
iRet = 1;
#endif
iRet = SerialWriteRead(&self->pData, pCommand, pReply, 131);
if (iRet != 1) {
return iRet;
}
/* proportional gain */
if (fOhms > 500.) {
strcpy(pCommand, "G3\r");
}
if (fOhms > 1000) {
strcpy(pCommand, "G2\r");
}
if (fOhms > 2000) {
strcpy(pCommand, "G1\r");
}
#ifdef debug
printf("A6\n");
#endif
iRet = SerialWriteRead(&self->pData, "A6\r", pReply, 131);
if (iRet != 1) {
return iRet;
}
#ifdef debug
printf("%s\n", pCommand);
#endif
iRet = SerialWriteRead(&self->pData, pCommand, pReply, 131);
if (iRet != 1) {
return iRet;
}
/* range calculation a la Elsenhans */
iRange = 1;
fTemp = fOhms * 10000.;
if ((fRead > 1.9) || (fOhms > 1.9)) {
iRange = 2;
fTemp = fOhms * 1000.;
}
if ((fRead > 19) || (fOhms > 19)) {
iRange = 3;
fTemp = fOhms * 100.;
}
if ((fRead > 190) || (fOhms > 190)) {
iRange = 4;
fTemp = fOhms * 10.;
}
if ((fRead > 750) || (fOhms > 750)) {
iRange = 5;
fTemp = fOhms;
}
if ((fRead > 19000) || (fOhms > 19000)) {
iRange = 6;
fTemp = fOhms / 10.;
}
if ((fRead > 190000) || (fOhms > 190000)) {
iRange = 7;
fTemp = fOhms / 100.;
}
sprintf(pCommand, "R%1.1d\r", iRange);
#ifdef debug
printf("%s\n", pCommand);
#endif
iRet = SerialWriteRead(&self->pData, pCommand, pReply, 131);
if (iRet != 1) {
return iRet;
}
/* finally set temperature */
#ifdef debug
printf("Set Val befor hex: %d\n", (int) fTemp);
#endif
sprintf(pCommand, "G%4.4X\r", (int) fTemp);
#ifdef debug
printf("A3\n");
#endif
iRet = SerialWriteRead(&self->pData, "A3\r", pReply, 131);
if (iRet != 1) {
return iRet;
}
#ifdef debug
printf("%s\n", pCommand);
#endif
iRet = SerialWriteRead(&self->pData, pCommand, pReply, 131);
if (iRet != 1) {
return iRet;
}
/* unset remote operation, so that users may mess everything up
from the panel
*/
#ifdef debug
printf("C1\n");
#endif
iRet = SerialWriteRead(&self->pData, "C0\r\n", pReply, 131);
if (iRet != 1) {
return iRet;
}
return 1;
}
/*-------------------------------------------------------------------------*/
void DILLU_Error2Text(pDILLU * pData, int iCode, char *pError, int iLen)
{
char pBueffel[512];
pDILLU self;
self = *pData;
switch (iCode) {
case DILLU__FILENOTFOUND:
strncpy(pError, "Translation Table file not found", iLen);
return;
break;
case DILLU__NODILLFILE:
strncpy(pError, "Translation Table file is not DILLU", iLen);
return;
break;
case DILLU__ERRORTABLE:
strncpy(pError, "Translation Table could not be created", iLen);
return;
break;
case DILLU__BADREAD:
strncpy(pError, "Message corrupted", iLen);
return;
break;
case DILLU__SILLYANSWER:
strncpy(pError, "Message corrupted", iLen);
return;
break;
case DILLU__BADMALLOC:
strncpy(pError, "Out of memory in Open_DILLU", iLen);
return;
break;
case DILLU__READONLY:
strncpy(pError, "DILLU is read-only", iLen);
return;
break;
case DILLU__OUTOFRANGE:
strncpy(pError, "Requested value is out of range", iLen);
return;
break;
default:
SerialError(iCode, pError, iLen);
break;
}
}