REKLAMA

source.zip

Jak połączyć nRF905 z ESP32-WROOM-32 v1.1? Nie działające nadawanie/odbieranie

Cześć, Chciałbym wykorzystać moduł nrf905 (radio 433 i 868 na SPI) z kontrolerem ESP32 WROOM 32... Znalazłem bibliotekę do obsługi tego modułu dla arduino, ze strony http://blog.zakkemble.co.uk/nrf905-avrarduino-librarydriver/ Do testów wykorzystałem źródła ping_client, i ping_server na 2 kompletach ESP32 +nRF905. Jeden miał pracować jako klient, drugi jako serwer. Sama biblioteka wymagała małego przemapowania pinów, dodatkowo SPI przepiąłem z VSPI na HSPI na pinach 12-15 Pozostałe wykorzystane piny to: CD - 6, AM - 27, DR - 7, PWR - 11, TxE - 0 CE - 34 Napięcie zasilana modułu 3,3V Chyba wszystko.... Przykłady kompilują się bez większych problemów, ładują się do ESP... i niby działają, ale... nie nadają, a przynajmniej jeden nie widzi drugiego. Pytanie czy ktoś próbował podpiąć nRF905 do ESP32, czy to działało, może jest jakaś inna biblioteka, dedykowana do ESP? A i jeszcze jedno, do kompilacji wykorzystuję Sloebera. W załączniku źródła klienta i serwera + biblioteka po korekcie. I jeszcze jeden szczegół w bibliotece SPI zmieniłem na końcu linijkę by przełączyć pinologię na HSPI //SPIClass SPI(VSPI); SPIClass SPI(HSPI); Z góry dzięki za wszelkie sugestie...


Pobierz plik - link do postu
  • source.zip
    • nrf905ESP32Server.ino
    • nrf905ESP32Client.ino
    • library
      • nRF905
        • 3.0.0
          • keywords.txt
          • examples
            • wirelessSerialLink
              • wirelessSerialLink.ino
            • callbacks_irq
              • callbacks_irq.ino
            • ping_server
              • ping_server.ino
            • lowpwr_client
              • lowpwr_client.ino
            • ping_client
              • ping_client.ino
            • lowpwr_server
              • lowpwr_server.ino
            • debug
              • debug.ino
          • src
            • nRF905.h
            • nRF905_defs.h
            • nRF905.cpp
            • nRF905_config.h
          • library.properties


source.zip > keywords.txt

#######################################
# Syntax Coloring Map nRF905
#######################################

#######################################
# Datatypes (KEYWORD1)
#######################################

nRF905 KEYWORD1

#######################################
# Methods and Functions (KEYWORD2)
#######################################
nRF905_init KEYWORD2
nRF905_setChannel KEYWORD2
nRF905_setBand KEYWORD2
nRF905_setAutoRetransmit KEYWORD2
nRF905_setLowRxPower KEYWORD2
nRF905_setTransmitPower KEYWORD2
nRF905_setCRC KEYWORD2
nRF905_setClockOut KEYWORD2
nRF905_setPayloadSize KEYWORD2
nRF905_setAddressSize KEYWORD2
nRF905_receiveBusy KEYWORD2
nRF905_airwayBusy KEYWORD2
nRF905_setListenAddress KEYWORD2
nRF905_TX KEYWORD2
nRF905_RX KEYWORD2
nRF905_read KEYWORD2
nRF905_powerDown KEYWORD2
nRF905_powerUp KEYWORD2
nRF905_standby KEYWORD2
nRF905_getConfigRegisters KEYWORD2
nRF905_SERVICE KEYWORD2
nRF905_irq_on KEYWORD2
nRF905_irq_off KEYWORD2
NRF905_NO_INTERRUPT KEYWORD2
NRF905_CALC_CHANNEL KEYWORD2

#######################################
# Constants (LITERAL1)
#######################################

NRF905_NEXTMODE_STANDBY LITERAL1
NRF905_NEXTMODE_RX LITERAL1
NRF905_NEXTMODE_TX LITERAL1
NRF905_BAND_433MHZ LITERAL1
NRF905_BAND_868MHZ LITERAL1
NRF905_BAND_915MHZ LITERAL1
NRF905_PWR_n10 LITERAL1
NRF905_PWR_n2 LITERAL1
NRF905_PWR_6 LITERAL1
NRF905_PWR_10 LITERAL1
NRF905_LOW_RX_ENABLE LITERAL1
NRF905_LOW_RX_DISABLE LITERAL1
NRF905_AUTO_RETRAN_ENABLE LITERAL1
NRF905_AUTO_RETRAN_DISABLE LITERAL1
NRF905_OUTCLK_DISABLE LITERAL1
NRF905_OUTCLK_4MHZ LITERAL1
NRF905_OUTCLK_2MHZ LITERAL1
NRF905_OUTCLK_1MHZ LITERAL1
NRF905_OUTCLK_500KHZ LITERAL1
NRF905_CRC_DISABLE LITERAL1
NRF905_CRC_MODE_8 LITERAL1
NRF905_CRC_MODE_16 LITERAL1
NRF905_ADDR_SIZE_1 LITERAL1
NRF905_ADDR_SIZE_4 LITERAL1
NRF905_MAX_PAYLOAD LITERAL1
NRF905_REGISTER_COUNT LITERAL1
NRF905_DEFAULT_RXADDR LITERAL1
NRF905_DEFAULT_TXADDR LITERAL1


source.zip > nRF905.h

/*
* Project: nRF905 AVR/Arduino Library/Driver
* Author: Zak Kemble, contact@zakkemble.co.uk
* Copyright: (C) 2017 by Zak Kemble
* License: GNU GPL v3 (see License.txt)
* Web: http://blog.zakkemble.co.uk/nrf905-avrarduino-librarydriver/
*/

#ifndef NRF905_H_
#define NRF905_H_

#ifdef ARDUINO
#include & lt; Arduino.h & gt;
#endif

#include & lt; stdint.h & gt;

#include " nRF905_config.h "

/**
* @brief Available modes after transmission complete.
*/
typedef enum
{
NRF905_NEXTMODE_STANDBY, /// & lt; Standby mode
NRF905_NEXTMODE_RX, /// & lt; Receive mode
NRF905_NEXTMODE_TX /// & lt; Transmit mode (will auto-retransmit if ::NRF905_AUTO_RETRAN is ::NRF905_AUTO_RETRAN_ENABLE, otherwise will transmit a carrier wave with no data)
} nRF905_nextmode_t;

/**
* @brief Frequency bands.
*/
typedef enum
{
// NOTE:
// When using NRF905_BAND_868 and NRF905_BAND_915 for calculating channel (NRF905_CALC_CHANNEL(f, b)) they should be value 0x01,
// but when using them for setting registers their value should be 0x02.
// They're defined as 0x02 here so when used for calculating channel they're right shifted by 1

NRF905_BAND_433 = 0x00, /// & lt; 433MHz band
NRF905_BAND_868 = 0x02, /// & lt; 868/915MHz band
NRF905_BAND_915 = 0x02 /// & lt; 868/915MHz band
} nRF905_band_t;

/**
* @brief Output power (n means negative, n10 = -10).
*/
typedef enum
{
NRF905_PWR_n10 = 0x00, /// & lt; -10dBm = 100uW
NRF905_PWR_n2 = 0x04, /// & lt; -2dBm = 631uW
NRF905_PWR_6 = 0x08, /// & lt; 6dBm = 4mW
NRF905_PWR_10 = 0x0C /// & lt; 10dBm = 10mW
} nRF905_pwr_t;

/**
* @brief Save a few mA by reducing receive sensitivity.
*/
typedef enum
{
NRF905_LOW_RX_DISABLE = 0x00, /// & lt; Disable low power receive
NRF905_LOW_RX_ENABLE = 0x10 /// & lt; Enable low power receive
} nRF905_low_rx_t;

/**
* @brief Auto re-transmit options.
*/
typedef enum
{
NRF905_AUTO_RETRAN_DISABLE = 0x00, /// & lt; Disable auto re-transmit
NRF905_AUTO_RETRAN_ENABLE = 0x20 /// & lt; Enable auto re-transmit
} nRF905_auto_retran_t;

