/**
 * \file
 *
 * \brief Empty user application template
 *
 */

/**
 * \mainpage User Application template doxygen documentation
 *
 * \par Empty user application template
 *
 * Bare minimum empty user application template
 *
 * \par Content
 *
 * -# Include the ASF header files (through asf.h)
 * -# "Insert system clock initialization code here" comment
 * -# Minimal main function that starts with a call to board_init()
 * -# "Insert application code here" comment
 *
 */

/*
 * Include header files for all drivers that have been imported from
 * Atmel Software Framework (ASF).
 */
/*
 * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
 */
#include <asf.h>
#include "main.h"
static volatile bool main_b_cdc_enable = false;
uint16_t color;

int main (void)
{
	uint32_t duty = 40;
	irq_initialize_vectors();
	cpu_irq_enable();
	wdt_disable(WDT);
	sysclk_init();
	fpu_enable();//habilita coprocesador matematico
	ioport_init();
	board_init();
	udc_start();
	tc0_0_init();
	SetupPeripherals();
	Pwm_init();
	pwm_update(2000, 600);
	twi0_init_m41t00();
	Adc_init(); 
	dac0_init();
	configure_usart0();
	w25q_SPI_init(60000000);
	Time_adjust(25,10,2);
	MOTOR_ON();
	BRAKE_ON();
	LCD_Init();

	DrawTestPage("Probando Display");
	POINT_COLOR = VGA_BLACK;
	BACK_COLOR = VGA_WHITE;


	LCD_setFont(font7_96_144);

	NT35510_printChar('4', 40, 300,VGA_BLUE, VGA_WHITE);
	NT35510_printChar('5', 140, 300,VGA_GREEN, VGA_WHITE);
	NT35510_printChar('3', 240, 300,VGA_RED, VGA_WHITE);
	LCD_setFont(font48);
	MOTOR_OFF();
	BRAKE_OFF();

	while(1)
	{
		if(Flags.sys_led_toogle)
		{
			Flags.sys_led_toogle = false;
			ioport_toggle_pin_level(SYS_LED);
			Motor_temperature();
			//NT35510_printNumI(motorTemp, 40, 200,4,'0',VGA_BLUE, VGA_WHITE);
			//NT35510_printNumF(temperatura,3,3,'0',10,200 , VGA_BLUE, VGA_WHITE);
			//LCD_ShowNum(40,600,motorTemp,5,16);
		}
		
		if(usb_datos_listos)
		{
			usb_datos_listos = false;
			Usb_cmd_decode();
			Usb_tx();
		}
		
	
	    if(!Flags.bitmap)
		{
		    twi_read_rtc();
			LCD_setFont(font7seg);
			NT35510_printNumI(decoded_time.hour, 20, 60,2,'0',VGA_BLUE, VGA_WHITE);
		    LCD_setFont(font48);
		    NT35510_printChar(':', 100, 60,VGA_BLUE, VGA_WHITE);
		    LCD_setFont(font7seg);
			NT35510_printNumI(decoded_time.min, 180, 60,2,'0',VGA_BLUE, VGA_WHITE);
		    LCD_setFont(font48);
		    NT35510_printChar(':', 260, 60,VGA_BLUE, VGA_WHITE);
		    LCD_setFont(font7seg);
		    NT35510_printNumI(decoded_time.sec, 340, 60,2,'0',VGA_BLUE, VGA_WHITE);

		}
		
	}
}



bool my_callback_cdc_enable(void)
{
	main_b_cdc_enable = true;
	return true;
}

void my_callback_cdc_disable(void)
{
	main_b_cdc_enable = false;
}


void usb_data_received(uint8_t port)
{
   iram_size_t Number_of_Rcvd_Bytes;
   Number_of_Rcvd_Bytes = udi_cdc_get_nb_received_data();
   udi_cdc_read_buf(usb_rx_buffer, Number_of_Rcvd_Bytes);
   usb_datos_listos = true;
}

