1 | /*
|
2 | *
|
3 | * ----------------------------------------------------------------------------
|
4 | * “THE COFFEEWARE LICENSE” (Revision 1):
|
5 | * <ihsan@kehribar.me> wrote this file. As long as you retain this notice you
|
6 | * can do whatever you want with this stuff. If we meet some day, and you think
|
7 | * this stuff is worth it, you can buy me a coffee in return.
|
8 | * -----------------------------------------------------------------------------
|
9 | * This library is based on this library:
|
10 | * https://github.com/aaronds/arduino-nrf24l01
|
11 | * Which is based on this library:
|
12 | * http://www.tinkerer.eu/AVRLib/nRF24L01
|
13 | * -----------------------------------------------------------------------------
|
14 | */
|
15 | #include "nrf24.h"
|
16 |
|
17 | uint8_t payload_len;
|
18 |
|
19 | /* init the hardware pins */
|
20 | void nrf24_init()
|
21 | {
|
22 | DDRB |= ((1<<CSN)|(1<<CE));
|
23 | wl_module_CE_lo;
|
24 | wl_module_CSN_hi;
|
25 |
|
26 | spi_init();
|
27 | }
|
28 |
|
29 | /* configure the module */
|
30 | void nrf24_config(uint8_t channel, uint8_t pay_length)//(2,4)
|
31 | {
|
32 | /* Use static payload length ... */
|
33 | payload_len = pay_length;
|
34 |
|
35 | // Set RF channel
|
36 | nrf24_configRegister(RF_CH,channel);
|
37 |
|
38 | // Set length of incoming payload
|
39 | nrf24_configRegister(RX_PW_P0, 0x00); // Auto-ACK pipe ...
|
40 | nrf24_configRegister(RX_PW_P1, payload_len); // Data payload pipe
|
41 | nrf24_configRegister(RX_PW_P2, 0x00); // Pipe not used
|
42 | nrf24_configRegister(RX_PW_P3, 0x00); // Pipe not used
|
43 | nrf24_configRegister(RX_PW_P4, 0x00); // Pipe not used
|
44 | nrf24_configRegister(RX_PW_P5, 0x00); // Pipe not used
|
45 |
|
46 | // 1 Mbps, TX gain: 0dbm
|
47 | nrf24_configRegister(RF_SETUP, (0<<RF_DR)|((0x03)<<RF_PWR));
|
48 |
|
49 | // CRC enable, 1 byte CRC length
|
50 | nrf24_configRegister(CONFIG,nrf24_CONFIG);
|
51 |
|
52 | // Auto Acknowledgment
|
53 | nrf24_configRegister(EN_AA,(1<<ENAA_P0)|(1<<ENAA_P1)|(0<<ENAA_P2)|(0<<ENAA_P3)|(0<<ENAA_P4)|(0<<ENAA_P5));
|
54 |
|
55 | // Enable RX addresses
|
56 | nrf24_configRegister(EN_RXADDR,(1<<ERX_P0)|(1<<ERX_P1)|(0<<ERX_P2)|(0<<ERX_P3)|(0<<ERX_P4)|(0<<ERX_P5));
|
57 |
|
58 | // Auto retransmit delay: 1000 us and Up to 15 retransmit trials
|
59 | nrf24_configRegister(SETUP_RETR,(0x04<<ARD)|(0x0F<<ARC));
|
60 |
|
61 | // Dynamic length configurations: No dynamic length
|
62 | nrf24_configRegister(DYNPD,(0<<DPL_P0)|(0<<DPL_P1)|(0<<DPL_P2)|(0<<DPL_P3)|(0<<DPL_P4)|(0<<DPL_P5));
|
63 |
|
64 | // Start listening
|
65 | nrf24_powerUpRx();
|
66 | }
|
67 |
|
68 | /* Set the RX address */
|
69 | void nrf24_rx_address(uint8_t * adr)
|
70 | {
|
71 | wl_module_CE_lo;
|
72 | nrf24_writeRegister(RX_ADDR_P1,adr,nrf24_ADDR_LEN);
|
73 | wl_module_CE_hi;
|
74 | }
|
75 |
|
76 | /* Returns the payload length */
|
77 | uint8_t nrf24_payload_length()
|
78 | {
|
79 | return payload_len;
|
80 | }
|
81 |
|
82 | /* Set the TX address */
|
83 | void nrf24_tx_address(uint8_t* adr)
|
84 | {
|
85 | /* RX_ADDR_P0 must be set to the sending addr for auto ack to work. */
|
86 | nrf24_writeRegister(RX_ADDR_P0,adr,nrf24_ADDR_LEN);
|
87 | nrf24_writeRegister(TX_ADDR,adr,nrf24_ADDR_LEN);
|
88 | }
|
89 |
|
90 | /* Checks if data is available for reading */
|
91 | /* Returns 1 if data is ready ... */
|
92 | uint8_t nrf24_dataReady()
|
93 | {
|
94 | // See note in getData() function - just checking RX_DR isn't good enough
|
95 | uint8_t status = nrf24_getStatus();
|
96 |
|
97 | // We can short circuit on RX_DR, but if it's not set, we still need
|
98 | // to check the FIFO for any pending packets
|
99 | if ( status & (1 << RX_DR) )
|
100 | {
|
101 | return 1;
|
102 | }
|
103 |
|
104 | return !nrf24_rxFifoEmpty();;
|
105 | }
|
106 |
|
107 | /* Checks if receive FIFO is empty or not */
|
108 | uint8_t nrf24_rxFifoEmpty()
|
109 | {
|
110 | uint8_t fifoStatus;
|
111 |
|
112 | nrf24_readRegister(FIFO_STATUS,&fifoStatus,1);
|
113 |
|
114 | return (fifoStatus & (1 << RX_EMPTY));
|
115 | }
|
116 |
|
117 | /* Returns the length of data waiting in the RX fifo */
|
118 | uint8_t nrf24_payloadLength()
|
119 | {
|
120 | uint8_t status;
|
121 | wl_module_CSN_lo;
|
122 | spi_fast_shift(R_RX_PL_WID);
|
123 | status = spi_fast_shift(0x00);
|
124 | wl_module_CSN_hi;
|
125 | return status;
|
126 | }
|
127 |
|
128 | /* Reads payload bytes into data array */
|
129 | void nrf24_getData(uint8_t* data)
|
130 | {
|
131 | /* Pull down chip select */
|
132 | wl_module_CSN_lo;
|
133 |
|
134 | /* Send cmd to read rx payload */
|
135 | spi_fast_shift( R_RX_PAYLOAD );
|
136 |
|
137 | /* Read payload */
|
138 | spi_transfer_sync(data,data,payload_len);
|
139 |
|
140 | /* Pull up chip select */
|
141 | wl_module_CSN_hi;
|
142 |
|
143 | /* Reset status register */
|
144 | nrf24_configRegister(STATUS,(1<<RX_DR));
|
145 | }
|
146 |
|
147 | /* Returns the number of retransmissions occured for the last message */
|
148 | uint8_t nrf24_retransmissionCount()
|
149 | {
|
150 | uint8_t rv;
|
151 | nrf24_readRegister(OBSERVE_TX,&rv,1);
|
152 | rv = rv & 0x0F;
|
153 | return rv;
|
154 | }
|
155 |
|
156 | // Sends a data package to the default address. Be sure to send the correct
|
157 | // amount of bytes as configured as payload on the receiver.
|
158 | void nrf24_send(uint8_t* value)
|
159 | {
|
160 | /* Go to Standby-I first */
|
161 | wl_module_CE_lo;
|
162 |
|
163 | /* Set to transmitter mode , Power up if needed */
|
164 | nrf24_powerUpTx();
|
165 |
|
166 | /* Do we really need to flush TX fifo each time ? */
|
167 | #if 1
|
168 | /* Pull down chip select */
|
169 | wl_module_CSN_lo;
|
170 |
|
171 | /* Write cmd to flush transmit FIFO */
|
172 | spi_fast_shift(FLUSH_TX);
|
173 |
|
174 | /* Pull up chip select */
|
175 | wl_module_CSN_hi;
|
176 | #endif
|
177 |
|
178 | /* Pull down chip select */
|
179 | wl_module_CSN_lo;
|
180 |
|
181 | /* Write cmd to write payload */
|
182 | spi_fast_shift(W_TX_PAYLOAD);
|
183 |
|
184 | /* Write payload */
|
185 | spi_transmit_sync(value,payload_len);
|
186 |
|
187 | /* Pull up chip select */
|
188 | wl_module_CSN_hi;
|
189 |
|
190 | /* Start the transmission */
|
191 | wl_module_CE_hi
|
192 | }
|
193 |
|
194 | uint8_t nrf24_isSending()
|
195 | {
|
196 | uint8_t status;
|
197 |
|
198 | /* read the current status */
|
199 | status = nrf24_getStatus();
|
200 |
|
201 | /* if sending successful (TX_DS) or max retries exceded (MAX_RT). */
|
202 | if((status & ((1 << TX_DS) | (1 << MAX_RT))))
|
203 | {
|
204 | return 0; /* false */
|
205 | }
|
206 |
|
207 | return 1; /* true */
|
208 |
|
209 | }
|
210 |
|
211 | uint8_t nrf24_getStatus()
|
212 | {
|
213 | uint8_t rv;
|
214 | wl_module_CSN_lo;
|
215 | rv = spi_fast_shift(NOP);
|
216 | wl_module_CSN_hi;
|
217 | return rv;
|
218 | }
|
219 |
|
220 | uint8_t nrf24_lastMessageStatus()
|
221 | {
|
222 | uint8_t rv;
|
223 |
|
224 | rv = nrf24_getStatus();
|
225 |
|
226 | /* Transmission went OK */
|
227 | if((rv & ((1 << TX_DS))))
|
228 | {
|
229 | return NRF24_TRANSMISSON_OK;
|
230 | }
|
231 | /* Maximum retransmission count is reached */
|
232 | /* Last message probably went missing ... */
|
233 | else if((rv & ((1 << MAX_RT))))
|
234 | {
|
235 | return NRF24_MESSAGE_LOST;
|
236 | }
|
237 | /* Probably still sending ... */
|
238 | else
|
239 | {
|
240 | return 0xFF;
|
241 | }
|
242 | }
|
243 |
|
244 | void nrf24_powerUpRx()
|
245 | {
|
246 | wl_module_CSN_lo;
|
247 | spi_fast_shift(FLUSH_RX);
|
248 | wl_module_CSN_hi;
|
249 |
|
250 | nrf24_configRegister(STATUS,(1<<RX_DR)|(1<<TX_DS)|(1<<MAX_RT));
|
251 |
|
252 | wl_module_CE_lo;
|
253 | nrf24_configRegister(CONFIG,nrf24_CONFIG|((1<<PWR_UP)|(1<<PRIM_RX)));
|
254 | wl_module_CE_hi
|
255 | }
|
256 |
|
257 | void nrf24_powerUpTx()
|
258 | {
|
259 | nrf24_configRegister(STATUS,(1<<RX_DR)|(1<<TX_DS)|(1<<MAX_RT));
|
260 |
|
261 | nrf24_configRegister(CONFIG,nrf24_CONFIG|((1<<PWR_UP)|(0<<PRIM_RX)));
|
262 | }
|
263 |
|
264 | void nrf24_powerDown()
|
265 | {
|
266 | wl_module_CE_lo;
|
267 | nrf24_configRegister(CONFIG,nrf24_CONFIG);
|
268 | }
|
269 |
|
270 | /* Clocks only one byte into the given nrf24 register */
|
271 | void nrf24_configRegister(uint8_t reg, uint8_t value)
|
272 | {
|
273 | wl_module_CSN_lo;
|
274 | spi_fast_shift(W_REGISTER | (REGISTER_MASK & reg));
|
275 | spi_fast_shift(value);
|
276 | wl_module_CSN_hi;
|
277 | }
|
278 |
|
279 | /* Read single register from nrf24 */
|
280 | void nrf24_readRegister(uint8_t reg, uint8_t* value, uint8_t len)
|
281 | {
|
282 | wl_module_CSN_lo;
|
283 | spi_fast_shift(R_REGISTER | (REGISTER_MASK & reg));
|
284 | spi_transfer_sync(value,value,len);
|
285 | wl_module_CSN_hi;
|
286 | }
|
287 |
|
288 | /* Write to a single register of nrf24 */
|
289 | void nrf24_writeRegister(uint8_t reg, uint8_t* value, uint8_t len)
|
290 | {
|
291 | wl_module_CSN_lo;
|
292 | spi_fast_shift(W_REGISTER | (REGISTER_MASK & reg));
|
293 | spi_transmit_sync(value,len);
|
294 | wl_module_CSN_hi;
|
295 | }
|