unsigned char ENC28J60_WRD(unsigned char cmd_opc, unsigned char data)
{
	ENC28J60_CS();
	SPIWR(cmd_opc);
	SPIWR(data);
	ENC28J60_DS();
	return(SPDR);
}

unsigned char ENC28J60_RD_MAMIREG(unsigned char addr)
{
	ENC28J60_CS();
	SPIWR(RCR|addr);			
	SPIWRD(DUMMY);
	SPIWRD(DUMMY);
	ENC28J60_DS();
	return(SPDR);
}

#define	ENC28J60_RD(addr)			ENC28J60_WRD((RCR|addr), DUMMY)
#define	ENC28J60_WR(addr, data)		ENC28J60_WRD((WCR|addr), data)
#define	ENC28J60_BFS(addr, reg)		ENC28J60_WRD((BFS|addr), reg)
#define	ENC28J60_BFC(addr, reg)		ENC28J60_WRD((BFC|addr), reg)

void ENC28J60_CLR_Buffer(void)
{
	ENC28J60_BANK_SEL(BANK0);
	
	ENC28J60_CS();
	SPIWR(WCR|EWRPTL);			//	0x00
	SPIWR(0);					//	EWRPTL		Buffer Write Pointer Low
	SPIWR(0);					//	EWRPTH		Buffer Write Pointer High
	SPIWR(0);					//	ETXSTL		Transmit Buffer Start Low
	SPIWR(0);					//	ETXSTH		Transmit Buffer Start High
	SPIWR(0xFF);				//	ETXNDL		Transmit Buffer End Low
	SPIWR(0x1F);				//	ETXNDH		Transmit Buffer End High
	ENC28J60_DS();
	
	ENC28J60_CS();
	SPIWR(WBM);
	for(unsigned int i = 0; i < 0x0200; i++)
	{
		SPIWR(0);
	}
	ENC28J60_DS();
}

unsigned char ENC28J60_SRC(void)				// System Reset Command (Soft Reset) 
{
	ENC28J60_CS();					// Enable
	SPIWR(0xFF);
	ENC28J60_DS();					// Disable
	_delay_ms(150);
	
	unsigned char i = 0;
	_delay_ms(1);	// Errata Page 3 - 2. Modue: Reset
	while(!(ENC28J60_RD(ESTAT) & CLKRDY) && (i <= 20))
	{
		i++;
		// UART Debugger Print
	}
	
	if(i < 20)
	{
		return(0);
	}
	else
	{
		return(1);
	}
}

unsigned char ENC28J60_PHYWR(unsigned char addr, unsigned char datah, unsigned char datal)
{
	// Datasheet Page 19 Section 3.3.2
	// To write to a PHY register:
	// 1. Write the address of the PHY register to write to
	// into the MIREGADR register.
	// 2. Write the lower 8 bits of data to write into the
	// MIWRL register.
	// 3. Write the upper 8 bits of data to write into the
	// MIWRH register. Writing to this register automatically
	// begins the MIIM transaction, so it must
	// be written to after MIWRL. The MISTAT.BUSY
	// bit becomes set.
	
	ENC28J60_BANK_SEL(BANK2);
	
	ENC28J60_CS();
	SPIWR(WCR|MIREGADR);
	SPIWR(addr);			//	MIREGADR
	SPIWR(DUMMY);			//	Reserved
	SPIWR(datal);			//	MIWRL
	SPIWR(datah);			//	MIWRH
	ENC28J60_DS();
	
	ENC28J60_BANK_SEL(BANK3);
	
	unsigned char i = 0;
	_delay_ms(1);
	while((ENC28J60_RD(MISTAT) & BUSY) && (i <= 20))
	{
		i++;
		// UART Debugger Print
	}
	
	if(i < 20)
	{
		return(0);
	}
	else
	{
		return(1);
	}
}