/**
* @brief Output a clock signal on pin 3 of IC.
*/
typedef enum
{
NRF905_OUTCLK_DISABLE = 0x00, /// & lt; Disable output clock
NRF905_OUTCLK_4MHZ = 0x04, /// & lt; 4MHz clock
NRF905_OUTCLK_2MHZ = 0x05, /// & lt; 2MHz clock
NRF905_OUTCLK_1MHZ = 0x06, /// & lt; 1MHz clock
NRF905_OUTCLK_500KHZ = 0x07, /// & lt; 500KHz clock (default)
} nRF905_outclk_t;

/**
* @brief CRC Checksum.
*
* The CRC is calculated across the address (SYNC word) and payload
*/
typedef enum
{
NRF905_CRC_DISABLE = 0x00, /// & lt; Disable CRC
NRF905_CRC_8 = 0x40, /// & lt; 8bit CRC (Don't know what algorithm is used for this one)
NRF905_CRC_16 = 0xC0, /// & lt; 16bit CRC (CRC16-CCITT-FALSE (0xFFFF))
} nRF905_crc_t;

/**
* @brief Address size.
*
* This is actually used as the SYNC word
*/
typedef enum
{
NRF905_ADDR_SIZE_1 = 0x01, /// & lt; 1 byte (not recommended, a lot of false invalid packets will be received)
NRF905_ADDR_SIZE_4 = 0x04, /// & lt; 4 bytes
} nRF905_addr_size_t;

// TODO remove?
// Setting options
//#define NRF905_BAND_433 0x00
//#define NRF905_BAND_868 0x02
//#define NRF905_BAND_915 0x02
//#define NRF905_PWR_n10 0x00
//#define NRF905_PWR_n2 0x04
//#define NRF905_PWR_6 0x08
//#define NRF905_PWR_10 0x0C
//#define NRF905_LOW_RX_ENABLE 0x10
//#define NRF905_LOW_RX_DISABLE 0x00
//#define NRF905_AUTO_RETRAN_ENABLE 0x20
//#define NRF905_AUTO_RETRAN_DISABLE 0x00
//#define NRF905_OUTCLK_DISABLE 0x00
//#define NRF905_OUTCLK_4MHZ 0x04
//#define NRF905_OUTCLK_2MHZ 0x05
//#define NRF905_OUTCLK_1MHZ 0x06
//#define NRF905_OUTCLK_500KHZ 0x07
//#define NRF905_CRC_DISABLE 0x00
//#define NRF905_CRC_8 0x40
//#define NRF905_CRC_16 0xC0
//#define NRF905_ADDR_SIZE_1 0x01
//#define NRF905_ADDR_SIZE_4 0x04

#define NRF905_MAX_PAYLOAD 32 /// & lt; Maximum payload size
#define NRF905_REGISTER_COUNT 10 /// & lt; Configuration register count
#define NRF905_DEFAULT_RXADDR 0xE7E7E7E7 /// & lt; Default receive address
#define NRF905_DEFAULT_TXADDR 0xE7E7E7E7 /// & lt; Default transmit/destination address

#define NRF905_CALC_CHANNEL(f, b) ((((f) / (1 + (b & gt; & gt; 1))) - 422400000UL) / 100000UL) /// & lt; Workout channel from frequency & band

#if defined(__cplusplus)
extern " C " {
#endif

/**
* @brief Initialise, must be called before anything else!
*
* @return (none)
*/
void nRF905_init(void);

/**
* @brief Channel to listen and transmit on
*
* 433MHz band: Channel 0 is 422.4MHz up to 511 which is 473.5MHz (Each channel is 100KHz apart)
*
* 868/915MHz band: Channel 0 is 844.8MHz up to 511 which is 947MHz (Each channel is 200KHz apart)
*
* @param [channel] The channel (0 - 511)
* @return (none)
*
* @see ::nRF905_setBand()
*/
void nRF905_setChannel(uint16_t channel);

/**
* @brief Frequency band
*
* @param [band] Frequency band, see ::nRF905_band_t
* @return (none)
*
* @see ::nRF905_setChannel() ::nRF905_band_t
*/
void nRF905_setBand(nRF905_band_t band);

/**
* @brief Set auto retransmit
*
* If next mode is set to ::NRF905_NEXTMODE_TX when calling ::nRF905_TX() and auto-retransmit is enabled then it will constantly retransmit the payload, otherwise a carrier wave with no data will be transmitted instead (kinda useless).\n
* Transmission will continue until the radio is put into standby, power down or RX mode.
*
* Can be useful in areas with lots of interference, but you'll need to make sure you can differentiate between re-transmitted packets and new packets (like an ID number).
*
* Other transmissions will be blocked if collision avoidance is enabled.
*
* @param [val] Enable/disable auto retransmit, see ::nRF905_auto_retran_t
* @return (none)
*/
void nRF905_setAutoRetransmit(nRF905_auto_retran_t val);

/**
* @brief Set low power receive
*
* @param [val] Enable/disable low power receive, see ::nRF905_low_rx_t
* @return (none)
*/
void nRF905_setLowRxPower(nRF905_low_rx_t val);

/**
* @brief Set output power
*
* @param [val] Output power level, see ::nRF905_pwr_t
* @return (none)
*/
void nRF905_setTransmitPower(nRF905_pwr_t val);

/**
* @brief Set CRC
*
* @param [val] CRC Type, see ::nRF905_crc_t
* @return (none)
*/
void nRF905_setCRC(nRF905_crc_t val);

/**
* @brief Set clock output
*
* @param [val] Clock out frequency, see ::nRF905_outclk_t
* @return (none)
*/
void nRF905_setClockOut(nRF905_outclk_t val);

/**
* @brief Payload size
*
* @param [size] Payload size (1 - 32)
* @return (none)
*
* @see ::NRF905_MAX_PAYLOAD
*/
void nRF905_setPayloadSize(uint8_t size);

/**
* @brief Address size
*
* @param [size] Address size, see ::nRF905_addr_size_t
* @return (none)
*/
void nRF905_setAddressSize(nRF905_addr_size_t size);

/**
* @brief See if the attach match is asserted
*
* @return 1 if currently receiving payload or payload is ready to be read, otherwise 0
*/
uint8_t nRF905_receiveBusy(void);

/**
* @brief See if airway is busy (carrier detect pin asserted).
*
* @return 1 if other transmissions detected, otherwise 0
*/
uint8_t nRF905_airwayBusy(void);

/**
* @brief Set address to listen to
*
* @note From the datasheet: Each byte within the address should be unique. Repeating bytes within the address reduces the effectiveness of the address and increases its susceptibility to noise which increases the packet error rate. The address should also have several level shifts (that is, 10101100) reducing the statistical effect of noise and the packet error rate.
* @param [address] The address, a 32 bit integer (default address is 0xE7E7E7E7)
* @return (none)
*/
void nRF905_setListenAddress(uint32_t address);

/**
* @brief Begin a transmission
*
* If the radio is still transmitting then the the payload and address will be updated as it is being sent, this means the payload on the receiving end may contain old and new data.\n
* This also means that a node may receive part of a payload that was meant for a node with a different address.\n
* Use the ::NRF905_CB_TXCOMPLETE callback to set a flag or something to ensure the transmission is complete before sending another payload.
*
* If the radio is in power down mode then this function will take an additional 3ms to complete.
* If 3ms is too long then call ::nRF905_standby(), do whatever you need to do for at least 3ms then call ::nRF905_TX().
*
* If \p nextMode is set to ::NRF905_NEXTMODE_RX then this function will take an additional 700us to complete.\n
* If 700us is too long then set \p nextMode to ::NRF905_NEXTMODE_STANDBY and call ::nRF905_RX() in the ::NRF905_CB_TXCOMPLETE callback instead.
*
* If \p data is NULL and/or \p len is 0 then the payload will not be modified, whatever was previously transmitted will be sent again to the \p sendTo address.
*
* For the collision avoidance to work the radio should be in RX mode for around 5ms before attempting to transmit.
*
* @param [sendTo] Address to send the payload to
* @param [data] The data
* @param [len] Data length (max ::NRF905_MAX_PAYLOAD)
* @param [nextMode] What mode to enter once the transmission is complete, see ::nRF905_nextmode_t
* @return 0 if other transmissions are going on and collision avoidance is enabled, 1 if transmission has successfully began
*/
uint8_t nRF905_TX(uint32_t sendTo, void* data, uint8_t len, nRF905_nextmode_t nextMode);

/**
* @brief Enter receive mode.
*
* If the radio is currently transmitting then receive mode will be entered once it has finished.
* This function will also automatically power up the radio and leave standby mode.
*
* @return (none)
*/
void nRF905_RX(void);

/**
* @brief Get received payload.
*
* This function can be called multiple times to read a few bytes at a time.
* The payload is cleared when the radio enters power down mode or leaves standby and enters RX mode.
* The radio will not receive anymore data until all of the payload has been read or cleared.
*
* @param [data] Buffer for the data
* @param [len] How many bytes to get
* @return (none)
*/
void nRF905_read(void* data, uint8_t len);

/**
* @brief Sleep.
*
* This also clears the RX payload.
*
* @return (none)
*/
void nRF905_powerDown(void);

/**
* @brief Enter standby mode.
*
* Will take 3ms to complete if the radio was in power down mode.
* ::nRF905_standby() does the same thing, but without the delay.
* There must be a 3ms delay between powering up and beginning a transmission.
*
* @return (none)
*/
void nRF905_powerUp(void);

/**
* @brief Enter standby mode.
*
* Similar to ::nRF905_powerUp() but without any delays.
* There must be a 3ms delay between powering up and beginning a transmission.
*
* @return (none)
*/
void nRF905_standby(void);

/**
* @brief Read configuration registers into byte array of ::NRF905_REGISTER_COUNT elements, mainly for debugging.
*
* @return (none)
*/
void nRF905_getConfigRegisters(void*);

/**
* @brief If interrupts are disabled (::NRF905_INTERRUPTS in nRF905_config.h) then this function should be called as often as possible to process any events
*
* If the radio seems to stop receiving new data then you're probably not calling this often enough (at least every few milliseconds).
*
* @return (none)
*/
#if DOXYGEN || NRF905_INTERRUPTS == 0
void nRF905_SERVICE(void);
#else
#define nRF905_SERVICE() ((void)(0))
#endif

/**
* @brief When using interrupts use this to disable them for the nRF905
*
* Ideally you should wrap sensitive sections with ::NRF905_NO_INTERRUPT() instead, as it automatically deals with this function and ::nRF905_irq_on()
*
* @see ::nRF905_irq_on() and ::NRF905_NO_INTERRUPT()
* @return The previous interrupt status; 1 if interrupt was enabled, 0 if it was already disabled
*/
uint8_t nRF905_irq_off(void);

/**
* @brief When using interrupts use this to re-enable them for the nRF905
*
* Ideally you should wrap sensitive sections with ::NRF905_NO_INTERRUPT() instead, as it automatically deals with this function and ::nRF905_irq_off()
*
* @see ::nRF905_irq_off() and ::NRF905_NO_INTERRUPT()
* @param [origVal] The original interrupt status returned from ::nRF905_irq_off()
* @return (none)
*/
void nRF905_irq_on(uint8_t origVal);

#if DOXYGEN || NRF905_INTERRUPTS != 0

#if !defined(DOXYGEN)
static inline void _nRF905_iRestore(const uint8_t *__s)
{
nRF905_irq_on(*__s);
__asm__ volatile ( " " ::: " memory " );
}
#endif

/**
* @brief Disable nRF905 interrupts for code inside this block
*
* When communicating with other SPI devices on the same bus as the radio then you should wrap those sections in a ::NRF905_NO_INTERRUPT() block, this will stop the nRF905 interrupt from running and trying to use the bus at the same time.
* This macro is based on the code from avr/atomic.h, and wraps the ::nRF905_irq_off() and ::nRF905_irq_on() functions instead of messing with global interrupts. It is safe to return, break or continue inside an ::NRF905_NO_INTERRUPT() block.
*
* Example:
*
* nRF905_RX();\n
* NRF905_NO_INTERRUPT()\n
* {\n
* OLED.write( " blah " , 2, 10); // Communicate with SPI OLED display\n
* }\n
*/
#define NRF905_NO_INTERRUPT() \
for(uint8_t nrf905_irq __attribute__((__cleanup__(_nRF905_iRestore))) = nRF905_irq_off(), \
nrf905_tmp = 1; nrf905_tmp ; nrf905_tmp = 0)

#else
#define NRF905_NO_INTERRUPT() ((void)(0));
#endif


#if defined(__cplusplus)
}
#endif

