■ ■ ■ ■ ■ ■
unit04_coding/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 | + | |
| 24 | + | end |
| 25 | + | methods |
| 26 | + | function obj = NRUERxFD(carrierConfig, pdschConfig, ... |
| 27 | + | varargin) |
| 28 | + | % Constructor |
| 29 | + | |
| 30 | + | % Save the carrier and PDSCH configuration |
| 31 | + | obj.carrierConfig = carrierConfig; |
| 32 | + | obj.pdschConfig = pdschConfig; |
| 33 | + | |
| 34 | + | % Create the waveform configuration from the carrier |
| 35 | + | % configuration |
| 36 | + | obj.waveformConfig = nrOFDMInfo(obj.carrierConfig); |
| 37 | + | |
| 38 | + | % Set parameters from constructor arguments |
| 39 | + | if nargin >= 1 |
| 40 | + | obj.set(varargin{:}); |
| 41 | + | end |
| 42 | + | |
| 43 | + | % Create DLSCH decoder |
| 44 | + | obj.decDLSCH = nrDLSCHDecoder('MultipleHARQProcesses', false, ... |
| 45 | + | 'TargetCodeRate', obj.targetCodeRate, ... |
| 46 | + | 'LDPCDecodingAlgorithm', 'Layered belief propagation'); |
| 47 | + | |
| 48 | + | end |
| 49 | + | end |
| 50 | + | methods (Access = protected) |
| 51 | + | |
| 52 | + | |
| 53 | + | function stepImpl(obj, rxGrid, chanGrid, noiseVar) |
| 54 | + | % Demodulates and decodes one slot of data |
| 55 | + | |
| 56 | + | % Get PDSCH received symbols and channel estimates |
| 57 | + | % from received grid |
| 58 | + | [pdschInd,pdschInfo] = nrPDSCHIndices(... |
| 59 | + | obj.carrierConfig, obj.pdschConfig); |
| 60 | + | [pdschRx, pdschHest] = nrExtractResources(pdschInd, rxGrid,... |
| 61 | + | chanGrid); |
| 62 | + | |
| 63 | + | % TODO: Perform the MMSE equalization using the |
| 64 | + | % nrEqualizeMMSE() function. |
| 65 | + | % Use the PDSCH Rx symbols, PDSCH channel estimate and noise |
| 66 | + | % variance as the input. Store the equalized symbols in |
| 67 | + | % obj.pdschEq and channel state information in a structure, |
| 68 | + | % csi. |
| 69 | + | % [obj.pdschEq,csi] = nrEqualizeMMSE(...); |
| 70 | + | |
| 71 | + | |
| 72 | + | % TODO: Get the LLRs with the nrPDSCHDecode() function. |
| 73 | + | % Use carrier and PDSCH configuration, the equalized symbols, |
| 74 | + | % and the noise variance, noiseVar. |
| 75 | + | % [obj.pdschEq,csi] = nrEqualizeMMSE(...); |
| 76 | + | |
| 77 | + | % Scale LLRs by EbN0. |
| 78 | + | % The csi value computed in the nrEqualizeMMSE() |
| 79 | + | % function is csi = |pdschHest|^2 + noiseVar. |
| 80 | + | % Also, the Eb/N0 = snrEq/Qm where Qm is the number of bits |
| 81 | + | % per symbol and snrEq is the SNR after equalization, |
| 82 | + | % |
| 83 | + | % snrEq = (|pdschHest|^2 + noiseVar)/noiseVar = csi/noiseVar |
| 84 | + | % |
| 85 | + | % Hence, Eb/N0 = csi/(noiseVar*Qm). |
| 86 | + | % Since the LLRs from the nrPDSCHDecode function are |
| 87 | + | % already scaled by 1/noiseVar, we multiply them by csi/Qm. |
| 88 | + | csi = nrLayerDemap(csi); % CSI layer demapping |
| 89 | + | numCW = length(csi); |
| 90 | + | for cwIdx = 1:numCW |
| 91 | + | Qm = length(dlschLLRs{cwIdx})/length(rxSym{cwIdx}); % bits per symbol |
| 92 | + | csi{cwIdx} = repmat(csi{cwIdx}.',Qm,1); % expand by each bit per symbol |
| 93 | + | dlschLLRs{cwIdx} = dlschLLRs{cwIdx} .* csi{cwIdx}(:); % scale |
| 94 | + | end |
| 95 | + | |
| 96 | + | % Compute the extra overhead from the PT-RS |
| 97 | + | Xoh_PDSCH = 6*obj.pdschConfig.EnablePTRS; |
| 98 | + | |
| 99 | + | % Calculate the transport block size based on the PDSCH |
| 100 | + | % allocation and target code rate |
| 101 | + | obj.trBlkSizes = nrTBS(obj.pdschConfig.Modulation,obj.pdschConfig.NumLayers,... |
| 102 | + | numel(obj.pdschConfig.PRBSet),pdschInfo.NREPerPRB,... |
| 103 | + | obj.targetCodeRate,Xoh_PDSCH); |
| 104 | + | obj.decDLSCH.TransportBlockLength = obj.trBlkSizes; |
| 105 | + | |
| 106 | + | % Reset the soft buffer |
| 107 | + | harqId = 0; |
| 108 | + | obj.decDLSCH.resetSoftBuffer(harqId); |
| 109 | + | |
| 110 | + | % TODO: Decode the bits with the obj.decDLSCH() method. |
| 111 | + | % Use the scaled LLRs from above. Use a redundancy version, |
| 112 | + | % rv = 0, since we are not using HARQ in this lab. |
| 113 | + | % rv = 0; |
| 114 | + | % obj.rxBit = obj.decDLSCH(...); |
| 115 | + | |
| 116 | + | end |
| 117 | + | |
| 118 | + | end |
| 119 | + | end |
| 120 | + | |
| 121 | + | |