/****************************************************************************/
/* Copyright (c) 2000 MBARI                                                 */
/* MBARI Proprietary Information. All rights reserved.                      */
/****************************************************************************/
/* Summary  :                                                               */
/* Filename : Seabird25p.h                                                         */
/* Author   :                                                               */
/* Project  :                                                               */
/* Version  : 1.0                                                           */
/* Created  : 02/07/2000                                                    */
/* Modified :                                                               */
/* Archived :                                                               */
/****************************************************************************/
/* Modification History:                                                    */
/* 09/08/2014 Renamed file from original Seabird files, and began           */
/* 			  refactoring so that this driver can support the seabird       */
/*            25plus system.  EJM                                           */
/****************************************************************************/
#ifndef _Seabird_H
#define _Seabird_H

#include "ourTypes.h"

#include "StreamSerialDriver.h"
#include "Seabird25pOutput.h"
#include "Seabird25pLog.h"
#include "DepthSensorIF.h"
#include "Attributes.h"
/*
CLASS 
Ctd

DESCRIPTION
Seabird Device Driver Interface

AUTHOR
John Rieffel

COMMENTS: Large sections of this code lifted directly from Odyssey
code file cond_temp.h and .c.  Thank you very much.

*/
#define    SBE_PRES_RANGE 0  //Altex configured vehicle appears not to ask
                             // JAR 12/09/99
#define MAXNAMELEN 20
#define MAXTAGLEN 10
#define MAXNUMVOLTAGES 8 	 // specific to 25plus

#define MaxRecordBytes 256

#define ExpectedRecordBytes 62


// THESE ARE CALIBRATION VALUES -- TO BE CHANGED
// CURRENTLY USING TP2185 
// and CP1722
/*
#define    T_A   3.68006968e-03
#define    T_B   6.02841367e-04
#define    T_C   1.61590477e-05
#define    T_D   2.23203474e-06#define    T_F0  2892.171


#define    C_A   1.34276393e-07
#define    C_B   4.85446233e-01
#define    C_C  -4.14760004e+00
#define    C_D  -6.411519262-05
#define    C_M   6.0
#define    EPS  -9.57e-08
*/

/*-----------------------------------------------------------------------*
  (from Odyssey Code)

  First do temp conversion:

      lf = log( f0 / f Hz )

       T = 1 / (a + b*lf + c*lf^2 + d*lf^3)  - 273.15

  Next conductivity (uses temperature)

      C (S/m) = (a*(c kHz)^m + b*(c kHz)^2 + c + d*T) /
                (10*(1 + eps*P))
      where P is dbar and T is deg C
 *-----------------------------------------------------------------------*/


class Seabird25p : public StreamSerialDriver {
  
  friend class Seabird25pLog;

public:

  Seabird25p(SerialDevice *serialDevice, char *configFile,
	  char *instName);

  virtual ~Seabird25p();

  double Seabird25p::sw_salt(double cndr, double T, double P);
  double Seabird25p::sw_salrt( double T);
  double Seabird25p::sw_salrp( double R, double T, double P);
  double Seabird25p::sw_sals(double Rt, double T);
  double Seabird25p::sw_c3515(void );

protected:

  Seabird25pLog *_log;
  time_t _lastFlush;
  time_t _flushInterval;
  char _recordBuf[MaxRecordBytes];
  int _nBytes;

  ////////////////////////////////////////////////////////////////////
  // Seabird calibration attributes
  Attributes attributes;

  void createCTDAttributes();
  void loadCTDConfigFile( char *filename );
  void reportCTDAttributes();

  double T_A, T_B, T_C, T_D, T_F0,
  	  T_G, T_H, T_I, T_J, T_GF0,
  	  P_A0, P_A1, P_A2, PT_A0, PT_A1, PT_A2, // Pressure sensor
  	  PTC_A0, PTC_A1, PTC_A2, PTC_B0, PTC_B1, PTC_B2,  // Pressure sensor
  	  C_A, C_B, C_C, C_D, C_M, EPS,
  	  C_G, C_H, C_I, C_J, C_PCOR, C_TCOR;

  double SOc, BOc, Voff, TCor, PCor;
  long ScaleFactor;
  double DarkCounts;
  char condCalibTag[MAXTAGLEN];
  char tempCalibTag[MAXTAGLEN];
  
  int NUMVOLTAGES;
  // char v1name[MAXNAMELEN];
  //char v2name[MAXNAMELEN];
  //char v3name[MAXNAMELEN];
  //char v4name[MAXNAMELEN];
  //char v5name[MAXNAMELEN];
  //char v6name[MAXNAMELEN];
//  char *_vname[8]; // 25plus supports 8 voltages
  
  //  char *v1name;
  // char *v2name;
  //char *v3name;
  // char *v4name;
  // char *v5name;
  //char *v6name;
 //char *_pressConfigFlag;
 char *_t_coefs;
 char *_c_coefs;
 int offset;

 double voltages[MAXNUMVOLTAGES];
 
 int i;
  
  ////////////////////////////////////////////////////////////////////
  // must use depth measurement to calculate cond. accurately
  DepthSensorIF *depthSensor;
  
  double read_temp;
  double read_cond;
  double read_press;
  double read_tfreq;
  double read_cfreq;
  double read_pcounts;
  double read_ptempcounts;
  double salinity;
  double depth;
  double cndr;      //Conductivity ratio; see sw_salt().
  
  //Status Variables
  Boolean voutEnabled[4];
  Boolean voutFaulted[4];
  Boolean memoryFull;
  Boolean batteryLow;
  Boolean serialOverFlow1;
  Boolean serialOverFlow2;
  Boolean pumpEnabled;
  Boolean genericError[3];


  ////////////////////////////////////////////////////////////////////
  // must know whether DepthSensor Server is/not running
  Boolean depthSensorRunning;
  double depthSensor_pres;// in dbar?
  double site_latitude;
  double start_depth;
  double init_pressure;

  timespec temp_readtime;
  timespec cond_readtime;
  
  Seabird25pOutput *_output;
  
  // currently no way to access these two fns for now
  void standby(void);
  void halt(void);
  

  ///////////////////////////////////////////////////////////////////
  // functions to calculate temperature and conductivity from raw
  // frequencies
  double calculate_Temp(double f); // assume ITPS68 (whatever that means)
  double calculate_Cond(double f, double t, double p); // ditto
  double calculate_Pres(double pc, double tc); //ITS90
  double corrected_depth(double bar);

  ////////////////////////////////////////////////////////////////////
  // initialization routine
  // Simply clears serial port
  virtual DeviceIF::Status initialize();

#if 1
  virtual DeviceIF::Status readRecord(unsigned char *record,
				     int maxRecordBytes,
				     const char *recordTerminator,
				     unsigned readTimeout,
				     int *nBytesRead);
#endif

  ////////////////////////////////////////////////////////////////////
  // Process a record
  virtual DeviceIF::Status  processRecord(unsigned char *record, int nRecordBytes);

  ////////////////////////////////////////////////////////////////////
  // EventCode to trigger when device has been initialized
  //  virtual EventCode initializedEventCode();

};

#endif
