From a426c8d552d4b477758f90d6bb08619fb1ff3edd Mon Sep 17 00:00:00 2001 From: Daniel Friesel Date: Tue, 16 Jul 2019 12:21:26 +0200 Subject: Working Nrf24 ping-pong --- include/driver/nrf24l01.h | 340 ++++++++++++++++++++++++++++++---------------- 1 file changed, 223 insertions(+), 117 deletions(-) (limited to 'include/driver') diff --git a/include/driver/nrf24l01.h b/include/driver/nrf24l01.h index 6b69029..e753604 100644 --- a/include/driver/nrf24l01.h +++ b/include/driver/nrf24l01.h @@ -11,27 +11,27 @@ class Nrf24l01 { private: - Nrf24l01(const Nrf24l01 ©); - 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 */ - - /** + Nrf24l01(const Nrf24l01 ©); + 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 */ + + /** * Write a single byte to a register * * @param reg Which register. Use constants from nRF24L01.h * @param value The new value to write * @return Current value of status register */ - uint8_t writeRegister(uint8_t reg, uint8_t value); + uint8_t writeRegister(uint8_t reg, uint8_t value); - /** + /** * Write a chunk of data to a register * * @param reg Which register. Use constants from nRF24L01.h @@ -39,17 +39,17 @@ private: * @param len How many bytes of data to transfer * @return Current value of status register */ - uint8_t writeRegister(uint8_t reg, const uint8_t *buf, uint8_t len); + uint8_t writeRegister(uint8_t reg, const uint8_t *buf, uint8_t len); - /** + /** * Read single byte from a register * * @param reg Which register. Use constants from nRF24L01.h * @return Current value of register @p reg */ - uint8_t readRegister(uint8_t reg); + uint8_t readRegister(uint8_t reg); - /** + /** * Write the transmit payload * * The size of data written is the fixed payload size, see getPayloadSize() @@ -58,69 +58,80 @@ private: * @param len Number of bytes to be sent * @return Current value of status register */ - 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(); - } + uint8_t writePayload(const void *buf, uint8_t data_len, const uint8_t writeType); + + /** + * Read the receive payload + * + * The size of data read is the fixed payload size, see getPayloadSize() + * + * @param buf Where to put the data + * @param len Maximum number of bytes to read + * @return Current value of status register + */ + uint8_t readPayload(void* buf, uint8_t len); + + 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) { pipe0_reading_address[0] = 0; } + Nrf24l01() : payload_size(32), dynamic_payloads_enabled(false), addr_width(5) { pipe0_reading_address[0] = 0; } - /** + /** * 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(). @@ -137,33 +148,43 @@ public: * radio.powerUp(); * @endcode */ - void powerDown(void); + 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); + void powerUp(void); - /** + /** + * Initialize the radio. Open a reading pipe at addr and set channel. + * + * @param addr Address at which the reading pipe will be opened. + * @param channel that will be used, can be 0-125. Channel bandwidth = 1 MHz starting at 2400 Mhz. + * @return 0: success, -1: invalid channel, -2 error setting channel, -3: other error. + * + */ + //int init(uint8_t addr, uint8_t channel, rf24_datarate_e datarate = RF24_2MBPS); + + /** * 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); + uint8_t flushTx(void); - /** + /** * Empty the receive buffer * * @return Current value of status register */ - uint8_t flushRx(void); + uint8_t flushRx(void); - void setup(); - /** + 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 * @@ -174,40 +195,40 @@ public: * * @param level Desired PA level. */ - void setPALevel(uint8_t level); // 0 (-18B), 1 (-12dB), 2 (-6dB), 3 (0dB) + 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); + 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); + 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); + void setChannel(uint8_t channel); - /** + /** * Get RF communication channel * * @return The currently configured RF Channel */ - uint8_t getChannel(void); + uint8_t getChannel(void); - /** + /** * Set Static Payload Size * * This implementation uses a pre-stablished fixed payload size for all @@ -219,18 +240,18 @@ public: * * @param size The number of bytes in the payload */ - void setPayloadSize(uint8_t size); + void setPayloadSize(uint8_t size); - /** + /** * Get Static Payload Size * * @see setPayloadSize() * * @return The number of bytes in the payload */ - uint8_t getPayloadSize(void); + uint8_t getPayloadSize(void); - /** + /** * Set the transmission data rate * * @warning setting RF24_250KBPS will fail for non-plus units @@ -238,9 +259,9 @@ public: * @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); + 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 @@ -256,17 +277,17 @@ public: * @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 maskIRQ(bool tx_ok, bool tx_fail, bool rx_ready); - /** + /** * 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 toggleFeatures(void); - /** + /** * Enable dynamically-sized payloads * * This way you don't always have to send large packets just to send them @@ -275,9 +296,9 @@ public: * @param enable desired DynamicPayloads status * */ - void setDynamicPayloads(bool enabled); + void setDynamicPayloads(bool enabled); - /** + /** * Enable dynamic ACKs (single write multicast or unicast) for chosen messages * * @param enable desired DynamicAck status @@ -291,9 +312,9 @@ public: * radio.write(&data,32,0); // Sends a payload using auto-retry/autoACK * @endcode */ - void setDynamicAck(bool enabled); + void setDynamicAck(bool enabled); - /** + /** * Enable or disable auto-acknowlede packets * * This is enabled by default, so it's only needed if you want to turn @@ -301,9 +322,9 @@ public: * * @param enable Whether to enable (true) or disable (false) auto-acks */ - void setAutoAck(bool enable); + void setAutoAck(bool enable); - /** + /** * Enable or disable auto-acknowlede packets on a per pipeline basis. * * AA is enabled by default, so it's only needed if you want to turn @@ -312,9 +333,20 @@ public: * @param pipe Which pipeline to modify * @param enable Whether to enable (true) or disable (false) auto-acks */ - void setAutoAck(uint8_t pipe, bool enable); + void setAutoAck(uint8_t pipe, bool enable); + + /** + * Enable custom payloads on the acknowledge packets + * + * Ack payloads are a handy way to return data back to senders without + * manually changing the radio modes on both units. + * + * @note Ack payloads are dynamic payloads. This only works on pipes 0&1 by default. Call + * enableDynamicPayloads() to enable on all pipes. + */ + void enableAckPayload(void); - /** + /** * Be sure to call openWritingPipe() first to set the destination * of where to write to. * @@ -337,9 +369,9 @@ public: * @endcode * @return True if the payload was delivered successfully false if not */ - uint8_t write(const void *buf, uint8_t len, bool await_ack, bool blocking); + uint8_t write(const void *buf, uint8_t len, bool await_ack, bool blocking); - /** + /** * Start listening on the pipes opened for reading. * * 1. Be sure to call openReadingPipe() first. @@ -354,9 +386,9 @@ public: * radio.startListening(); * @endcode */ - void startListening(void); + void startListening(void); - /** + /** * Stop listening for incoming messages, and switch to transmit mode. * * Do this before calling write(). @@ -365,9 +397,9 @@ public: * radio.write(&data,sizeof(data)); * @endcode */ - void stopListening(void); + void stopListening(void); - /** + /** * Check whether there are bytes available to be read * @code * if(radio.available()){ @@ -376,9 +408,27 @@ public: * @endcode * @return True if there is a payload available, false if none is */ - bool available(void); + bool available(void); + + /** + * Test whether there are bytes available to be read in the + * FIFO buffers. + * + * @param[out] pipe_num Which pipe has the payload available + * + * @code + * uint8_t pipeNum; + * if(radio.available(&pipeNum)){ + * radio.read(&data,sizeof(data)); + * Serial.print("Got data on pipe"); + * Serial.println(pipeNum); + * } + * @endcode + * @return True if there is a payload available, false if none is + */ + bool available(uint8_t *pipe_num); - /** + /** * Read the available payload * * The size of data read is the fixed payload size, see getPayloadSize() @@ -400,9 +450,9 @@ public: * @endcode * @return No return value. Use available(). */ - void read(void *buf, uint8_t len); + void read(void *buf, uint8_t len); - /** + /** * Open a pipe for reading * * Up to 6 pipes can be open for reading at once. Open all the required @@ -429,16 +479,72 @@ public: * @param number Which pipe# to open, 0-5. * @param address The 24, 32 or 40 bit address of the pipe to open. */ - void openReadingPipe(uint8_t number, const uint8_t *address); + void openReadingPipe(uint8_t number, const uint8_t *address); - /** + /** * Close a pipe after it has been previously opened. * Can be safely called without having previously opened a pipe. * @param pipe Which pipe # to close, 0-5. */ - void closeReadingPipe(uint8_t pipe); + void closeReadingPipe(uint8_t pipe); + + /** + * New: Open a pipe for writing via byte array. Old addressing format retained + * for compatibility. + * + * Only one writing pipe can be open at once, but you can change the address + * you'll write to. Call stopListening() first. + * + * Addresses are assigned via a byte array, default is 5 byte address length +s * + * @code + * uint8_t addresses[][6] = {"1Node","2Node"}; + * radio.openWritingPipe(addresses[0]); + * @endcode + * @code + * uint8_t address[] = { 0xCC,0xCE,0xCC,0xCE,0xCC }; + * radio.openWritingPipe(address); + * address[0] = 0x33; + * radio.openReadingPipe(1,address); + * @endcode + * @see setAddressWidth + * + * @param address The address of the pipe to open. Coordinate these pipe + * addresses amongst nodes on the network. + */ + + void openWritingPipe(const uint8_t *address); + + /** + * Test whether there was a carrier on the line for the + * previous listening period. + * + * Useful to check for interference on the current channel. + * + * @return true if was carrier, false if not + */ + bool testCarrier(void); + + /** + * Test whether a signal (carrier or otherwise) greater than + * or equal to -64dBm is present on the channel. Valid only + * on nRF24L01P (+) hardware. On nRF24L01, use testCarrier(). + * + * Useful to check for interference on the current channel and + * channel hopping strategies. + * + * @code + * bool goodSignal = radio.testRPD(); + * if(radio.available()){ + * Serial.println(goodSignal ? "Strong signal > 64dBm" : "Weak signal < 64dBm" ); + * radio.read(0,0); + * } + * @endcode + * @return true if signal => -64dBm, false if not + */ + bool testRPD(void); - uint8_t getStatus(); + uint8_t getStatus(); }; extern Nrf24l01 nrf24l01; -- cgit v1.2.3