Merge pull request #11297 from SteveCEvans/baro_state
[betaflight.git] / src / main / drivers / rx / rx_nrf24l01.c
blob0e85d814de88187bdfb510d56f5b917066aed699
1 /*
2 * This file is part of Cleanflight and Betaflight.
4 * Cleanflight and Betaflight are free software. You can redistribute
5 * this software and/or modify this software under the terms of the
6 * GNU General Public License as published by the Free Software
7 * Foundation, either version 3 of the License, or (at your option)
8 * any later version.
10 * Cleanflight and Betaflight are distributed in the hope that they
11 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 * See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this software.
18 * If not, see <http://www.gnu.org/licenses/>.
21 // This file is copied with modifications from project Deviation,
22 // see http://deviationtx.com
24 #include <stdbool.h>
25 #include <stdint.h>
26 #include <stdlib.h>
28 #include "platform.h"
30 #ifdef USE_RX_NRF24
32 #include "build/build_config.h"
34 #include "pg/rx.h"
36 #include "drivers/bus_spi.h"
37 #include "drivers/io.h"
38 #include "drivers/io_impl.h"
39 #include "drivers/rx/rx_spi.h"
40 #include "drivers/time.h"
42 #include "rx_nrf24l01.h"
44 #define NRF24_CE_HI() {IOHi(DEFIO_IO(RX_CE_PIN));}
45 #define NRF24_CE_LO() {IOLo(DEFIO_IO(RX_CE_PIN));}
47 // Instruction Mnemonics
48 // nRF24L01: Table 16. Command set for the nRF24L01 SPI. Product Specification, p46
49 // nRF24L01+: Table 20. Command set for the nRF24L01+ SPI. Product Specification, p51
50 #define R_REGISTER 0x00
51 #define W_REGISTER 0x20
52 #define REGISTER_MASK 0x1F
53 #define ACTIVATE 0x50
54 #define R_RX_PL_WID 0x60
55 #define R_RX_PAYLOAD 0x61
56 #define W_TX_PAYLOAD 0xA0
57 #define W_ACK_PAYLOAD 0xA8
58 #define FLUSH_TX 0xE1
59 #define FLUSH_RX 0xE2
60 #define REUSE_TX_PL 0xE3
61 #define NOP 0xFF
63 static void NRF24L01_InitGpio(void)
65 // CE as OUTPUT
66 const SPIDevice rxSPIDevice = spiDeviceByInstance(RX_SPI_INSTANCE);
67 IOInit(DEFIO_IO(RX_CE_PIN), OWNER_RX_SPI_CS, rxSPIDevice + 1);
68 IOConfigGPIO(DEFIO_IO(RX_CE_PIN), SPI_IO_CS_CFG);
69 NRF24_CE_LO();
72 void NRF24L01_WriteReg(uint8_t reg, uint8_t data)
74 rxSpiWriteCommand(W_REGISTER | (REGISTER_MASK & reg), data);
77 void NRF24L01_WriteRegisterMulti(uint8_t reg, const uint8_t *data, uint8_t length)
79 rxSpiWriteCommandMulti(W_REGISTER | ( REGISTER_MASK & reg), data, length);
83 * Transfer the payload to the nRF24L01 TX FIFO
84 * Packets in the TX FIFO are transmitted when the
85 * nRF24L01 next enters TX mode
87 void NRF24L01_WritePayload(const uint8_t *data, uint8_t length)
89 rxSpiWriteCommandMulti(W_TX_PAYLOAD, data, length);
92 void NRF24L01_WriteAckPayload(const uint8_t *data, uint8_t length, uint8_t pipe)
94 rxSpiWriteCommandMulti(W_ACK_PAYLOAD | (pipe & 0x07), data, length);
97 uint8_t NRF24L01_ReadReg(uint8_t reg)
99 return rxSpiReadCommand(R_REGISTER | (REGISTER_MASK & reg), NOP);
102 void NRF24L01_ReadRegisterMulti(uint8_t reg, uint8_t *data, uint8_t length)
104 rxSpiReadCommandMulti(R_REGISTER | (REGISTER_MASK & reg), NOP, data, length);
108 * Read a packet from the nRF24L01 RX FIFO.
110 void NRF24L01_ReadPayload(uint8_t *data, uint8_t length)
112 rxSpiReadCommandMulti(R_RX_PAYLOAD, NOP, data, length);
116 * Empty the transmit FIFO buffer.
118 void NRF24L01_FlushTx(void)
120 rxSpiWriteByte(FLUSH_TX);
124 * Empty the receive FIFO buffer.
126 void NRF24L01_FlushRx(void)
128 rxSpiWriteByte(FLUSH_RX);
131 void NRF24L01_Activate(uint8_t code)
133 rxSpiWriteCommand(ACTIVATE, code);
136 // standby configuration, used to simplify switching between RX, TX, and Standby modes
137 static uint8_t standbyConfig;
139 void NRF24L01_Initialize(uint8_t baseConfig)
141 standbyConfig = BIT(NRF24L01_00_CONFIG_PWR_UP) | baseConfig;
142 NRF24L01_InitGpio();
143 // nRF24L01+ needs 100 milliseconds settling time from PowerOnReset to PowerDown mode
144 static const uint32_t settlingTimeUs = 100000;
145 const uint32_t currentTimeUs = micros();
146 if (currentTimeUs < settlingTimeUs) {
147 delayMicroseconds(settlingTimeUs - currentTimeUs);
149 // now in PowerDown mode
150 NRF24L01_WriteReg(NRF24L01_00_CONFIG, standbyConfig); // set PWR_UP to enter Standby mode
151 // nRF24L01+ needs 4500 microseconds from PowerDown mode to Standby mode, for crystal oscillator startup
152 delayMicroseconds(4500);
153 // now in Standby mode
157 * Common setup of registers
159 void NRF24L01_SetupBasic(void)
161 NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No auto acknowledgment
162 NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, BIT(NRF24L01_02_EN_RXADDR_ERX_P0));
163 NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, NRF24L01_03_SETUP_AW_5BYTES); // 5-byte RX/TX address
164 NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x00); // Disable dynamic payload length on all pipes
168 * Enter standby mode
170 void NRF24L01_SetStandbyMode(void)
172 // set CE low and clear the PRIM_RX bit to enter standby mode
173 NRF24_CE_LO();
174 NRF24L01_WriteReg(NRF24L01_00_CONFIG, standbyConfig);
178 * Enter receive mode
180 void NRF24L01_SetRxMode(void)
182 NRF24_CE_LO(); // drop into standby mode
183 // set the PRIM_RX bit
184 NRF24L01_WriteReg(NRF24L01_00_CONFIG, standbyConfig | BIT(NRF24L01_00_CONFIG_PRIM_RX));
185 NRF24L01_ClearAllInterrupts();
186 // finally set CE high to start enter RX mode
187 NRF24_CE_HI();
188 // nRF24L01+ will now transition from Standby mode to RX mode after 130 microseconds settling time
192 * Enter transmit mode. Anything in the transmit FIFO will be transmitted.
194 void NRF24L01_SetTxMode(void)
196 // Ensure in standby mode, since can only enter TX mode from standby mode
197 NRF24L01_SetStandbyMode();
198 NRF24L01_ClearAllInterrupts();
199 // pulse CE for 10 microseconds to enter TX mode
200 NRF24_CE_HI();
201 delayMicroseconds(10);
202 NRF24_CE_LO();
203 // nRF24L01+ will now transition from Standby mode to TX mode after 130 microseconds settling time.
204 // Transmission will then begin and continue until TX FIFO is empty.
207 void NRF24L01_ClearAllInterrupts(void)
209 // Writing to the STATUS register clears the specified interrupt bits
210 NRF24L01_WriteReg(NRF24L01_07_STATUS, BIT(NRF24L01_07_STATUS_RX_DR) | BIT(NRF24L01_07_STATUS_TX_DS) | BIT(NRF24L01_07_STATUS_MAX_RT));
213 void NRF24L01_SetChannel(uint8_t channel)
215 NRF24L01_WriteReg(NRF24L01_05_RF_CH, channel);
218 bool NRF24L01_ReadPayloadIfAvailable(uint8_t *data, uint8_t length)
220 if (NRF24L01_ReadReg(NRF24L01_17_FIFO_STATUS) & BIT(NRF24L01_17_FIFO_STATUS_RX_EMPTY)) {
221 return false;
223 NRF24L01_ReadPayload(data, length);
224 return true;
227 #ifndef UNIT_TEST
228 #define DISABLE_RX() {IOHi(DEFIO_IO(RX_NSS_PIN));}
229 #define ENABLE_RX() {IOLo(DEFIO_IO(RX_NSS_PIN));}
231 * Fast read of payload, for use in interrupt service routine
233 bool NRF24L01_ReadPayloadIfAvailableFast(uint8_t *data, uint8_t length)
235 // number of bits transferred = 8 * (3 + length)
236 // for 16 byte payload, that is 8*19 = 152
237 // at 50MHz clock rate that is approximately 3 microseconds
238 bool ret = false;
239 ENABLE_RX();
240 rxSpiTransferByte(R_REGISTER | (REGISTER_MASK & NRF24L01_07_STATUS));
241 const uint8_t status = rxSpiTransferByte(NOP);
242 if ((status & BIT(NRF24L01_07_STATUS_RX_DR)) == 0) {
243 ret = true;
244 // clear RX_DR flag
245 rxSpiTransferByte(W_REGISTER | (REGISTER_MASK & NRF24L01_07_STATUS));
246 rxSpiTransferByte(BIT(NRF24L01_07_STATUS_RX_DR));
247 rxSpiTransferByte(R_RX_PAYLOAD);
248 for (uint8_t i = 0; i < length; i++) {
249 data[i] = rxSpiTransferByte(NOP);
252 DISABLE_RX();
253 return ret;
255 #endif // UNIT_TEST
256 #endif // USE_RX_NRF24