/** @file wlan_phy_util.c * @brief Physical Layer Utility * * This contains code for configuring low-level parameters in the PHY and hardware. * * @copyright Copyright 2013-2019, Mango Communications. All rights reserved. * Distributed under the Mango Communications Reference Design License * See LICENSE.txt included in the design archive or * at http://mangocomm.com/802.11/license * * This file is part of the Mango 802.11 Reference Design (https://mangocomm.com/802.11) */ /***************************** Include Files *********************************/ // Xilinx SDK includes #include "xio.h" #include "xparameters.h" // WLAN includes #include "wlan_platform_low.h" #include "wlan_platform_common.h" #include "wlan_mac_mailbox_util.h" #include "wlan_phy_util.h" #include "wlan_mac_low.h" #include "wlan_mac_common.h" #include "w3_low.h" #include "w3_mac_phy_regs.h" #include "wlan_common_types.h" #include "w3_phy_util.h" #include "wlan_mac_pkt_buf_util.h" /*****************************************************************************/ /** * Initialize the PHY * * @param None * * @return None * *****************************************************************************/ void wlan_phy_init() { // Assert Tx and Rx resets REG_SET_BITS(WLAN_RX_REG_CTRL, WLAN_RX_REG_CTRL_RESET); REG_SET_BITS(WLAN_TX_REG_CFG, WLAN_TX_REG_CFG_RESET); /************ PHY Rx ************/ // Set the max Tx/Rx packet sizes to 2KB (sane default for standard 802.11a/g links) wlan_phy_rx_set_max_pkt_len_kB( MAX_PKT_SIZE_KB ); wlan_phy_rx_set_max_pktbuf_addr( PKT_BUF_SIZE - sizeof(rx_frame_info_t) - PHY_RX_PKT_BUF_PHY_HDR_SIZE ); // WLAN_RX_DSSS_CFG reg // Configure the DSSS Rx pipeline // wlan_phy_DSSS_rx_config(sync_score_thresh, sync_timeout, sfd_timeout, search_time) wlan_phy_DSSS_rx_config(48, 45, 52, 39); // WLAN_RX_PKT_DET_DSSS_CFG reg // Configure the DSSS auto-correlation packet detector // wlan_phy_pktDet_autoCorr_dsss_cfg(corr_thresh, energy_thresh) // // Note: the below parameters will configure the packet detector such that // around 50% of short DSSS frames are successfully decoded at -82dBm. The // DSSS receiver can be made more sensitive by lowering the energy requirement // argument or clearing the WLAN_RX_REG_CFG_DSSS_RX_REQ_PKT_DET bit. wlan_phy_rx_pktDet_autoCorr_dsss_cfg(110, 60); // WLAN_RX_PKT_DET_OFDM_CFG reg // args: (corr_thresh, energy_thresh, min_dur, post_wait) // Using defaults from set_phy_samp_rate(20) wlan_phy_rx_pktDet_autoCorr_ofdm_cfg(100, 15, 4, 0x3F); // WLAN_RX_REG_CFG reg // Configure DSSS Rx to not wait for DSSS pkt det REG_CLEAR_BITS(WLAN_RX_REG_CFG, (WLAN_RX_REG_CFG_DSSS_RX_REQ_PKT_DET)); // Configure OFDM Rx to wait for pkt det before starting Rx REG_CLEAR_BITS(WLAN_RX_REG_CFG, WLAN_RX_REG_CFG_OFDM_RX_REQ_PKT_DET); // Enable the OFDM Rx pipeline REG_CLEAR_BITS(WLAN_RX_REG_CFG, WLAN_RX_REG_CFG_DISABLE_OFDM_RX); // Enable LTS-based CFO correction REG_CLEAR_BITS(WLAN_RX_REG_CFG, WLAN_RX_REG_CFG_CFO_EST_BYPASS); // Enable byte order swap for payloads and chan ests REG_SET_BITS(WLAN_RX_REG_CFG, WLAN_RX_REG_CFG_PKT_BUF_WEN_SWAP); REG_CLEAR_BITS(WLAN_RX_REG_CFG, WLAN_RX_REG_CFG_CHAN_EST_WEN_SWAP); // Enable writing OFDM chan ests to Rx pkt buffer REG_SET_BITS(WLAN_RX_REG_CFG, WLAN_RX_REG_CFG_RECORD_CHAN_EST); // The rate/length BUSY logic should hold the pkt det signal high to avoid // spurious AGC and detection events during an unsupported waveform REG_SET_BITS(WLAN_RX_REG_CFG, WLAN_RX_REG_CFG_BUSY_HOLD_PKT_DET); // Block Rx inputs during Tx REG_SET_BITS(WLAN_RX_REG_CFG, WLAN_RX_REG_CFG_USE_TX_SIG_BLOCK); // Enable HTMF waveform (11n waveform) detection in the PHY Rx // Disabling HTMF detection reverts the PHY to mac_hw -> phy_tx) for every packet * *****************************************************************************/ void wlan_rx_config_ant_mode(u32 ant_mode) { // Hold the Rx PHY in reset before changing any pkt det or radio enables REG_SET_BITS(WLAN_RX_REG_CTRL, WLAN_RX_REG_CTRL_RESET); wlan_platform_low_set_rx_ant_mode(ant_mode); // Disable all Rx modes first; selectively re-enabled in switch below REG_CLEAR_BITS(WLAN_RX_REG_CFG, (WLAN_RX_REG_CFG_PKT_DET_EN_ANT_A | WLAN_RX_REG_CFG_PKT_DET_EN_ANT_B | WLAN_RX_REG_CFG_PKT_DET_EN_ANT_C | WLAN_RX_REG_CFG_PKT_DET_EN_ANT_D | WLAN_RX_REG_CFG_SWITCHING_DIV_EN | WLAN_RX_REG_CFG_PKT_DET_EN_EXT | WLAN_RX_REG_CFG_ANT_SEL_MASK)); // Set the antenna mode // // For each antenna mode: // - Enable packet detection // - Select I/Q stream for Rx PHY // - Give PHY control of Tx/Rx status // - Configure AGC // switch (ant_mode) { case RX_ANTMODE_SISO_ANTA: REG_SET_BITS(WLAN_RX_REG_CFG, WLAN_RX_REG_CFG_PKT_DET_EN_ANT_A); wlan_phy_select_rx_antenna(RX_ANTMODE_SISO_ANTA); break; case RX_ANTMODE_SISO_ANTB: REG_SET_BITS(WLAN_RX_REG_CFG, WLAN_RX_REG_CFG_PKT_DET_EN_ANT_B); wlan_phy_select_rx_antenna(RX_ANTMODE_SISO_ANTB); break; case RX_ANTMODE_SISO_ANTC: REG_SET_BITS(WLAN_RX_REG_CFG, WLAN_RX_REG_CFG_PKT_DET_EN_ANT_C); wlan_phy_select_rx_antenna(RX_ANTMODE_SISO_ANTC); break; case RX_ANTMODE_SISO_ANTD: REG_SET_BITS(WLAN_RX_REG_CFG, WLAN_RX_REG_CFG_PKT_DET_EN_ANT_D); wlan_phy_select_rx_antenna(RX_ANTMODE_SISO_ANTD); break; case RX_ANTMODE_SISO_SELDIV_2ANT: REG_SET_BITS(WLAN_RX_REG_CFG, (WLAN_RX_REG_CFG_PKT_DET_EN_ANT_A | WLAN_RX_REG_CFG_PKT_DET_EN_ANT_B | WLAN_RX_REG_CFG_SWITCHING_DIV_EN)); break; case RX_ANTMODE_SISO_SELDIV_4ANT: REG_SET_BITS(WLAN_RX_REG_CFG, (WLAN_RX_REG_CFG_PKT_DET_EN_ANT_A | WLAN_RX_REG_CFG_PKT_DET_EN_ANT_B | WLAN_RX_REG_CFG_PKT_DET_EN_ANT_C | WLAN_RX_REG_CFG_PKT_DET_EN_ANT_D | WLAN_RX_REG_CFG_SWITCHING_DIV_EN)); break; default: // Default to SISO on A if user provides invalid mode xil_printf("wlan_rx_config_ant_mode ERROR: Invalid Mode - Defaulting to SISO on A\n"); REG_SET_BITS(WLAN_RX_REG_CFG, WLAN_RX_REG_CFG_PKT_DET_EN_ANT_A); wlan_phy_select_rx_antenna(RX_ANTMODE_SISO_ANTA); break; } // Release the PHY Rx reset REG_CLEAR_BITS(WLAN_RX_REG_CTRL, WLAN_RX_REG_CTRL_RESET); return; } /*****************************************************************************/ /** * Transmission debug methods * * @param Variable * * @return Variable * * @note These function is for debug use only. * *****************************************************************************/ inline void wlan_tx_start() { // Start the PHY Tx immediately; this bypasses the mac_hw MPDU Tx state machine // This should only be used for debug - normal transmissions should use mac_hw // REG_SET_BITS(WLAN_TX_REG_START, WLAN_TX_REG_START_VIA_RC); REG_CLEAR_BITS(WLAN_TX_REG_START, WLAN_TX_REG_START_VIA_RC); return; }