|
SDR - srsLTE Example - Pdsch_Ue Home : www.sharetechnote.com |
||||||||||||||||||||||||||
|
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 fileA 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()
}
ResultOnce 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.
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.
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.
Reference
|
||||||||||||||||||||||||||