source: ReferenceDesigns/w3_802.11/c/wlan_mac_low_framework/wlan_phy_util.c

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

1.8.0 release wlan-mac-se

File size: 10.0 KB
Line 
1/** @file wlan_phy_util.c
2 *  @brief Physical Layer Utility
3 *
4 *  This contains code for configuring low-level parameters in the PHY and hardware.
5 *
6 *  @copyright Copyright 2013-2019, Mango Communications. All rights reserved.
7 *          Distributed under the Mango Communications Reference Design License
8 *              See LICENSE.txt included in the design archive or
9 *              at http://mangocomm.com/802.11/license
10 *
11 *  This file is part of the Mango 802.11 Reference Design (https://mangocomm.com/802.11)
12 */
13/***************************** Include Files *********************************/
14
15// Xilinx SDK includes
16#include "stdio.h"
17#include "stdarg.h"
18#include "xio.h"
19#include "string.h"
20#include "xparameters.h"
21
22// WLAN includes
23#include "wlan_platform_low.h"
24#include "wlan_platform_common.h"
25#include "wlan_mac_mailbox_util.h"
26#include "wlan_phy_util.h"
27#include "wlan_mac_low.h"
28#include "wlan_mac_common.h"
29#include "wlan_mac_pkt_buf_util.h"
30
31// LUT of number of ones in each byte (used to calculate PARITY in SIGNAL)
32const u8 ones_in_chars[256] = {
33         0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,   // 0x00 - 0x0F
34         1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,   // 0x10 - 0x1F
35         1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,   // 0x20 - 0x2F
36         2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,   // 0x30 - 0x3F
37         1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,   // 0x40 - 0x4F
38         2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,   // 0x50 - 0x5F
39         2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,   // 0x60 - 0x6F
40         3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,   // 0x70 - 0x7F
41         1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,   // 0x80 - 0x8F
42         2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,   // 0x90 - 0x9F
43         2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,   // 0xA0 - 0xAF
44         3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,   // 0xB0 - 0xBF
45         2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,   // 0xC0 - 0xCF
46         3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,   // 0xD0 - 0xDF
47         3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,   // 0xE0 - 0xEF
48         4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8};  // 0xF0 - 0xFF
49
50
51// Common Platform Device Info
52extern platform_common_dev_info_t platform_common_dev_info;
53
54
55/*****************************************************************************/
56/**
57 * Calculates the PHY preamble (SIGNAL for 11a, L-SIG/HT-SIG for 11n) and writes
58 * the preamble bytes to the specified packet buffer. The PHY preamble must be
59 * written to the packet buffer for each transmission.
60 *
61 * @param   pkt_buf          - Packet buffer number
62 * @param   phy_mode         - Sets waveform format; must be PHY_MODE_NON_HT (11a) or PHY_MODE_HTMF (11n)
63 * @param   mcs              - MCS (modulation/coding scheme) index
64 * @param   length           - Length of the packet being transmitted
65 *
66 * @return  None
67 *
68 *****************************************************************************/
69const u8 sig_rate_vals[8] = {0xB, 0xF, 0xA, 0xE, 0x9, 0xD, 0x8, 0xC};
70
71void write_phy_preamble(u8 pkt_buf, u8 phy_mode, u8 mcs, u16 length) {
72
73    u8* htsig_ptr;
74    u16 lsig_length;
75    u8* phy_hdr_ptr;
76
77    phy_hdr_ptr = (u8*)(CALC_PKT_BUF_ADDR(platform_common_dev_info.tx_pkt_buf_baseaddr, pkt_buf) + PHY_TX_PKT_BUF_PHY_HDR_OFFSET);
78
79    // RATE field values for SIGNAL/L-SIG in PHY preamble (IEEE 802.11-2012 18.3.4.2)
80    //  RATE field in SIGNAL/L-SIG is one of 8 4-bit values indicating modulation scheme and coding rate
81    //  For 11a (NONHT) transmissions we map mcs index to SIGNAL.RATE directly
82    //  For 11n (HTMF) transmissions the L-SIG.RATE field is always the lowest (BSPK 1/2)
83
84    if((phy_mode & PHY_MODE_NONHT) == PHY_MODE_NONHT) {
85        //11a mode - write SIGNAL (3 bytes)
86
87        //Zero-out any stale header, also properly sets SERVICE and reserved bytes to 0
88        //Old: takes longer than necessary. We only really need the SERVICE bits 0.
89        //bzero((u32*)phy_hdr_ptr, PHY_TX_PKT_BUF_PHY_HDR_SIZE);
90
91        // Set SERVICE to 0.
92        // Unfortunately, SERVICE spans a 32-bit boundary so we need two write 2 words.
93        Xil_Out32((u32)(phy_hdr_ptr + 0), 0);
94        Xil_Out32((u32)(phy_hdr_ptr + 4), 0);
95
96        //Set SIGNAL with actual rate/length
97        Xil_Out32((u32)phy_hdr_ptr, WLAN_TX_SIGNAL_CALC(sig_rate_vals[mcs], length));
98
99    } else if((phy_mode & PHY_MODE_HTMF) == PHY_MODE_HTMF) {
100        //11n mode - write L-SIG (3 bytes) and HT-SIG (6 bytes)
101
102        //Zero-out any stale header, also properly sets SERVICE, reserved bytes, and auto-filled bytes of HT-SIG to 0
103        //Old: takes longer than necessary. We only really need the SERVICE bits 0.
104        //bzero((u32*)(TX_PKT_BUF_TO_ADDR(pkt_buf) + PHY_TX_PKT_BUF_PHY_HDR_OFFSET), PHY_TX_PKT_BUF_PHY_HDR_SIZE);
105
106        // Set SERVICE to 0.
107        Xil_Out32((u32)(phy_hdr_ptr + 8), 0);
108
109
110        // L-SIG is same format as 11a SIGNAL, but with RATE always 6Mb and LENGTH
111        //  set such that LENGTH/6Mb matches duration of HT transmission
112        //  Using equation from IEEE 802.11-2012 9.23.4
113        //   L-SIG.LENGTH = (3*ceil( (TXTIME - 6 - 20) / 4) - 3)
114        //  where TXTIME is actual duration of the HT transmission
115        //   The ceil((TXTIME - 6 - 20)/4) term represents the number of OFDM symbols after the L-SIG symbol
116        //  (-6-20) are (T_EXT-T_NONHT_PREAMBLE); (-3) accounts for service/tail
117
118        // Calc (3*(num_payload_syms+num_ht_preamble_syms) = (3*(num_payload_syms+4))
119
120        lsig_length = 3*wlan_ofdm_calc_num_payload_syms(length, mcs, phy_mode) + 12 - 3;
121
122       
123
124        Xil_Out32((u32)phy_hdr_ptr, WLAN_TX_SIGNAL_CALC(sig_rate_vals[0], lsig_length));
125
126        //Assign pointer to first byte of HTSIG (PHY header base + 3 for sizeof(L-SIG))
127        htsig_ptr = (u8*)(phy_hdr_ptr + 3);
128
129        //Set HTSIG bytes
130        // PHY logic fills in bytes 4 and 5; ok to ignore here
131        // Going byte-by-byte for now - maybe optimize to (unaligned) 32-bit write later
132        htsig_ptr[0] = mcs & 0x3F; //MSB is channel bandwidth; 0=20MHz
133        htsig_ptr[1] = length & 0xFF;
134        htsig_ptr[2] = (length >> 8) & 0xFF;
135        htsig_ptr[3] = 0x7; //smoothing=1, not-sounding=1, reserved=1, aggregation=STBC=FEC=short_GI=0
136        htsig_ptr[4] = 0x00; //NESS=0, CRC bytes must be 0 in pkt buf, PHY replaces with CRC value
137        htsig_ptr[5] = 0x00;
138    }
139
140
141    return;
142}
143
144/*****************************************************************************/
145/**
146 * Calculates duration of an OFDM waveform.
147 *
148 * This function assumes every OFDM symbol is the same duration. Duration
149 * calculation for short guard interval (SHORT_GI) waveforms is not supported.
150 *
151 * @param   length         - Length of MAC payload in bytes
152 * @param   mcs            - MCS index
153 * @param   phy_mode       - PHY waveform mode - either PHY_MODE_NONHT (11a/g) or PHY_MODE_HTMF (11n)
154 * @param   phy_samp_rate  - PHY sampling rate - one of (PHY_10M, PHY_20M, PHY_40M)
155 *
156 * @return  u16              - Duration of transmission in microseconds
157 *                             (See IEEE 802.11-2012 18.4.3 and 20.4.3)
158 *****************************************************************************/
159inline u16 wlan_ofdm_calc_txtime(u16 length, u8 mcs, u8 phy_mode, phy_samp_rate_t phy_samp_rate) {
160
161    u16 num_ht_preamble_syms, num_payload_syms;
162
163    u16 t_preamble;
164    u16 t_sym;
165
166    // Note: the t_ext signal extension represent the value used in the standard, which in turn
167    // is the value expected by other commercial WLAN devices. By default, the signal extensions
168    // programmed into the PHY match this value.
169    u16 t_ext = 6;
170
171    // Set OFDM symbol duration in microseconds; only depends on PHY sampling rate
172    switch(phy_samp_rate) {
173        case PHY_40M:
174            t_sym = 2;
175        break;
176
177        default:
178        case PHY_20M:
179            t_sym = 4;
180        break;
181
182        case PHY_10M:
183            t_sym = 8;
184        break;
185    }
186
187    // PHY preamble common to NONHT and HTMF waveforms consists of 5 OFDM symbols
188    //  4 symbols for STF/LTF
189    //  1 symbol for SIGNAL/L-SIG
190    t_preamble = 5*t_sym;
191
192    // Only HTMF waveforms have HT-SIG, HT-STF and HT-LTF symbols
193    if(phy_mode == PHY_MODE_HTMF) {
194        num_ht_preamble_syms = 4;
195    } else {
196        num_ht_preamble_syms = 0;
197    }
198
199    num_payload_syms = wlan_ofdm_calc_num_payload_syms(length, mcs, phy_mode);
200
201    // Sum each duration and return
202    return (t_preamble + (t_sym * (num_ht_preamble_syms + num_payload_syms)) + t_ext);
203}
204
205
206/*****************************************************************************/
207/**
208 * Calculates number of payload OFDM symbols in a packet. Implements
209 *  ceil(payload_length_bits / num_bits_per_ofdm_sym)
210 *   where num_bits_per_ofdm_sym is a function of the MCS index and PHY mode
211 *
212 * @param   length         - Length of MAC payload in bytes
213 * @param   mcs            - MCS index
214 * @param   phy_mode       - PHY waveform mode - either PHY_MODE_NONHT (11a/g) or PHY_MODE_HTMF (11n)
215 *
216 * @return  u16            - Number of OFDM symbols
217 *****************************************************************************/
218inline u16 wlan_ofdm_calc_num_payload_syms(u16 length, u8 mcs, u8 phy_mode) {
219    u16 num_payload_syms;
220    u32 num_payload_bits;
221    u16 n_dbps;
222
223    // Payload consists of:
224    //  16-bit SERVICE field
225    //  'length' byte MAC payload
226    //  6-bit TAIL field
227    num_payload_bits = 16 + (8 * length) + 6;
228
229    // Num payload syms is ceil(num_payload_bits / N_DATA_BITS_PER_SYM). The ceil()
230    //  operation implicitly accounts for any PAD bits in the waveform. The PHY inserts
231    //  PAD bits to fill the final OFDM symbol. A waveform always consists of an integer
232    //  number of OFDM symbols, so the actual number of PAD bits is irrelevant here
233    n_dbps = wlan_mac_low_mcs_to_n_dbps(mcs, phy_mode);
234    num_payload_syms = num_payload_bits / n_dbps;
235
236    // Apply ceil()
237    //  Integer div above implies floor(); increment result if floor() changed result
238    if( (n_dbps * num_payload_syms) != num_payload_bits ) {
239        num_payload_syms++;
240    }
241
242     return num_payload_syms;
243}
244
Note: See TracBrowser for help on using the repository browser.