/*---------------------------------------------------------------------------
eve.h

extended environment controller utilities
  
Markus Zolliker, Sept 2004
----------------------------------------------------------------------------*/

#ifndef EVE_H
#define EVE_H

#include "fsm.h"
#include "evcontroller.h"
#include "rs232controller.h"

typedef enum { idleState, readState, expectState, lostState } EveState;

typedef struct EveParArg EveParArg;
typedef struct EvePar EvePar;

/* the parameter definition function may call any parameter function (see below) */
typedef void (*EveParDef)(void *private, EveParArg *arg);

typedef int (*EveSubCmd)(SConnection *pCon, pEVControl evc, int argc, char *argv[]);

/* Eve must always be the first member of the EVCs private struct */

typedef struct Eve {
  EveParDef pardef;
  rs232 *ser;
  Fsm *task; /* a pointer to the task */
  FsmFunc todo;
  FsmFunc run;
  FsmFunc read;
  int hwstate;
  pEVControl evc;
  int errCode; /* error code of last operation. not changed on success  */
  int verbose;
  EveState state;
  time_t cmdtime;
  float value;
  int lost;
  int syntax; /* not used in Eve, may be used by the driver. used by OiConn */
  char cmd[32];
  char ans[64];
  char version[64];
  int (*checkStatus)(void *self, SConnection *pCon); /* original CheckStatus function */
  EvePar *par;
  int npar;
  time_t logtime;
  int period;
  char errMsg[128];
} Eve;

#define EVE_ACTPAR 1
#define EVE_LOGPAR 2
#define EVE_SAVEPAR 4

/* parameter functions (pfs)
*  -------------------------
*  there are some restrictions:
*
*  - pfs may only be called from within the pardef function
*  - the order and number of pfs must not change at runtime
*
*  Arguments:
* 
*  arg:      just the arg Argument in pardef
*  name:     parameter name, must be static and never changed
*            (usually a string literal)
*  value:    a pointer to the corr. member of the drivers private struct
*  fmt:      a format. if it contains a blank, the content after the blank is
*            skipped when not listing
*  access:   a SICS access mode (usInternal, usMugger, usUser, usSpy)
*  flags:    the sum of some flags values:
*             EVE_ACTPAR: parameter is active
*             EVE_LOGPAR: parameter is logged by default
*             EVE_SAVEPAR: parameter is saved on sics exit
*  maxsize:  the maximum size of a fixed size string, or 0 for a dynamic string
*  index:    the ObPar index
*  list:     a NULL terminated list of value names
*  subcmd:   a function for handling the subcommand
*  fsmFunc:  a fsm function to handle a subcommand
*/
void EveFloatPar(EveParArg *arg, char *name, float *value, char *fmt,
                 int access, int flags);
void EveIntPar(EveParArg *arg, char *name, int *value,
                 int access, int flags);
void EveStrPar(EveParArg *arg, char *name, char **value, int maxsize,
                 int access, int flags);
void EveObPar(EveParArg *arg, int index, char *fmt, int flags);
void EveObParEnum(EveParArg *arg, int index, char *list[], int flags);
void EveEnumPar(EveParArg *arg, char *name, int *value, char *list[],
                 int access, int flags);
void EveCmd(EveParArg *arg, char *name, EveSubCmd subcmd, int access);
void EveFloatCmd(EveParArg *arg, char *name, float *value, char *fmt,
                 FsmFunc fsmFunc, int access, int flags);
                 
/* a collection of parameters from the standard EVController
*  (limits, tolerance, drive handling, out of tolerance handling)
*  normally appearing at the top
*/
void EveStdPar(EveParArg *arg);

/* some even more standard values (should always be used)
*  appearing at the end of the list
*/
void EveStdParEnd(EveParArg *arg, char *fmt, int targetFlag);

/* return the connection related to the parameter request */
SConnection *EveArgConn(EveParArg *arg);

/* check if it is a user action (parameter list, set or read) */
int EveUserAction(EveParArg *arg);

/* write to the actual (last driving) connection */
int EvePrintf(Eve *eve, int iOut, char *fmt, ...);

/* evelog has to be called after all read operations */
void EveLog(Eve *eve);

void EveWriteError(Eve *eve);
void EveWrite(Eve *eve, char *cmd);
void EveWaitRead(Eve *eve);
int EveHandler(Eve *eve);
int EveIdle(long pc, Eve *eve);
int EveRun(pEVDriver driver, float fVal);
int EveSend(pEVDriver driver, char *pCommand, char *pReply, int iLen);
int EveCheckStatus(void *evcVoid, SConnection *pCon);
EVMode EveGetMode(void *data);
int EveClose(pEVDriver driver);
int EveAlwaysOk(void *data);
int EveDontFix(pEVDriver driver, int iError);
void EveKill(void *pData);
int EveGetError(pEVDriver driver, int *iCode, char *error, int iErrLen);
int EveInit(pEVDriver driver);
pEVDriver MakeEveDriver(int argc, char *argv[], Eve *eve, SConnection *pCon);
int EveWrapper(SConnection *pCon, SicsInterp *pSics, void *pData,
               int argc, char *argv[]);
pEVControl MakeEveEVC(int argc, char *argv[], Eve *eve, SConnection *pCon);

#define EVE_ILL_ANS -3000
#define EVE_FAULT -3001
#define EVE_DEV_CHANGED -3002

#endif
