/*
 * serial.c
 *
 *  Created on: Nov 30, 2022
 *      Author: thomm
 */

#include <stdint.h>
#include <stdbool.h>

#include "system.h"
#include "string.h"
#include "uartstdio.h"
#include "user_io.h"
#include "uart3.h"
#include "serial.h"
#include "sample.h"
#include "config.h"
#include "apf.h"
#include "test.h"
#include "mms_test.h"
#include "serial_cmd_fxn.h"

extern int microSD_flg;
extern struct systemSamplingData sys_samp;
struct rxStateMach rx0;             // defd in serial.h

struct apfGlobals apf;          // defd in serial.h for now, APF globals from Persistor CF2 ISUS/DURA MSC1

extern unsigned int databarFlg;
extern unsigned int barfSampleTime;

uint32_t testVar;

/*
 * serial_stateMachine on uart0
 *
 *
 * The expected behavior:
 *  wakeup, no menu, be ready to respond to serial commands
 *  perhaps, hit <CR> and the menu pops up
 *
 * commands:
 *      gdata,
 *      ts,
 *      stop,
 *      dump,
 *      samp_byte,
 *      gh,
 *      gm,
 *      sl,
 *      ss,
 *      pumpon,
 *      pumpoff,
 *      go,
 *      resume,
 *      exit
 *      Set Config Glider
 *      Set Congig MFET
 *
 * New Commands for Float use case (MSC3)
 *
 * W,M,E,P,S,T,C,Q,TS,T1,T2,SL,SE,SLP,OFF,RTC,FIT,CTD,MODE,INIT,BAKE,SPECTRA
 *
 * W: WW print ACK
 * M: Menu
 * E: ERR print error counts (depending on isus or ph mode)
 * P: PC or PP printf("ACK,P,%lu,%lu,%lu\n", sys_por_ctr, sys_reset_ctr, sys_reset_time);
 * S: SC or SS printf("ACK,S,%lu,%lu\n", isus_sample_ctr, isus_sample_time); or printf("ACK,S,%lu,%lu\n", dura_sample_ctr, dura_sample_time);
 * T: TA if got sample, printf("ACK,T,%.3f\n", acquire_time); else printf("NAK,T,-1.0\n");
 * C: CIH CDH OutputIsusHeader(stdout); or OutputDuraHeader(stdout);  C: Get MSC configuration information
 * Q: QQQ printf("ACK,Q,%d\n", sys_sensor_type);
 * TS: take sample (ISUS or pH based on sensor type
 * T1:  TakeIsusSample(dbuf, &acquire_time, CTD_Time, CTD_Temp, CTD_Salinity, CTD_Depth); (or pseudo isus)
 * T2: TakeDuraSample(dbuf, &acquire_time, CTD_Time, CTD_Temp, CTD_Salinity, CTD_Depth);
 * SL: send last
 * SE: if( (Erecs=CalcRecsPending((uchar)ERRORLOG_FILE)) >= 0 ) printf("ACK,SE?,%ld\n", Erecs);
 * SLP: SCIRxFlush();
 * OFF: SysShutDown();
 * RTC: printf("ACK,RTC?,%lu\n", RTCGetTime( NULL, NULL ) );
 * FIT: printf("ACK,FIT?,%.1lf,%.1lf\n", CellNumToLambda(isus_pixel_beg, ZeissCoefs), CellNumToLambda(isus_pixel_end, ZeissCoefs) );, and run the fit
 * CTD: printf("ACK,CTD?,%lu,%.4f,%.4f,%.2f\n", CTD_Time, CTD_Temp, CTD_Salinity, CTD_Depth); and more
 * RATE: printf("ACK,RATE?,%lu\n", isus_sleep);   set ISUS sample rate
 * MODE: printf("ACK,MODE?,%lu\n", (ulong)sys_sensor_mode);, and the ability to set
 * INIT: initialize and restore defaults
 * BAKE: initiate a UV cleaning
 * SPECTRA: printf("ACK,SPECTRA?,%.1lf,%.1lf\n", CellNumToLambda(isus_datpixel_beg, ZeissCoefs), CellNumToLambda(isus_datpixel_end, ZeissCoefs) );
 * CAL: Query the MSC for its calibration file for the ISUS or DuraFet (depending on mode)
 *
 * Notes from the MSC Spec (v1.0)
 * The CF2-based MSC remains powered throughout the entire profile phase but remains in a low-power sleep state except to measure samples.
 * Allowing the MSC to be powered-down between samples is the preferred mode but CF2-like compatibility will be retained as a fall-back, if needed.
 * The MSC will be responsible for implementing its own real time clock (RTC); the RTC of the MSC will be synchronized to the Apf11’s at the start of each profile.
 *
 * Apf11 to reconfigure the MSC using two-way iridium communication. However, in general, it will be the responsibility of the MSC to maintain any required configuration parameters in its own non-volatile storage.
 *
 * The MSC does not communicate directly with the Sbe41cp. Instead, the Apf11 queries the CTD and subsequently passes the salinity (S), temperature (T), and pressure (P) to the MSC
 * MSC should respond to a brown-out condition (ie., voltage less than 8V) by aborting any sample-in-progress
 *
 * Any character received by the sensor should cause it to wake and enter a command processing loop.  If no characters are received for 30 seconds
 *
 * Commands and responses are case insensitive
 *
 * Unrecognized: NAK,ReceivedCmd,ErrorMsg
 *
 * Arguments of commands should be validated by checking for type, count, and range
 *
 * BAKE
 *
 *
 *
 *
 *
 * CTD,Time,T,S,P
 *
 * CTD,?  ACK,CTD?,Time,T,S,P.
 *
 * E    reports the number of errors that have been encountered since the last invocation of the INIT command
 *    ACK,E,ErrorCounterValue,LastErrorTimeSec
 *
 * FIT,WindowBegin,WindowEnd
 *
 * FIT,?   ACK,FIT?,WindowBegin,WindowEnd
 *
 * INIT: Initialize MSC for deployment    ACK,INIT
 *
 * MODE,<Mode> and MSC sends back as an acknowledgment: ACK,MODE,<Mode>
 *
 * P: Get MSC power-on counter, system-reset counter, and event time (non-volatile)        ACK,P,PowerCycleCounter,SysResetCounter,LastResetTimeSec.
 *
 * Q: Query the MSC for supported sensors      ACK,Q,SensorSupport
 *
 * RTC: Set the MSC real time clock (RTC)     RTC,UnixEpoch      ACK,UnixEpoch,RtcEpoch
 *
 * RTC,?       ACK,RTC?,RtcEpoch
 *
 * S: Get MSC sample counter value (non-volatile)     ACK,S,SampleCounter,LastSampleTimeSec
 *
 * SE,?: Report the number of records in the error log      ACK,SE?,n
 *
 * SL: Send the last ISUS or DURA data record
 * SLP: Put MSC in Suspend Mode
 *
 * SPECTRA: Set reported (see SL command) ISUS spectra data range.  SPECTRA,WindowBegin,WindowEnd gets response:   ACK,SPECTRA,WindowBegin,WindowEnd
 *
 * SPECTRA,?     ACK,SPECTRA?,WindowBegin,WindowEnd.
 *
 * T: Get the time (in seconds) it took MSC to collect the last sample (see TS command)      ACK,T,LastDataAcquisitionTimeSec
 *
 * TINT: Set the spectrometer integration time (milliseconds) for ISUS samples.   TINT,SpecIntegrationTime  [100,2500] milliseconds
 *
 * TINT,?    TINIT,?,SpecIntegrationTime
 *
 * TS   ACK,TS,CMD    ACK,TS,DAT if successful or NAK,TS,DAT
 * CTD command (see below) is typically sent prior to issuing the TS
 * command as the CTD values (pressure, temperature, and salinity) are used by MSC to make
 * “on-the-fly” temperature corrections to the Bromide calibration spectra as well as for fixing
 * the Bromide (salinity) concentration within the fitting algorithm. The passed CTD values are
 * included within the MSC data record.
 *
 *
 * W    ACK.
 *
 *
 *
 *
 */


