This commit is contained in:
maniacbug 2011-03-18 20:32:34 -07:00
commit de083c964d
8 changed files with 2638 additions and 0 deletions

1551
Doxyfile Normal file

File diff suppressed because it is too large Load Diff

12
README Normal file
View File

@ -0,0 +1,12 @@
Aruino driver for nRF24L01 2.4GHz Wireless Transceiver
See Datasheet at http://www.nordicsemi.com/files/Product/data_sheet/nRF24L01_Product_Specification_v2_0.pdf
This chip uses the SPI bus, plus two chip control pins. Remember that pin 10 must still remain an output, or
the SPI hardware will go into 'slave' mode.
Design Goals: This library is designed to be...
* Maximally compliant with the intended operation of the chip
* Easy for beginners to use
* Consumed with a public interface that's similiar to other Arduino standard libraries
* Built against the standard SPI library.

419
RF24.cpp Normal file
View File

@ -0,0 +1,419 @@
/*
Copyright (C) 2011 James Coliz, Jr. <maniacbug@ymail.com>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation.
*/
#include <WProgram.h>
#include <SPI.h>
#include "RF24.h"
#include "nRF24L01.h"
#undef SERIAL_DEBUG
#ifdef SERIAL_DEBUG
#define IF_SERIAL_DEBUG(x) (x)
#else
#define IF_SERIAL_DEBUG(x)
#endif
/******************************************************************/
void RF24::csn(int mode)
{
digitalWrite(csn_pin,mode);
}
/******************************************************************/
void RF24::ce(int mode)
{
digitalWrite(ce_pin,mode);
}
/******************************************************************/
uint8_t RF24::read_register(uint8_t reg, uint8_t* buf, uint8_t len)
{
uint8_t status;
csn(LOW);
status = SPI.transfer( R_REGISTER | ( REGISTER_MASK & reg ) );
while ( len-- )
*buf++ = SPI.transfer(0xff);
csn(HIGH);
return status;
}
/******************************************************************/
uint8_t RF24::write_register(uint8_t reg, const uint8_t* buf, uint8_t len)
{
uint8_t status;
csn(LOW);
status = SPI.transfer( W_REGISTER | ( REGISTER_MASK & reg ) );
while ( len-- )
SPI.transfer(*buf++);
csn(HIGH);
return status;
}
/******************************************************************/
uint8_t RF24::write_register(uint8_t reg, uint8_t value)
{
uint8_t status;
csn(LOW);
status = SPI.transfer( W_REGISTER | ( REGISTER_MASK & reg ) );
SPI.transfer(value);
csn(HIGH);
return status;
}
/******************************************************************/
uint8_t RF24::write_payload(const void* buf)
{
uint8_t status;
const uint8_t* current = (const uint8_t*)buf;
csn(LOW);
status = SPI.transfer( W_TX_PAYLOAD );
uint8_t len = payload_size;
while ( len-- )
SPI.transfer(*current++);
csn(HIGH);
return status;
}
/******************************************************************/
uint8_t RF24::read_payload(void* buf)
{
uint8_t status;
uint8_t* current = (uint8_t*)buf;
csn(LOW);
status = SPI.transfer( R_RX_PAYLOAD );
uint8_t len = payload_size;
while ( len-- )
*current++ = SPI.transfer(0xff);
csn(HIGH);
return status;
}
/******************************************************************/
uint8_t RF24::flush_rx(void)
{
uint8_t status;
csn(LOW);
status = SPI.transfer( FLUSH_RX );
csn(HIGH);
return status;
}
/******************************************************************/
uint8_t RF24::flush_tx(void)
{
uint8_t status;
csn(LOW);
status = SPI.transfer( FLUSH_TX );
csn(HIGH);
return status;
}
/******************************************************************/
uint8_t RF24::get_status(void)
{
uint8_t status;
csn(LOW);
status = SPI.transfer( NOP );
csn(HIGH);
return status;
}
/******************************************************************/
void RF24::print_status(uint8_t status)
{
printf("STATUS=%02x: RX_DR=%x TX_DS=%x MAX_RT=%x RX_P_NO=%x TX_FULL=%x\n\r",
status,
(status & _BV(RX_DR))?1:0,
(status & _BV(TX_DS))?1:0,
(status & _BV(MAX_RT))?1:0,
((status >> RX_P_NO) & B111),
(status & _BV(TX_FULL))?1:0
);
}
/******************************************************************/
void RF24::print_observe_tx(uint8_t value)
{
printf("OBSERVE_TX=%02x: POLS_CNT=%x ARC_CNT=%x\n\r",
value,
(value >> PLOS_CNT) & B1111,
(value >> ARC_CNT) & B1111
);
}
/******************************************************************/
RF24::RF24(int _cepin, int _cspin):
ce_pin(_cepin), csn_pin(_cspin)
{
}
/******************************************************************/
void RF24::setChannel(int channel)
{
write_register(RF_CH,min(channel,127));
}
/******************************************************************/
void RF24::setPayloadSize(uint8_t size)
{
payload_size = min(size,32);
write_register(RX_PW_P0,min(size,32));
}
/******************************************************************/
uint8_t RF24::getPayloadSize(void)
{
return payload_size;
}
/******************************************************************/
void RF24::print_details(void)
{
uint8_t buffer[5];
uint8_t status = read_register(RX_ADDR_P0,buffer,5);
print_status(status);
printf("RX_ADDR_P0 = 0x",buffer);
uint8_t *bufptr = buffer + 5;
while( bufptr-- > buffer )
printf("%02x",*bufptr);
printf("\n\r");
status = read_register(RX_ADDR_P1,buffer,5);
printf("RX_ADDR_P1 = 0x",buffer);
bufptr = buffer + 5;
while( bufptr-- > buffer )
printf("%02x",*bufptr);
printf("\n\r");
status = read_register(TX_ADDR,buffer,5);
printf("TX_ADDR = 0x",buffer);
bufptr = buffer + 5;
while( bufptr-- > buffer )
printf("%02x",*bufptr);
printf("\n\r");
read_register(EN_AA,buffer,1);
printf("EN_AA = %02x\n\r",*buffer);
read_register(EN_RXADDR,buffer,1);
printf("EN_RXADDR = %02x\n\r",*buffer);
read_register(RF_CH,buffer,1);
printf("RF_CH = %02x\n\r",*buffer);
}
/******************************************************************/
void RF24::begin(void)
{
pinMode(ce_pin,OUTPUT);
pinMode(csn_pin,OUTPUT);
ce(LOW);
csn(HIGH);
SPI.begin();
SPI.setBitOrder(MSBFIRST);
SPI.setDataMode(SPI_MODE0);
SPI.setClockDivider(SPI_CLOCK_DIV8);
// Set generous timeouts, to make testing a little easier
write_register(SETUP_RETR,(B1111 << ARD) | (B1111 << ARC));
// Reset current status
write_register(STATUS,_BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT) );
// Flush buffers
flush_rx();
flush_tx();
// Set up default configuration. Callers can always change it later.
setChannel(1);
setPayloadSize(8);
}
/******************************************************************/
void RF24::startListening(void)
{
write_register(CONFIG, _BV(EN_CRC) | _BV(PWR_UP) | _BV(PRIM_RX));
write_register(STATUS, _BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT) );
// Flush buffers
flush_rx();
// Go!
ce(HIGH);
// wait for the radio to come up (130us actually only needed)
delay(1);
}
/******************************************************************/
void RF24::stopListening(void)
{
ce(LOW);
}
/******************************************************************/
boolean RF24::write( const void* buf )
{
boolean result = false;
// Transmitter power-up
write_register(CONFIG, _BV(EN_CRC) | _BV(PWR_UP));
// Send the payload
write_payload( buf );
// Allons!
ce(HIGH);
// IN the end, the send should be blocking. It comes back in 60ms worst case, or much faster
// if I tighted up the retry logic. (Default settings will be 750us.
// Monitor the send
uint8_t observe_tx;
uint8_t status;
do
{
status = read_register(OBSERVE_TX,&observe_tx,1);
IF_SERIAL_DEBUG(Serial.print(status,HEX));
IF_SERIAL_DEBUG(Serial.print(observe_tx,HEX));
}
while( ! ( status & ( _BV(TX_DS) | _BV(MAX_RT) ) ) );
if ( status & _BV(TX_DS) )
result = true;
IF_SERIAL_DEBUG(Serial.println(result?"...OK.":"...Failed"));
// Yay, we are done.
ce(LOW);
// Power down
write_register(CONFIG, _BV(EN_CRC) );
// Reset current status
write_register(STATUS,_BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT) );
// Flush buffers
flush_tx();
return result;
}
/******************************************************************/
boolean RF24::available(void)
{
uint8_t status = get_status();
boolean result = ( status & _BV(RX_DR) );
if (result)
{
IF_SERIAL_DEBUG(print_status(status));
// Clear the status bit
write_register(STATUS,_BV(RX_DR) );
}
return result;
}
/******************************************************************/
boolean RF24::read( void* buf )
{
// was this the last of the data available?
boolean result = false;
// Fetch the payload
read_payload( buf );
uint8_t fifo_status;
read_register(FIFO_STATUS,&fifo_status,1);
if ( fifo_status & _BV(RX_EMPTY) )
result = true;
return result;
}
/******************************************************************/
void RF24::openWritingPipe(uint64_t value)
{
// Note that AVR 8-bit uC's store this LSB first, and the NRF24L01
// expects it LSB first too, so we're good.
write_register(RX_ADDR_P0, reinterpret_cast<uint8_t*>(&value), 5);
write_register(TX_ADDR, reinterpret_cast<uint8_t*>(&value), 5);
}
/******************************************************************/
void RF24::openReadingPipe(uint8_t child, uint64_t value)
{
const uint8_t child_pipe[] = {
RX_ADDR_P1, RX_ADDR_P2, RX_ADDR_P3, RX_ADDR_P4, RX_ADDR_P5 };
const uint8_t child_payload_size[] = {
RX_PW_P1, RX_PW_P2, RX_PW_P3, RX_PW_P4, RX_PW_P5 };
const uint8_t child_pipe_enable[] = {
ENAA_P1, ENAA_P2, ENAA_P3, ENAA_P4, ENAA_P5 };
if (--child < 5)
{
write_register(child_pipe[child], reinterpret_cast<uint8_t*>(&value), 5);
write_register(child_payload_size[child],payload_size);
// Note this is kind of an inefficient way to set up these enable bits, bit I thought it made
// the calling code more simple
uint8_t en_aa;
read_register(EN_AA,&en_aa,1);
en_aa |= _BV(child_pipe_enable[child]);
write_register(EN_AA,en_aa);
}
}

