/*
 *
 * Thom Maughan; tm@mbari.org  starting 2018...
 *
 */


#ifndef PHFETSOS_SYSTEM_H_
#define PHFETSOS_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>
#include <assert.h>

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

#if BOARD_MSC == 3
    #ifdef PART_TM4C1290NCPDT
        #include "inc/tm4c1290ncpdt.h"
    #else
        #include "inc/tm4c123gh6pm.h"
        //#define TIVA_MOD_REVA 1
        #define TIVA_MOD_REVB 1
    #endif
#endif

#include "init.h"

#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"


#define CR  0x0d
#define LF  0x0a

#define H2M_MODE    0
#define M2M_MODE    1

#if BOARD_MSC == 3
#define DEFAULT_BAUDRATE        9600
#else
#define DEFAULT_BAUDRATE        115200
#endif


//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



#if BOARD_MSC == 3
    #ifdef PART_TM4C123GH6PM
        #define SIZEOF_PRNBUF  1536         // was 1536         // was 1536 on tiva 123g     //1020
    #endif
    #ifdef PART_TM4C1290NCPDT
        #define SIZEOF_PRNBUF  3072         // was 1536         // was 1536 on tiva 123g     //1020
    #endif
#else
#warning JLD - just moved this here was 512 for my initial work - needs testing all boards.
    #define SIZEOF_PRNBUF  1536             // was 1536         // was 1536 on tiva 123g     //1020
#endif

#define SIZEOF_SBUF     4096        // scratch pad, was a bunch of calloc in MSC1
#define SIZEOF_EBUF     256         // error message buffer

// JLD-TGM I added the VERSION MAJOR/MINOR/REVISION that gets used in the version string.
#define UseNewVersionMethod

#ifdef UseNewVersionMethod

#define VERSION_STRING_MAX_LEN  64

#define VERSION_MAJOR   5
#define VERSION_MINOR   02
#define REVISION        0

#if BOARD_MFET == 1
#define DEFAULT_TERMINAL_MODE H2M_MODE
#define VERSION_MAJOR   3
#define VERSION_MINOR   7
#define REVISION        1
#define PLATFORM         "MFETv1"     // MFET software version   Glider is 9600 baud
#define PLATFORM_COMMENT "v3.7.1 was the last support for MFET v1"
// 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 // BOARD_MFET == 1

#if BOARD_MFET == 2
#define DEFAULT_TERMINAL_MODE H2M_MODE
#define PLATFORM         "MFETv2"     // MFET software version   Glider is 9600 baud
#define PLATFORM_COMMENT "revC"
// 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  2       // was 1, 2 means use of sys_samp
#endif  // BOARD_MFET == 2

#if BOARD_MPHOX == 1
#define PLATFORM         "MpHOx"     // MFET software version   Glider is 9600 baud
#define PLATFORM_COMMENT "revA/B"
// 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  2       // was 1 (sys_samp)
#endif  // BOARD_MPHOX == 1

#if BOARD_NANOFET == 1
#define DEFAULT_TERMINAL_MODE H2M_MODE
//#define VERSION_MAJOR   5
//#define VERSION_MINOR   20
//#define REVISION        0
#define PLATFORM         "NanoFET"     // MFET software version   Glider is 9600 baud
#define PLATFORM_COMMENT "revC"
// 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  2
#endif   // BOARD_NANOFET == 1

#if BOARD_MSC == 3
//#define VERSION_MAJOR   5
//#define VERSION_MINOR   20
//#define REVISION        0
#define PLATFORM         "MSC3"     //

#ifdef PART_TM4C123GH6PM
#define PLATFORM_COMMENT "123g revB"
#endif

#ifdef PART_TM4C1290NCPDT
#define PLATFORM_COMMENT "1290 revB"
#endif

// FRAM (and battery backed HIB)
#define NONVOLATILEMEM  "Nonvol mem: i2c Ferroelectric RAM"
#define EEPROM_REG_STORE 0      // old, incrementing sample counter will wear out EEPROM (500K cycles)
#define HIB_REG_STORE   0       // used to turn on HIB register store to prevent EEPROM wearout
#define FRAM_REG_STORE  2
#endif   // BOARD_MSC == 3

#ifndef PLATFORM
#define VERSION_MAJOR   0
#define VERSION_MINOR   0
#define REVISION        0
#define PLATFORM         "Unk"     // MFET software version   Glider is 9600 baud
#define PLATFORM_COMMENT "COMPILER FLAGS BOARD_MFET or BOARD_MPHOX or BOARD NANOFET NOT DEFINED"
#endif

