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

#include "system.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 "ocr.h"
#include "picoph.h"
#include "nanofet.h"
#include "ctd_base.h"
#include "uartstdio.h"
#include "board_util.h"
#include "config.h"
#include "ctd_aand5860.h"
#include "ctd_sbe37.h"
#include "i2c_fram.h"
#include "i2c0.h"
#include "bme280.h"

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


extern struct systemSamplingData sys_samp;
extern struct bme280_data bme280_data;

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

extern int microSD_flg;

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

    // Test menu loop
    while(1)
    {
        //uprintf("\r\r\n\r\r\n\r\r\nTest Menu -- %s\r\r\n", VERSION);
        uprintf("\r\r\n\r\r\n\r\r\nTest Menu:\r\r\n");

        uprintf("1 -- Battery and Board Sensors\r\r\n");  //uprintf("1 -- Internal Environment Sensors\r\r\n");  //uprintf("1 -- Display Battery, Internal Temp, Pressure\r\r\n");
        uprintf("2 -- Durafet voltages\r\r\n");   //ISFET, References and Thermistor volts was Display pH Sensor Data
        uprintf("3 -- Calc pH using Int Ref and Thermistor\r\r\n");   //uprintf("3 -- Communicate with Instrument\r\r\n");
        uprintf("4 -- Calc pH using Ext Ref, Thermistor and Salinity\r\r\n");
        uprintf("5 -- Communicate with Instrument\r\r\n");
        uprintf("6 -- Power Output Tests for AUXx and Pump\r\r\n");
        //uprintf("7 -- Thoms Dev Test (i2c bus scan)\r\r\n");
        uprintf("8 -- Test 24bit ADC and MUX channels\r\r\n");
        uprintf("D/d- Data Header, Live Data (D loop), Sample Timing (d)\r\r\n");      //uprintf("D/d- Data Header print and test\r\r\n");
#if BOARD_MPHOX >= 1
        uprintf("P/p- Pump sequence, Data Header, Live Data (P loop), Sample Timing (p)\r\r\n");
#endif
        uprintf("M -- MetaData\r\r\n");     // Thom: belongs in Config menu
        //uprintf("R -- print QA Report\r\r\n");                                      // was uprintf("P -- Print QA report\r\r\n");
        //uprintf("Q -- QA and setup after board manufacture\r\r\n");

        uprintf("9 -- Exit to Main Menu\r\r\n");
        uprintf("\r\r\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 '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\r\r\n\r\r\n");
                power_output_tests();  // defd in test.c
                break;

            case '7':
                // Thomz test hook
                //bme280_dev_test();

                break;

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

            case 'd':
                test_get_sample_timing();
                break;
            case 'D':
                test_get_sample_loop();
                break;

            case 'p':
                pump_and_sample_timing_test();
                break;
            case 'P':
                pump_and_sample_loop_test();
                break;

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

            default: //Exit
                uprintf("\r\r\nPress enter to bring up main menu\r\r\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;

    int32_t temperature;
    int32_t pressure, humidity;

#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\r\r\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\r\r\n");
#endif

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

    openADS1248_iso();
    ROM_SysCtlDelay(MILLISECOND * 100);

    ADS1248_gpio_init();        // for reading bias bat
    ADS1248_gpio0(1);

    uprintf("\r\nBME280 relative humidity percent (0 to 99), Temperature in Celsius, Pressure in hectoPascals (hPa) / millibars where 1013 hPa is sealevel\r\n\r\n");
    uprintf("Warning: Bias bat readings require a jumper - pin 6 (gnd) to pin 16 (ain7) or it won't measure properly\r\n");
    loopCnt = 0;
    fBiasPos = 0.0;
    fBiasNeg = 0.0;
    while(1)
    {
        bme280_sample_fetch(&bme280_data);


        temperature = bme280_get_temperature(&bme280_data);
        pressure = bme280_get_pressure(&bme280_data);
        humidity = bme280_get_humidity(&bme280_data);

        ADS1248_gpio0(1);
        ROM_SysCtlDelay(MILLISECOND * 10);
        ADCResult = pollADS1248_iso(6, 7, 5, 1, 20);    // throw away first reading  THOM, need Scott to say how to measure bias battery
        ROM_SysCtlDelay(MILLISECOND * 100);
        ADCResult = pollADS1248_iso(6, 7, 5, 1, 20);
        fBiasPos = ADCResult*2.0;
        ADS1248_gpio0(0);

        uprintf("Humidity = %2u   Temp = %3d.%02d C   Pressure = %4d.%02d hPa   bias bat = %5.2fV  loop = %u\r", humidity/1024, temperature/100, temperature%100, (pressure/256)/100, (pressure/256)%100, fBiasPos, loopCnt++);


        //uprintf("bme280 temperature:   %4d.%02d  C\r\n", temperature/100, temperature%100);
        //uprintf("bme280 humidity:      %4d       percent RH\r\n", humidity/1024);
        //uprintf("bme280 pressure:      %4d.%02d  hPa\r\n", (pressure/256)/100, (pressure/256)%100);

        ROM_SysCtlDelay(MILLISECOND * 500);

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

    }

    closeADS1248_iso();

#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("\r\r\nOpen isolated ADS1248 and ADG1609 mux\r\r\n\r\r\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("\r\r\nOpen nFET ADS1248\r\r\n\r\r\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("\r\r\n\r\r\n    Date Time,   Ext Ref Off, Int Ref Off, Ext Ref V, Int Ref V, CntrE Cur, CntrE Volt,  Subst Cur,  Subst Vol,  Thermistor\r\r\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("\r\r\n\r\r\n    SampTime,         Vrse_B,     Vrse,      Vrsi_B,      Vrsi,      Ik,         Vk,          Ib,        Vb,     Vtherm\r\r\n");
    else
        uprintf("\r\r\n\r\r\n    SampTime,         Vrse_B,     Vrse,      Vrsi_B,      Vrsi,      Ik,         Vk,          Ib,     Vtherm\r\r\n");


#endif

#if BOARD_NANOFET >= 1
    //uprintf("\r\r\n\r\r\n    Date Time,  Ext Ref V, CntrE Cur, CntrE Volt,  Subst Cur,  Subst Vol,  Thermistor\r\r\n");
    if(sys_data.diag > 0)
        uprintf("\r\r\n\r\r\n    SampTime,         Vrse,       Ik,        Vk,        Ib,       Vb,      Vtherm\r\n");
    else
        uprintf("\r\r\n\r\r\n    SampTime,         Vrse,       Ik,        Vk,        Ib,      Vtherm\r\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);       // Vrse 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\r\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);       // Vrse 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);       // Ik   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);       // Vk   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);       // Ib  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);       // Vtherm thermistor

            uprintf("\r\r\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, Vrsi, pHint;


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

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

    uprintf("   TempC = TempC + sys_data.TCOffset   TCOffset is user entered in config menu\r\n");
    uprintf("   TempK = TempC + 273.15\r\n");
    uprintf("   NernstSlope = (R_=8.31451 * TempK) / F_=96487 * LN10=2.302585\r\n");
    uprintf("   NernstSlope = TempK / 26,720.7\r\n");
    uprintf("   Eoint = k0int + dEoINT_dt=-0.0011012 * (TC-25)   k0int is typically -0.4 and can be modified in Config menu\r\n");
    uprintf("   Eoint = -0.4 + -0.0011012 * (TempC-25)\r\n");
    //uprintf("   pHint = (Vrsi_B - Eoint) / NernstSlope\r\n");
    uprintf("   pHint = (Vrsi - Eoint) / NernstSlope\r\n");
    uprintf("\r\n\r\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
        Vrsi = pollADS1248_iso(1, 6, 5, 1, 5);       // Chan +1 -6, trials = 10, gain = 1, sps = 20 Hz (10*50ms = 500ms)
        //fVrsi_std = sys_samp.AD24_std;

        //pHint = calc_pHint(Vrsi_B, TC);
        pHint = calc_pHint(Vrsi, TC);   // per YUI  28 Dec 2021

        //uprintf("pH= %2.6f,  TC= %2.6f,  Vtherm= %.6f V, Vrsi_B= %.6f V, std= %.6f\r\n", pHint, TC, Vtherm, Vrsi_B, sys_samp.AD24_std);
        uprintf("pH= %2.6f,  TC= %2.6f,  Vtherm= %.6f V, Vrsi= %.6f V, std= %.6f\r\n", pHint, TC, Vtherm, Vrsi, 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\r\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("\r\n\r\n\r\nCommunicate with Instrument Menu:\r\n");
        uprintf("1 -- SBE37 MicroCAT (on CTD port)\r\n");
        uprintf("2 -- Aanderaa 5860 Conductivity (on CTD port)\r\n");
        uprintf("3 -- Aanderaa Optode\r\n");
        uprintf("4 -- Comm-Pwr Aux port\r\n");
        uprintf("5 -- Seabird OCR-504 on Optode port\r\n");
        uprintf("6 -- NanoFET pH on Optode port\r\n");
        //uprintf("5 -- Sample SBE37 MicroCAT (on CTD port)\r\n");
        //uprintf("6 -- Sample Aanderaa 5860 Conductivity (on CTD port)\r\n");
        //uprintf("7 -- Sample Aanderaa Optode\r\n");
        //uprintf("8 -- Sample Comm-Pwr Aux. port\r\n");

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

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

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

#endif

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

        input = get_key();
        switch(input)
        {
#if BOARD_MPHOX >= 1
            case '1':  // MicroCAT
                ctd_sbe37_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 || BOARD_MFET >=2
            case '4':  // OCR-504
                // now COMM-PWR formerly AUX 1 3
                //uprintf("\r\n\r\nCOMM-PWR port not supported on MPHOX, RS232 level shifter is not stuffed\r\n\r\n");
                ocr_comm_test();     // defd in ocr.c
                break;
#endif

#if BOARD_MPHOX >= 1 || BOARD_MFET >=2
            case '5': // NanoFET pH
                nanofet_comm_test();     // defd in nanofet.c
                // THOM TODO: move this to optode.c
                break;
#endif
#if BOARD_MPHOX >= 1 || BOARD_MFET >=2
            case '6': // NanoFET pH
                picoph_comm_test();     // defd in picoph.c

                break;
#endif

            case '7':
#if BOARD_MPHOX >= 1 || BOARD_MFET >=2

#endif
                break;

            case '8':
#if BOARD_MPHOX >= 1 || BOARD_MFET >=2
                // qa_test for driver development...
                //nanofet_qa_test();
#endif
                break;

            case 'O':
                if(sys_data.app_cfg[APPCFG_MENU_LEVEL] == 0)
                    break;
                uprintf("\r\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 \r\n\r\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_buf_print();        // uprintf("\r\n%s\r\n", optode.buf);
                            uprintf("\r\n\r\nOptode Read Time = %u ms  statemachine pump cycle = %u ms \r\n", (tick2-tick1)*10, sm_delay);

                            if(sm_delay > 0) sm_delay+=100;

                            if(sm_delay > 1500)
                                sm_delay = 0;

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

            case 'o':
                if(sys_data.app_cfg[APPCFG_MENU_LEVEL] == 0)
                    break;
                uprintf("\r\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 \r\n\r\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_buf_print();        // uprintf("\r\n%s\r\n", optode.buf);
                        uprintf("\r\n\r\nDebug Optode Read Time = %u ms \r\n", (tick2-tick1)*10);

                        break;
                    }
                }
                uprintf("\r\n\r\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_aand5860_serial_analyzer();
                break;

            case 'r':
                if(sys_data.app_cfg[APPCFG_MENU_LEVEL] == 0)
                    break;
                ctd_sbe37_serial_analyzer();
                break;
#if BOARD_MPHOX >= 1
            case 'c':
                if(sys_data.app_cfg[APPCFG_MENU_LEVEL] == 0)
                    break;
                uprintf("\r\nTest Conductivity (SBE37 statemachine code):  Power CTD with Vbat, wait for %% or 'S', Send 'do sample' or 'ts', receive and parse sample, turn power off \r\n\r\n");
                //uprintf("\r\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 \r\n\r\n");
                tick1 = Timer_10ms(false);
                ctdState = 1;
                ctdState = ctd_sbe37_stateMachine(ctdState);

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

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

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

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

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


                while(1)
                {
                    //if user types anything, send it to the CTD -- 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_sbe37_stateMachine(ctdState);


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


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

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

            default: //Exit
                return;
        }
    }
}




int power_output_tests(void)
{
    time_t timer;
    char input;
    unsigned int pwmVal = 33;
    int exitFlg = 0;
    //unsigned int indx;


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

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

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

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

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

        //uprintf("P/p -- Solenoid PWM (hacked for 1KHz)\r\n");
        uprintf("\r\n");
#endif
        uprintf("9 -- Exit to Test Menu\r\n");
        uprintf("\r\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 J12 (Pump1) ON\r\n");
                pwr_aux_pwr1_on();
                break;
#endif
            case 'a':
#if BOARD_MPHOX >= 1
                uprintf("AUX-PWR1 J12 (Pump1) OFF\r\n");
                pwr_aux_pwr1_off();
#endif
                break;

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

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

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

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

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

            case 'P':
            case 'p':
                pwmVal = sys_data.solenoid_hold_pwm;  //
                pwmSoln_set(pwmVal);


                uprintf("Lower case p to lower pwm value, Upper case P to raise pwm value, \r\n");
                uprintf("s/S to save PWM solenoid hold value, X to exit\r\n");
                uprintf("%03u", pwmVal);
                exitFlg = 0;
                UARTEchoSet(false);
                while(1)
                {
                    if( UARTRxBytesAvail() )
                    {
                        input = UARTgetc();

                        switch(input)
                        {
                        case 'p':
                            if(pwmVal > 0)
                            {
                                pwmVal--;
                                pwmSoln_set(pwmVal);
                                uprintf("\b\b\b%03u", pwmVal);
                                //uprintf("%03u", pwmVal);
                            }
                            break;

                        case 'P':
                            //if(pwmVal < 100)
                            if(pwmVal < 99)
                            {
                                pwmVal++;
                                pwmSoln_set(pwmVal);        // THOM Todo fix BUG when pwmVal=100
                                uprintf("\b\b\b%03u", pwmVal);
                                //uprintf("%03u", pwmVal);
                            }
                            break;

                        case 'S':
                        case 's':
                            sys_data.solenoid_hold_pwm = pwmVal;
                            storeSysDataVariables();
                            uprintf("\r\nsys_data.solenoid_hold updated to %03u\r\n", sys_data.solenoid_hold_pwm);
                            uprintf("%03u", pwmVal);
                            exitFlg = 0;
                            break;

                        case 'X':
                        case 'x':
                            exitFlg = 1;
                            break;
                        case CTRL_X:        // 24
                            exitFlg = 1;
                            break;
                        default:
                            exitFlg = 1;
                            break;
                        }

                    } // if char

                    if(exitFlg == 1)
                    {
                        UARTEchoSet(true);
                        break;
                    }
                }
                break;

            case 'S':
#if BOARD_MPHOX >= 1
                uprintf("Solenoid On (J9 SO/1)");
                //pwmSoln_stop(1);
                solenoid_on();
                //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)");
                //pwmSoln_stop(0);
                solenoid_off();
                //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\r\n\r\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("\r\niso power on, init ADG1609 mux\r\n\r\n");

    openADS1248_iso();      // 22msec

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

#if BOARD_NANOFET >= 1
    uprintf("\r\nOpen nFET ADS1248 and ADG1609 mux\r\n\r\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("\r\n\r\n\r\nTest pH (24bit ADC and Mux) Menu\r\n");
#if BOARD_MFET >= 2 || BOARD_MPHOX >= 1
        uprintf("0 -- Vrsi    - ISFET Source (pH) Voltage wrt Int Ref\r\n");
        uprintf("1 -- Vrsi_B  - pH Volt Biased (pH 7 is 0v) wrt Int Ref\r\n");
#endif
        uprintf("2 -- Vrse    - ISFET Source (pH) Voltage wrt Ext Ref\r\n");
#if BOARD_MFET >= 2 || BOARD_MPHOX >= 1
        uprintf("3 -- Vrse_B  - pH Volt Biased (pH 7 is 0v) wrt Ext Ref\r\n");
#endif
        uprintf("4 -- Ik      - Counter Electrode Current\r\n");  // Counter A and Counter B are current measurement Counter Electrode
        uprintf("5 -- Vk      - Counter Electrode Voltage wrt Ground\r\n");
        uprintf("6 -- Ib      - Substrate Current\r\n");
#if BOARD_MFET >= 2 || BOARD_MPHOX >= 1
        uprintf("7 -- Vb      - Substrate Voltage (Deprecated)\r\n");
#endif
        uprintf("8 -- Vtherm  - Thermistor Temperature\r\n");
        uprintf("S -- Sample all channels (0-8)\r\n");
        uprintf("X -- MCAP sample test (error check voltages), assumes Jensenian Analog Board\r\n");
        uprintf("9 -- Exit to Main Menu\r\n");
        uprintf("\r\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 '0':
#if BOARD_MFET >= 2 || BOARD_MPHOX >= 1
            // uprintf("0 -- Vrsi    - ISFET Source (pH) Voltage wrt Int Ref\r\n");
            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\r\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\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\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\r\n", ADCResult, tempAD24_std, indx++, tick2);
                }
                if( UARTRxBytesAvail() )
                {
                    input = get_key();
                    break;    // break from while(1)
                }
            }
#endif
            break;


            case '1':
#if BOARD_MFET >= 2 || BOARD_MPHOX >= 1
                //uprintf("1 -- Vrsi_B  - pH Volt Biased (pH 7 is 0v) wrt Int Ref\r\n");

                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\r\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\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\r\n", ADCResult, tempAD24_std, indx++, tick2);


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

            case '2':
                //uprintf("2 -- Vrse    - ISFET Source (pH) Voltage wrt Ext Ref\r\n");
#if BOARD_MFET >= 2 || BOARD_MPHOX >= 1
                ADS1248_gpio_ADG1609_mux(0);
#endif
                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\r\n", sampleCnt, sampleCnt);
                while(1)
                {
                    sampTime = Timer_10ms(FALSE);
                    if(sampTime >= nextTime)
                    {
                        nextTime = sampTime + sampDelay;
                        tick1 = Timer_10ms(FALSE);
#if BOARD_NANOFET >= 1
                        ADCResult = pollADS1248_iso(1, 0, sampleCnt, 1, 5);
                        //ADCResult = pollADS1248_iso(1, 5, sampleCnt, 1, 5);     // BUG 14 Feb 2023 Test routine is lower noise than deployment sampling


#endif
#if BOARD_MFET >= 2 || BOARD_MPHOX >= 1
                        ADCResult = pollADS1248_iso(1, 6, sampleCnt, 1, 5);       // Chan +1 -6, trials = 1, gain = user, sps = 5 Hz
#endif
                        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\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
#if BOARD_NANOFET >= 1
                        ADCResult = pollADS1248_iso(1, 0, sampleCnt, 1, 20);  // BUG 14 Feb 2023 Test routine is lower noise than deployment sampling
                        //ADCResult = pollADS1248_iso(1, 5, sampleCnt, 1, 20);
#endif
#if BOARD_MFET >= 2 || BOARD_MPHOX >= 1
                        ADCResult = pollADS1248_iso(1, 6, sampleCnt, 1, 20);       // Chan +1 -6, trials = 1, gain = user, sps = 20 Hz
#endif
                        tick2 = (Timer_10ms(FALSE) - tick1) * 10;
                        tempAD24_std = sys_samp.AD24_std;

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

            case '3':
#if BOARD_MFET >= 2 || BOARD_MPHOX >= 1
                //uprintf("3 -- Vrse_B  - pH Volt Biased (pH 7 is 0v) wrt Ext Ref\r\n");

                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\r\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\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\r\n", ADCResult, tempAD24_std, indx++, tick2);
                    }

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

            case '4':
                //uprintf("4 -- Ik      - Counter Electrode Current\r\n");  // Counter A and Counter B are current measurement Counter Electrode
#if BOARD_MFET >= 2 || BOARD_MPHOX >= 1
                ADS1248_gpio_ADG1609_mux(1);
#endif
                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\r\n", sampleCnt, sampleCnt);
                while(1)
                {
                    sampTime = Timer_10ms(FALSE);
                    if(sampTime >= nextTime)
                    {
                        nextTime = sampTime + sampDelay;

                        tick1 = Timer_10ms(FALSE);
#if BOARD_MFET >= 2 || BOARD_MPHOX >= 1
                        ADCResult = pollADS1248_iso(1, 5, sampleCnt, 1, 5);       // Chan +5 -1, trials = 1, gain = user, sps = 5 Hz
#endif
#if BOARD_NANOFET >= 1
                        ADCResult = pollADS1248_iso(3, 4, sampleCnt, 1, 5);
#endif
                        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\r\n", ADCResult, ADCResult*COUNTERELECTRODE_IK_SCALE, tempAD24_std, indx++, tick2);


                        tick1 = Timer_10ms(FALSE);
#if BOARD_MFET >= 2 || BOARD_MPHOX >= 1
                        ADCResult = pollADS1248_iso(1, 5, sampleCnt, 1, 20);       // Chan +5 -1, trials = 1, gain = user, sps = 5 Hz
#endif
#if BOARD_NANOFET >= 1
                        ADCResult = pollADS1248_iso(3, 4, sampleCnt, 1, 20);
#endif
                        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\r\n", ADCResult, ADCResult*COUNTERELECTRODE_IK_SCALE, tempAD24_std, indx++, tick2);
                    }
                    if( UARTRxBytesAvail() )
                    {
                        input = get_key();
                        break;    // break from while(1)
                    }
                }
                break;

            case '5':
                //uprintf("5 -- Vk      - Counter Electrode Voltage wrt Ground\r\n");
#if BOARD_MFET >= 2 || BOARD_MPHOX >= 1
                ADS1248_gpio_ADG1609_mux(1);
#endif
                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\r\n", sampleCnt, sampleCnt);
                while(1)
                {
                    sampTime = Timer_10ms(FALSE);
                    if(sampTime >= nextTime)
                    {
                        tick1 = Timer_10ms(FALSE);
#if BOARD_MFET >= 2 || BOARD_MPHOX >= 1
                        ADCResult = pollADS1248_iso(1, 6, sampleCnt, 1, 5);       // Chan +5 -1, trials = 1, gain = user, sps = 5 Hz
#endif
#if BOARD_NANOFET >= 1
                        ADCResult = pollADS1248_iso(3, 0, sampleCnt, 1, 5);       // Chan +5 -1, trials = 1, gain = user, sps = 5 Hz
#endif
                        tick2 = (Timer_10ms(FALSE) - tick1) * 10;

                        tempAD24_std = sys_samp.AD24_std;

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

                        tick1 = Timer_10ms(FALSE);
#if BOARD_MFET >= 2 || BOARD_MPHOX >= 1
                        ADCResult = pollADS1248_iso(1, 6, sampleCnt, 1, 20);       // Chan +5 -1, trials = 1, gain = user, sps = 5 Hz
#endif
#if BOARD_NANOFET >= 1
                        ADCResult = pollADS1248_iso(3, 0, sampleCnt, 1, 20);       // Chan +5 -1, trials = 1, gain = user, sps = 5 Hz
#endif
                        tick2 = (Timer_10ms(FALSE) - tick1) * 10;

                        tempAD24_std = sys_samp.AD24_std;

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

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

            case '6':
                //uprintf("6 -- Ib      - Substrate Current\r\n");
#if BOARD_MFET >= 2 || BOARD_MPHOX >= 1
                ADS1248_gpio_ADG1609_mux(2);
#endif
                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\r\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);
#if BOARD_MFET >= 2 || BOARD_MPHOX >= 1
                        ADCResult = pollADS1248_iso(1, 6, sampleCnt, 1, 5);
#endif
#if BOARD_NANOFET >= 1
                        ADCResult = pollADS1248_iso(2, 0, sampleCnt, 1, 5);
#endif
                        tick2 = (Timer_10ms(FALSE) - tick1) * 10;
                        //uprintf("Ib= %.6f V, Vb Std = %.6f,  Samp = %04u,  Time = %04lu ms 5Hz\r\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\r\n", ADCResult, ADCResult*SUBSTRATECURRENT_IB_SCALING, tempAD24_std, indx++, tick2);

                        tick1 = Timer_10ms(FALSE);
#if BOARD_MFET >= 2 || BOARD_MPHOX >= 1
                        ADCResult = pollADS1248_iso(1, 6, sampleCnt, 1, 20);
#endif
#if BOARD_NANOFET >= 1
                        ADCResult = pollADS1248_iso(2, 0, sampleCnt, 1, 20);
#endif
                        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\r\n", ADCResult, ADCResult*SUBSTRATECURRENT_IB_SCALING, tempAD24_std, indx++, tick2);

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

            case '7':
                //uprintf("7 -- Vb      - Substrate Voltage (Depracated)\r\n");
#if BOARD_MFET >= 2 || BOARD_MPHOX >= 1
                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\r\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\r\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\r\n", ADCResult, tempAD24_std, indx++, tick2);

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

            case '8':
                //uprintf("8 -- Vtherm  - Thermistor Temperature\r\n");
#if BOARD_MFET >= 2 || BOARD_MPHOX >= 1
                ADS1248_gpio_ADG1609_mux(0);        // Not necessary, but consistent
#endif
                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\r\n", sampleCnt, sampleCnt);
                while(1)
                {
                    sampTime = Timer_10ms(FALSE);
                    if(sampTime >= nextTime)
                    {
                        nextTime = sampTime + sampDelay;

                        tick1 = Timer_10ms(FALSE);
#if BOARD_MFET >= 2 || BOARD_MPHOX >= 1
                        ADCResult = pollADS1248_iso(0, 6, sampleCnt, 1, 5);
#endif
#if BOARD_NANOFET >= 1
                        ADCResult = pollADS1248_iso(5, 7, sampleCnt, 1, 5);
#endif
                        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\r\n", ADCResult, tempAD24_std, indx++, tick2);

                        tick1 = Timer_10ms(FALSE);
#if BOARD_MFET >= 2 || BOARD_MPHOX >= 1
                        ADCResult = pollADS1248_iso(0, 6, sampleCnt, 1, 20);
#endif
#if BOARD_NANOFET >= 1
                        ADCResult = pollADS1248_iso(5, 7, sampleCnt, 1, 20);
#endif
                        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\r\n", ADCResult, tempAD24_std, indx++, tick2);

                    }
                    if( UARTRxBytesAvail() )
                    {
                        input = get_key();
                        break;    // break from while(1)
                    }
                }
                break;
#ifdef NOCODE
            case 'a':
                uprintf("mux = 00\r\n");
                ADS1248_gpio_ADG1609_mux(0);
                break;
            case 'b':
                uprintf("mux = 01\r\n");
                ADS1248_gpio_ADG1609_mux(1);
                break;
            case 'c':
                uprintf("mux = 10\r\n");
                ADS1248_gpio_ADG1609_mux(2);
                break;
            case 'd':
                uprintf("mux = 11\r\n");
                ADS1248_gpio_ADG1609_mux(3);
                break;
            case 'e':
                ADS1248_gpio2(0);
                break;
            case 'E':
                ADS1248_gpio2(1);
                break;
#endif

            case 'S':
            case 's':
                //uprintf("S -- Sample all channels (0-8)\r\n");
                //   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("\r\n\r\n    Date Time,   Ext Ref Off, Int Ref Off, Ext Ref V, Int Ref V, CntrE Cur, CntrE Volt,  Subst Cur,  Subst Vol,  Thermistor\r\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("\r\n\r\n    Date Time,         Vrsi,      Vrsi_B,    Vrse,       Vrse_B,      Ik,       Vk,        Ib,       Vb,     VTherm\r\n");

#endif

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

                indx = 0;
                Timer_10ms(TRUE);       // reset 10msec tick count
                sampDelay = 200L;       // two second loop
                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\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

                        //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
#endif
#if BOARD_NANOFET >= 1
                        //Ext Ref V, Vrse
                        ADCResult = pollADS1248_iso(1, 0, sampleCnt, 1, 5);       // Chan +1 -6, trials = 1, gain = user, sps = 5 Hz
                        uprintf(" %.6f, ", ADCResult);       // Ext Ref Voltage

                        //CntrE Cur, Ik
                        ADCResult = pollADS1248_iso(3, 4, sampleCnt, 1, 5);       // Chan +5 -1, trials = 1, gain = user, sps = 5 Hz
                        uprintf(" %.2f, ", ADCResult*COUNTERELECTRODE_IK_SCALE);       // Counter Electrode Current

                        // CntrE Volt, Vk
                        ADCResult = pollADS1248_iso(3, 0, sampleCnt, 1, 5);       // Chan +5 -1, trials = 1, gain = user, sps = 5 Hz
                        uprintf(" %.6f, ", ADCResult);       // Counter Electrode Voltage

                        // Subst Cur, Ib
                        ADCResult = pollADS1248_iso(2, 0, sampleCnt, 1, 5);       // Chan +5 -1, trials = 1, gain = user, sps = 5 Hz
                        uprintf(" %.3f, ", ADCResult*SUBSTRATECURRENT_IB_SCALING);       // Substrate Current

                        // Subst Vol,
                        //ADCResult = pollADS1248_iso(5, 6, sampleCnt, 1, 5);       // Chan +5 -1, trials = 1, gain = user, sps = 5 Hz
                        //uprintf(" %.6f, ", ADCResult);       // Substrate Voltage

                        // Thermistor
                        ADCResult = pollADS1248_iso(5, 7, sampleCnt, 1, 5);       // Chan +5 -1, trials = 1, gain = user, sps = 5 Hz
                        uprintf(" %.6f", ADCResult);       // Substrate Voltage
#endif



                        uprintf("\r\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("\r\n\r\n    Date Time,   Ext Ref Off, Int Ref Off, Ext Ref V, Int Ref V, CntrE Cur, CntrE Volt,  Subst Cur,  Subst Vol,  Thermistor\r\n");

                uprintf("\r\n\r\n");
                if(sys_data.diag == 1)
                {
                    uprintf("               MIN: %.6f,  %.6f,  %.6f,  %.6f,  %.6f,  %.6f,  %.6f,  %.6f,  %.6f\r\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\r\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\r\n");
                }
                else
                {
                    uprintf("               MIN: %.6f,  %.6f,  %.6f,  %.6f,  %.6f,  %.6f,  %.6f,  %.6f\r\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\r\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\r\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("\r\nPress enter to bring up menu\r\n");
                closeADS1248_iso();
                uprintf("iso power off\r\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\r\n");
}

// subset of enter_metadata() from config.c
void enter_qa_metadata(void)
{
    char buff[128];

    uprintf("\r\nEnter data file name (no spaces, 8.3 format) [%s]: ", sys_data.fileName);  // 8 + 1 + 3 + 1 = 13  (null terminate)
    if( getUserInput(buff, 13) ) // was MAX_FILENAME-1) )  // storage size is 80, user input size was 100 - fixed a BUG!
    {
        strcpy(sys_data.fileName, buff);
        uprintf("\r\nFile name now: %s\r\n", sys_data.fileName);
    }

    uprintf("\r\nEnter user initials [%s]: ", sys_data.user);
    if( getUserInput(buff, MAX_USER_INITIALS-1) )       // was 10 user initials
    {
        strcpy(sys_data.user, buff);
        uprintf("\r\nUser initials now: %s\r\n", sys_data.user);
    }

    //char board_SN[MAX_BOARD_SN];   MAX_BOARD_SN 30
#if BOARD_MFET >= 1
    uprintf("\r\nEnter MFET Serial # [%s]: ", sys_data.board_SN);
#endif
#if BOARD_MPHOX >= 1
    uprintf("\r\nEnter MPHOX Serial # [%s]: ", sys_data.board_SN);
#endif
#if BOARD_NANOFET >= 1
    uprintf("\r\nEnter nanoFET Serial # [%s]: ", sys_data.board_SN);
#endif
    if( getUserInput(buff, MAX_BOARD_SN-1) )       // board serial number
    {
        strcpy(sys_data.board_SN, buff);
        uprintf("\r\nBoard Serial #: %s\r\n", sys_data.board_SN);
    }


    // char mcap_SN[MAX_MCAP_SN];  MAX_MCAP_SN  30
#if BOARD_MFET >= 1 || BOARD_MPHOX >= 1
    uprintf("\r\nEnter MCAP Serial # [%s]: ", sys_data.mcap_SN);
    if( getUserInput(buff, MAX_MCAP_SN-1) )       // board serial number
    {
        strcpy(sys_data.mcap_SN, buff);
        uprintf("\r\nMCAP Serial #: %s\r\n", sys_data.mcap_SN);
    }
#endif


    // char board_fab_note[MAX_board_fab_note];   MAX_board_fab_note 80
    uprintf("\r\nEnter board Fabrication notes [%s]: ", sys_data.qa.board_fab_note);
    if( getUserInput(buff, MAX_BOARD_FABNOTE-1) )       // board fabricaton notes
    {
        strcpy(sys_data.qa.board_fab_note, buff);
        uprintf("\r\nBoard Fab notes: %s\r\n", sys_data.qa.board_fab_note);
    }

}



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

    // NEW get board and mcap serial number

    // 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("\r\nQA: ----- EEPROM / sys_data init -----\r\n");
    // initialize EEPROM sys_data with defaults
    if(initFlg == 1)
    {

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

        // if the microSD was not initialized (likely due to if(sys_data.app_cfg[APPCFG_MICROSD_ENABLE] == 1) error
        // bug fix 16 Nov 2021 Thom  QA hangs during fileio
        if(microSD_flg == 0)
        {
            Init_SDCard();
            microSD_flg = 1;
        }

        init_sys_data_default();   // initialize entire sys_data with defaults (except the qa section)
        config_qa_data_init();  // 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\r\n", eeSize);
        temp = sizeof(struct systemData);
        if(verboseFlg == 1) uprintf("sizeof sys_data in EEPROM = %u\r\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)\r\n", sys_data.qa.eeprom);
            uprintf("   Pass sys_data init\r\n");
        }
        else
        {
            uprintf("   Fail EEPROM:  %u is less than sys_data size of %u\r\n", eeSize, temp);
            sys_data.qa.eeprom = 0;     // 0 is fail
            uprintf("   Fail sys_data init\r\n");
        }

        strcpy(sys_data.qa.firmware_version, VERSION);


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

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

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



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

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

        storeSysDataVariables();        // store initialized variables back in EEPROM in case of hang and need to reboot (bug fix 16 Nov 2021) Thom


    }



    // TODO 2 Jun 2021 There is a bug with string print of sys_data.qa.tester
    uprintf("\r\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]\r\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\r\n", indx);
                break;
            }
        }

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

    //uprintf("\r\nTester Debug 1 [%s]\r\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("\r\nQA: ----- RTC test -----\r\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("\r\nTime now: ");
        printCurrentTime();
        if(sys_data.GMT)
            uprintf(" GMT\r\n");
        else
            uprintf(" Local\r\n");

    }

    uprintf("\r\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);
#if BOARD_NANOFET >= 1
    uprintf("\r\nQA: ----- Skipping embedded Flash test for now -----\r\n");

#endif

#if BOARD_MFET >= 2 || BOARD_MPHOX >= 1
    uprintf("\r\nQA: ----- microSD test -----\r\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];

    //NOTE: BUG 11 Nov 2021.  If the sys_data struct is not init'd properly or has uSD card disabled, the following will fail


    //uprintf("DEBUG: qaFilename is %s\r\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\r\n", StringFromFresult(fresult));
        uprintf("QA file failed to open, check microSD card slot for 8GB uSD\r\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\r\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\r\n", StringFromFresult(fresult));
            }
            else
            {
                sys_data.qa.microSD = 1;
                uprintf("  Passed\r\n");
            }
        }
    }

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

#endif

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

    //sys_data init used to be here

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

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

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

        uprintf("\r\n\r\n");

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

    }

    if(verboseFlg == 1) uprintf("\r\nQA: Print Meta Data\r\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\r\n");
    }

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

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

    uprintf("\r\nQA: hit any key, additional current of 2mA to 3mA is expected, more or less is a Fail.\r\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\r\n\r\n");
    display_battery_boardSensors();

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

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


    openADS1248_iso();      // 22msec
    ROM_SysCtlDelay(MILLISECOND * 100);
    ADS1248_gpio_init();    // defd in ADS1248_iso.c   // Not used by nanoFET
    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("\r\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\r\n");
    sys_data.qa.adc24 = 10;  // pre-load with 10 errors
    if(sys_data.app_cfg[APPCFG_MENU_LEVEL] == 1) uprintf("\r\n\r\n    Date Time,         Vrsi,     Vrsi_B,     Vrse,      Vrse_B,       Ik,        Vk,         Ib,        Vb,       VTherm\r\n");
    else uprintf("\r\n\r\n    Date Time,         Vrsi,     Vrsi_B,     Vrse,      Vrse_B,       Ik,        Vk,         Ib,       VTherm\r\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\r\n", sys_data.qa.adc24);
            input = get_key();
            break;    // break from while(1)
        }
    }

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

    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("\r\nQA: ------- Testing External Instrument interfaces -------\r\n");

    sys_data.qa.ctd = ctd_sbe37_qa_test(); // return 1 for success, 0 for fail
    if(sys_data.qa.ctd > 0)
        uprintf("  CTD interface passed\r\n");
    else
        uprintf("  CTD interface failed\r\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\r\n");
    else
        uprintf("  Optode interface failed\r\n");
#endif
    uprintf("\r\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\r\n");
    }
    else
    {
        sys_data.qa.sys_data_init = 0;
        sys_data.qa.eeprom = 0;
        uprintf("\r\n\r\nError storing system data in EEPROM\r\n");

    }

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

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

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


    print_qa_report();


    uprintf("\r\n\r\nThankyou %s, your QA time was %u sec.  Have a nice day.\r\n\r\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\r\n", sys_data.qa.tester);
    uprintf("Board fabrication note: %s\r\n", sys_data.qa.board_fab_note);
    uprintf("MCAP SN: %s\r\n", sys_data.board_SN);
    uprintf("MCAP SN: %s\r\n", sys_data.mcap_SN);
    uprintf("Firmware QA version: %s\r\n", sys_data.qa.firmware_version);
    uprintf("Test time = %u sec\r\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\r\n", timeStamp);

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

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

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

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

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

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

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

#if BOARD_MPHOX >= 1
    if(sys_data.qa.comm_pwr > 0)
        uprintf("Comm Pwr passed\r\n");
    else
        uprintf("Comm Pwr failed\r\n");
#endif
    uprintf("ADC24 report:\r\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-\r\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-\r\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("%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("\r\n");


}



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


int test_sampling_mcap(int qaFlg)        // changed to DEFINES in test.h from noise 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;

// THOM TODO:  Update for NanoFET

    // Vrsi   Int Ref V,
#if BOARD_NANOFET >= 1
        // Int Ref with offset not applicable on nanoFET per Scott
        ADCResult = 0.0;
#endif
#if BOARD_MFET >= 1 || BOARD_MPHOX >= 1
    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++;
    }
    else
        uprintf(", ");
