nRF24L01 driver

Dependents:   Nucleo_IOT1 wireless

Revision:
0:7313e63394c3
Child:
1:cd113026825f
diff -r 000000000000 -r 7313e63394c3 nRF24L01P.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nRF24L01P.cpp	Sun Aug 11 11:58:05 2013 +0000
@@ -0,0 +1,555 @@
+#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,      0x07);
+   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 = 0x04;
+   char c = this->read_register(NRF24L01P_RF_SETUP);
+   this->write_register(NRF24L01P_RF_SETUP, (c & 0xDB) | 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;
+   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)
+{
+}
+
+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;
+}