/*
 * test.c
 *
 *  Created on: Apr 23, 2021
 *      Author: Thom Maughan, tm@mbari.org
 */

#include "system.h"



#include "aux1.h"
#include "aux2.h"
#include "config.h"
#include "sample.h"
#include "user_io.h"
#include "microsd.h"
#include "i2c_fram.h"
#include "fatfs/src/ff.h"
#include "adc_onchip.h"
#include "ads1248_iso.h"
#include "ads1248_noniso.h"
#include "sleep.h"
#include "Optode.h"
#include "ctd_base.h"
#include "uartstdio.h"
#include "board_util.h"
#include "config.h"
#include "ctd_aand5860.h"
#include "ctd_sbe37_microcat.h"
#include "i2c_fram.h"

#include "user_io.h"
#include "test.h"


extern struct systemSamplingData sys_samp;


//Test Menu -- v3.5.5 MpHOx revB pre-release, DO NOT DEPLOY this version of firmware
//1 -- Battery and Board Sensors
//void display_battery_boardSensors(void);
//2 -- ISFET, References and Thermistor volts
//void display_ph_ref_therm_volts(void);
//3 -- Calc pH using Int Ref and Thermistor
//void display_calcd_pH_intRef_therm(void);
//4 -- Calc pH using Ext Ref, Thermistor and Salinity
//void display_calcd_pH_extRef_therm_sal(float Salinity);
//5 -- Communicate with Instrument
//void communicate_with_instruments(void);
//6 -- Power Output Tests for AUXx and Pump
//int power_output_tests(void);
//8 -- Test 24bit ADC and MUX channels
//void test_24bit_adc_mux(void);
//D -- Data Header print
//extern void print_data_header(void);
//M -- Meta Data print
//extern void print_write_metadata_header(const time_t currentTime, uint32_t printFlg, uint32_t writeFlg);
//Q -- QA and setup after board manufacture
//int board_qa_and_init(int initFlg);


//int test_sampling_mcap(int qaFlg);


/*
 * Global System variables.
 */
extern uint32_t adc_data[];
extern char Optode_buff[];
extern float fBiasPos;  // used for read_bias_bat();
extern float fBiasNeg;

extern unsigned char prnBuf[];



/*************************************************************************************************************************
 * Test menu.
 *************************************************************************************************************************/
void test_menu(void)
{
    int response;
    time_t timer;
    time_t current_time;
    char input;

    // Test menu loop
    while(1)
    {
        //uprintf("\n\n\nTest Menu -- %s\n", VERSION);
        uprintf("\n\n\nTest Menu:\n");
        if(sys_data.app_cfg[APPCFG_MENU_LEVEL] == 0)
        {
            uprintf("1 -- Battery and Board Sensors\n");  //uprintf("1 -- Internal Environment Sensors\n");  //uprintf("1 -- Display Battery, Internal Temp, Pressure\n");
            uprintf("2 -- Durafet voltages\n");   //ISFET, References and Thermistor volts was Display pH Sensor Data
            uprintf("3 -- Calc pH using Int Ref and Thermistor\n");   //uprintf("3 -- Communicate with Instrument\n");
            uprintf("4 -- Calc pH using Ext Ref, Thermistor and Salinity\n");
            uprintf("5 -- Communicate with Instrument\n");
            uprintf("6 -- Power Output Tests for AUXx and Pump\n");
            //uprintf("7 -- spare\n");
            uprintf("8 -- Test 24bit ADC and MUX channels\n");
            uprintf("D/d- Data Header, Live Data (D loop), Sample Timing\n");      //uprintf("D/d- Data Header print and test\n");
            uprintf("M -- MetaData\n");
            uprintf("P -- Print QA report\n");
            uprintf("Q -- QA and setup after board manufacture\n");
        }
        else
        {       // sys_data.app_cfg[APPCFG_MENU_LEVEL] == 1
            uprintf("1 -- Battery and Board Sensors\n");
            uprintf("2 -- Durafet voltages\n");
            uprintf("3 -- Calc pH using Int Ref and Thermistor\n");
            uprintf("4 -- Calc pH using Ext Ref, Thermistor and Salinity\n");
            uprintf("5 -- Communicate with Instrument\n");
            uprintf("6 -- Power Output Tests for AUXx and Pump\n");
            //uprintf("7 -- spare\n");
            uprintf("8 -- Test 24bit ADC and MUX channels\n");
            uprintf("D/d- Data Header, Live Data (D loop), Sample Timing\n");
            uprintf("M -- MetaData\n");
            uprintf("P -- Print QA report\n");
            uprintf("Q -- QA and setup after board manufacture\n");

            uprintf("S -- DEBUG sys_data print\n");
        }
        uprintf("9 -- Exit to Main Menu\n");
        uprintf("\nEnter Selection [9]: ");

        UARTFlushRx();
        timer = 30000 + ROM_HibernateRTCGet();  //30 second

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

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

        switch(input)
        {
            //case 'f':
            //    test_buffer_filewrite();   testing formatted buffer, write size
            //    break;

            //case 's':
            //    uprintf("\n");
            //    temp = sizeof(struct systemData);
            //    uprintf("sizeof sys_data = %u\n", temp);
            //
            //    temp = EEPROMSizeGet(); // Get EEPROM Size
            //    uprintf("EEPROM Size %d bytes\n", temp);
            //    break;

            case 'S':
            case 's':
                if(sys_data.app_cfg[APPCFG_MENU_LEVEL] == 1)
                {
                    uprintf("sys_data structure:\n\n");
                    print_sys_data_structure();
                }
                break;

            case '1':
                display_battery_boardSensors();  // defd in test.c
                break;


            case '2':
                display_ph_ref_therm_volts();     // defd in test.c  // taken from 8->S sample all channels
                break;

            case '3':
                //Calculate pH with internal reference and temperature
                display_calcd_pH_intRef_therm();   // defd in test.c
                break;


            case '4':
                //Calculate pH with ext ref and temp, requires salinity
                display_calcd_pH_extRef_therm_sal(35.0);     // defd in test.c   // pass in Salinity (future, this will be read from conductivity or ctd
                break;

            case '5':
                communicate_with_instruments();  // defd in test.c   // peripheral instruments such as microcat, optode
                break;

            case '6':
                //uprintf("Power Output Tests for AUXx and Pump\n\n");
                power_output_tests();  // defd in test.c
                break;

            case '7':
                //Unused
                break;

            case '8':
                test_24bit_adc_mux(); // defd in test.c
                break;

            case 'd':
                print_config_data_fields();
                print_data_header();     // defd in system.c
                fast_sample(1);
                sys_data.app_cfg[APPCFG_SAMPLING_DIAG] = 1;
                uprintf("\n ---  Sample Timing ---\n");
                fast_sample(1);
                sys_data.app_cfg[APPCFG_SAMPLING_DIAG] = 0;
                break;
            case 'D':
                print_config_data_fields();
                if(sys_data.pumpon_time > 0)
                    uprintf("\nHit Ctrl-X to terminate pump cycle followed by any key to terminate sample loop\n");
                else
                    uprintf("\nHit any key to terminate sample loop\n");

                print_data_header();     // defd in system.c
                while(1)
                {
                    if( UARTRxBytesAvail() )
                    {
                        input = get_key();
                        break;    // break from while(1)
                    }
                    fast_sample(1);
                }
                break;

            case 'm':
            case 'M':
                current_time = ROM_HibernateRTCGet();
                print_write_metadata_header(current_time, 1, 0);
                break;

            case 'Q':
            case 'q':
                response = yesOrNoMenuChoice("\n\nQA for new board, this will wipe out ALL config and setup data, do you wish to proceed? [N]? ", NO);
                if(response == YES)
                {
                    board_qa_and_init(1); // pass in 1 for init of Flash mem
                }

                break;

            case 'P':
            case 'p':
                uprintf("\n\nQA Report:  \n\n");
                print_qa_report();
                break;

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

        }
    }
}


//1 -- Battery and Board Sensors
void display_battery_boardSensors(void)
{
    unsigned int loopCnt;
    unsigned int uiWater;
    unsigned int uiPressure;
    unsigned int uiHumidity;
    float fVbat;
    float fOnChipTemp;
    float fExtTemp;
    float fPressure;
    float ADCResult;
    char  input;

#if BOARD_MFET >= 1 || BOARD_MPHOX >= 1

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

    pwr_iso_on();  // was ROM_GPIOPinWrite(GPIO_PORTK_BASE, GPIO_PIN_2, 0xFF);        // Iso-power On
    openADS1248_iso();
    ROM_SysCtlDelay(MILLISECOND * 100);
    uprintf("iso power on for reading bias batteries\n");
    ADS1248_gpio_init();        // for reading bias bat

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

        read_all_adc();

        fVbat = (float)(adc_data[0]*100);
        fVbat /= 18193.77;         // Agilent U1252A meter used to calibrate

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

        //----------------

        // code taken from read_bias_bat();  (dont want to open and close, init and reinit)

        ADS1248_gpio3(0);
        ROM_SysCtlDelay(MILLISECOND * 10);
        ADCResult = pollADS1248_iso(7, 6, 5, 1, 20);    // throw away first reading
        ROM_SysCtlDelay(MILLISECOND * 100);
        ADCResult = pollADS1248_iso(7, 6, 5, 1, 20);
        fBiasNeg = ADCResult*2.0;

        ADS1248_gpio3(1);
        ROM_SysCtlDelay(MILLISECOND * 10);
        ADCResult = pollADS1248_iso(7, 6, 5, 1, 20);    // throw away first reading
        ROM_SysCtlDelay(MILLISECOND * 100);
        ADCResult = pollADS1248_iso(7, 6, 5, 1, 20);
        fBiasPos = ADCResult*2.0;

        //----------------



        uprintf("Bat = %6.2fV   Humidity = %3u  Water = %3u   BoardTemp = %5.1fC   bias(+,-) = %5.2fV, %5.2fV   i=%u\r", fVbat, uiHumidity, uiWater, fExtTemp, fBiasPos, fBiasNeg, loopCnt++);

        ROM_SysCtlDelay(MILLISECOND * 500);

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

    closeADS1248_iso();

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

#if BOARD_NANOFET >= 1
    uprintf("\nTHOM TODO: Test menu item 1 needs to be implemented for nanoFET (need a board)\n\n");

#endif

}



