/*
 * serial_cmd_fxn.c
 *
 *  Created on: May 3, 2024
 *      Author: thomm
 */

#include "stdint.h"
#include "string.h"


#include "system.h"
#include "sample.h"
#include "config.h"
#include "test.h"
#include "uart3.h"
#include "uartstdio.h"
#include "user_io.h"
#include "serial.h"
#include "serial_cmd_fxn.h"
#include "apf.h"
#include "apf_util.h"
#include "mms_test.h"




extern int microSD_flg;
extern struct systemSamplingData sys_samp;
extern struct rxStateMach rx0;             // defd in serial.h
extern struct apfGlobals apf;               // defd in apf.h

extern unsigned int databarFlg;
extern unsigned int barfSampleTime;

extern int    Zcoefs, Ecoefs, Zeros;





void apf_print_help(void)
{
    uprintf("\nCommands: [W,M,E,P,S,T,C,Q,TS,T1,T2,SL,SE,SLP,OFF,RTC,FIT,CTD,MODE,INIT,BAKE,SPECTRA]\n");
}

void apf_print_ping_response(void)
{
    uprintf("ACK\r\n");   // apf spec doesnt mention cr-lf,  CF2 implementation is \n only
}

void apf_bake_uv_lamp(void)
{
    uprintf("Imp es Nada apf_bake_uv_lamp\r\n");
}

void apf_get_cfg(void)
{


    if( apf.sys_sensor_mode == ISUS_SENSOR_MODE )
        print_isus_header();        //OutputIsusHeader(stdout);
    else if( apf.sys_sensor_mode == DURA_SENSOR_MODE )
        print_dura_header();     //OutputDuraHeader(stdout);
    else
        printf("NAK,C,InvalidModeValue: %d\n", apf.sys_sensor_mode);


    uprintf("Imp es Nada apf_get_cfg\r\n");
}

void apf_get_cal(void)
{
    uprintf("Imp es Nada apf_get_cal\r\n");
}

void apf_get_ctd(void)
{
    uprintf("Imp es Nada apf_get_ctd\r\n");
}

void apf_set_ctd(void)
{
    uprintf("Imp es Nada apf_set_ctd\r\n");
}

void apf_get_err(void)
{
    if( apf.sys_sensor_mode == ISUS_SENSOR_MODE )
        uprintf("ACK,E,%lu,%lu\n", apf.isus_error_ctr, apf.isus_error_time);
    else if( apf.sys_sensor_mode == DURA_SENSOR_MODE )
        uprintf("ACK,E,%lu,%lu\n", apf.dura_error_ctr, apf.dura_error_time);
    else
        uprintf("NAK,E,InvalidModeValue: %d\n", apf.sys_sensor_mode);

    //uprintf("Imp es Nada apf_get_err\r\n");
}



void apf_set_fit(void)
{
    uprintf("Imp es Nada apf_set_fit\r\n");
}

void apf_get_fit(void)
{
    uprintf("Imp es Nada apf_get_fit\r\n");
}

void apf_init(void)
{

    apf.sys_watchdog_enable=TRUE;           //DS3234_WrSRAM(SYS_WDOGENABLE_PTR, sizeof(uchar), (uchar*)&sys_watchdog_enable);
    apf.sys_message_enable=0;                   //DS3234_WrSRAM(SYS_MSGENABLE_PTR, sizeof(uchar), (uchar*)&sys_message_enable);
    apf.sys_data_mode=1;                            //DS3234_WrSRAM(SYS_DATAMODE_PTR, sizeof(uchar), (uchar*)&sys_data_mode);
    apf.isus_tcomp_mode=TRUE;                   //DS3234_WrSRAM(ISUS_TCOMPMODE_PTR, sizeof(uchar), (uchar*)&isus_tcomp_mode);
    apf.isus_salfit_mode=FIX;                       //DS3234_WrSRAM(ISUS_SALFITMODE_PTR, sizeof(uchar), (uchar*)&isus_salfit_mode);
    apf.dura_led_enable=0;                              //DS3234_WrSRAM(DURA_LEDENABLE_PTR, sizeof(uchar), (uchar*)&dura_led_enable);

    apf.isus_fit_concs=2;                           //DS3234_WrSRAM(ISUS_FITCONCS_PTR, sizeof(ushort), (ushort*)&isus_fit_concs);
    apf.sys_ef_limit=128;                               //DS3234_WrSRAM(SYS_EFLIMIT_PTR, sizeof(ushort), (ushort*)&sys_ef_limit);
    apf.sys_df_limit=5;                 //DS3234_WrSRAM(SYS_DFLIMIT_PTR, sizeof(ushort), (ushort*)&sys_df_limit);
    apf.sys_apf_tmout=10;                               //DS3234_WrSRAM(SYS_APFTMOUT_PTR, sizeof(ushort), (ushort*)&sys_apf_tmout);

    apf.sys_por_ctr=0L;                                     //DS3234_WrSRAM(SYS_PORCTR_PTR, sizeof(ulong), (ulong*)&sys_por_ctr);
    apf.sys_reset_ctr=0L;                               //DS3234_WrSRAM(SYS_RESETCTR_PTR, sizeof(ulong), (ulong*)&sys_reset_ctr);

    apf.sys_last_error=0;                               //DS3234_WrSRAM(SYS_LASTERROR_PTR, sizeof(int), (int*)&sys_last_error);
    apf.sys_error_ctr=0L;                               //DS3234_WrSRAM(SYS_ERRORCTR_PTR, sizeof(ulong), (ulong*)&sys_error_ctr);
    apf.sys_error_time=0L;                              //DS3234_WrSRAM(SYS_LASTERRTIME_PTR, sizeof(ulong), (ulong*)&sys_error_time);

    apf.isus_last_error=0;                              //DS3234_WrSRAM(ISUS_LASTERROR_PTR, sizeof(int), (int*)&isus_last_error);
    apf.isus_error_ctr=0L;                             // DS3234_WrSRAM(ISUS_ERRORCTR_PTR, sizeof(ulong), (ulong*)&isus_error_ctr);
    apf.isus_error_time=0L;                             //DS3234_WrSRAM(ISUS_LASTERRTIME_PTR, sizeof(ulong), (ulong*)&isus_error_time);
    apf.isus_sample_ctr=0L;                     //DS3234_WrSRAM(ISUS_SAMPLECTR_PTR, sizeof(ulong), (ulong*)&isus_sample_ctr);
    apf.isus_sample_time=0L;                    //DS3234_WrSRAM(ISUS_LASTSAMPTIME_PTR, sizeof(ulong), (ulong*)&isus_sample_time);

    apf.dura_last_error=0;                     //DS3234_WrSRAM(DURA_LASTERROR_PTR, sizeof(int), (int*)&dura_last_error);
    apf.dura_error_ctr=0L;                      //DS3234_WrSRAM(DURA_ERRORCTR_PTR, sizeof(ulong), (ulong*)&dura_error_ctr);
    apf.dura_error_time=0L;                     //DS3234_WrSRAM(DURA_LASTERRTIME_PTR, sizeof(ulong), (ulong*)&dura_error_time);
    apf.dura_sample_ctr=0L;                     //DS3234_WrSRAM(DURA_SAMPLECTR_PTR, sizeof(ulong), (ulong*)&dura_sample_ctr);
    apf.dura_sample_time=0L;                    //DS3234_WrSRAM(DURA_LASTSAMPTIME_PTR, sizeof(ulong), (ulong*)&dura_sample_time);

    if( (Zcoefs > 0) || (Ecoefs == 256) ) { //wavelength info SHOULD be loaded
        //SET FIT WINDOW
        apf.lambda_beg=217;
        apf.lambda_end=240;
        MatchPixelsToLambda(apf.LambdaData, apf.lambda_beg, apf.lambda_end, &apf.isus_pixel_beg, &apf.isus_pixel_end);
        uprintf("apf_init(), ser_cmd_fxn.c, needs DS3234 stored in FRAM");          //APFTODO
        //DS3234_WrSRAM(ISUS_PIXELBEG_PTR, sizeof(ushort), (ushort*)&apf.isus_pixel_beg);
        //DS3234_WrSRAM(ISUS_PIXELEND_PTR, sizeof(ushort), (ushort*)&apf.isus_pixel_end);
        apf.isus_fit_pixels = (apf.isus_pixel_end - apf.isus_pixel_beg) + 1;

        //SET DATA WINDOW (SEE TS AND SL COMMANDS)
        apf.lambda_beg=217;
        apf.lambda_end=250;
        MatchPixelsToLambda(apf.LambdaData, apf.lambda_beg, apf.lambda_end, &apf.isus_datpixel_beg, &apf.isus_datpixel_end);
        //DS3234_WrSRAM(ISUS_DATPIXELBEG_PTR, sizeof(ushort), (ushort*)&isus_datpixel_beg);
        //DS3234_WrSRAM(ISUS_DATPIXELEND_PTR, sizeof(ushort), (ushort*)&isus_datpixel_end);
    }

    printf("ACK,INIT\n");
    //SCIRxFlush();

//#endif
   // uprintf("Imp es Nada apf_init\r\n");
}

