/*
 * sample.c
 *
 *  Created on: Jun 8, 2021
 *      Author: thomm
 */


#include "system.h"

#include "user_io.h"
#include "ads1248_iso.h"
#include "ads1248_noniso.h"

#include "board_util.h"
#include "ctd_base.h"
#include "ctd_sbe37_microcat.h"
#include "optode.h"
#include "sleep.h"
#include "microsd.h"
#include "fatfs/src/ff.h"
#include "uartstdio.h"  // User local version with larger RX buffer
#include "pwm.h"
#include "sample.h"


extern struct systemSamplingData sys_samp;

extern int microSD_flg;
extern int ctd_stateMachine(int ctdState);
extern int optode_stateMachine(int optodeState);
extern struct optodeDriver optode;
extern struct microCatDriver microCat;
extern struct ctdDriver ctd;   // struct defd in ctd_base.h

extern void         adc_onchip_init(void);
extern uint32_t *   read_all_adc(void);
extern void         fram_store(void);
extern void         fram_retrieve(void);
extern void         ADS1248_gpio3(uint32_t state);


extern uint32_t     adc_data[];
extern int          dbg_flag;
extern int          ads1248noniso_flg;


float fBiasPos = 0.0;  // used for read_bias_bat();
float fBiasNeg = 0.0;

unsigned char prnBuf[SIZEOF_PRNBUF+4];      // size is defd in system.h

#if BOARD_MFET >= 1 || BOARD_MPHOX >= 1 || BOARD_NANOFET >= 1
/*
 * fast sample()
 * Take measurements and write them to SD card.
 * sys_data.diag = 1 turns on timing diagnostics
 *
     *  SampNum        VbatMain        VbiasPos        VbiasNeg          Vtherm        VthrmStd         TC_Dfet            Vrsi        Vrsi_std            Vrse        Vrse_std          Vrsi_B              Vk          Vk_std              Ik       Ib                Opt_PN  Opt_SN  Moxy    O2satper        TC_opt  Dphase  Bphase  Rphase  Bamp    Bpot    Ramp    Opt_rawtemp     TempC   Cond    Salt    Unk1    Date    Time            Cond_PN Cond_SN Cond    Temp     Unk1    Unk2    Unk3
    #0000004           11.95            3.64           -3.61        0.997208        0.000003          24.714        -0.055249       0.000004        -0.799259       0.000009        0.674751        -0.500849       0.000007        18222.69 -399.597        4831    856     220.421 93.265  29.895  26.032  28.323  36.656  8.333   527.3   600.9   -128.9  5860    29      -0.011  30.508  0.016   995.506 1510.343

     ---  Sample Timing ---

    Pump         =  2008,    2008
    Pwr on, init =    24,    2032
    Bias Bat     =    70,    2102
    Ib Substrate =    62,    2164
    Ik Cntr E    =    61,    2225
    Vk Cntr E    =   260,    2485
    Vtherm       =   250,    2735
    Vrsi_B       =   509,    3244
    Vrsi         =   509,    3753
    Vrse         =   509,    4262
    Optode St8Ma =     2,    4264
    Condo  St8Ma =    20,    4284
    Onchip ADC   =     0,    4284
    Calc TempC   =     2,    4286
    Optode       =  2119,    6405
    CTD          =   572,    6977
    format data  =     2,    6979
    #0000005           11.95            3.64           -3.61        0.997401        0.000004          24.708        -0.055247       0.000005        -0.799254       0.000008        0.674756        -0.500856       0.000005        18219.66 -399.600        4831    856     220.417 93.276  29.903  26.029  28.320  36.655  8.335   527.2   600.5   -129.2  5860    29      -0.011  30.515  0.016   995.504 1510.358        (6979 msec)

    uSD writes   =     9,    6988
    wait TX      =    22,    7010
 *
 */
