Projects
osmocom:master
osmo-bts
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 133
View file
osmo-bts.spec
Changed
@@ -14,13 +14,13 @@ Name: osmo-bts Requires: osmocom-master -Version: 1.6.0.168.f3a6 +Version: 1.6.0.175.4344 Release: 0 Summary: Osmocom BTS-Side code (Abis, scheduling) License: AGPL-3.0-or-later AND GPL-2.0-only Group: Productivity/Telephony/Servers URL: https://osmocom.org/projects/osmobts -Source: osmo-bts_1.6.0.168.f3a6.tar.xz +Source: osmo-bts_1.6.0.175.4344.tar.xz Source1: rpmlintrc BuildRequires: autoconf BuildRequires: automake
View file
commit_4344f323f23517e53c32deae75b3bb5e15b31ad4.txt
Added
View file
commit_f3a63758d1c41ded71d4911e1e927d0f95f099d8.txt
Deleted
View file
osmo-bts_1.6.0.168.f3a6.dsc -> osmo-bts_1.6.0.175.4344.dsc
Changed
@@ -2,7 +2,7 @@ Source: osmo-bts Binary: osmo-bts, osmo-bts-trx, osmo-bts-trx-dbg, osmo-bts-virtual, osmo-bts-virtual-dbg, osmo-bts-doc Architecture: any all -Version: 1.6.0.168.f3a6 +Version: 1.6.0.175.4344 Maintainer: Osmocom team <openbsc@lists.osmocom.org> Homepage: https://projects.osmocom.org/projects/osmobts Standards-Version: 3.9.8 @@ -17,8 +17,8 @@ osmo-bts-virtual deb net optional arch=any osmo-bts-virtual-dbg deb debug extra arch=any Checksums-Sha1: - b2b1e3418892aba418d85bc3e61def765e63be46 476496 osmo-bts_1.6.0.168.f3a6.tar.xz + c26593a5481011b13dc554f7e0946db923a92487 478772 osmo-bts_1.6.0.175.4344.tar.xz Checksums-Sha256: - 8e718b7130c6594445da9d4c05775049505baa9d352dedff406b38420e7ba026 476496 osmo-bts_1.6.0.168.f3a6.tar.xz + a7462330c01fd4205aa04512dc3dae34d83fb431365ce59293586144780d1b32 478772 osmo-bts_1.6.0.175.4344.tar.xz Files: - 700919e67d4f286bc72ea19530adae71 476496 osmo-bts_1.6.0.168.f3a6.tar.xz + 39ef231b2377193009a391778cdc8d3e 478772 osmo-bts_1.6.0.175.4344.tar.xz
View file
osmo-bts_1.6.0.168.f3a6.tar.xz/.tarball-version -> osmo-bts_1.6.0.175.4344.tar.xz/.tarball-version
Changed
@@ -1 +1 @@ -1.6.0.168-f3a6 +1.6.0.175-4344
View file
osmo-bts_1.6.0.168.f3a6.tar.xz/debian/changelog -> osmo-bts_1.6.0.175.4344.tar.xz/debian/changelog
Changed
@@ -1,8 +1,8 @@ -osmo-bts (1.6.0.168.f3a6) unstable; urgency=medium +osmo-bts (1.6.0.175.4344) unstable; urgency=medium * Automatically generated changelog entry for building the Osmocom master feed - -- Osmocom OBS scripts <info@osmocom.org> Wed, 12 Jul 2023 22:20:11 +0000 + -- Osmocom OBS scripts <info@osmocom.org> Thu, 13 Jul 2023 13:24:53 +0000 osmo-bts (1.6.0) unstable; urgency=medium
View file
osmo-bts_1.6.0.175.4344.tar.xz/doc/trx_sched_tch.txt
Added
@@ -0,0 +1,98 @@ +== rx_tchf_fn(): TCH/FS, TCH/EFS, TCH/AFS, TCH/F2.4, and FACCH/F + + 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 ++---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---|---+---+---+---+---+---+---+---+ << 4 +| | | | | | | | | | | | | | | | | | | | | a | b | c | d | Rx bid={0,1,2,3}, decode ++---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---|---+---+---+---+---+---+---+---+ << 4 +| | | | | | | | | | | | | | | | | a | b | c | d | e | f | g | h | Rx bid={0,1,2,3}, decode ++---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---|---+---+---+---+---+---+---+---+ << 4 + | + |<~~~~~~~~~~~~~~~~~~~~~~~~~~~~~>| frame A + | |<~~~~~~~~~~~~~~~~~~~~~~~~~~~~~>| frame B + @ decoding from here + + +== rx_tchf_fn(): TCH/F14.4, TCH/F9.6, TCH/F4.8 + + 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 +|---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ << 4 +| | | | | | | | | | | | | | | | | | | | | a | b | c | d | Rx bid={0,1,2,3}, decode +|---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ << 4 +| | | | | | | | | | | | | | | | | a | b | c | d | e | f | g | h | Rx bid={0,1,2,3}, decode +|---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ << 4 +| | | | | | | | | | | | | a | b | c | d | e | f | g | h | i | j | k | l | Rx bid={0,1,2,3}, decode +|---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ << 4 +| | | | | | | | | a | b | c | d | e | f | g | h | i | j | k | l | m | n | o | p | Rx bid={0,1,2,3}, decode +|---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ << 4 +| | | | | a | b | c | d | e | f | g | h | i | j | k | l | m | n | o | p | q | r | s | t | Rx bid={0,1,2,3}, decode +|---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ << 4 +| a | b | c | d | e | f | g | h | i | j | k | l | m | n | o | p | q | r | s | t | u | v | w | x | Rx bid={0,1,2,3}, decode +|---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ << 4 +| +|<~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~>| frame A +| |<~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~>| frame B +@ decoding from here + + +== rx_tchh_fn(): TCH/HS, TCH/AHS + + 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 ++---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---|---+---+---+---+---+---+---+---+ << 2 +| | | | | | | | | | | | | | | | | | | | | a | b | | | Rx bid={0,1}, decode ++---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---|---+---+---+---+---+---+---+---+ << 2 +| | | | | | | | | | | | | | | | | | | a | b | c | d | | | Rx bid={0,1}, decode ++---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---|---+---+---+---+---+---+---+---+ << 2 +| | | | | | | | | | | | | | | | | a | b | c | d | e | f | | | Rx bid={0,1}, decode ++---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---|---+---+---+---+---+---+---+---+ << 2 + | + |<~~~~~~~~~~~~~>| frame A + | |<~~~~~~~~~~~~~>| frame B + @ decoding from here + + +== rx_tchh_fn(): FACCH/H + + 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 ++---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---|---+---+---+---+---+---+---+---+ << 2 +| | | | | | | | | | | | | | | | | | | | | a | b | | | Rx bid={0,1}, decode ++---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---|---+---+---+---+---+---+---+---+ << 2 +| | | | | | | | | | | | | | | | | | | a | b | c | d | | | Rx bid={0,1} ++---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---|---+---+---+---+---+---+---+---+ << 2 +| | | | | | | | | | | | | | | | | a | b | c | d | e | f | | | Rx bid={0,1}, decode ++---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---|---+---+---+---+---+---+---+---+ << 2 + | + |<~~~~~~~~~~~~~~~~~~~~~>| frame A + | |<~~~~~~~~~~~~~~~~~~~~~>| frame B + @ decoding from here + + +== rx_tchh_fn(): TCH/H4.8, TCH/H2.4 + + 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 +|---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ << 2 +| | | | | | | | | | | | | | | | | | | | | a | b | | | Rx bid={0,1}, decode +|---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ << 2 +| | | | | | | | | | | | | | | | | | | a | b | c | d | | | Rx bid={0,1} +|---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ << 2 +| | | | | | | | | | | | | | | | | a | b | c | d | e | f | | | Rx bid={0,1}, decode +|---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ << 2 +| | | | | | | | | | | | | | | a | b | c | d | e | f | g | h | | | Rx bid={0,1} +|---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ << 2 +| | | | | | | | | | | | | a | b | c | d | e | f | g | h | i | j | | | Rx bid={0,1}, decode +|---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ << 2 +| | | | | | | | | | | a | b | c | d | e | f | g | h | i | j | k | l | | | Rx bid={0,1} +|---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ << 2 +| | | | | | | | | a | b | c | d | e | f | g | h | i | j | k | l | m | n | | | Rx bid={0,1}, decode +|---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ << 2 +| | | | | | | a | b | c | d | e | f | g | h | i | j | k | l | m | n | o | p | | | Rx bid={0,1} +|---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ << 2 +| | | | | a | b | c | d | e | f | g | h | i | j | k | l | m | n | o | p | q | r | | | Rx bid={0,1}, decode +|---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ << 2 +| | | a | b | c | d | e | f | g | h | i | j | k | l | m | n | o | p | q | r | s | t | | | Rx bid={0,1} +|---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ << 2 +| a | b | c | d | e | f | g | h | i | j | k | l | m | n | o | p | q | r | s | t | u | v | | | Rx bid={0,1}, decode +|---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ << 2 +| +|<~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~>| frame A +| |<~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~>| frame B +@ decoding from here
View file
osmo-bts_1.6.0.168.f3a6.tar.xz/include/osmo-bts/scheduler.h -> osmo-bts_1.6.0.175.4344.tar.xz/include/osmo-bts/scheduler.h
Changed
@@ -94,7 +94,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 */ @@ -132,7 +132,7 @@ /* Uplink measurements */ struct { /* Active channel measurements (simple ring buffer) */ - struct l1sched_meas_set buf8; /* up to 8 entries */ + struct l1sched_meas_set buf24; /* up to 24 entries */ unsigned int current; /* current position */ /* Interference measurements */ @@ -301,6 +301,10 @@ /* Averaging mode for trx_sched_meas_avg() */ enum sched_meas_avg_mode { + /* first 22 of last 24 bursts (for TCH/F14.4, TCH/F9.6, TCH/F4.8) */ + SCHED_MEAS_AVG_M_S24N22, + /* last 22 bursts (for TCH/H4.8, TCH/H2.4) */ + 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) */
View file
osmo-bts_1.6.0.168.f3a6.tar.xz/src/common/bts.c -> osmo-bts_1.6.0.175.4344.tar.xz/src/common/bts.c
Changed
@@ -780,23 +780,11 @@ return &bts->gsm_time; } -bool bts_supports_cm(const struct gsm_bts *bts, - const struct rsl_ie_chan_mode *cm) +bool 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 true; - case RSL_CMOD_SPD_SPEECH: - break; - case RSL_CMOD_SPD_DATA: - default: - return false; - } - /* Stage 1: check support for the requested channel type */ switch (cm->chan_rt) { case RSL_CMOD_CRT_TCH_GROUP_Bm: @@ -869,6 +857,48 @@ return false; } +static bool bts_supports_cm_data(const struct gsm_bts *bts, + const struct rsl_ie_chan_mode *cm) +{ + switch (bts->variant) { + case BTS_OSMO_TRX: + switch (cm->chan_rate) { + case RSL_CMOD_CSD_T_14k4: + case RSL_CMOD_CSD_T_9k6: + if (cm->chan_rt != RSL_CMOD_CRT_TCH_Bm) + return false; /* invalid */ + /* fall-through */ + case RSL_CMOD_CSD_T_4k8: + case RSL_CMOD_CSD_T_2k4: + case RSL_CMOD_CSD_T_1k2: + case RSL_CMOD_CSD_T_600: + case RSL_CMOD_CSD_T_1200_75: + return true; + default: + return false; + } + default: + return 0; + } +} + +bool 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 true; + 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 false; + } +} + /* return the gsm_lchan for the CBCH (if it exists at all) */ struct gsm_lchan *gsm_bts_get_cbch(struct gsm_bts *bts) {
View file
osmo-bts_1.6.0.168.f3a6.tar.xz/src/common/scheduler.c -> osmo-bts_1.6.0.175.4344.tar.xz/src/common/scheduler.c
Changed
@@ -1079,9 +1079,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 24 * (2 * 58) bytes, which is sufficient to store up to 24 GMSK + * modulated bursts for CSD or up to 8 8PSK modulated bursts for EGPRS. */ + const size_t buf_size = 24 * GSM_NBITS_NB_GMSK_PAYLOAD; if (trx_chan_descchan.dl_fn != NULL) chan_state->dl_bursts = talloc_zero_size(l1ts, buf_size); if (trx_chan_descchan.ul_fn != NULL) {
View file
osmo-bts_1.6.0.168.f3a6.tar.xz/src/osmo-bts-trx/sched_lchan_pdtch.c -> osmo-bts_1.6.0.175.4344.tar.xz/src/osmo-bts-trx/sched_lchan_pdtch.c
Changed
@@ -44,7 +44,7 @@ struct l1sched_chan_state *chan_state = &l1ts->chan_statebi->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 l2EGPRS_0503_MAX_BYTES; int n_errors = 0; @@ -122,8 +122,8 @@ if (rc > 0) { presence_info = PRES_INFO_BOTH; } else { - LOGL1SB(DL1P, LOGL_DEBUG, l1ts, bi, "Received bad PDTCH (%u/%u)\n", - bi->fn % l1ts->mf_period, l1ts->mf_period); + LOGL1SB(DL1P, LOGL_NOTICE, l1ts, bi, + BAD_DATA_MSG_FMT "\n", BAD_DATA_MSG_ARGS); rc = 0; presence_info = PRES_INFO_INVALID; }
View file
osmo-bts_1.6.0.168.f3a6.tar.xz/src/osmo-bts-trx/sched_lchan_tchf.c -> osmo-bts_1.6.0.175.4344.tar.xz/src/osmo-bts-trx/sched_lchan_tchf.c
Changed
@@ -1,7 +1,7 @@ /* * (C) 2013 by Andreas Eversberg <jolly@eversberg.eu> * (C) 2015-2017 by Harald Welte <laforge@gnumonks.org> - * Contributions by sysmocom - s.f.m.c. GmbH + * (C) 2020-2023 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> * * All Rights Reserved * @@ -69,22 +69,50 @@ extern const uint8_t sched_tchh_dl_amr_cmi_map26; -/*! \brief a single TCH/F burst was received by the PHY, process it */ +static int decode_fr_facch(struct l1sched_ts *l1ts, + const struct trx_ul_burst_ind *bi) +{ + struct l1sched_chan_state *chan_state = &l1ts->chan_statebi->chan; + const sbit_t *bursts_p = chan_state->ul_bursts; + struct l1sched_meas_set meas_avg; + uint8_t dataGSM_MACBLOCK_LEN; + int n_errors, n_bits_total; + int rc; + + rc = gsm0503_tch_fr_facch_decode(&data0, BUFTAIL8(bursts_p), + &n_errors, &n_bits_total); + if (rc != GSM_MACBLOCK_LEN) + return rc; + + /* average measurements of the last 8 bursts, obtain TDMA Fn of the first burst */ + trx_sched_meas_avg(chan_state, &meas_avg, SCHED_MEAS_AVG_M_S8N8); + + _sched_compose_ph_data_ind(l1ts, meas_avg.fn, bi->chan, + &data0, GSM_MACBLOCK_LEN, + compute_ber10k(n_bits_total, n_errors), + meas_avg.rssi, + meas_avg.toa256, + meas_avg.ci_cb, + PRES_INFO_UNKNOWN); + return GSM_MACBLOCK_LEN; +} + +/* Process a single Uplink TCH/F burst received by the PHY. + * This function is visualized in file 'doc/trx_sched_tch.txt'. */ int rx_tchf_fn(struct l1sched_ts *l1ts, const struct trx_ul_burst_ind *bi) { struct l1sched_chan_state *chan_state = &l1ts->chan_statebi->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_data128; /* just to be safe */ + uint8_t tch_data290; /* large enough to hold 290 unpacked bits for CSD */ enum sched_meas_avg_mode meas_avg_mode = SCHED_MEAS_AVG_M_S8N8; struct l1sched_meas_set meas_avg; int rc, amr = 0; int n_errors = 0; int n_bits_total = 0; - bool bfi_flag = false; unsigned int fn_begin; uint16_t ber10k; uint8_t is_sub = 0; @@ -100,8 +128,8 @@ /* shift the buffer by 4 bursts leftwards */ if (bi->bid == 0) { - memcpy(bursts_p, bursts_p + 464, 464); - memset(bursts_p + 464, 0, 464); + memmove(BUFPOS(bursts_p, 0), BUFPOS(bursts_p, 4), 20 * BPLEN); + memset(BUFPOS(bursts_p, 20), 0, 4 * BPLEN); *mask = *mask << 4; } @@ -111,8 +139,8 @@ /* 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 24 bursts */ + burst = BUFPOS(bursts_p, 20 + bi->bid); if (bi->burst_len > 0) { memcpy(burst, bi->burst + 3, 58); memcpy(burst + 58, bi->burst + 87, 58); @@ -130,17 +158,20 @@ 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. */ switch (tch_mode) { case GSM48_CMODE_SIGN: case GSM48_CMODE_SPEECH_V1: /* FR */ - rc = gsm0503_tch_fr_decode(tch_data, bursts_p, 1, 0, &n_errors, &n_bits_total); + rc = gsm0503_tch_fr_decode(tch_data, BUFTAIL8(bursts_p), + 1, 0, &n_errors, &n_bits_total); if (rc == GSM_FR_BYTES) /* only for valid *speech* frames */ lchan_set_marker(osmo_fr_is_any_sid(tch_data), lchan); /* DTXu */ break; case GSM48_CMODE_SPEECH_EFR: /* EFR */ - rc = gsm0503_tch_fr_decode(tch_data, bursts_p, 1, 1, &n_errors, &n_bits_total); + rc = gsm0503_tch_fr_decode(tch_data, BUFTAIL8(bursts_p), + 1, 1, &n_errors, &n_bits_total); if (rc == GSM_EFR_BYTES) /* only for valid *speech* frames */ lchan_set_marker(osmo_efr_is_any_sid(tch_data), lchan); /* DTXu */ break; @@ -166,7 +197,7 @@ * we receive an FACCH frame instead of a voice frame (we * do not know this before we actually decode the frame) */ amr = sizeof(struct amr_hdr); - rc = gsm0503_tch_afs_decode_dtx(tch_data + amr, bursts_p, + rc = gsm0503_tch_afs_decode_dtx(tch_data + amr, BUFTAIL8(bursts_p), amr_is_cmr, chan_state->codec, chan_state->codecs, &chan_state->ul_ft, &chan_state->ul_cmr, &n_errors, &n_bits_total, &chan_state->amr_last_dtx); @@ -219,6 +250,40 @@ } break; + /* CSD (TCH/F9.6): 12.0 kbit/s radio interface rate */ + case GSM48_CMODE_DATA_12k0: + /* FACCH/F does not steal TCH/F9.6 frames, but only disturbs some bits */ + decode_fr_facch(l1ts, bi); + rc = gsm0503_tch_fr96_decode(&tch_data0, BUFPOS(bursts_p, 0), + &n_errors, &n_bits_total); + meas_avg_mode = SCHED_MEAS_AVG_M_S24N22; + break; + /* CSD (TCH/F4.8): 6.0 kbit/s radio interface rate */ + case GSM48_CMODE_DATA_6k0: + /* FACCH/F does not steal TCH/F4.8 frames, but only disturbs some bits */ + decode_fr_facch(l1ts, bi); + rc = gsm0503_tch_fr48_decode(&tch_data0, BUFPOS(bursts_p, 0), + &n_errors, &n_bits_total); + meas_avg_mode = SCHED_MEAS_AVG_M_S24N22; + break; + /* CSD (TCH/F2.4): 3.6 kbit/s radio interface rate */ + case GSM48_CMODE_DATA_3k6: + /* TCH/F2.4 employs the same interleaving as TCH/FS (8 bursts), + * so FACCH/F *does* steal TCH/F2.4 frames completely. */ + if (decode_fr_facch(l1ts, bi) == GSM_MACBLOCK_LEN) + return 0; /* TODO: emit BFI */ + rc = gsm0503_tch_fr24_decode(&tch_data0, BUFTAIL8(bursts_p), + &n_errors, &n_bits_total); + meas_avg_mode = SCHED_MEAS_AVG_M_S8N8; + break; + /* CSD (TCH/F14.4): 14.5 kbit/s radio interface rate */ + case GSM48_CMODE_DATA_14k5: + /* FACCH/F does not steal TCH/F14.4 frames, but only disturbs some bits */ + decode_fr_facch(l1ts, bi); + rc = gsm0503_tch_fr144_decode(&tch_data0, BUFPOS(bursts_p, 0), + &n_errors, &n_bits_total); + meas_avg_mode = SCHED_MEAS_AVG_M_S24N22; + break; default: LOGL1SB(DL1P, LOGL_ERROR, l1ts, bi, "TCH mode %u invalid, please fix!\n", @@ -226,6 +291,8 @@ return -EINVAL; } + ber10k = compute_ber10k(n_bits_total, n_errors); + /* average measurements of the last N (depends on mode) bursts */ trx_sched_meas_avg(chan_state, &meas_avg, meas_avg_mode); /* meas_avg.fn now contains TDMA frame number of the first burst */ @@ -235,23 +302,11 @@ trx_loop_amr_input(chan_state, &meas_avg); /* Check if the frame is bad */ - if (rc < 0) { - LOGL1SB(DL1P, LOGL_NOTICE, l1ts, bi, "Received bad data (%u/%u)\n", - bi->fn % l1ts->mf_period, l1ts->mf_period); - bfi_flag = true; - } else if (rc < 4) { + if (rc < 4) { LOGL1SB(DL1P, LOGL_NOTICE, l1ts, bi, - "Received bad data (%u/%u) with invalid codec mode %d\n", - bi->fn % l1ts->mf_period, l1ts->mf_period, rc); - bfi_flag = true; - } - - ber10k = compute_ber10k(n_bits_total, n_errors); - if (bfi_flag) + BAD_DATA_MSG_FMT "\n", BAD_DATA_MSG_ARGS); rc = 0; /* this is how we signal BFI to l1sap */ - - /* FACCH */ - if (rc == GSM_MACBLOCK_LEN) { + } else if (rc == GSM_MACBLOCK_LEN) { /* FACCH/F */ _sched_compose_ph_data_ind(l1ts, fn_begin, bi->chan, &tch_dataamr, GSM_MACBLOCK_LEN, ber10k, @@ -271,7 +326,7 @@ rc = 0; } - if (rsl_cmode != RSL_CMOD_SPD_SPEECH) + if (rsl_cmode == RSL_CMOD_SPD_SIGN) return 0; /* TCH or BFI */ @@ -286,9 +341,10 @@ /* common section for generation of TCH bursts (TCH/H and TCH/F). * FIXME: this function is over-complicated, refactor / get rid of it. */ -struct msgb *tch_dl_dequeue(struct l1sched_ts *l1ts, struct trx_dl_burst_req *br) +void tch_dl_dequeue(struct l1sched_ts *l1ts, struct trx_dl_burst_req *br, + struct msgb **msg_tch, struct msgb **msg_facch) { - struct msgb *msg1, *msg2, *msg_tch = NULL, *msg_facch = NULL; + struct msgb *msg1, *msg2; struct l1sched_chan_state *chan_state = &l1ts->chan_statebr->chan; uint8_t rsl_cmode = chan_state->rsl_cmode; uint8_t tch_mode = chan_state->tch_mode; @@ -300,50 +356,39 @@ if (msg1) { l1sap = msgb_l1sap_prim(msg1); if (l1sap->oph.primitive == PRIM_TCH) { - msg_tch = msg1; + *msg_tch = msg1; if (msg2) { l1sap = msgb_l1sap_prim(msg2); if (l1sap->oph.primitive == PRIM_TCH) { LOGL1SB(DL1P, LOGL_FATAL, l1ts, br, "TCH twice, please FIX!\n"); msgb_free(msg2); } else - msg_facch = msg2; + *msg_facch = msg2; } } else { - msg_facch = msg1; + *msg_facch = msg1; if (msg2) { l1sap = msgb_l1sap_prim(msg2); if (l1sap->oph.primitive != PRIM_TCH) { LOGL1SB(DL1P, LOGL_FATAL, l1ts, br, "FACCH twice, please FIX!\n"); msgb_free(msg2); } else - msg_tch = msg2; + *msg_tch = msg2; } } } /* check validity of message */ - if (msg_facch && msgb_l2len(msg_facch) != GSM_MACBLOCK_LEN) { + if (*msg_facch != NULL && msgb_l2len(*msg_facch) != GSM_MACBLOCK_LEN) { LOGL1SB(DL1P, LOGL_FATAL, l1ts, br, "Prim has odd len=%u != %u\n", - msgb_l2len(msg_facch), GSM_MACBLOCK_LEN); + msgb_l2len(*msg_facch), GSM_MACBLOCK_LEN); /* free message */ - msgb_free(msg_facch); - msg_facch = NULL; - } - - /* prioritize FACCH over speech */ - if (msg_facch) { - /* Unlike SACCH, FACCH has no dedicated slots on the multiframe layout. - * It's multiplexed together with TCH (speech or data) frames basically - * by replacing (stealing) them. This is common for both TCH/F and - * TCH/H, with the only difference that FACCH/H steals two TCH frames - * (not just one) due to a longer interleaving period. */ - msgb_free(msg_tch); - return msg_facch; + msgb_free(*msg_facch); + *msg_facch = NULL; } /* check validity of message, get AMR ft and cmr */ - if (msg_tch) { + if (*msg_tch != NULL) { int len; uint8_t cmr_codec; int ft, i; @@ -371,7 +416,7 @@ len = GSM_EFR_BYTES; break; case GSM48_CMODE_SPEECH_AMR: /* AMR */ - len = osmo_amr_rtp_dec(msg_tch->l2h, msgb_l2len(msg_tch), + len = osmo_amr_rtp_dec(msgb_l2((*msg_tch)), msgb_l2len(*msg_tch), &cmr_codec, &cmi, &ft_codec, &bfi, &sti); if (len < 0) { @@ -403,26 +448,46 @@ goto free_bad_msg; } /* pull the AMR header, it's not being sent over Um */ - msg_tch->l2h += sizeof(struct amr_hdr); + (*msg_tch)->l2h += sizeof(struct amr_hdr); len -= sizeof(struct amr_hdr); break; + case GSM48_CMODE_DATA_14k5: /* TCH/F14.4 */ + if (OSMO_UNLIKELY(br->chan != TRXC_TCHF)) + goto inval_mode2; + len = 290; + break; + case GSM48_CMODE_DATA_12k0: /* TCH/F9.6 */ + if (OSMO_UNLIKELY(br->chan != TRXC_TCHF)) + goto inval_mode2; + len = 4 * 60; + break; + case GSM48_CMODE_DATA_6k0: /* TCH/FH4.8 */ + if (br->chan == TRXC_TCHF) + len = 2 * 60; + else + len = 4 * 60; + break; + case GSM48_CMODE_DATA_3k6: /* TCH/FH2.4 */ + if (br->chan == TRXC_TCHF) + len = 2 * 36; + else + len = 4 * 36; + break; default: inval_mode2: LOGL1SB(DL1P, LOGL_ERROR, l1ts, br, "TCH mode invalid, please fix!\n"); goto free_bad_msg; } - if (msgb_l2len(msg_tch) != len) { + if (msgb_l2len(*msg_tch) != len) { LOGL1SB(DL1P, LOGL_ERROR, l1ts, br, "Cannot send payload with " "invalid length! (expecting %d, received %d)\n", - len, msgb_l2len(msg_tch)); + len, msgb_l2len(*msg_tch)); free_bad_msg: /* free message */ - msgb_free(msg_tch); - msg_tch = NULL; + msgb_free(*msg_tch); + *msg_tch = NULL; } } - - return msg_tch; } /* obtain a to-be-transmitted TCH/F (Full Traffic Channel) burst */ @@ -432,7 +497,9 @@ uint8_t tch_mode = chan_state->tch_mode; ubit_t *burst, *bursts_p = chan_state->dl_bursts; uint8_t *mask = &chan_state->dl_mask; - struct msgb *msg; + struct msgb *msg_facch = NULL; + struct msgb *msg_tch = NULL; + struct msgb *msg = NULL; /* send burst, if we already got a frame */ if (br->bid > 0) { @@ -446,14 +513,12 @@ /* BURST BYPASS */ /* shift buffer by 4 bursts for interleaving */ - memcpy(bursts_p, bursts_p + 464, 464); - memset(bursts_p + 464, 0, 464); - - /* dequeue a message to be transmitted */ - msg = tch_dl_dequeue(l1ts, br); + memmove(BUFPOS(bursts_p, 0), BUFPOS(bursts_p, 4), 20 * BPLEN); + memset(BUFPOS(bursts_p, 20), 0, 4 * BPLEN); - /* no message at all, send a dummy L2 frame on FACCH */ - if (msg == NULL) { + /* dequeue a TCH and/or a FACCH message to be transmitted */ + tch_dl_dequeue(l1ts, br, &msg_tch, &msg_facch); + if (msg_tch == NULL && msg_facch == NULL) { static const uint8_t dummyGSM_MACBLOCK_LEN = { 0x03, 0x03, 0x01, /* TODO: use randomized padding */ 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, @@ -485,31 +550,69 @@ 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); + /* Unlike SACCH, FACCH has no dedicated slots on the multiframe layout. + * It's multiplexed together with TCH (speech or data) frames basically + * by replacing (stealing) their bits, either completely or partly. */ + msg = (msg_facch != NULL) ? msg_facch : msg_tch; + if (msg == msg_facch) 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(BUFPOS(bursts_p, 0), 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. */ - gsm0503_tch_afs_encode(bursts_p, + gsm0503_tch_afs_encode(BUFPOS(bursts_p, 0), msgb_l2(msg), msgb_l2len(msg), !sched_tchf_dl_amr_cmi_mapbr->fn % 26, 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; + /* CSD (TCH/F9.6): 12.0 kbit/s radio interface rate */ + case GSM48_CMODE_DATA_12k0: + gsm0503_tch_fr96_encode(BUFPOS(bursts_p, 0), msgb_l2(msg_tch)); + if (msg_facch != NULL) + gsm0503_tch_fr_facch_encode(BUFPOS(bursts_p, 0), msgb_l2(msg_facch)); + break; + /* CSD (TCH/F4.8): 6.0 kbit/s radio interface rate */ + case GSM48_CMODE_DATA_6k0: + gsm0503_tch_fr48_encode(BUFPOS(bursts_p, 0), msgb_l2(msg_tch)); + if (msg_facch != NULL) + gsm0503_tch_fr_facch_encode(BUFPOS(bursts_p, 0), msgb_l2(msg_facch)); + break; + /* CSD (TCH/F2.4): 3.6 kbit/s radio interface rate */ + case GSM48_CMODE_DATA_3k6: + /* FACCH/F does steal a TCH/F2.4 frame completely */ + if (msg == msg_facch) + gsm0503_tch_fr_facch_encode(BUFPOS(bursts_p, 0), msgb_l2(msg_facch)); + else + gsm0503_tch_fr24_encode(BUFPOS(bursts_p, 0), msgb_l2(msg_tch)); + break; + /* CSD (TCH/F14.4): 14.5 kbit/s radio interface rate */ + case GSM48_CMODE_DATA_14k5: + gsm0503_tch_fr144_encode(BUFPOS(bursts_p, 0), msgb_l2(msg_tch)); + if (msg_facch != NULL) + gsm0503_tch_fr_facch_encode(BUFPOS(bursts_p, 0), msgb_l2(msg_facch)); + break; + default: + OSMO_ASSERT(0); } - /* free message */ - msgb_free(msg); + /* free messages */ + msgb_free(msg_tch); + msgb_free(msg_facch); send_burst: /* compose burst */ - burst = bursts_p + br->bid * 116; + burst = BUFPOS(bursts_p, br->bid); memcpy(br->burst + 3, burst, 58); memcpy(br->burst + 61, TRX_GMSK_NB_TSC(br), 26); memcpy(br->burst + 87, burst + 58, 58);
View file
osmo-bts_1.6.0.168.f3a6.tar.xz/src/osmo-bts-trx/sched_lchan_tchh.c -> osmo-bts_1.6.0.175.4344.tar.xz/src/osmo-bts-trx/sched_lchan_tchh.c
Changed
@@ -1,7 +1,7 @@ /* * (C) 2013 by Andreas Eversberg <jolly@eversberg.eu> * (C) 2015-2017 by Harald Welte <laforge@gnumonks.org> - * Contributions by sysmocom - s.f.m.c. GmbH + * (C) 2020-2023 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> * * All Rights Reserved * @@ -91,21 +91,84 @@ /* TDMA frame number of burst 'a' is used as the table index. */ extern const uint8_t sched_tchh_dl_facch_map26; -/*! \brief a single TCH/H burst was received by the PHY, process it */ +/* 3GPP TS 45.002, table 2 in clause 7: Mapping tables for TCH/H2.4 and TCH/H4.8. + * + * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + * | a | b | c | d | e | f | g | h | i | j | k | l | m | n | o | p | q | r | s | t | u | v | + * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + * + * TCH/H(0): B0(0,2,4,6,8,10,13,15,17,19,21,23,0,2,4,6,8,10,13,15,17,19) + * TCH/H(1): B0(1,3,5,7,9,11,14,16,18,20,22,24,1,3,5,7,9,11,14,16,18,20) + * TCH/H(0): B1(8,10,13,15,17,19,21,23,0,2,4,6,8,10,13,15,17,19,21,23,0,2) + * TCH/H(1): B1(9,11,14,16,18,20,22,24,1,3,5,7,9,11,14,16,18,20,22,24,1,3) + * TCH/H(0): B2(17,19,21,23,0,2,4,6,8,10,13,15,17,19,21,23,0,2,4,6,8,10) + * TCH/H(1): B2(18,20,22,24,1,3,5,7,9,11,14,16,18,20,22,24,1,3,5,7,9,11) + * + * TDMA frame number of burst 'v' % 26 is the table index. + * This mapping is valid for both TCH/H(0) and TCH/H(1). */ +static const uint8_t sched_tchh_ul_csd_map26 = { + 19 = 1, /* TCH/H(0): B0(0 ... 19) */ + 20 = 1, /* TCH/H(1): B0(1 ... 20) */ + 2 = 1, /* TCH/H(0): B1(8 ... 2) */ + 3 = 1, /* TCH/H(1): B1(9 ... 3) */ + 10 = 1, /* TCH/H(0): B2(17 ... 10) */ + 11 = 1, /* TCH/H(1): B2(18 ... 11) */ +}; + +/* TDMA frame number of burst 'a' % 26 is the table index. + * This mapping is valid for both TCH/H(0) and TCH/H(1). */ +static const uint8_t sched_tchh_dl_csd_map26 = { + 0 = 1, /* TCH/H(0): B0(0 ... 19) */ + 1 = 1, /* TCH/H(1): B0(1 ... 20) */ + 8 = 1, /* TCH/H(0): B1(8 ... 2) */ + 9 = 1, /* TCH/H(1): B1(9 ... 3) */ + 17 = 1, /* TCH/H(0): B2(17 ... 10) */ + 18 = 1, /* TCH/H(1): B2(18 ... 11) */ +}; + +static int decode_hr_facch(struct l1sched_ts *l1ts, + const struct trx_ul_burst_ind *bi) +{ + struct l1sched_chan_state *chan_state = &l1ts->chan_statebi->chan; + const sbit_t *bursts_p = chan_state->ul_bursts; + struct l1sched_meas_set meas_avg; + uint8_t dataGSM_MACBLOCK_LEN; + int n_errors, n_bits_total; + int rc; + + rc = gsm0503_tch_hr_facch_decode(&data0, BUFTAIL8(bursts_p), + &n_errors, &n_bits_total); + if (rc != GSM_MACBLOCK_LEN) + return rc; + + /* average measurements of the last 6 bursts, obtain TDMA Fn of the first burst */ + trx_sched_meas_avg(chan_state, &meas_avg, SCHED_MEAS_AVG_M_S6N6); + + _sched_compose_ph_data_ind(l1ts, meas_avg.fn, bi->chan, + &data0, GSM_MACBLOCK_LEN, + compute_ber10k(n_bits_total, n_errors), + meas_avg.rssi, + meas_avg.toa256, + meas_avg.ci_cb, + PRES_INFO_UNKNOWN); + return GSM_MACBLOCK_LEN; +} + +/* Process a single Uplink TCH/H burst received by the PHY. + * This function is visualized in file 'doc/trx_sched_tch.txt'. */ int rx_tchh_fn(struct l1sched_ts *l1ts, const struct trx_ul_burst_ind *bi) { struct l1sched_chan_state *chan_state = &l1ts->chan_statebi->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_data128; /* just to be safe */ + uint8_t tch_data240; /* large enough to hold 240 unpacked bits for CSD */ int rc = 0; /* initialize to make gcc happy */ int amr = 0; int n_errors = 0; int n_bits_total = 0; - bool bfi_flag = false; enum sched_meas_avg_mode meas_avg_mode = SCHED_MEAS_AVG_M_S6N4; struct l1sched_meas_set meas_avg; unsigned int fn_begin; @@ -123,9 +186,8 @@ /* shift the buffer by 2 bursts leftwards */ if (bi->bid == 0) { - memcpy(bursts_p, bursts_p + 232, 232); - memcpy(bursts_p + 232, bursts_p + 464, 232); - memset(bursts_p + 464, 0, 232); + memmove(BUFPOS(bursts_p, 0), BUFPOS(bursts_p, 2), 20 * BPLEN); + memset(BUFPOS(bursts_p, 20), 0, 2 * BPLEN); *mask = *mask << 2; } @@ -135,8 +197,8 @@ /* store measurements */ trx_sched_meas_push(chan_state, bi); - /* copy burst to end of buffer of 6 bursts */ - burst = bursts_p + bi->bid * 116 + 464; + /* copy burst to end of buffer of 24 bursts */ + burst = BUFPOS(bursts_p, 20 + bi->bid); if (bi->burst_len > 0) { memcpy(burst, bi->burst + 3, 58); memcpy(burst + 58, bi->burst + 87, 58); @@ -165,14 +227,16 @@ goto bfi; } - /* decode - * also shift buffer by 4 bursts for interleaving */ + /* TCH/H: speech and signalling frames are interleaved over 4 and 6 bursts, + * respectively, while CSD frames are interleaved over 22 bursts. Unless + * we're in CSD mode, decode only the last 6 bursts to avoid introducing + * additional delays. */ switch (tch_mode) { case GSM48_CMODE_SIGN: meas_avg_mode = SCHED_MEAS_AVG_M_S6N6; /* fall-through */ case GSM48_CMODE_SPEECH_V1: /* HR or signalling */ - rc = gsm0503_tch_hr_decode2(tch_data, bursts_p, + rc = gsm0503_tch_hr_decode2(tch_data, BUFTAIL8(bursts_p), !sched_tchh_ul_facch_mapbi->fn % 26, &n_errors, &n_bits_total); if (rc == GSM_HR_BYTES) { /* only for valid *speech* frames */ @@ -199,7 +263,7 @@ /* See comment in function rx_tchf_fn() */ amr = sizeof(struct amr_hdr); - rc = gsm0503_tch_ahs_decode_dtx(tch_data + amr, bursts_p, + rc = gsm0503_tch_ahs_decode_dtx(tch_data + amr, BUFTAIL8(bursts_p), !sched_tchh_ul_facch_mapbi->fn % 26, !fn_is_cmi, chan_state->codec, chan_state->codecs, &chan_state->ul_ft, @@ -255,6 +319,26 @@ } break; + /* CSD (TCH/H4.8): 6.0 kbit/s radio interface rate */ + case GSM48_CMODE_DATA_6k0: + if (!sched_tchh_ul_csd_mapbi->fn % 26) + return 0; /* CSD: skip decoding attempt, need 2 more bursts */ + /* FACCH/F does not steal TCH/H4.8 frames, but only disturbs some bits */ + decode_hr_facch(l1ts, bi); + rc = gsm0503_tch_hr48_decode(&tch_data0, BUFPOS(bursts_p, 0), + &n_errors, &n_bits_total); + meas_avg_mode = SCHED_MEAS_AVG_M_S22N22; + break; + /* CSD (TCH/H2.4): 3.6 kbit/s radio interface rate */ + case GSM48_CMODE_DATA_3k6: + if (!sched_tchh_ul_csd_mapbi->fn % 26) + return 0; /* CSD: skip decoding attempt, need 2 more bursts */ + /* FACCH/F does not steal TCH/H2.4 frames, but only disturbs some bits */ + decode_hr_facch(l1ts, bi); + rc = gsm0503_tch_hr24_decode(&tch_data0, BUFPOS(bursts_p, 0), + &n_errors, &n_bits_total); + meas_avg_mode = SCHED_MEAS_AVG_M_S22N22; + break; default: LOGL1SB(DL1P, LOGL_ERROR, l1ts, bi, "TCH mode %u invalid, please fix!\n", @@ -273,22 +357,11 @@ trx_loop_amr_input(chan_state, &meas_avg); /* Check if the frame is bad */ - if (rc < 0) { - LOGL1SB(DL1P, LOGL_NOTICE, l1ts, bi, "Received bad data (%u/%u)\n", - bi->fn % l1ts->mf_period, l1ts->mf_period); - bfi_flag = true; - } else if (rc < 4) { + if (rc < 4) { LOGL1SB(DL1P, LOGL_NOTICE, l1ts, bi, - "Received bad data (%u/%u) with invalid codec mode %d\n", - bi->fn % l1ts->mf_period, l1ts->mf_period, rc); - bfi_flag = true; - } - - if (bfi_flag) + BAD_DATA_MSG_FMT "\n", BAD_DATA_MSG_ARGS); rc = 0; /* this is how we signal BFI to l1sap */ - - /* FACCH */ - if (rc == GSM_MACBLOCK_LEN) { + } else if (rc == GSM_MACBLOCK_LEN) { /* FACCH */ chan_state->ul_ongoing_facch = 1; /* In order to provide an even stream of measurement reports in *speech* * mode, here we intentionally invalidate RSSI for FACCH, so that this @@ -308,7 +381,7 @@ rc = 0; } - if (rsl_cmode != RSL_CMOD_SPD_SPEECH) + if (rsl_cmode == RSL_CMOD_SPD_SIGN) return 0; /* TCH or BFI */ @@ -323,7 +396,8 @@ /* common section for generation of TCH bursts (TCH/H and TCH/F). * FIXME: this function is over-complicated, refactor / get rid of it. */ -extern struct msgb *tch_dl_dequeue(struct l1sched_ts *l1ts, const struct trx_dl_burst_req *br); +extern void tch_dl_dequeue(struct l1sched_ts *l1ts, const struct trx_dl_burst_req *br, + struct msgb **msg_tch, struct msgb **msg_facch); /* obtain a to-be-transmitted TCH/H (Half Traffic Channel) burst */ int tx_tchh_fn(struct l1sched_ts *l1ts, struct trx_dl_burst_req *br) @@ -332,7 +406,9 @@ uint8_t tch_mode = chan_state->tch_mode; ubit_t *burst, *bursts_p = chan_state->dl_bursts; uint8_t *mask = &chan_state->dl_mask; - struct msgb *msg; + struct msgb *msg_facch = NULL; + struct msgb *msg_tch = NULL; + struct msgb *msg = NULL; /* send burst, if we already got a frame */ if (br->bid > 0) { @@ -345,27 +421,30 @@ /* BURST BYPASS */ - /* shift buffer by 2 bursts for interleaving */ - memcpy(bursts_p, bursts_p + 232, 232); - if (chan_state->dl_ongoing_facch) { - memcpy(bursts_p + 232, bursts_p + 464, 232); - memset(bursts_p + 464, 0, 232); - } else { - memset(bursts_p + 232, 0, 232); + /* shift buffer by 2 bursts for interleaving */ + memmove(BUFPOS(bursts_p, 0), BUFPOS(bursts_p, 2), 20 * BPLEN); + memset(BUFPOS(bursts_p, 20), 0, 2 * BPLEN); + + /* for half-rate CSD we dequeue every 4th burst */ + if (chan_state->rsl_cmode == RSL_CMOD_SPD_DATA) { + if (!sched_tchh_dl_csd_mapbr->fn % 26) + goto send_burst; } - /* dequeue a message to be transmitted */ - msg = tch_dl_dequeue(l1ts, br); + /* dequeue a TCH and/or a FACCH message to be transmitted */ + tch_dl_dequeue(l1ts, br, &msg_tch, &msg_facch); /* if we're sending 2 middle bursts of FACCH/H */ if (chan_state->dl_ongoing_facch) { - msgb_free(msg); /* drop 2nd speech frame */ + /* FACCH/H shall not be scheduled at wrong FNs */ + OSMO_ASSERT(msg_facch == NULL); + msgb_free(msg_tch); /* drop 2nd speech frame */ chan_state->dl_ongoing_facch = 0; goto send_burst; } /* no message at all, send a dummy L2 frame on FACCH */ - if (msg == NULL) { + if (msg_tch == NULL && msg_facch == NULL) { static const uint8_t dummyGSM_MACBLOCK_LEN = { 0x03, 0x03, 0x01, /* TODO: use randomized padding */ 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, @@ -397,38 +476,64 @@ goto send_burst; } - gsm0503_tch_hr_encode(bursts_p, dummy, sizeof(dummy)); - chan_state->dl_ongoing_facch = 1; + gsm0503_tch_hr_encode(BUFPOS(bursts_p, 0), dummy, sizeof(dummy)); + if (chan_state->rsl_cmode != RSL_CMOD_SPD_DATA) + chan_state->dl_ongoing_facch = 1; chan_state->dl_facch_bursts = 6; goto send_burst; } - /* populate the buffer with bursts */ - if (msgb_l2len(msg) == GSM_MACBLOCK_LEN) { - gsm0503_tch_hr_encode(bursts_p, msg->l2h, msgb_l2len(msg)); - chan_state->dl_ongoing_facch = 1; /* first of two TCH frames */ + /* Unlike SACCH, FACCH has no dedicated slots on the multiframe layout. + * It's multiplexed together with TCH (speech or data) frames basically + * by replacing (stealing) their bits, either completely or partly. */ + msg = (msg_facch != NULL) ? msg_facch : msg_tch; + if (msg == msg_facch) { + if (chan_state->rsl_cmode != RSL_CMOD_SPD_DATA) + chan_state->dl_ongoing_facch = 1; chan_state->dl_facch_bursts = 6; - } 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: + gsm0503_tch_hr_encode(BUFPOS(bursts_p, 0), msg->l2h, msgb_l2len(msg)); + break; + case GSM48_CMODE_SPEECH_AMR: /* the first FN 4,13,21 or 5,14,22 defines that CMI is included * in frame, the first FN 0,8,17 or 1,9,18 defines that CMR is * included in frame. */ - gsm0503_tch_ahs_encode(bursts_p, + gsm0503_tch_ahs_encode(BUFPOS(bursts_p, 0), msgb_l2(msg), msgb_l2len(msg), !sched_tchh_dl_amr_cmi_mapbr->fn % 26, chan_state->codec, chan_state->codecs, chan_state->dl_ft, chan_state->dl_cmr); - } else { - gsm0503_tch_hr_encode(bursts_p, msg->l2h, msgb_l2len(msg)); + break; + /* CSD (TCH/H4.8): 6.0 kbit/s radio interface rate */ + case GSM48_CMODE_DATA_6k0: + gsm0503_tch_hr48_encode(BUFPOS(bursts_p, 0), msgb_l2(msg_tch)); + if (msg_facch != NULL) + gsm0503_tch_hr_facch_encode(BUFPOS(bursts_p, 0), msgb_l2(msg_facch)); + break; + /* CSD (TCH/H2.4): 3.6 kbit/s radio interface rate */ + case GSM48_CMODE_DATA_3k6: + gsm0503_tch_hr24_encode(BUFPOS(bursts_p, 0), msgb_l2(msg_tch)); + if (msg_facch != NULL) + gsm0503_tch_hr_facch_encode(BUFPOS(bursts_p, 0), msgb_l2(msg_facch)); + break; + default: + OSMO_ASSERT(0); } - /* free message */ - msgb_free(msg); + /* free messages */ + msgb_free(msg_tch); + msgb_free(msg_facch); send_burst: /* compose burst */ - burst = bursts_p + br->bid * 116; + burst = BUFPOS(bursts_p, br->bid); memcpy(br->burst + 3, burst, 58); memcpy(br->burst + 61, TRX_GMSK_NB_TSC(br), 26); memcpy(br->burst + 87, burst + 58, 58);
View file
osmo-bts_1.6.0.168.f3a6.tar.xz/src/osmo-bts-trx/sched_lchan_xcch.c -> osmo-bts_1.6.0.175.4344.tar.xz/src/osmo-bts-trx/sched_lchan_xcch.c
Changed
@@ -52,7 +52,7 @@ struct l1sched_chan_state *chan_state = &l1ts->chan_statebi->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 l2GSM_MACBLOCK_LEN, l2_len; struct l1sched_meas_set meas_avg; int n_errors = 0; @@ -113,8 +113,8 @@ /* decode */ rc = gsm0503_xcch_decode(l2, bursts_p, &n_errors, &n_bits_total); if (rc) { - LOGL1SB(DL1P, LOGL_NOTICE, l1ts, bi, "Received bad data (%u/%u)\n", - bi->fn % l1ts->mf_period, l1ts->mf_period); + LOGL1SB(DL1P, LOGL_NOTICE, l1ts, bi, + BAD_DATA_MSG_FMT "\n", BAD_DATA_MSG_ARGS); l2_len = 0; /* When SACCH Repetition is active, we may try to decode the
View file
osmo-bts_1.6.0.168.f3a6.tar.xz/src/osmo-bts-trx/sched_utils.h -> osmo-bts_1.6.0.175.4344.tar.xz/src/osmo-bts-trx/sched_utils.h
Changed
@@ -23,8 +23,22 @@ #include <stdint.h> +/* Burst Payload LENgth (short alias) */ +#define BPLEN GSM_NBITS_NB_GMSK_PAYLOAD + +/* Burst BUFfer capacity (in BPLEN units) */ +#define BUFMAX 24 + +/* Burst BUFfer position macros */ +#define BUFPOS(buf, n) &buf(n) * BPLEN +#define BUFTAIL8(buf) BUFPOS(buf, (BUFMAX - 8)) + extern void *tall_bts_ctx; +#define BAD_DATA_MSG_FMT "Received bad data (rc=%d, BER %d/%d) ending at fn=%u/%u" +#define BAD_DATA_MSG_ARGS \ + rc, n_errors, n_bits_total, bi->fn % l1ts->mf_period, l1ts->mf_period + /* Compute the bit error rate in 1/10000 units */ static inline uint16_t compute_ber10k(int n_bits_total, int n_errors) {
View file
osmo-bts_1.6.0.168.f3a6.tar.xz/src/osmo-bts-trx/scheduler_trx.c -> osmo-bts_1.6.0.175.4344.tar.xz/src/osmo-bts-trx/scheduler_trx.c
Changed
@@ -638,6 +638,8 @@ /* Measurement averaging mode sets: MODE = { SHIFT, NUM } */ static const uint8_t trx_sched_meas_modeset2 = { + SCHED_MEAS_AVG_M_S24N22 = { 24, 22 }, + 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 },
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.