mac_radio.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561
  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-2009 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. void macRadioInit(void)
  88. {
  89. /* variable initialization for this module */
  90. reqChannel = MAC_RADIO_CHANNEL_DEFAULT;
  91. macPhyChannel = MAC_RADIO_CHANNEL_DEFAULT;
  92. reqTxPower = MAC_RADIO_TX_POWER_DEFAULT;
  93. macPhyTxPower = MAC_RADIO_TX_POWER_DEFAULT;
  94. }
  95. /**************************************************************************************************
  96. * @fn macRadioReset
  97. *
  98. * @brief Resets the radio module.
  99. *
  100. * @param none
  101. *
  102. * @return none
  103. **************************************************************************************************
  104. */
  105. 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. 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. 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. 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. 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 none
  196. **************************************************************************************************
  197. */
  198. #ifndef HAL_MAC_USE_REGISTER_POWER_VALUES
  199. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  200. void macRadioSetTxPower(uint8 txPower)
  201. {
  202. halIntState_t s;
  203. /* if the selected dBm is out of range, use the closest available */
  204. if (txPower > MAC_RADIO_TX_POWER_MAX_DBM)
  205. {
  206. txPower = MAC_RADIO_TX_POWER_MAX_DBM;
  207. }
  208. /*
  209. * Set the global variable reqTxPower. This variable is referenced
  210. * by the function macRadioUpdateTxPower() to write the radio register.
  211. *
  212. * A lookup table is used to translate the power level to the register
  213. * value.
  214. */
  215. HAL_ENTER_CRITICAL_SECTION(s);
  216. reqTxPower = macRadioDefsTxPowerTable[txPower];
  217. HAL_EXIT_CRITICAL_SECTION(s);
  218. /* update the radio power setting */
  219. macRadioUpdateTxPower();
  220. }
  221. #else
  222. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  223. void macRadioSetTxPower(uint8 txPower)
  224. {
  225. halIntState_t s;
  226. /* same as above but with no lookup table, use raw register value */
  227. HAL_ENTER_CRITICAL_SECTION(s);
  228. reqTxPower = txPower;
  229. HAL_EXIT_CRITICAL_SECTION(s);
  230. /* update the radio power setting */
  231. macRadioUpdateTxPower();
  232. }
  233. #endif
  234. /**************************************************************************************************
  235. * @fn macRadioUpdateTxPower
  236. *
  237. * @brief Update the radio's transmit power if a new power level has been requested
  238. *
  239. * @param reqTxPower - file scope variable that holds the last request power level
  240. * macPhyTxPower - global variable that holds radio's set power level
  241. *
  242. * @return none
  243. **************************************************************************************************
  244. */
  245. void macRadioUpdateTxPower(void)
  246. {
  247. halIntState_t s;
  248. /*
  249. * If the requested power setting is different from the actual radio setting,
  250. * attempt to udpate to the new power setting.
  251. */
  252. HAL_ENTER_CRITICAL_SECTION(s);
  253. if (reqTxPower != macPhyTxPower)
  254. {
  255. /*
  256. * Radio power cannot be updated when the radio is physically transmitting.
  257. * If there is a possibility radio is transmitting, do not change the power
  258. * setting. This function will be called again after the current transmit
  259. * completes.
  260. */
  261. if (!macRxOutgoingAckFlag && !MAC_TX_IS_PHYSICALLY_ACTIVE())
  262. {
  263. /*
  264. * Set new power level; update the shadow value and write
  265. * the new value to the radio hardware.
  266. */
  267. macPhyTxPower = reqTxPower;
  268. MAC_RADIO_SET_TX_POWER(macPhyTxPower);
  269. }
  270. }
  271. HAL_EXIT_CRITICAL_SECTION(s);
  272. }
  273. /**************************************************************************************************
  274. * @fn macRadioSetChannel
  275. *
  276. * @brief Set radio channel.
  277. *
  278. * @param channel - channel number, valid range is 11 through 26
  279. *
  280. * @return none
  281. **************************************************************************************************
  282. */
  283. void macRadioSetChannel(uint8 channel)
  284. {
  285. halIntState_t s;
  286. MAC_ASSERT((channel >= 11) && (channel <= 28)); /* illegal channel */
  287. /* critical section to make sure transmit does not start while updating channel */
  288. HAL_ENTER_CRITICAL_SECTION(s);
  289. /* set requested channel */
  290. reqChannel = channel;
  291. /*
  292. * If transmit is not active, update the radio hardware immediately. If transmit is active,
  293. * the channel will be updated at the end of the current transmit.
  294. */
  295. if (!macTxActive)
  296. {
  297. macRadioUpdateChannel();
  298. }
  299. HAL_EXIT_CRITICAL_SECTION(s);
  300. }
  301. /**************************************************************************************************
  302. * @fn macRadioUpdateChannel
  303. *
  304. * @brief Update the radio channel if a new channel has been requested.
  305. *
  306. * @param none
  307. *
  308. * @return none
  309. **************************************************************************************************
  310. */
  311. void macRadioUpdateChannel(void)
  312. {
  313. halIntState_t s;
  314. MAC_ASSERT(!macTxActive); /* cannot change channel during a transmit */
  315. /* if the channel has changed, set the radio to the new channel */
  316. HAL_ENTER_CRITICAL_SECTION(s);
  317. if (reqChannel != macPhyChannel)
  318. {
  319. macPhyChannel = reqChannel;
  320. HAL_EXIT_CRITICAL_SECTION(s);
  321. /* changing the channel stops any receive in progress */
  322. macRxOff();
  323. MAC_RADIO_SET_CHANNEL(macPhyChannel);
  324. /* If the channel is updated in the middle of receiving a frame, we must
  325. * clean up the Rx logic.
  326. */
  327. macRxHaltCleanup();
  328. macRxOnRequest();
  329. }
  330. else
  331. {
  332. HAL_EXIT_CRITICAL_SECTION(s);
  333. }
  334. }
  335. /**************************************************************************************************
  336. * @fn macRadioStartScan
  337. *
  338. * @brief Puts radio into selected scan mode.
  339. *
  340. * @param scanMode - scan mode, see #defines in .h file
  341. *
  342. * @return none
  343. **************************************************************************************************
  344. */
  345. void macRadioStartScan(uint8 scanMode)
  346. {
  347. MAC_ASSERT(macSleepState == MAC_SLEEP_STATE_AWAKE); /* radio must be awake */
  348. MAC_ASSERT(macRxFilter == RX_FILTER_OFF); /* all filtering must be off to start scan */
  349. /* set the receive filter based on the selected scan mode */
  350. if (scanMode == MAC_SCAN_ED)
  351. {
  352. macRxFilter = RX_FILTER_ALL;
  353. }
  354. else if (scanMode == MAC_SCAN_ORPHAN)
  355. {
  356. macRxFilter = RX_FILTER_NON_COMMAND_FRAMES;
  357. }
  358. else
  359. {
  360. MAC_ASSERT((scanMode == MAC_SCAN_ACTIVE) || (scanMode == MAC_SCAN_PASSIVE)); /* invalid scan type */
  361. macRxFilter = RX_FILTER_NON_BEACON_FRAMES;
  362. /* for active and passive scans, per spec the pan ID must be 0xFFFF */
  363. MAC_RADIO_SET_PAN_ID(0xFFFF);
  364. }
  365. }
  366. /**************************************************************************************************
  367. * @fn macRadioStopScan
  368. *
  369. * @brief Takes radio out of scan mode. Note can be called if
  370. *
  371. * @param none
  372. *
  373. * @return none
  374. **************************************************************************************************
  375. */
  376. void macRadioStopScan(void)
  377. {
  378. macRxFilter = RX_FILTER_OFF;
  379. /* restore the pan ID (passive and active scans set pan ID to 0xFFFF) */
  380. MAC_RADIO_SET_PAN_ID(macPib.panId);
  381. }
  382. /**************************************************************************************************
  383. * @fn macRadioEnergyDetectStart
  384. *
  385. * @brief Initiates energy detect. The highest energy detected is recorded from the time
  386. * when this function is called until the energy detect is stopped.
  387. *
  388. * @param none
  389. *
  390. * @return none
  391. **************************************************************************************************
  392. */
  393. void macRadioEnergyDetectStart(void)
  394. {
  395. MAC_RADIO_RECORD_MAX_RSSI_START();
  396. }
  397. /**************************************************************************************************
  398. * @fn macRadioEnergyDetectStop
  399. *
  400. * @brief Called at completion of an energy detect. Note: can be called even if energy
  401. * detect is already stopped (needed by reset).
  402. *
  403. * @param none
  404. *
  405. * @return highest energy detect measurement
  406. **************************************************************************************************
  407. */
  408. uint8 macRadioEnergyDetectStop(void)
  409. {
  410. uint8 rssiDbm;
  411. uint8 energyDetectMeasurement;
  412. rssiDbm = MAC_RADIO_RECORD_MAX_RSSI_STOP() + MAC_RADIO_RSSI_OFFSET;
  413. #if defined (HAL_PA_LNA) || defined (HAL_PA_LNA_CC2590)
  414. MAC_RADIO_RSSI_LNA_OFFSET(rssiDbm);
  415. #endif
  416. energyDetectMeasurement = radioComputeED(rssiDbm);
  417. return(energyDetectMeasurement);
  418. }
  419. /*=================================================================================================
  420. * @fn radioComputeED
  421. *
  422. * @brief Compute energy detect measurement.
  423. *
  424. * @param rssi - raw RSSI value from radio hardware
  425. *
  426. * @return energy detect measurement in the range of 0x00-0xFF
  427. *=================================================================================================
  428. */
  429. static uint8 radioComputeED(int8 rssiDbm)
  430. {
  431. uint8 ed;
  432. /*
  433. * Keep RF power between minimum and maximum values.
  434. * This min/max range is derived from datasheet and specification.
  435. */
  436. if (rssiDbm < ED_RF_POWER_MIN_DBM)
  437. {
  438. rssiDbm = ED_RF_POWER_MIN_DBM;
  439. }
  440. else if (rssiDbm > ED_RF_POWER_MAX_DBM)
  441. {
  442. rssiDbm = ED_RF_POWER_MAX_DBM;
  443. }
  444. /*
  445. * Create energy detect measurement by normalizing and scaling RF power level.
  446. *
  447. * Note : The division operation below is designed for maximum accuracy and
  448. * best granularity. This is done by grouping the math operations to
  449. * compute the entire numerator before doing any division.
  450. */
  451. ed = (MAC_SPEC_ED_MAX * (rssiDbm - ED_RF_POWER_MIN_DBM)) / (ED_RF_POWER_MAX_DBM - ED_RF_POWER_MIN_DBM);
  452. return(ed);
  453. }
  454. /**************************************************************************************************
  455. * @fn macRadioComputeLQI
  456. *
  457. * @brief Compute link quality indication.
  458. *
  459. * @param rssi - raw RSSI value from radio hardware
  460. * corr - correlation value from radio hardware
  461. *
  462. * @return link quality indicator value
  463. **************************************************************************************************
  464. */
  465. uint8 macRadioComputeLQI(int8 rssiDbm, uint8 corr)
  466. {
  467. (void) corr; /* suppress compiler warning of unused parameter */
  468. /*
  469. * Note : Currently the LQI value is simply the energy detect measurement.
  470. * A more accurate value could be derived by using the correlation
  471. * value along with the RSSI value.
  472. */
  473. return(radioComputeED(rssiDbm));
  474. }
  475. /**************************************************************************************************
  476. */