NetSim Source Code Help v14.4
All 13 Components
 
Loading...
Searching...
No Matches
IEEE802_11ax.c
1/************************************************************************************
2 * Copyright (C) 2023 *
3 * TETCOS, Bangalore. India *
4 * *
5 * Tetcos owns the intellectual property rights in the Product and its content. *
6 * The copying, redistribution, reselling or publication of any or all of the *
7 * Product or its content without express prior written consent of Tetcos is *
8 * prohibited. Ownership and / or any other right relating to the software and all *
9 * intellectual property rights therein shall remain at all times with Tetcos. *
10 * *
11 * Author: HESUOFDM@IITM *
12 * *
13 * ---------------------------------------------------------------------------------*/
14
15#include "main.h"
16#include "IEEE802_11.h"
17#include "IEEE802_11_Phy.h"
18
19/**
20This function is called to initialize the MIMO and OFDM parameters relevant to
21IEEE802.11ax.
22This function is called from the "fn_NetSim_WLAN_PHY_Configuration()" for HE PHY.
23Initialize time parameters as per the Table 27-13—Timing-related constants IEEE Std 802.11™-2024 pdf
24also initialize 802.11ax PHY header relevant parameters.
25*/
26void fn_NetSim_IEEE802_11ax_OFDM_MIMO_init(NETSIM_ID nDeviceId,NETSIM_ID nInterfaceId)
27{
28 UINT nNSTS_MAX = 8;
29 UINT nNSS_MAX = 8;
30 PIEEE802_11_PHY_VAR phy = IEEE802_11_PHY(nDeviceId,nInterfaceId);
31
32 // Initialize Subcarrier allocation related constants According Table 27-14 and Timing related constants from Table 27-13 from IEEE Std 802.11™-2024 pdf
33
34 if(phy->dChannelBandwidth == 20)
35 {
36 phy->PHY_TYPE.ofdmPhy_11ax.nCH_BANDWIDTH = HE_CBW20;
37 phy->PHY_TYPE.ofdmPhy_11ax.nNSD = 234; // NSD Number of complex data numbers
38 phy->PHY_TYPE.ofdmPhy_11ax.nNSP = 8; // NSP Number of pilot values
39 phy->PHY_TYPE.ofdmPhy_11ax.nNST = 242; // 52 + 4
40 phy->PHY_TYPE.ofdmPhy_11ax.nNSR = 122; // NSR Highest data subcarrier index
41 phy->PHY_TYPE.ofdmPhy_11ax.nFFT = 256; // FFT length
42 }
43 else if(phy->dChannelBandwidth == 40)
44 {
45 phy->PHY_TYPE.ofdmPhy_11ax.nCH_BANDWIDTH = HE_CBW40;
46 phy->PHY_TYPE.ofdmPhy_11ax.nNSD = 468; // NSD Number of complex data numbers
47 phy->PHY_TYPE.ofdmPhy_11ax.nNSP = 16; // NSP Number of pilot values
48 phy->PHY_TYPE.ofdmPhy_11ax.nNST = 484; // 108 + 6
49 phy->PHY_TYPE.ofdmPhy_11ax.nNSR = 244; // NSR Highest data subcarrier index
50 phy->PHY_TYPE.ofdmPhy_11ax.nFFT = 512; // FFT length
51 }
52 else if(phy->dChannelBandwidth == 80)
53 {
54 phy->PHY_TYPE.ofdmPhy_11ax.nCH_BANDWIDTH = HE_CBW80;
55 phy->PHY_TYPE.ofdmPhy_11ax.nNSD = 980; // NSD Number of complex data numbers
56 phy->PHY_TYPE.ofdmPhy_11ax.nNSP = 16; // NSP Number of pilot values
57 phy->PHY_TYPE.ofdmPhy_11ax.nNST = 996; // 108 + 6
58 phy->PHY_TYPE.ofdmPhy_11ax.nNSR = 500; // NSR Highest data subcarrier index
59 phy->PHY_TYPE.ofdmPhy_11ax.nFFT = 1024; // FFT length
60 }
61 else
62 {
63 phy->PHY_TYPE.ofdmPhy_11ax.nCH_BANDWIDTH = HE_CBW160;
64 phy->PHY_TYPE.ofdmPhy_11ax.nNSD = 1960; // NSD Number of complex data numbers
65 phy->PHY_TYPE.ofdmPhy_11ax.nNSP = 32; // NSP Number of pilot values
66 phy->PHY_TYPE.ofdmPhy_11ax.nNST = 1992; // 108 + 6
67 phy->PHY_TYPE.ofdmPhy_11ax.nNSR = 1012; // NSR Highest data subcarrier index
68 phy->PHY_TYPE.ofdmPhy_11ax.nFFT = 2048; // FFT length
69 }
70
71 // Assign all the timing relevent parameters
72 phy->PHY_TYPE.ofdmPhy_11ax.dDeltaF_PreHE = 312500; // SubcarrierFrequencySpacing 312.5KHz (20 MHz/64) or (40 MHz/128)
73 phy->PHY_TYPE.ofdmPhy_11ax.dDeltaF = phy->dChannelBandwidth/ (phy->PHY_TYPE.ofdmPhy_11ax.nFFT * 1.0);//SubcarrierFrequencySpacing 312.5KHz (20 MHz/64) or (40 MHz/128)
74 phy->PHY_TYPE.ofdmPhy_11ax.dTDFT_PreHE = 3.2; //IDFT/DFT period 3.2 MicroSecs for Pre HE
75 phy->PHY_TYPE.ofdmPhy_11ax.dTDFT = 12.8; // IDFT/DFT period 3.2 MicroSecs
76 phy->PHY_TYPE.ofdmPhy_11ax.dTGI_PreHE = 0.8; // 3.2/4 = 0.8 MicroSecs Guard interval duration 0.8 = TDFT/4
77 phy->PHY_TYPE.ofdmPhy_11ax.dTGIL_LTF = 1.6; // 0.8 * 2 = 1.6 MicroSecs Double guard interval 1.6
78 phy->PHY_TYPE.ofdmPhy_11ax.dTGI1 = 0.8; // Short guard interval duration dDFT/8 = 0.4
79 phy->PHY_TYPE.ofdmPhy_11ax.dTGI2 = 1.6;
80 phy->PHY_TYPE.ofdmPhy_11ax.dTGI4 = 3.2;
81
82 if(phy->nGuardInterval == 800)
83 phy->PHY_TYPE.ofdmPhy_11ax.dTGI_HE_LTF = phy->PHY_TYPE.ofdmPhy_11ax.dTGI1;
84 else if(phy->nGuardInterval == 1600)
85 phy->PHY_TYPE.ofdmPhy_11ax.dTGI_HE_LTF = phy->PHY_TYPE.ofdmPhy_11ax.dTGI2;
86 else
87 phy->PHY_TYPE.ofdmPhy_11ax.dTGI_HE_LTF = phy->PHY_TYPE.ofdmPhy_11ax.dTGI4;
88
89 phy->PHY_TYPE.ofdmPhy_11ax.dTSYM1 = 13.6;
90 phy->PHY_TYPE.ofdmPhy_11ax.dTSYM2 = 14.4;
91 phy->PHY_TYPE.ofdmPhy_11ax.dTSYM4 = 16.0;
92
93 if(phy->nGuardInterval == 800)
94 phy->PHY_TYPE.ofdmPhy_11ax.dTSYM = phy->PHY_TYPE.ofdmPhy_11ax.dTSYM1;
95 else if(phy->nGuardInterval == 1600)
96 phy->PHY_TYPE.ofdmPhy_11ax.dTSYM = phy->PHY_TYPE.ofdmPhy_11ax.dTSYM2;
97 else
98 phy->PHY_TYPE.ofdmPhy_11ax.dTSYM = phy->PHY_TYPE.ofdmPhy_11ax.dTSYM4;
99
100 phy->PHY_TYPE.ofdmPhy_11ax.nTL_STF = 8; // Non-HT short training sequence duration 8 = 10*TDFT/4
101 phy->PHY_TYPE.ofdmPhy_11ax.nTL_LTF = 8; // Non-HT long training field duration 8 =2 * TDFT + TGI2
102 phy->PHY_TYPE.ofdmPhy_11ax.nTL_SIG = 4; // Non-HT SIGNAL field duration 4 = TDFT/2 + TGI2
103 phy->PHY_TYPE.ofdmPhy_11ax.nTRL_SIG = 4;
104 phy->PHY_TYPE.ofdmPhy_11ax.nTHE_SIGA = 8; // HE-SIGA field duration 8 = TDFT/2 + TGI2
105 phy->PHY_TYPE.ofdmPhy_11ax.nTHE_SIGB = 4;
106 phy->PHY_TYPE.ofdmPhy_11ax.nTHE_STF_NT = 4;
107 phy->PHY_TYPE.ofdmPhy_11ax.nTHE_LTF_1x = 3.2;
108 phy->PHY_TYPE.ofdmPhy_11ax.nTHE_LTF_2x = 6.4; // HE long training field duration 3.2 in 1x, 6.4 in 2x
109 phy->PHY_TYPE.ofdmPhy_11ax.nTHE_LTF_4x = 12.8; // HE long training field duration 3.2 in 1x, 6.4 in 2x, 12.8 in 4x
110
111 if(phy->nGuardInterval == 800)
112 phy->PHY_TYPE.ofdmPhy_11ax.nTHE_LTF = phy->PHY_TYPE.ofdmPhy_11ax.nTHE_LTF_1x;
113 else if(phy->nGuardInterval == 1600)
114 phy->PHY_TYPE.ofdmPhy_11ax.nTHE_LTF = phy->PHY_TYPE.ofdmPhy_11ax.nTHE_LTF_2x;
115 else
116 phy->PHY_TYPE.ofdmPhy_11ax.nTHE_LTF = phy->PHY_TYPE.ofdmPhy_11ax.nTHE_LTF_4x;
117
118
119 phy->PHY_TYPE.ofdmPhy_11ax.nTHE_LTF_SYM = phy->PHY_TYPE.ofdmPhy_11ax.nTHE_LTF + phy->PHY_TYPE.ofdmPhy_11ax.dTGI_HE_LTF;
120 phy->PHY_TYPE.ofdmPhy_11ax.nTSYML = 4;
121 phy->PHY_TYPE.ofdmPhy_11ax.nTPE = 0; //Preamble extension duration set to 0
122
123
124 if(phy->nGuardInterval == 800)
125 phy->PHY_TYPE.ofdmPhy_11ax.nGI_TYPE = HE_GI_800NS;
126 else if(phy->nGuardInterval == 1600)
127 phy->PHY_TYPE.ofdmPhy_11ax.nGI_TYPE = HE_GI_1600NS;
128 else
129 phy->PHY_TYPE.ofdmPhy_11ax.nGI_TYPE = HE_GI_3200NS;
130
131
132 // STBC is disabled (0 = disabled, 1 = enabled)
133 phy->PHY_TYPE.ofdmPhy_11ax.nSTBC = 0;
134
135 // Set NSS (number of spatial streams) = min(TX antennas, RX antennas), max 8
136 phy->NSS = min((phy->nNTX < phy->nNRX ? phy->nNTX : phy->nNRX), nNSS_MAX);
137
138 // Set NSTS (number of space-time streams) = NSS if STBC is disabled
139 phy->NSTS = phy->NSS;
140
141 // Ensure NSTS does not exceed 8 (HE SU max)
142 phy->NSTS = min(phy->NSTS, 8);
143
144 // Set HE-LTF count based on NSTS and LTF mode (1x, 2x, or 4x)
145 // Default: 1x LTF mode (no compression)
146 switch (phy->NSTS) {
147 case 1: phy->N_HE_LTF = 1; break; // 1 LTF for 1 stream
148 case 2: phy->N_HE_LTF = 2; break; // 2 LTFs for 2 streams
149 case 3:
150 case 4: phy->N_HE_LTF = 4; break; // 4 LTFs for 3-4 streams
151 case 5:
152 case 6: phy->N_HE_LTF = 6; break; // 6 LTFs for 5-6 streams
153 case 7:
154 case 8: phy->N_HE_LTF = 8; break; // 8 LTFs for 7-8 streams
155 default: phy->N_HE_LTF = 1; break; // Fallback (should not happen)
156 }
157
158 phy->dControlFrameDataRate = fn_NetSim_IEEE802_11_HEPhy_getCtrlFrameDataRate(phy);
159 phy->dBroadcastFrameDataRate= fn_NetSim_IEEE802_11_HEPhy_getCtrlFrameDataRate(phy);
160}
161
162/**
163~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
164This function is updated from the corresponding IEEE802_11ac.c and definitely needs correction.
165A flag field may be considered to add preamble time to the transmission time.
166The implementation for BCC coding and LDPC are incorrect as it is in IEEE802_11ac.c!
167For BCC coding
168NSYM = mSTBC * ceil ( (8*length + 16 + 6*NES)/(mSTBC*NDBPS) )
169For LDPC
170NSYM = Navbits / NCBPS
171~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
172*/
173double fn_NetSim_IEEE802_11ax_TxTimeCalculation(NetSim_PACKET *pstruPacket, NETSIM_ID nDevId, NETSIM_ID nInterfaceId)
174{
175 double dTxTime = 0.0;
176 double dNSYM, dTempNum = 0.0;
177 int mSTBC = 1, nNDBPS, nNCBPS;
178 int nNavbits = 1;
179 PIEEE802_11_PHY_VAR pstruPhy = IEEE802_11_PHY(nDevId,nInterfaceId);
180 double dPacketLength = pstruPacket->pstruPhyData->dPayload;
181
182 if(isIEEE802_11_CtrlPacket(pstruPacket)) // Other than WLAN control packets
183 {
184 nNDBPS = pstruPhy->PHY_TYPE.ofdmPhy_11ax.nNDBPS/pstruPhy->NSS;
185 nNCBPS = pstruPhy->PHY_TYPE.ofdmPhy_11ax.nNCBPS/pstruPhy->NSS;
186 }
187 else
188 {
189 nNDBPS = pstruPhy->PHY_TYPE.ofdmPhy_11ax.nNDBPS;
190 nNCBPS = pstruPhy->PHY_TYPE.ofdmPhy_11ax.nNCBPS;
191 }
192
193
194 if(pstruPhy->PHY_TYPE.ofdmPhy_11ax.nFEC_CODING == BCC_CODING)
195 {
196 dTempNum = (8 * dPacketLength) + 16 + ( 6 * pstruPhy->NESS) ;
197 if(pstruPhy->PHY_TYPE.ofdmPhy_11ax.nSTBC)
198 mSTBC = 2;
199
200 dTempNum = 8*dPacketLength;
201 dNSYM = mSTBC* ( dTempNum/(mSTBC * nNDBPS));
202 dTxTime = pstruPhy->PHY_TYPE.ofdmPhy_11ax.dTSYM * dNSYM ;
203 return dTxTime;
204 }
205 else
206 {
207 dNSYM = nNavbits * nNCBPS;
208 dTxTime = pstruPhy->PHY_TYPE.ofdmPhy_11ax.dTSYM * dNSYM ;
209 return dTxTime;
210 }
211}
212
213double get_11ax_preamble_time(PIEEE802_11_PHY_VAR phy)
214{
215 double dTGF_HE_PREAMBLE;
216 int nSignalExtension = 0;
217
218 dTGF_HE_PREAMBLE = phy->PHY_TYPE.ofdmPhy_11ax.nTRL_SIG \
219 + phy->PHY_TYPE.ofdmPhy_11ax.nTHE_SIGA
220 + phy->PHY_TYPE.ofdmPhy_11ax.nTHE_STF_NT
221 + (phy->N_HE_LTF * phy->PHY_TYPE.ofdmPhy_11ax.nTHE_LTF_SYM);
222
223 return 20 + //Legacy preamble duration
224 dTGF_HE_PREAMBLE +
225 //(phy->PHY_TYPE.ofdmPhy_11ax.dTSYM * phy->PHY_TYPE.ofdmPhy_11ax.nNSYM) +
226 // N_MA*N_HE_LTF*THE_LTF_SYM +
227 // T_PE +
228 nSignalExtension;
229}
double nTHE_LTF_SYM
Duration of each OFDM Symbol with GI in HE LTF THE_LTF + TGI_HE_LTF.
double dTGI_PreHE
Guard interval duration 0.8 = Pre HE TDFT/4.
int nTRL_SIG
Repeated non HT signal field duration 4.
int nTL_STF
Non-HT short training sequence duration 8 = 10*TDFT/4.
double dTGI1
Base Guard interval duration for data field 0.8 us.
int nTHE_STF_NT
HE short training field duration for HE SU PPDU 4 = 5 * 0.8.
int nNSD
NSD Number of data subcarriers per frequency segment.
int nNSR
NSR Highest data subcarrier index per frequency segment.
double dDeltaF
dSubcarrierFrequencySpacing; // 78.125 khz
double nTHE_LTF_2x
Duration of each 2x HE LTF OFDM without GI 6.4.
double dTGI4
Quadruple guard interval 3.2.
double nTHE_LTF
Duration of each OFDM Symbol without GI in HE LTF.
int nTHE_SIGB
HE SIGNAL B field duration TDFT_PreHE + TGI_PreHE = 3.2 + 0.8 = 4.
double dTSYM1
TSYM: Symbol interval 13.6 = TDFT + TGI.
double nTHE_LTF_4x
Duration of each 4x HE LTF OFDM without GI 12.8.
int nNST
NST Total number of subcarriers per frequency segment.
int nNSP
NSP Number of pilot subcarriers per frequency segement.
int nTL_SIG
Non-HT SIGNAL field duration 4.
double dTGI_HE_LTF
Guard interval duration for HE LTF.
double dTDFT_PreHE
IDFT/DFT period for pre HE 3.2.
double dTGIL_LTF
Guard interval duration for Legacy LTF.
double dTSYM4
TSYM: Symbol interval 16 = TDFT + TGI.
double dTSYM
OFDM symbol interval for HE PPDU field.
int nTL_LTF
Non-HT long training field duration 8 =2 * TDFT + TGI2.
double dTDFT
IDFT/DFT period 12.8.
double dDeltaF_PreHE
dSubcarrierFrequencySpacing for Pre HE; //312.5 kHz
double dTSYM2
TSYM: Symbol interval 14.4 = TDFT + TGI.
double dTGI2
Double guard interval 1.6.
int nTSYML
OFDM symbol duration including GI prior to HE STF 4.
int nTHE_SIGA
HE SIGNAL A field duration 8 = 2 * 4.
double nTHE_LTF_1x
Duration of each 1x HE LTF OFDM without GI 3.2.