host/trxcon/scheduler: implement xCCH decoding

Change-Id: Ieb71e3727b525e85d161855973f63042366ccb05
This commit is contained in:
Vadim Yanitskiy 2017-07-06 13:17:24 +07:00
parent cf5c10f92a
commit 228d42bc30
7 changed files with 197 additions and 2 deletions

View File

@ -31,6 +31,7 @@ trxcon_SOURCES = \
# Scheduler
trxcon_SOURCES += \
sched_lchan_handlers.c \
sched_lchan_desc.c \
sched_mframe.c \
sched_clck.c \

View File

@ -123,6 +123,28 @@ int l1ctl_tx_reset_conf(struct l1ctl_link *l1l, uint8_t type)
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;

View File

@ -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);

View File

@ -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",

View File

@ -0,0 +1,161 @@
/*
* OsmocomBB <-> SDR connection bridge
* TDMA scheduler: handlers for DL / UL bursts on logical channels
*
* (C) 2017 by Vadim Yanitskiy <axilirator@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;
}

View File

@ -130,6 +130,8 @@ static void trxcon_fsm_managed_action(struct osmo_fsm_inst *fi,
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 @@ static struct osmo_fsm_state trxcon_fsm_states[] = {
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,

View File

@ -22,4 +22,5 @@ enum trxcon_fsm_events {
/* Scheduler specific events */
SCH_EVENT_CLCK_IND,
SCH_EVENT_CLCK_LOSS,
SCH_EVENT_DATA,
};