/*
  scpi.c

  Copyright 12-Aug-2013 MBARI
  Written: 12-Aug-2013 Hans THomas 
  Last mod: 12-Aug-2013 hans- creation

  Interface library to sn SCPI power supply
*/

#include <stdio.h>
#include "scpi.h"
#include "serial.h"
#include "error.h"

#define MAX_VOLT (45.0)
#define MAX_CURRENT (60.0)
#define SCPI_SERIAL_RETRY (10) /* 10x !!! */

// CLR command
int scpiInit (int scpi_port)
{
  return (sendStr (scpi_port, "SYST:SET REM;\r"));
}

// OUT 1 command
int scpiEnableOutput (int scpi_port)
{
  return (sendStr (scpi_port, "OUTP:STAT ON;\r"));
}

// OUT 0 command
int scpiDisableOutput (int scpi_port)
{
  return (sendStr (scpi_port, "OUTP:STAT OFF;\r"));
}

// OVSET command
int scpiOverVoltSet (int scpi_port, double ovp)
{
  char str[20];

  if (ovp < 0.0 || ovp > MAX_VOLT)
  {
    ERROR ("err: xfrOverVoltSet(%f) > %f\n", ovp, MAX_VOLT);
    return ERROR_ARG;
  }

  sprintf (str, ":VOLT:PROT:LEV %0.2f;\r", ovp);
  
  return (sendStr (scpi_port, str));
}

// RST command
int scpiReset (int scpi_port)
{
  return (sendStr (scpi_port, "*RST;\r"));
}

// TRG command
int scpiTrigger (int scpi_port)
{
//  return (sendStr (scpi_port, "TRG\r"));
    return 1;
}

// VMAX command
int scpiVMax (int xfr_port, double Vmax)
{
  char str[20];

  if (Vmax < 0.0 || Vmax > MAX_VOLT)
  {
    ERROR ("err: xfrVMax(%f) > %f\n", Vmax, MAX_VOLT);
    return ERROR_ARG;
  }

  sprintf (str, ":VOLT %0.2f;\r", Vmax);
  return (sendStr (xfr_port, str));
}

// VSET command
int scpiSetVolts (int scpi_port, double volts)
{
  char str[20];

  if (volts < 0.0 || volts >= MAX_VOLT)
  {
    ERROR ("err: xfrSetVolts(%f) >= %f\n", volts, MAX_VOLT);
    return ERROR_ARG;
  }

  sprintf (str, ":VOLT %0.2fV\r", volts);
  return (sendStr (scpi_port, str));
}

// IMAX command
int scpiIMax (int xfr_port, double current)
{
  char str[20];

  ASSERT (current >= 0.0 && current <= MAX_CURRENT);

  sprintf (str, ":CURR %0.2f;\r", current);
  return (sendStr (xfr_port, str));
}

// ISET command
int scpiSetCurrent (int xfr_port, double current)
{
  char str[20];

  ASSERT (current >= 0.0 && current <= MAX_CURRENT);

  sprintf (str, ":CURR %0.2f;\r", current);
  return (sendStr (xfr_port, str));
}

// IOUT? command
int scpiGetIOut (int xfr_port, double *Iout)
{
  int ret;
  char str[20];
  int retry;
  
  for (ret=-1,retry=0; retry<SCPI_SERIAL_RETRY && ret<=0; ++retry)
  {
	  flushRecv (xfr_port);

	  if ((ret = sendStr (xfr_port, "MEAS:CURR?;\r")) < 0)
	  {
		  ERROR ("err: xfrGetIOut: sendStr returned %d\n", ret);
		  return ret;
	  }
	  
	  if ((ret = recvStr (xfr_port, str, 20)) < 0)
	  {
		  ERROR ("err: xfrGetIOut: recvStr returned %d\n", ret);
			//return ret;
	  }
  }
  
  ret = sscanf(str, "%lf", Iout);
  DEBUG (1, "xfrGetIOut = %f, sscanf returned %d\n", *Iout, ret);
  return ret;
}

// ISET? command
int scpiGetISet (int xfr_port, double *Iset)
{
  int ret;
  char str[20];
  int retry;
  
  for (ret=-1,retry=0; retry<SCPI_SERIAL_RETRY && ret<=0; ++retry)
  {
	  flushRecv (xfr_port);
	  
	  if ((ret = sendStr (xfr_port, ":CURR?\r")) < 0)
	  {
		  ERROR ("err: xfrGetISet: sendStr returned %d\n", ret);
		  return ret;
	  }
	  
	  if ((ret = recvStr (xfr_port, str, 20)) < 0)
	  {
		  ERROR ("err: xfrGetISet: recvStr returned %d\n", ret);
			//return ret;
	  }
  }
  

  ret = sscanf(str, "ISET %lf", Iset);
  DEBUG (1, "xfrGetISet = %f, sscanf returned %d\n", *Iset, ret);
  return ret;
}

// OUT? command
int scpiGetOut (int xfr_port, int *status)
{
  int ret;
  char str[20];
  int retry;
  
  for (ret=-1,retry=0; retry<SCPI_SERIAL_RETRY && ret<=0; ++retry)
  {
	  flushRecv (xfr_port);
	  
	  if ((ret = sendStr (xfr_port, "OUTP:STAT?;\r")) < 0)
	  {
		  ERROR ("err: xfrGetOut: sendStr returned %d\n", ret);
		  return ret;
	  }
	  
	  if ((ret = recvStr (xfr_port, str, 20)) < 0)
	  {
		  ERROR ("err: xfrGetOut: recvStr returned %d\n", ret);
			//return ret;
	  }
  }

  if (!strncmp("ON", str,2)) ret = 1; else ret=0;
  DEBUG (1, "xfrGetOut = %d, sscanf returned %d\n", *status, ret);
  return ret;
}

