This commit is contained in:
DreamSourceLab 2014-06-29 19:27:43 +08:00
parent a6a3024de0
commit 95f2bf8964
70 changed files with 7233 additions and 58648 deletions

1348
COPYING

File diff suppressed because it is too large Load Diff

View File

@ -85,8 +85,8 @@ set(DS_TITLE DSLogic)
set(DS_DESCRIPTION "A GUI for DSLogic")
set(DS_VERSION_MAJOR 0)
set(DS_VERSION_MINOR 2)
set(DS_VERSION_MICRO 1)
set(DS_VERSION_MINOR 3)
set(DS_VERSION_MICRO 0)
set(DS_VERSION_STRING
${DS_VERSION_MAJOR}.${DS_VERSION_MINOR}.${DS_VERSION_MICRO}
)
@ -156,6 +156,8 @@ set(DSLogic_SOURCES
pv/view/view.cpp
pv/view/viewport.cpp
pv/view/dsosignal.cpp
pv/view/dsldial.cpp
pv/dock/dsotriggerdock.cpp
)
set(DSLogic_HEADERS
@ -187,6 +189,8 @@ set(DSLogic_HEADERS
pv/view/view.h
pv/view/dsosignal.h
pv/view/viewport.h
pv/view/dsldial.h
pv/dock/dsotriggerdock.h
)
set(DSLogic_FORMS

View File

@ -1,49 +1,49 @@
-------------------------------------------------------------------------------
INSTALL
-------------------------------------------------------------------------------
Requirements
------------
- git
- g++
- make
- libtool
- pkg-config >= 0.22
- cmake >= 2.6
- libglib >= 2.28.0
- Qt >= 4.5
- libboost >= 1.42 (including the following libs):
- libboost-system
- libboost-thread
- libsigrok4DSLogic >= 0.2.0
Building and installing
-----------------------
Get the DSLogic-gui source code from: www.dreamsourcelab.com/download.html
In order to build it, run:
$ cd DSLogic-gui
$ cmake .
$ make
For installing PulseView:
$ make install
See the following wiki page for more (OS-specific) instructions:
http://sigrok.org/wiki/Building
Creating a source distribution package
--------------------------------------
In order to build a source package begin with an unconfigured source tree.
$ mkdir dist
$ cd dist
$ cmake ..
$ make package_source
-------------------------------------------------------------------------------
INSTALL
-------------------------------------------------------------------------------
Requirements
------------
- git
- g++
- make
- libtool
- pkg-config >= 0.22
- cmake >= 2.6
- libglib >= 2.28.0
- Qt >= 4.5
- libboost >= 1.42 (including the following libs):
- libboost-system
- libboost-thread
- libsigrok4DSLogic >= 0.2.0
Building and installing
-----------------------
Get the DSLogic-gui source code from: www.dreamsourcelab.com/download.html
In order to build it, run:
$ cd DSLogic-gui
$ cmake .
$ make
For installing PulseView:
$ make install
See the following wiki page for more (OS-specific) instructions:
http://sigrok.org/wiki/Building
Creating a source distribution package
--------------------------------------
In order to build a source package begin with an unconfigured source tree.
$ mkdir dist
$ cd dist
$ cmake ..
$ make package_source

View File

@ -1,5 +1,5 @@
0.1.0 (2013-12-15)
------------------
* Initial release.
0.1.0 (2013-12-15)
------------------
* Initial release.

Binary file not shown.

Binary file not shown.

View File

@ -1,3 +0,0 @@
/usr/local/bin/DSLogic
/usr/local/bin/res/DSLogic.fw
/usr/local/bin/res/DSLogic.bin

File diff suppressed because it is too large Load Diff

View File

@ -70,8 +70,8 @@ void DsoSnapshot::append_payload(const sr_datafeed_dso &dso)
append_payload_to_envelope_levels();
}
const uint16_t* DsoSnapshot::get_samples(
int64_t start_sample, int64_t end_sample) const
const uint8_t *DsoSnapshot::get_samples(
int64_t start_sample, int64_t end_sample, uint16_t index) const
{
assert(start_sample >= 0);
assert(start_sample < (int64_t)get_sample_count());
@ -85,7 +85,7 @@ const uint16_t* DsoSnapshot::get_samples(
// memcpy(data, (uint16_t*)_data + start_sample, sizeof(uint16_t) *
// (end_sample - start_sample));
// return data;
return (uint16_t*)_data + start_sample;
return (uint8_t*)_data + start_sample * _channel_num + index;
}
void DsoSnapshot::get_envelope_section(EnvelopeSection &s,
@ -150,7 +150,7 @@ void DsoSnapshot::append_payload_to_envelope_levels()
dest_ptr = e0.samples + prev_length;
// Iterate through the samples to populate the first level mipmap
const uint16_t *const stop_src_ptr = (uint16_t*)_data +
const uint8_t *const stop_src_ptr = (uint8_t*)_data +
e0.length * EnvelopeScaleFactor * _channel_num;
// for (const uint16_t *src_ptr = (uint16_t*)_data +
// prev_length * EnvelopeScaleFactor;
@ -163,13 +163,13 @@ void DsoSnapshot::append_payload_to_envelope_levels()
// *dest_ptr++ = sub_sample;
// }
for (const uint16_t *src_ptr = (uint16_t*)_data +
for (const uint8_t *src_ptr = (uint8_t*)_data +
prev_length * EnvelopeScaleFactor * _channel_num + i;
src_ptr < stop_src_ptr; src_ptr += EnvelopeScaleFactor * _channel_num)
{
const uint16_t * begin_src_ptr =
const uint8_t * begin_src_ptr =
src_ptr;
const uint16_t *const end_src_ptr =
const uint8_t *const end_src_ptr =
src_ptr + EnvelopeScaleFactor * _channel_num;
EnvelopeSample sub_sample;

View File

@ -40,8 +40,8 @@ class DsoSnapshot : public Snapshot
public:
struct EnvelopeSample
{
uint16_t min;
uint16_t max;
uint8_t min;
uint8_t max;
};
struct EnvelopeSection
@ -74,8 +74,8 @@ public:
void append_payload(const sr_datafeed_dso &dso);
const uint16_t* get_samples(int64_t start_sample,
int64_t end_sample) const;
const uint8_t* get_samples(int64_t start_sample,
int64_t end_sample, uint16_t index) const;
void get_envelope_section(EnvelopeSection &s,
uint64_t start, uint64_t end, float min_length, int probe_index) const;

View File

@ -194,6 +194,7 @@ void DeviceOptions::disable_all_probes()
void DeviceOptions::mode_changed(QString mode)
{
(void)mode;
// Commit mode
sr_config_set(_sdi, SR_CONF_DEVICE_MODE, g_variant_new_string(_mode_comboBox.currentText().toLocal8Bit()));
setup_probes();

View File

@ -0,0 +1,196 @@
/*
* This file is part of the DSLogic-gui project.
* DSLogic-gui is based on PulseView.
*
* Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk>
* Copyright (C) 2013 DreamSourceLab <dreamsourcelab@dreamsourcelab.com>
*
* 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 "dsotriggerdock.h"
#include "../sigsession.h"
#include <QObject>
#include <QLabel>
#include <QRadioButton>
#include <QPainter>
#include <QStyleOption>
#include <QMessageBox>
#include <QVector>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include "libsigrok4DSLogic/libsigrok.h"
namespace pv {
namespace dock {
DsoTriggerDock::DsoTriggerDock(QWidget *parent, SigSession &session) :
QWidget(parent),
_session(session)
{
QLabel *position_label = new QLabel("Trigger Position: ", this);
position_spinBox = new QSpinBox(this);
position_spinBox->setRange(0, 99);
position_spinBox->setButtonSymbols(QAbstractSpinBox::NoButtons);
position_slider = new QSlider(Qt::Horizontal, this);
position_slider->setRange(0, 99);
connect(position_slider, SIGNAL(valueChanged(int)), position_spinBox, SLOT(setValue(int)));
connect(position_spinBox, SIGNAL(valueChanged(int)), position_slider, SLOT(setValue(int)));
connect(position_slider, SIGNAL(valueChanged(int)), this, SLOT(pos_changed(int)));
QLabel *tSource_labe = new QLabel("Trigger Sources: ", this);
QRadioButton *auto_radioButton = new QRadioButton("Auto");
auto_radioButton->setChecked(true);
QRadioButton *ch0_radioButton = new QRadioButton("Channel 0");
QRadioButton *ch1_radioButton = new QRadioButton("Channel 1");
QRadioButton *ch0a1_radioButton = new QRadioButton("Channel 0 && Channel 1");
QRadioButton *ch0o1_radioButton = new QRadioButton("Channel 0 | Channel 1");
connect(auto_radioButton, SIGNAL(clicked()), this, SLOT(source_changed()));
connect(ch0_radioButton, SIGNAL(clicked()), this, SLOT(source_changed()));
connect(ch1_radioButton, SIGNAL(clicked()), this, SLOT(source_changed()));
connect(ch0a1_radioButton, SIGNAL(clicked()), this, SLOT(source_changed()));
connect(ch0o1_radioButton, SIGNAL(clicked()), this, SLOT(source_changed()));
QLabel *tType_labe = new QLabel("Trigger Types: ", this);
QRadioButton *rising_radioButton = new QRadioButton("Rising Edge");
rising_radioButton->setChecked(true);
QRadioButton *falling_radioButton = new QRadioButton("Falling Edge");
connect(rising_radioButton, SIGNAL(clicked()), this, SLOT(type_changed()));
connect(falling_radioButton, SIGNAL(clicked()), this, SLOT(type_changed()));
source_group=new QButtonGroup(this);
type_group=new QButtonGroup(this);
source_group->addButton(auto_radioButton);
source_group->addButton(ch0_radioButton);
source_group->addButton(ch1_radioButton);
source_group->addButton(ch0a1_radioButton);
source_group->addButton(ch0o1_radioButton);
source_group->setId(auto_radioButton, DSO_TRIGGER_AUTO);
source_group->setId(ch0_radioButton, DSO_TRIGGER_CH0);
source_group->setId(ch1_radioButton, DSO_TRIGGER_CH1);
source_group->setId(ch0a1_radioButton, DSO_TRIGGER_CH0A1);
source_group->setId(ch0o1_radioButton, DSO_TRIGGER_CH0O1);
type_group->addButton(rising_radioButton);
type_group->addButton(falling_radioButton);
type_group->setId(rising_radioButton, DSO_TRIGGER_RISING);
type_group->setId(falling_radioButton, DSO_TRIGGER_FALLING);
QVBoxLayout *layout = new QVBoxLayout(this);
QGridLayout *gLayout = new QGridLayout();
gLayout->addWidget(position_label, 0, 0);
gLayout->addWidget(position_spinBox, 0, 1);
gLayout->addWidget(new QLabel(this), 0, 2);
gLayout->addWidget(position_slider, 1, 0, 1, 3);
gLayout->addWidget(new QLabel(this), 2, 0);
gLayout->addWidget(tSource_labe, 3, 0);
gLayout->addWidget(auto_radioButton, 4, 0);
gLayout->addWidget(ch0_radioButton, 5, 0);
gLayout->addWidget(ch1_radioButton, 5, 1);
gLayout->addWidget(ch0a1_radioButton, 6, 0);
gLayout->addWidget(ch0o1_radioButton, 6, 1);
gLayout->addWidget(new QLabel(this), 7, 0);
gLayout->addWidget(tType_labe, 8, 0);
gLayout->addWidget(rising_radioButton, 9, 0);
gLayout->addWidget(falling_radioButton, 10, 0);
gLayout->setColumnStretch(3, 1);
layout->addLayout(gLayout);
layout->addStretch(1);
setLayout(layout);
}
DsoTriggerDock::~DsoTriggerDock()
{
}
void DsoTriggerDock::paintEvent(QPaintEvent *)
{
QStyleOption opt;
opt.init(this);
QPainter p(this);
style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
}
void DsoTriggerDock::pos_changed(int pos)
{
int ret;
quint32 real_pos;
real_pos = pos*_session.get_total_sample_len()/100.0f;
real_pos = (_session.get_last_sample_rate() > SR_MHZ(100)) ? real_pos/2 : real_pos;
ret = sr_config_set(_session.get_device(), SR_CONF_HORIZ_TRIGGERPOS, g_variant_new_uint32(real_pos));
if (ret != SR_OK) {
QMessageBox msg(this);
msg.setText("Trigger Setting Issue");
msg.setInformativeText("Change horiz trigger position failed!");
msg.setStandardButtons(QMessageBox::Ok);
msg.setIcon(QMessageBox::Warning);
msg.exec();
}
}
void DsoTriggerDock::source_changed()
{
int id = source_group->checkedId();
int ret;
ret = sr_config_set(_session.get_device(), SR_CONF_TRIGGER_SOURCE, g_variant_new_byte(id));
if (ret != SR_OK) {
QMessageBox msg(this);
msg.setText("Trigger Setting Issue");
msg.setInformativeText("Change trigger source failed!");
msg.setStandardButtons(QMessageBox::Ok);
msg.setIcon(QMessageBox::Warning);
msg.exec();
}
}
void DsoTriggerDock::type_changed()
{
int id = type_group->checkedId();
int ret;
ret = sr_config_set(_session.get_device(), SR_CONF_TRIGGER_SLOPE, g_variant_new_byte(id));
if (ret != SR_OK) {
QMessageBox msg(this);
msg.setText("Trigger Setting Issue");
msg.setInformativeText("Change trigger type failed!");
msg.setStandardButtons(QMessageBox::Ok);
msg.setIcon(QMessageBox::Warning);
msg.exec();
}
}
void DsoTriggerDock::device_change()
{
if (strcmp(_session.get_device()->driver->name, "DSLogic") != 0) {
position_spinBox->setDisabled(true);
position_slider->setDisabled(true);
} else {
position_spinBox->setDisabled(false);
position_slider->setDisabled(false);
}
}
} // namespace dock
} // namespace pv

View File

@ -0,0 +1,76 @@
/*
* This file is part of the DSLogic-gui project.
* DSLogic-gui is based on PulseView.
*
* Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk>
* Copyright (C) 2013 DreamSourceLab <dreamsourcelab@dreamsourcelab.com>
*
* 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
*/
#ifndef DSLOGIC_PV_DSOTRIGGERDOCK_H
#define DSLOGIC_PV_DSOTRIGGERDOCK_H
#include <QDockWidget>
#include <QSlider>
#include <QSpinBox>
#include <QButtonGroup>
#include <vector>
#include <libsigrok4DSLogic/libsigrok.h>
namespace pv {
class SigSession;
namespace dock {
class DsoTriggerDock : public QWidget
{
Q_OBJECT
public:
DsoTriggerDock(QWidget *parent, SigSession &session);
~DsoTriggerDock();
void paintEvent(QPaintEvent *);
void device_change();
signals:
private slots:
void pos_changed(int pos);
void source_changed();
void type_changed();
private:
private:
SigSession &_session;
QSpinBox *position_spinBox;
QSlider *position_slider;
QButtonGroup *source_group;
QButtonGroup *type_group;
};
} // namespace dock
} // namespace pv
#endif // DSLOGIC_PV_DSOTRIGGERDOCK_H

View File

@ -57,6 +57,7 @@
#include "dock/protocoldock.h"
#include "dock/triggerdock.h"
#include "dock/dsotriggerdock.h"
#include "dock/measuredock.h"
#include "dock/searchdock.h"
@ -235,6 +236,14 @@ void MainWindow::setup_ui()
_trigger_widget = new dock::TriggerDock(_trigger_dock, _session);
_trigger_dock->setWidget(_trigger_widget);
_dso_trigger_dock=new QDockWidget(tr("Trigger Setting..."),this);
_dso_trigger_dock->setFeatures(QDockWidget::NoDockWidgetFeatures);
_dso_trigger_dock->setAllowedAreas(Qt::RightDockWidgetArea);
_dso_trigger_dock->setVisible(false);
_dso_trigger_widget = new dock::DsoTriggerDock(_dso_trigger_dock, _session);
_dso_trigger_dock->setWidget(_dso_trigger_widget);
// Setup _view widget
_view = new pv::view::View(_session, this);
_vertical_layout->addWidget(_view);
@ -250,9 +259,9 @@ void MainWindow::setup_ui()
SLOT(update()));
connect(_sampling_bar, SIGNAL(device_reload()), this,
SLOT(init()));
connect(_sampling_bar, SIGNAL(run_stop()), this,
SLOT(run_stop()));
addToolBar(_sampling_bar);
connect(_sampling_bar, SIGNAL(run_stop()), this,
SLOT(run_stop()));
addToolBar(_sampling_bar);
addToolBar(_trig_bar);
addToolBar(_device_bar);
addToolBar(_file_bar);
@ -296,6 +305,7 @@ void MainWindow::setup_ui()
_trigger_dock->setObjectName(tr("triggerDock"));
addDockWidget(Qt::RightDockWidgetArea,_protocol_dock);
addDockWidget(Qt::RightDockWidgetArea,_trigger_dock);
addDockWidget(Qt::RightDockWidgetArea,_dso_trigger_dock);
addDockWidget(Qt::RightDockWidgetArea, _measure_dock);
addDockWidget(Qt::BottomDockWidgetArea, _search_dock);
@ -312,6 +322,8 @@ void MainWindow::setup_ui()
SLOT(device_detach()));
connect(&_session, SIGNAL(test_data_error()), this,
SLOT(test_data_error()));
connect(&_session, SIGNAL(dso_ch_changed(uint16_t)), this,
SLOT(dso_ch_changed(uint16_t)));
connect(_view, SIGNAL(cursor_update()), _measure_widget,
SLOT(cursor_update()));
@ -327,6 +339,14 @@ void MainWindow::init()
_trigger_widget->device_change();
if (_session.get_device())
_session.init_signals(_session.get_device());
if (_session.get_device()->mode == DSO) {
_sampling_bar->set_record_length(DefaultDSODepth*2);
_sampling_bar->set_sample_rate(DefaultDSORate*2);
_sampling_bar->enable_toggle(false);
_view->hDial_changed(0);
} else if(_session.get_device()->mode == LOGIC) {
_sampling_bar->enable_toggle(true);
}
}
void MainWindow::update()
@ -377,6 +397,8 @@ void MainWindow::update_device_list(struct sr_dev_inst *selected_device)
// #ifdef HAVE_LA_DSLOGIC
_session.start_hotplug_proc(boost::bind(&MainWindow::session_error, this,
QString("Hotplug failed"), _1));
_session.start_dso_ctrl_proc(boost::bind(&MainWindow::session_error, this,
QString("Hotplug failed"), _1));
// #endif
}
@ -446,11 +468,39 @@ void MainWindow::device_selected()
_sampling_bar->set_device(_device_bar->get_selected_device());
_sampling_bar->update_sample_rate_selector();
_view->show_trig_cursor(false);
_trigger_dock->setVisible(false);
_dso_trigger_dock->setVisible(false);
_protocol_dock->setVisible(false);
_measure_dock->setVisible(false);
_search_dock->setVisible(false);
init();
} else {
show_session_error("Open Device Failed",
"the selected device can't be opened!");
}
if (_device_bar->get_selected_device()->mode == DSO) {
QMessageBox msg(this);
msg.setText("Zero Adjustment");
msg.setInformativeText("Please left both of channels unconnect for zero adjustment!");
msg.setStandardButtons(QMessageBox::Ok);
msg.setIcon(QMessageBox::Warning);
msg.exec();
int ret = sr_config_set(_device_bar->get_selected_device(), SR_CONF_ZERO, g_variant_new_boolean(TRUE));
if (ret != SR_OK) {
QMessageBox msg(this);
msg.setText("Zero Adjustment Issue");
msg.setInformativeText("Can't send out the command of zero adjustment!");
msg.setStandardButtons(QMessageBox::Ok);
msg.setIcon(QMessageBox::Warning);
msg.exec();
} else {
run_stop();
g_usleep(100000);
run_stop();
}
}
}
void MainWindow::device_attach()
@ -508,6 +558,31 @@ void MainWindow::run_stop()
_sampling_bar->enable_run_stop(true);
}
void MainWindow::dso_ch_changed(uint16_t num)
{
if(num == 1) {
_sampling_bar->set_record_length(DefaultDSODepth*2);
_sampling_bar->set_sample_rate(DefaultDSORate*2);
_session.set_total_sample_len(_sampling_bar->get_record_length());
if (_session.get_capture_state() == SigSession::Running) {
_session.stop_capture();
_session.start_capture(_sampling_bar->get_record_length(),
boost::bind(&MainWindow::session_error, this,
QString("Capture failed"), _1));
}
} else {
_sampling_bar->set_record_length(DefaultDSODepth);
_sampling_bar->set_sample_rate(DefaultDSORate);
_session.set_total_sample_len(_sampling_bar->get_record_length());
if (_session.get_capture_state() == SigSession::Running) {
_session.stop_capture();
_session.start_capture(_sampling_bar->get_record_length(),
boost::bind(&MainWindow::session_error, this,
QString("Capture failed"), _1));
}
}
}
void MainWindow::test_data_error()
{
_session.stop_capture();
@ -521,12 +596,14 @@ void MainWindow::test_data_error()
void MainWindow::capture_state_changed(int state)
{
_sampling_bar->enable_toggle(state != SigSession::Running);
_trig_bar->enable_toggle(state != SigSession::Running);
if (_session.get_device()->mode != DSO) {
_sampling_bar->enable_toggle(state != SigSession::Running);
_trig_bar->enable_toggle(state != SigSession::Running);
_measure_dock->widget()->setEnabled(state != SigSession::Running);
}
_device_bar->enable_toggle(state != SigSession::Running);
_file_bar->enable_toggle(state != SigSession::Running);
_sampling_bar->set_sampling(state == SigSession::Running);
_measure_dock->widget()->setEnabled(state != SigSession::Running);
_view->on_state_changed(state != SigSession::Running);
}
@ -537,7 +614,10 @@ void MainWindow::on_protocol(bool visible)
void MainWindow::on_trigger(bool visible)
{
_trigger_dock->setVisible(visible);
if (_session.get_device()->mode != DSO)
_trigger_dock->setVisible(visible);
else
_dso_trigger_dock->setVisible(visible);
}
void MainWindow::on_measure(bool visible)

View File

@ -54,6 +54,7 @@ class LogoBar;
namespace dock{
class ProtocolDock;
class TriggerDock;
class DsoTriggerDock;
class MeasureDock;
class SearchDock;
}
@ -66,6 +67,10 @@ class MainWindow : public QMainWindow
{
Q_OBJECT
private:
static const int DefaultDSODepth = 8192;
static const int DefaultDSORate = 100000000;
public:
explicit MainWindow(DeviceManager &device_manager,
const char *open_file_name = NULL,
@ -122,6 +127,9 @@ private slots:
void device_attach();
void device_detach();
/* */
void dso_ch_changed(uint16_t num);
private:
DeviceManager &_device_manager;
@ -155,7 +163,9 @@ private:
QDockWidget *_protocol_dock;
dock::ProtocolDock *_protocol_widget;
QDockWidget *_trigger_dock;
QDockWidget *_dso_trigger_dock;
dock::TriggerDock *_trigger_widget;
dock::DsoTriggerDock *_dso_trigger_widget;
QDockWidget *_measure_dock;
QDockWidget *_search_dock;
dock::SearchDock * _search_widget;

View File

@ -83,8 +83,12 @@ DeviceOptions::DeviceOptions(struct sr_dev_inst *sdi) :
case SR_CONF_BUFFERSIZE:
case SR_CONF_TRIGGER_SOURCE:
case SR_CONF_FILTER:
case SR_CONF_COUPLING:
case SR_CONF_COUPLING0:
case SR_CONF_COUPLING1:
case SR_CONF_EN_CH0:
case SR_CONF_EN_CH1:
case SR_CONF_OPERATION_MODE:
case SR_CONF_ZERO:
bind_enum(name, key, gvar_list);
break;
@ -100,9 +104,12 @@ DeviceOptions::DeviceOptions(struct sr_dev_inst *sdi) :
bind_enum(name, key, gvar_list, print_timebase);
break;
case SR_CONF_VDIV:
case SR_CONF_VDIV0:
case SR_CONF_VDIV1:
bind_enum(name, key, gvar_list, print_vdiv);
break;
break;
default:
gvar_list = NULL;
}
if (gvar_list)

View File

@ -65,7 +65,7 @@ SigSession::SigSession(DeviceManager &device_manager) :
_total_sample_len(1)
{
// TODO: This should not be necessary
_session = this;
_session = this;
_hot_attach = false;
_hot_detach = false;
_adv_trigger = false;
@ -73,7 +73,11 @@ SigSession::SigSession(DeviceManager &device_manager) :
_protocol_cnt = 0;
_decoderFactory = new decoder::DecoderFactory();
ds_trigger_init();
register_hotplug_callback();
_vDial_changed = false;
_hDial_changed = false;
_dso_ctrl_channel = 0;
register_hotplug_callback();
}
SigSession::~SigSession()
@ -90,9 +94,10 @@ SigSession::~SigSession()
}
ds_trigger_destroy();
stop_dso_ctrl_proc();
// TODO: This should not be necessary
_session = NULL;
// TODO: This should not be necessary
_session = NULL;
}
quint64 SigSession::get_last_sample_rate() const
@ -107,10 +112,7 @@ quint64 SigSession::get_total_sample_len() const
void SigSession::set_total_sample_len(quint64 length)
{
if (_sdi->mode == DSO)
_total_sample_len = 8 * 1024;
else
_total_sample_len = length;
_total_sample_len = length;
}
struct sr_dev_inst* SigSession::get_device() const
@ -223,12 +225,28 @@ void SigSession::start_capture(uint64_t record_length,
if (probe->enabled)
break;
}
if (!l) {
error_handler(tr("No probes enabled."));
return;
}
// Check that at least one signal channel is active under DSO mode
if (_sdi->mode == DSO) {
bool active = false;
BOOST_FOREACH(const shared_ptr<view::Signal> s, _signals)
{
assert(s);
if (s->get_active()) {
active = true;
break;
}
}
if (!active) {
error_handler(tr("No channels enabled."));
return;
}
}
// Begin the session
_sampling_thread.reset(new boost::thread(
&SigSession::sample_thread_proc, this, _sdi,
@ -464,6 +482,7 @@ void SigSession::feed_in_header(const sr_dev_inst *sdi)
uint64_t sample_rate = 0;
unsigned int logic_probe_count = 0;
unsigned int dso_probe_count = 0;
unsigned int dso_channel_count = 0;
unsigned int analog_probe_count = 0;
// Detect what data types we will receive
@ -499,20 +518,35 @@ void SigSession::feed_in_header(const sr_dev_inst *sdi)
sample_rate = g_variant_get_uint64(gvar);
g_variant_unref(gvar);
ret = sr_config_get(sdi->driver, SR_CONF_LIMIT_SAMPLES,
&gvar, sdi);
if (ret != SR_OK) {
qDebug("Failed to get total samples");
return;
}
if (g_variant_get_uint64(gvar) != 0)
_total_sample_len = g_variant_get_uint64(gvar);
g_variant_unref(gvar);
// ret = sr_config_get(sdi->driver, SR_CONF_LIMIT_SAMPLES,
// &gvar, sdi);
// if (ret != SR_OK) {
// qDebug("Failed to get total samples");
// return;
// }
// if (g_variant_get_uint64(gvar) != 0)
// _total_sample_len = g_variant_get_uint64(gvar);
// g_variant_unref(gvar);
if (sample_rate != _last_sample_rate) {
_last_sample_rate = sample_rate;
sample_rate_changed(sample_rate);
}
ret = sr_config_get(sdi->driver, SR_CONF_EN_CH0,
&gvar, sdi);
if (ret != SR_OK) {
qDebug("Failed to get ENABLE of DSO channel 0\n");
return;
}
dso_channel_count += g_variant_get_boolean(gvar);
ret = sr_config_get(sdi->driver, SR_CONF_EN_CH1,
&gvar, sdi);
if (ret != SR_OK) {
qDebug("Failed to get ENABLE of DSO channel 1\n");
return;
}
dso_channel_count += g_variant_get_boolean(gvar);
// Create data containers for the coming data snapshots
{
@ -528,7 +562,7 @@ void SigSession::feed_in_header(const sr_dev_inst *sdi)
}
if (dso_probe_count != 0) {
_dso_data.reset(new data::Dso(dso_probe_count, sample_rate));
_dso_data.reset(new data::Dso(dso_channel_count, sample_rate));
assert(_dso_data);
}
@ -693,7 +727,13 @@ void SigSession::init_signals(const sr_dev_inst *sdi)
uint64_t sample_rate = 0;
unsigned int logic_probe_count = 0;
unsigned int dso_probe_count = 0;
unsigned int dso_channel_count = 0;
unsigned int analog_probe_count = 0;
uint64_t vdiv;
uint64_t timebase;
bool coupling;
bool active;
int ret;
// Detect what data types we will receive
for (const GSList *l = sdi->probes; l; l = l->next) {
@ -719,21 +759,34 @@ void SigSession::init_signals(const sr_dev_inst *sdi)
// Read out the sample rate
assert(sdi->driver);
const int ret = sr_config_get(sdi->driver, SR_CONF_SAMPLERATE,
ret = sr_config_get(sdi->driver, SR_CONF_SAMPLERATE,
&gvar, sdi);
if (ret != SR_OK) {
qDebug("Failed to get samplerate\n");
return;
}
sample_rate = g_variant_get_uint64(gvar);
g_variant_unref(gvar);
if (sample_rate != _last_sample_rate) {
_last_sample_rate = sample_rate;
sample_rate_changed(sample_rate);
}
ret = sr_config_get(sdi->driver, SR_CONF_EN_CH0,
&gvar, sdi);
if (ret != SR_OK) {
qDebug("Failed to get ENABLE of DSO channel 0\n");
return;
}
dso_channel_count += g_variant_get_boolean(gvar);
ret = sr_config_get(sdi->driver, SR_CONF_EN_CH1,
&gvar, sdi);
if (ret != SR_OK) {
qDebug("Failed to get ENABLE of DSO channel 1\n");
return;
}
dso_channel_count += g_variant_get_boolean(gvar);
// Create data containers for the coming data snapshots
{
if (logic_probe_count != 0) {
@ -747,7 +800,7 @@ void SigSession::init_signals(const sr_dev_inst *sdi)
}
if (dso_probe_count != 0) {
_dso_data.reset(new data::Dso(dso_probe_count, sample_rate));
_dso_data.reset(new data::Dso(dso_channel_count, sample_rate));
assert(_dso_data);
}
@ -776,9 +829,68 @@ void SigSession::init_signals(const sr_dev_inst *sdi)
break;
case SR_PROBE_DSO:
if (probe->index == 0) {
ret = sr_config_get(sdi->driver, SR_CONF_VDIV0,
&gvar, sdi);
if (ret != SR_OK) {
qDebug("Failed to get VDIV of channel 0\n");
return;
}
vdiv = g_variant_get_uint64(gvar);
ret = sr_config_get(sdi->driver, SR_CONF_TIMEBASE,
&gvar, sdi);
if (ret != SR_OK) {
qDebug("Failed to get TIMEBASE\n");
return;
}
timebase = g_variant_get_uint64(gvar);
ret = sr_config_get(sdi->driver, SR_CONF_COUPLING0,
&gvar, sdi);
if (ret != SR_OK) {
qDebug("Failed to get AC COUPLING of channel 0\n");
return;
}
coupling = g_variant_get_boolean(gvar);
ret = sr_config_get(sdi->driver, SR_CONF_EN_CH0,
&gvar, sdi);
if (ret != SR_OK) {
qDebug("Failed to get ENABLE of channel 0\n");
return;
}
active = g_variant_get_boolean(gvar);
} else if (probe->index == 1) {
ret = sr_config_get(sdi->driver, SR_CONF_VDIV1,
&gvar, sdi);
if (ret != SR_OK) {
qDebug("Failed to get VDIV of channel 1\n");
return;
}
vdiv = g_variant_get_uint64(gvar);
ret = sr_config_get(sdi->driver, SR_CONF_TIMEBASE,
&gvar, sdi);
if (ret != SR_OK) {
qDebug("Failed to get TIMEBASE\n");
return;
}
timebase = g_variant_get_uint64(gvar);
ret = sr_config_get(sdi->driver, SR_CONF_COUPLING1,
&gvar, sdi);
if (ret != SR_OK) {
qDebug("Failed to get AC COUPLING of channel 1\n");
return;
}
coupling = g_variant_get_boolean(gvar);
ret = sr_config_get(sdi->driver, SR_CONF_EN_CH1,
&gvar, sdi);
if (ret != SR_OK) {
qDebug("Failed to get ENABLE of channel 1\n");
return;
}
active = g_variant_get_boolean(gvar);
}
signal = boost::shared_ptr<view::Signal>(
new view::DsoSignal(probe->name,
_dso_data, probe->index, _signals.size()));
_dso_data, probe->index, _signals.size(), vdiv, timebase, coupling, active));
break;
case SR_PROBE_ANALOG:
@ -793,6 +905,7 @@ void SigSession::init_signals(const sr_dev_inst *sdi)
signals_changed();
data_updated();
}
g_variant_unref(gvar);
}
void SigSession::update_signals(const sr_dev_inst *sdi)
@ -801,6 +914,12 @@ void SigSession::update_signals(const sr_dev_inst *sdi)
QMap<int, bool> probes_en_table;
QMap<int, bool> signals_en_table;
int index = 0;
GVariant *gvar;
uint64_t vdiv;
uint64_t timebase;
bool coupling;
bool active;
int ret;
std::vector< boost::shared_ptr<view::Signal> >::iterator i = _signals.begin();
while (i != _signals.end()) {
@ -832,9 +951,68 @@ void SigSession::update_signals(const sr_dev_inst *sdi)
break;
case SR_PROBE_DSO:
if (probe->index == 0) {
ret = sr_config_get(sdi->driver, SR_CONF_VDIV0,
&gvar, sdi);
if (ret != SR_OK) {
qDebug("Failed to get VDIV of channel 0\n");
return;
}
vdiv = g_variant_get_uint64(gvar);
ret = sr_config_get(sdi->driver, SR_CONF_TIMEBASE,
&gvar, sdi);
if (ret != SR_OK) {
qDebug("Failed to get TIMEBASE\n");
return;
}
timebase = g_variant_get_uint64(gvar);
ret = sr_config_get(sdi->driver, SR_CONF_COUPLING0,
&gvar, sdi);
if (ret != SR_OK) {
qDebug("Failed to get AC COUPLING of channel 0\n");
return;
}
coupling = g_variant_get_boolean(gvar);
ret = sr_config_get(sdi->driver, SR_CONF_EN_CH0,
&gvar, sdi);
if (ret != SR_OK) {
qDebug("Failed to get ENABLE of channel 0\n");
return;
}
active = g_variant_get_boolean(gvar);
} else if (probe->index == 1) {
ret = sr_config_get(sdi->driver, SR_CONF_VDIV1,
&gvar, sdi);
if (ret != SR_OK) {
qDebug("Failed to get VDIV of channel 1\n");
return;
}
vdiv = g_variant_get_uint64(gvar);
ret = sr_config_get(sdi->driver, SR_CONF_TIMEBASE,
&gvar, sdi);
if (ret != SR_OK) {
qDebug("Failed to get TIMEBASE\n");
return;
}
timebase = g_variant_get_uint64(gvar);
ret = sr_config_get(sdi->driver, SR_CONF_COUPLING1,
&gvar, sdi);
if (ret != SR_OK) {
qDebug("Failed to get AC COUPLING of channel 1\n");
return;
}
coupling = g_variant_get_boolean(gvar);
ret = sr_config_get(sdi->driver, SR_CONF_EN_CH1,
&gvar, sdi);
if (ret != SR_OK) {
qDebug("Failed to get ENABLE of channel 1\n");
return;
}
active = g_variant_get_boolean(gvar);
}
signal = boost::shared_ptr<view::Signal>(
new view::DsoSignal(probe->name,
_dso_data, probe->index, _signals.size()));
_dso_data, probe->index, _signals.size(), vdiv, timebase, coupling, active));
break;
case SR_PROBE_ANALOG:
@ -1245,4 +1423,92 @@ void SigSession::set_adv_trigger(bool adv_trigger)
_adv_trigger = adv_trigger;
}
/*
* oscilloscope control
*/
void SigSession::start_dso_ctrl_proc(boost::function<void (const QString)> error_handler)
{
// Begin the dso control thread
_dso_ctrl_thread.reset(new boost::thread(
&SigSession::dso_ctrl_proc, this, error_handler));
}
void SigSession::stop_dso_ctrl_proc()
{
if (_dso_ctrl_thread.get()) {
_dso_ctrl_thread->interrupt();
_dso_ctrl_thread->join();
}
_dso_ctrl_thread.reset();
}
int SigSession::set_dso_ctrl(int key)
{
int ret;
if (key== SR_CONF_TIMEBASE) {
uint64_t timebase = _signals.at(0)->get_hDialValue();
ret = sr_config_set(_sdi, key, g_variant_new_uint64(timebase));
} else if (key == SR_CONF_VDIV0) {
uint64_t vdiv = _signals.at(0)->get_vDialValue();
ret = sr_config_set(_sdi, key, g_variant_new_uint64(vdiv));
} else if (key == SR_CONF_VDIV1) {
uint64_t vdiv = _signals.at(1)->get_vDialValue();
ret = sr_config_set(_sdi, key, g_variant_new_uint64(vdiv));
} else if (key == SR_CONF_COUPLING0) {
bool acdc = _signals.at(0)->get_acCoupling();
ret = sr_config_set(_sdi, key, g_variant_new_boolean(acdc));
} else if (key == SR_CONF_COUPLING1) {
bool acdc = _signals.at(1)->get_acCoupling();
ret = sr_config_set(_sdi, key, g_variant_new_boolean(acdc));
} else if (key == SR_CONF_EN_CH0) {
bool enable = _signals.at(0)->get_active();
ret = sr_config_set(_sdi, key, g_variant_new_boolean(enable));
dso_ch_changed(get_dso_ch_num());
} else if (key == SR_CONF_EN_CH1) {
bool enable = _signals.at(1)->get_active();
ret = sr_config_set(_sdi, key, g_variant_new_boolean(enable));
dso_ch_changed(get_dso_ch_num());
}
return ret;
}
uint16_t SigSession::get_dso_ch_num()
{
uint16_t num_channels = 0;
BOOST_FOREACH(const shared_ptr<view::Signal> s, _signals)
{
assert(s);
if (s->get_active()) {
num_channels++;
}
}
return num_channels;
}
void SigSession::dso_ctrl_proc(boost::function<void (const QString)> error_handler)
{
(void)error_handler;
try {
while(_session) {
if (!_sdi) {
// do nothing
} else if (strcmp(_sdi->driver->name, "Demo") == 0) {
} else if (strcmp(_sdi->driver->name, "DSLogic") == 0) {
}
boost::this_thread::sleep(boost::posix_time::millisec(100));
}
} catch(...) {
qDebug("Interrupt exception for oscilloscope control thread was thrown.");
}
qDebug("Oscilloscope control thread exit!");
}
} // namespace pv

