TRX: Handover access burst support

This commit is contained in:
Andreas Eversberg 2013-06-12 09:12:04 +02:00 committed by Harald Welte
parent 6527dffc94
commit b9a917a138
6 changed files with 62 additions and 10 deletions

View File

@ -501,7 +501,8 @@ int bts_model_l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap)
lchan->tch.amr_mr.mode[1].mode,
lchan->tch.amr_mr.mode[2].mode,
lchan->tch.amr_mr.mode[3].mode,
amr_get_initial_mode(lchan));
amr_get_initial_mode(lchan),
(lchan->ho.active == 1));
/* init lapdm */
lchan_init_lapdm(lchan);
/* set lchan active */
@ -520,7 +521,8 @@ int bts_model_l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap)
lchan->tch.amr_mr.mode[1].mode,
lchan->tch.amr_mr.mode[2].mode,
lchan->tch.amr_mr.mode[3].mode,
amr_get_initial_mode(lchan));
amr_get_initial_mode(lchan),
0);
break;
}
if ((chan_nr & 0x80)) {

View File

@ -100,6 +100,9 @@ struct trx_chan_state {
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 trx_config {
@ -157,6 +160,7 @@ struct trx_l1h {
/* Channel states for all channels on all timeslots */
struct trx_chan_state chan_states[8][_TRX_CHAN_MAX];
struct llist_head dl_prims[8]; /* Queue primitves for TX */
uint8_t ho_rach_detect[8][8];
};
struct trx_l1h *l1if_open(struct gsm_bts_trx *trx);

View File

@ -1173,17 +1173,20 @@ static int rx_rach_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
enum trx_chan_type chan, uint8_t bid, sbit_t *bits, int8_t rssi,
float toa)
{
uint8_t chan_nr;
struct osmo_phsap_prim l1sap;
uint8_t ra;
int rc;
LOGP(DL1C, LOGL_NOTICE, "Received %s fn=%u toa=%.2f\n",
chan_nr = trx_chan_desc[chan].chan_nr | tn;
LOGP(DL1C, LOGL_NOTICE, "Received Access Burst on %s fn=%u toa=%.2f\n",
trx_chan_desc[chan].name, fn, toa);
/* decode */
rc = rach_decode(&ra, bits + 8 + 41, l1h->trx->bts->bsic);
if (rc) {
LOGP(DL1C, LOGL_NOTICE, "Received bad rach frame at fn=%u "
LOGP(DL1C, LOGL_NOTICE, "Received bad AB frame at fn=%u "
"(%u/51)\n", fn, fn % 51);
return 0;
}
@ -1193,6 +1196,7 @@ static int rx_rach_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
memset(&l1sap, 0, sizeof(l1sap));
osmo_prim_init(&l1sap.oph, SAP_GSM_PH, PRIM_PH_RACH, PRIM_OP_INDICATION,
NULL);
l1sap.u.rach_ind.chan_nr = chan_nr;
l1sap.u.rach_ind.ra = ra;
#ifdef TA_TEST
#warning TIMING ADVANCE TEST-HACK IS ENABLED!!!
@ -1222,6 +1226,10 @@ static int rx_data_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
uint8_t l2[23], l2_len;
int rc;
/* handle rach, if handover rach detection is turned on */
if (chan_state->ho_rach_detect == 1)
return rx_rach_fn(l1h, tn, fn, chan, bid, bits, rssi, toa);
LOGP(DL1C, LOGL_DEBUG, "Data received %s fn=%u ts=%u trx=%u bid=%u\n",
trx_chan_desc[chan].name, fn, tn, l1h->trx->nr, bid);
@ -1382,6 +1390,10 @@ static int rx_tchf_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
int rc, amr = 0;
float ber;
/* handle rach, if handover rach detection is turned on */
if (chan_state->ho_rach_detect == 1)
return rx_rach_fn(l1h, tn, fn, chan, bid, bits, rssi, toa);
LOGP(DL1C, LOGL_DEBUG, "TCH/F received %s fn=%u ts=%u trx=%u bid=%u\n",
trx_chan_desc[chan].name, fn, tn, l1h->trx->nr, bid);
@ -1522,6 +1534,10 @@ static int rx_tchh_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn,
int rc, amr = 0;
float ber;
/* handle rach, if handover rach detection is turned on */
if (chan_state->ho_rach_detect == 1)
return rx_rach_fn(l1h, tn, fn, chan, bid, bits, rssi, toa);
LOGP(DL1C, LOGL_DEBUG, "TCH/H received %s fn=%u ts=%u trx=%u bid=%u\n",
trx_chan_desc[chan].name, fn, tn, l1h->trx->nr, bid);
@ -2487,9 +2503,10 @@ int trx_sched_set_lchan(struct trx_l1h *l1h, uint8_t chan_nr, uint8_t link_id,
/* setting all logical channels given attributes to active/inactive */
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_id)
uint8_t codec2, uint8_t codec3, uint8_t initial_id, uint8_t handover)
{
uint8_t tn = L1SAP_CHAN2TS(chan_nr);
uint8_t ss = l1sap_chan2ss(chan_nr);
int i;
int rc = -EINVAL;
struct trx_chan_state *chan_state;
@ -2499,11 +2516,13 @@ int trx_sched_set_mode(struct trx_l1h *l1h, uint8_t chan_nr, uint8_t rsl_cmode,
if (trx_chan_desc[i].chan_nr == (chan_nr & 0xf8)
&& trx_chan_desc[i].link_id == 0x00) {
chan_state = &l1h->chan_states[tn][i];
LOGP(DL1C, LOGL_NOTICE, "Set mode %u, %u on "
"%s of trx=%d ts=%d\n", rsl_cmode, tch_mode,
trx_chan_desc[i].name, l1h->trx->nr, tn);
LOGP(DL1C, LOGL_NOTICE, "Set mode %u, %u, handover %u "
"on %s of trx=%d ts=%d\n", rsl_cmode, tch_mode,
handover, trx_chan_desc[i].name, l1h->trx->nr,
tn);
chan_state->rsl_cmode = rsl_cmode;
chan_state->tch_mode = tch_mode;
chan_state->ho_rach_detect = handover;
if (rsl_cmode == RSL_CMOD_SPD_SPEECH
&& tch_mode == GSM48_CMODE_SPEECH_AMR) {
chan_state->codecs = codecs;
@ -2522,6 +2541,19 @@ int trx_sched_set_mode(struct trx_l1h *l1h, uint8_t chan_nr, uint8_t rsl_cmode,
}
}
/* command rach detection
* always enable handover, even if state is still set (due to loss
* of transceiver link).
* disable handover, if state is still set, since we might not know
* the actual state of transceiver (due to loss of link) */
if (handover) {
l1h->ho_rach_detect[tn][ss] = 1;
trx_if_cmd_handover(l1h, tn, ss);
} else if (l1h->ho_rach_detect[tn][ss]) {
l1h->ho_rach_detect[tn][ss] = 0;
trx_if_cmd_nohandover(l1h, tn, ss);
}
return rc;
}
@ -2721,7 +2753,8 @@ int trx_sched_ul_burst(struct trx_l1h *l1h, uint8_t tn, uint32_t current_fn,
}
func(l1h, tn, fn, chan, bid, bits, rssi, toa);
} else if (chan != TRXC_RACH) {
} else if (chan != TRXC_RACH
&& !l1h->chan_states[tn][chan].ho_rach_detect) {
sbit_t spare[148];
memset(spare, 0, 148);

View File

@ -29,7 +29,8 @@ int trx_sched_set_lchan(struct trx_l1h *l1h, uint8_t chan_nr, uint8_t link_id,
/* setting all logical channels given attributes to active/inactive */
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 codec2, uint8_t codec3, uint8_t initial_codec,
uint8_t handover);
/* setting cipher on logical channels */
int trx_sched_set_cipher(struct trx_l1h *l1h, uint8_t chan_nr, int downlink,

View File

@ -294,6 +294,16 @@ int trx_if_cmd_txtune(struct trx_l1h *l1h, uint16_t arfcn)
return trx_ctrl_cmd(l1h, 1, "TXTUNE", "%d", freq10 * 100);
}
int trx_if_cmd_handover(struct trx_l1h *l1h, uint8_t tn, uint8_t ss)
{
return trx_ctrl_cmd(l1h, 1, "HANDOVER", "%d %d", tn, ss);
}
int trx_if_cmd_nohandover(struct trx_l1h *l1h, uint8_t tn, uint8_t ss)
{
return trx_ctrl_cmd(l1h, 1, "NOHANDOVER", "%d %d", tn, ss);
}
/* get response from ctrl socket */
static int trx_ctrl_read_cb(struct osmo_fd *ofd, unsigned int what)
{

View File

@ -24,6 +24,8 @@ int trx_if_cmd_setmaxdly(struct trx_l1h *l1h, int dly);
int trx_if_cmd_setslot(struct trx_l1h *l1h, uint8_t tn, uint8_t type);
int trx_if_cmd_rxtune(struct trx_l1h *l1h, uint16_t arfcn);
int trx_if_cmd_txtune(struct trx_l1h *l1h, uint16_t arfcn);
int trx_if_cmd_handover(struct trx_l1h *l1h, uint8_t tn, uint8_t ss);
int trx_if_cmd_nohandover(struct trx_l1h *l1h, uint8_t tn, uint8_t ss);
int trx_if_data(struct trx_l1h *l1h, uint8_t tn, uint32_t fn, uint8_t pwr,
const ubit_t *bits);
int trx_if_open(struct trx_l1h *l1h);