void fast_sample(int txFlg)
{
    char timestamp[TIMESTAMPLENGTH];
    uint32_t timeout;
    uint32_t tickStart, ticks, tickDelta, tickEnd, tick_onchip;
    struct tm *time_struct;

    float fVtherm;           // DuraFET raw temperature voltage
    float fVtherm_std;       // Std Dev for Durafet Thermistor
    float fTempC;            // Calculated DuraFET temperature
    //float fExtTemp;

    float fVrsi;             // DuraFET internal reference voltage   (Vint)
    float fVrsi_std;         // Std Dev for Durafet Internal Voltage
    float pHint;             // Calculated pH using internal reference

    float fVrse;             // External (AUX) reference voltage  (Vrs)
    float fVrse_std;         // Std Dev for Durafet External Voltage
    float pHext;             // Calculated pH using external reference

    float SBE_sal;           // MicroCAT salinity

    float fVrse_B;
    float fVrse_B_std;
    float fVrsi_B;
    float fVrsi_B_std;

    float fIk;              // (Ik) CounterElectrodeCurrent
    float fIk_std;
    float fVk;              // (Vk) CounterElectrodeVoltage
    float fVk_std;
    float fIb;              // (Ib) SubstrateCurrent
                            // float SubstrateVoltage;  //float SubstrateVoltage_std;
    float fVbat_main;
    float fBias_bat_lowest;

    float fHumidity;
    float fBrdTempC;
    uint32_t  uiHumidity;
    uint32_t  uiWater;

    uint32_t indx;
    int optodeState;
    int ctdState;

    FIL fileObject;
    FRESULT fresult;
    INT bw;

    optodeState = 0;
    ctdState = 0;

    tickStart = Timer_1ms(true);
    tickDelta = tickStart;
    char inChar;

    if(sys_data.test_mode == 1)
        uprintf("\nSampling...");

    // trying to cut down the sampling loop problem...   it's now fixed on it's own (worriesome) 4 Aug 2021  Fail was happening during single step at ADS1248_gpio_init(); line below.
#define CUT_A   1
#define CUT_B   1
#define CUT_C   1
#define CUT_D   1

#if BOARD_MPHOX >= 1
    if(sys_data.pumpon_time > 0)
    {
        // Pump on time
        if(sys_data.test_mode == 1)
            uprintf("\nPump on (test mode)\n");     // Don't want the pump to run in test deployment
        else
            pump_on();     // PORTD-3 is hanging in the breeze on MFET   ROM_GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_3, 0xff);
        led_red_on();

        timeout = Timer_1ms(false) + sys_data.pumpon_time*1000;

        do
        {
            ROM_SysCtlDelay(100 * MILLISECOND);

            if( UARTRxBytesAvail() )
            {
                inChar = get_key();
                if( (inChar == 24) || (inChar == 0x0d) )    //Ctrl_X or KEY_ENTER
                {
                    //uprintf("Pump cycle ended early by %u sec, due to 0x%02x / %u key\n", (timeout - Timer_1ms(false))/1000, inChar, (unsigned int)inChar);
                    uprintf("Pump cycle ended early due to 0x%02x / %u key\n", inChar, (unsigned int)inChar);
                    break;
                }
                if( sys_data.output == VERBOSE)
                    uprintf("\nPumping before sample, please wait...");
            }

        //} while( ROM_HibernateRTCGet() < timeout );
        } while( Timer_1ms(false) < timeout );

        pump_off();
        if(sys_data.test_mode == 1) uprintf("Pump off\n");
        led_red_off();
    }
#endif

    led_green_on();

    tickDelta = Timer_1ms(false) - tickDelta;
    ticks = (Timer_1ms(false) - tickStart);
    if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nPump         = %5u,   %5u", tickDelta, ticks);
    tickDelta = ticks;

    time_struct = get_RTC_time();
    strftime(timestamp, sizeof(timestamp), "%m/%d/%Y %H:%M:%S", time_struct);        // change format of date/time per Yui  7 jun 2018

#if CUT_A == 1

    openADS1248_iso();              // turn on isolated power to 24bit A/D converter
    ROM_SysCtlDelay(100*MILLISECOND);         // new, 3 Aug 2021 - BUG fix (Crash)
    ADS1248_gpio_init();            // defd in ADS1248_iso.c  (CRASH HAPPENS HERE - first call to fast_sampling is good, next call crashes

    // turn on sensor and battery monitoring circuit - needs at least 150msec to settle (use iso sampling as delay
    pwr_env_mon_on();    // Turn on Load switch for ENV monitoring
    pwr_vbat_mon_on();  //ROM_GPIOPinWrite(GPIO_PORTM_BASE, GPIO_PIN_6, 0xFF);   // Turn on VBat monitoring
    ROM_SysCtlDelay(1*MILLISECOND);         // fast sampling (was 800msec)

    adc_onchip_init();
    // read_adc_all was moved below as there is 100msec recommended for battery voltage to settle to within 1%

    tickDelta = Timer_1ms(false) - tickDelta;
    ticks = (Timer_1ms(false) - tickStart);
    if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nPwr on, init = %5u,   %5u", tickDelta, ticks);
    tickDelta = ticks;
    tick_onchip = Timer_1ms(false) ;        // for insuring 100msec settling reading input battery voltage.


    // ---- Start optode and ctd statemachines, these need to finish and be shutdown prior to pH voltage readings  -----------------
    if(sys_data.data_cfg[CFG_OPTODE] > 0)
    {
        //start the optode driver by passing 1, when complete, the statemachine returns 0
        optodeState = 1;
        optodeState = optode_stateMachine(optodeState);     //pass in 1 to start the state machine, hereafter pass retVal

        tickDelta = Timer_1ms(false) - tickDelta;
        ticks = (Timer_1ms(false) - tickStart);
        if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nOptode St8Ma = %5u,   %5u", tickDelta, ticks);
        tickDelta = ticks;
    }

    if(sys_data.data_cfg[CFG_CTD] > 0)
    {
        //start the ctd driver by passing 1, when complete, the statemachine returns 0
        ctdState = 1;
        ctdState = ctd_stateMachine(ctdState);     //pass in 1 to start the state machine, hereafter pass retVal

        tickDelta = Timer_1ms(false) - tickDelta;
        ticks = (Timer_1ms(false) - tickStart);
        if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nCTD    St8Ma = %5u,   %5u", tickDelta, ticks);
        tickDelta = ticks;
    }


    // ---------- Read the isolated domain 24 bit ADC -----------------

    // Sampling ideas.   Read each channel fast to equalize the ADC front end
    // read 'diagnostic' channels first to buy time for stabilizing.   Bias bat, Ik, Ib, Vbias
    // read pH related channels  Vtherm, Vrsi, Vrse

    //---------------------------- diagnostic voltages --------------------------------------

    if(sys_data.data_cfg[CFG_BIAS_BAT_NEG] > 0)
    {
        ADS1248_gpio3(0);
        ROM_SysCtlDelay(MILLISECOND * 10);
        //if(sys_data.app_cfg[APPCFG_SAMP_FLEX] == 1)
            fBiasNeg = pollADS1248_iso(7, 6, sys_data.Vbias_trials, 1, sys_data.Vbias_sps);     // Mux 01, Chan +7 -6, trials = 1, gain = 1, sps = 40 Hz
        //else
        //    fBiasNeg = pollADS1248_iso(7, 6, VBIAS_TRIALS, 1, VBIAS_SPS);     // Mux 01, Chan +7 -6, trials = 1, gain = 1, sps = 40 Hz
        fBiasNeg = fBiasNeg*2.0;                        // global var
    }

    if(sys_data.data_cfg[CFG_OPTODE] > 0)
    {
        optodeState = optode_stateMachine(optodeState);
        if((Timer_1ms(false) - tickDelta) > 1)
        {
            tickDelta = Timer_1ms(false) - tickDelta;
            ticks = (Timer_1ms(false) - tickStart);
            if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nOptode St8Ma = %5u,   %5u", tickDelta, ticks);
            tickDelta = ticks;
        }
    }
    if(sys_data.data_cfg[CFG_CTD] > 0)
    {
        ctdState = ctd_stateMachine(ctdState);
        if((Timer_1ms(false) - tickDelta) > 1)
        {
            tickDelta = Timer_1ms(false) - tickDelta;
            ticks = (Timer_1ms(false) - tickStart);
            if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nCTD    St8Ma = %5u,   %5u", tickDelta, ticks);
            tickDelta = ticks;
        }
    }


    if(sys_data.data_cfg[CFG_BIAS_BAT_POS] > 0)
    {
        ADS1248_gpio3(1);
        ROM_SysCtlDelay(MILLISECOND * 10);
        //if(sys_data.app_cfg[APPCFG_SAMP_FLEX] == 1)
            fBiasPos = pollADS1248_iso(7, 6, sys_data.Vbias_trials, 1, sys_data.Vbias_sps);
        //else
        //    fBiasPos = pollADS1248_iso(7, 6, VBIAS_TRIALS, 1, VBIAS_SPS);     // Mux 01, Chan +7 -6, trials = 1, gain = 1, sps = 40 Hz
        fBiasPos = fBiasPos*2.0;                        // global var
    }

    if(sys_data.data_cfg[CFG_OPTODE] > 0)
    {
        optodeState = optode_stateMachine(optodeState);
        if((Timer_1ms(false) - tickDelta) > 1)
        {
            tickDelta = Timer_1ms(false) - tickDelta;
            ticks = (Timer_1ms(false) - tickStart);
            if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nOptode St8Ma = %5u,   %5u", tickDelta, ticks);
            tickDelta = ticks;
        }
    }
    if(sys_data.data_cfg[CFG_CTD] > 0)
    {
        ctdState = ctd_stateMachine(ctdState);
        if((Timer_1ms(false) - tickDelta) > 1)
        {
            tickDelta = Timer_1ms(false) - tickDelta;
            ticks = (Timer_1ms(false) - tickStart);
            if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nCTD    St8Ma = %5u,   %5u", tickDelta, ticks);
            tickDelta = ticks;
        }
    }

    if(sys_data.data_cfg[CFG_BIAS_BAT_POS] > 0)
    {
        ADS1248_gpio3(1);
        ROM_SysCtlDelay(MILLISECOND * 10);
        fBiasPos = pollADS1248_iso(7, 6, sys_data.Vbias_trials, 1, sys_data.Vbias_sps);
        //    fBiasPos = pollADS1248_iso(7, 6, VBIAS_TRIALS, 1, VBIAS_SPS);     // Mux 01, Chan +7 -6, trials = 1, gain = 1, sps = 40 Hz
        fBiasPos = fBiasPos*2.0;                        // global var
    }

#ifdef OLDCODE
    // report whichever battery voltage is lower (the minus supply or the plus supply)  //TODO, make separate measurements / config data fields
    fBias_bat_lowest = fBiasPos;
    if(fBiasPos > (-1*fBiasNeg))
        fBias_bat_lowest = fBiasNeg;
#endif

    if((sys_data.data_cfg[CFG_BIAS_BAT_POS] > 0) || (sys_data.data_cfg[CFG_BIAS_BAT_NEG] > 0))
    if((Timer_1ms(false) - tickDelta) > 1)
    {
        tickDelta = Timer_1ms(false) - tickDelta;
        ticks = (Timer_1ms(false) - tickStart);
        if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nBias Bat     = %5u,   %5u", tickDelta, ticks);
        tickDelta = ticks;
    }


    // --- Finish sampling and turn off external instruments (CTD / Optode) ------
    if(sys_data.data_cfg[CFG_OPTODE] > 0)
    {

        while(1)
        {
            if(optodeState == 0)            // makes sure optode statemachine is finished
                break;
            optodeState = optode_stateMachine(optodeState);

        }
        tickDelta = Timer_1ms(false) - tickDelta;
        ticks = (Timer_1ms(false) - tickStart);
        if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nOptode       = %5u,   %5u", tickDelta, ticks);
        tickDelta = ticks;
    }

    if(sys_data.data_cfg[CFG_CTD] > 0)
    {

        while(1)
        {
            if(ctdState == 0)            // makes sure ctd statemachine is finished
                break;
            ctdState = ctd_stateMachine(ctdState);

        }
        tickDelta = Timer_1ms(false) - tickDelta;
        ticks = (Timer_1ms(false) - tickStart);
        if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nCTD          = %5u,   %5u", tickDelta, ticks);
        tickDelta = ticks;
    }

    // CTD and Optode state machines when finished turn off the instrument power.  Instrument Power for both is now off.

    //---------------------------- engineering data for isfet --------------------------------------

    // ----------- Ib Subst Cur, (Diagnostic) ------------------
    if(sys_data.data_cfg[CFG_I_SUBSTRATE] > 0)
    {
        ADS1248_gpio_ADG1609_mux(2);
        ROM_SysCtlDelay(MILLISECOND * 10);      // 10msec settling for MUX analog
        fIb = pollADS1248_iso(1, 6, sys_data.Ib_trials, 1, sys_data.Ib_sps);       // GLIDER 1 sample, 20 hz
        fIb *= SUBSTRATECURRENT_IB_SCALING;   // convert to nanoAmps (multiply by 1000)         // new 2 Apr 2021

        tickDelta = Timer_1ms(false) - tickDelta;
        ticks = (Timer_1ms(false) - tickStart);
        if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nIb Substrate = %5u,   %5u", tickDelta, ticks);
        tickDelta = ticks;
    }

    // ------------ Ik, CntrE Cur, (GLIDER)  Counter Electrode Current -------------
    if(sys_data.data_cfg[CFG_I_COUNTER] > 0)
    {
        ADS1248_gpio_ADG1609_mux(1);
        ROM_SysCtlDelay(MILLISECOND * 10);      // 10msec settling for MUX analog

        fIk = pollADS1248_iso(1, 5, sys_data.Ik_trials, 1, sys_data.Ik_sps);  // 3*25ms=75msec Chan +5 -1, trials = 1, gain = 1, sps = 20 Hz  //   GLIDER 40Hz

        // 15uV/nA for Ik - assuming Ik is counter electrode current.
        // V=IR  15uV = 1nA * R (15Kohm)
        fIk -= sys_data.offset_Ik;   // subtract opamp input offet voltage
        fIk *= COUNTERELECTRODE_IK_SCALE;

        fIk_std = sys_samp.AD24_std;        // Std dev does not apply with trials = 1
        fIk_std *= COUNTERELECTRODE_IK_SCALE;      // new 2 Apr 2021

        tickDelta = Timer_1ms(false) - tickDelta;
        ticks = (Timer_1ms(false) - tickStart);
        if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nIk Cntr E    = %5u,   %5u", tickDelta, ticks);
        tickDelta = ticks;
    }


    // Vk, Counter Electrode Voltage, CntrE Volt, (Diagnostic)
    if(sys_data.data_cfg[CFG_V_COUNTER_ELECT] > 0)
    {
        ADS1248_gpio_ADG1609_mux(1);
        ROM_SysCtlDelay(MILLISECOND * 10);      // 10msec settling for MUX analog
        fVk = pollADS1248_iso(1, 6, sys_data.Vk_trials, 1, sys_data.Vk_sps);   // Mux 01, Chan +1 -6, trials = 5, gain = 1, sps = 20 Hz
        fVk_std = sys_samp.AD24_std;

        tickDelta = Timer_1ms(false) - tickDelta;
        ticks = (Timer_1ms(false) - tickStart);
        if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nVk Cntr E    = %5u,   %5u", tickDelta, ticks);
        tickDelta = ticks;
    }


    //---------------------------- pH related voltages --------------------------------------

    //------------ Vtherm, Thermistor Voltage ----------------
    if(sys_data.data_cfg[CFG_V_THERMISTOR] > 0)
    {

        fVtherm = pollADS1248_iso(0, 6, sys_data.Vtherm_trials, 1, sys_data.Vtherm_sps);       // Chan +0 -6, trials = 5, gain = 1, sps = 20 Hz (per Yui 5May2021)
        fVtherm_std = sys_samp.AD24_std;

        tickDelta = Timer_1ms(false) - tickDelta;
        ticks = (Timer_1ms(false) - tickStart);
        if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nVtherm       = %5u,   %5u", tickDelta, ticks);
        tickDelta = ticks;
    }



    //-------------- Vrsi_B, Int Ref Off, ------------------------
    if(sys_data.data_cfg[CFG_VRSI_BIASED] > 0)     // Not valid on nanoFET
    {
#if BOARD_MFET >= 1 || BOARD_MPHOX >= 1
        //dbg_printf("\nno intref on glider\n");
        ADS1248_gpio_ADG1609_mux(3);
        ROM_SysCtlDelay(MILLISECOND * 10);      // 10msec settling for MUX analog

        fVrsi_B = pollADS1248_iso(1, 5, sys_data.Vrsi_trials, 1, sys_data.Vrsi_sps);  // 200msec Chan +1 -5, trials = 10, gain = user, sps = 20 Hz
        fVrsi_B_std = sys_samp.AD24_std;

#endif
#if BOARD_NANOFET >= 1
        // Int Ref with offset not applicable on nanoFET per Scott
        fVrsi_B = 0.0;
        fVrsi_B_std = 0.0;
#endif
        tickDelta = Timer_1ms(false) - tickDelta;
        ticks = (Timer_1ms(false) - tickStart);
        if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nVrsi_B       = %5u,   %5u", tickDelta, ticks);
        tickDelta = ticks;
    }



    // ----------- Vrsi (aka Vint) --------------
    if(sys_data.data_cfg[CFG_VRSI] > 0)        // Not valid on nanoFET
    {
#if BOARD_MFET >= 1 || BOARD_MPHOX >= 1
        //dbg_printf("\nno Vrsi on glider, not valid on nanoFET\n");
        ADS1248_gpio_ADG1609_mux(3);
        ROM_SysCtlDelay(MILLISECOND * 10);      // 10msec settling for MUX analog
        fVrsi = pollADS1248_iso(1, 6, sys_data.Vrsi_trials, 1, sys_data.Vrsi_sps);       // Chan +1 -6, trials = 10, gain = 1, sps = 20 Hz (10*50ms = 500ms)
        fVrsi_std = sys_samp.AD24_std;

#endif
#if BOARD_NANOFET >= 1
        fVrsi = 0.0;
        fVrsi_std = 0.0;
#endif

        tickDelta = Timer_1ms(false) - tickDelta;
        ticks = (Timer_1ms(false) - tickStart);
        if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nVrsi         = %5u,   %5u", tickDelta, ticks);
        tickDelta = ticks;
    }



    // --------- Vrse_B, Ext Ref Offset, -------------
    if(sys_data.data_cfg[CFG_VRSE_BIASED] > 0)     // Not valid on nanoFET
    {
#if BOARD_MFET >= 1 || BOARD_MPHOX >= 1
        //dbg_printf("\nno extref on glider\n");
        ADS1248_gpio_ADG1609_mux(0);
        ROM_SysCtlDelay(MILLISECOND * 10);      // 10msec settling for MUX analog
        fVrse_B = pollADS1248_iso(1, 5, sys_data.Vrse_trials, 1, sys_data.Vrse_sps);       // 200msec Chan +1 -5, trials = 10, gain = user, sps = 20 Hz
        fVrse_B_std = sys_samp.AD24_std;

#endif
#if BOARD_NANOFET >= 1
        fVrse_B = 0.0;
        fVrse_B_std = 0.0;
#endif
        tickDelta = Timer_1ms(false) - tickDelta;
        ticks = (Timer_1ms(false) - tickStart);
        if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nVrse_B       = %5u,   %5u", tickDelta, ticks);
        tickDelta = ticks;
    }




    // ----------- fVrse ----------------------
    if(sys_data.data_cfg[CFG_VRSE] > 0)
    {
        ADS1248_gpio_ADG1609_mux(0);
        ROM_SysCtlDelay(MILLISECOND * 10);      // 10msec settling for MUX analog
        fVrse = 0.0;         // new 30 Mar 2021
#if BOARD_MFET >= 1 || BOARD_MPHOX >= 1     //6 (gnd) NOT available on nanoFET
        fVrse = pollADS1248_iso(1, 6, sys_data.Vrse_trials, 1, sys_data.Vrse_sps);  // 10x50msec= 500msec  trials=10, gain=1, sps=20
#endif
#if BOARD_NANOFET >= 1
            // 6 (GND) is not connected on nanoFET
        fVrse = pollADS1248_iso(1, 5, sys_data.Vrse_trials, 1, sys_data.Vrse_sps);  // 10x50msec= 500msec  trials=10, gain=1, sps=20
#endif
        fVrse_std = sys_samp.AD24_std;

        tickDelta = Timer_1ms(false) - tickDelta;
        ticks = (Timer_1ms(false) - tickStart);
        if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nVrse         = %5u,   %5u", tickDelta, ticks);
        tickDelta = ticks;
    }


    // ------------- read internal adc (battery, etc), -----------------------
    // requires  adc_onchip_init(); is called and settled for 100msec or so prior to read_all_adc

    // fix for low reading of battery voltage when few fields are config'd 21 Jul 2021
    while(1)
    {
        if((Timer_1ms(false) - tick_onchip) > 150)      // at least 150msec for proper vbat reading
            break;
        ROM_SysCtlDelay(MILLISECOND * 5);
    }

    read_all_adc();
    read_all_adc();     // read a second time for better fidelity

    // battery voltage must be read for 'too low' check at bottom
    fVbat_main = (float)(adc_data[0]*100);
    fVbat_main /= 18193.77;      // 30 Sep 2019  11.75v is measured with Agilent meter as 12.069v
                               // must compute battery voltage as it is checked for 'too low' below

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

    // LM60 temp
    if(sys_data.data_cfg[CFG_BRD_TEMP] > 0)
    {
        fBrdTempC = ((((float)adc_data[4])*0.80566) - 424) / 6.25;   //VOut= (+6.25 mV/°C × T °C) + 424 mV  // LM60 temperature sensor - formula from datasheet / schematic (good job Scott)
    }

    // Humidity
    if(sys_data.data_cfg[CFG_BRD_HUMIDITY] > 0)
    {
        // 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;

        fHumidity = (float)( (adc_data[2] * 100) );  // VOUT=(VSUPPLY)(0.00636(sensor RH) + 0.1515), typical at 25C
        fHumidity /= 3284;
        uiHumidity = (adc_data[2] * 100) / 3284;
    }

    tickDelta = Timer_1ms(false) - tickDelta;
    ticks = (Timer_1ms(false) - tickStart);
    if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nOnchip ADC   = %5u,   %5u", tickDelta, ticks);
    tickDelta = ticks;

    int stopFlg;
    stopFlg = 0;


    // Check for low battery voltage. Exit and sleep if too low.
    if( fVbat_main < (sys_data.low_batt_volt + 0.005) )
    {
        pwr_vbat_mon_on();
        ROM_SysCtlDelay(MILLISECOND * 10);
        adc_onchip_init();
        ROM_SysCtlDelay(MILLISECOND * 100);
        for(indx=0; indx<5; indx++)
        {
            if(indx < 4)
                uprintf("\nLow battery voltage (%.2f < %.2f) !\n", fVbat_main, sys_data.low_batt_volt );
            else
                uprintf("\nLow battery voltage (%.2f < %.2f) ! Exiting deploy mode...\n", fVbat_main, sys_data.low_batt_volt );
            wait_consoleTx();

            ROM_SysCtlDelay(MILLISECOND * 150);

            read_all_adc();
            read_all_adc();     // read a second time for better fidelity

            // battery voltage must be read for 'too low' check at bottom
            fVbat_main = (float)(adc_data[0]*100);
            fVbat_main /= 18193.77;

            // if the input voltage is above the low batt threshold, then go ahead with the sample.   If after 5 checks, then SLEEP in IDLE and stop sampling to prevent uSD card failure
            if(fVbat_main > sys_data.low_batt_volt)
            {
                stopFlg = 0;
                break;
            }
            else
            {
                stopFlg = 1;
            }

            led_red_on();
            led_green_off();
            delay_msec(500);

            led_red_off();
            led_green_on();
            delay_msec(500);
        }

        if(stopFlg == 1)
        {
            error_store("Low battery! Exiting deploy mode");
            sleep(IDLE, 0);     // Sleep until woken by user, halt rtc wakeup by changing state to IDLE
        }
    } // Low voltage handler


    // poweroff monitoring circuitry
    pwr_vbat_mon_off();   // Turn off VBat monitoring
    pwr_env_mon_off();    // Turn off Load switch for ENV monitoring

    // Shutdown sensor power supply
    closeADS1248_iso();

#endif // CUT_A

    // ---------- Calculate the external and internal pH values -------------------------

    if(sys_data.data_cfg[CFG_CALC_TEMP] > 0)
    {
        fTempC = DuraFET_temp(fVtherm, sys_data.TCOffset);

        tickDelta = Timer_1ms(false) - tickDelta;
        ticks = (Timer_1ms(false) - tickStart);
        if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nCalc TempC   = %5u,   %5u", tickDelta, ticks);
        tickDelta = ticks;
    }



    if(sys_data.data_cfg[CFG_CALC_PH_VRSE] > 0)
    {
        if(sys_data.data_cfg[CFG_CTD] == 0)
            SBE_sal = sys_data.default_sal;       // for pH_ext calc  (init'd to 35.0)
        else
            SBE_sal = sys_data.sensor_sal;
        // Todo sys_data.sensor_sal;
        pHext = calc_pHext(fVrse, fTempC, SBE_sal);  // NOTE: this might be Vrse_B that is needed....   5 May 2021

        tickDelta = Timer_1ms(false) - tickDelta;
        ticks = (Timer_1ms(false) - tickStart);
        if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nCalc pH Ext  = %5u,   %5u", tickDelta, ticks);
        tickDelta = ticks;
    }



    if(sys_data.data_cfg[CFG_CALC_PH_VRSI] > 0)
    {
        // requires TC and fVrsi_B
        pHint = calc_pHint(fVrsi_B, fTempC);   // per YUI  7 Jun 2018

        tickDelta = Timer_1ms(false) - tickDelta;
        ticks = (Timer_1ms(false) - tickStart);
        if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nCalc pH Int  = %5u,   %5u", tickDelta, ticks);
        tickDelta = ticks;
    }





    //#000000    12.03           -3.59        0.997431        0.674842        -0.055235       0.000005        -0.799272       0.000004        -0.500569       0.000005        18178.39        -399.644        24.707  18.18122

    indx = 0;
    // for column alignment between data and header, 8 chars per field  - note, a negative sign throws off the print format

    if(sys_data.data_cfg[CFG_SAMPLE_NUM] > 0)       { indx += sprintf(&prnBuf[indx], "#%07u\t", sys_samp.current_sample);   } //0  // was %07d
    if(sys_data.data_cfg[CFG_TIMEDATE] > 0)         { indx += sprintf(&prnBuf[indx], "     %s\t", timestamp);               } //1

    if(sys_data.data_cfg[CFG_VIN_BAT_VOLT] > 0)     { indx += sprintf(&prnBuf[indx], "%8.2f\t", fVbat_main);            } //2  // was %5.2f
    if(sys_data.data_cfg[CFG_BIAS_BAT_POS] > 0)     { indx += sprintf(&prnBuf[indx], "%8.2f\t", fBiasPos);                  } //5  5.2
    if(sys_data.data_cfg[CFG_BIAS_BAT_NEG] > 0)     { indx += sprintf(&prnBuf[indx], "%8.2f\t", fBiasNeg);                  } //5  5.2
    if(sys_data.data_cfg[CFG_BRD_TEMP] > 0)     { indx += sprintf(&prnBuf[indx], "%8.2f\t", fBrdTempC);                  } //3  // was %5.2f
    if(sys_data.data_cfg[CFG_BRD_HUMIDITY] > 0)     { indx += sprintf(&prnBuf[indx], "%8u\t", uiHumidity);                  } //4  // was %3u

    if(sys_data.data_cfg[CFG_V_THERMISTOR] > 0)     { indx += sprintf(&prnBuf[indx], "%8.6f\t", fVtherm);                    } //6
    if(sys_data.data_cfg[CFG_V_THERMISTOR_STD] > 0) { indx += sprintf(&prnBuf[indx], "%8.6f\t", fVtherm_std);                } //7
    if(sys_data.data_cfg[CFG_CALC_TEMP] > 0)        { indx += sprintf(&prnBuf[indx], "%8.3f\t", fTempC);                        } //20

    if(sys_data.data_cfg[CFG_VRSI] > 0)            { indx += sprintf(&prnBuf[indx], "%8.6f\t", fVrsi);                      } //12
    if(sys_data.data_cfg[CFG_VRSI_STD] > 0)        { indx += sprintf(&prnBuf[indx], "%8.6f\t", fVrsi_std);                  } //13
    if(sys_data.data_cfg[CFG_CALC_PH_VRSI] > 0)       { indx += sprintf(&prnBuf[indx], "%8.3f\t", pHint);                     } //21

    if(sys_data.data_cfg[CFG_VRSE] > 0)            { indx += sprintf(&prnBuf[indx], "%8.6f\t", fVrse);                  } //14
    if(sys_data.data_cfg[CFG_VRSE_STD] > 0)        { indx += sprintf(&prnBuf[indx], "%8.6f\t", fVrse_std);                  } //15
    if(sys_data.data_cfg[CFG_CALC_PH_VRSE] > 0)       { indx += sprintf(&prnBuf[indx], "%8.3f\t", pHext);                     } //22

    if(sys_data.data_cfg[CFG_VRSI_BIASED] > 0)     { indx += sprintf(&prnBuf[indx], "%8.6f\t", fVrsi_B);         } //8
    if(sys_data.data_cfg[CFG_VRSI_BIASED_STD] > 0) { indx += sprintf(&prnBuf[indx], "%8.6f\t", fVrsi_B_std);     } //9
    if(sys_data.data_cfg[CFG_VRSE_BIASED] > 0)     { indx += sprintf(&prnBuf[indx], "%8.6f\t", fVrse_B);         } //10
    if(sys_data.data_cfg[CFG_VRSE_BIASED_STD] > 0) { indx += sprintf(&prnBuf[indx], "%8.6f\t", fVrse_B_std);     } //11

    if(sys_data.data_cfg[CFG_V_COUNTER_ELECT] > 0)  { indx += sprintf(&prnBuf[indx], "%8.6f\t", fVk);   } //16
    if(sys_data.data_cfg[CFG_V_COUNTER_ELECT_STD] > 0)  { indx += sprintf(&prnBuf[indx], "%8.6f\t", fVk_std);  } //17
    if(sys_data.data_cfg[CFG_I_COUNTER] > 0)        { indx += sprintf(&prnBuf[indx], "%8.2f\t", fIk);   } //18
    if(sys_data.data_cfg[CFG_I_SUBSTRATE] > 0)      { indx += sprintf(&prnBuf[indx], "%8.3f\t", fIb);          } //19

    if(sys_data.data_cfg[CFG_OPTODE] > 0)           { indx += sprintf(&prnBuf[indx], "%s\t", optode.buf);                   } //23
    if(sys_data.data_cfg[CFG_CTD] > 0)              { indx += sprintf(&prnBuf[indx], "%s\t", ctd.buf);                      } //23

    tickDelta = Timer_1ms(false) - tickDelta;
    ticks = (Timer_1ms(false) - tickStart);
    if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nformat data  = %5u,   %5u\n", tickDelta, ticks);
    tickDelta = ticks;

    tickEnd = Timer_1ms(false);
    ticks = (tickEnd - tickStart);
    //uprintf("(Time: %u msec)", ticks );
    if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1)  indx += sprintf(&prnBuf[indx], "(%u msec)\t", ticks);
    indx += sprintf(&prnBuf[indx], "\r\n");  // should this be cr-lf?
    prnBuf[indx] = 0;       // new, trying to track down a bug where the string does not print all the way, might not be 0 term

    //if(txFlg == 1) uprintf("%s", prnBuf);      // uprint maximum is 255 sample to console
    if(txFlg == 1) UARTwrite(prnBuf, strlen(prnBuf));



    if(microSD_flg == 1)
    {
         //FA_OPEN_APPEND is not supported in this fatfs version
         // Open a file
        fresult = f_open(&fileObject, sys_data.fileName, FA_READ | FA_WRITE | FA_OPEN_ALWAYS);
         if(fresult != FR_OK)
         {
             // != FR_OK
             uprintf("f_open error: %s\n", StringFromFresult(fresult));
             error_store("f_open error");

         }
         else  // FILE is open
         {
             //uprintf("\nSampling... f_open is good\n"); // THOM DEBUG

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

                 // 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("f_write error: %s\n", StringFromFresult(fresult));
                  }
                  else
                  {
                      //uprintf("\nSampling... f_write is good\n"); // THOM DEBUG
                  }

             }


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

         }



    } // if microSD_flg

    tickDelta = Timer_1ms(false) - tickDelta;
    ticks = (Timer_1ms(false) - tickStart);
    if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nuSD writes   = %5u,   %5u", tickDelta, ticks);
    tickDelta = ticks;

    wait_consoleTx();

    tickDelta = Timer_1ms(false) - tickDelta;
    ticks = (Timer_1ms(false) - tickStart);
    if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nwait TX      = %5u,   %5u", tickDelta, ticks);
    tickDelta = ticks;

    sys_samp.current_sample++;  // Increment the sample counter, this is stored to FRAM in sleep() routine

    led_green_off();

    // Low voltage check was here, moved up before uSD write

