/*************************************************************************\
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
*     National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
*     Operator of Los Alamos National Laboratory.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution. 
\*************************************************************************/
/* devSkeletonGpib.c */
/* devAB300.c,v 1.1 2003/09/02 19:00:46 norume Exp */
/*
 * 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     devAB300_ai
#define DSET_LI     devAB300_li
#define DSET_LO     devAB300_lo

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


/******************************************************************************
 *
 * Debugging flag
 *
 ******************************************************************************/
static int devAB300Debug = 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     5000       /* I/O must complete within 5 seconds */


/*
 * Custom conversion routines
 */
static int
convertPositionReply(struct gpibDpvt *pdpvt, int P1, int P2, char **P3)
{
    struct longinRecord *pli = ((struct longinRecord *)(pdpvt->precord));

    if( pdpvt->msg[2] == '\030')
        pli->val = pdpvt->msg[0];
    else
        recGblSetSevr(pli, READ_ALARM, INVALID_ALARM);
    return 0;
}
static int
convertStatusReply(struct gpibDpvt *pdpvt, int P1, int P2, char **P3)
{
    struct longinRecord *pli = ((struct longinRecord *)(pdpvt->precord));

    if( pdpvt->msg[2] == '\030')
        pli->val = pdpvt->msg[1];
    else
        recGblSetSevr(pli, READ_ALARM, INVALID_ALARM);
    return 0;
}

/******************************************************************************
 *
 * Array of structures that define all GPIB messages
 * supported for this type of instrument.
 *
 ******************************************************************************/

static struct gpibCmd gpibCmds[] = {
    /* Param 0 -- Device Reset */
    {&DSET_LO, GPIBWRITE|GPIBEOS, IB_Q_HIGH, NULL, "\377\377\033", 10, 10,
        NULL, 0, 0, NULL, NULL, '\033'},

    /* Param 1 -- Go to new filter position */
    {&DSET_LO, GPIBWRITE|GPIBEOS, IB_Q_LOW, NULL, "\017%c", 10, 10,
        NULL, 0, 0, NULL, NULL, '\030'},

    /* Param 2 -- Query filter position */
    {&DSET_LI, GPIBREAD|GPIBEOS, IB_Q_LOW, "\035", NULL, 0, 10,
        convertPositionReply, 0, 0, NULL, NULL, '\030'},

    /* Param 3 -- Query controller status */
    {&DSET_LI, GPIBREAD|GPIBEOS, IB_Q_LOW, "\035", NULL, 0, 10,
        convertStatusReply, 0, 0, NULL, NULL, '\030'}
};

/* 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 = &devAB300Debug;
        devSupParms.respond2Writes = 0;
        devSupParms.timeWindow = TIME_WINDOW;
        devSupParms.hwpvtHead = 0;
        devSupParms.gpibCmds = gpibCmds;
        devSupParms.numparams = NUMPARAMS;
        devSupParms.magicSrq = -1;
        devSupParms.name = "AB300";
        devSupParms.timeout = IO_TIME;
        devSupParms.srqHandler = devGpibLib_srqHandler;
        devSupParms.wrConversion = NULL;
    }
    return(devGpibLib_initDevSup(parm,&DSET_AI));
}
