/*
 * David Muller; Germán Alfaro
 * davehmuller@gmail.com; alfaro.germanevera@gmail.com
 *
 * Thom Maughan; tm@mbari.org  2018...
 */


#ifndef MPHOX_SYSTEM_H_
#define MPHOX_SYSTEM_H_

#include <stdint.h>
#include <stdbool.h>
#include <math.h>
#include <time.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <ctype.h>

#if BOARD_MFET >= 1 || BOARD_SEAPHOX == 1 || BOARD_MPHOX == 1
#include "inc/tm4c123gh6pge.h"
#endif
#if BOARD_NANOFET == 1
#include "inc/tm4c123gh6pm.h"
#endif

#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "inc/hw_hibernate.h"

#include "driverlib/debug.h"
#include "driverlib/fpu.h"
#include "driverlib/gpio.h"
#include "driverlib/pin_map.h"
#include "driverlib/rom.h"
#include "driverlib/rom_map.h"
#include "driverlib/sysctl.h"
#include "driverlib/uart.h"
#include "driverlib/eeprom.h"
#include "driverlib/gpio.h"
#include "driverlib/hibernate.h"
#include "driverlib/ssi.h"
#include "driverlib/interrupt.h"


//V=I*R => V=I*15K => I=V/15K amps => I=V*10^9/15K nano-Amps => I=V*66.6k nA => 15uV/nA.
#define COUNTERELECTRODE_IK_SCALE       66666.667   // 10^9/15K MCAP has 15K resistor, Ik
//
#define SUBSTRATECURRENT_IB_SCALING     1000        // 10^9/1M = 1000   MCAP has 1M resistor for Ib, substrate current

#define SIZEOF_PRNBUF  1020

#if BOARD_MFET == 1
#define 	VERSION		"v3.5.6 MFET v1"     // MFET software version   Glider is 9600 baud
// battery backed HIB, no FRAM
// only one can be set to 1.  HIB uses battery backed ram in hibernate module, EEPROM uses onchip EEPROM with 500K cycles, FRAM requires 24CL04B chip on MFET v2
#define NONVOLATILEMEM  "Nonvol mem: Hibernate module battery backed RAM"
#define EEPROM_REG_STORE 0      // old, wear out EEPROM
#define HIB_REG_STORE   1       // used to turn on HIB register store to prevent EEPROM wearout
#define FRAM_REG_STORE  0
#endif
#if BOARD_MFET == 2
#define     VERSION     "v3.5.6 MFET v2 pre-release, DO NOT DEPLOY this version of firmware"     // MFET software version   Glider is 9600 baud
// FRAM (and battery backed HIB)
#define NONVOLATILEMEM  "Nonvol mem: i2c Ferroelectric RAM"
#define EEPROM_REG_STORE 0      // old, wear out EEPROM
#define HIB_REG_STORE   0       // used to turn on HIB register store to prevent EEPROM wearout
#define FRAM_REG_STORE  1
#endif
#if BOARD_MPHOX == 1
#define     VERSION     "v3.5.6 MpHOx revB pre-release, DO NOT DEPLOY this version of firmware"     // MFET software version   Glider is 9600 baud
// FRAM (and battery backed HIB)
#define NONVOLATILEMEM  "Nonvol mem: i2c Ferroelectric RAM"
#define EEPROM_REG_STORE 1      // old, wear out EEPROM
#define HIB_REG_STORE   0       // used to turn on HIB register store to prevent EEPROM wearout
#define FRAM_REG_STORE  0
#endif
#if BOARD_NANOFET == 1
#define     VERSION     "v3.5.6 NanoFET pre-release, DO NOT DEPLOY"     // MFET software version   Glider is 9600 baud
// FRAM (and battery backed HIB)
#define NONVOLATILEMEM  "Nonvol mem: i2c Ferroelectric RAM"
#define EEPROM_REG_STORE 1      // old, wear out EEPROM
#define HIB_REG_STORE   0       // used to turn on HIB register store to prevent EEPROM wearout
#define FRAM_REG_STORE  0
#endif
#ifndef VERSION
#define     VERSION     "COMPILER FLAGS BOARD_MFET or BOARD_SEAPHOX NOT DEFINED"
#endif

#define NOMINAL_SAMPLE_TIMES    1
#define FAST_SAMPLE_TIMES       0

#if NOMINAL_SAMPLE_TIMES==1

#endif

#if FAST_SAMPLE_TIMES==1


#endif

/* Boolean type */
typedef enum { FALSE = 0, TRUE } BOOL;
typedef enum {IDLE, START, DEPLOYED, COMMAND} deploy_state;
typedef enum {NORMAL=1, VERBOSE} output_mode;

