summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile11
-rw-r--r--include/driver/nrf24l01.h69
-rw-r--r--include/driver/nrf24l01/registers.h127
-rw-r--r--src/app/nrf24l01test/Makefile.inc2
-rw-r--r--src/app/nrf24l01test/main.cc26
-rw-r--r--src/driver/nrf24l01.cc95
6 files changed, 330 insertions, 0 deletions
diff --git a/Makefile b/Makefile
index 179c493..5740eec 100644
--- a/Makefile
+++ b/Makefile
@@ -58,6 +58,17 @@ ifneq ($(findstring mmsimple,${drivers}), )
COMMON_FLAGS += -DDRIVER_MMSIMPLE
endif
+ifneq ($(findstring nrf24l01,${drivers}), )
+ CXX_TARGETS += src/driver/nrf24l01.cc
+ nrf24l01_en_pin ?= p4_3
+ nrf24l01_cs_pin ?= p2_4
+ nrf24l01_irq_pin ?= p1_5
+ COMMON_FLAGS += -DDRIVER_NRF24L01
+ COMMON_FLAGS += -DNRF24L01_EN_PIN=GPIO::${nrf24l01_en_pin}
+ COMMON_FLAGS += -DNRF24L01_CS_PIN=GPIO::${nrf24l01_cs_pin}
+ COMMON_FLAGS += -DNRF24L01_IRQ_PIN=GPIO::${nrf24l01_irq_pin}
+endif
+
ifneq ($(findstring sharp96,${drivers}), )
CXX_TARGETS += src/driver/sharp96.cc
sharp96_power_pin ?= p1_2
diff --git a/include/driver/nrf24l01.h b/include/driver/nrf24l01.h
new file mode 100644
index 0000000..911ef58
--- /dev/null
+++ b/include/driver/nrf24l01.h
@@ -0,0 +1,69 @@
+#ifndef NRF24L01_H
+#define NRF24L01_H
+
+#include <stdint.h>
+#include "driver/gpio.h"
+#include "arch.h"
+
+class Nrf24l01 {
+ private:
+ Nrf24l01(const Nrf24l01 &copy);
+ unsigned char txbuf[2];
+ unsigned char rxbuf[2];
+
+ uint8_t writeRegister(uint8_t reg, uint8_t value);
+ uint8_t readRegister(uint8_t reg);
+
+ inline void csnHigh() {
+ gpio.write(NRF24L01_CS_PIN, 1);
+ arch.delay_us(5);
+ }
+ inline void csnLow() {
+ gpio.write(NRF24L01_CS_PIN, 0);
+ arch.delay_us(5);
+ }
+ inline void beginTransaction() {
+ csnLow();
+ }
+ inline void endTransaction() {
+ csnHigh();
+ }
+
+ public:
+ Nrf24l01() {}
+
+ /**
+ * Power Amplifier level.
+ *
+ * For use with setPALevel()
+ */
+ enum rf24_pa_dbm_e { RF24_PA_MIN = 0,RF24_PA_LOW, RF24_PA_HIGH, RF24_PA_MAX, RF24_PA_ERROR };
+
+ /**
+ * Data rate. How fast data moves through the air.
+ *
+ * For use with setDataRate()
+ */
+ enum rf24_datarate_e { RF24_1MBPS = 0, RF24_2MBPS, RF24_250KBPS };
+
+ /**
+ * CRC Length. How big (if any) of a CRC is included.
+ *
+ * For use with setCRCLength()
+ */
+ enum rf24_crclength_e { RF24_CRC_DISABLED = 0, RF24_CRC_8, RF24_CRC_16 };
+
+
+ void setup();
+ void powerOn();
+ void powerOff();
+
+ void setRetries(uint8_t delay, uint8_t count);
+ void setPALevel ( uint8_t level ); // 0 (-18B), 1 (-12dB), 2 (-6dB), 3 (0dB)
+
+ uint8_t getStatus();
+};
+
+extern Nrf24l01 nrf24l01;
+
+#endif
diff --git a/include/driver/nrf24l01/registers.h b/include/driver/nrf24l01/registers.h
new file mode 100644
index 0000000..51ab310
--- /dev/null
+++ b/include/driver/nrf24l01/registers.h
@@ -0,0 +1,127 @@
+/*
+ Copyright (c) 2007 Stefan Engelke <mbox@stefanengelke.de>
+ Portions Copyright (C) 2011 Greg Copeland
+
+ 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 NRF_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 NRF_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
+#define DYNPD 0x1C
+#define FEATURE 0x1D
+
+/* 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 6
+#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
+#define DPL_P5 5
+#define DPL_P4 4
+#define DPL_P3 3
+#define DPL_P2 2
+#define DPL_P1 1
+#define DPL_P0 0
+#define EN_DPL 2
+#define EN_ACK_PAY 1
+#define EN_DYN_ACK 0
+
+/* Instruction Mnemonics */
+#define R_REGISTER 0x00
+#define W_REGISTER 0x20
+#define REGISTER_MASK 0x1F
+#define ACTIVATE 0x50
+#define R_RX_PL_WID 0x60
+#define R_RX_PAYLOAD 0x61
+#define W_TX_PAYLOAD 0xA0
+#define W_ACK_PAYLOAD 0xA8
+#define FLUSH_TX 0xE1
+#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
+#define W_TX_PAYLOAD_NO_ACK 0xB0
+
+/* P model bit Mnemonics */
+#define RF_DR_LOW 5
+#define RF_DR_HIGH 3
+#define RF_PWR_LOW 1
+#define RF_PWR_HIGH 2
diff --git a/src/app/nrf24l01test/Makefile.inc b/src/app/nrf24l01test/Makefile.inc
new file mode 100644
index 0000000..67e9c68
--- /dev/null
+++ b/src/app/nrf24l01test/Makefile.inc
@@ -0,0 +1,2 @@
+timer_s ?= 1
+loop ?= 1
diff --git a/src/app/nrf24l01test/main.cc b/src/app/nrf24l01test/main.cc
new file mode 100644
index 0000000..2f65a7c
--- /dev/null
+++ b/src/app/nrf24l01test/main.cc
@@ -0,0 +1,26 @@
+#include "arch.h"
+#include "driver/gpio.h"
+#include "driver/stdout.h"
+#include "driver/nrf24l01.h"
+
+void loop(void)
+{
+ gpio.led_toggle(1);
+ kout << "status: " << hex << nrf24l01.getStatus() << endl;
+}
+
+int main(void)
+{
+ arch.setup();
+ gpio.setup();
+ kout.setup();
+
+ kout << "nrf24l01.setup() ...";
+ nrf24l01.setup();
+ kout << " OK" << endl;
+
+ gpio.led_on(0);
+ arch.idle_loop();
+
+ return 0;
+}
diff --git a/src/driver/nrf24l01.cc b/src/driver/nrf24l01.cc
new file mode 100644
index 0000000..144158c
--- /dev/null
+++ b/src/driver/nrf24l01.cc
@@ -0,0 +1,95 @@
+/*
+ * Based on https://github.com/nRF24/RF24
+ */
+
+#include <stdlib.h>
+
+#include "driver/nrf24l01.h"
+#include "driver/nrf24l01/registers.h"
+#include "driver/spi_b.h"
+#include "driver/gpio.h"
+#include "arch.h"
+
+#ifndef NRF24L01_EN_PIN
+#error makeflag nrf24l01_en_pin required
+#endif
+
+#ifndef NRF24L01_CS_PIN
+#error makeflag nrf24l01_cs_pin required
+#endif
+
+void Nrf24l01::setup()
+{
+ spi.setup();
+ gpio.output(NRF24L01_EN_PIN);
+ gpio.output(NRF24L01_CS_PIN);
+ gpio.write(NRF24L01_EN_PIN, 0);
+ csnHigh();
+ arch.delay_ms(5);
+
+ // Reset NRF_CONFIG and enable 16-bit CRC.
+ writeRegister( NRF_CONFIG, 0b00001100 ) ;
+
+ // 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.
+ setRetries(5,15);
+
+ // Reset value is MAX
+ setPALevel( RF24_PA_MAX ) ;
+
+}
+
+void Nrf24l01::setRetries(uint8_t delay, uint8_t count)
+{
+ writeRegister(SETUP_RETR,(delay&0xf)<<ARD | (count&0xf)<<ARC);
+}
+
+void Nrf24l01::setPALevel(uint8_t level)
+{
+ uint8_t setup = readRegister(RF_SETUP) & 0b11111000;
+
+ if(level > 3){ // If invalid level, go to max PA
+ level = (RF24_PA_MAX << 1) + 1; // +1 to support the SI24R1 chip extra bit
+ }else{
+ level = (level << 1) + 1; // Else set level as requested
+ }
+
+ writeRegister( RF_SETUP, setup |= level ) ; // Write it to the chip
+}
+
+uint8_t Nrf24l01::getStatus()
+{
+ txbuf[0] = NOP;
+ beginTransaction();
+ spi.xmit(1, txbuf, 1, rxbuf);
+ endTransaction();
+
+ return rxbuf[0];
+}
+
+uint8_t Nrf24l01::readRegister(uint8_t reg)
+{
+ txbuf[0] = R_REGISTER | ( REGISTER_MASK & reg );
+ txbuf[1] = NOP;
+
+ beginTransaction();
+ spi.xmit(2, txbuf, 2, rxbuf);
+ endTransaction();
+
+ return rxbuf[1];
+}
+
+uint8_t Nrf24l01::writeRegister(uint8_t reg, uint8_t value)
+{
+ txbuf[0] = W_REGISTER | (REGISTER_MASK & reg);
+ txbuf[1] = value;
+
+ beginTransaction();
+ spi.xmit(2, txbuf, 1, rxbuf);
+ endTransaction();
+
+ return rxbuf[0];
+}
+
+Nrf24l01 nrf24l01;