diff options
-rw-r--r-- | src/output/Dexter.cpp | 172 | ||||
-rw-r--r-- | src/output/SDR.cpp | 35 | ||||
-rw-r--r-- | src/output/SDRDevice.h | 2 |
3 files changed, 186 insertions, 23 deletions
diff --git a/src/output/Dexter.cpp b/src/output/Dexter.cpp index dd882f2..515d810 100644 --- a/src/output/Dexter.cpp +++ b/src/output/Dexter.cpp @@ -344,30 +344,160 @@ SDRDevice::run_statistics_t Dexter::get_run_statistics(void) const std::unique_lock<std::mutex> lock(m_attr_thread_mutex); rs["underruns"] = underflows; } - rs["overruns"] = 0; - rs["late_packets"] = num_late; + rs["latepackets"] = num_late; rs["frames"] = num_frames_modulated; - long long clks = 0; - int r = 0; - if ((r = iio_device_attr_read_longlong(m_dexter_dsp_tx, "clks", &clks)) == 0) { - rs["clks"] = (size_t)clks; + 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("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"); + + constexpr double VMINFACT = 0.85; + constexpr double VMAXFACT = 1.15; + bool voltage_ok = true; + bool temp_ok = true; + + { + std::ifstream in("/sys/bus/i2c/devices/1-002f/hwmon/hwmon0/in2_input", std::ios::in | std::ios::binary); + if (in) { + double vcc3v3; + in >> vcc3v3; + rs["vcc3v3"] = vcc3v3 * (18+36)/36.0/1000.0; + voltage_ok = (vcc3v3 > VMINFACT * 3.3) and (vcc3v3 < VMAXFACT * 3.3); + } + else { + rs["vcc3v3"] = -1; + voltage_ok = false; + } } - else { - rs["clks"] = (ssize_t)-1; - etiLog.level(error) << "Failed to get dexter_dsp_tx.clks: " << get_iio_error(r); + { + std::ifstream in("/sys/bus/i2c/devices/1-002f/hwmon/hwmon0/in1_input", std::ios::in | std::ios::binary); + if (in) { + double vcc5v4; + in >> vcc5v4; + rs["vcc5v4"] = vcc5v4 * (51+36)/36.0/1000.0; + voltage_ok = (vcc5v4 > VMINFACT * 5.4) and (vcc5v4 < VMAXFACT * 5.4); + } + else { + rs["vcc5v4"] = -1; + voltage_ok = false; + } + } + { + std::ifstream in("/sys/bus/i2c/devices/1-002f/hwmon/hwmon0/in3_input", std::ios::in | std::ios::binary); + if (in) { + double vfan; + in >> vfan; + rs["vfan"] = vfan * (560+22)/22.0/1000.0; + } + else { + rs["vfan"] = -1; + voltage_ok = false; + } + } + { + std::ifstream in("/sys/bus/i2c/devices/1-002f/hwmon/hwmon0/in0_input", std::ios::in | std::ios::binary); + if (in) { + double vccmainin; + in >> vccmainin; + rs["vcc_main_in"] = vccmainin * (560+22)/22.0/1000.0; + voltage_ok |= vccmainin > 10.0; + } + else { + rs["vcc_main_in"] = -1; + voltage_ok = false; + } } + { + std::ifstream in("/sys/bus/i2c/devices/1-002f/hwmon/hwmon0/in4_input", std::ios::in | std::ios::binary); + if (in) { + double vcc3v3pll; + in >> vcc3v3pll; + rs["vcc3v3pll"] = vcc3v3pll * (18+36)/36.0/1000.0; + voltage_ok = (vcc3v3pll > VMINFACT * 3.3) and (vcc3v3pll < VMAXFACT * 3.3); + } + else { + rs["vcc3v3pll"] = -1; + voltage_ok = false; + } + } + { + std::ifstream in("/sys/bus/i2c/devices/1-002f/hwmon/hwmon0/in5_input", std::ios::in | std::ios::binary); + if (in) { + double vcc2v5io; + in >> vcc2v5io; + rs["vcc2v5io"] = vcc2v5io * (4.7+36)/36.0/1000.0; + voltage_ok = (vcc2v5io > VMINFACT * 2.5) and (vcc2v5io < VMAXFACT * 2.5); + } + else { + rs["vcc2v5io"] = -1; + voltage_ok = false; + } + } + { + std::ifstream in("/sys/bus/i2c/devices/1-002f/hwmon/hwmon0/in6_input", std::ios::in | std::ios::binary); + if (in) { + double vccocxo; + in >> vccocxo; + rs["vccocxo"] = vccocxo * (51+36)/36.0/1000.0; + } + else { + rs["vccocxo"] = -1; + voltage_ok = false; + } + } + + optional<double> tfpga; + for (int i = 0; i < 100; i++) { + std::string path = "/sys/bus/iio/devices/iio:device"; + path += to_string(i); - long long fifo_not_empty_clks = 0; + std::ifstream iio_name(path + "/name", std::ios::in | std::ios::binary); + std::ostringstream sstr; + sstr << iio_name.rdbuf(); + if (sstr.str() == "xadc\n") { + std::ifstream in_scale(path + "/in_temp0_scale", std::ios::in | std::ios::binary); + std::ifstream in_offset(path + "/in_temp0_offset", std::ios::in | std::ios::binary); + std::ifstream in_temp0_raw(path + "/in_temp0_raw", std::ios::in | std::ios::binary); - if ((r = iio_device_attr_read_longlong( - m_dexter_dsp_tx, "stream0_fifo_not_empty_clks", &fifo_not_empty_clks)) == 0) { - rs["fifo_not_empty_clks"] = (size_t)fifo_not_empty_clks; + if (in_scale and in_offset and in_temp0_raw) { + double scale, offset, temp0_raw ; + in_scale >> scale; + in_offset >> offset; + in_temp0_raw >> temp0_raw; + + tfpga = (temp0_raw + offset) * scale / 1000.0; + } + break; + } + } + + if (tfpga) { + rs["tempfpga"] = *tfpga; + temp_ok |= *tfpga <= 85; } else { - rs["fifo_not_empty_clks"] = (ssize_t)-1; - etiLog.level(error) << "Failed to get dexter_dsp_tx.fifo_not_empty_clks: " << get_iio_error(r); + rs["tempfpga"] = -1; + temp_ok = false; } + + rs["voltage_alarm"] = not voltage_ok; + rs["temp_alarm"] = not temp_ok; + return rs; } @@ -408,7 +538,6 @@ size_t Dexter::receive_frame( bool Dexter::is_clk_source_ok() const { - // TODO return true; } @@ -419,8 +548,15 @@ const char* Dexter::device_name(void) const std::optional<double> Dexter::get_temperature(void) const { - // TODO XADC contains temperature, but value is weird - return std::nullopt; + std::ifstream in("/sys/bus/i2c/devices/1-002f/hwmon/hwmon0/temp1_input", std::ios::in | std::ios::binary); + if (in) { + double tbaseboard; + in >> tbaseboard; + return tbaseboard / 1000.0; + } + else { + return {}; + } } void Dexter::transmit_frame(struct FrameData&& frame) diff --git a/src/output/SDR.cpp b/src/output/SDR.cpp index 99ced7d..cc080dc 100644 --- a/src/output/SDR.cpp +++ b/src/output/SDR.cpp @@ -25,7 +25,9 @@ */ #include "output/SDR.h" +#include "output/UHD.h" #include "output/Lime.h" +#include "output/Dexter.h" #include "PcDebug.h" #include "Log.h" @@ -82,8 +84,14 @@ SDR::SDR(SDRDeviceConfig& config, std::shared_ptr<SDRDevice> device) : RC_ADD_PARAMETER(underruns, "Counter of number of underruns"); RC_ADD_PARAMETER(latepackets, "Counter of number of late packets"); RC_ADD_PARAMETER(frames, "Counter of number of frames modulated"); - RC_ADD_PARAMETER(gpsdo_num_sv, "Number of Satellite Vehicles tracked by GPSDO"); - RC_ADD_PARAMETER(gpsdo_holdover, "1 if the GPSDO is in holdover, 0 if it is using gnss"); + +#ifdef HAVE_OUTPUT_UHD + if (std::dynamic_pointer_cast<UHD>(device)) { + RC_ADD_PARAMETER(gpsdo_num_sv, "Number of Satellite Vehicles tracked by GPSDO"); + RC_ADD_PARAMETER(gpsdo_holdover, "1 if the GPSDO is in holdover, 0 if it is using gnss"); + } +#endif // HAVE_OUTPUT_UHD + RC_ADD_PARAMETER(queued_frames_ms, "Number of frames queued, represented in milliseconds"); #ifdef HAVE_LIMESDR @@ -93,8 +101,24 @@ SDR::SDR(SDRDeviceConfig& config, std::shared_ptr<SDRDevice> device) : #endif // HAVE_LIMESDR #ifdef HAVE_DEXTER - RC_ADD_PARAMETER(clks, "DEXTER internal clk counter value"); - RC_ADD_PARAMETER(fifo_not_empty_clks, "DEXTER internal clk counter value when FIFO was last empty"); + if (std::dynamic_pointer_cast<Dexter>(device)) { + RC_ADD_PARAMETER(clks, "DEXTER internal clk counter value"); + RC_ADD_PARAMETER(fifo_not_empty_clks, "DEXTER internal clk counter value when FIFO was last empty"); + RC_ADD_PARAMETER(gpsdo_locked, "1 if GPSDO is locked"); + RC_ADD_PARAMETER(pps_clk_error_hz, "Estimated error in Hz of clock"); + RC_ADD_PARAMETER(pps_cnt, "Number of 1PPS pulses seen from GPS"); + RC_ADD_PARAMETER(dsp_version, "Version of FPGA DSP"); + RC_ADD_PARAMETER(vcc3v3, "Voltage of VCC 3V3"); + RC_ADD_PARAMETER(vcc5v4, "Voltage of VCC 5V4"); + RC_ADD_PARAMETER(vfan, "Fan voltage"); + RC_ADD_PARAMETER(vcc_main_in, "Main input voltage"); + RC_ADD_PARAMETER(vcc3v3pll, "Voltage of VCC 3V3 PLL"); + RC_ADD_PARAMETER(vcc2v5io, "Voltage of VCC 2V5 IO"); + RC_ADD_PARAMETER(vccocxo, "OCXO voltage"); + RC_ADD_PARAMETER(tempfpga, "FPGA temperature [celsius]"); + RC_ADD_PARAMETER(voltage_alarm, "Voltage out of bounds"); + RC_ADD_PARAMETER(temp_alarm, "Temperature out of bounds"); + } #endif // HAVE_DEXTER } @@ -455,6 +479,9 @@ const string SDR::get_parameter(const string& parameter) const if (std::holds_alternative<string>(value)) { ss << std::get<string>(value); } + else if (std::holds_alternative<double>(value)) { + ss << std::get<double>(value); + } else if (std::holds_alternative<ssize_t>(value)) { ss << std::get<ssize_t>(value); } diff --git a/src/output/SDRDevice.h b/src/output/SDRDevice.h index 337d501..a4f551c 100644 --- a/src/output/SDRDevice.h +++ b/src/output/SDRDevice.h @@ -112,7 +112,7 @@ struct FrameData { // All SDR Devices must implement the SDRDevice interface class SDRDevice { public: - using run_statistic_t = std::variant<std::string, size_t, ssize_t, bool>; + using run_statistic_t = std::variant<std::string, double, size_t, ssize_t, bool>; using run_statistics_t = std::unordered_map<std::string, run_statistic_t>; virtual void tune(double lo_offset, double frequency) = 0; |