/* devSkeletonGpib.c */
/* devSkeletonGpib.c,v 1.8 2003/04/10 15:17:02 mrk Exp */
/***********************************************************************
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* National Laboratory, and the Regents of the University of
* California, as Operator of Los Alamos National Laboratory, and
* Berliner Elektronenspeicherring-Gesellschaft m.b.H. (BESSY).
* gpibCore is distributed subject to a Software License Agreement
* found in file LICENSE that is included with this distribution.
***********************************************************************/
/*
 * Based on devXxSkeletonGpib.c:
 *      Original Author: John Winans
 *      Date:            02-18-92
 */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <alarm.h>
#include <recGbl.h>
#include <devCommonGpib.h>


/******************************************************************************
 *
 * The following define statements are used to declare the names to be used
 * for the dset tables.   
 *
 * A DSET_AI entry must be declared here and referenced in an application
 * database description file even if the device provides no AI records.
 *
 ******************************************************************************/
#define DSET_AI     devAiSkeletonGpib
#define DSET_AO     devAoSkeletonGpib
#define DSET_LI     devLiSkeletonGpib
#define DSET_LO     devLoSkeletonGpib
#define DSET_BI     devBiSkeletonGpib
#define DSET_BO     devBoSkeletonGpib
#define DSET_MBBI   devMbbiSkeletonGpib
#define DSET_MBBO   devMbboSkeletonGpib
#define DSET_SI     devSiSkeletonGpib
#define DSET_SO     devSoSkeletonGpib
#define DSET_EV     devEvSkeletonGpib

#include <devGpib.h> /* must be included after DSET defines */


/******************************************************************************
 *
 * Debugging flag
 *
 ******************************************************************************/
static int SkeletonDebug = 0;

/******************************************************************************
 *
 * TIME_WINDOW is the interval (in milliseconds) during which commands should
 * be ignored after the device times out. The ignored commands will appear
 * as errors to device support.
 *
 * IO_TIME is the interval (in milliseconds) in which an I/O operation must
 * complete.
 *
 ******************************************************************************/
#define TIME_WINDOW 2000       /* wait 2 seconds after device timeout */
#define IO_TIME     1000       /* I/O must complete within 1 second */

/******************************************************************************
 *
 * Strings used by the init routines to fill in the znam, onam, ...
 * fields in BI and BO record types.
 *
 ******************************************************************************/

static char  *offOnList[] = { "Off", "On" };
static struct devGpibNames   offOn = { 2, offOnList, NULL, 1 };

static char  *initNamesList[] = { "Init", "Init" };
static struct devGpibNames initNames = { 2, initNamesList, NULL, 1 };

static char  *disableEnableList[] = { "Disable", "Enable" };
static struct devGpibNames disableEnable = { 2, disableEnableList, NULL, 1 };

static char  *resetList[] = { "Reset", "Reset" };
static struct devGpibNames reset = { 2, resetList, NULL, 1 };

static char  *lozHizList[] = { "50 OHM", "IB_Q_HIGH Z" };
static struct devGpibNames lozHiz = {2, lozHizList, NULL, 1};

static char  *invertNormList[] = { "INVERT", "NORM" };
static struct devGpibNames invertNorm = { 2, invertNormList, NULL, 1 };

static char  *fallingRisingList[] = { "FALLING", "RISING" };
static struct devGpibNames fallingRising = { 2, fallingRisingList, NULL, 1 };

static char  *clearList[] = { "CLEAR", "CLEAR" };
static struct devGpibNames clear = { 2, clearList, NULL, 1 };

/******************************************************************************
 *
 * Structures used by the init routines to fill in the onst, twst,... and the
 * onvl, twvl,... fields in MBBI and MBBO record types.
 *
 * Note that the intExtSsBm and intExtSsBmStop structures use the same
 * intExtSsBmStopList and intExtSsBmStopVal lists but have a different number
 * of elements in them that they use... The intExtSsBm structure only represents
 * 4 elements, while the intExtSsBmStop structure represents 5.
 *
 ******************************************************************************/

static char           *intExtSsBmStopList[] = { "INTERNAL", "EXTERNAL",
                                "SINGLE SHOT", "BURST MODE", "STOP" };

static unsigned long   intExtSsBmStopVal[] = { 0, 1, 2, 3, 2 };

static struct devGpibNames intExtSsBm = { 4, intExtSsBmStopList, 
                                intExtSsBmStopVal, 2 };

static struct devGpibNames intExtSsBmStop = { 5, intExtSsBmStopList,
                                        intExtSsBmStopVal, 3 };

/******************************************************************************
 *
 * String arrays for EFAST operations.  Note that the last entry must be 
 * NULL.
 *
 * On input operations, only as many bytes as are found in the string array
 * elements are compared.  If there are more bytes than that in the input
 * message, they are ignored.  The first matching string found (starting
 * from the 0'th element) will be used as a match.
 *
 * NOTE: For the input operations, the strings are compared literally!  This
 * can cause problems if the instrument is returning things like \r and \n
 * characters.  You must take care when defining input strings so you include
 * them as well.
 *
 ******************************************************************************/

static char *(userOffOn[]) = {"USER OFF;", "USER ON;", NULL};

/******************************************************************************
 *
 * Array of structures that define all GPIB messages
 * supported for this type of instrument.
 *
 ******************************************************************************/

static struct gpibCmd gpibCmds[] = {
    /* Param 0 */
    {&DSET_BO, GPIBCMD, IB_Q_HIGH, "init", NULL, 0, 32,
      NULL, 0, 0, NULL, &initNames, -1},

    /* Param 1 */
    {&DSET_BO, GPIBEFASTO, IB_Q_HIGH, NULL, NULL, 0, 32,
      NULL, 0, 0, userOffOn, &offOn, -1},

    /* Param 2 */
    {&DSET_BI, GPIBEFASTI, IB_Q_HIGH, "user?", NULL, 0, 32,
      NULL, 0, 0, userOffOn, &offOn, -1},

    /* Param 3 */
    {&DSET_AI, GPIBREAD, IB_Q_LOW, "send", "%lf", 0, 32,
      NULL, 0, 0, NULL, NULL, -1}
};

/* The following is the number of elements in the command array above.  */
#define NUMPARAMS        sizeof(gpibCmds)/sizeof(struct gpibCmd)

/******************************************************************************
 *
 * Initialize device support parameters
 *
 * The magic SRQ parm is the parm number that, if specified on an I/O event
 * scanned record, will cause the record to be processed automatically when
 * an unsolicited SRQ interrupt is detected from the device.
 *
 *****************************************************************************/
static long init_ai(int parm)
{
    if(parm==0) {
        devSupParms.debugFlag = &SkeletonDebug;
        devSupParms.respond2Writes = -1;
        devSupParms.timeWindow = TIME_WINDOW;
        devSupParms.hwpvtHead = 0;
        devSupParms.gpibCmds = gpibCmds;
        devSupParms.numparams = NUMPARAMS;
        devSupParms.magicSrq = -1;
        devSupParms.name = "devSkeletonGpib";
        devSupParms.timeout = IO_TIME;
        devSupParms.srqHandler = devGpibLib_srqHandler;
        devSupParms.wrConversion = NULL;
    }
    return(devGpibLib_initDevSup(parm,&DSET_AI));
}
