Make the analog value voltage display more sane
authorSoeren Apel <soeren@apelpie.net>
Thu, 21 May 2020 21:13:01 +0000 (23:13 +0200)
committerSoeren Apel <soeren@apelpie.net>
Fri, 22 May 2020 13:21:29 +0000 (15:21 +0200)
We do this by choosing the prefix (kV, V, mV) based on the min/max value
of the signal, not the value at the cursor position.

That way, we won't have the situation where values are printed as e.g.
"400 mV" when the values are usually shown as "1.600 V".

pv/util.cpp
pv/util.hpp
pv/views/trace/analogsignal.cpp
pv/views/trace/analogsignal.hpp
pv/views/trace/logicsignal.hpp

index 9a9a5065a2e17180eb6cdebb71b4aefc07fb5833..897254e12160fa59e60c7766efbd5e84f1d5fff5 100644 (file)
@@ -110,25 +110,31 @@ static QTextStream& operator<<(QTextStream& stream, const Timestamp& t)
        return stream << QString::fromStdString(str);
 }
 
-QString format_time_si(const Timestamp& v, SIPrefix prefix,
-       unsigned int precision, QString unit, bool sign)
+SIPrefix determine_value_prefix(double v)
 {
-       if (prefix == SIPrefix::unspecified) {
-               // No prefix given, calculate it
-
-               if (v.is_zero()) {
-                       prefix = SIPrefix::none;
-               } else {
-                       int exp = exponent(SIPrefix::yotta);
-                       prefix = SIPrefix::yocto;
-                       while ((fabs(v) * pow(Timestamp(10), exp)) > 999 &&
-                                       prefix < SIPrefix::yotta) {
-                               prefix = successor(prefix);
-                               exp -= 3;
-                       }
+       SIPrefix prefix;
+
+       if (v == 0) {
+               prefix = SIPrefix::none;
+       } else {
+               int exp = exponent(SIPrefix::yotta);
+               prefix = SIPrefix::yocto;
+               while ((fabs(v) * pow(10, exp)) > 999 &&
+                               prefix < SIPrefix::yotta) {
+                       prefix = successor(prefix);
+                       exp -= 3;
                }
        }
 
+       return prefix;
+}
+
+QString format_time_si(const Timestamp& v, SIPrefix prefix,
+       unsigned int precision, QString unit, bool sign)
+{
+       if (prefix == SIPrefix::unspecified)
+               prefix = determine_value_prefix(v.convert_to<double>());
+
        assert(prefix >= SIPrefix::yocto);
        assert(prefix <= SIPrefix::yotta);
 
@@ -148,19 +154,7 @@ QString format_value_si(double v, SIPrefix prefix, unsigned precision,
        QString unit, bool sign)
 {
        if (prefix == SIPrefix::unspecified) {
-               // No prefix given, calculate it
-
-               if (v == 0) {
-                       prefix = SIPrefix::none;
-               } else {
-                       int exp = exponent(SIPrefix::yotta);
-                       prefix = SIPrefix::yocto;
-                       while ((fabs(v) * pow(Timestamp(10), exp)) > 999 &&
-                                       prefix < SIPrefix::yotta) {
-                               prefix = successor(prefix);
-                               exp -= 3;
-                       }
-               }
+               prefix = determine_value_prefix(v);
 
                const int prefix_order = -exponent(prefix);
                precision = (prefix >= SIPrefix::none) ? max((int)(precision + prefix_order), 0) :
index 354013fe13e673ed3f82f4718505183c64b373b8..fab29a14f05ac21ea90b88d37088c2f9274a278f 100644 (file)
@@ -62,6 +62,11 @@ typedef boost::multiprecision::number<
        boost::multiprecision::cpp_dec_float<24>,
        boost::multiprecision::et_off> Timestamp;
 
+/**
+ * Chooses a prefix so that the value in front of the decimal point is between 1 and 999.
+ */
+SIPrefix determine_value_prefix(double v);
+
 /**
  * Formats a given timestamp with the specified SI prefix.
  *
index a0dd9eb239cded2d3e279cc01b78c8a1476b500a..5c52ec8aaf641a6bd5d532b16613a82b136e4f22 100644 (file)
@@ -65,6 +65,7 @@ using std::vector;
 using pv::data::LogicSegment;
 using pv::data::SignalBase;
 using pv::util::SIPrefix;
+using pv::util::determine_value_prefix;
 
 namespace pv {
 namespace views {
@@ -302,12 +303,18 @@ void AnalogSignal::paint_fore(QPainter &p, ViewItemPaintParams &pp)
 
                QString infotext;
 
+               SIPrefix prefix;
+               if (fabs(signal_max_) > fabs(signal_min_))
+                       prefix = determine_value_prefix(fabs(signal_max_));
+               else
+                       prefix = determine_value_prefix(fabs(signal_min_));
+
                // Show the info section on the right side of the trace, including
                // the value at the hover point when the hover marker is enabled
                // and we have corresponding data available
                if (show_hover_marker_ && !std::isnan(value_at_hover_pos_)) {
                        infotext = QString("[%1] %2 V/div")
-                               .arg(format_value_si(value_at_hover_pos_, SIPrefix::unspecified, 2, "V", false))
+                               .arg(format_value_si(value_at_hover_pos_, prefix, 3, "V", false))
                                .arg(resolution_);
                } else
                        infotext = QString("%1 V/div").arg(resolution_);
@@ -852,7 +859,6 @@ void AnalogSignal::perform_autoranging(bool keep_divs, bool force_update)
        if (segments.empty())
                return;
 
-       double signal_min_ = 0, signal_max_ = 0;
        double min = 0, max = 0;
 
        for (const shared_ptr<pv::data::AnalogSegment>& segment : segments) {
@@ -1126,11 +1132,12 @@ void AnalogSignal::on_setting_changed(const QString &key, const QVariant &value)
 
 void AnalogSignal::on_min_max_changed(float min, float max)
 {
-       (void)min;
-       (void)max;
-
        if (autoranging_)
                perform_autoranging(false, false);
+       else {
+               if (min < signal_min_) signal_min_ = min;
+               if (max > signal_max_) signal_max_ = max;
+       }
 }
 
 void AnalogSignal::on_pos_vdivs_changed(int vdivs)
index b15c44342737222f715ade4e9a33e3530c2d9e04..1dd9893f1b9812f78c0a8d7c442491d1252107f5 100644 (file)
@@ -197,7 +197,8 @@ private:
        int current_pixel_pos_;  // Only used during lookup table update
 
        // ---------------------------------------------------------------------------
-       // Note: Make sure to update .. when adding a trace-configurable variable here
+       // Note: Make sure to update save_settings() and restore_settings() when
+       //       adding a trace-configurable variable here
        float scale_;
        int scale_index_;
 
index 96e98b4b0e27cdb2105a1d6cdc94118376f92898..e066d40340ee97f65c0993fc74a9e73769a70126 100644 (file)
@@ -141,7 +141,6 @@ private Q_SLOTS:
        void on_signal_height_changed(int height);
 
 private:
-       int signal_height_;
        QColor high_fill_color_;
        bool show_sampling_points_, fill_high_areas_;
 
@@ -161,6 +160,11 @@ private:
 
        static QCache<QString, const QIcon> icon_cache_;
        static QCache<QString, const QPixmap> pixmap_cache_;
+
+       // ---------------------------------------------------------------------------
+       // Note: Make sure to update save_settings() and restore_settings() when
+       //       adding a trace-configurable variable here
+       int signal_height_;
 };
 
 } // namespace trace