//2 -- ISFET, References and Thermistor volts
void display_ph_ref_therm_volts(void)
{
    float ADCResult;
    int sampleCnt;
    unsigned long sampTime;
    unsigned long nextTime;
    unsigned long sampDelay;
    uint32_t    indx;
    char        inChar;

    // this code taken from void test_24bit_adc_mux(void), S stream all channels

#if BOARD_MFET >= 1 || BOARD_MPHOX == 1

    //ROM_SysCtlDelay(MILLISECOND * 100);
    openADS1248_iso();      // 22msec
    uprintf("\nOpen isolated ADS1248 and ADG1609 mux\n\n");
    ROM_SysCtlDelay(MILLISECOND * 100);
    ADS1248_gpio_init();    // defd in ADS1248_iso.c

#endif

#if BOARD_NANOFET >= 1

    openADS1248_iso();      // 22msec  nanoFET is PD0 to PD3, MFET iso is PH0 to PH3
    uprintf("\nOpen nFET ADS1248 and ADG1609 mux\n\n");
    ROM_SysCtlDelay(MILLISECOND * 100);
    ADS1248_gpio_init();    // defd in ADS1248_iso.c
#endif


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


    sampDelay = 500L;

#if BOARD_MFET >= 1 || BOARD_MPHOX >= 1
//SampNum SampTime Vbatt_main TC_cont Humidity PresHousing Vtherm Vtherm_std VrsiBiased VrsiBiased_std VrseBiased VrseBiased_std Vrsi Vrsi_std Vrse Vrse_std Vk Vk_std Ik Ib TC_Dfet pHint_est Vbatt_iso or Vbatt_isop Vbatt_ison
// SampNum SampTime Vbatt   TC_brd Humid_brd Pres_brd Vtherm Vtherm_std Vrsi_O Vrsi_O_std Vrse_O Vrse_O_std Vrsi Vrsi_std Vrse Vrse_std Vk Vk_std Ik Ib TC_calc pHint pHext Vbias


    //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");
               //    SampTime,   Vrse_B,  Vrse, Vrsi_B, Vrsi, Ik, Vk,  Ib,  Vb,  Vtherm
               //04/23/21 13:21:08,  -0.069202,  -0.799240,  0.674855,  -0.055217,  0.272939,  -0.500563,  -0.399630,  0.000679,  0.997511
               //04/23/21 13:21:13,  -0.069171,  -0.799247,  0.674859,  -0.055215,  0.272926,  -0.500557,  -0.399631,  0.000677,  0.997506
    if(sys_data.diag > 0)
        uprintf("\n\n    SampTime,         Vrse_B,     Vrse,      Vrsi_B,      Vrsi,      Ik,         Vk,          Ib,        Vb,     Vtherm\n");
    else
        uprintf("\n\n    SampTime,         Vrse_B,     Vrse,      Vrsi_B,      Vrsi,      Ik,         Vk,          Ib,     Vtherm\n");


#endif

#if BOARD_NANOFET >= 1
    //uprintf("\n\n    Date Time,  Ext Ref V, CntrE Cur, CntrE Volt,  Subst Cur,  Subst Vol,  Thermistor\n");
    uprintf("\n\n    SampTime,   Vrse, Ik, Vk,  Ib,  Vb,  Vtherm   NEEDS WORK\n");
#endif

    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(", ");
#if BOARD_MFET >= 1 || BOARD_MPHOX >= 1
            //Ext Ref Off,
            ADS1248_gpio_ADG1609_mux(0);
            ROM_SysCtlDelay(MILLISECOND * 10);      // 10msec settling for MUX analog  (THOM CRASH 14 Jul 2021)
            ADCResult = pollADS1248_iso(1, 5, sampleCnt, 1, 5);       // was 20 Chan +1 -5, trials = 1, gain = user, sps = 5 Hz
            uprintf(" %.6f, ", ADCResult); // Ext Ref with Offset

            //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 Off,
            ADS1248_gpio_ADG1609_mux(3);
            ROM_SysCtlDelay(MILLISECOND * 10);      // 10msec settling for MUX analog
            ADCResult = pollADS1248_iso(1, 5, sampleCnt, 1, 5);       // 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);

            // 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
#endif
#if BOARD_NANOFET >= 1
            //Ext Ref V,
            ADS1248_gpio_ADG1609_mux(0);
            ROM_SysCtlDelay(MILLISECOND * 10);      // 10msec settling for MUX analog
            ADCResult = pollADS1248_iso(1, 5, sampleCnt, 1, 5);       // Chan +1 -6, trials = 1, gain = user, sps = 5 Hz
            uprintf(" %.6f, ", ADCResult);       // Ext Ref Voltage
#endif

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

            if(sys_data.diag > 0)
            {
                // 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() )
        {
            inChar = get_key();
            break;    // break from while(1)
        }
    }// while(1)


}




