Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Request] available() could be slightly faster #631

Closed
2bndy5 opened this issue Sep 20, 2020 · 2 comments
Closed

[Request] available() could be slightly faster #631

2bndy5 opened this issue Sep 20, 2020 · 2 comments

Comments

@2bndy5
Copy link
Member

2bndy5 commented Sep 20, 2020

Rationality

The current implementation for available() is as follows:

bool RF24::available(uint8_t* pipe_num) {
    if (!(read_register(FIFO_STATUS) & _BV(RX_EMPTY))) {
        // If the caller wants the pipe number, include that
        if (pipe_num) {
            uint8_t status = get_status();
            *pipe_num = (status >> RX_P_NO) & 0x07;
        }
        return 1;
    }
    return 0;
}  // removed empty lines from source for brevity

The nRF24L01's full duplex behavior gives us the status byte for free on every SPI transaction. This means we're fetching the status byte essentially twice. Once during read_register(FIFO_STATUS), and once during get_status(). Remember that the status byte holds information about what pipe received the next available payload in the RX FIFO (thus the *pipe_num = (status >> RX_P_NO) & 0x07;), and get_status() need only write a single byte (SPI command 0xFF). According to the datasheet, RX_P_NO of the STATUS register will be a number greater than 5 if the RX FIFO is empty.

Revision

By cutting out the extra SPI transaction for read_register(FIFO_STATUS), we can maintain the same behavior and save ourselves 5 microseconds (csDelay value) as well as the extra time spent on MOSI/MISO to complete checking the FIFO_STATUS register.

bool RF24::available(uint8_t* pipe_num)
{
    // get implied RX FIFO empty flag from status byte
    uint8_t pipe = (get_status() >> RX_P_NO) & 0x07;
    if (pipe <= 5)
    {
        // If the caller wants the pipe number, include that
        if (pipe_num)
        {
            *pipe_num = pipe;
        }
        return 1;
    }
    return 0;
}

Additional context

RX_P_0 information is consistent between plus and non-plus versions of nRF24L01 according to datasheets (link above goes to nRF24L01+ datasheet). Status byte received over MISO may get outdated until next SPI transaction when reading a payload from RX FIFO, thus using get_status() and why we can't use the RF24::status private member.

@2bndy5
Copy link
Member Author

2bndy5 commented Nov 11, 2020

I forgot about this little note from the datasheet:

Note: The 3 bit pipe information in the STATUS register is updated during the IRQ pin high to low transition. The pipe information is unreliable if the STATUS register is read during an IRQ pin high to low transition.

This would affect any program that calls available() during an ISR callback using attachInterrupt(irq_pin, isr_callback, FALLING). We can still speed up available() if we use the status byte fetched over MISO from the read_register(FIFO_STATUS) call (as suggested in #678). Which is just one byte slower than my initial proposal (and still 1 byte faster than original algorithm).

This note from the datasheet also negates my suggestion to @SimonMerrett about using FALLING as mode parameter to attachInterrupt() in #680

@2bndy5 2bndy5 reopened this Nov 11, 2020
@2bndy5
Copy link
Member Author

2bndy5 commented Nov 14, 2020

I have decided that my above comment about not using available(&pipe_number) during a FALLING transition on the IRQ pin should be avoided in docs and example comments because there is nothing the library can do to prevent the user from getting unreliable pipe_number information in such a specific use case.

@2bndy5 2bndy5 closed this as completed Nov 14, 2020
jscrane added a commit that referenced this issue Nov 29, 2020
* available() could be slightly faster #631

* allow skipping delay(5) in powerUp()

* allow skipping delay(5) in powerUp()

* Revert "allow skipping delay(5) in powerUp()"

This reverts commit ffd7524.

* Revert "allow skipping delay(5) in powerUp()"

This reverts commit ffd7524.

* add RF24_POWERUP_DELAY_MS to RF24_config.h

* delayMicroseconds()

* update doc comment
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant