/*
 * SR830 Lock-in AMP device support
 */

#include <epicsStdio.h>
#include <devCommonGpib.h>
#include <string.h>
#include <strings.h>
#include <stdio.h>
#include <stdlib.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     devAiSR830
#define DSET_AO     devAoSR830
#define DSET_BI     devBiSR830
#define DSET_BO     devBoSR830
#define DSET_EV     devEvSR830
#define DSET_LI     devLiSR830
#define DSET_LO     devLoSR830
#define DSET_MBBI   devMbbiSR830
#define DSET_MBBID  devMbbidSR830
#define DSET_MBBO   devMbboSR830
#define DSET_MBBOD  devMbbodSR830
#define DSET_SI     devSiSR830
#define DSET_SO     devSoSR830
#define DSET_WF     devWfSR830

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

#define TIMEOUT     1.0    /* I/O must complete within this time */
#define TIMEWINDOW  2.0    /* Wait this long after device timeout */


static float get_onedata(char wa1[]);
static int rd_data(char wav[], float temp[]);
static int rd_wf_data(struct gpibDpvt *pdpvt, int p1, int p2, char **p3);

/*static int rd_efast_data(struct gpibDpvt *pdpvt,  int p1, int p2, char **p3);
 */

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

/******************************************************************************
 * 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.
 ******************************************************************************/


/******************************************************************************
 * String arrays for EFAST operations. The last entry must be 0.
 *
 * On input operations,only as many bytes as are found in the string array
 * elements are compared.  Additional bytes are ignored.
 * The first matching string  will be used as a match.
 *
 * For the input operations,the strings are compared literally!  This
 * can cause problems if the instrument is returning things like  and \n
 * characters.  When defining input strings so you include them as well.
 ******************************************************************************/



/******************************************************************************
 * Array of structures that define all GPIB messages
 * supported for this type of instrument.
 ******************************************************************************/
static struct gpibCmd gpibCmds[] = { 

    /* CMMAND 0 set referece phase shift */
  {&DSET_AO, GPIBWRITE, IB_Q_LOW, NULL,"PHAS %lf\n", 0, 2047, NULL, 0, 0, NULL, NULL, NULL },
  /* CMD 1 read reference phase shift */
  {&DSET_AI, GPIBREAD, IB_Q_LOW,"PHAS?\n","%lf\n",0,2047,NULL,0,0,NULL,NULL,NULL}, 
  /* CMD 2 set freq */
  {&DSET_AO, GPIBWRITE, IB_Q_LOW, NULL,"FREQ %lf\n",0,2047,NULL,0,0,NULL,NULL,NULL},
  /* CMD 3 read freq */
  {&DSET_AI, GPIBREAD, IB_Q_LOW,"FREQ?\n","%lf\n",0,2047,NULL,0,0,NULL,NULL,NULL},
  /* CMD 4 set output amplitude */
  {&DSET_AO, GPIBWRITE,IB_Q_LOW,NULL,"SLVL %lf\n",0,2047,NULL,0,0,NULL,NULL,NULL},
  /* CMD 5 read output amplitude */
  {&DSET_AI,GPIBREAD,IB_Q_LOW,"SLVL?\n","%lf\n",0,2047,NULL,0,0,NULL,NULL,NULL},
  /* CMD 6 set SENS */
  {&DSET_LO, GPIBWRITE, IB_Q_LOW, NULL,"SENS %d\n",0,2047,NULL,0,0,NULL,NULL,NULL},
  /* CMD 7 read SENS */
  {&DSET_LI,GPIBREAD,IB_Q_LOW,"SENS?\n","%d\n",0.2047,NULL,0,0,NULL,NULL,NULL},
  /* CMD 8 set OFLT */
  {&DSET_LO,GPIBWRITE,IB_Q_LOW,NULL,"OFLT %d\n",0,2047,NULL,0,0,NULL,NULL,NULL},
  /* CMD 9 read OFLT */
  {&DSET_LI,GPIBREAD,IB_Q_LOW,"OFLT?\n","%d\n",0,2047,NULL,0,0,NULL,NULL,NULL},
  /* CMD 10 read detected amplitude */
  {&DSET_AI,GPIBREAD,IB_Q_LOW,"OUTP? 3\n","%lf\n",0,2047,NULL,0,0,NULL,NULL,NULL},
  /* CMD 11 read detected phase in degree */
  {&DSET_AI,GPIBREAD,IB_Q_LOW,"OUTP?4\n","%lf\n",0,2047,NULL,0,0,NULL,NULL,NULL},
  /* CMD 12 read X */
  {&DSET_AI,GPIBREAD,IB_Q_LOW,"OUTP?1\n","%lf\n",0,2047,NULL,0,0,NULL,NULL,NULL},
  /* CMD 13 read Y*/
  {&DSET_AI,GPIBREAD,IB_Q_LOW,"OUTP?2\n","%lf\n",0,2047,NULL,0,0,NULL,NULL,NULL}
  ,
  /* CMD 14 fast acquision */
  {&DSET_LO,GPIBWRITE,IB_Q_LOW,NULL,"OUTX 1;FAST 2\n",0,2047,NULL,0,0,NULL,NULL,NULL},
  /* CMD 15 snap command */
  {&DSET_WF, GPIBREAD, IB_Q_LOW,"SNAP?1,2,3,4,9\n",NULL,0,819100,rd_wf_data,0,0,NULL,NULL,NULL}
 


};




