Library for the nRF2401A Transceiver
Dependents: nRF2401A_Hello_World nRF2401A_Wireless_Accelerometer_joypad nRF2401A_Gameduino_Invaders
nRF2401A.cpp
00001 /** 00002 *@section DESCRIPTION 00003 * mbed nRF2401A Library 00004 *@section LICENSE 00005 * Copyright (c) 2011, Per Söderstam 00006 * 00007 * Permission is hereby granted, free of charge, to any person obtaining a copy 00008 * of this software and associated documentation files (the "Software"), to deal 00009 * in the Software without restriction, including without limitation the rights 00010 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00011 * copies of the Software, and to permit persons to whom the Software is 00012 * furnished to do so, subject to the following conditions: 00013 * 00014 * The above copyright notice and this permission notice shall be included in 00015 * all copies or substantial portions of the Software. 00016 * 00017 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00018 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00019 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00020 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00021 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00022 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 00023 * THE SOFTWARE. 00024 * @file "nRF2401A.cpp" 00025 */ 00026 00027 #include "nRF2401A.h " 00028 00029 #define Ts 1 /**< Setup time from data to rising clock edge on write (accualy 500 ns). */ 00030 #define Th 1 /**< Hold time from rising clock to data toggle/falling clock (accualy 500 ns). */ 00031 #define Tcs2data 5 /**< Min delay from CS assert to data, in us. */ 00032 #define Tce2data 5 /**< Min delay from CE assert to data, in us. */ 00033 #define Td 1 /**< Minimum delay between edges (actually 50 ns). */ 00034 #define Tpd2cfgm 3 /**< Minimum delay from power up of tranciever to configuration. */ 00035 #define Tsby2txSB 195 /**< Minimum delay from tx initation to air, in us. */ 00036 #define Tsby2rx 202 /**< Minimum delay from stanby to rx mode, in us. */ 00037 #define Thmin 5 /**< */ 00038 #define Tclk2data 1 /**< */ 00039 #define MAXIMUM_ADDR_LENGTH 40 /**< */ 00040 00041 00042 nRF2401A::nRF2401A(PinName ce, 00043 PinName cs, 00044 PinName dr1, 00045 PinName clk1, 00046 PinName data) 00047 : 00048 _ce(DigitalOut(ce)), 00049 _cs(DigitalOut(cs)), 00050 _dr1(DigitalIn(dr1)), 00051 _clk1(DigitalOut(clk1)), 00052 _data(DigitalInOut(data)), 00053 _state(nRF2401A::STANDBY), 00054 _rx_handler((nRF2401A_rx_handler_t) 0), 00055 _rx_handler_arg((void *) 0), 00056 _dr1_isr(InterruptIn(dr1)) { 00057 00058 // init member variables 00059 _data.output(); 00060 // set defaults 00061 _ctrl_packet_buf.crc_config = NO_CRC; 00062 _ctrl_packet_buf.rf_data_rate = BIT_RATE_250KBITS; 00063 _ctrl_packet_buf.rf_channel = 0x02; 00064 _ctrl_packet_buf.channel_1_data_payload_len = 0x20; 00065 // setup... 00066 _ctrl_packet = (uint8_t *) &_ctrl_packet_buf; 00067 _dr1_isr.rise(this, &nRF2401A::dataReadyHandler); 00068 // ...tranceiver in standby... 00069 _ce = 0; 00070 _cs = 0; 00071 // ...and clear receive buffer 00072 for (int i = 0; i < 16; i++) 00073 _data_buf[i] = 0x0; 00074 // ...set imutable control fields... 00075 _ctrl_packet_buf.enable_dual_channel_mode = 0x0; // single channel receive 00076 _ctrl_packet_buf.communication_mode = 0x1; // ShockBurst mode 00077 _ctrl_packet_buf.xo_frequency = 0x3; // 16 MHz crystal 00078 _ctrl_packet_buf.rf_power = 0x3; // 0 dBm (1 mW) output power 00079 // ...start in RX mode 00080 _ctrl_packet_buf.txr_switch = nRF2401A::RX_MODE; 00081 _state = nRF2401A::RX ; 00082 // assure minimum wake up time while assuming tranceiver powers up with uP 00083 wait_ms(Tpd2cfgm); 00084 00085 return; 00086 } 00087 00088 /* Public functions */ 00089 00090 /* Print control packet 00091 * Print the control packet to a serial port 00092 * @param arg Pointer to the port to transmit on 00093 * @return bool for correct parameters supplied 00094 */ 00095 bool nRF2401A::printControlPacket(Serial& port) 00096 { 00097 bool ok = false; 00098 if (port != NULL) 00099 { 00100 for(int i = 0; i < sizeof(_ctrl_packet_buf); i++) 00101 { 00102 port.printf("%02x ", _ctrl_packet[i]); 00103 } 00104 port.printf("\n\r"); 00105 ok = true; 00106 } 00107 return ok; 00108 } 00109 00110 /* Print data packet 00111 * Print the data packet to a serial port 00112 * @param arg Pointer to the port to transmit on 00113 * @return bool for correct parameters supplied 00114 */ 00115 bool nRF2401A::printDataPacket(Serial& port) 00116 { 00117 bool ok = false; 00118 if (port != NULL) 00119 { 00120 for(int i = 0; i < sizeof(_data_buf); i++) 00121 { 00122 port.printf("%02x ", _data_buf[i]); 00123 } 00124 port.printf("\r"); 00125 ok = true; 00126 } 00127 return ok; 00128 } 00129 00130 /* Send the control packet to the nRF2401A. 00131 * This function transfer the control packet image to the nRF2401A. 00132 * @return bool for successfull flushing of the packet 00133 */ 00134 bool nRF2401A::flushControlPacket() { 00135 bool flush = false; 00136 switch (_state) { 00137 case nRF2401A::RX: 00138 pushCtrl(_ctrl_packet, 15 << 3 ); 00139 _state = nRF2401A::RX; 00140 _ce = 1; 00141 _cs = 0; 00142 flush = true; 00143 break; 00144 case nRF2401A::STANDBY: 00145 pushCtrl(_ctrl_packet, 15 << 3 ); 00146 _state = nRF2401A::STANDBY; 00147 _ce = 0; 00148 _cs = 0; 00149 flush = true; 00150 break; 00151 case nRF2401A::TX: 00152 default: 00153 _ce = 0; 00154 _cs = 0; 00155 } 00156 return flush; 00157 } 00158 00159 /* Register a receive action callback. 00160 * Attach a callback that will be called when the tranceiver intercept a 00161 * message. This callback will be called in the context of an interrupt 00162 * routine and should act accordingly. 00163 * @param handler The callback, of type nRF2401_rx_handler_t. 00164 * @param arg Pointer to data supplied to the handler at call time. 00165 * @return Reference to the invoked object (for chaining operations). 00166 */ 00167 bool nRF2401A::attachRXHandler(nRF2401A_rx_handler_t handler, void *arg) 00168 { 00169 bool ok = false; 00170 if (handler != NULL) 00171 { 00172 _rx_handler = handler; 00173 _rx_handler_arg = arg; 00174 ok = true; 00175 } 00176 return ok; 00177 } 00178 00179 /* Set the payload length, in bits. 00180 * Set the control packet field for length, in number of bits, of the message payload. 00181 * @param n Number of bits of the message payload. 00182 * @return void 00183 */ 00184 void nRF2401A::setDataPayloadLength(uint8_t n) 00185 { 00186 _ctrl_packet_buf.channel_1_data_payload_len = n; 00187 } 00188 00189 /* Set the address of channel 1. 00190 * The channel address is a up to 40 bit number identifying the tranceiver. 00191 * @param addr4 Bits 39-32 of the address. 00192 * @param addr4 Bits 31-24 of the address. 00193 * @param addr4 Bits 23-16 of the address. 00194 * @param addr4 Bits 15-8 of the address. 00195 * @param addr4 Bits 7-0 of the address. 00196 * @param n_bits Number of bits used in the address. 00197 * @return bool for correct settings supplied 00198 */ 00199 bool nRF2401A::setAddress(uint8_t addr4, uint8_t addr3, uint8_t addr2, uint8_t addr1, uint8_t addr0, uint8_t n_bits) 00200 { 00201 bool ok = false; 00202 if (n_bits <= MAXIMUM_ADDR_LENGTH) 00203 { 00204 _ctrl_packet_buf.channel_1_address[0] = addr4; 00205 _ctrl_packet_buf.channel_1_address[1] = addr3; 00206 _ctrl_packet_buf.channel_1_address[2] = addr2; 00207 _ctrl_packet_buf.channel_1_address[3] = addr1; 00208 _ctrl_packet_buf.channel_1_address[4] = addr0; 00209 _ctrl_packet_buf.channel_address_len = n_bits; 00210 ok = true; 00211 } 00212 return ok; 00213 } 00214 00215 /* Set CRC use. 00216 * Set the CRC mode field of the control packet. Defaults to no CRC. 00217 * @param mode The CRC mode of choise. 00218 * @return bool for correct parameter supplied 00219 */ 00220 bool nRF2401A::setCRCMode(CRC_T mode) 00221 { 00222 bool ok = false; 00223 if (mode < INVALID_CRC) 00224 { 00225 _ctrl_packet_buf.crc_config = mode; 00226 ok = true; 00227 } 00228 return ok; 00229 } 00230 00231 /* Set RF power use. 00232 * Set the RF power field of the control packet. Defaults to full power. 00233 * @param power The RF power of choise. 00234 * @return bool for correct parameter supplied 00235 */ 00236 bool nRF2401A::setRFpower(RF_POWER_T power) 00237 { 00238 bool ok = false; 00239 if (power < INVALID_POWER) 00240 { 00241 _ctrl_packet_buf.rf_power = power; 00242 ok = true; 00243 } 00244 return ok; 00245 } 00246 00247 /* Set tranceiver data rate. 00248 * Sets the data rate field to either 250 kbit/s or 1 Mbit/s data transfer rate. 00249 * Defaults to 250 kbit/s. 00250 * @param mode The data rate of choise. 00251 * @return bool for correct parameter supplied 00252 */ 00253 bool nRF2401A::setDataRate(DATA_RATE_T data_rate) 00254 { 00255 bool ok = false; 00256 if ( data_rate < INVALID_RATE) 00257 { 00258 _ctrl_packet_buf.rf_data_rate = data_rate; 00259 ok = true; 00260 } 00261 return ok; 00262 } 00263 00264 /** Set RF channel. 00265 * Sets the control packet field for channel number. Channel numbers are from 0 to 127 00266 * representing channel frequencies equal to (2400 + channel number) MHz. Defaults to channel 1. 00267 * @param ch Channel number, from the range [0, 127]. 00268 * @return boolean to confirm valid parameters have been supplied 00269 */ 00270 bool nRF2401A::setChannel(uint8_t ch) 00271 { 00272 bool result = false; 00273 if (ch < 128) 00274 { 00275 _ctrl_packet_buf.rf_channel = ch; 00276 result = true; 00277 } 00278 return result; 00279 } 00280 00281 /* Read a message. 00282 * This routine will transfer the data from the receive buffer to the buffer 00283 * supplied. It will transfer a number of Bytes equal to the specified length. 00284 * @param msg_buf Message buffer. 00285 * @param msg_len Length of message, in bytes. 00286 * @return boolean to confirm if valid parameters have been supplied 00287 */ 00288 bool nRF2401A::readMsg( uint8_t *msg_buf, uint8_t msg_len ) { 00289 bool result = false; 00290 if ((msg_buf != NULL) && (msg_len <= DATA_BUFFER_SIZE)) 00291 { 00292 for(int i = 0; i < msg_len; i++) 00293 { 00294 msg_buf[i] = _data_buf[i]; 00295 } 00296 result = true; 00297 } 00298 return result; 00299 } 00300 00301 /* Read a byte from message. 00302 * This routine will transfer the data from the receive buffer to the buffer 00303 * supplied. It will transfer one Bytes at index buf_index. 00304 * @param msg_buf Message body. 00305 * @param buf_index index of byte to be read. 00306 * @return one Byte of the message buffer 00307 */ 00308 uint8_t nRF2401A::readMsg_byte( uint8_t buf_index ) { 00309 return _data_buf[buf_index]; 00310 } 00311 00312 /** Send a message. 00313 * This routine will transfer the data from the supplied buffer and send 00314 * it to the specified address using the current control packet settings. 00315 * @param addr The address to send to. 00316 * @param addr_len Length of address, in bits. 00317 * @param msg_buf Message body. 00318 * @param msg_len Length of message, in bits. 00319 * @return Reference to the invoked object (for chaining operations). 00320 */ 00321 bool nRF2401A::sendMsg(nRF2401A::address_t addr, uint8_t addr_len, uint8_t *msg_buf, uint8_t msg_len) { 00322 bool sent = false; 00323 if ((msg_buf != NULL) && (addr_len <= MAXIMUM_ADDR_LENGTH)) 00324 { 00325 // point to start of address byte in address 00326 uint8_t *aligned_addr = &addr[sizeof(address_t) - (addr_len / 8)]; 00327 // wait for tx completion 00328 int Toa = (_ctrl_packet_buf.rf_data_rate == nRF2401A::BIT_RATE_1MBITS ? 1 : 4) * (addr_len + msg_len + 1 + 16); 00329 00330 switch (_state) { 00331 case nRF2401A::STANDBY: 00332 //come out of standby into RX mode 00333 standby_mode(true); 00334 case nRF2401A::TX: 00335 //wait while in tx mode 00336 while (_state == nRF2401A::TX ) { 00337 } 00338 case nRF2401A::RX: 00339 // switch to transmit 00340 transmit_mode(); 00341 // push out the bits 00342 _data = nRF2401A::TX_MODE; 00343 wait_us(Ts); 00344 _clk1 = 1; 00345 wait_us(Th); 00346 _clk1 = 0; 00347 // wait Td 00348 wait_us(Td); 00349 // deassert CS/CE and done... 00350 _cs = 0; 00351 _ce = 0; 00352 00353 // zero control and data lines 00354 _clk1 = 0; 00355 _data = 0; 00356 // wait Td 00357 wait_us(Td); 00358 // assert CE and wait Tcs2data 00359 _ce = 1; 00360 wait_us(Tce2data); 00361 // push out the address bits 00362 for (int i = 0; i < addr_len; i++) { 00363 _data = ((0x80 >> (i % 8)) & aligned_addr[i / 8]) ? 0x1 : 0x0; 00364 wait_us(Ts); 00365 _clk1 = 1; 00366 wait_us(Th); 00367 _clk1 = 0; 00368 } 00369 // push out the message bits 00370 for (int i = 0; i < msg_len; i++) { 00371 _data = ((0x80 >> (i % 8)) & msg_buf[i / 8]) ? 0x1 : 0x0; 00372 wait_us(Ts); 00373 _clk1 = 1; 00374 wait_us(Th); 00375 _clk1 = 0; 00376 } 00377 // reset data 00378 _data = 0; 00379 // deassert CE will initiate transmission 00380 _ce = 0; 00381 wait_us(Tsby2txSB + Toa); 00382 00383 // switch back to receive 00384 receive_mode(); 00385 sent = true; 00386 break; 00387 } 00388 } 00389 return sent; 00390 } 00391 00392 00393 /* Put the tranceiver into, or bring out of standby. 00394 * Tx mode 10.5mA, RX mode 18mA, Standby 400nA. 00395 * @param active set standby state 00396 */ 00397 nRF2401A::STATE_T nRF2401A::standby_mode(bool active) { 00398 switch (_state) { 00399 case nRF2401A::TX: 00400 //wait while in tx mode 00401 while (_state == nRF2401A::TX ) { 00402 } 00403 case nRF2401A::RX: 00404 if (!active) { 00405 _state = nRF2401A::STANDBY; 00406 _ce = 0; 00407 _cs = 0; 00408 wait_us(Tsby2rx); 00409 } 00410 break; 00411 case nRF2401A::STANDBY: 00412 if (active) { 00413 _state = nRF2401A::RX; 00414 _ce = 1; 00415 _cs = 0; 00416 } 00417 break; 00418 } 00419 return _state; 00420 } 00421 00422 /* Private functions */ 00423 00424 /* transmit_mode 00425 * 00426 * put the transceiver into transmit mode 00427 */ 00428 void nRF2401A::transmit_mode( void ) { 00429 _ce = 0; 00430 _cs = 0; 00431 wait_us(Td); 00432 // assert CS/CE and wait Tcs2data 00433 _ce = 0; 00434 _cs = 1; 00435 wait_us(Tcs2data); 00436 _state = nRF2401A::TX; 00437 } 00438 00439 /* receive_mode 00440 * 00441 * put the transceiver into receive mode 00442 */ 00443 void nRF2401A::receive_mode( void ) { 00444 wait_us(Td); 00445 // assert CS/CE and wait Tcs2data 00446 _cs = 1; 00447 wait_us(Tcs2data); 00448 // push out the bits 00449 _data = nRF2401A::RX_MODE; 00450 wait_us(Ts); 00451 _clk1 = 1; 00452 wait_us(Th); 00453 _clk1 = 0; 00454 // wait Td 00455 wait_us(Td); 00456 _data = 0; 00457 // deassert CS/CE and done... 00458 _cs = 0; 00459 // wait Td to avoid simultaineous control high 00460 wait_us(Td); 00461 _ce = 1; 00462 // done 00463 _state = nRF2401A::RX; 00464 } 00465 00466 /* dataReadyHandler 00467 * 00468 * handle the incoming data and call callback 00469 */ 00470 void nRF2401A::dataReadyHandler(void) { 00471 switch (_state) { 00472 case nRF2401A::RX: 00473 pull(_data_buf); 00474 if (_rx_handler != (nRF2401A_rx_handler_t) 0) 00475 _rx_handler(_rx_handler_arg); 00476 break; 00477 default: 00478 // todo: error msg 00479 break; 00480 } 00481 return; 00482 } 00483 00484 /* pull 00485 * 00486 * Pull the data from the transceiver 00487 */ 00488 int nRF2401A::pull(uint8_t *buf) { 00489 int n = 0; 00490 00491 // read from data pin 00492 _data.input(); 00493 // init signals, go to standby 00494 _ce = 1; 00495 _cs = 0; 00496 _clk1 = 0; 00497 // ensure time from DR 00498 wait_us(Td); 00499 00500 while (_dr1 == 1) { 00501 _clk1 = 1; 00502 wait_us(Thmin); 00503 if(_data.read()) 00504 buf[n / 8] |= (0x80 >> (n % 8)); 00505 else 00506 buf[n / 8] &= ~(0x80 >> (n % 8)); 00507 n++; 00508 _clk1 = 0; 00509 wait_us(Thmin); 00510 } 00511 // return to active 00512 _ce = 1; 00513 // reset data pin direction 00514 _data.output(); 00515 00516 return n; 00517 } 00518 00519 /* pushCtrl 00520 * 00521 * Push the data to the transceiver 00522 */ 00523 void nRF2401A::pushCtrl(uint8_t *buf, uint8_t n_bits, bool is_ctrl) { 00524 00525 DigitalOut &ctrl_pin = is_ctrl ? _cs : _ce; 00526 00527 // set data to output 00528 _data.output(); 00529 // zero control and data lines 00530 _cs = 0; 00531 _ce = 0; 00532 _clk1 = 0; 00533 _data = 0; 00534 // wait Td 00535 wait_us(Td); 00536 // assert CS/CE and wait Tcs2data 00537 ctrl_pin = 1; 00538 wait_us(Tcs2data); 00539 // push out the bits 00540 for (int i = 0; i < n_bits; i++) { 00541 _data = ((0x80 >> (i % 8)) & buf[i / 8]) ? 0x1 : 0x0; 00542 wait_us(Ts); 00543 _clk1 = 1; 00544 wait_us(Th); 00545 _clk1 = 0; 00546 } 00547 _data = 0; 00548 // wait Td 00549 wait_us(Td); 00550 // deassert CS/CE and done... 00551 ctrl_pin = 0; 00552 00553 return; 00554 }
Generated on Tue Jul 12 2022 16:33:44 by 1.7.2