/************************************************************************/
/* Copyright 2015-2016 MBARI                                            */
/************************************************************************/
/* Summary  : Oasis5 Debug menu routine                                 */
/* Filename : o5debug.c                                                 */
/* Author   : Robert Herlien (rah)                                      */
/* Project  : Oasis5                                                    */
/* Revision: 1.0                                                        */
/* Created  : 02/11/2016 from mvdebug.c (FOCE)                          */
/*                                                                          */
/* MBARI provides this documentation and code "as is", with no warranty,    */
/* express or implied, of its quality or consistency. It is provided without*/
/* support and without obligation on the part of the Monterey Bay Aquarium  */
/* Research Institute to assist in its use, correction, modification, or    */
/* enhancement. This information should not be published or distributed to  */
/* third parties without specific written permission from MBARI.            */
/*                                                                          */
/************************************************************************/
/* Modification History:                                                */
/* 11feb2016 rah - created from mvdebug.c FOCE project                  */
/************************************************************************/

#include <mbariTypes.h>
#include <oasis.h>
#include <o5debug.h>
#include <serial.h>
#include <debug.h>
#include <dig_io.h>
#include <adc.h>
#include <rtc.h>
#include <timer.h>
#include <picConfig.h>
#include <olist.h>
#include <fileTest.h>
#include <syslog.h>
#include <istdio.h>

#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <ctype.h>

#include <FreeRTOS.h>
#include <task.h>


typedef struct                  /****************************************/
{                               /* Struct to hold commands              */
    char  *name;                /* Command name                         */
    int   (*func)();            /* Function to execute                  */
    int   nparms;               /* Number of parms (0 or 1 only for now)*/
    UINT  parmMin;              /* Max value of parm (0 to parmMax)     */
    UINT  parmMax;              /* Max value of parm (0 to parmMax)     */
} CommandStruct;                /****************************************/


/********************************/
/*      Forward Declarations    */
/********************************/

int     printDebugMenu(int port);
CommandStruct *getCommand(int port, UINT *parmp);
int     getline(int port, char *buf, int buflen);
int     pwrRelayOn(int port, UINT relay);
int     pwrRelayOff(int port, UINT relay);
int     enableSerial(int port, UINT serPort);
int     disableSerial(int port, UINT serPort);
int     writeSerial(int port, UINT serPort);
int     writeTestSerial(int port, UINT serPort);
int     readSerial(int port, UINT serPort);
int     loopbackSerial(int port, UINT serPort);
int     analogRead(int port, UINT analogPort);
int     analogAllRead(int port);
int     analogParms(int port);
int     analogNumAvg(int port, UINT numAvg);
int     analogAvgMs(int port, UINT avgMs);
int     analogStartup(int port, UINT startupCentisec);
int     pwrStatus(int port);
int     o5reset(int port);
int     testCmd(int port, UINT parm);
int     envPwr(int port, UINT parm);
int     gfLowCmd(int port);
int     gfHighCmd(int port);
int     gfOffCmd(int port);
int     doSleep(int port, UINT secs);
int     readRTC(int port);
int     getTime(int port);
int     setTime(int port);
int     setSysTime(int port);
int     getTick(int port);
int     setXon(int port, UINT onoff);
int     readRTCReg(int port, UINT reg);
int     writeRTCReg(int port, UINT reg);
int     checkUsTmr(int port, UINT parm);
int     checkMsTmr(int port, UINT parm);
#ifdef TEST_PRINTF
extern int testPrintf(void);
#endif


/********************************/
/*      External Data			*/
/********************************/

Extern LstHead	drv_list;
Extern MBool	diagnosticMode;
Extern Parm_t	adcStartupMs;


/********************************/
/*      Module Local Data       */
/********************************/

static char     inputBuf[256];
static char     msgBuf[256];

static UINT     adcNumAvg = 10;
static UINT     adcAvgMs = 10;