void apf_set_mode(void)
{
    uprintf("Imp es Nada apf_set_mode\r\n");
}

void apf_get_mode(void)
{
    uprintf("Imp es Nada apf_get_mode\r\n");
}

void apf_off(void)
{
    uprintf("Imp es Nada apf_off\r\n");
}

void apf_get_pc(void)
{
    uprintf("ACK,P,%lu,%lu,%lu\n", apf.sys_por_ctr, apf.sys_reset_ctr, apf.sys_reset_time);
    //uprintf("Imp es Nada apf_get_pc\r\n");
}

void apf_get_sensor_type(void)
{
    uprintf("ACK,Q,%d\n", apf.sys_sensor_type);     // APFTODO cr-lf
    //uprintf("Imp es Nada apf_get_sensor_type\r\n");
}

void apf_set_rtc(void)
{
    uprintf("Imp es Nada apf_set_rtc\r\n");
}

void apf_get_rtc(void)
{
    uprintf("Imp es Nada apf_get_rtc\r\n");
}

void apf_get_get_sc(void)
{
    uprintf("Imp es Nada apf_get_get_sc\r\n");
}

void apf_xfer_se(void)
{

#ifdef APFTODO
    if( (srchptr=strstr(cbuf, "SE")) != NULL ) {
        if(strchr(srchptr, '?') != NULL) {
            if( (Erecs=CalcRecsPending((uchar)ERRORLOG_FILE)) >= 0 )
                printf("ACK,SE?,%ld\n", Erecs);
            else
                printf("NAK,SE?,%ld\n", Erecs);
        }
        else
            SendRecords((uchar)ERRORLOG_FILE, &Efpos);

        SCIRxFlush();
        continue;
    }
#endif

    uprintf("Imp es Nada apf_xfer_se\r\n");
}

void apf_get_se(void)
{
    uprintf("Imp es Nada apf_get_se\r\n");
}

// get sample counter
void apf_get_sc(void)
{
#ifdef APFTODO
    if( apf.sys_sensor_mode == ISUS_SENSOR_MODE )
        printf("ACK,S,%lu,%lu\n", apf.isus_sample_ctr, apf.isus_sample_time);
    else if( apf.sys_sensor_mode == DURA_SENSOR_MODE )
        printf("ACK,S,%lu,%lu\n", apf.dura_sample_ctr, apf.dura_sample_time);
    else
        printf("NAK,S,InvalidModeValue: %d\n", apf.sys_sensor_mode);
#endif
    uprintf("Imp es Nada apf_get_sc\r\n");
}

void apf_slp_sleep(void)
{
    uprintf("Imp es Nada apf_slp_sleep\r\n");
}

void apf_set_spectra(void)
{
    uprintf("Imp es Nada apf_set_spectra\r\n");
}

void apf_get_spectra(void)
{
    uprintf("Imp es Nada apf_get_spectra\r\n");
}

void apf_get_acq_time(void)
{

    if( apf.gotSample == TRUE )
        uprintf("ACK,T,%.3f\n", apf.acquire_time);
    else
        uprintf("NAK,T,-1.0\n");

    uprintf("Imp es Nada apf_get_acq_time\r\n");
}

void apf_set_int_time(void)
{
    uprintf("Imp es Nada apf_set_int_time\r\n");
}

void apf_get_int_time(void)
{
    uprintf("Imp es Nada apf_get_int_time\r\n");
}

void apf_set_h2m_timeout(void)
{
    //uprintf("ACK,H2M timeout %u ms", H2M_DELIM_MS_TIMEOUT);

    rx0.tick_ms_delim = H2M_DELIM_MS_TIMEOUT;
}

void apf_set_m2m_timeout(void)
{
    //uprintf("ACK,M2M timeout %u ms", M2M_DELIM_MS_TIMEOUT);

    rx0.tick_ms_delim = M2M_DELIM_MS_TIMEOUT;
}


void apf_take_sample_pH(void)
{
    uprintf("Imp es Nada apf_take_sample_pH\r\n");
}

void apf_take_sample_nitrate(void)
{
    uprintf("Imp es Nada apf_take_sample_nitrate\r\n");
}

//--------- End of APF float commands (thank god) ---------//

void print_cmd_version(void)
{
    uprintf(VERSION);
    uprintf("\r\n");
}

