diff --git a/Examples/LL/SPI/nRF24L01_Wireless/main.c b/Examples/LL/SPI/nRF24L01_Wireless/main.c index 2c6437c..3dbd91a 100644 --- a/Examples/LL/SPI/nRF24L01_Wireless/main.c +++ b/Examples/LL/SPI/nRF24L01_Wireless/main.c @@ -17,12 +17,20 @@ #include "py32f0xx_bsp_printf.h" #include "nrf24l01.h" -/* MODE_TX, MODE_RX, MODE_RX_INT */ +/* Mode options: MODE_TX, MODE_RX, MODE_RX_INT */ #define MODE_TX 0 #define MODE_TX_FAST 1 #define MODE_RX 2 #define MODE_RX_INT 3 -#define NRF24_MODE MODE_TX_FAST + +#define NRF24_MODE MODE_RX + +/* Payload width options: fixed or dynamic */ +#define PAYLOAD_WIDTH_MODE_FIXED 0 +#define PAYLOAD_WIDTH_MODE_DYNAMIC 1 + +#define NRF24_PAYLOAD_WIDTH_MODE PAYLOAD_WIDTH_MODE_DYNAMIC + #if (NRF24_MODE == MODE_TX || NRF24_MODE == MODE_TX_FAST) uint8_t payload[] = { @@ -66,13 +74,38 @@ int main(void) } printf("nRF24L01 check: succ\r\n"); +#if (NRF24_PAYLOAD_WIDTH_MODE == PAYLOAD_WIDTH_MODE_DYNAMIC) + NRF24L01_SetEnableDynamicPayloads(1); + NRF24L01_SetEnableAckPayload(1); +#endif + #if (NRF24_MODE == MODE_RX) + uint8_t pipe, length; printf("nRF24L01 in RX polling mode\r\n"); NRF24L01_RX_Mode(TX_ADDRESS, RX_ADDRESS); + NRF24L01_DumpConfig(); - while(1) + while (1) { - NRF24L01_RxPacket(RX_BUF); + if (NRF24L01_RXFIFO_GetStatus() != NRF24L01_RXFIFO_STATUS_EMPTY) + { +#if (NRF24_PAYLOAD_WIDTH_MODE == PAYLOAD_WIDTH_MODE_DYNAMIC) + pipe = NRF24L01_ReadPayload(RX_BUF, &length, 1); +#else + pipe = NRF24L01_ReadPayload(RX_BUF, &length, 0); +#endif + BSP_UART_TxString("P:"); + BSP_UART_TxHex8(pipe); + BSP_UART_TxString(",L:"); + BSP_UART_TxHex8(length); + BSP_UART_TxChar(':'); + for (int i = 0; i < length; i++) + { + BSP_UART_TxHex8(RX_BUF[i]); + } + BSP_UART_TxString("\r\n"); + NRF24L01_ClearIRQFlags(); + } } #elif (NRF24_MODE == MODE_RX_INT) @@ -83,18 +116,28 @@ int main(void) while(1); #elif (NRF24_MODE == MODE_TX) - + uint8_t length = 0; printf("nRF24L01 in TX mode\r\n"); NRF24L01_TX_Mode(RX_ADDRESS, TX_ADDRESS); NRF24L01_DumpConfig(); while(1) { - NRF24L01_TxPacket(payload, 32); - LL_mDelay(100); +#if (NRF24_PAYLOAD_WIDTH_MODE == PAYLOAD_WIDTH_MODE_DYNAMIC) + length++; +#else + length = NRF24L01_PLOAD_WIDTH; +#endif + NRF24L01_TxPacket(payload, length); + if (length == 32) + { + length = 0; + } + LL_mDelay(200); } #elif (NRF24_MODE == MODE_TX_FAST) + uint8_t length = 0; printf("nRF24L01 in fast TX mode\r\n"); NRF24L01_TX_Mode(RX_ADDRESS, TX_ADDRESS); NRF24L01_DumpConfig(); @@ -102,7 +145,12 @@ int main(void) uint8_t succ = 0, err = 0; while (1) { - if (NRF24L01_TxFast(payload) != 0) +#if (NRF24_PAYLOAD_WIDTH_MODE == PAYLOAD_WIDTH_MODE_DYNAMIC) + length++; +#else + length = NRF24L01_PLOAD_WIDTH; +#endif + if (NRF24L01_TxFast(payload, length) != 0) { NRF24L01_ResetTX(); err++; @@ -117,7 +165,11 @@ int main(void) err = 0; succ = 0; } - LL_mDelay(5); + if (length == 32) + { + length = 0; + } + LL_mDelay(50); } #endif @@ -126,9 +178,25 @@ int main(void) #if (NRF24_MODE == MODE_RX_INT) void EXTI4_15_IRQHandler(void) { + uint8_t pipe, length; if(LL_EXTI_IsActiveFlag(LL_EXTI_LINE_4)) { - NRF24L01_IntRxPacket(RX_BUF); +#if (NRF24_PAYLOAD_WIDTH_MODE == PAYLOAD_WIDTH_MODE_DYNAMIC) + pipe = NRF24L01_ReadPayload(RX_BUF, &length, 1); +#else + pipe = NRF24L01_ReadPayload(RX_BUF, &length, 0); +#endif + BSP_UART_TxString("P:"); + BSP_UART_TxHex8(pipe); + BSP_UART_TxString(",L:"); + BSP_UART_TxHex8(length); + BSP_UART_TxChar(':'); + for (int i = 0; i < length; i++) + { + BSP_UART_TxHex8(RX_BUF[i]); + } + BSP_UART_TxString("\r\n"); + NRF24L01_ClearIRQFlags(); LL_EXTI_ClearFlag(LL_EXTI_LINE_4); } } diff --git a/Examples/LL/SPI/nRF24L01_Wireless/nrf24l01.c b/Examples/LL/SPI/nRF24L01_Wireless/nrf24l01.c index fecf356..7ffa5ca 100644 --- a/Examples/LL/SPI/nRF24L01_Wireless/nrf24l01.c +++ b/Examples/LL/SPI/nRF24L01_Wireless/nrf24l01.c @@ -31,12 +31,11 @@ uint8_t NRF24L01_Write_Reg(uint8_t reg, uint8_t value) { uint8_t status; CSN_LOW; - if (reg < NRF24L01_CMD_REGISTER_W) + if (reg < NRF24L01_CMD_W_REGISTER) { // This is a register access - status = SPI_TxRxByte(NRF24L01_CMD_REGISTER_W | (reg & NRF24L01_MASK_REG_MAP)); + status = SPI_TxRxByte(NRF24L01_CMD_W_REGISTER | (reg & NRF24L01_MASK_REG_MAP)); SPI_TxRxByte(value); - } else { @@ -98,8 +97,8 @@ uint8_t NRF24L01_Check(void) uint8_t *ptr = (uint8_t *)NRF24L01_TEST_ADDR; // Write test TX address and read TX_ADDR register - NRF24L01_Write_From_Buf(NRF24L01_CMD_REGISTER_W | NRF24L01_REG_TX_ADDR, ptr, 5); - NRF24L01_Read_To_Buf(NRF24L01_CMD_REGISTER_R | NRF24L01_REG_TX_ADDR, rxbuf, 5); + NRF24L01_Write_From_Buf(NRF24L01_CMD_W_REGISTER | NRF24L01_REG_TX_ADDR, ptr, 5); + NRF24L01_Read_To_Buf(NRF24L01_CMD_R_REGISTER | NRF24L01_REG_TX_ADDR, rxbuf, 5); // Compare buffers, return error on first mismatch for (i = 0; i < 5; i++) @@ -127,7 +126,7 @@ void NRF24L01_FlushTX(void) void NRF24L01_ResetTX(void) { - NRF24L01_Write_Reg(NRF24L01_CMD_REGISTER_W + NRF24L01_REG_STATUS, NRF24L01_FLAG_MAX_RT); // Clear max retry flag + NRF24L01_Write_Reg(NRF24L01_REG_STATUS, NRF24L01_FLAG_MAX_RT); // Clear max retry flag CE_LOW; CE_HIGH; } @@ -138,14 +137,16 @@ void NRF24L01_ResetTX(void) * NRF24L01_FLAG_TX_DSENT * NRF24L01_FLAG_MAX_RT */ -void NRF24L01_ClearIRQFlag(uint8_t reg) { - NRF24L01_Write_Reg(NRF24L01_CMD_REGISTER_W + NRF24L01_REG_STATUS, reg); +void NRF24L01_ClearIRQFlag(uint8_t reg) +{ + NRF24L01_Write_Reg(NRF24L01_REG_STATUS, reg); } /** * Clear RX_DR, TX_DS and MAX_RT bits of the STATUS register */ -void NRF24L01_ClearIRQFlags(void) { +void NRF24L01_ClearIRQFlags(void) +{ uint8_t reg; reg = NRF24L01_Read_Reg(NRF24L01_REG_STATUS); reg |= NRF24L01_MASK_STATUS_IRQ; @@ -158,21 +159,21 @@ void NRF24L01_ClearIRQFlags(void) { void _NRF24L01_Config(uint8_t *tx_addr) { // TX Address - NRF24L01_Write_From_Buf(NRF24L01_CMD_REGISTER_W + NRF24L01_REG_TX_ADDR, tx_addr, NRF24L01_ADDR_WIDTH); + NRF24L01_Write_From_Buf(NRF24L01_CMD_W_REGISTER + NRF24L01_REG_TX_ADDR, tx_addr, NRF24L01_ADDR_WIDTH); // RX P0 Payload Width - NRF24L01_Write_Reg(NRF24L01_CMD_REGISTER_W + NRF24L01_REG_RX_PW_P0, NRF24L01_PLOAD_WIDTH); + NRF24L01_Write_Reg(NRF24L01_REG_RX_PW_P0, NRF24L01_PLOAD_WIDTH); // Enable Auto ACK - NRF24L01_Write_Reg(NRF24L01_CMD_REGISTER_W + NRF24L01_REG_EN_AA, 0x3f); + NRF24L01_Write_Reg(NRF24L01_REG_EN_AA, 0x3f); // Enable RX channels - NRF24L01_Write_Reg(NRF24L01_CMD_REGISTER_W + NRF24L01_REG_EN_RXADDR, 0x3f); + NRF24L01_Write_Reg(NRF24L01_REG_EN_RXADDR, 0x3f); // RF channel: 2.400G + 0.001 * x - NRF24L01_Write_Reg(NRF24L01_CMD_REGISTER_W + NRF24L01_REG_RF_CH, 40); - // 000+0+[0:1Mbps,1:2Mbps]+[00:-18dbm,01:-12dbm,10:-6dbm,11:0dbm]+[0:LNA_OFF,1:LNA_ON] + NRF24L01_Write_Reg(NRF24L01_REG_RF_CH, 40); + // Format: 000+0+[0:1Mbps,1:2Mbps]+[00:-18dbm,01:-12dbm,10:-6dbm,11:0dbm]+[0:LNA_OFF,1:LNA_ON] // 01:1Mbps,-18dbm; 03:1Mbps,-12dbm; 05:1Mbps,-6dbm; 07:1Mbps,0dBm // 09:2Mbps,-18dbm; 0b:2Mbps,-12dbm; 0d:2Mbps,-6dbm; 0f:2Mbps,0dBm, - NRF24L01_Write_Reg(NRF24L01_CMD_REGISTER_W + NRF24L01_REG_RF_SETUP, 0x03); + NRF24L01_Write_Reg(NRF24L01_REG_RF_SETUP, 0x03); // 0A:delay=250us,count=10, 1A:delay=500us,count=10 - NRF24L01_Write_Reg(NRF24L01_CMD_REGISTER_W + NRF24L01_REG_SETUP_RETR, 0x0a); + NRF24L01_Write_Reg(NRF24L01_REG_SETUP_RETR, 0x0a); } /** @@ -183,7 +184,7 @@ void NRF24L01_RX_Mode(uint8_t *rx_addr, uint8_t *tx_addr) CE_LOW; _NRF24L01_Config(tx_addr); // RX Address of P0 - NRF24L01_Write_From_Buf(NRF24L01_CMD_REGISTER_W + NRF24L01_REG_RX_ADDR_P0, rx_addr, NRF24L01_ADDR_WIDTH); + NRF24L01_Write_From_Buf(NRF24L01_CMD_W_REGISTER + NRF24L01_REG_RX_ADDR_P0, rx_addr, NRF24L01_ADDR_WIDTH); /** REG 0x00: 0)PRIM_RX 0:TX 1:RX @@ -195,7 +196,7 @@ void NRF24L01_RX_Mode(uint8_t *rx_addr, uint8_t *tx_addr) 6)MASK_RX_DR 0:IRQ low 1:NO IRQ 7)Reserved 0 */ - NRF24L01_Write_Reg(NRF24L01_CMD_REGISTER_W + NRF24L01_REG_CONFIG, 0x0f); //RX,PWR_UP,CRC16,EN_CRC + NRF24L01_Write_Reg(NRF24L01_REG_CONFIG, 0x0f); //RX,PWR_UP,CRC16,EN_CRC CE_HIGH; NRF24L01_FlushRX(); } @@ -209,62 +210,61 @@ void NRF24L01_TX_Mode(uint8_t *rx_addr, uint8_t *tx_addr) _NRF24L01_Config(tx_addr); // On the PTX the **TX_ADDR** must be the same as the **RX_ADDR_P0** and as the pipe address for the designated pipe // RX_ADDR_P0 will be used for receiving ACK - NRF24L01_Write_From_Buf(NRF24L01_CMD_REGISTER_W + NRF24L01_REG_RX_ADDR_P0, tx_addr, NRF24L01_ADDR_WIDTH); - NRF24L01_Write_Reg(NRF24L01_CMD_REGISTER_W + NRF24L01_REG_CONFIG, 0x0e); //TX,PWR_UP,CRC16,EN_CRC + NRF24L01_Write_From_Buf(NRF24L01_CMD_W_REGISTER + NRF24L01_REG_RX_ADDR_P0, tx_addr, NRF24L01_ADDR_WIDTH); + NRF24L01_Write_Reg(NRF24L01_REG_CONFIG, 0x0e); //TX,PWR_UP,CRC16,EN_CRC CE_HIGH; } -/** -* Hold till data received and written to rx_buf -*/ -uint8_t NRF24L01_RxPacket(uint8_t *rx_buf) +uint8_t NRF24L01_RX_GetPayloadWidth(void) { - uint8_t status, result = 0; - while(IRQ); - CE_LOW; - status = NRF24L01_Read_Reg(NRF24L01_REG_STATUS); - BSP_UART_TxHex8(status); - BSP_UART_TxChar(':'); - - if(status & NRF24L01_FLAG_RX_DR) - { - NRF24L01_Read_To_Buf(NRF24L01_CMD_RX_PLOAD_R, rx_buf, NRF24L01_PLOAD_WIDTH); - for (int i = 0; i < 32; i++) - { - BSP_UART_TxHex8(RX_BUF[i]); - } - BSP_UART_TxString("\r\n"); - result = 1; - NRF24L01_ClearIRQFlag(NRF24L01_FLAG_RX_DR); - } - CE_HIGH; - return result; + uint8_t value; + CSN_LOW; + value = NRF24L01_Read_Reg(NRF24L01_CMD_R_RX_PL_WID); + CSN_HIGH; + return value; } -/** -* Read in interrupt -*/ -void NRF24L01_IntRxPacket(uint8_t *rx_buf) +uint8_t NRF24L01_RXFIFO_GetStatus(void) { - uint8_t status; - CE_LOW; - status = NRF24L01_Read_Reg(NRF24L01_REG_STATUS); - BSP_UART_TxHex8(status); - BSP_UART_TxChar(':'); + uint8_t reg = NRF24L01_Read_Reg(NRF24L01_REG_FIFO_STATUS); + return (reg & NRF24L01_MASK_RXFIFO); +} - if(status & NRF24L01_FLAG_RX_DR) +uint8_t NRF24L01_ReadPayload(uint8_t *pBuf, uint8_t *length, uint8_t dpl) +{ + uint8_t status, pipe; + + // Extract a payload pipe number from the STATUS register + status = NRF24L01_Read_Reg(NRF24L01_REG_STATUS); + pipe = (status & NRF24L01_MASK_RX_P_NO) >> 1; + // RX FIFO empty? + if (pipe < 6) { - NRF24L01_Read_To_Buf(NRF24L01_CMD_RX_PLOAD_R, rx_buf, NRF24L01_PLOAD_WIDTH); - for (int i = 0; i < 32; i++) + if (dpl) { - BSP_UART_TxHex8(RX_BUF[i]); + // Get payload width + *length = NRF24L01_RX_GetPayloadWidth(); + if (*length > 32) + { + // Error + *length = 0; + NRF24L01_FlushRX(); + } } - BSP_UART_TxString("\r\n"); - NRF24L01_ClearIRQFlag(NRF24L01_FLAG_RX_DR); + else + { + *length = NRF24L01_Read_Reg(NRF24L01_REG_RX_PW_P0 + pipe); + } + // Read a payload from the RX FIFO + if (*length) + { + NRF24L01_Read_To_Buf(NRF24L01_CMD_R_RX_PAYLOAD, pBuf, *length); + } + return pipe; } - status |= NRF24L01_MASK_STATUS_IRQ; - NRF24L01_Write_Reg(NRF24L01_REG_STATUS, status); - CE_HIGH; + // pipe value = 110: Not Used, 111: RX FIFO Empty + *length = 0; + return pipe; } /** @@ -275,7 +275,7 @@ uint8_t NRF24L01_TxPacket(uint8_t *tx_buf, uint8_t len) uint8_t status = 0x00; CE_LOW; len = len > NRF24L01_PLOAD_WIDTH? NRF24L01_PLOAD_WIDTH : len; - NRF24L01_Write_From_Buf(NRF24L01_CMD_TX_PLOAD_W, tx_buf, len); + NRF24L01_Write_From_Buf(NRF24L01_CMD_W_TX_PAYLOAD, tx_buf, len); CE_HIGH; while(IRQ != 0); // Waiting send finish @@ -302,13 +302,13 @@ uint8_t NRF24L01_TxPacket(uint8_t *tx_buf, uint8_t len) return status; } -void NRF24L01_TxPacketFast(const void *txbuf) +void NRF24L01_TxPacketFast(const void *pBuf, uint8_t len) { - NRF24L01_Write_From_Buf(NRF24L01_CMD_TX_PLOAD_W, txbuf, NRF24L01_PLOAD_WIDTH); + NRF24L01_Write_From_Buf(NRF24L01_CMD_W_TX_PAYLOAD, pBuf, len); CE_HIGH; } -uint8_t NRF24L01_TxFast(const void *txbuf) +uint8_t NRF24L01_TxFast(const void *pBuf, uint8_t len) { uint8_t status; // Blocking only if FIFO is full. This will loop and block until TX is successful or fail @@ -321,10 +321,82 @@ uint8_t NRF24L01_TxFast(const void *txbuf) } } while (status & NRF24L01_FLAG_TX_FULL); - NRF24L01_TxPacketFast(txbuf); + NRF24L01_TxPacketFast(pBuf, len); return 0; } +void NRF24L01_ToggleFeatures(void) +{ + CSN_LOW; + NRF24L01_Write_Reg(NRF24L01_CMD_ACTIVATE, 0x73); + CSN_HIGH; +} + +void NRF24L01_SetEnableDynamicPayloads(uint8_t mode) +{ + uint8_t reg = NRF24L01_Read_Reg(NRF24L01_REG_FEATURE); + if (mode == 0) + { + // Disable dynamic payload throughout the system + NRF24L01_Write_Reg(NRF24L01_REG_FEATURE, reg & (~NRF24L01_FEATURE_EN_DPL)); + // If it didn't work, the features are not enabled + reg = NRF24L01_Read_Reg(NRF24L01_REG_FEATURE); + if ((reg & NRF24L01_FEATURE_EN_DPL) != 0) + { + // Enable them and try again + NRF24L01_ToggleFeatures(); + NRF24L01_Write_Reg(NRF24L01_REG_FEATURE, reg & (~NRF24L01_FEATURE_EN_DPL)); + } + // Disable dynamic payload on all pipes + NRF24L01_Write_Reg(NRF24L01_REG_DYNPD, 0); + } + else + { + NRF24L01_Write_Reg(NRF24L01_REG_FEATURE, reg | NRF24L01_FEATURE_EN_DPL); + reg = NRF24L01_Read_Reg(NRF24L01_REG_FEATURE); + if ((reg & NRF24L01_FEATURE_EN_DPL) != NRF24L01_FEATURE_EN_DPL) + { + NRF24L01_ToggleFeatures(); + NRF24L01_Write_Reg(NRF24L01_REG_FEATURE, reg | NRF24L01_FEATURE_EN_DPL); + } + // Enable dynamic payload on all pipes + NRF24L01_Write_Reg(NRF24L01_REG_DYNPD, NRF24L01_DYNPD_DPL_P0 | NRF24L01_DYNPD_DPL_P1 + | NRF24L01_DYNPD_DPL_P2 | NRF24L01_DYNPD_DPL_P3 | NRF24L01_DYNPD_DPL_P4 | NRF24L01_DYNPD_DPL_P5); + } + +} + +void NRF24L01_SetEnableAckPayload(uint8_t mode) +{ + uint8_t reg = NRF24L01_Read_Reg(NRF24L01_REG_FEATURE); + if (mode == 0) + { + // Disable ack payload and dynamic payload features + NRF24L01_Write_Reg(NRF24L01_REG_FEATURE, reg &(~NRF24L01_FEATURE_EN_ACK_PAY)); + // If it didn't work, the features are not enabled + reg = NRF24L01_Read_Reg(NRF24L01_REG_FEATURE); + if ((reg & NRF24L01_FEATURE_EN_ACK_PAY) != NRF24L01_FEATURE_EN_ACK_PAY) + { + // Enable them and try again + NRF24L01_ToggleFeatures(); + NRF24L01_Write_Reg(NRF24L01_REG_FEATURE, reg &(~NRF24L01_FEATURE_EN_ACK_PAY)); + } + } + else + { + NRF24L01_Write_Reg(NRF24L01_REG_FEATURE, reg | NRF24L01_FEATURE_EN_ACK_PAY); + reg = NRF24L01_Read_Reg(NRF24L01_REG_FEATURE); + if ((reg & NRF24L01_FEATURE_EN_ACK_PAY) != NRF24L01_FEATURE_EN_ACK_PAY) + { + NRF24L01_ToggleFeatures(); + NRF24L01_Write_Reg(NRF24L01_REG_FEATURE, reg | NRF24L01_FEATURE_EN_ACK_PAY); + } + // Enable dynamic payload on pipes 0 & 1 + reg = NRF24L01_Read_Reg(NRF24L01_REG_DYNPD); + NRF24L01_Write_Reg(NRF24L01_REG_DYNPD, reg | NRF24L01_DYNPD_DPL_P0 | NRF24L01_DYNPD_DPL_P1); + } +} + /** * Dump nRF24L01 configuration */ @@ -502,4 +574,16 @@ void NRF24L01_DumpConfig(void) { // RX_PW_P5 i = NRF24L01_Read_Reg(NRF24L01_REG_RX_PW_P5); printf("[0x%02X] RX_PW_P5=%u\r\n",NRF24L01_REG_RX_PW_P5,i); + + // NRF24L01_REG_FIFO_STATUS + i = NRF24L01_Read_Reg(NRF24L01_REG_FIFO_STATUS); + printf("[0x%02X] FIFO_STATUS=0x%02x\r\n",NRF24L01_REG_FIFO_STATUS,i); + + // NRF24L01_REG_DYNPD + i = NRF24L01_Read_Reg(NRF24L01_REG_DYNPD); + printf("[0x%02X] DYNPD=0x%02x\r\n",NRF24L01_REG_DYNPD,i); + + // NRF24L01_REG_FEATURE + i = NRF24L01_Read_Reg(NRF24L01_REG_FEATURE); + printf("[0x%02X] FEATURE=0x%02x\r\n",NRF24L01_REG_FEATURE,i); } diff --git a/Examples/LL/SPI/nRF24L01_Wireless/nrf24l01.h b/Examples/LL/SPI/nRF24L01_Wireless/nrf24l01.h index 316d9b3..ad3b50c 100644 --- a/Examples/LL/SPI/nRF24L01_Wireless/nrf24l01.h +++ b/Examples/LL/SPI/nRF24L01_Wireless/nrf24l01.h @@ -11,14 +11,21 @@ #define IRQ READ_BIT(GPIOA->IDR, LL_GPIO_PIN_4) // SPI(nRF24L01) commands -#define NRF24L01_CMD_REGISTER_R 0x00 // Register read -#define NRF24L01_CMD_REGISTER_W 0x20 // Register write +#define NRF24L01_CMD_R_REGISTER 0x00 // Register read +#define NRF24L01_CMD_W_REGISTER 0x20 // Register write +/** + * ACTIVATE. For NRF24L01 only, removed from NRF24L01+ product specs + * - https://github.com/nRF24/RF24/issues/401 + * + * This write command followed by data 0x73 activates the following features: R_RX_PL_WID, W_ACK_PAYLOAD, W_TX_PAYLOAD_NOACK. + * A new ACTIVATE command with the same data deactivates them again. This is executable in power down or stand by modes only. +*/ #define NRF24L01_CMD_ACTIVATE 0x50 // (De)Activates R_RX_PL_WID, W_ACK_PAYLOAD, W_TX_PAYLOAD_NOACK features -#define NRF24L01_CMD_RX_PLOAD_WID_R 0x60 // Read RX-payload width for the top R_RX_PAYLOAD in the RX FIFO. -#define NRF24L01_CMD_RX_PLOAD_R 0x61 // Read RX payload -#define NRF24L01_CMD_TX_PLOAD_W 0xA0 // Write TX payload -#define NRF24L01_CMD_ACK_PAYLOAD_W 0xA8 // Write ACK payload -#define NRF24L01_CMD_TX_PAYLOAD_NOACK_W 0xB0 //Write TX payload and disable AUTOACK +#define NRF24L01_CMD_R_RX_PL_WID 0x60 // Read RX-payload width for the top R_RX_PAYLOAD in the RX FIFO. Flush RX FIFO if the read value is larger than 32 bytes +#define NRF24L01_CMD_R_RX_PAYLOAD 0x61 // Read RX payload +#define NRF24L01_CMD_W_TX_PAYLOAD 0xA0 // Write TX payload +#define NRF24L01_CMD_W_ACK_PAYLOAD 0xA8 // 1010 1PPP, Used in RX mode. Write Payload to be transmitted together with ACK packet on PIPE PPP. (PPP valid in the range from 000 to 101) +#define NRF24L01_CMD_W_TX_PAYLOAD_NOACK 0xB0 // Used in TX mode. Disables AUTOACK on this specific packet #define NRF24L01_CMD_FLUSH_TX 0xE1 // Flush TX FIFO #define NRF24L01_CMD_FLUSH_RX 0xE2 // Flush RX FIFO #define NRF24L01_CMD_REUSE_TX_PL 0xE3 // Reuse TX payload @@ -56,17 +63,42 @@ // Register bits definitions #define NRF24L01_CONFIG_PRIM_RX 0x01 // PRIM_RX bit in CONFIG register #define NRF24L01_CONFIG_PWR_UP 0x02 // PWR_UP bit in CONFIG register + +// Enable dynamic payload length on data pipes +#define NRF24L01_DYNPD_DPL_P5 0x20 +#define NRF24L01_DYNPD_DPL_P4 0x10 +#define NRF24L01_DYNPD_DPL_P3 0x08 +#define NRF24L01_DYNPD_DPL_P2 0x04 +#define NRF24L01_DYNPD_DPL_P1 0x02 +#define NRF24L01_DYNPD_DPL_P0 0x01 + +/** + * EN_DYN_ACK - this bit enables the W_TX_PAYLOAD_NOACK command + * + * The PTX can set the NO_ACK flag bit in the Packet Control Field with this command: W_TX_PAYLOAD_NOACK + * However, the function must first be enabled in the FEATURE register by setting the EN_DYN_ACK bit. + * When you use this option the PTX goes directly to standby-I mode after transmitting the packet. The PRX + * does not transmit an ACK packet when it receives the packet. +*/ #define NRF24L01_FEATURE_EN_DYN_ACK 0x01 // EN_DYN_ACK bit in FEATURE register +/** + * EN_ACK_PAY - Enables Payload with ACK + * If ACK packet payload is activated, ACK packets have dynamic payload lengths and the Dynamic Payload + * Length feature should be enabled for pipe 0 on the PTX and PRX. This is to ensure that they receive the + * ACK packets with payloads. If the ACK payload is more than 15 byte in 2Mbps mode the ARD must be + * 500µS or more, and if the ACK payload is more than 5 byte in 1Mbps mode the ARD must be 500µS or + * more. In 250kbps mode (even when the payload is not in ACK) the ARD must be 500µS or more. +*/ #define NRF24L01_FEATURE_EN_ACK_PAY 0x02 // EN_ACK_PAY bit in FEATURE register -#define NRF24L01_FEATURE_EN_DPL 0x04 // EN_DPL bit in FEATURE register +#define NRF24L01_FEATURE_EN_DPL 0x04 // EN_DPL bit in FEATURE register, enables Dynamic Payload Length + +// Status Flags #define NRF24L01_FLAG_RX_DR 0x40 // RX_DR bit (data ready RX FIFO interrupt) #define NRF24L01_FLAG_TX_DS 0x20 // TX_DS bit (data sent TX FIFO interrupt) #define NRF24L01_FLAG_MAX_RT 0x10 // MAX_RT bit (maximum number of TX re-transmits interrupt) #define NRF24L01_FLAG_IT_BITS 0x70 // RX_DR|TX_DS|MAX_RT #define NRF24L01_FLAG_TX_FULL 0x01 // TX FIFO full flag. 1: TX FIFO full. 0: Available locations in TX FIFO - - // Register masks definitions #define NRF24L01_MASK_REG_MAP 0x1F // Mask bits[4:0] for CMD_RREG and CMD_WREG commands #define NRF24L01_MASK_CRC 0x0C // Mask for CRC bits [3:2] in CONFIG register @@ -86,6 +118,11 @@ // Register masks definitions #define NRF24L01_MASK_REG_MAP 0x1F // Mask bits[4:0] for CMD_RREG and CMD_WREG commands +// RXFIFO status +#define NRF24L01_RXFIFO_STATUS_DATA 0x00 // The RX FIFO contains data and available locations +#define NRF24L01_RXFIFO_STATUS_EMPTY 0x01 // The RX FIFO is empty +#define NRF24L01_RXFIFO_STATUS_FULL 0x02 // The RX FIFO is full +#define NRF24L01_RXFIFO_STATUS_ERROR 0x03 // Impossible state: RX FIFO cannot be empty and full at the same time #define NRF24L01_ADDR_WIDTH 5 // RX/TX address width #define NRF24L01_PLOAD_WIDTH 32 // Payload width @@ -126,15 +163,19 @@ uint8_t NRF24L01_Read_To_Buf(uint8_t reg,uint8_t *pBuf,uint8_t len); */ uint8_t NRF24L01_Write_From_Buf(uint8_t reg, const uint8_t *pBuf,uint8_t len); -/** -* Hold till data received and written to rx_buf -*/ -uint8_t NRF24L01_RxPacket(uint8_t *rx_buf); +void NRF24L01_SetEnableDynamicPayloads(uint8_t mode); + +void NRF24L01_SetEnableAckPayload(uint8_t mode); /** - * Receive data in interrupt + * Get status of the RX FIFO */ -void NRF24L01_IntRxPacket(uint8_t *rx_buf); +uint8_t NRF24L01_RXFIFO_GetStatus(void); + +/** + * Read received data (no fifo status check, no status clear, just read) +*/ +uint8_t NRF24L01_ReadPayload(uint8_t *pBuf, uint8_t *length, uint8_t dpl); /** * Send data in tx_buf and wait till data is sent or max re-tr reached @@ -144,7 +185,7 @@ uint8_t NRF24L01_TxPacket(uint8_t *tx_buf, uint8_t len); /** * Send data in FIFO without sync ack */ -uint8_t NRF24L01_TxFast(const void *txbuf); +uint8_t NRF24L01_TxFast(const void *pBuf, uint8_t len); /** * Switch NRF24L01 to RX mode