/* * R&S RTA4004 oscilloscope 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     devAiRTA4004
#define DSET_AO     devAoRTA4004
#define DSET_BI     devBiRTA4004
#define DSET_BO     devBoRTA4004
#define DSET_EV     devEvRTA4004
#define DSET_LI     devLiRTA4004
#define DSET_LO     devLoRTA4004
#define DSET_MBBI   devMbbiRTA4004
#define DSET_MBBID  devMbbidRTA4004
#define DSET_MBBO   devMbboRTA4004
#define DSET_MBBOD  devMbbodRTA4004
#define DSET_SI     devSiRTA4004
#define DSET_SO     devSoRTA4004
#define DSET_WF     devWfRTA4004

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

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


static int rd_wf_data2(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.
 ******************************************************************************/
static char  *AcqStatList[]={"RUN","STOP","COMP","BRE"};
static unsigned long AcqStatVal[] ={0, 1, 2, 3};
static struct devGpibNames AcqStat = {4, AcqStatList, AcqStatVal, 4};
static char *(AcqStatR[])={"RUN","STOP","COMP","BRE",NULL};

/******************************************************************************
 * 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.
 ******************************************************************************/
#define EOSLN NULL


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

    /* COMMAND 0 initialize 1 */
  {&DSET_BO, GPIBWRITE, IB_Q_LOW, NULL,"CHAN:TYPE SAMPLE\n", 0, 2047, NULL, 0, 0, NULL, NULL, EOSLN },
  /* command 1 init 2 */
  {&DSET_BO, GPIBWRITE, IB_Q_LOW, NULL,"FORMAT:DATA REAL,32\n", 0, 2047, NULL, 0, 0, NULL, NULL, EOSLN }
  /* command 2 init 3 */,
  {&DSET_BO, GPIBWRITE, IB_Q_LOW, NULL,"FORMAT:BORDER LSBF\n", 0, 2047, NULL, 0, 0, NULL, NULL, EOSLN },
  /* command 3 init 4 */
  {&DSET_BO, GPIBWRITE, IB_Q_LOW, NULL,"CHAN:DATA:POIN DMAX\n", 0, 2047, NULL, 0, 0, NULL, NULL, EOSLN },
  /* command 4 RST */
  {&DSET_BO, GPIBWRITE, IB_Q_LOW, NULL, "*RST\n",0, 2047, NULL, 0, 0, NULL, NULL, EOSLN},
 
  /* command 5 single shot number */
  {&DSET_BO, GPIBWRITE, IB_Q_LOW, NULL, "ACQ:NSING:COUNT 1\n",0,2047, NULL, 0,0, NULL, NULL, EOSLN},
  /* command 6 stop running */
  {&DSET_BO, GPIBWRITE, IB_Q_LOW, NULL, "STOP\n",0,2047, NULL, 0,0, NULL, NULL,EOSLN},
  /* command 7 operation complete */
  {&DSET_MBBI, GPIBEFASTI,IB_Q_LOW, "ACQ:STAT?\n",NULL,0,2047, NULL,0,0,AcqStatR, &AcqStat, EOSLN},
  /* Command 8 CH1 Voltage read */
  {&DSET_AI, GPIBREAD, IB_Q_LOW, "CHAN1:SCALE?\n","%lf\n",0,2047,NULL,0,0,NULL,NULL,EOSLN },
  /* Command 9 CH2 Voltage read */
  {&DSET_AI, GPIBREAD, IB_Q_LOW, "CHAN2:SCALE?\n","%lf\n",0,2047,NULL,0,0,NULL,NULL,EOSLN },
  /* Command 10 CH3 Voltage read */
  {&DSET_AI, GPIBREAD, IB_Q_LOW, "CHAN3:SCALE?\n","%lf\n",0,2047,NULL,0,0,NULL,NULL,EOSLN },
  /* Command 11 CH4 Voltage read */
  {&DSET_AI, GPIBREAD, IB_Q_LOW, "CHAN4:SCALE?\n","%lf\n",0,2047,NULL,0,0,NULL,NULL,EOSLN },
  /* Command 12 CH1 Voltage set */
  {&DSET_AO, GPIBWRITE, IB_Q_LOW, NULL,"CHAN1:SCALE %lf\n",0,2047,NULL,0,0,NULL,NULL,EOSLN },
  /* Command 13 CH2 Voltage set */
  {&DSET_AO, GPIBWRITE, IB_Q_LOW, NULL,"CHAN2:SCALE %lf\n",0,2047,NULL,0,0,NULL,NULL,EOSLN },
  /* Command 14 CH3 Voltage set */
  {&DSET_AO, GPIBWRITE, IB_Q_LOW, NULL,"CHAN3:SCALE %lf\n",0,2047,NULL,0,0,NULL,NULL,EOSLN },
  /* Command 15 CH4 Voltage set */
  {&DSET_AO, GPIBWRITE, IB_Q_LOW, NULL,"CHAN4:SCALE %lf\n",0,2047,NULL,0,0,NULL,NULL,EOSLN },
  /* command 16 CH1 read */
  {&DSET_WF, GPIBREAD, IB_Q_LOW, "CHAN1:DATA?\n",NULL,0,5000000, rd_wf_data2, 0, 0, NULL, NULL, NULL},
  /* command 17 CH2 read */
  {&DSET_WF, GPIBREAD, IB_Q_LOW, "CHAN2:DATA?\n",NULL,0,5000000, rd_wf_data2, 0, 0, NULL, NULL, NULL},
  /* command 18 CH3 read */
  {&DSET_WF, GPIBREAD, IB_Q_LOW, "CHAN3:DATA?\n",NULL,0,5000000, rd_wf_data2, 0, 0, NULL, NULL, NULL},
  /* command 19 CH4 read */
  {&DSET_WF, GPIBREAD, IB_Q_LOW, "CHAN4:DATA?\n",NULL,0,5000000, rd_wf_data2, 0, 0, NULL, NULL, NULL},
  /* command 20 CH1 XINC */
  {&DSET_AI, GPIBREAD, IB_Q_LOW, "CHAN1:DATA:XINC?\n", "%lf\n",0, 2047, NULL, 0,0, NULL, NULL, EOSLN},
  /* command 21 CH2 XINC */
  {&DSET_AI, GPIBREAD, IB_Q_LOW, "CHAN2:DATA:XINC?\n", "%lf\n",0, 2047, NULL, 0,0, NULL, NULL, EOSLN},
  /* command 22 CH1 XINC */
  {&DSET_AI, GPIBREAD, IB_Q_LOW, "CHAN3:DATA:XINC?\n", "%lf\n",0, 2047, NULL, 0,0, NULL, NULL, EOSLN},
  /* command 23 CH2 XINC */
  {&DSET_AI, GPIBREAD, IB_Q_LOW, "CHAN4:DATA:XINC?\n", "%lf\n",0, 2047, NULL, 0,0, NULL, NULL, EOSLN},
  /* command 24 TRG* */
  {&DSET_BO, GPIBWRITE, IB_Q_LOW,NULL,"*TRG\n",0,2047, NULL, 0,0, NULL, NULL, EOSLN},
  /* command 25 timebase read */
  {&DSET_AI, GPIBREAD, IB_Q_LOW, "TIM:SCAL?\n","%lf\n",0,2047, NULL, 0, 0, NULL, NULL, EOSLN},
  /* command 26 timebase setting */
  {&DSET_AO, GPIBREAD, IB_Q_LOW, NULL,"TIM:SCAL %lf\n",0,2047, NULL, 0, 0, NULL, NULL, EOSLN},
  /* command 27 single trigger */
  {&DSET_BO, GPIBWRITE, IB_Q_LOW, NULL, "SING\n",0,2047, NULL, 0,0, NULL, NULL, EOSLN},


 
};