//reset the system errno variable on each pass
//ERANGE is used in commands that parse passed values, e.g, RTC, CTD, FIT


#define ST_RX_INIT      0
#define ST_RX_MAINMENU  1
#define ST_EXEC_CMD     2       // user types a command
#define ST_RX_CMD       3
#define ST_RX_DATA      4
#define ST_RX_EXEC      5

void save(void)
{
    storeSysDataVariables();    //save
}

void print_prompt(void)
{
    uprintf("\r\n>");   //prompt
}

void print_NAK(void)
{
    uprintf("NAK\r\n");
    //uprintf("NAK,UnrecognizedCmdChar: %s\n", cbuf);       // APF todo
}
void m2m_statemachine_init(void)
{
    unsigned int indx;

    UARTEchoSet(false);

    rx0.state = ST_RX_INIT;
    rx0.cmd = 0;
    rx0.cnt = 0;
    rx0.cr_cnt = 0;
    rx0.indx = 0;
    rx0.tick_ms_start = Timer_1ms(false);   // 'false' says don't reset the timer
    rx0.tick_ms_now = rx0.tick_ms_start;
    rx0.tick_ms_delta = 0;
    //rx0.tick_ms_delim = M2M_DELIM_MS_TIMEOUT;

    //uprintf("sm init rx0.tick_ms_delim = M2M\r\n");     // DEBUG

    for(indx=0; indx<MAX_SIZE_RX0_BUF; indx++)
        rx0.buf[indx] = 0;

    //uprintf("\r\n>");   //prompt
    print_prompt();

}



#ifdef EXEC_CMDS
                    gdata = strncmp(buff, "gdata", 5);      // get data
                    ts = strncmp(buff, "ts", 2);            // take sample
                    ss = strncmp(buff, "ss", 2);            // start sample, needs to have sl within 6 sec
                    gc = strncmp(buff, "gc", 2);            // get calibration coefficients
                    ec = strncmp(buff, "ec", 2);            // export calibration coefficients in cal file format
                    gh = strncmp(buff, "gh", 2);            // get data header
                    gm = strncmp(buff, "gm", 2);            // get metadata header
                    pumpon = strncmp(buff, "pumpon", 6);
                    pumpoff = strncmp(buff, "pumpoff", 7);
                    dump = strncmp(buff, "dump", 4);        // dump
                    go = strncmp(buff, "go", 2);            // go / resume
                    resume = strncmp(buff, "resume", 6);    // resume
                    stop = strncmp(buff, "stop", 4);        // stop deployment (sampling)
                    exit = strncmp(buff, "exit", 4);        // stop deployment (sampling)
                    quit = strncmp(buff, "quit", 4);        // stop deployment (sampling)
#endif

// call this routine from an exec loop
// return 0 if nothing happened
//        1 if char typed or command
//       -1 if sleep is commanded
// Notes:
//    give user immediate feedback if typing 'wrong command'
//    use timeout to terminate command entry, also accept 0x0d <cr> as terminating char
//    minimum 2 letter commands, measure time between 1st and 2nd char to determine if m2m (250msec?) or h2m timeout
//


