blob: 3afd99e4901e687ffe02854e2c4488bbe25b6c5d [file] [log] [blame]
rjw6c1fd8f2022-11-30 14:33:01 +08001from get_3GPP_N import get_3GPP_N
2from get_3GPP_crc_interleaver_pattern import get_3GPP_crc_interleaver_pattern
3from get_3GPP_rate_matching_pattern import get_3GPP_rate_matching_pattern
4from get_3GPP_sequence_pattern import get_3GPP_sequence_pattern
5from get_3GPP_info_bit_pattern import get_3GPP_info_bit_pattern
6from DCKA_polar_decoder import DCKA_polar_decoder
7from Scrambler import Scrambler
8import IQ_Utils
9
10class MIB_Parser:
11#####################################################
12# 38.331. 6.2.2
13# MIB ::= SEQUENCE {
14# systemFrameNumber BIT STRING (SIZE (6)), 6 bit
15# subCarrierSpacingCommon ENUMERATED {scs15or60, scs30or120}, 1 bit
16# ssb_SubcarrierOffset INTEGER (0..15), 4 bit
17# dmrs_TypeA_position ENUMERATED {pos2, pos3}, 1 bit
18# pdcchConfigSIB1 PDCCH-ConfigSIB1, 8 bit
19# cellBarred ENUMERATED {barred, notBarred}, 1 bit
20# intraFreqReselection ENUMERATED {allowed, notAllowed}, 1 bit
21# spare BIT STRING (SIZE (1)) 1 bit
22#
23#
24#pdcchConfigSIB1 ::= SEQUENCE {
25# controlResourceSetZero ControlResourceSetZero,
26# searchSpaceZero SearchSpaceZero
27#}
28#####################################################
29
30 def __init__(self, a_hat, Lmax):
31
32 ############# MIB fields parsing for frequency range 1 #############
33 mibbits = a_hat
34 mibbits = ''.join(map(str, mibbits))
35 mibbits = mibbits[::-1] #reverse
36 self.reservedBits = IQ_Utils.bi2de(mibbits[0:2])
37 self.k_ssb = mibbits[2]
38 self.HRF = mibbits[3]
39 sfnCombinePHYRRC = mibbits[25:31] + mibbits[4:8]
40 self.systemFrameNumber = IQ_Utils.bi2de(sfnCombinePHYRRC)
41
42 if Lmax == 64:
43 commonSCSs = [60, 120]
44
45 else:
46 commonSCSs = [15, 30]
47
48 self.RAN2_sparedBit = mibbits[8]
49 self.intraFreqSelection = mibbits[9]
50 self.cellBarred = mibbits[10]
51 self.pdcchConfigSIB1 = IQ_Utils.bi2de(mibbits[11:19])
52 self.dmrs_TypeA_position = 2 + int(mibbits[19])
53 self.ssb_SubcarrierOffset = IQ_Utils.bi2de(mibbits[20:24])
54 self.subCarrierSpacingCommon = commonSCSs[int(mibbits[24])]
55 self.msgIndicator = mibbits[31]
56
57 print "NFrame: ", self.systemFrameNumber
58 print "SubcarrierSpacingCommon: ", self.subCarrierSpacingCommon
59 print "ssb-SubcarrierOffset: ", self.ssb_SubcarrierOffset
60 print "DL-DMRS_typeA_pos: ", self.dmrs_TypeA_position
61 print "PDCCHConfigSIB1: ", self.pdcchConfigSIB1
62 print "CellBarred: ", self.cellBarred
63 print "IntraFreqSelection: ", self.intraFreqSelection
64 print "Spare: ", self.RAN2_sparedBit
65 print "k_ssb", self.k_ssb
66 print "HRF: ", self.HRF
67 print "reservedBits:", self.reservedBits
68
69##############################################################################
70# NR PBCH payload interleaving
71# NOTE: N/A
72# input:
73# payload (32-bit)
74# output:
75# interleaved payload (32-bit)
76##############################################################################
77
78def get_3GPP_PBCH_payload_intlv(payload_bit):
79
80 mib_intlv_pattern = [1,16,23,18,17,8,30,4,9,11,12,13,14,15,19,20,21,22,25,
81 26,27,28,29,31,10,6,24,7,0,5,3,2]
82
83 intlv_out = [0]*32
84 for idx in xrange(31,-1,-1):
85 intlv_out[idx] = payload_bit[mib_intlv_pattern[idx]]
86
87 return intlv_out
88
89#####################################################################################################################################
90# PBCH_DECODER Polar decoder for the Public Broadcast Channel (PBCH) of 3GPP New Radio, as defined in Section 7.1 of TS38.212.
91# Implements the Cyclic Redudancy Check (CRC) attachment of Section 7.1.3, the channel coding of Section 7.1.4 and the rate
92# matching of Section 7.1.5.
93# NOTE: This code does not implement the payload generation of Section 7.1.1 or the scrambling of Section 7.1.2. Function decodes
94# the encoded LLR sequence f_tilde, in order to obtain the recovered information bit sequence a_hat.
95# input:
96# f_tilde should be a real row vector comprising 864 Logarithmic Likelihood Ratios (LLRS), each having a value obtained
97# as LLR = ln(P(bit=0)/P(bit=1)). The first LLR corresponds to f_0 from Section 7.1.5 of TS38.212, while the last LLR
98# corresponds to f_E-1.
99# A should be 32. It specifies the number of bits in the information bit sequence.
100# L should be a scalar integer. It specifies the list size to use during Successive Cancellation List (SCL) decoding.
101# min_sum shoular be a scalar logical. If it is true, then the SCL decoding process will be completed using the min-sum
102# approximation. Otherwise, the log-sum-product will be used. The log-sum-product gives better error correction capability
103# than the min-sum, but it has higher complexity.
104# Lmax is number of SSB candidates in a burst.
105# output:
106# a_hat will be a binary row vector comprising 32 bits, each having the value 0 or 1. The first output bit corresponds
107# to a'_0 from Section 7.1.3 of TS38.212, while the last output bit corresponds to a'_A-1.
108#####################################################################################################################################
109def PBCH_decoder(f_tilde, A, list_size, min_sum, NidCell, Lmax, ibar_SSB):
110
111 E = len(f_tilde)
112
113 # A is always 32 in PBCH
114 if A != 32:
115 raise Exception('polar_3gpp_matlab:UnsupportedBlockLength, A should be 32.')
116
117 # E is always 864 in PBCH
118 if E != 864:
119 raise Exception('polar_3gpp_matlab:UnsupportedBlockLength, E should be 864.')
120
121 # The CRC polynomial used in 3GPP PBCH and PDCCH channel is
122 # D^24 + D^23 + D^21 + D^20 + D^17 + D^15 + D^13 + D^12 + D^8 + D^4 + D^2 + D + 1
123 crc_polynomial_pattern = [1,1,0,1,1,0,0,1,0,1,0,1,1,0,0,0,1,0,0,0,1,0,1,1,1]
124
125 # The CRC has P bits. P-min(P2,log2(L)) of these are used for error
126 # detection, where L is the list size. Meanwhile, min(P2,log2(L)) of
127 # them are used to improve error correction. So the CRC needs to be
128 # min(P2,log2(L)) number of bits longer than CRCs used in other codes,
129 # in order to achieve the same error detection capability.
130 P = len(crc_polynomial_pattern) - 1
131 P2 = 3
132
133 # Determine the number of information and CRC bits.
134 K = A + P
135
136 # Determine the number of bits used at the input and output of the polar
137 # encoder kernal.
138 N = get_3GPP_N(K, E, 9)
139
140 # Get the 3GPP CRC interleaver pattern.
141 crc_interleaver_pattern = get_3GPP_crc_interleaver_pattern(K)
142
143 # Get the 3GPP rate matching pattern.
144 rate_matching_pattern,mode = get_3GPP_rate_matching_pattern(K, N, E)
145
146 # Get the 3GPP sequence pattern.
147 Q_N = get_3GPP_sequence_pattern(N)
148
149 # Get the 3GPP information bit pattern.
150 info_bit_pattern = get_3GPP_info_bit_pattern(K, Q_N, rate_matching_pattern, mode)
151
152 # Initialize scrambler
153 scrambler = Scrambler(NidCell, Lmax)
154 f_tilde_scrambled = scrambler.get_3GPP_2nd_scramble_s_seq(f_tilde, ibar_SSB) # scramble 864 LLRs
155
156 # Perform Distributed-CRC-and-Known-bit-Aided polar decoding.
157 a_hat = DCKA_polar_decoder(f_tilde_scrambled, crc_polynomial_pattern, crc_interleaver_pattern, info_bit_pattern, rate_matching_pattern, mode, list_size, min_sum, P2)
158
159 if (a_hat == 0):
160 print "no MIB"
161 else:
162 cellSfn = 1 # System frame number for cell
163 scrambled = scrambler.get_3GPP_1st_scramble_s_seq(cellSfn, a_hat) # Get scrambled hard coded bits
164 out = get_3GPP_PBCH_payload_intlv(scrambled) # Get interleaved payload
165
166 MIB_Parser(out, Lmax) # Parse MIB field messages from bit sequence
167