This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Problem with the nRF24L01+ when trying to swap between Transmitter and Receiver

Hi all,

The setup that I am aiming for has a number of nodes, which will send the IMU data to a central base station. The communication is achieved using a bunch of nRF24L01+ modules.
So far I have been able to transmit and receive the data from one node to the base station. The problem starts when I want to swap the roles of the node and the base station so that I can transmit and receive the data bi-directionally.
Initially, the base station (configured as TX) sends an 8-byte data to the node (configured as RX). After checking the received data, the node (configured as TX) sends back the IMU data to the base station (configured as RX).

Somehow, after the node receives the data from the base station, it is never able to send the IMU data back to the base station. The TX is done with polling and the RX is done with interrupts.
Can anyone of you point me in the right direction? Thanks!

Additional info:
The nRF (module from Sparkfun) is interfaced with Atmega32U4. IDE is Atmel Studio v7 in Windows platform.

Base station code:

/*
 * Base_Station.c
 *
 * Created: 21-Nov-18 6:18:12 PM
 * Author : Frederic Philips
 */ 
#include <avr/io.h>
#include <avr/sfr_defs.h>
#include <stdint.h>
#include <stdlib.h>
#define F_CPU 16000000UL	//16 MHz frequency
#define BAUD  57600
#include <util/setbaud.h>
#include <util/delay.h>
#include <avr/interrupt.h>

#include "nrf.h"

#define MOSI		2
#define MISO		3
#define SCLK		1
#define CSN		0
#define CE		4

#define PAYLOAD_LEN	8

uint8_t BS_payload_TX[PAYLOAD_LEN] = {0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA};
uint8_t BS_payload_RX[PAYLOAD_LEN];

//0 - TX; 1 - RX
volatile uint8_t mode = 0;

void nRF_TX_mode(void);
void nRF_RX_mode(void);
void Flush_tx(void);
void Flush_rx(void);
void reset(void);
void Payload_RX(uint8_t *data_out, uint8_t *data_in, uint8_t len);
uint8_t nrf24_getStatus(void);
uint8_t nrf24_isSending(void);

/************************************************************************************
** AVR_Init function:
** - Start-up delay
** - Initializes the I/O peripherals
*************************************************************************************/
void AVR_Init(void)
{
	_delay_ms(750);		//Short pause after BNO055 Power-On Reset(Mandatory)
	DDRD |= _BV(1);		//Set TX as output
	DDRD &= ~(_BV(0));	//Set RX as input
}

/************************************************************************************
** USART Reference:
** - ATmega32U4 Datasheet - Rev. CORP072610(Pg.186)
** - AVR Microcontroller and Embedded Systems - Mazidi(Pg.395)
** - Embedded C Programming and the Atmel AVR - Barnett(Pg.132)
*************************************************************************************
** To initialize the UART, the following steps are to be followed:
** - Set the Baud rate(use <util/setbaud.h>, which depends on the macros F_CPU & BAUD)
** - Disable double speed(2x) mode
** - Set the no. of data bits(8/9 bits), stop bit(1/2) and parity bit(None/Odd/Even)
** - Set the USART mode(Synchronous/Asynchronous/Asynchronous 2x)
** - Enable Receiver & Transmitter(Set RXEN & TXEN bits in UCSRB register)
*************************************************************************************/
void UART_Init(void)
{
	DDRD |= _BV(1);		//Set TX as output
	DDRD &= ~(_BV(0));	//Set RX as input

	//Set the BAUD rate(Ref. ATmega32U4 Datasheet Pg.189, Table 18-1)
	//To hard-code the Baud rate, Ref. Tables 18-9 to 18-12 in Pgs. 210 - 213
	UBRR1 = ((F_CPU / (16UL * BAUD)) - 1);
	
	//Disables 2x speed
	UCSR1A &= ~(_BV(U2X1));
	
	//Enable 8-bit character size, one stop-bit, no parity & asynchronous mode
	UCSR1C |= _BV(UCSZ11) | _BV(UCSZ10);
	
	//Enable Transmitter & Receiver
	UCSR1B |= _BV(TXEN1) | _BV(RXEN1);
}

