NG Toolset开发笔记--5GNR Resource Grid(48)

3/17 update:

sendMsg1 is ready now, including:

*PRACH association period determination

*SSB to PRACH occasion mapping

*PRACH time-domain/freq-domain resource mapping

 

(1) PRACH association period determination

Used method is trying to find minimum valid prach occasions during 160ms (16 frames) period:

self.minNumValidPrachOccasionPerAssociationPeriod = math.ceil(self.numTxSsb / self.nrRachSsbPerRachOccasionM8 * 8)

where:

*numTxSsb is number of transmitted SSBs

*nrRachSsbPerRachOccasionM8 is ssb-perRACH-Occasion multiplied by 8.

Procedure to validate prach occasions:

#refer to 3GPP 38.213 vf40 8.1
                #For paired spectrum all PRACH occasions are valid.
                #If a UE is provided TDD-UL-DL-ConfigurationCommon, a PRACH occasion in a PRACH slot is valid if 
                #-	it is within UL symbols, or 
                #-	it does not precede a SS/PBCH block in the PRACH slot and starts at least N_gap symbols after a last downlink symbol and at least N_gap symbols after a last SS/PBCH block transmission symbol, where N_gap is provided in Table 8.1-2.
                for s in raSlots:
                    for t in range(self.nrRachCfgNumOccasionsPerSlot):
                        if self.nrDuplexMode == 'FDD':
                            for f in range(self.nrRachMsg1Fdm):
                                validPrachOccasionsPerAssociationPeriod.append([[curHsfn, curSfn, s], t, f])
                        else:
                            scaleTd = self.baseScsTd // self.prachScs
                            rachFirstSymbInBaseScsTd = (s * self.nrSymbPerSlotNormCp + self.nrRachCfgStartSymb + t * self.nrRachCfgDuration) * scaleTd
                            rachSymbsInbaseScsTd = [rachFirstSymbInBaseScsTd+k for k in range(self.nrRachCfgDuration*scaleTd)]
                            
                            nGapInBaseScsTd = 0 if self.nrRachScs in ('1.25', '5') or self.nrRachCfgFormat == 'B4' else 2*(self.baseScsTd//self.prachScs)
                            
                            valid = True
                            for k in rachSymbsInbaseScsTd:
                                if tdGrid[k] != 'U':
                                    valid = False
                                    break
                            
                            for k in range(rachFirstSymbInBaseScsTd, (s+1)*self.nrSymbPerSlotNormCp):
                                if tdGrid[k] == 'SSB':
                                    valid = False
                                    break
                            
                            for k in range(max(0, rachFirstSymbInBaseScsTd - nGapInBaseScsTd), rachFirstSymbInBaseScsTd):
                                if tdGrid[k] in ('SSB', 'SIB1'):
                                    valid = False
                                    break
                                
                            if valid:
                                for f in range(self.nrRachMsg1Fdm):
                                    validPrachOccasionsPerAssociationPeriod.append([[curHsfn, curSfn, s], t, f])
                            else:
                                for f in range(self.nrRachMsg1Fdm):
                                    invalidPrachOccasionsPerAssociationPeriod.append([[curHsfn, curSfn, s], t, f])

Example as below:

Configurations:
contents of ["freqBand"]: {'opBand': 'n77', 'duplexMode': 'TDD', 'maxDlFreq': 4200, 'freqRange': 'FR1'}
contents of ["ssbGrid"]: {'scs': '30KHz', 'pattern': 'Case C', 'minGuardBand240k': 'NA', 'kSsb': '0', 'nCrbSsb': '4'}
contents of ["ssbBurst"]: {'maxL': 8, 'inOneGroup': '10111111', 'groupPresence': 'NA', 'period': '20ms'}
contents of ["mib"]: {'sfn': '0', 'hrf': '0', 'dmrsTypeAPos': 'pos2', 'commonScs': '15KHz', 'rmsiCoreset0': '0', 'rmsiCss0': '0', 'coreset0MultiplexingPat': 1, 'coreset0NumRbs': 48, 'coreset0NumSymbs': 1, 'coreset0OffsetList': (2,), 'coreset0Offset': 2, 'coreset0StartRb': 0}
contents of ["carrierGrid"]: {'scs': '15KHz', 'bw': '10MHz', 'numRbs': '52', 'minGuardBand': '2'}
contents of ["pci"]: 0
contents of ["numUeAp"]: 4Tx
contents of ["tddCfg"]: {'refScs': '15KHz', 'pat1Period': '5ms', 'pat1NumDlSlots': '3', 'pat1NumDlSymbs': '10', 'pat1NumUlSymbs': '2', 'pat1NumUlSlots': '1', 'pat2Period': 'not used', 'pat2NumDlSlots': '', 'pat2NumDlSymbs': '', 'pat2NumUlSymbs': '', 'pat2NumUlSlots': ''}
contents of ["css0"]: {'aggLevel': '4', 'numCandidates': 'n4'}
contents of ["dci10Sib1"]: {'rnti': '0xFFFF', 'muPdcch': '0', 'muPdsch': '0', 'tdRa': '2', 'tdMappingType': 'Type A', 'tdK0': '0', 'tdSliv': '95', 'tdStartSymb': '2', 'tdNumSymbs': '9', 'fdRaType': 'RA Type1', 'fdRa': '00001011111', 'fdStartRb': '0', 'fdNumRbs': '48', 'fdVrbPrbMappingType': 'interleaved', 'fdBundleSize': 'n2', 'mcsCw0': '2', 'tbs': '1864'}
contents of ["dmrsSib1"]: {'dmrsType': 'Type 1', 'dmrsAddPos': 'pos2', 'maxLength': 'len1', 'dmrsPorts': '0', 'cdmGroupsWoData': '2', 'numFrontLoadSymbs': '1', 'tdL': [2, 6, 9], 'fdK': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]}
contents of ["iniUlBwp"]: {'bwpId': '0', 'scs': '15KHz', 'cp': 'normal', 'locAndBw': '14025', 'startRb': '0', 'numRbs': '52'}
contents of ["rach"]: {'prachConfId': '27', 'raFormat': '0', 'raX': 1, 'raY': (0,), 'raSubfNumFr1SlotNumFr2': (1, 3, 5, 7, 9), 'raStartingSymb': 0, 'raNumSlotsPerSubfFr1Per60KSlotFr2': 1, 'raNumOccasionsPerSlot': 1, 'raDuration': 0, 'scs': '1.25KHz', 'msg1Fdm': '2', 'msg1FreqStart': '2', 'totNumPreambs': '64', 'ssbPerRachOccasion': 'oneHalf', 'cbPreambsPerSsb': '8', 'msg3Tp': 'disabled', 'raLen': 839, 'raNumRbs': 6, 'raKBar': 7}
output for determining valid PRACH occasions:
contents of validPrachOccasionsPerAssociationPeriod(size=14,minSize=14):
[[0, 0, 9], 0, 0],[[0, 0, 9], 0, 1],[[0, 1, 9], 0, 0],[[0, 1, 9], 0, 1],[[0, 2, 9], 0, 0],[[0, 2, 9], 0, 1],[[0, 3, 9], 0, 0],[[0, 3, 9], 0, 1],[[0, 4, 9], 0, 0],[[0, 4, 9], 0, 1],[[0, 5, 9], 0, 0],[[0, 5, 9], 0, 1],[[0, 6, 9], 0, 0],[[0, 6, 9], 0, 1]
contents of invalidPrachOccasionsPerAssociationPeriod(size=50):
[[0, 0, 7], 0, 0],[[0, 0, 7], 0, 1],[[0, 1, 1], 0, 0],[[0, 1, 1], 0, 1],[[0, 1, 3], 0, 0],[[0, 1, 3], 0, 1],[[0, 1, 5], 0, 0],[[0, 1, 5], 0, 1],[[0, 1, 7], 0, 0],[[0, 1, 7], 0, 1],[[0, 2, 1], 0, 0],[[0, 2, 1], 0, 1],[[0, 2, 3], 0, 0],[[0, 2, 3], 0, 1],[[0, 2, 5], 0, 0],[[0, 2, 5], 0, 1],[[0, 2, 7], 0, 0],[[0, 2, 7], 0, 1],[[0, 3, 1], 0, 0],[[0, 3, 1], 0, 1],[[0, 3, 3], 0, 0],[[0, 3, 3], 0, 1],[[0, 3, 5], 0, 0],[[0, 3, 5], 0, 1],[[0, 3, 7], 0, 0],[[0, 3, 7], 0, 1],[[0, 4, 1], 0, 0],[[0, 4, 1], 0, 1],[[0, 4, 3], 0, 0],[[0, 4, 3], 0, 1],[[0, 4, 5], 0, 0],[[0, 4, 5], 0, 1],[[0, 4, 7], 0, 0],[[0, 4, 7], 0, 1],[[0, 5, 1], 0, 0],[[0, 5, 1], 0, 1],[[0, 5, 3], 0, 0],[[0, 5, 3], 0, 1],[[0, 5, 5], 0, 0],[[0, 5, 5], 0, 1],[[0, 5, 7], 0, 0],[[0, 5, 7], 0, 1],[[0, 6, 1], 0, 0],[[0, 6, 1], 0, 1],[[0, 6, 3], 0, 0],[[0, 6, 3], 0, 1],[[0, 6, 5], 0, 0],[[0, 6, 5], 0, 1],[[0, 6, 7], 0, 0],[[0, 6, 7], 0, 1]

