/****************************************************************************/
/*                                                                          */
/*  state_mgr.c                                                             */
/*                                                                          */
/*  PURPOSE:    This file contains a set of fuctions for keeping a model    */
/*              of the internal stae of the Mk4 system.                     */
/*              The current pointing possition, temperature and so on       */
/*              of the system is maintained by finctions in this file       */
/*                                                                          */
/*              Every time a command is send to the Mk4 a call to a         */
/*              "set_state" function must be made as well.  This function   */
/*              will record and timestamp the the command.  Later we        */
/*              can call a "get_state" function.  This will use rate        */
/*              information and the "delta t" between the set and get to    */
/*              compute by dead reconning the state at the requested time   */
/*                                                                          */
/*              The state table is never to be directly accessed.  Always   */
/*              use the functions in this file.                             */
/*                                                                          */
/****************************************************************************/


/* Used by RCS and ident */
char state_mgr_rcsid[] = 
    "$Id: state_mgr.c,v 1.1 1998/08/04 05:08:47 chris Exp $";
    
#include <stdio.h>
#include <string.h>
#include <errno.h>

#include "MLog.h"
#include "state_mgr.h"
#include "time_funct.h"


/****************************************************************************/
/*                                                                          */
/*  Attribute Table                                                         */
/*                                                                          */
/*  PURPOSE:                                                                */
/*      This table contains one entry per value that we want to track as    */
/*      part of our state model.                                            */
/*                                                                          */
/****************************************************************************/
/* Attribute Table Entry */
typedef struct
{
    int     Attribute;  /* code for specific state attribute                */
    int     CanSet;     /* May be set (step rate) or not (coolent temp)     */
    char    Name[32];   /* Name, used for display                           */
    double  MinValue;   /* Lowest valid value                               */
    double  MaxValue;   /* Highest valid value                              */    
    double  MinRate;    /* Lowest valid rate                                */
    double  MaxRate;    /* Highest valid rate                               */ 
} AttribEntryTyp;

/* Attribute table */
static AttribEntryTyp AT[MAX_ATTRIBUTE] =
{
    /*               Can                     Value           Rate           */
    /* Attribute     Set  Name             min  max      min     max        */
    {RA_STEP_COUNT,   1, "RA Step Count",  0.0, 20000.0, -200.0, 200.0},
    {DEC_STEP_COUNT,  1, "DEC Step Count", 0.0, 20000.0, -200.0, 200.0},
    {WATER_TEMP,      0, "Water Temp",     0.0, 40000.0,   -1.0,   1.0},
    {CCD_TEMP,        0, "CCD Temp",       0.0, 40000.0,   -1.0,   1.0}
}; 
        
/****************************************************************************/
/*                                                                          */
/* State Table       >>> Should be circular list <<<                        */
/*                                                                          */
/****************************************************************************/
/* State Table Entry */
typedef  struct
{
    double      value;      /* In Mk4 native units i.e. steps               */
    double      rate;       /* Change per second                            */
    double      time_stamp; /* Time at which Value & Rate was set           */
} StateEntryTyp;

/* State table */
/* For now we only hold one sample of each attribute.  Later we will        */
/* expand this if we need to.  (uncomment below and patch code)             */
/*#define ST_MEMSIZE    20                                                  */
/*static  StateEntryTyp   ST[MAX_ATTRIBUTE][ST_MEMSIZE];                    */
/*static  int             ST_next[MAX_ATTRIBUTE];       Next free slot in ST*/
static  StateEntryTyp   ST[MAX_ATTRIBUTE];


/****************************************************************************/
/*                                                                          */
/*  set_state_current                                                       */
/*                                                                          */
/*  PURPOSE:    Sets the current state of an attribute in the ST (State     */
/*              Table.)                                                     */
/*                                                                          */
/*  RETURNS:    0  = All is OK                                              */
/*              -1 = Error                                                  */
/*                                                                          */
/****************************************************************************/
int set_state_current(int Attrib, double Value, double Rate)
{
    ml_printf(ML_DEBUG, ML_INFORMATION, "set_state_current called.\n");
    return set_state_at(Attrib, get_epoc(), Value, Rate);
}

/****************************************************************************/
/*                                                                          */
/*  set_state_at                                                            */
/*                                                                          */
/*  PURPOSE:    Sets the state of an attribute in the ST (StateTable.)      */
/*              with a specified effective time                             */
/*                                                                          */
/*  RETURNS:    0  = All is OK                                              */
/*              -1 = Error                                                  */
/*                                                                          */
/*                                                                          */
/****************************************************************************/
int set_state_at(int Attrib, double TimeStamp,
                        double Value, double Rate)
{
    ml_printf(ML_DEBUG, ML_INFORMATION, "set_state_at called.\n");
    
    ST[Attrib].value      = Value;
    ST[Attrib].rate       = Rate;
    ST[Attrib].time_stamp = TimeStamp;
    
    return 0;
}
/****************************************************************************/
/*                                                                          */
/*  get_state_current                                                       */
/*                                                                          */
/*  PURPOSE:    Gets the current state of an attribute in the ST (State     */
/*              Table.)                                                     */
/*                                                                          */
/*  RETURNS:    0  = All is OK                                              */
/*              -1 = Error                                                  */
/*                                                                          */
/****************************************************************************/
int get_state_current(int Attrib, double *Value)
{
    ml_printf(ML_DEBUG, ML_INFORMATION, "get_state_current called.\n");
    return get_state_at(Attrib, get_epoc(), Value);
}

/****************************************************************************/
/*                                                                          */
/*  get_state_at                                                            */
/*                                                                          */
/*  PURPOSE:    Sets the state of an attribute in the ST (StateTable.)      */
/*              with a specified effective time                             */
/*                                                                          */
/*  LIMITATIONS:                                                            */
/*              The current implementation stores at most only one entry    */
/*              for each attribute.  So, we can only get the state for      */
/*              time _after_ the entry's time stamp.                        */
/*                                                                          */
/*  RETURNS:    0  = All is OK                                              */
/*              -1 = Error                                                  */
/*                                                                          */
/*                                                                          */
/****************************************************************************/
int get_state_at(int Attrib, double TimeStamp, double *Value)
{
    double  delta_t;
    
    
    ml_printf(ML_DEBUG, ML_INFORMATION, "get_state_at called.\n");
    
    if (ST[Attrib].time_stamp > TimeStamp)
    {
        /* we can not determine state _before_ time_stamp */
        ml_print(ML_MANDATORY, ML_ERROR,
            "ERROR get_state_at cannot determine state before time_stamp\n");
        return -1;
    }
    delta_t = TimeStamp - ST[Attrib].time_stamp;
    
    *Value = ST[Attrib].value + (ST[Attrib].rate * delta_t);
    return 0;
}

