summaryrefslogtreecommitdiff
path: root/.pio/libdeps/esp32-s3-n16r8/RF24/examples/InterruptConfigure
diff options
context:
space:
mode:
Diffstat (limited to '.pio/libdeps/esp32-s3-n16r8/RF24/examples/InterruptConfigure')
-rw-r--r--.pio/libdeps/esp32-s3-n16r8/RF24/examples/InterruptConfigure/InterruptConfigure.ino353
1 files changed, 353 insertions, 0 deletions
diff --git a/.pio/libdeps/esp32-s3-n16r8/RF24/examples/InterruptConfigure/InterruptConfigure.ino b/.pio/libdeps/esp32-s3-n16r8/RF24/examples/InterruptConfigure/InterruptConfigure.ino
new file mode 100644
index 0000000..9d59759
--- /dev/null
+++ b/.pio/libdeps/esp32-s3-n16r8/RF24/examples/InterruptConfigure/InterruptConfigure.ino
@@ -0,0 +1,353 @@
+/*
+ * See documentation at https://nRF24.github.io/RF24
+ * See License information at root directory of this library
+ * Author: Brendan Doherty (2bndy5)
+ */
+
+/**
+ * This example uses Acknowledgement (ACK) payloads attached to ACK packets to
+ * demonstrate how the nRF24L01's IRQ (Interrupt Request) pin can be
+ * configured to detect when data is received, or when data has transmitted
+ * successfully, or when data has failed to transmit.
+ *
+ * This example was written to be used on 2 devices acting as "nodes".
+ * Use the Serial Monitor to change each node's behavior.
+ */
+#include <SPI.h>
+#include "printf.h"
+#include "RF24.h"
+
+// We will be using the nRF24L01's IRQ pin for this example
+#define IRQ_PIN 2 // this needs to be a digital input capable pin
+volatile bool got_interrupt = false; // used to signal processing of interrupt
+volatile bool wait_for_event = false; // used to wait for an IRQ event to trigger
+
+#define CE_PIN 7
+#define CSN_PIN 8
+// instantiate an object for the nRF24L01 transceiver
+RF24 radio(CE_PIN, CSN_PIN);
+
+// Let these addresses be used for the pair
+uint8_t address[][6] = { "1Node", "2Node" };
+// It is very helpful to think of an address as a path instead of as
+// an identifying device destination
+
+// to use different addresses on a pair of radios, we need a variable to
+// uniquely identify which address this radio will use to transmit
+bool radioNumber = 1; // 0 uses address[0] to transmit, 1 uses address[1] to transmit
+
+// Used to control whether this node is sending or receiving
+bool role = false; // true = TX node, false = RX node
+
+// For this example, we'll be using a payload containing
+// a string that changes on every transmission. (successful or not)
+// Make a couple arrays of payloads & an iterator to traverse them
+const uint8_t tx_pl_size = 5;
+const uint8_t ack_pl_size = 4;
+uint8_t pl_iterator = 0;
+// The " + 1" compensates for the c-string's NULL terminating 0
+char tx_payloads[][tx_pl_size + 1] = { "Ping ", "Pong ", "Radio", "1FAIL" };
+char ack_payloads[][ack_pl_size + 1] = { "Yak ", "Back", " ACK" };
+
+void interruptHandler(); // prototype to handle IRQ events
+void printRxFifo(); // prototype to print RX FIFO with 1 buffer
+
+
+void setup() {
+ Serial.begin(115200);
+ while (!Serial) {
+ // some boards need to wait to ensure access to serial over USB
+ }
+
+ // initialize the transceiver on the SPI bus
+ if (!radio.begin()) {
+ Serial.println(F("radio hardware is not responding!!"));
+ while (1) {} // hold in infinite loop
+ }
+
+ // print example's introductory prompt
+ Serial.println(F("RF24/examples/InterruptConfigure"));
+
+ // To set the radioNumber via the Serial monitor on startup
+ Serial.println(F("Which radio is this? Enter '0' or '1'. Defaults to '0'"));
+ while (!Serial.available()) {
+ // wait for user input
+ }
+ char input = Serial.parseInt();
+ radioNumber = input == 1;
+ Serial.print(F("radioNumber = "));
+ Serial.println((int)radioNumber);
+
+ // role variable is hardcoded to RX behavior, inform the user of this
+ Serial.println(F("*** PRESS 'T' to begin transmitting to the other node"));
+
+ // setup the IRQ_PIN
+ pinMode(IRQ_PIN, INPUT);
+ attachInterrupt(digitalPinToInterrupt(IRQ_PIN), interruptHandler, FALLING);
+ // IMPORTANT: do not call radio.available() before calling
+ // radio.whatHappened() when the interruptHandler() is triggered by the
+ // IRQ pin FALLING event. According to the datasheet, the pipe information
+ // is unreliable during the IRQ pin FALLING transition.
+
+ // Set the PA Level low to try preventing power supply related problems
+ // because these examples are likely run with nodes in close proximity to
+ // each other.
+ radio.setPALevel(RF24_PA_LOW); // RF24_PA_MAX is default.
+
+ // For this example we use acknowledgment (ACK) payloads to trigger the
+ // IRQ pin when data is received on the TX node.
+ // to use ACK payloads, we need to enable dynamic payload lengths
+ radio.enableDynamicPayloads(); // ACK payloads are dynamically sized
+
+ // Acknowledgement packets have no payloads by default. We need to enable
+ // this feature for all nodes (TX & RX) to use ACK payloads.
+ radio.enableAckPayload();
+
+ // set the TX address of the RX node for use on the TX pipe (pipe 0)
+ radio.stopListening(address[radioNumber]); // put radio in TX mode
+
+ // set the RX address of the TX node into a RX pipe
+ radio.openReadingPipe(1, address[!radioNumber]); // using pipe 1
+
+ // additional setup specific to the node's RX role
+ if (!role) {
+ // setup for RX mode
+
+ // let IRQ pin only trigger on "data_ready" event in RX mode
+ radio.setStatusFlags(RF24_RX_DR);
+
+ // Fill the TX FIFO with 3 ACK payloads for the first 3 received
+ // transmissions on pipe 1
+ radio.writeAckPayload(1, &ack_payloads[0], ack_pl_size);
+ radio.writeAckPayload(1, &ack_payloads[1], ack_pl_size);
+ radio.writeAckPayload(1, &ack_payloads[2], ack_pl_size);
+
+ radio.startListening(); // put radio in RX mode
+ }
+
+ // For debugging info
+ // printf_begin(); // needed only once for printing details
+ // radio.printDetails(); // (smaller) function that prints raw register values
+ // radio.printPrettyDetails(); // (larger) function that prints human readable data
+}
+
+void loop() {
+ if (got_interrupt) {
+ assessInterruptEvent();
+ }
+
+ if (role && !wait_for_event) {
+
+ // This device is a TX node. This if block is only triggered when
+ // NOT waiting for an IRQ event to happen
+
+ if (pl_iterator == 0) {
+ // Test the "data ready" event with the IRQ pin
+
+ Serial.println(F("\nConfiguring IRQ pin to ignore the 'data sent' event"));
+ radio.setStatusFlags(RF24_RX_DR | RF24_TX_DF);
+ Serial.println(F(" Pinging RX node for 'data ready' event..."));
+
+ } else if (pl_iterator == 1) {
+ // Test the "data sent" event with the IRQ pin
+
+ Serial.println(F("\nConfiguring IRQ pin to ignore the 'data ready' event"));
+ radio.setStatusFlags(RF24_TX_DS | RF24_TX_DF);
+ Serial.println(F(" Pinging RX node for 'data sent' event..."));
+
+ } else if (pl_iterator == 2) {
+ // Use this iteration to fill the RX node's FIFO which sets us up for the next test.
+
+ // write() uses virtual interrupt flags that work despite the masking of the IRQ pin
+ // disable IRQ pin for this step
+ radio.setStatusFlags();
+
+ Serial.println(F("\nSending 1 payload to fill RX node's FIFO. IRQ pin is neglected."));
+ // write() will call flush_tx() on 'data fail' events
+ if (radio.write(&tx_payloads[pl_iterator], tx_pl_size)) {
+ if (radio.rxFifoFull()) {
+ Serial.println(F("RX node's FIFO is full; it is not listening any more"));
+ } else {
+ Serial.println("Transmission successful, but the RX node might still be listening.");
+ }
+ } else {
+ Serial.println(F("Transmission failed or timed out. Continuing anyway."));
+ radio.flush_tx(); // discard payload(s) that failed to transmit
+ }
+
+ } else if (pl_iterator == 3) {
+ // test the "data fail" event with the IRQ pin
+
+ Serial.println(F("\nConfiguring IRQ pin to reflect all events"));
+ radio.setStatusFlags(RF24_IRQ_ALL);
+ Serial.println(F(" Pinging inactive RX node for 'data fail' event..."));
+ }
+
+ if (pl_iterator < 4 && pl_iterator != 2) {
+
+ // IRQ pin is LOW when activated. Otherwise it is always HIGH
+ // Wait until IRQ pin is activated.
+ wait_for_event = true;
+
+ // use the non-blocking call to write a payload and begin transmission
+ // the "false" argument means we are expecting an ACK packet response
+ radio.startFastWrite(tx_payloads[pl_iterator++], tx_pl_size, false);
+
+ // In this example, the "data fail" event is always configured to
+ // trigger the IRQ pin active. Because the auto-ACK feature is on by
+ // default, we don't need a timeout check to prevent an infinite loop.
+
+ } else if (pl_iterator == 4) {
+ // all IRQ tests are done; flush_tx() and print the ACK payloads for fun
+
+ // CE pin is still HIGH which consumes more power. Example is now idling so...
+ radio.stopListening(); // ensure CE pin is LOW
+ // stopListening() also calls flush_tx() when ACK payloads are enabled
+
+ printRxFifo();
+ pl_iterator++;
+
+
+ // inform user what to do next
+ Serial.println(F("\n*** PRESS 'T' to restart the transmissions"));
+ Serial.println(F("*** PRESS 'R' to change to Receive role\n"));
+
+
+ } else if (pl_iterator == 2) {
+ pl_iterator++; // proceed from step 3 to last step (stop at step 4 for readability)
+ }
+
+ } else if (!role && radio.rxFifoFull()) {
+ // This device is a RX node:
+ // wait until RX FIFO is full then stop listening
+
+ delay(100); // let ACK payload finish transmitting
+ radio.stopListening(); // also discards unused ACK payloads
+ printRxFifo(); // flush the RX FIFO
+
+ // Fill the TX FIFO with 3 ACK payloads for the first 3 received
+ // transmissions on pipe 1.
+ radio.writeAckPayload(1, &ack_payloads[0], ack_pl_size);
+ radio.writeAckPayload(1, &ack_payloads[1], ack_pl_size);
+ radio.writeAckPayload(1, &ack_payloads[2], ack_pl_size);
+
+ delay(100); // let TX node finish its role
+ radio.startListening(); // We're ready to start over. Begin listening.
+
+ } // role
+
+ if (Serial.available()) {
+ // change the role via the serial monitor
+
+ char c = toupper(Serial.read());
+ if (c == 'T') {
+ // Become the TX node
+ if (!role)
+ Serial.println(F("*** CHANGING TO TRANSMIT ROLE -- PRESS 'R' TO SWITCH BACK"));
+ else
+ Serial.println(F("*** RESTARTING IRQ PIN TEST ***"));
+
+ role = true;
+ wait_for_event = false;
+ pl_iterator = 0; // reset the iterator
+ radio.flush_tx(); // discard any payloads in the TX FIFO
+
+ // startListening() clears the IRQ masks also. This is required for
+ // continued TX operations when a transmission fails.
+ radio.stopListening(); // this also discards any unused ACK payloads
+
+ } else if (c == 'R' && role) {
+ // Become the RX node
+ Serial.println(F("*** CHANGING TO RECEIVE ROLE -- PRESS 'T' TO SWITCH BACK"));
+
+ role = false;
+
+ // let IRQ pin only trigger on "data_ready" event in RX mode
+ radio.setStatusFlags(RF24_RX_DR);
+
+ // Fill the TX FIFO with 3 ACK payloads for the first 3 received
+ // transmissions on pipe 1
+ radio.flush_tx(); // make sure there is room for 3 new ACK payloads
+ radio.flush_rx(); // make sure there is room for 3 incoming payloads
+ radio.writeAckPayload(1, &ack_payloads[0], ack_pl_size);
+ radio.writeAckPayload(1, &ack_payloads[1], ack_pl_size);
+ radio.writeAckPayload(1, &ack_payloads[2], ack_pl_size);
+ radio.startListening();
+ }
+ } // Serial.available()
+} // loop
+
+
+/**
+ * when the IRQ pin goes active LOW.
+ * Here we just tell the main loop() to call `assessInterruptEve4nt()`.
+ */
+void interruptHandler() {
+ got_interrupt = true; // forward event handling back to main loop()
+}
+
+/**
+ * Called when an event has been triggered.
+ * Here, we want to verify the expected IRQ flag has been asserted.
+ */
+void assessInterruptEvent() {
+ // print IRQ status and all masking flags' states
+
+ Serial.println(F("\tIRQ pin is actively LOW")); // show that this function was called
+ delayMicroseconds(250);
+ uint8_t flags = radio.clearStatusFlags();
+ // Resetting the tx_df flag is required for
+ // continued TX operations when a transmission fails.
+ // clearing the status flags resets the IRQ pin to its inactive state (HIGH)
+
+ Serial.print(F("\tdata_sent: "));
+ Serial.print((flags & RF24_TX_DS) > 0); // print "data sent" flag state
+ Serial.print(F(", data_fail: "));
+ Serial.print((flags & RF24_TX_DF) > 0); // print "data fail" flag state
+ Serial.print(F(", data_ready: "));
+ Serial.println((flags & RF24_RX_DR) > 0); // print "data ready" flag state
+
+ if (flags & RF24_TX_DF) // if TX payload failed
+ radio.flush_tx(); // clear all payloads from the TX FIFO
+
+ // print if test passed or failed. Unintentional fails mean the RX node was not listening.
+ // pl_iterator has already been incremented by now
+ if (pl_iterator <= 1) {
+ Serial.print(F(" 'Data Ready' event test "));
+ Serial.println(flags & RF24_RX_DR ? F("passed") : F("failed"));
+ } else if (pl_iterator == 2) {
+ Serial.print(F(" 'Data Sent' event test "));
+ Serial.println(flags & RF24_TX_DS ? F("passed") : F("failed"));
+ } else if (pl_iterator == 4) {
+ Serial.print(F(" 'Data Fail' event test "));
+ Serial.println(flags & RF24_TX_DF ? F("passed") : F("failed"));
+ }
+ got_interrupt = false; // reset this flag to prevent calling this function from loop()
+ wait_for_event = false; // ready to continue with loop() operations
+}
+
+/**
+ * Print the entire RX FIFO with one buffer. This will also flush the RX FIFO.
+ * Remember that the payload sizes are declared as tx_pl_size and ack_pl_size.
+ */
+void printRxFifo() {
+ if (radio.available()) { // if there is data in the RX FIFO
+ // to flush the data from the RX FIFO, we'll fetch it all using 1 buffer
+
+ uint8_t pl_size = !role ? tx_pl_size : ack_pl_size;
+ char rx_fifo[pl_size * 3 + 1]; // RX FIFO is full & we know ACK payloads' size
+ if (radio.rxFifoFull()) {
+ rx_fifo[pl_size * 3] = 0; // add a NULL terminating char to use as a c-string
+ radio.read(&rx_fifo, pl_size * 3); // this clears the RX FIFO (for this example)
+ } else {
+ uint8_t i = 0;
+ while (radio.available()) {
+ radio.read(&rx_fifo + (i * pl_size), pl_size);
+ i++;
+ }
+ rx_fifo[i * pl_size] = 0; // add a NULL terminating char to use as a c-string
+ }
+ Serial.print(F("Complete RX FIFO: "));
+ Serial.println(rx_fifo); // print the entire RX FIFO with 1 buffer
+ }
+}