/************************************************************************************
** UART_Tx function:
** - Transmits the ADC data via the USB Serial
** - The data is received & displayed in a Hyperterminal
*************************************************************************************/
void UART_Tx(unsigned char data)
{
	loop_until_bit_is_set(UCSR1A, UDRE1);	//Wait until buffer is empty
	UDR1 = data;				//Send data	
}

void Init_SPI()
{
	//Set the output pin(s) for SPI
	DDRB |= _BV(CE);	//CE
	DDRB |= _BV(CSN);	//CSN
	DDRB |= _BV(MOSI);  	//MOSI
	DDRB |= _BV(SCLK);  	//SCLK

	//Set the input pin(s) for SPI
	DDRB &= ~_BV(MISO); 	//MISO

	
	SPCR |= ((1 << SPE) | (1 << MSTR) | (1 << SPR0));	//Enable SPI as master
	SPCR &= (~_BV(SPI2X) & ~_BV(SPR1)); 		   	//Set clock rate but not too important
	
	PORTB |= _BV(CSN);	//CSN high
	PORTB &= ~_BV(CE);	//CE low
}

unsigned char spi_tranceiver(unsigned char data)
{
	// Load data into the buffer
	SPDR = data;
	
	//Wait until transmission complete
	while(!(SPSR & (1 << SPIF)));   

	//Return received data
	return(SPDR);
}

unsigned char Read_Byte(unsigned char reg)
{
	_delay_us(10);
	PORTB &= ~_BV(CSN);	//CSN low
	_delay_us(10);
	spi_tranceiver(R_REGISTER + reg);
	_delay_us(10);
	reg = spi_tranceiver(NOP);
	_delay_us(10);
	PORTB |= _BV(CSN);	//CSN high
	return reg;
}

void Write_byte(unsigned char reg, unsigned char data)
{
	_delay_us(10);
	PORTB &= ~_BV(CSN);	//CSN low
	_delay_us(10);
	spi_tranceiver(W_REGISTER + reg);
	_delay_us(10);
	spi_tranceiver(data);
	_delay_us(10);
	PORTB |= _BV(CSN);	//CSN high
}

void Init_nrf(void)
{
	//Enable auto-acknowledgment for data pipe 0
	Write_byte(EN_AA, 0x01);
	
	//Enable data pipe 0
	Write_byte(EN_RXADDR, 0x01);

	//Set address width to 5 bytes
	Write_byte(SETUP_AW, 0x03);
	
	//Set channel frequency to 2.505GHz
	Write_byte(RF_CH, 0x69);
	
	//Set data rate to 2Mbps and 0dB gain
	Write_byte(RF_SETUP, 0x0E);
	
	//Enable W_TX_PAYLOAD_NOACK command
//	Write_byte(FEATURE, 0x01);
	
	//Set the 5-bytes receiver address as 0x01 0x02 0x03 0x04 0x05
	_delay_us(10);
	PORTB &= ~_BV(CSN);	//CSN low
	_delay_us(10);
	//Setup p0 pipe address for receiving
	spi_tranceiver(W_REGISTER + RX_ADDR_P0);
	_delay_us(10);
	spi_tranceiver(0x11);
	_delay_us(10);
	spi_tranceiver(0x12);
	_delay_us(10);
	spi_tranceiver(0x13);
	_delay_us(10);
	spi_tranceiver(0x14);
	_delay_us(10);
	spi_tranceiver(0x15);
	_delay_us(10);
	PORTB |= _BV(CSN);	//CSN high
	
	//Set the 5-bytes transmitter address as 0x01 0x02 0x03 0x04 0x05
	_delay_us(10);
	PORTB &= ~_BV(CSN);	//CSN low
	_delay_us(10);
	//Setup the transmitter address
	spi_tranceiver(W_REGISTER + TX_ADDR);
	_delay_us(10);
	spi_tranceiver(0xAA);
	_delay_us(10);
	spi_tranceiver(0xBB);
	_delay_us(10);
	spi_tranceiver(0xCC);
	_delay_us(10);
	spi_tranceiver(0xDD);
	_delay_us(10);
	spi_tranceiver(0xEE);
	_delay_us(10);
	PORTB |= _BV(CSN);	//CSN high
	
	//Set the payload width as 8-bytes
	Write_byte(RX_PW_P0, 0x08);
	
	//Set the retransmission delay to 750us with 15 retries
	Write_byte(SETUP_RETR, 0x2F);
	
	//Boot the nrf as TX and mask the maximum retransmission interrupt(disable)
	//Enable CRC and set the length to 2-bytes
	nRF_TX_mode();
	
	_delay_ms(10);		//10ms delay after power-up
}