/*
 * Delay lengths for SysCtlDelay().
 */
#define CLOCKSPEED 50000000.0  						//clock is set to run at 50MHZ
#define ONESEC (int)ceil((CLOCKSPEED/3.0))  		//SysCtlDelay takes 3 cycles per loop...so delay = DesiredDelayTimeInSeconds/((1/CLOCKSPEED)*3)
#define MILLISECOND (int)ceil((.001 / ((1.0/CLOCKSPEED)*3.0)))
#define MICROSECOND (int)ceil((.000001 / ((1.0/CLOCKSPEED)*3.0)))

/*
 * Buffer lengths.
 */
#define TIMESTAMPLENGTH 		50
#define INSTRUMENTBUFFSIZE 		400
#define MICROCAT_BUFFER_SIZE 	128
#define DBG_UART_BUFFER_SIZE    128     // buffer defined in microcat.h microcat sbe37 is on uart4
#define OPTODE_BUFFER_SIZE 		128     // buffer defined in optode.h optode is on uart3
#define CONDO_BUFFER_SIZE      128     // buffer defined in condo.h conductivity is on uart2 (aka AUX1)
#define AUX1_BUFFER_SIZE		128
#define AUX2_BUFFER_SIZE		128


#define GDATA_BYTES				512	// Number of bytes to read out with gdata command

#define IS_PRESENT		  1
#define NOT_PRESENT 	  0

/*
 * Constants
 */
#define R_			8.31451			// Univ gas constant
#define F_ 			96487			// Faraday constant
#define dEoINT_dt	-0.0011012		// Temperature coefficient for internal reference [Volts/C]
#define dEoEXT_dt	-0.0010482		// Temeprature coefficient for external reference [Volts/C]
#define LN10		2.302585		// Natural log of 10

// Standard deviation array values
#define SD_AVG		5
#define SD_MEAN		SD_AVG
#define SD_DIFF_SQ	SD_AVG+1
#define SD_VALUES	5

// AD1248 24-bit A/D defines
// signed 24bit numeric range is: -8,388608 to +8,388607
#define TWOTOTHE23 8388608  // 2 to the 23rd = 8388608
#define COUNTSTOVOLTS (float) (2.048 / (TWOTOTHE23 - 1))  //each count returned from the ADC has a weight of (Vref/PGA)/(2^23 -1 ).  We use PGA = 1.
#define PGA_1		0x00
#define PGA_2		0x10
#define PGA_4		0x20
#define PGA_8		0x30
#define PGA_16		0x40
#define PGA_32		0x50
#define PGA_64		0x60
#define PGA_128		0x70

#define SPS_5		0x00
#define SPS_10		0x01
#define SPS_20		0x02
#define SPS_40		0x03
#define SPS_80		0x04
#define SPS_160		0x05
#define SPS_320		0x06
#define SPS_640		0x07
#define SPS_1000	0x08
#define SPS_2000	0x09

/*
 * Definition of a structure containing the controller's parameters
 * These parameters are all modifiable by external user except where noted.
 * Structure is stored in EEPROM during hibernation.
 */
#define MAX_NUMOF_CONFIG_FIELDS     48  //was 30  These are for sampling / data logging configuration A-Z, 0-9

#define MAX_FILENAME        16      // 8.3 filename plus padding 24      //80 is too much, should be 32 or 40 at most.
#define MAX_USER_INITIALS   8

#define MAX_BOARD_SN        24      //30

#define MAX_MCAP_SN         24      //30
#define MAX_PACKAGE_NAME    32      //30
#define MAX_DURAFET_SN      24      //30
#define MAX_CAPADAP_SN      24      //30
#define MAX_ISE_SN          24      //30
//#define MAX_MICROCAT_SN     24      //30
#define MAX_OPTODE_SN       24      //30
#define MAX_CONDO_SN        24      //30
#define MAX_PUMP_SN         24      //30
#define MAX_BOARD_FABNOTE   80
#define MAX_DEPLOY_NOTE     80