//Initialize MCU Peripherals
void SetupPeripherals(void)
{
	/* Initialize IOPORTs */
	ioport_init();
	//System Led
	pio_set_output(PIOD,SYS_LED_MASK,0,0,0);
	
	/** Start, Stop Butoms */
	//START
	pio_set_input(PIOA,PIO_PA30,PIO_PULLUP|PIO_DEBOUNCE);
	//Configure debounce filter at 25Hz
	pio_set_debounce_filter(PIOA, PIO_PA30, 25);
	//STOP
	pio_set_input(PIOA,PIO_PA31,PIO_PULLUP|PIO_DEBOUNCE);
	//Configure debounce filter at 25Hz
	pio_set_debounce_filter(PIOA, PIO_PA31, 25);
	
	/** Rotary Encoder. */
	//CanalA
	pio_set_input(PIOA,PIO_PA22,PIO_INPUT);
	//CanalB
	pio_set_input(PIOA,PIO_PA23,PIO_INPUT);
	//Push Button
	pio_set_input(PIOA,PIO_PA24,PIO_PULLUP|PIO_DEBOUNCE);
	//Configure debounce filter at 25Hz
	pio_set_debounce_filter(PIOA, PIO_PA24, 25);
	
	//Configure External Interrupt on fall edge of PIO_PA22 (ENC A)
	pio_handler_set(PIOA, ID_PIOA, PIO_PA22, PIO_IT_FALL_EDGE, pioHandler);

	//Enable external interrupt
	pio_enable_pin_interrupt(PIO_PA22_IDX);
	
	//Configure Ext Interrupt in NVIC
	irq_register_handler(PIOA_IRQn,0);
	
	//VBUS Pin
	//ioport_set_pin_peripheral_mode(PIO_PB12_IDX, USB_VBUS_FLAGS);
	
	//NPCS PINS
	pio_set_output(PIOA,EXT_SPI_CS_PIN_MASK,1,0,0);
	pio_set_output(PIOA,AD7843_CS_PIN_MASK,1,0,0);
	pio_set_output(PIOA,WB_CS_PIN_MASK,1,0,0);
	
	//AD7843 TP_PEN PIN
	pio_set_input(PIOA,AD7843_TP_PEN_PIN_MASK,PIO_INPUT);
	
	//Digital Out Pins
	pio_set_output(PIOA,OUT0_PIN_MASK,0,0,0);
	pio_set_output(PIOA,OUT1_PIN_MASK,0,0,0);
	pio_set_output(PIOA,OUT2_PIN_MASK,0,0,0);
	
    // RS485 DE Bus Control Signal
	pio_set_output(PIOA,RS4_DE_PIN_MASK,0,0,0);
	
	//PWM Pins
	pio_set_peripheral(PIOD, PIO_PERIPH_A, PIO_PD24A_PWML0);
	pio_set_peripheral(PIOD, PIO_PERIPH_A, PIO_PD20A_PWMH0);
	
	//EQM-402B Signals
	pio_set_output(PIOA,MOTOR_CNTRL_PIN_MASK,0,0,0);
	pio_set_output(PIOA,BRAKE_CNTRL_PIN_MASK,0,0,0);
	
	/* ADC Pins. Disable pull-up*/
	PIOA->PIO_SODR = PIO_SODR_P17;
	PIOA->PIO_SODR = PIO_SODR_P18;
	PIOA->PIO_SODR = PIO_SODR_P19;
	PIOA->PIO_SODR = PIO_SODR_P20;
	PIOA->PIO_SODR = PIO_SODR_P21;
	
	//Pin DAC0
	pio_set_peripheral(PIOB, PIO_PERIPH_D, PIO_PB13X1_DAC0);
	
	//Allow TWI to control PA3 and PA4
	pio_set_peripheral(PIOA, PIO_PERIPH_A, PIO_PA3A_TWD0 | PIO_PA4A_TWCK0);
	
	//Allow USART0 to control PB0 and PB1
	pio_set_peripheral(PIOB, PIO_PERIPH_C, PIO_PB0C_RXD0 | PIO_PB1C_TXD0);
	
	//Pines CAN0
	pio_set_peripheral(PIOB, PIO_PERIPH_A, PIO_PB3A_CANRX0);
	pio_set_peripheral(PIOB, PIO_PERIPH_A, PIO_PB2A_CANTX0);
	
	//Pines de control del display TFT
	pio_set_output(PIOD,DB0_PIN_MASK,0,0,0); // DB0
	pio_set_output(PIOD,DB1_PIN_MASK,0,0,0); // DB1
	pio_set_output(PIOD,DB2_PIN_MASK,0,0,0); // DB2
	pio_set_output(PIOD,DB3_PIN_MASK,0,0,0); // DB3
	pio_set_output(PIOD,DB4_PIN_MASK,0,0,0); // DB4
	pio_set_output(PIOD,DB5_PIN_MASK,0,0,0); // DB5
	pio_set_output(PIOD,DB6_PIN_MASK,0,0,0); // DB6
	pio_set_output(PIOD,DB7_PIN_MASK,0,0,0); // DB7
	pio_set_output(PIOD,DB8_PIN_MASK,0,0,0); // DB8
	pio_set_output(PIOD,DB9_PIN_MASK,0,0,0); // DB9
	pio_set_output(PIOD,DB10_PIN_MASK,0,0,0); // DB10
	pio_set_output(PIOD,DB11_PIN_MASK,0,0,0); // DB11
	pio_set_output(PIOD,DB12_PIN_MASK,0,0,0); // DB12
	pio_set_output(PIOD,DB13_PIN_MASK,0,0,0); // DB13
	pio_set_output(PIOD,DB14_PIN_MASK,0,0,0); // DB14
	pio_set_output(PIOD,DB15_PIN_MASK,0,0,0); // DB15
	pio_set_output(PIOD,DB16_PIN_MASK,0,0,0); // DB16
	pio_set_output(PIOD,DB17_PIN_MASK,0,0,0); // DB17
	pio_set_output(PIOD,TFT_RD_PIN_MASK,1,0,0); // RD
	pio_set_output(PIOD,TFT_WR_PIN_MASK,1,0,0); // WR
	pio_set_output(PIOD,TFT_DC_PIN_MASK,1,0,0); // DC
	pio_set_output(PIOD,TFT_CS_PIN_MASK,1,0,0); // CS
	pio_set_output(PIOD,TFT_RST_PIN_MASK,1,0,0); // RST
	pio_set_output(PIOD,TFT_BKL_PIN_MASK,1,0,0); // BKL
	pio_set_output(PIOD,TFT_IM0_PIN_MASK,1,0,0); // IM0
	pio_set_output(PIOD,TFT_IM1_PIN_MASK,0,0,0); // IM1

	//Habilitamos control del bus de datos
	PIOD->PIO_OWER = 0xFFFF;
	
	//Pin de proteccion de la memoria flash serie
	pio_set_output(PIOD,WB_P_PIN_MASK,0,0,0); // WB_P

}

