diff options
-rw-r--r-- | include/osmocom/bsc/meas_rep.h | 24 | ||||
-rw-r--r-- | src/osmo-bsc/handover_decision.c | 16 | ||||
-rw-r--r-- | src/osmo-bsc/handover_decision_2.c | 10 | ||||
-rw-r--r-- | src/osmo-bsc/meas_rep.c | 58 |
4 files changed, 82 insertions, 26 deletions
diff --git a/include/osmocom/bsc/meas_rep.h b/include/osmocom/bsc/meas_rep.h index 54e0519e8..5cfeb98fb 100644 --- a/include/osmocom/bsc/meas_rep.h +++ b/include/osmocom/bsc/meas_rep.h @@ -51,14 +51,32 @@ struct gsm_meas_rep { struct gsm_meas_rep_cell cell[6]; }; +enum tdma_meas_field { + TDMA_MEAS_FIELD_RXLEV = 0, + TDMA_MEAS_FIELD_RXQUAL = 1, +}; + +enum tdma_meas_dir { + TDMA_MEAS_DIR_UL = 0, + TDMA_MEAS_DIR_DL = 1, +}; + +/* (function choose_meas_rep_field() depends on FULL and SUB being 0 and 1, but doesn't care about AUTO's value) */ +enum tdma_meas_set { + TDMA_MEAS_SET_FULL = 0, + TDMA_MEAS_SET_SUB = 1, + TDMA_MEAS_SET_AUTO, +}; + /* obtain an average over the last 'num' fields in the meas reps */ int get_meas_rep_avg(const struct gsm_lchan *lchan, - enum meas_rep_field field, unsigned int num); + enum tdma_meas_field field, enum tdma_meas_dir dir, enum tdma_meas_set set, + unsigned int num); /* Check if N out of M last values for FIELD are >= bd */ int meas_rep_n_out_of_m_be(const struct gsm_lchan *lchan, - enum meas_rep_field field, - unsigned int n, unsigned int m, int be); + enum tdma_meas_field field, enum tdma_meas_dir dir, enum tdma_meas_set set, + unsigned int n, unsigned int m, int be); unsigned int calc_initial_idx(unsigned int array_size, unsigned int meas_rep_idx, diff --git a/src/osmo-bsc/handover_decision.c b/src/osmo-bsc/handover_decision.c index 1eeb277ff..220fa1c7e 100644 --- a/src/osmo-bsc/handover_decision.c +++ b/src/osmo-bsc/handover_decision.c @@ -214,7 +214,7 @@ static void attempt_handover(struct gsm_meas_rep *mr) static void on_measurement_report(struct gsm_meas_rep *mr) { struct gsm_bts *bts = mr->lchan->ts->trx->bts; - enum meas_rep_field dlev, dqual; + enum tdma_meas_set meas_set; int av_rxlev; unsigned int pwr_interval; @@ -231,24 +231,18 @@ static void on_measurement_report(struct gsm_meas_rep *mr) return; } - if (mr->flags & MEAS_REP_F_DL_DTX) { - dlev = MEAS_REP_DL_RXLEV_SUB; - dqual = MEAS_REP_DL_RXQUAL_SUB; - } else { - dlev = MEAS_REP_DL_RXLEV_FULL; - dqual = MEAS_REP_DL_RXQUAL_FULL; - } + meas_set = (mr->flags & MEAS_REP_F_DL_DTX) ? TDMA_MEAS_SET_SUB : TDMA_MEAS_SET_FULL; /* parse actual neighbor cell info */ if (mr->num_cell > 0 && mr->num_cell < 7) process_meas_neigh(mr); - av_rxlev = get_meas_rep_avg(mr->lchan, dlev, + av_rxlev = get_meas_rep_avg(mr->lchan, TDMA_MEAS_FIELD_RXLEV, TDMA_MEAS_DIR_DL, meas_set, ho_get_hodec1_rxlev_avg_win(bts->ho)); /* Interference HO */ if (rxlev2dbm(av_rxlev) > -85 && - meas_rep_n_out_of_m_be(mr->lchan, dqual, 3, 4, 5)) { + meas_rep_n_out_of_m_be(mr->lchan, TDMA_MEAS_FIELD_RXQUAL, TDMA_MEAS_DIR_DL, meas_set, 3, 4, 5)) { LOGPC(DHO, LOGL_INFO, "HO cause: Interference HO av_rxlev=%d dBm\n", rxlev2dbm(av_rxlev)); attempt_handover(mr); @@ -256,7 +250,7 @@ static void on_measurement_report(struct gsm_meas_rep *mr) } /* Bad Quality */ - if (meas_rep_n_out_of_m_be(mr->lchan, dqual, 3, 4, 5)) { + if (meas_rep_n_out_of_m_be(mr->lchan, TDMA_MEAS_FIELD_RXQUAL, TDMA_MEAS_DIR_DL, meas_set, 3, 4, 5)) { LOGPC(DHO, LOGL_INFO, "HO cause: Bad Quality av_rxlev=%d dBm\n", rxlev2dbm(av_rxlev)); attempt_handover(mr); return; diff --git a/src/osmo-bsc/handover_decision_2.c b/src/osmo-bsc/handover_decision_2.c index d77887618..67208fe90 100644 --- a/src/osmo-bsc/handover_decision_2.c +++ b/src/osmo-bsc/handover_decision_2.c @@ -244,18 +244,16 @@ static struct gsm_meas_rep_cell *cell_in_rep(struct gsm_meas_rep *mr, uint16_t a static int current_rxlev(struct gsm_lchan *lchan) { struct gsm_bts *bts = lchan->ts->trx->bts; - return get_meas_rep_avg(lchan, - ho_get_hodec2_full_tdma(bts->ho) ? - MEAS_REP_DL_RXLEV_FULL : MEAS_REP_DL_RXLEV_SUB, + return get_meas_rep_avg(lchan, TDMA_MEAS_FIELD_RXLEV, TDMA_MEAS_DIR_DL, + ho_get_hodec2_full_tdma(bts->ho) ? TDMA_MEAS_SET_FULL : TDMA_MEAS_SET_SUB, ho_get_hodec2_rxlev_avg_win(bts->ho)); } static int current_rxqual(struct gsm_lchan *lchan) { struct gsm_bts *bts = lchan->ts->trx->bts; - return get_meas_rep_avg(lchan, - ho_get_hodec2_full_tdma(bts->ho) ? - MEAS_REP_DL_RXQUAL_FULL : MEAS_REP_DL_RXQUAL_SUB, + return get_meas_rep_avg(lchan, TDMA_MEAS_FIELD_RXQUAL, TDMA_MEAS_DIR_DL, + ho_get_hodec2_full_tdma(bts->ho) ? TDMA_MEAS_SET_FULL : TDMA_MEAS_SET_SUB, ho_get_hodec2_rxqual_avg_win(bts->ho)); } diff --git a/src/osmo-bsc/meas_rep.c b/src/osmo-bsc/meas_rep.c index 32c689db9..97c30ac1a 100644 --- a/src/osmo-bsc/meas_rep.c +++ b/src/osmo-bsc/meas_rep.c @@ -80,9 +80,47 @@ unsigned int calc_initial_idx(unsigned int array_size, return idx; } -/* obtain an average over the last 'num' fields in the meas reps */ +static inline enum meas_rep_field choose_meas_rep_field(enum tdma_meas_field field, enum tdma_meas_dir dir, + enum tdma_meas_set set) +{ + osmo_static_assert(TDMA_MEAS_FIELD_RXLEV >= 0 && TDMA_MEAS_FIELD_RXLEV <= 1 + && TDMA_MEAS_FIELD_RXQUAL >= 0 && TDMA_MEAS_FIELD_RXQUAL <= 1 + && TDMA_MEAS_DIR_UL >= 0 && TDMA_MEAS_DIR_UL <= 1 + && TDMA_MEAS_DIR_DL >= 0 && TDMA_MEAS_DIR_DL <= 1 + && TDMA_MEAS_SET_FULL >= 0 && TDMA_MEAS_SET_FULL <= 1 + && TDMA_MEAS_SET_SUB >= 0 && TDMA_MEAS_SET_SUB <= 1, + choose_meas_rep_field__mux_macro_input_ranges); +#define MUX(FIELD, DIR, SET) ((FIELD) + ((DIR) << 1) + ((SET) << 2)) + + switch (MUX(field, dir, set)) { + case MUX(TDMA_MEAS_FIELD_RXLEV, TDMA_MEAS_DIR_UL, TDMA_MEAS_SET_FULL): + return MEAS_REP_UL_RXLEV_FULL; + case MUX(TDMA_MEAS_FIELD_RXLEV, TDMA_MEAS_DIR_UL, TDMA_MEAS_SET_SUB): + return MEAS_REP_UL_RXLEV_SUB; + case MUX(TDMA_MEAS_FIELD_RXLEV, TDMA_MEAS_DIR_DL, TDMA_MEAS_SET_FULL): + return MEAS_REP_DL_RXLEV_FULL; + case MUX(TDMA_MEAS_FIELD_RXLEV, TDMA_MEAS_DIR_DL, TDMA_MEAS_SET_SUB): + return MEAS_REP_DL_RXLEV_SUB; + case MUX(TDMA_MEAS_FIELD_RXQUAL, TDMA_MEAS_DIR_UL, TDMA_MEAS_SET_FULL): + return MEAS_REP_UL_RXQUAL_FULL; + case MUX(TDMA_MEAS_FIELD_RXQUAL, TDMA_MEAS_DIR_UL, TDMA_MEAS_SET_SUB): + return MEAS_REP_UL_RXQUAL_SUB; + case MUX(TDMA_MEAS_FIELD_RXQUAL, TDMA_MEAS_DIR_DL, TDMA_MEAS_SET_FULL): + return MEAS_REP_DL_RXQUAL_FULL; + case MUX(TDMA_MEAS_FIELD_RXQUAL, TDMA_MEAS_DIR_DL, TDMA_MEAS_SET_SUB): + return MEAS_REP_DL_RXQUAL_SUB; + default: + OSMO_ASSERT(false); + } + +#undef MUX +} + +/* obtain an average over the last 'num' fields in the meas reps. For 'field', pass either DL_RXLEV or DL_RXQUAL, and + * by tdma_meas_set, choose between full, subset or automatic choice of set. */ int get_meas_rep_avg(const struct gsm_lchan *lchan, - enum meas_rep_field field, unsigned int num) + enum tdma_meas_field field, enum tdma_meas_dir dir, enum tdma_meas_set set, + unsigned int num) { unsigned int i, idx; int avg = 0, valid_num = 0; @@ -98,7 +136,11 @@ int get_meas_rep_avg(const struct gsm_lchan *lchan, for (i = 0; i < num; i++) { int j = (idx+i) % ARRAY_SIZE(lchan->meas_rep); - int val = get_field(&lchan->meas_rep[j], field); + enum meas_rep_field use_field; + int val; + + use_field = choose_meas_rep_field(field, dir, set); + val = get_field(&lchan->meas_rep[j], use_field); if (val >= 0) { avg += val; @@ -114,8 +156,8 @@ int get_meas_rep_avg(const struct gsm_lchan *lchan, /* Check if N out of M last values for FIELD are >= bd */ int meas_rep_n_out_of_m_be(const struct gsm_lchan *lchan, - enum meas_rep_field field, - unsigned int n, unsigned int m, int be) + enum tdma_meas_field field, enum tdma_meas_dir dir, enum tdma_meas_set set, + unsigned int n, unsigned int m, int be) { unsigned int i, idx; int count = 0; @@ -125,7 +167,11 @@ int meas_rep_n_out_of_m_be(const struct gsm_lchan *lchan, for (i = 0; i < m; i++) { int j = (idx + i) % ARRAY_SIZE(lchan->meas_rep); - int val = get_field(&lchan->meas_rep[j], field); + enum meas_rep_field use_field; + int val; + + use_field = choose_meas_rep_field(field, dir, set); + val = get_field(&lchan->meas_rep[j], use_field); if (val >= be) /* implies that val < 0 will not count */ count++; |