using std::deque;
using std::div;
using std::div_t;
-using std::isnan;
+// Note that "using std::isnan;" is _not_ put here since that would break
+// compilation on some platforms. Use "std::isnan()" instead in checks below.
using std::max;
using std::make_pair;
using std::min;
using std::shared_ptr;
using std::vector;
+using pv::data::LogicSegment;
using pv::data::SignalBase;
using pv::util::SIPrefix;
shared_ptr<data::SignalBase> base) :
Signal(session, base),
scale_index_(4), // 20 per div
- scale_index_drag_offset_(0),
pos_vdivs_(1),
neg_vdivs_(1),
resolution_(0),
display_type_(DisplayBoth),
- autoranging_(true)
+ autoranging_(true),
+ value_at_hover_pos_(std::numeric_limits<float>::quiet_NaN())
{
axis_pen_ = AxisPen;
update_scale();
}
-AnalogSignal::~AnalogSignal()
-{
- GlobalSettings::remove_change_handler(this);
-}
-
shared_ptr<pv::data::SignalData> AnalogSignal::data() const
{
return base_->analog_data();
return make_pair(-ph, nh);
}
-int AnalogSignal::scale_handle_offset() const
-{
- const int h = (pos_vdivs_ + neg_vdivs_) * div_height_;
-
- return ((scale_index_drag_offset_ - scale_index_) * h / 4) - h / 2;
-}
-
-void AnalogSignal::scale_handle_dragged(int offset)
-{
- const int h = (pos_vdivs_ + neg_vdivs_) * div_height_;
-
- scale_index_ = scale_index_drag_offset_ - (offset + h / 2) / (h / 4);
-
- update_scale();
-}
-
-void AnalogSignal::scale_handle_drag_release()
-{
- scale_index_drag_offset_ = scale_index_;
- update_scale();
-}
-
void AnalogSignal::on_setting_changed(const QString &key, const QVariant &value)
{
Signal::on_setting_changed(key, value);
// 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_ && !isnan(value_at_hover_pos_)) {
+ 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, 0, "V", false))
.arg(resolution_);
const int nh = min(neg_vdivs_, 1) * div_height_;
const float high_offset = y - ph + signal_margin + 0.5f;
const float low_offset = y + nh - signal_margin - 0.5f;
+ const float signal_height = low_offset - high_offset;
shared_ptr<pv::data::LogicSegment> segment = get_logic_segment_to_paint();
if (!segment || (segment->get_sample_count() == 0))
samples_per_pixel / LogicSignal::Oversampling, 0);
assert(edges.size() >= 2);
+ const float first_sample_x =
+ pp.left() + (edges.front().first / samples_per_pixel - pixels_offset);
+ const float last_sample_x =
+ pp.left() + (edges.back().first / samples_per_pixel - pixels_offset);
+
// Check whether we need to paint the sampling points
GlobalSettings settings;
const bool show_sampling_points =
(samples_per_pixel < 0.25);
vector<QRectF> sampling_points;
- float sampling_point_x = 0.0f;
+ float sampling_point_x = first_sample_x;
int64_t sampling_point_sample = start_sample;
const int w = 2;
- if (show_sampling_points) {
+ if (show_sampling_points)
sampling_points.reserve(end_sample - start_sample + 1);
- sampling_point_x = (edges.cbegin()->first / samples_per_pixel - pixels_offset) + pp.left();
- }
+
+ // Check whether we need to fill the high areas
+ const bool fill_high_areas =
+ settings.value(GlobalSettings::Key_View_FillSignalHighAreas).toBool();
+ float high_start_x;
+ vector<QRectF> high_rects;
// Paint the edges
const unsigned int edge_count = edges.size() - 2;
pixels_offset) + pp.left();
*line++ = QLineF(x, high_offset, x, low_offset);
+ if (fill_high_areas) {
+ if ((*i).second)
+ high_start_x = x;
+ else
+ high_rects.emplace_back(high_start_x, high_offset,
+ x - high_start_x, signal_height);
+ }
+
if (show_sampling_points)
while (sampling_point_sample < (*i).first) {
const float y = (*i).second ? low_offset : high_offset;
sampling_point_x += pixels_per_sample;
};
+ if (fill_high_areas) {
+ // Add last high rectangle if the signal is still high at the end of the view
+ if ((edges.cend() - 1)->second)
+ high_rects.emplace_back(high_start_x, high_offset,
+ last_sample_x - high_start_x, signal_height);
+
+ const QColor fill_color = QColor::fromRgba(settings.value(
+ GlobalSettings::Key_View_FillSignalHighAreaColor).value<uint32_t>());
+ p.setPen(fill_color);
+ p.setBrush(fill_color);
+ p.drawRects((const QRectF*)(high_rects.data()), high_rects.size());
+ }
+
p.setPen(LogicSignal::EdgeColor);
p.drawLines(edge_lines, edge_count);
delete[] edge_lines;
conv_threshold_cb_->blockSignals(false);
}
+vector<data::LogicSegment::EdgePair> AnalogSignal::get_nearest_level_changes(uint64_t sample_pos)
+{
+ assert(base_);
+ assert(owner_);
+
+ // Return if there's no logic data or we're showing only the analog trace
+ if (!base_->logic_data() || (display_type_ == DisplayAnalog))
+ return vector<data::LogicSegment::EdgePair>();
+
+ if (sample_pos == 0)
+ return vector<LogicSegment::EdgePair>();
+
+ shared_ptr<LogicSegment> segment = get_logic_segment_to_paint();
+ if (!segment || (segment->get_sample_count() == 0))
+ return vector<LogicSegment::EdgePair>();
+
+ const View *view = owner_->view();
+ assert(view);
+ const double samples_per_pixel = base_->get_samplerate() * view->scale();
+
+ vector<LogicSegment::EdgePair> edges;
+
+ segment->get_surrounding_edges(edges, sample_pos,
+ samples_per_pixel / LogicSignal::Oversampling, 0);
+
+ if (edges.empty())
+ return vector<LogicSegment::EdgePair>();
+
+ return edges;
+}
+
void AnalogSignal::perform_autoranging(bool keep_divs, bool force_update)
{
const deque< shared_ptr<pv::data::AnalogSegment> > &segments =
{
// Note: NAN is used to indicate the non-existance of a value at this pixel
- if (isnan(prev_value_at_pixel_)) {
+ if (std::isnan(prev_value_at_pixel_)) {
if (x < 0) {
min_value_at_pixel_ = value;
max_value_at_pixel_ = value;
if (pixel_pos > current_pixel_pos_) {
if (pixel_pos - current_pixel_pos_ == 1) {
- if (isnan(prev_value_at_pixel_)) {
+ if (std::isnan(prev_value_at_pixel_)) {
value_at_pixel_pos_.push_back(prev_value_at_pixel_);
} else {
// Average the min/max range to create one value for the previous pixel
connect(conv_threshold_cb_, SIGNAL(currentIndexChanged(int)),
this, SLOT(on_conv_threshold_changed(int)));
- connect(conv_threshold_cb_, SIGNAL(editTextChanged(const QString)),
+ connect(conv_threshold_cb_, SIGNAL(editTextChanged(const QString&)),
this, SLOT(on_conv_threshold_changed())); // index will be -1
// Add the display type dropdown
} else {
try {
value_at_hover_pos_ = value_at_pixel_pos_.at(hp.x());
- } catch (out_of_range) {
+ } catch (out_of_range&) {
value_at_hover_pos_ = std::numeric_limits<float>::quiet_NaN();
}
}