5G/NR - Pre Trial - Frame Structure - Matlab Code   

 

 

 

NOTE : This note is about a tempary 5G specification that was implemented and tried before 5G specification is finalized. I keep this note for study purpose.

Frame Structure - Matlab Code

 

Disclaimer : The code is ONLY for visualzing the resource element mapping for various physical channels defined in Pretrial specification. The resoure location would be accurate but the data assigned in the resource elements is just a dummy (meaningless) value. Also, there might be some errors in the code (or my mis-interpretation of the specification). Don't blame on me if there is any errors :). Play with the code and have fun.

Each section below matches a section of the Frame Structure page, which shows the plots that this code draws. So read the two pages side by side: the plot shows where a channel sits, and the code shows the index formula that puts it there.

Tips for Execution

The code on this page is split into small functions. Each channel section has one function that writes the channel into a subframe grid, and one Test script that draws it. Every function relies on the Common Library at the end of the page, so all the files have to sit in one folder. The steps below set that up.

The functions share one data structure. A subframe is a MATLAB struct with a Grid field, and every channel function takes a subframe, writes into its Grid and returns it. So you can call the functions in any order and stack several channels into one subframe, as TestFrame.m does.

    i) Create a folder where you want to store files (m files)

    ii) Create the files listed under Common Library Section store them in the folder created at step i).

    iii) Create other files as you like and store them in the folder created at step i).

After that, run TestFrame.m to draw the whole radio frame, or a single Test script such as TestPSS.m to draw one channel. One name needs attention. The scripts call PlotSubFrame, while the library file and its function are named PlotSubframe. MATLAB can report an inexact match or an undefined function for this, so rename one of them to match the other.

TestFrame

TestFrame.m builds a whole radio frame of 50 subframes and places every channel on this page into it. Keep in mind that MATLAB indexes arrays from 1, so radioframe(1) is subframe 0 and radioframe(26) is subframe 25.

Subframes 0 and 25 get PSS, SSS, ESS, xPBCH and BRS. Subframe 49 gets ePBCH and its DMRS, and subframe 26 gets BRRS on ports 600 to 607 in symbol 12. The other subframes get xREGs in symbols 0 and 1 with the xPDCCH DMRS of xREG 0, and PNRS for ports 60 and 61 in symbols 3 to 13. The script then draws the frame, and a zoom of subframe 0 between subcarrier 450 and 750.

 

Filename : TestFrame.m

Last Update : Dec 7, 2016

radioframe = [];

for i = 0:49

   radioframe = [radioframe CreateSubFrame(0,0,0)];

end;   

 

% Add PSS, SSS, ESS

sf = radioframe(1);

sf = SubFrame_AddPss(sf);

sf = SubFrame_AddSss(sf);

sf = SubFrame_AddEss(sf);

 

radioframe(1) = sf;

 

sf = radioframe(26);

sf = SubFrame_AddPss(sf);

sf = SubFrame_AddSss(sf);

sf = SubFrame_AddEss(sf);

radioframe(26) = sf;

 

% Add xPBCH

sf = radioframe(1);

xPBCH.N_DL_RB = 100;

xPBCH.N_RB_SC = 12;

 

xPBCH.Subblock = 'Even';

xPBCH.DummyValue = 0.7;

sf = SubFrame_Add_xPBCH_Subblock(sf,xPBCH);

 

xPBCH.Subblock = 'Odd';

xPBCH.DummyValue = 0.7;

sf = SubFrame_Add_xPBCH_Subblock(sf,xPBCH);

 

sf = radioframe(26);

xPBCH.N_DL_RB = 100;

xPBCH.N_RB_SC = 12;

 

xPBCH.Subblock = 'Even';

xPBCH.DummyValue = 0.7;

sf = SubFrame_Add_xPBCH_Subblock(sf,xPBCH);

 

xPBCH.Subblock = 'Odd';

xPBCH.DummyValue = 0.7;

sf = SubFrame_Add_xPBCH_Subblock(sf,xPBCH);

radioframe(1) = sf;

radioframe(26) = sf;

 

% Add BRS

sf = radioframe(1);

BRS.N_DL_RB = 100;

BRS.DummyValue = 0.2;

sf = SubFrame_AddBrs(sf,BRS);

radioframe(1) = sf;

 

sf = radioframe(26);

BRS.N_DL_RB = 100;

BRS.DummyValue = 0.2;

sf = SubFrame_AddBrs(sf,BRS);

radioframe(26) = sf;

 

% Add ePBCH

sf = radioframe(50);

 

ePBCH.N_DL_RB = 100;

 

ePBCH.DummyValue = 0.5;

sf = SubFrame_Add_ePBCH(sf,ePBCH);

 

ePBCH.AntennaPort = 500;

ePBCH.DummyValue = 0.3;

sf = SubFrame_Add_ePBCH_DMRS_Port(sf,ePBCH);

 

