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