laforge has uploaded this change for review. ( 
https://gerrit.osmocom.org/c/libosmocore/+/30762 )


Change subject: isdn: Add V.110 encoder/decoder
......................................................................

isdn: Add V.110 encoder/decoder

Change-Id: I1b5fd3847d3bfb0a0f763e0574893962ec699680
---
M include/Makefile.am
A include/osmocom/isdn/v110.h
M src/isdn/Makefile.am
M src/isdn/libosmoisdn.map
A src/isdn/v110.c
M tests/Makefile.am
M tests/testsuite.at
A tests/v110/test_frame.c
A tests/v110/test_frame.ok
A tests/v110/test_ra1.c
A tests/v110/test_ra1.ok
11 files changed, 949 insertions(+), 1 deletion(-)



  git pull ssh://gerrit.osmocom.org:29418/libosmocore refs/changes/62/30762/1

diff --git a/include/Makefile.am b/include/Makefile.am
index 35f7125..f857304 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -72,6 +72,7 @@
                       osmocom/ctrl/ports.h \
                        osmocom/isdn/i460_mux.h \
                        osmocom/isdn/lapd_core.h \
+                       osmocom/isdn/v110.h \
                        osmocom/gprs/frame_relay.h \
                        osmocom/gprs/bssgp_bvc_fsm.h \
                        osmocom/gprs/gprs_bssgp.h \
diff --git a/include/osmocom/isdn/v110.h b/include/osmocom/isdn/v110.h
new file mode 100644
index 0000000..2f4742b
--- /dev/null
+++ b/include/osmocom/isdn/v110.h
@@ -0,0 +1,60 @@
+#pragma once
+
+#include <osmocom/core/bits.h>
+
+/* See Section 5.1.2.1 of ITU-T V.110 */
+#define MAX_D_BITS     48
+#define MAX_E_BITS     7
+#define MAX_S_BITS     9
+#define MAX_X_BITS     2
+
+struct osmo_v110_decoded_frame {
+       //enum osmo_v110_frame_type type;
+       //enum osmo_v110_frame_direction dir;
+
+       ubit_t d_bits[MAX_D_BITS];
+       ubit_t e_bits[MAX_E_BITS];
+       ubit_t s_bits[MAX_S_BITS];
+       ubit_t x_bits[MAX_X_BITS];
+};
+
+int osmo_v110_decode_frame(struct osmo_v110_decoded_frame *fr, const ubit_t 
*ra_bits, size_t n_bits);
+int osmo_v110_encode_frame(ubit_t *ra_bits, size_t n_bits, const struct 
osmo_v110_decoded_frame *fr);
+
+void osmo_v110_ubit_dump(FILE *outf, const ubit_t *fr, size_t in_len);
+
+
+
+struct osmo_v110_sync_ra1 {
+       unsigned int data_rate;
+       unsigned int intermediate_rate;
+       unsigned int user_data_chunk_bits;
+       int (*adapt_user_to_ir)(struct osmo_v110_decoded_frame *fr, const 
ubit_t *d_in, size_t in_len);
+       int (*adapt_ir_to_user)(ubit_t *d_out, size_t out_len, const struct 
osmo_v110_decoded_frame *fr);
+};
+
+enum osmo_v100_sync_ra1_rate {
+       OSMO_V110_SYNC_RA1_600,
+       OSMO_V110_SYNC_RA1_1200,
+       OSMO_V110_SYNC_RA1_2400,
+       OSMO_V110_SYNC_RA1_4800,
+       OSMO_V110_SYNC_RA1_7200,
+       OSMO_V110_SYNC_RA1_9600,
+       OSMO_V110_SYNC_RA1_12000,
+       OSMO_V110_SYNC_RA1_14400,
+       OSMO_V110_SYNC_RA1_19200,
+       OSMO_V110_SYNC_RA1_24000,
+       OSMO_V110_SYNC_RA1_28800,
+       OSMO_V110_SYNC_RA1_38400,
+       _NUM_OSMO_V110_SYNC_RA1
+};
+
+extern const struct osmo_v110_sync_ra1 sync_ra1[_NUM_OSMO_V110_SYNC_RA1];
+
+
+
+struct osmo_v110_instance {
+       /* pointer to the sync rate adaptation */
+       const struct osmo_v110_sync_ra1 *sync_ra1;
+};
+
diff --git a/src/isdn/Makefile.am b/src/isdn/Makefile.am
index 95ec0ff..010338a 100644
--- a/src/isdn/Makefile.am
+++ b/src/isdn/Makefile.am
@@ -13,7 +13,7 @@
 noinst_LTLIBRARIES = libisdnint.la
 lib_LTLIBRARIES = libosmoisdn.la

-libisdnint_la_SOURCES = i460_mux.c lapd_core.c
+libisdnint_la_SOURCES = i460_mux.c lapd_core.c v110.c

 libisdnint_la_LDFLAGS = -no-undefined
 libisdnint_la_LIBADD = $(top_builddir)/src/libosmocore.la
diff --git a/src/isdn/libosmoisdn.map b/src/isdn/libosmoisdn.map
index 76e8c81..e983668 100644
--- a/src/isdn/libosmoisdn.map
+++ b/src/isdn/libosmoisdn.map
@@ -20,5 +20,11 @@
 osmo_i460_subchan_del;
 osmo_i460_ts_init;

+osmo_v110_decode_frame;
+osmo_v110_encode_frame;
+osmo_v110_ubit_dump;
+sync_ra1;
+
+
 local: *;
 };