// .diag is gone

}


void exercise_iso(void)
{
    float fVtherm, fVtherm_std;

    openADS1248_iso();              // turn on isolated power to 24bit A/D converter
    ADS1248_gpio_init();            // defd in ADS1248_iso.c

    // turn on sensor and battery monitoring circuit - needs at least 150msec to settle (use iso sampling as delay
    pwr_env_mon_on();    // Turn on Load switch for ENV monitoring
    pwr_vbat_mon_on();  //ROM_GPIOPinWrite(GPIO_PORTM_BASE, GPIO_PIN_6, 0xFF);   // Turn on VBat monitoring

    ROM_SysCtlDelay(1*MILLISECOND);         // fast sampling (was 800msec)

    adc_onchip_init();

    ROM_SysCtlDelay(100*MILLISECOND);

    fVtherm = pollADS1248_iso(0, 6, sys_data.Vtherm_trials, 1, sys_data.Vtherm_sps);       // Chan +0 -6, trials = 5, gain = 1, sps = 20 Hz (per Yui 5May2021)
    fVtherm_std = sys_samp.AD24_std;

    uprintf("\nThermistor = %.6f\n", fVtherm);

    ROM_SysCtlDelay(900*MILLISECOND);


    // poweroff monitoring circuitry
    pwr_vbat_mon_off();   // Turn off VBat monitoring
    pwr_env_mon_off();    // Turn off Load switch for ENV monitoring

    // Shutdown sensor power supply
    closeADS1248_iso();

}


