/****************************************************************************/
/* Copyright 2005 MBARI.                                                    */
/* Monterey Bay Aquarium Research Institute Proprietary Information.        */
/* All rights reserved.                                                     */
/****************************************************************************/
#include <16f876A.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#use delay(clock=4000000, restart_wdt)
#include "Gulper_Main.h"
#include "RS485.c"
#include "Command_Handler.c"


#if DEBUG
#device ICD=TRUE
#fuses XT,WDT,NOPROTECT,PUT,NOBROWNOUT,NOLVP
#else
#fuses XT,WDT,NOPROTECT,PUT,NOLVP
#endif

#define  RS485_RX_BUFFER_SIZE 64
#define  RS485_USE_EXT_INT    FALSE


int8 in_char = 0;
int8 next_in = 0;
int8 next_out = 0;
int8 *command;
int8 data[1];
#define INTS_PER_SECOND 15     // (20000000/(4*256*256))


#INT_TIMER1                        // This function is called every time
void clock_isr() {                 // timer 1 overflows (65535->0), which is
                                   // approximately 15 times per second for
    if(--int_count==0) {           // this program.
      ++seconds;
      int_count = INTS_PER_SECOND;
    }
}

// Purpose: Clears elapsed time to "start" the clock
void startTimer(void)
{
  disable_interrupts(INT_TIMER1);
 	seconds=0;
 	int_count=INTS_PER_SECOND;
 	enable_interrupts(INT_TIMER1);				
}

// Purpose: Stores elapsed time
void getElapsedTime(void)
{
	disable_interrupts(INT_TIMER1);
 	ElapsedSeconds=seconds;
 	Elapsed_int_count=INTS_PER_SECOND-int_count; // Number of interrupts since the last second, there are 15 per sec
 	enable_interrupts(INT_TIMER1);
}


// Purpose: Interrupt service routine for handling incoming proximity sensor. 
#INT_EXT
void proximity_isr() {
 //Only service proximity sensor after firing has been commanded
 //and only if proximity has not expired
 if((Fired) && (!proximity) && (!proximity_expired)) {
   getElapsedTime();
   output_bit(PIN_B4, HI); // Turn on proximity LED
   proximity = true;
 }
}

// Purpose: Holds software in infinite loop to allow watchdog to reset
void software_reset() {
  for(;;) {
    null;
  }
}

//
// Main execution loop
//
main()
{
    
  // Set up the system clocks
  int_count=INTS_PER_SECOND;
  setup_wdt(WDT_288MS); // Initialize the watchdog. See fuses WDT also
  
  //Using timer 1 so as not to interfere with WDT/RTC/Timer0
  setup_timer_1(T1_INTERNAL | T1_DIV_BY_1); 

  // Initialize Serial and enable interrupts
  rs485_init();
  enable_interrupts(INT_EXT);
  enable_interrupts(INT_TIMER1);

  // Initialize Outputs
  output_bit(PIN_C4, HI); 
	output_bit(PIN_C5, LO);
  output_bit(PIN_B1, LO);
  output_bit(PIN_B2, LO);
  output_bit(PIN_B4, LO);

  // Check for WDT reset and output error if necessary
  switch ( restart_cause() )
  {
    case WDT_TIMEOUT:
    {
      sprintf(response_message, "WDT\r\n");
      send_error_response(response_message);
      break;
    }
    case NORMAL_POWER_UP:
    {
      break;
    }
  }

 	// Send ID info via "blank" message
 	// send_response fills in the address
  sprintf(response_message, "\r\n");  
  send_response(response_message);
          

/* Begin Loop */        
    for(;;)
		{ 
		  // strobe the dog
		  restart_wdt(); 
		
 	  	if(rs485_get_new_message(RS485_ID, FALSE)) // Check for new command
		 	{
		 		// Check to see which command was received...
        if(!strcmp(cmd_InBuffer,fire)) {
          handle_fire_command();
        }
        else if(!strcmp(cmd_InBuffer,query))  {
          handle_query_command();
        }
        else if(!strcmp(cmd_InBuffer,status))  {
          handle_status_command();
        }
        else if(!strcmp(cmd_InBuffer,version))  {
          handle_version_command();
        }
        else if(!strcmp(cmd_InBuffer,actuation))  {
          handle_actuation_voltage_command();
        }
        //...Or if the command is invalid
        else { 
          sprintf(response_message, "BAD COMMAND\r\n");
          send_error_response(response_message);
        }
			}	// Check for new command

    
    /* If > 30 secs have elapsed and proximity ISR has not been called,
       report 0 for time elapsed
    */
    if( (Fired) && (!proximity) && (!proximity_expired) ) {
      getElapsedTime();
      if(ElapsedSeconds >= 30) {
        proximity_expired = true;
        sprintf(response_message, "prox_exp at:%Ld\r\n", ElapsedSeconds);
        send_response(response_message);
      }  
    }

		} // Main control loop
        
   

}