#endif /* NRF905_H_ */


source.zip > nRF905_defs.h

/*
* Project: nRF905 AVR/Arduino Library/Driver
* Author: Zak Kemble, contact@zakkemble.co.uk
* Copyright: (C) 2017 by Zak Kemble
* License: GNU GPL v3 (see License.txt)
* Web: http://blog.zakkemble.co.uk/nrf905-avrarduino-librarydriver/
*/

#ifndef NRF905_DEFS_H_
#define NRF905_DEFS_H_

// Instructions
#define NRF905_CMD_NOP 0xFF
#define NRF905_CMD_W_CONFIG 0x00
#define NRF905_CMD_R_CONFIG 0x10
#define NRF905_CMD_W_TX_PAYLOAD 0x20
#define NRF905_CMD_R_TX_PAYLOAD 0x21
#define NRF905_CMD_W_TX_ADDRESS 0x22
#define NRF905_CMD_R_TX_ADDRESS 0x23
#define NRF905_CMD_R_RX_PAYLOAD 0x24
#define NRF905_CMD_CHAN_CONFIG 0x80

// Registers
#define NRF905_REG_CHANNEL 0x00
#define NRF905_REG_CONFIG1 0x01
#define NRF905_REG_ADDR_WIDTH 0x02
#define NRF905_REG_RX_PAYLOAD_SIZE 0x03
#define NRF905_REG_TX_PAYLOAD_SIZE 0x04
#define NRF905_REG_RX_ADDRESS 0x05
#define NRF905_REG_CONFIG2 0x09


// TODO remove
#define NRF905_REG_AUTO_RETRAN NRF905_REG_CONFIG1
#define NRF905_REG_LOW_RX NRF905_REG_CONFIG1
#define NRF905_REG_PWR NRF905_REG_CONFIG1
#define NRF905_REG_BAND NRF905_REG_CONFIG1
#define NRF905_REG_CRC NRF905_REG_CONFIG2
#define NRF905_REG_CLK NRF905_REG_CONFIG2
#define NRF905_REG_OUTCLK NRF905_REG_CONFIG2
#define NRF905_REG_OUTCLK_FREQ NRF905_REG_CONFIG2


// Clock options
#define NRF905_CLK_4MHZ 0x00
#define NRF905_CLK_8MHZ 0x08
#define NRF905_CLK_12MHZ 0x10
#define NRF905_CLK_16MHZ 0x18
#define NRF905_CLK_20MHZ 0x20

// Register masks
#define NRF905_MASK_CHANNEL 0xFE
#define NRF905_MASK_AUTO_RETRAN ~(NRF905_AUTO_RETRAN_ENABLE | NRF905_AUTO_RETRAN_DISABLE) //0xDF
#define NRF905_MASK_LOW_RX ~(NRF905_LOW_RX_ENABLE | NRF905_LOW_RX_DISABLE) //0xEF
#define NRF905_MASK_PWR ~(NRF905_PWR_n10 | NRF905_PWR_n2 | NRF905_PWR_6 | NRF905_PWR_10) //0xF3
#define NRF905_MASK_BAND ~(NRF905_BAND_433 | NRF905_BAND_868 | NRF905_BAND_915) //0xFD
#define NRF905_MASK_CRC (uint8_t)(~(NRF905_CRC_DISABLE | NRF905_CRC_8 | NRF905_CRC_16)) //0x3F // typecast to stop compiler moaning about large integer truncation
#define NRF905_MASK_CLK ~(NRF905_CLK_4MHZ | NRF905_CLK_8MHZ | NRF905_CLK_12MHZ | NRF905_CLK_16MHZ | NRF905_CLK_20MHZ) //0xC7
#define NRF905_MASK_OUTCLK ~(NRF905_OUTCLK_DISABLE | NRF905_OUTCLK_4MHZ | NRF905_OUTCLK_2MHZ | NRF905_OUTCLK_1MHZ | NRF905_OUTCLK_500KHZ) // 0xF8