static CommandStruct cmdTbl[] = {
    {"f", fileTest, 0, 0, 0},
    {"on", pwrRelayOn, 1, 1, 4},
    {"off", pwrRelayOff, 1, 1, 4},
    {"en", enableSerial, 1, 1, 4},
    {"dis", disableSerial, 1, 1, 4},
    {"wr", writeSerial, 1, 1, 4},
    {"wt", writeTestSerial, 1, 1, 4},
    {"rd", readSerial, 1, 1, 4},
    {"lb", loopbackSerial, 1, 1, 4},
    {"aa", analogAllRead, 0, 0, 0},
    {"ar", analogRead, 1, ADC_CHAN_MIN, ADC_CHAN_MAX},
    {"an", analogNumAvg, 1, 1, 99},
    {"am", analogAvgMs, 1, 1, 99},
    {"as", analogStartup, 1, 1, 99},
    {"ap", analogParms, 0, 0, 0},
    {"gfl", gfLowCmd, 0, 0, 0}, 
    {"gfh", gfHighCmd, 0, 0, 0}, 
    {"gfoff", gfOffCmd, 0, 0, 0}, 
    {"p", pwrStatus, 0, 0, 0}, 
    {"ep", envPwr, 1, 0, 1}, 
    {"slp", doSleep, 1, 1, 99}, 
    {"res", o5reset, 0, 0, 0}, 
    {"rr", readRTCReg, 1, 0, 19}, 
    {"rw", writeRTCReg, 1, 0, 19}, 
    {"rtc", readRTC, 0, 0, 0}, 
    {"time", getTime, 0, 0, 0}, 
    {"stime", setTime, 0, 0, 0}, 
    {"sstime", setSysTime, 0, 0, 0}, 
    {"us", checkUsTmr, 1, 1, 99}, 
    {"ms", checkMsTmr, 1, 1, 99}, 
    {"tick", getTick, 0, 0, 0}, 
    {"xon", setXon, 1, 0, 9},
#ifdef TEST_PRINTF
    {"tp", testPrintf, 0, 0, 0},
#endif
    {"h", printDebugMenu, 0, 0, 0},
    {"?", printDebugMenu, 0, 0, 0},
    {"q", o5reset, 0, 0, 0},
    {"x", o5reset, 0, 0, 0},
    {"test", testCmd, 1, 1, 250}
};


/************************************************************************/
/* Function	   : diagSetup												*/
/* Purpose	   : Setup to run o5Diagnostic								*/
/* Inputs	   : pmask													*/
/* Outputs	   : OK or ERROR											*/
/************************************************************************/
CmdRtn diagSetup(ParmMask_t pmask)
{
	Tid			ourTd, td;
	SerDesc		*sdp;
	Reg Driver	*dp, *dp1;
	char		inbuf[32];

	if (((ourTd = xTaskGetCurrentTaskHandle()) == NULLTID) ||
		((sdp = pvTaskGetThreadLocalStoragePointer(NULL, ConsoleP)) == NULL) ||
		(sdp->serport != SER_CONSOLE))
	{
		xputs("You can only invoke the diagnostics from the main user console\n");
		return(ERROR);
	}

	if (pmask != 0xffff)
	{
		xputs("Running the O5 diagnostics will kill all driver tasks,\n");
		xputs("	 stop all data logging, and can erase all log data\n\n");
		xputs("Are you VERY, VERY sure you want to do this?\n");
		xputs("If you really want to do it, type \"XYZZY\"\n"  );
		xgets_tmout(inbuf, sizeof(inbuf), 30);
		if (cmp_ulc(inbuf, "xyzzy") == NULL)
			return(ERROR);
	}

	wdtDisable();						/* Turn off WDT					*/
	sysLog("Diagnotic mode");

	/* Suspend the root (oasis supervisor) task to keep from scheduling anything*/
	if (pmask != 0xffff)
		vTaskSuspend(getOasisTask());
	
	/* Kill all driver tasks except for ourself (presumeably UserIF)		*/
	lockList(&drv_list);
	for (dp = (Driver *)(drv_list.lst_head); dp != DRV_NULL; dp = dp1)
	{
		dp1 = dp->drv_next;
		if (dp->drv_td != ourTd)
			drvdel(1, dp->drv_name);
	}
	unlockList(&drv_list);
	
	/* Stop all scripts					*/
	stopScript(1, "all");

	/* Now should have only the IDLE, Kernel Timer, and this task running*/

	logFlush();							/* Flush log file				*/
	digBlinkyOff();
	digPwrVecSet(1);					/* Turn off all power except ourself*/
	diagnosticMode = TRUE;				/* Show we're in diagnostic mode*/

	return(OK);

} /* diagSetup() */


