/*
 * W5200.c
 *
 * Created: 14/08/2018 8:39:37
 *  Author: Ledo
 */ 

#include "W5200.h"


void Port_config(void)
{
	/* WIZNET Pins */
	//Reset
	pio_set_output(PIOD,WIZNET_RST_PIN_MASK,1,0,0);
	//Interrupt
	pio_set_input(PIOD,PIO_PD28,PIO_INPUT);
	//CS
	pio_set_output(PIOA,WIZNET_CS_PIN_MASK,1,0,0);

}



void Reset_W5200(void)
{
	pio_set_pin_low(WIZNET_RST_PIN);
	delay_us(2);
	pio_set_pin_high(WIZNET_RST_PIN);
	delay_ms(50);
	wdt_restart(WDT);
	delay_ms(50);
	wdt_restart(WDT);
	delay_ms(50);
	wdt_restart(WDT);
	
}

void InterruptEnable(void)
{
	//Configure External Interrupt on fall edge of PIO_PD26
	pio_handler_set(PIOD, ID_PIOD, PIO_PD28, PIO_IT_FALL_EDGE, pioHandler);
	//Enable external interrupt
	pio_enable_pin_interrupt(PIO_PD28_IDX);
	//Configure Ext Interrupt in NVIC
	irq_register_handler(PIOD_IRQn,0);
}

void InterruptDisable(void)
{
	pio_disable_pin_interrupt(PIO_PD28_IDX);
}

void IINCHIP_CS_low(void)
{
   // Activate the CS pin
   pio_set_pin_low(WIZNET_CS_PIN);
}

void IINCHIP_CS_high(void)
{
   // deactivate the CS pin
   pio_set_pin_high(WIZNET_CS_PIN);
}

uint8_t  IINCHIP_SpiSendData(uint8_t dat)
{
	return spi_master_transfer(dat);
}

 /**
 @brief	This function writes the data into W5200 registers.
 */

 uint8_t IINCHIP_WRITE(uint16_t addr,uint8_t data)
 {
	 InterruptDisable();                      // Interrupt Service Routine Disable

	 IINCHIP_CS_low();                            // CS=0, SPI start

	 IINCHIP_SpiSendData((addr & 0xFF00) >> 8);  // Address byte 1
	 IINCHIP_SpiSendData(addr & 0x00FF);         // Address byte 2
	 IINCHIP_SpiSendData(0x80);                  // Data write command and Write data length 1
	 IINCHIP_SpiSendData(0x01);                  // Write data length 2
	 IINCHIP_SpiSendData(data);                  // Data write (write 1byte data)

	 IINCHIP_CS_high();                             // CS=1,  SPI end

	 InterruptEnable();                     // Interrupt Service Routine Enable
	 return 1;
 }
 
 /**
@brief	This function reads the value from W5200 registers.
*/
uint8_t IINCHIP_READ(uint16_t addr)
{
	uint8_t data;
        
	InterruptDisable();                     // Interrupt Service Routine Disable
	
	IINCHIP_CS_low();                             // CS=0, SPI start
	
    IINCHIP_SpiSendData((addr & 0xFF00) >> 8);   // Address byte 1
	IINCHIP_SpiSendData(addr & 0x00FF);          // Address byte 2
	IINCHIP_SpiSendData(0x00);                   // Data read command and Read data length 1
	IINCHIP_SpiSendData(0x01);                   // Read data length 2   	
	data = IINCHIP_SpiSendData(0x00);            // Data read (read 1byte data)
	
        IINCHIP_CS_high();                              // CS=1,  SPI end
	
        InterruptEnable();                        // Interrupt Service Routine Enable
	return data;
}



/**
@brief	This function is for resetting of the iinchip. Initializes the iinchip to work in whether DIRECT or INDIRECT mode
*/ 
void iinchip_init(void)
{	
	setMR( MR_RST );

}




// added

/**
@brief	This function sets up gateway IP address.
*/ 
void setGAR(
	uint8_t * addr	/**< a pointer to a 4 -byte array responsible to set the Gateway IP address. */
	)
{
	IINCHIP_WRITE((GAR0 + 0),addr[0]);
	IINCHIP_WRITE((GAR0 + 1),addr[1]);
	IINCHIP_WRITE((GAR0 + 2),addr[2]);
	IINCHIP_WRITE((GAR0 + 3),addr[3]);
}

/*
void getGWIP(uint8_t * addr)
{
	addr[0] = IINCHIP_READ((GAR0 + 0));
	addr[1] = IINCHIP_READ((GAR0 + 1));
	addr[2] = IINCHIP_READ((GAR0 + 2));
	addr[3] = IINCHIP_READ((GAR0 + 3));
}
*/

