BayEOS-Arduino  1.8.0_0.0.4
iBoardRF24.cpp
1 /*
2  Copyright (C) 2011 J. Coliz <maniacbug@ymail.com>
3  Copyright (C) 2012 Andrey Karpov <andy.karpov@gmail.com>
4 
5  This program is free software; you can redistribute it and/or
6  modify it under the terms of the GNU General Public License
7  version 2 as published by the Free Software Foundation.
8  */
9 
10 #include "nRF24L01.h"
11 #include "RF24_config.h"
12 #include "iBoardRF24.h"
13 #include "digitalWriteFast.h"
14 
15 
16 /****************************************************************************/
17 
18 void iBoardRF24::csn(int mode)
19 {
20  digitalWriteFast2(csn_pin,mode);
21 }
22 
23 /****************************************************************************/
24 
25 void iBoardRF24::ce(int level)
26 {
27  digitalWriteFast2(ce_pin,level);
28 }
29 
30 unsigned char iBoardRF24::SPI_RW(unsigned char byte) {
31  unsigned char i;
32  for(i=0;i<8;i++) {
33  if(byte&0x80) {
34  digitalWriteFast2(mosi_pin, 1);
35  } else {
36  digitalWriteFast2(mosi_pin, 0);
37  }
38  digitalWriteFast2(sck_pin, 1);
39  byte <<= 1;
40  if(digitalReadFast2(miso_pin) == 1) {
41  byte |= 1;
42  }
43  digitalWriteFast2(sck_pin, 0);
44  }
45  return (byte);
46 }
47 
48 /****************************************************************************/
49 
50 uint8_t iBoardRF24::read_register(uint8_t reg, uint8_t* buf, uint8_t len)
51 {
52  uint8_t status;
53 
54  csn(LOW);
55  status = SPI_RW( R_REGISTER | ( REGISTER_MASK & reg ) );
56  while ( len-- )
57  *buf++ = SPI_RW(0xff);
58 
59  csn(HIGH);
60 
61  return status;
62 }
63 
64 /****************************************************************************/
65 
66 uint8_t iBoardRF24::read_register(uint8_t reg)
67 {
68  csn(LOW);
69  SPI_RW( R_REGISTER | ( REGISTER_MASK & reg ) );
70  uint8_t result = SPI_RW(0xff);
71 
72  csn(HIGH);
73  return result;
74 }
75 
76 /****************************************************************************/
77 
78 uint8_t iBoardRF24::write_register(uint8_t reg, const uint8_t* buf, uint8_t len)
79 {
80  uint8_t status;
81 
82  csn(LOW);
83  status = SPI_RW( W_REGISTER | ( REGISTER_MASK & reg ) );
84  while ( len-- )
85  SPI_RW(*buf++);
86 
87  csn(HIGH);
88 
89  return status;
90 }
91 
92 /****************************************************************************/
93 
94 uint8_t iBoardRF24::write_register(uint8_t reg, uint8_t value)
95 {
96  uint8_t status;
97 
98  csn(LOW);
99  status = SPI_RW( W_REGISTER | ( REGISTER_MASK & reg ) );
100  SPI_RW(value);
101  csn(HIGH);
102 
103  return status;
104 }
105 
106 /****************************************************************************/
107 
108 uint8_t iBoardRF24::write_payload(const void* buf, uint8_t len)
109 {
110  uint8_t status;
111 
112  const uint8_t* current = reinterpret_cast<const uint8_t*>(buf);
113 
114  uint8_t data_len = min(len,payload_size);
115  uint8_t blank_len = dynamic_payloads_enabled ? 0 : payload_size - data_len;
116 
117  //printf("[Writing %u bytes %u blanks]",data_len,blank_len);
118 
119  csn(LOW);
120  status = SPI_RW( W_TX_PAYLOAD );
121  while ( data_len-- )
122  SPI_RW(*current++);
123  while ( blank_len-- )
124  SPI_RW(0);
125  csn(HIGH);
126 
127  return status;
128 }
129 
130 /****************************************************************************/
131 
132 uint8_t iBoardRF24::read_payload(void* buf, uint8_t len)
133 {
134  uint8_t status;
135  uint8_t* current = reinterpret_cast<uint8_t*>(buf);
136 
137  uint8_t data_len = min(len,payload_size);
138  uint8_t blank_len = dynamic_payloads_enabled ? 0 : payload_size - data_len;
139 
140  //printf("[Reading %u bytes %u blanks]",data_len,blank_len);
141 
142  csn(LOW);
143  status = SPI_RW( R_RX_PAYLOAD );
144  while ( data_len-- )
145  *current++ = SPI_RW(0xff);
146  while ( blank_len-- )
147  SPI_RW(0xff);
148  csn(HIGH);
149 
150  return status;
151 }
152 
153 /****************************************************************************/
154 
155 uint8_t iBoardRF24::flush_rx(void)
156 {
157  uint8_t status;
158 
159  csn(LOW);
160  status = SPI_RW( FLUSH_RX );
161  csn(HIGH);
162 
163  return status;
164 }
165 
166 /****************************************************************************/
167 
168 uint8_t iBoardRF24::flush_tx(void)
169 {
170  uint8_t status;
171 
172  csn(LOW);
173  status = SPI_RW( FLUSH_TX );
174  csn(HIGH);
175 
176  return status;
177 }
178 
179 /****************************************************************************/
180 
182 {
183  uint8_t status;
184 
185  csn(LOW);
186  status = SPI_RW( NOP );
187  csn(HIGH);
188 
189  return status;
190 }
191 
192 /****************************************************************************/
193 
194 void iBoardRF24::print_status(uint8_t status)
195 {
196  printf_P(PSTR("STATUS\t\t = 0x%02x RX_DR=%x TX_DS=%x MAX_RT=%x RX_P_NO=%x TX_FULL=%x\r\n"),
197  status,
198  (status & _BV(RX_DR))?1:0,
199  (status & _BV(TX_DS))?1:0,
200  (status & _BV(MAX_RT))?1:0,
201  ((status >> RX_P_NO) & B111),
202  (status & _BV(TX_FULL))?1:0
203  );
204 }
205 
206 /****************************************************************************/
207 
208 void iBoardRF24::print_observe_tx(uint8_t value)
209 {
210  printf_P(PSTR("OBSERVE_TX=%02x: POLS_CNT=%x ARC_CNT=%x\r\n"),
211  value,
212  (value >> PLOS_CNT) & B1111,
213  (value >> ARC_CNT) & B1111
214  );
215 }
216 
217 /****************************************************************************/
218 
219 void iBoardRF24::print_byte_register(const char* name, uint8_t reg, uint8_t qty)
220 {
221  char extra_tab = strlen_P(name) < 8 ? '\t' : 0;
222  printf_P(PSTR(PRIPSTR"\t%c ="),name,extra_tab);
223  while (qty--)
224  printf_P(PSTR(" 0x%02x"),read_register(reg++));
225  printf_P(PSTR("\r\n"));
226 }
227 
228 /****************************************************************************/
229 
230 void iBoardRF24::print_address_register(const char* name, uint8_t reg, uint8_t qty)
231 {
232  char extra_tab = strlen_P(name) < 8 ? '\t' : 0;
233  printf_P(PSTR(PRIPSTR"\t%c ="),name,extra_tab);
234 
235  while (qty--)
236  {
237  uint8_t buffer[5];
238  read_register(reg++,buffer,sizeof buffer);
239 
240  printf_P(PSTR(" 0x"));
241  uint8_t* bufptr = buffer + sizeof buffer;
242  while( --bufptr >= buffer )
243  printf_P(PSTR("%02x"),*bufptr);
244  }
245 
246  printf_P(PSTR("\r\n"));
247 }
248 
249 /****************************************************************************/
250 
251 iBoardRF24::iBoardRF24(uint8_t _cepin, uint8_t _cspin, uint8_t _mosi_pin, uint8_t _miso_pin, uint8_t _sck_pin, uint8_t _irq_pin):
252  ce_pin(_cepin), csn_pin(_cspin), mosi_pin(_mosi_pin), miso_pin(_miso_pin), sck_pin(_sck_pin), irq_pin(_irq_pin),
253  wide_band(true), p_variant(false), payload_size(32), ack_payload_available(false),
254  dynamic_payloads_enabled(false), pipe0_reading_address(0)
255 {
256 }
257 
258 /****************************************************************************/
259 
260 void iBoardRF24::setChannel(uint8_t channel)
261 {
262  // TODO: This method could take advantage of the 'wide_band' calculation
263  // done in setChannel() to require certain channel spacing.
264 
265  const uint8_t max_channel = 127;
266  write_register(RF_CH,min(channel,max_channel));
267 }
268 
269 /****************************************************************************/
270 
271 void iBoardRF24::setPayloadSize(uint8_t size)
272 {
273  const uint8_t max_payload_size = 32;
274  payload_size = min(size,max_payload_size);
275 }
276 
277 /****************************************************************************/
278 
280 {
281  return payload_size;
282 }
283 
284 /****************************************************************************/
285 
286 static const char rf24_datarate_e_str_0[] PROGMEM = "1MBPS";
287 static const char rf24_datarate_e_str_1[] PROGMEM = "2MBPS";
288 static const char rf24_datarate_e_str_2[] PROGMEM = "250KBPS";
289 static const char * const rf24_datarate_e_str_P[] PROGMEM = {
290  rf24_datarate_e_str_0,
291  rf24_datarate_e_str_1,
292  rf24_datarate_e_str_2,
293 };
294 static const char rf24_model_e_str_0[] PROGMEM = "nRF24L01";
295 static const char rf24_model_e_str_1[] PROGMEM = "nRF24L01+";
296 static const char * const rf24_model_e_str_P[] PROGMEM = {
297  rf24_model_e_str_0,
298  rf24_model_e_str_1,
299 };
300 static const char rf24_crclength_e_str_0[] PROGMEM = "Disabled";
301 static const char rf24_crclength_e_str_1[] PROGMEM = "8 bits";
302 static const char rf24_crclength_e_str_2[] PROGMEM = "16 bits" ;
303 static const char * const rf24_crclength_e_str_P[] PROGMEM = {
304  rf24_crclength_e_str_0,
305  rf24_crclength_e_str_1,
306  rf24_crclength_e_str_2,
307 };
308 static const char rf24_pa_dbm_e_str_0[] PROGMEM = "PA_MIN";
309 static const char rf24_pa_dbm_e_str_1[] PROGMEM = "PA_LOW";
310 static const char rf24_pa_dbm_e_str_2[] PROGMEM = "LA_MED";
311 static const char rf24_pa_dbm_e_str_3[] PROGMEM = "PA_HIGH";
312 static const char * const rf24_pa_dbm_e_str_P[] PROGMEM = {
313  rf24_pa_dbm_e_str_0,
314  rf24_pa_dbm_e_str_1,
315  rf24_pa_dbm_e_str_2,
316  rf24_pa_dbm_e_str_3,
317 };
318 
320 {
322 
323  print_address_register(PSTR("RX_ADDR_P0-1"),RX_ADDR_P0,2);
324  print_byte_register(PSTR("RX_ADDR_P2-5"),RX_ADDR_P2,4);
325  print_address_register(PSTR("TX_ADDR"),TX_ADDR);
326 
327  print_byte_register(PSTR("RX_PW_P0-6"),RX_PW_P0,6);
328  print_byte_register(PSTR("EN_AA"),EN_AA);
329  print_byte_register(PSTR("EN_RXADDR"),EN_RXADDR);
330  print_byte_register(PSTR("RF_CH"),RF_CH);
331  print_byte_register(PSTR("RF_SETUP"),RF_SETUP);
332  print_byte_register(PSTR("CONFIG"),CONFIG);
333  print_byte_register(PSTR("DYNPD/FEATURE"),DYNPD,2);
334 
335  printf_P(PSTR("Data Rate\t = %S\r\n"),pgm_read_word(&rf24_datarate_e_str_P[getDataRate()]));
336  printf_P(PSTR("Model\t\t = %S\r\n"),pgm_read_word(&rf24_model_e_str_P[isPVariant()]));
337  printf_P(PSTR("CRC Length\t = %S\r\n"),pgm_read_word(&rf24_crclength_e_str_P[getCRCLength()]));
338  printf_P(PSTR("PA Power\t = %S\r\n"),pgm_read_word(&rf24_pa_dbm_e_str_P[getPALevel()]));
339 }
340 
341 /****************************************************************************/
342 
344 {
345  // Initialize pins
346  pinMode(ce_pin,OUTPUT);
347  pinMode(csn_pin,OUTPUT);
348 
349  pinMode(miso_pin, INPUT);
350  pinMode(irq_pin, INPUT);
351  pinMode(mosi_pin, OUTPUT);
352  pinMode(sck_pin, OUTPUT);
353 
354 // attachInterrupt(1, _ISR, LOW);
355 
356  ce(LOW);
357  csn(HIGH);
358 
359  // Must allow the radio time to settle else configuration bits will not necessarily stick.
360  // This is actually only required following power up but some settling time also appears to
361  // be required after resets too. For full coverage, we'll always assume the worst.
362  // Enabling 16b CRC is by far the most obvious case if the wrong timing is used - or skipped.
363  // Technically we require 4.5ms + 14us as a worst case. We'll just call it 5ms for good measure.
364  // WARNING: Delay is based on P-variant whereby non-P *may* require different timing.
365  delay( 5 ) ;
366 
367  // Set 1500uS (minimum for 32B payload in ESB@250KBPS) timeouts, to make testing a little easier
368  // WARNING: If this is ever lowered, either 250KBS mode with AA is broken or maximum packet
369  // sizes must never be used. See documentation for a more complete explanation.
370  write_register(SETUP_RETR,(B0100 << ARD) | (B1111 << ARC));
371 
372  // Restore our default PA level
373  setPALevel( RF24_PA_MAX ) ;
374 
375  // Determine if this is a p or non-p RF24 module and then
376  // reset our data rate back to default value. This works
377  // because a non-P variant won't allow the data rate to
378  // be set to 250Kbps.
379  if( setDataRate( RF24_250KBPS ) )
380  {
381  p_variant = true ;
382  }
383 
384  // Then set the data rate to the slowest (and most reliable) speed supported by all
385  // hardware.
386  setDataRate( RF24_1MBPS ) ;
387 
388  // Initialize CRC and request 2-byte (16bit) CRC
389  setCRCLength( RF24_CRC_16 ) ;
390 
391  // Disable dynamic payloads, to match dynamic_payloads_enabled setting
392  write_register(DYNPD,0);
393 
394  // Reset current status
395  // Notice reset and flush is the last thing we do
396  write_register(STATUS,_BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT) );
397 
398  // Set up default configuration. Callers can always change it later.
399  // This channel should be universally safe and not bleed over into adjacent
400  // spectrum.
401  setChannel(76);
402 
403  // Flush buffers
404  flush_rx();
405  flush_tx();
406 }
407 
408 /****************************************************************************/
409 
411 {
412  write_register(CONFIG, read_register(CONFIG) | _BV(PWR_UP) | _BV(PRIM_RX));
413  write_register(STATUS, _BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT) );
414 
415  // Restore the pipe0 adddress, if exists
416  if (pipe0_reading_address)
417  write_register(RX_ADDR_P0, reinterpret_cast<const uint8_t*>(&pipe0_reading_address), 5);
418 
419  // Flush buffers
420  flush_rx();
421  flush_tx();
422 
423  // Go!
424  ce(HIGH);
425 
426  // wait for the radio to come up (130us actually only needed)
427  delayMicroseconds(130);
428 }
429 
430 /****************************************************************************/
431 
433 {
434  ce(LOW);
435  flush_tx();
436  flush_rx();
437 }
438 
439 /****************************************************************************/
440 
442 {
443  write_register(CONFIG,read_register(CONFIG) & ~_BV(PWR_UP));
444 }
445 
446 /****************************************************************************/
447 
449 {
450  write_register(CONFIG,read_register(CONFIG) | _BV(PWR_UP));
451 }
452 
453 /******************************************************************/
454 
455 bool iBoardRF24::write( const void* buf, uint8_t len )
456 {
457  bool result = false;
458 
459  // Begin the write
460  startWrite(buf,len);
461 
462  // ------------
463  // At this point we could return from a non-blocking write, and then call
464  // the rest after an interrupt
465 
466  // Instead, we are going to block here until we get TX_DS (transmission completed and ack'd)
467  // or MAX_RT (maximum retries, transmission failed). Also, we'll timeout in case the radio
468  // is flaky and we get neither.
469 
470  // IN the end, the send should be blocking. It comes back in 60ms worst case, or much faster
471  // if I tighted up the retry logic. (Default settings will be 1500us.
472  // Monitor the send
473  uint8_t observe_tx;
474  uint8_t status;
475  uint32_t sent_at = millis();
476  const uint32_t timeout = 500; //ms to wait for timeout
477  do
478  {
479  status = read_register(OBSERVE_TX,&observe_tx,1);
480  IF_SERIAL_DEBUG(Serial.print(observe_tx,HEX));
481  }
482  while( ! ( status & ( _BV(TX_DS) | _BV(MAX_RT) ) ) && ( millis() - sent_at < timeout ) );
483 
484  // The part above is what you could recreate with your own interrupt handler,
485  // and then call this when you got an interrupt
486  // ------------
487 
488  // Call this when you get an interrupt
489  // The status tells us three things
490  // * The send was successful (TX_DS)
491  // * The send failed, too many retries (MAX_RT)
492  // * There is an ack packet waiting (RX_DR)
493  bool tx_ok, tx_fail;
494  whatHappened(tx_ok,tx_fail,ack_payload_available);
495 
496  //printf("%u%u%u\r\n",tx_ok,tx_fail,ack_payload_available);
497 
498  result = tx_ok;
499  IF_SERIAL_DEBUG(Serial.print(result?"...OK.":"...Failed"));
500 
501  // Handle the ack packet
502  if ( ack_payload_available )
503  {
504  ack_payload_length = getDynamicPayloadSize();
505  IF_SERIAL_DEBUG(Serial.print("[AckPacket]/"));
506  IF_SERIAL_DEBUG(Serial.println(ack_payload_length,DEC));
507  }
508 
509  // Yay, we are done.
510 
511  // Power down
512  powerDown();
513 
514  // Flush buffers (Is this a relic of past experimentation, and not needed anymore??)
515  flush_tx();
516 
517  return result;
518 }
519 /****************************************************************************/
520 
521 void iBoardRF24::startWrite( const void* buf, uint8_t len )
522 {
523  // Transmitter power-up
524  write_register(CONFIG, ( read_register(CONFIG) | _BV(PWR_UP) ) & ~_BV(PRIM_RX) );
525  delayMicroseconds(150);
526 
527  // Send the payload
528  write_payload( buf, len );
529 
530  // Allons!
531  ce(HIGH);
532  delayMicroseconds(15);
533  ce(LOW);
534 }
535 
536 /****************************************************************************/
537 
539 {
540  uint8_t result = 0;
541 
542  csn(LOW);
543  SPI_RW( R_RX_PL_WID );
544  result = SPI_RW(0xff);
545  csn(HIGH);
546 
547  return result;
548 }
549 
550 /****************************************************************************/
551 
553 {
554  return available(NULL);
555 }
556 
557 /****************************************************************************/
558 
559 bool iBoardRF24::available(uint8_t* pipe_num)
560 {
561  if (!( read_register(FIFO_STATUS) & _BV(RX_EMPTY) )){
562 
563  // If the caller wants the pipe number, include that
564  if ( pipe_num ){
565  uint8_t status = get_status();
566  *pipe_num = ( status >> RX_P_NO ) & 0b111;
567  }
568  return 1;
569  }
570 
571 
572  return 0;
573 }
574 
575 /****************************************************************************/
576 
577 uint8_t iBoardRF24::readPipe(void* buf, uint8_t* pipe){
578  uint8_t status = get_status();
579  bool result = ( status & _BV(RX_DR) );
580  if(! result) return 0;
581  //Read the status once again - see note on page 53
582  status = get_status();
583  *pipe =( status >> RX_P_NO ) & B111;
584  uint8_t len;
585  uint8_t total;
586  uint8_t* current = reinterpret_cast<uint8_t*>(buf);
587 
588  total=0;
589  while(result &&
590  *pipe==((status >> RX_P_NO) & B111) )
591 
592  {
593  len=getDynamicPayloadSize();
594  // Fetch the payload
595  read_payload( current, len );
596  current+=len;
597  total+=len;
598  // Clear the status bit
599  write_register(STATUS,_BV(RX_DR) );
600  // Handle ack payload receipt
601  if ( status & _BV(TX_DS) )
602  {
603  write_register(STATUS,_BV(TX_DS));
604  }
605 
606  if(read_register(FIFO_STATUS) & _BV(RX_EMPTY))
607  return total;
608 
609  status = get_status();
610  result = ( status & _BV(RX_DR) );
611 
612  }
613 
614  return total;
615 
616 }
617 
618 /****************************************************************************/
619 
620 bool iBoardRF24::read( void* buf, uint8_t len )
621 {
622  // Fetch the payload
623  read_payload( buf, len );
624 
625  //Clear the two possible interrupt flags with one command
626  write_register(NRF_STATUS,_BV(RX_DR) | _BV(MAX_RT) | _BV(TX_DS) );
627  // was this the last of the data available?
628 // return read_register(FIFO_STATUS) & _BV(RX_EMPTY);
629 }
630 
631 /****************************************************************************/
632 
633 void iBoardRF24::whatHappened(bool& tx_ok,bool& tx_fail,bool& rx_ready)
634 {
635  // Read the status & reset the status in one easy call
636  // Or is that such a good idea?
637  uint8_t status = write_register(STATUS,_BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT) );
638 
639  // Report to the user what happened
640  tx_ok = status & _BV(TX_DS);
641  tx_fail = status & _BV(MAX_RT);
642  rx_ready = status & _BV(RX_DR);
643 }
644 
645 /****************************************************************************/
646 
647 void iBoardRF24::openWritingPipe(uint64_t value)
648 {
649  // Note that AVR 8-bit uC's store this LSB first, and the NRF24L01(+)
650  // expects it LSB first too, so we're good.
651 
652  write_register(RX_ADDR_P0, reinterpret_cast<uint8_t*>(&value), 5);
653  write_register(TX_ADDR, reinterpret_cast<uint8_t*>(&value), 5);
654 
655  const uint8_t max_payload_size = 32;
656  write_register(RX_PW_P0,min(payload_size,max_payload_size));
657 }
658 
659 /****************************************************************************/
660 
661 static const uint8_t child_pipe[] PROGMEM =
662 {
663  RX_ADDR_P0, RX_ADDR_P1, RX_ADDR_P2, RX_ADDR_P3, RX_ADDR_P4, RX_ADDR_P5
664 };
665 static const uint8_t child_payload_size[] PROGMEM =
666 {
667  RX_PW_P0, RX_PW_P1, RX_PW_P2, RX_PW_P3, RX_PW_P4, RX_PW_P5
668 };
669 static const uint8_t child_pipe_enable[] PROGMEM =
670 {
671  ERX_P0, ERX_P1, ERX_P2, ERX_P3, ERX_P4, ERX_P5
672 };
673 
674 void iBoardRF24::openReadingPipe(uint8_t child, uint64_t address)
675 {
676  // If this is pipe 0, cache the address. This is needed because
677  // openWritingPipe() will overwrite the pipe 0 address, so
678  // startListening() will have to restore it.
679  if (child == 0)
680  pipe0_reading_address = address;
681 
682  if (child <= 6)
683  {
684  // For pipes 2-5, only write the LSB
685  if ( child < 2 )
686  write_register(pgm_read_byte(&child_pipe[child]), reinterpret_cast<const uint8_t*>(&address), 5);
687  else
688  write_register(pgm_read_byte(&child_pipe[child]), reinterpret_cast<const uint8_t*>(&address), 1);
689 
690  write_register(pgm_read_byte(&child_payload_size[child]),payload_size);
691 
692  // Note it would be more efficient to set all of the bits for all open
693  // pipes at once. However, I thought it would make the calling code
694  // more simple to do it this way.
695  write_register(EN_RXADDR,read_register(EN_RXADDR) | _BV(pgm_read_byte(&child_pipe_enable[child])));
696  }
697 }
698 
699 /****************************************************************************/
700 
702 {
703  csn(LOW);
704  SPI_RW( ACTIVATE );
705  SPI_RW( 0x73 );
706  csn(HIGH);
707 }
708 
709 /****************************************************************************/
710 
712 {
713  // Enable dynamic payload throughout the system
714  write_register(FEATURE,read_register(FEATURE) | _BV(EN_DPL) );
715 
716  // If it didn't work, the features are not enabled
717  if ( ! read_register(FEATURE) )
718  {
719  // So enable them and try again
720  toggle_features();
721  write_register(FEATURE,read_register(FEATURE) | _BV(EN_DPL) );
722  }
723 
724  IF_SERIAL_DEBUG(printf("FEATURE=%i\r\n",read_register(FEATURE)));
725 
726  // Enable dynamic payload on all pipes
727  //
728  // Not sure the use case of only having dynamic payload on certain
729  // pipes, so the library does not support it.
730  write_register(DYNPD,read_register(DYNPD) | _BV(DPL_P5) | _BV(DPL_P4) | _BV(DPL_P3) | _BV(DPL_P2) | _BV(DPL_P1) | _BV(DPL_P0));
731 
732  dynamic_payloads_enabled = true;
733 }
734 
735 /****************************************************************************/
736 
738 {
739  //
740  // enable ack payload and dynamic payload features
741  //
742 
743  write_register(FEATURE,read_register(FEATURE) | _BV(EN_ACK_PAY) | _BV(EN_DPL) );
744 
745  // If it didn't work, the features are not enabled
746  if ( ! read_register(FEATURE) )
747  {
748  // So enable them and try again
749  toggle_features();
750  write_register(FEATURE,read_register(FEATURE) | _BV(EN_ACK_PAY) | _BV(EN_DPL) );
751  }
752 
753  IF_SERIAL_DEBUG(printf("FEATURE=%i\r\n",read_register(FEATURE)));
754 
755  //
756  // Enable dynamic payload on pipes 0 & 1
757  //
758 
759  write_register(DYNPD,read_register(DYNPD) | _BV(DPL_P1) | _BV(DPL_P0));
760 }
761 
762 /****************************************************************************/
763 
764 void iBoardRF24::writeAckPayload(uint8_t pipe, const void* buf, uint8_t len)
765 {
766  const uint8_t* current = reinterpret_cast<const uint8_t*>(buf);
767 
768  csn(LOW);
769  SPI_RW( W_ACK_PAYLOAD | ( pipe & B111 ) );
770  const uint8_t max_payload_size = 32;
771  uint8_t data_len = min(len,max_payload_size);
772  while ( data_len-- )
773  SPI_RW(*current++);
774 
775  csn(HIGH);
776 }
777 
778 /****************************************************************************/
779 
781 {
782  bool result = ack_payload_available;
783  ack_payload_available = false;
784  return result;
785 }
786 
787 /****************************************************************************/
788 
790 {
791  return p_variant ;
792 }
793 
794 /****************************************************************************/
795 
796 void iBoardRF24::setAutoAck(bool enable)
797 {
798  if ( enable )
799  write_register(EN_AA, B111111);
800  else
801  write_register(EN_AA, 0);
802 }
803 
804 /****************************************************************************/
805 
806 void iBoardRF24::setAutoAck( uint8_t pipe, bool enable )
807 {
808  if ( pipe <= 6 )
809  {
810  uint8_t en_aa = read_register( EN_AA ) ;
811  if( enable )
812  {
813  en_aa |= _BV(pipe) ;
814  }
815  else
816  {
817  en_aa &= ~_BV(pipe) ;
818  }
819  write_register( EN_AA, en_aa ) ;
820  }
821 }
822 
823 /****************************************************************************/
824 
826 {
827  return ( read_register(CD) & 1 );
828 }
829 
830 /****************************************************************************/
831 
833 {
834  return ( read_register(RPD) & 1 ) ;
835 }
836 
837 /****************************************************************************/
838 
840 {
841  uint8_t setup = read_register(RF_SETUP) ;
842  setup &= ~(_BV(RF_PWR_LOW) | _BV(RF_PWR_HIGH)) ;
843 
844  // switch uses RAM (evil!)
845  if ( level == RF24_PA_MAX )
846  {
847  setup |= (_BV(RF_PWR_LOW) | _BV(RF_PWR_HIGH)) ;
848  }
849  else if ( level == RF24_PA_HIGH )
850  {
851  setup |= _BV(RF_PWR_HIGH) ;
852  }
853  else if ( level == RF24_PA_LOW )
854  {
855  setup |= _BV(RF_PWR_LOW);
856  }
857  else if ( level == RF24_PA_MIN )
858  {
859  // nothing
860  }
861  else if ( level == RF24_PA_ERROR )
862  {
863  // On error, go to maximum PA
864  setup |= (_BV(RF_PWR_LOW) | _BV(RF_PWR_HIGH)) ;
865  }
866 
867  write_register( RF_SETUP, setup ) ;
868 }
869 
870 /****************************************************************************/
871 
873 {
874  rf24_pa_dbm_e result = RF24_PA_ERROR ;
875  uint8_t power = read_register(RF_SETUP) & (_BV(RF_PWR_LOW) | _BV(RF_PWR_HIGH)) ;
876 
877  // switch uses RAM (evil!)
878  if ( power == (_BV(RF_PWR_LOW) | _BV(RF_PWR_HIGH)) )
879  {
880  result = RF24_PA_MAX ;
881  }
882  else if ( power == _BV(RF_PWR_HIGH) )
883  {
884  result = RF24_PA_HIGH ;
885  }
886  else if ( power == _BV(RF_PWR_LOW) )
887  {
888  result = RF24_PA_LOW ;
889  }
890  else
891  {
892  result = RF24_PA_MIN ;
893  }
894 
895  return result ;
896 }
897 
898 /****************************************************************************/
899 
901 {
902  bool result = false;
903  uint8_t setup = read_register(RF_SETUP) ;
904 
905  // HIGH and LOW '00' is 1Mbs - our default
906  wide_band = false ;
907  setup &= ~(_BV(RF_DR_LOW) | _BV(RF_DR_HIGH)) ;
908  if( speed == RF24_250KBPS )
909  {
910  // Must set the RF_DR_LOW to 1; RF_DR_HIGH (used to be RF_DR) is already 0
911  // Making it '10'.
912  wide_band = false ;
913  setup |= _BV( RF_DR_LOW ) ;
914  }
915  else
916  {
917  // Set 2Mbs, RF_DR (RF_DR_HIGH) is set 1
918  // Making it '01'
919  if ( speed == RF24_2MBPS )
920  {
921  wide_band = true ;
922  setup |= _BV(RF_DR_HIGH);
923  }
924  else
925  {
926  // 1Mbs
927  wide_band = false ;
928  }
929  }
930  write_register(RF_SETUP,setup);
931 
932  // Verify our result
933  if ( read_register(RF_SETUP) == setup )
934  {
935  result = true;
936  }
937  else
938  {
939  wide_band = false;
940  }
941 
942  return result;
943 }
944 
945 /****************************************************************************/
946 
948 {
949  rf24_datarate_e result ;
950  uint8_t dr = read_register(RF_SETUP) & (_BV(RF_DR_LOW) | _BV(RF_DR_HIGH));
951 
952  // switch uses RAM (evil!)
953  // Order matters in our case below
954  if ( dr == _BV(RF_DR_LOW) )
955  {
956  // '10' = 250KBPS
957  result = RF24_250KBPS ;
958  }
959  else if ( dr == _BV(RF_DR_HIGH) )
960  {
961  // '01' = 2MBPS
962  result = RF24_2MBPS ;
963  }
964  else
965  {
966  // '00' = 1MBPS
967  result = RF24_1MBPS ;
968  }
969  return result ;
970 }
971 
972 /****************************************************************************/
973 
975 {
976  uint8_t config = read_register(CONFIG) & ~( _BV(CRCO) | _BV(EN_CRC)) ;
977 
978  // switch uses RAM (evil!)
979  if ( length == RF24_CRC_DISABLED )
980  {
981  // Do nothing, we turned it off above.
982  }
983  else if ( length == RF24_CRC_8 )
984  {
985  config |= _BV(EN_CRC);
986  }
987  else
988  {
989  config |= _BV(EN_CRC);
990  config |= _BV( CRCO );
991  }
992  write_register( CONFIG, config ) ;
993 }
994 
995 /****************************************************************************/
996 
998 {
999  rf24_crclength_e result = RF24_CRC_DISABLED;
1000  uint8_t config = read_register(CONFIG) & ( _BV(CRCO) | _BV(EN_CRC)) ;
1001 
1002  if ( config & _BV(EN_CRC ) )
1003  {
1004  if ( config & _BV(CRCO) )
1005  result = RF24_CRC_16;
1006  else
1007  result = RF24_CRC_8;
1008  }
1009 
1010  return result;
1011 }
1012 
1013 /****************************************************************************/
1014 
1016 {
1017  uint8_t disable = read_register(CONFIG) & ~_BV(EN_CRC) ;
1018  write_register( CONFIG, disable ) ;
1019 }
1020 
1021 /****************************************************************************/
1022 void iBoardRF24::setRetries(uint8_t delay, uint8_t count)
1023 {
1024  write_register(SETUP_RETR,(delay&0xf)<<ARD | (count&0xf)<<ARC);
1025 }
1026 
1027 // vim:ai:cin:sts=2 sw=2 ft=cpp
1028 
void toggle_features(void)
Definition: iBoardRF24.cpp:701
uint8_t write_register(uint8_t reg, const uint8_t *buf, uint8_t len)
Definition: iBoardRF24.cpp:78
uint8_t readPipe(void *buf, uint8_t *pipe)
Definition: iBoardRF24.cpp:577
void csn(int mode)
Definition: iBoardRF24.cpp:18
void setChannel(uint8_t channel)
Definition: iBoardRF24.cpp:260
uint8_t getPayloadSize(void)
Definition: iBoardRF24.cpp:279
bool testCarrier(void)
Definition: iBoardRF24.cpp:825
void openWritingPipe(uint64_t address)
Definition: iBoardRF24.cpp:647
bool read(void *buf, uint8_t len)
Definition: iBoardRF24.cpp:620
unsigned char SPI_RW(unsigned char byte)
Definition: iBoardRF24.cpp:30
void writeAckPayload(uint8_t pipe, const void *buf, uint8_t len)
Definition: iBoardRF24.cpp:764
void setCRCLength(rf24_crclength_e length)
Definition: iBoardRF24.cpp:974
void setAutoAck(bool enable)
Definition: iBoardRF24.cpp:796
void setPALevel(rf24_pa_dbm_e level)
Definition: iBoardRF24.cpp:839
rf24_crclength_e getCRCLength(void)
Definition: iBoardRF24.cpp:997
void startListening(void)
Definition: iBoardRF24.cpp:410
rf24_pa_dbm_e getPALevel(void)
Definition: iBoardRF24.cpp:872
void stopListening(void)
Definition: iBoardRF24.cpp:432
bool isAckPayloadAvailable(void)
Definition: iBoardRF24.cpp:780
void enableAckPayload(void)
Definition: iBoardRF24.cpp:737
rf24_datarate_e
Definition: iBoardRF24.h:33
void setRetries(uint8_t delay, uint8_t count)
bool available(void)
Definition: iBoardRF24.cpp:552
void powerDown(void)
Definition: iBoardRF24.cpp:441
uint8_t read_register(uint8_t reg, uint8_t *buf, uint8_t len)
Definition: iBoardRF24.cpp:50
void powerUp(void)
Definition: iBoardRF24.cpp:448
iBoardRF24(uint8_t _cepin, uint8_t _cspin, uint8_t _mosi_pin, uint8_t _miso_pin, uint8_t _sck_pin, uint8_t _irq_pin)
Definition: iBoardRF24.cpp:251
bool testRPD(void)
Definition: iBoardRF24.cpp:832
void setPayloadSize(uint8_t size)
Definition: iBoardRF24.cpp:271
uint8_t flush_rx(void)
Definition: iBoardRF24.cpp:155
void print_address_register(const char *name, uint8_t reg, uint8_t qty=1)
Definition: iBoardRF24.cpp:230
void print_observe_tx(uint8_t value)
Definition: iBoardRF24.cpp:208
void ce(int level)
Definition: iBoardRF24.cpp:25
void disableCRC(void)
bool isPVariant(void)
Definition: iBoardRF24.cpp:789
void openReadingPipe(uint8_t number, uint64_t address)
Definition: iBoardRF24.cpp:674
void printDetails(void)
Definition: iBoardRF24.cpp:319
bool setDataRate(rf24_datarate_e speed)
Definition: iBoardRF24.cpp:900
uint8_t read_payload(void *buf, uint8_t len)
Definition: iBoardRF24.cpp:132
void startWrite(const void *buf, uint8_t len)
Definition: iBoardRF24.cpp:521
uint8_t flush_tx(void)
Definition: iBoardRF24.cpp:168
bool write(const void *buf, uint8_t len)
Definition: iBoardRF24.cpp:455
void begin(void)
Definition: iBoardRF24.cpp:343
uint8_t write_payload(const void *buf, uint8_t len)
Definition: iBoardRF24.cpp:108
uint8_t getDynamicPayloadSize(void)
Definition: iBoardRF24.cpp:538
rf24_pa_dbm_e
Definition: iBoardRF24.h:26
void print_byte_register(const char *name, uint8_t reg, uint8_t qty=1)
Definition: iBoardRF24.cpp:219
void whatHappened(bool &tx_ok, bool &tx_fail, bool &rx_ready)
Definition: iBoardRF24.cpp:633
void enableDynamicPayloads(void)
Definition: iBoardRF24.cpp:711
rf24_datarate_e getDataRate(void)
Definition: iBoardRF24.cpp:947
void print_status(uint8_t status)
Definition: iBoardRF24.cpp:194
uint8_t get_status(void)
Definition: iBoardRF24.cpp:181
rf24_crclength_e
Definition: iBoardRF24.h:40