/****************************************************************************/
/* Copyright 2009 MBARI.                                                    */
/* MBARI Proprietary Information. All rights reserved.                      */
/****************************************************************************/
#include <p24fxxxx.h>
#include <stdio.h>
#include <string.h>

#include "actions.h"
#include "parser.h"
#include "commands.h"
#include "errors.h"
#include "serial.h"
#include "config.h"
#include "dig_io.h"
#include "data_flash.h"
#include "ex_rtc.h"
#include "analog.h"
#include "spi.h"
#include "tasks.h"
#include "sys_timer.h"
#include "sys_defs.h"

/* JTAG/Code Protect/Write Protect/Clip-on Emulation mode
Watchdog Timer/ICD pins select */
_CONFIG1(JTAGEN_OFF & GCP_OFF & GWRP_OFF & COE_OFF & FWDTEN_OFF & ICS_PGx2) 
/* Enable CLK switch, Disable CLK monitor, OSCO or Fosc/2, 
Primary Oscillator Mode: Disabled, Internal Fast RC oscillator */
_CONFIG2(FCKSM_CSDCMD & OSCIOFNC_OFF & POSCMOD_XT & FNOSC_PRI)
/* Disable CLK switch and CLK monitor, OSCO or Fosc/2, HS oscillator,
Primary oscillator */

#define MAX_CHARS   80  /* maximum command line entry length */

static ConfigData configData;

int getCommand(char* cmd);

int main(void)
{
    int ret_val;
    char cmd_buff[MAX_CHARS];
    char err_buff[32];
   
    char* cmd_ptr;

    /* Configure select analog pins for digital */
    AD1PCFGbits.PCFG0 = 0;  /* battery voltage  */
    AD1PCFGbits.PCFG1 = 0;  /* humidity         */
    AD1PCFGbits.PCFG2 = 1;  /* ICSP 0           */
    AD1PCFGbits.PCFG3 = 1;  /* ICSP 1           */
    AD1PCFGbits.PCFG4 = 1;  /* Acessory pin 5   */
    AD1PCFGbits.PCFG5 = 1;  /* Acessory pin 4   */
    AD1PCFGbits.PCFG6 = 1;  /* Acessory pin 3   */
    AD1PCFGbits.PCFG7 = 1;  /* Acessory pin 2   */
    AD1PCFGbits.PCFG8 = 1;  /* Acessory pin 1   */
    AD1PCFGbits.PCFG9 = 1;  /* Acessory pin 6   */
    AD1PCFGbits.PCFG10 = 1; /* Acessory pin 7   */
    AD1PCFGbits.PCFG11 = 1; /* Acessory pin 8   */
    AD1PCFGbits.PCFG12 = 1; /* Output 7         */

    /* Map UARTs to pins */
	RPOR3bits.RP6R = 3;     /* Make Pin RP6 U1TX */
    RPINR18bits.U1RXR = 5; /* Make Pin RP5 U1RX */

    RPOR3bits.RP7R = 5;     /* Make Pin RP7 U2TX */
    RPINR19bits.U2RXR = 8;  /* Make Pin RP8 U2RX */

    /* map SPI bus pins */
    RPOR10bits.RP21R = 7;   /* Make Pin RP21 SDO (MOSI) */
    RPINR20bits.SDI1R = 20; /* Make Pin RP20 SDI (MISO) */
    RPOR9bits.RP19R = 8;    /* Make Pin RP19 SCK        */

    /* initialize I/O modules here */
    serInit();
    digInit();
    anaInit(); 
    spiInit();
    tmrInit();
    dmInit();
    rtcInit();
    taskInit();

    /* show the sign-on banner */
    sprintf(cmd_buff, "\r\nAUTONOMOUS TISSUE SAMPLER %s, %s\r\n", 
            __DATE__, __TIME__);
    serPutString(SER_CONSOLE, cmd_buff);

    sprintf(cmd_buff, "CVS tag \"%s\"\r\n\r\n", "$Name: jul_19_2011 $");
    serPutString(SER_CONSOLE, cmd_buff);
    
    /* read the config struct */
    if ( cfgRead(&configData) != 0 )
    {
        /* set the defaults */
        configData.bootFlag = DEFAULT_BOOT_FLAG;
        
        configData.triggerMode = TRIG_MODE_DEF;
        configData.timeLapseMode = TIME_LAPSE_MODE_DEF;
        
        configData.trigHoldoff = HOLDOFF_LEVEL_DEF;
        configData.trigDebounce = DEBOUNCE_LEVEL_DEF;
        
        configData.stopDelay = STOP_DELAY_DEF;
        configData.startDelay = START_DELAY_DEF;
        
        configData.triggerWindow = TRIG_WINDOW_DEF;
        
        configData.timeLapseOn = TIME_LAPSE_ON_DEF;
        configData.timeLapseOff = TIME_LAPSE_OFF_DEF;

        serPutString(SER_CONSOLE,
                     "Failed to read config, using default config\r\n");
        
        /* write the config to flash memory */
        cfgWrite(&configData);
    }

    /* initialize all parameters */
    taskSetTrigMode(configData.triggerMode);
    taskSetTimLapseMode(configData.timeLapseMode);

    tmrSetTrigHoldOff(configData.trigHoldoff);
    tmrSetTrigDebounce(configData.trigDebounce);
    
    taskSetStopDelay(configData.stopDelay);    
    taskSetStartDelay(configData.startDelay);

    taskSetTriggerWindow(configData.triggerWindow);

    taskSetTimeLapseOn(configData.timeLapseOn);
    taskSetTimeLapseOff(configData.timeLapseOff);

    /* main loop */
    for(;;)
    {
        /* call pseudo tasks */
        taskExecute(ALL_TASK);

        /* get command */
        if ( !getCommand(cmd_buff) )
        {
            ret_val = ERR_NO_LINE;
        }
        else
        {
            /* Skip white space here */
            cmd_ptr = prsSkip(cmd_buff, " \t");

            /* If the cmd from getCommand was empty then return here. */
            if ( !strlen(cmd_ptr) )
                ret_val = ERR_EMPTY_LINE;
            else
                ret_val = prsParse(cmd_ptr, cmdsRoot, ERR_NO_COMMAND);
        }

        /* display ERR code or RDY prompt */
        if ( ret_val != ERR_NO_LINE)
        {
            if ((ret_val != ERR_SUCCESS) && (ret_val != ERR_EMPTY_LINE))
            {
                sprintf(err_buff,"ERR %04d\r\n", ret_val);
                serPutString(SER_CONSOLE, err_buff);
            }

            serPutString(SER_CONSOLE, "RDY\r\n");
        }
    }

    return 0;
}

#define ECHO_MODE   1

int getCommand(char* cmd)
{
    static int char_count = 0;
    static char line[MAX_CHARS] = "";
    const unsigned char terminator = '\r';
    int got_line;
    unsigned char b;
    int i;
    
    got_line = FALSE;

    if ( serGetByte(1, &b) )
    {
        if ( ECHO_MODE )
        {
            serPutByte(1, b);
            if (b == '\r') serPutByte(1, '\n');
        }

        if ( b != terminator )
        {
            if ( (b != '\b') && (char_count < MAX_CHARS) )
                line[char_count++] = b;
            else if ( char_count > 0 )
                --char_count;

            cmd[0] = '\0';
        } 
        else
        {
            got_line = TRUE;
            line[char_count] = '\0';
            for (i = 0; i <= char_count; i++)
                cmd[i] = line[i];
            char_count = 0;
        }
    }

    return got_line;
}