/************************************************************************/
/* Function	   : o5Diagnostic											*/
/* Purpose	   : Hardware diagnostic routines for OASIS5				*/
/* Inputs	   : pmask = 0xffff if invoked from OASIS.CFG (i.e., before */
/*				 drivers are spawned) or due to error.	pmask = 0-7 otherwise*/
/* Outputs	   : ERROR, or never returns								*/
/* Comments	   : If it passes initial checks, this function won't return*/
/*				 except by doing a BIOSReset()							*/
/************************************************************************/
CmdRtn o5Diagnostic(ParmMask_t pmask)
{
	Port_t				port;
    UINT                cmdParm;
    CommandStruct       *cmdp;

	if (diagSetup(pmask) != OK)
		return(ERROR);

   	port = SER_CONSOLE;
    printDebugMenu(port);

    while (TRUE)
    {
        cmdParm = 0;
        if ((cmdp = getCommand(port, &cmdParm)) != NULL)
        {
            iprintf("\r\n");
            (*cmdp->func)(port, cmdParm);
        }
    }

} /* o5Diagnostic() */


/************************************************************************/
/* Function    : printDebugMenu                                         */
/* Purpose     : Print the menu                                         */
/* Inputs      : Serial port                                            */
/* Outputs     : None                                                   */
/************************************************************************/
int printDebugMenu(int port)
{
    iprintf("\r\nDEBUG MENU - Type a command:\r\n\n");
    iprintf("h for this help message\r\n");
    iprintf("f to go to file sub-menu\r\n\n");

    iprintf("on[1-4] to turn on a power/serial relay\r\n");
    iprintf("off[1-4] to turn off a power/serial relay\r\n");
    iprintf("p to read power vector\r\n");
    iprintf("en[1-4] to enable serial driver\r\n");
    iprintf("dis[1-4] to disable serial driver\r\n");
    iprintf("wr[1-4] to write to a serial port\r\n");
    iprintf("wt[1-4] to write test strings to a serial port\r\n");
    iprintf("rd[1-4] to read from a serial port\r\n");
    iprintf("lb[1-4] to loopback test a serial port\r\n");

    iprintf("ar[0-4] to read an analog port\r\n");
    iprintf("aa to read all analog ports\r\n");
    iprintf("ap to read analog parameters\r\n");
    iprintf("an[1-99] to set analog numAvg (number samples to average)\r\n");
    iprintf("am[1-99] to set analog avgMs (ms between samples)\r\n");
    iprintf("as[1-99] to set analog startup time (.01 sec)\r\n");
    iprintf("gfl to set GF_LOW bit\r\n");
    iprintf("gfh to set GF_HIGH bit\r\n");
    iprintf("gfoff to clear GF_xxx bits\r\n");
    iprintf("ep[0-1] to turn off/on Env power\r\n");
    iprintf("slp[1-99] to sleep for number of seconds\r\n");
    iprintf("res to reset the CPU\r\n");
    iprintf("rtc to read date/time directly from the RTC\r\n");
    iprintf("time to read system time/date\r\n");
    iprintf("stime to set time/date into RTC\r\n");
    iprintf("sstime to set system time from RTC\r\n");
    iprintf("rr to read one RTC register\r\n");
    iprintf("rw to write one RTC register\r\n");
#if 0
    iprintf("d[0-9] to set debug output level\r\n");
#endif

    return(OK);

} /* printDebugMenu() */


/********************************************************/
/*  Support routines for getCommand()                   */
/********************************************************/
static int getDec(char *s, UINT *num)
{
    UINT  val;
    int   rtn;

    rtn = val = 0;

    while (isdigit(*s))
    {
        val *= 10;
        val += (*s - '0');
        rtn = 1;
        s++;
    }

    if (rtn)
        *num = val;
    return(rtn);
}

/* findCommand()    */
static CommandStruct  *findCommand(UINT *parmp)
{
    int         i, nameSize, rtn;
    UINT        parm;
    CommandStruct *csp;

    for (i = 0, csp = cmdTbl; i < NumberOf(cmdTbl); i++, csp++)
    {
        nameSize = strlen(csp->name);

        if (strncasecmp(inputBuf, csp->name, nameSize) == 0)
        {
            if (csp->nparms == 0)
                return(csp);

            if (((rtn = getDec(&inputBuf[nameSize], &parm)) >= 1) && (parmp != NULL))
                *parmp = parm;
            
            return(csp);
        }
    }
    return(NULL);
}

/* checkParm()      */
static CommandStruct  *checkParm(int port, CommandStruct *csp, UINT *parmp)
{
    if (csp->nparms == 0)
        return(csp);
    if (parmp == NULL)
        return(NULL);
    if ((*parmp >= csp->parmMin) && (*parmp <= csp->parmMax))
        return(csp);

    iprintf("\r\nBad parameter: %u\r\n", *parmp);
    return(NULL);
}