#ifdef OLDCODE
void OLD_fast_sample(int txFlg)
{
    char timestamp[TIMESTAMPLENGTH];
    uint32_t timeout;
    uint32_t tickStart, ticks, tickDelta, tickEnd;
    struct tm *time_struct;

    float fVtherm;           // DuraFET raw temperature voltage
    float fVtherm_std;       // Std Dev for Durafet Thermistor
    float fTempC;            // Calculated DuraFET temperature
    //float fExtTemp;

    float fVrsi;             // DuraFET internal reference voltage   (Vint)
    float fVrsi_std;         // Std Dev for Durafet Internal Voltage
    float pHint;             // Calculated pH using internal reference

    float fVrse;             // External (AUX) reference voltage  (Vrs)
    float fVrse_std;         // Std Dev for Durafet External Voltage
    float pHext;             // Calculated pH using external reference

    float SBE_sal;           // MicroCAT salinity

    float fVrse_B;
    float fVrse_B_std;
    float fVrsi_B;
    float fVrsi_B_std;

    float fIk;              // (Ik) CounterElectrodeCurrent
    float fIk_std;
    float fVk;              // (Vk) CounterElectrodeVoltage
    float fVk_std;
    float fIb;              // (Ib) SubstrateCurrent
                            // float SubstrateVoltage;  //float SubstrateVoltage_std;
    float fVbat_main;
    float fBias_bat_lowest;

    float fHumidity;
    float fBrdTempC;
    uint32_t  uiHumidity;
    uint32_t  uiWater;

    uint32_t indx;
    int optodeState;
    int ctdState;

    FIL fileObject;
    FRESULT fresult;
    INT bw;

    optodeState = 0;
    ctdState = 0;

    tickStart = Timer_1ms(true);
    tickDelta = tickStart;
    char inChar;

    if(sys_data.test_mode == 1)
        uprintf("\nSampling...");

    //sys_data.app_cfg[APPCFG_SAMP_FLEX] = 1;   //FORCE use of the variables for trials and sps
    //sys_data.app_cfg[APPCFG_SAMPLING_DIAG] = 1;   //FORCE the timing data output

#if BOARD_MPHOX >= 1
    if(sys_data.pumpon_time > 0)
    {
        // Pump on time
        if(sys_data.test_mode == 1)
            uprintf("\nPump on (test mode)\n");     // Don't want the pump to run in test deployment
        else
            pump_on();     // PORTD-3 is hanging in the breeze on MFET   ROM_GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_3, 0xff);
        led_red_on();

        timeout = Timer_1ms(false) + sys_data.pumpon_time*1000;

        do
        {
            ROM_SysCtlDelay(100 * MILLISECOND);

            if( UARTRxBytesAvail() )
            {
                inChar = get_key();
                if( (inChar == 24) || (inChar == 0x0d) )    //Ctrl_X or KEY_ENTER
                {
                    //uprintf("Pump cycle ended early by %u sec, due to 0x%02x / %u key\n", (timeout - Timer_1ms(false))/1000, inChar, (unsigned int)inChar);
                    uprintf("Pump cycle ended early due to 0x%02x / %u key\n", inChar, (unsigned int)inChar);
                    break;
                }
                if( sys_data.output == VERBOSE)
                    uprintf("\nPumping before sample, please wait...");
            }

        //} while( ROM_HibernateRTCGet() < timeout );
        } while( Timer_1ms(false) < timeout );

        pump_off();
        if(sys_data.test_mode == 1) uprintf("Pump off\n");
        led_red_off();
    }
#endif

    led_green_on();

    tickDelta = Timer_1ms(false) - tickDelta;
    ticks = (Timer_1ms(false) - tickStart);
    if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nPump         = %5u,   %5u", tickDelta, ticks);
    tickDelta = ticks;

    time_struct = get_RTC_time();
    strftime(timestamp, sizeof(timestamp), "%m/%d/%Y %H:%M:%S", time_struct);        // change format of date/time per Yui  7 jun 2018

    openADS1248_iso();              // turn on isolated power to 24bit A/D converter
    ADS1248_gpio_init();            // defd in ADS1248_iso.c

    // turn on sensor and battery monitoring circuit - needs at least 150msec to settle (use iso sampling as delay
    pwr_env_mon_on();    // Turn on Load switch for ENV monitoring
    pwr_vbat_mon_on();  //ROM_GPIOPinWrite(GPIO_PORTM_BASE, GPIO_PIN_6, 0xFF);   // Turn on VBat monitoring

    ROM_SysCtlDelay(1*MILLISECOND);         // fast sampling (was 800msec)

#ifdef NOCODE
    if(sys_data.data_cfg[CFG_OPTODE] > 0)  { optodeState = optode_stateMachine(optodeState); }
    if(sys_data.data_cfg[CFG_CTD] > 0)   { ctdState = ctd_stateMachine(ctdState);    }
#endif

    adc_onchip_init();
    // read_adc_all was moved below as there is 100msec recommended for battery voltage to settle to within 1%

    tickDelta = Timer_1ms(false) - tickDelta;
    ticks = (Timer_1ms(false) - tickStart);
    if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nPwr on, init = %5u,   %5u", tickDelta, ticks);
    tickDelta = ticks;

#ifdef NOCODE
    // Open and poll the microCat and Optode
    if(sys_data.data_cfg[CFG_OPTODE] > 0)
    {
        //start the optode driver by passing 1, when complete, the statemachine returns 0
        optodeState = 1;
        optodeState = optode_stateMachine(optodeState);     //pass in 1 to start the state machine, hereafter pass retVal

        tickDelta = Timer_1ms(false) - tickDelta;
        ticks = (Timer_1ms(false) - tickStart);
        if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nOptode St8Ma = %5u,   %5u", tickDelta, ticks);
        tickDelta = ticks;
    }

    if(sys_data.data_cfg[CFG_CTD] > 0)
    {
        //start the ctd driver by passing 1, when complete, the statemachine returns 0
        ctdState = 1;
        ctdState = ctd_stateMachine(ctdState);     //pass in 1 to start the state machine, hereafter pass retVal

        tickDelta = Timer_1ms(false) - tickDelta;
        ticks = (Timer_1ms(false) - tickStart);
        if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nCondo  St8Ma = %5u,   %5u", tickDelta, ticks);
        tickDelta = ticks;
    }
#endif

    // ---------- Read the isolated domain 24 bit ADC -----------------

    // Sampling ideas.   Read each channel fast to equalize the ADC front end
    // read 'diagnostic' channels first to buy time for stabilizing.   Bias bat, Ik, Ib, Vbias
    // read pH related channels  Vtherm, Vrsi, Vrse

    //---------------------------- diagnostic voltages --------------------------------------

    if(sys_data.data_cfg[CFG_BIAS_BAT_NEG] > 0)
    {
        ADS1248_gpio3(0);
        ROM_SysCtlDelay(MILLISECOND * 10);
        //if(sys_data.app_cfg[APPCFG_SAMP_FLEX] == 1)
            fBiasNeg = pollADS1248_iso(7, 6, sys_data.Vbias_trials, 1, sys_data.Vbias_sps);     // Mux 01, Chan +7 -6, trials = 1, gain = 1, sps = 40 Hz
        //else
        //    fBiasNeg = pollADS1248_iso(7, 6, VBIAS_TRIALS, 1, VBIAS_SPS);     // Mux 01, Chan +7 -6, trials = 1, gain = 1, sps = 40 Hz
        fBiasNeg = fBiasNeg*2.0;                        // global var
    }

    if(sys_data.data_cfg[CFG_BIAS_BAT_POS] > 0)
    {
        ADS1248_gpio3(1);
        ROM_SysCtlDelay(MILLISECOND * 10);
        //if(sys_data.app_cfg[APPCFG_SAMP_FLEX] == 1)
            fBiasPos = pollADS1248_iso(7, 6, sys_data.Vbias_trials, 1, sys_data.Vbias_sps);
        //else
        //    fBiasPos = pollADS1248_iso(7, 6, VBIAS_TRIALS, 1, VBIAS_SPS);     // Mux 01, Chan +7 -6, trials = 1, gain = 1, sps = 40 Hz
        fBiasPos = fBiasPos*2.0;                        // global var
    }


    // report whichever battery voltage is lower (the minus supply or the plus supply)  //TODO, make separate measurements / config data fields
    fBias_bat_lowest = fBiasPos;
    if(fBiasPos > (-1*fBiasNeg))
        fBias_bat_lowest = fBiasNeg;

    if((sys_data.data_cfg[CFG_BIAS_BAT_POS] > 0) || (sys_data.data_cfg[CFG_BIAS_BAT_NEG] > 0))
    if((Timer_1ms(false) - tickDelta) > 1)
    {
        tickDelta = Timer_1ms(false) - tickDelta;
        ticks = (Timer_1ms(false) - tickStart);
        if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nBias Bat     = %5u,   %5u", tickDelta, ticks);
        tickDelta = ticks;
    }

#ifdef NOCODE
    if(sys_data.data_cfg[CFG_OPTODE] > 0)
    {
        optodeState = optode_stateMachine(optodeState);
        if((Timer_1ms(false) - tickDelta) > 1)
        {
            tickDelta = Timer_1ms(false) - tickDelta;
            ticks = (Timer_1ms(false) - tickStart);
            if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nOptode       = %5u,   %5u", tickDelta, ticks);
            tickDelta = ticks;
        }
    }
    if(sys_data.data_cfg[CFG_CTD] > 0)
    {
        ctdState = ctd_stateMachine(ctdState);
        if((Timer_1ms(false) - tickDelta) > 1)
        {
            tickDelta = Timer_1ms(false) - tickDelta;
            ticks = (Timer_1ms(false) - tickStart);
            if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nCondo        = %5u,   %5u", tickDelta, ticks);
            tickDelta = ticks;
        }
    }
#endif



    // ----------- Ib Subst Cur, (Diagnostic) ------------------
    if(sys_data.data_cfg[CFG_I_SUBSTRATE] > 0)
    {
        ADS1248_gpio_ADG1609_mux(2);
        ROM_SysCtlDelay(MILLISECOND * 10);      // 10msec settling for MUX analog
        //if(sys_data.app_cfg[APPCFG_SAMP_FLEX] == 1)
            fIb = pollADS1248_iso(1, 6, sys_data.Ib_trials, 1, sys_data.Ib_sps);       // GLIDER 1 sample, 20 hz
        //else
        //    fIb = pollADS1248_iso(1, 6, IB_TRIALS, 1, IB_SPS);       //  Mux 10, Chan +1 -6, trials = 1, gain = 1, sps = 20 Hz

        fIb *= SUBSTRATECURRENT_IB_SCALING;   // convert to nanoAmps (multiply by 1000)         // new 2 Apr 2021

        tickDelta = Timer_1ms(false) - tickDelta;
        ticks = (Timer_1ms(false) - tickStart);
        if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nIb Substrate = %5u,   %5u", tickDelta, ticks);
        tickDelta = ticks;

    }

#ifdef NOCODE
    if(sys_data.data_cfg[CFG_OPTODE] > 0)
    {
        optodeState = optode_stateMachine(optodeState);
        if((Timer_1ms(false) - tickDelta) > 1)
        {
            tickDelta = Timer_1ms(false) - tickDelta;
            ticks = (Timer_1ms(false) - tickStart);
            if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nOptode       = %5u,   %5u", tickDelta, ticks);
            tickDelta = ticks;
        }
    }
    if(sys_data.data_cfg[CFG_CTD] > 0)
    {
        ctdState = ctd_stateMachine(ctdState);
        if((Timer_1ms(false) - tickDelta) > 1)
        {
            tickDelta = Timer_1ms(false) - tickDelta;
            ticks = (Timer_1ms(false) - tickStart);
            if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nCondo        = %5u,   %5u", tickDelta, ticks);
            tickDelta = ticks;
        }
    }
#endif


    // ------------ Ik, CntrE Cur, (GLIDER)  Counter Electrode Current -------------
    if(sys_data.data_cfg[CFG_I_COUNTER] > 0)
    {
        ADS1248_gpio_ADG1609_mux(1);
        ROM_SysCtlDelay(MILLISECOND * 10);      // 10msec settling for MUX analog
        //if(sys_data.app_cfg[APPCFG_SAMP_FLEX] == 1)
            fIk = pollADS1248_iso(1, 5, sys_data.Ik_trials, 1, sys_data.Ik_sps);  // 3*25ms=75msec Chan +5 -1, trials = 1, gain = 1, sps = 20 Hz  //   GLIDER 40Hz
        //else
        //    fIk = pollADS1248_iso(1, 5, IK_TRIALS, 1, IK_SPS);  // Mux=01 Chan +5 -1, trials = 1, gain = 1, sps = 20 Hz  //

        // 15uV/nA for Ik - assuming Ik is counter electrode current.
        // V=IR  15uV = 1nA * R (15Kohm)
        fIk -= sys_data.offset_Ik;   // subtract opamp input offet voltage
        fIk *= COUNTERELECTRODE_IK_SCALE;

        fIk_std = sys_samp.AD24_std;        // Std dev does not apply with trials = 1
        fIk_std *= COUNTERELECTRODE_IK_SCALE;      // new 2 Apr 2021

        tickDelta = Timer_1ms(false) - tickDelta;
        ticks = (Timer_1ms(false) - tickStart);
        if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nIk Cntr E    = %5u,   %5u", tickDelta, ticks);
        tickDelta = ticks;
    }

#ifdef NOCODE
    if(sys_data.data_cfg[CFG_OPTODE] > 0)
    {
        optodeState = optode_stateMachine(optodeState);
        if((Timer_1ms(false) - tickDelta) > 1)
        {
            tickDelta = Timer_1ms(false) - tickDelta;
            ticks = (Timer_1ms(false) - tickStart);
            if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nOptode       = %5u,   %5u", tickDelta, ticks);
            tickDelta = ticks;
        }
    }
    if(sys_data.data_cfg[CFG_CTD] > 0)
    {
        ctdState = ctd_stateMachine(ctdState);
        if((Timer_1ms(false) - tickDelta) > 1)
        {
            tickDelta = Timer_1ms(false) - tickDelta;
            ticks = (Timer_1ms(false) - tickStart);
            if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nCondo        = %5u,   %5u", tickDelta, ticks);
            tickDelta = ticks;
        }
    }
#endif

    // Vk, Counter Electrode Voltage, CntrE Volt, (Diagnostic)
    if(sys_data.data_cfg[CFG_V_COUNTER_ELECT] > 0)
    {
        ADS1248_gpio_ADG1609_mux(1);
        ROM_SysCtlDelay(MILLISECOND * 10);      // 10msec settling for MUX analog
        //if(sys_data.app_cfg[APPCFG_SAMP_FLEX] == 1)
            fVk = pollADS1248_iso(1, 6, sys_data.Vk_trials, 1, sys_data.Vk_sps);   // Mux 01, Chan +1 -6, trials = 5, gain = 1, sps = 20 Hz
        //else
        //    fVk = pollADS1248_iso(1, 6, VK_TRIALS, 1, VK_SPS);   // Mux 01, Chan +1 -6, trials = 5, gain = 1, sps = 20 Hz


        fVk_std = sys_samp.AD24_std;

        tickDelta = Timer_1ms(false) - tickDelta;
        ticks = (Timer_1ms(false) - tickStart);
        if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nVk Cntr E    = %5u,   %5u", tickDelta, ticks);
        tickDelta = ticks;

    }

#ifdef NOCODE
    if(sys_data.data_cfg[CFG_OPTODE] > 0)
    {
        optodeState = optode_stateMachine(optodeState);
        if((Timer_1ms(false) - tickDelta) > 1)
        {
            tickDelta = Timer_1ms(false) - tickDelta;
            ticks = (Timer_1ms(false) - tickStart);
            if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nOptode       = %5u,   %5u", tickDelta, ticks);
            tickDelta = ticks;
        }
    }
    if(sys_data.data_cfg[CFG_CTD] > 0)
    {
        ctdState = ctd_stateMachine(ctdState);
        if((Timer_1ms(false) - tickDelta) > 1)
        {
            tickDelta = Timer_1ms(false) - tickDelta;
            ticks = (Timer_1ms(false) - tickStart);
            if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nCondo        = %5u,   %5u", tickDelta, ticks);
            tickDelta = ticks;
        }
    }
#endif


    //---------------------------- pH related voltages --------------------------------------

    //------------ Vtherm, Thermistor Voltage ----------------
    if(sys_data.data_cfg[CFG_V_THERMISTOR] > 0)
    {
        //if(sys_data.app_cfg[APPCFG_SAMP_FLEX] == 1)
            fVtherm = pollADS1248_iso(0, 6, sys_data.Vtherm_trials, 1, sys_data.Vtherm_sps);       // Chan +0 -6, trials = 5, gain = 1, sps = 20 Hz (per Yui 5May2021)
        //else
        //    fVtherm = pollADS1248_iso(0, 6, VTHERM_TRIALS, 1, VTHERM_SPS);       // Chan +0 -6, trials = 5, gain = 1, sps = 20 Hz (per Yui 5May2021)

        fVtherm_std = sys_samp.AD24_std;

        tickDelta = Timer_1ms(false) - tickDelta;
        ticks = (Timer_1ms(false) - tickStart);
        if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nVtherm       = %5u,   %5u", tickDelta, ticks);
        tickDelta = ticks;

    }

#ifdef NOCODE
    if(sys_data.data_cfg[CFG_OPTODE] > 0)
    {
        optodeState = optode_stateMachine(optodeState);
        if((Timer_1ms(false) - tickDelta) > 1)
        {
            tickDelta = Timer_1ms(false) - tickDelta;
            ticks = (Timer_1ms(false) - tickStart);
            if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nOptode       = %5u,   %5u", tickDelta, ticks);
            tickDelta = ticks;
        }
    }
    if(sys_data.data_cfg[CFG_CTD] > 0)
    {
        ctdState = ctd_stateMachine(ctdState);
        if((Timer_1ms(false) - tickDelta) > 1)
        {
            tickDelta = Timer_1ms(false) - tickDelta;
            ticks = (Timer_1ms(false) - tickStart);
            if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nCondo        = %5u,   %5u", tickDelta, ticks);
            tickDelta = ticks;
        }
    }
#endif


    //-------------- Vrsi_B, Int Ref Off, ------------------------
    if(sys_data.data_cfg[CFG_VRSI_BIASED] > 0)     // Not valid on nanoFET
    {
#if BOARD_MFET >= 1 || BOARD_MPHOX >= 1
        //dbg_printf("\nno intref on glider\n");
        ADS1248_gpio_ADG1609_mux(3);
        ROM_SysCtlDelay(MILLISECOND * 10);      // 10msec settling for MUX analog
        //if(sys_data.app_cfg[APPCFG_SAMP_FLEX] == 1)
            fVrsi_B = pollADS1248_iso(1, 5, sys_data.Vrsi_trials, 1, sys_data.Vrsi_sps);  // 200msec Chan +1 -5, trials = 10, gain = user, sps = 20 Hz
        //else
        //    fVrsi_B = pollADS1248_iso(1, 5, VRSI_TRIALS, 1, VRSI_SPS);  // 200msec Chan +1 -5, trials = 10, gain = user, sps = 20 Hz

        fVrsi_B_std = sys_samp.AD24_std;

#endif
#if BOARD_NANOFET >= 1
        // Int Ref with offset not applicable on nanoFET per Scott
        fVrsi_B = 0.0;
        fVrsi_B_std = 0.0;
#endif
        tickDelta = Timer_1ms(false) - tickDelta;
        ticks = (Timer_1ms(false) - tickStart);
        if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nVrsi_B       = %5u,   %5u", tickDelta, ticks);
        tickDelta = ticks;
    }

#ifdef NOCODE
    if(sys_data.data_cfg[CFG_OPTODE] > 0)
    {
        optodeState = optode_stateMachine(optodeState);
        if((Timer_1ms(false) - tickDelta) > 1)
        {
            tickDelta = Timer_1ms(false) - tickDelta;
            ticks = (Timer_1ms(false) - tickStart);
            if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nOptode       = %5u,   %5u", tickDelta, ticks);
            tickDelta = ticks;
        }
    }
    if(sys_data.data_cfg[CFG_CTD] > 0)
    {
        ctdState = ctd_stateMachine(ctdState);
        if((Timer_1ms(false) - tickDelta) > 1)
        {
            tickDelta = Timer_1ms(false) - tickDelta;
            ticks = (Timer_1ms(false) - tickStart);
            if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nCondo        = %5u,   %5u", tickDelta, ticks);
            tickDelta = ticks;
        }
    }
#endif



    // ----------- Vrsi (aka Vint) --------------
    if(sys_data.data_cfg[CFG_VRSI] > 0)        // Not valid on nanoFET
    {
#if BOARD_MFET >= 1 || BOARD_MPHOX >= 1
        //dbg_printf("\nno Vrsi on glider, not valid on nanoFET\n");
        ADS1248_gpio_ADG1609_mux(3);
        ROM_SysCtlDelay(MILLISECOND * 10);      // 10msec settling for MUX analog
        //if(sys_data.app_cfg[APPCFG_SAMP_FLEX] == 1)
            fVrsi = pollADS1248_iso(1, 6, sys_data.Vrsi_trials, 1, sys_data.Vrsi_sps);       // Chan +1 -6, trials = 10, gain = 1, sps = 20 Hz (10*50ms = 500ms)
        //else
        //    fVrsi = pollADS1248_iso(1, 6, VRSI_TRIALS, 1, VRSI_SPS);       // Chan +1 -6, trials = 10, gain = 1, sps = 20 Hz (10*50ms = 500ms)

        fVrsi_std = sys_samp.AD24_std;

#endif
#if BOARD_NANOFET >= 1
        fVrsi = 0.0;
        fVrsi_std = 0.0;
#endif

        tickDelta = Timer_1ms(false) - tickDelta;
        ticks = (Timer_1ms(false) - tickStart);
        if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nVrsi         = %5u,   %5u", tickDelta, ticks);
        tickDelta = ticks;
    }

#ifdef NOCODE
    if(sys_data.data_cfg[CFG_OPTODE] > 0)
    {
        optodeState = optode_stateMachine(optodeState);
        if((Timer_1ms(false) - tickDelta) > 1)
        {
            tickDelta = Timer_1ms(false) - tickDelta;
            ticks = (Timer_1ms(false) - tickStart);
            if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nOptode       = %5u,   %5u", tickDelta, ticks);
            tickDelta = ticks;
        }
    }
    if(sys_data.data_cfg[CFG_CTD] > 0)
    {
        ctdState = ctd_stateMachine(ctdState);
        if((Timer_1ms(false) - tickDelta) > 1)
        {
            tickDelta = Timer_1ms(false) - tickDelta;
            ticks = (Timer_1ms(false) - tickStart);
            if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nCondo        = %5u,   %5u", tickDelta, ticks);
            tickDelta = ticks;
        }
    }
#endif




    // --------- Vrse_B, Ext Ref Offset, -------------
    if(sys_data.data_cfg[CFG_VRSE_BIASED] > 0)     // Not valid on nanoFET
    {
#if BOARD_MFET >= 1 || BOARD_MPHOX >= 1
        dbg_printf("\nno extref on glider\n");
        ADS1248_gpio_ADG1609_mux(0);
        ROM_SysCtlDelay(MILLISECOND * 10);      // 10msec settling for MUX analog
        //if(sys_data.app_cfg[APPCFG_SAMP_FLEX] == 1)
            fVrse_B = pollADS1248_iso(1, 5, sys_data.Vrse_trials, 1, sys_data.Vrse_sps);       // 200msec Chan +1 -5, trials = 10, gain = user, sps = 20 Hz
        //else
        //    fVrse_B = pollADS1248_iso(1, 5, VRSE_TRIALS, 1, VRSE_SPS);       // 200msec Chan +1 -5, trials = 10, gain = user, sps = 20 Hz

        fVrse_B_std = sys_samp.AD24_std;

#endif
#if BOARD_NANOFET >= 1
        fVrse_B = 0.0;
        fVrse_B_std = 0.0;
#endif
        tickDelta = Timer_1ms(false) - tickDelta;
        ticks = (Timer_1ms(false) - tickStart);
        if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nVrse_B       = %5u,   %5u", tickDelta, ticks);
        tickDelta = ticks;
    }

#ifdef NOCODE
    if(sys_data.data_cfg[CFG_OPTODE] > 0)
    {
        optodeState = optode_stateMachine(optodeState);
        if((Timer_1ms(false) - tickDelta) > 1)
        {
            tickDelta = Timer_1ms(false) - tickDelta;
            ticks = (Timer_1ms(false) - tickStart);
            if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nOptode       = %5u,   %5u", tickDelta, ticks);
            tickDelta = ticks;
        }
    }
    if(sys_data.data_cfg[CFG_CTD] > 0)
    {
        ctdState = ctd_stateMachine(ctdState);
        if((Timer_1ms(false) - tickDelta) > 1)
        {
            tickDelta = Timer_1ms(false) - tickDelta;
            ticks = (Timer_1ms(false) - tickStart);
            if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nCondo        = %5u,   %5u", tickDelta, ticks);
            tickDelta = ticks;
        }
    }
#endif




    // ----------- fVrse (GLIDER) ----------------------
    if(sys_data.data_cfg[CFG_VRSE] > 0)
    {
        ADS1248_gpio_ADG1609_mux(0);
        ROM_SysCtlDelay(MILLISECOND * 10);      // 10msec settling for MUX analog
        fVrse = 0.0;         // new 30 Mar 2021
#if BOARD_MFET >= 1 || BOARD_MPHOX >= 1     //6 (gnd) NOT available on nanoFET
        //if(sys_data.app_cfg[APPCFG_SAMP_FLEX] == 1)
            fVrse = pollADS1248_iso(1, 6, sys_data.Vrse_trials, 1, sys_data.Vrse_sps);  // 10x50msec= 500msec  trials=10, gain=1, sps=20
        //else
        //    fVrse = pollADS1248_iso(1, 6, VRSE_TRIALS, 1, VRSE_SPS);  // 10x50msec= 500msec  trials=10, gain=1, sps=20

#endif
#if BOARD_NANOFET >= 1
            // 6 (GND) is not connected on nanoFET
        //if(sys_data.app_cfg[APPCFG_SAMP_FLEX] == 1)
            fVrse = pollADS1248_iso(1, 5, sys_data.Vrse_trials, 1, sys_data.Vrse_sps);  // 10x50msec= 500msec  trials=10, gain=1, sps=20
        //else
        //    fVrse = pollADS1248_iso(1, 5, VRSE_TRIALS, 1, VRSE_SPS);  // 10x50msec= 500msec  trials=10, gain=1, sps=20
#endif

        fVrse_std = sys_samp.AD24_std;

        tickDelta = Timer_1ms(false) - tickDelta;
        ticks = (Timer_1ms(false) - tickStart);
        if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nVrse         = %5u,   %5u", tickDelta, ticks);
        tickDelta = ticks;
    }

#ifdef NOCODE
    if(sys_data.data_cfg[CFG_OPTODE] > 0)
    {
        optodeState = optode_stateMachine(optodeState);
        if((Timer_1ms(false) - tickDelta) > 1)
        {
            tickDelta = Timer_1ms(false) - tickDelta;
            ticks = (Timer_1ms(false) - tickStart);
            if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nOptode       = %5u,   %5u", tickDelta, ticks);
            tickDelta = ticks;
        }
    }
    if(sys_data.data_cfg[CFG_CTD] > 0)
    {
        ctdState = ctd_stateMachine(ctdState);
        if((Timer_1ms(false) - tickDelta) > 1)
        {
            tickDelta = Timer_1ms(false) - tickDelta;
            ticks = (Timer_1ms(false) - tickStart);
            if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nCondo        = %5u,   %5u", tickDelta, ticks);
            tickDelta = ticks;
        }
    }
#endif

    // ---- Start optode and ctd statemachines now that sensitive pH measurements have been made -----------------
    // Open and poll the microCat and Optode
    if(sys_data.data_cfg[CFG_OPTODE] > 0)
    {
        //start the optode driver by passing 1, when complete, the statemachine returns 0
        optodeState = 1;
        optodeState = optode_stateMachine(optodeState);     //pass in 1 to start the state machine, hereafter pass retVal

        tickDelta = Timer_1ms(false) - tickDelta;
        ticks = (Timer_1ms(false) - tickStart);
        if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nOptode St8Ma = %5u,   %5u", tickDelta, ticks);
        tickDelta = ticks;
    }

    if(sys_data.data_cfg[CFG_CTD] > 0)
    {
        //start the ctd driver by passing 1, when complete, the statemachine returns 0
        ctdState = 1;
        ctdState = ctd_stateMachine(ctdState);     //pass in 1 to start the state machine, hereafter pass retVal

        tickDelta = Timer_1ms(false) - tickDelta;
        ticks = (Timer_1ms(false) - tickStart);
        if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nCondo  St8Ma = %5u,   %5u", tickDelta, ticks);
        tickDelta = ticks;
    }

    // ------------- read internal adc (battery, etc), -----------------------
    // requires  adc_onchip_init(); is called and settled for 100msec or so prior to read_all_adc
    read_all_adc();
    read_all_adc();     // read a second time for better fidelity

    // battery voltage must be read for 'too low' check at bottom
    fVbat_main = (float)(adc_data[0]*100);
    fVbat_main /= 18193.77;      // 30 Sep 2019  11.75v is measured with Agilent meter as 12.069v
                               // must compute battery voltage as it is checked for 'too low' below

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

    // LM60 temp
    if(sys_data.data_cfg[CFG_BRD_TEMP] > 0)
    {
        fBrdTempC = ((((float)adc_data[4])*0.80566) - 424) / 6.25;   //VOut= (+6.25 mV/°C × T °C) + 424 mV  // LM60 temperature sensor - formula from datasheet / schematic (good job Scott)
    }

    // Humidity
    if(sys_data.data_cfg[CFG_BRD_HUMIDITY] > 0)
    {
        // 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;

        fHumidity = (float)( (adc_data[2] * 100) );  // VOUT=(VSUPPLY)(0.00636(sensor RH) + 0.1515), typical at 25C
        fHumidity /= 3284;
        uiHumidity = (adc_data[2] * 100) / 3284;
    }

    tickDelta = Timer_1ms(false) - tickDelta;
    ticks = (Timer_1ms(false) - tickStart);
    if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nOnchip ADC   = %5u,   %5u", tickDelta, ticks);
    tickDelta = ticks;

    // poweroff monitoring circuitry
    pwr_vbat_mon_off();   // Turn off VBat monitoring
    pwr_env_mon_off();    // Turn off Load switch for ENV monitoring

    // Shutdown sensor power supply
    closeADS1248_iso();

    if(sys_data.data_cfg[CFG_OPTODE] > 0)
    {
        optodeState = optode_stateMachine(optodeState);
        if((Timer_1ms(false) - tickDelta) > 1)
        {
            tickDelta = Timer_1ms(false) - tickDelta;
            ticks = (Timer_1ms(false) - tickStart);
            if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nOptode       = %5u,   %5u", tickDelta, ticks);
            tickDelta = ticks;
        }
    }
    if(sys_data.data_cfg[CFG_CTD] > 0)
    {
        ctdState = ctd_stateMachine(ctdState);
        if((Timer_1ms(false) - tickDelta) > 1)
        {
            tickDelta = Timer_1ms(false) - tickDelta;
            ticks = (Timer_1ms(false) - tickStart);
            if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nCondo        = %5u,   %5u", tickDelta, ticks);
            tickDelta = ticks;
        }
    }




    // ---------- Calculate the external and internal pH values -------------------------

    if(sys_data.data_cfg[CFG_CALC_TEMP] > 0)
    {
        fTempC = DuraFET_temp(fVtherm, sys_data.TCOffset);

        tickDelta = Timer_1ms(false) - tickDelta;
        ticks = (Timer_1ms(false) - tickStart);
        if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nCalc TempC   = %5u,   %5u", tickDelta, ticks);
        tickDelta = ticks;
    }



    if(sys_data.data_cfg[CFG_CALC_PH_VRSE] > 0)
    {
        SBE_sal = sys_data.default_sal;       // for pH_ext calc  (init'd to 35.0)
        // Todo sys_data.sensor_sal;
        pHext = calc_pHext(fVrse, fTempC, SBE_sal);  // NOTE: this might be Vrse_B that is needed....   5 May 2021

        tickDelta = Timer_1ms(false) - tickDelta;
        ticks = (Timer_1ms(false) - tickStart);
        if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nCalc pH Ext  = %5u,   %5u", tickDelta, ticks);
        tickDelta = ticks;
    }



    if(sys_data.data_cfg[CFG_CALC_PH_VRSI] > 0)
    {
        // requires TC and fVrsi_B
        pHint = calc_pHint(fVrsi_B, fTempC);   // per YUI  7 Jun 2018

        tickDelta = Timer_1ms(false) - tickDelta;
        ticks = (Timer_1ms(false) - tickStart);
        if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nCalc pH Int  = %5u,   %5u", tickDelta, ticks);
        tickDelta = ticks;
    }




    if(sys_data.data_cfg[CFG_OPTODE] > 0)
    {

        while(1)
        {
            if(optodeState == 0)            // makes sure optode statemachine is finished
                break;
            optodeState = optode_stateMachine(optodeState);

        }
        tickDelta = Timer_1ms(false) - tickDelta;
        ticks = (Timer_1ms(false) - tickStart);
        if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nOptode       = %5u,   %5u", tickDelta, ticks);
        tickDelta = ticks;
    }



    if(sys_data.data_cfg[CFG_CTD] > 0)
    {

        while(1)
        {
            if(ctdState == 0)            // makes sure ctd statemachine is finished
                break;
            ctdState = ctd_stateMachine(ctdState);

        }
        tickDelta = Timer_1ms(false) - tickDelta;
        ticks = (Timer_1ms(false) - tickStart);
        if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nCTD          = %5u,   %5u", tickDelta, ticks);
        tickDelta = ticks;
    }



    //#000000    12.03           -3.59        0.997431        0.674842        -0.055235       0.000005        -0.799272       0.000004        -0.500569       0.000005        18178.39        -399.644        24.707  18.18122

    indx = 0;
    // for column alignment between data and header, 8 chars per field  - note, a negative sign throws off the print format

    if(sys_data.data_cfg[CFG_SAMPLE_NUM] > 0)       { indx += sprintf(&prnBuf[indx], "#%07u\t", sys_samp.current_sample);   } //0  // was %07d
    if(sys_data.data_cfg[CFG_TIMEDATE] > 0)         { indx += sprintf(&prnBuf[indx], "     %s\t", timestamp);               } //1

    if(sys_data.data_cfg[CFG_VIN_BAT_VOLT] > 0)     { indx += sprintf(&prnBuf[indx], "%8.2f\t", fVbat_main);            } //2  // was %5.2f
    if(sys_data.data_cfg[CFG_BIAS_BAT_POS] > 0)     { indx += sprintf(&prnBuf[indx], "%8.2f\t", fBiasPos);                  } //5  5.2
    if(sys_data.data_cfg[CFG_BIAS_BAT_NEG] > 0)     { indx += sprintf(&prnBuf[indx], "%8.2f\t", fBiasNeg);                  } //5  5.2
    if(sys_data.data_cfg[CFG_BRD_TEMP] > 0)     { indx += sprintf(&prnBuf[indx], "%8.2f\t", fBrdTempC);                  } //3  // was %5.2f
    if(sys_data.data_cfg[CFG_BRD_HUMIDITY] > 0)     { indx += sprintf(&prnBuf[indx], "%8u\t", uiHumidity);                  } //4  // was %3u

    if(sys_data.data_cfg[CFG_V_THERMISTOR] > 0)     { indx += sprintf(&prnBuf[indx], "%8.6f\t", fVtherm);                    } //6
    if(sys_data.data_cfg[CFG_V_THERMISTOR_STD] > 0) { indx += sprintf(&prnBuf[indx], "%8.6f\t", fVtherm_std);                } //7
    if(sys_data.data_cfg[CFG_CALC_TEMP] > 0)        { indx += sprintf(&prnBuf[indx], "%8.3f\t", fTempC);                        } //20

    if(sys_data.data_cfg[CFG_VRSI] > 0)            { indx += sprintf(&prnBuf[indx], "%8.6f\t", fVrsi);                      } //12
    if(sys_data.data_cfg[CFG_VRSI_STD] > 0)        { indx += sprintf(&prnBuf[indx], "%8.6f\t", fVrsi_std);                  } //13
    if(sys_data.data_cfg[CFG_CALC_PH_VRSI] > 0)       { indx += sprintf(&prnBuf[indx], "%8.3f\t", pHint);                     } //21

    if(sys_data.data_cfg[CFG_VRSE] > 0)            { indx += sprintf(&prnBuf[indx], "%8.6f\t", fVrse);                  } //14
    if(sys_data.data_cfg[CFG_VRSE_STD] > 0)        { indx += sprintf(&prnBuf[indx], "%8.6f\t", fVrse_std);                  } //15
    if(sys_data.data_cfg[CFG_CALC_PH_VRSE] > 0)       { indx += sprintf(&prnBuf[indx], "%8.3f\t", pHext);                     } //22

    if(sys_data.data_cfg[CFG_VRSI_BIASED] > 0)     { indx += sprintf(&prnBuf[indx], "%8.6f\t", fVrsi_B);         } //8
    if(sys_data.data_cfg[CFG_VRSI_BIASED_STD] > 0) { indx += sprintf(&prnBuf[indx], "%8.6f\t", fVrsi_B_std);     } //9
    if(sys_data.data_cfg[CFG_VRSE_BIASED] > 0)     { indx += sprintf(&prnBuf[indx], "%8.6f\t", fVrse_B);         } //10
    if(sys_data.data_cfg[CFG_VRSE_BIASED_STD] > 0) { indx += sprintf(&prnBuf[indx], "%8.6f\t", fVrse_B_std);     } //11

    if(sys_data.data_cfg[CFG_V_COUNTER_ELECT] > 0)  { indx += sprintf(&prnBuf[indx], "%8.6f\t", fVk);   } //16
    if(sys_data.data_cfg[CFG_V_COUNTER_ELECT_STD] > 0)  { indx += sprintf(&prnBuf[indx], "%8.6f\t", fVk_std);  } //17
    if(sys_data.data_cfg[CFG_I_COUNTER] > 0)        { indx += sprintf(&prnBuf[indx], "%8.2f\t", fIk);   } //18
    if(sys_data.data_cfg[CFG_I_SUBSTRATE] > 0)      { indx += sprintf(&prnBuf[indx], "%8.3f\t", fIb);          } //19

    if(sys_data.data_cfg[CFG_OPTODE] > 0)           { indx += sprintf(&prnBuf[indx], "%s\t", optode.buf);                   } //23
    if(sys_data.data_cfg[CFG_CTD] > 0)              { indx += sprintf(&prnBuf[indx], "%s\t", ctd.buf);                      } //23

    tickDelta = Timer_1ms(false) - tickDelta;
    ticks = (Timer_1ms(false) - tickStart);
    if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nformat data  = %5u,   %5u\n", tickDelta, ticks);
    tickDelta = ticks;

    tickEnd = Timer_1ms(false);
    ticks = (tickEnd - tickStart);
    //uprintf("(Time: %u msec)", ticks );
    if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1)  indx += sprintf(&prnBuf[indx], "(%u msec)\t", ticks);
    indx += sprintf(&prnBuf[indx], "\r\n");  // should this be cr-lf?
    prnBuf[indx] = 0;       // new, trying to track down a bug where the string does not print all the way, might not be 0 term

    //if(txFlg == 1) uprintf("%s", prnBuf);      // uprint maximum is 255 sample to console
    if(txFlg == 1) UARTwrite(prnBuf, strlen(prnBuf));






    if(microSD_flg == 1)
    {

        // TODO: future
        //FA_OPEN_APPEND
        // Open a file
        fresult = f_open(&fileObject, sys_data.fileName, FA_READ | FA_WRITE | FA_OPEN_ALWAYS);
        if(fresult == FR_OK)
        {
            // Seek to the end, to append our file
            fresult = f_lseek(&fileObject, fileObject.fsize);
            if(fresult == FR_OK)
            {
                // 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)
                {

                }
                else
                {
                    uprintf("f_write error: %s\n", StringFromFresult(fresult));
                }

            }
            else
            {
                uprintf("f_lseek error: %s\n", StringFromFresult(fresult));
                error_store("f_lseek error");
            }



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

        }
        else
        {
            // != FR_OK
            uprintf("f_open error: %s\n", StringFromFresult(fresult));
            error_store("f_open error");

        }
#ifdef NOCODE
        // Open a file
        fresult = f_open(&fileObject, sys_data.fileName, FA_READ | FA_WRITE | FA_OPEN_ALWAYS);
        if(fresult != FR_OK)
        {
            uprintf("f_open error: %s\n", StringFromFresult(fresult));
            error_store("f_open error");
        }
        else
        {
            // Seek to the end, to append our file
            fresult = f_lseek(&fileObject, fileObject.fsize);
            if(fresult != FR_OK)
            {
                uprintf("f_lseek error: %s\n", StringFromFresult(fresult));
                error_store("f_lseek error");
            }

            // 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("f_write error: %s\n", StringFromFresult(fresult));
            }

        }

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



    } // if microSD_flg

    tickDelta = Timer_1ms(false) - tickDelta;
    ticks = (Timer_1ms(false) - tickStart);
    if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nuSD writes   = %5u,   %5u", tickDelta, ticks);
    tickDelta = ticks;

    wait_consoleTx();

    tickDelta = Timer_1ms(false) - tickDelta;
    ticks = (Timer_1ms(false) - tickStart);
    if(sys_data.app_cfg[APPCFG_SAMPLING_DIAG] == 1) uprintf("\nwait TX      = %5u,   %5u", tickDelta, ticks);
    tickDelta = ticks;

    sys_samp.current_sample++;  // Increment the sample counter, this is stored to FRAM in sleep() routine

    led_green_off();

    // Check for low battery voltage. Exit and sleep if too low.
    if( fVbat_main < sys_data.low_batt_volt )
    {

        for(indx=0; indx<20; indx++)
        {
            if(indx%4 == 0) uprintf("\nLow battery voltage (%.2f < %.2f) ! Exiting deploy mode...\n", fVbat_main, sys_data.low_batt_volt );
            wait_consoleTx();

            led_red_on();
            led_green_off();
            delay_msec(500);

            led_red_off();
            led_green_on();
            delay_msec(500);
        }

        error_store("Low battery! Exiting deploy mode");
        sleep(IDLE, 0);     // Sleep until woken by user
    }

