#ifndef __SMART_BATTERY_H__
#define __SMART_BATTERY_H__

#define MAX_BATTS (256)

typedef enum {
  BATT_STATE_OFF, 
  BATT_STATE_DISCHARGE, 
  BATT_STATE_CHARGE, 
  BATT_STATE_BALANCE,
  BATT_STATE_UNKNOWN
} BattState_t;

#define BattStateStr(state) \
        ((state)==BATT_STATE_OFF ? "Off" :\
         (state)==BATT_STATE_DISCHARGE ? "Discharge" :\
         (state)==BATT_STATE_CHARGE ?  "Charge" :\
         (state)==BATT_STATE_BALANCE ? "Balance" :\
         "Unknown")

typedef enum {
  BATT_ERROR_CLEAR, 
  BATT_ERROR_OVER_VOLTAGE, 
  BATT_ERROR_UNDER_VOLTAGE, 
  BATT_ERROR_OVER_CURRENT, 
  BATT_ERROR_MAX_CELL_OVER_VOLTAGE, 
  BATT_ERROR_MIN_CELL_UNDER_VOLTAGE, 
  BATT_ERROR_OVER_TEMP, 
  BATT_ERROR_WATER_LEAK, 
  BATT_ERROR_HW_PROTECT, 
  BATT_ERROR_TRANS_HW_PROTECT, 
  BATT_ERROR_WD_TIMEOUT,
  BATT_ERROR_UNKNOWN
} BattError_t;

#define BattErrorStr(error) \
        ((error)==BATT_ERROR_CLEAR ? "Clear" :\
         (error)==BATT_ERROR_OVER_VOLTAGE ? "Over Voltage" :\
         (error)==BATT_ERROR_UNDER_VOLTAGE ? "Under Voltage" :\
         (error)==BATT_ERROR_OVER_CURRENT ? "Over Current" :\
         (error)==BATT_ERROR_MAX_CELL_OVER_VOLTAGE ? "Max cell over voltage" :\
         (error)==BATT_ERROR_MIN_CELL_UNDER_VOLTAGE ? "Min cell under voltage" :\
         (error)==BATT_ERROR_OVER_TEMP ? "Over Temp" :\
         (error)==BATT_ERROR_WATER_LEAK ? "Water Leak" :\
         (error)==BATT_ERROR_HW_PROTECT ? "HW Protect" :\
         (error)==BATT_ERROR_TRANS_HW_PROTECT ? "Trans HW Protect" :\
         (error)==BATT_ERROR_WD_TIMEOUT ? "WD Timeout" :\
         "Unknown")

typedef enum {
  BATT_MODE_SLAVE,
  BATT_MODE_MASTER,
  BATT_MODE_UNKNOWN
} BattMode_t;

#define BattModeStr(mode) \
        ((mode)==BATT_MODE_SLAVE ? "Slave" :\
         (mode)==BATT_MODE_MASTER ? "Master" :\
         "Unknown")
  
typedef struct {
  BattState_t state;
  BattError_t error;
  double pack_V; // Volts
  double pack_I; // Amps
  double max_temp; // Celsius
  double min_volt; // Volts of minimum cell
  double max_volt; // Volts of maximum cell
  int water_leak; // 0/1
  double capacity; // Estimated WHr
  long time; // Time since power-up in seconds
  BattMode_t mode; // master/slave
} BattSummary_t;

#define NUM_CELLS (8)
typedef struct {
  double cell_volts[NUM_CELLS]; // Volts of each cell
} BattVolts_t;

#define NUM_TEMPS (5)
typedef struct {
  double pack_temps[NUM_TEMPS];
} BattTemps_t;

typedef struct {
  char          batt_alive; // 0-not present, 1-present
  int           port;    // serial port fd
  int           address;
  BattSummary_t summary;
  BattVolts_t   volts;
  BattTemps_t   temps;
} SmartBattery_t;

typedef enum {
  BATT_WD_DISABLE = 0,
  BATT_WD_ENABLE = 1
} BattWD_t; 

int battSetAddress (int batt_port, int batt_num, int address);
int battSetState (int batt_port, int batt_num, BattState_t state);
int battQuerySummary (int batt_port, int batt_num, BattSummary_t *sum);
int battQueryCellVolts (int batt_port, int batt_num, BattVolts_t *cells);
int battQueryTemps (int batt_port, int batt_num, BattTemps_t *temps);
int battGetEnergy (int batt_port, int batt_num, double *energy);
int battSetEnergy (int batt_port, int batt_num, double energy);
int battSetStreaming (int batt_port, int batt_num, int mode);
int battSetMaster (int batt_port, int batt_num, int mode);
int battGetMaster (int batt_port, int batt_num, int *mode);
int battSetWatchdog (int batt_port, int batt_num, int mode);
int battGetVersion (int batt_port, int batt_num, char *ver, int ver_len);
int battCrash (int batt_port, int batt_num);

int battSync (int batt_port, SmartBattery_t *sm_batts);

#endif /* __SMART_BATTERY_H__ */