296
RF24.h Normal file
View File

@ -0,0 +1,296 @@
/*
Copyright (C) 2011 James Coliz, Jr. <maniacbug@ymail.com>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation.
*/
#ifndef __RF24_H__
#define __RF24_H__
#include <inttypes.h>
/**
* Driver for nRF24L01 2.4GHz Wireless Transceiver
*
* See <a href="http://www.nordicsemi.com/files/Product/data_sheet/nRF24L01_Product_Specification_v2_0.pdf">Datasheet</a>
*
* This chip uses the SPI bus, plus two chip control pins. Remember that pin 10 must still remain an output, or
* the SPI hardware will go into 'slave' mode.
*
* Design Goals: This library is designed to be...
* * Maximally compliant with the intended operation of the chip
* * Easy for beginners to use
* * Consumed with a public interface that's similiar to other Arduino standard libraries
* * Built against the standard SPI library.
*/
class RF24
{
private:
int ce_pin; /**< "Chip Enable" pin, activates the RX or TX role */
int csn_pin; /**< SPI Chip select */
int payload_size; /**< Fixed size of payloads */
protected:
/**
* @name Low-level internal interface.
*
* Protected methods that address the chip directly.
*/
/**@{*/
/**
* Set chip select pin
*
* @param mode HIGH to take this unit off the SPI bus, LOW to put it on
*/
void csn(int mode) ;
/**
* Set chip enable
*
* @param mode HIGH to actively begin transmission or LOW to put in standby. Please see data sheet
* for a much more detailed description of this pin.
*/
void ce(int mode);
/**
* Read a chunk of data in from a register
*
* @param reg Which register. Use constants from nRF24L01.h
* @param buf Where to put the data
* @param len How many bytes of data to transfer
* @return Current value of status register
*/
uint8_t read_register(uint8_t reg, uint8_t* buf, uint8_t len) ;
/**
* Write a chunk of data to a register
*
* @param reg Which register. Use constants from nRF24L01.h
* @param buf Where to get the data
* @param len How many bytes of data to transfer
* @return Current value of status register
*/
uint8_t write_register(uint8_t reg, const uint8_t* buf, uint8_t len);
/**
* Write a single byte to a register
*
* @param reg Which register. Use constants from nRF24L01.h
* @param value The new value to write
* @return Current value of status register
*/
uint8_t write_register(uint8_t reg, uint8_t value);
/**
* Write the transmit payload
*
* The size of data written is the fixed payload size, see getPayloadSize()
*
* @param buf Where to get the data
* @return Current value of status register
*/
uint8_t write_payload(const void* buf);
/**
* Read the receive payload
*
* The size of data read is the fixed payload size, see getPayloadSize()
*
* @param buf Where to put the data
* @return Current value of status register
*/
uint8_t read_payload(void* buf) ;
/**
* Empty the receive buffer
*
* @return Current value of status register
*/
uint8_t flush_rx(void);
/**
* Empty the transmit buffer
*
* @return Current value of status register
*/
uint8_t flush_tx(void);
/**
* Retrieve the current status of the chip
*
* @return Current value of status register
*/
uint8_t get_status(void) ;
/**
* Decode and print the given status to stdout
*
* @param status Status value to print
*
* @warning Does nothing if stdout is not defined. See fdevopen in stdio.h
*/
void print_status(uint8_t status) ;
/**
* Decode and print the given 'observe_tx' value to stdout
*
* @param Value The observe_tx value to print
*
* @warning Does nothing if stdout is not defined. See fdevopen in stdio.h
*/
void print_observe_tx(uint8_t value) ;
/**@}*/
public:
/**
* Constructor
*
* @param _cepin The pin attached to Chip Enable on the RF module
* @param _cspin The pin attached to Chip Select
*/
RF24(int _cepin, int _cspin);
/**
* Begin operation of the chip
*
* Call this in setup(), before calling any other methods.
*/
void begin(void);
/**
* Set RF communication channel
*
* @param channel Which RF channel to communicate on, 0-127
*/
void setChannel(int channel);
/**
* Set Payload Size
*
* This implementation uses a pre-stablished fixed payload size for all
* transmissions.
*
* @todo Implement variable-sized payloads feature
*
* @param size The number of bytes in the payload
*/
void setPayloadSize(uint8_t size);
/**
* Get Payload Size
*
* @see setPayloadSize()
*
* @return The number of bytes in the payload
*/
uint8_t getPayloadSize(void) ;
/**
* Print a giant block of debugging information to stdout
*
* @warning Does nothing if stdout is not defined. See fdevopen in stdio.h
*/
void print_details(void) ;
/**
* Start listening on the pipes opened for reading.
*
* Be sure to open some pipes for reading first. Do not call 'write'
* while in this mode, without first calling 'stopListening'.
*/
void startListening(void);
/**
* Stop listening for incoming messages
*
* Necessary to do this before writing.
*/
void stopListening(void);
/**
* Write to the open writing pipe
*
* This blocks until the message is successfully acknowledged by
* the receiver or the timeout/retransmit maxima are reached. In
* the current configuration, the max delay here is 60ms.
*
* The size of data written is the fixed payload size, see getPayloadSize()
*
* @param buf Pointer to the data to be sent
* @return True if the payload was delivered successfully false if not
*/
boolean write( const void* buf );
/**
* Test whether there are bytes available to be read
*
* @return True if there is a payload available, false if none is
*/
boolean available(void) ;
/**
* Read the payload
*
* Return the last payload received
*
* The size of data read is the fixed payload size, see getPayloadSize()
*
* @todo Indicate which pipe it came from
*
* @note I specifically chose 'void*' as a data type to make it easier
* for beginners to use. No casting needed.
*
* @param buf Pointer to a buffer where the data should be written
* @return True if the payload was delivered successfully false if not
*/
boolean read( void* buf ) ;
/**
* Open a pipe for writing
*
* Only one pipe can be open at once, but you can change the pipe
* you'll listen to. Do not call this while actively listening.
* Remember to stopListening() first.
*
* Addresses are 40-bit hex values, e.g.:
* @code
* openWritingPipe(0xF0F0F0F0F0);
* @endcode
*
* @param value The 40-bit address of the pipe to open. This can be
* any value whatsoever, as long as you are the only one writing to it
* and only one other radio is listening to it. Coordinate these pipe
* addresses amongst nodes on the network.
*/
void openWritingPipe(uint64_t address);
/**
* Open a pipe for reading
*
* Up to 5 pipes can be open for reading at once. Open all the
* reading pipes, and then call startListening().
*
* @see openWritingPipe
*
* @warning all 5 reading pipes should share the first 32 bits.
* Only the least significant byte should be unique, e.g.
* @code
* openReadingPipe(0xF0F0F0F0AA);
* openReadingPipe(0xF0F0F0F066);
* @endcode
*
* @todo Enforce the restriction that all pipes must share the top 32 bits
*
* @param number Which pipe# to open, 1-5.
* @param address The 40-bit address of the pipe to open.
*/
void openReadingPipe(uint8_t number, uint64_t address);
};
#endif // __RF24_H__

