For robots and stuff

Dependents:   Base Station

Committer:
jjones646
Date:
Wed Dec 31 22:16:01 2014 +0000
Revision:
2:c42a035d71ed
Parent:
1:05a48c038381
adding dummy cc1101 support

Who changed what in which revision?

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