void display_calcd_pH_intRef_therm(void)
{
    float Vtherm, TC, Vrsi_B, pHint;


    openADS1248_iso();          // 52 msec
    ROM_SysCtlDelay(MILLISECOND * 100);
    ADS1248_gpio_init();

    uprintf("Calculate temperature in degrees C using Durafet Thermistor\n");
    uprintf("   DuraFet Thermistor Quadratic coefficients:\n");
    uprintf("     c0 = 340.9819863\n");
    uprintf("     c1 = -9.10257E-05\n");
    uprintf("     c2 = -95.08806667\n");
    uprintf("     c3 = 0.965370274\n");
    uprintf("    Rtherm = 20000 / ((3.3 / V_therm) - 1)\n");
    uprintf("    TempC = c0 + c1*Rtherm + c2*(log10(Rtherm)) + c3*(pow(log10(Rtherm), 3))  Note: pow fxn is log10(Rtherm) cubed\n");
    uprintf("\n");
    uprintf("Compute pH using Temperature and Vrsi_B (ISFET pH voltage biased for 0v at 7pH with respect to internal reference):\n");

    uprintf("   TempC = TempC + sys_data.TCOffset   TCOffset is user entered in config menu\n");
    uprintf("   TempK = TempC + 273.15\n");
    uprintf("   NernstSlope = (R_=8.31451 * TempK) / F_=96487 * LN10=2.302585\n");
    uprintf("   NernstSlope = TempK / 26,720.7\n");
    uprintf("   Eoint = k0int + dEoINT_dt=-0.0011012 * (TC-25)   k0int is typically -0.4 and can be modified in Config menu\n");
    uprintf("   Eoint = -0.4 + -0.0011012 * (TempC-25)\n");
    uprintf("   pHint = (Vrsi_B - Eoint) / NernstSlope\n");
    uprintf("\n\n");


    // Apply offset to TC; TCOffset is an user input,
    // or derived during pH calibration process.


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



    while(!UARTRxBytesAvail())
    {

        //get Vtherm voltage
        Vtherm = pollADS1248_iso(0, 6, 5, 1, 10);      // Chan 0-6, trials = 5, gain = 1, sps = 10 Hz
        TC = DuraFET_temp(Vtherm,sys_data.TCOffset);                    // temperature centigrade

        //get Vrsi_B voltage
        ADS1248_gpio_ADG1609_mux(3);
        ROM_SysCtlDelay(MILLISECOND * 10);      // 10msec settling for MUX analog
        Vrsi_B = pollADS1248_iso(1, 5, 5, 1, 5);  // VintRef_withoffset  Mux=3, Chan 1-5, trials=5, gain=1, sps=5 Hz

        pHint = calc_pHint(Vrsi_B, TC);

        uprintf("pH= %2.6f,  TC= %2.6f,  Vtherm= %.6f V, Vrsi_B= %.6f V, std= %.6f\n", pHint, TC, Vtherm, Vrsi_B, sys_samp.AD24_std);

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





void display_calcd_pH_extRef_therm_sal(float Salinity)
{
    float Vrse;
    float TempC;
    float pHext;
    float Vtherm;
    //char input;


    openADS1248_iso();          // 52 msec
    ROM_SysCtlDelay(MILLISECOND * 100);
    ADS1248_gpio_init();

    ROM_SysCtlDelay(MILLISECOND * 200); // Let electronics settle (was 1000)
    while(!UARTRxBytesAvail())
    {
        Vtherm = pollADS1248_iso(0, 6, 5, 1, 10);      // Chan 0-6, trials=5, gain=1, sps = 5 Hz

        TempC = DuraFET_temp(Vtherm, sys_data.TCOffset);                    // temperature centigrade

        //

        ADS1248_gpio_ADG1609_mux(0);
        ROM_SysCtlDelay(MILLISECOND * 10);      // 10msec settling for MUX analog
#if BOARD_MFET >= 1 || BOARD_MPHOX >= 1
        //Vrse = pollADS1248_iso(1, 6, 10, 1, 20);  // 10x50msec= 500msec  trials=10, gain=1, sps=20  THOM note: suggest using 1,6,5,1,10 to allow adc to do better filtering
        Vrse = pollADS1248_iso(1, 6, 5, 1, 5);  // 10x50msec= 500msec  trials=5, gain=1, sps=5  THOM note: suggest using 1,6,5,1,10 to allow adc to do better filtering
#endif
#if BOARD_NANOFET >= 1
            // 6 (GND) is not connected on nanoFET
        Vrse = pollADS1248_iso(1, 5, 5, 1, 5);  // 10x50msec= 500msec  trials=10, gain=1, sps=20  THOM note: suggest using 1,6,5,1,10 to allow adc to do better filtering
#endif
        // what is the difference between Vrse and Vrse_B, is it constant or temperature dependent?  offset gives reading of 7pH with 0 volts
        // was VextOff = pollADS1248_iso(4, 6, 4, 1, 5);        // trials = 4, gain=1, sps=5   let the sigma delta do the best it can do


        // THOM Todo - is this
        pHext = calc_pHext(Vrse, TempC, Salinity);                       // Vrse, TC, Sal

        uprintf("pHext= %2.6f,  TC= %2.6f,  Vtherm= %.6f V, Vrse= %.6f V, std= %.6f\n", pHext, TempC, Vtherm, Vrse, sys_samp.AD24_std);


        ROM_SysCtlDelay(MILLISECOND*100);
    }

    closeADS1248_iso();
}





void communicate_with_instruments(void)
{
    int optodeState;
    int ctdState;
    unsigned int tick1, tick2;
    uint32_t sm_delay;
    char input;
    char charInput;

    while(1)
    {
#if BOARD_MPHOX >= 1
        uprintf("\n\n\nCommunicate with Instrument Menu:\n");
        uprintf("1 -- SBE37 MicroCAT (on CTD port)\n");
        uprintf("2 -- Aanderaa 5860 Conductivity (on CTD port)\n");
        uprintf("3 -- Aanderaa Optode\n");
        uprintf("4 -- Comm-Pwr Aux port\n");
        //uprintf("5 -- Sample SBE37 MicroCAT (on CTD port)\n");
        //uprintf("6 -- Sample Aanderaa 5860 Conductivity (on CTD port)\n");
        //uprintf("7 -- Sample Aanderaa Optode\n");
        //uprintf("8 -- Sample Comm-Pwr Aux. port\n");

        if(sys_data.app_cfg[APPCFG_MENU_LEVEL] > 0)
        {
        uprintf("o/O- DEBUG Test Optode Setup\n");
        uprintf("p -- DEBUG Optode serial analyzer\n");
        uprintf("q -- DEBUG ctd aanderaa serial Analyzer\n");
        uprintf("r -- DEBUG ctd microcat serial Analyzer\n");
        uprintf("c/C- DEBUG Test conductivity\n");
        }

#endif
#if BOARD_MFET >= 1
        uprintf("\n\n\nCommunicate with Instrument Menu:\n");
        //uprintf("1 -- SBE37 MicroCAT (on CTD port)\n");
        //uprintf("2 -- Aanderaa 5860 Conductivity (on CTD port)\n");
        uprintf("3 -- Aanderaa Optode on J7\n");
        //uprintf("4 -- Comm-Pwr Aux port\n");
        //uprintf("5 -- Sample SBE37 MicroCAT (on CTD port)\n");
        //uprintf("6 -- Sample Aanderaa 5860 Conductivity (on CTD port)\n");
        //uprintf("7 -- Sample Aanderaa Optode\n");
        //uprintf("8 -- Sample Comm-Pwr Aux. port\n");

        if(sys_data.app_cfg[APPCFG_MENU_LEVEL] > 0)
        {
        uprintf("o/O- DEBUG Test Optode Setup\n");
        uprintf("p -- DEBUG Optode serial analyzer\n");
        }

#endif

        uprintf("9 -- Exit\n");
        uprintf("\nEnter Selection [9]: ");

        input = get_key();
        switch(input)
        {
#if BOARD_MPHOX >= 1
            case '1':  // MicroCAT
                ctd_microCat_comm_test();
                break;

            case '2':
                ctd_Aand5860_comm_test();
                break;
#endif
#if BOARD_MPHOX >= 1 || BOARD_MFET >=2
            case '3': // Optode
                optode_comm_test();     // defd in optode.c
                // THOM TODO: move this to optode.c
                break;
#endif
#if BOARD_MPHOX >=1
            case '4': // now COMM-PWR formerly AUX 1 3
                uprintf("\n\nCOMM-PWR port not supported on MPHOX, RS232 level shifter is not stuffed\n\n");
                break;

#ifdef NOCODE
                uprintf("\n\n*Press CTRL-X to stop communicating with COMM-PWR port.*\n\n");


                AUX1_init();

                UARTFlushTx(0);         //THOM todo, stdio routines need renaming, possibly goofed with optode in main.c and renamed a stdio pass thru
                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;
#endif

#endif

            case 'O':
                if(sys_data.app_cfg[APPCFG_MENU_LEVEL] == 0)
                    break;
                uprintf("\nLoop Test Optode (statemachine code):  Power Optode with 5v, wait for %, send crlf, wait for !, Send 'do sample', Receive, trim and print Optode sample terminated by #, turn power off \n\n");
                sm_delay = 100;   // make sure the statemachine can handle as slow as 1.5sec pump cycle
                //sm_delay = 0;
                while(1)
                {
                    //if user types anything, send it to the Optode--exit on CTRL-X
                    if(UARTRxBytesAvail())
                    {
                        charInput = UARTgetc();

                        //if(charInput == 24)  // ctrl-x
                            break;

                    }
                    tick1 = Timer_10ms(false);
                    optodeState = 1;
                    optodeState = optode_stateMachine(optodeState);

                    while(1)
                    {
                        if(sm_delay > 0) ROM_SysCtlDelay(MILLISECOND*sm_delay); // how often do we need to pump the statemachine
                        optodeState = optode_stateMachine(optodeState);

                        if(optodeState == 0)
                        {
                            tick2 = Timer_10ms(false);
                            optode_print_buf();        // uprintf("\n%s\n", optode.buf);
                            uprintf("\n\nOptode Read Time = %u ms  statemachine pump cycle = %u ms \n", (tick2-tick1)*10, sm_delay);

                            if(sm_delay > 0) sm_delay+=100;

                            if(sm_delay > 1500)
                                sm_delay = 0;

                            break;
                        }
                    }
                    uprintf("\n\n");
                    ROM_SysCtlDelay(MILLISECOND*300);
                }
                break;

            case 'o':
                if(sys_data.app_cfg[APPCFG_MENU_LEVEL] == 0)
                    break;
                uprintf("\nTest Optode (statemachine code):  Power Optode with 5v, wait for %, send crlf, wait for !, Send 'do sample', Receive, trim and print Optode sample terminated by #, turn power off \n\n");
                //int optodeState;
                //unsigned int tick1, tick2;
                tick1 = Timer_10ms(false);
                optodeState = 1;
                optodeState = optode_stateMachine(optodeState);

                while(1)
                {
                    optodeState = optode_stateMachine(optodeState);

                    if(optodeState == 0)
                    {
                        tick2 = Timer_10ms(false);
                        optode_print_buf();        // uprintf("\n%s\n", optode.buf);
                        uprintf("\n\nDebug Optode Read Time = %u ms \n", (tick2-tick1)*10);

                        break;
                    }
                }
                uprintf("\n\n");
                break;

            case 'p':
                if(sys_data.app_cfg[APPCFG_MENU_LEVEL] == 0)
                    break;
                optode_serial_analyzer();
                break;

            case 'q':
                if(sys_data.app_cfg[APPCFG_MENU_LEVEL] == 0)
                    break;
                ctd_aanderaa_serial_analyzer();
                break;

            case 'r':
                if(sys_data.app_cfg[APPCFG_MENU_LEVEL] == 0)
                    break;
                ctd_microcat_serial_analyzer();
                break;
#if BOARD_MPHOX >= 1
            case 'c':
                if(sys_data.app_cfg[APPCFG_MENU_LEVEL] == 0)
                    break;
                uprintf("\nTest Conductivity (statemachine code):  Power CTD with Vbat, wait for %% or 'S', Send 'do sample' or 'ts', receive and parse sample, turn power off \n\n");
                //uprintf("\nTest Conductivity (statemachine code):  Power CTD with Vbat, wait for %, send crlf, wait for !, Send 'do sample', Receive, trim and print Optode sample terminated by #, turn power off \n\n");
                tick1 = Timer_10ms(false);
                ctdState = 1;
                ctdState = ctd_stateMachine(ctdState);

                while(1)
                {
                    ctdState = ctd_stateMachine(ctdState);

                    if(ctdState == 0)
                    {
                        tick2 = Timer_10ms(false);
                        ctd_print_buf();        // uprintf("\n%s\n", ctd.buf);
                        uprintf("\n\nCTD Read Time = %u ms \n", (tick2-tick1)*10);

                        break;
                    }
                }
                uprintf("\n\n");
                wait_consoleTx();
                break;

            case 'C':
                if(sys_data.app_cfg[APPCFG_MENU_LEVEL] == 0)
                    break;

                sm_delay = 100;
                //sm_delay = 0;
                uprintf("\nLoop Test (%u msec) Conductivity (statemachine code):  Power CTD with Vbat, wait for %% or 'S', Send do 'sample' or 'ts', receive and parse sample, turn power off \n\n", sm_delay);


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

                        //if(charInput == 24)  // ctrl-x
                            break;

                    }
                    tick1 = Timer_10ms(false);
                    ctdState = 1;                           // start the machine again
                    ctdState = ctd_stateMachine(ctdState);


                    while(1)
                    {
                        if(sm_delay > 0) ROM_SysCtlDelay(MILLISECOND*sm_delay); // how often do we need to pump the statemachine
                        ctdState = ctd_stateMachine(ctdState);


                        if(ctdState == 0)
                        {
                            tick2 = Timer_10ms(false);
                            ctd_print_buf();        // uprintf("\n%s\n", ctd.buf);
                            uprintf("\n\nCTD Read Time = %u ms, statemachine pump cycle = %u ms \n", (tick2-tick1)*10, sm_delay);
                            if(sm_delay > 0) sm_delay+=100;
                            break;
                        }
                    }

                    uprintf("\n\n");
                    wait_consoleTx();
                    ROM_SysCtlDelay(MILLISECOND*300);
                }
                break;
#endif

            default: //Exit
                return;
        }
    }
}