/**
@brief	It sets up SubnetMask address
*/ 

void setSUBR(uint8_t * addr)
{   
	IINCHIP_WRITE((SUBR0 + 0), addr[0]);
	IINCHIP_WRITE((SUBR0 + 1), addr[1]);
	IINCHIP_WRITE((SUBR0 + 2), addr[2]);
	IINCHIP_WRITE((SUBR0 + 3), addr[3]);
}

void clearSUBR(void)
{
	
	IINCHIP_WRITE((SUBR0 + 0), 0);
	IINCHIP_WRITE((SUBR0 + 1), 0);
	IINCHIP_WRITE((SUBR0 + 2), 0);
	IINCHIP_WRITE((SUBR0 + 3), 0);
}


/**
@brief	This function sets up MAC address.
*/ 
void setSHAR(
	uint8_t * addr	/**< a pointer to a 6 -byte array responsible to set the MAC address. */
	)
{
	IINCHIP_WRITE((SHAR0 + 0),addr[0]);
	IINCHIP_WRITE((SHAR0 + 1),addr[1]);
	IINCHIP_WRITE((SHAR0 + 2),addr[2]);
	IINCHIP_WRITE((SHAR0 + 3),addr[3]);
	IINCHIP_WRITE((SHAR0 + 4),addr[4]);
	IINCHIP_WRITE((SHAR0 + 5),addr[5]);
}

/**
@brief	This function sets up Source IP address.
*/
void setSIPR(
	uint8_t * addr	/**< a pointer to a 4 -byte array responsible to set the Source IP address. */
	)
{
	IINCHIP_WRITE((SIPR0 + 0),addr[0]);
	IINCHIP_WRITE((SIPR0 + 1),addr[1]);
	IINCHIP_WRITE((SIPR0 + 2),addr[2]);
	IINCHIP_WRITE((SIPR0 + 3),addr[3]);
}

/**
@brief	This function sets up Source IP address.
*/
void getGAR(uint8_t * addr)
{
	addr[0] = IINCHIP_READ(GAR0);
	addr[1] = IINCHIP_READ(GAR0+1);
	addr[2] = IINCHIP_READ(GAR0+2);
	addr[3] = IINCHIP_READ(GAR0+3);
}
void getSUBR(uint8_t * addr)
{
	addr[0] = IINCHIP_READ(SUBR0);
	addr[1] = IINCHIP_READ(SUBR0+1);
	addr[2] = IINCHIP_READ(SUBR0+2);
	addr[3] = IINCHIP_READ(SUBR0+3);
}
void getSHAR(uint8_t * addr)
{
	addr[0] = IINCHIP_READ(SHAR0);
	addr[1] = IINCHIP_READ(SHAR0+1);
	addr[2] = IINCHIP_READ(SHAR0+2);
	addr[3] = IINCHIP_READ(SHAR0+3);
	addr[4] = IINCHIP_READ(SHAR0+4);
	addr[5] = IINCHIP_READ(SHAR0+5);
}
void getSIPR(uint8_t * addr)
{
	addr[0] = IINCHIP_READ(SIPR0);
	addr[1] = IINCHIP_READ(SIPR0+1);
	addr[2] = IINCHIP_READ(SIPR0+2);
	addr[3] = IINCHIP_READ(SIPR0+3);
}

void setMR(uint8_t val)
{
	IINCHIP_WRITE(MR,val);
}

/**
@brief	This function gets Interrupt register in common register.
 */
uint8_t getIR( void )
{
   return IINCHIP_READ(IR);
}






/**
@brief	This function set the interrupt mask Enable/Disable appropriate Interrupt. ('1' : interrupt enable)

If any bit in IMR is set as '0' then there is not interrupt signal though the bit is
set in IR register.
*/
void setIMR(uint8_t mask)
{
	IINCHIP_WRITE(IMR,mask); // must be setted 0x10.
}







void Set_network(uint8_t * Mac,uint8_t * Ip,uint8_t * Subn ,uint8_t * Gat)
{
	Port_config();
	Reset_W5200();
	
	// Configuration Network Information of W5200
	// Setting the Wiznet W5100 Mode Register: 0x0000
	IINCHIP_WRITE(MR,0x80); // MR = 0b10000000;	
	// MAC ADDRESS
	setSHAR(Mac);
	// Local IP ADDRESS
	setSIPR(Ip);
	// Subnet Mask ADDRESS
    setSUBR(Subn);
	// GateWay ADDRESS
	setGAR(Gat);
	//Set PTR and RCR register
	//setRTR(6000);
	//setRCR(3);

}