/* decDigits()      */
static UINT decDigits(UINT n)
{
    UINT digits=1;

    while (n >= 10)
    {
        digits++;
        n /= 10;
    }

    return(digits);
}


/************************************************************************/
/* Function    : getCommand                                             */
/* Purpose     : Get a command                                          */
/* Inputs      : Serial port, ptr to place to put parm                  */
/* Outputs     : Ptr to command to execute                              */
/************************************************************************/
CommandStruct  *getCommand(int port, UINT *parmp)
{
    int         nchars, nameSize, digits;
    char        *p, c;
    CommandStruct *csp;

    iprintf("\r\nEnter a command:  ");
    memset(inputBuf, 0, sizeof(inputBuf));
    nchars = 0;
    p = inputBuf;

    while( nchars < sizeof(inputBuf) - 1 )
        if ((c = ser_getc(port)) != ERROR)
        {
            ser_putc(port, c);

			*p = c;
            if ((c == '\n') || (c == '\r'))
            {
                *p = '\0';
                if ((csp = findCommand(parmp)) == NULL)
                    return(NULL);
                return(checkParm(port, csp, parmp));
            }

            nchars++;
            p++;
            *p = '\0';

            if ((csp = findCommand(parmp)) != NULL)
            {
                if (csp->nparms == 0)
                    return(csp);

                nameSize = strlen(csp->name);
                digits = decDigits(csp->parmMax);

                if (nchars >= nameSize + digits)
                    return(checkParm(port, csp, parmp));
                
                if ((csp->parmMax < 20) && (nchars >= nameSize+1) && (*parmp >= 2))
                    return(checkParm(port, csp, parmp));
            }
        }
        else
			task_delay(10);
	
    return(NULL);
}

/****************************************/
/* Helper functions                     */
/****************************************/

/************************************************************************/
/* Function    : getline                                                */
/* Purpose     : Get one line of user input                             */
/* Inputs      : Serial port number, buffer pointer, buf length         */
/* Outputs     : Length of returned line                                */
/************************************************************************/
int getline(int port, char *buf, int buflen)
{
    int         len, b;

    for (len = 0; len < buflen-1; )
    {
        if ((b = ser_getc(port)) != ERROR)
        {
            ser_putc(port, (Byte)b);
            buf[len++] = (Byte)b;

            if (b == '\r')
            {
                ser_putc(0, (Byte)'\n');
                buf[len] = '\0';
                return(len);
            }
        }
        else
			task_delay(10);
    }

    buf[buflen] = '\0';
    return(buflen);
}


/********************************************************/
/* Functions to implement menu commands                 */
/********************************************************/

/************************************************************************/
/* Function    : o5reset												*/
/* Purpose     : Reset the CPU											*/
/* Inputs      : Serial port in use										*/
/* Outputs     : OK, but should never get there							*/
/************************************************************************/
int o5reset(int port)
{
	sysLog("Reset from diagnostic mode");
	serWaitTxComplete(port);
	picSoftReset();
    return(OK);
}

/************************************************************************/
/* Function    : pwrRelayOn                                             */
/* Purpose     : Command function to turn on a FOCE power relay         */
/* Inputs      : Serial port, Relay Number                              */
/* Outputs     : Return code                                            */
/************************************************************************/
int pwrRelayOn(int port, UINT relay)
{
    iprintf("Turning on relay %u\r\n", relay);
    digPwrOn(relay);
    return(OK);
}


/************************************************************************/
/* Function    : pwrRelayOff                                            */
/* Purpose     : Command function to turn off a FOCE power relay        */
/* Inputs      : Serial port, Relay Number                              */
/* Outputs     : Return code                                            */
/************************************************************************/
int pwrRelayOff(int port, UINT relay)
{
    iprintf("Turning off relay %u\r\n", relay);
    digPwrOff(relay);
    return(OK);
}


/************************************************************************/
/* Function    : enableSerial                                           */
/* Purpose     : Command function to enable a serial port               */
/* Inputs      : User serial port, serial port to enable                */
/* Outputs     : Return code                                            */
/************************************************************************/
int enableSerial(int port, UINT serPort)
{
    iprintf("Enabling serial port %u\r\n", serPort);
    digSerEnable(serPort);
    return(OK);
}


