Library for the nRF2401A Transceiver

Dependents:   nRF2401A_Hello_World nRF2401A_Wireless_Accelerometer_joypad nRF2401A_Gameduino_Invaders

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers nRF2401A.cpp Source File

nRF2401A.cpp

Go to the documentation of this file.
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 }