// Bit positions
#define NRF905_STATUS_DR 5
#define NRF905_STATUS_AM 7

#include " nRF905_config.h "

#if (NRF905_DR_SW & & NRF905_INTERRUPTS)
#error " NRF905_INTERRUPTS and NRF905_DR_SW cannot both be enabled "
#elif (NRF905_AM_SW & & NRF905_INTERRUPTS_AM)
#error " NRF905_INTERRUPTS_AM and NRF905_AM_SW cannot both be enabled "
#elif (!NRF905_INTERRUPTS & & NRF905_INTERRUPTS_AM)
#error " NRF905_INTERRUPTS_AM cannot be enabled without NRF905_INTERRUPTS "
#endif

#ifndef ARDUINO

#define CONCAT(a, b) a ## b
#define CONCAT2(a, b, c) a ## b ## c

#define PORT(port) CONCAT(PORT, port)
#define PORTBIT(port, bit) CONCAT2(PORT, port, bit)
#define DDR(port) CONCAT(DDR, port)
#define PINPORT(port) CONCAT(PIN, port)
#define PINBIT(port, bit) CONCAT2(PIN, port, bit)
#define PCINT(pcint) CONCAT(PCINT, pcint)

#define TRX_EN_DDR DDR(NRF905_TRX_EN_PORT)
#define TRX_EN_PORT PORT(NRF905_TRX_EN_PORT)
#define TRX_EN_BIT PORTBIT(NRF905_TRX_EN_PORT, NRF905_TRX_EN_BIT)

#define PWR_MODE_DDR DDR(NRF905_PWR_MODE_PORT)
#define PWR_MODE_PORT PORT(NRF905_PWR_MODE_PORT)
#define PWR_MODE_BIT PORTBIT(NRF905_PWR_MODE_PORT, NRF905_PWR_MODE_BIT)

#define TX_EN_DDR DDR(NRF905_TX_EN_PORT)
#define TX_EN_PORT PORT(NRF905_TX_EN_PORT)
#define TX_EN_BIT PORTBIT(NRF905_TX_EN_PORT, NRF905_TX_EN_BIT)

#define CD_DDR DDR(NRF905_CD_PORT)
#define CD_PORT PINPORT(NRF905_CD_PORT)
#define CD_BIT PINBIT(NRF905_CD_PORT, NRF905_CD_BIT)

#define AM_DDR DDR(NRF905_AM_PORT)
#define AM_PORT PINPORT(NRF905_AM_PORT)
#define AM_BIT PINBIT(NRF905_AM_PORT, NRF905_AM_BIT)

#define DR_DDR DDR(NRF905_DR_PORT)
#define DR_PORT PINPORT(NRF905_DR_PORT)
#define DR_BIT PINBIT(NRF905_DR_PORT, NRF905_DR_BIT)

#define CSN_DDR DDR(NRF905_CSN_PORT)
#define CSN_PORT PORT(NRF905_CSN_PORT)
#define CSN_BIT PORTBIT(NRF905_CSN_PORT, NRF905_CSN_BIT)



#define INTCONCAT(num) CONCAT(INT, num)
#define ISCCONCAT(num, bit) CONCAT2(ISC, num, bit)
#define INTVECTCONCAT(num) CONCAT2(INT, num, _vect)
/*
#ifndef NRF905_REG_EXTERNAL_INT_DR
#ifdef EIMSK
#define NRF905_REG_EXTERNAL_INT_DR EIMSK
#elif defined GICR
#define NRF905_REG_EXTERNAL_INT_DR GICR
#else
#define NRF905_REG_EXTERNAL_INT_DR GIMSK
#endif
#endif
*/
#ifndef NRF905_REG_EXTERNAL_INT_CTL_DR
#ifdef EICRA
#if NRF905_INTERRUPT_NUM_DR & lt; 4
#define NRF905_REG_EXTERNAL_INT_CTL_DR EICRA
#else
#define NRF905_REG_EXTERNAL_INT_CTL_DR EICRB
#endif
#else
#define NRF905_REG_EXTERNAL_INT_CTL_DR MCUCR
#endif
#endif
/*
#ifndef NRF905_BIT_EXTERNAL_INT_DR
#define NRF905_BIT_EXTERNAL_INT_DR INTCONCAT(NRF905_INTERRUPT_NUM_DR)
#endif
*/
#ifndef NRF905_BIT_EXTERNAL_INT_CTL_DR
#define NRF905_BIT_EXTERNAL_INT_CTL_DR (_BV(ISCCONCAT(NRF905_INTERRUPT_NUM_DR, 1))|_BV(ISCCONCAT(NRF905_INTERRUPT_NUM_DR, 0))) // Rising
#endif

#ifndef NRF905_INT_VECTOR_DR
#define NRF905_INT_VECTOR_DR INTVECTCONCAT(NRF905_INTERRUPT_NUM_DR)
#endif


/*
#ifndef NRF905_REG_EXTERNAL_INT_AM
#ifdef EIMSK
#define NRF905_REG_EXTERNAL_INT_AM EIMSK
#elif defined GICR
#define NRF905_REG_EXTERNAL_INT_AM GICR
#else
#define NRF905_REG_EXTERNAL_INT_AM GIMSK
#endif
#endif
*/
#ifndef NRF905_REG_EXTERNAL_INT_CTL_AM
#ifdef EICRA
#if NRF905_INTERRUPT_NUM_AM & lt; 4
#define NRF905_REG_EXTERNAL_INT_CTL_AM EICRA
#else
#define NRF905_REG_EXTERNAL_INT_CTL_AM EICRB
#endif
#else
#define NRF905_REG_EXTERNAL_INT_CTL_AM MCUCR
#endif
#endif
/*
#ifndef NRF905_BIT_EXTERNAL_INT_AM
#define NRF905_BIT_EXTERNAL_INT_AM INTCONCAT(NRF905_INTERRUPT_NUM_AM)
#endif
*/
#ifndef NRF905_BIT_EXTERNAL_INT_CTL_AM
#define NRF905_BIT_EXTERNAL_INT_CTL_AM (_BV(ISCCONCAT(NRF905_INTERRUPT_NUM_AM, 0))) // Any change
#endif

#ifndef NRF905_INT_VECTOR_AM
#define NRF905_INT_VECTOR_AM INTVECTCONCAT(NRF905_INTERRUPT_NUM_AM)
#endif

#endif

#endif /* NRF905_DEFS_H_ */


source.zip > nRF905.cpp

/*
* Project: nRF905 AVR/Arduino Library/Driver
* Author: Zak Kemble, contact@zakkemble.co.uk
* Copyright: (C) 2017 by Zak Kemble
* License: GNU GPL v3 (see License.txt)
* Web: http://blog.zakkemble.co.uk/nrf905-avrarduino-librarydriver/
*/

#ifdef ARDUINO
#include & lt; Arduino.h & gt;
#include & lt; SPI.h & gt;
#else
#include & lt; avr/io.h & gt;
#include & lt; avr/interrupt.h & gt;
#include & lt; avr/pgmspace.h & gt;
#include & lt; util/atomic.h & gt;
#include & lt; util/delay.h & gt;
#include " nRF905_spi.h "
#endif

#include & lt; string.h & gt;
#include & lt; stdint.h & gt;
#include " nRF905.h "
#include " nRF905_config.h "
#include " nRF905_defs.h "

#define noinline __attribute__ ((__noinline__))

#define NEED_SW_STATUS_SUPPORT (NRF905_AM_SW || NRF905_DR_SW)

#define NRF905_USE_PWR 1 // TODO

#if !NRF905_USE_PWR
#define POWERED_UP() (1)
#define POWER_UP() (void)(0)
#define POWER_DOWN() (void)(0)
#endif

#ifdef ARDUINO

#define delay_ms(ms) delay(ms)
#define delay_us(us) delayMicroseconds(us)

#if NRF905_USE_PWR
#define POWERED_UP() (digitalRead(NRF905_PWR_MODE) == HIGH)
#define POWER_UP() (digitalWrite(NRF905_PWR_MODE, HIGH))
#define POWER_DOWN() (digitalWrite(NRF905_PWR_MODE, LOW))
#endif

