Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
R
RF24
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Analytics
Analytics
Repository
Value Stream
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Commits
Open sidebar
xpstem
RF24
Commits
602d9626
Commit
602d9626
authored
Jul 31, 2011
by
maniacbug
Browse files
Options
Browse Files
Download
Plain Diff
Merge gcopeland/constremove
parents
d436895f
0c2515df
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
345 additions
and
47 deletions
+345
-47
RF24.cpp
RF24.cpp
+255
-41
RF24.h
RF24.h
+77
-4
nRF24L01.h
nRF24L01.h
+13
-2
No files found.
RF24.cpp
View file @
602d9626
...
...
@@ -8,8 +8,8 @@
#include <WProgram.h>
#include <SPI.h>
#include "RF24.h"
#include "nRF24L01.h"
#include "RF24.h"
#undef SERIAL_DEBUG
#ifdef SERIAL_DEBUG
...
...
@@ -28,16 +28,17 @@
void
RF24
::
csn
(
int
mode
)
{
SPI
.
setBitOrder
(
MSBFIRST
);
SPI
.
setDataMode
(
SPI_MODE0
);
SPI
.
setClockDivider
(
SPI_CLOCK_DIV
8
);
SPI
.
setClockDivider
(
SPI_CLOCK_DIV
2
);
digitalWrite
(
csn_pin
,
mode
);
}
/****************************************************************************/
void
RF24
::
ce
(
int
mode
)
void
RF24
::
ce
(
int
level
)
{
digitalWrite
(
ce_pin
,
mode
);
digitalWrite
(
ce_pin
,
level
);
}
/****************************************************************************/
...
...
@@ -252,8 +253,9 @@ void RF24::print_address_register(prog_char* name, uint8_t reg, uint8_t qty)
/****************************************************************************/
RF24
::
RF24
(
uint8_t
_cepin
,
uint8_t
_cspin
)
:
ce_pin
(
_cepin
),
csn_pin
(
_cspin
),
payload_size
(
32
),
ack_payload_available
(
false
)
RF24
::
RF24
(
uint8_t
_cepin
,
uint8_t
_cspin
)
:
ce_pin
(
_cepin
),
csn_pin
(
_cspin
),
wide_band
(
true
),
p_variant
(
false
),
payload_size
(
32
),
ack_payload_available
(
false
)
{
}
...
...
@@ -295,38 +297,82 @@ void RF24::printDetails(void)
print_byte_register
(
PSTR
(
"RF_SETUP"
),
RF_SETUP
);
print_byte_register
(
PSTR
(
"CONFIG"
),
CONFIG
);
print_byte_register
(
PSTR
(
"DYNPD/FEATURE"
),
DYNPD
,
2
);
// These need to be merged in with the register printing scheme
#if 0
read_register(RF_SETUP,buffer,1);
printf_P(PSTR("RF_SETUP = 0x%02x (data rate: %d)\n\r"),*buffer,getDataRate());
printf_P(PSTR("Hardware; isPVariant: %d\n\r"),isPVariant());
read_register(CONFIG,buffer,1);
printf_P(PSTR("CONFIG = 0x%02x (CRC enable: %d; CRC16: %d)\n\r"),
*buffer,(*buffer)&_BV(EN_CRC)?1:0,
(*buffer)&_BV(CRCO)?1:0);
#endif
}
/****************************************************************************/
void
RF24
::
begin
(
void
)
{
// Initialize pins
pinMode
(
ce_pin
,
OUTPUT
);
pinMode
(
csn_pin
,
OUTPUT
);
ce
(
LOW
);
csn
(
HIGH
);
// Initialize SPI bus
// Minimum ideal SPI bus speed is 2x data rate
// If we assume 2Mbs data rate and 16Mhz clock, a
// divider of 4 is the minimum we want.
// CLK:BUS 8Mhz:2Mhz, 16Mhz:4Mhz, or 20Mhz:5Mhz
// We'll use a divider of 2 which will work up to
// MCU speeds of 20Mhz.
// CLK:BUS 8Mhz:4Mhz, 16Mhz:8Mhz, or 20Mhz:10Mhz (max)
SPI
.
begin
();
SPI
.
setBitOrder
(
MSBFIRST
);
SPI
.
setDataMode
(
SPI_MODE0
);
SPI
.
setClockDivider
(
SPI_CLOCK_DIV8
);
SPI
.
setClockDivider
(
SPI_CLOCK_DIV2
);
ce
(
LOW
);
csn
(
HIGH
);
// Must allow the radio time to settle else configuration bits will not necessarily stick.
// This is actually only required following power up but some settling time also appears to
// be required after resets too. For full coverage, we'll always assume the worst.
// Enabling 16b CRC is by far the most obvious case if the wrong timing is used - or skipped.
// Technically we require 4.5ms + 14us as a worst case. We'll just call it 5ms for good measure.
// WARNING: Delay is based on P-variant whereby non-P *may* require different timing.
delay
(
5
)
;
// Set 1500uS (minimum for 32B payload in ESB@250KBPS) timeouts, to make testing a little easier
// WARNING: If this is ever lowered, either 250KBS mode with AA is broken or maximum packet
// sizes must never be used. See documentation for a more complete explanation.
write_register
(
SETUP_RETR
,(
B0100
<<
ARD
)
|
(
B1111
<<
ARC
));
// Restore our default PA level
setPALevel
(
RF24_PA_MAX
)
;
// Determine if this is a p or non-p RF24 module and then
// reset our data rate back to default value. This works
// because a non-P variant won't allow the data rate to
// be set to 250Kbps.
if
(
setDataRate
(
RF24_250KBPS
)
)
{
p_variant
=
true
;
}
setDataRate
(
RF24_2MBPS
)
;
//
Set generous timeouts, to make testing a little easier
write_register
(
SETUP_RETR
,(
B1111
<<
ARD
)
|
(
B1111
<<
ARC
))
;
//
Initialize CRC and request 2-byte (16bit) CRC
setCRCLength
(
RF24_CRC_16
)
;
// Reset current status
// Notice reset and flush is the last thing we do
write_register
(
STATUS
,
_BV
(
RX_DR
)
|
_BV
(
TX_DS
)
|
_BV
(
MAX_RT
)
);
//
Initialize CRC
write_register
(
CONFIG
,
_BV
(
EN_CRC
)
);
//
Set up default configuration. Callers can always change it later.
setChannel
(
1
);
// Flush buffers
flush_rx
();
flush_tx
();
// Set up default configuration. Callers can always change it later.
setChannel
(
1
);
}
/****************************************************************************/
...
...
@@ -337,7 +383,7 @@ void RF24::startListening(void)
write_register
(
STATUS
,
_BV
(
RX_DR
)
|
_BV
(
TX_DS
)
|
_BV
(
MAX_RT
)
);
// Restore the pipe0 adddress
write_register
(
RX_ADDR_P0
,
reinterpret_cast
<
uint8_t
*>
(
&
pipe0_reading_address
),
5
);
write_register
(
RX_ADDR_P0
,
reinterpret_cast
<
const
uint8_t
*>
(
&
pipe0_reading_address
),
5
);
// Flush buffers
flush_rx
();
...
...
@@ -365,7 +411,14 @@ void RF24::powerDown(void)
/****************************************************************************/
bool
RF24
::
write
(
const
void
*
buf
,
uint8_t
len
)
void
RF24
::
powerUp
(
void
)
{
write_register
(
CONFIG
,
read_register
(
CONFIG
)
|
_BV
(
PWR_UP
));
}
/******************************************************************/
boolean
RF24
::
write
(
const
void
*
buf
,
uint8_t
len
)
{
bool
result
=
false
;
...
...
@@ -380,6 +433,9 @@ bool RF24::write( const void* buf, uint8_t len )
// or MAX_RT (maximum retries, transmission failed). Also, we'll timeout in case the radio
// is flaky and we get neither.
// 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 1500us.
// Monitor the send
uint8_t
observe_tx
;
uint8_t
status
;
uint32_t
sent_at
=
millis
();
...
...
@@ -524,9 +580,9 @@ void RF24::whatHappened(bool& tx_ok,bool& tx_fail,bool& rx_ready)
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.
// 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
);
write_register
(
RX_PW_P0
,
min
(
payload_size
,
32
));
...
...
@@ -534,7 +590,7 @@ void RF24::openWritingPipe(uint64_t value)
/****************************************************************************/
void
RF24
::
openReadingPipe
(
uint8_t
child
,
uint64_t
value
)
void
RF24
::
openReadingPipe
(
uint8_t
child
,
uint64_t
address
)
{
const
uint8_t
child_pipe
[]
=
{
...
...
@@ -553,15 +609,15 @@ void RF24::openReadingPipe(uint8_t child, uint64_t value)
// openWritingPipe() will overwrite the pipe 0 address, so
// startListening() will have to restore it.
if
(
child
==
0
)
pipe0_reading_address
=
value
;
pipe0_reading_address
=
address
;
if
(
child
<=
5
)
if
(
child
<=
6
)
{
// For pipes 2-5, only write the LSB
if
(
child
<
2
)
write_register
(
child_pipe
[
child
],
reinterpret_cast
<
uint8_t
*>
(
&
value
),
5
);
write_register
(
child_pipe
[
child
],
reinterpret_cast
<
const
uint8_t
*>
(
&
value
),
5
);
else
write_register
(
child_pipe
[
child
],
reinterpret_cast
<
uint8_t
*>
(
&
value
),
1
);
write_register
(
child_pipe
[
child
],
reinterpret_cast
<
const
uint8_t
*>
(
&
value
),
1
);
write_register
(
child_payload_size
[
child
],
payload_size
);
...
...
@@ -659,6 +715,12 @@ bool RF24::isAckPayloadAvailable(void)
/****************************************************************************/
boolean
RF24
::
isPVariant
(
void
)
{
return
p_variant
;
}
/******************************************************************/
void
RF24
::
setAutoAck
(
bool
enable
)
{
if
(
enable
)
...
...
@@ -669,38 +731,190 @@ void RF24::setAutoAck(bool enable)
/****************************************************************************/
bool
RF24
::
testCarrier
(
void
)
void
RF24
::
setAutoAck
(
uint8_t
pipe
,
bool
enable
)
{
if
(
pipe
<=
6
)
{
uint8_t
en_aa
=
read_register
(
EN_AA
)
;
if
(
enable
)
{
en_aa
|=
_BV
(
pipe
)
;
}
else
{
en_aa
&=
~
_BV
(
pipe
)
;
}
write_register
(
EN_AA
,
en_aa
)
;
}
}
/******************************************************************/
boolean
RF24
::
testCarrier
(
void
)
{
return
(
read_register
(
CD
)
&
1
);
}
/****************************************************************************/
void
RF24
::
setDataRate
(
rf24_datarate_e
speed
)
boolean
RF24
::
testRPD
(
void
)
{
return
(
read_register
(
RPD
)
&
1
)
;
}
/******************************************************************/
void
RF24
::
setPALevel
(
rf24_pa_dbm_e
level
)
{
uint8_t
setup
=
read_register
(
RF_SETUP
)
;
setup
&=
~
(
_BV
(
RF_PWR_LOW
)
|
_BV
(
RF_PWR_HIGH
))
;
switch
(
level
)
{
case
RF24_PA_MAX
:
setup
|=
(
_BV
(
RF_PWR_LOW
)
|
_BV
(
RF_PWR_HIGH
))
;
break
;
case
RF24_PA_HIGH
:
setup
|=
_BV
(
RF_PWR_HIGH
)
;
break
;
case
RF24_PA_LOW
:
setup
|=
_BV
(
RF_PWR_LOW
)
;
break
;
case
RF24_PA_MIN
:
break
;
case
RF24_PA_ERROR
:
// On error, go to maximum PA
setup
|=
(
_BV
(
RF_PWR_LOW
)
|
_BV
(
RF_PWR_HIGH
))
;
break
;
}
write_register
(
RF_SETUP
,
setup
)
;
}
/******************************************************************/
rf24_pa_dbm_e
RF24
::
getPALevel
(
void
)
{
rf24_pa_dbm_e
result
=
RF24_PA_ERROR
;
uint8_t
power
=
read_register
(
RF_SETUP
)
&
(
_BV
(
RF_PWR_LOW
)
|
_BV
(
RF_PWR_HIGH
))
;
switch
(
power
)
{
case
(
_BV
(
RF_PWR_LOW
)
|
_BV
(
RF_PWR_HIGH
)):
result
=
RF24_PA_MAX
;
break
;
case
_BV
(
RF_PWR_HIGH
):
result
=
RF24_PA_HIGH
;
break
;
case
_BV
(
RF_PWR_LOW
):
result
=
RF24_PA_LOW
;
break
;
default:
result
=
RF24_PA_MIN
;
break
;
}
return
result
;
}
/******************************************************************/
boolean
RF24
::
setDataRate
(
rf24_datarate_e
speed
)
{
uint8_t
setup
=
read_register
(
RF_SETUP
)
&
~
_BV
(
RF_DR
);
if
(
speed
==
RF24_2MBPS
)
setup
|=
_BV
(
RF_DR
);
uint8_t
setup
=
read_register
(
RF_SETUP
)
;
// HIGH and LOW '00' is 1Mbs - our default
wide_band
=
false
;
setup
&=
~
(
_BV
(
RF_DR_LOW
)
|
_BV
(
RF_DR_HIGH
))
;
if
(
speed
==
RF24_250KBPS
)
{
// Must set the RF_DR_LOW to 1; RF_DR_HIGH (used to be RF_DR) is already 0
// Making it '10'.
wide_band
=
false
;
setup
|=
_BV
(
RF_DR_LOW
)
;
}
else
{
// Set 2Mbs, RF_DR (RF_DR_HIGH) is set 1
// Making it '01'
if
(
speed
==
RF24_2MBPS
)
{
wide_band
=
true
;
setup
|=
_BV
(
RF_DR_HIGH
);
}
else
{
// 1Mbs
wide_band
=
false
;
}
}
write_register
(
RF_SETUP
,
setup
);
// Verify our result
setup
=
read_register
(
RF_SETUP
)
;
if
(
setup
==
setup
)
{
return
true
;
}
wide_band
=
false
;
return
false
;
}
/******************************************************************/
rf24_datarate_e
RF24
::
getDataRate
(
void
)
{
rf24_datarate_e
result
;
uint8_t
setup
=
read_register
(
RF_SETUP
)
;
// Order matters in our case below
switch
(
setup
&
(
_BV
(
RF_DR_LOW
)
|
_BV
(
RF_DR_HIGH
))
)
{
case
_BV
(
RF_DR_LOW
):
// '10' = 250KBPS
result
=
RF24_250KBPS
;
break
;
case
_BV
(
RF_DR_HIGH
):
// '01' = 2MBPS
result
=
RF24_2MBPS
;
break
;
default:
// '00' = 1MBPS
result
=
RF24_1MBPS
;
break
;
}
return
result
;
}
/****************************************************************************/
void
RF24
::
setCRCLength
(
rf24_crclength_e
length
)
{
uint8_t
config
=
read_register
(
CONFIG
)
&
~
_BV
(
CRCO
);
if
(
length
==
RF24_CRC_16
)
config
|=
_BV
(
CRCO
);
write_register
(
CONFIG
,
config
);
uint8_t
config
=
read_register
(
CONFIG
)
&
~
_BV
(
CRCO
)
;
// Always make sure CRC hardware validation is actually on
config
|=
_BV
(
EN_CRC
)
;
// Now config 8 or 16 bit CRCs - only 16bit need be turned on
// 8b is the default.
if
(
length
==
RF24_CRC_16
)
{
config
|=
_BV
(
CRCO
)
;
}
write_register
(
CONFIG
,
config
)
;
}
/******************************************************************
**********
/
/******************************************************************/
void
RF24
::
setRetries
(
uint8_t
delay
,
uint8_t
count
)
void
RF24
::
disableCRC
(
void
)
{
write_register
(
SETUP_RETR
,(
delay
&
0xf
)
<<
ARD
|
(
count
&
0xf
)
<<
ARC
);
uint8_t
disable
=
read_register
(
CONFIG
)
&
~
_BV
(
EN_CRC
)
;
write_register
(
CONFIG
,
disable
)
;
}
// vim:ai:cin:sts=2 sw=2 ft=cpp
RF24.h
View file @
602d9626
...
...
@@ -12,7 +12,8 @@
#include <stddef.h>
#include <avr/pgmspace.h>
typedef
enum
{
RF24_1MBPS
=
0
,
RF24_2MBPS
}
rf24_datarate_e
;
typedef
enum
{
RF24_PA_MIN
=
0
,
RF24_PA_LOW
,
RF24_PA_HIGH
,
RF24_PA_MAX
,
RF24_PA_ERROR
}
rf24_pa_dbm_e
;
typedef
enum
{
RF24_1MBPS
=
0
,
RF24_2MBPS
,
RF24_250KBPS
}
rf24_datarate_e
;
typedef
enum
{
RF24_CRC_8
=
0
,
RF24_CRC_16
}
rf24_crclength_e
;
/**
...
...
@@ -24,6 +25,8 @@ class RF24
private:
uint8_t
ce_pin
;
/**< "Chip Enable" pin, activates the RX or TX role */
uint8_t
csn_pin
;
/**< SPI Chip select */
bool
wide_band
;
/* 2Mbs data rate in use? */
bool
p_variant
;
/* False for RF24L01 and true for RF24L01P */
uint8_t
payload_size
;
/**< Fixed size of payloads */
bool
ack_payload_available
;
/**< Whether there is an ack payload waiting */
uint8_t
ack_payload_length
;
/**< Dynamic size of pending ack payload. Note: not used. */
...
...
@@ -42,6 +45,11 @@ protected:
/**
* Set chip select pin
*
* Running SPI bus at PI_CLOCK_DIV2 so we don't waste time transferring data
* and best of all, we make use of the radio's FIFO buffers. A lower speed
* means we're less likely to effectively leverage our FIFOs and pay a higher
* AVR runtime cost as toll.
*
* @param mode HIGH to take this unit off the SPI bus, LOW to put it on
*/
void
csn
(
int
mode
);
...
...
@@ -49,10 +57,10 @@ protected:
/**
* Set chip enable
*
* @param
mode
HIGH to actively begin transmission or LOW to put in standby. Please see data sheet
* @param
level
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
);
void
ce
(
int
level
);
/**
* Read a chunk of data in from a register
...
...
@@ -390,6 +398,13 @@ public:
*/
void
powerDown
(
void
);
/**
* Leave low-power mode - making radio more responsive
*
* To return to low power mode, call powerDown().
*/
void
powerUp
(
void
)
;
/**
* Test whether there are bytes available to be read
*
...
...
@@ -467,6 +482,14 @@ public:
*/
bool
isAckPayloadAvailable
(
void
);
/**
* Determine whether the hardware is an nRF24L01+ or not.
*
* @return true if the hardware is nRF24L01+ (or compatible) and false
* if its not.
*/
boolean
isPVariant
(
void
)
;
/**
* Call this when you get an interrupt to find out why
*
...
...
@@ -489,6 +512,17 @@ public:
*/
void
setAutoAck
(
bool
enable
);
/**
* Enable or disable auto-acknowlede packets on a per pipeline basis.
*
* AA is enabled by default, so it's only needed if you want to turn
* it off/on for some reason on a per pipeline basis.
*
* @param which pipeline to modify
* @param enable Whether to enable (true) or disable (false) auto-acks
*/
void
setAutoAck
(
uint8_t
pipe
,
bool
enable
)
;
/**
* Test whether there was a carrier on the line for the
* previous listening period.
...
...
@@ -499,10 +533,43 @@ public:
*/
bool
testCarrier
(
void
);
/**
* Test whether a signal (carrier or otherwise) greater than
* or equal to -64dBm is present on the channel. Valid only
* on nRF24L01P (+) hardware. On nRF24L01, use testCarrier().
*
* Useful to check for interference on the current channel and
* channel hopping strategies.
*
* @return true if signal => -64dBm, false if not
*/
boolean
testRPD
(
void
)
;
/**
* Set Power Amplifier (PA) level to one of four levels.
* Relative mnemonics have been used to allow for future PA level
* changes. According to 6.5 of the nRF24L01+ specification sheet,
* they translate to: RF24_PA_MIN=-18dBm, RF24_PA_LOW=-12dBm,
* RF24_PA_MED=-6dBM, and RF24_PA_HIGH=0dBm.
*
* @param Desired PA level.
*/
void
setPALevel
(
rf24_pa_dbm_e
level
)
;
/**
* Fetches the current PA level.
*
* @return Returns a value from the rf24_pa_dbm_e enum describing
* the current PA setting. Please remember, all values represented
* by the enum mnemonics are negative dBm. See setPALevel for
* return value descriptions.
*/
rf24_pa_dbm_e
getPALevel
(
void
)
;
/**
* Set the transmission data rate
*
* @param speed RF24_
1MBPS for 1Mbps
or RF24_2MBPS for 2Mbps
* @param speed RF24_
250KBPS for 250kbs, RF24_1MBPS for 1Mbps,
or RF24_2MBPS for 2Mbps
*/
void
setDataRate
(
rf24_datarate_e
speed
);
...
...
@@ -513,6 +580,12 @@ public:
*/
void
setCRCLength
(
rf24_crclength_e
length
);
/**
* Disable CRC validation
*
*/
void
disableCRC
(
void
)
;
/**@}*/
};
...
...
nRF24L01.h
View file @
602d9626
...
...
@@ -75,8 +75,7 @@
#define ARC 0
#define PLL_LOCK 4
#define RF_DR 3
#define RF_PWR 1
#define LNA_HCURR 0
#define RF_PWR 6
#define RX_DR 6
#define TX_DS 5
#define MAX_RT 4
...
...
@@ -112,3 +111,15 @@
#define FLUSH_RX 0xE2
#define REUSE_TX_PL 0xE3
#define NOP 0xFF
/* Non-P omissions */
#define LNA_HCURR 0
/* P model memory Map */
#define RPD 0x09
/* P model bit Mnemonics */
#define RF_DR_LOW 5
#define RF_DR_HIGH 3
#define RF_PWR_LOW 1
#define RF_PWR_HIGH 2
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment