2/12,完成recvNpdschWoBcch和fillNpdschWoBcch(TODO:NPDSCH Gap未实现):
其中recvNpdschWoBcch实现如下:
def recvNpdschWoBcch(self, hsfn, sfn, subf):
self.ngwin.logEdit.append('call resetNpdschWoBcchMap with N=%d, k0=%d @ [HSFN=%d,SFN=%d,SUBF=%d]' % (self.args['npdschNoBcchDciN1NumSf']*self.args['npdschNoBcchDciN1NumRep'], self.args['npdschNoBcchDciN1K0'], hsfn, sfn, subf))
self.resetNpdschWoBcchMap(hsfn, sfn, subf)
for key,val in self.npdschWoBcchMap.items():
self.ngwin.logEdit.append('key=%s,val=%s' % (key, val))
#note there is no need to call normalOps again!
#self.normalOps(hsfn, sfn)
self.fillNpdschWoBcch(hsfn, sfn)
#proceed to receive NPDSCH
allKeys = list(self.npdschWoBcchMap.keys())
key = str(hsfn) + '_' + str(sfn)
if key in allKeys:
current = key
last = allKeys[-1] if len(allKeys) > 1 else None
else:
current = key
last = allKeys[-1]
if last is not None:
while True:
hsfn, sfn = incSfn(hsfn, sfn, 1)
self.normalOps(hsfn, sfn)
self.fillNpdschWoBcch(hsfn, sfn)
current = str(hsfn) + '_' + str(sfn)
if current == last:
break
#make return tuple
retHsfn, retSfn = allKeys[-1].split('_')
retSubf = self.npdschWoBcchMap[allKeys[-1]][-1]
return (int(retHsfn), int(retSfn), retSubf)
resetNpdschWoBcchMap用于生成NPDSCH(without BCCH)mapping子帧序列:
def resetNpdschWoBcchMap(self, hsfn, sfn, subf):
self.npdschWoBcchMap.clear()
#36.213 16.4.1
#A UE shall upon detection on a given serving cell of a NPDCCH with DCI format N1, N2 ending in subframe n intended for the UE, decode, starting in n+5 DL subframe, the corresponding NPDSCH transmission in N consecutive NB-IoT DL subframe(s) ni with i = 0, 1, …, N-1 according to the NPDCCH information
hsfn, sfn, subf = incSubf(hsfn, sfn, subf, 5)
N = self.args['npdschNoBcchDciN1NumSf'] * self.args['npdschNoBcchDciN1NumRep']
k0 = self.args['npdschNoBcchDciN1K0']
#skip k0 NB-IoT DL subframes (scheduling delay)
markSubf = 0
for _subf in range(subf, self.subfPerRfNbDl):
if self.validateNbDlSubf(sfn, _subf):
k0 = k0 - 1
if k0 <= 0:
markSubf = _subf
break
while k0 > 0:
hsfn, sfn = incSfn(hsfn, sfn, 1)
for _subf in range(self.subfPerRfNbDl):
if self.validateNbDlSubf(sfn, _subf):
k0 = k0 - 1
if k0 <= 0:
markSubf = _subf
break
#find NPDSCH NB-IoT DL subframes n[0..N-1]
key = str(hsfn) + '_' + str(sfn)
for _subf in range(markSubf+1, self.subfPerRfNbDl):
if self.validateNbDlSubf(sfn, _subf):
if not ((key in self.sib2Map and _subf in self.sib2Map[key]) or (key in self.sib3Map and _subf in self.sib3Map[key])):
N = N - 1
if key in self.npdschWoBcchMap:
self.npdschWoBcchMap[key].append(_subf)
else:
self.npdschWoBcchMap[key] = [_subf]
if N == 0:
break
while N > 0:
hsfn, sfn = incSfn(hsfn, sfn, 1)
key = str(hsfn) + '_' + str(sfn)
for _subf in range(self.subfPerRfNbDl):
if self.validateNbDlSubf(sfn, _subf):
if not ((key in self.sib2Map and _subf in self.sib2Map[key]) or (key in self.sib3Map and _subf in self.sib3Map[key])):
N = N - 1
if key in self.npdschWoBcchMap:
self.npdschWoBcchMap[key].append(_subf)
else:
self.npdschWoBcchMap[key] = [_subf]
if N == 0:
break
incSubf和incSfn类似,用于递增n个子帧,调用方式为:hsfn, sfn, subf = incSubf(hsfn, sfn, subf, n)
fillNpdschWoBcch实现如下:
def fillNpdschWoBcch(self, hsfn, sfn):
dn = str(hsfn) + '_' + str(sfn)
if not dn in self.gridNbDl:
self.ngwin.logEdit.append('Call NgNbiotGrid.fillHostCrs at first to initialize NgNbiotGrid.gridNbDl!')
return
key = str(hsfn) + '_' + str(sfn)
if not key in self.npdschWoBcchMap:
return
self.ngwin.logEdit.append('recving NPDSCH w/o BCCH @ [HSFN=%d,SFN=%d]' % (hsfn, sfn))
slots = []
for subf in self.npdschWoBcchMap[key]:
slots.extend([2*subf, 2*subf+1])
#from 36.211 10.2.5.5
#...which meet all of the following criteria in the current subframe:
#- the subframe is not used for transmission of NPBCH, NPSS, or NSSS, and
#- they are assumed by the UE not to be used for NRS, and
#- they are not overlapping with resource elements used for CRS as defined in clause 6 (if any), and
#- the index l in the first slot in a subframe fulfills l >= l_Data_Start where l_Data_Start is given by clause 16.4.1.4 of 3GPP TS 36.213 [4].
for iap in range(self.args['nbDlAp']):
for islot in slots:
#l = CFI of host LTE in the first slot if a subframe
for isymb in range(self.args['hostLteCfi'] if islot % 2 == 0 else 0, self.symbPerSlotNb):
for isc in range(self.scNbDl):
if self.gridNbDl[dn][iap][isc][islot*self.symbPerSlotNb+isymb] == NbiotResType.NBIOT_RES_BLANK.value and self.args['hostLteGridDlNpdsch'][iap][self.args['nbInbandPrbIndDl'] * 12 + isc][islot*self.symbPerSlotNb+isymb] == LteResType.LTE_RES_PDSCH.value:
self.gridNbDl[dn][iap][isc][islot*self.symbPerSlotNb+isymb] = NbiotResType.NBIOT_RES_NPDSCH_WO_BCCH.value
#TODO: NPDSCH Gap to be implemented!
其中self.args['hostLteGridDlNpdsch']在NgNbiotGridUi中调用NgLteGrid时赋值:
#step 2: call NgLteGrid
lteGrid = NgLteGrid(self.ngwin, self.argsLte)
if lteGrid.isOk:
lteGrid.fillCrs()
#36.211 10.2.3.4 NPDSCH mapping
#- they are not overlapping with resource elements used for CRS as defined in clause 6 (if any),
#note the use of ndarray.copy()!
self.argsNbiot['hostLteGridDlNpdsch'] = lteGrid.gridDl.copy()
lteGrid.fillPbch()
lteGrid.fillSch()
#36.211 10.2.5.5 NPDCCH mapping
#- they are not overlapping with resource elements used for PBCH, PSS, SSS, or CRS as defined in clause 6 (if any),
#note the use of ndarray.copy()!
self.argsNbiot['hostLteGridDlNpdcch'] = lteGrid.gridDl.copy()