int power_output_tests(void)
{
    time_t timer;
    char input;
    //unsigned int indx;


    // IO Test menu loop
    while(1)
    {
        uprintf("\n\n\nPower Output Test Menu -- %s\n", VERSION);
#if BOARD_MPHOX >= 1

        //uprintf("A/a -- AUX-PWR1 ON/off (J12 AUX-PWR1)\n");   // 16 Jul 2021
        uprintf("A/a -- Pump ON/off     (J12 AUX-PWR1)\n");
        uprintf("B/b -- AUX-PWR2 ON/off (J13 AUX-PWR2)\n");
        uprintf("C/c -- AUX-PWR3 ON/off (J14 COMM-PWR)\n");
        //uprintf("D/d -- Pump ON/off     (J12 AUX-PWR1)\n");
        uprintf("F/f -- 5v for Optode ON/off\n");

        uprintf("G/g -- Green LED\n");
        uprintf("R/r -- Red LED\n");

        uprintf("S/s -- Solenoid ON/off\n");
        //uprintf("P/p -- Solenoid PWM (hacked for 1KHz)\n");
        uprintf("\n");
#endif
#if BOARD_MFET >= 1
        uprintf("F/f -- 5v for Optode ON/off\n");

        uprintf("G/g -- Green LED\n");
        uprintf("R/r -- Red LED\n");

        //uprintf("P/p -- Solenoid PWM (hacked for 1KHz)\n");
        uprintf("\n");
#endif
        uprintf("9 -- Exit to Test Menu\n");
        uprintf("\nEnter Selection [9]: ");

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

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

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

        switch(input)
        {
            case 'A':  //J8
#if BOARD_MPHOX >= 1
                uprintf("AUX-PWR1 ON\n");
                pwr_aux_pwr1_on();
                break;
#endif
            case 'a':
#if BOARD_MPHOX >= 1
                uprintf("AUX-PWR1 OFF\n");
                pwr_aux_pwr1_off();
#endif
                break;

            case 'B':  //J12
#if BOARD_MPHOX >= 1
                //uprintf("B/b -- AUX1 ON\n");
                //AUX1_on();
                uprintf("AUX-PWR2 ON\n");
                pwr_aux_pwr2_on();
#endif
                break;
            case 'b':
#if BOARD_MPHOX >= 1
                //uprintf("B/b -- AUX1 off\n");
                //AUX1_off();
                uprintf("AUX-PWR2 OFF\n");
                pwr_aux_pwr2_off();
#endif
                break;

            case 'C':  // J13
#if BOARD_MPHOX >= 1
                //uprintf("C/c -- AUX2 ON\n");
                ///AUX2_on();
                uprintf("AUX-PWR3 ON (J14 COMM-PWR)\n");
                pwr_aux_pwr3_on();
#endif
                break;
            case 'c':
#if BOARD_MPHOX >= 1
                //uprintf("C/c -- AUX2 off\n");
                //AUX2_off();
                uprintf("AUX-PWR3 OFF (J14 COMM-PWR)\n");
                pwr_aux_pwr2_off();
#endif
                break;

            case 'D':  //J8
#if BOARD_MPHOX >= 1
                uprintf("Pump ON\n");
                pump_on();
#endif
                break;
            case 'd':
#if BOARD_MPHOX >= 1
                uprintf("Pump OFF\n");
                pump_off();
#endif
                break;

            case 'F':
                uprintf("F/f -- 5v for Optode ON\n");
                optode_open();
                break;
            case 'f':
                uprintf("F/f -- 5v for Optode off\n");
                optode_close();
                break;

            case 'G':
                uprintf("Green On\n");
                led_green(1);  //ROM_GPIOPinWrite(GPIO_PORTE_BASE, GPIO_PIN_3, 0xff);
                break;
            case 'g':
                uprintf("Green Off\n");
                led_green(0);   //ROM_GPIOPinWrite(GPIO_PORTE_BASE, GPIO_PIN_3, 0x00);
                break;
            case 'R':
                uprintf("Red On\n");
                led_red(1);     //ROM_GPIOPinWrite(GPIO_PORTP_BASE, GPIO_PIN_2, 0xff);
                break;
            case 'r':
                uprintf("Red Off\n");
                led_red(0);     //ROM_GPIOPinWrite(GPIO_PORTP_BASE, GPIO_PIN_2, 0x00);
                break;

            case 'S':
#if BOARD_MPHOX >= 1
                uprintf("Solenoid On (J9 SO/1)");
                pwr_so1n_on();       // J9 SO/1 silk on MPHOX  PG1,PG3
                ROM_GPIOPinWrite(GPIO_PORTG_BASE, GPIO_PIN_1, 0xff);
                ROM_GPIOPinWrite(GPIO_PORTG_BASE, GPIO_PIN_3, 0xff);

                //ROM_SysCtlDelay(MILLISECOND * sys_data.solenoid_on2hold_msec);
#endif
                break;

            case 's':
#if BOARD_MPHOX >= 1
                uprintf("Solenoid Off (J9 SO/1)");
                pwr_so1n_off();  //PG1,PG3
                //ROM_GPIOPinWrite(GPIO_PORTG_BASE, GPIO_PIN_1, 0x00);
                //ROM_GPIOPinWrite(GPIO_PORTG_BASE, GPIO_PIN_3, 0x00);
                //ROM_SysCtlDelay(MILLISECOND * 2000);
#endif
                break;

            case '9':
                return(1);

            default:
                //uprintf("key = %c\n\n", input);
                return(1);

        } // end switch

    }  // end IO Test menu loop

    return(1);
}



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


#if BOARD_MFET >= 1 || BOARD_MPHOX == 1
    uprintf("\niso power on, init ADG1609 mux\n\n");

    openADS1248_iso();      // 22msec

    ROM_SysCtlDelay(MILLISECOND * 100);
    ADS1248_gpio_init();    // defd in ADS1248_iso.c
#endif

#if BOARD_NANOFET >= 1
    uprintf("\nOpen nFET ADS1248 and ADG1609 mux\n\n");

    openADS1248_iso();      // 22msec  nanoFET is PD0 to PD3, MFET iso is PH0 to PH3
    ROM_SysCtlDelay(MILLISECOND * 100);

    ADS1248_gpio_init();    // defd in ADS1248_iso.c