#define STANDBY_LEAVE() (digitalWrite(NRF905_TRX_EN, HIGH))
#define STANDBY_ENTER() (digitalWrite(NRF905_TRX_EN, LOW))
#define MODE_RX() (digitalWrite(NRF905_TX_EN, LOW))
#define MODE_TX() (digitalWrite(NRF905_TX_EN, HIGH))
#define spiSelect() (digitalWrite(NRF905_CSN, LOW))
#define spiDeselect() (digitalWrite(NRF905_CSN, HIGH))
#define spi_transfer(data) (SPI.transfer(data))
#define spi_transfer_nr(data) (SPI.transfer(data))

#else

#define delay_ms(ms) _delay_ms(ms)
#define delay_us(us) _delay_us(us)

#if NRF905_USE_PWR
#define POWERED_UP() (PWR_MODE_PORT & _BV(PWR_MODE_BIT))
#define POWER_UP() (PWR_MODE_PORT |= _BV(PWR_MODE_BIT))
#define POWER_DOWN() (PWR_MODE_PORT & = ~_BV(PWR_MODE_BIT))
#endif

#define STANDBY_LEAVE() (TRX_EN_PORT |= _BV(TRX_EN_BIT))
#define STANDBY_ENTER() (TRX_EN_PORT & = ~_BV(TRX_EN_BIT))
#define MODE_RX() (TX_EN_PORT & = ~_BV(TX_EN_BIT))
#define MODE_TX() (TX_EN_PORT |= _BV(TX_EN_BIT))
#define spiSelect() (CSN_PORT & = ~_BV(CSN_BIT))
#define spiDeselect() (CSN_PORT |= _BV(CSN_BIT))

#endif

#if defined(__cplusplus)
extern " C " {
#endif
static void __empty_callback0(void){}
#if defined(__cplusplus)
}
#endif

void __attribute__((weak, alias ( " __empty_callback0 " ))) NRF905_CB_RXCOMPLETE(void);
void __attribute__((weak, alias ( " __empty_callback0 " ))) NRF905_CB_RXINVALID(void);
void __attribute__((weak, alias ( " __empty_callback0 " ))) NRF905_CB_TXCOMPLETE(void);
//void __attribute__((weak, alias ( " __empty_callback0 " ))) NRF905_CB_AIRWAYBUSY(void);
//void __attribute__((weak, alias ( " __empty_callback0 " ))) NRF905_CB_AIRWAYCLEAR(void);
void __attribute__((weak, alias ( " __empty_callback0 " ))) NRF905_CB_ADDRMATCH(void);

#ifdef ARDUINO

#define SPI_SETTINGS SPISettings(10000000, MSBFIRST, SPI_MODE0)

#if NRF905_INTERRUPTS != 0
// It's not possible to get the current interrupt enabled state in Arduino (SREG only works for AVR based Arduinos, and no way of getting attachInterrupt() status), so we use a counter thing instead
static volatile uint8_t isrState_local;

static void nRF905_SERVICE_DR(void);
#if NRF905_INTERRUPTS_AM
static void nRF905_SERVICE_AM(void);
#endif

#endif

#if NRF905_INTERRUPTS == 1 || NRF905_INT_SPI_COMMS == 1
static volatile uint8_t isrState;
static volatile uint8_t isrBusy; // Don't mess with global interrupts if we're inside an ISR

static inline uint8_t interrupt_off(void)
{
if(!isrBusy)
{
noInterrupts();
isrState++;
}
return 1;
}

static inline uint8_t interrupt_on(void)
{
if(!isrBusy)
{
if(isrState & gt; 0)
isrState--;
if(isrState == 0)
interrupts();
}
return 0;
}
#endif

#endif

static inline uint8_t cselect(void)
{
// spi_enable();
#ifdef ARDUINO
// SPI.beginTransaction(SPI_SETTINGS);
#endif
spiSelect();
return 1;
}

static inline uint8_t cdeselect(void)
{
spiDeselect();
#ifdef ARDUINO
// SPI.endTransaction();
#endif
// spi_disable();
return 0;
}

// Can be in any mode to write registers, but standby or power down is recommended
#define STANDBY (STANDBY_ENTER())

#define CHIPSELECT(standby) standby; \
for(uint8_t _cs = cselect(); _cs; _cs = cdeselect())


/*
static inline uint8_t interrupt_off(void)
{
nRF905_irq_off();
return 1;
}

static inline uint8_t interrupt_on(void)
{
nRF905_irq_on();
return 0;
}
*/

#if NRF905_INTERRUPTS == 0 & & NRF905_INT_SPI_COMMS == 0
#define NRF905_ATOMIC() ((void)(0));
#elif defined(ARDUINO)
#define NRF905_ATOMIC() for(uint8_t _cs2 = interrupt_off(); _cs2; _cs2 = interrupt_on())
#else
#define NRF905_ATOMIC() ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
#endif

// When doing SPI comms with the radio or doing multiple commands we don't want the radio interrupt to mess it up.
uint8_t nRF905_irq_off()
{
#if NRF905_INTERRUPTS != 0

#ifdef ARDUINO
detachInterrupt(digitalPinToInterrupt(NRF905_DR));
#if NRF905_INTERRUPTS_AM
detachInterrupt(digitalPinToInterrupt(NRF905_AM));
#endif
isrState_local++;
return 0;
#else
uint8_t origVal = NRF905_REG_EXTERNAL_INT_DR;
NRF905_REG_EXTERNAL_INT_DR & = ~_BV(NRF905_BIT_EXTERNAL_INT_DR);
#if NRF905_INTERRUPTS_AM
NRF905_REG_EXTERNAL_INT_AM & = ~_BV(NRF905_BIT_EXTERNAL_INT_AM);
#endif
origVal = !!(origVal & _BV(NRF905_BIT_EXTERNAL_INT_DR));
return origVal;
#endif

#else
return 0;
#endif
}

void nRF905_irq_on(uint8_t origVal)
{
#if NRF905_INTERRUPTS != 0

#ifdef ARDUINO
((void)(origVal));
if(isrState_local & gt; 0)
isrState_local--;
if(isrState_local == 0)
{
attachInterrupt(digitalPinToInterrupt(NRF905_DR), nRF905_SERVICE_DR, RISING);
#if NRF905_INTERRUPTS_AM
attachInterrupt(digitalPinToInterrupt(NRF905_AM), nRF905_SERVICE_AM, CHANGE);
#endif
}
#else
if(origVal)
{
NRF905_REG_EXTERNAL_INT_DR |= _BV(NRF905_BIT_EXTERNAL_INT_DR);
#if NRF905_INTERRUPTS_AM
NRF905_REG_EXTERNAL_INT_AM |= _BV(NRF905_BIT_EXTERNAL_INT_AM);
#endif
}
#endif

#else
((void)(origVal));
#endif
}

static uint8_t readConfigRegister(uint8_t reg)
{
uint8_t val = 0;
NRF905_ATOMIC()
{
CHIPSELECT()
{
spi_transfer_nr(NRF905_CMD_R_CONFIG | reg);
val = spi_transfer(NRF905_CMD_NOP);
}
}
return val;
}

static void writeConfigRegister(uint8_t reg, uint8_t val)
{
NRF905_ATOMIC()
{
CHIPSELECT()
{
spi_transfer_nr(NRF905_CMD_W_CONFIG | reg);
spi_transfer_nr(val);
}
}
}

static void setConfigReg1(uint8_t val, uint8_t mask, uint8_t reg)
{
writeConfigRegister(reg, (readConfigRegister(NRF905_REG_CONFIG1) & mask) | val);
}

static void setConfigReg2(uint8_t val, uint8_t mask, uint8_t reg)
{
writeConfigRegister(reg, (readConfigRegister(NRF905_REG_CONFIG2) & mask) | val);
}