/* The following is the number of elements in the command array above.  */
#define NUMPARAMS sizeof(gpibCmds)/sizeof(struct gpibCmd)

/******************************************************************************
 * Initialize device support parameters
 *
 *****************************************************************************/
static long init_ai(int parm)
{
    if(parm==0) {
        devSupParms.name = "devSR830";
        devSupParms.gpibCmds = gpibCmds;
        devSupParms.numparams = NUMPARAMS;
        devSupParms.timeout = TIMEOUT;
        devSupParms.timeWindow = TIMEWINDOW;
        devSupParms.respond2Writes = -1;
    }
    return(0);
}

/******************************************************************************
 *
 * c code
 *
 *****************************************************************************/
static float get_onedata(char wa1[])
{
  return atof(wa1);
}

static int rd_data(char wav[], float vdata[])
{

  int i;
  char wa1[819100];

  strcpy(wa1,strtok(wav,","));
  vdata[0] = get_onedata(wa1);

  for (i=1;i<5;i++)
    {
      strcpy(wa1,strtok(NULL,","));
      vdata[i]=get_onedata(wa1);
    }
  return 0;
}
 
static int rd_wf_data(struct gpibDpvt *pdpvt, int p1, int p2, char **p3)
{ 
  struct waveformRecord *pwf = (struct waveformRecord *) (pdpvt->precord);
  unsigned char *craw;
  float *temparray;
  float  temp[819100],*ptemp;
  int   s[819100],ok_flag;        
  unsigned long numElem;

  temparray = ( float *) pwf->bptr;
  craw = pdpvt->msg; 

  
  ok_flag = rd_data(craw,temp);
 

  if (ok_flag != 0) 
    {
      /* devGpibLib_setPvSevr(pwf,READ_ALARM, INVALID_ALARM); */
      /*  logMsg("Not OK SR830\n"); */
      return(-1);
    }
  
  numElem = 5;
  if (numElem > pwf->nelm)      numElem = pwf->nelm;
  pwf->nord = numElem;
  ptemp=temp;   
  while (numElem--)
    {
      /*   printf( "\n%d-th data: %f",numElem, *ptemp);  */  
      *temparray++ = (float) *ptemp++;
    }
  /*  logMsg( "\nread_wf end normally\n"); */
  return(0);
}


mailto: makoto.tobiyama@kek.jp
Last update: 16/Sep/2011