Project for MPOA 2015/2016. Communication link with nRF24L01+.

Dependencies:   mbed

Fork of nRF24L01P_Hello_World by Owen Edwards

main.cpp

Committer:
petrsedlacek
Date:
2016-01-17
Revision:
3:10a2f47a53a6
Parent:
2:f555c7caa707

File content as of revision 3:10a2f47a53a6:

//Autor: Petr Sedláček
//Project for MPOA 2015/2016, Experimental Point-to-point link with nRF24L01+ in 2.4 GHz ISM band

#include "mbed.h"
#include "nRF24L01P.h"
#include <string.h>
#include <Timer.h>
#include "menu.h"

#define TRANSFER_SIZE 16 //Maximum data size


Serial pc(USBTX, USBRX); // tx, rx

nRF24L01P my_nrf24l01p(PTD2, PTD3, PTD1, PTD0, PTD5, PTA13);    // mosi, miso, sck, csn, ce, irq

DigitalOut rled(LED_RED, 1);
DigitalOut gled(LED_GREEN, 1);  

Timer rtt_timer; //Timer to measure RTT
Ticker rled_ticker; //Tickers for blinking LEDs
Ticker gled_ticker;

static uint16_t error_bits = 0; //static to be only visible in this file
static uint16_t all_bits = 0;   //static to be only visible in this file
uint8_t interval;
char txData[TRANSFER_SIZE];
int txDataCnt = 0;
bool tx_mode;
bool keyboard_mode;

//Functions for LED blinks
void led_red_flip() {
    rled = !rled;
    rled_ticker.detach();
        
}

void led_green_flip() {
    gled = !gled;
    gled_ticker.detach();    
}

//Function for BER calculation
void ber_calculate(char recData[]) {
    float ber = 0;
    char sent_string[] = "ACK\r"; //Compared string
    
    all_bits += (strlen(recData) *8); //Increase the size if incoming bits
    
    for (uint8_t i=0; i<= strlen(recData); i++) {
        recData[i] ^= sent_string[i]; //XOR received data with expected string
        
        //If there was no error, all bits must be zero
        while(recData[i] !=0) {
            //If there was an error, increase number of error bits and shift by one
            if (recData[i] & 1) { 
                error_bits++;
                recData[i] >>= 1;
            }
        }
        
        
    }
    ber =  (((float)error_bits)/all_bits) *100; //BER calculation
    pc.printf("BER: %3.4f %%\n", ber);
    
}
//Function to send data automatically
void send() {
    //If the device is TX, send ping message
    if (tx_mode) {
        sprintf(txData, "ping\r");
        rtt_timer.start();
    }
    //If the device is RX, send ACK message
    else {
        sprintf(txData, "ACK\r");
    }
    //Print sent data and send it via nrf24l01
    pc.printf("\nSent: %s", txData);
    txDataCnt = 4;
    my_nrf24l01p.write( NRF24L01P_PIPE_P0, txData, txDataCnt );
    //Small blocking delay for LED blink
    if (!tx_mode) {
        wait_ms(200);
    }
    rled = 0; 
    rled_ticker.attach(&led_red_flip, 0.2);
}



