/*
 * MBARI software for MFET and SeaFET boards, derived from Scripps Institute
 *     SeapHOx software for Rev-E PC board Version 2.0
 *
 * David Muller, davehmuller@gmail.com
 * Germán Alfaro, alfaro.germanevera@gmail.com
 * Rob Glatts, rglatts@ucsd.edu (from 4/2014)
 * Taylor Wirth, twirth@ucsd.edu (from 4/2015)
 *
 * Thom Maughan (TM), MBARI, tm@mbari.org (from 2/2018)
 *
 * v3.1.2:  deployment for Ischia
 * v3.1.3:  interim version, decided to roll to v3.1.4 for Glider and Cleanup
 * v3.1.4:  added configuration of data fields in get_sample, added get_header (gh) command  14 Aug 2018
 * v3.1.5:  glider deployment  Nov 2018  added 'sl' command and 'ts'   sl (send last) uses uSD to cache sample.  This makes the glider code simpler.
 * v3.1.6   glider deployment with mods to workaround power glitching (if sample period is 0, and power cycled, start in deployed mode)
 * v3.1.7:  Update fatfs to fix 'debug' build crash.  8 Feb 2019, Fix in ff.c (uninitialized FatFs[0] pointer in Debug Build.  Release relies on linker init of pointer
 * v3.2.0:  Bug fixes (spurious serial wakeup, aligned to hour default, var headers data cfg), bring SEAPHOX up to the same state as MFET.  29 Apr 2019 TM
 * v3.2.1:  Interim build tag, reduction of delays to improve sample request-response time and to reduce power.  Identified eeprom writecycle (500K) bug - eeprom being written on each sample
 * v3.2.2:  Project named changed from SeaFET_SeapHOx to SeapHOx_MFET.   Using register file in hibernate module to store volatile data in config struct to prevent eeprom burn out
 * v3.3.0:  Adding support for MFETrevB/MCAPrevC  1) different rs232 xcvr (MAX2333) so EN# and SHUTD#,  2) i2c_fram.c basic driver, 3) optode (has bug in ring buffer)
 * v3.3.1:  fram support for nonvolatile data (sequence number, etc) tested on MFET v2.  Sep 2019
 */
// NOTE: // VERSION is defd in system.h

// mA-Hr * Volts * 3.6 = Joules
// pH sampling  12.0v @ 14.5mA for 1.2seconds => 0.2 Joules

#include "System.h"
#include "Init.h"
#include "IO.h"
#include "SDCard.h"
#include "fatfs/src/ff.h"
#include "ADS1248_iso.h"
#include "ADS1248_noniso.h"
#include "Sleep.h"
#include "AUX1.h"
#include "AUX2.h"
#include "uartstdio.h"	// User local version with larger RX buffer

// Force a compile error if more than one board is =1
#if (BOARD_SEAPHOX==1 && BOARD_MFET>=1) || (BOARD_SEAPHOX==0 && BOARD_MFET==0)
    PROBLEM  Right click project->properties, Build->Compiler->Predefine Symbols and define only one BOARD_XXX=1
#endif


extern int print_sampBuf(void);

extern void ADS1248_gpio2(uint32_t state);
extern void ADS1248_gpio2_test(void);
extern void get_header(void);

extern void led_green_off(void);
extern void led_green_on(void);
extern void led_red_toggle(void);
extern void led_red_off(void);
extern void led_red_on(void);
extern void profile_toggle(int target);
extern void profile_off(int target);
extern void profile_on(int target);

extern void profile2_toggle(int target);
extern void profile2_off(int target);
extern void profile2_on(int target);

extern uint16_t read_adc_temperature(void);
extern uint16_t read_adc(uint32_t chan);

extern void ADS1248_gpio_ADG1609_mux(uint32_t chan);
extern unsigned long Timer_10ms(bool reset);

extern void print_bias_volt_iso(void);
extern uint32_t storeSysDataVariables(void);

//int test_sampling_mcap(float extRefOff, float intRefOff, float extRefV, float intRefV, float cntrC, float cntrV, float substCur, float substV, float thermistor);

void test_24bit_adc_mux(void);
void adc_onchip_init(void);
uint16_t * read_all_adc(void);
void state_dump(void);
void configuration(void);
void test(void);
void deploy(deploy_state state);

/*
 * Global System variables.
 */
extern uint32_t adc_data[];
extern char Optode_buff[];

struct systemData sys_data;
struct systemDataVolatile sys_data_vol;
struct systemDataVolatile sys_data_chg;         // used to write to hibernate module battery backed register file


int dbg_flag = 0;                 // global var used for dbg_printf
int profileTarget = 0;
int profile2Target = 0;
int ads1248noniso_flg = 0;


// -- Glider Data Config Set
// A Sample Num
// B MM/DD/YYYY HH:MM:SS
// C Battery Volt
// O Vext Ref
// P Vext Ref Std
// Q Vcounter Electrode
// R Vcounter Electrode Std
// S Counter Electrode Current
// T Substrate Current
// Z FAST

/*
 * main.c
 */

int main(void)
{
	char input;
	time_t timer;
	uint16_t deployDelay;    // added variable per the request to make deploy delay configurable. 24 Jan 2019


	Init();		// Initialize pins and ports  // 425 usec  (removed 400 msec delay)

	// Symbols for board builds are define in Project Properties (right click project, Select properties,
	// then select Build->ARM Compiler->Predefined Symbols.  Edit the BOARD_XXX and define = 1.  Only 1 board
	// should be =1, the deselected board is =0
#if BOARD_SEAPHOX == 1
    dbg_printf("\n***** BOARD_SEAPHOX = 1 *****\n");        // 100usec
#endif
#if BOARD_MFET == 1
    dbg_printf("\n***** BOARD_MFET = 1 *****\n");
#endif
#if BOARD_MFET == 2
    dbg_printf("\n***** BOARD_MFET = 2 *****\n");
#endif


    /*  Thoms notes on top level statemachine:  the code needs refactoring as it is too challenging to make changes
     *
     * Re-write of the top level state machine as it is layered with quick fixes and is getting difficult to implement changes
     * without side effects
     *
     * SLEEP/IDLE - state for a pre-deployment system
     *    - woke up by serial or reset switch
     * DEPLOY - after configuration of sampling parameters, this is the lower power state woke by
     *     A) real time clock based on sampling period
     *     B) when sampling period = 0, it is in polled mode and responds to 'ts' or 'sl'   STOP to get it out of sampling mode
     *
     * Use Cases:
     *    LABINSTRUMENT - wired, power cycled at times, typically polled. does not need to log to uSD.
     *    DATALOGGER - battery powered, self timed RTC based logging to uSD, insure the battery does not get too low to prevent uSD corruption
     *    'GLIDER" - power is being cycled.  power on, polled get_sample, save to uSD, respond to ts, sleep.  When the glider is on a down cast, power is turned off
     *
     *
     * MENU - state for setup and testing with user interface provided through the console port
     *    - times out and returns to previous state (SLEEP or DEPLOY).
     *    - Test is part of the menu state
     *    - MENU is not a state that is stored in sys_dataq
     *
     *    The question is, when a key is hit, the app wakes up,
     *      if nothing is commanded,
     *      then it should go back to the state it was in (SLEEP or DEPLOY) within a few seconds
     *
     *    if the menu key is hit (m, M, h, H, or <ENTER>) then the menu is displayed and the return to state it was in time should be 30 seconds (maybe even a minute)
     *      if the user changes the state in the menu, then this state gets stored in sys_data.state and off the app goes in that mode
     *
     *    Polled mode is achieved by a sample_period of 0, this could also be what makes it 'sleep'.   Deploy would then ask - polled or timed?
     *
     */


    if( sys_data.state == IDLE)
    {
        dbg_printf("\nstate = IDLE\n");
    }


	// when you upload a new program, it goes straight into deplyoment.YT 4/29/2015 fix later.
	if(sys_data.state == DEPLOYED)
	{
        dbg_printf("\ncalling deploy(DEPLOYED)\n");
	    deploy(DEPLOYED);
	    //state_dump();       // DEBUG
	}

	if( sys_data.state == COMMAND)
	{
        dbg_printf("\ncalling deploy(COMMAND)\n");
	    deploy(COMMAND);

	}


    deployDelay = 30;

	while(1) //added while loop for user to choose command or enter deployment automatically --1/24/2017 -TW
		{
		uprintf("\n*****Press enter to bring up main menu*****\n");

        // Else must be IDLE mode
        while(1)
        {
            // Get user's selection with a 30 sec timeout - enter deployment mode --1/24/2017 -TW
            UARTFlushRx();
            //timer = 30 + ROM_HibernateRTCGet(); // 30 second delay | timer = 300 + ROM_HibernateRTCGet();

            // THOM per Yui/Brent to hack the power glitch problem (header gets written, seems to be power cycled.
            timer = deployDelay + ROM_HibernateRTCGet(); // 30 second delay | timer = 300 + ROM_HibernateRTCGet();

            while(1)
            {
                if( UARTRxBytesAvail() )
                {
                    input = get_key();
                    break;    // break from while(1)
                }
                if( timer <= ROM_HibernateRTCGet() )
                {
                    // THOM 23Apr2019 - timeout on menu is resulting in a big when SP is in sleep and a spurious character wakes it up, this results in 'deploy'
                     //deploy(START); //enter deployment mode | if( timer <= ROM_HibernateRTCGet() ) sleep(IDLE, 0);
                    if(sys_data.state == IDLE)
                    {
                        dbg_printf("\n***** SLEEP *****\n");  // THOM DEBUG
                        sleep(IDLE, 0);
                    }
                    if (sys_data.state == DEPLOYED)
                    {
                        // if woke up by spurious character and was deployed, got back to sleep
                        dbg_printf("\n***** D E P L O Y (was deployed, stay deployed) *****\n");  // THOM DEBUG
                        deploy(DEPLOYED);  // THOM new 7May2019
                    }
                    else            // if (sys_data.state == DEPLOY)
                    {
                        dbg_printf("\n***** D E P L O Y  (and write header) *****\n");  // THOM DEBUG
                        deploy(START);      // THOM this causes the header to be written
                    }
                }
            }


            // Print out the menu:
            uprintf("\n\n\nMain Menu -- %s -- Will sleep in %u seconds", VERSION, deployDelay);      // VERSION is defd in system.h

            uprintf("\n1 -- Configure");
            uprintf("\n2 -- Deploy");
            uprintf("\n3 -- Test");
            uprintf("\n4 -- Sleep");
            uprintf("\n5 -- Files");
            uprintf("\nH -- Help");
            uprintf("\nEnter Selection: ");

            switch(input)
            {
                case '1':
                    configuration();
                    break;

                case '2':
                    deploy(START);
                    break;

                case '3':
                    test();
                    break;

                case '4':
                    sleep(IDLE, 0);
                    break;

                case '5':
                    viewFiles();
                    break;

                case '6':
					if(dbg_flag == 1)
	                    state_dump();
                    break;

                case '7':
                    if(dbg_flag == 1)
                    {
                        uprintf("\n\ninitSysDataVolatileVariables()\n");
                        initSysDataVolatileVariables();
                        uprintf("\nsys_data_chg.state = %u\n", sys_data_chg.state);
                        uprintf("\nsys_data_chg.nextWakeUp = %u\n", sys_data_chg.nextWakeUp);
                        uprintf("\nsys_data_chg.next_gdata_fptr = %u\n", sys_data_chg.next_gdata_fptr);
                        uprintf("\nsys_data_chg.current_sample = %u\n", sys_data_chg.current_sample);
                        uprintf("\nsys_data_chg.AD24_std = %f\n", sys_data_chg.AD24_std);
                        uprintf("\nsys_data_chg.samp_state = %u\n", sys_data_chg.samp_state);
                        uprintf("\nsys_data_chg.chksum = 0x%08x\n", sys_data_chg.chksum);

                        uprintf("\n\nretrieveSysDataVariables()\n");
                        retrieveSysDataVariables();
                        uprintf("\nsys_data_chg.state = %u\n", sys_data_chg.state);
                        uprintf("\nsys_data_chg.nextWakeUp = %u\n", sys_data_chg.nextWakeUp);
                        uprintf("\nsys_data_chg.next_gdata_fptr = %u\n", sys_data_chg.next_gdata_fptr);
                        uprintf("\nsys_data_chg.current_sample = %u\n", sys_data_chg.current_sample);
                        uprintf("\nsys_data_chg.AD24_std = %f\n", sys_data_chg.AD24_std);
                        uprintf("\nsys_data_chg.samp_state = %u\n", sys_data_chg.samp_state);
                        uprintf("\nsys_data_chg.chksum = 0x%08x\n", sys_data_chg.chksum);


                    }
                    break;

                case '8':
                    if(dbg_flag == 1)
                    {
                        uprintf("\n\nretrieveSysDataVariables()\n");
                        retrieveSysDataVariables();
                        uprintf("\nsys_data_chg.state = %u\n", sys_data_chg.state);
                        uprintf("\nsys_data_chg.nextWakeUp = %u\n", sys_data_chg.nextWakeUp);
                        uprintf("\nsys_data_chg.next_gdata_fptr = %u\n", sys_data_chg.next_gdata_fptr);
                        uprintf("\nsys_data_chg.current_sample = %u\n", sys_data_chg.current_sample);
                        uprintf("\nsys_data_chg.AD24_std = %f\n", sys_data_chg.AD24_std);
                        uprintf("\nsys_data_chg.samp_state = %u\n", sys_data_chg.samp_state);
                        uprintf("\nsys_data_chg.chksum = 0x%08x\n", sys_data_chg.chksum);
                    }

                    break;

                case 'a':
                    if(dbg_flag == 1)
                    {
                        uprintf("\nled green toggle\n");
                        led_green_toggle();
                    }
                    break;
                case 'b':
                    if(dbg_flag == 1)
                    {
                        uprintf("\nled red toggle\n");
                        led_red_toggle();
                    }
                    break;

                case 'h':
                case 'H':
                    uprintf("\n\nVersion -- %s, %s \n ", VERSION, NONVOLATILEMEM);      // VERSION is defd in system.h
#if BOARD_MFET >= 1
                    uprintf("\nMFET Power Consumption per Sample = ~0.2 Joules per sample:  12v, 1.2sec, ~14.5mA => 12 * 14.5 * (1.2 / 3600) * 3.6 = ~0.2 Joules\n\n");
#endif

                    uprintf("\n\n--------- Configuration --------------\n");
                    uprintf("\nConfiguration checklist: (use Main Menu 1--Configure)\n");
                    uprintf("\n1 -- Set Clock");
                    uprintf("\n2 -- Change File Name");
                    uprintf("\n3 -- Set Deployment Parameters");
                    uprintf("\n        - Sample aligned to hour? (Y/N) [Y]?");
                    uprintf("\n        - Enter sample period [20] sec:   Polled Mode: configure with a period of 0 seconds");
                    //uprintf("\n       Enter pH sample average [5] samples:");
                    uprintf("\n        - Enter pump on time [0] sec:");
                    uprintf("\n        - Enter low battery_voltage (10.5 V for SeapHOx, 5.5 V for MFET) [5.5 V]:");
                    uprintf("\n4 -- Enter pH Sensor Calibration Coefficients");
                    uprintf("\n7 -- Config Data Fields");
                    uprintf("\n");
                    ROM_SysCtlDelay(MILLISECOND*300);  // tx buffer before filling with more
                    uprintf("\n\n------ Deployment Mode commands ------\n");
                    uprintf("\nany character to wake, then issue command:\n");
                    uprintf("\nstop  -- stop sampling, exit deployment mode");
                    uprintf("\ngdata -- get data since last command");
                    uprintf("\nts    -- take sample with 1.2 sec response time");
                    uprintf("\nss    -- start sample followed by 'sl' command to send last sample, times out after 8 sec");
                    uprintf("\ngh    -- get header");
                    uprintf("\n");
                    uprintf("\n");

                    break;

                default:
                    // if an invalid char is received, then
                    break;


            }
        }
    }
}

