diff options
author | Jacob Erlbeck <jerlbeck@sysmocom.de> | 2016-02-02 11:48:37 +0100 |
---|---|---|
committer | Jacob Erlbeck <jerlbeck@sysmocom.de> | 2016-02-02 17:06:39 +0100 |
commit | 1a880da4f9548145dfc8cbe54fd7f6c3eb9edc1b (patch) | |
tree | 2b32fc38ca57b87e96ac0dd1a6ea9719b33742cf /src | |
parent | 205a943205ac2c65e14c012bac8c936a6a642c44 (diff) |
rlc: Support encoding of EGPRS header type 1 + 2
Currently only header type 3 (MCS-1 to MCS-4) is supported.
Add header structs to rlc.h and extend
Encoding::rlc_write_dl_data_header accordingly.
Sponsored-by: On-Waves ehf
Diffstat (limited to 'src')
-rw-r--r-- | src/encoding.cpp | 63 | ||||
-rw-r--r-- | src/rlc.cpp | 10 | ||||
-rw-r--r-- | src/rlc.h | 32 | ||||
-rw-r--r-- | src/tbf_dl.cpp | 3 |
4 files changed, 100 insertions, 8 deletions
diff --git a/src/encoding.cpp b/src/encoding.cpp index e3e1245e..7a6abb75 100644 --- a/src/encoding.cpp +++ b/src/encoding.cpp @@ -711,10 +711,13 @@ unsigned Encoding::write_repeated_page_info(bitvec * dest, unsigned& wp, uint8_t int Encoding::rlc_write_dl_data_header(const struct gprs_rlc_data_info *rlc, uint8_t *data) { + struct gprs_rlc_dl_header_egprs_1 *egprs1; + struct gprs_rlc_dl_header_egprs_2 *egprs2; struct gprs_rlc_dl_header_egprs_3 *egprs3; struct rlc_dl_header *gprs; unsigned int e_fbi_header; GprsCodingScheme cs = rlc->cs; + unsigned int offs; switch(cs.headerTypeData()) { case GprsCodingScheme::HEADER_GPRS_DATA: @@ -733,6 +736,62 @@ int Encoding::rlc_write_dl_data_header(const struct gprs_rlc_data_info *rlc, gprs->bsn = rlc->block_info[0].bsn; break; + case GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_1: + egprs1 = static_cast<struct gprs_rlc_dl_header_egprs_1 *> + ((void *)data); + + egprs1->usf = rlc->usf; + egprs1->es_p = rlc->es_p; + egprs1->rrbp = rlc->rrbp; + egprs1->tfi_a = rlc->tfi >> 0; /* 1 bit LSB */ + egprs1->tfi_b = rlc->tfi >> 1; /* 4 bits */ + egprs1->pr = rlc->pr; + egprs1->cps = rlc->cps; + + egprs1->bsn1_a = rlc->block_info[0].bsn >> 0; /* 2 bits LSB */ + egprs1->bsn1_b = rlc->block_info[0].bsn >> 2; /* 8 bits */ + egprs1->bsn1_c = rlc->block_info[0].bsn >> 10; /* 1 bit */ + + egprs1->bsn2_a = rlc->block_info[1].bsn >> 0; /* 7 bits LSB */ + egprs1->bsn2_b = rlc->block_info[1].bsn >> 7; /* 3 bits */ + + /* first FBI/E header */ + e_fbi_header = rlc->block_info[0].e ? 0x01 : 0; + e_fbi_header |= rlc->block_info[0].cv == 0 ? 0x02 : 0; /* FBI */ + e_fbi_header <<= 0; + data[5] = (data[5] & 0b11111100) | e_fbi_header; + + /* second FBI/E header */ + e_fbi_header = rlc->block_info[1].e ? 0x01 : 0; + e_fbi_header |= rlc->block_info[1].cv == 0 ? 0x02 : 0; /* FBI */ + offs = rlc->data_offs_bits[1] / 8; + OSMO_ASSERT(rlc->data_offs_bits[1] % 8 == 4); + e_fbi_header <<= 2; + data[offs] = (data[offs] & 0b11110011) | e_fbi_header; + break; + + case GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_2: + egprs2 = static_cast<struct gprs_rlc_dl_header_egprs_2 *> + ((void *)data); + + egprs2->usf = rlc->usf; + egprs2->es_p = rlc->es_p; + egprs2->rrbp = rlc->rrbp; + egprs2->tfi_a = rlc->tfi >> 0; /* 1 bit LSB */ + egprs2->tfi_b = rlc->tfi >> 1; /* 4 bits */ + egprs2->pr = rlc->pr; + egprs2->cps = rlc->cps; + + egprs2->bsn1_a = rlc->block_info[0].bsn >> 0; /* 2 bits LSB */ + egprs2->bsn1_b = rlc->block_info[0].bsn >> 2; /* 8 bits */ + egprs2->bsn1_c = rlc->block_info[0].bsn >> 10; /* 1 bit */ + + e_fbi_header = rlc->block_info[0].e ? 0x01 : 0; + e_fbi_header |= rlc->block_info[0].cv == 0 ? 0x02 : 0; /* FBI */ + e_fbi_header <<= 4; + data[3] = (data[3] & 0b11001111) | e_fbi_header; + break; + case GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_3: egprs3 = static_cast<struct gprs_rlc_dl_header_egprs_3 *> ((void *)data); @@ -758,10 +817,6 @@ int Encoding::rlc_write_dl_data_header(const struct gprs_rlc_data_info *rlc, data[4] = (data[4] & 0b11111110) | (e_fbi_header >> 8); break; - case GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_1: - case GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_2: - /* TODO: Support both header types */ - /* fall through */ default: LOGP(DRLCMACDL, LOGL_ERROR, "Encoding of uplink %s data blocks not yet supported.\n", diff --git a/src/rlc.cpp b/src/rlc.cpp index e4a9563a..31cea4c8 100644 --- a/src/rlc.cpp +++ b/src/rlc.cpp @@ -327,7 +327,8 @@ void gprs_rlc_data_block_info_init(struct gprs_rlc_data_block_info *rdbi, rdbi->spb = 0; } -unsigned int gprs_rlc_mcs_cps(GprsCodingScheme cs, int punct, int with_padding) +unsigned int gprs_rlc_mcs_cps(GprsCodingScheme cs, int punct, int punct2, + int with_padding) { switch (GprsCodingScheme::Scheme(cs)) { case GprsCodingScheme::MCS1: return 0b1011 + punct % 2; @@ -335,7 +336,12 @@ unsigned int gprs_rlc_mcs_cps(GprsCodingScheme cs, int punct, int with_padding) case GprsCodingScheme::MCS3: return (with_padding ? 0b0110 : 0b0011) + punct % 3; case GprsCodingScheme::MCS4: return 0b0000 + punct % 3; - /* TODO: Add missing MCS */ + case GprsCodingScheme::MCS5: return 0b100 + punct % 2; + case GprsCodingScheme::MCS6: return (with_padding ? 0b010 : 0b000) + + punct % 2; + case GprsCodingScheme::MCS7: return 0b10100 + 3 * (punct % 3) + punct2 % 3; + case GprsCodingScheme::MCS8: return 0b01011 + 3 * (punct % 3) + punct2 % 3; + case GprsCodingScheme::MCS9: return 0b00000 + 3 * (punct % 3) + punct2 % 3; default: ; } @@ -106,7 +106,8 @@ void gprs_rlc_data_info_init_ul(struct gprs_rlc_data_info *rlc, GprsCodingScheme cs); void gprs_rlc_data_block_info_init(struct gprs_rlc_data_block_info *rdbi, GprsCodingScheme cs); -unsigned int gprs_rlc_mcs_cps(GprsCodingScheme cs, int punct, int with_padding); +unsigned int gprs_rlc_mcs_cps(GprsCodingScheme cs, int punct, int punct2, + int with_padding); /* * I hold the currently transferred blocks and will provide @@ -300,6 +301,35 @@ struct gprs_rlc_ul_header_egprs_3 { dummy:1; } __attribute__ ((packed)); +struct gprs_rlc_dl_header_egprs_1 { + uint8_t usf:3, + es_p:2, + rrbp:2, + tfi_a:1; + uint8_t tfi_b:4, + pr:2, + bsn1_a:2; + uint8_t bsn1_b:8; + uint8_t bsn1_c:1, + bsn2_a:7; + uint8_t bsn2_b:3, + cps:5; +} __attribute__ ((packed)); + +struct gprs_rlc_dl_header_egprs_2 { + uint8_t usf:3, + es_p:2, + rrbp:2, + tfi_a:1; + uint8_t tfi_b:4, + pr:2, + bsn1_a:2; + uint8_t bsn1_b:8; + uint8_t bsn1_c:1, + cps:3, + dummy:4; +} __attribute__ ((packed)); + struct gprs_rlc_dl_header_egprs_3 { uint8_t usf:3, es_p:2, diff --git a/src/tbf_dl.cpp b/src/tbf_dl.cpp index c4027d7c..2d8b4fed 100644 --- a/src/tbf_dl.cpp +++ b/src/tbf_dl.cpp @@ -545,7 +545,8 @@ struct msgb *gprs_rlcmac_dl_tbf::create_dl_acked_block( rlc.usf = 7; /* will be set at scheduler */ rlc.pr = 0; /* FIXME: power reduction */ rlc.tfi = m_tfi; /* TFI */ - rlc.cps = gprs_rlc_mcs_cps(cs, 0, 0); + /* TODO: Use real puncturing values */ + rlc.cps = gprs_rlc_mcs_cps(cs, 0, 0, 0); rlc.block_info[data_block_idx] = m_rlc.block(index)->block_info; rdbi = &rlc.block_info[data_block_idx]; |