View File

@ -157,38 +157,41 @@ public:
void set_adv_trigger(bool adv_trigger);
void start_dso_ctrl_proc(boost::function<void (const QString)> error_handler);
void stop_dso_ctrl_proc();
int set_dso_ctrl(int key);
uint16_t get_dso_ch_num();
private:
void set_capture_state(capture_state state);
private:
// thread for sample/load
void load_thread_proc(const std::string name,
boost::function<void (const QString)> error_handler);
void sample_thread_proc(struct sr_dev_inst *sdi,
uint64_t record_length,
boost::function<void (const QString)> error_handler);
// data feed
void feed_in_header(const sr_dev_inst *sdi);
void feed_in_meta(const sr_dev_inst *sdi,
const sr_datafeed_meta &meta);
void feed_in_trigger(const ds_trigger_pos &trigger_pos);
void feed_in_trigger(const ds_trigger_pos &trigger_pos);
void feed_in_logic(const sr_datafeed_logic &logic);
void feed_in_dso(const sr_datafeed_dso &dso);
void feed_in_dso(const sr_datafeed_dso &dso);
void feed_in_analog(const sr_datafeed_analog &analog);
void data_feed_in(const struct sr_dev_inst *sdi,
const struct sr_datafeed_packet *packet);
static void data_feed_in_proc(const struct sr_dev_inst *sdi,
const struct sr_datafeed_packet *packet, void *cb_data);
const struct sr_datafeed_packet *packet);
static void data_feed_in_proc(const struct sr_dev_inst *sdi,
const struct sr_datafeed_packet *packet, void *cb_data);
void hotplug_proc(boost::function<void (const QString)> error_handler);
static int hotplug_callback(struct libusb_context *ctx, struct libusb_device *dev,
libusb_hotplug_event event, void *user_data);
void dso_ctrl_proc(boost::function<void (const QString)> error_handler);
private:
DeviceManager &_device_manager;
@ -232,6 +235,11 @@ private:
bool _adv_trigger;
bool _vDial_changed;
bool _hDial_changed;
uint16_t _dso_ctrl_channel;
std::auto_ptr<boost::thread> _dso_ctrl_thread;
signals:
void capture_state_changed(int state);
@ -250,6 +258,8 @@ signals:
void receive_trigger(quint64 trigger_pos);
void dso_ch_changed(uint16_t num);
public slots:

View File

@ -31,6 +31,7 @@
#include <QAction>
#include <QDebug>
#include <QMessageBox>
#include "devicebar.h"
@ -123,11 +124,11 @@ void DeviceBar::on_configure()
pv::dialogs::DeviceOptions dlg(this, sdi);
ret = dlg.exec();
if (ret == QDialog::Accepted) {
//if (dlg.exec()) {
if (dev_mode != sdi->mode)
device_selected();
else
device_updated();
if (dev_mode != sdi->mode) {
device_selected();
} else {
device_updated();
}
}
}

View File

@ -54,7 +54,6 @@ public:
signals:
void device_selected();
void device_updated();
private slots:

View File