int handle_m2m_comm(void)
{
    int rxByte;
    int retVal;
    int timeoutFlg;

    //Insert timebased delimiter check here - if char entry timeout is hit, then insert rx0.byte = 0x0d and bypass UARTrdy() check


    timeoutFlg = 0;
    if(rx0.indx > 0)
    {
        // start is set on first valid char, then reset again on each valid char
        // check timeout delim
        rx0.tick_ms_delta = (Timer_1ms(false) - rx0.tick_ms_start);

        //uprintf("s %lu, d %lu\r\n", rx0.tick_ms_start, rx0.tick_ms_delta);        // DEBUG
        //delay_msec(20);       //DEBUG
        if(rx0.tick_ms_delta >= rx0.tick_ms_delim)
        {
            //uprintf("timed out\r\n>");   // debug
            rxByte = 0x0d;          // if timeout, insert 0x0d 'end of rx delimiter'
            timeoutFlg = 1;
            rx0.cr_cnt = 0;     // is this needed?
        }

    }

    // if not timed out, then check for rx
    if(timeoutFlg == 0)
    {
        if(UARTrdy() == 0)
            return(0);
        rxByte = getChar();
    }



    //rxByte = getChar();   // old code before timeout code added
    rx0.byte = rxByte;
    //UARTputc(rx0.byte);     // DEBUG

    switch(rx0.state)
    {
        case ST_RX_INIT:
            //m2m_statemachine_init();
            // transition to MAINMENU if <cr> or 'm'
            // transition to CMD if 0xaa or 'U'
            switch(rx0.byte)
            {
                // command terminator
                case 0x0d:  //<CR>
                    //uprintf("\r\n>");           // prompt
                    print_prompt();
                    //uprintf(" CR Rxd %u\r\n", rx0.cr_cnt);  //DEBUG
                    rx0.cr_cnt++;
                    if(rx0.cr_cnt >= 2)
                    {
                        rx0.cr_cnt = 0;
                        rx0.state = ST_RX_MAINMENU;
                        UARTEchoSet(true);
                    }
                    return(1);

                //case 'a':
                case 'b':       //bias
                case 'c':       //config
                case 'd':       //deploy
                case 'e':
                case 'f':
                case 'g':
                case 'h':
                case 'i':
                //case 'j':
                //case 'k':
                //case 'l':
                case 'm':
                case 'n':
                //case 'o':
                case 'p':
                case 'q':
                case 'r':
                case 's':
                case 't':
                //case 'u':
                case 'v':
                case 'w':
                //case 'x':
                case 'z':
                    //uprintf("s %ul\r\n", rx0.tick_ms_start);        // debug

                    // first letter of valid user typed command = Immediate feedback
                    UARTputc(rx0.byte);         //echo user typed commands
                    rx0.state = ST_EXEC_CMD;
                    rx0.cmd = 0;
                    rx0.indx = 0;
                    rx0.tick_ms_start = Timer_1ms(false);       // set time start after receiving first good char
                    //rx0.cnt = 2;                // THOMREMOVE default is to look for 2 byte commands first
                    rx0.buf[rx0.indx] = rx0.byte;
                    rx0.indx++;
                    rx0.buf[rx0.indx] = 0;
                    return(1);

                case M2M_RX_PREAMBLE_HACK:   //'U'
                case M2M_RX_PREAMBLE_TXT:   //'<'
                case M2M_RX_PREAMBLE:       // 0xAA
                    rx0.state = ST_RX_CMD;
                    rx0.cmd = 0;
                    rx0.indx = 0;
                    rx0.tick_ms_start = Timer_1ms(false);       // set time start after receiving first good char
                    return(1);

                default:
                    // TODO - return 1 resets timer in main_exec_loop
                    // This might be a silly feature - early first char warning on bad command
                    //uprintf("NAK 0x%2x\r\n>", rx0.byte);        // TODO: perhaps print help?
                    print_NAK();

                    // TODO APF might need: printf("NAK,NON-ALPHA Character Received!\n");

                    rx0.state = ST_RX_INIT;
                    m2m_statemachine_init();
                    return(1);
                    //break;

            }
            break;

        case ST_EXEC_CMD:
            if(rx0.byte == 0x0d)        // exec command terminated by 0x0d
            {
                uprintf("\r\n");
                retVal = parse_rx0_buf();   // exec command parse
                if(retVal == 0)             // bad or no command
                {
                    //uprintf("NAK p\r\n");
                    print_NAK();
                }
                else if(retVal == CMD_SLEEP)
                    return(-1);
                else if(retVal == CMD_TAKESAMPLE)    // sleep after sample
                    return(-1);
                else if(retVal == CMD_SENDLAST)    // sleep after send last
                    return(-1);
                else if(retVal == CMD_MAINMENU)
                {
                    rx0.state = ST_RX_INIT;
                    m2m_statemachine_init();
                }
                else
                {

                }
                rx0.state = ST_RX_INIT;
                m2m_statemachine_init();
            }
            else if(rx0.byte == '\b')       // backspace
            {

                UARTputc('\b');
                UARTputc(' ');
                UARTputc('\b');
                if(rx0.indx > 0)
                    rx0.indx--;
                rx0.buf[rx0.indx] = 0;
                rx0.tick_ms_start = Timer_1ms(false);       // reset time start
            }
            else
            {
                UARTputc(rx0.byte);         //echo user typed commands and carriage return
                rx0.buf[rx0.indx] = rx0.byte;
                if(rx0.indx < MAX_SIZE_RX0_BUF-1)
                    rx0.indx++;
                rx0.buf[rx0.indx] = 0;
                rx0.tick_ms_start = Timer_1ms(false);       // reset time start
                //Thom todo on checking this condition

                //uprintf("s %ul\r\n", rx0.tick_ms_start);        // DEBUG
            }
            break;

        case ST_RX_MAINMENU:

            if( apf.isus_spec_pwr == TRUE )
            {
                mms_specPwrOff();       //SpecPwrOff( SpecPort );
                uprintf("\n  Spectrometer Power was left ON! Powering DOWN...\n");
                }
            if( apf.isus_lamp_pwr == TRUE )
            {
                mms_lampPwrOff();         //LampPwrOff();
                uprintf("\n  Fiberlight Power was left ON! Powering DOWN...\n");
                }
#ifdef APFTODOCODE
            if( apf.isus_ref_pwr == TRUE ){
                RefPwrOff();
                uprintf("\n  Ref Detector Power was left ON! Powering DOWN...\n");
                }
            if( apf.dura_atod_pwr == TRUE ){
                AtodPowerOff();
                uprintf("\n  ATOD Interface Power was left ON! Powering DOWN...\n");
                }
#endif




            exec_main_menu();       // DEBUG, call this loop to prove 'M'
            //new_exec_main(rx0.byte);
            rx0.state = ST_RX_INIT;
            m2m_statemachine_init();
            //UARTEchoSet(true);          // NEW 26 Apr 2024, causes double return...  Trying to solve the Menu lack of echo problem
            return(1);
            break;

        case ST_RX_CMD:
            switch(rx0.byte)
            {
                case M2M_RX_PREAMBLE_TXT:   //'U'  Note: with this active, no command
                case M2M_RX_PREAMBLE:       // 0xAA
                    // handle multiple preamble by doing nothing
                    rx0.tick_ms_start = Timer_1ms(false);       // reset time start
                    break;

                default:
                    if( ((rx0.byte >= 'A') && (rx0.byte <= 'Z')) || ((rx0.byte >= 'a') && (rx0.byte <= 'z')) )
                    {
                        rx0.buf[rx0.indx] = rx0.byte & 0x5f;   // make lower case 0101 1111   42 vs 62  0100 0110
                        rx0.buf[rx0.indx] = rx0.byte | 0x20;   // make lower case 0101 1111   42 vs 62  0100 0110  0010 0000
                        //UARTputc(rx0.buf[rx0.indx]);         // DEBUG
                        if(rx0.indx < MAX_SIZE_RX0_BUF-1)
                            rx0.indx++;
                        rx0.buf[rx0.indx] = 0;      // null terminate for string ops

                        //THOM TODO BIG TODO - let's move these commands to the 'parse commands' now that all will be terminated by timeout
                        if(rx0.indx == 2)           // 2 char commands
                        {
                            if(strncmp(rx0.buf, "ts", 2) == 0)            // take sample
                            {
                                rx0.cmd = CMD_TAKESAMPLE;
                                pump_and_sample(1,1);
                                rx0.state = ST_RX_INIT;
                                m2m_statemachine_init();
                            }
                            if(strncmp(rx0.buf, "ss", 2) == 0)           // start sample, needs to have sl within 6 sec
                            {
                                rx0.cmd = CMD_STARTSAMPLE;

                                pump_and_sample(0,1);
                                rx0.state = ST_RX_INIT;
                                m2m_statemachine_init();
                            }
                            if(strncmp(rx0.buf, "sl", 2) == 0)           // start sample, needs to have sl within 6 sec
                            {
                                rx0.cmd = CMD_SENDLAST;
                                send_last_sample();
                                rx0.state = ST_RX_INIT;
                                m2m_statemachine_init();
                            }
                            if(strncmp(rx0.buf, "gc", 2) == 0)            // get calibration coefficients
                            {
                                rx0.cmd = CMD_GETCAL;
                                get_pH_sensor_cal_coeff();
                                rx0.state = ST_RX_INIT;
                                m2m_statemachine_init();
                            }
                            if(strncmp(rx0.buf, "ec", 2) == 0)            // export calibration coefficients in cal file format
                            {
                                rx0.cmd = CMD_EXPORTCAL;
                                export_pH_sensor_cal_coeff();
                                rx0.state = ST_RX_INIT;
                                m2m_statemachine_init();
                            }
                            if(strncmp(rx0.buf, "gh", 2) == 0)            // get data header
                            {
                                rx0.cmd = CMD_GETHEADER;
                                get_header();
                                rx0.state = ST_RX_INIT;
                                m2m_statemachine_init();
                            }
                            if(strncmp(rx0.buf, "gm", 2) == 0)            // get metadata header
                            {
                                rx0.cmd = CMD_GETMETADATA;
                                print_metadata_header( ROM_HibernateRTCGet() );
                                rx0.state = ST_RX_INIT;
                                m2m_statemachine_init();
                            }

                        }
                        else if(rx0.indx == 3)      // 3 char commands
                        {

                        }
                    }
                    else  // For now, valid commands are all ascii alphabet
                    {
                        // handle non alpha characters here...  For now, re-init
                        rx0.state = ST_RX_INIT;
                        m2m_statemachine_init();
                    }
                    break;
            }
            break;

        case ST_RX_DATA:
            break;
        case ST_RX_EXEC:
            break;
        default:
            rx0.state = ST_RX_INIT;
            m2m_statemachine_init();
            break;
    }

}