diff --git a/src/isdn/v110.c b/src/isdn/v110.c
new file mode 100644
index 0000000..e3e50d0
--- /dev/null
+++ b/src/isdn/v110.c
@@ -0,0 +1,497 @@
+/* V.110 frames according to ITU-T V.110
+ *
+ * This code implements the following functionality:
+ * - parsing/encoding of osmo_v110_decoded_frame from/to actual 80-bit V.110 
frame
+ * - synchronous rate adapting of user bit rate to V.110 D-bits as per Table 6
+ *
+ * It is (at least initially) a very "naive" implementation, as it first and 
foremost
+ * aims to be functional and correct, rather than efficient in any way.  Hence 
it
+ * operates on unpacked bits (ubit_t, 1 bit per byte), and has various 
intermediate
+ * representations and indirect function calls.  If needed, a more optimized 
variant
+ * can always be developed later on.
+ */
+
+/* (C) 2022 by Harald Welte <[email protected]>
+ * All Rights Reserved
+ */
+
+#include <stdint.h>
+#include <errno.h>
+
+#include <osmocom/core/bits.h>
+
+#include <osmocom/isdn/v110.h>
+
+/*************************************************************************
+ * V.110 frame decoding/encoding (ubits <-> struct with D/S/X/E bits)
+ *************************************************************************/
+
+/*! Decode a 80-bit V.110 frame present as 80 ubits into a struct 
osmo_v110_decoded_frame.
+ *  \param[out] caller-allocated output data structure, filled by this function
+ *  \param[in] ra_bits One V.110 frame as 80 unpacked bits. */
+int osmo_v110_decode_frame(struct osmo_v110_decoded_frame *fr, const ubit_t 
*ra_bits, size_t n_bits)
+{
+       if (n_bits < 80)
+               return -EINVAL;
+
+       /* X1 .. X2 */
+       fr->x_bits[0] = ra_bits[2*8 + 7];
+       fr->x_bits[1] = ra_bits[7*8 + 7];
+
+       /* S1, S3, S4, S6, S8, S9 */
+       fr->s_bits[0] = ra_bits[1*8 + 7];
+       fr->s_bits[2] = ra_bits[3*8 + 7];
+       fr->s_bits[3] = ra_bits[4*8 + 7];
+       fr->s_bits[5] = ra_bits[6*8 + 7];
+       fr->s_bits[7] = ra_bits[8*8 + 7];
+       fr->s_bits[8] = ra_bits[9*8 + 7];
+
+       /* E1 .. E7 */
+       memcpy(fr->e_bits, ra_bits + 5*8 + 1, 7);
+
+       /* D-bits */
+       memcpy(fr->d_bits + 0*6, ra_bits + 1*8 + 1, 6);
+       memcpy(fr->d_bits + 1*6, ra_bits + 2*8 + 1, 6);
+       memcpy(fr->d_bits + 2*6, ra_bits + 3*8 + 1, 6);
+       memcpy(fr->d_bits + 3*6, ra_bits + 4*8 + 1, 6);
+
+       memcpy(fr->d_bits + 4*6, ra_bits + 6*8 + 1, 6);
+       memcpy(fr->d_bits + 5*6, ra_bits + 7*8 + 1, 6);
+       memcpy(fr->d_bits + 6*6, ra_bits + 8*8 + 1, 6);
+       memcpy(fr->d_bits + 7*6, ra_bits + 9*8 + 1, 6);
+
+       return 0;
+}
+
+/*! Encode a struct osmo_v110_decoded_frame into an 80-bit V.110 frame as 
ubits.
+ *  \param[out] ra_bits caller-provided output buffer at leat 80 ubits large
+ *  \param[in] n_bits length of ra_bits. Must be at least 80.
+ *  \param[in] input data structure
+ *  \returns number of bits written to ra_bits */
+int osmo_v110_encode_frame(ubit_t *ra_bits, size_t n_bits, const struct 
osmo_v110_decoded_frame *fr)
+{
+       if (n_bits < 80)
+               return -ENOSPC;
+
+       /* alignment pattern */
+       memset(ra_bits+0, 0, 8);
+       for (int i = 1; i < 10; i++)
+               ra_bits[i*8] = 1;
+
+       /* X1 .. X2 */
+       ra_bits[2*8 +7] = fr->x_bits[0];
+       ra_bits[7*8 +7] = fr->x_bits[1];
+
+       /* S1, S3, S4, S6, S8, S9 */
+       ra_bits[1*8 + 7] = fr->s_bits[0];
+       ra_bits[3*8 + 7] = fr->s_bits[2];
+       ra_bits[4*8 + 7] = fr->s_bits[3];
+       ra_bits[6*8 + 7] = fr->s_bits[5];
+       ra_bits[8*8 + 7] = fr->s_bits[7];
+       ra_bits[9*8 + 7] = fr->s_bits[8];
+
+       /* E1 .. E7 */
+       memcpy(ra_bits + 5*8 + 1, fr->e_bits, 7);
+
+       /* D-bits */
+       memcpy(ra_bits + 1*8 + 1, fr->d_bits + 0*6, 6);
+       memcpy(ra_bits + 2*8 + 1, fr->d_bits + 1*6, 6);
+       memcpy(ra_bits + 3*8 + 1, fr->d_bits + 2*6, 6);
+       memcpy(ra_bits + 4*8 + 1, fr->d_bits + 3*6, 6);
+
+       memcpy(ra_bits + 6*8 + 1, fr->d_bits + 4*6, 6);
+       memcpy(ra_bits + 7*8 + 1, fr->d_bits + 5*6, 6);
+       memcpy(ra_bits + 8*8 + 1, fr->d_bits + 6*6, 6);
+       memcpy(ra_bits + 9*8 + 1, fr->d_bits + 7*6, 6);
+
+       return 10 * 8;
+}
+
+/*! Print a encoded V.110 frame in the same table-like structure as the spec. 
*/
+void osmo_v110_ubit_dump(FILE *outf, const ubit_t *fr, size_t in_len)
+{
+       if (in_len < 80)
+               fprintf(outf, "short input data\n");
+
+       for (unsigned int octet = 0; octet < 10; octet++) {
+               fprintf(outf, "%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n",
+                       fr[octet*8+0], fr[octet*8+1], fr[octet*8+2], 
fr[octet*8+3],
+                       fr[octet*8+4], fr[octet*8+5], fr[octet*8+6], 
fr[octet*8+7]);
+       }
+}
+
+/*************************************************************************
+ * RA1 synchronous rate adaptation
+ *************************************************************************/
+
+/* I actually couldn't  find any reference as to the value of F(ill) bits */
+#define F 1
+
+/*! Adapt from 6 synchronous 600bit/s input bits to a decoded V.110 frame.
+ *  \param[out] fr caller-allocated output frame to which E+D bits are stored
+ *  \param[in] d_in input user bits
+ *  \param[in] in_len number of bits in d_in. Must be 6.
+ *  \returns 0 on success; negative in case of error. */
+static int v110_adapt_600_to_IR8000(struct osmo_v110_decoded_frame *fr, const 
ubit_t *d_in, size_t in_len)
+{
+       if (in_len != 6)
+               return -EINVAL;
+
+       /* Table 6a / V.110 */
+       fr->e_bits[0] = 1;
+       fr->e_bits[1] = 0;
+       fr->e_bits[2] = 0;
+       for (int i = 0; i < 6; i++)
+               memset(fr->d_bits + i*8, d_in[i], 8);
+
+       return 0;
+}
+
+static int v110_adapt_IR8000_to_600(ubit_t *d_out, size_t out_len, const 
struct osmo_v110_decoded_frame *fr)
+{
+       if (out_len < 6)
+               return -ENOSPC;
+
+       if (fr->e_bits[0] != 1 || fr->e_bits[1] != 0 || fr->e_bits[2] != 0)
+               return -EINVAL;
+
+       for (int i = 0; i < 6; i++) {
+               /* we only use one of the bits, not some kind of consistency 
check or majority vote */
+               d_out[i] = fr->d_bits[i*8];
+       }
+
+       return 6;
+}
+
+/*! Adapt from 12 synchronous 1200bit/s input bits to a decoded V.110 frame.
+ *  \param[out] fr caller-allocated output frame to which E+D bits are stored
+ *  \param[in] d_in input user bits
+ *  \param[in] in_len number of bits in d_in. Must be 12.
+ *  \returns 0 on success; negative in case of error. */
+static int v110_adapt_1200_to_IR8000(struct osmo_v110_decoded_frame *fr, const 
ubit_t *d_in, size_t in_len)
+{
+       if (in_len != 12)
+               return -EINVAL;
+
+       /* Table 6b / V.110 */
+       fr->e_bits[0] = 0;
+       fr->e_bits[1] = 1;
+       fr->e_bits[2] = 0;
+       for (int i = 0; i < 12; i++)
+               memset(fr->d_bits + i*4, d_in[i], 4);
+
+       return 0;
+}
+
+static int v110_adapt_IR8000_to_1200(ubit_t *d_out, size_t out_len, const 
struct osmo_v110_decoded_frame *fr)
+{
+       if (out_len < 12)
+               return -ENOSPC;
+
+       if (fr->e_bits[0] != 0 || fr->e_bits[1] != 1 || fr->e_bits[2] != 0)
+               return -EINVAL;
+
+       for (int i = 0; i < 12; i++) {
+               /* we only use one of the bits, not some kind of consistency 
check or majority vote */
+               d_out[i] = fr->d_bits[i*4];
+       }
+
+       return 12;
+}
+
+/*! Adapt from 24 synchronous 2400bit/s input bits to a decoded V.110 frame.
+ *  \param[out] fr caller-allocated output frame to which E+D bits are stored
+ *  \param[in] d_in input user bits
+ *  \param[in] in_len number of bits in d_in. Must be 24.
+ *  \returns 0 on success; negative in case of error. */
+static int v110_adapt_2400_to_IR8000(struct osmo_v110_decoded_frame *fr, const 
ubit_t *d_in, size_t in_len)
+{
+       if (in_len != 24)
+               return -EINVAL;
+
+       /* Table 6c / V.110 */
+       fr->e_bits[0] = 1;
+       fr->e_bits[1] = 1;
+       fr->e_bits[2] = 0;
+       for (int i = 0; i < 24; i++) {
+               fr->d_bits[i*2 + 0] = d_in[i];
+               fr->d_bits[i*2 + 1] = d_in[i];
+       }
+
+       return 0;
+}
+
+static int v110_adapt_IR8000_to_2400(ubit_t *d_out, size_t out_len, const 
struct osmo_v110_decoded_frame *fr)
+{
+       if (out_len < 24)
+               return -ENOSPC;
+
+       if (fr->e_bits[1] != 1 || fr->e_bits[1] != 1 || fr->e_bits[2] != 0)
+               return -EINVAL;
+
+       for (int i = 0; i < 24; i++) {
+               /* we only use one of the bits, not some kind of consistency 
check or majority vote */
+               d_out[i] = fr->d_bits[i*2];
+       }
+
+       return 24;
+}
+
+/*! Adapt from 36 synchronous N x 3600bit/s input bits to a decoded V.110 
frame.
+ *  \param[out] fr caller-allocated output frame to which E+D bits are stored
+ *  \param[in] d_in input user bits
+ *  \param[in] in_len number of bits in d_in. Must be 36.
+ *  \returns 0 on success; negative in case of error. */
+static int v110_adapt_Nx3600_to_IR(struct osmo_v110_decoded_frame *fr, const 
ubit_t *d_in, size_t in_len)
+{
+       int d_idx = 0;
+
+       if (in_len != 36)
+               return -EINVAL;
+
+       /* Table 6d / V.110 */
+       fr->e_bits[0] = 1;
+       fr->e_bits[1] = 0;
+       fr->e_bits[2] = 1;
+
+       memcpy(fr->d_bits + d_idx, d_in + 0, 10); d_idx += 10;  /* D1..D10 */
+       memset(fr->d_bits + d_idx, F, 2); d_idx += 2;
+       memcpy(fr->d_bits + d_idx, d_in + 10, 2); d_idx += 2;   /* D11..D12 */
+       memset(fr->d_bits + d_idx, F, 2); d_idx += 2;
+       memcpy(fr->d_bits + d_idx, d_in + 12, 2); d_idx += 2;   /* D13..D14 */
+       memset(fr->d_bits + d_idx, F, 2); d_idx += 2;
+       memcpy(fr->d_bits + d_idx, d_in + 14, 14); d_idx += 14; /* D15..D28 */
+       memset(fr->d_bits + d_idx, F, 2); d_idx += 2;
+       memcpy(fr->d_bits + d_idx, d_in + 28, 2); d_idx += 2;   /* D29..D30 */
+       memset(fr->d_bits + d_idx, F, 2); d_idx += 2;
+       memcpy(fr->d_bits + d_idx, d_in + 30, 2); d_idx += 2;   /* D31..D32 */
+       memset(fr->d_bits + d_idx, F, 2); d_idx += 2;
+       memcpy(fr->d_bits + d_idx, d_in + 32, 4); d_idx += 4;   /* D33..D36 */
+
+       OSMO_ASSERT(d_idx == 48);
+
+       return 0;
+}
+
+static int v110_adapt_IR_to_Nx3600(ubit_t *d_out, size_t out_len, const struct 
osmo_v110_decoded_frame *fr)
+{
+       int d_idx = 0;
+
+       if (out_len < 36)
+               return -ENOSPC;
+
+       if (fr->e_bits[0] != 1 || fr->e_bits[1] != 0 || fr->e_bits[2] != 1)
+               return -EINVAL;
+
+       memcpy(d_out + 0, fr->d_bits + d_idx, 10); d_idx += 10; /* D1..D10 */
+       d_idx += 2;
+       memcpy(d_out + 10, fr->d_bits + d_idx, 2); d_idx += 2;  /* D11..D12 */
+       d_idx += 2;
+       memcpy(d_out + 12, fr->d_bits + d_idx, 2); d_idx += 2;  /* D13..D14 */
+       d_idx += 2;
+       memcpy(d_out + 14, fr->d_bits + d_idx, 14); d_idx += 14;/* D15..D28 */
+       d_idx += 2;
+       memcpy(d_out + 28, fr->d_bits + d_idx, 2); d_idx += 2;  /* D29..D30 */
+       d_idx += 2;
+       memcpy(d_out + 30, fr->d_bits + d_idx, 2); d_idx += 2;  /* D31..D32 */
+       d_idx += 2;
+       memcpy(d_out + 32, fr->d_bits + d_idx, 4); d_idx += 4;  /* D33..D36 */
+
+       OSMO_ASSERT(d_idx == 48);
+
+       return 36;
+}
+
+
+/*! Adapt from 48 synchronous N x 4800bit/s input bits to a decoded V.110 
frame.
+ *  \param[out] fr caller-allocated output frame to which E+D bits are stored
+ *  \param[in] d_in input user bits
+ *  \param[in] in_len number of bits in d_in. Must be 48.
+ *  \returns 0 on success; negative in case of error. */
+static int v110_adapt_Nx4800_to_IR(struct osmo_v110_decoded_frame *fr, const 
ubit_t *d_in, size_t in_len)
+{
+       if (in_len != 48)
+               return -EINVAL;
+
+       /* Table 6e / V.110 */
+       fr->e_bits[0] = 0;
+       fr->e_bits[1] = 1;
+       fr->e_bits[2] = 1;
+
+       memcpy(fr->d_bits, d_in, 48);
+
+       return 0;
+}
+
+static int v110_adapt_IR_to_Nx4800(ubit_t *d_out, size_t out_len, const struct 
osmo_v110_decoded_frame *fr)
+{
+       if (out_len < 48)
+               return -ENOSPC;
+
+       if (fr->e_bits[0] != 0 || fr->e_bits[1] != 1 || fr->e_bits[2] != 1)
+               return -EINVAL;
+
+       memcpy(d_out, fr->d_bits, 48);
+
+       return 48;
+}
+
+/*! Adapt from 30 synchronous N x 12000bit/s input bits to a decoded V.110 
frame.
+ *  \param[out] fr caller-allocated output frame to which E+D bits are stored
+ *  \param[in] d_in input user bits
+ *  \param[in] in_len number of bits in d_in. Must be 30.
+ *  \returns 0 on success; negative in case of error. */
+static int v110_adapt_Nx12000_to_IR(struct osmo_v110_decoded_frame *fr, const 
ubit_t *d_in, size_t in_len)
+{
+       int d_idx = 0;
+
+       if (in_len != 30)
+               return -EINVAL;
+
+       /* Table 6f / V.110 */
+       fr->e_bits[0] = 0;
+       fr->e_bits[1] = 0;
+       fr->e_bits[2] = 1;
+
+       memcpy(fr->d_bits + d_idx, d_in + 0, 10); d_idx += 10;  /* D1..D10 */
+       memset(fr->d_bits + d_idx, F, 2); d_idx += 2;
+       memcpy(fr->d_bits + d_idx, d_in + 10, 2); d_idx += 2;   /* D11..D12 */
+       memset(fr->d_bits + d_idx, F, 2); d_idx += 2;
+       memcpy(fr->d_bits + d_idx, d_in + 12, 2); d_idx += 2;   /* D13..D14 */
+       memset(fr->d_bits + d_idx, F, 2); d_idx += 2;
+       fr->d_bits[d_idx++] = d_in[14];                         /* D15 */
+       memset(fr->d_bits + d_idx, F, 3); d_idx += 3;
+       memcpy(fr->d_bits + d_idx, d_in + 15, 10); d_idx += 10; /* D16..D25 */
+       memset(fr->d_bits + d_idx, F, 2); d_idx += 2;
+       memcpy(fr->d_bits + d_idx, d_in + 25, 2); d_idx += 2;   /* D26..D27 */
+       memset(fr->d_bits + d_idx, F, 2); d_idx += 2;
+       memcpy(fr->d_bits + d_idx, d_in + 27, 2); d_idx += 2;   /* D28..D29 */
+       memset(fr->d_bits + d_idx, F, 2); d_idx += 2;
+       fr->d_bits[d_idx++] = d_in[29];                         /* D30 */
+       memset(fr->d_bits + d_idx, F, 3); d_idx += 3;
+
+       OSMO_ASSERT(d_idx == 48);
+
+       return 0;
+}
+
+static int v110_adapt_IR_to_Nx12000(ubit_t *d_out, size_t out_len, const 
struct osmo_v110_decoded_frame *fr)
+{
+       int d_idx = 0;
+
+       if (out_len < 30)
+               return -ENOSPC;
+
+       if (fr->e_bits[0] != 0 || fr->e_bits[1] != 0 || fr->e_bits[2] != 1)
+               return -EINVAL;
+
+       memcpy(d_out + 0, fr->d_bits + d_idx, 10); d_idx += 10; /* D1..D10 */
+       d_idx += 2;
+       memcpy(d_out + 10, fr->d_bits + d_idx, 2); d_idx += 2;  /* D11..D12 */
+       d_idx += 2;
+       memcpy(d_out + 12, fr->d_bits + d_idx, 2); d_idx += 2;  /* D13..D14 */
+       d_idx += 2;
+       d_out[14] = fr->d_bits[d_idx++];                        /* D15 */
+       d_idx += 3;
+       memcpy(d_out + 15, fr->d_bits + d_idx, 10); d_idx += 10;/* D16..D25 */
+       d_idx += 2;
+       memcpy(d_out + 25, fr->d_bits + d_idx, 2); d_idx += 2;  /* D26..D27 */
+       d_idx += 2;
+       memcpy(d_out + 27, fr->d_bits + d_idx, 2); d_idx += 2;  /* D28..D29 */
+       d_idx += 2;
+       d_out[29] = fr->d_bits[d_idx++];                        /* D30 */
+       d_idx += 3;
+
+       OSMO_ASSERT(d_idx == 48);
+
+       return 30;
+}
+
+
+/* all of the synchronous data signalling rates; see Table 1/V.110 */
+const struct osmo_v110_sync_ra1 sync_ra1[_NUM_OSMO_V110_SYNC_RA1] = {
+       [OSMO_V110_SYNC_RA1_600] = {
+               .data_rate = 600,
+               .intermediate_rate = 8000,
+               .user_data_chunk_bits = 6,
+               .adapt_user_to_ir = v110_adapt_600_to_IR8000,
+               .adapt_ir_to_user = v110_adapt_IR8000_to_600,
+       },
+       [OSMO_V110_SYNC_RA1_1200] = {
+               .data_rate = 1200,
+               .intermediate_rate = 8000,
+               .user_data_chunk_bits = 12,
+               .adapt_user_to_ir = v110_adapt_1200_to_IR8000,
+               .adapt_ir_to_user = v110_adapt_IR8000_to_1200,
+       },
+       [OSMO_V110_SYNC_RA1_2400] = {
+               .data_rate = 2400,
+               .intermediate_rate = 8000,
+               .user_data_chunk_bits = 24,
+               .adapt_user_to_ir = v110_adapt_2400_to_IR8000,
+               .adapt_ir_to_user = v110_adapt_IR8000_to_2400,
+       },
+       [OSMO_V110_SYNC_RA1_4800] = {
+               .data_rate = 4800,
+               .intermediate_rate = 8000,
+               .user_data_chunk_bits = 48,
+               .adapt_user_to_ir = v110_adapt_Nx4800_to_IR,
+               .adapt_ir_to_user = v110_adapt_IR_to_Nx4800,
+       },
+       [OSMO_V110_SYNC_RA1_7200] = {
+               .data_rate = 7200,
+               .intermediate_rate = 16000,
+               .user_data_chunk_bits = 36,
+               .adapt_user_to_ir = v110_adapt_Nx3600_to_IR,
+               .adapt_ir_to_user = v110_adapt_IR_to_Nx3600,
+       },
+       [OSMO_V110_SYNC_RA1_9600] = {
+               .data_rate = 9600,
+               .intermediate_rate = 16000,
+               .user_data_chunk_bits = 48,
+               .adapt_user_to_ir = v110_adapt_Nx4800_to_IR,
+               .adapt_ir_to_user = v110_adapt_IR_to_Nx4800,
+       },
+       [OSMO_V110_SYNC_RA1_12000] = {
+               .data_rate = 12000,
+               .intermediate_rate = 32000,
+               .user_data_chunk_bits = 30,
+               .adapt_user_to_ir = v110_adapt_Nx12000_to_IR,
+               .adapt_ir_to_user = v110_adapt_IR_to_Nx12000,
+       },
+       [OSMO_V110_SYNC_RA1_14400] = {
+               .data_rate = 14400,
+               .intermediate_rate = 32000,
+               .user_data_chunk_bits = 36,
+               .adapt_user_to_ir = v110_adapt_Nx3600_to_IR,
+               .adapt_ir_to_user = v110_adapt_IR_to_Nx3600,
+       },
+       [OSMO_V110_SYNC_RA1_19200] = {
+               .data_rate = 19200,
+               .intermediate_rate = 32000,
+               .user_data_chunk_bits = 48,
+               .adapt_user_to_ir = v110_adapt_Nx4800_to_IR,
+               .adapt_ir_to_user = v110_adapt_IR_to_Nx4800,
+       },
+       [OSMO_V110_SYNC_RA1_24000] = {
+               .data_rate = 24000,
+               .intermediate_rate = 64000,
+               .user_data_chunk_bits = 30,
+               .adapt_user_to_ir = v110_adapt_Nx12000_to_IR,
+               .adapt_ir_to_user = v110_adapt_IR_to_Nx12000,
+       },
+       [OSMO_V110_SYNC_RA1_28800] = {
+               .data_rate = 28800,
+               .intermediate_rate = 64000,
+               .user_data_chunk_bits = 36,
+               .adapt_user_to_ir = v110_adapt_Nx3600_to_IR,
+               .adapt_ir_to_user = v110_adapt_IR_to_Nx3600,
+       },
+       [OSMO_V110_SYNC_RA1_38400] = {
+               .data_rate = 38400,
+               .intermediate_rate = 64000,
+               .user_data_chunk_bits = 48,
+               .adapt_user_to_ir = v110_adapt_Nx4800_to_IR,
+               .adapt_ir_to_user = v110_adapt_IR_to_Nx4800,
+       },
+};
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 46464e1..a5c5538 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -338,6 +338,12 @@
 iuup_iuup_test_SOURCES = iuup/iuup_test.c
 iuup_iuup_test_LDADD = $(LDADD) $(top_builddir)/src/gsm/libosmogsm.la