View File

@ -0,0 +1,216 @@
/*
Copyright (C) 2011 James Coliz, Jr. <maniacbug@ymail.com>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation.
*/
/**
* Example RF Radio Ping Pair
*
* This sketch is an example of using the RF24 library for Arduino. Deploy this on
* two nodes, set one as the 'trasmit' and the other the 'receive' unit. The transmit
* unit will send out the value of millis() once a second. The receive unit will respond
* back with a copy of the value. The transmit unit can get that 'ping' back, and
* determine how long the whole cycle took.
*/
#include <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"
#include "printf.h"
//
// Hardware configuration
//
// Set up nRF24L01 radio on SPI bus plus pins 8 & 9
RF24 radio(8,9);
// sets the address (and therefore the role of operation) of this unit.
// lo = node0, hi = node1
const int addr_pin = 7;
// The actual value of the node's address will be filled in by the sketch
// when it reads the addr_pin
int node_address;
//
// Topology
//
// Radio pipe addresses for the 2 nodes to communicate.
const uint64_t pipes[2] = { 0xF0F0F0F0E1LL, 0xF0F0F0F0D2LL };
//
// Role management
//
// Set up address & role. This sketch uses the same software for all the nodes
// in this system. Doing so greatly simplifies testing. The hardware itself specifies
// which node it is.
//
// This is done through the addr_pin. Set it low for address #0, high for #1.
//
// The various roles supported by this sketch
typedef enum { role_rx = 1, role_tx1, role_end } role_e;
// The debug-friendly names of those roles
const char* role_friendly_name[] = { "invalid", "Receive", "Transmit"};
// Which role is assumed by each of the possible hardware addresses
const role_e role_map[2] = { role_rx, role_tx1 };
// The role of the current running sketch
role_e role;
void setup(void)
{
//
// Address & Role
//
// set up the address pin
pinMode(addr_pin, INPUT);
digitalWrite(addr_pin,HIGH);
delay(20); // Just to get a solid reading on the addr pin
// read the address pin, establish our address and role
node_address = digitalRead(addr_pin) ? 0 : 1;
role = role_map[node_address];
//
// Print preamble
//
Serial.begin(9600);
printf_begin();
printf("\n\rRF24 pingpair example\n\r");
printf("ADDRESS: %x\n\r",node_address);
printf("ROLE: %s\n\r",role_friendly_name[role]);
//
// Setup and configure rf radio
//
radio.begin();
// Set channel (optional)
radio.setChannel(1);
// Set size of payload (optional, but recommended)
// The library uses a fixed-size payload, so if you don't set one, it will pick
// one for you!
radio.setPayloadSize(sizeof(unsigned long));
//
// Open pipes to other nodes for communication (required)
//
// This simple sketch opens two pipes for these two nodes to communicate
// back and forth.
// We will open 'our' pipe for writing
radio.openWritingPipe(pipes[node_address]);
// We open the 'other' pipe for reading, in position #1 (we can have up to 5 pipes open for reading)
int other_node_address;
if (node_address == 0)
other_node_address = 1;
else
other_node_address = 0;
radio.openReadingPipe(1,pipes[other_node_address]);
//
// Start listening
//
radio.startListening();
//
// Dump the configuration of the rf unit for debugging
//
radio.print_details();
}
void loop(void)
{
//
// Transmitter role. Repeatedly send the current time
//
if (role == role_tx1)
{
// First, stop listening so we can talk.
radio.stopListening();
// Take the time, and send it. This will block until complete
unsigned long time = millis();
printf("Now sending %lu...",time);
bool ok = radio.write( &time );
// Now, continue listening
radio.startListening();
// Wait here until we get a response, or timeout (250ms)
unsigned long started_waiting_at = millis();
bool timeout = false;
while ( ! radio.available() && ! timeout )
if (millis() - started_waiting_at > 250 )
timeout = true;
// Describe the results
if ( timeout )
{
printf("Failed, response timed out.\n\r");
}
else
{
// Grab the response, compare, and send to debugging spew
unsigned long got_time;
radio.read( &got_time );
// Spew it
printf("Got response %lu, round-trip delay: %lu\n\r",got_time,millis()-got_time);
}
// Try again 1s later
delay(1000);
}
//
// Receiver role. Receive each packet, dump it out, and send it back to the transmitter
//
if ( role == role_rx )
{
// if there is data ready
if ( radio.available() )
{
// Dump the payloads until we've gotten everything
unsigned long got_time;
boolean done = false;
while (!done)
{
// Fetch the payload, and see if this was the last one.
done = radio.read( &got_time );
// Spew it
printf("Got payload %lu...",got_time);
}
// First, stop listening so we can talk
radio.stopListening();
// Send the final one back.
radio.write( &got_time );
printf("Sent response.\n\r");
// Now, resume listening so we catch the next packets.
radio.startListening();
}
}
}