radioframe(50) = sf;

 

% Add BRRS

sf = radioframe(27);

BRRS.AntennaPort = 600;

BRRS.N_DL_RB = 100;

BRRS.N_RB_SC = 12;

BRRS.SymbolIndex = 12;

 

BRRS.DummyValue = 0.8;

sf = SubFrame_AddBrrs_Port(sf, BRRS);

 

BRRS.AntennaPort = 601;

BRRS.DummyValue = 0.8;

sf = SubFrame_AddBrrs_Port(sf, BRRS);

 

BRRS.AntennaPort = 602;

BRRS.DummyValue = 0.8;

sf = SubFrame_AddBrrs_Port(sf, BRRS);

 

BRRS.AntennaPort = 603;

BRRS.DummyValue = 0.8;

sf = SubFrame_AddBrrs_Port(sf, BRRS);

 

BRRS.AntennaPort = 604;

BRRS.DummyValue = 0.8;

sf = SubFrame_AddBrrs_Port(sf, BRRS);

 

BRRS.AntennaPort = 605;

BRRS.DummyValue = 0.8;

sf = SubFrame_AddBrrs_Port(sf, BRRS);

 

BRRS.AntennaPort = 606;

BRRS.DummyValue = 0.8;

sf = SubFrame_AddBrrs_Port(sf, BRRS);

 

BRRS.AntennaPort = 607;

BRRS.DummyValue = 0.8;

sf = SubFrame_AddBrrs_Port(sf, BRRS);

 

radioframe(27) = sf;

 

%Add xREG and xPDCCH DMRS

for i = [2:25 27:49]

    sf = radioframe(i);

    xREG.N_RB_SC = 12;

 

    xREG.DummyValue1 = 0.2;

    xREG.DummyValue2 = 0.5;

    xREG.Symbol = 0;

    sf = SubFrame_Add_xREG_Symbol(sf,xREG);

 

    xREG.DummyValue1 = 0.5;

    xREG.DummyValue2 = 0.2;

    xREG.Symbol = 1;

    sf = SubFrame_Add_xREG_Symbol(sf,xREG);

 

    xPDCCH.N_RB_SC = 12;

 

    xPDCCH.DummyValue = 0.7;

    xPDCCH.Symbol = 0;

    xPDCCH.n_xREG = 0;

    sf = SubFrame_Add_xPDCCH_DMRS_UE(sf,xPDCCH);

 

    radioframe(i) = sf;

end;

 

% Add PDSCH PNRS

for i = [2:25 27:49]

    sf = radioframe(i);

    xPDSCH.N_RB_SC = 12;

    xPDSCH.n_PRB_xPDSCH = 0;

    xPDSCH.N_PRB_xPDSCH = 4*25;

    xPDSCH.lp_first_xPDSCH = 3;

    xPDSCH.lp_last_xPDSCH = 13;

 

    xPDSCH.AntennaPort = 60;

    xPDSCH.DummyValue = 0.4;

    sf = SubFrame_Add_xPDSCH_PNRS_Port(sf,xPDSCH);

 

    xPDSCH.AntennaPort = 61;

    xPDSCH.DummyValue = 0.6;

    sf = SubFrame_Add_xPDSCH_PNRS_Port(sf,xPDSCH);

    radioframe(i) = sf;

end;

 

figure(1);

Option = 0;

PlotFrame(radioframe,Option)

 

figure(2);

sf = radioframe(1);

PlotSubFrame(sf,0,14,450,750);

 

PSS - Primary Synchronization Signal

SubFrame_AddPss.m places 62 PSS values on subcarriers k = n - 31 + 600, for n from 0 to 61, in all 14 symbols. With 100 RB, subcarrier 600 is the centre of the band, so the PSS sits on subcarriers 569 to 630. Every value is set to 1, because the code shows where the PSS goes, not the Zadoff-Chu sequence itself. TestPSS.m draws the result between subcarrier 450 and 750.

The comment at the top of the function points to V5G.211 clause 6.8.1.2, which is where the mapping formula comes from. To draw the real sequence instead of a flat value, replace the line d = 0 .* [0:61] + 1 with a vector of the 62 Zadoff-Chu values. The loop already takes d(n+1) for each subcarrier, so nothing else has to change.

 

Filename : SubFrame_AddPss.m

Last Update : Dec 7, 2016

%V5G.211 - 6.8.1.2

function sf = SubFrame_AddPss(subFrame)

 

    p = 300;

 

    N_DL_RB = 100;

    N_RB_SC = 12;

 

    d = 0 .* [0:61] + 1;

 

    sList = [];

    for n = 0:61

       for l = 0:13

          k = n - 31 + (N_DL_RB*N_RB_SC/2);

          sList = [sList ; [l k d(n+1)]];

       end    

    end    

    

    subFrame = SubFrame_SetSymbolAt(subFrame,sList);

    

    sf = subFrame;

    

