aboutsummaryrefslogtreecommitdiffstats
path: root/src/osmo-bts-trx/tch_fr.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/osmo-bts-trx/tch_fr.c')
-rw-r--r--src/osmo-bts-trx/tch_fr.c365
1 files changed, 0 insertions, 365 deletions
diff --git a/src/osmo-bts-trx/tch_fr.c b/src/osmo-bts-trx/tch_fr.c
deleted file mode 100644
index 23130e94..00000000
--- a/src/osmo-bts-trx/tch_fr.c
+++ /dev/null
@@ -1,365 +0,0 @@
-/*
- * tch_fr.c
- *
- * Copyright (c) 2013 Andreas Eversberg <jolly@eversberg.eu>
- */
-
-#include <stdio.h>
-#include <stdint.h>
-#include <string.h>
-
-#include <osmocom/core/bits.h>
-#include <osmocom/core/conv.h>
-#include <osmocom/core/crcgen.h>
-
-#include "xcch.h"
-#include "tch_fr.h"
-
-
-/*
- * GSM TCH FR/EFR parity
- *
- * g(x) = x^3 + x + 1
- */
-
-const struct osmo_crc8gen_code tch_fr_crc3 = {
- .bits = 3,
- .poly = 0x3,
- .init = 0x0,
- .remainder = 0x7,
-};
-
-
-/*
- * GSM TCH FR/EFR convolutional coding
- *
- * G_0 = 1 + x^3 + x^4
- * G_1 = 1 + x + x^3 + x^4
- */
-
-static const uint8_t conv_tch_fr_next_output[][2] = {
- { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 },
- { 3, 0 }, { 2, 1 }, { 3, 0 }, { 2, 1 },
- { 3, 0 }, { 2, 1 }, { 3, 0 }, { 2, 1 },
- { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 },
-};
-
-static const uint8_t conv_tch_fr_next_state[][2] = {
- { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 },
- { 8, 9 }, { 10, 11 }, { 12, 13 }, { 14, 15 },
- { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 },
- { 8, 9 }, { 10, 11 }, { 12, 13 }, { 14, 15 },
-};
-
-static const struct osmo_conv_code conv_tch_fr = {
- .N = 2,
- .K = 5,
- .len = 185,
- .next_output = conv_tch_fr_next_output,
- .next_state = conv_tch_fr_next_state,
-};
-
-
-/*
- * GSM TCH FR/EFR interleaving and burst mapping
- *
- * Interleaving:
- *
- * Given 456 coded input bits, form 8 blocks of 114 bits,
- * where event bits of the first 4 block and off bits of the last 4 block
- * are used:
- *
- * i(B, j) = c(n, k) k = 0, ..., 455
- * n = 0, ..., N, N + 1, ...
- * B = B_0 + 4n + (k mod 8)
- * j = 2(49k mod 57) + ((k mod 8) div 4)
- *
- * Mapping on Burst:
- *
- * e(B, j) = i(B, j)
- * e(B, 59 + j) = i(B, 57 + j) j = 0, ..., 56
- * e(B, 57) = h_l(B)
- * e(B, 58) = h_n(B)
- *
- * Where hl(B) and hn(B) are bits in burst B indicating flags.
- */
-
-static void
-tch_fr_deinterleave(sbit_t *cB, sbit_t *iB)
-{
- int j, k, B;
-
- for (k=0; k<456; k++) {
- B = k & 7;
- j = 2 * ((49 * k) % 57) + ((k & 7) >> 2);
- cB[k] = iB[B * 114 + j];
- }
-}
-
-static void
-tch_fr_interleave(ubit_t *cB, ubit_t *iB)
-{
- int j, k, B;
-
- for (k=0; k<456; k++) {
- B = k & 7;
- j = 2 * ((49 * k) % 57) + ((k & 7) >> 2);
- iB[B * 114 + j] = cB[k];
- }
-}
-
-static void
-tch_fr_burst_unmap(sbit_t *iB, sbit_t *eB, sbit_t *h, int odd)
-{
- int i;
-
- /* brainfuck: only copy even or odd bits */
- for (i=odd; i<57; i+=2)
- iB[i] = eB[i];
- for (i=58-odd; i<114; i+=2)
- iB[i] = eB[i+2];
-
- if (h && !odd)
- *h = eB[58];
-
- if (h && odd)
- *h = eB[57];
-}
-
-static void
-tch_fr_burst_map(ubit_t *iB, ubit_t *eB, ubit_t *h, int odd)
-{
- int i;
-
- /* brainfuck: only copy even or odd bits */
- for (i=odd; i<57; i+=2)
- eB[i] = iB[i];
- for (i=58-odd; i<114; i+=2)
- eB[i+2] = iB[i];
-
- if (h && !odd)
- eB[58] = *h;
- if (h && odd)
- eB[57] = *h;
-}
-
-/* this corresponds to the bit-lengths of the individual codec
- * parameters as indicated in Table 1.1 of TS 06.10 */
-static const uint8_t gsm_fr_map[] = {
- 6, 6, 5, 5, 4, 4, 3, 3,
- 7, 2, 2, 6, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 7, 2, 2, 6, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 7, 2, 2, 6, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 7, 2, 2, 6, 3,
- 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3
-};
-
-static void
-tch_fr_reassemble(uint8_t *tch_data, ubit_t *b_bits)
-{
- int i, j, k, l, o;
-
- tch_data[0] = 0xd << 4;
- memset(tch_data + 1, 0, 32);
- /* reassemble d-bits */
- i = 0; /* counts bits */
- j = 4; /* counts output bits */
- k = gsm_fr_map[0]-1; /* current number bit in element */
- l = 0; /* counts element bits */
- o = 0; /* offset input bits */
- while (i < 260) {
- tch_data[j>>3] |= (b_bits[k+o] << (7-(j&7)));
- if (--k < 0) {
- o += gsm_fr_map[l];
- k = gsm_fr_map[++l]-1;
- }
- i++;
- j++;
- }
-
- /* rearrange according to Table 2 of TS 05.03 */
-}
-
-static void
-tch_fr_disassemble(ubit_t *b_bits, uint8_t *tch_data)
-{
- int i, j, k, l, o;
-
- i = 0; /* counts bits */
- j = 4; /* counts input bits */
- k = gsm_fr_map[0]-1; /* current number bit in element */
- l = 0; /* counts element bits */
- o = 0; /* offset output bits */
- while (i < 260) {
- b_bits[k+o] = (tch_data[j>>3] >> (7-(j&7))) & 1;
- if (--k < 0) {
- o += gsm_fr_map[l];
- k = gsm_fr_map[++l]-1;
- }
- i++;
- j++;
- }
-
-}
-
-
-/* b(0..259) from d(0..259) according to (corrected) Table 2 of T 05.03 */
-static uint16_t d_to_b_index[260] = {
- 5, 52,108,164,220, 4, 11, 16, 3, 10, 15, 21, 42, 98,154,210,
- 51,107,163,219, 9, 25, 29, 41, 97,153,209, 40, 96,152,208, 39,
- 95,151,207, 38, 94,150,206, 50,106,162,218, 2, 20, 32, 37, 93,
- 149,205, 24, 28, 44,100,156,212, 36, 92,148,204, 46,102,158,214,
- 1, 8, 14, 35, 19, 23, 31, 43, 99,155,211, 49,105,161,217, 55,
- 58, 61, 64, 67, 70, 73, 76, 79, 82, 85, 88, 91,111,114,117,120,
- 123,126,129,132,135,138,141,144,147,167,170,173,176,179,182,185,
- 188,191,194,197,200,203,223,226,229,232,235,238,241,244,247,250,
- 253,256,259, 45,101,157,213, 48,104,160,216, 54, 57, 60, 63, 66,
- 69, 72, 75, 78, 81, 84, 87, 90,110,113,116,119,122,125,128,131,
- 134,137,140,143,146,166,169,172,175,178,181,184,187,190,193,196,
- 199,202,222,225,228,231,234,237,240,243,246,249,252,255,258, 0,
- 7, 13, 27, 30, 34, 33, 12, 18, 17, 22, 47,103,159,215, 53, 56,
- 59, 62, 65, 68, 71, 74, 77, 80, 83, 86, 89,109,112,115,118,121,
- 124,127,130,133,136,139,142,145,165,168,171,174,177,180,183,186,
- 189,192,195,198,201,221,224,227,230,233,236,239,242,245,248,251,
- 254,257, 6, 26,
-};
-
-
-static void
-tch_fr_d_to_b(ubit_t *b_bits, ubit_t *d_bits)
-{
- int i;
-
- for (i = 0; i < 260; i++)
- b_bits[d_to_b_index[i]] = d_bits[i];
-}
-
-static void
-tch_fr_b_to_d(ubit_t *d_bits, ubit_t *b_bits)
-{
- int i;
-
- for (i = 0; i < 260; i++)
- d_bits[i] = b_bits[d_to_b_index[i]];
-}
-
-static void
-tch_fr_unreorder(ubit_t *d, ubit_t *p, ubit_t *u)
-{
- int i;
-
- for (i=0; i<91; i++) {
- d[i<<1] = u[i];
- d[(i<<1)+1] = u[184-i];
- }
- for (i=0; i<3; i++)
- p[i] = u[91+i];
-}
-
-static void
-tch_fr_reorder(ubit_t *u, ubit_t *d, ubit_t *p)
-{
- int i;
-
- for (i=0; i<91; i++) {
- u[i] = d[i<<1];
- u[184-i] = d[(i<<1)+1];
- }
- for (i=0; i<3; i++)
- u[91+i] = p[i];
-}
-
-int
-tch_fr_decode(uint8_t *tch_data, sbit_t *bursts, int network_order)
-{
- sbit_t iB[912], cB[456], h;
- ubit_t conv[185], b[260], d[260], p[3];
- int i, rv, len, steal = 0;
-
- for (i=0; i<8; i++) {
- tch_fr_burst_unmap(&iB[i * 114], &bursts[i * 116], &h, i>>2);
- if (h < 0)
- steal++;
- }
-
- tch_fr_deinterleave(cB, iB);
-
- if (steal < 4) {
- osmo_conv_decode(&conv_tch_fr, cB, conv);
-
- tch_fr_unreorder(d, p, conv);
-
- for (i=0; i<78; i++)
- d[i+182] = (cB[i+378] < 0) ? 1:0;
-
- rv = osmo_crc8gen_check_bits(&tch_fr_crc3, d, 50, p);
- if (rv)
- return -1;
-
- if (network_order) {
- tch_fr_d_to_b(b, d);
-
- tch_fr_reassemble(tch_data, b);
- } else
- tch_fr_d_to_b(tch_data, d);
-
- len = 33;
- } else {
- rv = xcch_decode_cB(tch_data, cB);
- if (rv)
- return -1;
-
- len = 23;
- }
-
- return len;
-}
-
-int
-tch_fr_encode(ubit_t *bursts, uint8_t *tch_data, int len, int network_order)
-{
- ubit_t iB[912], cB[456], h;
- ubit_t conv[185], b[260], d[260], p[3];
- int i;
-
- switch (len) {
- case 33: /* TCH FR */
- if (network_order) {
- tch_fr_disassemble(b, tch_data);
-
- tch_fr_b_to_d(d, b);
- } else
- tch_fr_b_to_d(d, tch_data);
-
- osmo_crc8gen_set_bits(&tch_fr_crc3, d, 50, p);
-
- tch_fr_reorder(conv, d, p);
-
- memcpy(cB+378, d+182, 78);
-
- osmo_conv_encode(&conv_tch_fr, conv, cB);
-
- h = 0;
-
- break;
- case 23: /* FACCH */
- xcch_encode_cB(cB, tch_data);
-
- h = 1;
-
- break;
- default:
- return -1;
- }
-
- tch_fr_interleave(cB, iB);
-
- for (i=0; i<8; i++)
- tch_fr_burst_map(&iB[i * 114], &bursts[i * 116], &h, i>>2);
-
- return 0;
-}