I was just looking at the function you wrote and in this line: PORTAbits.RA3 = (txdata > 127); // Copy bit 7 of txdata to RA3 (MOSI)
I've never seen an argument like this before, wish this was something my professors taught me, very useful. Can you apply this to select out certain bits, like: PORTAbits.RA3 = (txdata>1 && txdata<4)
would that give me access to only bit 1?
No. Comparing the byte value to a constant (in this case, 127) only works for isolating the top bit. Because if the top bit is 1, the byte value will be 128 or more; if the top bit is 0, the byte value will be 127 or less.
A more general way to isolate any bit, which you can use in that function for better clarity, is:
PORTAbits.RA3 = ((txdata & 0b10000000) != 0);
This performs a bitwise AND between txdata and that binary constant, which has only one bit set, then compares the result to 0. If the bit we're interested in was set, the result of the AND would be non-zero, so the "!= 0" comparison would succeed and would produce a result of 1, to be assigned to PORTAbits.RA3. If the bit we're interested in was clear, the result of the AND would be zero, the comparison would fail and the result assigned to PORTAbits.RA3 would be 0. In both cases, the value assigned to PORTAbits.RA3 is the value of the bit identified by the bitmask in the bitwise AND operation with txdata.
I found in the NRF datasheet(p.53) it says that the microcontroller needs to write a '1' to the IRQ source bit in the status register in order for the IRQ pin the release control. So it looks like I will need to write to the NRF twice whenever it has data that needs to be processed. Good thing I found this because for some reason I was under the impression that once the RX-FIFO was emptied the IRQ went back high.
Cool.
I had a quick look at your code. You seem to have several const uint8_t variables that you don't need. Just say #define NRF_CONFIG 0x4F and so on, and pass those named constants to spi_txrx_byte() instead of the variables.
You can, and should, use more #defines to equate meaningful names to I/O bits. You're using PORTAbits.RA0 as an active high chip enable for the nRF, so you could say:
#define NRF_CHIP_ENABLE PORTAbits.RA0
then later you can say:
NRF_CHIP_ENABLE = 0; // Disable nRF receiver
which looks a lot clearer. You can also #define statements as pseudofunctions:
#define ENABLE_NRF() PORTAbitsRA0 = 1
#define DISABLE_NRF() PORTAbits.RA0 = 0
then just say ENABLE_NRF() when you want to enable the nRF, and DISABLE_NRF() when you want to disable it.
By convention, constant values, and pseudofunctions created using #define, are named in full upper case.
Finally, I'm not sure you have the right sequence of commands for reading the data and resetting the interrupt. I would expect you should request the data, receive it (into a buffer with enough room for the maximum response; receive the number of bytes that the nRF tells you it has received), and only then clear the interrupt request flag.
Other than that, the code looks good to me. But I haven't studied the nRF communication protocol so I can't say it's exactly right.