This is merely a historical archive of years 2008-2021, before the migration to mailman3.
A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.
Vadim Yanitskiy gerrit-no-reply at lists.osmocom.orgVadim Yanitskiy has uploaded this change for review. ( https://gerrit.osmocom.org/10460 Change subject: trxcon/scheduler: add TCH/H channel support ...................................................................... trxcon/scheduler: add TCH/H channel support Change-Id: Ibb2a0850692c5ff86b13b820af10b12085589e67 --- M src/host/trxcon/Makefile.am M src/host/trxcon/sched_lchan_desc.c A src/host/trxcon/sched_lchan_tchh.c M src/host/trxcon/sched_trx.c M src/host/trxcon/sched_trx.h 5 files changed, 329 insertions(+), 7 deletions(-) git pull ssh://gerrit.osmocom.org:29418/osmocom-bb refs/changes/60/10460/1 diff --git a/src/host/trxcon/Makefile.am b/src/host/trxcon/Makefile.am index c9cc170..7095cb5 100644 --- a/src/host/trxcon/Makefile.am +++ b/src/host/trxcon/Makefile.am @@ -35,6 +35,7 @@ sched_lchan_desc.c \ sched_lchan_xcch.c \ sched_lchan_tchf.c \ + sched_lchan_tchh.c \ sched_lchan_rach.c \ sched_lchan_sch.c \ sched_mframe.c \ diff --git a/src/host/trxcon/sched_lchan_desc.c b/src/host/trxcon/sched_lchan_desc.c index 37d1273..4cac439 100644 --- a/src/host/trxcon/sched_lchan_desc.c +++ b/src/host/trxcon/sched_lchan_desc.c @@ -27,10 +27,7 @@ /* TODO: implement */ #define tx_pdtch_fn NULL -#define tx_tchh_fn NULL - #define rx_pdtch_fn NULL -#define rx_tchh_fn NULL /* Forward declaration of handlers */ int rx_data_fn(struct trx_instance *trx, struct trx_ts *ts, @@ -54,6 +51,14 @@ int tx_tchf_fn(struct trx_instance *trx, struct trx_ts *ts, struct trx_lchan_state *lchan, uint32_t fn, uint8_t bid); +int rx_tchh_fn(struct trx_instance *trx, struct trx_ts *ts, + struct trx_lchan_state *lchan, uint32_t fn, uint8_t bid, + sbit_t *bits, int8_t rssi, int16_t toa256); + +int tx_tchh_fn(struct trx_instance *trx, struct trx_ts *ts, + struct trx_lchan_state *lchan, uint32_t fn, uint8_t bid); + + const struct trx_lchan_desc trx_lchan_desc[_TRX_CHAN_MAX] = { { TRXC_IDLE, "IDLE", diff --git a/src/host/trxcon/sched_lchan_tchh.c b/src/host/trxcon/sched_lchan_tchh.c new file mode 100644 index 0000000..678fca8 --- /dev/null +++ b/src/host/trxcon/sched_lchan_tchh.c @@ -0,0 +1,316 @@ +/* + * OsmocomBB <-> SDR connection bridge + * TDMA scheduler: handlers for DL / UL bursts on logical channels + * + * (C) 2018 by Vadim Yanitskiy <axilirator at gmail.com> + * (C) 2018 by Harald Welte <laforge at gnumonks.org> + * + * All Rights Reserved + * + * 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. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include <errno.h> +#include <string.h> +#include <stdint.h> + +#include <osmocom/core/logging.h> +#include <osmocom/core/bits.h> + +#include <osmocom/gsm/protocol/gsm_04_08.h> +#include <osmocom/gsm/gsm_utils.h> + +#include <osmocom/coding/gsm0503_coding.h> +#include <osmocom/codec/codec.h> + +#include "l1ctl_proto.h" +#include "scheduler.h" +#include "sched_trx.h" +#include "logging.h" +#include "trx_if.h" +#include "trxcon.h" +#include "l1ctl.h" + +int rx_tchh_fn(struct trx_instance *trx, struct trx_ts *ts, + struct trx_lchan_state *lchan, uint32_t fn, uint8_t bid, + sbit_t *bits, int8_t rssi, int16_t toa256) +{ + const struct trx_lchan_desc *lchan_desc; + int n_errors = -1, n_bits_total, rc; + sbit_t *buffer, *offset; + uint8_t l2[128], *mask; + uint32_t *first_fn; + bool facch_now; + size_t l2_len; + + /* Set up pointers */ + lchan_desc = &trx_lchan_desc[lchan->type]; + first_fn = &lchan->rx_first_fn; + mask = &lchan->rx_burst_mask; + buffer = lchan->rx_bursts; + + LOGP(DSCHD, LOGL_DEBUG, "Traffic received on %s: fn=%u ts=%u bid=%u\n", + lchan_desc->name, fn, ts->index, bid); + + /* Reset internal state */ + if (bid == 0) { + /* FIXME: clean up old measurements */ + memset(&lchan->meas, 0x00, sizeof(lchan->meas)); + + /* FIXME: clear history buffer: no need? */ + memset(buffer + 464, 0, 232); + + *first_fn = fn; + *mask = 0x00; + } + + /* Update mask */ + *mask |= (1 << bid); + + /* Update mask and RSSI */ + lchan->meas.rssi_sum += rssi; + lchan->meas.toa256_sum += toa256; + lchan->meas.rssi_num++; + lchan->meas.toa256_num++; + + /* Copy burst to the end of buffer of 6 bursts */ + offset = buffer + bid * 116 + 464; + memcpy(offset, bits + 3, 58); + memcpy(offset + 58, bits + 87, 58); + + /* Wait until complete set of bursts */ + if (bid != 1) + return 0; + + /* Check for complete set of bursts */ + if ((*mask & 0x3) != 0x3) { + LOGP(DSCHD, LOGL_ERROR, "Received incomplete traffic frame at " + "fn=%u (%u/%u) for %s\n", *first_fn, + (*first_fn) % ts->mf_layout->period, + ts->mf_layout->period, + lchan_desc->name); + + /* Send BFI */ + goto bfi; + } + + /* skip second of two TCH frames of FACCH was received */ + if (lchan->dl_ongoing_facch) { + lchan->dl_ongoing_facch = false; + memcpy(buffer, buffer + 232, 232); + memcpy(buffer + 232, buffer + 464, 232); + goto bfi; + } + + /* May we have a FACCH/H frame on the current frame number? */ + facch_now = sched_facch_h_dl_end(lchan->type, fn); + + switch (lchan->tch_mode) { + case GSM48_CMODE_SIGN: + case GSM48_CMODE_SPEECH_V1: /* HR */ + rc = gsm0503_tch_hr_decode(l2, buffer, + !facch_now, &n_errors, &n_bits_total); + break; + case GSM48_CMODE_SPEECH_AMR: /* AMR */ + /** + * TODO: AMR requires a dedicated loop, + * which will be implemented later... + */ + LOGP(DSCHD, LOGL_ERROR, "AMR isn't supported yet\n"); + return -ENOTSUP; + default: + LOGP(DSCHD, LOGL_ERROR, "Invalid TCH mode: %u\n", lchan->tch_mode); + return -EINVAL; + } + + /* Shift buffer by 4 bursts for interleaving */ + memcpy(buffer, buffer + 232, 232); + memcpy(buffer + 232, buffer + 464, 232); + + /* Check decoding result */ + if (rc < 4) { + LOGP(DSCHD, LOGL_ERROR, "Received bad TCH frame ending at " + "fn=%u for %s: %d\n", fn, lchan_desc->name, rc); + + /* Send BFI */ + goto bfi; + } else if (rc == GSM_MACBLOCK_LEN) { + lchan->dl_ongoing_facch = true; + /* FACCH received, forward it to the higher layers */ + sched_send_dt_ind(trx, ts, lchan, l2, GSM_MACBLOCK_LEN, + n_errors, false, false); + + /* Send BFI instead of a stolen TCH frame */ + goto bfi; + } else { + /* A good TCH frame received */ + l2_len = rc; + } + + /* Send a traffic frame to the higher layers */ + return sched_send_dt_ind(trx, ts, lchan, l2, l2_len, + n_errors, false, true); + +bfi: + /* Bad frame indication */ + l2_len = sched_bad_frame_ind(l2, lchan); + + /* Didn't try to decode */ + if (n_errors < 0) + n_errors = 116 * 4; + + /* Send a BFI frame to the higher layers */ + return sched_send_dt_ind(trx, ts, lchan, l2, l2_len, + n_errors, true, true); +} + +int tx_tchh_fn(struct trx_instance *trx, struct trx_ts *ts, + struct trx_lchan_state *lchan, uint32_t fn, uint8_t bid) +{ + const struct trx_lchan_desc *lchan_desc; + ubit_t burst[GSM_BURST_LEN]; + ubit_t *buffer, *offset; + const uint8_t *tsc; + uint8_t *mask; + size_t l2_len; + int rc; + + /* Set up pointers */ + lchan_desc = &trx_lchan_desc[lchan->type]; + mask = &lchan->tx_burst_mask; + buffer = lchan->tx_bursts; + + if (bid > 0) { + /* Align to the first burst */ + if (*mask == 0x00) + return 0; + goto send_burst; + } + + if (*mask == 0x00) { + /* Align transmission of the first FACCH/H frame */ + if (lchan->tch_mode == GSM48_CMODE_SIGN) + if (!sched_facch_h_ul_start(lchan->type, fn)) + return 0; + } + + /* Shift buffer by 2 bursts back for interleaving */ + memcpy(buffer, buffer + 232, 232); + + /* Also shift TX burst mask */ + *mask = *mask << 2; + + /* If FACCH/H blocks are still pending */ + if (lchan->ul_facch_blocks > 2) { + memcpy(buffer + 232, buffer + 464, 232); + goto send_burst; + } + + /* Check the current TCH mode */ + switch (lchan->tch_mode) { + case GSM48_CMODE_SIGN: + case GSM48_CMODE_SPEECH_V1: /* HR */ + l2_len = GSM_HR_BYTES + 1; + break; + case GSM48_CMODE_SPEECH_AMR: /* AMR */ + /** + * TODO: AMR requires a dedicated loop, + * which will be implemented later... + */ + LOGP(DSCHD, LOGL_ERROR, "AMR isn't supported yet, " + "dropping frame...\n"); + + /* Forget this primitive */ + sched_prim_drop(lchan); + return -ENOTSUP; + default: + LOGP(DSCHD, LOGL_ERROR, "Invalid TCH mode: %u, " + "dropping frame...\n", lchan->tch_mode); + + /* Forget this primitive */ + sched_prim_drop(lchan); + return -EINVAL; + } + + /* Determine payload length */ + if (PRIM_IS_FACCH(lchan->prim)) { + l2_len = GSM_MACBLOCK_LEN; /* FACCH */ + } else if (lchan->prim->payload_len != l2_len) { + LOGP(DSCHD, LOGL_ERROR, "Primitive has odd length %zu " + "(expected %zu for TCH or %u for FACCH), so dropping...\n", + lchan->prim->payload_len, l2_len, GSM_MACBLOCK_LEN); + + /* Forget this primitive */ + sched_prim_drop(lchan); + return -EINVAL; + } + + /* Encode the payload */ + rc = gsm0503_tch_hr_encode(buffer, lchan->prim->payload, l2_len); + if (rc) { + LOGP(DSCHD, LOGL_ERROR, "Failed to encode L2 payload\n"); + + /* Forget this primitive */ + sched_prim_drop(lchan); + return -EINVAL; + } + + /* A FACCH/H frame occupies 6 bursts */ + if (PRIM_IS_FACCH(lchan->prim)) + lchan->ul_facch_blocks = 6; + +send_burst: + /* Determine which burst should be sent */ + offset = buffer + bid * 116; + + /* Update mask */ + *mask |= (1 << bid); + + /* Choose proper TSC */ + tsc = sched_nb_training_bits[trx->tsc]; + + /* Compose a new burst */ + memset(burst, 0, 3); /* TB */ + memcpy(burst + 3, offset, 58); /* Payload 1/2 */ + memcpy(burst + 61, tsc, 26); /* TSC */ + memcpy(burst + 87, offset + 58, 58); /* Payload 2/2 */ + memset(burst + 145, 0, 3); /* TB */ + + LOGP(DSCHD, LOGL_DEBUG, "Transmitting %s fn=%u ts=%u burst=%u\n", + lchan_desc->name, fn, ts->index, bid); + + /* Forward burst to transceiver */ + sched_trx_handle_tx_burst(trx, ts, lchan, fn, burst); + + /* In case of a FACCH/H frame, one block less */ + if (lchan->ul_facch_blocks) + lchan->ul_facch_blocks--; + + if ((*mask & 0x0f) == 0x0f) { + /** + * If no more FACCH/H blocks pending, + * confirm data / traffic sending + */ + if (!lchan->ul_facch_blocks) + sched_send_dt_conf(trx, ts, lchan, fn, + PRIM_IS_TCH(lchan->prim)); + + /* Forget processed primitive */ + sched_prim_drop(lchan); + } + + return 0; +} diff --git a/src/host/trxcon/sched_trx.c b/src/host/trxcon/sched_trx.c index 8bd3c72..bc51d96 100644 --- a/src/host/trxcon/sched_trx.c +++ b/src/host/trxcon/sched_trx.c @@ -463,7 +463,7 @@ /* TCH specific variables */ if (CHAN_IS_TCH(lchan->type)) { lchan->dl_ongoing_facch = 0; - lchan->ul_ongoing_facch = 0; + lchan->ul_facch_blocks = 0; lchan->tch_mode = GSM48_CMODE_SIGN; diff --git a/src/host/trxcon/sched_trx.h b/src/host/trxcon/sched_trx.h index f8898cd..57b4782 100644 --- a/src/host/trxcon/sched_trx.h +++ b/src/host/trxcon/sched_trx.h @@ -171,9 +171,9 @@ uint8_t tch_mode; /*! \brief FACCH/H on downlink */ - uint8_t dl_ongoing_facch; - /*! \brief FACCH/H on uplink */ - uint8_t ul_ongoing_facch; + bool dl_ongoing_facch; + /*! \brief pending FACCH/H blocks on Uplink */ + uint8_t ul_facch_blocks; struct { /*! \brief Number of RSSI values */ -- To view, visit https://gerrit.osmocom.org/10460 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: osmocom-bb Gerrit-Branch: master Gerrit-MessageType: newchange Gerrit-Change-Id: Ibb2a0850692c5ff86b13b820af10b12085589e67 Gerrit-Change-Number: 10460 Gerrit-PatchSet: 1 Gerrit-Owner: Vadim Yanitskiy <axilirator at gmail.com> -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20180815/f0482935/attachment.htm>