void print_cmd_help(void)
{
    //uprintf("**** command help ****\r\n");
    uprintf("** datalogger setup:  0 for off, 1 for on\r\n");
    uprintf(" time, gettime\r\n");
    uprintf(" time MM/DD/YY HH:MM:SS, settime MM/DD/YY HH:MM:SS\r\n");
    uprintf(" per, period, getperiod\r\n");
    uprintf(" per 20, period 20, setperiod 20\r\n");
    uprintf(" config, getconfig \r\n");
    uprintf(" config, setconfig\r\n");
    uprintf(" config help\r\n");
    uprintf(" filename, getfilename\r\n");
    uprintf(" filename filename.ext, setfilename filename.ext\r\n");
    uprintf(" microsd, store");
    uprintf(" align\r\n");
    uprintf("** commands:\r\n");
    uprintf(" help\r\n");
    uprintf(" sleep\r\n");
    uprintf(" deploy\r\n");
    uprintf(" ts\r\n");
    uprintf(" ss \r\n");
    uprintf(" sl\r\n");
    uprintf(" gc\r\n");
    uprintf(" ec\r\n");
    uprintf(" gh\r\n");
    uprintf(" eh\r\n");
    uprintf(" stop, exit, quit, <ctrl-c>\r\n");
    uprintf("\r\n");
    uprintf("vrsi set 1    vrsi get    vrsi    vrsi 0   vrsi 2000");


}


void cmd_get_period(void)
{
    uprintf("%u", sys_data.sampling_period);
}

void cmd_set_period(void)
{
    int indx;
    int st;
    int spaceFlg;
    unsigned int period;

    //uprintf("dbg %s  %u\r\n", rx0.buf, rx0.indx);  //DEBUG

    spaceFlg = 0;
    // per 1000, period 1000, setperiod 1000
    for(indx=3; indx<rx0.indx; indx++)
    {
        if( (rx0.buf[indx] == ' ') )       // find first space after 'time' or 'settime'
        {
            spaceFlg = 1;
            //uprintf("time: %s", &rx0.buf[indx]);     // DEBUG
        }
        if( (spaceFlg == 1) && ( (rx0.buf[indx] >= '1') && (rx0.buf[indx] <= '9') ) )   //find first number after space
        {
            break;
        }
    }

    st = indx;
    //uprintf("dbg %s\r\n", &rx0.buf[st]);  //DEBUG
    if(sscanf(&rx0.buf[st], "%u", &period) == 1)
    {
        //uprintf("per=%u\r\n", period);
        // sample_period = 0 means POLLED MODE

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


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

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

    }
    else
    {
        uprintf("\r\nEnter seconds greater than or equal to 0 and less than 3600\r\n");
    }

}
unsigned int cmd_get_time(void)
{
    unsigned int ticks;
    ticks = ROM_HibernateRTCGet();
    print_time_t_Time(ticks);

    return(ticks);
}
void cmd_set_time(void)
{
    int indx;
    int st;
    int spaceFlg;

    char monthString[3];
    char dayString[3];
    char yearString[3];
    char hourString[3];
    char minuteString[3];
    char secondString[3];

    char *p;  //helper variable

    int month;
    int day;
    int year;
    int hour;
    int minute;
    int second;

    int validInput = 1; //helper boolean

    //time variables:
    time_t rawtime;
    struct tm * timeStruct;

    //uprintf("dbg %s  %u\r\n", rx0.buf, rx0.cnt);  //DEBUG

    spaceFlg = 0;
    for(indx=4; indx<rx0.indx; indx++)
    {
        if( (rx0.buf[indx] == ' ') )       // find first space after 'time' or 'settime'
        {
            spaceFlg = 1;
            //uprintf("time: %s", &rx0.buf[indx]);     // DEBUG
        }
        if( (spaceFlg == 1) && ( (rx0.buf[indx] >= '1') && (rx0.buf[indx] <= '9') ) )   //find first number after space
        {
            break;
        }
    }

    // if formatted for time
    st = indx;      // start of time string
    if( (rx0.buf[st+2] == '/') && (rx0.buf[st+5] == '/')  && (rx0.buf[st+11] == ':') && (rx0.buf[st+14] == ':') )
    {
        sscanf(&rx0.buf[st], "%02d/%02d/%02d %d:%d:%d", &month, &day, &year, &hour, &minute, &second);

        if( second >= 0 && minute >= 0 && hour >= 0 && month >= 1 && day >= 1 && year >= 0)
        {
            if( second <= 61 && minute <= 59 && hour <= 23 && day <= 31 && month <= 12)
            {
                //fill in time.h's tm struct initially (timeStruct just points to time.h's struct)
                time(&rawtime);
                timeStruct = localtime(&rawtime);

                //modify as user desired
                timeStruct->tm_sec = second;
                timeStruct->tm_min = minute;
                timeStruct->tm_hour = hour;
                timeStruct->tm_mday = day;
                timeStruct->tm_mon = month - 1;
                timeStruct->tm_year = (year + 2000) - 1900;

                //GMT HAS NO DAYLIGHT SAVINGS
                timeStruct->tm_isdst = 0;


                //remake the struct
                rawtime = mktime(timeStruct);

                //print out the time the user entered
                //uprintf( "\r\n\r\nTime is: %s", asctime(timeStruct));

                ROM_HibernateRTCSet(rawtime); // Set time if user entered valid time

                //uprintf("\r\nTime now: ");
                //printCurrentTime();
                //if(sys_data.GMT) uprintf(" GMT");
                //else uprintf(" Local");

                //uprintf("\r\n\r\nNote: Daylight Savings not observed. Use GMT when this will be an issue.\r\n");

                //return rawtime;
            }
        }
        else
        {
            print_NAK();
        }

    }
    else
    {
        print_NAK();
    }

}

void cmd_get_filename(void)
{
    uprintf("%s", sys_data.fileName);
}

void cmd_set_filename(void)
{
    int indx;
    int st;
    int cnt;
    int name_len, ext_len;
    int spaceFlg;
    char name[32];
    char ext[16];


    //uprintf("dbg %s  %u\r\n", rx0.buf, rx0.cnt);

    spaceFlg = 0;
    for(indx=0; indx<rx0.indx; indx++)
    {
        if( (spaceFlg == 0) && (rx0.buf[indx] == ' ') )       // find first space
        {
            spaceFlg = 1;
            //uprintf("filename: %s", &rx0.buf[indx]);     // DEBUG
        }


        if( (spaceFlg == 1) && ( (rx0.buf[indx] >= 'a') && (rx0.buf[indx] <= 'z') ) )   //find first alpha after space
        {
            st = indx;      // buf indx
            //uprintf("dbg filename: %s\r\n", &rx0.buf[st]);     // DEBUG
            //cnt = sscanf(&rx0.buf[st], "%s.%s", &name, &ext);

            name_len = strlen(&rx0.buf[st]);

            if (name_len > 12)
            {
              uprintf("filename is too long, needs to be 8.3 format\r\n");
              break;
            }

            for(indx=st; indx<rx0.indx; indx++)
            {
                if(rx0.buf[indx] == '.')
                {
                    rx0.buf[indx+4] = 0;        // trim ext to 3 chars
                }
            }


            strcpy(sys_data.fileName, &rx0.buf[st]);
            storeSysDataVariables();    //save
            //uprintf("filename: %s", sys_data.fileName);     // DEBUG
            break;
        }
    }

    //find first space after file..., then find first alpha char
}

