rjw | 6c1fd8f | 2022-11-30 14:33:01 +0800 | [diff] [blame] | 1 | from get_3GPP_N import get_3GPP_N
|
| 2 | from get_3GPP_crc_interleaver_pattern import get_3GPP_crc_interleaver_pattern
|
| 3 | from get_3GPP_rate_matching_pattern import get_3GPP_rate_matching_pattern
|
| 4 | from get_3GPP_sequence_pattern import get_3GPP_sequence_pattern
|
| 5 | from get_3GPP_info_bit_pattern import get_3GPP_info_bit_pattern
|
| 6 | from DCKA_polar_decoder import DCKA_polar_decoder
|
| 7 | from Scrambler import Scrambler
|
| 8 | import IQ_Utils
|
| 9 |
|
| 10 | class 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 |
|
| 78 | def 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 | #####################################################################################################################################
|
| 109 | def 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 |
|