static const uint8_t config[] PROGMEM = {
NRF905_CMD_W_CONFIG,
NRF905_CHANNEL,
NRF905_AUTO_RETRAN | NRF905_LOW_RX | NRF905_PWR | NRF905_BAND | ((NRF905_CHANNEL & gt; & gt; 8) & 0x01),
(NRF905_ADDR_SIZE & lt; & lt; 4) | NRF905_ADDR_SIZE,
NRF905_PAYLOAD_SIZE, // RX payload size
NRF905_PAYLOAD_SIZE, // TX payload size
0xE7, 0xE7, 0xE7, 0xE7, // Default receive address
NRF905_CRC | NRF905_CLK_FREQ | NRF905_OUTCLK
};

static noinline void defaultConfig(void)
{
// Should be in standby mode

NRF905_ATOMIC()
{
// Set control registers
CHIPSELECT()
{
for(uint8_t i=0;i & lt; sizeof(config);i++)
spi_transfer_nr(pgm_read_byte( & ((uint8_t*)config)[i]));
}

// Default transmit address
CHIPSELECT()
{
spi_transfer_nr(NRF905_CMD_W_TX_ADDRESS);
for(uint8_t i=0;i & lt; 4;i++)
spi_transfer_nr(0xE7);
}

// Clear transmit payload
CHIPSELECT()
{
spi_transfer_nr(NRF905_CMD_W_TX_PAYLOAD);
for(uint8_t i=0;i & lt; NRF905_MAX_PAYLOAD;i++)
spi_transfer_nr(0x00);
}

#if !NRF905_USE_PWR
// Clear DR by reading receive payload
CHIPSELECT()
{
spi_transfer_nr(NRF905_CMD_R_RX_PAYLOAD);
for(uint8_t i=0;i & lt; NRF905_MAX_PAYLOAD;i++)
spi_transfer_nr(NRF905_CMD_NOP);
}
#endif
}
}

static void setAddress(uint32_t address, uint8_t cmd)
{
NRF905_ATOMIC()
{
CHIPSELECT()
{
spi_transfer_nr(cmd);
for(uint8_t i=0;i & lt; 4;i++)
spi_transfer_nr(address & gt; & gt; (8 * i));
}
}
}

#if NEED_SW_STATUS_SUPPORT
static uint8_t readStatus(void)
{
uint8_t status;
NRF905_ATOMIC()
{
CHIPSELECT()
status = spi_transfer(NRF905_CMD_NOP);
}
return status;
}
#endif

// Hardware: Data ready pin high
// Software: Data ready status bit set
#if !NRF905_INTERRUPTS
static uint8_t dataReady(void)
{
#if NRF905_DR_SW
return (readStatus() & (1 & lt; & lt; NRF905_STATUS_DR));
#elif defined(ARDUINO)
return digitalRead(NRF905_DR);
#else
return (DR_PORT & _BV(DR_BIT));
#endif
}
#endif

// Hardware: Address match pin high
// Software: Address match status bit set
static uint8_t addressMatched(void)
{
#if NRF905_AM_SW
return (readStatus() & (1 & lt; & lt; NRF905_STATUS_AM));
#elif defined(ARDUINO)
return digitalRead(NRF905_AM);
#else
return (AM_PORT & _BV(AM_BIT));
#endif
}

void nRF905_init()
{
#ifdef ARDUINO
digitalWrite(NRF905_CSN, HIGH);
pinMode(NRF905_CSN, OUTPUT);

pinMode(NRF905_TRX_EN, OUTPUT);
pinMode(NRF905_TX_EN, OUTPUT);

#if NRF905_USE_PWR
pinMode(NRF905_PWR_MODE, OUTPUT);
#endif

SPI.begin();
// SPI.setClockDivider(SPI_CLOCK_DIV2); // TODO CHECK THIS! Max SPI clock is 10MHz, but DIV2 will be 42MHz on the Due!
// SPI.usingInterrupt(digitalPinToInterrupt(NRF905_DR));
//#if NRF905_INTERRUPTS_AM
// SPI.usingInterrupt(digitalPinToInterrupt(NRF905_AM));
//#endif
#else
spiDeselect();
CSN_DDR |= _BV(CSN_BIT);

TRX_EN_DDR |= _BV(TRX_EN_BIT);
TX_EN_DDR |= _BV(TX_EN_BIT);

#if NRF905_USE_PWR
PWR_MODE_DDR |= _BV(PWR_MODE_BIT);
#endif

spi_init();
#endif

POWER_DOWN();
STANDBY_ENTER();
MODE_RX();
delay_ms(3);
defaultConfig();

#if NRF905_INTERRUPTS
// Set interrupts
#if !defined(ARDUINO)
NRF905_REG_EXTERNAL_INT_CTL_DR |= NRF905_BIT_EXTERNAL_INT_CTL_DR; // Trigger on rising
#if NRF905_INTERRUPTS_AM
NRF905_REG_EXTERNAL_INT_CTL_AM |= NRF905_BIT_EXTERNAL_INT_CTL_AM; // Trigger on change
#endif
#endif
nRF905_irq_on(1);
#endif
}

void nRF905_setChannel(uint16_t channel)
{
if(channel & gt; 511)
channel = 511;

NRF905_ATOMIC()
{
uint8_t reg = (readConfigRegister(NRF905_REG_CONFIG1) & NRF905_MASK_CHANNEL) | (channel & gt; & gt; 8);

CHIPSELECT()
{
spi_transfer_nr(NRF905_CMD_W_CONFIG | NRF905_REG_CHANNEL);
spi_transfer_nr(channel);
spi_transfer_nr(reg);
}
}
}

void nRF905_setBand(nRF905_band_t band)
{
NRF905_ATOMIC()
{
uint8_t reg = (readConfigRegister(NRF905_REG_CONFIG1) & NRF905_MASK_BAND) | band;

CHIPSELECT()
{
spi_transfer_nr(NRF905_CMD_W_CONFIG | NRF905_REG_CONFIG1);
spi_transfer_nr(reg);
}
}
}

void nRF905_setAutoRetransmit(nRF905_auto_retran_t val)
{
setConfigReg1(val, NRF905_MASK_AUTO_RETRAN, NRF905_REG_AUTO_RETRAN);
}

void nRF905_setLowRxPower(nRF905_low_rx_t val)
{
setConfigReg1(val, NRF905_MASK_LOW_RX, NRF905_REG_LOW_RX);
}

void nRF905_setTransmitPower(nRF905_pwr_t val)
{
setConfigReg1(val, NRF905_MASK_PWR, NRF905_REG_PWR);
}

void nRF905_setCRC(nRF905_crc_t val)
{
setConfigReg2(val, NRF905_MASK_CRC, NRF905_REG_CRC);
}

void nRF905_setClockOut(nRF905_outclk_t val)
{
setConfigReg2(val, NRF905_MASK_OUTCLK, NRF905_REG_OUTCLK);
}

void nRF905_setPayloadSize(uint8_t size)
{
NRF905_ATOMIC()
{
CHIPSELECT()
{
if(size & gt; NRF905_MAX_PAYLOAD)
size = NRF905_MAX_PAYLOAD;

spi_transfer_nr(NRF905_CMD_W_CONFIG | NRF905_REG_RX_PAYLOAD_SIZE);
spi_transfer_nr(size);
spi_transfer_nr(size);
}
}
}

void nRF905_setAddressSize(nRF905_addr_size_t size)
{
CHIPSELECT()
{
spi_transfer_nr(NRF905_CMD_W_CONFIG | NRF905_REG_ADDR_WIDTH);
spi_transfer_nr((size & lt; & lt; 4) | size);
}
}

uint8_t nRF905_receiveBusy()
{
return addressMatched();
}

uint8_t nRF905_airwayBusy()
{
#ifdef ARDUINO
return digitalRead(NRF905_CD);
#else
return (CD_PORT & _BV(CD_BIT));
#endif
}

void nRF905_setListenAddress(uint32_t address)
{
setAddress(address, NRF905_CMD_W_CONFIG | NRF905_REG_RX_ADDRESS);
}