void nRF_TX_mode(void)
{
	Flush_tx();							 //Flush TX FIFO
	Write_byte(STATUS, (1 << RX_DR) | (1 << TX_DS) | (1 << MAX_RT)); //Reset status
	PORTB &= ~_BV(CE);						 //CE low - Standby-I
	//Power-up and set as TX
	Write_byte(CONFIG, Read_Byte(CONFIG) | (1 << PWR_UP) | (0 << PRIM_RX));
	//Mask TX_DR and MAX_RT interrupts
	Write_byte(CONFIG, Read_Byte(CONFIG) | (1 << MASK_TX_DS) | (1 << MASK_MAX_RT));
	_delay_us(150);
}

void nRF_RX_mode(void)
{
	Flush_rx();							 //Flush RX FIFO
	Write_byte(STATUS, (1 << RX_DR) | (1 << TX_DS) | (1 << MAX_RT)); //Reset status
	PORTB &= ~_BV(CE); 						 //CE low
	//Power-up as set as RX
	Write_byte(CONFIG, Read_Byte(CONFIG) | (1 << PWR_UP) | (1 << PRIM_RX));
	//Mask TX_DR and MAX_RT interrupts
	Write_byte(CONFIG, Read_Byte(CONFIG) | (1 << MASK_TX_DS) | (1 << MASK_MAX_RT));
	PORTB |= _BV(CE);  						 //CE high
	_delay_us(150);
}

void Flush_tx(void)
{
	_delay_us(10);
	PORTB &= ~_BV(CSN);	//CSN low
	_delay_us(10);
	spi_tranceiver(FLUSH_TX);
	_delay_us(10);
	PORTB |= _BV(CSN);	//CSN high
	_delay_us(10);
}

void Flush_rx(void)
{
	_delay_us(10);
	PORTB &= ~_BV(CSN);
	_delay_us(10);
	spi_tranceiver(FLUSH_RX);
	_delay_us(10);
	PORTB |= _BV(CSN);
	_delay_us(10);
}

void Payload_TX(uint8_t* data, uint8_t len)
{
	uint8_t i;
	
	for(i = 0; i < len; i++)
	{
		spi_tranceiver(BS_payload_TX[i]);
	}
}

void transmit_data(unsigned char *tdata)
{
	Flush_tx();
	PORTB &= ~_BV(CSN); //CSN low
	_delay_us(10);
	//Transmit payload with ACK enabled
	spi_tranceiver(W_TX_PAYLOAD);
	_delay_us(10);
	Payload_TX(BS_payload_TX, PAYLOAD_LEN);
	_delay_us(10);
	PORTB |= _BV(CSN);  //CSN high
	_delay_us(10);      //Need at least 10us before sending
	PORTB |= _BV(CE);   //CE high
	_delay_us(10);      //Hold CE high for at least 10us and not longer than 4ms
	PORTB &= ~_BV(CE);  //CE low
}

uint8_t nrf24_getStatus()
{
	uint8_t rv;
	PORTB &= ~_BV(CSN); //CSN low
	rv = spi_tranceiver(NOP);
	PORTB |= _BV(CSN);  //CSN high
	return rv;
}

uint8_t nrf24_isSending()
{
	uint8_t status;

	/* read the current status */
	status = nrf24_getStatus();
	
	/* if sending successful (TX_DS) or max retries exceeded (MAX_RT). */
	if((status & ((1 << TX_DS)  | (1 << MAX_RT))))
	{
		return 0; /* false */
	}

	return 1; /* true */
}

void Init_INT6(void)
{
	EICRB &= ~(1 << ISC60) | (1 << ISC61);	//INT6 active when low
	EIMSK |= (1 << INT6);			//Enable INT6
	sei();					//Enable global interrupts
}