// .diag is gone

}
#endif

#endif

#ifdef TIMINGINFO
SampNum             MM/DD/YYYY HH:MM:SS          Vtherm        VthrmStd         TC_Dfet            Vrsi        Vrsi_std        pHintEst            Vrse        Vrse_std        pHextEst          Vrsi_B        VrsiBstd          Vrse_B VrseBstd              Vk          Vk_std              Ik              Ib        VbatMain        VbiasPos        VbiasNeg         TC_cont        Humidity

Pump         = 2002,   2002
Pwr on, init =   24,   2026
CTD Optode   =    0,   2026
Bias Bat     =   71,  2097
Ib Substrate =   61,   2158
Ik Cntr E    =   60,   2218
Vk Cntr E    =  260,   2478
Vtherm       =  249,   2727
Vrsi         =  508,   3235
Vrse         =  508,   3743
Vrse_B       =  507,   4250
Vrsi_B       =  508,   4758
Onchip ADC   =    0,   4758
Calc TempC   =    1,   4759
Calc pH Ext  =    2,   4761
Calc pH Int  =    0,   4761
Optode       =    0,   4761
CTD          =    0,   4761
format data  =    2,   4763
#0000492             05/17/2021 04:26:32        0.997514        0.000002          24.704        -0.055202       0.000009          18.182        -0.799227       0.000005           7.826        0.674909        0.000008        -0.069118        0.000006        -0.500551       0.000003        18197.15        -399.608           12.00            3.61           -3.60           18.01              59        (4763 msec)

