/**
 Read a register

 @param Reg Register to read

 @return Registry Value
*/
char NRF24L01_R_ReadReg(char Reg) {
	char Result;

	NRF24L01_R_CS_LOW;
	SPI_R(Reg);
	Result = SPI_R(NOP);
	NRF24L01_R_CS_HIGH;

	return Result;
}
/**
 Returns the STATUS register

 @return STATUS Register
*/
char NRF24L01_R_Get_Status(void) {
	char Result;

	NRF24L01_R_CS_LOW;
	SPI_R(0x07);     
	Result = SPI_R(NOP);
	NRF24L01_R_CS_HIGH;

	return Result;
}
/**
 Returns the STATUS register and then modify a register

 @param Reg Register to change
 @param Value New value

 @return STATUS Register
*/
char NRF24L01_R_WriteReg(char Reg, char Value) {
	char Result;

	NRF24L01_R_CS_LOW;
	Result = SPI_R(Reg);
	
	SPI_R(Value);
	//PORTD.OUTSET = 1<<7;
	NRF24L01_R_CS_HIGH;

	return Result;
}
/**
 Returns the STATUS register and then write "n" registers

 @param Reg Registers to change
 @param Buf Pointer to a buffer
 @param Size Buffer Size

 @return STATUS Register
*/
char NRF24L01_R_WriteRegBuf(char Reg, char *Buf, int Size) {
	int i;
	char Result;

	NRF24L01_R_CS_LOW;
	Result = SPI_R(Reg);

	for (i = 0; i < Size; i++) {
		SPI_R(Buf[i]);
	}
	NRF24L01_R_CS_HIGH;

	return Result;
}
/**
 Returns the STATUS register and then read "n" registers

 @param Reg Register to read
 @param Buf Pointer to a buffer
 @param Size Buffer Size

 @return STATUS Register
*/
char NRF24L01_R_ReadRegBuf(char Reg, char *Buf, int Size) {
	int i;
	char Result;

	NRF24L01_R_CS_LOW;
	Result = SPI_R(Reg);

	for (i = 0; i < Size; i++) {
		Buf[i] = SPI_R(NOP);
	}

	NRF24L01_R_CS_HIGH;

	return Result;
}
/**
* \brief Power Off COG Driver
* \note For detailed flow and description, please refer to the COG G2 document Section 6.
*
* \param EPD_type_index The defined EPD size
*/
uint8_t EPD_power_off(uint8_t EPD_type_index) {
	uint8_t y;		

	if(EPD_type_index==EPD_144 || EPD_type_index==EPD_200) 	{
		border_dummy_line(EPD_type_index);
		dummy_line(EPD_type_index);
	}

	delay_ms (25);
	if(EPD_type_index==EPD_270)	{
		EPD_border_low();
		delay_ms (200);
		EPD_border_high();
	}

	//Check DC/DC
	if((SPI_R(0x0F,0x00) & 0x40) == 0x00) return ERROR_DC;
	
	//Turn on Latch Reset
	epd_spi_send_byte (0x03, 0x01);
	//Turn off OE
	epd_spi_send_byte (0x02, 0x05);
	//Power off charge pump Vcom
	epd_spi_send_byte (0x05, 0x0E);
	//Power off charge pump neg voltage
	epd_spi_send_byte (0x05, 0x02);
	//Turn off all charge pump 
	epd_spi_send_byte (0x05, 0x00);
	//Turn off OSC
	epd_spi_send_byte (0x07, 0x0D);
	
	epd_spi_send_byte (0x04, 0x83);
	delay_ms(120);
	epd_spi_send_byte (0x04, 0x00);
	
	epd_spi_detach ();
	EPD_cs_low();
	EPD_rst_low();
	EPD_Vcc_turn_off ();
	EPD_border_low();
	delay_ms (10);
		
	for(y=0;y<10;y++)
	{
		EPD_discharge_high ();		
		delay_ms (10);		
		EPD_discharge_low ();	
		delay_ms (10);	
	}
	return RES_OK;
}
/**
* \brief Initialize COG Driver
* \note For detailed flow and description, please refer to the COG G2 document Section 4.
*
* \param EPD_type_index The defined EPD size
*/
uint8_t EPD_initialize_driver (uint8_t EPD_type_index) {
	
	uint16_t i;
	// Empty the Line buffer
	for (i = 0; i <= LINE_BUFFER_DATA_SIZE; i ++) {
		COG_Line.uint8[i] = 0x00;
	}
	// Determine the EPD size for driving COG
	COG_driver_EPDtype_select(EPD_type_index);

	// Sense temperature to determine Temperature Factor
	set_temperature_factor(EPD_type_index);
	i = 0;
	
	while (EPD_IsBusy()) {
		if((i++) >= 0x0FFF) return ERROR_BUSY;
	}
	
	//Check COG ID
	if((SPI_R(0x72,0x00) & 0x0f) !=0x02) return ERROR_COG_ID;

	//Disable OE
	epd_spi_send_byte(0x02,0x40);	

	//Check Breakage
	if((SPI_R(0x0F,0x00) & 0x80) != 0x80) return ERROR_BREAKAGE;
	
	//Power Saving Mode
 	epd_spi_send_byte(0x0B, 0x02);

	//Channel Select
	epd_spi_send (0x01, (uint8_t *)&COG_parameters[EPD_type_index].channel_select, 8);

	//High Power Mode Osc Setting
	epd_spi_send_byte(0x07,0xD1);

	//Power Setting
	epd_spi_send_byte(0x08,0x02);

	//Set Vcom level
	epd_spi_send_byte(0x09,0xC2);

	//Power Setting
	epd_spi_send_byte(0x04,0x03);

	//Driver latch on
	epd_spi_send_byte(0x03,0x01);

	//Driver latch off
	epd_spi_send_byte(0x03,0x00);

	delay_ms(5);

	//Chargepump Start
	i=0;
	do {
		//Start chargepump positive V
		//VGH & VDH on
		epd_spi_send_byte(0x05,0x01);

		delay_ms(240);

		//Start chargepump neg voltage
		//VGL & VDL on
		epd_spi_send_byte(0x05,0x03);

		delay_ms(40);

		//Set chargepump
		//Vcom_Driver to ON
		//Vcom_Driver on
		epd_spi_send_byte(0x05,0x0F);

		delay_ms(40);

		//Check DC/DC
		if((SPI_R(0x0F,0x00) & 0x40) != 0x00) break;	
		
	}while((i++) != 4);
	
	if(i>=4) 
	{
		//Output enable to disable
		epd_spi_send_byte(0x02,0x40);
		return ERROR_CHARGEPUMP;
	}
	else  return RES_OK;
}
/**
 Used in TX mode. Disables AUTOACK on this
 specific packet.
*/
void NRF24L01_R_NOACK_TX(void)
 {
	NRF24L01_R_CS_LOW;
	SPI_R(W_TX_PAYLOAD_NOACK);
	NRF24L01_R_CS_HIGH;
}
/**
 Empty the receive buffer
*/
void NRF24L01_R_Flush_RX(void) {
	NRF24L01_R_CS_LOW;
	SPI_R(FLUSH_RX);
	NRF24L01_R_CS_HIGH;
}