mirror of
https://gitea.osmocom.org/cellular-infrastructure/osmo-bts.git
synced 2025-11-09 16:37:11 +00:00
Compare commits
32 Commits
laforge/tm
...
keith/lc15
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9192c6c6c2 | ||
|
|
ae4d85d891 | ||
|
|
dbb5addf7d | ||
|
|
e2f9d0eabe | ||
|
|
4e07b83a64 | ||
|
|
f1efd727fb | ||
|
|
e36fbca15f | ||
|
|
5914d76d5c | ||
|
|
cb4340b8a4 | ||
|
|
58d79e88ad | ||
|
|
6a5039674f | ||
|
|
3f35ab258d | ||
|
|
f9e7ccce27 | ||
|
|
2b948a3d17 | ||
|
|
1f932689fc | ||
|
|
7364ef15d9 | ||
|
|
24f98a0df9 | ||
|
|
6ea3b28321 | ||
|
|
eba074e081 | ||
|
|
5184576572 | ||
|
|
ac61baed2e | ||
|
|
aea29c7249 | ||
|
|
52d7eafcea | ||
|
|
cb69d607c9 | ||
|
|
d4f67591c7 | ||
|
|
8969adc5d9 | ||
|
|
a0403d3769 | ||
|
|
e7d835ca8c | ||
|
|
113712c728 | ||
|
|
e5711efbb5 | ||
|
|
f9115ae67a | ||
|
|
b54f1bf122 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -62,6 +62,7 @@ tests/meas/meas_test
|
||||
tests/misc/misc_test
|
||||
tests/handover/handover_test
|
||||
tests/tx_power/tx_power_test
|
||||
tests/ta_control/ta_control_test
|
||||
tests/testsuite
|
||||
tests/testsuite.log
|
||||
|
||||
|
||||
@@ -382,6 +382,7 @@ AC_OUTPUT(
|
||||
tests/sysmobts/Makefile
|
||||
tests/misc/Makefile
|
||||
tests/handover/Makefile
|
||||
tests/ta_control/Makefile
|
||||
tests/tx_power/Makefile
|
||||
tests/power/Makefile
|
||||
tests/meas/Makefile
|
||||
|
||||
@@ -22,7 +22,6 @@ line vty
|
||||
!
|
||||
phy 0
|
||||
instance 0
|
||||
osmotrx rx-gain 1
|
||||
osmotrx ip local 127.0.0.1
|
||||
osmotrx ip remote 127.0.0.1
|
||||
osmotrx timing-advance-loop
|
||||
|
||||
@@ -21,7 +21,6 @@ line vty
|
||||
!
|
||||
phy 0
|
||||
instance 0
|
||||
osmotrx rx-gain 1
|
||||
osmotrx ip local 127.0.0.1
|
||||
osmotrx ip remote 127.0.0.1
|
||||
bts 0
|
||||
|
||||
@@ -423,9 +423,9 @@ The activation of PDCH is performed by using the regular 'RSL CHANNEL ACTIVATE'
|
||||
procedure according to <<CHANNEL_ACTIVATION>>, with these modifications:
|
||||
|
||||
* The 'C-bits' part of the 'Channel Number' IE take the non-standard binary
|
||||
value 11000 (C5 thru C1 as seen in 3GPP TS 08.58 § 9.3.1).
|
||||
value 11000 (C5 through C1 as seen in 3GPP TS 08.58 § 9.3.1).
|
||||
* The 'A-bits' part of the 'Activation Type' IE take the non-standard binary
|
||||
value 1111, with an additional fourth bit (add A4 to A3 thru A1 as seen in
|
||||
value 1111, with an additional fourth bit (add A4 to A3 through A1 as seen in
|
||||
3GPP TS 08.58 § 9.3.3; all remaining reserved bits as well as the 'R' bit are
|
||||
coded as zero).
|
||||
* The normally mandatory 'Channel Mode' IE is omitted; none of the optional IEs
|
||||
|
||||
@@ -2,4 +2,4 @@ noinst_HEADERS = abis.h bts.h bts_model.h gsm_data.h gsm_data_shared.h logging.h
|
||||
oml.h paging.h rsl.h signal.h vty.h amr.h pcu_if.h pcuif_proto.h \
|
||||
handover.h msg_utils.h tx_power.h control_if.h cbch.h l1sap.h \
|
||||
power_control.h scheduler.h scheduler_backend.h phy_link.h \
|
||||
dtx_dl_amr_fsm.h
|
||||
dtx_dl_amr_fsm.h ta_control.h
|
||||
|
||||
@@ -479,6 +479,11 @@ enum gsm_bts_features {
|
||||
BTS_FEAT_SPEECH_H_AMR,
|
||||
BTS_FEAT_ETWS_PN,
|
||||
BTS_FEAT_MS_PWR_CTRL_DSP,
|
||||
/* When the feature is set then the measurement data is included in
|
||||
* (PRIM_PH_DATA) and struct ph_tch_param (PRIM_TCH). Otherwise the
|
||||
* measurement data is passed using a separate MPH INFO MEAS IND.
|
||||
* (See also ticket: OS#2977) */
|
||||
BTS_FEAT_MEAS_PAYLOAD_COMB,
|
||||
_NUM_BTS_FEAT
|
||||
};
|
||||
|
||||
@@ -736,6 +741,7 @@ struct gsm_bts {
|
||||
uint16_t rtp_port_range_start;
|
||||
uint16_t rtp_port_range_end;
|
||||
uint16_t rtp_port_range_next;
|
||||
int rtp_ip_dscp;
|
||||
|
||||
struct {
|
||||
uint8_t ciphers; /* flags A5/1==0x1, A5/2==0x2, A5/3==0x4 */
|
||||
@@ -777,6 +783,14 @@ struct gsm_bts {
|
||||
} pcu;
|
||||
|
||||
void *model_priv; /* Allocated by bts_model, contains model specific data pointer */
|
||||
#ifdef ENABLE_LC15BTS
|
||||
/* specific to LC15 BTS */
|
||||
struct {
|
||||
uint8_t led_ctrl_mode; /* 0: control by BTS, 1: not control by BTS */
|
||||
struct llist_head ceased_alarm_list; /* ceased alarm list*/
|
||||
unsigned int rtp_drift_thres_ms; /* RTP timestamp drift detection threshold */
|
||||
} lc15;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -134,7 +134,8 @@ extern uint8_t gsmtap_sapi_acch;
|
||||
|
||||
int add_l1sap_header(struct gsm_bts_trx *trx, struct msgb *rmsg,
|
||||
struct gsm_lchan *lchan, uint8_t chan_nr, uint32_t fn,
|
||||
uint16_t ber10k, int16_t lqual_cb);
|
||||
uint16_t ber10k, int16_t lqual_cb, int8_t rssi,
|
||||
int16_t ta_offs, uint8_t is_sub);
|
||||
|
||||
#define msgb_l1sap_prim(msg) ((struct osmo_phsap_prim *)(msg)->l1h)
|
||||
|
||||
|
||||
@@ -44,7 +44,6 @@ struct phy_link {
|
||||
uint16_t base_port_local;
|
||||
uint16_t base_port_remote;
|
||||
struct osmo_fd trx_ofd_clk;
|
||||
bool trx_ta_loop;
|
||||
uint32_t clock_advance;
|
||||
uint32_t rts_advance;
|
||||
bool use_legacy_setbsic;
|
||||
@@ -54,6 +53,7 @@ struct phy_link {
|
||||
} osmotrx;
|
||||
struct {
|
||||
char *mcast_dev; /* Network device for multicast */
|
||||
int ttl; /* TTL of transmitted udp multicast */
|
||||
char *bts_mcast_group; /* BTS are listening to this group */
|
||||
uint16_t bts_mcast_port;
|
||||
char *ms_mcast_group; /* MS are listening to this group */
|
||||
|
||||
@@ -54,7 +54,8 @@ int _sched_compose_ph_data_ind(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
||||
enum osmo_ph_pres_info_type presence_info);
|
||||
|
||||
int _sched_compose_tch_ind(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
||||
enum trx_chan_type chan, uint8_t *tch, uint8_t tch_len);
|
||||
enum trx_chan_type chan, uint8_t *tch, uint8_t tch_len,
|
||||
int16_t ta_offs_256bits, uint16_t ber10k, float rssi);
|
||||
|
||||
ubit_t *tx_idle_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
||||
enum trx_chan_type chan, uint8_t bid, uint16_t *nbits);
|
||||
|
||||
5
include/osmo-bts/ta_control.h
Normal file
5
include/osmo-bts/ta_control.h
Normal file
@@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <osmo-bts/gsm_data.h>
|
||||
|
||||
void lchan_ms_ta_ctrl(struct gsm_lchan *lchan);
|
||||
@@ -6,12 +6,16 @@ if ENABLE_LC15BTS
|
||||
AM_CFLAGS += -DENABLE_LC15BTS
|
||||
endif
|
||||
|
||||
if ENABLE_LC15BTS
|
||||
AM_CFLAGS += -DENABLE_LC15BTS
|
||||
endif
|
||||
|
||||
noinst_LIBRARIES = libbts.a libl1sched.a
|
||||
libbts_a_SOURCES = gsm_data_shared.c sysinfo.c logging.c abis.c oml.c bts.c \
|
||||
rsl.c vty.c paging.c measurement.c amr.c lchan.c \
|
||||
load_indication.c pcu_sock.c handover.c msg_utils.c \
|
||||
tx_power.c bts_ctrl_commands.c bts_ctrl_lookup.c \
|
||||
l1sap.c cbch.c power_control.c main.c phy_link.c \
|
||||
dtx_dl_amr_fsm.c scheduler_mframe.c
|
||||
dtx_dl_amr_fsm.c scheduler_mframe.c ta_control.c
|
||||
|
||||
libl1sched_a_SOURCES = scheduler.c
|
||||
|
||||
@@ -128,7 +128,8 @@ static struct e1inp_sign_link *sign_link_up(void *unit, struct e1inp_line *line,
|
||||
e1inp_ts_config_sign(&line->ts[type-1], line);
|
||||
sign_link = trx->rsl_link =
|
||||
e1inp_sign_link_create(&line->ts[type-1],
|
||||
E1INP_SIGN_RSL, trx, 0, 0);
|
||||
E1INP_SIGN_RSL, trx,
|
||||
trx->rsl_tei, 0);
|
||||
trx_link_estab(trx);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -159,6 +159,7 @@ int bts_init(struct gsm_bts *bts)
|
||||
bts->rtp_port_range_start = 16384;
|
||||
bts->rtp_port_range_end = 17407;
|
||||
bts->rtp_port_range_next = bts->rtp_port_range_start;
|
||||
bts->rtp_ip_dscp = -1;
|
||||
|
||||
/* configurable via OML */
|
||||
bts->load.ccch.load_ind_period = 112;
|
||||
|
||||
@@ -109,6 +109,7 @@ const struct value_string gsm_bts_features_descs[] = {
|
||||
{ BTS_FEAT_SPEECH_H_AMR, "Halfrate speech AMR" },
|
||||
{ BTS_FEAT_ETWS_PN, "ETWS Primary Notification on PCH" },
|
||||
{ BTS_FEAT_MS_PWR_CTRL_DSP, "DSP/HW based MS Power Control Loop" },
|
||||
{ BTS_FEAT_MEAS_PAYLOAD_COMB, "Measurement and Payload data combined"},
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
|
||||
@@ -176,9 +176,15 @@ struct msgb *l1sap_msgb_alloc(unsigned int l2_len)
|
||||
return msg;
|
||||
}
|
||||
|
||||
/* Enclose rmsg into an osmo_phsap primitive and hand it over to the higher
|
||||
* layers. The phsap primitive also contains measurement information. The
|
||||
* parameters rssi, ta_offs and is_sub are only needed when the measurement
|
||||
* information is passed along with the TCH data. When separate measurement
|
||||
* indications are used, those last three parameters may be set to zero. */
|
||||
int add_l1sap_header(struct gsm_bts_trx *trx, struct msgb *rmsg,
|
||||
struct gsm_lchan *lchan, uint8_t chan_nr, uint32_t fn,
|
||||
uint16_t ber10k, int16_t lqual_cb)
|
||||
uint16_t ber10k, int16_t lqual_cb, int8_t rssi,
|
||||
int16_t ta_offs, uint8_t is_sub)
|
||||
{
|
||||
struct osmo_phsap_prim *l1sap;
|
||||
|
||||
@@ -194,6 +200,10 @@ int add_l1sap_header(struct gsm_bts_trx *trx, struct msgb *rmsg,
|
||||
l1sap->u.tch.ber10k = ber10k;
|
||||
l1sap->u.tch.lqual_cb = lqual_cb;
|
||||
|
||||
l1sap->u.tch.rssi = rssi;
|
||||
l1sap->u.tch.ta_offs_256bits = ta_offs;
|
||||
l1sap->u.tch.is_sub = is_sub;
|
||||
|
||||
return l1sap_up(trx, l1sap);
|
||||
}
|
||||
|
||||
@@ -629,42 +639,93 @@ static inline void set_ms_to_data(struct gsm_lchan *lchan, int16_t data, bool se
|
||||
}
|
||||
|
||||
/* measurement information received from bts model */
|
||||
static int l1sap_info_meas_ind(struct gsm_bts_trx *trx,
|
||||
static void process_l1sap_meas_data(struct gsm_bts_trx *trx,
|
||||
struct osmo_phsap_prim *l1sap,
|
||||
struct info_meas_ind_param *info_meas_ind)
|
||||
enum osmo_ph_prim ind_type)
|
||||
{
|
||||
struct bts_ul_meas ulm;
|
||||
struct gsm_lchan *lchan;
|
||||
struct info_meas_ind_param *info_meas_ind;
|
||||
struct ph_data_param *ph_data_ind;
|
||||
struct ph_tch_param *ph_tch_ind;
|
||||
uint8_t chan_nr;
|
||||
uint32_t fn;
|
||||
uint8_t inv_rssi;
|
||||
uint8_t is_sub;
|
||||
int16_t ta_offs_256bits;
|
||||
uint16_t ber10k;
|
||||
const char *ind_name;
|
||||
|
||||
lchan = get_active_lchan_by_chan_nr(trx, info_meas_ind->chan_nr);
|
||||
if (!lchan) {
|
||||
LOGPFN(DL1P, LOGL_ERROR, info_meas_ind->fn,
|
||||
"No lchan for MPH INFO MEAS IND (chan_nr=%s)\n", rsl_chan_nr_str(info_meas_ind->chan_nr));
|
||||
return 0;
|
||||
switch (ind_type) {
|
||||
case PRIM_MPH_INFO:
|
||||
/* (legacy way, see also OS#2977) */
|
||||
info_meas_ind = &l1sap->u.info.u.meas_ind;
|
||||
chan_nr = info_meas_ind->chan_nr;
|
||||
fn = info_meas_ind->fn;
|
||||
inv_rssi = info_meas_ind->inv_rssi;
|
||||
is_sub = info_meas_ind->is_sub;
|
||||
ta_offs_256bits = info_meas_ind->ta_offs_256bits;
|
||||
ber10k = info_meas_ind->ber10k;
|
||||
ind_name = "MPH INFO";
|
||||
break;
|
||||
case PRIM_TCH:
|
||||
ph_tch_ind = &l1sap->u.tch;
|
||||
if (ph_tch_ind->rssi == 0)
|
||||
return;
|
||||
chan_nr = ph_tch_ind->chan_nr;
|
||||
fn = ph_tch_ind->fn;
|
||||
inv_rssi = abs(ph_tch_ind->rssi);
|
||||
is_sub = ph_tch_ind->is_sub;
|
||||
ta_offs_256bits = ph_tch_ind->ta_offs_256bits;
|
||||
ber10k = ph_tch_ind->ber10k;
|
||||
ind_name = "TCH";
|
||||
break;
|
||||
case PRIM_PH_DATA:
|
||||
ph_data_ind = &l1sap->u.data;
|
||||
if (ph_data_ind->rssi == 0)
|
||||
return;
|
||||
chan_nr = ph_data_ind->chan_nr;
|
||||
fn = ph_data_ind->fn;
|
||||
inv_rssi = abs(ph_data_ind->rssi);
|
||||
is_sub = ph_data_ind->is_sub;
|
||||
ta_offs_256bits = ph_data_ind->ta_offs_256bits;
|
||||
ber10k = ph_data_ind->ber10k;
|
||||
ind_name = "DATA";
|
||||
break;
|
||||
default:
|
||||
OSMO_ASSERT(false);
|
||||
}
|
||||
|
||||
DEBUGPFN(DL1P, info_meas_ind->fn,
|
||||
"%s MPH_INFO meas ind, ta_offs_256bits=%d, ber10k=%d, inv_rssi=%u\n",
|
||||
gsm_lchan_name(lchan), info_meas_ind->ta_offs_256bits,
|
||||
info_meas_ind->ber10k, info_meas_ind->inv_rssi);
|
||||
lchan = get_active_lchan_by_chan_nr(trx, chan_nr);
|
||||
if (!lchan) {
|
||||
LOGPFN(DL1P, LOGL_ERROR, fn,
|
||||
"No lchan for %s MEAS IND (chan_nr=%s)\n",
|
||||
ind_name, rsl_chan_nr_str(chan_nr));
|
||||
return;
|
||||
}
|
||||
|
||||
DEBUGPFN(DL1P, fn,
|
||||
"%s %s meas ind, ta_offs_256bits=%d, ber10k=%d, inv_rssi=%u\n",
|
||||
gsm_lchan_name(lchan), ind_name, ta_offs_256bits, ber10k,
|
||||
inv_rssi);
|
||||
|
||||
/* in the GPRS case we are not interested in measurement
|
||||
* processing. The PCU will take care of it */
|
||||
if (lchan->type == GSM_LCHAN_PDTCH)
|
||||
return 0;
|
||||
return;
|
||||
|
||||
memset(&ulm, 0, sizeof(ulm));
|
||||
ulm.ta_offs_256bits = info_meas_ind->ta_offs_256bits;
|
||||
ulm.ber10k = info_meas_ind->ber10k;
|
||||
ulm.inv_rssi = info_meas_ind->inv_rssi;
|
||||
ulm.is_sub = info_meas_ind->is_sub;
|
||||
ulm.ta_offs_256bits = ta_offs_256bits;
|
||||
ulm.ber10k = ber10k;
|
||||
ulm.inv_rssi = inv_rssi;
|
||||
ulm.is_sub = is_sub;
|
||||
|
||||
/* we assume that symbol period is 1 bit: */
|
||||
set_ms_to_data(lchan, info_meas_ind->ta_offs_256bits / 256, true);
|
||||
set_ms_to_data(lchan, ta_offs_256bits / 256, true);
|
||||
|
||||
lchan_meas_process_measurement(lchan, &ulm, info_meas_ind->fn);
|
||||
lchan_meas_process_measurement(lchan, &ulm, fn);
|
||||
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* any L1 MPH_INFO indication prim received from bts model */
|
||||
@@ -685,7 +746,12 @@ static int l1sap_mph_info_ind(struct gsm_bts_trx *trx,
|
||||
&info->u.time_ind);
|
||||
break;
|
||||
case PRIM_INFO_MEAS:
|
||||
rc = l1sap_info_meas_ind(trx, l1sap, &info->u.meas_ind);
|
||||
/* We should never get an INFO_IND with PRIM_INFO_MEAS
|
||||
* when BTS_FEAT_MEAS_PAYLOAD_COMB is enabled */
|
||||
if (gsm_bts_has_feature(trx->bts, BTS_FEAT_MEAS_PAYLOAD_COMB))
|
||||
OSMO_ASSERT(false);
|
||||
|
||||
process_l1sap_meas_data(trx, l1sap, PRIM_MPH_INFO);
|
||||
break;
|
||||
default:
|
||||
LOGP(DL1P, LOGL_NOTICE, "unknown MPH_INFO ind type %d\n",
|
||||
@@ -1200,6 +1266,12 @@ static int l1sap_ph_data_ind(struct gsm_bts_trx *trx,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* The ph_data_param contained in the l1sap primitive may contain
|
||||
* measurement data. If this data is present, forward it for
|
||||
* processing */
|
||||
if (gsm_bts_has_feature(trx->bts, BTS_FEAT_MEAS_PAYLOAD_COMB))
|
||||
process_l1sap_meas_data(trx, l1sap, PRIM_PH_DATA);
|
||||
|
||||
if (ts_is_pdch(&trx->ts[tn])) {
|
||||
lchan = get_lchan_by_chan_nr(trx, chan_nr);
|
||||
if (!lchan)
|
||||
@@ -1283,8 +1355,7 @@ static int l1sap_ph_data_ind(struct gsm_bts_trx *trx,
|
||||
l1sap_tx_ciph_req(lchan->ts->trx, chan_nr, 1, 0);
|
||||
|
||||
/* SDCCH, SACCH and FACCH all go to LAPDm */
|
||||
msgb_pull(msg, (msg->l2h - msg->data));
|
||||
msg->l1h = NULL;
|
||||
msgb_pull_to_l2(msg);
|
||||
lapdm_phsap_up(&l1sap->oph, le);
|
||||
|
||||
/* don't free, because we forwarded data */
|
||||
@@ -1307,7 +1378,7 @@ static int l1sap_tch_ind(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap,
|
||||
|
||||
gsm_fn2gsmtime(&g_time, fn);
|
||||
|
||||
LOGPGT(DL1P, LOGL_INFO, &g_time, "Rx TCH.ind chan_nr=%s\n", rsl_chan_nr_str(chan_nr));
|
||||
LOGPGT(DL1P, LOGL_DEBUG, &g_time, "Rx TCH.ind chan_nr=%s\n", rsl_chan_nr_str(chan_nr));
|
||||
|
||||
lchan = get_active_lchan_by_chan_nr(trx, chan_nr);
|
||||
if (!lchan) {
|
||||
@@ -1315,7 +1386,13 @@ static int l1sap_tch_ind(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap,
|
||||
return 0;
|
||||
}
|
||||
|
||||
msgb_pull(msg, sizeof(*l1sap));
|
||||
/* The ph_tch_param contained in the l1sap primitive may contain
|
||||
* measurement data. If this data is present, forward it for
|
||||
* processing */
|
||||
if (gsm_bts_has_feature(trx->bts, BTS_FEAT_MEAS_PAYLOAD_COMB))
|
||||
process_l1sap_meas_data(trx, l1sap, PRIM_TCH);
|
||||
|
||||
msgb_pull_to_l2(msg);
|
||||
|
||||
/* Low level layers always call us when TCH content is expected, even if
|
||||
* the content is not available due to decoding issues. Content not
|
||||
@@ -1358,7 +1435,7 @@ static bool rach_pass_filter(struct ph_rach_ind_param *rach_ind, struct gsm_bts
|
||||
|
||||
/* Check for RACH exceeding BER threshold (ghost RACH) */
|
||||
if (rach_ind->ber10k > bts->max_ber10k_rach) {
|
||||
LOGPFN(DL1C, LOGL_INFO, rach_ind->fn, "Ignoring an Access Burst on %s: "
|
||||
LOGPFN(DL1C, LOGL_DEBUG, rach_ind->fn, "Ignoring an Access Burst on %s: "
|
||||
"BER10k(%u) > BER10k_MAX(%u)\n", chan_name,
|
||||
rach_ind->ber10k, bts->max_ber10k_rach);
|
||||
return false;
|
||||
@@ -1370,7 +1447,7 @@ static bool rach_pass_filter(struct ph_rach_ind_param *rach_ind, struct gsm_bts
|
||||
* according to maximal allowed Timing Advance value.
|
||||
*/
|
||||
if (toa256 < RACH_MIN_TOA256 || toa256 > bts->max_ta * 256) {
|
||||
LOGPFN(DL1C, LOGL_INFO, rach_ind->fn, "Ignoring an Access Burst on %s: "
|
||||
LOGPFN(DL1C, LOGL_DEBUG, rach_ind->fn, "Ignoring an Access Burst on %s: "
|
||||
"ToA(%d) exceeds the allowed range (%d..%d)\n", chan_name,
|
||||
toa256, RACH_MIN_TOA256, bts->max_ta * 256);
|
||||
return false;
|
||||
@@ -1378,7 +1455,7 @@ static bool rach_pass_filter(struct ph_rach_ind_param *rach_ind, struct gsm_bts
|
||||
|
||||
/* Link quality defined by C/I (Carrier-to-Interference ratio) */
|
||||
if (rach_ind->lqual_cb < bts->min_qual_rach) {
|
||||
LOGPFN(DL1C, LOGL_INFO, rach_ind->fn, "Ignoring an Access Burst on %s: "
|
||||
LOGPFN(DL1C, LOGL_DEBUG, rach_ind->fn, "Ignoring an Access Burst on %s: "
|
||||
"link quality (%d) below the minimum (%d)\n", chan_name,
|
||||
rach_ind->lqual_cb, bts->min_qual_rach);
|
||||
return false;
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <osmo-bts/measurement.h>
|
||||
#include <osmo-bts/scheduler.h>
|
||||
#include <osmo-bts/rsl.h>
|
||||
#include <osmo-bts/ta_control.h>
|
||||
|
||||
/* Tables as per TS 45.008 Section 8.3 */
|
||||
static const uint8_t ts45008_83_tch_f[] = { 52, 53, 54, 55, 56, 57, 58, 59 };
|
||||
@@ -655,14 +656,14 @@ int lchan_meas_check_compute(struct gsm_lchan *lchan, uint32_t fn)
|
||||
ber_full_sum = ber_full_sum / num_ul_meas;
|
||||
|
||||
if (!irssi_full_sum)
|
||||
ber_full_sum = MEASUREMENT_DUMMY_IRSSI;
|
||||
irssi_full_sum = MEASUREMENT_DUMMY_IRSSI;
|
||||
else
|
||||
irssi_full_sum = irssi_full_sum / num_ul_meas_actual;
|
||||
|
||||
if (!num_ul_meas_actual)
|
||||
ta256b_sum = lchan->meas.ms_toa256;
|
||||
else
|
||||
ta256b_sum = ta256b_sum / num_ul_meas_actual;
|
||||
ta256b_sum = ta256b_sum / (signed)num_ul_meas_actual;
|
||||
|
||||
if (!num_meas_sub)
|
||||
ber_sub_sum = MEASUREMENT_DUMMY_BER;
|
||||
@@ -696,6 +697,11 @@ int lchan_meas_check_compute(struct gsm_lchan *lchan, uint32_t fn)
|
||||
|
||||
lchan_meas_compute_extended(lchan);
|
||||
|
||||
/* Compute new ta_req value. This has to be done here since the value
|
||||
* in lchan->meas.num_ul_meas together with lchan->meas.ms_toa256
|
||||
* is needed for the computation. */
|
||||
lchan_ms_ta_ctrl(lchan);
|
||||
|
||||
lchan->meas.num_ul_meas = 0;
|
||||
|
||||
/* return 1 to indicate that the computation has been done and the next
|
||||
|
||||
@@ -1323,8 +1323,10 @@ static int rx_oml_ipa_rsl_connect(struct gsm_bts_trx *trx, struct msgb *msg,
|
||||
if (trx->bts->variant == BTS_OSMO_OMLDUMMY) {
|
||||
rc = 0;
|
||||
LOGP(DOML, LOGL_NOTICE, "%s: Not connecting RSL in OML-DUMMY!\n", trx_name);
|
||||
} else
|
||||
} else {
|
||||
trx->rsl_tei = stream_id;
|
||||
rc = e1inp_ipa_bts_rsl_connect_n(oml_link->ts->line, inet_ntoa(in), port, trx->nr);
|
||||
}
|
||||
if (rc < 0) {
|
||||
LOGP(DOML, LOGL_ERROR, "%s: Error in abis_open(RSL): %d\n", trx_name, rc);
|
||||
return oml_fom_ack_nack(msg, NM_NACK_CANT_PERFORM);
|
||||
|
||||
@@ -2009,7 +2009,14 @@ static int bind_rtp(struct gsm_bts *bts, struct osmo_rtp_socket *rs, const char
|
||||
|
||||
bts->rtp_port_range_next += 2;
|
||||
|
||||
if (rc == 0)
|
||||
if (rc != 0)
|
||||
continue;
|
||||
|
||||
if (bts->rtp_ip_dscp != -1) {
|
||||
if (osmo_rtp_socket_set_dscp(rs, bts->rtp_ip_dscp))
|
||||
LOGP(DRSL, LOGL_ERROR, "failed to set DSCP=%i: %s\n",
|
||||
bts->rtp_ip_dscp, strerror(errno));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2081,7 +2088,7 @@ static int rsl_rx_ipac_XXcx(struct msgb *msg)
|
||||
}
|
||||
|
||||
if (dch->c.msg_type == RSL_MT_IPAC_CRCX) {
|
||||
char cname[32];
|
||||
char cname[256+4];
|
||||
char *ipstr = NULL;
|
||||
if (lchan->abis_ip.rtp_socket) {
|
||||
LOGPLCHAN(lchan, DRSL, LOGL_ERROR, "Rx RSL IPAC CRCX, "
|
||||
|
||||
@@ -191,6 +191,7 @@ const struct trx_chan_desc trx_chan_desc[_TRX_CHAN_MAX] = {
|
||||
.rts_fn = rts_tchf_fn,
|
||||
.dl_fn = tx_tchf_fn,
|
||||
.ul_fn = rx_tchf_fn,
|
||||
.nope_fn = rx_tchf_fn,
|
||||
},
|
||||
[TRXC_TCHH_0] = {
|
||||
.name = "TCH/H(0)", /* 3GPP TS 05.02, section 3.2 */
|
||||
@@ -211,6 +212,7 @@ const struct trx_chan_desc trx_chan_desc[_TRX_CHAN_MAX] = {
|
||||
.rts_fn = rts_tchh_fn,
|
||||
.dl_fn = tx_tchh_fn,
|
||||
.ul_fn = rx_tchh_fn,
|
||||
.nope_fn = rx_tchh_fn,
|
||||
},
|
||||
[TRXC_TCHH_1] = {
|
||||
.name = "TCH/H(1)", /* 3GPP TS 05.02, section 3.2 */
|
||||
@@ -222,6 +224,7 @@ const struct trx_chan_desc trx_chan_desc[_TRX_CHAN_MAX] = {
|
||||
.rts_fn = rts_tchh_fn,
|
||||
.dl_fn = tx_tchh_fn,
|
||||
.ul_fn = rx_tchh_fn,
|
||||
.nope_fn = rx_tchh_fn,
|
||||
},
|
||||
[TRXC_SDCCH4_0] = {
|
||||
.name = "SDCCH/4(0)", /* 3GPP TS 05.02, section 3.3.4.1 */
|
||||
@@ -233,6 +236,7 @@ const struct trx_chan_desc trx_chan_desc[_TRX_CHAN_MAX] = {
|
||||
.rts_fn = rts_data_fn,
|
||||
.dl_fn = tx_data_fn,
|
||||
.ul_fn = rx_data_fn,
|
||||
.nope_fn = rx_data_fn,
|
||||
},
|
||||
[TRXC_SDCCH4_1] = {
|
||||
.name = "SDCCH/4(1)", /* 3GPP TS 05.02, section 3.3.4.1 */
|
||||
@@ -244,6 +248,7 @@ const struct trx_chan_desc trx_chan_desc[_TRX_CHAN_MAX] = {
|
||||
.rts_fn = rts_data_fn,
|
||||
.dl_fn = tx_data_fn,
|
||||
.ul_fn = rx_data_fn,
|
||||
.nope_fn = rx_data_fn,
|
||||
},
|
||||
[TRXC_SDCCH4_2] = {
|
||||
.name = "SDCCH/4(2)", /* 3GPP TS 05.02, section 3.3.4.1 */
|
||||
@@ -255,6 +260,7 @@ const struct trx_chan_desc trx_chan_desc[_TRX_CHAN_MAX] = {
|
||||
.rts_fn = rts_data_fn,
|
||||
.dl_fn = tx_data_fn,
|
||||
.ul_fn = rx_data_fn,
|
||||
.nope_fn = rx_data_fn,
|
||||
},
|
||||
[TRXC_SDCCH4_3] = {
|
||||
.name = "SDCCH/4(3)", /* 3GPP TS 05.02, section 3.3.4.1 */
|
||||
@@ -266,6 +272,7 @@ const struct trx_chan_desc trx_chan_desc[_TRX_CHAN_MAX] = {
|
||||
.rts_fn = rts_data_fn,
|
||||
.dl_fn = tx_data_fn,
|
||||
.ul_fn = rx_data_fn,
|
||||
.nope_fn = rx_data_fn,
|
||||
},
|
||||
[TRXC_SDCCH8_0] = {
|
||||
.name = "SDCCH/8(0)", /* 3GPP TS 05.02, section 3.3.4.1 */
|
||||
@@ -277,6 +284,7 @@ const struct trx_chan_desc trx_chan_desc[_TRX_CHAN_MAX] = {
|
||||
.rts_fn = rts_data_fn,
|
||||
.dl_fn = tx_data_fn,
|
||||
.ul_fn = rx_data_fn,
|
||||
.nope_fn = rx_data_fn,
|
||||
},
|
||||
[TRXC_SDCCH8_1] = {
|
||||
.name = "SDCCH/8(1)", /* 3GPP TS 05.02, section 3.3.4.1 */
|
||||
@@ -288,6 +296,7 @@ const struct trx_chan_desc trx_chan_desc[_TRX_CHAN_MAX] = {
|
||||
.rts_fn = rts_data_fn,
|
||||
.dl_fn = tx_data_fn,
|
||||
.ul_fn = rx_data_fn,
|
||||
.nope_fn = rx_data_fn,
|
||||
},
|
||||
[TRXC_SDCCH8_2] = {
|
||||
.name = "SDCCH/8(2)", /* 3GPP TS 05.02, section 3.3.4.1 */
|
||||
@@ -299,6 +308,7 @@ const struct trx_chan_desc trx_chan_desc[_TRX_CHAN_MAX] = {
|
||||
.rts_fn = rts_data_fn,
|
||||
.dl_fn = tx_data_fn,
|
||||
.ul_fn = rx_data_fn,
|
||||
.nope_fn = rx_data_fn,
|
||||
},
|
||||
[TRXC_SDCCH8_3] = {
|
||||
.name = "SDCCH/8(3)", /* 3GPP TS 05.02, section 3.3.4.1 */
|
||||
@@ -310,6 +320,7 @@ const struct trx_chan_desc trx_chan_desc[_TRX_CHAN_MAX] = {
|
||||
.rts_fn = rts_data_fn,
|
||||
.dl_fn = tx_data_fn,
|
||||
.ul_fn = rx_data_fn,
|
||||
.nope_fn = rx_data_fn,
|
||||
},
|
||||
[TRXC_SDCCH8_4] = {
|
||||
.name = "SDCCH/8(4)", /* 3GPP TS 05.02, section 3.3.4.1 */
|
||||
@@ -321,6 +332,7 @@ const struct trx_chan_desc trx_chan_desc[_TRX_CHAN_MAX] = {
|
||||
.rts_fn = rts_data_fn,
|
||||
.dl_fn = tx_data_fn,
|
||||
.ul_fn = rx_data_fn,
|
||||
.nope_fn = rx_data_fn,
|
||||
},
|
||||
[TRXC_SDCCH8_5] = {
|
||||
.name = "SDCCH/8(5)", /* 3GPP TS 05.02, section 3.3.4.1 */
|
||||
@@ -332,6 +344,7 @@ const struct trx_chan_desc trx_chan_desc[_TRX_CHAN_MAX] = {
|
||||
.rts_fn = rts_data_fn,
|
||||
.dl_fn = tx_data_fn,
|
||||
.ul_fn = rx_data_fn,
|
||||
.nope_fn = rx_data_fn,
|
||||
},
|
||||
[TRXC_SDCCH8_6] = {
|
||||
.name = "SDCCH/8(6)", /* 3GPP TS 05.02, section 3.3.4.1 */
|
||||
@@ -343,6 +356,7 @@ const struct trx_chan_desc trx_chan_desc[_TRX_CHAN_MAX] = {
|
||||
.rts_fn = rts_data_fn,
|
||||
.dl_fn = tx_data_fn,
|
||||
.ul_fn = rx_data_fn,
|
||||
.nope_fn = rx_data_fn,
|
||||
},
|
||||
[TRXC_SDCCH8_7] = {
|
||||
.name = "SDCCH/8(7)", /* 3GPP TS 05.02, section 3.3.4.1 */
|
||||
@@ -354,6 +368,7 @@ const struct trx_chan_desc trx_chan_desc[_TRX_CHAN_MAX] = {
|
||||
.rts_fn = rts_data_fn,
|
||||
.dl_fn = tx_data_fn,
|
||||
.ul_fn = rx_data_fn,
|
||||
.nope_fn = rx_data_fn,
|
||||
},
|
||||
[TRXC_SACCHTF] = {
|
||||
.name = "SACCH/TF", /* 3GPP TS 05.02, section 3.3.4.1 */
|
||||
@@ -753,7 +768,8 @@ int _sched_compose_ph_data_ind(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
||||
}
|
||||
|
||||
int _sched_compose_tch_ind(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
||||
enum trx_chan_type chan, uint8_t *tch, uint8_t tch_len)
|
||||
enum trx_chan_type chan, uint8_t *tch, uint8_t tch_len,
|
||||
int16_t ta_offs_256bits, uint16_t ber10k, float rssi)
|
||||
{
|
||||
struct msgb *msg;
|
||||
struct osmo_phsap_prim *l1sap;
|
||||
@@ -769,6 +785,10 @@ int _sched_compose_tch_ind(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
||||
PRIM_OP_INDICATION, msg);
|
||||
l1sap->u.tch.chan_nr = chan_nr;
|
||||
l1sap->u.tch.fn = fn;
|
||||
l1sap->u.tch.rssi = (int8_t) (rssi);
|
||||
l1sap->u.tch.ber10k = ber10k;
|
||||
l1sap->u.tch.ta_offs_256bits = ta_offs_256bits;
|
||||
|
||||
msg->l2h = msgb_put(msg, tch_len);
|
||||
if (tch_len)
|
||||
memcpy(msg->l2h, tch, tch_len);
|
||||
|
||||
@@ -156,7 +156,7 @@ uint8_t num_agch(struct gsm_bts_trx *trx, const char * arg)
|
||||
si3 = GSM_BTS_SI(b, SYSINFO_TYPE_3);
|
||||
return si3->control_channel_desc.bs_ag_blks_res;
|
||||
}
|
||||
LOGP(DL1P, LOGL_ERROR, "%s: Unable to determine actual BS_AG_BLKS_RES "
|
||||
LOGP(DL1P, LOGL_NOTICE, "%s: Unable to determine actual BS_AG_BLKS_RES "
|
||||
"value as SI3 is not available yet, fallback to 1\n", arg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
55
src/common/ta_control.c
Normal file
55
src/common/ta_control.c
Normal file
@@ -0,0 +1,55 @@
|
||||
/* Loop control for Timing Advance */
|
||||
|
||||
/* (C) 2013 by Andreas Eversberg <jolly@eversberg.eu>
|
||||
*
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation; either version 3 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 Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <osmo-bts/gsm_data.h>
|
||||
#include <osmo-bts/logging.h>
|
||||
|
||||
/* 90% of one bit duration in 1/256 symbols: 256*0.9 */
|
||||
#define TOA256_9OPERCENT 230
|
||||
|
||||
/* rqd_ta value range */
|
||||
#define TOA_MIN 0
|
||||
#define TOA_MAX 63
|
||||
|
||||
void lchan_ms_ta_ctrl(struct gsm_lchan *lchan)
|
||||
{
|
||||
int16_t toa256 = lchan->meas.ms_toa256;
|
||||
|
||||
/* Do not perform any computation when the amount of measurement
|
||||
* results is too little. */
|
||||
if (lchan->meas.num_ul_meas < 4)
|
||||
return;
|
||||
|
||||
if (toa256 < -TOA256_9OPERCENT && lchan->rqd_ta > TOA_MIN) {
|
||||
LOGPLCHAN(lchan, DLOOP, LOGL_INFO,
|
||||
"TOA is too early (%d), now lowering TA from %d to %d\n",
|
||||
toa256, lchan->rqd_ta, lchan->rqd_ta - 1);
|
||||
lchan->rqd_ta--;
|
||||
} else if (toa256 > TOA256_9OPERCENT && lchan->rqd_ta < TOA_MAX) {
|
||||
LOGPLCHAN(lchan, DLOOP, LOGL_INFO,
|
||||
"TOA is too late (%d), now raising TA from %d to %d\n",
|
||||
toa256, lchan->rqd_ta, lchan->rqd_ta + 1);
|
||||
lchan->rqd_ta++;
|
||||
} else
|
||||
LOGPLCHAN(lchan, DLOOP, LOGL_DEBUG,
|
||||
"TOA is correct (%d), keeping current TA of %d\n",
|
||||
toa256, lchan->rqd_ta);
|
||||
}
|
||||
@@ -125,48 +125,6 @@ int bts_vty_is_config_node(struct vty *vty, int node)
|
||||
}
|
||||
}
|
||||
|
||||
gDEFUN(ournode_exit, ournode_exit_cmd, "exit",
|
||||
"Exit current node, go down to provious node")
|
||||
{
|
||||
switch (vty->node) {
|
||||
case PHY_INST_NODE:
|
||||
vty->node = PHY_NODE;
|
||||
{
|
||||
struct phy_instance *pinst = vty->index;
|
||||
vty->index = pinst->phy_link;
|
||||
}
|
||||
break;
|
||||
case PHY_NODE:
|
||||
vty->node = CONFIG_NODE;
|
||||
vty->index = NULL;
|
||||
break;
|
||||
case TRX_NODE:
|
||||
vty->node = BTS_NODE;
|
||||
{
|
||||
struct gsm_bts_trx *trx = vty->index;
|
||||
vty->index = trx->bts;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
gDEFUN(ournode_end, ournode_end_cmd, "end",
|
||||
"End current mode and change to enable mode")
|
||||
{
|
||||
switch (vty->node) {
|
||||
default:
|
||||
vty_config_unlock(vty);
|
||||
vty->node = ENABLE_NODE;
|
||||
vty->index = NULL;
|
||||
vty->index_sub = NULL;
|
||||
break;
|
||||
}
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
static const char osmobts_copyright[] =
|
||||
"Copyright (C) 2010, 2011 by Harald Welte, Andreas Eversberg and On-Waves\r\n"
|
||||
"License AGPLv3+: GNU AGPL version 3 or later <http://gnu.org/licenses/agpl-3.0.html>\r\n"
|
||||
@@ -279,6 +237,8 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts)
|
||||
vty_out(vty, "%s", VTY_NEWLINE);
|
||||
vty_out(vty, " rtp port-range %u %u%s", bts->rtp_port_range_start,
|
||||
bts->rtp_port_range_end, VTY_NEWLINE);
|
||||
if (bts->rtp_ip_dscp != -1)
|
||||
vty_out(vty, " rtp ip-dscp %i%s", bts->rtp_ip_dscp, VTY_NEWLINE);
|
||||
vty_out(vty, " paging queue-size %u%s", paging_get_queue_max(bts->paging_state),
|
||||
VTY_NEWLINE);
|
||||
vty_out(vty, " paging lifetime %u%s", paging_get_lifetime(bts->paging_state),
|
||||
@@ -292,7 +252,7 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts)
|
||||
bts->agch_queue.high_level, VTY_NEWLINE);
|
||||
|
||||
for (i = 0; i < 32; i++) {
|
||||
if (gsmtap_sapi_mask & (1 << i)) {
|
||||
if (gsmtap_sapi_mask & ((uint32_t) 1 << i)) {
|
||||
sapi_buf = osmo_str_tolower(get_value_string(gsmtap_sapi_names, i));
|
||||
vty_out(vty, " gsmtap-sapi %s%s", sapi_buf, VTY_NEWLINE);
|
||||
}
|
||||
@@ -543,6 +503,19 @@ DEFUN(cfg_bts_rtp_port_range,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_bts_rtp_ip_dscp,
|
||||
cfg_bts_rtp_ip_dscp_cmd,
|
||||
"rtp ip-dscp <0-63>",
|
||||
RTP_STR "Specify DSCP for RTP/IP packets\n" "The DSCP value (upper 6 bits of TOS)\n")
|
||||
{
|
||||
struct gsm_bts *bts = vty->index;
|
||||
int dscp = atoi(argv[0]);
|
||||
|
||||
bts->rtp_ip_dscp = dscp;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
#define PAG_STR "Paging related parameters\n"
|
||||
|
||||
DEFUN(cfg_bts_paging_queue_size,
|
||||
@@ -955,6 +928,25 @@ DEFUN(show_bts, show_bts_cmd, "show bts <0-255>",
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(test_send_failure_event_report, test_send_failure_event_report_cmd, "test send-failure-event-report <0-255>",
|
||||
"Various testing commands\n"
|
||||
"Send a test OML failure event report to the BSC\n" BTS_NR_STR)
|
||||
{
|
||||
struct gsm_network *net = gsmnet_from_vty(vty);
|
||||
int bts_nr = atoi(argv[0]);
|
||||
struct gsm_bts *bts;
|
||||
|
||||
if (bts_nr >= net->num_bts) {
|
||||
vty_out(vty, "%% can't find BTS '%s'%s", argv[0], VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
bts = gsm_bts_num(net, bts_nr);
|
||||
oml_tx_failure_event_rep(&bts->mo, NM_SEVER_MINOR, OSMO_EVT_WARN_SW_WARN, "test message sent from VTY");
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
static void trx_dump_vty(struct vty *vty, struct gsm_bts_trx *trx)
|
||||
{
|
||||
vty_out(vty, "TRX %u of BTS %u is on ARFCN %u%s",
|
||||
@@ -1707,6 +1699,7 @@ int bts_vty_init(struct gsm_bts *bts)
|
||||
install_element(BTS_NODE, &cfg_bts_rtp_bind_ip_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_rtp_jitbuf_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_rtp_port_range_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_rtp_ip_dscp_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_band_cmd);
|
||||
install_element(BTS_NODE, &cfg_description_cmd);
|
||||
install_element(BTS_NODE, &cfg_no_description_cmd);
|
||||
@@ -1742,6 +1735,7 @@ int bts_vty_init(struct gsm_bts *bts)
|
||||
install_element(ENABLE_NODE, &bts_t_t_l_jitter_buf_cmd);
|
||||
install_element(ENABLE_NODE, &bts_t_t_l_loopback_cmd);
|
||||
install_element(ENABLE_NODE, &no_bts_t_t_l_loopback_cmd);
|
||||
install_element(ENABLE_NODE, &test_send_failure_event_report_cmd);
|
||||
|
||||
install_element(CONFIG_NODE, &cfg_phy_cmd);
|
||||
install_node(&phy_node, config_write_phy);
|
||||
|
||||
@@ -936,12 +936,8 @@ empty_frame:
|
||||
goto tx;
|
||||
}
|
||||
|
||||
static void dump_meas_res(int ll, GsmL1_MeasParam_t *m)
|
||||
{
|
||||
LOGPC(DL1C, ll, ", Meas: RSSI %-3.2f dBm, Qual %-3.2f dB, "
|
||||
"BER %-3.2f, Timing %d\n", m->fRssi, m->fLinkQuality,
|
||||
m->fBer, m->i16BurstTiming);
|
||||
}
|
||||
#define LOG_FMT_MEAS "Meas: RSSI %-3.2f dBm, Qual %-3.2f dB, BER %-3.2f, Timing %d"
|
||||
#define LOG_PARAM_MEAS(meas_param) (meas_param)->fRssi, (meas_param)->fLinkQuality, (meas_param)->fBer, (meas_param)->i16BurstTiming
|
||||
|
||||
static int process_meas_res(struct gsm_bts_trx *trx, uint8_t chan_nr,
|
||||
GsmL1_MeasParam_t *m, uint32_t fn)
|
||||
@@ -992,10 +988,10 @@ static int handle_ph_data_ind(struct lc15l1_hdl *fl1, GsmL1_PhDataInd_t *data_in
|
||||
process_meas_res(trx, chan_nr, &data_ind->measParam, fn);
|
||||
|
||||
|
||||
DEBUGPGT(DL1P, &g_time, "Rx PH-DATA.ind %s (hL2 %08x): %s\n",
|
||||
DEBUGPGT(DL1P, &g_time, "Rx PH-DATA.ind %s (hL2 %08x): %s, " LOG_FMT_MEAS "\n",
|
||||
get_value_string(lc15bts_l1sapi_names, data_ind->sapi), (uint32_t)data_ind->hLayer2,
|
||||
osmo_hexdump(data_ind->msgUnitParam.u8Buffer, data_ind->msgUnitParam.u8Size));
|
||||
dump_meas_res(LOGL_DEBUG, &data_ind->measParam);
|
||||
osmo_hexdump(data_ind->msgUnitParam.u8Buffer, data_ind->msgUnitParam.u8Size),
|
||||
LOG_PARAM_MEAS(&data_ind->measParam));
|
||||
|
||||
/* check for TCH */
|
||||
if (data_ind->sapi == GsmL1_Sapi_TchF
|
||||
@@ -1028,11 +1024,10 @@ static int handle_ph_data_ind(struct lc15l1_hdl *fl1, GsmL1_PhDataInd_t *data_in
|
||||
l1sap->u.data.chan_nr = chan_nr;
|
||||
l1sap->u.data.fn = fn;
|
||||
l1sap->u.data.rssi = rssi;
|
||||
if (!pcu_direct) {
|
||||
l1sap->u.data.ber10k = data_ind->measParam.fBer * 10000;
|
||||
l1sap->u.data.ta_offs_256bits = data_ind->measParam.i16BurstTiming*64;
|
||||
l1sap->u.data.lqual_cb = data_ind->measParam.fLinkQuality * 10;
|
||||
}
|
||||
|
||||
return l1sap_up(trx, l1sap);
|
||||
}
|
||||
|
||||
@@ -1046,7 +1041,8 @@ static int handle_ph_ra_ind(struct lc15l1_hdl *fl1, GsmL1_PhRaInd_t *ra_ind,
|
||||
struct ph_rach_ind_param rach_ind_param;
|
||||
|
||||
set_log_ctx_sapi(ra_ind->sapi);
|
||||
dump_meas_res(LOGL_DEBUG, &ra_ind->measParam);
|
||||
LOGPFN(DL1C, LOGL_DEBUG, ra_ind->u32Fn, "Rx PH-RA.ind, " LOG_FMT_MEAS "\n",
|
||||
LOG_PARAM_MEAS(&ra_ind->measParam));
|
||||
|
||||
if ((ra_ind->msgUnitParam.u8Size != 1) &&
|
||||
(ra_ind->msgUnitParam.u8Size != 2)) {
|
||||
@@ -1267,8 +1263,10 @@ static int activate_rf_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp,
|
||||
LOGP(DL1C, LOGL_FATAL, "RF-ACT.conf with status %s\n",
|
||||
get_value_string(lc15bts_l1status_names, status));
|
||||
bts_shutdown(trx->bts, "RF-ACT failure");
|
||||
} else
|
||||
} else {
|
||||
if(trx->bts->lc15.led_ctrl_mode == LC15_LED_CONTROL_BTS)
|
||||
bts_update_status(BTS_STATUS_RF_ACTIVE, 1);
|
||||
}
|
||||
|
||||
/* signal availability */
|
||||
oml_mo_state_chg(&trx->mo, NM_OPSTATE_DISABLED, NM_AVSTATE_OK);
|
||||
@@ -1279,6 +1277,7 @@ static int activate_rf_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp,
|
||||
for (i = 0; i < ARRAY_SIZE(trx->ts); i++)
|
||||
oml_mo_state_chg(&trx->ts[i].mo, NM_OPSTATE_DISABLED, NM_AVSTATE_DEPENDENCY);
|
||||
} else {
|
||||
if(trx->bts->lc15.led_ctrl_mode == LC15_LED_CONTROL_BTS)
|
||||
bts_update_status(BTS_STATUS_RF_ACTIVE, 0);
|
||||
oml_mo_state_chg(&trx->mo, NM_OPSTATE_DISABLED, NM_AVSTATE_OFF_LINE);
|
||||
oml_mo_state_chg(&trx->bb_transc.mo, NM_OPSTATE_DISABLED, NM_AVSTATE_OFF_LINE);
|
||||
@@ -1294,17 +1293,27 @@ int l1if_activate_rf(struct lc15l1_hdl *hdl, int on)
|
||||
{
|
||||
struct msgb *msg = sysp_msgb_alloc();
|
||||
Litecell15_Prim_t *sysp = msgb_sysprim(msg);
|
||||
struct phy_instance *pinst = hdl->phy_inst;
|
||||
|
||||
if (on) {
|
||||
sysp->id = Litecell15_PrimId_ActivateRfReq;
|
||||
sysp->u.activateRfReq.msgq.u8UseTchMsgq = 0;
|
||||
sysp->u.activateRfReq.msgq.u8UsePdtchMsgq = pcu_direct;
|
||||
|
||||
sysp->u.activateRfReq.u8UnusedTsMode = 0;
|
||||
sysp->u.activateRfReq.u8UnusedTsMode = pinst->u.lc15.pedestal_mode;
|
||||
sysp->u.activateRfReq.u8McCorrMode = 0;
|
||||
|
||||
/* diversity mode: 0: SISO-A, 1: SISO-B, 2: MRC */
|
||||
sysp->u.activateRfReq.u8DiversityMode = pinst->u.lc15.diversity_mode;
|
||||
|
||||
/* maximum cell size in quarter-bits, 90 == 12.456 km */
|
||||
sysp->u.activateRfReq.u8MaxCellSize = 90;
|
||||
sysp->u.activateRfReq.u8MaxCellSize = pinst->u.lc15.max_cell_size;
|
||||
|
||||
/* auto tx power adjustment mode 0:none, 1: automatic*/
|
||||
sysp->u.activateRfReq.autoPowerAdjust.u8EnAutoPowerAdjust = pinst->u.lc15.tx_pwr_adj_mode;
|
||||
|
||||
/* PSK modulation scheme maximum power level */
|
||||
sysp->u.activateRfReq.autoPowerAdjust.u8PowerReduction8Psk = pinst->u.lc15.tx_pwr_red_8psk;
|
||||
} else {
|
||||
sysp->id = Litecell15_PrimId_DeactivateRfReq;
|
||||
}
|
||||
@@ -1357,6 +1366,7 @@ static int mute_rf_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp,
|
||||
|
||||
LOGP(DL1C, LOGL_INFO, "Rx RF-MUTE.conf with status=%s\n",
|
||||
get_value_string(lc15bts_l1status_names, status));
|
||||
if(trx->bts->lc15.led_ctrl_mode == LC15_LED_CONTROL_BTS)
|
||||
bts_update_status(BTS_STATUS_RF_MUTE, fl1h->last_rf_mute[0]);
|
||||
oml_mo_rf_lock_chg(&trx->mo, fl1h->last_rf_mute, 1);
|
||||
|
||||
@@ -1593,6 +1603,53 @@ int l1if_close(struct lc15l1_hdl *fl1h)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dsp_alive_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp, void *data)
|
||||
{
|
||||
Litecell15_Prim_t *sysp = msgb_sysprim(resp);
|
||||
Litecell15_IsAliveCnf_t *sac = &sysp->u.IsAliveCnf;
|
||||
struct lc15l1_hdl *fl1h = trx_lc15l1_hdl(trx);
|
||||
|
||||
fl1h->hw_alive.dsp_alive_cnt++;
|
||||
LOGP(DL1C, LOGL_NOTICE, "Rx SYS prim %s, status=%d (%d)\n",
|
||||
get_value_string(lc15bts_sysprim_names, sysp->id), sac->status, trx->nr);
|
||||
|
||||
msgb_free(resp);
|
||||
}
|
||||
|
||||
static int dsp_alive_timer_cb(void *data)
|
||||
{
|
||||
struct lc15l1_hdl *fl1h = data;
|
||||
struct gsm_bts_trx *trx = fl1h->phy_inst->trx;
|
||||
struct msgb *msg = sysp_msgb_alloc();
|
||||
int rc;
|
||||
|
||||
Litecell15_Prim_t *sys_prim = msgb_sysprim(msg);
|
||||
sys_prim->id = Litecell15_PrimId_IsAliveReq;
|
||||
|
||||
if (fl1h->hw_alive.dsp_alive_cnt == 0) {
|
||||
|
||||
LOGP(DL1C, LOGL_ERROR, "Timeout waiting for SYS prim %s primitive (%d)\n",
|
||||
get_value_string(lc15bts_sysprim_names, sys_prim->id + 1), trx->nr);
|
||||
|
||||
exit(23);
|
||||
}
|
||||
|
||||
LOGP(DL1C, LOGL_NOTICE, "Tx SYS prim %s (%d)\n",
|
||||
get_value_string(lc15bts_sysprim_names, sys_prim->id), trx->nr);
|
||||
|
||||
rc = l1if_req_compl(fl1h, msg, dsp_alive_compl_cb, NULL);
|
||||
if (rc < 0) {
|
||||
LOGP(DL1C, LOGL_FATAL, "Failed to send %s primitive\n", get_value_string(lc15bts_sysprim_names, sys_prim->id));
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* restart timer */
|
||||
fl1h->hw_alive.dsp_alive_cnt = 0;
|
||||
osmo_timer_schedule(&fl1h->hw_alive.dsp_alive_timer, fl1h->hw_alive.dsp_alive_period, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bts_model_phy_link_open(struct phy_link *plink)
|
||||
{
|
||||
struct phy_instance *pinst = phy_instance_by_num(plink, 0);
|
||||
@@ -1612,6 +1669,24 @@ int bts_model_phy_link_open(struct phy_link *plink)
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* Set default PHY parameters */
|
||||
if (!pinst->u.lc15.max_cell_size)
|
||||
pinst->u.lc15.max_cell_size = LC15_BTS_MAX_CELL_SIZE_DEFAULT;
|
||||
|
||||
if (!pinst->u.lc15.diversity_mode)
|
||||
pinst->u.lc15.diversity_mode = LC15_BTS_DIVERSITY_MODE_DEFAULT;
|
||||
|
||||
if (!pinst->u.lc15.pedestal_mode)
|
||||
pinst->u.lc15.pedestal_mode = LC15_BTS_PEDESTAL_MODE_DEFAULT;
|
||||
|
||||
if (!pinst->u.lc15.dsp_alive_period)
|
||||
pinst->u.lc15.dsp_alive_period = LC15_BTS_DSP_ALIVE_TMR_DEFAULT;
|
||||
|
||||
if (!pinst->u.lc15.tx_pwr_adj_mode)
|
||||
pinst->u.lc15.tx_pwr_adj_mode = LC15_BTS_TX_PWR_ADJ_DEFAULT;
|
||||
|
||||
if (!pinst->u.lc15.tx_pwr_red_8psk)
|
||||
pinst->u.lc15.tx_pwr_red_8psk = LC15_BTS_TX_RED_PWR_8PSK_DEFAULT;
|
||||
|
||||
struct lc15l1_hdl *fl1h = pinst->u.lc15.hdl;
|
||||
fl1h->dsp_trace_f = dsp_trace;
|
||||
@@ -1620,5 +1695,24 @@ int bts_model_phy_link_open(struct phy_link *plink)
|
||||
|
||||
phy_link_state_set(plink, PHY_LINK_CONNECTED);
|
||||
|
||||
/* Send first IS_ALIVE primitive */
|
||||
struct msgb *msg = sysp_msgb_alloc();
|
||||
int rc;
|
||||
|
||||
Litecell15_Prim_t *sys_prim = msgb_sysprim(msg);
|
||||
sys_prim->id = Litecell15_PrimId_IsAliveReq;
|
||||
|
||||
rc = l1if_req_compl(fl1h, msg, dsp_alive_compl_cb, NULL);
|
||||
if (rc < 0) {
|
||||
LOGP(DL1C, LOGL_FATAL, "Failed to send %s primitive\n", get_value_string(lc15bts_sysprim_names, sys_prim->id));
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* initialize DSP heart beat alive timer */
|
||||
fl1h->hw_alive.dsp_alive_timer.cb = dsp_alive_timer_cb;
|
||||
fl1h->hw_alive.dsp_alive_timer.data = fl1h;
|
||||
fl1h->hw_alive.dsp_alive_cnt = 0;
|
||||
fl1h->hw_alive.dsp_alive_period = pinst->u.lc15.dsp_alive_period;
|
||||
osmo_timer_schedule(&fl1h->hw_alive.dsp_alive_timer, fl1h->hw_alive.dsp_alive_period, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -62,6 +62,12 @@ struct lc15l1_hdl {
|
||||
struct calib_send_state st;
|
||||
|
||||
uint8_t last_rf_mute[8];
|
||||
|
||||
struct {
|
||||
struct osmo_timer_list dsp_alive_timer;
|
||||
unsigned int dsp_alive_cnt;
|
||||
uint8_t dsp_alive_period;
|
||||
} hw_alive;
|
||||
};
|
||||
|
||||
#define msgb_l1prim(msg) ((GsmL1_Prim_t *)(msg)->l1h)
|
||||
|
||||
@@ -121,6 +121,8 @@ enum l1prim_type lc15bts_get_sysprim_type(Litecell15_PrimId_t id)
|
||||
case Litecell15_PrimId_MuteRfCnf: return L1P_T_CONF;
|
||||
case Litecell15_PrimId_SetRxAttenReq: return L1P_T_REQ;
|
||||
case Litecell15_PrimId_SetRxAttenCnf: return L1P_T_CONF;
|
||||
case Litecell15_PrimId_IsAliveReq: return L1P_T_REQ;
|
||||
case Litecell15_PrimId_IsAliveCnf: return L1P_T_CONF;
|
||||
default: return L1P_T_INVALID;
|
||||
}
|
||||
}
|
||||
@@ -142,6 +144,8 @@ const struct value_string lc15bts_sysprim_names[Litecell15_PrimId_NUM+1] = {
|
||||
{ Litecell15_PrimId_MuteRfCnf, "MUTE-RF.cnf" },
|
||||
{ Litecell15_PrimId_SetRxAttenReq, "SET-RX-ATTEN.req" },
|
||||
{ Litecell15_PrimId_SetRxAttenCnf, "SET-RX-ATTEN-CNF.cnf" },
|
||||
{ Litecell15_PrimId_IsAliveReq, "IS-ALIVE.req" },
|
||||
{ Litecell15_PrimId_IsAliveCnf, "IS-ALIVE-CNF.cnf" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
@@ -155,6 +159,7 @@ Litecell15_PrimId_t lc15bts_get_sysprim_conf(Litecell15_PrimId_t id)
|
||||
case Litecell15_PrimId_SetCalibTblReq: return Litecell15_PrimId_SetCalibTblCnf;
|
||||
case Litecell15_PrimId_MuteRfReq: return Litecell15_PrimId_MuteRfCnf;
|
||||
case Litecell15_PrimId_SetRxAttenReq: return Litecell15_PrimId_SetRxAttenCnf;
|
||||
case Litecell15_PrimId_IsAliveReq: return Litecell15_PrimId_IsAliveCnf;
|
||||
default: return -1; // Weak
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,27 @@ enum l1prim_type {
|
||||
L1P_T_IND,
|
||||
};
|
||||
|
||||
enum lc15_diversity_mode{
|
||||
LC15_DIVERSITY_SISO_A = 0,
|
||||
LC15_DIVERSITY_SISO_B,
|
||||
LC15_DIVERSITY_MRC,
|
||||
};
|
||||
|
||||
enum lc15_pedestal_mode{
|
||||
LC15_PEDESTAL_OFF = 0,
|
||||
LC15_PEDESTAL_ON,
|
||||
};
|
||||
|
||||
enum lc15_led_control_mode{
|
||||
LC15_LED_CONTROL_BTS = 0,
|
||||
LC15_LED_CONTROL_EXT,
|
||||
};
|
||||
|
||||
enum lc15_auto_pwr_adjust_mode{
|
||||
LC15_TX_PWR_ADJ_NONE = 0,
|
||||
LC15_TX_PWR_ADJ_AUTO,
|
||||
};
|
||||
|
||||
enum l1prim_type lc15bts_get_l1prim_type(GsmL1_PrimId_t id);
|
||||
const struct value_string lc15bts_l1prim_names[GsmL1_PrimId_NUM+1];
|
||||
GsmL1_PrimId_t lc15bts_get_l1prim_conf(GsmL1_PrimId_t id);
|
||||
@@ -61,4 +82,13 @@ enum pdch_cs {
|
||||
|
||||
const uint8_t pdch_msu_size[_NUM_PDCH_CS];
|
||||
|
||||
/* LC15 default parameters */
|
||||
#define LC15_BTS_MAX_CELL_SIZE_DEFAULT 166 /* 166 qbits is default value */
|
||||
#define LC15_BTS_DIVERSITY_MODE_DEFAULT 0 /* SISO-A is default mode */
|
||||
#define LC15_BTS_PEDESTAL_MODE_DEFAULT 0 /* Unused TS is off by default */
|
||||
#define LC15_BTS_LED_CTRL_MODE_DEFAULT 0 /* LED is controlled by BTS by default */
|
||||
#define LC15_BTS_DSP_ALIVE_TMR_DEFAULT 5 /* Default DSP alive timer is 5 seconds */
|
||||
#define LC15_BTS_TX_PWR_ADJ_DEFAULT 0 /* Default Tx power auto adjustment is none */
|
||||
#define LC15_BTS_TX_RED_PWR_8PSK_DEFAULT 0 /* Default 8-PSK maximum power level is 0 dB */
|
||||
|
||||
#endif /* LC15BTS_H */
|
||||
|
||||
@@ -65,6 +65,31 @@ extern int lchan_activate(struct gsm_lchan *lchan);
|
||||
|
||||
static struct gsm_bts *vty_bts;
|
||||
|
||||
static const struct value_string lc15_diversity_mode_strs[] = {
|
||||
{ LC15_DIVERSITY_SISO_A, "siso-a" },
|
||||
{ LC15_DIVERSITY_SISO_B, "siso-b" },
|
||||
{ LC15_DIVERSITY_MRC, "mrc" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
static const struct value_string lc15_pedestal_mode_strs[] = {
|
||||
{ LC15_PEDESTAL_OFF, "off" },
|
||||
{ LC15_PEDESTAL_ON, "on" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
static const struct value_string lc15_led_mode_strs[] = {
|
||||
{ LC15_LED_CONTROL_BTS, "bts" },
|
||||
{ LC15_LED_CONTROL_EXT, "external" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
static const struct value_string lc15_auto_adj_pwr_strs[] = {
|
||||
{ LC15_TX_PWR_ADJ_NONE, "none" },
|
||||
{ LC15_TX_PWR_ADJ_AUTO, "auto" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
/* configuration */
|
||||
|
||||
DEFUN(cfg_phy_cal_path, cfg_phy_cal_path_cmd,
|
||||
@@ -321,8 +346,130 @@ DEFUN(cfg_trx_nominal_power, cfg_trx_nominal_power_cmd,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_phy_max_cell_size, cfg_phy_max_cell_size_cmd,
|
||||
"max-cell-size <0-166>",
|
||||
"Set the maximum cell size in qbits\n")
|
||||
{
|
||||
struct phy_instance *pinst = vty->index;
|
||||
int cell_size = (uint8_t)atoi(argv[0]);
|
||||
|
||||
if (( cell_size > 166 ) || ( cell_size < 0 )) {
|
||||
vty_out(vty, "Max cell size must be between 0 and 166 qbits (%d) %s",
|
||||
cell_size, VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
pinst->u.lc15.max_cell_size = (uint8_t)cell_size;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_phy_diversity_mode, cfg_phy_diversity_mode_cmd,
|
||||
"diversity-mode (siso-a|siso-b|mrc)",
|
||||
"Set reception diversity mode \n"
|
||||
"Reception diversity mode can be (siso-a, siso-b, mrc)\n")
|
||||
{
|
||||
struct phy_instance *pinst = vty->index;
|
||||
int val = get_string_value(lc15_diversity_mode_strs, argv[0]);
|
||||
|
||||
if((val < LC15_DIVERSITY_SISO_A) || (val > LC15_DIVERSITY_MRC)) {
|
||||
vty_out(vty, "Invalid reception diversity mode %d%s", val, VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
pinst->u.lc15.diversity_mode = (uint8_t)val;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_phy_pedestal_mode, cfg_phy_pedestal_mode_cmd,
|
||||
"pedestal-mode (on|off)",
|
||||
"Set unused time-slot transmission in pedestal mode\n"
|
||||
"Transmission pedestal mode can be (off, on)\n")
|
||||
{
|
||||
struct phy_instance *pinst = vty->index;
|
||||
int val = get_string_value(lc15_pedestal_mode_strs, argv[0]);
|
||||
|
||||
if((val < LC15_PEDESTAL_OFF) || (val > LC15_PEDESTAL_ON)) {
|
||||
vty_out(vty, "Invalid unused time-slot transmission mode %d%s", val, VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
pinst->u.lc15.pedestal_mode = (uint8_t)val;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_bts_led_mode, cfg_bts_led_mode_cmd,
|
||||
"led-control-mode (bts|external)",
|
||||
"Set LED controlled by BTS or external software\n"
|
||||
"LED can be controlled by (bts, external)\n")
|
||||
{
|
||||
struct gsm_bts *bts = vty->index;
|
||||
int val = get_string_value(lc15_led_mode_strs, argv[0]);
|
||||
|
||||
if((val < LC15_LED_CONTROL_BTS) || (val > LC15_LED_CONTROL_EXT)) {
|
||||
vty_out(vty, "Invalid LED control mode %d%s", val, VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
bts->lc15.led_ctrl_mode = (uint8_t)val;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_phy_dsp_alive_timer, cfg_phy_dsp_alive_timer_cmd,
|
||||
"dsp-alive-period <0-60>",
|
||||
"Set DSP alive timer period in second\n")
|
||||
{
|
||||
struct phy_instance *pinst = vty->index;
|
||||
uint8_t period = (uint8_t)atoi(argv[0]);
|
||||
|
||||
if (( period > 60 ) || ( period < 0 )) {
|
||||
vty_out(vty, "DSP heart beat alive timer period must be between 0 and 60 seconds (%d) %s",
|
||||
period, VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
pinst->u.lc15.dsp_alive_period = period;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_phy_auto_tx_pwr_adj, cfg_phy_auto_tx_pwr_adj_cmd,
|
||||
"pwr-adj-mode (none|auto)",
|
||||
"Set output power adjustment mode\n")
|
||||
{
|
||||
struct phy_instance *pinst = vty->index;
|
||||
int val = get_string_value(lc15_auto_adj_pwr_strs, argv[0]);
|
||||
|
||||
if((val < LC15_TX_PWR_ADJ_NONE) || (val > LC15_TX_PWR_ADJ_AUTO)) {
|
||||
vty_out(vty, "Invalid output power adjustment mode %d%s", val, VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
pinst->u.lc15.tx_pwr_adj_mode = (uint8_t)val;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_phy_tx_red_pwr_8psk, cfg_phy_tx_red_pwr_8psk_cmd,
|
||||
"tx-red-pwr-8psk <0-40>",
|
||||
"Set reduction output power for 8-PSK scheme in dB unit\n")
|
||||
{
|
||||
struct phy_instance *pinst = vty->index;
|
||||
int val = atoi(argv[0]);
|
||||
|
||||
if ((val > 40) || (val < 0)) {
|
||||
vty_out(vty, "Reduction Tx power level must be between 0 and 40 dB (%d) %s",
|
||||
val, VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
pinst->u.lc15.tx_pwr_red_8psk = (uint8_t)val;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
void bts_model_config_write_bts(struct vty *vty, struct gsm_bts *bts)
|
||||
{
|
||||
|
||||
vty_out(vty, " led-control-mode %s%s",
|
||||
get_value_string(lc15_led_mode_strs, bts->lc15.led_ctrl_mode), VTY_NEWLINE);
|
||||
|
||||
}
|
||||
|
||||
void bts_model_config_write_trx(struct vty *vty, struct gsm_bts_trx *trx)
|
||||
@@ -349,6 +496,25 @@ void bts_model_config_write_phy_inst(struct vty *vty, struct phy_instance *pinst
|
||||
if (pinst->u.lc15.calib_path)
|
||||
vty_out(vty, " trx-calibration-path %s%s",
|
||||
pinst->u.lc15.calib_path, VTY_NEWLINE);
|
||||
|
||||
vty_out(vty, " max-cell-size %d%s",
|
||||
pinst->u.lc15.max_cell_size, VTY_NEWLINE);
|
||||
|
||||
vty_out(vty, " diversity-mode %s%s",
|
||||
get_value_string(lc15_diversity_mode_strs, pinst->u.lc15.diversity_mode), VTY_NEWLINE);
|
||||
|
||||
vty_out(vty, " pedestal-mode %s%s",
|
||||
get_value_string(lc15_pedestal_mode_strs, pinst->u.lc15.pedestal_mode) , VTY_NEWLINE);
|
||||
|
||||
vty_out(vty, " dsp-alive-period %d%s",
|
||||
pinst->u.lc15.dsp_alive_period, VTY_NEWLINE);
|
||||
|
||||
vty_out(vty, " pwr-adj-mode %s%s",
|
||||
get_value_string(lc15_auto_adj_pwr_strs, pinst->u.lc15.tx_pwr_adj_mode), VTY_NEWLINE);
|
||||
|
||||
vty_out(vty, " tx-red-pwr-8psk %d%s",
|
||||
pinst->u.lc15.tx_pwr_red_8psk, VTY_NEWLINE);
|
||||
|
||||
}
|
||||
|
||||
int bts_model_vty_init(struct gsm_bts *bts)
|
||||
@@ -401,12 +567,20 @@ int bts_model_vty_init(struct gsm_bts *bts)
|
||||
|
||||
install_element(BTS_NODE, &cfg_bts_auto_band_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_no_auto_band_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_led_mode_cmd);
|
||||
|
||||
install_element(TRX_NODE, &cfg_trx_nominal_power_cmd);
|
||||
|
||||
install_element(PHY_INST_NODE, &cfg_phy_dsp_trace_f_cmd);
|
||||
install_element(PHY_INST_NODE, &cfg_phy_no_dsp_trace_f_cmd);
|
||||
install_element(PHY_INST_NODE, &cfg_phy_cal_path_cmd);
|
||||
install_element(PHY_INST_NODE, &cfg_phy_diversity_mode_cmd);
|
||||
install_element(PHY_INST_NODE, &cfg_phy_pedestal_mode_cmd);
|
||||
install_element(PHY_INST_NODE, &cfg_phy_max_cell_size_cmd);
|
||||
install_element(PHY_INST_NODE, &cfg_phy_dsp_alive_timer_cmd);
|
||||
install_element(PHY_INST_NODE, &cfg_phy_auto_tx_pwr_adj_cmd);
|
||||
install_element(PHY_INST_NODE, &cfg_phy_tx_red_pwr_8psk_cmd);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -90,7 +90,8 @@ int bts_model_init(struct gsm_bts *bts)
|
||||
|
||||
bts->variant = BTS_OSMO_LITECELL15;
|
||||
bts->support.ciphers = CIPHER_A5(1) | CIPHER_A5(2) | CIPHER_A5(3);
|
||||
|
||||
/* specific default values for LC15 platform */
|
||||
bts->lc15.led_ctrl_mode = LC15_BTS_LED_CTRL_MODE_DEFAULT;
|
||||
rc = oml_router_init(bts, OML_ROUTER_PATH, &accept_fd, &read_fd);
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "Error creating the OML router: %s rc=%d\n",
|
||||
|
||||
@@ -161,7 +161,7 @@ int lc15bts_swd_init(struct lc15bts_mgr_instance *mgr, int swd_num_events)
|
||||
the value must be in the range of [0,'swd_num_events'[ (see lc15bts_swd_init).
|
||||
For example, if 'swd_num_events' was 64, 'swd_event' events are numbered 0 to 63.
|
||||
WARNING: if this function can be used from multiple threads at the same time,
|
||||
it must be protected with a kind of mutex to avoid loosing event notification.
|
||||
it must be protected with a kind of mutex to avoid losing event notification.
|
||||
*/
|
||||
int lc15bts_swd_event(struct lc15bts_mgr_instance *mgr, enum mgr_swd_events swd_event)
|
||||
{
|
||||
|
||||
@@ -373,7 +373,7 @@ int l1if_tch_rx(struct gsm_bts_trx *trx, uint8_t chan_nr, struct msgb *l1p_msg)
|
||||
rmsg = msgb_alloc_headroom(256, 128, "L1P-to-RTP");
|
||||
return add_l1sap_header(trx, rmsg, lchan, chan_nr, data_ind->u32Fn,
|
||||
data_ind->measParam.fBer * 10000,
|
||||
data_ind->measParam.fLinkQuality * 10);
|
||||
data_ind->measParam.fLinkQuality * 10, 0, 0, 0);
|
||||
}
|
||||
|
||||
payload_type = data_ind->msgUnitParam.u8Buffer[0];
|
||||
@@ -463,7 +463,7 @@ int l1if_tch_rx(struct gsm_bts_trx *trx, uint8_t chan_nr, struct msgb *l1p_msg)
|
||||
if (rmsg)
|
||||
return add_l1sap_header(trx, rmsg, lchan, chan_nr, data_ind->u32Fn,
|
||||
data_ind->measParam.fBer * 10000,
|
||||
data_ind->measParam.fLinkQuality * 10);
|
||||
data_ind->measParam.fLinkQuality * 10, 0, 0, 0);
|
||||
|
||||
return 0;
|
||||
|
||||
|
||||
@@ -992,12 +992,9 @@ empty_frame:
|
||||
goto tx;
|
||||
}
|
||||
|
||||
static void dump_meas_res(int ll, GsmL1_MeasParam_t *m)
|
||||
{
|
||||
LOGPC(DL1C, ll, ", Meas: RSSI %-3.2f dBm, Qual %-3.2f dB, "
|
||||
"BER %-3.2f, Timing %d\n", m->fRssi, m->fLinkQuality,
|
||||
m->fBer, m->i16BurstTiming);
|
||||
}
|
||||
|
||||
#define LOG_FMT_MEAS "Meas: RSSI %-3.2f dBm, Qual %-3.2f dB, BER %-3.2f, Timing %d"
|
||||
#define LOG_PARAM_MEAS(meas_param) (meas_param)->fRssi, (meas_param)->fLinkQuality, (meas_param)->fBer, (meas_param)->i16BurstTiming
|
||||
|
||||
static int process_meas_res(struct gsm_bts_trx *trx, uint8_t chan_nr,
|
||||
GsmL1_MeasParam_t *m, uint32_t fn)
|
||||
@@ -1048,10 +1045,10 @@ static int handle_ph_data_ind(struct oc2gl1_hdl *fl1, GsmL1_PhDataInd_t *data_in
|
||||
process_meas_res(trx, chan_nr, &data_ind->measParam, fn);
|
||||
|
||||
|
||||
DEBUGPGT(DL1P, &g_time, "Rx PH-DATA.ind %s (hL2 %08x): %s\n",
|
||||
DEBUGPGT(DL1P, &g_time, "Rx PH-DATA.ind %s (hL2 %08x): %s, " LOG_FMT_MEAS "\n",
|
||||
get_value_string(oc2gbts_l1sapi_names, data_ind->sapi), (uint32_t)data_ind->hLayer2,
|
||||
osmo_hexdump(data_ind->msgUnitParam.u8Buffer, data_ind->msgUnitParam.u8Size));
|
||||
dump_meas_res(LOGL_DEBUG, &data_ind->measParam);
|
||||
osmo_hexdump(data_ind->msgUnitParam.u8Buffer, data_ind->msgUnitParam.u8Size),
|
||||
LOG_PARAM_MEAS(&data_ind->measParam));
|
||||
|
||||
/* check for TCH */
|
||||
if (data_ind->sapi == GsmL1_Sapi_TchF
|
||||
@@ -1084,11 +1081,10 @@ static int handle_ph_data_ind(struct oc2gl1_hdl *fl1, GsmL1_PhDataInd_t *data_in
|
||||
l1sap->u.data.chan_nr = chan_nr;
|
||||
l1sap->u.data.fn = fn;
|
||||
l1sap->u.data.rssi = rssi;
|
||||
if (!pcu_direct) {
|
||||
l1sap->u.data.ber10k = data_ind->measParam.fBer * 10000;
|
||||
l1sap->u.data.ta_offs_256bits = data_ind->measParam.i16BurstTiming*64;
|
||||
l1sap->u.data.lqual_cb = data_ind->measParam.fLinkQuality * 10;
|
||||
}
|
||||
|
||||
return l1sap_up(trx, l1sap);
|
||||
}
|
||||
|
||||
@@ -1102,7 +1098,8 @@ static int handle_ph_ra_ind(struct oc2gl1_hdl *fl1, GsmL1_PhRaInd_t *ra_ind,
|
||||
struct ph_rach_ind_param rach_ind_param;
|
||||
|
||||
set_log_ctx_sapi(ra_ind->sapi);
|
||||
dump_meas_res(LOGL_DEBUG, &ra_ind->measParam);
|
||||
LOGPFN(DL1C, LOGL_DEBUG, ra_ind->u32Fn, "Rx PH-RA.ind, " LOG_FMT_MEAS "\n",
|
||||
LOG_PARAM_MEAS(&ra_ind->measParam));
|
||||
|
||||
if ((ra_ind->msgUnitParam.u8Size != 1) &&
|
||||
(ra_ind->msgUnitParam.u8Size != 2)) {
|
||||
|
||||
@@ -161,7 +161,7 @@ int oc2gbts_swd_init(struct oc2gbts_mgr_instance *mgr, int swd_num_events)
|
||||
the value must be in the range of [0,'swd_num_events'[ (see oc2gbts_swd_init).
|
||||
For example, if 'swd_num_events' was 64, 'swd_event' events are numbered 0 to 63.
|
||||
WARNING: if this function can be used from multiple threads at the same time,
|
||||
it must be protected with a kind of mutex to avoid loosing event notification.
|
||||
it must be protected with a kind of mutex to avoid losing event notification.
|
||||
*/
|
||||
int oc2gbts_swd_event(struct oc2gbts_mgr_instance *mgr, enum mgr_swd_events swd_event)
|
||||
{
|
||||
|
||||
@@ -373,7 +373,7 @@ int l1if_tch_rx(struct gsm_bts_trx *trx, uint8_t chan_nr, struct msgb *l1p_msg)
|
||||
rmsg = msgb_alloc_headroom(256, 128, "L1P-to-RTP");
|
||||
return add_l1sap_header(trx, rmsg, lchan, chan_nr, data_ind->u32Fn,
|
||||
data_ind->measParam.fBer * 10000,
|
||||
data_ind->measParam.fLinkQuality * 10);
|
||||
data_ind->measParam.fLinkQuality * 10, 0, 0, 0);
|
||||
}
|
||||
|
||||
payload_type = data_ind->msgUnitParam.u8Buffer[0];
|
||||
@@ -475,7 +475,7 @@ int l1if_tch_rx(struct gsm_bts_trx *trx, uint8_t chan_nr, struct msgb *l1p_msg)
|
||||
if (rmsg)
|
||||
return add_l1sap_header(trx, rmsg, lchan, chan_nr, data_ind->u32Fn,
|
||||
data_ind->measParam.fBer * 10000,
|
||||
data_ind->measParam.fLinkQuality * 10);
|
||||
data_ind->measParam.fLinkQuality * 10, 0, 0, 0);
|
||||
|
||||
return 0;
|
||||
|
||||
|
||||
@@ -906,14 +906,9 @@ static void process_meas_res(struct gsm_bts_trx *trx, uint8_t chan_nr,
|
||||
l1sap_up(trx, &l1sap);
|
||||
}
|
||||
|
||||
static void dump_meas_res(int ll, tOCTVC1_GSM_MEASUREMENT_INFO * m)
|
||||
{
|
||||
LOGP(DMEAS, ll,
|
||||
"Meas: RSSI %d dBm, Burst Timing %d Quarter of bits :%d, "
|
||||
"BER Error Count %d , BER Toatal Bit count %d in last decoded frame\n",
|
||||
m->sRSSIDbm, m->sBurstTiming, m->sBurstTiming4x, m->usBERCnt,
|
||||
m->usBERTotalBitCnt);
|
||||
}
|
||||
|
||||
#define LOG_FMT_MEAS "Meas: RSSI %d dBm, Burst Timing %d Quarter of bits: %d, BER Error Count %d, BER Toatal Bit count %d in last decoded frame"
|
||||
#define LOG_PARAM_MEAS(meas_param) (meas_param)->sRSSIDbm, (meas_param)->sBurstTiming, (meas_param)->sBurstTiming4x, (meas_param)->usBERCnt, (meas_param)->usBERTotalBitCnt
|
||||
|
||||
static int handle_mph_time_ind(struct octphy_hdl *fl1, uint8_t trx_id, uint32_t fn)
|
||||
{
|
||||
@@ -1218,7 +1213,8 @@ static int handle_ph_rach_ind(struct octphy_hdl *fl1,
|
||||
|
||||
set_log_ctx_sapi(ra_ind->LchId.bySAPI);
|
||||
|
||||
dump_meas_res(LOGL_DEBUG, &ra_ind->MeasurementInfo);
|
||||
LOGPFN(DL1C, LOGL_DEBUG, ra_ind->ulFrameNumber, "Rx PH-RA.ind, " LOG_FMT_MEAS "\n",
|
||||
LOG_PARAM_MEAS(&ra_ind->MeasurementInfo));
|
||||
|
||||
if (ra_ind->ulMsgLength != 1) {
|
||||
LOGPFN(DL1C, LOGL_ERROR, ra_ind->ulFrameNumber,
|
||||
|
||||
@@ -151,7 +151,7 @@ int l1if_tch_rx(struct gsm_bts_trx *trx, uint8_t chan_nr,
|
||||
rmsg = msgb_alloc_headroom(256, 128, "L1P-to-RTP");
|
||||
return add_l1sap_header(trx, rmsg, lchan, chan_nr,
|
||||
data_ind->Data.ulFrameNumber,
|
||||
ber10k, lqual_cb);
|
||||
ber10k, lqual_cb, 0, 0, 0);
|
||||
}
|
||||
|
||||
payload_len = data_ind->Data.ulDataLength;
|
||||
@@ -210,7 +210,7 @@ int l1if_tch_rx(struct gsm_bts_trx *trx, uint8_t chan_nr,
|
||||
if (rmsg)
|
||||
return add_l1sap_header(trx, rmsg, lchan, chan_nr,
|
||||
data_ind->Data.ulFrameNumber,
|
||||
ber10k, lqual_cb);
|
||||
ber10k, lqual_cb, 0, 0, 0);
|
||||
|
||||
return 0;
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ l1fwd_proxy_SOURCES = l1_fwd_main.c l1_transp_hw.c
|
||||
l1fwd_proxy_LDADD = $(top_builddir)/src/common/libbts.a $(COMMON_LDADD)
|
||||
|
||||
if ENABLE_SYSMOBTS_CALIB
|
||||
bin_PROGRAMS = sysmobts-calib
|
||||
bin_PROGRAMS += sysmobts-calib
|
||||
|
||||
sysmobts_calib_SOURCES = misc/sysmobts-calib.c misc/sysmobts-layer1.c
|
||||
sysmobts_calib_LDADD = -lrt $(COMMON_LDADD)
|
||||
|
||||
@@ -937,31 +937,8 @@ empty_frame:
|
||||
goto tx;
|
||||
}
|
||||
|
||||
static void dump_meas_res(int ll, GsmL1_MeasParam_t *m)
|
||||
{
|
||||
LOGPC(DL1C, ll, ", Meas: RSSI %-3.2f dBm, Qual %-3.2f dB, "
|
||||
"BER %-3.2f, Timing %d\n", m->fRssi, m->fLinkQuality,
|
||||
m->fBer, m->i16BurstTiming);
|
||||
}
|
||||
|
||||
static int process_meas_res(struct gsm_bts_trx *trx, uint8_t chan_nr,
|
||||
uint32_t fn, GsmL1_MeasParam_t *m)
|
||||
{
|
||||
struct osmo_phsap_prim l1sap;
|
||||
memset(&l1sap, 0, sizeof(l1sap));
|
||||
osmo_prim_init(&l1sap.oph, SAP_GSM_PH, PRIM_MPH_INFO,
|
||||
PRIM_OP_INDICATION, NULL);
|
||||
l1sap.u.info.type = PRIM_INFO_MEAS;
|
||||
l1sap.u.info.u.meas_ind.chan_nr = chan_nr;
|
||||
l1sap.u.info.u.meas_ind.ta_offs_256bits = m->i16BurstTiming * 64;
|
||||
l1sap.u.info.u.meas_ind.ber10k = (unsigned int) (m->fBer * 10000);
|
||||
l1sap.u.info.u.meas_ind.inv_rssi = (uint8_t) (m->fRssi * -1);
|
||||
l1sap.u.info.u.meas_ind.fn = fn;
|
||||
|
||||
/* l1sap wants to take msgb ownership. However, as there is no
|
||||
* msg, it will msgb_free(l1sap.oph.msg == NULL) */
|
||||
return l1sap_up(trx, &l1sap);
|
||||
}
|
||||
#define LOG_FMT_MEAS "Meas: RSSI %-3.2f dBm, Qual %-3.2f dB, BER %-3.2f, Timing %d"
|
||||
#define LOG_PARAM_MEAS(meas_param) (meas_param)->fRssi, (meas_param)->fLinkQuality, (meas_param)->fBer, (meas_param)->i16BurstTiming
|
||||
|
||||
static int handle_ph_data_ind(struct femtol1_hdl *fl1, GsmL1_PhDataInd_t *data_ind,
|
||||
struct msgb *l1p_msg)
|
||||
@@ -987,14 +964,12 @@ static int handle_ph_data_ind(struct femtol1_hdl *fl1, GsmL1_PhDataInd_t *data_i
|
||||
fn = data_ind->u32Fn;
|
||||
link_id = (data_ind->sapi == GsmL1_Sapi_Sacch) ? LID_SACCH : LID_DEDIC;
|
||||
|
||||
process_meas_res(trx, chan_nr, fn, &data_ind->measParam);
|
||||
|
||||
gsm_fn2gsmtime(&g_time, fn);
|
||||
|
||||
DEBUGPGT(DL1P, &g_time, "Rx PH-DATA.ind %s (hL2 %08x): %s\n",
|
||||
DEBUGPGT(DL1P, &g_time, "Rx PH-DATA.ind %s (hL2 %08x): %s, " LOG_FMT_MEAS "\n",
|
||||
get_value_string(femtobts_l1sapi_names, data_ind->sapi), data_ind->hLayer2,
|
||||
osmo_hexdump(data_ind->msgUnitParam.u8Buffer, data_ind->msgUnitParam.u8Size));
|
||||
dump_meas_res(LOGL_DEBUG, &data_ind->measParam);
|
||||
osmo_hexdump(data_ind->msgUnitParam.u8Buffer, data_ind->msgUnitParam.u8Size),
|
||||
LOG_PARAM_MEAS(&data_ind->measParam));
|
||||
|
||||
/* check for TCH */
|
||||
if (data_ind->sapi == GsmL1_Sapi_TchF
|
||||
@@ -1014,11 +989,10 @@ static int handle_ph_data_ind(struct femtol1_hdl *fl1, GsmL1_PhDataInd_t *data_i
|
||||
l1sap->u.data.chan_nr = chan_nr;
|
||||
l1sap->u.data.fn = fn;
|
||||
l1sap->u.data.rssi = (int8_t) (data_ind->measParam.fRssi);
|
||||
if (!pcu_direct) { /* FIXME: if pcu_direct=1, then this is not set, what to do in pcu_tx_data_ind() in this case ?*/
|
||||
l1sap->u.data.ber10k = data_ind->measParam.fBer * 10000;
|
||||
l1sap->u.data.ta_offs_256bits = data_ind->measParam.i16BurstTiming * 64;
|
||||
l1sap->u.data.lqual_cb = data_ind->measParam.fLinkQuality * 10;
|
||||
}
|
||||
|
||||
/* copy data from L1 primitive to L1SAP primitive */
|
||||
sap_msg->l2h = msgb_put(sap_msg, data_ind->msgUnitParam.u8Size);
|
||||
memcpy(sap_msg->l2h, data_ind->msgUnitParam.u8Buffer,
|
||||
@@ -1040,8 +1014,8 @@ static int handle_ph_ra_ind(struct femtol1_hdl *fl1, GsmL1_PhRaInd_t *ra_ind,
|
||||
struct ph_rach_ind_param rach_ind_param;
|
||||
|
||||
set_log_ctx_sapi(ra_ind->sapi);
|
||||
|
||||
dump_meas_res(LOGL_DEBUG, &ra_ind->measParam);
|
||||
LOGPFN(DL1C, LOGL_DEBUG, ra_ind->u32Fn, "Rx PH-RA.ind, " LOG_FMT_MEAS "\n",
|
||||
LOG_PARAM_MEAS(&ra_ind->measParam));
|
||||
|
||||
if ((ra_ind->msgUnitParam.u8Size != 1) &&
|
||||
(ra_ind->msgUnitParam.u8Size != 2)) {
|
||||
|
||||
@@ -87,6 +87,7 @@ int bts_model_init(struct gsm_bts *bts)
|
||||
gsm_bts_set_feature(bts, BTS_FEAT_SPEECH_F_AMR);
|
||||
gsm_bts_set_feature(bts, BTS_FEAT_SPEECH_H_AMR);
|
||||
gsm_bts_set_feature(bts, BTS_FEAT_MS_PWR_CTRL_DSP);
|
||||
gsm_bts_set_feature(bts, BTS_FEAT_MEAS_PAYLOAD_COMB);
|
||||
|
||||
bts_model_vty_init(bts);
|
||||
|
||||
|
||||
@@ -518,7 +518,10 @@ int l1if_tch_rx(struct gsm_bts_trx *trx, uint8_t chan_nr, struct msgb *l1p_msg)
|
||||
rmsg = msgb_alloc_headroom(256, 128, "L1P-to-RTP");
|
||||
return add_l1sap_header(trx, rmsg, lchan, chan_nr, data_ind->u32Fn,
|
||||
data_ind->measParam.fBer * 10000,
|
||||
data_ind->measParam.fLinkQuality * 10);
|
||||
data_ind->measParam.fLinkQuality * 10,
|
||||
data_ind->measParam.fRssi,
|
||||
data_ind->measParam.i16BurstTiming * 64,
|
||||
0);
|
||||
}
|
||||
|
||||
payload_type = data_ind->msgUnitParam.u8Buffer[0];
|
||||
@@ -613,7 +616,10 @@ int l1if_tch_rx(struct gsm_bts_trx *trx, uint8_t chan_nr, struct msgb *l1p_msg)
|
||||
if (rmsg)
|
||||
return add_l1sap_header(trx, rmsg, lchan, chan_nr, data_ind->u32Fn,
|
||||
data_ind->measParam.fBer * 10000,
|
||||
data_ind->measParam.fLinkQuality * 10);
|
||||
data_ind->measParam.fLinkQuality * 10,
|
||||
data_ind->measParam.fRssi,
|
||||
data_ind->measParam.i16BurstTiming * 64,
|
||||
0);
|
||||
|
||||
return 0;
|
||||
|
||||
|
||||
@@ -572,40 +572,6 @@ int l1if_mph_time_ind(struct gsm_bts *bts, uint32_t fn)
|
||||
return l1sap_up(bts->c0, &l1sap);
|
||||
}
|
||||
|
||||
|
||||
static void l1if_fill_meas_res(struct osmo_phsap_prim *l1sap, uint8_t chan_nr, int16_t toa256,
|
||||
float ber, float rssi, uint32_t fn)
|
||||
{
|
||||
memset(l1sap, 0, sizeof(*l1sap));
|
||||
osmo_prim_init(&l1sap->oph, SAP_GSM_PH, PRIM_MPH_INFO,
|
||||
PRIM_OP_INDICATION, NULL);
|
||||
l1sap->u.info.type = PRIM_INFO_MEAS;
|
||||
l1sap->u.info.u.meas_ind.chan_nr = chan_nr;
|
||||
l1sap->u.info.u.meas_ind.ta_offs_256bits = toa256;
|
||||
l1sap->u.info.u.meas_ind.ber10k = (unsigned int) (ber * 10000);
|
||||
l1sap->u.info.u.meas_ind.inv_rssi = (uint8_t) (rssi * -1);
|
||||
l1sap->u.info.u.meas_ind.fn = fn;
|
||||
}
|
||||
|
||||
int l1if_process_meas_res(struct gsm_bts_trx *trx, uint8_t tn, uint32_t fn, uint8_t chan_nr,
|
||||
int n_errors, int n_bits_total, float rssi, int16_t toa256)
|
||||
{
|
||||
struct gsm_lchan *lchan = &trx->ts[tn].lchan[l1sap_chan2ss(chan_nr)];
|
||||
struct osmo_phsap_prim l1sap;
|
||||
/* 100% BER is n_bits_total is 0 */
|
||||
float ber = n_bits_total==0 ? 1.0 : (float)n_errors / (float)n_bits_total;
|
||||
|
||||
LOGPFN(DMEAS, LOGL_DEBUG, fn, "RX UL measurement for %s fn=%u chan_nr=0x%02x MS pwr=%ddBm rssi=%.1f dBFS "
|
||||
"ber=%.2f%% (%d/%d bits) L1_ta=%d rqd_ta=%d toa256=%d\n",
|
||||
gsm_lchan_name(lchan), fn, chan_nr, ms_pwr_dbm(lchan->ts->trx->bts->band, lchan->ms_power_ctrl.current),
|
||||
rssi, ber*100, n_errors, n_bits_total, lchan->meas.l1_info[1], lchan->rqd_ta, toa256);
|
||||
|
||||
l1if_fill_meas_res(&l1sap, chan_nr, toa256, ber, rssi, fn);
|
||||
|
||||
return l1sap_up(trx, &l1sap);
|
||||
}
|
||||
|
||||
|
||||
/* primitive from common part */
|
||||
int bts_model_l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap)
|
||||
{
|
||||
|
||||
@@ -115,8 +115,6 @@ struct trx_l1h *trx_l1h_alloc(void *tall_ctx, struct phy_instance *pinst);
|
||||
int l1if_provision_transceiver_trx(struct trx_l1h *l1h);
|
||||
int l1if_provision_transceiver(struct gsm_bts *bts);
|
||||
int l1if_mph_time_ind(struct gsm_bts *bts, uint32_t fn);
|
||||
int l1if_process_meas_res(struct gsm_bts_trx *trx, uint8_t tn, uint32_t fn, uint8_t chan_nr,
|
||||
int n_errors, int n_bits_total, float rssi, int16_t toa256);
|
||||
|
||||
static inline struct l1sched_trx *trx_l1sched_hdl(struct gsm_bts_trx *trx)
|
||||
{
|
||||
|
||||
@@ -35,63 +35,6 @@
|
||||
#include "l1_if.h"
|
||||
#include "loops.h"
|
||||
|
||||
/*
|
||||
* Timing Advance loop
|
||||
*/
|
||||
|
||||
/* 90% of one bit duration in 1/256 symbols: 256*0.9 */
|
||||
#define TOA256_9OPERCENT 230
|
||||
|
||||
void ta_val(struct gsm_lchan *lchan, struct l1sched_chan_state *chan_state, int16_t toa256)
|
||||
{
|
||||
/* check if the current L1 header acks to the current ordered TA */
|
||||
if (lchan->meas.l1_info[1] != lchan->rqd_ta)
|
||||
return;
|
||||
|
||||
/* sum measurement */
|
||||
chan_state->meas.toa256_sum += toa256;
|
||||
if (++(chan_state->meas.toa_num) < 16)
|
||||
return;
|
||||
|
||||
/* complete set */
|
||||
toa256 = chan_state->meas.toa256_sum / chan_state->meas.toa_num;
|
||||
|
||||
/* check for change of TOA */
|
||||
if (toa256 < -TOA256_9OPERCENT && lchan->rqd_ta > 0) {
|
||||
LOGPLCHAN(lchan, DLOOP, LOGL_INFO, "TOA is too early (%d), now lowering TA from %d to %d\n",
|
||||
toa256, lchan->rqd_ta, lchan->rqd_ta - 1);
|
||||
lchan->rqd_ta--;
|
||||
} else if (toa256 > TOA256_9OPERCENT && lchan->rqd_ta < 63) {
|
||||
LOGPLCHAN(lchan, DLOOP, LOGL_INFO, "TOA is too late (%d), now raising TA from %d to %d\n",
|
||||
toa256, lchan->rqd_ta, lchan->rqd_ta + 1);
|
||||
lchan->rqd_ta++;
|
||||
} else
|
||||
LOGPLCHAN(lchan, DLOOP, LOGL_INFO, "TOA is correct (%d), keeping current TA of %d\n",
|
||||
toa256, lchan->rqd_ta);
|
||||
|
||||
chan_state->meas.toa_num = 0;
|
||||
chan_state->meas.toa256_sum = 0;
|
||||
}
|
||||
|
||||
/*! Process a SACCH event as input to the MS power control and TA loop. Function
|
||||
* is called once every uplink SACCH block is received.
|
||||
* \param l1t L1 TRX instance on which we operate
|
||||
* \param chan_nr RSL channel number on which we operate
|
||||
* \param chan_state L1 scheduler channel state of the channel on which we operate
|
||||
* \param[in] rssi Receive Signal Strength Indication
|
||||
* \param[in] toa256 Time of Arrival in 1/256 symbol periods */
|
||||
void trx_loop_sacch_input(struct l1sched_trx *l1t, uint8_t chan_nr,
|
||||
struct l1sched_chan_state *chan_state, int16_t toa256)
|
||||
{
|
||||
struct gsm_lchan *lchan = &l1t->trx->ts[L1SAP_CHAN2TS(chan_nr)]
|
||||
.lchan[l1sap_chan2ss(chan_nr)];
|
||||
struct phy_instance *pinst = trx_phy_instance(l1t->trx);
|
||||
|
||||
/* if TA loop is enabled, handle it */
|
||||
if (pinst->phy_link->u.osmotrx.trx_ta_loop)
|
||||
ta_val(lchan, chan_state, toa256);
|
||||
}
|
||||
|
||||
void trx_loop_amr_input(struct l1sched_trx *l1t, uint8_t chan_nr,
|
||||
struct l1sched_chan_state *chan_state,
|
||||
int n_errors, int n_bits_total)
|
||||
|
||||
@@ -11,9 +11,6 @@
|
||||
* loops api
|
||||
*/
|
||||
|
||||
void trx_loop_sacch_input(struct l1sched_trx *l1t, uint8_t chan_nr,
|
||||
struct l1sched_chan_state *chan_state, int16_t toa);
|
||||
|
||||
void trx_loop_amr_input(struct l1sched_trx *l1t, uint8_t chan_nr,
|
||||
struct l1sched_chan_state *chan_state,
|
||||
int n_errors, int n_bits_total);
|
||||
|
||||
@@ -116,6 +116,7 @@ int bts_model_init(struct gsm_bts *bts)
|
||||
gsm_bts_set_feature(bts, BTS_FEAT_SPEECH_F_AMR);
|
||||
gsm_bts_set_feature(bts, BTS_FEAT_SPEECH_H_AMR);
|
||||
gsm_bts_set_feature(bts, BTS_FEAT_CBCH);
|
||||
gsm_bts_set_feature(bts, BTS_FEAT_MEAS_PAYLOAD_COMB);
|
||||
|
||||
bts_model_vty_init(bts);
|
||||
|
||||
@@ -135,7 +136,6 @@ void bts_model_phy_link_set_defaults(struct phy_link *plink)
|
||||
plink->u.osmotrx.base_port_remote = 5700;
|
||||
plink->u.osmotrx.clock_advance = 20;
|
||||
plink->u.osmotrx.rts_advance = 5;
|
||||
plink->u.osmotrx.trx_ta_loop = true;
|
||||
/* attempt use newest TRXD version by default: */
|
||||
plink->u.osmotrx.trxd_hdr_ver_max = TRX_DATA_FORMAT_VER;
|
||||
}
|
||||
|
||||
@@ -193,12 +193,10 @@ got_msg:
|
||||
/* TODO: Should we pass old TOA here? Otherwise we risk
|
||||
* unnecessary decreasing TA */
|
||||
|
||||
/* Send uplink measurement information to L2 */
|
||||
l1if_process_meas_res(l1t->trx, tn, fn, trx_chan_desc[chan].chan_nr | tn,
|
||||
456, 456, -110, 0);
|
||||
/* FIXME: use actual values for BER etc */
|
||||
/* Note: RSSI is set to 0 to indicate to the higher
|
||||
* layers that this is a faked ph_data_ind */
|
||||
_sched_compose_ph_data_ind(l1t, tn, 0, chan, NULL, 0,
|
||||
-110, 0, 0, 10000,
|
||||
0, 0, 0, 10000,
|
||||
PRES_INFO_INVALID);
|
||||
}
|
||||
}
|
||||
@@ -345,6 +343,9 @@ static void tx_tch_common(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
||||
uint8_t rsl_cmode = chan_state->rsl_cmode;
|
||||
uint8_t tch_mode = chan_state->tch_mode;
|
||||
struct osmo_phsap_prim *l1sap;
|
||||
int32_t *toa256_sum = &chan_state->toa256_sum;
|
||||
uint8_t *toa_num = &chan_state->toa_num;
|
||||
int16_t toa256;
|
||||
|
||||
/* handle loss detection of received TCH frames */
|
||||
if (rsl_cmode == RSL_CMOD_SPD_SPEECH
|
||||
@@ -390,8 +391,17 @@ inval_mode1:
|
||||
LOGL1S(DL1P, LOGL_ERROR, l1t, tn, chan, fn, "TCH mode invalid, please fix!\n");
|
||||
len = 0;
|
||||
}
|
||||
if (len)
|
||||
_sched_compose_tch_ind(l1t, tn, fn, chan, tch_data, len);
|
||||
|
||||
if (len) {
|
||||
if (*toa_num == 0)
|
||||
toa256 = 0;
|
||||
else
|
||||
toa256 = *toa256_sum / *toa_num;
|
||||
|
||||
/* Note: RSSI is set to 0 to indicate to the higher
|
||||
* layers that this is a faked tch_ind */
|
||||
_sched_compose_tch_ind(l1t, tn, fn, chan, tch_data, len, toa256, 10000, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* get frame and unlink from queue */
|
||||
@@ -946,7 +956,7 @@ int rx_data_fn(struct l1sched_trx *l1t, enum trx_chan_type chan,
|
||||
}
|
||||
|
||||
/* Copy burst to buffer of 4 bursts. If the burst indication contains
|
||||
* no data, ensure that the buffer does not stay uninitalized */
|
||||
* no data, ensure that the buffer does not stay uninitialized */
|
||||
burst = *bursts_p + bid * 116;
|
||||
if (bi->burst_len > 0) {
|
||||
memcpy(burst, bi->burst + 3, 58);
|
||||
@@ -954,12 +964,6 @@ int rx_data_fn(struct l1sched_trx *l1t, enum trx_chan_type chan,
|
||||
} else
|
||||
memset(burst, 0, 58 * 2);
|
||||
|
||||
/* send burst information to loops process */
|
||||
if (L1SAP_IS_LINK_SACCH(trx_chan_desc[chan].link_id)) {
|
||||
trx_loop_sacch_input(l1t, trx_chan_desc[chan].chan_nr | bi->tn,
|
||||
chan_state, bi->toa256);
|
||||
}
|
||||
|
||||
/* wait until complete set of bursts */
|
||||
if (bid != 3)
|
||||
return 0;
|
||||
@@ -988,12 +992,6 @@ int rx_data_fn(struct l1sched_trx *l1t, enum trx_chan_type chan,
|
||||
} else
|
||||
l2_len = GSM_MACBLOCK_LEN;
|
||||
|
||||
/* Send uplink measurement information to L2 */
|
||||
l1if_process_meas_res(l1t->trx, bi->tn, *first_fn,
|
||||
trx_chan_desc[chan].chan_nr | bi->tn,
|
||||
n_errors, n_bits_total,
|
||||
*rssi_sum / *rssi_num,
|
||||
*toa256_sum / *toa_num);
|
||||
lqual_cb = *ci_cb_num ? (*ci_cb_sum / *ci_cb_num) : 0;
|
||||
ber10k = compute_ber10k(n_bits_total, n_errors);
|
||||
return _sched_compose_ph_data_ind(l1t, bi->tn, *first_fn,
|
||||
@@ -1103,14 +1101,6 @@ int rx_pdtch_fn(struct l1sched_trx *l1t, enum trx_chan_type chan,
|
||||
&n_errors, &n_bits_total);
|
||||
}
|
||||
|
||||
|
||||
/* Send uplink measurement information to L2 */
|
||||
l1if_process_meas_res(l1t->trx, bi->tn, *first_fn,
|
||||
trx_chan_desc[chan].chan_nr | bi->tn,
|
||||
n_errors, n_bits_total,
|
||||
*rssi_sum / *rssi_num,
|
||||
*toa256_sum / *toa_num);
|
||||
|
||||
if (rc <= 0) {
|
||||
LOGL1S(DL1P, LOGL_DEBUG, l1t, bi->tn, chan, bi->fn,
|
||||
"Received bad PDTCH (%u/%u)\n",
|
||||
@@ -1147,6 +1137,7 @@ int rx_tchf_fn(struct l1sched_trx *l1t, enum trx_chan_type chan,
|
||||
struct gsm_lchan *lchan =
|
||||
get_lchan_by_chan_nr(l1t->trx, trx_chan_desc[chan].chan_nr | bi->tn);
|
||||
unsigned int fn_begin;
|
||||
uint16_t ber10k;
|
||||
|
||||
/* handle rach, if handover rach detection is turned on */
|
||||
if (chan_state->ho_rach_detect == 1)
|
||||
@@ -1174,8 +1165,11 @@ int rx_tchf_fn(struct l1sched_trx *l1t, enum trx_chan_type chan,
|
||||
|
||||
/* copy burst to end of buffer of 8 bursts */
|
||||
burst = *bursts_p + bid * 116 + 464;
|
||||
if (bi->burst_len > 0) {
|
||||
memcpy(burst, bi->burst + 3, 58);
|
||||
memcpy(burst + 58, bi->burst + 87, 58);
|
||||
} else
|
||||
memset(burst, 0, 116);
|
||||
|
||||
/* wait until complete set of bursts */
|
||||
if (bid != 3)
|
||||
@@ -1246,17 +1240,13 @@ int rx_tchf_fn(struct l1sched_trx *l1t, enum trx_chan_type chan,
|
||||
if (rc != GSM_MACBLOCK_LEN && lchan->ecu_state)
|
||||
osmo_ecu_frame_in(lchan->ecu_state, bfi_flag, tch_data, rc);
|
||||
|
||||
ber10k = compute_ber10k(n_bits_total, n_errors);
|
||||
if (bfi_flag)
|
||||
goto bfi;
|
||||
|
||||
/* FACCH */
|
||||
if (rc == GSM_MACBLOCK_LEN) {
|
||||
uint16_t ber10k = compute_ber10k(n_bits_total, n_errors);
|
||||
fn_begin = gsm0502_fn_remap(bi->fn, FN_REMAP_FACCH_F);
|
||||
l1if_process_meas_res(l1t->trx, bi->tn, fn_begin,
|
||||
trx_chan_desc[chan].chan_nr | bi->tn,
|
||||
n_errors, n_bits_total,
|
||||
bi->rssi, bi->toa256);
|
||||
_sched_compose_ph_data_ind(l1t, bi->tn, fn_begin, chan,
|
||||
tch_data + amr, GSM_MACBLOCK_LEN,
|
||||
/* FIXME: AVG RSSI and ToA256 */
|
||||
@@ -1317,12 +1307,8 @@ bfi:
|
||||
/* TCH or BFI */
|
||||
compose_l1sap:
|
||||
fn_begin = gsm0502_fn_remap(bi->fn, FN_REMAP_TCH_F);
|
||||
l1if_process_meas_res(l1t->trx, bi->tn, fn_begin,
|
||||
trx_chan_desc[chan].chan_nr | bi->tn,
|
||||
n_errors, n_bits_total,
|
||||
bi->rssi, bi->toa256);
|
||||
return _sched_compose_tch_ind(l1t, bi->tn, fn_begin, chan,
|
||||
tch_data, rc);
|
||||
tch_data, rc, bi->toa256, ber10k, bi->rssi);
|
||||
}
|
||||
|
||||
/*! \brief a single TCH/H burst was received by the PHY, process it */
|
||||
@@ -1349,6 +1335,7 @@ int rx_tchh_fn(struct l1sched_trx *l1t, enum trx_chan_type chan,
|
||||
*/
|
||||
int fn_is_odd = (((bi->fn + 26 - 10) % 26) >> 2) & 1;
|
||||
unsigned int fn_begin;
|
||||
uint16_t ber10k;
|
||||
|
||||
/* handle RACH, if handover RACH detection is turned on */
|
||||
if (chan_state->ho_rach_detect == 1)
|
||||
@@ -1376,8 +1363,11 @@ int rx_tchh_fn(struct l1sched_trx *l1t, enum trx_chan_type chan,
|
||||
|
||||
/* copy burst to end of buffer of 6 bursts */
|
||||
burst = *bursts_p + bid * 116 + 464;
|
||||
if (bi->burst_len > 0) {
|
||||
memcpy(burst, bi->burst + 3, 58);
|
||||
memcpy(burst + 58, bi->burst + 87, 58);
|
||||
} else
|
||||
memset(burst, 0, 116);
|
||||
|
||||
/* wait until complete set of bursts */
|
||||
if (bid != 1)
|
||||
@@ -1396,6 +1386,7 @@ int rx_tchh_fn(struct l1sched_trx *l1t, enum trx_chan_type chan,
|
||||
chan_state->ul_ongoing_facch = 0;
|
||||
memcpy(*bursts_p, *bursts_p + 232, 232);
|
||||
memcpy(*bursts_p + 232, *bursts_p + 464, 232);
|
||||
ber10k = 0;
|
||||
goto bfi;
|
||||
}
|
||||
|
||||
@@ -1442,6 +1433,8 @@ int rx_tchh_fn(struct l1sched_trx *l1t, enum trx_chan_type chan,
|
||||
}
|
||||
memcpy(*bursts_p, *bursts_p + 232, 232);
|
||||
memcpy(*bursts_p + 232, *bursts_p + 464, 232);
|
||||
ber10k = compute_ber10k(n_bits_total, n_errors);
|
||||
|
||||
|
||||
/* Check if the frame is bad */
|
||||
if (rc < 0) {
|
||||
@@ -1470,10 +1463,6 @@ int rx_tchh_fn(struct l1sched_trx *l1t, enum trx_chan_type chan,
|
||||
fn_begin = gsm0502_fn_remap(bi->fn, FN_REMAP_FACCH_H0);
|
||||
else
|
||||
fn_begin = gsm0502_fn_remap(bi->fn, FN_REMAP_FACCH_H1);
|
||||
l1if_process_meas_res(l1t->trx, bi->tn, fn_begin,
|
||||
trx_chan_desc[chan].chan_nr | bi->tn,
|
||||
n_errors, n_bits_total, bi->rssi,
|
||||
bi->toa256);
|
||||
_sched_compose_ph_data_ind(l1t, bi->tn, fn_begin, chan,
|
||||
tch_data + amr, GSM_MACBLOCK_LEN,
|
||||
/* FIXME: AVG both RSSI and ToA */
|
||||
@@ -1539,12 +1528,8 @@ compose_l1sap:
|
||||
fn_begin = gsm0502_fn_remap(bi->fn, FN_REMAP_TCH_H0);
|
||||
else
|
||||
fn_begin = gsm0502_fn_remap(bi->fn, FN_REMAP_TCH_H1);
|
||||
l1if_process_meas_res(l1t->trx, bi->tn, fn_begin,
|
||||
trx_chan_desc[chan].chan_nr | bi->tn,
|
||||
n_errors, n_bits_total, bi->rssi,
|
||||
bi->toa256);
|
||||
return _sched_compose_tch_ind(l1t, bi->tn, fn_begin, chan,
|
||||
tch_data, rc);
|
||||
tch_data, rc, bi->toa256, ber10k, bi->rssi);
|
||||
}
|
||||
|
||||
/* schedule all frames of all TRX for given FN */
|
||||
|
||||
@@ -394,8 +394,8 @@ static int parse_rsp(const char *buf_in, size_t len_in, struct trx_ctrl_rsp *rsp
|
||||
goto parse_err;
|
||||
|
||||
if (p - buf_in >= sizeof(rsp->cmd)) {
|
||||
LOGP(DTRX, LOGL_ERROR, "cmd buffer too small %lu >= %lu\n",
|
||||
p - buf_in, sizeof(rsp->cmd));
|
||||
LOGP(DTRX, LOGL_ERROR, "cmd buffer too small %lu >= %zu\n",
|
||||
(long unsigned) (p - buf_in), sizeof(rsp->cmd));
|
||||
goto parse_err;
|
||||
}
|
||||
|
||||
@@ -415,7 +415,7 @@ static int parse_rsp(const char *buf_in, size_t len_in, struct trx_ctrl_rsp *rsp
|
||||
k = p + strlen(p);
|
||||
|
||||
if (strlen(k) >= sizeof(rsp->params)) {
|
||||
LOGP(DTRX, LOGL_ERROR, "params buffer too small %lu >= %lu\n",
|
||||
LOGP(DTRX, LOGL_ERROR, "params buffer too small %zu >= %zu\n",
|
||||
strlen(k), sizeof(rsp->params));
|
||||
goto parse_err;
|
||||
}
|
||||
|
||||
@@ -181,23 +181,19 @@ DEFUN_DEPRECATED(cfg_phy_no_ms_power_loop, cfg_phy_no_ms_power_loop_cmd,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_phy_timing_advance_loop, cfg_phy_timing_advance_loop_cmd,
|
||||
DEFUN_DEPRECATED(cfg_phy_timing_advance_loop, cfg_phy_timing_advance_loop_cmd,
|
||||
"osmotrx timing-advance-loop", OSMOTRX_STR
|
||||
"Enable timing advance control loop\n")
|
||||
{
|
||||
struct phy_link *plink = vty->index;
|
||||
|
||||
plink->u.osmotrx.trx_ta_loop = true;
|
||||
vty_out (vty, "'osmotrx timing-advance-loop' is deprecated, ta control is now active by default%s", VTY_NEWLINE);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
DEFUN(cfg_phy_no_timing_advance_loop, cfg_phy_no_timing_advance_loop_cmd,
|
||||
DEFUN_DEPRECATED(cfg_phy_no_timing_advance_loop, cfg_phy_no_timing_advance_loop_cmd,
|
||||
"no osmotrx timing-advance-loop",
|
||||
NO_STR OSMOTRX_STR "Disable timing advance control loop\n")
|
||||
{
|
||||
struct phy_link *plink = vty->index;
|
||||
|
||||
plink->u.osmotrx.trx_ta_loop = false;
|
||||
vty_out (vty, "'no osmotrx timing-advance-loop' is deprecated, ta control is now active by default%s", VTY_NEWLINE);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
@@ -522,8 +518,6 @@ void bts_model_config_write_phy(struct vty *vty, struct phy_link *plink)
|
||||
vty_out(vty, " osmotrx ip remote %s%s",
|
||||
plink->u.osmotrx.remote_ip, VTY_NEWLINE);
|
||||
|
||||
vty_out(vty, " %sosmotrx timing-advance-loop%s", (plink->u.osmotrx.trx_ta_loop) ? "" : "no ", VTY_NEWLINE);
|
||||
|
||||
if (plink->u.osmotrx.base_port_local)
|
||||
vty_out(vty, " osmotrx base-port local %"PRIu16"%s",
|
||||
plink->u.osmotrx.base_port_local, VTY_NEWLINE);
|
||||
|
||||
@@ -128,12 +128,7 @@ static void virt_um_rcv_cb(struct virt_um_inst *vui, struct msgb *msg)
|
||||
break;
|
||||
case GSMTAP_CHANNEL_TCH_F:
|
||||
case GSMTAP_CHANNEL_TCH_H:
|
||||
#if 0
|
||||
/* TODO: handle voice messages */
|
||||
if (!facch && ! tch_acch) {
|
||||
osmo_prim_init(&l1sap.oph, SAP_GSM_PH, PRIM_TCH, PRIM_OP_INDICATION, msg);
|
||||
}
|
||||
#endif
|
||||
/* This is TCH signalling, for voice frames see GSMTAP_CHANNEL_VOICE */
|
||||
case GSMTAP_CHANNEL_SDCCH4:
|
||||
case GSMTAP_CHANNEL_SDCCH8:
|
||||
case GSMTAP_CHANNEL_PACCH:
|
||||
@@ -151,6 +146,19 @@ static void virt_um_rcv_cb(struct virt_um_inst *vui, struct msgb *msg)
|
||||
l1sap.u.data.pdch_presence_info = PRES_INFO_BOTH;
|
||||
l1if_process_meas_res(pinst->trx, timeslot, fn, chan_nr, 0, 0, 0, 0);
|
||||
break;
|
||||
case GSMTAP_CHANNEL_VOICE_F:
|
||||
case GSMTAP_CHANNEL_VOICE_H:
|
||||
/* the first byte indicates the type of voice codec (gsmtap_um_voice_type) */
|
||||
msg->l2h = msgb_pull(msg, 1);
|
||||
osmo_prim_init(&l1sap.oph, SAP_GSM_PH, PRIM_TCH, PRIM_OP_INDICATION, msg);
|
||||
l1sap.u.tch.chan_nr = chan_nr;
|
||||
l1sap.u.tch.fn = fn;
|
||||
l1sap.u.tch.rssi = 0; /* Radio Signal Strength Indicator. Best -> 0 */
|
||||
l1sap.u.tch.ber10k = 0; /* Bit Error Rate in 0.01%. Best -> 0 */
|
||||
l1sap.u.tch.ta_offs_256bits = 0; /* Burst time of arrival in quarter bits. Probably used for Timing Advance calc. Best -> 0 */
|
||||
l1sap.u.tch.lqual_cb = 10 * signal_dbm; /* Link quality in centiBel = 10 * dB. */
|
||||
l1if_process_meas_res(pinst->trx, timeslot, fn, chan_nr, 0, 0, 0, 0);
|
||||
break;
|
||||
case GSMTAP_CHANNEL_AGCH:
|
||||
case GSMTAP_CHANNEL_PCH:
|
||||
case GSMTAP_CHANNEL_BCCH:
|
||||
@@ -196,7 +204,7 @@ int bts_model_phy_link_open(struct phy_link *plink)
|
||||
|
||||
plink->u.virt.virt_um = virt_um_init(plink, plink->u.virt.ms_mcast_group, plink->u.virt.ms_mcast_port,
|
||||
plink->u.virt.bts_mcast_group, plink->u.virt.bts_mcast_port,
|
||||
virt_um_rcv_cb);
|
||||
plink->u.virt.ttl, plink->u.virt.mcast_dev, virt_um_rcv_cb);
|
||||
if (!plink->u.virt.virt_um) {
|
||||
phy_link_state_set(plink, PHY_LINK_SHUTDOWN);
|
||||
return -1;
|
||||
|
||||
@@ -119,10 +119,11 @@ void bts_model_abis_close(struct gsm_bts *bts)
|
||||
|
||||
void bts_model_phy_link_set_defaults(struct phy_link *plink)
|
||||
{
|
||||
plink->u.virt.bts_mcast_group = DEFAULT_BTS_MCAST_GROUP;
|
||||
plink->u.virt.bts_mcast_group = talloc_strdup(plink, DEFAULT_BTS_MCAST_GROUP);
|
||||
plink->u.virt.bts_mcast_port = DEFAULT_BTS_MCAST_PORT;
|
||||
plink->u.virt.ms_mcast_group = DEFAULT_MS_MCAST_GROUP;
|
||||
plink->u.virt.ms_mcast_group = talloc_strdup(plink, DEFAULT_MS_MCAST_GROUP);
|
||||
plink->u.virt.ms_mcast_port = DEFAULT_MS_MCAST_PORT;
|
||||
plink->u.virt.ttl = -1; /* initialize to -1 to prevent us setting the TTL */
|
||||
}
|
||||
|
||||
void bts_model_phy_instance_set_defaults(struct phy_instance *pinst)
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
#include <ctype.h>
|
||||
@@ -46,21 +47,13 @@
|
||||
|
||||
#define MODULO_HYPERFRAME 0
|
||||
|
||||
static const char *gsmtap_hdr_stringify(const struct gsmtap_hdr *gh)
|
||||
{
|
||||
static char buf[256];
|
||||
snprintf(buf, sizeof(buf), "(ARFCN=%u, ts=%u, ss=%u, type=%u/%u)",
|
||||
gh->arfcn & GSMTAP_ARFCN_MASK, gh->timeslot, gh->sub_slot, gh->type, gh->sub_type);
|
||||
return buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a message over the virtual um interface.
|
||||
* This will at first wrap the msg with a GSMTAP header and then write it to the declared multicast socket.
|
||||
* TODO: we might want to remove unused argument uint8_t tn
|
||||
*/
|
||||
static void tx_to_virt_um(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
||||
enum trx_chan_type chan, struct msgb *msg)
|
||||
static void _tx_to_virt_um(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
||||
enum trx_chan_type chan, struct msgb *msg, bool is_voice_frame)
|
||||
{
|
||||
const struct trx_chan_desc *chdesc = &trx_chan_desc[chan];
|
||||
struct msgb *outmsg; /* msg to send with gsmtap header prepended */
|
||||
@@ -83,7 +76,7 @@ static void tx_to_virt_um(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
||||
l1sap_fn2ccch_block(fn) >= num_agch(l1t->trx, "PH-DATA-REQ"))
|
||||
gsmtap_chantype = GSMTAP_CHANNEL_PCH;
|
||||
else
|
||||
gsmtap_chantype = chantype_rsl2gsmtap(rsl_chantype, chdesc->link_id); /* the logical channel type */
|
||||
gsmtap_chantype = chantype_rsl2gsmtap2(rsl_chantype, chdesc->link_id, is_voice_frame); /* the logical channel type */
|
||||
|
||||
#if MODULO_HYPERFRAME
|
||||
/* Restart fn after every superframe (26 * 51 frames) to simulate hyperframe overflow each 6 seconds. */
|
||||
@@ -94,18 +87,17 @@ static void tx_to_virt_um(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
||||
|
||||
if (outmsg) {
|
||||
struct phy_instance *pinst = trx_phy_instance(l1t->trx);
|
||||
struct gsmtap_hdr *gh = (struct gsmtap_hdr *)msgb_data(outmsg);
|
||||
int rc;
|
||||
|
||||
rc = virt_um_write_msg(pinst->phy_link->u.virt.virt_um, outmsg);
|
||||
if (rc < 0)
|
||||
LOGL1S(DL1P, LOGL_ERROR, l1t, tn, chan, fn,
|
||||
"%s GSMTAP msg could not send to virtual Um\n", gsmtap_hdr_stringify(gh));
|
||||
"GSMTAP msg could not send to virtual Um: %s\n", strerror(-rc));
|
||||
else if (rc == 0)
|
||||
bts_shutdown(l1t->trx->bts, "VirtPHY write socket died\n");
|
||||
else
|
||||
LOGL1S(DL1P, LOGL_DEBUG, l1t, tn, chan, fn,
|
||||
"%s Sending GSMTAP message to virtual Um\n", gsmtap_hdr_stringify(gh));
|
||||
"Sending GSMTAP message to virtual Um\n");
|
||||
} else
|
||||
LOGL1S(DL1P, LOGL_ERROR, l1t, tn, chan, fn, "GSMTAP msg could not be created!\n");
|
||||
|
||||
@@ -113,6 +105,65 @@ static void tx_to_virt_um(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
||||
msgb_free(msg);
|
||||
}
|
||||
|
||||
static void tx_to_virt_um(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
||||
enum trx_chan_type chan, struct msgb *msg)
|
||||
{
|
||||
_tx_to_virt_um(l1t, tn, fn, chan, msg, false);
|
||||
}
|
||||
|
||||
|
||||
static struct gsm_lchan *lchan_from_l1t(struct l1sched_trx *l1t, uint8_t tn, enum trx_chan_type chan)
|
||||
{
|
||||
struct gsm_bts_trx_ts *ts;
|
||||
uint8_t subslot = 0;
|
||||
|
||||
OSMO_ASSERT(l1t && l1t->trx);
|
||||
|
||||
if (chan == TRXC_TCHH_1)
|
||||
subslot = 1;
|
||||
|
||||
ts = &l1t->trx->ts[tn];
|
||||
return &ts->lchan[subslot];
|
||||
}
|
||||
|
||||
/* Determine the gsmtap_um_voice_type of a gsm_lchan */
|
||||
static int get_um_voice_type(const struct gsm_lchan *lchan)
|
||||
{
|
||||
switch (lchan->tch_mode) {
|
||||
case GSM48_CMODE_SPEECH_V1:
|
||||
if (lchan->type == GSM_LCHAN_TCH_H)
|
||||
return GSMTAP_UM_VOICE_HR;
|
||||
else
|
||||
return GSMTAP_UM_VOICE_FR;
|
||||
case GSM48_CMODE_SPEECH_EFR:
|
||||
return GSMTAP_UM_VOICE_EFR;
|
||||
case GSM48_CMODE_SPEECH_AMR:
|
||||
return GSMTAP_UM_VOICE_AMR;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static void tx_to_virt_um_voice_frame(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
||||
enum trx_chan_type chan, struct msgb *msg)
|
||||
{
|
||||
struct gsm_lchan *lchan = lchan_from_l1t(l1t, tn, chan);
|
||||
int um_voice_type;
|
||||
|
||||
OSMO_ASSERT(lchan);
|
||||
um_voice_type = get_um_voice_type(lchan);
|
||||
if (um_voice_type < 0) {
|
||||
LOGPLCHAN(lchan, DL1P, LOGL_ERROR, "Cannot determine Um voice type from lchan\n");
|
||||
um_voice_type = 0xff;
|
||||
}
|
||||
|
||||
/* the first byte indicates the type of voice codec (gsmtap_um_voice_type) */
|
||||
msgb_pull_to_l2(msg);
|
||||
msgb_push_u8(msg, um_voice_type);
|
||||
msg->l2h = msg->data;
|
||||
_tx_to_virt_um(l1t, tn, fn, chan, msg, true);
|
||||
}
|
||||
|
||||
/*
|
||||
* TX on downlink
|
||||
*/
|
||||
@@ -422,8 +473,8 @@ ubit_t *tx_tchf_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
||||
if (msg_facch) {
|
||||
tx_to_virt_um(l1t, tn, fn, chan, msg_facch);
|
||||
msgb_free(msg_tch);
|
||||
} else
|
||||
tx_to_virt_um(l1t, tn, fn, chan, msg_tch);
|
||||
} else if (msg_tch)
|
||||
tx_to_virt_um_voice_frame(l1t, tn, fn, chan, msg_tch);
|
||||
|
||||
send_burst:
|
||||
|
||||
@@ -464,7 +515,7 @@ ubit_t *tx_tchh_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
||||
tx_to_virt_um(l1t, tn, fn, chan, msg_facch);
|
||||
msgb_free(msg_tch);
|
||||
} else if (msg_tch)
|
||||
tx_to_virt_um(l1t, tn, fn, chan, msg_tch);
|
||||
tx_to_virt_um_voice_frame(l1t, tn, fn, chan, msg_tch);
|
||||
|
||||
send_burst:
|
||||
return NULL;
|
||||
|
||||
@@ -27,7 +27,9 @@
|
||||
#include <osmocom/core/talloc.h>
|
||||
#include "osmo_mcast_sock.h"
|
||||
#include "virtual_um.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
/**
|
||||
* Virtual UM interface file descriptor callback.
|
||||
@@ -60,10 +62,12 @@ static int virt_um_fd_cb(struct osmo_fd *ofd, unsigned int what)
|
||||
}
|
||||
|
||||
struct virt_um_inst *virt_um_init(void *ctx, char *tx_mcast_group, uint16_t tx_mcast_port,
|
||||
char *rx_mcast_group, uint16_t rx_mcast_port,
|
||||
char *rx_mcast_group, uint16_t rx_mcast_port, int ttl, const char *dev_name,
|
||||
void (*recv_cb)(struct virt_um_inst *vui, struct msgb *msg))
|
||||
{
|
||||
struct virt_um_inst *vui = talloc_zero(ctx, struct virt_um_inst);
|
||||
int rc;
|
||||
|
||||
vui->mcast_sock = mcast_bidir_sock_setup(ctx, tx_mcast_group, tx_mcast_port,
|
||||
rx_mcast_group, rx_mcast_port, 1, virt_um_fd_cb, vui);
|
||||
if (!vui->mcast_sock) {
|
||||
@@ -73,8 +77,34 @@ struct virt_um_inst *virt_um_init(void *ctx, char *tx_mcast_group, uint16_t tx_m
|
||||
}
|
||||
vui->recv_cb = recv_cb;
|
||||
|
||||
/* -1 means default, i.e. no TTL explicitly configured in VTY */
|
||||
if (ttl >= 0) {
|
||||
rc = osmo_sock_mcast_ttl_set(vui->mcast_sock->tx_ofd.fd, ttl);
|
||||
if (rc < 0) {
|
||||
perror("Cannot set TTL of Virtual Um transmit socket");
|
||||
goto out_close;
|
||||
}
|
||||
}
|
||||
|
||||
if (dev_name) {
|
||||
rc = osmo_sock_mcast_iface_set(vui->mcast_sock->tx_ofd.fd, dev_name);
|
||||
if (rc < 0) {
|
||||
perror("Cannot bind multicast tx to given device");
|
||||
goto out_close;
|
||||
}
|
||||
rc = osmo_sock_mcast_iface_set(vui->mcast_sock->rx_ofd.fd, dev_name);
|
||||
if (rc < 0) {
|
||||
perror("Cannot bind multicast rx to given device");
|
||||
goto out_close;
|
||||
}
|
||||
}
|
||||
|
||||
return vui;
|
||||
|
||||
out_close:
|
||||
mcast_bidir_sock_close(vui->mcast_sock);
|
||||
talloc_free(vui);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void virt_um_destroy(struct virt_um_inst *vui)
|
||||
@@ -93,7 +123,7 @@ int virt_um_write_msg(struct virt_um_inst *vui, struct msgb *msg)
|
||||
rc = mcast_bidir_sock_tx(vui->mcast_sock, msgb_data(msg),
|
||||
msgb_length(msg));
|
||||
if (rc < 0)
|
||||
perror("Writing to multicast socket");
|
||||
rc = -errno;
|
||||
msgb_free(msg);
|
||||
|
||||
return rc;
|
||||
|
||||
@@ -23,7 +23,7 @@ struct virt_um_inst {
|
||||
|
||||
struct virt_um_inst *virt_um_init(
|
||||
void *ctx, char *tx_mcast_group, uint16_t tx_mcast_port,
|
||||
char *rx_mcast_group, uint16_t rx_mcast_port,
|
||||
char *rx_mcast_group, uint16_t rx_mcast_port, int ttl, const char *dev_name,
|
||||
void (*recv_cb)(struct virt_um_inst *vui, struct msgb *msg));
|
||||
|
||||
void virt_um_destroy(struct virt_um_inst *vui);
|
||||
|
||||
@@ -69,6 +69,9 @@ void bts_model_config_write_phy(struct vty *vty, struct phy_link *plink)
|
||||
if (plink->u.virt.mcast_dev)
|
||||
vty_out(vty, " virtual-um net-device %s%s",
|
||||
plink->u.virt.mcast_dev, VTY_NEWLINE);
|
||||
if (plink->u.virt.ttl != -1)
|
||||
vty_out(vty, " virtual-um ttl %d%s",
|
||||
plink->u.virt.ttl, VTY_NEWLINE);
|
||||
if (strcmp(plink->u.virt.ms_mcast_group, DEFAULT_BTS_MCAST_GROUP))
|
||||
vty_out(vty, " virtual-um ms-multicast-group %s%s",
|
||||
plink->u.virt.ms_mcast_group, VTY_NEWLINE);
|
||||
@@ -171,6 +174,23 @@ DEFUN(cfg_phy_mcast_dev, cfg_phy_mcast_dev_cmd,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_phy_mcast_ttl, cfg_phy_mcast_ttl_cmd,
|
||||
"virtual-um ttl <0-255>",
|
||||
VUM_STR "Configure the TTL for transmitted multicast GSMTAP packets\n")
|
||||
{
|
||||
struct phy_link *plink = vty->index;
|
||||
|
||||
if (plink->state != PHY_LINK_SHUTDOWN) {
|
||||
vty_out(vty, "Can only reconfigure a PHY link that is down%s",
|
||||
VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
plink->u.virt.ttl = atoi(argv[0]);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
int bts_model_vty_init(struct gsm_bts *bts)
|
||||
{
|
||||
vty_bts = bts;
|
||||
@@ -180,6 +200,7 @@ int bts_model_vty_init(struct gsm_bts *bts)
|
||||
install_element(PHY_NODE, &cfg_phy_bts_mcast_group_cmd);
|
||||
install_element(PHY_NODE, &cfg_phy_bts_mcast_port_cmd);
|
||||
install_element(PHY_NODE, &cfg_phy_mcast_dev_cmd);
|
||||
install_element(PHY_NODE, &cfg_phy_mcast_ttl_cmd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
SUBDIRS = paging cipher agch misc handover tx_power power meas
|
||||
SUBDIRS = paging cipher agch misc handover tx_power power meas ta_control
|
||||
|
||||
if ENABLE_SYSMOBTS
|
||||
SUBDIRS += sysmobts
|
||||
|
||||
@@ -585,8 +585,8 @@ meas.ext.toa256_min | 0 | 0
|
||||
meas.ext.toa256_max | 0 | 0
|
||||
meas.ms_toa256 | 0 | 0
|
||||
meas.ext.toa256_std_dev | 0 | 0
|
||||
meas.ul_res.full.rx_lev | 63 | 63
|
||||
meas.ul_res.full.rx_qual | 3 | 3
|
||||
meas.ul_res.full.rx_lev | 1 | 1
|
||||
meas.ul_res.full.rx_qual | 7 | 7
|
||||
|
||||
|
||||
===========================================================
|
||||
|
||||
@@ -131,8 +131,8 @@ static const struct meas_testcase mtc4 = {
|
||||
.pchan = GSM_PCHAN_TCH_F,
|
||||
.res = {
|
||||
.success = 1,
|
||||
.rx_lev_full = 63,
|
||||
.rx_qual_full = 3,
|
||||
.rx_lev_full = 1,
|
||||
.rx_qual_full = 7,
|
||||
.toa256_mean = 0,
|
||||
.toa256_max = 0,
|
||||
.toa256_min = 0,
|
||||
|
||||
6
tests/ta_control/Makefile.am
Normal file
6
tests/ta_control/Makefile.am
Normal file
@@ -0,0 +1,6 @@
|
||||
AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include
|
||||
AM_CFLAGS = -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOCODEC_CFLAGS) $(LIBOSMOTRAU_CFLAGS) $(LIBOSMOABIS_CFLAGS)
|
||||
LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(LIBOSMOCODEC_LIBS) $(LIBOSMOTRAU_LIBS) $(LIBOSMOABIS_LIBS)
|
||||
noinst_PROGRAMS = ta_control_test
|
||||
EXTRA_DIST = ta_control_test.ok
|
||||
ta_control_test_LDADD = $(top_builddir)/src/common/libbts.a $(LDADD)
|
||||
77
tests/ta_control/ta_control_test.c
Normal file
77
tests/ta_control/ta_control_test.c
Normal file
@@ -0,0 +1,77 @@
|
||||
/* Test cases for tx_control.c Timing Advance Computation */
|
||||
|
||||
/* (C) 2016 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
|
||||
* All Rights Reserved
|
||||
*
|
||||
* Author: Philipp Maier
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation; either version 3 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <osmocom/core/talloc.h>
|
||||
#include <osmocom/core/application.h>
|
||||
#include <osmo-bts/logging.h>
|
||||
#include <osmo-bts/gsm_data.h>
|
||||
#include <osmo-bts/ta_control.h>
|
||||
|
||||
void lchan_ms_ta_ctrl_test(int16_t toa256_start, unsigned int steps)
|
||||
{
|
||||
struct gsm_lchan lchan = { };
|
||||
unsigned int i;
|
||||
uint8_t rqd_ta_after;
|
||||
uint8_t rqd_ta_before;
|
||||
int16_t toa256 = toa256_start;
|
||||
|
||||
/* Arbitrary value, high enough so that a computation can happen. */
|
||||
lchan.meas.num_ul_meas = 10;
|
||||
|
||||
printf("toa256_start = %u / 256 = %u, steps = %u\n", toa256_start,
|
||||
toa256_start / 256, steps);
|
||||
|
||||
for (i = 0; i < steps; i++) {
|
||||
printf("Step #%u\n", i);
|
||||
printf(" lchan.rqd_ta (before) = %u\n", lchan.rqd_ta);
|
||||
printf(" toa256 (before) = %u / 256 = %u\n", toa256,
|
||||
toa256 / 256);
|
||||
|
||||
rqd_ta_before = lchan.rqd_ta;
|
||||
|
||||
lchan.meas.ms_toa256 = toa256;
|
||||
lchan_ms_ta_ctrl(&lchan);
|
||||
|
||||
rqd_ta_after = lchan.rqd_ta;
|
||||
toa256 -= (rqd_ta_after - rqd_ta_before) * 256;
|
||||
|
||||
printf(" lchan.rqd_ta (after) = %u\n", lchan.rqd_ta);
|
||||
printf(" toa256 (after) = %u / 256 = %u\n", toa256,
|
||||
toa256 / 256);
|
||||
}
|
||||
|
||||
printf("Done.\n");
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
void *tall_bts_ctx;
|
||||
|
||||
tall_bts_ctx = talloc_named_const(NULL, 1, "OsmoBTS context");
|
||||
osmo_init_logging2(tall_bts_ctx, &bts_log_info);
|
||||
|
||||
lchan_ms_ta_ctrl_test(16 * 256, 20);
|
||||
lchan_ms_ta_ctrl_test(4000, 50);
|
||||
lchan_ms_ta_ctrl_test(12345, 50);
|
||||
}
|
||||
609
tests/ta_control/ta_control_test.ok
Normal file
609
tests/ta_control/ta_control_test.ok
Normal file
@@ -0,0 +1,609 @@
|
||||
toa256_start = 4096 / 256 = 16, steps = 20
|
||||
Step #0
|
||||
lchan.rqd_ta (before) = 0
|
||||
toa256 (before) = 4096 / 256 = 16
|
||||
lchan.rqd_ta (after) = 1
|
||||
toa256 (after) = 3840 / 256 = 15
|
||||
Step #1
|
||||
lchan.rqd_ta (before) = 1
|
||||
toa256 (before) = 3840 / 256 = 15
|
||||
lchan.rqd_ta (after) = 2
|
||||
toa256 (after) = 3584 / 256 = 14
|
||||
Step #2
|
||||
lchan.rqd_ta (before) = 2
|
||||
toa256 (before) = 3584 / 256 = 14
|
||||
lchan.rqd_ta (after) = 3
|
||||
toa256 (after) = 3328 / 256 = 13
|
||||
Step #3
|
||||
lchan.rqd_ta (before) = 3
|
||||
toa256 (before) = 3328 / 256 = 13
|
||||
lchan.rqd_ta (after) = 4
|
||||
toa256 (after) = 3072 / 256 = 12
|
||||
Step #4
|
||||
lchan.rqd_ta (before) = 4
|
||||
toa256 (before) = 3072 / 256 = 12
|
||||
lchan.rqd_ta (after) = 5
|
||||
toa256 (after) = 2816 / 256 = 11
|
||||
Step #5
|
||||
lchan.rqd_ta (before) = 5
|
||||
toa256 (before) = 2816 / 256 = 11
|
||||
lchan.rqd_ta (after) = 6
|
||||
toa256 (after) = 2560 / 256 = 10
|
||||
Step #6
|
||||
lchan.rqd_ta (before) = 6
|
||||
toa256 (before) = 2560 / 256 = 10
|
||||
lchan.rqd_ta (after) = 7
|
||||
toa256 (after) = 2304 / 256 = 9
|
||||
Step #7
|
||||
lchan.rqd_ta (before) = 7
|
||||
toa256 (before) = 2304 / 256 = 9
|
||||
lchan.rqd_ta (after) = 8
|
||||
toa256 (after) = 2048 / 256 = 8
|
||||
Step #8
|
||||
lchan.rqd_ta (before) = 8
|
||||
toa256 (before) = 2048 / 256 = 8
|
||||
lchan.rqd_ta (after) = 9
|
||||
toa256 (after) = 1792 / 256 = 7
|
||||
Step #9
|
||||
lchan.rqd_ta (before) = 9
|
||||
toa256 (before) = 1792 / 256 = 7
|
||||
lchan.rqd_ta (after) = 10
|
||||
toa256 (after) = 1536 / 256 = 6
|
||||
Step #10
|
||||
lchan.rqd_ta (before) = 10
|
||||
toa256 (before) = 1536 / 256 = 6
|
||||
lchan.rqd_ta (after) = 11
|
||||
toa256 (after) = 1280 / 256 = 5
|
||||
Step #11
|
||||
lchan.rqd_ta (before) = 11
|
||||
toa256 (before) = 1280 / 256 = 5
|
||||
lchan.rqd_ta (after) = 12
|
||||
toa256 (after) = 1024 / 256 = 4
|
||||
Step #12
|
||||
lchan.rqd_ta (before) = 12
|
||||
toa256 (before) = 1024 / 256 = 4
|
||||
lchan.rqd_ta (after) = 13
|
||||
toa256 (after) = 768 / 256 = 3
|
||||
Step #13
|
||||
lchan.rqd_ta (before) = 13
|
||||
toa256 (before) = 768 / 256 = 3
|
||||
lchan.rqd_ta (after) = 14
|
||||
toa256 (after) = 512 / 256 = 2
|
||||
Step #14
|
||||
lchan.rqd_ta (before) = 14
|
||||
toa256 (before) = 512 / 256 = 2
|
||||
lchan.rqd_ta (after) = 15
|
||||
toa256 (after) = 256 / 256 = 1
|
||||
Step #15
|
||||
lchan.rqd_ta (before) = 15
|
||||
toa256 (before) = 256 / 256 = 1
|
||||
lchan.rqd_ta (after) = 16
|
||||
toa256 (after) = 0 / 256 = 0
|
||||
Step #16
|
||||
lchan.rqd_ta (before) = 16
|
||||
toa256 (before) = 0 / 256 = 0
|
||||
lchan.rqd_ta (after) = 16
|
||||
toa256 (after) = 0 / 256 = 0
|
||||
Step #17
|
||||
lchan.rqd_ta (before) = 16
|
||||
toa256 (before) = 0 / 256 = 0
|
||||
lchan.rqd_ta (after) = 16
|
||||
toa256 (after) = 0 / 256 = 0
|
||||
Step #18
|
||||
lchan.rqd_ta (before) = 16
|
||||
toa256 (before) = 0 / 256 = 0
|
||||
lchan.rqd_ta (after) = 16
|
||||
toa256 (after) = 0 / 256 = 0
|
||||
Step #19
|
||||
lchan.rqd_ta (before) = 16
|
||||
toa256 (before) = 0 / 256 = 0
|
||||
lchan.rqd_ta (after) = 16
|
||||
toa256 (after) = 0 / 256 = 0
|
||||
Done.
|
||||
|
||||
toa256_start = 4000 / 256 = 15, steps = 50
|
||||
Step #0
|
||||
lchan.rqd_ta (before) = 0
|
||||
toa256 (before) = 4000 / 256 = 15
|
||||
lchan.rqd_ta (after) = 1
|
||||
toa256 (after) = 3744 / 256 = 14
|
||||
Step #1
|
||||
lchan.rqd_ta (before) = 1
|
||||
toa256 (before) = 3744 / 256 = 14
|
||||
lchan.rqd_ta (after) = 2
|
||||
toa256 (after) = 3488 / 256 = 13
|
||||
Step #2
|
||||
lchan.rqd_ta (before) = 2
|
||||
toa256 (before) = 3488 / 256 = 13
|
||||
lchan.rqd_ta (after) = 3
|
||||
toa256 (after) = 3232 / 256 = 12
|
||||
Step #3
|
||||
lchan.rqd_ta (before) = 3
|
||||
toa256 (before) = 3232 / 256 = 12
|
||||
lchan.rqd_ta (after) = 4
|
||||
toa256 (after) = 2976 / 256 = 11
|
||||
Step #4
|
||||
lchan.rqd_ta (before) = 4
|
||||
toa256 (before) = 2976 / 256 = 11
|
||||
lchan.rqd_ta (after) = 5
|
||||
toa256 (after) = 2720 / 256 = 10
|
||||
Step #5
|
||||
lchan.rqd_ta (before) = 5
|
||||
toa256 (before) = 2720 / 256 = 10
|
||||
lchan.rqd_ta (after) = 6
|
||||
toa256 (after) = 2464 / 256 = 9
|
||||
Step #6
|
||||
lchan.rqd_ta (before) = 6
|
||||
toa256 (before) = 2464 / 256 = 9
|
||||
lchan.rqd_ta (after) = 7
|
||||
toa256 (after) = 2208 / 256 = 8
|
||||
Step #7
|
||||
lchan.rqd_ta (before) = 7
|
||||
toa256 (before) = 2208 / 256 = 8
|
||||
lchan.rqd_ta (after) = 8
|
||||
toa256 (after) = 1952 / 256 = 7
|
||||
Step #8
|
||||
lchan.rqd_ta (before) = 8
|
||||
toa256 (before) = 1952 / 256 = 7
|
||||
lchan.rqd_ta (after) = 9
|
||||
toa256 (after) = 1696 / 256 = 6
|
||||
Step #9
|
||||
lchan.rqd_ta (before) = 9
|
||||
toa256 (before) = 1696 / 256 = 6
|
||||
lchan.rqd_ta (after) = 10
|
||||
toa256 (after) = 1440 / 256 = 5
|
||||
Step #10
|
||||
lchan.rqd_ta (before) = 10
|
||||
toa256 (before) = 1440 / 256 = 5
|
||||
lchan.rqd_ta (after) = 11
|
||||
toa256 (after) = 1184 / 256 = 4
|
||||
Step #11
|
||||
lchan.rqd_ta (before) = 11
|
||||
toa256 (before) = 1184 / 256 = 4
|
||||
lchan.rqd_ta (after) = 12
|
||||
toa256 (after) = 928 / 256 = 3
|
||||
Step #12
|
||||
lchan.rqd_ta (before) = 12
|
||||
toa256 (before) = 928 / 256 = 3
|
||||
lchan.rqd_ta (after) = 13
|
||||
toa256 (after) = 672 / 256 = 2
|
||||
Step #13
|
||||
lchan.rqd_ta (before) = 13
|
||||
toa256 (before) = 672 / 256 = 2
|
||||
lchan.rqd_ta (after) = 14
|
||||
toa256 (after) = 416 / 256 = 1
|
||||
Step #14
|
||||
lchan.rqd_ta (before) = 14
|
||||
toa256 (before) = 416 / 256 = 1
|
||||
lchan.rqd_ta (after) = 15
|
||||
toa256 (after) = 160 / 256 = 0
|
||||
Step #15
|
||||
lchan.rqd_ta (before) = 15
|
||||
toa256 (before) = 160 / 256 = 0
|
||||
lchan.rqd_ta (after) = 15
|
||||
toa256 (after) = 160 / 256 = 0
|
||||
Step #16
|
||||
lchan.rqd_ta (before) = 15
|
||||
toa256 (before) = 160 / 256 = 0
|
||||
lchan.rqd_ta (after) = 15
|
||||
toa256 (after) = 160 / 256 = 0
|
||||
Step #17
|
||||
lchan.rqd_ta (before) = 15
|
||||
toa256 (before) = 160 / 256 = 0
|
||||
lchan.rqd_ta (after) = 15
|
||||
toa256 (after) = 160 / 256 = 0
|
||||
Step #18
|
||||
lchan.rqd_ta (before) = 15
|
||||
toa256 (before) = 160 / 256 = 0
|
||||
lchan.rqd_ta (after) = 15
|
||||
toa256 (after) = 160 / 256 = 0
|
||||
Step #19
|
||||
lchan.rqd_ta (before) = 15
|
||||
toa256 (before) = 160 / 256 = 0
|
||||
lchan.rqd_ta (after) = 15
|
||||
toa256 (after) = 160 / 256 = 0
|
||||
Step #20
|
||||
lchan.rqd_ta (before) = 15
|
||||
toa256 (before) = 160 / 256 = 0
|
||||
lchan.rqd_ta (after) = 15
|
||||
toa256 (after) = 160 / 256 = 0
|
||||
Step #21
|
||||
lchan.rqd_ta (before) = 15
|
||||
toa256 (before) = 160 / 256 = 0
|
||||
lchan.rqd_ta (after) = 15
|
||||
toa256 (after) = 160 / 256 = 0
|
||||
Step #22
|
||||
lchan.rqd_ta (before) = 15
|
||||
toa256 (before) = 160 / 256 = 0
|
||||
lchan.rqd_ta (after) = 15
|
||||
toa256 (after) = 160 / 256 = 0
|
||||
Step #23
|
||||
lchan.rqd_ta (before) = 15
|
||||
toa256 (before) = 160 / 256 = 0
|
||||
lchan.rqd_ta (after) = 15
|
||||
toa256 (after) = 160 / 256 = 0
|
||||
Step #24
|
||||
lchan.rqd_ta (before) = 15
|
||||
toa256 (before) = 160 / 256 = 0
|
||||
lchan.rqd_ta (after) = 15
|
||||
toa256 (after) = 160 / 256 = 0
|
||||
Step #25
|
||||
lchan.rqd_ta (before) = 15
|
||||
toa256 (before) = 160 / 256 = 0
|
||||
lchan.rqd_ta (after) = 15
|
||||
toa256 (after) = 160 / 256 = 0
|
||||
Step #26
|
||||
lchan.rqd_ta (before) = 15
|
||||
toa256 (before) = 160 / 256 = 0
|
||||
lchan.rqd_ta (after) = 15
|
||||
toa256 (after) = 160 / 256 = 0
|
||||
Step #27
|
||||
lchan.rqd_ta (before) = 15
|
||||
toa256 (before) = 160 / 256 = 0
|
||||
lchan.rqd_ta (after) = 15
|
||||
toa256 (after) = 160 / 256 = 0
|
||||
Step #28
|
||||
lchan.rqd_ta (before) = 15
|
||||
toa256 (before) = 160 / 256 = 0
|
||||
lchan.rqd_ta (after) = 15
|
||||
toa256 (after) = 160 / 256 = 0
|
||||
Step #29
|
||||
lchan.rqd_ta (before) = 15
|
||||
toa256 (before) = 160 / 256 = 0
|
||||
lchan.rqd_ta (after) = 15
|
||||
toa256 (after) = 160 / 256 = 0
|
||||
Step #30
|
||||
lchan.rqd_ta (before) = 15
|
||||
toa256 (before) = 160 / 256 = 0
|
||||
lchan.rqd_ta (after) = 15
|
||||
toa256 (after) = 160 / 256 = 0
|
||||
Step #31
|
||||
lchan.rqd_ta (before) = 15
|
||||
toa256 (before) = 160 / 256 = 0
|
||||
lchan.rqd_ta (after) = 15
|
||||
toa256 (after) = 160 / 256 = 0
|
||||
Step #32
|
||||
lchan.rqd_ta (before) = 15
|
||||
toa256 (before) = 160 / 256 = 0
|
||||
lchan.rqd_ta (after) = 15
|
||||
toa256 (after) = 160 / 256 = 0
|
||||
Step #33
|
||||
lchan.rqd_ta (before) = 15
|
||||
toa256 (before) = 160 / 256 = 0
|
||||
lchan.rqd_ta (after) = 15
|
||||
toa256 (after) = 160 / 256 = 0
|
||||
Step #34
|
||||
lchan.rqd_ta (before) = 15
|
||||
toa256 (before) = 160 / 256 = 0
|
||||
lchan.rqd_ta (after) = 15
|
||||
toa256 (after) = 160 / 256 = 0
|
||||
Step #35
|
||||
lchan.rqd_ta (before) = 15
|
||||
toa256 (before) = 160 / 256 = 0
|
||||
lchan.rqd_ta (after) = 15
|
||||
toa256 (after) = 160 / 256 = 0
|
||||
Step #36
|
||||
lchan.rqd_ta (before) = 15
|
||||
toa256 (before) = 160 / 256 = 0
|
||||
lchan.rqd_ta (after) = 15
|
||||
toa256 (after) = 160 / 256 = 0
|
||||
Step #37
|
||||
lchan.rqd_ta (before) = 15
|
||||
toa256 (before) = 160 / 256 = 0
|
||||
lchan.rqd_ta (after) = 15
|
||||
toa256 (after) = 160 / 256 = 0
|
||||
Step #38
|
||||
lchan.rqd_ta (before) = 15
|
||||
toa256 (before) = 160 / 256 = 0
|
||||
lchan.rqd_ta (after) = 15
|
||||
toa256 (after) = 160 / 256 = 0
|
||||
Step #39
|
||||
lchan.rqd_ta (before) = 15
|
||||
toa256 (before) = 160 / 256 = 0
|
||||
lchan.rqd_ta (after) = 15
|
||||
toa256 (after) = 160 / 256 = 0
|
||||
Step #40
|
||||
lchan.rqd_ta (before) = 15
|
||||
toa256 (before) = 160 / 256 = 0
|
||||
lchan.rqd_ta (after) = 15
|
||||
toa256 (after) = 160 / 256 = 0
|
||||
Step #41
|
||||
lchan.rqd_ta (before) = 15
|
||||
toa256 (before) = 160 / 256 = 0
|
||||
lchan.rqd_ta (after) = 15
|
||||
toa256 (after) = 160 / 256 = 0
|
||||
Step #42
|
||||
lchan.rqd_ta (before) = 15
|
||||
toa256 (before) = 160 / 256 = 0
|
||||
lchan.rqd_ta (after) = 15
|
||||
toa256 (after) = 160 / 256 = 0
|
||||
Step #43
|
||||
lchan.rqd_ta (before) = 15
|
||||
toa256 (before) = 160 / 256 = 0
|
||||
lchan.rqd_ta (after) = 15
|
||||
toa256 (after) = 160 / 256 = 0
|
||||
Step #44
|
||||
lchan.rqd_ta (before) = 15
|
||||
toa256 (before) = 160 / 256 = 0
|
||||
lchan.rqd_ta (after) = 15
|
||||
toa256 (after) = 160 / 256 = 0
|
||||
Step #45
|
||||
lchan.rqd_ta (before) = 15
|
||||
toa256 (before) = 160 / 256 = 0
|
||||
lchan.rqd_ta (after) = 15
|
||||
toa256 (after) = 160 / 256 = 0
|
||||
Step #46
|
||||
lchan.rqd_ta (before) = 15
|
||||
toa256 (before) = 160 / 256 = 0
|
||||
lchan.rqd_ta (after) = 15
|
||||
toa256 (after) = 160 / 256 = 0
|
||||
Step #47
|
||||
lchan.rqd_ta (before) = 15
|
||||
toa256 (before) = 160 / 256 = 0
|
||||
lchan.rqd_ta (after) = 15
|
||||
toa256 (after) = 160 / 256 = 0
|
||||
Step #48
|
||||
lchan.rqd_ta (before) = 15
|
||||
toa256 (before) = 160 / 256 = 0
|
||||
lchan.rqd_ta (after) = 15
|
||||
toa256 (after) = 160 / 256 = 0
|
||||
Step #49
|
||||
lchan.rqd_ta (before) = 15
|
||||
toa256 (before) = 160 / 256 = 0
|
||||
lchan.rqd_ta (after) = 15
|
||||
toa256 (after) = 160 / 256 = 0
|
||||
Done.
|
||||
|
||||
toa256_start = 12345 / 256 = 48, steps = 50
|
||||
Step #0
|
||||
lchan.rqd_ta (before) = 0
|
||||
toa256 (before) = 12345 / 256 = 48
|
||||
lchan.rqd_ta (after) = 1
|
||||
toa256 (after) = 12089 / 256 = 47
|
||||
Step #1
|
||||
lchan.rqd_ta (before) = 1
|
||||
toa256 (before) = 12089 / 256 = 47
|
||||
lchan.rqd_ta (after) = 2
|
||||
toa256 (after) = 11833 / 256 = 46
|
||||
Step #2
|
||||
lchan.rqd_ta (before) = 2
|
||||
toa256 (before) = 11833 / 256 = 46
|
||||
lchan.rqd_ta (after) = 3
|
||||
toa256 (after) = 11577 / 256 = 45
|
||||
Step #3
|
||||
lchan.rqd_ta (before) = 3
|
||||
toa256 (before) = 11577 / 256 = 45
|
||||
lchan.rqd_ta (after) = 4
|
||||
toa256 (after) = 11321 / 256 = 44
|
||||
Step #4
|
||||
lchan.rqd_ta (before) = 4
|
||||
toa256 (before) = 11321 / 256 = 44
|
||||
lchan.rqd_ta (after) = 5
|
||||
toa256 (after) = 11065 / 256 = 43
|
||||
Step #5
|
||||
lchan.rqd_ta (before) = 5
|
||||
toa256 (before) = 11065 / 256 = 43
|
||||
lchan.rqd_ta (after) = 6
|
||||
toa256 (after) = 10809 / 256 = 42
|
||||
Step #6
|
||||
lchan.rqd_ta (before) = 6
|
||||
toa256 (before) = 10809 / 256 = 42
|
||||
lchan.rqd_ta (after) = 7
|
||||
toa256 (after) = 10553 / 256 = 41
|
||||
Step #7
|
||||
lchan.rqd_ta (before) = 7
|
||||
toa256 (before) = 10553 / 256 = 41
|
||||
lchan.rqd_ta (after) = 8
|
||||
toa256 (after) = 10297 / 256 = 40
|
||||
Step #8
|
||||
lchan.rqd_ta (before) = 8
|
||||
toa256 (before) = 10297 / 256 = 40
|
||||
lchan.rqd_ta (after) = 9
|
||||
toa256 (after) = 10041 / 256 = 39
|
||||
Step #9
|
||||
lchan.rqd_ta (before) = 9
|
||||
toa256 (before) = 10041 / 256 = 39
|
||||
lchan.rqd_ta (after) = 10
|
||||
toa256 (after) = 9785 / 256 = 38
|
||||
Step #10
|
||||
lchan.rqd_ta (before) = 10
|
||||
toa256 (before) = 9785 / 256 = 38
|
||||
lchan.rqd_ta (after) = 11
|
||||
toa256 (after) = 9529 / 256 = 37
|
||||
Step #11
|
||||
lchan.rqd_ta (before) = 11
|
||||
toa256 (before) = 9529 / 256 = 37
|
||||
lchan.rqd_ta (after) = 12
|
||||
toa256 (after) = 9273 / 256 = 36
|
||||
Step #12
|
||||
lchan.rqd_ta (before) = 12
|
||||
toa256 (before) = 9273 / 256 = 36
|
||||
lchan.rqd_ta (after) = 13
|
||||
toa256 (after) = 9017 / 256 = 35
|
||||
Step #13
|
||||
lchan.rqd_ta (before) = 13
|
||||
toa256 (before) = 9017 / 256 = 35
|
||||
lchan.rqd_ta (after) = 14
|
||||
toa256 (after) = 8761 / 256 = 34
|
||||
Step #14
|
||||
lchan.rqd_ta (before) = 14
|
||||
toa256 (before) = 8761 / 256 = 34
|
||||
lchan.rqd_ta (after) = 15
|
||||
toa256 (after) = 8505 / 256 = 33
|
||||
Step #15
|
||||
lchan.rqd_ta (before) = 15
|
||||
toa256 (before) = 8505 / 256 = 33
|
||||
lchan.rqd_ta (after) = 16
|
||||
toa256 (after) = 8249 / 256 = 32
|
||||
Step #16
|
||||
lchan.rqd_ta (before) = 16
|
||||
toa256 (before) = 8249 / 256 = 32
|
||||
lchan.rqd_ta (after) = 17
|
||||
toa256 (after) = 7993 / 256 = 31
|
||||
Step #17
|
||||
lchan.rqd_ta (before) = 17
|
||||
toa256 (before) = 7993 / 256 = 31
|
||||
lchan.rqd_ta (after) = 18
|
||||
toa256 (after) = 7737 / 256 = 30
|
||||
Step #18
|
||||
lchan.rqd_ta (before) = 18
|
||||
toa256 (before) = 7737 / 256 = 30
|
||||
lchan.rqd_ta (after) = 19
|
||||
toa256 (after) = 7481 / 256 = 29
|
||||
Step #19
|
||||
lchan.rqd_ta (before) = 19
|
||||
toa256 (before) = 7481 / 256 = 29
|
||||
lchan.rqd_ta (after) = 20
|
||||
toa256 (after) = 7225 / 256 = 28
|
||||
Step #20
|
||||
lchan.rqd_ta (before) = 20
|
||||
toa256 (before) = 7225 / 256 = 28
|
||||
lchan.rqd_ta (after) = 21
|
||||
toa256 (after) = 6969 / 256 = 27
|
||||
Step #21
|
||||
lchan.rqd_ta (before) = 21
|
||||
toa256 (before) = 6969 / 256 = 27
|
||||
lchan.rqd_ta (after) = 22
|
||||
toa256 (after) = 6713 / 256 = 26
|
||||
Step #22
|
||||
lchan.rqd_ta (before) = 22
|
||||
toa256 (before) = 6713 / 256 = 26
|
||||
lchan.rqd_ta (after) = 23
|
||||
toa256 (after) = 6457 / 256 = 25
|
||||
Step #23
|
||||
lchan.rqd_ta (before) = 23
|
||||
toa256 (before) = 6457 / 256 = 25
|
||||
lchan.rqd_ta (after) = 24
|
||||
toa256 (after) = 6201 / 256 = 24
|
||||
Step #24
|
||||
lchan.rqd_ta (before) = 24
|
||||
toa256 (before) = 6201 / 256 = 24
|
||||
lchan.rqd_ta (after) = 25
|
||||
toa256 (after) = 5945 / 256 = 23
|
||||
Step #25
|
||||
lchan.rqd_ta (before) = 25
|
||||
toa256 (before) = 5945 / 256 = 23
|
||||
lchan.rqd_ta (after) = 26
|
||||
toa256 (after) = 5689 / 256 = 22
|
||||
Step #26
|
||||
lchan.rqd_ta (before) = 26
|
||||
toa256 (before) = 5689 / 256 = 22
|
||||
lchan.rqd_ta (after) = 27
|
||||
toa256 (after) = 5433 / 256 = 21
|
||||
Step #27
|
||||
lchan.rqd_ta (before) = 27
|
||||
toa256 (before) = 5433 / 256 = 21
|
||||
lchan.rqd_ta (after) = 28
|
||||
toa256 (after) = 5177 / 256 = 20
|
||||
Step #28
|
||||
lchan.rqd_ta (before) = 28
|
||||
toa256 (before) = 5177 / 256 = 20
|
||||
lchan.rqd_ta (after) = 29
|
||||
toa256 (after) = 4921 / 256 = 19
|
||||
Step #29
|
||||
lchan.rqd_ta (before) = 29
|
||||
toa256 (before) = 4921 / 256 = 19
|
||||
lchan.rqd_ta (after) = 30
|
||||
toa256 (after) = 4665 / 256 = 18
|
||||
Step #30
|
||||
lchan.rqd_ta (before) = 30
|
||||
toa256 (before) = 4665 / 256 = 18
|
||||
lchan.rqd_ta (after) = 31
|
||||
toa256 (after) = 4409 / 256 = 17
|
||||
Step #31
|
||||
lchan.rqd_ta (before) = 31
|
||||
toa256 (before) = 4409 / 256 = 17
|
||||
lchan.rqd_ta (after) = 32
|
||||
toa256 (after) = 4153 / 256 = 16
|
||||
Step #32
|
||||
lchan.rqd_ta (before) = 32
|
||||
toa256 (before) = 4153 / 256 = 16
|
||||
lchan.rqd_ta (after) = 33
|
||||
toa256 (after) = 3897 / 256 = 15
|
||||
Step #33
|
||||
lchan.rqd_ta (before) = 33
|
||||
toa256 (before) = 3897 / 256 = 15
|
||||
lchan.rqd_ta (after) = 34
|
||||
toa256 (after) = 3641 / 256 = 14
|
||||
Step #34
|
||||
lchan.rqd_ta (before) = 34
|
||||
toa256 (before) = 3641 / 256 = 14
|
||||
lchan.rqd_ta (after) = 35
|
||||
toa256 (after) = 3385 / 256 = 13
|
||||
Step #35
|
||||
lchan.rqd_ta (before) = 35
|
||||
toa256 (before) = 3385 / 256 = 13
|
||||
lchan.rqd_ta (after) = 36
|
||||
toa256 (after) = 3129 / 256 = 12
|
||||
Step #36
|
||||
lchan.rqd_ta (before) = 36
|
||||
toa256 (before) = 3129 / 256 = 12
|
||||
lchan.rqd_ta (after) = 37
|
||||
toa256 (after) = 2873 / 256 = 11
|
||||
Step #37
|
||||
lchan.rqd_ta (before) = 37
|
||||
toa256 (before) = 2873 / 256 = 11
|
||||
lchan.rqd_ta (after) = 38
|
||||
toa256 (after) = 2617 / 256 = 10
|
||||
Step #38
|
||||
lchan.rqd_ta (before) = 38
|
||||
toa256 (before) = 2617 / 256 = 10
|
||||
lchan.rqd_ta (after) = 39
|
||||
toa256 (after) = 2361 / 256 = 9
|
||||
Step #39
|
||||
lchan.rqd_ta (before) = 39
|
||||
toa256 (before) = 2361 / 256 = 9
|
||||
lchan.rqd_ta (after) = 40
|
||||
toa256 (after) = 2105 / 256 = 8
|
||||
Step #40
|
||||
lchan.rqd_ta (before) = 40
|
||||
toa256 (before) = 2105 / 256 = 8
|
||||
lchan.rqd_ta (after) = 41
|
||||
toa256 (after) = 1849 / 256 = 7
|
||||
Step #41
|
||||
lchan.rqd_ta (before) = 41
|
||||
toa256 (before) = 1849 / 256 = 7
|
||||
lchan.rqd_ta (after) = 42
|
||||
toa256 (after) = 1593 / 256 = 6
|
||||
Step #42
|
||||
lchan.rqd_ta (before) = 42
|
||||
toa256 (before) = 1593 / 256 = 6
|
||||
lchan.rqd_ta (after) = 43
|
||||
toa256 (after) = 1337 / 256 = 5
|
||||
Step #43
|
||||
lchan.rqd_ta (before) = 43
|
||||
toa256 (before) = 1337 / 256 = 5
|
||||
lchan.rqd_ta (after) = 44
|
||||
toa256 (after) = 1081 / 256 = 4
|
||||
Step #44
|
||||
lchan.rqd_ta (before) = 44
|
||||
toa256 (before) = 1081 / 256 = 4
|
||||
lchan.rqd_ta (after) = 45
|
||||
toa256 (after) = 825 / 256 = 3
|
||||
Step #45
|
||||
lchan.rqd_ta (before) = 45
|
||||
toa256 (before) = 825 / 256 = 3
|
||||
lchan.rqd_ta (after) = 46
|
||||
toa256 (after) = 569 / 256 = 2
|
||||
Step #46
|
||||
lchan.rqd_ta (before) = 46
|
||||
toa256 (before) = 569 / 256 = 2
|
||||
lchan.rqd_ta (after) = 47
|
||||
toa256 (after) = 313 / 256 = 1
|
||||
Step #47
|
||||
lchan.rqd_ta (before) = 47
|
||||
toa256 (before) = 313 / 256 = 1
|
||||
lchan.rqd_ta (after) = 48
|
||||
toa256 (after) = 57 / 256 = 0
|
||||
Step #48
|
||||
lchan.rqd_ta (before) = 48
|
||||
toa256 (before) = 57 / 256 = 0
|
||||
lchan.rqd_ta (after) = 48
|
||||
toa256 (after) = 57 / 256 = 0
|
||||
Step #49
|
||||
lchan.rqd_ta (before) = 48
|
||||
toa256 (before) = 57 / 256 = 0
|
||||
lchan.rqd_ta (after) = 48
|
||||
toa256 (after) = 57 / 256 = 0
|
||||
Done.
|
||||
|
||||
@@ -49,3 +49,9 @@ AT_KEYWORDS([meas])
|
||||
cat $abs_srcdir/meas/meas_test.ok > expout
|
||||
AT_CHECK([$abs_top_builddir/tests/meas/meas_test], [], [expout], [ignore])
|
||||
AT_CLEANUP
|
||||
|
||||
AT_SETUP([ta_control])
|
||||
AT_KEYWORDS([ta_control])
|
||||
cat $abs_srcdir/ta_control/ta_control_test.ok > expout
|
||||
AT_CHECK([$abs_top_builddir/tests/ta_control/ta_control_test], [], [expout], [ignore])
|
||||
AT_CLEANUP
|
||||
|
||||
Reference in New Issue
Block a user