fixeria has uploaded this change for review.
coding: implement TCH/F9.6, TCH/[FH]4.8, TCH/F14.4
Implement all CSD specific channel modes, except TCH/{FH}2.4. The
later is slightly more complicated and can be added later.
It's not yet clear to me how to implement FACCH/[FH] for these new
CSD specific channel modes. According to 3GPP TS 45.003, sections
4.2.5 and 4.3.5, a FACCH/[FH] does not steal but disturb some part
of the CSD data blocks. Leaving this as TODO.
Change-Id: Ib482817b5f6a4e3c7299f6e0b3841143b60fc93d
Related: OS#1572
---
M include/osmocom/coding/gsm0503_coding.h
M src/coding/gsm0503_coding.c
M src/coding/libosmocoding.map
3 files changed, 284 insertions(+), 0 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/libosmocore refs/changes/08/32808/1
diff --git a/include/osmocom/coding/gsm0503_coding.h b/include/osmocom/coding/gsm0503_coding.h
index 2afa049..67efcf1 100644
--- a/include/osmocom/coding/gsm0503_coding.h
+++ b/include/osmocom/coding/gsm0503_coding.h
@@ -86,4 +86,20 @@
int gsm0503_sch_encode(ubit_t *burst, const uint8_t *sb_info);
int gsm0503_sch_decode(uint8_t *sb_info, const sbit_t *burst);
+int gsm0503_tch_fr96_encode(sbit_t *bursts, const uint8_t *data);
+int gsm0503_tch_fr96_decode(uint8_t *data, const sbit_t *bursts,
+ int *n_errors, int *n_bits_total);
+
+int gsm0503_tch_fr48_encode(sbit_t *bursts, const uint8_t *data);
+int gsm0503_tch_fr48_decode(uint8_t *data, const sbit_t *bursts,
+ int *n_errors, int *n_bits_total);
+
+int gsm0503_tch_hr48_encode(sbit_t *bursts, const uint8_t *data);
+int gsm0503_tch_hr48_decode(uint8_t *data, const sbit_t *bursts,
+ int *n_errors, int *n_bits_total);
+
+int gsm0503_tch_fr144_encode(sbit_t *bursts, const uint8_t *data);
+int gsm0503_tch_fr144_decode(uint8_t *data, const sbit_t *bursts,
+ int *n_errors, int *n_bits_total);
+
/*! @} */
diff --git a/src/coding/gsm0503_coding.c b/src/coding/gsm0503_coding.c
index 3fd440f..dab961d 100644
--- a/src/coding/gsm0503_coding.c
+++ b/src/coding/gsm0503_coding.c
@@ -3265,4 +3265,245 @@
return 0;
}
+/*
+ * GSM CSD transcoding
+ */
+
+/*! Perform channel encoding of a TCH/F9.6 channel as per section 3.3.
+ * \param[out] bursts Caller-allocated buffer for symbols of 22 bursts,
+ * 22 * 2 * 58 == 2552 bits total.
+ * \param[in] data Data to be encoded (240 / 8 bytes).
+ * \returns 0 in case of success; negative on error */
+int gsm0503_tch_fr96_encode(sbit_t *bursts, const uint8_t *data)
+{
+ ubit_t iB[22 * 114], cB[4 * 114];
+ ubit_t conv[244];
+
+ /* 3.3.2 Block code: b1(60) + b2(60) + b3(60) + b4(60) */
+ osmo_pbit2ubit_ext(&conv[0], 0, &data[0], 0, 240, 1);
+ memset(&conv[240], 0, 4); /* + pad(4) */
+
+ /* 3.3.3 Convolutional encoder */
+ osmo_conv_encode(&gsm0503_tch_f96, &conv[0], &cB[0]);
+
+ /* 3.3.4 Interleaving */
+ gsm0503_tch_f96_interleave(&cB[0], &iB[0]);
+
+ /* 3.3.5 Mapping on a burst: as specified for TCH/FS in subclause 3.1.4 */
+ for (unsigned int i = 0; i < 22; i++) {
+ memcpy(&bursts[i * 116], &iB[i * 114], 57);
+ memcpy(&bursts[i * 116 + 59], &iB[i * 114 + 57], 57);
+ /* TODO: properly set hl(B) or hu(B) for FACCH */
+ }
+
+ return 0;
+}
+
+/*! Perform channel decoding of a TCH/F9.6 channel as per section 3.3.
+ * \param[out] data Caller-allocated buffer for decoded data.
+ * \param[in] bursts Buffer containing the symbols of 22 bursts,
+ * 22 * 2 * 58 == 2552 bits total.
+ * \param[out] n_errors Number of detected bit errors.
+ * \param[out] n_bits_total Total number of bits.
+ * \returns Length of bytes used in \a data output buffer; negative on error. */
+int gsm0503_tch_fr96_decode(uint8_t *data, const sbit_t *bursts,
+ int *n_errors, int *n_bits_total)
+{
+ sbit_t iB[22 * 114], cB[4 * 114];
+ ubit_t conv[244];
+
+ /* 3.3.5 Mapping on a burst: as specified for TCH/FS in subclause 3.1.4 */
+ for (unsigned int i = 0; i < 22; i++) {
+ memcpy(&iB[i * 114], &bursts[i * 116], 57);
+ memcpy(&iB[i * 114 + 57], &bursts[i * 116 + 59], 57);
+ /* TODO: check hl(B) or hu(B) for FACCH */
+ }
+
+ /* 3.3.4 Interleaving */
+ gsm0503_tch_f96_deinterleave(&cB[0], &iB[0]);
+
+ /* TODO: implement FACCH decoding */
+
+ /* 3.3.3 Convolutional encoder */
+ osmo_conv_decode_ber(&gsm0503_tch_f96, &cB[0], &conv[0], n_errors, n_bits_total);
+
+ /* 3.3.2 Block code: b1(60) + b2(60) + b3(60) + b4(60) */
+ osmo_ubit2pbit_ext(&data[0], 0, &conv[0], 0, 240, 1);
+
+ return 240 / 8;
+}
+
+/*! Perform channel encoding of a TCH/F4.8 channel as per section 3.4.
+ * \param[out] bursts Caller-allocated buffer for symbols of 22 bursts,
+ * 22 * 2 * 58 == 2552 bits total.
+ * \param[in] data Data to be encoded (120 / 8 bytes).
+ * \returns 0 in case of success; negative on error */
+int gsm0503_tch_fr48_encode(sbit_t *bursts, const uint8_t *data)
+{
+ ubit_t iB[22 * 114], cB[4 * 114];
+ ubit_t conv[120 + 32], d[2 * 60];
+
+ /* 3.4.2 Block code:
+ *
+ * Sixteen bits equal to 0 are added to the 60 information bits, the result
+ * being a block of 76 bits, {u(0),u(1),...,u(75)}, with:
+ *
+ * u(19k+p) = d(15k+p) for k = 0,1,2,3 and p = 0,1,...,14;
+ * u(19k+p) = 0 for k = 0,1,2,3 and p = 15,16,17,18.
+ *
+ * Two such blocks forming a block of 152 bits: u1 + u2. */
+ osmo_pbit2ubit_ext(&d[0], 0, &data[0], 0, 2 * 60, 1);
+ for (unsigned int k = 0; k < 2 * 4; k++) {
+ memcpy(&conv[19 * k], &d[15 * k], 15);
+ memset(&conv[19 * k + 15], 0, 4);
+ }
+
+ /* 3.4.3 Convolutional encoder */
+ osmo_conv_encode(&gsm0503_tch_f48, &conv[0], &cB[0]);
+
+ /* 3.4.4 Interleaving: as specified for the TCH/F9.6 in subclause 3.3.4 */
+ gsm0503_tch_f96_interleave(&cB[0], &iB[0]);
+
+ /* 3.4.5 Mapping on a burst: as specified for TCH/FS in subclause 3.1.4 */
+ for (unsigned int i = 0; i < 22; i++) {
+ memcpy(&bursts[i * 116], &iB[i * 114], 57);
+ memcpy(&bursts[i * 116 + 59], &iB[i * 114 + 57], 57);
+ /* TODO: properly set hl(B) or hu(B) for FACCH */
+ }
+
+ return 0;
+}
+
+/*! Perform channel decoding of a TCH/F4.8 channel as per section 3.4.
+ * \param[out] data Caller-allocated buffer for decoded data.
+ * \param[in] bursts Buffer containing the symbols of 22 bursts,
+ * 22 * 2 * 58 == 2552 bits total.
+ * \param[out] n_errors Number of detected bit errors.
+ * \param[out] n_bits_total Total number of bits.
+ * \returns Length of bytes used in \a data output buffer; negative on error. */
+int gsm0503_tch_fr48_decode(uint8_t *data, const sbit_t *bursts,
+ int *n_errors, int *n_bits_total)
+{
+ sbit_t iB[22 * 114], cB[4 * 114];
+ ubit_t conv[120 + 32], d[2 * 60];
+
+ /* 3.4.5 Mapping on a burst: as specified for TCH/FS in subclause 3.1.4 */
+ for (unsigned int i = 0; i < 22; i++) {
+ memcpy(&iB[i * 114], &bursts[i * 116], 57);
+ memcpy(&iB[i * 114 + 57], &bursts[i * 116 + 59], 57);
+ /* TODO: check hl(B) or hu(B) for FACCH */
+ }
+
+ /* 3.4.4 Interleaving: as specified for the TCH/F9.6 in subclause 3.3.4 */
+ gsm0503_tch_f96_deinterleave(&cB[0], &iB[0]);
+
+ /* TODO: implement FACCH decoding */
+
+ /* 3.4.3 Convolutional encoder */
+ osmo_conv_decode_ber(&gsm0503_tch_f48, &cB[0], &conv[0], n_errors, n_bits_total);
+
+ /* 3.4.2 Block code:
+ *
+ * Sixteen bits equal to 0 are added to the 60 information bits, the result
+ * being a block of 76 bits, {u(0),u(1),...,u(75)}, with:
+ *
+ * u(19k+p) = d(15k+p) for k = 0,1,2,3 and p = 0,1,...,14;
+ * u(19k+p) = 0 for k = 0,1,2,3 and p = 15,16,17,18.
+ *
+ * Two such blocks forming a block of 152 bits: u1 + u2. */
+ for (unsigned int k = 0; k < 2 * 4; k++)
+ memcpy(&d[15 * k], &conv[19 * k], 15);
+ osmo_ubit2pbit_ext(&data[0], 0, &d[0], 0, 2 * 60, 1);
+
+ return (2 * 60) / 8;
+}
+
+/*! Perform channel encoding of a TCH/H4.8 channel as per section 3.5.
+ * \param[out] bursts Caller-allocated buffer for symbols of 22 bursts,
+ * 22 * 2 * 58 == 2552 bits total.
+ * \param[in] data Data to be encoded (240 / 8 bytes).
+ * \returns 0 in case of success; negative on error */
+int gsm0503_tch_hr48_encode(sbit_t *bursts, const uint8_t *data)
+{
+ return gsm0503_tch_fr96_encode(bursts, data);
+}
+
+/*! Perform channel decoding of a TCH/H4.8 channel as per section 3.5.
+ * The algorithm is identical to TCH/F9.6, so it's just a wrapper.
+ * \param[out] data Caller-allocated buffer for decoded data.
+ * \param[in] bursts Buffer containing the symbols of 22 bursts,
+ * 22 * 2 * 58 == 2552 bits total.
+ * \param[out] n_errors Number of detected bit errors.
+ * \param[out] n_bits_total Total number of bits.
+ * \returns Length of bytes used in \a data output buffer; negative on error. */
+int gsm0503_tch_hr48_decode(uint8_t *data, const sbit_t *bursts,
+ int *n_errors, int *n_bits_total)
+{
+ return gsm0503_tch_fr96_decode(data, bursts, n_errors, n_bits_total);
+}
+
+/*! Perform channel encoding of a TCH/F14.4 channel as per section 3.8.
+ * \param[out] bursts Caller-allocated buffer for symbols of 22 bursts,
+ * 22 * 2 * 58 == 2552 bits total.
+ * \param[in] data Data to be encoded (296 / 8 bytes).
+ * \returns 0 in case of success; negative on error */
+int gsm0503_tch_fr144_encode(sbit_t *bursts, const uint8_t *data)
+{
+ ubit_t iB[22 * 114], cB[4 * 114];
+ ubit_t conv[294];
+
+ /* 3.8.2 Block code: b(290) + pad(4) */
+ osmo_pbit2ubit_ext(&conv[0], 0, &data[0], 0, 290, 1);
+ memset(&conv[290], 0, 4); /* + pad(4) */
+
+ /* 3.8.3 Convolutional encoder */
+ osmo_conv_encode(&gsm0503_tch_f144, &conv[0], &cB[0]);
+
+ /* 3.8.4 Interleaving */
+ gsm0503_tch_f96_interleave(&cB[0], &iB[0]);
+
+ /* 3.8.5 Mapping on a burst: as specified for TCH/FS in subclause 3.1.4 */
+ for (unsigned int i = 0; i < 22; i++) {
+ memcpy(&bursts[i * 116], &iB[i * 114], 57);
+ memcpy(&bursts[i * 116 + 59], &iB[i * 114 + 57], 57);
+ /* TODO: properly set hl(B) or hu(B) for FACCH */
+ }
+
+ return 0;
+}
+
+/*! Perform channel decoding of a TCH/14.4 channel as per section 3.8.
+ * \param[out] data Caller-allocated buffer for decoded data.
+ * \param[in] bursts Buffer containing the symbols of 22 bursts,
+ * 22 * 2 * 58 == 2552 bits total.
+ * \param[out] n_errors Number of detected bit errors.
+ * \param[out] n_bits_total Total number of bits.
+ * \returns Length of bytes used in \a data output buffer; negative on error. */
+int gsm0503_tch_fr144_decode(uint8_t *data, const sbit_t *bursts,
+ int *n_errors, int *n_bits_total)
+{
+ sbit_t iB[22 * 114], cB[4 * 114];
+ ubit_t conv[294];
+
+ /* 3.8.5 Mapping on a burst: as specified for TCH/FS in subclause 3.1.4 */
+ for (unsigned int i = 0; i < 22; i++) {
+ memcpy(&iB[i * 114], &bursts[i * 116], 57);
+ memcpy(&iB[i * 114 + 57], &bursts[i * 116 + 59], 57);
+ /* TODO: check hl(B) or hu(B) for FACCH */
+ }
+
+ /* 3.8.4 Interleaving: as specified for the TCH/F9.6 in subclause 3.3.4 */
+ gsm0503_tch_f96_deinterleave(&cB[0], &iB[0]);
+
+ /* TODO: implement FACCH decoding */
+
+ /* 3.8.3 Convolutional encoder */
+ osmo_conv_decode_ber(&gsm0503_tch_f144, &cB[0], &conv[0], n_errors, n_bits_total);
+
+ /* 3.8.2 Block code: b(290) + pad(4) */
+ osmo_ubit2pbit_ext(&data[0], 0, &conv[0], 0, 290, 1);
+
+ return (290 + 6) / 8; /* 6 unused bits */
+}
+
/*! @} */
diff --git a/src/coding/libosmocoding.map b/src/coding/libosmocoding.map
index ff6ea80..aba7453 100644
--- a/src/coding/libosmocoding.map
+++ b/src/coding/libosmocoding.map
@@ -128,5 +128,14 @@
gsm0503_detect_afs_dtx_frame2;
gsm0503_detect_ahs_dtx_frame2;
+gsm0503_tch_fr96_encode;
+gsm0503_tch_fr96_decode;
+gsm0503_tch_fr48_encode;
+gsm0503_tch_fr48_decode;
+gsm0503_tch_hr48_encode;
+gsm0503_tch_hr48_decode;
+gsm0503_tch_fr144_encode;
+gsm0503_tch_fr144_decode;
+
local: *;
};
To view, visit change 32808. To unsubscribe, or for help writing mail filters, visit settings.