+v110_test_frame_SOURCES = iuup/test_frame.c
+v110_test_frame_LDADD = $(LDADD) $(top_builddir)/src/gsm/libosmoisdn.la
+
+v110_test_ra1_SOURCES = iuup/test_ra1.c
+v110_test_ra1_LDADD = $(LDADD) $(top_builddir)/src/gsm/libosmoisdn.la
+
 # The `:;' works around a Bash 3.2 bug when the output is not writeable.
 $(srcdir)/package.m4: $(top_srcdir)/configure.ac
        :;{ \
@@ -435,6 +441,8 @@
             smscb/smscb_test.ok \
             smscb/gsm0341_test.ok \
             smscb/cbsp_test.ok \
+            v110/test_frame.ok \
+            v110/test_ra1.ok \
             $(NULL)

 if ENABLE_LIBSCTP
@@ -638,6 +646,10 @@
                >$(srcdir)/time_cc/time_cc_test.ok
        iuup/iuup_test \
                >$(srcdir)/iuup/iuup_test.ok
+       v110/test_frame \
+               >$(srcdir)/v110/test_frame.ok
+       v110/test_ra1 \
+               >$(srcdir)/v110/test_ra1.ok

 check-local: atconfig $(TESTSUITE)
        [ -e /proc/cpuinfo ] && cat /proc/cpuinfo
diff --git a/tests/testsuite.at b/tests/testsuite.at
index 6b2e75f..c1fd805 100644
--- a/tests/testsuite.at
+++ b/tests/testsuite.at
@@ -484,3 +484,15 @@
 cat $abs_srcdir/iuup/iuup_test.ok > expout
 AT_CHECK([$abs_top_builddir/tests/iuup/iuup_test], [0], [expout], [ignore])
 AT_CLEANUP
+
+AT_SETUP([v110_test_frame])
+AT_KEYWORDS([v110_test_frame])
+cat $abs_srcdir/v110/test_frame.ok > expout
+AT_CHECK([$abs_top_builddir/tests/v110/test_frame], [], [expout],[])
+AT_CLEANUP
+
+AT_SETUP([v110_test_ra1])
+AT_KEYWORDS([v110_test_ra1])
+cat $abs_srcdir/v110/test_ra1.ok > expout
+AT_CHECK([$abs_top_builddir/tests/v110/test_ra1], [], [expout],[])
+AT_CLEANUP
diff --git a/tests/v110/test_frame.c b/tests/v110/test_frame.c
new file mode 100644
index 0000000..7630028
--- /dev/null
+++ b/tests/v110/test_frame.c
@@ -0,0 +1,54 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+
+#include <osmocom/core/bits.h>
+#include <osmocom/isdn/v110.h>
+
+
+static void test_frame_enc(void)
+{
+       struct osmo_v110_decoded_frame fr;
+       ubit_t bits[80];
+       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;
+
+       /* run encoder and dump to stdout */
+       memset(bits, 0xff, sizeof(bits));
+       osmo_v110_encode_frame(bits, sizeof(bits), &fr);
+       osmo_v110_ubit_dump(stdout, bits, sizeof(bits));
+
+       /* run decoder on what we just encoded */
+       memset(&fr, 0, sizeof(fr));
+       v110_decode_frame(&fr, bits, sizeof(bits));
+
+       /* re-encode and dump again 'expout' will match it. */
+       memset(bits, 0xff, sizeof(bits));
+       osmo_v110_encode_frame(bits, sizeof(bits), &fr);
+       osmo_v110_ubit_dump(stdout, bits, sizeof(bits));
+}
+
+
+int main(int argc, char **argv)
+{
+       test_frame_enc();
+}
+
diff --git a/tests/v110/test_frame.ok b/tests/v110/test_frame.ok
new file mode 100644
index 0000000..ecefaa8
--- /dev/null
+++ b/tests/v110/test_frame.ok
@@ -0,0 +1,20 @@
+0      0       0       0       0       0       0       0
+1      101     102     103     104     105     106     211
+1      107     108     109     110     111     112     221
+1      113     114     115     116     117     118     213
+1      119     120     121     122     123     124     214
+1      201     202     203     204     205     206     207
+1      125     126     127     128     129     130     216
+1      131     132     133     134     135     136     222
+1      137     138     139     140     141     142     218
+1      143     144     145     146     147     148     219
+0      0       0       0       0       0       0       0
+1      101     102     103     104     105     106     211
+1      107     108     109     110     111     112     221
+1      113     114     115     116     117     118     213
+1      119     120     121     122     123     124     214
+1      201     202     203     204     205     206     207
+1      125     126     127     128     129     130     216
+1      131     132     133     134     135     136     222
+1      137     138     139     140     141     142     218
+1      143     144     145     146     147     148     219
diff --git a/tests/v110/test_ra1.c b/tests/v110/test_ra1.c
new file mode 100644
index 0000000..4260a1a
--- /dev/null
+++ b/tests/v110/test_ra1.c
@@ -0,0 +1,70 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+
+#include <osmocom/core/bits.h>
+#include <osmocom/isdn/v110.h>
+
+
+static void test_ra1(enum osmo_v100_sync_ra1_rate rate)
+{
+       const struct osmo_v110_sync_ra1 *ra1 = &sync_ra1[rate];
+       struct osmo_v110_decoded_frame fr;
+       ubit_t user_bits[48];
+       ubit_t bits[80];
+       unsigned int i;
+       int rc;
+
+       printf("\n======= User data rate %u\n", ra1->data_rate);
+
+       /* we abuse the fact that ubit_t is 8bit so we can actually
+        * store integer values to clearly identify which bit ends up where */
+       memset(user_bits, 0xFE, sizeof(user_bits));
+       for (i = 0; i < ra1->user_data_chunk_bits; i++)
+               user_bits[i] = 101 + i;
+
+       printf("user_bits: ");
+       for (i = 0; i < ra1->user_data_chunk_bits; i++)
+               printf("%03d ", user_bits[i]);
+       printf("\n");
+
+       /* generate the decoded v.110 frame */
+       memset(&fr, 0, sizeof(fr));
+       rc = ra1->adapt_user_to_ir(&fr, user_bits, ra1->user_data_chunk_bits);
+       OSMO_ASSERT(rc == 0);
+
+       /* run encoder and dump to stdout */
+       memset(bits, 0xff, sizeof(bits));
+       osmo_v110_encode_frame(bits, sizeof(bits), &fr);
+       printf("dumping %u encoded bits in V.110 frame:\n", 
ra1->user_data_chunk_bits);
+       osmo_v110_ubit_dump(stdout, bits, sizeof(bits));
+
+       /* run decoder on what we just encoded */
+       memset(&fr, 0, sizeof(fr));
+       osmo_v110_decode_frame(&fr, bits, sizeof(bits));
+       printf("dumping re-decoded V.110 frame:\n");
+       printf("E-bits: %s\n", osmo_hexdump(fr.e_bits, sizeof(fr.e_bits)));
+       printf("S-bits: %s\n", osmo_hexdump(fr.s_bits, sizeof(fr.s_bits)));
+
+       /* re-encode and dump again 'expout' will match it. */
+       memset(user_bits, 0xff, sizeof(user_bits));
+       rc = ra1->adapt_ir_to_user(user_bits, sizeof(user_bits), &fr);
+       if (rc != ra1->user_data_chunk_bits) {
+               fprintf(stderr, "ERROR: adapt_ir_to_user() returned %d, 
expected %u\n", rc,
+                       ra1->user_data_chunk_bits);
+               exit(23);
+       }
+       fprintf(stdout, "re-decoded user bits: ");
+       for (i = 0; i < ra1->user_data_chunk_bits; i++)
+               printf("%03d ", user_bits[i]);
+       printf("\n");
+}
+
+
+int main(int argc, char **argv)
+{
+       for (int i = 0; i < _NUM_OSMO_V110_SYNC_RA1; i++)
+               test_ra1(i);
+}
+
diff --git a/tests/v110/test_ra1.ok b/tests/v110/test_ra1.ok
new file mode 100644
index 0000000..8a61fc3
--- /dev/null
+++ b/tests/v110/test_ra1.ok
@@ -0,0 +1,216 @@
+
+======= User data rate 600
+user_bits: 101 102 103 104 105 106
+dumping 6 encoded bits in V.110 frame:
+0      0       0       0       0       0       0       0
+1      101     101     101     101     101     101     0
+1      101     101     102     102     102     102     0
+1      102     102     102     102     103     103     0
+1      103     103     103     103     103     103     0
+1      1       0       0       0       0       0       0
+1      104     104     104     104     104     104     0
+1      104     104     105     105     105     105     0
+1      105     105     105     105     106     106     0
+1      106     106     106     106     106     106     0
+dumping re-decoded V.110 frame:
+E-bits: 01 00 00 00 00 00 00
+S-bits: 00 00 00 00 00 00 00 00 00
+re-decoded user bits: 101 102 103 104 105 106
+
+======= User data rate 1200
+user_bits: 101 102 103 104 105 106 107 108 109 110 111 112
+dumping 12 encoded bits in V.110 frame:
+0      0       0       0       0       0       0       0
+1      101     101     101     101     102     102     0
+1      102     102     103     103     103     103     0
+1      104     104     104     104     105     105     0
+1      105     105     106     106     106     106     0
+1      0       1       0       0       0       0       0
+1      107     107     107     107     108     108     0
+1      108     108     109     109     109     109     0
+1      110     110     110     110     111     111     0
+1      111     111     112     112     112     112     0
+dumping re-decoded V.110 frame:
+E-bits: 00 01 00 00 00 00 00
+S-bits: 00 00 00 00 00 00 00 00 00
+re-decoded user bits: 101 102 103 104 105 106 107 108 109 110 111 112
+
+======= User data rate 2400
+user_bits: 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 
118 119 120 121 122 123 124
+dumping 24 encoded bits in V.110 frame:
+0      0       0       0       0       0       0       0
+1      101     101     102     102     103     103     0
+1      104     104     105     105     106     106     0
+1      107     107     108     108     109     109     0
+1      110     110     111     111     112     112     0
+1      1       1       0       0       0       0       0
+1      113     113     114     114     115     115     0
+1      116     116     117     117     118     118     0
+1      119     119     120     120     121     121     0
+1      122     122     123     123     124     124     0
+dumping re-decoded V.110 frame:
+E-bits: 01 01 00 00 00 00 00
+S-bits: 00 00 00 00 00 00 00 00 00
+re-decoded user bits: 101 102 103 104 105 106 107 108 109 110 111 112 113 114 
115 116 117 118 119 120 121 122 123 124
+
+======= User data rate 4800
+user_bits: 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 145 146 147 148
+dumping 48 encoded bits in V.110 frame:
+0      0       0       0       0       0       0       0
+1      101     102     103     104     105     106     0
+1      107     108     109     110     111     112     0
+1      113     114     115     116     117     118     0
+1      119     120     121     122     123     124     0
+1      0       1       1       0       0       0       0
+1      125     126     127     128     129     130     0
+1      131     132     133     134     135     136     0
+1      137     138     139     140     141     142     0
+1      143     144     145     146     147     148     0
+dumping re-decoded V.110 frame:
+E-bits: 00 01 01 00 00 00 00
+S-bits: 00 00 00 00 00 00 00 00 00
+re-decoded user bits: 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 145 146 147 148
+
+======= User data rate 7200
+user_bits: 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
+dumping 36 encoded bits in V.110 frame:
+0      0       0       0       0       0       0       0
+1      101     102     103     104     105     106     0
+1      107     108     109     110     1       1       0
+1      111     112     1       1       113     114     0
+1      1       1       115     116     117     118     0
+1      1       0       1       0       0       0       0
+1      119     120     121     122     123     124     0
+1      125     126     127     128     1       1       0
+1      129     130     1       1       131     132     0
+1      1       1       133     134     135     136     0
+dumping re-decoded V.110 frame:
+E-bits: 01 00 01 00 00 00 00
+S-bits: 00 00 00 00 00 00 00 00 00
+re-decoded user bits: 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
+
+======= User data rate 9600
+user_bits: 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 145 146 147 148
+dumping 48 encoded bits in V.110 frame:
+0      0       0       0       0       0       0       0
+1      101     102     103     104     105     106     0
+1      107     108     109     110     111     112     0
+1      113     114     115     116     117     118     0
+1      119     120     121     122     123     124     0
+1      0       1       1       0       0       0       0
+1      125     126     127     128     129     130     0
+1      131     132     133     134     135     136     0
+1      137     138     139     140     141     142     0
+1      143     144     145     146     147     148     0
+dumping re-decoded V.110 frame:
+E-bits: 00 01 01 00 00 00 00
+S-bits: 00 00 00 00 00 00 00 00 00
+re-decoded user bits: 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 145 146 147 148
+
+======= User data rate 12000
+user_bits: 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
+dumping 30 encoded bits in V.110 frame:
+0      0       0       0       0       0       0       0
+1      101     102     103     104     105     106     0
+1      107     108     109     110     1       1       0
+1      111     112     1       1       113     114     0
+1      1       1       115     1       1       1       0
+1      0       0       1       0       0       0       0
+1      116     117     118     119     120     121     0
+1      122     123     124     125     1       1       0
+1      126     127     1       1       128     129     0
+1      1       1       130     1       1       1       0
+dumping re-decoded V.110 frame:
+E-bits: 00 00 01 00 00 00 00
+S-bits: 00 00 00 00 00 00 00 00 00
+re-decoded user bits: 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
+
+======= User data rate 14400
+user_bits: 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
+dumping 36 encoded bits in V.110 frame:
+0      0       0       0       0       0       0       0
+1      101     102     103     104     105     106     0
+1      107     108     109     110     1       1       0
+1      111     112     1       1       113     114     0
+1      1       1       115     116     117     118     0
+1      1       0       1       0       0       0       0
+1      119     120     121     122     123     124     0
+1      125     126     127     128     1       1       0
+1      129     130     1       1       131     132     0
+1      1       1       133     134     135     136     0
+dumping re-decoded V.110 frame:
+E-bits: 01 00 01 00 00 00 00
+S-bits: 00 00 00 00 00 00 00 00 00
+re-decoded user bits: 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
+
+======= User data rate 19200
+user_bits: 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 145 146 147 148
+dumping 48 encoded bits in V.110 frame:
+0      0       0       0       0       0       0       0
+1      101     102     103     104     105     106     0
+1      107     108     109     110     111     112     0
+1      113     114     115     116     117     118     0
+1      119     120     121     122     123     124     0
+1      0       1       1       0       0       0       0
+1      125     126     127     128     129     130     0
+1      131     132     133     134     135     136     0
+1      137     138     139     140     141     142     0
+1      143     144     145     146     147     148     0
+dumping re-decoded V.110 frame:
+E-bits: 00 01 01 00 00 00 00
+S-bits: 00 00 00 00 00 00 00 00 00
+re-decoded user bits: 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 145 146 147 148
+
+======= User data rate 24000
+user_bits: 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
+dumping 30 encoded bits in V.110 frame:
+0      0       0       0       0       0       0       0
+1      101     102     103     104     105     106     0
+1      107     108     109     110     1       1       0
+1      111     112     1       1       113     114     0
+1      1       1       115     1       1       1       0
+1      0       0       1       0       0       0       0
+1      116     117     118     119     120     121     0
+1      122     123     124     125     1       1       0
+1      126     127     1       1       128     129     0
+1      1       1       130     1       1       1       0
+dumping re-decoded V.110 frame:
+E-bits: 00 00 01 00 00 00 00
+S-bits: 00 00 00 00 00 00 00 00 00
+re-decoded user bits: 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
+
+======= User data rate 28800
+user_bits: 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
+dumping 36 encoded bits in V.110 frame:
+0      0       0       0       0       0       0       0
+1      101     102     103     104     105     106     0
+1      107     108     109     110     1       1       0
+1      111     112     1       1       113     114     0
+1      1       1       115     116     117     118     0
+1      1       0       1       0       0       0       0
+1      119     120     121     122     123     124     0
+1      125     126     127     128     1       1       0
+1      129     130     1       1       131     132     0
+1      1       1       133     134     135     136     0
+dumping re-decoded V.110 frame:
+E-bits: 01 00 01 00 00 00 00
+S-bits: 00 00 00 00 00 00 00 00 00
+re-decoded user bits: 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
+
+======= User data rate 38400
+user_bits: 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 145 146 147 148
+dumping 48 encoded bits in V.110 frame:
+0      0       0       0       0       0       0       0
+1      101     102     103     104     105     106     0
+1      107     108     109     110     111     112     0
+1      113     114     115     116     117     118     0
+1      119     120     121     122     123     124     0
+1      0       1       1       0       0       0       0
+1      125     126     127     128     129     130     0
+1      131     132     133     134     135     136     0
+1      137     138     139     140     141     142     0
+1      143     144     145     146     147     148     0
+dumping re-decoded V.110 frame:
+E-bits: 00 01 01 00 00 00 00
+S-bits: 00 00 00 00 00 00 00 00 00
+re-decoded user bits: 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 145 146 147 148

--
To view, visit https://gerrit.osmocom.org/c/libosmocore/+/30762
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.osmocom.org/settings

Gerrit-Project: libosmocore
Gerrit-Branch: master
Gerrit-Change-Id: I1b5fd3847d3bfb0a0f763e0574893962ec699680
Gerrit-Change-Number: 30762
Gerrit-PatchSet: 1
Gerrit-Owner: laforge <[email protected]>
Gerrit-MessageType: newchange

Reply via email to