diff options
-rw-r--r-- | Makefile | 11 | ||||
-rw-r--r-- | include/driver/nrf24l01.h | 69 | ||||
-rw-r--r-- | include/driver/nrf24l01/registers.h | 127 | ||||
-rw-r--r-- | src/app/nrf24l01test/Makefile.inc | 2 | ||||
-rw-r--r-- | src/app/nrf24l01test/main.cc | 26 | ||||
-rw-r--r-- | src/driver/nrf24l01.cc | 95 |
6 files changed, 330 insertions, 0 deletions
@@ -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 ©); + 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; |