/**************************************************************************************************/
/* LOW VOLTAGE LOAD SWITCHER BOARD																  */
/* COPYRIGHT: 2012 MBARI.                                                   					  */
/* MBARI Proprietary Information. All rights reserved.                      					  */
/* FILENAME:		main.c																		  */
/* AUTHORS: 		Jaine E. Perotti, adapted from code written by Roland Quiros				  */
/* CONTACT: 		jperotti@my.fit.edu															  */	
/* DESCRIPTION: 	Main source code for the Shallow Water FOCE's low voltage					  */
/*					load switcher.  This is designed to be compiled with the					  */
/*					MPLAB C30 Compiler, for use with the PIC24FJ256GA106.						  */
/* FUNCTION LIST:	main()																		  */
/*					getCommand(char* cmd)														  */															
/**************************************************************************************************/
#include <p24fxxxx.h>
#include <stdio.h>
#include <string.h>

#include "card.h"
#include "sys_defs.h"
#include "actions.h"
#include "parser.h"
#include "commands.h"
#include "errors.h"
#include "serial.h"
#include "spi1.h"
#include "spi2.h"
#include "dig_io.h"
#include "sys_timer.h"
#include "potentiometer.h"
#include "adcnew.h"
#include "relay.h"
#include "conditions.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)

//	Definitions
#define MAX_CHARS   80  /* maximum command line entry length */
#define SER_CONSOLE 1
#define ECHO_MODE   1
#define TERM        '\r'

//	Prototypes
int getCommand(char* cmd);

//	Set Globals
int int1_state = 0;
int expPrevState[5][2] = {{0,0},{0,0},{0,0},{0,0},{0,0}};	//holds previous state of the I/O expanders

////////////////////////////////////////////////////////////////////////////////////////////////////
//******************************************* Main *************************************************
////////////////////////////////////////////////////////////////////////////////////////////////////
int main()
{
    int ret_val;
    char cmd_buff[MAX_CHARS];
    char err_buff[32];     
    char* cmd_ptr;
    unsigned int reg;
    unsigned int spiCount = 0;

    Timer Timer1;
    Timer Timer2;
     
    // Map UART pins 
    RPINR18bits.U1RXR = 3;  	// Make Pin RP3 U1RX 
    RPOR2bits.RP4R = 3;     	// Make Pin RP4 U1TX 
    
    // Map SPI #1 Pins 			
    RPINR20bits.SDI1R = 21; 	// SDI1 (MISO) RP21 
    RPOR13bits.RP26R = 7;   	// SDO1 (MOSI) RP26 
    RPINR20bits.SCK1R = 19;    	// SCK1 (SCK)  RP19 
	RPINR21bits.SS1R = 27;		// SS1  (CS)   RP27

	//Map External Interrupt Pins
	RPINR0bits.INT1R = 22;		// EXT INTERRUPT 1 	RP22
	
	// initialize the shizzle 
	digInit();					// DIGITAL I/O INIT
    serInit();					// SERIAL
    tmrInit();					// TIMERS
    spiInit();					// SPI 1
	spi2Init();					// SPI 2
	expInit();					// I/O EXPANDERS
    cardInit();					// CARD

    // spit out the banner 
    sprintf(cmd_buff, 
            "\r\nFOCE CHASSIS LOW VOLTAGE LOAD SWITCHER BOARD Built on %s at %s\r\n\n", 
            __DATE__, __TIME__);
    serPutString(SER_CONSOLE, cmd_buff);

    tmrClear(&Timer1);
    tmrStart(&Timer1);
    tmrClear(&Timer2);
    tmrStart(&Timer2);

	tmrDelayMs(100);

	brkrReset(CHAN1);
	brkrReset(CHAN2);

	relayOn(CHAN1);
	relayOn(CHAN2);

	// Initialize External Interrupt 1
	INTCON2 = 0x00;				// Interrupt on positive edge
	IFS1bits.INT1IF = 0;		// Reset INT1 interrupt flag
	IEC1bits.INT1IE = 1;    	// Enable INT1 Interrupt Service Routine
	IPC5bits.INT1IP = 7;		// Set priority

	int count = 0;
	int dummy, OverCurr1, OverVolt1, UnderVolt1, OverCurr2, OverVolt2, UnderVolt2, prev_state1, prev_state2;
	dummy = potReadWrite(POT_01_CS, WRITE, WIPER_3, 255);

    // ***************** enter the main loop *****************
    for(;;)
    {
		if(count < 10)
		{
			// SAVE PREVIOUS STATE OF POTENTIOMETERS
			prev_state1 = potReadWrite(POT_01_CS, READ, WIPER_2, 0x00);
			
			// GET CONDITIONS
			OverCurr1 = condOverCurr(CHAN1);
			OverVolt1 = condOverVolt(CHAN1);
			UnderVolt1 = condUnderVolt(CHAN1);

			// CHECK CHANNEL, TURN OFF RELAY, RESET BREAKER, WAIT, THEN TURN RELAY BACK ON
			// Is condition on channel 1?
			if((OverCurr1|OverVolt1|UnderVolt1) != 0)					
			{	
				// turn pot down to prevent UV condition when relay is off
				dummy = potReadWrite(POT_01_CS, WRITE, WIPER_2, 0);		
				relayOff(CHAN1);
				brkrReset(CHAN1);
				tmrDelayMs(50);
				relayOn(CHAN1);
				dummy = potReadWrite(POT_01_CS, WRITE, WIPER_2, prev_state1);
				count++;
			}
		}

        // get command 
        if ( !getCommand(cmd_buff) )
        {
            ret_val = ERR_NO_LINE;	
        }
        else
        {
            // Skip white space here 
            cmd_ptr = prsSkip(cmd_buff, "     ");
            
            // 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\n", ret_val);
                serPutString(SER_CONSOLE, err_buff);
            }
            serPutString(SER_CONSOLE, "RDY\r\n\n");
        }

        cardPoll();
        spiUpdate();
    }
    return 0;    
}

////////////////////////////////////////////////////////////////////////////////////////////////////
//	NAME:			getCommand(char* cmd)
//	DESCRIPTION:	Retrieves commands from the user.
////////////////////////////////////////////////////////////////////////////////////////////////////
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;
}
