Review at https://gerrit.osmocom.org/6696
host/trxcon/scheduler: implement xCCH decoding Change-Id: Ieb71e3727b525e85d161855973f63042366ccb05 --- M src/host/trxcon/Makefile.am M src/host/trxcon/l1ctl.c M src/host/trxcon/l1ctl.h M src/host/trxcon/sched_lchan_desc.c A src/host/trxcon/sched_lchan_handlers.c M src/host/trxcon/trxcon.c M src/host/trxcon/trxcon.h 7 files changed, 197 insertions(+), 2 deletions(-) git pull ssh://gerrit.osmocom.org:29418/osmocom-bb refs/changes/96/6696/1 diff --git a/src/host/trxcon/Makefile.am b/src/host/trxcon/Makefile.am index 1a373f7..b2f22fa 100644 --- a/src/host/trxcon/Makefile.am +++ b/src/host/trxcon/Makefile.am @@ -31,6 +31,7 @@ # Scheduler trxcon_SOURCES += \ + sched_lchan_handlers.c \ sched_lchan_desc.c \ sched_mframe.c \ sched_clck.c \ diff --git a/src/host/trxcon/l1ctl.c b/src/host/trxcon/l1ctl.c index 0bb26f7..3bcc5cb 100644 --- a/src/host/trxcon/l1ctl.c +++ b/src/host/trxcon/l1ctl.c @@ -123,6 +123,28 @@ return l1ctl_link_send(l1l, msg); } +int l1ctl_tx_data_ind(struct l1ctl_link *l1l, struct l1ctl_info_dl *data) +{ + struct l1ctl_info_dl *dl; + struct msgb *msg; + size_t len; + + msg = l1ctl_alloc_msg(L1CTL_DATA_IND); + if (msg == NULL) + return -ENOMEM; + + /* We store the 23-byte payload as a flexible array member */ + len = sizeof(struct l1ctl_info_dl) + 23; + dl = (struct l1ctl_info_dl *) msgb_put(msg, len); + + /* Copy header and data from source message */ + memcpy(dl, data, len); + talloc_free(data); + + /* Put message to upper layers */ + return l1ctl_link_send(l1l, msg); +} + static int l1ctl_rx_fbsb_req(struct l1ctl_link *l1l, struct msgb *msg) { struct l1ctl_fbsb_req *fbsb, *fbsb_copy; diff --git a/src/host/trxcon/l1ctl.h b/src/host/trxcon/l1ctl.h index ffd1a81..05a2c54 100644 --- a/src/host/trxcon/l1ctl.h +++ b/src/host/trxcon/l1ctl.h @@ -4,9 +4,12 @@ #include <osmocom/core/msgb.h> #include "l1ctl_link.h" +#include "l1ctl_proto.h" int l1ctl_tx_pm_conf(struct l1ctl_link *l1l, uint16_t band_arfcn, int dbm, int last); int l1ctl_tx_reset_conf(struct l1ctl_link *l1l, uint8_t type); int l1ctl_tx_reset_ind(struct l1ctl_link *l1l, uint8_t type); int l1ctl_rx_cb(struct l1ctl_link *l1l, struct msgb *msg); + +int l1ctl_tx_data_ind(struct l1ctl_link *l1l, struct l1ctl_info_dl *ind); diff --git a/src/host/trxcon/sched_lchan_desc.c b/src/host/trxcon/sched_lchan_desc.c index 880c2a5..93927a6 100644 --- a/src/host/trxcon/sched_lchan_desc.c +++ b/src/host/trxcon/sched_lchan_desc.c @@ -35,11 +35,15 @@ #define tx_tchh_fn NULL #define tx_rach_fn NULL -#define rx_data_fn NULL #define rx_pdtch_fn NULL #define rx_tchf_fn NULL #define rx_tchh_fn NULL +/* Forward declaration of handlers */ +int rx_data_fn(struct trx_instance *trx, struct trx_ts *ts, + uint32_t fn, enum trx_lchan_type chan, uint8_t bid, + sbit_t *bits, uint16_t nbits, int8_t rssi, float toa); + const struct trx_lchan_desc trx_lchan_desc[_TRX_CHAN_MAX] = { { TRXC_IDLE, "IDLE", diff --git a/src/host/trxcon/sched_lchan_handlers.c b/src/host/trxcon/sched_lchan_handlers.c new file mode 100644 index 0000000..2c2cb6a --- /dev/null +++ b/src/host/trxcon/sched_lchan_handlers.c @@ -0,0 +1,161 @@ +/* + * OsmocomBB <-> SDR connection bridge + * TDMA scheduler: handlers for DL / UL bursts on logical channels + * + * (C) 2017 by Vadim Yanitskiy <axilira...@gmail.com> + * + * 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 <talloc.h> +#include <stdint.h> + +#include <arpa/inet.h> + +#include <osmocom/core/logging.h> +#include <osmocom/core/bits.h> +#include <osmocom/core/msgb.h> +#include <osmocom/core/fsm.h> + +#include <osmocom/coding/gsm0503_coding.h> + +#include "l1ctl_proto.h" +#include "scheduler.h" +#include "sched_trx.h" +#include "logging.h" +#include "trx_if.h" +#include "trxcon.h" + +extern struct osmo_fsm_inst *trxcon_fsm; + +int rx_data_fn(struct trx_instance *trx, struct trx_ts *ts, + uint32_t fn, enum trx_lchan_type chan, uint8_t bid, + sbit_t *bits, uint16_t nbits, int8_t rssi, float toa) +{ + int n_errors, n_bits_total, rc; + struct trx_lchan_state *lchan; + uint8_t *rssi_num, *toa_num; + float *rssi_sum, *toa_sum; + sbit_t *buffer, *offset; + uint8_t l2[23], *mask; + uint32_t *first_fn; + + LOGP(DSCH, LOGL_DEBUG, "Data received on %s: fn=%u ts=%u bid=%u\n", + trx_lchan_desc[chan].name, fn, ts->index, bid); + + /* Find required channel state */ + lchan = sched_trx_find_lchan(ts, chan); + if (lchan == NULL) + return -EINVAL; + + /* Set up pointers */ + first_fn = &lchan->rx_first_fn; + mask = &lchan->rx_burst_mask; + buffer = lchan->rx_bursts; + + rssi_sum = &lchan->rssi_sum; + rssi_num = &lchan->rssi_num; + toa_sum = &lchan->toa_sum; + toa_num = &lchan->toa_num; + + /* Clear buffer & store frame number of first burst */ + if (bid == 0) { + memset(buffer, 0, 464); + + *first_fn = fn; + *mask = 0x0; + + *rssi_sum = 0; + *rssi_num = 0; + *toa_sum = 0; + *toa_num = 0; + } + + /* Update mask and RSSI */ + *mask |= (1 << bid); + *rssi_sum += rssi; + (*rssi_num)++; + *toa_sum += toa; + (*toa_num)++; + + /* Copy burst to buffer of 4 bursts */ + offset = buffer + bid * 116; + memcpy(offset, bits + 3, 58); + memcpy(offset + 58, bits + 87, 58); + + /* Wait until complete set of bursts */ + if (bid != 3) + return 0; + + /* Check for complete set of bursts */ + if ((*mask & 0xf) != 0xf) { + LOGP(DSCH, LOGL_DEBUG, "Received incomplete data frame at " + "fn=%u (%u/%u) for %s\n", *first_fn, + (*first_fn) % ts->mf_layout->period, + ts->mf_layout->period, + trx_lchan_desc[chan].name); + + /* We require first burst to have correct FN */ + if (!(*mask & 0x1)) { + *mask = 0x0; + return 0; + } + + /* FIXME: return from here? */ + } + + /* Attempt to decode */ + rc = gsm0503_xcch_decode(l2, buffer, &n_errors, &n_bits_total); + if (rc) { + LOGP(DSCH, LOGL_DEBUG, "Received bad data frame at fn=%u " + "(%u/%u) for %s\n", *first_fn, + (*first_fn) % ts->mf_layout->period, + ts->mf_layout->period, + trx_lchan_desc[chan].name); + return rc; + } + + /* Compose a message to the higher layers */ + struct l1ctl_info_dl *data; + data = talloc_zero_size(ts, sizeof(struct l1ctl_info_dl) + 23); + if (data == NULL) + return -ENOMEM; + + /* Fill in some downlink info */ + data->chan_nr = trx_lchan_desc[chan].chan_nr | ts->index; + data->link_id = trx_lchan_desc[chan].link_id; + data->band_arfcn = htons(trx->band_arfcn); + data->frame_nr = htonl(*first_fn); + data->rx_level = -(*rssi_sum / *rssi_num); + + /* FIXME: set proper values */ + data->num_biterr = n_errors; + data->fire_crc = 0; + data->snr = 0; + + /* Fill in decoded payload */ + memcpy(data->payload, l2, 23); + + /* Raise an event to trxcon */ + osmo_fsm_inst_dispatch(trxcon_fsm, SCH_EVENT_DATA, data); + + /* TODO: AGC, TA loops */ + return 0; +} diff --git a/src/host/trxcon/trxcon.c b/src/host/trxcon/trxcon.c index 6f50d1a..32de253 100644 --- a/src/host/trxcon/trxcon.c +++ b/src/host/trxcon/trxcon.c @@ -130,6 +130,8 @@ case L1CTL_EVENT_FBSB_REQ: trxcon_handle_fbsb_req((struct l1ctl_fbsb_req *) data); break; + case SCH_EVENT_DATA: + l1ctl_tx_data_ind(app_data.l1l, (struct l1ctl_info_dl *) data); case TRX_EVENT_RSP_ERROR: case TRX_EVENT_OFFLINE: case SCH_EVENT_CLCK_IND: @@ -157,7 +159,8 @@ GEN_MASK(TRX_EVENT_RSP_ERROR) | GEN_MASK(TRX_EVENT_OFFLINE) | GEN_MASK(SCH_EVENT_CLCK_IND) | - GEN_MASK(SCH_EVENT_CLCK_LOSS)), + GEN_MASK(SCH_EVENT_CLCK_LOSS) | + GEN_MASK(SCH_EVENT_DATA)), .out_state_mask = GEN_MASK(TRXCON_STATE_IDLE), .name = "MANAGED", .action = trxcon_fsm_managed_action, diff --git a/src/host/trxcon/trxcon.h b/src/host/trxcon/trxcon.h index c266eae..da777a9 100644 --- a/src/host/trxcon/trxcon.h +++ b/src/host/trxcon/trxcon.h @@ -22,4 +22,5 @@ /* Scheduler specific events */ SCH_EVENT_CLCK_IND, SCH_EVENT_CLCK_LOSS, + SCH_EVENT_DATA, }; -- To view, visit https://gerrit.osmocom.org/6696 To unsubscribe, visit https://gerrit.osmocom.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: Ieb71e3727b525e85d161855973f63042366ccb05 Gerrit-PatchSet: 1 Gerrit-Project: osmocom-bb Gerrit-Branch: master Gerrit-Owner: Harald Welte <lafo...@gnumonks.org>