void ENC28J60_Full_RST(void)
{
	ENC28J60_BFS(ECON1, TXRST|RXRST);
	_delay_ms(5);
	ENC28J60_PHYWR(PHCON1,PRST,0);	//	PHY RST
	_delay_ms(5);
	ENC28J60_SRC();
	_delay_ms(5);
	ENC28J60_BFC(ECON1, TXRST|RXRST);
	_delay_ms(5);
	
	ENC28J60_CLR_Buffer();
}

void ENC28J60_Init(unsigned char MAC[6])
{
	ENC28J60_Full_RST();
	// Init TX/RX Buffer	Datasheet Section 6.1
	ENC28J60_BANK_SEL(BANK0);
	
	// defined in _ENC28J60_DEFS_H_
	// Errata Page 3 - 5. Module: Memory (Ethernet Buffer)
	#define RXSTART			0x0000		//	0x0000		0   0
	#define RXEND			4095		//	0x0FFF		15 255
	#define TXSTART			(RXEND+1)	//	0x1000		16  0
	#define TXEND			0x1FFF		//	0x1FFF		31 255
	
	ENC28J60_CS();
	SPIWR(WCR|ERDPTL);			//	0x00
	SPIWR(RXSTART&0xFF);		//	ERDPTL		Buffer Read Pointer Low
	SPIWR(RXSTART>>8);			//	ERDPTH		Buffer Read Pointer High
	SPIWR(TXSTART&0xFF);		//	EWRPTL		Buffer Write Pointer Low
	SPIWR(TXSTART>>8);			//	EWRPTH		Buffer Write Pointer High
	SPIWR(TXSTART&0xFF);		//	ETXSTL		Transmit Buffer Start Low
	SPIWR(TXSTART>>8);			//	ETXSTH		Transmit Buffer Start High
	SPIWR(TXEND&0xFF);			//	ETXNDL		Transmit Buffer End Low
	SPIWR(TXEND>>8);			//	ETXNDH		Transmit Buffer End High
	SPIWR(RXSTART&0xFF);		//	ERXSTL		Recive Buffer Start Low
	SPIWR(RXSTART>>8);			//	ERXSTH		Recive Buffer Start High
	SPIWR(RXEND&0xFF);			//	ERXNDL		Recive Buffer End Low
	SPIWR(RXEND>>8);			//	ERXNDH		Recive Buffer End High
	SPIWR(RXSTART&0xFF);		//	ERXRDPTL	Recive Buffer Read Pointer Low
	SPIWR(RXSTART>>8);			//	ERXRDPTH	Recive Buffer Read Pointer High
	SPIWR(RXSTART&0xFF);		//	ERXWRPTL	Recive Buffer Write Pointer Low
	SPIWR(RXSTART>>8);			//	ERXWRPTH	Recive Buffer Write Pointer High
	ENC28J60_DS();
	_delay_ms(5);
	
	ENC28J60_BANK_SEL(BANK1);
	ENC28J60_WR(ERXFCON, (UCEN|CRCEN|PMEN|MPEN|HTEN|BCEN));		//	addr 0x18

	ENC28J60_BANK_SEL(BANK2);
	ENC28J60_CS();
	SPIWR(WCR|MACON1);						//	0x00
	SPIWR(MARXEN|TXPAUS|RXPAUS);			//	MACON1		0x0D
	SPIWR(DUMMY);							//	MACON2?		0x00
	SPIWR(PADCFG2|PADCFG0|FRMLNEN|TXCRCEN|FULDPX);	//	MACON3		0x33
	SPIWR(DEFER);							//	MACON4		0x40
	SPIWR(0x15);							//	MABBIPG		0x15
	SPIWR(DUMMY);							//				0x00
	SPIWR(0x12);							//	MAIPGL		0x12
	SPIWR(0x00);							//	MAIPGH
	SPIWR(0x0F);							//	MACLCON1
	SPIWR(0x37);							//	MACLCON2
	SPIWR(0xEE);							//	MAMXFLL		MAC MaXimum Frame Length is set to 0x0500 or 1280byte (0x05EE 1518byte)
	SPIWR(0x05);							//	MAMXFLH
	ENC28J60_DS();
	_delay_ms(5);

	// MAC Init			Datasheet Section 6.5
	ENC28J60_BANK_SEL(BANK3);
	ENC28J60_CS();
	SPIWR(WCR|MAADR5);						//	0x00
	SPIWR(MAC[4]);
	SPIWR(MAC[5]);
	SPIWR(MAC[2]);
	SPIWR(MAC[3]);
	SPIWR(MAC[0]);
	SPIWR(MAC[1]);
	ENC28J60_DS();
	_delay_ms(5);
	
	//	PHY Init			Datasheet Section 6.6
	ENC28J60_PHYWR(PHCON1,PDPXMD,0);	//	PHY in Full-Duplex Mode
	ENC28J60_PHYWR(PHLCON,0b00000010,0b00010010);	//	LED Init 0x02 0x12
	
	ENC28J60_BFS(EIE, (INTIE|PKTIE));
	ENC28J60_BFC(ECON2, RXRST);
	_delay_ms(5);
	ENC28J60_BFC(ECON2, RXRST);
	//ENC28J60_BFS(ECON1, RXEN);
	//RXEN	UART-on keresztül kapcsolom ki/be a teszt alatt

}

