aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <holger@moiji-mobile.com>2014-07-25 14:37:47 +0200
committerHolger Hans Peter Freyther <holger@moiji-mobile.com>2014-07-25 14:45:52 +0200
commitbc24955e91f050e904851f589400eac4c3443917 (patch)
tree72e4d09dc148c77d27342cd486bdb8fd3cd3fed0 /src
parentbac0ff7f6df5c8fb002f3588952922b43772e770 (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.c120
-rw-r--r--src/osmo-bts-sysmo/l1_if.h4
-rw-r--r--src/osmo-bts-sysmo/sysmobts_vty.c28
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);