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