source: ReferenceDesigns/w3_802.11/c/wlan_w3_low/w3_low.c

Last change on this file was 6319, checked in by chunter, 5 years ago

1.8.0 release wlan-mac-se

File size: 41.7 KB
Line 
1/** @file wlan_platform_low.c
2 *  @brief Platform abstraction for CPU Low
3 *
4 *  @copyright Copyright 2014-2019, Mango Communications. All rights reserved.
5 *          Distributed under the Mango Communications Reference Design License
6 *              See LICENSE.txt included in the design archive or
7 *              at http://mangocomm.com/802.11/license
8 *
9 *  This file is part of the Mango 802.11 Reference Design (https://mangocomm.com/802.11)
10 */
11
12// SDK includes
13#include "xil_types.h"
14#include "xil_cache.h"
15#include "xil_assert.h"
16#include "xstatus.h"
17#include "xparameters.h"
18#include "stdarg.h"
19#include "stdlib.h"
20
21// Platform includes
22#include "w3_mac_phy_regs.h"
23#include "w3_low.h"
24#include "w3_common.h"
25#include "wlan_platform_common.h"
26#include "wlan_platform_debug_hdr.h"
27#include "wlan_platform_low.h"
28#include "w3_userio_util.h"
29#include "w3_phy_util.h"
30
31// Low framework includes
32#include "wlan_phy_util.h"
33#include "wlan_mac_low.h"
34#include "wlan_mac_common.h"
35#include "wlan_mac_mailbox_util.h"
36#include "wlan_common_types.h"
37
38// WARP v3 hardware includes
39#include "w3_userio.h"
40#include "w3_ad_controller.h"
41#include "w3_clock_controller.h"
42#include "radio_controller.h"
43#include "w3_phy_util.h"
44
45static channel_band_t gl_current_band;
46static int gl_enable_phy_cs;
47platform_common_dev_info_t platform_common_dev_info;
48
49/*****************************************************************************
50 * Public functions - the functions below are exported to the low framework
51 *****************************************************************************/
52void wlan_platform_cpu_low_init() {
53
54    Xil_AssertSetCallback((Xil_AssertCallback)wlan_assert_print);
55
56    // Disable I and D cache
57    Xil_DCacheDisable();
58    Xil_ICacheDisable();
59
60    // Enable exceptions - exceptions *must* be enabled on MicroBlaze
61    //  to handle unaligned memory accesses
62    microblaze_enable_exceptions();
63
64    return;
65}
66
67void wlan_platform_low_userio_disp_status(userio_disp_low_status_t status, ...){
68   va_list valist;
69   static u8 red_led_index = 0;
70   static u8 green_led_index = 0;
71
72   /* initialize valist for num number of arguments */
73   va_start(valist, status);
74
75   switch(status){
76
77       case USERIO_DISP_STATUS_GOOD_FCS_EVENT: {
78           green_led_index = (green_led_index + 1) % 4;
79           userio_write_leds_green(USERIO_BASEADDR, (1<<green_led_index));
80       } break;
81
82       case USERIO_DISP_STATUS_BAD_FCS_EVENT: {
83           red_led_index = (red_led_index + 1) % 4;
84           userio_write_leds_red(USERIO_BASEADDR, (1<<red_led_index));
85       } break;
86       case USERIO_DISP_STATUS_CPU_ERROR: {
87           u32 error_code = va_arg(valist, u32);
88           if (error_code != WLAN_ERROR_CPU_STOP) {
89               // Print error message
90               xil_printf("\n\nERROR:  CPU is halting with error code: E%X\n\n", (error_code & 0xF));
91
92               // Set the error code on the hex display
93               set_hex_display_error_status(error_code & 0xF);
94
95               // Enter infinite loop blinking the hex display
96               blink_hex_display(0, 250000);
97            } else {
98                // Stop execution
99                while (1) {};
100            }
101       } break;
102
103       default:
104       break;
105   }
106
107   /* clean memory reserved for valist */
108   va_end(valist);
109   return;
110}
111
112int wlan_platform_low_init() {
113    int status;
114
115    // Get the device info
116    platform_common_dev_info = wlan_platform_common_get_dev_info();
117
118    status = w3_node_init();
119    if(status != 0) {
120        xil_printf("ERROR in w3_node_init(): %d\n", status);
121        return status;
122    }
123
124    w3_radio_init();
125    w3_agc_init();
126
127    wlan_platform_enable_phy_cs(0); //Call once so we know the global gets set. This will be overwritten when the Low Framework
128                                           //finishes booting
129
130    return WLAN_SUCCESS;
131}
132
133
134void max2829_tune_custom(u32 band_sel, u32 pll_div_int, u32 pll_div_frac) {
135    // band_sel: 0=2.4GHz; 1=4.9-5.35GHz; 2=>5.35GHz
136    // pll_div_int: integer part of PLL divider ratio
137    // pll_div_frac: fractional part of PLL divider ratio as UFix16_16
138
139    // Assume only RF A
140    u32 rfSel = RC_RFA;
141
142    u16 reg3 = (pll_div_int & 0x0FF) | ((pll_div_frac & 0x3) << 12); //reg3[11:8] always 0
143    u16 reg4 = (pll_div_frac & 0xFFFC) >> 2;
144
145    if(band_sel == 0) {
146        //MAX2829 tuning process for 2.4GHz channels:
147        // -Set reg5[0] to 0 (selects 2.4GHz)
148        // -Set reg3, reg4 with PLL tuning params
149
150        radio_controller_SPI_setRegBits(RC_BASEADDR, rfSel, 5, 0x1, 0x0);
151
152        //Write the PLL parameters
153        radio_controller_SPI_write(RC_BASEADDR, rfSel, 3, reg3);
154        radio_controller_SPI_write(RC_BASEADDR, rfSel, 4, reg4);
155
156    } else {
157        //MAX2829 tuning process for 5GHz channels:
158        //(Assumes default config of 5GHz sub-band tuning via FSM; see MAX2829 datasheet for details)
159        // -Set:
160        //   -reg5[0] to 1 (selects 5GHz)
161        //   -reg5[6] based on selected freq (0:4.9-5.35GHz, 1:5.47-5.875GHz)
162        // -Set reg3, reg4 with PLL tuning params
163
164        if(band_sel == 1)
165            radio_controller_SPI_setRegBits(RC_BASEADDR, rfSel, 5, 0x41, 0x01);
166        else
167            radio_controller_SPI_setRegBits(RC_BASEADDR, rfSel, 5, 0x41, 0x41);
168
169        //Reset the band select FSM
170        radio_controller_SPI_setRegBits(RC_BASEADDR, rfSel, 5, 0x80, 0x00);
171
172        //Write the PLL parameters
173        radio_controller_SPI_write(RC_BASEADDR, rfSel, 3, reg3);
174        radio_controller_SPI_write(RC_BASEADDR, rfSel, 4, reg4);
175
176        //Start the band select FSM
177        radio_controller_SPI_setRegBits(RC_BASEADDR, rfSel, 5, 0x80, 0x80);
178    }
179
180    return;
181}
182
183void wlan_platform_low_param_handler(u8 mode, u32* payload) {
184    if(mode != IPC_REG_WRITE_MODE) {
185        xil_printf("ERROR wlan_platform_low_param_handler: unrecognized mode (%d) - mode must be WRITE\n", mode);
186        return;
187    }
188
189    switch(payload[0]) {
190        case LOW_PARAM_PKT_DET_MIN_POWER: {
191            int min_pwr_arg = payload[1] & 0xFF;
192            if(min_pwr_arg == 0) {
193                // wlan_exp uses 0 to disable min power det logic
194                wlan_platform_set_pkt_det_min_power(0);
195            } else {
196                //The value sent from wlan_exp will be unsigned with 0 representing PKT_DET_MIN_POWER_MIN
197                wlan_platform_set_pkt_det_min_power(min_pwr_arg + PKT_DET_MIN_POWER_MIN);
198            }
199        }
200        break;
201
202        case LOW_PARAM_CUSTOM_MAX2829_TUNE: {
203            // Tune MAX2829 PLL to non-standard center frequency
204            max2829_tune_custom(payload[1], payload[2], payload[3]);
205        }
206        break;
207
208        default:
209        break;
210    }
211
212    return;
213}
214
215void wlan_platform_low_set_rx_ant_mode(u32 ant_mode) {
216
217    // Disable PHY control of all RF interfaces - selected interfaces to re-enabled below
218    radio_controller_setCtrlSource(RC_BASEADDR, RC_ALL_RF, RC_REG0_RXEN_CTRLSRC, RC_CTRLSRC_REG);
219
220    // Set the antenna mode
221    //
222    // For each antenna mode:
223    //   - Enable packet detection
224    //   - Select I/Q stream for Rx PHY
225    //   - Give PHY control of Tx/Rx status
226    //   - Configure AGC
227    //
228    switch (ant_mode) {
229        case RX_ANTMODE_SISO_ANTA:
230            radio_controller_setCtrlSource(RC_BASEADDR, RC_RFA, RC_REG0_RXEN_CTRLSRC, RC_CTRLSRC_HW);
231        break;
232
233        case RX_ANTMODE_SISO_ANTB:
234            radio_controller_setCtrlSource(RC_BASEADDR, RC_RFB, RC_REG0_RXEN_CTRLSRC, RC_CTRLSRC_HW);
235        break;
236
237        case RX_ANTMODE_SISO_ANTC:
238            radio_controller_setCtrlSource(RC_BASEADDR, RC_RFC, RC_REG0_RXEN_CTRLSRC, RC_CTRLSRC_HW);
239        break;
240
241        case RX_ANTMODE_SISO_ANTD:
242            radio_controller_setCtrlSource(RC_BASEADDR, RC_RFD, RC_REG0_RXEN_CTRLSRC, RC_CTRLSRC_HW);
243        break;
244
245        case RX_ANTMODE_SISO_SELDIV_2ANT:
246            // By enabling the antenna switching, the I/Q stream is automatically switched for Rx PHY
247            radio_controller_setCtrlSource(RC_BASEADDR, (RC_RFA | RC_RFB), RC_REG0_RXEN_CTRLSRC, RC_CTRLSRC_HW);
248        break;
249
250        case RX_ANTMODE_SISO_SELDIV_4ANT:
251            // By enabling the antenna switching, the I/Q stream is automatically switched for Rx PHY
252            radio_controller_setCtrlSource(RC_BASEADDR, RC_ALL_RF, RC_REG0_RXEN_CTRLSRC, RC_CTRLSRC_HW);
253        break;
254
255        default:
256            // Default to SISO on A if user provides invalid mode
257            xil_printf("wlan_platform_low_set_rx_ant_mode ERROR: Invalid Mode - Defaulting to SISO on A\n");
258
259            radio_controller_setCtrlSource(RC_BASEADDR, RC_RFA, RC_REG0_RXEN_CTRLSRC, RC_CTRLSRC_HW);
260        break;
261    }
262    return;
263}
264
265int wlan_platform_low_set_samp_rate(phy_samp_rate_t phy_samp_rate) {
266    if((phy_samp_rate != PHY_10M) && (phy_samp_rate != PHY_20M) && (phy_samp_rate != PHY_40M)) {
267        xil_printf("Invalid PHY samp rate (%d)\n", phy_samp_rate);
268        return WLAN_FAILURE;
269    }
270
271    // Assert PHY Tx/Rx and MAC Resets
272    REG_SET_BITS(WLAN_RX_REG_CTRL, WLAN_RX_REG_CTRL_RESET);
273    REG_SET_BITS(WLAN_TX_REG_CFG, WLAN_TX_REG_CFG_RESET);
274    wlan_mac_reset(1);
275
276    // Set RF interface clocking and interp/decimation filters
277    switch(phy_samp_rate){
278        case PHY_40M:
279            // Set ADC_CLK=DAC_CLK=40MHz, interp_rate=decim_rate=1
280            clk_config_dividers(CLK_BASEADDR, 2, (CLK_SAMP_OUTSEL_AD_RFA | CLK_SAMP_OUTSEL_AD_RFB));
281            ad_config_filters(AD_BASEADDR, AD_ALL_RF, 1, 1);
282            ad_spi_write(AD_BASEADDR, (AD_ALL_RF), 0x32, 0x2F);
283            ad_spi_write(AD_BASEADDR, (AD_ALL_RF), 0x33, 0x00);
284            ad_spi_write(AD_BASEADDR, (AD_ALL_RF), 0x33, 0x08);
285        break;
286        case PHY_20M:
287            // Set ADC_CLK=DAC_CLK=40MHz, interp_rate=decim_rate=2
288            clk_config_dividers(CLK_BASEADDR, 2, (CLK_SAMP_OUTSEL_AD_RFA | CLK_SAMP_OUTSEL_AD_RFB));
289
290            ad_config_filters(AD_BASEADDR, AD_ALL_RF, 2, 2);
291            ad_spi_write(AD_BASEADDR, (AD_ALL_RF), 0x32, 0x27);
292            ad_spi_write(AD_BASEADDR, (AD_ALL_RF), 0x33, 0x00);
293            ad_spi_write(AD_BASEADDR, (AD_ALL_RF), 0x33, 0x08);
294        break;
295        case PHY_10M:
296            // Set ADC_CLK=DAC_CLK=20MHz, interp_rate=decim_rate=2
297            clk_config_dividers(CLK_BASEADDR, 4, (CLK_SAMP_OUTSEL_AD_RFA | CLK_SAMP_OUTSEL_AD_RFB));
298            ad_config_filters(AD_BASEADDR, AD_ALL_RF, 2, 2);
299            ad_spi_write(AD_BASEADDR, (AD_ALL_RF), 0x32, 0x27);
300            ad_spi_write(AD_BASEADDR, (AD_ALL_RF), 0x33, 0x00);
301            ad_spi_write(AD_BASEADDR, (AD_ALL_RF), 0x33, 0x08);
302        break;
303    }
304
305    switch(phy_samp_rate){
306        case PHY_40M:
307            radio_controller_setRadioParam(RC_BASEADDR, RC_ALL_RF, RC_PARAMID_RXLPF_BW, 3);
308            radio_controller_setRadioParam(RC_BASEADDR, RC_ALL_RF, RC_PARAMID_TXLPF_BW, 3);
309        break;
310        case PHY_10M:
311        case PHY_20M:
312            radio_controller_setRadioParam(RC_BASEADDR, RC_ALL_RF, RC_PARAMID_RXLPF_BW, 1);
313            radio_controller_setRadioParam(RC_BASEADDR, RC_ALL_RF, RC_PARAMID_TXLPF_BW, 1);
314        break;
315    }
316
317    // AGC timing: capt_rssi_1, capt_rssi_2, capt_v_db, agc_done
318    switch(phy_samp_rate){
319        case PHY_40M:
320            wlan_agc_set_AGC_timing(10, 30, 90, 96);
321        break;
322        case PHY_10M:
323        case PHY_20M:
324            wlan_agc_set_AGC_timing(1, 30, 90, 96);
325        break;
326    }
327
328   
329    // Configure auto-correlation packet detection
330    //  wlan_phy_rx_pktDet_autoCorr_ofdm_cfg(corr_thresh, energy_thresh, min_dur, post_wait)
331    switch(phy_samp_rate){
332        case PHY_40M:
333            // TODO: investigate need for lower correlation threshold at 40MSps
334            wlan_phy_rx_pktDet_autoCorr_ofdm_cfg(100, 15, 4, 0x3F);
335        break;
336        case PHY_10M:
337        case PHY_20M:
338            wlan_phy_rx_pktDet_autoCorr_ofdm_cfg(100, 15, 4, 0x3F);
339        break;
340    }
341
342    // Set post Rx extension
343    //  Number of sample periods post-Rx the PHY waits before asserting Rx END. This value
344    //  should be 6 usec and backdated by the delay through the Rx chain. This aligns the
345    //  Rx END event to the correct sample at the antenna.
346    switch(phy_samp_rate){
347        case PHY_40M:
348            wlan_phy_rx_set_extension((6*40) - (platform_common_dev_info.rx_analog_latency_100ns*4));
349        break;
350        case PHY_20M:
351            wlan_phy_rx_set_extension((6*20) - (platform_common_dev_info.rx_analog_latency_100ns*2));
352        break;
353        case PHY_10M:
354            wlan_phy_rx_set_extension((6*10) - (platform_common_dev_info.rx_analog_latency_100ns));
355        break;
356    }
357
358    // Set Tx duration extension, in units of sample periods. This value should be 6 usec, but
359    // pushed forward to account for delay through the Tx chain. The results should be a Tx END
360    // that asserts at the same time as an Rx END on the node receiving the packet (ignoring
361    // propagation delay).
362    switch(phy_samp_rate){
363        case PHY_40M:
364            wlan_phy_tx_set_extension((6*40) + (platform_common_dev_info.tx_analog_latency_100ns*4));
365
366            // Set extension from last samp output to RF Tx -> Rx transition
367            //     This delay allows the Tx pipeline to finish driving samples into DACs
368            //     and for DAC->RF frontend to finish output Tx waveform
369            wlan_phy_tx_set_txen_extension(100);
370
371            // Set extension from RF Rx -> Tx to un-blocking Rx samples
372            wlan_phy_tx_set_rx_invalid_extension(300);
373        break;
374        case PHY_20M:
375            wlan_phy_tx_set_extension((6*20) + (platform_common_dev_info.tx_analog_latency_100ns*2));
376
377            // Set extension from last samp output to RF Tx -> Rx transition
378            //     This delay allows the Tx pipeline to finish driving samples into DACs
379            //     and for DAC->RF frontend to finish output Tx waveform
380            wlan_phy_tx_set_txen_extension(50); //50
381
382            // Set extension from RF Rx -> Tx to un-blocking Rx samples
383            wlan_phy_tx_set_rx_invalid_extension(150);
384        break;
385        case PHY_10M:
386            wlan_phy_tx_set_extension((6*10) + (platform_common_dev_info.tx_analog_latency_100ns));
387
388            // Set extension from last samp output to RF Tx -> Rx transition
389            //     This delay allows the Tx pipeline to finish driving samples into DACs
390            //     and for DAC->RF frontend to finish output Tx waveform
391            wlan_phy_tx_set_txen_extension(25);
392
393            // Set extension from RF Rx -> Tx to un-blocking Rx samples
394            wlan_phy_tx_set_rx_invalid_extension(75);
395        break;
396    }
397   
398    // Deassert PHY Tx/Rx and MAC Resets
399    REG_CLEAR_BITS(WLAN_RX_REG_CTRL, WLAN_RX_REG_CTRL_RESET);
400    REG_CLEAR_BITS(WLAN_TX_REG_CFG, WLAN_TX_REG_CFG_RESET);
401    wlan_mac_reset(0);
402
403    // Let PHY Tx take control of radio TXEN/RXEN
404    REG_CLEAR_BITS(WLAN_TX_REG_CFG, WLAN_TX_REG_CFG_SET_RC_RXEN);
405    REG_SET_BITS(WLAN_TX_REG_CFG, WLAN_TX_REG_CFG_SET_RC_RXEN);
406   
407    return WLAN_SUCCESS;
408}
409
410
411
412/*****************************************************************************/
413/**
414 * @brief Set the radio channel
415 *
416 * This function will set the radio channel for CPU LOW
417 *
418 * @param   channel     - Radio channel
419 * @return  None
420 *
421 */
422int wlan_platform_low_set_radio_channel(u32 channel) {
423    channel_band_t prev_band = gl_current_band;
424
425    if(channel <= 14) {
426        // 2.4GHz channel
427        radio_controller_setCenterFrequency(RC_BASEADDR, (RC_ALL_RF), RC_24GHZ, w3_wlan_chan_to_rc_chan(channel));
428        gl_current_band = BAND_24GHZ;
429    } else {
430        // 5GHz channel
431        radio_controller_setCenterFrequency(RC_BASEADDR, (RC_ALL_RF), RC_5GHZ, w3_wlan_chan_to_rc_chan(channel));
432        gl_current_band = BAND_5GHZ;
433    }
434
435    if(prev_band != gl_current_band){
436        //Update the CS thresh since the RSSI <-> Rx Power mapping as changed
437        wlan_platform_enable_phy_cs(gl_enable_phy_cs);
438    }
439
440    return WLAN_SUCCESS;
441}
442
443
444/********************************************************************************
445 * Private functions - the functions below are not exported to the low framework
446 ********************************************************************************/
447
448
449/*****************************************************************************/
450/**
451 * Initialize the WARP v3 node
452 *
453 * @param   None
454 *
455 * @return  int              - Status of the command:
456 *                                 WLAN_SUCCESS - Command completed successfully
457 *                                 WLAN_FAILURE - There was an error in the command
458 *
459 *****************************************************************************/
460int w3_node_init() {
461
462    int ret_val = WLAN_SUCCESS;
463    int status;
464    u32 clkmod_status;
465
466    // Initialize w3_clock_controller hardware and AD9512 buffers
467    //   NOTE:  The clock initialization will set the clock divider to 2 (for 40MHz clock) to RF A/B AD9963's
468    status = clk_init(CLK_BASEADDR, 2);
469    if(status != XST_SUCCESS) {
470        xil_printf("ERROR: (w3_node_init) Clock initialization failed with error code: %d\n", status);
471        ret_val = WLAN_FAILURE;
472    }
473
474    // Check for a clock module and configure clock inputs, outputs and dividers as needed
475    clkmod_status = clk_config_read_clkmod_status(CLK_BASEADDR);
476
477    switch(clkmod_status & CM_STATUS_SW) {
478        case CM_STATUS_DET_NOCM:
479        case CM_STATUS_DET_CMPLL_BYPASS:
480            // No clock module - default config from HDL/driver is good as-is
481            xil_printf("No clock module detected - selecting on-board clocks\n\n");
482        break;
483
484        case CM_STATUS_DET_CMMMCX_CFG_A:
485            // CM-MMCX config A:
486            //     Samp clk: on-board, RF clk: on-board
487            //     Samp MMCX output: 80MHz, RF MMCX output: 80MHz
488            xil_printf("CM-MMCX Config A Detected:\n");
489            xil_printf("  RF: On-board\n  Samp: On-board\n  MMCX Outputs: Enabled\n\n");
490
491            clk_config_outputs(CLK_BASEADDR, CLK_OUTPUT_ON, (CLK_SAMP_OUTSEL_CLKMODHDR | CLK_RFREF_OUTSEL_CLKMODHDR));
492            clk_config_dividers(CLK_BASEADDR, 1, CLK_SAMP_OUTSEL_CLKMODHDR | CLK_RFREF_OUTSEL_CLKMODHDR);
493        break;
494
495        case CM_STATUS_DET_CMMMCX_CFG_B:
496            // CM-MMCX config B:
497            //     Samp clk: off-board, RF clk: off-board
498            //     Samp MMCX output: 80MHz, RF MMCX output: 80MHz
499            xil_printf("CM-MMCX Config B Detected:\n");
500            xil_printf("  RF: Off-board\n  Samp: Off-board\n  MMCX Outputs: Enabled\n\n");
501
502            clk_config_input_rf_ref(CLK_BASEADDR, CLK_INSEL_CLKMOD);
503            clk_config_outputs(CLK_BASEADDR, CLK_OUTPUT_ON, (CLK_SAMP_OUTSEL_CLKMODHDR | CLK_RFREF_OUTSEL_CLKMODHDR));
504            clk_config_dividers(CLK_BASEADDR, 1, (CLK_SAMP_OUTSEL_CLKMODHDR | CLK_RFREF_OUTSEL_CLKMODHDR));
505        break;
506
507        case CM_STATUS_DET_CMMMCX_CFG_C:
508            // CM-MMCX config C:
509            //     Samp clk: off-board, RF clk: off-board
510            //     Samp MMCX output: Off, RF MMCX output: Off
511            xil_printf("CM-MMCX Config C Detected:\n");
512            xil_printf("  RF: Off-board\n  Samp: Off-board\n  MMCX Outputs: Disabled\n\n");
513
514            clk_config_input_rf_ref(CLK_BASEADDR, CLK_INSEL_CLKMOD);
515            clk_config_outputs(CLK_BASEADDR, CLK_OUTPUT_OFF, (CLK_SAMP_OUTSEL_CLKMODHDR | CLK_RFREF_OUTSEL_CLKMODHDR));
516        break;
517
518        case CM_STATUS_DET_CMPLL_CFG_A:
519            // CM-PLL config A:
520            //     Samp clk: clock module PLL
521            //     RF clk: on-board
522            xil_printf("CM-PLL Config A Detected:\n");
523            xil_printf("  RF: On-board\n  Samp: clock module PLL\n");
524
525            // No changes from configuration applied by HDL and clk_init()
526        break;
527
528        case CM_STATUS_DET_CMPLL_CFG_B:
529            // CM-PLL config B:
530            //     Samp clk: clock module PLL
531            //     RF clk: clock module PLL
532            xil_printf("CM-PLL Config B Detected:\n");
533            xil_printf("  RF: clock module PLL\n  Samp: clock module PLL\n");
534
535            clk_config_input_rf_ref(CLK_BASEADDR, CLK_INSEL_CLKMOD);
536        break;
537
538        case CM_STATUS_DET_CMPLL_CFG_C:
539            // CM-PLL config C:
540            //     Samp clk: clock module PLL
541            //     RF clk: clock module PLL
542            xil_printf("CM-PLL Config C Detected:\n");
543            xil_printf("  RF: clock module PLL\n  Samp: clock module PLL\n");
544
545            clk_config_input_rf_ref(CLK_BASEADDR, CLK_INSEL_CLKMOD);
546        break;
547
548        default:
549            // Should be impossible
550            xil_printf("ERROR: (w3_node_init) Invalid clock module switch settings! (0x%08x)\n", clkmod_status);
551            ret_val = XST_FAILURE;
552        break;
553    }
554
555#ifdef WLAN_4RF_EN
556    // Turn on clocks to FMC
557    clk_config_outputs(CLK_BASEADDR, CLK_OUTPUT_ON, (CLK_SAMP_OUTSEL_FMC | CLK_RFREF_OUTSEL_FMC));
558
559    // FMC samp clock divider = 2 (40MHz sampling reference, same as on-board AD9963 ref clk)
560    clk_config_dividers(CLK_BASEADDR, 2, CLK_SAMP_OUTSEL_FMC);
561
562    // FMC RF ref clock divider = 2 (40MHz RF reference, same as on-board MAX2829 ref clk)
563    clk_config_dividers(CLK_BASEADDR, 2, CLK_RFREF_OUTSEL_FMC);
564#endif
565
566    // Initialize the AD9963 ADCs/DACs for on-board RF interfaces
567    ad_init(AD_BASEADDR, AD_ALL_RF, 3);
568
569    // Disable AD9963 Duty Cycle Stabilizer (recommended when ADCCLK < 75MHz)
570    ad_config_clocks(AD_BASEADDR, AD_ALL_RF, AD_DACCLKSRC_EXT, AD_ADCCLKSRC_EXT, AD_ADCCLKDIV_1, AD_DCS_OFF);
571
572    if(status != XST_SUCCESS) {
573        xil_printf("ERROR: (w3_node_init) ADC/DAC initialization failed with error code: %d\n", status);
574        ret_val = WLAN_FAILURE;
575    }
576
577    // Initialize the radio_controller core and MAX2829 transceivers for on-board RF interfaces
578    status = radio_controller_init(RC_BASEADDR, RC_ALL_RF, 1, 1);
579
580    if(status != XST_SUCCESS) {
581        xil_printf("ERROR: (w3_node_init) Radio controller initialization failed with error code: %d\n", status);
582
583        // Comment out the line below to allow the node to boot even if a radio PLL is unlocked
584        ret_val = WLAN_FAILURE;
585    }
586
587#ifdef WLAN_4RF_EN
588    //TODO: 4RF mode not supported in 1.7.0. We will add it back in
589    // in a future dot release.
590    iic_eeprom_init(FMC_EEPROM_BASEADDR, 0x64);
591#endif
592
593    // Give the PHY control of the red user LEDs (PHY counts 1-hot on SIGNAL errors)
594    //
595    // NOTE: Uncommenting this line will make the RED LEDs controlled by hardware.
596    //     This will move the LEDs on PHY bad signal events
597    //
598    // userio_set_ctrlSrc_hw(USERIO_BASEADDR, W3_USERIO_CTRLSRC_LEDS_RED);
599
600    // Initialize Debug Header
601    //  Configure pins 15:12 as software controlled outputs, pins 11:0 as hardware controlled
602    //  This configuration is applied only by CPU Low to avoid races between CPUs at boot
603    //  Both CPUs can control the software-controlled pins
604    wlan_mac_set_dbg_hdr_ctrlsrc(DBG_HDR_CTRLSRC_HW, 0x0FFF);
605    wlan_mac_set_dbg_hdr_ctrlsrc(DBG_HDR_CTRLSRC_SW, 0xF000);
606    wlan_mac_set_dbg_hdr_dir(DBG_HDR_DIR_OUTPUT, 0xF000);
607
608    return ret_val;
609}
610
611/*****************************************************************************/
612/**
613 * Initialize the Radio Controller
614 *
615 * @param   None
616 *
617 * @return  None
618 *
619 * @note    This function supports both 2RF and 4RF configurations.  Also, there are
620 *     sections (ie #if sections) that have been added to assist if clocking changes
621 *     are needed.
622 *
623 *****************************************************************************/
624void w3_radio_init() {
625
626#if 1
627
628    // Setup clocking and filtering (20MSps, 2x interp/decimate in AD9963)
629    clk_config_dividers(CLK_BASEADDR, 2, (CLK_SAMP_OUTSEL_AD_RFA | CLK_SAMP_OUTSEL_AD_RFB));
630    ad_config_filters(AD_BASEADDR, AD_ALL_RF, 2, 2);
631    ad_spi_write(AD_BASEADDR, (AD_ALL_RF), 0x32, 0x27);
632    ad_spi_write(AD_BASEADDR, (AD_ALL_RF), 0x33, 0x08);
633
634#else
635    // Setup clocking and filtering:
636    //     80MHz ref clk to AD9963
637    //     20MSps Tx/Rx at FPGA
638    //     80MHz DAC, 4x interp in AD9963
639    //     40MHz ADC, 2x decimate in AD9963
640    //
641    clk_config_dividers(CLK_BASEADDR, 1, (CLK_SAMP_OUTSEL_AD_RFA | CLK_SAMP_OUTSEL_AD_RFB));
642
643    ad_config_clocks(AD_BASEADDR, AD_ALL_RF, AD_DACCLKSRC_EXT, AD_ADCCLKSRC_EXT, AD_ADCCLKDIV_2, AD_DCS_OFF);
644
645    ad_config_filters(AD_BASEADDR, AD_ALL_RF, 4, 2);
646#endif
647
648    // Setup all RF interfaces
649    radio_controller_TxRxDisable(RC_BASEADDR, RC_ALL_RF);
650
651    radio_controller_apply_TxDCO_calibration(AD_BASEADDR, EEPROM_BASEADDR, (RC_RFA | RC_RFB));
652#ifdef WLAN_4RF_EN
653    radio_controller_apply_TxDCO_calibration(AD_BASEADDR, FMC_EEPROM_BASEADDR, (RC_RFC | RC_RFD));
654#endif
655
656    radio_controller_setCenterFrequency(RC_BASEADDR, RC_ALL_RF, RC_24GHZ, 4);
657
658    radio_controller_setRadioParam(RC_BASEADDR, RC_ALL_RF, RC_PARAMID_RSSI_HIGH_BW_EN, 0);
659
660    // Filter bandwidths
661    radio_controller_setRadioParam(RC_BASEADDR, RC_ALL_RF, RC_PARAMID_RXHPF_HIGH_CUTOFF_EN, 1);
662
663#if 0
664    // To set the gains manually for all radios:
665    radio_controller_setCtrlSource(RC_BASEADDR, RC_ALL_RF, RC_REG0_RXHP_CTRLSRC, RC_CTRLSRC_REG);
666    radio_controller_setRxHP(RC_BASEADDR, RC_ALL_RF, RC_RXHP_OFF);
667    radio_controller_setRxGainSource(RC_BASEADDR, RC_ALL_RF, RC_GAINSRC_SPI);
668
669    // Set Rx gains
670    radio_controller_setRadioParam(RC_BASEADDR, RC_ALL_RF, RC_PARAMID_RXGAIN_RF, 1);
671    radio_controller_setRadioParam(RC_BASEADDR, RC_ALL_RF, RC_PARAMID_RXGAIN_BB, 8);
672
673#else
674    // AGC
675    radio_controller_setCtrlSource(RC_BASEADDR, RC_ALL_RF, RC_REG0_RXHP_CTRLSRC, RC_CTRLSRC_HW);
676    radio_controller_setRxGainSource(RC_BASEADDR, RC_ALL_RF, RC_GAINSRC_HW);
677#endif
678
679    // Set Tx gains
680    //
681    // NOTE:  To use software to control the Tx gains, use the following lines:
682    //     radio_controller_setTxGainSource(RC_BASEADDR, RC_ALL_RF, RC_GAINSRC_REG); //Used for software control of gains
683    //     radio_controller_setTxGainTarget(RC_BASEADDR, RC_ALL_RF, 45);
684    //
685    radio_controller_setTxGainSource(RC_BASEADDR, RC_ALL_RF, RC_GAINSRC_HW); //Used for hardware control of gains
686
687    radio_controller_setRadioParam(RC_BASEADDR, RC_ALL_RF, RC_PARAMID_TXGAIN_BB, 1);
688
689    // Set misc radio params
690    radio_controller_setRadioParam(RC_BASEADDR, RC_ALL_RF, RC_PARAMID_TXLINEARITY_PADRIVER, 2);
691    radio_controller_setRadioParam(RC_BASEADDR, RC_ALL_RF, RC_PARAMID_TXLINEARITY_VGA, 0);
692    radio_controller_setRadioParam(RC_BASEADDR, RC_ALL_RF, RC_PARAMID_TXLINEARITY_UPCONV, 0);
693
694    // Set Tx state machine timing
695    //
696    // NOTE:  radio_controller_setTxDelays(dly_GainRamp, dly_PA, dly_TX, dly_PHY)
697    //
698    radio_controller_setTxDelays(RC_BASEADDR, 40, 20, 0, 0); //240 PA time after 180 PHY time is critical point
699
700    // Configure the radio_controller Tx/Rx enable control sources
701    //     The Tx PHY drives a 4-bit TxEn, one bit per RF interface
702    //     The Tx PHY drives a 1-bit RxEn, common to all RF interfaces
703    //     MAC software should select active Rx interface by changing RFA/RFB RxEn ctrl src between _HW and _REG
704    radio_controller_setCtrlSource(RC_BASEADDR, RC_RFA, (RC_REG0_RXEN_CTRLSRC), RC_CTRLSRC_HW);
705    radio_controller_setCtrlSource(RC_BASEADDR, RC_RFB, (RC_REG0_RXEN_CTRLSRC), RC_CTRLSRC_REG);
706
707    radio_controller_setCtrlSource(RC_BASEADDR, (RC_RFA | RC_RFB), (RC_REG0_TXEN_CTRLSRC), RC_CTRLSRC_HW);
708
709#ifdef WLAN_4RF_EN
710    radio_controller_setCtrlSource(RC_BASEADDR, (RC_RFC | RC_RFD), (RC_REG0_TXEN_CTRLSRC), RC_CTRLSRC_HW);
711    radio_controller_setCtrlSource(RC_BASEADDR, (RC_RFC | RC_RFD), (RC_REG0_RXEN_CTRLSRC), RC_CTRLSRC_REG);
712#else
713    // Disable any hardware control of RFC/RFD
714    radio_controller_setCtrlSource(RC_BASEADDR, (RC_RFC | RC_RFD), (RC_REG0_RXEN_CTRLSRC | RC_REG0_TXEN_CTRLSRC), RC_CTRLSRC_REG);
715#endif
716
717    return;
718}
719
720int w3_agc_init() {
721
722    // Post Rx_done reset delays for [rxhp, g_rf, g_bb]
723    wlan_agc_set_reset_timing(4, 250, 250);
724
725    // AGC config:
726    //     RFG Thresh 3->2, 2->1, Avg_len_sel, V_DB_Adj, Init G_BB
727    wlan_agc_set_config((256 - 56), (256 - 37), 0, 6, 24);
728
729    // AGC RSSI->Rx power offsets
730    wlan_agc_set_RSSI_pwr_calib(100, 85, 70);
731
732    // AGC timing: start_dco, en_iir_filt
733    wlan_agc_set_DCO_timing(100, (100 + 34));
734
735    // AGC target output power (log scale)
736    wlan_agc_set_target((64 - 16));
737
738    // Configure AGC to keep RXHP asserted between pkt det events
739    // Note: this mode should be left 0 to prevent false positive OFDM
740    // detection events immediately following a reception.
741    wlan_agc_set_rxhp_mode(0);
742
743    // Configure AGC to leave RXHP de-asserted until the AGC is triggered
744    //wlan_agc_set_rxhp_mode(1);
745
746#if 0
747    // To set the gains manually:
748
749    //xil_printf("Switching to MGC\n");
750    radio_controller_setCtrlSource(RC_BASEADDR, RC_ALL_RF, RC_REG0_RXHP_CTRLSRC, RC_CTRLSRC_REG);
751    radio_controller_setRxHP(RC_BASEADDR, RC_ALL_RF, RC_RXHP_OFF);
752    radio_controller_setRxGainSource(RC_BASEADDR, RC_ALL_RF, RC_GAINSRC_SPI);
753
754    // Set Rx gains
755    radio_controller_setRadioParam(RC_BASEADDR, RC_ALL_RF, RC_PARAMID_RXGAIN_RF, 2);
756    radio_controller_setRadioParam(RC_BASEADDR, RC_ALL_RF, RC_PARAMID_RXGAIN_BB, 8);
757#endif
758
759    return WLAN_SUCCESS;
760}
761
762
763
764/*****************************************************************************/
765/**
766 * @brief Map the WLAN channel frequencies onto the convention used by the radio controller
767 */
768inline u32 w3_wlan_chan_to_rc_chan(u32 mac_channel) {
769    int return_value = 0;
770
771    switch(mac_channel){
772        // 2.4GHz channels
773        case 1:
774        case 2:
775        case 3:
776        case 4:
777        case 5:
778        case 6:
779        case 7:
780        case 8:
781        case 9:
782        case 10:
783        case 11:
784            return_value = mac_channel;
785        break;
786
787        // 5GHz channels
788        case 36: // 5180 MHz
789            return_value = 1;
790        break;
791        case 38: // 5190 MHz
792            return_value = 2;
793        break;
794        case 40: // 5200 MHz
795            return_value = 3;
796        break;
797        case 44: // 5220 MHz
798            return_value = 4;
799        break;
800        case 46: // 5230 MHz
801            return_value = 5;
802        break;
803        case 48: // 5240 MHz
804            return_value = 6;
805        break;
806#if 0 // Disable these channels by default
807        case 52: // 5260 MHz
808            return_value = 7;
809        break;
810        case 54: // 5270 MHz
811            return_value = 8;
812        break;
813        case 56: // 5280 MHz
814            return_value = 9;
815        break;
816        case 60: // 5300 MHz
817            return_value = 10;
818        break;
819        case 62: // 5310 MHz
820            return_value = 11;
821        break;
822        case 64: // 5320 MHz
823            return_value = 12;
824        break;
825        case 100: // 5500 MHz
826            return_value = 13;
827        break;
828        case 102: // 5510 MHz
829            return_value = 14;
830        break;
831        case 104: // 5520 MHz
832            return_value = 15;
833        break;
834        case 108: // 5540 MHz
835            return_value = 16;
836        break;
837        case 110: // 5550 MHz
838            return_value = 17;
839        break;
840        case 112: // 5560 MHz
841            return_value = 18;
842        break;
843        case 116: // 5580 MHz
844            return_value = 19;
845        break;
846        case 118: // 5590 MHz
847            return_value = 20;
848        break;
849        case 120: // 5600 MHz
850            return_value = 21;
851        break;
852        case 124: // 5620 MHz
853            return_value = 22;
854        break;
855        case 126: // 5630 MHz
856            return_value = 23;
857        break;
858        case 128: // 5640 MHz
859            return_value = 24;
860        break;
861        case 132: // 5660 MHz
862            return_value = 25;
863        break;
864        case 134: // 5670 MHz
865            return_value = 26;
866        break;
867        case 136: // 5680 MHz
868            return_value = 27;
869        break;
870        case 140: // 5700 MHz
871            return_value = 28;
872        break;
873        case 142: // 5710 MHz
874            return_value = 29;
875        break;
876        case 144: // 5720 MHz
877            return_value = 30;
878        break;
879        case 149: // 5745 MHz
880            return_value = 31;
881        break;
882        case 151: // 5755 MHz
883            return_value = 32;
884        break;
885        case 153: // 5765 MHz
886            return_value = 33;
887        break;
888        case 157: // 5785 MHz
889            return_value = 34;
890        break;
891        case 159: // 5795 MHz
892            return_value = 35;
893        break;
894        case 161: // 5805 MHz
895            return_value = 36;
896        break;
897        case 165: // 5825 MHz
898            return_value = 37;
899        break;
900        case 172: // 5860 MHz
901            return_value = 38;
902        break;
903        case 174: // 5870 MHz
904            return_value = 39;
905        break;
906        case 175: // 5875 MHz
907            return_value = 40;
908        break;
909        case 176: // 5880 MHz
910            return_value = 41;
911        break;
912        case 177: // 5885 MHz
913            return_value = 42;
914        break;
915        case 178: // 5890 MHz
916            return_value = 43;
917        break;
918#endif
919    }
920
921    return return_value;
922}
923
924
925/*****************************************************************************/
926/**
927 * @brief Calculates Rx Power (in dBm)
928 *
929 * This function calculates receive power for a given band, RSSI and LNA gain. This
930 * provides a reasonable estimate of Rx power, accurate to a few dB for standard waveforms.
931 *
932 * This function does not use the VGA gain setting or I/Q magnitudes. The PHY should use these
933 * to refine its own power measurement if needed.
934 *
935 * NOTE:  These lookup tables were developed as part of the RF characterization.  See:
936 *     http://warpproject.org/trac/wiki/802.11/Benchmarks/Rx_Char
937 *
938 *
939 * @param   rssi             - RSSI value from RF frontend
940 * @param   lna_gain         - Value of LNA gain stage in RF frontend
941 * @return  int              - Power in dBm
942 */
943static const s8 pow_lookup_B24[128]  = {-90, -90, -89, -88, -88, -87, -87, -86, -86, -85, -84, -84, -83, -83, -82, -82,
944                                        -81, -81, -80, -79, -79, -78, -78, -77, -77, -76, -75, -75, -74, -74, -73, -73,
945                                        -72, -72, -71, -70, -70, -69, -69, -68, -68, -67, -66, -66, -65, -65, -64, -64,
946                                        -63, -63, -62, -61, -61, -60, -60, -59, -59, -58, -58, -57, -56, -56, -55, -55,
947                                        -54, -54, -53, -52, -52, -51, -51, -50, -50, -49, -49, -48, -47, -47, -46, -46,
948                                        -45, -45, -44, -43, -43, -42, -42, -41, -41, -40, -40, -39, -38, -38, -37, -37,
949                                        -36, -36, -35, -34, -34, -33, -33, -32, -32, -31, -31, -30, -29, -29, -28, -28,
950                                        -27, -27, -26, -26, -25, -24, -24, -23, -23, -22, -22, -21, -20, -20, -19, -19};
951
952static const s8 pow_lookup_B5[128]   = {-97, -97, -96, -96, -95, -94, -94, -93, -93, -92, -92, -91, -90, -90, -89, -89,
953                                        -88, -88, -87, -87, -86, -85, -85, -84, -84, -83, -83, -82, -81, -81, -80, -80,
954                                        -79, -79, -78, -78, -77, -76, -76, -75, -75, -74, -74, -73, -72, -72, -71, -71,
955                                        -70, -70, -69, -69, -68, -67, -67, -66, -66, -65, -65, -64, -63, -63, -62, -62,
956                                        -61, -61, -60, -60, -59, -58, -58, -57, -57, -56, -56, -55, -54, -54, -53, -53,
957                                        -52, -52, -51, -51, -50, -49, -49, -48, -48, -47, -47, -46, -45, -45, -44, -44,
958                                        -43, -43, -42, -42, -41, -40, -40, -39, -39, -38, -38, -37, -36, -36, -35, -35,
959                                        -34, -34, -33, -32, -32, -31, -31, -30, -30, -29, -29, -28, -27, -27, -26, -26};
960
961
962inline int w3_rssi_to_rx_power(u16 rssi, u8 lna_gain, channel_band_t band) {
963
964    int power = -100;
965    u16 adj_rssi = 0;
966
967    if(band == BAND_24GHZ) {
968        switch(lna_gain) {
969            case 0:
970            case 1:
971                // Low LNA Gain State
972                adj_rssi = rssi + (440 << PHY_RX_RSSI_SUM_LEN_BITS);
973            break;
974
975            case 2:
976                // Medium LNA Gain State
977                adj_rssi = rssi + (220 << PHY_RX_RSSI_SUM_LEN_BITS);
978            break;
979
980            case 3:
981                // High LNA Gain State
982                adj_rssi = rssi;
983            break;
984        }
985
986        power = pow_lookup_B24[(adj_rssi >> (PHY_RX_RSSI_SUM_LEN_BITS+POW_LOOKUP_SHIFT))];
987
988    } else if(band == BAND_5GHZ) {
989        switch(lna_gain){
990            case 0:
991            case 1:
992                // Low LNA Gain State
993                adj_rssi = rssi + (540 << PHY_RX_RSSI_SUM_LEN_BITS);
994            break;
995
996            case 2:
997                // Medium LNA Gain State
998                adj_rssi = rssi + (280 << PHY_RX_RSSI_SUM_LEN_BITS);
999            break;
1000
1001            case 3:
1002                // High LNA Gain State
1003                adj_rssi = rssi;
1004            break;
1005        }
1006
1007        power = pow_lookup_B5[(adj_rssi >> (PHY_RX_RSSI_SUM_LEN_BITS+POW_LOOKUP_SHIFT))];
1008    }
1009
1010    return power;
1011}
1012
1013
1014
1015/*****************************************************************************/
1016/**
1017 * @brief Calculates RSSI from Rx power (in dBm)
1018 *
1019 * This function calculates receive power for a given band, RSSI and LNA gain. This
1020 * provides a reasonable estimate of Rx power, accurate to a few dB for standard waveforms.
1021 *
1022 * This function does not use the VGA gain setting or I/Q magnitudes. The PHY should use these
1023 * to refine its own power measurement if needed.
1024 *
1025 * NOTE:  These lookup tables were developed as part of the RF characterization.  See:
1026 *     http://warpproject.org/trac/wiki/802.11/Benchmarks/Rx_Char
1027 *
1028 *
1029 * @param   rx_pow           - Receive power in dBm
1030 * @return  u16              - RSSI value
1031 *
1032 * @note    rx_pow must be in the range [PKT_DET_MIN_POWER_MIN, PKT_DET_MIN_POWER_MAX] inclusive
1033 */
1034static const u16 rssi_lookup_B24[61] = {  1,  16,  24,  40,  56,  72,  80,  96, 112, 128, 144, 152, 168, 184, 200, 208,
1035                                        224, 240, 256, 272, 280, 296, 312, 328, 336, 352, 368, 384, 400, 408, 424, 440,
1036                                        456, 472, 480, 496, 512, 528, 536, 552, 568, 584, 600, 608, 624, 640, 656, 664,
1037                                        680, 696, 712, 728, 736, 752, 768, 784, 792, 808, 824, 840, 856};
1038
1039static const u16 rssi_lookup_B5[61]  = { 96, 112, 128, 144, 160, 168, 184, 200, 216, 224, 240, 256, 272, 288, 296, 312,
1040                                        328, 344, 352, 368, 384, 400, 416, 424, 440, 456, 472, 480, 496, 512, 528, 544,
1041                                        552, 568, 584, 600, 608, 624, 640, 656, 672, 680, 696, 712, 728, 736, 752, 768,
1042                                        784, 800, 808, 824, 840, 856, 864, 880, 896, 912, 920, 936, 952};
1043
1044
1045int w3_rx_power_to_rssi(s8 rx_pow, channel_band_t band) {
1046    u16 rssi_val = 0;
1047
1048    if ((rx_pow <= PKT_DET_MIN_POWER_MAX) && (rx_pow >= PKT_DET_MIN_POWER_MIN)) {
1049        if(band == BAND_24GHZ){
1050            rssi_val = rssi_lookup_B24[rx_pow-PKT_DET_MIN_POWER_MIN];
1051        } else if(band == BAND_5GHZ){
1052            rssi_val = rssi_lookup_B5[rx_pow-PKT_DET_MIN_POWER_MIN];
1053        }
1054
1055        return rssi_val;
1056
1057    } else {
1058        return WLAN_FAILURE;
1059    }
1060}
1061
1062int wlan_platform_get_rx_pkt_pwr(u8 ant) {
1063    u16 rssi;
1064    u8 lna_gain;
1065    int pwr;
1066
1067    rssi = wlan_phy_rx_get_pkt_rssi(ant);
1068    lna_gain = wlan_phy_rx_get_agc_RFG(ant);
1069    pwr = w3_rssi_to_rx_power(rssi, lna_gain, gl_current_band);
1070
1071    return pwr;
1072}
1073
1074void wlan_platform_enable_phy_cs(u8 enable) {
1075
1076    gl_enable_phy_cs = enable;
1077
1078    if(gl_enable_phy_cs == 0) {
1079        // Disable physical CS
1080        wlan_phy_rx_set_cca_thresh(0xFFFF);
1081        return;
1082    }
1083
1084    wlan_phy_rx_set_cca_thresh(PHY_RX_RSSI_SUM_LEN * w3_rx_power_to_rssi(-62, gl_current_band));
1085
1086    return;
1087}
1088
1089/*****************************************************************************/
1090/**
1091 * @brief Set the minimum power for packet detection
1092 *
1093 * @param   rx_pow           - Receive power in dBm
1094 * @return  int              - Status:  0 - Success; -1 - Failure
1095 */
1096int wlan_platform_set_pkt_det_min_power(int min_power) {
1097    int rssi_val;
1098
1099    if(min_power == 0) {
1100        // 0 disables the min-power logic
1101        wlan_phy_disable_req_both_pkt_det();
1102        return WLAN_SUCCESS;
1103
1104    } else {
1105        wlan_phy_enable_req_both_pkt_det();
1106        rssi_val = w3_rx_power_to_rssi(min_power, gl_current_band);
1107
1108        if(rssi_val != -1) {
1109            wlan_phy_rx_pktDet_RSSI_cfg( (PHY_RX_RSSI_SUM_LEN-1), (rssi_val << PHY_RX_RSSI_SUM_LEN_BITS), 1);
1110
1111            return  0;
1112        } else {
1113            xil_printf("wlan_platform_set_pkt_det_min_power: invalid min_power argument: %d\n", min_power);
1114            return WLAN_FAILURE;
1115        }
1116    }
1117}
1118
1119int wlan_platform_get_rx_pkt_gain(u8 ant) {
1120    u8 bb_gain;
1121    u8 rf_gain;
1122
1123    switch(ant) {
1124        case 0: // RF A
1125            bb_gain = (Xil_In32(WLAN_RX_PKT_AGC_GAINS) >>  0) & 0x1F;
1126            rf_gain = (Xil_In32(WLAN_RX_PKT_AGC_GAINS) >>  5) & 0x03;
1127        break;
1128        case 1: // RF B
1129            bb_gain = (Xil_In32(WLAN_RX_PKT_AGC_GAINS) >>  8) & 0x1F;
1130            rf_gain = (Xil_In32(WLAN_RX_PKT_AGC_GAINS) >>  13) & 0x03;
1131        break;
1132        case 2: // RF C
1133            bb_gain = (Xil_In32(WLAN_RX_PKT_AGC_GAINS) >>  16) & 0x1F;
1134            rf_gain = (Xil_In32(WLAN_RX_PKT_AGC_GAINS) >>  21) & 0x03;
1135        break;
1136        case 3: // RF D
1137            bb_gain = (Xil_In32(WLAN_RX_PKT_AGC_GAINS) >>  24) & 0x1F;
1138            rf_gain = (Xil_In32(WLAN_RX_PKT_AGC_GAINS) >>  29) & 0x03;
1139        break;
1140        default:
1141            xil_printf("wlan_platform_get_rx_pkt_gain: invalid antenna ID: %d\n", ant);
1142            return WLAN_FAILURE;
1143        break;
1144    }
1145
1146    // For MAX2829 RF interface construct 8-bit gain_index value as:
1147    //  [  8]: 0
1148    //  [6:5]: RF gain index (0, 1, 2)
1149    //  [4:0]: BB gain index (0, 1, ..., 31)
1150    return ((rf_gain << 5) | bb_gain);
1151}
1152
1153
1154
1155
1156int wlan_platform_set_radio_tx_power(s8 power) {
1157    // Empty function for WARP v3 - all Tx powers are configured per-packet via
1158    //  tx_frame_info and the mac_hw core driving the radio_controller's Tx gain pins
1159
1160    return WLAN_SUCCESS;
1161}
1162
1163/*****************************************************************************/
1164/**
1165 * @brief Convert dBm to Tx Gain Target
1166 *
1167 * This function maps a transmit power (in dBm) to a radio gain target.
1168 *
1169 * @param   s8 power          - Power in dBm
1170 * @return  u32 gain_target   - Tx attenuation (in dB)
1171 */
1172inline u32 wlan_platform_tx_power_to_gain_target(s8 power){
1173    s8 power_railed;
1174    u32 return_value;
1175
1176    if(power > TX_POWER_MAX_DBM){
1177        power_railed = TX_POWER_MAX_DBM;
1178    } else if( power < TX_POWER_MIN_DBM){
1179        power_railed = TX_POWER_MIN_DBM;
1180    } else {
1181        power_railed = power;
1182    }
1183
1184    // This is only safe because 'power' is constrained to less than half the dynamic range of an s8 type
1185    return_value = (u32)((power_railed << 1) + 20);
1186
1187    return return_value;
1188}
1189
1190
Note: See TracBrowser for help on using the repository browser.