root/ResearchApps/PHY/MIMO_OFDM/Alamouti/ofdm_tx_alamouti_init.m
| Revision 810, 11.7 kB (checked in by murphpo, 11 months ago) |
|---|
| Line | |
|---|---|
| 1 | warning off; |
| 2 | |
| 3 | %Compile-time maximum values; used to set precision of control logic values |
| 4 | max_OFDM_symbols = 2047; |
| 5 | max_num_subcarriers = 64; |
| 6 | max_CP_length = 16; |
| 7 | max_num_baseRateSymbols = 31; |
| 8 | max_num_trainingSymbols = 15; |
| 9 | |
| 10 | %Hard-coded OFDM parameters for now; these might be dynamic some day |
| 11 | numSubcarriers = 64; |
| 12 | CPLength = 16; |
| 13 | |
| 14 | %Set SISO mode |
| 15 | %tx_SISO_Mode = 1; |
| 16 | tx_alamouti_mode = 1; |
| 17 | |
| 18 | %Cyclic Redundancy Check parameters |
| 19 | CRCPolynomial = hex2dec('04c11db7'); |
| 20 | CRC_Table = CRC_table_gen(CRCPolynomial); |
| 21 | |
| 22 | %Define the preamble which is pre-pended to each packet |
| 23 | %These long and short symbols are borrowed from the 802.11a PHY standard |
| 24 | shortSymbol_freq = [0 0 0 0 0 0 0 0 1+i 0 0 0 -1+i 0 0 0 -1-i 0 0 0 1-i 0 0 0 -1-i 0 0 0 1-i 0 0 0 0 0 0 0 1-i 0 0 0 -1-i 0 0 0 1-i 0 0 0 -1-i 0 0 0 -1+i 0 0 0 1+i 0 0 0 0 0 0 0].'; |
| 25 | shortSymbol_time = ifft(fftshift(shortSymbol_freq)); |
| 26 | shortSymbol_time = shortSymbol_time(1:16).'; |
| 27 | |
| 28 | longSymbol_freq_bot = [0 0 0 0 0 0 1 1 -1 -1 1 1 -1 1 -1 1 1 1 1 1 1 -1 -1 1 1 -1 1 -1 1 1 1 1]'; |
| 29 | longSymbol_freq_top = [1 -1 -1 1 1 -1 1 -1 1 -1 -1 -1 -1 -1 1 1 -1 -1 1 -1 1 -1 1 1 1 1 0 0 0 0 0]'; |
| 30 | longSymbol_freq = [longSymbol_freq_bot ; 0 ; longSymbol_freq_top]; |
| 31 | longSymbol_time = ifft(fftshift(longSymbol_freq)).'; |
| 32 | |
| 33 | %Concatenate 10 short symbols together |
| 34 | shortsyms_10 = repmat(shortSymbol_time,1,10); |
| 35 | |
| 36 | %Concatenate and cyclicly extend two long symbols |
| 37 | %longsyms_2 = [longSymbol_time(33:64) repmat(longSymbol_time,1,2)]; |
| 38 | %longSymbol_time = linspace(-1/6, 1/6, 64); |
| 39 | %longsyms_2 = [longSymbol_time(end-31:end) repmat(longSymbol_time,1,2)]; |
| 40 | longsyms_2 = [repmat(longSymbol_time,1,2) longSymbol_time(1:32)]; |
| 41 | |
| 42 | %Scale the resulting time-domain preamble to fit [-1,1] |
| 43 | preamble = 6*[0 shortsyms_10 longsyms_2]; |
| 44 | preamble_ssOnly = 6*[0 shortsyms_10 zeros(1,longsyms_2)]; |
| 45 | |
| 46 | %randseed(1); |
| 47 | %preamble = 6*[0 complex(randn(1,160),randn(1,160)).*0.01 longsyms_2]; |
| 48 | |
| 49 | preamble_I = real(preamble);%[+1*ones(1,length(preamble)-1) -0.1]; |
| 50 | preamble_Q = imag(preamble);%[-1*ones(1,length(preamble)-1) +0.1]; |
| 51 | |
| 52 | %Configure the pilot tone registers |
| 53 | pilot1_indicies = 7 + ( (64-7) * 2^16); |
| 54 | pilot2_indicies = 21 + ( (64-21) * 2^16); |
| 55 | %pilotValue_pos = hex2dec('7FFF') + (2^16 * hex2dec('7FFF'));%+0.9; |
| 56 | %pilotValue_neg = hex2dec('8000') + (2^16 * hex2dec('8000'));%-0.9; |
| 57 | pilotValue_pos = hex2dec('7FFF') + (2^16 * 0);%+0.9; |
| 58 | pilotValue_neg = hex2dec('8000') + (2^16 * 0);%-0.9; |
| 59 | |
| 60 | %Training sequence, borrowed from 802.11a |
| 61 | train = [0 -1 1 -1 1 -1 1 -1 1 -1 -1 -1 -1 1 1 -1 1 1 1 1 1 -1 -1 1 1 -1 -1 0 0 0 0 0 0 0 0 0 0 0 1 -1 1 1 1 -1 -1 -1 -1 1 1 -1 1 -1 1 1 -1 1 1 1 -1 -1 -1 -1 -1 -1]; |
| 62 | train = train * -1; |
| 63 | train(22) = -1; |
| 64 | train(58) = 1; |
| 65 | |
| 66 | %MIMO training; use the same sequence for both antennas |
| 67 | train = [train train]; |
| 68 | |
| 69 | %Maximum number of bytes per packet |
| 70 | RAM_init_size = 4096; |
| 71 | |
| 72 | %Standard 48-active subcarriers |
| 73 | subcarrier_masks = ones(1,numSubcarriers); |
| 74 | subcarrier_masks(1)=0; %DC tone at Xk=0 |
| 75 | subcarrier_masks(8)=0; %pilot tone at Xk=7 |
| 76 | subcarrier_masks(22)=0; %pilot tone at Xk=21 |
| 77 | subcarrier_masks(44)=0; %pilot tone at Xk=43 |
| 78 | subcarrier_masks(58)=0; %pilot tone at Xk=57 |
| 79 | subcarrier_masks([28:32])=0; %zeros at higher frequencies |
| 80 | subcarrier_masks([33:38])=0; %zeros at higher frequencies |
| 81 | |
| 82 | %Choose the modulation schemes to use for the base-rate and full-rate symbols |
| 83 | %Replcae the "2" with one of [0,2,4,6,8] to use 0, QPSK, 16/64/256 QAM |
| 84 | modMask_baseRate = 2; |
| 85 | modMask_fullRate = 2; |
| 86 | modulation_baseRate = modMask_baseRate*subcarrier_masks; |
| 87 | modulation_fullRate = modMask_fullRate*subcarrier_masks; |
| 88 | |
| 89 | %Final vector must be: [FullRate BaseRate] |
| 90 | subcarrier_QAM_Values = [modulation_fullRate modulation_baseRate]; |
| 91 | numBytes_BaseRateOFDMSymbol = sum(modulation_baseRate)/8; |
| 92 | numBytes_FullRateOFDMSymbol = sum(modulation_fullRate)/8; |
| 93 | |
| 94 | %Setup the packet length for simulation |
| 95 | numTrainingSymbols = 4; |
| 96 | %numFullRateSymbols = ceil(120/12);%124; |
| 97 | numBaseRateSymbols = 2; |
| 98 | |
| 99 | %Setup the packet contents |
| 100 | rand('state',1); %Get the same packet each time for BER testing |
| 101 | |
| 102 | %Define the packet's header & other meta-information |
| 103 | pkt_MACAddr_RX = randint(1,6,255); %Radnom MAC addresses |
| 104 | pkt_MACAddr_TX = randint(1,6,255); |
| 105 | pkt_version = 1; |
| 106 | pkt_rate = 2; |
| 107 | pkt_pktType = 0; |
| 108 | pkt_reserved = [0 0 0 0 0]; % 6 bytes |
| 109 | |
| 110 | %Define the indicies (zero-indexed, like C) of some important bytes in the header |
| 111 | %Define the indicies (zero-indexed, like C) of some important bytes in the header |
| 112 | %byteIndex_numPayloadBytes = [22 23]; |
| 113 | %byteIndex_simpleDynModMasks = 8; |
| 114 | byteIndex_numPayloadBytes = [9 10]; |
| 115 | byteIndex_simpleDynModMasks = 8; |
| 116 | numHeaderBytes = 24; |
| 117 | |
| 118 | |
| 119 | %Define the some header meta-data that is common to every packet |
| 120 | % Number of header bytes, used to insert the header checksum in the right spot |
| 121 | % Indicies of three header bytes - 16-bit packet length and 8-bit modulation masks |
| 122 | % It is required that the Tx and Rx nodes have matching values ahead of time |
| 123 | pktByteNums = numHeaderBytes + ... |
| 124 | byteIndex_numPayloadBytes(1)*2^8 + ... |
| 125 | byteIndex_numPayloadBytes(2)*2^16 + ... |
| 126 | byteIndex_simpleDynModMasks * 2^24; |
| 127 | |
| 128 | %Calculate the number of bytes in the packet, based on the number of OFDM symbols specified above |
| 129 | % In hardware, the user code will provide this value per-packet |
| 130 | pkt_numPayloadBytes = 24+4+20+20;%1400;%numBytes_BaseRateOFDMSymbol*numBaseRateSymbols + numBytes_FullRateOFDMSymbol*numFullRateSymbols; |
| 131 | %numFullRateSymbols = ceil( (pkt_numPayloadBytes/numBytes_FullRateOFDMSymbol) - numBaseRateSymbols );%124; |
| 132 | numFullRateSymbols = ceil((pkt_numPayloadBytes - numBytes_BaseRateOFDMSymbol*numBaseRateSymbols)/numBytes_FullRateOFDMSymbol); |
| 133 | numFullRateSymbols = numFullRateSymbols + mod(numFullRateSymbols, 2); |
| 134 | |
| 135 | %Construct the packet header (base-rate symbol data) byte-by-byte |
| 136 | packetHeader = [... |
| 137 | pkt_MACAddr_RX... %bytes 0-5 |
| 138 | pkt_MACAddr_TX... %bytes 6-11 |
| 139 | pkt_version... %byte 12 |
| 140 | floor((pkt_numPayloadBytes/256))... %byte 13 |
| 141 | mod(pkt_numPayloadBytes,256)... %byte 14 |
| 142 | (modMask_fullRate) ... %byte 15 |
| 143 | pkt_rate... %byte 16 |
| 144 | pkt_pktType... %byte 17 |
| 145 | 0 ... %byte 18 |
| 146 | pkt_reserved... %bytes 19-23 |
| 147 | ]; |
| 148 | |
| 149 | %Construct the packet header (base-rate symbol data) byte-by-byte |
| 150 | %packetHeader = [... |
| 151 | % pkt_MACAddr_RX... %bytes 0-5 |
| 152 | % pkt_MACAddr_TX... %bytes 6-11 |
| 153 | % pkt_version... %byte 12 |
| 154 | % pkt_rate... %byte 13 |
| 155 | % pkt_pktType... %byte 14 |
| 156 | % 0 ... %byte 15 |
| 157 | % floor((pkt_numPayloadBytes/256))... %byte 16 |
| 158 | % mod(pkt_numPayloadBytes,256)... %byte 17 |
| 159 | % pkt_reserved... %bytes 18-23 |
| 160 | % ]; |
| 161 | |
| 162 | %Assemble the rest of the packet, using random bytes for the full-rate payload |
| 163 | %packet = [packetHeader 1:-4+(numBytes_FullRateOFDMSymbol*numFullRateSymbols)]; |
| 164 | %packet = [packetHeader randint(1,(pkt_numPayloadBytes-4-24),255)];%1:(pkt_numPayloadBytes-4-24)]; |
| 165 | packet = [packetHeader 1:(pkt_numPayloadBytes-length(packetHeader)-4)]; |
| 166 | |
| 167 | %Add the 32-bit checksum to the end of the payload |
| 168 | % In hardware, the checksum automatically over-writes the last four bytes of the payload |
| 169 | packet = mod(packet,256); |
| 170 | packet = [packet calcTxCRC(packet)]; |
| 171 | |
| 172 | %This value allows the simulated transmitter to start new packets |
| 173 | % leaving a few hundred cycles of idle time between each packet |
| 174 | simOnly_numSamples = length(preamble)+( (numSubcarriers+CPLength)*(numTrainingSymbols + numBaseRateSymbols + numFullRateSymbols) ); |
| 175 | |
| 176 | %Parameters to initialize the packet buffers |
| 177 | % The default packet is loaded at configuration, allowing real-time BER tests |
| 178 | % This packet will be overwritten in hardware when user-code loads packets |
| 179 | packet_length = length(packet)-1; |
| 180 | RAM_init_values = [packet, zeros(1,RAM_init_size-1-packet_length)]; |
| 181 | |
| 182 | BER_RAM_init_values = reshape(flipud(reshape(RAM_init_values, 8, RAM_init_size/8)), 1, RAM_init_size); |
| 183 | |
| 184 | %LSFR parameters, used for random payload mode |
| 185 | txLSFR_numBits = 13; |
| 186 | txLSFR_polynomials = {'21' '35' '0B' '1D' '35' '0B' '3D' '2B'}; |
| 187 | txLSFR_initValues = {'3F' '1B' '03' '35' '17' '0A' '74' '39'}; |
| 188 | |
| 189 | %Precision for the constants which store the modulation values |
| 190 | modConstellation_prec = 8; |
| 191 | modConstellation_bp = 7; |
| 192 | |
| 193 | TxRx_FFTScaling = bin2dec('011011') + (bin2dec('000101') * 2^6); |
| 194 | |
| 195 | %Defintion of the various constellations |
| 196 | %Gray coded bit-symbol mappings |
| 197 | %Borrowed from the IEEE 802.16 specification |
| 198 | % IEEE Std 802.16-2004 Tables 153-155 (pg. 329) |
| 199 | |
| 200 | %QPSK constellation |
| 201 | %2 bits per symbol, 1 bit per I/Q |
| 202 | % I = MSB, Q = LSB |
| 203 | %modConstellation_qpsk = [1 -1]; |
| 204 | modConstellation_qpsk = [1 -1]./sqrt(2); |
| 205 | %modConstellation_qpsk = (1-2^-modConstellation_bp).*modConstellation_qpsk./(max(abs(modConstellation_qpsk))); |
| 206 | |
| 207 | %16-QAM constellation |
| 208 | %4 bits per symbol, 2 bits per I/Q |
| 209 | % I = 2MSB, Q = 2LSB |
| 210 | modConstellation_qam16 = 0.75*[1 3 -1 -3]./3; |
| 211 | %modConstellation_qam16 = [1 3 -1 -3]; |
| 212 | %modConstellation_qam16 = [1 3 -1 -3]./sqrt(10); |
| 213 | %modConstellation_qam16 = (1-2^-modConstellation_bp).*modConstellation_qam16./(max(abs(modConstellation_qam16))); |
| 214 | |
| 215 | %FIXME: 64/256QAM constellations exceed +/-1, which won't fit in the current data types! |
| 216 | %64-QAM constellation |
| 217 | %6 bits per symbol, 3 bits per I/Q |
| 218 | % I = 3MSB, Q = 3LSB |
| 219 | modConstellation_qam64 = 0.875*[3 1 5 7 -3 -1 -5 -7]./7; |
| 220 | %modConstellation_qam64 = [3 1 5 7 -3 -1 -5 -7]; |
| 221 | %modConstellation_qam64 = [3 1 5 7 -3 -1 -5 -7]./(7*3/sqrt(10));%sqrt(42); |
| 222 | %modConstellation_qam64 = (1-2^-modConstellation_bp).*modConstellation_qam64./(max(abs(modConstellation_qam64))); |
| 223 | |
| 224 | %256-QAM constellation |
| 225 | %8 bits per symbol, 4 bits per I/Q |
| 226 | % I = 4MSB, Q = 4LSB |
| 227 | modConstellation_qam256 = 0.9375*[3 1 5 7 11 9 13 15 -3 -1 -5 -7 -11 -9 -13 -15]./15; |
| 228 | %modConstellation_qam256 = [3 1 5 7 11 9 13 15 -3 -1 -5 -7 -11 -9 -13 -15]; |
| 229 | %1/(modnorm(qammod(0:255,256),'avpow',1))^2 |
| 230 | %modConstellation_qam256 = [3 1 5 7 11 9 13 15 -3 -1 -5 -7 -11 -9 -13 -15]./sqrt(170); |
| 231 | %modConstellation_qam256 = (1-2^-modConstellation_bp).*modConstellation_qam256./(max(abs(modConstellation_qam256))); |
| 232 | |
| 233 | %interpFilter = firpm(40, [0 0.18 0.25 1], [1 1 0 0]); |
| 234 | [x, interpFilter] = interp(longSymbol_time, 5); |
| 235 | [x, interpFilter_4] = interp(longSymbol_time, 4); |
| 236 | %interpFilter_4 = firpm(31,[0 0.22 0.32 1], [1 1 0 0]); |
| 237 | %interpFilter_4 = firpm(31,[0 (1-52/64)*.25 (1+52/64)*.25 1], [1 1 0 0]); |
| 238 | %interpFilter_4 = 2*interpFilter_4./norm(interpFilter_4); |
| 239 | %interpFilter_4 = rcosfir(0.2, 4, 4, 1); |
| 240 | |
| 241 | antB_preambleShift = 4; |
| 242 | |
| 243 | %Popluate the TxControlBits register |
| 244 | %0x1: 1: Unused |
| 245 | %0x2: 2: Unused |
| 246 | %0x4: 4: Disable antenna B preamble |
| 247 | %0x8: 8: Enable pilot tone scrambling |
| 248 | %0xF0: : Antenna B preamble shift |
| 249 | %0x100: 256: Enable re-transmission (relay mode) |
| 250 | %0x200: 512: Swap antenna A/B (sends stream B first in relay mode) |
| 251 | %0x400: 1024: Enable Tx PreCFO |
| 252 | %0x800: 2048: Enable relay re-transmission |
| 253 | %0xFFFF0000: Delay before re-transmission |
| 254 | |
| 255 | tx_controlBits = ... |
| 256 | 0 * 1 ... %Unused |
| 257 | + 0 * 2 ... %Unused |
| 258 | + 0 * 4 ... %0=enable antenna B preamble |
| 259 | + 1 * 8 ... %1=enable pilot scrambling |
| 260 | + 1 * 16 * (antB_preambleShift) ... %4-bit preamble shift |
| 261 | + 0 * 256 ... %1=relay mode |
| 262 | + 0 * 512 ... %1=antenna swap |
| 263 | + 1 * 1024 ... %1=enable Tx preCFO |
| 264 | + 1 * 2048 ... %1=Enable relay (DF) re-transmission on goodPkt |
| 265 | + 1 * 2^16 * 1000; %16-bit re-transmit delay |
| 266 | |
| 267 | %DataScrambling_Seq = zeros(1,32); |
| 268 | TxDataScrambling_Seq = [40 198 78 63 82 173 102 245 48 111 172 115 147 230 216 93 72 65 62 2 205 242 122 90 128 83 105 97 73 10 5 252]; |
| 269 | RxDataScrambling_Seq = [40 198 78 63 82 173 102 245 48 111 172 115 147 230 216 93 72 65 62 2 205 242 122 90 128 83 105 97 73 10 5 252]; |
| 270 | |
| 271 | %Load Chipscope capture data |
| 272 | AntA_ADC_I = 0;AntA_ADC_Q = 0; csInterp = 2; t_start = 1; |
| 273 | %xlloadchipScopeData('cfo_v06_capt1_coarseEstOffBy10x.prn'); csInterp = 2; t_start = 1000; |
| 274 | %xlloadchipScopeData('cfo_v08_coarseCfoTooBig_1.prn'); csInterp = 2; t_start = 2913; |
| 275 | %xlloadchipScopeData('cfo_v08_coarseCfoGood_0.prn'); csInterp = 2; t_start = 535; |
| 276 | rxAntI.time = []; |
| 277 | rxAntQ.time = []; |
| 278 | rxAntI.signals.values = AntA_ADC_I(t_start:csInterp:end); |
| 279 | rxAntQ.signals.values = AntA_ADC_Q(t_start:csInterp:end); |
Note: See TracBrowser
for help on using the browser.