end

 

Filename : TestPSS.m

Last Update : Dec 7, 2016

subframe = CreateSubFrame(0,0,0);

 

subframe = SubFrame_AddPss(subframe);

 

PlotSubFrame(subframe,0,14,450,750);

SSS - Secondary Synchronization Signal

SubFrame_AddSss.m uses the same loop as the PSS, with k = n + 41 + 600. The SSS therefore sits on subcarriers 641 to 702, directly above the PSS, in all 14 symbols. The dummy value is 0.7 instead of 1, so the SSS shows in a different colour from the PSS in the plot.

The comment points to V5G.211 clause 6.8.2.2. Compare the offset with the PSS function: -31 there and +41 here. The difference is 72 subcarriers, which is exactly one allocation of 6 RB. So the SSS allocation starts where the PSS allocation, with its five guard subcarriers on each side, ends.

To see the three synchronization signals together, call SubFrame_AddPss, SubFrame_AddSss and SubFrame_AddEss on one subframe, as TestFrame.m does for subframes 0 and 25. Then plot the range from subcarrier 450 to 750. The three blocks fill the band from subcarrier 496 to 702 without any overlap.

 

Filename : SubFrame_AddSss.m 

Last Update : Dec 7, 2016

%V5G.211 - 6.8.2.2

function sf = SubFrame_AddSss(subFrame)

 

   p = 300;

 

    N_DL_RB = 100;

    N_RB_SC = 12;

 

    d = 0 .* [0:61] + 0.7;

 

    sList = [];

    for n = 0:61

       for l = 0:13

          k = n + 41 + (N_DL_RB*N_RB_SC/2);

          sList = [sList ; [l k d(n+1)]];

       end    

    end    

    

    subFrame = SubFrame_SetSymbolAt(subFrame,sList);

    

    sf = subFrame;

    

end

 

Filename : TestSSS.m

Last Update : Dec 7, 2016

subframe = CreateSubFrame(0,0,0);

 

subframe = SubFrame_AddSss(subframe);

 

PlotSubFrame(subframe,0,14,450,750);

ESS - Extended Synchronization Signal

SubFrame_AddEss.m maps the ESS to k = n - 104 + 600, for n from 0 to 62. That is 63 values, on subcarriers 496 to 558, below the PSS. The PSS and SSS loops stop at 61, while this loop runs to 62. So the code agrees with the 63 sub carriers labelled in the ESS picture of the Frame Structure page.

The comment points to V5G.211 clause 6.8.3.2. The ESS carries the OFDM symbol index, so a real ESS differs from one symbol to the next. A version of this function with real values would therefore index d by both n and l. The loop over l is already there, so the change stays inside the line that builds sList.

 

Filename : SubFrame_AddEss.m

Last Update : Dec 7, 2016

%V5G.211 - 6.8.3.2

function sf = SubFrame_AddEss(subFrame)

 

    p = 300;

 

    N_DL_RB = 100;

    N_RB_SC = 12;

 

    d = 0 .* [0:62] + 0.5;

 

    sList = [];

    for n = 0:62

       for l = 0:13

          k = n - 104 + (N_DL_RB*N_RB_SC/2);

          sList = [sList ; [l k d(n+1)]];

       end    

    end    

    

    subFrame = SubFrame_SetSymbolAt(subFrame,sList);

    

    sf = subFrame;

    

end

 

Filename : TestESS.m

Last Update : Dec 7, 2016

subframe = CreateSubFrame(0,0,0);

 

subframe = SubFrame_AddEss(subframe);

 

PlotSubFrame(subframe,0,14,450,750);

xPBCH

SubFrame_Add_xPBCH_Subblock.m fills subcarriers 0 to 3 of each RB in all 14 symbols, in two subblocks. The Even subblock covers RBs 59 to 99, above the centre, and the Odd subblock covers RBs 40 down to 0, below it. The 18 RBs in between, 41 to 58, stay free for PSS, SSS and ESS. Test_xPBCH.m draws both subblocks and zooms into the lowest four RBs.

 

Filename : SubFrame_Add_xPBCH_Subblock.m

Last Update : Dec 7, 2016

%V5G.211 - 6.5.4