ISR(INT6_vect)
{
	cli();					//Disable global interrupt
	
	PORTB &= ~_BV(CE); 			//Stop listening
	// Pull down chip select 
	PORTB &= ~_BV(CSN); //CSN low
	_delay_us(10);
	// Send command to read RX payload 
	spi_tranceiver(R_RX_PAYLOAD);
	_delay_us(10);
	// Read payload 
	Payload_RX(BS_payload_RX, BS_payload_RX, PAYLOAD_LEN);
	_delay_us(10);
	// Pull up chip select
	PORTB |= _BV(CSN);  //CSN high
	_delay_us(10);
	// Reset status register 
	Write_byte(STATUS, (1 << RX_DR));
	mode = 0;	    //Set as TX
}

/* send and receive multiple bytes over SPI */
void Payload_RX(uint8_t *data_out, uint8_t *data_in, uint8_t len)
{
	uint8_t i;

	for(i = 0; i < len; i++)
	{
		data_in[i] = spi_tranceiver(data_out[i]);
		UART_Tx(data_in[i]);   //Send the received data to UART
	}
}

void reset(void)
{
	_delay_us(10);
	//Reset IRQ-flags in status register
    	Write_byte(STATUS, 0x70);   
	_delay_us(10);
}

int main(void)
{
	AVR_Init();
	Init_SPI();
	Init_nrf();
	UART_Init();
	Init_INT6();
	
	//0 - TX; 1 - RX
	int8_t mode = 0;
	
	//Disable Interrupt initially
	cli();

	//Endless Loop
	while(1)
	{
		if(mode == 0) //TX
		{
			//Configure as Transmitter
			nRF_TX_mode();
		
//			UART_Tx(0x55);   	//Send BP1 to UART
		
			transmit_data(BS_payload_TX);
			while(nrf24_isSending());
			reset();

//			UART_Tx(0x66);   	//Send BP2 to UART
		
			//Configure as Receiver
			mode = 1;		//Set as RX
			nRF_RX_mode();
			PORTB |= _BV(CE);	//Start listening again	
			sei();		

//			UART_Tx(0x77);   	//Send BP3 to UART			
		}

//		UART_Tx(0x88);   		//Send BP4 to UART
	}
}

Node code:

/*
 * Node_1.c
 *
 * Created: 21-Nov-18 6:21:39 PM
 * Author : Frederic Philips
 */ 
#include <avr/io.h>
#include <avr/sfr_defs.h>
#include <stdint.h>
#include <stdlib.h>
#define F_CPU 16000000UL	//16 MHz frequency
#define BAUD  57600
#include <util/setbaud.h>
#include <util/delay.h>
#include <avr/interrupt.h>

#include "Test_BNO055.h"
#include "i2cmaster.h"
#include "nrf.h"

#define MOSI		2
#define MISO		3
#define SCLK		1
#define CSN		0
#define CE		4

#define PAYLOAD_LEN	8

uint8_t N1_payload_TX[PAYLOAD_LEN];
uint8_t N1_payload_RX[PAYLOAD_LEN];

volatile uint8_t RX_Payload_cnt;

void nRF_TX_mode(void);
void nRF_RX_mode(void);
void Flush_tx(void);
void Flush_rx(void);
void reset(void);
void Payload_RX(uint8_t *data_out, uint8_t *data_in, uint8_t len);
uint8_t nrf24_getStatus(void);
uint8_t nrf24_isSending(void);

/************************************************************************************
** AVR_Init function:
** - Start-up delay
** - Initializes the I/O peripherals
*************************************************************************************/
void AVR_Init(void)
{
	_delay_ms(750);		//Short pause after BNO055 Power-On Reset(Mandatory)
	DDRD |= _BV(1);		//Set TX as output
	DDRD &= ~(_BV(0));	//Set RX as input

	//Initialize TWI data
	TWI_data = 0;
}

