mac_radio.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594
  1. /**************************************************************************************************
  2. Filename: mac_radio.c
  3. Revised: $Date: 2007-09-11 10:58:41 -0700 (Tue, 11 Sep 2007) $
  4. Revision: $Revision: 15371 $
  5. Description: Describe the purpose and contents of the file.
  6. Copyright 2006-2012 Texas Instruments Incorporated. All rights reserved.
  7. IMPORTANT: Your use of this Software is limited to those specific rights
  8. granted under the terms of a software license agreement between the user
  9. who downloaded the software, his/her employer (which must be your employer)
  10. and Texas Instruments Incorporated (the "License"). You may not use this
  11. Software unless you agree to abide by the terms of the License. The License
  12. limits your use, and you acknowledge, that the Software may not be modified,
  13. copied or distributed unless embedded on a Texas Instruments microcontroller
  14. or used solely and exclusively in conjunction with a Texas Instruments radio
  15. frequency transceiver, which is integrated into your product. Other than for
  16. the foregoing purpose, you may not use, reproduce, copy, prepare derivative
  17. works of, modify, distribute, perform, display or sell this Software and/or
  18. its documentation for any purpose.
  19. YOU FURTHER ACKNOWLEDGE AND AGREE THAT THE SOFTWARE AND DOCUMENTATION ARE
  20. PROVIDED “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED,
  21. INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, TITLE,
  22. NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL
  23. TEXAS INSTRUMENTS OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER CONTRACT,
  24. NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR OTHER
  25. LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
  26. INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE
  27. OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT
  28. OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
  29. (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
  30. Should you have any questions regarding your right to use this Software,
  31. contact Texas Instruments Incorporated at www.TI.com.
  32. **************************************************************************************************/
  33. /* ------------------------------------------------------------------------------------------------
  34. * Includes
  35. * ------------------------------------------------------------------------------------------------
  36. */
  37. /* hal */
  38. #include "hal_types.h"
  39. /* high-level */
  40. #include "mac_pib.h"
  41. /* exported low-level */
  42. #include "mac_low_level.h"
  43. /* low-level specific */
  44. #include "mac_radio.h"
  45. #include "mac_tx.h"
  46. #include "mac_rx.h"
  47. #include "mac_rx_onoff.h"
  48. #include "mac_sleep.h"
  49. #include "mac_backoff_timer.h"
  50. /* target specific */
  51. #include "mac_radio_defs.h"
  52. /* debug */
  53. #include "mac_assert.h"
  54. /* ------------------------------------------------------------------------------------------------
  55. * Includes
  56. * ------------------------------------------------------------------------------------------------
  57. */
  58. #define ED_RF_POWER_MIN_DBM (MAC_RADIO_RECEIVER_SENSITIVITY_DBM + MAC_SPEC_ED_MIN_DBM_ABOVE_RECEIVER_SENSITIVITY)
  59. #define ED_RF_POWER_MAX_DBM MAC_RADIO_RECEIVER_SATURATION_DBM
  60. /* ------------------------------------------------------------------------------------------------
  61. * Global Variables
  62. * ------------------------------------------------------------------------------------------------
  63. */
  64. uint8 macPhyTxPower;
  65. uint8 macPhyChannel;
  66. /* ------------------------------------------------------------------------------------------------
  67. * Local Variables
  68. * ------------------------------------------------------------------------------------------------
  69. */
  70. static uint8 reqChannel;
  71. static uint8 reqTxPower;
  72. /* ------------------------------------------------------------------------------------------------
  73. * Local Functions
  74. * ------------------------------------------------------------------------------------------------
  75. */
  76. static uint8 radioComputeED(int8 rssiDbm);
  77. /**************************************************************************************************
  78. * @fn macRadioInit
  79. *
  80. * @brief Initialize radio software.
  81. *
  82. * @param none
  83. *
  84. * @return none
  85. **************************************************************************************************
  86. */
  87. MAC_INTERNAL_API void macRadioInit(void)
  88. {
  89. /* variable initialization for this module */
  90. reqChannel = MAC_RADIO_CHANNEL_DEFAULT;
  91. macPhyChannel = MAC_RADIO_CHANNEL_INVALID;
  92. reqTxPower = MAC_RADIO_TX_POWER_INVALID;
  93. macPhyTxPower = MAC_RADIO_TX_POWER_INVALID;
  94. }
  95. /**************************************************************************************************
  96. * @fn macRadioReset
  97. *
  98. * @brief Resets the radio module.
  99. *
  100. * @param none
  101. *
  102. * @return none
  103. **************************************************************************************************
  104. */
  105. MAC_INTERNAL_API void macRadioReset(void)
  106. {
  107. macRadioStopScan();
  108. macRadioEnergyDetectStop();
  109. }
  110. /**************************************************************************************************
  111. * @fn macRadioRandomByte
  112. *
  113. * @brief Return a random byte derived from previously set random seed.
  114. *
  115. * @param none
  116. *
  117. * @return a random byte
  118. **************************************************************************************************
  119. */
  120. MAC_INTERNAL_API uint8 macRadioRandomByte(void)
  121. {
  122. return(MAC_RADIO_RANDOM_BYTE());
  123. }
  124. /**************************************************************************************************
  125. * @fn macRadioSetPanCoordinator
  126. *
  127. * @brief Configure the pan coordinator status of the radio
  128. *
  129. * @param panCoordFlag - non-zero to configure radio to be pan coordinator
  130. * zero to configure radio as NON pan coordinator
  131. *
  132. * @return none
  133. **************************************************************************************************
  134. */
  135. MAC_INTERNAL_API void macRadioSetPanCoordinator(uint8 panCoordFlag)
  136. {
  137. /* abstracted radio configuration */
  138. MAC_RADIO_SET_PAN_COORDINATOR(panCoordFlag);
  139. }
  140. /**************************************************************************************************
  141. * @fn macRadioSetPanID
  142. *
  143. * @brief Set the pan ID on the radio.
  144. *
  145. * @param panID - 16 bit PAN identifier
  146. *
  147. * @return none
  148. **************************************************************************************************
  149. */
  150. void macRadioSetPanID(uint16 panID)
  151. {
  152. /* abstracted radio configuration */
  153. MAC_RADIO_SET_PAN_ID(panID);
  154. }
  155. /**************************************************************************************************
  156. * @fn macRadioSetShortAddr
  157. *
  158. * @brief Set the short addrss on the radio.
  159. *
  160. * @param shortAddr - 16 bit short address
  161. *
  162. * @return none
  163. **************************************************************************************************
  164. */
  165. MAC_INTERNAL_API void macRadioSetShortAddr(uint16 shortAddr)
  166. {
  167. /* abstracted radio configuration */
  168. MAC_RADIO_SET_SHORT_ADDR(shortAddr);
  169. }
  170. /**************************************************************************************************
  171. * @fn macRadioSetIEEEAddr
  172. *
  173. * @brief Set the IEEE address on the radio.
  174. *
  175. * @param pIEEEAddr - pointer to array holding 64 bit IEEE address; array must be little
  176. * endian format (starts with lowest signficant byte)
  177. *
  178. * @return none
  179. **************************************************************************************************
  180. */
  181. MAC_INTERNAL_API void macRadioSetIEEEAddr(uint8 * pIEEEAddr)
  182. {
  183. /* abstracted radio configuration */
  184. MAC_RADIO_SET_IEEE_ADDR(pIEEEAddr);
  185. }
  186. /**************************************************************************************************
  187. * @fn macRadioSetTxPower
  188. *
  189. * @brief Set transmitter power of the radio.
  190. *
  191. * @param txPower - the minus dBm for power but as a postive integer (or if configured
  192. * for it, txPower is the raw register value). If PA/LNA is installed
  193. * then txPower becomes positive dBm.
  194. *
  195. * @return The minus dBm for power actually set according to what is possible according to
  196. the build and run-time configuration set.
  197. **************************************************************************************************
  198. */
  199. #ifndef HAL_MAC_USE_REGISTER_POWER_VALUES
  200. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  201. MAC_INTERNAL_API uint8 macRadioSetTxPower(uint8 txPower)
  202. {
  203. halIntState_t s;
  204. #if defined MAC_RUNTIME_CC2591 || defined MAC_RUNTIME_CC2590
  205. const uint8 CODE *pTable = macRadioDefsTxPwrTables[macRadioDefsRefTableId >> 4];
  206. #elif defined HAL_PA_LNA || defined HAL_PA_LNA_CC2590
  207. const uint8 CODE *pTable = macRadioDefsTxPwrTables[0];
  208. #else
  209. const uint8 CODE *pTable = macRadioDefsTxPwrBare;
  210. #endif
  211. /* if the selected dBm is out of range, use the closest available */
  212. if ((int8)txPower > (int8)pTable[MAC_RADIO_DEFS_TBL_TXPWR_FIRST_ENTRY])
  213. {
  214. /* greater than base value -- out of table range */
  215. txPower = pTable[MAC_RADIO_DEFS_TBL_TXPWR_FIRST_ENTRY];
  216. }
  217. else if ((int8)txPower < (int8)pTable[MAC_RADIO_DEFS_TBL_TXPWR_LAST_ENTRY])
  218. {
  219. /* smaller than the lowest power level -- out of table range */
  220. txPower = pTable[MAC_RADIO_DEFS_TBL_TXPWR_LAST_ENTRY];
  221. }
  222. /*
  223. * Set the global variable reqTxPower. This variable is referenced
  224. * by the function macRadioUpdateTxPower() to write the radio register.
  225. *
  226. * A lookup table is used to translate the power level to the register
  227. * value.
  228. */
  229. HAL_ENTER_CRITICAL_SECTION(s);
  230. /* When calculating index to the power register value table,
  231. * either txPower (of uint8 type) has to be explicitly type-casted to int8
  232. * or the subtraction expression has to be type-casted to uint8 to work
  233. * with the integral promotions.
  234. * The latter is more code size efficient and hence the latter is used.
  235. */
  236. {
  237. uint8 index = pTable[MAC_RADIO_DEFS_TBL_TXPWR_FIRST_ENTRY] - txPower
  238. + MAC_RADIO_DEFS_TBL_TXPWR_ENTRIES;
  239. reqTxPower = pTable[index];
  240. }
  241. HAL_EXIT_CRITICAL_SECTION(s);
  242. /* update the radio power setting */
  243. macRadioUpdateTxPower();
  244. return txPower;
  245. }
  246. #else
  247. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  248. MAC_INTERNAL_API uint8 macRadioSetTxPower(uint8 txPower)
  249. {
  250. halIntState_t s;
  251. /* same as above but with no lookup table, use raw register value */
  252. HAL_ENTER_CRITICAL_SECTION(s);
  253. reqTxPower = txPower;
  254. HAL_EXIT_CRITICAL_SECTION(s);
  255. /* update the radio power setting */
  256. macRadioUpdateTxPower();
  257. return txPower;
  258. }
  259. #endif
  260. /**************************************************************************************************
  261. * @fn macRadioUpdateTxPower
  262. *
  263. * @brief Update the radio's transmit power if a new power level has been requested
  264. *
  265. * @param reqTxPower - file scope variable that holds the last request power level
  266. * macPhyTxPower - global variable that holds radio's set power level
  267. *
  268. * @return none
  269. **************************************************************************************************
  270. */
  271. MAC_INTERNAL_API void macRadioUpdateTxPower(void)
  272. {
  273. halIntState_t s;
  274. /*
  275. * If the requested power setting is different from the actual radio setting,
  276. * attempt to udpate to the new power setting.
  277. */
  278. HAL_ENTER_CRITICAL_SECTION(s);
  279. if (reqTxPower != macPhyTxPower)
  280. {
  281. /*
  282. * Radio power cannot be updated when the radio is physically transmitting.
  283. * If there is a possibility radio is transmitting, do not change the power
  284. * setting. This function will be called again after the current transmit
  285. * completes.
  286. */
  287. if (!macRxOutgoingAckFlag && !MAC_TX_IS_PHYSICALLY_ACTIVE())
  288. {
  289. /*
  290. * Set new power level; update the shadow value and write
  291. * the new value to the radio hardware.
  292. */
  293. macPhyTxPower = reqTxPower;
  294. MAC_RADIO_SET_TX_POWER(macPhyTxPower);
  295. }
  296. }
  297. HAL_EXIT_CRITICAL_SECTION(s);
  298. }
  299. /**************************************************************************************************
  300. * @fn macRadioSetChannel
  301. *
  302. * @brief Set radio channel.
  303. *
  304. * @param channel - channel number, valid range is 11 through 26. Allow
  305. * channels 27 and 28 for some Japanese customers.
  306. *
  307. * @return none
  308. **************************************************************************************************
  309. */
  310. MAC_INTERNAL_API void macRadioSetChannel(uint8 channel)
  311. {
  312. halIntState_t s;
  313. MAC_ASSERT((channel >= 11) && (channel <= 28)); /* illegal channel */
  314. /* critical section to make sure transmit does not start while updating channel */
  315. HAL_ENTER_CRITICAL_SECTION(s);
  316. /* set requested channel */
  317. reqChannel = channel;
  318. /*
  319. * If transmit is not active, update the radio hardware immediately. If transmit is active,
  320. * the channel will be updated at the end of the current transmit.
  321. */
  322. if (!macTxActive)
  323. {
  324. macRadioUpdateChannel();
  325. }
  326. HAL_EXIT_CRITICAL_SECTION(s);
  327. }
  328. /**************************************************************************************************
  329. * @fn macRadioUpdateChannel
  330. *
  331. * @brief Update the radio channel if a new channel has been requested.
  332. *
  333. * @param none
  334. *
  335. * @return none
  336. **************************************************************************************************
  337. */
  338. MAC_INTERNAL_API void macRadioUpdateChannel(void)
  339. {
  340. halIntState_t s;
  341. MAC_ASSERT(!macTxActive); /* cannot change channel during a transmit */
  342. /* if the channel has changed, set the radio to the new channel */
  343. HAL_ENTER_CRITICAL_SECTION(s);
  344. if (reqChannel != macPhyChannel)
  345. {
  346. macPhyChannel = reqChannel;
  347. HAL_EXIT_CRITICAL_SECTION(s);
  348. /* changing the channel stops any receive in progress */
  349. macRxOff();
  350. MAC_RADIO_SET_CHANNEL(macPhyChannel);
  351. /* If the channel is updated in the middle of receiving a frame, we must
  352. * clean up the Rx logic.
  353. */
  354. macRxHaltCleanup();
  355. macRxOnRequest();
  356. }
  357. else
  358. {
  359. HAL_EXIT_CRITICAL_SECTION(s);
  360. }
  361. }
  362. /**************************************************************************************************
  363. * @fn macRadioStartScan
  364. *
  365. * @brief Puts radio into selected scan mode.
  366. *
  367. * @param scanMode - scan mode, see #defines in .h file
  368. *
  369. * @return none
  370. **************************************************************************************************
  371. */
  372. MAC_INTERNAL_API void macRadioStartScan(uint8 scanMode)
  373. {
  374. MAC_ASSERT(macSleepState == MAC_SLEEP_STATE_AWAKE); /* radio must be awake */
  375. MAC_ASSERT(macRxFilter == RX_FILTER_OFF); /* all filtering must be off to start scan */
  376. /* set the receive filter based on the selected scan mode */
  377. if (scanMode == MAC_SCAN_ED)
  378. {
  379. macRxFilter = RX_FILTER_ALL;
  380. }
  381. else if (scanMode == MAC_SCAN_ORPHAN)
  382. {
  383. macRxFilter = RX_FILTER_NON_COMMAND_FRAMES;
  384. }
  385. else
  386. {
  387. MAC_ASSERT((scanMode == MAC_SCAN_ACTIVE) || (scanMode == MAC_SCAN_PASSIVE)); /* invalid scan type */
  388. macRxFilter = RX_FILTER_NON_BEACON_FRAMES;
  389. /* for active and passive scans, per spec the pan ID must be 0xFFFF */
  390. MAC_RADIO_SET_PAN_ID(0xFFFF);
  391. }
  392. }
  393. /**************************************************************************************************
  394. * @fn macRadioStopScan
  395. *
  396. * @brief Takes radio out of scan mode. Note can be called if
  397. *
  398. * @param none
  399. *
  400. * @return none
  401. **************************************************************************************************
  402. */
  403. MAC_INTERNAL_API void macRadioStopScan(void)
  404. {
  405. macRxFilter = RX_FILTER_OFF;
  406. /* restore the pan ID (passive and active scans set pan ID to 0xFFFF) */
  407. MAC_RADIO_SET_PAN_ID(macPib.panId);
  408. }
  409. /**************************************************************************************************
  410. * @fn macRadioEnergyDetectStart
  411. *
  412. * @brief Initiates energy detect. The highest energy detected is recorded from the time
  413. * when this function is called until the energy detect is stopped.
  414. *
  415. * @param none
  416. *
  417. * @return none
  418. **************************************************************************************************
  419. */
  420. void macRadioEnergyDetectStart(void)
  421. {
  422. /* Energy Detection Scan should be run with CC2591 compresson workaround off */
  423. COMPRESSION_WORKAROUND_OFF();
  424. MAC_RADIO_RECORD_MAX_RSSI_START();
  425. }
  426. /**************************************************************************************************
  427. * @fn macRadioEnergyDetectStop
  428. *
  429. * @brief Called at completion of an energy detect. Note: can be called even if energy
  430. * detect is already stopped (needed by reset).
  431. *
  432. * @param none
  433. *
  434. * @return highest energy detect measurement
  435. **************************************************************************************************
  436. */
  437. uint8 macRadioEnergyDetectStop(void)
  438. {
  439. uint8 rssiDbm;
  440. uint8 energyDetectMeasurement;
  441. rssiDbm = MAC_RADIO_RECORD_MAX_RSSI_STOP() + MAC_RADIO_RSSI_OFFSET;
  442. MAC_RADIO_RSSI_LNA_OFFSET(rssiDbm);
  443. energyDetectMeasurement = radioComputeED(rssiDbm);
  444. /* Trun on CC2591 compresson workaround */
  445. COMPRESSION_WORKAROUND_ON();
  446. return(energyDetectMeasurement);
  447. }
  448. /*=================================================================================================
  449. * @fn radioComputeED
  450. *
  451. * @brief Compute energy detect measurement.
  452. *
  453. * @param rssi - raw RSSI value from radio hardware
  454. *
  455. * @return energy detect measurement in the range of 0x00-0xFF
  456. *=================================================================================================
  457. */
  458. static uint8 radioComputeED(int8 rssiDbm)
  459. {
  460. uint8 ed;
  461. /*
  462. * Keep RF power between minimum and maximum values.
  463. * This min/max range is derived from datasheet and specification.
  464. */
  465. if (rssiDbm < ED_RF_POWER_MIN_DBM)
  466. {
  467. rssiDbm = ED_RF_POWER_MIN_DBM;
  468. }
  469. else if (rssiDbm > ED_RF_POWER_MAX_DBM)
  470. {
  471. rssiDbm = ED_RF_POWER_MAX_DBM;
  472. }
  473. /*
  474. * Create energy detect measurement by normalizing and scaling RF power level.
  475. *
  476. * Note : The division operation below is designed for maximum accuracy and
  477. * best granularity. This is done by grouping the math operations to
  478. * compute the entire numerator before doing any division.
  479. */
  480. ed = (MAC_SPEC_ED_MAX * (rssiDbm - ED_RF_POWER_MIN_DBM)) / (ED_RF_POWER_MAX_DBM - ED_RF_POWER_MIN_DBM);
  481. return(ed);
  482. }
  483. /**************************************************************************************************
  484. * @fn macRadioComputeLQI
  485. *
  486. * @brief Compute link quality indication.
  487. *
  488. * @param rssi - raw RSSI value from radio hardware
  489. * corr - correlation value from radio hardware
  490. *
  491. * @return link quality indicator value
  492. **************************************************************************************************
  493. */
  494. MAC_INTERNAL_API uint8 macRadioComputeLQI(int8 rssiDbm, uint8 corr)
  495. {
  496. (void) corr; /* suppress compiler warning of unused parameter */
  497. /*
  498. * Note : Currently the LQI value is simply the energy detect measurement.
  499. * A more accurate value could be derived by using the correlation
  500. * value along with the RSSI value.
  501. */
  502. return(radioComputeED(rssiDbm));
  503. }
  504. /**************************************************************************************************
  505. */