/************************************************************************/
/* Function    : disableSerial                                          */
/* Purpose     : Command function to disable a serial port              */
/* Inputs      : User serial port, serial port to disable               */
/* Outputs     : Return code                                            */
/************************************************************************/
int disableSerial(int port, UINT serPort)
{
    iprintf("Disabling serial port %u\r\n", serPort);
    digSerDisable(serPort);
    return(OK);
}


/************************************************************************/
/* Function    : writeSerial                                            */
/* Purpose     : Command function to write to a serial port             */
/* Inputs      : User serial port, serial port to write to              */
/* Outputs     : Return code                                            */
/************************************************************************/
int     writeSerial(int port, UINT serPort)
{
    unsigned char       b;

    iprintf("Writing to serial port %d\r\n^D to exit\r\n", serPort);

    while(TRUE)
    {
        if ((b = ser_getc(port)) != ERROR)
        {
            if (b == 0x4)
                return(OK);
            while (!ser_putc(serPort, b))
				task_delay(10);
        }
    }

    return(OK);
}


/************************************************************************/
/* Function    : writeTestSerial                                        */
/* Purpose     : Command function to write test strings to a serial port*/
/* Inputs      : User serial port, serial port to write to              */
/* Outputs     : Return code                                            */
/************************************************************************/
int     writeTestSerial(int port, UINT serPort)
{
    int         i;

    iprintf("Writing 10 test messages to serial port %d\r\n", serPort);

    for (i = 0; i < 10; i++)
    {
        iprintf("This is test message %d for serial port %d\r\n",
                i, serPort);
    }

    return(OK);
}


/************************************************************************/
/* Function    : readSerial                                             */
/* Purpose     : Command function to read from a serial port            */
/* Inputs      : User serial port, serial port to read from             */
/* Outputs     : Return code                                            */
/************************************************************************/
int     readSerial(int port, UINT serPort)
{
    unsigned char       b;

    iprintf("Reading from serial port %d\r\nType ^D on port %d to exit\r\n",
            serPort, serPort);

    while(TRUE)
    {
        if ((b = ser_getc(serPort)) != ERROR)
        {
            if (b == 0x4)
                return(OK);
            while (!ser_putc(port, b))
				task_delay(10);
        }
    }

    return(OK);
}


/************************************************************************/
/* Function    : loopbackSerial                                         */
/* Purpose     : Command function to perform loopback test on serial port*/
/* Inputs      : User serial port, serial port to read from             */
/* Outputs     : Return code                                            */
/************************************************************************/
int loopbackSerial(int port, UINT serPort)
{
    unsigned char       b;

    iprintf("Loopback test for serial port %d\r\nType ^D on port %d to exit\r\n",
            serPort, serPort);

    while(TRUE)
    {
        if ((b = ser_getc(serPort)) != ERROR)
        {
            if (b == 0x4)
                return(OK);
            while (!ser_putc(serPort, b))
				task_delay(10);
        }
    }

    return(OK);
}


/************************************************************************/
/* Function    : analogRead                                             */
/* Purpose     : Command function to read analog channel                */
/* Inputs      : Serial port, analog channel number                     */
/* Outputs     : Return code                                            */
/************************************************************************/
int     analogRead(int port, UINT chan)
{
    UINT16      i;
    UINT32      accum;

    adcSetupSingle(chan + ADC_CHAN_OFFSET);
	task_delay(adcStartupMs);
    accum = 0;

    for (i = 0; i < adcNumAvg; i++)
    {
        accum += adcConvertSingle();
		task_delay(adcAvgMs);
    }

    adcStop();

    printAnalogChan(chan, (Nat16)((64*accum + (adcNumAvg/2))/adcNumAvg));

    return(OK);
}

/************************************************************************/
/* Function    : analogAllRead                                          */
/* Purpose     : Command function to read all 5 analog channels         */
/* Inputs      : Serial port                                            */
/* Outputs     : Return code                                            */
/************************************************************************/
int     analogAllRead(int port)
{
    UINT        i, j;
    UINT32      accum[ADC_CHANS];

    adcSetupMult(ADC_CHAN_MIN + ADC_CHAN_OFFSET, ADC_CHANS);
	task_delay(adcStartupMs);
    memset(accum, 0, sizeof(accum));

    for (i = 0; i < adcNumAvg; i++)
    {
        adcConvertMult();
        for (j = 0; j < ADC_CHANS; j++)
            accum[j] += adcGetResult(j);
		task_delay(adcAvgMs);
    }

    adcStop();

    for (j = 0; j < ADC_CHANS; j++)
        printAnalogChan(j + ADC_CHAN_MIN, 
                        (UINT16)((64*accum[j] + (adcNumAvg/2))/adcNumAvg));
    
    return(OK);
}