function sf = SubFrame_Add_xPBCH_Subblock(subFrame,xPBCH)

 

    Subblock = upper(xPBCH.Subblock);

       

    N_DL_RB = xPBCH.N_DL_RB;

    N_RB_SC = xPBCH.N_RB_SC;

    

    d = xPBCH.DummyValue;

    

    sList = [];

    

    if strcmp(Subblock,'EVEN') == 1

        for l = 0:13

           for kp = floor((N_DL_RB+18)/2):(N_DL_RB - 1)

               for kpp = 0:3

                    k = kp * N_RB_SC + kpp;

                    sList = [sList ; [l k d]];

               end; %end of for kpp = 0:3

           end; %end of for kp = floor((N_DL_RB+18)/2):(N_DL_RB - 1)  

        end; %end of for l = 0:13

    elseif strcmp(Subblock,'ODD') == 1

        for l = 0:13

           for kp = floor((N_DL_RB-18)/2)-1:-1:0

               for kpp = 3:-1:0

                    k = kp * N_RB_SC + kpp;

                    sList = [sList ; [l k d]];

               end; %end of for kpp = 0:3

           end; %end of for kp = floor((N_DL_RB+18)/2):(N_DL_RB - 1)  

        end; %end of for l = 0:13         

    end;

    

    subFrame = SubFrame_SetSymbolAt(subFrame,sList);

    sf = subFrame;

    

end

 

Filename : Test_xPBCH.m

Last Update : Dec 7, 2016

subframe = CreateSubFrame(0,0,0);

 

xPBCH.N_DL_RB = 100;

xPBCH.N_RB_SC = 12;

 

xPBCH.Subblock = 'Even';

xPBCH.DummyValue = 0.2;

subframe = SubFrame_Add_xPBCH_Subblock(subframe,xPBCH);

 

xPBCH.Subblock = 'Odd';

xPBCH.DummyValue = 0.5;

subframe = SubFrame_Add_xPBCH_Subblock(subframe,xPBCH);

 

PlotSubFrame(subframe,0,14,0,47);

BRS - Beam measurement Reference Signal

SubFrame_AddBrs.m uses the same RBs as xPBCH, 0 to 40 and 59 to 99. Inside each RB, it fills subcarriers 4 to 11 in all 14 symbols. So BRS and xPBCH fill every RB between them, and neither enters the centre 18 RBs.

The comment points to V5G.211 clause 6.7.4.2. The line that builds kpList produces both RB ranges at once. floor(1/2*(N_DL_RB-18)) - 1 gives 40, and floor(1/2*(N_DL_RB+18)) gives 59. Because the formula uses N_DL_RB, the same function works for a narrower carrier, and the gap of 18 RBs stays in the centre.

Run TestBRS.m and Test_xPBCH.m with the zoom they already use, the lowest four RBs. The two plots are complements of each other, because every RE that one function fills, the other leaves empty.

 

Filename : SubFrame_AddBrs.m

Last Update : Dec 7, 2016

%V5G.211 - 6.7.4.2

function sf = SubFrame_AddBrs(subFrame,BRS)

 

    N_DL_RB = BRS.N_DL_RB;

    N_RB_SC = 12;

    

    d = BRS.DummyValue;

    kpList = [0:(floor(1/2*(N_DL_RB-18))-1) floor(1/2*(N_DL_RB+18)):(N_DL_RB-1)] ;

 

    sList = [];

    for l = 0:13

       for kp = kpList

           for kpp = 4:11

              k = kp * N_RB_SC + kpp;

              sList = [sList ; [l k d]];

           end  

       end

    end    

    

    subFrame = SubFrame_SetSymbolAt(subFrame,sList);

    

    sf = subFrame;

    

end

 

Filename : TestBRS.m 

Last Update : Dec 7, 2016

subframe = CreateSubFrame(0,0,0);

 

BRS.N_DL_RB = 100;

BRS.DummyValue = 0.5;

subframe = SubFrame_AddBrs(subframe,BRS);

 

PlotSubFrame(subframe,0,14,0,48);

BRRS - Beam Refinement Reference Signal

SubFrame_AddBrrs_Port.m places one antenna port at a time, in the symbol given by SymbolIndex. For port p, it uses k = 4*(p - 600 + 8m) + k0, for m from 0 to 36. So each port takes one subcarrier in every 32, and ports 600 to 607 together take one subcarrier in every 4. The offset k0 is 0 in the lower half of the band and 3 in the upper half. TestBRRS.m adds all eight ports in symbol 12.

 

Filename : SubFrame_AddBrrs_Port.m

Last Update : Dec 7, 2016

%V5G.211 - 6.7.5.2

function sf = SubFrame_AddBrrs_Port(subFrame,BRRS)

 

    p = BRRS.AntennaPort;

 

    N_RB_SC = BRRS.N_RB_SC;

    N_DL_RB = BRRS.N_DL_RB;

    l = BRRS.SymbolIndex;

    d = BRRS.DummyValue;

    

    sList = [];

    for m = 0:floor(3*N_DL_RB/8)-1

        kp = p + 8*m - 600;

        if 4*kp < floor(N_RB_SC*N_DL_RB/2)

           k0 = 0;

        else

           k0 = 3;

        end;

        

        k = 4*kp+k0;

        sList = [sList ; [l k d]];

     end;    

    

    subFrame = SubFrame_SetSymbolAt(subFrame,sList);

    

    sf = subFrame;

    

end

 

Filename : TestBRRS.m

