123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594 |
- /**************************************************************************************************
- Filename: mac_radio.c
- Revised: $Date: 2007-09-11 10:58:41 -0700 (Tue, 11 Sep 2007) $
- Revision: $Revision: 15371 $
- Description: Describe the purpose and contents of the file.
- Copyright 2006-2012 Texas Instruments Incorporated. All rights reserved.
- IMPORTANT: Your use of this Software is limited to those specific rights
- granted under the terms of a software license agreement between the user
- who downloaded the software, his/her employer (which must be your employer)
- and Texas Instruments Incorporated (the "License"). You may not use this
- Software unless you agree to abide by the terms of the License. The License
- limits your use, and you acknowledge, that the Software may not be modified,
- copied or distributed unless embedded on a Texas Instruments microcontroller
- or used solely and exclusively in conjunction with a Texas Instruments radio
- frequency transceiver, which is integrated into your product. Other than for
- the foregoing purpose, you may not use, reproduce, copy, prepare derivative
- works of, modify, distribute, perform, display or sell this Software and/or
- its documentation for any purpose.
- YOU FURTHER ACKNOWLEDGE AND AGREE THAT THE SOFTWARE AND DOCUMENTATION ARE
- PROVIDED “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED,
- INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, TITLE,
- NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL
- TEXAS INSTRUMENTS OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER CONTRACT,
- NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR OTHER
- LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
- INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE
- OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT
- OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
- (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
- Should you have any questions regarding your right to use this Software,
- contact Texas Instruments Incorporated at www.TI.com.
- **************************************************************************************************/
- /* ------------------------------------------------------------------------------------------------
- * Includes
- * ------------------------------------------------------------------------------------------------
- */
- /* hal */
- #include "hal_types.h"
- /* high-level */
- #include "mac_pib.h"
- /* exported low-level */
- #include "mac_low_level.h"
- /* low-level specific */
- #include "mac_radio.h"
- #include "mac_tx.h"
- #include "mac_rx.h"
- #include "mac_rx_onoff.h"
- #include "mac_sleep.h"
- #include "mac_backoff_timer.h"
- /* target specific */
- #include "mac_radio_defs.h"
- /* debug */
- #include "mac_assert.h"
- /* ------------------------------------------------------------------------------------------------
- * Includes
- * ------------------------------------------------------------------------------------------------
- */
- #define ED_RF_POWER_MIN_DBM (MAC_RADIO_RECEIVER_SENSITIVITY_DBM + MAC_SPEC_ED_MIN_DBM_ABOVE_RECEIVER_SENSITIVITY)
- #define ED_RF_POWER_MAX_DBM MAC_RADIO_RECEIVER_SATURATION_DBM
- /* ------------------------------------------------------------------------------------------------
- * Global Variables
- * ------------------------------------------------------------------------------------------------
- */
- uint8 macPhyTxPower;
- uint8 macPhyChannel;
- /* ------------------------------------------------------------------------------------------------
- * Local Variables
- * ------------------------------------------------------------------------------------------------
- */
- static uint8 reqChannel;
- static uint8 reqTxPower;
- /* ------------------------------------------------------------------------------------------------
- * Local Functions
- * ------------------------------------------------------------------------------------------------
- */
- static uint8 radioComputeED(int8 rssiDbm);
- /**************************************************************************************************
- * @fn macRadioInit
- *
- * @brief Initialize radio software.
- *
- * @param none
- *
- * @return none
- **************************************************************************************************
- */
- MAC_INTERNAL_API void macRadioInit(void)
- {
- /* variable initialization for this module */
- reqChannel = MAC_RADIO_CHANNEL_DEFAULT;
- macPhyChannel = MAC_RADIO_CHANNEL_INVALID;
- reqTxPower = MAC_RADIO_TX_POWER_INVALID;
- macPhyTxPower = MAC_RADIO_TX_POWER_INVALID;
- }
- /**************************************************************************************************
- * @fn macRadioReset
- *
- * @brief Resets the radio module.
- *
- * @param none
- *
- * @return none
- **************************************************************************************************
- */
- MAC_INTERNAL_API void macRadioReset(void)
- {
- macRadioStopScan();
- macRadioEnergyDetectStop();
- }
- /**************************************************************************************************
- * @fn macRadioRandomByte
- *
- * @brief Return a random byte derived from previously set random seed.
- *
- * @param none
- *
- * @return a random byte
- **************************************************************************************************
- */
- MAC_INTERNAL_API uint8 macRadioRandomByte(void)
- {
- return(MAC_RADIO_RANDOM_BYTE());
- }
- /**************************************************************************************************
- * @fn macRadioSetPanCoordinator
- *
- * @brief Configure the pan coordinator status of the radio
- *
- * @param panCoordFlag - non-zero to configure radio to be pan coordinator
- * zero to configure radio as NON pan coordinator
- *
- * @return none
- **************************************************************************************************
- */
- MAC_INTERNAL_API void macRadioSetPanCoordinator(uint8 panCoordFlag)
- {
- /* abstracted radio configuration */
- MAC_RADIO_SET_PAN_COORDINATOR(panCoordFlag);
- }
- /**************************************************************************************************
- * @fn macRadioSetPanID
- *
- * @brief Set the pan ID on the radio.
- *
- * @param panID - 16 bit PAN identifier
- *
- * @return none
- **************************************************************************************************
- */
- void macRadioSetPanID(uint16 panID)
- {
- /* abstracted radio configuration */
- MAC_RADIO_SET_PAN_ID(panID);
- }
- /**************************************************************************************************
- * @fn macRadioSetShortAddr
- *
- * @brief Set the short addrss on the radio.
- *
- * @param shortAddr - 16 bit short address
- *
- * @return none
- **************************************************************************************************
- */
- MAC_INTERNAL_API void macRadioSetShortAddr(uint16 shortAddr)
- {
- /* abstracted radio configuration */
- MAC_RADIO_SET_SHORT_ADDR(shortAddr);
- }
- /**************************************************************************************************
- * @fn macRadioSetIEEEAddr
- *
- * @brief Set the IEEE address on the radio.
- *
- * @param pIEEEAddr - pointer to array holding 64 bit IEEE address; array must be little
- * endian format (starts with lowest signficant byte)
- *
- * @return none
- **************************************************************************************************
- */
- MAC_INTERNAL_API void macRadioSetIEEEAddr(uint8 * pIEEEAddr)
- {
- /* abstracted radio configuration */
- MAC_RADIO_SET_IEEE_ADDR(pIEEEAddr);
- }
- /**************************************************************************************************
- * @fn macRadioSetTxPower
- *
- * @brief Set transmitter power of the radio.
- *
- * @param txPower - the minus dBm for power but as a postive integer (or if configured
- * for it, txPower is the raw register value). If PA/LNA is installed
- * then txPower becomes positive dBm.
- *
- * @return The minus dBm for power actually set according to what is possible according to
- the build and run-time configuration set.
- **************************************************************************************************
- */
- #ifndef HAL_MAC_USE_REGISTER_POWER_VALUES
- /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- MAC_INTERNAL_API uint8 macRadioSetTxPower(uint8 txPower)
- {
- halIntState_t s;
- #if defined MAC_RUNTIME_CC2591 || defined MAC_RUNTIME_CC2590
- const uint8 CODE *pTable = macRadioDefsTxPwrTables[macRadioDefsRefTableId >> 4];
- #elif defined HAL_PA_LNA || defined HAL_PA_LNA_CC2590
- const uint8 CODE *pTable = macRadioDefsTxPwrTables[0];
- #else
- const uint8 CODE *pTable = macRadioDefsTxPwrBare;
- #endif
- /* if the selected dBm is out of range, use the closest available */
- if ((int8)txPower > (int8)pTable[MAC_RADIO_DEFS_TBL_TXPWR_FIRST_ENTRY])
- {
- /* greater than base value -- out of table range */
- txPower = pTable[MAC_RADIO_DEFS_TBL_TXPWR_FIRST_ENTRY];
- }
- else if ((int8)txPower < (int8)pTable[MAC_RADIO_DEFS_TBL_TXPWR_LAST_ENTRY])
- {
- /* smaller than the lowest power level -- out of table range */
- txPower = pTable[MAC_RADIO_DEFS_TBL_TXPWR_LAST_ENTRY];
- }
- /*
- * Set the global variable reqTxPower. This variable is referenced
- * by the function macRadioUpdateTxPower() to write the radio register.
- *
- * A lookup table is used to translate the power level to the register
- * value.
- */
- HAL_ENTER_CRITICAL_SECTION(s);
- /* When calculating index to the power register value table,
- * either txPower (of uint8 type) has to be explicitly type-casted to int8
- * or the subtraction expression has to be type-casted to uint8 to work
- * with the integral promotions.
- * The latter is more code size efficient and hence the latter is used.
- */
- {
- uint8 index = pTable[MAC_RADIO_DEFS_TBL_TXPWR_FIRST_ENTRY] - txPower
- + MAC_RADIO_DEFS_TBL_TXPWR_ENTRIES;
- reqTxPower = pTable[index];
- }
- HAL_EXIT_CRITICAL_SECTION(s);
- /* update the radio power setting */
- macRadioUpdateTxPower();
- return txPower;
- }
- #else
- /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- MAC_INTERNAL_API uint8 macRadioSetTxPower(uint8 txPower)
- {
- halIntState_t s;
- /* same as above but with no lookup table, use raw register value */
- HAL_ENTER_CRITICAL_SECTION(s);
- reqTxPower = txPower;
- HAL_EXIT_CRITICAL_SECTION(s);
- /* update the radio power setting */
- macRadioUpdateTxPower();
- return txPower;
- }
- #endif
- /**************************************************************************************************
- * @fn macRadioUpdateTxPower
- *
- * @brief Update the radio's transmit power if a new power level has been requested
- *
- * @param reqTxPower - file scope variable that holds the last request power level
- * macPhyTxPower - global variable that holds radio's set power level
- *
- * @return none
- **************************************************************************************************
- */
- MAC_INTERNAL_API void macRadioUpdateTxPower(void)
- {
- halIntState_t s;
- /*
- * If the requested power setting is different from the actual radio setting,
- * attempt to udpate to the new power setting.
- */
- HAL_ENTER_CRITICAL_SECTION(s);
- if (reqTxPower != macPhyTxPower)
- {
- /*
- * Radio power cannot be updated when the radio is physically transmitting.
- * If there is a possibility radio is transmitting, do not change the power
- * setting. This function will be called again after the current transmit
- * completes.
- */
- if (!macRxOutgoingAckFlag && !MAC_TX_IS_PHYSICALLY_ACTIVE())
- {
- /*
- * Set new power level; update the shadow value and write
- * the new value to the radio hardware.
- */
- macPhyTxPower = reqTxPower;
- MAC_RADIO_SET_TX_POWER(macPhyTxPower);
- }
- }
- HAL_EXIT_CRITICAL_SECTION(s);
- }
- /**************************************************************************************************
- * @fn macRadioSetChannel
- *
- * @brief Set radio channel.
- *
- * @param channel - channel number, valid range is 11 through 26. Allow
- * channels 27 and 28 for some Japanese customers.
- *
- * @return none
- **************************************************************************************************
- */
- MAC_INTERNAL_API void macRadioSetChannel(uint8 channel)
- {
- halIntState_t s;
- MAC_ASSERT((channel >= 11) && (channel <= 28)); /* illegal channel */
- /* critical section to make sure transmit does not start while updating channel */
- HAL_ENTER_CRITICAL_SECTION(s);
- /* set requested channel */
- reqChannel = channel;
- /*
- * If transmit is not active, update the radio hardware immediately. If transmit is active,
- * the channel will be updated at the end of the current transmit.
- */
- if (!macTxActive)
- {
- macRadioUpdateChannel();
- }
- HAL_EXIT_CRITICAL_SECTION(s);
- }
- /**************************************************************************************************
- * @fn macRadioUpdateChannel
- *
- * @brief Update the radio channel if a new channel has been requested.
- *
- * @param none
- *
- * @return none
- **************************************************************************************************
- */
- MAC_INTERNAL_API void macRadioUpdateChannel(void)
- {
- halIntState_t s;
- MAC_ASSERT(!macTxActive); /* cannot change channel during a transmit */
- /* if the channel has changed, set the radio to the new channel */
- HAL_ENTER_CRITICAL_SECTION(s);
- if (reqChannel != macPhyChannel)
- {
- macPhyChannel = reqChannel;
- HAL_EXIT_CRITICAL_SECTION(s);
- /* changing the channel stops any receive in progress */
- macRxOff();
- MAC_RADIO_SET_CHANNEL(macPhyChannel);
- /* If the channel is updated in the middle of receiving a frame, we must
- * clean up the Rx logic.
- */
- macRxHaltCleanup();
- macRxOnRequest();
- }
- else
- {
- HAL_EXIT_CRITICAL_SECTION(s);
- }
- }
- /**************************************************************************************************
- * @fn macRadioStartScan
- *
- * @brief Puts radio into selected scan mode.
- *
- * @param scanMode - scan mode, see #defines in .h file
- *
- * @return none
- **************************************************************************************************
- */
- MAC_INTERNAL_API void macRadioStartScan(uint8 scanMode)
- {
- MAC_ASSERT(macSleepState == MAC_SLEEP_STATE_AWAKE); /* radio must be awake */
- MAC_ASSERT(macRxFilter == RX_FILTER_OFF); /* all filtering must be off to start scan */
- /* set the receive filter based on the selected scan mode */
- if (scanMode == MAC_SCAN_ED)
- {
- macRxFilter = RX_FILTER_ALL;
- }
- else if (scanMode == MAC_SCAN_ORPHAN)
- {
- macRxFilter = RX_FILTER_NON_COMMAND_FRAMES;
- }
- else
- {
- MAC_ASSERT((scanMode == MAC_SCAN_ACTIVE) || (scanMode == MAC_SCAN_PASSIVE)); /* invalid scan type */
- macRxFilter = RX_FILTER_NON_BEACON_FRAMES;
- /* for active and passive scans, per spec the pan ID must be 0xFFFF */
- MAC_RADIO_SET_PAN_ID(0xFFFF);
- }
- }
- /**************************************************************************************************
- * @fn macRadioStopScan
- *
- * @brief Takes radio out of scan mode. Note can be called if
- *
- * @param none
- *
- * @return none
- **************************************************************************************************
- */
- MAC_INTERNAL_API void macRadioStopScan(void)
- {
- macRxFilter = RX_FILTER_OFF;
- /* restore the pan ID (passive and active scans set pan ID to 0xFFFF) */
- MAC_RADIO_SET_PAN_ID(macPib.panId);
- }
- /**************************************************************************************************
- * @fn macRadioEnergyDetectStart
- *
- * @brief Initiates energy detect. The highest energy detected is recorded from the time
- * when this function is called until the energy detect is stopped.
- *
- * @param none
- *
- * @return none
- **************************************************************************************************
- */
- void macRadioEnergyDetectStart(void)
- {
- /* Energy Detection Scan should be run with CC2591 compresson workaround off */
- COMPRESSION_WORKAROUND_OFF();
- MAC_RADIO_RECORD_MAX_RSSI_START();
- }
- /**************************************************************************************************
- * @fn macRadioEnergyDetectStop
- *
- * @brief Called at completion of an energy detect. Note: can be called even if energy
- * detect is already stopped (needed by reset).
- *
- * @param none
- *
- * @return highest energy detect measurement
- **************************************************************************************************
- */
- uint8 macRadioEnergyDetectStop(void)
- {
- uint8 rssiDbm;
- uint8 energyDetectMeasurement;
- rssiDbm = MAC_RADIO_RECORD_MAX_RSSI_STOP() + MAC_RADIO_RSSI_OFFSET;
- MAC_RADIO_RSSI_LNA_OFFSET(rssiDbm);
- energyDetectMeasurement = radioComputeED(rssiDbm);
- /* Trun on CC2591 compresson workaround */
- COMPRESSION_WORKAROUND_ON();
- return(energyDetectMeasurement);
- }
- /*=================================================================================================
- * @fn radioComputeED
- *
- * @brief Compute energy detect measurement.
- *
- * @param rssi - raw RSSI value from radio hardware
- *
- * @return energy detect measurement in the range of 0x00-0xFF
- *=================================================================================================
- */
- static uint8 radioComputeED(int8 rssiDbm)
- {
- uint8 ed;
- /*
- * Keep RF power between minimum and maximum values.
- * This min/max range is derived from datasheet and specification.
- */
- if (rssiDbm < ED_RF_POWER_MIN_DBM)
- {
- rssiDbm = ED_RF_POWER_MIN_DBM;
- }
- else if (rssiDbm > ED_RF_POWER_MAX_DBM)
- {
- rssiDbm = ED_RF_POWER_MAX_DBM;
- }
- /*
- * Create energy detect measurement by normalizing and scaling RF power level.
- *
- * Note : The division operation below is designed for maximum accuracy and
- * best granularity. This is done by grouping the math operations to
- * compute the entire numerator before doing any division.
- */
- ed = (MAC_SPEC_ED_MAX * (rssiDbm - ED_RF_POWER_MIN_DBM)) / (ED_RF_POWER_MAX_DBM - ED_RF_POWER_MIN_DBM);
- return(ed);
- }
- /**************************************************************************************************
- * @fn macRadioComputeLQI
- *
- * @brief Compute link quality indication.
- *
- * @param rssi - raw RSSI value from radio hardware
- * corr - correlation value from radio hardware
- *
- * @return link quality indicator value
- **************************************************************************************************
- */
- MAC_INTERNAL_API uint8 macRadioComputeLQI(int8 rssiDbm, uint8 corr)
- {
- (void) corr; /* suppress compiler warning of unused parameter */
- /*
- * Note : Currently the LQI value is simply the energy detect measurement.
- * A more accurate value could be derived by using the correlation
- * value along with the RSSI value.
- */
- return(radioComputeED(rssiDbm));
- }
- /**************************************************************************************************
- */
|