/************************************************************************/
/* Function    : analogNumAvg                                           */
/* Purpose     : Command function to set numAvg                         */
/* Inputs      : MVConvHandle, parm                                     */
/* Outputs     : OK                                                     */
/************************************************************************/
int     analogNumAvg(int port, UINT numAvg)
{
    adcNumAvg = numAvg;
    iprintf("Set numAvg to %u\r\n", numAvg);

    return(OK);
}

/************************************************************************/
/* Function    : analogAvgMs                                            */
/* Purpose     : Command function to set avgMs                          */
/* Inputs      : MVConvHandle, parm                                     */
/* Outputs     : OK                                                     */
/************************************************************************/
int     analogAvgMs(int port, UINT avgMs)
{
    adcAvgMs = avgMs;
    iprintf("Set avgMs to %u\r\n", avgMs);

    return(OK);
}

/************************************************************************/
/* Function    : analogStartup                                          */
/* Purpose     : Command function to set ADC startup time, in .01s      */
/* Inputs      : MVConvHandle, parm                                     */
/* Outputs     : OK                                                     */
/************************************************************************/
int  analogStartup(int port, UINT startupCentisec)
{
    adcStartupMs = 10 * startupCentisec;
    iprintf(msgBuf, "Set ADC startup time to %u ms\r\n", adcStartupMs);

    return(OK);
}

/************************************************************************/
/* Function    : analogParms                                            */
/* Purpose     : Command function to print analog parms                 */
/* Inputs      : Serial port                                            */
/* Outputs     : Return code                                            */
/************************************************************************/
int     analogParms(int port)
{
    iprintf("numAvg = %u, avgMs = %u, startupMs = %u\r\n",
            adcNumAvg, adcAvgMs, adcStartupMs);

    return(OK);
}

/************************************************************************/
/* Function    : pwrStatus                                              */
/* Purpose     : Command function to get power status vector            */
/* Inputs      : Serial port                                            */
/* Outputs     : OK                                                     */
/************************************************************************/
int     pwrStatus(int port)
{
    iprintf("Power Vector = 0x%x    Power On Bit = %u\r\n",
			digPwrVecGet(), digPwrOnSts() ? 1 : 0);

    return(OK);
}


/************************************************************************/
/* Function    : envPwr                                                 */
/* Purpose     : Command function to turn on/off env power              */
/* Inputs      : Serial port, parm                                      */
/* Outputs     : OK                                                     */
/************************************************************************/
int     envPwr(int port, UINT parm)
{
    if (parm)
        digEnvEnable();
    else
        digEnvDisable();

    iprintf("Turning EnvEnable %s \r\n", parm ? "ON" : "OFF");

    return(OK);
}

/************************************************************************/
/* Function    : gfLowCmd                                               */
/* Purpose     : Command function to set GF ckt to measure LOW side     */
/* Inputs      : Serial port                                            */
/* Outputs     : OK                                                     */
/************************************************************************/
int     gfLowCmd(int port)
{
    digGFLowOn();
    digGFHighOff();
    iprintf("Setting GF circuit to measure LOW side\r\n");
    return(OK);
}

/************************************************************************/
/* Function    : gfHighCmd                                               */
/* Purpose     : Command function to set GF ckt to measure HIGH side    */
/* Inputs      : Serial port                                            */
/* Outputs     : OK                                                     */
/************************************************************************/
int     gfHighCmd(int port)
{
    digGFLowOff();
    digGFHighOn();
    iprintf("Setting GF circuit to measure HIGH side\r\n");
    return(OK);
}

/************************************************************************/
/* Function    : gfOffCmd                                               */
/* Purpose     : Command function to turn off GF ckt                    */
/* Inputs      : Serial port                                            */
/* Outputs     : OK                                                     */
/************************************************************************/
int     gfOffCmd(int port)
{
    digGFLowOff();
    digGFHighOff();
    iprintf("Turning off GF circuit\r\n");
    return(OK);
}