Last Update : Dec 7, 2016

subframe = CreateSubFrame(0,0,0);

 

BRRS.AntennaPort = 600;

BRRS.N_DL_RB = 100;

BRRS.N_RB_SC = 12;

BRRS.SymbolIndex = 12;

BRRS.DummyValue = 0.2;

subframe = SubFrame_AddBrrs_Port(subframe, BRRS);

 

BRRS.AntennaPort = 601;

BRRS.DummyValue = 0.3;

subframe = SubFrame_AddBrrs_Port(subframe, BRRS);

 

BRRS.AntennaPort = 602;

BRRS.DummyValue = 0.4;

subframe = SubFrame_AddBrrs_Port(subframe, BRRS);

 

BRRS.AntennaPort = 603;

BRRS.DummyValue = 0.5;

subframe = SubFrame_AddBrrs_Port(subframe, BRRS);

 

BRRS.AntennaPort = 604;

BRRS.DummyValue = 0.5;

subframe = SubFrame_AddBrrs_Port(subframe, BRRS);

 

BRRS.AntennaPort = 605;

BRRS.DummyValue = 0.6;

subframe = SubFrame_AddBrrs_Port(subframe, BRRS);

 

BRRS.AntennaPort = 606;

BRRS.DummyValue = 0.7;

subframe = SubFrame_AddBrrs_Port(subframe, BRRS);

 

BRRS.AntennaPort = 607;

BRRS.DummyValue = 0.8;

subframe = SubFrame_AddBrrs_Port(subframe, BRRS);

 

PlotSubFrame(subframe,0,14,0,48);

 

ePBCH

SubFrame_Add_ePBCH.m treats the band as 200 groups of six subcarriers, two groups per RB. In each group, it fills subcarriers 0, 1, 3, 4 and 5 in all 14 symbols, and it leaves subcarrier 2 free for the DMRS. TestFrame.m puts ePBCH in subframe 49.

The comment points to V5G.211 clause 6.5A.4. The formula k = 6*kp + kpp counts in groups of six subcarriers rather than in RBs, so kp runs from 0 to 199 for 100 RB. The same group of six appears in the ePBCH DMRS, xREG and xPDCCH DMRS functions below. It is the common unit of the resource maps on this page.

 

Filename : SubFrame_Add_ePBCH.m

Last Update : Dec 7, 2016

%V5G.211 - 6.5A.4

function sf = SubFrame_Add_ePBCH(subFrame,ePBCH)

 

    N_DL_RB = ePBCH.N_DL_RB;

    d = ePBCH.DummyValue;

    

    sList = [];

    

    for l = 0:13

       for kp = 0:(2 * N_DL_RB - 1 )  

           for kpp = [0 1 3 4 5]

               k = 6 * kp + kpp;

               sList = [sList ; [l k d]];

           end; %end of kpp = [0 1 3 4 5]   

        end; %end of for m = 0:(2 * N_DL_RB - 1 )   

    end; %end of for l = 0:13    

    

    subFrame = SubFrame_SetSymbolAt(subFrame,sList);

    

    sf = subFrame;

    

end

 

Filename : Test_ePBCH.m

Last Update : Dec 7, 2016

subframe = CreateSubFrame(0,0,0);

 

ePBCH.N_DL_RB = 100;

 

ePBCH.DummyValue = 0.5;

subframe = SubFrame_Add_ePBCH(subframe,ePBCH);

 

PlotSubFrame(subframe,0,14,0,47);

ePBCH DMRS

SubFrame_Add_ePBCH_DMRS_Port.m fills the subcarrier that ePBCH leaves free, k = 6m + 2, in all 14 symbols. That is the 3rd and the 9th subcarrier of each RB. Test_ePBCH_and_DMRS.m adds port 500. The lines for port 501 are commented out, and the function does not use the port number, so port 501 would land on the same subcarriers as port 500.

The comment points to V5G.211 clause 6.7.7.2. Run Test_ePBCH_and_DMRS.m to see the two functions together. The ePBCH values and the DMRS values never overlap, because one function skips subcarrier 2 of each group of six and the other writes only subcarrier 2.

 

Filename : SubFrame_Add_ePBCH_DMRS_Port.m

Last Update : Dec 7, 2016

%V5G.211 - 6.7.7.2

function sf = SubFrame_Add_ePBCH_DMRS_Port(subFrame,ePBCH)

 

    p = ePBCH.AntennaPort;

        

    N_DL_RB = ePBCH.N_DL_RB;

    d = ePBCH.DummyValue;

    

    sList = [];

    

    for l = 0:13

       for m = 0:(2 * N_DL_RB - 1 )  

           

          k = 6 * m + 2;

          sList = [sList ; [l k d]];

           

       end; %end of for m = 0:(2 * N_DL_RB - 1 )   

    end; %end of for l = 0:13    

    

    subFrame = SubFrame_SetSymbolAt(subFrame,sList);

    

    sf = subFrame;

    