void change_baud_rate(void)
{
    char input;
    time_t timer;

    //print out config menu
    uprintf("\n\n\nChange Baud Rate - select baud menu item, change terminal baud rate, then hit 'V' to verify, then sleep and wakeup");
    //uprintf("\nV -- Verify");
    uprintf("\n1 -- 115200");
    uprintf("\n2 -- 9600");
    uprintf("\n9 -- Exit to Main Menu");
    uprintf("\nEnter Selection [9]: ");

    // Get user's selection with a 5 min timeout
    UARTFlushRx();
    timer = 300 + ROM_HibernateRTCGet();

    while(1)
    {
        if( UARTRxBytesAvail() )
        {
            input = get_key();
            break;
        }

        if( timer <= ROM_HibernateRTCGet() ) sleep(IDLE, 0);
    }

    switch(input)
    {
        case 'V':
        case 'v':
            uprintf("\nBaud rate verify\n");
            break;
        case '1':
            // 115200
            sys_data.baud_rate = 115200L;
            UARTStdioConfig(0, 115200, 16000000);       // 115200 bits per second
            break;
        case '2':
            sys_data.baud_rate = 9600L;
            UARTStdioConfig(0, 9600, 16000000);       // 9600 bits per second
            break;
        default:
            // Write the sys_data struct into EEPROM.  Last argument ensures # of bytes is multiple of 4
            if(storeSysDataVariables())                 //if(EEPROMProgram((uint32_t*) &sys_data, 0x400, (sizeof(sys_data) + 3) & ~3))
            {
                uprintf("\n\nError storing system data.\n");
            }
            else
                uprintf("\n\nSystem data stored.  -- Press enter to bring up main menu\n");
            break;

    }

}

/********************************************************************************************
 *  Config Data Fields
 ********************************************************************************************/
