/* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
/* Copyright (c) 2015 King Kévin */
/* This library allows to communicate with a nordic semiconductor nRF24L01 2.4GHz single chip transceiver
* this library uses the SPI bus and requires interrupts to handle the IRQ
*/
#include // Standard Integer Types
#include // General utilities
#include // Boolean
#include // Memory utilities
#include // AVR device-specific IO definitions
#include // Interrupts
#include // SPI functions
#include // nRF24L01 configuration
#include // Standard IO facilities
#include // Program Space Utilities
#if defined(IRQ_DDR) && defined(IRQ_IO)
/* if the nRF24L01 is initialized with interrupts, watch for nrf_activity to go true
* once true, check if transmission or reception happened using nrf24_activity(), then nrf24_tx_activity() or nrf24_rx_activity()
* you can then check is transmission succeeded using nrf24_tx_succeeded()
* or get the received data using nrf24_rx_data()
* set it to false after checks are done
*/
volatile bool nrf24_flag = false;
#endif
/* stay in RX mode to receive data */
bool rx = false;
/* initialize the nRF24L01 */
void nrf24_init()
{
// configure SPI
spi_init(); // SPI is used to communicate with the nRF24L01
// configure IO
CE_DDR |= (1<125) {
return;
}
/* verify there is space in the FIFO */
uint8_t cmd[2]; // command
cmd[0] = 0x20+0x05; // W_REGISTER command + RF_CH register
cmd[1] = channel; // set channel
spi_transfer_wait(cmd,sizeof(cmd)); // write RF_CH
}
/* transmit with of bytes (max 32 bytes)
* returns false if input is corrupted or FIFO is already full
* returns true after payload is written
*/
bool nrf24_transmit(uint8_t* payload, uint8_t length)
{
if (payload==NULL || length==0 || length>32) { // ensure data and size is valid
return false;
}
/* check if TX FIFO is full */
uint8_t cmd[2]; // command
cmd[0] = 0x00+0x17; // R_REGISTER command + FIFO_STATUS register
spi_transfer_wait(cmd,sizeof(cmd)); // read FIFO status
if (cmd[1]&(1<<5)) { // TX_FULL
return false;
}
/* go into TX mode */
cmd[0] = 0x00+0x00; // R_REGISTER command + CONFIG register
spi_transfer_wait(cmd,sizeof(cmd)); // read config
cmd[0] = 0x20+0x00; // W_REGISTER command + CONFIG register
cmd[1] &= ~(1<<0); // set PRIM_RX to 0 (PTX)
spi_transfer_wait(cmd,sizeof(cmd)); // write config to got in PTX mode
/* write TX payload */
uint8_t* tx = calloc(length+1,sizeof(uint8_t));
tx[0] = 0xa0; // W_TX_PAYLOAD command
memcpy(&tx[1],payload,length); // copy data
spi_transfer_wait(tx,length+1); // write TX payload
/* start transmission */
CE_PORT |= (1< pointer
* returns size of received data
* returns 0 if no data is available
* write maximum in (max payload size is 32)
*/
uint8_t nrf24_rx_payload(uint8_t* payload, uint8_t size)
{
uint8_t to_return = 0; // the size of the data
uint8_t cmd[2]; // SPI nFR24L01 command
cmd[0] = 0x60; // R_RX_PL_WID command
spi_transfer_wait(cmd,2); // get size (and STATUS)
if ((cmd[0]&0x0e)==0x0e) { // RX_FIFO empty based on RX_P_NO
to_return = 0; // no data is available
} else if (cmd[1]>32) { // something is wrong
cmd[0] = 0xe2; // FLUSH_RX command
spi_transfer_wait(cmd,1); // flush, as suggested by the note
to_return = 0;
} else { // data is available
to_return = cmd[1];
if (to_return>size) { // avoid buffer overflow
to_return = size;
}
// go into RX mode
cmd[0] = 0x00+0x00; // R_REGISTER command + CONFIG register
spi_transfer_wait(cmd,2); // read config
cmd[0] = 0x20+0x00; // W_REGISTER command + CONFIG register
cmd[1] |= (1<<0); // set PRIM_RX to 1 (PRX)
spi_transfer_wait(cmd,2); // write config to got in PRX mode
// read RX payload
uint8_t* data = calloc(to_return+1,sizeof(uint8_t)); // re-allocated memory to get data
data[0] = 0x61; // R_RX_PAYLOAD command
spi_transfer_wait(data,to_return+1); // read FIFO (automatically deleted)
memcpy(payload,&data[1],to_return); // copy payload
free(data); // clean memory
data = NULL; // clean memory
}
return to_return;
}