#ifndef F_CPU
#define F_CPU 20000000
#endif

#include <avr/io.h>
#include <util/delay.h>
#include <stdlib.h>
#include <stdio.h> 
#include <string.h> 
#include <avr/interrupt.h>



#define CSN_H 	PORTB|=(1<<PORTB0);	// CSN high
#define CSN_L	PORTB&=~(1<<PORTB0);	// CSN low
#define CE_H 	PORTD|=(1<<PORTD7);	// CE high
#define CE_L	PORTD&=~(1<<PORTD7);	// CE low

#define W_REG	0b00100000	// write

#define CONFIG 	0x00
#define EN_AA	0x01
#define EN_RXADDR	0x02
#define RF_SETUP	0x06
#define STATUS		0x07
#define RX_PW_P0	0x11
#define PAYLOAD_WIDTH	0x20	//32byte payload

#define RECEIVER 	0
#define TRANSMITTER	1
#define NOP 		0xFF

#define R_RX_PAYLOAD	0b01100001
#define W_TX_PAYLOAD	0b10100000

#define RX_ADDR_P0	0x0A	// register address
#define TX_ADDR		0x10

#define RX_ADRS_P0	0x741DE9E933 	// NRF24L01 module address
#define TX_ADRS		0x741DE9E933	// https://www.random.org/cgi-bin/randbyte?nbytes=5&format=h

///////////////////////////////////////////////////////////////////////////////////////////////

volatile uint8_t is_data_received=0;	//0:no	1:yes
uint8_t data_to_send[PAYLOAD_WIDTH];
uint8_t data_received[PAYLOAD_WIDTH];
volatile uint8_t nrf_status=0; // nrf status register
volatile uint8_t check_nrf_status=0;	// counter for decrease 1kHz to 50Hz
volatile int16_t timeout;	// counter interrupt decrements to time out, signed to be able to go negative and set to 0
///////////////////////////////////////////////////////////////////////////////////////////////
void init_timer2(void)	// timer ISR
{
	TCCR2B|=(1<<CS22);	// 64 prescaler -> 1.024 ms
	TCNT2=0;	// init counter
	TIMSK2|=(1<<TOIE2);	// enable overflow interrupt
	sei();
}//init_timer2

void initSPI(void)
{
	DDRB|=0b00101000;	//5:sck, 4:miso, 3:mosi
	SPCR=	(0<<SPIE)|	// spi interrupt enable
			(1<<SPE)|	// spi enable
			(0<<DORD)|	// data order 0->MSbit first, 1->LSbit first
			(1<<MSTR)|	// master
			(0<<CPHA)|	// clock phase
			(0<<CPOL)|	// clock polarity
			(1<<SPR1)|	// 
			(0<<SPR0);	// prescale 64
}//spi init

uint8_t spi_r_w(uint8_t send) // SPI
{
	uint8_t temp=0;
	_delay_us(1);
	cli();
	SPDR = send; //send
	while(!(SPSR & (1<<SPIF)))
	temp=SPDR;
	sei();
	return temp;
}//spi

void CE(void)
{
	CE_H;	// CE high
	_delay_us(15);//15, min=10us
	CE_L;	// CE low
}//CE toggle