#endif

    //Vrsi_B   Int Ref Off,
#if BOARD_NANOFET >= 1
        // Int Ref with offset not applicable on nanoFET per Scott
        ADCResult = 0.0;
#endif
#if BOARD_MFET >= 1 || BOARD_MPHOX >= 1
    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\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++;
    }
    else
        uprintf(", ");
#endif

    //Vrse   Ext Ref V,
#if BOARD_NANOFET >= 1
        ADCResult = pollADS1248_iso(1, 0, sys_data.Vrse_trials, 1, sys_data.Vrse_sps);  // 10x50msec= 500msec  trials=10, gain=1, sps=20
#endif
#if BOARD_MFET >= 1 || BOARD_MPHOX >= 1
    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
#endif
    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++;
    }
    else
        uprintf(", ");

    //Vrse_B   Ext Ref Off,
#if BOARD_NANOFET >= 1
        ADCResult = 0.0;
#endif
#if BOARD_MFET >= 1 || BOARD_MPHOX >= 1
    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++;
    }
    else
        uprintf(", ");
#endif

    //Ik   CntrE Cur,
#if BOARD_NANOFET >= 1
    ADCResult = pollADS1248_iso(3, 4, sys_data.Ik_trials, 1, sys_data.Ik_sps);
#endif
#if BOARD_MFET >= 1 || BOARD_MPHOX >= 1
    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