end

 

Filename : Test_ePBCH_and_DMRS.m

Last Update : Dec 7, 2016

subframe = CreateSubFrame(0,0,0);

 

ePBCH.N_DL_RB = 100;

 

ePBCH.DummyValue = 0.5;

subframe = SubFrame_Add_ePBCH(subframe,ePBCH);

 

ePBCH.AntennaPort = 500;

ePBCH.DummyValue = 0.3;

subframe = SubFrame_Add_ePBCH_DMRS_Port(subframe,ePBCH);

 

% ePBCH.AntennaPort = 501;

% ePBCH.DummyValue = 0.6;

% subframe = SubFrame_Add_ePBCH_DMRS_Port(subframe,ePBCH);

 

PlotSubFrame(subframe,0,14,0,47);

xREG

SubFrame_Add_xREG_Symbol.m builds 16 xREGs in one OFDM symbol, each of 72 subcarriers, starting at k0 = 72*n_xREG. Inside each group of six subcarriers, it fills subcarriers 0, 1, 4 and 5 and leaves 2 and 3 free. So one xREG carries 48 data REs, and 24 REs stay free for the xPDCCH DMRS. Even and odd xREGs get different dummy values, so neighbouring xREGs show in different colours.

 

Filename : SubFrame_Add_xREG_Symbol.m

Last Update : Dec 7, 2016

%V5G.211 - 6.2.4

function sf = SubFrame_Add_xREG_Symbol(subFrame,xREG)

 

    N_RB_SC = xREG.N_RB_SC;

    d1 = xREG.DummyValue1;

    d2 = xREG.DummyValue2;

    l = xREG.Symbol;

    

    sList = [];

    

    for n_xREG = 0:15

       for m = 0:11  

          for k1 = [0 1 4 5]

            k0 = 6 * n_xREG * N_RB_SC;

            k = k0 + k1 + 6 * m;

            if mod(n_xREG,2) == 0

                sList = [sList ; [l k d1]];

            else

                sList = [sList ; [l k d2]];

            end;    

          end; %end of for k1 = [0 1 4 5]

       end; %end of for m = 0:(2 * N_DL_RB - 1 )   

    end; %end of for n_xREG = 0:15    

    

    subFrame = SubFrame_SetSymbolAt(subFrame,sList);

    

    sf = subFrame;

    

end

 

Filename : Test_xREG.m

Last Update : Dec 7, 2016

subframe = CreateSubFrame(0,0,0);

    

xREG.N_RB_SC = 12;

 

xREG.DummyValue1 = 0.2;

xREG.DummyValue2 = 0.5;

xREG.Symbol = 0;

subframe = SubFrame_Add_xREG_Symbol(subframe,xREG);

 

xREG.DummyValue1 = 0.5;

xREG.DummyValue2 = 0.2;

xREG.Symbol = 1;

subframe = SubFrame_Add_xREG_Symbol(subframe,xREG);

 

PlotSubFrame(subframe,0,14,0,144);

xPDCCH DMRS

SubFrame_Add_xPDCCH_DMRS_UE.m fills the 24 REs that the xREG function leaves free: subcarriers 2 and 3 of every group of six, inside one xREG. The test scripts call it for all 16 xREGs in symbols 0 and 1. Test_xREG_and_xPDCCH_DMRS_UE.m combines both functions, so every RE of the two control symbols is filled.

 

Filename : SubFrame_Add_xPDCCH_DMRS_UE.m

Last Update : Dec 7, 2016

%V5G.211 - 6.7.2.2

function sf = SubFrame_Add_xPDCCH_DMRS_UE(subFrame,xPDCCH)

 

    N_RB_SC = xPDCCH.N_RB_SC;

    d = xPDCCH.DummyValue;

    n_xREG = xPDCCH.n_xREG;

    l = xPDCCH.Symbol;

    

    sList = [];

    

    for mp = 0:23  

            k0 = 6 * n_xREG * N_RB_SC;

            k = k0 + 2 + mod(mp,2) + 6 * floor(mp / 2);

            sList = [sList ; [l k d]];

    end; %end of for mp = 0:23  

    

    subFrame = SubFrame_SetSymbolAt(subFrame,sList);

    

    sf = subFrame;

    

end

 

Filename : Test_xPDCCH_DMRS_UE.m

Last Update : Dec 7, 2016

subframe = CreateSubFrame(0,0,0);

    

xPDCCH.N_RB_SC = 12;

 

for j = 0:1

    for i = 0:15

        xPDCCH.DummyValue = 0.7;

        xPDCCH.Symbol = j;

        xPDCCH.n_xREG = i;

        subframe = SubFrame_Add_xPDCCH_DMRS_UE(subframe,xPDCCH);

    end

end

 