(2) SSB to valid PRACH occasion mapping

#SSB and PRACH occasion mapping
        ssb2RachOccasionMap = dict()
        if self.nrRachSsbPerRachOccasionM8 < 8:
            numRachOccasionPerSsb = 8 // self.nrRachSsbPerRachOccasionM8
            count = 0
            for issb in range(len(self.ssbSet)):
                if self.ssbSet[issb] == '1':
                    rachOccasions = [validPrachOccasionsPerAssociationPeriod[numRachOccasionPerSsb*count+k] for k in range(numRachOccasionPerSsb)]
                    cbPreambs = list(range(0, self.nrRachCbPreambsPerSsb))
                    ssb2RachOccasionMap[issb] = [rachOccasions, cbPreambs]
                    count = count + 1
        else:
            numSsbPerRachOccasion = self.nrRachSsbPerRachOccasionM8 // 8
            availCbPreambsPerSsb = self.nrRachTotNumPreambs // numSsbPerRachOccasion
            count = 0
            for issb in range(len(self.ssbSet)):
                if self.ssbSet[issb] == '1':
                    rachOccasions = [validPrachOccasionsPerAssociationPeriod[count // numSsbPerRachOccasion]]
                    cbPreambs = [availCbPreambsPerSsb*(count%numSsbPerRachOccasion)+k for k in range(self.nrRachCbPreambsPerSsb)]
                    ssb2RachOccasionMap[issb] = [rachOccasions, cbPreambs]
                    count = count + 1

Example output:

output of SSB-to-PRACH occasion mapping:
contents of ssb2RachOccasionMap:
issb=0: rachOccasion=[[[0, 0, 9], 0, 0], [[0, 0, 9], 0, 1]], cbPreambs=[0, 1, 2, 3, 4, 5, 6, 7]
issb=2: rachOccasion=[[[0, 1, 9], 0, 0], [[0, 1, 9], 0, 1]], cbPreambs=[0, 1, 2, 3, 4, 5, 6, 7]
issb=3: rachOccasion=[[[0, 2, 9], 0, 0], [[0, 2, 9], 0, 1]], cbPreambs=[0, 1, 2, 3, 4, 5, 6, 7]
issb=4: rachOccasion=[[[0, 3, 9], 0, 0], [[0, 3, 9], 0, 1]], cbPreambs=[0, 1, 2, 3, 4, 5, 6, 7]
issb=5: rachOccasion=[[[0, 4, 9], 0, 0], [[0, 4, 9], 0, 1]], cbPreambs=[0, 1, 2, 3, 4, 5, 6, 7]
issb=6: rachOccasion=[[[0, 5, 9], 0, 0], [[0, 5, 9], 0, 1]], cbPreambs=[0, 1, 2, 3, 4, 5, 6, 7]
issb=7: rachOccasion=[[[0, 6, 9], 0, 0], [[0, 6, 9], 0, 1]], cbPreambs=[0, 1, 2, 3, 4, 5, 6, 7]

(3) PRACH time-domain/freq-domain resource mapping:

time-domain:

#PRACH time/freq domain RE mapping
        msg1Hsfn, msg1Sfn, msg1Slot = bestSsbRachOccasion[0]
        msg1OccasionInd = bestSsbRachOccasion[1]
        msg1FdmInd = bestSsbRachOccasion[2]
        
        scaleTd = self.baseScsTd // self.prachScs
        msg1FirstSymbInBaseScsTd = (msg1Slot * self.nrSymbPerSlotNormCp + self.nrRachCfgStartSymb + msg1OccasionInd * self.nrRachCfgDuration) * scaleTd
        msg1SymbsInBaseScsTd = [msg1FirstSymbInBaseScsTd+k for k in range(self.nrRachCfgDuration*scaleTd)]

freq-domain:

#determine freq-domain
        scaleFd = self.nrIniUlBwpScs // self.baseScsFd
        msg1FirstScInBaseScsFd = self.nrCarrierMinGuardBand * self.nrScPerPrb * (self.nrCarrierScs // self.baseScsFd) + self.nrIniUlBwpStartRb * self.nrScPerPrb * scaleFd + (self.nrRachMsg1FreqStart + msg1FdmInd * self.nrRachNumRbs) * self.nrScPerPrb * scaleFd
        msg1ScsInBaseScsFd = [msg1FirstScInBaseScsFd+k for k in range(self.nrRachNumRbs*self.nrScPerPrb*scaleFd)]

 

Final note: I'm planning to release first alpha version of '5GNR Resource Grid tool'.

你可能感兴趣的:(Dev,4G/5G,Python)