Projects STRLCPY wirelesscomm Commits ee83fac8
🤬
Revision indexing in progress... (symbol navigation in revisions will be accurate after indexed)
  • lectures/Unit04_Coding.pptx
    Binary file.
  • lectures/Unit05_AMC.pdf
    Binary file.
  • lectures/Unit05_AMC.pptx
    Binary file.
  • ■ ■ ■ ■ ■ ■
    unit05_amc/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 + 
  • unit05_amc/amc_inclass.mlx
    Binary file.
  • unit05_amc/amc_inclass.pdf
    Binary file.
  • unit05_amc/amc_inclass_soln.mlx
    Binary file.
  • unit05_amc/amc_inclass_soln.pdf
    Binary file.
  • unit05_amc/demo_csirs.mlx
    Binary file.
  • unit05_amc/demo_csirs.pdf
    Binary file.
  • unit05_amc/demo_csirs_soln.mlx
    Binary file.
  • unit05_amc/demo_csirs_soln.pdf
    Binary file.
  • unit05_amc/demo_mcs.mlx
    Binary file.
  • unit05_amc/demo_mcs.pdf
    Binary file.
  • unit05_amc/demo_mcs_soln.mlx
    Binary file.
  • unit05_amc/demo_mcs_soln.pdf
    Binary file.
  • ■ ■ ■ ■ ■ ■
    unit05_amc/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 + % Path parameters
     9 + gain; % Relative path gain in dB
     10 + dly; % Delay of each path in seconds
     11 + aoaAz, aoaEl; % Angle of arrival of each path in degrees
     12 + fd; % Doppler shift for each path
     13 +
     14 + rxVel = [30,0,0]'; % Mobile velocity vector in m/s
     15 + fc = 28e9; % Carrier freq in Hz
     16 +
     17 + gainComplex; % Complex gain of each path
     18 +
     19 + % SNR parameters
     20 + Etx = 1; % average energy per PDSCH symbol
     21 + EsN0Avg = 20; % Avg SNR per RX symbol in dB
     22 +
     23 + % Symbol times
     24 + symStart; % symStart(i) = start of symbol i relative to subframe
     25 +
     26 + end
     27 + methods
     28 + function obj = FDChan(carrierConfig, varargin)
     29 + % Constructor
     30 +
     31 + % Save the carrier configuration
     32 + obj.carrierConfig = carrierConfig;
     33 + 
     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 + 
  • ■ ■ ■ ■ ■ ■
    unit05_amc/lab_partial/HARQProcess.m
     1 +classdef HARQProcess
     2 + %HARQPROCESS Summary of this class goes here
     3 + % Detailed explanation goes here
     4 +
     5 + properties
     6 + Property1
     7 + end
     8 +
     9 + methods
     10 + function obj = HARQProcess(inputArg1,inputArg2)
     11 + %HARQPROCESS Construct an instance of this class
     12 + % Detailed explanation goes here
     13 + obj.Property1 = inputArg1 + inputArg2;
     14 + end
     15 +
     16 + function outputArg = method1(obj,inputArg)
     17 + %METHOD1 Summary of this method goes here
     18 + % Detailed explanation goes here
     19 + outputArg = obj.Property1 + inputArg;
     20 + end
     21 + end
     22 +end
     23 + 
     24 + 
  • ■ ■ ■ ■ ■ ■
    unit05_amc/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 + % Transport block data for last transmission
     13 + targetCodeRate = 490/1024; % Target code rate
     14 + trBlkSizes; % Transport block size
     15 +
     16 + % Received data in last slots
     17 + pdschEq; % Equalized PDSCH symbols
     18 + rxBits; % RX bits
     19 +
     20 + % DLSCH decoder
     21 + decDLSCH;
     22 +
     23 + % HARQ Process
     24 + nharq = 8; % number of HARQ processes
     25 +
     26 + % RV sequence. This is the sequence that the TX will cycle
     27 + % through in the RVs
     28 + rvSeq = [0,3,2,1]';
     29 + 
     30 + % TX parameters per HARQ process
     31 + TBId; % ID of the last TX packet
     32 + rvInd; % Index of the RV for the current transmission
     33 + newDataAvail; % If HARQ process can take new data
     34 + txBits; % Cell array of TX bits
     35 +
     36 +
     37 + end
     38 + methods
     39 + function obj = NRUERxFD(carrierConfig, pdschConfig, ...
     40 + varargin)
     41 + % Constructor
     42 +
     43 + % Save the carrier and PDSCH configuration
     44 + obj.carrierConfig = carrierConfig;
     45 + obj.pdschConfig = pdschConfig;
     46 +
     47 + % Create the waveform configuration from the carrier
     48 + % configuration
     49 + obj.waveformConfig = nrOFDMInfo(obj.carrierConfig);
     50 +
     51 + % Set parameters from constructor arguments
     52 + if nargin >= 1
     53 + obj.set(varargin{:});
     54 + end
     55 +
     56 + % Create DLSCH decoder
     57 + obj.decDLSCH = nrDLSCHDecoder('MultipleHARQProcesses', true, ...
     58 + 'TargetCodeRate', obj.targetCodeRate, ...
     59 + 'LDPCDecodingAlgorithm', 'Layered belief propagation');
     60 +
     61 + end
     62 + end
     63 + methods (Access = protected)
     64 +
     65 +
     66 + function stepImpl(obj, rxGrid, chanGrid, noiseVar, ...
     67 + iharq, rv, newDat)
     68 + % Demodulates and decodes one slot of data
     69 + %
     70 + % Parameters
     71 + % ----------
     72 + % iharq: HARQ process ID
     73 + % rv: Rendundancy version
     74 + % newData: If data is new
     75 + %
     76 + % Note that the last three parameters would normally be
     77 + % sent on the PDCCH
     78 +
     79 +
     80 + % Get PDSCH received symbols and channel estimates
     81 + % from received grid
     82 + [pdschInd,pdschInfo] = nrPDSCHIndices(...
     83 + obj.carrierConfig, obj.pdschConfig);
     84 + [pdschRx, pdschHest] = nrExtractResources(pdschInd, rxGrid,...
     85 + chanGrid);
     86 +
     87 + % Perform the MMSE equalization using the
     88 + % nrEqualizeMMSE() function
     89 + [obj.pdschEq,csi] = nrEqualizeMMSE(pdschRx,pdschHest,noiseVar);
     90 +
     91 +
     92 + % TODO: Get the LLRs with the nrPDSCHDecode() function.
     93 + % Use carrier and PDSCH configuration, the equalized symbols,
     94 + % and the noise variance, noiseVar.
     95 + % [dlschLLRs, rxSym] = nrPDSCHDecode(...);
     96 +
     97 + % Scale LLRs by EbN0.
     98 + % The csi value computed in the nrEqualizeMMSE()
     99 + % function is csi = |pdschHest|^2 + noiseVar.
     100 + % Also, the Eb/N0 = snrEq/Qm where Qm is the number of bits
     101 + % per symbol and snrEq is the SNR after equalization,
     102 + %
     103 + % snrEq = (|pdschHest|^2 + noiseVar)/noiseVar = csi/noiseVar
     104 + %
     105 + % Hence, Eb/N0 = csi/(noiseVar*Qm).
     106 + % Since the LLRs from the nrPDSCHDecode function are
     107 + % already scaled by 1/noiseVar, we multiply them by csi/Qm.
     108 + csi = nrLayerDemap(csi); % CSI layer demapping
     109 + numCW = length(csi);
     110 + for cwIdx = 1:numCW
     111 + Qm = length(dlschLLRs{cwIdx})/length(rxSym{cwIdx}); % bits per symbol
     112 + csi{cwIdx} = repmat(csi{cwIdx}.',Qm,1); % expand by each bit per symbol
     113 + dlschLLRs{cwIdx} = dlschLLRs{cwIdx} .* csi{cwIdx}(:); % scale
     114 + end
     115 +
     116 + % Compute the extra overhead from the PT-RS
     117 + Xoh_PDSCH = 6*obj.pdschConfig.EnablePTRS;
     118 +
     119 + % Calculate the transport block size based on the PDSCH
     120 + % allocation and target code rate
     121 + obj.trBlkSizes = nrTBS(obj.pdschConfig.Modulation,obj.pdschConfig.NumLayers,...
     122 + numel(obj.pdschConfig.PRBSet),pdschInfo.NREPerPRB,...
     123 + obj.targetCodeRate,Xoh_PDSCH);
     124 + obj.decDLSCH.TransportBlockLength = obj.trBlkSizes;
     125 +
     126 + % Reset the soft buffer for all codewords
     127 + if newDat
     128 + for cwIdx = 1:numCW
     129 + obj.decDLSCH.resetSoftBuffer(cwIdx, iharq-1);
     130 + end
     131 + end
     132 +
     133 + % TODO: Decode the bits with the obj.decDLSCH() method.
     134 + % Use the scaled LLRs from above.
     135 +
     136 + end
     137 +
     138 + end
     139 +end
     140 + 
     141 + 
  • ■ ■ ■ ■ ■ ■
    unit05_amc/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 + % Transport block data for last transmission
     9 + targetCodeRate = 490/1024; % Target code rate
     10 + trBlkSizes; % Transport block size
     11 +
     12 + % DLSCH encoder
     13 + encDLSCH;
     14 +
     15 + % HARQ Process
     16 + nharq = 8; % number of HARQ processes
     17 +
     18 + % RV sequence. This is the sequence that the TX will cycle
     19 + % through in the RVs
     20 + rvSeq = [0,3,2,1]';
     21 + 
     22 + % TX parameters per HARQ process
     23 + rvInd; % Index of the RV for the current transmission
     24 + newDataAvail; % If HARQ process can take new data
     25 + txBits; % Cell array of TX bits
     26 +
     27 + end
     28 + methods
     29 + function obj = NRgNBTxFD(carrierConfig, pdschConfig, ...
     30 + varargin)
     31 + % Constructor
     32 +
     33 + % Save the carrier and PDSCH configuration
     34 + obj.carrierConfig = carrierConfig;
     35 + obj.pdschConfig = pdschConfig;
     36 +
     37 + % Set parameters from constructor arguments
     38 + if nargin >= 1
     39 + obj.set(varargin{:});
     40 + end
     41 +
     42 + % Create DLSCH encoder system object
     43 + obj.encDLSCH = nrDLSCH('MultipleHARQProcesses', true, ...
     44 + 'TargetCodeRate', obj.targetCodeRate);
     45 +
     46 + % Initialize the HARQ process parameters
     47 + obj.rvInd = zeros(obj.nharq, 1);
     48 + obj.newDataAvail = ones(obj.nharq,1);
     49 +
     50 + % TX bits for each HARQ process
     51 + obj.txBits = cell(obj.nharq,1);
     52 +
     53 +
     54 + end
     55 +
     56 + function setAck(obj, iharq)
     57 + % Set that the HARQ transmission was received correctly
     58 + obj.newDataAvail(iharq) = 1;
     59 +
     60 + end
     61 + end
     62 + methods (Access = protected)
     63 +
     64 + function [txGrid, rv, newDat] = stepImpl(obj, iharq)
     65 + % step implementation. Creates one slot of samples for each
     66 + % component carrier
     67 + %
     68 + % Parameters
     69 + % ----------
     70 + % iharq: HARQ process index to use
     71 + %
     72 + % Returns:
     73 + % --------
     74 + % txGrid: OFDM grid of transmitted symbols
     75 + % rv: Redundancy version for the data
     76 + % newDat: If new data was transmitted in this slot
     77 +
     78 +
     79 + % Create the OFDM grid representing the array of modulation
     80 + % symbols to be transmitted
     81 + txGrid = nrResourceGrid(obj.carrierConfig, ...
     82 + obj.pdschConfig.NumLayers);
     83 +
     84 +
     85 + % Get indices on where the PDSCH is allocated
     86 + [pdschInd,pdschInfo] = nrPDSCHIndices(obj.carrierConfig, obj.pdschConfig);
     87 +
     88 +
     89 + if obj.newDataAvail(iharq)
     90 + % If new data can be transmitted in the HARQ process
     91 +
     92 + % Compute the extra overhead from the PT-RS
     93 + Xoh_PDSCH = 6*obj.pdschConfig.EnablePTRS;
     94 + 
     95 + % Calculate the transport block size based on the PDSCH
     96 + % allocation and target code rate
     97 + obj.trBlkSizes = nrTBS(obj.pdschConfig.Modulation,obj.pdschConfig.NumLayers,...
     98 + numel(obj.pdschConfig.PRBSet),pdschInfo.NREPerPRB,...
     99 + obj.targetCodeRate,Xoh_PDSCH);
     100 + 
     101 + % Generate random bits for each codeword and set the transport
     102 + % block
     103 + obj.txBits{iharq} = cell(obj.pdschConfig.NumCodewords, 1);
     104 + for icw = 1:obj.pdschConfig.NumCodewords
     105 + 
     106 + % TODO: Create random bits for each codeword
     107 + % obj.txBits{iharq}{icw} = ...
     108 + 
     109 + % TODO: Set the transport block to be encoded
     110 + % obj.echDLSCH.setTransportBlock(...)
     111 + % You will need to pass the codeword index, icw-1,
     112 + % and HARQ process ID, iharq-1
     113 + end
     114 +
     115 + % Set the RV index to zero on the first transmission
     116 + obj.rvInd(iharq) = 0;
     117 +
     118 + % Clear new data flag
     119 + obj.newDataAvail(iharq) = 0;
     120 +
     121 + % Mark that the data
     122 + newDat = true;
     123 + else
     124 + % Mark that this data is a re-transmission
     125 + newDat = false;
     126 + end
     127 +
     128 + % TODO: Get the redundancy version from the current redundancy
     129 + % version index, obj.rvInd(iharq). The rv should be
     130 + % rv = obj.rvSeq(irv+1),
     131 + % where irv cycles, 0,1,2,3,0,1,2,3,...
     132 +
     133 + % Encode the DL-SCH transport block
     134 + codedTrBlock = obj.encDLSCH(obj.pdschConfig.Modulation, ...
     135 + obj.pdschConfig.NumLayers, pdschInfo.G, rv, iharq-1);
     136 +
     137 + % Increment the RV sequence
     138 + obj.rvInd(iharq) = obj.rvInd(iharq) + 1;
     139 +
     140 + % Modulate the PDSCH modulation
     141 + pdschSymbols = nrPDSCH(obj.carrierConfig, obj.pdschConfig, ...
     142 + codedTrBlock);
     143 +
     144 + % Map the modulated symbols to the OFDM grid
     145 + txGrid(pdschInd) = pdschSymbols;
     146 +
     147 + end
     148 +
     149 +
     150 +
     151 + end
     152 +end
     153 + 
     154 + 
  • unit05_amc/lab_partial/labHarq.mlx
    Binary file.
  • unit05_amc/lab_partial/labHarq.pdf
    Binary file.
  • ■ ■ ■ ■ ■ ■
    unit05_amc/plotChan.m
     1 +function plotChan(grid, labels, varargin)
     2 + 
     3 + % Plot the grid
     4 + imagesc(grid);
     5 +
     6 + if nargin == 2
     7 + hold on;
     8 + 
     9 + % Plot a dummy rectangle for each color
     10 + nchan = length(labels);
     11 + colorArr = parula(nchan);
     12 + for i = 1:nchan
     13 + fill([1,1],[1,1], colorArr(i,:), 'DisplayName', labels{i});
     14 + end
     15 + hold off;
     16 + 
     17 + % Create the legend
     18 + legend();
     19 + end
     20 +end
Please wait...
Page is in error, reload to recover