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>

Reply via email to