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
This commit is contained in:
parent
f1a7b8fc66
commit
9e8593917f
|
@ -711,10 +711,14 @@ 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,
|
int Encoding::rlc_write_dl_data_header(const struct gprs_rlc_data_info *rlc,
|
||||||
uint8_t *data)
|
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 gprs_rlc_dl_header_egprs_3 *egprs3;
|
||||||
struct rlc_dl_header *gprs;
|
struct rlc_dl_header *gprs;
|
||||||
unsigned int e_fbi_header;
|
unsigned int e_fbi_header;
|
||||||
GprsCodingScheme cs = rlc->cs;
|
GprsCodingScheme cs = rlc->cs;
|
||||||
|
unsigned int offs;
|
||||||
|
unsigned int bsn_delta;
|
||||||
|
|
||||||
switch(cs.headerTypeData()) {
|
switch(cs.headerTypeData()) {
|
||||||
case GprsCodingScheme::HEADER_GPRS_DATA:
|
case GprsCodingScheme::HEADER_GPRS_DATA:
|
||||||
|
@ -733,6 +737,65 @@ int Encoding::rlc_write_dl_data_header(const struct gprs_rlc_data_info *rlc,
|
||||||
gprs->bsn = rlc->block_info[0].bsn;
|
gprs->bsn = rlc->block_info[0].bsn;
|
||||||
break;
|
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 */
|
||||||
|
|
||||||
|
bsn_delta = (rlc->block_info[1].bsn - rlc->block_info[0].bsn) &
|
||||||
|
(RLC_EGPRS_SNS - 1);
|
||||||
|
|
||||||
|
egprs1->bsn2_a = bsn_delta >> 0; /* 7 bits LSB */
|
||||||
|
egprs1->bsn2_b = bsn_delta >> 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:
|
case GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_3:
|
||||||
egprs3 = static_cast<struct gprs_rlc_dl_header_egprs_3 *>
|
egprs3 = static_cast<struct gprs_rlc_dl_header_egprs_3 *>
|
||||||
((void *)data);
|
((void *)data);
|
||||||
|
@ -758,10 +821,6 @@ int Encoding::rlc_write_dl_data_header(const struct gprs_rlc_data_info *rlc,
|
||||||
data[4] = (data[4] & 0b11111110) | (e_fbi_header >> 8);
|
data[4] = (data[4] & 0b11111110) | (e_fbi_header >> 8);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_1:
|
|
||||||
case GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_2:
|
|
||||||
/* TODO: Support both header types */
|
|
||||||
/* fall through */
|
|
||||||
default:
|
default:
|
||||||
LOGP(DRLCMACDL, LOGL_ERROR,
|
LOGP(DRLCMACDL, LOGL_ERROR,
|
||||||
"Encoding of uplink %s data blocks not yet supported.\n",
|
"Encoding of uplink %s data blocks not yet supported.\n",
|
||||||
|
|
10
src/rlc.cpp
10
src/rlc.cpp
|
@ -327,7 +327,8 @@ void gprs_rlc_data_block_info_init(struct gprs_rlc_data_block_info *rdbi,
|
||||||
rdbi->spb = 0;
|
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)) {
|
switch (GprsCodingScheme::Scheme(cs)) {
|
||||||
case GprsCodingScheme::MCS1: return 0b1011 + punct % 2;
|
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) +
|
case GprsCodingScheme::MCS3: return (with_padding ? 0b0110 : 0b0011) +
|
||||||
punct % 3;
|
punct % 3;
|
||||||
case GprsCodingScheme::MCS4: return 0b0000 + 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 + 4 * (punct % 3) + punct2 % 3;
|
||||||
default: ;
|
default: ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
32
src/rlc.h
32
src/rlc.h
|
@ -106,7 +106,8 @@ void gprs_rlc_data_info_init_ul(struct gprs_rlc_data_info *rlc,
|
||||||
GprsCodingScheme cs);
|
GprsCodingScheme cs);
|
||||||
void gprs_rlc_data_block_info_init(struct gprs_rlc_data_block_info *rdbi,
|
void gprs_rlc_data_block_info_init(struct gprs_rlc_data_block_info *rdbi,
|
||||||
GprsCodingScheme cs);
|
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
|
* I hold the currently transferred blocks and will provide
|
||||||
|
@ -300,6 +301,35 @@ struct gprs_rlc_ul_header_egprs_3 {
|
||||||
dummy:1;
|
dummy:1;
|
||||||
} __attribute__ ((packed));
|
} __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 {
|
struct gprs_rlc_dl_header_egprs_3 {
|
||||||
uint8_t usf:3,
|
uint8_t usf:3,
|
||||||
es_p:2,
|
es_p:2,
|
||||||
|
|
|
@ -545,7 +545,8 @@ struct msgb *gprs_rlcmac_dl_tbf::create_dl_acked_block(
|
||||||
rlc.usf = 7; /* will be set at scheduler */
|
rlc.usf = 7; /* will be set at scheduler */
|
||||||
rlc.pr = 0; /* FIXME: power reduction */
|
rlc.pr = 0; /* FIXME: power reduction */
|
||||||
rlc.tfi = m_tfi; /* TFI */
|
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;
|
rlc.block_info[data_block_idx] = m_rlc.block(index)->block_info;
|
||||||
rdbi = &rlc.block_info[data_block_idx];
|
rdbi = &rlc.block_info[data_block_idx];
|
||||||
|
|
Loading…
Reference in New Issue