my_16b ENC28J60_RX_Packet(unsigned char array[], unsigned int* package_length)
{
	unsigned int pckt_length = 0;
	my_16b	ret;
	
	ENC28J60_BANK_SEL(BANK0);
	
	ENC28J60_CS();
	SPIWR(RBM);
	//	reading next packet pointer (NPP) and Recieve Status Vector (RSV)
	my_32b		 	Next_Packet_Pointer,
					Receive_Status_Vector;
	Next_Packet_Pointer.b[0]		=	SPIWRD(DUMMY);
	Next_Packet_Pointer.b[1]		=	SPIWRD(DUMMY);
	Receive_Status_Vector.b[0]	=	SPIWRD(DUMMY);
	Receive_Status_Vector.b[1]	=	SPIWRD(DUMMY);
	Receive_Status_Vector.b[2]	=	SPIWRD(DUMMY);
	Receive_Status_Vector.b[3]	=	SPIWRD(DUMMY);
	
	
	// UART Print (NPP:	0xérték)
	// UART Print (RSV(low int):	0xérték)	csomag mérete
	// UART Print (RSV(high int):	0xérték)

	pckt_length = (Receive_Status_Vector.i[0]);					//	merging RSV byte 0 and 1 into integer (Byte Count)
	if(pckt_length%2 != 0)																//	if it's odd
	{
		pckt_length++;																	//	add +1
	}
	
	if(pckt_length == 0)
	{
		ENC28J60_DS();
		
		*package_length	= pckt_length;
	}
	else if(pckt_length < 1518)
	{
		for(unsigned int i = 0; i < pckt_length; i++)
		{
			array[i]	=	SPIWRD(DUMMY);
		}
		*package_length	= pckt_length;
		ENC28J60_DS();
		_delay_ms(1);
		
		ENC28J60_CS();
		SPIWR(WCR|ERXRDPTL);
		SPIWR(Next_Packet_Pointer.b[0]);					//	ERXRDPTL
		SPIWR(Next_Packet_Pointer.b[1]);					//	ERXRDPTH
		ENC28J60_DS();
	}
	else
	{
		ENC28J60_DS();
		
		*package_length	= 0;
		// ha tul nagy csomag -> Reset
		enc28j60_sreg &= ~ENC28J60_INIT;
	}
	
	ENC28J60_CS();
	SPIWR(BFS|ECON2);
	SPIWR(PKTDEC);
	ENC28J60_DS();
	
	ret.i = Receive_Status_Vector.i[0];
	return(ret);
}