dsosignal.cpp 51.8 KB
Newer Older
DreamSourceLab's avatar
DreamSourceLab committed
1
/*
DreamSourceLab's avatar
DreamSourceLab committed
2 3
 * This file is part of the DSView project.
 * DSView is based on PulseView.
DreamSourceLab's avatar
DreamSourceLab committed
4
 *
5
 * Copyright (C) 2013 DreamSourceLab <support@dreamsourcelab.com>
DreamSourceLab's avatar
DreamSourceLab committed
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
 */

#include <extdef.h>
#include <math.h>

DreamSourceLab's avatar
DreamSourceLab committed
25
#include "../../extdef.h"
DreamSourceLab's avatar
DreamSourceLab committed
26 27 28
#include "dsosignal.h"
#include "pv/data/dso.h"
#include "pv/data/dsosnapshot.h"
DreamSourceLab's avatar
DreamSourceLab committed
29 30 31 32
#include "view.h"
#include "../sigsession.h"
#include "../device/devinst.h"

DreamSourceLab's avatar
DreamSourceLab committed
33 34
#include <boost/foreach.hpp>

DreamSourceLab's avatar
DreamSourceLab committed
35
#include <QDebug>
36
#include <QTimer>
DreamSourceLab's avatar
DreamSourceLab committed
37 38 39 40 41 42 43

using namespace boost;
using namespace std;