#endif

    ROM_SysCtlDelay(MILLISECOND * 10);

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

    // Test menu loop
    while(1)
    {
        uprintf("\n\n\nTest pH (24bit ADC and Mux) Menu\n");
        uprintf("0 -- Vrsi    - ISFET Source (pH) Voltage wrt Int Ref\n");
        uprintf("1 -- Vrsi_B  - pH Volt Biased (pH 7 is 0v) wrt Int Ref\n");
        uprintf("2 -- Vrse    - ISFET Source (pH) Voltage wrt Ext Ref\n");
        uprintf("3 -- Vrse_B  - pH Volt Biased (pH 7 is 0v) wrt Ext Ref\n");
        uprintf("4 -- Ik      - Counter Electrode Current\n");  // Counter A and Counter B are current measurement Counter Electrode
        uprintf("5 -- Vk      - Counter Electrode Voltage wrt Ground\n");
        uprintf("6 -- Ib      - Substrate Current\n");
        uprintf("7 -- Vb      - Substrate Voltage (Depracated)\n");
        uprintf("8 -- Vtherm  - Thermistor Temperature\n");
        uprintf("S -- Sample all channels (0-8)\n");
        uprintf("X -- MCAP sample test (error check voltages), assumes Jensenian Analog Board\n");
        uprintf("9 -- Exit to Main Menu\n");
        uprintf("\nEnter Selection [9]: ");


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

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

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

#ifdef FUTURE  // todo, add timing and the ability to adjust ads1284 sample rate
        tickEnd = Timer_10ms(false);
        ticks = (tickEnd - tickStart)*10;
        //uprintf("(Time: %u msec)", ticks );
        if(sys_data.app_cfg[APPCFG_MENU_LEVEL] >= 1)  indx += sprintf(&prnBuf[indx], "(%u msec)\t", ticks);
#endif


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

                    uprintf("Vrsi   = %.6f V, Std = %.6f,  Samp = %04u,  Time = %04lu ms 5Hz\r\n", ADCResult, tempAD24_std, indx++, tick2);

                    tick1 = Timer_10ms(FALSE);
                    ADCResult = pollADS1248_iso(1, 6, sampleCnt, 1, 20);       // Chan +1 -6, trials = 1, gain = user, sps = 20 Hz
                    tick2 = (Timer_10ms(FALSE) - tick1) * 10;
                    tempAD24_std = sys_samp.AD24_std;

                    uprintf("Vrsi   = %.6f V, Std = %.6f,  Samp = %04u,  Time = %04lu ms 20Hz\n", ADCResult, tempAD24_std, indx++, tick2);
                }
                if( UARTRxBytesAvail() )
                {
                    input = get_key();
                    break;    // break from while(1)
                }
            }
            break;


            case '1':
                ADS1248_gpio_ADG1609_mux(3);
                indx = 0;
                Timer_10ms(TRUE);       // reset 10msec tick count
                sampleCnt = 10;
                sampTime = 0L;
                nextTime = 0L;
                uprintf("1 -- Vrsi_B (pH Int Ref with bias offset), Mux = 11,  AIN1+ AIN5, sampleCnt = %u for 5Hz and %u for 20Hz\n", sampleCnt, sampleCnt);
                while(1)
                {
                    sampTime = Timer_10ms(FALSE);
                    if(sampTime >= nextTime)
                    {
                        nextTime = sampTime + sampDelay;
                        tick1 = Timer_10ms(FALSE);
                        ADCResult = pollADS1248_iso(1, 5, sampleCnt, 1, 5);       // Chan +1 -5, trials = 1, gain = user, sps = 5 Hz
                        tick2 = (Timer_10ms(FALSE) - tick1) * 10;
                        tempAD24_std = sys_samp.AD24_std;

                        uprintf("Vrsi_B = %.6f V, Std = %.6f,  Samp = %04u,  Time = %04lu ms 5Hz\r\n", ADCResult, tempAD24_std, indx++, tick2);

                        tick1 = Timer_10ms(FALSE);
                        ADCResult = pollADS1248_iso(1, 5, sampleCnt, 1, 20);       // Chan +1 -5, trials = 1, gain = user, sps = 20 Hz
                        tick2 = (Timer_10ms(FALSE) - tick1) * 10;
                        tempAD24_std = sys_samp.AD24_std;

                        uprintf("Vrsi_B = %.6f V, Std = %.6f,  Samp = %04u,  Time = %04lu ms 20Hz\n", ADCResult, tempAD24_std, indx++, tick2);


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

            case '2':
                ADS1248_gpio_ADG1609_mux(0);
                indx = 0;
                Timer_10ms(TRUE);       // reset 10msec tick count
                sampleCnt = 10;
                sampTime = 0L;
                nextTime = 0L;
                uprintf("2 -- Vrse (pH Ext Ref) Voltage, Mux = 00,  AIN1+ AIN6-, sampleCnt = %u for 5Hz and %u for 20Hz\n", sampleCnt, sampleCnt);
                while(1)
                {
                    sampTime = Timer_10ms(FALSE);
                    if(sampTime >= nextTime)
                    {
                        nextTime = sampTime + sampDelay;
                        tick1 = Timer_10ms(FALSE);
                        ADCResult = pollADS1248_iso(1, 6, sampleCnt, 1, 5);       // Chan +1 -6, trials = 1, gain = user, sps = 5 Hz
                        tick2 = (Timer_10ms(FALSE) - tick1) * 10;
                        tempAD24_std = sys_samp.AD24_std;

                        uprintf("Vrse   = %.6f V, Std = %.6f,  Samp = %04u,  Time = %04lu ms 5Hz\r\n", ADCResult, tempAD24_std, indx++, tick2);

                        tick1 = Timer_10ms(FALSE);
                        ADCResult = pollADS1248_iso(1, 6, sampleCnt, 1, 20);       // Chan +1 -6, trials = 1, gain = user, sps = 5 Hz
                        tick2 = (Timer_10ms(FALSE) - tick1) * 10;
                        tempAD24_std = sys_samp.AD24_std;

                        uprintf("Vrse   = %.6f V, Std = %.6f,  Samp = %04u,  Time = %04lu ms 20Hz\n", ADCResult, tempAD24_std, indx++, tick2);
                    }
                    if( UARTRxBytesAvail() )
                    {
                        input = get_key();
                        break;    // break from while(1)
                    }
                }
                break;

            case '3':
                ADS1248_gpio_ADG1609_mux(0);
                indx = 0;
                Timer_10ms(TRUE);       // reset 10msec tick count
                sampleCnt = 10;
                sampTime = 0L;
                nextTime = 0L;
                uprintf("3 -- Vrse_B (pH Ext Ref with bias offset) Voltage, Mux = 00,  AIN1+ AIN6-, sampleCnt = %u for 5Hz and %u for 20Hz\n", sampleCnt, sampleCnt);

                while(1)
                {
                    sampTime = Timer_10ms(FALSE);
                    if(sampTime >= nextTime)
                    {
                        nextTime = sampTime + sampDelay;

                        tick1 = Timer_10ms(FALSE);
                        ADCResult = pollADS1248_iso(1, 5, sampleCnt, 1, 5);
                        tick2 = (Timer_10ms(FALSE) - tick1) * 10;
                        tempAD24_std = sys_samp.AD24_std;

                        uprintf("Vrse_B = %.6f V, Std = %.6f,  Samp = %04u,  Time = %04lu ms 5Hz\r\n", ADCResult, tempAD24_std, indx++, tick2);

                        tick1 = Timer_10ms(FALSE);
                        ADCResult = pollADS1248_iso(1, 5, sampleCnt, 1, 20);
                        tick2 = (Timer_10ms(FALSE) - tick1) * 10;
                        tempAD24_std = sys_samp.AD24_std;

                        uprintf("Vrse_B = %.6f V, Std = %.6f,  Samp = %04u,  Time = %04lu ms 20Hz\n", ADCResult, tempAD24_std, indx++, tick2);
                    }

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

            case '4':
                ADS1248_gpio_ADG1609_mux(1);
                indx = 0;
                Timer_10ms(TRUE);       // reset 10msec tick count
                sampleCnt = 10;
                sampTime = 0L;
                nextTime = 0L;
                uprintf("4 -- Ik (Counter Electrode Current), Mux = 01,  AIN1+ AIN5-, sampleCnt = %u for 5Hz and %u for 20Hz\n", sampleCnt, sampleCnt);
                while(1)
                {
                    sampTime = Timer_10ms(FALSE);
                    if(sampTime >= nextTime)
                    {
                        nextTime = sampTime + sampDelay;

                        tick1 = Timer_10ms(FALSE);
                        ADCResult = pollADS1248_iso(1, 5, sampleCnt, 1, 5);       // Chan +5 -1, trials = 1, gain = user, sps = 5 Hz
                        tick2 = (Timer_10ms(FALSE) - tick1) * 10;
                        tempAD24_std = sys_samp.AD24_std;

                        uprintf("Ik = (%.6f V / 15k) = %.2f nA , Std = %.6f V,  Samp = %04u,  Time = %04lu ms 5Hz\n", ADCResult, ADCResult*COUNTERELECTRODE_IK_SCALE, tempAD24_std, indx++, tick2);


                        tick1 = Timer_10ms(FALSE);
                        ADCResult = pollADS1248_iso(1, 5, sampleCnt, 1, 20);       // Chan +5 -1, trials = 1, gain = user, sps = 5 Hz
                        tick2 = (Timer_10ms(FALSE) - tick1) * 10;

                        tempAD24_std = sys_samp.AD24_std;

                        uprintf("Ik = (%.6f V / 15k) = %.2f nA , Std = %.6f V,  Samp = %04u,  Time = %04lu ms 20Hz\n", ADCResult, ADCResult*COUNTERELECTRODE_IK_SCALE, tempAD24_std, indx++, tick2);
                    }
                    if( UARTRxBytesAvail() )
                    {
                        input = get_key();
                        break;    // break from while(1)
                    }
                }
                break;

            case '5':
                ADS1248_gpio_ADG1609_mux(1);
                indx = 0;
                Timer_10ms(TRUE);       // reset 10msec tick count
                sampleCnt = 10;
                sampTime = 0L;
                nextTime = 0L;
                uprintf("5 -- Vk (Counter Electrode Voltage), Mux = 01,  AIN1+ AIN6-, sampleCnt = %u for 5Hz and %u for 20Hz\n", sampleCnt, sampleCnt);
                while(1)
                {
                    sampTime = Timer_10ms(FALSE);
                    if(sampTime >= nextTime)
                    {
                        tick1 = Timer_10ms(FALSE);
                        ADCResult = pollADS1248_iso(1, 6, sampleCnt, 1, 5);       // Chan +5 -1, trials = 1, gain = user, sps = 5 Hz
                        tick2 = (Timer_10ms(FALSE) - tick1) * 10;

                        tempAD24_std = sys_samp.AD24_std;

                        uprintf("Vk = %.6f V, Std = %.6f,  Samp = %04u,  Time = %04lu ms 5Hz\n", ADCResult, tempAD24_std, indx++, tick2);

                        tick1 = Timer_10ms(FALSE);
                        ADCResult = pollADS1248_iso(1, 6, sampleCnt, 1, 20);       // Chan +5 -1, trials = 1, gain = user, sps = 5 Hz
                        tick2 = (Timer_10ms(FALSE) - tick1) * 10;

                        tempAD24_std = sys_samp.AD24_std;

                        uprintf("Vk = %.6f V, Std = %.6f,  Samp = %04u,  Time = %04lu ms 20Hz\n", ADCResult, tempAD24_std, indx++, tick2);

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

            case '6':
                ADS1248_gpio_ADG1609_mux(2);
                indx = 0;
                Timer_10ms(TRUE);       // reset 10msec tick count
                sampleCnt = 10;
                sampTime = 0L;
                nextTime = 0L;
                uprintf("6 -- Ib Substrate Current (voltage across 1M resistor), Mux = 10,  AIN1+ AIN6-, sampleCnt = %u for 5Hz and %u for 20Hz\n", sampleCnt, sampleCnt);
                while(1)
                {
                    sampTime = Timer_10ms(FALSE);
                    if(sampTime >= nextTime)
                    {
                        nextTime = sampTime + sampDelay;

                        //SUBSTRATECURRENT_IB_SCALING is defd in system.h
                        tick1 = Timer_10ms(FALSE);
                        ADCResult = pollADS1248_iso(1, 6, sampleCnt, 1, 5);
                        tick2 = (Timer_10ms(FALSE) - tick1) * 10;
                        //uprintf("Ib= %.6f V, Vb Std = %.6f,  Samp = %04u,  Time = %04lu ms 5Hz\n", ADCResult/IB_RESISTOR, sys_data.AD24_std, indx++, tick2);
                        tempAD24_std = sys_samp.AD24_std;

                        uprintf("Vb= %.6f V, Ib= %.3f nA, Vb Std = %.6f,  Samp = %04u,  Time = %04lu ms 5Hz\n", ADCResult, ADCResult*SUBSTRATECURRENT_IB_SCALING, tempAD24_std, indx++, tick2);


                        tick1 = Timer_10ms(FALSE);
                        ADCResult = pollADS1248_iso(1, 6, sampleCnt, 1, 20);
                        tick2 = (Timer_10ms(FALSE) - tick1) * 10;
                        tempAD24_std = sys_samp.AD24_std;

                        uprintf("Vb= %.6f V, Ib= %.3f nA, Vb Std = %.6f,  Samp = %04u,  Time = %04lu ms 20Hz\n", ADCResult, ADCResult*SUBSTRATECURRENT_IB_SCALING, tempAD24_std, indx++, tick2);

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

            case '7':
                ADS1248_gpio_ADG1609_mux(2);
                indx = 0;
                Timer_10ms(TRUE);       // reset 10msec tick count
                sampleCnt = 10;
                sampTime = 0L;
                nextTime = 0L;
                uprintf("7 -- Substrate Voltage, Mux = 10,  AIN5+ AIN6-, sampleCnt = %u for 5Hz and %u for 20Hz\n", sampleCnt, sampleCnt);

                while(1)
                {
                    sampTime = Timer_10ms(FALSE);
                    if(sampTime >= nextTime)
                    {
                        nextTime = sampTime + sampDelay;

                        tick1 = Timer_10ms(FALSE);
                        ADCResult = pollADS1248_iso(5, 6, sampleCnt, 1, 5);
                        tick2 = (Timer_10ms(FALSE) - tick1) * 10;

                        tempAD24_std = sys_samp.AD24_std;

                        uprintf("Vsubstrate = %.6f V, Vb Std = %.6f,  Samp = %04u,  Time = %04lu ms 5Hz\n", ADCResult, tempAD24_std, indx++, tick2);

                        tick1 = Timer_10ms(FALSE);
                        ADCResult = pollADS1248_iso(5, 6, sampleCnt, 1, 20);
                        tick2 = (Timer_10ms(FALSE) - tick1) * 10;

                        tempAD24_std = sys_samp.AD24_std;

                        uprintf("Vsubstrate = %.6f V, Vb Std = %.6f,  Samp = %04u,  Time = %04lu ms 20Hz\n", ADCResult, tempAD24_std, indx++, tick2);

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

            case '8':
                ADS1248_gpio_ADG1609_mux(0);        // Not necessary, but consistent
                indx = 0;
                Timer_10ms(TRUE);       // reset 10msec tick count
                sampleCnt = 10;
                sampTime = 0L;
                nextTime = 0L;
                uprintf("8 -- Thermistor ISFET Temperature, Mux = XX,  AIN0+ AIN6-, sampleCnt = %u for 5Hz and %u for 20Hz\n", sampleCnt, sampleCnt);
                while(1)
                {
                    sampTime = Timer_10ms(FALSE);
                    if(sampTime >= nextTime)
                    {
                        nextTime = sampTime + sampDelay;

                        tick1 = Timer_10ms(FALSE);
                        ADCResult = pollADS1248_iso(0, 6, sampleCnt, 1, 5);
                        tick2 = (Timer_10ms(FALSE) - tick1) * 10;
                        tempAD24_std = sys_samp.AD24_std;

                        uprintf("Vtherm = %.6f V, Vb Std = %.6f,  Samp = %04u,  Time = %04lu ms 5Hz\n", ADCResult, tempAD24_std, indx++, tick2);

                        tick1 = Timer_10ms(FALSE);
                        ADCResult = pollADS1248_iso(0, 6, sampleCnt, 1, 20);
                        tick2 = (Timer_10ms(FALSE) - tick1) * 10;
                        tempAD24_std = sys_samp.AD24_std;

                        uprintf("Vtherm = %.6f V, Vb Std = %.6f,  Samp = %04u,  Time = %04lu ms 20Hz\n", ADCResult, tempAD24_std, indx++, tick2);

                    }
                    if( UARTRxBytesAvail() )
                    {
                        input = get_key();
                        break;    // break from while(1)
                    }
                }
                break;
#ifdef NOCODE
            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;
#endif

            case 'S':
            case 's':

                //   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
#if BOARD_MFET >= 1 || BOARD_MPHOX >= 1
                //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");

                           //    Date Time,         Vrsi,      Vrsi_B,    Vrse,       Vrse_B,      Ik,         Vk,         Ib,        Vb,     VTherm
                           //04/24/21 10:26:00,  -0.055155,  0.674927,  -0.799240,  -0.069124,  0.272970,  -0.500551,  -0.399626,  0.000691,  0.997603
                uprintf("\n\n    Date Time,         Vrsi,      Vrsi_B,    Vrse,       Vrse_B,      Ik,         Vk,         Ib,        Vb,     VTherm\n");

#endif

#if BOARD_NANOFET >= 1
                uprintf("\n\n    Date Time,         Vrse,        Ik,       Vk,           Ib,       Vb,       Vtherm\n");
#endif

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

                        // Date Time,
                        printCurrentTime();

                        uprintf(", ");
#if BOARD_MFET >= 1 || BOARD_MPHOX >= 1
                        //Vrsi   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

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

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

                        //Vrse_B   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
#endif
#if BOARD_NANOFET >= 1
                        //Ext Ref V,
                        ADS1248_gpio_ADG1609_mux(0);
                        ROM_SysCtlDelay(MILLISECOND * 10);      // 10msec settling for MUX analog
                        ADCResult = pollADS1248_iso(1, 5, sampleCnt, 1, 5);       // Chan +1 -6, trials = 1, gain = user, sps = 5 Hz
                        uprintf(" %.6f, ", ADCResult);       // Ext Ref Voltage
#endif

                        //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(" %.2f, ", ADCResult*COUNTERELECTRODE_IK_SCALE);       // 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(" %.3f, ", ADCResult*SUBSTRATECURRENT_IB_SCALING);       // 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
                //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");

                uprintf("\n\n");
                if(sys_data.diag == 1)
                {
                    uprintf("               MIN: %.6f,  %.6f,  %.6f,  %.6f,  %.6f,  %.6f,  %.6f,  %.6f,  %.6f\n", VRSI_MIN, VRSI_B_MIN, VRSE_MIN, VRSE_B_MIN, IK_MIN, VK_MIN, IB_MIN, VB_MIN, VTHERM_MIN);
                    uprintf("               MAX: %.6f,  %.6f,  %.6f,  %.6f,  %.6f,  %.6f,  %.6f,  %.6f,  %.6f\n", VRSI_MAX, VRSI_B_MAX, VRSE_MAX, VRSE_B_MAX, IK_MAX, VK_MAX, IB_MAX, VB_MAX, VTHERM_MAX);
                    uprintf("    Date Time,         Vrsi,     Vrsi_B,     Vrse,      Vrse_B,       Ik,        Vk,         Ib,        Vb,       VTherm\n");
                }
                else
                {
                    uprintf("               MIN: %.6f,  %.6f,  %.6f,  %.6f,  %.6f,  %.6f,  %.6f,  %.6f\n", VRSI_MIN, VRSI_B_MIN, VRSE_MIN, VRSE_B_MIN, IK_MIN, VK_MIN, IB_MIN, VTHERM_MIN);
                    uprintf("               MAX: %.6f,  %.6f,  %.6f,  %.6f,  %.6f,  %.6f,  %.6f,  %.6f\n", VRSI_MAX, VRSI_B_MAX, VRSE_MAX, VRSE_B_MAX, IK_MAX, VK_MAX, IB_MAX, VTHERM_MAX);
                    uprintf("    Date Time,         Vrsi,     Vrsi_B,     Vrse,      Vrse_B,       Ik,        Vk,         Ib,       VTherm\n");
                }

                indx = 0;
                Timer_10ms(TRUE);       // reset 10msec tick count
                sampDelay = 500L;
                sampleCnt = 10;
                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);
                        test_sampling_mcap(0);

                    }


                    if( UARTRxBytesAvail() )
                    {
                        input = get_key();
                        break;    // break from while(1)
                    }
                }
                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");
}





int board_qa_and_init(int initFlg)
{

    float ftemp;
    unsigned int temp;
    unsigned int eeSize;
    time_t current_time;

    FIL fileObject;     // File object
    FRESULT fresult;
    UINT bw;
    int retVal;

    char timeStamp[TIMESTAMPLENGTH];
    struct tm *time_struct;

    int verboseFlg;
    int response;

    char qaFilename[16];
    char buff[128];

    //uint32_t    ctd;
    //uint32_t    optode;
    //uint32_t    comm_pwr;

    //char        tester[MAX_TESTER_NAME];



    verboseFlg = 0;

    // RTC: set clock, read clock.   Later clock should be tested after power has been shut off.   The board should never drop time - 3yr to 5yr battery life (unless bad battery or bad board)

    // get tester name

    // check if the EEPROM size is big enough for sys_data

    // initialize sys_data defaults, test EEPROM

    // set filename (set metadata)

    // test uSD card

    // test the adc24 ADS1248

    // check the board level sensors

    // check fram

    // check outputs

    // check communication ports with instrument sims

    uprintf("\nQA: ----- EEPROM / sys_data init -----\n");
    // initialize EEPROM sys_data with defaults
    if(initFlg == 1)
    {

        sys_data.qa.sys_data_init = 0;      // was the data initialized
        //uprintf("\nQA: Initializing sys_data variables in EEPROM to defaults\n");

        config_sys_data_default_init();   // initialize entire sys_data with defaults (zero's out sys_data.qa data fields)

        sys_data.qa.eeprom = 0;
        eeSize = EEPROMSizeGet(); // Get EEPROM Size
        if(verboseFlg == 1) uprintf("EEPROM Size %d bytes\n", eeSize);
        temp = sizeof(struct systemData);
        if(verboseFlg == 1) uprintf("sizeof sys_data in EEPROM = %u\n", temp);
        if(eeSize >= temp)
        {
            sys_data.qa.eeprom = (uint32_t)temp;      // eeprom is non-zero if EEPROM passes test
            uprintf("   Pass EEPROM (sys_data size %u)\n", sys_data.qa.eeprom);
            uprintf("   Pass sys_data init\n");
        }
        else
        {
            uprintf("   Fail EEPROM:  %u is less than sys_data size of %u\n", eeSize, temp);
            sys_data.qa.eeprom = 0;     // 0 is fail
            uprintf("   Fail sys_data init\n");
        }

        strcpy(sys_data.qa.firmware_version, VERSION);


        sys_data.qa.sys_data_init = 1;      // was the data initialized
        if(verboseFlg == 1) uprintf("\nQA: Print sys_data structure\n");
        if(verboseFlg == 1) print_sys_data_structure();     // print it

        if(verboseFlg == 1) uprintf("\nQA: Print data field configuration\n");
        if(verboseFlg == 1) print_config_data_fields();
        if(verboseFlg == 1) uprintf("\n");

        if(verboseFlg == 1) uprintf("\nQA: Print data header\n");
        if(verboseFlg == 1) print_data_header();
        if(verboseFlg == 1) uprintf("\n");



        sys_data.qa.fram = 0;
        if(fram_probe() == 0xAA55AA55)
        {
            sys_data.qa.fram = 1;
            uprintf("   Pass FRAM\n");
        }
        else
        {
            uprintf("   Fail FRAM.   This board cannot be used for science\n");
        }

        if(verboseFlg == 1) uprintf("Initialize sys_samp variables in FRAM to defaults\n");
        initSysSampFRAMVariables();


    }



    // TODO 2 Jun 2021 There is a bug with string print of sys_data.qa.tester
    uprintf("\nEnter Tester Name (your name will be added to the lottery drawing) [%s]: ", sys_data.qa.tester);
    if( getUserInput(buff, MAX_TESTER_NAME-2) )       //  48
    {
        //uprintf("buff = [%s]\n", buff);
        int indx;
        for(indx=0; indx< MAX_TESTER_NAME; indx++)
        {
            sys_data.qa.tester[indx] = buff[indx]; //strcpy(sys_data.qa.tester, buff);
            if(buff[indx] == 0)
            {
                //uprintf("sys_data.qa.tester string size is %d\n", indx);
                break;
            }
        }

        uprintf("\nTester name recorded as: %s.  Welcome to Quality Assurance!\n", sys_data.qa.tester);
    }

    //uprintf("\nTester Debug 1 [%s]\n", sys_data.qa.tester);

    // RTC: set clock, read clock.   Later clock should be tested after power has been shut off.   The board should never drop time - 3yr to 5yr battery life (unless bad battery or bad board)
    uprintf("\nQA: ----- RTC test -----\n");
    sys_data.GMT = false;

    current_time = getDateAndTime();        // user enters time
    if(current_time)
    {
        // only when time is entered
        ROM_HibernateRTCSet(current_time); // Set time if user entered valid time
        uprintf("\nTime now: ");
        printCurrentTime();
        if(sys_data.GMT)
            uprintf(" GMT\n");
        else
            uprintf(" Local\n");

    }

    uprintf("\n");

    current_time = ROM_HibernateRTCGet();
    sys_data.qa.time = current_time;        //time of QA

    time_struct = localtime((const time_t*)&sys_data.qa.time);

    // DEBUG to print the time
    strftime(timeStamp, sizeof(timeStamp),"%m/%d/%y %H:%M:%S", time_struct);
    uprintf("   Test timestamp:  %s", timeStamp);

    uprintf("\nQA: ----- microSD test -----\n");

    sys_data.qa.microSD = 0;
    sprintf(qaFilename, "qaMMDDYY.txt", current_time%10000);
    qaFilename[2] = timeStamp[0];
    qaFilename[3] = timeStamp[1];
    qaFilename[4] = timeStamp[3];
    qaFilename[5] = timeStamp[4];
    qaFilename[6] = timeStamp[6];
    qaFilename[7] = timeStamp[7];



    //uprintf("DEBUG: qaFilename is %s\n", qaFilename);
    // Open a file
    fresult = f_open(&fileObject, qaFilename, FA_READ |FA_WRITE |FA_OPEN_ALWAYS);
    if(fresult != FR_OK)
    {
        //uprintf("f_open error: %s\n", StringFromFresult(fresult));
        uprintf("QA file failed to open, check microSD card slot for 8GB uSD\n");
        //error_store("f_open error");
    }
    else
    {
        // Seek to the end, to append our file
        fresult = f_lseek(&fileObject, fileObject.fsize);
        if(fresult != FR_OK)
        {
            uprintf("f_lseek error: %s\n", StringFromFresult(fresult));
            error_store("f_lseek error");
        }
        else
        {
            // Write the formatted data string in the prnBuf buffer to the SD card
            fresult = f_write( &fileObject, prnBuf, strlen(prnBuf), (UINT*)&bw);
            if(fresult != FR_OK)
            {
                uprintf("  Fail: f_write error: %s\n", StringFromFresult(fresult));
            }
            else
            {
                sys_data.qa.microSD = 1;
                uprintf("  Passed\n");
            }
        }
    }

    // Close the file
    fresult = f_close( &fileObject );
    if(fresult != FR_OK)
    {
        uprintf("   Fail: f_close error: %s\n", StringFromFresult(fresult));
        error_store("f_close error");
    }

    //uprintf("\nTester Debug 2 [%s]\n", sys_data.qa.tester);

    //sys_data init used to be here

    uprintf("\nQA: --------- Enter Meta Data  --------------\n");

    while(1)
    {
        enter_metadata();     // get user input and set metadata fields

        //uprintf("Redo metadata entry (Y/N) [N]: ");

        uprintf("\n\n");

        response = yesOrNoMenuChoice("Redo metadata entry (Y/N) [N]:  ", NO);
        if(response == YES)
        {
            uprintf("\nwell ok, re-enter the metadata\n\n");
        }
        else
        {
            break;
        }

    }

    if(verboseFlg == 1) uprintf("\nQA: Print Meta Data\n");
    if(verboseFlg == 1) print_all_metadata();


    // test the uSD card and print settings to the screen
    if( print_write_metadata_header(sys_data.qa.time, 1, 1) )
    {
        sys_data.qa.microSD = 0;
        uprintf("FAIL: Not able to write metadata, File system error, check SD Card\n");
    }

    uprintf("\nQA: about to turn iso power on - note current now on 12v supply\n");

    //uprintf("\nTester Debug 3 [%s]\n", sys_data.qa.tester);

    uprintf("\nQA: hit any key, additional current of 2mA to 3mA is expected, more or less is a Fail.\n");
    while(1)
    {
        if( UARTRxBytesAvail() )
        {
            get_key();
            break;    // break from while(1)
        }
    }

    //-----------------------------
    uprintf("checking bias battery and onboard environmental sensors: bias batteries should be above 3.55v\n\n");
    display_battery_boardSensors();

    sys_data.qa.Vbias_pos = fBiasPos;   //globals
    sys_data.qa.Vbias_neg = fBiasNeg;

    uprintf("\nAnalog to Digital test: iso power on, adg1609 mux init'd, reading ads1284 adc and testing analog frontend against expected variation \n\n");


    openADS1248_iso();      // 22msec
    ROM_SysCtlDelay(MILLISECOND * 100);
    ADS1248_gpio_init();    // defd in ADS1248_iso.c
    ROM_SysCtlDelay(MILLISECOND * 10);


    uint32_t sampDelay;
    uint32_t sampTime;
    uint32_t nextTime;
    char input;

    //indx = 0;
    sampDelay = 500L;
    Timer_10ms(TRUE);       // reset 10msec tick count
    //sampleCnt = 10;
    sampTime = 0L;
    nextTime = 0L;

    uprintf("\nThe 24bit ADC QA test assumes an analog sim, aka Jensenian v2, is connected to the MCAP.   To end MCAP test, Hit a key, then wait for sample row to finish\n");
    sys_data.qa.adc24 = 10;  // pre-load with 10 errors
    if(sys_data.app_cfg[APPCFG_MENU_LEVEL] == 1) uprintf("\n\n    Date Time,         Vrsi,     Vrsi_B,     Vrse,      Vrse_B,       Ik,        Vk,         Ib,        Vb,       VTherm\n");
    else uprintf("\n\n    Date Time,         Vrsi,     Vrsi_B,     Vrse,      Vrse_B,       Ik,        Vk,         Ib,       VTherm\n");
    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);
            sys_data.qa.adc24 = test_sampling_mcap(1); // checks for errors in voltage readings
        }

        if( UARTRxBytesAvail() )
        {
            if(sys_data.qa.adc24 > 0)
                uprintf("sys_data.qa.adc24 error count = %u\n", sys_data.qa.adc24);
            input = get_key();
            break;    // break from while(1)
        }
    }

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

    //uprintf("\nTester Debug 4 [%s]\n", sys_data.qa.tester);



    sys_data.qa.aux_pwr1 = 0;
    sys_data.qa.aux_pwr2 = 0;
    sys_data.qa.aux_pwr3 = 0;

    sys_data.qa.ctd = 0;
    sys_data.qa.optode = 0;
    sys_data.qa.comm_pwr = 0;
#if BOARD_MPHOX >= 1
    // test aux power

    // test ctd
    uprintf("\nQA: ------- Testing External Instrument interfaces -------\n");

    sys_data.qa.ctd = ctd_qa_test(); // return 1 for success, 0 for fail
    if(sys_data.qa.ctd > 0)
        uprintf("  CTD interface passed\n");
    else
        uprintf("  CTD interface failed\n");


    // test comm pwr

#endif
#if BOARD_MPHOX >= 1 || BOARD_MFET >= 2
    // test optode
    sys_data.qa.optode = optode_qa_test();
    if(sys_data.qa.ctd > 0)
        uprintf("  Optode interface passed\n");
    else
        uprintf("  Optode interface failed\n");
#endif
    uprintf("\n");
    //sys_data.qa.time;

    // Write the sys_data struct into EEPROM.
    if(storeSysDataVariables() == 0)         // return 0 on success
    {
        uprintf("QA data written to EEPROM, use Test menu to see QA report\n");
    }
    else
    {
        sys_data.qa.sys_data_init = 0;
        sys_data.qa.eeprom = 0;
        uprintf("\n\nError storing system data in EEPROM\n");

    }

    sys_data.qa.test_time = ROM_HibernateRTCGet() - sys_data.qa.time;

    uprintf("Elapsed time %u sec\n", sys_data.qa.test_time);

    uprintf("\n\n----- QA Procedure complete, QA Report:  -----\n\n");


    print_qa_report();


    uprintf("\n\nThankyou %s, your QA time was %u sec.  Have a nice day.\n\n", sys_data.qa.tester, sys_data.qa.test_time);

    return(1);
}

void print_qa_report(void)
{
    char timeStamp[TIMESTAMPLENGTH];
    struct tm *time_struct;


    uprintf("Tester: %s\n", sys_data.qa.tester);
    uprintf("Firmware version: %s\n", sys_data.qa.firmware_version);
    uprintf("Test time = %u sec\n", sys_data.qa.test_time);

    time_struct = localtime((const time_t*)&sys_data.qa.time);
    strftime(timeStamp, sizeof(timeStamp),"%m/%d/%y %H:%M:%S", time_struct);
    uprintf("Test timestamp:  %s\n", timeStamp);

    if(sys_data.qa.microSD > 0)
        uprintf("microSD passed\n");
    else
        uprintf("microSD failed\n");

    if(sys_data.qa.eeprom > 0)
    {
        uprintf("EEPROM passed\n");
    }
    else
    {
        uprintf("EEPROM failed\n");
    }

    if(sys_data.qa.sys_data_init > 0)
        uprintf("sys_data initialized, passed\n");
    else
        uprintf("sys_data NOT initialized, failed\n");

    if(sys_data.qa.fram > 0)
        uprintf("FRAM passed\n");
    else
        uprintf("FRAM failed\n");
#if BOARD_MPHOX >= 1
    if(sys_data.qa.aux_pwr1 > 0)
        uprintf("Aux Pwr1 passed\n");
    else
        uprintf("Aux Pwr1 failed\n");

    if(sys_data.qa.aux_pwr2 > 0)
        uprintf("Aux Pwr2 passed\n");
    else
        uprintf("Aux Pwr2 failed\n");

    if(sys_data.qa.aux_pwr3 > 0)
        uprintf("Aux Pwr3 passed\n");
    else
        uprintf("Aux Pwr3 failed\n");

    if(sys_data.qa.ctd > 0)
        uprintf("CTD passed\n");
    else
        uprintf("CTD failed\n");
#endif
#if BOARD_MPHOX >= 1 || BOARD_MFET >= 2
    if(sys_data.qa.optode > 0)
        uprintf("Optode passed\n");
    else
        uprintf("Optode failed\n");
#endif

#if BOARD_MPHOX >= 1
    if(sys_data.qa.comm_pwr > 0)
        uprintf("Comm Pwr passed\n");
    else
        uprintf("Comm Pwr failed\n");
#endif
    uprintf("ADC24 report:\n");

    uprintf("\tADCerr  \t Vrsi   \tVrsiStd \tVrsiErr \t  Vrse  \tVrseStd \tVrseErr \tVtherm  \tVthrmStd\tVthrmErr");
    if(sys_data.app_cfg[APPCFG_MENU_LEVEL] == 0) uprintf("\t  Ik    \t Ik_std \t Ik_err \t  Vk    \t Vk_std \t Vk_err \t   Ib   \t  Ib_std\t Ib_err \t Vbias+ \t  Vbias-\n");
    if(sys_data.app_cfg[APPCFG_MENU_LEVEL] == 1) uprintf("\t  Ik    \t Ik_std \t Ik_err \t  Vk    \t Vk_std \t Vk_err \t   Ib   \t  Ib_std\t Ib_err \t   Vb   \t  Vb_std \t Vb_err \t Vbias+ \t Vbias-\n");

    uprintf("\t  %3u   \t", sys_data.qa.adc24);
    uprintf("%8.6f\t", sys_data.qa.Vrsi);
    uprintf("%8.6f\t", sys_data.qa.Vrsi_std);
    uprintf("%8.6f\t", sys_data.qa.Vrsi_err);
    uprintf("%8.6f\t", sys_data.qa.Vrse);
    uprintf("%8.6f\t", sys_data.qa.Vrse_std);
    uprintf("%8.6f\t", sys_data.qa.Vrse_err);
    uprintf("%8.6f\t", sys_data.qa.Vtherm);
    uprintf("%8.6f\t", sys_data.qa.Vtherm_std);
    uprintf("%8.6f\t", sys_data.qa.Vtherm_err);

    //uprintf("\n");

    //if(sys_data.app_cfg[APPCFG_MENU_LEVEL] == 0) uprintf("\t  Ik    \t Ik_std \t Ik_err \t  Vk    \t Vk_std \t Vk_err \t   Ib   \t  Ib_std\t Ib_err \t Vbias+ \t  Vbias-\n");
    //if(sys_data.app_cfg[APPCFG_MENU_LEVEL] == 1) uprintf("\t  Ik    \t Ik_std \t Ik_err \t  Vk    \t Vk_std \t Vk_err \t   Ib   \t  Ib_std\t Ib_err \t   Vb   \t  Vb_std \t Vb_err \t Vbias+ \t Vbias-\n");

    uprintf("%8.6f\t", sys_data.qa.Ik);
    uprintf("%8.6f\t", sys_data.qa.Ik_std);
    uprintf("%8.6f\t", sys_data.qa.Ik_err);

    uprintf("%8.6f\t", sys_data.qa.Vk);
    uprintf("%8.6f\t", sys_data.qa.Vk_std);
    uprintf("%8.6f\t", sys_data.qa.Vk_err);

    uprintf("%8.6f\t", sys_data.qa.Ib);
    uprintf("%8.6f\t", sys_data.qa.Ib_std);
    uprintf("%8.6f\t", sys_data.qa.Ib_err);

    if(sys_data.app_cfg[APPCFG_MENU_LEVEL] == 1)
    {
        uprintf("%8.6f\t", sys_data.qa.Vb);
        uprintf("%8.6f\t", sys_data.qa.Vb_std);
        uprintf("%8.6f\t", sys_data.qa.Vb_err);
    }

    uprintf("%8.3f\t", sys_data.qa.Vbias_pos);
    uprintf("%8.3f\t", sys_data.qa.Vbias_neg);
    uprintf("\n");


}



//------------------------ The Basement ------------------------------------


int test_sampling_mcap(int qaFlg)        // changed to DEFINES in test.h from nois analysis

{
    float delta;
    float ADCResult;
    int sampleCnt;
    int error;
    int debugFlg = 0;

    error = 0;

    sampleCnt = 1;
    if(qaFlg >= 1)
        sampleCnt = 5;


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



    // Vrsi   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);       // Vrsi Voltage
    if(qaFlg >= 1) sys_data.qa.Vrsi = ADCResult;
    if(qaFlg >= 1) sys_data.qa.Vrsi_std = sys_samp.AD24_std;
    //if((ADCResult > (intRefV+delta))  || (ADCResult < (intRefV-delta)))
    if((ADCResult < VRSI_MIN)  || (ADCResult > VRSI_MAX))
    {
        if(ADCResult < VRSI_MIN)
            if(qaFlg >= 1) sys_data.qa.Vrsi_err = ADCResult - VRSI_MIN;
        else
            if(qaFlg >= 1) sys_data.qa.Vrsi_err = VRSI_MAX - ADCResult;
        uprintf(" Err ");
        if(debugFlg) uprintf("Vrsi(min %.6f < %.6f < max %.6f) ", VRSI_MIN, ADCResult, VRSI_MAX);
        error++;
    }


    //Vrsi_B   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 < VRSI_B_MIN)  || (ADCResult > VRSI_B_MAX))
    {
        uprintf(" Err ");
        if(debugFlg) uprintf("Vrsi_B(min %.6f < %.6f < max %.6f) ", VRSI_B_MIN, ADCResult, VRSI_B_MAX);
        error++;
    }


    //Vrse   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
    if(qaFlg >= 1) sys_data.qa.Vrse = ADCResult;
    if(qaFlg >= 1) sys_data.qa.Vrse_std = sys_samp.AD24_std;
    uprintf(" %.6f, ", ADCResult);       // Ext Ref Voltage
    //if((ADCResult > (extRefV+delta))  || (ADCResult < (extRefV-delta)))
    if((ADCResult < VRSE_MIN)  || (ADCResult > VRSE_MAX))
    {
        if(ADCResult < VRSE_MIN)
            if(qaFlg >= 1) sys_data.qa.Vrse_err = ADCResult - VRSE_MIN;
        else
            if(qaFlg >= 1) sys_data.qa.Vrse_err = VRSE_MAX - ADCResult;
        uprintf(" Err ");
        if(debugFlg) uprintf("Vrse(min %.6f < %.6f < max %.6f) ", VRSE_MIN, ADCResult, VRSE_MAX);
        error++;
    }

    //Vrse_B   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)))
    if((ADCResult < VRSE_B_MIN)  || (ADCResult > VRSE_B_MAX))
    {
        uprintf(" Err ");
        if(debugFlg) uprintf("Vrse_B(min %.6f < %.6f < max %.6f) ", VRSE_B_MIN, ADCResult, VRSE_B_MAX);
        error++;
    }


    //Ik   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
    if(qaFlg >= 1) sys_data.qa.Ik = ADCResult;
    if(qaFlg >= 1) sys_data.qa.Ik_std = sys_samp.AD24_std;
    uprintf(" %.6f, ", ADCResult);       // Counter Electrode Current
    if((ADCResult < IK_MIN)  || (ADCResult > IK_MAX))
    {
        if(ADCResult < IK_MIN)
            if(qaFlg >= 1) sys_data.qa.Ik_err = ADCResult - IK_MIN;
        else
            if(qaFlg >= 1) sys_data.qa.Ik_err = IK_MAX - ADCResult;
        uprintf(" Err ");
        if(debugFlg) uprintf("Ik(min %.6f < %.6f < max %.6f) ", IK_MIN, ADCResult, IK_MAX);
        error++;
    }


    // Vk  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
    if(qaFlg >= 1) sys_data.qa.Vk = ADCResult;
    if(qaFlg >= 1) sys_data.qa.Vk_std = sys_samp.AD24_std;
    uprintf(" %.6f, ", ADCResult);       // Counter Electrode Voltage
    if((ADCResult < VK_MIN)  || (ADCResult > VK_MAX))
    {
        if(ADCResult < VK_MIN)
            if(qaFlg >= 1) sys_data.qa.Vk_err = ADCResult - VK_MIN;
        else
            if(qaFlg >= 1) sys_data.qa.Vk_err = VK_MAX - ADCResult;
        uprintf(" Err ");
        if(debugFlg) uprintf("Vk(min %.6f < %.6f < max %.6f) ", VK_MIN, ADCResult, VK_MAX);
        error++;
    }


    // Ib   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
    if(qaFlg >= 1) sys_data.qa.Ib = ADCResult;
    if(qaFlg >= 1) sys_data.qa.Ib_std = sys_samp.AD24_std;
    uprintf(" %.6f, ", ADCResult);       // Substrate Current
    if((ADCResult < IB_MIN)  || (ADCResult > IB_MAX))
    {
        if(ADCResult < IB_MIN)
            if(qaFlg >= 1) sys_data.qa.Ib_err = ADCResult - IB_MIN;
        else
            if(qaFlg >= 1) sys_data.qa.Ib_err = IB_MAX - ADCResult;
        uprintf(" Err ");
        if(debugFlg) uprintf("Ib(min %.6f < %.6f < max %.6f) ", IB_MIN, ADCResult, IB_MAX);
        error++;
    }

    if(qaFlg >= 1) sys_data.qa.Vb = 0.0;
    if(qaFlg >= 1) sys_data.qa.Vb_std = 0.0;
    if(qaFlg >= 1) sys_data.qa.Vb_err = 0.0;
    if(sys_data.app_cfg[APPCFG_MENU_LEVEL] >= 1)
    {
        // VB  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
        if(qaFlg >= 1) sys_data.qa.Vb = ADCResult;
        if(qaFlg >= 1) sys_data.qa.Vb_std = sys_samp.AD24_std;
        uprintf(" %.6f, ", ADCResult);       // Substrate Voltage
        if((ADCResult < VB_MIN)  || (ADCResult > VB_MAX))
        {
            if(ADCResult < VB_MIN)
                if(qaFlg >= 1) sys_data.qa.Vb_err = ADCResult - VB_MIN;
            else
                if(qaFlg >= 1) sys_data.qa.Vb_err = VB_MAX - ADCResult;
            uprintf(" Err ");
            if(debugFlg) uprintf("Vb(min %.6f < %.6f < max %.6f) ", VB_MIN, ADCResult, VB_MAX);
            error++;
        }
    }


    // Vtherm 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
    if(qaFlg >= 1) sys_data.qa.Vtherm = ADCResult;
    if(qaFlg >= 1) sys_data.qa.Vtherm_std = sys_samp.AD24_std;
    uprintf(" %.6f", ADCResult);       // Substrate Voltage
    if((ADCResult < VTHERM_MIN)  || (ADCResult > VTHERM_MAX))
    {
        if(ADCResult < VTHERM_MIN)
            if(qaFlg >= 1) sys_data.qa.Vrse_err = ADCResult - VTHERM_MIN;
        else
            if(qaFlg >= 1) sys_data.qa.Vrse_err = VTHERM_MAX - ADCResult;
        uprintf(" Err ");
        if(debugFlg) uprintf("Vtherm(min %.6f < %.6f < max %.6f) ", VTHERM_MIN, ADCResult, VTHERM_MAX);
        error++;
    }


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

    return(error);
}


void test_buffer_filewrite(void)
{
    uint32_t indx;
    uint32_t bufPtr;

    FIL fileObject;
    FRESULT fresult;
    UINT bw;


    for(indx=0; indx<1024; indx++)
    {
        prnBuf[indx] = 0;
    }

    bufPtr = 0;
    for(indx=0; indx<128; indx++)
    {
        bufPtr += sprintf(&prnBuf[bufPtr], "hello %03u %04u ", indx, bufPtr);
        if(bufPtr >= 1000)
            break;
    }

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

    // Seek to the end, to append our file
    fresult = f_lseek(&fileObject, fileObject.fsize);
    if(fresult != FR_OK)
    {
        uprintf("f_lseek error: %s\n", StringFromFresult(fresult));
        error_store("f_lseek error");
    }


    // Write the buffer to the SD card
    fresult = f_write( &fileObject, (const char *)prnBuf, strlen(prnBuf), (UINT*)&bw);
    if(fresult != FR_OK)
    {
        uprintf("f_write error: %s\n", StringFromFresult(fresult));
    }


    // Close the file
    fresult = f_close( &fileObject );
    if(fresult != FR_OK)
    {
        uprintf("f_close error: %s\n", StringFromFresult(fresult));
        error_store("f_close error");
    }


}
