diff options
author | Andreas Eversberg <jolly@eversberg.eu> | 2013-03-14 07:57:07 +0100 |
---|---|---|
committer | Harald Welte <laforge@gnumonks.org> | 2015-09-22 16:41:27 +0200 |
commit | 917cf7018b6a9ec778add719fcec1692f0e35931 (patch) | |
tree | 9bee76907128100a2182d406e0165fd8d4e2c137 /src | |
parent | 84b9a445351937703334629f3fec02689153f986 (diff) |
TRX: Add support for EFR transcoding
Diffstat (limited to 'src')
-rw-r--r-- | src/osmo-bts-trx/gsm0503_coding.c | 131 | ||||
-rw-r--r-- | src/osmo-bts-trx/gsm0503_coding.h | 2 | ||||
-rw-r--r-- | src/osmo-bts-trx/gsm0503_parity.c | 13 | ||||
-rw-r--r-- | src/osmo-bts-trx/gsm0503_parity.h | 1 | ||||
-rw-r--r-- | src/osmo-bts-trx/gsm0503_tables.c | 12 | ||||
-rw-r--r-- | src/osmo-bts-trx/gsm0503_tables.h | 1 | ||||
-rw-r--r-- | src/osmo-bts-trx/scheduler.c | 30 |
7 files changed, 181 insertions, 9 deletions
diff --git a/src/osmo-bts-trx/gsm0503_coding.c b/src/osmo-bts-trx/gsm0503_coding.c index 5ceb1d58..3f4ae159 100644 --- a/src/osmo-bts-trx/gsm0503_coding.c +++ b/src/osmo-bts-trx/gsm0503_coding.c @@ -300,7 +300,7 @@ int pdtch_encode(ubit_t *bursts, uint8_t *l2_data, uint8_t l2_len) /* - * GSM TCH/F FR transcoding + * GSM TCH/F FR/EFR transcoding */ static void tch_fr_reassemble(uint8_t *tch_data, ubit_t *b_bits, int net_order) @@ -338,6 +338,35 @@ static void tch_fr_reassemble(uint8_t *tch_data, ubit_t *b_bits, int net_order) } } +static void tch_efr_reassemble(uint8_t *tch_data, ubit_t *b_bits) +{ + int i, j; + + tch_data[0] = 0xc << 4; + memset(tch_data + 1, 0, 30); + + i = 0; /* counts bits */ + j = 4; /* counts output bits */ + while (i < 244) { + tch_data[j>>3] |= (b_bits[i] << (7-(j&7))); + i++; + j++; + } +} + +static void tch_efr_disassemble(ubit_t *b_bits, uint8_t *tch_data) +{ + int i, j; + + i = 0; /* counts bits */ + j = 4; /* counts output bits */ + while (i < 244) { + b_bits[i] = (tch_data[j>>3] >> (7-(j&7))) & 1; + i++; + j++; + } +} + static void tch_fr_disassemble(ubit_t *b_bits, uint8_t *tch_data, int net_order) { int i, j, k, l, o; @@ -386,6 +415,30 @@ static void tch_fr_b_to_d(ubit_t *d_bits, ubit_t *b_bits) d_bits[i] = b_bits[gsm610_bitorder[i]]; } +static void tch_efr_d_to_w(ubit_t *b_bits, ubit_t *d_bits) +{ + int i; + + for (i = 0; i < 260; i++) + b_bits[gsm660_bitorder[i]] = d_bits[i]; +} + +static void tch_efr_w_to_d(ubit_t *d_bits, ubit_t *b_bits) +{ + int i; + + for (i = 0; i < 260; i++) + d_bits[i] = b_bits[gsm660_bitorder[i]]; +} + +static void tch_efr_protected(ubit_t *s_bits, ubit_t *b_bits) +{ + int i; + + for (i = 0; i < 65; i++) + b_bits[i] = s_bits[gsm0503_gsm_efr_protected_bits[i]-1]; +} + static void tch_fr_unreorder(ubit_t *d, ubit_t *p, ubit_t *u) { int i; @@ -410,10 +463,43 @@ static void tch_fr_reorder(ubit_t *u, ubit_t *d, ubit_t *p) u[91+i] = p[i]; } -int tch_fr_decode(uint8_t *tch_data, sbit_t *bursts, int net_order) +static void tch_efr_reorder(ubit_t *w, ubit_t *s, ubit_t *p) +{ + memcpy(w, s, 71); + w[71] = w[72] = s[69]; + memcpy(w+73, s+71, 50); + w[123] = w[124] = s[119]; + memcpy(w+125, s+121, 53); + w[178] = w[179] = s[172]; + memcpy(w+180, s+174, 50); + w[230] = w[231] = s[222]; + memcpy(w+232, s+224, 20); + memcpy(w+252, p, 8); +} + +static void tch_efr_unreorder(ubit_t *s, ubit_t *p, ubit_t *w) +{ + int sum; + + memcpy(s, w, 71); + sum = s[69] + w[71] + w[72]; + s[69] = (sum > 2); + memcpy(s+71, w+73, 50); + sum = s[119] + w[123] + w[124]; + s[119] = (sum > 2); + memcpy(s+121, w+125, 53); + sum = s[172] + w[178] + w[179]; + s[172] = (sum > 2); + memcpy(s+174, w+180, 50); + sum = s[220] + w[230] + w[231]; + s[222] = (sum > 2); + memcpy(s+224, w+232, 20); + memcpy(p, w+252, 8); +} +int tch_fr_decode(uint8_t *tch_data, sbit_t *bursts, int net_order, int efr) { sbit_t iB[912], cB[456], h; - ubit_t conv[185], b[260], d[260], p[3]; + ubit_t conv[185], s[244], w[260], b[65], d[260], p[8]; int i, rv, len, steal = 0; for (i=0; i<8; i++) { @@ -444,11 +530,28 @@ int tch_fr_decode(uint8_t *tch_data, sbit_t *bursts, int net_order) return -1; - tch_fr_d_to_b(b, d); + if (efr) { + tch_efr_d_to_w(w, d); - tch_fr_reassemble(tch_data, b, net_order); + tch_efr_unreorder(s, p, w); - len = 33; + tch_efr_protected(s, b); + + rv = osmo_crc8gen_check_bits(&gsm0503_tch_efr_crc8, b, + 65, p); + if (rv) + return -1; + + tch_efr_reassemble(tch_data, s); + + len = 31; + } else { + tch_fr_d_to_b(w, d); + + tch_fr_reassemble(tch_data, w, net_order); + + len = 33; + } return len; } @@ -456,15 +559,29 @@ int tch_fr_decode(uint8_t *tch_data, sbit_t *bursts, int net_order) int tch_fr_encode(ubit_t *bursts, uint8_t *tch_data, int len, int net_order) { ubit_t iB[912], cB[456], h; - ubit_t conv[185], w[260], d[260], p[8]; + ubit_t conv[185], w[260], b[65], s[244], d[260], p[8]; int i; switch (len) { + case 31: /* TCH EFR */ + + tch_efr_disassemble(s, tch_data); + + tch_efr_protected(s, b); + + osmo_crc8gen_set_bits(&gsm0503_tch_efr_crc8, b, 65, p); + + tch_efr_reorder(w, s, p); + + tch_efr_w_to_d(d, w); + + goto coding_efr_fr; case 33: /* TCH FR */ tch_fr_disassemble(w, tch_data, net_order); tch_fr_b_to_d(d, w); +coding_efr_fr: osmo_crc8gen_set_bits(&gsm0503_tch_fr_crc3, d, 50, p); tch_fr_reorder(conv, d, p); diff --git a/src/osmo-bts-trx/gsm0503_coding.h b/src/osmo-bts-trx/gsm0503_coding.h index 240b2c07..96b162f3 100644 --- a/src/osmo-bts-trx/gsm0503_coding.h +++ b/src/osmo-bts-trx/gsm0503_coding.h @@ -5,7 +5,7 @@ int xcch_decode(uint8_t *l2_data, sbit_t *bursts); int xcch_encode(ubit_t *bursts, uint8_t *l2_data); int pdtch_decode(uint8_t *l2_data, sbit_t *bursts, uint8_t *usf_p); int pdtch_encode(ubit_t *bursts, uint8_t *l2_data, uint8_t l2_len); -int tch_fr_decode(uint8_t *tch_data, sbit_t *bursts, int net_order); +int tch_fr_decode(uint8_t *tch_data, sbit_t *bursts, int net_order, int efr); int tch_fr_encode(ubit_t *bursts, uint8_t *tch_data, int len, int net_order); int rach_decode(uint8_t *ra, sbit_t *burst, uint8_t bsic); int rach_encode(ubit_t *burst, uint8_t *ra, uint8_t bsic); diff --git a/src/osmo-bts-trx/gsm0503_parity.c b/src/osmo-bts-trx/gsm0503_parity.c index 1ecadcc7..cbb2bf0b 100644 --- a/src/osmo-bts-trx/gsm0503_parity.c +++ b/src/osmo-bts-trx/gsm0503_parity.c @@ -75,3 +75,16 @@ const struct osmo_crc8gen_code gsm0503_tch_fr_crc3 = { .remainder = 0x7, }; +/* + * GSM TCH EFR parity + * + * g(x) = x^8 + x^4 + x^3 + x^2 + 1 + */ + +const struct osmo_crc8gen_code gsm0503_tch_efr_crc8 = { + .bits = 8, + .poly = 0x1d, + .init = 0x00, + .remainder = 0x00, +}; + diff --git a/src/osmo-bts-trx/gsm0503_parity.h b/src/osmo-bts-trx/gsm0503_parity.h index 50d14bfc..e3678b22 100644 --- a/src/osmo-bts-trx/gsm0503_parity.h +++ b/src/osmo-bts-trx/gsm0503_parity.h @@ -6,5 +6,6 @@ const struct osmo_crc16gen_code gsm0503_cs234_crc16; const struct osmo_crc8gen_code gsm0503_rach_crc6; const struct osmo_crc16gen_code gsm0503_sch_crc10; const struct osmo_crc8gen_code gsm0503_tch_fr_crc3; +const struct osmo_crc8gen_code gsm0503_tch_efr_crc8; #endif /* _0503_PARITY_H */ diff --git a/src/osmo-bts-trx/gsm0503_tables.c b/src/osmo-bts-trx/gsm0503_tables.c index 8ab6060b..837cc68e 100644 --- a/src/osmo-bts-trx/gsm0503_tables.c +++ b/src/osmo-bts-trx/gsm0503_tables.c @@ -109,3 +109,15 @@ const uint8_t gsm0503_gsm_fr_map[76] = { 3, 3, 3, 3 }; +/* this table describes the 65 most importaint bits from EFR coded + * bits as indicated in TS 05.03 (3.1.1.1) */ +const uint8_t gsm0503_gsm_efr_protected_bits[65] = { + 39, 40, 41, 42, 43, 44, 48, 87, 45, 2, + 3, 8, 10, 18, 19, 24, 46, 47,142,143, + 144,145,146,147, 92, 93,195,196, 98,137, + 148, 94,197,149,150, 95,198, 4, 5, 11, + 12, 16, 9, 6, 7, 13, 17, 20, 96,199, + 1, 14, 15, 21, 25, 26, 28,151,201,190, + 240, 88,138,191,241 +}; + diff --git a/src/osmo-bts-trx/gsm0503_tables.h b/src/osmo-bts-trx/gsm0503_tables.h index 827fded4..66f325bf 100644 --- a/src/osmo-bts-trx/gsm0503_tables.h +++ b/src/osmo-bts-trx/gsm0503_tables.h @@ -9,5 +9,6 @@ extern const sbit_t gsm0503_usf2twelve_sbit[8][12]; extern const uint8_t gsm0503_puncture_cs2[588]; extern const uint8_t gsm0503_puncture_cs3[676]; extern const uint8_t gsm0503_gsm_fr_map[76]; +extern const uint8_t gsm0503_gsm_efr_protected_bits[65]; #endif /* _0503_TABLES_H */ diff --git a/src/osmo-bts-trx/scheduler.c b/src/osmo-bts-trx/scheduler.c index 023be372..f1a0b629 100644 --- a/src/osmo-bts-trx/scheduler.c +++ b/src/osmo-bts-trx/scheduler.c @@ -779,7 +779,14 @@ static void tx_tch_common(struct trx_l1h *l1h, uint8_t tn, uint32_t fn, memset(tch_data, 0, 33); len = 33; break; + case GSM48_CMODE_SPEECH_EFR: /* EFR */ + if (chan != TRXC_TCHF) + goto inval_mode1; + memset(tch_data, 0, 31); + len = 31; + break; default: +inval_mode1: LOGP(DL1C, LOGL_ERROR, "TCH mode invalid, please " "fix!\n"); len = 0; @@ -857,7 +864,21 @@ static void tx_tch_common(struct trx_l1h *l1h, uint8_t tn, uint32_t fn, goto free_bad_msg; } break; + case GSM48_CMODE_SPEECH_EFR: /* EFR */ + if (chan != TRXC_TCHF) + goto inval_mode2; + len = 31; + if (msgb_l2len(msg_tch) >= 1 + && (msg_tch->l2h[0] >> 4) != 0xc) { + LOGP(DL1C, LOGL_NOTICE, "%s Transmitting 'bad " + "EFR frame' trx=%u ts=%u at fn=%u.\n", + trx_chan_desc[chan].name, + l1h->trx->nr, tn, fn); + goto free_bad_msg; + } + break; default: +inval_mode2: LOGP(DL1C, LOGL_ERROR, "TCH mode invalid, please " "fix!\n"); goto free_bad_msg; @@ -1185,7 +1206,10 @@ static int rx_tchf_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn, switch ((rsl_cmode != RSL_CMOD_SPD_SPEECH) ? GSM48_CMODE_SPEECH_V1 : tch_mode) { case GSM48_CMODE_SPEECH_V1: /* FR */ - rc = tch_fr_decode(tch_data, *bursts_p, 1); + rc = tch_fr_decode(tch_data, *bursts_p, 1, 0); + break; + case GSM48_CMODE_SPEECH_EFR: /* EFR */ + rc = tch_fr_decode(tch_data, *bursts_p, 1, 1); break; default: LOGP(DL1C, LOGL_ERROR, "TCH mode %u invalid, please fix!\n", @@ -1217,6 +1241,10 @@ bfi: memset(tch_data, 0, 33); rc = 33; break; + case GSM48_CMODE_SPEECH_EFR: /* EFR */ + memset(tch_data, 0, 31); + rc = 31; + break; default: LOGP(DL1C, LOGL_ERROR, "TCH mode invalid, " "please fix!\n"); |