void cmd_get_vrsi_std(void)
{
    uprintf("%u", sys_data.data_cfg[CFG_VRSI_STD]);
}

void cmd_set_vrsi_std(unsigned int val)
{
    if((val == '1') || (val == 1))
    {
        sys_data.data_cfg[CFG_VRSI_STD] = 1;
        sys_data.data_cfg[CFG_VRSI] = 1;
    }
    else
        sys_data.data_cfg[CFG_VRSI_STD] = 0;

    save();
}

void cmd_test_vrsi_std(unsigned int num)
{
    // min num is 5
    //uprintf("Not available");
    // TODO, parse trials, for now, set to 5
    test_vrsi(num, 1, 5, 0, 500);
}

void cmd_get_vrsi(void)
{
    uprintf("%u", sys_data.data_cfg[CFG_VRSI]);
}

void cmd_set_vrsi(unsigned int val)
{
    if((val == '1') || (val == 1))
        sys_data.data_cfg[CFG_VRSI] = 1;
    else
        sys_data.data_cfg[CFG_VRSI] = 0;

    save();
}

void cmd_test_vrsi(unsigned int num)
{
    //uprintf("Not available");
    test_vrsi(num, 0, 0, 0, 500);
}

void cmd_get_vrse_std(void)
{
    uprintf("%u", sys_data.data_cfg[CFG_VRSE_STD]);
}

void cmd_set_vrse_std(unsigned int val)
{
    if((val == '1') || (val == 1))
    {
        sys_data.data_cfg[CFG_VRSE_STD] = 1;
        sys_data.data_cfg[CFG_VRSE] = 1;
    }
    else
        sys_data.data_cfg[CFG_VRSE_STD] = 0;

    save();
}

void cmd_test_vrse_std(unsigned int num)
{
    //uprintf("Not available");
    // TODO, parse trials, for now, set to 5
    test_vrse(num, 1, 5, 0, 500);
}

void cmd_get_vrse(void)
{
    uprintf("%u", sys_data.data_cfg[CFG_VRSE]);
}

void cmd_set_vrse(unsigned int val)
{
    if((val == '1') || (val == 1))
        sys_data.data_cfg[CFG_VRSE] = 1;
    else
        sys_data.data_cfg[CFG_VRSE] = 0;

    save();
}

void cmd_test_vrse(unsigned int num)
{
    test_vrse(num, 0, 0, 0, 500);

}

void cmd_get_ib(void)
{
    uprintf("%u", sys_data.data_cfg[CFG_I_SUBSTRATE]);
}

void cmd_set_ib(unsigned int val)
{
    if((val == '1') || (val == 1))
        sys_data.data_cfg[CFG_I_SUBSTRATE] = 1;
    else
        sys_data.data_cfg[CFG_I_SUBSTRATE] = 0;

    save();
}

void cmd_test_ib(unsigned int num)
{
    //uprintf("Not available");
    test_ib(num, 0, 0, 0, 500);
}

void cmd_get_ik(void)
{
    uprintf("%u", sys_data.data_cfg[CFG_I_COUNTER]);
}

void cmd_set_ik(unsigned int val)
{
    if((val == '1') || (val == 1))
        sys_data.data_cfg[CFG_I_COUNTER] = 1;
    else
        sys_data.data_cfg[CFG_I_COUNTER] = 0;

    save();
}

void cmd_test_ik(unsigned int num)
{
    //uprintf("Not available");
    //void test_ik(unsigned int num, unsigned int stdFlg, unsigned int trials, unsigned int sps, unsigned int msec)
    test_ik(num, 0, 0, 0, 500);     // defd in test.c
}


void cmd_get_vk(void)
{
    uprintf("%u", sys_data.data_cfg[CFG_V_COUNTER_ELECT]);
}

void cmd_set_vk(unsigned int val)
{
    if((val == '1') || (val == 1))
        sys_data.data_cfg[CFG_V_COUNTER_ELECT] = 1;
    else
        sys_data.data_cfg[CFG_V_COUNTER_ELECT] = 0;

    save();
}

void cmd_test_vk(unsigned int num)
{
    //uprintf("Not available");
    test_vk(num, 0, 0, 0, 500);
}

void cmd_get_vk_std(void)
{
    uprintf("%u", sys_data.data_cfg[CFG_V_COUNTER_ELECT_STD]);
}

void cmd_set_vk_std(unsigned int val)
{
    if((val == '1') || (val == 1))
    {
        sys_data.data_cfg[CFG_V_COUNTER_ELECT_STD] = 1;
        sys_data.data_cfg[CFG_V_COUNTER_ELECT_STD] = 1;
    }
    else
        sys_data.data_cfg[CFG_V_COUNTER_ELECT_STD] = 0;

    save();
}

void cmd_test_vk_std(unsigned int num)
{
    //uprintf("Not available");
    test_vk(num, 1, 5, 0, 500);

}

void cmd_get_vtherm(void)
{
    uprintf("%u", sys_data.data_cfg[CFG_V_THERMISTOR]);
}

void cmd_set_vtherm(unsigned int val)
{
    if((val == '1') || (val == 1))
        sys_data.data_cfg[CFG_V_THERMISTOR] = 1;
    else
        sys_data.data_cfg[CFG_V_THERMISTOR] = 0;

    save();
}

void cmd_test_vtherm(unsigned int num)
{
    test_vtherm(num, 0, 0, 0, 500);
}

void cmd_get_vtherm_std(void)
{
    uprintf("%u", sys_data.data_cfg[CFG_V_THERMISTOR_STD]);
}

void cmd_set_vtherm_std(unsigned int val)
{
    if((val == '1') || (val == 1))
    {
        sys_data.data_cfg[CFG_V_THERMISTOR] = 1;
        sys_data.data_cfg[CFG_V_THERMISTOR_STD] = 1;
    }
    else
        sys_data.data_cfg[CFG_V_THERMISTOR_STD] = 0;

    save();
}

void cmd_test_vtherm_std(unsigned int num)
{
    test_vtherm(num, 1, 5, 0, 500);
}


void cmd_get_tempc(void)
{
    uprintf("%u", sys_data.data_cfg[CFG_CALC_TEMP]);
}