void config_data_fields(void)
{
    char input;
    time_t timer;
    unsigned char cfg;
    unsigned char index;

    while(1)
    {
        //print out config menu
        uprintf("\n\n\nChange Data Field - lower case turns data field off (=0), upper case turns field on (=1)\n\n\n");
#if BOARD_MFET>=1
        uprintf("\nA -- Sample Num = %u\t\t", sys_data.data_cfg[CFG_SAMPLE_NUM]);    //+ Sample_Number\t
        uprintf("\nB -- MM/DD/YYYY HH:MM:SS = %u\t", sys_data.data_cfg[CFG_TIMEDATE]);                     //+ MM/DD/YYYY HH:MM:SS\t
        uprintf("\nC -- Battery Volt = %u\t\t", sys_data.data_cfg[CFG_ENV_BAT_VOLT]);             //+ Battery_Voltage\t
        uprintf("\nD -- Board Temp = %u\t\t", sys_data.data_cfg[CFG_ENV_BRD_TEMP]);                   //+ Board_Temperature\t
        uprintf("\nE -- Humidity = %u\t\t\t", sys_data.data_cfg[CFG_ENV_HUMIDITY]);                  //+ Humidity_sensor\t
        uprintf("\nF -- Pressure = %u\t\t\t", sys_data.data_cfg[CFG_INT_PRESSURE]);                  //+ Internal_Pressure\t
        uprintf("\nG -- Vthermistor = %u\t\t\t", sys_data.data_cfg[CFG_V_THERMISTOR]);                     //+ Vthermistor\t
        uprintf("\nH -- Vtermistor Std = %u\t\t", sys_data.data_cfg[CFG_V_THERMISTOR_STD]);                 //+ Vthermistor_std\t
        uprintf("\nI -- Vint Offset = %u\t\t\t", sys_data.data_cfg[CFG_V_INT_OFFSET]);                //- Vint_offset\t
        uprintf("\nJ -- Vint Offset Std = %u\t\t", sys_data.data_cfg[CFG_V_INT_OFFSET_STD]);            //- Vint_offset_std\t
        uprintf("\nK -- Vext Offset = %u\t\t", sys_data.data_cfg[CFG_V_EXT_OFFSET]);                //- Vext_offset\t
        uprintf("\nL -- Vext Offset Std = %u\t\t", sys_data.data_cfg[CFG_V_EXT_OFFSET_STD]);            //- Vext_offset_std\t
        uprintf("\nM -- Vint = %u\t\t\t", sys_data.data_cfg[CFG_V_INT]);                       //+ Vint\t
        uprintf("\nN -- Vint Std = %u\t\t\t", sys_data.data_cfg[CFG_V_INT_STD]);                   //+ Vint_std\t
        uprintf("\nO -- Vext Ref = %u\t\t\t", sys_data.data_cfg[CFG_V_EXT]);                   //- Vext\t
        uprintf("\nP -- Vext Ref Std = %u\t\t\t", sys_data.data_cfg[CFG_V_EXT_STD]);                   //- Vext_std\t
        uprintf("\nQ -- Vcounter Electrode = %u\t\t", sys_data.data_cfg[CFG_V_COUNTER_ELECT]);         // Vcounter_electrode\t
        uprintf("\nR -- Vcounter Electrode Std = %u\t\t", sys_data.data_cfg[CFG_V_COUNTER_ELECT_STD]);     // Vcounter_electrode_std\t
        uprintf("\nS -- Counter Electrode Current = %u\t", sys_data.data_cfg[CFG_I_COUNTER]);            // Counter_current\t
        uprintf("\nT -- Substrate Current = %u\t\t\t", sys_data.data_cfg[CFG_I_SUBSTRATE]);         // Substrate_current\t
        uprintf("\nU -- Calc Temperature = %u\t\t\t", sys_data.data_cfg[CFG_CALC_TEMP]); //uprintf("%8.6f\t", calculated_temperature_Vthermistor);          // calculated_temperature_Vthermistor\t
        //uprintf("\nV -- Estimated pH = %u\t\t\t", sys_data.data_cfg[CFG_EST_PH_INT]);                      // estimated_pH_int\r\n
        uprintf("\nV -- Estimated pH Int = %u\t\t\t", sys_data.data_cfg[CFG_EST_PH_INT]);                      // estimated_pH_int\r\n
        uprintf("\nW -- Estimated pH Ext = %u\t\t\t", sys_data.data_cfg[CFG_EST_PH_EXT]);
        uprintf("\nX -- Optode = %u\t\t\t", sys_data.data_cfg[CFG_OPTODE]);
        uprintf("\nZ -- Fast Mode = %u\t\t\t", sys_data.fast_mode);
        uprintf("\n0 -- Zero (Clear) all config fields");
        uprintf("\n1 -- Set all config fields");
        uprintf("\n2 -- Use Case: GLIDER, fields (A,B,C,O,P,Q,R,S,T,Z)");

#endif

#if BOARD_SEAPHOX==1
        uprintf("\nA -- Sample Num = %u\t\t", sys_data.data_cfg[CFG_SAMPLE_NUM]);    //+ Sample_Number\t
        uprintf("\nB -- MM/DD/YYYY HH:MM:SS = %u\t", sys_data.data_cfg[CFG_TIMEDATE]);                     //+ MM/DD/YYYY HH:MM:SS\t
        uprintf("\nC -- Battery Volt = %u\t\t", sys_data.data_cfg[CFG_ENV_BAT_VOLT]);             //+ Battery_Voltage\t
        uprintf("\nD -- Board Temp = %u\t\t", sys_data.data_cfg[CFG_ENV_BRD_TEMP]);                   //+ Board_Temperature\t
        uprintf("\nE -- Humidity (MFET) = %u\t\t\t", sys_data.data_cfg[CFG_ENV_HUMIDITY]);                  //+ Humidity_sensor\t
        uprintf("\nF -- Pressure (MFET) = %u\t\t\t", sys_data.data_cfg[CFG_INT_PRESSURE]);                  //+ Internal_Pressure\t
        uprintf("\nG -- Vthermistor = %u\t\t\t", sys_data.data_cfg[CFG_V_THERMISTOR]);                     //+ Vthermistor\t
        uprintf("\nH -- Vtermistor Std = %u\t\t", sys_data.data_cfg[CFG_V_THERMISTOR_STD]);                 //+ Vthermistor_std\t
        uprintf("\nI -- Vint Offset (MFET) = %u\t\t\t", sys_data.data_cfg[CFG_V_INT_OFFSET]);                //- Vint_offset\t
        uprintf("\nJ -- Vint Offset Std (MFET) = %u\t\t", sys_data.data_cfg[CFG_V_INT_OFFSET_STD]);            //- Vint_offset_std\t
        uprintf("\nK -- Vext Offset (MFET) = %u\t\t", sys_data.data_cfg[CFG_V_EXT_OFFSET]);                //- Vext_offset\t
        uprintf("\nL -- Vext Offset Std (MFET) = %u\t\t", sys_data.data_cfg[CFG_V_EXT_OFFSET_STD]);            //- Vext_offset_std\t
        uprintf("\nM -- Vint = %u\t\t\t", sys_data.data_cfg[CFG_V_INT]);                       //+ Vint\t
        uprintf("\nN -- Vint Std = %u\t\t\t", sys_data.data_cfg[CFG_V_INT_STD]);                   //+ Vint_std\t
        uprintf("\nO -- Vext Ref = %u\t\t\t", sys_data.data_cfg[CFG_V_EXT]);                   //- Vext\t
        uprintf("\nP -- Vext Ref Std = %u\t\t\t", sys_data.data_cfg[CFG_V_EXT_STD]);                   //- Vext_std\t
        uprintf("\nQ -- Vcounter Electrode (MFET) = %u\t\t", sys_data.data_cfg[CFG_V_COUNTER_ELECT]);         // Vcounter_electrode\t
        uprintf("\nR -- Vcounter Electrode Std (MFET) = %u\t\t", sys_data.data_cfg[CFG_V_COUNTER_ELECT_STD]);     // Vcounter_electrode_std\t
        uprintf("\nS -- Counter Electrode Current = %u\t", sys_data.data_cfg[CFG_I_COUNTER]);            // Counter_current\t
        uprintf("\nT -- Substrate Current = %u\t\t\t", sys_data.data_cfg[CFG_I_SUBSTRATE]);         // Substrate_current\t
        uprintf("\nU -- DuraFET Temperature = %u\t\t\t", sys_data.data_cfg[CFG_CALC_TEMP]); //uprintf("%8.6f\t", calculated_temperature_Vthermistor);          // calculated_temperature_Vthermistor\t
        uprintf("\nV -- Estimated pH Int = %u\t\t\t", sys_data.data_cfg[CFG_EST_PH_INT]);                      // estimated_pH_int\r\n
        uprintf("\nW -- Estimated pH Ext = %u\t\t\t", sys_data.data_cfg[CFG_EST_PH_EXT]);
#endif


        uprintf("\n9 -- Exit to Main Menu");
        uprintf("\nEnter Selection [9]: ");

        // Get user's selection with a 5 min timeout
        UARTFlushRx();
        timer = 300 + ROM_HibernateRTCGet();

        while(1)
        {
            if( UARTRxBytesAvail() )
            {
                input = get_key();
                break;
            }

            if( timer <= ROM_HibernateRTCGet() ) sleep(IDLE, 0);
        }

        switch(input)
        {
            case 'A':
                sys_data.data_cfg[CFG_SAMPLE_NUM] = 1;   //
                break;
            case 'a':
                sys_data.data_cfg[CFG_SAMPLE_NUM] = 0;
                break;
            case 'B':
                sys_data.data_cfg[CFG_TIMEDATE] = 1;
                break;
            case 'b':
                sys_data.data_cfg[CFG_TIMEDATE] = 0;
                break;
            case 'C':
                sys_data.data_cfg[CFG_ENV_BAT_VOLT] = 1;   //        2   //+ Battery_Volt
                break;
            case 'c':
                sys_data.data_cfg[CFG_ENV_BAT_VOLT] = 0;
                break;
            case 'D':
                sys_data.data_cfg[CFG_ENV_BRD_TEMP] = 1;   //        3   //+ Board_Temperature\t
                break;
            case 'd':
                sys_data.data_cfg[CFG_ENV_BRD_TEMP] = 0;
                break;
            case 'E':
                sys_data.data_cfg[CFG_ENV_HUMIDITY] = 1;   //        4   // + Humidity_sensor
                break;
            case 'e':
                sys_data.data_cfg[CFG_ENV_HUMIDITY] = 0;
                break;
            case 'F':
                sys_data.data_cfg[CFG_INT_PRESSURE] = 1;   //        5   //+ Internal_pressure
                break;
            case 'f':
                sys_data.data_cfg[CFG_INT_PRESSURE] = 0;
                break;
            case 'G':
                sys_data.data_cfg[CFG_V_THERMISTOR] = 1;   //        6       //+ Vthermistor\t
                break;
            case 'g':
                sys_data.data_cfg[CFG_V_THERMISTOR] = 0;
                sys_data.data_cfg[CFG_V_THERMISTOR_STD] = 0;
                break;
            case 'H':
                sys_data.data_cfg[CFG_V_THERMISTOR_STD] = 1;   //    7   //+ Vthermistor_std\t
                sys_data.data_cfg[CFG_V_THERMISTOR] = 1;
                break;
            case 'h':
                sys_data.data_cfg[CFG_V_THERMISTOR_STD] = 0;
                break;
            case 'I':
                sys_data.data_cfg[CFG_V_INT_OFFSET] = 1;   //        8   //+ Vint_offset\t
                break;
            case 'i':
                sys_data.data_cfg[CFG_V_INT_OFFSET] = 0;
                sys_data.data_cfg[CFG_V_INT_OFFSET_STD] = 0;
                break;
            case 'J':
                sys_data.data_cfg[CFG_V_INT_OFFSET_STD] = 1;   //    9   //+ Vint_offset_std\t
                sys_data.data_cfg[CFG_V_INT_OFFSET] = 1;
                break;
            case 'j':
                sys_data.data_cfg[CFG_V_INT_OFFSET_STD] = 0;
                break;
            case 'K':
                sys_data.data_cfg[CFG_V_EXT_OFFSET] = 1;   //        10   //+ Vext_offset\t
                break;
            case 'k':
                sys_data.data_cfg[CFG_V_EXT_OFFSET] = 0;
                sys_data.data_cfg[CFG_V_EXT_OFFSET_STD] = 0;
                break;
            case 'L':
                sys_data.data_cfg[CFG_V_EXT_OFFSET_STD] = 1;   //    11   //+ Vext_offset_std\t
                sys_data.data_cfg[CFG_V_EXT_OFFSET] = 1;
                break;
            case 'l':
                sys_data.data_cfg[CFG_V_EXT_OFFSET_STD] = 0;
                break;
            case 'M':
                sys_data.data_cfg[CFG_V_INT] = 1;   //               12   //+ Vint\t
                break;
            case 'm':
                sys_data.data_cfg[CFG_V_INT] = 0;
                sys_data.data_cfg[CFG_V_INT_STD] = 0;
                break;
            case 'N':
                sys_data.data_cfg[CFG_V_INT_STD] = 1;   //           13   //+ Vint_std\t
                sys_data.data_cfg[CFG_V_INT] = 1;
                break;
            case 'n':
                sys_data.data_cfg[CFG_V_INT_STD] = 0;
                break;
            case 'O':
                sys_data.data_cfg[CFG_V_EXT] = 1;   //               14   //+ Vext
                break;
            case 'o':
                sys_data.data_cfg[CFG_V_EXT] = 0;
                sys_data.data_cfg[CFG_V_EXT_STD] = 0;
                break;
            case 'P':
                sys_data.data_cfg[CFG_V_EXT_STD] = 1;   //           15   // + Vext_std
                sys_data.data_cfg[CFG_V_EXT] = 1;
                break;
            case 'p':
                sys_data.data_cfg[CFG_V_EXT_STD] = 0;
                break;
            case 'Q':
                sys_data.data_cfg[CFG_V_COUNTER_ELECT] = 1;   //     16   //+ Vcounter_electrode
                break;
            case 'q':
                sys_data.data_cfg[CFG_V_COUNTER_ELECT] = 0;
                sys_data.data_cfg[CFG_V_COUNTER_ELECT_STD] = 0;
                break;
            case 'R':
                sys_data.data_cfg[CFG_V_COUNTER_ELECT_STD] = 1;   //   //+ Vcounter_electrode_std
                sys_data.data_cfg[CFG_V_COUNTER_ELECT] = 1;
                break;
            case 'r':
                sys_data.data_cfg[CFG_V_COUNTER_ELECT_STD] = 0;
                break;
            case 'S':
                sys_data.data_cfg[CFG_I_COUNTER] = 1;   //           18   // + Counter_current
                break;
            case 's':
                sys_data.data_cfg[CFG_I_COUNTER] = 0;
                break;
            case 'T':
                sys_data.data_cfg[CFG_I_SUBSTRATE] = 1;   //         19   //+ Substrate_current
                break;
            case 't':
                sys_data.data_cfg[CFG_I_SUBSTRATE] = 0;
                break;
            case 'U':
                sys_data.data_cfg[CFG_CALC_TEMP] = 1;   //           20   //+ calculated_temperature_Vthermistor\t
                break;
            case 'u':
                sys_data.data_cfg[CFG_CALC_TEMP] = 0;
                break;
            case 'V':
                sys_data.data_cfg[CFG_EST_PH_INT] = 1;   //          21   //+ estimated_pH_int\r\n
                break;
            case 'v':
                sys_data.data_cfg[CFG_EST_PH_INT] = 0;
                break;
            case 'W':
                sys_data.data_cfg[CFG_EST_PH_EXT] = 1;   //          22   //+ estimated_pH_ext\r\n (new 6May2019 TM)
                break;
            case 'w':
                sys_data.data_cfg[CFG_EST_PH_EXT] = 0;
                break;
            case 'X':
                sys_data.data_cfg[CFG_OPTODE] = 1;
                break;
            case 'x':
                sys_data.data_cfg[CFG_OPTODE] = 0;
                break;

            case 'Z':
                sys_data.fast_mode = 1;
                break;
            case 'z':
                sys_data.fast_mode = 0;
                break;

            case '2':
                // -- Glider Data Config Set
                // A Sample Num
                // B MM/DD/YYYY HH:MM:SS
                // C Battery Volt
                // O Vext Ref
                // P Vext Ref Std
                // Q Vcounter Electrode
                // R Vcounter Electrode Std
                // S Counter Electrode Current
                // T Substrate Current
                // Z FAST

                sys_data.data_cfg[CFG_SAMPLE_NUM] = 1;          // A
                sys_data.data_cfg[CFG_TIMEDATE] = 1;            // B
                sys_data.data_cfg[CFG_ENV_BAT_VOLT] = 1;        // C
                sys_data.data_cfg[CFG_ENV_BRD_TEMP] = 0;        // d
                sys_data.data_cfg[CFG_ENV_HUMIDITY] = 0;        //e
                sys_data.data_cfg[CFG_INT_PRESSURE] = 0;        //f
                sys_data.data_cfg[CFG_V_THERMISTOR] = 0;        //g
                sys_data.data_cfg[CFG_V_THERMISTOR_STD] = 0;    //h
                sys_data.data_cfg[CFG_V_INT_OFFSET] = 0;        //i
                sys_data.data_cfg[CFG_V_INT_OFFSET_STD] = 0;    // j
                sys_data.data_cfg[CFG_V_EXT_OFFSET] = 0;        // k
                sys_data.data_cfg[CFG_V_EXT_OFFSET_STD] = 0;    //l
                sys_data.data_cfg[CFG_V_INT] = 0;               // m
                sys_data.data_cfg[CFG_V_INT_STD] = 0;           // n
                sys_data.data_cfg[CFG_V_EXT] = 1;               // O              14   //+ Vext
                sys_data.data_cfg[CFG_V_EXT_STD] = 1;           //   P        15   // + Vext_std
                sys_data.data_cfg[CFG_V_COUNTER_ELECT] = 1;     //  Q   16   //+ Vcounter_electrode
                sys_data.data_cfg[CFG_V_COUNTER_ELECT_STD] = 1; // R  //+ Vcounter_electrode_std
                sys_data.data_cfg[CFG_I_COUNTER] = 1;           //  S         18   // + Counter_current
                sys_data.data_cfg[CFG_I_SUBSTRATE] = 1;         // T        19   //+ Substrate_current
                sys_data.data_cfg[CFG_CALC_TEMP] = 0;           // u
                sys_data.data_cfg[CFG_EST_PH_INT] = 0;          // v
                sys_data.data_cfg[CFG_EST_PH_EXT] = 0;          // w
                sys_data.data_cfg[CFG_OPTODE] = 0;              // x
                sys_data.fast_mode = 1;                         // Z

                break;

            case '0':
                sys_data.data_cfg[CFG_SAMPLE_NUM] = 0;          // A
                sys_data.data_cfg[CFG_TIMEDATE] = 0;            // B
                sys_data.data_cfg[CFG_ENV_BAT_VOLT] = 0;        // C
                sys_data.data_cfg[CFG_ENV_BRD_TEMP] = 0;        // d
                sys_data.data_cfg[CFG_ENV_HUMIDITY] = 0;        //e
                sys_data.data_cfg[CFG_INT_PRESSURE] = 0;        //f
                sys_data.data_cfg[CFG_V_THERMISTOR] = 0;        //g
                sys_data.data_cfg[CFG_V_THERMISTOR_STD] = 0;    //h
                sys_data.data_cfg[CFG_V_INT_OFFSET] = 0;        //i
                sys_data.data_cfg[CFG_V_INT_OFFSET_STD] = 0;    // j
                sys_data.data_cfg[CFG_V_EXT_OFFSET] = 0;        // k
                sys_data.data_cfg[CFG_V_EXT_OFFSET_STD] = 0;    //l
                sys_data.data_cfg[CFG_V_INT] = 0;               // m
                sys_data.data_cfg[CFG_V_INT_STD] = 0;           // n
                sys_data.data_cfg[CFG_V_EXT] = 0;               // O              14   //+ Vext
                sys_data.data_cfg[CFG_V_EXT_STD] = 0;           //   P        15   // + Vext_std
                sys_data.data_cfg[CFG_V_COUNTER_ELECT] = 0;     //  Q   16   //+ Vcounter_electrode
                sys_data.data_cfg[CFG_V_COUNTER_ELECT_STD] = 0; // R  //+ Vcounter_electrode_std
                sys_data.data_cfg[CFG_I_COUNTER] = 0;           //  S         18   // + Counter_current
                sys_data.data_cfg[CFG_I_SUBSTRATE] = 0;         // T        19   //+ Substrate_current
                sys_data.data_cfg[CFG_CALC_TEMP] = 0;           // u
                sys_data.data_cfg[CFG_EST_PH_INT] = 0;          // v
                sys_data.data_cfg[CFG_EST_PH_EXT] = 0;          // w
                sys_data.fast_mode = 0;                         // Z
                break;

            case '1':
                sys_data.data_cfg[CFG_SAMPLE_NUM] = 1;          // A
                sys_data.data_cfg[CFG_TIMEDATE] = 1;            // B
                sys_data.data_cfg[CFG_ENV_BAT_VOLT] = 1;        // C
                sys_data.data_cfg[CFG_ENV_BRD_TEMP] = 1;        // d
                sys_data.data_cfg[CFG_ENV_HUMIDITY] = 1;        //e
                sys_data.data_cfg[CFG_INT_PRESSURE] = 1;        //f
                sys_data.data_cfg[CFG_V_THERMISTOR] = 1;        //g
                sys_data.data_cfg[CFG_V_THERMISTOR_STD] = 1;    //h
                sys_data.data_cfg[CFG_V_INT_OFFSET] = 1;        //i
                sys_data.data_cfg[CFG_V_INT_OFFSET_STD] = 1;    // j
                sys_data.data_cfg[CFG_V_EXT_OFFSET] = 1;        // k
                sys_data.data_cfg[CFG_V_EXT_OFFSET_STD] = 1;    //l
                sys_data.data_cfg[CFG_V_INT] = 1;               // m
                sys_data.data_cfg[CFG_V_INT_STD] = 1;           // n
                sys_data.data_cfg[CFG_V_EXT] = 1;               // O              14   //+ Vext
                sys_data.data_cfg[CFG_V_EXT_STD] = 1;           //   P        15   // + Vext_std
                sys_data.data_cfg[CFG_V_COUNTER_ELECT] = 1;     //  Q   16   //+ Vcounter_electrode
                sys_data.data_cfg[CFG_V_COUNTER_ELECT_STD] = 1; // R  //+ Vcounter_electrode_std
                sys_data.data_cfg[CFG_I_COUNTER] = 1;           //  S         18   // + Counter_current
                sys_data.data_cfg[CFG_I_SUBSTRATE] = 1;         // T        19   //+ Substrate_current
                sys_data.data_cfg[CFG_CALC_TEMP] = 1;           // u
                sys_data.data_cfg[CFG_EST_PH_INT] = 1;          // v
                sys_data.data_cfg[CFG_EST_PH_EXT] = 1;          // w
                sys_data.fast_mode = 1;                         // Z
                break;

            case '3':
                uprintf("\nfast_mode = 3    2*200msec = 400msec  trials=2, gain=1, sps=5\n");
                sys_data.fast_mode = 3;
                break;
            case '4':
                uprintf("\nfast_mode = 2    4*100msec = 400msec  trials=4, gain=1, sps=10\n");
                sys_data.fast_mode = 2;
                break;

            case 'Y':
                //break;
            case 'y':
                //break;


            case '9':
            default:
                // Write the sys_data struct into EEPROM.  Last argument ensures # of bytes is multiple of 4
                if(storeSysDataVariables())                         //if(EEPROMProgram((uint32_t*) &sys_data, 0x400, (sizeof(sys_data) + 3) & ~3))
                {
                    uprintf("\n\nError storing system data.\n");
                }
                else
                    uprintf("\n\nSystem data stored. (910) -- Press enter to bring up main menu\n");
                return;

        }

    }
}




/********************************************************************************************
 *  Configuration Menu.
 ********************************************************************************************/
