diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/osmo-bts-sysmo/l1_if.c | 120 | ||||
-rw-r--r-- | src/osmo-bts-sysmo/l1_if.h | 4 | ||||
-rw-r--r-- | src/osmo-bts-sysmo/sysmobts_vty.c | 28 |
3 files changed, 150 insertions, 2 deletions
diff --git a/src/osmo-bts-sysmo/l1_if.c b/src/osmo-bts-sysmo/l1_if.c index cdcf066d..5bda73fd 100644 --- a/src/osmo-bts-sysmo/l1_if.c +++ b/src/osmo-bts-sysmo/l1_if.c @@ -1,6 +1,7 @@ /* Interface handler for Sysmocom L1 */ /* (C) 2011 by Harald Welte <laforge@gnumonks.org> + * (C) 2014 by Holger Hans Peter Freyther * * All Rights Reserved * @@ -1486,8 +1487,9 @@ struct femtol1_hdl *l1if_open(void *priv) #if SUPERFEMTO_API_VERSION >= SUPERFEMTO_API(2,1,0) if (fl1h->hw_info.model_nr == 2050) { /* On the sysmoBTS 2050, we don't have an OCXO but - * always slave our clock to the GPS receiver */ - fl1h->clk_src = SuperFemto_ClkSrcId_GpsPps; + * start with the TCXO and will sync it with the PPS + * of the GPS in case there is a fix. */ + fl1h->clk_src = SuperFemto_ClkSrcId_Tcxo; LOGP(DL1C, LOGL_INFO, "Clock source defaulting to GPS 1PPS " "on sysmoBTS 2050\n"); } else { @@ -1524,3 +1526,117 @@ int l1if_close(struct femtol1_hdl *fl1h) l1if_transport_close(MQ_SYS_WRITE, fl1h); return 0; } + +#ifdef HW_SYSMOBTS_V1 +int l1if_rf_clock_info_reset(struct femtol1_hdl *fl1h) +{ + LOGP(DL1C, LOGL_ERROR, "RfClock calibration not supported on v1 hw.\n"); + return -ENOTSUP; +} + +int l1if_rf_clock_info_correct(struct femtol1_hdl *fl1h) +{ + LOGP(DL1C, LOGL_ERROR, "RfClock calibration not supported on v1 hw.\n"); + return -ENOTSUP; +} + +#else +static int clock_reset_cb(struct gsm_bts_trx *trx, struct msgb *resp) +{ + msgb_free(resp); + return 0; +} + +static int clock_setup_cb(struct gsm_bts_trx *trx, struct msgb *resp) +{ + SuperFemto_Prim_t *sysp = msgb_sysprim(resp); + + if (sysp->u.rfClockSetupCnf.status != GsmL1_Status_Success) + LOGP(DL1C, LOGL_ERROR, "Rx RfClockSetupConf failed with: %d\n", + sysp->u.rfClockSetupCnf.status); + msgb_free(resp); + return 0; +} + +static int clock_correct_info_cb(struct gsm_bts_trx *trx, struct msgb *resp) +{ + struct femtol1_hdl *fl1h = trx_femtol1_hdl(trx); + SuperFemto_Prim_t *sysp = msgb_sysprim(resp); + + LOGP(DL1C, LOGL_NOTICE, + "RfClockInfo iClkCor=%d/clkSrc=%s Err=%d/ErrRes=%d/clkSrc=%s\n", + sysp->u.rfClockInfoCnf.rfTrx.iClkCor, + get_value_string(femtobts_clksrc_names, + sysp->u.rfClockInfoCnf.rfTrx.clkSrc), + sysp->u.rfClockInfoCnf.rfTrxClkCal.iClkErr, + sysp->u.rfClockInfoCnf.rfTrxClkCal.iClkErrRes, + get_value_string(femtobts_clksrc_names, + sysp->u.rfClockInfoCnf.rfTrxClkCal.clkSrc)); + + if (sysp->u.rfClockInfoCnf.rfTrx.clkSrc == SuperFemto_ClkSrcId_GpsPps) { + LOGP(DL1C, LOGL_ERROR, + "Calibrating GPS against GPS doesn not make sense.\n"); + msgb_free(resp); + return -1; + } + + if (sysp->u.rfClockInfoCnf.rfTrxClkCal.clkSrc == SuperFemto_ClkSrcId_None) { + LOGP(DL1C, LOGL_ERROR, + "No reference clock set. Please reset first.\n"); + msgb_free(resp); + return -1; + } + + if (sysp->u.rfClockInfoCnf.rfTrxClkCal.iClkErrRes == 0) { + LOGP(DL1C, LOGL_ERROR, + "Couldn't determine the clock difference.\n"); + msgb_free(resp); + return -1; + } + + fl1h->clk_cal = sysp->u.rfClockInfoCnf.rfTrxClkCal.iClkErr; + fl1h->clk_use_eeprom = 0; + msgb_free(resp); + + /* + * Let's reset the counter and this will lead to applying the + * new calibration. + */ + l1if_rf_clock_info_reset(fl1h); + + return 0; +} + +int l1if_rf_clock_info_reset(struct femtol1_hdl *fl1h) +{ + struct msgb *msg = sysp_msgb_alloc(); + SuperFemto_Prim_t *sysp = msgb_sysprim(msg); + + /* Set GPS/PPS as reference */ + sysp->id = SuperFemto_PrimId_RfClockSetupReq; + sysp->u.rfClockSetupReq.rfTrx.iClkCor = get_clk_cal(fl1h); + sysp->u.rfClockSetupReq.rfTrx.clkSrc = fl1h->clk_src; + sysp->u.rfClockSetupReq.rfTrxClkCal.clkSrc = SuperFemto_ClkSrcId_GpsPps; + l1if_req_compl(fl1h, msg, clock_setup_cb); + + /* Reset the error counters */ + msg = sysp_msgb_alloc(); + sysp = msgb_sysprim(msg); + + sysp->id = SuperFemto_PrimId_RfClockInfoReq; + sysp->u.rfClockInfoReq.u8RstClkCal = 1; + + return l1if_req_compl(fl1h, msg, clock_reset_cb); +} + +int l1if_rf_clock_info_correct(struct femtol1_hdl *fl1h) +{ + struct msgb *msg = sysp_msgb_alloc(); + SuperFemto_Prim_t *sysp = msgb_sysprim(msg); + + sysp->id = SuperFemto_PrimId_RfClockInfoReq; + sysp->u.rfClockInfoReq.u8RstClkCal = 0; + + return l1if_req_compl(fl1h, msg, clock_correct_info_cb); +} +#endif diff --git a/src/osmo-bts-sysmo/l1_if.h b/src/osmo-bts-sysmo/l1_if.h index dd65de9a..1168aeaf 100644 --- a/src/osmo-bts-sysmo/l1_if.h +++ b/src/osmo-bts-sysmo/l1_if.h @@ -120,4 +120,8 @@ int l1if_set_ciphering(struct femtol1_hdl *fl1h, /* calibration loading */ int calib_load(struct femtol1_hdl *fl1h); +/* on-line re-calibration */ +int l1if_rf_clock_info_reset(struct femtol1_hdl *fl1h); +int l1if_rf_clock_info_correct(struct femtol1_hdl *fl1h); + #endif /* _FEMTO_L1_H */ diff --git a/src/osmo-bts-sysmo/sysmobts_vty.c b/src/osmo-bts-sysmo/sysmobts_vty.c index 06b288bd..690ffed9 100644 --- a/src/osmo-bts-sysmo/sysmobts_vty.c +++ b/src/osmo-bts-sysmo/sysmobts_vty.c @@ -426,6 +426,32 @@ DEFUN(set_tx_power, set_tx_power_cmd, return CMD_SUCCESS; } +DEFUN(reset_rf_clock_ctr, reset_rf_clock_ctr_cmd, + "trx <0-0> rf-clock-info reset", + TRX_STR + "RF Clock Information\n" "Reset the counter\n") +{ + int trx_nr = atoi(argv[0]); + struct gsm_bts_trx *trx = gsm_bts_trx_num(vty_bts, trx_nr); + struct femtol1_hdl *fl1h = trx_femtol1_hdl(trx); + + l1if_rf_clock_info_reset(fl1h); + return CMD_SUCCESS; +} + +DEFUN(correct_rf_clock_ctr, correct_rf_clock_ctr_cmd, + "trx <0-0> rf-clock-info correct", + TRX_STR + "RF Clock Information\n" "Apply\n") +{ + int trx_nr = atoi(argv[0]); + struct gsm_bts_trx *trx = gsm_bts_trx_num(vty_bts, trx_nr); + struct femtol1_hdl *fl1h = trx_femtol1_hdl(trx); + + l1if_rf_clock_info_correct(fl1h); + return CMD_SUCCESS; +} + DEFUN(loopback, loopback_cmd, "trx <0-0> <0-7> loopback <0-1>", TRX_STR @@ -576,6 +602,8 @@ int bts_model_vty_init(struct gsm_bts *bts) install_element(ENABLE_NODE, &activate_lchan_cmd); install_element(ENABLE_NODE, &set_tx_power_cmd); + install_element(ENABLE_NODE, &reset_rf_clock_ctr_cmd); + install_element(ENABLE_NODE, &correct_rf_clock_ctr_cmd); install_element(ENABLE_NODE, &loopback_cmd); install_element(ENABLE_NODE, &no_loopback_cmd); |