#endif
    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++;
    }
    else
        uprintf(", ");


    // Vk  CntrE Volt,
#if BOARD_NANOFET >= 1
    ADCResult = pollADS1248_iso(3, 0, sys_data.Vk_trials, 1, sys_data.Vk_sps);
#endif
#if BOARD_MFET >= 1 || BOARD_MPHOX >= 1
    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
#endif
    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++;
    }
    else
        uprintf(", ");


    // Ib   Subst Cur,
#if BOARD_NANOFET >= 1
        // is there a scaling change?  no
        ADCResult = pollADS1248_iso(2, 0, sys_data.Ib_trials, 1, sys_data.Ib_sps);
#endif
#if BOARD_MFET >= 1 || BOARD_MPHOX >= 1
    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
#endif
    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++;
    }
    else
        uprintf(", ");

#if BOARD_MFET >= 1 || BOARD_MPHOX >= 1
    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++;
        }
        else
            uprintf(", ");
    }
#endif


    // Vtherm Thermistor
#if BOARD_NANOFET >= 1
    ADCResult = pollADS1248_iso(5, 7, sys_data.Vtherm_trials, 1, sys_data.Vtherm_sps);
#endif
#if BOARD_MFET >= 1 || BOARD_MPHOX >= 1
    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
#endif
    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;     // BUG 14 Feb 2023
            if(qaFlg >= 1) sys_data.qa.Vtherm_err = ADCResult - VTHERM_MIN;
        else
            if(qaFlg >= 1) sys_data.qa.Vtherm_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("\r\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\r\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\r\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\r\n", StringFromFresult(fresult));
    }


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


}
