1 | /*
|
2 | Copyright (c) 2011 by Ernst Buchmann
|
3 |
|
4 | Code based on the work of Stefan Engelke and Brennan Ball
|
5 |
|
6 | Permission is hereby granted, free of charge, to any person
|
7 | obtaining a copy of this software and associated documentation
|
8 | files (the "Software"), to deal in the Software without
|
9 | restriction, including without limitation the rights to use, copy,
|
10 | modify, merge, publish, distribute, sublicense, and/or sell copies
|
11 | of the Software, and to permit persons to whom the Software is
|
12 | furnished to do so, subject to the following conditions:
|
13 |
|
14 | The above copyright notice and this permission notice shall be
|
15 | included in all copies or substantial portions of the Software.
|
16 |
|
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
18 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
19 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
20 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
21 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
22 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
24 | DEALINGS IN THE SOFTWARE.
|
25 |
|
26 |
|
27 | */
|
28 |
|
29 | #include "wl_module.h"
|
30 | #include "nRF24L01.h"
|
31 | #include "spi.h"
|
32 | #include <avr/io.h>
|
33 | #include <avr/interrupt.h>
|
34 | #include <util/delay.h>
|
35 |
|
36 | // Defines for setting the wl_module registers for transmitting or receiving mode
|
37 | #define TX_POWERUP wl_module_config_register(CONFIG, wl_module_CONFIG | ( (1<<PWR_UP) | (0<<PRIM_RX) ) )
|
38 | #define RX_POWERUP wl_module_config_register(CONFIG, wl_module_CONFIG | ( (1<<PWR_UP) | (1<<PRIM_RX) ) )
|
39 |
|
40 |
|
41 | // Flag which denotes transmitting mode
|
42 | volatile uint8_t PTX;
|
43 |
|
44 | void wl_module_init()
|
45 | // Initializes pins and interrupt to communicate with the wl_module
|
46 | // Should be called in the early initializing phase at startup.
|
47 | {
|
48 | // Define CSN and CE as Output and set them to default
|
49 | DDRB |= ((1<<CSN)|(1<<CE));
|
50 | wl_module_CE_lo;
|
51 | wl_module_CSN_hi;
|
52 |
|
53 |
|
54 | // Initialize spi module
|
55 | spi_init();
|
56 | }
|
57 |
|
58 |
|
59 | void wl_module_config()
|
60 | // Sets the important registers in the wl-module and powers the module
|
61 | // in receiving mode
|
62 | {
|
63 | // Set RF channel
|
64 | wl_module_config_register(RF_CH,wl_module_CH);
|
65 | // Set data speed & Output Power configured in wl_module.h
|
66 | //wl_module_config_register(RF_SETUP,wl_module_RF_SETUP);
|
67 | wl_module_config_register(RF_SETUP,0b00000111); // 0 dBm, 1Mbps
|
68 | // Set length of incoming payload
|
69 | wl_module_config_register(RX_PW_P0, wl_module_PAYLOAD);
|
70 |
|
71 | // Start receiver
|
72 | PTX = 0; // Start in receiving mode
|
73 | RX_POWERUP; // Power up in receiving mode
|
74 | wl_module_CE_hi; // Listening for pakets
|
75 | }
|
76 |
|
77 | extern void wl_module_rx_config()
|
78 | // Sets the important registers in the wl-module and powers the module
|
79 | // in receiving mode
|
80 | {
|
81 | uint8_t data[5];
|
82 | // Set RF channel
|
83 | wl_module_config_register(RF_CH,wl_module_CH);
|
84 | // Set data speed & Output Power configured in wl_module.h
|
85 | //wl_module_config_register(RF_SETUP,wl_module_RF_SETUP);
|
86 | wl_module_config_register(RF_SETUP,0b00000111); // 0 dBm, 1Mbps
|
87 | //Enable all RX Data-Pipes
|
88 | wl_module_config_register(EN_RXADDR, EN_RXADDR_ERX_ALL);
|
89 | //Set RX_Address Pipe 0
|
90 | data[0]= data[1]= data[2]= data[3]= data[4]= RX_ADDR_P0_B0_DEFAULT_VAL;
|
91 | wl_module_set_rx_addr(data, 5, 0);
|
92 | //Set RX_Address Pipe 1
|
93 | data[0]= data[1]= data[2]= data[3]= data[4]= RX_ADDR_P1_B0_DEFAULT_VAL;
|
94 | wl_module_set_rx_addr(data, 5, 1);
|
95 | //Set RX_Address Pipe 2-5
|
96 | data[0]=RX_ADDR_P2_DEFAULT_VAL;
|
97 | wl_module_set_rx_addr(data, 1, 2);
|
98 | data[0]=RX_ADDR_P3_DEFAULT_VAL;
|
99 | wl_module_set_rx_addr(data, 1, 3);
|
100 | data[0]=RX_ADDR_P4_DEFAULT_VAL;
|
101 | wl_module_set_rx_addr(data, 1, 4);
|
102 | data[0]=RX_ADDR_P5_DEFAULT_VAL;
|
103 | wl_module_set_rx_addr(data, 1, 5);
|
104 | // Set length of incoming payload
|
105 | wl_module_config_register(RX_PW_P0, wl_module_PAYLOAD);
|
106 | wl_module_config_register(RX_PW_P1, wl_module_PAYLOAD);
|
107 | wl_module_config_register(RX_PW_P2, wl_module_PAYLOAD);
|
108 | wl_module_config_register(RX_PW_P3, wl_module_PAYLOAD);
|
109 | wl_module_config_register(RX_PW_P4, wl_module_PAYLOAD);
|
110 | wl_module_config_register(RX_PW_P5, wl_module_PAYLOAD);
|
111 |
|
112 |
|
113 | // Start receiver
|
114 | PTX = 0; // Start in receiving mode
|
115 | RX_POWERUP; // Power up in receiving mode
|
116 | wl_module_CE_hi; // Listening for pakets
|
117 | }
|
118 |
|
119 | // Sets the wl-module as one of the six sender. Define for every sender a unique Number (wl_module_TX_NR_x)
|
120 | // when you call this Function.
|
121 | // Each TX will get a TX-Address corresponding to the RX-Device.
|
122 | // RX_Address_Pipe_0 must be the same as the TX-Address
|
123 | extern void wl_module_tx_config(uint8_t tx_nr)
|
124 | {
|
125 | uint8_t tx_addr[5];
|
126 |
|
127 | // Set RF channel
|
128 | wl_module_config_register(RF_CH,wl_module_CH);
|
129 | // Set data speed & Output Power configured in wl_module.h
|
130 | //wl_module_config_register(RF_SETUP,wl_module_RF_SETUP);
|
131 | wl_module_config_register(RF_SETUP,0b00000111); // 0 dBm, 1Mbps
|
132 | //Config the CONFIG Register (Mask IRQ, CRC, etc)
|
133 | wl_module_config_register(CONFIG, wl_module_CONFIG);
|
134 | // Set length of incoming payload
|
135 | wl_module_config_register(RX_PW_P0, wl_module_PAYLOAD);
|
136 |
|
137 | wl_module_config_register(SETUP_RETR,(SETUP_RETR_ARD_750 | SETUP_RETR_ARC_15));
|
138 |
|
139 |
|
140 |
|
141 | //set the TX address for the pipe with the same number as the iteration
|
142 | switch(tx_nr)
|
143 | {
|
144 | case 0: //setup TX address as default RX address for pipe 0 (E7:E7:E7:E7:E7)
|
145 | tx_addr[0] = tx_addr[1] = tx_addr[2] = tx_addr[3] = tx_addr[4] = RX_ADDR_P0_B0_DEFAULT_VAL;
|
146 | wl_module_set_TADDR(tx_addr);
|
147 | wl_module_set_RADDR(tx_addr);
|
148 | break;
|
149 | case 1: //setup TX address as default RX address for pipe 1 (C2:C2:C2:C2:C2)
|
150 | tx_addr[0] = tx_addr[1] = tx_addr[2] = tx_addr[3] = tx_addr[4] = RX_ADDR_P1_B0_DEFAULT_VAL;
|
151 | wl_module_set_TADDR(tx_addr);
|
152 | wl_module_set_RADDR(tx_addr);
|
153 | break;
|
154 | case 2: //setup TX address as default RX address for pipe 2 (C2:C2:C2:C2:C3)
|
155 | tx_addr[1] = tx_addr[2] = tx_addr[3] = tx_addr[4] = RX_ADDR_P1_B0_DEFAULT_VAL;
|
156 | tx_addr[0] = RX_ADDR_P2_DEFAULT_VAL;
|
157 | wl_module_set_TADDR(tx_addr);
|
158 | wl_module_set_RADDR(tx_addr);
|
159 | break;
|
160 | case 3: //setup TX address as default RX address for pipe 3 (C2:C2:C2:C2:C4)
|
161 | tx_addr[1] = tx_addr[2] = tx_addr[3] = tx_addr[4] = RX_ADDR_P1_B0_DEFAULT_VAL;
|
162 | tx_addr[0] = RX_ADDR_P3_DEFAULT_VAL;
|
163 | wl_module_set_TADDR(tx_addr);
|
164 | wl_module_set_RADDR(tx_addr);
|
165 | break;
|
166 | case 4: //setup TX address as default RX address for pipe 4 (C2:C2:C2:C2:C5)
|
167 | tx_addr[1] = tx_addr[2] = tx_addr[3] = tx_addr[4] = RX_ADDR_P1_B0_DEFAULT_VAL;
|
168 | tx_addr[0] = RX_ADDR_P4_DEFAULT_VAL;
|
169 | wl_module_set_TADDR(tx_addr);
|
170 | wl_module_set_RADDR(tx_addr);
|
171 | break;
|
172 | case 5: //setup TX address as default RX address for pipe 5 (C2:C2:C2:C2:C6)
|
173 | tx_addr[1] = tx_addr[2] = tx_addr[3] = tx_addr[4] = RX_ADDR_P1_B0_DEFAULT_VAL;
|
174 | tx_addr[0] = RX_ADDR_P5_DEFAULT_VAL;
|
175 | wl_module_set_TADDR(tx_addr);
|
176 | wl_module_set_RADDR(tx_addr);
|
177 | break;
|
178 | }
|
179 |
|
180 | PTX =0;
|
181 | TX_POWERUP;
|
182 | /*
|
183 | // Start receiver
|
184 | PTX = 0; // Start in receiving mode
|
185 | RX_POWERUP; // Power up in receiving mode
|
186 | wl_module_CE_hi; // Listening for pakets
|
187 | */
|
188 | }
|
189 |
|
190 | //sets the TX address in the TX_ADDR register
|
191 | //unsigned char * address is the actual address to be used. It should be sized
|
192 | // according to the tx_addr length specified to the nrf24l01.
|
193 | //unsigned int len is the length of the address. Its value should be specified
|
194 | // according to the tx_addr length specified to the nrf24l01.
|
195 | extern void wl_module_set_tx_addr(uint8_t * address, uint8_t len)
|
196 | {
|
197 | wl_module_write_register(TX_ADDR, address, len);
|
198 | }
|
199 |
|
200 | //sets up the 24L01 as a transmitter
|
201 | //this function takes the existing contents of the CONFIG register and simply
|
202 | // clears the PRIM_RX bit in the CONFIG register.
|
203 | //note: if the read value of the CONFIG register already has the PRIM_RX bit cleared, this
|
204 | // function exits in order to not make an unecessary register write.
|
205 | extern void wl_module_set_as_tx()
|
206 | {
|
207 | unsigned char config;
|
208 |
|
209 | wl_module_read_register(CONFIG, &config, 1);
|
210 |
|
211 | if((config & CONFIG_PRIM_RX) == 0)
|
212 | return;
|
213 |
|
214 | config &= (~CONFIG_PRIM_RX);
|
215 |
|
216 | wl_module_write_register(CONFIG, &config, 1);
|
217 |
|
218 | wl_module_CE_lo;
|
219 | }
|
220 |
|
221 | //powers down the 24L01
|
222 | //this function takes the existing contents of the CONFIG register and simply
|
223 | // clears the PWR_UP bit in the CONFIG register.
|
224 | //note: if the read value of the CONFIG register already has the PWR_UP bit cleared, this
|
225 | // function exits in order to not make an unecessary register write.
|
226 | extern void wl_module_power_down()
|
227 | {
|
228 | unsigned char config;
|
229 |
|
230 | wl_module_read_register(CONFIG, &config, 1);
|
231 |
|
232 | if((config & CONFIG_PWR_UP) == 0)
|
233 | return;
|
234 |
|
235 | config &= (~CONFIG_PWR_UP);
|
236 |
|
237 | wl_module_write_register(CONFIG, &config, 1);
|
238 |
|
239 | wl_module_CE_lo;
|
240 | }
|
241 |
|
242 | //sets the RX address in the RX_ADDR register that is offset by rxpipenum
|
243 | //unsigned char * address is the actual address to be used. It should be sized
|
244 | // according to the rx_addr length that is being filled.
|
245 | //unsigned int len is the length of the address. Its value should be specified
|
246 | // according to the rx_addr length specified to the nrf24l01.
|
247 | //unsigned char rxpipenum is the pipe number (zero to five) whose address is being
|
248 | // specified. If an invalid address (greater than five) is supplied, the function
|
249 | // does nothing.
|
250 | extern void wl_module_set_rx_addr(uint8_t * address, uint8_t len, uint8_t rxpipenum)
|
251 | {
|
252 | if(rxpipenum > 5)
|
253 | return;
|
254 |
|
255 | wl_module_write_register(RX_ADDR_P0 + rxpipenum, address, len);
|
256 | }
|
257 |
|
258 | extern void wl_module_get_rx_addr(uint8_t *data, uint8_t rxpipenum, uint8_t len)
|
259 | {
|
260 |
|
261 | if((rxpipenum > 5))
|
262 | return;
|
263 |
|
264 | wl_module_read_register(RX_ADDR_P0 + rxpipenum, data, len);
|
265 |
|
266 |
|
267 | }
|
268 |
|
269 | //sets the RX payload width on the pipe offset by rxpipenum
|
270 | //unsigned char payloadwidth is the length of the payload for the pipe referenced in
|
271 | // rxpipenum. It must be less than or equal to 32. If an invalid payload width is
|
272 | // specified, the function does nothing.
|
273 | //unsigned char rxpipenum is the pipe number (zero to five) whose address is being
|
274 | // specified. If an invalid address (greater than five) is supplied, the function
|
275 | // does nothing.
|
276 | extern void wl_module_set_rx_pw(unsigned char payloadwidth, unsigned char rxpipenum)
|
277 | {
|
278 | if((rxpipenum > 5) || (payloadwidth > 32))
|
279 | return;
|
280 |
|
281 | wl_module_write_register(RX_PW_P0 + rxpipenum, &payloadwidth, 1);
|
282 | }
|
283 |
|
284 | //gets the RX payload width on the pipe offset by rxpipenum
|
285 | //unsigned char rxpipenum is the pipe number (zero to five) whose address is being
|
286 | // specified. If an invalid address (greater than five) is supplied, the function
|
287 | // does nothing.
|
288 | extern uint8_t wl_module_get_rx_pw(uint8_t rxpipenum)
|
289 | {
|
290 | unsigned char data;
|
291 |
|
292 | if((rxpipenum > 5))
|
293 | return 0;
|
294 |
|
295 | wl_module_read_register(RX_PW_P0 + rxpipenum, &data, 1);
|
296 |
|
297 | return data;
|
298 | }
|
299 |
|
300 | //returns the current pipe in the 24L01's STATUS register
|
301 | extern uint8_t wl_module_get_rx_pipe()
|
302 | {
|
303 | return wl_module_get_rx_pipe_from_status(wl_module_get_status());
|
304 | }
|
305 |
|
306 | extern uint8_t wl_module_get_rx_pipe_from_status(uint8_t status)
|
307 | {
|
308 | return ((status & 0xE) >> 1);
|
309 | }
|
310 |
|
311 | void wl_module_set_RADDR(uint8_t * adr)
|
312 | // Sets the receiving address
|
313 | {
|
314 | // wl_module_CE_lo; //<----------- Wozu diese Bit wechsel ????
|
315 | wl_module_write_register(RX_ADDR_P0,adr,5);
|
316 | // wl_module_CE_hi; //<----------- Wozu diese Bit wechsel ????
|
317 | }
|
318 |
|
319 | void wl_module_set_TADDR(uint8_t * adr)
|
320 | // Sets the transmitting address
|
321 | {
|
322 | wl_module_write_register(TX_ADDR, adr,5);
|
323 | }
|
324 |
|
325 |
|
326 |
|
327 | extern uint8_t wl_module_data_ready()
|
328 | // Checks if data is available for reading
|
329 | {
|
330 | if (PTX) return 0;
|
331 | uint8_t status;
|
332 | // Read wl_module status
|
333 | wl_module_CSN_lo; // Pull down chip select
|
334 | status = spi_fast_shift(NOP); // Read status register
|
335 | wl_module_CSN_hi; // Pull up chip select
|
336 | return status & (1<<RX_DR);
|
337 | }
|
338 |
|
339 | //returns true if TX_EMPTY bit in FIFO_STATUS register is set, false otherwise
|
340 | extern uint8_t wl_module_fifo_tx_empty()
|
341 | {
|
342 | uint8_t data;
|
343 |
|
344 | wl_module_read_register(FIFO_STATUS, &data, 1);
|
345 |
|
346 |
|
347 | return (data & FIFO_STATUS_TX_EMPTY);
|
348 | }
|
349 |
|
350 | //returns true if RX_EMPTY bit in FIFO_STATUS register is set, false otherwise
|
351 | extern uint8_t wl_module_fifo_rx_empty()
|
352 | {
|
353 | uint8_t data;
|
354 |
|
355 | wl_module_read_register(FIFO_STATUS, &data, 1);
|
356 |
|
357 | return (data & FIFO_STATUS_RX_EMPTY);
|
358 | }
|
359 |
|
360 | //returns the current RF channel in RF_CH register
|
361 | extern uint8_t wl_module_get_rf_ch()
|
362 | {
|
363 | uint8_t data;
|
364 |
|
365 | wl_module_read_register(RF_CH, &data, 1);
|
366 |
|
367 | return data;
|
368 | }
|
369 |
|
370 | //returns the current RF_SETUP Register
|
371 | extern uint8_t wl_module_get_rf_setup()
|
372 | {
|
373 | uint8_t data;
|
374 |
|
375 | wl_module_read_register(RF_SETUP, &data, 1);
|
376 |
|
377 | return data;
|
378 | }
|
379 |
|
380 | //returns the current PLOS_CNT value in OBSERVE_TX register
|
381 | extern uint8_t wl_module_get_plos_cnt()
|
382 | {
|
383 | uint8_t data;
|
384 |
|
385 | wl_module_read_register(OBSERVE_TX, &data, 1);
|
386 |
|
387 | return ((data & OBSERVE_TX_PLOS_CNT) >> 4);
|
388 | }
|
389 |
|
390 | //returns the current ARC_CNT value in OBSERVE_TX register
|
391 | extern uint8_t wl_module_get_arc_cnt()
|
392 | {
|
393 | uint8_t data;
|
394 |
|
395 | wl_module_read_register(OBSERVE_TX, &data, 1);
|
396 |
|
397 | return (data & OBSERVE_TX_ARC_CNT);
|
398 | }
|
399 |
|
400 | //return the value of the status register
|
401 | extern uint8_t wl_module_get_status()
|
402 | {
|
403 | return wl_module_get_one_byte(NOP);
|
404 | }
|
405 |
|
406 | extern uint8_t wl_module_get_rx_pipe_reading_status()
|
407 | {
|
408 | uint8_t pipe;
|
409 | pipe = wl_module_get_one_byte(NOP);
|
410 | return ((pipe & 0x0E) >> 1);
|
411 | }
|
412 |
|
413 | extern uint8_t wl_module_get_one_byte(uint8_t command)
|
414 | {
|
415 | uint8_t status;
|
416 |
|
417 | wl_module_CSN_lo;
|
418 | status = spi_fast_shift(command);
|
419 | wl_module_CSN_hi;
|
420 |
|
421 | return status;
|
422 |
|
423 | }
|
424 |
|
425 | extern uint8_t wl_module_get_data(uint8_t * data)
|
426 | // Reads wl_module_PAYLOAD bytes into data array
|
427 | {
|
428 | uint8_t status;
|
429 | wl_module_CSN_lo; // Pull down chip select
|
430 | status = spi_fast_shift( R_RX_PAYLOAD ); // Send cmd to read rx payload
|
431 | spi_transfer_sync(data,data,wl_module_PAYLOAD); // Read payload
|
432 | wl_module_CSN_hi; // Pull up chip select
|
433 | wl_module_config_register(STATUS,(1<<RX_DR)); // Reset status register
|
434 | return status;
|
435 | }
|
436 |
|
437 | void wl_module_config_register(uint8_t reg, uint8_t value)
|
438 | // Clocks only one byte into the given wl-module register
|
439 | {
|
440 | wl_module_CSN_lo;
|
441 | spi_fast_shift(W_REGISTER | (REGISTER_MASK & reg));
|
442 | spi_fast_shift(value);
|
443 | wl_module_CSN_hi;
|
444 | }
|
445 |
|
446 | void wl_module_read_register(uint8_t reg, uint8_t * value, uint8_t len)
|
447 | // Reads an array of bytes from the given start position in the wl-module registers.
|
448 | {
|
449 | wl_module_CSN_lo;
|
450 | spi_fast_shift(R_REGISTER | (REGISTER_MASK & reg));
|
451 | spi_transfer_sync(value,value,len);
|
452 | wl_module_CSN_hi;
|
453 | }
|
454 |
|
455 | void wl_module_write_register(uint8_t reg, uint8_t * value, uint8_t len)
|
456 | // Writes an array of bytes into inte the wl-module registers.
|
457 | {
|
458 | wl_module_CSN_lo;
|
459 | spi_fast_shift(W_REGISTER | (REGISTER_MASK & reg));
|
460 | spi_transmit_sync(value,len);
|
461 | wl_module_CSN_hi;
|
462 | }
|
463 |
|
464 |
|
465 | void wl_module_send(uint8_t * value, uint8_t len)
|
466 | // Sends a data package to the default address. Be sure to send the correct
|
467 | // amount of bytes as configured as payload on the receiver.
|
468 | {
|
469 | while (PTX) {} // Wait until last paket is send
|
470 |
|
471 | wl_module_CE_lo;
|
472 |
|
473 | PTX = 1; // Set to transmitter mode
|
474 | TX_POWERUP; // Power up
|
475 |
|
476 | wl_module_CSN_lo; // Pull down chip select
|
477 | spi_fast_shift( FLUSH_TX ); // Write cmd to flush tx fifo
|
478 | wl_module_CSN_hi; // Pull up chip select
|
479 |
|
480 | wl_module_CSN_lo; // Pull down chip select
|
481 | spi_fast_shift( W_TX_PAYLOAD ); // Write cmd to write payload
|
482 | spi_transmit_sync(value,len); // Write payload
|
483 | wl_module_CSN_hi; // Pull up chip select
|
484 |
|
485 | wl_module_CE_hi; // Start transmission
|
486 | _delay_us(50); // Grünes Modul funktioniert nicht mit 10µs delay
|
487 | wl_module_CE_lo;
|
488 | }
|