fixeria has uploaded this change for review. ( 
https://gerrit.osmocom.org/c/osmo-bts/+/32727 )


Change subject: [WIP] osmo-bts-trx: implement TCH/F9.6 support for CSD
......................................................................

[WIP] osmo-bts-trx: implement TCH/F9.6 support for CSD

According to 3GPP TS 45.003, Figure 1a and section 3.3.4, for CSD
a new block of coded data starts with every fourth burst and is
distributed over 22 bursts.  This requires us to:

* enlarge the maximum burst buffer size to 22 * (2 * 58) bytes;
* enlarge per-l1cs Uplink burst mask to hold up to 32 bits;
* enlarge per-l1cs Uplink meas ring buffer to 22 entries;
* add SCHED_MEAS_AVG_M_S22N22 - new Uplink meas AVG mode.

Change-Id: I08ffbf8e79ce76a586d61f5463890c6e72a6d9b9
Related: OS#1572
---
M include/osmo-bts/scheduler.h
M src/common/bts.c
M src/common/scheduler.c
M src/osmo-bts-trx/sched_lchan_pdtch.c
M src/osmo-bts-trx/sched_lchan_tchf.c
M src/osmo-bts-trx/sched_lchan_tchh.c
M src/osmo-bts-trx/sched_lchan_xcch.c
M src/osmo-bts-trx/scheduler_trx.c
8 files changed, 126 insertions(+), 38 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/osmo-bts refs/changes/27/32727/1

diff --git a/include/osmo-bts/scheduler.h b/include/osmo-bts/scheduler.h
index 01e8e2b..b0c4b2f 100644
--- a/include/osmo-bts/scheduler.h
+++ b/include/osmo-bts/scheduler.h
@@ -93,7 +93,7 @@
        sbit_t                  *ul_bursts;     /* burst buffer for RX */
        sbit_t                  *ul_bursts_prev;/* previous burst buffer for RX 
(repeated SACCH) */
        uint32_t                ul_first_fn;    /* fn of first burst */
-       uint8_t                 ul_mask;        /* mask of received bursts */
+       uint32_t                ul_mask;        /* mask of received bursts */

        /* loss detection */
        uint32_t                last_tdma_fn;   /* last processed TDMA frame 
number */
@@ -131,7 +131,7 @@
        /* Uplink measurements */
        struct {
                /* Active channel measurements (simple ring buffer) */
-               struct l1sched_meas_set buf[8]; /* up to 8 entries */
+               struct l1sched_meas_set buf[22]; /* up to 22 entries */
                unsigned int current; /* current position */

                /* Interference measurements */
@@ -300,6 +300,8 @@

 /* Averaging mode for trx_sched_meas_avg() */
 enum sched_meas_avg_mode {
+       /* last 22 bursts (for CSD on TCH/F and TCH/H) */
+       SCHED_MEAS_AVG_M_S22N22,
        /* last 4 bursts (default for xCCH, PTCCH and PDTCH) */
        SCHED_MEAS_AVG_M_S4N4,
        /* last 8 bursts (default for TCH/F and FACCH/F) */
diff --git a/src/common/bts.c b/src/common/bts.c
index 242c5dd..0f8dcc7 100644
--- a/src/common/bts.c
+++ b/src/common/bts.c
@@ -776,23 +776,11 @@
        return &bts->gsm_time;
 }

-int bts_supports_cm(const struct gsm_bts *bts,
-                   const struct rsl_ie_chan_mode *cm)
+static int bts_supports_cm_speech(const struct gsm_bts *bts,
+                                 const struct rsl_ie_chan_mode *cm)
 {
        enum osmo_bts_features feature = _NUM_BTS_FEAT;

-       switch (cm->spd_ind) {
-       case RSL_CMOD_SPD_SIGN:
-               /* We assume that signalling support is mandatory,
-                * there is no BTS_FEAT_* definition to check that. */
-               return 1;
-       case RSL_CMOD_SPD_SPEECH:
-               break;
-       case RSL_CMOD_SPD_DATA:
-       default:
-               return 0;
-       }
-
        /* Before the requested pchan/cm combination can be checked, we need to
         * convert it to a feature identifier we can check */
        switch (cm->chan_rt) {
@@ -849,6 +837,44 @@
        return 0;
 }

+static int bts_supports_cm_data(const struct gsm_bts *bts,
+                               const struct rsl_ie_chan_mode *cm)
+{
+       /* XXX: only osmo-bts-trx has limited support of CSD */
+       switch (bts->variant) {
+       case BTS_OSMO_TRX:
+               /* XXX: only TCH/F9.6 (Um rate 12.0 kbit/s) is supported */
+               if (cm->chan_rt != RSL_CMOD_CRT_TCH_Bm)
+                       return 0;
+               switch (cm->chan_rate) {
+               case RSL_CMOD_CSD_NT_12k0:
+               case RSL_CMOD_CSD_T_9k6:
+                       return 1;
+               }
+               return 0;
+       default:
+               return 0;
+       }
+}
+
+int bts_supports_cm(const struct gsm_bts *bts,
+                   const struct rsl_ie_chan_mode *cm)
+{
+       switch (cm->spd_ind) {
+       case RSL_CMOD_SPD_SIGN:
+               /* We assume that signalling support is mandatory,
+                * there is no BTS_FEAT_* definition to check that. */
+               return 1;
+       case RSL_CMOD_SPD_SPEECH:
+               return bts_supports_cm_speech(bts, cm);
+       case RSL_CMOD_SPD_DATA:
+               return bts_supports_cm_data(bts, cm);
+       default:
+               return 0;
+       }
+
+}
+
 /* return the gsm_lchan for the CBCH (if it exists at all) */
 struct gsm_lchan *gsm_bts_get_cbch(struct gsm_bts *bts)
 {
diff --git a/src/common/scheduler.c b/src/common/scheduler.c
index cacae6c..62fe758 100644
--- a/src/common/scheduler.c
+++ b/src/common/scheduler.c
@@ -1077,9 +1077,9 @@
                chan_state->lchan = lchan;

                /* Allocate memory for Rx/Tx burst buffers.  Use the maximim 
size
-                * of 4 * (3 * 2 * 58) bytes, which is sufficient to store 4 
8PSK
-                * modulated bursts. */
-               const size_t buf_size = 4 * GSM_NBITS_NB_8PSK_PAYLOAD;
+                * of 22 * (2 * 58) bytes, which is sufficient to store 22 GMSK
+                * modulated bursts for CSD or 4 8PSK modulated bursts for 
EGPRS. */
+               const size_t buf_size = 22 * GSM_NBITS_NB_GMSK_PAYLOAD;
                if (trx_chan_desc[chan].dl_fn != NULL)
                        chan_state->dl_bursts = talloc_zero_size(l1ts, 
buf_size);
                if (trx_chan_desc[chan].ul_fn != NULL) {
diff --git a/src/osmo-bts-trx/sched_lchan_pdtch.c 
b/src/osmo-bts-trx/sched_lchan_pdtch.c
index 5ff7229..9ae68d0 100644
--- a/src/osmo-bts-trx/sched_lchan_pdtch.c
+++ b/src/osmo-bts-trx/sched_lchan_pdtch.c
@@ -44,7 +44,7 @@
        struct l1sched_chan_state *chan_state = &l1ts->chan_state[bi->chan];
        sbit_t *burst, *bursts_p = chan_state->ul_bursts;
        uint32_t first_fn;
-       uint8_t *mask = &chan_state->ul_mask;
+       uint32_t *mask = &chan_state->ul_mask;
        struct l1sched_meas_set meas_avg;
        uint8_t l2[EGPRS_0503_MAX_BYTES];
        int n_errors = 0;
diff --git a/src/osmo-bts-trx/sched_lchan_tchf.c 
b/src/osmo-bts-trx/sched_lchan_tchf.c
index 6dfdff8..400252d 100644
--- a/src/osmo-bts-trx/sched_lchan_tchf.c
+++ b/src/osmo-bts-trx/sched_lchan_tchf.c
@@ -76,7 +76,7 @@
        struct l1sched_chan_state *chan_state = &l1ts->chan_state[bi->chan];
        struct gsm_lchan *lchan = chan_state->lchan;
        sbit_t *burst, *bursts_p = chan_state->ul_bursts;
-       uint8_t *mask = &chan_state->ul_mask;
+       uint32_t *mask = &chan_state->ul_mask;
        uint8_t rsl_cmode = chan_state->rsl_cmode;
        uint8_t tch_mode = chan_state->tch_mode;
        uint8_t tch_data[128]; /* just to be safe */
@@ -101,8 +101,9 @@

        /* shift the buffer by 4 bursts leftwards */
        if (bi->bid == 0) {
-               memcpy(bursts_p, bursts_p + 464, 464);
-               memset(bursts_p + 464, 0, 464);
+               const size_t bl = GSM_NBITS_NB_GMSK_PAYLOAD;
+               memmove(&bursts_p[0], &bursts_p[4 * bl], 18 * bl);
+               memset(&bursts_p[18 * bl], 0, 4 * bl);
                *mask = *mask << 4;
        }

@@ -112,13 +113,13 @@
        /* store measurements */
        trx_sched_meas_push(chan_state, bi);

-       /* copy burst to end of buffer of 8 bursts */
-       burst = bursts_p + bi->bid * 116 + 464;
+       /* copy burst to end of buffer of 22 bursts */
+       burst = bursts_p + (bi->bid + 18) * GSM_NBITS_NB_GMSK_PAYLOAD;
        if (bi->burst_len > 0) {
                memcpy(burst, bi->burst + 3, 58);
                memcpy(burst + 58, bi->burst + 87, 58);
        } else
-               memset(burst, 0, 116);
+               memset(burst, 0, GSM_NBITS_NB_GMSK_PAYLOAD);

        /* wait until complete set of bursts */
        if (bi->bid != 3)
@@ -132,8 +133,13 @@
                return 0; /* TODO: send BFI */
        }

-       /* decode
-        * also shift buffer by 4 bursts for interleaving */
+       /* TCH/F: speech and signalling frames are interleaved over 8 bursts, 
while
+        * CSD frames are interleaved over 22 bursts.  Unless we're in CSD mode,
+        * decode only the last 8 bursts to avoid introducing additional 
delays. */
+       if (rsl_cmode != RSL_CMOD_SPD_DATA)
+               bursts_p += (22 - 8) * GSM_NBITS_NB_GMSK_PAYLOAD;
+
+       /* decode the payload */
        switch (tch_mode) {
        case GSM48_CMODE_SIGN:
        case GSM48_CMODE_SPEECH_V1: /* FR */
@@ -221,6 +227,21 @@
                }

                break;
+#if 0
+       /* CSD (TCH/F9.6): 12.0 kbit/s radio interface rate */
+       case GSM48_CMODE_DATA_12k0:
+       {
+               ubit_t decoded[244];
+               sbit_t cB[456];
+
+               /* TODO: unmap, handle FACCH */
+               gsm0503_tch_f96_deinterleave(&cB[0], bursts_p);
+               osmo_conv_decode(&gsm0503_tch_f96, &cB[0], &decoded[0]);
+               osmo_ubit2pbit_ext(&tch_data[0], 0, decoded, 0, 240, 1);
+               meas_avg_mode = SCHED_MEAS_AVG_M_S22N22;
+               break;
+       }
+#endif
        default:
                LOGL1SB(DL1P, LOGL_ERROR, l1ts, bi,
                        "TCH mode %u invalid, please fix!\n",
@@ -474,6 +495,7 @@
        struct l1sched_chan_state *chan_state = &l1ts->chan_state[br->chan];
        uint8_t tch_mode = chan_state->tch_mode;
        ubit_t *burst, *bursts_p = chan_state->dl_bursts;
+       const size_t bl = GSM_NBITS_NB_GMSK_PAYLOAD;
        struct msgb *msg;

        /* send burst, if we already got a frame */
@@ -483,8 +505,8 @@
        /* BURST BYPASS */

         /* shift buffer by 4 bursts for interleaving */
-       memcpy(bursts_p, bursts_p + 464, 464);
-       memset(bursts_p + 464, 0, 464);
+       memmove(&bursts_p[0], &bursts_p[4 * bl], 18 * bl);
+       memset(&bursts_p[18 * bl], 0, 4 * bl);

        /* dequeue a message to be transmitted */
        msg = tch_dl_dequeue(l1ts, br);
@@ -503,11 +525,17 @@
                goto send_burst;
        }

-       /* populate the buffer with bursts */
-       if (msgb_l2len(msg) == GSM_MACBLOCK_LEN) {
-               gsm0503_tch_fr_encode(bursts_p, msg->l2h, msgb_l2len(msg), 1);
+       if (msgb_l2len(msg) == GSM_MACBLOCK_LEN)
                chan_state->dl_facch_bursts = 8;
-       } else if (tch_mode == GSM48_CMODE_SPEECH_AMR) {
+
+       /* populate the buffer with bursts */
+       switch (tch_mode) {
+       case GSM48_CMODE_SIGN:
+       case GSM48_CMODE_SPEECH_V1:
+       case GSM48_CMODE_SPEECH_EFR:
+               gsm0503_tch_fr_encode(bursts_p, msg->l2h, msgb_l2len(msg), 1);
+               break;
+       case GSM48_CMODE_SPEECH_AMR:
                /* the first FN 4,13,21 defines that CMI is included in frame,
                 * the first FN 0,8,17 defines that CMR is included in frame.
                 */
@@ -517,8 +545,20 @@
                        chan_state->codec, chan_state->codecs,
                        chan_state->dl_ft,
                        chan_state->dl_cmr);
-       } else {
-               gsm0503_tch_fr_encode(bursts_p, msg->l2h, msgb_l2len(msg), 1);
+               break;
+#if 0
+       case GSM48_CMODE_DATA_12k0:
+       {
+               ubit_t encoded[244];
+               sbit_t cB[456];
+
+               // osmo_conv_encode(&gsm0503_tch_f96, &cB[0], &decoded[0]);
+               // gsm0503_tch_f96_interleave(&cB[0], bursts_p);
+               break;
+       }
+#endif
+       default:
+               OSMO_ASSERT(0);
        }

        /* free message */
diff --git a/src/osmo-bts-trx/sched_lchan_tchh.c 
b/src/osmo-bts-trx/sched_lchan_tchh.c
index 94e2a9c..e9f0b6f 100644
--- a/src/osmo-bts-trx/sched_lchan_tchh.c
+++ b/src/osmo-bts-trx/sched_lchan_tchh.c
@@ -98,7 +98,7 @@
        struct l1sched_chan_state *chan_state = &l1ts->chan_state[bi->chan];
        struct gsm_lchan *lchan = chan_state->lchan;
        sbit_t *burst, *bursts_p = chan_state->ul_bursts;
-       uint8_t *mask = &chan_state->ul_mask;
+       uint32_t *mask = &chan_state->ul_mask;
        uint8_t rsl_cmode = chan_state->rsl_cmode;
        uint8_t tch_mode = chan_state->tch_mode;
        uint8_t tch_data[128]; /* just to be safe */
diff --git a/src/osmo-bts-trx/sched_lchan_xcch.c 
b/src/osmo-bts-trx/sched_lchan_xcch.c
index 1945d32..34b37c1 100644
--- a/src/osmo-bts-trx/sched_lchan_xcch.c
+++ b/src/osmo-bts-trx/sched_lchan_xcch.c
@@ -52,7 +52,7 @@
        struct l1sched_chan_state *chan_state = &l1ts->chan_state[bi->chan];
        sbit_t *burst, *bursts_p = chan_state->ul_bursts;
        uint32_t *first_fn = &chan_state->ul_first_fn;
-       uint8_t *mask = &chan_state->ul_mask;
+       uint32_t *mask = &chan_state->ul_mask;
        uint8_t l2[GSM_MACBLOCK_LEN], l2_len;
        struct l1sched_meas_set meas_avg;
        int n_errors = 0;
diff --git a/src/osmo-bts-trx/scheduler_trx.c b/src/osmo-bts-trx/scheduler_trx.c
index e7ed5ea..08f3fda 100644
--- a/src/osmo-bts-trx/scheduler_trx.c
+++ b/src/osmo-bts-trx/scheduler_trx.c
@@ -638,6 +638,7 @@

 /* Measurement averaging mode sets: [MODE] = { SHIFT, NUM } */
 static const uint8_t trx_sched_meas_modeset[][2] = {
+       [SCHED_MEAS_AVG_M_S22N22] = { 22, 22 },
        [SCHED_MEAS_AVG_M_S4N4] = { 4, 4 },
        [SCHED_MEAS_AVG_M_S8N8] = { 8, 8 },
        [SCHED_MEAS_AVG_M_S6N4] = { 6, 4 },

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

Gerrit-Project: osmo-bts
Gerrit-Branch: master
Gerrit-Change-Id: I08ffbf8e79ce76a586d61f5463890c6e72a6d9b9
Gerrit-Change-Number: 32727
Gerrit-PatchSet: 1
Gerrit-Owner: fixeria <[email protected]>
Gerrit-MessageType: newchange

Reply via email to