// systemData struct organized for 4 byte packing, also fixed buffer overruns by setting size of fields in define
struct systemData
{
    uint32_t deploy_time;           // deployment time
	uint32_t sampling_period;	    //8 pH sampling period
	int32_t sample_average;	    	//12 Number of pH sensor samples to average
	uint32_t averaging_interval;    //16 Number of seconds between each average
	uint32_t pumpon_time;		    //20 Active pump time
	float low_batt_volt;            //4  Low battery voltage threshold
	float TCOffset;					//24 DuraFET temperature calibration variable
	float k0ext;					//28 was float Eo_ext_25C;, renamed k0ext 2 Apr 2021
	float k0int;					//32 was float Eo_int_25C;, renamed k0int  2 Apr 2021
    float k2ext;                    //28 added  25 Apr 2021
    float k2int;                    //32 added  25 Apr 2021
    float shTherm_c0;                   // steinhart-hart coefficient c0 for thermistor
    float shTherm_c1;                   // steinhart-hart coefficient c1 for thermistor
    float shTherm_c2;                   // steinhart-hart coefficient c2 for thermistor
    float shTherm_c3;                   // steinhart-hart coefficient c3 for thermistor
	float default_sal;              //36 default salinity
	float sensor_sal;               // salinity read from conductivity (SBE, Aanderaa)
	                                //int spare1;                     //410			// Pressure sensor full-scale value (psi)   placeholder to keep previous version struct integrity
	uint32_t Vint_gain;					//414 pH Vint PGA gain setting
	uint32_t gain1;                  // Future, parameterize sampling wiht gain0(Vint), thru gain3
	uint32_t gain2;
	uint32_t gain3;
	uint32_t Vint_sps;					//418 pH Vint data rate setting (sps)
	uint32_t sps1;
    uint32_t sps2;
    uint32_t sps3;
    uint32_t offset_Ik;             // 800uV or so, tbd measure a QA step.
    uint32_t offset_Ib;
	output_mode output;				//422 Verbose mode during deployment if true (enum is 4 bytes?)
	int32_t test_mode;		        //426 Indicates test deployment
	uint32_t fast_mode;             // Future: changed to sampling mode (fast, precise, etc.)

	// THOM Todo - remove these from EEPROM, only use FRAM
	int32_t state;						//430 IDLE, DEPLOYED, COMMAND,  NOT USER MODIFIABLE                        <<<<<------
	uint32_t nextWakeUp;			//434 Next intended RTC match (wake-up time) NOT USER MODIFIABLE           <<<<<------
	uint32_t next_gdata_fptr;	//438 The file position of the next gdata sample. NOT USER MODIFIABLE      <<<<<------
	uint32_t current_sample;	//442 The current data record to be stored. NOT USER MODIFIABLE            <<<<<------
    float AD24_std;                 //464 standard deviation for AD24                                          <<<<--------

    uint32_t baud_rate;        //470 baud rate  (added by tm Jul 2018)
	unsigned char data_cfg[MAX_NUMOF_CONFIG_FIELDS];     //510 was 30, changed to 40 34  data field / logging configuration (added by tm Jul 2018)


    bool GMT;                       //456 GMT or Local time
    bool sample_aligned;            //460 Sample aligned to hour

	float spare[10];                // 10 4 byte spares (40 bytes) for future expansion without causing EEPROM struct issues

	// re-arranged struct to put char fields after numeric
    char fileName[MAX_FILENAME];              //116 The name the user would like to give their data output file
    char user[MAX_USER_INITIALS];                  //452 User initials

    char board_SN[MAX_BOARD_SN];              //146 (added 3Apr2021) board (MFET, MpHOx, nanoFET) serial number
    char mcap_SN[MAX_MCAP_SN];               //176 (added 3Apr2021) mcap serial number
    char durafet_SN[MAX_DURAFET_SN];            //226 DuraFET sensor serial number
    //char capadap_SN[MAX_CAPADAP_SN];            //256 CAP adapter serial number
    //char ISE_SN[MAX_ISE_SN];                //286 ISE serial number
    char package_name[MAX_PACKAGE_NAME];       //196 Name of integrated package (underway system, etc.)  (was 20, now 30, bug in buff entry size)
    //char microcat_SN[MAX_MICROCAT_SN];           //Combine with Condo 316 Microcat serial number
    char optode_SN[MAX_OPTODE_SN];             //346 (added 3Apr2021) Aanderaa optode serial number
    char condo_SN[MAX_CONDO_SN];              //376 (added 3Apr2021) Aanderaa conductivity or MicroCat aka condo serial number
    char pump_SN[MAX_PUMP_SN];               //406 Pump serial number
    char deploy_note[MAX_DEPLOY_NOTE];
    char board_fab_note[MAX_BOARD_FABNOTE];        //  (added 4Apr2021)  board fabrication notes, dates, etc.

};