/************************************************************************************
** USART Reference:
** - ATmega32U4 Datasheet - Rev. CORP072610(Pg.186)
** - AVR Microcontroller and Embedded Systems - Mazidi(Pg.395)
** - Embedded C Programming and the Atmel AVR - Barnett(Pg.132)
*************************************************************************************
** To initialize the UART, the following steps are to be followed:
** - Set the Baud rate(use <util/setbaud.h>, which depends on the macros F_CPU & BAUD)
** - Disable double speed(2x) mode
** - Set the no. of data bits(8/9 bits), stop bit(1/2) and parity bit(None/Odd/Even)
** - Set the USART mode(Synchronous/Asynchronous/Asynchronous 2x)
** - Enable Receiver & Transmitter(Set RXEN & TXEN bits in UCSRB register)
*************************************************************************************/
void UART_Init(void)
{
	DDRD |= _BV(1);		//Set TX as output
	DDRD &= ~(_BV(0));	//Set RX as input

	//Set the BAUD rate(Ref. ATmega32U4 Datasheet Pg.189, Table 18-1)
	//To hard-code the Baud rate, Ref. Tables 18-9 to 18-12 in Pgs. 210 - 213
	UBRR1 = ((F_CPU / (16UL * BAUD)) - 1);
	
	//Disables 2x speed
	UCSR1A &= ~(_BV(U2X1));
	
	//Enable 8-bit character size, one stop-bit, no parity & asynchronous mode
	UCSR1C |= _BV(UCSZ11) | _BV(UCSZ10);
	
	//Enable Transmitter & Receiver
	UCSR1B |= _BV(TXEN1) | _BV(RXEN1);
}

/************************************************************************************
** UART_Tx function:
** - Transmits the ADC data via the USB Serial
** - The data is received & displayed in a Hyperterminal
*************************************************************************************/
void UART_Tx(unsigned char data)
{
	loop_until_bit_is_set(UCSR1A, UDRE1);	//Wait until buffer is empty
	UDR1 = data;				//Send data
}

void BNO_Read_Quaternions(void)
{
	i2c_start_wait(BNO055_ADDRESS+I2C_WRITE);	//Set device address and read mode
	i2c_write(BNO055_QUATERNION_DATA_W_LSB_ADDR);	//Access LSB of Quaternion_W value
	i2c_rep_start(BNO055_ADDRESS+I2C_READ);		//Set device address and read mode
	N1_payload_TX[0] = i2c_readNak();
	UART_Tx(N1_payload_TX[0]);
	i2c_stop();

	i2c_start_wait(BNO055_ADDRESS+I2C_WRITE);	//Set device address and read mode
	i2c_write(BNO055_QUATERNION_DATA_W_MSB_ADDR);	//Access MSB of Quaternion_W value
	i2c_rep_start(BNO055_ADDRESS+I2C_READ);		//Set device address and read mode
	N1_payload_TX[1] = i2c_readNak();
	UART_Tx(N1_payload_TX[1]);
	i2c_stop();

	i2c_start_wait(BNO055_ADDRESS+I2C_WRITE);	//Set device address and read mode
	i2c_write(BNO055_QUATERNION_DATA_X_LSB_ADDR);	//Access LSB of Quaternion_X value
	i2c_rep_start(BNO055_ADDRESS+I2C_READ);		//Set device address and read mode
	N1_payload_TX[2] = i2c_readNak();
	UART_Tx(N1_payload_TX[2]);
	i2c_stop();

	i2c_start_wait(BNO055_ADDRESS+I2C_WRITE);	//Set device address and read mode
	i2c_write(BNO055_QUATERNION_DATA_X_MSB_ADDR);	//Access MSB of Quaternion_X value
	i2c_rep_start(BNO055_ADDRESS+I2C_READ);		//Set device address and read mode
	N1_payload_TX[3] = i2c_readNak();
	UART_Tx(N1_payload_TX[3]);
	i2c_stop();
		
	i2c_start_wait(BNO055_ADDRESS+I2C_WRITE);	//Set device address and read mode
	i2c_write(BNO055_QUATERNION_DATA_Y_LSB_ADDR);	//Access LSB of Quaternion_Y value
	i2c_rep_start(BNO055_ADDRESS+I2C_READ);		//Set device address and read mode
	N1_payload_TX[4] = i2c_readNak();
	UART_Tx(N1_payload_TX[4]);
	i2c_stop();
		
	i2c_start_wait(BNO055_ADDRESS+I2C_WRITE);	//Set device address and read mode
	i2c_write(BNO055_QUATERNION_DATA_Y_MSB_ADDR);	//Access MSB of Quaternion_Y value
	i2c_rep_start(BNO055_ADDRESS+I2C_READ);		//Set device address and read mode
	N1_payload_TX[5] = i2c_readNak();
	UART_Tx(N1_payload_TX[5]);
	i2c_stop();
		
	i2c_start_wait(BNO055_ADDRESS+I2C_WRITE);	//Set device address and read mode
	i2c_write(BNO055_QUATERNION_DATA_Z_LSB_ADDR);	//Access LSB of Quaternion_Z value
	i2c_rep_start(BNO055_ADDRESS+I2C_READ);		//Set device address and read mode
	N1_payload_TX[6] = i2c_readNak();
	UART_Tx(N1_payload_TX[6]);
	i2c_stop();
		
	i2c_start_wait(BNO055_ADDRESS+I2C_WRITE);	//Set device address and read mode
	i2c_write(BNO055_QUATERNION_DATA_Z_MSB_ADDR);	//Access MSB of Quaternion_Z value
	i2c_rep_start(BNO055_ADDRESS+I2C_READ);		//Set device address and read mode
	N1_payload_TX[7] = i2c_readNak();
	UART_Tx(N1_payload_TX[7]);
	i2c_stop();	
}

