1 | function [signal_bytes, ht_sig_bytes] = calc_phy_preamble(phy_mode, mcs, len) |
---|
2 | % phy_mode: 1 = 11a, 2 = 11n |
---|
3 | % mcs: integer MCS index |
---|
4 | % length: integer payload length, in bytes |
---|
5 | |
---|
6 | if phy_mode == 1 |
---|
7 | %802.11a SIGNAL field - 24 bits (IEEE 802.11-2012 18.3.4) |
---|
8 | % [ 0: 3]: RATE (8 4-bit magic numbers, encoded in switch/case below) |
---|
9 | % [ 4]: Reserved (1'b0) |
---|
10 | % [ 5:16]: LENGTH |
---|
11 | % [ 17]: Parity (XOR of bits 0-16) |
---|
12 | % [18:23]: TAIL (6'b0) |
---|
13 | |
---|
14 | switch mcs |
---|
15 | case 0 %BPSK 1/2 |
---|
16 | SIG_RATE = uint8(11); %1101 -> 1011 |
---|
17 | case 1 %BPSK 3/4 |
---|
18 | SIG_RATE = uint8(15); %1111 -> 1111 |
---|
19 | case 2 %QPSK 1/2 |
---|
20 | SIG_RATE = uint8(10); %0101 -> 1010 |
---|
21 | case 3 %QPSK 3/4 |
---|
22 | SIG_RATE = uint8(14); %0111 -> 1110 |
---|
23 | case 4 %16QAM 1/2 |
---|
24 | SIG_RATE = uint8(9); %1001 -> 1001 |
---|
25 | case 5 %16QAM 3/4 |
---|
26 | SIG_RATE = uint8(13); %1011 -> 1101 |
---|
27 | case 6' %64QAM 2/3 |
---|
28 | SIG_RATE = uint8(8); %0001 -> 1000 |
---|
29 | case 7 %64QAM 3/4 |
---|
30 | SIG_RATE = uint8(12); %0011 -> 1100 |
---|
31 | otherwise |
---|
32 | error('Invalid mod_order or code_rate'); |
---|
33 | end |
---|
34 | |
---|
35 | signal_bytes = calc_signal_field(len, SIG_RATE); |
---|
36 | ht_sig_bytes = []; |
---|
37 | |
---|
38 | return; |
---|
39 | |
---|
40 | elseif phy_mode == 2 |
---|
41 | %802.11n L-SIG field - 24 bits (IEEE 802.11-2012 20.3.9.3.5) |
---|
42 | % [ 0: 3]: RATE (4-bit magic number) |
---|
43 | % [ 4]: Reserved (1'b0) |
---|
44 | % [ 5:16]: LENGTH |
---|
45 | % [ 17]: Parity (XOR of bits 0-16) |
---|
46 | % [18:23]: TAIL (6'b0) |
---|
47 | |
---|
48 | %L-SIG is same format as 11a SIGNAL, but with RATE always 6Mb and LENGTH |
---|
49 | % set such that LENGTH/6Mb matches duration of HT transmission |
---|
50 | % Using equation from IEEE 802.11-2012 9.23.4 |
---|
51 | % L-SIG.LENGTH = (3*ceil( (TXTIME - 6 - 20) / 4) - 3) |
---|
52 | % where TXTIME is actual duration of the HT transmission |
---|
53 | % Calculating TXTIME is complicated in general; for now, since our PHY only |
---|
54 | % supports the 1SS, long-GI rates, we'll just use a 8-entry LUT |
---|
55 | mcs_datarates = [6.5 13 19.5 26 39 52 38.5 65]; %Table 20-30 |
---|
56 | ht_txtime_usec = 16 + 5*4 + ((2+len)*8 + 6)/mcs_datarates(mcs+1) + 6; %approx, good enough for sim |
---|
57 | LSIG_LENGTH = 3*ceil((ht_txtime_usec - 6 - 20)/4) - 3; |
---|
58 | LSIG_RATE = uint8(11); %6Mb |
---|
59 | |
---|
60 | signal_bytes = calc_signal_field(LSIG_LENGTH, LSIG_RATE); |
---|
61 | |
---|
62 | %802.11n HT-SIG field - 48 bits (IEEE 802.11-2012 20.3.9.4.3) |
---|
63 | %HTSIG1 |
---|
64 | % [ 0: 6]: MCS |
---|
65 | % [ 7]: CBW 20/40 |
---|
66 | % [ 8:23]: HT LENGTH |
---|
67 | %HTSIG2 |
---|
68 | % [ 0]: Smoothing |
---|
69 | % [ 1]: Not Sounding |
---|
70 | % [ 2]: Reserved (1'b1) |
---|
71 | % [ 3]: Aggregation |
---|
72 | % [ 4: 5]: STBC |
---|
73 | % [ 6]: FEC CODING |
---|
74 | % [ 7]: SHORT GI |
---|
75 | % [ 8: 9]: Num ext spatial streams |
---|
76 | % [10:17]: Checksum (CRC8 of HTSIG1[0:23] and HTSIG2[0:9]) |
---|
77 | % [18:23]: Tail (6'b0) |
---|
78 | HTSIG1_b0 = uint8(bitand(uint8(mcs), hex2dec('3f'))); %CBW is 0 for 20MHz |
---|
79 | HTSIG1_b1 = uint8(bitand(uint16(len), hex2dec('ff'))); |
---|
80 | HTSIG1_b2 = uint8(bitshift( bitand(uint16(len), hex2dec('ff00')), -8)); |
---|
81 | |
---|
82 | HTSIG2_b0 = uint8(bin2dec('00000111')); %Yes smoothing |
---|
83 | HTSIG2_b1 = uint8(0); %0 ESS, CRC filled in by hardware |
---|
84 | HTSIG2_b2 = uint8(0); %CRC filled in by hardware, tail always 0 |
---|
85 | |
---|
86 | ht_sig_bytes = [HTSIG1_b0 HTSIG1_b1 HTSIG1_b2 HTSIG2_b0 HTSIG2_b1 HTSIG2_b2]; |
---|
87 | end |
---|
88 | end |
---|
89 | |
---|
90 | function signal_bytes = calc_signal_field(length, rate) |
---|
91 | %Select 12 LSB of length argument |
---|
92 | length_u = bitand(uint16(length), hex2dec('fff')); |
---|
93 | |
---|
94 | %Isolate the 3 parts of LENGTH that span byte boundaries |
---|
95 | length_2to0 = uint8(bitand(length_u, 7)); |
---|
96 | length_10to3 = uint8(bitand(bitshift(length_u, -3), 255)); |
---|
97 | length_msb = uint8(bitshift(length_u, -11)); |
---|
98 | |
---|
99 | %Calculate the parity bit |
---|
100 | parity = mod(sum(sum(dec2bin([uint32(length_u) uint32(rate)]) == '1')), 2); |
---|
101 | |
---|
102 | %Calculate final 3-byte output |
---|
103 | b0 = bitor(rate, bitshift(length_2to0, 5)); |
---|
104 | b1 = length_10to3; |
---|
105 | b2 = bitor(length_msb, bitshift(parity, 1)); |
---|
106 | |
---|
107 | %Return as array - sim uses this to replace bytes in init value of simulated packet buffer |
---|
108 | signal_bytes = [b0 b1 b2]; |
---|
109 | end |
---|