uSD writes   =   12,   4775
wait TX      =   27,   4802



A -- Sample Num               = 1
B -- MM/DD/YYYY HH:MM:SS      = 1

C -- Vthermistor              = 1
     Vtermistor Std           = 1
D -- Temperature Calc         = 1
E -- Vrsi (Int Ref pH volt)   = 1
     Vrsi Std                 = 1
F -- pH Vrsi Calc             = 1
G -- Vrse (Ext Ref pH volt)   = 1
     Vrse Std                 = 1
H -- pH Vrse Calc             = 1
I -- Vrsi Biased (7pH=0v)     = 1
J -- Vrsi Biased Std          = 1
K -- Vrse Biased (7pH=0v)     = 1
L -- Vrse Biased Std          = 1

M -- Counter Electrode Vk     = 1
N -- Counter Electrode Vk Std = 1
O -- Counter Electrode Cur Ik = 1
P -- Substrate Current        = 1

Q -- Battery Volt             = 1
R -- Bias Battery Pos         = 1
S -- Bias Battery Neg         = 1
T -- Board Temperature        = 1
U -- Board Humidity           = 1

U -- Optode                   = 1
V -- Conductivity             = 1


 SampNum             MM/DD/YYYY HH:MM:SS          Vtherm        VthrmStd         TC_Dfet            Vrsi        Vrsi_std        pHintEst            Vrse        Vrse_std        pHextEst          Vrsi_B        VrsiBstd          Vrse_B VrseBstd              Vk          Vk_std              Ik              Ib        VbatMain        VbiasPos        VbiasNeg         TC_cont        Humidity                Opt_PN  Opt_SN  Moxy    O2satper        TC_opt  Dphase   Bphase  Rphase  Bamp    Bpot    Ramp    Opt_rawtemp     TempC   Cond    Salt    Unk1    Date    Time            Cond_PN Cond_SN Cond    Temp    Unk1    Unk2    Unk3