void init_nrf24l01(void)	// init only, need to set rx/tx mode too !!!
{
	CSN_L;
	spi_r_w(EN_AA|W_REG);	// disable auto-ack on all channel
	spi_r_w(0b00000000);
	CSN_H;
	CSN_L;
	spi_r_w(EN_RXADDR|W_REG);	// enable channel 0
	spi_r_w(0b00000001);
	CSN_H;
	CSN_L;
	spi_r_w(RF_SETUP|W_REG);	// 250kbps, 0dBm tx power
	spi_r_w(0b00100110);
	CSN_H;
	CSN_L;
	spi_r_w(RX_PW_P0|W_REG);	// payload width (0-32byte)
	spi_r_w(PAYLOAD_WIDTH);
	CSN_H;

	// SET ADDRESS !!!
	CSN_L;
	spi_r_w(RX_ADDR_P0|W_REG);	// P0 pipe RX address
	spi_r_w(RX_ADRS_P0 & 0xFF);
	spi_r_w(RX_ADRS_P0>>8 & 0xFF);
	spi_r_w(RX_ADRS_P0>>16 & 0xFF);
	spi_r_w(RX_ADRS_P0>>24 & 0xFF);
	spi_r_w(RX_ADRS_P0>>32 & 0xFF);
	CSN_H;

	CSN_L;
	spi_r_w(TX_ADDR|W_REG);	// TX address
	spi_r_w(TX_ADRS & 0xFF);
	spi_r_w(TX_ADRS>>8 & 0xFF);
	spi_r_w(TX_ADRS>>16 & 0xFF);
	spi_r_w(TX_ADRS>>24 & 0xFF);
	spi_r_w(TX_ADRS>>32 & 0xFF);
	CSN_H;
}//init_nrf24l01

void set_mode_nrf24l01(uint8_t mode)// 0:Rx 1:Tx
{
	if(mode)//Tx
	{
		CSN_L;
		spi_r_w(CONFIG|W_REG);
		spi_r_w(0b01111110);	// No interrupt reflected, 2byte crc, power up, tx mode
		CSN_H;
		CE_L;
	}
	else//Rx
	{
		_delay_ms(10);// ha küldés után egyből váltok, nem küldi el.
	
		CSN_L;
		spi_r_w(CONFIG|W_REG);
		spi_r_w(0b01111111);	// No interrupt reflected, 2byte crc, power up, rx mode
		CSN_H;
		CE_H;					// Start receive
	}
	_delay_us(150);// time to set mode
}//set_mode_nrf24l01

void read_data_nrf24l01(void)	// reads and puts data into data_received
{
	is_data_received=0;	
	CE_L;
	CSN_L;
	spi_r_w(R_RX_PAYLOAD);
	for(uint8_t i=0;i<PAYLOAD_WIDTH;i++)
	{
		data_received[i]=spi_r_w(NOP);
	}
	CSN_H;
	CE_H;

	CSN_L;
	spi_r_w(STATUS|W_REG);
	spi_r_w(0b01110000);	//reset interrupt
	CSN_H;

}//read_data_nrf24l01

void send_data_nrf24l01(void)	// send data from data_to_send
{
	CSN_L;
	spi_r_w(STATUS|W_REG);
	spi_r_w(0b01110000);	//reset interrupt
	CSN_H;

	CSN_L;
	spi_r_w(W_TX_PAYLOAD);
	for(uint8_t i=0;i<PAYLOAD_WIDTH;i++)
	{
		spi_r_w(data_to_send[i]);
	}
	CSN_H;
	_delay_us(50);
	CE();
}//send_data_nrf24l01


//////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////

int main(void)
{

	DDRD|=(1<<DDD7);//CE output
	DDRB|=(1<<DDB0);//CS output
	CSN_H;
	
	initSPI();
	init_timer2();			// ~1ms

	_delay_ms(500);
	init_nrf24l01();		// 

	set_mode_nrf24l01(RECEIVER);


	while(1)
	{


		while(!is_data_received);
									
		read_data_nrf24l01();		
						
		for(uint8_t i=0; i<PAYLOAD_WIDTH; i++){
			data_to_send[i]=data_received[i];	// send data back
		}
			
		_delay_ms(50);// let remote controller change to receiver mode
			
		set_mode_nrf24l01(TRANSMITTER);	
		send_data_nrf24l01();

		set_mode_nrf24l01(RECEIVER);

	}//while
}//main

//////////////////////////////////////////////////////////////////////////////////////////////
ISR(TIMER2_OVF_vect)
{
	timeout--;
	if(timeout<0) timeout=0;

	check_nrf_status++;
	if(check_nrf_status>=20)// ~10ms/~100Hz
	{
		check_nrf_status=0;
		CSN_L;
		nrf_status = spi_r_w(NOP);
		CSN_H;
		if(nrf_status & (0b01000000))
		{is_data_received=1;}
	}
}//timer2_overflow