void configuration(void)
{
	char input, buff[100];
	int response;
	time_t usersTime, timer;
	unsigned long temp;
	float ftemp;
    int matchFlg = 0;

	while(1)
	{
		//print out config menu
		uprintf("\n\n\nConfiguration Menu--SeaFET/SeapHOx %s", VERSION);
		uprintf("\n1 -- Set Clock");
		uprintf("\n2 -- Change File Name");
		uprintf("\n3 -- Set Deployment Parameters");
		uprintf("\n4 -- Enter pH Sensor Calibration Coefficients");
		uprintf("\n5 -- Calculate pH Sensor Calibration Coefficients");
		uprintf("\n6 -- Change Baud Rate");
		uprintf("\n7 -- Config Data Fields");
		uprintf("\n9 -- Exit to Main Menu");
		uprintf("\nEnter Selection [9]: ");

		// Get user's selection with a 5 min timeout
		UARTFlushRx();
		timer = 300 + ROM_HibernateRTCGet();

		while(1)
		{
			if( UARTRxBytesAvail() )
			{
				input = get_key();
				break;
			}

			if( timer <= ROM_HibernateRTCGet() ) sleep(IDLE, 0);
		}

		switch(input)
		{
            case 'd':
                uprintf("\ndbg_flag = 0   OFF\n");
                dbg_flag = 0;
                break;
            case 'D':
                uprintf("\ndbg_flag = 1   ON\n");
                dbg_flag = 1;
                break;
			case '1':  // Set Clock
				response = yesOrNoMenuChoice("\n\nIs time GMT? (Y/N) [N]? ", NO);
				if(response == YES) sys_data.GMT = true;
				else sys_data.GMT = false;

				usersTime = getDateAndTime();

				if(usersTime)
				{
					ROM_HibernateRTCSet(usersTime); // Set time if user entered valid time
					uprintf("\nTime now: ");
					printCurrentTime();
					if(sys_data.GMT) uprintf(" GMT");
					else uprintf(" Local");
					uprintf("\n\nNote: Daylight Savings not observed. Use GMT when this will be an issue.\n");
				}
				break;

			case '2':  //Set / Change file name
				uprintf("\nEnter data file name (no spaces, 8 characters before .txt or .xls) [%s]: ", sys_data.fileName);
				if( getUserInput(buff, 100) )
				{
					strcpy(sys_data.fileName, buff);
					uprintf("\nFile name now: %s\n", sys_data.fileName);
				}

				uprintf("\n\nEnter user initials [%s]: ", sys_data.user);

				if( getUserInput(buff, 10) )
				{
					strcpy(sys_data.user, buff);
					uprintf("\nUser initials now: %s\n", sys_data.user);
				}
				break;

			case '3':  //Set timing (query user for values, save them in EEPROM)

				// Sample period
				//response = yesOrNoMenuChoice("\n\nSample aligned to hour? (Y/N) [Y]? ", YES);
			    if(sys_data.sample_aligned == YES)  // THOM new 23Apr2019
			    {
			        response = yesOrNoMenuChoice("\n\nSample aligned to hour? (Y/N) [Y]? ", YES);
			    }
			    else
			    {
			        response = yesOrNoMenuChoice("\n\nSample aligned to hour? (Y/N) [N]? ", NO);
			    }

				if(response == YES)	sys_data.sample_aligned = true;
				else sys_data.sample_aligned = false;

				while(1)
				{
					uprintf("\n\nEnter sample period [%u] sec: ", sys_data.sampling_period);
					if(getUserInput(buff, 20))
					{
						if(sscanf(buff, "%u", &temp) == 1)
						{

						    // sample_period = 0 means POLLED MODE
						    // use COMMAND mode to keep from going into DEPLOY   THOMHERE

						    if(temp == 0)
						    {
                                uprintf("\nSample period is zero - polled mode\n");
						    }
						    //else
						    //{

                                if(sys_data.sample_aligned)		// Sample aligned to hour?
                                {
                                    //if(3600 % temp)
                                    if((3600 % temp) && (temp > 0))     // BUG Fix 6 May 2019, per request to allow sample aligned to hour in polled mode (sample period = 0) - Not sure the sense of it though since in polled mode, the poller is determining the time
                                    {
                                        uprintf("\nSample period must evenly divide hour (e.g. 5, 10, 15, 20, 30 minutes)");
                                        continue;
                                    }
                                }

                                if(temp <= 3600)		// Check if less than hour
                                {
                                    sys_data.sampling_period = temp;
                                    uprintf("Sample period now %u sec.\n\n", sys_data.sampling_period);
                                    break;
                                }
                                else
                                    {
                                    uprintf("\nEnter time less than or equal to 3600 sec");
                                    }

                                continue;
                            }
                            else break;
                        //} // if (sscanf...)
					}
					else break;
				}

				// Sample average
				if(sys_data.fast_mode >= 1)
				{
				    uprintf("\npH sample average is 10 at 20 sps (fast sample)\n");
				}
				else
				{
                    while(1)
                    {
                        uprintf("\nEnter pH sample average [%d] samples: ", sys_data.sample_average);
                        if(getUserInput(buff, 20))
                        {
                            if(sscanf(buff, "%d", &temp) == 1)
                            {
                                if(temp <= 100)
                                {
                                    sys_data.sample_average = temp;
                                    uprintf("\npH sample average now %d.\n\n", sys_data.sample_average);
                                    break;
                                }
                                else uprintf("\nEnter value less than 100");
                                continue;
                            }
                            else break;
                        }
                        else break;
                    }
				}

				// Pump on time
				while(1)
				{
					uprintf("\nEnter pump on time [%u] sec: ", sys_data.pumpon_time);
					if(getUserInput(buff, 20))
					{
						if(sscanf(buff, "%u", &temp) == 1)
						{
							if(temp <= 3600)
							{
								sys_data.pumpon_time = temp;
								uprintf("Pump on time now %u sec.\n\n", sys_data.pumpon_time);
								break;
							}
							else uprintf("\nEnter time less than 3600 sec");
							continue;
						}
						else break;
					}
					else break;
				}

				// Low battery voltage
				while(1)
					{
						sprintf(buff, "\nEnter low battery_voltage (10.5 V for SeapHOx, 5.5 V for MFET) [%.1f V]: ", sys_data.low_batt_volt);
						uprintf("%s", buff);
						if(getUserInput(buff, 20))
						{
							if(sscanf(buff, "%f", &ftemp) == 1)
							{
								if(ftemp >= 0 && ftemp <= 30)
								{
									sys_data.low_batt_volt = ftemp;
									sprintf(buff, "\nLow battery_voltage now [%.1f V]\n\n", sys_data.low_batt_volt);
									uprintf("%s", buff);
								break;
								}
								else uprintf("\nEnter voltage less than 30 V");
								continue;
							}
							else break;
						}
							else break;
					}


				// Output mode
				uprintf("\n\nOutput mode menu");
				uprintf("\n1 -- Normal  (Data only)");
				uprintf("\n2 -- Verbose (Data with prompts)");
				uprintf("\nEnter Selection [%d]: ", (int)sys_data.output);

				input = get_key();

				if(input)
				{
					switch(input)
					{
						case '1': sys_data.output = NORMAL;
						uprintf("\n\nOutput mode now: NORMAL");
							break;

						case '2': sys_data.output = VERBOSE;
						uprintf("\n\nOutput mode now: VERBOSE");
							break;
					}

				}
				break;

			float ftemp;
			case '4': //Enter pH Sensor Calibration Coefficients
				//Eo_int_25


				while(1)
				{
                    // a good default is -0.4
                    sprintf(buff, "\nEnter E0_int @25 C (ex. -0.4) [%f]: ", sys_data.Eo_int_25C);
                    uprintf("%s", buff);
                    if(getUserInput(buff, 20))
                    {
                        if(sscanf(buff, "%f", &ftemp) == 1)
                        {
                            if(ftemp >= (-2) && ftemp <= 2)
                            {
                                sys_data.Eo_int_25C = ftemp;
                                break;
                            }
                            else uprintf("Enter number between -2 and 2 (ex. -0.4)\n\n");
                            continue;
                        }
                    else break;
                    }
                    else break;
				}


				//Eo_ext_25
				while(1)
				{
                        // a good default is -1.3
                    sprintf(buff, "\nEnter E0_ext @25 C (ex. -1.3) [%f]: ", sys_data.Eo_ext_25C);
                    uprintf("%s", buff);
                    if(getUserInput(buff, 20))
                    {
                        if(sscanf(buff, "%f", &ftemp) == 1)
                        {
                            if(ftemp >= (-2) && ftemp <= 2)
                            {
                                sys_data.Eo_ext_25C = ftemp;
                                break;
                            }
                            else uprintf("Enter number between -2 and 2 (ex. -1.3)\n\n");
                            continue;
                        }
                        else break;
                        }
                    else break;
				}

				sys_data.TCOffset = 0.0;        // new THOM 29 Apr 2019, remove TCOffset per Yui

				uprintf("\n*****Calibration Coefficients Saved*****\n\n");
				break;

			case '5': //Calculate pH Sensor Calibration Coeffcients
				ph_calib();
				break;

			case '6':  // Change baud rate
			    change_baud_rate();
			    break;

            case '7':  // Config data fields (select which fields are logged and displayed)
                config_data_fields();
                break;

			case '8': // Hidden menu option to change sensor name.
				uprintf("\n\nFactory settings. Enter password: ");
				// Compare user input with password
				if( getUserInput(buff, 14) )
				{
				    uprintf("Pass: %s\n\n", buff);
				    buff[12] = 0x00;
                    if( strcmp("takeshitalab", buff)  == 0  ) // if strings are equal, strcmp returns 0
                        //      012345678901
                        matchFlg = 1;  //break;
                    buff[8] = 0x00;
					if( strcmp("martzlab", buff) == 0 )
					    matchFlg = 1;  //break;

				}
				else
				    break;

				// if bad password, no access
				if(matchFlg == 0)
				    break;

				// Sensor name
				uprintf("\n\nEnter sensor name [%s]: ", sys_data.sensor_name);
				if( getUserInput(buff, 30) )
				{
					strcpy(sys_data.sensor_name, buff);
					uprintf("Sensor name now: %s\n\n", sys_data.sensor_name);
				}

				// DuraFET serial #
				uprintf("\nEnter Durafet serial number [%s]: ", sys_data.durafet_SN);
				if( getUserInput(buff, 30) )
				{
					strcpy(sys_data.durafet_SN, buff);
					uprintf("Durafet serial number now: %s\n\n", sys_data.durafet_SN);
				}

				// Cap adapter serial #
				uprintf("\nEnter CAP adapter serial number [%s]: ", sys_data.capadap_SN);
				if( getUserInput(buff, 30) )
				{
					strcpy(sys_data.capadap_SN, buff);
					uprintf("CAP adapter serial number now: %s\n\n", sys_data.capadap_SN);
				}

				// ISE serial #
				uprintf("\nEnter ISE serial number [%s]: ", sys_data.ISE_SN);
				if( getUserInput(buff, 30) )
				{
					strcpy(sys_data.ISE_SN, buff);
					uprintf("ISE serial number now: %s\n\n", sys_data.ISE_SN);
				}

				// Microcat serial #
				uprintf("\nEnter Microcat serial number [%s]: ", sys_data.microcat_SN);
				if( getUserInput(buff, 30) )
				{
					strcpy(sys_data.microcat_SN, buff);
					uprintf("Microcat serial number now: %s\n\n", sys_data.microcat_SN);
				}

				// Pump serial #
				uprintf("\nEnter pump serial number [%s]: ", sys_data.pump_SN);
				if( getUserInput(buff, 30) )
				{
					strcpy(sys_data.pump_SN, buff);
					uprintf("Pump serial number now: %s\n\n", sys_data.pump_SN);
				}

				// Pressure sensor full scale
				while(1)
				{
					uprintf("\nEnter pressure sensor full-scale [%d] psi: ", sys_data.press_full_scale);
					if(getUserInput(buff, 20))
					{
						if(sscanf(buff, "%d", &temp) == 1)
						{
							if(temp == 100 || temp == 300)
							{
								sys_data.press_full_scale = temp;
								uprintf("\nPressure sensor full-scale now %d psi\n\n", sys_data.press_full_scale);
								break;
							}
							else uprintf("\nEnter 100 or 300");
							continue;
						}
						else break;
					}
					else break;
				}

				// pH Vint gain setting
				while(1)
				{
					uprintf("\nEnter pH Vint gain setting [%d]: ", sys_data.Vint_gain);
					if(getUserInput(buff, 20))
					{
						if(sscanf(buff, "%d", &temp) == 1)
						{
							if(temp == 1 || temp == 2 || temp == 4 || temp == 8 || temp == 16 || temp == 32)
							{
								sys_data.Vint_gain = temp;
								uprintf("\npH Vint gain now %d\n\n", sys_data.Vint_gain);
								break;
							}
							else uprintf("\nEnter 1, 2, 4, 8, 16, or 32");
							continue;
						}
						else break;
					}
					else break;
				}

				// pH Vint gain setting
				while(1)
				{
					uprintf("\nEnter pH Vint sample rate setting [%d]: ", sys_data.Vint_sps);
					if(getUserInput(buff, 20))
					{
						if(sscanf(buff, "%d", &temp) == 1)
						{
							if(temp == 5 || temp == 10 || temp == 20 || temp == 40 || temp == 80 || temp == 160
									|| temp == 320 || temp == 640 || temp == 1000 || temp == 2000)
							{
								sys_data.Vint_sps = temp;
								uprintf("\npH Vint data rate now %d sps\n\n", sys_data.Vint_sps);
								break;
							}
							else uprintf("\nEnter 5, 10, 20, 40, 80, 160, 320, 640, 1000, or 2000");
							continue;
						}
						else break;
					}
					else break;
				}

			default: //Exit
				// Write the sys_data struct into EEPROM.  Last argument ensures # of bytes is multiple of 4
			    if(storeSysDataVariables())                     //if(EEPROMProgram((uint32_t*) &sys_data, 0x400, (sizeof(sys_data) + 3) & ~3))
				{
					uprintf("\n\nError storing system data.\n");
				}
				else uprintf("\n\nSystem data stored.  -- Press enter to bring up main menu\n");
				return;
		}
	}
}



/*************************************************************************************************************************
 * Test menu.
 *************************************************************************************************************************/