@ -165,12 +165,41 @@ uint64_t SamplingBar::get_record_length() const
return _record_length_selector.itemData(index).value<uint64_t>();
}
void SamplingBar::set_record_length(uint64_t length)
{
for (int i = 0; i < _record_length_selector.count(); i++) {
if (length == _record_length_selector.itemData(
i).value<uint64_t>()) {
_record_length_selector.setCurrentIndex(i);
break;
}
}
}
void SamplingBar::set_sampling(bool sampling)
{
_run_stop_button.setIcon(sampling ? _icon_stop : _icon_start);
//_run_stop_button.setText(sampling ? " Stop" : "Start");
}
void SamplingBar::set_sample_rate(uint64_t sample_rate)
{
for (int i = 0; i < _sample_rate_list.count(); i++) {
if (sample_rate == _sample_rate_list.itemData(
i).value<uint64_t>()) {
_sample_rate_list.setCurrentIndex(i);
// Set the samplerate
if (sr_config_set(_sdi, SR_CONF_SAMPLERATE,
g_variant_new_uint64(sample_rate)) != SR_OK) {
qDebug() << "Failed to configure samplerate.";
return;
}
break;
}
}
}
void SamplingBar::update_sample_rate_selector()
{
GVariant *gvar_dict, *gvar_list;
@ -280,7 +309,7 @@ void SamplingBar::commit_sample_rate()
return;
}
if (strcmp(_sdi->driver->name, "DSLogic") == 0) {
if (strcmp(_sdi->driver->name, "DSLogic") == 0 && _sdi->mode != DSO) {
if ((last_sample_rate == SR_MHZ(200)&& sample_rate != SR_MHZ(200)) ||
(last_sample_rate != SR_MHZ(200) && sample_rate == SR_MHZ(200)) ||
(last_sample_rate == SR_MHZ(400)&& sample_rate != SR_MHZ(400)) ||

View File

@ -54,9 +54,11 @@ public:
SamplingBar(QWidget *parent);
uint64_t get_record_length() const;
void set_record_length(uint64_t length);
void set_sampling(bool sampling);
void update_sample_rate_selector();
void set_sample_rate(uint64_t sample_rate);
void set_device(struct sr_dev_inst *sdi);

View File

@ -0,0 +1,110 @@
#include "dsldial.h"
#include <assert.h>
namespace pv {
namespace view {
dslDial::dslDial(quint64 div, quint64 step,
QVector<quint64> value, QVector<QString> unit)
{
assert(div > 0);
assert(step > 0);
assert((quint64)value.count() == div);
assert(unit.count() > 0);
_div = div;
_step = step;
_value = value;
_unit = unit;
_sel = 0;
}
dslDial::~dslDial()
{
}
void dslDial::paint(QPainter &p, QRectF dialRect, QColor dialColor)
{
p.setRenderHint(QPainter::Antialiasing, true);
p.setPen(dialColor);
p.setBrush(dialColor);
int dialStartAngle = 225 * 16;
int dialSpanAngle = -270 * 16;
// draw dial arc
p.drawArc(dialRect, dialStartAngle, dialSpanAngle);
// draw ticks
p.save();
p.translate(dialRect.center());
p.rotate(45);
for (quint64 i = 0; i < _div; i++) {
// draw major ticks
p.drawLine(0, dialRect.width()/2+3, 0, dialRect.width()/2+8);
// draw minor ticks
for (quint64 j = 0; (j < 5) && (i < _div - 1); j++) {
p.drawLine(0, dialRect.width()/2+3, 0, dialRect.width()/2+5);
p.rotate(54.0/(_div-1));
}
}
// draw pointer
p.rotate(90+270.0/(_div-1)*_sel);
p.drawEllipse(-3, -3, 6, 6);
p.drawLine(3, 0, 0, dialRect.width()/2-3);
p.drawLine(-3, 0, 0, dialRect.width()/2-3);
p.restore();
// draw value
quint64 displayValue = _value[_sel];
quint64 displayIndex = 0;
while(displayValue / _step >= 1) {
displayValue = displayValue / _step;
displayIndex++;
}
QString pText = QString::number(displayValue) + _unit[displayIndex] + "/div";
QFontMetrics fm(p.font());
p.drawText(QRectF(dialRect.left(), dialRect.bottom()-dialRect.width()*0.3+fm.height()*0.5, dialRect.width(), fm.height()), Qt::AlignCenter, pText);
}
void dslDial::set_sel(quint64 sel)
{
assert(sel < _div);
_sel = sel;
}
quint64 dslDial::get_sel()
{
return _sel;
}
bool dslDial::isMin()
{
if(_sel == 0)
return true;
else
return false;
}
bool dslDial::isMax()
{
if(_sel == _div - 1)
return true;
else
return false;
}
quint64 dslDial::get_value()
{
return _value[_sel];
}
bool dslDial::set_value(quint64 value)
{
assert(_value.contains(value));
_sel = _value.indexOf(value, 0);
}
} // namespace view
} // namespace pv

View File

@ -0,0 +1,48 @@
#ifndef DSLOGIC_PV_VIEW_DSLDIAL_H
#define DSLOGIC_PV_VIEW_DSLDIAL_H
#include <QRect>
#include <QPainter>
namespace pv {
namespace view {
class dslDial
{
public:
dslDial(quint64 div, quint64 step,
QVector<quint64> value, QVector<QString> unit);
virtual ~dslDial();
public:
/**
* Paints the dial with a QPainter
* @param p the QPainter to paint into.
* @param dialRect the rectangle to draw the dial at.
**/
void paint(QPainter &p, QRectF dialRect, QColor dialColor);
// set/get current select
void set_sel(quint64 sel);
quint64 get_sel();
// boundary detection
bool isMin();
bool isMax();
// get current value
quint64 get_value();
bool set_value(quint64 value);
private:
quint64 _div;
quint64 _step;
QVector<quint64> _value;
QVector<QString> _unit;
quint64 _sel;
};
} // namespace view
} // namespace pv
#endif // DSLOGIC_PV_VIEW_DSLDIAL_H

View File

@ -35,21 +35,26 @@ namespace pv {
namespace view {
const QColor DsoSignal::SignalColours[4] = {
QColor(17, 133, 209, 255), // dsBlue
QColor(238, 178, 17, 255), // dsYellow
QColor(213, 15, 37, 255), // dsRed
QColor(0, 153, 37, 255) // dsGreen
QColor(238, 178, 17, 200), // dsYellow
QColor(0, 153, 37, 200), // dsGreen
QColor(213, 15, 37, 200), // dsRed
QColor(17, 133, 209, 200) // dsBlue
};
const float DsoSignal::EnvelopeThreshold = 256.0f;
DsoSignal::DsoSignal(QString name, boost::shared_ptr<data::Dso> data,
int probe_index, int order) :
int probe_index, int order, uint64_t vdiv, uint64_t timebase, bool coupling, bool active) :
Signal(name, probe_index, DS_DSO, order),
_data(data)
{
_colour = SignalColours[probe_index % countof(SignalColours)];
_scale = _signalHeight * 1.0f / 256;
_scale = _windowHeight * 1.0f / 256;
_vDial->set_value(vdiv);
_hDial->set_value(timebase);
_acCoupling = coupling;
_active = active;
}
DsoSignal::~DsoSignal()
@ -76,28 +81,27 @@ void DsoSignal::set_scale(float scale)
}
void DsoSignal::paint(QPainter &p, int y, int left, int right, double scale,
double offset)
double offset)
{
assert(scale > 0);
assert(_data);
assert(right >= left);
//paint_axis(p, y, left, right);
const deque< boost::shared_ptr<pv::data::DsoSnapshot> > &snapshots =
_data->get_snapshots();
if (snapshots.empty())
return;
_scale = _signalHeight * 1.0f / 256;
_scale = _windowHeight * 1.0f / 256;
const boost::shared_ptr<pv::data::DsoSnapshot> &snapshot =
snapshots.front();
if ((unsigned int)get_index() >= snapshot->get_channel_num())
const uint16_t number_channels = snapshot->get_channel_num();
if ((unsigned int)get_index() >= number_channels)
return;
const double pixels_offset = offset / scale;
const double samplerate = _data->get_samplerate();
const double samplerate = _data->get_samplerate();
const double start_time = _data->get_start_time();
const int64_t last_sample = max((int64_t)(snapshot->get_sample_count() - 1), (int64_t)0);
const double samples_per_pixel = samplerate * scale;
@ -112,7 +116,7 @@ void DsoSignal::paint(QPainter &p, int y, int left, int right, double scale,
if (samples_per_pixel < EnvelopeThreshold)
paint_trace(p, snapshot, y, left,
start_sample, end_sample,
pixels_offset, samples_per_pixel);
pixels_offset, samples_per_pixel, number_channels);
else
paint_envelope(p, snapshot, y, left,
start_sample, end_sample,
@ -121,13 +125,13 @@ void DsoSignal::paint(QPainter &p, int y, int left, int right, double scale,
void DsoSignal::paint_trace(QPainter &p,
const boost::shared_ptr<pv::data::DsoSnapshot> &snapshot,
int y, int left, const int64_t start, const int64_t end,
const double pixels_offset, const double samples_per_pixel)
int y, int left, const int64_t start, const int64_t end,
const double pixels_offset, const double samples_per_pixel, uint64_t num_channels)
{
const int64_t sample_count = end - start;
if (sample_count > 0) {
const uint16_t *const samples = snapshot->get_samples(start, end);
const uint8_t *const samples = snapshot->get_samples(start, end, get_index());
assert(samples);
p.setPen(_colour);
@ -136,11 +140,11 @@ void DsoSignal::paint_trace(QPainter &p,
QPointF *points = new QPointF[sample_count];
QPointF *point = points;
for (int64_t sample = start; sample != end; sample++) {
for (int64_t sample = start; sample < end; sample++) {
const float x = (sample / samples_per_pixel - pixels_offset) + left;
uint16_t offset = samples[sample - start];
uint8_t offset = samples[(sample - start)*num_channels];
*point++ = QPointF(x,
y - ((get_index() == 0) ? offset & 0x00ff : offset >> 8) * _scale);
y - offset * _scale);
}
p.drawPolyline(points, point - points);

View File

@ -47,7 +47,8 @@ private:
public:
DsoSignal(QString name,
boost::shared_ptr<pv::data::Dso> data, int probe_index, int order);
boost::shared_ptr<pv::data::Dso> data, int probe_index, int order,
uint64_t vdiv, uint64_t timebase, bool coupling, bool active);
virtual ~DsoSignal();
@ -63,8 +64,8 @@ public:
* @param offset the time to show at the left hand edge of
* the view in seconds.
**/
void paint(QPainter &p, int y, int left, int right, double scale,
double offset);
void paint(QPainter &p, int y, int left, int right, double scale,
double offset);
const std::vector< std::pair<uint64_t, bool> > cur_edges() const;
@ -83,7 +84,8 @@ private:
void paint_trace(QPainter &p,
const boost::shared_ptr<pv::data::DsoSnapshot> &snapshot,
int y, int left, const int64_t start, const int64_t end,
const double pixels_offset, const double samples_per_pixel);
const double pixels_offset, const double samples_per_pixel,
uint64_t num_channels);
void paint_envelope(QPainter &p,
const boost::shared_ptr<pv::data::DsoSnapshot> &snapshot,

View File

@ -50,7 +50,7 @@ GroupSignal::GroupSignal(QString name, boost::shared_ptr<data::Group> data,
_data(data)
{
_colour = SignalColours[probe_index_list.front() % countof(SignalColours)];
_scale = _signalHeight * 1.0f / std::pow(2.0, static_cast<double>(probe_index_list.size()));
_scale = _signalHeight * 1.0f / pow(2, probe_index_list.size());
}
GroupSignal::~GroupSignal()
@ -77,13 +77,13 @@ void GroupSignal::set_scale(float scale)
}
void GroupSignal::paint(QPainter &p, int y, int left, int right, double scale,
double offset)
double offset)
{
assert(scale > 0);
assert(_data);
assert(right >= left);
_scale = _signalHeight * 1.0f / std::pow(2.0, static_cast<int>(_index_list.size()));
_scale = _signalHeight * 1.0f / pow(2, _index_list.size());
paint_axis(p, y, left, right);
const deque< boost::shared_ptr<pv::data::GroupSnapshot> > &snapshots =

View File

@ -39,6 +39,7 @@
#include <QPainter>
#include <QRect>
#include <QStyleOption>
#include <QMessageBox>
using namespace boost;
using namespace std;
@ -46,14 +47,6 @@ using namespace std;
namespace pv {
namespace view {
const int Header::COLOR = 1;
const int Header::NAME = 2;
const int Header::POSTRIG = 3;
const int Header::HIGTRIG = 4;
const int Header::NEGTRIG = 5;
const int Header::LOWTRIG = 6;
const int Header::LABEL = 7;
Header::Header(View &parent) :
QWidget(&parent),
_view(parent),
@ -90,7 +83,7 @@ int Header::get_nameEditWidth()
return 0;
}
boost::shared_ptr<pv::view::Signal> Header::get_mouse_over_signal(
boost::shared_ptr<pv::view::Signal> Header::get_mSig(
int &action,
const QPoint &pt)
{
@ -185,17 +178,18 @@ void Header::mousePressEvent(QMouseEvent *event)
make_pair(s, s->get_v_offset()));
// Select the signal if it has been clicked
const boost::shared_ptr<Signal> mouse_over_signal =
get_mouse_over_signal(action, event->pos());
if (action == COLOR && mouse_over_signal) {
const boost::shared_ptr<Signal> mSig =
get_mSig(action, event->pos());
if (action == Signal::COLOR && mSig) {
_colorFlag = true;
} else if (action == NAME && mouse_over_signal) {
} else if (action == Signal::NAME && mSig) {
_nameFlag = true;
} else if (action == LABEL && mouse_over_signal) {
if (mouse_over_signal->selected())
mouse_over_signal->select(false);
} else if (action == Signal::LABEL && mSig) {
if (mSig->selected())
mSig->select(false);
else {
mouse_over_signal->select(true);
if (mSig->get_type() != Signal::DS_DSO)
mSig->select(true);
if (~QApplication::keyboardModifiers() &
Qt::ControlModifier)
@ -204,37 +198,91 @@ void Header::mousePressEvent(QMouseEvent *event)
// Add the signal to the drag list
if (event->button() & Qt::LeftButton)
_drag_sigs.push_back(
make_pair(mouse_over_signal,
mouse_over_signal->get_v_offset()));
make_pair(mSig,
(mSig->get_type() == Signal::DS_DSO) ? mSig->get_zeroPos() : mSig->get_v_offset()));
}
mouse_over_signal->set_old_v_offset(mouse_over_signal->get_v_offset());
} else if (action == POSTRIG && mouse_over_signal) {
if (mouse_over_signal->get_trig() == POSTRIG)
mouse_over_signal->set_trig(0);
mSig->set_old_v_offset(mSig->get_v_offset());
} else if (action == Signal::POSTRIG && mSig) {
if (mSig->get_trig() == Signal::POSTRIG)
mSig->set_trig(0);
else
mouse_over_signal->set_trig(POSTRIG);
} else if (action == HIGTRIG && mouse_over_signal) {
if (mouse_over_signal->get_trig() == HIGTRIG)
mouse_over_signal->set_trig(0);
mSig->set_trig(Signal::POSTRIG);
} else if (action == Signal::HIGTRIG && mSig) {
if (mSig->get_trig() == Signal::HIGTRIG)
mSig->set_trig(0);
else
mouse_over_signal->set_trig(HIGTRIG);
} else if (action == NEGTRIG && mouse_over_signal) {
if (mouse_over_signal->get_trig() == NEGTRIG)
mouse_over_signal->set_trig(0);
mSig->set_trig(Signal::HIGTRIG);
} else if (action == Signal::NEGTRIG && mSig) {
if (mSig->get_trig() == Signal::NEGTRIG)
mSig->set_trig(0);
else
mouse_over_signal->set_trig(NEGTRIG);
} else if (action == LOWTRIG && mouse_over_signal) {
if (mouse_over_signal->get_trig() == LOWTRIG)
mouse_over_signal->set_trig(0);
mSig->set_trig(Signal::NEGTRIG);
} else if (action == Signal::LOWTRIG && mSig) {
if (mSig->get_trig() == Signal::LOWTRIG)
mSig->set_trig(0);
else
mouse_over_signal->set_trig(LOWTRIG);
mSig->set_trig(Signal::LOWTRIG);
} else if (action == Signal::EDGETRIG && mSig) {
if (mSig->get_trig() == Signal::EDGETRIG)
mSig->set_trig(0);
else
mSig->set_trig(Signal::EDGETRIG);
} else if (action == Signal::VDIAL && mSig) {
BOOST_FOREACH(const shared_ptr<Signal> s, sigs) {
s->set_hDialActive(false);
if (s != mSig) {
s->set_vDialActive(false);
}
}
mSig->set_vDialActive(!mSig->get_vDialActive());
} else if (action == Signal::HDIAL && mSig) {
if (mSig->get_hDialActive()) {
BOOST_FOREACH(const shared_ptr<Signal> s, sigs) {
s->set_vDialActive(false);
s->set_hDialActive(false);
}
} else {
BOOST_FOREACH(const shared_ptr<Signal> s, sigs) {
s->set_vDialActive(false);
s->set_hDialActive(true);
}
}
} else if (action == Signal::CHEN && mSig) {
int channel;
if (mSig->get_index() == 0) {
bool last = 1;
channel = 0;
BOOST_FOREACH(const shared_ptr<Signal> s, sigs) {
if (s->get_index() != 0 && s->get_active()) {
QMessageBox msg(this);
msg.setText("Tips");
msg.setInformativeText("If only one channel want, Channel0 has a higher maximum sample rate!");
msg.setStandardButtons(QMessageBox::Ok);
msg.setIcon(QMessageBox::Information);
msg.exec();
s->set_active(!s->get_active());
last = 0;
channel = s->get_index();
break;
}
}
if (last)
mSig->set_active(!mSig->get_active());
} else {
mSig->set_active(!mSig->get_active());
channel = mSig->get_index();
}
ch_changed(channel);
} else if (action == Signal::ACDC && mSig) {
mSig->set_acCoupling(!mSig->get_acCoupling());
acdc_changed(mSig->get_index());
}
if (~QApplication::keyboardModifiers() & Qt::ControlModifier) {
// Unselect all other signals because the Ctrl is not
// pressed
BOOST_FOREACH(const boost::shared_ptr<Signal> s, sigs)
if (s != mouse_over_signal)
if (s != mSig)
s->select(false);
}
update();
@ -247,15 +295,15 @@ void Header::mouseReleaseEvent(QMouseEvent *event)
// judge for color / name / trigger / move
int action;
const boost::shared_ptr<Signal> mouse_over_signal =
get_mouse_over_signal(action, event->pos());
if (mouse_over_signal){
if (action == COLOR && _colorFlag) {
_context_signal = mouse_over_signal;
const boost::shared_ptr<Signal> mSig =
get_mSig(action, event->pos());
if (mSig){
if (action == Signal::COLOR && _colorFlag) {
_context_signal = mSig;
changeColor(event);
_view.set_need_update(true);
} else if (action == NAME && _nameFlag) {
_context_signal = mouse_over_signal;
} else if (action == Signal::NAME && _nameFlag) {
_context_signal = mSig;
changeName(event);
}
}
@ -270,6 +318,42 @@ void Header::mouseReleaseEvent(QMouseEvent *event)
_view.normalize_layout();
}
void Header::wheelEvent(QWheelEvent *event)
{
assert(event);
if (event->orientation() == Qt::Vertical) {
const vector< shared_ptr<Signal> > sigs(
_view.session().get_signals());
// Vertical scrolling
double shift = event->delta() / 20.0;
if (shift > 1.0) {
BOOST_FOREACH(const shared_ptr<Signal> s, sigs) {
if (s->get_vDialActive()) {
if(s->go_vDialNext())
vDial_changed(s->get_index());
break;
} else if (s->get_hDialActive()) {
if(s->go_hDialNext())
hDial_changed(0);
}
}
} else if (shift < -1.0) {
BOOST_FOREACH(const shared_ptr<Signal> s, sigs) {
if (s->get_vDialActive()) {
if(s->go_vDialPre())
vDial_changed(s->get_index());
break;
} else if (s->get_hDialActive()) {
if(s->go_hDialPre())
hDial_changed(0);
}
}
}
update();
}
}
void Header::move(QMouseEvent *event)
{
bool _moveValid = false;
@ -439,24 +523,31 @@ void Header::mouseMoveEvent(QMouseEvent *event)
i != _drag_sigs.end(); i++) {
const boost::shared_ptr<Signal> sig((*i).first);
if (sig) {
const int y = (*i).second + delta;
const int y_snap =
((y + View::SignalSnapGridSize / 2) /
View::SignalSnapGridSize) *
View::SignalSnapGridSize;
if (y_snap != sig->get_v_offset()) {
_moveFlag = true;
sig->set_v_offset(y_snap);
int y = (*i).second + delta;
if (sig->get_type() != Signal::DS_DSO) {
const int y_snap =
((y + View::SignalSnapGridSize / 2) /
View::SignalSnapGridSize) *
View::SignalSnapGridSize;
if (y_snap != sig->get_v_offset()) {
_moveFlag = true;
sig->set_v_offset(y_snap);
}
// Ensure the signal is selected
sig->select(true);
} else {
if (y < 0)
y = 0;
else if (y > height())
y = height();
sig->set_zeroPos(y);
sig->select(false);
signals_moved();
}
// Ensure the signal is selected
sig->select(true);
}
}
//signals_moved();
}
update();
}
@ -470,10 +561,9 @@ void Header::contextMenuEvent(QContextMenuEvent *event)
{
int action;
const boost::shared_ptr<Signal> s = get_mouse_over_signal(action, _mouse_point);
const boost::shared_ptr<Signal> s = get_mSig(action, _mouse_point);
//if (!s || action != LABEL)
if (!s || !s->selected() || action != LABEL)
if (!s || !s->selected() || action != Signal::LABEL)
return;
QMenu menu(this);

View File

@ -47,16 +47,7 @@ public:
Header(View &parent);
private:
static const int COLOR;
static const int NAME;
static const int POSTRIG;
static const int HIGTRIG;
static const int NEGTRIG;
static const int LOWTRIG;
static const int LABEL;
private:
boost::shared_ptr<pv::view::Signal> get_mouse_over_signal(
boost::shared_ptr<pv::view::Signal> get_mSig(
int &action,
const QPoint &pt);
@ -65,13 +56,10 @@ private:
private:
void mousePressEvent(QMouseEvent * event);
void mouseReleaseEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent *event);
void leaveEvent(QEvent *event);
void wheelEvent(QWheelEvent *event);
void contextMenuEvent(QContextMenuEvent *event);
void move(QMouseEvent *event);
@ -93,8 +81,11 @@ private slots:
signals:
void signals_moved();
void header_updated();
void vDial_changed(quint16);
void hDial_changed(quint16);
void acdc_changed(quint16);
void ch_changed(quint16);
private:
View &_view;

View File

@ -33,26 +33,67 @@
namespace pv {
namespace view {
const int Signal::SquareWidth = 20;
const int Signal::Margin = 5;
const int Signal::COLOR = 1;
const int Signal::NAME = 2;
const int Signal::POSTRIG = 3;
const int Signal::HIGTRIG = 4;
const int Signal::NEGTRIG = 5;
const int Signal::LOWTRIG = 6;
const int Signal::LABEL = 7;
const QColor Signal::dsBlue = QColor(17, 133, 209, 255);
const QColor Signal::dsYellow = QColor(238, 178, 17, 255);
const QColor Signal::dsRed = QColor(213, 15, 37, 255);
const QColor Signal::dsGreen = QColor(0, 153, 37, 255);
const QColor Signal::dsGray = QColor(0x88, 0x8A, 0x85, 100);
const QColor Signal::dsDisable = QColor(0x88, 0x8A, 0x85, 200);
const QColor Signal::dsActive = QColor(17, 133, 209, 255);
const QColor Signal::dsLightBlue = QColor(17, 133, 209, 150);
const QColor Signal::dsLightRed = QColor(213, 15, 37, 150);
const QPen Signal::SignalAxisPen = QColor(128, 128, 128, 64);
const QPen Signal::SignalAxisPen(QColor(128, 128, 128, 64));
const uint64_t Signal::vDialValue[Signal::vDialValueCount] = {
5,
10,
20,
50,
100,
200,
500,
1000,
2000,
5000,
};
const QString Signal::vDialUnit[Signal::vDialUnitCount] = {
"mv",
"v",
};
const uint64_t Signal::hDialValue[Signal::hDialValueCount] = {
10,
20,
50,
100,
200,
500,
1000,
2000,
5000,
10000,
20000,
50000,
100000,
200000,
500000,
1000000,
2000000,
5000000,
10000000,
20000000,
50000000,
100000000,
200000000,
500000000,
1000000000,
};
const QString Signal::hDialUnit[Signal::hDialUnitCount] = {
"ns",
"us",
"ms",
"s",
};
Signal::Signal(QString name, int index, int type, int order) :
_type(type),
@ -62,9 +103,37 @@ Signal::Signal(QString name, int index, int type, int order) :
_v_offset(0),
_signalHeight(30),
_selected(false),
_trig(0)
_trig(0),
_vDialActive(false),
_hDialActive(false),
_acCoupling(false),
_active(true),
_windowHeight(0)
{
_index_list.push_back(index);
if (_type == DS_DSO) {
QVector<uint64_t> vValue;
QVector<QString> vUnit;
QVector<uint64_t> hValue;
QVector<QString> hUnit;
for(quint64 i = 0; i < Signal::vDialValueCount; i++)
vValue.append(Signal::vDialValue[i]);
for(quint64 i = 0; i < Signal::vDialUnitCount; i++)
vUnit.append(Signal::vDialUnit[i]);
for(quint64 i = 0; i < Signal::hDialValueCount; i++)
hValue.append(Signal::hDialValue[i]);
for(quint64 i = 0; i < Signal::hDialUnitCount; i++)
hUnit.append(Signal::hDialUnit[i]);
_vDial = new dslDial(vDialValueCount, vDialValueStep, vValue, vUnit);
_hDial = new dslDial(hDialValueCount, hDialValueStep, hValue, hUnit);
_vDial->set_sel(0);
_hDial->set_sel(0);
_trig_vpos = 0;
_trig_en = true;
}
}
Signal::Signal(QString name, std::list<int> index_list, int type, int order, int sec_index) :
@ -76,8 +145,32 @@ Signal::Signal(QString name, std::list<int> index_list, int type, int order, int
_v_offset(0),
_signalHeight(30),
_selected(false),
_trig(0)
_trig(0),
_vDialActive(false),
_hDialActive(false),
_acCoupling(false),
_active(true)
{
if (_type == DS_DSO) {
QVector<uint64_t> vValue;
QVector<QString> vUnit;
QVector<uint64_t> hValue;
QVector<QString> hUnit;
for(quint64 i = 0; i < Signal::vDialValueCount; i++)
vValue.append(Signal::vDialValue[i]);
for(quint64 i = 0; i < Signal::vDialUnitCount; i++)
vUnit.append(Signal::vDialUnit[i]);
for(quint64 i = 0; i < Signal::hDialValueCount; i++)
hValue.append(Signal::hDialValue[i]);
for(quint64 i = 0; i < Signal::hDialUnitCount; i++)
hUnit.append(Signal::hDialUnit[i]);
_vDial = new dslDial(Signal::vDialValueCount, Signal::vDialValueStep, vValue, vUnit);
_hDial = new dslDial(Signal::hDialValueCount, Signal::hDialValueStep, hValue, hUnit);
_vDial->set_sel(0);
_hDial->set_sel(0);
}
}
int Signal::get_type() const
@ -104,7 +197,7 @@ int Signal::get_leftWidth() const
int Signal::get_rightWidth() const
{
return 2 * Margin + 4 * SquareWidth + 1.5 * SquareWidth;
return 2 * Margin + SquareNum * SquareWidth + 1.5 * SquareWidth;
}
int Signal::get_headerHeight() const
@ -217,31 +310,174 @@ void Signal::set_trig(int trig)
ds_trigger_probe_set(_index_list.front(), 'F', 'X');
else if (trig == LOWTRIG)
ds_trigger_probe_set(_index_list.front(), '0', 'X');
else if (trig == EDGETRIG)
ds_trigger_probe_set(_index_list.front(), 'C', 'X');
}
bool Signal::get_vDialActive() const
{
return _vDialActive;
}
void Signal::set_vDialActive(bool active)
{
_vDialActive = active;
}
bool Signal::go_vDialPre()
{
assert(_type == DS_DSO);
if (!_vDial->isMin()) {
_vDial->set_sel(_vDial->get_sel() - 1);
return true;
} else {
return false;
}
}
bool Signal::go_vDialNext()
{
assert(_type == DS_DSO);
if (!_vDial->isMax()) {
_vDial->set_sel(_vDial->get_sel() + 1);
return true;
} else {
return false;
}
}
bool Signal::get_hDialActive() const
{
return _hDialActive;
}
void Signal::set_hDialActive(bool active)
{
_hDialActive = active;
}
bool Signal::go_hDialPre()
{
assert(_type == DS_DSO);
if (!_hDial->isMin()) {
_hDial->set_sel(_hDial->get_sel() - 1);
return true;
} else {
return false;
}
}
bool Signal::go_hDialNext()
{
assert(_type == DS_DSO);
if (!_hDial->isMax()) {
_hDial->set_sel(_hDial->get_sel() + 1);
return true;
} else {
return false;
}
}
uint64_t Signal::get_vDialValue() const
{
return _vDial->get_value();
}
uint64_t Signal::get_hDialValue() const
{
return _hDial->get_value();
}
uint16_t Signal::get_vDialSel() const
{
return _vDial->get_sel();
}
uint16_t Signal::get_hDialSel() const
{
return _hDial->get_sel();
}
bool Signal::get_acCoupling() const
{
return _acCoupling;
}
void Signal::set_acCoupling(bool coupling)
{
_acCoupling = coupling;
}
bool Signal::get_active() const
{
return _active;
}
void Signal::set_active(bool active)
{
_active = active;
}
int Signal::get_zeroPos() const
{
return _zeroPos;
}
void Signal::set_zeroPos(int pos)
{
_zeroPos = pos;
}
int Signal::get_windowHeight() const
{
return _windowHeight;
}
void Signal::set_windowHeight(int height)
{
_windowHeight = height;
}
int Signal::get_trig_vpos() const
{
return _trig_vpos;
}
void Signal::set_trig_vpos(int value)
{
_trig_vpos = value;
}
void Signal::paint_label(QPainter &p, int y, int right, bool hover, int action)
{
compute_text_size(p);
const QRectF color_rect = get_rect("color", y, right);
const QRectF name_rect = get_rect("name", y, right);
const QRectF posTrig_rect = get_rect("posTrig", y, right);
const QRectF higTrig_rect = get_rect("higTrig", y, right);
const QRectF negTrig_rect = get_rect("negTrig", y, right);
const QRectF lowTrig_rect = get_rect("lowTrig", y, right);
const QRectF label_rect = get_rect("label", y, right);
const QRectF label_rect = get_rect("label", (_type == DS_DSO) ? _zeroPos : y, right);
p.setRenderHint(QPainter::Antialiasing);
// Paint the ColorButton
p.setPen(Qt::transparent);
p.setBrush(_colour);
p.setBrush(_active ? _colour : dsDisable);
p.drawRect(color_rect);
// Paint the signal name
p.setPen(Qt::black);
p.setPen(_active ? Qt::black : dsDisable);
p.drawText(name_rect, Qt::AlignLeft | Qt::AlignVCenter, _name);
// Paint the trigButton
if (_type == DS_LOGIC) {
if (_type == DS_LOGIC) {
const QRectF posTrig_rect = get_rect("posTrig", y, right);
const QRectF higTrig_rect = get_rect("higTrig", y, right);
const QRectF negTrig_rect = get_rect("negTrig", y, right);
const QRectF lowTrig_rect = get_rect("lowTrig", y, right);
const QRectF edgeTrig_rect = get_rect("edgeTrig", y, right);
p.setPen(Qt::transparent);
p.setBrush(((hover && action == POSTRIG) || (_trig == POSTRIG)) ?
dsYellow :
@ -259,6 +495,10 @@ void Signal::paint_label(QPainter &p, int y, int right, bool hover, int action)
dsYellow :
dsBlue);
p.drawRect(lowTrig_rect);
p.setBrush(((hover && action == EDGETRIG) || (_trig == EDGETRIG)) ?
dsYellow :
dsBlue);
p.drawRect(edgeTrig_rect);
p.setPen(QPen(Qt::blue, 1, Qt::DotLine));
p.setBrush(Qt::transparent);
@ -268,6 +508,8 @@ void Signal::paint_label(QPainter &p, int y, int right, bool hover, int action)
higTrig_rect.right(), higTrig_rect.bottom() - 3);
p.drawLine(negTrig_rect.right(), negTrig_rect.top() + 3,
negTrig_rect.right(), negTrig_rect.bottom() - 3);
p.drawLine(lowTrig_rect.right(), lowTrig_rect.top() + 3,
lowTrig_rect.right(), lowTrig_rect.bottom() - 3);
p.setPen(QPen(Qt::white, 2, Qt::SolidLine));
p.setBrush(Qt::transparent);
@ -290,6 +532,17 @@ void Signal::paint_label(QPainter &p, int y, int right, bool hover, int action)
p.drawLine(lowTrig_rect.left() + 5, lowTrig_rect.bottom() - 5,
lowTrig_rect.right() - 5, lowTrig_rect.bottom() - 5);
p.drawLine(edgeTrig_rect.left() + 5, edgeTrig_rect.top() + 5,
edgeTrig_rect.center().x() - 2, edgeTrig_rect.top() + 5);
p.drawLine(edgeTrig_rect.center().x() + 2 , edgeTrig_rect.top() + 5,
edgeTrig_rect.right() - 5, edgeTrig_rect.top() + 5);
p.drawLine(edgeTrig_rect.center().x(), edgeTrig_rect.top() + 7,
edgeTrig_rect.center().x(), edgeTrig_rect.bottom() - 7);
p.drawLine(edgeTrig_rect.left() + 5, edgeTrig_rect.bottom() - 5,
edgeTrig_rect.center().x() - 2, edgeTrig_rect.bottom() - 5);
p.drawLine(edgeTrig_rect.center().x() + 2, edgeTrig_rect.bottom() - 5,
edgeTrig_rect.right() - 5, edgeTrig_rect.bottom() - 5);
} else if (_type == DS_GROUP || _type == DS_PROTOCOL) {
const QRectF group_index_rect = get_rect("groupIndex", y, right);
QString index_string;
@ -311,40 +564,92 @@ void Signal::paint_label(QPainter &p, int y, int right, bool hover, int action)
}
p.setPen(Qt::white);
p.drawText(group_index_rect, Qt::AlignRight | Qt::AlignVCenter, index_string);
} else if (_type == DS_DSO) {
const QRectF vDial_rect = get_rect("vDial", y, right);
const QRectF hDial_rect = get_rect("hDial", y, right);
const QRectF acdc_rect = get_rect("acdc", y, right);
const QRectF chEn_rect = get_rect("chEn", y, right);
QColor vDial_color = _vDialActive ? dsActive : dsDisable;
QColor hDial_color = _hDialActive ? dsActive : dsDisable;
_vDial->paint(p, vDial_rect, vDial_color);
_hDial->paint(p, hDial_rect, hDial_color);
p.setPen(Qt::transparent);
p.setBrush((hover && action == CHEN) ? _colour.darker() : _colour);
p.drawRect(chEn_rect);
p.setPen(Qt::white);
p.drawText(chEn_rect, Qt::AlignCenter | Qt::AlignVCenter, _active ? "EN" : "DIS");
p.setPen(Qt::transparent);
p.setBrush(_active ? ((hover && action == ACDC) ? _colour.darker() : _colour) : dsDisable);
p.drawRect(acdc_rect);
p.setPen(Qt::white);
p.drawText(acdc_rect, Qt::AlignCenter | Qt::AlignVCenter, _acCoupling ? "AC" : "DC");
}
// Paint the label
const QPointF points[] = {
label_rect.topLeft(),
label_rect.topRight(),
QPointF(right, y),
label_rect.bottomRight(),
label_rect.bottomLeft()
};
if (_active) {
const QPointF points[] = {
label_rect.topLeft(),
label_rect.topRight(),
QPointF(right, (_type == DS_DSO) ? _zeroPos : y),
label_rect.bottomRight(),
label_rect.bottomLeft()
};
p.setPen(Qt::transparent);
p.setBrush(((hover && action == LABEL) || _selected) ? dsYellow : dsBlue);
p.drawPolygon(points, countof(points));
p.setPen(Qt::transparent);
if (_type == DS_DSO)
p.setBrush(((hover && action == LABEL) || _selected) ? _colour.darker() : _colour);
else
p.setBrush(((hover && action == LABEL) || _selected) ? dsYellow : dsBlue);
p.drawPolygon(points, countof(points));
if ((hover && action == LABEL) || _selected) {
p.setPen(QPen(dsBlue, 2, Qt::DotLine));
p.setPen(QPen(Qt::blue, 1, Qt::DotLine));
p.setBrush(Qt::transparent);
p.drawPoint(label_rect.right(), label_rect.top() + 4);
p.drawPoint(label_rect.right(), label_rect.top() + 8);
p.drawPoint(label_rect.right(), label_rect.top() + 12);
p.drawPoint(label_rect.right(), label_rect.top() + 16);
}
p.drawLine(label_rect.right(), label_rect.top() + 3,
label_rect.right(), label_rect.bottom() - 3);
// Paint the text
p.setPen(Qt::white);
if (_type == DS_GROUP)
p.drawText(label_rect, Qt::AlignCenter | Qt::AlignVCenter, "G");
else if (_type == DS_ANALOG)
p.drawText(label_rect, Qt::AlignCenter | Qt::AlignVCenter, "A");
else if (_type == DS_PROTOCOL)
p.drawText(label_rect, Qt::AlignCenter | Qt::AlignVCenter, "D");
else
p.drawText(label_rect, Qt::AlignCenter | Qt::AlignVCenter, QString::number(_index_list.front()));
// Paint the text
p.setPen(Qt::white);
if (_type == DS_GROUP)
p.drawText(label_rect, Qt::AlignCenter | Qt::AlignVCenter, "G");
else if (_type == DS_ANALOG)
p.drawText(label_rect, Qt::AlignCenter | Qt::AlignVCenter, "A");
else if (_type == DS_PROTOCOL)
p.drawText(label_rect, Qt::AlignCenter | Qt::AlignVCenter, "D");
else
p.drawText(label_rect, Qt::AlignCenter | Qt::AlignVCenter, QString::number(_index_list.front()));
}
}
void Signal::paint_trig(QPainter &p, int left, int right, bool hover)
{
if (_type == DS_DSO) {
const QRectF label_rect = get_rect("dsoTrig", -1, right);
// Paint the trig line
if (_trig_en) {
const QPointF points[] = {
QPointF(right - label_rect.width()*1.5, _trig_vpos),
label_rect.topLeft(),
label_rect.topRight(),
label_rect.bottomRight(),
label_rect.bottomLeft()
};
p.setPen(Qt::transparent);
p.setBrush(_colour);
p.drawPolygon(points, countof(points));
// paint the _trig_vpos line
p.setPen(QPen(_colour, hover ? 2 : 1, Qt::DashLine));
p.drawLine(left, _trig_vpos, right - label_rect.width()*1.5, _trig_vpos);
// Paint the text
p.setPen(Qt::white);
p.drawText(label_rect, Qt::AlignCenter | Qt::AlignVCenter, "T");
}
}
}
int Signal::pt_in_rect(int y, int right, const QPoint &point)
@ -355,11 +660,17 @@ int Signal::pt_in_rect(int y, int right, const QPoint &point)
const QRectF higTrig = get_rect("higTrig", y, right);
const QRectF negTrig = get_rect("negTrig", y, right);
const QRectF lowTrig = get_rect("lowTrig", y, right);
const QRectF label = get_rect("label", y, right);
const QRectF edgeTrig = get_rect("edgeTrig", y, right);
const QRectF label = get_rect("label", (_type == DS_DSO) ? _zeroPos : y, right);
const QRectF vDial = get_rect("vDial", y, right);
const QRectF hDial = get_rect("hDial", y, right);
const QRectF chEn = get_rect("chEn", y, right);
const QRectF acdc = get_rect("acdc", y, right);
const QRectF dsoTrig = get_rect("dsoTrig", 0, right);
if (color.contains(point))
if (color.contains(point) && _active)
return COLOR;
else if (name.contains(point))
else if (name.contains(point) && _active)
return NAME;
else if (posTrig.contains(point) && _type == DS_LOGIC)
return POSTRIG;
@ -369,8 +680,20 @@ int Signal::pt_in_rect(int y, int right, const QPoint &point)
return NEGTRIG;
else if (lowTrig.contains(point) && _type == DS_LOGIC)
return LOWTRIG;
else if (label.contains(point))
else if (edgeTrig.contains(point) && _type == DS_LOGIC)
return EDGETRIG;
else if (label.contains(point) && _active)
return LABEL;
else if (vDial.contains(point) && _type == DS_DSO && _active)
return VDIAL;
else if (hDial.contains(point) && _type == DS_DSO && _active)
return HDIAL;
else if (chEn.contains(point) && _type == DS_DSO)
return CHEN;
else if (acdc.contains(point) && _type == DS_DSO && _active)
return ACDC;
else if (dsoTrig.contains(point) && _type == DS_DSO && _active)
return DSOTRIG;
else
return 0;
}
@ -392,7 +715,8 @@ QRectF Signal::get_rect(const char *s, int y, int right)
{
const QSizeF color_size(SquareWidth, SquareWidth);
const QSizeF name_size(right - get_leftWidth() - get_rightWidth(), SquareWidth);
const QSizeF label_size(_text_size.width() + Margin, SquareWidth);
//const QSizeF label_size(_text_size.width() + Margin, SquareWidth);
const QSizeF label_size(SquareWidth, SquareWidth);
if (!strcmp(s, "name"))
return QRectF(
@ -402,38 +726,68 @@ QRectF Signal::get_rect(const char *s, int y, int right)
else if (!strcmp(s, "label"))
return QRectF(
right - 1.5f * label_size.width(),
y - label_size.height() / 2,
y - SquareWidth / 2,
label_size.width(), label_size.height());
else if (!strcmp(s, "posTrig"))
return QRectF(
get_leftWidth() + name_size.width() + Margin,
y - color_size.height() / 2,
color_size.width(), color_size.height());
y - SquareWidth / 2,
SquareWidth, SquareWidth);
else if (!strcmp(s, "higTrig"))
return QRectF(
get_leftWidth() + name_size.width() + SquareWidth + Margin,
y - color_size.height() / 2,
color_size.width(), color_size.height());
y - SquareWidth / 2,
SquareWidth, SquareWidth);
else if (!strcmp(s, "negTrig"))
return QRectF(
get_leftWidth() + name_size.width() + 2 * SquareWidth + Margin,
y - color_size.height() / 2,
color_size.width(), color_size.height());
y - SquareWidth / 2,
SquareWidth, SquareWidth);
else if (!strcmp(s, "lowTrig"))
return QRectF(
get_leftWidth() + name_size.width() + 3 * SquareWidth + Margin,
y - color_size.height() / 2,
color_size.width(), color_size.height());
y - SquareWidth / 2,
SquareWidth, SquareWidth);
else if (!strcmp(s, "edgeTrig"))
return QRectF(
get_leftWidth() + name_size.width() + 4 * SquareWidth + Margin,
y - SquareWidth / 2,
SquareWidth, SquareWidth);
else if (!strcmp(s, "groupIndex"))
return QRectF(
get_leftWidth() + name_size.width() + Margin,
y - color_size.height() / 2,
color_size.width() * 4, color_size.height());
y - SquareWidth / 2,
SquareWidth * SquareNum, SquareWidth);
else if (!strcmp(s, "vDial"))
return QRectF(
get_leftWidth() + name_size.width() + SquareWidth*0.5 + Margin,
y - SquareWidth * SquareNum,
SquareWidth * (SquareNum-1), SquareWidth * (SquareNum-1));
else if (!strcmp(s, "hDial"))
return QRectF(
get_leftWidth() + name_size.width() + SquareWidth*0.5 + Margin,
y + SquareWidth * 1.5,
SquareWidth * (SquareNum-1), SquareWidth * (SquareNum-1));
else if (!strcmp(s, "chEn"))
return QRectF(
get_leftWidth() + name_size.width() + SquareWidth*0.75 + Margin,
y - SquareWidth / 2,
SquareWidth * 1.5, SquareWidth);
else if (!strcmp(s, "acdc"))
return QRectF(
get_leftWidth() + name_size.width() + SquareWidth*2.75 + Margin,
y - SquareWidth / 2,
SquareWidth * 1.5, SquareWidth);
else if (!strcmp(s, "dsoTrig"))
return QRectF(
right - label_size.width(),
_trig_vpos - SquareWidth / 2,
label_size.width(), label_size.height());
else
return QRectF(
2,
y - color_size.height() / 2,
color_size.width(), color_size.height());
y - SquareWidth / 2,
SquareWidth, SquareWidth);
}
} // namespace view

View File

@ -36,6 +36,7 @@
#include <list>
#include "libsigrok4DSLogic/libsigrok.h"
#include "dsldial.h"
namespace pv {
@ -56,26 +57,47 @@ namespace view {
class Signal
{
private:
static const int SquareWidth;
static const int Margin;
static const int SquareWidth = 20;
static const int Margin = 3;
static const int SquareNum = 5;
static const int COLOR;
static const int NAME;
static const int POSTRIG;
static const int HIGTRIG;
static const int NEGTRIG;
static const int LOWTRIG;
static const int LABEL;
static const uint64_t vDialValueCount = 10;
static const uint64_t vDialValueStep = 1000;
static const uint64_t vDialUnitCount = 2;
static const uint64_t hDialValueCount = 25;
static const uint64_t hDialValueStep = 1000;
static const uint64_t hDialUnitCount = 4;
static const uint64_t vDialValue[vDialValueCount];
static const QString vDialUnit[vDialUnitCount];
static const uint64_t hDialValue[hDialValueCount];
static const QString hDialUnit[hDialUnitCount];
public:
static const int COLOR = 1;
static const int NAME = 2;
static const int POSTRIG = 3;
static const int HIGTRIG = 4;
static const int NEGTRIG = 5;
static const int LOWTRIG = 6;
static const int EDGETRIG = 7;
static const int LABEL = 8;
static const int VDIAL = 9;
static const int HDIAL = 10;
static const int CHEN = 11;
static const int ACDC = 12;
static const int DSOTRIG = 13;
static const QColor dsBlue;
static const QColor dsYellow;
static const QColor dsRed;
static const QColor dsGreen;
static const QColor dsGray;
static const QColor dsDisable;
static const QColor dsActive;
static const QColor dsLightBlue;
static const QColor dsLightRed;
static const QPen SignalAxisPen;
static const QPen SignalAxisPen;
enum {DS_LOGIC = 0, DS_ANALOG, DS_GROUP, DS_PROTOCOL, DS_DSO};
@ -166,6 +188,32 @@ public:
int get_trig() const;
void set_trig(int trig);
/*
*
*/
bool get_vDialActive() const;
void set_vDialActive(bool active);
bool get_hDialActive() const;
void set_hDialActive(bool active);
bool go_vDialPre();
bool go_vDialNext();
bool go_hDialPre();
bool go_hDialNext();
uint64_t get_vDialValue() const;
uint64_t get_hDialValue() const;
uint16_t get_vDialSel() const;
uint16_t get_hDialSel() const;
bool get_acCoupling() const;
void set_acCoupling(bool coupling);
bool get_active() const;
void set_active(bool active);
int get_zeroPos() const;
void set_zeroPos(int pos);
int get_windowHeight() const;
void set_windowHeight(int height);
void set_trig_vpos(int value);
int get_trig_vpos() const;
/**
* Paints the signal with a QPainter
* @param p the QPainter to paint into.
@ -177,7 +225,7 @@ public:
* the view in seconds.
**/
virtual void paint(QPainter &p, int y, int left, int right,
double scale, double offset) = 0;
double scale, double offset) = 0;
virtual const std::vector< std::pair<uint64_t, bool> > cur_edges() const = 0;
@ -200,9 +248,12 @@ public:
* area.
* @param hover true if the label is being hovered over by the mouse.
*/
virtual void paint_label(QPainter &p, int y, int right,
virtual void paint_label(QPainter &p, int y, int right,
bool hover, int action);
virtual void paint_trig(QPainter &p, int left, int right,
bool hover);
/**
* Determines if a point is in the header rect.
* 1 - in color rect
@ -221,6 +272,16 @@ public:
int pt_in_rect(int y, int right,
const QPoint &point);
/**
* Computes the outline rectangle of a label.
* @param p the QPainter to lay out text with.
* @param y the y-coordinate of the signal.
* @param right the x-coordinate of the right edge of the header
* area.
* @return Returns the rectangle of the signal label.
*/
QRectF get_rect(const char *s, int y, int right);
protected:
/**
@ -239,16 +300,6 @@ private:
*/
void compute_text_size(QPainter &p);
/**
* Computes the outline rectangle of a label.
* @param p the QPainter to lay out text with.
* @param y the y-coordinate of the signal.
* @param right the x-coordinate of the right edge of the header
* area.
* @return Returns the rectangle of the signal label.
*/
QRectF get_rect(const char *s, int y, int right);
protected:
int _type;
std::list<int> _index_list;
@ -266,6 +317,17 @@ protected:
int _trig;
QSizeF _text_size;
dslDial *_vDial;
dslDial *_hDial;
bool _vDialActive;
bool _hDialActive;
bool _acCoupling;
bool _active;
int _zeroPos;
int _windowHeight;
int _trig_vpos;
bool _trig_en;
};
} // namespace view

View File

@ -105,6 +105,14 @@ View::View(SigSession &session, QWidget *parent) :
this, SLOT(on_signals_moved()));
connect(_header, SIGNAL(header_updated()),
this, SLOT(header_updated()));
connect(_header, SIGNAL(vDial_changed(quint16)),
this, SLOT(vDial_changed(quint16)));
connect(_header, SIGNAL(hDial_changed(quint16)),
this, SLOT(hDial_changed(quint16)));
connect(_header, SIGNAL(acdc_changed(quint16)),
this, SLOT(acdc_changed(quint16)));
connect(_header, SIGNAL(ch_changed(quint16)),
this, SLOT(ch_changed(quint16)));
setViewportMargins(headerWidth(), RulerHeight, 0, 0);
setViewport(_viewport);
@ -176,8 +184,20 @@ void View::zoom(double steps, int offset)
_preOffset = _offset;
const double cursor_offset = _offset + _scale * offset;
_scale *= pow(3.0/2.0, -steps);
_scale = max(min(_scale, _maxscale), _minscale);
if (_session.get_device()->mode != DSO) {
_scale *= pow(3.0/2.0, -steps);
_scale = max(min(_scale, _maxscale), _minscale);
} else {
const vector< shared_ptr<Signal> > sigs(_session.get_signals());
if (steps > 0.5) {
BOOST_FOREACH(const shared_ptr<Signal> s, sigs)
s->go_hDialNext();
} else if(steps < -0.5) {
BOOST_FOREACH(const shared_ptr<Signal> s, sigs)
s->go_hDialPre();
}
_scale = sigs.at(0)->get_hDialValue() * pow(10, -9) * Viewport::NumSpanX / _viewport->width();
}
_offset = cursor_offset - _scale * offset;
const double MinOffset = -(_scale * (_viewport->width() * (1 - MaxViewRate)));
const double MaxOffset = _data_length * 1.0f / _session.get_last_sample_rate() -
@ -185,6 +205,7 @@ void View::zoom(double steps, int offset)
_offset = max(min(_offset, MaxOffset), MinOffset);
if (_scale != _preScale || _offset != _preOffset) {
_header->update();
_ruler->update();
_viewport->update();
update_scroll();
@ -199,7 +220,9 @@ void View::set_scale_offset(double scale, double offset)
_preScale = _scale;
_preOffset = _offset;
_scale = max(min(scale, _maxscale), _minscale);
if (_session.get_device()->mode != DSO)
_scale = max(min(scale, _maxscale), _minscale);
const double MinOffset = -(_scale * (_viewport->width() * (1 - MaxViewRate)));
const double MaxOffset = _data_length * 1.0f / _session.get_last_sample_rate()
- _scale * (_viewport->width() * MaxViewRate);
@ -380,9 +403,11 @@ void View::reset_signal_layout()
const vector< boost::shared_ptr<Signal> > sigs(_session.get_signals());
BOOST_FOREACH(boost::shared_ptr<Signal> s, sigs) {
s->set_signalHeight(SignalHeight);
s->set_windowHeight(_viewport->height());
//s->set_v_offset(offset);
//offset += SignalHeight + 2 * SignalMargin;
s->set_v_offset(offset + s->get_order() * _spanY);
s->set_zeroPos(_viewport->height()*0.5);
}
normalize_layout();
}
@ -439,7 +464,7 @@ int View::headerWidth()
int maxNameWidth = 0;
int maxLeftWidth = 0;
int maxRightWidth = 0;
QFont font = QApplication::font();
QFontMetrics fm(font);
int fontWidth=fm.width("A");
@ -518,7 +543,8 @@ void View::data_updated()
// Get the new data length
_data_length = max(_session.get_total_sample_len(), (quint64)1000);
_maxscale = (_data_length * 1.0f / _session.get_last_sample_rate()) / (_viewport->width() * MaxViewRate);
_scale = min(_scale, _maxscale);
if(_session.get_device()->mode != DSO)
_scale = min(_scale, _maxscale);
setViewportMargins(headerWidth(), RulerHeight, 0, 0);
update_margins();
@ -555,7 +581,9 @@ void View::sample_rate_changed(quint64 sample_rate)
{
assert(sample_rate > 0);
_scale = (1.0f / sample_rate) / WellPixelsPerSample;
if (_session.get_device()->mode != DSO)
_scale = (1.0f / sample_rate) / WellPixelsPerSample;
_minscale = (1.0f / sample_rate) / (_viewport->width() * MaxViewRate);
_offset = 0;
_preScale = _scale;
@ -574,7 +602,8 @@ void View::marker_time_changed()
void View::on_signals_moved()
{
update_scroll();
signals_moved();
_viewport->update();
//signals_moved();
}
/*
@ -704,5 +733,39 @@ void View::on_state_changed(bool stop)
_viewport->stop_trigger_timer();
}
void View::vDial_changed(uint16_t channel)
{
if (channel == 0)
_session.set_dso_ctrl(SR_CONF_VDIV0);
else
_session.set_dso_ctrl(SR_CONF_VDIV1);
}
void View::hDial_changed(uint16_t channel)
{
const vector< shared_ptr<Signal> > sigs(_session.get_signals());
_session.set_dso_ctrl(SR_CONF_TIMEBASE);
_scale = sigs.at(channel)->get_hDialValue() * pow(10, -9) * Viewport::NumSpanX / _viewport->width();
_ruler->update();
_viewport->update();
update_scroll();
}
void View::acdc_changed(uint16_t channel)
{
if (channel == 0)
_session.set_dso_ctrl(SR_CONF_COUPLING0);
else
_session.set_dso_ctrl(SR_CONF_COUPLING1);
}
void View::ch_changed(uint16_t channel)
{
if (channel == 0)
_session.set_dso_ctrl(SR_CONF_EN_CH0);
else
_session.set_dso_ctrl(SR_CONF_EN_CH1);
}
} // namespace view
} // namespace pv

View File

@ -187,7 +187,8 @@ private:
void resizeEvent(QResizeEvent *e);
public slots:
void set_measure_en(int enable);
void set_measure_en(int enable);
void hDial_changed(quint16 channel);
private slots:
@ -209,6 +210,10 @@ private slots:
void set_trig_pos(quint64 trig_pos);
void vDial_changed(quint16 channel);
void acdc_changed(quint16 channel);
void ch_changed(quint16 channel);
private:
SigSession &_session;

View File

@ -105,19 +105,19 @@ void Viewport::paintEvent(QPaintEvent *event)
p.setRenderHint(QPainter::Antialiasing);
if (_view.session().get_device()->mode == LOGIC) {
switch(_view.session().get_capture_state()) {
case SigSession::Init:
break;
switch(_view.session().get_capture_state()) {
case SigSession::Init:
break;
case SigSession::Stopped:
paintSignals(p);
break;
case SigSession::Stopped:
paintSignals(p);
break;
case SigSession::Running:
//p.setRenderHint(QPainter::Antialiasing);
paintProgress(p);
break;
}
case SigSession::Running:
//p.setRenderHint(QPainter::Antialiasing);
paintProgress(p);
break;
}
} else {
paintSignals(p);
}
@ -161,8 +161,8 @@ void Viewport::paintEvent(QPaintEvent *event)
p.setPen(Signal::dsGray);
p.setPen(Qt::DotLine);
const double spanY =height() * 1.0f / 8;
for (i = 1; i < 9; i++) {
const double spanY =height() * 1.0f / 10;
for (i = 1; i < 11; i++) {
const double posY = spanY * i;
p.drawLine(0, posY, width(), posY);
const double miniSpanY = spanY / 5;
@ -210,8 +210,9 @@ void Viewport::paintSignals(QPainter &p)
p.setRenderHint(QPainter::Antialiasing, false);
BOOST_FOREACH(const boost::shared_ptr<Signal> s, sigs) {
assert(s);
s->paint(dbp, s->get_v_offset() - v_offset, 0, width(),
_view.scale(), _view.offset());
if (s->get_active())
s->paint(dbp, ((s->get_type() == Signal::DS_DSO) ? s->get_zeroPos() + height()*0.5 : s->get_v_offset() - v_offset), 0, width(),
_view.scale(), _view.offset());
}
// p.setRenderHint(QPainter::Antialiasing);
// BOOST_FOREACH(const boost::shared_ptr<Signal> s, pro_sigs) {
@ -223,6 +224,13 @@ void Viewport::paintSignals(QPainter &p)
}
p.drawPixmap(0, 0, pixmap);
// plot trig line in DSO mode
BOOST_FOREACH(const shared_ptr<Signal> s, sigs) {
assert(s);
if (s->get_active() && s->get_type() == Signal::DS_DSO)
s->paint_trig(p, 0, width(), qAbs(_mouse_point.y() - s->get_trig_vpos()) <= HitCursorMargin );
}
// plot cursors
if (_view.cursors_shown()) {
list<Cursor*>::iterator i = _view.get_cursorList().begin();
@ -391,6 +399,20 @@ void Viewport::mousePressEvent(QMouseEvent *event)
// if (!_view.get_ruler()->get_grabbed_cursor()) {
// _zoom_rect_visible = true;
// }
const vector< shared_ptr<Signal> > sigs(_view.session().get_signals());
BOOST_FOREACH(const shared_ptr<Signal> s, sigs) {
assert(s);
if (s->get_active() &&
s->get_type() == Signal::DS_DSO &&
qAbs(_mouse_point.y() - s->get_trig_vpos()) <= HitCursorMargin) {
if (_drag_sig)
_drag_sig.reset();
else
_drag_sig = s;
break;
}
}
update();
}
}
@ -398,7 +420,7 @@ void Viewport::mousePressEvent(QMouseEvent *event)
void Viewport::mouseMoveEvent(QMouseEvent *event)
{
assert(event);
_mouse_point = event->pos();
if (event->buttons() & Qt::RightButton) {
_zoom_rect = QRectF(_mouse_down_point, event->pos());
_zoom_rect_visible = true;
@ -409,16 +431,35 @@ void Viewport::mouseMoveEvent(QMouseEvent *event)
_mouse_down_offset +
(_mouse_down_point - event->pos()).x() *
_view.scale());
measure();
}
if (!(event->buttons() || Qt::NoButton)) {
if (_drag_sig) {
uint16_t trig_value = 0;
int vpos = _mouse_point.y();
if (vpos < 0)
vpos = 0;
else if (vpos > height())
vpos = height();
_drag_sig->set_trig_vpos(vpos);
const vector< shared_ptr<Signal> > sigs(_view.session().get_signals());
BOOST_FOREACH(const shared_ptr<Signal> s, sigs) {
assert(s);
if (s->get_active() &&
s->get_type() == Signal::DS_DSO) {
trig_value += (((uint16_t)(255 - s->get_trig_vpos()*1.0/height()*255)) << 8*s->get_index());
}
}
sr_config_set(_view.session().get_device(),
SR_CONF_TRIGGER_VALUE, g_variant_new_uint16(trig_value));
}
TimeMarker* grabbed_marker = _view.get_ruler()->get_grabbed_cursor();
if (_view.cursors_shown() && grabbed_marker) {
grabbed_marker->set_time(_view.offset() + _view.hover_point().x() * _view.scale());
}
measure();
}
@ -472,6 +513,7 @@ void Viewport::wheelEvent(QWheelEvent *event)
void Viewport::leaveEvent(QEvent *)
{
_measure_shown = false;
_mouse_point = QPoint(-1, -1);
//_view.show_cursors(false);
update();
}

View File

@ -24,6 +24,9 @@
#ifndef DSLOGIC_PV_VIEW_VIEWPORT_H
#define DSLOGIC_PV_VIEW_VIEWPORT_H
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
#include <QTimer>
#include <QWidget>
#include <stdint.h>
@ -35,13 +38,14 @@ class SigSession;
namespace pv {
namespace view {
class Signal;
class View;
class Viewport : public QWidget
{
Q_OBJECT
private:
public:
static const int HitCursorMargin;
static const int NumSpanY;
static const int NumMiniSpanY;
@ -88,6 +92,7 @@ private:
View &_view;
quint64 _total_receive_len;
QPoint _mouse_point;
QPoint _mouse_down_point;
double _mouse_down_offset;
double _curScale;
@ -115,6 +120,8 @@ private:
QTimer trigger_timer;
bool triggered;
int timer_cnt;
boost::shared_ptr<Signal> _drag_sig;
};
} // namespace view

Binary file not shown.

Binary file not shown.

View File

@ -1,6 +1,6 @@
palette {
background: rgb(17, 133, 209, 255);
disabled: rgb(232, 232, 230, 255);
disabled: rgb(200, 200, 200, 255);
}
QMainWindow {
@ -77,7 +77,7 @@ QSpinBox {
QLineEdit:disabled,
QComboBox:disabled,
QSpinBox:disabled {
background-color: rgb(232, 232, 230, 255);
background-color: rgb(200, 200, 200, 255);
}
QComboBox:!editable {
@ -163,7 +163,7 @@ QGroupBox::title
}
QGroupBox:disabled
{
color: rgb(232, 232, 230, 255);
color: rgb(200, 200, 200, 255);
}
QDockWidget > QWidget > QTabWidget::pane{
@ -175,7 +175,7 @@ QDockWidget > QWidget > QTabWidget::pane{
}
QDockWidget > QWidget > QTabWidget::pane:disabled{
border: 1px solid rgb(232, 232, 230, 255);
border: 1px solid rgb(200, 200, 200, 255);
border-right-color: rgb(17, 133, 209, 255); /* same as the pane color */
}
@ -203,7 +203,7 @@ QDockWidget > QWidget > QTabWidget > QTabBar::tab:selected
}
QDockWidget > QWidget > QTabWidget > QTabBar::tab:disabled
{
color: rgb(232, 232, 230, 50);
color: rgb(200, 200, 200, 50);
border: 1px solid rgb(232, 232, 230, 255);
background: transparent;
border-left-color: rgb(17, 133, 209, 255); /* same as the pane color */
@ -213,25 +213,29 @@ QCheckBox,
QRadioButton,
QLabel {
border: none;
color: white;
min-height: 20px;
}
QCheckBox::checked,
QRadioButton::checked {
color: black;
}
QLabel,
QCheckBox::unchecked,
QRadioButton::unchecked {
color: white;
}
QCheckBox,
QLabel {
padding: 1px 1px 1px 1px;
margin: 0px;
}
QCheckBox::indicator:checked {
image: url(:icons/checkbox.png);
}
QRadioButton::indicator:checked {
image: url(:icons/radiobutton.png);
}
QLabel:disabled {
color: rgb(232, 232, 230, 255);
color: rgb(200, 200, 200, 255);
}
QSlider::groove:horizontal {

View File

@ -2,7 +2,8 @@
## This file is part of the PulseView project.
##
## Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk>
## Copyright (C) 2012 Alexandru Gagniuc <mr.nuke.me@gmail.com>
## Copyright (C) 2012-2013 Alexandru Gagniuc <mr.nuke.me@gmail.com>
## Copyright (C) 2013-2014 DreamSourceLab <support@dreamsourcelab.com>
##
## 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
@ -18,35 +19,293 @@
## along with this program. If not, see <http://www.gnu.org/licenses/>.
##
cmake_minimum_required(VERSION 2.6)
include(FindPkgConfig)
include(GNUInstallDirs)
project(DSLogic)
#===============================================================================
#= User Options
#-------------------------------------------------------------------------------
option(DISABLE_WERROR "Build without -Werror" TRUE)
option(ENABLE_SIGNALS "Build with UNIX signals" TRUE)
option(ENABLE_TESTS "Enable unit tests" FALSE)
option(STATIC_PKGDEPS_LIBS "Statically link to (pkgconfig) libraries" FALSE)
if(WIN32)
# On Windows/MinGW we need to statically link to libraries.
# This option is user configurable, but enable it by default on win32.
set(STATIC_PKGDEPS_LIBS TRUE)
# For boost-thread we need two additional settings on win32:
set(Boost_USE_STATIC_LIBS on)
add_definitions(-DBOOST_THREAD_USE_LIB)
# Windsws does not support UNIX signals
set(ENABLE_SIGNALS FALSE)
endif()
#===============================================================================
#= Dependencies
#-------------------------------------------------------------------------------
list(APPEND PKGDEPS
libsigrok4DSLogic>=0.2.0
libusb-1.0>=1.0.16
)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules/")
find_package(PkgConfig)
pkg_check_modules(PKGDEPS REQUIRED ${PKGDEPS})
find_package(Qt4 REQUIRED)
# Find the platform's thread library (needed for boost-thread).
# This will set ${CMAKE_THREAD_LIBS_INIT} to the correct, OS-specific value.
find_package(Threads)
find_package(Boost 1.46 COMPONENTS unit_test_framework REQUIRED)
if(WIN32)
# On Windows/MinGW the we need to use 'thread_win32' instead of 'thread'.
# The library is named libboost_thread_win32* (not libboost_thread*).
find_package(Boost 1.42 COMPONENTS system thread_win32 REQUIRED)
else()
find_package(Boost 1.42 COMPONENTS system thread REQUIRED)
endif()
set(pulseview_TEST_SOURCES
${PROJECT_SOURCE_DIR}/pv/data/analogsnapshot.cpp
${PROJECT_SOURCE_DIR}/pv/data/snapshot.cpp
${PROJECT_SOURCE_DIR}/pv/data/logicsnapshot.cpp
data/analogsnapshot.cpp
data/logicsnapshot.cpp
test.cpp
find_package(libusb-1.0 REQUIRED)
#===============================================================================
#= Config Header
#-------------------------------------------------------------------------------
set(DS_TITLE DSLogic)
set(DS_DESCRIPTION "A GUI for DSLogic")
set(DS_VERSION_MAJOR 0)
set(DS_VERSION_MINOR 3)
set(DS_VERSION_MICRO 0)
set(DS_VERSION_STRING
${DS_VERSION_MAJOR}.${DS_VERSION_MINOR}.${DS_VERSION_MICRO}
)
add_definitions(-DBOOST_TEST_DYN_LINK)
configure_file (
${PROJECT_SOURCE_DIR}/config.h.in
${PROJECT_BINARY_DIR}/config.h
)
#===============================================================================
#= Sources
#-------------------------------------------------------------------------------
set(DSLogic_SOURCES
main.cpp
pv/devicemanager.cpp
pv/mainwindow.cpp
pv/sigsession.cpp
pv/data/analog.cpp
pv/data/analogsnapshot.cpp
pv/data/group.cpp
pv/data/groupsnapshot.cpp
pv/data/logic.cpp
pv/data/logicsnapshot.cpp
pv/data/signaldata.cpp
pv/data/snapshot.cpp
pv/data/dso.cpp
pv/data/dsosnapshot.cpp
pv/decoder/decoder.cpp
pv/decoder/decoderfactory.cpp
pv/decoder/democonfig.cpp
pv/decoder/ds1wire.cpp
pv/decoder/dsdmx512.cpp
pv/decoder/dsi2c.cpp
pv/decoder/dsserial.cpp
pv/decoder/dsspi.cpp
pv/dialogs/about.cpp
pv/dialogs/connect.cpp
pv/dialogs/deviceoptions.cpp
pv/dialogs/search.cpp
pv/dock/fakelineedit.cpp
pv/dock/measuredock.cpp
pv/dock/protocoldock.cpp
pv/dock/searchdock.cpp
pv/dock/triggerdock.cpp
pv/prop/bool.cpp
pv/prop/double.cpp
pv/prop/enum.cpp
pv/prop/int.cpp
pv/prop/property.cpp
pv/prop/binding/binding.cpp
pv/prop/binding/binding_deviceoptions.cpp
pv/toolbars/devicebar.cpp
pv/toolbars/filebar.cpp
pv/toolbars/logobar.cpp
pv/toolbars/samplingbar.cpp
pv/toolbars/trigbar.cpp
pv/view/analogsignal.cpp
pv/view/cursor.cpp
pv/view/groupsignal.cpp
pv/view/header.cpp
pv/view/logicsignal.cpp
pv/view/protocolsignal.cpp
pv/view/ruler.cpp
pv/view/signal.cpp
pv/view/timemarker.cpp
pv/view/view.cpp
pv/view/viewport.cpp
pv/view/dsosignal.cpp
pv/view/dsldial.cpp
pv/dock/dsotriggerdock.cpp
)
set(DSLogic_HEADERS
pv/sigsession.h
pv/mainwindow.h
pv/decoder/democonfig.h
pv/dock/fakelineedit.h
pv/dock/measuredock.h
pv/dock/protocoldock.h
pv/dock/searchdock.h
pv/dock/triggerdock.h
pv/dialogs/about.h
pv/dialogs/connect.h
pv/dialogs/deviceoptions.h
pv/dialogs/search.h
pv/toolbars/samplingbar.h
pv/toolbars/devicebar.h
pv/toolbars/filebar.h
pv/toolbars/logobar.h
pv/toolbars/trigbar.h
pv/data/dso.h
pv/data/dsosnapshot.h
pv/view/cursor.h
pv/view/header.h
pv/view/ruler.h
pv/view/timemarker.h
pv/view/groupsignal.h
pv/view/protocolsignal.h
pv/view/view.h
pv/view/dsosignal.h
pv/view/viewport.h
pv/view/dsldial.h
pv/dock/dsotriggerdock.h
)
set(DSLogic_FORMS
pv/dialogs/about.ui
pv/decoder/dmx512config.ui
pv/decoder/i2cconfig.ui
pv/decoder/serialconfig.ui
pv/decoder/spiconfig.ui
pv/decoder/wire1config.ui
)
set(DSLogic_RESOURCES
DSLogic.qrc
)
qt4_wrap_cpp(DSLogic_HEADERS_MOC ${DSLogic_HEADERS})
qt4_wrap_ui(DSLogic_FORMS_HEADERS ${DSLogic_FORMS})
qt4_add_resources(DSLogic_RESOURCES_RCC ${DSLogic_RESOURCES})
include(${QT_USE_FILE})
#===============================================================================
#= Global Definitions
#-------------------------------------------------------------------------------
add_definitions(${QT_DEFINITIONS})
add_definitions(-Wall -Wextra -Wno-return-type -Wno-ignored-qualifiers)
if(NOT DISABLE_WERROR)
add_definitions(-Werror)
endif()
#===============================================================================
#= Global Include Directories
#-------------------------------------------------------------------------------
include_directories(
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR}
${Boost_INCLUDE_DIRS}
)
set(PULSEVIEW_LINK_LIBS
if(STATIC_PKGDEPS_LIBS)
include_directories(${PKGDEPS_STATIC_INCLUDE_DIRS})
else()
include_directories(${PKGDEPS_INCLUDE_DIRS})
endif()
#===============================================================================
#= Linker Configuration
#-------------------------------------------------------------------------------
link_directories(${Boost_LIBRARY_DIRS})
set(DSLOGIC_LINK_LIBS
${Boost_LIBRARIES}
${CMAKE_THREAD_LIBS_INIT}
${QT_LIBRARIES}
${LIBUSB_1_LIBRARIES}
)
add_executable(pulseview-test
${pulseview_TEST_SOURCES}
if(STATIC_PKGDEPS_LIBS)
link_directories(${PKGDEPS_STATIC_LIBRARY_DIRS})
list(APPEND DSLOGIC_LINK_LIBS ${PKGDEPS_STATIC_LIBRARIES})
else()
link_directories(${PKGDEPS_LIBRARY_DIRS})
list(APPEND DSLOGIC_LINK_LIBS ${PKGDEPS_LIBRARIES})
endif()
add_executable(${PROJECT_NAME}
${DSLogic_SOURCES}
${DSLogic_HEADERS_MOC}
${DSLogic_FORMS_HEADERS}
${DSLogic_RESOURCES_RCC}
)
target_link_libraries(pulseview-test ${PULSEVIEW_LINK_LIBS})
target_link_libraries(${PROJECT_NAME} ${DSLOGIC_LINK_LIBS})
if(WIN32)
# Pass -mwindows so that no "DOS box" will open when PulseView is started.
set_target_properties(${PROJECT_NAME} PROPERTIES LINK_FLAGS "-mwindows")
endif()
set_target_properties(${PROJECT_NAME} PROPERTIES INSTALL_RPATH "/usr/local/lib")
#===============================================================================
#= Installation
#-------------------------------------------------------------------------------
# Install the executable.
install(TARGETS ${PROJECT_NAME} DESTINATION bin/)
install(FILES res/DSLogic.fw DESTINATION bin/res/)
install(FILES res/DSLogic.bin DESTINATION bin/res/)
#===============================================================================
#= Packaging (handled by CPack)
#-------------------------------------------------------------------------------
set(CPACK_PACKAGE_VERSION_MAJOR ${DS_VERSION_MAJOR})
set(CPACK_PACKAGE_VERSION_MINOR ${DS_VERSION_MINOR})
set(CPACK_PACKAGE_VERSION_PATCH ${DS_VERSION_MICRO})
set(CPACK_PACKAGE_DESCRIPTION_FILE ${CMAKE_CURRENT_SOURCE_DIR}/README)
set(CPACK_RESOURCE_FILE_LICENSE ${CMAKE_CURRENT_SOURCE_DIR}/COPYING)
set(CPACK_SOURCE_IGNORE_FILES ${CMAKE_CURRENT_BINARY_DIR} ".gitignore" ".git")
set(CPACK_SOURCE_PACKAGE_FILE_NAME
"${CMAKE_PROJECT_NAME}-${DS_VERSION_MAJOR}.${DS_VERSION_MINOR}.${DS_VERSION_MICRO}")
set(CPACK_SOURCE_GENERATOR "TGZ")
include(CPack)
#===============================================================================
#= Tests
#-------------------------------------------------------------------------------
if(ENABLE_TESTS)
add_subdirectory(test)
enable_testing()
add_test(test ${CMAKE_CURRENT_BINARY_DIR}/test/DSLogic-test)
endif(ENABLE_TESTS)

674
DSLogic-gui/test/COPYING Normal file
View File

@ -0,0 +1,674 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
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 3 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, see <http://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<http://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.

49
DSLogic-gui/test/INSTALL Normal file
View File

@ -0,0 +1,49 @@
-------------------------------------------------------------------------------
INSTALL
-------------------------------------------------------------------------------
Requirements
------------
- git
- g++
- make
- libtool
- pkg-config >= 0.22
- cmake >= 2.6
- libglib >= 2.28.0
- Qt >= 4.5
- libboost >= 1.42 (including the following libs):
- libboost-system
- libboost-thread
- libsigrok4DSLogic >= 0.2.0
Building and installing
-----------------------
Get the DSLogic-gui source code from: www.dreamsourcelab.com/download.html
In order to build it, run:
$ cd DSLogic-gui
$ cmake .
$ make
For installing PulseView:
$ make install
See the following wiki page for more (OS-specific) instructions:
http://sigrok.org/wiki/Building
Creating a source distribution package
--------------------------------------
In order to build a source package begin with an unconfigured source tree.
$ mkdir dist
$ cd dist
$ cmake ..
$ make package_source

5
DSLogic-gui/test/NEWS Normal file
View File

@ -0,0 +1,5 @@
0.1.0 (2013-12-15)
------------------
* Initial release.

72
DSLogic-gui/test/README Normal file
View File

@ -0,0 +1,72 @@
-------------------------------------------------------------------------------
README
-------------------------------------------------------------------------------
DSLogic-gui is GUI for DSLogic software, it's based on PulseView
from the sigrok project.
The sigrok project aims at creating a portable, cross-platform,
Free/Libre/Open-Source signal analysis software suite that supports various
device types (such as logic analyzers, oscilloscopes, multimeters, and more).
PulseView is a Qt-based LA/scope/MSO GUI for sigrok.
Status
------
DSLogic-gui is in a usable state and has had official tarball releases.
However, it is still work in progress. Some basic functionality
is available and working, but other things are still on the TODO list.
Copyright and license
---------------------
DSLogic-gui is licensed under the terms of the GNU General Public License
(GPL), version 3 or later.
While some individual source code files are licensed under the GPLv2+, and
some files are licensed under the GPLv3+, this doesn't change the fact that
the program as a whole is licensed under the terms of the GPLv3+ (e.g. also
due to the fact that it links against GPLv3+ libraries).
Please see the individual source files for the full list of copyright holders.
Copyright notices
-----------------
A copyright notice indicating a range of years, must be interpreted as having
had copyrightable material added in each of those years.
Example:
Copyright (C) 2010-2013 Contributor Name
is to be interpreted as
Copyright (C) 2010,2011,2012,2013 Contributor Name
Mailing lists
-------------
There are two mailing lists for sigrok/PulseView:
https://lists.sourceforge.net/lists/listinfo/sigrok-devel
https://lists.sourceforge.net/lists/listinfo/sigrok-commits
IRC
---
You can find the sigrok developers in the #sigrok IRC channel on Freenode.
Website
-------
http://sigrok.org/wiki/PulseView
http://dreamsourcelab.com

View File

@ -0,0 +1,34 @@
/*
* This file is part of the PulseView project.
*
* Copyright (C) 2012 Alexandru Gagniuc <mr.nuke.me@gmail.com>
*
* 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef _DSLOGIC_CONFIG_H
#define _DSLOGIC_CONFIG_H
/* Application details */
#define DS_TITLE "@DS_TITLE@"
#define DS_DESCRIPTION "@DS_DESCRIPTION@"
#define DS_BIN_NAME "@PROJECT_NAME@"
/* DSLogic version information */
#define DS_VERSION_MAJOR @DS_VERSION_MAJOR@
#define DS_VERSION_MINOR @DS_VERSION_MINOR@
#define DS_VERSION_MICRO @DS_VERSION_MICRO@
#define DS_VERSION_STRING "@DS_VERSION_STRING@"
#endif

32
DSLogic-gui/test/extdef.h Normal file
View File

@ -0,0 +1,32 @@
/*
* This file is part of the DSLogic-gui project.
* DSLogic-gui is based on PulseView.
*
* Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk>
* Copyright (C) 2013 DreamSourceLab <dreamsourcelab@dreamsourcelab.com>
*
* 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
*/
#ifndef DSLOGIC_EXTDEF_H
#define DSLOGIC_EXTDEF_H
#define countof(x) (sizeof(x)/sizeof(x[0]))
#define begin_element(x) (&x[0])
#define end_element(x) (&x[countof(x)])
#endif // DSLOGIC_EXTDEF_H

163
DSLogic-gui/test/main.cpp Normal file
View File

@ -0,0 +1,163 @@
/*
* This file is part of the DSLogic-gui project.
* DSLogic-gui is based on PulseView.
*
* Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk>
* Copyright (C) 2013 DreamSourceLab <dreamsourcelab@dreamsourcelab.com>
*
* 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
*/
#ifdef ENABLE_SIGROKDECODE
#include <libsigrokdecode/libsigrokdecode.h> /* First, so we avoid a _POSIX_C_SOURCE warning. */
#endif
#include <stdint.h>
#include <libsigrok4DSLogic/libsigrok.h>
#include <getopt.h>
#include <QtGui/QApplication>
#include <QDebug>
#include <QFile>
#include "pv/devicemanager.h"
#include "pv/mainwindow.h"
#include "config.h"
void usage()
{
fprintf(stdout,
"Usage:\n"
" %s [OPTION…] [FILE] — %s\n"
"\n"
"Help Options:\n"
" -l, --loglevel Set libsigrok/libsigrokdecode loglevel\n"
" -V, --version Show release version\n"
" -h, -?, --help Show help option\n"
"\n", DS_BIN_NAME, DS_DESCRIPTION);
}
int main(int argc, char *argv[])
{
int ret = 0;
struct sr_context *sr_ctx = NULL;
const char *open_file = NULL;
QApplication a(argc, argv);
// Set some application metadata
QApplication::setApplicationVersion(DS_VERSION_STRING);
QApplication::setApplicationName("DSLogic(Beta)");
QApplication::setOrganizationDomain("http://www.DreamSourceLab.com");
// Parse arguments
while (1) {
static const struct option long_options[] = {
{"loglevel", required_argument, 0, 'l'},
{"version", no_argument, 0, 'V'},
{"help", no_argument, 0, 'h'},
{0, 0, 0, 0}
};
const int c = getopt_long(argc, argv,
"l:Vh?", long_options, NULL);
if (c == -1)
break;
switch (c) {
case 'l':
{
const int loglevel = atoi(optarg);
sr_log_loglevel_set(loglevel);
#ifdef ENABLE_SIGROKDECODE
srd_log_loglevel_set(loglevel);
#endif
break;
}
case 'V':
// Print version info
fprintf(stdout, "%s %s\n", DS_TITLE, DS_VERSION_STRING);
return 0;
case 'h':
case '?':
usage();
return 0;
}
}
if (argc - optind > 1) {
fprintf(stderr, "Only one file can be openened.\n");
return 1;
} else if (argc - optind == 1)
open_file = argv[argc - 1];
// Initialise libsigrok
if (sr_init(&sr_ctx) != SR_OK) {
qDebug() << "ERROR: libsigrok init failed.";
return 1;
}
do {
#ifdef ENABLE_SIGROKDECODE
// Initialise libsigrokdecode
if (srd_init(NULL) != SRD_OK) {
qDebug() << "ERROR: libsigrokdecode init failed.";
break;
}
// Load the protocol decoders
srd_decoder_load_all();
#endif
try {
// Create the device manager, initialise the drivers
pv::DeviceManager device_manager(sr_ctx);
// Initialise the main window
pv::MainWindow w(device_manager, open_file);
QFile qss(":/stylesheet.qss");
qss.open(QFile::ReadOnly);
a.setStyleSheet(qss.readAll());
qss.close();
w.show();
// Run the application
ret = a.exec();
} catch(std::exception e) {
qDebug() << e.what();
}
#ifdef ENABLE_SIGROKDECODE
// Destroy libsigrokdecode
srd_exit();
#endif
} while (0);
// Destroy libsigrok
if (sr_ctx)
sr_exit(sr_ctx);
return ret;
}

View File

@ -0,0 +1,279 @@
palette {
background: rgb(17, 133, 209, 255);
disabled: rgb(200, 200, 200, 255);
}
QMainWindow {
icon-size: 48px, 48px;
}
QDialog {
border: none;
background: rgb(17, 133, 209, 255);
}
QToolBar {
border: none;
/*background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
stop: 0 rgb(0, 75, 165, 255),
stop: 0.05 rgb(31, 164, 227, 255),
stop: 0.5 rgb(17, 133, 209, 255),
stop: 0.95 rgb(0, 102, 185, 255),
stop: 1 rgb(0, 75, 165, 255));*/
background: rgb(17, 133, 209, 255);
min-height: 50px;
}
pv--view--View,
pv--view--Viewport{
margin: 0px;
border: none;
background-color: rgb(255, 255, 255);
padding: 0px;
}
QToolButton {
border: none;
border-style: flat;
color: white;
font: bold 10ft;
min-height: 50px;
min-width: 50px;
}
QPushButton:hover,
QToolButton:hover {
background-color: rgb(238, 178, 17, 200);
}
QPushButton:pressed,
QToolButton:pressed {
background-color: rgb(238, 178, 17, 255);
}
QPushButton {
padding: 3px;
border: none;
border-style: flat;
border-radius: 4px;
color: white;
background-color: rgb(255, 255, 255, 50);
font: bold 10ft;
min-height: 20px;
min-width: 20px;
}
/* >>> QToolBar: QLineEdit/QComboBox */
QLineEdit,
QComboBox:!editable,
QSpinBox {
border: none;
border-radius: 4px;
background-color: white;
padding: 3px;
min-height: 20px;
}
QLineEdit:disabled,
QComboBox:disabled,
QSpinBox:disabled {
background-color: rgb(200, 200, 200, 255);
}
QComboBox:!editable {
padding-right: 5px;
}
/* QComboBox gets the "on" state when the popup is open */
QComboBox:!editable:on, QToolBar > QComboBox::drop-down:editable:on {
background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
stop: 0 #D3D3D3, stop: 0.4 #D8D8D8,
stop: 0.5 #DDDDDD, stop: 1.0 #E1E1E1);
}
QComboBox:on { /* shift the text when the popup opens */
padding-top: 3px;
padding-left: 4px;
}
QComboBox::drop-down {
subcontrol-origin: padding;
subcontrol-position: top right;
width: 20px;
border-left-width: 0px;
border-top-right-radius: 4px; /* same radius as the QComboBox */
border-bottom-right-radius: 4px;
}
QComboBox::down-arrow {
image: url(:/icons/down-arrow.png);
}
QComboBox::down-arrow:disabled {
image: none;
}
QComboBox::down-arrow:on { /* shift the arrow when popup is open */
top: 1px;
left: 1px;
}
/* <<< QToolBar: QLineEdit/QComboBox */
/* >>> QDockWidget */
QDockWidget {
margin: 0px;
background-color: rgb(17, 133, 209, 255);
border: 0px;
padding: 0px;
color: rgb(17, 133, 209, 255);
font-size: 16px;
font-weight: bold;
}
QDockWidget::title {
margin: 0px;
text-align: left center;
background-color: rgb(255, 255, 255, 255);
border: 0px;
color: white;
padding: 8px;
}
QDockWidget > QWidget{
margin: 0px;
background-color: rgb(17, 133, 209, 255);
border: 0px;
padding: 0px;
}
QGroupBox {
margin: 0px;
background-color: rgb(17, 133, 209, 255);
border: 0px;
padding: 40px, 10px, 10px, 10px;
color: white;
font-size: 20px;
font-weight: bold;
}
QGroupBox::title
{
subcontrol-origin: margin;
subcontrol-position: top center;
padding: 5 20px;
}
QGroupBox:disabled
{
color: rgb(200, 200, 200, 255);
}
QDockWidget > QWidget > QTabWidget::pane{
margin: 0px;
background-color: rgb(17, 133, 209, 255);
border: 1px solid rgb(255, 255, 255);
border-right-color: rgb(17, 133, 209, 255); /* same as the pane color */
padding: 0px;
}
QDockWidget > QWidget > QTabWidget::pane:disabled{
border: 1px solid rgb(200, 200, 200, 255);
border-right-color: rgb(17, 133, 209, 255); /* same as the pane color */
}
QDockWidget > QWidget > QTabWidget > QTabBar::tab
{
background: transparent;
color: white;
border: 2px solid rgb(238, 178, 17, 255);
border-left-color: rgb(17, 133, 209, 255); /* same as the pane color */
border-bottom-right-radius: 4px;
border-top-right-radius: 4px;
min-height: 8ex;
padding: 2px;
}
QDockWidget > QWidget > QTabWidget > QTabBar::tab:hover
{
border: 3px solid rgb(238, 178, 17, 255);
border-left-color: rgb(17, 133, 209, 255); /* same as the pane color */
}
QDockWidget > QWidget > QTabWidget > QTabBar::tab:selected
{
color: white;
background: rgb(238, 178, 17, 255);
border-left-color: rgb(17, 133, 209, 255); /* same as the pane color */
}
QDockWidget > QWidget > QTabWidget > QTabBar::tab:disabled
{
color: rgb(200, 200, 200, 50);
border: 1px solid rgb(232, 232, 230, 255);
background: transparent;
border-left-color: rgb(17, 133, 209, 255); /* same as the pane color */
}
QCheckBox,
QRadioButton,
QLabel {
border: none;
min-height: 20px;
}
QCheckBox::checked,
QRadioButton::checked {
color: black;
}
QLabel,
QCheckBox::unchecked,
QRadioButton::unchecked {
color: white;
}
QCheckBox,
QLabel {
padding: 1px 1px 1px 1px;
margin: 0px;
}
QLabel:disabled {
color: rgb(200, 200, 200, 255);
}
QSlider::groove:horizontal {
border: 1px solid #999999;
height: 2px;
margin: 0px 0;
left: 10px; right: 10px;
border-radius: 4px;
}
QSlider::handle:horizontal {
border-image:url(:/icons/slider-handle.png);
margin-left: -12px;
margin-right: -12px;
margin-top: -11px;
margin-bottom: -11px;
}
QSlider::sub-page:horizontal{
background: qlineargradient(spread:pad,
x1:0, y1:1, x2:0, y2:0,
stop:0 rgba(17, 133, 209, 255),
stop:0.25 rgba(238, 178, 17, 255),
stop:0.75 rgba(238, 178, 17, 255),
stop:1 rgba(17, 133, 209, 255));
height: 2px;
border-radius: 4px;
}
QSlider::add-page:horizontal{
background: qlineargradient(spread:pad,
x1:0, y1:1, x2:0, y2:0,
stop:0 rgba(17, 133, 209, 255),
stop:0.25 rgba(255, 255, 255, 255),
stop:0.75 rgba(255, 255, 255, 255),
stop:1 rgba(17, 133, 209, 255));
height: 2px;
border-radius: 4px;
}
/* <<< QDockWidget */

File diff suppressed because it is too large Load Diff

200
INSTALL
View File

@ -1,100 +1,100 @@
-------------------------------------------------------------------------------
INSTALL
-------------------------------------------------------------------------------
Requirements
------------
libsigrok4DSLoigc
- gcc (>= 4.0)
- make
- autoconf >= 2.63
- automake >= 1.11
- libtool
- pkg-config >= 0.22
This is part of the standard OpenBSD install (not an extra package), apparently.
- libglib >= 2.32.0
- libzip >= 0.10
- libusb-1.0 >= 1.0.16
On FreeBSD, this is an integral part of the FreeBSD libc, not an extra package/library.
This is part of the standard OpenBSD install (not an extra package), apparently.
- check >= 0.9.4 (optional, only needed to run unit tests)
DSLgoic-gui
- git
- g++
- make
- libtool
- pkg-config >= 0.22
- cmake >= 2.6
- libglib >= 2.28.0
- Qt >= 4.5
- libboost >= 1.42 (including the following libs):
- libboost-system
- libboost-thread
- libsigrok4DSLogic >= 0.2.0
Building and installing
-----------------------
Get the DSLogic source code from: www.dreamsourcelab.com/download.html
Step1: Build libusbx-1.0.18
Building:
$ cd libusbx-1.0.18
$ ./configure
$ make
$ sudo make install
Step2: Build libsigrok4DSLogic
Installing the requirements:
Example on Debian/Ubuntu (please check your respective distro's package manager tool if you use other distros):
$ sudo apt-get install git-core gcc make autoconf automake libtool pkg-config \
libglib2.0-dev libzip-dev libudev-dev libasound2-dev check
Fedora (18, 19):
$ sudo yum install git gcc make autoconf automake libtool pkgconfig glib2-devel \
libzip-devel libudev-devel alsa-lib-devel check
OpenSuSE (12.2):
$ zypper install git gcc make autoconf automake libtool pkg-config glib2-devel \
libzip-devel libudev-devel alsa-devel check
Building:
$ cd libsigrok4DSLogic
$ ./autogen.sh
$ ./configure
$ make
$ sudo make install
Step3: Build DSLogic-gui
Installing the requirements:
Example on Debian/Ubuntu (please check your respective distro's package manager tool if you use other distros):
$ sudo apt-get install git-core g++ make cmake libtool pkg-config \
libglib2.0-dev libqt4-dev libboost-dev libboost-test-dev libboost-thread-dev libboost-system-dev
Fedora (18, 19):
$ sudo yum install git gcc cmake libtool pkgconfig glib2-devel \
boost-devel qt-devel boost-devel
Building:
$ cd DSLogic-gui
$ cmake .
$ make
$ sudo make install
See the following wiki page for more (OS-specific) instructions:
http://sigrok.org/wiki/Building
-------------------------------------------------------------------------------
INSTALL
-------------------------------------------------------------------------------
Requirements
------------
libsigrok4DSLoigc
- gcc (>= 4.0)
- make
- autoconf >= 2.63
- automake >= 1.11
- libtool
- pkg-config >= 0.22
This is part of the standard OpenBSD install (not an extra package), apparently.
- libglib >= 2.32.0
- libzip >= 0.10
- libusb-1.0 >= 1.0.16
On FreeBSD, this is an integral part of the FreeBSD libc, not an extra package/library.
This is part of the standard OpenBSD install (not an extra package), apparently.
- check >= 0.9.4 (optional, only needed to run unit tests)
DSLgoic-gui
- git
- g++
- make
- libtool
- pkg-config >= 0.22
- cmake >= 2.6
- libglib >= 2.28.0
- Qt >= 4.5
- libboost >= 1.42 (including the following libs):
- libboost-system
- libboost-thread
- libsigrok4DSLogic >= 0.2.0
Building and installing
-----------------------
Get the DSLogic source code from: www.dreamsourcelab.com/download.html
Step1: Build libusbx-1.0.18
Building:
$ cd libusbx-1.0.18
$ ./configure
$ make
$ sudo make install
Step2: Build libsigrok4DSLogic
Installing the requirements:
Example on Debian/Ubuntu (please check your respective distro's package manager tool if you use other distros):
$ sudo apt-get install git-core gcc make autoconf automake libtool pkg-config \
libglib2.0-dev libzip-dev libudev-dev libasound2-dev check
Fedora (18, 19):
$ sudo yum install git gcc make autoconf automake libtool pkgconfig glib2-devel \
libzip-devel libudev-devel alsa-lib-devel check
OpenSuSE (12.2):
$ zypper install git gcc make autoconf automake libtool pkg-config glib2-devel \
libzip-devel libudev-devel alsa-devel check
Building:
$ cd libsigrok4DSLogic
$ ./autogen.sh
$ ./configure
$ make
$ sudo make install
Step3: Build DSLogic-gui
Installing the requirements:
Example on Debian/Ubuntu (please check your respective distro's package manager tool if you use other distros):
$ sudo apt-get install git-core g++ make cmake libtool pkg-config \
libglib2.0-dev libqt4-dev libboost-dev libboost-test-dev libboost-thread-dev libboost-system-dev
Fedora (18, 19):
$ sudo yum install git gcc cmake libtool pkgconfig glib2-devel \
boost-devel qt-devel boost-devel
Building:
$ cd DSLogic-gui
$ cmake .
$ make
$ sudo make install
See the following wiki page for more (OS-specific) instructions:
http://sigrok.org/wiki/Building

48
NEWS
View File

@ -1,18 +1,30 @@
0.1.0 (2013-12-15)
------------------
* Initial release.
0.2.0 (2014-04-13)
------------------
* Add DSLogic hardware support.
0.2.1 (2014-05-08)
------------------
* Add wireless extension hardware support.
* Fix libusb_error_io issue on Linux when sample rate >= 100MHz.
* Fix channel enable/disable bug.
* Fix device options config issue.
* Fix some display issues of UI.
0.1.0 (2013-12-15)
------------------
* Initial release.
0.2.0 (2014-04-13)
------------------
* Add DSLogic hardware support.
0.2.1 (2014-05-08)
------------------
* Add wireless extension hardware support.
* Fix libusb_error_io issue on Linux when sample rate >= 100MHz.
* Fix channel enable/disable bug.
* Fix device options config issue.
* Fix some display issues of UI.
0.3 (2014-06-29)
-----------------
* Add DSLogic Oscilloscope module support.
* Fix data display issue when not all channels be enabled.
* Fix issue of data mirrored to other channels.
* Fix radiobutton/checkbox display issue under certain windows theme.
* Add new simple trigger type
* Fix bugs of trigger setting and detection
* Fix other minior issues.
* Clean up the git repository

114
README
View File

@ -1,57 +1,57 @@
-------------------------------------------------------------------------------
README
-------------------------------------------------------------------------------
DSLogic is an open source multi-function instrument for everyone.
DSLogic software is based on sigrok project.
You can find DSLogic on:
www.dreamsourcelab.com
www.kickstarter.com/projects/dreamsourcelab/dslogic-multifunction-instruments-for-everyone
The sigrok project aims at creating a portable, cross-platform,
Free/Libre/Open-Source signal analysis software suite that supports various
device types (such as logic analyzers, oscilloscopes, multimeters, and more).
Status
------
DSLogic software is in a usable state and has had official tarball releases.
However, it is still work in progress. Some basic functionality
is available and working, but other things are still on the TODO list.
Copyright and license
---------------------
DSLogic software is licensed under the terms of the GNU General Public License
(GPL), version 3 or later.
While some individual source code files are licensed under the GPLv2+, and
some files are licensed under the GPLv3+, this doesn't change the fact that
the program as a whole is licensed under the terms of the GPLv3+ (e.g. also
due to the fact that it links against GPLv3+ libraries).
Please see the individual source files for the full list of copyright holders.
Copyright notices
-----------------
A copyright notice indicating a range of years, must be interpreted as having
had copyrightable material added in each of those years.
Example:
Copyright (C) 2010-2013 Contributor Name
is to be interpreted as
Copyright (C) 2010,2011,2012,2013 Contributor Name
Website
-------
http://dreamsourcelab.com
http://sigrok.org
-------------------------------------------------------------------------------
README
-------------------------------------------------------------------------------
DSLogic is an open source multi-function instrument for everyone.
DSLogic software is based on sigrok project.
You can find DSLogic on:
www.dreamsourcelab.com
www.kickstarter.com/projects/dreamsourcelab/dslogic-multifunction-instruments-for-everyone
The sigrok project aims at creating a portable, cross-platform,
Free/Libre/Open-Source signal analysis software suite that supports various
device types (such as logic analyzers, oscilloscopes, multimeters, and more).
Status
------
DSLogic software is in a usable state and has had official tarball releases.
However, it is still work in progress. Some basic functionality
is available and working, but other things are still on the TODO list.
Copyright and license
---------------------
DSLogic software is licensed under the terms of the GNU General Public License
(GPL), version 3 or later.
While some individual source code files are licensed under the GPLv2+, and
some files are licensed under the GPLv3+, this doesn't change the fact that
the program as a whole is licensed under the terms of the GPLv3+ (e.g. also
due to the fact that it links against GPLv3+ libraries).
Please see the individual source files for the full list of copyright holders.
Copyright notices
-----------------
A copyright notice indicating a range of years, must be interpreted as having
had copyrightable material added in each of those years.
Example:
Copyright (C) 2010-2013 Contributor Name
is to be interpreted as
Copyright (C) 2010,2011,2012,2013 Contributor Name
Website
-------
http://dreamsourcelab.com
http://sigrok.org

File diff suppressed because it is too large Load Diff

View File

@ -1,177 +1,208 @@
/*
* This file is part of the libsigrok project.
*
* Copyright (C) 2013 Bert Vermeulen <bert@biot.com>
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*/
#include <libusb.h>
#include "command.h"
//#include "libsigrok.h"
#include "libsigrok-internal.h"
#include "dslogic.h"
SR_PRIV int command_get_fw_version(libusb_device_handle *devhdl,
struct version_info *vi)
{
int ret;
ret = libusb_control_transfer(devhdl, LIBUSB_REQUEST_TYPE_VENDOR |
LIBUSB_ENDPOINT_IN, CMD_GET_FW_VERSION, 0x0000, 0x0000,
(unsigned char *)vi, sizeof(struct version_info), 100);
if (ret < 0) {
sr_err("Unable to get version info: %s.",
libusb_error_name(ret));
return SR_ERR;
}
return SR_OK;
}
SR_PRIV int command_get_revid_version(libusb_device_handle *devhdl,
uint8_t *revid)
{
int ret;
ret = libusb_control_transfer(devhdl, LIBUSB_REQUEST_TYPE_VENDOR |
LIBUSB_ENDPOINT_IN, CMD_GET_REVID_VERSION, 0x0000, 0x0000,
revid, 1, 100);
if (ret < 0) {
sr_err("Unable to get REVID: %s.", libusb_error_name(ret));
return SR_ERR;
}
return SR_OK;
}
SR_PRIV int command_start_acquisition(libusb_device_handle *devhdl,
uint64_t samplerate, gboolean samplewide)
{
struct cmd_start_acquisition cmd;
int delay = 0, ret;
/* Compute the sample rate. */
// if (samplewide && samplerate > MAX_16BIT_SAMPLE_RATE) {
// sr_err("Unable to sample at %" PRIu64 "Hz "
// "when collecting 16-bit samples.", samplerate);
// return SR_ERR;
// }
// if ((SR_MHZ(48) % samplerate) == 0) {
// cmd.flags = CMD_START_FLAGS_CLK_48MHZ;
// delay = SR_MHZ(48) / samplerate - 1;
// if (delay > MAX_SAMPLE_DELAY)
// delay = 0;
// }
// if (delay == 0 && (SR_MHZ(30) % samplerate) == 0) {
// cmd.flags = CMD_START_FLAGS_CLK_30MHZ;
// delay = SR_MHZ(30) / samplerate - 1;
// }
cmd.flags = CMD_START_FLAGS_CLK_30MHZ;
delay = 0;
sr_info("GPIF delay = %d, clocksource = %sMHz.", delay,
(cmd.flags & CMD_START_FLAGS_CLK_48MHZ) ? "48" : "30");
// if (delay <= 0 || delay > MAX_SAMPLE_DELAY) {
// sr_err("Unable to sample at %" PRIu64 "Hz.", samplerate);
// return SR_ERR;
// }
cmd.sample_delay_h = (delay >> 8) & 0xff;
cmd.sample_delay_l = delay & 0xff;
/* Select the sampling width. */
cmd.flags |= samplewide ? CMD_START_FLAGS_SAMPLE_16BIT :
CMD_START_FLAGS_SAMPLE_8BIT;
/* Send the control message. */
ret = libusb_control_transfer(devhdl, LIBUSB_REQUEST_TYPE_VENDOR |
LIBUSB_ENDPOINT_OUT, CMD_START, 0x0000, 0x0000,
(unsigned char *)&cmd, sizeof(cmd), 3000);
if (ret < 0) {
sr_err("Unable to send start command: %s.",
libusb_error_name(ret));
return SR_ERR;
}
return SR_OK;
}
SR_PRIV int command_stop_acquisition(libusb_device_handle *devhdl)
{
struct cmd_start_acquisition cmd;
int ret;
/* stop acquisition command */
cmd.flags = CMD_START_FLAGS_STOP;
cmd.sample_delay_h = 0;
cmd.sample_delay_l = 0;
/* Send the control message. */
ret = libusb_control_transfer(devhdl, LIBUSB_REQUEST_TYPE_VENDOR |
LIBUSB_ENDPOINT_OUT, CMD_START, 0x0000, 0x0000,
(unsigned char *)&cmd, sizeof(cmd), 3000);
if (ret < 0) {
sr_err("Unable to send stop command: %s.",
libusb_error_name(ret));
return SR_ERR;
}
return SR_OK;
}
SR_PRIV int command_fpga_config(libusb_device_handle *devhdl)
{
int ret;
/* Send the control message. */
ret = libusb_control_transfer(devhdl, LIBUSB_REQUEST_TYPE_VENDOR |
LIBUSB_ENDPOINT_OUT, CMD_CONFIG, 0x0000, 0x0000,
NULL, 0, 3000);
if (ret < 0) {
sr_err("Unable to send FPGA configure command: %s.",
libusb_error_name(ret));
return SR_ERR;
}
return SR_OK;
}
SR_PRIV int command_fpga_setting(libusb_device_handle *devhdl, uint32_t setting_count)
{
struct cmd_setting_count cmd;
int ret;
/* ... */
cmd.byte0 = (uint8_t)setting_count;
cmd.byte1 = (uint8_t)(setting_count >> 8);
cmd.byte2 = (uint8_t)(setting_count >> 16);
/* Send the control message. */
ret = libusb_control_transfer(devhdl, LIBUSB_REQUEST_TYPE_VENDOR |
LIBUSB_ENDPOINT_OUT, CMD_SETTING, 0x0000, 0x0000,
(unsigned char *)&cmd, sizeof(cmd), 100);
if (ret < 0) {
sr_err("Unable to send FPGA setting command: %s.",
libusb_error_name(ret));
return SR_ERR;
}
return SR_OK;
}
/*
* This file is part of the libsigrok project.
*
* Copyright (C) 2013 Bert Vermeulen <bert@biot.com>
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*/
#include <libusb.h>
#include "command.h"
//#include "libsigrok.h"
#include "libsigrok-internal.h"
#include "dslogic.h"
SR_PRIV int command_get_fw_version(libusb_device_handle *devhdl,
struct version_info *vi)
{
int ret;
ret = libusb_control_transfer(devhdl, LIBUSB_REQUEST_TYPE_VENDOR |
LIBUSB_ENDPOINT_IN, CMD_GET_FW_VERSION, 0x0000, 0x0000,
(unsigned char *)vi, sizeof(struct version_info), 100);
if (ret < 0) {
sr_err("Unable to get version info: %s.",
libusb_error_name(ret));
return SR_ERR;
}
return SR_OK;
}
SR_PRIV int command_get_revid_version(libusb_device_handle *devhdl,
uint8_t *revid)
{
int ret;
ret = libusb_control_transfer(devhdl, LIBUSB_REQUEST_TYPE_VENDOR |
LIBUSB_ENDPOINT_IN, CMD_GET_REVID_VERSION, 0x0000, 0x0000,
revid, 1, 100);
if (ret < 0) {
sr_err("Unable to get REVID: %s.", libusb_error_name(ret));
return SR_ERR;
}
return SR_OK;
}
SR_PRIV int command_start_acquisition(libusb_device_handle *devhdl,
uint64_t samplerate, gboolean samplewide)
{
struct cmd_start_acquisition cmd;
int delay = 0, ret;
/* Compute the sample rate. */
// if (samplewide && samplerate > MAX_16BIT_SAMPLE_RATE) {
// sr_err("Unable to sample at %" PRIu64 "Hz "
// "when collecting 16-bit samples.", samplerate);
// return SR_ERR;
// }
// if ((SR_MHZ(48) % samplerate) == 0) {
// cmd.flags = CMD_START_FLAGS_CLK_48MHZ;
// delay = SR_MHZ(48) / samplerate - 1;
// if (delay > MAX_SAMPLE_DELAY)
// delay = 0;
// }
// if (delay == 0 && (SR_MHZ(30) % samplerate) == 0) {
// cmd.flags = CMD_START_FLAGS_CLK_30MHZ;
// delay = SR_MHZ(30) / samplerate - 1;
// }
cmd.flags = CMD_START_FLAGS_CLK_30MHZ;
delay = 0;
sr_info("GPIF delay = %d, clocksource = %sMHz.", delay,
(cmd.flags & CMD_START_FLAGS_CLK_48MHZ) ? "48" : "30");
// if (delay <= 0 || delay > MAX_SAMPLE_DELAY) {
// sr_err("Unable to sample at %" PRIu64 "Hz.", samplerate);
// return SR_ERR;
// }
cmd.sample_delay_h = (delay >> 8) & 0xff;
cmd.sample_delay_l = delay & 0xff;
/* Select the sampling width. */
cmd.flags |= samplewide ? CMD_START_FLAGS_SAMPLE_16BIT :
CMD_START_FLAGS_SAMPLE_8BIT;
/* Send the control message. */
ret = libusb_control_transfer(devhdl, LIBUSB_REQUEST_TYPE_VENDOR |
LIBUSB_ENDPOINT_OUT, CMD_START, 0x0000, 0x0000,
(unsigned char *)&cmd, sizeof(cmd), 3000);
if (ret < 0) {
sr_err("Unable to send start command: %s.",
libusb_error_name(ret));
return SR_ERR;
}
return SR_OK;
}
SR_PRIV int command_stop_acquisition(libusb_device_handle *devhdl)
{
struct cmd_start_acquisition cmd;
int ret;
/* stop acquisition command */
cmd.flags = CMD_START_FLAGS_STOP;
cmd.sample_delay_h = 0;
cmd.sample_delay_l = 0;
/* Send the control message. */
ret = libusb_control_transfer(devhdl, LIBUSB_REQUEST_TYPE_VENDOR |
LIBUSB_ENDPOINT_OUT, CMD_START, 0x0000, 0x0000,
(unsigned char *)&cmd, sizeof(cmd), 3000);
if (ret < 0) {
sr_err("Unable to send stop command: %s.",
libusb_error_name(ret));
return SR_ERR;
}
return SR_OK;
}
SR_PRIV int command_fpga_config(libusb_device_handle *devhdl)
{
struct cmd_cfg_count cmd;
int ret;
/* ... */
cmd.byte0 = (uint8_t)XC6SLX9_BYTE_CNT;
cmd.byte1 = (uint8_t)(XC6SLX9_BYTE_CNT >> 8);
cmd.byte2 = (uint8_t)(XC6SLX9_BYTE_CNT >> 16);
/* Send the control message. */
ret = libusb_control_transfer(devhdl, LIBUSB_REQUEST_TYPE_VENDOR |
LIBUSB_ENDPOINT_OUT, CMD_CONFIG, 0x0000, 0x0000,
(unsigned char *)&cmd, sizeof(cmd), 3000);
if (ret < 0) {
sr_err("Unable to send FPGA configure command: %s.",
libusb_error_name(ret));
return SR_ERR;
}
return SR_OK;
}
SR_PRIV int command_fpga_setting(libusb_device_handle *devhdl, uint32_t setting_count)
{
struct cmd_setting_count cmd;
int ret;
/* ... */
cmd.byte0 = (uint8_t)setting_count;
cmd.byte1 = (uint8_t)(setting_count >> 8);
cmd.byte2 = (uint8_t)(setting_count >> 16);
/* Send the control message. */
ret = libusb_control_transfer(devhdl, LIBUSB_REQUEST_TYPE_VENDOR |
LIBUSB_ENDPOINT_OUT, CMD_SETTING, 0x0000, 0x0000,
(unsigned char *)&cmd, sizeof(cmd), 3000);
if (ret < 0) {
sr_err("Unable to send FPGA setting command: %s.",
libusb_error_name(ret));
return SR_ERR;
}
return SR_OK;
}
SR_PRIV int command_dso_ctrl(libusb_device_handle *devhdl, uint32_t command)
{
struct cmd_control cmd;
int ret;
/* ... */
cmd.byte0 = (uint8_t)command;
cmd.byte1 = (uint8_t)(command >> 8);
cmd.byte2 = (uint8_t)(command >> 16);
cmd.byte3 = (uint8_t)(command >> 24);
/* Send the control command. */
ret = libusb_control_transfer(devhdl, LIBUSB_REQUEST_TYPE_VENDOR |
LIBUSB_ENDPOINT_OUT, CMD_CONTROL, 0x0000, 0x0000,
(unsigned char *)&cmd, sizeof(cmd), 3000);
if (ret < 0) {
sr_err("Unable to send oscilloscope control command: %s.",
libusb_error_name(ret));
return SR_ERR;
}
return SR_OK;
}

View File

@ -1,79 +1,93 @@
/*
* This file is part of the libsigrok project.
*
* Copyright (C) 2013 Bert Vermeulen <bert@biot.com>
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef LIBDSLOGIC_HARDWARE_COMMAND_H
#define LIBDSLOGIC_HARDWARE_COMMAND_H
#include <glib.h>
#include "libsigrok.h"
/* Protocol commands */
#define CMD_GET_FW_VERSION 0xb0
#define CMD_GET_REVID_VERSION 0xb1
#define CMD_START 0xb2
#define CMD_CONFIG 0xb3
#define CMD_SETTING 0xb4
#define CMD_START_FLAGS_WIDE_POS 5
#define CMD_START_FLAGS_CLK_SRC_POS 6
#define CMD_START_FLAGS_STOP_POS 7
#define CMD_START_FLAGS_SAMPLE_8BIT (0 << CMD_START_FLAGS_WIDE_POS)
#define CMD_START_FLAGS_SAMPLE_16BIT (1 << CMD_START_FLAGS_WIDE_POS)
#define CMD_START_FLAGS_CLK_30MHZ (0 << CMD_START_FLAGS_CLK_SRC_POS)
#define CMD_START_FLAGS_CLK_48MHZ (1 << CMD_START_FLAGS_CLK_SRC_POS)
#define CMD_START_FLAGS_STOP (1 << CMD_START_FLAGS_STOP_POS)
#pragma pack(push, 1)
struct version_info {
uint8_t major;
uint8_t minor;
};
struct cmd_start_acquisition {
uint8_t flags;
uint8_t sample_delay_h;
uint8_t sample_delay_l;
};
struct cmd_setting_count {
uint8_t byte0;
uint8_t byte1;
uint8_t byte2;
};
#pragma pack(pop)
SR_PRIV int command_get_fw_version(libusb_device_handle *devhdl,
struct version_info *vi);
SR_PRIV int command_get_revid_version(libusb_device_handle *devhdl,
uint8_t *revid);
SR_PRIV int command_start_acquisition(libusb_device_handle *devhdl,
uint64_t samplerate, gboolean samplewide);
SR_PRIV int command_stop_acquistition(libusb_device_handle *devhdl);
SR_PRIV int command_fpga_config(libusb_device_handle *devhdl);
SR_PRIV int command_fpga_setting(libusb_device_handle *devhdl, uint32_t setting_count);
#endif
/*
* This file is part of the libsigrok project.
*
* Copyright (C) 2013 Bert Vermeulen <bert@biot.com>
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef LIBDSLOGIC_HARDWARE_COMMAND_H
#define LIBDSLOGIC_HARDWARE_COMMAND_H
#include <glib.h>
#include "libsigrok.h"
/* Protocol commands */
#define CMD_GET_FW_VERSION 0xb0
#define CMD_GET_REVID_VERSION 0xb1
#define CMD_START 0xb2
#define CMD_CONFIG 0xb3
#define CMD_SETTING 0xb4
#define CMD_CONTROL 0xb5
#define CMD_START_FLAGS_WIDE_POS 5
#define CMD_START_FLAGS_CLK_SRC_POS 6
#define CMD_START_FLAGS_STOP_POS 7
#define CMD_START_FLAGS_SAMPLE_8BIT (0 << CMD_START_FLAGS_WIDE_POS)
#define CMD_START_FLAGS_SAMPLE_16BIT (1 << CMD_START_FLAGS_WIDE_POS)
#define CMD_START_FLAGS_CLK_30MHZ (0 << CMD_START_FLAGS_CLK_SRC_POS)
#define CMD_START_FLAGS_CLK_48MHZ (1 << CMD_START_FLAGS_CLK_SRC_POS)
#define CMD_START_FLAGS_STOP (1 << CMD_START_FLAGS_STOP_POS)
#pragma pack(push, 1)
struct version_info {
uint8_t major;
uint8_t minor;
};
struct cmd_start_acquisition {
uint8_t flags;
uint8_t sample_delay_h;
uint8_t sample_delay_l;
};
struct cmd_setting_count {
uint8_t byte0;
uint8_t byte1;
uint8_t byte2;
};
struct cmd_cfg_count {
uint8_t byte0;
uint8_t byte1;
uint8_t byte2;
};
struct cmd_control {
uint8_t byte0;
uint8_t byte1;
uint8_t byte2;
uint8_t byte3;
};
#pragma pack(pop)
SR_PRIV int command_get_fw_version(libusb_device_handle *devhdl,
struct version_info *vi);
SR_PRIV int command_get_revid_version(libusb_device_handle *devhdl,
uint8_t *revid);
SR_PRIV int command_start_acquisition(libusb_device_handle *devhdl,
uint64_t samplerate, gboolean samplewide);
SR_PRIV int command_stop_acquistition(libusb_device_handle *devhdl);
SR_PRIV int command_fpga_config(libusb_device_handle *devhdl);
SR_PRIV int command_fpga_setting(libusb_device_handle *devhdl, uint32_t setting_count);
SR_PRIV int command_dso_ctrl(libusb_device_handle *devhdl, uint32_t command);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,196 +1,212 @@
/*
* This file is part of the libsigrok project.
*
* Copyright (C) 2013 Bert Vermeulen <bert@biot.com>
* Copyright (C) 2013 DreamSourceLab <dreamsourcelab@dreamsourcelab.com>
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef LIBDSLOGIC_HARDWARE_DSLOGIC_H
#define LIBDSLOGIC_HARDWARE_DSLOGIC_H
#include <glib.h>
/* Message logging helpers with subsystem-specific prefix string. */
#define LOG_PREFIX "DSLogic Hardware: "
#define ds_log(l, s, args...) ds_log(l, LOG_PREFIX s, ## args)
#define ds_spew(s, args...) ds_spew(LOG_PREFIX s, ## args)
#define ds_dbg(s, args...) ds_dbg(LOG_PREFIX s, ## args)
#define ds_info(s, args...) ds_info(LOG_PREFIX s, ## args)
#define ds_warn(s, args...) ds_warn(LOG_PREFIX s, ## args)
#define ds_err(s, args...) ds_err(LOG_PREFIX s, ## args)
#define USB_INTERFACE 0
#define USB_CONFIGURATION 1
#define NUM_TRIGGER_STAGES 16
#define TRIGGER_TYPE "01"
#define MAX_RENUM_DELAY_MS 3000
#define NUM_SIMUL_TRANSFERS 64
#define MAX_EMPTY_TRANSFERS (NUM_SIMUL_TRANSFERS * 2)
#define DSLOGIC_REQUIRED_VERSION_MAJOR 1
#define MAX_8BIT_SAMPLE_RATE DS_MHZ(24)
#define MAX_16BIT_SAMPLE_RATE DS_MHZ(12)
/* 6 delay states of up to 256 clock ticks */
#define MAX_SAMPLE_DELAY (6 * 256)
/* Software trigger implementation: positive values indicate trigger stage. */
#define TRIGGER_FIRED -1
#define DEV_CAPS_16BIT_POS 0
#define DEV_CAPS_16BIT (1 << DEV_CAPS_16BIT_POS)
#define XC3S250E_BYTE_CNT 169216
//#define XC6SLX9_BYTE_CNT 340884
#define XC6SLX9_BYTE_CNT 340604
#define MAX_ANALOG_PROBES_NUM 9
#define MAX_DSO_PROBES_NUM 2
struct DSLogic_profile {
uint16_t vid;
uint16_t pid;
const char *vendor;
const char *model;
const char *model_version;
const char *firmware;
const char *fpga_bit;
uint32_t dev_caps;
};
static const struct DSLogic_profile supported_fx2[3] = {
/*
* DSLogic
*/
{0x2A0E, 0x0001, NULL, "DSLogic", NULL,
"DSLogic.fw",
"DSLogic.bin",
DEV_CAPS_16BIT},
{ 0, 0, 0, 0, 0, 0, 0 }
};
enum {
DSLOGIC_ERROR = -1,
DSLOGIC_INIT = 0,
DSLOGIC_START = 1,
DSLOGIC_TRIGGERED = 2,
DSLOGIC_DATA = 3,
DSLOGIC_STOP = 4,
};
struct dev_context {
const struct DSLogic_profile *profile;
/*
* Since we can't keep track of an DSLogic device after upgrading
* the firmware (it renumerates into a different device address
* after the upgrade) this is like a global lock. No device will open
* until a proper delay after the last device was upgraded.
*/
int64_t fw_updated;
/* Device/capture settings */
uint64_t cur_samplerate;
uint64_t limit_samples;
/* Operational settings */
gboolean sample_wide;
gboolean clock_type;
uint16_t op_mode;
uint16_t trigger_mask[NUM_TRIGGER_STAGES];
uint16_t trigger_value[NUM_TRIGGER_STAGES];
int trigger_stage;
uint16_t trigger_buffer[NUM_TRIGGER_STAGES];
int num_samples;
int submitted_transfers;
int empty_transfer_count;
void *cb_data;
unsigned int num_transfers;
struct libusb_transfer **transfers;
int *usbfd;
int status;
};
struct DSLogic_setting {
uint32_t sync;
uint16_t mode_header; // 0
uint16_t mode;
uint32_t divider_header; // 1-2
uint32_t divider;
uint32_t count_header; // 3-4
uint32_t count;
uint32_t trig_pos_header; // 5-6
uint32_t trig_pos;
uint16_t trig_glb_header; // 7
uint16_t trig_glb;
uint32_t trig_adp_header; // 10-11
uint32_t trig_adp;
uint32_t trig_sda_header; // 12-13
uint32_t trig_sda;
uint32_t trig_mask0_header; // 16
uint16_t trig_mask0[NUM_TRIGGER_STAGES];
uint32_t trig_mask1_header; // 17
uint16_t trig_mask1[NUM_TRIGGER_STAGES];
//uint32_t trig_mask2_header; // 18
//uint16_t trig_mask2[NUM_TRIGGER_STAGES];
//uint32_t trig_mask3_header; // 19
//uint16_t trig_mask3[NUM_TRIGGER_STAGES];
uint32_t trig_value0_header; // 20
uint16_t trig_value0[NUM_TRIGGER_STAGES];
uint32_t trig_value1_header; // 21
uint16_t trig_value1[NUM_TRIGGER_STAGES];
//uint32_t trig_value2_header; // 22
//uint16_t trig_value2[NUM_TRIGGER_STAGES];
//uint32_t trig_value3_header; // 23
//uint16_t trig_value3[NUM_TRIGGER_STAGES];
uint32_t trig_edge0_header; // 24
uint16_t trig_edge0[NUM_TRIGGER_STAGES];
uint32_t trig_edge1_header; // 25
uint16_t trig_edge1[NUM_TRIGGER_STAGES];
//uint32_t trig_edge2_header; // 26
//uint16_t trig_edge2[NUM_TRIGGER_STAGES];
//uint32_t trig_edge3_header; // 27
//uint16_t trig_edge3[NUM_TRIGGER_STAGES];
uint32_t trig_count0_header; // 28
uint16_t trig_count0[NUM_TRIGGER_STAGES];
uint32_t trig_count1_header; // 29
uint16_t trig_count1[NUM_TRIGGER_STAGES];
//uint32_t trig_count2_header; // 30
//uint16_t trig_count2[NUM_TRIGGER_STAGES];
//uint32_t trig_count3_header; // 31
//uint16_t trig_count3[NUM_TRIGGER_STAGES];
uint32_t trig_logic0_header; // 32
uint16_t trig_logic0[NUM_TRIGGER_STAGES];
uint32_t trig_logic1_header; // 33
uint16_t trig_logic1[NUM_TRIGGER_STAGES];
//uint32_t trig_logic2_header; // 34
//uint16_t trig_logic2[NUM_TRIGGER_STAGES];
//uint32_t trig_logic3_header; // 35
//uint16_t trig_logic3[NUM_TRIGGER_STAGES];
uint32_t end_sync;
};
#endif
/*
* This file is part of the libsigrok project.
*
* Copyright (C) 2013 Bert Vermeulen <bert@biot.com>
* Copyright (C) 2013 DreamSourceLab <dreamsourcelab@dreamsourcelab.com>
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef LIBDSLOGIC_HARDWARE_DSLOGIC_H
#define LIBDSLOGIC_HARDWARE_DSLOGIC_H
#include <glib.h>
/* Message logging helpers with subsystem-specific prefix string. */
#define LOG_PREFIX "DSLogic Hardware: "
#define ds_log(l, s, args...) ds_log(l, LOG_PREFIX s, ## args)
#define ds_spew(s, args...) ds_spew(LOG_PREFIX s, ## args)
#define ds_dbg(s, args...) ds_dbg(LOG_PREFIX s, ## args)
#define ds_info(s, args...) ds_info(LOG_PREFIX s, ## args)
#define ds_warn(s, args...) ds_warn(LOG_PREFIX s, ## args)
#define ds_err(s, args...) ds_err(LOG_PREFIX s, ## args)
#define USB_INTERFACE 0
#define USB_CONFIGURATION 1
#define NUM_TRIGGER_STAGES 16
#define TRIGGER_TYPE "01"
#define MAX_RENUM_DELAY_MS 3000
#define NUM_SIMUL_TRANSFERS 64
#define MAX_EMPTY_TRANSFERS (NUM_SIMUL_TRANSFERS * 2)
#define DSLOGIC_REQUIRED_VERSION_MAJOR 1
#define MAX_8BIT_SAMPLE_RATE DS_MHZ(24)
#define MAX_16BIT_SAMPLE_RATE DS_MHZ(12)
/* 6 delay states of up to 256 clock ticks */
#define MAX_SAMPLE_DELAY (6 * 256)
/* Software trigger implementation: positive values indicate trigger stage. */
#define TRIGGER_FIRED -1
#define DEV_CAPS_16BIT_POS 0
#define DEV_CAPS_16BIT (1 << DEV_CAPS_16BIT_POS)
#define XC3S250E_BYTE_CNT 169216
//#define XC6SLX9_BYTE_CNT 341160
#define XC6SLX9_BYTE_CNT 340884
//#define XC6SLX9_BYTE_CNT 340604
#define MAX_ANALOG_PROBES_NUM 9
#define MAX_DSO_PROBES_NUM 2
struct DSLogic_profile {
uint16_t vid;
uint16_t pid;
const char *vendor;
const char *model;
const char *model_version;
const char *firmware;
const char *fpga_bit;
uint32_t dev_caps;
};
static const struct DSLogic_profile supported_fx2[3] = {
/*
* DSLogic
*/
{0x2A0E, 0x0001, NULL, "DSLogic", NULL,
"DSLogic.fw",
"DSLogic.bin",
DEV_CAPS_16BIT},
{ 0, 0, 0, 0, 0, 0, 0 }
};
enum {
DSLOGIC_ERROR = -1,
DSLOGIC_INIT = 0,
DSLOGIC_START = 1,
DSLOGIC_TRIGGERED = 2,
DSLOGIC_DATA = 3,
DSLOGIC_STOP = 4,
};
struct dev_context {
const struct DSLogic_profile *profile;
/*
* Since we can't keep track of an DSLogic device after upgrading
* the firmware (it renumerates into a different device address
* after the upgrade) this is like a global lock. No device will open
* until a proper delay after the last device was upgraded.
*/
int64_t fw_updated;
/* Device/capture settings */
uint64_t cur_samplerate;
uint64_t limit_samples;
/* Operational settings */
gboolean sample_wide;
gboolean clock_type;
uint16_t op_mode;
uint16_t trigger_mask[NUM_TRIGGER_STAGES];
uint16_t trigger_value[NUM_TRIGGER_STAGES];
int trigger_stage;
uint16_t trigger_buffer[NUM_TRIGGER_STAGES];
uint64_t vdiv0;
uint64_t vdiv1;
uint64_t timebase;
gboolean coupling0;
gboolean coupling1;
gboolean en_ch0;
gboolean en_ch1;
uint8_t trigger_slope;
uint8_t trigger_source;
uint16_t trigger_vpos;
uint32_t trigger_hpos;
gboolean zero;
int num_samples;
int submitted_transfers;
int empty_transfer_count;
void *cb_data;
unsigned int num_transfers;
struct libusb_transfer **transfers;
int *usbfd;
int pipe_fds[2];
GIOChannel *channel;
int status;
};
struct DSLogic_setting {
uint32_t sync;
uint16_t mode_header; // 0
uint16_t mode;
uint32_t divider_header; // 1-2
uint32_t divider;
uint32_t count_header; // 3-4
uint32_t count;
uint32_t trig_pos_header; // 5-6
uint32_t trig_pos;
uint16_t trig_glb_header; // 7
uint16_t trig_glb;
uint32_t trig_adp_header; // 10-11
uint32_t trig_adp;
uint32_t trig_sda_header; // 12-13
uint32_t trig_sda;
uint32_t trig_mask0_header; // 16
uint16_t trig_mask0[NUM_TRIGGER_STAGES];
uint32_t trig_mask1_header; // 17
uint16_t trig_mask1[NUM_TRIGGER_STAGES];
//uint32_t trig_mask2_header; // 18
//uint16_t trig_mask2[NUM_TRIGGER_STAGES];
//uint32_t trig_mask3_header; // 19
//uint16_t trig_mask3[NUM_TRIGGER_STAGES];
uint32_t trig_value0_header; // 20
uint16_t trig_value0[NUM_TRIGGER_STAGES];
uint32_t trig_value1_header; // 21
uint16_t trig_value1[NUM_TRIGGER_STAGES];
//uint32_t trig_value2_header; // 22
//uint16_t trig_value2[NUM_TRIGGER_STAGES];
//uint32_t trig_value3_header; // 23
//uint16_t trig_value3[NUM_TRIGGER_STAGES];
uint32_t trig_edge0_header; // 24
uint16_t trig_edge0[NUM_TRIGGER_STAGES];
uint32_t trig_edge1_header; // 25
uint16_t trig_edge1[NUM_TRIGGER_STAGES];
//uint32_t trig_edge2_header; // 26
//uint16_t trig_edge2[NUM_TRIGGER_STAGES];
//uint32_t trig_edge3_header; // 27
//uint16_t trig_edge3[NUM_TRIGGER_STAGES];
uint32_t trig_count0_header; // 28
uint16_t trig_count0[NUM_TRIGGER_STAGES];
uint32_t trig_count1_header; // 29
uint16_t trig_count1[NUM_TRIGGER_STAGES];
//uint32_t trig_count2_header; // 30
//uint16_t trig_count2[NUM_TRIGGER_STAGES];
//uint32_t trig_count3_header; // 31
//uint16_t trig_count3[NUM_TRIGGER_STAGES];
uint32_t trig_logic0_header; // 32
uint16_t trig_logic0[NUM_TRIGGER_STAGES];
uint32_t trig_logic1_header; // 33
uint16_t trig_logic1[NUM_TRIGGER_STAGES];
//uint32_t trig_logic2_header; // 34
//uint16_t trig_logic2[NUM_TRIGGER_STAGES];
//uint32_t trig_logic3_header; // 35
//uint16_t trig_logic3[NUM_TRIGGER_STAGES];
uint32_t end_sync;
};
#endif

View File

@ -1,143 +1,143 @@
/*
* This file is part of the libsigrok project.
*
* Copyright (C) 2013 Bert Vermeulen <bert@biot.com>
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*/
/*
* Helper functions for the Cypress EZ-USB / FX2 series chips.
*/
#include <libusb.h>
#include <glib.h>
#include <glib/gstdio.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include "libsigrok.h"
#include "libsigrok-internal.h"
/* Message logging helpers with subsystem-specific prefix string. */
#define LOG_PREFIX "ezusb: "
#define sr_log(l, s, args...) sr_log(l, LOG_PREFIX s, ## args)
#define sr_spew(s, args...) sr_spew(LOG_PREFIX s, ## args)
#define sr_dbg(s, args...) sr_dbg(LOG_PREFIX s, ## args)
#define sr_info(s, args...) sr_info(LOG_PREFIX s, ## args)
#define sr_warn(s, args...) sr_warn(LOG_PREFIX s, ## args)
#define sr_err(s, args...) sr_err(LOG_PREFIX s, ## args)
SR_PRIV int ezusb_reset(struct libusb_device_handle *hdl, int set_clear)
{
int ret;
unsigned char buf[1];
sr_info("setting CPU reset mode %s...",
set_clear ? "on" : "off");
buf[0] = set_clear ? 1 : 0;
ret = libusb_control_transfer(hdl, LIBUSB_REQUEST_TYPE_VENDOR, 0xa0,
0xe600, 0x0000, buf, 1, 100);
if (ret < 0)
sr_err("Unable to send control request: %s.",
libusb_error_name(ret));
return ret;
}
SR_PRIV int ezusb_install_firmware(libusb_device_handle *hdl,
const char *filename)
{
FILE *fw;
int offset, chunksize, ret, result;
unsigned char buf[4096];
sr_info("Uploading firmware at %s", filename);
if ((fw = g_fopen(filename, "rb")) == NULL) {
sr_err("Unable to open firmware file %s for reading: %s",
filename, strerror(errno));
return SR_ERR;
}
result = SR_OK;
offset = 0;
while (1) {
chunksize = fread(buf, 1, 4096, fw);
if (chunksize == 0)
break;
ret = libusb_control_transfer(hdl, LIBUSB_REQUEST_TYPE_VENDOR |
LIBUSB_ENDPOINT_OUT, 0xa0, offset,
0x0000, buf, chunksize, 100);
if (ret < 0) {
sr_err("Unable to send firmware to device: %s.",
libusb_error_name(ret));
result = SR_ERR;
break;
}
sr_info("Uploaded %d bytes", chunksize);
offset += chunksize;
}
fclose(fw);
sr_info("Firmware upload done");
return result;
}
SR_PRIV int ezusb_upload_firmware(libusb_device *dev, int configuration,
const char *filename)
{
struct libusb_device_handle *hdl;
int ret;
sr_info("uploading firmware to device on %d.%d",
libusb_get_bus_number(dev), libusb_get_device_address(dev));
if ((ret = libusb_open(dev, &hdl)) < 0) {
sr_err("failed to open device: %s.", libusb_error_name(ret));
return SR_ERR;
}
/*
* The libusbx darwin backend is broken: it can report a kernel driver being
* active, but detaching it always returns an error.
*/
#if !defined(__APPLE__)
if (libusb_kernel_driver_active(hdl, 0) == 1) {
if ((ret = libusb_detach_kernel_driver(hdl, 0)) < 0) {
sr_err("failed to detach kernel driver: %s",
libusb_error_name(ret));
return SR_ERR;
}
}
#endif
if ((ret = libusb_set_configuration(hdl, configuration)) < 0) {
sr_err("Unable to set configuration: %s",
libusb_error_name(ret));
return SR_ERR;
}
if ((ezusb_reset(hdl, 1)) < 0)
return SR_ERR;
if (ezusb_install_firmware(hdl, filename) < 0)
return SR_ERR;
if ((ezusb_reset(hdl, 0)) < 0)
return SR_ERR;
libusb_close(hdl);
return SR_OK;
}
/*
* This file is part of the libsigrok project.
*
* Copyright (C) 2013 Bert Vermeulen <bert@biot.com>
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*/
/*
* Helper functions for the Cypress EZ-USB / FX2 series chips.
*/
#include <libusb.h>
#include <glib.h>
#include <glib/gstdio.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include "libsigrok.h"
#include "libsigrok-internal.h"
/* Message logging helpers with subsystem-specific prefix string. */
#define LOG_PREFIX "ezusb: "
#define sr_log(l, s, args...) sr_log(l, LOG_PREFIX s, ## args)
#define sr_spew(s, args...) sr_spew(LOG_PREFIX s, ## args)
#define sr_dbg(s, args...) sr_dbg(LOG_PREFIX s, ## args)
#define sr_info(s, args...) sr_info(LOG_PREFIX s, ## args)
#define sr_warn(s, args...) sr_warn(LOG_PREFIX s, ## args)
#define sr_err(s, args...) sr_err(LOG_PREFIX s, ## args)
SR_PRIV int ezusb_reset(struct libusb_device_handle *hdl, int set_clear)
{
int ret;
unsigned char buf[1];
sr_info("setting CPU reset mode %s...",
set_clear ? "on" : "off");
buf[0] = set_clear ? 1 : 0;
ret = libusb_control_transfer(hdl, LIBUSB_REQUEST_TYPE_VENDOR, 0xa0,
0xe600, 0x0000, buf, 1, 100);
if (ret < 0)
sr_err("Unable to send control request: %s.",
libusb_error_name(ret));
return ret;
}
SR_PRIV int ezusb_install_firmware(libusb_device_handle *hdl,
const char *filename)
{
FILE *fw;
int offset, chunksize, ret, result;
unsigned char buf[4096];
sr_info("Uploading firmware at %s", filename);
if ((fw = g_fopen(filename, "rb")) == NULL) {
sr_err("Unable to open firmware file %s for reading: %s",
filename, strerror(errno));
return SR_ERR;
}
result = SR_OK;
offset = 0;
while (1) {
chunksize = fread(buf, 1, 4096, fw);
if (chunksize == 0)
break;
ret = libusb_control_transfer(hdl, LIBUSB_REQUEST_TYPE_VENDOR |
LIBUSB_ENDPOINT_OUT, 0xa0, offset,
0x0000, buf, chunksize, 100);
if (ret < 0) {
sr_err("Unable to send firmware to device: %s.",
libusb_error_name(ret));
result = SR_ERR;
break;
}
sr_info("Uploaded %d bytes", chunksize);
offset += chunksize;
}
fclose(fw);
sr_info("Firmware upload done");
return result;
}
SR_PRIV int ezusb_upload_firmware(libusb_device *dev, int configuration,
const char *filename)
{
struct libusb_device_handle *hdl;
int ret;
sr_info("uploading firmware to device on %d.%d",
libusb_get_bus_number(dev), libusb_get_device_address(dev));
if ((ret = libusb_open(dev, &hdl)) < 0) {
sr_err("failed to open device: %s.", libusb_error_name(ret));
return SR_ERR;
}
/*
* The libusbx darwin backend is broken: it can report a kernel driver being
* active, but detaching it always returns an error.
*/
#if !defined(__APPLE__)
if (libusb_kernel_driver_active(hdl, 0) == 1) {
if ((ret = libusb_detach_kernel_driver(hdl, 0)) < 0) {
sr_err("failed to detach kernel driver: %s",
libusb_error_name(ret));
return SR_ERR;
}
}
#endif
if ((ret = libusb_set_configuration(hdl, configuration)) < 0) {
sr_err("Unable to set configuration: %s",
libusb_error_name(ret));
return SR_ERR;
}
if ((ezusb_reset(hdl, 1)) < 0)
return SR_ERR;
if (ezusb_install_firmware(hdl, filename) < 0)
return SR_ERR;
if ((ezusb_reset(hdl, 0)) < 0)
return SR_ERR;
libusb_close(hdl);
return SR_OK;
}

View File

@ -1,245 +1,245 @@
/*
* This file is part of the libsigrok project.
*
* Copyright (C) 2013 Bert Vermeulen <bert@biot.com>
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <glib.h>
#include <libusb.h>
#include "libsigrok.h"
#include "libsigrok-internal.h"
/* SR_CONF_CONN takes one of these: */
#define CONN_USB_VIDPID "^([0-9a-z]{4})\\.([0-9a-z]{4})$"
#define CONN_USB_BUSADDR "^(\\d+)\\.(\\d+)$"
/* Some USBTMC-specific enums, as defined in the USBTMC standard. */
#define SUBCLASS_USBTMC 0x03
#define USBTMC_USB488 0x01
/* Message logging helpers with subsystem-specific prefix string. */
#define LOG_PREFIX "usb: "
#define sr_log(l, s, args...) sr_log(l, LOG_PREFIX s, ## args)
#define sr_spew(s, args...) sr_spew(LOG_PREFIX s, ## args)
#define sr_dbg(s, args...) sr_dbg(LOG_PREFIX s, ## args)
#define sr_info(s, args...) sr_info(LOG_PREFIX s, ## args)
#define sr_warn(s, args...) sr_warn(LOG_PREFIX s, ## args)
#define sr_err(s, args...) sr_err(LOG_PREFIX s, ## args)
/**
* Find USB devices according to a connection string.
*
* @param usb_ctx libusb context to use while scanning.
* @param conn Connection string specifying the device(s) to match. This
* can be of the form "<bus>.<address>", or "<vendorid>.<productid>".
*
* @return A GSList of struct sr_usb_dev_inst, with bus and address fields
* matching the device that matched the connection string. The GSList and
* its contents must be freed by the caller.
*/
SR_PRIV GSList *sr_usb_find(libusb_context *usb_ctx, const char *conn)
{
struct sr_usb_dev_inst *usb;
struct libusb_device **devlist;
struct libusb_device_descriptor des;
GSList *devices;
GRegex *reg;
GMatchInfo *match;
int vid, pid, bus, addr, b, a, ret, i;
char *mstr;
vid = pid = bus = addr = 0;
reg = g_regex_new(CONN_USB_VIDPID, 0, 0, NULL);
if (g_regex_match(reg, conn, 0, &match)) {
if ((mstr = g_match_info_fetch(match, 1)))
vid = strtoul(mstr, NULL, 16);
g_free(mstr);
if ((mstr = g_match_info_fetch(match, 2)))
pid = strtoul(mstr, NULL, 16);
g_free(mstr);
sr_dbg("Trying to find USB device with VID:PID = %04x:%04x.",
vid, pid);
} else {
//g_match_info_unref(match);
g_match_info_free(match);
g_regex_unref(reg);
reg = g_regex_new(CONN_USB_BUSADDR, 0, 0, NULL);
if (g_regex_match(reg, conn, 0, &match)) {
if ((mstr = g_match_info_fetch(match, 1)))
bus = strtoul(mstr, NULL, 10);
g_free(mstr);
if ((mstr = g_match_info_fetch(match, 2)))
addr = strtoul(mstr, NULL, 10);
g_free(mstr);
sr_dbg("Trying to find USB device with bus.address = "
"%d.%d.", bus, addr);
}
}
//g_match_info_unref(match);
g_match_info_free(match);
g_regex_unref(reg);
if (vid + pid + bus + addr == 0) {
sr_err("Neither VID:PID nor bus.address was specified.");
return NULL;
}
if (bus > 64) {
sr_err("Invalid bus specified: %d.", bus);
return NULL;
}
if (addr > 127) {
sr_err("Invalid address specified: %d.", addr);
return NULL;
}
/* Looks like a valid USB device specification, but is it connected? */
devices = NULL;
libusb_get_device_list(usb_ctx, &devlist);
for (i = 0; devlist[i]; i++) {
if ((ret = libusb_get_device_descriptor(devlist[i], &des))) {
sr_err("Failed to get device descriptor: %s.",
libusb_error_name(ret));
continue;
}
if (vid + pid && (des.idVendor != vid || des.idProduct != pid))
continue;
b = libusb_get_bus_number(devlist[i]);
a = libusb_get_device_address(devlist[i]);
if (bus + addr && (b != bus || a != addr))
continue;
sr_dbg("Found USB device (VID:PID = %04x:%04x, bus.address = "
"%d.%d).", des.idVendor, des.idProduct, b, a);
usb = sr_usb_dev_inst_new(libusb_get_bus_number(devlist[i]),
libusb_get_device_address(devlist[i]), NULL);
devices = g_slist_append(devices, usb);
}
libusb_free_device_list(devlist, 1);
sr_dbg("Found %d device(s).", g_slist_length(devices));
return devices;
}
/**
* Find USB devices supporting the USBTMC class
*
* @param usb_ctx libusb context to use while scanning.
*
* @return A GSList of struct sr_usb_dev_inst, with bus and address fields
* indicating devices with USBTMC support.
*/
SR_PRIV GSList *sr_usb_find_usbtmc(libusb_context *usb_ctx)
{
struct sr_usb_dev_inst *usb;
struct libusb_device **devlist;
struct libusb_device_descriptor des;
struct libusb_config_descriptor *confdes;
const struct libusb_interface_descriptor *intfdes;
GSList *devices;
int confidx, intfidx, ret, i;
devices = NULL;
libusb_get_device_list(usb_ctx, &devlist);
for (i = 0; devlist[i]; i++) {
if ((ret = libusb_get_device_descriptor(devlist[i], &des))) {
sr_err("Failed to get device descriptor: %s.",
libusb_error_name(ret));
continue;
}
for (confidx = 0; confidx < des.bNumConfigurations; confidx++) {
if (libusb_get_config_descriptor(devlist[i], confidx, &confdes) != 0) {
sr_err("Failed to get configuration descriptor.");
break;
}
for (intfidx = 0; intfidx < confdes->bNumInterfaces; intfidx++) {
intfdes = confdes->interface[intfidx].altsetting;
if (intfdes->bInterfaceClass != LIBUSB_CLASS_APPLICATION
|| intfdes->bInterfaceSubClass != SUBCLASS_USBTMC
|| intfdes->bInterfaceProtocol != USBTMC_USB488)
continue;
sr_dbg("Found USBTMC device (VID:PID = %04x:%04x, bus.address = "
"%d.%d).", des.idVendor, des.idProduct,
libusb_get_bus_number(devlist[i]),
libusb_get_device_address(devlist[i]));
usb = sr_usb_dev_inst_new(libusb_get_bus_number(devlist[i]),
libusb_get_device_address(devlist[i]), NULL);
devices = g_slist_append(devices, usb);
}
libusb_free_config_descriptor(confdes);
}
}
libusb_free_device_list(devlist, 1);
sr_dbg("Found %d device(s).", g_slist_length(devices));
return devices;
}
SR_PRIV int sr_usb_open(libusb_context *usb_ctx, struct sr_usb_dev_inst *usb)
{
struct libusb_device **devlist;
struct libusb_device_descriptor des;
int ret, r, cnt, i, a, b;
sr_dbg("Trying to open USB device %d.%d.", usb->bus, usb->address);
if ((cnt = libusb_get_device_list(usb_ctx, &devlist)) < 0) {
sr_err("Failed to retrieve device list: %s.",
libusb_error_name(cnt));
return SR_ERR;
}
ret = SR_ERR;
for (i = 0; i < cnt; i++) {
if ((r = libusb_get_device_descriptor(devlist[i], &des)) < 0) {
sr_err("Failed to get device descriptor: %s.",
libusb_error_name(r));
continue;
}
b = libusb_get_bus_number(devlist[i]);
a = libusb_get_device_address(devlist[i]);
if (b != usb->bus || a != usb->address)
continue;
if ((r = libusb_open(devlist[i], &usb->devhdl)) < 0) {
sr_err("Failed to open device: %s.",
libusb_error_name(r));
break;
}
sr_dbg("Opened USB device (VID:PID = %04x:%04x, bus.address = "
"%d.%d).", des.idVendor, des.idProduct, b, a);
ret = SR_OK;
break;
}
libusb_free_device_list(devlist, 1);
return ret;
}
/*
* This file is part of the libsigrok project.
*
* Copyright (C) 2013 Bert Vermeulen <bert@biot.com>
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <glib.h>
#include <libusb.h>
#include "libsigrok.h"
#include "libsigrok-internal.h"
/* SR_CONF_CONN takes one of these: */
#define CONN_USB_VIDPID "^([0-9a-z]{4})\\.([0-9a-z]{4})$"
#define CONN_USB_BUSADDR "^(\\d+)\\.(\\d+)$"
/* Some USBTMC-specific enums, as defined in the USBTMC standard. */
#define SUBCLASS_USBTMC 0x03
#define USBTMC_USB488 0x01
/* Message logging helpers with subsystem-specific prefix string. */
#define LOG_PREFIX "usb: "
#define sr_log(l, s, args...) sr_log(l, LOG_PREFIX s, ## args)
#define sr_spew(s, args...) sr_spew(LOG_PREFIX s, ## args)
#define sr_dbg(s, args...) sr_dbg(LOG_PREFIX s, ## args)
#define sr_info(s, args...) sr_info(LOG_PREFIX s, ## args)
#define sr_warn(s, args...) sr_warn(LOG_PREFIX s, ## args)
#define sr_err(s, args...) sr_err(LOG_PREFIX s, ## args)
/**
* Find USB devices according to a connection string.
*
* @param usb_ctx libusb context to use while scanning.
* @param conn Connection string specifying the device(s) to match. This
* can be of the form "<bus>.<address>", or "<vendorid>.<productid>".
*
* @return A GSList of struct sr_usb_dev_inst, with bus and address fields
* matching the device that matched the connection string. The GSList and
* its contents must be freed by the caller.
*/
SR_PRIV GSList *sr_usb_find(libusb_context *usb_ctx, const char *conn)
{
struct sr_usb_dev_inst *usb;
struct libusb_device **devlist;
struct libusb_device_descriptor des;
GSList *devices;
GRegex *reg;
GMatchInfo *match;
int vid, pid, bus, addr, b, a, ret, i;
char *mstr;
vid = pid = bus = addr = 0;
reg = g_regex_new(CONN_USB_VIDPID, 0, 0, NULL);
if (g_regex_match(reg, conn, 0, &match)) {
if ((mstr = g_match_info_fetch(match, 1)))
vid = strtoul(mstr, NULL, 16);
g_free(mstr);
if ((mstr = g_match_info_fetch(match, 2)))
pid = strtoul(mstr, NULL, 16);
g_free(mstr);
sr_dbg("Trying to find USB device with VID:PID = %04x:%04x.",
vid, pid);
} else {
//g_match_info_unref(match);
g_match_info_free(match);
g_regex_unref(reg);
reg = g_regex_new(CONN_USB_BUSADDR, 0, 0, NULL);
if (g_regex_match(reg, conn, 0, &match)) {
if ((mstr = g_match_info_fetch(match, 1)))
bus = strtoul(mstr, NULL, 10);
g_free(mstr);
if ((mstr = g_match_info_fetch(match, 2)))
addr = strtoul(mstr, NULL, 10);
g_free(mstr);
sr_dbg("Trying to find USB device with bus.address = "
"%d.%d.", bus, addr);
}
}
//g_match_info_unref(match);
g_match_info_free(match);
g_regex_unref(reg);
if (vid + pid + bus + addr == 0) {
sr_err("Neither VID:PID nor bus.address was specified.");
return NULL;
}
if (bus > 64) {
sr_err("Invalid bus specified: %d.", bus);
return NULL;
}
if (addr > 127) {
sr_err("Invalid address specified: %d.", addr);
return NULL;
}
/* Looks like a valid USB device specification, but is it connected? */
devices = NULL;
libusb_get_device_list(usb_ctx, &devlist);
for (i = 0; devlist[i]; i++) {
if ((ret = libusb_get_device_descriptor(devlist[i], &des))) {
sr_err("Failed to get device descriptor: %s.",
libusb_error_name(ret));
continue;
}
if (vid + pid && (des.idVendor != vid || des.idProduct != pid))
continue;
b = libusb_get_bus_number(devlist[i]);
a = libusb_get_device_address(devlist[i]);
if (bus + addr && (b != bus || a != addr))
continue;
sr_dbg("Found USB device (VID:PID = %04x:%04x, bus.address = "
"%d.%d).", des.idVendor, des.idProduct, b, a);
usb = sr_usb_dev_inst_new(libusb_get_bus_number(devlist[i]),
libusb_get_device_address(devlist[i]), NULL);
devices = g_slist_append(devices, usb);
}
libusb_free_device_list(devlist, 1);
sr_dbg("Found %d device(s).", g_slist_length(devices));
return devices;
}
/**
* Find USB devices supporting the USBTMC class
*
* @param usb_ctx libusb context to use while scanning.
*
* @return A GSList of struct sr_usb_dev_inst, with bus and address fields
* indicating devices with USBTMC support.
*/
SR_PRIV GSList *sr_usb_find_usbtmc(libusb_context *usb_ctx)
{
struct sr_usb_dev_inst *usb;
struct libusb_device **devlist;
struct libusb_device_descriptor des;
struct libusb_config_descriptor *confdes;
const struct libusb_interface_descriptor *intfdes;
GSList *devices;
int confidx, intfidx, ret, i;
devices = NULL;
libusb_get_device_list(usb_ctx, &devlist);
for (i = 0; devlist[i]; i++) {
if ((ret = libusb_get_device_descriptor(devlist[i], &des))) {
sr_err("Failed to get device descriptor: %s.",
libusb_error_name(ret));
continue;
}
for (confidx = 0; confidx < des.bNumConfigurations; confidx++) {
if (libusb_get_config_descriptor(devlist[i], confidx, &confdes) != 0) {
sr_err("Failed to get configuration descriptor.");
break;
}
for (intfidx = 0; intfidx < confdes->bNumInterfaces; intfidx++) {
intfdes = confdes->interface[intfidx].altsetting;
if (intfdes->bInterfaceClass != LIBUSB_CLASS_APPLICATION
|| intfdes->bInterfaceSubClass != SUBCLASS_USBTMC
|| intfdes->bInterfaceProtocol != USBTMC_USB488)
continue;
sr_dbg("Found USBTMC device (VID:PID = %04x:%04x, bus.address = "
"%d.%d).", des.idVendor, des.idProduct,
libusb_get_bus_number(devlist[i]),
libusb_get_device_address(devlist[i]));
usb = sr_usb_dev_inst_new(libusb_get_bus_number(devlist[i]),
libusb_get_device_address(devlist[i]), NULL);
devices = g_slist_append(devices, usb);
}
libusb_free_config_descriptor(confdes);
}
}
libusb_free_device_list(devlist, 1);
sr_dbg("Found %d device(s).", g_slist_length(devices));
return devices;
}
SR_PRIV int sr_usb_open(libusb_context *usb_ctx, struct sr_usb_dev_inst *usb)
{
struct libusb_device **devlist;
struct libusb_device_descriptor des;
int ret, r, cnt, i, a, b;
sr_dbg("Trying to open USB device %d.%d.", usb->bus, usb->address);
if ((cnt = libusb_get_device_list(usb_ctx, &devlist)) < 0) {
sr_err("Failed to retrieve device list: %s.",
libusb_error_name(cnt));
return SR_ERR;
}
ret = SR_ERR;
for (i = 0; i < cnt; i++) {
if ((r = libusb_get_device_descriptor(devlist[i], &des)) < 0) {
sr_err("Failed to get device descriptor: %s.",
libusb_error_name(r));
continue;
}
b = libusb_get_bus_number(devlist[i]);
a = libusb_get_device_address(devlist[i]);
if (b != usb->bus || a != usb->address)
continue;
if ((r = libusb_open(devlist[i], &usb->devhdl)) < 0) {
sr_err("Failed to open device: %s.",
libusb_error_name(r));
break;
}
sr_dbg("Opened USB device (VID:PID = %04x:%04x, bus.address = "
"%d.%d).", des.idVendor, des.idProduct, b, a);
ret = SR_OK;
break;
}
libusb_free_device_list(devlist, 1);
return ret;
}

View File

@ -85,6 +85,13 @@ struct dev_context {
void *cb_data;
int64_t starttime;
int stop;
gboolean en_ch0;
gboolean en_ch1;
uint64_t vdiv0;
uint64_t vdiv1;
uint64_t timebase;
gboolean coupling0;
gboolean coupling1;
int trigger_stage;
uint16_t trigger_mask;
@ -192,6 +199,11 @@ static GSList *hw_scan(GSList *options)
devc->limit_samples = 0;
devc->limit_msec = 0;
devc->sample_generator = PATTERN_SINE;
devc->vdiv0 = 1000;
devc->vdiv1 = 1000;
devc->timebase = 100;
devc->coupling0 = FALSE;
devc->coupling1 = FALSE;
sdi->priv = devc;
@ -290,6 +302,27 @@ static int config_get(int id, GVariant **data, const struct sr_dev_inst *sdi)
case SR_CONF_PATTERN_MODE:
*data = g_variant_new_string(pattern_strings[devc->sample_generator]);
break;
case SR_CONF_VDIV0:
*data = g_variant_new_uint64(devc->vdiv0);
break;
case SR_CONF_VDIV1:
*data = g_variant_new_uint64(devc->vdiv1);
break;
case SR_CONF_TIMEBASE:
*data = g_variant_new_uint64(devc->timebase);
break;
case SR_CONF_COUPLING0:
*data = g_variant_new_uint64(devc->coupling0);
break;
case SR_CONF_COUPLING1:
*data = g_variant_new_uint64(devc->coupling1);
break;
case SR_CONF_EN_CH0:
*data = g_variant_new_uint64(devc->en_ch0);
break;
case SR_CONF_EN_CH1:
*data = g_variant_new_uint64(devc->en_ch1);
break;
default:
return SR_ERR_NA;
}
@ -380,7 +413,42 @@ static int config_set(int id, GVariant *data, struct sr_dev_inst *sdi)
}
sr_dbg("%s: setting pattern to %d",
__func__, devc->sample_generator);
} else {
} else if (id == SR_CONF_EN_CH0) {
devc->en_ch0 = g_variant_get_boolean(data);
sr_dbg("%s: setting ENABLE of channel 0 to %d", __func__,
devc->en_ch0);
ret = SR_OK;
} else if (id == SR_CONF_EN_CH1) {
devc->en_ch1 = g_variant_get_boolean(data);
sr_dbg("%s: setting ENABLE of channel 1 to %d", __func__,
devc->en_ch1);
ret = SR_OK;
} else if (id == SR_CONF_VDIV0) {
devc->vdiv0 = g_variant_get_uint64(data);
sr_dbg("%s: setting VDIV of channel 0 to %" PRIu64, __func__,
devc->vdiv0);
ret = SR_OK;
} else if (id == SR_CONF_VDIV1) {
devc->vdiv1 = g_variant_get_uint64(data);
sr_dbg("%s: setting VDIV of channel 1 to %" PRIu64, __func__,
devc->vdiv1);
ret = SR_OK;
} else if (id == SR_CONF_TIMEBASE) {
devc->timebase = g_variant_get_uint64(data);
sr_dbg("%s: setting TIMEBASE to %" PRIu64, __func__,
devc->timebase);
ret = SR_OK;
} else if (id == SR_CONF_COUPLING0) {
devc->coupling0 = g_variant_get_boolean(data);
sr_dbg("%s: setting AC COUPLING of channel 0 to %d", __func__,
devc->coupling0);
ret = SR_OK;
} else if (id == SR_CONF_COUPLING1) {
devc->coupling1 = g_variant_get_boolean(data);
sr_dbg("%s: setting AC COUPLING of channel 1 to %d", __func__,
devc->coupling1);
ret = SR_OK;
} else {
ret = SR_ERR_NA;
}

View File

@ -81,10 +81,14 @@ static struct sr_config_info sr_config_info_data[] = {
"Time base", NULL},
{SR_CONF_FILTER, SR_T_CHAR, "filter",
"Filter targets", NULL},
{SR_CONF_VDIV, SR_T_RATIONAL_VOLT, "vdiv",
{SR_CONF_VDIV0, SR_T_RATIONAL_VOLT, "vdiv",
"Volts/div", NULL},
{SR_CONF_COUPLING, SR_T_CHAR, "coupling",
{SR_CONF_VDIV1, SR_T_RATIONAL_VOLT, "vdiv",
"Volts/div", NULL},
{SR_CONF_COUPLING0, SR_T_CHAR, "coupling",
"Coupling", NULL},
{SR_CONF_COUPLING1, SR_T_CHAR, "coupling",
"Coupling", NULL},
{SR_CONF_DATALOG, SR_T_BOOL, "datalog",
"Datalog", NULL},
{SR_CONF_OPERATION_MODE, SR_T_CHAR, "operation",

View File

@ -689,6 +689,9 @@ enum {
/** Trigger source. */
SR_CONF_TRIGGER_SOURCE,
/** Trigger Value. */
SR_CONF_TRIGGER_VALUE,
/** Horizontal trigger position. */
SR_CONF_HORIZ_TRIGGERPOS,
@ -701,11 +704,23 @@ enum {
/** Filter. */
SR_CONF_FILTER,
/** DSO configure sync */
SR_CONF_DSO_SYNC,
/** Zero */
SR_CONF_ZERO,
/** Volts/div. */
SR_CONF_VDIV,
SR_CONF_VDIV0,
SR_CONF_VDIV1,
/** Coupling. */
SR_CONF_COUPLING,
SR_CONF_COUPLING0,
SR_CONF_COUPLING1,
/** Channel enable*/
SR_CONF_EN_CH0,
SR_CONF_EN_CH1,
/** Trigger types. */
SR_CONF_TRIGGER_TYPE,
@ -871,7 +886,7 @@ struct sr_session {
/** List of struct datafeed_callback pointers. */
GSList *datafeed_callbacks;
GTimeVal starttime;
gboolean running;
gboolean running;
unsigned int num_sources;
@ -899,6 +914,18 @@ enum {
ADV_TRIGGER,
};
enum {
DSO_TRIGGER_AUTO = 0,
DSO_TRIGGER_CH0,
DSO_TRIGGER_CH1,
DSO_TRIGGER_CH0A1,
DSO_TRIGGER_CH0O1,
};
enum {
DSO_TRIGGER_RISING = 0,
DSO_TRIGGER_FALLING,
};
struct ds_trigger {
uint16_t trigger_en;
uint16_t trigger_mode;

View File

@ -1,15 +0,0 @@
prefix=/usr/local
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include
Name: libsigrok4DSLogic
Description: Backend library of DSLogic software based on libsigrok
URL: http://www.dreamsourcelab.com
Requires: glib-2.0
Requires.private: libzip libusb-1.0
Version: 0.2.0
Libs: -L${libdir} -lsigrok4DSLogic
Libs.private: -lm
Cflags: -I${includedir}

View File

@ -1,15 +1,15 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: libsigrok4DSLogic
Description: Backend library of DSLogic software based on libsigrok
URL: http://www.dreamsourcelab.com
Requires: glib-2.0
Requires.private: @SR_PKGLIBS@
Version: @VERSION@
Libs: -L${libdir} -lsigrok4DSLogic
Libs.private: -lm
Cflags: -I${includedir}
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: libsigrok4DSLogic
Description: Backend library of DSLogic software based on libsigrok
URL: http://www.dreamsourcelab.com
Requires: glib-2.0
Requires.private: @SR_PKGLIBS@
Version: @VERSION@
Libs: -L${libdir} -lsigrok4DSLogic
Libs.private: -lm
Cflags: -I${includedir}

View File

@ -1,392 +0,0 @@
/*
* This file is part of the DSLogic project.
*/
#include "libsigrok.h"
#include "hardware/DSLogic/dslogic.h"
#ifdef __linux__
#include <poll.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#endif/*__linux__*/
#ifdef _WIN32
#include <windows.h>
#include <initguid.h>
#include <ddk/usbiodef.h>
#include <Setupapi.h>
#include <tchar.h>
#include <conio.h>
#include <dbt.h>
#include <stdio.h>
#include <winuser.h>
#endif/*_WIN32*/
#ifdef __linux__
static void dev_list_add(struct libusbhp_t *h, const char *path,
unsigned short vid, unsigned short pid)
{
struct dev_list_t *dev =
(struct dev_list_t*)malloc(sizeof(struct dev_list_t));
dev->path = strdup(path);
dev->vid = vid;
dev->pid = pid;
dev->next = NULL;
struct dev_list_t *p = h->devlist;
if(!p) {
h->devlist = dev;
return;
}
while(p->next) {
p = p->next;
}
p->next = dev;
}
static int dev_list_remove(struct libusbhp_t *h, const char *path)
{
struct dev_list_t *p = h->devlist;
if(!p) return 1;
if(!strcmp(p->path, path)) {
h->devlist = p->next;
free(p->path);
free(p);
return 0;
}
while(p->next) {
if(!strcmp(p->next->path, path)) {
struct dev_list_t *pp = p->next;
p->next = pp->next;
free(pp->path);
free(pp->next);
free(pp);
return 0;
}
p = p->next;
}
// Not found
return 1;
}
static int dev_list_find(struct libusbhp_t *h, const char *path,
unsigned short *vid, unsigned short *pid)
{
struct dev_list_t *p = h->devlist;
while(p) {
if(!strcmp(p->path, path)) {
*vid = p->vid;
*pid = p->pid;
return 0;
}
p = p->next;
}
// Not found
return 1;
}
#endif/*__linux__*/
#ifdef _WIN32
SR_PRIV LRESULT CALLBACK WinProcCallback(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
{
struct libusbhp_t *h = (struct libusbhp_t*)GetWindowLong(hwnd, GWL_USERDATA);
switch(msg) {
case WM_DEVICECHANGE:
{
PDEV_BROADCAST_HDR phdr = (PDEV_BROADCAST_HDR)lp;
if(!phdr || phdr->dbch_devicetype != DBT_DEVTYP_DEVICEINTERFACE) break;
PDEV_BROADCAST_DEVICEINTERFACE devif =
(PDEV_BROADCAST_DEVICEINTERFACE)lp;
HDEVINFO devinfolist = SetupDiCreateDeviceInfoList(NULL, NULL);
SP_DEVICE_INTERFACE_DATA devifdata;
memset(&devifdata, 0, sizeof(devifdata));
devifdata.cbSize = sizeof(devifdata);
BOOL b = SetupDiOpenDeviceInterface(devinfolist, devif->dbcc_name, 0,
&devifdata);
DWORD required;
SP_DEVICE_INTERFACE_DETAIL_DATA devdetaildata;
memset(&devdetaildata, 0, sizeof(devdetaildata));
devdetaildata.cbSize = sizeof(devdetaildata);
SP_DEVINFO_DATA devinfodata;
memset(&devinfodata, 0, sizeof(devinfodata));
devinfodata.cbSize = sizeof(devinfodata);
b = SetupDiGetDeviceInterfaceDetail(devinfolist, &devifdata,
&devdetaildata,
sizeof(devdetaildata),
&required, &devinfodata);
TCHAR deviceidw[1024];
b = SetupDiGetDeviceInstanceIdW(devinfolist, &devinfodata, deviceidw,
sizeof(deviceidw), NULL);
char deviceid[1024];
//size_t sz;
//wcstombs_s(&sz, deviceid, deviceidw, sizeof(deviceid) - 1);
wcstombs(deviceid, deviceidw, sizeof(deviceid) - 1);
char *vid = strstr(deviceid, "VID_");
if(vid != NULL) vid += 4;
char *pid = strstr(deviceid, "PID_");
if(pid != NULL) pid += 4;
struct libusbhp_device_t *device = NULL;
if(pid || vid) {
device =
(struct libusbhp_device_t*)malloc(sizeof(struct libusbhp_device_t));
}
if(pid) {
pid[4] = '\0';
device->idProduct = (unsigned short)strtol(pid, NULL, 16);
}
if(vid) {
vid[4] = '\0';
device->idVendor = (unsigned short)strtol(vid, NULL, 16);
}
if ((device->idVendor == supported_fx2[0].vid) &&
(device->idProduct == supported_fx2[0].pid)) {
switch(wp) {
case DBT_DEVICEARRIVAL:
if(h->attach) h->attach(device, h->user_data);
break;
case DBT_DEVICEREMOVECOMPLETE:
if(h->detach) h->detach(device, h->user_data);
break;
case DBT_DEVNODES_CHANGED:
default:
break;
}
}
if(device) free(device);
}
break;
default:
break;
}
return DefWindowProc(hwnd, msg, wp, lp);
}
#endif/*OS_WINDOWS*/
SR_API int libusbhp_init(struct libusbhp_t **handle)
{
struct libusbhp_t *h = (struct libusbhp_t *)malloc(sizeof(struct libusbhp_t));
h->attach = NULL;
h->detach = NULL;
h->user_data = NULL;
#ifdef __linux__
h->devlist = NULL;
// create the udev object
h->hotplug = udev_new();
if(!h->hotplug)
{
printf("Cannot create udev object\n");
free(h);
return 1;
}
// create the udev monitor
h->hotplug_monitor = udev_monitor_new_from_netlink(h->hotplug, "udev");
// start receiving hotplug events
udev_monitor_filter_add_match_subsystem_devtype(h->hotplug_monitor,
"usb", "usb_device");
udev_monitor_enable_receiving(h->hotplug_monitor);
struct udev_enumerate *de = udev_enumerate_new (h->hotplug);
udev_enumerate_add_match_subsystem(de, "usb");
udev_enumerate_scan_devices(de);
struct udev_list_entry *lst = udev_enumerate_get_list_entry(de);
while(lst) {
struct udev_device *dev =
udev_device_new_from_syspath(h->hotplug,
udev_list_entry_get_name(lst));
if(udev_device_get_devnode(dev)) {
unsigned short idVendor =
strtol(udev_device_get_sysattr_value(dev, "idVendor"), NULL, 16);
unsigned short idProduct =
strtol(udev_device_get_sysattr_value(dev, "idProduct"), NULL, 16);
dev_list_add(h, udev_device_get_devnode(dev), idVendor, idProduct);
}
udev_device_unref(dev);
lst = udev_list_entry_get_next(lst);
}
udev_enumerate_unref(de);
#endif/*__linux__*/
#ifdef _WIN32
memset(&h->wcex, 0, sizeof(h->wcex));
h->wcex.cbSize = sizeof(WNDCLASSEX);
h->wcex.lpfnWndProc = WinProcCallback;
h->wcex.hInstance = GetModuleHandle(NULL);
h->wcex.lpszClassName = TEXT("UsbHotplugClass");
h->wcex.cbWndExtra = sizeof(struct libusbhp_t*); // Size of data.
RegisterClassEx(&h->wcex);
h->hwnd =
CreateWindowEx(0, h->wcex.lpszClassName, TEXT("UsbHotplug"), 0, 0, 0, 0,
0, 0, NULL, GetModuleHandle(NULL), NULL);
SetWindowLong(h->hwnd, GWL_USERDATA, (LONG)h);
DEV_BROADCAST_DEVICEINTERFACE *filter =
(DEV_BROADCAST_DEVICEINTERFACE*)malloc(sizeof(DEV_BROADCAST_DEVICEINTERFACE));
memset(filter, 0, sizeof(DEV_BROADCAST_DEVICEINTERFACE));
filter->dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
filter->dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
filter->dbcc_classguid = GUID_DEVINTERFACE_USB_DEVICE;
h->hDeviceNotify =
RegisterDeviceNotification(h->hwnd, filter, DEVICE_NOTIFY_WINDOW_HANDLE);
if(h->hDeviceNotify == 0) {
//printf("RegisterDeviceNotification error\n");
free(h);
return 1;
}
#endif/*_WIN32*/
*handle = h;
return 0;
}
SR_API void libusbhp_exit(struct libusbhp_t *h)
{
#ifdef __linux__
// destroy the udev monitor
udev_monitor_unref(h->hotplug_monitor);
// destroy the udev object
udev_unref(h->hotplug);
#endif/*__linux__*/
#ifdef _WIN32
UnregisterDeviceNotification(h->hDeviceNotify);
DestroyWindow(h->hwnd);
UnregisterClass(h->wcex.lpszClassName, h->wcex.hInstance);
#endif/*_WIN32*/
free(h);
}
SR_API int libusbhp_handle_events_timeout(struct libusbhp_t *h, struct timeval *tv)
{
int ms = tv->tv_sec * 1000 + tv->tv_usec / 1000;
#ifdef __linux__
// create the poll item
struct pollfd items[1];
items[0].fd = udev_monitor_get_fd(h->hotplug_monitor);
items[0].events = POLLIN;
items[0].revents = 0;
// while there are hotplug events to process
while(poll(items, 1, ms) > 0) {
// receive the relevant device
struct udev_device* dev = udev_monitor_receive_device(h->hotplug_monitor);
if(!dev) {
// error receiving device, skip it
continue;
}
if(!strcmp(udev_device_get_action(dev), "add")) {
struct libusbhp_device_t device;
device.idVendor =
strtol(udev_device_get_sysattr_value(dev, "idVendor"), NULL, 16);
device.idProduct =
strtol(udev_device_get_sysattr_value(dev, "idProduct"), NULL, 16);
dev_list_add(h, udev_device_get_devnode(dev),
device.idVendor, device.idProduct);
if(h->attach) h->attach(&device, h->user_data);
}
if(!strcmp(udev_device_get_action(dev), "remove")) {
struct libusbhp_device_t device;
int res = dev_list_find(h, udev_device_get_devnode(dev),
&device.idVendor, &device.idProduct);
if(res) {
if(h->detach) h->detach(NULL, h->user_data);
} else {
dev_list_remove(h, udev_device_get_devnode(dev));
if(h->detach) h->detach(&device, h->user_data);
}
}
// destroy the relevant device
udev_device_unref(dev);
// clear the revents
items[0].revents = 0;
}
#endif/*__linux__*/
#ifdef _WIN32
UINT_PTR timer = SetTimer(h->hwnd, 0, ms, NULL);
MSG msg;
int ret = GetMessage(&msg, NULL, 0, 0);
if(ret <= 0) return 0;
TranslateMessage(&msg);
DispatchMessage(&msg);
KillTimer(h->hwnd, timer);
#endif/*_WIN32*/
return 0;
}
SR_API void libusbhp_register_hotplug_listeners(struct libusbhp_t *handle,
libusbhp_hotplug_cb_fn connected_cb,
libusbhp_hotplug_cb_fn disconnected_cb,
void *user_data)
{
handle->attach = connected_cb;
handle->detach = disconnected_cb;
handle->user_data = user_data;
}

View File

@ -1,69 +0,0 @@
/*
* This file is part of the libsigrok project.
*
* Copyright (C) 2010-2012 Bert Vermeulen <bert@biot.com>
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef LIBSIGROK_VERSION_H
#define LIBSIGROK_VERSION_H
/**
* @file
*
* Version number definitions and macros.
*/
/**
* @ingroup grp_versions
*
* @{
*/
/*
* Package version macros (can be used for conditional compilation).
*/
/** The libsigrok package 'major' version number. */
#define SR_PACKAGE_VERSION_MAJOR 0
/** The libsigrok package 'minor' version number. */
#define SR_PACKAGE_VERSION_MINOR 2
/** The libsigrok package 'micro' version number. */
#define SR_PACKAGE_VERSION_MICRO 0
/** The libsigrok package version ("major.minor.micro") as string. */
#define SR_PACKAGE_VERSION_STRING "0.2.0"
/*
* Library/libtool version macros (can be used for conditional compilation).
*/
/** The libsigrok libtool 'current' version number. */
#define SR_LIB_VERSION_CURRENT 1
/** The libsigrok libtool 'revision' version number. */
#define SR_LIB_VERSION_REVISION 2
/** The libsigrok libtool 'age' version number. */
#define SR_LIB_VERSION_AGE 0
/** The libsigrok libtool version ("current:revision:age") as string. */
#define SR_LIB_VERSION_STRING "1:2:0"
/** @} */
#endif