#ifndef DEFAULT_TERMINAL_MODE
#define DEFAULT_TERMINAL_MODE M2M_MODE
#endif

#else  // older style version details here - remove ASAP!!!

#if BOARD_MFET == 1
#define 	VERSION		"v3.7.1 was the last support for 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     "v5.2.0 MFET revC"     // 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  2       // was 1, 2 means use of sys_samp
#endif
#if BOARD_MPHOX == 1
#define     VERSION     "v5.2.0 MpHOx revA/B %s %s"     // 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  2       // was 1 (sys_samp)
#endif
#if BOARD_NANOFET == 1
#define     VERSION     "v5.2.0 NanoFET revB"     // NanoFET software version, hardware version (revA and revB and compatible)
// 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  2
#endif
#if BOARD_MSC == 3
#ifdef PART_TM4C123GH6PM
#define     VERSION     "MoSoS v5.2.0 MSC3 123g revB"     // MSC3 Tiva software version, hardware version
#endif
#ifdef PART_TM4C1290NCPDT
#define     VERSION     "MoSoS v5.2.0 MSC3 1290 revB"     // MSC3 Tiva software version, hardware version
#endif
// FRAM (and battery backed HIB)
#define NONVOLATILEMEM  "Nonvol mem: i2c Ferroelectric RAM"
#define EEPROM_REG_STORE 0      // old, incrementing sample counter will wear out EEPROM (500K cycles)
#define HIB_REG_STORE   0       // used to turn on HIB register store to prevent EEPROM wearout
#define FRAM_REG_STORE  2
#endif
#ifndef VERSION
#define     VERSION     "COMPILER FLAGS BOARD_MFET or BOARD_MPHOX or BOARD NANOFET NOT DEFINED"
#endif
#endif

// Texas Instruments 'nutty' epoch time starts at "01/01/1900 06:00:00" not "01/01/1970 00:00:00"
// This offset determined by putting the unix epoch into mktime with the timezone set to GMT
#define TI_CCS_UNIX_EPOCH_OFFSET (0x83AA2A20UL)

#define NOMINAL_SAMPLE_TIMES    1
#define FAST_SAMPLE_TIMES       0

/* Boolean type */
typedef enum { FALSE = 0, TRUE } BOOL;
//typedef enum {IDLE, START, DEPLOYED, COMMAND} deploy_state;
typedef enum {IDLE, DEPLOYED} deploy_state;     //DEPLOYED is WAKERTC, IDLE is WAKEGPIO
typedef enum {NORMAL=1, VERBOSE} output_mode;
#define GPIOWAKEUP      0
#define RTCWAKEUP       1


/*
 * Delay lengths for SysCtlDelay().
 */
#if BOARD_MSC == 3
    #if defined(PART_TM4C123GH6PM)
        #define CLOCKSPEED 50000000  //clock is set to run at 50MHZ
    #elif defined(PART_TM4C1290NCPDT)
        #define CLOCKSPEED 120000000 //clock is set to run at 120MHZ
    #else
        #error "Unknown part"
    #endif
#elif BOARD_MPHOX == 1
    #if defined(PART_TM4C1290NCPDT)
        #define CLOCKSPEED 50000000  //clock is set to run at 50MHZ
    #elif defined(PART_TM4C123GH6PM)
        #define CLOCKSPEED 120000000  //clock is set to run at 120MHZ
    #else
        #warning "MPHOX CLOCKSPEED issue -- Unknown part using 50MHz!"
        #define CLOCKSPEED 50000000  //clock is set to run at 50MHZ
    #endif
#elif BOARD_NANOFET == 1
    #if defined(PART_TM4C1290NCPDT)
        #define CLOCKSPEED 50000000  //clock is set to run at 50MHZ
    #elif defined(PART_TM4C123GH6PM)
        #define CLOCKSPEED 120000000  //clock is set to run at 120MHZ
    #else
        #warning "NANOFET CLOCKSPEED issue -- Unknown part using 50MHz!"
        #define CLOCKSPEED 50000000  //clock is set to run at 50MHZ
    #endif