View File

@ -0,0 +1,31 @@
/*
Copyright (C) 2011 James Coliz, Jr. <maniacbug@ymail.com>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation.
*/
/**
* @file printf.h
*
* Setup necessary to direct stdout to the Arduino Serial library, which
* enables 'printf'
*/
#ifndef __PRINTF_H__
#define __PRINTF_H__
#include "WProgram.h"
int serial_putc( char c, FILE *t )
{
Serial.write( c );
}
void printf_begin(void)
{
fdevopen( &serial_putc, 0 );
}
#endif // __PRINTF_H__

13
keywords.txt Normal file
View File

@ -0,0 +1,13 @@
RF24 KEYWORD1
begin KEYWORD2
setChannel KEYWORD2
setPayloadSize KEYWORD2
getPayloadSize KEYWORD2
print_details KEYWORD2
startListening KEYWORD2
stopListening KEYWORD2
write KEYWORD2
available KEYWORD2
read KEYWORD2
openWritingPipe KEYWORD2
openReadingPipe KEYWORD2

100
nRF24L01.h Normal file
View File

@ -0,0 +1,100 @@
/*
Copyright (c) 2007 Stefan Engelke <mbox@stefanengelke.de>
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use, copy,
modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
/* Memory Map */
#define CONFIG 0x00
#define EN_AA 0x01
#define EN_RXADDR 0x02
#define SETUP_AW 0x03
#define SETUP_RETR 0x04
#define RF_CH 0x05
#define RF_SETUP 0x06
#define STATUS 0x07
#define OBSERVE_TX 0x08
#define CD 0x09
#define RX_ADDR_P0 0x0A
#define RX_ADDR_P1 0x0B
#define RX_ADDR_P2 0x0C
#define RX_ADDR_P3 0x0D
#define RX_ADDR_P4 0x0E
#define RX_ADDR_P5 0x0F
#define TX_ADDR 0x10
#define RX_PW_P0 0x11
#define RX_PW_P1 0x12
#define RX_PW_P2 0x13
#define RX_PW_P3 0x14
#define RX_PW_P4 0x15
#define RX_PW_P5 0x16
#define FIFO_STATUS 0x17
/* Bit Mnemonics */
#define MASK_RX_DR 6
#define MASK_TX_DS 5
#define MASK_MAX_RT 4
#define EN_CRC 3
#define CRCO 2
#define PWR_UP 1
#define PRIM_RX 0
#define ENAA_P5 5
#define ENAA_P4 4
#define ENAA_P3 3
#define ENAA_P2 2
#define ENAA_P1 1
#define ENAA_P0 0
#define ERX_P5 5
#define ERX_P4 4
#define ERX_P3 3
#define ERX_P2 2
#define ERX_P1 1
#define ERX_P0 0
#define AW 0
#define ARD 4
#define ARC 0
#define PLL_LOCK 4
#define RF_DR 3
#define RF_PWR 1
#define LNA_HCURR 0
#define RX_DR 6
#define TX_DS 5
#define MAX_RT 4
#define RX_P_NO 1
#define TX_FULL 0
#define PLOS_CNT 4
#define ARC_CNT 0
#define TX_REUSE 6
#define FIFO_FULL 5
#define TX_EMPTY 4
#define RX_FULL 1
#define RX_EMPTY 0
/* Instruction Mnemonics */
#define R_REGISTER 0x00
#define W_REGISTER 0x20
#define REGISTER_MASK 0x1F
#define R_RX_PAYLOAD 0x61
#define W_TX_PAYLOAD 0xA0
#define FLUSH_TX 0xE1
#define FLUSH_RX 0xE2
#define REUSE_TX_PL 0xE3
#define NOP 0xFF