aboutsummaryrefslogtreecommitdiffstats
path: root/src/output
diff options
context:
space:
mode:
authorMatthias P. Braendli <matthias.braendli@mpb.li>2023-04-27 13:43:22 +0200
committerMatthias P. Braendli <matthias.braendli@mpb.li>2023-04-27 13:43:22 +0200
commitf0bb1e24952c7e261ba13907c0a5d8c3e1d198ca (patch)
tree08992867c48cc4daf8841275969d484497e34c1d /src/output
parent830fb3ab0a8631055b2341b8dac50b937b6e99bb (diff)
downloaddabmod-f0bb1e24952c7e261ba13907c0a5d8c3e1d198ca.tar.gz
dabmod-f0bb1e24952c7e261ba13907c0a5d8c3e1d198ca.tar.bz2
dabmod-f0bb1e24952c7e261ba13907c0a5d8c3e1d198ca.zip
Improve dexter clock handling
Diffstat (limited to 'src/output')
-rwxr-xr-xsrc/output/BladeRF.cpp2
-rwxr-xr-xsrc/output/BladeRF.h2
-rw-r--r--src/output/Dexter.cpp73
-rw-r--r--src/output/Dexter.h3
-rw-r--r--src/output/Lime.cpp2
-rw-r--r--src/output/Lime.h2
-rw-r--r--src/output/SDR.cpp29
-rw-r--r--src/output/SDR.h4
-rw-r--r--src/output/SDRDevice.h2
-rw-r--r--src/output/Soapy.cpp2
-rw-r--r--src/output/Soapy.h2
-rw-r--r--src/output/UHD.cpp2
-rw-r--r--src/output/UHD.h2
13 files changed, 64 insertions, 63 deletions
diff --git a/src/output/BladeRF.cpp b/src/output/BladeRF.cpp
index 2dd7176..c16b64d 100755
--- a/src/output/BladeRF.cpp
+++ b/src/output/BladeRF.cpp
@@ -273,7 +273,7 @@ size_t BladeRF::receive_frame(
return 0;
}
-bool BladeRF::is_clk_source_ok() const
+bool BladeRF::is_clk_source_ok()
{
// TODO
return true;
diff --git a/src/output/BladeRF.h b/src/output/BladeRF.h
index eb3e58b..fa3419e 100755
--- a/src/output/BladeRF.h
+++ b/src/output/BladeRF.h
@@ -87,7 +87,7 @@ class BladeRF : public Output::SDRDevice
double timeout_secs) override;
// Return true if GPS and reference clock inputs are ok
- virtual bool is_clk_source_ok(void) const override;
+ virtual bool is_clk_source_ok(void) override;
virtual const char* device_name(void) const override;
virtual std::optional<double> get_temperature(void) const override;
diff --git a/src/output/Dexter.cpp b/src/output/Dexter.cpp
index 59baf7e..25de030 100644
--- a/src/output/Dexter.cpp
+++ b/src/output/Dexter.cpp
@@ -277,7 +277,9 @@ void Dexter::handle_hw_time()
m_utc_seconds_at_startup = time_now.tv_sec;
m_clock_count_at_startup = pps_clks2;
m_holdover_since = chrono::steady_clock::time_point::min();
+ m_holdover_since_t = 0;
m_clock_state = DexterClockState::Normal;
+ etiLog.level(debug) << "Dexter: switch clock state Startup -> Normal";
}
}
break;
@@ -291,20 +293,31 @@ void Dexter::handle_hw_time()
if (pps_loss_of_signal == 1) {
m_holdover_since = chrono::steady_clock::now();
+ m_holdover_since_t = chrono::system_clock::to_time_t(chrono::system_clock::now());
m_clock_state = DexterClockState::Holdover;
+ etiLog.level(debug) << "Dexter: switch clock state Normal -> Holdover";
}
}
break;
case DexterClockState::Holdover:
{
using namespace chrono;
+
+ long long pps_loss_of_signal = 0;
+ if ((r = iio_device_attr_read_longlong(m_dexter_dsp_tx, "pps_loss_of_signal", &pps_loss_of_signal)) != 0) {
+ etiLog.level(error) << "Failed to get dexter_dsp_tx.pps_loss_of_signal: " << get_iio_error(r);
+ throw std::runtime_error("Dexter: Cannot read IIO attribute");
+ }
+
const duration<double> d = steady_clock::now() - m_holdover_since;
const auto max_holdover_duration = seconds(m_conf.maxGPSHoldoverTime);
- if (d > max_holdover_duration) {
+ if (d > max_holdover_duration or pps_loss_of_signal == 0) {
m_clock_state = DexterClockState::Startup;
m_utc_seconds_at_startup = 0;
m_clock_count_at_startup = 0;
m_holdover_since = chrono::steady_clock::time_point::min();
+ m_holdover_since_t = 0;
+ etiLog.level(debug) << "Dexter: switch clock state Holdover -> Startup";
}
}
break;
@@ -383,6 +396,21 @@ double Dexter::get_bandwidth(void) const
return 0;
}
+template <typename T>
+static void attr_to_stat(
+ Dexter::run_statistics_t& rs, iio_device *dexter_dsp_tx,
+ const char* attr_name, const char* stat_name) {
+ long long attr_value = 0;
+ int r = 0;
+ if ((r = iio_device_attr_read_longlong(dexter_dsp_tx, attr_name, &attr_value)) == 0) {
+ rs[stat_name] = (T)attr_value;
+ }
+ else {
+ rs[stat_name] = (ssize_t)-1;
+ etiLog.level(error) << "Failed to get dexter_dsp_tx." << attr_name << ": " << get_iio_error(r);
+ }
+};
+
SDRDevice::run_statistics_t Dexter::get_run_statistics(void) const
{
run_statistics_t rs;
@@ -393,24 +421,25 @@ SDRDevice::run_statistics_t Dexter::get_run_statistics(void) const
rs["latepackets"] = num_late;
rs["frames"] = num_frames_modulated;
- auto attr_to_stat = [&](const char* attr_name, const char* stat_name) {
- long long attr_value = 0;
- int r = 0;
- if ((r = iio_device_attr_read_longlong(m_dexter_dsp_tx, attr_name, &attr_value)) == 0) {
- rs[stat_name] = (size_t)attr_value;
- }
- else {
- rs[stat_name] = (ssize_t)-1;
- etiLog.level(error) << "Failed to get dexter_dsp_tx." << attr_name << ": " << get_iio_error(r);
- }
- };
+ attr_to_stat<size_t>(rs, m_dexter_dsp_tx, "clks", "clks");
+ attr_to_stat<size_t>(rs, m_dexter_dsp_tx, "stream0_fifo_not_empty_clks", "fifo_not_empty_clks");
+ attr_to_stat<size_t>(rs, m_dexter_dsp_tx, "gpsdo_locked", "gpsdo_locked");
+ attr_to_stat<ssize_t>(rs, m_dexter_dsp_tx, "pps_clk_error_hz", "pps_clk_error_hz");
+ attr_to_stat<size_t>(rs, m_dexter_dsp_tx, "pps_cnt", "pps_cnt");
+ attr_to_stat<size_t>(rs, m_dexter_dsp_tx, "pps_loss_of_signal", "pps_loss_of_signal");
+ attr_to_stat<size_t>(rs, m_dexter_dsp_tx, "dsp_version", "dsp_version");
- attr_to_stat("clks", "clks");
- attr_to_stat("stream0_fifo_not_empty_clks", "fifo_not_empty_clks");
- attr_to_stat("gpsdo_locked", "gpsdo_locked");
- attr_to_stat("pps_clk_error_hz", "pps_clk_error_hz");
- attr_to_stat("pps_cnt", "pps_cnt");
- attr_to_stat("dsp_version", "dsp_version");
+ rs["in_holdover_since"] = 0;
+ switch (m_clock_state) {
+ case DexterClockState::Startup:
+ rs["clock_state"] = "startup"; break;
+ case DexterClockState::Normal:
+ rs["clock_state"] = "normal"; break;
+ case DexterClockState::Holdover:
+ rs["clock_state"] = "holdover";
+ rs["in_holdover_since"] = m_holdover_since_t;
+ break;
+ }
constexpr double VMINFACT = 0.85;
constexpr double VMAXFACT = 1.15;
@@ -589,9 +618,11 @@ size_t Dexter::receive_frame(
}
-bool Dexter::is_clk_source_ok() const
+bool Dexter::is_clk_source_ok()
{
- return true;
+ handle_hw_time();
+
+ return m_clock_state != DexterClockState::Startup;
}
const char* Dexter::device_name(void) const
@@ -623,8 +654,6 @@ void Dexter::transmit_frame(struct FrameData&& frame)
const bool require_timestamped_tx = (m_conf.enableSync and frame.ts.timestamp_valid);
- handle_hw_time();
-
if (not m_channel_is_up) {
if (require_timestamped_tx) {
if (m_clock_state == DexterClockState::Startup) {
diff --git a/src/output/Dexter.h b/src/output/Dexter.h
index f70bb14..d4f425f 100644
--- a/src/output/Dexter.h
+++ b/src/output/Dexter.h
@@ -84,7 +84,7 @@ class Dexter : public Output::SDRDevice
double timeout_secs) override;
// Return true if GPS and reference clock inputs are ok
- virtual bool is_clk_source_ok() const override;
+ virtual bool is_clk_source_ok() override;
virtual const char* device_name() const override;
virtual std::optional<double> get_temperature() const override;
@@ -129,6 +129,7 @@ class Dexter : public Output::SDRDevice
// Only valid when m_clock_state Holdover
std::chrono::steady_clock::time_point m_holdover_since =
std::chrono::steady_clock::time_point::min();
+ std::time_t m_holdover_since_t = 0;
};
} // namespace Output
diff --git a/src/output/Lime.cpp b/src/output/Lime.cpp
index 83c54ad..8fb90bb 100644
--- a/src/output/Lime.cpp
+++ b/src/output/Lime.cpp
@@ -361,7 +361,7 @@ size_t Lime::receive_frame(
return 0;
}
-bool Lime::is_clk_source_ok() const
+bool Lime::is_clk_source_ok()
{
// TODO
return true;
diff --git a/src/output/Lime.h b/src/output/Lime.h
index e09e82d..4510bf2 100644
--- a/src/output/Lime.h
+++ b/src/output/Lime.h
@@ -79,7 +79,7 @@ class Lime : public Output::SDRDevice
double timeout_secs) override;
// Return true if GPS and reference clock inputs are ok
- virtual bool is_clk_source_ok(void) const override;
+ virtual bool is_clk_source_ok(void) override;
virtual const char *device_name(void) const override;
virtual std::optional<double> get_temperature(void) const override;
diff --git a/src/output/SDR.cpp b/src/output/SDR.cpp
index 860d8ed..11321f2 100644
--- a/src/output/SDR.cpp
+++ b/src/output/SDR.cpp
@@ -258,44 +258,19 @@ const char* SDR::name()
return m_name.c_str();
}
-void SDR::sleep_through_frame()
-{
- using namespace std::chrono;
-
- const auto now = steady_clock::now();
-
- if (not t_last_frame_initialised) {
- t_last_frame = now;
- t_last_frame_initialised = true;
- }
-
- const auto delta = now - t_last_frame;
- const auto wait_time = transmission_frame_duration(m_config.dabMode);
-
- if (wait_time > delta) {
- this_thread::sleep_for(wait_time - delta);
- }
-
- t_last_frame += wait_time;
-}
void SDR::handle_frame(struct FrameData&& frame)
{
// Assumes m_device is valid
if (not m_device->is_clk_source_ok()) {
- sleep_through_frame();
return;
}
const auto& time_spec = frame.ts;
- if (m_config.enableSync and m_config.muteNoTimestamps and
- not time_spec.timestamp_valid) {
- sleep_through_frame();
- etiLog.log(info,
- "OutputSDR: Muting sample %d : no timestamp\n",
- frame.ts.fct);
+ if (m_config.enableSync and m_config.muteNoTimestamps and not time_spec.timestamp_valid) {
+ etiLog.log(info, "OutputSDR: Muting sample %d : no timestamp\n", frame.ts.fct);
return;
}
diff --git a/src/output/SDR.h b/src/output/SDR.h
index 9f08348..94c972b 100644
--- a/src/output/SDR.h
+++ b/src/output/SDR.h
@@ -72,7 +72,6 @@ class SDR : public ModOutput, public ModMetadata, public RemoteControllable {
private:
void process_thread_entry(void);
void handle_frame(struct FrameData&& frame);
- void sleep_through_frame(void);
SDRDeviceConfig& m_config;
@@ -91,9 +90,6 @@ class SDR : public ModOutput, public ModMetadata, public RemoteControllable {
uint32_t last_tx_second = 0;
uint32_t last_tx_pps = 0;
size_t num_queue_overflows = 0;
-
- bool t_last_frame_initialised = false;
- std::chrono::steady_clock::time_point t_last_frame;
};
}
diff --git a/src/output/SDRDevice.h b/src/output/SDRDevice.h
index 628372a..26272be 100644
--- a/src/output/SDRDevice.h
+++ b/src/output/SDRDevice.h
@@ -135,7 +135,7 @@ class SDRDevice {
virtual std::optional<double> get_temperature(void) const = 0;
// Return true if GPS and reference clock inputs are ok
- virtual bool is_clk_source_ok(void) const = 0;
+ virtual bool is_clk_source_ok(void) = 0;
virtual const char* device_name(void) const = 0;
diff --git a/src/output/Soapy.cpp b/src/output/Soapy.cpp
index 00df9dc..4d33e39 100644
--- a/src/output/Soapy.cpp
+++ b/src/output/Soapy.cpp
@@ -254,7 +254,7 @@ size_t Soapy::receive_frame(
}
-bool Soapy::is_clk_source_ok() const
+bool Soapy::is_clk_source_ok()
{
// TODO
return true;
diff --git a/src/output/Soapy.h b/src/output/Soapy.h
index b98ac21..4fce11a 100644
--- a/src/output/Soapy.h
+++ b/src/output/Soapy.h
@@ -78,7 +78,7 @@ class Soapy : public Output::SDRDevice
double timeout_secs) override;
// Return true if GPS and reference clock inputs are ok
- virtual bool is_clk_source_ok(void) const override;
+ virtual bool is_clk_source_ok(void) override;
virtual const char* device_name(void) const override;
virtual std::optional<double> get_temperature(void) const override;
diff --git a/src/output/UHD.cpp b/src/output/UHD.cpp
index 7f07ff2..6638b6c 100644
--- a/src/output/UHD.cpp
+++ b/src/output/UHD.cpp
@@ -439,7 +439,7 @@ size_t UHD::receive_frame(
}
// Return true if GPS and reference clock inputs are ok
-bool UHD::is_clk_source_ok(void) const
+bool UHD::is_clk_source_ok(void)
{
bool ok = true;
diff --git a/src/output/UHD.h b/src/output/UHD.h
index 97a821e..9891c7a 100644
--- a/src/output/UHD.h
+++ b/src/output/UHD.h
@@ -84,7 +84,7 @@ class UHD : public Output::SDRDevice
double timeout_secs) override;
// Return true if GPS and reference clock inputs are ok
- virtual bool is_clk_source_ok(void) const override;
+ virtual bool is_clk_source_ok(void) override;
virtual const char* device_name(void) const override;
virtual std::optional<double> get_temperature(void) const override;