diff --git a/A1931.c b/A1931.c deleted file mode 100644 index c174359..0000000 --- a/A1931.c +++ /dev/null @@ -1,367 +0,0 @@ -/*------------------------------------------------------------------------- - This is the implementation file for a driver for the Risoe A1931a - temperature controller. This driver controls the device through a GPIB - interface. - - copyright: see file COPYRIGHT - - Mark Koennecke, February 2003 - -------------------------------------------------------------------------*/ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "A1931.h" - -/*========================== private data structure ====================*/ -typedef struct { - int sensor; /* the control sensor */ - pGPIB gpib; /* the GPIB interface to use in order to talk to the thing */ - int gpibAddress; /* address on bus */ - int devID; /* deviceID of the controller on the GPIB */ - char errorBuffer[132]; /* a buffer for error messages from the thing */ - char commandLine[132]; /* buffer to keep the offending command line */ - int errorCode; /* error indicator */ -} A1931, *pA1931; -/*============================ defines ================================*/ -#define COMMERROR -300 -#define A1931ERROR -301 -#define FILEERROR -302 -/*====================================================================*/ -static char *A1931comm(pEVDriver pData, char *command) -{ - char buffer[256], *pPtr; - int status; - pA1931 self = NULL; - Tcl_DString reply; - - self = (pA1931) pData->pPrivate; - assert(self); - - /* - send - */ - strlcpy(buffer, command, 250); - strcat(buffer, "\n"); - status = GPIBsend(self->gpib, self->devID, buffer, (int) strlen(buffer)); - if (status < 0) { - self->errorCode = COMMERROR; - GPIBerrorDescription(self->gpib, status, self->errorBuffer, 131); - return NULL; - } - - /* - read until > is found - */ - Tcl_DStringInit(&reply); - while (1) { - pPtr = GPIBreadTillTerm(self->gpib, self->devID, 10); - if (strstr(pPtr, "GPIB READ ERROR") != NULL) { - free(pPtr); - self->errorCode = COMMERROR; - Tcl_DStringFree(&reply); - return NULL; - } else { - Tcl_DStringAppend(&reply, pPtr, -1); - if (strchr(pPtr, '>') != NULL) { - /* - finished - */ - free(pPtr); - break; - } - free(pPtr); - } - } - pPtr = NULL; - pPtr = strdup(Tcl_DStringValue(&reply)); - Tcl_DStringFree(&reply); - if (pPtr[0] == '#') { - /* - error - */ - self->errorCode = A1931ERROR; - strlcpy(self->errorBuffer, pPtr, 131); - free(pPtr); - return NULL; - } - return pPtr; -} - -/*--------------------------------------------------------------------*/ -static int A1931command(pEVDriver pData, char *command, char *replyBuffer, - int replyBufferLen) -{ - pA1931 self = NULL; - char *pReply = NULL; - - self = (pA1931) pData->pPrivate; - assert(self); - - pReply = A1931comm(pData, command); - if (pReply != NULL) { - strlcpy(replyBuffer, pReply, replyBufferLen); - free(pReply); - return 1; - } else { - strlcpy(replyBuffer, self->errorBuffer, replyBufferLen); - return 0; - } -} - -/*====================================================================*/ -static int A1931Init(pEVDriver pData) -{ - pA1931 self = NULL; - - self = (pA1931) pData->pPrivate; - assert(self); - - self->devID = GPIBattach(self->gpib, 0, self->gpibAddress, 0, 13, 0, 0); - if (self->devID < 0) { - return 0; - } - return 1; -} - -/*====================================================================*/ -static int A1931Close(pEVDriver pData) -{ - pA1931 self = NULL; - - self = (pA1931) pData->pPrivate; - assert(self); - - GPIBdetach(self->gpib, self->devID); - self->devID = 0; - return 1; -} - -/*===================================================================*/ -static int A1931Get(pEVDriver pData, float *fPos) -{ - pA1931 self = NULL; - char buffer[132], command[50]; - int status; - - self = (pA1931) pData->pPrivate; - assert(self); - - sprintf(command, "?TEMP%1.1d", self->sensor); - status = A1931command(pData, command, buffer, 131); - if (!status) { - return 0; - } - sscanf(buffer, "%f", fPos); - return 1; -} - -/*=====================================================================*/ -static int A1931Set(pEVDriver pData, float fNew) -{ - pA1931 self = NULL; - char buffer[132], command[50]; - int status; - - self = (pA1931) pData->pPrivate; - assert(self); - - sprintf(command, "SET%1.1d=%f", self->sensor, fNew); - status = A1931command(pData, command, buffer, 131); - if (!status) { - return 0; - } - return 1; -} - -/*====================================================================*/ -static int A1931error(pEVDriver pData, int *iCode, char *errBuff, - int bufLen) -{ - pA1931 self = NULL; - char pError[256]; - - self = (pA1931) pData->pPrivate; - assert(self); - - *iCode = self->errorCode; - sprintf(pError, "ERROR: %s", self->errorBuffer); - strlcpy(errBuff, pError, bufLen); - return 1; -} - -/*====================================================================*/ -static int A1931fix(pEVDriver pData, int iCode) -{ - pA1931 self = NULL; - char pError[256]; - - self = (pA1931) pData->pPrivate; - assert(self); - - if (iCode == COMMERROR) { - GPIBclear(self->gpib, self->devID); - return DEVREDO; - } - return DEVFAULT; -} - -/*=====================================================================*/ -pEVDriver CreateA1931Driver(int argc, char *argv[]) -{ - pEVDriver self = NULL; - pA1931 priv = NULL; - - if (argc < 2) { - return NULL; - } - - /* - allocate space - */ - self = CreateEVDriver(argc, argv); - priv = (pA1931) malloc(sizeof(A1931)); - if (self == NULL || priv == NULL) { - return NULL; - } - memset(priv, 0, sizeof(A1931)); - self->pPrivate = priv; - self->KillPrivate = free; - - /* - initialize - */ - priv->gpib = (pGPIB) FindCommandData(pServ->pSics, argv[0], "GPIB"); - if (!priv->gpib) { - DeleteEVDriver(self); - return NULL; - } - priv->sensor = 1; - priv->gpibAddress = atoi(argv[1]); - - /* - initialize function pointers - */ - self->Send = A1931command; - self->Init = A1931Init; - self->Close = A1931Close; - self->GetValue = A1931Get; - self->SetValue = A1931Set; - self->GetError = A1931error; - self->TryFixIt = A1931fix; - - return self; -} - -/*=======================================================================*/ -static int downloadFile(pA1931 self, FILE * fd) -{ - char buffer[132], *pPtr; - int status; - - while (1) { - if (fgets(buffer, 130, fd) == NULL) { - self->errorCode = FILEERROR; - strcpy(self->errorBuffer, "Failed to read from file"); - return 0; - } - if (strstr(buffer, "$END") != NULL) { - break; - } - status = - GPIBsend(self->gpib, self->devID, buffer, (int) strlen(buffer)); - if (status < 0) { - self->errorCode = COMMERROR; - GPIBerrorDescription(self->gpib, status, self->errorBuffer, 131); - return 0; - } - pPtr = GPIBreadTillTerm(self->gpib, self->devID, 10); - if (pPtr[0] == '#') { - self->errorCode = A1931ERROR; - strlcpy(self->errorBuffer, pPtr, 131); - strlcpy(self->commandLine, buffer, 131); - free(pPtr); - return 0; - } - free(pPtr); - usleep(50); - } - return 1; -} - -/*=======================================================================*/ -int A1931Action(SConnection * pCon, SicsInterp * pSics, void *pData, - int argc, char *argv[]) -{ - pEVControl pEV = NULL; - pA1931 self = NULL; - char buffer[256]; - char error[132]; - FILE *fd = NULL; - int status, iCode; - - pEV = (pEVControl) pData; - assert(pEV); - self = (pA1931) pEV->pDriv->pPrivate; - assert(self); - - if (argc > 1) { - strtolower(argv[1]); - if (strcmp(argv[1], "sensor") == 0) { - if (argc > 2) { - /* set case */ - if (!SCMatchRights(pCon, usUser)) { - return 0; - } - self->sensor = atoi(argv[2]); - SCSendOK(pCon); - return 1; - } else { - /* get case */ - sprintf(buffer, "%s.sensor = %d", argv[0], self->sensor); - SCWrite(pCon, buffer, eValue); - return 1; - } - } else if (strcmp(argv[1], "list") == 0) { - sprintf(buffer, "%s.sensor = %d", argv[0], self->sensor); - SCWrite(pCon, buffer, eValue); - return EVControlWrapper(pCon, pSics, pData, argc, argv); - } else if (strcmp(argv[1], "file") == 0) { - if (!SCMatchRights(pCon, usUser)) { - return 0; - } - if (argc < 3) { - SCWrite(pCon, "ERROR: need filename argument", eError); - return 0; - } - fd = fopen(argv[2], "r"); - if (fd == NULL) { - sprintf(buffer, "ERROR: failed to open %s", argv[2]); - SCWrite(pCon, buffer, eError); - return 0; - } - status = downloadFile(self, fd); - fclose(fd); - if (!status) { - A1931error(pEV->pDriv, &iCode, error, 131); - sprintf(buffer, "%s while transfering file", error); - SCWrite(pCon, buffer, eError); - sprintf(buffer, "Offending command: %s", self->commandLine); - SCWrite(pCon, buffer, eError); - return 0; - } - SCSendOK(pCon); - return 1; - } - } - return EVControlWrapper(pCon, pSics, pData, argc, argv); -} diff --git a/A1931.h b/A1931.h deleted file mode 100644 index 3f24667..0000000 --- a/A1931.h +++ /dev/null @@ -1,20 +0,0 @@ -/*------------------------------------------------------------------------- - This is the header file for a driver for the Risoe A1931a temperature - controller. This driver controls the device through a GPIB interface. - - copyright: see file COPYRIGHT - - Mark Koennecke, February 2003 - -------------------------------------------------------------------------*/ -#ifndef A1931A -#define A19131A - -#include "sics.h" - -pEVDriver CreateA1931Driver(int argc, char *argv[]); - -int A1931Action(SConnection * pCon, SicsInterp * pSics, void *pData, - int argc, char *argv[]); - - -#endif diff --git a/audinelib.c b/audinelib.c deleted file mode 100644 index e7ec204..0000000 --- a/audinelib.c +++ /dev/null @@ -1,626 +0,0 @@ -/* - * -*- linux-c -*- - * Linux Kernel Module for the Audine Camera - * Copyright (C) 2001 Peter Kirchgessner - * http://www.kirchgessner.net, mailto:peter@kirchgessner.net - * - * Modified by F. Manenti for the use in the - * NOVA environment (nova.sourceforge.net) - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * The sample interface routines for the module have been taken from the - * Linux Kernel Module Programming Guide by Ori Pomerantz contained - * in the Linux Documentation Project. - * - */ - -#include "audineccd.h" -#include "audinelib.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define AUD_DEVICE_FILE "/dev/audine" - -#define ERRNORET(a) return (errno = a, -(a)) - -#define AUD_HANDLE_CHECK(a) \ - { if (!(a)) ERRNORET (EINVAL); if ((a)->fd < 0) ERRNORET (EBADF); } - -struct aud_handle_s { - int fd; - int single_read; -}; - - -AUD_HANDLE aud_open(void) -{ - AUD_HANDLE aud = (AUD_HANDLE) calloc(1, sizeof(struct aud_handle_s)); - - if (!aud) - return 0; - - aud->fd = open(AUD_DEVICE_FILE, O_RDWR); - if (aud->fd < 0) { - free(aud); - return 0; - } - - aud->single_read = 1; - - return aud; -} - - -void aud_close(AUD_HANDLE aud) -{ - if (aud) { - if (aud->fd >= 0) - close(aud->fd); - free(aud); - } -} - - -char *aud_version(const AUD_HANDLE aud) -{ - static struct ccd_capability Info; - char *version = ""; - int ret; - - if (aud) { - ret = ioctl(aud->fd, CCD_RD_VER, &Info); - if (ret == 0) - version = &(Info.name[0]); - } - return version; -} - - -int aud_clear(const AUD_HANDLE aud, int nclear) -{ - int ret = 0; - - if (nclear > 0) - ret = ioctl(aud->fd, CCD_CLR, &nclear); - return ret; -} - - -int aud_binning_set(const AUD_HANDLE aud, int vb, int hb) -{ - struct ccd_capability Info; - - AUD_HANDLE_CHECK(aud); - if ((vb < 1) || (vb > 4) || (hb < 1) || (hb > 4)) - ERRNORET(EINVAL); - - Info.width = vb; - Info.height = hb; - return ioctl(aud->fd, CCD_SET_BNN, &Info); -} - - -int aud_binning_get(const AUD_HANDLE aud, int *vb, int *hb) -{ - struct ccd_capability Info; - int ret; - - AUD_HANDLE_CHECK(aud); - - Info.width = 0; - Info.height = 0; - ret = ioctl(aud->fd, CCD_SET_BNN, &Info); - if (ret != 0) - return ret; - if (vb) - *vb = Info.width; - if (hb) - *hb = Info.height; - return 0; -} - - -int aud_geometry_set(const AUD_HANDLE aud, int x, int y, int width, - int height) -{ - struct ccd_capability Info; - - AUD_HANDLE_CHECK(aud); - - Info.minwidth = x; - Info.minheight = y; - Info.width = width; - Info.height = height; - return ioctl(aud->fd, CCD_SET_WND, &Info); -} - - -int aud_geometry_reset(const AUD_HANDLE aud) -{ - AUD_HANDLE_CHECK(aud); - - return ioctl(aud->fd, CCD_RST_WND); -} - - -int aud_geometry_get(const AUD_HANDLE aud, int *xorigin, int *yorigin, - int *winwidth, int *winheight, int *color) -{ - struct ccd_capability Info; - int ret; - - AUD_HANDLE_CHECK(aud); - - ret = ioctl(aud->fd, CCD_RD_GEOM, &Info); - if (ret != 0) - return ret; - - if (xorigin) - *xorigin = Info.minwidth; - if (yorigin) - *yorigin = Info.minheight; - if (winwidth) - *winwidth = Info.width; - if (winheight) - *winheight = Info.height; - if (color) - *color = Info.color; - - return 0; -} - - -int aud_port_set(const AUD_HANDLE aud, int base) -{ - AUD_HANDLE_CHECK(aud); - if (base <= 0) - return -EINVAL; - return ioctl(aud->fd, CCD_SET_PRT, &base); -} - - -int aud_port_get(const AUD_HANDLE aud, int *base) -{ - AUD_HANDLE_CHECK(aud); - if (!base) - return -1; - *base = 0; - return ioctl(aud->fd, CCD_SET_PRT, base); -} - - -static int aud_line_ctrl_set(const AUD_HANDLE aud, int cmd, int ctrl) -{ - AUD_HANDLE_CHECK(aud); - if ((ctrl != 1) && (ctrl != 2) && (ctrl != 4) && (ctrl != 8)) - ERRNORET(EINVAL); - return ioctl(aud->fd, cmd, &ctrl); -} - - -static int aud_line_set(const AUD_HANDLE aud, int cmd, int on_off) -{ - AUD_HANDLE_CHECK(aud); - if (on_off != 0) - on_off = 1; - return ioctl(aud->fd, cmd, &on_off); -} - - -int aud_amplifier_ctrl_set(const AUD_HANDLE aud, int ctrl) -{ - return aud_line_ctrl_set(aud, CCD_SET_AMP, ctrl); -} - - -int aud_amplifier_set(const AUD_HANDLE aud, int on_off) -{ - return aud_line_set(aud, CCD_SWTC_AMP, on_off); -} - - -int aud_shutter_ctrl_set(const AUD_HANDLE aud, int ctrl) -{ - return aud_line_ctrl_set(aud, CCD_SET_SHT, ctrl); -} - - -int aud_shutter_set(const AUD_HANDLE aud, int on_off) -{ - return aud_line_set(aud, CCD_SWTC_SHT, on_off); -} - - -int aud_aux0_ctrl_set(const AUD_HANDLE aud, int ctrl) -{ - return aud_line_ctrl_set(aud, CCD_SET_AX0, ctrl); -} - - -int aud_aux0_set(const AUD_HANDLE aud, int on_off) -{ - return aud_line_set(aud, CCD_SWTC_AX0, on_off); -} - - -int aud_aux1_ctrl_set(const AUD_HANDLE aud, int ctrl) -{ - return aud_line_ctrl_set(aud, CCD_SET_AX1, ctrl); -} - - -int aud_aux1_set(const AUD_HANDLE aud, int on_off) -{ - return aud_line_set(aud, CCD_SWTC_AX1, on_off); -} - - -int aud_ccd_info_get(const AUD_HANDLE aud, char **name, int *width, - int *height, int *color) -{ - static struct ccd_capability Info; - int ret; - - AUD_HANDLE_CHECK(aud); - if ((ret = ioctl(aud->fd, CCD_RD_CHIP, &Info)) != 0) - return ret; - - if (name) - *name = Info.name; - if (width) - *width = Info.width; - if (height) - *height = Info.height; - if (color) - *color = Info.color; - - return 0; -} - - -int aud_ccd_listentry_get(const AUD_HANDLE aud, int entry, char **name, - int *width, int *height, int *color) -{ - static struct ccd_capability Info; - int ret; - - AUD_HANDLE_CHECK(aud); - Info.color = entry; - if ((ret = ioctl(aud->fd, CCD_RD_CCDL, &Info)) != 0) - return ret; - - if (name) - *name = Info.name; - if (width) - *width = Info.width; - if (height) - *height = Info.height; - if (color) - *color = Info.color; - - return 0; -} - - -void aud_single_read_set(AUD_HANDLE aud, int single_read) -{ - if (aud) - aud->single_read = single_read; -} - - -int aud_image_read(const AUD_HANDLE aud, char **buf, int *bufsize, - int *width, int *height, int *color) -{ - int ret; - int nbytes, nread, len; - char *imgbuf; - - AUD_HANDLE_CHECK(aud); - if ((!buf) || (!bufsize)) - ERRNORET(EINVAL); - if ((!width) || (!height) || (!color)) - ERRNORET(EINVAL); - - if ((ret = aud_geometry_get(aud, 0, 0, width, height, color)) != 0) - return ret; - - /* We get 2 bytes per pixel */ - nbytes = *width * *height * 2; - - /* Do we have to free the user buffer ? */ - if ((*bufsize < nbytes) && (*buf)) { - free(*buf); - *buf = 0; - *bufsize = 0; - } - - /* If buffer not supplied, allocate buffer */ - if (!(*buf)) { - *buf = malloc(nbytes); - if (!*buf) - ERRNORET(ENOMEM); - *bufsize = nbytes; - } - - /* Start reading image */ - if ((ret = ioctl(aud->fd, CCD_RD_IMG)) != 0) - return ret; - - imgbuf = *buf; - while (nbytes > 0) { - if (aud->single_read) { - nread = nbytes; - } else { - nread = *width * 2; - if (nread > nbytes) - nread = nbytes; - } - len = read(aud->fd, imgbuf, nread); - if (len <= 0) - return -1; - nbytes -= len; - imgbuf += len; - } - return 0; -} - - -static void aud_ccdstruct_log(const char *fct, int ret, - const struct ccd_capability *info) -{ - printf("\nFunction %s returned %d\n", fct, ret); - if (ret != 0) - return; - printf("Name : %-32s\n", info->name); - printf - ("Width: %-6d Height: %-6d Minwidth: %-6d Minheight: %-6d Color: %d\n", - info->width, info->height, info->minwidth, info->minheight, - info->color); -} - - -void aud_ioctl_test(AUD_HANDLE aud) -{ - int ret; - struct ccd_capability info; - char *buf = 0, *name; - int bufsize = 0, width, height, color; - int j; - - if ((!aud) || (aud->fd < 0)) - return; - - /* Read driver version */ - ret = ioctl(aud->fd, CCD_RD_VER, &info); - aud_ccdstruct_log("CCD_RD_VER", ret, &info); - - /* Read chip information */ - ret = ioctl(aud->fd, CCD_RD_CHIP, &info); - aud_ccdstruct_log("CCD_RD_CHIP", ret, &info); - - /* Read geometry */ - ret = ioctl(aud->fd, CCD_RD_GEOM, &info); - aud_ccdstruct_log("CCD_RD_GEOM", ret, &info); - - /* Set Window */ - info.minwidth = 1; - info.minheight = 2; - info.width = 200; - info.height = 100; - ret = ioctl(aud->fd, CCD_SET_WND, &info); - printf("\nCalled CCD_SET_WND: (1,2) (200,100)\n"); - - /* Read geometry */ - ret = ioctl(aud->fd, CCD_RD_GEOM, &info); - aud_ccdstruct_log("CCD_RD_GEOM", ret, &info); - - /* Set binning */ - info.width = 2; - info.height = 3; - printf("\nSet binning %dx%d", info.width, info.height); - ret = ioctl(aud->fd, CCD_SET_BNN, &info); - aud_ccdstruct_log("CCD_SET_BNN", ret, &info); - - /* Read geometry */ - ret = ioctl(aud->fd, CCD_RD_GEOM, &info); - aud_ccdstruct_log("CCD_RD_GEOM", ret, &info); - - /* (Re-)Set binning */ - info.width = 1; - info.height = 1; - printf("\nSet binning %dx%d", info.width, info.height); - ret = ioctl(aud->fd, CCD_SET_BNN, &info); - aud_ccdstruct_log("CCD_SET_BNN", ret, &info); - - /* Read geometry */ - ret = ioctl(aud->fd, CCD_RD_GEOM, &info); - aud_ccdstruct_log("CCD_RD_GEOM", ret, &info); - - /* Clear two times */ - info.width = 2; - printf("\nStart clear %d times\n", info.width); - fflush(stdout); - ret = ioctl(aud->fd, CCD_CLR, &info.width); - printf("Clear finished.\n"); - - /* Reading */ - printf("Start reading image\n"); - ret = aud_image_read(aud, &buf, &bufsize, &width, &height, &color); - printf - ("Finished reading: ret=%d width=%d height=%d color=%d bufsize=%d\n", - ret, width, height, color, bufsize); - - /* Set binning */ - info.width = 2; - info.height = 3; - printf("\nSet binning %dx%d", info.width, info.height); - ret = ioctl(aud->fd, CCD_SET_BNN, &info); - aud_ccdstruct_log("CCD_SET_BNN", ret, &info); - - /* Reading */ - printf("Start reading small image\n"); - ret = aud_image_read(aud, &buf, &bufsize, &width, &height, &color); - printf - ("Finished reading: ret=%d width=%d height=%d color=%d bufsize=%d\n", - ret, width, height, color, bufsize); - - /* Reset window */ - ret = ioctl(aud->fd, CCD_RST_WND); - printf("\nReset window\n"); - - /* Reset binning */ - info.width = 1; - info.height = 1; - printf("\nSet binning %dx%d", info.width, info.height); - ret = ioctl(aud->fd, CCD_SET_BNN, &info); - aud_ccdstruct_log("CCD_SET_BNN", ret, &info); - - /* Read geometry */ - ret = ioctl(aud->fd, CCD_RD_GEOM, &info); - aud_ccdstruct_log("CCD_RD_GEOM", ret, &info); - - /* Reading */ - printf("Start reading large image\n"); - ret = aud_image_read(aud, &buf, &bufsize, &width, &height, &color); - printf - ("Finished reading: ret=%d width=%d height=%d color=%d bufsize=%d\n", - ret, width, height, color, bufsize); - - /* Read current port */ - ret = aud_port_get(aud, &j); - printf("\naud_port_get returned with %d. Port=0x%x\n", ret, j); - - printf("\nList of supported CCDs:\n"); - j = 0; - while (aud_ccd_listentry_get(aud, j, &name, &info.width, &info.height, - &info.color) == 0) { - printf("%d: %s, %dx%d, %d\n", j, name, info.width, info.height, - info.color); - j++; - } - - -} - - -#define FITS_WRITE_BOOLCARD(fp,key,value) \ -{char card[81]; \ - sprintf (card, "%-8.8s= %20s%50s", key, value ? "T" : "F", " "); \ - fwrite (card, 1, 80, fp); } - -#define FITS_WRITE_LONGCARD(fp,key,value) \ -{char card[81]; \ - sprintf (card, "%-8.8s= %20ld%50s", key, (long)value, " "); \ - fwrite (card, 1, 80, fp); } - -#define FITS_WRITE_DOUBLECARD(fp,key,value) \ -{char card[81], dbl[21], *istr; \ - sprintf (dbl, "%20f", (double)value); istr = strstr (dbl, "e"); \ - if (istr) *istr = 'E'; \ - sprintf (card, "%-8.8s= %20.20s%50s", key, dbl, " "); \ - fwrite (card, 1, 80, fp); } - -#define FITS_WRITE_STRINGCARD(fp,key,value) \ -{char card[81]; int k;\ - sprintf (card, "%-8.8s= \'%s", key, value); \ - for (k = strlen (card); k < 81; k++) card[k] = ' '; \ - k = strlen (key); if (k < 8) card[19] = '\''; else card[11+k] = '\''; \ - fwrite (card, 1, 80, fp); } - -#define FITS_WRITE_CARD(fp,value) \ -{char card[81]; \ - sprintf (card, "%-80.80s", value); \ - fwrite (card, 1, 80, fp); } - -int audine_fits_write(const char *fname, const char *img, - int width, int height) -{ - FILE *fp; - char value[50]; - unsigned short *us_img = (unsigned short *) img; - unsigned short *row; - int x, y, high, low; - long pos; - time_t timp; - - fp = fopen(fname, "w"); - if (fp) { - FITS_WRITE_BOOLCARD(fp, "SIMPLE", 1); - FITS_WRITE_LONGCARD(fp, "BITPIX", 16); - FITS_WRITE_LONGCARD(fp, "NAXIS", 2); - FITS_WRITE_LONGCARD(fp, "NAXIS1", width); - FITS_WRITE_LONGCARD(fp, "NAXIS2", height); - FITS_WRITE_DOUBLECARD(fp, "BZERO", 0.0); - FITS_WRITE_DOUBLECARD(fp, "BSCALE", 1.0); - FITS_WRITE_DOUBLECARD(fp, "DATAMIN", 0.0); - FITS_WRITE_DOUBLECARD(fp, "DATAMAX", 32767.0); - FITS_WRITE_CARD(fp, " "); - FITS_WRITE_CARD(fp, "HISTORY THIS FILE WAS GENERATED BY AUDINELIB"); - FITS_WRITE_CARD(fp, " "); - - timp = time(NULL); - strftime(value, sizeof(value), "%d/%m/%Y", gmtime(&timp)); - FITS_WRITE_STRINGCARD(fp, "DATE", value); - - FITS_WRITE_CARD(fp, "END"); - - /* Fill up primary HDU to multiple of 2880 bytes */ - fflush(fp); - pos = ftell(fp) % 2880; - if (pos != 0) { - pos = 2880 - pos; - while (pos-- > 0) - putc(' ', fp); - } - - /* FITS standard requires integer data to be most significant - byte first, */ - /* image origin bottom left. We want to create an astronomical - oriented image (top is bottom, left is right) */ - for (y = 0; y < height; y++) { - row = us_img + y * width; - for (x = width - 1; x >= 0; x--) { - high = (row[x] >> 8) & 0xff; - low = (row[x] & 0xff); - putc(high, fp); - putc(low, fp); - } - } - /* Fill up file to multiple of 2880 bytes */ - fflush(fp); - pos = ftell(fp) % 2880; - if (pos != 0) { - pos = 2880 - pos; - while (pos-- > 0) - putc(0, fp); - } - fclose(fp); - } else { - return -1; - } - return 0; -} diff --git a/audinelib.h b/audinelib.h deleted file mode 100644 index f5677fb..0000000 --- a/audinelib.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * -*- linux-c -*- - * Library Module for the Audine Camera - * Copyright (C) 2001 Peter Kirchgessner - * http://www.kirchgessner.net, mailto:peter@kirchgessner.net - * - * Modified by F. Manenti for the use in the - * NOVA environment (nova.sourceforge.net) - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * The sample interface routines for the module have been taken from the - * Linux Kernel Module Programming Guide by Ori Pomerantz contained - * in the Linux Documentation Project. - * - */ - -#ifndef _AUDINELIB_H_ -#define _AUDINELIB_H_ - -typedef struct aud_handle_s *AUD_HANDLE; - -AUD_HANDLE aud_open(void); - -void aud_close(AUD_HANDLE aud); - -char *aud_version(const AUD_HANDLE aud); - -int aud_image_read(const AUD_HANDLE aud, char **buf, int *bufsize, - int *width, int *height, int *color); -void aud_single_read_set(AUD_HANDLE aud, int single_read); - -int aud_ccd_info_get(const AUD_HANDLE aud, char **name, - int *width, int *height, int *color); - -int aud_ccd_listentry_get(const AUD_HANDLE aud, int entry, char **name, - int *width, int *height, int *color); - -int aud_binning_set(const AUD_HANDLE aud, int vb, int hb); -int aud_binning_get(const AUD_HANDLE aud, int *vb, int *hb); - -int aud_geometry_set(const AUD_HANDLE aud, int x, int y, int width, - int height); -int aud_geometry_get(const AUD_HANDLE aud, int *xorigin, int *yorigin, - int *winwidth, int *winheight, int *color); -int aud_geometry_reset(const AUD_HANDLE aud); - -int aud_amplifier_ctrl_set(const AUD_HANDLE aud, int ctrl); -int aud_amplifier_set(const AUD_HANDLE aud, int off_on); - -int aud_shutter_ctrl_set(const AUD_HANDLE aud, int ctrl); -int aud_shutter_set(const AUD_HANDLE aud, int off_on); - -int aud_aux0_ctrl_set(const AUD_HANDLE aud, int ctrl); -int aud_aux0_set(const AUD_HANDLE aud, int off_on); - -int aud_aux1_ctrl_set(const AUD_HANDLE aud, int ctrl); -int aud_aux1_set(const AUD_HANDLE aud, int off_on); - -int aud_clear(const AUD_HANDLE, int nclear); - -void aud_ioctl_test(AUD_HANDLE aud); - -int audine_fits_write(const char *fname, const char *img, - int width, int height); -#endif diff --git a/docho.c b/docho.c deleted file mode 100644 index ba64ce5..0000000 --- a/docho.c +++ /dev/null @@ -1,698 +0,0 @@ -/*-------------------------------------------------------------------------- - D o C h o - - - A SICS driver for a Dornier Chopper Control System accessed through a - RS-232 interface connected to a Macintosh PC running the SerialPortServer - terminal server program. There are two choppers which ususally run at fixed - speed ratios against each other. There ia also a phase difference between - the two choppers. And lots of machine surveillance parameters. - - This driver is used by the generic chopper or device controller as described - in choco.tex. - - - Mark Koennecke, January 1999 - - Modified to support a single chopper only, - - Uwe Filges, Mark Koennecke; November 2001 ---------------------------------------------------------------------------*/ -#include -#include -#include -#include -#include -#include -#include "hardsup/serialsinq.h" -#include "hardsup/el734_errcodes.h" -#include "hardsup/el734fix.h" -#include - -/*----------------------------------------------------------------------- - A private data structure for this Dornier chopper --------------------------------------------------------------------------*/ -typedef struct { - char *pHost; - int iPort; - int iChannel; - void *pData; - int iRefreshIntervall; - pStringDict pPar; - time_t tRefresh; - int iStop; - long lTask; - int iError; - int iBusy; - float fRatio; - int iSingle; - char pError[80]; -} DoCho, *pDoCho; -/* - pHost, iPort and iChannel combined are the adress of the chopper - controller at the Macintosh terminal server. pData is the serial - port connection data structure needed and managed by the SerialIO - functions. - - As the communication with the Dornier Chopper System is very slow the - parameter list of this driver will only be updated a predefined time - intervalls. In between buffered values will be returned for requests. - The buffered parameters are held in the string dictioanry pPar. - iRefreshIntervall is the time between refreshs. tRefresh is the time for - the next refresh. iBusy is flag which indicates, that it was tried to - modify a variable. This will only be reflected with the next status update. - In between DoChoCheckPar might conclude, that the chopper is already - done. iBusy is meant to stop that. It is set when a parameter is changed - and cleared bu the status message code. DoChoCheckPar checks for it. - - Refreshing will be performed by a special SICS task which will be - started when the driver is initialized. In order to stop this task when - need arises the parameter iStop can be set to true. - - iError is the last error reported on this device. If no error: 0 - - fRatio is the target value for the chopper ratio. In contrast to the - other parameters, its target value cannot be extracted from the chopper - status message. - - iSingle is a flag which is true if only a single chopper is controlled - through this driver. This supports the POLDI single choper case. - -*/ -/*---------------------------------------------------------------------- - ERROR CODES: -*/ -#define UNDRIVABLE -8002 -#define UNKNOWNPAR -8003 -#define PARERROR -8004 -#define BADSYNC -8005 -#define BADSTOP -8006 -#define CHOPERROR -8007 - -extern char *trim(char *pTrim); /* trim.c */ - -/*----------------------------------------------------------------------*/ -static void SplitChopperReply(pCodri self, char *prefix, char *pBueffel) -{ - char pToken[30], pValue[20], pEntry[80]; - char *pPtr, *pTok, *pVal; - int iCount, iRet; - pDoCho pPriv = NULL; - - pPriv = (pDoCho) self->pPrivate; - - /* decompose pBueffel and store into string dictionary */ - pPtr = strtok(pBueffel, ";"); - while (pPtr != NULL) { - iCount = sscanf(pPtr, "%s %s", pToken, pValue); - if (iCount == 2) { - pTok = trim(pToken); - pVal = trim(pValue); - pEntry[0] = '\0'; - sprintf(pEntry, "%s.%s", prefix, pTok); - iRet = StringDictUpdate(pPriv->pPar, pEntry, pVal); - if (!iRet) { - StringDictAddPair(pPriv->pPar, pEntry, pVal); - strcat(self->pParList, pEntry); - strcat(self->pParList, ","); - } - } else { - /* this fixes a bug with oversized messages in dphas oder averl*/ - if (strstr(pPtr, "dphas") != NULL ) { - sprintf(pEntry, "%s.dphas", prefix); - iRet = StringDictUpdate(pPriv->pPar, pEntry, pPtr + 5); - if (!iRet) { - StringDictAddPair(pPriv->pPar, pEntry, pPtr + 5); - strcat(self->pParList, pEntry); - strcat(self->pParList, ","); - } - } - if (strstr(pPtr, "averl") != NULL ) { - sprintf(pEntry, "%s.averl", prefix); - iRet = StringDictUpdate(pPriv->pPar, pEntry, pPtr + 5); - if (!iRet) { - StringDictAddPair(pPriv->pPar, pEntry, pPtr + 5); - strcat(self->pParList, pEntry); - strcat(self->pParList, ","); - } - } - } - pPtr = strtok(NULL, ";"); - } -} - -/*------------------------------------------------------------------------- - Well, DoChoStatus sends a status request to the Dornier chopper control - system. There is a gotcha, you need three reads to get the full information. - Then the answer is parsed and decomposed into parameter content for the - string dictionary. The single status components are separated by ;. --------------------------------------------------------------------------*/ - -static int DoChoStatus(pCodri self) -{ - int iRet, iCount, iCode; - char pBueffel[1024], pToken[30], pValue[20]; - char *pPtr, *pTok, *pVal; - pDoCho pPriv = NULL; - - assert(self); - pPriv = (pDoCho) self->pPrivate; - assert(pPriv); - pPriv->iBusy = 0; - pPriv->iError = 0; - - - /* first send, command, returns the echo */ - iRet = SerialWriteRead(&(pPriv->pData), "asyst 1", pBueffel, 1023); - if (iRet < 0) { - pPriv->iError = iRet; - return 0; - } - - /* next send: reads first chopper line */ - iRet = SerialWriteRead(&(pPriv->pData), "", pBueffel, 1023); - if (iRet < 0) { - pPriv->iError = iRet; - return 0; - } - SplitChopperReply(self, "chopper1", pBueffel); - - if (!pPriv->iSingle) { - /* second send: get next second chopper line */ - iRet = SerialWriteRead(&(pPriv->pData), "", pBueffel, 1023); - if (iRet < 0) { - pPriv->iError = iRet; - return 0; - } - SplitChopperReply(self, "chopper2", pBueffel); - } - - - return 1; -} - -/*-------------------------------------------------------------------------*/ -static int DoChoTask(void *pData) -{ - pCodri self = NULL; - pDoCho pPriv = NULL; - int iCode, iRet; - char pDummy[60]; - - self = (pCodri) pData; - assert(self); - pPriv = (pDoCho) self->pPrivate; - assert(pPriv); - - /* check for stop */ - if (pPriv->iStop) - return 0; - - - /* check if it is time to run a status request */ - if (time(NULL) > pPriv->tRefresh) { - /* try, fix error */ - if (pPriv->iError != 0) { - self->GetError(self, &iCode, pDummy, 59); - iRet = self->TryFixIt(self, iCode); - if (iRet == CHFAIL) { - pPriv->tRefresh = time(NULL) + pPriv->iRefreshIntervall; - return 1; - } - } - /* do it */ - DoChoStatus(self); - pPriv->tRefresh = time(NULL) + pPriv->iRefreshIntervall; - } - return 1; -} - -/*------------------------------------------------------------------------*/ -static void DoChoKill(void *pData) -{ - pCodri self = NULL; - pDoCho pPriv = NULL; - - self = (pCodri) pData; - if (!self) - return; - pPriv = (pDoCho) self->pPrivate; - if (!pPriv) - return; - - - if (pPriv->pData) { - SerialClose(&(pPriv->pData)); - pPriv->pData = NULL; - } - - if (pPriv->pHost) - free(pPriv->pHost); - if (pPriv->pPar) - DeleteStringDict(pPriv->pPar); - - free(pPriv); -} - -/*-------------------------------------------------------------------------*/ -static int DoChoInit(pCodri self) -{ - pDoCho pPriv = NULL; - int iRet; - - assert(self); - pPriv = (pDoCho) self->pPrivate; - assert(pPriv); - pPriv->iError = 0; - - /* first open the connection to the serial port server and channel */ - iRet = SerialOpen(&(pPriv->pData), pPriv->pHost, pPriv->iPort, - pPriv->iChannel); - if (iRet <= 0) { - pPriv->iError = iRet; - return 0; - } - /* configure the connection */ - SerialConfig(&(pPriv->pData), 10000); - SerialATerm(&(pPriv->pData), "1\r\n"); - SerialSendTerm(&(pPriv->pData), "\r"); - - pPriv->iStop = 0; - pPriv->tRefresh = 0; /* force a status request when first run */ - - /* start the update task */ - if (pPriv->lTask == 0) { - pPriv->lTask = TaskRegister(pServ->pTasker, - DoChoTask, NULL, NULL, self, 1); - } - return 1; -} - -/*------------------------------------------------------------------------*/ -static int DoChoClose(pCodri self) -{ - pDoCho pPriv = NULL; - int iRet; - long lVal; - - assert(self); - pPriv = (pDoCho) self->pPrivate; - assert(pPriv); - - if (pPriv->pData) { - SerialClose(&(pPriv->pData)); - pPriv->pData = NULL; - } - return 1; -} - -/*------------------------------------------------------------------------*/ -static int DoChoDelete(pCodri self) -{ - pDoCho pPriv = NULL; - - assert(self); - pPriv = (pDoCho) self->pPrivate; - assert(pPriv); - - if (pPriv->pData) { - SerialClose(&(pPriv->pData)); - pPriv->pData = NULL; - } - - if (pPriv->pHost) - free(pPriv->pHost); - if (pPriv->pPar) - DeleteStringDict(pPriv->pPar); - - free(pPriv); - - return 1; -} - -/*--------------------------------------------------------------------------*/ -static int DoChoSetPar2(pCodri self, char *parname, char *pValue) -{ - pDoCho pPriv = NULL; - char pCommand[80], pReply[132]; - char pState[20]; - int iRet; - - assert(self); - pPriv = (pDoCho) self->pPrivate; - assert(pPriv); - - /* deal with our four parameters */ - if (strcmp(parname, "chopper1.nspee") == 0) { - sprintf(pCommand, "nspee 1 %s", pValue); - } else if (strcmp(parname, "chopper2.nspee") == 0) { - iRet = StringDictGet(pPriv->pPar, "chopper2.state", pState, 19); - if (iRet && strstr(pState, "async") != NULL) { - sprintf(pCommand, "nspee 2 %s", pValue); - } else { - pPriv->iError = BADSYNC; - return 0; - } - } else if (strcmp(parname, "chopper2.nphas") == 0) { - sprintf(pCommand, "nphas 2 %s", pValue); - } else if (strcmp(parname, "chopper1.nphas") == 0) { - sprintf(pCommand, "nphas 1 %s", pValue); - } else if (strcmp(parname, "chopper2.ratio") == 0) { - sprintf(pCommand, "ratio 2 %s", pValue); - } else { - pPriv->iError = UNDRIVABLE; - return 0; - } - - iRet = SerialWriteRead(&(pPriv->pData), pCommand, pReply, 131); - if (iRet != 1) { - pPriv->iError = iRet; - return 0; - } - if (strstr(pReply, "error") != NULL) { - pPriv->iError = CHOPERROR; - strlcpy(pPriv->pError, pReply, 79); - return 0; - } else { - pPriv->iError = 0; - } - pPriv->iBusy = 1; - return 1; -} - -/*-------------------------------------------------------------------------*/ -static int DoChoHalt(pCodri self) -{ - pDoCho pPriv = NULL; - - assert(self); - pPriv = (pDoCho) self->pPrivate; - assert(pPriv); - - /* - there is no documented way to stop the Dornier chopper - system. This at least makes SICS happy. - */ - pPriv->iError = BADSTOP; - pPriv->iBusy = 0; - return 1; -} - -/*---------------------------------------------------------------------------*/ -static int DoChoSetPar(pCodri self, char *parname, float fValue) -{ - char pValue[50]; - pDoCho pPriv = NULL; - - assert(self); - pPriv = (pDoCho) self->pPrivate; - assert(pPriv); - - if (strstr(parname, "nspee") != NULL) { - sprintf(pValue, "%d", (int) fValue); - } else if (strstr(parname, "ratio") != NULL) { - sprintf(pValue, "%d", (int) fValue); - pPriv->fRatio = (int) fValue; - } else if (strcmp(parname, "updateintervall") == 0) { - sprintf(pValue, "%d", (int) fValue); - StringDictUpdate(pPriv->pPar, "updateintervall", pValue); - pPriv->iRefreshIntervall = (int) fValue; - return 1; - } else { - sprintf(pValue, "%f", fValue); - } - return DoChoSetPar2(self, parname, pValue); -} - -/*----------------------------------------------------------------------*/ -static int DoChoGetPar(pCodri self, char *parname, - char *pBuffer, int iBufLen) -{ - pDoCho pPriv = NULL; - int iRet; - - assert(self); - pPriv = (pDoCho) self->pPrivate; - assert(pPriv); - - if (pPriv->iError != 0) { - self->GetError(self, &iRet, pBuffer, iBufLen); - return 0; - } - - iRet = StringDictGet(pPriv->pPar, parname, pBuffer, iBufLen); - if (!iRet) { - pPriv->iError = UNKNOWNPAR; - return 0; - } - return 1; -} - -/*-----------------------------------------------------------------------*/ -static int DoChoCheckPar(pCodri self, char *parname) -{ - pDoCho pPriv = NULL; - char pVal1[20], pVal2[20]; - float fTarget, fIst, fDelta; - int iRet; - - assert(self); - pPriv = (pDoCho) self->pPrivate; - assert(pPriv); - - /* check the busy flag first */ - if (pPriv->iBusy) - return HWBusy; - - /* was there an error in the status show? */ - if (pPriv->iError != 0) { - return HWFault; - } - - /* updateintervall is always HWIdle */ - if (strcmp(parname, "updateintervall") == 0) { - return HWIdle; - } - - /* OK, got a new status let us check the parameter */ - /* chopper 1 speed */ - if (strcmp(parname, "chopper1.nspee") == 0) { - iRet = StringDictGet(pPriv->pPar, "chopper1.nspee", pVal1, 19); - iRet += StringDictGet(pPriv->pPar, "chopper1.aspee", pVal2, 19); - if (iRet != 2) { - pPriv->iError = PARERROR; - return HWFault; - } - sscanf(pVal1, "%f", &fTarget); - sscanf(pVal2, "%f", &fIst); - fDelta = fTarget - fIst; - if (fDelta < 0.0) - fDelta = -fDelta; - if (fDelta > 50) { - return HWBusy; - } else { - return HWIdle; - } - } - /* chopper 2 speed */ - if (strcmp(parname, "chopper2.nspee") == 0) { - iRet = StringDictGet(pPriv->pPar, "chopper2.nspee", pVal1, 19); - iRet += StringDictGet(pPriv->pPar, "chopper2.aspee", pVal2, 19); - if (iRet != 2) { - pPriv->iError = PARERROR; - return HWFault; - } - sscanf(pVal1, "%f", &fTarget); - sscanf(pVal2, "%f", &fIst); - fDelta = fTarget - fIst; - if (fDelta < 0.0) - fDelta = -fDelta; - if (fDelta > 5.) { - return HWBusy; - } else { - return HWIdle; - } - } - - /* phase */ - if (strcmp(parname, "chopper2.nphas") == 0) { - iRet = StringDictGet(pPriv->pPar, "chopper2.dphas", pVal1, 19); - sscanf(pVal1, "%f", &fDelta); - if (fDelta < 0.) - fDelta = -fDelta; - if (fDelta > 0.3) { - return HWBusy; - } else { - return HWIdle; - } - } - if (strcmp(parname, "chopper1.nphas") == 0) { - iRet = StringDictGet(pPriv->pPar, "chopper1.dphas", pVal1, 19); - sscanf(pVal1, "%f", &fDelta); - if (fDelta < 0.) - fDelta = -fDelta; - if (fDelta > 0.3) { - return HWBusy; - } else { - return HWIdle; - } - } - - /* ratio */ - if (strcmp(parname, "chopper2.ratio") == 0) { - iRet = StringDictGet(pPriv->pPar, "chopper2.ratio", pVal1, 19); - sscanf(pVal1, "%f", &fIst); - fDelta = fIst - pPriv->fRatio; - if (fDelta < 0.) - fDelta = -fDelta; - if (fDelta > 0.3) { - return HWBusy; - } else { - return HWIdle; - } - } - pPriv->iError = UNKNOWNPAR; - return HWFault; -} - -/*-------------------------------------------------------------------------*/ -static int DoChoError(pCodri self, int *iCode, char *pError, int iLen) -{ - pDoCho pPriv = NULL; - - assert(self); - pPriv = (pDoCho) self->pPrivate; - assert(pPriv); - - *iCode = pPriv->iError; - switch (pPriv->iError) { - case UNDRIVABLE: - strlcpy(pError, "Parameter is not drivable", iLen); - break; - case UNKNOWNPAR: - strlcpy(pError, "Parameter is unknown", iLen); - break; - case PARERROR: - strlcpy(pError, "Internal parameter error", iLen); - break; - case BADSYNC: - strlcpy(pError, "Cannot drive slave chopper", iLen); - break; - case CHOPERROR: - strlcpy(pError, pPriv->pError, iLen); - break; - case BADSTOP: - strlcpy(pError, - "User called STOP. WARNING: chopper is still untamed!", iLen); - break; - default: - SerialError(pPriv->iError, pError, iLen); - break; - } - pPriv->iError = 0; - return 1; -} - -/*------------------------------------------------------------------------*/ -static int DoChoFix(pCodri self, int iCode) -{ - pDoCho pPriv = NULL; - int iRet; - - assert(self); - pPriv = (pDoCho) self->pPrivate; - assert(pPriv); - - switch (iCode) { - /* 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: - case NOCONNECTION: - SerialForceClose(&(pPriv->pData)); - pPriv->pData = NULL; - iRet = SerialOpen(&(pPriv->pData), pPriv->pHost, - pPriv->iPort, pPriv->iChannel); - if (iRet == 1) { - return CHREDO; - } else { - return CHFAIL; - } - break; - case EL734__FORCED_CLOSED: - iRet = DoChoInit(self); - if (iRet) { - return CHREDO; - } else { - return CHFAIL; - } - break; - default: - return CHFAIL; - break; - } - return CHFAIL; -} - -/*-------------------------------------------------------------------------*/ -pCodri MakeDoChoDriver(char *pHost, int iPort, int iChannel, int iSingle) -{ - pCodri pNew = NULL; - pDoCho pPriv = NULL; - char *pText; - - /* allocate memory */ - pText = (char *) malloc(4096 * sizeof(char)); - pNew = (pCodri) malloc(sizeof(Codri)); - pPriv = (pDoCho) malloc(sizeof(DoCho)); - if (!pText || !pNew || !pPriv) { - return NULL; - } - memset(pText, 0, 4096); - memset(pNew, 0, sizeof(Codri)); - memset(pPriv, 0, sizeof(DoCho)); - - /* initialize private data structure */ - pPriv->pHost = strdup(pHost); - pPriv->iPort = iPort; - pPriv->iChannel = iChannel; - pPriv->pData = NULL; - pPriv->iRefreshIntervall = 60; - pPriv->pPar = CreateStringDict(); - pPriv->tRefresh = time(NULL); - pPriv->iSingle = iSingle; - if (!pPriv->pPar) { - free(pText); - free(pNew); - free(pPriv); - return NULL; - } - - /* install codri */ - pNew->Init = DoChoInit; - pNew->Close = DoChoClose; - pNew->Delete = DoChoDelete; - pNew->SetPar = DoChoSetPar; - pNew->SetPar2 = DoChoSetPar2; - pNew->GetPar = DoChoGetPar; - pNew->CheckPar = DoChoCheckPar; - pNew->GetError = DoChoError; - pNew->TryFixIt = DoChoFix; - pNew->Halt = DoChoHalt; - pNew->pParList = pText; - strcpy(pNew->pParList, "updateintervall,"); - StringDictAddPair(pPriv->pPar, "updateintervall", "60"); - pNew->pPrivate = pPriv; - - return pNew; -} diff --git a/dornier2.c b/dornier2.c deleted file mode 100644 index 71881a3..0000000 --- a/dornier2.c +++ /dev/null @@ -1,708 +0,0 @@ -/*------------------------------------------------------------------------ - - Another driver for a Dornier velocity selector. This is for a newer - version of the velocity selector driver as delivered with SANS-2. It - also uses a direct connection to the terminal server without David Maden's - SerPortServer program in between. - - I believe this is for Dornier software version: NGS037 of 2002. - - The protocoll is inconsistent: status messages come back with a , - command responses tend to come back with a \ and no ! - - There is a scheme here: while waiting for status reponses during driving, - the last status read is used for any requests. - - copyright: see file COPYRIGHT - - Mark Koennecke, July 2003 - ---------------------------------------------------------------------------*/ -#include -#include -#include -#include -#include -#include -#include -typedef struct __VelSelDriv *pVelSelDriv; - -#include -#include "velodorn.h" - -/* VELO* MUST be the same as in velo.i!*/ -#define VELOREDO 2 -#define VELOFAIL 0 -#define VELOOK 1 -#define VSNOCON 0 -#define VSOK 1 -#define VSACCEL -7 -#define VSFAIL -2 - - -/* start speed */ -#define STARTSPEED 3100 - -/*--------- special Dornier conditions*/ -#define STARTED -88 -#define HALTREQ -77 -/* INVALIDSTATUS is defined in velodorn.h */ -#define TARGETREJECTED -7001 -#define NOSTATUS -7002 - -/*---------- DORNIER status modes */ -#define STATSEND 1 -#define STATREAD 2 -/*----------------------------- The private data structure ---------------*/ -typedef struct { - prs232 controller; - int iTimeOut; - int iLastError; - time_t t_End; - time_t t_timeout; - float fTarget; - float fLastRPM; - int statusMode; - DornierStatus lastStatus; - int minRPM; /* the minimum control speed of the thing */ - int haltCount; - int rejectCount; - int noStatus; /* flag which indicates that no valid status - has yet been read. Solves a starting - problem - */ - int firstStatus; /* at times the nvs does not send - the reply to the first status - request after starting. This flag - helps to suppress an error message - which may be confusing to loosers - */ -} Dornier, *pDornier; -/*------------------------------------------------------------------*/ -static int requestDornierStatus(pDornier pDorn) -{ - int status; - - status = writeRS232(pDorn->controller, "???\n", 4); - if (status < 0) { - pDorn->iLastError = status; - return 0; - } - return 1; -} - -/*------------------------------------------------------------------*/ -static int readAndInterpretStatus(pDornier pDorn, DornierStatus * DStatus) -{ - int status, datalen; - char reply[512]; - - datalen = 512; - status = readRS232TillTerm(pDorn->controller, reply, &datalen); - if (status < 0) { - pDorn->iLastError = status; - return 0; - } - if (strlen(reply) < 80) { - pDorn->iLastError = INVALIDSTATUS; - pDorn->statusMode = STATSEND; - return 0; - } - - DecodeNewDornierStatus(reply, DStatus); - if (pDorn->noStatus == 1) { - pDorn->noStatus = 0; - } - return 1; -} - -/*-----------------------------------------------------------------*/ -static int takeControl(pDornier pDorn) -{ - int iRet; - char pError[80]; - setRS232ReplyTerminator(pDorn->controller, "\\"); - iRet = transactRS232(pDorn->controller, "REM\n", 4, pError, 79); - setRS232ReplyTerminator(pDorn->controller, "\n"); - return iRet; -} - -/*--------------------------------------------------------------------*/ -static int GetDornierPos(pVelSelDriv self, float *fPos) -{ - pDornier pDorn = NULL; - DornierStatus DStatus; - int status; - - assert(self); - pDorn = (pDornier) self->pPrivate; - - if (pDorn->statusMode == STATSEND) { - if (!requestDornierStatus(pDorn)) { - *fPos = -9999.; - return 0; - } - if (!readAndInterpretStatus(pDorn, &DStatus)) { - *fPos = -9999.; - return 0; - } - pDorn->lastStatus = DStatus; - } - - *fPos = pDorn->lastStatus.cur_rpm; - pDorn->fLastRPM = pDorn->lastStatus.cur_rpm; - return 1; -} - -/*--------------------------------------------------------------------------*/ -static int DornierHalt(pVelSelDriv self) -{ - pDornier pDorn = NULL; - int iRet; - char pCom[50]; - char pAnswer[80]; - - assert(self); - pDorn = (pDornier) self->pPrivate; - - snprintf(pCom, 49, "SDR %d\n", pDorn->minRPM); - iRet = transactRS232(pDorn->controller, pCom, strlen(pCom), pAnswer, 79); - if (iRet < 1) { - pDorn->iLastError = iRet; - return 0; - } - return 1; -} - -/*----------------------------------------------------------------------*/ -static int DornierText(pVelSelDriv self, char *pText, int iTextLen) -{ - pDornier pDorn = NULL; - int iRet, iErrStat; - DornierStatus sStatus; - char pBueffel[1024]; - char pHelp[80]; - - assert(self); - pDorn = (pDornier) self->pPrivate; - - /* - use cached status while waiting for reply during drive - */ - if (pDorn->statusMode == STATSEND) { - if (!requestDornierStatus(pDorn)) { - return 0; - } - if (!readAndInterpretStatus(pDorn, &sStatus)) { - return 0; - } - pDorn->lastStatus = sStatus; - } else { - sStatus = pDorn->lastStatus; - } - - /* format it to a string */ - sprintf(pHelp, "RPM: %d , should %d\n", sStatus.cur_rpm, - sStatus.nom_rpm); - strcpy(pBueffel, pHelp); - sprintf(pHelp, "State: %s\n", sStatus.rm); - strcat(pBueffel, pHelp); - sprintf(pHelp, "Current: %d\n", sStatus.pwr); - strcat(pBueffel, pHelp); - sprintf(pHelp, "Rotor T: %d, Housing T: %d\n", sStatus.rot_temp, - sStatus.cont_temp); - strcat(pBueffel, pHelp); - sprintf(pHelp, "Cooling: In-T: %d, Out-T: %d, Flow: %f\n", - sStatus.inl_temp, sStatus.outl_temp, sStatus.cool_wat); - strcat(pBueffel, pHelp); - sprintf(pHelp, "Vaccum: %f, Accel: %f", sStatus.vacuum, sStatus.accel); - strcat(pBueffel, pHelp); - - strlcpy(pText, pBueffel, iTextLen); - return 1; -} - -/*-------------------------------------------------------------------------*/ -static int DornierRun(pVelSelDriv self, float fVal) -{ - int iRet; - char pCommand[50], pAnswer[50], pText[132]; - pDornier pDorn = NULL; - int startFlag = 0; - int i; - DornierStatus sStatus; - - assert(self); - pDorn = (pDornier) self->pPrivate; - - /* - make sure that a status was read before we do anything here, - otherwise we may be in deep trouble - */ - if (pDorn->statusMode == STATSEND) { - iRet = requestDornierStatus(pDorn); - if (iRet == 0) { - return 0; - } - } - iRet = readAndInterpretStatus(pDorn, &sStatus); - if (iRet == 0) { - return 0; - } - pDorn->lastStatus = sStatus; - - /* - less then STARTSPEED, means halt in this case. - Accept this only after three times, see code in GetError as well. - */ - if (fVal < 0) { - fVal = -fVal; - } - memset(pCommand, 0, 50); - pDorn->rejectCount = 0; - - if (fVal < STARTSPEED - 3 * self->fTolerance) { - if (pDorn->haltCount < 3) { - pDorn->iLastError = HALTREQ; - return 0; - } - strcpy(pCommand, "HAL\n"); - setRS232ReplyTerminator(pDorn->controller, "\r"); - pDorn->haltCount = 0; - pDorn->fTarget = fVal; - } else { - if (pDorn->lastStatus.cur_rpm < STARTSPEED - 3 * self->fTolerance) { - strcpy(pCommand, "SST\n"); - startFlag = 1; - pDorn->fTarget = STARTSPEED; - setRS232ReplyTerminator(pDorn->controller, "\r"); - } else { - setRS232ReplyTerminator(pDorn->controller, "\r"); - sprintf(pCommand, "SDR %d\n", (int) fVal); - pDorn->fTarget = fVal; - } - } - - iRet = transactRS232(pDorn->controller, pCommand, strlen(pCommand), - pAnswer, 49); - setRS232ReplyTerminator(pDorn->controller, "\n"); - pDorn->firstStatus = 1; - if (iRet < 1) { - if (iRet != INCOMPLETE) { - - pDorn->iLastError = iRet; - return 0; - } - } - pDorn->statusMode = STATSEND; - if (startFlag) { - pDorn->iLastError = STARTED; - return 0; - } - return 1; -} - -/*---------------------------------------------------------------------*/ -static int DornierError(pVelSelDriv self, int *iCode, - char *error, int iErrLen) -{ - pDornier pDorn = NULL; - - assert(self); - pDorn = (pDornier) self->pPrivate; - - *iCode = pDorn->iLastError; - - switch (pDorn->iLastError) { - case HALTREQ: - strlcpy(error, "Repeat command if you really want to HALT selector", - iErrLen); - pDorn->haltCount++; - break; - case STARTED: - strlcpy(error, - "Started selector, standby and check manually when ready", - iErrLen); - break; - case INVALIDSTATUS: - strlcpy(error, "Received invalid status reply", iErrLen); - break; - case TARGETREJECTED: - strlcpy(error, "VS in local mode or target out of range", iErrLen); - break; - case NOSTATUS: - strlcpy(error, "No successfull status request after 3 tries", iErrLen); - break; - default: - getRS232Error(pDorn->iLastError, error, iErrLen); - break; - } - return 1; -} - -/*-------------------------------------------------------------------*/ -static int DornierFixIt(pVelSelDriv self, int iCode) -{ - pDornier pDorn = NULL; - int status, oldReject; - - assert(self); - pDorn = (pDornier) self->pPrivate; - - switch (iCode) { - case NOTCONNECTED: - status = initRS232(pDorn->controller); - if (status) { - return VELOREDO; - } else { - return VELOFAIL; - } - break; - case TIMEOUT: - case INCOMPLETE: - case INVALIDSTATUS: - return VELOREDO; - break; - case TARGETREJECTED: - if (pDorn->rejectCount >= 3) { - pDorn->rejectCount = 0; - return VELOFAIL; - } - oldReject = pDorn->rejectCount; - status = takeControl(pDorn); - if (status >= 1) { - DornierRun(self, pDorn->fTarget); - pDorn->rejectCount = oldReject + 1; - return VELOREDO; - } - return VELOFAIL; - break; - default: - return VELOFAIL; - } -} - -/*---------------------------------------------------------------------*/ -static int statusSendHandler(pDornier pDorn) -{ - int status; - - if (!requestDornierStatus(pDorn)) { - return VSFAIL; - } - pDorn->t_timeout = time(NULL) + pDorn->iTimeOut / 1000; - pDorn->statusMode = STATREAD; - return VSACCEL; -} - -/*------------------------------------------------------------------*/ -static int evaluateStatus(pVelSelDriv self, int *iCode) -{ - int status; - DornierStatus sStatus; - char pCommand[80]; - char pAnswer[80]; - float fDelta; - static int iCount = 0; - pDornier pDorn = NULL; - - pDorn = (pDornier) self->pPrivate; - - pDorn->statusMode = STATSEND; - status = readAndInterpretStatus(pDorn, &sStatus); - if (!status) { - if (pDorn->firstStatus == 1) { - pDorn->firstStatus = 0; - return VSACCEL; - } - return VELOFAIL; - } - - *iCode = ROTMOVE; - - /* - sometimes the velocity selector does not accept a new target: - Two reasons: a) it is local, b) out of range - Check for this here as it is the only place appropriate. - */ - fDelta = sStatus.nom_rpm - pDorn->fTarget; - if (fDelta < 0) { - fDelta = -fDelta; - } - if (fDelta > self->fTolerance) { - pDorn->iLastError = TARGETREJECTED; - return VSFAIL; - } - - /* - This code considers the velocity selector arrived if it reads - four times a difference between requested speed and actual speed - below difference - */ - pDorn->fLastRPM = sStatus.cur_rpm; - fDelta = sStatus.cur_rpm - sStatus.nom_rpm; - if (fDelta < 0) { - fDelta = -fDelta; - } - if (fDelta > self->fTolerance) { - iCount = 0; - return VSACCEL; - } else { - iCount++; - if (iCount > 4) { - return VSOK; - } else { - return VSACCEL; - } - } -} - -/*---------------------------------------------------------------------*/ -static int statusReceiveHandler(pVelSelDriv self, int *iCode) -{ - int status; - pDornier pDorn = NULL; - - pDorn = (pDornier) self->pPrivate; - - status = availableRS232(pDorn->controller); - if (!status) { - if (time(NULL) > pDorn->t_timeout) { - pDorn->iLastError = TIMEOUT; - pDorn->statusMode = STATSEND; - return VELOFAIL; - } else { - return VSACCEL; - } - } - - return evaluateStatus(self, iCode); -} - -/*-------------------------------------------------------------------------- - The Dornier takes a long time to answer a status message. In order to keep - SICS responsive the following state machine is implemented: - - a status request is sent. - - next data availability will be checked, if available: process! - ---------------------------------------------------------------------------*/ -static int DornierStatNew(pVelSelDriv self, int *iCode, float *fCur) -{ - pDornier pDorn = NULL; - int status; - - assert(self); - pDorn = (pDornier) self->pPrivate; - - if (pDorn->statusMode == STATSEND) { - return statusSendHandler(pDorn); - } else { - status = statusReceiveHandler(self, iCode); - *fCur = pDorn->fLastRPM; - return status; - } -} - -/*------------------------------------------------------------------------*/ -static int DornierLoss(pVelSelDriv self, float *fLoss) -{ - pDornier pDorn = NULL; - int iRet, iErrStat, iDelta; - DornierStatus DStatus; - char pCommand[] = { "BRE\n" }; - char pAnswer[80]; - static int iCount; - static int iError; - int i; - - assert(self); - pDorn = (pDornier) self->pPrivate; - - /* send a command */ - iRet = transactRS232(pDorn->controller, pCommand, strlen(pCommand), - pAnswer, 79); - if (iRet < 1) { - pDorn->iLastError = iRet; - return 0; - } - - /* wait 10 seconds before doing anything */ - SicsWait(10); - - /* loop until back to speed again */ - for (i = 0; i < 100; i++) { - if (!requestDornierStatus(pDorn)) { - return 0; - } - if (!readAndInterpretStatus(pDorn, &DStatus)) { - return 0; - } - iError = 0; - iDelta = DStatus.cur_rpm - DStatus.nom_rpm; - if (iDelta < 0) { - iDelta = -iDelta; - } - if (iDelta < 15) { - iCount++; - if (iCount > 4) { - break; - } - } else { - iCount = 0; - } - } - *fLoss = DStatus.pwr; - return 1; -} - -/*-------------------------------------------------------------------------*/ -static void DornierKill(void *pData) -{ - pDornier pDorn = NULL; - - pDorn = (pDornier) pData; - assert(pDorn); - - writeRS232(pDorn->controller, "TTY\n", 4); - KillRS232(pDorn->controller); - free(pDorn); -} - -/*------------------------------------------------------------------------*/ -static int DornierInit(pVelSelDriv self, SConnection * pCon) -{ - pDornier pDorn = NULL; - int iRet, iError; - float fRot; - char pError[80], pBueffel[256]; - - assert(self); - pDorn = (pDornier) self->pPrivate; - assert(pDorn); - - iRet = initRS232(pDorn->controller); - if (iRet < 0) { - return 1; - } - setRS232SendTerminator(pDorn->controller, "\n"); - setRS232Timeout(pDorn->controller, pDorn->iTimeOut); - setRS232Debug(pDorn->controller, 0); - - /* - tell him that we want control. - Funny enough no or is sent in the reply to this. - */ - iRet = takeControl(pDorn); - if (iRet <= 1) { - sprintf(pBueffel, - "ERROR: %s while switching velocity selector to remote", - pError); - SCWrite(pCon, pBueffel, eError); - } - /* - check which status the velo is in - */ - pDorn->statusMode = STATSEND; - return 1; -} - -/*-------------------------------------------------------------------------*/ -pVelSelDriv VSCreateDornier2003(char *name, Tcl_Interp * pTcl) -{ - pVelSelDriv pNew = NULL; - pDornier pDorn = NULL; - char *pPtr = NULL; - int iVal, iRet, iPort; - char pHost[132]; - - - /* the most likely error is the parameters specified are wrong! - So check this first. We''ll use Tcl's result for error reporting. - name is the name of an Tcl array which should hold the info - necessary - */ - - /* allocate a Dornier structure */ - pDorn = (pDornier) malloc(sizeof(Dornier)); - if (!pDorn) { - return NULL; - } - memset(pDorn, 0, sizeof(Dornier)); - - /* host name */ - pPtr = (char *) Tcl_GetVar2(pTcl, name, "Host", TCL_GLOBAL_ONLY); - if (!pPtr) { - Tcl_AppendResult(pTcl, "ERROR: no hostname found in", name, NULL); - free(pDorn); - return NULL; - } - strlcpy(pHost, pPtr, 131); - - /* port number */ - pPtr = (char *) Tcl_GetVar2(pTcl, name, "Port", TCL_GLOBAL_ONLY); - if (!pPtr) { - Tcl_AppendResult(pTcl, "ERROR: no port number found in", name, NULL); - free(pDorn); - return NULL; - } - iRet = Tcl_GetInt(pTcl, pPtr, &iPort); - if (iRet != TCL_OK) { - free(pDorn); - return NULL; - } - - /* time out. This one gets defaulted when not specified */ - pPtr = (char *) Tcl_GetVar2(pTcl, name, "Timeout", TCL_GLOBAL_ONLY); - if (!pPtr) { - pDorn->iTimeOut = 1000; - } else { - iRet = Tcl_GetInt(pTcl, pPtr, &iVal); - if (iRet != TCL_OK) { - pDorn->iTimeOut = 1000; - } - pDorn->iTimeOut = iVal; - } - - /* minimum control speed */ - pPtr = (char *) Tcl_GetVar2(pTcl, name, "MinControl", TCL_GLOBAL_ONLY); - if (!pPtr) { - pDorn->minRPM = 3100; - } else { - iRet = Tcl_GetInt(pTcl, pPtr, &iVal); - if (iRet != TCL_OK) { - pDorn->minRPM = 3100; - } - pDorn->minRPM = iVal; - } - - - /* business as usual: allocate memory */ - pNew = (pVelSelDriv) malloc(sizeof(VelSelDriv)); - if (!pNew) { - return NULL; - } - - /* zero the world */ - memset(pNew, 0, sizeof(VelSelDriv)); - pNew->pPrivate = pDorn; - pDorn->controller = createRS232(pHost, iPort); - if (!pDorn->controller) { - DornierKill(pNew->pPrivate); - free(pNew); - return NULL; - } - pDorn->noStatus = 1; - - /* initialise function pointers */ - pNew->DeletePrivate = DornierKill; - pNew->Halt = DornierHalt; - pNew->GetError = DornierError; - pNew->TryAndFixIt = DornierFixIt; - pNew->GetRotation = GetDornierPos; - pNew->SetRotation = DornierRun; - pNew->GetStatus = DornierStatNew; - pNew->GetDriverText = DornierText; - pNew->GetLossCurrent = DornierLoss; - pNew->Init = DornierInit; - - /* done it */ - return pNew; -} diff --git a/ecbcounter.c b/ecbcounter.c deleted file mode 100644 index 560d01b..0000000 --- a/ecbcounter.c +++ /dev/null @@ -1,640 +0,0 @@ -/*---------------------------------------------------------------------------- - 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 readTime(pECBCounter pPriv, float *time) -{ - int status; - Z80_reg in, out; - Ecb_pack data; - - in.c = (unsigned char) 0; - 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; - *time = (float) data.result / (float) pPriv->tfreq; - 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 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 ECBGetStatus(struct __COUNTER *self, float *fControl) -{ - pECBCounter pPriv = (pECBCounter) self->pData; - int status, result, scaler; - Z80_reg in, out; - int count, beam; - float time; - - 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; - readTime(pPriv, fControl); - } else { - scaler = pPriv->control; - readScaler(pPriv, scaler, &count); - *fControl = (float) count; - } - - if (*fControl > self->fPreset + 1.) { - ECBHalt(self); - } - 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 ECBTransfer(struct __COUNTER *self) -{ - int status, count, i; - pECBCounter pPriv = NULL; - - assert(self); - pPriv = (pECBCounter) self->pData; - assert(pPriv); - - /* - read time - */ - status = readTime(pPriv, &self->fTime); - if (status <= 0) { - self->iErrorCode = COMMERROR; - return HWFault; - } - - /* - 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: - strlcpy(errorText, "Communication error with ECB", errlen); - break; - case TOMANYCOUNTS: - strlcpy(errorText, "Preset is to high!", errlen); - break; - case NOSEND: - strlcpy(errorText, "Cannot send naked data to ECB", errlen); - break; - case UNKNOWNPAR: - strlcpy(errorText, "parameter unknown", errlen); - break; - case INVALIDCOUNTER: - strlcpy(errorText, "Invalid counter number requested, 0-7 allowed", - errlen); - break; - case INVALIDPRESCALER: - strlcpy(errorText, "Invalid prescaler value, allowed 1 or 10", errlen); - break; - case BADFREQ: - strlcpy(errorText, "Bad timer frequency: 10 or 1000 allowed", errlen); - break; - default: - sprintf(pBueffel, "Unknown error code %d", self->iErrorCode); - strlcpy(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) -{ - strlcpy(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->iNoOfMonitors = 8; - - self->pData = pPriv; - return self; -} diff --git a/ecbcounter.h b/ecbcounter.h deleted file mode 100644 index cbfad22..0000000 --- a/ecbcounter.h +++ /dev/null @@ -1,17 +0,0 @@ -/*------------------------------------------------------------------------- - 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/ecbdriv.c b/ecbdriv.c deleted file mode 100644 index 15b0119..0000000 --- a/ecbdriv.c +++ /dev/null @@ -1,1370 +0,0 @@ -/*------------------------------------------------------------------------ - this is a motor driver for the Risoe motor controllers within the - ECB system. The motor is controlled through functions invoked in the - Z80 processor of the ECB system which is connected through a GPIB - bus to the wider world. This driver has to do a lot of extra things: - - it has to convert from physical values to motor steps. - - Quite a few parameters, such as ramping parameters, - have to be downloaded to the ECB - - Risoe motors may have a virtual encoder or a real encoder. - - The motor may have to control air cushions as well. - - Tricky backlash handling. Backlash handling ensures that a position is - always arrived at from a defined direction. If backlash is applied - a restart flag is set in ECBRunTo. ECBGetStatus checks for that and - causes the motor to drive back to the position actually desired. - - This driver support only P2048a motor controllers, as these are the - only ones which seem to have arrived at PSI. The P1648 and Tridynamic - things are not supported. - - Multiplexed motors: Originally the ECB supported 24 motors. This did - prove to be not enough. Therefore another device called P2234e was - introduced which allowed to run 8 motors from one controller port. In this - case the motor parameters have to be copied to the ECB before - driving the motor. Multiplexing is selected through the parameter MULT. - MULT 0 means no multiplexing, MULT > 0 makes MULT the number of the - motor in the multiplexer. MULT is now also used to flag a download of - parameters to the ECB. In such a case MULT is -1. - - - Some of this code was taken from the tascom driver for the ECB. - - copyright: see file COPYRIGHT - - Mark Koennecke, January 2003 - ---------------------------------------------------------------------------*/ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "ecb.h" - -/*------------------------------------------------------------------------ -Parameter indexes in ObPar array and meanings --------------------------------------------------------------------------*/ -#define ENCODER 0 /* encoder number, 0 if no encoder */ -#define CONTROL 1 /* control signals, > 1 means required. */ -#define RANGE 2 /* 0 = slow, 1 = fast */ -#define MULT 3 /* 0 = not multiplexed, > 0 multiplex motor number */ -#define MULTCHAN 16 /* multiplexer channel */ -#define ACCTIME 4 /* acceleration time: 500, 1000 or 2000 milSecs */ -#define ROTDIR 5 /* rotation direction */ -#define STARTSPEED 6 /* start speed: 100-500 steps/s */ -#define MAXSPEED 7 /* maximum speed: 100-2000 steps/sec */ -#define SLOWAUTO 8 /* slow speed in auto mode */ -#define SLOWMAN 9 /* slow speed in manual mode */ -#define DELAY 10 /* start delay 0 - 2500 millSecs */ -#define OFFSET 11 /* encoder offset */ -#define TOLERANCE 12 /* tolerance in steps */ -#define STEPS2DEG 13 /* conversion factor motor steps to Degree */ -#define DEG2STEP 14 /* conversion factor from degree to encoder digits */ -#define BACKLASH 15 /* motor backlash */ -#define PORT 17 /* ECB port when multiplexed */ -#define DEC 18 /* Decimals in display */ - -#define MAXPAR 20 /* 1 extra for the sentinel, do not forget to initialize! */ - -/*------------------------------ ECB defines -------------------------*/ -#define MAX_ENCODER 40 -#define FENCOR 167 /* read encoder */ -#define MOREAD 145 /* read motor steps */ -#define MOPARA 140 /* motor parameter */ -#define MOCLOA 146 -#define ABS(x) (x < 0 ? -(x) : (x)) -#define MOSTEP 141 -#define MOSTAT 144 - -/********************* error codes *************************************/ -#define COMMERROR -300 -#define ECBMANUELL -301 -#define ECBINUSE -302 -#define UNIDENTIFIED -303 -#define ECBINHIBIT -304 -#define ECBRUNNING -305 -#define ECBSTART -306 -#define ECBLIMIT -307 -#define ECBREADERROR -308 -/*================== The Driver data structure ============================*/ -typedef struct __ECBMotorDriv { - /* general motor driver interface - fields. REQUIRED! - */ - float fUpper; /* upper limit */ - float fLower; /* lower limit */ - char *name; - int (*GetPosition) (void *self, float *fPos); - int (*RunTo) (void *self, float fNewVal); - int (*GetStatus) (void *self); - void (*GetError) (void *self, int *iCode, char *buffer, int iBufLen); - int (*TryAndFixIt) (void *self, int iError, float fNew); - int (*Halt) (void *self); - int (*GetDriverPar) (void *self, char *name, float *value); - int (*SetDriverPar) (void *self, SConnection * pCon, - char *name, float newValue); - void (*ListDriverPar) (void *self, char *motorName, SConnection * pCon); - void (*KillPrivate) (void *self); - - /* ECB specific fields */ - pECB ecb; /* ECB controller for everything */ - int ecbIndex; /* motor index in ECB */ - int errorCode; - int restart; /* flag if we have to restart - because of backlash - compensation - */ - float restartTarget; /* target to restart to */ - ObPar driverPar[MAXPAR]; /* parameters */ -} ECBMOTDriv, *pECBMotDriv; -/*======================================================================= - Reading the motor position means reading the encoder if such a thing - is present or the counted motor steps (Pseudo Encoder) if not. - If the ECB answers us, the value has to be converted to physical - values. - ----------------------------------------------------------------------*/ -static int readEncoder(pECBMotDriv self, long *digits) -{ - int status; - Z80_reg in, out; - Ecb_pack data; - - in.c = (unsigned char) ObVal(self->driverPar, ENCODER) + MAX_ENCODER; - status = ecbExecute(self->ecb, FENCOR, in, &out); - if (!status) { - self->errorCode = COMMERROR; - return status; - } - - /* pack bytes */ - data.b.byt3 = 0; - data.b.byt2 = out.b; - data.b.byt1 = out.d; - data.b.byt0 = out.e; - if (out.c != 1) { - *digits = -data.result; - } else { - *digits = data.result; - } - return OKOK; -} - -/*---------------------------------------------------------------------*/ -static int readPseudoEncoder(pECBMotDriv self, long *digits) -{ - int status; - Z80_reg in, out; - Ecb_pack data; - - in.c = (unsigned char) self->ecbIndex; - status = ecbExecute(self->ecb, MOREAD, in, &out); - if (!status) { - self->errorCode = COMMERROR; - return status; - } - - /* pack bytes */ - data.b.byt3 = 0; - data.b.byt2 = out.b; - data.b.byt1 = out.d; - data.b.byt0 = out.e; - if (out.c != 1) { - *digits = -data.result; - } else { - *digits = data.result; - } - return OKOK; -} - -/*----------------------------------------------------------------------*/ -int ECBMOTGetPos(void *pData, float *fPos) -{ - pECBMotDriv self = (pECBMotDriv) pData; - long digits = 0; - int status; - double step2degree; - - assert(self); - self->errorCode = 0; - - if ((int) ObVal(self->driverPar, ENCODER) > 0) { - status = readEncoder(self, &digits); - step2degree = ObVal(self->driverPar, DEG2STEP); - if (step2degree == 0.0) { - step2degree = 1; - } - *fPos = (digits / step2degree) - ObVal(self->driverPar, OFFSET); - return status; - } else { - status = readPseudoEncoder(self, &digits); - } - step2degree = ObVal(self->driverPar, STEPS2DEG); - if (step2degree == 0.0) { - step2degree = 1.; - } - *fPos = (float) ((double) digits / step2degree); - - return status; -} - -/*======================================================================== -In order to start a motor we need to do a couple of steps: - - check if the motors parameters have been changed or it is a multiplexed - motor. In each case download the motor parameters. - - the direction of the motor has to be determined, the speed to be - selected etc. - - Then the motor can be started. - ------------------------------------------------------------------------*/ -static int mustDownload(pECBMotDriv self) -{ - int multi; - - multi = (int) rint(ObVal(self->driverPar, MULT)); - if (multi > 0 || multi < 0) { - return 1; - } else { - return 0; - } -} - -/*--------------------------------------------------------------------*/ -static int checkMotorResult(pECBMotDriv self, Z80_reg out) -{ - /* - checks the return values from a motor function invocation - and sets error codes in case of problems. - */ - if (out.c == '\0') { - switch (out.b) { - case 128: - self->errorCode = ECBMANUELL; - break; - case 64: - self->errorCode = ECBINHIBIT; - break; - case 32: - case 96: - self->errorCode = ECBRUNNING; - break; - case 1: - self->errorCode = ECBSTART; - break; - case 16: - self->errorCode = ECBLIMIT; - break; - case 4: - self->errorCode = ECBINUSE; - break; - default: - fprintf(stderr, "Unidentified ECB motor error code %d\n", out.b); - self->errorCode = UNIDENTIFIED; - break; - } - return 0; - } else { - return 1; - } -} - -/*---------------------------------------------------------------------*/ -static int loadAcceleration(pECBMotDriv self) -{ - unsigned char parameter; - Z80_reg in, out; - int accel, status; - - accel = (int) rint(ObVal(self->driverPar, ACCTIME)); - if (accel == 500) { - parameter = 1; - } else if (accel == 1000) { - parameter = 2; - } else if (accel == 2000) { - parameter = 3; - } else { - parameter = 0; - } - /* - apply rotation direction mask - */ - if (ObVal(self->driverPar, ROTDIR) < 0) { - parameter += 128; - } - in.c = (unsigned char) self->ecbIndex; - in.b = 7; - in.e = parameter; - in.d = 0; - out.d = out.e = out.b = out.c = 0; - status = ecbExecute(self->ecb, MOPARA, in, &out); - if (!status) { - self->errorCode = COMMERROR; - return 0; - } - - if (!checkMotorResult(self, out)) { - return 0; - } - - return 1; -} - -/*--------------------------- speed tables ------------------------------*/ -#define SPEED_TAB3 64 /* Size of speed table */ -const unsigned int low_2048[SPEED_TAB3] = { - 1, 2, 3, 4, 5, 6, 8, 10, 12, 14, - 16, 20, 24, 28, 32, 36, 40, 44, 48, 56, - 64, 72, 80, 88, 96, 104, 112, 120, 128, 136, - 144, 152, 160, 168, 176, 184, 192, 200, 208, 216, - 224, 236, 248, 260, 272, 284, 296, 308, 320, 332, - 344, 356, 368, 380, 392, 404, 416, 428, 440, 452, - 464, 476, 488, 500 -}; - -#define SPEED_TAB4 96 /* Size of speed table */ -const unsigned int high_2048[SPEED_TAB4] = { - 11, 15, 20, 27, 36, 47, 59, 74, - 93, 107, 124, 143, 165, 190, 213, 239, - 268, 298, 331, 368, 405, 446, 491, 536, - 585, 632, 683, 731, 783, 827, 873, 922, - 974, 1028, 1085, 1146, 1211, 1278, 1349, 1424, - 1503, 1587, 1675, 1720, 1820, 1913, 2014, 2123, - 2237, 2360, 2483, 2620, 2755, 2905, 3058, 3221, - 3384, 3575, 3756, 3945, 4150, 4370, 4600, 4800, - 5000, 5250, 5533, 5822, 6120, 6440, 6770, 7090, - 7450, 7800, 8130, 8500, 8900, 9320, 9730, 10200, - 10700, 11200, 11700, 12200, 12800, 13300, 13900, 14500, - 15100, 15800, 16700, 17300, 18000, 18600, 19300, 20000 -}; - -/*---------------------------------------------------------------------*/ -static unsigned char getSpeedIndex(float value, - int range, int *actualValue) -{ - unsigned char index; - const unsigned int *table; - int length; - - if (range == 0) { - table = low_2048; - length = SPEED_TAB3; - } else { - table = high_2048; - length = SPEED_TAB4; - } - - for (index = 0; index < length - 1; index++) { - if (table[index] >= value) { - break; - } - } - *actualValue = table[index]; - return index; -} - -/*--------------------------------------------------------------------*/ -static int loadSpeed(pECBMotDriv self, float value, int code) -{ - unsigned char parameter; - Z80_reg in, out; - int accel, status, actual; - - parameter = - getSpeedIndex(value, (int) rint(ObVal(self->driverPar, RANGE)), - &actual); - - in.c = (unsigned char) self->ecbIndex; - in.b = code; - in.e = parameter; - status = ecbExecute(self->ecb, MOPARA, in, &out); - if (!status) { - self->errorCode = COMMERROR; - return 0; - } - if (!checkMotorResult(self, out)) { - return 0; - } - return 1; -} - -/*-------------------------------------------------------------------*/ -static int loadDelay(pECBMotDriv self) -{ - int parameter; - Z80_reg in, out; - int accel, status; - unsigned char control; - - parameter = (int) rint(ObVal(self->driverPar, DELAY)); - control = (unsigned char) rint(ObVal(self->driverPar, CONTROL)); - if (control & 3) { - parameter = 5; - } else { - parameter /= 10; - } - in.c = (unsigned char) self->ecbIndex; - in.b = 8; - in.e = parameter; - status = ecbExecute(self->ecb, MOPARA, in, &out); - if (!status) { - self->errorCode = COMMERROR; - return 0; - } - - if (!checkMotorResult(self, out)) { - return 0; - } - - return 1; -} - -/*---------------------------------------------------------------------*/ -static int loadMulti(pECBMotDriv self) -{ - int multi, mult_chan; - Z80_reg in, out; - int status; - - multi = rint(ObVal(self->driverPar, MULT)); - if (multi <= 0) { - return 1; /* not multiplexed */ - } - - mult_chan = (unsigned char) rint(ObVal(self->driverPar, MULTCHAN)); - in.b = -1; /* SET_PORT */ - in.d = (unsigned char) (multi + (mult_chan << 4)); - in.e = (unsigned char) rint(ObVal(self->driverPar, PORT)); - in.c = self->ecbIndex; - status = ecbExecute(self->ecb, MOPARA, in, &out); - if (status != 1) { - self->errorCode = COMMERROR; - return 0; - } - return 1; -} - -/*------------------------------------------------------------------*/ -static int loadOffset(pECBMotDriv self, float offset) -{ - Z80_reg in, out; - int status; - Ecb_pack data; - - /* - ignored - */ - if (ObVal(self->driverPar, ENCODER) <= .0) { - return 1; - } - - data.result = offset * ObVal(self->driverPar, STEPS2DEG); - in.b = data.b.byt2; - in.d = data.b.byt1; - in.e = data.b.byt0; - in.c = (unsigned char) rint(ObVal(self->driverPar, ENCODER)); - - status = ecbExecute(self->ecb, 168, in, &out); - if (status == 1) { - self->driverPar[OFFSET].fVal = offset; - } else { - self->errorCode = COMMERROR; - } - return status; -} - -/*--------------------------------------------------------------------- - This loads the gearing parameters for the CRT display. This should - not have any influence on the running of the motor - ------------------------------------------------------------------------*/ -static double To_ten(int v) -{ - double vv; - - - vv = 1.0; - if (v == 1) - vv = 10.0; - if (v == 2) - vv = 100.0; - if (v == 3) - vv = 1000.0; - if (v == 4) - vv = 10000.0; - if (v == 5) - vv = 100000.0; - if (v == 6) - vv = 1000000.0; - if (v == 7) - vv = 10000000.0; - return (vv); -} - -/*----------------------------------------------------------------------*/ -static int loadGearing(pECBMotDriv self) -{ - int status; - double dgear; - int gdec, dec = 0, ratio; - Ecb_pack data; - Z80_reg in, out; - - dec = (int) ObVal(self->driverPar, DEC); - in.c = self->ecbIndex; - dgear = (double) ObVal(self->driverPar, STEPS2DEG);; - - /* Calculate decimals in display and gearing ratio for the ECB system */ - gdec = (int) (1.0 + (log10(dgear - .01))); - if (dec < gdec) - dec = gdec; /* Display does not work with decimals < gdec */ - ratio = (long) (0.5 + dgear * To_ten(6 + 1 - dec)); - - data.result = ratio; - in.b = data.b.byt2; - in.d = data.b.byt1; - in.e = data.b.byt0; - status = ecbExecute(self->ecb, 174, in, &out); - if (status != 1) { - self->errorCode = COMMERROR; - } - - if (ObVal(self->driverPar, ENCODER) == 0) { - in.b = self->ecbIndex; - } else { - in.b = 1; - in.e = (unsigned char) ObVal(self->driverPar, ENCODER); - } - in.d = 0; - in.e = dec; - status = ecbExecute(self->ecb, 173, in, &out); - if (status != 1) { - self->errorCode = COMMERROR; - } - - return 1; -} - -/*----------------------------------------------------------------------*/ -static int downloadECBParam(pECBMotDriv self) -{ - int status, parameter; - unsigned char func_code; - Z80_reg in, out; - - /* - We assume that all parameters have useful values. It is the task of - SetDriverPar to ensure just that! - */ - if ((status = loadAcceleration(self) <= 0)) { - return 0; - } - - if ((status = - loadSpeed(self, ObVal(self->driverPar, STARTSPEED), 6)) <= 0) { - return 0; - } - - if ((status = loadSpeed(self, ObVal(self->driverPar, MAXSPEED), 5)) <= 0) { - return 0; - } - - if ((status = loadSpeed(self, ObVal(self->driverPar, SLOWAUTO), 4)) <= 0) { - return 0; - } - - if ((status = loadSpeed(self, ObVal(self->driverPar, SLOWMAN), 10)) <= 0) { - return 0; - } - - if ((status = loadDelay(self)) <= 0) { - return 0; - } - - if ((status = loadMulti(self)) <= 0) { - return 0; - } - - if ((status = ecbLoadEncoder(self->ecb)) <= 0) { - return 0; - } - - if ((status = loadOffset(self, ObVal(self->driverPar, OFFSET))) <= 0) { - return 0; - } - - - /* - It would be good practice to read the parameters written back - in order to check them. This does not seem to be supported with the - ECB system though. - */ - if (ObVal(self->driverPar, MULT) < 0.) { - self->driverPar[MULT].fVal = .0; - } - - if ((status = loadGearing(self)) <= 0) { - return 0; - } - - return 1; -} - -/*--------------------------------------------------------------------*/ -int degree2Step(pECBMotDriv self, float degree) -{ - double steps; - - steps = degree * ObVal(self->driverPar, STEPS2DEG); - if (ObVal(self->driverPar, ENCODER) > .0) - steps = steps * ObVal(self->driverPar, DEG2STEP); - if (degree < 0) { - steps = -steps; - } - return ((int) steps); -} - -/*---------------------------------------------------------------------- - controlMotor enables or disables the motor, according to flag enable. - This is also used to switch on air cushions and the like. - ------------------------------------------------------------------------*/ -static int controlMotor(pECBMotDriv self, int enable) -{ - int status, delay, control; - Z80_reg in, out; - - /* - nothing to do if we are not in control - */ - control = (int) rint(ObVal(self->driverPar, CONTROL)); - if (!(control & 1)) { - return 1; - } - - delay = (int) rint(ObVal(self->driverPar, DELAY)); - if (enable == 1) { - /* - enabling - */ - in.e = 12; /* 8 + 4 */ - in.b = 11; /* set control signal */ - in.c = (unsigned char) self->ecbIndex; - status = ecbExecute(self->ecb, MOPARA, in, &out); - if (status != 1) { - self->errorCode = COMMERROR; - return 0; - } - /* - wait for air cushions to settle - */ - usleep(delay); - return 1; - } else { - - /* - disable air cushions - */ - in.e = 8; - in.b = 11; /* set control signal */ - in.c = self->ecbIndex; - status = ecbExecute(self->ecb, MOPARA, in, &out); - if (status != 1) { - self->errorCode = COMMERROR; - return 0; - } - usleep(delay); - - /* - clear enable - */ - in.e = 0; - in.b = 11; /* set control signal */ - in.c = self->ecbIndex; - status = ecbExecute(self->ecb, MOPARA, in, &out); - if (status != 1) { - self->errorCode = COMMERROR; - return 0; - } - usleep(delay); - - - return 1; - } -} - -/*-----------------------------------------------------------------------*/ -static int ECBRunTo(void *pData, float newPosition) -{ - pECBMotDriv self = (pECBMotDriv) pData; - long digits = 0; - int status; - float oldValue, diff, steps2degree, backlash; - Ecb_pack data; - Z80_reg in, out; - - assert(self); - - if (mustDownload(self)) { - status = downloadECBParam(self); - if (!status) { - return 0; - } - } - - /* - read old position - */ - status = ECBMOTGetPos(self, &oldValue); - if (status != 1) { - return status; - } - - /* - do not start if there - */ - diff = newPosition - oldValue; - steps2degree = ObVal(self->driverPar, STEPS2DEG); - if (ABS(diff) <= ObVal(self->driverPar, TOLERANCE)) { - return OKOK; - } - /* - if(ABS(diff) <= .5/steps2degree + ObVal(self->driverPar,TOLERANCE)){ - return OKOK; - } - */ - - /* - save restartTarget for backlash handling - */ - self->restartTarget = newPosition; - - /* - enable and push up airy cushions - */ - status = controlMotor(self, 1); - if (status != 1) { - return status; - } - - - /* - write control data - */ - in.d = 0; - if (diff > .0) { - in.d |= 32; /* positive direction */ - } - in.d |= 16; /* interrupts */ - if (rint(ObVal(self->driverPar, RANGE)) == 1.) { - in.d |= 64; /* fast speed */ - } - in.c = (unsigned char) self->ecbIndex; - status = ecbExecute(self->ecb, MOCLOA, in, &out); - if (status != 1) { - self->errorCode = COMMERROR; - return 0; - } - - /* - calculate steps - */ - self->restart = 0; - backlash = ObVal(self->driverPar, BACKLASH); - if (diff < 0) { - diff = -diff; - if (backlash > 0.) { - diff += backlash; - self->restart = 1; - } - } else { - if (backlash < 0.) { - diff -= backlash; - self->restart = 1; - } - } - data.result = degree2Step(self, diff); - - /* - finally start the motor - */ - in.b = data.b.byt2; - in.d = data.b.byt1; - in.e = data.b.byt0; - in.c = (unsigned char) self->ecbIndex; - status = ecbExecute(self->ecb, MOSTEP, in, &out); - if (status != 1) { - self->errorCode = COMMERROR; - return 0; - } - - if (!checkMotorResult(self, out)) { - return 0; - } - - return OKOK; -} - -/*=======================================================================*/ -static int checkStatusResponse(pECBMotDriv self, Z80_reg out) -{ - - if (out.c == '\0') { - if (out.b & 4) { - self->errorCode = ECBINUSE; - } else { - self->errorCode = ECBREADERROR; - } - return HWFault; - } - - if (out.b & 128) { - self->errorCode = ECBMANUELL; - return HWFault; - } else if (out.b & 32) { - return HWBusy; - } else if (out.b & 16) { - self->errorCode = ECBLIMIT; - return HWFault; - } - return HWIdle; -} - -/*----------------------------------------------------------------------*/ -static int ECBGetStatus(void *pData) -{ - pECBMotDriv self = (pECBMotDriv) pData; - Z80_reg in, out; - int status, result; - - assert(self); - - in.c = (unsigned char) self->ecbIndex; - in.b = 12; - status = ecbExecute(self->ecb, MOSTAT, in, &out); - if (status != 1) { - self->errorCode = COMMERROR; - return HWFault; - } - - result = checkStatusResponse(self, out); - if (result == HWFault || result == HWIdle) { - /* - run down airy cushions ........ - */ - controlMotor(self, 0); - } - - /* - take care of backlash..... - */ - if (result == HWIdle && self->restart == 1) { - self->restart = 0; - ECBRunTo(self, self->restartTarget); - return HWBusy; - } - - return result; -} - -/*======================================================================*/ -static void ECBGetError(void *pData, int *iCode, char *buffer, - int bufferlen) -{ - pECBMotDriv self = (pECBMotDriv) pData; - char pBueffel[132]; - - assert(self); - - *iCode = self->errorCode; - switch (self->errorCode) { - case COMMERROR: - strlcpy(buffer, "communication problem with ECB", bufferlen); - break; - case ECBMANUELL: - strlcpy(buffer, "ECB is in manual mode, trying to switch...", - bufferlen); - break; - case ECBINUSE: - strlcpy(buffer, "Power supply is in use", bufferlen); - break; - case ECBINHIBIT: - strlcpy(buffer, "motor is inhibited", bufferlen); - break; - case ECBRUNNING: - strlcpy(buffer, "motor is running", bufferlen); - break; - case ECBSTART: - strlcpy(buffer, "failed to start motor", bufferlen); - break; - case ECBLIMIT: - strlcpy(buffer, "hit limit switch or amplifier error", bufferlen); - break; - default: - strlcpy(buffer, "unidentified error code", bufferlen); - break; - } -} - -/*========================================================================*/ -static int ECBHalt(void *pData) -{ - pECBMotDriv self = (pECBMotDriv) pData; - Z80_reg in, out; - unsigned char par = 2; - - assert(self); - - if (rint(ObVal(self->driverPar, RANGE)) == 1) { - par |= 64; - } - - in.b = 9; - in.e = par; - in.c = (unsigned char) self->ecbIndex; - ecbExecute(self->ecb, MOPARA, in, &out); - self->restart = 0; - return 1; -} - -/*=======================================================================*/ -static int ECBTryAndFixIt(void *pData, int iCode, float fNew) -{ - pECBMotDriv self = (pECBMotDriv) pData; - int result; - Z80_reg in, out; - int i; - - assert(self); - - switch (iCode) { - case ECBMANUELL: - in.d = 1; - ecbExecute(self->ecb, 162, in, &out); - result = MOTREDO; - break; - case ECBRUNNING: - ECBHalt(pData); - self->restart = 0; - for (i = 0; i < 7; i++) { - if (ECBGetStatus(pData) == HWIdle) { - break; - } - SicsWait(1); - } - result = MOTREDO; - break; - case COMMERROR: - ecbClear(self->ecb); - result = MOTREDO; - break; - default: - result = MOTFAIL; - break; - } - return result; -} - -/*=======================================================================*/ -static int ECBGetDriverPar(void *pData, char *name, float *value) -{ - pECBMotDriv self = (pECBMotDriv) pData; - ObPar *par = NULL; - - assert(self); - - if (strcmp(name, "ecbindex") == 0) { - *value = self->ecbIndex; - return 1; - } - /* - * catch the command parameters - */ - if (strcmp(name, "putpos") == 0 || strcmp(name, "download") == 0) { - *value = .0; - return 1; - } - - par = ObParFind(self->driverPar, name); - if (par != NULL) { - *value = par->fVal; - return 1; - } else { - return 0; - } -} - -/*=====================================================================*/ -static float fixAccTime(float newValue) -{ - float corrected, min, diff; - int val, possibleValues[4] = { 500, 1000, 2000, 5000 }, i; - - val = (int) rint(newValue); - min = 9999999.99; - for (i = 0; i < 4; i++) { - diff = val - possibleValues[i]; - if (ABS(diff) < min) { - min = ABS(diff); - corrected = possibleValues[i]; - } - } - return corrected; -} - -/*--------------------------------------------------------------------*/ -static void setDownloadFlag(pECBMotDriv self, int parNumber) -{ - int mustDownload; - - switch (parNumber) { - case CONTROL: - case MULT: - case MULTCHAN: - case ACCTIME: - case ROTDIR: - case STARTSPEED: - case MAXSPEED: - case SLOWAUTO: - case SLOWMAN: - case DELAY: - mustDownload = 1; - break; - default: - mustDownload = 0; - break; - } - - if (mustDownload && (self->driverPar[MULT].fVal == 0)) { - self->driverPar[MULT].fVal = -1.0; - } -} - -/*--------------------------------------------------------------------*/ -static int putMotorPosition(pECBMotDriv self, float newValue) -{ - Z80_reg in, out; - Ecb_pack data; - float oldPos; - int status; - - if (ABS(ObVal(self->driverPar, ENCODER)) > .1) { - status = ECBMOTGetPos(self, &oldPos); - if (status != 1) { - return status; - } - return loadOffset(self, oldPos - newValue); - } else { - data.result = newValue * ObVal(self->driverPar, STEPS2DEG); - in.b = data.b.byt2; - in.d = data.b.byt1; - in.e = data.b.byt0; - in.c = (unsigned char) self->ecbIndex; - status = ecbExecute(self->ecb, 142, in, &out); - if (status != 1) { - self->errorCode = COMMERROR; - return 0; - } - if (!checkMotorResult(self, out)) { - return 0; - } - } - - return 1; -} - -/*---------------------------------------------------------------------*/ -static int ECBSetDriverPar(void *pData, SConnection * pCon, char *name, - float newValue) -{ - pECBMotDriv self = (pECBMotDriv) pData; - int parNumber, speedNumber, actualSpeed, status; - char pBueffel[256]; - float correctedValue; - - assert(self); - - - /* - only managers shall edit these parameters.... - */ - if (!SCMatchRights(pCon, usMugger)) { - return 0; - } - - /* - this is rather a command and forces a parameter download - to the ECB - */ - if (strcmp(name, "download") == 0) { - status = downloadECBParam(self); - if (status != 1) { - ECBGetError(self, &actualSpeed, pBueffel, 254); - SCWrite(pCon, pBueffel, eError); - return status; - } - } - - /* - this is another command and assigns a position to the current - motor place - */ - if (strcmp(name, "putpos") == 0) { - status = putMotorPosition(self, newValue); - if (status != 1) { - ECBGetError(self, &actualSpeed, pBueffel, 254); - SCWrite(pCon, pBueffel, eError); - return status; - } - return 1; - } - - /* - get the parameter number - */ - parNumber = ObParIndex(self->driverPar, name); - if (parNumber < 0) { - return 0; - } - - /* - make these parameters right, at least as far as we can ....... - */ - switch (parNumber) { - case ACCTIME: - correctedValue = fixAccTime(newValue); - break; - case STARTSPEED: - getSpeedIndex(rint(newValue), 1, &actualSpeed); - correctedValue = actualSpeed; - if (correctedValue < 10) { - correctedValue = 10; - } - if (correctedValue > 4400) { - correctedValue = 4400; - } - break; - case MAXSPEED: - getSpeedIndex(rint(newValue), 1, &actualSpeed); - correctedValue = actualSpeed; - break; - case SLOWAUTO: - case SLOWMAN: - getSpeedIndex(rint(newValue), 0, &actualSpeed); - correctedValue = actualSpeed; - if (correctedValue > 500) { - correctedValue = 500; - } - break; - case DELAY: - correctedValue = newValue; - if (correctedValue > 2500) { - correctedValue = 2500; - } - break; - case RANGE: - correctedValue = newValue; - if (correctedValue != 0.0 && correctedValue != 1.0) { - correctedValue = .0; /* slow by default! */ - } - break; - case ENCODER: - if (newValue < 0. || newValue > 3.) { - SCWrite(pCon, "ERROR: encoder numbers can only be 0 - 3", eError); - return 0; - } else if (newValue == 0) { - correctedValue = newValue; - } else { - ecbAssignEncoder(self->ecb, (int) newValue, self->ecbIndex); - correctedValue = newValue; - } - break; - case STEPS2DEG: - case DEG2STEP: - if (ABS(newValue) < .1) { - correctedValue = 1.; - } else { - correctedValue = newValue; - } - break; - case OFFSET: - correctedValue = newValue; - break; - default: - correctedValue = newValue; - break; - } - - if (ABS(correctedValue - newValue) > 0.) { - sprintf(pBueffel, - "WARNING: Illegal value %6.2f verbosely coerced to %6.2f", - newValue, correctedValue); - SCWrite(pCon, pBueffel, eWarning); - } - - ObParSet(self->driverPar, self->name, name, correctedValue, pCon); - - setDownloadFlag(self, parNumber); - - return 1; -} - -/*=========================================================================*/ -static void ECBListPar(void *pData, char *motorName, SConnection * pCon) -{ - pECBMotDriv self = (pECBMotDriv) pData; - char pBueffel[256]; - int i; - - assert(self); - - for (i = 0; i < MAXPAR - 1; i++) { - snprintf(pBueffel, 255, "%s.%s = %f", - motorName, self->driverPar[i].name, self->driverPar[i].fVal); - SCWrite(pCon, pBueffel, eValue); - } -} - -/*========================================================================*/ -static int interpretArguments(pECBMotDriv self, SConnection * pCon, - int argc, char *argv[]) -{ - char pBueffel[256]; - TokenList *pList, *pCurrent; - - pList = SplitArguments(argc, argv); - if (!pList || argc < 4) { - SCWrite(pCon, "ERROR: no arguments to CreateECBMotor", eError); - return 0; - } - pCurrent = pList; - - /* - first should be the name of the ECB to use - */ - if (pCurrent->Type != eText) { - sprintf(pBueffel, "ERROR: expected EDB name, got: %s", pCurrent->text); - DeleteTokenList(pList); - return 0; - } - self->ecb = (pECB) FindCommandData(pServ->pSics, pCurrent->text, "ECB"); - if (!self->ecb) { - sprintf(pBueffel, "ERROR: %s is no ECB controller", pCurrent->text); - SCWrite(pCon, pBueffel, eError); - DeleteTokenList(pList); - return 0; - } - - /* - next the motor number - */ - pCurrent = pCurrent->pNext; - if (pCurrent->Type != eInt) { - sprintf(pBueffel, "ERROR: expected int motor number, got %s", - pCurrent->text); - SCWrite(pCon, pBueffel, eError); - DeleteTokenList(pList); - return 0; - } - self->ecbIndex = pCurrent->iVal; - - /* - next the limits - */ - pCurrent = pCurrent->pNext; - if (pCurrent->Type != eFloat) { - sprintf(pBueffel, "ERROR: expected float type limit, got %s", - pCurrent->text); - SCWrite(pCon, pBueffel, eError); - DeleteTokenList(pList); - return 0; - } - self->fLower = pCurrent->fVal; - pCurrent = pCurrent->pNext; - if (pCurrent->Type != eFloat) { - sprintf(pBueffel, "ERROR: expected float type limit, got %s", - pCurrent->text); - SCWrite(pCon, pBueffel, eError); - DeleteTokenList(pList); - return 0; - } - self->fUpper = pCurrent->fVal; - DeleteTokenList(pList); - - return 1; -} - -/*-----------------------------------------------------------------------*/ -static void initializeParameters(pECBMotDriv self) -{ - ObParInit(self->driverPar, ENCODER, "encoder", 0, usMugger); - ObParInit(self->driverPar, CONTROL, "control", 0, usMugger); - ObParInit(self->driverPar, RANGE, "range", 1, usMugger); - ObParInit(self->driverPar, MULT, "multi", 0, usMugger); - ObParInit(self->driverPar, MULTCHAN, "multchan", 0, usMugger); - ObParInit(self->driverPar, ACCTIME, "acceleration", 500, usMugger); - ObParInit(self->driverPar, ROTDIR, "rotation_dir", 1, usMugger); - ObParInit(self->driverPar, STARTSPEED, "startspeed", 100, usMugger); - ObParInit(self->driverPar, MAXSPEED, "maxspeed", 2000, usMugger); - ObParInit(self->driverPar, SLOWAUTO, "auto", 100, usMugger); - ObParInit(self->driverPar, SLOWMAN, "manuell", 100, usMugger); - ObParInit(self->driverPar, DELAY, "delay", 50, usMugger); - ObParInit(self->driverPar, OFFSET, "offset", 0, usMugger); - ObParInit(self->driverPar, TOLERANCE, "dtolerance", 0., usMugger); - ObParInit(self->driverPar, STEPS2DEG, "step2deg", 1, usMugger); - ObParInit(self->driverPar, DEG2STEP, "step2dig", 0, usMugger); - ObParInit(self->driverPar, BACKLASH, "backlash", 0, usMugger); - ObParInit(self->driverPar, PORT, "port", 0, usMugger); - ObParInit(self->driverPar, DEC, "dec", 1, usMugger); - ObParInit(self->driverPar, MAXPAR - 1, "tueet", -100, -100); /* sentinel! */ -} - -/*=======================================================================*/ -void KillECBMotor(void *pDriver) -{ - int i; - pECBMotDriv self = (pECBMotDriv) pDriver; - - for (i = 0; i < MAXPAR; i++) { - if (self->driverPar[i].name != NULL) { - free(self->driverPar[i].name); - } - } -} - -/*------------------------------------------------------------------------*/ -MotorDriver *CreateECBMotor(SConnection * pCon, int argc, char *argv[]) -{ - pECBMotDriv self = NULL; - - self = (pECBMotDriv) malloc(sizeof(ECBMOTDriv)); - if (self == NULL) { - return NULL; - } - memset(self, 0, sizeof(ECBMOTDriv)); - - if (!interpretArguments(self, pCon, argc, argv)) { - free(self); - return 0; - } - - initializeParameters(self); - - /* - set function pointers - */ - self->GetPosition = ECBMOTGetPos; - self->RunTo = ECBRunTo; - self->GetStatus = ECBGetStatus; - self->GetError = ECBGetError; - self->TryAndFixIt = ECBTryAndFixIt; - self->Halt = ECBHalt; - self->GetDriverPar = ECBGetDriverPar; - self->SetDriverPar = ECBSetDriverPar; - self->ListDriverPar = ECBListPar; - self->KillPrivate = KillECBMotor; - - self->errorCode = 0; - return (MotorDriver *) self; -} diff --git a/ecbdriv.h b/ecbdriv.h deleted file mode 100644 index c83d52a..0000000 --- a/ecbdriv.h +++ /dev/null @@ -1,43 +0,0 @@ -/*------------------------------------------------------------------------ - this is a motor driver for the Risoe motor controllers within the - ECB system. The motor is controlled through functions invoked in the - Z80 processor of the ECB system which is connected through a GPIB - bus to the wider world. This driver has to do a lot of extra things: - - it has to convert from physical values to motor steps. - - Quite a few parameters, such as ramping parameters, - have to be downloaded to the ECB - - Risoe motors may have a virtual encoder or a real encoder. - - The motor may have to control air cushions as well. - - Tricky backlash handling. Backlash handling ensures that a position is - always arrived at from a defined direction. If backlash is applied - a restart flag is set in ECBRunTo. ECBGetStatus checks for that and - causes the motor to drive back to the position actually desired. - - This driver support only P2048a motor controllers, as these are the - only ones which seem to have arrived at PSI. The P1648 and Tridynamic - things are not supported. - - Multiplexed motors: Originally the ECB supported 24 motors. This did - prove to be not enough. Therefore another device called P2234e was - introduced which allowed to run 8 motors from one controller port. In this - case the motor parameters have to be copied to the ECB before - driving the motor. Multiplexing is selected through the parameter MULT. - MULT 0 means no multiplexing, MULT > 0 makes MULT the number of the - motor in the multiplexer. MULT is now also used to flag a download of - parameters to the ECB. In such a case MULT is -1. - - - Some of this code was taken from the tascom driver for the ECB. - - copyright: see file COPYRIGHT - - Mark Koennecke, January 2003 - ---------------------------------------------------------------------------*/ -#ifndef ECBDRIV -#define ECBDRIV - -MotorDriver *CreateECBMotor(SConnection * pCon, int argc, char *argv[]); -void KillECBMotor(void *driver); - -#endif diff --git a/eigermono.c b/eigermono.c new file mode 100644 index 0000000..713b11b --- /dev/null +++ b/eigermono.c @@ -0,0 +1,730 @@ +/** + * This is a special monochromator module for EIGER. EIGER has a ton of + * specialities: + * + * - d2r and d2l must be moved with a2rot in order to maintain the slit + * width a2w + * - When interrupting a2, a2 must be stooped and d2l, d2r aligned afterwards. + * - There is a special drivable a2w which is that slit width. + * - When driving the monochromator energy, then not only curvatures but also + * a monochromator translation must be driven. This needs extra parameters + * - There are two additional virtual motors: a2 and a2w. + * - There are multiple modes of operation: + * * Driving only a2 + * * Driving only a2w + * * Driving the whole monochromator + * + * All this shite is addressed in this module. This is already a second version, + * the old version contained a virtual motor for a2, a2w only. This fell over because + * it did not account for the monochromator translation and a rare bug could not be + * fixed in the old module. + * + * Mark Koennecke, February 2013 + */ +#include +#include +#include +#include +#include + +/* motors */ +#define A1 0 +#define A2ROT 1 +#define D2R 2 +#define D2L 3 +#define MCV 4 +#define MCH 5 +#define MTX 6 +static char *motNames[] = { + "a1", + "a2rot", + "d2r", + "d2l", + "mcv", + "mch", + "mt" + }; + + + +/* states */ +#define IDLE 0 +#define STARTMONO 1 +#define STARTA2 2 +#define STARTA2W 3 +#define WAITING 4 +#define WAITA2 5 +#define WAITSLIT 6 + +/* constants */ +#define RIGHTSIZE -3.5 +#define LEFTSIZE -101.5 + +#define ABS(x) (x < 0 ? -(x) : (x)) +#define MOTPREC .1 +#define NOTSTARTED -100 +/*------------------- module private data structure -------------*/ +typedef struct { + pmaCrystal mono; + ptasUB tasub; + pIDrivable drivs[7]; + void *motData[7]; + double a2wTarget; + double a2Target; + int state; + long waitID; +}eigerMono, *peigerMono; + +/*---------------------------------------------------------------- + This routine can return either OKOK or HWFault when thing + go wrong. However, the return value of Halt is usually ignored! +------------------------------------------------------------------*/ +static int EIMOHalt(void *data) { + pSICSOBJ self = NULL; + int i; + + self = (pSICSOBJ)data; + peigerMono mono = (peigerMono)self->pPrivate; + + for(i = 0; i < 7; i++){ + mono->drivs[i]->Halt(mono->motData[i]); + } + mono->state = WAITA2; + + return OKOK; +} +/*---------------------------------------------------------------- + This routine can return either 1 or 0. 1 means the position can + be reached, 0 NOT + If 0, error shall contain up to errlen characters of information + about which limit was violated +------------------------------------------------------------------*/ +static int EIMOCheckLimits(void *data, float val, + char *error, int errlen){ + pSICSOBJ self = NULL; + + self = (pSICSOBJ)data; + peigerMono mono = (peigerMono)self->pPrivate; + + /* + does not make sense in this context + */ + return 1; +} +/*---------------------------------------------------------------- + This routine can return 0 when a limit problem occurred + OKOK when the motor was successfully started + HWFault when a problem occured starting the device + Possible errors shall be printed to pCon + For real motors, this is supposed to try at least three times + to start the motor in question + val is the value to drive the motor too +------------------------------------------------------------------*/ +static long EIMOSetValue(void *data, SConnection *pCon, float val){ + pSICSOBJ self = NULL; + + self = (pSICSOBJ)data; + peigerMono mono = (peigerMono)self->pPrivate; + + mono->a2Target = val; + mono->state = STARTMONO; + + return 1; +} +/*-----------------------------------------------------------------*/ +static long EIMOSetA2Value(void *data, SConnection *pCon, float val){ + pSICSOBJ self = NULL; + + self = (pSICSOBJ)data; + peigerMono mono = (peigerMono)self->pPrivate; + + mono->a2Target = val; + mono->state = STARTA2; + + return 1; +} +/*----------------------------------------------------------------*/ +static long EIMOSetA2WValue(void *data, SConnection *pCon, float val){ + pSICSOBJ self = NULL; + + self = (pSICSOBJ)data; + peigerMono mono = (peigerMono)self->pPrivate; + + mono->a2wTarget = val; + mono->state = STARTA2W; + + return 1; +} +/*------------------------------------------------------------------------*/ +static void writeMotPos(SConnection * pCon, int silent, char *name, + float val, float target) +{ + char pBueffel[132]; + + if (silent != 1) { + snprintf(pBueffel, 131, "Driving %5s from %8.3f to %8.3f", + name, val, target); + SCWrite(pCon, pBueffel, eLog); + } +} +/*--------------------------------------------------------------------------*/ +static long startTASMotor(pMotor mot, SConnection * pCon, char *name, + double target, int silent, int stopFixed) +{ + float val, fixed, precision = MOTPREC; + long status = NOTSTARTED; + char buffer[132]; + pIDrivable pDriv = NULL; + pDummy dum = NULL; + pDynString mes = NULL; + + + dum = (pDummy)mot; + GetDrivablePosition(mot, pCon,&val); + if(strcmp(dum->pDescriptor->name,"Motor") == 0){ + MotorGetPar(mot,"precision",&precision); + MotorGetPar(mot, "fixed", &fixed); + if (ABS(fixed - 1.0) < .1) { + if(stopFixed == 0){ + snprintf(buffer, 131, "WARNING: %s is FIXED", name); + SCWrite(pCon, buffer, eLog); + } + return NOTSTARTED; + } + } + mot->stopped = 0; + if (ABS(val - target) > precision) { + status = StartDriveTask(mot, pCon, name, (float)target); + if(status < 0){ + SCPrintf(pCon,eLog,"ERROR: failed to drive %s to %f", name, target); + } + /* + to force updates on targets + */ + InvokeNewTarget(pServ->pExecutor, name, target); + writeMotPos(pCon, silent, name, val, target); + return status; + } + return NOTSTARTED; +} +/*---------------------------------------------------------------*/ +static void calcSlitTargets(peigerMono self, float a2, float *d2r, float *d2l) +{ + *d2r = RIGHTSIZE - a2 + self->a2wTarget/2; + *d2l = LEFTSIZE + a2 + self->a2wTarget/2; +} +/*--------------------------------------------------------------*/ +static void startMono(pSICSOBJ self, SConnection *pCon) +{ + int stopFixed = 0; + int silent = 1; + int status; + double curve; + float d2r, d2l, mtx; + peigerMono mono = (peigerMono)self->pPrivate; + hdbValue mta, mtb; + + assert(mono != NULL); + + double val = mono->a2Target; + + + mono->waitID = GetTaskGroupID(pServ->pTasker); + + silent = mono->tasub->silent; + + /* + the meat: A1, A2 + */ + status = startTASMotor((pMotor)mono->motData[A1], pCon, "a1", + val / 2., silent, stopFixed); + if (status < 0 && status != NOTSTARTED) { + SCWrite(pCon,"ERROR: failed to start required motor A1",eLogError); + return; + } + if(status != NOTSTARTED){ + AddTaskToGroup(pServ->pTasker,status, mono->waitID); + } + + status = startTASMotor((pMotor)mono->motData[A2ROT], pCon, "a2", + val, silent,stopFixed); + if (status < 0 && status != NOTSTARTED) { + SCWrite(pCon,"ERROR: failed to start required motor A2",eLogError); + return ; + } + if(status != NOTSTARTED){ + AddTaskToGroup(pServ->pTasker,status, mono->waitID); + } + + /* + the slits + */ + calcSlitTargets(mono,val,&d2r,&d2l); + status = startTASMotor((pMotor)mono->motData[D2R], pCon, "d2r", + d2r, silent,stopFixed); + if (status < 0 && status != NOTSTARTED) { + SCWrite(pCon,"WARNING: monochromator d2r failed to start", eLog); + SCSetInterrupt(pCon,eContinue); + } else { + AddTaskToGroup(pServ->pTasker,status, mono->waitID); + } + status = startTASMotor((pMotor)mono->motData[D2L], pCon, "d2l", + d2l, silent,stopFixed); + if (status < 0 && status != NOTSTARTED) { + SCWrite(pCon,"WARNING: monochromator d2l failed to start", eLog); + SCSetInterrupt(pCon,eContinue); + } else { + AddTaskToGroup(pServ->pTasker,status, mono->waitID); + } + + + /* + curvatures + */ + curve = maCalcHorizontalCurvature(*mono->mono, + val); + status = startTASMotor((pMotor)mono->motData[MCH], pCon, "mch", + curve, silent,stopFixed); + if (status < 0 && status != NOTSTARTED) { + SCWrite(pCon,"WARNING: monochromator horizontal curvature motor failed to start", eLog); + SCSetInterrupt(pCon,eContinue); + }else { + AddTaskToGroup(pServ->pTasker,status,mono->waitID); + } + + curve = maCalcVerticalCurvature(*mono->mono, + val); + status = startTASMotor((pMotor)mono->motData[MCV], pCon, "mcv", + curve, silent,stopFixed); + if (status < 0 && status != NOTSTARTED) { + SCWrite(pCon,"WARNING: monochromator vertical curvature motor failed to start", eLog); + SCSetInterrupt(pCon,eContinue); + } else { + AddTaskToGroup(pServ->pTasker,status, mono->waitID); + } + + + /* + the translation + */ + if(status > 0){ + /* + only run mt when mcv started + */ + SICSHdbGetPar(self,pCon,"MTA",&mta); + SICSHdbGetPar(self,pCon,"MTB",&mtb); + mtx = mta.v.doubleValue + mtb.v.doubleValue*pow(curve,.75); + status = startTASMotor((pMotor)mono->motData[MTX], pCon, "mt", + mtx, silent,stopFixed); + if (status < 0 && status != NOTSTARTED) { + SCWrite(pCon,"WARNING: monochromator translation motor failed to start", eLog); + SCSetInterrupt(pCon,eContinue); + } else { + AddTaskToGroup(pServ->pTasker,status, mono->waitID); + } + } + +} +/*--------------------------------------------------------------*/ +static void startA2(peigerMono mono, SConnection *pCon) +{ + float d2r, d2l; + int status; + + mono->waitID = GetTaskGroupID(pServ->pTasker); + + status = StartDriveTask(mono->motData[A2ROT],pCon, + "a2rot",mono->a2Target); + if(status > 0) { + AddTaskToGroup(pServ->pTasker,status,mono->waitID); + } else { + return; + } + + calcSlitTargets(mono,mono->a2Target,&d2r,&d2l); + status = StartDriveTask(mono->motData[D2R],pCon, + "d2r",d2r); + if(status > 0) { + AddTaskToGroup(pServ->pTasker,status,mono->waitID); + } + status = StartDriveTask(mono->motData[D2L],pCon, + "d2l",d2l); + if(status > 0) { + AddTaskToGroup(pServ->pTasker,status,mono->waitID); + } +} +/*--------------------------------------------------------------*/ +static void startA2W(peigerMono mono, SConnection *pCon) +{ + float d2r, d2l, val; + int status; + + GetDrivablePosition(mono->motData[A2ROT],pCon,&val); + if(val < -99999.99) { + SCWrite(pCon,"ERROR: failed to read a2rot",eError); + return; + } + + mono->waitID = GetTaskGroupID(pServ->pTasker); + calcSlitTargets(mono,val,&d2r,&d2l); + status = StartDriveTask(mono->motData[D2R],pCon, + "d2r",d2r); + if(status > 0) { + AddTaskToGroup(pServ->pTasker,status,mono->waitID); + } + status = StartDriveTask(mono->motData[D2L],pCon, + "d2l",d2l); + if(status > 0) { + AddTaskToGroup(pServ->pTasker,status,mono->waitID); + } +} +/*---------------------------------------------------------------- + Checks the status of a running motor. Possible return values + HWBusy The motor is still running + OKOK or HWIdle when the motor finished driving + HWFault when a hardware problem ocurred + HWPosFault when the hardware cannot reach a position + Errors are duly to be printed to pCon + For real motors CheckStatus again shall try hard to fix any + issues with the motor +------------------------------------------------------------------*/ +static int EIMOCheckStatus(void *data, SConnection *pCon){ + pSICSOBJ self = NULL; + float val; + + self = (pSICSOBJ)data; + peigerMono mono = (peigerMono)self->pPrivate; + + switch(mono->state){ + case IDLE: + return HWIdle; + break; + case STARTMONO: + startMono(self,pCon); + mono->state = WAITING; + break; + case STARTA2: + startA2(mono,pCon); + mono->state = WAITING; + break; + case STARTA2W: + startA2W(mono,pCon); + mono->state = WAITING; + break; + case WAITING: + if(isTaskGroupRunning(pServ->pTasker, mono->waitID)){ + return HWBusy; + } else { + mono->state = IDLE; + return HWIdle; + } + break; + case WAITA2: + /* + after a Halt, wait for A2 to finish, then drive the slits + into an open position + */ + if(isTaskGroupRunning(pServ->pTasker, mono->waitID)){ + return HWBusy; + } else { + GetDrivablePosition(mono->motData[A2ROT], pCon, &val); + if(val > -99999.99){ + mono->a2Target = val; + startA2W(mono,pCon); + } + mono->state = WAITING; + return HWBusy; + } + break; + default: + assert(1); + break; + } + return HWBusy; +} +/*---------------------------------------------------------------- + GetValue is supposed to read a motor position + On errors, -99999999.99 is returned and messages printed to pCon +------------------------------------------------------------------*/ +static float EIMOGetValue(void *data, SConnection *pCon){ + pSICSOBJ self = NULL; + float val = -99999999.99; + + self = (pSICSOBJ)data; + peigerMono mono = (peigerMono)self->pPrivate; + + GetDrivablePosition(mono->motData[A2ROT],pCon,&val); + + return val; +} +/*------------------------------------------------------------------*/ +static float EIMOGetA2WValue(void *data, SConnection *pCon){ + pSICSOBJ self = NULL; + float vall, valr; + double d2ro, d2lo, a2w; + + self = (pSICSOBJ)data; + peigerMono mono = (peigerMono)self->pPrivate; + + GetDrivablePosition(mono->motData[D2R],pCon,&valr); + GetDrivablePosition(mono->motData[D2L],pCon,&vall); + + d2ro = RIGHTSIZE - mono->a2Target; + d2lo = LEFTSIZE + mono->a2Target; + a2w = (d2lo - vall) + (d2ro - valr); + return ABS(a2w); +} +/*---------------------------------------------------------------- + returns NULL on failure, a new datastructure else +------------------------------------------------------------------*/ +static pIDrivable EIMOMakeDrivable(){ + pIDrivable pDriv; + + pDriv = calloc(1,sizeof(IDrivable)); + if(pDriv == NULL){ + return NULL; + } + pDriv->Halt = EIMOHalt; + pDriv->CheckLimits = EIMOCheckLimits; + pDriv->SetValue = EIMOSetValue; + pDriv->CheckStatus = EIMOCheckStatus; + pDriv->GetValue = EIMOGetValue; + + return pDriv; +} + +/*====================================================== + * The A2W Drivable + ======================================================*/ +typedef struct { + pObjectDescriptor pDes; + pIDrivable pDriv; + peigerMono eiger; +}EigerA2W, *eigera2w; + +/*------------------------------------------------------*/ +static void *eigera2wGetInterface(void *data, int iD){ + eigera2w self = NULL; + + self = (eigera2w)data; + if(self != NULL && iD == DRIVEID){ + return self->pDriv; + } else { + return NULL; + } + return NULL; +} +/*---------------------------------------------------------------*/ +static int eigera2wSaveStatus(void *data, char *name, FILE *fd) +{ + eigera2w self = NULL; + + self = (eigera2w)data; + fprintf(fd,"%s target %f\n", name, self->eiger->a2wTarget); + return 1; +} +/*---------------------------------------------------------------- + returns NULL on failure, a new datastructure else +------------------------------------------------------------------*/ +static eigera2w eigera2wMakeObject(peigerMono eiger){ + eigera2w self = NULL; + + self = malloc(sizeof(EigerA2W)); + if(self == NULL){ + return NULL; + } + memset(self,0,sizeof(EigerA2W)); + self->pDes = CreateDescriptor("EigerA2W"); + self->pDriv = CreateDrivableInterface(); + if(self->pDes == NULL || self->pDriv == NULL){ + return NULL; + } + self->eiger = eiger; + + self->pDes->GetInterface = eigera2wGetInterface; + self->pDes->SaveStatus = eigera2wSaveStatus; + self->pDriv->Halt = EIMOHalt; + self->pDriv->CheckLimits = EIMOCheckLimits; + self->pDriv->SetValue = EIMOSetA2WValue; + self->pDriv->CheckStatus = EIMOCheckStatus; + self->pDriv->GetValue = EIMOGetA2WValue; + + return self; +} +/*====================================================== + * The A2 Drivable + ======================================================*/ +static void *eigera2GetInterface(void *data, int iD){ + eigera2w self = NULL; + + self = (eigera2w)data; + if(self != NULL && iD == DRIVEID){ + return self->pDriv; + } else { + return NULL; + } + return NULL; +} +/*---------------------------------------------------------------*/ +static int eigera2SaveStatus(void *data, char *name, FILE *fd) +{ + eigera2w self = NULL; + + self = (eigera2w)data; + fprintf(fd,"%s target %f\n", name, self->eiger->a2Target); + return 1; +} +/*---------------------------------------------------------------- + returns NULL on failure, a new datastructure else +------------------------------------------------------------------*/ +static eigera2w eigera2MakeObject(peigerMono eiger){ + eigera2w self = NULL; + + self = malloc(sizeof(EigerA2W)); + if(self == NULL){ + return NULL; + } + memset(self,0,sizeof(EigerA2W)); + self->pDes = CreateDescriptor("EigerA2"); + self->pDriv = CreateDrivableInterface(); + if(self->pDes == NULL || self->pDriv == NULL){ + return NULL; + } + self->eiger = eiger; + + self->pDes->GetInterface = eigera2GetInterface; + self->pDes->SaveStatus = eigera2SaveStatus; + self->pDriv->Halt = EIMOHalt; + self->pDriv->CheckLimits = EIMOCheckLimits; + self->pDriv->SetValue = EIMOSetA2Value; + self->pDriv->CheckStatus = EIMOCheckStatus; + self->pDriv->GetValue = EIMOGetValue; + + return self; +} +/*---------------------------------------------------------------*/ +int EIMODrivableAction(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + pIDrivable pDriv = NULL; + pDummy pDum; + float value; + char pBuffer[132]; + eigera2w self= NULL; + eigera2w selfe = NULL; + + + assert(pData != NULL); + + if(argc > 1){ + strtolower(argv[1]); + if(strcmp(argv[1],"target") == 0){ + if(strcmp(argv[0],"a2w") == 0 && argc > 2){ + self = (eigera2w)pData; + self->eiger->a2wTarget = atof(argv[2]); + SCSendOK(pCon); + return 1; + } else if (strcmp(argv[0],"a2") == 0 && argc > 2) { + selfe = (eigera2w)pData; + selfe->eiger->a2Target = atof(argv[2]); + SCSendOK(pCon); + return 1; + } + } + } + pDum = (pDummy)pData; + pDriv = (pIDrivable) pDum->pDescriptor->GetInterface(pDum,DRIVEID); + value = pDriv->GetValue(pDum, pCon); + if (value < -9000.) { + snprintf(pBuffer, 131, "ERROR: failed to read %s", argv[0]); + SCWrite(pCon, pBuffer, eError); + return 0; + } + snprintf(pBuffer, 131, "%s = %f", argv[0], value); + SCWrite(pCon, pBuffer, eValue); + return 1; +} +/*-------------------------------------------------------------------------*/ +static int RegisterFunc(pSICSOBJ self, SConnection *pCon, + pHdb commandNode, pHdb par[], int nPar) +{ + peigerMono eiger = (peigerMono)self->pPrivate; + ptasUB tas = NULL; + + /* + install into TAS + */ + tas = (ptasUB)FindCommandData(pServ->pSics,"tasub",NULL); + if(!tas){ + SCWrite(pCon,"ERROR: tasub module not found", eError); + return 0; + } + eiger->mono = &(tas->machine.monochromator); + eiger->tasub = tas; + tas->monoData = self; + tas->mono = EIMOMakeDrivable(); + if(tas->mono == NULL){ + SCWrite(pCon,"ERROR: error initializing EIGER monochromator, tasub now broken", + eError); + return 0; + } + return 1; +} +/*-------------------------------------------------------------------------*/ +int InitEigerMono(SConnection *pCon, SicsInterp *pSics, + void *pData, int argc, char *argv[]) +{ + pIDrivable pDriv = NULL; + eigera2w a2 = NULL; + eigera2w a2w = NULL; + pSICSOBJ pNew = NULL; + peigerMono eiger = NULL; + int i; + ptasUB tas = NULL; + pHdb cmd; + + pNew = MakeSICSOBJ("emo","EigerMonochromator"); + eiger = calloc(1,sizeof(eigerMono)); + if(pNew == NULL || eiger == NULL){ + SCWrite(pCon,"ERROR: out of memory creating Eiger Monochromator",eError); + return 0; + } + pNew->pPrivate = eiger; + cmd = AddSICSHdbPar(pNew->objectNode, "MTA", usMugger, MakeHdbFloat(.0)); + SetHdbProperty(cmd,"__save","true"); + cmd = AddSICSHdbPar(pNew->objectNode, "MTB", usMugger, MakeHdbFloat(3.7)); + SetHdbProperty(cmd,"__save","true"); + AddSICSHdbPar(pNew->objectNode, "register", usMugger, + MakeSICSFunc(RegisterFunc)); + + + /* + get motors + */ + for(i = 0; i < 7; i++){ + pDriv = FindDrivable(pSics,motNames[i]); + if(pDriv == NULL){ + SCPrintf(pCon,eError,"ERROR: %s motor not found", motNames[i]); + return 0; + } + eiger->drivs[i] = pDriv; + eiger->motData[i] = FindCommandData(pSics,motNames[i],NULL); + } + + + + /* + install into interpreter + */ + a2 = eigera2MakeObject(eiger); + a2w = eigera2wMakeObject(eiger); + if(a2 == NULL || a2w == NULL){ + SCWrite(pCon,"ERROR: out of memory creating a2, a2w", eError); + return 0; + } + AddCommand(pSics, "a2", EIMODrivableAction, NULL, a2); + AddCommand(pSics, "a2w", EIMODrivableAction, NULL, a2w); + AddCommand(pSics,"emo", InterInvokeSICSOBJ, KillSICSOBJ, pNew); + + return 1; +} diff --git a/el734dc.c b/el734dc.c deleted file mode 100644 index 9bd404a..0000000 --- a/el734dc.c +++ /dev/null @@ -1,892 +0,0 @@ -/*------------------------------------------------------------------------- - A motor driver for EL734 DC motors as used at SinQ - - - Mark Koennecke, November 1996 - - Original code foe EL734 stepper, modified for DC motors, the - 11-June-1997 Mark Koennecke - - 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 -#include "modriv.h" -#include "hardsup/sinq_prototypes.h" -#include "hardsup/rs232c_def.h" -#include "hardsup/el734_def.h" -#include "hardsup/el734fix.h" -#include -#include -#include - -static int EL734EncodeMSR(char *text, int iLen, - int iMSR, int iOMSR, int iFP, int iFR); - -static int EL734AnalyzeMSR(int iMSR, int iOMSR); - -/* addional error codes for Status-things */ -#define MSRBUSY -40 -#define MSRONLIMIT -41 -#define MSRRUNFAULT -42 -#define MSRPOSFAULT -43 -#define MSRDEADCUSHION -44 -#define MSRHALT -45 -#define MSRSTOP -46 -#define MSROK -47 -#define MSRREF -48 -#define MSRFAULT -49 -/*----------------------------------------------------------------------- - The motor driver structure. Please note that the first set of fields has - be identical with the fields of AbstractModriv in ../modriv.h -------------------------------------------------------------------------*/ -typedef struct __MoDriv { - /* general motor driver interface - fields. REQUIRED! - */ - float fUpper; /* upper limit */ - float fLower; /* lower limit */ - char *name; - int (*GetPosition) (void *self, float *fPos); - int (*RunTo) (void *self, float fNewVal); - int (*GetStatus) (void *self); - void (*GetError) (void *self, int *iCode, char *buffer, int iBufLen); - int (*TryAndFixIt) (void *self, int iError, float fNew); - int (*Halt) (void *self); - int (*GetDriverPar) (void *self, char *name, float *value); - int (*SetDriverPar) (void *self, SConnection * pCon, - char *name, float newValue); - void (*ListDriverPar) (void *self, char *motorName, SConnection * pCon); - void (*KillPrivate) (void *self); - - - /* EL-734 specific fields */ - int iPort; - char *hostname; - int iChannel; - int iMotor; - void *EL734struct; - int iMSR; -} EL734Driv; - -/* --------------------------------------------------------------------------*/ -static int GetPos(void *self, float *fData) -{ - EL734Driv *pDriv; - float fPos; - int iRet, iMSR, iOMSR, iFRC, iFPC, iSS; - - assert(self); - - pDriv = (EL734Driv *) self; - iRet = EL734_GetStatus(&(pDriv->EL734struct), - &iMSR, &iOMSR, &iFPC, &iFRC, &iSS, &fPos); - if (iMSR != 0) { - pDriv->iMSR = iMSR; - } - *fData = fPos; - if (iRet != 1) { - return HWFault; - } else - return OKOK; - -} - -/*--------------------------------------------------------------------------*/ -static int Run(void *self, float fNew) -{ - EL734Driv *pDriv; - int iRet; - - assert(self); - - pDriv = (EL734Driv *) self; - iRet = EL734_MoveNoWait(&(pDriv->EL734struct), fNew); - if (iRet == 1) { - return OKOK; - } else { - return HWFault; - } -} - -/*--------------------------------------------------------------------------- - - EL734Error2Text converts between an EL734 error code to text ------------------------------------------------------------------------------*/ -static void EL734Error2Text(char *pBuffer, int iErr) -{ - strcpy(pBuffer, "ERROR: HW:"); - switch (iErr) { - case EL734__BAD_ADR: - strcat(pBuffer, "EL734__BAD_ADR"); - break; - case EL734__BAD_BIND: - strcat(pBuffer, "EL734__BAD_BIND"); - break; - case EL734__BAD_CMD: - strcat(pBuffer, "EL734__BAD_CMD"); - break; - case EL734__BAD_CONNECT: - strcat(pBuffer, "EL734__BAD_CONNECT"); - break; - case EL734__BAD_FLUSH: - strcat(pBuffer, "EL734__BAD_FLUSH"); - break; - case EL734__BAD_HOST: - strcat(pBuffer, "EL734__BAD_HOST"); - break; - case EL734__BAD_ID: - strcat(pBuffer, "EL734__BAD_ID"); - break; - case EL734__BAD_ILLG: - strcat(pBuffer, "EL734__BAD_ILLG"); - break; - case EL734__BAD_LOC: - strcat(pBuffer, "EL734__BAD_LOC"); - break; - case EL734__BAD_MALLOC: - strcat(pBuffer, "EL734__BAD_MALLOC"); - break; - case EL734__BAD_NOT_BCD: - strcat(pBuffer, "EL734__BAD_NOT_BCD"); - break; - case EL734__BAD_OFL: - strcat(pBuffer, "EL734__BAD_OFL"); - break; - case EL734__BAD_PAR: - strcat(pBuffer, "EL734__BAD_PAR"); - break; - - case EL734__BAD_RECV: - strcat(pBuffer, "EL734__BAD_RECV"); - break; - case EL734__BAD_RECV_NET: - strcat(pBuffer, "EL734__BAD_RECV_NET"); - break; - case EL734__BAD_RECV_PIPE: - strcat(pBuffer, "EL734__BAD_RECV_PIPE"); - break; - case EL734__BAD_RECV_UNKN: - strcat(pBuffer, "EL734__BAD_RECV_UNKN"); - break; - case EL734__BAD_RECVLEN: - strcat(pBuffer, "EL734__BAD_RECVLEN"); - break; - case EL734__BAD_RECV1: - strcat(pBuffer, "EL734__BAD_RECV1"); - break; - case EL734__BAD_RECV1_NET: - strcat(pBuffer, "EL734__BAD_RECV1_NET"); - break; - case EL734__BAD_RECV1_PIPE: - strcat(pBuffer, "EL734__BAD_RECV1_PIPE"); - break; - case EL734__BAD_RNG: - strcat(pBuffer, "EL734__BAD_RNG"); - break; - case EL734__BAD_SEND: - strcat(pBuffer, "EL734__BAD_SEND"); - break; - case EL734__BAD_SEND_PIPE: - strcat(pBuffer, "EL734__BAD_SEND_PIPE"); - break; - case EL734__BAD_SEND_NET: - strcat(pBuffer, "EL734__BAD_SEND_NET"); - break; - case EL734__BAD_SEND_UNKN: - strcat(pBuffer, "EL734__BAD_SEND_UNKN"); - break; - case EL734__BAD_SENDLEN: - strcat(pBuffer, "EL734__BAD_SENDLEN"); - break; - case EL734__BAD_SOCKET: - strcat(pBuffer, "EL734__BAD_SOCKET"); - break; - case EL734__BAD_TMO: - strcat(pBuffer, "EL734__BAD_TMO"); - break; - case EL734__FORCED_CLOSED: - strcat(pBuffer, "EL734__FORCED_CLOSED"); - break; - case EL734__BAD_STP: - strcat(pBuffer, "EL734__BAD_STP"); - break; - case EL734__EMERG_STOP: - strcat(pBuffer, "EL734__EMERG_STOP"); - break; - case EL734__NOT_OPEN: - strcat(pBuffer, "EL734__NOT_OPEN"); - break; - case EL734__BAD_ASYNSRV: - strcat(pBuffer, "EL734__BAD_ASYNSRV"); - break; - default: - sprintf(pBuffer, "Unknown EL734 error %d", iErr); - break; - } -} - -/*-------------------------------------------------------------------------*/ -static void GetErr(void *self, int *iCode, char *buffer, int iBufLen) -{ - EL734Driv *pDriv; - char pBueffel[512]; - int iMSR, iOMSR, iSS; - int iRet, iFPC, iFRC; - int iErr; - float fPos; - char *pErr; - - assert(self); - - /* get EL734 error codes */ - pDriv = (EL734Driv *) self; - EL734_ErrInfo(&pErr, &iMSR, &iOMSR, &iSS); - if (iMSR != 0) { - EL734Error2Text(pBueffel, iMSR); - strlcpy(buffer, pBueffel, (iBufLen - 1)); - *iCode = iMSR; - return; - } else { /* check status flag for addional errors */ - iRet = EL734_GetStatus(&(pDriv->EL734struct), - &iMSR, &iOMSR, &iFPC, &iFRC, &iSS, &fPos); - if (iRet != 1) { /* failure on this one, this has to be handled */ - EL734_ErrInfo(&pErr, &iMSR, &iOMSR, &iSS); - EL734Error2Text(pBueffel, iMSR); - strlcpy(buffer, pBueffel, (iBufLen - 1)); - *iCode = iMSR; - return; - - } else { - /* we really come down to looking at status flags */ - *iCode = EL734EncodeMSR(buffer, iBufLen, iMSR, iOMSR, iFPC, iFRC); - } - } -} - -/* ------------------------------------------------------------------------ - Types of errors possible on EL734: - - Network error: Try reopening connection and redo command. - - Than there are problems which might have to do with a dodgy RS232, - resend command may help - - Some things cannot be fixed. -*/ - -static int FixError(void *self, int iError, float fNew) -{ - EL734Driv *pDriv; - int iRet; - char pBueffel[512]; - int iMSR, iOMSR, iSS; - float fPos; - - assert(self); - pDriv = (EL734Driv *) self; - sprintf(pBueffel, "EL734 : %s %d %d %d Problem:", pDriv->hostname, - pDriv->iPort, pDriv->iChannel, pDriv->iMotor); - - /* get & check MSR flags */ - - - /* check for codes */ - switch (iError) { - case 0: /* no error at all */ - return MOTOK; - case EL734__BAD_ID: /* ID */ - case EL734__BAD_ADR: /* ADR */ - case EL734__BAD_CMD: /* CMD */ - case EL734__BAD_ILLG: /* ILLG */ - case EL734__BAD_PAR: /* PAR */ - case EL734__BAD_TMO: - SICSLogWrite(pBueffel, eHWError); - SICSLogWrite("BAD Command or dodgy RS-232", eHWError); - return MOTREDO; - case EL734__EMERG_STOP: - return MOTFAIL; - case EL734__BAD_RNG: /* RNG */ - case MSRONLIMIT: - SICSLogWrite(pBueffel, eHWError); - SICSLogWrite("Out of Range", eHWError); - return MOTFAIL; - case EL734__BAD_STP: - return MOTFAIL; - break; - case MSRBUSY: - return MOTREDO; - case MSRRUNFAULT: - SICSLogWrite(pBueffel, eHWError); - SICSLogWrite("------ RUN Fault in Controller ---- ", eHWError); - return MOTFAIL; - case MSRPOSFAULT: - SICSLogWrite(pBueffel, eHWError); - SICSLogWrite("------ POS Fault in Controller ---- ", eHWError); - return MOTFAIL; - case MSRDEADCUSHION: - SICSLogWrite(pBueffel, eHWError); - SICSLogWrite("------ Air cushion Fault in Controller ---- ", eHWError); - return MOTFAIL; - case MSRFAULT: - return MOTFAIL; - case MSRHALT: - case MSRSTOP: - return MOTFAIL; - case EL734__FORCED_CLOSED: - case EL734__NOT_OPEN: - iRet = EL734_Open(&(pDriv->EL734struct), pDriv->hostname, - pDriv->iPort, pDriv->iChannel, - pDriv->iMotor, "DCMC EL734"); - if (iRet != 1) { - return MOTFAIL; - } else { - return MOTREDO; - } - break; - case EL734__BAD_LOC: /* LO2 */ - case EL734__BAD_OFL: - EL734_Close(&(pDriv->EL734struct), 0); - iRet = EL734_Open(&(pDriv->EL734struct), pDriv->hostname, - pDriv->iPort, pDriv->iChannel, - pDriv->iMotor, "DCMC EL734"); - if (iRet != 1) { - return MOTFAIL; - } else { - return MOTREDO; - } - break; -/* case EL734__BAD_ASYNSRV: - EL734_Close(&(pDriv->EL734struct),1); - return MOTREDO; - break; -*/ default: - SICSLogWrite(pBueffel, eHWError); - SICSLogWrite("Network problem, trying to reopen", eHWError); - EL734_Close(&(pDriv->EL734struct), 1); - iRet = EL734_Open(&(pDriv->EL734struct), pDriv->hostname, - pDriv->iPort, pDriv->iChannel, - pDriv->iMotor, "DCMC EL734"); - if (iRet != 1) { - return MOTFAIL; - } else { - return MOTREDO; - } - } - -} - -/*--------------------------------------------------------------------------*/ -static int Halt(void *self) -{ - EL734Driv *pDriv; - int iRet; - char pBueffel[80]; - - assert(self); - pDriv = (EL734Driv *) self; - iRet = EL734_Stop(&(pDriv->EL734struct)); - if (iRet != 1) { - return OKOK; - } - return HWFault; -} - -/*--------------------------------------------------------------------------*/ -static int GetStat(void *self) -{ - EL734Driv *pDriv; - float fPos; - int iRet, iMSR, iOMSR, iFRC, iFPC, iSS; - int eRet; - int iTest; - char pBueffel[80]; - - assert(self); - - pDriv = (EL734Driv *) self; - iRet = EL734_GetStatus(&(pDriv->EL734struct), - &iMSR, &iOMSR, &iFPC, &iFRC, &iSS, &fPos); - if (iRet != 1) { - return HWFault; - } - - if (iMSR != 0) { - pDriv->iMSR = iMSR; - } - - iTest = EL734AnalyzeMSR(iMSR, iOMSR); - switch (iTest) { - case MSRDEADCUSHION: - case MSRONLIMIT: - case MSRREF: - case MSRHALT: - case MSRSTOP: - return HWFault; - break; - case MSRRUNFAULT: - case MSRPOSFAULT: - return HWPosFault; - break; - case MSRBUSY: - return HWBusy; - break; - case MSRFAULT: - return HWWarn; - break; - default: - return HWIdle; - break; - } - -} - -/*--------------------------------------------------------------------------*/ -extern void KillEL734(void *pdata); /* from el734driv.c */ -/*---------------------------------------------------------------------------*/ -static EL734Driv *MakeEL734DC(char *hostname, int iPort, int iChannel, - int iMotor) -{ - EL734Driv *pDriv = NULL; - - int iError; - char pBueffel[80]; - char *pErr; - int iRet; - int iDummy; - - /* create a new struct */ - pDriv = (EL734Driv *) malloc(sizeof(EL734Driv)); - if (!pDriv) { - return NULL; - } - memset(pDriv, 0, sizeof(EL734Driv)); - - /* fill in some of the data entered */ - pDriv->hostname = strdup(hostname); - pDriv->iPort = iPort; - pDriv->iChannel = iChannel; - pDriv->iMotor = iMotor; - pDriv->name = strdup("EL734"); - - /* try opening the motor */ - iRet = EL734_Open(&(pDriv->EL734struct), hostname, iPort, - iChannel, iMotor, "DCMC EL734"); - if (iRet != 1) { - EL734_ErrInfo(&pErr, &iError, &iRet, &iDummy); - KillEL734((void *) pDriv); - return NULL; - } - - /* now get the limits */ - EL734_GetLimits(&(pDriv->EL734struct), &(pDriv->fLower), - &(pDriv->fUpper)); - - - /* initialise the function pointers */ - pDriv->GetPosition = GetPos; - pDriv->RunTo = Run; - pDriv->GetError = GetErr; - pDriv->GetStatus = GetStat; - pDriv->Halt = Halt; - pDriv->TryAndFixIt = FixError; - pDriv->KillPrivate = KillEL734; - - return pDriv; -} - -/*-------------------------------------------------------------------------- - interpreting the driver parameters is up to the driver, this below - inplements just this - */ -MotorDriver *CreateEL734DC(SConnection * pCon, int argc, char *argv[]) -{ - EL734Driv *pDriv = NULL; - TokenList *pList = NULL; - TokenList *pCurrent; - char *hostname; - int iPort, iChannel, iMotor; - char pBueffel[512]; - - assert(pCon); - - /* split arguments */ - pList = SplitArguments(argc, argv); - if (!pList) { - SCWrite(pCon, "Error parsing arguments", eError); - return NULL; - } - - /* first must be hostname */ - pCurrent = pList; - if (pCurrent->Type != eText) { - sprintf(pBueffel, "EL734DC: Expected hostname but got --> %s <--", - pCurrent->text); - SCWrite(pCon, pBueffel, eError); - DeleteTokenList(pList); - return NULL; - } - hostname = pCurrent->text; - - /* next should be port */ - pCurrent = pCurrent->pNext; - if (!pCurrent) { - SCWrite(pCon, "EL734DC: Insufficient number of arguments", eError); - DeleteTokenList(pList); - return NULL; - } - if (pCurrent->Type != eInt) { - sprintf(pBueffel, - "EL734DC: Expected Integer as Port number, got --> %s <--", - pCurrent->text); - SCWrite(pCon, pBueffel, eError); - DeleteTokenList(pList); - return NULL; - } - iPort = pCurrent->iVal; - - - /* next should be Channel number */ - pCurrent = pCurrent->pNext; - if (!pCurrent) { - SCWrite(pCon, "EL734DC: Insufficient number of arguments", eError); - DeleteTokenList(pList); - return NULL; - } - if (pCurrent->Type != eInt) { - sprintf(pBueffel, - "EL734DC: Expected Integer as channel number, got --> %s <--", - pCurrent->text); - SCWrite(pCon, pBueffel, eError); - DeleteTokenList(pList); - return NULL; - } - iChannel = pCurrent->iVal; - - /* finally motor number */ - pCurrent = pCurrent->pNext; - if (!pCurrent) { - - SCWrite(pCon, "EL734DC: Insufficient number of arguments", eError); - DeleteTokenList(pList); - return NULL; - } - if (pCurrent->Type != eInt) { - sprintf(pBueffel, - "EL734DC: Expected Integer as motor number, got --> %s <--", - pCurrent->text); - SCWrite(pCon, pBueffel, eError); - DeleteTokenList(pList); - return NULL; - } - iMotor = pCurrent->iVal; - - - /* finally initialize driver */ - pDriv = MakeEL734DC(hostname, iPort, iChannel, iMotor); - if (!pDriv) { - SCWrite(pCon, "EL734DC: error opening motor, check adress", eError); - pDriv = NULL; - } - - /* clean up */ - DeleteTokenList(pList); - return (MotorDriver *) pDriv; -} - -/*------------------------------------------------------------------------- - Stolen from David and modified to return an integer error code as well -*/ -static int EL734EncodeMSR(char *text, int text_len, - int msr, int ored_msr, int fp_cntr, int fr_cntr) -{ - int len; - char my_text[132]; - char my_text_0[32]; - int iRet = 0; - - if (msr == 0) { - ored_msr = ored_msr & ~(MSR__BUSY); /* Zero "Busy" bit */ - if (ored_msr == MSR__OK) { - StrJoin(text, text_len, "Status, MSR = Idle. Positioned OK.", ""); - } else { - if ((ored_msr & MSR__OK) != 0) { - StrJoin(text, text_len, "Status, MSR = Idle. Positioned OK. ", ""); - } else { - StrJoin(text, text_len, "Status, MSR = Idle. ", ""); - } - if ((ored_msr & MSR__REF_OK) != 0) { - StrJoin(my_text, sizeof(my_text), text, ""); - StrJoin(text, text_len, my_text, "Ref. Pos'n OK. "); - } - if ((ored_msr & MSR__LIM_ERR) != 0) { - StrJoin(my_text, sizeof(my_text), text, ""); - StrJoin(text, text_len, my_text, "Limit Switch Problem. "); - iRet = MSRONLIMIT; - } - if ((ored_msr & MSR__AC_FAIL) != 0) { - StrJoin(my_text, sizeof(my_text), text, ""); - StrJoin(text, text_len, my_text, "Air-Cushion Error. "); - iRet = MSRDEADCUSHION; - } - if ((ored_msr & MSR__REF_FAIL) != 0) { - StrJoin(my_text, sizeof(my_text), text, ""); - StrJoin(text, text_len, my_text, "Ref. Pos'n Fail. "); - } - if ((ored_msr & MSR__POS_FAIL) != 0) { - StrJoin(my_text, sizeof(my_text), text, ""); - StrJoin(text, text_len, my_text, "Pos'n Fail. "); - iRet = MSRPOSFAULT; - } - if ((ored_msr & MSR__POS_FAULT) != 0) { - StrJoin(my_text, sizeof(my_text), text, ""); - if (fp_cntr == 1) { - StrJoin(text, text_len, my_text, "1 Pos'n Fault. "); - } else { - sprintf(my_text_0, "%d Pos'n Faults. ", fp_cntr); - StrJoin(text, text_len, my_text, my_text_0); - } - } - if ((ored_msr & MSR__RUN_FAIL) != 0) { - StrJoin(my_text, sizeof(my_text), text, ""); - StrJoin(text, text_len, my_text, "Run Fail. "); - iRet = MSRRUNFAULT; - } - if ((ored_msr & MSR__RUN_FAULT) != 0) { - StrJoin(my_text, sizeof(my_text), text, ""); - if (fr_cntr == 1) { - StrJoin(text, text_len, my_text, "1 Run Fault. "); - } else { - sprintf(my_text_0, "%d Run Faults. ", fr_cntr); - StrJoin(text, text_len, my_text, my_text_0); - } - } - if ((ored_msr & MSR__HALT) != 0) { - StrJoin(my_text, sizeof(my_text), text, ""); - StrJoin(text, text_len, my_text, "Halt. "); - iRet = MSRHALT; - } - if ((ored_msr & MSR__HI_LIM) != 0) { - StrJoin(my_text, sizeof(my_text), text, ""); - StrJoin(text, text_len, my_text, "Hit HiLim. "); - iRet = MSRONLIMIT; - } - if ((ored_msr & MSR__LO_LIM) != 0) { - StrJoin(my_text, sizeof(my_text), text, ""); - StrJoin(text, text_len, my_text, "Hit LoLim. "); - iRet = MSRONLIMIT; - } - if ((ored_msr & MSR__STOPPED) != 0) { - StrJoin(my_text, sizeof(my_text), text, ""); - StrJoin(text, text_len, my_text, "Stopped. "); - iRet = MSRSTOP; - } - } - } else if ((msr & ~(0x2fff)) != 0) { - StrJoin(text, text_len, "Status, MSR = ??", ""); - } else { - sprintf(my_text, "%#x ", msr); - StrJoin(text, text_len, "Status, MSR = ", my_text); - if ((msr & MSR__LIM_ERR) != 0) { - StrJoin(my_text, sizeof(my_text), text, ""); - StrJoin(text, text_len, my_text, "Limit Switch Problem/"); - iRet = MSRONLIMIT; - } - if ((msr & MSR__AC_FAIL) != 0) { - StrJoin(my_text, sizeof(my_text), text, ""); - StrJoin(text, text_len, my_text, "Air-Cushion Error/"); - iRet = MSRDEADCUSHION; - } - if ((msr & MSR__REF_FAIL) != 0) { - StrJoin(my_text, sizeof(my_text), text, ""); - StrJoin(text, text_len, my_text, "Ref. Pos'n Fail/"); - } - if ((msr & MSR__POS_FAIL) != 0) { - StrJoin(my_text, sizeof(my_text), text, ""); - StrJoin(text, text_len, my_text, "Pos'n Fail/"); - iRet = MSRPOSFAULT; - } - if ((msr & MSR__POS_FAULT) != 0) { - StrJoin(my_text, sizeof(my_text), text, ""); - StrJoin(text, text_len, my_text, "Pos'n Fault/"); - } - if ((msr & MSR__RUN_FAIL) != 0) { - StrJoin(my_text, sizeof(my_text), text, ""); - StrJoin(text, text_len, my_text, "Run Fail/"); - iRet = MSRRUNFAULT; - } - if ((msr & MSR__RUN_FAULT) != 0) { - StrJoin(my_text, sizeof(my_text), text, ""); - StrJoin(text, text_len, my_text, "Run Fault/"); - } - if ((msr & MSR__HALT) != 0) { - StrJoin(my_text, sizeof(my_text), text, ""); - StrJoin(text, text_len, my_text, "Halt/"); - iRet = MSRHALT; - } - if ((msr & MSR__HI_LIM) != 0) { - StrJoin(my_text, sizeof(my_text), text, ""); - StrJoin(text, text_len, my_text, "Hit HiLim/"); - iRet = MSRONLIMIT; - } - if ((msr & MSR__LO_LIM) != 0) { - StrJoin(my_text, sizeof(my_text), text, ""); - StrJoin(text, text_len, my_text, "Hit LoLim/"); - iRet = MSRONLIMIT; - } - if ((msr & MSR__STOPPED) != 0) { - StrJoin(my_text, sizeof(my_text), text, ""); - StrJoin(text, text_len, my_text, "Stopped/"); - iRet = MSRSTOP; - } - if ((msr & MSR__REF_OK) != 0) { - StrJoin(my_text, sizeof(my_text), text, ""); - StrJoin(text, text_len, my_text, "Ref. Pos'n OK/"); - } - if ((msr & MSR__OK) != 0) { - StrJoin(my_text, sizeof(my_text), text, ""); - StrJoin(text, text_len, my_text, "OK/"); - } - if ((msr & MSR__BUSY) != 0) { - StrJoin(my_text, sizeof(my_text), text, ""); - StrJoin(text, text_len, my_text, "Busy/"); - } - len = strlen(text); - text[len - 1] = '\0'; - } - return iRet; -} - -/*-------------------------------------------------------------------------*/ -static int EL734AnalyzeMSR(int msr, int ored_msr) -{ - int iRet = 0; - - /* this means the motor is done */ - if (msr == 0) { - ored_msr = ored_msr & ~(MSR__BUSY); /* Zero "Busy" bit */ - if (ored_msr == MSR__OK) { - iRet = MSROK; - } else { - if ((ored_msr & MSR__OK) != 0) { - iRet = MSROK; - } else { - iRet = MSROK; - } - if ((ored_msr & MSR__REF_OK) != 0) { - iRet = MSROK; - } - if ((ored_msr & MSR__LIM_ERR) != 0) { - return MSRONLIMIT; - } - if ((ored_msr & MSR__AC_FAIL) != 0) { - return MSRDEADCUSHION; - } - if ((ored_msr & MSR__REF_FAIL) != 0) { - iRet = MSRREF; - } - if ((ored_msr & MSR__POS_FAIL) != 0) { - return MSRPOSFAULT; - } - if ((ored_msr & MSR__POS_FAULT) != 0) { - iRet = MSRFAULT; - } - if ((ored_msr & MSR__RUN_FAIL) != 0) { - return MSRRUNFAULT; - } - if ((ored_msr & MSR__RUN_FAULT) != 0) { - iRet = MSRFAULT; - } - if ((ored_msr & MSR__HALT) != 0) { - return MSRHALT; - } - if ((ored_msr & MSR__HI_LIM) != 0) { - return MSRONLIMIT; - } - if ((ored_msr & MSR__LO_LIM) != 0) { - return MSRONLIMIT; - } - if ((ored_msr & MSR__STOPPED) != 0) { - return MSRSTOP; - } - } - /* the motor is still fighting along */ - } else if ((msr & ~(0x2fff)) != 0) { - iRet = MSROK; - } else { - if ((msr & MSR__LIM_ERR) != 0) { - return MSRONLIMIT; - } - if ((msr & MSR__AC_FAIL) != 0) { - return MSRDEADCUSHION; - } - if ((msr & MSR__REF_FAIL) != 0) { - iRet = MSRREF; - } - if ((msr & MSR__POS_FAIL) != 0) { - return MSRPOSFAULT; - } - if ((msr & MSR__POS_FAULT) != 0) { - iRet = MSRFAULT; - } - if ((msr & MSR__RUN_FAIL) != 0) { - return MSRRUNFAULT; - } - if ((msr & MSR__RUN_FAULT) != 0) { - iRet = MSRFAULT; - } - if ((msr & MSR__HALT) != 0) { - return MSRHALT; - } - if ((msr & MSR__HI_LIM) != 0) { - return MSRONLIMIT; - } - if ((msr & MSR__LO_LIM) != 0) { - return MSRONLIMIT; - } - if ((msr & MSR__STOPPED) != 0) { - return MSRSTOP; - } - if ((msr & MSR__REF_OK) != 0) { - iRet = MSROK; - } - if ((msr & MSR__OK) != 0) { - iRet = MSROK; - } - if ((msr & MSR__BUSY) != 0) { - iRet = MSRBUSY; - } - } - return iRet; -} diff --git a/el734driv.c b/el734driv.c deleted file mode 100644 index 422bf8b..0000000 --- a/el734driv.c +++ /dev/null @@ -1,905 +0,0 @@ -/*-------------------------------------------------------------------------- - A motor driver for EL734 type motors as used at SinQ - - - Mark Koennecke, November 1996 - - modified for new directory structure, June 2003, Mark Koennecke - - Copyright: - - Labor fuer Neutrnenstreuung - 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 -#include -#include "hardsup/sinq_prototypes.h" -#include "hardsup/rs232c_def.h" -#include "hardsup/el734_def.h" -#include "hardsup/el734fix.h" -#include -#include - -/*----------------------------------------------------------------------- - The motor driver structure. Please note that the first set of fields has - be identical with the fields of AbstractModriv in ../modriv.h -------------------------------------------------------------------------*/ -typedef struct __MoDriv { - /* general motor driver interface - fields. REQUIRED! - */ - float fUpper; /* upper limit */ - float fLower; /* lower limit */ - char *name; - int (*GetPosition) (void *self, float *fPos); - int (*RunTo) (void *self, float fNewVal); - int (*GetStatus) (void *self); - void (*GetError) (void *self, int *iCode, char *buffer, int iBufLen); - int (*TryAndFixIt) (void *self, int iError, float fNew); - int (*Halt) (void *self); - int (*GetDriverPar) (void *self, char *name, float *value); - int (*SetDriverPar) (void *self, SConnection * pCon, - char *name, float newValue); - void (*ListDriverPar) (void *self, char *motorName, SConnection * pCon); - void (*KillPrivate) (void *self); - - - /* EL-734 specific fields */ - int iPort; - char *hostname; - int iChannel; - int iMotor; - void *EL734struct; - int iMSR; -} EL734Driv; - -static int EL734EncodeMSR(char *text, int iLen, - int iMSR, int iOMSR, int iFP, int iFR); - -static int EL734AnalyzeMSR(int iMSR, int iOMSR); - -/* addional error codes for Status-things */ -#define MSRBUSY -40 -#define MSRONLIMIT -41 -#define MSRRUNFAULT -42 -#define MSRPOSFAULT -43 -#define MSRDEADCUSHION -44 -#define MSRHALT -45 -#define MSRSTOP -46 -#define MSROK -47 -#define MSRREF -48 -#define MSRFAULT -49 -/* --------------------------------------------------------------------------*/ -static int GetPos(void *self, float *fData) -{ - EL734Driv *pDriv; - float fPos; - int iRet, iMSR, iOMSR, iFRC, iFPC, iSS; - - assert(self); - - pDriv = (EL734Driv *) self; - iRet = EL734_GetStatus(&(pDriv->EL734struct), - &iMSR, &iOMSR, &iFPC, &iFRC, &iSS, &fPos); - if (iMSR != 0) { - pDriv->iMSR = iMSR; - } - *fData = fPos; - if (iRet != 1) { - return HWFault; - } else - return OKOK; - -} - -/*--------------------------------------------------------------------------*/ -static int Run(void *self, float fNew) -{ - EL734Driv *pDriv; - int iRet; - - assert(self); - - pDriv = (EL734Driv *) self; - iRet = EL734_MoveNoWait(&(pDriv->EL734struct), fNew); - if (iRet == 1) { - return OKOK; - } else { - return HWFault; - } -} - -/*--------------------------------------------------------------------------- - - EL734Error2Text converts between an EL734 error code to text ------------------------------------------------------------------------------*/ -extern char EL734_IllgText[256]; - -static void EL734Error2Text(char *pBuffer, int iErr) -{ - strcpy(pBuffer, "ERROR: HW:"); - switch (iErr) { - case EL734__BAD_ADR: - strcat(pBuffer, "EL734__BAD_ADR"); - break; - case EL734__BAD_BIND: - strcat(pBuffer, "EL734__BAD_BIND"); - break; - case EL734__BAD_CMD: - strcat(pBuffer, "EL734__BAD_CMD"); - break; - case EL734__BAD_CONNECT: - strcat(pBuffer, "EL734__BAD_CONNECT"); - break; - case EL734__BAD_FLUSH: - strcat(pBuffer, "EL734__BAD_FLUSH"); - break; - case EL734__BAD_HOST: - strcat(pBuffer, "EL734__BAD_HOST"); - break; - case EL734__BAD_ID: - strcat(pBuffer, "EL734__BAD_ID"); - break; - case EL734__BAD_ILLG: - strcat(pBuffer, "EL734__BAD_ILLG "); - - strcat(pBuffer, EL734_IllgText); - - break; - case EL734__BAD_LOC: - strcat(pBuffer, "EL734__BAD_LOC"); - break; - case EL734__BAD_MALLOC: - strcat(pBuffer, "EL734__BAD_MALLOC"); - break; - case EL734__BAD_NOT_BCD: - strcat(pBuffer, "EL734__BAD_NOT_BCD"); - break; - case EL734__BAD_OFL: - strcat(pBuffer, "EL734__BAD_OFL"); - break; - case EL734__BAD_PAR: - strcat(pBuffer, "EL734__BAD_PAR"); - break; - - case EL734__BAD_RECV: - strcat(pBuffer, "EL734__BAD_RECV"); - break; - case EL734__BAD_RECV_NET: - strcat(pBuffer, "EL734__BAD_RECV_NET"); - break; - case EL734__BAD_RECV_PIPE: - strcat(pBuffer, "EL734__BAD_RECV_PIPE"); - break; - case EL734__BAD_RECV_UNKN: - strcat(pBuffer, "EL734__BAD_RECV_UNKN"); - break; - case EL734__BAD_RECVLEN: - strcat(pBuffer, "EL734__BAD_RECVLEN"); - break; - case EL734__BAD_RECV1: - strcat(pBuffer, "EL734__BAD_RECV1"); - break; - case EL734__BAD_RECV1_NET: - strcat(pBuffer, "EL734__BAD_RECV1_NET"); - break; - case EL734__BAD_RECV1_PIPE: - strcat(pBuffer, "EL734__BAD_RECV1_PIPE"); - break; - case EL734__BAD_RNG: - strcat(pBuffer, "EL734__BAD_RNG"); - break; - case EL734__BAD_SEND: - strcat(pBuffer, "EL734__BAD_SEND"); - break; - case EL734__BAD_SEND_PIPE: - strcat(pBuffer, "EL734__BAD_SEND_PIPE"); - break; - case EL734__BAD_SEND_NET: - strcat(pBuffer, "EL734__BAD_SEND_NET"); - break; - case EL734__BAD_SEND_UNKN: - strcat(pBuffer, "EL734__BAD_SEND_UNKN"); - break; - case EL734__BAD_SENDLEN: - strcat(pBuffer, "EL734__BAD_SENDLEN"); - break; - case EL734__BAD_SOCKET: - strcat(pBuffer, "EL734__BAD_SOCKET"); - break; - case EL734__BAD_TMO: - strcat(pBuffer, "EL734__BAD_TMO"); - break; - case EL734__FORCED_CLOSED: - strcat(pBuffer, "EL734__FORCED_CLOSED"); - break; - case EL734__BAD_STP: - strcat(pBuffer, "The motor is switched off at the motor controller"); - break; - case EL734__EMERG_STOP: - strcat(pBuffer, "Emergency stop button depressed, please release"); - break; - case EL734__NOT_OPEN: - strcat(pBuffer, "EL734__NOT_OPEN"); - break; - case EL734__BAD_ASYNSRV: - strcat(pBuffer, "EL734__BAD_ASYNSRV"); - break; - default: - sprintf(pBuffer, "Unknown EL734 error %d", iErr); - break; - } -} - -/*-------------------------------------------------------------------------*/ -static void GetErr(void *self, int *iCode, char *buffer, int iBufLen) -{ - EL734Driv *pDriv; - char pBueffel[512]; - int iMSR, iOMSR, iSS; - int iRet, iFPC, iFRC; - int iErr; - float fPos; - char *pErr; - - assert(self); - - /* get EL734 error codes */ - pDriv = (EL734Driv *) self; - EL734_ErrInfo(&pErr, &iMSR, &iOMSR, &iSS); - if (iMSR != 0) { - EL734Error2Text(pBueffel, iMSR); - strlcpy(buffer, pBueffel, (iBufLen - 1)); - *iCode = iMSR; - return; - } else { /* check status flag for addional errors */ - iRet = EL734_GetStatus(&(pDriv->EL734struct), - &iMSR, &iOMSR, &iFPC, &iFRC, &iSS, &fPos); - if (iRet != 1) { /* failure on this one, this has to be handled */ - EL734_ErrInfo(&pErr, &iMSR, &iOMSR, &iSS); - EL734Error2Text(pBueffel, iMSR); - strlcpy(buffer, pBueffel, (iBufLen - 1)); - *iCode = iMSR; - return; - - } else { - /* we really come down to looking at status flags */ - *iCode = EL734EncodeMSR(buffer, iBufLen, iMSR, iOMSR, iFPC, iFRC); - } - } -} - -/* ------------------------------------------------------------------------ - Types of errors possible on EL734: - - Network error: Try reopening connection and redo command. - - Than there are problems which might have to do with a dodgy RS232, - resend command may help - - Some things cannot be fixed. -*/ - -static int FixError(void *self, int iError, float fNew) -{ - EL734Driv *pDriv; - int iRet; - char pBueffel[512]; - int iMSR, iOMSR, iSS; - float fPos; - - assert(self); - pDriv = (EL734Driv *) self; - sprintf(pBueffel, "EL734 : %s %d %d %d Problem:", pDriv->hostname, - pDriv->iPort, pDriv->iChannel, pDriv->iMotor); - - /* get & check MSR flags */ - - - /* check for codes */ - switch (iError) { - case 0: /* no error at all */ - return MOTOK; - case EL734__BAD_ID: /* ID */ - case EL734__BAD_ADR: /* ADR */ - case EL734__BAD_CMD: /* CMD */ - case EL734__BAD_ILLG: /* ILLG */ - case EL734__BAD_PAR: /* PAR */ - case EL734__BAD_TMO: /* timeout */ - SICSLogWrite(pBueffel, eHWError); - SICSLogWrite("BAD Command or dodgy RS-232", eHWError); - return MOTREDO; - case EL734__EMERG_STOP: - return MOTFAIL; - case EL734__BAD_STP: /* motor disabled by switch */ - return MOTFAIL; - break; - case EL734__BAD_RNG: /* RNG */ - case MSRONLIMIT: - SICSLogWrite(pBueffel, eHWError); - SICSLogWrite("Out of Range", eHWError); - return MOTFAIL; - case MSRBUSY: - return MOTREDO; - case MSRRUNFAULT: - SICSLogWrite(pBueffel, eHWError); - SICSLogWrite("------ RUN Fault in Controller ---- ", eHWError); - return MOTFAIL; - case MSRPOSFAULT: - SICSLogWrite(pBueffel, eHWError); - SICSLogWrite("------ POS Fault in Controller ---- ", eHWError); - return MOTFAIL; - case MSRDEADCUSHION: - SICSLogWrite(pBueffel, eHWError); - SICSLogWrite("------ Air cushion Fault in Controller ---- ", eHWError); - return MOTFAIL; - case MSRFAULT: - return MOTFAIL; - case MSRHALT: - case MSRSTOP: - return MOTFAIL; - case EL734__FORCED_CLOSED: - case EL734__NOT_OPEN: - iRet = EL734_Open(&(pDriv->EL734struct), pDriv->hostname, - pDriv->iPort, pDriv->iChannel, - pDriv->iMotor, "STPMC EL734"); - if (iRet != 1) { - return MOTFAIL; - } else { - return MOTREDO; - } - break; - case EL734__BAD_OFL: - case EL734__BAD_LOC: /* LOocal mode */ - EL734_Close(&(pDriv->EL734struct), 0); - iRet = EL734_Open(&(pDriv->EL734struct), pDriv->hostname, - pDriv->iPort, pDriv->iChannel, - pDriv->iMotor, "STPMC EL734"); - if (iRet != 1) { - return MOTFAIL; - } else { - return MOTREDO; - } - break; -/* case EL734__BAD_ASYNSRV: - EL734_Close(&(pDriv->EL734struct),1); - return MOTREDO; -*/ - default: - SICSLogWrite(pBueffel, eHWError); - SICSLogWrite("Network problem, trying to reopen", eHWError); - EL734_Close(&(pDriv->EL734struct), 1); - iRet = EL734_Open(&(pDriv->EL734struct), pDriv->hostname, - pDriv->iPort, pDriv->iChannel, - pDriv->iMotor, "STPMC EL734"); - if (iRet != 1) { - return MOTFAIL; - } else { - return MOTREDO; - } - } - -} - -/*--------------------------------------------------------------------------*/ -static int Halt(void *self) -{ - EL734Driv *pDriv; - int iRet; - char pBueffel[80]; - - assert(self); - pDriv = (EL734Driv *) self; - iRet = EL734_Stop(&(pDriv->EL734struct)); - if (iRet == 1) { - return OKOK; - } - return HWFault; -} - -/*--------------------------------------------------------------------------*/ -static int GetStat(void *self) -{ - EL734Driv *pDriv; - float fPos; - int iRet, iMSR, iOMSR, iFRC, iFPC, iSS; - int eRet; - int iTest; - char pBueffel[80]; - - assert(self); - - pDriv = (EL734Driv *) self; - iRet = EL734_GetStatus(&(pDriv->EL734struct), - &iMSR, &iOMSR, &iFPC, &iFRC, &iSS, &fPos); - if (iRet != 1) { - return HWFault; - } - - if (iMSR != 0) { - pDriv->iMSR = iMSR; - } - - iTest = EL734AnalyzeMSR(iMSR, iOMSR); - switch (iTest) { - case MSRDEADCUSHION: - case MSRONLIMIT: - case MSRREF: - case MSRHALT: - case MSRSTOP: - return HWFault; - break; - case MSRRUNFAULT: - case MSRPOSFAULT: - return HWPosFault; - break; - case MSRBUSY: - return HWBusy; - break; - case MSRFAULT: - return HWWarn; - break; - default: - return HWIdle; - break; - } -} - -/*--------------------------------------------------------------------------*/ -void KillEL734(void *self) -{ - EL734Driv *pDriv; - - assert(self); - pDriv = (EL734Driv *) self; - - EL734_Close(&(pDriv->EL734struct), 0); - if (pDriv->hostname) - free(pDriv->hostname); -} - -/*---------------------------------------------------------------------------*/ -static EL734Driv *MakeEL734(char *hostname, int iPort, int iChannel, - int iMotor) -{ - EL734Driv *pDriv = NULL; - - int iError; - char pBueffel[80]; - char *pErr; - int iRet; - int iDummy; - - /* create a new struct */ - pDriv = (EL734Driv *) malloc(sizeof(EL734Driv)); - if (!pDriv) { - return NULL; - } - memset(pDriv, 0, sizeof(EL734Driv)); - - /* fill in some of the data entered */ - pDriv->hostname = strdup(hostname); - pDriv->iPort = iPort; - pDriv->iChannel = iChannel; - pDriv->iMotor = iMotor; - pDriv->name = strdup("EL734"); - - /* try opening the motor */ - iRet = EL734_Open(&(pDriv->EL734struct), hostname, iPort, - iChannel, iMotor, "STPMC EL734"); - if (iRet != 1) { - EL734_ErrInfo(&pErr, &iError, &iRet, &iDummy); - KillEL734((void *) pDriv); - return NULL; - } - - /* now get the limits */ - EL734_GetLimits(&(pDriv->EL734struct), &(pDriv->fLower), - &(pDriv->fUpper)); - - - /* initialise the function pointers */ - pDriv->GetPosition = GetPos; - pDriv->RunTo = Run; - pDriv->GetError = GetErr; - pDriv->GetStatus = GetStat; - pDriv->Halt = Halt; - pDriv->TryAndFixIt = FixError; - pDriv->KillPrivate = KillEL734; - - return pDriv; -} - -/*-------------------------------------------------------------------------- - interpreting the driver parameters is up to the driver, this below - inplements just this - */ -MotorDriver *CreateEL734(SConnection * pCon, int argc, char *argv[]) -{ - EL734Driv *pDriv = NULL; - TokenList *pList = NULL; - TokenList *pCurrent; - char *hostname; - int iPort, iChannel, iMotor; - char pBueffel[512]; - - assert(pCon); - - /* split arguments */ - pList = SplitArguments(argc, argv); - if (!pList) { - SCWrite(pCon, "Error parsing arguments", eError); - return NULL; - } - - /* first must be hostname */ - pCurrent = pList; - if (pCurrent->Type != eText) { - sprintf(pBueffel, "EL734: Expected hostname but got --> %s <--", - pCurrent->text); - SCWrite(pCon, pBueffel, eError); - DeleteTokenList(pList); - return NULL; - } - hostname = pCurrent->text; - - /* next should be port */ - pCurrent = pCurrent->pNext; - if (!pCurrent) { - SCWrite(pCon, "EL734: Insufficient number of arguments", eError); - DeleteTokenList(pList); - return NULL; - } - if (pCurrent->Type != eInt) { - sprintf(pBueffel, - "EL734: Expected Integer as Port number, got --> %s <--", - pCurrent->text); - SCWrite(pCon, pBueffel, eError); - DeleteTokenList(pList); - return NULL; - } - iPort = pCurrent->iVal; - - - /* next should be Channel number */ - pCurrent = pCurrent->pNext; - if (!pCurrent) { - SCWrite(pCon, "EL734: Insufficient number of arguments", eError); - DeleteTokenList(pList); - return NULL; - } - if (pCurrent->Type != eInt) { - sprintf(pBueffel, - "EL734: Expected Integer as channel number, got --> %s <--", - pCurrent->text); - SCWrite(pCon, pBueffel, eError); - DeleteTokenList(pList); - return NULL; - } - iChannel = pCurrent->iVal; - - /* finally motor number */ - pCurrent = pCurrent->pNext; - if (!pCurrent) { - - SCWrite(pCon, "EL734: Insufficient number of arguments", eError); - DeleteTokenList(pList); - return NULL; - } - if (pCurrent->Type != eInt) { - sprintf(pBueffel, - "EL734: Expected Integer as motor number, got --> %s <--", - pCurrent->text); - SCWrite(pCon, pBueffel, eError); - DeleteTokenList(pList); - return NULL; - } - iMotor = pCurrent->iVal; - - - /* finally initialize driver */ - pDriv = MakeEL734(hostname, iPort, iChannel, iMotor); - if (!pDriv) { - SCWrite(pCon, "EL734: error opening motor, check adress", eError); - pDriv = NULL; - } - - /* clean up */ - DeleteTokenList(pList); - return (MotorDriver *) pDriv; -} - -/*------------------------------------------------------------------------- - Stolen from David and modified to return an integer error code as well -*/ -static int EL734EncodeMSR(char *text, int text_len, - int msr, int ored_msr, int fp_cntr, int fr_cntr) -{ - int len; - char my_text[132]; - char my_text_0[32]; - int iRet = 0; - - if (msr == 0) { - ored_msr = ored_msr & ~(MSR__BUSY); /* Zero "Busy" bit */ - if (ored_msr == MSR__OK) { - StrJoin(text, text_len, "Status, MSR = Idle. Positioned OK.", ""); - } else { - if ((ored_msr & MSR__OK) != 0) { - StrJoin(text, text_len, "Status, MSR = Idle. Positioned OK. ", ""); - } else { - StrJoin(text, text_len, "Status, MSR = Idle. ", ""); - } - if ((ored_msr & MSR__REF_OK) != 0) { - StrJoin(my_text, sizeof(my_text), text, ""); - StrJoin(text, text_len, my_text, "Ref. Pos'n OK. "); - } - if ((ored_msr & MSR__LIM_ERR) != 0) { - StrJoin(my_text, sizeof(my_text), text, ""); - StrJoin(text, text_len, my_text, "Limit Switch Problem. "); - iRet = MSRONLIMIT; - } - if ((ored_msr & MSR__AC_FAIL) != 0) { - StrJoin(my_text, sizeof(my_text), text, ""); - StrJoin(text, text_len, my_text, "Air-Cushion Error. "); - iRet = MSRDEADCUSHION; - } - if ((ored_msr & MSR__REF_FAIL) != 0) { - StrJoin(my_text, sizeof(my_text), text, ""); - StrJoin(text, text_len, my_text, "Ref. Pos'n Fail. "); - } - if ((ored_msr & MSR__POS_FAIL) != 0) { - StrJoin(my_text, sizeof(my_text), text, ""); - StrJoin(text, text_len, my_text, "Pos'n Fail. "); - iRet = MSRPOSFAULT; - } - if ((ored_msr & MSR__POS_FAULT) != 0) { - StrJoin(my_text, sizeof(my_text), text, ""); - if (fp_cntr == 1) { - StrJoin(text, text_len, my_text, "1 Pos'n Fault. "); - } else { - sprintf(my_text_0, "%d Pos'n Faults. ", fp_cntr); - StrJoin(text, text_len, my_text, my_text_0); - } - } - if ((ored_msr & MSR__RUN_FAIL) != 0) { - StrJoin(my_text, sizeof(my_text), text, ""); - StrJoin(text, text_len, my_text, "Run Fail. "); - iRet = MSRRUNFAULT; - } - if ((ored_msr & MSR__RUN_FAULT) != 0) { - StrJoin(my_text, sizeof(my_text), text, ""); - if (fr_cntr == 1) { - StrJoin(text, text_len, my_text, "1 Run Fault. "); - } else { - sprintf(my_text_0, "%d Run Faults. ", fr_cntr); - StrJoin(text, text_len, my_text, my_text_0); - } - } - if ((ored_msr & MSR__HALT) != 0) { - StrJoin(my_text, sizeof(my_text), text, ""); - StrJoin(text, text_len, my_text, "Halt. "); - iRet = MSRHALT; - } - if ((ored_msr & MSR__HI_LIM) != 0) { - StrJoin(my_text, sizeof(my_text), text, ""); - StrJoin(text, text_len, my_text, "Hit HiLim. "); - iRet = MSRONLIMIT; - } - if ((ored_msr & MSR__LO_LIM) != 0) { - StrJoin(my_text, sizeof(my_text), text, ""); - StrJoin(text, text_len, my_text, "Hit LoLim. "); - iRet = MSRONLIMIT; - } - if ((ored_msr & MSR__STOPPED) != 0) { - StrJoin(my_text, sizeof(my_text), text, ""); - StrJoin(text, text_len, my_text, "Stopped. "); - iRet = MSRSTOP; - } - } - } else if ((msr & ~(0x2fff)) != 0) { - StrJoin(text, text_len, "Status, MSR = ??", ""); - } else { - sprintf(my_text, "%#x ", msr); - StrJoin(text, text_len, "Status, MSR = ", my_text); - if ((msr & MSR__LIM_ERR) != 0) { - StrJoin(my_text, sizeof(my_text), text, ""); - StrJoin(text, text_len, my_text, "Limit Switch Problem/"); - iRet = MSRONLIMIT; - } - if ((msr & MSR__AC_FAIL) != 0) { - StrJoin(my_text, sizeof(my_text), text, ""); - StrJoin(text, text_len, my_text, "Air-Cushion Error/"); - iRet = MSRDEADCUSHION; - } - if ((msr & MSR__REF_FAIL) != 0) { - StrJoin(my_text, sizeof(my_text), text, ""); - StrJoin(text, text_len, my_text, "Ref. Pos'n Fail/"); - } - if ((msr & MSR__POS_FAIL) != 0) { - StrJoin(my_text, sizeof(my_text), text, ""); - StrJoin(text, text_len, my_text, "Pos'n Fail/"); - iRet = MSRPOSFAULT; - } - if ((msr & MSR__POS_FAULT) != 0) { - StrJoin(my_text, sizeof(my_text), text, ""); - StrJoin(text, text_len, my_text, "Pos'n Fault/"); - } - if ((msr & MSR__RUN_FAIL) != 0) { - StrJoin(my_text, sizeof(my_text), text, ""); - StrJoin(text, text_len, my_text, "Run Fail/"); - iRet = MSRRUNFAULT; - } - if ((msr & MSR__RUN_FAULT) != 0) { - StrJoin(my_text, sizeof(my_text), text, ""); - StrJoin(text, text_len, my_text, "Run Fault/"); - } - if ((msr & MSR__HALT) != 0) { - StrJoin(my_text, sizeof(my_text), text, ""); - StrJoin(text, text_len, my_text, "Halt/"); - iRet = MSRHALT; - } - if ((msr & MSR__HI_LIM) != 0) { - StrJoin(my_text, sizeof(my_text), text, ""); - StrJoin(text, text_len, my_text, "Hit HiLim/"); - iRet = MSRONLIMIT; - } - if ((msr & MSR__LO_LIM) != 0) { - StrJoin(my_text, sizeof(my_text), text, ""); - StrJoin(text, text_len, my_text, "Hit LoLim/"); - iRet = MSRONLIMIT; - } - if ((msr & MSR__STOPPED) != 0) { - StrJoin(my_text, sizeof(my_text), text, ""); - StrJoin(text, text_len, my_text, "Stopped/"); - iRet = MSRSTOP; - } - if ((msr & MSR__REF_OK) != 0) { - StrJoin(my_text, sizeof(my_text), text, ""); - StrJoin(text, text_len, my_text, "Ref. Pos'n OK/"); - } - if ((msr & MSR__OK) != 0) { - StrJoin(my_text, sizeof(my_text), text, ""); - StrJoin(text, text_len, my_text, "OK/"); - } - if ((msr & MSR__BUSY) != 0) { - StrJoin(my_text, sizeof(my_text), text, ""); - StrJoin(text, text_len, my_text, "Busy/"); - } - len = strlen(text); - text[len - 1] = '\0'; - } - return iRet; -} - -/*-------------------------------------------------------------------------*/ -static int EL734AnalyzeMSR(int msr, int ored_msr) -{ - int iRet = 0; - - /* this means the motor is done */ - if (msr == 0) { - ored_msr = ored_msr & ~(MSR__BUSY); /* Zero "Busy" bit */ - if (ored_msr == MSR__OK) { - iRet = MSROK; - } else { - if ((ored_msr & MSR__OK) != 0) { - iRet = MSROK; - } else { - iRet = MSROK; - } - if ((ored_msr & MSR__REF_OK) != 0) { - iRet = MSROK; - } - if ((ored_msr & MSR__LIM_ERR) != 0) { - return MSRONLIMIT; - } - if ((ored_msr & MSR__AC_FAIL) != 0) { - return MSRDEADCUSHION; - } - if ((ored_msr & MSR__REF_FAIL) != 0) { - iRet = MSRREF; - } - if ((ored_msr & MSR__POS_FAIL) != 0) { - return MSRPOSFAULT; - } - if ((ored_msr & MSR__POS_FAULT) != 0) { - iRet = MSRFAULT; - } - if ((ored_msr & MSR__RUN_FAIL) != 0) { - return MSRRUNFAULT; - } - if ((ored_msr & MSR__RUN_FAULT) != 0) { - iRet = MSRFAULT; - } - if ((ored_msr & MSR__HALT) != 0) { - return MSRHALT; - } - if ((ored_msr & MSR__HI_LIM) != 0) { - return MSRONLIMIT; - } - if ((ored_msr & MSR__LO_LIM) != 0) { - return MSRONLIMIT; - } - if ((ored_msr & MSR__STOPPED) != 0) { - return MSRSTOP; - } - } - /* the motor is still fighting along */ - } else if ((msr & ~(0x2fff)) != 0) { - iRet = MSROK; - } else { - if ((msr & MSR__LIM_ERR) != 0) { - return MSRONLIMIT; - } - if ((msr & MSR__AC_FAIL) != 0) { - return MSRDEADCUSHION; - } - if ((msr & MSR__REF_FAIL) != 0) { - iRet = MSRREF; - } - if ((msr & MSR__POS_FAIL) != 0) { - return MSRPOSFAULT; - } - if ((msr & MSR__POS_FAULT) != 0) { - iRet = MSRFAULT; - } - if ((msr & MSR__RUN_FAIL) != 0) { - return MSRRUNFAULT; - } - if ((msr & MSR__RUN_FAULT) != 0) { - iRet = MSRFAULT; - } - if ((msr & MSR__HALT) != 0) { - return MSRHALT; - } - if ((msr & MSR__HI_LIM) != 0) { - return MSRONLIMIT; - } - if ((msr & MSR__LO_LIM) != 0) { - return MSRONLIMIT; - } - if ((msr & MSR__STOPPED) != 0) { - return MSRSTOP; - } - if ((msr & MSR__REF_OK) != 0) { - iRet = MSROK; - } - if ((msr & MSR__OK) != 0) { - iRet = MSROK; - } - if ((msr & MSR__BUSY) != 0) { - iRet = MSRBUSY; - } - } - return iRet; -} diff --git a/julcho.c b/julcho.c deleted file mode 100644 index 673f9ab..0000000 --- a/julcho.c +++ /dev/null @@ -1,1385 +0,0 @@ -/** -* This is the implementation of a chopper driver for the MARS Chopper cascade -* as provided by the Forschungszentrum Juelich. The original host protocol -* from Juelich has been changed on our request; Gerd Theidel did some of that -* Turbo Pascal coding. -* -* copyright: see file COPYRIGHT -* -* Mark Koennecke, June-July 2006 -* -* Parameter updating is to slow, therefore it happens in two groups now: -* actspeed and actphase are requested more frequently, so they go separate -* -* Mark Koennecke, October 2006 -*/ -#include -#include -#include -#include -#include -#define CHOCOINTERNAL -#include -#include -#include -#include -#include -#include -/*----------------------------- error codes -----------------------------*/ -#define FRAMEERROR -801 -#define CKERROR -802 -#define BADCOMMAND -803 -#define WRONGNOPAR -804 -#define ILLPAR -805 -#define PARRANGE -806 -#define BADERR -807 -#define BADREPLY -808 -#define NOTPAR -809 -#define BADTEXT -810 -#define ROPAR -811 -#define NOMEM -812 -#define HALT -813 -/*--------------------- update flags -------------------------------------*/ -#define ALL 1 -#define SPEED 2 -/*--------------------- wait after set -----------------------------------*/ -#define STWAIT 5 -/*------------------------- chopper internal names -----------------------*/ -#define CH1N "snail" -#define CH2N "master" -#define CH3N "rabbit" -#define CH4N "four" -#define CH5N "five" -/*=============== Juelich chopper private data structure ================== */ -typedef struct { - prs232 controller; - pHdb parNode; - int errorCode; - time_t lastUpdate; - int updateIntervall; - int speedUpdate; - int halt; -} JulCho, *pJulCho; -/*------------------------------------------------------------------------*/ -typedef struct { - char prefix[10]; - char postfix[10]; - char comCode[10]; - pJulCho pDriv; -} julCBData, *pJulCBData; -/*================= internal support functions ============================*/ -static int calculateJulCheckSum(char *realCommand) -{ - int i, checkSum = 0; - - for (i = 1; i < strlen(realCommand); i++) { - checkSum += (int) realCommand[i]; - } - return checkSum; -} - -/*------------------------------------------------------------------------*/ -static int testJulError(char *reply) -{ - char *pPtr = NULL, *pEnd = NULL; - int code, status; - - if (strstr(reply, "ERR") == NULL) { - return 1; - } - pPtr = &reply[9]; /* #ERR:CCC: */ - pEnd = strchr(pPtr, '{'); - if (pEnd == NULL) { - return BADERR; - } - *pEnd = '\0'; - code = atoi(pPtr); - switch (code) { - case 1: - status = FRAMEERROR; - break; - case 2: - status = CKERROR; - break; - case 3: - status = BADCOMMAND; - break; - case 4: - status = WRONGNOPAR; - break; - case 5: - status = ILLPAR; - break; - case 6: - status = PARRANGE; - break; - default: - status = BADERR; - break; - } - return status; -} - -/*------------------------------------------------------------------------*/ -static void readClean(prs232 controller) -{ - char buffer[1024]; - int count = 0, bufSize; - - while (availableRS232(controller) == 1 && count < 20) { - bufSize = 1024; - readRS232(controller, buffer, &bufSize); - } -} - -/*-------------------------------------------------------------------------*/ -static int JulChoTransact(pJulCho self, char *command, - char *reply, int replyLen) -{ - int status, length, checkSum; - char realCommand[1024], checkString[30]; - - strcpy(realCommand, "#"); - strcat(realCommand, command); - - checkSum = calculateJulCheckSum(realCommand); - snprintf(checkString, 30, "{%d}$", checkSum); - strcat(realCommand, checkString); - - /* - * clean the socket: If someone whacked the keyboard and the - * controller did not repsond, the line might be full of shit - */ - readClean(self->controller); - - status = - transactRS232(self->controller, realCommand, strlen(realCommand), - (void *) reply, replyLen); - if (status <= 0) { - return status; - } - - status = testJulError(reply); - - return status; -} - -/*---------------------------------------------------------------------------*/ -static hdbCallbackReturn JulChoSetCallback(pHdb node, void *userData, - pHdbMessage message) -{ - pJulCBData cbData = NULL; - char command[256], reply[256]; - pHdbDataMessage mm = NULL; - int status; - - cbData = (pJulCBData) userData; - if (cbData == NULL) { - return hdbContinue; - } - - /* - * Is this for us? - */ - mm = GetHdbSetMessage(message); - if (mm == NULL) { - return hdbContinue; - } - - - if (mm->v->dataType == HIPINT) { - snprintf(command, 255, "%s %s%d%s", cbData->comCode, cbData->prefix, - (int) mm->v->v.intValue, cbData->postfix); - } else if (mm->v->dataType == HIPFLOAT) { - snprintf(command, 255, "%s %s%f%s", cbData->comCode, cbData->prefix, - (float) mm->v->v.doubleValue, cbData->postfix); - } else { - assert(0); /* this is a programming error */ - } - - cbData->pDriv->halt = 0; - status = JulChoTransact(cbData->pDriv, command, reply, 255); - if (status < 0) { - cbData->pDriv->errorCode = status; - return hdbAbort; - } - return hdbContinue; -} - -/*------------------------------------------------------------------------------*/ -static pHdbCallback MakeJulChoSetCallback(pJulCho driv, char *command, - char *prefix, char *postfix) -{ - pJulCBData cbData = NULL; - pHdbCallback hdbCB = NULL; - - hdbCB = malloc(sizeof(hdbCallback)); - cbData = malloc(sizeof(julCBData)); - if (cbData == NULL || hdbCB == NULL) { - return NULL; - } - cbData->pDriv = driv; - strlcpy(cbData->comCode, command, 9); - strlcpy(cbData->prefix, prefix, 9); - strlcpy(cbData->postfix, postfix, 9); - hdbCB->next = NULL; - hdbCB->previous = NULL; - hdbCB->killFunc = free; - hdbCB->userCallback = JulChoSetCallback; - hdbCB->userData = cbData; - return hdbCB; -} - -/*--------------------------------------------------------------------------*/ -static int splitJulChoInt(char *reply, int data[5]) -{ - char number[10]; - char *pPtr = NULL; - int count = 0; - - pPtr = stptok(reply, number, 10, ":"); - pPtr = stptok(pPtr, number, 10, ":"); - while (pPtr != NULL && count < 5) { - data[count] = atoi(number); - count++; - pPtr = stptok(pPtr, number, 10, ":"); - } - if (count < 4) { - return 0; - } - return 1; -} - -/*--------------------------------------------------------------------------*/ -static int splitJulChoDouble(char *reply, double data[5]) -{ - char number[10]; - char *pPtr = NULL; - int count = 0; - - pPtr = stptok(reply, number, 10, ":"); - pPtr = stptok(pPtr, number, 10, ":"); - while (pPtr != NULL && count < 5) { - data[count] = (double) atof(number); - count++; - pPtr = stptok(pPtr, number, 10, ":"); - } - if (count < 4) { - return 0; - } - return 1; -} - -/*--------------------------------------------------------------------------*/ -static int setJulChoIntPar(pHdb root, char *par, int data[5]) -{ - char path[256]; - hdbValue v; - pHdb node = NULL; - - memset(&v, 0, sizeof(hdbValue)); - v.dataType = HIPINT; - - snprintf(path, 255, "%s/%s", CH1N, par); - node = GetHipadabaNode(root, path); - assert(node != NULL); - v.v.intValue = (long) data[0]; - UpdateHipadabaPar(node, v, NULL); - - snprintf(path, 255, "%s/%s", CH2N, par); - node = GetHipadabaNode(root, path); - assert(node != NULL); - v.v.intValue = (long) data[1]; - UpdateHipadabaPar(node, v, NULL); - - snprintf(path, 255, "%s/%s", CH3N, par); - node = GetHipadabaNode(root, path); - assert(node != NULL); - v.v.intValue = (long) data[2]; - UpdateHipadabaPar(node, v, NULL); - - snprintf(path, 255, "%s/%s", CH4N, par); - node = GetHipadabaNode(root, path); - assert(node != NULL); - v.v.intValue = (long) data[3]; - UpdateHipadabaPar(node, v, NULL); - - snprintf(path, 255, "%s/%s", CH5N, par); - node = GetHipadabaNode(root, path); - assert(node != NULL); - v.v.intValue = (long) data[4]; - UpdateHipadabaPar(node, v, NULL); - - return 1; -} - -/*--------------------------------------------------------------------------*/ -static int setJulChoDoublePar(pHdb root, char *par, double data[5]) -{ - char path[256]; - hdbValue v; - pHdb node = NULL; - - memset(&v, 0, sizeof(hdbValue)); - v.dataType = HIPFLOAT; - - snprintf(path, 255, "%s/%s", CH1N, par); - node = GetHipadabaNode(root, path); - assert(node != NULL); - v.v.doubleValue = data[0]; - UpdateHipadabaPar(node, v, NULL); - - snprintf(path, 255, "%s/%s", CH2N, par); - node = GetHipadabaNode(root, path); - assert(node != NULL); - v.v.doubleValue = data[1]; - UpdateHipadabaPar(node, v, NULL); - - snprintf(path, 255, "%s/%s", CH3N, par); - node = GetHipadabaNode(root, path); - assert(node != NULL); - v.v.doubleValue = data[2]; - UpdateHipadabaPar(node, v, NULL); - - snprintf(path, 255, "%s/%s", CH4N, par); - node = GetHipadabaNode(root, path); - assert(node != NULL); - v.v.doubleValue = data[3]; - UpdateHipadabaPar(node, v, NULL); - - snprintf(path, 255, "%s/%s", CH5N, par); - node = GetHipadabaNode(root, path); - assert(node != NULL); - v.v.doubleValue = data[4]; - UpdateHipadabaPar(node, v, NULL); - - return 1; -} - -/*--------------------------------------------------------------------------*/ -static void updateJulChoFlag(pHdb node, char *choppername, char *parname, - int code, int mask) -{ - char path[256]; - hdbValue v; - pHdb target = NULL; - - v.dataType = HIPINT; - snprintf(path, 255, "%s/%s", choppername, parname); - if ((mask & code) > 0) { - v.v.intValue = 1; - } else { - v.v.intValue = 0; - } - target = GetHipadabaNode(node, path); - assert(target != NULL); - UpdateHipadabaPar(target, v, NULL); -} - -/*---------------------------------------------------------------------------*/ -static int setJulChoFlags(pHdb node, int intData[5]) -{ - char *chNames[] = { CH1N, - CH2N, - CH3N, - CH4N, - CH5N, - NULL - }; - char path[256]; - int i, code; - hdbValue v; - - memset(&v, 0, sizeof(hdbValue)); - v.dataType = HIPINT; - for (i = 0; i < 5; i++) { - code = intData[i]; - updateJulChoFlag(node, chNames[i], "microok", code, 1); - updateJulChoFlag(node, chNames[i], "atspeed", code, 2); - updateJulChoFlag(node, chNames[i], "atphase", code, 4); - updateJulChoFlag(node, chNames[i], "magneton", code, 8); - updateJulChoFlag(node, chNames[i], "dcon", code, 16); - updateJulChoFlag(node, chNames[i], "driveon", code, 32); - updateJulChoFlag(node, chNames[i], "currentdc", code, 64); - updateJulChoFlag(node, chNames[i], "lockopen", code, 128); - updateJulChoFlag(node, chNames[i], "diskopen", code, 256); - updateJulChoFlag(node, chNames[i], "diskclosed", code, 512); - updateJulChoFlag(node, chNames[i], "speedoverflow", code, 1024); - updateJulChoFlag(node, chNames[i], "bearingfailed", code, 2048); - updateJulChoFlag(node, chNames[i], "voltagetohigh", code, 4096); - } - - return 1; -} - -/*--------------------------------------------------------------------------*/ -static int ReadJulChoFlags(pJulCho self) -{ - int status, intData[5]; - char reply[256]; - - status = JulChoTransact(self, "RSC", reply, 255); -/* fprintf(stdout,"Chopper flags = %s\n", reply);*/ - if (status < 0) { - self->errorCode = status; - return 0; - } - if (!splitJulChoInt(reply, intData)) { - self->errorCode = BADREPLY; - } - setJulChoFlags(self->parNode, intData); - return 1; -} - -/*---------------------------------------------------------------------------*/ -static int UpdateJulChoParameters(pJulCho self, int what) -{ - int status, intData[5]; - double doubleData[5]; - char reply[255]; - - assert(what == ALL || what == SPEED); - - if (what == SPEED) { - if (time(NULL) < self->speedUpdate + self->updateIntervall) { - return 1; - } - } else { - if (time(NULL) < self->lastUpdate + self->updateIntervall) { - return 1; - } - } - - status = JulChoTransact(self, "RAS", reply, 255); - if (status < 0) { - self->errorCode = status; - return 0; - } - if (!splitJulChoInt(reply, intData)) { - self->errorCode = BADREPLY; - } - setJulChoIntPar(self->parNode, "actspeed", intData); - - status = JulChoTransact(self, "RAP", reply, 255); - if (status < 0) { - self->errorCode = status; - return 0; - } - if (!splitJulChoDouble(reply, doubleData)) { - self->errorCode = BADREPLY; - } - setJulChoDoublePar(self->parNode, "actphase", doubleData); - - if (what != ALL) { - self->speedUpdate = time(NULL); - return 1; - } - - status = JulChoTransact(self, "RNS", reply, 255); - if (status < 0) { - self->errorCode = status; - return 0; - } - if (!splitJulChoInt(reply, intData)) { - self->errorCode = BADREPLY; - } - setJulChoIntPar(self->parNode, "nomspeed", intData); - - - status = JulChoTransact(self, "RNP", reply, 255); - if (status < 0) { - self->errorCode = status; - return 0; - } - if (!splitJulChoDouble(reply, doubleData)) { - self->errorCode = BADREPLY; - } - setJulChoDoublePar(self->parNode, "nomphase", doubleData); - - - status = JulChoTransact(self, "RGW", reply, 255); - if (status < 0) { - self->errorCode = status; - return 0; - } - if (!splitJulChoDouble(reply, doubleData)) { - self->errorCode = BADREPLY; - } - setJulChoDoublePar(self->parNode, "gatewidth", doubleData); - - status = JulChoTransact(self, "RNC", reply, 255); - if (status < 0) { - self->errorCode = status; - return 0; - } - if (!splitJulChoDouble(reply, doubleData)) { - self->errorCode = BADREPLY; - } - setJulChoDoublePar(self->parNode, "nomcurrent", doubleData); - - - status = JulChoTransact(self, "RAC", reply, 255); - if (status < 0) { - self->errorCode = status; - return 0; - } - if (!splitJulChoDouble(reply, doubleData)) { - self->errorCode = BADREPLY; - } - setJulChoDoublePar(self->parNode, "actcurrent", doubleData); - - status = JulChoTransact(self, "RAV", reply, 255); - if (status < 0) { - self->errorCode = status; - return 0; - } - if (!splitJulChoDouble(reply, doubleData)) { - self->errorCode = BADREPLY; - } - setJulChoDoublePar(self->parNode, "voltage", doubleData); - - status = JulChoTransact(self, "RIT", reply, 255); - if (status < 0) { - self->errorCode = status; - return 0; - } - if (!splitJulChoDouble(reply, doubleData)) { - self->errorCode = BADREPLY; - } - setJulChoDoublePar(self->parNode, "inverter_temperature", doubleData); - - status = JulChoTransact(self, "RST", reply, 255); - if (status < 0) { - self->errorCode = status; - return 0; - } - if (!splitJulChoDouble(reply, doubleData)) { - self->errorCode = BADREPLY; - } - setJulChoDoublePar(self->parNode, "stator_temperature", doubleData); - - status = ReadJulChoFlags(self); - - self->lastUpdate = time(NULL); - self->speedUpdate = time(NULL); - return status; -} - -/*------------------------------------------------------------------------*/ -static void JulChoErrorcodeToString(int code, char *pError, int iLen) -{ - switch (code) { - case FRAMEERROR: - strlcpy(pError, "Frame error", iLen); - break; - case CKERROR: - strlcpy(pError, "Checksum error", iLen); - break; - case BADCOMMAND: - strlcpy(pError, "Bad Command", iLen); - break; - case WRONGNOPAR: - strlcpy(pError, "Wrong number of parameters", iLen); - break; - case ILLPAR: - strlcpy(pError, "Illegal parameter", iLen); - break; - case PARRANGE: - strlcpy(pError, "Parameter out of range", iLen); - break; - case BADERR: - strlcpy(pError, "Controller error not recognised", iLen); - break; - case BADREPLY: - strlcpy(pError, "Unexpected reply", iLen); - break; - case NOTPAR: - strlcpy(pError, "Unsupported parameter", iLen); - break; - case BADTEXT: - strlcpy(pError, "Failed to convert text to number", iLen); - break; - case ROPAR: - strlcpy(pError, "Read only Parameter", iLen); - break; - case NOMEM: - strlcpy(pError, "Out of memory formatting parameter", iLen); - break; - case HALT: - strlcpy(pError, "User requested HALT; choppers status undefined ", - iLen); - break; - case SICSCBRANGE: - strlcpy(pError, "Parameter value out of range", iLen); - break; - case SICSCBRO: - strlcpy(pError, "Parameter is READ-ONLY", iLen); - break; - default: - getRS232Error(code, pError, iLen); - break; - } -} - -/*------------------------------------------------------------------------*/ -static int testParGroup(char *name) -{ - if (strstr(name, "actspeed") != NULL || strstr(name, "actphase") != NULL) { - return SPEED; - } else { - return ALL; - } -} - -/*-------------------------------------------------------------------------*/ -static hdbCallbackReturn JulChoGetCallback(pHdb currentNode, - void *userData, - pHdbMessage message) -{ - pJulCho self = NULL; - SConnection *pCon = NULL; - int status; - char error[128], buffer[256]; - pHdbDataMessage mm = NULL; - - self = (pJulCho) userData; - assert(self != NULL); - - mm = GetHdbGetMessage(message); - if (mm == NULL) { - return hdbContinue; - } - pCon = (SConnection *) mm->callData; - - status = UpdateJulChoParameters(self, testParGroup(currentNode->name)); - if (status != 1 && pCon != NULL) { - JulChoErrorcodeToString(self->errorCode, error, 127); - snprintf(buffer, 255, "ERROR: %s occurred reading par", error); - SCWrite(pCon, buffer, eError); - } - return hdbContinue; -} - -/*--------------------------------------------------------------------------*/ -static int AppendJulChoROPar(pHdb parent, char *name, int type) -{ - pHdb child = NULL; - child = AddSICSHdbROPar(parent, name, makeHdbValue(type, 1)); - if (child != NULL) { - return 1; - } else { - return 0; - } -} - -/*---------------------------------------------------------------------------*/ -static int ConfigureSingleJulCho(pHdb parent, pJulCho driv, - char *prefix, char *postfix) -{ - pHdb child = NULL; - pHdbCallback pCb = NULL; - - /* - * write parameters - */ - - child = MakeHipadabaNode("nomphase", HIPFLOAT, 0); - if (child == NULL) { - return 0; - } - pCb = MakeCheckPermissionCallback(usUser); - if (pCb == NULL) { - return 0; - } - AppendHipadabaCallback(child, pCb); - pCb = MakeFloatRangeCallback(5.0, 355.); - if (pCb == NULL) { - return 0; - } - AppendHipadabaCallback(child, pCb); - pCb = MakeJulChoSetCallback(driv, "SPH", prefix, postfix); - if (pCb == NULL) { - return 0; - } - AppendHipadabaCallback(child, pCb); - AddHipadabaChild(parent, child, NULL); - - child = MakeHipadabaNode("gatewidth", HIPFLOAT, 0); - if (child == NULL) { - return 0; - } - pCb = MakeCheckPermissionCallback(usUser); - if (pCb == NULL) { - return 0; - } - AppendHipadabaCallback(child, pCb); - pCb = MakeJulChoSetCallback(driv, "SGW", prefix, postfix); - if (pCb == NULL) { - return 0; - } - AppendHipadabaCallback(child, pCb); - AddHipadabaChild(parent, child, NULL); - - if (!AppendJulChoROPar(parent, "nomspeed", HIPINT)) { - return 0; - } - - if (!AppendJulChoROPar(parent, "actspeed", HIPINT)) { - return 0; - } - - if (!AppendJulChoROPar(parent, "actphase", HIPFLOAT)) { - return 0; - } - - if (!AppendJulChoROPar(parent, "nomcurrent", HIPFLOAT)) { - return 0; - } - - if (!AppendJulChoROPar(parent, "actcurrent", HIPFLOAT)) { - return 0; - } - - if (!AppendJulChoROPar(parent, "voltage", HIPFLOAT)) { - return 0; - } - - if (!AppendJulChoROPar(parent, "inverter_temperature", HIPFLOAT)) { - return 0; - } - - if (!AppendJulChoROPar(parent, "stator_temperature", HIPFLOAT)) { - return 0; - } - - if (!AppendJulChoROPar(parent, "microok", HIPINT)) { - return 0; - } - - if (!AppendJulChoROPar(parent, "atspeed", HIPINT)) { - return 0; - } - - if (!AppendJulChoROPar(parent, "atphase", HIPINT)) { - return 0; - } - - if (!AppendJulChoROPar(parent, "magneton", HIPINT)) { - return 0; - } - - if (!AppendJulChoROPar(parent, "dcon", HIPINT)) { - return 0; - } - - if (!AppendJulChoROPar(parent, "driveon", HIPINT)) { - return 0; - } - - if (!AppendJulChoROPar(parent, "currentdc", HIPINT)) { - return 0; - } - - if (!AppendJulChoROPar(parent, "lockopen", HIPINT)) { - return 0; - } - - if (!AppendJulChoROPar(parent, "diskopen", HIPINT)) { - return 0; - } - - if (!AppendJulChoROPar(parent, "diskclosed", HIPINT)) { - return 0; - } - - if (!AppendJulChoROPar(parent, "speedoverflow", HIPINT)) { - return 0; - } - - if (!AppendJulChoROPar(parent, "bearingfailed", HIPINT)) { - return 0; - } - - if (!AppendJulChoROPar(parent, "voltagetohigh", HIPINT)) { - return 0; - } - - /* - * append get callbacks - */ - child = parent->child; - while (child != NULL) { - AppendHipadabaCallback(child, - MakeHipadabaCallback(JulChoGetCallback, driv, - NULL)); - child = child->next; - } - return 1; -} - -/*--------------------------------------------------------------------------*/ -static int InitJulChoPar(pJulCho driv) -{ - pHdb child = NULL, parChild = NULL; - pHdbCallback pCb = NULL; - - - child = MakeHipadabaNode(CH1N, HIPNONE, 0); - if (child == NULL) { - return 0; - } - if (!ConfigureSingleJulCho(child, driv, "", "::::")) { - return 0; - } - AddHipadabaChild(driv->parNode, child, NULL); - - child = MakeHipadabaNode(CH2N, HIPNONE, 0); - if (child == NULL) { - return 0; - } - if (!ConfigureSingleJulCho(child, driv, ":", ":::")) { - return 0; - } - /** - * the master speed can be set, the slaves not, thus remove the read only - * set callback and replace by a speed setting callback - */ - parChild = GetHipadabaNode(child, "nomspeed"); - assert(parChild != NULL); - /* - * delete the callback cahin in order to remove the - * read only callback - */ - DeleteCallbackChain(parChild); - parChild->callBackChain = NULL; - - pCb = MakeCheckPermissionCallback(usUser); - if (pCb == NULL) { - return 0; - } - AppendHipadabaCallback(parChild, pCb); - pCb = MakeJulChoSetCallback(driv, "SMS", "", ""); - if (pCb == NULL) { - return 0; - } - AppendHipadabaCallback(parChild, pCb); - AppendHipadabaCallback(parChild, - MakeHipadabaCallback(JulChoGetCallback, driv, - NULL)); - - - AddHipadabaChild(driv->parNode, child, NULL); - - child = MakeHipadabaNode(CH3N, HIPNONE, 0); - if (child == NULL) { - return 0; - } - if (!ConfigureSingleJulCho(child, driv, "::", "::")) { - return 0; - } - AddHipadabaChild(driv->parNode, child, NULL); - - child = MakeHipadabaNode(CH4N, HIPNONE, 0); - if (child == NULL) { - return 0; - } - if (!ConfigureSingleJulCho(child, driv, ":::", ":")) { - return 0; - } - AddHipadabaChild(driv->parNode, child, NULL); - - child = MakeHipadabaNode(CH5N, HIPNONE, 0); - if (child == NULL) { - return 0; - } - if (!ConfigureSingleJulCho(child, driv, "::::", "")) { - return 0; - } - AddHipadabaChild(driv->parNode, child, NULL); - - return 1; -} - -/*================= actual interface functions ==============================*/ -static int JulChoInit(pCodri pDriv) -{ - pJulCho self = NULL; - int status; - - self = (pJulCho) pDriv->pPrivate; - status = initRS232(self->controller); - if (status < 1) { - self->errorCode = status; - } - setRS232SendTerminator(self->controller, "$"); - setRS232ReplyTerminator(self->controller, "$"); - setRS232Timeout(self->controller, 2000); - return 1; -} - -/*---------------------------------------------------------------------------*/ -static int JulChoClose(pCodri pDriv) -{ - pJulCho self = NULL; - - self = (pJulCho) pDriv->pPrivate; - closeRS232(self->controller); - return 1; -} - -/*---------------------------------------------------------------------------*/ -static int JulChoKill(pCodri pDriv) -{ - pJulCho self = NULL; - - if (pDriv == NULL) { - return 1; - } - self = (pJulCho) pDriv->pPrivate; - JulChoClose(pDriv); - if (self->controller != NULL) { - KillRS232(self->controller); - self->controller = NULL; - } - free(self); - return 1; -} - -/*--------------------------------------------------------------------------- - * The set and get routines introduce phase and speed values which map to - * nomspeed when setting and actspeed when reading. This ugly hack saves me - * to introduce another drive adapter which set one parameter and reads - * another - *---------------------------------------------------------------------------*/ -static int JulChoSetPar2(pCodri pDriv, char *parname, char *pValue) -{ - pJulCho self = NULL; - pHdb target = NULL; - hdbValue v; - char error[64], *pPtr = NULL; - int status; - - if (strcmp(parname, "master/speed") == 0) { - status = JulChoSetPar2(pDriv, "master/nomspeed", pValue); - if (status == 1) { - SicsWait(10); - } - return status; - } else if (strcmp(parname, "master/phase") == 0) { - return JulChoSetPar2(pDriv, "master/nomphase", pValue); - } else if (strcmp(parname, "snail/phase") == 0) { - return JulChoSetPar2(pDriv, "snail/nomphase", pValue); - } else if (strcmp(parname, "rabbit/phase") == 0) { - return JulChoSetPar2(pDriv, "rabbit/nomphase", pValue); - } else if (strcmp(parname, "four/phase") == 0) { - return JulChoSetPar2(pDriv, "four/nomphase", pValue); - } else if (strcmp(parname, "five/phase") == 0) { - return JulChoSetPar2(pDriv, "five/nomphase", pValue); - } - - self = (pJulCho) pDriv->pPrivate; - target = GetHipadabaNode(self->parNode, parname); - if (target == NULL) { - self->errorCode = NOTPAR; - return 0; - } - v.dataType = target->value.dataType; - if (!readHdbValue(&v, pValue, error, 63)) { - self->errorCode = BADTEXT; - return 0; - } - self->errorCode = 0; - status = SetHipadabaPar(target, v, NULL); - if (status == 0 && self->errorCode == 0) { - self->errorCode = status; - return 0; - } - /* - * The SicsWait is here to allow the chopper to update his status flags. - * There were occurrences where the chopper was still driving but the - * status flag did not reflect this. - */ - SicsWait(STWAIT); - self->lastUpdate = 0; - return status; -} - -/*-------------------------------------------------------------------------------*/ -static int JulChoSetPar(pCodri pDriv, char *parname, float fValue) -{ - pJulCho self = NULL; - pHdb target = NULL; - hdbValue v; - char error[64]; - int status; - - if (strcmp(parname, "master/speed") == 0) { - status = JulChoSetPar(pDriv, "master/nomspeed", fValue); - if (status == 1) { - SicsWait(10); - } - return status; - } else if (strcmp(parname, "master/phase") == 0) { - return JulChoSetPar(pDriv, "master/nomphase", fValue); - } else if (strcmp(parname, "snail/phase") == 0) { - return JulChoSetPar(pDriv, "snail/nomphase", fValue); - } else if (strcmp(parname, "rabbit/phase") == 0) { - return JulChoSetPar(pDriv, "rabbit/nomphase", fValue); - } else if (strcmp(parname, "four/phase") == 0) { - return JulChoSetPar(pDriv, "four/nomphase", fValue); - } else if (strcmp(parname, "five/phase") == 0) { - return JulChoSetPar(pDriv, "five/nomphase", fValue); - } - - self = (pJulCho) pDriv->pPrivate; - target = GetHipadabaNode(self->parNode, parname); - if (target == NULL) { - self->errorCode = NOTPAR; - return 0; - } - v.dataType = target->value.dataType; - if (v.dataType == HIPINT) { - v.v.intValue = (int) fValue; - } else { - v.v.doubleValue = (double) fValue; - } - self->errorCode = 0; - status = SetHipadabaPar(target, v, NULL); - if (status == 0 && self->errorCode == 0) { - self->errorCode = status; - return 0; - } - /* - * The SicsWait is here to allow the chopper to update his status flags. - * There were occurrences where the chopper was still driving but the - * status flag did not reflect this. - */ - SicsWait(STWAIT); - self->lastUpdate = 0; - return status; -} - -/*---------------------------------------------------------------------------*/ -static int JulChoHalt(pCodri pDriv) -{ - pJulCho self = NULL; - - self = (pJulCho) pDriv->pPrivate; - self->halt = 1; - /* - * empty function on Philips request - */ - return 1; -} - -/*--------------------------------------------------------------------------*/ -static int JulChoGetPar(pCodri pDriv, char *parname, - char *pBuffer, int iBufLen) -{ - pJulCho self = NULL; - pHdb target = NULL; - pDynString val = NULL; - - if (strcmp(parname, "master/speed") == 0) { - return JulChoGetPar(pDriv, "master/actspeed", pBuffer, iBufLen); - } else if (strcmp(parname, "master/phase") == 0) { - return JulChoGetPar(pDriv, "master/actphase", pBuffer, iBufLen); - } else if (strcmp(parname, "snail/phase") == 0) { - return JulChoGetPar(pDriv, "snail/actphase", pBuffer, iBufLen); - } else if (strcmp(parname, "rabbit/phase") == 0) { - return JulChoGetPar(pDriv, "rabbit/actphase", pBuffer, iBufLen); - } else if (strcmp(parname, "four/phase") == 0) { - return JulChoGetPar(pDriv, "four/actphase", pBuffer, iBufLen); - } else if (strcmp(parname, "five/phase") == 0) { - return JulChoGetPar(pDriv, "five/actphase", pBuffer, iBufLen); - } - - - self = (pJulCho) pDriv->pPrivate; - target = GetHipadabaNode(self->parNode, parname); - if (target == NULL) { - self->errorCode = NOTPAR; - return 0; - } - if (!UpdateJulChoParameters(self, testParGroup(parname))) { - return 0; - } - val = formatValue(target->value, target); - if (val == NULL) { - self->errorCode = NOMEM; - return 0; - } - strlcpy(pBuffer, GetCharArray(val), iBufLen); - DeleteDynString(val); - return 1; -} - -/*---------------------------------------------------------------------------*/ -static int JulChoCheckPar(pCodri pDriv, char *parname) -{ - pJulCho self = NULL; - int i, status; - char path[256], reply[256]; - pHdb target = NULL; - char *chNames[] = { CH1N, - CH2N, - CH3N, - CH4N, - CH5N, - NULL - }; - - self = (pJulCho) pDriv->pPrivate; - - if (self->halt == 1) { - self->errorCode = HALT; - return HWFault; - } - /* - * For the Juelich chopper this means checking the atspeed, atphase - * flags - */ - if (!ReadJulChoFlags(self)) { - return HWFault; - } - for (i = 0; i < 5; i++) { - snprintf(path, 255, "%s/atspeed", chNames[i]); - target = GetHipadabaNode(self->parNode, path); - assert(target != NULL); - if (target->value.v.intValue == 0) { - return HWBusy; - } - snprintf(path, 255, "%s/atphase", chNames[i]); - target = GetHipadabaNode(self->parNode, path); - assert(target != NULL); - if (target->value.v.intValue == 0) { - return HWBusy; - } - } - status = JulChoTransact(self, "RSC", reply, 255); - if (status < 0) { - self->errorCode = status; - return HWFault; - } -/* fprintf(stdout,"Chopper Flags at finish: %s\n", reply);*/ - return HWIdle; -} - -/*---------------------------------------------------------------------------*/ -static int JulChoError(pCodri pDriv, int *iCode, char *pError, int iLen) -{ - pJulCho self = NULL; - - self = (pJulCho) pDriv->pPrivate; - - *iCode = self->errorCode; - JulChoErrorcodeToString(self->errorCode, pError, iLen); - return 1; -} - -/*---------------------------------------------------------------------------*/ -static int JulChoFix(pCodri pDriv, int code) -{ - pJulCho self = NULL; - - self = (pJulCho) pDriv->pPrivate; - - switch (code) { - case TIMEOUT: - case CKERROR: - case BADERR: - case BADREPLY: - return CHREDO; - break; - case NOTCONNECTED: - if (initRS232(self->controller) == 1) { - return CHREDO; - } else { - return CHFAIL; - } - break; - case INCOMPLETE: - case BADSEND: - case BADREAD: - closeRS232(self->controller); - if (initRS232(self->controller) == 1) { - return CHREDO; - } else { - return CHFAIL; - } - break; - default: - return CHFAIL; - break; - } -} - -/*---------------------------------------------------------------------------*/ -static pCodri MakeJulChoDriver(char *pHost, int port, pHdb parNode) -{ - pCodri pDriv = NULL; - pJulCho self = NULL; - int i; - pDynString names = NULL; - char *chNames[] = { CH1N, - CH2N, - CH3N, - CH4N, - CH5N, - NULL - }; - char path[256], *par = NULL; - - pDriv = malloc(sizeof(Codri)); - self = malloc(sizeof(JulCho)); - names = CreateDynString(256, 256); - - if (pDriv == NULL && self == NULL && names == NULL) { - return NULL; - } - memset(pDriv, 0, sizeof(Codri)); - memset(self, 0, sizeof(JulCho)); - - self->parNode = parNode; - self->controller = createRS232(pHost, port); - if (self->controller == NULL) { - free(self); - free(pDriv); - return NULL; - } - self->updateIntervall = 10; - if (!InitJulChoPar(self)) { - free(self); - free(pDriv); - return NULL; - } - - pDriv->pPrivate = self; - - pDriv->Init = JulChoInit; - pDriv->Close = JulChoClose; - pDriv->Delete = JulChoKill; - pDriv->SetPar = JulChoSetPar; - pDriv->SetPar2 = JulChoSetPar2; - pDriv->GetPar = JulChoGetPar; - pDriv->CheckPar = JulChoCheckPar; - pDriv->GetError = JulChoError; - pDriv->TryFixIt = JulChoFix; - pDriv->Halt = JulChoHalt; - - for (i = 0; i < 5; i++) { - snprintf(path, 255, "%s/nomspeed,", chNames[i]); - DynStringConcat(names, path); - snprintf(path, 255, "%s/actspeed,", chNames[i]); - DynStringConcat(names, path); - snprintf(path, 255, "%s/nomphase,", chNames[i]); - DynStringConcat(names, path); - snprintf(path, 255, "%s/actphase,", chNames[i]); - DynStringConcat(names, path); - snprintf(path, 255, "%s/gatewidth,", chNames[i]); - DynStringConcat(names, path); - snprintf(path, 255, "%s/nomcurrent,", chNames[i]); - DynStringConcat(names, path); - snprintf(path, 255, "%s/actcurrent,", chNames[i]); - DynStringConcat(names, path); - snprintf(path, 255, "%s/voltage,", chNames[i]); - DynStringConcat(names, path); - snprintf(path, 255, "%s/inverter_temperature,", chNames[i]); - DynStringConcat(names, path); - snprintf(path, 255, "%s/stator_temperature,", chNames[i]); - DynStringConcat(names, path); - snprintf(path, 255, "%s/microok,", chNames[i]); - DynStringConcat(names, path); - snprintf(path, 255, "%s/atspeed,", chNames[i]); - DynStringConcat(names, path); - snprintf(path, 255, "%s/atphase,", chNames[i]); - DynStringConcat(names, path); - snprintf(path, 255, "%s/magneton,", chNames[i]); - DynStringConcat(names, path); - snprintf(path, 255, "%s/dcon,", chNames[i]); - DynStringConcat(names, path); - snprintf(path, 255, "%s/driveon,", chNames[i]); - DynStringConcat(names, path); - snprintf(path, 255, "%s/currentdc,", chNames[i]); - DynStringConcat(names, path); - snprintf(path, 255, "%s/lockopen,", chNames[i]); - DynStringConcat(names, path); - snprintf(path, 255, "%s/diskopen,", chNames[i]); - DynStringConcat(names, path); - snprintf(path, 255, "%s/diskclosed,", chNames[i]); - DynStringConcat(names, path); - snprintf(path, 255, "%s/speedoverflow,", chNames[i]); - DynStringConcat(names, path); - snprintf(path, 255, "%s/bearingfailed,", chNames[i]); - DynStringConcat(names, path); - snprintf(path, 255, "%s/voltagetohigh,", chNames[i]); - DynStringConcat(names, path); - } - par = GetCharArray(names); - par[strlen(par) - 1] = '\0'; - pDriv->pParList = strdup(par); - DeleteDynString(names); - if (pDriv->pParList == NULL) { - JulChoKill(pDriv); - free(pDriv); - return NULL; - } - - return pDriv; -} - -/*--------------------------------------------------------------------------*/ -int JulChoFactory(SConnection * pCon, SicsInterp * pSics, void *pData, - int argc, char *argv[]) -{ - pChoco pNew = NULL; - pCodri pDriv = NULL; - pObjectDescriptor pDes = NULL; - char pBueffel[132]; - int iRet, iPort, iChannel; - int iSingle = 0; - - if (argc < 4) { - SCWrite(pCon, - "ERROR: Insufficient number of arguments to MakeJulCho", - eError); - return 0; - } - - - /* first try to get everything done */ - pNew = (pChoco) malloc(sizeof(Choco)); - pDes = CreateDescriptor("Chopper"); - pDes->parNode = MakeHipadabaNode(argv[1], HIPNONE, 0); - /* do driver */ - - pDriv = MakeJulChoDriver(argv[2], atoi(argv[3]), pDes->parNode); - if (pDriv == NULL) { - sprintf(pBueffel, "ERROR: Failed to initialize JulCho Driver"); - SCWrite(pCon, pBueffel, eError); - return 0; - } - if ((pNew == NULL) || (pDes == NULL) || (pDriv == NULL)) { - SCWrite(pCon, "ERROR: No memory left to create controller", eError); - return 0; - } - pNew->pDes = pDes; - pNew->pDriv = pDriv; - - /* initialize driver */ - iRet = pDriv->Init(pDriv); - if (!iRet) { - SCWrite(pCon, "ERROR: Failed to initialize driver", eError); - KillChoco(pNew); - return 0; - } - - /* install as command */ - iRet = AddCommand(pSics, argv[1], ChocoAction, KillChoco, pNew); - if (!iRet) { - sprintf(pBueffel, "ERROR: duplicate command %s NOT created", argv[1]); - SCWrite(pCon, pBueffel, eError); - return 0; - } - return 1; -} diff --git a/make_gen b/make_gen index 1bf035d..cc6a561 100644 --- a/make_gen +++ b/make_gen @@ -12,19 +12,20 @@ OBJ=psi.o buffer.o ruli.o sps.o pimotor.o charbychar.o\ pipiezo.o sanswave.o faverage.o spss7.o\ amorstat.o tasinit.o ptasdrive.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 sanscook.o tecsdriv.o itc4driv.o itc4.o\ - bruker.o ltc11.o A1931.o eurodriv.o slsmagnet.o \ + polterwrite.o ecb.o frame.o \ + el737driv.o sinqhmdriv.o tdchm.o \ + sanscook.o tecsdriv.o itc4driv.o itc4.o\ + bruker.o ltc11.o eurodriv.o \ el755driv.o serial.o scontroller.o t_update.o \ - t_rlp.o t_conv.o el737hpdriv.o dornier2.o el734hp.o \ + t_rlp.o t_conv.o el737hpdriv.o el734hp.o \ el737hpv2driv.o swmotor2.o tricssupport.o amorcomp.o \ $(MZOBJ) amordrive.o amorset.o sinqhttp.o slsecho.o\ - dgrambroadcast.o sinq.o tabledrive.o julcho.o sinqhttpopt.o\ - ritastorage.o poldizug.o audinelib.o delcam.o el737hpdrivsps.o \ + dgrambroadcast.o sinq.o tabledrive.o sinqhttpopt.o\ + ritastorage.o poldizug.o el737hpdrivsps.o \ rebin.o sanslirebin.o lmd200.o slsvme.o julprot.o sinqhttpprot.o \ pmacprot.o pfeifferprot.o termprot.o phytron.o autowin.o eigera2.o \ - tclClock.o tclDate.o tclUnixTime.o jvlprot.o + tclClock.o tclDate.o tclUnixTime.o jvlprot.o epicscounter.o \ + eigermono.o .SECONDARY.: sanslirebin.c diff --git a/makefile_linux b/makefile_linux index dbb606f..53f289a 100644 --- a/makefile_linux +++ b/makefile_linux @@ -13,7 +13,7 @@ include ../sllinux_def CC = gcc CFLAGS = -I$(HDFROOT)/include -DHDF4 -DHDF5 $(NI) -I$(TCLINC) -Ihardsup \ - -I.. -I. -MMD -DCYGNUS -DNONINTF -g $(DFORTIFY) \ + -I.. -I. -MMD -DCYGNUS -DNONINTF $(DBG) $(DFORTIFY) \ -Wall -Wno-unused -Wunused-value -Wno-comment -Wno-switch -Werror EXTRA=nintf.o diff --git a/psi.c b/psi.c index e5e5285..55018b5 100644 --- a/psi.c +++ b/psi.c @@ -24,15 +24,12 @@ #include "site.h" #include #include -#include "ecbdriv.h" -#include "ecbcounter.h" #include "sinqhmdriv.i" #include "tdchm.h" #include "tecsdriv.h" #include "itc4.h" #include "bruker.h" #include "ltc11.h" -#include "A1931.h" #include "eurodriv.h" #include "el755driv.h" #include @@ -110,10 +107,8 @@ static void AddPsiCommands(SicsInterp * pInter) SCMD("MakeAmorStatus", AmorStatusFactory); SCMD("MakeECB", MakeECB); SCMD("MakeFocusAverager", MakeFA); - SCMD("MakeJulCho", JulChoFactory); SCMD("MakeLMD200", MakeLMD200); SCMD("MakePIMotor", PIMotorFactory); - SCMD("MakePoldiReiss", MakePoldiReiss); SCMD("MakePSDFrame", MakeFrameFunc); SCMD("MakeRitaFix", MakeRitaFix); SCMD("MakeRitaWin", MakeRitaWin); @@ -132,6 +127,7 @@ static void AddPsiCommands(SicsInterp * pInter) SCMD("PolterInstall", PolterInstall); SCMD("SerialInit", SerialInit); SCMD("MakeEiger", InitEiger); + SCMD("MakeEigerMono", InitEigerMono); PCMD("cnvrt", CnvrtAction); /* @@ -146,8 +142,6 @@ static void AddPsiCommands(SicsInterp * pInter) } /*---------------------------------------------------------------------*/ -MotorDriver *CreateEL734(SConnection * pCon, int argc, char *argv[]); -MotorDriver *CreateEL734DC(SConnection * pCon, int argc, char *argv[]); MotorDriver *CreateEL734HP(SConnection * pCon, int argc, char *argv[]); MotorDriver *CreateEL734HPT(SConnection * pCon, int argc, char *argv[]); MotorDriver *MakePiPiezo(Tcl_Interp * pTcl, char *pArray); @@ -173,18 +167,6 @@ static pMotor CreatePsiMotor(SConnection * pCon, int argc, char *argv[]) SCWrite(pCon, pBueffel, eError); return NULL; } - } else if (strcmp(argv[1], "el734") == 0) { - pDriver = (MotorDriver *) CreateEL734(pCon, argc - 2, &argv[2]); - if (!pDriver) { - return NULL; - } - /* create the motor */ - pNew = MotorInit("EL734", argv[0], pDriver); - if (!pNew) { - snprintf(pBueffel,131, "Failure to create motor %s", argv[1]); - SCWrite(pCon, pBueffel, eError); - return NULL; - } } else if (strcmp(argv[1], "el734hp") == 0) { pDriver = (MotorDriver *) CreateEL734HP(pCon, argc - 2, &argv[2]); if (!pDriver) { @@ -209,30 +191,6 @@ static pMotor CreatePsiMotor(SConnection * pCon, int argc, char *argv[]) SCWrite(pCon, pBueffel, eError); return NULL; } - } else if (strcmp(argv[1], "el734dc") == 0) { - pDriver = (MotorDriver *) CreateEL734DC(pCon, argc - 2, &argv[2]); - if (!pDriver) { - return NULL; - } - /* create the motor */ - pNew = MotorInit("EL734DC", argv[0], pDriver); - if (!pNew) { - snprintf(pBueffel,131, "Failure to create motor %s", argv[1]); - SCWrite(pCon, pBueffel, eError); - return NULL; - } - } else if (strcmp(argv[1], "ecb") == 0) { - pDriver = (MotorDriver *) CreateECBMotor(pCon, argc - 2, &argv[2]); - if (!pDriver) { - return NULL; - } - /* create the motor */ - pNew = MotorInit("ECB", argv[0], pDriver); - if (!pNew) { - snprintf(pBueffel,131, "Failure to create motor %s", argv[0]); - SCWrite(pCon, pBueffel, eError); - return NULL; - } } return pNew; } @@ -246,6 +204,8 @@ extern pCounterDriver MakeEL737HPV2(SConnection * pCon, char *name, int argc, char *argv[]); pCounterDriver MakeEL737hpsps(SConnection * pCon, char *name, int argc, char *argv[]); + +pCounterDriver MakeEPICSCounter(char *rootname); /*-------------------------------------------------------------------*/ static pCounterDriver CreatePsiCounterDriver(SConnection * pCon, int argc, char *argv[]) @@ -263,20 +223,17 @@ static pCounterDriver CreatePsiCounterDriver(SConnection * pCon, pNew = MakeEL737hpsps(pCon, argv[1], argc - 3, &argv[3]); } else if (strcmp(argv[2], "el737hpv2") == 0) { pNew = MakeEL737HPV2(pCon, argv[1], argc - 3, &argv[3]); - } else if (strcmp(argv[2], "ecb") == 0) { + } else if (strcmp(argv[2], "epics") == 0) { if (argc < 4) { SCWrite(pCon, - "ERROR: insufficient no of arguments to create ECB counter", + "ERROR: insufficient no of arguments to create epics counter", eError); return NULL; } - pNew = MakeECBCounter(argv[3]); + pNew = MakeEPICSCounter(argv[3]); } return pNew; } - -/*-------------------------------------------------------------------*/ -extern pHistDriver MakeDelcamHM(pStringDict options); /* in delcam.c */ /*--------------------------------------------------------------------*/ static HistDriver *CreatePsiHistMem(char *name, pStringDict pOptions) { @@ -288,24 +245,6 @@ static HistDriver *CreatePsiHistMem(char *name, pStringDict pOptions) pNew = MakeTDCHM(pOptions); } else if (strcmp(name, "sinqhttp") == 0) { pNew = CreateSinqHttpDriver(pOptions); - } else if (strcmp(name, "delcam") == 0) { - pNew = MakeDelcamHM(pOptions); - } - return pNew; -} - -/*-------------------------------------------------------------------*/ -extern pVelSelDriv VSCreateDornierSINQ(char *name, Tcl_Interp * pTcl); -extern pVelSelDriv VSCreateDornier2003(char *name, Tcl_Interp * pTcl); -/*-------------------------------------------------------------------*/ -static pVelSelDriv CreatePsiVelSelDriv(char *name, char *array, - Tcl_Interp * pTcl) -{ - pVelSelDriv pNew = NULL; - if (strcmp(name, "dornier") == 0) { - pNew = VSCreateDornierSINQ(array, pTcl); - } else if (strcmp(name, "dornier2003") == 0) { - pNew = VSCreateDornier2003(array, pTcl); } return pNew; } @@ -375,7 +314,6 @@ static void ConfigureController(char *name, pEVControl pNew, } /*-------------------------------------------------------------------*/ -extern pEVDriver CreateSLSDriv(int argc, char *argv[]); extern pEVDriver CreateSLSVMEDriv(int argc, char *argv[]); /*------------------------------------------------------------------*/ @@ -436,28 +374,12 @@ static pEVControl InstallPsiEnvironmentController(SicsInterp * pSics, commandInstalled = 1; } } - } else if (strcmp(argv[3], "a1931") == 0) { - checkError = 1; - pDriv = CreateA1931Driver(argc - 4, &argv[4]); - if (pDriv != NULL) { - pNew = CreateEVController(pDriv, argv[2], &status); - if (pNew != NULL) { - AddCommand(pSics, argv[2], A1931Action, DeleteEVController, pNew); - commandInstalled = 1; - } - } } else if (strcmp(argv[3], "euro") == 0) { checkError = 1; pDriv = CreateEURODriv(argc - 4, &argv[4]); if (pDriv != NULL) { pNew = CreateEVController(pDriv, argv[2], &status); } - } else if (strcmp(argv[3], "psi-dsp") == 0) { - checkError = 1; - pDriv = CreateSLSDriv(argc - 4, &argv[4]); - if (pDriv != NULL) { - pNew = CreateEVController(pDriv, argv[2], &status); - } } else if (strcmp(argv[3], "vme-dsp") == 0) { checkError = 1; pDriv = CreateSLSVMEDriv(argc - 4, &argv[4]); @@ -538,7 +460,7 @@ pSite getSite(void) sitePSI->CreateMotor = CreatePsiMotor; sitePSI->CreateCounterDriver = CreatePsiCounterDriver; sitePSI->CreateHistogramMemoryDriver = CreatePsiHistMem; - sitePSI->CreateVelocitySelector = CreatePsiVelSelDriv; + sitePSI->CreateVelocitySelector = NULL; sitePSI->CreateControllerDriver = CreatePsiController; sitePSI->InstallEnvironmentController = InstallPsiEnvironmentController; diff --git a/sinqhttp.c b/sinqhttp.c index e3571e0..0bfc34c 100644 --- a/sinqhttp.c +++ b/sinqhttp.c @@ -20,6 +20,7 @@ #include #include #include +#include extern char *trim(char *); /*=================================================================== @@ -133,6 +134,7 @@ static int sinqHttpGet(pSinqHttp self, char *request) * try two times: a reconnect is no error */ ghttp_prepare(self->syncRequest); + traceIO(self->hmAddress,"OUT:%s",request); httpStatus = ghttp_process(self->syncRequest); if (httpStatus != ghttp_done) { ghttp_close(self->syncRequest); @@ -145,6 +147,7 @@ static int sinqHttpGet(pSinqHttp self, char *request) self->errorCode = SERVERERROR; return 0; } else { + traceIO(self->hmAddress,"IN:%s",request); return sinqHttpCheckResponse(self); } return 1; @@ -416,6 +419,7 @@ static int SinqHttpStatus(pHistDriver self, SConnection * pCon) if (pPriv->asyncRunning == 0) { status = sinqHttpGetPrepare(pPriv, statusdaq); + traceIO(pPriv->hmAddress,"OUT:%s", statusdaq); ghttp_set_sync(pPriv->syncRequest, ghttp_async); ghttp_prepare(pPriv->syncRequest); if (status != 1) { @@ -446,6 +450,7 @@ static int SinqHttpStatus(pHistDriver self, SConnection * pCon) if (status != 1) { return HWFault; } + traceIO(pPriv->hmAddress,"IN:%s", statusdaq); break; } @@ -569,6 +574,8 @@ static int SinqHttpGetHistogram(pHistDriver self, SConnection * pCon, snprintf(command, 255, "%s?bank=%d&start=%d&end=%d", gethm, bank, start, end); + /* printf("SinqHttpGetHistogram:%d-%d\n", start,end); */ + status = sinqHttpGet(pPriv, command); if (status != 1) { return HWFault; diff --git a/slsmagnet.c b/slsmagnet.c deleted file mode 100644 index 0528efc..0000000 --- a/slsmagnet.c +++ /dev/null @@ -1,1024 +0,0 @@ - /*-------------------------------------------------------------------------- - 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 - - Adaptiert auf neue DSP Software version, Mark Koennecke, August 2005 - - Fixed some bugs and added resetting of error conditions: - Mark Koennecke, May 2007 - - There is another scheme for resetting controller erros which might need - to be implemented: - 1) switch the controller off - 2) Write 0 to 0x21 - 3) switch on - 4) drive to target - This reboots the controller. Lukas Tanner does not recommend to do this - automatically. This is why it is not implemented yet. This reboot anyway - is not as hard as a full power cycle. - - Copyright: see copyright.h -----------------------------------------------------------------------------*/ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "evdriver.h" -#include -#include - -/* - 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 -#define BADLOWLIM -5301 -#define BADHIGHLIM -5302 -#define DEVICERROR -5304 -/* - packet header codes -*/ -#define DSPWRITE 0x80 -#define DSPREAD 0x0 - -#define ABS(x) (x < 0 ? -(x) : (x)) - -/*-----------------------------------------------------------------------*/ -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, address, status; - - if (!pSock) - return NOTCONNECTED; - - memset(reply, 0, 6); - address = (int) msg[1]; - 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) { - status = NETRead(pSock, reply + lVal, 6 - lVal, -10); - if (status >= 0) { - lVal += status; - } else { - /* - * network read error - */ - return status; - } - if (lVal >= 6) { - return (int) lVal; - } else { - continue; - } - } - } - if ((int) reply[1] != address) { - return BADECHO; - } - return TIMEOUT; -} - -/*---------------------------------------------------------------------------*/ -static int GetSLSPos(pEVDriver self, float *fPos) -{ - pSLSDriv pMe = NULL; - int iRet, ival, err; - double dval; - char msg[6], reply[6]; - long lVal; - - assert(self); - pMe = (pSLSDriv) self->pPrivate; - assert(pMe); - - memset(msg, 0, 6 * sizeof(char)); - memset(reply, 0, 6 * sizeof(char)); - msg[0] = DSPREAD; /* read request */ - /* old address of mag current - msg[1] = 0x92; - */ - msg[1] = 0x9c; /* address of mag current */ - iRet = communicateSLS(pMe->pSock, msg, reply); - if (iRet < 0) { - pMe->iError = iRet; - return 0; - } - memcpy(&ival, reply + 2, 4); - dval = DSPfloat2double(ival); - *fPos = (float) dval; - pMe->iError = 0; - - /* - * try read error codes - */ - msg[1] = 0x29; - iRet = communicateSLS(pMe->pSock, msg, reply); - if (iRet < 0) { - pMe->iError = iRet; - return 0; - } - err = (int) reply[5]; - if (err != 0) { - pMe->iError = -7000 - err; - return 0; - } - - return 1; -} - -/*----------------------------------------------------------------------------*/ -static int SLSRun(pEVDriver self, float fVal) -{ - pSLSDriv pMe = NULL; - int iRet, ival, i; - char msg[6], reply[6]; - double min, max; - - assert(self); - pMe = (pSLSDriv) self->pPrivate; - assert(pMe); - - memset(msg, 0, 6 * sizeof(char)); - memset(reply, 0, 6 * sizeof(char)); - - /* - * test high limit - */ - msg[0] = DSPREAD; - msg[1] = 0x76; - iRet = communicateSLS(pMe->pSock, msg, reply); - if (iRet <= 0) { - pMe->iError = iRet; - return iRet; - } - memcpy(&ival, reply + 2, 4); - max = DSPfloat2double(ival); - if (fVal > max) { - pMe->iError = BADHIGHLIM; - return 0; - } - - /* - * test low limit - */ - msg[0] = DSPREAD; - msg[1] = 0x77; - iRet = communicateSLS(pMe->pSock, msg, reply); - if (iRet <= 0) { - pMe->iError = iRet; - return iRet; - } - memcpy(&ival, reply + 2, 4); - min = -ABS(DSPfloat2double(ival)); - if (fVal < min) { - pMe->iError = BADLOWLIM; - return 0; - } - - /* - * actual set the new value - */ - 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 0; - } - for (i = 1; i < 6; i++) { - if (msg[i] != reply[i]) { - pMe->iError = BADECHO; - return 0; - } - } - return 1; -} - - /*---------------------------------------------------------------------*/ -static void slsdspCodeToText(int code, char *text, int textlen) -{ - switch (code) { - case 0x0: - strlcpy(text, "NO", textlen); - break; - case 0x1: - strlcpy(text, "DEVICE_STATE_ERROR", textlen); - break; - case 0x2: - strlcpy(text, "DEVICE_SUPERVISOR_DISABLED", textlen); - break; - case 0x3: - strlcpy(text, "COMMAND_ABORT", textlen); - break; - case 0x4: - strlcpy(text, "DATA_NOT_STORED", textlen); - break; - case 0x5: - strlcpy(text, "ERROR_ERASING_FLASH", textlen); - break; - case 0x6: - strlcpy(text, "COMMUNICATION_BREAK", textlen); - break; - case 0x7: - strlcpy(text, "INTERNAL_COMMUNICATION_ERROR", textlen); - break; - case 0x8: - strlcpy(text, "MASTER_CARD_ERROR", textlen); - break; - case 0x9: - strlcpy(text, "INTERNAL_BUFFER_FULL", textlen); - break; - case 0xa: - strlcpy(text, "WRONG_SECTOR", textlen); - break; - case 0xb: - strlcpy(text, "DATA_NOT_COPIED", textlen); - break; - case 0xc: - strlcpy(text, "WRONG_DOWNLOAD_PARAMETERS", textlen); - break; - case 0xd: - strlcpy(text, "DEVICE_PARAMETRIZATION_ERROR", textlen); - break; - case 0x10: - strlcpy(text, "TIMEOUT_DC_LINK_VOLTAGE", textlen); - break; - case 0x11: - strlcpy(text, "TIMEOUT_AUXILIARY_RELAY_ON", textlen); - break; - case 0x12: - strlcpy(text, "TIMEOUT_AUXILIARY_RELAY_OFF", textlen); - break; - case 0x13: - strlcpy(text, "TIMEOUT_MAIN_RELAY_ON", textlen); - break; - case 0x14: - strlcpy(text, "TIMEOUT_MAIN_RELAY_OFF", textlen); - break; - case 0x15: - strlcpy(text, "TIMEOUT_DATA_DOWNLOAD", textlen); - break; - case 0x20: - strlcpy(text, "INTERLOCK", textlen); - break; - case 0x21: - strlcpy(text, "MASTER_SWITCH", textlen); - break; - case 0x22: - strlcpy(text, "MAGNET_INTERLOCK", textlen); - break; - case 0x23: - strlcpy(text, "TEMPERATURE_TRANSFORMER", textlen); - break; - case 0x24: - strlcpy(text, "TEMPERATURE_RECTIFIER", textlen); - break; - case 0x25: - strlcpy(text, "TEMPERATURE_CONVERTER", textlen); - break; - case 0x26: - strlcpy(text, "CURRENT_TRANSDUCER", textlen); - break; - case 0x27: - strlcpy(text, "TEMPERATURE_POLARITY_SWITCH", textlen); - break; - case 0x28: - strlcpy(text, "POWER_SEMICONDUCTOR", textlen); - break; - case 0x29: - strlcpy(text, "MAIN_RELAY", textlen); - break; - case 0x2a: - strlcpy(text, "AD_CONVERTER_CARD", textlen); - break; - case 0x2b: - strlcpy(text, "POLARITY_SWITCH", textlen); - break; - case 0x2c: - strlcpy(text, "AUXILIARY_RELAY", textlen); - break; - case 0x2d: - strlcpy(text, "MASTER_SWITCH_T1", textlen); - break; - case 0x2e: - strlcpy(text, "MASTER_SWITCH_T2", textlen); - break; - case 0x2f: - strlcpy(text, "TEMPERATURE_MAGNET", textlen); - break; - case 0x30: - strlcpy(text, "WATER_MAGNET", textlen); - break; - case 0x31: - strlcpy(text, "WATER_RACK", textlen); - break; - case 0x40: - strlcpy(text, "LOAD_CURRENT_TOO_HIGH", textlen); - break; - case 0x41: - strlcpy(text, "DC_LINK_VOLTAGE_TOO_LOW", textlen); - break; - case 0x42: - strlcpy(text, "DC_LINK_VOLTAGE_TOO_HIGH", textlen); - break; - case 0x43: - strlcpy(text, "LOAD_VOLTAGE_TOO_HIGH", textlen); - break; - case 0x44: - strlcpy(text, "LOAD_CURRENT_RIPPLE_TOO_HIGH", textlen); - break; - case 0x45: - strlcpy(text, "DC_LINK_ISOLATION_NOT_OK", textlen); - break; - case 0x46: - strlcpy(text, "LOAD_ISOLATION_NOT_OK", textlen); - break; - case 0x47: - strlcpy(text, "LOAD_IMPEDANCE_OUT_OF_RANGE", textlen); - break; - case 0x48: - strlcpy(text, "SHUT_OFF_CURRENT_TOO_HIGH", textlen); - break; - case 0x49: - strlcpy(text, "LOAD_DC_CURRENT_TOO_HIGH", textlen); - break; - case 0x4a: - strlcpy(text, "CURRENT_I1A1_TOO_HIGH", textlen); - break; - case 0x4b: - strlcpy(text, "CURRENT_I1B1_TOO_HIGH", textlen); - break; - case 0x4c: - strlcpy(text, "CURRENT_I1A2_TOO_HIGH", textlen); - break; - case 0x4d: - strlcpy(text, "CURRENT_I1B2_TOO_HIGH", textlen); - break; - case 0x4e: - strlcpy(text, "CURRENT_I2A1_TOO_HIGH", textlen); - break; - case 0x4f: - strlcpy(text, "CURRENT_I2B1_TOO_HIGH", textlen); - break; - case 0x50: - strlcpy(text, "CURRENT_I2A2_TOO_HIGH", textlen); - break; - case 0x51: - strlcpy(text, "CURRENT_I2B2_TOO_HIGH", textlen); - break; - case 0x52: - strlcpy(text, "CURRENT_I3P_TOO_HIGH", textlen); - break; - case 0x53: - strlcpy(text, "CURRENT_I3N_TOO_HIGH", textlen); - break; - case 0x54: - strlcpy(text, "CURRENT_IE_TOO_HIGH", textlen); - break; - case 0x55: - strlcpy(text, "VOLTAGE_U1A_TOO_LOW", textlen); - break; - case 0x56: - strlcpy(text, "VOLTAGE_U1B_TOO_LOW", textlen); - break; - case 0x57: - strlcpy(text, "DIFF_CURRENT_I1A1_I1A2_TOO_HIGH", textlen); - break; - case 0x58: - strlcpy(text, "DIFF_CURRENT_I1B1_I1B2_TOO_HIGH", textlen); - break; - case 0x59: - strlcpy(text, "DIFF_CURRENT_I2A1_I2A2_TOO_HIGH", textlen); - break; - case 0x5a: - strlcpy(text, "DIFF_CURRENT_I2B1_I2B2_TOO_HIGH", textlen); - break; - case 0x5b: - strlcpy(text, "DIFF_CURRENT_I3P_I3N_TOO_HIGH", textlen); - break; - case 0x5c: - strlcpy(text, "CURRENT_I1A_TOO_HIGH", textlen); - break; - case 0x5d: - strlcpy(text, "CURRENT_I1B_TOO_HIGH", textlen); - break; - case 0x5e: - strlcpy(text, "CURRENT_I3A1_TOO_HIGH", textlen); - break; - case 0x5f: - strlcpy(text, "CURRENT_I3B1_TOO_HIGH", textlen); - break; - case 0x60: - strlcpy(text, "CURRENT_I3A2_TOO_HIGH", textlen); - break; - case 0x61: - strlcpy(text, "CURRENT_I3B2_TOO_HIGH", textlen); - break; - case 0x62: - strlcpy(text, "CURRENT_I4_TOO_HIGH", textlen); - break; - case 0x63: - strlcpy(text, "CURRENT_I5_TOO_HIGH", textlen); - break; - case 0x64: - strlcpy(text, "DIFF_CURRENT_I3A1_I3A2_TOO_HIGH", textlen); - break; - case 0x65: - strlcpy(text, "DIFF_CURRENT_I3B1_I3B2_TOO_HIGH", textlen); - break; - case 0x66: - strlcpy(text, "DIFF_CURRENT_I4_I5_TOO_HIGH", textlen); - break; - case 0x67: - strlcpy(text, "VOLTAGE_U3A_TOO_LOW", textlen); - break; - case 0x68: - strlcpy(text, "VOLTAGE_U3B_TOO_LOW", textlen); - break; - case 0x69: - strlcpy(text, "VOLTAGE_U1_TOO_LOW", textlen); - break; - case 0x6a: - strlcpy(text, "VOLTAGE_U3A_TOO_HIGH", textlen); - break; - case 0x6b: - strlcpy(text, "VOLTAGE_U3B_TOO_HIGH", textlen); - break; - case 0x6c: - strlcpy(text, "SPEED_ERROR_TOO_HIGH", textlen); - break; - case 0x70: - strlcpy(text, "MAIN_RELAY_A", textlen); - break; - case 0x71: - strlcpy(text, "MAIN_RELAY_B", textlen); - break; - case 0x72: - strlcpy(text, "POWER_SWITCH_A", textlen); - break; - case 0x73: - strlcpy(text, "POWER_SWITCH_B", textlen); - break; - case 0x74: - strlcpy(text, "MONITOR_TRAFO_A", textlen); - break; - case 0x75: - strlcpy(text, "MONITOR_TRAFO_B", textlen); - break; - case 0x76: - strlcpy(text, "TEMPERATURE_RECTIFIER_A", textlen); - break; - case 0x77: - strlcpy(text, "TEMPERATURE_RECTIFIER_B", textlen); - break; - case 0x78: - strlcpy(text, "TEMPERATURE_CONVERTER_A", textlen); - break; - case 0x79: - strlcpy(text, "TEMPERATURE_CONVERTER_B", textlen); - break; - case 0x7a: - strlcpy(text, "TEMPERATURE_CONVERTER_A1", textlen); - break; - case 0x7b: - strlcpy(text, "TEMPERATURE_CONVERTER_B1", textlen); - break; - case 0x7c: - strlcpy(text, "TEMPERATURE_CONVERTER_A2", textlen); - break; - case 0x7d: - strlcpy(text, "TEMPERATURE_CONVERTER_B2", textlen); - break; - case 0x7e: - strlcpy(text, "TEMPERATURE_TRANSFORMER_A", textlen); - break; - case 0x7f: - strlcpy(text, "TEMPERATURE_TRANSFORMER_B", textlen); - break; - case 0x80: - strlcpy(text, "WATER_RECTIFIER_A", textlen); - break; - case 0x81: - strlcpy(text, "WATER_RECTIFIER_B", textlen); - break; - case 0x82: - strlcpy(text, "WATER_CONVERTER_A", textlen); - break; - case 0x83: - strlcpy(text, "WATER_CONVERTER_B", textlen); - break; - case 0x84: - strlcpy(text, "WATER_CONVERTER_A1", textlen); - break; - case 0x85: - strlcpy(text, "WATER_CONVERTER_B1", textlen); - break; - case 0x86: - strlcpy(text, "WATER_CONVERTER_A2", textlen); - break; - case 0x87: - strlcpy(text, "WATER_CONVERTER_B2", textlen); - break; - case 0x88: - strlcpy(text, "WATER_TRANSFORMER_A", textlen); - break; - case 0x89: - strlcpy(text, "WATER_TRANSFORMER_B", textlen); - break; - case 0x8a: - strlcpy(text, "DOOR_A", textlen); - break; - case 0x8b: - strlcpy(text, "DOOR_B", textlen); - break; - case 0x8c: - strlcpy(text, "DOOR_C", textlen); - break; - case 0x8d: - strlcpy(text, "POWER_SEMICONDUCTOR_CONVERTER_A", textlen); - break; - case 0x8e: - strlcpy(text, "POWER_SEMICONDUCTOR_CONVERTER_B", textlen); - break; - case 0x8f: - strlcpy(text, "POWER_SEMICONDUCTOR_CONVERTER_A1", textlen); - break; - case 0x90: - strlcpy(text, "POWER_SEMICONDUCTOR_CONVERTER_B1", textlen); - break; - case 0x91: - strlcpy(text, "POWER_SEMICONDUCTOR_CONVERTER_A2", textlen); - break; - case 0x92: - strlcpy(text, "POWER_SEMICONDUCTOR_CONVERTER_B2", textlen); - break; - case 0x93: - strlcpy(text, "CURRENT_TRANSDUCER_I3P", textlen); - break; - case 0x94: - strlcpy(text, "CURRENT_TRANSDUCER_I3N", textlen); - break; - case 0x95: - strlcpy(text, "MAGNET_INTERLOCK_1", textlen); - break; - case 0x96: - strlcpy(text, "MAGNET_INTERLOCK_2", textlen); - break; - case 0x97: - strlcpy(text, "VENTILATOR", textlen); - break; - case 0x98: - strlcpy(text, "EMERGENCY_SWITCH", textlen); - break; - case 0x99: - strlcpy(text, "CAPACITOR_DISCHARGE_A_ON", textlen); - break; - case 0x9a: - strlcpy(text, "CAPACITOR_DISCHARGE_B_ON", textlen); - break; - case 0x9b: - strlcpy(text, "CURRENT_TRANSDUCER_I4", textlen); - break; - case 0x9c: - strlcpy(text, "CURRENT_TRANSDUCER_I5", textlen); - break; - case 0xb0: - strlcpy(text, "TIMEOUT_DC_LINK_VOLTAGE_PART_A", textlen); - break; - case 0xb1: - strlcpy(text, "TIMEOUT_DC_LINK_VOLTAGE_PART_B", textlen); - break; - case 0xb2: - strlcpy(text, "TIMEOUT_AUXILIARY_RELAY_A_ON", textlen); - break; - case 0xb3: - strlcpy(text, "TIMEOUT_AUXILIARY_RELAY_B_ON", textlen); - break; - case 0xb4: - strlcpy(text, "TIMEOUT_AUXILIARY_RELAY_A_OFF", textlen); - break; - case 0xb5: - strlcpy(text, "TIMEOUT_AUXILIARY_RELAY_B_OFF", textlen); - break; - case 0xb6: - strlcpy(text, "TIMEOUT_MAIN_RELAY_A_ON", textlen); - break; - case 0xb7: - strlcpy(text, "TIMEOUT_MAIN_RELAY_B_ON", textlen); - break; - case 0xb8: - strlcpy(text, "TIMEOUT_MAIN_RELAY_A_OFF", textlen); - break; - case 0xb9: - strlcpy(text, "TIMEOUT_MAIN_RELAY_B_OFF", textlen); - break; - } -} - -/*--------------------------------------------------------------------------*/ -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; - if (*iCode < -7000) { - slsdspCodeToText(-(pMe->iError + 7000), error, iErrLen); - return 1; - } - - - switch (*iCode) { - case BADECHO: - strlcpy(error, "message sent and reply did not match", iErrLen); - break; - case NOTCONNECTED: - strlcpy(error, "Not connected to device", iErrLen); - break; - case TIMEOUT: - strlcpy(error, "Timeout waiting for response", iErrLen); - break; - case BADHIGHLIM: - strlcpy(error, "Device internal upper limit violated", iErrLen); - break; - case BADLOWLIM: - strlcpy(error, "Device internal lower limit violated", iErrLen); - break; - default: - getRS232Error(*iCode, error, iErrLen); - break; - } - - return 1; -} - -/*-------------------------------------------------------------------------*/ -static int SLSSend(pEVDriver self, char *pCommand, char *pReply, int iLen) -{ - pSLSDriv pMe = NULL; - int iRet, ival; - char msg[6], reply[6]; - - assert(self); - pMe = (pSLSDriv) self->pPrivate; - assert(pMe); - - - - msg[0] = DSPWRITE; - msg[1] = 0x3c; - if (strcmp(pCommand, "off") == 0) { - /* - * ival = 0: ausschalten - */ - ival = 0; - memcpy(msg + 2, &ival, 4); - iRet = communicateSLS(pMe->pSock, msg, reply); - if (iRet <= 0) { - pMe->iError = iRet; - SLSError(self, &ival, pReply, iLen); - return 0; - } else { - strlcpy(pReply, "Done", iLen); - return 1; - } - } else if (strcmp(pCommand, "on") == 0) { - /* - * ival = 1: einschalten - */ - ival = 1; - memcpy(msg + 2, &ival, 4); - iRet = communicateSLS(pMe->pSock, msg, reply); - if (iRet <= 0) { - pMe->iError = iRet; - SLSError(self, &ival, pReply, iLen); - return 0; - } else { - strlcpy(pReply, "Done", iLen); - return 1; - } - } else { - strlcpy(pReply, "SLSMagnet only understands on or off on send", iLen); - return 0; - } - - - 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] = 0x3c; - /* - * ival = 0: ausschalten - */ - 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, ival; - char msg[6], reply[6]; - - assert(self); - pMe = (pSLSDriv) self->pPrivate; - assert(pMe); - - /* - msg[0] = DSPWRITE; - msg[1] = 0x3c; - ival = 0; - memcpy(msg+2, &ival,4); - iRet = communicateSLS(pMe->pSock,msg,reply); - */ - NETClosePort(pMe->pSock); - pMe->pSock = NULL; - return 1; -} - -/*---------------------------------------------------------------------------*/ -static int SLSFix(pEVDriver self, int iError) -{ - pSLSDriv pMe = NULL; - int iRet, i, ival; - char buffer[80]; - char msg[6], reply[6]; - float fVal = .0; - - assert(self); - pMe = (pSLSDriv) self->pPrivate; - assert(pMe); - - if (iError < -7000) { - /* - * This logic tries to reset the error code. Then it reads the - * error back. Serious errors persist and must be fixed by magnet - * technicians. But some can be cleared.... - */ - msg[0] = DSPWRITE; - msg[1] = 0x29; - ival = double2DSPfloat((double) fVal); - memcpy(msg + 2, &ival, 4); - communicateSLS(pMe->pSock, msg, reply); - /* - * read again: if persists: this is really, really bad - */ - msg[0] = DSPREAD; - msg[1] = 0x29; - iRet = communicateSLS(pMe->pSock, msg, reply); - if (iRet < 0) { - return DEVFAULT; - } - ival = (int) reply[5]; - if (ival == 0) { - return DEVREDO; - } - /* - * OK, clearing the error did not work, I try to reinitialize the - * socket because this helps sometimes. - */ - NETClosePort(pMe->pSock); - pMe->pSock = NULL; - pMe->pSock = NETConnect(pMe->pHost, pMe->iPort); - if (!pMe->pSock) { - return DEVFAULT; - } - sleep(1); - msg[0] = DSPREAD; - msg[1] = 0x29; - iRet = communicateSLS(pMe->pSock, msg, reply); - if (iRet < 0) { - return DEVFAULT; - } - ival = (int) reply[5]; - if (ival == 0) { - return DEVREDO; - } else { - return DEVFAULT; - } - } - - switch (iError) { - case BADHIGHLIM: - case BADLOWLIM: - return DEVFAULT; - break; - case BADECHO: - case TIMEOUT: - for (i = 0; i < 10; i++) { - iRet = NETAvailable(pMe->pSock, 0); - if (iRet == 1) { - NETRead(pMe->pSock, buffer, 70, -10); - } - } - return DEVREDO; - break; - 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; -} diff --git a/velodorn.c b/velodorn.c deleted file mode 100644 index d5914df..0000000 --- a/velodorn.c +++ /dev/null @@ -1,385 +0,0 @@ -/*------------------------------------------------------------------------- - - V E L O D O R N - - Utility functions for talking to a Dornier velocity selector in the - SINQ setup. - - Mark Koennecke, Juli 1997 - - Updated to decode the new dornier status messages as coughed up by the new - style Dornier software. - - Mark Koennecke, July 2003 - - 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 -#include -#include -#include "hardsup/sinq_prototypes.h" -#include "velodorn.h" -#include "hardsup/serialsinq.h" -#include - -#define TOK_BUF_L 25 -/*--------------------------- analyse Dornier status string ----------------*/ -int AnalyseDornierStatus(char *pText, pDornierStatus pResult) -{ - int cnt, key_id, sl, sts; - long err; - char ena_str[] = "ENABLED"; - char dis_str[] = "DISABLED"; - char keys[16][9] = { - "Status:\0 ", - "S_DREH:\0 ", - "I_DREH:\0 ", - "P_VERL:\0 ", - "STROM:\0 ", - "T_ROT:\0 ", - "T_GEH:\0 ", - "T_VOR:\0 ", - "T_RUECK:\0", - "DURCHFL:\0", - "VAKUUM:\0 ", - "BESCHL:\0 ", - "KOM: \0 ", - "DATE: \0 ", - "TIME: \0 ", - "Hz:\0 " - }; - - char tok_buf[TOK_BUF_L], *ptr_token, *ptr_src, *ptr; - const char tok_c[] = "/\\\0"; - char status[255]; - - ptr_src = pText; - memset(pResult, 0, sizeof(DornierStatus)); - - /* skip over first token, should be command echo */ - ptr_token = strtok(ptr_src, tok_c); - if (ptr_token == NULL) - return 0; /* error */ - strcpy(pResult->echo, (const char *) ptr_token); - ptr_src += strlen(ptr_token); - - ptr_src = NULL; /* necessary for further search with strtok */ - for (;;) { - /* read text till next separator '/' */ - ptr_token = strtok(ptr_src, tok_c); - if (ptr_token == NULL) - break; - strcpy(tok_buf, ptr_token); - - for (key_id = 0; key_id <= 15; key_id++) { - /* search key ? */ - sl = strlen(keys[key_id]); - if (strncmp(&keys[key_id][0], tok_buf, sl) == 0) { - /* step over key */ - for (cnt = 0; cnt + sl < TOK_BUF_L; cnt++) - tok_buf[cnt] = tok_buf[cnt + sl]; - switch (key_id) { - case 0:{ - strcpy(pResult->rm, tok_buf); - break; - } - case 1:{ - sscanf(tok_buf, "%d", &pResult->nom_rpm); - break; - } - case 2:{ - sscanf(tok_buf, "%d", &pResult->cur_rpm); - break; - } - case 3:{ - sscanf(tok_buf, "%d", &pResult->pwr); - break; - } - case 4:{ - sscanf(tok_buf, "%f", &pResult->curr); - break; - } - case 5:{ - sscanf(tok_buf, "%d", &pResult->rot_temp); - break; - } - case 6:{ - sscanf(tok_buf, "%d", &pResult->cont_temp); - break; - } - case 7:{ - sscanf(tok_buf, "%d", &pResult->inl_temp); - break; - } - case 8:{ - sscanf(tok_buf, "%d", &pResult->outl_temp); - break; - } - case 9:{ - sscanf(tok_buf, "%f", &pResult->cool_wat); - break; - } - case 10:{ - sscanf(tok_buf, "%f", &pResult->vacuum); - break; - } - case 11:{ - sscanf(tok_buf, "%f", &pResult->accel); - break; - } - case 12:{ - if (strcmp(tok_buf, ena_str) == 0) { - pResult->komm = 1; - break; - } - if (strcmp(tok_buf, dis_str) == 0) { - pResult->komm = 0; - break; - } - break; - } - case 13: - break; /* date */ - case 14: - break; /* time */ - case 15:{ - sscanf(tok_buf, "%d", &pResult->iHz); - break; - } - } - } - } - } - return (1); -} - -/*--------------------------- analyse Dornier status string ---------------- - This is the version for the NGS037 software from Dornier. Main difference - is that the keycodes are in germlish. - -------------------------------------------------------------------------*/ -int DecodeNewDornierStatus(char *pText, pDornierStatus pResult) -{ - int cnt, key_id, sl, sts; - long err; - char ena_str[] = "ENABLED"; - char dis_str[] = "DISABLED"; - char keys[16][14] = { - "MODE:\0 ", - "R_SPEED:\0 ", - "A_SPEED:\0 ", - "P_LOSS:\0 ", - "R_Current:\0 ", - "T_ROT:\0 ", - "T_HHH:\0 ", - "T_INL:\0 ", - "T_OUT:\0", - "F_RATE:\0", - "A_Vac:\0 ", - "V_OSC:\0 ", - "COM: \0 ", - "DATE: \0 ", - "TIME: \0 ", - "Hz:\0 " - }; - - char tok_buf[TOK_BUF_L], *ptr_token, *ptr_src, *ptr; - const char tok_c[] = "/\\\0"; - char status[255]; - - ptr_src = pText; - memset(pResult, 0, sizeof(DornierStatus)); - - /* skip over first token, should be command echo */ - ptr_token = strtok(ptr_src, tok_c); - if (ptr_token == NULL) - return 0; /* error */ - strcpy(pResult->echo, (const char *) ptr_token); - ptr_src += strlen(ptr_token); - - ptr_src = NULL; /* necessary for further search with strtok */ - for (;;) { - /* read text till next separator '/' */ - ptr_token = strtok(ptr_src, tok_c); - if (ptr_token == NULL) - break; - strcpy(tok_buf, ptr_token); - - for (key_id = 0; key_id <= 15; key_id++) { - /* search key ? */ - sl = strlen(keys[key_id]); - if (strncmp(&keys[key_id][0], tok_buf, sl) == 0) { - /* step over key */ - for (cnt = 0; cnt + sl < TOK_BUF_L; cnt++) - tok_buf[cnt] = tok_buf[cnt + sl]; - switch (key_id) { - case 0:{ - strcpy(pResult->rm, tok_buf); - break; - } - case 1:{ - sscanf(tok_buf, "%d", &pResult->nom_rpm); - break; - } - case 2:{ - sscanf(tok_buf, "%d", &pResult->cur_rpm); - break; - } - case 3:{ - sscanf(tok_buf, "%d", &pResult->pwr); - break; - } - case 4:{ - sscanf(tok_buf, "%f", &pResult->curr); - break; - } - case 5:{ - sscanf(tok_buf, "%d", &pResult->rot_temp); - break; - } - case 6:{ - sscanf(tok_buf, "%d", &pResult->cont_temp); - break; - } - case 7:{ - sscanf(tok_buf, "%d", &pResult->inl_temp); - break; - } - case 8:{ - sscanf(tok_buf, "%d", &pResult->outl_temp); - break; - } - case 9:{ - sscanf(tok_buf, "%f", &pResult->cool_wat); - break; - } - case 10:{ - sscanf(tok_buf, "%f", &pResult->vacuum); - break; - } - case 11:{ - sscanf(tok_buf, "%f", &pResult->accel); - break; - } - case 12:{ - if (strcmp(tok_buf, ena_str) == 0) { - pResult->komm = 1; - break; - } - if (strcmp(tok_buf, dis_str) == 0) { - pResult->komm = 0; - break; - } - break; - } - case 13: - break; /* date */ - case 14: - break; /* time */ - case 15:{ - sscanf(tok_buf, "%d", &pResult->iHz); - break; - } - } - } - } - } - return (1); -} - -/*-------------------------------------------------------------------------*/ -int DornierSend(void **pData, char *pCommand, char *pReply, int iRepLen) -{ - char pOldCom[10]; - char *pPtr; - int iRet; - - /* first copy the command send out, in order to test for echo */ - pPtr = pCommand; - memset(pOldCom, 0, 10); - while (isspace(*pPtr) && (*pPtr != '\0')) { - pPtr++; - } - if (*pPtr == '\0') { /* no command */ - return NOCOMMAND; - } - strncpy(pOldCom, pPtr, 3); /* strlcpy probably wrong here */ - - iRet = SerialWriteRead(pData, pCommand, pReply, iRepLen); -/* - iRet = SerialSicsExecute(pData,pCommand,pReply,iRepLen); -*/ - if (iRet != 1) { - return iRet; /* an error ocurred */ - } - - /* try to find command in the reply */ - pPtr = strstr(pReply, pOldCom); - if (pPtr == NULL) { - SICSLogWrite("Velocity Selector: Bad Reply:", eError); - SICSLogWrite(pReply, eError); - return ECHOMISSING; - } - return 1; -} - -/*-------------------------------------------------------------------------*/ -int GetDornierStatus(void **pData, pDornierStatus pDornier) -{ - char pCommand[10] = { "???" }; - char pReply[256]; - int iRet; - - /* send command */ - iRet = DornierSend(pData, pCommand, pReply, 255); - if (iRet < 0) { - return iRet; - } - if (strlen(pReply) < 100) { - SICSLogWrite("Velocity Selector: Bad Reply:", eError); - SICSLogWrite(pReply, eError); - return INVALIDSTATUS; - } - - - /* analyse reply */ - iRet = AnalyseDornierStatus(pReply, pDornier); - if (!iRet) { - return BADANALYSIS; - } - if (pDornier->cur_rpm > 70000) { - printf("Shitty status reply: %s detected \n", pReply); - } - return 1; -} diff --git a/velodorn.h b/velodorn.h deleted file mode 100644 index ff9439f..0000000 --- a/velodorn.h +++ /dev/null @@ -1,58 +0,0 @@ - -#line 47 "velodorn.w" - -/*--------------------------------------------------------------------------- - V E L O D O R N - - a set of utility functions needed in order to communicate with a - Dornier velocity selector through the SINQ system. - - Mark Koennecke, Juli 1997 - - updated to support new format fo status messages, Mark Koennecke, July 2003 - - copyright: see implementation file. -------------------------------------------------------------------------------*/ -#ifndef VELODORN -#define VELODORN -/*-------------------- a data structure for status analysis ---------------*/ -typedef struct { - char echo[30]; /* echo of command */ - char rm[10]; /* operation status: REG == adjusting, STB == idle, - BRE == braking */ - int nom_rpm; /* envisaged rotation */ - int cur_rpm; /* actual rotation speed */ - int pwr; /* loss current, only valid after check */ - float curr; /* electircal current */ - int rot_temp; /* temperature of rotor */ - int cont_temp; /* temperature of housing */ - int inl_temp; /* in temperature of cooling water */ - int outl_temp; /* temperature of cooling water after - velocity selector */ - float cool_wat; /* cooling water flow (l/minute) */ - float vacuum; /* vacuum (mbar) */ - float accel; /* rotation acceleration (g) */ - int komm; /* communication status PC-Host, - 0 = enabled, 1 = disabled - */ - int iHz; -} DornierStatus, *pDornierStatus; - -/*--------- error codes */ -#define NOCOMMAND -300 -#define ECHOMISSING -302 -#define BADANALYSIS -303 -#define STARTTIMEOUT -304 -#define INVALIDSTATUS -305 -/*------ functions */ - -#line 41 "velodorn.w" - -int GetDornierStatus(void **pData, pDornierStatus pDornier); -int DornierSend(void **pData, char *pCommand, char *pReply, int iLen); -int DecodeNewDornierStatus(char *pText, pDornierStatus pDornier); - -#line 92 "velodorn.w" - - -#endif diff --git a/velodornier.c b/velodornier.c deleted file mode 100644 index 1f485f3..0000000 --- a/velodornier.c +++ /dev/null @@ -1,636 +0,0 @@ -/*-------------------------------------------------------------------------- - V E L O D O R N I E R - - A driver for a Dornier velocity selector, connected to our world - via a terminal server and TCP/IP. Please note, that the protocoll - implemented by the velocity selector PC has been changed in the following - ways from the standard as supplied by Dornier: - - no messages we have not asked for. - - The whole response will be concatenated in a string, each item - separated by a /. At the end is a single . This is because - our terminal server reads only up to the first terminator. - - - Author: Mark Koennecke, Juli 1997 - Thoroughly revised: October 1997 Mark Koennecke - - 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 "sics.h" -#include -#include -#include -#include -#include - -typedef struct __VelSelDriv *pVelSelDriv; - -#include -#include "velodorn.h" -#include "hardsup/serialsinq.h" -#include "hardsup/el734_def.h" -#include "hardsup/el734fix.h" -#include - -/* VELO* MUST be the same as in velo.i!*/ -#define VELOREDO -1 -#define VELOFAIL 0 -#define VELOOK 1 -#define VSNOCON 0 -#define VSOK 1 -#define VSACCEL -7 -#define VSFAIL -2 - -typedef enum { vStart, eRegel, eHalted } eVeloMode; -#define RPMALIFE 3090 - -/*----------------------------- The private data structure ---------------*/ -typedef struct { - char *pComputer; - int iPort; - int iChannel; - int iTimeOut; - int iLastError; - void *pData; - eVeloMode eVelo; - time_t t_End; - float fTarget; - int iBusy; - float fLastRPM; -} Dornier, *pDornier; -/*----------------------------------------------------------------------------*/ - -static int GetDornierPos(pVelSelDriv self, float *fPos) -{ - pDornier pDorn = NULL; - DornierStatus DStatus; - int iRet; - - assert(self); - pDorn = (pDornier) self->pPrivate; - - if (pDorn->iBusy) { - *fPos = pDorn->fLastRPM; - return 1; - } - - pDorn->iBusy = 1; - iRet = GetDornierStatus(&pDorn->pData, &DStatus); - pDorn->iBusy = 0; - if (iRet < 0) { - *fPos = -9999.; - return 0; - } - *fPos = DStatus.cur_rpm; - pDorn->fLastRPM = DStatus.cur_rpm; - return 1; -} - -/*--------------------------------------------------------------------------*/ -static int DornierHalt(pVelSelDriv self) -{ - pDornier pDorn = NULL; - int iRet; - char pCom[] = { "HAL" }; - char pAnswer[80]; - - assert(self); - pDorn = (pDornier) self->pPrivate; - - iRet = SerialWriteRead(&pDorn->pData, pCom, pAnswer, 79); -/* iRet = SerialSicsExecute(&pDorn->pData, pCom,pAnswer,79); -*/ - pDorn->eVelo = eHalted; - if (iRet != 1) { - pDorn->iLastError = iRet; - return 0; - } - return 1; -} - -/*----------------------------------------------------------------------------*/ -static int DornierRun(pVelSelDriv self, float fVal) -{ - int iRet; - char pCommand[50], pAnswer[50]; - pDornier pDorn = NULL; - - assert(self); - pDorn = (pDornier) self->pPrivate; - - /* less then zero, means halt in this case */ - if (fVal < RPMALIFE) { - DornierHalt(self); - return 1; - } - - /* if busy, wait until free */ - while (pDorn->iBusy) { - SicsWait(1); - } - - switch (pDorn->eVelo) { - case eHalted: - strcpy(pCommand, "SST"); - pDorn->fTarget = fVal; - pDorn->eVelo = vStart; - pDorn->t_End = time(NULL) + 1800; /* start time + 30 min */ - break; - case eRegel: - sprintf(pCommand, "SDR %5u", (int) fVal); - pDorn->fTarget = fVal; - break; - } - - pDorn->iBusy = 1; - iRet = SerialWriteRead(&pDorn->pData, pCommand, pAnswer, 49); - -/* iRet = SerialSicsExecute(&pDorn->pData,pCommand,pAnswer,49); -*/ - pDorn->iBusy = 0; - - if (iRet != 1) { - pDorn->iLastError = iRet; - return 0; - } - return 1; -} - -/*--------------------------------------------------------------------------*/ -static int DornierError(pVelSelDriv self, int *iCode, char *error, - int iErrLen) -{ - pDornier pDorn = NULL; - - assert(self); - pDorn = (pDornier) self->pPrivate; - - *iCode = pDorn->iLastError; - - switch (pDorn->iLastError) { - case NOCOMMAND: - strlcpy(error, "No command was specified, internal error", iErrLen); - break; - case ECHOMISSING: - strlcpy(error, "No echo received, may be busy", iErrLen); - break; - case BADANALYSIS: - strlcpy(error, "Error analysing status messge", iErrLen); - break; - case STARTTIMEOUT: - strlcpy(error, "Velocity Selector failed to start", iErrLen); - break; - default: - SerialError(pDorn->iLastError, error, iErrLen); - break; - } - return 1; -} - -/*---------------------------------------------------------------------------*/ -static int DornierFixIt(pVelSelDriv self, int iError) -{ - pDornier pDorn = NULL; - int iRet; - - assert(self); - pDorn = (pDornier) self->pPrivate; - - switch (iError) { - /* network errors */ - case NOCONNECTION: - 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: - SerialClose(&pDorn->pData); - iRet = SerialForceOpen(&pDorn->pData, pDorn->pComputer, - pDorn->iPort, pDorn->iChannel); - if (iRet != 1) { - return VELOREDO; - } else { - return VELOFAIL; - } - break; - /* handable protocoll errors */ - case ECHOMISSING: - case EL734__BAD_TMO: - case -1: - case TIMEOUT: - return VELOREDO; - break; - case STARTTIMEOUT: - return VELOFAIL; - break; - case INVALIDSTATUS: - return VELOREDO; - break; - default: - return VELOFAIL; - break; - } - return VELOFAIL; -} - -/*--------------------------------------------------------------------------*/ -static int DornierStat(pVelSelDriv self, int *iCode, float *fCur) -{ - pDornier pDorn = NULL; - int iRet, iErrStat; - DornierStatus sStatus; - char pCommand[80]; - char pAnswer[80]; - float fDelta; - static int iCount = 0; - - assert(self); - pDorn = (pDornier) self->pPrivate; - - /* if busy, return VSACCEL */ - if (pDorn->iBusy) { - *fCur = pDorn->fLastRPM; - return VSACCEL; - } - - *iCode = ROTMOVE; - /* get the status */ - pDorn->iBusy = 1; - iRet = GetDornierStatus(&pDorn->pData, &sStatus); - pDorn->iBusy = 0; - if (iRet < 0) { - iErrStat = DornierFixIt(self, iRet); - *iCode = 9384; /* ignore this one */ - if (iErrStat == VELOREDO) { - /* the velcocity selector will not respond when busy. - Therefore such cases are interpreted as busy! - */ - return VSACCEL; - } else { - /* this is what we got if there is network trouble */ - return VELOFAIL; - } - } - - - /* some serious logic because of multi - modes */ - switch (pDorn->eVelo) { - case vStart: - *iCode = ROTSTART; - *fCur = 0.; - if (sStatus.cur_rpm >= RPMALIFE) { - sprintf(pCommand, "SDR %5u", (int) pDorn->fTarget); - pDorn->iBusy = 1; - iRet = SerialWriteRead(&pDorn->pData, pCommand, pAnswer, 49); - -/* iRet = SerialSicsExecute(&pDorn->pData,pCommand,pAnswer,49); -*/ - pDorn->iBusy = 0; - pDorn->eVelo = eRegel; - iCount = 0; - if (iRet != 1) { - pDorn->iLastError = iRet; - return VELOFAIL; - } - return VSACCEL; - } else { - if (time(NULL) > pDorn->t_End) { - pDorn->iLastError = STARTTIMEOUT; - return VELOFAIL; - } - return VSACCEL; - } - break; - case eRegel: - *iCode = ROTMOVE; - *fCur = (float) sStatus.cur_rpm; - pDorn->fLastRPM = *fCur; - fDelta = sStatus.cur_rpm - sStatus.nom_rpm; - if (fDelta < 0) { - fDelta = -fDelta; - } - if (fDelta > self->fTolerance) { - iCount = 0; - return VSACCEL; - } else { - iCount++; - if (iCount > 4) { - return VSOK; - } else { - return VSACCEL; - } - } - - case eHalted: - if (sStatus.iHz > 5) { - *iCode = ROTMOVE; - *fCur = (float) sStatus.cur_rpm; - pDorn->fLastRPM = *fCur; - return VSACCEL; - } else { - return VSOK; - } - break; - } - return VELOOK; -} - -/*-------------------------------------------------------------------------*/ -static int DornierText(pVelSelDriv self, char *pText, int iTextLen) -{ - pDornier pDorn = NULL; - int iRet, iErrStat; - DornierStatus sStatus; - char pBueffel[1024]; - char pHelp[80]; - - assert(self); - pDorn = (pDornier) self->pPrivate; - - /* get the status */ - iRet = GetDornierStatus(&pDorn->pData, &sStatus); - if (iRet < 0) { - pDorn->iLastError = iRet; - return 0; - } - - /* format it to a string */ - sprintf(pHelp, "RPM: %d , should %d\n", sStatus.cur_rpm, - sStatus.nom_rpm); - strcpy(pBueffel, pHelp); - sprintf(pHelp, "State: %s\n", sStatus.rm); - strcat(pBueffel, pHelp); - sprintf(pHelp, "Current: %d\n", sStatus.pwr); - strcat(pBueffel, pHelp); - sprintf(pHelp, "Rotor T: %d, Housing T: %d\n", sStatus.rot_temp, - sStatus.cont_temp); - strcat(pBueffel, pHelp); - sprintf(pHelp, "Cooling: In-T: %d, Out-T: %d, Flow: %f\n", - sStatus.inl_temp, sStatus.outl_temp, sStatus.cool_wat); - strcat(pBueffel, pHelp); - sprintf(pHelp, "Vaccum: %f, Accel: %f", sStatus.vacuum, sStatus.accel); - strcat(pBueffel, pHelp); - - strlcpy(pText, pBueffel, iTextLen); - return 1; -} - -/*------------------------------------------------------------------------*/ -static int SimSetRot(pVelSelDriv self, float fNew) -{ - return 1; -} - -/*------------------------------------------------------------------------*/ -static int DornierLoss(pVelSelDriv self, float *fLoss) -{ - pDornier pDorn = NULL; - int iRet, iErrStat, iDelta; - DornierStatus DStatus; - char pCommand[] = { "BRE" }; - char pAnswer[80]; - static int iCount; - static int iError; - - assert(self); - pDorn = (pDornier) self->pPrivate; - - /* wait until not busy, to do it */ - while (pDorn->iBusy) { - SicsWait(1); - } - - /* send a command */ - pDorn->iBusy = 1; - iRet = SerialWriteRead(&pDorn->pData, pCommand, pAnswer, 79); - pDorn->iBusy = 0; - if (iRet != 1) { - pDorn->iLastError = iRet; - return 0; - } - - /* wait 10 seconds before doing anything */ - SicsWait(10); - - /* loop until back to speed again */ - for (;;) { - iRet = GetDornierStatus(&pDorn->pData, &DStatus); - if (iRet) { - iError = 0; - iDelta = DStatus.cur_rpm - DStatus.nom_rpm; - if (iDelta < 0) { - iDelta = -iDelta; - } - if (iDelta < 15) { - iCount++; - if (iCount > 4) { - break; - } - } else { - iCount = 0; - } - } else { - iError++; - if (iError > 10) { - break; - } - } - } - - - *fLoss = DStatus.pwr; - return 1; -} - -/*-------------------------------------------------------------------------*/ -static void DornierKill(void *pData) -{ - pDornier pDorn = NULL; - - pDorn = (pDornier) pData; - assert(pDorn); - - SerialSend(&pDorn->pData, "TTY"); - SerialClose(&pDorn->pData); - if (pDorn->pComputer) { - free(pDorn->pComputer); - } - free(pDorn); -} - -/*------------------------------------------------------------------------*/ -static int DornierInit(pVelSelDriv self, SConnection * pCon) -{ - pDornier pDorn = NULL; - int iRet, iError; - char pError[80], pBueffel[256]; - - assert(self); - pDorn = (pDornier) self->pPrivate; - assert(pDorn); - - /* if there is no connection, open it */ - if (!pDorn->pData) { - iRet = SerialForceOpen(&pDorn->pData, pDorn->pComputer, - pDorn->iPort, pDorn->iChannel); - if (iRet != 1) { - SerialError(iRet, pError, 79); - sprintf(pBueffel, "ERROR: %s when initialising Velocity selector", - pError); - SCWrite(pCon, pBueffel, eError); - return 0; - } - SerialConfig(&pDorn->pData, pDorn->iTimeOut); - SerialATerm(&pDorn->pData, "1\r"); - SerialSendTerm(&pDorn->pData, "\n"); - } - - /* tell him that we want control */ - iRet = DornierSend(&pDorn->pData, "REM", pError, 79); - if (iRet != 1) { - sprintf(pBueffel, - "ERROR: %s while switching velocity selector to remote", - pError); - SCWrite(pCon, pBueffel, eError); - return 1; - } - pDorn->eVelo = eHalted; - pDorn->iBusy = 0; - - return 1; -} - -/*-------------------------------------------------------------------------*/ -pVelSelDriv VSCreateDornierSINQ(char *name, Tcl_Interp * pTcl) -{ - pVelSelDriv pNew = NULL; - pDornier pDorn = NULL; - char *pPtr = NULL; - int iVal, iRet; - - /* the most likely error is the parameters specified are wrong! - So check this first. We''ll use Tcl's result for error reporting. - name is the name of an Tcl array which should hold the info - necessary - */ - - /* allocate a Dornier structure */ - pDorn = (pDornier) malloc(sizeof(Dornier)); - if (!pDorn) { - return NULL; - } - memset(pDorn, 0, sizeof(Dornier)); - - /* host name */ - pPtr = (char *) Tcl_GetVar2(pTcl, name, "Host", TCL_GLOBAL_ONLY); - if (!pPtr) { - Tcl_AppendResult(pTcl, "ERROR: no hostname found in", name, NULL); - free(pDorn); - return NULL; - } - pDorn->pComputer = strdup(pPtr); - - /* port number */ - pPtr = (char *) Tcl_GetVar2(pTcl, name, "Port", TCL_GLOBAL_ONLY); - if (!pPtr) { - Tcl_AppendResult(pTcl, "ERROR: no port number found in", name, NULL); - free(pDorn); - return NULL; - } - iRet = Tcl_GetInt(pTcl, pPtr, &iVal); - if (iRet != TCL_OK) { - free(pDorn->pComputer); - free(pDorn); - return NULL; - } - pDorn->iPort = iVal; - - /* channel number */ - pPtr = (char *) Tcl_GetVar2(pTcl, name, "Channel", TCL_GLOBAL_ONLY); - if (!pPtr) { - Tcl_AppendResult(pTcl, "ERROR: no channel number found in", name, - NULL); - free(pDorn); - return NULL; - } - iRet = Tcl_GetInt(pTcl, pPtr, &iVal); - if (iRet != TCL_OK) { - free(pDorn->pComputer); - free(pDorn); - return NULL; - } - pDorn->iChannel = iVal; - - /* time out. This one gets defaulted when not specified */ - pPtr = (char *) Tcl_GetVar2(pTcl, name, "Timeout", TCL_GLOBAL_ONLY); - if (!pPtr) { - pDorn->iTimeOut = 1000; - } else { - iRet = Tcl_GetInt(pTcl, pPtr, &iVal); - if (iRet != TCL_OK) { - pDorn->iTimeOut = 1000; - } - pDorn->iTimeOut = iVal; - } - - /* business as usual: allocate memory */ - pNew = (pVelSelDriv) malloc(sizeof(VelSelDriv)); - if (!pNew) { - return NULL; - } - - /* zero the world */ - memset(pNew, 0, sizeof(VelSelDriv)); - pNew->pPrivate = pDorn; - - /* initialise function pointers */ - pNew->DeletePrivate = DornierKill; - pNew->Halt = DornierHalt; - pNew->GetError = DornierError; - pNew->TryAndFixIt = DornierFixIt; - pNew->GetRotation = GetDornierPos; - pNew->SetRotation = DornierRun; - pNew->GetStatus = DornierStat; - pNew->GetDriverText = DornierText; - pNew->GetLossCurrent = DornierLoss; - pNew->Init = DornierInit; - - /* done it */ - return pNew; -}