void Init_SPI()
{
	//Set the output pin(s) for SPI
	DDRB |= _BV(CE);	//CE
	DDRB |= _BV(CSN);	//CSN
	DDRB |= _BV(MOSI);  	//MOSI
	DDRB |= _BV(SCLK);  	//SCLK

	//Set the input pin(s) for SPI
	DDRB &= ~_BV(MISO); 	//MISO

	
	SPCR |= ((1 << SPE) | (1 << MSTR) | (1 << SPR0));	//Enable SPI as master
	SPCR &= (~_BV(SPI2X) & ~_BV(SPR1)); 		   	//Set clock rate but not too important
	
	PORTB |= _BV(CSN);	//CSN high
	PORTB &= ~_BV(CE);	//CE low
	_delay_ms(10);		//10ms delay
}

unsigned char spi_tranceiver(unsigned char data)
{
	//Load data into the buffer
	SPDR = data;
	
	//Wait until transmission complete
	while(!(SPSR & (1 << SPIF)));

	//Return received data
	return(SPDR);
}

unsigned char Read_Byte(unsigned char reg)
{
	_delay_us(10);
	PORTB &= ~_BV(CSN);	//CSN low
	_delay_us(10);
	spi_tranceiver(R_REGISTER + reg);
	_delay_us(10);
	reg = spi_tranceiver(NOP);
	_delay_us(10);
	PORTB |= _BV(CSN);	//CSN high
	return reg;
}

void Write_byte(unsigned char reg, unsigned char data)
{
	_delay_us(10);
	PORTB &= ~_BV(CSN);	//CSN low
	_delay_us(10);
	spi_tranceiver(W_REGISTER + reg);
	_delay_us(10);
	spi_tranceiver(data);
	_delay_us(10);
	PORTB |= _BV(CSN);	//CSN high
}

