aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/rlc.cpp74
-rw-r--r--src/rlc.h6
-rw-r--r--src/tbf_dl.cpp25
3 files changed, 101 insertions, 4 deletions
diff --git a/src/rlc.cpp b/src/rlc.cpp
index 6ea1597..6770043 100644
--- a/src/rlc.cpp
+++ b/src/rlc.cpp
@@ -399,3 +399,77 @@ void gprs_rlc_mcs_cps_decode(unsigned int cps,
default: ;
}
}
+
+/*
+ * Finds the PS value for retransmission with MCS change,
+ * retransmission with no MCS change, fresh transmission cases.
+ * The return value shall be used for current transmission only
+ * 44.060 9.3.2.1 defines the PS selection for MCS change case
+ * cs_current is the output of MCS selection algorithm for retx
+ * cs is coding scheme of previous transmission of RLC data block
+ */
+enum egprs_puncturing_values gprs_get_punct_scheme(
+ enum egprs_puncturing_values punct,
+ const GprsCodingScheme &cs,
+ const GprsCodingScheme &cs_current)
+{
+ /* TS 44.060 9.3.2.1.1 */
+ if ((GprsCodingScheme::Scheme(cs) == GprsCodingScheme::MCS9) &&
+ (GprsCodingScheme::Scheme(cs_current) == GprsCodingScheme::MCS6)) {
+ if ((punct == EGPRS_PS_1) || (punct == EGPRS_PS_3))
+ return EGPRS_PS_1;
+ else if (punct == EGPRS_PS_2)
+ return EGPRS_PS_2;
+ } else if ((GprsCodingScheme::Scheme(cs) == GprsCodingScheme::MCS6) &&
+ (GprsCodingScheme::Scheme(cs_current) == GprsCodingScheme::MCS9)) {
+ if (punct == EGPRS_PS_1)
+ return EGPRS_PS_3;
+ else if (punct == EGPRS_PS_2)
+ return EGPRS_PS_2;
+ } else if ((GprsCodingScheme::Scheme(cs) == GprsCodingScheme::MCS7) &&
+ (GprsCodingScheme::Scheme(cs_current) == GprsCodingScheme::MCS5))
+ return EGPRS_PS_1;
+ else if ((GprsCodingScheme::Scheme(cs) == GprsCodingScheme::MCS5) &&
+ (GprsCodingScheme::Scheme(cs_current) == GprsCodingScheme::MCS7))
+ return EGPRS_PS_2;
+ else if (cs != cs_current)
+ return EGPRS_PS_1;
+ /* TS 44.060 9.3.2.1.1 ends here */
+ /*
+ * Below else will handle fresh transmission, retransmission with no
+ * MCS change case
+ */
+ else
+ return punct;
+ return EGPRS_PS_INVALID;
+}
+
+/*
+ * This function calculates puncturing scheme for retransmission of a RLC
+ * block with same MCS. The computed value shall be used for next transmission
+ * of the same RLC block
+ * TS 44.060 10.4.8a.3.1, 10.4.8a.2.1, 10.4.8a.1.1
+ */
+void gprs_update_punct_scheme(enum egprs_puncturing_values *punct,
+ const GprsCodingScheme &cs)
+{
+ switch (GprsCodingScheme::Scheme(cs)) {
+ case GprsCodingScheme::MCS1 :
+ case GprsCodingScheme::MCS2 :
+ case GprsCodingScheme::MCS5 :
+ case GprsCodingScheme::MCS6 :
+ *punct = ((enum egprs_puncturing_values)((*punct + 1) %
+ EGPRS_MAX_PS_NUM_2));
+ break;
+ case GprsCodingScheme::MCS3 :
+ case GprsCodingScheme::MCS4 :
+ case GprsCodingScheme::MCS7 :
+ case GprsCodingScheme::MCS8 :
+ case GprsCodingScheme::MCS9 :
+ *punct = ((enum egprs_puncturing_values)((*punct + 1) %
+ EGPRS_MAX_PS_NUM_3));
+ break;
+ default:
+ break;
+ }
+}
diff --git a/src/rlc.h b/src/rlc.h
index 6a8fd29..8f75588 100644
--- a/src/rlc.h
+++ b/src/rlc.h
@@ -136,7 +136,11 @@ unsigned int gprs_rlc_mcs_cps(GprsCodingScheme cs, enum egprs_puncturing_values
punct, enum egprs_puncturing_values punct2, int with_padding);
void gprs_rlc_mcs_cps_decode(unsigned int cps, GprsCodingScheme cs,
int *punct, int *punct2, int *with_padding);
-
+enum egprs_puncturing_values gprs_get_punct_scheme(enum egprs_puncturing_values
+ punct, const GprsCodingScheme &cs,
+ const GprsCodingScheme &cs_current_trans);
+void gprs_update_punct_scheme(enum egprs_puncturing_values *punct,
+ const GprsCodingScheme &cs);
/*
* I hold the currently transferred blocks and will provide
* the routines to manipulate these arrays.
diff --git a/src/tbf_dl.cpp b/src/tbf_dl.cpp
index 56dedd0..9e4d078 100644
--- a/src/tbf_dl.cpp
+++ b/src/tbf_dl.cpp
@@ -587,6 +587,7 @@ struct msgb *gprs_rlcmac_dl_tbf::create_dl_acked_block(
bool is_final = false;
gprs_rlc_data_info rlc;
GprsCodingScheme cs;
+ GprsCodingScheme cs_current_trans;
int bsns[ARRAY_SIZE(rlc.block_info)];
unsigned num_bsns;
enum egprs_puncturing_values punct[ARRAY_SIZE(rlc.block_info)];
@@ -638,6 +639,7 @@ struct msgb *gprs_rlcmac_dl_tbf::create_dl_acked_block(
GprsCodingScheme cs_enc;
uint8_t *block_data;
gprs_rlc_data_block_info *rdbi, *block_info;
+ enum egprs_puncturing_values punct_scheme;
/* Check if there are more blocks than BSNs */
if (data_block_idx < num_bsns)
@@ -650,9 +652,19 @@ struct msgb *gprs_rlcmac_dl_tbf::create_dl_acked_block(
/* get data and header from current block */
block_data = m_rlc.block(bsn)->block;
- /* TODO: Use real puncturing values */
- punct[data_block_idx] =
- (enum egprs_puncturing_values) data_block_idx;
+ /* TODO: Need to support MCS change during retx */
+ cs_current_trans = cs;
+
+ /* Get current puncturing scheme from block */
+ punct_scheme = gprs_get_punct_scheme(
+ m_rlc.block(bsn)->next_ps,
+ cs, cs_current_trans);
+
+ if (cs.isEgprs()) {
+ OSMO_ASSERT(punct_scheme >= EGPRS_PS_1);
+ OSMO_ASSERT(punct_scheme <= EGPRS_PS_3);
+ }
+ punct[data_block_idx] = punct_scheme;
rdbi = &rlc.block_info[data_block_idx];
block_info = &m_rlc.block(bsn)->block_info;
@@ -665,6 +677,13 @@ struct msgb *gprs_rlcmac_dl_tbf::create_dl_acked_block(
data_block_idx, bsn, cs_enc.name());
OSMO_ASSERT(rdbi->data_len == m_rlc.block(bsn)->len);
}
+
+ /* TODO: Need to handle 2 same bsns
+ * in header type 1
+ */
+ gprs_update_punct_scheme(&m_rlc.block(bsn)->next_ps,
+ cs_current_trans);
+
rdbi->e = block_info->e;
rdbi->cv = block_info->cv;
rdbi->bsn = bsn;