/****************************************************************************
*  07/04/2011 started coding
*
****************************************************************************/
#define __MAIN_C__

#include "type.h"
#include "timer.h"
#include <stdint.h>
#include <LPC17xx.h>

void LCD_Init(void);
void write_a_string(void);
void blink(void);
void Init_Motors(void);
void Reverse_Motors(void);
void TurnLeft_Motors(void);
void TurnRight_Motors(void);
void Forward_Motors(void);
void Init_Rangers(void);
void Start_Rangers(void);
uint8_t LeftRangerFlag;
uint32_t LeftRangerDistance = 0;

//static const uint32_t d  = 7;
//static const float    fd = 5.3;
void led_init (void)
{
	//P0.22 was 12 and 1
	LPC_PINCON->PINSEL3	&= (~(3 << 26));
	// Set GPIO - P1_29 - to be output
	LPC_GPIO1->FIODIR |= (1 << 29);
}


// Function to turn LED2 on
void led_on (void)
{
	LPC_GPIO1->FIOSET |= (1 << 29);
}

// Function to turn LED2 off
void led_off (void)
{
	LPC_GPIO1->FIOCLR |= (1 << 29);
}

/* Init LCD and write the character H

   FIOSET and FIOCLR only respond to 1 not 0
   FIOMASK 0 means effected by FIOPIN

*/
void LCD_Init()
{
	//wait for power up
	delayUs(0,40000);
    //RS Goes low P1.18
	LPC_GPIO1->FIOCLR = (1 << 18);
    //R/W goes low
	LPC_GPIO1->FIOCLR = (1 << 19);
	delayUs(0,2);
    //Enable goes high
	LPC_GPIO1->FIOSET = (1 << 20);
	//Only change 1.21 through 1.28
	LPC_GPIO1->FIOMASK = (~(0x1FE00000));
	//Put data on bus
	LPC_GPIO1->FIOPIN = 0x07000000;  //Function set
	//Reset all
	LPC_GPIO1->FIOMASK = 0x00000000;
	delayUs(0,2);
    //Enable goes low
	LPC_GPIO1->FIOCLR = (1 << 20);
	delayUs(0,2);
    //Enable goes high
	LPC_GPIO1->FIOSET = (1 << 20);

 	delayUs(0,6000);
    //RS Goes low P1.18
	LPC_GPIO1->FIOCLR = (1 << 18);
    //R/W goes low
	LPC_GPIO1->FIOCLR = (1 << 19);
	delayUs(0,2);
    //Enable goes high
	LPC_GPIO1->FIOSET = (1 << 20);
	//Only change 1.21 through 1.28
	LPC_GPIO1->FIOMASK = (~(0x1FE00000));
	//Put data on bus
	LPC_GPIO1->FIOPIN  = 0x01C00000;  //Display on plus cursor
	//Reset all
	LPC_GPIO1->FIOMASK = 0x00000000;
	delayUs(0,2);
    //Enable goes low
	LPC_GPIO1->FIOCLR = (1 << 20);
	delayUs(0,2);
    //Enable goes high
	LPC_GPIO1->FIOSET = (1 << 20);
	
	delayUs(0,200);
   //RS Goes low P1.18
	LPC_GPIO1->FIOCLR = (1 << 18);
    //R/W goes low
	LPC_GPIO1->FIOCLR = (1 << 19);
	delayUs(0,2);
    //Enable goes high
	LPC_GPIO1->FIOSET = (1 << 20);
	//Only change 1.21 through 1.28
	LPC_GPIO1->FIOMASK = (~(0x1FE00000));
	//Put data on bus
	LPC_GPIO1->FIOPIN  = 0x00C00000;  //Entry mode set
	//Reset all
	LPC_GPIO1->FIOMASK = 0x00000000;
	delayUs(0,2);
    //Enable goes low
	LPC_GPIO1->FIOCLR = (1 << 20);
	delayUs(0,2);
    //Enable goes high
	LPC_GPIO1->FIOSET = (1 << 20);
 
	delayUs(0,1000);
    //RS Goes high - data mode P1.18
	LPC_GPIO1->FIOSET = (1 << 18);
	delayUs(0,100);
    //R/W goes low
	LPC_GPIO1->FIOCLR = (1 << 19);
	delayUs(0,2);
    //Enable goes high
	LPC_GPIO1->FIOSET = (1 << 20);
	//Only change 1.21 through 1.28
	LPC_GPIO1->FIOMASK = (~(0x1FE00000));
	//Put data on bus
	LPC_GPIO1->FIOPIN  = 0x09000000;  //H
    //Reset all
	LPC_GPIO1->FIOMASK = 0x00000000;
    delayUs(0,60);
    //Enable goes low
	LPC_GPIO1->FIOCLR = (1 << 20);
	delayUs(0,60);
    //Enable goes high
	LPC_GPIO1->FIOSET = (1 << 20);
}

void write_a_string()
{
}