% xPDCCH.DummyValue = 0.7;

% xPDCCH.Symbol = 0;

% xPDCCH.n_xREG = 0;

% subframe = SubFrame_Add_xPDCCH_DMRS_UE(subframe,xPDCCH);

%

% xPDCCH.DummyValue = 0.7;

% xPDCCH.Symbol = 0;

% xPDCCH.n_xREG = 5;

% subframe = SubFrame_Add_xPDCCH_DMRS_UE(subframe,xPDCCH);

%

% xPDCCH.DummyValue = 0.7;

% xPDCCH.Symbol = 0;

% xPDCCH.n_xREG = 15;

% subframe = SubFrame_Add_xPDCCH_DMRS_UE(subframe,xPDCCH);

 

PlotSubFrame(subframe,0,14,0,144);

 

 

Filename : Test_xREG_and_xPDCCH_DMRS_UE.m

Last Update : Dec 7, 2016

subframe = CreateSubFrame(0,0,0);

 

xREG.N_RB_SC = 12;

 

xREG.DummyValue1 = 0.2;

xREG.DummyValue2 = 0.5;

xREG.Symbol = 0;

subframe = SubFrame_Add_xREG_Symbol(subframe,xREG);

 

xREG.DummyValue1 = 0.5;

xREG.DummyValue2 = 0.2;

xREG.Symbol = 1;

subframe = SubFrame_Add_xREG_Symbol(subframe,xREG);

 

xPDCCH.N_RB_SC = 12;

 

for j = 0:1

    for i = 0:15

        xPDCCH.DummyValue = 0.7;

        xPDCCH.Symbol = j;

        xPDCCH.n_xREG = i;

        subframe = SubFrame_Add_xPDCCH_DMRS_UE(subframe,xPDCCH);

    end

end

 

% xPDCCH.DummyValue = 0.7;

% xPDCCH.Symbol = 0;

% xPDCCH.n_xREG = 0;

% subframe = SubFrame_Add_xPDCCH_DMRS_UE(subframe,xPDCCH);

%

% xPDCCH.DummyValue = 0.7;

% xPDCCH.Symbol = 0;

% xPDCCH.n_xREG = 5;

% subframe = SubFrame_Add_xPDCCH_DMRS_UE(subframe,xPDCCH);

%

% xPDCCH.DummyValue = 0.7;

% xPDCCH.Symbol = 0;

% xPDCCH.n_xREG = 15;

% subframe = SubFrame_Add_xPDCCH_DMRS_UE(subframe,xPDCCH);

 

PlotSubFrame(subframe,0,14,0,144);

xPDSCH PNRS

SubFrame_Add_xPDSCH_PNRS_Port.m places one PNRS port in the symbols from lp_first_xPDSCH to lp_last_xPDSCH, 3 to 13 in the test. Port 60 uses subcarrier 24 and port 61 uses subcarrier 23 of each group of four RBs, counted from the first xPDSCH RB. So the two ports sit on neighbouring subcarriers, once every 48 subcarriers. The inner loop writes each position four times, which does not change the result.

 

Filename : SubFrame_Add_xPDSCH_PNRS_Port.m

Last Update : Dec 7, 2016

% V5G.211 - 6.7.6.2

function sf = SubFrame_Add_xPDSCH_PNRS_Port(subFrame,xPDSCH)

 

    p = xPDSCH.AntennaPort;

 

    N_RB_SC = xPDSCH.N_RB_SC;

    n_PRB_xPDSCH = xPDSCH.n_PRB_xPDSCH;

    N_PRB_xPDSCH = xPDSCH.N_PRB_xPDSCH;

    lp_first_xPDSCH = xPDSCH.lp_first_xPDSCH;

    lp_last_xPDSCH = xPDSCH.lp_last_xPDSCH;

    

    d = xPDSCH.DummyValue;

    

    if (p == 60)

       kp = 24;

    elseif (p == 61)  

       kp = 23;

    end;

        

    sList = [];

    

    for l = lp_first_xPDSCH:lp_last_xPDSCH

        for mp = 0:(N_PRB_xPDSCH-1)

           

          kpp = floor(mp/4);

          k = N_RB_SC * (n_PRB_xPDSCH + kpp * 4) + kp;

          

          sList = [sList ; [l k d]];

          

       end; %end of for mp = 0:(N_PRB_xPDSCH-1)  

    end; %end of l = lp_first_xPDSCH:lp_last_xPDSCH    

    

    subFrame = SubFrame_SetSymbolAt(subFrame,sList);

    

    sf = subFrame;

    

end

 

Filename : TestPNRS_xPDSCH.m

Last Update : Dec 7, 2016

subframe = CreateSubFrame(0,0,0);

 

xPDSCH.N_RB_SC = 12;

xPDSCH.n_PRB_xPDSCH = 0;

xPDSCH.N_PRB_xPDSCH = 4*25;