#elif BOARD_MFET >= 1
    #if defined(PART_TM4C1290NCPDT)
        #define CLOCKSPEED 50000000  //clock is set to run at 50MHZ
    #elif defined(PART_TM4C123GH6PM)
        #define CLOCKSPEED 120000000  //clock is set to run at 120MHZ
    #else
        #warning "MFET CLOCKSPEED issue -- Unknown part using 50MHz!"
        #define CLOCKSPEED 50000000  //clock is set to run at 50MHZ
    #endif
#else
    #error "Unknown board"
#endif

#define ONESEC      (CLOCKSPEED/3       + ((CLOCKSPEED % 3)       != 0)) //SysCtlDelay takes 3 cycles per loop...so delay = DesiredDelayTimeInSeconds/((1/CLOCKSPEED)*3)
#define MILLISECOND (CLOCKSPEED/3000    + ((CLOCKSPEED % 3000)    != 0))
#define MICROSECOND (CLOCKSPEED/3000000 + ((CLOCKSPEED % 3000000) != 0))

// TM4C129 may not get clock speed from SysCtlClockGet, and must use return value from SysCtlClockFreqSet
// TM4C123 may call ROM_SysCtlClockGet
#if defined(TARGET_IS_TM4C129_RA0) || defined(TARGET_IS_TM4C129_RA1) || defined(TARGET_IS_TM4C129_RA2)
    #define GetSysClkHz() g_ui32SysClock
#elif defined(TARGET_IS_TM4C123_RA1) || defined(TARGET_IS_TM4C123_RA3) || defined(TARGET_IS_TM4C123_RB1) || defined(TARGET_IS_TM4C123_RB2)
    #define GetSysClkHz() MAP_SysCtlClockGet()
#else
    #error "Unknown target - add code to check TARGET_IS_TM4C* and implement GetSysClkHz"
#endif

/*
 * Buffer lengths.   Thom TODO: consolidate the buffers to one for each uart rather than for each driver.
 */
#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 CTD_BUFFER_SIZE         128
#define AUX1_BUFFER_SIZE		128
#define AUX2_BUFFER_SIZE		128
//#define OCR_BUFFER_SIZE         128     // UART3
//#define NANOFET_BUFFER_SIZE     256 //128     // UART3

#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 (2.048f / ((float)(TWOTOTHE23 - 1)))  //each count returned from the ADC has a weight of (Vref/PGA)/(2^23 -1 ).  We use PGA = 1.
#define PGA_1		0x00U
#define PGA_2		0x10U
#define PGA_4		0x20U
#define PGA_8		0x30U
#define PGA_16		0x40U
#define PGA_32		0x50U
#define PGA_64		0x60U
#define PGA_128		0x70U

#define SPS_5		0x00U
#define SPS_10		0x01U
#define SPS_20		0x02U
#define SPS_40		0x03U
#define SPS_80		0x04U
#define SPS_160		0x05U
#define SPS_320		0x06U
#define SPS_640		0x07U
#define SPS_1000	0x08U
#define SPS_2000	0x09U

#define VTHERM_TRIALS   5
#define VTHERM_SPS      20

#define VRSI_TRIALS     10
#define VRSI_SPS        20

#define VRSE_TRIALS     10
#define VRSE_SPS        20

#define IK_TRIALS       1
#define IK_SPS          20

#define VK_TRIALS       5
#define VK_SPS          20

#define IB_TRIALS       1
#define IB_SPS          20

#define VB_TRIALS       5
#define VB_SPS          20

#define VBIAS_TRIALS   1
#define VBIAS_SPS      40


#define MAX_SAMPLING_PERIOD     3600            // New 15 Aug 2022, implementing a fix in sleep.c for a corrupt wakeup time.
#define MIN_SAMPLING_PERIOD     2

