A Atmel RF2xx Radio Library for Mbed

Dependents:   xBedRadio MxSniffer

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers MxRadio.cpp Source File

MxRadio.cpp

00001 /* Copyright (c) 2011 Frank Zhao
00002    All rights reserved.
00003 
00004    Redistribution and use in source and binary forms, with or without
00005    modification, are permitted provided that the following conditions
00006    are met:
00007 
00008  * Redistributions of source code must retain the above copyright
00009      notice, this list of conditions and the following disclaimer.
00010  * Redistributions in binary form must reproduce the above copyright
00011      notice, this list of conditions and the following disclaimer in the
00012      documentation and/or other materials provided with the distribution.
00013  * Neither the name of the authors nor the names of its contributors
00014      may be used to endorse or promote products derived from this software
00015      without specific prior written permission.
00016 
00017    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00018    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020    ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00021    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00022    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00023    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00024    INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00025    CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00026    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00027    POSSIBILITY OF SUCH DAMAGE. */
00028 
00029 #include "MxRadio.h"
00030 #include "MxRadioEvents.h"
00031 //#define radio_set_state radio_force_state
00032 
00033 // the write function checks if beginTransmission was called prior to write
00034 // in order to determine whether to use immediate or non-immediate transmission
00035 
00036 const uint8_t HeadSize=9;
00037 
00038 // a busy indicator so transmit functions can wait until the last transmission has finished
00039 volatile uint8_t txIsBusy = 0;
00040 
00041 
00042 cMxRadio::~cMxRadio()
00043 {
00044 }
00045 // empty constructor, should not be called by user
00046 cMxRadio::cMxRadio(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName rst, PinName slp, PinName irq)
00047 :m_spi(mosi, miso, sclk), m_cs(cs), reset_pin(rst), sleep_pin(slp),irq_pin(irq)
00048 {
00049     // default event handlers
00050     
00051     zrEventTxDone=0;
00052     zrEventReceiveFrame=0;
00053     temprssi=0;
00054     setautotx=false;
00055     setautorx=false;
00056     needack=false;
00057     usedBeginTransmission = 0;
00058     hasAttachedTxEvent = 0;
00059     hasAttachedRxEvent = 0;
00060     lastLqi = 0;
00061     lastRssi = 0;
00062     txTmpBufferLength = 0;
00063     rxRingBufferHead = 0;
00064     rxRingBufferTail = 0;
00065     /*
00066     user_radio_tx_done=0;
00067     user_radio_receive_frame=0;
00068     user_radio_irq=0;
00069     user_radio_error=0;
00070     */
00071     zr_attach_receive_frame(&cMxRadio::onReceiveFrame);
00072     zr_attach_tx_done(&cMxRadio::onTxDone);
00073 
00074 }
00075 
00076 /**
00077  * @brief Radio Initialization
00078  *
00079  * The function initializes all IO ressources,
00080  * needed for the usage of the radio and performs
00081  * a reset to the radio.
00082  * It prepares the frame header.
00083  * Then it sets the channel number and defaults to RX state.
00084  *
00085  * @param chan the channel number for the radio to use, 11 to 26
00086  */
00087 void cMxRadio::begin(channel_t chan)
00088 {
00089     begin(chan, 0);
00090 }
00091 
00092 void cMxRadio::begin(channel_t chan,uint16_t panid,uint16_t localaddress,bool needackval,bool autotxval,bool autorxval,char autoretrycount)
00093 {
00094     setautotx=autotxval;
00095     setautorx=autorxval;
00096     needack=needackval;
00097     radio_init(rxFrameBuffer, MAX_FRAME_SIZE);
00098 
00099     //////////////////////////////
00100 #ifdef SR_MAX_FRAME_RETRES
00101     trx_bit_write(SR_MAX_FRAME_RETRES,autoretrycount & 0Xf);//for auto wake up
00102     //////////////////////////////
00103 #endif
00104 
00105 
00106     if(!needack)
00107         txTmpBuffer[0] = 0x41;
00108     else
00109         txTmpBuffer[0] = 0x61; //ack required
00110     txTmpBuffer[1] = 0x88;
00111     txTmpBuffer[2] =  0;
00112     txTmpBuffer[3]=(uint8_t)(panid & 0xFF );
00113     txTmpBuffer[4]=(uint8_t)((panid>>8) & 0xFF );
00114     txTmpBuffer[5] = 0xFF; //dest address low byte
00115     txTmpBuffer[6] = 0xFF; //dest address hight byte
00116     txTmpBuffer[7] = (uint8_t)(localaddress & 0xFF );
00117     txTmpBuffer[8] = (uint8_t)((localaddress>>8) & 0xFF );
00118     setParam(phyPanId,(uint16_t)panid );
00119     setParam(phyShortAddr,(uint16_t)localaddress );
00120 
00121     radio_set_param(RP_CHANNEL(chan));
00122 
00123     // default to receiver
00124     if (setautorx)
00125         radio_set_state(STATE_RXAUTO);
00126     else
00127         radio_set_state(STATE_RX);
00128 #ifdef ENABLE_DIG3_DIG4
00129     trx_bit_write(SR_PA_EXT_EN, 1);
00130 #endif
00131 }
00132 void cMxRadio::begin(channel_t chan,uint16_t panid,uint16_t localaddress,bool needackval,bool autotxval,bool autorxval)
00133 {
00134     cMxRadio::begin(chan,panid,localaddress,needackval,autotxval,autorxval,4);
00135 
00136 }
00137 void cMxRadio::sendFrame(uint16_t destaddress,bool needackval,uint8_t* frm, uint8_t len)
00138 {
00139     uint8_t oldvalue=txTmpBuffer[0];
00140     if(!needackval)
00141         txTmpBuffer[0] = 0x41;
00142     else
00143         txTmpBuffer[0] = 0x61;
00144     beginTransmission(destaddress);
00145     write(frm,len);
00146     endTransmission();
00147     txTmpBuffer[0]=oldvalue;
00148 
00149 }
00150 /**
00151  * @brief Radio Initialization
00152  *
00153  * Overload for radio initalization that allows for the user to set a custom frame header
00154  *
00155  * @param chan channel number for the radio to use, 11 to 26
00156  * @param frameHeader HeadSize byte custom frame header
00157  */
00158 void cMxRadio::begin(channel_t chan, uint8_t* frameHeader)
00159 {
00160     radio_init(rxFrameBuffer, MAX_FRAME_SIZE);
00161 
00162     if (frameHeader)
00163     {
00164         // copy custom frame header
00165         int i;
00166         for (i = 0; i < HeadSize; i++)
00167             txTmpBuffer[i] = frameHeader[i];
00168     }
00169     else
00170     {
00171         txTmpBuffer[0] = 0x41;
00172         txTmpBuffer[1] = 0x88;
00173         txTmpBuffer[2] =  0;
00174         txTmpBuffer[3]=0xCD;
00175         txTmpBuffer[4]=0xAB;
00176         txTmpBuffer[5] = 0xFF; //dest address low byte
00177         txTmpBuffer[6] = 0xFF; //dest address hight byte
00178         txTmpBuffer[7] = 0x01;;
00179         txTmpBuffer[8] = 0x00;;
00180     }
00181 
00182     // set the channel
00183     radio_set_param(RP_CHANNEL(chan));
00184 
00185     // default to receiver
00186     if (setautorx)
00187         radio_set_state(STATE_RXAUTO);
00188     else
00189         radio_set_state(STATE_RX);
00190 
00191 #ifdef ENABLE_DIG3_DIG4
00192     trx_bit_write(SR_PA_EXT_EN, 1);
00193 #endif
00194 
00195 }
00196 
00197 /**
00198  * @brief Set Frame Header
00199  *
00200  * changes the custom frame header
00201  *
00202  * @param frameHeader HeadSize byte custom frame header
00203  */
00204 void cMxRadio::setFrameHeader(uint8_t* frameHeader)
00205 {
00206     // copy custom frame header
00207     int i;
00208     for (i = 0; i < HeadSize; i++)
00209         txTmpBuffer[i] = frameHeader[i];
00210 }
00211 
00212 /**
00213  * @brief Attach Error Event Handler
00214  *
00215  * Allows the user to set a error handling function
00216  * An empty one is used if none is set
00217  *
00218  * @param funct the function pointer to the event handler
00219  */
00220 void cMxRadio::attachError(void (*funct)(radio_error_t))
00221 {
00222     user_radio_error = funct;
00223 }
00224 
00225 /**
00226  * @brief Attach IRQ Event Handler
00227  *
00228  * Allows the user to set a IRQ handling function
00229  * An empty one is used if none is set
00230  *
00231  * @param funct the function pointer to the event handler
00232  */
00233 void cMxRadio::attachIrq(void (*funct)(uint8_t))
00234 {
00235     user_radio_irq = funct;
00236 }
00237 
00238 /**
00239  * @brief Attach RX Event Handler
00240  *
00241  * Allows the user to set a RX handling function
00242  * The default handler will read in the received frame and place it into the RX FIFO ring buffer
00243  * If the user chooses to use this attach function, then the default handler will not be used
00244  * This means read/peek/available/flush will stop working
00245  *
00246  * @param funct the function pointer to the event handler
00247  */
00248 void cMxRadio::attachReceiveFrame(uint8_t* (*funct)(uint8_t, uint8_t*, uint8_t,int8_t, uint8_t))
00249 {
00250     zrEventReceiveFrame = funct;
00251     hasAttachedRxEvent = (funct == 0) ? 0 : 1;
00252 }
00253 
00254 /**
00255  * @brief Attach TX Complete Event Handler
00256  *
00257  * Allows the user to set a TX complete handling function
00258  * An empty one is used if none is set
00259  * The event will occur before the busy flag is reset and returning to RX state
00260  *
00261  * @param funct the function pointer to the event handler
00262  */
00263 void cMxRadio::attachTxDone(void (*funct)(radio_tx_done_t))
00264 {
00265     zrEventTxDone = funct;
00266     hasAttachedTxEvent = (funct == 0) ? 0 : 1;
00267 }
00268 
00269 /**
00270  * @brief Default RX Event Handler
00271  *
00272  * If the user has not attached a custom event handler, then the bytes are placed into the FIFO ring buffer
00273  * If the frame contains a header, then the frame header is ignored, only the payload is read
00274  * The above does not occur if a user handler is attached, which will be called instead
00275  * The LQI and RSSI is always remembered
00276  *
00277  * This should not be called by the user
00278  *
00279  * @param len length of the frame
00280  * @param frm array containing frame data
00281  * @param lqi link quality indicator
00282  * @param crc_fail boolean indicating whether the received frame failed FCS verification, not used
00283  */
00284 uint8_t* cMxRadio::onReceiveFrame(uint8_t len, uint8_t* frm, uint8_t lqi, int8_t ed,uint8_t crc_fail)
00285 {
00286     if (crc_fail)
00287         return rxRingBuffer;
00288     lastLqi = lqi;
00289     //lastRssi=ed;
00290     if (hasAttachedRxEvent == 0)
00291     {
00292         // no event handler, so write it into the FIFO
00293 
00294         if (len >= HeadSize-1)
00295         {
00296             // frame header exists
00297             // copy only payload
00298 
00299             for (uint8_t i = HeadSize; i < len - 2; i++)
00300             {
00301                 uint16_t j = ((uint16_t)((uint16_t)rxRingBufferHead + 1)) % ZR_FIFO_SIZE;
00302                 if (j != rxRingBufferTail)
00303                 {
00304                     // push into FIFO
00305                     rxRingBuffer[rxRingBufferHead] = frm[i];
00306                     rxRingBufferHead = j;
00307                 }
00308                 else
00309                 {
00310                     // FIFO full
00311                     break;
00312                 }
00313             }
00314         }
00315         else
00316         {
00317             // frame header does not exist
00318             // copy everything
00319 
00320             for (uint8_t i = 0; i < len; i++)
00321             {
00322                 uint16_t j = ((uint16_t)((uint16_t)rxRingBufferHead + 1)) % ZR_FIFO_SIZE;
00323                 if (j != rxRingBufferTail)
00324                 {
00325                     // push into FIFO
00326                     rxRingBuffer[rxRingBufferHead] = frm[i];
00327                     rxRingBufferHead = j;
00328                 }
00329                 else
00330                 {
00331                     // FIFO full
00332                     break;
00333                 }
00334             }
00335         }
00336 
00337         return rxRingBuffer;
00338     }
00339     else
00340     {
00341         // user event is attached so call it
00342         return zrEventReceiveFrame(len, frm, lqi, ed,crc_fail);
00343     }
00344 }
00345 
00346 /**
00347  * @brief RX Buffer Flush
00348  *
00349  * Flush the RX FIFO ring buffer
00350  */
00351 void cMxRadio::flush()
00352 {
00353     rxRingBufferHead = rxRingBufferTail;
00354 }
00355 
00356 /**
00357  * @brief RX Buffer Read
00358  *
00359  * pops and returns the next byte from the FIFO ring buffer
00360  *
00361  * @return the next byte, or -1 if buffer is empty
00362  */
00363 int16_t cMxRadio::read()
00364 {
00365     // if the head isn't ahead of the tail, we don't have any characters
00366     if (rxRingBufferHead == rxRingBufferTail)
00367     {
00368         return -1;
00369     }
00370     else
00371     {
00372         uint8_t c = rxRingBuffer[rxRingBufferTail];
00373         rxRingBufferTail = (rxRingBufferTail + 1) % ZR_FIFO_SIZE; // pop
00374         return c;
00375     }
00376 }
00377 
00378 /**
00379  * @brief RX Buffer Peek
00380  *
00381  * returns the next byte from the FIFO ring buffer without removing it
00382  *
00383  * @return the next byte, or -1 if buffer is empty
00384  */
00385 int16_t cMxRadio::peek()
00386 {
00387     // if the head isn't ahead of the tail, we don't have any characters
00388     if (rxRingBufferHead == rxRingBufferTail)
00389     {
00390         return -1;
00391     }
00392     else
00393     {
00394         uint8_t c = rxRingBuffer[rxRingBufferTail];
00395         return c;
00396     }
00397 }
00398 
00399 /**
00400  * @brief RX Buffer Size
00401  *
00402  * Shows how many bytes are in the RX FIFO ring buffer
00403  *
00404  * @return how many bytes are in the RX FIFO ring buffer
00405  */
00406 int8_t cMxRadio::available()
00407 {
00408     return ((int16_t)((int16_t)ZR_FIFO_SIZE + (int16_t)rxRingBufferHead - (int16_t)rxRingBufferTail)) % ZR_FIFO_SIZE;
00409 }
00410 
00411 /**
00412  * @brief Raw Frame Transmit
00413  *
00414  * Transmits a frame
00415  * Warning: no frame header or FCS is added
00416  *
00417  * @param frm array containing frame data
00418  * @param len length of the frame
00419  */
00420 void cMxRadio::txFrame(uint8_t* frm, uint8_t len)
00421 {
00422 #ifdef ZR_TXWAIT_BEFORE
00423     waitTxDone(0xFFFF);
00424 #endif
00425     txIsBusy = 1;
00426     if (setautotx)
00427         radio_set_state(STATE_TXAUTO);
00428     else
00429         radio_set_state(STATE_TX);
00430     ZR_RFTX_LED_ON();
00431     radio_send_frame(len, frm, 0);
00432 #ifdef ZR_TXWAIT_AFTER
00433     waitTxDone(0xFFFF);
00434     if (setautorx)
00435         radio_set_state(STATE_RXAUTO);
00436     else
00437         radio_set_state(STATE_RX);
00438     txIsBusy = 0;
00439 #endif
00440 }
00441 
00442 /**
00443  * @brief Prepare for Trasmission
00444  *
00445  * Goes into non-immediate transmit mode, resets the transmit payload
00446  * Non-immediate mode sends multiple bytes per frame
00447  *
00448  */
00449 void cMxRadio::beginTransmission()
00450 {
00451     usedBeginTransmission = 1;
00452     txTmpBuffer[5]= 0xFF;
00453     txTmpBuffer[6]= 0XFF;
00454     // add frame header
00455     txTmpBufferLength = HeadSize;
00456 }
00457 
00458 void cMxRadio::beginTransmission(uint16_t destaddress)
00459 {
00460     txTmpBuffer[5]=(uint8_t)(destaddress & 0xFF );
00461     txTmpBuffer[6]=(uint8_t)((destaddress>>8) & 0xFF );
00462     usedBeginTransmission = 1;
00463 
00464     // add frame header
00465     txTmpBufferLength = HeadSize;
00466 }
00467 
00468 /**
00469  * @brief Finalize Trasmission
00470  *
00471  * Finalize the payload and transmits it when ready
00472  *
00473  */
00474 void cMxRadio::endTransmission()
00475 {
00476     usedBeginTransmission = 0;
00477 
00478     // empty FCS field
00479     txTmpBufferLength += 2;
00480 
00481 #ifdef ZR_TXWAIT_BEFORE
00482     waitTxDone(0xFFFF);
00483 #endif
00484     txIsBusy = 1;
00485     if (setautotx)
00486         radio_set_state(STATE_TXAUTO);
00487     else
00488         radio_set_state(STATE_TX);
00489     ZR_RFTX_LED_ON();
00490     //if broadcase ,cant need ack
00491     if(txTmpBuffer[5]==0xff && txTmpBuffer[5]==0xff)
00492         txTmpBuffer[0]=txTmpBuffer[0]&0xdf;
00493     else
00494     {
00495         if(!needack)
00496             txTmpBuffer[0] = 0x41;
00497         else
00498             txTmpBuffer[0] = 0x61; //ack required
00499     }
00500     radio_send_frame(txTmpBufferLength, txTmpBuffer, 0);
00501 #ifdef ZR_TXWAIT_AFTER
00502     waitTxDone(0xFFFF);
00503     if (setautorx)
00504         radio_set_state(STATE_RXAUTO);
00505     else
00506         radio_set_state(STATE_RX);
00507     txIsBusy = 0;
00508 #endif
00509 }
00510 
00511 /**
00512  * @brief Cancel Trasmission
00513  *
00514  * Clears payload buffer
00515  *
00516  * Warning: does not actually cancel a transmission in progress
00517  *
00518  */
00519 void cMxRadio::cancelTransmission()
00520 {
00521     usedBeginTransmission = 0;
00522 
00523     // add frame header
00524     txTmpBufferLength = HeadSize;
00525 }
00526 /**
00527  * @brief TX a Byte
00528  *
00529  * Wrapper for "write", since the "Wire" library uses "send"
00530  *
00531  */
00532 void cMxRadio::send(uint8_t c)
00533 {
00534     write(c);
00535 }
00536 
00537 /**
00538  * @brief TX a Byte
00539  *
00540  * If "beginTrasmission" was used, then it writes into the transmit buffer for non-immediate mode
00541  * If "beginTrasmission" was not used, then it transmits the single byte immediately (slower for multiple bytes)
00542  *
00543  * @param c character to be sent
00544  */
00545 void cMxRadio::write(uint8_t c)
00546 {
00547     if (usedBeginTransmission)
00548     {
00549         if (txTmpBufferLength < ZR_TXTMPBUFF_SIZE - 2)
00550         {
00551             txTmpBuffer[txTmpBufferLength] = c;
00552             txTmpBufferLength++;
00553 
00554             if (txTmpBufferLength >= ZR_TXTMPBUFF_SIZE - 2)
00555             {
00556                 // buffer is now full
00557                 // just send it all out so we have more room
00558                 endTransmission();
00559                 beginTransmission();
00560             }
00561         }
00562     }
00563     else
00564     {
00565         txTmpBuffer[HeadSize] = c; // set payload
00566         txTmpBuffer[HeadSize+1] = 0; // empty FCS
00567         txTmpBuffer[HeadSize+2] = 0; // empty FCS
00568 
00569 #ifdef ZR_TXWAIT_BEFORE
00570         waitTxDone(0xFFFF);
00571 #endif
00572         txIsBusy = 1;
00573         if (setautotx)
00574             radio_set_state(STATE_TXAUTO);
00575         else
00576             radio_set_state(STATE_TX);
00577         ZR_RFTX_LED_ON();
00578         radio_send_frame(10, txTmpBuffer, 0);
00579 #ifdef ZR_TXWAIT_AFTER
00580         waitTxDone(0xFFFF);
00581         if (setautorx)
00582             radio_set_state(STATE_RXAUTO);
00583         else
00584             radio_set_state(STATE_RX);
00585         txIsBusy = 0;
00586 #endif
00587     }
00588 }
00589 /**
00590  * @brief TX a String
00591  *
00592  * A overload for "write" that sends a null-terminated string
00593  *
00594  * @param str null-terminated string to be sent
00595  */
00596 void cMxRadio::write(char* str)
00597 {
00598     while (*str)
00599         write(*str++);
00600 }
00601 
00602 /**
00603  * @brief TX an Array
00604  *
00605  * A overload for "write" that sends an array
00606  *
00607  * @param arr data array to be sent
00608  * @param len length of data array
00609  */
00610 void cMxRadio::write(uint8_t* arr, uint8_t len)
00611 {
00612     uint8_t i;
00613     for (i = 0; i < len; i++)
00614         write(arr[i]);
00615 }
00616 
00617 /**
00618  * @brief Default TX Complete Event Handler
00619  *
00620  * Calls the user event function if one is attached
00621  * Clear the TX busy status flag
00622  * Defaults back to RX state
00623  *
00624  * this should not be called by the user
00625  *
00626  * @param x one of the radio_tx_done_t enumerations indicating transmission success
00627  */
00628 void cMxRadio::onTxDone(radio_tx_done_t x)
00629 {
00630     if (hasAttachedTxEvent)
00631     {
00632         zrEventTxDone(x);
00633     }
00634 
00635     txIsBusy = 0;
00636 }
00637 
00638 /**
00639  * @brief radio_set_param Wrapper
00640  *
00641  * set a radio parameter
00642  *
00643  * see radio.h for more info
00644  */
00645 void cMxRadio::setParam(radio_attribute_t attr, radio_param_t parm)
00646 {
00647     radio_set_param(attr, parm);
00648 }
00649 
00650 /**
00651  * @brief radio_do_cca Wrapper
00652  *
00653  * perform CCA measure
00654  *
00655  * see radio.h for more info
00656  */
00657 radio_cca_t cMxRadio::doCca()
00658 {
00659     return radio_do_cca();
00660 }
00661 
00662 /**
00663  * @brief Set Radio State Wrapper
00664  *
00665  * sets or forces the radio into a state
00666  *
00667  * see radio.h for more info
00668  *
00669  * @param state requested radio state
00670  * @param force boolean indicating to force the state
00671  */
00672 void cMxRadio::setState(radio_state_t state, uint8_t force)
00673 {
00674     if (force)
00675         radio_force_state(state);
00676     else
00677         radio_set_state(state);
00678 }
00679 
00680 /**
00681  * @brief radio_set_state Wrapper
00682  *
00683  * bring the the radio in the requested state
00684  *
00685  * see radio.h for more info
00686  */
00687 void cMxRadio::setState(radio_state_t state)
00688 {
00689     radio_set_state(state);
00690 }
00691 
00692 /**
00693  * @brief radio_set_state to STATE_RX
00694  *
00695  * bring the the radio in the requested state of STATE_RX
00696  *
00697  * the radio state does not return to STATE_RX automatically if ZR_TXWAIT_AFTER is not used
00698  * thus why this is provided
00699  *
00700  * see radio.h for more info
00701  */
00702 void cMxRadio::setStateRx()
00703 {
00704     if (setautorx)
00705         radio_set_state(STATE_RXAUTO);
00706     else
00707         radio_set_state(STATE_RX);
00708 }
00709 
00710 /**
00711  * @brief radio_force_state Wrapper
00712  *
00713  * force the radio to the requested state
00714  *
00715  * see radio.h for more info
00716  */
00717 void cMxRadio::forceState(radio_state_t state)
00718 {
00719     radio_force_state(state);
00720 }
00721 
00722 /**
00723  * @brief Sets Radio Channel
00724  *
00725  * changes the radio channel by setting the radio channel state
00726  *
00727  * @param chan channel number, 11 to 26
00728  */
00729 void cMxRadio::setChannel(channel_t chan)
00730 {
00731     radio_set_param(RP_CHANNEL(chan));
00732 }
00733 uint8_t cMxRadio::getChannel()
00734 {
00735     trx_param_t p;
00736     trx_parms_get(&p);
00737     channel_t chan= p.chan;
00738     return (uint8_t)chan;
00739 }
00740 
00741 
00742 /**
00743  * @brief Read Receiver Signal Strength Indicator Now
00744  *
00745  * returns the current RSSI
00746  *
00747  * range is between -91 and -9 dBm
00748  * where -9 is the best
00749  *
00750  * @return RSSI of the last transmission received
00751  */
00752 int8_t cMxRadio::getRssiNow()
00753 {
00754     int16_t rssi = ((int16_t)(trx_reg_read(RG_PHY_RSSI) & 0x1F)); // mask only important bits
00755     rssi = (rssi == 0) ? (RSSI_BASE_VAL - 1) : ((rssi < 28) ? ((rssi - 1) * 3 + RSSI_BASE_VAL) : -9);
00756     // if 0, then rssi < RSSI_BASE_VAL, if 28, then >= -10
00757 
00758     return rssi;
00759 }
00760 
00761 
00762 
00763 /**
00764  * @brief Read Last Receiver Signal Strength Indicator
00765  *
00766  * returns the RSSI of the last transmission
00767  *
00768  * range is between -91 and -9 dBm
00769  * where -9 is the best
00770  *
00771  * @return RSSI of the last transmission received
00772  */
00773 int8_t cMxRadio::getLastRssi()
00774 {
00775     int16_t rssi = ((int16_t)(temprssi & 0x1F)); // mask only important bits
00776     rssi = (rssi == 0) ? (RSSI_BASE_VAL - 1) : ((rssi < 28) ? ((rssi - 1) * 3 + RSSI_BASE_VAL) : -9);
00777     // if 0, then rssi < RSSI_BASE_VAL, if 28, then >= -10
00778 
00779     return rssi;
00780 }
00781 
00782 
00783 /**
00784  * @brief Read Link Quality Indicator
00785  *
00786  * returns the LQI of the last transmission received
00787  *
00788  * range is from 0 to 255
00789  * 255 is the best
00790  *
00791  * @return LQI of the last transmission received
00792  */
00793 uint8_t cMxRadio::getLqi()
00794 {
00795     return lastLqi;
00796 }
00797 
00798 /**
00799  * @brief Read Last Energy Detection Level
00800  *
00801  * returns the ED level of the last transmission received
00802  *
00803  * range is between -90 and -6 dBm
00804  * where -6 is the best
00805  *
00806  * @return ED level of the last transmission received
00807  */
00808 int8_t cMxRadio::getLastEd()
00809 {
00810     int8_t ed = trx_reg_read(RG_PHY_ED_LEVEL);
00811 
00812     return ed == 0xFF ? 0 : (ed + RSSI_BASE_VAL);
00813     //return lastRssi == 0xFF ? 0 : (lastRssi + RSSI_BASE_VAL);
00814 
00815 }
00816 
00817 /**
00818  * @brief Read Energy Detection Level Now
00819  *
00820  * forces a reading of the ED level
00821  *
00822  * range is between -90 and -6 dBm
00823  * where -6 is the best
00824  *
00825  * @return ED level
00826  */
00827 int8_t cMxRadio::getEdNow()
00828 {
00829     trx_reg_write(RG_PHY_ED_LEVEL, 0); // forces a reading
00830 
00831     return getLastEd();
00832 }
00833 
00834 /**
00835  * @brief Wait for TX to Complete
00836  *
00837  * waits until the last transmission is complete, or timed out
00838  *
00839  * @param timeout iterations to countdown before timeout
00840  */
00841 void cMxRadio::waitTxDone(uint16_t timeout)
00842 {
00843     volatile uint16_t cnt = timeout;
00844     while (txIsBusy && cnt--);
00845 }
00846 
00847