xPDSCH.lp_first_xPDSCH = 3;

xPDSCH.lp_last_xPDSCH = 13;

 

xPDSCH.AntennaPort = 60;

xPDSCH.DummyValue = 0.4;

subframe = SubFrame_Add_xPDSCH_PNRS_Port(subframe,xPDSCH);

 

xPDSCH.AntennaPort = 61;

xPDSCH.DummyValue = 0.6;

subframe = SubFrame_Add_xPDSCH_PNRS_Port(subframe,xPDSCH);

 

PlotSubFrame(subframe,0,14,0,47);

Common Library

Every channel function above ends with a call to SubFrame_SetSymbolAt, which writes a list of symbol, subcarrier and value triples into the grid. CreateSubFrame.m makes that grid, with 15 rows for symbols and 1201 columns for subcarriers. PlotSubframe.m draws the whole subframe on the left and a zoomed area on the right, and PlotFrame.m draws all 50 subframes side by side.

 

Filename :  SubFrame_SetSymbolAt.m

Last Update : Dec 7, 2016

function sf = SubFrame_SetSymbolAt(subFrame,sList)

 

    NoOfElement = size(sList,1);

    

    for i = 1:NoOfElement

        sItem = sList(i,:);

        s = sItem(1)+1; % symbol Index

        sc = sItem(2)+1; % subcarrier Index

        sVal = sItem(3);

        subFrame.Grid(s,sc) = sVal;

    end

    

    sf = subFrame;

    

end

 

Filename : SubFrame_SetSymbolAtFrequency.m  

Last Update : Dec 7, 2016

function sf = SubFrame_SetSymbolAtFrequency(subFrame,scIndex,sStart,sEnd,sVec)

    subFrame.Grid(sStart+1:sEnd+1,scIndex+1) = sVec';

    sf = subFrame;

end

 

Filename : SubFrame_SetSymbolAtTime.m  

Last Update : Dec 7, 2016

function sf = SubFrame_SetSymbolAtTime(subFrame,sIndex,scStart,scEnd,sVec)

    subFrame.Grid(sIndex+1,scStart+1:scEnd+1) = sVec;

    sf = subFrame;

end

 

Filename : CreateFrame.m 

Last Update : Dec 7, 2016  

function frm = CreateFrame()

 

t = 0:14 * 10 * 5;

f = 0:100;

[gx,gy] = meshgrid(t,f);

gz = (0 .* gx) + (0 .* gy);

frm = [gx, gy, gz];

 

end

 

Filename : CreateSubFrame.m  

Last Update : Dec 7, 2016

function sf = CreateSubFrame(hfn,sfn,subframe)

    sf.HyperFrameNumber = hfn;

    sf.SystemFrameNumber = sfn;

    sf.SubframeNumber = subframe;

    sf.Grid = 0 .* ones(15,100*12+1);

end

 

Filename : PlotSubframe.m  

Last Update : Dec 7, 2016

function h=PlotSubframe(subFrame,sStart,sEnd,scStart,scEnd)

    

    m = subFrame.Grid;

    

    xStep = 0:size(m,1)-1;

    yStep = 0:size(m,2)-1;

    [X,Y] = meshgrid(xStep,yStep);

    Z = m'; %0 .* X + 0 .* Y;

    %Z(601,1:14) = 0 .* [1:14] + 1;

 

    subplot(1,2,1);

    surface(X,Y,Z,'EdgeColor','none');

    tMax = size(m,1);

    fMax = size(m,2);

    axis([0 (tMax-1) 0 fMax 0 1]);

    view([0,90]);

 

    xMin = sStart;

    xMax = sEnd;

    yMin = scStart;

    yMax = scEnd;

 

    subplot(1,2,2);

    surface(X,Y,Z);

    axis([xMin xMax yMin yMax 0 1]);

    view([0,90]);

end

 

Filename : PlotFrame.m  

Last Update : Dec 7, 2016

function h=PlotFrame(radioFrame,Option)

    

    rf = radioFrame;

    

    for i = 0:49

        sf = rf(i+1);

        m = sf.Grid;

 

        xStep = 0:size(m,1)-1;

        yStep = 0:size(m,2)-1;

        [X,Y] = meshgrid(xStep,yStep);

        Z = m'; %0 .* X + 0 .* Y;

        %Z(601,1:14) = 0 .* [1:14] + 1;

 

        subplot(1,50,i+1);

        surface(X,Y,Z,'EdgeColor','none');

        set(gca,'xticklabel',[]);

        set(gca,'yticklabel',[]);

        set(gca,'xtick',[]);

        set(gca,'ytick',[]);

        set(gca,'fontsize',6)

        title(num2str(i));

    %     pos = [(i/50.0) 0.01 (1.0/50.0) 0.98];

    %     set(gca,'Position',pos)

        view([0,90]);

    end;    

 

end