uint8_t nRF905_TX(uint32_t sendTo, void* data, uint8_t len, nRF905_nextmode_t nextMode)
{
// TODO check DR is low?

NRF905_NO_INTERRUPT()
{
#if NRF905_COLLISION_AVOID
if(nRF905_airwayBusy())
return 0;
#endif

setAddress(sendTo, NRF905_CMD_W_TX_ADDRESS);

// Load new payload
if(data != NULL)
{
NRF905_ATOMIC()
{
CHIPSELECT()
{
spi_transfer_nr(NRF905_CMD_W_TX_PAYLOAD);
for(uint8_t i=0;i & lt; len;i++)
spi_transfer_nr(((uint8_t*)data)[i]);
}
}
}

if(!POWERED_UP())
{
STANDBY_ENTER();
POWER_UP();
delay_ms(3);
}

#if NRF905_COLLISION_AVOID
if(nRF905_airwayBusy())
return 0;
#endif

// Put into transmit mode
MODE_TX();

// Pulse standby pin to start transmission
STANDBY_LEAVE();

if(nextMode == NRF905_NEXTMODE_RX)
{
// The datasheets says that the radio can switch straight to RX mode after
// a transmission is complete by clearing TX_EN while transmitting, but
// if this is done within ~700us the transmission seems to get corrupt.
delay_us(700);
MODE_RX();
}
else if(nextMode == NRF905_NEXTMODE_STANDBY)
{
delay_us(14);
STANDBY_ENTER();
}
// else NRF905_NEXTMODE_TX
}

return 1;
}

void nRF905_RX()
{
NRF905_NO_INTERRUPT()
{
MODE_RX();
STANDBY_LEAVE();
POWER_UP();
}
}

void nRF905_read(void* data, uint8_t len)
{
if(len & gt; NRF905_MAX_PAYLOAD)
len = NRF905_MAX_PAYLOAD;

NRF905_ATOMIC()
{
CHIPSELECT()
{
spi_transfer_nr(NRF905_CMD_R_RX_PAYLOAD);

// Get received payload
for(uint8_t i=0;i & lt; len;i++)
((uint8_t*)data)[i] = spi_transfer(NRF905_CMD_NOP);

// Must make sure all of the payload has been read, otherwise DR never goes low
//uint8_t remaining = NRF905_MAX_PAYLOAD - len;
//while(remaining--)
// spi_transfer_nr(NRF905_CMD_NOP);
}
}
}

void nRF905_powerDown()
{
POWER_DOWN();
}

void nRF905_powerUp()
{
uint8_t wasPoweredUp = POWERED_UP();
STANDBY_ENTER();
POWER_UP();
if(!wasPoweredUp)
delay_ms(3);
}

void nRF905_standby()
{
STANDBY_ENTER();
POWER_UP();
}

void nRF905_getConfigRegisters(void* regs)
{
NRF905_ATOMIC()
{
CHIPSELECT()
{
spi_transfer_nr(NRF905_CMD_R_CONFIG);
for(uint8_t i=0;i & lt; NRF905_REGISTER_COUNT;i++)
((uint8_t*)regs)[i] = spi_transfer(NRF905_CMD_NOP);
}
}
}

#if !NRF905_INTERRUPTS

void nRF905_SERVICE()
{
static uint8_t invalidPacket;
static uint8_t rxComplete;
static uint8_t addrMatch;
static uint8_t txComplete;

uint8_t state_DR = dataReady();
uint8_t state_AM = addressMatched();

if(state_AM)
{
txComplete = 0;
invalidPacket = 0;

if(!addrMatch)
{
NRF905_CB_ADDRMATCH();
addrMatch = 1;
}

if(state_DR & & !rxComplete)
{
NRF905_CB_RXCOMPLETE();
rxComplete = 1;
}
}
else
{
if(!invalidPacket)
{
if(!rxComplete)
NRF905_CB_RXINVALID();
invalidPacket = 1;
}

if(state_DR & & !txComplete)
{
NRF905_CB_TXCOMPLETE();
txComplete = 1;
}

addrMatch = 0;
rxComplete = 0;
}
}

#else

static volatile uint8_t validPacket;

#ifdef ARDUINO
static void nRF905_SERVICE_DR()
#else
ISR(NRF905_INT_VECTOR_DR)
#endif
{
#if defined(ARDUINO) & & (NRF905_INTERRUPTS == 1 || NRF905_INT_SPI_COMMS == 1)
isrBusy = 1;
#endif
// If DR & & AM = RX new packet
// If DR & & !AM = TX finished

if(addressMatched())
{
validPacket = 1;
NRF905_CB_RXCOMPLETE();
}
else
NRF905_CB_TXCOMPLETE();

#if defined(ARDUINO) & & (NRF905_INTERRUPTS == 1 || NRF905_INT_SPI_COMMS == 1)
isrBusy = 0;
#endif
}

#if NRF905_INTERRUPTS_AM

#ifdef ARDUINO
static void nRF905_SERVICE_AM()
#else
ISR(NRF905_INT_VECTOR_AM)
#endif
{
#if defined(ARDUINO) & & (NRF905_INTERRUPTS == 1 || NRF905_INT_SPI_COMMS == 1)
isrBusy = 1;
#endif
// If AM goes HIGH then LOW without DR going HIGH then we got a bad packet

if(addressMatched())
NRF905_CB_ADDRMATCH();
else if(!validPacket)
NRF905_CB_RXINVALID();
validPacket = 0;

#if defined(ARDUINO) & & (NRF905_INTERRUPTS == 1 || NRF905_INT_SPI_COMMS == 1)
isrBusy = 0;
#endif
}

#endif

#endif


source.zip > nRF905_config.h

/*
* Project: nRF905 AVR/Arduino Library/Driver
* Author: Zak Kemble, contact@zakkemble.co.uk
* Copyright: (C) 2017 by Zak Kemble
* License: GNU GPL v3 (see License.txt)
* Web: http://blog.zakkemble.co.uk/nrf905-avrarduino-librarydriver/
*/

#ifndef NRF905_CONFIG_H_
#define NRF905_CONFIG_H_

// Crystal frequency (the one the radio module is using)
// NRF905_CLK_4MHZ
// NRF905_CLK_8MHZ
// NRF905_CLK_12MHZ
// NRF905_CLK_16MHZ
// NRF905_CLK_20MHZ
#define NRF905_CLK_FREQ NRF905_CLK_16MHZ

// Use pin interrupt for data ready (DR)
// NOTE: If you have other devices connected that use the SPI bus then you will need to wrap those bits of code in NRF905_NO_INTERRUPT() blocks
#define NRF905_INTERRUPTS 1

// If you want to use the NRF905_CB_ADDRMATCH and NRF905_CB_RXINVALID callbacks with interrupts then both NRF905_INTERRUPTS and NRF905_INTERRUPTS_AM need to be enabled
#define NRF905_INTERRUPTS_AM 1

// If other libraries communicate with SPI devices while inside an interrupt then set this to 1, otherwise you can set this to 0
// If you're not sure then leave this at 1
// If this is 1 then global interrupts will be turned off when this library uses the SPI bus
#define NRF905_INT_SPI_COMMS 1

// Use software to get data ready state instead of reading pin for high/low state, this means you don't need to connect to DR pin
// This option can only be used if NRF905_INTERRUPTS is 0
#define NRF905_DR_SW 0

// Use software to get address match state instead of reading pin for high/low state, this means you don't need to connect to AM pin
// This option can only be used if NRF905_INTERRUPTS_AM is 0
#define NRF905_AM_SW 0

// Don't transmit if airway is busy (other transmissions are going on)
// This feature uses the CD pin
#define NRF905_COLLISION_AVOID 1


///////////////////
// Default radio settings
///////////////////

// Frequency
// Channel 0 is 422.4MHz for the 433MHz band, each channel increments the frequency by 100KHz, so channel 10 would be 423.4MHz
// Channel 0 is 844.8MHz for the 868/915MHz band, each channel increments the frequency by 200KHz, so channel 10 would be 846.8MHz
// Max channel is 511 (473.5MHz / 947.0MHz)
#define NRF905_CHANNEL 10

// Frequency band
// 868 and 915 are actually the same thing
// NRF905_BAND_433
// NRF905_BAND_868
// NRF905_BAND_915
#define NRF905_BAND NRF905_BAND_433

// Output power
// n means negative, n10 = -10
// NRF905_PWR_n10 (-10dBm = 100uW)
// NRF905_PWR_n2 (-2dBm = 631uW)
// NRF905_PWR_6 (6dBm = 4mW)
// NRF905_PWR_10 (10dBm = 10mW)
#define NRF905_PWR NRF905_PWR_10