/************************************************************************/
/* Function    : doSleep                                                */
/* Purpose     : Command function to go to low-power sleep mode         */
/* Inputs      : Serial port, Seconds to sleep                          */
/* Outputs     : OK                                                     */
/************************************************************************/
int doSleep(int port, UINT secs)
{
    iprintf("Going to sleep for %u seconds\r\n", secs);
    serWaitTxComplete(port);
    digTx0Dis();
    digTx1Dis();
    digTx2Dis();
    digTx3Dis();
    digTx4Dis();

    tmrSleep(secs);
    digTx0En();

    return(OK);
}


/************************************************************************/
/* Function    : readRTC                                                */
/* Purpose     : Command function to read RTC registers                 */
/* Inputs      : Serial port                                            */
/* Outputs     : OK                                                     */
/************************************************************************/
int     readRTC(int port)
{
    int         i, rtn;
    Byte        regs[16];

    if ((rtn = rtcReadMultRegs(RTC_SEC, 16, regs)) != SUCCESS)
    {
        iprintf("Error reading RTC regs, errno = %d\r\n", rtn);
    }

    for (i = 0; i < 16; i++)
    {
        iprintf("%02x ", (UINT)(regs[i] & 0xff));
    }

    iprintf("\r\n\n%02d:%02d:%02d  %04u/%02d/%02d\r\n",
            (int)fromBCD((UINT16)regs[RTC_HOUR]), 
            (int)fromBCD((UINT16)regs[RTC_MIN]), 
            (int)fromBCD((UINT16)regs[RTC_SEC]), 
            (int)fromBCD((UINT16)regs[RTC_YEAR]) + 2000, 
            (int)fromBCD((UINT16)(regs[RTC_MON] & 0x1f)),
            (int)fromBCD((UINT16)regs[RTC_MDAY]));


    iprintf("rtcTime() returns %u\r\n", rtcTime(NULL));
	clkPrintTime(NULL);

    return(OK);
}

/************************************************************************/
/* Function    : getTime                                                */
/* Purpose     : Command function to get system time/date               */
/* Inputs      : Serial port                                            */
/* Outputs     : OK                                                     */
/************************************************************************/
int     getTime(int port)
{
    time_t      now;
    UINT16      nowMs;

    clkGetTime(&now, &nowMs);
    clkPrintTime(&now);
    iprintf(".%03u\r\n", nowMs);

    iprintf("rtcTime() returns %u\r\n", rtcTime(NULL));
}


/************************************************************************/
/* Function    : getTick                                                */
/* Purpose     : Command function to get tick count                     */
/* Inputs      : Serial port                                            */
/* Outputs     : OK                                                     */
/************************************************************************/
int     getTick(int port)
{
    iprintf("Tick count = %ld\r\n", tmrGetTicks());
}


/************************************************************************/
/* Function    : setTime                                                */
/* Purpose     : Command function to set time/date into RTC             */
/* Inputs      : Serial port                                            */
/* Outputs     : OK                                                     */
/************************************************************************/
int     setTime(int port)
{
    UINT        n, rtn, year, mon, day, hr, min, sec;
    Byte        regs[8];

    iprintf("Enter new time/date as either:\r\n");
    iprintf("\tyyyy/mm/dd hh:mm:ss    or\r\n");
    iprintf("\thh:mm:ss    or\r\n");
    iprintf("\thh:mm\r\n");

    if (getline(port, inputBuf, sizeof(inputBuf)) < 5)
        return(OK);

    n = sscanf(inputBuf, " %u/%u/%u %u:%u:%u", &year, &mon, &day, &hr, &min, &sec);
    if ((n == 5) || (n >= 6))
    {
        if (n == 5)
            sec = 0;
        else
            regs[0] = (Byte)toBCD(sec % 60);
        regs[1] = (Byte)toBCD(min % 60);
        regs[2] = (Byte)toBCD(hr % 24);
        regs[3] = 1;
        regs[4] = (Byte)toBCD(day % 31);
        regs[5] = (Byte)toBCD(mon % 12);
        regs[6] = (Byte)toBCD(year % 100);

        if ((rtn = rtcWriteMultRegs(RTC_SEC, 7, regs)) != SUCCESS)
        {
            iprintf("Error writing 7 RTC regs, errno = %d\r\n", rtn);
        }

        return(OK);
    }

    sec = 0;
    n = sscanf(inputBuf, " %u:%u:%u", &hr, &min, &sec);
    if (n >= 2)
    {
        regs[0] = (Byte)toBCD(sec % 60);
        regs[1] = (Byte)toBCD(min % 60);
        regs[2] = (Byte)toBCD(hr % 24);

        if ((rtn = rtcWriteMultRegs(RTC_SEC, 3, regs)) != SUCCESS)
            iprintf("Error writing 3 RTC regs, errno = %d\r\n", rtn);
        else
            iprintf("Setting time to %02d:%02d:%02d\r\n",
                    hr, min, sec);

        return(OK);
    }

    return(OK);
}