/*
 * 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         32  //was 30  These are for sampling / data logging configuration A-Z, 0-9
#define MAX_NUMOF_APP_CONFIG_FIELDS     16  // was 8 in 4.0.7

#define MAX_NUMOF_K2_CAL_FIELDS         4   // Storage allocated in sys_data
#define NUMOF_K2_CAL_FIELDS             4   // present size of polynomial
#define MAX_NUMOF_FP_CAL_FIELDS         10      //WAS 7  // Worse case storage allocation based on Josh Plant discussion
#define NUMOF_FP_CAL_FIELDS             MAX_NUMOF_FP_CAL_FIELDS //was 7   // present size of polynomial

#define MAX_FILENAME_SIZE               32      // was 16, now 32 30Jan2025 8.3 filename plus padding 24      //80 is too much, should be 32 or 40 at most.
#define MAX_USER_INITIALS   8
#define MAX_TESTER_NAME     48
#define MAX_VERSION_SIZE    32

#define MAX_BOARD_SN        24      //30
#define MAX_SPEC_SN         8
#define MAX_SPEC_DIGITAL_SN  8
#define MAX_SPEC_ANALOG_SN  8
#define MAX_LAMP_SN         24
#define MAX_PROBE_SN        24
#define MAX_PT_CAL_DATE     12
#define MAX_K0_CAL_DATE     12
#define MAX_SERVICE_DATE    12
#define MAX_CAL_FILENAME    48      //was 32      //16

#define MAX_MCAP_SN         24      //30
#define MAX_PACKAGE_NAME    32      //30
#define MAX_SENSOR_SN       12      //8       //24      //30  new 7 Sep 2023 changed from 24 to 8 and added 2 more 8 char fields, was MAX_DURAFET_SN
#define MAX_ISFET_SN        12       //was 8 MAX_CAPADAP_SN      24      //30
#define MAX_ISE_SN          12       //was 8 24      //30
#define MAX_OPTODE_SN       24      //30
#define MAX_CTD_SN          24      //30
#define MAX_PUMP_SN         24      //30
#define MAX_TIVA_SN         24
#define MAX_BOARD_FABNOTE   80      // was 80, now part of qa
#define MAX_PACKAGE_FABNOTE 80      //
#define MAX_DEPLOY_NOTE     80
#define MAX_QA_NOTE         80

// pump_sequencing types for selecting sequencing statemachine
#define TYPE_PUMP_NOTDEFD       0
#define TYPE_PUMP_SINGLE        1
#define TYPE_2PUMP_BEAMSV1      2
#define TYPE_2PUMP_BEAMSV2      3
#define TYPE_PUMP_SELFCAL       4

// MSC operation (MSC1 vs MSC3)
#define MSC1_OP                 0       // mimic Persistor CF2 behavior, even at the expense of power consumption and command semantics (stay stuck in the past to keep APF11 risk low)
#define MSC3_OP                 1


struct qaData
{
    uint32_t    microSD;            // microSD
    uint32_t    time;               // time of QA
    uint32_t    test_time;          // time it took to run QA
    uint32_t    eeprom;             // size of sys_data in eeprom, 0 if there is a problem
    uint32_t    sys_data_init;      // was the data initialized
    uint32_t    fram;
    uint32_t    nand;
    uint32_t    adc12onchip;
    uint32_t    adc24;              // how many of the ADC fields are out of expected Jensenian range


    float    Vrsi;
    float    Vrsi_std;
    float    Vrsi_err;
    float    Vrse;
    float    Vrse_std;
    float    Vrse_err;
    float    Vtherm;
    float    Vtherm_std;
    float    Vtherm_err;

    float    Ik;
    float    Ik_std;
    float    Ik_err;

    float    Vk;
    float    Vk_std;
    float    Vk_err;

    float    Ib;
    float    Ib_std;
    float    Ib_err;

    float    Vb;
    float    Vb_std;
    float    Vb_err;

    float    Vbias_pos;
    float    Vbias_neg;

    float    fSysVolt;
    float    fSysAmp;
    float    fLampVolt;
    float    fLampAmp;
    float    fBrdTempC;
    float    fBrdPress;
    uint32_t uiHumidity;

    uint32_t    aux_pwr1;
    uint32_t    aux_pwr2;
    uint32_t    aux_pwr3;

    uint32_t    ctd;
    uint32_t    optode;
    uint32_t    comm_pwr;

    char        tester[MAX_TESTER_NAME];
    char        firmware_version[MAX_VERSION_SIZE];
    char        board_fab_note[MAX_BOARD_FABNOTE];        //  New  board fabrication notes, dates, etc.
    char        qa_note[MAX_QA_NOTE];
};



//sampl
struct sampData
{
    uint32_t        initNumBeg;
    uint32_t        sampNum;        // 1
    uint32_t        timestamp;      // 2
    float           fBiasNeg;       // 3
    float           fBiasPos;       // 4
    float           fIb;            // 5 (Ib) SubstrateCurrent
    float           fIk;            // 6 (Ik) CounterElectrodeCurrent
    float           fIk_std;        // 7
    float           fVk;            // 8 (Vk) CounterElectrodeVoltage
    float           fVk_std;        // 9
    float           fVtherm;        // 10
    float           fVtherm_std;    // 11  Likely not needed
    float           fTempC;         // 12
    float           fVrsi;          // 13
    float           fVrsi_std;      // 14
    float           pHint;          // 15
    float           fVrse;          // 16
    float           fVrse_std;      // 17
    float           pHext;          // 18
    float           fVbat_main;     // 19
    float           fBrdTempC;      // 20
    unsigned int    uiHumidity;     // 21
    float           fsysAmp;        // 22  //new 8 Oct 2024
    float           spare1;
    float           spare2;
    uint32_t        initNumEnd;
    uint32_t        pad[2];         // 23  pad with spares after initNumEnd
};

// systemData struct organized for 4 byte packing, also fixed buffer overruns by setting size of fields in define
struct systemData
{
    //---------------- system config  ---------------------------
    uint32_t    initNumBeg;

    uint32_t    baud_rate;        //470 baud rate  (added by tm Jul 2018)
    // JLD->TGM should these be conditionally compiled out for all but the MSC3 boards?
    float       dura_vin_min_volt;        //4  Low battery voltage threshold for pH sample and uSD write  // was dura_vin_min_volt
    float       isus_vin_min_volt;        //   Low battery voltage threshold for nitrate sample and uSD write

    uint32_t    echo_flag;
    uint32_t    terminal_mode;             // H2M_MODE=0, M2M_MODE=1.   M2M suppresses prompt and cr-lf response
    uint32_t    autoSleepSec;               // inactivity sleep delay (was deployDelay)
    uint32_t    msc_op;                    //added to config MSC1 operation vs MSC3 operation
    uint32_t    diag;                  // diagnostic flag, for developer
    uint32_t    debug_flag;            // turn on diagnostic debug printf's

    uint32_t    syscfgspare[8];            //spares for future system config

    //---------------- pH datalogger samplingData ---------------------------
	uint32_t    sampling_period;	    //8 pH sampling period
	uint32_t    chksum;	    	    // was sample_average DEPRECATED (was int32_t) 12 Number of pH sensor samples to average
	uint32_t    averaging_interval;    //16 Number of seconds between each average
    bool        GMT;                       //456 GMT or Local time
    bool        sample_aligned;            //460 Sample aligned to hour
    uint32_t    deploy_time;               // timestamp of when 'deploy' menu action.   deployment time  (Todo, put in FRAM?) (variable location changed from above diag).

    unsigned char data_cfg[MAX_NUMOF_CONFIG_FIELDS];     //data field / logging configuration (added by tm Jul 2018)
    unsigned char app_cfg[MAX_NUMOF_APP_CONFIG_FIELDS];

	float       TCOffset;					//24 DuraFET temperature calibration variable (not needed)
    float       TCSlope;
	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
    double      quadTherm_c0;             // 4 coefficient c0 for thermistor
    double      quadTherm_c1;             // 4 coefficient c1 for thermistor
    double      quadTherm_c2;             // 4 coefficient c2 for thermistor
    double      quadTherm_c3;             // 4 coefficient c3 for thermistor
    double      shTherm_A;                // steinhart-hart coefficient A
    double      shTherm_B;                // steinhart-hart coefficient C
    double      shTherm_C;                // steinhart-hart coefficient B
	float       default_sal;               //36 default salinity (FRAM) TODO

	uint32_t    Vrsi_sps;				//Vrsi_sps	//418 pH Vint data rate setting (sps)
	uint32_t    Vrsi_trials;            //Vrsi_trials
	uint32_t    Vrse_sps;
	uint32_t    Vrse_trials;
	uint32_t    Vtherm_sps;
	uint32_t    Vtherm_trials;
	uint32_t    Ik_sps;
	uint32_t    Ik_trials;
	uint32_t    Vk_sps;
	uint32_t    Vk_trials;
	uint32_t    Ib_sps;
	uint32_t    Ib_trials;
    uint32_t    Vb_sps;
    uint32_t    Vb_trials;
    uint32_t    Vbias_sps;
    uint32_t    Vbias_trials;

    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?)
	uint32_t    test_mode;		        //426 Indicates test deployment
	uint32_t    fast_mode;             // Future: changed to sampling mode (fast, precise, etc.)
	uint32_t    solenoid_on2hold_msec;
	uint32_t    solenoid_hold_pwm;
	uint32_t    solenoid_holdtime;     // new 20 Jul 2021

	// Sampling and Sequencing StateMachine variables
    uint32_t    start_pump_time;         // (seconds) Wakeup on sampling interval, but check the 'start deployment time' before actual pumping/sampling 16 Feb 2022
    uint32_t    pump_seq_type;             // 0) legacy single pump, 1) BEAMS v1 dual pump seq, 2) BEAMS v2
    uint32_t    sampleCnt_duty_on;         // duty cycle for extending experiment.   3 days on, 5 days off.   Number of 'sample periods' on
    uint32_t    sampleCnt_duty_off;        // in sample periods.    Accept input in hours, translate to sample periods (keep implementation simple for now).
    uint32_t    pump1_cycles;                   // = 10 cycles
    uint32_t    pump2_cycles;                   // = 5 cycles
    uint32_t    pump1_ontime;          //20 Active pump time;                 // = 30 cycles
    uint32_t    pump2_ontime;                 // = 10 cycles
    uint32_t    pump_spare[12];            // was 16, now 12, echo_flag, terminal_mode, autoSleepSec, msc_op added

    float       pHOffset;                 // new 3 Aug 2021 (speculative placeholders, can be used as spare)  k0, etc are used for offsets on ph
    float       pHSlope;
    float       sensor_ctd_TC;
    float       sensor_optode_TC;
    float       K2_Cal[MAX_NUMOF_K2_CAL_FIELDS];                // worse case 4th order polynomial
    float       fP_Cal[MAX_NUMOF_FP_CAL_FIELDS];               // worse case 10th order polynomial
    float       k0_HCL;
    float       k0_SW;
    float       k0std_SW;

    float       spare[24];   // was 25, isus_vin, was spare[56] until 6 K2 and 12 F(p) cal coeeff (56-6-12=38), was float spare[64]; reduced by 32bytes (8 float) 10 Oct 2022  // LAYOUT CHANGE 16 Feb 2022, now 64 for v4.x future expansion. was 4 (was 9) 4 byte spares (36 bytes) for future expansion without causing EEPROM struct issues

    char        service_date[MAX_SERVICE_DATE];    //12
    char        PT_Cal_date[MAX_PT_CAL_DATE];      //12
    char        k0_Cal_date[MAX_K0_CAL_DATE];      //12
    char        cal_filename[MAX_CAL_FILENAME];       //32, was 16  duracalfile
	char        firmware_version[MAX_VERSION_SIZE]; //32
	//------------------ System MetaData ------------------
	// re-arranged struct to put char fields after numeric
    char        fileName[MAX_FILENAME_SIZE];              //116 The name the user would like to give their data output file, fatfs max is 8.3
    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        sensor_SN[MAX_SENSOR_SN];            //226 was 24, now 8, was durafet_SN, now sensor_SN, 7 Sep 2023 DuraFET sensor serial number
    char        isfet_SN[MAX_ISFET_SN];              // new 7 Sep 2023
    char        ise_SN[MAX_ISE_SN];                // new 7 Sep 2023
    char        package_name[MAX_PACKAGE_NAME];       //196 Name of integrated package (underway system, etc.)  (was 20, now 30, bug in buff entry size)
    char        spec_SN[MAX_SPEC_SN];
    char        spec_digital_SN[MAX_SPEC_DIGITAL_SN];
    char        spec_analog_SN[MAX_SPEC_ANALOG_SN];
    char        lamp_SN[MAX_LAMP_SN];
    char        probe_SN[MAX_PROBE_SN];

    char        optode_SN[MAX_OPTODE_SN];               // (added 3Apr2021) Aanderaa optode serial number
    char        ctd_SN[MAX_CTD_SN];                     // (added 3Apr2021) Aanderaa conductivity or MicroCat aka ctd serial number
    char        pump_SN[MAX_PUMP_SN];                   //406 Pump serial number
    char        pump2_SN[MAX_PUMP_SN];                  //406 Pump serial number
    char        tiva_SN[MAX_TIVA_SN];                   // Tiva serial number
    char        package_fab_note[MAX_BOARD_FABNOTE];    //  (added 4Apr2021)  was board fabrication notes, now 7 Nov 2023 package fab notes
    char        deploy_note[MAX_DEPLOY_NOTE];           // (Todo FRAM)

    uint32_t    initNumEnd;

    //struct      qaData qa;                       //qa struct serves as pad TODO, move to it's own struct
};
static_assert((sizeof(struct systemData) % 4) == 0, "systemData size must be evenly divisible by 4");

//Note: i2c_fram.c has fram layout (64bytes allocated for the 15*4=60 byte struct)  sys_samp
struct systemSamplingData           //TODO: rename to systemVolatileData
{
    uint32_t    initNumBeg;
    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                                          <<<<--------
    float       sensor_sal;               // salinity read from conductivity (SBE, Aanderaa)
    float       spare1;
    float       spare2;
    float       spare3;
    float       spare4;
    uint32_t    pump_seq_state;      // for controlling/sequencing pump/solenoid
    uint32_t    pump1_cnt;
    uint32_t    pump2_cnt;
    uint32_t    start_pump_cntdown;      // count down in 'sample periods'
    uint32_t    initNumEnd;
    uint32_t    pad[2];
};

// DEPRECATED variables that change each sample (will wear out onchip 500k write cycle flash / eeprom), stored in FRAM
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
//#endif


//DEFAULT Configuration for get_sample() is for all fields
// index into sys_data.data_cfg[]
#define CFG_SAMPLE_NUM          0
#define CFG_TIMESTAMP           1   // + MM/DD/YYYY HH:MM:SS

#define CFG_V_THERMISTOR        2       //+ Vthermistor\t
#define CFG_V_THERMISTOR_STD    3   //+ Vthermistor_std\t
#define CFG_CALC_TEMP           4   //+ calculated_temperature_Vthermistor\t

#define CFG_VRSI                5   //+ Vint\t
#define CFG_VRSI_STD            6   //+ Vint_std\t
#define CFG_CALC_PH_VRSI        7   //+ estimated_pH_int\r\n

#define CFG_VRSE                8   //+ Vext
#define CFG_VRSE_STD            9   // + Vext_std
#define CFG_CALC_PH_VRSE        10   //+ estimated_pH_ext\r\n (new 6May2019 TM)

#define CFG_VRSI_BIASED         11   //+ Vint_offset\t
#define CFG_VRSI_BIASED_STD     12   //+ Vint_offset_std\t
#define CFG_VRSE_BIASED         13   //+ Vext_offset\t
#define CFG_VRSE_BIASED_STD     14   //+ Vext_offset_std\t


#define CFG_V_COUNTER_ELECT     15   //+ Vcounter_electrode
#define CFG_V_COUNTER_ELECT_STD 16   //+ Vcounter_electrode_std
#define CFG_I_COUNTER           17   // + Counter_current
#define CFG_I_SUBSTRATE         18   //+ Substrate_current

#define CFG_VIN_BAT_VOLT        19   //+ Battery_Volt
#define CFG_BIAS_BAT_POS        20   //+ Bias Bat Volt
#define CFG_BIAS_BAT_NEG        21

#define CFG_BRD_TEMP            22   //+ Board_Temperature\t
#define CFG_BRD_HUMIDITY        23   // + Humidity_sensor


#define CFG_UART3_INST          24      // UART3 Instrument, was #define CFG_OPTODE              24   // Aanderaa optode
#define CFG_UART4_INST          25   // Aanderaa or MicroCat conductivity, AKA CFG_CONDUCTIVITY new 25 Mar 2021, was CFG_CTD

#define CFG_SPARE1              26  // was spare1 CFG_OCR
#define CFG_SPARE2              27

#define CFG_SPARE3              28
#define CFG_SPARE4              29
#define CFG_SPARE5              30
#define CFG_SPARE6              31

// Instrument drivers for UART3/Optode port and UART4/CTD port (sequential numbering, renumber is OK to do)
#define INST_OPTODE_NOTDEFD     0       // Instrument driver types for Uart3 / Optode port
#define INST_OPTODE             1
#define INST_OCR504             2
#define INST_NANOFET            3
#define INST_PICOPH             4

#define INST_CTD_NOTDEFD        5       // Instrument driver types for Uart4 / CTD port
#define INST_SBE37_MICROCAT     6
#define INST_AANDERAA_5860      7
#define INST_ADV                8

// MAX_NUMOF_CONFIG_FIELDS is set to 32 above.

//sys_data.app_cfg
// App config, used for bringing out new features, etc
#define APPCFG_SAMPLING_DIAG        0   // switch on timing printfs in fast_sample
#define APPCFG_TEMPC_SH_ALG         1   // used in Durafet_temp to switch algorithm
#define APPCFG_MICROSD_ENABLE       2   // APPCFG_SAMP_FLEX        2   // In fast_sample, used to allow for user edit variables for Trials and sps per ADS1284 sample
#define APPCFG_MENU_LEVEL           3
#define APPCFG_DEPLOY_UARTECHO      4   //Turn off uartEcho in deployment to help m2m with labview   //#define APPCFG_SPARE4           4
#define APPCFG_EXEC_SWITCHERONI     5   // Was APPCFG_SPARE5
#define APPCFG_FLOATMODE            6   // Was APPCFG_SPARE6  21 Aug 2024
#define APPCFG_SER_LINETERM_MODE    7   // Was APPCFG_SPARE7  21 Aug 2024 for serial console string line term 0=CR-LF, 1=CR, 2=LF
#define APPCFG_FILE_LINETERM_MODE   8   // Was APPCFG_SPARE8  16 Apr 2025 for file string line term  0=CR-LF, 1=CR, 2=LF
#define APPCFG_SPARE9           9
#define APPCFG_SPARE10          10
#define APPCFG_SPARE11          11
#define APPCFG_SPARE12          12
#define APPCFG_SPARE13          13
#define APPCFG_SPARE14          14
#define APPCFG_SPARE15          15


// Defines for exec / sampling function called in main
#define EXEC_DEPLOY               0
#define EXEC_EDDY_COVARIANCE      1
#define EXEC_FASTSAMP             2
// Defaults and limits
#define EXEC_MAXDEFD                EXEC_FASTSAMP
#define EXEC_DEFAULT                EXEC_DEPLOY




//----------- Key Defs --------
#define CTRL_X          24
//#define CTRL-X          CTRL_X


// Global variables
extern struct systemDataVolatile sys_data_vol;
extern struct systemDataVolatile sys_data_chg;


void read_bias_bat(void);

void display_battery_boardSensors(void);
void display_ph_ref_therm_volts(void);
void display_calcd_pH_intRef_therm(void);
void display_calcd_pH_extRef_therm_sal(float Salinity);
void communicate_with_instruments(void);
int power_output_tests(void);
void test_24bit_adc_mux(void);
int board_qa_and_init(int initFlg);


void initSysDataVolatileVariables(void);

void SysTickHandler(void);
unsigned long Timer_10ms(void);
unsigned long Timer_1ms(void);

bool is_timer_1ms_expired(const unsigned long t0, const unsigned long dt_ms);
bool is_timer_10ms_expired(const unsigned long t0, const unsigned long dt_10ms);

#if 0
    // delay for secs seconds, with only +2/-0 systick accuracy. Spins on __wfi() for power savings. Do not reset SysTick timer during use.
    void delay_sec_coarse(unsigned long secs);
    // delay for secs seconds, with only +2/-0 systick accuracy. Spins on __wfi() for power savings. Do not reset SysTick timer during use.
    void delay_msec_coarse(unsigned long msec);
#endif

// busy loop delay for secs seconds
void delay_sec(unsigned int secs);
// busy loop delay for msec milliseconds
void delay_msec(unsigned int msec);
void delay_msec_noDog(unsigned int msec);
// busy loop delay for usec microseconds
void delay_usec(unsigned int usec);
struct tm *get_RTC_time(void);

// Timer helper
// Uses Timer_1ms tick, +2/-0 tick, tends to oversleep by a tick
typedef struct
{
    unsigned long t0_ms;
    unsigned long dt_ms;
} TimerState;

void init_timer(TimerState* const t_ptr, unsigned long dt);
bool is_timer_expired(TimerState const * const t_ptr);

uint32_t eeprom_sys_data_store(void); //EEPROM
int eeprom_sys_data_retrieve(void);             //was retrieveSysDataVariables

uint32_t eeprom_sys_qa_store(void);
int eeprom_sys_qa_retrieve(void);

int sys_data_verify(void);
uint32_t smartStoreSysData(void);


uint32_t eeprom_apf_cfg_store(void);
int eeprom_apf_cfg_retrieve(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 fast_sample(int txFlg);  // moved to sampling.c

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);

bool check_silicon_revision_matches_tiva_build();


#if BOARD_MSC == 3
#define LOGERRORMSG(a,b,c) logErrorMsg(a,b,c)
#else
#define LOGERRORMSG(a,b,c)
#endif


#endif /* PHFETSOS_SYSTEM_H_ */
