/****************************************************************************/
/* Copyright 2010 MBARI.                                                    */
/* MBARI Proprietary Information. All rights reserved.                      */
/****************************************************************************/
#include <p24fxxxx.h>
#include <stdio.h>
#include <string.h>

#include "spi.h"
#include "sys_defs.h"
#include "actions.h"
#include "parser.h"
#include "commands.h"
#include "errors.h"
#include "serial.h"
#include "slot.h"
#include "sys_timer.h"


/* FLASH Configuration */

/* JTAG/Code Protect/Write Protect/Clip-on Emulation mode
Watchdog Timer/ICD pins select */
_CONFIG1(JTAGEN_OFF & GCP_OFF & GWRP_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 */
_CONFIG3(WPEND_WPSTARTMEM & WPCFG_WPCFGEN & WPDIS_WPEN & WPFP_WPFP2)


#define MAX_CHARS   80  /* maximum command line entry length */
#define SER_CONSOLE 2
#define TIMER_100 100
#define TIMER_1000 1000

int getCommand(char* cmd);
extern int actDebug1;


int main()
{
		int test;
		
		for(test = 0; test <= 1000; test++)
		{

		}

    unsigned int bits = 0;
    int ret_val;
    char cmd_buff[MAX_CHARS];
    char err_buff[32];
    
    char* cmd_ptr;
    
    Timer Timer1;
    Timer Timer2;

    /* Set up bus bits and deselect all slots for periph init below */
    TRISBbits.TRISB12 = 0;	
    TRISBbits.TRISB13 = 0;
    TRISBbits.TRISB14 = 0;
    TRISBbits.TRISB15 = 0;
    
    LATBbits.LATB12 = 0; /* DIG_ADD_GATE    */
    Nop();
    LATBbits.LATB13 = 0; /* DIG_ADD_0 (LSB) */
    Nop();
    LATBbits.LATB14 = 0; /* DIG_ADD_1       */
    Nop();
    LATBbits.LATB15 = 0; /* DIG_ADD_2 (MSB) */
    Nop();
    

    /* Map UARTs to pins */
    /* should move this to periph mapping module */

    /* Map UART #1 pins */
    RPINR18bits.U1RXR = 3;  /* Make Pin RP3 U1RX */
    RPOR2bits.RP4R = 3;     /* Make Pin RP4 U1TX */

    /* Map UART #2 pins */
    RPINR19bits.U2RXR = 11; /* Make Pin RP11 U2RX */
    RPOR6bits.RP12R = 5;    /* Make Pin RP12 U2TX */

    /* Map SPI #1 pins */
    RPINR20bits.SDI1R = 21; /* SDI1 (MISO) RP21 */
    RPOR13bits.RP26R = 7;   /* SDO1 (MOSI) RP26 */
    RPOR9bits.RP19R = 8;    /* SCK1 (SCK)  RP19 */

    /* make bit RG9 the CS */
    LATGbits.LATG9 = 1;				
    Nop();
    TRISGbits.TRISG9 = 0;
    Nop();

    /* initialize the shizzle */
    serInit();
    tmrInit();
    spiInit();
    
    cacheInit();
    slotInit();

    /* spit out the banner */
    sprintf(cmd_buff, "\r\nFOCE CHASSIS CPU BOARD Built on %s at %s\r\n", 
            __DATE__, __TIME__);
    serPutString(SER_CONSOLE, cmd_buff);

    tmrClear(&Timer1);
    tmrStart(&Timer1);
    tmrClear(&Timer2);
    tmrStart(&Timer2);

    /* enter the main loop */
    for(;;)
    {
#if 0
        if (tmrRead(&Timer1) > 100)
        {
            tmrClear(&Timer1);
            
            /* write the bits to mem location 0 */
            spiSlaveWrite(0, ++bits);
        }
            
        if (tmrRead(&Timer2) > 10000)
        {
            tmrClear(&Timer2);
/*            serPutString(SER_CONSOLE, "Timer2 fired\r\n");*/
        }
#endif


        if ( actDebug1 == 1)
        {
            actDebug1 = 0;
            tmrStart(&Timer1);
        }
        
        if ( actDebug1 == 2)
        {
            actDebug1 = 0;
            tmrStop(&Timer1);
        }

        /* 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");
        }
        
        if (tmrRead(&Timer1) > slotUpdateInterval)
        {
            tmrClear(&Timer1);
            slotUpdate();
        }
    }

    return 0;    
}

#define ECHO_MODE   1
#define TERM        '\r'

int getCommand(char* cmd)
{
    static int char_count = 0;
    static char line[MAX_CHARS] = "";
    int got_line;
    unsigned char b;
    int i;
    
    got_line = FALSE;


    if ( serGetByte(SER_CONSOLE, &b) )
    {
        if ( ECHO_MODE )
        {
            serPutByte(SER_CONSOLE, b);
            if (b == '\r') serPutByte(SER_CONSOLE, '\n');
        }

        if ( b != TERM )
        {
            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;
}