//PIO Handler - called by the PIO ISR
void pioHandler(uint32_t id, uint32_t index)
{
	//If PD26 (Encoder A)
	if(id == ID_PIOA && index == PIO_PA22)
	{
		EncoderPulse();
	}
	
	
}



void EncoderPulse(void)
{
	if(ioport_get_pin_level(PIO_PA22_IDX))
	{
		pio_handler_set(PIOA, ID_PIOA, PIO_PA22, PIO_IT_FALL_EDGE, pioHandler);
		if(ioport_get_pin_level(PIO_PA23_IDX))
		{
			Encoder.direction = false;
			Encoder.pulse_counter--;
		}
		else
		{
			Encoder.direction = true;
			Encoder.pulse_counter++;
		}
		
	}
	else
	{
		pio_handler_set(PIOA, ID_PIOA, PIO_PA26, PIO_IT_RISE_EDGE, pioHandler);
		if(ioport_get_pin_level(PIO_PA23_IDX))
		{
			Encoder.direction = true;
			Encoder.pulse_counter++;
		}
		else
		{
			Encoder.direction = false;
			Encoder.pulse_counter--;
		}
		
	}
	
	Encoder.pulse = true;
}


void Usb_cmd_decode(void)
{
	uint16_t ivalue;

	// Create union of shared memory space
	union {
		float float_var;
		uint8_t temp_array[4];
	} u;
	
	switch(usb_rx_buffer[0])
	{
	   case 1://external flash prog
	   Flags.bitmap = true;
	   address = ((uint32_t)(usb_rx_buffer[1])<<16) |((uint16_t) (usb_rx_buffer[2])<<8) | usb_rx_buffer[3];
	   page = ((uint32_t)(usb_rx_buffer[4])<<8) | usb_rx_buffer[5];
	   subpage = usb_rx_buffer[6];
	   for(int i=0;i<32;i++)
	   {
		  ivalue = ((uint16_t)32 * subpage) + i;
		  temp_buffer[ivalue] =  usb_rx_buffer[i + 10];
	   }
	   if(subpage >= 7)
	   {
		  w25q_IO_Write_nBytes(address + (page << 8),256);
		  LCD_setFont(font16x16);
		  NT35510_printNumI(page, 20, 700,4,'0',VGA_BLUE, VGA_WHITE);
		  NT35510_printNumI(address, 20, 750,6,'0',VGA_BLUE, VGA_WHITE);
		
	   }
	   break;
	  case 2://external flash erase
	  w25q_IO_Erase_Chip();
	  w25q_IO_Erase_Chip();
	  break;
	  case 3://mostrar bitmap
	  Flags.bitmap = true;
	  address = ((uint32_t)(usb_rx_buffer[1])<<16) |((uint32_t) (usb_rx_buffer[2])<<8) | usb_rx_buffer[3];
	  x = ((uint16_t)(usb_rx_buffer[4])<<8) | usb_rx_buffer[5];
	  y = ((uint16_t)(usb_rx_buffer[6])<<8) | usb_rx_buffer[7];
	  ancho = ((uint16_t)(usb_rx_buffer[8])<<8) | usb_rx_buffer[9];
	  alto = ((uint16_t)(usb_rx_buffer[10])<<8) | usb_rx_buffer[11];
	  NT35510_drawBitmap_from_w25q(x,y,ancho,alto,address,1);
	  break;
	  case 150:
	  SAMBA_reboot ();
	  break;
	  case 251:
	  memcpy(ul_page_buffer, (const void *)(DATA_PAGE_ADDRESS ), IFLASH_PAGE_SIZE / sizeof(uint32_t));
	  break;
	  case 252:
		//read_params_from_flash_buffer();
	  break;
	  default:
	  break;
		
		/*
		case 26://q
		u.temp_array[0] = usb_rx_buffer[1];
		u.temp_array[1] = usb_rx_buffer[2];
		u.temp_array[2] = usb_rx_buffer[3];
		u.temp_array[3] = usb_rx_buffer[4];
		params.q = u.float_var;
		save_params_to_flash();
		break;
		case 27: //Temperatura armario
		params.set_Temp_armario = (usb_rx_buffer[2] << 8) | usb_rx_buffer[1];
		save_params_to_flash();
		break;
		
		*/

	}
	usb_rx_buffer[0] = 0;//para no repetir comando
}

