SDR  - srsLTE Example - Pdsch_Ue                                           Home : www.sharetechnote.com

 

 

 

srsLTE - Example - Pdsch_Ue

 

This example is implemented by the source srsLTE\examples\Pdsch_ue.c. The functionality of this example is read OFDMA data (in the form of I/Q) from a file or RF Board and decode PDSCH. But you need to complete many of things before you decode PDSCH. So the source code would look much more complicated as you might think. But this would be a very good example of understanding the overall process of detect/decoding dowlink signal happening in UE.

By setting a simple flag, you can let this function to decode PDSCH from a file (meaning you don't need any RF hardware) or directly from a RF hardware (e.g, USRP).

Since my main purpose is to understand the details of the code, not building a working hardware. I chose to look into the details of the code that decode PDSCH from a file. I simplied the code which is directly related to this process and removing all error handling parts just leaving the parts that is directly related to the decoding process.

I hope this summary and additional comments help you to undertand the original source code in the project.

Case 1 : Decoding PDSCH from a file

A UE cannot decode PDSCH straight away. It first has to find the cell and the frame timing. Then it reads the MIB to learn the frame number. Only after that can it look for its PDCCH and decode the PDSCH that the PDCCH points to. The main() function below runs exactly this chain as a small state machine with two states, DECODE_MIB and DECODE_PDSCH.

Let's walk through it before reading the code. The first four calls prepare the resources: the file reader for synchronization, the MIB decoder, the downlink decoder and the RNTI. The while loop then reads one subframe per turn. The call srslte_ue_sync_get_buffer returns 1 when it has one aligned subframe. In DECODE_MIB, the loop tries PBCH in subframe 0 and moves to DECODE_PDSCH once the MIB is decoded. In DECODE_PDSCH, it decodes the downlink for the configured RNTI and updates RSRQ, RSRP and noise with a moving average. After subframe 9, it increments the SFN, and it wraps the SFN at 1024.

Source listing - main() of pdsch_ue.c from the srsLTE project, simplified by the author, with the author's comments in green

/**
 *
 * \section COPYRIGHT
 *
 * Copyright 2013-2015 Software Radio Systems Limited
 *
 * \section LICENSE
 *
 * This file is part of the srsLTE library.
 *
 * srsLTE is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of
 * the License, or (at your option) any later version.
 *
 * srsLTE is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * A copy of the GNU Affero General Public License can be found in
 * the LICENSE file in the top-level directory of this distribution
 * and at http://www.gnu.org/licenses/.
 *
 */


int main(int argc, char **argv) {
    // Initialize all the resources that is required to perform Synchronization. When you decode PDSCH from file,
    // the main role of this function is to read data from pdsch file and store it into an internal array to be used in
    // other process.
    srslte_ue_sync_init_file(&ue_sync,
                                   prog_args.file_nof_prb,
                                   prog_args.input_file_name,
                                   prog_args.file_offset_time,
                                   prog_args.file_offset_freq)

    // Initialize all the resources that is required for decode MIB. Initialization of OFDM symbol array and Channel
    // Estimation resource are done in this function as well.
    srslte_ue_mib_init(&ue_mib, cell);

    // This function initialize all the resources (Arrays, Channels) to decode all the downlink channels (PCFICH,
    // PHICH, PDCCH, PDSCH). A lot of initialization routine for ofdm, channel estimation, and other physical channels
    // ( (PCFICH, PHICH, PDCCH, PDSCH) are called within this function
    srslte_ue_dl_init(&ue_dl, cell);

    // Configure downlink receiver for the RNTI specied by the option flag
    srslte_ue_dl_set_rnti(&ue_dl, prog_args.rnti);

    // Set initial CFO for ue_sync
    srslte_ue_sync_set_cfo(&ue_sync, cfo);

    // Decode channels for each subframe.
    while (!go_exit && (sf_cnt < prog_args.nof_subframes || prog_args.nof_subframes == -1)) {

        // Check if Sync signal is detected. It return 1 when sync detected, otherwise it return 0.
        ret = srslte_ue_sync_get_buffer(&ue_sync, &sf_buffer);

        /* srslte_ue_sync_get_buffer returns 1 if successfully read 1 aligned subframe */
        // if Sync is not detected (i.e, ret == 0) this part (Channel Decode) is skipped and go to next loop
        // try srslte_ue_sync_get_buffer() again.
        if (ret == 1) {
          switch (state) {
            case DECODE_MIB:
              if (srslte_ue_sync_get_sfidx(&ue_sync) == 0) {
                srslte_pbch_decode_reset(&ue_mib.pbch);

                //Detect PBCH and decode MIB
                n = srslte_ue_mib_decode(&ue_mib, sf_buffer, bch_payload, NULL, &sfn_offset)

                   // When PBCH is decoded, set state = DECODE_PDSCH, so that the routine decode PDSCH in next loop
                state = DECODE_PDSCH;
              }
              break;
            case DECODE_PDSCH:
              if (decode_pdsch) {
                INFO("Attempting DL decode SFN=%d\n", sfn);
                if (prog_args.rnti != SRSLTE_SIRNTI) {
                  // if rnti option flag is not SI RNTI, perform regular dl decoding
                  n = srslte_ue_dl_decode(&ue_dl,
                                                   &sf_buffer[prog_args.time_offset],
                                                   data, srslte_ue_sync_get_sfidx(&ue_sync));
                } else {
                  // if rnti option flag is set to be SI RNTI, perform regular dl decoding with the calculated rv
                  // RV for SIB1 is predefined
                  uint32_t k  = (sfn/2)%4;
                  uint32_t rv = ((uint32_t) ceilf((float)1.5*k))%4;

                  n = srslte_ue_dl_decode_rnti_rv(&ue_dl, &sf_buffer[prog_args.time_offset], data,
                                                  srslte_ue_sync_get_sfidx(&ue_sync),
                                                  SRSLTE_SIRNTI, rv);
                }

                nof_trials++;

                rsrq = SRSLTE_VEC_EMA(srslte_chest_dl_get_rsrq(&ue_dl.chest), rsrq, 0.1);
                rsrp = SRSLTE_VEC_EMA(srslte_chest_dl_get_rsrp(&ue_dl.chest), rsrp, 0.05);
                noise = SRSLTE_VEC_EMA(srslte_chest_dl_get_noise_estimate(&ue_dl.chest), noise, 0.05);
                nframes++;
              }

              break;
          }
          if (srslte_ue_sync_get_sfidx(&ue_sync) == 9) {
            // if subframe index == 9, increment SFN number by 1
            sfn++;
            if (sfn == 1024) {
              // if SFN == 1024, initialize SFN = 0
              sfn = 0;
              printf("\n");
              ue_dl.pkt_errors = 0;
              ue_dl.pkts_total = 0;
              ue_dl.nof_detected = 0;
              nof_trials = 0;
            }
          }


        } else if (ret == 0) { // if Sync is not detected, do following
          printf("Finding PSS... Peak: %8.1f, FrameCnt: %d, State: %d\r",
            srslte_sync_get_peak_value(&ue_sync.sfind),
            ue_sync.frame_total_cnt, ue_sync.state);
        }

        sf_cnt++;
      } // end of while()

}
  • The licence header comes from the srsLTE source file. It is the GNU Affero General Public License text, version 3 or later.
  • The SI RNTI branch computes the redundancy version of SIB1 as k = (sfn/2)%4 and rv = ceil(1.5 x k)%4. This matches 36.321 clause 5.3.1, where RVK = ceiling(3/2 x k) modulo 4 and k = (SFN/2) modulo 4 for SystemInformationBlockType1. So SIB1 uses the redundancy versions 0, 2, 3 and 1 in turn.
  • The line n = srslte_ue_mib_decode(...) has no semicolon at its end. So this listing would not compile as shown. Treat it as a slip in the simplified listing, which is kept here as the author wrote it.
  • SRSLTE_VEC_EMA applies an exponential moving average. The weight is 0.1 for RSRQ and 0.05 for RSRP and noise, so a single subframe moves each estimate only a little.
  • The SFN wraps at 1024 because the SFN in LTE runs from 0 to 1023.
  • The UE decodes MIB before PDSCH : the state machine stays in DECODE_MIB until PBCH in subframe 0 is decoded.
  • A regular RNTI and SI-RNTI take different paths : for SI-RNTI the code has to compute the SIB1 redundancy version from the SFN.
  • The code tracks the SFN itself : it counts subframe 9 boundaries after the MIB instead of decoding PBCH again.

Result

Once you have built the code successful, you can run this code as shown in the following example. (If you are not familiar with how to build install srsLTE project and build it, refer to How to build srsLTE page).

Note 1: "pdsch.out" is the file that contains the I/Q data of LTE eNB downlink frame (I created this file using pdsch_enodeb example program.).

Note 2: Keep in mind that you have to specify C_RNTI using -r option as shown below. You have to use the RNTI value 1234 since it is hard coded in the example.

The box below holds the command and its short output. The program first prints the cell it found from the MIB, then a single summary line for the run.

Capture - console output of pdsch_ue decoding pdsch.out, as run by the author

# ~/srsLTE/build/srslte/examples$ ./pdsch_ue -i "pdsch.out" -n 10 -r 1234

linux; GNU C++ version 5.3.1 20160413; Boost_105800; UHD_003.009.004-release

 - Cell ID:         0
 - Nof ports:       1
 - CP:              Normal
 - PRB:             25
 - PHICH Length:    Normal
 - PHICH Resources: 1
 - SFN:             0
Decoded MIB. SFN: 0, offset: 0
CFO:  +0.00 kHz, SNR: 139.3 dB, PDCCH-Miss: 20.00%, PDSCH-BLER:  0.00%
Bye

The summary line needs one comment. An SNR of 139.3 dB is far beyond anything a real receiver sees. It appears because pdsch.out comes straight from pdsch_enodeb, and no channel or noise was added between the two programs. So this run checks the decoding chain, not the receiver performance.

This is it.  Now have fun !

If you want to get more detailed information about generation and decoding process, you can use -v option as follows.

Capture - verbose console output of pdsch_enodeb generating pdsch.out, as run by the author

#~/srsLTE/build/srslte/examples$ ./pdsch_enodeb -o "pdsch.out" -n 10 -m 9 -v

linux; GNU C++ version 5.3.1 20160413; Boost_105800; UHD_003.009.004-release

[INFO]:  Indexing 200 REGs. CellId: 0, 25 PRB, CP: Normal
[INFO]:  PCFICH allocating 4 regs. CellID: 0, PRB: 25
[INFO]:  Creating 4 PHICH mapping units. Normal length, Ng=1.00
[INFO]:  Init PDCCH REG space CFI 1. 27 useful REGs (3 CCEs)
[INFO]:  Init PDCCH REG space CFI 2. 108 useful REGs (12 CCEs)
[INFO]:  Init PDCCH REG space CFI 3. 180 useful REGs (20 CCEs)
[INFO]:  Init PDCCH: Max bits: 1440, 1 ports.
[INFO]:  Init PDSCH: 1 ports 25 PRBs, max_symbols: 4200
 - Resource Allocation Type:        Type 0
   + Resource Block Group Size:     2
   + RBG Bitmap:            0x1fff
 - Modulation and coding scheme index:  9
 - HARQ process:            0
 - New data indicator:          No
 - Redundancy version:          0
 - TPC command for PUCCH:       --
 - PRB Bitmap Assignment 0st slot:
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
 - PRB Bitmap Assignment 1st slot:
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
 - Number of PRBs:          25
 - Modulation type:         QPSK
 - Transport block size:        4008
Type new MCS index and press Enter: [INFO]:  SF: 0, Generating 0 random bits
[INFO]:  SF: 1, Generating 0 random bits
[INFO]:  Putting DCI to location: n=8, L=3
[INFO]:  CB Segmentation: TBS: 4008, C=1, C+=1 K+=4032, C-=0, K-=0, F=0, Bp=4032
[INFO]:  Encoding PDSCH SF: 1, Mod QPSK, NofBits: 4008, NofSymbols: 3150, NofBitsE: 6300, rv_idx: 0
[INFO]:  CB#0: cb_len: 4032, rlen: 4032, wp: 0, rp: 0, E: 6300
[INFO]:  Last CB, appending parity: 4008 from 0 and 24 to 4008
[INFO]:  END CB#1: wp: 6300, rp: 4032
[INFO]:  SF: 2, Generating 4008 random bits
....

In the same way, you can get more detailed information about the decoded result as shown below.

Capture - verbose console output of pdsch_ue decoding pdsch.out, as run by the author

# ~/srsLTE/build/srslte/examples$ ./pdsch_ue -i "pdsch.out" -n 10 -r 1234 -v

linux; GNU C++ version 5.3.1 20160413; Boost_105800; UHD_003.009.004-release

[INFO]:  Offseting input file by 0 samples and 0.0 kHz
[INFO]:  Indexing 200 REGs. CellId: 0, 25 PRB, CP: Normal
[INFO]:  PCFICH allocating 4 regs. CellID: 0, PRB: 25
[INFO]:  Creating 4 PHICH mapping units. Normal length, Ng=1.00
[INFO]:  Init PDCCH REG space CFI 1. 27 useful REGs (3 CCEs)
[INFO]:  Init PDCCH REG space CFI 2. 108 useful REGs (12 CCEs)
[INFO]:  Init PDCCH REG space CFI 3. 180 useful REGs (20 CCEs)
[INFO]:  Init PDCCH: Max bits: 1440, 1 ports.
[INFO]:  Init PDSCH: 1 ports 25 PRBs, max_symbols: 4200
[INFO]:
Entering main loop...

[INFO]:  Reading 5760 samples. sf_idx = 0
[INFO]:  Decoded PBCH: src=0, dst=0, nb=1, sfn_offset=0
[INFO]:  MIB decoded: 0
 - Cell ID:         0
 - Nof ports:       1
 - CP:              Normal
 - PRB:             25
 - PHICH Length:    Normal
 - PHICH Resources: 1
 - SFN:             0
Decoded MIB. SFN: 0, offset: 0
[INFO]:  Reading 5760 samples. sf_idx = 1
[INFO]:  Attempting DL decode SFN=0
[INFO]:  Decoded CFI=3 with correlation 32.00, sf_idx=1
[INFO]:  Found DCI nCCE: 8, L: 3, n_bits=27
[INFO]:  Format1 PDSCH Scheduling
 - Resource Allocation Type:        Type 0
   + Resource Block Group Size:     2
   + RBG Bitmap:            0x1fff
 - Modulation and coding scheme index:  9
 - HARQ process:            0
 - New data indicator:          No
 - Redundancy version:          0
 - TPC command for PUCCH:       --
 - PRB Bitmap Assignment 0st slot:
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
 - PRB Bitmap Assignment 1st slot:
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
 - Number of PRBs:          25
 - Modulation type:         QPSK
 - Transport block size:        4008
[INFO]:  CB Segmentation: TBS: 4008, C=1, C+=1 K+=4032, C-=0, K-=0, F=0, Bp=4032
[INFO]:  Decoding PDSCH SF: 1, RNTI: 0x1234, Mod QPSK, TBS: 4008, NofSymbols: 3150, NofBitsE: 6300, rv_idx: 0, C_prb=25
[INFO]:  CB#0: cb_len: 4032, rlen: 4032, wp: 0, rp: 0, E: 6300, n_iters=1
[INFO]:  END CB#1: wp: 4032, rp: 6300
[INFO]:
    CAUTION!! Received all-zero transport block

[INFO]:  TB decoded OK
[INFO]:  Reading 5760 samples. sf_idx = 2
[INFO]:  Attempting DL decode SFN=0
[INFO]:  Decoded CFI=3 with correlation 32.00, sf_idx=2
[INFO]:  Found DCI nCCE: 8, L: 3, n_bits=27
[INFO]:  Format1 PDSCH Scheduling
 - Resource Allocation Type:        Type 0
   + Resource Block Group Size:     2
   + RBG Bitmap:            0x1fff
 - Modulation and coding scheme index:  9
 - HARQ process:            0
 - New data indicator:          No
 - Redundancy version:          0
 - TPC command for PUCCH:       --
 - PRB Bitmap Assignment 0st slot:
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
 - PRB Bitmap Assignment 1st slot:
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
 - Number of PRBs:          25
 - Modulation type:         QPSK
 - Transport block size:        4008
[INFO]:  CB Segmentation: TBS: 4008, C=1, C+=1 K+=4032, C-=0, K-=0, F=0, Bp=4032
[INFO]:  Decoding PDSCH SF: 2, RNTI: 0x1234, Mod QPSK, TBS: 4008, NofSymbols: 3150, NofBitsE: 6300, rv_idx: 0, C_prb=25
[INFO]:  CB#0: cb_len: 4032, rlen: 4032, wp: 0, rp: 0, E: 6300, n_iters=1
[INFO]:  END CB#1: wp: 4032, rp: 6300
[INFO]:  TB decoded OK
[INFO]:  Reading 5760 samples. sf_idx = 3
[INFO]:  Attempting DL decode SFN=0
[INFO]:  Decoded CFI=3 with correlation 32.00, sf_idx=3
[INFO]:  Found DCI nCCE: 8, L: 3, n_bits=27
[INFO]:  Format1 PDSCH Scheduling
 - Resource Allocation Type:        Type 0
   + Resource Block Group Size:     2
   + RBG Bitmap:            0x1fff
 - Modulation and coding scheme index:  9
 - HARQ process:            0
 - New data indicator:          No
 - Redundancy version:          0
 - TPC command for PUCCH:       --
 - PRB Bitmap Assignment 0st slot:
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
 - PRB Bitmap Assignment 1st slot:
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
 - Number of PRBs:          25
 - Modulation type:         QPSK
 - Transport block size:        4008

....

Put the two verbose logs side by side and they match line for line. The eNB side puts the DCI at n=8 with L=3, and the UE side finds the DCI at nCCE 8 with L 3. Both sides use Format 1 with Resource Allocation Type 0, MCS index 9, QPSK and a transport block of 4008 bits. The eNB side generates 0 random bits for subframe 1, and the UE side reports an all-zero transport block for subframe 1. From subframe 2, the eNB generates 4008 random bits, and the UE no longer gives that warning.

  • The file carries no noise : this is why the SNR estimate reaches 139.3 dB.
  • The two verbose logs describe the same subframes from both ends : the DCI location, format, MCS and TBS agree.
  • The all-zero warning is expected in subframe 1 : the eNB side generated 0 random bits for that subframe.

Do the numbers in the log agree with the LTE specifications ?

The verbose logs print many numbers without saying where they come from. Each of them follows from three settings in the MIB and the DCI: 25 PRB, one antenna port and normal CP, with CFI 3 and MCS 9. So we can check the log against 36.211, 36.212 and 36.213, and the table below does this line by line. If you change the bandwidth or the MCS, you can redo the same arithmetic.

 

Log line

Where the number comes from

Creating 4 PHICH mapping units. Normal length, Ng=1.00

36.211 clause 6.9 gives the number of PHICH groups as ceiling(Ng x NRB/8) for normal CP. With Ng = 1 and 25 RBs, this is ceiling(3.125) = 4.

PCFICH allocating 4 regs

PCFICH always uses 4 REGs, which carry its 16 QPSK symbols.

Init PDCCH REG space CFI 1. 27 useful REGs (3 CCEs)

Symbol 0 has 2 REGs per RB because of the CRS, so 50 REGs. PCFICH takes 4 and 4 PHICH groups take 12, which leaves 34. One CCE is 9 REGs, so 3 CCEs fit, and they use 27 REGs.

Init PDCCH REG space CFI 2. 108 useful REGs (12 CCEs)

With one antenna port, symbol 1 carries no CRS and has 3 REGs per RB, so it adds 75 REGs. 34 + 75 = 109 REGs give 12 CCEs, which use 108 REGs.

Init PDCCH REG space CFI 3. 180 useful REGs (20 CCEs)

Symbol 2 adds another 75 REGs. 109 + 75 = 184 REGs give 20 CCEs, which use 180 REGs.

Init PDSCH: 1 ports 25 PRBs, max_symbols: 4200

25 PRB x 12 subcarriers x 14 symbols = 4200 REs in one subframe. This is the upper bound before control region and CRS are removed.

RBG Bitmap: 0x1fff, Resource Block Group Size: 2

36.213 Table 7.1.6.1-1 gives an RBG size P = 2 for 11 to 26 RBs. 25 RBs then form 13 RBGs, and 0x1fff sets all 13 bits, so all 25 PRBs are allocated.

Found DCI nCCE: 8, L: 3, n_bits=27

Format 1 for 25 RBs with FDD has 27 bits. The resource allocation takes 1 header bit and 13 bitmap bits. MCS takes 5 bits, the HARQ process 3, NDI 1, RV 2 and TPC 2. L = 3 stands for aggregation level 8, that is 23, so the PDCCH uses 8 CCEs from CCE 8 to CCE 15. This fits inside the 20 CCEs of CFI 3.

Modulation type: QPSK, Transport block size: 4008

MCS 9 maps to QPSK and ITBS 9 in 36.213 Table 7.1.7.1-1. Table 7.1.7.2.1-1 gives 4008 bits for ITBS 9 and 25 PRBs.

NofSymbols: 3150, NofBitsE: 6300

CFI 3 leaves 11 symbols for PDSCH. With one antenna port, the CRS takes 2 REs per RB in 3 of those symbols. So each PRB has 11 x 12 - 6 = 126 REs, and 25 PRBs have 3150 REs. QPSK carries 2 bits per RE, which gives 6300 bits.

CB Segmentation: TBS: 4008, C=1, K+=4032, F=0

36.212 clause 5.3.2 adds a 24 bit transport block CRC to the transport block, so B = 4032. Clause 5.1.2 splits a block only when it is larger than 6144 bits, so there is one code block and no code block CRC. 4032 is itself a turbo interleaver size, so no filler bits are needed.

Reading 5760 samples. sf_idx = 0

5760 samples in one 1 ms subframe is a sampling rate of 5.76 MHz. That is a 384 point FFT at 15 kHz subcarrier spacing, which is enough for the 300 subcarriers of 25 PRBs.

 

The code rate follows from the last rows. The turbo coder takes 4032 bits and rate matching sends 6300 bits, so the effective code rate is about 0.64. That is a moderate rate for QPSK in a noiseless file, and the n_iters=1 in the UE log agrees with it: the turbo decoder needed only one iteration.

  • 25 PRB, one port and CFI 3 fix most of the log : the REG, CCE and RE counts all follow from these three settings.
  • MCS 9 with 25 PRBs gives TBS 4008 : the number comes straight from 36.213 Table 7.1.7.2.1-1.
  • One code block is enough here : 4008 bits plus a 24 bit CRC stay below the 6144 bit limit.
  • The effective code rate is about 0.64 : 4032 coded input bits are sent as 6300 bits.

Reference

  • 36.211 v19.3.0 : E-UTRA Physical channels and modulation. Clause 6.7 PCFICH, clause 6.8 PDCCH, clause 6.9 PHICH.
  • 36.212 v19.3.0 : E-UTRA Multiplexing and channel coding. Clause 5.1.2 Code block segmentation and clause 5.3.2 Downlink shared channel.
  • 36.213 v19.4.0 : E-UTRA Physical layer procedures. Table 7.1.6.1-1, Table 7.1.7.1-1 and Table 7.1.7.2.1-1.
  • 36.321 v19.3.0 : E-UTRA Medium Access Control - MAC; Protocol specification. Clause 5.3.1 DL Assignment reception.