1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
|
/*
* This program is a test for osmo_hr_sid_classify(). It reads a set of
* TCH/HS Rx bit patterns in TI DSP format (originally captured from a
* Calypso MS under conditions of induced radio errors), converts each
* bit pattern to TS 101 318 format (using same bit reordering function
* as libosmocoding gsm0503 implementation), and feeds each test line
* to osmo_hr_sid_classify(). It then prints the output next to each input.
*
* Author: Mychaela N. Falconia <falcon@freecalypso.org>, 2024 - however,
* Mother Mychaela's contributions are NOT subject to copyright.
* No rights reserved, all rights relinquished.
*
* 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.
*/
#include <ctype.h>
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <osmocom/core/bits.h>
#include <osmocom/core/utils.h>
#include <osmocom/codec/codec.h>
#define HR_CODEC_BITS (GSM_HR_BYTES * 8)
#define HR_BYTES_TIDSP (GSM_HR_BYTES + 1)
/* re-arrange according to TS 05.03 Table 3a (receiver) */
/* function copied from src/coding/gsm0503_coding.c */
static void tch_hr_d_to_b(ubit_t *b_bits, const ubit_t *d_bits)
{
int i;
const uint16_t *map;
if (!d_bits[93] && !d_bits[94])
map = gsm620_unvoiced_bitorder;
else
map = gsm620_voiced_bitorder;
for (i = 0; i < 112; i++)
b_bits[map[i]] = d_bits[i];
}
static void process_record(const char *hex_str, bool bci_flag)
{
uint8_t dsp_rx_bytes[HR_BYTES_TIDSP];
ubit_t bits_transmission_order[HR_BYTES_TIDSP * 8];
ubit_t bits_codec_order[HR_CODEC_BITS];
uint8_t hr_bytes_ts101318[GSM_HR_BYTES];
bool bfi_flag = false;
enum osmo_gsm631_sid_class sidc;
osmo_hexparse(hex_str, dsp_rx_bytes, HR_BYTES_TIDSP);
osmo_pbit2ubit(bits_transmission_order, dsp_rx_bytes,
HR_BYTES_TIDSP * 8);
/* TI DSP format has a gap of 4 bits between class 1 and class 2
* portions - get rid of it. 95 is the number of class 1 bits,
* 17 is the number of class 2 bits. */
memmove(bits_transmission_order + 95,
bits_transmission_order + 95 + 4, 17);
tch_hr_d_to_b(bits_codec_order, bits_transmission_order);
osmo_ubit2pbit(hr_bytes_ts101318, bits_codec_order, HR_CODEC_BITS);
sidc = osmo_hr_sid_classify(hr_bytes_ts101318, bci_flag, &bfi_flag);
printf("%s %d ==> %d %d\n", hex_str, (int) bci_flag,
(int) sidc, (int) bfi_flag);
}
static void process_line(char *linebuf, const char *infname, int lineno)
{
char *cp = linebuf, *hex_str;
int ndig;
bool bci_flag;
while (isspace(*cp))
cp++;
if (*cp == '\0' || *cp == '#')
return;
/* expect string of 30 hex digits */
hex_str = cp;
for (ndig = 0; ndig < HR_BYTES_TIDSP * 2; ndig++) {
if (!isxdigit(*cp))
goto inv;
cp++;
}
if (!isspace(*cp))
goto inv;
*cp++ = '\0';
while (isspace(*cp))
cp++;
/* 0 or 1 must follow, giving BCI flag */
if (*cp == '0')
bci_flag = false;
else if (*cp == '1')
bci_flag = true;
else
goto inv;
cp++;
/* must be end of non-comment line */
while (isspace(*cp))
cp++;
if (*cp != '\0' && *cp != '#')
goto inv;
process_record(hex_str, bci_flag);
return;
inv: fprintf(stderr, "%s line %d: invalid syntax\n", infname, lineno);
exit(1);
}
int main(int argc, char **argv)
{
const char *infname;
FILE *inf;
char linebuf[128];
int lineno;
if (argc != 2) {
fprintf(stderr, "usage: %s input-file\n", argv[0]);
exit(1);
}
infname = argv[1];
inf = fopen(infname, "r");
if (!inf) {
perror(infname);
exit(1);
}
for (lineno = 1; fgets(linebuf, sizeof(linebuf), inf); lineno++)
process_line(linebuf, infname, lineno);
fclose(inf);
exit(0);
}
|