diff options
Diffstat (limited to 'src/coding/gsm0503_interleaving.c')
-rw-r--r-- | src/coding/gsm0503_interleaving.c | 573 |
1 files changed, 573 insertions, 0 deletions
diff --git a/src/coding/gsm0503_interleaving.c b/src/coding/gsm0503_interleaving.c new file mode 100644 index 00000000..22ad6f69 --- /dev/null +++ b/src/coding/gsm0503_interleaving.c @@ -0,0 +1,573 @@ +/* + * (C) 2013 by Andreas Eversberg <jolly@eversberg.eu> + * (C) 2016 by Tom Tsou <tom.tsou@ettus.com> + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include <stdint.h> +#include <string.h> + +#include <osmocom/core/bits.h> +#include <osmocom/coding/gsm0503_tables.h> +#include <osmocom/coding/gsm0503_interleaving.h> + +/* + * GSM xCCH interleaving and burst mapping + * + * Interleaving: + * + * Given 456 coded input bits, form 4 blocks of 114 bits: + * + * i(B, j) = c(n, k) k = 0, ..., 455 + * n = 0, ..., N, N + 1, ... + * B = B_0 + 4n + (k mod 4) + * 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. + */ + +void gsm0503_xcch_deinterleave(sbit_t *cB, const sbit_t *iB) +{ + int j, k, B; + + for (k = 0; k < 456; k++) { + B = k & 3; + j = 2 * ((49 * k) % 57) + ((k & 7) >> 2); + cB[k] = iB[B * 114 + j]; + } +} + +void gsm0503_xcch_interleave(ubit_t *cB, ubit_t *iB) +{ + int j, k, B; + + for (k = 0; k < 456; k++) { + B = k & 3; + j = 2 * ((49 * k) % 57) + ((k & 7) >> 2); + iB[B * 114 + j] = cB[k]; + } +} + +void gsm0503_mcs1_dl_deinterleave(sbit_t *u, sbit_t *hc, + sbit_t *dc, const sbit_t *iB) +{ + int k; + sbit_t c[452]; + sbit_t cp[456]; + + gsm0503_xcch_deinterleave(cp, iB); + + for (k = 0; k < 25; k++) + c[k] = cp[k]; + for (k = 26; k < 82; k++) + c[k - 1] = cp[k]; + for (k = 83; k < 139; k++) + c[k - 2] = cp[k]; + for (k = 140; k < 424; k++) + c[k - 3] = cp[k]; + for (k = 425; k < 456; k++) + c[k - 4] = cp[k]; + + if (u) { + for (k = 0; k < 12; k++) + u[k] = c[k]; + } + + if (hc) { + for (k = 12; k < 80; k++) + hc[k - 12] = c[k]; + } + + if (dc) { + for (k = 80; k < 452; k++) + dc[k - 80] = c[k]; + } +} + +void gsm0503_mcs1_dl_interleave(const ubit_t *up, const ubit_t *hc, + const ubit_t *dc, ubit_t *iB) +{ + int k; + ubit_t c[452]; + ubit_t cp[456]; + + for (k = 0; k < 12; k++) + c[k] = up[k]; + for (k = 12; k < 80; k++) + c[k] = hc[k - 12]; + for (k = 80; k < 452; k++) + c[k] = dc[k - 80]; + + for (k = 0; k < 25; k++) + cp[k] = c[k]; + for (k = 26; k < 82; k++) + cp[k] = c[k - 1]; + for (k = 83; k < 139; k++) + cp[k] = c[k - 2]; + for (k = 140; k < 424; k++) + cp[k] = c[k - 3]; + for (k = 425; k < 456; k++) + cp[k] = c[k - 4]; + + cp[25] = 0; + cp[82] = 0; + cp[139] = 0; + cp[424] = 0; + + gsm0503_xcch_interleave(cp, iB); +} + +void gsm0503_mcs1_ul_deinterleave(sbit_t *hc, sbit_t *dc, const sbit_t *iB) +{ + int k; + sbit_t c[452]; + sbit_t cp[456]; + + gsm0503_xcch_deinterleave(cp, iB); + + for (k = 0; k < 25; k++) + c[k] = cp[k]; + for (k = 26; k < 82; k++) + c[k - 1] = cp[k]; + for (k = 83; k < 139; k++) + c[k - 2] = cp[k]; + for (k = 140; k < 424; k++) + c[k - 3] = cp[k]; + for (k = 425; k < 456; k++) + c[k - 4] = cp[k]; + + if (hc) { + for (k = 0; k < 80; k++) + hc[k] = c[k]; + } + + if (dc) { + for (k = 80; k < 452; k++) + dc[k - 80] = c[k]; + } +} + +void gsm0503_mcs1_ul_interleave(const ubit_t *hc, const ubit_t *dc, ubit_t *iB) +{ + int k; + ubit_t c[452]; + ubit_t cp[456]; + + for (k = 0; k < 80; k++) + c[k] = hc[k]; + for (k = 80; k < 452; k++) + c[k] = dc[k - 80]; + + for (k = 0; k < 25; k++) + cp[k] = c[k]; + for (k = 26; k < 82; k++) + cp[k] = c[k - 1]; + for (k = 83; k < 139; k++) + cp[k] = c[k - 2]; + for (k = 140; k < 424; k++) + cp[k] = c[k - 3]; + for (k = 425; k < 456; k++) + cp[k] = c[k - 4]; + + cp[25] = 0; + cp[82] = 0; + cp[139] = 0; + cp[424] = 0; + + gsm0503_xcch_interleave(cp, iB); +} + +void gsm0503_mcs5_ul_interleave(const ubit_t *hc, const ubit_t *dc, + ubit_t *hi, ubit_t *di) +{ + int j, k; + + /* Header */ + for (k = 0; k < 136; k++) { + j = 34 * (k % 4) + 2 * (11 * k % 17) + k % 8 / 4; + hi[j] = hc[k]; + } + + /* Data */ + for (k = 0; k < 1248; k++) { + j = gsm0503_interleave_mcs5[k]; + di[j] = dc[k]; + } +} + +void gsm0503_mcs5_ul_deinterleave(sbit_t *hc, sbit_t *dc, + const sbit_t *hi, const sbit_t *di) +{ + int j, k; + + /* Header */ + if (hc) { + for (k = 0; k < 136; k++) { + j = 34 * (k % 4) + 2 * (11 * k % 17) + k % 8 / 4; + hc[k] = hi[j]; + } + } + + /* Data */ + if (dc) { + for (k = 0; k < 1248; k++) { + j = gsm0503_interleave_mcs5[k]; + dc[k] = di[j]; + } + } +} + +void gsm0503_mcs5_dl_interleave(const ubit_t *hc, const ubit_t *dc, + ubit_t *hi, ubit_t *di) +{ + int j, k; + + /* Header */ + for (k = 0; k < 100; k++) { + j = 25 * (k % 4) + ((17 * k) % 25); + hi[j] = hc[k]; + } + + /* Data */ + for (k = 0; k < 1248; k++) { + j = gsm0503_interleave_mcs5[k]; + di[j] = dc[k]; + } +} + +void gsm0503_mcs5_dl_deinterleave(sbit_t *hc, sbit_t *dc, + const sbit_t *hi, const sbit_t *di) +{ + int j, k; + + /* Header */ + if (hc) { + for (k = 0; k < 100; k++) { + j = 25 * (k % 4) + ((17 * k) % 25); + hc[k] = hi[j]; + } + } + + /* Data */ + if (dc) { + for (k = 0; k < 1248; k++) { + j = gsm0503_interleave_mcs5[k]; + dc[k] = di[j]; + } + } +} + +void gsm0503_mcs7_dl_interleave(const ubit_t *hc, const ubit_t *c1, + const ubit_t *c2, ubit_t *hi, ubit_t *di) +{ + int j, k; + ubit_t dc[1224]; + + /* Header */ + for (k = 0; k < 124; k++) { + j = 31 * (k % 4) + ((17 * k) % 31); + hi[j] = hc[k]; + } + + memcpy(&dc[0], c1, 612); + memcpy(&dc[612], c2, 612); + + /* Data */ + for (k = 0; k < 1224; k++) { + j = 306 * (k % 4) + 3 * (44 * k % 102 + k / 4 % 2) + + (k + 2 - k / 408) % 3; + di[j] = dc[k]; + } +} + + +void gsm0503_mcs7_dl_deinterleave(sbit_t *hc, sbit_t *c1, sbit_t *c2, + const sbit_t *hi, const sbit_t *di) +{ + int j, k; + ubit_t dc[1224]; + + /* Header */ + if (hc) { + for (k = 0; k < 124; k++) { + j = 31 * (k % 4) + ((17 * k) % 31); + hc[k] = hi[j]; + } + } + + /* Data */ + if (c1 && c2) { + for (k = 0; k < 1224; k++) { + j = 306 * (k % 4) + 3 * (44 * k % 102 + k / 4 % 2) + + (k + 2 - k / 408) % 3; + dc[k] = di[j]; + } + + memcpy(c1, &dc[0], 612); + memcpy(c2, &dc[612], 612); + } +} + +void gsm0503_mcs7_ul_interleave(const ubit_t *hc, const ubit_t *c1, + const ubit_t *c2, ubit_t *hi, ubit_t *di) +{ + int j, k; + ubit_t dc[1224]; + + /* Header */ + for (k = 0; k < 160; k++) { + j = 40 * (k % 4) + 2 * (13 * (k / 8) % 20) + k % 8 / 4; + hi[j] = hc[k]; + } + + memcpy(&dc[0], c1, 612); + memcpy(&dc[612], c2, 612); + + /* Data */ + for (k = 0; k < 1224; k++) { + j = 306 * (k % 4) + 3 * (44 * k % 102 + k / 4 % 2) + + (k + 2 - k / 408) % 3; + di[j] = dc[k]; + } +} + +void gsm0503_mcs7_ul_deinterleave(sbit_t *hc, sbit_t *c1, sbit_t *c2, + const sbit_t *hi, const sbit_t *di) +{ + int j, k; + ubit_t dc[1224]; + + /* Header */ + if (hc) { + for (k = 0; k < 160; k++) { + j = 40 * (k % 4) + 2 * (13 * (k / 8) % 20) + k % 8 / 4; + hc[k] = hi[j]; + } + } + + /* Data */ + if (c1 && c2) { + for (k = 0; k < 1224; k++) { + j = 306 * (k % 4) + 3 * (44 * k % 102 + k / 4 % 2) + + (k + 2 - k / 408) % 3; + dc[k] = di[j]; + } + + memcpy(c1, &dc[0], 612); + memcpy(c2, &dc[612], 612); + } +} + +void gsm0503_mcs8_ul_interleave(const ubit_t *hc, const ubit_t *c1, + const ubit_t *c2, ubit_t *hi, ubit_t *di) +{ + int j, k; + ubit_t dc[1224]; + + /* Header */ + for (k = 0; k < 160; k++) { + j = 40 * (k % 4) + 2 * (13 * (k / 8) % 20) + k % 8 / 4; + hi[j] = hc[k]; + } + + memcpy(&dc[0], c1, 612); + memcpy(&dc[612], c2, 612); + + /* Data */ + for (k = 0; k < 1224; k++) { + j = 306 * (2 * (k / 612) + (k % 2)) + + 3 * (74 * k % 102 + k / 2 % 2) + (k + 2 - k / 204) % 3; + di[j] = dc[k]; + } +} + +void gsm0503_mcs8_ul_deinterleave(sbit_t *hc, sbit_t *c1, sbit_t *c2, + const sbit_t *hi, const sbit_t *di) +{ + int j, k; + ubit_t dc[1224]; + + /* Header */ + if (hc) { + for (k = 0; k < 160; k++) { + j = 40 * (k % 4) + 2 * (13 * (k / 8) % 20) + k % 8 / 4; + hc[k] = hi[j]; + } + } + + /* Data */ + if (c1 && c2) { + for (k = 0; k < 1224; k++) { + j = 306 * (2 * (k / 612) + (k % 2)) + + 3 * (74 * k % 102 + k / 2 % 2) + (k + 2 - k / 204) % 3; + dc[k] = di[j]; + } + + memcpy(c1, &dc[0], 612); + memcpy(c2, &dc[612], 612); + } +} + +void gsm0503_mcs8_dl_interleave(const ubit_t *hc, const ubit_t *c1, + const ubit_t *c2, ubit_t *hi, ubit_t *di) +{ + int j, k; + ubit_t dc[1224]; + + /* Header */ + for (k = 0; k < 124; k++) { + j = 31 * (k % 4) + ((17 * k) % 31); + hi[j] = hc[k]; + } + + memcpy(&dc[0], c1, 612); + memcpy(&dc[612], c2, 612); + + /* Data */ + for (k = 0; k < 1224; k++) { + j = 306 * (2 * (k / 612) + (k % 2)) + + 3 * (74 * k % 102 + k / 2 % 2) + (k + 2 - k / 204) % 3; + di[j] = dc[k]; + } +} + +void gsm0503_mcs8_dl_deinterleave(sbit_t *hc, sbit_t *c1, sbit_t *c2, + const sbit_t *hi, const sbit_t *di) +{ + int j, k; + ubit_t dc[1224]; + + /* Header */ + if (hc) { + for (k = 0; k < 124; k++) { + j = 31 * (k % 4) + ((17 * k) % 31); + hc[k] = hi[j]; + } + } + + /* Data */ + if (c1 && c2) { + for (k = 0; k < 1224; k++) { + j = 306 * (2 * (k / 612) + (k % 2)) + + 3 * (74 * k % 102 + k / 2 % 2) + (k + 2 - k / 204) % 3; + dc[k] = di[j]; + } + + memcpy(c1, &dc[0], 612); + memcpy(c2, &dc[612], 612); + } +} + +/* + * GSM TCH FR/EFR/AFS interleaving and burst mapping + * + * Interleaving: + * + * Given 456 coded input bits, form 8 blocks of 114 bits, + * where even bits of the first 4 blocks and odd bits of the last 4 blocks + * 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. + */ + +void gsm0503_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]; + } +} + +void gsm0503_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]; + } +} + +/* + * GSM TCH HR/AHS interleaving and burst mapping + * + * Interleaving: + * + * Given 288 coded input bits, form 4 blocks of 114 bits, + * where even bits of the first 2 blocks and odd bits of the last 2 blocks + * are used: + * + * i(B, j) = c(n, k) k = 0, ..., 227 + * n = 0, ..., N, N + 1, ... + * B = B_0 + 2n + b + * j, b = table[k]; + * + * 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. + */ + +void gsm0503_tch_hr_deinterleave(sbit_t *cB, sbit_t *iB) +{ + int j, k, B; + + for (k = 0; k < 228; k++) { + B = gsm0503_tch_hr_interleaving[k][1]; + j = gsm0503_tch_hr_interleaving[k][0]; + cB[k] = iB[B * 114 + j]; + } +} + +void gsm0503_tch_hr_interleave(ubit_t *cB, ubit_t *iB) +{ + int j, k, B; + + for (k = 0; k < 228; k++) { + B = gsm0503_tch_hr_interleaving[k][1]; + j = gsm0503_tch_hr_interleaving[k][0]; + iB[B * 114 + j] = cB[k]; + } +} |