/***************************************************************************/
/*  main                                                                   */
/***************************************************************************/
int main (void)
{

    init_timer( 0, TIME_INTERVAL ); // 1us	
    enable_timer( 0 );
    //Set Pins 1.x as GPIO
	LPC_PINCON->PINSEL3	&= 0x00000000;
 	//Set Pins on 1.16 - 1.31 as outputs
	LPC_GPIO1->FIODIR |= 0xFFFFFFFF;
	//Set all low
	LPC_GPIO1->FIOPIN  = 0x00000000;  
    LCD_Init();
	Init_Rangers();
	delayUs(0,1000000); //1s
	//Init_Motors();  //start going forward
	
	LeftRangerDistance = 9*147;
	while(1)
	{
  	  delayUs(0,250000);
	  led_off();
	  Start_Rangers();
	  delayUs(0,250000);
	  if (LeftRangerDistance < 8*147) //8 inches
	  {
	      //Reverse_Motors();
	      delayUs(0,1000000);  //1s
		  //TurnLeft_Motors();
	      delayUs(0,500000);  //.5s
          //Forward_Motors();		  
	  }else
  	      delayUs(0,250000);
	  led_on();
	}

  //fake return 
  return(0);
}

void Init_Rangers()
{
   LPC_PINCON->PINSEL4 |= (0x01 << 22); //Set P2.11 as EINT1
   LPC_SC->EXTMODE |= 0x02; //EINT1 is edge sensitive
   LPC_SC->EXTPOLAR |= 0x01; //EINT1 is rising edge
   init_timer( 1, TIME_INTERVAL ); // 1us	
   enable_timer( 1 );
}

/* 49ms period
   > 37.5ms, no target
   147us per inch
   Rx goes high, then stuff, the PW goes high, when goes low is range.
*/
void Start_Rangers()
{
    LeftRangerFlag = 1;
    //Left Ranger, Rx goes high
	LPC_GPIO1->FIOSET = (1 << 29);
	//Clear Interrupt
    LPC_SC->EXTINT = (1 << 1);
    //Get rising edge
	NVIC_EnableIRQ(EINT1_IRQn);
}    



void EINT1_IRQHandler(void)
{
   NVIC_DisableIRQ(EINT1_IRQn);
   
   if (LeftRangerFlag == 1)  //rising edge, start counting
   {
      LeftRangerFlag = 0;
      reset_timer( 1 );
      LPC_SC->EXTPOLAR &= 0xFFFFFFF0; //EINT1 is falling edge
      LPC_SC->EXTINT = (1 << 1);
      NVIC_EnableIRQ(EINT1_IRQn);
	  //Left Ranger, Rx goes low
	  LPC_GPIO1->FIOCLR = (1 << 29);
   }
   else
   {
      LeftRangerDistance = get_timer_value( 1 );  //Count length of pulse
   }

  return;  
}

void Init_Motors()
{
	LPC_PINCON->PINSEL7	|= (0x3 << 18); //Turn on PWM1.2
	LPC_PINCON->PINSEL4	|= (0x1 << 4); //Turn on PWM1.3
	LPC_PWM1->TCR = 0x0;
	LPC_PWM1->PR  = 0x00;		/* set prescaler to zero */
	LPC_PWM1->MR0 = 20 * (27000000 / 1000-1);  //should be period, 20ms
	LPC_PWM1->MR2 = 1700 * (27000 / 1000-1);  //should be match 1.7ms
	LPC_PWM1->MR3 = 1300 * (27000 / 1000-1);  //should be match 1.3ms
	LPC_PWM1->MCR = 0x02;		/* reset timer on match */
	LPC_PWM1->PCR |= (3 << 10);		/* enable PWM2 and PWM3*/
	LPC_PWM1->TCR |= 0x9;		/* start timer */
}

void Reverse_Motors()
{
	LPC_PWM1->MR2 = 1300 * (27000 / 1000-1);  //should be match 1.3ms
	LPC_PWM1->MR3 = 1700 * (27000 / 1000-1);  //should be match 1.7ms
    LPC_PWM1->LER = (0x3<<2);
}

void TurnRight_Motors()
{
	LPC_PWM1->MR2 = 1700 * (27000 / 1000-1);  //should be match 1.7ms
	LPC_PWM1->MR3 = 0;  
    LPC_PWM1->LER = (0x3<<2);
}

void TurnLeft_Motors()
{
	LPC_PWM1->MR2 = 0;
	LPC_PWM1->MR3 = 1300 * (27000 / 1000-1);  //should be match 1.3ms
    LPC_PWM1->LER = (0x3<<2);
}

void Forward_Motors()
{
	LPC_PWM1->MR2 = 1700 * (27000 / 1000-1);  //should be match 1.7ms
	LPC_PWM1->MR3 = 1300 * (27000 / 1000-1);  //should be match 1.3ms
    LPC_PWM1->LER = (0x3<<2);
}