#ifdef TEMPCOPY
struct systemData
{
    float low_batt_volt;            //4  Low battery voltage threshold
    uint32_t sampling_period;       //8 pH sampling period
    int32_t sample_average;         //12 Number of pH sensor samples to average
    uint32_t averaging_interval;    //16 Number of seconds between each average
    uint32_t pumpon_time;           //20 Active pump time
    float TCOffset;                 //24 DuraFET temperature calibration variable
    float k0ext;                    //28 was float Eo_ext_25C;, renamed k0ext 2 Apr 2021
    float k0int;                    //32 was float Eo_int_25C;, renamed k0int  2 Apr 2021
    float default_sal;              //36 default salinity
    char fileName[80];              //116 The name the user would like to give their data output file
    char board_SN[30];              //146 (added 3Apr2021) board (MFET, MpHOx, nanoFET) serial number
    char board_Fabnotes[30];        //  (added 4Apr2021)  board fabrication notes, dates, etc.
    char mcap_SN[30];               //176 (added 3Apr2021) mcap serial number
    char sensor_name[30];           //196 Temperature sensor name  (was 20, now 30, bug in buff entry size)
    char durafet_SN[30];            //226 DuraFET sensor serial number
    char capadap_SN[30];            //256 CAP adapter serial number
    char ISE_SN[30];                //286 ISE serial number
    char microcat_SN[30];           //316 Microcat serial number
    char optode_SN[30];             //346 (added 3Apr2021) Aanderaa optode serial number
    char condo_SN[30];              //376 (added 3Apr2021) Aanderaa conductivity aka condo serial number
    char pump_SN[30];               //406 Pump serial number
    int spare_was_press_full_scale; //410           // Pressure sensor full-scale value (psi)   placeholder to keep previous version struct integrity
    int Vint_gain;                  //414 pH Vint PGA gain setting
    int Vint_sps;                   //418 pH Vint data rate setting (sps)
    output_mode output;             //422 Verbose mode during deployment if true (enum is 4 bytes?)
    int test_mode;                  //426 Indicates test deployment

    int state;                      //430 IDLE, DEPLOYED, COMMAND,  NOT USER MODIFIABLE                        <<<<<------
    uint32_t nextWakeUp;            //434 Next intended RTC match (wake-up time) NOT USER MODIFIABLE           <<<<<------
    unsigned long next_gdata_fptr;  //438 The file position of the next gdata sample. NOT USER MODIFIABLE      <<<<<------
    unsigned int current_sample;    //442 The current data record to be stored. NOT USER MODIFIABLE            <<<<<------

    char user[10];                  //452 User initials
    bool GMT;                       //456 GMT or Local time
    bool sample_aligned;            //460 Sample aligned to hour

    float AD24_std;                 //464 standard deviation for AD24                                          <<<<--------

