/*---------------------------------------------------------------------------
oicom.c

Communication routines for Oxford Instruments equipment
  
Markus Zolliker, Aug 2004
----------------------------------------------------------------------------

there is no error return value, eve->errCode is used. On success, eve->errCode
is not changed, i.e. an existing errCode is not overwritten.
*/

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <fortify.h>
#include "sics.h"
#include "rs232controller.h"
#include "oicom.h"


/*----------------------------------------------------------------------------*/
int OiHandler(Eve *eve) {
  int iret, l;
  
  if (availableNetRS232(eve->ser)) {
    l = sizeof(eve->ans);
    iret = readRS232TillTerm(eve->ser, eve->ans, &l);
    if (eve->state < expectState) {
      if (iret == 1) {
        EvePrintf(eve, eError, "unexpected answer: %s", eve->ans);
      }
      goto quit;
    }
    if (iret == 1) {
      EvePrintf(eve, -2, "ans: %s", eve->ans);
      if (strcmp(eve->ans, "?ck") == 0) {
        if (eve->state == lostState) {
          EveWrite(eve, "V");
          goto quit;
        }
      } else if (eve->state == lostState) {
        goto quit;
      } else if (eve->cmd[0] == 'V') {
        if (strcmp(eve->ans, eve->version) == 0) {
          /* we are still connected with the same device */
        } else if (*eve->version == '\0') {
          strncat(eve->version, eve->ans, sizeof(eve->version)-1);
        } else { /* version (and therefore device) changed */
          eve->errCode = EVE_DEV_CHANGED;
          eve->state = idleState;
          goto error;
        }
        eve->state = idleState;
        goto quit;
      } else if (eve->cmd[1] == 'k') { /* ck */
      } else if (eve->cmd[0] != eve->ans[0]) {
        iret = EVE_ILL_ANS;
      }
    }
    if (iret != 1) {
      eve->errCode = iret;
      eve->state = idleState;
      goto error;
    }
    eve->state = readState;
  } else if (eve->state == expectState) {
    if (time(NULL) > eve->cmdtime+60) {
      eve->errCode = TIMEOUT;
      eve->state = lostState;
    }
  } else if (eve->state == lostState) {
    if (time(NULL) > eve->cmdtime) {
      EveWrite(eve, "ck");
      eve->state = lostState;
    }
  }
  goto quit;
error:
  EveWriteError(eve);
quit:
  return EveHandler(eve);
}

double OiGetFlt(Eve *eve, int dig, int *pdig) {
  char *endp, *p;
  double val;
  
  if (eve->state != readState) {
    /* eve->errCode = EVE_ILL_ANS; */
    return 0.0;
  }
  p = strchr(eve->ans, '.');
  if (p) {
    if (pdig != NULL) {
      *pdig = strlen(eve->ans) - (p - eve->ans) - 1;
    }
    val=strtod(eve->ans+1, &endp);
    if (*endp != '\0') {
      eve->errCode = EVE_ILL_ANS;
      return 0.0;
    }
  } else {
    val=strtol(eve->ans+1, &endp, 10);
    if (*endp != '\0') {
      eve->errCode = EVE_ILL_ANS;
      return 0.0;
    }
    if (eve->syntax == 0) { /* old style format */
      for (; dig > 0; dig--) val=val*0.1;
    }
  }
  return val;
}

void OiSet(Eve *eve, char *cmd, double val, int dig) {
  char buf[64];
  long lval;

  if (eve->syntax == 0) {
    snprintf(buf, sizeof(buf), "%s%.*f", cmd, dig, val);
  } else {
    snprintf(buf, sizeof(buf), "%s%f", cmd, val);
  }
  EveWrite(eve, buf);
}