int main() {
    Timer send_timer; //Timer for sending automatic messages
    uint16_t lost_num = 0; //Number of lost packets
    uint16_t ack_num = 0; //Number of ACKs
    uint16_t rec_messages = 0;  //Number of received messages
    char rxData[TRANSFER_SIZE];
    
    my_nrf24l01p.powerUp();
    settings(); //Function for user menu 
    
    // Display the (default) setup of the nRF24L01+ chip
    pc.printf( "nRF24L01 Frequency    : %d MHz\n",  my_nrf24l01p.getRfFrequency() );
    pc.printf( "nRF24L01 Output power : %d dBm\n",  my_nrf24l01p.getRfOutputPower() );
    pc.printf( "nRF24L01 Data Rate    : %d kbps\n", my_nrf24l01p.getAirDataRate() );
    pc.printf( "nRF24L01 TX Address   : 0x%010llX\n", my_nrf24l01p.getTxAddress() );
    pc.printf( "nRF24L01 RX Address   : 0x%010llX\n", my_nrf24l01p.getRxAddress() );
    //If TX mode and automatic mode are chosen, print the set interval for messages 
    if (tx_mode) {
        pc.printf( "Message Interval      : %d seconds\n",  interval);
    }
    //If keyboard mode is set, print this message
    if (keyboard_mode) {
        pc.printf( "Type keys to test transfers:\r\n  (transfers are grouped into variable characters, maximum is a group of %d characters)\r\n", TRANSFER_SIZE );
    }
    //Set registers for dynamic payload
    my_nrf24l01p.setRegister(_NRF24L01P_REG_FEATURE, 0x04); 
    my_nrf24l01p.setRegister(_NRF24L01P_REG_DYNPD, 0x01);
    //Start up the nrf24L01
    my_nrf24l01p.enable();
    my_nrf24l01p.setReceiveMode();
    
    //Start the timer for automatic transmissions
    if (!keyboard_mode && tx_mode) {
        send_timer.start();
    }


    while (1) {
        //Send messages periodically
        if (!keyboard_mode && tx_mode) {
            if ((int) send_timer.read_ms() % (interval*1000) == 0) {
                send();    
            }
        }
        //If keyboard mode is activated, read user input
        if (keyboard_mode) {
            // If we've received anything over the host serial link...
            if ( pc.readable() ) {
                // ...add it to the transmit buffer
                txData[txDataCnt++] = pc.getc();
                // If the transmit buffer is full or Enter is pressed
                if ( txDataCnt >= sizeof( txData ) || txData[txDataCnt-1] == '\r') {
                    // Send the transmit buffer via the nRF24L01+
                    my_nrf24l01p.write( NRF24L01P_PIPE_P0, txData, txDataCnt );
                    pc.printf("\nSent: %s\n", txData);
                    //Start the RTT timer in TX Mode
                    if (tx_mode) {
                        rtt_timer.start();
                    }   
                    // Blink Red LED to indicate message sent
                    txDataCnt = 0;
                    rled = 0; 
                    rled_ticker.attach(&led_red_flip, 0.2);
                }
   
            }
        }


        // If we've received anything in the nRF24L01+...
        if ( my_nrf24l01p.readable() ) {
            //Stop RTT timer
            if (tx_mode) {
                rtt_timer.stop();
                wait_ms(200);
            }
            // ...read the data into the receive buffer
            my_nrf24l01p.read( NRF24L01P_PIPE_P0, rxData, sizeof( rxData ) );
            pc.printf("Received: %s", rxData);
            //Blink green led to indicate message received
            gled = 0;
            gled_ticker.attach(led_green_flip, 0.2);
            //Send automatic response in RX mode  
            if (!keyboard_mode && !tx_mode) {
                send();
            }
               
            if (tx_mode) {
                //If a message wasn't received between automatic transmissions, increase BER and NACKs 
                if ((int) rtt_timer.read() >= interval && !keyboard_mode) {
                    lost_num = ((int) rtt_timer.read()/interval);
                    error_bits += (strlen(rxData) * 8) * lost_num;
                    all_bits += (strlen(rxData) * 8) * lost_num;
                }
                ack_num++; //If message was received between retransmissions, increase number of ACKs
                pc.printf("RTT: %3.4f\n", rtt_timer.read()); //Print RTT
                pc.printf("Number of ACKs: %d\n", ack_num); //Number of ACKs
                pc.printf("Number of NACKs: %d\n", lost_num); //Number of NACKs
                rtt_timer.reset(); //Reset the RTT timer
                //Calculate BER, but only in automatic mode
                if (!keyboard_mode) {
                    ber_calculate(rxData);
                }
            //If RX mode is activated, diplay number of received messages
            } else {
                rec_messages++;
                pc.printf("Recieved message No.: %d\n\n", rec_messages);
            }
            

            
        }

    }
}