Pump         = 2002,   2002
Pwr on, init =   23,   2025
CTD Optode   =   22,   2047
Bias Bat     =   70,  2117
Ib Substrate =   61,   2178
Ik Cntr E    =   61,   2239
Vk Cntr E    =  989,   3228
Vtherm       =  250,   3478
Vrsi         =  508,   3986
Vrse         =  507,   4493
Vrse_B       =  508,   5001
Vrsi_B       =  508,   5509
Onchip ADC   =    0,   5509
Calc TempC   =    1,   5510
Calc pH Ext  =    1,   5511
Calc pH Int  =    1,   5512
Optode       =    0,   5512
CTD          =    0,   5512
format data  =    2,   5514
#0000491             05/17/2021 04:21:05        0.997609        0.000002          24.701        -0.055199       0.000011          18.183        -0.799234       0.000007           7.826        0.674919        0.000005        -0.069120        0.000007        -0.500557       0.000005        18197.77        -399.623           11.99            3.61           -3.60           17.50              60        4831    856     273.940 92.968  18.159  28.090  30.381   38.298  7.917   599.9   704.4   252.7   5860    29      -0.004  17.101  0.010   998.766 1473.130        (5514 msec)

uSD writes   =   14,   5528
wait TX      =   35,   5563





Pump         = 1900
Pwr on, init = 1920
CTD Optode   = 1920
Bias Bat     = 1920
Ib Substrate = 1980
Ik Cntr E    = 2040
Vk Cntr E    = 2300
Vtherm       = 2300
Vrsi         = 2300
Vrse         = 2810
Vrse_B       = 2810
Vrsi_B       = 2810
Onchip ADC   = 2810
Calc TempC   = 2810
Calc pH Ext  = 2810
Calc pH Int  = 2810
Optode       = 2810
CTD          = 2810
format data  = 2810
 SampNum             MM/DD/YYYY HH:MM:SS            Vrse        Vrse_std              Vk          Vk_std              Ik              Ib        VbatMain
#0000003             05/15/2021 09:36:42        -0.799235       0.000009        -0.500556       0.000003        18197.32        -399.593           12.00        (2810 msec)

uSD writes   = 2980
wait TX      = 2980





#endif