void cmd_set_tempc(unsigned int val)
{
    if((val == '1') || (val == 1))
    {
        sys_data.data_cfg[CFG_V_THERMISTOR] = 1;
        sys_data.data_cfg[CFG_CALC_TEMP] = 1;
    }
    else
        sys_data.data_cfg[CFG_CALC_TEMP] = 0;

    save();
}

void cmd_test_tempc(unsigned int num)
{
    test_tempc(num, 0, 0, 0, 500);   // stdFlg will print vtherm and vtherm_std
}

void cmd_test_vbat(unsigned int num)
{
    //uprintf("Not available");
    display_battery_boardSensors();
}

void cmd_get_vbat(void)
{
    uprintf("%u", sys_data.data_cfg[CFG_VIN_BAT_VOLT]);
}

void cmd_set_vbat(unsigned int val)
{
    if((val == '1') || (val == 1))
        sys_data.data_cfg[CFG_VIN_BAT_VOLT] = 1;
    else
        sys_data.data_cfg[CFG_VIN_BAT_VOLT] = 0;

    save();
}

void cmd_test_biasneg(unsigned int num)
{
    //uprintf("Not available");
    test_bias_bat(num, 1, 0, 0);

}

void cmd_get_biasneg(void)
{
    uprintf("%u", sys_data.data_cfg[CFG_BIAS_BAT_NEG]);
}

void cmd_set_biasneg(unsigned int val)
{
    if((val == '1') || (val == 1))
        sys_data.data_cfg[CFG_BIAS_BAT_NEG] = 1;
    else
        sys_data.data_cfg[CFG_BIAS_BAT_NEG] = 0;

    save();
}

void cmd_test_biaspos(unsigned int num)
{
    //uprintf("Not available");
    test_bias_bat(num, 0, 1, 0);

}

void cmd_get_biaspos(void)
{
    uprintf("%u", sys_data.data_cfg[CFG_BIAS_BAT_POS]);
}

void cmd_set_biaspos(unsigned int val)
{
    if((val == '1') || (val == 1))
        sys_data.data_cfg[CFG_BIAS_BAT_POS] = 1;
    else
        sys_data.data_cfg[CFG_BIAS_BAT_POS] = 0;

    save();
}


void cmd_get_timestamp(void)
{
    uprintf("%u", sys_data.data_cfg[CFG_TIMESTAMP]);

}

void cmd_set_timestamp(unsigned int val)
{
    if((val == '1') || (val == 1))
        sys_data.data_cfg[CFG_TIMESTAMP] = 1;
    else     if((val == '2') || (val == 2))
        sys_data.data_cfg[CFG_TIMESTAMP] = 2;
    else
        sys_data.data_cfg[CFG_TIMESTAMP] = 0;

    save();
}

void cmd_test_timestamp(unsigned int num)
{
    char timeStamp[TIMESTAMPLENGTH];
    struct tm *time_struct;
    time_t current_time;
    unsigned long long posixtime_ms;

    if(sys_data.data_cfg[CFG_TIMESTAMP] == TYPE_EPOCH_MSEC)
    {
        //1648165197 - 12365360
        // = 1,635,799,837
        // 1648165439000

        current_time = ROM_HibernateRTCGet();
        posixtime_ms = (long long)current_time;     // was ROM_HibernateRTCGet();   // cast to unsigned long long ?

        posixtime_ms -= 2208963602;  //2208963732;   //(2208964102);  // hacked offset  https://www.epoch101.com/  subtract what rtc is displaying in teraterm

        posixtime_ms *= 1000LL;      // make it msec
        sprintf(timeStamp, "%13llu", posixtime_ms);
        uprintf("%s", timeStamp);
    }

    if(sys_data.data_cfg[CFG_TIMESTAMP] == TYPE_US_DATETIME)
    {
        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
        uprintf("%s", timeStamp);

    }

}

void cmd_get_cfg_sampnum(void)
{
    uprintf("%u", sys_data.data_cfg[CFG_SAMPLE_NUM]);
}

void cmd_set_cfg_sampnum(unsigned int val)
{
    if((val == '1') || (val == 1))
        sys_data.data_cfg[CFG_SAMPLE_NUM] = 1;
    else
        sys_data.data_cfg[CFG_SAMPLE_NUM] = 0;

    save();
}

void cmd_set_sampnum(unsigned int num)
{
    sys_samp.current_sample = num;
    uprintf("#%07u\r\n", sys_samp.current_sample);

    save();
}

void cmd_test_sampnum(unsigned int num)
{
    //sys_samp.current_sample
    uprintf("#%07u\r\n", sys_samp.current_sample);
}

void cmd_help_config(void)
{
    uprintf("not available\r\n");
}

void cmd_get_config(void)
{
    //print_write_config_data_fields(1,0,0);  // print, no write, no pad of //
    print_config();
}

void cmd_set_config(void)
{
#ifdef NOCODE
    0 -- Zero (Clear) all config fields
    1 -- Set all config fields
    2 -- Use Case: GLIDER,          (A,B,C,D,L,M,R,T,U)
    3 -- Use Case: mFET Default,    (A,B,C,D,E,F,G,H,I,J,K,R,T,U)
    4 -- Use Case: MpHOx Default,   (A,B,C,D,F,G,H,I,L,M,R,T,U,V,W)
    5 -- Use Case: MpHOx m2m,       (A,C,D,E,F,G,H,I,J,K,N,R,T,U)
    6 -- Use Case: nanoFET Default, (A,B,D,F,G,H,I,L,R,S,T,U)
    7 -- Use Case: MFET WireWalker, (B,G,L,R,T,U)
#endif

    if( (strncmp(&rx0.buf[7], "glider", 4) == 0)  )
    {
        config_data_fields_glider(0);
    }
    else if ( (strncmp(&rx0.buf[7], "wirewalker", 6) == 0)  )
    {
        config_data_fields_wirewalker(0);
    }
    else if ( (strncmp(&rx0.buf[7], "mfet", 4) == 0)  )
    {
        config_data_fields_mfet(0);
    }
    else if ( (strncmp(&rx0.buf[7], "mphox", 5) == 0)  )
    {
        config_data_fields_mphox(0);
    }
    else if ( (strncmp(&rx0.buf[7], "m2m mphox", 8) == 0)  )
    {
        config_data_fields_m2m_mphox(0);
    }
    else if ( (strncmp(&rx0.buf[7], "nanofet", 4) == 0)  )
    {
        config_data_fields_nanofet(0);
    }
    else if ( (strncmp(&rx0.buf[7], "all", 3) == 0) || (rx0.buf[7] == '1') )
    {
        config_data_fields_all(0);
    }
    else if ( (strncmp(&rx0.buf[7], "none", 4) == 0)  || (rx0.buf[7] == '0') )
    {
        config_data_fields_none(0);
    }
    else if ( (strncmp(&rx0.buf[7], "test", 4) == 0)  )
    {
        uprintf("not available\r\n");
    }
    else
    {
        print_NAK();
    }
}