// VOUT? command
int scpiGetVOut (int xfr_port, double *volts)
{
  int ret;
  char str[20];
  int retry;
  
  for (ret=-1,retry=0; retry<SCPI_SERIAL_RETRY && ret<=0; ++retry)
  {
	  flushRecv (xfr_port);
	  
	  if ((ret = sendStr (xfr_port, "MEAS:VOLT?;\r")) < 0)
	  {
		  ERROR ("err: xfrGetVout: sendStr returned %d\n", ret);
		  return ret;
	  }
	  
	  if ((ret = recvStr (xfr_port, str, 20)) < 0)
	  {
		  ERROR ("err: xfrGetVout: recvStr returned %d\n", ret);
			//return ret;
	  }
  }
  
  ret = sscanf(str, "%lf", volts);
  DEBUG (1, "xfrGetVout = %f, sscanf returned %d\n", *volts, ret);
  return ret;
}

// VSET? command
int scpiGetVSet (int xfr_port, double *Vset)
{
  int ret;
  char str[20];
  int retry;
  
  for (ret=-1,retry=0; retry<SCPI_SERIAL_RETRY && ret<=0; ++retry)
  {
	  flushRecv (xfr_port);
	  
	  if ((ret = sendStr (xfr_port, ":VOLT?;\r")) < 0)
	  {
		  ERROR ("err: xfrGetVset: sendStr returned %d\n", ret);
		  return ret;
	  }
	  
	  if ((ret = recvStr (xfr_port, str, 20)) < 0)
	  {
		  ERROR ("err: xfrGetVset: recvStr returned %d\n", ret);
			//return ret;
	  }
  }
  
  ret = sscanf(str, "%lf", Vset);
  DEBUG (1, "xfrGetVset = %f, sscanf returned %d\n", *Vset, ret);
  return ret;
}

// ERR? command
int scpiGetErr (int xfr_port, int *err)
{
  int ret;
  char str[20];
  int retry;
  
  for (ret=-1,retry=0; retry<SCPI_SERIAL_RETRY && ret<=0; ++retry)
  {
	  flushRecv (xfr_port);
	  
	  if ((ret = sendStr (xfr_port, "STAT:OPER:COND?;\r")) < 0)
	  {
		  ERROR ("err: xfrGetErr: sendStr returned %d\n", ret);
		  return ret;
	  }
	  
	  if ((ret = recvStr (xfr_port, str, 20)) < 0)
	  {
		  ERROR ("err: xfrGetErr: recvStr returned %d\n", ret);
			//return ret;
	  }
  }
  
  ret = sscanf(str, "%d", err);
  DEBUG (1, "xfrGetErr = %d, sscanf returned %d\n", *err, ret);
  return ret;
}

 // ASTS?, STS?, and FAULT? commands
int scpiGetStatus (int xfr_port, int *astatus, int *status, int *fault)
{
  int ret;
  char str[20];
  int retry;

  *astatus = *status = *fault = 0;
  return 1;

#ifdef FALSE   
  for (ret=-1,retry=0; retry<SCPI_SERIAL_RETRY && ret<=0; ++retry)
  {
		// ASTS? command
	  flushRecv (xfr_port);
	  
	  if ((ret = sendStr (xfr_port, "ASTS?\r")) < 0)
	  {
		  ERROR ("err: xfrGetStatus: sendStr returned %d\n", ret);
		  return ret;
	  }
	  
	  if ((ret = recvStr (xfr_port, str, 20)) < 0)
	  {
		  ERROR ("err: xfrGetStatus: recvStr returned %d\n", ret);
			//return ret;
	  }
  }
  
  ret = sscanf(str, "ASTS %d", astatus);
  DEBUG (1, "xfrGetStatus = %d, sscanf returned %d\n", *astatus, ret);

  for (ret=-1,retry=0; retry<SCPI_SERIAL_RETRY && ret<=0; ++retry)
  {
		// STS? command
	  flushRecv (xfr_port);
	  
	  if ((ret = sendStr (xfr_port, "STS?\r")) < 0)
	  {
		  ERROR ("err: xfrGetStatus: sendStr returned %d\n", ret);
		  return ret;
	  }
	  
	  if ((ret = recvStr (xfr_port, str, 20)) < 0)
	  {
		  ERROR ("err: xfrGetStatus: recvStr returned %d\n", ret);
			//return ret;
	  }
  }
  
  ret = sscanf(str, "STS %d", status);
  DEBUG (1, "xfrGetStatus = %d, sscanf returned %d\n", *status, ret);

  for (ret=-1,retry=0; retry<SCPI_SERIAL_RETRY && ret<=0; ++retry)
  {
		// FAULT? command
	  flushRecv (xfr_port);
	  
	  if ((ret = sendStr (xfr_port, "FAULT?\r")) < 0)
	  {
		  ERROR ("err: xfrGetStatus: sendStr returned %d\n", ret);
		  return ret;
	  }
	  
	  if ((ret = recvStr (xfr_port, str, 20)) < 0)
	  {
		  ERROR ("err: xfrGetStatus: recvStr returned %d\n", ret);
			//return ret;
	  }
  }
  
  ret = sscanf(str, "FAULT %d", fault);
  DEBUG (1, "xfrGetStatus = %d, sscanf returned %d\n", *fault, ret);

  return ret;
#endif
}