/* 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 = "devRTA4004";
        devSupParms.gpibCmds = gpibCmds;
        devSupParms.numparams = NUMPARAMS;
        devSupParms.timeout = TIMEOUT;
        devSupParms.timeWindow = TIMEWINDOW;
        devSupParms.respond2Writes = -1;
    }
    return(0);
}

/******************************************************************************
 *
 * c code
 *
 *****************************************************************************/



static int rd_wf_data2(struct gpibDpvt *pdpvt, int p1, int p2, char **p3)
{
  struct waveformRecord *pwf = (struct waveformRecord *)(pdpvt ->precord);
  char *craw;
  char ll[24000000];
  int n,n1;
  float *temparray, *lx,lf[4000000];

  unsigned long numElem;

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

  strncpy(ll,craw,1);
  ll[1]=NULL;
 
  /*   
   printf("craw 1st %s\n",ll);

   if (strcmp(ll,"#")!=0){
    printf("Invalid data  %s\n",ll);
    return(-1); 
    } 
  */
 
  strncpy(ll,craw+1,1);
  ll[1]=NULL;
  n = atoi(ll);
  /*
  printf("n= %d\n",n);
  */

  strncpy(ll,craw+2,n);
  ll[n]=NULL;
  /*
  printf("ll %s\n",ll);
  */
  n1 = atoi(ll);
 
  /*
  printf("n= %d n1 =%d\n",n,n1);
  */  
  numElem = n1 >>2;
  /* 
  printf("numElem %ld\n",numElem);  
  */
 
  memcpy(ll,craw+2+n,n1); 
  lx = (float *)ll;


 
 
  while(numElem--){
    *temparray++ =  *lx++;
  }
 
  pwf->nord = numElem;
      
 
return(0); }