void cmd_get_store(void)
{
    uprintf("%u", sys_data.app_cfg[APPCFG_MICROSD_ENABLE]);
    sys_data.app_cfg[APPCFG_MICROSD_ENABLE] = 1;
}


void cmd_set_store(void)
{
    sys_data.app_cfg[APPCFG_MICROSD_ENABLE] = 1;

    if(rx0.buf[6] == '1')      // store 1
        sys_data.app_cfg[APPCFG_MICROSD_ENABLE] = 1;
    else if (rx0.buf[8] == '1')      // microsd 1
        sys_data.app_cfg[APPCFG_MICROSD_ENABLE] = 1;
    else
        sys_data.app_cfg[APPCFG_MICROSD_ENABLE] = 0;

    save();
}

void cmd_filesystem(void)
{
    float fVbat;

    UARTEchoSet(true);
#if BOARD_MFET >= 2 || BOARD_MPHOX >= 1
    fVbat = read_vbat();     //  print a warning if Vin is too low, especially for ymodem transfers  Bug fix 11 Mar 2022
    if( fVbat < (sys_data.low_batt_volt + 0.005) )
    {
        uprintf("\r\n\r\nVoltage input is low (%.2fv < threshold %.2fv, avoid file operations!!!\r\n", fVbat, sys_data.low_batt_volt);
    }

    if(sys_data.app_cfg[APPCFG_MICROSD_ENABLE] == 0)   // Fix 6 Aug 2021
    {
        uprintf("\r\nMicroSD card disabled, file commands are not available\r\n");
        uprintf("   To enable, use 1-Config -> A-App Config to edit app_cfg[APPCFG_MICROSD_ENABLE]=1\r\n");
    }
    else
    {
        if(microSD_flg == 1)
        {
            viewFiles();
        }
        else
        {
            uprintf("\r\nMicroSD card not detected, file commands are not available\r\n");
        }
    }
#endif
#if BOARD_NANOFET > 0
    uprintf("\r\nMicroSD card is not available on NanoFET, file commands are not available\r\n");
#endif

    UARTEchoSet(false);
}

// pass in sample loopTime in seconds
void cmd_test_sample(unsigned int loopTime)
{

    barfSampleTime = loopTime;
    databarFlg = 1;
}

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



void print_isus_header(void)
{
#ifdef APFTODO
    int i;

    if(fptr == FNULL)
        return;

    pdcfinfo("C:", &size, &avail);
    DS1683_RdElapsedTimer( &isus_lamp_elp );
    DS1683_RdEventCounter( &isus_lamp_evt );
    hdiv = ldiv(isus_lamp_elp, 3600L);
    mdiv = ldiv(hdiv.rem, 60L);

    fprintf(fptr, "H, Datalogger Serial Num , SN:%04hu\n", sys_serial_num );
    fprintf(fptr, "H, Application      Name , %s\n", strupr(bfile) );
    fprintf(fptr, "H, App Build        Date , %s, %s\n", bdate, btime);
    tp = localtime( &sys_reset_time );
    fprintf(fptr, "H, Power Up Time   (GMT) , %02d/%02d/%02d %02d:%02d:%02d\n", tp->tm_mon+1, tp->tm_mday, tp->tm_year+1900, tp->tm_hour, tp->tm_min, tp->tm_sec);
    current_time = RTCGetTime( NULL, NULL );
    tp = localtime( &current_time );
    fprintf(fptr, "H, Current  Time   (GMT) , %02d/%02d/%02d %02d:%02d:%02d\n", tp->tm_mon+1, tp->tm_mday, tp->tm_year+1900, tp->tm_hour, tp->tm_min, tp->tm_sec);
    tp = localtime( &alarm_time );
    fprintf(fptr, "H, Alarm    Time   (GMT) , %02d/%02d/%02d %02d:%02d:%02d\n", tp->tm_mon+1, tp->tm_mday, tp->tm_year+1900, tp->tm_hour, tp->tm_min, tp->tm_sec);
    fprintf(fptr, "H, Power Active  Timeout , %hu\n", sys_apf_tmout);
    fprintf(fptr, "H, Persistor CF2-1M Info , S/N:%ld - BIOS:%d.%02d - PicoDOS:%d.%02d\n", BIOSGVT.CFxSerNum, BIOSGVT.BIOSVersion, BIOSGVT.BIOSRelease, BIOSGVT.PICOVersion, BIOSGVT.PICORelease);
    fprintf(fptr, "H, Compact FLASH    Size , %ld\n", size);
    fprintf(fptr, "H, Compact FLASH    Left , %.2f%%\n", (float)(((float)avail/(float)size)*100.0));
    fprintf(fptr, "H, Power Cycle   Counter , %lu\n", sys_por_ctr);
    fprintf(fptr, "H, System Reset  Counter , %lu\n", sys_reset_ctr);

    fprintf(fptr, "H, System Error  Counter , %lu\n", sys_error_ctr);
    fprintf(fptr, "H, Last System     Error , %d\n",  sys_last_error);
    tp = localtime( &sys_error_time );
    fprintf(fptr, "H, Last System ErrorTime , %02d/%02d/%02d %02d:%02d:%02d\n", tp->tm_mon+1, tp->tm_mday, tp->tm_year+1900, tp->tm_hour, tp->tm_min, tp->tm_sec);

    fprintf(fptr, "H, ISUS  Error   Counter , %lu\n", isus_error_ctr);
    fprintf(fptr, "H, Last ISUS       Error , %d\n", isus_last_error);
    tp = localtime( &isus_error_time );
    fprintf(fptr, "H, Last ISUS Error  Time , %02d/%02d/%02d %02d:%02d:%02d\n", tp->tm_mon+1, tp->tm_mday, tp->tm_year+1900, tp->tm_hour, tp->tm_min, tp->tm_sec);

    fprintf(fptr, "H, ISUS Sample   Counter , %lu\n", isus_sample_ctr);
    tp = localtime( &isus_sample_time );
    fprintf(fptr, "H, Last Sample Rec. Time , %02d/%02d/%02d %02d:%02d:%02d\n", tp->tm_mon+1, tp->tm_mday, tp->tm_year+1900, tp->tm_hour, tp->tm_min, tp->tm_sec);

    fprintf(fptr, "H, Fiberlite    Odometer , %02ld:%02ld:%02ld\n", hdiv.quot, mdiv.quot, mdiv.rem);
    fprintf(fptr, "H, Fiberlite      Cycles , %hu\n", isus_lamp_evt);
    fprintf(fptr, "H, Spec Intensity LampON , %hu\n", isus_ref_limit);
    fprintf(fptr, "H, Spec Integration Time , %lu\n", isus_spec_period);
    fprintf(fptr, "H, Spec Pre  scans taken , %hu\n", isus_pre_scans);
    fprintf(fptr, "H, Spec Lite scans taken , %hu\n", isus_scan_num);
    fprintf(fptr, "H, Spec Dark scans taken , %hu\n", isus_dark_num);
    if(Zcoefs <= 0)
        fprintf(fptr, "H, Zceof File    Error   , ZCoefs = %d\n", Zcoefs);
    if(Ecoefs != 256)
        fprintf(fptr, "H, Eceof File    Error   , ECoefs = %d\n", Ecoefs);
    else
        fprintf(fptr, "H, Calibration      Date , %s\n", CalDate);
    fprintf(fptr, "H, Sw Calibration   Temp , %.2lf\n", SwCalTemp);
    fprintf(fptr, "H, Wavelength Fit  Range , %.3f <-> %.3f\n", LambdaData[isus_pixel_beg], LambdaData[isus_pixel_end]);
    fprintf(fptr, "H, Pixel Fit       Range , %d <-> %d\n", isus_pixel_beg, isus_pixel_end);
    fprintf(fptr, "H, Fitted Concentrations , %d\n", isus_fit_concs);
    fprintf(fptr, "H, Baseline        Model , ");
    if(isus_bsl_model == 1)
        fprintf(fptr, "(ax + b)\n");
    if(isus_bsl_model == 2)
        fprintf(fptr, "(ax^2 + bx + c)\n");
    if(isus_bsl_model == 3)
        fprintf(fptr, "exp(ax + b)\n");
    if(isus_bsl_model == 4)
        fprintf(fptr, "exp(ax^2 + bx + c)\n");
    fprintf(fptr, "H, Br Temp  Compensation , ");
    if(isus_tcomp_mode == TRUE)
        fprintf(fptr, "ENABLED\n");
    else
        fprintf(fptr, "DISABLED\n");
    fprintf(fptr, "H, Bromide Term in Model , ");
    if(isus_salfit_mode == TRUE)
        fprintf(fptr, "will be FIT (to absorbance data)\n");
    else
        fprintf(fptr, "will be FIXED (to external CTD value)\n");

    if(Zcoefs > 0) {
        fprintf(fptr, "H, Zeiss Coefficient Vals, ");
        for(i = 0; i < 5; i++) {
            if(i != 4)
                fprintf(fptr,"%e,", ZeissCoefs[i]);
            else
                fprintf(fptr,"%e\n", ZeissCoefs[i]);
        }
    } //end Zcoefs if
#endif
}


