diff options
author | Holger Hans Peter Freyther <holger@moiji-mobile.com> | 2014-07-25 14:37:47 +0200 |
---|---|---|
committer | Holger Hans Peter Freyther <holger@moiji-mobile.com> | 2014-07-25 14:45:52 +0200 |
commit | bc24955e91f050e904851f589400eac4c3443917 (patch) | |
tree | 72e4d09dc148c77d27342cd486bdb8fd3cd3fed0 /src | |
parent | bac0ff7f6df5c8fb002f3588952922b43772e770 (diff) |
sysmobts: Provide VTY routines to do clock calibrations
The sysmoBTS2050 does not have a OCXO and we should not rely
on the GPS module to always have a fix. Instead use the TCXO
by default and from time to time (and we know we have a fix
calibrate the TCXO). This can be done by:
trx 0 rf-clock-info reset
wait...
trx 0 rf-clock-info correct
write
The output is currently only written to the log as the VTY
connection might go away during the operation. The reset will
set the approriate reference clock and the correct will attempt
to determine and apply the correction. The write terminal will
make sure that next on start a known good value will be used.
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); |