You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

788 rivejä
22 KiB

  1. /**
  2. *
  3. * \file
  4. *
  5. * \brief NMC1500 Peripherials Application Interface.
  6. *
  7. * Copyright (c) 2014 - 2018 Atmel Corporation. All rights reserved.
  8. *
  9. * \asf_license_start
  10. *
  11. * \page License
  12. *
  13. * Redistribution and use in source and binary forms, with or without
  14. * modification, are permitted provided that the following conditions are met:
  15. *
  16. * 1. Redistributions of source code must retain the above copyright notice,
  17. * this list of conditions and the following disclaimer.
  18. *
  19. * 2. Redistributions in binary form must reproduce the above copyright notice,
  20. * this list of conditions and the following disclaimer in the documentation
  21. * and/or other materials provided with the distribution.
  22. *
  23. * 3. The name of Atmel may not be used to endorse or promote products derived
  24. * from this software without specific prior written permission.
  25. *
  26. * 4. This software may only be redistributed and used in connection with an
  27. * Atmel microcontroller product.
  28. *
  29. * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
  30. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  31. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
  32. * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
  33. * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  34. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  35. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  36. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  37. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  38. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  39. * POSSIBILITY OF SUCH DAMAGE.
  40. *
  41. * \asf_license_stop
  42. *
  43. */
  44. #ifdef _M2M_ATE_FW_
  45. /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
  46. INCLUDES
  47. *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
  48. #include "driver/include/m2m_ate_mode.h"
  49. #include "driver/source/nmasic.h"
  50. #include "driver/source/nmdrv.h"
  51. #include "m2m_hif.h"
  52. #include "driver/source/nmbus.h"
  53. #include "bsp/include/nm_bsp.h"
  54. /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
  55. MACROS
  56. *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
  57. #define rInterrupt_CORTUS_0 (0x10a8)
  58. #define rInterrupt_CORTUS_1 (0x10ac)
  59. #define rInterrupt_CORTUS_2 (0x10b0)
  60. #define rBurstTx_NMI_TX_RATE (0x161d00)
  61. #define rBurstTx_NMI_NUM_TX_FRAMES (0x161d04)
  62. #define rBurstTx_NMI_TX_FRAME_LEN (0x161d08)
  63. #define rBurstTx_NMI_TX_CW_PARAM (0x161d0c)
  64. #define rBurstTx_NMI_TX_GAIN (0x161d10)
  65. #define rBurstTx_NMI_TX_DPD_CTRL (0x161d14)
  66. #define rBurstTx_NMI_USE_PMU (0x161d18)
  67. #define rBurstTx_NMI_TEST_CH (0x161d1c)
  68. #define rBurstTx_NMI_TX_PHY_CONT (0x161d20)
  69. #define rBurstTx_NMI_TX_CW_MODE (0x161d24)
  70. #define rBurstTx_NMI_TEST_XO_OFF (0x161d28)
  71. #define rBurstTx_NMI_USE_EFUSE_XO_OFF (0x161d2c)
  72. #define rBurstTx_NMI_MAC_FILTER_ENABLE_DA (0x161d30)
  73. #define rBurstTx_NMI_MAC_ADDR_LO_PEER (0x161d34)
  74. #define rBurstTx_NMI_MAC_ADDR_LO_SELF (0x161d38)
  75. #define rBurstTx_NMI_MAC_ADDR_HI_PEER (0x161d3c)
  76. #define rBurstTx_NMI_MAC_ADDR_HI_SELF (0x161d40)
  77. #define rBurstTx_NMI_RX_PKT_CNT_SUCCESS (0x161d44)
  78. #define rBurstTx_NMI_RX_PKT_CNT_FAIL (0x161d48)
  79. #define rBurstTx_NMI_SET_SELF_MAC_ADDR (0x161d4c)
  80. #define rBurstTx_NMI_MAC_ADDR_LO_SA (0x161d50)
  81. #define rBurstTx_NMI_MAC_ADDR_HI_SA (0x161d54)
  82. #define rBurstTx_NMI_MAC_FILTER_ENABLE_SA (0x161d58)
  83. #define rBurstRx_NMI_RX_ALL_PKTS_CONT (0x9898)
  84. #define rBurstRx_NMI_RX_ERR_PKTS_CONT (0x988c)
  85. #define TX_DGAIN_MAX_NUM_REGS (4)
  86. #define TX_DGAIN_REG_BASE_ADDRESS (0x1240)
  87. #define TX_GAIN_CODE_MAX_NUM_REGS (3)
  88. #define TX_GAIN_CODE_BASE_ADDRESS (0x1250)
  89. #define TX_PA_MAX_NUM_REGS (3)
  90. #define TX_PA_BASE_ADDRESS (0x1e58)
  91. /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
  92. VARIABLES
  93. *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
  94. volatile static uint8 gu8AteIsRunning = 0; /*!< ATE firmware status, 1 means ATE is running otherwise stopped */
  95. volatile static uint8 gu8RxState = 0; /*!< RX status, 1 means Rx is running otherwise stopped */
  96. volatile static uint8 gu8TxState = 0; /*!< TX status, 1 means Tx is running otherwise stopped */
  97. volatile static uint32 gaAteFwTxRates[M2M_ATE_MAX_NUM_OF_RATES] = {
  98. 0x01, 0x02, 0x05, 0x0B, /*B-Rats*/
  99. 0x06, 0x09, 0x0C, 0x12, 0x18, 0x24, 0x30, 0x36, /*G-Rats*/
  100. 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87 /*N-Rats*/
  101. };
  102. /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
  103. STATIC FUNCTIONS
  104. *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
  105. static void m2m_ate_set_rx_status(uint8 u8Value)
  106. {
  107. gu8RxState = u8Value;
  108. }
  109. static void m2m_ate_set_tx_status(uint8 u8Value)
  110. {
  111. gu8TxState = u8Value;
  112. }
  113. /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
  114. FUNCTION IMPLEMENTATION
  115. *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
  116. /*!
  117. @fn \
  118. sint8 m2m_ate_init(void);
  119. @brief
  120. This function used to download ATE firmware from flash and start it
  121. @return
  122. The function SHALL return 0 for success and a negative value otherwise.
  123. */
  124. sint8 m2m_ate_init(void)
  125. {
  126. sint8 s8Ret = M2M_SUCCESS;
  127. uint8 u8WifiMode = M2M_WIFI_MODE_ATE_HIGH;
  128. s8Ret = nm_drv_init(&u8WifiMode);
  129. return s8Ret;
  130. }
  131. /*!
  132. @fn \
  133. sint8 m2m_ate_init(tstrM2mAteInit *pstrInit);
  134. @brief
  135. This function used to download ATE firmware from flash and start it
  136. @return
  137. The function SHALL return 0 for success and a negative value otherwise.
  138. */
  139. sint8 m2m_ate_init_param(tstrM2mAteInit *pstrInit)
  140. {
  141. sint8 s8Ret = M2M_SUCCESS;
  142. s8Ret = nm_drv_init((void *)&pstrInit->u8RxPwrMode);
  143. return s8Ret;
  144. }
  145. /*!
  146. @fn \
  147. sint8 m2m_ate_deinit(void);
  148. @brief
  149. De-Initialization of ATE firmware mode
  150. @return
  151. The function SHALL return 0 for success and a negative value otherwise.
  152. */
  153. sint8 m2m_ate_deinit(void)
  154. {
  155. return nm_drv_deinit(NULL);
  156. }
  157. /*!
  158. @fn \
  159. sint8 m2m_ate_set_fw_state(uint8);
  160. @brief
  161. This function used to change ATE firmware status from running to stopped or vice versa.
  162. @param [in] u8State
  163. Required state of ATE firmware, one of \ref tenuM2mAteFwState enumeration values.
  164. @return
  165. The function SHALL return 0 for success and a negative value otherwise.
  166. \sa
  167. m2m_ate_init
  168. */
  169. sint8 m2m_ate_set_fw_state(uint8 u8State)
  170. {
  171. sint8 s8Ret = M2M_SUCCESS;
  172. uint32_t u32Val = 0;
  173. if ((M2M_ATE_FW_STATE_STOP == u8State) && (M2M_ATE_FW_STATE_STOP != gu8AteIsRunning)) {
  174. u32Val = nm_read_reg(rNMI_GLB_RESET);
  175. u32Val &= ~(1 << 10);
  176. s8Ret = nm_write_reg(rNMI_GLB_RESET, u32Val);
  177. gu8AteIsRunning = M2M_ATE_FW_STATE_STOP;
  178. } else if ((M2M_ATE_FW_STATE_RUN == u8State) && (M2M_ATE_FW_STATE_RUN != gu8AteIsRunning)) {
  179. /* 0x1118[0]=0 at power-on-reset: pad-based control. */
  180. /* Switch cortus reset register to register control. 0x1118[0]=1. */
  181. u32Val = nm_read_reg(rNMI_BOOT_RESET_MUX);
  182. u32Val |= (1 << 0);
  183. s8Ret = nm_write_reg(rNMI_BOOT_RESET_MUX, u32Val);
  184. if (M2M_SUCCESS != s8Ret) {
  185. goto __EXIT;
  186. }
  187. /**
  188. Write the firmware download complete magic value 0x10ADD09E at
  189. location 0xFFFF000C (Cortus map) or C000C (AHB map).
  190. This will let the boot-rom code execute from RAM.
  191. **/
  192. s8Ret = nm_write_reg(0xc0000, 0x71);
  193. if (M2M_SUCCESS != s8Ret) {
  194. goto __EXIT;
  195. }
  196. u32Val = nm_read_reg(rNMI_GLB_RESET);
  197. if ((u32Val & (1ul << 10)) == (1ul << 10)) {
  198. u32Val &= ~(1ul << 10);
  199. s8Ret = nm_write_reg(rNMI_GLB_RESET, u32Val);
  200. if (M2M_SUCCESS != s8Ret) {
  201. goto __EXIT;
  202. }
  203. }
  204. u32Val |= (1ul << 10);
  205. s8Ret = nm_write_reg(rNMI_GLB_RESET, u32Val);
  206. if (M2M_SUCCESS != s8Ret) {
  207. goto __EXIT;
  208. }
  209. gu8AteIsRunning = M2M_ATE_FW_STATE_RUN;
  210. } else {
  211. s8Ret = M2M_ATE_ERR_UNHANDLED_CASE;
  212. }
  213. __EXIT:
  214. if ((M2M_SUCCESS == s8Ret) && (M2M_ATE_FW_STATE_RUN == gu8AteIsRunning)) {
  215. nm_bsp_sleep(500); /*wait for ATE firmware start up*/
  216. }
  217. return s8Ret;
  218. }
  219. /*!
  220. @fn \
  221. sint8 m2m_ate_get_fw_state(uint8);
  222. @brief
  223. This function used to return status of ATE firmware.
  224. @return
  225. The function SHALL return status of ATE firmware, one of \ref tenuM2mAteFwState enumeration values.
  226. \sa
  227. m2m_ate_init, m2m_ate_set_fw_state
  228. */
  229. sint8 m2m_ate_get_fw_state(void)
  230. {
  231. return gu8AteIsRunning;
  232. }
  233. /*!
  234. @fn \
  235. uint32 m2m_ate_get_tx_rate(uint8);
  236. @brief
  237. This function used to return value of TX rate required by application developer.
  238. @param [in] u8Index
  239. Index of required rate , one of \ref tenuM2mAteTxIndexOfRates enumeration values.
  240. @return
  241. The function SHALL return 0 for in case of failure otherwise selected rate value.
  242. \sa
  243. tenuM2mAteTxIndexOfRates
  244. */
  245. uint32 m2m_ate_get_tx_rate(uint8 u8Index)
  246. {
  247. if (M2M_ATE_MAX_NUM_OF_RATES <= u8Index) {
  248. return 0;
  249. }
  250. return gaAteFwTxRates[u8Index];
  251. }
  252. /*!
  253. @fn \
  254. sint8 m2m_ate_get_tx_status(void);
  255. @brief
  256. This function used to return status of TX test case either running or stopped.
  257. @return
  258. The function SHALL return status of ATE firmware, 1 if TX is running otherwise 0.
  259. \sa
  260. m2m_ate_start_tx, m2m_ate_stop_tx
  261. */
  262. sint8 m2m_ate_get_tx_status(void)
  263. {
  264. return gu8TxState;
  265. }
  266. /*!
  267. @fn \
  268. sint8 m2m_ate_start_tx(tstrM2mAteTx *)
  269. @brief
  270. This function used to start TX test case.
  271. @param [in] strM2mAteTx
  272. Type of \ref tstrM2mAteTx, with the values required to enable TX test case. You must use \ref m2m_ate_init
  273. first.
  274. @return
  275. The function SHALL return 0 for success and a negative value otherwise.
  276. \sa
  277. m2m_ate_init, m2m_ate_stop_tx, m2m_ate_get_tx_status
  278. */
  279. sint8 m2m_ate_start_tx(tstrM2mAteTx *strM2mAteTx)
  280. {
  281. sint8 s8Ret = M2M_SUCCESS;
  282. uint8 u8LoopCntr = 0;
  283. uint32_t val32;
  284. if (NULL == strM2mAteTx) {
  285. s8Ret = M2M_ATE_ERR_VALIDATE;
  286. goto __EXIT;
  287. }
  288. if (0 != m2m_ate_get_tx_status()) {
  289. s8Ret = M2M_ATE_ERR_TX_ALREADY_RUNNING;
  290. goto __EXIT;
  291. }
  292. if (0 != m2m_ate_get_rx_status()) {
  293. s8Ret = M2M_ATE_ERR_RX_ALREADY_RUNNING;
  294. goto __EXIT;
  295. }
  296. if ((strM2mAteTx->channel_num < M2M_ATE_CHANNEL_1) || (strM2mAteTx->channel_num > M2M_ATE_CHANNEL_14)
  297. || (strM2mAteTx->tx_gain_sel < M2M_ATE_TX_GAIN_DYNAMIC) || (strM2mAteTx->tx_gain_sel > M2M_ATE_TX_GAIN_TELEC)
  298. || (strM2mAteTx->frame_len > M2M_ATE_MAX_FRAME_LENGTH) || (strM2mAteTx->frame_len < M2M_ATE_MIN_FRAME_LENGTH)) {
  299. s8Ret = M2M_ATE_ERR_VALIDATE;
  300. goto __EXIT;
  301. }
  302. if ((strM2mAteTx->duty_cycle < M2M_ATE_TX_DUTY_MAX_VALUE /*1*/)
  303. || (strM2mAteTx->duty_cycle > M2M_ATE_TX_DUTY_MIN_VALUE /*10*/)
  304. || (strM2mAteTx->dpd_ctrl < M2M_ATE_TX_DPD_DYNAMIC) || (strM2mAteTx->dpd_ctrl > M2M_ATE_TX_DPD_ENABLED)
  305. || (strM2mAteTx->use_pmu > M2M_ATE_PMU_ENABLE) || (strM2mAteTx->phy_burst_tx < M2M_ATE_TX_SRC_MAC)
  306. || (strM2mAteTx->phy_burst_tx > M2M_ATE_TX_SRC_PHY) || (strM2mAteTx->cw_tx < M2M_ATE_TX_MODE_NORM)
  307. || (strM2mAteTx->cw_tx > M2M_ATE_TX_MODE_CW)) {
  308. s8Ret = M2M_ATE_ERR_VALIDATE;
  309. goto __EXIT;
  310. }
  311. for (u8LoopCntr = 0; u8LoopCntr < M2M_ATE_MAX_NUM_OF_RATES; u8LoopCntr++) {
  312. if (gaAteFwTxRates[u8LoopCntr] == strM2mAteTx->data_rate) {
  313. break;
  314. }
  315. }
  316. if (M2M_ATE_MAX_NUM_OF_RATES == u8LoopCntr) {
  317. s8Ret = M2M_ATE_ERR_VALIDATE;
  318. goto __EXIT;
  319. }
  320. s8Ret += nm_write_reg(rBurstTx_NMI_USE_PMU, strM2mAteTx->use_pmu);
  321. s8Ret += nm_write_reg(rBurstTx_NMI_TX_PHY_CONT, strM2mAteTx->phy_burst_tx);
  322. s8Ret += nm_write_reg(rBurstTx_NMI_NUM_TX_FRAMES, strM2mAteTx->num_frames);
  323. s8Ret += nm_write_reg(rBurstTx_NMI_TX_GAIN, strM2mAteTx->tx_gain_sel);
  324. s8Ret += nm_write_reg(rBurstTx_NMI_TEST_CH, strM2mAteTx->channel_num);
  325. s8Ret += nm_write_reg(rBurstTx_NMI_TX_FRAME_LEN, strM2mAteTx->frame_len);
  326. s8Ret += nm_write_reg(rBurstTx_NMI_TX_CW_PARAM, strM2mAteTx->duty_cycle);
  327. s8Ret += nm_write_reg(rBurstTx_NMI_TX_DPD_CTRL, strM2mAteTx->dpd_ctrl);
  328. s8Ret += nm_write_reg(rBurstTx_NMI_TX_RATE, strM2mAteTx->data_rate);
  329. s8Ret += nm_write_reg(rBurstTx_NMI_TX_CW_MODE, strM2mAteTx->cw_tx);
  330. s8Ret += nm_write_reg(rBurstTx_NMI_TEST_XO_OFF, strM2mAteTx->xo_offset_x1000);
  331. s8Ret += nm_write_reg(rBurstTx_NMI_USE_EFUSE_XO_OFF, strM2mAteTx->use_efuse_xo_offset);
  332. val32 = strM2mAteTx->peer_mac_addr[5] << 0;
  333. val32 |= strM2mAteTx->peer_mac_addr[4] << 8;
  334. val32 |= strM2mAteTx->peer_mac_addr[3] << 16;
  335. nm_write_reg(rBurstTx_NMI_MAC_ADDR_LO_PEER, val32);
  336. val32 = strM2mAteTx->peer_mac_addr[2] << 0;
  337. val32 |= strM2mAteTx->peer_mac_addr[1] << 8;
  338. val32 |= strM2mAteTx->peer_mac_addr[0] << 16;
  339. nm_write_reg(rBurstTx_NMI_MAC_ADDR_HI_PEER, val32);
  340. if (M2M_SUCCESS == s8Ret) {
  341. s8Ret += nm_write_reg(rInterrupt_CORTUS_0, 1); /*Interrupt Cortus*/
  342. m2m_ate_set_tx_status(1);
  343. nm_bsp_sleep(200); /*Recommended*/
  344. }
  345. __EXIT:
  346. return s8Ret;
  347. }
  348. /*!
  349. @fn \
  350. sint8 m2m_ate_stop_tx(void)
  351. @brief
  352. This function used to stop TX test case.
  353. @return
  354. The function SHALL return 0 for success and a negative value otherwise.
  355. \sa
  356. m2m_ate_init, m2m_ate_start_tx, m2m_ate_get_tx_status
  357. */
  358. sint8 m2m_ate_stop_tx(void)
  359. {
  360. sint8 s8Ret = M2M_SUCCESS;
  361. s8Ret = nm_write_reg(rInterrupt_CORTUS_1, 1);
  362. if (M2M_SUCCESS == s8Ret) {
  363. m2m_ate_set_tx_status(0);
  364. }
  365. return s8Ret;
  366. }
  367. /*!
  368. @fn \
  369. sint8 m2m_ate_get_rx_status(uint8);
  370. @brief
  371. This function used to return status of RX test case either running or stopped.
  372. @return
  373. The function SHALL return status of ATE firmware, 1 if RX is running otherwise 0.
  374. \sa
  375. m2m_ate_start_rx, m2m_ate_stop_rx
  376. */
  377. sint8 m2m_ate_get_rx_status(void)
  378. {
  379. return gu8RxState;
  380. }
  381. /*!
  382. @fn \
  383. sint8 m2m_ate_start_rx(tstrM2mAteRx *)
  384. @brief
  385. This function used to start RX test case.
  386. @param [in] strM2mAteRx
  387. Type of \ref tstrM2mAteRx, with the values required to enable RX test case. You must use \ref m2m_ate_init
  388. first.
  389. @return
  390. The function SHALL return 0 for success and a negative value otherwise.
  391. \sa
  392. m2m_ate_init, m2m_ate_stop_rx, m2m_ate_get_rx_status
  393. */
  394. sint8 m2m_ate_start_rx(tstrM2mAteRx *strM2mAteRxStr)
  395. {
  396. sint8 s8Ret = M2M_SUCCESS;
  397. uint32 val32;
  398. if (NULL == strM2mAteRxStr) {
  399. s8Ret = M2M_ATE_ERR_VALIDATE;
  400. goto __EXIT;
  401. }
  402. if (0 != m2m_ate_get_tx_status()) {
  403. s8Ret = M2M_ATE_ERR_TX_ALREADY_RUNNING;
  404. goto __EXIT;
  405. }
  406. if (0 != m2m_ate_get_rx_status()) {
  407. s8Ret = M2M_ATE_ERR_RX_ALREADY_RUNNING;
  408. goto __EXIT;
  409. }
  410. if ((strM2mAteRxStr->channel_num < M2M_ATE_CHANNEL_1) || (strM2mAteRxStr->channel_num > M2M_ATE_CHANNEL_14)
  411. || (strM2mAteRxStr->use_pmu > M2M_ATE_PMU_ENABLE)) {
  412. s8Ret = M2M_ATE_ERR_VALIDATE;
  413. goto __EXIT;
  414. }
  415. s8Ret += nm_write_reg(rBurstTx_NMI_TEST_CH, strM2mAteRxStr->channel_num);
  416. s8Ret += nm_write_reg(rBurstTx_NMI_USE_PMU, strM2mAteRxStr->use_pmu);
  417. s8Ret += nm_write_reg(rBurstTx_NMI_TEST_XO_OFF, strM2mAteRxStr->xo_offset_x1000);
  418. s8Ret += nm_write_reg(rBurstTx_NMI_USE_EFUSE_XO_OFF, strM2mAteRxStr->use_efuse_xo_offset);
  419. if (strM2mAteRxStr->override_self_mac_addr) {
  420. val32 = strM2mAteRxStr->self_mac_addr[5] << 0;
  421. val32 |= strM2mAteRxStr->self_mac_addr[4] << 8;
  422. val32 |= strM2mAteRxStr->self_mac_addr[3] << 16;
  423. nm_write_reg(rBurstTx_NMI_MAC_ADDR_LO_SELF, val32);
  424. val32 = strM2mAteRxStr->self_mac_addr[2] << 0;
  425. val32 |= strM2mAteRxStr->self_mac_addr[1] << 8;
  426. val32 |= strM2mAteRxStr->self_mac_addr[0] << 16;
  427. nm_write_reg(rBurstTx_NMI_MAC_ADDR_HI_SELF, val32);
  428. }
  429. if (strM2mAteRxStr->mac_filter_en_sa) {
  430. val32 = strM2mAteRxStr->peer_mac_addr[5] << 0;
  431. val32 |= strM2mAteRxStr->peer_mac_addr[4] << 8;
  432. val32 |= strM2mAteRxStr->peer_mac_addr[3] << 16;
  433. nm_write_reg(rBurstTx_NMI_MAC_ADDR_LO_SA, val32);
  434. val32 = strM2mAteRxStr->peer_mac_addr[2] << 0;
  435. val32 |= strM2mAteRxStr->peer_mac_addr[1] << 8;
  436. val32 |= strM2mAteRxStr->peer_mac_addr[0] << 16;
  437. nm_write_reg(rBurstTx_NMI_MAC_ADDR_HI_SA, val32);
  438. }
  439. nm_write_reg(rBurstTx_NMI_MAC_FILTER_ENABLE_DA, strM2mAteRxStr->mac_filter_en_da);
  440. nm_write_reg(rBurstTx_NMI_MAC_FILTER_ENABLE_SA, strM2mAteRxStr->mac_filter_en_sa);
  441. nm_write_reg(rBurstTx_NMI_SET_SELF_MAC_ADDR, strM2mAteRxStr->override_self_mac_addr);
  442. if (M2M_SUCCESS == s8Ret) {
  443. s8Ret += nm_write_reg(rInterrupt_CORTUS_2, 1); /*Interrupt Cortus*/
  444. m2m_ate_set_rx_status(1);
  445. nm_bsp_sleep(10); /*Recommended*/
  446. }
  447. __EXIT:
  448. return s8Ret;
  449. }
  450. /*!
  451. @fn \
  452. sint8 m2m_ate_stop_rx(void)
  453. @brief
  454. This function used to stop RX test case.
  455. @return
  456. The function SHALL return 0 for success and a negative value otherwise.
  457. \sa
  458. m2m_ate_init, m2m_ate_start_rx, m2m_ate_get_rx_status
  459. */
  460. sint8 m2m_ate_stop_rx(void)
  461. {
  462. m2m_ate_set_rx_status(0);
  463. nm_bsp_sleep(200); /*Recommended*/
  464. return M2M_SUCCESS;
  465. }
  466. /*!
  467. @fn \
  468. sint8 m2m_ate_read_rx_status(tstrM2mAteRxStatus *)
  469. @brief
  470. This function used to read RX statistics from ATE firmware.
  471. @param [out] strM2mAteRxStatus
  472. Type of \ref tstrM2mAteRxStatus used to save statistics of RX test case. You must use \ref m2m_ate_start_rx
  473. first.
  474. @return
  475. The function SHALL return 0 for success and a negative value otherwise.
  476. \sa
  477. m2m_ate_init, m2m_ate_start_rx
  478. */
  479. sint8 m2m_ate_read_rx_status(tstrM2mAteRxStatus *strM2mAteRxStatus)
  480. {
  481. sint8 s8Ret = M2M_SUCCESS;
  482. if (NULL == strM2mAteRxStatus) {
  483. s8Ret = M2M_ATE_ERR_VALIDATE;
  484. goto __EXIT;
  485. }
  486. if (0 != m2m_ate_get_tx_status()) {
  487. s8Ret = M2M_ATE_ERR_TX_ALREADY_RUNNING;
  488. goto __EXIT;
  489. }
  490. if (nm_read_reg(rBurstTx_NMI_MAC_FILTER_ENABLE_DA) || nm_read_reg(rBurstTx_NMI_MAC_FILTER_ENABLE_SA)) {
  491. strM2mAteRxStatus->num_rx_pkts
  492. = nm_read_reg(rBurstTx_NMI_RX_PKT_CNT_SUCCESS) + nm_read_reg(rBurstTx_NMI_RX_PKT_CNT_FAIL);
  493. strM2mAteRxStatus->num_good_pkts = nm_read_reg(rBurstTx_NMI_RX_PKT_CNT_SUCCESS);
  494. strM2mAteRxStatus->num_err_pkts = nm_read_reg(rBurstTx_NMI_RX_PKT_CNT_FAIL);
  495. } else {
  496. strM2mAteRxStatus->num_rx_pkts = nm_read_reg(rBurstRx_NMI_RX_ALL_PKTS_CONT) + nm_read_reg(0x989c);
  497. strM2mAteRxStatus->num_err_pkts = nm_read_reg(rBurstRx_NMI_RX_ERR_PKTS_CONT);
  498. strM2mAteRxStatus->num_good_pkts = strM2mAteRxStatus->num_rx_pkts - strM2mAteRxStatus->num_err_pkts;
  499. }
  500. __EXIT:
  501. return s8Ret;
  502. }
  503. /*!
  504. @fn \
  505. sint8 m2m_ate_set_dig_gain(double dGaindB)
  506. @brief
  507. This function is used to set the digital gain
  508. @param [in] double dGaindB
  509. The digital gain value required to be set.
  510. @return
  511. The function SHALL return 0 for success and a negative value otherwise.
  512. */
  513. sint8 m2m_ate_set_dig_gain(double dGaindB)
  514. {
  515. uint32_t dGain, val32;
  516. dGain = (uint32_t)(pow(10, dGaindB / 20.0) * 1024.0);
  517. val32 = nm_read_reg(0x160cd0);
  518. val32 &= ~(0x1ffful << 0);
  519. val32 |= (((uint32_t)dGain) << 0);
  520. nm_write_reg(0x160cd0, val32);
  521. return M2M_SUCCESS;
  522. }
  523. /*!
  524. @fn \
  525. sint8 m2m_ate_get_dig_gain(double * dGaindB)
  526. @brief
  527. This function is used to get the digital gain
  528. @param [out] double * dGaindB
  529. The retrieved digital gain value obtained from HW registers in dB.
  530. @return
  531. The function SHALL return 0 for success and a negative value otherwise.
  532. */
  533. sint8 m2m_ate_get_dig_gain(double *dGaindB)
  534. {
  535. uint32 dGain, val32;
  536. if (!dGaindB)
  537. return M2M_ERR_INVALID_ARG;
  538. val32 = nm_read_reg(0x160cd0);
  539. dGain = (val32 >> 0) & 0x1ffful;
  540. *dGaindB = 20.0 * log10((double)dGain / 1024.0);
  541. return M2M_SUCCESS;
  542. }
  543. /*!
  544. @fn \
  545. void m2m_ate_set_pa_gain(uint8 gain_db)
  546. @brief
  547. This function is used to set the PA gain (18/15/12/9/6/3/0 only)
  548. @param [in] uint8 gain_db
  549. PA gain level allowed (18/15/12/9/6/3/0 only)
  550. */
  551. void m2m_ate_set_pa_gain(uint8 gain_db)
  552. {
  553. uint32 PA_1e9c;
  554. uint8 aGain[] = {/* "0 dB" */ 0x00,
  555. /* "3 dB" */ 0x01,
  556. /* "6 dB" */ 0x03,
  557. /* "9 dB" */ 0x07,
  558. /* "12 dB" */ 0x0f,
  559. /* "15 dB" */ 0x1f,
  560. /* "18 dB" */ 0x3f};
  561. /* The variable PA gain is valid only for High power mode */
  562. PA_1e9c = nm_read_reg(0x1e9c);
  563. /* TX bank 0. */
  564. PA_1e9c &= ~(0x3ful << 8);
  565. PA_1e9c |= (((uint32)aGain[gain_db / 3] & 0x3f) << 8);
  566. nm_write_reg(0x1e9c, PA_1e9c);
  567. }
  568. /*!
  569. @fn \
  570. sint8 m2m_ate_get_pa_gain(double *paGaindB)
  571. @brief
  572. This function is used to get the PA gain
  573. @param [out] double *paGaindB
  574. The retrieved PA gain value obtained from HW registers in dB.
  575. @return
  576. The function SHALL return 0 for success and a negative value otherwise.
  577. */
  578. sint8 m2m_ate_get_pa_gain(double *paGaindB)
  579. {
  580. uint32 val32, paGain;
  581. uint32 m_cmbPAGainStep;
  582. if (!paGaindB)
  583. return M2M_ERR_INVALID_ARG;
  584. val32 = nm_read_reg(0x1e9c);
  585. paGain = (val32 >> 8) & 0x3f;
  586. switch (paGain) {
  587. case 0x1:
  588. m_cmbPAGainStep = 5;
  589. break;
  590. case 0x3:
  591. m_cmbPAGainStep = 4;
  592. break;
  593. case 0x7:
  594. m_cmbPAGainStep = 3;
  595. break;
  596. case 0xf:
  597. m_cmbPAGainStep = 2;
  598. break;
  599. case 0x1f:
  600. m_cmbPAGainStep = 1;
  601. break;
  602. case 0x3f:
  603. m_cmbPAGainStep = 0;
  604. break;
  605. default:
  606. m_cmbPAGainStep = 0;
  607. break;
  608. }
  609. *paGaindB = 18 - m_cmbPAGainStep * 3;
  610. return M2M_SUCCESS;
  611. }
  612. /*!
  613. @fn \
  614. sint8 m2m_ate_get_ppa_gain(double * ppaGaindB)
  615. @brief
  616. This function is used to get the PPA gain
  617. @param [out] uint32 * ppaGaindB
  618. The retrieved PPA gain value obtained from HW registers in dB.
  619. @return
  620. The function SHALL return 0 for success and a negative value otherwise.
  621. */
  622. sint8 m2m_ate_get_ppa_gain(double *ppaGaindB)
  623. {
  624. uint32 val32, ppaGain, m_cmbPPAGainStep;
  625. if (!ppaGaindB)
  626. return M2M_ERR_INVALID_ARG;
  627. val32 = nm_read_reg(0x1ea0);
  628. ppaGain = (val32 >> 5) & 0x7;
  629. switch (ppaGain) {
  630. case 0x1:
  631. m_cmbPPAGainStep = 2;
  632. break;
  633. case 0x3:
  634. m_cmbPPAGainStep = 1;
  635. break;
  636. case 0x7:
  637. m_cmbPPAGainStep = 0;
  638. break;
  639. default:
  640. m_cmbPPAGainStep = 3;
  641. break;
  642. }
  643. *ppaGaindB = 9 - m_cmbPPAGainStep * 3;
  644. return M2M_SUCCESS;
  645. }
  646. /*!
  647. @fn \
  648. sint8 m2m_ate_get_tot_gain(double * totGaindB)
  649. @brief
  650. This function is used to calculate the total gain
  651. @param [out] double * totGaindB
  652. The retrieved total gain value obtained from calculations made based on the digital gain, PA and PPA gain
  653. values.
  654. @return
  655. The function SHALL return 0 for success and a negative value otherwise.
  656. */
  657. sint8 m2m_ate_get_tot_gain(double *totGaindB)
  658. {
  659. double dGaindB, paGaindB, ppaGaindB;
  660. if (!totGaindB)
  661. return M2M_ERR_INVALID_ARG;
  662. m2m_ate_get_pa_gain(&paGaindB);
  663. m2m_ate_get_ppa_gain(&ppaGaindB);
  664. m2m_ate_get_dig_gain(&dGaindB);
  665. *totGaindB = dGaindB + paGaindB + ppaGaindB;
  666. return M2M_SUCCESS;
  667. }
  668. #endif //_M2M_ATE_FW_