summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVadim Yanitskiy <axilirator@gmail.com>2019-04-21 19:22:21 +0700
committerVadim Yanitskiy <axilirator@gmail.com>2019-04-22 09:17:23 +0000
commit4dd92e2520d228a80cde10c439ad041ddfc93fdd (patch)
tree5aee60fade5faa1c8dba44f1fcbd2e3e9fdcdc07
parent5e473cb4785074a8ad2da8f327050bc0890ed80b (diff)
trxcon: introduce extended (11-bit) RACH support
According to 3GPP TS 05.03, section 5.3, two coding schemes are specified for access bursts: one for regular 8-bit bursts, another - for extended 11-bit packet access bursts. According to 3GPP TS 05.02, section 5.2.7, there are two additional training (synchronization) sequences for RACH bursts: TS1 & TS2. By default, TS0 synch. sequence is used, unless explicitly stated otherwise (see 3GPP TS 04.60). According to 3GPP TS 04.60, section 11.2.5a, the EGPRS capability can be indicated by the MS using an alternative training sequence (i.e. TS1 or TS2) and the 11-bit RACH coding scheme. Change-Id: I36fd20cd5502ce33c52f644ee4c22abb83350df8
-rw-r--r--src/host/trxcon/l1ctl.c34
-rw-r--r--src/host/trxcon/sched_lchan_rach.c146
2 files changed, 128 insertions, 52 deletions
diff --git a/src/host/trxcon/l1ctl.c b/src/host/trxcon/l1ctl.c
index 97c24966..653ddf34 100644
--- a/src/host/trxcon/l1ctl.c
+++ b/src/host/trxcon/l1ctl.c
@@ -500,8 +500,9 @@ exit:
return rc;
}
-static int l1ctl_rx_rach_req(struct l1ctl_link *l1l, struct msgb *msg)
+static int l1ctl_rx_rach_req(struct l1ctl_link *l1l, struct msgb *msg, bool ext)
{
+ struct l1ctl_ext_rach_req *ext_req;
struct l1ctl_rach_req *req;
struct l1ctl_info_ul *ul;
struct trx_ts_prim *prim;
@@ -510,11 +511,25 @@ static int l1ctl_rx_rach_req(struct l1ctl_link *l1l, struct msgb *msg)
int rc;
ul = (struct l1ctl_info_ul *) msg->l1h;
- req = (struct l1ctl_rach_req *) ul->payload;
- len = sizeof(struct l1ctl_rach_req);
- /* Convert offset value to host format */
- req->offset = ntohs(req->offset);
+ /* Is it extended (11-bit) RACH or not? */
+ if (ext) {
+ ext_req = (struct l1ctl_ext_rach_req *) ul->payload;
+ ext_req->offset = ntohs(ext_req->offset);
+ ext_req->ra11 = ntohs(ext_req->ra11);
+ len = sizeof(*ext_req);
+
+ LOGP(DL1C, LOGL_NOTICE, "Received extended (11-bit) RACH request "
+ "(offset=%u, synch_seq=%u, ra11=0x%02hx)\n",
+ ext_req->offset, ext_req->synch_seq, ext_req->ra11);
+ } else {
+ req = (struct l1ctl_rach_req *) ul->payload;
+ req->offset = ntohs(req->offset);
+ len = sizeof(*req);
+
+ LOGP(DL1C, LOGL_NOTICE, "Received regular (8-bit) RACH request "
+ "(offset=%u, ra=0x%02x)\n", req->offset, req->ra);
+ }
/**
* FIXME: l1ctl_info_ul doesn't provide channel description
@@ -523,9 +538,6 @@ static int l1ctl_rx_rach_req(struct l1ctl_link *l1l, struct msgb *msg)
chan_nr = 0x88;
link_id = 0x00;
- LOGP(DL1C, LOGL_NOTICE, "Received RACH request "
- "(offset=%u ra=0x%02x)\n", req->offset, req->ra);
-
/* Init a new primitive */
rc = sched_prim_init(l1l->trx, &prim, len, chan_nr, link_id);
if (rc)
@@ -544,7 +556,7 @@ static int l1ctl_rx_rach_req(struct l1ctl_link *l1l, struct msgb *msg)
}
/* Fill in the payload */
- memcpy(prim->payload, req, len);
+ memcpy(prim->payload, ul->payload, len);
exit:
msgb_free(msg);
@@ -845,7 +857,9 @@ int l1ctl_rx_cb(struct l1ctl_link *l1l, struct msgb *msg)
case L1CTL_CCCH_MODE_REQ:
return l1ctl_rx_ccch_mode_req(l1l, msg);
case L1CTL_RACH_REQ:
- return l1ctl_rx_rach_req(l1l, msg);
+ return l1ctl_rx_rach_req(l1l, msg, false);
+ case L1CTL_EXT_RACH_REQ:
+ return l1ctl_rx_rach_req(l1l, msg, true);
case L1CTL_DM_EST_REQ:
return l1ctl_rx_dm_est_req(l1l, msg);
case L1CTL_DM_REL_REQ:
diff --git a/src/host/trxcon/sched_lchan_rach.c b/src/host/trxcon/sched_lchan_rach.c
index ecf5df81..58e86ae1 100644
--- a/src/host/trxcon/sched_lchan_rach.c
+++ b/src/host/trxcon/sched_lchan_rach.c
@@ -40,68 +40,130 @@
#include "trx_if.h"
#include "l1ctl.h"
-/**
- * 8-bit RACH extended tail bits
- * GSM 05.02 Chapter 5.2.7 Access burst (AB)
- */
-
-static ubit_t rach_ext_tail_bits[] = {
+/* FIXME: we need a better way to identify / distinguish primitives */
+#define PRIM_IS_EXT_RACH(prim) \
+ (prim->payload_len == sizeof(struct l1ctl_ext_rach_req))
+#define PRIM_IS_RACH(prim) \
+ (prim->payload_len == sizeof(struct l1ctl_rach_req))
+
+/* 3GPP TS 05.02, section 5.2.7 "Access burst (AB)" */
+#define RACH_EXT_TAIL_BITS_LEN 8
+#define RACH_SYNCH_SEQ_LEN 41
+#define RACH_PAYLOAD_LEN 36
+
+/* Extended tail bits (BN0..BN7) */
+static const ubit_t rach_ext_tail_bits[] = {
0, 0, 1, 1, 1, 0, 1, 0,
};
-/**
- * 41-bit RACH synchronization sequence
- * GSM 05.02 Chapter 5.2.7 Access burst (AB)
- */
-static ubit_t rach_synch_seq[] = {
- 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1,
- 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0,
- 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0,
+/* Synchronization (training) sequence types */
+enum rach_synch_seq_t {
+ RACH_SYNCH_SEQ_UNKNOWN = -1,
+ RACH_SYNCH_SEQ_TS0, /* GSM, GMSK (default) */
+ RACH_SYNCH_SEQ_TS1, /* EGPRS, 8-PSK */
+ RACH_SYNCH_SEQ_TS2, /* EGPRS, GMSK */
+ RACH_SYNCH_SEQ_NUM
+};
+
+/* Synchronization (training) sequence bits */
+static const char rach_synch_seq_bits[RACH_SYNCH_SEQ_NUM][RACH_SYNCH_SEQ_LEN] = {
+ [RACH_SYNCH_SEQ_TS0] = "01001011011111111001100110101010001111000",
+ [RACH_SYNCH_SEQ_TS1] = "01010100111110001000011000101111001001101",
+ [RACH_SYNCH_SEQ_TS2] = "11101111001001110101011000001101101110111",
+};
+
+/* Synchronization (training) sequence names */
+static struct value_string rach_synch_seq_names[] = {
+ { RACH_SYNCH_SEQ_UNKNOWN, "UNKNOWN" },
+ { RACH_SYNCH_SEQ_TS0, "TS0: GSM, GMSK" },
+ { RACH_SYNCH_SEQ_TS1, "TS1: EGPRS, 8-PSK" },
+ { RACH_SYNCH_SEQ_TS2, "TS2: EGPRS, GMSK" },
+ { 0, NULL },
};
/* Obtain a to-be-transmitted RACH burst */
int tx_rach_fn(struct trx_instance *trx, struct trx_ts *ts,
struct trx_lchan_state *lchan, uint32_t fn, uint8_t bid)
{
- struct l1ctl_rach_req *req;
+ struct l1ctl_ext_rach_req *ext_req = NULL;
+ struct l1ctl_rach_req *req = NULL;
+ enum rach_synch_seq_t synch_seq;
uint8_t burst[GSM_BURST_LEN];
+ uint8_t *burst_ptr = burst;
uint8_t payload[36];
- int rc;
-
- /* Check the prim payload length */
- if (lchan->prim->payload_len != sizeof(*req)) {
- LOGP(DSCHD, LOGL_ERROR, "Primitive has odd length %zu (expected %zu), "
- "so dropping...\n", lchan->prim->payload_len, sizeof(*req));
-
+ int i, rc;
+
+ /* Is it extended (11-bit) RACH or not? */
+ if (PRIM_IS_EXT_RACH(lchan->prim)) {
+ ext_req = (struct l1ctl_ext_rach_req *) lchan->prim->payload;
+ synch_seq = ext_req->synch_seq;
+
+ /* Check requested synch. sequence */
+ if (synch_seq >= RACH_SYNCH_SEQ_NUM) {
+ LOGP(DSCHD, LOGL_ERROR, "Unknown RACH synch. sequence=0x%02x\n", synch_seq);
+
+ /* Forget this primitive */
+ sched_prim_drop(lchan);
+ return -ENOTSUP;
+ }
+
+ /* Delay sending according to offset value */
+ if (ext_req->offset-- > 0)
+ return 0;
+
+ /* Encode extended (11-bit) payload */
+ rc = gsm0503_rach_ext_encode(payload, ext_req->ra11, trx->bsic, true);
+ if (rc) {
+ LOGP(DSCHD, LOGL_ERROR, "Could not encode extended RACH burst\n");
+
+ /* Forget this primitive */
+ sched_prim_drop(lchan);
+ return rc;
+ }
+ } else if (PRIM_IS_RACH(lchan->prim)) {
+ req = (struct l1ctl_rach_req *) lchan->prim->payload;
+ synch_seq = RACH_SYNCH_SEQ_TS0;
+
+ /* Delay sending according to offset value */
+ if (req->offset-- > 0)
+ return 0;
+
+ /* Encode regular (8-bit) payload */
+ rc = gsm0503_rach_ext_encode(payload, req->ra, trx->bsic, false);
+ if (rc) {
+ LOGP(DSCHD, LOGL_ERROR, "Could not encode RACH burst\n");
+
+ /* Forget this primitive */
+ sched_prim_drop(lchan);
+ return rc;
+ }
+ } else {
+ LOGP(DSCHD, LOGL_ERROR, "Primitive has odd length %zu (expected %zu or %zu), "
+ "so dropping...\n", lchan->prim->payload_len,
+ sizeof(*req), sizeof(*ext_req));
sched_prim_drop(lchan);
return -EINVAL;
}
- /* Get the payload from a current primitive */
- req = (struct l1ctl_rach_req *) lchan->prim->payload;
- /* Delay RACH sending according to offset value */
- if (req->offset-- > 0)
- return 0;
+ /* BN0-7: extended tail bits */
+ memcpy(burst_ptr, rach_ext_tail_bits, RACH_EXT_TAIL_BITS_LEN);
+ burst_ptr += RACH_EXT_TAIL_BITS_LEN;
- /* Encode (8-bit) payload */
- rc = gsm0503_rach_ext_encode(payload, req->ra, trx->bsic, false);
- if (rc) {
- LOGP(DSCHD, LOGL_ERROR, "Could not encode RACH burst\n");
+ /* BN8-48: chosen synch. (training) sequence */
+ for (i = 0; i < RACH_SYNCH_SEQ_LEN; i++)
+ *(burst_ptr++) = rach_synch_seq_bits[synch_seq][i] == '1';
- /* Forget this primitive */
- sched_prim_drop(lchan);
-
- return rc;
- }
+ /* BN49-84: encrypted bits (the payload) */
+ memcpy(burst_ptr, payload, RACH_PAYLOAD_LEN);
+ burst_ptr += RACH_PAYLOAD_LEN;
- /* Compose RACH burst */
- memcpy(burst, rach_ext_tail_bits, 8); /* TB */
- memcpy(burst + 8, rach_synch_seq, 41); /* sync seq */
- memcpy(burst + 49, payload, 36); /* payload */
- memset(burst + 85, 0, 63); /* TB + GP */
+ /* BN85-156: tail bits & extended guard period */
+ memset(burst_ptr, 0, burst + GSM_BURST_LEN - burst_ptr);
- LOGP(DSCHD, LOGL_DEBUG, "Transmitting RACH fn=%u\n", fn);
+ LOGP(DSCHD, LOGL_DEBUG, "Transmitting %s RACH (%s) fn=%u\n",
+ PRIM_IS_EXT_RACH(lchan->prim) ? "extended (11-bit)" : "regular (8-bit)",
+ get_value_string(rach_synch_seq_names, synch_seq), fn);
/* Forward burst to scheduler */
rc = sched_trx_handle_tx_burst(trx, ts, lchan, fn, burst);