void test(void)
{
	char input;
	float ADCResult, TC, ADCvolts, fVbat, fOnChipTemp, fExtTemp, fPressure;
	float ADCResult2, ADCResult3, ADCResult4, ADCResult5;
	uint32_t  uiPressure, uiHumidity, uiWater;
	int32_t charInput;
	int response;
	time_t timer;
	bool pump_on = false, AUX1_on = false, AUX2_on = false;

	uint32_t indx = 0;

	// Test menu loop
	while(1)
	{
		uprintf("\n\n\nTest Menu--SeaFET/SeapHOx %s\n", VERSION);
		uprintf("1 -- Display Battery, Internal Temp, Pressure\n");
		uprintf("2 -- Display pH Sensor Data\n");
		uprintf("3 -- Communicate with Instrument\n");
		uprintf("4 -- Pump ON/OFF\n");
		uprintf("5 -- AUX1 ON/OFF\n");
		uprintf("6 -- AUX2 ON/OFF\n");
#if BOARD_MFET >= 1
		uprintf("7 -- Internal Environment Sensors\n");
        uprintf("8 -- Test 24bit ADC and MUX - GOOD FOR BOARD BRINGUP\n");

#endif
        uprintf("O -- Test Optode, o for loop\n");
        uprintf("S -- Fast Sample once, s for loop\n");
        uprintf("T -- Get Sample once, t for loop\n");
        uprintf("U -- turn on non iso sampling in S\n");
        uprintf("B -- Bias battery voltage measurement\n");

        if(dbg_flag == 1)
        {
            uprintf("d -- Software diagnostic printf messages off\n");
        }
        else
        {
            uprintf("D -- Software diagnostic printf messages on\n");
        }


		uprintf("9 -- Exit to Main Menu\n");
		uprintf("\nEnter Selection: ");

		UARTFlushRx();
		timer = 30000 + ROM_HibernateRTCGet();

		while(1)
		{
			if( UARTRxBytesAvail() )
			{
				input = get_key();
				break;
			}

			if( timer <= ROM_HibernateRTCGet() ) sleep(IDLE, 0);
		}

		switch(input)
		{
		    case 'B':
		    case 'b':
		        print_bias_volt_iso();
		        break;

            case 'h':
            case 'H':
                print_header();     // defd in system.c
                break;
            case 'O':
                //test_optode();
                break;
            case 'o':
                // loop
                break;

            case 's':
                uprintf("\ncalling fast_sample(1), hit key to stop\n");
                while(1)
                {
                    profile_toggle(1);
                    fast_sample(1);     // =1 is 1200msec (reducing the 800msec delay to 100msec)
                    //profile_off(1);

                    if( UARTRxBytesAvail() )  //if( kbhit() )
                    {
                        input = get_key();

                        if((input >= '0') && (input <= '9'))
                        {
                            uprintf("profileTarget = %c\n", input);
                            profileTarget = (int)(input & 0x0f);
                        }
                        else
                        {
                            uprintf("break from while s\n");
                            break;
                        }
                    }
                }
                break;
            case 'S':
                uprintf("\ncalling fast_sample(1)\n");
                profile_on(1);       // DEBUG profiling with scope
                fast_sample(1);     // =1 is 1200msec (reducing the 800msec delay to 100msec)
                profile_off(1);
                break;


            case 't':
                uprintf("\ncalling get_sample(1) loop, hit key to stop\n");
                while(1)
                {
                    profile_toggle(1);
                    get_sample(1);     // =1 is 1200msec (reducing the 800msec delay to 100msec)
                    //profile_off(1);

                    if( UARTRxBytesAvail() )  //if( kbhit() )
                    {
                        input = get_key();

                        if((input >= '0') && (input <= '9'))
                        {
                            uprintf("profileTarget = %c\n", input);
                            profileTarget = (int)(input & 0x0f);
                        }
                        else
                        {
                            uprintf("break from while s\n");
                            break;
                        }
                    }
                }
                break;
            case 'T':
                uprintf("\ncalling fast_sample(1)\n");
                profile_on(1);       // DEBUG profiling with scope
                get_sample(1);     // =1 is 1200msec (reducing the 800msec delay to 100msec)
                profile_off(1);
                break;


            case 'u':
                uprintf("\ncalling fast_sample(1), then get_sample(1) in a loop loop, hit key to stop\n");
                while(1)
                {
                    profile_toggle(1);
                    fast_sample(1);     // =1 is 1200msec (reducing the 800msec delay to 100msec)
                    profile_toggle(1);
                    get_sample(1);     // =1 is 1200msec (reducing the 800msec delay to 100msec)
                    //profile_off(1);

                    if( UARTRxBytesAvail() )  //if( kbhit() )
                    {
                        input = get_key();

                        if((input >= '0') && (input <= '9'))
                        {
                            uprintf("profileTarget = %c\n", input);
                            profileTarget = (int)(input & 0x0f);
                        }
                        else
                        {
                            uprintf("break from while s\n");
                            break;
                        }
                    }
                }
                break;
            case 'U':
                uprintf("\ncalling fast_sample(1) then get_sample(1)\n");
                profile_toggle(1);
                fast_sample(1);     // =1 is 1200msec (reducing the 800msec delay to 100msec)
                profile_toggle(1);       // DEBUG profiling with scope
                get_sample(1);     // =1 is 1200msec (reducing the 800msec delay to 100msec)
                profile_toggle(1);
                break;

            case 'd':
                dbg_flag = 0;
                uprintf("\n\nSoftware diagnostic printf messages off (dbg_flag = 0)\n\n");
                break;

            case 'D':
                dbg_flag = 1;
                uprintf("\n\nSoftware diagnostic printf messages on (dbg_flag = 1)\n\n");
                break;


			case '1': //Read Voltages from ADC on Non-isolated side.
				openADS1248_noniso();
				//pressureOn();			// Turn on 5V to pressure sensor

				while(!UARTRxBytesAvail())
				{

					// TM 6May2019 - format for scrolling columns (THOM  what is ADCvolts??)
                    ADCvolts = pollADS1248_noniso(3, 7, 1);
                    uprintf("Battery = %.3f V,  Controller Temp = %.3f C,  Raw Voltage = %.3f V\r\n", batt_volt(), controller_temp(), ADCvolts);

                    ROM_SysCtlDelay(MILLISECOND*3000);

				}

				//pressureOff(); // removed 16May2019
				closeADS1248_noniso();
				break;

			case '2': //Read Voltages from the isolated ADC

				openADS1248_iso();          // 52 msec

				ROM_SysCtlDelay(MILLISECOND * 800);	// Let electronics settle (was 1000)

				while(!UARTRxBytesAvail())  // Code faults into 'loader_exit' on this statement
				{

                    //get Vtherm voltage
                    ADCResult = pollADS1248_iso(0, 6, sys_data.sample_average, 1, 20);      // Chan 0-6, trials = 1, gain = user, sps = 5 Hz (changed to 20 6May2019 TM per YT)
                    TC = DuraFET_temp(ADCResult,0);

                    //get Vint voltage
                    ADCResult2 = pollADS1248_iso(1, 6, sys_data.sample_average, sys_data.Vint_gain, sys_data.Vint_sps);

                    //get Aux_Ref voltage
                    ADCResult3 = pollADS1248_iso(4, 6, sys_data.sample_average, 1, 20);   //sps changed from 5 to 20 6May2019 TM

                    //get voltage b/w Ik+ Ik-
                    ADCResult4 = pollADS1248_iso(3, 2, 1, 1, 20);                // Chan 3-2, trials = 1, gain = 1, sps = 5 Hz  //sps changed from 5 to 20 6May2019 TM

                    //get Ib+ voltage
                    ADCResult5 = pollADS1248_iso(7, 6, 1, 1, 20);                // Chan 7-6, trials = 1, gain = 1, sps = 5 Hz  //sps changed from 5 to 20 6May2019 TM


                    uprintf("\nVtherm= %.6f V, TC= %2.6f, Vint= %.6f V, Est. pHint= %2.6f, Aux_Ref= %.6f V, Est.(S=35) pHext= %2.6f, IsoBat= %.6f V, Ik+ Ik- Volt= %.6f V, Ib+=%.6f V \r\n",  ADCResult, TC, ADCResult2, calc_pHint(ADCResult2, TC), ADCResult3, calc_pHext(ADCResult3, TC, 35), batt_volt_iso(), ADCResult4, ADCResult5);

					ROM_SysCtlDelay(MILLISECOND*3000);
				}
				//close the isolated ADC
				closeADS1248_iso();
				break;

			case '3': //Communicate with Instruments
				while(1)
				{
					uprintf("\n\n\nMicroCAT and Optode Peripheral Communication Menu\n");
					uprintf("1 -- MicroCAT\n");
					uprintf("2 -- Optode\n");
					uprintf("3 -- AUX 1\n");
					uprintf("4 -- AUX 2\n");
					uprintf("9 -- Exit\n");
					uprintf("\nEnter peripheral device selection[9]: ");

					input = get_key();
					switch(input)
					{
						case '1':  // MicroCAT
							UARTEchoSet(false);	// Disable console echo for MicroCAT
							uprintf("\n\n*Press CTRL-X to stop communicating with the MicroCAT.*\n\n");

							//set up the MicroCAT
							openMicroCAT();

							while(1)
							{
								//if MicroCAT sent anything, print it out on UART1 (the desktop)
								if( MicroCAT_UARTRxBytesAvail() )
								{
									uprintf( "%c", MicroCAT_UARTgetc() );
								}

								//if user types anything, send it to the MicroCAT--exit on CTRL-X
								if(UARTRxBytesAvail())
								{
									charInput = UARTgetc();

									if(charInput == 24)
									{
										break;
									}

									MicroCAT_putc(charInput);
								}
							}


							//close up the MicroCAT
							closeMicroCAT();
							UARTEchoSet(true);	// Enable console echo
							break;


						case '2': // Optode

						    uprintf("\nNote: there is a bug with the serial ring buffer code / isr for optode \n\n");
						    uprintf("\n\nCommand procedure to setup Optode for numeric output:\n\n");
						    uprintf("set passkey(1)\n");
						    uprintf("set mode(smart sensor terminal)\n");
						    uprintf("set enable polled mode(yes)\n");
						    uprintf("save\n");

						    uprintf("set passkey(1)\n");
						    uprintf("set enable text(no)\n");
						    uprintf("save\n");
                            uprintf("do sample\n");
                            uprintf("\nThis should return a sample: 5730    1565    208.411 98.928  26.187  29.670  29.670  37.411  7.741   739.9   714.3   43.2 \n\n");

							uprintf("\n\n*Press CTRL-X to stop communicating with the Optode.*\n\n");

							//set up the optode
							openOptode();               // power on optode
					        ROM_SysCtlDelay(500);       //500 is a guess
                            //Optode_UARTwrite("do sample\r\n",12 );
                            //ROM_SysCtlDelay(MILLISECOND*2000);

							while(1)
							{
								//if Optode sent anything, print it out on UART1 (the desktop)
								if( Optode_UARTRxBytesAvail() )
								{
									uprintf( "%c", Optode_UARTgetc() );
								}

								//if user types anything, send it to the Optode--exit on CTRL-X
								if(UARTRxBytesAvail())
								{
									charInput = UARTgetc();

									if(charInput == 13)		// If user hit carriage return, add a line feed
									{
										Optode_putc(charInput);	// CR
										Optode_putc(10);		// LF
									}
									else if(charInput == 24) break;
									else( Optode_putc(charInput) );
								}
							}

							closeOptode();	// Close up the Optode
							break;

						case '3': // AUX 1
							uprintf("\n\n*Press CTRL-X to stop communicating with AUX 1.*\n\n");
							UARTFlushTx(0);
							UARTEchoSet(0);		// Disable echo. Set to 1 to enable
							Open_AUX1();

							while(1)
							{
								//if AUX1 sent anything, print it out on UART1 (the desktop)
								if(ROM_UARTCharsAvail(UART2_BASE))
								{
									uprintf("%c", ROM_UARTCharGet(UART2_BASE));
								}

								//if user types anything, send it to the AUX1--exit on CTRL-X
								if(UARTRxBytesAvail())
								{
									charInput = UARTgetc();

									if(charInput == 24)
									{
										break;
									}

									ROM_UARTCharPut(UART2_BASE, charInput);
								}
							}

							Close_AUX1();
							UARTEchoSet(1);
							break;

						case '4': // AUX 2
							uprintf("\n\n*Press CTRL-X to stop communicating with AUX 2.*\n\n");
							UARTFlushTx(0);
							UARTEchoSet(0);		// Disable echo. Set to 1 to enable
							Open_AUX2();

							while(1)
							{
								//if AUX1 sent anything, print it out on UART1 (the desktop)
								if(ROM_UARTCharsAvail(UART5_BASE))
								{
									uprintf("%c", ROM_UARTCharGet(UART5_BASE));
								}

								//if user types anything, send it to the AUX1--exit on CTRL-X
								if(UARTRxBytesAvail())
								{
									charInput = UARTgetc();

									if(charInput == 24)
									{
										break;
									}

									ROM_UARTCharPut(UART5_BASE, charInput);
								}
							}

							Close_AUX2();
							UARTEchoSet(1);
							break;

						default: //Exit
							return;
					}
				}

			case '4':  // Pump ON/OFF
				if(pump_on)
				{
					pump_off();
					pump_on = false;
					uprintf("\n\nPump off\n");
				}
				else
				{
					response = yesOrNoMenuChoice("\n\nIs pump immersed in water? (Y/N) [N]? ", NO);
					if(response == YES)
					{
						pump_on();
						pump_on = true;
						uprintf("\n\nPump on...\n");
					}
				}
				break;

			case '5':  // AUX1 ON/OFF
				if(AUX1_on)
				{
					AUX1_off();
					AUX1_on = false;
					uprintf("\n\nAUX1 off\n");
				}
				else
				{
					AUX1_on();
					AUX1_on = true;
					uprintf("\n\nAUX1 on...\n");
				}
				break;

			case '6':  // AUX2 ON/OFF
				if(AUX2_on)
				{
					AUX2_off();
					AUX2_on = false;
					uprintf("\n\nAUX2 off\n");
				}
				else
				{
					AUX2_on();
					AUX2_on = true;
					uprintf("\n\nAUX2 on...\n");
				}
				break;
#if BOARD_MFET >= 1
			case '7':
			    // THOMz world
			    uprintf("\n\n\n");

                indx = 0;
                ROM_GPIOPinWrite(GPIO_PORTM_BASE, GPIO_PIN_7, 0xFF);    // Turn on Load switch for ENV monitoring
                ROM_GPIOPinWrite(GPIO_PORTM_BASE, GPIO_PIN_6, 0xFF);   // Turn on VBat monitoring

                ROM_GPIOPinWrite(GPIO_PORTK_BASE, GPIO_PIN_2, 0xFF);        // Iso-power On
                uprintf("iso power on\n");

                adc_onchip_init();
                ROM_SysCtlDelay(MILLISECOND * 100);          // 10ms gives 5.06v (12.02v input), 20ms gives 7.88, 50 ms gives 11.07, 70 ms gives 11.65, 100 ms gives 11.93
                while(1)
                {
                    //float ADCResult, TC, ADCvolts, fVbat, fOnChipTemp, fExtTemp;
                    //uint32_t  TempValueC, uiPressure, uiHumidity, uiWater;

                    read_all_adc();

                    fVbat = (float)(adc_data[0]*100);
                    fVbat /= 18687.707;

                    // onchip temperature (formulae from TI example code)
                    //TempValueC = (uint32_t)(147.5 - ((75.0*3.3 *(float)adc_data[7])) / 4096.0);
                    fOnChipTemp = (147.5 - ((75.0*3.3 *(float)adc_data[7])) / 4096.0);

                    // LM60 temperature sensor - formula from datasheet / schematic (good job Scott Jensen)
                    // Vout = (+6.25 mV/C * T) + 424mV   =>  T = ((ADCcnt * 0.80566) - 424) / 6.25
                    fExtTemp = ((((float)adc_data[4])*0.80566) - 424) / 6.25;

                    // Water sensor - convert to percent
                    uiWater = (adc_data[3] * 100) / 2596;    // NOTE: Water voltage adc cnts is 2622 when pulled to 3.3v  (measured at 2.1092v on test point with agilent u1272a meter)
                    if(uiWater > 100)
                        uiWater = 100;

                    // Humidity
                    uiHumidity = (adc_data[2] * 100) / 3284;

                    // Pressure
                    uiPressure = adc_data[1];
                    fPressure = (float)uiPressure;   //2020x = 14.70psi     (From scotts schematic0.33V = 0psia, 3.0V = 30psia)
                    fPressure *= 0.0072772;

                    //uprintf("Bat = %6.2fV VBAT=%u VPRESS=%3u  VHUM=%3u  VWATER=%3u   VXTEMP=%3u   VBAT=%3u, VBAT=%u, VTEMP=%u  i=%u\r", fVbat, adc_data[0], adc_data[1], adc_data[2], adc_data[3], adc_data[4], adc_data[5], adc_data[6], TempValueC, indx++);
                    uprintf("Bat = %6.2fV Pressure = %5.1f  Humidity = %3u  Water = %3u  Temperature = %5.1fC (%4u)   ChipTemp = %5.1fC  i=%u\r", fVbat, fPressure, uiHumidity, uiWater, fExtTemp, adc_data[4], fOnChipTemp, indx++);

                    ROM_SysCtlDelay(MILLISECOND * 500);

                    if( UARTRxBytesAvail() )
                    {
                        input = get_key();
                        break;    // break from while(1)
                    }
                }

                ROM_GPIOPinWrite(GPIO_PORTM_BASE, GPIO_PIN_6, 0x00);   // Turn off VBat monitoring
                ROM_GPIOPinWrite(GPIO_PORTK_BASE, GPIO_PIN_2, 0x00);        // Iso-power Off
                uprintf("iso power off, vbat monitoring off\n");
			    break;

			case '8':
			    test_24bit_adc_mux();
			    break;
#endif   // if MFET==1

			default: //Exit
				uprintf("\nPress enter to bring up main menu\n");
				return;

		}
	}
}