void Usb_tx(void)
{
	usb_tx_buffer[0] = 1;
	usb_tx_buffer[1] = 2;

	for(int i=0;i<USB_TX_BUFFER_SIZE;i++)
	{
		if(udi_cdc_is_tx_ready())
		{
			udi_cdc_putc(usb_tx_buffer[i]);
			while(!udi_cdc_is_tx_ready());
		}
	}
}


/***************************************************************
* Temperatura del motor en ºC x 10
***************************************************************/
void Motor_temperature(void)
{
	float v;
	v = (float)Adc1_read_adc_channel2() * 2.526f / 4095.0f;
	temperatura = (247.15f * v - 15.61f) / 10.0f;
	motorTemp = (int16_t) (247.15f * v - 15.61f) ;

}

RAMFUNC void SAMBA_reboot (void)
{
	
	// Wait until Flash is ready
	while(!(EFC->EEFC_FSR & EEFC_FSR_FRDY));
	
	//Send Clear GPNVM bit command with argument 1 (Clear GPNVM1)
	EFC->EEFC_FCR = (EEFC_FCR_FKEY_PASSWD | EEFC_FCR_FCMD_CGPB |(1 << EEFC_FCR_FARG_Pos));
	while(!(EFC->EEFC_FSR & EEFC_FSR_FRDY));
	
	// Perform Software reset
	RSTC->RSTC_CR |= (RSTC_CR_KEY_PASSWD | RSTC_CR_PROCRST | RSTC_CR_PERRST);
	
	//Infinite loop to avoid further code execution - chip should reset
	while(1);
}





