Maniacbug's nRF24L01+ arduino library ported to mbed. Functional with minor issues.

Committer:
Christilut
Date:
Fri Apr 05 10:18:40 2013 +0000
Revision:
2:a483f426d380
Parent:
1:d061e50ccc5d
Child:
4:491267614a10
Working, some issues

Who changed what in which revision?

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