Handle TDD pattern 2 in UL TDA allocation

Add the possibility to use UL slots in TDD pattern 2. For simplicity, we
require the mixed slot to be of the same symbols in pattern 1 & 2. For
UL slots, simply use the right amount of UL TDAs, depending on which
number of UL slots among pattern 1 & 2 is bigger.

One complication is the TDA for the mixed slot. The current code assumes
that k2 has to be equal or larger than (number of DL slots +1) (because
the spec says min k2=2, but we might want to schedule DSUUU). Then,
there could be for instance the following cases:

- only pattern 1: DSUUU DSUUU ...: the mixed slot has to be reached an
  entire period in advance
- pattern 1 & 2: DSUUU DDDDD: normal mixed slot k2, e.g., like for 7DS2U
- pattern 1 & 2: DSUUU DDDSU: the mixed slot has to be reached
  N_ul2+N_dl1+1 slots in advance

I can't think of more cases right now. To avoid unscheduled slots, I put
an assertion (which could also trivially be taken out).
This commit is contained in:
Robert Schmidt
2025-08-14 12:50:03 +02:00
parent 135525c17a
commit c24673798a
2 changed files with 25 additions and 24 deletions
-4
View File
@@ -1206,10 +1206,6 @@ static NR_ServingCellConfigCommon_t *get_scc_config(configmodule_interface_t *cf
struct NR_TDD_UL_DL_ConfigCommon *tdd = scc->tdd_UL_DL_ConfigurationCommon;
tdd->pattern2 = calloc_or_fail(1, sizeof(*tdd->pattern2));
*scc->tdd_UL_DL_ConfigurationCommon->pattern2 = p2;
AssertFatal(p2.nrofUplinkSlots ^ scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots,
"UL slots in pattern1 (%ld) and pattern2 (%ld) are mutually exclusive (e.g. DDDFUU DDDD, DDDD DDDFUU)\n",
scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots,
p2.nrofUplinkSlots);
}
struct NR_FrequencyInfoDL *frequencyInfoDL = scc->downlinkConfigCommon->frequencyInfoDL;
LOG_I(RRC,
+25 -20
View File
@@ -1102,44 +1102,49 @@ void nr_rrc_config_ul_tda(NR_ServingCellConfigCommon_t *scc, int min_fb_delay, i
}
if (scc->tdd_UL_DL_ConfigurationCommon) {
int ul_symb = 0;
NR_TDD_UL_DL_Pattern_t *p1 = &scc->tdd_UL_DL_ConfigurationCommon->pattern1;
int ul_symb = p1->nrofUplinkSymbols;
NR_TDD_UL_DL_Pattern_t *p2 = scc->tdd_UL_DL_ConfigurationCommon->pattern2;
if (p2 && p2->nrofUplinkSymbols)
AssertFatal(p2->nrofUplinkSymbols == p1->nrofUplinkSymbols,
"nrofDownlinkSymbols in pattern1 %ld and pattern2 %ld must be the same in current implementation\n",
p1->nrofUplinkSymbols,
AssertFatal(p2->nrofUplinkSymbols == ul_symb,
"nrofDownlinkSymbols in pattern1 %d and pattern2 %ld must be the same in current implementation\n",
ul_symb,
p2->nrofUplinkSymbols);
if (p1->nrofUplinkSymbols) {
ul_symb = p1->nrofUplinkSymbols;
} else if (p2) {
ul_symb = p1->nrofUplinkSymbols;
}
AssertFatal(!p2 || p2->nrofDownlinkSlots >= p2->nrofUplinkSlots,
"nrofDownlinkSlots must be larger than nrofUplinkSlots for pattern2 in current implementation\n");
DevAssert(p2 == NULL);
int N_dl = p1->nrofDownlinkSlots;
int N_ul = p1->nrofUplinkSlots;
int N_dl1 = p1->nrofDownlinkSlots;
int N_ul1 = p1->nrofUplinkSlots;
int N_dl2 = p2 ? p2->nrofDownlinkSlots : 0;
int N_ul2 = p2 ? p2->nrofUplinkSlots : 0;
int tdd_period_idx = get_tdd_period_idx(scc->tdd_UL_DL_ConfigurationCommon);
int nb_periods_per_frame = get_nb_periods_per_frame(tdd_period_idx);
int nb_slots_per_period = ((1 << mu) * 10) / nb_periods_per_frame;
// make TDA for the mixed slot
if (ul_symb > 1 && k2 <= N_dl) {
// UL TDA index 2 for mixed slot (TDD)
long sliv = get_SLIV(NR_NUMBER_OF_SYMBOLS_PER_SLOT - ul_symb, ul_symb - 1);
tda = set_TimeDomainResourceAllocation(k2, sliv); // to be reached from suitable DL slot
long mixed_sliv = get_SLIV(NR_NUMBER_OF_SYMBOLS_PER_SLOT - ul_symb, ul_symb - 1);
if (ul_symb > 1 && (k2 <= N_dl1 || (p2 && N_ul2 == 0))) {
// UL TDA index 2 for mixed slot (TDD) (no pattern 2 and enough DL slots, or pattern2 only DL)
tda = set_TimeDomainResourceAllocation(k2, mixed_sliv); // to be reached from suitable DL slot
asn1cSeqAdd(&tda_list->list, tda);
} else if (ul_symb > 1) { // k2 > N_Dl
long sliv = get_SLIV(NR_NUMBER_OF_SYMBOLS_PER_SLOT - ul_symb, ul_symb - 1);
tda = set_TimeDomainResourceAllocation(nb_slots_per_period, sliv); // to be reached from last DL (mixed) slot, if any
} else if (ul_symb > 1 && !p2 && k2 > N_dl1) { // k2 > N_Dl1
// UL TDA for mixed slot without pattern 2 and less DL slots than k2
tda = set_TimeDomainResourceAllocation(nb_slots_per_period, mixed_sliv); // to be reached from last DL (mixed) slot, if any
asn1cSeqAdd(&tda_list->list, tda);
} else if (ul_symb > 1 && N_ul2 > 0 && k2 > N_dl1) {
// we have pattern 2 with UL, and less p1 DL slots than k2
tda = set_TimeDomainResourceAllocation(N_dl1 + N_ul2 + 1, mixed_sliv);
asn1cSeqAdd(&tda_list->list, tda);
} else {
AssertFatal(ul_symb == 0, "unhandled case of mixed slot: N_dl1 %d N_ul1 %d N_dl2 %d N_ul2 %d\n", N_dl1, N_ul1, N_dl2, N_ul2);
}
// make TDA for UL slots that are not reachable within k2/min_rxtxtime
int N_ul = max(N_ul1, N_ul2);
if (N_ul > k2) {
// enforce that with k2, we could reach all but one slot (which is mixed
// and taken into account above
AssertFatal(N_dl >= k2 - 1, "cannot fulfil TDD pattern: N_dl %d, k2 %d\n", N_dl, k2);
AssertFatal(N_dl1 >= k2 - 1, "cannot fulfil TDD pattern: N_dl1 %d, k2 %d\n", N_dl1, k2);
for (int i = k2 + 1; i <= N_ul; ++i) {
tda = set_TimeDomainResourceAllocation(i, get_SLIV(0, 13));
asn1cSeqAdd(&tda_list->list, tda);