36#include "../utilities.h"
41#include "nrf24l01p_internals.h"
109 NRF24L01(uint16_t net, uint8_t dev);
207 template<
typename T,
typename TREF = const T&>
208 int send(uint8_t dest, uint8_t port, TREF buf)
210 return send_(dest, port, (
const uint8_t*) &buf,
sizeof(T));
225 int send(uint8_t dest, uint8_t port)
227 return send_(dest, port,
nullptr, 0);
254 template<
typename T,
typename TREF = T&>
255 int recv(uint8_t& src, uint8_t& port, TREF buf, uint32_t ms = 0L)
257 return recv_(src, port, (uint8_t*) &buf,
sizeof(T), ms);
277 int recv(uint8_t& src, uint8_t& port, uint32_t ms = 0L)
279 return recv_(src, port,
nullptr, 0, ms);
328 template<
typename T,
typename TREF = const T&>
345 int send_(uint8_t dest, uint8_t port,
const uint8_t* buf,
size_t len);
346 int recv_(uint8_t& src, uint8_t& port, uint8_t* buf,
size_t size, uint32_t ms);
439 uint8_t reserved1 : 2;
443 uint8_t reserved2 : 1;
474 POWER_DOWN_STATE = 0,
493 uint8_t reserved : 1;
505 uint8_t read(uint8_t cmd)
508 status_ = status_t{this->
transfer(cmd)};
513 void write(uint8_t cmd)
516 status_ = status_t{this->
transfer(cmd)};
519 void write(uint8_t cmd, uint8_t data)
522 status_ = status_t{this->
transfer(cmd)};
526 void write(uint8_t cmd,
const uint8_t* buf,
size_t size)
529 status_ = status_t{this->
transfer(cmd)};
530 this->
transfer((uint8_t*) buf, size);
535 uint8_t read_command(
Command cmd)
537 return read(uint8_t(cmd));
539 void write_command(
Command cmd)
549 void write_register(
Register reg, uint8_t data)
553 void write_register(
Register reg,
const uint8_t* buf,
size_t size)
558 status_t read_status()
566 void transmit_mode(uint8_t dest);
570 int read_fifo_payload(uint8_t& src, uint8_t& port, uint8_t* buf,
size_t count);
571 fifo_status_t read_fifo_status()
575 observe_tx_t read_observe_tx()
582 static const uint8_t DEFAULT_CHANNEL = 64;
587 uint8_t channel_ = DEFAULT_CHANNEL;
590 status_t status_ = status_t{0};
591 State state_ = State::POWER_DOWN_STATE;
594 uint16_t retrans_ = 0;
629 template<board::DigitalPin CSN, board::DigitalPin CE, board::ExternalInterruptPin IRQ>
668 template<board::DigitalPin CSN, board::DigitalPin CE>
673 using namespace nrf24l01p_internals;
675 write_register(Register::FEATURE, (
bits::BV8(EN_DPL, EN_ACK_PAY, EN_DYN_ACK)));
676 write_register(Register::RF_CH, channel_);
677 write_register(Register::RF_SETUP, RF_DR_2MBPS | RF_PWR_0DBM);
678 write_register(Register::SETUP_RETR, uint8_t(DEFAULT_ARD << ARD) | uint8_t(DEFAULT_ARC << ARC));
679 write_register(Register::DYNPD, DPL_PA);
686 write_register(Register::SETUP_AW, AW_3BYTES);
687 write_register(Register::RX_ADDR_P1, (
const uint8_t*) &rx_addr,
sizeof(rx_addr));
688 write_register(Register::RX_ADDR_P2, BROADCAST);
689 write_register(Register::EN_RXADDR,
bits::BV8(ERX_P2, ERX_P1));
690 write_register(Register::EN_AA,
bits::BV8(ENAA_P1, ENAA_P0));
698 using namespace nrf24l01p_internals;
699 if (state_ != State::POWER_DOWN_STATE)
return;
703 write_register(Register::CONFIG,
bits::BV8(EN_CRC, CRCO, PWR_UP));
705 state_ = State::STANDBY_STATE;
708 write_register(Register::STATUS,
bits::BV8(RX_DR, TX_DS, MAX_RT));
709 write_command(Command::FLUSH_TX);
710 write_command(Command::FLUSH_RX);
715 if (state_ == State::STANDBY_STATE)
return;
717 state_ = State::STANDBY_STATE;
722 using namespace nrf24l01p_internals;
723 if (state_ == State::POWER_DOWN_STATE)
return;
725 write_register(Register::CONFIG,
bits::BV8(EN_CRC, CRCO));
726 state_ = State::POWER_DOWN_STATE;
730 template<board::DigitalPin CSN, board::DigitalPin CE>
733 using namespace nrf24l01p_internals;
742 Command command = ((dest != BROADCAST) ? Command::W_TX_PAYLOAD : Command::W_TX_PAYLOAD_NO_ACK);
743 this->start_transfer();
744 status_ = status_t{this->transfer(uint8_t(command))};
745 this->transfer(addr_.device);
746 this->transfer(port);
747 this->transfer(buf, len);
748 this->end_transfer();
753 if (dest != BROADCAST)
755 addr_t tx_addr(addr_.network, dest);
756 write_register(Register::RX_ADDR_P0, (
const uint8_t*) &tx_addr,
sizeof(tx_addr));
757 write_register(Register::EN_RXADDR,
bits::BV8(ERX_P2, ERX_P1, ERX_P0));
761 status_t status = status_t{0};
764 status = read_status();
765 if (status.tx_ds || status.max_rt)
break;
769 bool data_sent = status.tx_ds;
772 if (dest != BROADCAST) write_register(Register::EN_RXADDR,
bits::BV8(ERX_P2, ERX_P1));
775 write_register(Register::STATUS,
bits::BV8(TX_DS, MAX_RT));
778 observe_tx_t observe = read_observe_tx();
779 retrans_ += observe.arc_cnt;
782 if (data_sent)
return len;
785 write_command(Command::FLUSH_TX);
791 template<board::DigitalPin CSN, board::DigitalPin CE>
792 int NRF24L01<CSN, CE>::recv_(uint8_t& src, uint8_t& port, uint8_t* buf,
size_t size, uint32_t ms)
806 return read_fifo_payload(src, port, buf, size);
812 using namespace nrf24l01p_internals;
822 write_register(Register::RF_SETUP, RF_DR_2MBPS | pwr);
828 using namespace nrf24l01p_internals;
830 addr_t tx_addr(addr_.network, dest);
831 write_register(Register::TX_ADDR, (
const uint8_t*) &tx_addr,
sizeof(tx_addr));
834 if (state_ != State::TX_STATE)
837 write_register(Register::CONFIG,
bits::BV8(EN_CRC, CRCO, PWR_UP));
843 state_ = State::TX_STATE;
846 template<board::DigitalPin CSN, board::DigitalPin CE>
void NRF24L01<CSN, CE>::receive_mode()
848 using namespace nrf24l01p_internals;
850 if (state_ == State::RX_STATE)
return;
853 write_register(Register::CONFIG,
bits::BV8(EN_CRC, CRCO, PWR_UP, PRIM_RX));
856 state_ = State::RX_STATE;
859 template<board::DigitalPin CSN, board::DigitalPin CE>
bool NRF24L01<CSN, CE>::available()
862 if (read_fifo_status().rx_empty)
return false;
865 if (read_command(Command::R_RX_PL_WID) <= DEVICE_PAYLOAD_MAX)
return true;
866 write_command(Command::FLUSH_RX);
870 template<board::DigitalPin CSN, board::DigitalPin CE>
871 int NRF24L01<CSN, CE>::read_fifo_payload(uint8_t& src, uint8_t& port, uint8_t* buf,
size_t size)
874 uint8_t count = read_command(Command::R_RX_PL_WID) - 2;
875 if ((count > PAYLOAD_MAX) || (count > size))
877 write_command(Command::FLUSH_RX);
882 dest_ = (read_status().rx_p_no == 1 ? addr_.device : BROADCAST);
885 this->start_transfer();
886 status_ = status_t{this->transfer(uint8_t(Command::R_RX_PAYLOAD))};
887 src = this->transfer(0);
888 port = this->transfer(0);
889 this->transfer(buf, count, uint8_t(Command::NOP));
890 this->end_transfer();
SPI device driver for Nordic Semiconductor nRF24L01+ support, with IRQ.
IRQ_NRF24L01(uint16_t net, uint8_t dev)
Construct NRF transceiver with given channel and pin numbers for SPI slave select,...
void end()
Shut down the device driver.
void begin()
Start up the device driver.
SPI device driver for Nordic Semiconductor nRF24L01+ support, without IRQ support.
void set_output_power_level(int8_t dBm)
Set output power level (-30..10 dBm)
uint8_t get_device_address() const
Get driver device address.
uint16_t get_trans() const
Return number of transmitted messages.
uint16_t get_retrans() const
Return number of retransmissions.
int send(uint8_t dest, uint8_t port, TREF buf)
Send message with given object reference.
int send(uint8_t dest, uint8_t port)
Send an empty message.
void powerdown()
Set power down.
uint16_t get_drops() const
Return number of dropped messages.
void set_channel(uint8_t channel)
Set device transmission channel.
void set_address(int16_t net, uint8_t dev)
Set network and device address.
void end()
Shut down the device driver.
static const size_t DEVICE_PAYLOAD_MAX
Maximum size of payload on device.
static const uint8_t BROADCAST
Broadcast device address.
NRF24L01(uint16_t net, uint8_t dev)
Construct NRF transceiver with given channel and pin numbers for SPI slave select,...
int recv(uint8_t &src, uint8_t &port, uint32_t ms=0L)
Receive an empty message.
int recv(uint8_t &src, uint8_t &port, TREF buf, uint32_t ms=0L)
Receive message and store into given object reference.
bool is_broadcast() const
Return true if the latest received message was a broadcast otherwise false.
int broadcast(uint8_t port, TREF buf)
Broadcast message with given object reference.
void powerup()
Set power up mode.
uint8_t get_channel() const
Get driver channel.
State
NRF transceiver states (See chap.
void standby()
Set standby mode.
Command
SPI Commands (See chap.
@ NOP
No operation, return status.
@ R_REGISTER
Read command and status register.
@ R_RX_PAYLOAD
Read RX payload.
@ R_RX_PL_WID
Read RX payload width.
@ W_TX_PAYLOAD_NO_ACK
Disable AUTOACK on this specific packet.
@ W_REGISTER
Write command and status register.
@ W_ACK_PAYLOAD
Write TX payload with ACK (3 bit addr).
@ W_TX_PAYLOAD
Write TX payload.
@ PIPE_MASK
Mask pipe address.
@ REG_MASK
Mask register address (5b).
@ REUSE_TX_PL
Reuse last transmitted payload.
static const size_t PAYLOAD_MAX
Maximum size of payload.
uint16_t get_network_address() const
Get driver network address.
Register
NRF transceiver registers map (See chap.
@ RF_SETUP
RF setup register.
@ TX_ADDR
Transmit address.
@ SETUP_RETR
Setup of auto retransmission.
@ RX_ADDR_P0
Receive address data pipe 0.
@ SETUP_AW
Setup of address width.
@ EN_AA
Enable auto acknowledgement.
@ FIFO_STATUS
FIFO status register.
@ CONFIG
Configuration register.
@ RX_PW_P0
Number of bytes in RX payload in data pipe 0.
@ DYNPD
Enable dynamic payload length.
@ FEATURE
Feature register.
@ RPD
Received power detector.
@ EN_RXADDR
Enable rx addresses.
@ OBSERVE_TX
Transmit observe register.
void begin()
Start up the device driver.
API that manipulates a given digital IO pin of a the target MCU.
Handler of an External Interrupt.
void disable()
Disable interrupts for this external interrupt pin.
void enable()
Enable interrupts for this external interrupt pin.
uint8_t transfer(uint8_t data)
Transfer one byte to the currently selected SPI slave device through MOSI pin, and get the byte retur...
Base class for any SPI slave device.
void start_transfer()
Start an SPI transfer to this device.
void end_transfer() INLINE
End the current SPI ransfer tot hsi device.
#define INLINE
Specific GCC attribute to force the compiler to always inline code of a given function.
static constexpr uint8_t BV8(uint8_t bit)
Create a uint8_t bitmask for the given bit number.
Defines the API for radio-frequency (wireless) communication support.
Defines all API for all external devices supported by FastArduino.
constexpr const int EINVAL
Invalid argument or invalid Future.
constexpr const int EIO
Input/output error.
constexpr const int EMSGSIZE
Message too long.
constexpr const int ETIME
Timer expired.
typename FastPinType< DPIN_ >::TYPE FAST_PIN
Useful alias type to the FastPin type matching a given board::DigitalPin.
@ OUTPUT
Digital pin is configured as output.
@ INPUT_PULLUP
Digital pin is configured as input with an internal pullup resistor.
@ FALLING_EDGE
Interrupt is triggered whenever pin level is falling from high to low.
MILLIS_PTR millis
Count number of milliseconds elapsed since some time base reference (generally since MCU startup).
void delay_us(uint16_t us) INLINE
Delay program execution for the given amount of microseconds.
void yield()
Utility method used by many FastArduino API in order to "yield" some processor time; concretely it ju...
uint32_t since(uint32_t start_ms)
Compute the time elapsed, in milliseconds, since start_ms.
void delay_ms(uint16_t ms) INLINE
Delay program execution for the given amount of milliseconds.
Network address together with port.
uint8_t device
Device address (LSB).
addr_t(uint16_t net, uint8_t dev) INLINE
Create an addr_t from a netwrok and a device address.
uint16_t network
Network address.
Register FIFO_STATUS data type, transmission queue status.
uint8_t as_byte
Byte representation of fifo status.
bool rx_empty
RX FIFO empty flag.
fifo_status_t(uint8_t value) INLINE
Construct transmitter queue status from register reading.
bool tx_reuse
Reuse last transmitted data packat.
bool tx_empty
TX FIFO empty flag.
bool tx_full
TX FIFO full flag.
bool rx_full
RX FIFO full flag.
Register OBSERVE_TX data type, performance statistics.
observe_tx_t(uint8_t value) INLINE
Construct transmitter performance statistics from register reading.
uint8_t as_byte
Byte representation of performance statistics.
uint8_t plos_cnt
Count lost packets.
uint8_t arc_cnt
Count retransmitted packets.
Register STATUS data type.
status_t(uint8_t value) INLINE
Construct status from register reading.
bool tx_ds
Data send TX FIFO interrupt.
uint8_t rx_p_no
Data pipe number for available payload.
uint8_t as_byte
Byte representation of status.
bool tx_full
TX FIFO full.
bool max_rt
Max number of TX retransmit interrupt.
bool rx_dr
Data ready RX FIFO interrupt.