[5186] | 1 | function [signal_bytes, ht_sig_bytes] = calc_phy_preamble(phy_mode, mcs, len) |
---|
[5095] | 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 | |
---|
[5186] | 35 | signal_bytes = calc_signal_field(len, SIG_RATE); |
---|
[5095] | 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 |
---|
[5651] | 49 | % set such that LENGTH/6Mb matches duration of HT transmission |
---|
[5095] | 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 |
---|
[5186] | 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; |
---|
[5095] | 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 |
---|
[5186] | 79 | HTSIG1_b1 = uint8(bitand(uint16(len), hex2dec('ff'))); |
---|
| 80 | HTSIG1_b2 = uint8(bitshift( bitand(uint16(len), hex2dec('ff00')), -8)); |
---|
[5095] | 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 |
---|