From 966f8e30a8a309865b129dbe68855c6e55c8fb67 Mon Sep 17 00:00:00 2001 From: koennecke Date: Tue, 2 Apr 2013 15:13:36 +0000 Subject: [PATCH] - Removed old code - Extended tasker to support task groups - Added task functions for motors and counters - Modifed devexec to use the new task functions - Modified TAS to treat the monochromator separatly - Coded a EIGER monochromator module to reflect even more new requirements - Added EPICS counters and motors - Modified multicounter to be better performing --- A1931.c | 367 ------------- A1931.h | 20 - audinelib.c | 626 ---------------------- audinelib.h | 79 --- docho.c | 698 ------------------------ dornier2.c | 708 ------------------------- ecbcounter.c | 640 ---------------------- ecbcounter.h | 17 - ecbdriv.c | 1370 ----------------------------------------------- ecbdriv.h | 43 -- eigermono.c | 730 +++++++++++++++++++++++++ el734dc.c | 892 ------------------------------- el734driv.c | 905 ------------------------------- julcho.c | 1385 ------------------------------------------------ make_gen | 17 +- makefile_linux | 2 +- psi.c | 92 +--- sinqhttp.c | 7 + slsmagnet.c | 1024 ----------------------------------- velodorn.c | 385 -------------- velodorn.h | 58 -- velodornier.c | 636 ---------------------- 22 files changed, 754 insertions(+), 9947 deletions(-) delete mode 100644 A1931.c delete mode 100644 A1931.h delete mode 100644 audinelib.c delete mode 100644 audinelib.h delete mode 100644 docho.c delete mode 100644 dornier2.c delete mode 100644 ecbcounter.c delete mode 100644 ecbcounter.h delete mode 100644 ecbdriv.c delete mode 100644 ecbdriv.h create mode 100644 eigermono.c delete mode 100644 el734dc.c delete mode 100644 el734driv.c delete mode 100644 julcho.c delete mode 100644 slsmagnet.c delete mode 100644 velodorn.c delete mode 100644 velodorn.h delete mode 100644 velodornier.c 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; -}