int test_sampling_mcap(float extRefOff, float intRefOff, float extRefV, float intRefV, float cntrC, float cntrV, float substCur, float substV, float thermistor)
{
    float delta, ADCResult;
    int sampleCnt;
    int error;

    error = 0;
    sampleCnt = 1;

    //   Date Time,    Ext Ref Off, Int Ref Off, Ext Ref V, Int Ref V, CntrE Cur, CntrE Volt, Subst Cur, Subst Vol, Therm
    //04/20/18 19:00:24, -0.326934, -0.326969, 0.670350, 0.670312, 0.326919, -0.670372, -0.670333, -0.997410


    // Date Time,
    printCurrentTime();

    uprintf(", ");

    delta = 0.0200;

    //Ext Ref Off,
    ADS1248_gpio_ADG1609_mux(0);
    ROM_SysCtlDelay(MILLISECOND * 10);      // 10msec settling for MUX analog
    ADCResult = pollADS1248_iso(1, 5, sampleCnt, 1, 20);       // Chan +1 -5, trials = 1, gain = user, sps = 5 Hz
    uprintf(" %.6f, ", ADCResult); // Ext Ref with Offset
    if((ADCResult > (extRefOff+delta))  || (ADCResult < (extRefOff-delta)))
    {
        uprintf(" Err ");
        error++;
    }

    //Int Ref Off,
    ADS1248_gpio_ADG1609_mux(3);
    ROM_SysCtlDelay(MILLISECOND * 10);      // 10msec settling for MUX analog
    ADCResult = pollADS1248_iso(1, 5, sampleCnt, 1, 20);       // Chan +1 -5, trials = 1, gain = user, sps = 5 Hz
    uprintf(" %.6f, ", ADCResult); // Int Ref with Offset  // uprintf("Int Ref Offset = %.6f V,  Samp = %04u,  Time = %06lu \r\n", ADCResult, indx++, sampTime/100L);
    if((ADCResult > (intRefOff+delta))  || (ADCResult < (intRefOff-delta)))
    {
        uprintf(" Err ");
        error++;
    }


    //Ext Ref V,
    ADS1248_gpio_ADG1609_mux(0);
    ROM_SysCtlDelay(MILLISECOND * 10);      // 10msec settling for MUX analog
    ADCResult = pollADS1248_iso(1, 6, sampleCnt, 1, 5);       // Chan +1 -6, trials = 1, gain = user, sps = 5 Hz
    uprintf(" %.6f, ", ADCResult);       // Ext Ref Voltage
    if((ADCResult > (extRefV+delta))  || (ADCResult < (extRefV-delta)))
    {
        uprintf(" Err ");
        error++;
    }

    // Int Ref V,
    ADS1248_gpio_ADG1609_mux(3);
    ROM_SysCtlDelay(MILLISECOND * 10);      // 10msec settling for MUX analog
    ADCResult = pollADS1248_iso(1, 6, sampleCnt, 1, 5);       // Chan +1 -6, trials = 1, gain = user, sps = 5 Hz
    uprintf(" %.6f, ", ADCResult);       // Int Ref Voltage
    if((ADCResult > (intRefV+delta))  || (ADCResult < (intRefV-delta)))
    {
        uprintf(" Err ");
        error++;
    }


    //CntrE Cur,
    ADS1248_gpio_ADG1609_mux(1);
    ROM_SysCtlDelay(MILLISECOND * 10);      // 10msec settling for MUX analog
    ADCResult = pollADS1248_iso(1, 5, sampleCnt, 4, 5);       // Chan +5 -1, trials = 1, gain = user, sps = 5 Hz
    uprintf(" %.6f, ", ADCResult);       // Counter Electrode Current
    if((ADCResult > (cntrC+delta))  || (ADCResult < (cntrC-delta)))
    {
        uprintf(" Err ");
        error++;
    }


    // CntrE Volt,
    ADS1248_gpio_ADG1609_mux(1);
    ROM_SysCtlDelay(MILLISECOND * 10);      // 10msec settling for MUX analog
    ADCResult = pollADS1248_iso(1, 6, sampleCnt, 4, 5);       // Chan +5 -1, trials = 1, gain = user, sps = 5 Hz
    uprintf(" %.6f, ", ADCResult);       // Counter Electrode Voltage
    if((ADCResult > (cntrV+delta))  || (ADCResult < (cntrV-delta)))
    {
        uprintf(" Err ");
        error++;
    }

    // Subst Cur,
    ADS1248_gpio_ADG1609_mux(2);
    ROM_SysCtlDelay(MILLISECOND * 10);      // 10msec settling for MUX analog
    ADCResult = pollADS1248_iso(1, 6, sampleCnt, 1, 5);       // Chan +5 -1, trials = 1, gain = user, sps = 5 Hz
    uprintf(" %.6f, ", ADCResult);       // Substrate Current
    if((ADCResult > (substCur+delta))  || (ADCResult < (substCur-delta)))
    {
        uprintf(" Err ");
        error++;
    }

    // Subst Vol,
    ADS1248_gpio_ADG1609_mux(2);
    ROM_SysCtlDelay(MILLISECOND * 10);      // 10msec settling for MUX analog
    ADCResult = pollADS1248_iso(5, 6, sampleCnt, 1, 5);       // Chan +5 -1, trials = 1, gain = user, sps = 5 Hz
    uprintf(" %.6f, ", ADCResult);       // Substrate Voltage
    if((ADCResult > (substV+delta))  || (ADCResult < (substV-delta)))
    {
        uprintf(" Err ");
        error++;
    }

    // Thermistor
    ADS1248_gpio_ADG1609_mux(0);        // Not necessary, but consistent
    ROM_SysCtlDelay(MILLISECOND * 10);      // 10msec settling for MUX analog
    ADCResult = pollADS1248_iso(0, 6, sampleCnt, 1, 5);       // Chan +5 -1, trials = 1, gain = user, sps = 5 Hz
    uprintf(" %.6f", ADCResult);       // Substrate Voltage
    if((ADCResult > (thermistor+delta))  || (ADCResult < (thermistor-delta)))
    {
        uprintf(" Err ");
        error++;
    }

    if(error > 0)
    {
        uprintf("  ERROR count = %d  ", error);
    }
    uprintf("\n");

    return(error);
}

