aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhilipp Maier <pmaier@sysmocom.de>2019-10-09 13:38:38 +0200
committerlaforge <laforge@osmocom.org>2019-10-28 19:43:14 +0000
commit69e00ccd6ff3a19b771070b78ed3d85dd219799f (patch)
treebf4914255ba3a4491423bd7e06f8f4efda1953ef
parenta0c8195ad37292ab800a6c777fc28383995b4b64 (diff)
gsm0508: add functions to calculate beginning of a block
The calculation of the beginning of a block for TCH/F, TCH/H and FACCH can be challenging since those channels are affected by the diagonal interleaving of the TCH channels. However, GSM 05.02 Section 7 Table 1 of 5 specifies how the blocks are distributed over the TDMA frame interval. Lets add a mapping function that is based on that table Related: OS#3803 Change-Id: I3d71c66f8c401f5afbad9b1c86c24580dab9e0ce
-rw-r--r--include/osmocom/gsm/gsm0502.h12
-rw-r--r--src/gsm/gsm0502.c157
-rw-r--r--src/gsm/libosmogsm.map1
-rw-r--r--tests/Makefile.am5
-rw-r--r--tests/gsm0502/gsm0502_test.c159
-rw-r--r--tests/gsm0502/gsm0502_test.ok271
-rw-r--r--tests/testsuite.at6
7 files changed, 611 insertions, 0 deletions
diff --git a/include/osmocom/gsm/gsm0502.h b/include/osmocom/gsm/gsm0502.h
index fe5cf7e1..c9901dfd 100644
--- a/include/osmocom/gsm/gsm0502.h
+++ b/include/osmocom/gsm/gsm0502.h
@@ -35,3 +35,15 @@ gsm0502_get_paging_group(uint64_t imsi, unsigned int bs_cc_chans,
unsigned int
gsm0502_calc_paging_group(struct gsm48_control_channel_descr *chan_desc, uint64_t imsi);
+
+enum gsm0502_fn_remap_channel {
+ FN_REMAP_TCH_F,
+ FN_REMAP_TCH_H0,
+ FN_REMAP_TCH_H1,
+ FN_REMAP_FACCH_F,
+ FN_REMAP_FACCH_H0,
+ FN_REMAP_FACCH_H1,
+ FN_REMAP_MAX,
+};
+
+uint32_t gsm0502_fn_remap(uint32_t fn, enum gsm0502_fn_remap_channel channel);
diff --git a/src/gsm/gsm0502.c b/src/gsm/gsm0502.c
index 53259a42..1a71e617 100644
--- a/src/gsm/gsm0502.c
+++ b/src/gsm/gsm0502.c
@@ -27,6 +27,9 @@
#include <osmocom/gsm/gsm0502.h>
#include <osmocom/gsm/gsm48.h>
#include <osmocom/gsm/rsl.h>
+#include <osmocom/gsm/gsm_utils.h>
+#include <osmocom/core/logging.h>
+#include <inttypes.h>
unsigned int
gsm0502_calc_paging_group(struct gsm48_control_channel_descr *chan_desc, uint64_t imsi)
@@ -44,3 +47,157 @@ gsm0502_calc_paging_group(struct gsm48_control_channel_descr *chan_desc, uint64_
return group;
}
+
+/* Clause 7 Table 1 of 5 Mapping of logical channels onto physical channels */
+#define TCH_REPEAT_LENGTH 13
+#define FACCH_F_REPEAT_LENGTH 13
+#define FACCH_H_REPEAT_LENGTH 26
+
+static const uint8_t gsm0502_tch_f_traffic_block_map[3][8] = {
+ {0, 1, 2, 3, 4, 5, 6, 7},
+ {4, 5, 6, 7, 8, 9, 10, 11},
+ {8, 9, 10, 11, 0, 1, 2, 3}
+};
+
+static const uint8_t gsm0502_tch_h0_traffic_block_map[3][4] = {
+ {0, 2, 4, 6},
+ {4, 6, 8, 10},
+ {8, 10, 0, 2}
+};
+
+static const uint8_t gsm0502_tch_h1_traffic_block_map[3][4] = {
+ {1, 3, 5, 7},
+ {5, 7, 9, 11},
+ {9, 11, 1, 3}
+};
+
+static const uint8_t gsm0502_tch_f_facch_block_map[3][8] = {
+ {0, 1, 2, 3, 4, 5, 6, 7},
+ {4, 5, 6, 7, 8, 9, 10, 11},
+ {8, 9, 10, 11, 0, 1, 2, 3}
+};
+
+static const uint8_t gsm0502_tch_h0_facch_block_map[3][6] = {
+ {0, 2, 4, 6, 8, 10},
+ {8, 10, 13, 15, 17, 19},
+ {17, 19, 21, 23, 0, 2}
+};
+
+static const uint8_t gsm0502_tch_h1_facch_block_map[3][6] = {
+ {1, 3, 5, 7, 9, 11},
+ {9, 11, 14, 16, 18, 20},
+ {18, 20, 22, 24, 1, 3}
+};
+
+/* Struct to describe a remapping function for block frame nbumbers. The member
+ * blockend describes the ending of a block for which we want to determine the
+ * beginning frame number. The member distance describes the value we need to
+ * subtract from the blockend frame number in order to get the beginning of the
+ * the block. The member cycle describes the Repeat length in TDMA frames we
+ * are dealing with. For traffic channels this is always 13, for control
+ * channels it is different. The member len simply defines amount of
+ * blockendings and distances we store in the remap table */
+struct fn_remap_table {
+ unsigned int cycle;
+ unsigned int len;
+ uint8_t blockend[8];
+ uint8_t distance[8];
+};
+
+/* Memory to hold the remap tables we will automatically generate on startup */
+static struct fn_remap_table tch_f_remap_table;
+static struct fn_remap_table tch_h0_remap_table;
+static struct fn_remap_table tch_h1_remap_table;
+static struct fn_remap_table facch_f_remap_table;
+static struct fn_remap_table facch_h0_remap_table;
+static struct fn_remap_table facch_h1_remap_table;
+static struct fn_remap_table *fn_remap_table_ptr[FN_REMAP_MAX];
+
+/* Generate a remap table from a given block map. A block map lists the block
+ * layout as defined in GSM 05.02, Clause 7 Table 1 of 5, one block per row.
+ * Parameters:
+ * table: name of the remap table to output
+ * map: traffic block map input
+ * rows: length of the traffic block map
+ * cols: witdh of the traffic block map
+ * repeat: repeat length in TDMA frames (cycle) */
+#define fn_remap_table_from_traffic_block_map(table, map, rows, cols, repeat) \
+ for(i=0;i<rows;i++) { \
+ table.blockend[i] = map[i][cols-1]; \
+ if(map[i][0] <= map[i][cols-1]) \
+ table.distance[i] = map[i][cols-1] - map[i][0]; \
+ else \
+ table.distance[i] = repeat - map[i][0] + map[i][cols-1]; \
+ } \
+ table.cycle = repeat; \
+ table.len = rows;
+
+/* Automatically generate fn remap tables on startupmake */
+static __attribute__ ((constructor))
+void fn_remap_tables_build(void)
+{
+ /* Required by macro */
+ unsigned int i;
+
+ /* Generate tables */
+ fn_remap_table_from_traffic_block_map(tch_f_remap_table,
+ gsm0502_tch_f_traffic_block_map, 3, 8,
+ TCH_REPEAT_LENGTH);
+ fn_remap_table_from_traffic_block_map(tch_h0_remap_table,
+ gsm0502_tch_h0_traffic_block_map, 3, 4,
+ TCH_REPEAT_LENGTH);
+ fn_remap_table_from_traffic_block_map(tch_h1_remap_table,
+ gsm0502_tch_h1_traffic_block_map, 3, 4,
+ TCH_REPEAT_LENGTH);
+ fn_remap_table_from_traffic_block_map(facch_f_remap_table,
+ gsm0502_tch_f_facch_block_map, 3, 8,
+ FACCH_F_REPEAT_LENGTH);
+ fn_remap_table_from_traffic_block_map(facch_h0_remap_table,
+ gsm0502_tch_h0_facch_block_map, 3, 6,
+ FACCH_H_REPEAT_LENGTH);
+ fn_remap_table_from_traffic_block_map(facch_h1_remap_table,
+ gsm0502_tch_h1_facch_block_map, 3, 6,
+ FACCH_H_REPEAT_LENGTH);
+
+ fn_remap_table_ptr[FN_REMAP_TCH_F] = &tch_f_remap_table;
+ fn_remap_table_ptr[FN_REMAP_TCH_H0] = &tch_h0_remap_table;
+ fn_remap_table_ptr[FN_REMAP_TCH_H1] = &tch_h1_remap_table;
+ fn_remap_table_ptr[FN_REMAP_FACCH_F] = &facch_f_remap_table;
+ fn_remap_table_ptr[FN_REMAP_FACCH_H0] = &facch_h0_remap_table;
+ fn_remap_table_ptr[FN_REMAP_FACCH_H1] = &facch_h1_remap_table;
+}
+
+/*! Calculate the frame number of the beginning of a block.
+ * \param[in] fn frame number of the block ending.
+ * \param[in] channel channel type (see also enum fn_remap_channel).
+ * \returns frame number of the beginning of the block or input frame number if
+ * remapping was not possible. */
+uint32_t gsm0502_fn_remap(uint32_t fn, enum gsm0502_fn_remap_channel channel)
+{
+ uint8_t fn_cycle;
+ uint8_t i;
+ int sub = -1;
+ uint32_t fn_map;
+ struct fn_remap_table *table;
+
+ OSMO_ASSERT(channel < ARRAY_SIZE(fn_remap_table_ptr));
+ table = fn_remap_table_ptr[(uint8_t)channel];
+
+ fn_cycle = fn % table->cycle;
+
+ for (i = 0; i < table->len; i++) {
+ if (table->blockend[i] == fn_cycle) {
+ sub = table->distance[i];
+ break;
+ }
+ }
+
+ if (sub == -1) {
+ LOGP(DLGLOBAL, LOGL_ERROR, "could not remap frame number!, fn=%"PRIu32"\n", fn);
+ return fn;
+ }
+
+ fn_map = (fn + GSM_MAX_FN - sub) % GSM_MAX_FN;
+
+ return fn_map;
+}
diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map
index ea1f759d..724fe5b1 100644
--- a/src/gsm/libosmogsm.map
+++ b/src/gsm/libosmogsm.map
@@ -107,6 +107,7 @@ gsm0480_gen_return_error;
gsm0480_gen_reject;
gsm0502_calc_paging_group;
+gsm0502_fn_remap;
gsm0503_xcch;
gsm0503_rach;
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 60213ed3..76249966 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -33,6 +33,7 @@ check_PROGRAMS = timer/timer_test sms/sms_test ussd/ussd_test \
sockaddr_str/sockaddr_str_test \
use_count/use_count_test \
context/context_test \
+ gsm0502/gsm0502_test \
$(NULL)
if ENABLE_MSGFILE
@@ -108,6 +109,9 @@ bits_bitfield_test_SOURCES = bits/bitfield_test.c
conv_conv_test_SOURCES = conv/conv_test.c conv/conv.c
conv_conv_test_LDADD = $(LDADD) $(top_builddir)/src/gsm/libgsmint.la
+gsm0502_gsm0502_test_SOURCES = gsm0502/gsm0502_test.c
+gsm0502_gsm0502_test_LDADD = $(LDADD) $(top_builddir)/src/gsm/libosmogsm.la
+
conv_conv_gsm0503_test_SOURCES = conv/conv_gsm0503_test.c conv/conv.c conv/gsm0503_test_vectors.c
conv_conv_gsm0503_test_LDADD = $(LDADD) $(top_builddir)/src/gsm/libgsmint.la
conv_conv_gsm0503_test_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/tests/conv
@@ -328,6 +332,7 @@ EXTRA_DIST = testsuite.at $(srcdir)/package.m4 $(TESTSUITE) \
sockaddr_str/sockaddr_str_test.ok \
use_count/use_count_test.ok use_count/use_count_test.err \
context/context_test.ok \
+ gsm0502/gsm0502_test.ok \
$(NULL)
DISTCLEANFILES = atconfig atlocal conv/gsm0503_test_vectors.c
diff --git a/tests/gsm0502/gsm0502_test.c b/tests/gsm0502/gsm0502_test.c
new file mode 100644
index 00000000..a950c6c1
--- /dev/null
+++ b/tests/gsm0502/gsm0502_test.c
@@ -0,0 +1,159 @@
+/*
+ * (C) 2019 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
+ * Author: Philipp Maier <pmaier@sysmocom.de>
+ * All Rights Reserved
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ *
+ * 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 <string.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <osmocom/core/utils.h>
+#include <osmocom/gsm/gsm0502.h>
+
+/* TCH-F, block endings, 3x 104-frame cycles */
+uint32_t tch_f_fn_samples[] = { 1036987, 1036991, 1036995, 1037000, 1037004, 1037008, 1037013, 1037017,
+ 1037021, 1037026, 1037030, 1037034, 1037039, 1037043, 1037047, 1037052,
+ 1037056, 1037060, 1037065,
+ 1037069, 1037073, 1037078, 1037082, 1037086, 1037091, 1037095, 1037099,
+ 1037104, 1037108, 1037112,
+ 1037117, 1037121, 1037125, 1037130, 1037134, 1037138, 1037143, 1037147,
+ 1037151, 1037156, 1037160,
+ 1037164, 1037169, 1037173, 1037177, 1037182, 1037186, 1037190, 1037195,
+ 1037199, 1037203, 1037208,
+ 1037212, 1037216, 1037221, 1037225, 1037229, 1037234, 1037238, 1037242,
+ 1037247, 1037251, 1037255,
+ 1037260, 1037264, 1037268, 1037273, 1037277, 1037281, 1037286, 1037290,
+ 1037294
+};
+
+/* TCH-H0, block endings, 3x 104-frame cycles */
+uint32_t tch_h0_fn_samples[] = { 1175826, 1175830, 1175834, 1175839, 1175843, 1175847, 1175852, 1175856,
+ 1175860, 1175865, 1175869, 1175873, 1175878, 1175882, 1175886, 1175891,
+ 1175895, 1175899, 1175904,
+ 1175908, 1175912, 1175917, 1175921, 1175925, 1175930, 1175934, 1175938,
+ 1175943, 1175947, 1175951,
+ 1175956, 1175960, 1175964, 1175969, 1175973, 1175977, 1175982, 1175986,
+ 1175990, 1175995, 1175999,
+ 1176003, 1176008, 1176012, 1176016, 1176021, 1176025, 1176029, 1176034,
+ 1176038, 1176042, 1176047,
+ 1176051, 1176055, 1176060, 1176064, 1176068, 1176073, 1176077, 1176081,
+ 1176086, 1176090, 1176094,
+ 1176099, 1176103, 1176107, 1176112, 1176116, 1176120, 1176125, 1176129,
+ 1176133
+};
+
+/* TCH-H1, block endings, 3x 104-frame cycles */
+unsigned int tch_h1_fn_samples[] = { 1175827, 1175831, 1175835, 1175840, 1175844, 1175848, 1175853, 1175857,
+ 1175861, 1175866, 1175870, 1175874, 1175879, 1175883, 1175887, 1175892,
+ 1175896, 1175900, 1175905,
+ 1175909, 1175913, 1175918, 1175922, 1175926, 1175931, 1175935, 1175939,
+ 1175944, 1175948, 1175952,
+ 1175957, 1175961, 1175965, 1175970, 1175974, 1175978, 1175983, 1175987,
+ 1175991, 1175996, 1176000,
+ 1176004, 1176009, 1176013, 1176017, 1176022, 1176026, 1176030, 1176035,
+ 1176039, 1176043, 1176048,
+ 1176052, 1176056, 1176061, 1176065, 1176069, 1176074, 1176078, 1176082,
+ 1176087, 1176091, 1176095,
+ 1176100, 1176104, 1176108, 1176113, 1176117, 1176121, 1176126, 1176130,
+ 1176134
+};
+
+/* FACCH-F, block endings */
+uint32_t facch_f_fn_samples[] = { 177275, 177314, 177336, 177375, 177396, 177435, 178328, 178367, 178393,
+ 180014, 180053, 180079, 180113, 180144, 180183
+};
+
+/* FACCH-H0, block endings */
+uint32_t facch_h0_fn_samples[] = { 499956, 499999, 500034, 500077, 500952, 501836, 501880, 502850, 502894,
+ 502937, 503006, 503050
+};
+
+/* FACCH-H1, block endings */
+uint32_t facch_h1_fn_samples[] = { 500728, 500771, 500797, 500841, 500875, 500919, 501751, 501794, 501837,
+ 502782, 502825, 502869, 502903, 502955, 502999
+};
+
+static void test_gsm0502_fn_remap()
+{
+ unsigned int i;
+ uint32_t fn_begin;
+ uint32_t fn_end;
+
+ printf("Testing gsm0502_fn_remap()\n");
+ printf("TCH/F\n");
+ for (i = 0; i < ARRAY_SIZE(tch_h1_fn_samples); i++) {
+ fn_end = tch_f_fn_samples[i];
+ fn_begin = gsm0502_fn_remap(fn_end, FN_REMAP_TCH_F);
+ printf("fn_end=%u, fn_end%%104=%u, fn_begin=%u, fn_begin%%104=%u\n", fn_end, fn_end % 104, fn_begin,
+ fn_begin % 104);
+ }
+ printf("\n");
+
+ printf("TCH/H0\n");
+ for (i = 0; i < ARRAY_SIZE(tch_h0_fn_samples); i++) {
+ fn_end = tch_h0_fn_samples[i];
+ fn_begin = gsm0502_fn_remap(fn_end, FN_REMAP_TCH_H0);
+ printf("fn_end=%u, fn_end%%104=%u, fn_begin=%u, fn_begin%%104=%u\n", fn_end, fn_end % 104, fn_begin,
+ fn_begin % 104);
+ }
+ printf("\n");
+
+ printf("TCH/H1\n");
+ for (i = 0; i < ARRAY_SIZE(tch_h1_fn_samples); i++) {
+ fn_end = tch_h1_fn_samples[i];
+ fn_begin = gsm0502_fn_remap(fn_end, FN_REMAP_TCH_H1);
+ printf("fn_end=%u, fn_end%%104=%u, fn_begin=%u, fn_begin%%104=%u\n", fn_end, fn_end % 104, fn_begin,
+ fn_begin % 104);
+ }
+ printf("\n");
+
+ printf("FACCH/F\n");
+ for (i = 0; i < ARRAY_SIZE(facch_f_fn_samples); i++) {
+ fn_end = facch_f_fn_samples[i];
+ fn_begin = gsm0502_fn_remap(fn_end, FN_REMAP_FACCH_F);
+ printf("fn_end=%u, fn_end%%104=%u, fn_begin=%u, fn_begin%%104=%u\n", fn_end, fn_end % 104, fn_begin,
+ fn_begin % 104);
+ }
+ printf("\n");
+
+ printf("FACCH/H0\n");
+ for (i = 0; i < ARRAY_SIZE(facch_h0_fn_samples); i++) {
+ fn_end = facch_h0_fn_samples[i];
+ fn_begin = gsm0502_fn_remap(fn_end, FN_REMAP_FACCH_H0);
+ printf("fn_end=%u, fn_end%%104=%u, fn_begin=%u, fn_begin%%104=%u\n", fn_end, fn_end % 104, fn_begin,
+ fn_begin % 104);
+ }
+ printf("\n");
+
+ printf("FACCH/H1\n");
+ for (i = 0; i < ARRAY_SIZE(facch_h1_fn_samples); i++) {
+ fn_end = facch_h1_fn_samples[i];
+ fn_begin = gsm0502_fn_remap(fn_end, FN_REMAP_FACCH_H1);
+ printf("fn_end=%u, fn_end%%104=%u, fn_begin=%u, fn_begin%%104=%u\n", fn_end, fn_end % 104, fn_begin,
+ fn_begin % 104);
+ }
+ printf("\n");
+}
+
+int main(int argc, char **argv)
+{
+ test_gsm0502_fn_remap();
+ return EXIT_SUCCESS;
+}
diff --git a/tests/gsm0502/gsm0502_test.ok b/tests/gsm0502/gsm0502_test.ok
new file mode 100644
index 00000000..89418d3f
--- /dev/null
+++ b/tests/gsm0502/gsm0502_test.ok
@@ -0,0 +1,271 @@
+Testing gsm0502_fn_remap()
+TCH/F
+fn_end=1036987, fn_end%104=3, fn_begin=1036979, fn_begin%104=99
+fn_end=1036991, fn_end%104=7, fn_begin=1036984, fn_begin%104=0
+fn_end=1036995, fn_end%104=11, fn_begin=1036988, fn_begin%104=4
+fn_end=1037000, fn_end%104=16, fn_begin=1036992, fn_begin%104=8
+fn_end=1037004, fn_end%104=20, fn_begin=1036997, fn_begin%104=13
+fn_end=1037008, fn_end%104=24, fn_begin=1037001, fn_begin%104=17
+fn_end=1037013, fn_end%104=29, fn_begin=1037005, fn_begin%104=21
+fn_end=1037017, fn_end%104=33, fn_begin=1037010, fn_begin%104=26
+fn_end=1037021, fn_end%104=37, fn_begin=1037014, fn_begin%104=30
+fn_end=1037026, fn_end%104=42, fn_begin=1037018, fn_begin%104=34
+fn_end=1037030, fn_end%104=46, fn_begin=1037023, fn_begin%104=39
+fn_end=1037034, fn_end%104=50, fn_begin=1037027, fn_begin%104=43
+fn_end=1037039, fn_end%104=55, fn_begin=1037031, fn_begin%104=47
+fn_end=1037043, fn_end%104=59, fn_begin=1037036, fn_begin%104=52
+fn_end=1037047, fn_end%104=63, fn_begin=1037040, fn_begin%104=56
+fn_end=1037052, fn_end%104=68, fn_begin=1037044, fn_begin%104=60
+fn_end=1037056, fn_end%104=72, fn_begin=1037049, fn_begin%104=65
+fn_end=1037060, fn_end%104=76, fn_begin=1037053, fn_begin%104=69
+fn_end=1037065, fn_end%104=81, fn_begin=1037057, fn_begin%104=73
+fn_end=1037069, fn_end%104=85, fn_begin=1037062, fn_begin%104=78
+fn_end=1037073, fn_end%104=89, fn_begin=1037066, fn_begin%104=82
+fn_end=1037078, fn_end%104=94, fn_begin=1037070, fn_begin%104=86
+fn_end=1037082, fn_end%104=98, fn_begin=1037075, fn_begin%104=91
+fn_end=1037086, fn_end%104=102, fn_begin=1037079, fn_begin%104=95
+fn_end=1037091, fn_end%104=3, fn_begin=1037083, fn_begin%104=99
+fn_end=1037095, fn_end%104=7, fn_begin=1037088, fn_begin%104=0
+fn_end=1037099, fn_end%104=11, fn_begin=1037092, fn_begin%104=4
+fn_end=1037104, fn_end%104=16, fn_begin=1037096, fn_begin%104=8
+fn_end=1037108, fn_end%104=20, fn_begin=1037101, fn_begin%104=13
+fn_end=1037112, fn_end%104=24, fn_begin=1037105, fn_begin%104=17
+fn_end=1037117, fn_end%104=29, fn_begin=1037109, fn_begin%104=21
+fn_end=1037121, fn_end%104=33, fn_begin=1037114, fn_begin%104=26
+fn_end=1037125, fn_end%104=37, fn_begin=1037118, fn_begin%104=30
+fn_end=1037130, fn_end%104=42, fn_begin=1037122, fn_begin%104=34
+fn_end=1037134, fn_end%104=46, fn_begin=1037127, fn_begin%104=39
+fn_end=1037138, fn_end%104=50, fn_begin=1037131, fn_begin%104=43
+fn_end=1037143, fn_end%104=55, fn_begin=1037135, fn_begin%104=47
+fn_end=1037147, fn_end%104=59, fn_begin=1037140, fn_begin%104=52
+fn_end=1037151, fn_end%104=63, fn_begin=1037144, fn_begin%104=56
+fn_end=1037156, fn_end%104=68, fn_begin=1037148, fn_begin%104=60
+fn_end=1037160, fn_end%104=72, fn_begin=1037153, fn_begin%104=65
+fn_end=1037164, fn_end%104=76, fn_begin=1037157, fn_begin%104=69
+fn_end=1037169, fn_end%104=81, fn_begin=1037161, fn_begin%104=73
+fn_end=1037173, fn_end%104=85, fn_begin=1037166, fn_begin%104=78
+fn_end=1037177, fn_end%104=89, fn_begin=1037170, fn_begin%104=82
+fn_end=1037182, fn_end%104=94, fn_begin=1037174, fn_begin%104=86
+fn_end=1037186, fn_end%104=98, fn_begin=1037179, fn_begin%104=91
+fn_end=1037190, fn_end%104=102, fn_begin=1037183, fn_begin%104=95
+fn_end=1037195, fn_end%104=3, fn_begin=1037187, fn_begin%104=99
+fn_end=1037199, fn_end%104=7, fn_begin=1037192, fn_begin%104=0
+fn_end=1037203, fn_end%104=11, fn_begin=1037196, fn_begin%104=4
+fn_end=1037208, fn_end%104=16, fn_begin=1037200, fn_begin%104=8
+fn_end=1037212, fn_end%104=20, fn_begin=1037205, fn_begin%104=13
+fn_end=1037216, fn_end%104=24, fn_begin=1037209, fn_begin%104=17
+fn_end=1037221, fn_end%104=29, fn_begin=1037213, fn_begin%104=21
+fn_end=1037225, fn_end%104=33, fn_begin=1037218, fn_begin%104=26
+fn_end=1037229, fn_end%104=37, fn_begin=1037222, fn_begin%104=30
+fn_end=1037234, fn_end%104=42, fn_begin=1037226, fn_begin%104=34
+fn_end=1037238, fn_end%104=46, fn_begin=1037231, fn_begin%104=39
+fn_end=1037242, fn_end%104=50, fn_begin=1037235, fn_begin%104=43
+fn_end=1037247, fn_end%104=55, fn_begin=1037239, fn_begin%104=47
+fn_end=1037251, fn_end%104=59, fn_begin=1037244, fn_begin%104=52
+fn_end=1037255, fn_end%104=63, fn_begin=1037248, fn_begin%104=56
+fn_end=1037260, fn_end%104=68, fn_begin=1037252, fn_begin%104=60
+fn_end=1037264, fn_end%104=72, fn_begin=1037257, fn_begin%104=65
+fn_end=1037268, fn_end%104=76, fn_begin=1037261, fn_begin%104=69
+fn_end=1037273, fn_end%104=81, fn_begin=1037265, fn_begin%104=73
+fn_end=1037277, fn_end%104=85, fn_begin=1037270, fn_begin%104=78
+fn_end=1037281, fn_end%104=89, fn_begin=1037274, fn_begin%104=82
+fn_end=1037286, fn_end%104=94, fn_begin=1037278, fn_begin%104=86
+fn_end=1037290, fn_end%104=98, fn_begin=1037283, fn_begin%104=91
+fn_end=1037294, fn_end%104=102, fn_begin=1037287, fn_begin%104=95
+
+TCH/H0
+fn_end=1175826, fn_end%104=2, fn_begin=1175819, fn_begin%104=99
+fn_end=1175830, fn_end%104=6, fn_begin=1175824, fn_begin%104=0
+fn_end=1175834, fn_end%104=10, fn_begin=1175828, fn_begin%104=4
+fn_end=1175839, fn_end%104=15, fn_begin=1175832, fn_begin%104=8
+fn_end=1175843, fn_end%104=19, fn_begin=1175837, fn_begin%104=13
+fn_end=1175847, fn_end%104=23, fn_begin=1175841, fn_begin%104=17
+fn_end=1175852, fn_end%104=28, fn_begin=1175845, fn_begin%104=21
+fn_end=1175856, fn_end%104=32, fn_begin=1175850, fn_begin%104=26
+fn_end=1175860, fn_end%104=36, fn_begin=1175854, fn_begin%104=30
+fn_end=1175865, fn_end%104=41, fn_begin=1175858, fn_begin%104=34
+fn_end=1175869, fn_end%104=45, fn_begin=1175863, fn_begin%104=39
+fn_end=1175873, fn_end%104=49, fn_begin=1175867, fn_begin%104=43
+fn_end=1175878, fn_end%104=54, fn_begin=1175871, fn_begin%104=47
+fn_end=1175882, fn_end%104=58, fn_begin=1175876, fn_begin%104=52
+fn_end=1175886, fn_end%104=62, fn_begin=1175880, fn_begin%104=56
+fn_end=1175891, fn_end%104=67, fn_begin=1175884, fn_begin%104=60
+fn_end=1175895, fn_end%104=71, fn_begin=1175889, fn_begin%104=65
+fn_end=1175899, fn_end%104=75, fn_begin=1175893, fn_begin%104=69
+fn_end=1175904, fn_end%104=80, fn_begin=1175897, fn_begin%104=73
+fn_end=1175908, fn_end%104=84, fn_begin=1175902, fn_begin%104=78
+fn_end=1175912, fn_end%104=88, fn_begin=1175906, fn_begin%104=82
+fn_end=1175917, fn_end%104=93, fn_begin=1175910, fn_begin%104=86
+fn_end=1175921, fn_end%104=97, fn_begin=1175915, fn_begin%104=91
+fn_end=1175925, fn_end%104=101, fn_begin=1175919, fn_begin%104=95
+fn_end=1175930, fn_end%104=2, fn_begin=1175923, fn_begin%104=99
+fn_end=1175934, fn_end%104=6, fn_begin=1175928, fn_begin%104=0
+fn_end=1175938, fn_end%104=10, fn_begin=1175932, fn_begin%104=4
+fn_end=1175943, fn_end%104=15, fn_begin=1175936, fn_begin%104=8
+fn_end=1175947, fn_end%104=19, fn_begin=1175941, fn_begin%104=13
+fn_end=1175951, fn_end%104=23, fn_begin=1175945, fn_begin%104=17
+fn_end=1175956, fn_end%104=28, fn_begin=1175949, fn_begin%104=21
+fn_end=1175960, fn_end%104=32, fn_begin=1175954, fn_begin%104=26
+fn_end=1175964, fn_end%104=36, fn_begin=1175958, fn_begin%104=30
+fn_end=1175969, fn_end%104=41, fn_begin=1175962, fn_begin%104=34
+fn_end=1175973, fn_end%104=45, fn_begin=1175967, fn_begin%104=39
+fn_end=1175977, fn_end%104=49, fn_begin=1175971, fn_begin%104=43
+fn_end=1175982, fn_end%104=54, fn_begin=1175975, fn_begin%104=47
+fn_end=1175986, fn_end%104=58, fn_begin=1175980, fn_begin%104=52
+fn_end=1175990, fn_end%104=62, fn_begin=1175984, fn_begin%104=56
+fn_end=1175995, fn_end%104=67, fn_begin=1175988, fn_begin%104=60
+fn_end=1175999, fn_end%104=71, fn_begin=1175993, fn_begin%104=65
+fn_end=1176003, fn_end%104=75, fn_begin=1175997, fn_begin%104=69
+fn_end=1176008, fn_end%104=80, fn_begin=1176001, fn_begin%104=73
+fn_end=1176012, fn_end%104=84, fn_begin=1176006, fn_begin%104=78
+fn_end=1176016, fn_end%104=88, fn_begin=1176010, fn_begin%104=82
+fn_end=1176021, fn_end%104=93, fn_begin=1176014, fn_begin%104=86
+fn_end=1176025, fn_end%104=97, fn_begin=1176019, fn_begin%104=91
+fn_end=1176029, fn_end%104=101, fn_begin=1176023, fn_begin%104=95
+fn_end=1176034, fn_end%104=2, fn_begin=1176027, fn_begin%104=99
+fn_end=1176038, fn_end%104=6, fn_begin=1176032, fn_begin%104=0
+fn_end=1176042, fn_end%104=10, fn_begin=1176036, fn_begin%104=4
+fn_end=1176047, fn_end%104=15, fn_begin=1176040, fn_begin%104=8
+fn_end=1176051, fn_end%104=19, fn_begin=1176045, fn_begin%104=13
+fn_end=1176055, fn_end%104=23, fn_begin=1176049, fn_begin%104=17
+fn_end=1176060, fn_end%104=28, fn_begin=1176053, fn_begin%104=21
+fn_end=1176064, fn_end%104=32, fn_begin=1176058, fn_begin%104=26
+fn_end=1176068, fn_end%104=36, fn_begin=1176062, fn_begin%104=30
+fn_end=1176073, fn_end%104=41, fn_begin=1176066, fn_begin%104=34
+fn_end=1176077, fn_end%104=45, fn_begin=1176071, fn_begin%104=39
+fn_end=1176081, fn_end%104=49, fn_begin=1176075, fn_begin%104=43
+fn_end=1176086, fn_end%104=54, fn_begin=1176079, fn_begin%104=47
+fn_end=1176090, fn_end%104=58, fn_begin=1176084, fn_begin%104=52
+fn_end=1176094, fn_end%104=62, fn_begin=1176088, fn_begin%104=56
+fn_end=1176099, fn_end%104=67, fn_begin=1176092, fn_begin%104=60
+fn_end=1176103, fn_end%104=71, fn_begin=1176097, fn_begin%104=65
+fn_end=1176107, fn_end%104=75, fn_begin=1176101, fn_begin%104=69
+fn_end=1176112, fn_end%104=80, fn_begin=1176105, fn_begin%104=73
+fn_end=1176116, fn_end%104=84, fn_begin=1176110, fn_begin%104=78
+fn_end=1176120, fn_end%104=88, fn_begin=1176114, fn_begin%104=82
+fn_end=1176125, fn_end%104=93, fn_begin=1176118, fn_begin%104=86
+fn_end=1176129, fn_end%104=97, fn_begin=1176123, fn_begin%104=91
+fn_end=1176133, fn_end%104=101, fn_begin=1176127, fn_begin%104=95
+
+TCH/H1
+fn_end=1175827, fn_end%104=3, fn_begin=1175820, fn_begin%104=100
+fn_end=1175831, fn_end%104=7, fn_begin=1175825, fn_begin%104=1
+fn_end=1175835, fn_end%104=11, fn_begin=1175829, fn_begin%104=5
+fn_end=1175840, fn_end%104=16, fn_begin=1175833, fn_begin%104=9
+fn_end=1175844, fn_end%104=20, fn_begin=1175838, fn_begin%104=14
+fn_end=1175848, fn_end%104=24, fn_begin=1175842, fn_begin%104=18
+fn_end=1175853, fn_end%104=29, fn_begin=1175846, fn_begin%104=22
+fn_end=1175857, fn_end%104=33, fn_begin=1175851, fn_begin%104=27
+fn_end=1175861, fn_end%104=37, fn_begin=1175855, fn_begin%104=31
+fn_end=1175866, fn_end%104=42, fn_begin=1175859, fn_begin%104=35
+fn_end=1175870, fn_end%104=46, fn_begin=1175864, fn_begin%104=40
+fn_end=1175874, fn_end%104=50, fn_begin=1175868, fn_begin%104=44
+fn_end=1175879, fn_end%104=55, fn_begin=1175872, fn_begin%104=48
+fn_end=1175883, fn_end%104=59, fn_begin=1175877, fn_begin%104=53
+fn_end=1175887, fn_end%104=63, fn_begin=1175881, fn_begin%104=57
+fn_end=1175892, fn_end%104=68, fn_begin=1175885, fn_begin%104=61
+fn_end=1175896, fn_end%104=72, fn_begin=1175890, fn_begin%104=66
+fn_end=1175900, fn_end%104=76, fn_begin=1175894, fn_begin%104=70
+fn_end=1175905, fn_end%104=81, fn_begin=1175898, fn_begin%104=74
+fn_end=1175909, fn_end%104=85, fn_begin=1175903, fn_begin%104=79
+fn_end=1175913, fn_end%104=89, fn_begin=1175907, fn_begin%104=83
+fn_end=1175918, fn_end%104=94, fn_begin=1175911, fn_begin%104=87
+fn_end=1175922, fn_end%104=98, fn_begin=1175916, fn_begin%104=92
+fn_end=1175926, fn_end%104=102, fn_begin=1175920, fn_begin%104=96
+fn_end=1175931, fn_end%104=3, fn_begin=1175924, fn_begin%104=100
+fn_end=1175935, fn_end%104=7, fn_begin=1175929, fn_begin%104=1
+fn_end=1175939, fn_end%104=11, fn_begin=1175933, fn_begin%104=5
+fn_end=1175944, fn_end%104=16, fn_begin=1175937, fn_begin%104=9
+fn_end=1175948, fn_end%104=20, fn_begin=1175942, fn_begin%104=14
+fn_end=1175952, fn_end%104=24, fn_begin=1175946, fn_begin%104=18
+fn_end=1175957, fn_end%104=29, fn_begin=1175950, fn_begin%104=22
+fn_end=1175961, fn_end%104=33, fn_begin=1175955, fn_begin%104=27
+fn_end=1175965, fn_end%104=37, fn_begin=1175959, fn_begin%104=31
+fn_end=1175970, fn_end%104=42, fn_begin=1175963, fn_begin%104=35
+fn_end=1175974, fn_end%104=46, fn_begin=1175968, fn_begin%104=40
+fn_end=1175978, fn_end%104=50, fn_begin=1175972, fn_begin%104=44
+fn_end=1175983, fn_end%104=55, fn_begin=1175976, fn_begin%104=48
+fn_end=1175987, fn_end%104=59, fn_begin=1175981, fn_begin%104=53
+fn_end=1175991, fn_end%104=63, fn_begin=1175985, fn_begin%104=57
+fn_end=1175996, fn_end%104=68, fn_begin=1175989, fn_begin%104=61
+fn_end=1176000, fn_end%104=72, fn_begin=1175994, fn_begin%104=66
+fn_end=1176004, fn_end%104=76, fn_begin=1175998, fn_begin%104=70
+fn_end=1176009, fn_end%104=81, fn_begin=1176002, fn_begin%104=74
+fn_end=1176013, fn_end%104=85, fn_begin=1176007, fn_begin%104=79
+fn_end=1176017, fn_end%104=89, fn_begin=1176011, fn_begin%104=83
+fn_end=1176022, fn_end%104=94, fn_begin=1176015, fn_begin%104=87
+fn_end=1176026, fn_end%104=98, fn_begin=1176020, fn_begin%104=92
+fn_end=1176030, fn_end%104=102, fn_begin=1176024, fn_begin%104=96
+fn_end=1176035, fn_end%104=3, fn_begin=1176028, fn_begin%104=100
+fn_end=1176039, fn_end%104=7, fn_begin=1176033, fn_begin%104=1
+fn_end=1176043, fn_end%104=11, fn_begin=1176037, fn_begin%104=5
+fn_end=1176048, fn_end%104=16, fn_begin=1176041, fn_begin%104=9
+fn_end=1176052, fn_end%104=20, fn_begin=1176046, fn_begin%104=14
+fn_end=1176056, fn_end%104=24, fn_begin=1176050, fn_begin%104=18
+fn_end=1176061, fn_end%104=29, fn_begin=1176054, fn_begin%104=22
+fn_end=1176065, fn_end%104=33, fn_begin=1176059, fn_begin%104=27
+fn_end=1176069, fn_end%104=37, fn_begin=1176063, fn_begin%104=31
+fn_end=1176074, fn_end%104=42, fn_begin=1176067, fn_begin%104=35
+fn_end=1176078, fn_end%104=46, fn_begin=1176072, fn_begin%104=40
+fn_end=1176082, fn_end%104=50, fn_begin=1176076, fn_begin%104=44
+fn_end=1176087, fn_end%104=55, fn_begin=1176080, fn_begin%104=48
+fn_end=1176091, fn_end%104=59, fn_begin=1176085, fn_begin%104=53
+fn_end=1176095, fn_end%104=63, fn_begin=1176089, fn_begin%104=57
+fn_end=1176100, fn_end%104=68, fn_begin=1176093, fn_begin%104=61
+fn_end=1176104, fn_end%104=72, fn_begin=1176098, fn_begin%104=66
+fn_end=1176108, fn_end%104=76, fn_begin=1176102, fn_begin%104=70
+fn_end=1176113, fn_end%104=81, fn_begin=1176106, fn_begin%104=74
+fn_end=1176117, fn_end%104=85, fn_begin=1176111, fn_begin%104=79
+fn_end=1176121, fn_end%104=89, fn_begin=1176115, fn_begin%104=83
+fn_end=1176126, fn_end%104=94, fn_begin=1176119, fn_begin%104=87
+fn_end=1176130, fn_end%104=98, fn_begin=1176124, fn_begin%104=92
+fn_end=1176134, fn_end%104=102, fn_begin=1176128, fn_begin%104=96
+
+FACCH/F
+fn_end=177275, fn_end%104=59, fn_begin=177268, fn_begin%104=52
+fn_end=177314, fn_end%104=98, fn_begin=177307, fn_begin%104=91
+fn_end=177336, fn_end%104=16, fn_begin=177328, fn_begin%104=8
+fn_end=177375, fn_end%104=55, fn_begin=177367, fn_begin%104=47
+fn_end=177396, fn_end%104=76, fn_begin=177389, fn_begin%104=69
+fn_end=177435, fn_end%104=11, fn_begin=177428, fn_begin%104=4
+fn_end=178328, fn_end%104=72, fn_begin=178321, fn_begin%104=65
+fn_end=178367, fn_end%104=7, fn_begin=178360, fn_begin%104=0
+fn_end=178393, fn_end%104=33, fn_begin=178386, fn_begin%104=26
+fn_end=180014, fn_end%104=94, fn_begin=180006, fn_begin%104=86
+fn_end=180053, fn_end%104=29, fn_begin=180045, fn_begin%104=21
+fn_end=180079, fn_end%104=55, fn_begin=180071, fn_begin%104=47
+fn_end=180113, fn_end%104=89, fn_begin=180106, fn_begin%104=82
+fn_end=180144, fn_end%104=16, fn_begin=180136, fn_begin%104=8
+fn_end=180183, fn_end%104=55, fn_begin=180175, fn_begin%104=47
+
+FACCH/H0
+fn_end=499956, fn_end%104=28, fn_begin=499945, fn_begin%104=17
+fn_end=499999, fn_end%104=71, fn_begin=499988, fn_begin%104=60
+fn_end=500034, fn_end%104=2, fn_begin=500023, fn_begin%104=95
+fn_end=500077, fn_end%104=45, fn_begin=500066, fn_begin%104=34
+fn_end=500952, fn_end%104=88, fn_begin=500942, fn_begin%104=78
+fn_end=501836, fn_end%104=36, fn_begin=501826, fn_begin%104=26
+fn_end=501880, fn_end%104=80, fn_begin=501869, fn_begin%104=69
+fn_end=502850, fn_end%104=10, fn_begin=502840, fn_begin%104=0
+fn_end=502894, fn_end%104=54, fn_begin=502883, fn_begin%104=43
+fn_end=502937, fn_end%104=97, fn_begin=502926, fn_begin%104=86
+fn_end=503006, fn_end%104=62, fn_begin=502996, fn_begin%104=52
+fn_end=503050, fn_end%104=2, fn_begin=503039, fn_begin%104=95
+
+FACCH/H1
+fn_end=500728, fn_end%104=72, fn_begin=500717, fn_begin%104=61
+fn_end=500771, fn_end%104=11, fn_begin=500761, fn_begin%104=1
+fn_end=500797, fn_end%104=37, fn_begin=500787, fn_begin%104=27
+fn_end=500841, fn_end%104=81, fn_begin=500830, fn_begin%104=70
+fn_end=500875, fn_end%104=11, fn_begin=500865, fn_begin%104=1
+fn_end=500919, fn_end%104=55, fn_begin=500908, fn_begin%104=44
+fn_end=501751, fn_end%104=55, fn_begin=501740, fn_begin%104=44
+fn_end=501794, fn_end%104=98, fn_begin=501783, fn_begin%104=87
+fn_end=501837, fn_end%104=37, fn_begin=501827, fn_begin%104=27
+fn_end=502782, fn_end%104=46, fn_begin=502771, fn_begin%104=35
+fn_end=502825, fn_end%104=89, fn_begin=502815, fn_begin%104=79
+fn_end=502869, fn_end%104=29, fn_begin=502858, fn_begin%104=18
+fn_end=502903, fn_end%104=63, fn_begin=502893, fn_begin%104=53
+fn_end=502955, fn_end%104=11, fn_begin=502945, fn_begin%104=1
+fn_end=502999, fn_end%104=55, fn_begin=502988, fn_begin%104=44
+
diff --git a/tests/testsuite.at b/tests/testsuite.at
index a043f0c7..c231b964 100644
--- a/tests/testsuite.at
+++ b/tests/testsuite.at
@@ -126,6 +126,12 @@ cat $abs_srcdir/lapd/lapd_test.ok > expout
AT_CHECK([$abs_top_builddir/tests/lapd/lapd_test], [0], [expout], [ignore])
AT_CLEANUP
+AT_SETUP([gsm0502])
+AT_KEYWORDS([gsm0502])
+cat $abs_srcdir/gsm0502/gsm0502_test.ok > expout
+AT_CHECK([$abs_top_builddir/tests/gsm0502/gsm0502_test], [0], [expout], [ignore])
+AT_CLEANUP
+
AT_SETUP([gsm0808])
AT_KEYWORDS([gsm0808])
cat $abs_srcdir/gsm0808/gsm0808_test.ok > expout