void Init_nrf(void)
{	
	//Enable auto-acknowledgment for data pipe 0
	Write_byte(EN_AA, 0x01);
	
	//Enable data pipe 0
	Write_byte(EN_RXADDR, 0x01);

	//Set address width to 5 bytes
	Write_byte(SETUP_AW, 0x03);
	
	//Set channel frequency to 2.505GHz
	Write_byte(RF_CH, 0x69);
	
	//Set data rate to 2Mbps and 0dB gain
	Write_byte(RF_SETUP, 0x0E);
	
	//Enable W_TX_PAYLOAD_NOACK command
//	Write_byte(FEATURE, 0x01);
	
	//Set the 5-bytes receiver address as 0x01 0x02 0x03 0x04 0x05
	_delay_us(10);
	PORTB &= ~_BV(CSN);	//CSN low
	_delay_us(10);
	//Setup p0 pipe address for receiving
	spi_tranceiver(W_REGISTER + RX_ADDR_P0);
	_delay_us(10);
	spi_tranceiver(0xAA);
	_delay_us(10);
	spi_tranceiver(0xBB);
	_delay_us(10);
	spi_tranceiver(0xCC);
	_delay_us(10);
	spi_tranceiver(0xDD);
	_delay_us(10);
	spi_tranceiver(0xEE);
	_delay_us(10);
	PORTB |= _BV(CSN);	//CSN high
	
	//Set the 5-bytes transmitter address as 0x01 0x02 0x03 0x04 0x05
	_delay_us(10);
	PORTB &= ~_BV(CSN);	//CSN low
	_delay_us(10);
	//Setup the transmitter address
	spi_tranceiver(W_REGISTER + TX_ADDR);
	_delay_us(10);
	spi_tranceiver(0x11);
	_delay_us(10);
	spi_tranceiver(0x12);
	_delay_us(10);
	spi_tranceiver(0x13);
	_delay_us(10);
	spi_tranceiver(0x14);
	_delay_us(10);
	spi_tranceiver(0x15);
	_delay_us(10);
	PORTB |= _BV(CSN);	//CSN high
	
	//Set the payload width as 8-bytes
	Write_byte(RX_PW_P0, 0x08);
	
	//Set the retransmission delay to 750us with 15 retries
	Write_byte(SETUP_RETR, 0x2F);
	
	//Boot the nrf as RX and mask the maximum retransmission interrupt(disable)
	//Enable CRC and set the length to 2-bytes
	nRF_RX_mode();
	
	_delay_ms(10);		//10ms delay after power-up
}

void nRF_TX_mode(void)
{
	Flush_tx();							 //Flush TX FIFO
	Write_byte(STATUS, (1 << RX_DR) | (1 << TX_DS) | (1 << MAX_RT)); //Reset status
	PORTB &= ~_BV(CE);						 //CE low - Standby-I
	//Power-up and set as TX
	Write_byte(CONFIG, Read_Byte(CONFIG) | (1 << PWR_UP) | (0 << PRIM_RX));
	//Mask TX_DR and MAX_RT interrupts
	Write_byte(CONFIG, Read_Byte(CONFIG) | (1 << MASK_TX_DS) | (1 << MASK_MAX_RT));
	_delay_us(150);
}

void nRF_RX_mode(void)
{
	Flush_rx();							 //Flush RX FIFO
	Write_byte(STATUS, (1 << RX_DR) | (1 << TX_DS) | (1 << MAX_RT)); //Reset status
	PORTB &= ~_BV(CE); 						 //CE low
	//Power-up as set as RX
	Write_byte(CONFIG, Read_Byte(CONFIG) | (1 << PWR_UP) | (1 << PRIM_RX));
	//Mask TX_DR and MAX_RT interrupts
	Write_byte(CONFIG, Read_Byte(CONFIG) | (1 << MASK_TX_DS) | (1 << MASK_MAX_RT));
	PORTB |= _BV(CE);  						 //CE high
	_delay_us(150);
}

void Flush_tx(void)
{
	_delay_us(10);
	PORTB &= ~_BV(CSN);	//CSN low
	_delay_us(10);
	spi_tranceiver(FLUSH_TX);
	_delay_us(10);
	PORTB |= _BV(CSN);	//CSN high
	_delay_us(10);
}

void Flush_rx(void)
{
	_delay_us(10);
	PORTB &= ~_BV(CSN);	//CSN low
	_delay_us(10);
	spi_tranceiver(FLUSH_RX);
	_delay_us(10);
	PORTB |= _BV(CSN);	//CSN high
	_delay_us(10);
}

void Payload_TX(uint8_t* data, uint8_t len)
{
	uint8_t i;
	
	for(i = 0; i < len; i++)
	{
		spi_tranceiver(N1_payload_TX[i]);
	}
}

void transmit_data(unsigned char *tdata)
{
	Flush_tx();
	PORTB &= ~_BV(CSN); //CSN low
	_delay_us(10);
	//Transmit payload with ACK enabled
	spi_tranceiver(W_TX_PAYLOAD);
	_delay_us(10);
	Payload_TX(N1_payload_TX, PAYLOAD_LEN);
	_delay_us(10);
	PORTB |= _BV(CSN);  //CSN high
	_delay_us(10);      //Need at least 10us before sending
	PORTB |= _BV(CE);   //CE high
	_delay_us(10);      //Hold CE high for at least 10us and not longer than 4ms
	PORTB &= ~_BV(CE);  //CE low
}

