Projects STRLCPY wirelesscomm Commits 165e3d4e
🤬
Revision indexing in progress... (symbol navigation in revisions will be accurate after indexed)
  • lectures/Unit07_ChanEst.pdf
    Binary file.
  • lectures/Unit07_ChanEst.pptx
    Binary file.
  • ■ ■ ■ ■
    readme.md
    skipped 64 lines
    65 65   * Demo: 802.11 MCS selection [[PDF]](./unit05_amc/demo_mcs.pdf) [[Matlab Live]](./unit05_amc/demo_mcs.mlx)
    66 66   * Demo: Channel Tracking with 5G NR CSI-RS [[PDF]](./unit05_amc/demo_csirs.pdf) [[Matlab Live]](./unit05_amc/demo_csirs.mlx)
    67 67   * Lab: 5G NR DL Throughput with Multi-Process HARQ [[PDF]](./unit05_amc/lab_partial/labHarq.pdf) [[Matlab Live]](./unit05_amc/lab_partial/labHarq.mlx)
    68  - * Problems: [[PDF]](./unit05_amc/prob/prob_amc.pdf) [[Latex]](./unit05_amc/prob/prob_amc.tex)
     68 + * Problems: [[PDF]](./unit05_amc/prob/prob_amc.pdf) [[Latex]](./unit05_amc/prob/prob_amc .tex)
    69 69  * Unit 6. Channel Estimation and Equalization
    70 70  * Unit 7. Multiple Antennas and Beamforming
    71 71   * Lecture: [[PDF]](./lectures/Unit06_Beamforming.pdf) [[PPT]](./lectures/Unit06_Beamforming.pptx)
    skipped 8 lines
  • ■ ■ ■ ■ ■ ■
    unit07_chanest/FDChan.m
     1 +classdef FDChan < matlab.System
     2 + % Frequency-domain multipath channel
     3 + properties
     4 + % Configuration
     5 + carrierConfig; % Carrier configuration
     6 + waveformConfig; % Waveform parameters
     7 +
     8 + % Path parameters
     9 + gain; % Relative path gain in dB
     10 + dly; % Delay of each path in seconds
     11 + fd; % Doppler shift for each path
     12 +
     13 + gainComplex; % Complex gain of each path
     14 +
     15 + % SNR parameters
     16 + Etx = 1; % average energy per PDSCH symbol
     17 + EsN0Avg = 20; % Avg SNR per RX symbol in dB
     18 +
     19 + % Symbol times
     20 + symStart; % symStart(i) = start of symbol i relative to subframe
     21 +
     22 + end
     23 + methods
     24 + function obj = FDChan(carrierConfig, varargin)
     25 + % Constructor
     26 +
     27 + % Save the carrier configuration
     28 + obj.carrierConfig = carrierConfig;
     29 + 
     30 +
     31 + % Set parameters from constructor arguments
     32 + if nargin >= 1
     33 + obj.set(varargin{:});
     34 + end
     35 +
     36 + % Complex gain for each path using a random initial phase
     37 + % The gains are normalized to an average of one
     38 + npath = length(obj.gain);
     39 + phase = 2*pi*rand(npath, 1);
     40 + obj.gainComplex = db2mag(obj.gain).*exp(1i*phase);
     41 + obj.gainComplex = obj.gainComplex / norm(obj.gainComplex);
     42 +
     43 +
     44 + % Symbol times relative to the start of the subframe
     45 + obj.waveformConfig = nrOFDMInfo(obj.carrierConfig);
     46 + nsym = obj.waveformConfig.SymbolLengths;
     47 + obj.symStart = nsym/obj.waveformConfig.SampleRate;
     48 + obj.symStart = cumsum([0 obj.symStart]');
     49 +
     50 + end
     51 +
     52 +
     53 + end
     54 + methods (Access = protected)
     55 +
     56 +
     57 + function [rxGrid, chanGrid, noiseVar] = stepImpl(obj, txGrid, frameNum, slotNum)
     58 + % Applies a frequency domain channel and noise
     59 + %
     60 + % Parameters
     61 + % ----------
     62 + % txGrid: The OFDM grid of TX symbols for one slot
     63 + % frameNum: The index of the frame (1 frame = 10ms)
     64 + % slotNum: The index of the slot in the frame
     65 + % This should be 0,...,waveformConfig.SlotsPerFrame
     66 + %
     67 + % Outputs
     68 + % -------
     69 + % rxGrid: RX grid of RX symbols for one slot
     70 + % chanGrid: Grid of the channel values
     71 + % noiseVar: Noise variance
     72 +
     73 + % Get dimensions of the TX grid
     74 + [nsc, nsym] = size(txGrid);
     75 +
     76 + % Compute the frequency of each carrier
     77 + f = (0:nsc-1)'*obj.carrierConfig.SubcarrierSpacing*1e3;
     78 +
     79 + % Compute slot in sub-frame and sub-frame index
     80 + sfNum = floor(slotNum / obj.waveformConfig.SlotsPerSubframe);
     81 + slotNum1 = mod(slotNum, obj.waveformConfig.SlotsPerSubframe);
     82 +
     83 + % Compute the time for each symbol
     84 + framePeriod = 0.01;
     85 + sfPeriod = 1e-3;
     86 + t = frameNum*framePeriod + sfPeriod*sfNum + ...
     87 + obj.symStart(slotNum1+1:slotNum1+nsym);
     88 +
     89 + % Generate the channel
     90 + chanGrid = zeros(nsc, nsym);
     91 + npath = length(obj.gain);
     92 + for i = 1:npath
     93 + phase = 2*pi*(f*obj.dly(i) + t'*obj.fd(i));
     94 + chanGrid = chanGrid + obj.gainComplex(i)*exp(1i*phase);
     95 + end
     96 +
     97 + % Compute noise variance
     98 + Erx = sum(abs(obj.gainComplex).^2,'all')*obj.Etx;
     99 + noiseVar = Erx * db2pow(-obj.EsN0Avg);
     100 +
     101 + % Apply channel
     102 + rxGrid = chanGrid.*txGrid;
     103 +
     104 + % Add noise
     105 + w = (randn(nsc,nsym) + 1i*randn(nsc,nsym))*sqrt(noiseVar/2);
     106 + rxGrid = rxGrid + w;
     107 +
     108 + end
     109 +
     110 + end
     111 +end
     112 + 
     113 + 
  • unit07_chanest/demoDMRSConfig.mlx
    Binary file.
  • unit07_chanest/demoDMRSConfig.pdf
    Binary file.
  • unit07_chanest/demoDMRSConfigSoln.mlx
    Binary file.
  • unit07_chanest/demoDMRSConfigSoln.pdf
    Binary file.
  • unit07_chanest/demoKernelEst.mlx
    Binary file.
  • unit07_chanest/demoKernelEst.pdf
    Binary file.
  • unit07_chanest/demoKernelEstSoln.mlx
    Binary file.
  • unit07_chanest/demoKernelEstSoln.pdf
    Binary file.
  • ■ ■ ■ ■ ■ ■
    unit07_chanest/kernelReg.m
     1 + 
     2 +function [hest, w] = kernelReg(ind,hestRaw,nsc,len,sig)
     3 +% kernelReg: Kernel regression with a RBF
     4 + 
     5 +% Create the RBF kernel
     6 +w = exp(-0.5*(-len:len).^2/sig^2)';
     7 + 
     8 +% Place the raw channel esimates in a vector at the locations
     9 +% of the indices.
     10 +% y(ind(i)) = hestRaw(i)
     11 +% y0(ind(i)) = 1
     12 +y = zeros(nsc,1);
     13 +y0 = zeros(nsc,1);
     14 +y(ind) = hestRaw;
     15 +y0(ind) = 1;
     16 + 
     17 +% Get the filter length
     18 +len = floor(length(w)/2);
     19 + 
     20 +% Filter both raw estimates and the indicators
     21 +[z1, z1f] = filter(w,1,y);
     22 +z1 = [z1(len+1:end); z1f(1:len)];
     23 +[z0, z0f] = filter(w,1,y0);
     24 +z0 = [z0(len+1:end); z0f(1:len)];
     25 + 
     26 +% Compute the channel estimate
     27 +hest = z1./max(1e-8,z0);
     28 +end
     29 + 
     30 + 
  • ■ ■ ■ ■ ■ ■
    unit07_chanest/lab_partial/FDChan.m
     1 +classdef FDChan < matlab.System
     2 + % Frequency-domain multipath channel
     3 + properties
     4 + % Configuration
     5 + carrierConfig; % Carrier configuration
     6 + waveformConfig; % Waveform parameters
     7 +
     8 +
     9 + % Path parameters
     10 + gain; % Relative path gain in dB
     11 + dly; % Delay of each path in seconds
     12 + aoaAz, aoaEl; % Angle of arrival of each path in degrees
     13 + fd; % Doppler shift for each path
     14 +
     15 + rxVel = [30,0,0]'; % Mobile velocity vector in m/s
     16 + fc = 28e9; % Carrier freq in Hz
     17 +
     18 + gainComplex; % Complex gain of each path
     19 +
     20 + % SNR parameters
     21 + Etx = 1; % average energy per PDSCH symbol
     22 + EsN0Avg = 20; % Avg SNR per RX symbol in dB
     23 +
     24 + % Symbol times
     25 + symStart; % symStart(i) = start of symbol i relative to subframe
     26 +
     27 + end
     28 + methods
     29 + function obj = FDChan(carrierConfig, varargin)
     30 + % Constructor
     31 +
     32 + % Save the carrier configuration
     33 + obj.carrierConfig = carrierConfig;
     34 +
     35 + % Set parameters from constructor arguments
     36 + if nargin >= 1
     37 + obj.set(varargin{:});
     38 + end
     39 +
     40 + % Complex gain for each path using a random initial phase
     41 + % The gains are normalized to an average of one
     42 + npath = length(obj.gain);
     43 + phase = 2*pi*rand(npath, 1);
     44 + obj.gainComplex = db2mag(obj.gain).*exp(1i*phase);
     45 + obj.gainComplex = obj.gainComplex / norm(obj.gainComplex);
     46 +
     47 +
     48 + % Symbol times relative to the start of the subframe
     49 + obj.waveformConfig = nrOFDMInfo(obj.carrierConfig);
     50 + nsym = obj.waveformConfig.SymbolLengths;
     51 + obj.symStart = nsym/obj.waveformConfig.SampleRate;
     52 + obj.symStart = cumsum([0 obj.symStart]');
     53 +
     54 + % Compute unit vector in direction of each path
     55 + [ux, uy, uz] = sph2cart(deg2rad(obj.aoaAz), deg2rad(obj.aoaEl), 1);
     56 +
     57 + % Get Doppler shift
     58 + vc = physconst('Lightspeed');
     59 + obj.fd = [ux uy uz]*obj.rxVel*obj.fc/vc;
     60 +
     61 + end
     62 +
     63 +
     64 + end
     65 + methods (Access = protected)
     66 +
     67 +
     68 + function [rxGrid, chanGrid, noiseVar] = stepImpl(obj, txGrid, frameNum, slotNum)
     69 + % Applies a frequency domain channel and noise
     70 + %
     71 + % Parameters
     72 + % ----------
     73 + % txGrid: The OFDM grid of TX symbols for one slot
     74 + % frameNum: The index of the frame (1 frame = 10ms)
     75 + % slotNum: The index of the slot in the frame
     76 + % This should be 0,...,waveformConfig.SlotsPerFrame
     77 + %
     78 + % Outputs
     79 + % -------
     80 + % rxGrid: RX grid of RX symbols for one slot
     81 + % chanGrid: Grid of the channel values
     82 + % noiseVar: Noise variance
     83 +
     84 + % Get dimensions of the TX grid
     85 + [nsc, nsym] = size(txGrid);
     86 +
     87 + % Compute the frequency of each carrier
     88 + f = (0:nsc-1)'*obj.carrierConfig.SubcarrierSpacing*1e3;
     89 +
     90 + % Compute slot in sub-frame and sub-frame index
     91 + sfNum = floor(slotNum / obj.waveformConfig.SlotsPerSubframe);
     92 + slotNum1 = mod(slotNum, obj.waveformConfig.SlotsPerSubframe);
     93 +
     94 + % Compute the time for each symbol
     95 + framePeriod = 0.01;
     96 + sfPeriod = 1e-3;
     97 + t = frameNum*framePeriod + sfPeriod*sfNum + ...
     98 + obj.symStart(slotNum1+1:slotNum1+nsym);
     99 +
     100 + % Generate the channel
     101 + chanGrid = zeros(nsc, nsym);
     102 + npath = length(obj.gain);
     103 + for i = 1:npath
     104 + phase = 2*pi*(f*obj.dly(i) + t'*obj.fd(i));
     105 + chanGrid = chanGrid + obj.gainComplex(i)*exp(1i*phase);
     106 + end
     107 +
     108 + % Compute noise variance
     109 + Erx = sum(abs(obj.gainComplex).^2,'all')*obj.Etx;
     110 + noiseVar = Erx * db2pow(-obj.EsN0Avg);
     111 +
     112 + % Apply channel
     113 + rxGrid = chanGrid.*txGrid;
     114 +
     115 + % Add noise
     116 + w = (randn(nsc,nsym) + 1i*randn(nsc,nsym))*sqrt(noiseVar/2);
     117 + rxGrid = rxGrid + w;
     118 +
     119 + end
     120 +
     121 + end
     122 +end
     123 + 
     124 + 
  • ■ ■ ■ ■ ■ ■
    unit07_chanest/lab_partial/NRUERxFD.m
     1 +classdef NRUERxFD < matlab.System
     2 + % 5G NR UR receiver class implemented in frequency domain
     3 + properties
     4 + % Configuration
     5 + carrierConfig; % Carrier configuration
     6 + pdschConfig; % Default PDSCH config
     7 + waveformConfig; % Waveform config
     8 +
     9 + % OFDM grid
     10 + rxGrid;
     11 +
     12 + % Channel estimation parameters
     13 + sigFreq = 7; % Channel smoothing in freq
     14 + sigTime = 3; % Channel smoothing in time
     15 + lenFreq = 21; % Filter length in freq
     16 + Wtime;
     17 +
     18 + % Test bit parameters
     19 + bitsPerSym = 2;
     20 +
     21 + % Channel and noise estimate
     22 + chanEstGrid;
     23 + noiseEst;
     24 +
     25 + % RX symbols and estimated channel on the PDSCH
     26 + pdschChan;
     27 + pdschSym;
     28 +
     29 +
     30 + % Received data in last slots
     31 + pdschSymEq; % Equalized PDSCH symbols
     32 + rxBits; % RX bits
     33 +
     34 + end
     35 + methods
     36 + function obj = NRUERxFD(carrierConfig, pdschConfig, ...
     37 + varargin)
     38 + % Constructor
     39 +
     40 + % Save the carrier and PDSCH configuration
     41 + obj.carrierConfig = carrierConfig;
     42 + obj.pdschConfig = pdschConfig;
     43 +
     44 + % Create the waveform configuration from the carrier
     45 + % configuration
     46 + obj.waveformConfig = nrOFDMInfo(obj.carrierConfig);
     47 +
     48 + % Set parameters from constructor arguments
     49 + if nargin >= 1
     50 + obj.set(varargin{:});
     51 + end
     52 +
     53 +
     54 + end
     55 +
     56 + function chanEst(obj, rxGrid)
     57 + % Computes the channel estimate
     58 +
     59 + % TODO: Get the TX DM-RS symbols and indices
     60 + % dmrsSymTx = ...
     61 + % dmrsInd = ...
     62 +
     63 + % TODO: Get RX symbols on the DM-RS
     64 + % dmrsSymRx = ...
     65 +
     66 + % TODO: Get the raw channel estimate
     67 + % chanEstRaw = ...
     68 +
     69 + % Get the symbol numbers and sub-carrier indices of the
     70 + % DM-RS symbols from the DM-RS
     71 + % dmrsSymNum(i) = symbol number for the i-th DM-RS symbol
     72 + % dmrsScInd(i) = sub-carrier index for the i-th DM-RS symbol
     73 +
     74 + % TODO: Get the list of all symbol numbers on which DM-RS was
     75 + % transmitted. You can use the unique command
     76 + % dmrsSymNums = unique(...);
     77 + % ndrmsSym = length(dmrsSymNums);
     78 + 
     79 + % We first compute the channel and noise
     80 + % estimate on each of the symbols on which the DM-RS was
     81 + % transmitted. We will store these in two arrays
     82 + % chanEstDmrs(k,i) = chan est on sub-carrier k in DM-RS
     83 + % symbol i
     84 + % noiseEstDmrs(i) = noise est for DM-RS symbol i
     85 + chanEstDmrs = zeros(nsc, ndrmsSym);
     86 + noiseEstDmrs = zeros(ndrmsSym, 1);
     87 +
     88 + % Loop over the DM-RS symbols
     89 + for i = 1:ndrmsSym
     90 +
     91 + % TODO: Find the indices, k, in which the DM-RS
     92 + % dmrsSymNum(k)= dmrsSymNum(i).
     93 + % I = find(...)
     94 +
     95 + % TODO: Get the sub-carrier indices and raw channel
     96 + % channel estimate for these RS on the symbol
     97 + % ind = ...
     98 + % raw = ...
     99 +
     100 + % TODO: Use kernelReg to compute the channel estimate
     101 + % on that DM-RS symbol. Use the lenFreq and sigFreq
     102 + % for the kernel length and sigma.
     103 + % chanEstDmrs(:,i) = kernelReg(...)
     104 +
     105 + % TODO: Compute the noise estimate on the symbol
     106 + % using the residual method
     107 + % noiseEstDmrs(i) = ...
     108 +
     109 + end
     110 +
     111 + % TODO: Find the noise estimate over the PDSCH by
     112 + % averaging noiseEstDmrs
     113 + % obj.noiseEst = mean(...);
     114 +
     115 + % TODO: Finally, we interpolate over time.
     116 + % We will use an estimate of the form
     117 + % obj.chaneEstGrid = chanEstDrms*W
     118 + % so that
     119 + % chanEstGrid(k,j) = \sum_i chanEstDmrs(k,i)*W(i,j)
     120 + %
     121 + % We use a kernel estimator
     122 + %
     123 + % W(i,j) = W0(i,j) / \sum_k W0(k,j)
     124 + % W0(k,j) = exp(-D(k,j)^2/(2*obj.sigTime^2))
     125 + % D(k,j) = dmrsSymNum(k) - j
     126 + %
     127 +
     128 + % Save the time interpolation matrix
     129 + obj.Wtime = W;
     130 +
     131 + % Create the channel estimate grid
     132 + obj.chanEstGrid = chanEstDmrs*W;
     133 +
     134 + end
     135 + end
     136 + methods (Access = protected)
     137 +
     138 +
     139 + function rxBits = stepImpl(obj, rxGrid, chanGrid, noiseVar)
     140 + % Performs channel estimation, equalization and
     141 + % symbol demodulation for one slot of data.
     142 + %
     143 + % Input
     144 + % -----
     145 + % rxGrid: Received symbols in one slot
     146 + % chanGrid: Optional true channel estimate.
     147 + % noiseVar: Optional true noise variance
     148 + %
     149 + % If (chanGrid, noiseVar) are supplied the function skips
     150 + % the channel estimate. This is useful for testing a true
     151 + % channel estimate without channel estimation error.
     152 +
     153 + if nargin >= 3
     154 + % Set the estimated channel and noise to the supplied
     155 + % values if provided.
     156 + obj.chanEstGrid = chanGrid;
     157 + obj.noiseEst = noiseVar;
     158 + else
     159 +
     160 + % Compute the channel and noise estimate
     161 + obj.chanEst(rxGrid);
     162 + end
     163 + 
     164 + % Get indices on where the PDSCH is allocated
     165 + pdschInd = nrPDSCHIndices(obj.carrierConfig, obj.pdschConfig);
     166 +
     167 + % TODO: Get the PDSCH symbols and channel on the indicies
     168 + % obj.pdschSym = ...
     169 + % obj.pdschChan = ...
     170 +
     171 + % TODO: Perform the MMSE equalization
     172 + % obj.pdschSymEq
     173 +
     174 + % Demodulate the symbols
     175 + M = 2^obj.bitsPerSym;
     176 + rxBits = qamdemod(obj.pdschSymEq, M, 'OutputType', 'bit',...
     177 + 'UnitAveragePower', true);
     178 + end
     179 +
     180 + end
     181 +end
     182 + 
     183 + 
  • ■ ■ ■ ■ ■ ■
    unit07_chanest/lab_partial/NRgNBTxFD.m
     1 +classdef NRgNBTxFD < matlab.System
     2 + % 5G NR gNB transmitter class implemented in frequency domain
     3 + properties
     4 + % Configuration
     5 + carrierConfig; % Carrier configuration
     6 + pdschConfig; % PDSCH configuration
     7 +
     8 + % Coded bits transmitted on PDSCH
     9 + txBits;
     10 +
     11 + % Transmitted symbols
     12 + pdschSym;
     13 +
     14 + % Modulation parameters for test
     15 + bitsPerSym = 2;
     16 +
     17 + % Channel
     18 + txGridChan;
     19 + chanNames;
     20 +
     21 +
     22 + end
     23 + methods
     24 + function obj = NRgNBTxFD(carrierConfig, pdschConfig, ...
     25 + varargin)
     26 + % Constructor
     27 +
     28 + % Save the carrier and PDSCH configuration
     29 + obj.carrierConfig = carrierConfig;
     30 + obj.pdschConfig = pdschConfig;
     31 +
     32 + % Set parameters from constructor arguments
     33 + if nargin >= 1
     34 + obj.set(varargin{:});
     35 + end
     36 +
     37 +
     38 + end
     39 +
     40 + function setAck(obj, iharq)
     41 + % Set that the HARQ transmission was received correctly
     42 + obj.newDataAvail(iharq) = 1;
     43 +
     44 + end
     45 + end
     46 + methods (Access = protected)
     47 +
     48 + function [txGrid] = stepImpl(obj)
     49 + % step implementation. Creates one slot of samples for each
     50 + % component carrier
     51 +
     52 +
     53 + % Create the OFDM grid representing the array of modulation
     54 + % symbols to be transmitted
     55 + txGrid = nrResourceGrid(obj.carrierConfig, ...
     56 + obj.pdschConfig.NumLayers);
     57 +
     58 + % TODO: Get indices on where the PDSCH is allocated
     59 + % pdschInd = nrPDSCHIndices(...);
     60 +
     61 +
     62 + % TODO: Create random bits for the PDSCH
     63 + % and modulate the bits to symbols.
     64 + % Use obj.bitsPerSym to determine the modulation order
     65 + % obj.txBits = ...
     66 + % obj.pdschSym = qammod(...);
     67 +
     68 + % Insert the PDSCH symbols into the TX grid
     69 + txGrid(pdschInd) = obj.pdschSym;
     70 +
     71 + % Get the PT-RS symbols and indices and insert them
     72 + % in the TX grid
     73 + ptrsSym = nrPDSCHPTRS(obj.carrierConfig, obj.pdschConfig);
     74 + ptrsInd = nrPDSCHPTRSIndices(obj.carrierConfig, obj.pdschConfig);
     75 + txGrid(ptrsInd) = ptrsSym;
     76 + 
     77 + % TODO: Get the DM-R indices and symbols and insert them
     78 + % in the TX grid
     79 + % dmrsSym = ...
     80 + % dmrsInd = ...
     81 + % txGrid(dmrsInd) = ...
     82 +
     83 + % For debugging, we create a grid with the labels for
     84 + % the channel indices
     85 + numPorts = 1;
     86 + obj.txGridChan = nrResourceGrid(obj.carrierConfig, numPorts);
     87 + obj.txGridChan(pdschInd) = 1;
     88 + obj.txGridChan(dmrsInd) = 2;
     89 + obj.txGridChan(ptrsInd) = 3;
     90 + obj.chanNames = {'Other', 'PDSCH', 'DM-RS', 'PT-RS'};
     91 +
     92 + end
     93 +
     94 +
     95 +
     96 + end
     97 +end
     98 + 
     99 + 
  • ■ ■ ■ ■ ■ ■
    unit07_chanest/lab_partial/kernelReg.m
     1 +function [hest, w] = kernelReg(ind,hestRaw,nsc,len,sig)
     2 +% kernelReg: Kernel regression with a RBF
     3 + 
     4 +% Create the RBF kernel
     5 +w = exp(-0.5*(-len:len).^2/sig^2)';
     6 + 
     7 +% Place the raw channel esimates in a vector at the locations
     8 +% of the indices.
     9 +% y(ind(i)) = hestRaw(i)
     10 +% y0(ind(i)) = 1
     11 +y = zeros(nsc,1);
     12 +y0 = zeros(nsc,1);
     13 +y(ind) = hestRaw;
     14 +y0(ind) = 1;
     15 + 
     16 +% Get the filter length
     17 +len = floor(length(w)/2);
     18 + 
     19 +% Filter both raw estimates and the indicators
     20 +[z1, z1f] = filter(w,1,y);
     21 +z1 = [z1(len+1:end); z1f(1:len)];
     22 +[z0, z0f] = filter(w,1,y0);
     23 +z0 = [z0(len+1:end); z0f(1:len)];
     24 + 
     25 +% Compute the channel estimate
     26 +hest = z1./max(1e-8,z0);
     27 +end
     28 + 
     29 + 
  • unit07_chanest/lab_partial/labChanEst.mlx
    Binary file.
  • unit07_chanest/lab_partial/labChanEst.pdf
    Binary file.
  • ■ ■ ■ ■ ■ ■
    unit07_chanest/lab_partial/plotChan.m
     1 +function plotChan(grid, labels, varargin)
     2 + 
     3 + % Plot the grid
     4 + nchan = length(labels);
     5 + imagesc(grid, [0 nchan-1]);
     6 + hold on;
     7 + 
     8 + % Plot a dummy rectangle for each color
     9 + nchan = length(labels);
     10 + colorArr = parula(nchan);
     11 + for i = 1:nchan
     12 + fill([1,1],[1,1], colorArr(i,:), 'DisplayName', labels{i});
     13 +
     14 + end
     15 + hold off;
     16 + 
     17 + 
     18 + % Create the legend
     19 + legend();
     20 + 
     21 +end
  • ■ ■ ■ ■ ■ ■
    unit07_chanest/plotChan.m
     1 +function plotChan(grid, labels, varargin)
     2 + 
     3 + % Plot the grid
     4 + nchan = length(labels);
     5 + imagesc(grid, [0 nchan-1]);
     6 + hold on;
     7 + 
     8 + % Plot a dummy rectangle for each color
     9 + nchan = length(labels);
     10 + colorArr = parula(nchan);
     11 + for i = 1:nchan
     12 + fill([1,1],[1,1], colorArr(i,:), 'DisplayName', labels{i});
     13 +
     14 + end
     15 + hold off;
     16 + 
     17 + 
     18 + % Create the legend
     19 + legend();
     20 + 
     21 +end
Please wait...
Page is in error, reload to recover