// return 0 if no command
// return CMD_xxx otherwise
// return -1 to exit exec_main_loop
//
/* config:
 *  - time, gettime
 *  - settime
 *  - period, getperiod
 *  - setperiod
 *  - config, getconfig      datafields,
 *  - setconfig
 *  - filename, getfilename
 *  - setfilename
 *  - align
 *  commands:
 *  - help
 *  - sleep
 *  - ts
 *  - ss
 *  - sl
 *  - gc
 *  - ec
 *  - gh
 *  - eh
 *  - stop, exit, quit, <ctrl-c>
 */


int parse_rx0_buf(void)
{
    int retVal;
    unsigned int num;

    retVal = 0;

#ifdef NOCODE
    //handle main menu selection first
    if((rx0.buf[0] == 'm') && (rx0.buf[1] == 0))
    {
        exec_main_menu();       // DEBUG, call this loop to prove 'M'
        return(CMD_MAINMENU);
    }
#endif

    //---------- B --------------
    // was else if
    if (strncmp(rx0.buf, "bake", 4) == 0)            // APF BAKE UV Lamp
    {
        rx0.cmd = CMD_APF_BAKE;
        apf_bake_uv_lamp();

        retVal = rx0.cmd;
        return(retVal);
    }

    else if( (strncmp(rx0.buf, "biasneg", 7) == 0)  )          //
    {

        if(rx0.buf[5] == 's')
        {
            //biasneg set 1
            //012345678901234
            rx0.cmd = CMD_SETCFG_BIASNEG;
            cmd_set_biasneg(rx0.buf[9]);
        }
        else if(rx0.buf[5] == 'g')
        {
            //biasneg get
            rx0.cmd = CMD_GETCFG_BIASNEG;
            cmd_get_biasneg();
        }
        else
        {
            // get count, pass in as num
            rx0.cmd = CMD_TEST_BIASNEG;
            num = 1;
            cmd_test_biasneg(num);
        }
        retVal = rx0.cmd;
        return(retVal);
    }

    else if( (strncmp(rx0.buf, "biaspos", 7) == 0)  )          //
    {

        if(rx0.buf[8] == 's')
        {
            //biaspos set 1
            //012345678901234
            rx0.cmd = CMD_SETCFG_BIASPOS;
            cmd_set_biaspos(rx0.buf[12]);
        }
        else if(rx0.buf[5] == 'g')
        {
            //biaspos get
            rx0.cmd = CMD_GETCFG_BIASPOS;
            cmd_get_biaspos();
        }
        else
        {
            // get count, pass in as num
            rx0.cmd = CMD_TEST_BIASPOS;
            num = 1;
            cmd_test_biaspos(num);
        }
        retVal = rx0.cmd;
        return(retVal);
    }


    //---------- C --------------
    //else if (strncmp(rx0.buf, "cfg", 3) == 0)
    else if((rx0.buf[0] == 'c') && (rx0.buf[1] == 0))
    {
        rx0.cmd = CMD_APF_CFG;
        apf_get_cfg();

        retVal = rx0.cmd;
        return(retVal);
    }

    else if (strncmp(rx0.buf, "cal", 3) == 0)
    {
        rx0.cmd = CMD_APF_CAL;
        apf_get_cal();

        retVal = rx0.cmd;
        return(retVal);
    }
    if( (strncmp(rx0.buf, "config", 6) == 0)  )
    {
        if(rx0.indx > 6)
        {
            if(rx0.buf[7] == 'h')       //config help
            {
                rx0.cmd = CMD_HELPCONFIG;
                cmd_help_config();
            }
            else
            {
                rx0.cmd = CMD_SETCFG_CONFIG;
                cmd_set_config();
            }
        }
        else
        {
            rx0.cmd = CMD_GETCFG_CONFIG;
            cmd_get_config();
        }
        retVal = rx0.cmd;
        return(retVal);
    }
    else if (strncmp(rx0.buf, "ctd,?", 5) == 0)
    {
        rx0.cmd = CMD_APF_GET_CTD;
        apf_get_ctd();

        retVal = rx0.cmd;
        return(retVal);
    }

    else if (strncmp(rx0.buf, "ctd", 3) == 0)
    {
        rx0.cmd = CMD_APF_SET_CTD;
        apf_set_ctd();

        retVal = rx0.cmd;
        return(retVal);
    }

    //---------- E --------------
    //else if (strncmp(rx0.buf, "err", 3) == 0)
    else if((rx0.buf[0] == 'e') && (rx0.buf[1] == 0))
    {
        rx0.cmd = CMD_APF_GET_ERR;
        apf_get_err();

        retVal = rx0.cmd;
        return(retVal);
    }

    else if(strncmp(rx0.buf, "ec", 2) == 0)            // export calibration coefficients in cal file format
    {
        rx0.cmd = CMD_EXPORTCAL;

        export_pH_sensor_cal_coeff();
        retVal = rx0.cmd;
        return(retVal);
    }

    //---------- F --------------
    else if( (strncmp(rx0.buf, "filename", 4) == 0) ||   (strncmp(rx0.buf, "getfilename", 6) == 0) )        // getfilename
    {
        if(rx0.indx > 10)
        {
            rx0.cmd = CMD_SETFILENAME;
            cmd_set_filename();
        }
        else
        {
            rx0.cmd = CMD_GETFILENAME;
            cmd_get_filename();
        }

        retVal = rx0.cmd;
        return(retVal);
    }

    else if( (strncmp(rx0.buf, "filesystem", 5) == 0)  )        // getfilename
    {

        rx0.cmd = CMD_FILESYSTEM;
        cmd_filesystem();
        retVal = rx0.cmd;
        return(retVal);
    }

    else if (strncmp(rx0.buf, "fit,?", 5) == 0)
    {
        rx0.cmd = CMD_APF_GET_FIT;
        apf_get_fit();

        retVal = rx0.cmd;
        return(retVal);
    }

    else if (strncmp(rx0.buf, "fit", 3) == 0)
    {
        rx0.cmd = CMD_APF_SET_FIT;
        apf_set_fit();

        retVal = rx0.cmd;
        return(retVal);
    }

    //---------- G --------------
    else if(strncmp(rx0.buf, "gc", 2) == 0)            // get calibration coefficients
    {
        rx0.cmd = CMD_GETCAL;

        get_pH_sensor_cal_coeff();
        retVal = rx0.cmd;
    }

    else if (strncmp(rx0.buf, "getperiod", 6) == 0)
    {
        rx0.cmd = CMD_GETPERIOD;
        cmd_get_period();
        retVal = rx0.cmd;
        return(retVal);
    }

    else if(strncmp(rx0.buf, "gh", 2) == 0)            // get data header
    {
        rx0.cmd = CMD_GETHEADER;

        get_header();
        retVal = rx0.cmd;
        return(retVal);
    }

    else if (strncmp(rx0.buf, "gm", 2) == 0)            // get metadata header
    {
        rx0.cmd = CMD_GETMETADATA;

        print_metadata_header( ROM_HibernateRTCGet() );
        retVal = rx0.cmd;
        return(retVal);
    }

    //---------- H --------------

    else if(strncmp(rx0.buf, "help", 4) == 0)            // help
    {
        rx0.cmd = CMD_HELP;
        print_cmd_help();
        retVal = rx0.cmd;
        return(retVal);
    }

    else if(strncmp(rx0.buf, "h2m", 3) == 0)            // h2m timing
    {
        rx0.cmd = CMD_APF_H2M;
        apf_set_h2m_timeout();
        retVal = rx0.cmd;
        return(retVal);
    }

    //else if(strncmp(rx0.buf, "h2m", 3) == 0)            // h2m timing
    else if((rx0.buf[0] == 'h') && (rx0.buf[1] == 0))
    {
        rx0.cmd = CMD_APF_H2M;
        apf_set_h2m_timeout();
        apf_print_help();
        retVal = rx0.cmd;
        return(retVal);
    }

    //---------- I --------------
    else if( (strncmp(rx0.buf, "ik", 2) == 0)  )          // Ik Counter electrode current
    {
        //if(rx0.indx > 2)
        if(rx0.buf[3] == 's')
        {
            //ik set 1
            //01234567
            rx0.cmd = CMD_SETCFG_IK;
            cmd_set_ik((unsigned int)rx0.buf[7]);
        }
        else if(rx0.buf[3] == 'g')
        {
            rx0.cmd = CMD_GETCFG_IK;
            cmd_get_ik();
        }
        else
        {
            rx0.cmd = CMD_TEST_IK;
            num = 1;
            //if num >= 3, then vk_std is automatic
            cmd_test_ik(num);
        }
        retVal = rx0.cmd;
        return(retVal);
    }

    else if( (strncmp(rx0.buf, "ib", 2) == 0)  )          // Ib Substrate current
    {
        //if(rx0.indx > 2)
        if(rx0.buf[3] == 's')
        {
            //ib set 1
            //01234567
            rx0.cmd = CMD_SETCFG_IB;
            cmd_set_ib((unsigned int)rx0.buf[7]);
        }
        else if(rx0.buf[3] == 'g')
        {
            rx0.cmd = CMD_GETCFG_IB;
            cmd_get_ib();
        }
        else
        {
            rx0.cmd = CMD_TEST_IB;
            num = 1;
            //if num >= 3, then ib_std is automatic
            cmd_test_ib(num);
        }
        retVal = rx0.cmd;
        return(retVal);
    }

    else if (strncmp(rx0.buf, "init", 4) == 0)
    {
        rx0.cmd = CMD_APF_INIT;
        apf_init();

        retVal = rx0.cmd;
        return(retVal);
    }

    //---------- M --------------

    else if( (strncmp(rx0.buf, "microsd", 7) == 0) )          // store (microsd or spi flash)
    {
        if(rx0.indx > 7)
        {
            rx0.cmd = CMD_SETSTORE;
            cmd_set_store();
        }
        else
        {
            rx0.cmd = CMD_GETSTORE;
            cmd_get_store();
        }
        retVal = rx0.cmd;
        return(retVal);
    }

    else if (strncmp(rx0.buf, "mode,?", 6) == 0)
    {
        rx0.cmd = CMD_APF_GET_MODE;
        apf_get_mode();

        retVal = rx0.cmd;
        return(retVal);
    }

    else if (strncmp(rx0.buf, "mode", 4) == 0)
    {
        rx0.cmd = CMD_APF_SET_MODE;
        apf_set_mode();

        retVal = rx0.cmd;
        return(retVal);
    }

    else if(strncmp(rx0.buf, "m2m", 3) == 0)            // m2m timing
    {
        rx0.cmd = CMD_APF_M2M;
        apf_set_m2m_timeout();
        retVal = rx0.cmd;
        return(retVal);
    }

    //handle main menu selection
    else if((rx0.buf[0] == 'm') && (rx0.buf[1] == 0))
    {
        exec_main_menu();       // DEBUG, call this loop to prove 'M'
        return(CMD_MAINMENU);
    }

    //---------- O --------------
    else if (strncmp(rx0.buf, "off", 3) == 0)
    {
        rx0.cmd = CMD_APF_OFF;
        apf_off();

        retVal = rx0.cmd;
        return(retVal);
    }

    //---------- P --------------

    //else if (strncmp(rx0.buf, "pc", 2) == 0)
    else if((rx0.buf[0] == 'p') && (rx0.buf[1] == 0))
    {
        rx0.cmd = CMD_APF_GET_PC;
        apf_get_pc();               // PC Print Counters

        retVal = rx0.cmd;
        return(retVal);
    }
    else if( (strncmp(rx0.buf, "period", 3) == 0) )        // getperiod
    {

       // if( (rx0.indx > 7) || ( (rx0.buf[3]) == ' ') && (rx0.buf[5] >= '0') && (rx0.buf[5] <= '9') ) )
        if( (rx0.buf[3] == ' ') && (rx0.buf[5] >= '0') && (rx0.buf[5] <= '9') )
        {
            rx0.cmd = CMD_SETPERIOD;
            cmd_set_period();
        }
        else if (rx0.indx > 7)
        {
            rx0.cmd = CMD_SETPERIOD;
            cmd_set_period();
        }
        else
        {
            rx0.cmd = CMD_GETPERIOD;
            cmd_get_period();
        }

        retVal = rx0.cmd;
        return(retVal);
    }

    //---------- Q --------------
    //else if (strncmp(rx0.buf, "qq", 2) == 0)
    else if((rx0.buf[0] == 'q') && (rx0.buf[1] == 0))
    {
        rx0.cmd = CMD_APF_GET_QQ;
        apf_get_sensor_type();               // Sensor mode (ISUS, DURAFET)  would like to deprecate this

        retVal = rx0.cmd;
        return(retVal);
    }

    //---------- R --------------
    else if (strncmp(rx0.buf, "rtc,?", 5) == 0)
    {
        rx0.cmd = CMD_APF_GET_RTC;
        apf_get_rtc();

        retVal = rx0.cmd;
        return(retVal);
    }
    else if (strncmp(rx0.buf, "rtc", 3) == 0)
    {
        rx0.cmd = CMD_APF_SET_RTC;
        apf_set_rtc();

        retVal = rx0.cmd;
        return(retVal);
    }


    //---------- S --------------

    //else if( (strncmp(rx0.buf, "samp", 4) == 0)  || (strncmp(rx0.buf, "sample", 6) == 0) )          // sample
    // sample turns on regular sleepless sampling by toggling a flag in main loop
    else if( (strncmp(rx0.buf, "sample", 6) == 0) )          // sample
    {
        if( (rx0.buf[8] >= '0') && (rx0.buf[8] <= '9') )
        {
            //samp 3
            //sample 3
            //0123456789012
            //read in loop time (seconds)

            // TODO read number of seconds
            rx0.cmd = CMD_SAMP_DATABARF;
            //barfSampleTime = (rx0.buf[7] & 0x0f) * 1000;
            cmd_test_sample((unsigned int)(rx0.buf[7] & 0x0f));

        }
        else
        {
            rx0.cmd = CMD_SAMP_DATABARF;

            cmd_test_sample(5);
        }
        retVal = rx0.cmd;
        return(retVal);
    }

    else if( (strncmp(rx0.buf, "sampnum", 7) == 0)  )          // sampnum
    {
        if(rx0.buf[8] == 's')
        {
            //sampnum set 1
            //0123456789012
            rx0.cmd = CMD_SETCFG_SAMPNUM;
            cmd_set_cfg_sampnum((unsigned int)rx0.buf[12]);
        }
        else if(rx0.buf[8] == 'g')
        {
            rx0.cmd = CMD_GETCFG_SAMPNUM;
            cmd_get_cfg_sampnum();
        }
        else
        {
            rx0.cmd = CMD_TEST_SAMPNUM;
            if(rx0.indx > 7)
            {
                //read argument (up to 7 digits)
                num = 0;    // force to 0 for now
                cmd_set_sampnum(num);
            }
            else
            {
                num = 1;        // Future: num in this context might mean number of times to read sampnum???
                cmd_test_sampnum(num);
            }

        }
        retVal = rx0.cmd;
        return(retVal);
    }



    //else if (strncmp(rx0.buf, "sc", 2) == 0)
    else if((rx0.buf[0] == 's') && (rx0.buf[1] == 0))
    {
        rx0.cmd = CMD_APF_GET_SC;
        apf_get_sc();                           // get sample counter

        retVal = rx0.cmd;
        return(retVal);
    }
    else if(strncmp(rx0.buf, "setfilename", 6) == 0)        // setfilename
    {
        rx0.cmd = CMD_SETFILENAME;
        cmd_set_filename();
        retVal = rx0.cmd;
        return(retVal);
    }

    else if(strncmp(rx0.buf, "setperiod", 6) == 0)        // setperiod
    {
        rx0.cmd = CMD_SETPERIOD;
        cmd_set_period();
        retVal = rx0.cmd;
        return(retVal);
    }

    else if(strncmp(rx0.buf, "settime", 5) == 0)        // settime
    {
        rx0.cmd = CMD_SETTIME;
        cmd_set_time();
        retVal = rx0.cmd;
        return(retVal);
    }

    else if (strncmp(rx0.buf, "se,?", 4) == 0)
    {
        rx0.cmd = CMD_APF_GET_SE;
        apf_get_se();                           // get number of error messages

        retVal = rx0.cmd;
        return(retVal);
    }

    else if ((strncmp(rx0.buf, "se", 2) == 0) && rx0.buf[2] == 0 )
    {
        rx0.cmd = CMD_APF_XFER_SE;
        apf_xfer_se();                          // send msc error messages

        retVal = rx0.cmd;
        return(retVal);
    }
    else if( (strncmp(rx0.buf, "sleep", 5) == 0) || (strncmp(rx0.buf, "nap", 3) == 0) || (strncmp(rx0.buf, "zz", 2) == 0) || (strncmp(rx0.buf, "zzz", 3) == 0)
            || (strncmp(rx0.buf, "quit", 4) == 0) || (strncmp(rx0.buf, "stop", 4) == 0) || (strncmp(rx0.buf, "exit", 4) == 0)    )
    {
        databarFlg = 0;
        rx0.cmd = CMD_SLEEP;
        retVal = rx0.cmd;            // return -1 to exit exec_main_loop
        return(retVal);
    }

    else if (strncmp(rx0.buf, "slp", 3) == 0)
    {
        rx0.cmd = CMD_APF_SLP;
        apf_slp_sleep();                        // MSC suspend mode = SLP

        retVal = rx0.cmd;
        return(retVal);
    }
    else if(strncmp(rx0.buf, "sl", 2) == 0)           // start sample, needs to have sl within 6 sec
    {
        rx0.cmd = CMD_SENDLAST;

        send_last_sample();
        retVal = rx0.cmd;
        return(retVal);
    }

    else if (strncmp(rx0.buf, "spectra,?", 9) == 0)
    {
        rx0.cmd = CMD_APF_GET_SPEC;
        apf_get_spectra();                        // get reported ISUS data range

        retVal = rx0.cmd;
        return(retVal);
    }
    else if (strncmp(rx0.buf, "spectra", 7) == 0)
    {
        rx0.cmd = CMD_APF_SET_SPEC;
        apf_set_spectra();                 // set reported ISUS data range

        retVal = rx0.cmd;
        return(retVal);
    }
    else if(strncmp(rx0.buf, "ss", 2) == 0)           // start sample, needs to have sl within 6 sec
    {
        //flush the receive and transmit buffers
       // UARTFlushRx();
        rx0.cmd = CMD_STARTSAMPLE;

        //get_sample(0,1);
        pump_and_sample(0,1);       // 10 Apr 2022
        fram_last_samp_store();     // defd in i2c_fram.c
#ifdef NOCODE
        // Wait for command 6 seconds, then back to sleep (and dump the data)
        charCount = getUserInputTimeLimit(buff, sizeof(buff), 6);

        if(charCount == TIMELIMITPASSED)  // if retVal is -1, timeout occurred
        {
            if(sys_data.output == VERBOSE) uprintf("\r\n\r\nNo command, resuming deployment...");
            return(1);
        }
        else
        {
            // Parse command
            sl = strncmp(buff, "sl", 2);            // send last sample, must have sent ss first
            if( sl == 0 )
            {
                print_sampBuf();
                wait_consoleTx();

                return(1);

            }
            else
            {
                uprintf("\r\nexpected sl, received %s\r\n", buff);
                // no return or break, should put the code back to looking for next command
            }
        }
#endif
        retVal = rx0.cmd;
        return(retVal);
    }
    else if( (strncmp(rx0.buf, "store", 5) == 0) )          // store (microsd or spi flash)
    {
        if(rx0.indx > 5)
        {
            rx0.cmd = CMD_SETSTORE;
            cmd_set_store();
        }
        else
        {
            rx0.cmd = CMD_GETSTORE;
            cmd_get_store();
        }
        retVal = rx0.cmd;
        return(retVal);
    }



    //---------- T --------------
    //else if (strncmp(rx0.buf, "ta", 2) == 0)
    else if((rx0.buf[0] == 't') && (rx0.buf[1] == 0))
    {
        rx0.cmd = CMD_APF_GET_TA;
        apf_get_acq_time();                        // get acquisition time for last sample

        retVal = rx0.cmd;
        return(retVal);
    }

    else if( (strncmp(rx0.buf, "tempc", 5) == 0)  )          // compute temperature in celsius
    {
        if(rx0.buf[6] == 's')
        {
            //tempc set 1
            //012345678901
            rx0.cmd = CMD_SETCFG_TEMPC;
            cmd_set_tempc((unsigned int)rx0.buf[10]);
        }
        else if(rx0.buf[6] == 'g')
        {
            rx0.cmd = CMD_GETCFG_TEMPC;
            cmd_get_tempc();
        }
        else
        {
            rx0.cmd = CMD_TEST_TEMPC;
            num = 1;
            cmd_test_tempc(num);

        }
        retVal = rx0.cmd;
        return(retVal);
    }


    else if( (strncmp(rx0.buf, "timestamp", 9) == 0)  )          // timestamp
    {
        //if(rx0.indx > 9)
        if(rx0.buf[10] == 's')
        {
            //timestamp set 1
            //012345678901234
            rx0.cmd = CMD_SETCFG_TIMESTAMP;
            cmd_set_timestamp((unsigned int)rx0.buf[14]);
        }
        else if(rx0.buf[10] == 'g')
        {
            rx0.cmd = CMD_GETCFG_TIMESTAMP;
            cmd_get_timestamp();
        }
        else
        {
            rx0.cmd = CMD_TEST_TIMESTAMP;
            num = 1;
            cmd_test_timestamp(num);
        }
        retVal = rx0.cmd;
        return(retVal);
    }



    else if( (strncmp(rx0.buf, "time", 4) == 0) ||  (strncmp(rx0.buf, "gettime", 5) == 0) )          // gettime
    {
        // allow >time 11/07/23 13:45:30<cr>
        if(rx0.indx > 6)
        {
            rx0.cmd = CMD_SETTIME;
            cmd_set_time();
        }
        else
        {
            rx0.cmd = CMD_GETTIME;
            cmd_get_time();
        }
        retVal = rx0.cmd;
        return(retVal);
    }

    else if (strncmp(rx0.buf, "tint,?", 5) == 0)
    {
        rx0.cmd = CMD_APF_GET_TINT;
        apf_get_int_time();                        // get integration time

        retVal = rx0.cmd;
        return(retVal);
    }
    else if (strncmp(rx0.buf, "tint", 4) == 0)
    {
        rx0.cmd = CMD_APF_SET_TINT;
        apf_set_int_time();                        // set integration time

        retVal = rx0.cmd;
        return(retVal);
    }

    else if(strncmp(rx0.buf, "ts", 2) == 0)            // take sample
    {
        rx0.cmd = CMD_TAKESAMPLE;
        pump_and_sample(1,1);
        retVal = rx0.cmd;
        return(retVal);

#ifdef APFTODO
        if( sys_sensor_mode == ISUS_SENSOR_MODE ) {
            printf("ACK,TS,CMD\n");
            if( sys_data_mode == 2 )
                ret = TakeIsusPseudoSample(dbuf, &acquire_time, CTD_Time, CTD_Temp, CTD_Salinity, CTD_Depth);
            else
                ret = TakeIsusSample(dbuf, &acquire_time, CTD_Time, CTD_Temp, CTD_Salinity, CTD_Depth);
        }
        else if( sys_sensor_mode == DURA_SENSOR_MODE ) {
            printf("ACK,TS,CMD\n");
            ret = TakeDuraSample(dbuf, &acquire_time, CTD_Time, CTD_Temp, CTD_Salinity, CTD_Depth);
        }
        else{
            printf("NAK,TS,InvalidModeValue: %d\n", sys_sensor_mode);
            SCIRxFlush();
            continue;
        }

        if( ret == OK ) {
            printf("ACK,TS,DAT\n");
            gotSample = TRUE;
        }
        else{
            printf("NAK,TS,DAT\n");
            gotSample = FALSE;
        }
        SCIRxFlush();
        continue;
#endif

    }

    else if(strncmp(rx0.buf, "t1", 2) == 0)            // take Isus Sample
    {
        rx0.cmd = CMD_APF_ISUS_T1;

        apf_take_sample_nitrate();      // ISUS sample
        retVal = rx0.cmd;
        return(retVal);

#ifdef APFTODO
        printf("ACK,T1,CMD\n");
        if( sys_data_mode == 2 )
            ret = TakeIsusPseudoSample(dbuf, &acquire_time, CTD_Time, CTD_Temp, CTD_Salinity, CTD_Depth);
        else
            ret = TakeIsusSample(dbuf, &acquire_time, CTD_Time, CTD_Temp, CTD_Salinity, CTD_Depth);

        if( ret == OK ) {
            printf("ACK,T1,DAT\n");
            gotSample = TRUE;
        }
        else{
            printf("NAK,T1,DAT\n");
            gotSample = FALSE;
        }
        SCIRxFlush();
#endif


    }
    else if(strncmp(rx0.buf, "t2", 2) == 0)            // take Dura pH Sample
    {
        rx0.cmd = CMD_APF_DURA_T2;
        apf_take_sample_pH();

        retVal = rx0.cmd;
        return(retVal);
#ifdef APFTODO
        printf("ACK,T2,CMD\n");
        ret = TakeDuraSample(dbuf, &acquire_time, CTD_Time, CTD_Temp, CTD_Salinity, CTD_Depth);

        if( ret == OK ) {
            printf("ACK,T2,DAT\n");
            gotSample = TRUE;
        }
        else{
            printf("NAK,T2,DAT\n");
            gotSample = FALSE;
        }
        SCIRxFlush();

#endif
    }



    //---------- V --------------
    else if( (strncmp(rx0.buf, "vbat", 4) == 0)  )          // vbat
    {

        if(rx0.buf[5] == 's')
        {
            //vbat set 1
            rx0.cmd = CMD_SETCFG_VBAT;
            cmd_set_vbat(rx0.buf[9]);
        }
        else if(rx0.buf[5] == 'g')
        {
            //vbat get
            rx0.cmd = CMD_GETCFG_VBAT;
            cmd_get_vbat();
        }
        else
        {
            // get count, pass in as num
            rx0.cmd = CMD_TEST_VBAT;
            num = 1;
            cmd_test_vbat(num);

            //vbat or vbat nnnnnn (doforever if 0)
        }
        retVal = rx0.cmd;
        return(retVal);
    }


    else if(strncmp(rx0.buf, "version", 3) == 0)            // help
    {
        rx0.cmd = CMD_GETVERSION;
        print_cmd_version();
        retVal = rx0.cmd;
        return(retVal);
    }

    // parse vk_std ahead of vk
    else if( (strncmp(rx0.buf, "vk_std", 6) == 0)  )          // Vk_std Counter electrode current
    {
        if(rx0.buf[7] == 's')
        {
            //vk_std set 1
            //012345678901
            rx0.cmd = CMD_SETCFG_VK_STD;
            cmd_set_vk_std((unsigned int)rx0.buf[11]);
        }
        else if(rx0.buf[7] == 'g')
        {
            rx0.cmd = CMD_GETCFG_VK_STD;
            cmd_get_vk_std();
        }
        else
        {
            rx0.cmd = CMD_TEST_VK_STD;
            num = 1;
            //if num >= 3, then vk_std is automatic
            cmd_test_vk_std(num);
        }
        retVal = rx0.cmd;
        return(retVal);
    }



    else if( (strncmp(rx0.buf, "vk", 2) == 0)  )          // Vk Counter electrode voltage
    {
        //if(rx0.indx > 2)
        if(rx0.buf[3] == 's')
        {
            //vk set 1
            //01234567
            rx0.cmd = CMD_SETCFG_VK;
            cmd_set_vk((unsigned int)rx0.buf[7]);
        }
        else if(rx0.buf[3] == 'g')
        {
            rx0.cmd = CMD_GETCFG_VK;
            cmd_get_vk();
        }
        else
        {
            rx0.cmd = CMD_TEST_VK;
            num = 1;
            //if num >= 3, then vk_std is automatic
            cmd_test_vk(num);

        }
        retVal = rx0.cmd;
        return(retVal);
    }



    else if( (strncmp(rx0.buf, "vrsi_std", 6) == 0)  )          // vrse_std
    {
        //if(rx0.indx > 8)
        if(rx0.buf[9] == 's')
        {
            //vrsi_std set 1
            //01234567890123
            rx0.cmd = CMD_SETCFG_VRSI_STD;
            cmd_set_vrsi_std((unsigned int)rx0.buf[13]);
        }
        else if(rx0.buf[9] == 'g')
        {
            rx0.cmd = CMD_GETCFG_VRSI_STD;
            cmd_get_vrsi_std();
        }
        else
        {
            rx0.cmd = CMD_TEST_VRSI_STD;
            num = 1;
            cmd_test_vrsi_std(num);
        }
        retVal = rx0.cmd;
        return(retVal);
    }

    else if( (strncmp(rx0.buf, "vrse_std", 6) == 0)  )          // vrse_std
    {
        //if(rx0.indx > 8)
        if(rx0.buf[9] == 's')
        {
            rx0.cmd = CMD_SETCFG_VRSE_STD;
            cmd_set_vrse_std((unsigned int)rx0.buf[13]);
        }
        else if(rx0.buf[9] == 'g')
        {
            rx0.cmd = CMD_GETCFG_VRSE_STD;
            cmd_get_vrse_std();
        }
        else
        {
            rx0.cmd = CMD_TEST_VRSE_STD;
            num = 1;
            cmd_test_vrse_std(num);
        }
        retVal = rx0.cmd;
        return(retVal);
    }

    //vrsi
    //vrsi 1
    //vrsi set 1
    //vrsi get
    //vrsi test (t)
    //vrsi testcontinuous (c)
    else if( (strncmp(rx0.buf, "vrsi", 4) == 0) )        // getvrsi
    {
        //if((rx0.indx > 5) && (rx0.buf[5] >= '0') && (rx0.buf[5] <= '1'))
        if(rx0.buf[5] == 's')
        {
            //vrsi set 1
            //0123456789
            rx0.cmd = CMD_SETCFG_VRSI;
            cmd_set_vrsi((unsigned int)rx0.buf[9]);
        }
        else if(rx0.buf[5] == 'g')
        {
            rx0.cmd = CMD_GETCFG_VRSI;
            cmd_get_vrsi();
        }
        else
        {
            rx0.cmd = CMD_TEST_VRSI;
            num = 1;
            cmd_test_vrsi(num);
        }

        retVal = rx0.cmd;
        return(retVal);
    }

    //vrse
    //vrse 1
    //vrse test (t)
    //vrse testcontinuous (c)
    else if( (strncmp(rx0.buf, "vrse", 4) == 0) )        // getvrse
    {
        //if((rx0.indx > 5) && (rx0.buf[5] >= '0') && (rx0.buf[5] <= '1'))
        if(rx0.buf[5] == 's')
        {
            //vrse set 1
            //0123456789
            rx0.cmd = CMD_SETCFG_VRSE;
            cmd_set_vrse((unsigned int)rx0.buf[9]);
        }
        else if(rx0.buf[5] == 'g')
        {
            rx0.cmd = CMD_GETCFG_VRSE;
            cmd_get_vrse();
        }
        else
        {
            rx0.cmd = CMD_TEST_VRSE;
            num = 1;
            cmd_test_vrse(num);

        }

        retVal = rx0.cmd;
        return(retVal);
    }
    // parse vtherm_std before vtherm
    else if( (strncmp(rx0.buf, "vtherm_std", 9) == 0)  )          // Vk Counter electrode voltage
    {
        //if(rx0.indx > 6)
        //vtherm_std set 1
        //012345678901234567
        if(rx0.buf[11] == 's')
        {
            // vtherm set 1
            // 012345678901
            rx0.cmd = CMD_SETCFG_VTHERM_STD;
            cmd_set_vtherm_std((unsigned int)rx0.buf[15]);
        }
        else if(rx0.buf[11] == 'g')
        {
            rx0.cmd = CMD_GETCFG_VTHERM_STD;
            cmd_get_vtherm_std();
        }
        else
        {
            rx0.cmd = CMD_TEST_VTHERM_STD;
            num = 1;
            cmd_test_vtherm_std(num);

        }
        retVal = rx0.cmd;
        return(retVal);
    }

    else if( (strncmp(rx0.buf, "vtherm", 6) == 0)  )          // Vk Counter electrode voltage
    {
        //if(rx0.indx > 6)
        if(rx0.buf[7] == 's')
        {
            // vtherm set 1
            // 012345678901
            rx0.cmd = CMD_SETCFG_VTHERM;
            cmd_set_vtherm((unsigned int)rx0.buf[11]);
        }
        else if(rx0.buf[7] == 'g')
        {
            rx0.cmd = CMD_GETCFG_VTHERM;
            cmd_get_vtherm();
        }
        else
        {
            rx0.cmd = CMD_TEST_VTHERM;
            num = 1;
            cmd_test_vtherm(num);

        }
        retVal = rx0.cmd;
        return(retVal);
    }


    //---------- W --------------

    //else if (strncmp(rx0.buf, "ww", 2) == 0)            // APF ping response
    else if((rx0.buf[0] == 'w') && (rx0.buf[1] == 0))
    {
        rx0.cmd = CMD_APF_PING;
        apf_print_ping_response();

        retVal = rx0.cmd;
        return(retVal);
    }


    else if((rx0.buf[0] == 'z') && (rx0.buf[1] == 0))
    {
        rx0.cmd = CMD_THOMZ_TEST;
        IsusLampTest();

        retVal = rx0.cmd;
        return(retVal);
    }


    else
    {

    }


    return(retVal);

}

#ifdef OLDCODE

    // handle TS and ts

    // Configure
    //  "CTS        Configure:Time:Set
    //  "CTG"       Configure:Time:Get
    //  "CFS        Configure:FileName:Set
    //  "CFG        Configure:Filename:Get
    //  "CSS        Configure:Sampleperiod:Set
    //  "SLP        Sleep
    //  "DGO        Deploy Go
    //  "DSP        Deploy Stop
    //  "TS         Take Sample
    //  "SS         Start Sample
    //  "SL         Send last
    //  "GH         Get Header
    //  "GC         Get Cal
    //  "EC         Export Cal
    //  "DG         Data Get

#endif




