summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Friesel <daniel.friesel@uos.de>2019-06-24 12:48:14 +0200
committerDaniel Friesel <daniel.friesel@uos.de>2019-06-24 12:48:14 +0200
commitdefe3e47dd837f9f2ae8447b7148893af8e8f1d0 (patch)
treecbed9022046695ffa118c21c581159d48943a1c0
parent0dbe2001333b8f6a01e3082ce16e7326db801991 (diff)
import nRF24 TX code
-rw-r--r--include/driver/nrf24l01.h251
-rw-r--r--src/app/nrf24l01test/main.cc2
-rw-r--r--src/arch/msp430fr5994lp/Makefile.inc2
-rw-r--r--src/driver/nrf24l01.cc198
4 files changed, 402 insertions, 51 deletions
diff --git a/include/driver/nrf24l01.h b/include/driver/nrf24l01.h
index 911ef58..c10332d 100644
--- a/include/driver/nrf24l01.h
+++ b/include/driver/nrf24l01.h
@@ -5,63 +5,236 @@
#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() {}
-
- /**
+#define rf24_max(a, b) ((a) > (b) ? (a) : (b))
+#define rf24_min(a, b) ((a) < (b) ? (a) : (b))
+
+class Nrf24l01
+{
+private:
+ Nrf24l01(const Nrf24l01 &copy);
+ unsigned char txbuf[2];
+ unsigned char rxbuf[2];
+
+ bool p_variant; /* False for RF24L01 and true for RF24L01P */
+ uint8_t payload_size; /**< Fixed size of payloads */
+ bool dynamic_payloads_enabled; /**< Whether dynamic payloads are enabled. */
+ uint8_t pipe0_reading_address[5]; /**< Last address set on pipe 0 for reading. */
+ uint8_t addr_width; /**< The address width to use - 3,4 or 5 bytes. */
+ uint32_t txRxDelay; /**< Var for adjusting delays depending on datarate */
+
+ uint8_t writeRegister(uint8_t reg, uint8_t value);
+ uint8_t readRegister(uint8_t reg);
+ uint8_t writePayload(const void *buf, uint8_t data_len, const uint8_t writeType);
+
+ 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() : payload_size(32), dynamic_payloads_enabled(false), addr_width(5) {}
+
+ /**
* 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 };
+ 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 };
+ 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 };
+ enum rf24_crclength_e
+ {
+ RF24_CRC_DISABLED = 0,
+ RF24_CRC_8,
+ RF24_CRC_16
+ };
+
+ /**
+ * Enter low-power mode
+ *
+ * To return to normal power mode, call powerUp().
+ *
+ * @note After calling startListening(), a basic radio will consume about 13.5mA
+ * at max PA level.
+ * During active transmission, the radio will consume about 11.5mA, but this will
+ * be reduced to 26uA (.026mA) between sending.
+ * In full powerDown mode, the radio will consume approximately 900nA (.0009mA)
+ *
+ * @code
+ * radio.powerDown();
+ * avr_enter_sleep_mode(); // Custom function to sleep the device
+ * radio.powerUp();
+ * @endcode
+ */
+ void powerDown(void);
+
+ /**
+ * Leave low-power mode - required for normal radio operation after calling powerDown()
+ *
+ * To return to low power mode, call powerDown().
+ * @note This will take up to 5ms for maximum compatibility
+ */
+ void powerUp(void);
+
+ /**
+ * Empty the transmit buffer. This is generally not required in standard operation.
+ * May be required in specific cases after stopListening() , if operating at 250KBPS data rate.
+ *
+ * @return Current value of status register
+ */
+ uint8_t flushTx(void);
+
+ /**
+ * Empty the receive buffer
+ *
+ * @return Current value of status register
+ */
+ uint8_t flushRx(void);
+
+ void setup();
+ /**
+ * Set Power Amplifier (PA) level to one of four levels:
+ * RF24_PA_MIN, RF24_PA_LOW, RF24_PA_HIGH and RF24_PA_MAX
+ *
+ * The power levels correspond to the following output levels respectively:
+ * NRF24L01: -18dBm, -12dBm,-6dBM, and 0dBm
+ *
+ * SI24R1: -6dBm, 0dBm, 3dBM, and 7dBm.
+ *
+ * @param level Desired PA level.
+ */
+ void setPALevel(uint8_t level); // 0 (-18B), 1 (-12dB), 2 (-6dB), 3 (0dB)
+
+ /**
+ * Set the address width from 3 to 5 bytes (24, 32 or 40 bit)
+ *
+ * @param a_width The address width to use: 3,4 or 5
+ */
+
+ void setAddressWidth(uint8_t a_width);
+
+ /**
+ * Set the number and delay of retries upon failed submit
+ *
+ * @param delay How long to wait between each retry, in multiples of 250us,
+ * max is 15. 0 means 250us, 15 means 4000us.
+ * @param count How many retries before giving up, max 15
+ */
+ void setRetries(uint8_t delay, uint8_t count);
+
+ /**
+ * Set RF communication channel
+ *
+ * @param channel Which RF channel to communicate on, 0-125
+ */
+ void setChannel(uint8_t channel);
+
+ /**
+ * Get RF communication channel
+ *
+ * @return The currently configured RF Channel
+ */
+ uint8_t getChannel(void);
+
+ /**
+ * Set Static Payload Size
+ *
+ * This implementation uses a pre-stablished fixed payload size for all
+ * transmissions. If this method is never called, the driver will always
+ * transmit the maximum payload size (32 bytes), no matter how much
+ * was sent to write().
+ *
+ * @todo Implement variable-sized payloads feature
+ *
+ * @param size The number of bytes in the payload
+ */
+ void setPayloadSize(uint8_t size);
+
+ /**
+ * Get Static Payload Size
+ *
+ * @see setPayloadSize()
+ *
+ * @return The number of bytes in the payload
+ */
+ uint8_t getPayloadSize(void);
+
+ /**
+ * Set the transmission data rate
+ *
+ * @warning setting RF24_250KBPS will fail for non-plus units
+ *
+ * @param speed RF24_250KBPS for 250kbs, RF24_1MBPS for 1Mbps, or RF24_2MBPS for 2Mbps
+ * @return true if the change was successful
+ */
+ bool setDataRate(rf24_datarate_e speed);
+ /**
+ * The radio will generate interrupt signals when a transmission is complete,
+ * a transmission fails, or a payload is received. This allows users to mask
+ * those interrupts to prevent them from generating a signal on the interrupt
+ * pin. Interrupts are enabled on the radio chip by default.
+ *
+ * @code
+ * Mask all interrupts except the receive interrupt:
+ *
+ * radio.maskIRQ(1,1,0);
+ * @endcode
+ *
+ * @param tx_ok Mask transmission complete interrupts
+ * @param tx_fail Mask transmit failure interrupts
+ * @param rx_ready Mask payload received interrupts
+ */
+ void maskIRQ(bool tx_ok, bool tx_fail, bool rx_ready);
- void setup();
- void powerOn();
- void powerOff();
+ /**
+ * Turn on or off the special features of the chip
+ *
+ * The chip has certain 'features' which are only available when the 'features'
+ * are enabled. See the datasheet for details.
+ */
+ void toggleFeatures(void);
- void setRetries(uint8_t delay, uint8_t count);
- void setPALevel ( uint8_t level ); // 0 (-18B), 1 (-12dB), 2 (-6dB), 3 (0dB)
+ uint8_t write(const void *buf, uint8_t len, bool blocking);
- uint8_t getStatus();
+ uint8_t getStatus();
};
extern Nrf24l01 nrf24l01;
diff --git a/src/app/nrf24l01test/main.cc b/src/app/nrf24l01test/main.cc
index 2f65a7c..c12cbf5 100644
--- a/src/app/nrf24l01test/main.cc
+++ b/src/app/nrf24l01test/main.cc
@@ -7,6 +7,8 @@ void loop(void)
{
gpio.led_toggle(1);
kout << "status: " << hex << nrf24l01.getStatus() << endl;
+ kout << "write: ";
+ kout << nrf24l01.write("foo", 3, true) << endl;
}
int main(void)
diff --git a/src/arch/msp430fr5994lp/Makefile.inc b/src/arch/msp430fr5994lp/Makefile.inc
index 6498597..535e01b 100644
--- a/src/arch/msp430fr5994lp/Makefile.inc
+++ b/src/arch/msp430fr5994lp/Makefile.inc
@@ -3,7 +3,7 @@
CPU = 430x
MCU = msp430fr5994
-cpu_freq ?= 16000000
+cpu_freq ?= 8000000
MSP430_FLASHER_DIR ?= /home/derf/var/projects/msp430/MSP430Flasher_1.3.15
diff --git a/src/driver/nrf24l01.cc b/src/driver/nrf24l01.cc
index 144158c..ff19240 100644
--- a/src/driver/nrf24l01.cc
+++ b/src/driver/nrf24l01.cc
@@ -21,6 +21,7 @@
void Nrf24l01::setup()
{
spi.setup();
+ gpio.input(NRF24L01_IRQ_PIN, true);
gpio.output(NRF24L01_EN_PIN);
gpio.output(NRF24L01_CS_PIN);
gpio.write(NRF24L01_EN_PIN, 0);
@@ -28,34 +29,167 @@ void Nrf24l01::setup()
arch.delay_ms(5);
// Reset NRF_CONFIG and enable 16-bit CRC.
- writeRegister( NRF_CONFIG, 0b00001100 ) ;
+ 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);
+ setRetries(5, 10);
// Reset value is MAX
- setPALevel( RF24_PA_MAX ) ;
+ setPALevel(RF24_PA_MAX);
+ setDataRate(RF24_1MBPS);
+
+ toggleFeatures();
+ writeRegister(FEATURE, 0);
+ writeRegister(DYNPD, 0);
+ dynamic_payloads_enabled = false;
+
+ // Reset current status
+ // Notice reset and flush is the last thing we do
+ writeRegister(NRF_STATUS, (1 << RX_DR) | (1 << TX_DS) | (1 << MAX_RT));
+
+ // Set up default configuration. Callers can always change it later.
+ // This channel should be universally safe and not bleed over into adjacent
+ // spectrum.
+ setChannel(76);
+
+ // Flush buffers
+ flushRx();
+ flushTx();
+
+ maskIRQ(true, false, false);
+
+ powerUp(); //Power up by default when begin() is called
+
+ // Enable PTX, do not write CE high so radio will remain in standby I mode ( 130us max to transition to RX or TX instead of 1500us from powerUp )
+ // PTX should use only 22uA of power
+ writeRegister(NRF_CONFIG, (readRegister(NRF_CONFIG)) & ~(1 << PRIM_RX));
+}
+
+//Power up now. Radio will not power down unless instructed by MCU for config changes etc.
+void Nrf24l01::powerUp(void)
+{
+ uint8_t cfg = readRegister(NRF_CONFIG);
+
+ // if not powered up then power up and wait for the radio to initialize
+ if (!(cfg & (1 << PWR_UP)))
+ {
+ writeRegister(NRF_CONFIG, cfg | (1 << PWR_UP));
+
+ // For nRF24L01+ to go from power down mode to TX or RX mode it must first pass through stand-by mode.
+ // There must be a delay of Tpd2stby (see Table 16.) after the nRF24L01+ leaves power down mode before
+ // the CEis set high. - Tpd2stby can be up to 5ms per the 1.0 datasheet
+ arch.delay_us(5);
+ }
}
void Nrf24l01::setRetries(uint8_t delay, uint8_t count)
{
- writeRegister(SETUP_RETR,(delay&0xf)<<ARD | (count&0xf)<<ARC);
+ 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
+ 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
+}
+
+bool Nrf24l01::setDataRate(Nrf24l01::rf24_datarate_e speed)
+{
+ bool result = false;
+ uint8_t setup = readRegister(RF_SETUP);
+
+ // HIGH and LOW '00' is 1Mbs - our default
+ setup &= ~((1 << RF_DR_LOW) | (1 << RF_DR_HIGH));
+
+ txRxDelay = 85;
+ if (speed == RF24_250KBPS)
+ {
+ // Must set the RF_DR_LOW to 1; RF_DR_HIGH (used to be RF_DR) is already 0
+ // Making it '10'.
+ setup |= (1 << RF_DR_LOW);
+ txRxDelay = 155;
}
+ else
+ {
+ // Set 2Mbs, RF_DR (RF_DR_HIGH) is set 1
+ // Making it '01'
+ if (speed == RF24_2MBPS)
+ {
+ setup |= (1 << RF_DR_HIGH);
+ txRxDelay = 65;
+ }
+ }
+ writeRegister(RF_SETUP, setup);
+
+ // Verify our result
+ if (readRegister(RF_SETUP) == setup)
+ {
+ result = true;
+ }
+ return result;
+}
+
+void Nrf24l01::toggleFeatures(void)
+{
+ beginTransaction();
+ txbuf[0] = ACTIVATE;
+ txbuf[1] = 0x73;
+ spi.xmit(2, txbuf, 0, rxbuf);
+ endTransaction();
+}
- writeRegister( RF_SETUP, setup |= level ) ; // Write it to the chip
+void Nrf24l01::setChannel(uint8_t channel)
+{
+ writeRegister(RF_CH, rf24_min(channel, 125));
+}
+
+uint8_t Nrf24l01::write(const void *buf, uint8_t len, bool blocking)
+{
+ writePayload(buf, len, W_TX_PAYLOAD);
+
+ gpio.write(NRF24L01_EN_PIN, 1);
+ arch.delay_us(10);
+ gpio.write(NRF24L01_EN_PIN, 0);
+
+ if (!blocking)
+ {
+ return 0;
+ }
+
+ while (!(getStatus() & ((1 << TX_DS) | (1 << MAX_RT))))
+ ;
+ uint8_t status = writeRegister(NRF_STATUS, ((1 << TX_DS) | (1 << MAX_RT)));
+
+ if (status & (1 << MAX_RT))
+ {
+ // flush_tx(); //Only going to be 1 packet int the FIFO at a time using this method, so just flush
+ return 0;
+ }
+ return 1;
+}
+
+void Nrf24l01::maskIRQ(bool tx, bool fail, bool rx)
+{
+
+ uint8_t config = readRegister(NRF_CONFIG);
+ /* clear the interrupt flags */
+ config &= ~(1 << MASK_MAX_RT | 1 << MASK_TX_DS | 1 << MASK_RX_DR);
+ /* set the specified interrupt flags */
+ config |= fail << MASK_MAX_RT | tx << MASK_TX_DS | rx << MASK_RX_DR;
+ writeRegister(NRF_CONFIG, config);
}
uint8_t Nrf24l01::getStatus()
@@ -70,7 +204,7 @@ uint8_t Nrf24l01::getStatus()
uint8_t Nrf24l01::readRegister(uint8_t reg)
{
- txbuf[0] = R_REGISTER | ( REGISTER_MASK & reg );
+ txbuf[0] = R_REGISTER | (REGISTER_MASK & reg);
txbuf[1] = NOP;
beginTransaction();
@@ -92,4 +226,46 @@ uint8_t Nrf24l01::writeRegister(uint8_t reg, uint8_t value)
return rxbuf[0];
}
-Nrf24l01 nrf24l01;
+uint8_t Nrf24l01::writePayload(const void *buf, uint8_t data_len, const uint8_t writeType)
+{
+ data_len = rf24_min(data_len, payload_size);
+ uint8_t blank_len = dynamic_payloads_enabled ? 0 : payload_size - data_len;
+
+ //printf("[Writing %u bytes %u blanks]",data_len,blank_len);
+ //IF_SERIAL_DEBUG( printf("[Writing %u bytes %u blanks]\n",data_len,blank_len); );
+
+ beginTransaction();
+ txbuf[0] = writeType;
+ spi.xmit(1, txbuf, 1, rxbuf);
+ spi.xmit(data_len, (unsigned char *)buf, 0, NULL);
+ txbuf[0] = 0;
+ while (blank_len--)
+ {
+ spi.xmit(1, txbuf, 0, NULL);
+ }
+ endTransaction();
+
+ return rxbuf[0];
+}
+
+uint8_t Nrf24l01::flushRx(void)
+{
+ txbuf[0] = FLUSH_RX;
+ beginTransaction();
+ spi.xmit(1, txbuf, 1, rxbuf);
+ endTransaction();
+ return rxbuf[0];
+}
+
+/****************************************************************************/
+
+uint8_t Nrf24l01::flushTx(void)
+{
+ txbuf[0] = FLUSH_TX;
+ beginTransaction();
+ spi.xmit(1, txbuf, 1, rxbuf);
+ endTransaction();
+ return rxbuf[0];
+}
+
+Nrf24l01 nrf24l01; \ No newline at end of file