nRF24 / RF24

OSI Layer 2 driver for nRF24L01 on Arduino & Raspberry Pi/Linux Devices
https://nrf24.github.io/RF24
GNU General Public License v2.0
2.23k stars 1.02k forks source link

[Question] Should whatHappened() clear the IRQ status flags? #673

Closed 2bndy5 closed 3 years ago

2bndy5 commented 4 years ago

The source code for whatHappened() contains:

void RF24::whatHappened(bool& tx_ok, bool& tx_fail, bool& rx_ready)
{
    // Read the status & reset the status in one easy call
    // Or is that such a good idea?
    uint8_t status = write_register(NRF_STATUS, _BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT));

    // Report to the user what happened
    tx_ok = status & _BV(TX_DS);
    tx_fail = status & _BV(MAX_RT);
    rx_ready = status & _BV(RX_DR);
}

While fetching & resetting the status flags with one SPI transaction is extremely clever, the comment saying "is this a good idea?" is a good question. Personally I'm on the fence about this. I'd prefer that there be a separate function to clear the IRQ status flags when the application is done dealing with the event(s) that were triggered.

2bndy5 commented 3 years ago

EDIT: disregard this post. I've solved the problems with the new interruptConfigure examples. I'm leaving this post for posterity...

So I've been testing the new InterruptConfigure example using an Arduino nano and the attachInterrupt(). The problematic output looks like:

Which radio is this? Enter '0' or '1'. Defaults to '0'
radioNumber = 1
*** PRESS 'T' to begin transmitting to the other node
*** CHANGING TO TRANSMIT ROLE -- PRESS 'R' TO SWITCH BACK

Configuring IRQ pin to reflect all events
   Pinging RX node for 'data ready' event...
    IRQ pin is actively LOW
available() = 1
    data_sent: 1, data_fail: 0, data_ready: 0
   'Data Ready' event test failed

Configuring IRQ pin to ignore the 'data ready' event
   Pinging RX node for 'data sent' event...
    IRQ pin is actively LOW
available() = 0
    data_sent: 1, data_fail: 0, data_ready: 0
   'Data Sent' event test passed

Sending 1 payload to fill RX node's FIFO. IRQ pin is neglected.
RX node's FIFO is full; it is not listening any more

Configuring IRQ pin to reflect all events
   Pinging inactive RX node for 'data fail' event...
    IRQ pin is actively LOW
available() = 0
    data_sent: 0, data_fail: 1, data_ready: 0
   'Data Fail' event test passed

Notice the first paragraph says the "'Data Ready' event test failed", but there is data received from an ACK payload in the RX FIFO (as evident by the "available() = 1"). Believe it or not I've seen this before in python. The RX_DR flag actually gets asserted after the TX_DS flag when using ACK payloads (contrary to what the datasheet says). This is because the chip clocks the payload into the RX FIFO after asserting the TX_DS flag. I think this error has something to do with whatHappened() since it calls write_payload(NRF_STATUS, 0x70) and returns the status byte's IRQ flags from MISO during that transaction (I'm trying to say the status byte returned may be outdated).

Furthermore, I have stumbled into a scenario that could actually use a separate clear_status_flags() when using writeFast() without using reUseTX()... I can provide more on that if anyone is curious.

I'm starting to really want this clear status flags behavior separate from whatHappened()

Then again, I could be completely wrong because the "Data Ready" event test hangs indefinitely when I mask (ignore) the "Data Sent" event on the IRQ pin (even though data is received). What's also concerning is that I never fetched data from the RX FIFO and available() returns false for the rest of the event tests. Clearly I'm not done debugging this, but I wanted to document this somewhere. For the record, I had to declare the radio variable as volatile to use the whatHappened() inside the ISR callback (per Arduino.cc docs on attachInterrupt()).