diff --git a/src/bts.cpp b/src/bts.cpp index 24666af0..c8b63750 100644 --- a/src/bts.cpp +++ b/src/bts.cpp @@ -842,6 +842,53 @@ int BTS::rcv_rach(uint16_t ra, uint32_t Fn, int16_t qta, bool is_11bit, return rc; } +/* PTCCH/U sub-slot / frame-number mapping (see 3GPP TS 45.002, table 6) */ +static uint32_t ptcch_slot_map[PTCCH_TAI_NUM] = { + 12, 38, 64, 90, + 116, 142, 168, 194, + 220, 246, 272, 298, + 324, 350, 376, 402, +}; + +int BTS::rcv_ptcch_rach(uint8_t trx_nr, uint8_t ts_nr, uint32_t fn, int16_t qta) +{ + struct gprs_rlcmac_bts *bts = bts_data(); + struct gprs_rlcmac_pdch *pdch; + uint32_t fn416 = fn % 416; + uint8_t ss; + + /* Prevent buffer overflow */ + if (trx_nr >= ARRAY_SIZE(bts->trx) || ts_nr >= 8) { + LOGP(DRLCMAC, LOGL_ERROR, "Malformed RACH.ind message " + "(TRX=%u TS=%u FN=%u)\n", trx_nr, ts_nr, fn); + return -EINVAL; + } + + /* Make sure PDCH time-slot is enabled */ + pdch = &bts->trx[trx_nr].pdch[ts_nr]; + if (!pdch->m_is_enabled) { + LOGP(DRLCMAC, LOGL_NOTICE, "Rx PTCCH RACH.ind for inactive PDCH " + "(TRX=%u TS=%u FN=%u)\n", trx_nr, ts_nr, fn); + return -EAGAIN; + } + + /* Convert TDMA frame-number to PTCCH/U sub-slot number */ + for (ss = 0; ss < PTCCH_TAI_NUM; ss++) + if (ptcch_slot_map[ss] == fn416) + break; + if (ss == PTCCH_TAI_NUM) { + LOGP(DRLCMAC, LOGL_ERROR, "Failed to map PTCCH/U sub-slot for fn=%u\n", fn); + return -ENODEV; + } + + /* Apply the new Timing Advance value */ + LOGP(DRLCMAC, LOGL_INFO, "Continuous Timing Advance update " + "for TAI %u, new TA is %u\n", ss, qta2ta(qta)); + pdch->update_ta(ss, qta2ta(qta)); + + return 0; +} + void BTS::snd_dl_ass(gprs_rlcmac_tbf *tbf, bool poll, const char *imsi) { int plen; diff --git a/src/bts.h b/src/bts.h index c2cc3163..54a29cb7 100644 --- a/src/bts.h +++ b/src/bts.h @@ -301,6 +301,7 @@ public: uint32_t rfn_to_fn(int32_t rfn); int rcv_rach(uint16_t ra, uint32_t Fn, int16_t qta, bool is_11bit, enum ph_burst_type burst_type); + int rcv_ptcch_rach(uint8_t trx_nr, uint8_t ts_nr, uint32_t fn, int16_t qta); void snd_dl_ass(gprs_rlcmac_tbf *tbf, bool poll, const char *imsi); diff --git a/src/osmo-bts-litecell15/lc15_l1_if.c b/src/osmo-bts-litecell15/lc15_l1_if.c index 670263fc..24eb0faf 100644 --- a/src/osmo-bts-litecell15/lc15_l1_if.c +++ b/src/osmo-bts-litecell15/lc15_l1_if.c @@ -223,10 +223,6 @@ static int handle_ph_data_ind(struct lc15l1_hdl *fl1h, data_ind->u32Fn, &meas); break; - case GsmL1_Sapi_Ptcch: - // FIXME - rc = -1; - break; default: LOGP(DL1IF, LOGL_NOTICE, "Rx PH-DATA.ind for unknown L1 SAPI %s\n", get_value_string(lc15bts_l1sapi_names, data_ind->sapi)); @@ -251,8 +247,21 @@ static int handle_ph_ra_ind(struct lc15l1_hdl *fl1h, GsmL1_PhRaInd_t *ra_ind) return 0; DEBUGP(DL1IF, "Rx PH-RA.ind"); - bts_update_tbf_ta("PH-RA", ra_ind->u32Fn, fl1h->trx_no, ra_ind->u8Tn, - qta2ta(ra_ind->measParam.i16BurstTiming), true); + + switch (ra_ind->sapi) { + case GsmL1_Sapi_Pdtch: + bts_update_tbf_ta("PH-RA", ra_ind->u32Fn, fl1h->trx_no, ra_ind->u8Tn, + qta2ta(ra_ind->measParam.i16BurstTiming), true); + break; + case GsmL1_Sapi_Ptcch: + pcu_rx_rach_ind_pdtch(fl1h->trx_no, ra_ind->u8Tn, ra_ind->u32Fn, + ra_ind->measParam.i16BurstTiming); + break; + default: + LOGP(DL1IF, LOGL_NOTICE, "Rx PH-RA.ind for unknown L1 SAPI %s\n", + get_value_string(lc15bts_l1sapi_names, ra_ind->sapi)); + return -ENOTSUP; + } return 0; } diff --git a/src/osmo-bts-oc2g/oc2g_l1_if.c b/src/osmo-bts-oc2g/oc2g_l1_if.c index a02e9629..11fecba1 100644 --- a/src/osmo-bts-oc2g/oc2g_l1_if.c +++ b/src/osmo-bts-oc2g/oc2g_l1_if.c @@ -229,9 +229,6 @@ static int handle_ph_data_ind(struct oc2gl1_hdl *fl1h, data_ind->u32Fn, &meas); break; - case GsmL1_Sapi_Ptcch: - // FIXME - break; default: LOGP(DL1IF, LOGL_NOTICE, "Rx PH-DATA.ind for unknown L1 SAPI %s\n", get_value_string(oc2gbts_l1sapi_names, data_ind->sapi)); @@ -250,8 +247,20 @@ static int handle_ph_ra_ind(struct oc2gl1_hdl *fl1h, GsmL1_PhRaInd_t *ra_ind) LOGP(DL1IF, LOGL_DEBUG, "PH-RA-IND L1 qta=%d\n", ra_ind->measParam.i16BurstTiming); - bts_update_tbf_ta("PH-RA", ra_ind->u32Fn, fl1h->trx_no, ra_ind->u8Tn, - qta2ta(ra_ind->measParam.i16BurstTiming), true); + switch (ra_ind->sapi) { + case GsmL1_Sapi_Pdtch: + bts_update_tbf_ta("PH-RA", ra_ind->u32Fn, fl1h->trx_no, ra_ind->u8Tn, + qta2ta(ra_ind->measParam.i16BurstTiming), true); + break; + case GsmL1_Sapi_Ptcch: + pcu_rx_rach_ind_pdtch(fl1h->trx_no, ra_ind->u8Tn, ra_ind->u32Fn, + ra_ind->measParam.i16BurstTiming); + break; + default: + LOGP(DL1IF, LOGL_NOTICE, "Rx PH-RA.ind for unknown L1 SAPI %s\n", + get_value_string(oc2gbts_l1sapi_names, ra_ind->sapi)); + return -ENOTSUP; + } return 0; } diff --git a/src/osmo-bts-sysmo/sysmo_l1_if.c b/src/osmo-bts-sysmo/sysmo_l1_if.c index 9b310cc5..751629c8 100644 --- a/src/osmo-bts-sysmo/sysmo_l1_if.c +++ b/src/osmo-bts-sysmo/sysmo_l1_if.c @@ -208,10 +208,6 @@ static int handle_ph_data_ind(struct femtol1_hdl *fl1h, data_ind->u32Fn, &meas); break; - case GsmL1_Sapi_Ptcch: - // FIXME - rc = -1; - break; default: LOGP(DL1IF, LOGL_NOTICE, "Rx PH-DATA.ind for unknown L1 SAPI %s\n", get_value_string(femtobts_l1sapi_names, data_ind->sapi)); @@ -240,8 +236,21 @@ static int handle_ph_ra_ind(struct femtol1_hdl *fl1h, GsmL1_PhRaInd_t *ra_ind) return 0; DEBUGP(DL1IF, "Rx PH-RA.ind"); - bts_update_tbf_ta("PH-RA", ra_ind->u32Fn, fl1h->trx_no, ra_ind->u8Tn, - qta2ta(ra_ind->measParam.i16BurstTiming), true); + + switch (ra_ind->sapi) { + case GsmL1_Sapi_Pdtch: + bts_update_tbf_ta("PH-RA", ra_ind->u32Fn, fl1h->trx_no, ra_ind->u8Tn, + qta2ta(ra_ind->measParam.i16BurstTiming), true); + break; + case GsmL1_Sapi_Ptcch: + pcu_rx_rach_ind_pdtch(fl1h->trx_no, ra_ind->u8Tn, ra_ind->u32Fn, + ra_ind->measParam.i16BurstTiming); + break; + default: + LOGP(DL1IF, LOGL_NOTICE, "Rx PH-RA.ind for unknown L1 SAPI %s\n", + get_value_string(femtobts_l1sapi_names, ra_ind->sapi)); + return -ENOTSUP; + } return 0; } diff --git a/src/pcu_l1_if.cpp b/src/pcu_l1_if.cpp index 9c7724ce..5e22c5cc 100644 --- a/src/pcu_l1_if.cpp +++ b/src/pcu_l1_if.cpp @@ -405,6 +405,12 @@ static int pcu_rx_rts_req(struct gsm_pcu_if_rts_req *rts_req) return rc; } +/* C -> C++ adapter for direct DSP access code (e.g. osmo-bts-sysmo) */ +extern "C" int pcu_rx_rach_ind_pdtch(uint8_t trx_nr, uint8_t ts_nr, uint32_t fn, int16_t qta) +{ + return BTS::main_bts()->rcv_ptcch_rach(trx_nr, ts_nr, fn, qta); +} + static int pcu_rx_rach_ind(struct gsm_pcu_if_rach_ind *rach_ind) { int rc = 0; @@ -421,6 +427,11 @@ static int pcu_rx_rach_ind(struct gsm_pcu_if_rach_ind *rach_ind) rach_ind->qta, rach_ind->is_11bit, (ph_burst_type)rach_ind->burst_type); break; + case PCU_IF_SAPI_PTCCH: + rc = BTS::main_bts()->rcv_ptcch_rach( + rach_ind->trx_nr, rach_ind->ts_nr, + rach_ind->fn, rach_ind->qta); + break; default: LOGP(DL1IF, LOGL_ERROR, "Received PCU rach request with " "unsupported sapi %d\n", rach_ind->sapi); diff --git a/src/pcu_l1_if.h b/src/pcu_l1_if.h index 888ad284..a77a6c87 100644 --- a/src/pcu_l1_if.h +++ b/src/pcu_l1_if.h @@ -178,6 +178,7 @@ int pcu_rx_rts_req_pdtch(uint8_t trx, uint8_t ts, int pcu_rx_rts_req_ptcch(uint8_t trx, uint8_t ts, uint32_t fn, uint8_t block_nr); +int pcu_rx_rach_ind_pdtch(uint8_t trx_nr, uint8_t ts_nr, uint32_t fn, int16_t qta); int pcu_rx_data_ind_pdtch(uint8_t trx, uint8_t ts, uint8_t *data, uint8_t len, uint32_t fn, struct pcu_l1_meas *meas);