void print_dura_header(void)
{
#ifdef APFTODO
    if(fptr == FNULL)
        return;

    pdcfinfo("C:", &size, &avail);

    fprintf(fptr, "H, Datalogger Serial Num , SN:%04hu\n", sys_serial_num );
    fprintf(fptr, "H, Application      Name , %s\n", strupr(bfile) );
    fprintf(fptr, "H, App Build        Date , %s, %s\n", bdate, btime);
    tp = localtime(&sys_reset_time);
    fprintf(fptr, "H, Power Up Time   (GMT) , %02d/%02d/%02d %02d:%02d:%02d\n", tp->tm_mon+1, tp->tm_mday, tp->tm_year+1900, tp->tm_hour, tp->tm_min, tp->tm_sec);
    current_time = RTCGetTime( NULL, NULL );
    tp = localtime(&current_time);
    fprintf(fptr, "H, Current  Time   (GMT) , %02d/%02d/%02d %02d:%02d:%02d\n", tp->tm_mon+1, tp->tm_mday, tp->tm_year+1900, tp->tm_hour, tp->tm_min, tp->tm_sec);
    tp = localtime(&alarm_time);
    fprintf(fptr, "H, Alarm    Time   (GMT) , %02d/%02d/%02d %02d:%02d:%02d\n", tp->tm_mon+1, tp->tm_mday, tp->tm_year+1900, tp->tm_hour, tp->tm_min, tp->tm_sec);
    fprintf(fptr, "H, Power Active  Timeout , %hu\n", sys_apf_tmout);
    fprintf(fptr, "H, Persistor CF2-1M Info , S/N:%ld - BIOS:%d.%02d - PicoDOS:%d.%02d\n", BIOSGVT.CFxSerNum, BIOSGVT.BIOSVersion, BIOSGVT.BIOSRelease, BIOSGVT.PICOVersion, BIOSGVT.PICORelease);
    fprintf(fptr, "H, Compact FLASH    Size , %ld\n", size);
    fprintf(fptr, "H, Compact FLASH    Left , %.2f%%\n", (float)(((float)avail/(float)size)*100.0));
    fprintf(fptr, "H, Power Cycle   Counter , %lu\n", sys_por_ctr);
    fprintf(fptr, "H, System Reset  Counter , %lu\n", sys_reset_ctr);

    fprintf(fptr, "H, System Error  Counter , %lu\n", sys_error_ctr);
    fprintf(fptr, "H, Last System     Error , %d\n",  sys_last_error);
    tp = localtime( &sys_error_time );
    fprintf(fptr, "H, Last System ErrorTime , %02d/%02d/%02d %02d:%02d:%02d\n", tp->tm_mon+1, tp->tm_mday, tp->tm_year+1900, tp->tm_hour, tp->tm_min, tp->tm_sec);

    fprintf(fptr, "H, DURA  Error   Counter , %lu\n", dura_error_ctr);
    fprintf(fptr, "H, Last DURA       Error , %d\n", dura_last_error);
    tp = localtime( &dura_error_time );
    fprintf(fptr, "H, Last DURA Error  Time , %02d/%02d/%02d %02d:%02d:%02d\n", tp->tm_mon+1, tp->tm_mday, tp->tm_year+1900, tp->tm_hour, tp->tm_min, tp->tm_sec);

    fprintf(fptr, "H, DURA Sample   Counter , %lu\n", dura_sample_ctr);
    tp = localtime( &dura_sample_time );
    fprintf(fptr, "H, Last Sample Rec. Time , %02d/%02d/%02d %02d:%02d:%02d\n", tp->tm_mon+1, tp->tm_mday, tp->tm_year+1900, tp->tm_hour, tp->tm_min, tp->tm_sec);
    fprintf(fptr, "H, AtoD Reads per Sample , %hu\n", dura_atod_readings);
    fprintf(fptr, "H, AtoD Reading    Delay , %hu\n", dura_atod_delay);
    fprintf(fptr, "H, Samps per AtoD  Recal , %lu\n", dura_samps_per_cal);
#endif
}