// Save a few mA by reducing receive sensitivity
// NRF905_LOW_RX_DISABLE (Normal sensitivity)
// NRF905_LOW_RX_ENABLE (Lower sensitivity)
#define NRF905_LOW_RX NRF905_LOW_RX_DISABLE

// Constantly retransmit payload while in transmit mode
// Can be useful in areas with lots of interference, but you'll need to make sure you can differentiate between re-transmitted packets and new packets (like an ID number).
// It will also block other transmissions if collision avoidance is enabled.
// NRF905_AUTO_RETRAN_DISABLE
// NRF905_AUTO_RETRAN_ENABLE
#define NRF905_AUTO_RETRAN NRF905_AUTO_RETRAN_DISABLE

// Output a clock signal on pin 3 of IC
// NRF905_OUTCLK_DISABLE
// NRF905_OUTCLK_500KHZ
// NRF905_OUTCLK_1MHZ
// NRF905_OUTCLK_2MHZ
// NRF905_OUTCLK_4MHZ
#define NRF905_OUTCLK NRF905_OUTCLK_DISABLE

// CRC checksum
// NRF905_CRC_DISABLE
// NRF905_CRC_8
// NRF905_CRC_16
#define NRF905_CRC NRF905_CRC_16

// Address size
// The address is actually the SYNC part of the packet, just after the preamble and before the data
// NRF905_ADDR_SIZE_1 (not recommended, a lot of false invalid packets will be received)
// NRF905_ADDR_SIZE_4
#define NRF905_ADDR_SIZE NRF905_ADDR_SIZE_4

// Payload size (1 - 32)
#define NRF905_PAYLOAD_SIZE 32 //NRF905_MAX_PAYLOAD


///////////////////
// Pin stuff
///////////////////

// Arduino pin assignments
/*
#define NRF905_TRX_EN 7 // Enable/standby pin (Required)
#define NRF905_PWR_MODE 8 // Power mode pin (Required)
#define NRF905_TX_EN 9 // TX / RX mode pin (Required)
#define NRF905_CD 4 // Carrier detect pin (Optional, used for collision avoidance if NRF905_COLLISION_AVOID is 1 or if you want to use the nRF905_airwayBusy() function)
#define NRF905_CSN 10 // SPI slave select pin (Required)

// Data ready pin
// If using interrupts (NRF905_INTERRUPTS 1) then this must be an interrupt pin
// If NRF905_INTERRUPTS is 0 and NRF905_DR_SW is 1 then this pin does not need to be connected
#define NRF905_DR 3

// Address match pin
// If using AM interrupt (NRF905_INTERRUPTS_AM 1) then this must be an interrupt pin
// If NRF905_INTERRUPT_AM is 0 and NRF905_AM_SW is 1 then this pin does not need to be connected
#define NRF905_AM 2
*/

//Piny ESP32 Wroom32
#define NRF905_TRX_EN 34 // Enable/standby pin (Required)
#define NRF905_PWR_MODE 11 // Power mode pin (Required)
#define NRF905_TX_EN 0 // TX / RX mode pin (Required)
#define NRF905_CD 6 // Carrier detect pin (Optional, used for collision avoidance if NRF905_COLLISION_AVOID is 1 or if you want to use the nRF905_airwayBusy() function)
#define NRF905_CSN SS // SPI slave select pin (Required)

// Data ready pin
// If using interrupts (NRF905_INTERRUPTS 1) then this must be an interrupt pin
// If NRF905_INTERRUPTS is 0 and NRF905_DR_SW is 1 then this pin does not need to be connected
#define NRF905_DR 7

// Address match pin
// If using AM interrupt (NRF905_INTERRUPTS_AM 1) then this must be an interrupt pin
// If NRF905_INTERRUPT_AM is 0 and NRF905_AM_SW is 1 then this pin does not need to be connected
#define NRF905_AM 27


// --------------------------------------
// Everything below here is for non-Arduino stuff
// --------------------------------------

// Enable/standby pin
#define NRF905_TRX_EN_PORT D
#define NRF905_TRX_EN_BIT 7

// Power mode pin
#define NRF905_PWR_MODE_PORT B
#define NRF905_PWR_MODE_BIT 0

// TX / RX mode pin
#define NRF905_TX_EN_PORT B
#define NRF905_TX_EN_BIT 1

// Carrier detect pin (Optional, used for collision avoidance if NRF905_COLLISION_AVOID is 1 or if you want to use the nRF905_airwayBusy() function)
#define NRF905_CD_PORT D
#define NRF905_CD_BIT 4

// Data ready pin
// If using interrupts (NRF905_INTERRUPTS 1) then this must be an external interrupt pin that matches the interrupt settings below.
// If NRF905_INTERRUPTS is 0 and NRF905_DR_SW is 1 then this pin does not need to be connected
#define NRF905_DR_PORT D
#define NRF905_DR_BIT 3

// Address match pin
// If using AM interrupt (NRF905_INTERRUPTS_AM 1) then this must be an external interrupt pin that matches the interrupt settings below.
// If NRF905_INTERRUPT_AM is 0 and NRF905_AM_SW is 1 then this pin does not need to be connected
#define NRF905_AM_PORT C
#define NRF905_AM_BIT 3

// SPI slave select pin
#define NRF905_CSN_PORT D
#define NRF905_CSN_BIT 6


///////////////////
// **************************** NOT for Arduino ****************************
// Interrupt register stuff
// Only needed if NRF905_INTERRUPTS or NRF905_INTERRUPTS_AM are 1
///////////////////

// Interrupt number (INT0, INT1 etc)
// This must match the INT that the DR pin is connected to
#define NRF905_INTERRUPT_NUM_DR 1

// Interrupt number
// This must match the INT that the AM pin is connected to
#define NRF905_INTERRUPT_NUM_AM 0



// Leave these commented out to let the library figure out what registers to use

// Which interrupt to use for data ready (DR)
//#define NRF905_REG_EXTERNAL_INT_DR EIMSK
//#define NRF905_BIT_EXTERNAL_INT_DR INT1
//#define NRF905_INT_VECTOR_DR INT1_vect

// Set interrupt to trigger on rising edge
//#define NRF905_REG_EXTERNAL_INT_CTL_DR EICRA
//#define NRF905_BIT_EXTERNAL_INT_CTL_DR (_BV(ISC11)|_BV(ISC10)) // Rising


// Which interrupt to use for address match (AM)
//#define NRF905_REG_EXTERNAL_INT_AM EIMSK
//#define NRF905_BIT_EXTERNAL_INT_AM INT0
//#define NRF905_INT_VECTOR_AM INT0_vect

// Set interrupt to trigger on any change
//#define NRF905_REG_EXTERNAL_INT_CTL_AM EICRA
//#define NRF905_BIT_EXTERNAL_INT_CTL_AM (_BV(ISC00)) // Any change



#define NRF905_CONCAT(a, b) a ## b
#define NRF905_INTCONCAT(num) NRF905_CONCAT(INT, num)

#ifndef NRF905_REG_EXTERNAL_INT_DR
#ifdef EIMSK
#define NRF905_REG_EXTERNAL_INT_DR EIMSK
#elif defined GICR
#define NRF905_REG_EXTERNAL_INT_DR GICR
#else
#define NRF905_REG_EXTERNAL_INT_DR GIMSK
#endif
#endif

#ifndef NRF905_BIT_EXTERNAL_INT_DR
#define NRF905_BIT_EXTERNAL_INT_DR NRF905_INTCONCAT(NRF905_INTERRUPT_NUM_DR)
#endif

#ifndef NRF905_REG_EXTERNAL_INT_AM
#ifdef EIMSK
#define NRF905_REG_EXTERNAL_INT_AM EIMSK
#elif defined GICR
#define NRF905_REG_EXTERNAL_INT_AM GICR
#else
#define NRF905_REG_EXTERNAL_INT_AM GIMSK
#endif
#endif

#ifndef NRF905_BIT_EXTERNAL_INT_AM
#define NRF905_BIT_EXTERNAL_INT_AM NRF905_INTCONCAT(NRF905_INTERRUPT_NUM_AM)
#endif

#endif /* NRF905_CONFIG_H_ */