2017-07-26 08:30:35 +00:00
|
|
|
/*
|
|
|
|
* OsmocomBB <-> SDR connection bridge
|
|
|
|
* TDMA scheduler: handlers for DL / UL bursts on logical channels
|
|
|
|
*
|
2022-07-06 11:06:07 +00:00
|
|
|
* (C) 2017-2022 by Vadim Yanitskiy <axilirator@gmail.com>
|
2021-06-14 21:14:34 +00:00
|
|
|
* Contributions by sysmocom - s.f.m.c. GmbH
|
2017-07-26 08:30:35 +00:00
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <errno.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdint.h>
|
2017-12-16 08:09:51 +00:00
|
|
|
#include <stdbool.h>
|
2017-07-26 08:30:35 +00:00
|
|
|
|
|
|
|
#include <osmocom/core/logging.h>
|
|
|
|
#include <osmocom/core/bits.h>
|
|
|
|
|
|
|
|
#include <osmocom/gsm/gsm_utils.h>
|
|
|
|
#include <osmocom/coding/gsm0503_coding.h>
|
|
|
|
|
2022-07-22 12:54:14 +00:00
|
|
|
#include <osmocom/bb/l1sched/l1sched.h>
|
2022-07-22 00:21:11 +00:00
|
|
|
#include <osmocom/bb/l1sched/logging.h>
|
2017-07-26 08:30:35 +00:00
|
|
|
|
2019-04-21 12:22:21 +00:00
|
|
|
/* 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[] = {
|
2018-07-16 07:11:26 +00:00
|
|
|
0, 0, 1, 1, 1, 0, 1, 0,
|
|
|
|
};
|
|
|
|
|
2019-04-21 12:22:21 +00:00
|
|
|
/* 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 },
|
2017-07-26 08:30:35 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/* Obtain a to-be-transmitted RACH burst */
|
2022-07-06 11:06:07 +00:00
|
|
|
int tx_rach_fn(struct l1sched_lchan_state *lchan,
|
2022-07-01 18:42:26 +00:00
|
|
|
struct l1sched_burst_req *br)
|
2017-07-26 08:30:35 +00:00
|
|
|
{
|
2022-07-06 11:06:07 +00:00
|
|
|
const uint8_t bsic = lchan->ts->sched->bsic;
|
2021-06-14 21:14:34 +00:00
|
|
|
uint8_t *burst_ptr = br->burst;
|
2017-07-26 08:30:35 +00:00
|
|
|
uint8_t payload[36];
|
2019-04-21 12:22:21 +00:00
|
|
|
int i, rc;
|
|
|
|
|
2023-07-13 21:40:01 +00:00
|
|
|
if (llist_empty(&lchan->tx_prims))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
struct msgb *msg = llist_first_entry(&lchan->tx_prims, struct msgb, list);
|
|
|
|
struct l1sched_prim *prim = l1sched_prim_from_msgb(msg);
|
2022-07-09 15:33:59 +00:00
|
|
|
|
|
|
|
/* Delay sending according to offset value */
|
2023-04-12 16:52:09 +00:00
|
|
|
if (prim->rach_req.offset-- > 0)
|
2022-07-09 15:33:59 +00:00
|
|
|
return 0;
|
2023-07-13 21:40:01 +00:00
|
|
|
llist_del(&msg->list);
|
2022-07-09 15:33:59 +00:00
|
|
|
|
2023-04-12 16:52:09 +00:00
|
|
|
/* Check requested synch. sequence */
|
|
|
|
if (prim->rach_req.synch_seq >= RACH_SYNCH_SEQ_NUM) {
|
2022-07-22 00:21:11 +00:00
|
|
|
LOGP_LCHAND(lchan, LOGL_ERROR,
|
2023-04-12 16:52:09 +00:00
|
|
|
"Unknown RACH synch. sequence=0x%02x\n",
|
|
|
|
prim->rach_req.synch_seq);
|
2023-07-13 21:40:01 +00:00
|
|
|
msgb_free(msg);
|
2023-04-12 16:52:09 +00:00
|
|
|
return -ENOTSUP;
|
2018-07-24 15:24:13 +00:00
|
|
|
}
|
|
|
|
|
2023-04-12 16:52:09 +00:00
|
|
|
/* Encode the payload */
|
|
|
|
rc = gsm0503_rach_ext_encode(payload, prim->rach_req.ra,
|
|
|
|
bsic, prim->rach_req.is_11bit);
|
|
|
|
if (rc) {
|
|
|
|
LOGP_LCHAND(lchan, LOGL_ERROR,
|
|
|
|
"Could not encode %s-bit RACH burst (ra=%u bsic=%u)\n",
|
|
|
|
prim->rach_req.is_11bit ? "11" : "8",
|
|
|
|
prim->rach_req.ra, bsic);
|
2023-07-13 21:40:01 +00:00
|
|
|
msgb_free(msg);
|
2023-04-12 16:52:09 +00:00
|
|
|
return rc;
|
|
|
|
}
|
2017-07-26 08:30:35 +00:00
|
|
|
|
2019-04-21 12:22:21 +00:00
|
|
|
/* BN0-7: extended tail bits */
|
|
|
|
memcpy(burst_ptr, rach_ext_tail_bits, RACH_EXT_TAIL_BITS_LEN);
|
|
|
|
burst_ptr += RACH_EXT_TAIL_BITS_LEN;
|
2017-07-26 08:30:35 +00:00
|
|
|
|
2019-04-21 12:22:21 +00:00
|
|
|
/* BN8-48: chosen synch. (training) sequence */
|
|
|
|
for (i = 0; i < RACH_SYNCH_SEQ_LEN; i++)
|
2023-04-12 16:52:09 +00:00
|
|
|
*(burst_ptr++) = rach_synch_seq_bits[prim->rach_req.synch_seq][i] == '1';
|
2017-12-17 20:47:23 +00:00
|
|
|
|
2019-04-21 12:22:21 +00:00
|
|
|
/* BN49-84: encrypted bits (the payload) */
|
|
|
|
memcpy(burst_ptr, payload, RACH_PAYLOAD_LEN);
|
|
|
|
burst_ptr += RACH_PAYLOAD_LEN;
|
2017-07-26 08:30:35 +00:00
|
|
|
|
2019-04-21 12:22:21 +00:00
|
|
|
/* BN85-156: tail bits & extended guard period */
|
2023-03-07 19:30:48 +00:00
|
|
|
memset(burst_ptr, 0, br->burst + GSM_NBITS_NB_GMSK_BURST - burst_ptr);
|
|
|
|
br->burst_len = GSM_NBITS_NB_GMSK_BURST;
|
2017-07-26 08:30:35 +00:00
|
|
|
|
2022-07-28 23:31:54 +00:00
|
|
|
LOGP_LCHAND(lchan, LOGL_NOTICE, "Scheduled %s-bit RACH (%s) at fn=%u\n",
|
2023-04-12 16:52:09 +00:00
|
|
|
prim->rach_req.is_11bit ? "11" : "8",
|
|
|
|
get_value_string(rach_synch_seq_names, prim->rach_req.synch_seq), br->fn);
|
2019-09-18 14:38:03 +00:00
|
|
|
|
2023-07-13 21:40:01 +00:00
|
|
|
/* Confirm RACH request (pass ownership of the msgb/prim) */
|
|
|
|
l1sched_lchan_emit_data_cnf(lchan, msg, br->fn);
|
2017-07-26 08:30:35 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|