//int TakeIsusPseudoSample(char *dbuf, float *atime, ulong CTD_Time, float CTD_Temp, float CTD_Salinity, float CTD_Depth)

int TakeIsusPseudoSample(char *dbuf, float *atime, uint32_t CTD_Time, float CTD_Temp, float CTD_Salinity, float CTD_Depth)
{
#ifdef APFTODO
    char   *tbuf;
    char   *ebuf;
    char   *tmbuf;
    ushort crc;
    int i;
    double ref_ch_mean, ref_ch_sd, dc_mean, dc_sd, sw_dc_mean;
    double isus_no3, isus_sal, isus_hs, isus_err;
    ldiv_t sdiv;
    RTCTimer ElpTm;

    *atime = -1.0;

    RTCElapsedTimerSetup( &ElpTm );

    HIH6130_ReadTempHumidity( &sysTemperature, &sysHumidity );

    dat_file = OpenApfLogFile( ISUS_DATA_FILE );
    if( dat_file != FNULL ) {
        if( isus_reset_flag == TRUE ) {
            OutputIsusHeader(dat_file);
            isus_reset_flag = FALSE;
        }
    }

    if( SpecPwrOn( &SpecPort ) != TRUE ) {
        if( dat_file != FNULL )
            fclose(dat_file);
        return( ERROR );
    }

    DelayMilliSecs( 500 );

    isus_sample_time = RTCGetTime( NULL, NULL );
    tp = localtime(&isus_sample_time);
    DelayMilliSecs( isus_spec_period );

    dc_mean   = 435.23;
    dc_sd     = 4.31;
    if( dat_file != FNULL ) {
        fprintf(dat_file,"D,%02d/%02d/%02d %02d:%02d:%02d,%.2f,%.2f,%.2f,", tp->tm_mon+1, tp->tm_mday, tp->tm_year+1900, tp->tm_hour, tp->tm_min, tp->tm_sec, sysTemperature, dc_mean, dc_sd);
        for(i = 1; i <= 256; i++) {
            if(i != 256) {
                if( (Zcoefs > 0) || (Ecoefs == 256) )
                    fprintf(dat_file, "%.1f,", LambdaData[i]);
                else
                    fprintf(dat_file, "%05d,", i);
            }
            else{
                if( (Zcoefs > 0) || (Ecoefs == 256) )
                    fprintf(dat_file, "%.1f\n", LambdaData[i]);
                else
                    fprintf(dat_file, "%05d\n", i);
            }
        } //end i loop
    } //end FNULL if


    LampPwrOn();

    isus_sample_time = RTCGetTime( NULL, NULL );
    tp = localtime(&isus_sample_time);
    DelayMilliSecs( isus_spec_period );

    ref_ch_mean = 1022.16;
    ref_ch_sd   = 1.67;
    if( dat_file != FNULL ) {
        fprintf(dat_file,"S,%02d/%02d/%02d %02d:%02d:%02d,%.2f,%.2f,%.2f,", tp->tm_mon+1, tp->tm_mday, tp->tm_year+1900, tp->tm_hour, tp->tm_min, tp->tm_sec,sysTemperature, ref_ch_mean, ref_ch_sd);
        for(i = 1; i <= 256; i++) {
            if(i != 256) {
                if( (Zcoefs > 0) || (Ecoefs == 256) )
                    fprintf(dat_file, "%.1f,", LambdaData[i]);
                else
                    fprintf(dat_file, "%05d,", i);
            }
            else{
                if( (Zcoefs > 0) || (Ecoefs == 256) )
                    fprintf(dat_file, "%.1f\n", LambdaData[i]);
                else
                    fprintf(dat_file, "%05d\n", i);
            }
        } //end i loop

        fclose(dat_file);
    } //end FNULL if

    INA219_ReadVoltageCurrent( &sysVoltage, &sysCurrent );

    LampPwrOff();
    SpecPwrOff( SpecPort );

    isus_sal       = 32.57;
    isus_no3       = 12.35;
    isus_hs        = -1.0;
    isus_err       = 0.0001245;

    if( CTD_Time != 0 ) {           //time will be zero if CTD values are not passed
        if( (isus_salfit_mode == FIX) && (CTD_Time != 0) )
            isus_sal=CTD_Salinity;
    }

    if( (tbuf = calloc((size_t)DATBUFSIZE, sizeof(char))) == NULL ) {
        if( (ebuf = calloc((size_t)ERRBUFSIZE, sizeof(char))) == NULL )
            return( ERROR );
        sprintf(ebuf, "CAN'T allocate TakeSample() tbuf memory");
        LogErrorMsg(ebuf, (int)MALLOC_FAILURE, sys_message_enable);
        free(ebuf);
        return( ERROR );
    }

    sprintf(tbuf, "A,%02d/%02d/%02d %02d:%02d:%02d,%lu,%.2f,%.4f,%.4f,%lu,%lu,%lu,%lu,%.2f,%.2f,%.3f,%.3e,%.2lf,%.2lf,%.2lf,%.2lf,%.2lf,%.2lf,%.3le,%d,%d,",
            tp->tm_mon+1, tp->tm_mday, tp->tm_year+1900, tp->tm_hour, tp->tm_min, tp->tm_sec,
            CTD_Time, CTD_Depth, CTD_Temp, CTD_Salinity,
            isus_sample_ctr, sys_por_ctr, isus_error_ctr, sys_error_ctr,
            sysTemperature, sysHumidity, sysVoltage, sysCurrent,
            ref_ch_mean, ref_ch_sd, dc_mean, dc_sd,
            isus_sal, isus_no3, isus_err, isus_datpixel_beg, isus_datpixel_end);

    for( i = isus_datpixel_beg; i <= isus_datpixel_end; i++ ) {
        sprintf(tbuf+strlen(tbuf), "%04X", i);
    }

    sw_dc_mean = 411.35;
    sprintf(tbuf+strlen(tbuf), ",%.1lf", sw_dc_mean);

    crc = fCrc16Bit((const unsigned char *)tbuf);

    sprintf(dbuf,"0x%04X,%s", crc, tbuf);

    free(tbuf);

    ++isus_sample_ctr;
    DS3234_WrSRAM(ISUS_SAMPLECTR_PTR, sizeof(ulong), (ulong*)&isus_sample_ctr);
    DS3234_WrSRAM(ISUS_LASTSAMPTIME_PTR, sizeof(ulong), (ulong*)&isus_sample_time);

    sdiv = ldiv(RTCElapsedTime( &ElpTm ), 1000000L);
    if( (tmbuf = calloc((size_t)40, sizeof(char))) != NULL ) {
        sprintf(tmbuf, "%ld.%.6ld", sdiv.quot, sdiv.rem);
        *atime = atof(tmbuf);
        free(tmbuf);
    }
#endif
    return( TRUE );       // OK

}