uint8_t nrf24_getStatus()
{
	uint8_t rv;
	PORTB &= ~_BV(CSN); //CSN low
	rv = spi_tranceiver(NOP);
	PORTB |= _BV(CSN);  //CSN high
	return rv;
}

uint8_t nrf24_isSending()
{
	uint8_t status;

	/* read the current status */
	status = nrf24_getStatus();
	
	/* if sending successful (TX_DS) or max retries exceeded (MAX_RT). */
	if((status & ((1 << TX_DS)  | (1 << MAX_RT))))
	{
		return 0; /* false */
	}

	return 1; /* true */
}

void Init_INT6(void)
{
	EICRB &= ~(1 << ISC60) | (1 << ISC61);	//INT6 active when low
	EIMSK |= (1 << INT6);			//Enable INT6
	sei();					//Enable global interrupts
}

ISR(INT6_vect)
{
	cli();					//Disable global interrupt
	
	PORTB &= ~_BV(CE); 			//Stop listening
	// Pull down chip select 
	PORTB &= ~_BV(CSN); //CSN low
	_delay_us(10);
	// Send command to read RX payload 
	spi_tranceiver(R_RX_PAYLOAD);
	_delay_us(10);
	// Read payload 
	Payload_RX(N1_payload_RX, N1_payload_RX, PAYLOAD_LEN);
	_delay_us(10);
	// Pull up chip select
	PORTB |= _BV(CSN);  //CSN high
	_delay_us(10);
	// Reset status register 
	Write_byte(STATUS, (1 << RX_DR));
}

/* send and receive multiple bytes over SPI */
void Payload_RX(uint8_t *data_out, uint8_t *data_in, uint8_t len)
{
	uint8_t i;

	for(i=0; i<len; i++)
	{
		data_in[i] = spi_tranceiver(data_out[i]);
		UART_Tx(data_in[i]);		   //Send the received data to UART
		if (data_in[i] == 0xAA)
		{
			RX_Payload_cnt++;
			UART_Tx(RX_Payload_cnt);   //Send RX_Payload count to UART
		}
	}
}

void reset(void)
{
	_delay_us(10);
	//Reset IRQ-flags in status register
	Write_byte(STATUS, 0x70);
	_delay_us(10);
}

/************************************************************************************
** Main function:
** - Contains an endless loop
** - Sets the BNO055 in NDOF mode and fetches the quaternion data
*************************************************************************************/
int main(void)
{
	AVR_Init();
	i2c_init();
	
	Init_SPI();
	Init_nrf();
	UART_Init();
	Init_INT6();

	i2c_start_wait(BNO055_ADDRESS+I2C_WRITE);	//Set device address and read mode
	i2c_write(BNO055_OPR_MODE_ADDR);
	i2c_write(OPERATION_MODE_NDOF);			//Set operation mode to NDOF
	i2c_stop();
	_delay_ms(10);
	
	//Initialize the received payload count
	RX_Payload_cnt = 0;
	
	Flush_rx();
	reset();
	PORTB |= _BV(CE);			//Start listening

	//Endless Loop
	while(1)
	{	
		if (RX_Payload_cnt == PAYLOAD_LEN)
		{
			UART_Tx(0x55);   	//Send BP1 to UART
			
			RX_Payload_cnt = 0;
			
			//Configure as Transmitter
			nRF_TX_mode();

			UART_Tx(0x66);   	//Send BP2 to UART
			
			//Read the Quaternions data from the BNO055
			BNO_Read_Quaternions();

			UART_Tx(0x77);   	//Send BP3 to UART
			
			//Transmit Quaternion payload
			transmit_data(N1_payload_TX);
			while(nrf24_isSending());
			reset();

			UART_Tx(0x88);   	//Send BP4 to UART
				
			//Configure as Receiver
			nRF_RX_mode();
			Flush_rx();
			reset();
			PORTB |= _BV(CE);	//Start listening again
			sei();

			UART_Tx(0x99);   	//Send BP5 to UART
		}

//		UART_Tx(0x00);   //Send BP5 to UART
	}
}

Related