Merge branch 'laforge/trx-split'
This splits the TRX scheduler into a generic part and an osmo-bts-trx specific part. It is the basis for re-using the scheduler from other bts modules such as the upcoming osmo-bts-virtual.
This commit is contained in:
commit
f58542899a
|
@ -1,4 +1,4 @@
|
|||
noinst_HEADERS = abis.h bts.h bts_model.h gsm_data.h logging.h measurement.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
|
||||
power_control.h scheduler.h scheduler_backend.h
|
||||
|
|
|
@ -0,0 +1,175 @@
|
|||
#ifndef TRX_SCHEDULER_H
|
||||
#define TRX_SCHEDULER_H
|
||||
|
||||
/* These types define the different channels on a multiframe.
|
||||
* Each channel has queues and can be activated individually.
|
||||
*/
|
||||
enum trx_chan_type {
|
||||
TRXC_IDLE = 0,
|
||||
TRXC_FCCH,
|
||||
TRXC_SCH,
|
||||
TRXC_BCCH,
|
||||
TRXC_RACH,
|
||||
TRXC_CCCH,
|
||||
TRXC_TCHF,
|
||||
TRXC_TCHH_0,
|
||||
TRXC_TCHH_1,
|
||||
TRXC_SDCCH4_0,
|
||||
TRXC_SDCCH4_1,
|
||||
TRXC_SDCCH4_2,
|
||||
TRXC_SDCCH4_3,
|
||||
TRXC_SDCCH8_0,
|
||||
TRXC_SDCCH8_1,
|
||||
TRXC_SDCCH8_2,
|
||||
TRXC_SDCCH8_3,
|
||||
TRXC_SDCCH8_4,
|
||||
TRXC_SDCCH8_5,
|
||||
TRXC_SDCCH8_6,
|
||||
TRXC_SDCCH8_7,
|
||||
TRXC_SACCHTF,
|
||||
TRXC_SACCHTH_0,
|
||||
TRXC_SACCHTH_1,
|
||||
TRXC_SACCH4_0,
|
||||
TRXC_SACCH4_1,
|
||||
TRXC_SACCH4_2,
|
||||
TRXC_SACCH4_3,
|
||||
TRXC_SACCH8_0,
|
||||
TRXC_SACCH8_1,
|
||||
TRXC_SACCH8_2,
|
||||
TRXC_SACCH8_3,
|
||||
TRXC_SACCH8_4,
|
||||
TRXC_SACCH8_5,
|
||||
TRXC_SACCH8_6,
|
||||
TRXC_SACCH8_7,
|
||||
TRXC_PDTCH,
|
||||
TRXC_PTCCH,
|
||||
_TRX_CHAN_MAX
|
||||
};
|
||||
|
||||
/* States each channel on a multiframe */
|
||||
struct l1sched_chan_state {
|
||||
/* scheduler */
|
||||
uint8_t active; /* Channel is active */
|
||||
ubit_t *dl_bursts; /* burst buffer for TX */
|
||||
sbit_t *ul_bursts; /* burst buffer for RX */
|
||||
uint32_t ul_first_fn; /* fn of first burst */
|
||||
uint8_t ul_mask; /* mask of received bursts */
|
||||
|
||||
/* RSSI / TOA */
|
||||
uint8_t rssi_num; /* number of RSSI values */
|
||||
float rssi_sum; /* sum of RSSI values */
|
||||
uint8_t toa_num; /* number of TOA values */
|
||||
float toa_sum; /* sum of TOA values */
|
||||
|
||||
/* loss detection */
|
||||
uint8_t lost; /* (SACCH) loss detection */
|
||||
|
||||
/* mode */
|
||||
uint8_t rsl_cmode, tch_mode; /* mode for TCH channels */
|
||||
|
||||
/* AMR */
|
||||
uint8_t codec[4]; /* 4 possible codecs for amr */
|
||||
int codecs; /* number of possible codecs */
|
||||
float ber_sum; /* sum of bit error rates */
|
||||
int ber_num; /* number of bit error rates */
|
||||
uint8_t ul_ft; /* current uplink FT index */
|
||||
uint8_t dl_ft; /* current downlink FT index */
|
||||
uint8_t ul_cmr; /* current uplink CMR index */
|
||||
uint8_t dl_cmr; /* current downlink CMR index */
|
||||
uint8_t amr_loop; /* if AMR loop is enabled */
|
||||
|
||||
/* TCH/H */
|
||||
uint8_t dl_ongoing_facch; /* FACCH/H on downlink */
|
||||
uint8_t ul_ongoing_facch; /* FACCH/H on uplink */
|
||||
|
||||
/* encryption */
|
||||
int ul_encr_algo; /* A5/x encry algo downlink */
|
||||
int dl_encr_algo; /* A5/x encry algo uplink */
|
||||
int ul_encr_key_len;
|
||||
int dl_encr_key_len;
|
||||
uint8_t ul_encr_key[MAX_A5_KEY_LEN];
|
||||
uint8_t dl_encr_key[MAX_A5_KEY_LEN];
|
||||
|
||||
/* measurements */
|
||||
struct {
|
||||
uint8_t clock; /* cyclic clock counter */
|
||||
int8_t rssi[32]; /* last RSSI values */
|
||||
int rssi_count; /* received RSSI values */
|
||||
int rssi_valid_count; /* number of stored value */
|
||||
int rssi_got_burst; /* any burst received so far */
|
||||
float toa_sum; /* sum of TOA values */
|
||||
int toa_num; /* number of TOA value */
|
||||
} meas;
|
||||
|
||||
/* handover */
|
||||
uint8_t ho_rach_detect; /* if rach detection is on */
|
||||
};
|
||||
|
||||
struct l1sched_ts {
|
||||
uint8_t mf_index; /* selected multiframe index */
|
||||
uint32_t mf_last_fn; /* last received frame number */
|
||||
uint8_t mf_period; /* period of multiframe */
|
||||
const struct trx_sched_frame *mf_frames; /* pointer to frame layout */
|
||||
|
||||
struct llist_head dl_prims; /* Queue primitves for TX */
|
||||
|
||||
/* Channel states for all logical channels */
|
||||
struct l1sched_chan_state chan_state[_TRX_CHAN_MAX];
|
||||
};
|
||||
|
||||
struct l1sched_trx {
|
||||
struct gsm_bts_trx *trx;
|
||||
struct l1sched_ts ts[TRX_NR_TS];
|
||||
};
|
||||
|
||||
struct l1sched_ts *l1sched_trx_get_ts(struct l1sched_trx *l1t, uint8_t tn);
|
||||
|
||||
/*! \brief how many frame numbers in advance we should send bursts to PHY */
|
||||
extern uint32_t trx_clock_advance;
|
||||
/*! \brief advance RTS.ind to L2 by that many clocks */
|
||||
extern uint32_t trx_rts_advance;
|
||||
/*! \brief last frame number as received from PHY */
|
||||
extern uint32_t transceiver_last_fn;
|
||||
|
||||
|
||||
/*! \brief Initialize the scheudler data structures */
|
||||
int trx_sched_init(struct l1sched_trx *l1t);
|
||||
|
||||
/*! \brief De-initialize the scheudler data structures */
|
||||
void trx_sched_exit(struct l1sched_trx *l1t);
|
||||
|
||||
/*! \brief Handle a PH-DATA.req from L2 down to L1 */
|
||||
int trx_sched_ph_data_req(struct l1sched_trx *l1t, struct osmo_phsap_prim *l1sap);
|
||||
|
||||
/*! \brief Handle a PH-TCH.req from L2 down to L1 */
|
||||
int trx_sched_tch_req(struct l1sched_trx *l1t, struct osmo_phsap_prim *l1sap);
|
||||
|
||||
/*! \brief PHY informs us of new (current) GSM freme nunmber */
|
||||
int trx_sched_clock(struct gsm_bts *bts, uint32_t fn);
|
||||
|
||||
/*! \brief handle an UL burst received by PHY */
|
||||
int trx_sched_ul_burst(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
||||
sbit_t *bits, int8_t rssi, float toa);
|
||||
|
||||
/*! \brief set multiframe scheduler to given physical channel config */
|
||||
int trx_sched_set_pchan(struct l1sched_trx *l1t, uint8_t tn,
|
||||
enum gsm_phys_chan_config pchan);
|
||||
|
||||
/*! \brief set all matching logical channels active/inactive */
|
||||
int trx_sched_set_lchan(struct l1sched_trx *l1t, uint8_t chan_nr, uint8_t link_id,
|
||||
int active);
|
||||
|
||||
/*! \brief set mode of all matching logical channels to given mode(s) */
|
||||
int trx_sched_set_mode(struct l1sched_trx *l1t, uint8_t chan_nr, uint8_t rsl_cmode,
|
||||
uint8_t tch_mode, int codecs, uint8_t codec0, uint8_t codec1,
|
||||
uint8_t codec2, uint8_t codec3, uint8_t initial_codec,
|
||||
uint8_t handover);
|
||||
|
||||
/*! \brief set ciphering on given logical channels */
|
||||
int trx_sched_set_cipher(struct l1sched_trx *l1t, uint8_t chan_nr, int downlink,
|
||||
int algo, uint8_t *key, int key_len);
|
||||
|
||||
/* \brief close all logical channels and reset timeslots */
|
||||
void trx_sched_reset(struct l1sched_trx *l1t);
|
||||
|
||||
#endif /* TRX_SCHEDULER_H */
|
|
@ -0,0 +1,82 @@
|
|||
#pragma once
|
||||
|
||||
typedef int trx_sched_rts_func(struct l1sched_trx *l1t, uint8_t tn,
|
||||
uint32_t fn, enum trx_chan_type chan);
|
||||
|
||||
typedef ubit_t *trx_sched_dl_func(struct l1sched_trx *l1t, uint8_t tn,
|
||||
uint32_t fn, enum trx_chan_type chan,
|
||||
uint8_t bid);
|
||||
|
||||
typedef int trx_sched_ul_func(struct l1sched_trx *l1t, uint8_t tn,
|
||||
uint32_t fn, enum trx_chan_type chan,
|
||||
uint8_t bid, sbit_t *bits, int8_t rssi,
|
||||
float toa);
|
||||
|
||||
struct trx_chan_desc {
|
||||
/*! \brief Is this on a PDCH (PS) ? */
|
||||
int pdch;
|
||||
/*! \brief TRX Channel Type */
|
||||
enum trx_chan_type chan;
|
||||
/*! \brief Channel Number (like in RSL) */
|
||||
uint8_t chan_nr;
|
||||
/*! \brief Link ID (like in RSL) */
|
||||
uint8_t link_id;
|
||||
/*! \brief Human-readable name */
|
||||
const char *name;
|
||||
/*! \brief function to call when we want to generate RTS.req to L2 */
|
||||
trx_sched_rts_func *rts_fn;
|
||||
/*! \brief function to call when DATA.req received from L2 */
|
||||
trx_sched_dl_func *dl_fn;
|
||||
/*! \brief function to call when burst received from PHY */
|
||||
trx_sched_ul_func *ul_fn;
|
||||
/*! \breif is this channel automatically active at start? */
|
||||
int auto_active;
|
||||
};
|
||||
extern const struct trx_chan_desc trx_chan_desc[_TRX_CHAN_MAX];
|
||||
|
||||
extern const ubit_t _sched_tsc[8][26];
|
||||
const ubit_t _sched_fcch_burst[148];
|
||||
const ubit_t _sched_sch_train[64];
|
||||
|
||||
struct msgb *_sched_dequeue_prim(struct l1sched_trx *l1t, int8_t tn, uint32_t fn,
|
||||
enum trx_chan_type chan);
|
||||
|
||||
int _sched_compose_ph_data_ind(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
||||
enum trx_chan_type chan, uint8_t *l2, uint8_t l2_len, float rssi);
|
||||
|
||||
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);
|
||||
|
||||
ubit_t *tx_idle_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
||||
enum trx_chan_type chan, uint8_t bid);
|
||||
ubit_t *tx_fcch_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
||||
enum trx_chan_type chan, uint8_t bid);
|
||||
ubit_t *tx_sch_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
||||
enum trx_chan_type chan, uint8_t bid);
|
||||
ubit_t *tx_data_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
||||
enum trx_chan_type chan, uint8_t bid);
|
||||
ubit_t *tx_pdtch_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
||||
enum trx_chan_type chan, uint8_t bid);
|
||||
ubit_t *tx_tchf_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
||||
enum trx_chan_type chan, uint8_t bid);
|
||||
ubit_t *tx_tchh_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
||||
enum trx_chan_type chan, uint8_t bid);
|
||||
int rx_rach_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
||||
enum trx_chan_type chan, uint8_t bid, sbit_t *bits, int8_t rssi,
|
||||
float toa);
|
||||
int rx_data_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
||||
enum trx_chan_type chan, uint8_t bid, sbit_t *bits, int8_t rssi,
|
||||
float toa);
|
||||
int rx_pdtch_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
||||
enum trx_chan_type chan, uint8_t bid, sbit_t *bits, int8_t rssi,
|
||||
float toa);
|
||||
int rx_tchf_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
||||
enum trx_chan_type chan, uint8_t bid, sbit_t *bits, int8_t rssi,
|
||||
float toa);
|
||||
int rx_tchh_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
||||
enum trx_chan_type chan, uint8_t bid, sbit_t *bits, int8_t rssi,
|
||||
float toa);
|
||||
|
||||
const ubit_t *_sched_dl_burst(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn);
|
||||
int _sched_rts(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn);
|
||||
void _sched_act_rach_det(struct l1sched_trx *l1t, uint8_t tn, uint8_t ss, int activate);
|
|
@ -2,10 +2,12 @@ AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include -I$(OPENBSC_INCDIR)
|
|||
AM_CFLAGS = -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOTRAU_CFLAGS)
|
||||
LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOTRAU_LIBS)
|
||||
|
||||
noinst_LIBRARIES = libbts.a
|
||||
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 \
|
||||
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
|
||||
|
||||
libl1sched_a_SOURCES = scheduler.c
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -2,10 +2,10 @@ AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include -I$(OPENBSC_INCDIR)
|
|||
AM_CFLAGS = -Wall -fno-strict-aliasing $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOCODEC_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(LIBOSMOTRAU_CFLAGS) $(LIBOSMOABIS_CFLAGS) $(LIBOSMOCTRL_CFLAGS) $(ORTP_CFLAGS)
|
||||
LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(LIBOSMOCODEC_LIBS) $(LIBOSMOVTY_LIBS) $(LIBOSMOTRAU_LIBS) $(LIBOSMOABIS_LIBS) $(LIBOSMOCTRL_LIBS) $(ORTP_LIBS)
|
||||
|
||||
EXTRA_DIST = trx_if.h l1_if.h scheduler.h gsm0503_parity.h gsm0503_conv.h gsm0503_interleaving.h gsm0503_mapping.h gsm0503_coding.h gsm0503_tables.h loops.h amr.h
|
||||
EXTRA_DIST = trx_if.h l1_if.h gsm0503_parity.h gsm0503_conv.h gsm0503_interleaving.h gsm0503_mapping.h gsm0503_coding.h gsm0503_tables.h loops.h amr.h
|
||||
|
||||
bin_PROGRAMS = osmobts-trx
|
||||
|
||||
osmobts_trx_SOURCES = main.c trx_if.c l1_if.c scheduler.c trx_vty.c gsm0503_parity.c gsm0503_conv.c gsm0503_interleaving.c gsm0503_mapping.c gsm0503_coding.c gsm0503_tables.c loops.c amr.c
|
||||
osmobts_trx_LDADD = $(top_builddir)/src/common/libbts.a $(LDADD)
|
||||
osmobts_trx_SOURCES = main.c trx_if.c l1_if.c scheduler_trx.c trx_vty.c gsm0503_parity.c gsm0503_conv.c gsm0503_interleaving.c gsm0503_mapping.c gsm0503_coding.c gsm0503_tables.c loops.c amr.c
|
||||
osmobts_trx_LDADD = $(top_builddir)/src/common/libbts.a $(top_builddir)/src/common/libl1sched.a $(LDADD)
|
||||
|
||||
|
|
|
@ -36,10 +36,10 @@
|
|||
#include <osmo-bts/bts_model.h>
|
||||
#include <osmo-bts/amr.h>
|
||||
#include <osmo-bts/abis.h>
|
||||
#include <osmo-bts/scheduler.h>
|
||||
|
||||
#include "l1_if.h"
|
||||
#include "trx_if.h"
|
||||
#include "scheduler.h"
|
||||
|
||||
|
||||
static const uint8_t transceiver_chan_types[_GSM_PCHAN_MAX] = {
|
||||
|
@ -68,9 +68,10 @@ struct trx_l1h *l1if_open(struct gsm_bts_trx *trx)
|
|||
if (!l1h)
|
||||
return NULL;
|
||||
l1h->trx = trx;
|
||||
l1h->l1s.trx = trx;
|
||||
trx->role_bts.l1h = l1h;
|
||||
|
||||
trx_sched_init(l1h);
|
||||
trx_sched_init(&l1h->l1s);
|
||||
|
||||
rc = trx_if_open(l1h);
|
||||
if (rc < 0) {
|
||||
|
@ -89,7 +90,7 @@ err:
|
|||
void l1if_close(struct trx_l1h *l1h)
|
||||
{
|
||||
trx_if_close(l1h);
|
||||
trx_sched_exit(l1h);
|
||||
trx_sched_exit(&l1h->l1s);
|
||||
talloc_free(l1h);
|
||||
}
|
||||
|
||||
|
@ -267,7 +268,7 @@ int bts_model_trx_close(struct gsm_bts_trx *trx)
|
|||
enum gsm_phys_chan_config pchan = trx->ts[0].pchan;
|
||||
|
||||
/* close all logical channels and reset timeslots */
|
||||
trx_sched_reset(l1h);
|
||||
trx_sched_reset(&l1h->l1s);
|
||||
|
||||
/* deactivate lchan for CCCH */
|
||||
if (pchan == GSM_PCHAN_CCCH || pchan == GSM_PCHAN_CCCH_SDCCH4) {
|
||||
|
@ -374,8 +375,12 @@ static uint8_t trx_set_ts(struct gsm_bts_trx_ts *ts)
|
|||
l1if_provision_transceiver_trx(l1h);
|
||||
}
|
||||
|
||||
/* ignore disabled slots */
|
||||
if (!(l1h->config.slotmask & (1 << tn)))
|
||||
return NM_NACK_RES_NOTAVAIL;
|
||||
|
||||
/* set physical channel */
|
||||
rc = trx_sched_set_pchan(l1h, tn, pchan);
|
||||
rc = trx_sched_set_pchan(&l1h->l1s, tn, pchan);
|
||||
if (rc)
|
||||
return NM_NACK_RES_NOTAVAIL;
|
||||
|
||||
|
@ -413,17 +418,17 @@ static int l1if_set_ciphering(struct trx_l1h *l1h, struct gsm_lchan *lchan,
|
|||
|
||||
if (!downlink) {
|
||||
/* set uplink */
|
||||
trx_sched_set_cipher(l1h, chan_nr, 0, lchan->encr.alg_id - 1,
|
||||
trx_sched_set_cipher(&l1h->l1s, chan_nr, 0, lchan->encr.alg_id - 1,
|
||||
lchan->encr.key, lchan->encr.key_len);
|
||||
lchan->ciph_state = LCHAN_CIPH_RX_CONF;
|
||||
} else {
|
||||
/* set downlink and also set uplink, if not already */
|
||||
if (lchan->ciph_state != LCHAN_CIPH_RX_CONF) {
|
||||
trx_sched_set_cipher(l1h, chan_nr, 0,
|
||||
trx_sched_set_cipher(&l1h->l1s, chan_nr, 0,
|
||||
lchan->encr.alg_id - 1, lchan->encr.key,
|
||||
lchan->encr.key_len);
|
||||
}
|
||||
trx_sched_set_cipher(l1h, chan_nr, 1, lchan->encr.alg_id - 1,
|
||||
trx_sched_set_cipher(&l1h->l1s, chan_nr, 1, lchan->encr.alg_id - 1,
|
||||
lchan->encr.key, lchan->encr.key_len);
|
||||
lchan->ciph_state = LCHAN_CIPH_RXTX_CONF;
|
||||
}
|
||||
|
@ -510,12 +515,12 @@ int bts_model_l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap)
|
|||
if (!msg)
|
||||
break;
|
||||
/* put data into scheduler's queue */
|
||||
return trx_sched_ph_data_req(l1h, l1sap);
|
||||
return trx_sched_ph_data_req(&l1h->l1s, l1sap);
|
||||
case OSMO_PRIM(PRIM_TCH, PRIM_OP_REQUEST):
|
||||
if (!msg)
|
||||
break;
|
||||
/* put data into scheduler's queue */
|
||||
return trx_sched_tch_req(l1h, l1sap);
|
||||
return trx_sched_tch_req(&l1h->l1s, l1sap);
|
||||
case OSMO_PRIM(PRIM_MPH_INFO, PRIM_OP_REQUEST):
|
||||
switch (l1sap->u.info.type) {
|
||||
case PRIM_INFO_ACT_CIPH:
|
||||
|
@ -542,11 +547,11 @@ int bts_model_l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap)
|
|||
break;
|
||||
}
|
||||
/* activate dedicated channel */
|
||||
trx_sched_set_lchan(l1h, chan_nr, 0x00, 1);
|
||||
trx_sched_set_lchan(&l1h->l1s, chan_nr, 0x00, 1);
|
||||
/* activate associated channel */
|
||||
trx_sched_set_lchan(l1h, chan_nr, 0x40, 1);
|
||||
trx_sched_set_lchan(&l1h->l1s, chan_nr, 0x40, 1);
|
||||
/* set mode */
|
||||
trx_sched_set_mode(l1h, chan_nr,
|
||||
trx_sched_set_mode(&l1h->l1s, chan_nr,
|
||||
lchan->rsl_cmode, lchan->tch_mode,
|
||||
lchan->tch.amr_mr.num_modes,
|
||||
lchan->tch.amr_mr.bts_mode[0].mode,
|
||||
|
@ -574,7 +579,7 @@ int bts_model_l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap)
|
|||
}
|
||||
if (l1sap->u.info.type == PRIM_INFO_MODIFY) {
|
||||
/* change mode */
|
||||
trx_sched_set_mode(l1h, chan_nr,
|
||||
trx_sched_set_mode(&l1h->l1s, chan_nr,
|
||||
lchan->rsl_cmode, lchan->tch_mode,
|
||||
lchan->tch.amr_mr.num_modes,
|
||||
lchan->tch.amr_mr.bts_mode[0].mode,
|
||||
|
@ -591,12 +596,12 @@ int bts_model_l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap)
|
|||
break;
|
||||
}
|
||||
/* deactivate associated channel */
|
||||
trx_sched_set_lchan(l1h, chan_nr, 0x40, 0);
|
||||
trx_sched_set_lchan(&l1h->l1s, chan_nr, 0x40, 0);
|
||||
if (!l1sap->u.info.u.act_req.sacch_only) {
|
||||
/* set lchan inactive */
|
||||
lchan_set_state(lchan, LCHAN_S_NONE);
|
||||
/* deactivate dedicated channel */
|
||||
trx_sched_set_lchan(l1h, chan_nr, 0x00, 0);
|
||||
trx_sched_set_lchan(&l1h->l1s, chan_nr, 0x00, 0);
|
||||
/* confirm only on dedicated channel */
|
||||
mph_info_chan_confirm(l1h, chan_nr,
|
||||
PRIM_INFO_DEACTIVATE, 0);
|
||||
|
|
|
@ -1,109 +1,7 @@
|
|||
#ifndef L1_IF_H_TRX
|
||||
#define L1_IF_H_TRX
|
||||
|
||||
/* These types define the different channels on a multiframe.
|
||||
* Each channel has queues and can be activated individually.
|
||||
*/
|
||||
enum trx_chan_type {
|
||||
TRXC_IDLE = 0,
|
||||
TRXC_FCCH,
|
||||
TRXC_SCH,
|
||||
TRXC_BCCH,
|
||||
TRXC_RACH,
|
||||
TRXC_CCCH,
|
||||
TRXC_TCHF,
|
||||
TRXC_TCHH_0,
|
||||
TRXC_TCHH_1,
|
||||
TRXC_SDCCH4_0,
|
||||
TRXC_SDCCH4_1,
|
||||
TRXC_SDCCH4_2,
|
||||
TRXC_SDCCH4_3,
|
||||
TRXC_SDCCH8_0,
|
||||
TRXC_SDCCH8_1,
|
||||
TRXC_SDCCH8_2,
|
||||
TRXC_SDCCH8_3,
|
||||
TRXC_SDCCH8_4,
|
||||
TRXC_SDCCH8_5,
|
||||
TRXC_SDCCH8_6,
|
||||
TRXC_SDCCH8_7,
|
||||
TRXC_SACCHTF,
|
||||
TRXC_SACCHTH_0,
|
||||
TRXC_SACCHTH_1,
|
||||
TRXC_SACCH4_0,
|
||||
TRXC_SACCH4_1,
|
||||
TRXC_SACCH4_2,
|
||||
TRXC_SACCH4_3,
|
||||
TRXC_SACCH8_0,
|
||||
TRXC_SACCH8_1,
|
||||
TRXC_SACCH8_2,
|
||||
TRXC_SACCH8_3,
|
||||
TRXC_SACCH8_4,
|
||||
TRXC_SACCH8_5,
|
||||
TRXC_SACCH8_6,
|
||||
TRXC_SACCH8_7,
|
||||
TRXC_PDTCH,
|
||||
TRXC_PTCCH,
|
||||
_TRX_CHAN_MAX
|
||||
};
|
||||
|
||||
/* States each channel on a multiframe */
|
||||
struct trx_chan_state {
|
||||
/* scheduler */
|
||||
uint8_t active; /* Channel is active */
|
||||
ubit_t *dl_bursts; /* burst buffer for TX */
|
||||
sbit_t *ul_bursts; /* burst buffer for RX */
|
||||
uint32_t ul_first_fn; /* fn of first burst */
|
||||
uint8_t ul_mask; /* mask of received bursts */
|
||||
|
||||
/* RSSI / TOA */
|
||||
uint8_t rssi_num; /* number of RSSI values */
|
||||
float rssi_sum; /* sum of RSSI values */
|
||||
uint8_t toa_num; /* number of TOA values */
|
||||
float toa_sum; /* sum of TOA values */
|
||||
|
||||
/* loss detection */
|
||||
uint8_t lost; /* (SACCH) loss detection */
|
||||
|
||||
/* mode */
|
||||
uint8_t rsl_cmode, tch_mode; /* mode for TCH channels */
|
||||
|
||||
/* AMR */
|
||||
uint8_t codec[4]; /* 4 possible codecs for amr */
|
||||
int codecs; /* number of possible codecs */
|
||||
float ber_sum; /* sum of bit error rates */
|
||||
int ber_num; /* number of bit error rates */
|
||||
uint8_t ul_ft; /* current uplink FT index */
|
||||
uint8_t dl_ft; /* current downlink FT index */
|
||||
uint8_t ul_cmr; /* current uplink CMR index */
|
||||
uint8_t dl_cmr; /* current downlink CMR index */
|
||||
uint8_t amr_loop; /* if AMR loop is enabled */
|
||||
|
||||
/* TCH/H */
|
||||
uint8_t dl_ongoing_facch; /* FACCH/H on downlink */
|
||||
uint8_t ul_ongoing_facch; /* FACCH/H on uplink */
|
||||
|
||||
/* encryption */
|
||||
int ul_encr_algo; /* A5/x encry algo downlink */
|
||||
int dl_encr_algo; /* A5/x encry algo uplink */
|
||||
int ul_encr_key_len;
|
||||
int dl_encr_key_len;
|
||||
uint8_t ul_encr_key[MAX_A5_KEY_LEN];
|
||||
uint8_t dl_encr_key[MAX_A5_KEY_LEN];
|
||||
|
||||
/* measurements */
|
||||
struct {
|
||||
uint8_t clock; /* cyclic clock counter */
|
||||
int8_t rssi[32]; /* last RSSI values */
|
||||
int rssi_count; /* received RSSI values */
|
||||
int rssi_valid_count; /* number of stored value */
|
||||
int rssi_got_burst; /* any burst received so far */
|
||||
float toa_sum; /* sum of TOA values */
|
||||
int toa_num; /* number of TOA value */
|
||||
} meas;
|
||||
|
||||
/* handover */
|
||||
uint8_t ho_rach_detect; /* if rach detection is on */
|
||||
};
|
||||
#include <osmo-bts/scheduler.h>
|
||||
|
||||
struct trx_config {
|
||||
uint8_t poweron; /* poweron(1) or poweroff(0) */
|
||||
|
@ -152,16 +50,9 @@ struct trx_l1h {
|
|||
|
||||
/* transceiver config */
|
||||
struct trx_config config;
|
||||
|
||||
uint8_t mf_index[TRX_NR_TS]; /* selected multiframe index */
|
||||
uint32_t mf_last_fn[TRX_NR_TS]; /* last received frame */
|
||||
uint8_t mf_period[TRX_NR_TS]; /* period of multiframe */
|
||||
const struct trx_sched_frame *mf_frames[TRX_NR_TS]; /* pointer to frame layout */
|
||||
|
||||
/* Channel states for all channels on all timeslots */
|
||||
struct trx_chan_state chan_states[TRX_NR_TS][_TRX_CHAN_MAX];
|
||||
struct llist_head dl_prims[TRX_NR_TS]; /* Queue primitves for TX */
|
||||
uint8_t ho_rach_detect[TRX_NR_TS][TS_MAX_LCHAN];
|
||||
|
||||
struct l1sched_trx l1s;
|
||||
};
|
||||
|
||||
struct trx_l1h *l1if_open(struct gsm_bts_trx *trx);
|
||||
|
@ -176,4 +67,10 @@ void l1if_fill_meas_res(struct osmo_phsap_prim *l1sap, uint8_t chan_nr, float ta
|
|||
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, float toa);
|
||||
|
||||
static inline struct l1sched_trx *trx_l1sched_hdl(struct gsm_bts_trx *trx)
|
||||
{
|
||||
struct trx_l1h *l1h = trx_l1h_hdl(trx);
|
||||
return &l1h->l1s;
|
||||
}
|
||||
|
||||
#endif /* L1_IF_H_TRX */
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
#include "l1_if.h"
|
||||
#include "loops.h"
|
||||
|
||||
#define MS_PWR_DBM(lvl) ms_pwr_dbm(gsm_arfcn2band(l1h->config.arfcn), lvl)
|
||||
#define MS_PWR_DBM(arfcn, lvl) ms_pwr_dbm(gsm_arfcn2band(arfcn), lvl)
|
||||
|
||||
/*
|
||||
* MS Power loop
|
||||
|
@ -42,11 +42,12 @@
|
|||
int trx_ms_power_loop = 0;
|
||||
int8_t trx_target_rssi = -10;
|
||||
|
||||
static int ms_power_diff(struct trx_l1h *l1h, struct gsm_lchan *lchan,
|
||||
uint8_t chan_nr, struct trx_chan_state *chan_state, int8_t diff)
|
||||
static int ms_power_diff(struct gsm_lchan *lchan, uint8_t chan_nr, int8_t diff)
|
||||
{
|
||||
struct gsm_bts_trx *trx = lchan->ts->trx;
|
||||
uint16_t arfcn = trx->arfcn;
|
||||
int8_t new_power;
|
||||
|
||||
|
||||
new_power = lchan->ms_power - (diff >> 1);
|
||||
|
||||
if (diff == 0)
|
||||
|
@ -56,7 +57,7 @@ static int ms_power_diff(struct trx_l1h *l1h, struct gsm_lchan *lchan,
|
|||
new_power = 0;
|
||||
|
||||
// FIXME: to go above 1W, we need to know classmark of MS
|
||||
if (l1h->config.arfcn >= 512 && l1h->config.arfcn <= 885) {
|
||||
if (arfcn >= 512 && arfcn <= 885) {
|
||||
if (new_power > 15)
|
||||
new_power = 15;
|
||||
} else {
|
||||
|
@ -73,8 +74,8 @@ static int ms_power_diff(struct trx_l1h *l1h, struct gsm_lchan *lchan,
|
|||
if (lchan->ms_power == new_power) {
|
||||
LOGP(DLOOP, LOGL_INFO, "Keeping MS new_power of trx=%u "
|
||||
"chan_nr=0x%02x at control level %d (%d dBm)\n",
|
||||
l1h->trx->nr, chan_nr, new_power,
|
||||
MS_PWR_DBM(new_power));
|
||||
trx->nr, chan_nr, new_power,
|
||||
MS_PWR_DBM(arfcn, new_power));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -82,15 +83,16 @@ static int ms_power_diff(struct trx_l1h *l1h, struct gsm_lchan *lchan,
|
|||
LOGP(DLOOP, LOGL_INFO, "%s MS new_power of trx=%u chan_nr=0x%02x from "
|
||||
"control level %d (%d dBm) to %d (%d dBm)\n",
|
||||
(diff > 0) ? "Raising" : "Lowering",
|
||||
l1h->trx->nr, chan_nr, lchan->ms_power,
|
||||
MS_PWR_DBM(lchan->ms_power), new_power, MS_PWR_DBM(new_power));
|
||||
trx->nr, chan_nr, lchan->ms_power,
|
||||
MS_PWR_DBM(arfcn, lchan->ms_power), new_power,
|
||||
MS_PWR_DBM(arfcn, new_power));
|
||||
|
||||
lchan->ms_power = new_power;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ms_power_val(struct trx_chan_state *chan_state, int8_t rssi)
|
||||
static int ms_power_val(struct l1sched_chan_state *chan_state, int8_t rssi)
|
||||
{
|
||||
/* ignore inserted dummy frames, treat as lost frames */
|
||||
if (rssi < -127)
|
||||
|
@ -112,9 +114,10 @@ static int ms_power_val(struct trx_chan_state *chan_state, int8_t rssi)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int ms_power_clock(struct trx_l1h *l1h, struct gsm_lchan *lchan,
|
||||
uint8_t chan_nr, struct trx_chan_state *chan_state)
|
||||
static int ms_power_clock(struct gsm_lchan *lchan,
|
||||
uint8_t chan_nr, struct l1sched_chan_state *chan_state)
|
||||
{
|
||||
struct gsm_bts_trx *trx = lchan->ts->trx;
|
||||
int rssi;
|
||||
int i;
|
||||
|
||||
|
@ -134,9 +137,8 @@ static int ms_power_clock(struct trx_l1h *l1h, struct gsm_lchan *lchan,
|
|||
if (chan_state->meas.rssi_count == 0) {
|
||||
LOGP(DLOOP, LOGL_NOTICE, "LOST SACCH frame of trx=%u "
|
||||
"chan_nr=0x%02x, so we raise MS power\n",
|
||||
l1h->trx->nr, chan_nr);
|
||||
return ms_power_diff(l1h, lchan, chan_nr, chan_state,
|
||||
MS_RAISE_MAX);
|
||||
trx->nr, chan_nr);
|
||||
return ms_power_diff(lchan, chan_nr, MS_RAISE_MAX);
|
||||
}
|
||||
|
||||
/* reset total counter */
|
||||
|
@ -157,9 +159,10 @@ static int ms_power_clock(struct trx_l1h *l1h, struct gsm_lchan *lchan,
|
|||
/* change RSSI */
|
||||
LOGP(DLOOP, LOGL_DEBUG, "Lowest RSSI: %d Target RSSI: %d Current "
|
||||
"MS power: %d (%d dBm) of trx=%u chan_nr=0x%02x\n", rssi,
|
||||
trx_target_rssi, lchan->ms_power, MS_PWR_DBM(lchan->ms_power),
|
||||
l1h->trx->nr, chan_nr);
|
||||
ms_power_diff(l1h, lchan, chan_nr, chan_state, trx_target_rssi - rssi);
|
||||
trx_target_rssi, lchan->ms_power,
|
||||
MS_PWR_DBM(trx->arfcn, lchan->ms_power),
|
||||
trx->nr, chan_nr);
|
||||
ms_power_diff(lchan, chan_nr, trx_target_rssi - rssi);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -171,9 +174,11 @@ static int ms_power_clock(struct trx_l1h *l1h, struct gsm_lchan *lchan,
|
|||
|
||||
int trx_ta_loop = 1;
|
||||
|
||||
int ta_val(struct trx_l1h *l1h, struct gsm_lchan *lchan, uint8_t chan_nr,
|
||||
struct trx_chan_state *chan_state, float toa)
|
||||
int ta_val(struct gsm_lchan *lchan, uint8_t chan_nr,
|
||||
struct l1sched_chan_state *chan_state, float toa)
|
||||
{
|
||||
struct gsm_bts_trx *trx = lchan->ts->trx;
|
||||
|
||||
/* check if the current L1 header acks to the current ordered TA */
|
||||
if (lchan->meas.l1_info[1] != lchan->rqd_ta)
|
||||
return 0;
|
||||
|
@ -190,19 +195,19 @@ int ta_val(struct trx_l1h *l1h, struct gsm_lchan *lchan, uint8_t chan_nr,
|
|||
if (toa < -0.9F && lchan->rqd_ta > 0) {
|
||||
LOGP(DLOOP, LOGL_INFO, "TOA of trx=%u chan_nr=0x%02x is too "
|
||||
"early (%.2f), now lowering TA from %d to %d\n",
|
||||
l1h->trx->nr, chan_nr, toa, lchan->rqd_ta,
|
||||
trx->nr, chan_nr, toa, lchan->rqd_ta,
|
||||
lchan->rqd_ta - 1);
|
||||
lchan->rqd_ta--;
|
||||
} else if (toa > 0.9F && lchan->rqd_ta < 63) {
|
||||
LOGP(DLOOP, LOGL_INFO, "TOA of trx=%u chan_nr=0x%02x is too "
|
||||
"late (%.2f), now raising TA from %d to %d\n",
|
||||
l1h->trx->nr, chan_nr, toa, lchan->rqd_ta,
|
||||
trx->nr, chan_nr, toa, lchan->rqd_ta,
|
||||
lchan->rqd_ta + 1);
|
||||
lchan->rqd_ta++;
|
||||
} else
|
||||
LOGP(DLOOP, LOGL_INFO, "TOA of trx=%u chan_nr=0x%02x is "
|
||||
"correct (%.2f), keeping current TA of %d\n",
|
||||
l1h->trx->nr, chan_nr, toa, lchan->rqd_ta);
|
||||
trx->nr, chan_nr, toa, lchan->rqd_ta);
|
||||
|
||||
chan_state->meas.toa_num = 0;
|
||||
chan_state->meas.toa_sum = 0;
|
||||
|
@ -210,29 +215,29 @@ int ta_val(struct trx_l1h *l1h, struct gsm_lchan *lchan, uint8_t chan_nr,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int trx_loop_sacch_input(struct trx_l1h *l1h, uint8_t chan_nr,
|
||||
struct trx_chan_state *chan_state, int8_t rssi, float toa)
|
||||
int trx_loop_sacch_input(struct l1sched_trx *l1t, uint8_t chan_nr,
|
||||
struct l1sched_chan_state *chan_state, int8_t rssi, float toa)
|
||||
{
|
||||
struct gsm_lchan *lchan = &l1h->trx->ts[L1SAP_CHAN2TS(chan_nr)]
|
||||
struct gsm_lchan *lchan = &l1t->trx->ts[L1SAP_CHAN2TS(chan_nr)]
|
||||
.lchan[l1sap_chan2ss(chan_nr)];
|
||||
|
||||
if (trx_ms_power_loop)
|
||||
ms_power_val(chan_state, rssi);
|
||||
|
||||
if (trx_ta_loop)
|
||||
ta_val(l1h, lchan, chan_nr, chan_state, toa);
|
||||
ta_val(lchan, chan_nr, chan_state, toa);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int trx_loop_sacch_clock(struct trx_l1h *l1h, uint8_t chan_nr,
|
||||
struct trx_chan_state *chan_state)
|
||||
int trx_loop_sacch_clock(struct l1sched_trx *l1t, uint8_t chan_nr,
|
||||
struct l1sched_chan_state *chan_state)
|
||||
{
|
||||
struct gsm_lchan *lchan = &l1h->trx->ts[L1SAP_CHAN2TS(chan_nr)]
|
||||
struct gsm_lchan *lchan = &l1t->trx->ts[L1SAP_CHAN2TS(chan_nr)]
|
||||
.lchan[l1sap_chan2ss(chan_nr)];
|
||||
|
||||
if (trx_ms_power_loop)
|
||||
ms_power_clock(l1h, lchan, chan_nr, chan_state);
|
||||
ms_power_clock(lchan, chan_nr, chan_state);
|
||||
|
||||
/* count the number of SACCH clocks */
|
||||
chan_state->meas.clock++;
|
||||
|
@ -240,10 +245,11 @@ int trx_loop_sacch_clock(struct trx_l1h *l1h, uint8_t chan_nr,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int trx_loop_amr_input(struct trx_l1h *l1h, uint8_t chan_nr,
|
||||
struct trx_chan_state *chan_state, float ber)
|
||||
int trx_loop_amr_input(struct l1sched_trx *l1t, uint8_t chan_nr,
|
||||
struct l1sched_chan_state *chan_state, float ber)
|
||||
{
|
||||
struct gsm_lchan *lchan = &l1h->trx->ts[L1SAP_CHAN2TS(chan_nr)]
|
||||
struct gsm_bts_trx *trx = l1t->trx;
|
||||
struct gsm_lchan *lchan = &trx->ts[L1SAP_CHAN2TS(chan_nr)]
|
||||
.lchan[l1sap_chan2ss(chan_nr)];
|
||||
int c_i;
|
||||
|
||||
|
@ -280,7 +286,7 @@ int trx_loop_amr_input(struct trx_l1h *l1h, uint8_t chan_nr,
|
|||
|
||||
LOGP(DLOOP, LOGL_DEBUG, "Current bit error rate (BER) %.6f "
|
||||
"codec id %d of trx=%u chan_nr=0x%02x\n", ber,
|
||||
chan_state->ul_ft, l1h->trx->nr, chan_nr);
|
||||
chan_state->ul_ft, trx->nr, chan_nr);
|
||||
|
||||
/* degrade */
|
||||
if (chan_state->dl_cmr > 0) {
|
||||
|
@ -290,7 +296,7 @@ int trx_loop_amr_input(struct trx_l1h *l1h, uint8_t chan_nr,
|
|||
LOGP(DLOOP, LOGL_DEBUG, "Degrading due to BER %.6f "
|
||||
"from codec id %d to %d of trx=%u "
|
||||
"chan_nr=0x%02x\n", ber, chan_state->dl_cmr,
|
||||
chan_state->dl_cmr - 1, l1h->trx->nr, chan_nr);
|
||||
chan_state->dl_cmr - 1, trx->nr, chan_nr);
|
||||
chan_state->dl_cmr--;
|
||||
}
|
||||
|
||||
|
@ -306,7 +312,7 @@ int trx_loop_amr_input(struct trx_l1h *l1h, uint8_t chan_nr,
|
|||
LOGP(DLOOP, LOGL_DEBUG, "Upgrading due to BER %.6f "
|
||||
"from codec id %d to %d of trx=%u "
|
||||
"chan_nr=0x%02x\n", ber, chan_state->dl_cmr,
|
||||
chan_state->dl_cmr + 1, l1h->trx->nr, chan_nr);
|
||||
chan_state->dl_cmr + 1, trx->nr, chan_nr);
|
||||
chan_state->dl_cmr++;
|
||||
}
|
||||
|
||||
|
@ -316,7 +322,7 @@ int trx_loop_amr_input(struct trx_l1h *l1h, uint8_t chan_nr,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int trx_loop_amr_set(struct trx_chan_state *chan_state, int loop)
|
||||
int trx_loop_amr_set(struct l1sched_chan_state *chan_state, int loop)
|
||||
{
|
||||
if (chan_state->amr_loop && !loop) {
|
||||
chan_state->amr_loop = 0;
|
||||
|
@ -336,4 +342,3 @@ int trx_loop_amr_set(struct trx_chan_state *chan_state, int loop)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,15 +17,15 @@ extern int trx_ms_power_loop;
|
|||
extern int8_t trx_target_rssi;
|
||||
extern int trx_ta_loop;
|
||||
|
||||
int trx_loop_sacch_input(struct trx_l1h *l1h, uint8_t chan_nr,
|
||||
struct trx_chan_state *chan_state, int8_t rssi, float toa);
|
||||
int trx_loop_sacch_input(struct l1sched_trx *l1t, uint8_t chan_nr,
|
||||
struct l1sched_chan_state *chan_state, int8_t rssi, float toa);
|
||||
|
||||
int trx_loop_sacch_clock(struct trx_l1h *l1h, uint8_t chan_nr,
|
||||
struct trx_chan_state *chan_state);
|
||||
int trx_loop_sacch_clock(struct l1sched_trx *l1t, uint8_t chan_nr,
|
||||
struct l1sched_chan_state *chan_state);
|
||||
|
||||
int trx_loop_amr_input(struct trx_l1h *l1h, uint8_t chan_nr,
|
||||
struct trx_chan_state *chan_state, float ber);
|
||||
int trx_loop_amr_input(struct l1sched_trx *l1t, uint8_t chan_nr,
|
||||
struct l1sched_chan_state *chan_state, float ber);
|
||||
|
||||
int trx_loop_amr_set(struct trx_chan_state *chan_state, int loop);
|
||||
int trx_loop_amr_set(struct l1sched_chan_state *chan_state, int loop);
|
||||
|
||||
#endif /* _TRX_LOOPS_H */
|
||||
|
|
|
@ -53,10 +53,10 @@
|
|||
#include <osmo-bts/pcu_if.h>
|
||||
#include <osmo-bts/l1sap.h>
|
||||
#include <osmo-bts/control_if.h>
|
||||
#include <osmo-bts/scheduler.h>
|
||||
|
||||
#include "l1_if.h"
|
||||
#include "trx_if.h"
|
||||
#include "scheduler.h"
|
||||
|
||||
int bts_model_init(struct gsm_bts *bts)
|
||||
{
|
||||
|
|
|
@ -1,52 +0,0 @@
|
|||
#ifndef TRX_SCHEDULER_H
|
||||
#define TRX_SCHEDULER_H
|
||||
|
||||
/*! \brief how many frame numbers in advance we should send bursts to PHY */
|
||||
extern uint32_t trx_clock_advance;
|
||||
/*! \brief advance RTS.ind to L2 by that many clocks */
|
||||
extern uint32_t trx_rts_advance;
|
||||
/*! \brief last frame number as received from PHY */
|
||||
extern uint32_t transceiver_last_fn;
|
||||
|
||||
|
||||
/*! \brief Initialize the scheudler data structures */
|
||||
int trx_sched_init(struct trx_l1h *l1h);
|
||||
|
||||
/*! \brief De-initialize the scheudler data structures */
|
||||
void trx_sched_exit(struct trx_l1h *l1h);
|
||||
|
||||
/*! \brief Handle a PH-DATA.req from L2 down to L1 */
|
||||
int trx_sched_ph_data_req(struct trx_l1h *l1h, struct osmo_phsap_prim *l1sap);
|
||||
|
||||
/*! \brief Handle a PH-TCH.req from L2 down to L1 */
|
||||
int trx_sched_tch_req(struct trx_l1h *l1h, struct osmo_phsap_prim *l1sap);
|
||||
|
||||
/*! \brief PHY informs us of new (current) GSM freme nunmber */
|
||||
int trx_sched_clock(uint32_t fn);
|
||||
|
||||
/*! \brief handle an UL burst received by PHY */
|
||||
int trx_sched_ul_burst(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
|
||||
sbit_t *bits, int8_t rssi, float toa);
|
||||
|
||||
/*! \brief set multiframe scheduler to given physical channel config */
|
||||
int trx_sched_set_pchan(struct trx_l1h *l1h, uint8_t tn,
|
||||
enum gsm_phys_chan_config pchan);
|
||||
|
||||
/*! \brief set all matching logical channels active/inactive */
|
||||
int trx_sched_set_lchan(struct trx_l1h *l1h, uint8_t chan_nr, uint8_t link_id,
|
||||
int active);
|
||||
|
||||
/*! \brief set mode of all matching logical channels to given mode(s) */
|
||||
int trx_sched_set_mode(struct trx_l1h *l1h, uint8_t chan_nr, uint8_t rsl_cmode,
|
||||
uint8_t tch_mode, int codecs, uint8_t codec0, uint8_t codec1,
|
||||
uint8_t codec2, uint8_t codec3, uint8_t initial_codec,
|
||||
uint8_t handover);
|
||||
|
||||
/*! \brief set ciphering on given logical channels */
|
||||
int trx_sched_set_cipher(struct trx_l1h *l1h, uint8_t chan_nr, int downlink,
|
||||
int algo, uint8_t *key, int key_len);
|
||||
|
||||
/* \brief close all logical channels and reset timeslots */
|
||||
void trx_sched_reset(struct trx_l1h *l1h);
|
||||
|
||||
#endif /* TRX_SCHEDULER_H */
|
File diff suppressed because it is too large
Load Diff
|
@ -36,10 +36,10 @@
|
|||
|
||||
#include <osmo-bts/logging.h>
|
||||
#include <osmo-bts/bts.h>
|
||||
#include <osmo-bts/scheduler.h>
|
||||
|
||||
#include "l1_if.h"
|
||||
#include "trx_if.h"
|
||||
#include "scheduler.h"
|
||||
|
||||
/* enable to print RSSI level graph */
|
||||
//#define TOA_RSSI_DEBUG
|
||||
|
@ -121,6 +121,7 @@ static struct osmo_fd trx_ofd_clk;
|
|||
/* get clock from clock socket */
|
||||
static int trx_clk_read_cb(struct osmo_fd *ofd, unsigned int what)
|
||||
{
|
||||
struct trx_l1h *l1h = ofd->data;
|
||||
char buf[1500];
|
||||
int len;
|
||||
uint32_t fn;
|
||||
|
@ -145,7 +146,7 @@ static int trx_clk_read_cb(struct osmo_fd *ofd, unsigned int what)
|
|||
"correctly, correcting to fn=%u\n", fn);
|
||||
}
|
||||
|
||||
trx_sched_clock(fn);
|
||||
trx_sched_clock(l1h->trx->bts, fn);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -454,7 +455,7 @@ static int trx_data_read_cb(struct osmo_fd *ofd, unsigned int what)
|
|||
fprintf(stderr, "%s\n", deb);
|
||||
#endif
|
||||
|
||||
trx_sched_ul_burst(l1h, tn, fn, bits, rssi, toa);
|
||||
trx_sched_ul_burst(&l1h->l1s, tn, fn, bits, rssi, toa);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -503,7 +504,7 @@ int trx_if_open(struct trx_l1h *l1h)
|
|||
|
||||
/* open sockets */
|
||||
if (l1h->trx->nr == 0) {
|
||||
rc = trx_udp_open(NULL, &trx_ofd_clk, base_port_local,
|
||||
rc = trx_udp_open(l1h, &trx_ofd_clk, base_port_local,
|
||||
trx_clk_read_cb);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
@ -558,3 +559,7 @@ void trx_if_close(struct trx_l1h *l1h)
|
|||
trx_udp_close(&l1h->trx_ofd_data);
|
||||
}
|
||||
|
||||
int trx_if_powered(struct trx_l1h *l1h)
|
||||
{
|
||||
return l1h->config.poweron;
|
||||
}
|
||||
|
|
|
@ -31,5 +31,6 @@ int trx_if_data(struct trx_l1h *l1h, uint8_t tn, uint32_t fn, uint8_t pwr,
|
|||
int trx_if_open(struct trx_l1h *l1h);
|
||||
void trx_if_flush(struct trx_l1h *l1h);
|
||||
void trx_if_close(struct trx_l1h *l1h);
|
||||
int trx_if_powered(struct trx_l1h *l1h);
|
||||
|
||||
#endif /* TRX_IF_H */
|
||||
|
|
|
@ -39,9 +39,9 @@
|
|||
#include <osmo-bts/gsm_data.h>
|
||||
#include <osmo-bts/logging.h>
|
||||
#include <osmo-bts/vty.h>
|
||||
#include <osmo-bts/scheduler.h>
|
||||
|
||||
#include "l1_if.h"
|
||||
#include "scheduler.h"
|
||||
#include "trx_if.h"
|
||||
#include "loops.h"
|
||||
|
||||
|
|
Loading…
Reference in New Issue