aboutsummaryrefslogtreecommitdiffstats
path: root/tests/coding/coding_test.c
diff options
context:
space:
mode:
Diffstat (limited to 'tests/coding/coding_test.c')
-rw-r--r--tests/coding/coding_test.c194
1 files changed, 185 insertions, 9 deletions
diff --git a/tests/coding/coding_test.c b/tests/coding/coding_test.c
index bdfe3002..d536e443 100644
--- a/tests/coding/coding_test.c
+++ b/tests/coding/coding_test.c
@@ -13,10 +13,6 @@
* 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 <stdio.h>
@@ -28,6 +24,7 @@
#include <osmocom/core/bits.h>
#include <osmocom/core/utils.h>
+#include <osmocom/gsm/protocol/gsm_04_08.h>
#include <osmocom/coding/gsm0503_coding.h>
#define DUMP_U_AT(b, x, u) do { \
@@ -303,7 +300,7 @@ static void test_hr(uint8_t *speech, int len)
memset(bursts_s + 6, 0, 20);
/* Decode, correcting errors */
- rc = gsm0503_tch_hr_decode(result, bursts_s, 0,
+ rc = gsm0503_tch_hr_decode2(result, bursts_s, 0,
&n_errors, &n_bits_total);
CHECK_RC_OR_RET(rc == len, "decoding");
@@ -316,6 +313,51 @@ static void test_hr(uint8_t *speech, int len)
printf("\n");
}
+static void test_facch(const uint8_t *data, bool half_rate)
+{
+ ubit_t bursts_u[116 * 8 * 2] = { 0 };
+ sbit_t bursts_s[116 * 8 * 2] = { 0 };
+ int rc;
+
+ /* Encode the given FACCH message three times (at different offsets) */
+ printf("%s(FACCH/%c): encoding: %s\n",
+ __func__, half_rate ? 'H' : 'F',
+ osmo_hexdump(&data[0], GSM_MACBLOCK_LEN));
+ for (unsigned int i = 0; i < 3; i++) {
+ ubit_t *pos = &bursts_u[116 * 4 * i];
+
+ if (half_rate)
+ rc = gsm0503_tch_hr_facch_encode(pos, &data[0]);
+ else
+ rc = gsm0503_tch_fr_facch_encode(pos, &data[0]);
+ CHECK_RC_OR_RET(rc == 0, "encoding");
+ }
+
+ /* Prepare soft-bits */
+ osmo_ubit2sbit(bursts_s, bursts_u, sizeof(bursts_s));
+
+ /* Decode three FACCH messages (at different offsets) */
+ for (unsigned int i = 0; i < 3; i++) {
+ const sbit_t *pos = &bursts_s[116 * 4 * i];
+ uint8_t result[GSM_MACBLOCK_LEN];
+ int n_errors, n_bits_total;
+
+ if (half_rate)
+ rc = gsm0503_tch_hr_facch_decode(&result[0], pos,
+ &n_errors, &n_bits_total);
+ else
+ rc = gsm0503_tch_fr_facch_decode(&result[0], pos,
+ &n_errors, &n_bits_total);
+ CHECK_RC_OR_RET(rc == GSM_MACBLOCK_LEN, "decoding");
+
+ printf("%s(FACCH/%c): decoded (BER=%d/%d): %s\n",
+ __func__, half_rate ? 'H' : 'F', n_errors, n_bits_total,
+ osmo_hexdump(result, GSM_MACBLOCK_LEN));
+ }
+
+ printf("\n");
+}
+
struct test_macblock {
bool is_egprs;
uint16_t exp_burst_bits;
@@ -399,11 +441,11 @@ static void test_pdtch(const struct test_macblock *tmb, int len)
case 34:
case 54:
l2[len - 1] &= 0x7f;
- result[len - 1] &= 0x7f;
+ result[len - 1] = 0x00;
break;
case 40:
l2[len - 1] &= 0x07;
- result[len - 1] &= 0x07;
+ result[len - 1] = 0x00;
break;
}
@@ -491,7 +533,128 @@ static const sbit_t test_rach_11bit[6][36] = {
uint8_t test_speech_fr[33];
uint8_t test_speech_efr[31];
-uint8_t test_speech_hr[15];
+uint8_t test_speech_hr[14];
+
+struct csd_test_case {
+ const char *name;
+ unsigned int num_bits;
+ int (*enc_fn)(ubit_t *out, const ubit_t *in);
+ int (*dec_fn)(ubit_t *out, const sbit_t *in, int *ne, int *nb);
+ bool half_rate;
+};
+
+static const struct csd_test_case csd_tests[] = {
+ {
+ .name = "TCH/F9.6",
+ .num_bits = 4 * 60,
+ .enc_fn = &gsm0503_tch_fr96_encode,
+ .dec_fn = &gsm0503_tch_fr96_decode,
+ },
+ {
+ .name = "TCH/F4.8",
+ .num_bits = 2 * 60,
+ .enc_fn = &gsm0503_tch_fr48_encode,
+ .dec_fn = &gsm0503_tch_fr48_decode,
+ },
+ {
+ .name = "TCH/H4.8",
+ .num_bits = 4 * 60,
+ .enc_fn = &gsm0503_tch_hr48_encode,
+ .dec_fn = &gsm0503_tch_hr48_decode,
+ .half_rate = true,
+ },
+ {
+ .name = "TCH/F2.4",
+ .num_bits = 2 * 36,
+ .enc_fn = &gsm0503_tch_fr24_encode,
+ .dec_fn = &gsm0503_tch_fr24_decode,
+ },
+ {
+ .name = "TCH/H2.4",
+ .num_bits = 4 * 36,
+ .enc_fn = &gsm0503_tch_hr24_encode,
+ .dec_fn = &gsm0503_tch_hr24_decode,
+ .half_rate = true,
+ },
+ {
+ .name = "TCH/F14.4",
+ .num_bits = 290,
+ .enc_fn = &gsm0503_tch_fr144_encode,
+ .dec_fn = &gsm0503_tch_fr144_decode,
+ },
+};
+
+static void test_csd(const struct csd_test_case *tc, bool facch)
+{
+ const uint8_t patterns[] = { 0x00, 0xaa, 0xff };
+ ubit_t bursts_u[116 * (22 + 8)] = { 0 };
+ sbit_t bursts_s[116 * (22 + 8)] = { 0 };
+ ubit_t data[512];
+ int rc;
+
+ /* Encode three data blocks, each block filled-in with a pattern */
+ for (unsigned int i = 0; i < ARRAY_SIZE(patterns); i++) {
+ for (unsigned int j = 0; j < tc->num_bits; j++)
+ data[j] = (patterns[i] & (1 << (j % 8))) != 0;
+
+ rc = tc->enc_fn(&bursts_u[i * 4 * 116], &data[0]);
+ CHECK_RC_OR_RET(rc == 0, "encoding");
+
+ /* Test FACCH bitstealing */
+ if (facch && i == 1) {
+ memset(&data, GSM_MACBLOCK_PADDING, GSM_MACBLOCK_LEN);
+ if (tc->half_rate)
+ rc = gsm0503_tch_hr_facch_encode(&bursts_u[116 * 4], &data[0]);
+ else
+ rc = gsm0503_tch_fr_facch_encode(&bursts_u[116 * 4], &data[0]);
+ CHECK_RC_OR_RET(rc == 0, "encoding FACCH");
+ }
+ }
+
+ /* Prepare soft-bits */
+ osmo_ubit2sbit(&bursts_s[0], &bursts_u[0], sizeof(bursts_s));
+
+ /* Decode the soft-bits, print decoded blocks */
+ for (unsigned int i = 0; i < ARRAY_SIZE(patterns); i++) {
+ int n_errors, n_bits_total;
+
+ rc = tc->dec_fn(&data[0], &bursts_s[i * 4 * 116],
+ &n_errors, &n_bits_total);
+ CHECK_RC_OR_RET(rc == tc->num_bits, "decoding");
+
+ printf("%s(%s): block #%u (pattern 0x%02x): n_errors=%d / n_bits_total=%d\n",
+ __func__, tc->name, i, patterns[i], n_errors, n_bits_total);
+
+ for (unsigned int j = 0; j < tc->num_bits; j++) {
+ if (j && j % 64 == 0)
+ printf("\n");
+ else if (j && j % 8 == 0)
+ printf(" ");
+ printf("%c", data[j] ? '1' : '0');
+ }
+ printf("\n");
+ }
+
+ /* Test FACCH bitstealing if requested */
+ if (facch) {
+ int n_errors = 0, n_bits_total = 0;
+
+ if (tc->half_rate) {
+ rc = gsm0503_tch_hr_facch_decode(&data[0], &bursts_s[116 * 4],
+ &n_errors, &n_bits_total);
+ } else {
+ rc = gsm0503_tch_fr_facch_decode(&data[0], &bursts_s[116 * 4],
+ &n_errors, &n_bits_total);
+ }
+ CHECK_RC_OR_RET(rc == GSM_MACBLOCK_LEN, "decoding FACCH");
+
+ printf("%s(%s): FACCH/%c (pattern 0x2b): n_errors=%d / n_bits_total=%d\n",
+ __func__, tc->name, tc->half_rate ? 'H' : 'F', n_errors, n_bits_total);
+ printf("%s\n", osmo_hexdump(&data[0], GSM_MACBLOCK_LEN));
+ }
+
+ printf("\n");
+}
int main(int argc, char **argv)
{
@@ -537,7 +700,6 @@ int main(int argc, char **argv)
for (i = 0; i < sizeof(test_speech_hr); i++)
test_speech_hr[i] = i * 17;
- test_speech_hr[0] = 0x00;
test_hr(test_speech_hr, sizeof(test_speech_hr));
for (i = 0; i < len_l2; i++)
@@ -554,6 +716,20 @@ int main(int argc, char **argv)
}
}
+ printf("\nTesting FACCH/F codec:\n");
+ for (i = 0; i < ARRAY_SIZE(test_l2); i++)
+ test_facch(test_l2[i], false);
+ printf("\nTesting FACCH/H codec:\n");
+ for (i = 0; i < ARRAY_SIZE(test_l2); i++)
+ test_facch(test_l2[i], true);
+
+ printf("\nTesting CSD functions (no FACCH):\n");
+ for (i = 0; i < ARRAY_SIZE(csd_tests); i++)
+ test_csd(&csd_tests[i], false);
+ printf("\nTesting CSD functions (with FACCH):\n");
+ for (i = 0; i < ARRAY_SIZE(csd_tests); i++)
+ test_csd(&csd_tests[i], true);
+
printf("Success\n");
return 0;