For robots and stuff
Wireless/nRF24L01/nRF24L01.cpp@0:c5afea7b9057, 2014-12-28 (annotated)
- Committer:
- jjones646
- Date:
- Sun Dec 28 06:27:18 2014 +0000
- Revision:
- 0:c5afea7b9057
initial commit;
Who changed what in which revision?
User | Revision | Line number | New 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 | } |