void test_24bit_adc_mux(void)
{
    char input;
    float ADCResult;
    uint32_t indx = 0;
    time_t timer;
    int sampleCnt;
    unsigned long sampTime;
    unsigned long nextTime;
    unsigned long sampDelay;

    uprintf("\nOpen isolated ADS1248 and ADG1609 mux\n\n");
    ROM_SysCtlDelay(MILLISECOND * 100);
    //profile_on(1);      // THOM debug
    openADS1248_iso();      // 22msec
    //profile_off(1);

    ADS1248_gpio_init();    // defd in ADS1248_iso.c

    //ROM_SysCtlDelay(MILLISECOND * 100);

    sampleCnt = 10;
    sampDelay = 200L;   // 500 is 5 seconds using 10ms tick

    // Test menu loop
    while(1)
    {
        uprintf("\n\n\nTest pH (24bit ADC Mux) Menu\n");
        uprintf("0 -- Ext Ref with Offset\n");
        uprintf("1 -- Int Ref with Offset\n");
        uprintf("2 -- Ext Ref Voltage\n");          // Counter A and Counter B are current measurement Counter Electrode
        uprintf("3 -- Int Ref Voltage\n");
        uprintf("4 -- Counter Electrode Current\n");
        uprintf("5 -- Counter Electrode Voltage\n");
        uprintf("6 -- Substrate Current\n");
        uprintf("7 -- Substrate Voltage\n");
        uprintf("8 -- Thermistor ISFET Temperature\n");
        uprintf("S -- Sample all channels (0-8)\n");
        uprintf("X -- MCAP sample test (delta 0.0003), assumes Jensonian Analog Board\n");
        uprintf("9 -- Exit to Main Menu\n");
        uprintf("\nEnter Selection: ");



        UARTFlushRx();
        timer = 30000 + ROM_HibernateRTCGet();

        while(1)
        {
            if( UARTRxBytesAvail() )
            {
                input = get_key();
                break;
            }

            if( timer <= ROM_HibernateRTCGet() ) sleep(IDLE, 0);
        }

        switch(input)
        {

            case 'a':
                uprintf("mux = 00\n");
                ADS1248_gpio_ADG1609_mux(0);
                break;
            case 'b':
                uprintf("mux = 01\n");
                ADS1248_gpio_ADG1609_mux(1);
                break;
            case 'c':
                uprintf("mux = 10\n");
                ADS1248_gpio_ADG1609_mux(2);
                break;
            case 'd':
                uprintf("mux = 11\n");
                ADS1248_gpio_ADG1609_mux(3);
                break;
            case 'e':
                ADS1248_gpio2(0);
                break;
            case 'E':
                ADS1248_gpio2(1);

                break;

            case 'S':
            case 's':
                sampDelay = 500L;
                //   Date Time,    Ext Ref Off, Int Ref Off, Ext Ref V, Int Ref V, CntrE Cur, CntrE Volt, Subst Cur, Subst Vol, Therm
                //04/20/18 19:00:24, -0.326934, -0.326969, 0.670350, 0.670312, 0.326919, -0.670372, -0.670333, -0.997410

                uprintf("\n\n    Date Time,   Ext Ref Off, Int Ref Off, Ext Ref V, Int Ref V, CntrE Cur, CntrE Volt,  Subst Cur,  Subst Vol,  Thermistor\n");

                indx = 0;
                Timer_10ms(TRUE);       // reset 10msec tick count
                sampleCnt = 1;
                sampTime = 0L;
                nextTime = 0L;
                while(1)
                {
                    sampTime = Timer_10ms(FALSE);
                    if(sampTime >= nextTime)
                    {
                        nextTime = sampTime + sampDelay;

                        // Date Time,
                        printCurrentTime();

                        uprintf(", ");

                        //Ext Ref Off,
                        ADS1248_gpio_ADG1609_mux(0);
                        ROM_SysCtlDelay(MILLISECOND * 10);      // 10msec settling for MUX analog
                        ADCResult = pollADS1248_iso(1, 5, sampleCnt, 1, 20);       // Chan +1 -5, trials = 1, gain = user, sps = 5 Hz
                        uprintf(" %.6f, ", ADCResult); // Ext Ref with Offset

                        //Int Ref Off,
                        ADS1248_gpio_ADG1609_mux(3);
                        ROM_SysCtlDelay(MILLISECOND * 10);      // 10msec settling for MUX analog
                        ADCResult = pollADS1248_iso(1, 5, sampleCnt, 1, 20);       // Chan +1 -5, trials = 1, gain = user, sps = 5 Hz
                        uprintf(" %.6f, ", ADCResult); // Int Ref with Offset  // uprintf("Int Ref Offset = %.6f V,  Samp = %04u,  Time = %06lu \r\n", ADCResult, indx++, sampTime/100L);

                        //Ext Ref V,
                        ADS1248_gpio_ADG1609_mux(0);
                        ROM_SysCtlDelay(MILLISECOND * 10);      // 10msec settling for MUX analog
                        ADCResult = pollADS1248_iso(1, 6, sampleCnt, 1, 5);       // Chan +1 -6, trials = 1, gain = user, sps = 5 Hz
                        uprintf(" %.6f, ", ADCResult);       // Ext Ref Voltage

                        // Int Ref V,
                        ADS1248_gpio_ADG1609_mux(3);
                        ROM_SysCtlDelay(MILLISECOND * 10);      // 10msec settling for MUX analog
                        ADCResult = pollADS1248_iso(1, 6, sampleCnt, 1, 5);       // Chan +1 -6, trials = 1, gain = user, sps = 5 Hz
                        uprintf(" %.6f, ", ADCResult);       // Int Ref Voltage

                        //CntrE Cur,
                        ADS1248_gpio_ADG1609_mux(1);
                        ROM_SysCtlDelay(MILLISECOND * 10);      // 10msec settling for MUX analog
                        ADCResult = pollADS1248_iso(1, 5, sampleCnt, 1, 5);       // Chan +5 -1, trials = 1, gain = user, sps = 5 Hz
                        uprintf(" %.6f, ", ADCResult);       // Counter Electrode Current

                        // CntrE Volt,
                        ADS1248_gpio_ADG1609_mux(1);
                        ROM_SysCtlDelay(MILLISECOND * 10);      // 10msec settling for MUX analog
                        ADCResult = pollADS1248_iso(1, 6, sampleCnt, 1, 5);       // Chan +5 -1, trials = 1, gain = user, sps = 5 Hz
                        uprintf(" %.6f, ", ADCResult);       // Counter Electrode Voltage

                        // Subst Cur,
                        ADS1248_gpio_ADG1609_mux(2);
                        ROM_SysCtlDelay(MILLISECOND * 10);      // 10msec settling for MUX analog
                        ADCResult = pollADS1248_iso(1, 6, sampleCnt, 1, 5);       // Chan +5 -1, trials = 1, gain = user, sps = 5 Hz
                        uprintf(" %.6f, ", ADCResult);       // Substrate Current

                        // Subst Vol,
                        ADS1248_gpio_ADG1609_mux(2);
                        ROM_SysCtlDelay(MILLISECOND * 10);      // 10msec settling for MUX analog
                        ADCResult = pollADS1248_iso(5, 6, sampleCnt, 1, 5);       // Chan +5 -1, trials = 1, gain = user, sps = 5 Hz
                        uprintf(" %.6f, ", ADCResult);       // Substrate Voltage

                        // Thermistor
                        ADS1248_gpio_ADG1609_mux(0);        // Not necessary, but consistent
                        ROM_SysCtlDelay(MILLISECOND * 10);      // 10msec settling for MUX analog
                        ADCResult = pollADS1248_iso(0, 6, sampleCnt, 1, 5);       // Chan +5 -1, trials = 1, gain = user, sps = 5 Hz
                        uprintf(" %.6f", ADCResult);       // Substrate Voltage

                        uprintf("\n");


                    }

                    if( UARTRxBytesAvail() )
                    {
                        input = get_key();
                        break;    // break from while(1)
                    }
                }
                break;


            case 'X':
            case 'x':

                //Date Time,   Ext Ref Off, Int Ref Off, Ext Ref V, Int Ref V, CntrE Cur, CntrE Volt,  Subst Cur,  Subst Vol,  Thermistor
            //09/19/19 12:04:16,  -0.067811,  0.132143,  -0.798702,  -0.598748,  0.291080,  -0.501614,  -0.399307,  0.000322,  1.000455
            //09/19/19 12:04:21,  -0.067814,  0.132146,  -0.798713,  -0.598748,  0.291105,  -0.501616,  -0.399309,  0.000326,  1.000459
                sampDelay = 500L;
                uprintf("\n\n    Date Time,   Ext Ref Off, Int Ref Off, Ext Ref V, Int Ref V, CntrE Cur, CntrE Volt,  Subst Cur,  Subst Vol,  Thermistor\n");

                indx = 0;
                Timer_10ms(TRUE);       // reset 10msec tick count
                sampleCnt = 1;
                sampTime = 0L;
                nextTime = 0L;
                while(1)
                {
                    sampTime = Timer_10ms(FALSE);
                    if(sampTime >= nextTime)
                    {
                        nextTime = sampTime + sampDelay;
                        test_sampling_mcap(-0.067814,  0.132146,  -0.798713,  -0.598748,  0.290849,  -0.501616,  -0.399309,  0.000326,  1.000159);
                    }


                    if( UARTRxBytesAvail() )
                    {
                        input = get_key();
                        break;    // break from while(1)
                    }
                }
                break;


            case '0':
                sampDelay = 200L;
                uprintf("0 -- Ext Ref with Offset,  Mux = 00,  AIN1+ AIN5-\n");
                ADS1248_gpio_ADG1609_mux(0);
                indx = 0;
                Timer_10ms(TRUE);       // reset 10msec tick count
                sampleCnt = 1;
                sampTime = 0L;
                nextTime = 0L;
                while(1)
                {
                    sampTime = Timer_10ms(FALSE);
                    if(sampTime >= nextTime)
                    {
                        nextTime = sampTime + sampDelay;
                        ADCResult = pollADS1248_iso(1, 5, sampleCnt, 1, 5);       // Chan +1 -5, trials = 1, gain = user, sps = 5 Hz
                        uprintf("Ext Ref Offset = %.6f V,  Samp = %04u,  Time = %06lu\r\n", ADCResult, indx++, sampTime/100L);
                    }

                    if( UARTRxBytesAvail() )
                    {
                        input = get_key();
                        break;    // break from while(1)
                    }
                }
                break;


            case '1':
                uprintf("1 -- Int Ref with Offset, Mux = 11,  AIN1+ AIN5-\n");
                ADS1248_gpio_ADG1609_mux(3);
                indx = 0;
                Timer_10ms(TRUE);       // reset 10msec tick count
                sampleCnt = 1;
                sampTime = 0L;
                nextTime = 0L;
                while(1)
                {
                    sampTime = Timer_10ms(FALSE);
                    if(sampTime >= nextTime)
                    {
                        nextTime = sampTime + sampDelay;
                        ADCResult = pollADS1248_iso(1, 5, sampleCnt, 1, 5);       // Chan +1 -5, trials = 1, gain = user, sps = 5 Hz
                        uprintf("Int Ref Offset = %.6f V,  Samp = %04u,  Time = %06lu \r\n", ADCResult, indx++, sampTime/100L);
                    }
                    if( UARTRxBytesAvail() )
                    {
                        input = get_key();
                        break;    // break from while(1)
                    }
                }
                break;

            case '2':
                uprintf("2 -- Ext Ref Voltage, Mux = 00,  AIN1+ AIN6-\n");
                ADS1248_gpio_ADG1609_mux(0);
                indx = 0;
                Timer_10ms(TRUE);       // reset 10msec tick count
                sampleCnt = 1;
                sampTime = 0L;
                nextTime = 0L;
                while(1)
                {
                    sampTime = Timer_10ms(FALSE);
                    if(sampTime >= nextTime)
                    {
                        nextTime = sampTime + sampDelay;
                        ADCResult = pollADS1248_iso(1, 6, sampleCnt, 1, 5);       // Chan +1 -6, trials = 1, gain = user, sps = 5 Hz
                        uprintf("Ext Ref = %.6f V,  Samp = %04u,  Time = %06lu \r\n", ADCResult, indx++, sampTime/100L);
                    }
                    if( UARTRxBytesAvail() )
                    {
                        input = get_key();
                        break;    // break from while(1)
                    }
                }
                break;


            case '3':
                uprintf("3 -- Int Ref Voltage, Mux = 11,  AIN1+ AIN6-\n");
                ADS1248_gpio_ADG1609_mux(3);
                indx = 0;
                Timer_10ms(TRUE);       // reset 10msec tick count
                sampleCnt = 10;
                sampTime = 0L;
                nextTime = 0L;
                while(1)
                {
                    sampTime = Timer_10ms(FALSE);
                    if(sampTime >= nextTime)
                    {
                        // Step function and sample rate testing
                        nextTime = sampTime + sampDelay;
                        ADCResult = pollADS1248_iso(1, 6, sampleCnt, 1, 5);       // Chan +1 -6, trials = 1, gain = user, sps = 5 Hz
                        uprintf("Int Ref = %.6f V, Std = %.6f,  Samp = %04u,  Time = %06lu  5Hz\r\n", ADCResult, sys_data.AD24_std, indx++, sampTime/100L);

                        ADCResult = pollADS1248_iso(1, 6, sampleCnt*4, 1, 20);       // Chan +1 -6, trials = 1, gain = user, sps = 5 Hz
                        uprintf("Int Ref = %.6f V, Std = %.6f,  Samp = %04u,  Time = %06lu  20Hz\r\n", ADCResult, sys_data.AD24_std, indx++, sampTime/100L);
                    }
                    if( UARTRxBytesAvail() )
                    {
                        input = get_key();
                        break;    // break from while(1)
                    }
                }
                break;

            case '4':
                uprintf("4 -- Counter Electrode Current, Mux = 01,  AIN1+ AIN5-\n");
                ADS1248_gpio_ADG1609_mux(1);
                indx = 0;
                Timer_10ms(TRUE);       // reset 10msec tick count
                sampleCnt = 1;
                sampTime = 0L;
                nextTime = 0L;
                while(1)
                {
                    sampTime = Timer_10ms(FALSE);
                    if(sampTime >= nextTime)
                    {
                        nextTime = sampTime + sampDelay;
                        ADCResult = pollADS1248_iso(1, 5, sampleCnt, 1, 5);       // Chan +5 -1, trials = 1, gain = user, sps = 5 Hz
                        uprintf("Counter Electrode Current = %.6f,  Samp = %04u,  Time = %06lu \r\n", ADCResult, indx++, sampTime/100L);
                    }
                    if( UARTRxBytesAvail() )
                    {
                        input = get_key();
                        break;    // break from while(1)
                    }
                }
                break;

            case '5':
                uprintf("5 -- Counter Electrode Voltage, Mux = 01,  AIN1+ AIN6-\n");
                ADS1248_gpio_ADG1609_mux(1);
                indx = 0;
                Timer_10ms(TRUE);       // reset 10msec tick count
                sampleCnt = 1;
                sampTime = 0L;
                nextTime = 0L;
                while(1)
                {
                    sampTime = Timer_10ms(FALSE);
                    if(sampTime >= nextTime)
                    {
                        nextTime = sampTime + sampDelay;
                        ADCResult = pollADS1248_iso(1, 6, sampleCnt, 1, 5);       // Chan +5 -1, trials = 1, gain = user, sps = 5 Hz
                        uprintf("Counter Electrode Voltage = %.6f V,  Samp = %04u,  Time = %06lu \r\n", ADCResult, indx++, sampTime/100L);
                    }
                    if( UARTRxBytesAvail() )
                    {
                        input = get_key();
                        break;    // break from while(1)
                    }
                }
                break;

            case '6':
                uprintf("6 -- Substrate Current, Mux = 10,  AIN1+ AIN6-\n");
                ADS1248_gpio_ADG1609_mux(2);
                indx = 0;
                Timer_10ms(TRUE);       // reset 10msec tick count
                sampleCnt = 1;
                sampTime = 0L;
                nextTime = 0L;
                while(1)
                {
                    sampTime = Timer_10ms(FALSE);
                    if(sampTime >= nextTime)
                    {
                        nextTime = sampTime + sampDelay;
                        ADCResult = pollADS1248_iso(1, 6, sampleCnt, 1, 5);       // Chan +5 -1, trials = 1, gain = user, sps = 5 Hz
                        uprintf("Substrate Current = %.6f,  Samp = %04u,  Time = %06lu \r\n", ADCResult, indx++, sampTime/100L);
                    }
                    if( UARTRxBytesAvail() )
                    {
                        input = get_key();
                        break;    // break from while(1)
                    }
                }
                break;

            case '7':
                uprintf("7 -- Substrate Voltage, Mux = 10,  AIN5+ AIN6-\n");
                ADS1248_gpio_ADG1609_mux(2);
                indx = 0;
                Timer_10ms(TRUE);       // reset 10msec tick count
                sampleCnt = 1;
                sampTime = 0L;
                nextTime = 0L;
                while(1)
                {
                    sampTime = Timer_10ms(FALSE);
                    if(sampTime >= nextTime)
                    {
                        nextTime = sampTime + sampDelay;
                        ADCResult = pollADS1248_iso(5, 6, sampleCnt, 1, 5);       // Chan +5 -1, trials = 1, gain = user, sps = 5 Hz
                        sampTime = Timer_10ms(FALSE);
                        uprintf("Substrate Voltage = %.6f V,  Samp = %04u,  Time = %06lu \r\n", ADCResult, indx++, sampTime/100L);
                    }
                    if( UARTRxBytesAvail() )
                    {
                        input = get_key();
                        break;    // break from while(1)
                    }
                }
                break;

            case '8':
                uprintf("8 -- Thermistor ISFET Temperature, Mux = XX,  AIN0+ AIN6-\n");
                ADS1248_gpio_ADG1609_mux(0);        // Not necessary, but consistent
                indx = 0;
                Timer_10ms(TRUE);       // reset 10msec tick count
                sampleCnt = 1;
                sampTime = 0L;
                nextTime = 0L;
                while(1)
                {
                    sampTime = Timer_10ms(FALSE);
                    if(sampTime >= nextTime)
                    {
                        nextTime = sampTime + sampDelay;
                        ADCResult = pollADS1248_iso(0, 6, sampleCnt, 1, 5);       // Chan +5 -1, trials = 1, gain = user, sps = 5 Hz
                        sampTime = Timer_10ms(FALSE);
                        uprintf("Thermistor = %.6f,  Samp = %04u,  Time = %06lu \r\n", ADCResult, indx++, sampTime/100L);
                    }
                    if( UARTRxBytesAvail() )
                    {
                        input = get_key();
                        break;    // break from while(1)
                    }
                }
                break;



            case 'T':
                // reading pH voltage
                uprintf("\nReading 24bit voltage via ADG1609 mux and ADS1248\n");
                ROM_SysCtlDelay(MILLISECOND * 100);
                openADS1248_iso();
                ADS1248_gpio_init();    // defd in ADS1248_iso.c

                ROM_SysCtlDelay(MILLISECOND * 100);
                // Now read the pH value (diff across AIN1- and AIN5+)
                uprintf("\n\n1: ADG1609 mux=00 (0) S1A S1B, ADS1248 AIN1- to AIN5+\n");
                ADS1248_gpio_ADG1609_mux(0);

                indx = 0;
                while(1)
                {
                    // pos chan, neg chan, avg=2, gain=1, sps=5
                    // pH to pH ref
                    ADCResult = pollADS1248_iso(5, 1, 2, 1, 5);       // Chan 5-1, trials = 1, gain = user, sps = 5 Hz
                    uprintf("pH = %.6f V,  loop= %u \r", ADCResult, indx++);

                    if( UARTRxBytesAvail() )
                    {
                        input = get_key();
                        break;    // break from while(1)
                    }
                }

                uprintf("\n\n2: ADG1609 mux=00 (0) S1A S1B, ADS1248 AIN1- to AIN6+(gnd)\n");
                ADS1248_gpio_ADG1609_mux(0);

                indx = 0;
                while(1)
                {
                    // pos chan, neg chan, avg=2, gain=1, sps=5
                    // pH to pH ref
                    ADCResult = pollADS1248_iso(6, 1, 2, 1, 5);       // Chan 6-1, trials = 1, gain = user, sps = 5 Hz
                    uprintf("pH = %.6f V,  loop= %u \r", ADCResult, indx++);

                    if( UARTRxBytesAvail() )
                    {
                        input = get_key();
                        break;    // break from while(1)
                    }
                }

                uprintf("\n\n3: ADG1609 mux=11 (3) S4A S4B, ADS1248 AIN1- to AIN5+\n");
                ADS1248_gpio_ADG1609_mux(3);
                indx = 0;
                while(1)
                {
                    // pos chan, neg chan, avg=2, gain=1, sps=5
                    // pH to pH ref
                    ADCResult = pollADS1248_iso(5, 1, 2, 1, 5);       // Chan 5-1, trials = 1, gain = user, sps = 5 Hz
                    uprintf("pH = %.6f V,  loop= %u \r", ADCResult, indx++);

                    if( UARTRxBytesAvail() )
                    {
                        input = get_key();
                        break;    // break from while(1)
                    }
                }

                uprintf("\n\n4: ADG1609 mux=11 (3) S4A S4B, ADS1248 AIN1- to AIN6+(gnd)\n");
                ADS1248_gpio_ADG1609_mux(3);
                indx = 0;
                while(1)
                {
                    // pos chan, neg chan, avg=2, gain=1, sps=5
                    // pH to pH ref
                    ADCResult = pollADS1248_iso(6, 1, 2, 1, 5);       // Chan 6-1, trials = 1, gain = user, sps = 5 Hz
                    uprintf("pH = %.6f V,  loop= %u \r", ADCResult, indx++);

                    if( UARTRxBytesAvail() )
                    {
                        input = get_key();
                        break;    // break from while(1)
                    }
                }

                closeADS1248_iso();
                uprintf("iso power off\n");

                break;

            default:
                uprintf("\nPress enter to bring up menu\n");
                closeADS1248_iso();
                uprintf("iso power off\n");
                return;
        } // switch

    } // while(1)

    // Future: if break from while(1), then make sure to close isolated supply (return is from switch-default)
    closeADS1248_iso();
    uprintf("iso power off\n");
}