namespace pv {
namespace view {

DreamSourceLab's avatar
DreamSourceLab committed
44
const QString DsoSignal::vDialUnit[DsoSignal::vDialUnitCount] = {
Andy Dneg's avatar
Andy Dneg committed
45 46
    "mV",
    "V",
DreamSourceLab's avatar
DreamSourceLab committed
47 48
};

DreamSourceLab's avatar
DreamSourceLab committed
49
const QColor DsoSignal::SignalColours[4] = {
50 51 52 53
    QColor(238, 178, 17, 255),  // dsYellow
    QColor(0, 153, 37, 255),    // dsGreen
    QColor(213, 15, 37, 255),   // dsRed
    QColor(17, 133, 209, 255)  // dsBlue
DreamSourceLab's avatar
v0.3  
DreamSourceLab committed
54

DreamSourceLab's avatar
DreamSourceLab committed
55 56 57
};

const float DsoSignal::EnvelopeThreshold = 256.0f;
DreamSourceLab's avatar
DreamSourceLab committed
58 59

DsoSignal::DsoSignal(boost::shared_ptr<pv::device::DevInst> dev_inst,
60
                     boost::shared_ptr<data::Dso> data,
61
                     sr_channel *probe):
DreamSourceLab's avatar
DreamSourceLab committed
62
    Signal(dev_inst, probe),
DreamSourceLab's avatar
DreamSourceLab committed
63 64
    _data(data),
    _scale(0),
65
    _en_lock(false),
Andy Dneg's avatar
Andy Dneg committed
66
    _show(true),
DreamSourceLab's avatar
DreamSourceLab committed
67
    _vDialActive(false),
Andy Dneg's avatar
Andy Dneg committed
68 69
    _mValid(false),
    _level_valid(false),
DreamSourceLab's avatar
DreamSourceLab committed
70
    _autoV(false),
71
    _autoH(false),
Andy Dneg's avatar
Andy Dneg committed
72 73
    _autoV_over(false),
    _auto_cnt(0),
74 75 76
    _hover_en(false),
    _hover_index(0),
    _hover_point(QPointF(0, 0)),
Andy Dneg's avatar
Andy Dneg committed
77
    _hover_value(0)
DreamSourceLab's avatar
DreamSourceLab committed
78
{
79
    QVector<uint64_t> vValue;
DreamSourceLab's avatar
DreamSourceLab committed
80
    QVector<QString> vUnit;
81
    for(uint64_t i = 0; i < vDialUnitCount; i++)
DreamSourceLab's avatar
DreamSourceLab committed
82 83
        vUnit.append(vDialUnit[i]);

84 85 86 87 88 89 90 91 92
    GVariant *gvar_list, *gvar_list_vdivs;
    if (sr_config_list(dev_inst->dev_inst()->driver, dev_inst->dev_inst(),
                       NULL, SR_CONF_PROBE_VDIV, &gvar_list) == SR_OK) {
        assert(gvar_list);
        if ((gvar_list_vdivs = g_variant_lookup_value(gvar_list,
                "vdivs", G_VARIANT_TYPE("at")))) {
            GVariant *gvar;
            GVariantIter iter;
            g_variant_iter_init(&iter, gvar_list_vdivs);
Andy Dneg's avatar
Andy Dneg committed
93
            while(NULL != (gvar = g_variant_iter_next_value(&iter))) {
94
                vValue.push_back(g_variant_get_uint64(gvar));
Andy Dneg's avatar
Andy Dneg committed
95 96
                g_variant_unref(gvar);
            }
97 98 99 100 101
            g_variant_unref(gvar_list_vdivs);
            g_variant_unref(gvar_list);
        }
    }
    _vDial = new dslDial(vValue.count(), vDialValueStep, vValue, vUnit);
DreamSourceLab's avatar
DreamSourceLab committed
102 103
    _colour = SignalColours[probe->index % countof(SignalColours)];

104
    load_settings();
DreamSourceLab's avatar
DreamSourceLab committed
105 106 107 108 109 110
}

DsoSignal::~DsoSignal()
{
}

111
boost::shared_ptr<pv::data::SignalData> DsoSignal::data() const
DreamSourceLab's avatar
DreamSourceLab committed
112
{
DreamSourceLab's avatar
DreamSourceLab committed
113
    return _data;
DreamSourceLab's avatar
DreamSourceLab committed
114 115
}

DreamSourceLab's avatar
DreamSourceLab committed
116
boost::shared_ptr<pv::data::Dso> DsoSignal::dso_data() const
DreamSourceLab's avatar
DreamSourceLab committed
117
{
DreamSourceLab's avatar
DreamSourceLab committed
118 119 120
    return _data;
}

Andy Dneg's avatar
Andy Dneg committed
121
void DsoSignal::set_scale(int height)
DreamSourceLab's avatar
DreamSourceLab committed
122
{
123
    _scale = height / (_ref_max - _ref_min) * _view->session().stop_scale();
Andy Dneg's avatar
Andy Dneg committed
124
}
125

Andy Dneg's avatar
Andy Dneg committed
126 127 128 129
float DsoSignal::get_scale()
{
    return _scale;
}
130

Andy Dneg's avatar
Andy Dneg committed
131 132 133
uint8_t DsoSignal::get_bits()
{
    return _bits;
DreamSourceLab's avatar
DreamSourceLab committed
134 135
}

Andy Dneg's avatar
Andy Dneg committed
136
double DsoSignal::get_ref_min() const
DreamSourceLab's avatar
DreamSourceLab committed
137
{
Andy Dneg's avatar
Andy Dneg committed
138
    return _ref_min;
DreamSourceLab's avatar
DreamSourceLab committed
139 140
}

Andy Dneg's avatar
Andy Dneg committed
141
double DsoSignal::get_ref_max() const
142
{
Andy Dneg's avatar
Andy Dneg committed
143
    return _ref_max;
144 145
}

146 147 148 149 150
int DsoSignal::get_name_width() const
{
    return 0;
}

DreamSourceLab's avatar
DreamSourceLab committed
151
void DsoSignal::set_enable(bool enable)
DreamSourceLab's avatar
DreamSourceLab committed
152
{
153
    if (_dev_inst->name() == "DSLogic" &&
DreamSourceLab's avatar
DreamSourceLab committed
154 155 156
         get_index() == 0)
        return;

157
    _en_lock = true;
DreamSourceLab's avatar
DreamSourceLab committed
158
    GVariant* gvar;
159
    bool cur_enable;
160
    gvar = _dev_inst->get_config(_probe, NULL, SR_CONF_PROBE_EN);
DreamSourceLab's avatar
DreamSourceLab committed
161
    if (gvar != NULL) {
162
        cur_enable = g_variant_get_boolean(gvar);
DreamSourceLab's avatar
DreamSourceLab committed
163 164
        g_variant_unref(gvar);
    } else {
165 166
        qDebug() << "ERROR: config_get SR_CONF_PROBE_EN failed.";
        _en_lock = false;
DreamSourceLab's avatar
DreamSourceLab committed
167 168
        return;
    }
169 170
    if (cur_enable == enable) {
        _en_lock = false;
DreamSourceLab's avatar
DreamSourceLab committed
171
        return;
172
    }
173 174 175 176 177

    bool running =  false;
    if (_view->session().get_capture_state() == SigSession::Running) {
        running = true;
        _view->session().stop_capture();
DreamSourceLab's avatar
DreamSourceLab committed
178
    }
179 180
    while(_view->session().get_capture_state() == SigSession::Running)
        QCoreApplication::processEvents();
DreamSourceLab's avatar
DreamSourceLab committed
181

182
    set_vDialActive(false);
183
    _dev_inst->set_config(_probe, NULL, SR_CONF_PROBE_EN,
184
                          g_variant_new_boolean(enable));
DreamSourceLab's avatar
DreamSourceLab committed
185

186
    _view->update_hori_res();
187 188 189
    if (running) {
        _view->session().repeat_resume();
    }
190

191 192
    _view->set_update(_viewport, true);
    _view->update();
193
    _en_lock = false;
DreamSourceLab's avatar
DreamSourceLab committed
194
}
DreamSourceLab's avatar
DreamSourceLab committed
195

DreamSourceLab's avatar
DreamSourceLab committed
196 197 198 199
bool DsoSignal::get_vDialActive() const
{
    return _vDialActive;
}
DreamSourceLab's avatar
DreamSourceLab committed
200

DreamSourceLab's avatar
DreamSourceLab committed
201 202 203 204 205 206
void DsoSignal::set_vDialActive(bool active)
{
    if (enabled())
        _vDialActive = active;
}

Andy Dneg's avatar
Andy Dneg committed
207
bool DsoSignal::go_vDialPre(bool manul)
DreamSourceLab's avatar
DreamSourceLab committed
208
{
Andy Dneg's avatar
Andy Dneg committed
209 210 211
    if (_autoV && manul)
        autoV_end();

DreamSourceLab's avatar
DreamSourceLab committed
212
    if (enabled() && !_vDial->isMin()) {
213 214
        if (_view->session().get_capture_state() == SigSession::Running)
            _view->session().refresh(RefreshShort);
215
        const double pre_vdiv = _vDial->get_value();
DreamSourceLab's avatar
DreamSourceLab committed
216
        _vDial->set_sel(_vDial->get_sel() - 1);
217
        _dev_inst->set_config(_probe, NULL, SR_CONF_PROBE_VDIV,
DreamSourceLab's avatar
DreamSourceLab committed
218
                              g_variant_new_uint64(_vDial->get_value()));
219
        if (_view->session().get_capture_state() == SigSession::Stopped) {
220
            _view->session().set_stop_scale(_view->session().stop_scale() * (pre_vdiv/_vDial->get_value()));
221 222
            set_scale(get_view_rect().height());
        }
Andy Dneg's avatar
Andy Dneg committed
223 224 225 226
        _dev_inst->set_config(_probe, NULL, SR_CONF_PROBE_OFFSET,
                              g_variant_new_uint16(_zero_offset));

        _view->vDial_updated();
227 228
        _view->set_update(_viewport, true);
        _view->update();
DreamSourceLab's avatar
DreamSourceLab committed
229 230
        return true;
    } else {
Andy Dneg's avatar
Andy Dneg committed
231
        if (_autoV && !_autoV_over)
232
            autoV_end();
DreamSourceLab's avatar
DreamSourceLab committed
233 234 235 236
        return false;
    }
}

Andy Dneg's avatar
Andy Dneg committed
237
bool DsoSignal::go_vDialNext(bool manul)
DreamSourceLab's avatar
DreamSourceLab committed
238
{
Andy Dneg's avatar
Andy Dneg committed
239 240 241
    if (_autoV && manul)
        autoV_end();

DreamSourceLab's avatar
DreamSourceLab committed
242
    if (enabled() && !_vDial->isMax()) {
243 244
        if (_view->session().get_capture_state() == SigSession::Running)
            _view->session().refresh(RefreshShort);
245
        const double pre_vdiv = _vDial->get_value();
DreamSourceLab's avatar
DreamSourceLab committed
246
        _vDial->set_sel(_vDial->get_sel() + 1);
247
        _dev_inst->set_config(_probe, NULL, SR_CONF_PROBE_VDIV,
DreamSourceLab's avatar
DreamSourceLab committed
248
                              g_variant_new_uint64(_vDial->get_value()));
249
        if (_view->session().get_capture_state() == SigSession::Stopped) {
250
            _view->session().set_stop_scale(_view->session().stop_scale() * (pre_vdiv/_vDial->get_value()));
251 252
            set_scale(get_view_rect().height());
        }
Andy Dneg's avatar
Andy Dneg committed
253 254 255 256
        _dev_inst->set_config(_probe, NULL, SR_CONF_PROBE_OFFSET,
                              g_variant_new_uint16(_zero_offset));

        _view->vDial_updated();
257 258
        _view->set_update(_viewport, true);
        _view->update();
DreamSourceLab's avatar
DreamSourceLab committed
259 260
        return true;
    } else {
Andy Dneg's avatar
Andy Dneg committed
261
        if (_autoV && !_autoV_over)
262
            autoV_end();
DreamSourceLab's avatar
DreamSourceLab committed
263 264 265 266
        return false;
    }
}

267
bool DsoSignal::load_settings()
268
{
269 270 271
    GVariant* gvar;

    // -- enable
DreamSourceLab's avatar
DreamSourceLab committed
272
//    bool enable;
273
//    gvar = _dev_inst->get_config(_probe, NULL, SR_CONF_PROBE_EN);
DreamSourceLab's avatar
DreamSourceLab committed
274 275 276 277
//    if (gvar != NULL) {
//        enable = g_variant_get_boolean(gvar);
//        g_variant_unref(gvar);
//    } else {
278
//        qDebug() << "ERROR: config_get SR_CONF_PROBE_EN failed.";
DreamSourceLab's avatar
DreamSourceLab committed
279 280
//        return false;
//    }
281 282

    // dso channel bits
283
    gvar = _dev_inst->get_config(NULL, NULL, SR_CONF_UNIT_BITS);
DreamSourceLab's avatar
DreamSourceLab committed
284 285 286 287 288
    if (gvar != NULL) {
        _bits = g_variant_get_byte(gvar);
        g_variant_unref(gvar);
    } else {
        _bits = DefaultBits;
289
        qDebug("Warning: config_get SR_CONF_UNIT_BITS failed, set to %d(default).", DefaultBits);
290 291
        if (strncmp(_dev_inst->name().toLocal8Bit(), "virtual", 7))
            return false;
DreamSourceLab's avatar
DreamSourceLab committed
292
    }
Andy Dneg's avatar
Andy Dneg committed
293 294 295 296 297 298 299 300 301 302 303 304 305 306
    gvar = _dev_inst->get_config(NULL, NULL, SR_CONF_REF_MIN);
    if (gvar != NULL) {
        _ref_min = g_variant_get_uint32(gvar);
        g_variant_unref(gvar);
    } else {
        _ref_min = 1;
    }
    gvar = _dev_inst->get_config(NULL, NULL, SR_CONF_REF_MAX);
    if (gvar != NULL) {
        _ref_max = g_variant_get_uint32(gvar);
        g_variant_unref(gvar);
    } else {
        _ref_max = ((1 << _bits) - 1);
    }
307 308

    // -- vdiv
309
    uint64_t vdiv;
DreamSourceLab's avatar
DreamSourceLab committed
310
    uint64_t vfactor;
311
    gvar = _dev_inst->get_config(_probe, NULL, SR_CONF_PROBE_VDIV);
312 313 314 315
    if (gvar != NULL) {
        vdiv = g_variant_get_uint64(gvar);
        g_variant_unref(gvar);
    } else {
316
        qDebug() << "ERROR: config_get SR_CONF_PROBE_VDIV failed.";
317 318
        return false;
    }
319
    gvar = _dev_inst->get_config(_probe, NULL, SR_CONF_PROBE_FACTOR);
DreamSourceLab's avatar
DreamSourceLab committed
320 321 322 323
    if (gvar != NULL) {
        vfactor = g_variant_get_uint64(gvar);
        g_variant_unref(gvar);
    } else {
324
        qDebug() << "ERROR: config_get SR_CONF_PROBE_FACTOR failed.";
DreamSourceLab's avatar
DreamSourceLab committed
325 326
        return false;
    }
327 328

    _vDial->set_value(vdiv);
DreamSourceLab's avatar
DreamSourceLab committed
329
    _vDial->set_factor(vfactor);
330
//    _dev_inst->set_config(_probe, NULL, SR_CONF_PROBE_VDIV,
331
//                          g_variant_new_uint64(_vDial->get_value()));
DreamSourceLab's avatar
DreamSourceLab committed
332

333
    // -- coupling
334
    gvar = _dev_inst->get_config(_probe, NULL, SR_CONF_PROBE_COUPLING);
335
    if (gvar != NULL) {
336
        _acCoupling = g_variant_get_byte(gvar);
337 338
        g_variant_unref(gvar);
    } else {
339
        qDebug() << "ERROR: config_get SR_CONF_PROBE_COUPLING failed.";
340 341 342
        return false;
    }

343
//    _dev_inst->set_config(_probe, NULL, SR_CONF_PROBE_COUPLING,
344
//                          g_variant_new_byte(_acCoupling));
345

346
    // -- vpos
Andy Dneg's avatar
Andy Dneg committed
347
    gvar = _dev_inst->get_config(_probe, NULL, SR_CONF_PROBE_OFFSET);
348
    if (gvar != NULL) {
Andy Dneg's avatar
Andy Dneg committed
349
        _zero_offset = g_variant_get_uint16(gvar);
350 351
        g_variant_unref(gvar);
    } else {
Andy Dneg's avatar
Andy Dneg committed
352
        qDebug() << "ERROR: config_get SR_CONF_PROBE_OFFSET failed.";
353 354 355
        return false;
    }

356 357 358
    // -- trig_value
    gvar = _dev_inst->get_config(_probe, NULL, SR_CONF_TRIGGER_VALUE);
    if (gvar != NULL) {
DreamSourceLab's avatar
DreamSourceLab committed
359
        _trig_value = g_variant_get_byte(gvar);
Andy Dneg's avatar
Andy Dneg committed
360
        _trig_delta = get_trig_vrate() - get_zero_ratio();
361 362 363
        g_variant_unref(gvar);
    } else {
        qDebug() << "ERROR: config_get SR_CONF_TRIGGER_VALUE failed.";
364 365
        if (strncmp(_dev_inst->name().toLocal8Bit(), "virtual", 7))
            return false;
366 367
    }

368
    if (_view) {
DreamSourceLab's avatar
DreamSourceLab committed
369
        _view->set_update(_viewport, true);
370 371 372 373 374
        _view->update();
    }
    return true;
}

375 376 377 378
int DsoSignal::commit_settings()
{
    int ret;
    // -- enable
379
    ret = _dev_inst->set_config(_probe, NULL, SR_CONF_PROBE_EN,
380 381 382
                                g_variant_new_boolean(enabled()));

    // -- vdiv
383
    ret = _dev_inst->set_config(_probe, NULL, SR_CONF_PROBE_VDIV,
384
                                g_variant_new_uint64(_vDial->get_value()));
385
    ret = _dev_inst->set_config(_probe, NULL, SR_CONF_PROBE_FACTOR,
386 387 388
                                g_variant_new_uint64(_vDial->get_factor()));

    // -- coupling
389
    ret = _dev_inst->set_config(_probe, NULL, SR_CONF_PROBE_COUPLING,
390 391
                                g_variant_new_byte(_acCoupling));

Andy Dneg's avatar
Andy Dneg committed
392 393 394
    // -- offset
    ret = _dev_inst->set_config(_probe, NULL, SR_CONF_PROBE_OFFSET,
                                g_variant_new_uint16(_zero_offset));
395

396 397 398 399
    // -- trig_value
    _dev_inst->set_config(_probe, NULL, SR_CONF_TRIGGER_VALUE,
                          g_variant_new_byte(_trig_value));

400 401 402
    return ret;
}

Andy Dneg's avatar
Andy Dneg committed
403 404 405 406 407
dslDial * DsoSignal::get_vDial() const
{
    return _vDial;
}

DreamSourceLab's avatar
DreamSourceLab committed
408 409 410 411 412 413 414 415 416 417
uint64_t DsoSignal::get_vDialValue() const
{
    return _vDial->get_value();
}

uint16_t DsoSignal::get_vDialSel() const
{
    return _vDial->get_sel();
}

DreamSourceLab's avatar
DreamSourceLab committed
418
uint8_t DsoSignal::get_acCoupling() const
DreamSourceLab's avatar
DreamSourceLab committed
419 420 421 422
{
    return _acCoupling;
}

DreamSourceLab's avatar
DreamSourceLab committed
423
void DsoSignal::set_acCoupling(uint8_t coupling)
DreamSourceLab's avatar
DreamSourceLab committed
424 425 426
{
    if (enabled()) {
        _acCoupling = coupling;
427
        _dev_inst->set_config(_probe, NULL, SR_CONF_PROBE_COUPLING,
DreamSourceLab's avatar
DreamSourceLab committed
428
                              g_variant_new_byte(_acCoupling));
DreamSourceLab's avatar
DreamSourceLab committed
429 430 431
    }
}

Andy Dneg's avatar
Andy Dneg committed
432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447
int DsoSignal::ratio2value(double ratio) const
{
    return ratio * (_ref_max - _ref_min) + _ref_min;
}

int DsoSignal::ratio2pos(double ratio) const
{
    return ratio * get_view_rect().height() + get_view_rect().top();
}

double DsoSignal::value2ratio(int value) const
{
    return max(0.0, (value - _ref_min) / (_ref_max - _ref_min));
}

double DsoSignal::pos2ratio(int pos) const
DreamSourceLab's avatar
DreamSourceLab committed
448
{
Andy Dneg's avatar
Andy Dneg committed
449
    return min(max(pos - get_view_rect().top(), 0), get_view_rect().height()) * 1.0 / get_view_rect().height();
DreamSourceLab's avatar
DreamSourceLab committed
450 451
}

DreamSourceLab's avatar
DreamSourceLab committed
452
double DsoSignal::get_trig_vrate() const
453
{
454
    if (_dev_inst->name() == "DSLogic")
Andy Dneg's avatar
Andy Dneg committed
455
        return value2ratio(_trig_value - ratio2value(0.5)) + get_zero_ratio();
456
    else
Andy Dneg's avatar
Andy Dneg committed
457
        return value2ratio(_trig_value);
458 459
}

DreamSourceLab's avatar
DreamSourceLab committed
460
void DsoSignal::set_trig_vpos(int pos, bool delta_change)
DreamSourceLab's avatar
DreamSourceLab committed
461 462 463
{
    assert(_view);
    if (enabled()) {
Andy Dneg's avatar
Andy Dneg committed
464
        set_trig_ratio(pos2ratio(pos), delta_change);
DreamSourceLab's avatar
DreamSourceLab committed
465 466 467
    }
}

Andy Dneg's avatar
Andy Dneg committed
468
void DsoSignal::set_trig_ratio(double ratio, bool delta_change)
469
{
Andy Dneg's avatar
Andy Dneg committed
470
    double delta = ratio;
DreamSourceLab's avatar
DreamSourceLab committed
471
    if (_dev_inst->name() == "DSLogic") {
Andy Dneg's avatar
Andy Dneg committed
472
        delta = delta - get_zero_ratio();
473 474
        delta = min(delta, 0.5);
        delta = max(delta, -0.5);
Andy Dneg's avatar
Andy Dneg committed
475
        _trig_value = ratio2value(delta + 0.5);
DreamSourceLab's avatar
DreamSourceLab committed
476
    } else {
Andy Dneg's avatar
Andy Dneg committed
477
        _trig_value = ratio2value(delta);
478
    }
Andy Dneg's avatar
Andy Dneg committed
479 480 481 482 483

    int margin = TrigMargin;
    _trig_value = std::min(std::max(_trig_value, margin), (ratio2value(1) - margin));
    if (delta_change)
        _trig_delta = get_trig_vrate() - get_zero_ratio();
484
    _dev_inst->set_config(_probe, NULL, SR_CONF_TRIGGER_VALUE,
DreamSourceLab's avatar
DreamSourceLab committed
485
                          g_variant_new_byte(_trig_value));
486 487
}

488
int DsoSignal::get_zero_vpos() const
DreamSourceLab's avatar
DreamSourceLab committed
489
{
Andy Dneg's avatar
Andy Dneg committed
490
    return ratio2pos(get_zero_ratio());
DreamSourceLab's avatar
DreamSourceLab committed
491 492
}

Andy Dneg's avatar
Andy Dneg committed
493
double DsoSignal::get_zero_ratio() const
494
{
Andy Dneg's avatar
Andy Dneg committed
495
    return value2ratio(_zero_offset);
496 497
}

Andy Dneg's avatar
Andy Dneg committed
498
int DsoSignal::get_hw_offset() const
DreamSourceLab's avatar
DreamSourceLab committed
499
{
Andy Dneg's avatar
Andy Dneg committed
500 501 502 503 504 505 506
    int hw_offset = 0;
    GVariant *gvar = _dev_inst->get_config(_probe, NULL, SR_CONF_PROBE_HW_OFFSET);
    if (gvar != NULL) {
        hw_offset = g_variant_get_uint16(gvar);
        g_variant_unref(gvar);
    }
    return hw_offset;
DreamSourceLab's avatar
DreamSourceLab committed
507 508
}

DreamSourceLab's avatar
DreamSourceLab committed
509
void DsoSignal::set_zero_vpos(int pos)
DreamSourceLab's avatar
DreamSourceLab committed
510 511
{
    if (enabled()) {
Andy Dneg's avatar
Andy Dneg committed
512 513
        set_zero_ratio(pos2ratio(pos));
        set_trig_ratio(_trig_delta + get_zero_ratio(), false);
DreamSourceLab's avatar
DreamSourceLab committed
514 515 516
    }
}

Andy Dneg's avatar
Andy Dneg committed
517
void DsoSignal::set_zero_ratio(double ratio)
518
{
Andy Dneg's avatar
Andy Dneg committed
519 520 521
    _zero_offset = ratio2value(ratio);
    _dev_inst->set_config(_probe, NULL, SR_CONF_PROBE_OFFSET,
                          g_variant_new_uint16(_zero_offset));
522 523
}

524 525 526 527 528
void DsoSignal::set_factor(uint64_t factor)
{
    if (enabled()) {
        GVariant* gvar;
        uint64_t prefactor = 0;
529
        gvar = _dev_inst->get_config(_probe, NULL, SR_CONF_PROBE_FACTOR);
530 531 532 533
        if (gvar != NULL) {
            prefactor = g_variant_get_uint64(gvar);
            g_variant_unref(gvar);
        } else {
534
            qDebug() << "ERROR: config_get SR_CONF_PROBE_FACTOR failed.";
535 536 537
            return;
        }
        if (prefactor != factor) {
538
            _dev_inst->set_config(_probe, NULL, SR_CONF_PROBE_FACTOR,
539 540
                                  g_variant_new_uint64(factor));
            _vDial->set_factor(factor);
DreamSourceLab's avatar
DreamSourceLab committed
541
            _view->set_update(_viewport, true);
542 543 544 545 546
            _view->update();
        }
    }
}

547 548 549 550
uint64_t DsoSignal::get_factor()
{
    GVariant* gvar;
    uint64_t factor;
551
    gvar = _dev_inst->get_config(_probe, NULL, SR_CONF_PROBE_FACTOR);
552 553 554 555 556
    if (gvar != NULL) {
        factor = g_variant_get_uint64(gvar);
        g_variant_unref(gvar);
        return factor;
    } else {
557
        qDebug() << "ERROR: config_get SR_CONF_PROBE_FACTOR failed.";
558 559 560 561
        return 1;
    }
}

Andy Dneg's avatar
Andy Dneg committed
562
void DsoSignal::set_show(bool show)
563
{
Andy Dneg's avatar
Andy Dneg committed
564
    _show = show;
565 566
}

Andy Dneg's avatar
Andy Dneg committed
567
bool DsoSignal::show() const
568
{
Andy Dneg's avatar
Andy Dneg committed
569
    return _show;
570 571
}

572 573 574 575 576
void DsoSignal::set_mValid(bool valid)
{
    _mValid = valid;
}

Andy Dneg's avatar
Andy Dneg committed
577
QString DsoSignal::get_measure(enum DSO_MEASURE_TYPE type)
578
{
Andy Dneg's avatar
Andy Dneg committed
579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690
    const QString mNone = "--";
    QString mString;
    if (_mValid) {
        const int hw_offset = get_hw_offset();
        switch(type) {
        case DSO_MS_AMPT:
            if (_level_valid)
                mString = get_voltage(_high - _low, 2);
            else
                mString = mNone;
            break;
        case DSO_MS_VHIG:
            if (_level_valid)
                mString = get_voltage(hw_offset - _low, 2);
            else
                mString = mNone;
            break;
        case DSO_MS_VLOW:
            if (_level_valid)
                mString = get_voltage(hw_offset - _high, 2);
            else
                mString = mNone;
            break;
        case DSO_MS_VP2P:
            mString = get_voltage(_max - _min, 2);
            break;
        case DSO_MS_VMAX:
            mString = get_voltage(hw_offset - _min, 2);
            break;
        case DSO_MS_VMIN:
            mString = get_voltage(hw_offset - _max, 2);
            break;
        case DSO_MS_PERD:
            mString = get_time(_period);
            break;
        case DSO_MS_FREQ:
            mString = (abs(_period) > 1000000 ? QString::number(1000000000/_period, 'f', 2) + "Hz" :
                       abs(_period) > 1000 ? QString::number(1000000/_period, 'f', 2) + "kHz" : QString::number(1000/_period, 'f', 2) + "MHz");
            break;
        case DSO_MS_VRMS:
            mString = get_voltage(_rms, 2);
            break;
        case DSO_MS_VMEA:
            mString = get_voltage(_mean, 2);
            break;
        case DSO_MS_NOVR:
            if (_level_valid)
                mString = QString::number((_max - _high) * 100.0 / (_high - _low), 'f', 2) + "%";
            else
                mString = mNone;
            break;
        case DSO_MS_POVR:
            if (_level_valid)
                mString = QString::number((_low - _min) * 100.0 / (_high - _low), 'f', 2) + "%";
            else
                mString = mNone;
            break;
        case DSO_MS_PDUT:
            if (_level_valid)
                mString = QString::number(_high_time/_period*100, 'f', 2)+"%";
            else
                mString = mNone;
            break;
        case DSO_MS_NDUT:
            if (_level_valid)
                mString = QString::number(100 - _high_time/_period*100, 'f', 2)+"%";
            else
                mString = mNone;
            break;
        case DSO_MS_PWDT:
            if (_level_valid)
                mString = get_time(_high_time);
            else
                mString = mNone;
            break;
        case DSO_MS_NWDT:
            if (_level_valid)
                mString = get_time(_period - _high_time);
            else
                mString = mNone;
            break;
        case DSO_MS_RISE:
            if (_level_valid)
                mString = get_time(_rise_time);
            else
                mString = mNone;
            break;
        case DSO_MS_FALL:
            if (_level_valid)
                mString = get_time(_fall_time);
            else
                mString = mNone;
            break;
        case DSO_MS_BRST:
            if (_level_valid)
                mString = get_time(_burst_time);
            else
                mString = mNone;
            break;
        case DSO_MS_PCNT:
            if (_level_valid)
                mString = (_pcount > 1000000 ? QString::number(_pcount/1000000, 'f', 6) + "M" :
                           _pcount > 1000 ? QString::number(_pcount/1000, 'f', 3) + "K" : QString::number(_pcount, 'f', 0));
            else
                mString = mNone;
            break;
        default:
            mString = "Error";
            break;
        }
    } else {
        mString = mNone;
691
    }
Andy Dneg's avatar
Andy Dneg committed
692
    return mString;
DreamSourceLab's avatar
DreamSourceLab committed
693 694
}

DreamSourceLab's avatar
DreamSourceLab committed
695
QRect DsoSignal::get_view_rect() const
DreamSourceLab's avatar
DreamSourceLab committed
696
{
DreamSourceLab's avatar
DreamSourceLab committed
697
    assert(_viewport);
DreamSourceLab's avatar
DreamSourceLab committed
698
    return QRect(0, UpMargin,
DreamSourceLab's avatar
DreamSourceLab committed
699 700
                  _viewport->width() - RightMargin,
                  _viewport->height() - UpMargin - DownMargin);
DreamSourceLab's avatar
DreamSourceLab committed
701 702
}

703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754
void DsoSignal::paint_prepare()
{
    assert(_view);

    const deque< boost::shared_ptr<pv::data::DsoSnapshot> > &snapshots =
        _data->get_snapshots();
    if (snapshots.empty())
        return;
    const boost::shared_ptr<pv::data::DsoSnapshot> &snapshot =
        snapshots.front();
    if (snapshot->empty())
        return;

    if (!snapshot->has_data(get_index()))
        return;

    const uint16_t enabled_channels = snapshot->get_channel_num();
    if (_view->session().trigd()) {
        if (get_index() == _view->session().trigd_ch()) {
            uint8_t slope = DSO_TRIGGER_RISING;
            GVariant *gvar = _view->session().get_device()->get_config(NULL, NULL, SR_CONF_TRIGGER_SLOPE);
            if (gvar != NULL) {
                slope = g_variant_get_byte(gvar);
                g_variant_unref(gvar);
            }

            int64_t trig_index = _view->get_trig_cursor()->index();
            if (trig_index >= (int64_t)snapshot->get_sample_count())
                return;
            const uint8_t *const trig_samples = snapshot->get_samples(0, 0, get_index());
            for (uint16_t i = 0; i < TrigHRng; i++) {
                const int64_t i0 = (trig_index - i - 1)*enabled_channels;
                const int64_t i1 = (trig_index - i)*enabled_channels;
                if (i1 < 0)
                    break;
                const uint8_t t0 = trig_samples[i0];
                const uint8_t t1 = trig_samples[i1];
                if((slope == DSO_TRIGGER_RISING && t0 >= _trig_value && t1 <= _trig_value) ||
                   (slope == DSO_TRIGGER_FALLING && t0 <= _trig_value && t1 >= _trig_value)) {
                    const double xoff = (t1 == t0) ? 0 : (_trig_value - t0) * 1.0 / (t1 - t0);
                    _view->set_trig_hoff(i + 1 - xoff);
                    break;
                }
            }
        }
        //if (_view->trig_hoff() == 0 && trig_samples[3] != _trig_value)
        //    _view->set_trig_hoff(0);
    } else {
        _view->set_trig_hoff(0);
    }
}

Andy Dneg's avatar
Andy Dneg committed
755
void DsoSignal::paint_back(QPainter &p, int left, int right, QColor fore, QColor back)
DreamSourceLab's avatar
DreamSourceLab committed
756 757 758
{
    assert(_view);

Andy Dneg's avatar
Andy Dneg committed
759 760 761
    if (!_show)
        return;

DreamSourceLab's avatar
DreamSourceLab committed
762
    int i, j;
763
    const int height = get_view_rect().height();
DreamSourceLab's avatar
DreamSourceLab committed
764
    const int width = right - left;
DreamSourceLab's avatar
DreamSourceLab committed
765

Andy Dneg's avatar
Andy Dneg committed
766 767 768
    fore.setAlpha(View::BackAlpha);

    QPen solidPen(fore);
DreamSourceLab's avatar
DreamSourceLab committed
769 770
    solidPen.setStyle(Qt::SolidLine);
    p.setPen(solidPen);
Andy Dneg's avatar
Andy Dneg committed
771
    p.setBrush(back.black() > 0x80 ? back.darker() : back.lighter());
DreamSourceLab's avatar
DreamSourceLab committed
772 773
    p.drawRect(left, UpMargin, width, height);

Andy Dneg's avatar
Andy Dneg committed
774 775 776
    // draw zoom region
    fore.setAlpha(View::ForeAlpha);
    p.setPen(fore);
777
    const uint64_t sample_len = _view->session().cur_samplelimits();
778
    const double samplerate = _view->session().cur_snap_samplerate();
DreamSourceLab's avatar
DreamSourceLab committed
779
    const double samples_per_pixel = samplerate * _view->scale();
780
    const double shown_rate = min(samples_per_pixel * width * 1.0 / sample_len, 1.0);
781
    const double start = _view->offset() * samples_per_pixel;
DreamSourceLab's avatar
DreamSourceLab committed
782
    const double shown_offset = min(start / sample_len, 1.0) * width;
Andy Dneg's avatar
Andy Dneg committed
783
    const double shown_len = max(shown_rate * width, 6.0);
DreamSourceLab's avatar
DreamSourceLab committed
784 785 786 787 788 789 790 791
    const QPointF left_edge[] =  {QPoint(shown_offset + 3, UpMargin/2 - 6),
                                  QPoint(shown_offset, UpMargin/2 - 6),
                                  QPoint(shown_offset, UpMargin/2 + 6),
                                  QPoint(shown_offset + 3, UpMargin/2 + 6)};
    const QPointF right_edge[] = {QPoint(shown_offset + shown_len - 3, UpMargin/2 - 6),
                                  QPoint(shown_offset + shown_len , UpMargin/2 - 6),
                                  QPoint(shown_offset + shown_len , UpMargin/2 + 6),
                                  QPoint(shown_offset + shown_len - 3, UpMargin/2 + 6)};
Andy Dneg's avatar
Andy Dneg committed
792 793
    p.drawLine(left, UpMargin/2, shown_offset, UpMargin/2);
    p.drawLine(shown_offset + shown_len, UpMargin/2, left + width, UpMargin/2);
DreamSourceLab's avatar
DreamSourceLab committed
794 795
    p.drawPolyline(left_edge, countof(left_edge));
    p.drawPolyline(right_edge, countof(right_edge));
Andy Dneg's avatar
Andy Dneg committed
796
    p.setBrush(fore);
DreamSourceLab's avatar
DreamSourceLab committed
797 798
    p.drawRect(shown_offset, UpMargin/2 - 3, shown_len, 6);

Andy Dneg's avatar
Andy Dneg committed
799 800 801
    // draw divider
    fore.setAlpha(View::BackAlpha);
    QPen dashPen(fore);
DreamSourceLab's avatar
DreamSourceLab committed
802 803
    dashPen.setStyle(Qt::DashLine);
    p.setPen(dashPen);
804
    const double spanY =height * 1.0 / DS_CONF_DSO_VDIVS;
DreamSourceLab's avatar
DreamSourceLab committed
805 806
    for (i = 1; i <= DS_CONF_DSO_VDIVS; i++) {
        const double posY = spanY * i + UpMargin;
DreamSourceLab's avatar
DreamSourceLab committed
807 808
        if (i != DS_CONF_DSO_VDIVS)
            p.drawLine(left, posY, right, posY);
DreamSourceLab's avatar
DreamSourceLab committed
809 810
        const double miniSpanY = spanY / 5;
        for (j = 1; j < 5; j++) {
DreamSourceLab's avatar
DreamSourceLab committed
811 812
            p.drawLine(width / 2.0f - 5, posY - miniSpanY * j,
                       width / 2.0f + 5, posY - miniSpanY * j);
DreamSourceLab's avatar
DreamSourceLab committed
813 814
        }
    }
815
    const double spanX = width * 1.0 / DS_CONF_DSO_HDIVS;
DreamSourceLab's avatar
DreamSourceLab committed
816 817
    for (i = 1; i <= DS_CONF_DSO_HDIVS; i++) {
        const double posX = spanX * i;
DreamSourceLab's avatar
DreamSourceLab committed
818 819
        if (i != DS_CONF_DSO_HDIVS)
            p.drawLine(posX, UpMargin,posX, height + UpMargin);
DreamSourceLab's avatar
DreamSourceLab committed
820 821
        const double miniSpanX = spanX / 5;
        for (j = 1; j < 5; j++) {
DreamSourceLab's avatar
DreamSourceLab committed
822 823
            p.drawLine(posX - miniSpanX * j, height / 2.0f + UpMargin - 5,
                       posX - miniSpanX * j, height / 2.0f + UpMargin + 5);
DreamSourceLab's avatar
DreamSourceLab committed
824 825
        }
    }
Andy Dneg's avatar
Andy Dneg committed
826
    _view->set_back(true);
DreamSourceLab's avatar
DreamSourceLab committed
827 828
}

Andy Dneg's avatar
Andy Dneg committed
829
void DsoSignal::paint_mid(QPainter &p, int left, int right, QColor fore, QColor back)
DreamSourceLab's avatar
DreamSourceLab committed
830
{
Andy Dneg's avatar
Andy Dneg committed
831 832 833 834 835 836
    (void)fore;
    (void)back;

    if (!_show)
        return;

DreamSourceLab's avatar
DreamSourceLab committed
837 838 839 840 841
    assert(_data);
    assert(_view);
    assert(right >= left);

    if (enabled()) {
Andy Dneg's avatar
Andy Dneg committed
842
        const int index = get_index();
DreamSourceLab's avatar
DreamSourceLab committed
843
        const int width = right - left;
Andy Dneg's avatar
Andy Dneg committed
844
        const float zeroY = get_zero_vpos();
DreamSourceLab's avatar
DreamSourceLab committed
845 846 847

        const double scale = _view->scale();
        assert(scale > 0);
848
        const int64_t offset = _view->offset();
DreamSourceLab's avatar
DreamSourceLab committed
849 850 851 852 853

        const deque< boost::shared_ptr<pv::data::DsoSnapshot> > &snapshots =
            _data->get_snapshots();
        if (snapshots.empty())
            return;
854
        const boost::shared_ptr<pv::data::DsoSnapshot> &snapshot =
DreamSourceLab's avatar
DreamSourceLab committed
855
            snapshots.front();
856 857
        if (snapshot->empty())
            return;
DreamSourceLab's avatar
DreamSourceLab committed
858

Andy Dneg's avatar
Andy Dneg committed
859
        if (!snapshot->has_data(index))
DreamSourceLab's avatar
DreamSourceLab committed
860 861
            return;

Andy Dneg's avatar
Andy Dneg committed
862
        const uint16_t enabled_channels = snapshot->get_channel_num();
863
        const double pixels_offset = offset;
Andy Dneg's avatar
Andy Dneg committed
864
        const double samplerate = _data->samplerate();
865
        //const double samplerate = _dev_inst->get_sample_rate();
866
        //const double samplerate = _view->session().cur_snap_samplerate();
DreamSourceLab's avatar
DreamSourceLab committed
867 868
        const int64_t last_sample = max((int64_t)(snapshot->get_sample_count() - 1), (int64_t)0);
        const double samples_per_pixel = samplerate * scale;
869
        const double start = offset * samples_per_pixel - _view->trig_hoff();
DreamSourceLab's avatar
DreamSourceLab committed
870 871 872 873 874 875
        const double end = start + samples_per_pixel * width;

        const int64_t start_sample = min(max((int64_t)floor(start),
            (int64_t)0), last_sample);
        const int64_t end_sample = min(max((int64_t)ceil(end) + 1,
            (int64_t)0), last_sample);
Andy Dneg's avatar
Andy Dneg committed
876
        const int hw_offset = get_hw_offset();
DreamSourceLab's avatar
DreamSourceLab committed
877

DreamSourceLab's avatar
DreamSourceLab committed
878 879
        if (samples_per_pixel < EnvelopeThreshold) {
            snapshot->enable_envelope(false);
880
            paint_trace(p, snapshot, zeroY, left,
Andy Dneg's avatar
Andy Dneg committed
881 882
                start_sample, end_sample, hw_offset,
                pixels_offset, samples_per_pixel, enabled_channels);
DreamSourceLab's avatar
DreamSourceLab committed
883 884
        } else {
            snapshot->enable_envelope(true);
885
            paint_envelope(p, snapshot, zeroY, left,
Andy Dneg's avatar
Andy Dneg committed
886 887 888 889 890
                start_sample, end_sample, hw_offset,
                pixels_offset, samples_per_pixel, enabled_channels);
        }

        sr_status status;
891
        if (sr_status_get(_dev_inst->dev_inst(), &status, false) == SR_OK) {
Andy Dneg's avatar
Andy Dneg committed
892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929
            _mValid = true;
            if (status.measure_valid) {
                _min = (index == 0) ? status.ch0_min : status.ch1_min;
                _max = (index == 0) ? status.ch0_max : status.ch1_max;

                _level_valid = (index == 0) ? status.ch0_level_valid : status.ch1_level_valid;
                _low = (index == 0) ? status.ch0_low_level : status.ch1_low_level;
                _high = (index == 0) ? status.ch0_high_level : status.ch1_high_level;

                const uint32_t count  = (index == 0) ? status.ch0_cyc_cnt : status.ch1_cyc_cnt;
                const bool plevel = (index == 0) ? status.ch0_plevel : status.ch1_plevel;
                const bool startXORend = (index == 0) ? (status.ch0_cyc_llen == 0) : (status.ch1_cyc_llen == 0);
                const uint16_t total_channels = g_slist_length(_dev_inst->dev_inst()->channels);
                const double tfactor = (total_channels / enabled_channels) * SR_GHZ(1) * 1.0 / samplerate;

                double samples = (index == 0) ? status.ch0_cyc_tlen : status.ch1_cyc_tlen;
                _period = ((count == 0) ? 0 : samples / count) * tfactor;

                samples = (index == 0) ? status.ch0_cyc_flen : status.ch1_cyc_flen;
                _rise_time = ((count == 0) ? 0 : samples / ((plevel && startXORend) ? count : count + 1)) * tfactor;
                samples = (index == 0) ? status.ch0_cyc_rlen : status.ch1_cyc_rlen;
                _fall_time = ((count == 0) ? 0 : samples / ((!plevel && startXORend) ? count : count + 1)) * tfactor;

                samples = (index == 0) ? (status.ch0_plevel ? status.ch0_cyc_plen - status.ch0_cyc_llen :
                                                              status.ch0_cyc_tlen - status.ch0_cyc_plen + status.ch0_cyc_llen) :
                                         (status.ch1_plevel ? status.ch1_cyc_plen - status.ch1_cyc_llen :
                                                              status.ch1_cyc_tlen - status.ch1_cyc_plen + status.ch1_cyc_llen);
                _high_time = ((count == 0) ? 0 : samples / count) * tfactor;

                samples = (index == 0) ? status.ch0_cyc_tlen + status.ch0_cyc_llen : status.ch1_cyc_flen + status.ch1_cyc_llen;
                _burst_time = samples * tfactor;

                _pcount = count + (plevel & !startXORend);
                _rms = (index == 0) ? status.ch0_acc_square : status.ch1_acc_square;
                _rms = sqrt(_rms / snapshot->get_sample_count());
                _mean = (index == 0) ? status.ch0_acc_mean : status.ch1_acc_mean;
                _mean = hw_offset - _mean / snapshot->get_sample_count();
            }
DreamSourceLab's avatar
DreamSourceLab committed
930
        }
DreamSourceLab's avatar
DreamSourceLab committed
931 932 933
    }
}

Andy Dneg's avatar
Andy Dneg committed
934
void DsoSignal::paint_fore(QPainter &p, int left, int right, QColor fore, QColor back)
DreamSourceLab's avatar
DreamSourceLab committed
935
{
Andy Dneg's avatar
Andy Dneg committed
936 937
    if (!_show)
        return;
DreamSourceLab's avatar
DreamSourceLab committed
938

Andy Dneg's avatar
Andy Dneg committed
939
    assert(_view);
940

Andy Dneg's avatar
Andy Dneg committed
941 942
    fore.setAlpha(View::BackAlpha);
    QPen pen(fore);
DreamSourceLab's avatar
DreamSourceLab committed
943 944
    pen.setStyle(Qt::DotLine);
    p.setPen(pen);
DreamSourceLab's avatar
DreamSourceLab committed
945
    p.drawLine(left, get_zero_vpos(), right, get_zero_vpos());
DreamSourceLab's avatar
DreamSourceLab committed
946

Andy Dneg's avatar
Andy Dneg committed
947
    fore.setAlpha(View::ForeAlpha);
DreamSourceLab's avatar
DreamSourceLab committed
948 949 950 951 952 953 954
    if(enabled()) {
        const QPointF mouse_point = _view->hover_point();
        const QRectF label_rect = get_trig_rect(left, right);
        const bool hover = label_rect.contains(mouse_point);

        // Paint the trig line
        const QPointF points[] = {
Andy Dneg's avatar
Andy Dneg committed
955
            QPointF(right, ratio2pos(get_trig_vrate())),
DreamSourceLab's avatar
DreamSourceLab committed
956 957 958 959 960 961 962
            label_rect.topLeft(),
            label_rect.topRight(),
            label_rect.bottomRight(),
            label_rect.bottomLeft()
        };

        p.setPen(Qt::transparent);
963
        p.setBrush(_colour);
DreamSourceLab's avatar
DreamSourceLab committed
964 965
        p.drawPolygon(points, countof(points));

Andy Dneg's avatar
Andy Dneg committed
966
        p.setPen(fore);
967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992
        const QPointF arrow_points[] = {
            QPoint(label_rect.left(), label_rect.center().y()),
            QPoint(label_rect.left(), label_rect.center().y()-1),
            QPoint(label_rect.left(), label_rect.center().y()+1),
            QPoint(label_rect.left(), label_rect.center().y()-2),
            QPoint(label_rect.left(), label_rect.center().y()+2),
            QPoint(label_rect.left(), label_rect.center().y()-3),
            QPoint(label_rect.left(), label_rect.center().y()+3),
            QPoint(label_rect.left(), label_rect.center().y()-4),
            QPoint(label_rect.left(), label_rect.center().y()+4),
            QPoint(label_rect.left()-1, label_rect.center().y()-3),
            QPoint(label_rect.left()-1, label_rect.center().y()+3),
            QPoint(label_rect.left()+1, label_rect.center().y()-3),
            QPoint(label_rect.left()+1, label_rect.center().y()+3),
            QPoint(label_rect.left()-1, label_rect.center().y()-2),
            QPoint(label_rect.left()-1, label_rect.center().y()+2),
            QPoint(label_rect.left()+1, label_rect.center().y()-2),
            QPoint(label_rect.left()+1, label_rect.center().y()+2),
            QPoint(label_rect.left()-2, label_rect.center().y()-2),
            QPoint(label_rect.left()-2, label_rect.center().y()+2),
            QPoint(label_rect.left()+2, label_rect.center().y()-2),
            QPoint(label_rect.left()+2, label_rect.center().y()+2),
        };
        if (hover || selected())
            p.drawPoints(arrow_points, countof(arrow_points));

993
        // paint the trig voltage
Andy Dneg's avatar
Andy Dneg committed
994 995
        int trigp = ratio2pos(get_trig_vrate());
        QString t_vol_s = get_voltage(get_zero_vpos() - trigp, 2, true);
996 997 998
        int vol_width = p.boundingRect(0, 0, INT_MAX, INT_MAX,
                                       Qt::AlignLeft | Qt::AlignTop, t_vol_s).width();
        const QRectF t_vol_rect = QRectF(right-vol_width, trigp-10, vol_width, 20);
Andy Dneg's avatar
Andy Dneg committed
999
        p.setPen(fore);
1000 1001
        p.drawText(t_vol_rect, Qt::AlignRight | Qt::AlignVCenter, t_vol_s);

DreamSourceLab's avatar
DreamSourceLab committed
1002
        // paint the _trig_vpos line
1003 1004 1005 1006
        if (_view->get_dso_trig_moved()) {
            p.setPen(QPen(_colour, 1, Qt::DotLine));
            p.drawLine(left, trigp, right - p.boundingRect(t_vol_rect, Qt::AlignLeft, t_vol_s).width(), trigp);
        }
DreamSourceLab's avatar
DreamSourceLab committed
1007 1008

        // Paint the text
Andy Dneg's avatar
Andy Dneg committed
1009
        p.setPen(fore);
DreamSourceLab's avatar
DreamSourceLab committed
1010
        p.drawText(label_rect, Qt::AlignCenter | Qt::AlignVCenter, "T");
1011 1012

        // Paint measure
Andy Dneg's avatar
Andy Dneg committed
1013 1014
        if (_view->session().get_capture_state() == SigSession::Stopped)
            paint_hover_measure(p, fore, back);
1015

Andy Dneg's avatar
Andy Dneg committed
1016 1017 1018
        // autoset
        auto_set();
    }
DreamSourceLab's avatar
DreamSourceLab committed
1019 1020 1021 1022 1023 1024
}

QRectF DsoSignal::get_trig_rect(int left, int right) const
{
    (void)left;

DreamSourceLab's avatar
DreamSourceLab committed
1025
    return QRectF(right + SquareWidth / 2,
Andy Dneg's avatar
Andy Dneg committed
1026
                  ratio2pos(get_trig_vrate()) - SquareWidth / 2,
DreamSourceLab's avatar
DreamSourceLab committed
1027
                  SquareWidth, SquareWidth);
DreamSourceLab's avatar
DreamSourceLab committed
1028 1029 1030
}

void DsoSignal::paint_trace(QPainter &p,
DreamSourceLab's avatar
v0.21  
DreamSourceLab committed
1031
    const boost::shared_ptr<pv::data::DsoSnapshot> &snapshot,
Andy Dneg's avatar
Andy Dneg committed
1032
    int zeroY, int left, const int64_t start, const int64_t end, int hw_offset,
DreamSourceLab's avatar
v0.3  
DreamSourceLab committed
1033
    const double pixels_offset, const double samples_per_pixel, uint64_t num_channels)
DreamSourceLab's avatar
DreamSourceLab committed
1034
{
DreamSourceLab's avatar
DreamSourceLab committed
1035
    const int64_t sample_count = end - start + 1;
DreamSourceLab's avatar
DreamSourceLab committed
1036 1037

    if (sample_count > 0) {
DreamSourceLab's avatar
v0.3  
DreamSourceLab committed
1038
        const uint8_t *const samples = snapshot->get_samples(start, end, get_index());
DreamSourceLab's avatar
DreamSourceLab committed
1039 1040
        assert(samples);

1041
        QColor trace_colour = _colour;
Andy Dneg's avatar
Andy Dneg committed
1042
        trace_colour.setAlpha(View::ForeAlpha);
1043
        p.setPen(trace_colour);
DreamSourceLab's avatar
DreamSourceLab committed
1044 1045 1046 1047

        QPointF *points = new QPointF[sample_count];
        QPointF *point = points;

DreamSourceLab's avatar
DreamSourceLab committed
1048 1049
        float top = get_view_rect().top();
        float bottom = get_view_rect().bottom();
DreamSourceLab's avatar
DreamSourceLab committed
1050
        double  pixels_per_sample = 1.0/samples_per_pixel;
1051

Andy Dneg's avatar
Andy Dneg committed
1052
        uint8_t value;
DreamSourceLab's avatar
DreamSourceLab committed
1053
        int64_t sample_end = sample_count*num_channels;
1054
        float x = (start / samples_per_pixel - pixels_offset) + left + _view->trig_hoff()*pixels_per_sample;
DreamSourceLab's avatar
DreamSourceLab committed
1055
        for (int64_t sample = 0; sample < sample_end; sample+=num_channels) {
Andy Dneg's avatar
Andy Dneg committed
1056 1057
            value = samples[sample];
            const float y = min(max(top, zeroY + (value - hw_offset) * _scale), bottom);
DreamSourceLab's avatar
DreamSourceLab committed
1058 1059
            *point++ = QPointF(x, y);
            x += pixels_per_sample;
DreamSourceLab's avatar
DreamSourceLab committed
1060 1061 1062
        }

        p.drawPolyline(points, point - points);
DreamSourceLab's avatar
DreamSourceLab committed
1063
        p.eraseRect(get_view_rect().right()+1, get_view_rect().top(),
1064
                    _view->viewport()->width() - get_view_rect().width(), get_view_rect().height());
DreamSourceLab's avatar
DreamSourceLab committed
1065 1066 1067 1068 1069 1070

        delete[] points;
    }
}

void DsoSignal::paint_envelope(QPainter &p,
DreamSourceLab's avatar
v0.21  
DreamSourceLab committed
1071
    const boost::shared_ptr<pv::data::DsoSnapshot> &snapshot,
Andy Dneg's avatar
Andy Dneg committed
1072
    int zeroY, int left, const int64_t start, const int64_t end, int hw_offset,
DreamSourceLab's avatar
DreamSourceLab committed
1073
    const double pixels_offset, const double samples_per_pixel, uint64_t num_channels)
DreamSourceLab's avatar
DreamSourceLab committed
1074 1075 1076 1077 1078
{
	using namespace Qt;
    using pv::data::DsoSnapshot;

    DsoSnapshot::EnvelopeSection e;
DreamSourceLab's avatar
DreamSourceLab committed
1079 1080
    const uint16_t index = get_index() % num_channels;
    snapshot->get_envelope_section(e, start, end, samples_per_pixel, index);
DreamSourceLab's avatar
DreamSourceLab committed
1081 1082 1083 1084 1085 1086

	if (e.length < 2)
		return;

    p.setPen(QPen(NoPen));
    //p.setPen(QPen(_colour, 2, Qt::SolidLine));
1087
    QColor envelope_colour = _colour;
Andy Dneg's avatar
Andy Dneg committed
1088
    envelope_colour.setAlpha(View::ForeAlpha);
1089
    p.setBrush(envelope_colour);
DreamSourceLab's avatar
DreamSourceLab committed
1090 1091 1092

	QRectF *const rects = new QRectF[e.length];
	QRectF *rect = rects;
DreamSourceLab's avatar
DreamSourceLab committed
1093 1094 1095
    float top = get_view_rect().top();
    float bottom = get_view_rect().bottom();
    for(uint64_t sample = 0; sample < e.length-1; sample++) {
DreamSourceLab's avatar
DreamSourceLab committed
1096
		const float x = ((e.scale * sample + e.start) /
1097
            samples_per_pixel - pixels_offset) + left + _view->trig_hoff()/samples_per_pixel;
DreamSourceLab's avatar
DreamSourceLab committed
1098 1099 1100 1101 1102
        const DsoSnapshot::EnvelopeSample *const s =
			e.samples + sample;

		// We overlap this sample with the next so that vertical
		// gaps do not appear during steep rising or falling edges
Andy Dneg's avatar
Andy Dneg committed
1103 1104
        const float b = min(max(top, ((max(s->max, (s+1)->min) - hw_offset) * _scale + zeroY)), bottom);
        const float t = min(max(top, ((min(s->min, (s+1)->max) - hw_offset) * _scale + zeroY)), bottom);
DreamSourceLab's avatar
DreamSourceLab committed
1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120

		float h = b - t;
		if(h >= 0.0f && h <= 1.0f)
			h = 1.0f;
		if(h <= 0.0f && h >= -1.0f)
			h = -1.0f;

		*rect++ = QRectF(x, t, 1.0f, h);
	}

	p.drawRects(rects, e.length);

	delete[] rects;
    //delete[] e.samples;
}

Andy Dneg's avatar
Andy Dneg committed
1121
void DsoSignal::paint_type_options(QPainter &p, int right, const QPoint pt, QColor fore)
DreamSourceLab's avatar
DreamSourceLab committed
1122
{
Andy Dneg's avatar
Andy Dneg committed
1123 1124 1125 1126
    p.setRenderHint(QPainter::Antialiasing, true);

    QColor foreBack = fore;
    foreBack.setAlpha(View::BackAlpha);
DreamSourceLab's avatar
DreamSourceLab committed
1127
    int y = get_y();
1128 1129 1130 1131 1132 1133
    const QRectF vDial_rect = get_rect(DSO_VDIAL, y, right);
    const QRectF x1_rect = get_rect(DSO_X1, y, right);
    const QRectF x10_rect = get_rect(DSO_X10, y, right);
    const QRectF x100_rect = get_rect(DSO_X100, y, right);
    const QRectF acdc_rect = get_rect(DSO_ACDC, y, right);
    const QRectF chEn_rect = get_rect(DSO_CHEN, y, right);
1134
    const QRectF auto_rect = get_rect(DSO_AUTO, y, right);
1135

Andy Dneg's avatar
Andy Dneg committed
1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149
    QString pText;
    _vDial->paint(p, vDial_rect, _colour, pt, pText);
    QFontMetrics fm(p.font());
    const QRectF valueRect = QRectF(chEn_rect.left(), vDial_rect.top()-fm.height()-10, right, fm.height());
    p.drawText(valueRect, Qt::AlignCenter, pText);

    const char *strings[6] = {
        QT_TR_NOOP("EN"),
        QT_TR_NOOP("DIS"),
        QT_TR_NOOP("GND"),
        QT_TR_NOOP("DC"),
        QT_TR_NOOP("AC"),
        QT_TR_NOOP("AUTO"),
    };
DreamSourceLab's avatar
DreamSourceLab committed
1150
    p.setPen(Qt::transparent);
1151
    p.setBrush(chEn_rect.contains(pt) ? _colour.darker() : _colour);
DreamSourceLab's avatar
DreamSourceLab committed
1152 1153
    p.drawRect(chEn_rect);
    p.setPen(Qt::white);
Andy Dneg's avatar
Andy Dneg committed
1154
    p.drawText(chEn_rect, Qt::AlignCenter | Qt::AlignVCenter, enabled() ? tr(strings[0]) : tr(strings[1]));
DreamSourceLab's avatar
DreamSourceLab committed
1155 1156

    p.setPen(Qt::transparent);
Andy Dneg's avatar
Andy Dneg committed
1157
    p.setBrush(enabled() ? (acdc_rect.contains(pt) ? _colour.darker() : _colour) : foreBack);
DreamSourceLab's avatar
DreamSourceLab committed
1158 1159
    p.drawRect(acdc_rect);
    p.setPen(Qt::white);
Andy Dneg's avatar
Andy Dneg committed
1160 1161
    p.drawText(acdc_rect, Qt::AlignCenter | Qt::AlignVCenter, (_acCoupling == SR_GND_COUPLING) ? tr(strings[2]):
                                                              (_acCoupling == SR_DC_COUPLING) ? tr(strings[3]) : tr(strings[4]));
1162

1163 1164
    if (!_dev_inst->name().contains("virtual")) {
        p.setPen(Qt::transparent);
Andy Dneg's avatar
Andy Dneg committed
1165
        p.setBrush(enabled() ? (auto_rect.contains(pt) ? _colour.darker() : _colour) : foreBack);
1166 1167
        p.drawRect(auto_rect);
        p.setPen(Qt::white);
Andy Dneg's avatar
Andy Dneg committed
1168
        p.drawText(auto_rect, Qt::AlignCenter | Qt::AlignVCenter, tr(strings[5]));
1169
    }
1170

1171 1172 1173
    // paint the probe factor selector
    GVariant* gvar;
    uint64_t factor;
1174
    gvar = _dev_inst->get_config(_probe, NULL, SR_CONF_PROBE_FACTOR);
1175 1176 1177 1178
    if (gvar != NULL) {
        factor = g_variant_get_uint64(gvar);
        g_variant_unref(gvar);
    } else {
1179
        qDebug() << "ERROR: config_get SR_CONF_PROBE_FACTOR failed.";
1180 1181 1182
        return;
    }

DreamSourceLab's avatar
DreamSourceLab committed
1183
    p.setPen(Qt::transparent);
Andy Dneg's avatar
Andy Dneg committed
1184
    p.setBrush((enabled() && (factor == 100)) ? (x100_rect.contains(pt) ? _colour.darker() : _colour)  : (x100_rect.contains(pt) ? _colour.darker() : foreBack));
1185
    p.drawRect(x100_rect);
Andy Dneg's avatar
Andy Dneg committed
1186
    p.setBrush((enabled() && (factor == 10)) ? (x10_rect.contains(pt) ? _colour.darker() : _colour)  : (x10_rect.contains(pt) ? _colour.darker() : foreBack));
1187
    p.drawRect(x10_rect);
Andy Dneg's avatar
Andy Dneg committed
1188
    p.setBrush((enabled() && (factor == 1)) ? (x1_rect.contains(pt) ? _colour.darker() : _colour)  : (x1_rect.contains(pt) ? _colour.darker() : foreBack));
1189
    p.drawRect(x1_rect);
DreamSourceLab's avatar
DreamSourceLab committed
1190 1191 1192 1193

    p.setPen(Qt::white);
    p.drawText(x100_rect, Qt::AlignCenter | Qt::AlignVCenter, "x100");
    p.drawText(x10_rect, Qt::AlignCenter | Qt::AlignVCenter, "x10");
1194
    p.drawText(x1_rect, Qt::AlignCenter | Qt::AlignVCenter, "x1");
Andy Dneg's avatar
Andy Dneg committed
1195 1196

    p.setRenderHint(QPainter::Antialiasing, false);
DreamSourceLab's avatar
DreamSourceLab committed
1197 1198
}

1199 1200 1201
bool DsoSignal::mouse_press(int right, const QPoint pt)
{
    int y = get_y();
1202
    const QRectF vDial_rect = get_rect(DSO_VDIAL, y, right);
1203 1204
    const QRectF chEn_rect = get_rect(DSO_CHEN, y, right);
    const QRectF acdc_rect = get_rect(DSO_ACDC, y, right);
1205
    const QRectF auto_rect = get_rect(DSO_AUTO, y, right);
1206 1207 1208 1209
    const QRectF x1_rect = get_rect(DSO_X1, y, right);
    const QRectF x10_rect = get_rect(DSO_X10, y, right);
    const QRectF x100_rect = get_rect(DSO_X100, y, right);

1210
    if (chEn_rect.contains(pt)) {
1211
       if (_dev_inst->name() != "virtual-session" &&
1212
           !_en_lock) {
1213
           set_enable(!enabled());
1214
       }
1215 1216
       return true;
    } else if (enabled()) {
1217 1218
        if (vDial_rect.contains(pt) && pt.x() > vDial_rect.center().x()) {
            if (pt.y() > vDial_rect.center().y())
Andy Dneg's avatar
Andy Dneg committed
1219
                go_vDialNext(true);
1220
            else
Andy Dneg's avatar
Andy Dneg committed
1221
                go_vDialPre(true);
1222
        } else if (_dev_inst->name() != "virtual-session" &&
1223
                   acdc_rect.contains(pt)) {
1224
           if (_dev_inst->name() == "DSLogic")
1225 1226
               set_acCoupling((get_acCoupling()+1)%2);
           else
1227
               set_acCoupling((get_acCoupling()+1)%2);
1228
        } else if (auto_rect.contains(pt)) {
1229 1230
            if (!_dev_inst->name().contains("virtual"))
                auto_start();
1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250
        } else if (x1_rect.contains(pt)) {
           set_factor(1);
        } else if (x10_rect.contains(pt)) {
           set_factor(10);
        } else if (x100_rect.contains(pt)) {
           set_factor(100);
        } else {
            return false;
        }
        return true;
    }
    return false;
}

bool DsoSignal::mouse_wheel(int right, const QPoint pt, const int shift)
{
    int y = get_y();
    const QRectF vDial_rect = get_rect(DSO_VDIAL, y, right);

    if (vDial_rect.contains(pt)) {
1251
        if (shift > 0.5)
Andy Dneg's avatar
Andy Dneg committed
1252
            go_vDialPre(true);
1253
        else if (shift < -0.5)
Andy Dneg's avatar
Andy Dneg committed
1254
            go_vDialNext(true);
1255 1256 1257 1258 1259 1260 1261 1262 1263 1264
        return true;
    } else {
        return false;
    }

    return true;
}

QRectF DsoSignal::get_rect(DsoSetRegions type, int y, int right)
{
1265
    (void)right;
1266 1267 1268

    if (type == DSO_VDIAL)
        return QRectF(
1269 1270
            get_leftWidth() + SquareWidth*0.5 + Margin,
            y - SquareWidth * SquareNum + SquareWidth * 3,
1271 1272 1273
            SquareWidth * (SquareNum-1), SquareWidth * (SquareNum-1));
    else if (type == DSO_X1)
        return QRectF(
1274 1275
            get_leftWidth() + SquareWidth*0.5,
            y - SquareWidth * 2 - SquareWidth * (SquareNum-2) * 1 + SquareWidth * 3,
1276 1277 1278
            SquareWidth * 1.75, SquareWidth);
    else if (type == DSO_X10)
        return QRectF(
1279 1280
            get_leftWidth() + SquareWidth*0.5,
            y - SquareWidth * 2 - SquareWidth * (SquareNum-2) * 0.5 + SquareWidth * 3,
1281 1282 1283
            SquareWidth * 1.75, SquareWidth);
    else if (type == DSO_X100)
        return QRectF(
1284 1285
            get_leftWidth() + SquareWidth*0.5,
            y - SquareWidth * 2 - SquareWidth * (SquareNum-2) * 0 + SquareWidth * 3,
1286 1287 1288
            SquareWidth * 1.75, SquareWidth);
    else if (type == DSO_CHEN)
        return QRectF(
1289 1290 1291
            2,
            y - SquareWidth / 2 + SquareWidth * 3,
            SquareWidth * 1.75, SquareWidth);
1292 1293
    else if (type == DSO_ACDC)
        return QRectF(
1294 1295 1296 1297 1298 1299 1300 1301
            2+SquareWidth*1.75 + Margin,
            y - SquareWidth / 2 + SquareWidth * 3,
            SquareWidth * 1.75, SquareWidth);
    else if (type == DSO_AUTO)
        return QRectF(
            2+SquareWidth*3.5 + Margin*2,
            y - SquareWidth / 2 + SquareWidth * 3,
            SquareWidth * 1.75, SquareWidth);
1302 1303 1304 1305
    else
        return QRectF(0, 0, 0, 0);
}

Andy Dneg's avatar
Andy Dneg committed
1306
void DsoSignal::paint_hover_measure(QPainter &p, QColor fore, QColor back)
DreamSourceLab's avatar
DreamSourceLab committed
1307
{
Andy Dneg's avatar
Andy Dneg committed
1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327
    const int hw_offset = get_hw_offset();
    // Hover measure
    if (_hover_en) {
        QString hover_str = get_voltage(hw_offset - _hover_value, 2);
        const int hover_width = p.boundingRect(0, 0, INT_MAX, INT_MAX,
            Qt::AlignLeft | Qt::AlignTop, hover_str).width() + 10;
        const int hover_height = p.boundingRect(0, 0, INT_MAX, INT_MAX,
            Qt::AlignLeft | Qt::AlignTop, hover_str).height();
        QRectF hover_rect(_hover_point.x(), _hover_point.y()-hover_height/2, hover_width, hover_height);
        if (hover_rect.right() > get_view_rect().right())
            hover_rect.moveRight(_hover_point.x());
        if (hover_rect.top() < get_view_rect().top())
            hover_rect.moveTop(_hover_point.y());
        if (hover_rect.bottom() > get_view_rect().bottom())
            hover_rect.moveBottom(_hover_point.y());

        p.setPen(fore);
        p.setBrush(back);
        p.drawRect(_hover_point.x()-1, _hover_point.y()-1, HoverPointSize, HoverPointSize);
        p.drawText(hover_rect, Qt::AlignCenter | Qt::AlignTop | Qt::TextDontClip, hover_str);
1328
    }
1329

Andy Dneg's avatar
Andy Dneg committed
1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352
    list<Cursor*>::iterator i = _view->get_cursorList().begin();
    while (i != _view->get_cursorList().end()) {
        float pt_value;
        const QPointF pt = get_point((*i)->index(), pt_value);
        QString pt_str = get_voltage(hw_offset - pt_value, 2);
        const int pt_width = p.boundingRect(0, 0, INT_MAX, INT_MAX,
            Qt::AlignLeft | Qt::AlignTop, pt_str).width() + 10;
        const int pt_height = p.boundingRect(0, 0, INT_MAX, INT_MAX,
            Qt::AlignLeft | Qt::AlignTop, pt_str).height();
        QRectF pt_rect(pt.x(), pt.y()-pt_height/2, pt_width, pt_height);
        if (pt_rect.right() > get_view_rect().right())
            pt_rect.moveRight(pt.x());
        if (pt_rect.top() < get_view_rect().top())
            pt_rect.moveTop(pt.y());
        if (pt_rect.bottom() > get_view_rect().bottom())
            pt_rect.moveBottom(pt.y());

        p.drawRect(pt.x()-1, pt.y()-1, 2, 2);
        p.drawLine(pt.x()-2, pt.y()-2, pt.x()+2, pt.y()+2);
        p.drawLine(pt.x()+2, pt.y()-2, pt.x()-2, pt.y()+2);
        p.drawText(pt_rect, Qt::AlignCenter | Qt::AlignTop | Qt::TextDontClip, pt_str);

        i++;
1353
    }
Andy Dneg's avatar
Andy Dneg committed
1354
}
1355

Andy Dneg's avatar
Andy Dneg committed
1356 1357
void DsoSignal::auto_set()
{
1358 1359 1360 1361 1362
    if (_view->session().get_capture_state() == SigSession::Stopped) {
        if (_autoV)
            autoV_end();
        if (_autoH)
            autoH_end();
Andy Dneg's avatar
Andy Dneg committed
1363 1364 1365
    } else {
        if (_autoH && _autoV && get_zero_ratio() != 0.5) {
            set_zero_ratio(0.5);
1366
        }
Andy Dneg's avatar
Andy Dneg committed
1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414
        if (_mValid && !_view->session().get_data_auto_lock()) {
            if (_autoH) {
                bool roll = false;
                GVariant *gvar = _dev_inst->get_config(NULL, NULL, SR_CONF_ROLL);
                if (gvar != NULL) {
                    roll = g_variant_get_boolean(gvar);
                    g_variant_unref(gvar);
                }
                const double hori_res = _view->get_hori_res();
                if (_level_valid && ((!roll && _pcount < 3) || _period > 4*hori_res)) {
                    _view->zoom(-1);
                } else if (_level_valid && _pcount > 6 && _period < 1.5*hori_res) {
                    _view->zoom(1);
                } else if (_level_valid) {
                    autoH_end();
                }
            }
            if (_autoV) {
                const bool over_flag = _max == 0xff || _min == 0x0;
                const bool out_flag = _max >= 0xE0 || _min <= 0x20;
                const bool under_flag = _max <= 0xA0 && _min >= 0x60;
                if (over_flag) {
                    if (!_autoV_over)
                        _auto_cnt = 0;
                    _autoV_over = true;
                    go_vDialNext(false);
                } else if (out_flag) {
                    go_vDialNext(false);
                } else if (!_autoV_over && under_flag) {
                    go_vDialPre(false);
                } else if (!_autoH) {
                    autoV_end();
                }

                if (_autoV_over && under_flag) {
                    if (_auto_cnt++ > 16)
                        _autoV_over = false;
                } else {
                    _auto_cnt = 0;
                }

                if (_level_valid) {
                    _trig_value = (_min+_max)/2;
                    set_trig_vpos(ratio2pos(get_trig_vrate()));
                }
            }
            if (_autoH || _autoV)
                _view->session().data_auto_lock(AutoLock);
1415 1416
        }
    }
DreamSourceLab's avatar
DreamSourceLab committed
1417 1418
}

1419
void DsoSignal::autoV_end()
DreamSourceLab's avatar
DreamSourceLab committed
1420
{
1421
    _autoV = false;
Andy Dneg's avatar
Andy Dneg committed
1422
    _autoV_over = false;
1423 1424
    _view->auto_trig(get_index());
    _trig_value = (_min+_max)/2;
Andy Dneg's avatar
Andy Dneg committed
1425
    set_trig_vpos(ratio2pos(get_trig_vrate()));
1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449
    _view->set_update(_viewport, true);
    _view->update();
}

void DsoSignal::autoH_end()
{
    _autoH = false;
    _view->set_update(_viewport, true);
    _view->update();
}

void DsoSignal::auto_end()
{
    if (_autoV)
        autoV_end();
    if (_autoH)
        autoH_end();
}

void DsoSignal::auto_start()
{
    if (_autoV || _autoH)
        return;
    if (_view->session().get_capture_state() == SigSession::Running) {
1450
        _view->session().data_auto_lock(AutoLock);
DreamSourceLab's avatar
DreamSourceLab committed
1451 1452
        _autoV = true;
        _autoH = true;
1453
        _view->auto_trig(get_index());
Andy Dneg's avatar
Andy Dneg committed
1454
        QTimer::singleShot(AutoTime, &_view->session(), SLOT(auto_end()));
DreamSourceLab's avatar
DreamSourceLab committed
1455
    }
DreamSourceLab's avatar
DreamSourceLab committed
1456 1457
}

1458 1459
bool DsoSignal::measure(const QPointF &p)
{
Andy Dneg's avatar
Andy Dneg committed
1460 1461
    _hover_en = false;
    if (!enabled() || !show())
1462 1463
        return false;

Andy Dneg's avatar
Andy Dneg committed
1464
    if (_view->session().get_capture_state() != SigSession::Stopped)
1465 1466
        return false;

1467 1468 1469 1470
    const QRectF window = get_view_rect();
    if (!window.contains(p))
        return false;

1471 1472 1473 1474 1475 1476 1477
    const deque< boost::shared_ptr<pv::data::DsoSnapshot> > &snapshots =
        _data->get_snapshots();
    if (snapshots.empty())
        return false;

    const boost::shared_ptr<pv::data::DsoSnapshot> &snapshot =
        snapshots.front();
1478
    if (snapshot->empty())
1479 1480
        return false;

1481
    _hover_index = _view->pixel2index(p.x());
1482 1483 1484
    if (_hover_index >= snapshot->get_sample_count())
        return false;

Andy Dneg's avatar
Andy Dneg committed
1485 1486 1487
    _hover_point = get_point(_hover_index, _hover_value);
    _hover_en = true;
    return true;
1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500
}

bool DsoSignal::get_hover(uint64_t &index, QPointF &p, double &value)
{
    if (_hover_en) {
        index = _hover_index;
        p = _hover_point;
        value = _hover_value;
        return true;
    }
    return false;
}

Andy Dneg's avatar
Andy Dneg committed
1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524
QPointF DsoSignal::get_point(uint64_t index, float &value)
{
    QPointF pt = QPointF(0, 0);

    if (!enabled())
        return pt;

    const deque< boost::shared_ptr<pv::data::DsoSnapshot> > &snapshots =
        _data->get_snapshots();
    if (snapshots.empty())
        return pt;

    const boost::shared_ptr<pv::data::DsoSnapshot> &snapshot =
        snapshots.front();
    if (snapshot->empty())
        return pt;

    if (index >= snapshot->get_sample_count())
        return pt;

    value = *snapshot->get_samples(index, index, get_index());
    const float top = get_view_rect().top();
    const float bottom = get_view_rect().bottom();
    const int hw_offset = get_hw_offset();
1525
    const float x = _view->index2pixel(index);
Andy Dneg's avatar
Andy Dneg committed
1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573
    const float y = min(max(top, get_zero_vpos() + (value - hw_offset)* _scale), bottom);
    pt = QPointF(x, y);

    return pt;
}

double DsoSignal::get_voltage(uint64_t index)
{
    if (!enabled())
        return 1;

    const deque< boost::shared_ptr<pv::data::DsoSnapshot> > &snapshots =
        _data->get_snapshots();
    if (snapshots.empty())
        return 1;

    const boost::shared_ptr<pv::data::DsoSnapshot> &snapshot =
        snapshots.front();
    if (snapshot->empty())
        return 1;

    if (index >= snapshot->get_sample_count())
        return 1;

    const double value = *snapshot->get_samples(index, index, get_index());
    const int hw_offset = get_hw_offset();
    return (hw_offset - value) * _scale *
            _vDial->get_value() * _vDial->get_factor() *
            DS_CONF_DSO_VDIVS / get_view_rect().height();
}

QString DsoSignal::get_voltage(double v, int p, bool scaled)
{
    if (scaled)
        v = v * _vDial->get_value() * _vDial->get_factor() * DS_CONF_DSO_VDIVS / get_view_rect().height();
    else
        v = v * _scale * _vDial->get_value() * _vDial->get_factor() * DS_CONF_DSO_VDIVS / get_view_rect().height();
    return abs(v) >= 1000 ? QString::number(v/1000.0, 'f', p) + "V" : QString::number(v, 'f', p) + "mV";
}

QString DsoSignal::get_time(double t)
{
    QString str = (abs(t) > 1000000000 ? QString::number(t/1000000000, 'f', 2) + "S" :
                   abs(t) > 1000000 ? QString::number(t/1000000, 'f', 2) + "mS" :
                   abs(t) > 1000 ? QString::number(t/1000, 'f', 2) + "uS" : QString::number(t, 'f', 2) + "nS");
    return str;
}

DreamSourceLab's avatar
DreamSourceLab committed
1574 1575
} // namespace view
} // namespace pv