nRF24L01 driver
Dependents: Nucleo_IOT1 wireless
nRF24L01P.cpp
- Committer:
- ianmcc
- Date:
- 2016-09-14
- Revision:
- 6:952996e3abdb
- Parent:
- 4:8f612189af31
File content as of revision 6:952996e3abdb:
#include "nRF24L01P.h" #define NRF24L01P_SPI_MAX_DATA_RATE 10000000 #define NRF24L01P_CMD_R_REGISTER 0x00 #define NRF24L01P_CMD_W_REGISTER 0x20 #define NRF24L01P_CMD_R_RX_PAYLOAD 0x61 #define NRF24L01P_CMD_W_TX_PAYLOAD 0xA0 #define NRF24L01P_CMD_FLUSH_TX 0xE1 #define NRF24L01P_CMD_FLUSH_RX 0xE2 #define NRF24L01P_CMD_REUSE_TX_PL 0xE3 #define NRF24L01P_CMD_R_RX_PL_WID 0x60 #define NRF24L01P_CMD_W_ACK_PAYLOAD 0xA8 #define NRF24L01P_CMD_W_TX_PYLD_NO_ACK 0xB0 #define NRF24L01P_CMD_NOP 0xFF // registers #define NRF24L01P_CONFIG 0x00 #define NRF24L01P_EN_AA 0x01 #define NRF24L01P_EN_RXADDR 0x02 #define NRF24L01P_SETUP_AW 0x03 #define NRF24L01P_SETUP_RETR 0x04 #define NRF24L01P_RF_CH 0x05 #define NRF24L01P_RF_SETUP 0x06 #define NRF24L01P_STATUS 0x07 #define NRF24L01P_OBSERVE_TX 0x08 #define NRF24L01P_RPD 0x09 #define NRF24L01P_RX_ADDR_P0 0x0A #define NRF24L01P_RX_ADDR_P1 0x0B #define NRF24L01P_RX_ADDR_P2 0x0C #define NRF24L01P_RX_ADDR_P3 0x0D #define NRF24L01P_RX_ADDR_P4 0x0E #define NRF24L01P_RX_ADDR_P5 0x0F #define NRF24L01P_TX_ADDR 0x10 #define NRF24L01P_RX_PW_P0 0x11 #define NRF24L01P_RX_PW_P1 0x12 #define NRF24L01P_RX_PW_P2 0x13 #define NRF24L01P_RX_PW_P3 0x14 #define NRF24L01P_RX_PW_P4 0x15 #define NRF24L01P_RX_PW_P5 0x16 #define NRF24L01P_FIFO_STATUS 0x17 #define NRF24L01P_DYNPD 0x1C #define NRF24L01P_FEATURE 0x1D #define NRF24L01P_MAX 0x1F nRF24L01P::nRF24L01P(PinName mosi, PinName miso, PinName sck, PinName csn, long SPIFrequency) : Spi(mosi, miso, sck), NCS(csn) { Spi.format(8,0); // 8-bit, ClockPhase = 0, ClockPolarity = 0 Spi.frequency(SPIFrequency); NCS = 1; this->reset(); } void nRF24L01P::reset() { this->write_register(NRF24L01P_CONFIG, 0x08); // power down this->flush_tx_fifo(); this->flush_rx_fifo(); this->write_register(NRF24L01P_EN_AA, 0x3F); this->write_register(NRF24L01P_EN_RXADDR, 0x03); this->write_register(NRF24L01P_SETUP_AW, 0x03); this->write_register(NRF24L01P_SETUP_RETR, 0x03); this->write_register(NRF24L01P_RF_CH, 0x02); this->write_register(NRF24L01P_RF_SETUP, 0x0F); this->write_register(NRF24L01P_STATUS, 0x0E); this->write_register_40(NRF24L01P_RX_ADDR_P0, 0xE7E7E7E7E7ULL); this->write_register_40(NRF24L01P_RX_ADDR_P1, 0xC2C2C2C2C2ULL); this->write_register(NRF24L01P_RX_ADDR_P2, 0xC3); this->write_register(NRF24L01P_RX_ADDR_P3, 0xC4); this->write_register(NRF24L01P_RX_ADDR_P4, 0xC4); this->write_register(NRF24L01P_RX_ADDR_P5, 0xC5); this->write_register_40(NRF24L01P_TX_ADDR, 0xE7E7E7E7E7ULL); this->write_register(NRF24L01P_RX_PW_P0, 0x00); this->write_register(NRF24L01P_RX_PW_P1, 0x00); this->write_register(NRF24L01P_RX_PW_P2, 0x00); this->write_register(NRF24L01P_RX_PW_P3, 0x00); this->write_register(NRF24L01P_RX_PW_P4, 0x00); this->write_register(NRF24L01P_RX_PW_P5, 0x00); this->write_register(NRF24L01P_FIFO_STATUS, 0x00); this->write_register(NRF24L01P_DYNPD, 0x00); this->write_register(NRF24L01P_FEATURE, 0x00); } void nRF24L01P::set_spi_frequency(long Freq) { Spi.frequency(Freq); } void nRF24L01P::set_air_data_rate(int Rate) { char r = 0; if (Rate == 250) r = 0x20; else if (Rate == 1000) r = 0x00; else if (Rate == 2000) r = 0x08; char c = this->read_register(NRF24L01P_RF_SETUP); this->write_register(NRF24L01P_RF_SETUP, (c & 0xD7) | r); } void nRF24L01P::set_channel(int Channel) { char c = Channel; c = c & 0x7F; this->write_register(NRF24L01P_RF_CH, c); } bool nRF24L01P::received_power_detector() { return this->read_register(NRF24L01P_RPD) == 0x01; } void nRF24L01P::set_tx_power(int Power) { char p = 0; if (Power == 0) p = 0x03; else if (Power == -6) p = 0x02; else if (Power == -12) p = 0x01; else if (Power == -18) p = 0x00; char c = this->read_register(NRF24L01P_RF_SETUP); this->write_register(NRF24L01P_RF_SETUP, (c & 0xFC) | p); } void nRF24L01P::enable_dynamic_payload(int Pipe, bool Enable) { char Mask = 1 << Pipe; char c = this->read_register(NRF24L01P_DYNPD); if (Enable) c = c | Mask; else c = c & ~Mask; this->write_register(NRF24L01P_DYNPD, c); } void nRF24L01P::enable_ack_payload(bool Enable) { char c = this->read_register(NRF24L01P_FEATURE); this->write_register(NRF24L01P_FEATURE, Enable ? (c | 0x02) : (c & 0xFD)); } void nRF24L01P::enable_no_ack(bool Enable) { char c = this->read_register(NRF24L01P_FEATURE); this->write_register(NRF24L01P_FEATURE, Enable ? (c | 0x01) : (c & 0xFE)); } void nRF24L01P::set_address_width(int Width) { char c = 0; if (Width == 3) c = 0x01; else if (Width == 4) c = 0x02; else if (Width == 5) c = 0x03; this->write_register(NRF24L01P_SETUP_AW, c); } int nRF24L01P::get_address_width() { int r = this->read_register(NRF24L01P_SETUP_AW); switch (r & 0x03) { case 0x01 : return 3; case 0x02 : return 4; case 0x03 : return 5; } return 0; } void nRF24L01P::set_rx_address(int Pipe, uint64_t Address) { if (Pipe < 0 || Pipe > 1) error("RF24L01P::set_rx_address: invalid pipe"); this->write_register_40(NRF24L01P_RX_ADDR_P0+Pipe, Address); } void nRF24L01P::set_rx_address_low(int Pipe, uint8_t Address) { this->write_register(NRF24L01P_RX_ADDR_P0+Pipe, Address); } void nRF24L01P::set_rx_payload_bytes(int Pipe, int Bytes) { this->write_register(NRF24L01P_RX_PW_P0+Pipe, Bytes & 0x1F); } bool nRF24L01P::is_rx_full() { return (this->read_register(NRF24L01P_FIFO_STATUS) & 0x02) != 0x00; } bool nRF24L01P::is_rx_empty() { return (this->read_register(NRF24L01P_FIFO_STATUS) & 0x01) != 0x00; } bool nRF24L01P::is_rx_ready() { return (this->read_register(NRF24L01P_STATUS) & 0x40) != 0x00; } void nRF24L01P::clear_rx_ready() { char c = this->read_register(NRF24L01P_STATUS); this->write_register(NRF24L01P_STATUS, c | 0x40); } void nRF24L01P::set_interrupt_rx_ready(bool Enable) { char c = this->read_register(NRF24L01P_CONFIG); this->write_register(NRF24L01P_CONFIG, Enable ? (c & 0xBF) : (c | 0x40)); } bool nRF24L01P::is_tx_full() { return (this->read_register(NRF24L01P_FIFO_STATUS) & 0x20) != 0x00; } bool nRF24L01P::is_tx_empty() { return (this->read_register(NRF24L01P_FIFO_STATUS) & 0x10) != 0x00; } bool nRF24L01P::is_tx_sent() { return (this->read_register(NRF24L01P_STATUS) & 0x20) != 0x00; } void nRF24L01P::clear_tx_sent() { char c = this->read_register(NRF24L01P_STATUS); this->write_register(NRF24L01P_STATUS, c | 0x20); } void nRF24L01P::set_interrupt_tx(bool Enable) { char c = this->read_register(NRF24L01P_CONFIG); this->write_register(NRF24L01P_CONFIG, Enable ? (c & 0xDF) : (c | 0x20)); } void nRF24L01P::set_retransmit_delay(int Delay) { char c = this->read_register(NRF24L01P_SETUP_RETR); this->write_register(NRF24L01P_SETUP_RETR, (c & 0x0f) | ((Delay & 0x0f) << 4)); } void nRF24L01P::set_retransmit_attempts(int Attempts) { char c = this->read_register(NRF24L01P_SETUP_RETR); this->write_register(NRF24L01P_SETUP_RETR, (c & 0xf0) | (Attempts & 0x0f)); } bool nRF24L01P::is_max_rt() { return (this->read_register(NRF24L01P_STATUS) & 0x10) != 0x00; } void nRF24L01P::clear_max_rt() { char c = this->read_register(NRF24L01P_STATUS); this->write_register(NRF24L01P_STATUS, c | 0x10); } void nRF24L01P::set_interrupt_max_rt(bool Enable) { char c = this->read_register(NRF24L01P_CONFIG); this->write_register(NRF24L01P_CONFIG, Enable ? (c & 0xEF) : (c | 0x10)); } void nRF24L01P::set_crc_width(int Width) { char c = this->read_register(NRF24L01P_CONFIG); this->write_register(NRF24L01P_CONFIG, Width == 1 ? (c & 0xFB) : (c | 0x04)); } void nRF24L01P::enable_crc(bool Enable) { char c = this->read_register(NRF24L01P_CONFIG); this->write_register(NRF24L01P_CONFIG, Enable ? (c | 0x08) : (c & 0xF7)); } void nRF24L01P::set_power_up() { char c = this->read_register(NRF24L01P_CONFIG); this->write_register(NRF24L01P_CONFIG, c | 0x02); } void nRF24L01P::set_power_down() { char c = this->read_register(NRF24L01P_CONFIG); this->write_register(NRF24L01P_CONFIG, c & 0xFD); } void nRF24L01P::set_prx_mode() { char c = this->read_register(NRF24L01P_CONFIG); this->write_register(NRF24L01P_CONFIG, c | 0x01); } void nRF24L01P::set_ptx_mode() { char c = this->read_register(NRF24L01P_CONFIG); this->write_register(NRF24L01P_CONFIG, c & 0xFE); } void nRF24L01P::set_auto_acknowledge(int Pipe, bool Enable) { char c = this->read_register(NRF24L01P_EN_AA); char Mask = 1 << Pipe; this->write_register(NRF24L01P_EN_AA, Enable ? (c | Mask) : (c & ~Mask)); } void nRF24L01P::enable_rx_pipe(int Pipe, bool Enable) { char c = this->read_register(NRF24L01P_EN_RXADDR); char Mask = 1 << Pipe; this->write_register(NRF24L01P_EN_RXADDR, Enable ? (c | Mask) : (c & ~Mask)); } int nRF24L01P::which_rx_pipe() { return (this->read_register(NRF24L01P_STATUS) & 0x0E) >> 1; } bool nRF24L01P::tx_full() { return this->read_register(NRF24L01P_STATUS) & 0x01; } int nRF24L01P::num_lost_packets() { return (this->read_register(NRF24L01P_OBSERVE_TX) & 0xF0) >> 4; } int nRF24L01P::num_retransmitted_packets() { return this->read_register(NRF24L01P_OBSERVE_TX) & 0x0F; } void nRF24L01P::set_tx_address(uint64_t Address) { this->write_register_40(NRF24L01P_TX_ADDR, Address); } // commands int nRF24L01P::read_register(int Register) { NCS = 0; Spi.write(NRF24L01P_CMD_R_REGISTER | Register); int Result = Spi.write(NRF24L01P_CMD_NOP); NCS = 1; return Result; } int nRF24L01P::read_register_n(int Register, char* Buf, int Bytes) { NCS = 0; Spi.write(NRF24L01P_CMD_R_REGISTER | Register); for (int i = 0; i < Bytes; ++i) { *Buf++ = Spi.write(NRF24L01P_CMD_NOP); } NCS = 1; return 0; } int nRF24L01P::write_register(int Register, char x) { NCS = 0; Spi.write(NRF24L01P_CMD_W_REGISTER | Register); Spi.write(x); NCS = 1; return 0; } int nRF24L01P::write_register_16(int Register, uint16_t x) { NCS = 0; Spi.write(NRF24L01P_CMD_W_REGISTER | Register); Spi.write(x & 0xFF); Spi.write((x >> 8) & 0xFF); NCS = 1; return 0; } int64_t nRF24L01P::write_register_40(int Register, uint64_t x) { NCS = 0; Spi.write(NRF24L01P_CMD_W_REGISTER | Register); Spi.write(x & 0xFF); x = x >> 8; Spi.write(x & 0xFF); x = x >> 8; Spi.write(x & 0xFF); x = x >> 8; Spi.write(x & 0xFF); x = x >> 8; Spi.write(x & 0xFF); NCS = 1; return 0; } int nRF24L01P::write_register_bytes(int Register, char const* Buf, int Bytes) { NCS = 0; Spi.write(NRF24L01P_CMD_W_REGISTER | Register); for (int i = 0; i < Bytes; ++i) { Spi.write(*Buf++); } NCS = 1; return 0; } void nRF24L01P::write_tx_payload(char const* Buf, int Bytes) { NCS = 0; Spi.write(NRF24L01P_CMD_W_TX_PAYLOAD); for (int i = 0; i < Bytes; ++i) { Spi.write(*Buf++); } NCS = 1; } void nRF24L01P::write_tx_payload_no_ack(char const* Buf, int Bytes) { NCS = 0; Spi.write(NRF24L01P_CMD_W_TX_PYLD_NO_ACK); for (int i = 0; i < Bytes; ++i) { Spi.write(*Buf++); } NCS = 1; } void nRF24L01P::flush_tx_fifo() { NCS = 0; Spi.write(NRF24L01P_CMD_FLUSH_TX); NCS = 1; } void nRF24L01P::reuse_tx_payload() { NCS = 0; Spi.write(NRF24L01P_CMD_REUSE_TX_PL); NCS = 1; } int nRF24L01P::rx_payload_width() { NCS = 0; Spi.write(NRF24L01P_CMD_R_RX_PL_WID); int Result = Spi.write(NRF24L01P_CMD_NOP); NCS = 1; return Result; } void nRF24L01P::read_rx_payload(char* Buf, int Bytes) { NCS = 0; Spi.write(NRF24L01P_CMD_R_RX_PAYLOAD); for (int i = 0; i < Bytes; ++i) { *Buf++ = Spi.write(NRF24L01P_CMD_NOP); } NCS = 1; } int nRF24L01P::read_rx_payload(char* Buf) { this->read_rx_payload(Buf, this->rx_payload_width()); return 0; } void nRF24L01P::flush_rx_fifo() { NCS = 0; Spi.write(NRF24L01P_CMD_FLUSH_RX); NCS = 1; } void nRF24L01P::write_ack_payload(int Pipe, char const* Buf, int Bytes) { NCS = 0; Spi.write(NRF24L01P_CMD_W_ACK_PAYLOAD); for (int i = 0; i < Bytes; ++i) { Spi.write(*Buf++); } NCS = 1; }