    unsigned long baud_rate;        //470 baud rate  (added by tm Jul 2018)
    unsigned char data_cfg[MAX_NUMOF_CONFIG_FIELDS];     //510 was 30, changed to 40 34  data field / logging configuration (added by tm Jul 2018)
    unsigned char fast_mode;        //511 added 10 Jun 2019
#endif


// variables that change each sample (will wear out onchip 500k write cycle flash / eeprom)
struct systemDataVolatile
{
    uint32_t state;                     // IDLE, DEPLOYED, COMMAND,  NOT USER MODIFIABLE
    uint32_t nextWakeUp;                // Next intended RTC match (wake-up time) NOT USER MODIFIABLE
    uint32_t next_gdata_fptr;           // The file position of the next gdata sample. NOT USER MODIFIABLE Note: was unsigned long
    uint32_t current_sample;            // The current data record to be stored. NOT USER MODIFIABLE
    float AD24_std;
    uint32_t samp_state;
    uint32_t chksum;
};


#define SYSDATACHG_NUMWORDS     7       // number of 4byte words in above struct

//DEFAULT Configuration for get_sample() is for all fields
// index into sys_data.data_cfg[]
#define CFG_SAMPLE_NUM          0
#define CFG_TIMEDATE            1   // + MM/DD/YYYY HH:MM:SS
#define CFG_ENV_BAT_VOLT        2   //+ Battery_Volt
#define CFG_ENV_BRD_TEMP        3   //+ Board_Temperature\t
#define CFG_ENV_HUMIDITY        4   // + Humidity_sensor
#define CFG_BIAS_BAT_VOLT       5   //+ Bias Bat Volt, was Internal_pressure
#define CFG_V_THERMISTOR        6       //+ Vthermistor\t
#define CFG_V_THERMISTOR_STD    7   //+ Vthermistor_std\t
#define CFG_V_INT_OFFSET        8   //+ Vint_offset\t
#define CFG_V_INT_OFFSET_STD    9   //+ Vint_offset_std\t
#define CFG_V_EXT_OFFSET        10   //+ Vext_offset\t
#define CFG_V_EXT_OFFSET_STD    11   //+ Vext_offset_std\t

#define CFG_V_INT               12   //+ Vint\t
#define CFG_V_INT_STD           13   //+ Vint_std\t
#define CFG_V_EXT               14   //+ Vext
#define CFG_V_EXT_STD           15   // + Vext_std
#define CFG_V_COUNTER_ELECT     16   //+ Vcounter_electrode
#define CFG_V_COUNTER_ELECT_STD 17   //+ Vcounter_electrode_std
#define CFG_I_COUNTER           18   // + Counter_current
#define CFG_I_SUBSTRATE         19   //+ Substrate_current
#define CFG_CALC_TEMP           20   //+ calculated_temperature_Vthermistor\t
#define CFG_EST_PH_INT          21   //+ estimated_pH_int\r\n
#define CFG_EST_PH_EXT          22   //+ estimated_pH_ext\r\n (new 6May2019 TM)
#define CFG_OPTODE              23   // Aanderaa optode
#define CFG_CONDO               24   // Aanderaa or MicroCat conductivity, AKA CFG_CONDUCTIVITY new 25 Mar 2021

#define DATA_CFG_NUM    25          // Number of Data Config items (used in main.c for array index limit)


// Global variables
extern struct systemData sys_data;
extern struct systemDataVolatile sys_data_vol;
extern struct systemDataVolatile sys_data_chg;
//extern char MicroCAT_buff[MICROCAT_BUFFER_SIZE];
//extern char Optode_buff[OPTODE_BUFFER_SIZE];

#ifdef OLDCODE
// Function Macros
#if BOARD_SEAPHOX == 1
#define pump_on()		ROM_GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_3, 0xff);
#define pump_off()		ROM_GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_3, 0x00);
#endif

#if BOARD_MFET >= 1 || BOARD_MPHOX == 1
#define pump_on()       ROM_GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_0, 0xff);
#define pump_off()      ROM_GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_0, 0x00);
#endif

#if BOARD_NANOFET >= 1
// There is no pump_on for NANOFET, wiggle unused pin
#define pump_on()       ROM_GPIOPinWrite(GPIO_PORTE_BASE, GPIO_PIN_3, 0xff);
#define pump_off()      ROM_GPIOPinWrite(GPIO_PORTE_BASE, GPIO_PIN_3, 0x00);
#endif

#if BOARD_NANOFET >= 1
// There is no pressure on off_on for NANOFET, wiggle unused pin
#define pressureOn()       ROM_GPIOPinWrite(GPIO_PORTE_BASE, GPIO_PIN_3, 0xff);
#define pressureOff()      ROM_GPIOPinWrite(GPIO_PORTE_BASE, GPIO_PIN_3, 0x00);
#endif


#if BOARD_MFET >= 1 || BOARD_MPHOX == 1
#define pressureOn()	ROM_GPIOPinWrite(GPIO_PORTM_BASE, GPIO_PIN_5, 0xff);
#define pressureOff()	ROM_GPIOPinWrite(GPIO_PORTM_BASE, GPIO_PIN_5, 0x00);
#endif
//#define console_on()	ROM_GPIOPinWrite(GPIO_PORTL_BASE, GPIO_PIN_0, 0xff);
// Thom new - make console into a routine
//#define console_off()	ROM_GPIOPinWrite(GPIO_PORTL_BASE, GPIO_PIN_0, 0x00);
#endif

// Function prototypes for System.c
//void print_header(void);

//void console_on(void);
//void console_off(void);

void initSysDataVolatileVariables(void);

void SysTickHandler(void);
unsigned long Timer_10ms(bool reset);
void ms_delay(unsigned int msec);

uint32_t storeSysDataVariables(void);
void retrieveSysDataVariables();
uint32_t smartStoreSysData(void);

int isNameInSavedDataString(char* name);
void saveSysDataVariableName();

float batt_volt();
float batt_volt_iso();


float controller_temp();
float pressure(void);
//int writeDeploymentInformationHeader(const time_t currentTime);  //deprecated 21 Apr 2021

void sendlast_takesample(void);
void get_sample(int txFlg);
void fast_sample(int txFlg);

void error_store(const char *error_buff);
float DuraFET_temp(float V_therm, float TCOffset);
float calc_pHext(float Eext, float TC, float salt);
float calc_pHint(float Eint, float TC);
void ph_calib(void);

float read_env_sensors(void);

#ifdef NOCODE
void led_green_off(void);
void led_green_on(void);
void led_green_toggle(void);
void led_red_off(void);
void led_red_on(void);
void led_red_toggle(void);

void profile_toggle(int target);
void profile_off(int target);
void profile_on(int target);
#endif




#endif /* SEAPHOX_MFET_SYSTEM_H_ */
