blob: 4ee5bf7fc215681c7988dabf446ed5899fd76b67 [file] [log] [blame]
Philipp Maier898c9c62020-02-06 14:25:01 +01001/*
2 * (C) 2019 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
3 * Author: Philipp Maier <pmaier@sysmocom.de>
4 * All Rights Reserved
5 *
6 * SPDX-License-Identifier: GPL-2.0+
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
Philipp Maier898c9c62020-02-06 14:25:01 +010018 */
19
20#include <string.h>
21#include <stdio.h>
22#include <stdint.h>
23#include <osmocom/core/utils.h>
Vadim Yanitskiyf673fd52022-05-18 01:16:27 +030024#include <osmocom/coding/gsm0503_coding.h>
Philipp Maier898c9c62020-02-06 14:25:01 +010025#include <osmocom/coding/gsm0503_amr_dtx.h>
26
Vadim Yanitskiyf673fd52022-05-18 01:16:27 +030027/* Length of payload bits in a Normal Burst */
28#define BURST_PLEN (57 * 2 + 2)
29
Philipp Maier898c9c62020-02-06 14:25:01 +010030char sample_afs_sid_frame[] =
31 {
32"111111110000000011001100101010100100010011111111001000100111011110011001001100111100110010011001111011100100010011111111001000100111011110011001001100111100110010011001111011100100010011111111001000100111011110011001001100111100110010011001111011100100010011111111001000100111011110011001001100111100110010011001111011100100010011111111001000100111011110011001001100111100110010011001111011100100010011111111001000100111011110011001001100111100110010011001"
33};
34
35char sample_afs_sid_update_frame[] =
36 {
37"111111110000000011001100101010100000010000001111111100101011011110001001000000110111110000001001011111101111010011001111100000101000011111001001111100110111110011111001001111101100010001001111000000100100011100111001100000111000110000111001010011101111010011111111010000101100011100111001111100110111110011111001110011101000010010001111110000100000011111001001011100110011110010111001101111100011010001111111001100100100011111111001000000110000110000001001"
38};
39
40char sample_afs_onset_frame[] =
41 {
42"111111110000000011001100101010100000111100000000111111000100101000111111100000000111110010001010001111110100000011111100111110100100111111000000110011001011101001001111011100001011110000001010010011111100000000111100111110101000111110110000111111000000101011111111010000001100110000111010111111111000000010111100000010100100111100110000100011001000101000111111101100001011110000111010011111110011000010111100101110101100111111000000010011001111101000001111"
43};
44
45char sample_ahs_sid_update_frame[] =
46 {
47"111100001100101010110000110110000110110000110110000110110000110110000110110000110110000110110000110110000110110000110110000110110000110110000110110000110110000110110000110110000110110000110110000110110000110110000110110000110110100011001000011010000000000000001111010010000000000001000000000010110000000011001000000000000000100000101000000000000000001010100000010010000000000010000111110001110110110011001101000000000100100011001000001010000100100000000011"
48};
49
50char sample_ahs_sid_first_p1_frame[] =
51 {
52"111100001100101001001111001001111001001111001001111001001111001001111001001111001001111001001111001001111001001111001001111001001111001001111001001111001001111001001111001001111001001111001001111001001111001001111001001111001001001011010110001101100101001110001111001110100110010000111101110110110000100100011111001001110000011110110001010010101100001010100000111101110110001010000111110001110110110011001101001111000011101001010011100011000111010110000011"
53};
54
55char sample_ahs_sid_first_p2_frame[] =
56 {
57"111110100100000010100000110111001110101100000100101001011101100011101010010000001010010010001100101010100100010111110101110011011110101000010100111000001001110111101110010101001110000010001101101011110000000011100100110110011111100011001000001101100101001110001111001110100110010000111101110110110000100100011111001001110000011110110001010010101100001010100000111101110110001010000111110001110110110011001101001111000011101001010011100011000111010110000011"
58};
59
60char sample_ahs_onset_frame[] =
61 {
62"111101011000101001010000111001000111011110000000011110001110010011011111100000101101101001101110011111010000000001010010110001101101110100000010011110101100010001011101101010000111100011101100111101011010100011110010110001001111100011001000011010000000000000001010010010000000000001000000000000100000000011001000000000000000100000101000000000000000010010000101010010000000000010101100111110101000110110011001000000000100100011001000001010000100100000001100"
63};
64
65char sample_sid_first_inh_frame[] =
66 {
67"xBxBxBxBxBxBxBxBxBxBxBxBxBxBxBxBx1x0x1x1x0x0x0x0x1x1x0x1x1x0x0x0x0x1x1x0x1x1x0x0x0x0x1x1x0x1x1x0x0x0x0x1x1x0x1x1x0x0x0x0x1x1x0x1x1x0x0x0x0x1x1x0x1x1x0x0x0x0x1x1x0x1x1x0x0x0x0x1x1x0x1x1x0x0x0x0x1x1x0x1x1x0x0x0x0x1x1x0x1x1x0x0x0x0x1x1x0x1x1x0x0x0x0x1x1x0x1x1x0x0x0x0x1x1x0x1x1x0x0x0x0x1x1x0x1x1x0x0x0x0x1x1x0x1x1x0x0x0x0x1x1x0x1x1x0x0x0x0x1x1x0x1x1x0x0x0x0x1x1x0x1x1x0x0x0x0x1x1x0x1x1x0x0x0x0x1x1x0x1x1x0x0x0x0x1x1x0x1x1x0x0x0x0x1x1x0x1x1x0x0x0x0x1x1x0x1x1x0"
68};
69
70char sample_sid_update_inh_frame[] =
71 {
72"xBxBxBxBxBxBxBxBxBxBxBxBxBxBxBxBx0x1x0x0x1x1x1x1x0x0x1x0x0x1x1x1x1x0x0x1x0x0x1x1x1x1x0x0x1x0x0x1x1x1x1x0x0x1x0x0x1x1x1x1x0x0x1x0x0x1x1x1x1x0x0x1x0x0x1x1x1x1x0x0x1x0x0x1x1x1x1x0x0x1x0x0x1x1x1x1x0x0x1x0x0x1x1x1x1x0x0x1x0x0x1x1x1x1x0x0x1x0x0x1x1x1x1x0x0x1x0x0x1x1x1x1x0x0x1x0x0x1x1x1x1x0x0x1x0x0x1x1x1x1x0x0x1x0x0x1x1x1x1x0x0x1x0x0x1x1x1x1x0x0x1x0x0x1x1x1x1x0x0x1x0x0x1x1x1x1x0x0x1x0x0x1x1x1x1x0x0x1x0x0x1x1x1x1x0x0x1x0x0x1x1x1x1x0x0x1x0x0x1x1x1x1x0x0x1x0x0x1"
73};
74
75unsigned int string_to_ubit(ubit_t * ubits, char *string)
76{
77 unsigned int len;
78 unsigned int i;
79
80 len = strlen(string);
81
82 for (i = 0; i < len; i++) {
83 ubits[i] = string[i] & 1;
84 }
85
86 return len;
87}
88
89void test_gsm0503_detect_afs_dtx_frame(char *string)
90{
91 ubit_t ubits[512];
92 uint8_t dtx_frame_type;
93 int n_errors;
94 int n_bits_total;
95
96 string_to_ubit(ubits, string);
97 dtx_frame_type = gsm0503_detect_afs_dtx_frame(&n_errors, &n_bits_total, ubits);
98 printf(" ==> %s, n_errors=%i, n_bits_total=%i\n", gsm0503_amr_dtx_frame_name(dtx_frame_type),
99 n_errors, n_bits_total);
100}
101
102void test_gsm0503_detect_ahs_dtx_frame(char *string)
103{
104 ubit_t ubits[512];
105 uint8_t dtx_frame_type;
106 int n_errors;
107 int n_bits_total;
108
109 string_to_ubit(ubits, string);
110 dtx_frame_type = gsm0503_detect_ahs_dtx_frame(&n_errors, &n_bits_total, ubits);
111 printf(" ==> %s, n_errors=%i, n_bits_total=%i\n", gsm0503_amr_dtx_frame_name(dtx_frame_type),
112 n_errors, n_bits_total);
113}
114
Vadim Yanitskiyf673fd52022-05-18 01:16:27 +0300115static void test_gsm0503_tch_afhs_decode_dtx(const sbit_t *bursts, size_t offset,
116 enum gsm0503_amr_dtx_frames *amr_last_dtx,
117 bool full_rate, const char *test_desc)
118{
119 uint8_t tch_data[128]; /* just to be safe */
120 int n_errors = 0, n_bits_total = 0;
121 int rc;
122
123 printf("Running %s(at offset=%zu): testing %s\n", __func__, offset, test_desc);
124
125 /* Dummy (not really important) values */
126 uint8_t codec[4] = { 0, 1, 2, 3 };
127 int codecs = ARRAY_SIZE(codec);
128 uint8_t ul_cmr = 0;
129 uint8_t ul_ft = 0;
130
131 if (full_rate) {
132 rc = gsm0503_tch_afs_decode_dtx(&tch_data[0], &bursts[offset], false,
133 codec, codecs, &ul_ft, &ul_cmr,
134 &n_errors, &n_bits_total,
135 (uint8_t *)amr_last_dtx);
136 } else {
137 rc = gsm0503_tch_ahs_decode_dtx(&tch_data[0], &bursts[offset], false, false,
138 codec, codecs, &ul_ft, &ul_cmr,
139 &n_errors, &n_bits_total,
140 (uint8_t *)amr_last_dtx);
141 }
142 printf(" ==> gsm0503_tch_a%cs_decode_dtx() yields '%s' (rc=%d, BER %d/%d)\n",
143 full_rate ? 'f' : 'h', gsm0503_amr_dtx_frame_name(*amr_last_dtx),
144 rc, n_errors, n_bits_total);
145 if (rc > 0)
146 printf(" ====> tch_data[] = { %s }\n", osmo_hexdump_nospc(tch_data, rc));
147}
148
149static void test_gsm0503_tch_afhs_decode_dtx_sid_update(void)
150{
151 enum gsm0503_amr_dtx_frames amr_last_dtx = AMR_OTHER;
152 sbit_t bursts[BURST_PLEN * 12]; /* 12 bursts */
153 int rc;
154
155 /* 456 soft-bits containing an AFS_SID_UPDATE frame (captured on the air) */
156 const char *afs_sid_update = \
157 "94 81 83 76 7b 81 6b 7f 76 8c 81 81 81 86 71 7f 75 81 6d 7a 81 6b 7f 78 8a 87 70 75 8e"
158 "81 8d 7f 81 70 72 81 7f 85 86 7f 93 81 8a 74 7f 71 89 8a 75 7f 7f 78 8c 81 8b 7f 81 7f"
159 "7f 7f 70 8a 8b 7f 90 81 81 81 8a 77 7f 7f 70 81 70 71 86 8e 7f 81 7f 81 75 72 87 8c 76"
160 "7f 72 8e 81 81 81 81 92 7f 8c 81 92 7f 8c 89 7f 81 7f 8f 8b 77 76 86 8c 78 73 88 81 8b"
161 "81 7f 8c 85 77 7b 8d 81 81 81 8b 7f 81 7f 8e 81 8e 7f 8a 8a 7f 93 85 6b 7f 7f 72 81 6f"
162 "76 89 81 81 81 8a 73 7f 72 88 87 73 7f 73 81 7f 81 7f 92 87 73 78 81 6f 7f 71 81 76 77"
163 "6f 81 7f 81 71 7f 6e 81 75 77 83 81 81 90 7f 8b 88 76 76 8a 8d 76 74 81 7f 92 81 81 8b"
164 "78 72 81 77 76 81 6c 7c 8b 81 81 8d 7f 8b 81 8e 74 7f 7f 72 81 7f 81 74 7f 71 81 75 7f"
165 "8e 81 81 8c 72 79 85 8c 78 75 8c 8a 7f 90 81 8e 77 77 81 70 7f 7f 71 81 7f 81 7f 8e 89"
166 "7f 8f 81 8f 7f 8c 8d 7f 81 7f 81 6f 7f 71 8a 87 7f 81 6f 77 81 7f 8d 88 73 79 8a 8a 7f"
167 "7f 7f 7f 7f 76 8b 81 8c 77 7c 8a 81 91 7f 81 76 79 81 71 7f 7f 6f 84 8e 78 7f 7f 7f 74"
168 "88 86 7b 77 81 6f 7f 7f 7f 7f 7f 75 81 70 7f 76 89 81 81 81 8d 78 74 84 81 8e 7f 8d 8a"
169 "7f 79 8c 87 7f 81 7f 81 6f 7f 75 8d 8a 7f 81 7f 92 81 81 85 76 7f 6f 8c 88 6c 7f 73 91"
170 "81 8d 71 7f 7f 73 8d 88 7f 81 7f 91 86 6f 7f 73 8e 81 8d 79 78 81 72 74 8c 86 72 7f 77"
171 "6e 81 7f 81 77 76 81 72 74 81 6f 7f 6f 8d 81 91 7f 81 6d 7f 6d 81 6c 7f 6c 81 7f 81 7f"
172 "8c 8b 7f 8e 89 74 74 8c 81 81 81 81 81 92 7f 8e 8b 7f 93 81 8f 7f 90 81 8d 74 7b 8b 89";
173
174 memset(&bursts[0], 0, sizeof(bursts));
175 rc = osmo_hexparse(afs_sid_update, (uint8_t *)&bursts[BURST_PLEN * 4], BURST_PLEN * 8);
176 OSMO_ASSERT(rc == BURST_PLEN * 4);
177
178 /* Test detection of AFS_SID_UPDATE (marker) */
179 test_gsm0503_tch_afhs_decode_dtx(&bursts[0], BURST_PLEN * 0, &amr_last_dtx, true /* AFS */,
180 "detection of AFS_SID_UPDATE");
181
182 /* Test decoding of AFS_SID_UPDATE_CN (actual SID) */
183 test_gsm0503_tch_afhs_decode_dtx(&bursts[0], BURST_PLEN * 4, &amr_last_dtx, true /* AFS */,
184 "decoding of AFS_SID_UPDATE");
185
186 /* 456 soft-bits containing an AHS_SID_UPDATE frame (captured on the air) */
187 const char *ahs_sid_update = \
188 "81 67 7f 7f 7f 71 8f 88 6f 73 81 7e 81 6b 7f 7e 7d 6f 8f 8a 72 76 92 81 82 81 8f 6d 6f"
189 "81 7f 92 8c 7f 97 81 8e 6f 7f 7c 7f 6e 81 7e 81 6e 73 81 7f 93 8d 6f 7f 6c 81 6b 7f 72"
190 "7c 7c 7d 7f 6f 8f 81 94 7f 92 8d 6e 7d 7d 7f 6c 8b 8e 73 71 81 7f 92 90 7f 81 6e 6e 81"
191 "7f 94 8e 70 7f 6e 8c 8d 77 7f 6a 81 7f 81 70 6d 81 6c 71 8c 91 7f 90 8e 73 6e 81 6d 7f"
192 "81 8b 71 6e 81 7f 82 7c 81 7f 81 6d 73 81 6c 6d 81 6d 7f 6e 81 7e 81 6b 7f 7f 7f 6b 81"
193 "6e 6f 81 68 7f 71 91 81 82 81 8e 70 7f 7c 7d 7f 70 81 7f 91 8f 7f 81 6c 7f 71 81 6d 74"
194 "6f 8f 81 92 7f 82 7f 91 8b 7f 81 6b 7f 6d 81 6b 6f 81 6f 6e 90 81 81 92 7f 94 81 95 7f"
195 "96 81 96 70 7f 72 8f 81 95 7f 81 6f 70 81 7f 90 92 7f 81 6c 70 81 6b 7f 6f 8d 8d 7f 81"
196 "77 81 6a 7e 7e 73 92 8c 7f 81 6a 7f 6c 8e 8e 6e 7f 71 8e 8d 7e 81 6d 7f 6c 81 6d 6c 81"
197 "7f 94 81 92 7f 97 81 92 6e 7f 70 8c 8b 73 73 91 81 93 7f 81 70 72 81 7d 81 71 70 81 7f"
198 "7d 7f 6d 90 8d 73 76 92 81 92 6f 7d 7d 70 91 81 8f 73 75 8c 90 7f 94 81 91 70 7f 7d 7e"
199 "70 8d 8d 73 7f 7c 7e 6a 81 7e 81 6d 7f 6a 81 6f 7f 7f 71 8e 81 82 81 81 81 96 72 7e 7d"
200 "81 8d 7f 81 68 7f 7e 7c 7b 7f 6c 81 6a 7f 7f 71 8f 8d 7f 81 6c 72 8e 88 70 70 81 6d 70"
201 "8d 90 7f 81 7e 95 81 94 7f 92 8b 6e 7f 7f 70 8c 8c 73 75 91 81 91 6d 7d 7e 7b 7c 7d 71"
202 "6c 89 91 7f 81 7f 95 81 93 7f 95 90 7f 81 6d 70 81 6f 75 8c 8e 75 71 81 6e 70 8d 8d 7f"
203 "91 92 7f 81 7f 94 8d 70 71 81 6e 6d 81 6e 75 8e 81 93 70 7f 70 8f 8c 7f 81 6d 6f 81 6a";
204
205 memset(&bursts[0], 0, sizeof(bursts));
206 rc = osmo_hexparse(ahs_sid_update, (uint8_t *)&bursts[BURST_PLEN * 2], BURST_PLEN * 10);
207 OSMO_ASSERT(rc == BURST_PLEN * 4);
208
209 /* Test detection and decoding of AHS_SID_UPDATE */
210 test_gsm0503_tch_afhs_decode_dtx(&bursts[0], BURST_PLEN * 0, &amr_last_dtx, false /* AHS */,
211 "detection/decoding of AHS_SID_UPDATE");
212 test_gsm0503_tch_afhs_decode_dtx(&bursts[0], BURST_PLEN * 2, &amr_last_dtx, false /* AHS */,
213 "detection/decoding of AHS_SID_UPDATE");
214 test_gsm0503_tch_afhs_decode_dtx(&bursts[0], BURST_PLEN * 4, &amr_last_dtx, false /* AHS */,
215 "detection/decoding of AHS_SID_UPDATE");
216}
217
Philipp Maier898c9c62020-02-06 14:25:01 +0100218int main(int argc, char **argv)
219{
220 printf("FR AMR DTX FRAMES:\n");
221 test_gsm0503_detect_afs_dtx_frame(sample_afs_sid_frame);
222 test_gsm0503_detect_afs_dtx_frame(sample_afs_sid_update_frame);
223 test_gsm0503_detect_afs_dtx_frame(sample_afs_onset_frame);
224 printf("HR AMR DTX FRAMES:\n");
225 test_gsm0503_detect_ahs_dtx_frame(sample_ahs_sid_update_frame);
226 test_gsm0503_detect_ahs_dtx_frame(sample_ahs_sid_first_p1_frame);
227 test_gsm0503_detect_ahs_dtx_frame(sample_ahs_sid_first_p2_frame);
228 test_gsm0503_detect_ahs_dtx_frame(sample_ahs_onset_frame);
229 test_gsm0503_detect_ahs_dtx_frame(sample_sid_first_inh_frame);
230 test_gsm0503_detect_ahs_dtx_frame(sample_sid_update_inh_frame);
231
Vadim Yanitskiyf673fd52022-05-18 01:16:27 +0300232 test_gsm0503_tch_afhs_decode_dtx_sid_update();
233
Philipp Maier898c9c62020-02-06 14:25:01 +0100234 return EXIT_SUCCESS;
235}