falconia has submitted this change. ( https://gerrit.osmocom.org/c/libosmo-abis/+/38293?usp=email )
Change subject: libosmotrau: implement RAA' decoder function ......................................................................
libosmotrau: implement RAA' decoder function
The previous patch implements RAA' encoder function; now comes the decoder.
Related: OS#6167 Change-Id: I1347a25ce97d5022502ee9112caded66315b09a4 --- M .gitignore M include/osmocom/trau/csd_raa_prime.h M src/Makefile.am A src/trau/raa_prime_decode.c M tests/Makefile.am A tests/raa_prime/test_dec.c M tests/testsuite.at 7 files changed, 280 insertions(+), 0 deletions(-)
Approvals: falconia: Looks good to me, approved Jenkins Builder: Verified
diff --git a/.gitignore b/.gitignore index 2f3ba99..fd0974d 100644 --- a/.gitignore +++ b/.gitignore @@ -40,6 +40,7 @@ tests/subchan_demux/.dirstamp tests/subchan_demux/subchan_demux_test tests/ipa_recv/ipa_recv_test +tests/raa_prime/test_dec tests/raa_prime/test_enc tests/trau_pcu_ericsson/trau_pcu_ericsson_test tests/trau_conv/trau16_to_rtp diff --git a/include/osmocom/trau/csd_raa_prime.h b/include/osmocom/trau/csd_raa_prime.h index 43bfe4e..7c3e817 100644 --- a/include/osmocom/trau/csd_raa_prime.h +++ b/include/osmocom/trau/csd_raa_prime.h @@ -55,3 +55,31 @@ void osmo_csd144_to_atrau_ra2(uint8_t *out_bytes, const ubit_t *m_bits, const ubit_t *d_bits, ubit_t atrau_c4, ubit_t atrau_c5); + +/*! Decode aligned A-TRAU frame into user form of 288 D-bits and + * two M-bits; the A-TRAU frame input is given in unpacked bit form. + * + * \param[out] m_bits caller-provided buffer for 2 M-bits + * \param[out] d_bits caller-provided buffer for 288 user data bits + * \param[out] atrau_c4 return of A-TRAU frame bit C4 (NULL pointer OK) + * \param[out] atrau_c5 return of A-TRAU frame bit C5 (NULL pointer OK) + * \param[in] atrau_bits A-TRAU frame as 320 unpacked bits + * \return 0 if A-TRAU frame is good; negative if it is invalid + */ +int osmo_csd144_from_atrau_bits(ubit_t *m_bits, ubit_t *d_bits, + ubit_t *atrau_c4, ubit_t *atrau_c5, + const ubit_t *atrau_bits); + +/*! Decode aligned A-TRAU frame into user form of 288 D-bits and + * two M-bits; the A-TRAU frame input is given in RA2 octet form. + * + * \param[out] m_bits caller-provided buffer for 2 M-bits + * \param[out] d_bits caller-provided buffer for 288 user data bits + * \param[out] atrau_c4 return of A-TRAU frame bit C4 (NULL pointer OK) + * \param[out] atrau_c5 return of A-TRAU frame bit C5 (NULL pointer OK) + * \param[in] atrau_bytes A-TRAU frame as 160 RA2 octets + * \return 0 if A-TRAU frame is good; negative if it is invalid + */ +int osmo_csd144_from_atrau_ra2(ubit_t *m_bits, ubit_t *d_bits, + ubit_t *atrau_c4, ubit_t *atrau_c5, + const uint8_t *atrau_bytes); diff --git a/src/Makefile.am b/src/Makefile.am index 6d8bc98..3a6b83d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -42,6 +42,7 @@ $(NULL) libosmotrau_la_LIBADD = $(COMMONLIBS) $(LIBOSMOCODEC_LIBS) $(ORTP_LIBS) libosmotrau_la_SOURCES = trau/csd_ra2.c \ + trau/raa_prime_decode.c \ trau/raa_prime_encode.c \ trau/trau_frame.c \ trau/trau_pcu_ericsson.c \ diff --git a/src/trau/raa_prime_decode.c b/src/trau/raa_prime_decode.c new file mode 100644 index 0000000..65d916e --- /dev/null +++ b/src/trau/raa_prime_decode.c @@ -0,0 +1,121 @@ +/* + * This C module contains the implementation of RAA' (RAA-prime) function + * in the decoding direction, from an A-TRAU frame to user bits. + * The interface is defined in <osmocom/trau/csd_raa_prime.h>. + * + * 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 <stdint.h> +#include <string.h> +#include <errno.h> +#include <osmocom/core/bits.h> +#include <osmocom/core/utils.h> +#include <osmocom/trau/csd_raa_prime.h> +#include <osmocom/trau/csd_ra2.h> + +static int decode_zsp(const ubit_t *atrau_bits, unsigned *pos) +{ + unsigned pos1, n; + + /* guard bits must be set */ + if (!atrau_bits[0] || !atrau_bits[7]) + return -EINVAL; + pos1 = 0; + for (n = 0; n < 5; n++) { + pos1 <<= 1; + pos1 |= atrau_bits[2 + n]; + } + if (pos1 < 1 || pos1 > 29) + return -EINVAL; + *pos = pos1 - 1; + return 0; +} + +static int decode_subframe(ubit_t *d_bits, const ubit_t *atrau_bits) +{ + ubit_t zi, cbit; + unsigned pos, z_pos, numd; + int rc; + + /* consume Zi bit and weed out the trivial case */ + zi = *atrau_bits++; + if (zi) { + memcpy(d_bits, atrau_bits, 36); + return 0; + } + pos = 0; + for (;;) { + if (pos > 28) + return -EINVAL; + rc = decode_zsp(atrau_bits + pos, &z_pos); + if (rc < 0) + return rc; + cbit = atrau_bits[pos + 1]; + if (z_pos < pos) + return -EINVAL; + numd = z_pos - pos; + memcpy(d_bits + pos, atrau_bits + 8 + pos, numd); + memset(d_bits + pos + numd, 0, 8); + pos += numd + 8; + if (cbit) + break; + } + OSMO_ASSERT(pos <= 36); + numd = 36 - pos; + memcpy(d_bits + pos, atrau_bits + pos, numd); + return 0; +} + +int osmo_csd144_from_atrau_bits(ubit_t *m_bits, ubit_t *d_bits, + ubit_t *atrau_c4, ubit_t *atrau_c5, + const ubit_t *atrau_bits) +{ + static const ubit_t header_bits[20] = {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 1, 1}; + int subf, rc; + + if (memcmp(atrau_bits, header_bits, 20) != 0) + return -EINVAL; + if (atrau_c4) + *atrau_c4 = atrau_bits[20]; + if (atrau_c5) + *atrau_c5 = atrau_bits[21]; + m_bits[0] = atrau_bits[22]; + m_bits[1] = atrau_bits[23]; + + /* done with the header, do the 8 subframes */ + atrau_bits += 24; + for (subf = 0; subf < 8; subf++) { + rc = decode_subframe(d_bits, atrau_bits); + if (rc < 0) + return rc; + atrau_bits += 37; + d_bits += 36; + } + return 0; +} + +int osmo_csd144_from_atrau_ra2(ubit_t *m_bits, ubit_t *d_bits, + ubit_t *atrau_c4, ubit_t *atrau_c5, + const uint8_t *atrau_bytes) +{ + ubit_t atrau_bits[OSMO_ATRAU_FRAME_BITS]; + + osmo_csd_ra2_16k_unpack(atrau_bits, atrau_bytes, OSMO_ATRAU_RA2_OCTETS); + return osmo_csd144_from_atrau_bits(m_bits, d_bits, atrau_c4, atrau_c5, + atrau_bits); +} diff --git a/tests/Makefile.am b/tests/Makefile.am index d50b09a..fd264d0 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -7,6 +7,7 @@ ipa_proxy_test \ subchan_demux/subchan_demux_test \ ipa_recv/ipa_recv_test \ + raa_prime/test_dec \ raa_prime/test_enc \ trau_conv/trau16_to_rtp \ trau_sync/trau_sync_test \ @@ -39,6 +40,10 @@ $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) \ $(LIBOSMOVTY_LIBS)
+raa_prime_test_dec_SOURCES = raa_prime/test_dec.c +raa_prime_test_dec_LDADD = $(top_builddir)/src/libosmotrau.la \ + $(LIBOSMOCORE_LIBS) + raa_prime_test_enc_SOURCES = raa_prime/test_enc.c raa_prime_test_enc_LDADD = $(top_builddir)/src/libosmotrau.la \ $(LIBOSMOCORE_LIBS) diff --git a/tests/raa_prime/test_dec.c b/tests/raa_prime/test_dec.c new file mode 100644 index 0000000..9ca1b02 --- /dev/null +++ b/tests/raa_prime/test_dec.c @@ -0,0 +1,118 @@ +/* + * This C module is a unit test program for libosmotrau implementation + * of RAA' function in the decoding direction. + * + * 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/trau/csd_raa_prime.h> + +static uint8_t frame_buf[OSMO_ATRAU_RA2_OCTETS]; +static unsigned hex_chunk_count; + +static void process_frame(void) +{ + ubit_t m_bits[2], d_bits[288]; + uint8_t d_bits_packed[36]; + int rc, i; + + rc = osmo_csd144_from_atrau_ra2(m_bits, d_bits, NULL, NULL, frame_buf); + if (rc < 0) { + printf("Bad A-TRAU frame!\n"); + return; + } + osmo_ubit2pbit(d_bits_packed, d_bits, 288); + printf("%u%u ", m_bits[0], m_bits[1]); + for (i = 0; i < 36; i++) + printf("%02x", d_bits_packed[i]); + putchar('\n'); +} + +static void process_hex_input(const char *hex_str) +{ + osmo_hexparse(hex_str, frame_buf + hex_chunk_count * 40, 40); + hex_chunk_count++; + if (hex_chunk_count >= 4) { + process_frame(); + hex_chunk_count = 0; + } +} + +static void process_line(char *linebuf, const char *infname, int lineno) +{ + char *cp = linebuf, *hex_str; + int ndig; + + while (isspace(*cp)) + cp++; + if (*cp == '\0' || *cp == '#') + return; + /* expect string of 80 hex digits */ + hex_str = cp; + for (ndig = 0; ndig < 80; ndig++) { + if (!isxdigit(*cp)) + goto inv; + cp++; + } + if (*cp) { + if (!isspace(*cp)) + goto inv; + *cp++ = '\0'; + } + /* must be end of non-comment line */ + while (isspace(*cp)) + cp++; + if (*cp != '\0' && *cp != '#') + goto inv; + + process_hex_input(hex_str); + 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[256]; + 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); +} diff --git a/tests/testsuite.at b/tests/testsuite.at index c430220..70e7f25 100644 --- a/tests/testsuite.at +++ b/tests/testsuite.at @@ -36,6 +36,12 @@ AT_CHECK([$abs_top_builddir/tests/raa_prime/test_enc $abs_srcdir/raa_prime/d144-ul-input.asc], [0], [expout], [ignore]) AT_CLEANUP
+AT_SETUP([raa_prime_decode]) +AT_KEYWORDS([raa_prime_decode]) +cat $abs_srcdir/raa_prime/d144-ul-input.asc > expout +AT_CHECK([$abs_top_builddir/tests/raa_prime/test_dec $abs_srcdir/raa_prime/nokia-tcsm2-atrau.hex], [0], [expout], [ignore]) +AT_CLEANUP + AT_SETUP([trau_sync]) AT_KEYWORDS([trau_sync]) cat $abs_srcdir/trau_sync/trau_sync_test.ok > expout