/************************************************************************/
/* Function    : setSysTime                                             */
/* Purpose     : Command function to set system date/time from RTC      */
/* Inputs      : Serial port                                            */
/* Outputs     : OK                                                     */
/************************************************************************/
int     setSysTime(int port)
{
    time_t curTod = rtcTime(NULL);

    clkSetTime(curTod);
    clkPrintTime( NULL);
    iprintf("  %iu\r\n", curTod);
}


/************************************************************************/
/* Function    : readRTCReg                                             */
/* Purpose     : Command function to read one RTC register              */
/* Inputs      : Serial port, reg number                                */
/* Outputs     : OK                                                     */
/************************************************************************/
int     readRTCReg(int port, UINT reg)
{
    Byte        rdat;
    Errno       rtn;

    if ((rtn = rtcReadReg(reg, &rdat)) != SUCCESS)
        iprintf("Error reading RTC Reg %u, errno %d\r\n",
                reg, rtn);
    else
        iprintf("RTC register %u = 0x%x\r\n",
                reg, (UINT16)rdat);
    
    return(OK);
}

/************************************************************************/
/* Function    : writeRTCReg                                            */
/* Purpose     : Command function to write one RTC register             */
/* Inputs      : Serial port, reg number                                */
/* Outputs     : OK                                                     */
/************************************************************************/
int     writeRTCReg(int port, UINT reg)
{
    Byte        wdat;
    Errno       rtn;

    iprintf("Enter value, in hex, to write to register %u:  ", reg);

    if (getline(port, inputBuf, sizeof(inputBuf)) < 1)
        return(OK);

    wdat = strtoul(inputBuf, NULL, 16) & 0xff;

    iprintf("Writing 0x%x to register %u\r\n", wdat, reg);

    rtn = rtcWriteReg(reg, wdat);

    iprintf("Return code was %d\r\n", rtn);

    return(OK);
}

/************************************************************************/
/* Function    : setXon													*/
/* Purpose     : Get/set xon status										*/
/* Inputs      : Serial port, parm                                      */
/* Outputs     : OK                                                     */
/************************************************************************/
int     setXon(int port, UINT onoff)
{
	int		status;
	time_t	xtime;

	if (onoff == 0)
		serSetXonStatus(port, FALSE);
	else if (onoff == 1)
		serSetXonStatus(port, TRUE);

	status = serGetXonStatus(port, &xtime);

	iprintf("Serial port %d, XON %sabled", port,
			(status & 1) ? "en" : "dis");

	if (status & 1)
	{
		iprintf(", status is %sXOFF, time = %u\r\n", 
				(status & 2) ? "" : "NOT ", xtime);
	}

    return(OK);
}


/************************************************************************/
/* Function    : testCmd                                                */
/* Purpose     : Command function to test parser                        */
/* Inputs      : Serial port, parm                                      */
/* Outputs     : OK                                                     */
/************************************************************************/
int     testCmd(int port, UINT parm)
{
	double	f = 2.0;

    sprintf(msgBuf, "Test Command, parm = %u, digits = %u, f = %f\r\n", parm, decDigits(parm), f);
    iprintf(msgBuf);
	serWaitTxComplete(port);
    return(OK);
}

/************************************************************************/
/* Function    : checkUsTmr                                             */
/* Purpose     : Command function show timing of microsecond timer      */
/* Inputs      : Serial port, usecs to delay                            */
/* Outputs     : OK                                                     */
/************************************************************************/
int     checkUsTmr(int port, UINT parm)
{
    while(serRxCount(port) == 0)
    {
		digTest2Toggle();
        tmrBusyWaitUs(parm);
    }
}

/************************************************************************/
/* Function    : checkMsTmr                                             */
/* Purpose     : Command function show timing of millisecond timer      */
/* Inputs      : Serial port, msecs to delay                            */
/* Outputs     : OK                                                     */
/************************************************************************/
int     checkMsTmr(int port, UINT parm)
{
    while(serRxCount(port) == 0)
	{
		digTest2Toggle();
		task_delay(parm);
	}
}