/**************************************************************************************
 * deploy()
 * Accepts a deployment state argument that determines whether to start the deployment,
 * take a sample, or enter the command mode.
 ***************************************************************************************/
void deploy(deploy_state state)
{
	int response;
	time_t start_time, current_time;
	int charCount, gdata, ts, stop, dump, samp_byte, gh, sl, ss;
	char buff[81];
	FIL fileObject;
	FRESULT fresult;
	UINT br;
	bool line_end;

	// START mode
	if(state == START)	// New deployment or test
	{
		uprintf("\n\n\n\n\n***************** Deployment Settings **************\n");
		// Sensor name
		// Durafet ID

		uprintf("Sampling period: \t%d seconds\n", sys_data.sampling_period);

		uprintf("Samples hour aligned\t");
		if(sys_data.sample_aligned)	uprintf("Yes\n");
		else uprintf("No\n)");

		// THOM: update the header with correct info (fast sampling, etc)
		uprintf("pH sample average: \t%d samples\n", sys_data.sample_average);
		uprintf("Pump on time: \t%d seconds\n", sys_data.pumpon_time);
		uprintf("Low battery voltage: \t%.1f V\n", sys_data.low_batt_volt);

		if(sys_data.output == 1) uprintf("Output mode: \tNormal\n");
		else if(sys_data.output == 2) uprintf("Output mode: \tVerbose\n");
		uprintf("Eo_int @ 25 C = \t%1.6f V\n", sys_data.Eo_int_25C);
		uprintf("Eo_ext @ 25 C = \t%1.6f V\n", sys_data.Eo_ext_25C);

		uprintf("File name: \t%s\n", sys_data.fileName);

		uprintf("Current time: ");
		printCurrentTime();

		uprintf("\n*****************************************************\n");

		//response = yesOrNoMenuChoice("\n\nTest deployment (SBE pump disabled)? (Y/N) [Y]? ", YES);
		response = NO;      // THOM - added this line 3 May 2018

		// Test deployment
		if(response == YES)             // THOM: TODO, this line relies on a commented out line above - 'response' is tested before it is set
		{
			sys_data.test_mode = 1;

			uprintf("\n\nEntering test deployment mode (SBE pump disabled)\n\n");
			sys_data.nextWakeUp =  ROM_HibernateRTCGet();	// Start immediately
			start_time = sys_data.nextWakeUp;
		}

		//Actual deployment (SBE pump will run)
		else
		{
			sys_data.test_mode = 0;			// SBE pump will run

			// Set a custom start time?
			//response = yesOrNoMenuChoice("\nSet custom start time (Y/N) [N]? ", NO);
			response = NO;          // THOM added 7 May 2018 (line commented out above)
			// Custom start time
			if(response == YES)
			{
				while(1)
				{
					start_time = getDateAndTime();

					uprintf("\nStart time now: ");
					print_time_t_Time(start_time);
					//response = yesOrNoMenuChoice("\nStart time correct (Y/N) [N]? ", NO);
					response = YES;  // THOM New 8 May 2018
					if( response == NO )
					{
						//start the loop over, they want to change the time
						continue;
					}

					sys_data.nextWakeUp = start_time;
					break;
				}
			}
			// No custom start time
			else
			{
				current_time = ROM_HibernateRTCGet();    //THOMHERE - check for 0 to make polled happen
				sys_data.nextWakeUp = current_time;		// Start immediately

			}

			if(sys_data.pumpon_time > 0)
			{
			    uprintf("\nSBE pump will run and must be immersed at start time!");
			}
			//response = yesOrNoMenuChoice("\n\nDo you really want to deploy (Y/N [N])? ", NO);
			//response = YES;         // THOM added 7 May 2018 due to line above commented
			//if(response == NO)
			//    return;
		}

		/*// Exit deployment mode if file name is not reset
		if(sys_data.fileName == g_sFileInfo.fname)
		{
			// prompt for new filename
			uprintf("\nFile Already Exists! Enter new File name\n");
			return;
		}*/


		// Begin deployment...
		sys_data.current_sample = 0;	// Reset sample number
		sys_data.state = DEPLOYED;

		if(sys_data.sampling_period == 0)
		{
		    uprintf("\n\nDeployed in polled mode (COMMAND)...\n\n");        // THOM, polled mode  7 May 2018
		    sys_data.state = COMMAND;
		}

		if( writeDeploymentInformationHeader(current_time, start_time, 1) )  // Write deployment header to data file
		{
			return;		// File access error, abort deployment
		}
		else
		{
			uprintf("\n\nStarting deployment...\r\n");       // THOM New 07 Jun 2018 - added crlf
			ROM_SysCtlDelay(MILLISECOND*100);        // time to send string

		}

	}	// End of sys_data.state == START if statement

	// COMMAND mode
	else if(sys_data.state == COMMAND)
	{

		while(1)	// Command loop
		{
			if(sys_data.output == VERBOSE || sys_data.test_mode) uprintf("\nEnter command (ts, ss, gh, gdata, stop): ");

			//flush the receive and transmit buffers
			UARTFlushRx();

			// Wait for command for 10 seconds
			charCount = getUserInputTimeLimit(buff, sizeof(buff), 10);

			// If the time limit passed...
			if(charCount == TIMELIMITPASSED)
			{
				if(sys_data.output == VERBOSE) uprintf("\n\nNo command, resuming deployment...");
				break;
			}
			else
			{
				// Parse command
				gdata = strncmp(buff, "gdata", 5);      // get data
				ts = strncmp(buff, "ts", 2);            // take sample
				ss = strncmp(buff, "ss", 2);            // start sample, needs to have sl
				//sl = strncmp(buff, "sl", 2);            // send last sample, must have sent ss first
				gh = strncmp(buff, "gh", 2);            // get header
				stop = strncmp(buff, "stop", 4);        // stop deployment (sampling)
				dump = strncmp(buff, "dump", 4);        // dump

				if(gdata == 0)	// Display samples since last gdata command
				{
					UARTEchoSet(false);		// Turn off console echo so key hit doesn't mess up screen output

					// Open a file
					fresult = f_open(&fileObject, sys_data.fileName, FA_READ|FA_OPEN_ALWAYS);
					if(fresult != FR_OK)
					{
						uprintf("Error.txt f_open error: %s\n", StringFromFresult(fresult));
					}

					// Seek to the next byte in data file since last gdata
					fresult = f_lseek(&fileObject, sys_data.next_gdata_fptr);
					if(fresult != FR_OK)
					{
						uprintf("Error.txt f_lseek error: %s\n", StringFromFresult(fresult));
					}

					// Print out the records
					line_end = false;

					do
					{
						fresult = f_read(&fileObject, buff, 80, &br);
						if(fresult != FR_OK)
						{
							uprintf("Error.txt f_read error: %s\n", StringFromFresult(fresult));
						}

						buff[br] = '\0';

						// Wait till there is room in tx buffer, then print the buffer
						while( UARTTxBytesFree() <= 80 );
						uprintf("%s", buff);

						// Stop reading and printing if user hits key
						if(kbhit())
						{
							// Print out any remaining characters of the last sample
							do
							{
								fresult = f_read(&fileObject, buff, 80, &br);
								{
									uprintf("Error.txt f_read error: %s\n", StringFromFresult(fresult));
								}

								for(samp_byte = 0; samp_byte < br; samp_byte++)
								{
									uprintf("%c", buff[samp_byte]);

									if( buff[samp_byte] == '\n' )	// Look for the end of the line
									{
										line_end = true;
										break;
									}
								}
							} while(br == 80 && !line_end);

							break;
						}

					} while (br == 80 && !line_end);		// Keep doing this until the end of the file

					sys_data.next_gdata_fptr = fileObject.fptr;		// Store the current file position for next gdata command
					UARTEchoSet(true);								// Turn console echo back on
				}

				// Take a sample and continue with deployment
				else if( ts == 0 )
				{
				    //profile_on(8);
				    sys_data.state = DEPLOYED;
				    if(sys_data.sampling_period == 0)   // THOM Polled Mode
				        sys_data.state = COMMAND;      // THOM NEW - use command mode to stop RTC wakeup (polled mode)

				    profile_on(1);
				    //get_sample(1);
					fast_sample(1);     // new fast sampling - replaced get_sample per Yui Jun 2019
					profile_off(1);
					break;
				}
                else if( ss == 0 )
                {
                    //profile_on(8);
                    sys_data.state = DEPLOYED;
                    if(sys_data.sampling_period == 0)   // THOM Polled Mode
                        sys_data.state = COMMAND;      // THOM NEW - use command mode to stop RTC wakeup (polled mode)

                    //flush the receive and transmit buffers
                    UARTFlushRx();

                    //get_sample(1);
                    profile_on(1);
                    fast_sample(0);     // new fast sampling - replaced get_sample per Yui Jun 2019
                    profile_off(1);

                    // Wait for command for 6 seconds
                    charCount = getUserInputTimeLimit(buff, sizeof(buff), 6);

                    if(charCount == TIMELIMITPASSED)
                    {
                        if(sys_data.output == VERBOSE) uprintf("\n\nNo command, resuming deployment...");
                        break;
                    }
                    else
                    {
                        // Parse command
                        sl = strncmp(buff, "sl", 2);            // send last sample, must have sent ss first
                        if( sl == 0 )
                        {
                            print_sampBuf();
                            ROM_SysCtlDelay(MILLISECOND*30);        // time to send string
                            break;

                        }
                        else
                        {
                            uprintf("\nexpected sl, received %s\n", buff);
                        }
                    }

                    //break;
                }
				// Get header info and dump to terminal
                else if( gh == 0 )
                {
                    sys_data.state = DEPLOYED;
                    if(sys_data.sampling_period == 0)   // THOM Polled Mode
                        sys_data.state = COMMAND;      // THOM NEW - use command mode to stop RTC wakeup (polled mode)
                    get_header();
                    break;
                }
				// Exit deployment and return to main menu
				else if( stop == 0 )
				{
					sys_data.state = IDLE;
					return;
				}
				else if( dump == 0)
				{
				    state_dump();
				    // no break here - means another command can be entered, break leads to sleep
				}

				// Invalid command
				else
				{
					if(sys_data.output == VERBOSE) uprintf("\nInvalid command");	// Goes back to top of command loop
					uprintf("NAK\n");
				}
			}
			dbg_printf("\nbottom of command loop\n");   // THOM debug
		}	// End of command loop

		if(sys_data.sampling_period == 0)       // THOM new 7 May 2018
		    sys_data.state = COMMAND;       // COMMAND state is how polling occurs
		else
		    sys_data.state = DEPLOYED;	// Go back to DEPLOYED state


	}   // else if(sys_data.state == COMMAND)

	// DEPLOYED mode
	else
	{
	    // RTC wakeup

	    profile_toggle(1);

	    // this code used for overnight testing and ADCsampling noise analysis, tradeoff with std dev vs adc sigmadelta
#ifdef DEBUGCOMPARESAMPLING
	    current_time = ROM_HibernateRTCGet();

	    current_time /= 10;
	    current_time %= 2;
	    //uprintf("\nget vs fast %u\n", current_time);



	    if((current_time % 10) == 0)        // if tenths of seconds is even
	    {
	        //uprintf("get_sample(1)\n");
	        get_sample(1);          // RTC wakeup sampling
	    }
	    else
	    {
	        //uprintf("fast_sample(1)\n");
	        fast_sample(1);

	    }
#endif


//#ifdef NORMALSAMPLING
	    // this is the normal sampling, the above section is for comparison of sampling
	    fast_sample(1);
	    profile_toggle(1);   // toggle profile as sleep is about to happen
//#endif

		// Calculate the next sample time
		if(sys_data.sample_aligned)		// Sample time hour aligned?
		{
			current_time = ROM_HibernateRTCGet();
			sys_data.nextWakeUp = (current_time / 3600) * 3600;	 		// Find last hour

			// THOM 2 Jul TODO: this code nears an error check to insure time is not whacked - have seen a hang here
			do
			{
				sys_data.nextWakeUp += sys_data.sampling_period;
			} while(sys_data.nextWakeUp < current_time);
		}
		else sys_data.nextWakeUp += sys_data.sampling_period;	// Not hour aligned
	}

	if(sys_data.sampling_period == 0)  // NEW 8 May 2018
	{
	    //profile_off(8);
	    sleep(COMMAND, 0);   // Sleep until woken by UART (keystroke at serial terminal)   THOM New 8 May 2018
	}
	else
	{
	    sleep(DEPLOYED, sys_data.nextWakeUp);	// Sleep until woken by RTC or keystroke
	}
}



void state_dump(void)
{
    time_t current_time;

    dbg_flag = 1;

    dbg_printf("\n\n");

    if(sys_data.state == DEPLOYED)
    {
        dbg_printf("DEPLOYED\n");
    }
    if( sys_data.state == COMMAND)
    {
        dbg_printf("COMMAND\n");
    }
    if( sys_data.state == IDLE)
    {
        dbg_printf("IDLE\n");
    }

    current_time = ROM_HibernateRTCGet();

    dbg_printf("now %lu, next wake %lu, sampling period %lu\n", (unsigned int)current_time, sys_data.nextWakeUp, sys_data.sampling_period);

}



