gsm: TS 44.021 modified V.110 frame encoding/decoding support
3GPP TS 44.021 specifies the format for modified V.110 frames as used
on the GSM air (radio) interface. Implement encoders and decoders for
this modified V.110 format.
Related: OS#1572
Change-Id: I60a2f2690459359437df20cf4da9043fa7c3ad11
diff --git a/tests/Makefile.am b/tests/Makefile.am
index f0c80d5..275cf5f 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -52,6 +52,7 @@
auth/xor2g_test \
v110/test_frame \
v110/test_ra1 \
+ gsm44021/test_frame_csd \
$(NULL)
if ENABLE_MSGFILE
@@ -347,6 +348,11 @@
v110_test_ra1_SOURCES = v110/test_ra1.c
v110_test_ra1_LDADD = $(LDADD) $(top_builddir)/src/isdn/libosmoisdn.la
+gsm44021_test_frame_csd_SOURCES = gsm44021/test_frame_csd.c
+gsm44021_test_frame_csd_LDADD = $(LDADD) $(top_builddir)/src/isdn/libosmoisdn.la \
+ $(top_builddir)/src/gsm/libosmogsm.la
+
+
# The `:;' works around a Bash 3.2 bug when the output is not writeable.
$(srcdir)/package.m4: $(top_srcdir)/configure.ac
:;{ \
@@ -447,6 +453,7 @@
smscb/cbsp_test.ok \
v110/test_frame.ok \
v110/test_ra1.ok \
+ gsm44021/test_frame_csd.ok \
$(NULL)
if ENABLE_LIBSCTP
@@ -654,6 +661,8 @@
>$(srcdir)/v110/test_frame.ok
v110/test_ra1 \
>$(srcdir)/v110/test_ra1.ok
+ gsm44021/test_frame_csd \
+ >$(srcdir)/gsm44021/test_frame_csd.ok
check-local: atconfig $(TESTSUITE)
[ -e /proc/cpuinfo ] && cat /proc/cpuinfo
diff --git a/tests/gsm44021/test_frame_csd.c b/tests/gsm44021/test_frame_csd.c
new file mode 100644
index 0000000..98efdac
--- /dev/null
+++ b/tests/gsm44021/test_frame_csd.c
@@ -0,0 +1,93 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+
+#include <osmocom/core/bits.h>
+#include <osmocom/isdn/v110.h>
+#include <osmocom/gsm/gsm44021.h>
+
+
+static void fill_v110_frame(struct osmo_v110_decoded_frame *fr)
+{
+ unsigned int i;
+
+ memset(fr, 0, sizeof(*fr));
+
+ /* we abuse the fact that ubit_t is 8bit so we can actually
+ * store integer values to clearly identify which bit ends up where */
+
+ /* D1..D48: 101..148 */
+ for (i = 0; i < ARRAY_SIZE(fr->d_bits); i++)
+ fr->d_bits[i] = 101 + i;
+ /* E1..E7: 201..207 */
+ for (i = 0; i < ARRAY_SIZE(fr->e_bits); i++)
+ fr->e_bits[i] = 201 + i;
+ /* S1..S9: 211..219 */
+ for (i = 0; i < ARRAY_SIZE(fr->s_bits); i++)
+ fr->s_bits[i] = 211 + i;
+ /* X1..X2: 221..222 */
+ for (i = 0; i < ARRAY_SIZE(fr->x_bits); i++)
+ fr->x_bits[i] = 221 + i;
+}
+
+
+static void test_frame_enc_12k_6k(void)
+{
+ struct osmo_v110_decoded_frame fr;
+ ubit_t bits[60];
+
+ printf("Testing Frame Encoding for 12k/6k radio interface rate\n");
+
+ fill_v110_frame(&fr);
+
+ /* run encoder and dump to stdout */
+ memset(bits, 0xff, sizeof(bits));
+ osmo_csd_12k_6k_encode_frame(bits, sizeof(bits), &fr);
+ osmo_csd_ubit_dump(stdout, bits, sizeof(bits));
+
+ /* run decoder on what we just encoded */
+ memset(&fr, 0, sizeof(fr));
+ osmo_csd_12k_6k_decode_frame(&fr, bits, sizeof(bits));
+
+ /* re-encode and dump again 'expout' will match it. */
+ memset(bits, 0xff, sizeof(bits));
+ osmo_csd_12k_6k_encode_frame(bits, sizeof(bits), &fr);
+ osmo_csd_ubit_dump(stdout, bits, sizeof(bits));
+}
+
+static void test_frame_enc_3k6(void)
+{
+ struct osmo_v110_decoded_frame fr;
+ ubit_t bits[36];
+
+ printf("Testing Frame Encoding for 3.6k radio interface rate\n");
+
+ fill_v110_frame(&fr);
+ /* different D-bit numbering for 3k6, see TS 44.021 Section 8.1.4 */
+ for (unsigned int i = 0; i < ARRAY_SIZE(fr.d_bits); i++)
+ fr.d_bits[i] = 101 + i/2;
+
+ /* run encoder and dump to stdout */
+ memset(bits, 0xff, sizeof(bits));
+ osmo_csd_3k6_encode_frame(bits, sizeof(bits), &fr);
+ osmo_csd_ubit_dump(stdout, bits, sizeof(bits));
+
+ /* run decoder on what we just encoded */
+ memset(&fr, 0, sizeof(fr));
+ osmo_csd_3k6_decode_frame(&fr, bits, sizeof(bits));
+
+ /* re-encode and dump again 'expout' will match it. */
+ memset(bits, 0xff, sizeof(bits));
+ osmo_csd_3k6_encode_frame(bits, sizeof(bits), &fr);
+ osmo_csd_ubit_dump(stdout, bits, sizeof(bits));
+}
+
+
+int main(int argc, char **argv)
+{
+ test_frame_enc_12k_6k();
+ printf("\n");
+ test_frame_enc_3k6();
+}
+
diff --git a/tests/gsm44021/test_frame_csd.ok b/tests/gsm44021/test_frame_csd.ok
new file mode 100644
index 0000000..1a5d3f2
--- /dev/null
+++ b/tests/gsm44021/test_frame_csd.ok
@@ -0,0 +1,31 @@
+Testing Frame Encoding for 12k/6k radio interface rate
+101 102 103 104 105 106 211
+107 108 109 110 111 112 221
+113 114 115 116 117 118 213
+119 120 121 122 123 124 214
+204 205 206 207 125 126 127
+128 129 130 216 131 132 133
+134 135 136 222 137 138 139
+140 141 142 218 143 144 145
+146 147 148 219
+101 102 103 104 105 106 211
+107 108 109 110 111 112 221
+113 114 115 116 117 118 213
+119 120 121 122 123 124 214
+204 205 206 207 125 126 127
+128 129 130 216 131 132 133
+134 135 136 222 137 138 139
+140 141 142 218 143 144 145
+146 147 148 219
+
+Testing Frame Encoding for 3.6k radio interface rate
+101 102 103 211 104 105 106 221
+107 108 109 213 110 111 112 214
+204 205 206 207 113 114 115 216
+116 117 118 222 119 120 121 218
+122 123 124 219
+101 102 103 211 104 105 106 221
+107 108 109 213 110 111 112 214
+204 205 206 207 113 114 115 216
+116 117 118 222 119 120 121 218
+122 123 124 219
diff --git a/tests/testsuite.at b/tests/testsuite.at
index 39cf54a..60aa74d 100644
--- a/tests/testsuite.at
+++ b/tests/testsuite.at
@@ -502,3 +502,9 @@
cat $abs_srcdir/v110/test_ra1.ok > expout
AT_CHECK([$abs_top_builddir/tests/v110/test_ra1], [], [expout],[])
AT_CLEANUP
+
+AT_SETUP([gsm44021_test_frame_csd])
+AT_KEYWORDS([gsm44021_test_frame_csd])
+cat $abs_srcdir/gsm44021/test_frame_csd.ok > expout
+AT_CHECK([$abs_top_builddir/tests/gsm44021/test_frame_csd], [], [expout],[])
+AT_CLEANUP