Basic port of the gcopeland nRF24L01 library

Dependencies:   mbed

Committer:
iforce2d
Date:
Mon Mar 25 07:35:02 2019 +0000
Revision:
2:75a5b58b2338
Basic port of gcopeland nRF24L01 library

Who changed what in which revision?

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