Improve usb transfer and othre minor issues

This commit is contained in:
DreamSourceLab 2016-07-20 08:59:39 +08:00
parent 4cc02c8d78
commit f15aa50d32
264 changed files with 36467 additions and 2074 deletions

View File

@ -93,6 +93,7 @@ find_package(Threads)
find_package(Boost 1.42 COMPONENTS filesystem system thread REQUIRED)
find_package(libusb-1.0 REQUIRED)
find_package(FFTW REQUIRED)
#===============================================================================
#= Config Header
@ -118,107 +119,147 @@ configure_file (
#-------------------------------------------------------------------------------
set(DSView_SOURCES
main.cpp
pv/devicemanager.cpp
pv/mainwindow.cpp
pv/sigsession.cpp
pv/storesession.cpp
pv/data/analog.cpp
pv/data/analogsnapshot.cpp
pv/data/dso.cpp
pv/data/dsosnapshot.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/device/devinst.cpp
pv/device/device.cpp
pv/device/file.cpp
pv/device/inputfile.cpp
pv/device/sessionfile.cpp
pv/dialogs/about.cpp
pv/dialogs/deviceoptions.cpp
pv/dialogs/search.cpp
pv/dialogs/storeprogress.cpp
pv/dialogs/streamoptions.cpp
pv/dialogs/waitingdialog.cpp
pv/dialogs/dsomeasure.cpp
pv/dock/dsotriggerdock.cpp
pv/dock/measuredock.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/string.cpp
pv/prop/binding/binding.cpp
pv/prop/binding/binding_deviceoptions.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/devmode.cpp
pv/view/dsldial.cpp
pv/view/dsosignal.cpp
pv/view/groupsignal.cpp
pv/view/header.cpp
pv/view/logicsignal.cpp
pv/view/ruler.cpp
pv/view/selectableitem.cpp
pv/view/signal.cpp
pv/view/timemarker.cpp
pv/view/trace.cpp
pv/view/view.cpp
pv/view/viewport.cpp
pv/widgets/fakelineedit.cpp
main.cpp
pv/sigsession.cpp
pv/mainwindow.cpp
pv/devicemanager.cpp
pv/data/snapshot.cpp
pv/data/signaldata.cpp
pv/data/logicsnapshot.cpp
pv/data/logic.cpp
pv/data/analogsnapshot.cpp
pv/data/analog.cpp
pv/dialogs/deviceoptions.cpp
pv/prop/property.cpp
pv/prop/int.cpp
pv/prop/enum.cpp
pv/prop/double.cpp
pv/prop/bool.cpp
pv/prop/binding/binding.cpp
pv/toolbars/samplingbar.cpp
pv/view/viewport.cpp
pv/view/view.cpp
pv/view/timemarker.cpp
pv/view/signal.cpp
pv/view/ruler.cpp
pv/view/logicsignal.cpp
pv/view/header.cpp
pv/view/cursor.cpp
pv/view/analogsignal.cpp
pv/prop/binding/binding_deviceoptions.cpp
pv/toolbars/trigbar.cpp
pv/toolbars/filebar.cpp
pv/dock/protocoldock.cpp
pv/dock/triggerdock.cpp
pv/dock/measuredock.cpp
pv/dock/searchdock.cpp
pv/toolbars/logobar.cpp
pv/data/groupsnapshot.cpp
pv/view/groupsignal.cpp
pv/data/group.cpp
pv/dialogs/about.cpp
pv/dialogs/search.cpp
pv/data/dsosnapshot.cpp
pv/data/dso.cpp
pv/view/dsosignal.cpp
pv/view/dsldial.cpp
pv/dock/dsotriggerdock.cpp
pv/view/trace.cpp
pv/view/selectableitem.cpp
pv/data/decoderstack.cpp
pv/data/decode/rowdata.cpp
pv/data/decode/row.cpp
pv/data/decode/decoder.cpp
pv/data/decode/annotation.cpp
pv/view/decodetrace.cpp
pv/prop/binding/decoderoptions.cpp
pv/widgets/fakelineedit.cpp
pv/widgets/decodermenu.cpp
pv/widgets/decodergroupbox.cpp
pv/prop/string.cpp
pv/device/sessionfile.cpp
pv/device/inputfile.cpp
pv/device/file.cpp
pv/device/devinst.cpp
pv/dialogs/storeprogress.cpp
pv/storesession.cpp
pv/view/devmode.cpp
pv/device/device.cpp
pv/dialogs/waitingdialog.cpp
pv/dialogs/dsomeasure.cpp
pv/dialogs/calibration.cpp
pv/data/decodermodel.cpp
pv/dialogs/protocollist.cpp
pv/dialogs/protocolexp.cpp
pv/dialogs/fftoptions.cpp
pv/data/mathstack.cpp
pv/view/mathtrace.cpp
dsapplication.cpp
pv/widgets/viewstatus.cpp
pv/toolbars/titlebar.cpp
pv/mainframe.cpp
pv/widgets/border.cpp
pv/dialogs/dsmessagebox.cpp
pv/dialogs/shadow.cpp
pv/dialogs/dsdialog.cpp
)
set(DSView_HEADERS
pv/mainwindow.h
pv/sigsession.h
pv/storesession.h
pv/device/devinst.h
pv/dialogs/about.h
pv/dialogs/deviceoptions.h
pv/dialogs/search.h
pv/dialogs/storeprogress.h
pv/dialogs/streamoptions.h
pv/dialogs/waitingdialog.h
pv/dialogs/dsomeasure.h
pv/dock/dsotriggerdock.h
pv/dock/measuredock.h
pv/dock/searchdock.h
pv/dock/triggerdock.h
pv/prop/bool.h
pv/prop/double.h
pv/prop/enum.h
pv/prop/int.h
pv/prop/property.h
pv/prop/string.h
pv/toolbars/filebar.h
pv/toolbars/logobar.h
pv/toolbars/samplingbar.h
pv/toolbars/trigbar.h
pv/view/cursor.h
pv/view/devmode.h
pv/view/header.h
pv/view/ruler.h
pv/view/selectableitem.h
pv/view/timemarker.h
pv/view/trace.h
pv/view/view.h
pv/view/viewport.h
pv/widgets/fakelineedit.h
pv/sigsession.h
pv/mainwindow.h
pv/dialogs/deviceoptions.h
pv/prop/property.h
pv/prop/int.h
pv/prop/enum.h
pv/prop/double.h
pv/prop/bool.h
pv/toolbars/samplingbar.h
pv/view/viewport.h
pv/view/view.h
pv/view/timemarker.h
pv/view/ruler.h
pv/view/header.h
pv/view/cursor.h
pv/toolbars/trigbar.h
pv/toolbars/filebar.h
pv/dock/protocoldock.h
pv/dock/triggerdock.h
pv/dock/measuredock.h
pv/dock/searchdock.h
pv/toolbars/logobar.h
pv/dialogs/about.h
pv/dialogs/search.h
pv/dock/dsotriggerdock.h
pv/view/trace.h
pv/view/selectableitem.h
pv/data/decoderstack.h
pv/view/decodetrace.h
pv/widgets/fakelineedit.h
pv/widgets/decodermenu.h
pv/widgets/decodergroupbox.h
pv/prop/string.h
pv/device/devinst.h
pv/dialogs/storeprogress.h
pv/storesession.h
pv/view/devmode.h
pv/dialogs/waitingdialog.h
pv/dialogs/dsomeasure.h
pv/dialogs/calibration.h
pv/dialogs/protocollist.h
pv/dialogs/protocolexp.h
pv/dialogs/fftoptions.h
pv/data/mathstack.h
pv/view/mathtrace.h
pv/widgets/viewstatus.h
pv/toolbars/titlebar.h
pv/mainframe.h
pv/widgets/border.h
pv/dialogs/dsmessagebox.h
pv/dialogs/shadow.h
pv/dialogs/dsdialog.h
)
set(DSView_FORMS
pv/dialogs/about.ui
)
set(DSView_RESOURCES
@ -310,6 +351,7 @@ set(DSVIEW_LINK_LIBS
${CMAKE_THREAD_LIBS_INIT}
${QT_LIBRARIES}
${LIBUSB_1_LIBRARIES}
${FFTW_LIBRARIES}
)
if(STATIC_PKGDEPS_LIBS)

View File

@ -662,7 +662,7 @@ QAbstractSpinBox {
background-color: #201F1F;
color: silver;
border-radius: 2px;
min-width: 50px;
min-width: 60px;
}
QAbstractSpinBox:up-button

View File

@ -137,7 +137,7 @@ int main(int argc, char *argv[])
// Initialise the main frame
pv::MainFrame w(device_manager, open_file);
//QFile qss(":/stylesheet.qss");
QFile qss(":qdarkstyle/style.qss");
QFile qss(":darkstyle/style.qss");
qss.open(QFile::ReadOnly);
a.setStyleSheet(qss.readAll());
qss.close();

View File

@ -117,7 +117,7 @@ void DecoderStack::remove(boost::shared_ptr<Decoder> &decoder)
{
// Find the decoder in the stack
list< shared_ptr<Decoder> >::iterator iter = _stack.begin();
for(int i = 0; i < _stack.size(); i++, iter++)
for(unsigned int i = 0; i < _stack.size(); i++, iter++)
if ((*iter) == decoder)
break;
@ -285,7 +285,6 @@ uint64_t DecoderStack::list_annotation_size() const
{
lock_guard<boost::recursive_mutex> lock(_output_mutex);
uint64_t max_annotation_size = 0;
int row = 0;
for (map<const Row, RowData>::const_iterator i = _rows.begin();
i != _rows.end(); i++) {
map<const Row, bool>::const_iterator iter = _rows_lshow.find((*i).first);
@ -316,7 +315,6 @@ bool DecoderStack::list_annotation(pv::data::decode::Annotation &ann,
uint16_t row_index, uint64_t col_index) const
{
//lock_guard<mutex> lock(_output_mutex);
int row = 0;
for (map<const Row, RowData>::const_iterator i = _rows.begin();
i != _rows.end(); i++) {
map<const Row, bool>::const_iterator iter = _rows_lshow.find((*i).first);
@ -334,7 +332,6 @@ bool DecoderStack::list_annotation(pv::data::decode::Annotation &ann,
bool DecoderStack::list_row_title(int row, QString &title) const
{
//lock_guard<mutex> lock(_output_mutex);
int index = 0;
for (map<const Row, RowData>::const_iterator i = _rows.begin();
i != _rows.end(); i++) {
map<const Row, bool>::const_iterator iter = _rows_lshow.find((*i).first);
@ -574,8 +571,8 @@ void DecoderStack::decode_proc()
optional<uint64_t> sample_count;
srd_session *session;
srd_decoder_inst *prev_di = NULL;
uint64_t decode_start;
uint64_t decode_end;
uint64_t decode_start = 0;
uint64_t decode_end = 0;
assert(_snapshot);
@ -726,7 +723,6 @@ int DecoderStack::list_rows_size()
{
//lock_guard<mutex> lock(_output_mutex);
int rows_size = 0;
int row = 0;
for (map<const Row, RowData>::const_iterator i = _rows.begin();
i != _rows.end(); i++) {
map<const Row, bool>::const_iterator iter = _rows_lshow.find((*i).first);

View File

@ -32,9 +32,9 @@
#include <QObject>
#include <QString>
#include <../data/decode/row.h>
#include <../data/decode/rowdata.h>
#include <../data/signaldata.h>
#include "../data/decode/row.h"
#include "../data/decode/rowdata.h"
#include "../data/signaldata.h"
namespace DecoderStackTest {
class TwoDecoderStack;

View File

@ -166,7 +166,7 @@ void DsoSnapshot::enable_envelope(bool enable)
const uint8_t *DsoSnapshot::get_samples(
int64_t start_sample, int64_t end_sample, uint16_t index) const
{
(void)end_sample;
(void)end_sample;
assert(start_sample >= 0);
assert(start_sample < (int64_t)get_sample_count());
@ -202,9 +202,9 @@ void DsoSnapshot::get_envelope_section(EnvelopeSection &s,
s.start = start << scale_power;
s.scale = 1 << scale_power;
//if (_envelope_levels[probe_index][min_level].length < get_sample_count() / EnvelopeScaleFactor)
// s.length = 0;
//else
if (_envelope_levels[probe_index][min_level].length == 0)
s.length = 0;
else
s.length = end - start;
// s.samples = new EnvelopeSample[s.length];
// memcpy(s.samples, _envelope_levels[min_level].samples + start,

View File

@ -205,7 +205,7 @@ void MathStack::calc_fft()
const uint16_t step = _snapshot->get_channel_num() * _sample_interval;
const uint8_t *const samples = _snapshot->get_samples(0, _sample_num*_sample_interval-1, _index);
double wsum = 0;
for (int i = 0; i < _sample_num; i++) {
for (unsigned int i = 0; i < _sample_num; i++) {
double w = window(i, _windows_index);
_xn[i] = ((double)samples[i*step] - offset) * vscale * w;
wsum += w;
@ -216,7 +216,7 @@ void MathStack::calc_fft()
// calculate power spectrum
_power_spectrum[0] = abs(_xk[0])/wsum; /* DC component */
for (int k = 1; k < (_sample_num + 1) / 2; ++k) /* (k < N/2 rounded up) */
for (unsigned int k = 1; k < (_sample_num + 1) / 2; ++k) /* (k < N/2 rounded up) */
_power_spectrum[k] = sqrt((_xk[k]*_xk[k] + _xk[_sample_num-k]*_xk[_sample_num-k]) * 2) / wsum;
if (_sample_num % 2 == 0) /* N is even */
_power_spectrum[_sample_num/2] = abs(_xk[_sample_num/2])/wsum; /* Nyquist freq. */

View File

@ -44,14 +44,14 @@ sr_dev_inst* Device::dev_inst() const
void Device::use(SigSession *owner) throw(QString)
{
DevInst::use(owner);
DevInst::use(owner);
sr_session_new();
sr_session_new();
assert(_sdi);
sr_dev_open(_sdi);
if (sr_session_dev_add(_sdi) != SR_OK)
throw QString(tr("Failed to use device."));
assert(_sdi);
sr_dev_open(_sdi);
if (sr_session_dev_add(_sdi) != SR_OK)
throw QString(tr("Failed to use device."));
}
void Device::release()

View File

@ -1,69 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>About</class>
<widget class="QDialog" name="About">
<property name="windowModality">
<enum>Qt::WindowModal</enum>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>600</width>
<height>320</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>600</width>
<height>320</height>
</size>
</property>
<property name="windowTitle">
<string>About</string>
</property>
<property name="whatsThis">
<string/>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="icon">
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="../../DSView.qrc">:/icons/dsl_logo.png</pixmap>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="versionInfo">
<property name="text">
<string/>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources>
<include location="../../DSView.qrc"/>
</resources>
<connections/>
</ui>

View File

@ -98,8 +98,8 @@ void Calibration::set_device(boost::shared_ptr<device::DevInst> dev_inst)
sr_channel *const probe = (sr_channel*)l->data;
assert(probe);
uint64_t vgain, vgain_default;
uint16_t vgain_range;
uint64_t vgain = 0, vgain_default = 0;
uint16_t vgain_range = 0;
GVariant* gvar = _dev_inst->get_config(probe, NULL, SR_CONF_VGAIN);
if (gvar != NULL) {
vgain = g_variant_get_uint64(gvar);
@ -126,18 +126,13 @@ void Calibration::set_device(boost::shared_ptr<device::DevInst> dev_inst)
_slider_list.push_back(gain_slider);
_label_list.push_back(gain_label);
uint64_t voff, voff_default;
uint16_t voff_range;
uint64_t voff = 0;
uint16_t voff_range = 0;
gvar = _dev_inst->get_config(probe, NULL, SR_CONF_VOFF);
if (gvar != NULL) {
voff = g_variant_get_uint16(gvar);
g_variant_unref(gvar);
}
gvar = _dev_inst->get_config(probe, NULL, SR_CONF_VOFF_DEFAULT);
if (gvar != NULL) {
voff_default = g_variant_get_uint16(gvar);
g_variant_unref(gvar);
}
gvar = _dev_inst->get_config(probe, NULL, SR_CONF_VOFF_RANGE);
if (gvar != NULL) {
voff_range = g_variant_get_uint16(gvar);
@ -204,10 +199,10 @@ void Calibration::on_save()
this->hide();
QFuture<void> future;
future = QtConcurrent::run([&]{
QTime dieTime = QTime::currentTime().addSecs(1);
//QTime dieTime = QTime::currentTime().addSecs(1);
_dev_inst->set_config(NULL, NULL, SR_CONF_ZERO_SET,
g_variant_new_boolean(true));
while( QTime::currentTime() < dieTime );
//while( QTime::currentTime() < dieTime );
});
Qt::WindowFlags flags = Qt::CustomizeWindowHint;
QProgressDialog dlg(tr("Save Calibration Result... It can take a while."),
@ -229,11 +224,11 @@ void Calibration::on_reset()
this->hide();
QFuture<void> future;
future = QtConcurrent::run([&]{
QTime dieTime = QTime::currentTime().addSecs(1);
//QTime dieTime = QTime::currentTime().addSecs(1);
_dev_inst->set_config(NULL, NULL, SR_CONF_ZERO_LOAD,
g_variant_new_boolean(true));
reload_value();
while( QTime::currentTime() < dieTime );
//while( QTime::currentTime() < dieTime );
});
Qt::WindowFlags flags = Qt::CustomizeWindowHint;
QProgressDialog dlg(tr("Reset Calibration Result... It can take a while."),
@ -256,8 +251,8 @@ void Calibration::reload_value()
sr_channel *const probe = (sr_channel*)l->data;
assert(probe);
uint64_t vgain, vgain_default;
uint16_t vgain_range;
uint64_t vgain = 0, vgain_default = 0;
uint16_t vgain_range = 0;
GVariant* gvar = _dev_inst->get_config(probe, NULL, SR_CONF_VGAIN);
if (gvar != NULL) {
vgain = g_variant_get_uint64(gvar);
@ -274,8 +269,8 @@ void Calibration::reload_value()
g_variant_unref(gvar);
}
uint64_t voff;
uint16_t voff_range;
uint64_t voff = 0;
uint16_t voff_range = 0;
gvar = _dev_inst->get_config(probe, NULL, SR_CONF_VOFF);
if (gvar != NULL) {
voff = g_variant_get_uint16(gvar);

View File

@ -62,6 +62,7 @@ void DSDialog::reject()
bool DSDialog::eventFilter(QObject *object, QEvent *event)
{
(void)object;
const QEvent::Type type = event->type();
const QMouseEvent *const mouse_event = (QMouseEvent*)event;
if (type == QEvent::MouseMove) {

View File

@ -83,6 +83,7 @@ void DSMessageBox::reject()
bool DSMessageBox::eventFilter(QObject *object, QEvent *event)
{
(void)object;
const QEvent::Type type = event->type();
const QMouseEvent *const mouse_event = (QMouseEvent*)event;
if (type == QEvent::MouseMove) {

View File

@ -43,7 +43,7 @@ DsoMeasure::DsoMeasure(QWidget *parent, boost::shared_ptr<DsoSignal> dsoSig) :
{
setMinimumWidth(300);
for (int i=DsoSignal::DSO_MS_BEGIN+1; i<DsoSignal::DSO_MS_END; i++) {
for (int i=DSO_MS_BEGIN+1; i<DSO_MS_END; i++) {
QCheckBox *checkBox = new QCheckBox(_dsoSig->get_ms_string(i), this);
checkBox->setProperty("id", QVariant(i));
checkBox->setChecked(dsoSig->get_ms_en(i));

View File

@ -90,12 +90,12 @@ FftOptions::FftOptions(QWidget *parent, SigSession &session) :
assert(length.size() > 0);
assert(view_modes.size() > 0);
assert(dbv_ranges.size() > 0);
for (int i = 0; i < windows.size(); i++)
for (unsigned int i = 0; i < windows.size(); i++)
{
_window_combobox->addItem(windows[i],
qVariantFromValue(i));
}
for (int i = 0; i < length.size(); i++)
for (unsigned int i = 0; i < length.size(); i++)
{
if (length[i] < _sample_limit)
_len_combobox->addItem(QString::number(length[i]),
@ -112,14 +112,14 @@ FftOptions::FftOptions(QWidget *parent, SigSession &session) :
_interval_combobox->addItem(QString::number(i),
qVariantFromValue(i));
}
for (int i = 0; i < view_modes.size(); i++)
for (unsigned int i = 0; i < view_modes.size(); i++)
{
_view_combobox->addItem(view_modes[i],
qVariantFromValue(i));
}
assert(_view_combobox->count() > 0);
_view_combobox->setCurrentIndex(_view_combobox->count()-1);
for (int i = 0; i < dbv_ranges.size(); i++)
for (unsigned int i = 0; i < dbv_ranges.size(); i++)
{
_dbv_combobox->addItem(QString::number(dbv_ranges[i]),
qVariantFromValue(dbv_ranges[i]));
@ -138,7 +138,7 @@ FftOptions::FftOptions(QWidget *parent, SigSession &session) :
}
}
for (int i = 0; i < _len_combobox->count(); i++) {
if (mathTrace->get_math_stack()->get_sample_num() == _len_combobox->itemData(i).toLongLong()) {
if (mathTrace->get_math_stack()->get_sample_num() == _len_combobox->itemData(i).toULongLong()) {
_len_combobox->setCurrentIndex(i);
break;
}

View File

@ -1,86 +0,0 @@
/*
* This file is part of the DSView project.
* DSView is based on PulseView.
*
* Copyright (C) 2016 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
* 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 "messagebox.h"
#include <QVBoxLayout>
#include <QAbstractButton>
namespace pv {
namespace dialogs {
MessageBox::MessageBox(QWidget *parent) :
QDialog(parent)
{
setWindowFlags(Qt::FramelessWindowHint | Qt::Dialog);
_msg = new QMessageBox(this);
_msg->setWindowFlags(Qt::FramelessWindowHint | Qt::Widget);
_titlebar = new toolbars::TitleBar(false, parent);
_titlebar->setTitle(tr("Message"));
QVBoxLayout *layout = new QVBoxLayout(this);
layout->addWidget(_titlebar);
layout->addWidget(_msg);
setLayout(layout);
//connect(_msg, SIGNAL(finished(int)), this, SLOT(accept()));
connect(_msg, SIGNAL(buttonClicked(QAbstractButton*)), this, SLOT(on_button(QAbstractButton*)));
}
void MessageBox::accept()
{
using namespace Qt;
QDialog::accept();
}
void MessageBox::reject()
{
using namespace Qt;
QDialog::reject();
}
QMessageBox* MessageBox::mBox()
{
return _msg;
}
int MessageBox::exec()
{
//_msg->show();
return QDialog::exec();
}
void MessageBox::on_button(QAbstractButton *btn)
{
QMessageBox::ButtonRole role = _msg->buttonRole(btn);
if (role == QMessageBox::AcceptRole)
accept();
else
reject();
}
} // namespace dialogs
} // namespace pv

View File

@ -139,7 +139,7 @@ void ProtocolExp::accept()
future = QtConcurrent::run([&]{
_export_cancel = false;
QString title;
int index;
int index = 0;
for (std::list<QRadioButton *>::const_iterator i = _row_sel_list.begin();
i != _row_sel_list.end(); i++) {
if ((*i)->isChecked()) {

View File

@ -91,10 +91,10 @@ void WaitingDialog::accept()
QFuture<void> future;
future = QtConcurrent::run([&]{
QTime dieTime = QTime::currentTime().addSecs(1);
//QTime dieTime = QTime::currentTime().addSecs(1);
_dev_inst->set_config(NULL, NULL, SR_CONF_ZERO_SET,
g_variant_new_boolean(true));
while( QTime::currentTime() < dieTime );
//while( QTime::currentTime() < dieTime );
});
Qt::WindowFlags flags = Qt::CustomizeWindowHint;
QProgressDialog dlg(tr("Save Auto Zero Result... It can take a while."),
@ -120,11 +120,11 @@ void WaitingDialog::reject()
QFuture<void> future;
future = QtConcurrent::run([&]{
QTime dieTime = QTime::currentTime().addSecs(1);
//QTime dieTime = QTime::currentTime().addSecs(1);
_dev_inst->set_config(NULL, NULL, SR_CONF_ZERO, g_variant_new_boolean(false));
_dev_inst->set_config(NULL, NULL, SR_CONF_ZERO_LOAD,
g_variant_new_boolean(true));
while( QTime::currentTime() < dieTime );
//while( QTime::currentTime() < dieTime );
});
Qt::WindowFlags flags = Qt::CustomizeWindowHint;
QProgressDialog dlg(tr("Load Current Setting... It can take a while."),
@ -149,11 +149,11 @@ void WaitingDialog::stop()
QDialog::reject();
}
void WaitingDialog::start()
int WaitingDialog::start()
{
movie->start();
timer->start(300);
this->exec();
return this->exec();
}
void WaitingDialog::changeText()

View File

@ -53,7 +53,7 @@ private:
public:
WaitingDialog(QWidget *parent, boost::shared_ptr<pv::device::DevInst> dev_inst);
void start();
int start();
protected:
void accept();

View File

@ -24,6 +24,10 @@
#include "../sigsession.h"
#include "../device/devinst.h"
#include "../dialogs/dsmessagebox.h"
#include "../view/dsosignal.h"
#include <boost/shared_ptr.hpp>
#include <boost/foreach.hpp>
#include <QObject>
#include <QLabel>
@ -37,6 +41,9 @@
#include "libsigrok4DSL/libsigrok.h"
using namespace boost;
using namespace std;
namespace pv {
namespace dock {
@ -61,6 +68,7 @@ DsoTriggerDock::DsoTriggerDock(QWidget *parent, SigSession &session) :
holdoff_comboBox->addItem(tr("uS"), qVariantFromValue(1000));
holdoff_comboBox->addItem(tr("mS"), qVariantFromValue(1000000));
holdoff_comboBox->addItem(tr("S"), qVariantFromValue(1000000000));
holdoff_comboBox->setCurrentIndex(0);
holdoff_spinBox = new QSpinBox(_widget);
holdoff_spinBox->setRange(0, 999);
holdoff_spinBox->setButtonSymbols(QAbstractSpinBox::NoButtons);
@ -98,6 +106,7 @@ DsoTriggerDock::DsoTriggerDock(QWidget *parent, SigSession &session) :
connect(falling_radioButton, SIGNAL(clicked()), this, SLOT(type_changed()));
source_group=new QButtonGroup(_widget);
channel_comboBox = new QComboBox(_widget);
type_group=new QButtonGroup(_widget);
source_group->addButton(auto_radioButton);
@ -126,6 +135,7 @@ DsoTriggerDock::DsoTriggerDock(QWidget *parent, SigSession &session) :
gLayout->addWidget(new QLabel(_widget), 2, 0);
gLayout->addWidget(tSource_labe, 3, 0);
gLayout->addWidget(auto_radioButton, 4, 0);
gLayout->addWidget(channel_comboBox, 4, 1, 1, 3);
gLayout->addWidget(ch0_radioButton, 5, 0);
gLayout->addWidget(ch1_radioButton, 5, 1, 1, 3);
gLayout->addWidget(ch0a1_radioButton, 6, 0);
@ -245,6 +255,24 @@ void DsoTriggerDock::source_changed()
}
}
void DsoTriggerDock::channel_changed(int ch)
{
(void)ch;
int ret;
ret = _session.get_device()->set_config(NULL, NULL,
SR_CONF_TRIGGER_CHANNEL,
g_variant_new_byte(channel_comboBox->currentData().toInt()));
if (!ret) {
dialogs::DSMessageBox msg(this);
msg.mBox()->setText(tr("Trigger Setting Issue"));
msg.mBox()->setInformativeText(tr("Change trigger channel failed!"));
msg.mBox()->setStandardButtons(QMessageBox::Ok);
msg.mBox()->setIcon(QMessageBox::Warning);
msg.exec();
}
}
void DsoTriggerDock::type_changed()
{
int id = type_group->checkedId();
@ -285,6 +313,7 @@ void DsoTriggerDock::init()
holdoff_spinBox->setDisabled(true);
holdoff_comboBox->setDisabled(true);
margin_slider->setDisabled(true);
channel_comboBox->setDisabled(true);
return;
} else {
foreach(QAbstractButton * btn, source_group->buttons())
@ -295,6 +324,7 @@ void DsoTriggerDock::init()
holdoff_spinBox->setDisabled(false);
holdoff_comboBox->setDisabled(false);
margin_slider->setDisabled(false);
channel_comboBox->setDisabled(false);
}
// TRIGGERPOS
@ -314,6 +344,29 @@ void DsoTriggerDock::init()
source_group->button(src)->setChecked(true);
}
// setup channel_comboBox
disconnect(channel_comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(channel_changed(int)));
channel_comboBox->clear();
BOOST_FOREACH(const boost::shared_ptr<view::Signal> s, _session.get_signals()) {
boost::shared_ptr<view::DsoSignal> dsoSig;
if (dsoSig = dynamic_pointer_cast<view::DsoSignal>(s)) {
channel_comboBox->addItem(dsoSig->get_name(), qVariantFromValue(dsoSig->get_index()));
}
}
gvar = _session.get_device()->get_config(NULL, NULL,
SR_CONF_TRIGGER_CHANNEL);
if (gvar != NULL) {
uint8_t src = g_variant_get_byte(gvar);
g_variant_unref(gvar);
for (int i = 0; i < channel_comboBox->count(); i++) {
if (src == channel_comboBox->itemData(i).toInt()) {
channel_comboBox->setCurrentIndex(i);
break;
}
}
}
connect(channel_comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(channel_changed(int)));
gvar = _session.get_device()->get_config(NULL, NULL,
SR_CONF_TRIGGER_SLOPE);
if (gvar != NULL) {
@ -321,6 +374,39 @@ void DsoTriggerDock::init()
g_variant_unref(gvar);
type_group->button(slope)->setChecked(true);
}
disconnect(holdoff_slider, SIGNAL(valueChanged(int)), this, SLOT(hold_changed(int)));
disconnect(holdoff_comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(hold_changed(int)));
gvar = _session.get_device()->get_config(NULL, NULL,
SR_CONF_TRIGGER_HOLDOFF);
if (gvar != NULL) {
uint64_t holdoff = g_variant_get_uint64(gvar);
g_variant_unref(gvar);
for (int i = holdoff_comboBox->count()-1; i >= 0; i--) {
if (holdoff >= holdoff_comboBox->itemData(i).toDouble()) {
holdoff_comboBox->setCurrentIndex(i);
break;
}
}
if (holdoff_comboBox->currentData().toDouble() == 1000000000) {
holdoff_slider->setRange(0, 10);
} else {
holdoff_slider->setRange(0, 999);
}
holdoff_spinBox->setValue(holdoff * 10.0/holdoff_comboBox->currentData().toDouble());
}
connect(holdoff_slider, SIGNAL(valueChanged(int)), this, SLOT(hold_changed(int)));
connect(holdoff_comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(hold_changed(int)));
disconnect(margin_slider, SIGNAL(valueChanged(int)), this, SLOT(margin_changed(int)));
gvar = _session.get_device()->get_config(NULL, NULL,
SR_CONF_TRIGGER_MARGIN);
if (gvar != NULL) {
uint8_t margin = g_variant_get_byte(gvar);
g_variant_unref(gvar);
margin_slider->setValue(margin);
}
connect(margin_slider, SIGNAL(valueChanged(int)), this, SLOT(margin_changed(int)));
}
} // namespace dock

View File

@ -63,6 +63,7 @@ private slots:
void margin_changed(int margin);
void source_changed();
void type_changed();
void channel_changed(int ch);
private:
@ -81,6 +82,7 @@ private:
QSlider *position_slider;
QButtonGroup *source_group;
QComboBox *channel_comboBox;
QButtonGroup *type_group;
};

View File

@ -206,9 +206,9 @@ void MeasureDock::cursor_update()
index++;
}
_t1_comboBox->setMinimumWidth(_t1_comboBox->sizeHint().width()+15);
_t2_comboBox->setMinimumWidth(_t2_comboBox->sizeHint().width()+15);
_t3_comboBox->setMinimumWidth(_t3_comboBox->sizeHint().width()+15);
_t1_comboBox->setMinimumWidth(_t1_comboBox->sizeHint().width()+30);
_t2_comboBox->setMinimumWidth(_t2_comboBox->sizeHint().width()+30);
_t3_comboBox->setMinimumWidth(_t3_comboBox->sizeHint().width()+30);
if (_t1_last_index < _t1_comboBox->count())
_t1_comboBox->setCurrentIndex(_t1_last_index);

View File

@ -414,7 +414,7 @@ void ProtocolDock::decoded_progress(int progress)
{
(void) progress;
int pg;
int pg = 0;
QString err="";
const std::vector< boost::shared_ptr<pv::view::DecodeTrace> > decode_sigs(
_session.get_decode_signals());
@ -454,7 +454,7 @@ void ProtocolDock::update_model()
else if (!decoder_model->getDecoderStack())
decoder_model->setDecoderStack(decode_sigs.at(0)->decoder());
else {
int index = 0;
unsigned int index = 0;
BOOST_FOREACH(const boost::shared_ptr<pv::view::DecodeTrace> d, decode_sigs) {
if (d->decoder() == decoder_model->getDecoderStack()) {
decoder_model->setDecoderStack(d->decoder());
@ -570,7 +570,7 @@ void ProtocolDock::search_pre()
_cur_search_index = -1;
return;
}
int i;
int i = 0;
uint64_t rowCount = _model_proxy.rowCount();
QModelIndex matchingIndex;
pv::data::DecoderModel *decoder_model = _session.get_decoder_model();
@ -626,7 +626,7 @@ void ProtocolDock::search_nxt()
_cur_search_index = -1;
return;
}
int i;
int i = 0;
uint64_t rowCount = _model_proxy.rowCount();
QModelIndex matchingIndex;
pv::data::DecoderModel *decoder_model = _session.get_decoder_model();

View File

@ -37,6 +37,9 @@
#include <QRegExpValidator>
#include <QRect>
#include <QMouseEvent>
#include <QFuture>
#include <QProgressDialog>
#include <QtConcurrent/QtConcurrent>
#include <stdint.h>
#include <boost/shared_ptr.hpp>
@ -64,7 +67,7 @@ SearchDock::SearchDock(QWidget *parent, View &view, SigSession &session) :
_nxt_button.setIcon(QIcon::fromTheme("searchDock",
QIcon(":/icons/next.png")));
QPushButton *_search_button = new QPushButton(this);
_search_button = new QPushButton(this);
_search_button->setIcon(QIcon::fromTheme("searchDock",
QIcon(":/icons/search.png")));
_search_button->setFixedWidth(_search_button->height());
@ -109,6 +112,7 @@ void SearchDock::paintEvent(QPaintEvent *)
void SearchDock::on_previous()
{
bool ret;
uint64_t last_pos;
uint8_t *data;
int unit_size;
@ -136,7 +140,22 @@ void SearchDock::on_previous()
msg.exec();
return;
} else {
const bool ret = search_value(data, unit_size, length, last_pos, 1, value);
QFuture<void> future;
future = QtConcurrent::run([&]{
ret = search_value(data, unit_size, length, last_pos, 1, value);
});
Qt::WindowFlags flags = Qt::CustomizeWindowHint;
QProgressDialog dlg(tr("Search Previous..."),
tr("Cancel"),0,0,this,flags);
dlg.setWindowModality(Qt::WindowModal);
dlg.setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint);
dlg.setCancelButton(NULL);
QFutureWatcher<void> watcher;
connect(&watcher,SIGNAL(finished()),&dlg,SLOT(cancel()));
watcher.setFuture(future);
dlg.exec();
if (!ret) {
dialogs::DSMessageBox msg(this);
msg.mBox()->setText(tr("Search"));
@ -154,6 +173,7 @@ void SearchDock::on_previous()
void SearchDock::on_next()
{
bool ret;
uint64_t last_pos;
int unit_size;
uint64_t length;
@ -180,7 +200,22 @@ void SearchDock::on_next()
msg.exec();
return;
} else {
const int ret = search_value(data, unit_size, length, last_pos, 0, value);
QFuture<void> future;
future = QtConcurrent::run([&]{
ret = search_value(data, unit_size, length, last_pos, 0, value);
});
Qt::WindowFlags flags = Qt::CustomizeWindowHint;
QProgressDialog dlg(tr("Search Next..."),
tr("Cancel"),0,0,this,flags);
dlg.setWindowModality(Qt::WindowModal);
dlg.setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint);
dlg.setCancelButton(NULL);
QFutureWatcher<void> watcher;
connect(&watcher,SIGNAL(finished()),&dlg,SLOT(cancel()));
watcher.setFuture(future);
dlg.exec();
if (!ret) {
dialogs::DSMessageBox msg(this);
msg.mBox()->setText(tr("Search"));
@ -204,6 +239,9 @@ void SearchDock::on_set()
_pattern.remove(QChar(' '), Qt::CaseInsensitive);
_pattern = _pattern.toUpper();
_search_value->setText(_pattern);
QFontMetrics fm = this->fontMetrics();
_search_value->setFixedWidth(fm.width(_pattern)+_search_button->width()+20);
}
}

View File

@ -90,6 +90,7 @@ private:
QPushButton _pre_button;
QPushButton _nxt_button;
widgets::FakeLineEdit* _search_value;
QPushButton *_search_button;
};
} // namespace dock

View File

@ -45,6 +45,7 @@
#include <QDesktopWidget>
#include <QKeyEvent>
#include <QEvent>
#include <QtGlobal>
#include "mainwindow.h"
@ -148,7 +149,7 @@ void MainWindow::setup_ui()
connect(_file_bar, SIGNAL(save()), this,
SLOT(on_save()));
connect(_file_bar, SIGNAL(on_screenShot()), this,
SLOT(on_screenShot()));
SLOT(on_screenShot()), Qt::QueuedConnection);
connect(_file_bar, SIGNAL(load_session(QString)), this,
SLOT(load_session(QString)));
connect(_file_bar, SIGNAL(store_session(QString)), this,
@ -244,9 +245,9 @@ void MainWindow::setup_ui()
connect(&_session, SIGNAL(capture_state_changed(int)), this,
SLOT(capture_state_changed(int)));
connect(&_session, SIGNAL(device_attach()), this,
SLOT(device_attach()));
SLOT(device_attach()), Qt::QueuedConnection);
connect(&_session, SIGNAL(device_detach()), this,
SLOT(device_detach()));
SLOT(device_detach()), Qt::QueuedConnection);
connect(&_session, SIGNAL(test_data_error()), this,
SLOT(test_data_error()));
connect(&_session, SIGNAL(malloc_error()), this,
@ -258,8 +259,6 @@ void MainWindow::setup_ui()
SLOT(cursor_update()));
connect(_view, SIGNAL(cursor_moved()), _measure_widget,
SLOT(cursor_moved()));
connect(_view, SIGNAL(mode_changed()), this,
SLOT(update_device_list()));
// event filter
_view->installEventFilter(this);
@ -320,11 +319,19 @@ void MainWindow::update_device_list()
if (!selected_device->name().contains("virtual")) {
_file_bar->set_settings_en(true);
_logo_bar->dsl_connected(true);
QString ses_name = DS_RES_PATH +
selected_device->name() +
QString::number(selected_device->dev_inst()->mode) +
".dsc";
load_session(ses_name);
#if QT_VERSION >= 0x050400
QDir dir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation));
#else
QDir dir(QStandardPaths::writableLocation(QStandardPaths::DataLocation));
#endif
if (dir.exists()) {
QString str = dir.absolutePath() + "/";
QString ses_name = str +
selected_device->name() +
QString::number(selected_device->dev_inst()->mode) +
".dsc";
load_session(ses_name);
}
} else {
_file_bar->set_settings_en(false);
_logo_bar->dsl_connected(false);
@ -439,7 +446,13 @@ void MainWindow::run_stop()
void MainWindow::instant_stop()
{
#ifdef TEST_MODE
if (!test_timer_linked) {
connect(&test_timer, SIGNAL(timeout()),
this, SLOT(instant_stop()));
test_timer_linked = true;
}
#endif
switch(_session.get_capture_state()) {
case SigSession::Init:
case SigSession::Stopped:
@ -506,12 +519,24 @@ void MainWindow::capture_state_changed(int state)
_trig_bar->enable_toggle(state != SigSession::Running);
_measure_dock->widget()->setEnabled(state != SigSession::Running);
}
#ifdef TEST_MODE
if (state == SigSession::Stopped) {
test_timer.start(qrand()%1000);
}
#endif
}
void MainWindow::session_save()
{
QDir dir(DS_RES_PATH);
if (dir.exists()) {
QDir dir;
#if QT_VERSION >= 0x050400
QString path = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
#else
QString path = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
#endif
if(dir.mkpath(path)) {
dir.cd(path);
QString driver_name = _session.get_device()->name();
QString mode_name = QString::number(_session.get_device()->dev_inst()->mode);
QString file_name = dir.absolutePath() + "/" + driver_name + mode_name + ".dsc";
@ -585,7 +610,8 @@ void MainWindow::on_screenShot()
QSettings settings;
QPixmap pixmap;
QDesktopWidget *desktop = QApplication::desktop();
pixmap = QPixmap::grabWindow(desktop->winId(), pos().x(), pos().y(), frameGeometry().width(), frameGeometry().height());
pixmap = QPixmap::grabWindow(desktop->winId(), parentWidget()->pos().x(), parentWidget()->pos().y(),
parentWidget()->frameGeometry().width(), parentWidget()->frameGeometry().height());
QString format = "png";
QString fileName = QFileDialog::getSaveFileName(this,
@ -625,12 +651,13 @@ bool MainWindow::load_session(QString name)
{
QFile sessionFile(name);
if (!sessionFile.open(QIODevice::ReadOnly)) {
dialogs::DSMessageBox msg(this);
msg.mBox()->setText(tr("File Error"));
msg.mBox()->setInformativeText(tr("Couldn't open session file!"));
msg.mBox()->setStandardButtons(QMessageBox::Ok);
msg.mBox()->setIcon(QMessageBox::Warning);
msg.exec();
// dialogs::DSMessageBox msg(this);
// msg.mBox()->setText(tr("File Error"));
// msg.mBox()->setInformativeText(tr("Couldn't open session file!"));
// msg.mBox()->setStandardButtons(QMessageBox::Ok);
// msg.mBox()->setIcon(QMessageBox::Warning);
// msg.exec();
qDebug("Warning: Couldn't open session file!");
return false;
}
@ -740,12 +767,13 @@ bool MainWindow::store_session(QString name)
{
QFile sessionFile(name);
if (!sessionFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
dialogs::DSMessageBox msg(this);
msg.mBox()->setText(tr("File Error"));
msg.mBox()->setInformativeText(tr("Couldn't open session file to write!"));
msg.mBox()->setStandardButtons(QMessageBox::Ok);
msg.mBox()->setIcon(QMessageBox::Warning);
msg.exec();
// dialogs::DSMessageBox msg(this);
// msg.mBox()->setText(tr("File Error"));
// msg.mBox()->setInformativeText(tr("Couldn't open session file to write!"));
// msg.mBox()->setStandardButtons(QMessageBox::Ok);
// msg.mBox()->setIcon(QMessageBox::Warning);
// msg.exec();
qDebug("Warning: Couldn't open session file to write!");
return false;
}
QTextStream outStream(&sessionFile);

View File

@ -23,6 +23,7 @@
#include <assert.h>
#include <QComboBox>
#include <QAbstractItemView>
#include "enum.h"
@ -60,12 +61,14 @@ QWidget* Enum::get_widget(QWidget *parent, bool auto_commit)
return NULL;
_selector = new QComboBox(parent);
_selector->setSizeAdjustPolicy(QComboBox::AdjustToContents);
for (unsigned int i = 0; i < _values.size(); i++) {
const pair<GVariant*, QString> &v = _values[i];
_selector->addItem(v.second, qVariantFromValue((void*)v.first));
if (value && g_variant_compare(v.first, value) == 0)
_selector->setCurrentIndex(i);
}
_selector->view()->setMinimumWidth(_selector->width()+30);
g_variant_unref(value);

View File

@ -120,6 +120,11 @@ SigSession::SigSession(DeviceManager &device_manager) :
connect(&_view_timer, SIGNAL(timeout()), this, SLOT(check_update()));
connect(&_refresh_timer, SIGNAL(timeout()), this, SLOT(data_unlock()));
#ifdef TEST_MODE
_test_timer.setSingleShot(true);
connect(&_test_timer, SIGNAL(timeout()), this, SLOT(stop_capture()));
#endif
}
SigSession::~SigSession()
@ -509,10 +514,12 @@ void SigSession::capture_init()
_cur_samplerate = _dev_inst->get_sample_rate();
_cur_samplelimits = _dev_inst->get_sample_limit();
_data_updated = false;
if (_dev_inst->dev_inst()->mode == DSO) {
if (_dev_inst->dev_inst()->mode != LOGIC)
_view_timer.start(ViewTime);
_noData_cnt = 0;
}
else
_view_timer.stop();
_noData_cnt = 0;
data_unlock();
// Init and Set sample rate for all SignalData
// Logic/Analog/Dso
@ -595,7 +602,8 @@ void SigSession::start_capture(bool instant,
void SigSession::stop_capture()
{
_instant = false;
_view_timer.stop();
//_data_lock = true;
//_view_timer.stop();
#ifdef ENABLE_DECODE
for (vector< boost::shared_ptr<view::DecodeTrace> >::iterator i =
_decode_traces.begin();
@ -608,9 +616,9 @@ void SigSession::stop_capture()
sr_session_stop();
// Check that sampling stopped
if (_sampling_thread.get())
_sampling_thread->join();
_sampling_thread.reset();
if (_sampling_thread.get())
_sampling_thread->join();
_sampling_thread.reset();
}
vector< boost::shared_ptr<view::Signal> > SigSession::get_signals()
@ -710,22 +718,30 @@ void SigSession::sample_thread_proc(boost::shared_ptr<device::DevInst> dev_inst,
dev_inst->run();
set_capture_state(Stopped);
// Confirm that SR_DF_END was received
assert(_cur_logic_snapshot->last_ended());
assert(_cur_dso_snapshot->last_ended());
assert(_cur_analog_snapshot->last_ended());
set_capture_state(Stopped);
}
void SigSession::check_update()
{
if (_capture_state != Running)
return;
if (_data_updated) {
data_updated();
_data_updated = false;
_noData_cnt = 0;
#ifdef TEST_MODE
if (!_test_timer.isActive())
_test_timer.start(qrand()%5000);
#endif
} else {
if (++_noData_cnt >= (WaitShowTime/ViewTime))
show_wait_trigger();
nodata_timeout();
}
}
@ -960,10 +976,9 @@ void SigSession::refresh(int holdtime)
{
boost::lock_guard<boost::mutex> lock(_data_mutex);
if (!_dev_inst->name().contains("virtual")) {
_data_lock = true;
_refresh_timer.start(holdtime);
}
_data_lock = true;
_refresh_timer.start(holdtime);
if (_logic_data) {
_logic_data->init();
//_cur_logic_snapshot.reset();
@ -1004,6 +1019,7 @@ bool SigSession::get_data_lock()
void SigSession::feed_in_header(const sr_dev_inst *sdi)
{
(void)sdi;
_trigger_pos = 0;
_trigger_time = QDateTime::currentDateTime();
const int64_t secs = -cur_sampletime();
@ -1100,6 +1116,7 @@ void SigSession::feed_in_logic(const sr_datafeed_logic &logic)
emit receive_data(logic.length/logic.unitsize);
data_received();
//data_updated();
_data_updated = true;
}
void SigSession::feed_in_dso(const sr_datafeed_dso &dso)
@ -1141,6 +1158,7 @@ void SigSession::feed_in_dso(const sr_datafeed_dso &dso)
m->get_math_stack()->calc_fft();
}
_trigger_flag = dso.trig_flag;
receive_data(dso.num_samples);
//data_updated();
_data_updated = true;
@ -1537,7 +1555,7 @@ void SigSession::mathTraces_rebuild()
has_dso_signal = true;
// check already have
std::vector< boost::shared_ptr<view::MathTrace> >::iterator iter = _math_traces.begin();
for(int i = 0; i < _math_traces.size(); i++, iter++)
for(unsigned int i = 0; i < _math_traces.size(); i++, iter++)
if ((*iter)->get_index() == dsoSig->get_index())
break;
// if not, rebuild
@ -1573,4 +1591,19 @@ uint64_t SigSession::get_trigger_pos() const
return _trigger_pos;
}
bool SigSession::trigd() const
{
return _trigger_flag;
}
void SigSession::nodata_timeout()
{
GVariant *gvar = _dev_inst->get_config(NULL, NULL, SR_CONF_TRIGGER_SOURCE);
if (gvar == NULL)
return;
if (g_variant_get_byte(gvar) != DSO_TRIGGER_AUTO) {
show_wait_trigger();
}
}
} // namespace pv

View File

@ -97,7 +97,7 @@ private:
public:
static const int ViewTime = 50;
static const int WaitShowTime = 1000;
static const int WaitShowTime = 500;
public:
enum capture_state {
@ -142,7 +142,6 @@ public:
void start_capture(bool instant,
boost::function<void (const QString)> error_handler);
void capture_init();
void stop_capture();
std::set< boost::shared_ptr<data::SignalData> > get_data() const;
@ -192,9 +191,10 @@ public:
bool get_instant();
bool get_data_lock();
void mathTraces_rebuild();
bool trigd() const;
private:
void set_capture_state(capture_state state);
@ -282,8 +282,13 @@ private:
bool _data_lock;
bool _data_updated;
#ifdef TEST_MODE
QTimer _test_timer;
#endif
QDateTime _trigger_time;
uint64_t _trigger_pos;
bool _trigger_flag;
signals:
void capture_state_changed(int state);
@ -331,11 +336,13 @@ signals:
public slots:
void reload();
void refresh(int holdtime);
void stop_capture();
private slots:
void cancelSaveFile();
void data_unlock();
void check_update();
void nodata_timeout();
private:
// TODO: This should not be necessary. Multiple concurrent

View File

@ -119,6 +119,9 @@ FileBar::FileBar(SigSession &session, QWidget *parent) :
_menu->addAction(_action_capture);
_file_button.setMenu(_menu);
addWidget(&_file_button);
_screenshot_timer.setSingleShot(true);
connect(&_screenshot_timer, SIGNAL(timeout()), this, SIGNAL(on_screenShot()));
}
void FileBar::on_actionOpen_triggered()
@ -277,7 +280,9 @@ void FileBar::on_actionStore_triggered()
void FileBar::on_actionCapture_triggered()
{
on_screenShot();
_file_button.close();
QCoreApplication::sendPostedEvents();
_screenshot_timer.start(100);
}
void FileBar::enable_toggle(bool enable)

View File

@ -85,6 +85,8 @@ private:
QAction *_action_export;
QAction *_action_capture;
QTimer _screenshot_timer;
};
} // namespace toolbars

View File

@ -105,7 +105,7 @@ SamplingBar::SamplingBar(SigSession &session, QWidget *parent) :
connect(&_configure_button, SIGNAL(clicked()),
this, SLOT(on_configure()));
connect(&_run_stop_button, SIGNAL(clicked()),
this, SLOT(on_run_stop()));
this, SLOT(on_run_stop()), Qt::DirectConnection);
connect(&_instant_button, SIGNAL(clicked()),
this, SLOT(on_instant_stop()));
@ -268,7 +268,13 @@ void SamplingBar::zero_adj()
run_stop();
pv::dialogs::WaitingDialog wait(this, get_selected_device());
wait.start();
if (wait.start() ==QDialog::Rejected) {
BOOST_FOREACH(const boost::shared_ptr<view::Signal> s, _session.get_signals())
{
if (dsoSig = dynamic_pointer_cast<view::DsoSignal>(s))
dsoSig->commit_settings();
}
}
if (_session.get_capture_state() == pv::SigSession::Running)
run_stop();
@ -327,15 +333,13 @@ void SamplingBar::set_sampling(bool sampling)
}
if (!sampling) {
g_usleep(100000);
_run_stop_button.setEnabled(true);
_instant_button.setEnabled(true);
enable_run_stop(true);
enable_instant(true);
} else {
g_usleep(100000);
if (_instant)
_instant_button.setEnabled(true);
enable_instant(true);
else
_run_stop_button.setEnabled(true);
enable_run_stop(true);
}
_configure_button.setEnabled(!sampling);
@ -452,7 +456,6 @@ void SamplingBar::update_sample_rate_selector_value()
void SamplingBar::commit_sample_rate()
{
uint64_t sample_rate = 0;
uint64_t last_sample_rate = 0;
if (_updating_sample_rate)
return;
@ -468,15 +471,9 @@ void SamplingBar::commit_sample_rate()
if (sample_rate == 0)
return;
// Get last samplerate
last_sample_rate = get_selected_device()->get_sample_rate();
//if (last_sample_rate != sample_rate) {
// Set the samplerate
get_selected_device()->set_config(NULL, NULL,
SR_CONF_SAMPLERATE,
g_variant_new_uint64(sample_rate));
//}
get_selected_device()->set_config(NULL, NULL,
SR_CONF_SAMPLERATE,
g_variant_new_uint64(sample_rate));
_updating_sample_rate = false;
}

View File

@ -39,10 +39,10 @@ namespace pv {
namespace toolbars {
TitleBar::TitleBar(bool top, QWidget *parent, bool hasClose) :
QWidget(parent),
_moving(false),
_isTop(top),
_hasClose(hasClose),
QWidget(parent)
_hasClose(hasClose)
{
setObjectName("TitleBar");
setFixedHeight(28);

View File

@ -281,9 +281,6 @@ void DecodeTrace::paint_mid(QPainter &p, int left, int right)
assert(_decoder_stack);
const double decode_startX = _decode_start/samples_per_pixel - (_view->offset() / _view->scale());
const double decode_endX = _decode_end/samples_per_pixel - (_view->offset() / _view->scale());
BOOST_FOREACH(boost::shared_ptr<data::decode::Decoder> dec,
_decoder_stack->stack()) {
if (dec->shown()) {
@ -335,6 +332,8 @@ void DecodeTrace::paint_fore(QPainter &p, int left, int right)
{
using namespace pv::data::decode;
(void)p;
(void)left;
(void)right;
}
@ -504,6 +503,7 @@ void DecodeTrace::draw_nodetail(QPainter &p,
int h, int left, int right, int y,
size_t base_colour) const
{
(void)base_colour;
const QRectF nodetail_rect(left, y - h/2 + 0.5, right - left, h);
QString info = tr("Zoom in For Detials");
int info_left = nodetail_rect.center().x() - p.boundingRect(QRectF(), 0, info).width();

View File

@ -107,6 +107,9 @@ void DevMode::on_mode_change()
const boost::shared_ptr<device::DevInst> dev_inst = _session.get_device();
assert(dev_inst);
QPushButton *button = qobject_cast<QPushButton *>(sender());
button->setChecked(true);
if (dev_inst->dev_inst()->mode == _mode_button_list[button]->mode)
return;
for(std::map<QPushButton *, sr_dev_mode *>::const_iterator i = _mode_button_list.begin();
i != _mode_button_list.end(); i++) {

View File

@ -21,7 +21,8 @@
#include "dsldial.h"
#include <assert.h>
#include <cassert>
#include <cmath>
namespace pv {
namespace view {

View File

@ -120,8 +120,7 @@ DsoSignal::DsoSignal(boost::shared_ptr<pv::device::DevInst> dev_inst,
_hover_point(QPointF(0, 0)),
_hover_value(0),
_ms_gear_hover(false),
_ms_show_hover(false),
_ms_show(false)
_ms_show_hover(false)
{
QVector<uint64_t> vValue;
QVector<QString> vUnit;
@ -142,12 +141,6 @@ DsoSignal::DsoSignal(boost::shared_ptr<pv::device::DevInst> dev_inst,
_colour = SignalColours[probe->index % countof(SignalColours)];
for (int i = DSO_MS_BEGIN; i < DSO_MS_END; i++)
_ms_en[i] = false;
_ms_en[DSO_MS_FREQ] = true;
_ms_en[DSO_MS_VMAX] = true;
_ms_en[DSO_MS_VMIN] = true;
load_settings();
}
@ -194,6 +187,10 @@ void DsoSignal::set_enable(bool enable)
get_index() == 0)
return;
_view->session().refresh(INT_MAX);
/*
* avoid race condition for en_ch_num
* data lock need to lock usb event
*/
_dev_inst->set_config(_probe, NULL, SR_CONF_DATALOCK,
g_variant_new_boolean(true));
set_vDialActive(false);
@ -230,7 +227,9 @@ void DsoSignal::set_enable(bool enable)
_dev_inst->set_config(_probe, NULL, SR_CONF_DATALOCK,
g_variant_new_boolean(false));
_view->session().refresh(800);
_view->session().refresh(RefreshLong);
_view->set_update(_viewport, true);
_view->update();
}
bool DsoSignal::get_vDialActive() const
@ -247,6 +246,8 @@ void DsoSignal::set_vDialActive(bool active)
bool DsoSignal::go_vDialPre()
{
if (enabled() && !_vDial->isMin()) {
if (_view->session().get_capture_state() == SigSession::Running)
_view->session().refresh(RefreshShort);
const double pre_vdiv = _vDial->get_value();
_vDial->set_sel(_vDial->get_sel() - 1);
_dev_inst->set_config(_probe, NULL, SR_CONF_VDIV,
@ -267,6 +268,8 @@ bool DsoSignal::go_vDialPre()
bool DsoSignal::go_vDialNext()
{
if (enabled() && !_vDial->isMax()) {
if (_view->session().get_capture_state() == SigSession::Running)
_view->session().refresh(RefreshShort);
const double pre_vdiv = _vDial->get_value();
_vDial->set_sel(_vDial->get_sel() + 1);
_dev_inst->set_config(_probe, NULL, SR_CONF_VDIV,
@ -307,7 +310,7 @@ bool DsoSignal::go_hDialPre(bool setted)
} else if ((_view->session().get_capture_state() == SigSession::Running ||
_data->get_snapshots().empty()) &&
!_view->session().get_instant()) {
_view->session().refresh(100);
_view->session().refresh(RefreshShort);
_hDial->set_sel(_hDial->get_sel() - 1);
if (!setted) {
@ -349,7 +352,7 @@ bool DsoSignal::go_hDialCur()
if (ch_num == 0)
return false;
_view->session().refresh(100);
_view->session().refresh(RefreshShort);
uint64_t sample_limit = _view->session().get_device()->get_sample_limit();
GVariant* gvar;
uint64_t max_sample_rate;
@ -383,7 +386,7 @@ bool DsoSignal::go_hDialNext(bool setted)
} else if ((_view->session().get_capture_state() == SigSession::Running ||
_data->get_snapshots().empty()) &&
!_view->session().get_instant()) {
_view->session().refresh(100);
_view->session().refresh(RefreshShort);
_hDial->set_sel(_hDial->get_sel() + 1);
if (!setted) {
@ -485,8 +488,8 @@ bool DsoSignal::load_settings()
_vDial->set_value(vdiv);
_vDial->set_factor(vfactor);
_dev_inst->set_config(_probe, NULL, SR_CONF_VDIV,
g_variant_new_uint64(_vDial->get_value()));
// _dev_inst->set_config(_probe, NULL, SR_CONF_VDIV,
// g_variant_new_uint64(_vDial->get_value()));
// -- coupling
gvar = _dev_inst->get_config(_probe, NULL, SR_CONF_COUPLING);
@ -498,8 +501,8 @@ bool DsoSignal::load_settings()
return false;
}
_dev_inst->set_config(_probe, NULL, SR_CONF_COUPLING,
g_variant_new_byte(_acCoupling));
// _dev_inst->set_config(_probe, NULL, SR_CONF_COUPLING,
// g_variant_new_byte(_acCoupling));
// -- vpos
double vpos;
@ -512,7 +515,10 @@ bool DsoSignal::load_settings()
return false;
}
_zero_vrate = min(max((0.5 - vpos / (_vDial->get_value() * DS_CONF_DSO_VDIVS)), 0.0), 1.0);
_zero_value = _zero_vrate * ((1 << _bits) - 1);
if (_dev_inst->name() == "DSCope")
_zero_value = _zero_vrate * ((1 << _bits) - 1);
else
_zero_value = 0x80;
// -- trig_value
gvar = _dev_inst->get_config(_probe, NULL, SR_CONF_TRIGGER_VALUE);
@ -602,7 +608,10 @@ int DsoSignal::get_trig_vpos() const
double DsoSignal::get_trig_vrate() const
{
return _trig_value * 1.0 / ((1 << _bits) - 1.0);
if (_dev_inst->name() == "DSLogic")
return (_trig_value - (1 << (_bits - 1)))* 1.0 / ((1 << _bits) - 1.0) + _zero_vrate;
else
return _trig_value * 1.0 / ((1 << _bits) - 1.0);
}
void DsoSignal::set_trig_vpos(int pos, bool delta_change)
@ -671,7 +680,10 @@ void DsoSignal::set_zero_vpos(int pos)
void DsoSignal::set_zero_vrate(double rate)
{
_zero_vrate = rate;
_zero_value = rate * ((1 << _bits) - 1);
if (_dev_inst->name() == "DSCope")
_zero_value = _zero_vrate * ((1 << _bits) - 1);
else
_zero_value = 0x80;
update_offset();
}
@ -715,13 +727,13 @@ uint64_t DsoSignal::get_factor()
void DsoSignal::set_ms_show(bool show)
{
_ms_show = show;
_probe->ms_show = show;
_view->set_update(_viewport, true);
}
bool DsoSignal::get_ms_show() const
{
return _ms_show;
return _probe->ms_show;
}
bool DsoSignal::get_ms_show_hover() const
@ -739,7 +751,7 @@ void DsoSignal::set_ms_en(int index, bool en)
assert(index > DSO_MS_BEGIN);
assert(index < DSO_MS_END);
_ms_en[index] = en;
_probe->ms_en[index] = en;
}
bool DsoSignal::get_ms_en(int index) const
@ -747,7 +759,7 @@ bool DsoSignal::get_ms_en(int index) const
assert(index > DSO_MS_BEGIN);
assert(index < DSO_MS_END);
return _ms_en[index];
return _probe->ms_en[index];
}
QString DsoSignal::get_ms_string(int index) const
@ -861,8 +873,6 @@ void DsoSignal::paint_mid(QPainter &p, int left, int right)
assert(scale > 0);
const double offset = _view->offset();
paint_measure(p);
const deque< boost::shared_ptr<pv::data::DsoSnapshot> > &snapshots =
_data->get_snapshots();
if (snapshots.empty())
@ -949,6 +959,9 @@ void DsoSignal::paint_fore(QPainter &p, int left, int right)
// Paint the text
p.setPen(Qt::white);
p.drawText(label_rect, Qt::AlignCenter | Qt::AlignVCenter, "T");
// Paint measure
paint_measure(p);
}
}
@ -986,7 +999,7 @@ void DsoSignal::paint_trace(QPainter &p,
float zeroP = _zero_vrate * get_view_rect().height() + top;;
if (_dev_inst->name() == "DSCope" &&
_view->session().get_capture_state() == SigSession::Running)
_zero_value = _zero_vrate * ((1 << _bits) - 1);
_zero_value = _zero_vrate * ((1 << _bits) - 1);
float x = (start / samples_per_pixel - pixels_offset) + left;
double pixels_per_sample = 1.0/samples_per_pixel;
uint8_t offset;
@ -1042,7 +1055,7 @@ void DsoSignal::paint_envelope(QPainter &p,
float zeroP = _zero_vrate * get_view_rect().height() + top;
if (_dev_inst->name() == "DSCope" &&
_view->session().get_capture_state() == SigSession::Running)
_zero_value = _zero_vrate * ((1 << _bits) - 1);
_zero_value = _zero_vrate * ((1 << _bits) - 1);
for(uint64_t sample = 0; sample < e.length-1; sample++) {
const float x = ((e.scale * sample + e.start) /
samples_per_pixel - pixels_offset) + left;
@ -1212,19 +1225,19 @@ bool DsoSignal::mouse_wheel(int right, const QPoint pt, const int shift)
const QRectF hDial_rect = get_rect(DSO_HDIAL, y, right);
if (vDial_rect.contains(pt)) {
if (shift > 1.0)
if (shift > 0.5)
go_vDialNext();
else if (shift < -1.0)
else if (shift < -0.5)
go_vDialPre();
return true;
} else if (hDial_rect.contains(pt)) {
boost::shared_ptr<view::DsoSignal> dsoSig;
BOOST_FOREACH(const boost::shared_ptr<Trace> t, traces) {
if (dsoSig = dynamic_pointer_cast<view::DsoSignal>(t)) {
if (shift > 1.0) {
if (shift > 0.5) {
dsoSig->go_hDialNext(setted);
setted = true;
} else if (shift < -1.0) {
} else if (shift < -0.5) {
dsoSig->go_hDialPre(setted);
setted = true;
}
@ -1327,7 +1340,7 @@ void DsoSignal::paint_measure(QPainter &p)
abs(_period) > 1000 ? QString::number(1000000/_period, 'f', 2) + "kHz" : QString::number(1000/_period, 'f', 2) + "MHz");
_ms_string[DSO_MS_VP2P] = "Vp-p: " + (abs(value_p2p) > 1000 ? QString::number(value_p2p/1000.0, 'f', 2) + "V" : QString::number(value_p2p, 'f', 2) + "mV");
if (_ms_show && _ms_en[DSO_MS_VRMS]) {
if (_probe->ms_show && _probe->ms_en[DSO_MS_VRMS]) {
const deque< boost::shared_ptr<pv::data::DsoSnapshot> > &snapshots =
_data->get_snapshots();
if (!snapshots.empty()) {
@ -1339,7 +1352,7 @@ void DsoSignal::paint_measure(QPainter &p)
}
}
if (_ms_show && _ms_en[DSO_MS_VMEA]) {
if (_probe->ms_show && _probe->ms_en[DSO_MS_VMEA]) {
const deque< boost::shared_ptr<pv::data::DsoSnapshot> > &snapshots =
_data->get_snapshots();
if (!snapshots.empty()) {
@ -1372,7 +1385,7 @@ void DsoSignal::paint_measure(QPainter &p)
p.setBrush(measure_colour);
p.drawRoundedRect(_ms_rect[DSO_MS_BEGIN], MS_RectRad, MS_RectRad);
const QPixmap gear_pix(":/icons/settings.png");
const QPixmap show_pix(_ms_show ? ":/icons/shown.png" : ":/icons/hidden.png");
const QPixmap show_pix(_probe->ms_show ? ":/icons/shown.png" : ":/icons/hidden.png");
if (_ms_gear_hover) {
p.setBrush(back_colour);
p.drawRoundedRect(_ms_gear_rect, MS_RectRad, MS_RectRad);
@ -1385,11 +1398,11 @@ void DsoSignal::paint_measure(QPainter &p)
p.setPen(Qt::white);
p.drawText(_ms_rect[DSO_MS_BEGIN], Qt::AlignCenter | Qt::AlignVCenter, "CH"+QString::number(index));
if (_ms_show) {
if (_probe->ms_show) {
p.setBrush(back_colour);
int j = DSO_MS_BEGIN+1;
for (int i=DSO_MS_BEGIN+1; i<DSO_MS_END; i++) {
if (_ms_en[i]) {
if (_probe->ms_en[i]) {
p.setPen(_colour);
p.drawText(_ms_rect[j], Qt::AlignLeft | Qt::AlignVCenter, _ms_string[i]);
p.setPen(Qt::NoPen);
@ -1436,7 +1449,7 @@ void DsoSignal::paint_measure(QPainter &p)
}
}
}
_view->update();
//_view->update();
}
void DsoSignal::auto_set()

View File

@ -63,20 +63,10 @@ private:
static const uint8_t DefaultBits = 8;
static const int TrigMargin = 16;
static const int RefreshShort = 200;
static const int RefreshLong = 800;
public:
enum DSO_MEASURE_TYPE {
DSO_MS_BEGIN = 0,
DSO_MS_FREQ,
DSO_MS_PERD,
DSO_MS_VMAX,
DSO_MS_VMIN,
DSO_MS_VRMS,
DSO_MS_VMEA,
DSO_MS_VP2P,
DSO_MS_END,
};
enum DsoSetRegions {
DSO_NONE = -1,
DSO_VDIAL,

View File

@ -257,7 +257,7 @@ void Header::wheelEvent(QWheelEvent *event)
const vector< boost::shared_ptr<Trace> > traces(
_view.get_traces(ALL_VIEW));
// Vertical scrolling
double shift = event->delta() / 20.0;
double shift = event->delta() / 80.0;
BOOST_FOREACH(const boost::shared_ptr<Trace> t, traces)
if (t->mouse_wheel(width(), event->pos(), shift))
break;

View File

@ -117,7 +117,7 @@ void MathTrace::set_view_mode(int mode)
std::vector<QString> MathTrace::get_view_modes_support()
{
std::vector<QString> modes;
for (int i = 0; i < sizeof(FFT_ViewMode)/sizeof(FFT_ViewMode[0]); i++) {
for (unsigned int i = 0; i < sizeof(FFT_ViewMode)/sizeof(FFT_ViewMode[0]); i++) {
modes.push_back(FFT_ViewMode[i]);
}
return modes;
@ -191,7 +191,7 @@ int MathTrace::dbv_range() const
std::vector<int> MathTrace::get_dbv_ranges()
{
std::vector<int> range;
for (int i = 0; i < sizeof(DbvRanges)/sizeof(DbvRanges[0]); i++) {
for (unsigned int i = 0; i < sizeof(DbvRanges)/sizeof(DbvRanges[0]); i++) {
range.push_back(DbvRanges[i]);
}
return range;
@ -231,9 +231,9 @@ bool MathTrace::measure(const QPoint &p)
if(samples.empty())
return false;
const int full_size = (_math_stack->get_sample_num()/2+1);
const unsigned int full_size = (_math_stack->get_sample_num()/2);
const double view_off = full_size * _offset;
const int view_size = full_size*_scale;
const double view_size = full_size*_scale;
const double sample_per_pixels = view_size/window.width();
_hover_index = std::round(p.x() * sample_per_pixels + view_off);
@ -251,7 +251,6 @@ void MathTrace::paint_back(QPainter &p, int left, int right)
if(!_view)
return;
int i, j;
const int height = get_view_rect().height();
const int width = right - left;
@ -277,7 +276,7 @@ void MathTrace::paint_mid(QPainter &p, int left, int right)
trace_colour.setAlpha(150);
p.setPen(trace_colour);
const int full_size = (_math_stack->get_sample_num()/2+1);
const int full_size = (_math_stack->get_sample_num()/2);
const double view_off = full_size * _offset;
const int view_start = floor(view_off);
const int view_size = full_size*_scale;
@ -289,8 +288,8 @@ void MathTrace::paint_mid(QPainter &p, int left, int right)
const double width = right - left;
const double pixels_per_sample = width/view_size;
double vdiv;
double vfactor;
double vdiv = 0;
double vfactor = 0;
BOOST_FOREACH(const boost::shared_ptr<Signal> s, _session.get_signals()) {
boost::shared_ptr<DsoSignal> dsoSig;
if (dsoSig = dynamic_pointer_cast<DsoSignal>(s)) {
@ -349,6 +348,8 @@ void MathTrace::paint_fore(QPainter &p, int left, int right)
return;
assert(right >= left);
(void)left;
(void)right;
const int text_height = p.boundingRect(0, 0, INT_MAX, INT_MAX,
AlignLeft | AlignTop, "8").height();
const double width = get_view_rect().width();
@ -427,7 +428,7 @@ void MathTrace::paint_fore(QPainter &p, int left, int right)
const std::vector<double> samples(_math_stack->get_fft_spectrum());
if(samples.empty())
return;
const int full_size = (_math_stack->get_sample_num()/2+1);
const int full_size = (_math_stack->get_sample_num()/2);
const double view_off = full_size * _offset;
const int view_size = full_size*_scale;
const double scale = height / (_vmax - _vmin);

View File

@ -81,7 +81,8 @@ View::View(SigSession &session, pv::toolbars::SamplingBar *sampling_bar, QWidget
_preOffset(0),
_updating_scroll(false),
_show_cursors(false),
_hover_point(-1, -1)
_hover_point(-1, -1),
_dso_auto(true)
{
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
@ -165,8 +166,6 @@ View::View(SigSession &session, pv::toolbars::SamplingBar *sampling_bar, QWidget
connect(&_session, SIGNAL(show_wait_trigger()),
_time_viewport, SLOT(show_wait_trigger()));
// connect(_devmode, SIGNAL(mode_changed()),
// this, SIGNAL(mode_changed()));
connect(_devmode, SIGNAL(mode_changed()),
parent, SLOT(update_device_list()), Qt::DirectConnection);
@ -629,7 +628,7 @@ void View::signals_changed()
// Find the decoder in the stack
std::list< Viewport *>::iterator iter = _viewport_list.begin();
for(int i = 0; i < _viewport_list.size(); i++, iter++)
for(unsigned int i = 0; i < _viewport_list.size(); i++, iter++)
if ((*iter) == _fft_viewport)
break;
// Delete the element
@ -803,6 +802,7 @@ void View::h_scroll_value_changed(int value)
void View::v_scroll_value_changed(int value)
{
(void)value;
_header->update();
viewport_update();
}

View File

@ -202,8 +202,6 @@ signals:
void cursor_moved();
void mode_changed();
void measure_updated();
private:
@ -305,6 +303,7 @@ private:
QPoint _hover_point;
dialogs::Calibration *_cali;
bool _dso_auto;
};
} // namespace view

View File

@ -238,14 +238,36 @@ void Viewport::paintSignals(QPainter &p)
//plot measure arrow
paintMeasure(p);
//plot waiting trigger
if (_waiting_trig > 0) {
//plot trigger information
if (_view.session().get_device()->dev_inst()->mode == DSO &&
_view.session().get_capture_state() == SigSession::Running) {
uint8_t type;
bool stream = false;
QString type_str="";
GVariant *gvar = _view.session().get_device()->get_config(NULL, NULL, SR_CONF_STREAM);
if (gvar != NULL) {
stream = g_variant_get_boolean(gvar);
g_variant_unref(gvar);
}
gvar = _view.session().get_device()->get_config(NULL, NULL, SR_CONF_TRIGGER_SOURCE);
if (gvar != NULL) {
type = g_variant_get_byte(gvar);
g_variant_unref(gvar);
if (type == DSO_TRIGGER_AUTO && stream) {
type_str = "Auto(Roll)";
} else if (type == DSO_TRIGGER_AUTO && !_view.session().trigd()) {
type_str = "Auto";
} else if (_waiting_trig > 0) {
type_str = "Waiting Trig";
for (int i = 1; i < _waiting_trig; i++)
if (i % (WaitLoopTime / SigSession::ViewTime) == 0)
type_str += ".";
} else {
type_str = "Trig'd";
}
}
p.setPen(Trace::DARK_FORE);
QString text = "Waiting Trig";
for (int i = 1; i < _waiting_trig; i++)
if (i % (WaitLoopTime / SigSession::ViewTime) == 0)
text += ".";
p.drawText(_view.get_view_rect(), Qt::AlignLeft | Qt::AlignTop, text);
p.drawText(_view.get_view_rect(), Qt::AlignLeft | Qt::AlignTop, type_str);
}
}
}
@ -255,6 +277,7 @@ void Viewport::paintProgress(QPainter &p)
using pv::view::Signal;
const uint64_t _total_sample_len = _view.session().cur_samplelimits();
double progress = -(_total_receive_len * 1.0 / _total_sample_len * 360 * 16);
int captured_progress = 0;
@ -338,10 +361,12 @@ void Viewport::paintProgress(QPainter &p)
sr_status status;
if (sr_status_get(_view.session().get_device()->dev_inst(), &status, SR_STATUS_TRIG_BEGIN, SR_STATUS_TRIG_END) == SR_OK){
const bool triggred = status.trig_hit & 0x01;
const uint32_t captured_cnt = (status.captured_cnt0 +
uint32_t captured_cnt = (status.captured_cnt0 +
(status.captured_cnt1 << 8) +
(status.captured_cnt2 << 16) +
(status.captured_cnt3 << 24));
if (_view.session().get_device()->dev_inst()->mode == DSO)
captured_cnt = captured_cnt * _view.session().get_signals().size() / _view.session().get_ch_num(SR_CHANNEL_DSO);
if (triggred)
captured_progress = (_total_sample_len - captured_cnt) * 100.0 / _total_sample_len;
else
@ -924,7 +949,7 @@ void Viewport::measure()
BOOST_FOREACH(const boost::shared_ptr<view::MathTrace> t, _view.session().get_math_signals()) {
assert(t);
if(t->enabled()) {
t->measure(_view.hover_point());
t->measure(_mouse_point);
}
}
}
@ -1279,7 +1304,12 @@ void Viewport::on_drag_timer()
_drag_strength /= DragDamping;
if (_drag_strength != 0)
_drag_timer.start(DragTimerInterval);
} else if (_action_type == NO_ACTION){
} else if (offset == _view.get_max_offset() ||
offset == _view.get_min_offset()) {
_drag_strength = 0;
_drag_timer.stop();
_action_type = NO_ACTION;
}else if (_action_type == NO_ACTION){
_drag_strength = 0;
_drag_timer.stop();
}

View File

@ -30,8 +30,8 @@ namespace pv {
namespace widgets {
Border::Border(int type, QWidget *parent) :
_type(type),
QWidget(parent)
QWidget(parent),
_type(type)
{
setAttribute(Qt::WA_TranslucentBackground);
setMouseTracking(true);

BIN
DSView/res/DSCope.bin Normal file → Executable file

Binary file not shown.

BIN
DSView/res/DSCope.fw Normal file → Executable file

Binary file not shown.

6
DSView/res/DSCope1.def.dsc Normal file → Executable file
View File

@ -1,7 +1,7 @@
{
{
"Device": "DSCope",
"DeviceMode": 1,
"Horizontal trigger position": "0",
"Horizontal trigger position": "1",
"Operation Mode": "Normal",
"Sample count": "1048576",
"Sample rate": "100000000",
@ -16,7 +16,6 @@
"enabled": true,
"index": 0,
"name": "0",
"strigger": 0,
"trigValue": 0.5,
"type": 10001,
"vdiv": 1000,
@ -29,7 +28,6 @@
"enabled": true,
"index": 1,
"name": "1",
"strigger": 0,
"trigValue": 0.5,
"type": 10001,
"vdiv": 1000,

View File

@ -1,40 +0,0 @@
{
"Device": "DSCope",
"DeviceMode": 1,
"Horizontal trigger position": "0",
"Operation Mode": "Normal",
"Sample count": "1048576",
"Sample rate": "100000000",
"Time base": "10000",
"Trigger hold off": "0",
"Trigger slope": "0",
"Trigger source": "0",
"channel": [
{
"colour": "#eeb211",
"coupling": 0,
"enabled": true,
"index": 0,
"name": "0",
"strigger": 0,
"trigValue": 0.5,
"type": 10001,
"vdiv": 1000,
"vfactor": 1,
"zeroPos": 0.5
},
{
"colour": "#009925",
"coupling": 0,
"enabled": true,
"index": 1,
"name": "1",
"strigger": 0,
"trigValue": 0.5,
"type": 10001,
"vdiv": 1000,
"vfactor": 1,
"zeroPos": 0.5
}
]
}

BIN
DSView/res/DSCope20.bin Executable file

Binary file not shown.

BIN
DSView/res/DSCope20.fw Executable file

Binary file not shown.

BIN
DSView/res/DSLogic.fw Normal file → Executable file

Binary file not shown.

538
DSView/res/DSLogic0.def.dsc Normal file → Executable file
View File

@ -1,268 +1,270 @@
{
"Device": "DSLogic",
"DeviceMode": 0,
"Filter Targets": "None",
"Horizontal trigger position": "0",
"Operation Mode": "Normal",
"Sample count": "16777216",
"Sample rate": "100000000",
"Threshold Level": 1,
"Trigger hold off": "0",
"Trigger slope": "0",
"Trigger source": "0",
"Using Clock Negedge": 0,
"Using External Clock": 0,
"channel": [
{
"colour": "#16191a",
"enabled": true,
"index": 0,
"name": "0",
"strigger": 0,
"type": 10000
},
{
"colour": "#8f5202",
"enabled": true,
"index": 1,
"name": "1",
"strigger": 0,
"type": 10000
},
{
"colour": "#cc0000",
"enabled": true,
"index": 2,
"name": "2",
"strigger": 0,
"type": 10000
},
{
"colour": "#f57900",
"enabled": true,
"index": 3,
"name": "3",
"strigger": 0,
"type": 10000
},
{
"colour": "#edd400",
"enabled": true,
"index": 4,
"name": "4",
"strigger": 0,
"type": 10000
},
{
"colour": "#73d216",
"enabled": true,
"index": 5,
"name": "5",
"strigger": 0,
"type": 10000
},
{
"colour": "#3465a4",
"enabled": true,
"index": 6,
"name": "6",
"strigger": 0,
"type": 10000
},
{
"colour": "#75507b",
"enabled": true,
"index": 7,
"name": "7",
"strigger": 0,
"type": 10000
},
{
"colour": "#16191a",
"enabled": true,
"index": 8,
"name": "8",
"strigger": 0,
"type": 10000
},
{
"colour": "#8f5202",
"enabled": true,
"index": 9,
"name": "9",
"strigger": 0,
"type": 10000
},
{
"colour": "#cc0000",
"enabled": true,
"index": 10,
"name": "10",
"strigger": 0,
"type": 10000
},
{
"colour": "#f57900",
"enabled": true,
"index": 11,
"name": "11",
"strigger": 0,
"type": 10000
},
{
"colour": "#edd400",
"enabled": true,
"index": 12,
"name": "12",
"strigger": 0,
"type": 10000
},
{
"colour": "#73d216",
"enabled": true,
"index": 13,
"name": "13",
"strigger": 0,
"type": 10000
},
{
"colour": "#3465a4",
"enabled": true,
"index": 14,
"name": "14",
"strigger": 0,
"type": 10000
},
{
"colour": "#75507b",
"enabled": true,
"index": 15,
"name": "15",
"strigger": 0,
"type": 10000
}
],
"trigger": {
"triggerChannel": 0,
"triggerClock": "X X X X X X X X X X X X X X X X",
"triggerCount00": 1,
"triggerCount01": 1,
"triggerCount010": 1,
"triggerCount011": 1,
"triggerCount012": 1,
"triggerCount013": 1,
"triggerCount014": 1,
"triggerCount015": 1,
"triggerCount02": 1,
"triggerCount03": 1,
"triggerCount04": 1,
"triggerCount05": 1,
"triggerCount06": 1,
"triggerCount07": 1,
"triggerCount08": 1,
"triggerCount09": 1,
"triggerCount10": 1,
"triggerCount11": 1,
"triggerCount110": 1,
"triggerCount111": 1,
"triggerCount112": 1,
"triggerCount113": 1,
"triggerCount114": 1,
"triggerCount115": 1,
"triggerCount12": 1,
"triggerCount13": 1,
"triggerCount14": 1,
"triggerCount15": 1,
"triggerCount16": 1,
"triggerCount17": 1,
"triggerCount18": 1,
"triggerCount19": 1,
"triggerData": "X X X X X X X X X X X X X X X X",
"triggerInv00": 0,
"triggerInv01": 0,
"triggerInv010": 0,
"triggerInv011": 0,
"triggerInv012": 0,
"triggerInv013": 0,
"triggerInv014": 0,
"triggerInv015": 0,
"triggerInv02": 0,
"triggerInv03": 0,
"triggerInv04": 0,
"triggerInv05": 0,
"triggerInv06": 0,
"triggerInv07": 0,
"triggerInv08": 0,
"triggerInv09": 0,
"triggerInv10": 0,
"triggerInv11": 0,
"triggerInv110": 0,
"triggerInv111": 0,
"triggerInv112": 0,
"triggerInv113": 0,
"triggerInv114": 0,
"triggerInv115": 0,
"triggerInv12": 0,
"triggerInv13": 0,
"triggerInv14": 0,
"triggerInv15": 0,
"triggerInv16": 0,
"triggerInv17": 0,
"triggerInv18": 0,
"triggerInv19": 0,
"triggerLogic0": 1,
"triggerLogic1": 1,
"triggerLogic10": 1,
"triggerLogic11": 1,
"triggerLogic12": 1,
"triggerLogic13": 1,
"triggerLogic14": 1,
"triggerLogic15": 1,
"triggerLogic2": 1,
"triggerLogic3": 1,
"triggerLogic4": 1,
"triggerLogic5": 1,
"triggerLogic6": 1,
"triggerLogic7": 1,
"triggerLogic8": 1,
"triggerLogic9": 1,
"triggerMode": 0,
"triggerPos": 0,
"triggerSerial": 0,
"triggerStages": 0,
"triggerStart": "X X X X X X X X X X X X X X X X",
"triggerStop": "X X X X X X X X X X X X X X X X",
"triggerValue00": "X X X X X X X X X X X X X X X X",
"triggerValue01": "X X X X X X X X X X X X X X X X",
"triggerValue010": "X X X X X X X X X X X X X X X X",
"triggerValue011": "X X X X X X X X X X X X X X X X",
"triggerValue012": "X X X X X X X X X X X X X X X X",
"triggerValue013": "X X X X X X X X X X X X X X X X",
"triggerValue014": "X X X X X X X X X X X X X X X X",
"triggerValue015": "X X X X X X X X X X X X X X X X",
"triggerValue02": "X X X X X X X X X X X X X X X X",
"triggerValue03": "X X X X X X X X X X X X X X X X",
"triggerValue04": "X X X X X X X X X X X X X X X X",
"triggerValue05": "X X X X X X X X X X X X X X X X",
"triggerValue06": "X X X X X X X X X X X X X X X X",
"triggerValue07": "X X X X X X X X X X X X X X X X",
"triggerValue08": "X X X X X X X X X X X X X X X X",
"triggerValue09": "X X X X X X X X X X X X X X X X",
"triggerValue10": "X X X X X X X X X X X X X X X X",
"triggerValue11": "X X X X X X X X X X X X X X X X",
"triggerValue110": "X X X X X X X X X X X X X X X X",
"triggerValue111": "X X X X X X X X X X X X X X X X",
"triggerValue112": "X X X X X X X X X X X X X X X X",
"triggerValue113": "X X X X X X X X X X X X X X X X",
"triggerValue114": "X X X X X X X X X X X X X X X X",
"triggerValue115": "X X X X X X X X X X X X X X X X",
"triggerValue12": "X X X X X X X X X X X X X X X X",
"triggerValue13": "X X X X X X X X X X X X X X X X",
"triggerValue14": "X X X X X X X X X X X X X X X X",
"triggerValue15": "X X X X X X X X X X X X X X X X",
"triggerValue16": "X X X X X X X X X X X X X X X X",
"triggerValue17": "X X X X X X X X X X X X X X X X",
"triggerValue18": "X X X X X X X X X X X X X X X X",
"triggerValue19": "X X X X X X X X X X X X X X X X"
}
}
{
"Channel Mode": "Use Channels 0~15 (Max 100MHz)",
"Device": "DSLogic",
"DeviceMode": 0,
"Filter Targets": "None",
"Horizontal trigger position": "0",
"Operation Mode": "Buffer Mode",
"Sample count": "1048576",
"Sample rate": "1000000",
"Threshold Level": 1,
"Trigger hold off": "0",
"Trigger slope": "0",
"Trigger source": "0",
"Using Clock Negedge": 0,
"Using External Clock": 0,
"channel": [
{
"colour": "#6a6a6a",
"enabled": true,
"index": 0,
"name": "0",
"strigger": 0,
"type": 10000
},
{
"colour": "#6a6a6a",
"enabled": true,
"index": 1,
"name": "1",
"strigger": 0,
"type": 10000
},
{
"colour": "#6a6a6a",
"enabled": true,
"index": 2,
"name": "2",
"strigger": 0,
"type": 10000
},
{
"colour": "#6a6a6a",
"enabled": true,
"index": 3,
"name": "3",
"strigger": 0,
"type": 10000
},
{
"colour": "#6a6a6a",
"enabled": true,
"index": 4,
"name": "4",
"strigger": 0,
"type": 10000
},
{
"colour": "#6a6a6a",
"enabled": true,
"index": 5,
"name": "5",
"strigger": 0,
"type": 10000
},
{
"colour": "#6a6a6a",
"enabled": true,
"index": 6,
"name": "6",
"strigger": 0,
"type": 10000
},
{
"colour": "#6a6a6a",
"enabled": true,
"index": 7,
"name": "7",
"strigger": 0,
"type": 10000
},
{
"colour": "#6a6a6a",
"enabled": true,
"index": 8,
"name": "8",
"strigger": 0,
"type": 10000
},
{
"colour": "#6a6a6a",
"enabled": true,
"index": 9,
"name": "9",
"strigger": 0,
"type": 10000
},
{
"colour": "#6a6a6a",
"enabled": true,
"index": 10,
"name": "10",
"strigger": 0,
"type": 10000
},
{
"colour": "#6a6a6a",
"enabled": true,
"index": 11,
"name": "11",
"strigger": 0,
"type": 10000
},
{
"colour": "#6a6a6a",
"enabled": true,
"index": 12,
"name": "12",
"strigger": 0,
"type": 10000
},
{
"colour": "#6a6a6a",
"enabled": true,
"index": 13,
"name": "13",
"strigger": 0,
"type": 10000
},
{
"colour": "#6a6a6a",
"enabled": true,
"index": 14,
"name": "14",
"strigger": 0,
"type": 10000
},
{
"colour": "#6a6a6a",
"enabled": true,
"index": 15,
"name": "15",
"strigger": 0,
"type": 10000
}
],
"trigger": {
"triggerChannel": 0,
"triggerClock": "X X X X X X X X X X X X X X X X",
"triggerCount00": 1,
"triggerCount01": 1,
"triggerCount010": 1,
"triggerCount011": 1,
"triggerCount012": 1,
"triggerCount013": 1,
"triggerCount014": 1,
"triggerCount015": 1,
"triggerCount02": 1,
"triggerCount03": 1,
"triggerCount04": 1,
"triggerCount05": 1,
"triggerCount06": 1,
"triggerCount07": 1,
"triggerCount08": 1,
"triggerCount09": 1,
"triggerCount10": 1,
"triggerCount11": 1,
"triggerCount110": 1,
"triggerCount111": 1,
"triggerCount112": 1,
"triggerCount113": 1,
"triggerCount114": 1,
"triggerCount115": 1,
"triggerCount12": 1,
"triggerCount13": 1,
"triggerCount14": 1,
"triggerCount15": 1,
"triggerCount16": 1,
"triggerCount17": 1,
"triggerCount18": 1,
"triggerCount19": 1,
"triggerData": "X X X X X X X X X X X X X X X X",
"triggerInv00": 0,
"triggerInv01": 0,
"triggerInv010": 0,
"triggerInv011": 0,
"triggerInv012": 0,
"triggerInv013": 0,
"triggerInv014": 0,
"triggerInv015": 0,
"triggerInv02": 0,
"triggerInv03": 0,
"triggerInv04": 0,
"triggerInv05": 0,
"triggerInv06": 0,
"triggerInv07": 0,
"triggerInv08": 0,
"triggerInv09": 0,
"triggerInv10": 0,
"triggerInv11": 0,
"triggerInv110": 0,
"triggerInv111": 0,
"triggerInv112": 0,
"triggerInv113": 0,
"triggerInv114": 0,
"triggerInv115": 0,
"triggerInv12": 0,
"triggerInv13": 0,
"triggerInv14": 0,
"triggerInv15": 0,
"triggerInv16": 0,
"triggerInv17": 0,
"triggerInv18": 0,
"triggerInv19": 0,
"triggerLogic0": 1,
"triggerLogic1": 1,
"triggerLogic10": 1,
"triggerLogic11": 1,
"triggerLogic12": 1,
"triggerLogic13": 1,
"triggerLogic14": 1,
"triggerLogic15": 1,
"triggerLogic2": 1,
"triggerLogic3": 1,
"triggerLogic4": 1,
"triggerLogic5": 1,
"triggerLogic6": 1,
"triggerLogic7": 1,
"triggerLogic8": 1,
"triggerLogic9": 1,
"triggerMode": 0,
"triggerPos": 1,
"triggerSerial": 0,
"triggerStages": 0,
"triggerStart": "X X X X X X X X X X X X X X X X",
"triggerStop": "X X X X X X X X X X X X X X X X",
"triggerValue00": "X X X X X X X X X X X X X X X X",
"triggerValue01": "X X X X X X X X X X X X X X X X",
"triggerValue010": "X X X X X X X X X X X X X X X X",
"triggerValue011": "X X X X X X X X X X X X X X X X",
"triggerValue012": "X X X X X X X X X X X X X X X X",
"triggerValue013": "X X X X X X X X X X X X X X X X",
"triggerValue014": "X X X X X X X X X X X X X X X X",
"triggerValue015": "X X X X X X X X X X X X X X X X",
"triggerValue02": "X X X X X X X X X X X X X X X X",
"triggerValue03": "X X X X X X X X X X X X X X X X",
"triggerValue04": "X X X X X X X X X X X X X X X X",
"triggerValue05": "X X X X X X X X X X X X X X X X",
"triggerValue06": "X X X X X X X X X X X X X X X X",
"triggerValue07": "X X X X X X X X X X X X X X X X",
"triggerValue08": "X X X X X X X X X X X X X X X X",
"triggerValue09": "X X X X X X X X X X X X X X X X",
"triggerValue10": "X X X X X X X X X X X X X X X X",
"triggerValue11": "X X X X X X X X X X X X X X X X",
"triggerValue110": "X X X X X X X X X X X X X X X X",
"triggerValue111": "X X X X X X X X X X X X X X X X",
"triggerValue112": "X X X X X X X X X X X X X X X X",
"triggerValue113": "X X X X X X X X X X X X X X X X",
"triggerValue114": "X X X X X X X X X X X X X X X X",
"triggerValue115": "X X X X X X X X X X X X X X X X",
"triggerValue12": "X X X X X X X X X X X X X X X X",
"triggerValue13": "X X X X X X X X X X X X X X X X",
"triggerValue14": "X X X X X X X X X X X X X X X X",
"triggerValue15": "X X X X X X X X X X X X X X X X",
"triggerValue16": "X X X X X X X X X X X X X X X X",
"triggerValue17": "X X X X X X X X X X X X X X X X",
"triggerValue18": "X X X X X X X X X X X X X X X X",
"triggerValue19": "X X X X X X X X X X X X X X X X",
"triggerVcnt": 1
}
}

View File

@ -1,268 +0,0 @@
{
"Device": "DSLogic",
"DeviceMode": 0,
"Filter Targets": "None",
"Horizontal trigger position": "0",
"Operation Mode": "Normal",
"Sample count": "16777216",
"Sample rate": "100000000",
"Threshold Level": 1,
"Trigger hold off": "0",
"Trigger slope": "0",
"Trigger source": "0",
"Using Clock Negedge": 0,
"Using External Clock": 0,
"channel": [
{
"colour": "#16191a",
"enabled": true,
"index": 0,
"name": "0",
"strigger": 0,
"type": 10000
},
{
"colour": "#8f5202",
"enabled": true,
"index": 1,
"name": "1",
"strigger": 0,
"type": 10000
},
{
"colour": "#cc0000",
"enabled": true,
"index": 2,
"name": "2",
"strigger": 0,
"type": 10000
},
{
"colour": "#f57900",
"enabled": true,
"index": 3,
"name": "3",
"strigger": 0,
"type": 10000
},
{
"colour": "#edd400",
"enabled": true,
"index": 4,
"name": "4",
"strigger": 0,
"type": 10000
},
{
"colour": "#73d216",
"enabled": true,
"index": 5,
"name": "5",
"strigger": 0,
"type": 10000
},
{
"colour": "#3465a4",
"enabled": true,
"index": 6,
"name": "6",
"strigger": 0,
"type": 10000
},
{
"colour": "#75507b",
"enabled": true,
"index": 7,
"name": "7",
"strigger": 0,
"type": 10000
},
{
"colour": "#16191a",
"enabled": true,
"index": 8,
"name": "8",
"strigger": 0,
"type": 10000
},
{
"colour": "#8f5202",
"enabled": true,
"index": 9,
"name": "9",
"strigger": 0,
"type": 10000
},
{
"colour": "#cc0000",
"enabled": true,
"index": 10,
"name": "10",
"strigger": 0,
"type": 10000
},
{
"colour": "#f57900",
"enabled": true,
"index": 11,
"name": "11",
"strigger": 0,
"type": 10000
},
{
"colour": "#edd400",
"enabled": true,
"index": 12,
"name": "12",
"strigger": 0,
"type": 10000
},
{
"colour": "#73d216",
"enabled": true,
"index": 13,
"name": "13",
"strigger": 0,
"type": 10000
},
{
"colour": "#3465a4",
"enabled": true,
"index": 14,
"name": "14",
"strigger": 0,
"type": 10000
},
{
"colour": "#75507b",
"enabled": true,
"index": 15,
"name": "15",
"strigger": 0,
"type": 10000
}
],
"trigger": {
"triggerChannel": 0,
"triggerClock": "X X X X X X X X X X X X X X X X",
"triggerCount00": 1,
"triggerCount01": 1,
"triggerCount010": 1,
"triggerCount011": 1,
"triggerCount012": 1,
"triggerCount013": 1,
"triggerCount014": 1,
"triggerCount015": 1,
"triggerCount02": 1,
"triggerCount03": 1,
"triggerCount04": 1,
"triggerCount05": 1,
"triggerCount06": 1,
"triggerCount07": 1,
"triggerCount08": 1,
"triggerCount09": 1,
"triggerCount10": 1,
"triggerCount11": 1,
"triggerCount110": 1,
"triggerCount111": 1,
"triggerCount112": 1,
"triggerCount113": 1,
"triggerCount114": 1,
"triggerCount115": 1,
"triggerCount12": 1,
"triggerCount13": 1,
"triggerCount14": 1,
"triggerCount15": 1,
"triggerCount16": 1,
"triggerCount17": 1,
"triggerCount18": 1,
"triggerCount19": 1,
"triggerData": "X X X X X X X X X X X X X X X X",
"triggerInv00": 0,
"triggerInv01": 0,
"triggerInv010": 0,
"triggerInv011": 0,
"triggerInv012": 0,
"triggerInv013": 0,
"triggerInv014": 0,
"triggerInv015": 0,
"triggerInv02": 0,
"triggerInv03": 0,
"triggerInv04": 0,
"triggerInv05": 0,
"triggerInv06": 0,
"triggerInv07": 0,
"triggerInv08": 0,
"triggerInv09": 0,
"triggerInv10": 0,
"triggerInv11": 0,
"triggerInv110": 0,
"triggerInv111": 0,
"triggerInv112": 0,
"triggerInv113": 0,
"triggerInv114": 0,
"triggerInv115": 0,
"triggerInv12": 0,
"triggerInv13": 0,
"triggerInv14": 0,
"triggerInv15": 0,
"triggerInv16": 0,
"triggerInv17": 0,
"triggerInv18": 0,
"triggerInv19": 0,
"triggerLogic0": 1,
"triggerLogic1": 1,
"triggerLogic10": 1,
"triggerLogic11": 1,
"triggerLogic12": 1,
"triggerLogic13": 1,
"triggerLogic14": 1,
"triggerLogic15": 1,
"triggerLogic2": 1,
"triggerLogic3": 1,
"triggerLogic4": 1,
"triggerLogic5": 1,
"triggerLogic6": 1,
"triggerLogic7": 1,
"triggerLogic8": 1,
"triggerLogic9": 1,
"triggerMode": 0,
"triggerPos": 0,
"triggerSerial": 0,
"triggerStages": 0,
"triggerStart": "X X X X X X X X X X X X X X X X",
"triggerStop": "X X X X X X X X X X X X X X X X",
"triggerValue00": "X X X X X X X X X X X X X X X X",
"triggerValue01": "X X X X X X X X X X X X X X X X",
"triggerValue010": "X X X X X X X X X X X X X X X X",
"triggerValue011": "X X X X X X X X X X X X X X X X",
"triggerValue012": "X X X X X X X X X X X X X X X X",
"triggerValue013": "X X X X X X X X X X X X X X X X",
"triggerValue014": "X X X X X X X X X X X X X X X X",
"triggerValue015": "X X X X X X X X X X X X X X X X",
"triggerValue02": "X X X X X X X X X X X X X X X X",
"triggerValue03": "X X X X X X X X X X X X X X X X",
"triggerValue04": "X X X X X X X X X X X X X X X X",
"triggerValue05": "X X X X X X X X X X X X X X X X",
"triggerValue06": "X X X X X X X X X X X X X X X X",
"triggerValue07": "X X X X X X X X X X X X X X X X",
"triggerValue08": "X X X X X X X X X X X X X X X X",
"triggerValue09": "X X X X X X X X X X X X X X X X",
"triggerValue10": "X X X X X X X X X X X X X X X X",
"triggerValue11": "X X X X X X X X X X X X X X X X",
"triggerValue110": "X X X X X X X X X X X X X X X X",
"triggerValue111": "X X X X X X X X X X X X X X X X",
"triggerValue112": "X X X X X X X X X X X X X X X X",
"triggerValue113": "X X X X X X X X X X X X X X X X",
"triggerValue114": "X X X X X X X X X X X X X X X X",
"triggerValue115": "X X X X X X X X X X X X X X X X",
"triggerValue12": "X X X X X X X X X X X X X X X X",
"triggerValue13": "X X X X X X X X X X X X X X X X",
"triggerValue14": "X X X X X X X X X X X X X X X X",
"triggerValue15": "X X X X X X X X X X X X X X X X",
"triggerValue16": "X X X X X X X X X X X X X X X X",
"triggerValue17": "X X X X X X X X X X X X X X X X",
"triggerValue18": "X X X X X X X X X X X X X X X X",
"triggerValue19": "X X X X X X X X X X X X X X X X"
}
}

10
DSView/res/DSLogic1.def.dsc Normal file → Executable file
View File

@ -1,13 +1,15 @@
{
{
"Channel Mode": "Use Channels 0~15 (Max 100MHz)",
"Device": "DSLogic",
"DeviceMode": 1,
"Filter Targets": "None",
"Horizontal trigger position": "0",
"Operation Mode": "Normal",
"Horizontal trigger position": "1",
"Operation Mode": "Buffer Mode",
"Sample count": "1048576",
"Sample rate": "100000000",
"Threshold Level": "1.8/2.5/3.3V Level",
"Trigger hold off": "0",
"Trigger margin": "8",
"Trigger slope": "0",
"Trigger source": "0",
"Using Clock Negedge": 0,
@ -19,7 +21,6 @@
"enabled": true,
"index": 0,
"name": "0",
"strigger": 0,
"trigValue": 0.5,
"type": 10001,
"vdiv": 1000,
@ -32,7 +33,6 @@
"enabled": true,
"index": 1,
"name": "1",
"strigger": 0,
"trigValue": 0.5,
"type": 10001,
"vdiv": 1000,

View File

@ -1,43 +0,0 @@
{
"Device": "DSLogic",
"DeviceMode": 1,
"Filter Targets": "None",
"Horizontal trigger position": "0",
"Operation Mode": "Normal",
"Sample count": "1048576",
"Sample rate": "100000000",
"Threshold Level": "1.8/2.5/3.3V Level",
"Trigger hold off": "0",
"Trigger slope": "0",
"Trigger source": "0",
"Using Clock Negedge": 0,
"Using External Clock": 0,
"channel": [
{
"colour": "#eeb211",
"coupling": 0,
"enabled": true,
"index": 0,
"name": "0",
"strigger": 0,
"trigValue": 0.5,
"type": 10001,
"vdiv": 1000,
"vfactor": 1,
"zeroPos": 0.5
},
{
"colour": "#009925",
"coupling": 0,
"enabled": true,
"index": 1,
"name": "1",
"strigger": 0,
"trigValue": 0.5,
"type": 10001,
"vdiv": 1000,
"vfactor": 1,
"zeroPos": 0.5
}
]
}

18
DSView/res/DSLogic2.def.dsc Normal file → Executable file
View File

@ -1,10 +1,11 @@
{
{
"Channel Mode": "Use Channels 0~15 (Max 100MHz)",
"Device": "DSLogic",
"DeviceMode": 2,
"Filter Targets": "None",
"Horizontal trigger position": "0",
"Operation Mode": "Normal",
"Sample count": "16777216",
"Horizontal trigger position": "245",
"Operation Mode": "Buffer Mode",
"Sample count": "1048576",
"Sample rate": "100000000",
"Threshold Level": "1.8/2.5/3.3V Level",
"Trigger hold off": "0",
@ -18,7 +19,6 @@
"enabled": true,
"index": 0,
"name": "0",
"strigger": 0,
"type": 10002
},
{
@ -26,7 +26,6 @@
"enabled": true,
"index": 1,
"name": "1",
"strigger": 0,
"type": 10002
},
{
@ -34,7 +33,6 @@
"enabled": true,
"index": 2,
"name": "2",
"strigger": 0,
"type": 10002
},
{
@ -42,7 +40,6 @@
"enabled": true,
"index": 3,
"name": "3",
"strigger": 0,
"type": 10002
},
{
@ -50,7 +47,6 @@
"enabled": true,
"index": 4,
"name": "4",
"strigger": 0,
"type": 10002
},
{
@ -58,7 +54,6 @@
"enabled": true,
"index": 5,
"name": "5",
"strigger": 0,
"type": 10002
},
{
@ -66,7 +61,6 @@
"enabled": true,
"index": 6,
"name": "6",
"strigger": 0,
"type": 10002
},
{
@ -74,7 +68,6 @@
"enabled": true,
"index": 7,
"name": "7",
"strigger": 0,
"type": 10002
},
{
@ -82,7 +75,6 @@
"enabled": true,
"index": 8,
"name": "8",
"strigger": 0,
"type": 10002
}
]

View File

@ -1,89 +0,0 @@
{
"Device": "DSLogic",
"DeviceMode": 2,
"Filter Targets": "None",
"Horizontal trigger position": "0",
"Operation Mode": "Normal",
"Sample count": "16777216",
"Sample rate": "100000000",
"Threshold Level": "1.8/2.5/3.3V Level",
"Trigger hold off": "0",
"Trigger slope": "0",
"Trigger source": "0",
"Using Clock Negedge": 0,
"Using External Clock": 0,
"channel": [
{
"colour": "#1185d1",
"enabled": true,
"index": 0,
"name": "0",
"strigger": 0,
"type": 10002
},
{
"colour": "#eeb211",
"enabled": true,
"index": 1,
"name": "1",
"strigger": 0,
"type": 10002
},
{
"colour": "#d50f25",
"enabled": true,
"index": 2,
"name": "2",
"strigger": 0,
"type": 10002
},
{
"colour": "#009925",
"enabled": true,
"index": 3,
"name": "3",
"strigger": 0,
"type": 10002
},
{
"colour": "#1185d1",
"enabled": true,
"index": 4,
"name": "4",
"strigger": 0,
"type": 10002
},
{
"colour": "#eeb211",
"enabled": true,
"index": 5,
"name": "5",
"strigger": 0,
"type": 10002
},
{
"colour": "#d50f25",
"enabled": true,
"index": 6,
"name": "6",
"strigger": 0,
"type": 10002
},
{
"colour": "#009925",
"enabled": true,
"index": 7,
"name": "7",
"strigger": 0,
"type": 10002
},
{
"colour": "#1185d1",
"enabled": true,
"index": 8,
"name": "8",
"strigger": 0,
"type": 10002
}
]
}

BIN
DSView/res/DSLogic33.bin Normal file → Executable file

Binary file not shown.

BIN
DSView/res/DSLogic50.bin Normal file → Executable file

Binary file not shown.

BIN
DSView/res/DSLogicPro.bin Normal file → Executable file

Binary file not shown.

BIN
DSView/res/DSLogicPro.fw Normal file → Executable file

Binary file not shown.

10
INSTALL
View File

@ -25,6 +25,7 @@ Requirements
- pkg-config >= 0.22
This is part of the standard OpenBSD install (not an extra package), apparently.
- check >= 0.9.4 (optional, only needed to run unit tests)
- libfftw3 >= 3.3
Building and installing
-----------------------
@ -35,17 +36,17 @@ please check your respective distro's package manager tool if you use other dist
Debian/Ubuntu:
$ sudo apt-get install git-core gcc g++ make cmake autoconf automake libtool pkg-config \
libglib2.0-dev libzip-dev libudev-dev libusb-1.0-0-dev \
python3-dev qt5-default libboost-dev libboost-test-dev libboost-thread-dev libboost-system-dev libboost-filesystem-dev check
python3-dev qt5-default libboost-dev libboost-test-dev libboost-thread-dev libboost-system-dev libboost-filesystem-dev check libfftw3-dev
Fedora (18, 19):
$ sudo yum install git gcc g++ make cmake autoconf automake libtool pkgconfig glib2-devel \
libzip-devel libudev-devel libusb1-devel \
python3-devel qt-devel boost-devel check
python3-devel qt-devel boost-devel check libfftw3-devel
Arch:
$ pacman -S git gcc make cmake autoconf autoconf-archive automake libtool \
pkg-config glib2 glibmm libzip libusb check
python boost qt5 qt5-base qt5-svg
python boost qt5 qt5-base qt5-svg libfftw3
Step2: Get the DSView source code
@ -60,8 +61,7 @@ Step3: Building
$ sudo make install
$ cd ..
$ git clone git://sigrok.org/libsigrokdecode
$ cd libsigrokdecode
$ cd libsigrokdecode4DSL
$ ./autogen.sh
$ ./configure
$ make

View File

@ -305,3 +305,22 @@ SR_PRIV int command_rd_nvm(libusb_device_handle *devhdl, unsigned char *ctx, uin
return SR_OK;
}
SR_PRIV int command_get_fpga_done(libusb_device_handle *devhdl,
uint8_t *fpga_done)
{
int ret;
ret = libusb_control_transfer(devhdl, LIBUSB_REQUEST_TYPE_VENDOR |
LIBUSB_ENDPOINT_IN, CMD_FPGA_DONE, 0x0000, 0x0000,
fpga_done, 1, 3000);
if (ret < 0) {
sr_err("Unable to get fpga done info: %s.",
libusb_error_name(ret));
return SR_ERR;
}
return SR_OK;
}

View File

@ -37,6 +37,7 @@
#define CMD_WR_NVM 0xb9
#define CMD_RD_NVM 0xba
#define CMD_RD_NVM_PRE 0xbb
#define CMD_FPGA_DONE 0xbc
#define CMD_START_FLAGS_MODE_POS 4
#define CMD_START_FLAGS_WIDE_POS 5
@ -165,4 +166,6 @@ SR_PRIV int command_wr_reg(libusb_device_handle *devhdl, uint8_t value, uint8_t
SR_PRIV int command_wr_nvm(libusb_device_handle *devhdl, unsigned char *ctx, uint8_t len);
SR_PRIV int command_rd_nvm(libusb_device_handle *devhdl, unsigned char *ctx, uint8_t addr, uint8_t len);
SR_PRIV int command_get_fpga_done(libusb_device_handle *devhdl,
uint8_t *fpga_done);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -121,6 +121,11 @@
#define CALI_VGAIN_RANGE 100
#define CALI_VOFF_RANGE (1024-DSCOPE20_DEFAULT_TRANS)
#define DSO_AUTOTRIG_THRESHOLD 16
#define TRIG_CHECKID 0xa500005a
#define DSO_PKTID 0xa500
struct DSL_profile {
uint16_t vid;
uint16_t pid;
@ -175,6 +180,17 @@ static const struct DSL_profile supported_DSCope[3] = {
{ 0, 0, 0, 0, 0, 0, 0, 0, 0 }
};
static const gboolean default_ms_en[DSO_MS_END - DSO_MS_BEGIN] = {
FALSE, /* DSO_MS_BEGIN */
TRUE, /* DSO_MS_FREQ */
FALSE, /* DSO_MS_PERD */
TRUE, /* DSO_MS_VMAX */
TRUE, /* DSO_MS_VMIN */
FALSE, /* DSO_MS_VRMS */
FALSE, /* DSO_MS_VMEA */
FALSE, /* DSO_MS_VP2P */
FALSE, /* DSO_MS_END */
};
enum {
DSL_ERROR = -1,
@ -184,6 +200,7 @@ enum {
DSL_TRIGGERED = 3,
DSL_DATA = 4,
DSL_STOP = 5,
DSL_FINISH = 6,
};
struct DSL_context {
@ -210,6 +227,7 @@ struct DSL_context {
uint16_t op_mode;
uint16_t ch_mode;
uint16_t samplerates_size;
uint16_t samplecounts_size;
uint16_t th_level;
double vth;
uint16_t filter;
@ -219,6 +237,7 @@ struct DSL_context {
uint16_t trigger_buffer[NUM_TRIGGER_STAGES];
uint64_t timebase;
uint8_t max_height;
uint8_t trigger_channel;
uint8_t trigger_slope;
uint8_t trigger_source;
uint8_t trigger_hrate;
@ -235,7 +254,6 @@ struct DSL_context {
uint8_t dso_bits;
int num_samples;
uint64_t sent_samples;
int submitted_transfers;
int empty_transfer_count;
@ -249,6 +267,7 @@ struct DSL_context {
int status;
gboolean mstatus_valid;
gboolean abort;
};
struct DSL_setting {

File diff suppressed because it is too large Load Diff

View File

@ -100,6 +100,7 @@ struct dev_context {
GIOChannel *channel;
uint64_t cur_samplerate;
uint64_t limit_samples;
uint64_t limit_samples_show;
uint64_t limit_msec;
uint8_t sample_generator;
uint64_t samples_counter;
@ -285,6 +286,18 @@ static const char *probe_names[NUM_PROBES + 1] = {
};
static const gboolean default_ms_en[DSO_MS_END - DSO_MS_BEGIN] = {
FALSE, /* DSO_MS_BEGIN */
TRUE, /* DSO_MS_FREQ */
FALSE, /* DSO_MS_PERD */
TRUE, /* DSO_MS_VMAX */
TRUE, /* DSO_MS_VMIN */
FALSE, /* DSO_MS_VRMS */
FALSE, /* DSO_MS_VMEA */
FALSE, /* DSO_MS_VP2P */
FALSE, /* DSO_MS_END */
};
/* Private, per-device-instance driver context. */
/* TODO: struct context as with the other drivers. */
@ -341,6 +354,7 @@ static GSList *hw_scan(GSList *options)
devc->sdi = sdi;
devc->cur_samplerate = SR_MHZ(1);
devc->limit_samples = SR_MB(1);
devc->limit_samples_show = devc->limit_samples;
devc->limit_msec = 0;
devc->sample_generator = PATTERN_SINE;
devc->timebase = 200;
@ -457,6 +471,20 @@ static int hw_cleanup(void)
return ret;
}
static int en_ch_num(const struct sr_dev_inst *sdi)
{
GSList *l;
int channel_en_cnt = 0;
for (l = sdi->channels; l; l = l->next) {
struct sr_channel *probe = (struct sr_channel *)l->data;
channel_en_cnt += probe->enabled;
}
channel_en_cnt += (channel_en_cnt == 0);
return channel_en_cnt;
}
static int config_get(int id, GVariant **data, const struct sr_dev_inst *sdi,
const struct sr_channel *ch,
const struct sr_channel_group *cg)
@ -470,7 +498,7 @@ static int config_get(int id, GVariant **data, const struct sr_dev_inst *sdi,
*data = g_variant_new_uint64(devc->cur_samplerate);
break;
case SR_CONF_LIMIT_SAMPLES:
*data = g_variant_new_uint64(devc->limit_samples);
*data = g_variant_new_uint64(devc->limit_samples_show);
break;
case SR_CONF_LIMIT_MSEC:
*data = g_variant_new_uint64(devc->limit_msec);
@ -546,7 +574,7 @@ static int config_set(int id, GVariant *data, struct sr_dev_inst *sdi,
struct sr_channel *ch,
const struct sr_channel_group *cg)
{
uint16_t i;
uint16_t i, j;
int ret;
const char *stropt;
struct sr_channel *probe;
@ -567,14 +595,19 @@ static int config_set(int id, GVariant *data, struct sr_dev_inst *sdi,
devc->cur_samplerate);
ret = SR_OK;
} else if (id == SR_CONF_LIMIT_SAMPLES) {
devc->limit_msec = 0;
devc->limit_samples = g_variant_get_uint64(data);
devc->limit_msec = 0;
devc->limit_samples = g_variant_get_uint64(data);
devc->limit_samples_show = devc->limit_samples;
if (sdi->mode == DSO && en_ch_num(sdi) == 1) {
devc->limit_samples /= 2;
}
sr_dbg("%s: setting limit_samples to %" PRIu64, __func__,
devc->limit_samples);
ret = SR_OK;
} else if (id == SR_CONF_LIMIT_MSEC) {
devc->limit_msec = g_variant_get_uint64(data);
devc->limit_samples = 0;
devc->limit_samples_show = devc->limit_samples;
sr_dbg("%s: setting limit_msec to %" PRIu64, __func__,
devc->limit_msec);
ret = SR_OK;
@ -590,6 +623,9 @@ static int config_set(int id, GVariant *data, struct sr_dev_inst *sdi,
else
sdi->channels = g_slist_append(sdi->channels, probe);
}
devc->cur_samplerate = SR_MHZ(1);
devc->limit_samples = SR_MB(1);
devc->limit_samples_show = devc->limit_samples;
} else if (sdi->mode == DSO) {
sr_dev_probes_free(sdi);
for (i = 0; i < DEMO_MAX_DSO_PROBES_NUM; i++) {
@ -603,10 +639,14 @@ static int config_set(int id, GVariant *data, struct sr_dev_inst *sdi,
probe->trig_value = 0x80;
probe->vpos = (probe->index == 0 ? 0.5 : -0.5)*probe->vdiv;
sdi->channels = g_slist_append(sdi->channels, probe);
probe->ms_show = TRUE;
for (j = DSO_MS_BEGIN; j < DSO_MS_END; j++)
probe->ms_en[j] = default_ms_en[j];
}
}
devc->cur_samplerate = DEMO_MAX_DSO_SAMPLERATE / DEMO_MAX_DSO_PROBES_NUM;
devc->limit_samples = DEMO_MAX_DSO_DEPTH / DEMO_MAX_DSO_PROBES_NUM;
devc->limit_samples_show = devc->limit_samples;
} else if (sdi->mode == ANALOG) {
sr_dev_probes_free(sdi);
for (i = 0; i < DS_MAX_ANALOG_PROBES_NUM; i++) {
@ -618,6 +658,7 @@ static int config_set(int id, GVariant *data, struct sr_dev_inst *sdi,
}
devc->cur_samplerate = SR_HZ(100);
devc->limit_samples = SR_KB(1);
devc->limit_samples_show = devc->limit_samples;
} else {
ret = SR_ERR;
}
@ -980,6 +1021,8 @@ static int receive_data(int fd, int revents, const struct sr_dev_inst *sdi)
dso.num_samples = sending_now;
else
dso.num_samples = devc->samples_counter;
if (en_ch_num(sdi) == 1)
dso.num_samples *= 2;
dso.mq = SR_MQ_VOLTAGE;
dso.unit = SR_UNIT_VOLT;
dso.mqflags = SR_MQFLAG_AC;
@ -997,8 +1040,7 @@ static int receive_data(int fd, int revents, const struct sr_dev_inst *sdi)
if (sdi->mode == DSO && !devc->instant) {
devc->pre_index += sending_now;
if (sdi->mode == DSO && !devc->instant &&
devc->pre_index >= devc->limit_samples)
if (devc->pre_index >= devc->limit_samples)
devc->pre_index = 0;
}
@ -1012,7 +1054,7 @@ static int receive_data(int fd, int revents, const struct sr_dev_inst *sdi)
}
}
if ((sdi->mode == LOGIC || devc->instant) && devc->limit_samples &&
if ((sdi->mode != DSO || devc->instant) && devc->limit_samples &&
devc->samples_counter >= devc->limit_samples) {
sr_info("Requested number of samples reached.");
hw_dev_acquisition_stop(sdi, NULL);

View File

@ -76,6 +76,8 @@ static struct sr_config_info sr_config_info_data[] = {
"Trigger slope", "Trigger slope", NULL},
{SR_CONF_TRIGGER_SOURCE, SR_T_UINT8, "triggersource",
"Trigger source", "Trigger source", NULL},
{SR_CONF_TRIGGER_CHANNEL, SR_T_UINT8, "triggerchannel",
"Trigger channel", "Trigger channel", NULL},
{SR_CONF_HORIZ_TRIGGERPOS, SR_T_UINT8, "horiz_triggerpos",
"Horizontal trigger position", "Horizontal trigger position", NULL},
{SR_CONF_TRIGGER_HOLDOFF, SR_T_UINT64, "triggerholdoff",

View File

@ -288,6 +288,18 @@ enum {
SR_MQFLAG_SPL_PCT_OVER_ALARM = 0x10000,
};
enum DSO_MEASURE_TYPE {
DSO_MS_BEGIN = 0,
DSO_MS_FREQ,
DSO_MS_PERD,
DSO_MS_VMAX,
DSO_MS_VMIN,
DSO_MS_VRMS,
DSO_MS_VMEA,
DSO_MS_VP2P,
DSO_MS_END,
};
struct sr_context;
struct sr_datafeed_packet {
@ -327,6 +339,8 @@ struct sr_datafeed_dso {
uint64_t mqflags;
/** samplerate different from last packet */
gboolean samplerate_tog;
/** trig flag */
gboolean trig_flag;
/** The analog value(s). The data is interleaved according to
* the probes list. */
void *data;
@ -575,6 +589,8 @@ struct sr_channel {
uint8_t trig_value;
int8_t comb_diff_top;
int8_t comb_diff_bom;
gboolean ms_show;
gboolean ms_en[DSO_MS_END - DSO_MS_BEGIN];
};
/** Structure for groups of channels that have common properties. */
@ -632,6 +648,9 @@ struct sr_status {
gboolean stream_mode;
uint32_t sample_divider;
gboolean sample_divider_tog;
gboolean trig_flag;
uint16_t pkt_id;
};
enum {
@ -718,6 +737,9 @@ enum {
/** Trigger source. */
SR_CONF_TRIGGER_SOURCE,
/** Trigger channel */
SR_CONF_TRIGGER_CHANNEL,
/** Trigger Value. */
SR_CONF_TRIGGER_VALUE,
@ -1099,10 +1121,11 @@ struct ds_trigger {
};
struct ds_trigger_pos {
uint32_t check_id;
uint32_t real_pos;
uint32_t ram_saddr;
uint32_t remain_cnt;
unsigned char first_block[500];
unsigned char first_block[496];
};
#include "proto.h"

Binary file not shown.

38
libsigrokdecode4DSL/.gitignore vendored Normal file
View File

@ -0,0 +1,38 @@
# autotools cruft
/INSTALL
/Makefile.in
/aclocal.m4
/autom4te.cache/
/autostuff/
/configure
/configure.lineno
/m4/libtool.m4
/m4/lt*.m4
# Editor/IDE cruft
*.kate-swp
*~
/*.kdev4
/Makefile.am.user
# Configure/build cruft
*.[ao]
*.l[ao]
.deps/
.dirstamp
.libs/
/ChangeLog
/Makefile
/config.*
/libsigrokdecode-*.tar.*
/libsigrokdecode.pc
/libtool
/version.h
__pycache__/
stamp-h?
# Files generated by the testsuite
/test-suite.log
/tests/*.log
/tests/*.trs
/tests/main

Binary file not shown.

View File

@ -0,0 +1,7 @@
-------------------------------------------------------------------------------
AUTHORS
-------------------------------------------------------------------------------
Please check the source code files and/or git history and/or ChangeLog for
a list of all authors and contributors.

674
libsigrokdecode4DSL/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>.

2318
libsigrokdecode4DSL/Doxyfile Normal file

File diff suppressed because it is too large Load Diff

200
libsigrokdecode4DSL/HACKING Normal file
View File

@ -0,0 +1,200 @@
-------------------------------------------------------------------------------
HACKING
-------------------------------------------------------------------------------
Coding style
------------
This project is programmed using the Linux kernel coding style, see
http://lxr.linux.no/linux/Documentation/CodingStyle for details.
Please use the same style for any code contributions, thanks!
The Python decoders should follow the usual Python conventions and use
Python idioms as far as it makes sense. The coding style should mostly follow
the Python PEP-8, which includes the convention of 4 spaces for indentation.
See http://www.python.org/dev/peps/pep-0008/ for details.
Contributions
-------------
- Patches should be sent to the development mailinglist at
sigrok-devel@lists.sourceforge.net (please subscribe to the list first).
https://lists.sourceforge.net/lists/listinfo/sigrok-devel
- Alternatively, you can also clone the git repository and let us know
from where to pull/review your changes. You can use gitorious.org,
github.com, or any other public git hosting site.
Random notes
------------
- Don't do variable declarations in compound statements, only at the
beginning of a function.
- Generally avoid assigning values to variables at declaration time,
especially so for complex and/or run-time dependent values.
- Consistently use g_*malloc() / g_*malloc0(). Do not use standard
malloc()/calloc() if it can be avoided (sometimes other libs such
as libftdi can return malloc()'d memory, for example).
- Always properly match allocations with the proper *free() functions. If
glib's g_*malloc()/g_*malloc0() was used, use g_free() to free the
memory. Otherwise use standard free(). Never use the wrong function!
- We assume that "small" memory allocations (< 1MB) will always succeed.
Thus, it's fine to use g_malloc() or g_malloc0() for allocations of
simple/small structs and such (instead of using g_try_malloc()), and
there's no need to check the return value.
Do use g_try_malloc() or g_try_malloc0() for large (>= 1MB) allocations
and check the return value.
- You should never print any messages (neither to stdout nor stderr nor
elsewhere) "manually" via e.g. printf() or g_log() or similar functions.
Only srd_err()/srd_warn()/srd_info()/srd_dbg()/srd_spew() should be used.
- Use glib's gboolean / TRUE / FALSE for boolean types consistently.
Do not use <stdbool.h> and its true / false, and do not invent private
definitions for this either.
- Consistently use the same naming convention for #include guards in headers:
<PROJECTNAME>_<PATH_TO_FILE>_<FILE>
This ensures that all #include guards are always unique and consistent.
Example: LIBSIGROKDECODE_LIBSIGROKDECODE_INTERNAL_H
- Consistently use the same naming convention for API functions:
<libprefix>_<groupname>_<action>().
Examples:
srd_log_loglevel_set(), srd_log_loglevel_get(), srd_log_handler_set(),
srd_log_handler_set_default(), and so on.
Getter/setter function names should usually end with "_get" or "_set".
Functions creating new "objects" should end with "_new".
Functions destroying "objects" should end with "_destroy".
Functions adding or removing items (e.g. from lists) should end with
either "_add" or "_remove".
Functions operating on all items from a list (not on only one of them),
should end with "_all", e.g. "_remove_all", "_get_all", and so on.
Use "_remove_all" in favor of "_clear" for consistency.
- All enums should generally use an explicit start number of 10000.
If there are multiple "categories" in the enum entries, each category
should be 10000 entries apart from the next one. The start of categories
are thus 10000, 20000, 30000, and so on.
Adding items to an enum MUST always append to a "category", never add
items in the middle of a category. The order of items MUST NOT be changed.
Any of the above would break the ABI.
The enum item 0 is special and is used as terminator in some lists, thus
enums should not use this for "valid" entries (and start at 10000 instead).
Doxygen
-------
- In Doxygen comments, put an empty line between the block of @param lines
and the final @return line. The @param lines themselves (if there is more
than one) are not separated by empty lines.
- Mark private functions (SRD_PRIV) with /** @private */, so that Doxygen
doesn't include them in the output. Functions that are "static" anyway
don't need to be marked like this.
- Mark private variables/#defines with /** @cond PRIVATE */ and
/** @endcond */, so that Doxygen doesn't include them in the output.
Variables that are "static" don't need to be marked like this.
- Mark all public API functions (SRD_API) with a @since tag which indicates
in which release the respective function was added (e.g. "@since 0.1.0").
If the function has existed before, but its API changed later, the @since
tag should mention only the release when the API last changed.
Example: The srd_foo() call was added in 0.1.0, but the API changed in
the later 0.2.0 release. The docs should read "@since 0.2.0" in that case.
Non-public functions (static ones, and those marked SRD_PRIV) don't need
to have @since markers.
The @since tag should be the last one, i.e. it should come after @param,
@return, @see, and so on.
Protocol decoder guidelines
---------------------------
- The 'desc' metadata field for a protocol decoder, which contains a
short, one-line description of the protocol/bus, should be at most 55
characters long, and end with a full stop. This short description can be
displayed on the command-line using "sigrok-cli -V -l 3", or in various
different places in GUIs.
- Longer, multi-line descriptions should be placed in the protocol
decoder's __init__.py file as docstring. It can be viewed (for a specific
protocol decoder, e.g., UART) via "sigrok-cli -a uart", or in various
other places in GUIs.
- Generally use strings for states (of the PD state machine), not integers.
This avoids having to keep a list of state definitions at the top of file.
The performance overhead for this is negligible in practice.
Recommended:
self.state = 'IDLE'
self.state = 'GET STOP BIT'
Not recommended:
self.state = IDLE
self.state = GET_STOP_BIT
(where IDLE = 0 and GET_STOP_BIT = 1, for example)
- Generally use strings for commands/IDs in generated protocol packets.
This avoids having to know magic numbers of the PD in higher-level PDs.
The performance overhead for this is negligible in practice.
Recommended:
self.put(x, y, p, ['STOPBIT', 0, 0])
self.put(x, y, p, ['ADDRESS READ', 0x51])
Not recommended:
self.put(x, y, p, [STOPBIT, 0, 0])
self.put(x, y, p, [ADDRESS_READ, 0x51])
(with STOPBIT = 3 and ADDRESS_READ = 7, for example)
- Use ALL-CAPS names for PD states and protocol packet commands/ID.
Words should be separated by spaces (not underscores or the like).
Recommended:
'FIND ADDRESS', 'GET TEMPERATURE', 'START'
Not recommended:
'FIND_ADDRESS', 'Get Temperature', 'start'
Testsuite
---------
You can run the libsigrokdecode testsuite using:
$ make check
Protocol decoder test framework
-------------------------------
Please see the sigrok-test repository for a protocol decoder test suite that
checks the decoded data of various PDs against known-good reference data.
Release engineering
-------------------
See
http://sigrok.org/wiki/Developers/Release_process
for a list of items that need to be done when releasing a new tarball.

View File

@ -0,0 +1,96 @@
##
## This file is part of the libsigrokdecode project.
##
## Copyright (C) 2010 Uwe Hermann <uwe@hermann-uwe.de>
##
## 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
##
ACLOCAL_AMFLAGS = -I m4
AM_LIBTOOLFLAGS = --silent
GNUMAKEFLAGS = --no-print-directory
DECODERS_DIR = $(pkgdatadir)/decoders
AM_CPPFLAGS = -DDECODERS_DIR='"$(DECODERS_DIR)"'
# The tests CFLAGS are a superset of the libsigrokdecode CFLAGS.
AM_CFLAGS = $(SRD_EXTRA_CFLAGS) $(SRD_WFLAGS) $(TESTS_CFLAGS)
lib_LTLIBRARIES = libsigrokdecode.la
libsigrokdecode_la_SOURCES = \
srd.c \
session.c \
decoder.c \
instance.c \
log.c \
util.c \
exception.c \
module_sigrokdecode.c \
type_decoder.c \
type_logic.c \
error.c \
version.c
libsigrokdecode_la_LIBADD = $(SRD_EXTRA_LIBS) $(LIBSIGROKDECODE_LIBS)
libsigrokdecode_la_LDFLAGS = -version-info $(SRD_LIB_VERSION) -no-undefined
pkginclude_HEADERS = libsigrokdecode.h
nodist_pkginclude_HEADERS = version.h
noinst_HEADERS = libsigrokdecode-internal.h
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libsigrokdecode.pc
EXTRA_DIST = Doxyfile HACKING contrib/sigrok-logo-notext.png
if HAVE_CHECK
TESTS = tests/main
check_PROGRAMS = ${TESTS}
endif
tests_main_SOURCES = \
libsigrokdecode.h \
tests/lib.h \
tests/main.c \
tests/core.c \
tests/decoder.c \
tests/inst.c \
tests/session.c
tests_main_CPPFLAGS = -DDECODERS_DIR='"$(abs_top_srcdir)/decoders"'
tests_main_LDADD = libsigrokdecode.la $(SRD_EXTRA_LIBS) $(TESTS_LIBS)
MAINTAINERCLEANFILES = ChangeLog
.PHONY: ChangeLog install-decoders
ChangeLog:
git --git-dir '$(top_srcdir)/.git' log >$@ || touch $@
dist-hook: ChangeLog
$(MKDIR_P) $(distdir)/tools
cp ${top_srcdir}/tools/install-decoders $(distdir)/tools
$(MKDIR_P) $(distdir)/decoders
${top_srcdir}/tools/install-decoders -i ${top_srcdir}/decoders \
-o $(distdir)/decoders
install-decoders:
$(MKDIR_P) $(DESTDIR)$(DECODERS_DIR)
$(PYTHON3) ${top_srcdir}/tools/install-decoders \
-i ${top_srcdir}/decoders -o $(DESTDIR)$(DECODERS_DIR)
install-data-hook: install-decoders

223
libsigrokdecode4DSL/NEWS Normal file
View File

@ -0,0 +1,223 @@
0.3.0 (2014-05-06)
------------------
Note: This release DOES change the libsigrokdecode public C API. This
means it is NOT backwards-compatible and frontends will need updates.
* New supported protocol decoders:
- guess_bitrate Guess the bitrate/baudrate of a signal
- ir_nec NEC infrared remote control protocol
- ir_rc5 RC-5 infrared remote control protocol
- midi Musical Instrument Digital Interface
- parallel Parallel synchronous bus decoder
- rgb_led_spi RGB LED string decoder (SPI)
- xfp 10 Gigabit Small Form Factor Pluggable Module
- z80 Zilog Z80 microprocessor disassembly
* Add support for annotation rows, i.e. groups of annotation classes that
are supposed to be displayed on the same GUI "row" together.
* Add support for the new OUTPUT_BINARY feature, which allows PDs to output
decoded data in various file formats (for loading and further processing
in other tools, or for direct live piping into other tools).
* Add support for the OUTPUT_META output type. This is used by PDs for
reporting various data points to the frontends, allowing them to perform
various post-processing and statistics tasks on them (e.g. simple counts,
average/mean values, min/max values, and so on).
* The OUTPUT_PROTO output type is now called OUTPUT_PYTHON.
* All protocol decoders:
- Bump the 'api_version' field of all decoders to 2. They are no longer
compatible (and cannot be used with) older libsigrokdecode versions.
- Updates to emit proper annotation classes, annotation sample numbers,
and annotation rows for GUI usage (bugs #146, #148, #150, #151, #154,
#155, #162, #147, #163, #168, #156, #309, and #344).
- Longer and shorter annotations are now supplied for GUI usage (frontends
can for example always show the longest annotation per zoom-level).
- Extensive protocol information has been moved from the PDs to the wiki.
Example: http://sigrok.org/wiki/Protocol_decoder:Uart
- Use correct I²C / I²S names in user-visible texts (not I2C/I2S).
* dcf77:
- Fix a bug in the handling of DCF77 bit 0.
- Drop handling of the 'PON' pin, this is not DCF77 related (bug #153).
- Fix the data parity check (bug #157).
* i2c:
- Fix corner case that can yield issues when using triggers on LAs.
- Drop unneeded 'addressing' option.
- Output bit-exact annotations and data for use by stacked PDs.
* i2s:
- Add OUTPUT_BINARY support for dumping the decoded data in WAV format.
* lpc:
- Various fixes to make the PD work better (or at all).
- Fix the handling of optional channels.
- Make the RESET# pin optional.
* onewire_link:
- Split 'reset' and 'presence' annotations.
* pan1321:
- Support the JSEC, JPRO, JAAC, and JSDA commands.
- Various internal fixes and improvements.
* parallel:
- Fix internal use of the obsolete 'metadata' parameter (bug #202).
* rtc8564:
- Properly handle register 0x06 (weekday) and the 'century' bit.
* sdcard_spi:
- Emit bit-exact annotations for the register fields that need them.
- Fix a Python issue with duplicate keys in a dict (bug #191).
* spi:
- Either MISO or MOSI can be optional now, but not both (bug #175).
- The CS# pin is optional now. If the pin is supplied, it is honored
(decoding only happens when the pin is asserted). Otherwise decoding will
use every CLK edge, regardless of CS# state or CS# existence (bug #152).
- Rename the 'SCK' pin to the more common 'CLK'.
- Output bit-exact annotations and data for use by stacked PDs.
- Fix a bug occurring when only MOSI (but not MISO) was supplied.
* transitioncounter:
- Drop the obsolete 'transitioncounter' dummy protocol decoder.
* uart:
- Fix corner case that can yield issues when using triggers on LAs.
- Use 'T' for stop bits and 'P' for parity bits (shortest annotations).
- Add a data format selection option.
- Annotations for RX and TX are now emitted in different annotation rows.
- Either the RX or TX signal can be optional now (but not both).
- Fix incorrectly displayed characters (bug #201).
- Add support for OUTPUT_BINARY output for RX, TX, or both.
- Output bit-exact annotations and data for use by stacked PDs.
* uart_dump:
- Drop the obsolete 'uart_dump' decoder (the feature is now included
in the 'uart' protocol decoder itself via OUTPUT_BINARY).
* usb_packet:
- The 'usb_protocol' decoder has been renamed to 'usb_packet'.
- Various bugfixes and decoding improvements.
* usb_signalling:
- Fix decoding of individual bits, sample in the middle of bits (bug #158).
* libsigrokdecode API changes overview:
- Add srd_session_new(), srd_session_destroy(), and a session context.
- Add srd_session_metadata_set().
- The name 'probe' has been renamed to 'channel' everywhere.
- The lib no longer defineѕ names with _t suffix (POSIX reserved).
- Drop the obsolete SRD_MAX_NUM_PROBES.
- Add the SRD_CONF_SAMPLERATE config key.
- Please see the Doxygen API documentation for further details.
* Protocol decoder API:
- Metadata is passed to PDs at runtime now (not at decoder start).
PDs now have a new optional metadata() method to receive it.
- Output types are now registered via Decoder.register(), not Decoder.add().
- The report() method is now obsolete. This kind of information will be
passed to the frontends via the OUTPUT_META output type, allowing the
frontends to perform various post-processing and statistics tasks.
- PDs can now define BINARY_OUTPUT types via the 'binary' tuple.
- PDs can now define annotation rows via the 'annotation_rows' tuple.
- PD options are now a tuple of dicts. Each option is a dict containing
the keys 'id', 'desc', 'def', and 'values'. Valid option types are
UTF-8 strings, integers, and floats (bugs #254, #306, #317, #165).
- Channels, optional channels, and annotations are now tuples (not lists).
- Only load PDs of API version 2, all other versions are incompatible.
* srd_inst_channel_set_all(): Report an error if not all channels required
by the respective protocol decoder have been supplied.
* Remove some internal limitations to max. 64 channels (bug #120).
* Add a unit test suite framework for libsigrokdecode ('make check').
* Add a protocol decoder test-suite framework for developers (tests/pdtest).
* Various bugfixes:
- srd_inst_option_set(): Properly return an error on exceptions.
- srd_inst_option_set(): Fix setting of instance options, caused by class
variable clobbering or releasing borrowed references (bugs #170, #174).
- srd_decoder_load(): Error out upon invalid module names (bug #176).
- srd_decoder_load(): Don't try to load an already loaded PD twice.
- srd_decoder_load_all(): Avoid issues without prior srd_init() (bug #178).
- srd_decoder_doc_get(): Fix an issue in the unit test suite (bug #179).
- srd_pd_output_callback_add(): Honor cb_data value (bug #143).
- Fix issues with PDs not getting the samplerate (bugs #97, #132, #166).
- Don't incorrectly decrease a borrowed reference (bug #177).
- Fix various memory leaks and segfault conditions.
* Build system:
- Use pkg-config (not python3-config) to check for Python libs.
This enables (better) libsigrokdecode cross-compile support.
- PDs no longer have an extra Makefile.am, and 'make install' now
happens via a Python script.
- configure: Clearly mark required and optional libs.
- Fix an issue with DESTDIR support (bug #215).
- Add the HACKING file to the tarball.
* Updated or new build-time and runtime requirements:
- Python >= 3.2 (required)
- check >= 0.9.4 (optional, only needed for the libsigrokdecode testsuite)
- libsigrok >= 0.3.0 (optional, only needed for the developer PD testsuite)
- python3-coverage (optional, only needed for the developer PD testsuite)
* New 'make install'-time requirement:
- Python >= 3.2 (required)
0.2.0 (2013-05-04)
------------------
Note: This release DOES change the libsigrokdecode public C API. This
means it is NOT backwards-compatible and frontends will need updates.
* New supported protocol decoders:
- Dallas DS1307 RTC
* Library: Decoders now expose their options via the GSList *options field
in struct srd_decoder.
* API related changes:
- Various API documentation fixes.
- srd_decoder_list() now returns 'const GSList *' instead of 'GSList *'.
- Added new srd_strerror() and srd_strerror_name() API calls.
* Added support for optional probes for PDs.
0.1.1 (2013-01-27)
------------------
Note: This release does NOT change the libsigrokdecode public C API. This
means existing libsigrokdecode frontends should not require any changes.
However, individual PDs and their output changed, which may require
some adaptations on the user's side in some cases.
* New supported protocol decoders:
- avr_isp AVR In-System Programming
- can Controller Area Network
- jtag Joint Test Action Group (IEEE 1149.1)
- jtag_stm32 Joint Test Action Group / ST STM32
- lm75 National LM75
- lpc Low-Pin-Count
- maxim_ds28ea00 Maxim DS28EA00 1-Wire digital thermometer
- onewire_link 1-Wire serial communication bus (link layer)
- onewire_network 1-Wire serial communication bus (network layer)
- sdcard_spi Secure Digital card (SPI mode)
- tlc5620 Texas Instruments TLC5620
- uart_dump UART dump
* i2cfilter: Now outputs 'i2c' packets instead of just data bytes, so
other PDs can stack on top of it. It filters by I2C slave address.
* edid: Now takes 'i2c' packets as input.
* pan1321:
- Various bugfixes to make the PD actually work.
- Now features 'Text (short)' and 'Text (verbose)' outputs.
* usb:
- The PD is split into 'usb_signalling' and 'usb_protocol' (stacked on top).
- Various bugfixes to make the PD work (better).
- The DP/DM probes were swapped, this is now fixed.
- Preliminary support for USB low-speed (in addition to full-speed).
* mlx90614: Minor bugfixes.
* dcf77:
- Major bugfix, this PD was not working correctly at all.
- Handle PON signal.
* nunchuk: Complete rewrite, works (better) now.
* spi: Update docs, send CS# change packets, change output API slightly.
If you have a PD which stacks on top of SPI, it'll need to be adapted.
The PDs that ship with libsigrokdecode are updated already.
* mx25lxx05d:
- Implement support for the READ, RDSR, and PP commands.
- Decode status register bits.
- Fix SE command handling.
- Fix inverted SRWD bit handling.
* Various smaller style and consistency changes in code and PD descriptions.
* Fix the build with Homebrew on Mac OS X.
* Performance improvements in some PDs.
* Documentation: Update website and git URLs.
* pkg-config file: Small fix to improve behaviour on Windows with cmake.
* All PD implementation files are now named 'pd.py' consistently.
* configure script:
- Also check for python3.3-config in addition to python-config and others.
- Add missing -fvisibility=hidden to default CFLAGS.
- Fix CFLAGS handling (configure.ac amends CFLAGS, doesn't overwrite now).
* The minimum required glib version is 2.24.0 now.
* We now ship a standard INSTALL file which documents the 'configure' options.
0.1.0 (2012-04-17)
------------------
* Initial release.

101
libsigrokdecode4DSL/README Normal file
View File

@ -0,0 +1,101 @@
-------------------------------------------------------------------------------
README
-------------------------------------------------------------------------------
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).
libsigrokdecode is a shared library written in C which provides the basic
API for running sigrok protocol decoders. The protocol decoders themselves
are written in Python.
Status
------
libsigrokdecode is in a usable state and has had official tarball releases.
While the API can change from release to release, this will always be
properly documented and reflected in the package version number and
in the shared library / libtool / .so-file version numbers.
However, there are _NO_ guarantees at all for stable APIs in git snapshots!
Distro packagers should only use released tarballs (no git snapshots).
Requirements
------------
- git (only needed when building from git)
- gcc (>= 4.0) or clang
- make
- autoconf >= 2.63 (only needed when building from git)
- automake >= 1.11 (only needed when building from git)
- libtool (only needed when building from git)
- pkg-config >= 0.22
- libglib >= 2.24.0
- Python >= 3.2
- check >= 0.9.4 (optional, only needed to run unit tests)
- doxygen (optional, only needed for the C API docs)
- graphviz (optional, only needed for the C API docs)
Building and installing
-----------------------
In order to get the libsigrokdecode source code and build it, run:
$ git clone git://sigrok.org/libsigrokdecode
$ cd libsigrokdecode
$ ./autogen.sh
$ ./configure
$ make
For installing libsigrokdecode:
$ make install
See INSTALL or the following wiki page for more (OS-specific) instructions:
http://sigrok.org/wiki/Building
Copyright and license
---------------------
libsigrokdecode is licensed under the terms of the GNU General Public License
(GPL), version 3 or later.
The protocol decoders (PDs) included in libsigrokdecode are an integral part
of the shared library (they are not merely external "plugins", they are not
external programs that libsigrokdecode calls via fork/exec, they cannot
function standalone without libsigrokdecode at all, the PDs and the rest of
the libsigrokdecode codebase share data structures and make function calls
to each other). Thus, since the PDs are part of the library, they are also
licensed under the terms of the GPLv3+.
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 library as a whole is licensed under the terms of the GPLv3+.
Please see the individual source files for the full list of copyright holders.
Mailing list
------------
https://lists.sourceforge.net/lists/listinfo/sigrok-devel
IRC
---
You can find the sigrok developers in the #sigrok IRC channel on Freenode.
Website
-------
http://sigrok.org/wiki/Libsigrokdecode

24
libsigrokdecode4DSL/autogen.sh Executable file
View File

@ -0,0 +1,24 @@
#!/bin/sh -e
##
## This file is part of the libsigrokdecode 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/>.
##
test -n "$srcdir" || srcdir=`dirname "$0"`
test -n "$srcdir" || srcdir=.
autoreconf --force --install --verbose "$srcdir"

View File

@ -0,0 +1,161 @@
##
## This file is part of the libsigrokdecode project.
##
## Copyright (C) 2010 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/>.
##
# We require at least autoconf 2.63 (AC_INIT format changed there).
AC_PREREQ([2.63])
# libsigrokdecode package version number (NOT the same as shared lib version!).
AC_INIT([libsigrokdecode], [0.4.0],
[sigrok-devel@lists.sourceforge.net], [libsigrokdecode],
[http://www.sigrok.org])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_AUX_DIR([autostuff])
AC_CONFIG_HEADERS([config.h version.h])
# We require at least automake 1.11 (needed for 'silent rules').
AM_INIT_AUTOMAKE([1.11 -Wall -Werror no-define subdir-objects check-news color-tests])
AM_SILENT_RULES([yes])
m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
AC_CANONICAL_HOST
# Checks for programs.
AC_PROG_CC
AC_PROG_INSTALL
AC_PROG_LN_S
# Required for per-target flags or subdir-objects with C sources.
AM_PROG_CC_C_O
# Set the standard the C library headers should conform to.
AH_VERBATIM([_POSIX_C_SOURCE], [/* The targeted POSIX standard. */
#ifndef _POSIX_C_SOURCE
# define _POSIX_C_SOURCE 200112L
#endif])
# Get compiler versions.
SR_PROG_VERSION([$CC], [srd_cc_version])
# Initialize libtool.
LT_INIT
# Set up the libsigrokdecode version defines.
SR_PKG_VERSION_SET([SRD_PACKAGE_VERSION], [AC_PACKAGE_VERSION])
# Library version for libsigrokdecode (NOT the same as the package version).
# Carefully read the libtool docs before updating these numbers!
# The algorithm for determining which number to change (and how) is nontrivial!
# http://www.gnu.org/software/libtool/manual/libtool.html#Updating-version-info
SR_LIB_VERSION_SET([SRD_LIB_VERSION], [2:0:0])
############################
## Package dependencies ##
############################
# Initialize pkg-config.
# We require at least 0.22, as "Requires.private" behaviour changed there.
PKG_PROG_PKG_CONFIG([0.22])
# Collect the pkg-config module names of all dependencies in SRD_PKGLIBS.
# These are used to derive the compiler flags and for the "Requires.private"
# field in the generated libsigrokdecode.pc file.
SRD_PKGLIBS=
SRD_PKGLIBS_TESTS=
# Keep track of all checked modules so we can list them at the end.
SR_PKG_CHECK_SUMMARY([srd_pkglibs_summary])
# Python 3 is always needed.
SR_PKG_CHECK([python3], [SRD_PKGLIBS],
[python3 >= 3.2], [python-3.4 >= 3.4], [python-3.3 >= 3.3], [python-3.2 >= 3.2])
AS_IF([test "x$sr_have_python3" = xno],
[AC_MSG_ERROR([Cannot find Python 3 development headers.])])
# We also need to find the name of the python3 executable (for 'make install').
# Some OSes call this python3, some call it python3.2, etc. etc.
AC_ARG_VAR([PYTHON3], [Python 3 interpreter])
AC_CHECK_PROGS([PYTHON3], [python3.4 python3.3 python3.2 python3])
AS_IF([test "x$PYTHON3" = x],
[AC_MSG_ERROR([Cannot find Python 3 interpreter.])])
######################
## Feature checks ##
######################
# Keep track of all checked modules so we can list them at the end.
SR_PKG_CHECK_SUMMARY([srd_pkglibs_opt_summary])
# The Check unit testing framework is optional. Disable if not found.
SR_PKG_CHECK([check], [SRD_PKGLIBS_TESTS], [check >= 0.9.4])
AM_CONDITIONAL([HAVE_CHECK], [test "x$sr_have_check" = xyes])
# Enable the C99 standard if possible, and enforce the use
# of SRD_API to explicitly mark all public API functions.
SRD_EXTRA_CFLAGS=
SR_CHECK_COMPILE_FLAGS([SRD_EXTRA_CFLAGS], [C99], [-std=c99 -c99 -AC99 -qlanglvl=extc99])
SR_CHECK_COMPILE_FLAGS([SRD_EXTRA_CFLAGS], [visibility], [-fvisibility=hidden])
# Select suitable compiler warning flags.
SR_ARG_ENABLE_WARNINGS([SRD_WFLAGS], [-Wall], [-Wall -Wextra -Wmissing-prototypes])
# Link against libm, this is required (among other things) by Python.
SRD_EXTRA_LIBS=
SR_SEARCH_LIBS([SRD_EXTRA_LIBS], [pow], [m])
AC_SYS_LARGEFILE
##############################
## Finalize configuration ##
##############################
AC_SUBST([SRD_PKGLIBS])
# Retrieve the compile and link flags for all modules combined.
# Also, bail out at this point if any module dependency is not met.
PKG_CHECK_MODULES([LIBSIGROKDECODE], [glib-2.0 >= 2.24.0 $SRD_PKGLIBS])
PKG_CHECK_MODULES([TESTS], [$SRD_PKGLIBS_TESTS glib-2.0 $SRD_PKGLIBS])
srd_glib_version=`$PKG_CONFIG --modversion glib-2.0 2>&AS_MESSAGE_LOG_FD`
AC_CONFIG_FILES([Makefile libsigrokdecode.pc])
AC_OUTPUT
cat >&AS_MESSAGE_FD <<_EOF
libsigrokdecode configuration summary:
- Package version................. $SRD_PACKAGE_VERSION
- Library ABI version............. $SRD_LIB_VERSION
- Prefix.......................... $prefix
- Building on..................... $build
- Building for.................... $host
Compile configuration:
- C compiler...................... $CC
- C compiler version.............. $srd_cc_version
- C compiler flags................ $CFLAGS
- Additional C compiler flags..... $SRD_EXTRA_CFLAGS
- C compiler warnings............. $SRD_WFLAGS
Detected libraries (required):
- glib-2.0 >= 2.24.0.............. $srd_glib_version
$srd_pkglibs_summary
Detected libraries (optional):
$srd_pkglibs_opt_summary
_EOF

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

View File

@ -0,0 +1,856 @@
/*
* This file is part of the libsigrokdecode project.
*
* Copyright (C) 2010 Uwe Hermann <uwe@hermann-uwe.de>
* Copyright (C) 2012 Bert Vermeulen <bert@biot.com>
* Copyright (C) 2016 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
* 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 "config.h"
#include "libsigrokdecode-internal.h" /* First, so we avoid a _POSIX_C_SOURCE warning. */
#include "libsigrokdecode.h"
#include <glib.h>
/**
* @file
*
* Listing, loading, unloading, and handling protocol decoders.
*/
/**
* @defgroup grp_decoder Protocol decoders
*
* Handling protocol decoders.
*
* @{
*/
/** @cond PRIVATE */
/* The list of protocol decoders. */
static GSList *pd_list = NULL;
/* srd.c */
extern SRD_PRIV GSList *searchpaths;
/* session.c */
extern SRD_PRIV GSList *sessions;
extern SRD_PRIV int max_session_id;
/* module_sigrokdecode.c */
extern SRD_PRIV PyObject *mod_sigrokdecode;
/** @endcond */
static gboolean srd_check_init(void)
{
if (max_session_id < 0) {
srd_err("Library is not initialized.");
return FALSE;
} else
return TRUE;
}
/**
* Returns the list of supported/loaded protocol decoders.
*
* This is a GSList of pointers to struct srd_decoder items.
*
* @return List of decoders, NULL if none are supported or loaded.
*
* @since 0.2.0
*/
SRD_API const GSList *srd_decoder_list(void)
{
return pd_list;
}
/**
* Get the decoder with the specified ID.
*
* @param id The ID string of the decoder to return.
*
* @return The decoder with the specified ID, or NULL if not found.
*
* @since 0.1.0
*/
SRD_API struct srd_decoder *srd_decoder_get_by_id(const char *id)
{
GSList *l;
struct srd_decoder *dec;
for (l = pd_list; l; l = l->next) {
dec = l->data;
if (!strcmp(dec->id, id))
return dec;
}
return NULL;
}
static int get_channels(const struct srd_decoder *d, const char *attr,
GSList **pdchl)
{
PyObject *py_channellist, *py_entry;
struct srd_channel *pdch;
int ret, num_channels, i;
if (!PyObject_HasAttrString(d->py_dec, attr))
/* No channels of this type specified. */
return SRD_OK;
py_channellist = PyObject_GetAttrString(d->py_dec, attr);
if (!PyTuple_Check(py_channellist)) {
srd_err("Protocol decoder %s %s attribute is not a tuple.",
d->name, attr);
return SRD_ERR_PYTHON;
}
if ((num_channels = PyTuple_Size(py_channellist)) == 0)
/* Empty channellist. */
return SRD_OK;
ret = SRD_OK;
for (i = 0; i < num_channels; i++) {
py_entry = PyTuple_GetItem(py_channellist, i);
if (!PyDict_Check(py_entry)) {
srd_err("Protocol decoder %s %s attribute is not "
"a list with dict elements.", d->name, attr);
ret = SRD_ERR_PYTHON;
break;
}
pdch = g_malloc(sizeof(struct srd_channel));
if ((py_dictitem_as_str(py_entry, "id", &pdch->id)) != SRD_OK) {
ret = SRD_ERR_PYTHON;
break;
}
if ((py_dictitem_as_str(py_entry, "name", &pdch->name)) != SRD_OK) {
ret = SRD_ERR_PYTHON;
break;
}
if ((py_dictitem_as_str(py_entry, "desc", &pdch->desc)) != SRD_OK) {
ret = SRD_ERR_PYTHON;
break;
}
pdch->order = i;
*pdchl = g_slist_append(*pdchl, pdch);
}
Py_DecRef(py_channellist);
return ret;
}
static int get_options(struct srd_decoder *d)
{
PyObject *py_opts, *py_opt, *py_val, *py_default, *py_item;
Py_ssize_t opt, i;
struct srd_decoder_option *o;
GVariant *gvar;
gint64 lval;
double dval;
int overflow;
char *sval;
if (!PyObject_HasAttrString(d->py_dec, "options"))
/* No options, that's fine. */
return SRD_OK;
/* If present, options must be a tuple. */
py_opts = PyObject_GetAttrString(d->py_dec, "options");
if (!PyTuple_Check(py_opts)) {
srd_err("Protocol decoder %s: options attribute is not "
"a tuple.", d->id);
return SRD_ERR_PYTHON;
}
for (opt = 0; opt < PyTuple_Size(py_opts); opt++) {
py_opt = PyTuple_GetItem(py_opts, opt);
if (!PyDict_Check(py_opt)) {
srd_err("Protocol decoder %s options: each option "
"must consist of a dictionary.", d->name);
return SRD_ERR_PYTHON;
}
if (!(py_val = PyDict_GetItemString(py_opt, "id"))) {
srd_err("Protocol decoder %s option %zd has no "
"id.", d->name, opt);
return SRD_ERR_PYTHON;
}
o = g_malloc0(sizeof(struct srd_decoder_option));
py_str_as_str(py_val, &o->id);
if ((py_val = PyDict_GetItemString(py_opt, "desc")))
py_str_as_str(py_val, &o->desc);
if ((py_default = PyDict_GetItemString(py_opt, "default"))) {
if (PyUnicode_Check(py_default)) {
/* UTF-8 string */
py_str_as_str(py_default, &sval);
o->def = g_variant_new_string(sval);
g_free(sval);
} else if (PyLong_Check(py_default)) {
/* Long */
lval = PyLong_AsLongAndOverflow(py_default, &overflow);
if (overflow) {
/* Value is < LONG_MIN or > LONG_MAX */
PyErr_Clear();
srd_err("Protocol decoder %s option 'default' has "
"invalid default value.", d->name);
return SRD_ERR_PYTHON;
}
o->def = g_variant_new_int64(lval);
} else if (PyFloat_Check(py_default)) {
/* Float */
if ((dval = PyFloat_AsDouble(py_default)) == -1.0) {
PyErr_Clear();
srd_err("Protocol decoder %s option 'default' has "
"invalid default value.", d->name);
return SRD_ERR_PYTHON;
}
o->def = g_variant_new_double(dval);
} else {
srd_err("Protocol decoder %s option 'default' has "
"value of unsupported type '%s'.", d->name,
Py_TYPE(py_default)->tp_name);
return SRD_ERR_PYTHON;
}
g_variant_ref_sink(o->def);
}
if ((py_val = PyDict_GetItemString(py_opt, "values"))) {
/* A default is required if a list of values is
* given, since it's used to verify their type. */
if (!o->def) {
srd_err("No default for option '%s'", o->id);
return SRD_ERR_PYTHON;
}
if (!PyTuple_Check(py_val)) {
srd_err("Option '%s' values should be a tuple.", o->id);
return SRD_ERR_PYTHON;
}
for (i = 0; i < PyTuple_Size(py_val); i++) {
py_item = PyTuple_GetItem(py_val, i);
if (Py_TYPE(py_default) != Py_TYPE(py_item)) {
srd_err("All values for option '%s' must be "
"of the same type as the default.",
o->id);
return SRD_ERR_PYTHON;
}
if (PyUnicode_Check(py_item)) {
/* UTF-8 string */
py_str_as_str(py_item, &sval);
gvar = g_variant_new_string(sval);
g_variant_ref_sink(gvar);
g_free(sval);
o->values = g_slist_append(o->values, gvar);
} else if (PyLong_Check(py_item)) {
/* Long */
lval = PyLong_AsLongAndOverflow(py_item, &overflow);
if (overflow) {
/* Value is < LONG_MIN or > LONG_MAX */
PyErr_Clear();
srd_err("Protocol decoder %s option 'values' "
"has invalid value.", d->name);
return SRD_ERR_PYTHON;
}
gvar = g_variant_new_int64(lval);
g_variant_ref_sink(gvar);
o->values = g_slist_append(o->values, gvar);
} else if (PyFloat_Check(py_item)) {
/* Float */
if ((dval = PyFloat_AsDouble(py_item)) == -1.0) {
PyErr_Clear();
srd_err("Protocol decoder %s option 'default' has "
"invalid default value.", d->name);
return SRD_ERR_PYTHON;
}
gvar = g_variant_new_double(dval);
g_variant_ref_sink(gvar);
o->values = g_slist_append(o->values, gvar);
}
}
}
d->options = g_slist_append(d->options, o);
}
return SRD_OK;
}
/**
* Load a protocol decoder module into the embedded Python interpreter.
*
* @param module_name The module name to be loaded.
*
* @return SRD_OK upon success, a (negative) error code otherwise.
*
* @since 0.1.0
*/
SRD_API int srd_decoder_load(const char *module_name)
{
PyObject *py_basedec, *py_method, *py_attr, *py_annlist, *py_ann;
PyObject *py_bin_classes, *py_bin_class, *py_ann_rows, *py_ann_row;
PyObject *py_ann_classes, *py_long;
struct srd_decoder *d;
int ret, i, j;
char **ann, **bin, *ann_row_id, *ann_row_desc;
struct srd_channel *pdch;
GSList *l, *ann_classes;
struct srd_decoder_annotation_row *ann_row;
int ann_type = 7;
int ann_len;
if (!srd_check_init())
return SRD_ERR;
if (!module_name)
return SRD_ERR_ARG;
if (PyDict_GetItemString(PyImport_GetModuleDict(), module_name)) {
/* Module was already imported. */
return SRD_OK;
}
srd_dbg("Loading protocol decoder '%s'.", module_name);
py_basedec = py_method = py_attr = NULL;
d = g_malloc0(sizeof(struct srd_decoder));
ret = SRD_ERR_PYTHON;
/* Import the Python module. */
if (!(d->py_mod = PyImport_ImportModule(module_name))) {
srd_exception_catch("Import of '%s' failed.", NULL, module_name);
goto err_out;
}
/* Get the 'Decoder' class as Python object. */
if (!(d->py_dec = PyObject_GetAttrString(d->py_mod, "Decoder"))) {
/* This generated an AttributeError exception. */
PyErr_Clear();
srd_err("Decoder class not found in protocol decoder %s.",
module_name);
goto err_out;
}
if (!(py_basedec = PyObject_GetAttrString(mod_sigrokdecode, "Decoder"))) {
srd_dbg("sigrokdecode module not loaded.");
goto err_out;
}
if (!PyObject_IsSubclass(d->py_dec, py_basedec)) {
srd_err("Decoder class in protocol decoder module %s is not "
"a subclass of sigrokdecode.Decoder.", module_name);
goto err_out;
}
Py_CLEAR(py_basedec);
/*
* Check that this decoder has the correct PD API version.
* PDs of different API versions are incompatible and cannot work.
*/
py_long = PyObject_GetAttrString(d->py_dec, "api_version");
if (PyLong_AsLong(py_long) != 2) {
srd_err("Only PDs of API version 2 are supported.");
goto err_out;
}
Py_CLEAR(py_long);
/* Check for a proper start() method. */
if (!PyObject_HasAttrString(d->py_dec, "start")) {
srd_err("Protocol decoder %s has no start() method Decoder "
"class.", module_name);
goto err_out;
}
py_method = PyObject_GetAttrString(d->py_dec, "start");
if (!PyFunction_Check(py_method)) {
srd_err("Protocol decoder %s Decoder class attribute 'start' "
"is not a method.", module_name);
goto err_out;
}
Py_CLEAR(py_method);
/* Check for a proper decode() method. */
if (!PyObject_HasAttrString(d->py_dec, "decode")) {
srd_err("Protocol decoder %s has no decode() method Decoder "
"class.", module_name);
goto err_out;
}
py_method = PyObject_GetAttrString(d->py_dec, "decode");
if (!PyFunction_Check(py_method)) {
srd_err("Protocol decoder %s Decoder class attribute 'decode' "
"is not a method.", module_name);
goto err_out;
}
Py_CLEAR(py_method);
/* Store required fields in newly allocated strings. */
if (py_attr_as_str(d->py_dec, "id", &(d->id)) != SRD_OK)
goto err_out;
if (py_attr_as_str(d->py_dec, "name", &(d->name)) != SRD_OK)
goto err_out;
if (py_attr_as_str(d->py_dec, "longname", &(d->longname)) != SRD_OK)
goto err_out;
if (py_attr_as_str(d->py_dec, "desc", &(d->desc)) != SRD_OK)
goto err_out;
if (py_attr_as_str(d->py_dec, "license", &(d->license)) != SRD_OK)
goto err_out;
/* All options and their default values. */
if (get_options(d) != SRD_OK)
goto err_out;
/* Check and import required channels. */
if (get_channels(d, "channels", &d->channels) != SRD_OK)
goto err_out;
/* Check and import optional channels. */
if (get_channels(d, "optional_channels", &d->opt_channels) != SRD_OK)
goto err_out;
/*
* Fix order numbers for the optional channels.
*
* Example:
* Required channels: r1, r2, r3. Optional: o1, o2, o3, o4.
* 'order' fields in the d->channels list = 0, 1, 2.
* 'order' fields in the d->opt_channels list = 3, 4, 5, 6.
*/
for (l = d->opt_channels; l; l = l->next) {
pdch = l->data;
pdch->order += g_slist_length(d->channels);
}
/* Convert annotation class attribute to GSList of char **. */
d->annotations = NULL;
if (PyObject_HasAttrString(d->py_dec, "annotations")) {
py_annlist = PyObject_GetAttrString(d->py_dec, "annotations");
if (!PyTuple_Check(py_annlist)) {
srd_err("Protocol decoder %s annotations should "
"be a tuple.", module_name);
goto err_out;
}
for (i = 0; i < PyTuple_Size(py_annlist); i++) {
py_ann = PyTuple_GetItem(py_annlist, i);
if (!PyTuple_Check(py_ann) || (PyTuple_Size(py_ann) != 3 && PyTuple_Size(py_ann) != 2)) {
srd_err("Protocol decoder %s annotation %d should "
"be a tuple with two elements.", module_name, i + 1);
goto err_out;
}
if (py_strseq_to_char(py_ann, &ann) != SRD_OK) {
goto err_out;
}
d->annotations = g_slist_append(d->annotations, ann);
if (PyTuple_Size(py_ann) == 3) {
ann_type = 0;
ann_len = strlen(ann[0]);
for (j = 0; j < ann_len; j++)
ann_type = ann_type * 10 + (ann[0][j] - '0');
d->ann_types = g_slist_append(d->ann_types, GINT_TO_POINTER(ann_type));
} else if (PyTuple_Size(py_ann) == 2) {
d->ann_types = g_slist_append(d->ann_types, GINT_TO_POINTER(ann_type));
ann_type++;
}
}
}
/* Convert annotation_rows to GSList of 'struct srd_decoder_annotation_row'. */
d->annotation_rows = NULL;
if (PyObject_HasAttrString(d->py_dec, "annotation_rows")) {
py_ann_rows = PyObject_GetAttrString(d->py_dec, "annotation_rows");
if (!PyTuple_Check(py_ann_rows)) {
srd_err("Protocol decoder %s annotation row list "
"must be a tuple.", module_name);
goto err_out;
}
for (i = 0; i < PyTuple_Size(py_ann_rows); i++) {
py_ann_row = PyTuple_GetItem(py_ann_rows, i);
if (!PyTuple_Check(py_ann_row)) {
srd_err("Protocol decoder %s annotation rows "
"must be tuples.", module_name);
goto err_out;
}
if (PyTuple_Size(py_ann_row) != 3
|| !PyUnicode_Check(PyTuple_GetItem(py_ann_row, 0))
|| !PyUnicode_Check(PyTuple_GetItem(py_ann_row, 1))
|| !PyTuple_Check(PyTuple_GetItem(py_ann_row, 2))) {
srd_err("Protocol decoder %s annotation rows "
"must contain tuples containing two "
"strings and a tuple.", module_name);
goto err_out;
}
if (py_str_as_str(PyTuple_GetItem(py_ann_row, 0), &ann_row_id) != SRD_OK)
goto err_out;
if (py_str_as_str(PyTuple_GetItem(py_ann_row, 1), &ann_row_desc) != SRD_OK)
goto err_out;
py_ann_classes = PyTuple_GetItem(py_ann_row, 2);
ann_classes = NULL;
for (j = 0; j < PyTuple_Size(py_ann_classes); j++) {
py_long = PyTuple_GetItem(py_ann_classes, j);
if (!PyLong_Check(py_long)) {
srd_err("Protocol decoder %s annotation row class "
"list must only contain numbers.", module_name);
goto err_out;
}
ann_classes = g_slist_append(ann_classes,
GINT_TO_POINTER(PyLong_AsLong(py_long)));
}
ann_row = g_malloc0(sizeof(struct srd_decoder_annotation_row));
ann_row->id = ann_row_id;
ann_row->desc = ann_row_desc;
ann_row->ann_classes = ann_classes;
d->annotation_rows = g_slist_append(d->annotation_rows, ann_row);
}
}
/* Convert binary class to GSList of char *. */
d->binary = NULL;
if (PyObject_HasAttrString(d->py_dec, "binary")) {
py_bin_classes = PyObject_GetAttrString(d->py_dec, "binary");
if (!PyTuple_Check(py_bin_classes)) {
srd_err("Protocol decoder %s binary classes should "
"be a tuple.", module_name);
goto err_out;
}
for (i = 0; i < PyTuple_Size(py_bin_classes); i++) {
py_bin_class = PyTuple_GetItem(py_bin_classes, i);
if (!PyTuple_Check(py_bin_class)) {
srd_err("Protocol decoder %s binary classes "
"should consist of tuples.", module_name);
goto err_out;
}
if (PyTuple_Size(py_bin_class) != 2
|| !PyUnicode_Check(PyTuple_GetItem(py_bin_class, 0))
|| !PyUnicode_Check(PyTuple_GetItem(py_bin_class, 1))) {
srd_err("Protocol decoder %s binary classes should "
"contain tuples with two strings.", module_name);
goto err_out;
}
if (py_strseq_to_char(py_bin_class, &bin) != SRD_OK) {
goto err_out;
}
d->binary = g_slist_append(d->binary, bin);
}
}
/* Append it to the list of supported/loaded decoders. */
pd_list = g_slist_append(pd_list, d);
ret = SRD_OK;
err_out:
if (ret != SRD_OK) {
Py_XDECREF(py_method);
Py_XDECREF(py_basedec);
Py_XDECREF(d->py_dec);
Py_XDECREF(d->py_mod);
g_free(d);
}
return ret;
}
/**
* Return a protocol decoder's docstring.
*
* @param dec The loaded protocol decoder.
*
* @return A newly allocated buffer containing the protocol decoder's
* documentation. The caller is responsible for free'ing the buffer.
*
* @since 0.1.0
*/
SRD_API char *srd_decoder_doc_get(const struct srd_decoder *dec)
{
PyObject *py_str;
char *doc;
if (!srd_check_init())
return NULL;
if (!dec)
return NULL;
if (!PyObject_HasAttrString(dec->py_mod, "__doc__"))
return NULL;
if (!(py_str = PyObject_GetAttrString(dec->py_mod, "__doc__"))) {
srd_exception_catch("", NULL);
return NULL;
}
doc = NULL;
if (py_str != Py_None)
py_str_as_str(py_str, &doc);
Py_DecRef(py_str);
return doc;
}
static void free_channels(GSList *channellist)
{
GSList *l;
struct srd_channel *pdch;
if (channellist == NULL)
return;
for (l = channellist; l; l = l->next) {
pdch = l->data;
g_free(pdch->id);
g_free(pdch->name);
g_free(pdch->desc);
g_free(pdch);
}
g_slist_free(channellist);
}
/**
* Unload the specified protocol decoder.
*
* @param dec The struct srd_decoder to be unloaded.
*
* @return SRD_OK upon success, a (negative) error code otherwise.
*
* @since 0.1.0
*/
SRD_API int srd_decoder_unload(struct srd_decoder *dec)
{
struct srd_decoder_option *o;
struct srd_decoder_annotation_row *row;
struct srd_session *sess;
GSList *l;
if (!srd_check_init())
return SRD_ERR;
if (!dec)
return SRD_ERR_ARG;
srd_dbg("Unloading protocol decoder '%s'.", dec->name);
/*
* Since any instances of this decoder need to be released as well,
* but they could be anywhere in the stack, just free the entire
* stack. A frontend reloading a decoder thus has to restart all
* instances, and rebuild the stack.
*/
for (l = sessions; l; l = l->next) {
sess = l->data;
srd_inst_free_all(sess, NULL);
}
for (l = dec->options; l; l = l->next) {
o = l->data;
g_free(o->id);
g_free(o->desc);
g_variant_unref(o->def);
g_free(o);
}
g_slist_free(dec->options);
g_slist_foreach(dec->annotations, (GFunc)g_free, NULL);
g_slist_free(dec->annotations);
for (l = dec->annotation_rows; l; l = l->next) {
row = l->data;
g_free(row->id);
g_free(row->desc);
g_slist_free(row->ann_classes);
g_free(row);
}
g_slist_free(dec->annotation_rows);
g_slist_foreach(dec->binary, (GFunc)g_free, NULL);
g_slist_free(dec->binary);
free_channels(dec->channels);
free_channels(dec->opt_channels);
g_free(dec->id);
g_free(dec->name);
g_free(dec->longname);
g_free(dec->desc);
g_free(dec->license);
/* The module's Decoder class. */
Py_XDECREF(dec->py_dec);
/* The module itself. */
Py_XDECREF(dec->py_mod);
g_free(dec);
return SRD_OK;
}
static void srd_decoder_load_all_zip_path(char *path)
{
PyObject *zipimport_mod, *zipimporter_class, *zipimporter;
PyObject *prefix_obj, *files, *key, *value, *set, *modname;
Py_ssize_t pos = 0;
char *prefix;
size_t prefix_len;
set = files = prefix_obj = zipimporter = zipimporter_class = NULL;
zipimport_mod = PyImport_ImportModule("zipimport");
if (zipimport_mod == NULL)
goto err_out;
zipimporter_class = PyObject_GetAttrString(zipimport_mod, "zipimporter");
if (zipimporter_class == NULL)
goto err_out;
zipimporter = PyObject_CallFunction(zipimporter_class, "s", path);
if (zipimporter == NULL)
goto err_out;
prefix_obj = PyObject_GetAttrString(zipimporter, "prefix");
if (prefix_obj == NULL)
goto err_out;
files = PyObject_GetAttrString(zipimporter, "_files");
if (files == NULL)
goto err_out;
set = PySet_New(NULL);
if (set == NULL)
goto err_out;
if (py_str_as_str(prefix_obj, &prefix) != SRD_OK)
goto err_out;
prefix_len = strlen(prefix);
while (PyDict_Next(files, &pos, &key, &value)) {
char *path, *slash;
if (py_str_as_str(key, &path) == SRD_OK) {
if (strlen(path) > prefix_len &&
!memcmp(path, prefix, prefix_len) &&
(slash = strchr(path+prefix_len, '/'))) {
modname =
PyUnicode_FromStringAndSize(path+prefix_len,
slash-(path+prefix_len));
if (modname == NULL) {
PyErr_Clear();
} else {
PySet_Add(set, modname);
Py_XDECREF(modname);
}
}
free(path);
}
}
free(prefix);
while ((modname = PySet_Pop(set))) {
char *modname_str;
if (py_str_as_str(modname, &modname_str) == SRD_OK) {
/* The directory name is the module name (e.g. "i2c"). */
srd_decoder_load(modname_str);
free(modname_str);
}
Py_XDECREF(modname);
}
err_out:
Py_XDECREF(set);
Py_XDECREF(files);
Py_XDECREF(prefix_obj);
Py_XDECREF(zipimporter);
Py_XDECREF(zipimporter_class);
Py_XDECREF(zipimport_mod);
PyErr_Clear();
}
static void srd_decoder_load_all_path(char *path)
{
GDir *dir;
const gchar *direntry;
if (!(dir = g_dir_open(path, 0, NULL))) {
/* Not really fatal */
/* Try zipimport method too */
srd_decoder_load_all_zip_path(path);
return;
}
/* This ignores errors returned by srd_decoder_load(). That
* function will have logged the cause, but in any case we
* want to continue anyway. */
while ((direntry = g_dir_read_name(dir)) != NULL) {
/* The directory name is the module name (e.g. "i2c"). */
srd_decoder_load(direntry);
}
g_dir_close(dir);
}
/**
* Load all installed protocol decoders.
*
* @return SRD_OK upon success, a (negative) error code otherwise.
*
* @since 0.1.0
*/
SRD_API int srd_decoder_load_all(void)
{
GSList *l;
if (!srd_check_init())
return SRD_ERR;
for (l = searchpaths; l; l = l->next)
srd_decoder_load_all_path(l->data);
return SRD_OK;
}
/**
* Unload all loaded protocol decoders.
*
* @return SRD_OK upon success, a (negative) error code otherwise.
*
* @since 0.1.0
*/
SRD_API int srd_decoder_unload_all(void)
{
GSList *l;
struct srd_decoder *dec;
for (l = pd_list; l; l = l->next) {
dec = l->data;
srd_decoder_unload(dec);
}
g_slist_free(pd_list);
pd_list = NULL;
return SRD_OK;
}
/** @} */

View File

@ -0,0 +1,26 @@
##
## This file is part of the libsigrokdecode project.
##
## Copyright (C) 2012 Uwe Hermann <uwe@hermann-uwe.de>
##
## 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
##
'''
I²C (Inter-Integrated Circuit) is a bidirectional, multi-master
bus using two signals (SCL = serial clock line, SDA = serial data line).
'''
from .pd import Decoder

View File

@ -0,0 +1,343 @@
##
## This file is part of the libsigrokdecode project.
##
## Copyright (C) 2010-2014 Uwe Hermann <uwe@hermann-uwe.de>
## Copyright (C) 2016 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
## 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
##
# TODO: Look into arbitration, collision detection, clock synchronisation, etc.
# TODO: Implement support for 10bit slave addresses.
# TODO: Implement support for inverting SDA/SCL levels (0->1 and 1->0).
# TODO: Implement support for detecting various bus errors.
import sigrokdecode as srd
'''
OUTPUT_PYTHON format:
Packet:
[<ptype>, <pdata>]
<ptype>:
- 'START' (START condition)
- 'START REPEAT' (Repeated START condition)
- 'ADDRESS READ' (Slave address, read)
- 'ADDRESS WRITE' (Slave address, write)
- 'DATA READ' (Data, read)
- 'DATA WRITE' (Data, write)
- 'STOP' (STOP condition)
- 'ACK' (ACK bit)
- 'NACK' (NACK bit)
- 'BITS' (<pdata>: list of data/address bits and their ss/es numbers)
<pdata> is the data or address byte associated with the 'ADDRESS*' and 'DATA*'
command. Slave addresses do not include bit 0 (the READ/WRITE indication bit).
For example, a slave address field could be 0x51 (instead of 0xa2).
For 'START', 'START REPEAT', 'STOP', 'ACK', and 'NACK' <pdata> is None.
'''
# CMD: [annotation-type-index, long annotation, short annotation]
proto = {
'START': [0, 'Start', 'S'],
'START REPEAT': [1, 'Start repeat', 'Sr'],
'STOP': [2, 'Stop', 'P'],
'ACK': [3, 'ACK', 'A'],
'NACK': [4, 'NACK', 'N'],
'READ': [5, 'Read', 'R'],
'WRITE': [6, 'Write', 'W'],
'BIT': [7, 'Bit', 'B'],
'ADDRESS READ': [8, 'Address read', 'AR'],
'ADDRESS WRITE': [9, 'Address write', 'AW'],
'DATA READ': [10, 'Data read', 'DR'],
'DATA WRITE': [11, 'Data write', 'DW'],
}
class SamplerateError(Exception):
pass
class Decoder(srd.Decoder):
api_version = 2
id = '0:i2c'
name = '0:I²C'
longname = 'Inter-Integrated Circuit'
desc = 'Two-wire, multi-master, serial bus.'
license = 'gplv2+'
inputs = ['logic']
outputs = ['i2c']
channels = (
{'id': 'scl', 'name': 'SCL', 'desc': 'Serial clock line'},
{'id': 'sda', 'name': 'SDA', 'desc': 'Serial data line'},
)
options = (
{'id': 'address_format', 'desc': 'Displayed slave address format',
'default': 'shifted', 'values': ('shifted', 'unshifted')},
)
annotations = (
('7', 'start', 'Start condition'),
('6', 'repeat-start', 'Repeat start condition'),
('1', 'stop', 'Stop condition'),
('5', 'ack', 'ACK'),
('0', 'nack', 'NACK'),
('12', 'read', 'Read'),
('11', 'write', 'Write'),
('108', 'bit', 'Data/address bit'),
('112', 'address-read', 'Address read'),
('111', 'address-write', 'Address write'),
('110', 'data-read', 'Data read'),
('109', 'data-write', 'Data write'),
('1000', 'warnings', 'Human-readable warnings'),
)
annotation_rows = (
#('bits', 'Bits', (7,)),
('addr-data', 'Address/Data', (0, 1, 2, 3, 4, 5, 6, 8, 9, 10, 11)),
#('warnings', 'Warnings', (12,)),
)
binary = (
('address-read', 'Address read'),
('address-write', 'Address write'),
('data-read', 'Data read'),
('data-write', 'Data write'),
)
def __init__(self):
self.samplerate = None
self.ss = self.es = self.ss_byte = -1
self.samplenum = None
self.bitcount = 0
self.databyte = 0
self.wr = -1
self.is_repeat_start = 0
self.state = 'FIND START'
self.oldscl = self.oldsda = -1
self.pdu_start = None
#self.pdu_bits = 0
#self.bits = []
def metadata(self, key, value):
if key == srd.SRD_CONF_SAMPLERATE:
self.samplerate = value
def start(self):
self.out_python = self.register(srd.OUTPUT_PYTHON)
self.out_ann = self.register(srd.OUTPUT_ANN)
self.out_binary = self.register(srd.OUTPUT_BINARY)
self.out_bitrate = self.register(srd.OUTPUT_META,
meta=(int, 'Bitrate', 'Bitrate from Start bit to Stop bit'))
if not self.samplerate:
raise SamplerateError('Cannot decode without samplerate.')
def putx(self, data):
self.put(self.ss, self.es, self.out_ann, data)
#def putp(self, data):
# self.put(self.ss, self.es, self.out_python, data)
#def putb(self, data):
# self.put(self.ss, self.es, self.out_binary, data)
def found_start(self, scl, sda):
self.ss, self.es = self.samplenum, self.samplenum
self.pdu_start = self.samplenum
#self.pdu_bits = 0
cmd = 'START REPEAT' if (self.is_repeat_start == 1) else 'START'
#self.putp([cmd, None])
self.putx([proto[cmd][0], proto[cmd][1:]])
self.state = 'FIND ADDRESS'
self.bitcount = self.databyte = 0
self.is_repeat_start = 1
self.wr = -1
#self.bits = []
# Gather 7 bits of address, 1 bit of rd/wr, plus the ACK/NACK bit.
def found_address(self, scl, sda):
# Address and data are transmitted MSB-first.
self.databyte <<= 1
self.databyte |= sda
# Remember the start of the first data/address bit.
if self.bitcount == 0:
self.ss_byte = self.samplenum
if self.bitcount == 1:
self.bitwidth = self.samplenum - self.ss_byte
# Store individual bits and their start/end samplenumbers.
# In the list, index 0 represents the MSB (I²C transmits MSB-first).
#self.bits.append([sda, self.samplenum, self.samplenum])
#if self.bitcount > 0:
# self.bits[self.bitcount-1][2] = self.samplenum
#if self.bitcount == 7:
# self.bits[7][2] += self.bitwidth
# Return if we haven't collected all 8 + 1 bits, yet.
if self.bitcount < 7:
self.bitcount += 1
return
# The READ/WRITE bit is only in address bytes, not data bytes.
self.wr = 0 if (self.databyte & 1) else 1
if self.options['address_format'] == 'shifted':
self.databyte = self.databyte >> 1
cmd = 'ADDRESS WRITE' if self.wr else 'ADDRESS READ'
#bin_class = 1 if self.wr else 0
self.ss, self.es = self.ss_byte, self.samplenum
#self.putp(['BITS', self.bits])
#self.putp([cmd, self.databyte])
#self.putb([bin_class, bytes([self.databyte])])
#for bit in self.bits:
# self.put(bit[1], bit[2], self.out_ann, [5, ['%d' % bit[0]]])
self.putx([proto[cmd][0], ['%s: %02X' % (proto[cmd][1], self.databyte),
'%s: %02X' % (proto[cmd][2], self.databyte), '%02X' % self.databyte]])
cmd = 'WRITE' if self.wr else 'READ'
self.ss, self.es = self.samplenum, self.samplenum + self.bitwidth
w = ['Write', 'Wr', 'W'] if self.wr else ['Read', 'Rd', 'R']
self.putx([proto[cmd][0], w])
# Done with this packet.
self.bitcount = self.databyte = 0
#self.bits = []
self.state = 'FIND ACK'
# Gather 8 bits of data plus the ACK/NACK bit.
def found_data(self, scl, sda):
# Address and data are transmitted MSB-first.
self.databyte <<= 1
self.databyte |= sda
# Remember the start of the first data/address bit.
if self.bitcount == 0:
self.ss_byte = self.samplenum
if self.bitcount == 1:
self.bitwidth = self.samplenum - self.ss_byte
# Store individual bits and their start/end samplenumbers.
# In the list, index 0 represents the MSB (I²C transmits MSB-first).
#self.bits.append([sda, self.samplenum, self.samplenum])
#if self.bitcount > 0:
# self.bits[self.bitcount-1][2] = self.samplenum
#if self.bitcount == 7:
# self.bits[7][2] += self.bitwidth
# Return if we haven't collected all 8 + 1 bits, yet.
if self.bitcount < 7:
self.bitcount += 1
return
cmd = 'DATA WRITE' if self.wr else 'DATA READ'
#bin_class = 3 if self.wr else 2
self.ss, self.es = self.ss_byte, self.samplenum + self.bitwidth
#self.putp(['BITS', self.bits])
#self.putp([cmd, self.databyte])
#self.putb([bin_class, bytes([self.databyte])])
#for bit in self.bits:
# self.put(bit[1], bit[2], self.out_ann, [5, ['%d' % bit[0]]])
self.putx([proto[cmd][0], ['%s: %02X' % (proto[cmd][1], self.databyte),
'%s: %02X' % (proto[cmd][2], self.databyte), '%02X' % self.databyte]])
# Done with this packet.
self.bitcount = self.databyte = 0
#self.bits = []
self.state = 'FIND ACK'
def get_ack(self, scl, sda):
self.ss, self.es = self.samplenum, self.samplenum + self.bitwidth
cmd = 'NACK' if (sda == 1) else 'ACK'
#self.putp([cmd, None])
self.putx([proto[cmd][0], proto[cmd][1:]])
# There could be multiple data bytes in a row, so either find
# another data byte or a STOP condition next.
self.state = 'FIND DATA'
def found_stop(self, scl, sda):
# Meta bitrate
#elapsed = 1 / float(self.samplerate) * (self.samplenum - self.pdu_start + 1)
#bitrate = int(1 / elapsed * self.pdu_bits)
#self.put(self.ss_byte, self.samplenum, self.out_bitrate, bitrate)
cmd = 'STOP'
self.ss, self.es = self.samplenum, self.samplenum
#self.putp([cmd, None])
self.putx([proto[cmd][0], proto[cmd][1:]])
self.state = 'FIND START'
self.is_repeat_start = 0
self.wr = -1
#self.bits = []
def decode(self, ss, es, logic):
for (self.samplenum, pins) in logic:
(scl, sda) = pins
#self.pdu_bits += 1
logic.logic_mask = 0b11
logic.cur_pos = self.samplenum
logic.edge_index = -1
# State machine.
if self.state == 'FIND START':
# START condition (S): SDA = falling, SCL = high
if (self.oldsda == 1 and sda == 0) and scl == 1:
self.found_start(scl, sda)
logic.exp_logic = 0b01
logic.logic_mask = 0b01
logic.edge_index = 0
scl = 0
else:
logic.exp_logic = 0b01
logic.logic_mask = 0b11
logic.edge_index = 1
sda = 1
elif self.state == 'FIND ADDRESS':
# Data sampling of receiver: SCL = rising
if self.oldscl == 0 and scl == 1:
self.found_address(scl, sda)
# START condition (S): SDA = falling, SCL = high
elif (self.oldsda == 1 and sda == 0) and scl == 1:
self.found_start(scl, sda)
# STOP condition (P): SDA = rising, SCL = high
elif (self.oldsda == 0 and sda == 1) and scl == 1:
self.found_stop(scl, sda)
elif self.state == 'FIND DATA':
# Data sampling of receiver: SCL = rising
if self.oldscl == 0 and scl == 1:
self.found_data(scl, sda)
# START condition (S): SDA = falling, SCL = high
elif (self.oldsda == 1 and sda == 0) and scl == 1:
self.found_start(scl, sda)
# STOP condition (P): SDA = rising, SCL = high
elif (self.oldsda == 0 and sda == 1) and scl == 1:
self.found_stop(scl, sda)
elif self.state == 'FIND ACK':
# Data sampling of receiver: SCL = rising
if self.oldscl == 0 and scl == 1:
self.get_ack(scl, sda)
logic.exp_logic = 0b01
logic.logic_mask = 0b01
logic.edge_index = 0
scl = 0
# Save current SDA/SCL values for the next round.
self.oldscl, self.oldsda = scl, sda

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,32 @@
##
## This file is part of the libsigrokdecode project.
##
## Copyright (C) 2012 Uwe Hermann <uwe@hermann-uwe.de>
##
## 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
##
'''
The SPI (Serial Peripheral Interface) protocol decoder supports synchronous
SPI(-like) protocols with a clock line, a MISO and MOSI line for data
transfer in two directions, and an optional CS# pin.
Either MISO or MOSI (but not both) can be optional.
If CS# is supplied, data is only decoded when CS# is asserted (clock
transitions where CS# is not asserted are ignored). If CS# is not supplied,
data is decoded on every clock transition (depending on SPI mode).
'''
from .pd import Decoder

View File

@ -0,0 +1,293 @@
##
## This file is part of the libsigrokdecode project.
##
## Copyright (C) 2011 Gareth McMullin <gareth@blacksphere.co.nz>
## Copyright (C) 2012-2014 Uwe Hermann <uwe@hermann-uwe.de>
## Copyright (C) 2016 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
## 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
##
import sigrokdecode as srd
from collections import namedtuple
Data = namedtuple('Data', ['ss', 'es', 'val'])
'''
OUTPUT_PYTHON format:
Packet:
[<ptype>, <data1>, <data2>]
<ptype>:
- 'DATA': <data1> contains the MOSI data, <data2> contains the MISO data.
The data is _usually_ 8 bits (but can also be fewer or more bits).
Both data items are Python numbers (not strings), or None if the respective
channel was not supplied.
- 'BITS': <data1>/<data2> contain a list of bit values in this MOSI/MISO data
item, and for each of those also their respective start-/endsample numbers.
- 'CS-CHANGE': <data1> is the old CS# pin value, <data2> is the new value.
Both data items are Python numbers (0/1), not strings. At the beginning of
the decoding a packet is generated with <data1> = None and <data2> being the
initial state of the CS# pin or None if the chip select pin is not supplied.
- 'TRANSFER': <data1>/<data2> contain a list of Data() namedtuples for each
byte transferred during this block of CS# asserted time. Each Data() has
fields ss, es, and val.
Examples:
['CS-CHANGE', None, 1]
['CS-CHANGE', 1, 0]
['DATA', 0xff, 0x3a]
['BITS', [[1, 80, 82], [1, 83, 84], [1, 85, 86], [1, 87, 88],
[1, 89, 90], [1, 91, 92], [1, 93, 94], [1, 95, 96]],
[[0, 80, 82], [1, 83, 84], [0, 85, 86], [1, 87, 88],
[1, 89, 90], [1, 91, 92], [0, 93, 94], [0, 95, 96]]]
['DATA', 0x65, 0x00]
['DATA', 0xa8, None]
['DATA', None, 0x55]
['CS-CHANGE', 0, 1]
['TRANSFER', [Data(ss=80, es=96, val=0xff), ...],
[Data(ss=80, es=96, val=0x3a), ...]]
'''
# Key: (CPOL, CPHA). Value: SPI mode.
# Clock polarity (CPOL) = 0/1: Clock is low/high when inactive.
# Clock phase (CPHA) = 0/1: Data is valid on the leading/trailing clock edge.
spi_mode = {
(0, 0): 0, # Mode 0
(0, 1): 1, # Mode 1
(1, 0): 2, # Mode 2
(1, 1): 3, # Mode 3
}
class SamplerateError(Exception):
pass
class ChannelError(Exception):
pass
class Decoder(srd.Decoder):
api_version = 2
id = '0:spi'
name = '0:SPI'
longname = 'Serial Peripheral Interface'
desc = 'Full-duplex, synchronous, serial bus.'
license = 'gplv2+'
inputs = ['logic']
outputs = ['spi']
channels = (
{'id': 'clk', 'name': 'CLK', 'desc': 'Clock'},
)
optional_channels = (
{'id': 'miso', 'name': 'MISO', 'desc': 'Master in, slave out'},
{'id': 'mosi', 'name': 'MOSI', 'desc': 'Master out, slave in'},
{'id': 'cs', 'name': 'CS#', 'desc': 'Chip-select'},
)
options = (
{'id': 'cs_polarity', 'desc': 'CS# polarity', 'default': 'active-low',
'values': ('active-low', 'active-high')},
{'id': 'cpol', 'desc': 'Clock polarity', 'default': 0,
'values': (0, 1)},
{'id': 'cpha', 'desc': 'Clock phase', 'default': 0,
'values': (0, 1)},
{'id': 'bitorder', 'desc': 'Bit order',
'default': 'msb-first', 'values': ('msb-first', 'lsb-first')},
{'id': 'wordsize', 'desc': 'Word size', 'default': 8},
)
annotations = (
('106', 'miso-data', 'MISO data'),
('108', 'mosi-data', 'MOSI data'),
('107', 'miso-bits', 'MISO bits'),
('109', 'mosi-bits', 'MOSI bits'),
('1000', 'warnings', 'Human-readable warnings'),
)
annotation_rows = (
('miso-data', 'MISO data', (0,)),
#('miso-bits', 'MISO bits', (2,)),
('mosi-data', 'MOSI data', (1,)),
#('mosi-bits', 'MOSI bits', (3,)),
#('other', 'Other', (4,)),
)
binary = (
('miso', 'MISO'),
('mosi', 'MOSI'),
)
def __init__(self):
self.samplerate = None
self.oldclk = -1
self.bitcount = 0
self.misodata = self.mosidata = 0
self.misobits = []
self.mosibits = []
self.misobytes = []
self.mosibytes = []
self.ss_block = -1
self.samplenum = -1
self.ss_transfer = -1
self.cs_was_deasserted = False
self.oldcs = None
self.oldpins = None
self.have_cs = self.have_miso = self.have_mosi = None
self.no_cs_notification = False
self.mode = None
self.active_low = None
self.pin_checked = False
self.ws = None
self.bitwidth = 0
def metadata(self, key, value):
if key == srd.SRD_CONF_SAMPLERATE:
self.samplerate = value
def start(self):
self.out_python = self.register(srd.OUTPUT_PYTHON)
self.out_ann = self.register(srd.OUTPUT_ANN)
self.out_binary = self.register(srd.OUTPUT_BINARY)
self.out_bitrate = self.register(srd.OUTPUT_META,
meta=(int, 'Bitrate', 'Bitrate during transfers'))
if not self.samplerate:
raise SamplerateError('Cannot decode without samplerate.')
#Sample data on rising/falling clock edge (depends on mode).
self.mode = spi_mode[self.options['cpol'], self.options['cpha']]
self.active_low = (self.options['cs_polarity'] == 'active-low')
self.ws = self.options['wordsize']
def putw(self, data):
self.put(self.ss_block, self.samplenum, self.out_ann, data)
def putdata(self):
# Pass MISO and MOSI bits and then data to the next PD up the stack.
if self.have_miso:
ss, es = self.misobits[0][1], self.misobits[self.ws-1][2]
self.put(ss, es, self.out_python, ['BITS', self.mosibits, self.misobits])
self.misobytes.append(Data(ss=ss, es=es, val=self.misodata))
for bit in self.misobits:
self.put(bit[1], bit[2], self.out_ann, [2, ['%d' % bit[0]]])
self.put(ss, es, self.out_ann, [0, ['%02X' % self.misodata]])
# self.put(ss, es, self.out_binary, [0, bytes([self.misodata])])
if self.have_mosi:
ss, es = self.mosibits[0][1], self.mosibits[self.ws-1][2]
self.put(ss, es, self.out_python, ['DATA', self.mosidata, self.misodata])
self.mosibytes.append(Data(ss=ss, es=es, val=self.mosidata))
for bit in self.mosibits:
self.put(bit[1], bit[2], self.out_ann, [3, ['%d' % bit[0]]])
self.put(ss, es, self.out_ann, [1, ['%02X' % self.mosidata]])
# self.put(ss, es, self.out_binary, [1, bytes([si])])
def reset_decoder_state(self):
self.misodata = 0 if self.have_miso else None
self.mosidata = 0 if self.have_mosi else None
#self.misobits = [] if self.have_miso else None
#self.mosibits = [] if self.have_mosi else None
self.bitcount = 0
def handle_bit(self, miso, mosi, clk, cs):
# If this is the first bit of a dataword, save its sample number.
if self.bitcount == 0:
self.ss_block = self.samplenum
# self.cs_was_deasserted = (cs == self.deasserted_cs)
if self.bitcount == 1:
self.bitwidth = self.samplenum - self.ss_block
shift_cnt = (self.ws - 1 - self.bitcount) if (self.options['bitorder'] == 'msb-first') else self.bitcount
# Receive MISO bit into our shift register.
if self.have_miso:
self.misodata |= miso << shift_cnt
#self.misobits.append([miso, self.samplenum, es])
#if self.bitcount > 0:
# self.misobits[self.bitcount-1][2] = self.samplenum
# Receive MOSI bit into our shift register.
if self.have_mosi:
self.mosidata |= mosi << shift_cnt
#self.mosibits.append([mosi, self.samplenum, es])
#if self.bitcount > 0:
# self.mosibits[self.bitcount-1][2] = self.samplenum
self.bitcount += 1
# Continue to receive if not enough bits were received, yet.
if self.bitcount != self.ws:
return
es = self.samplenum + self.bitwidth
if self.have_miso:
self.put(self.ss_block, es, self.out_ann, [0, ['%02X' % self.misodata]])
if self.have_mosi:
self.put(self.ss_block, es, self.out_ann, [1, ['%02X' % self.mosidata]])
# Meta bitrate.
#elapsed = 1 / float(self.samplerate)
#elapsed *= (self.samplenum - self.ss_block + 1)
#bitrate = int(1 / elapsed * self.options['wordsize'])
#self.put(self.ss_block, self.samplenum, self.out_bitrate, bitrate)
#if self.have_cs and self.cs_was_deasserted:
# self.putw([4, ['CS# was deasserted during this data word!']])
self.reset_decoder_state()
def decode(self, ss, es, logic):
# Either MISO or MOSI can be omitted (but not both). CS# is optional.
for (self.samplenum, pins) in logic:
(clk, miso, mosi, cs) = pins
if not self.pin_checked:
self.have_miso = (miso in (0, 1))
self.have_mosi = (mosi in (0, 1))
self.have_cs = (cs in (0, 1))
# Either MISO or MOSI (but not both) can be omitted.
if not (self.have_miso or self.have_mosi):
raise ChannelError('Either MISO or MOSI (or both) pins required.')
if (self.mode == 0 or self.mode == 3):
self.exp_oldclk = 0
self.exp_clk = 1
else:
self.exp_oldclk = 1
self.exp_clk = 0
self.logic_mask = 0b1001 if self.have_cs else 0b0001
self.exp_logic = 0b0000 if self.active_low else 0b1000
self.asserted_oldcs = 1 if self.active_low else 0
self.asserted_cs = 0 if self.active_low else 1
self.deasserted_oldcs = 0 if self.active_low else 1
self.deasserted_cs = 1 if self.active_low else 0
self.pin_checked = True
logic.logic_mask = self.logic_mask
logic.cur_pos = self.samplenum
logic.edge_index = -1
#logic.itercnt += 1
# Tell stacked decoders that we don't have a CS# signal.
#if not self.no_cs_notification and not self.have_cs:
# self.put(0, 0, self.out_python, ['CS-CHANGE', None, None])
# self.no_cs_notification = True
if (self.oldcs, cs) == (self.asserted_oldcs, self.asserted_cs):
#self.ss_transfer = self.samplenum
#self.misobytes = []
#self.mosibytes = []
self.reset_decoder_state()
elif (self.oldcs, cs) == (self.deasserted_oldcs, self.deasserted_cs):
#self.put(self.ss_transfer, self.samplenum, self.out_python,
# ['TRANSFER', self.mosibytes, self.misobytes])
logic.exp_logic = self.exp_logic
cs = self.asserted_oldcs
logic.logic_mask = 0b1000
logic.edge_index = 3
elif not self.have_cs or cs == self.asserted_cs:
if (self.oldclk, clk) == (self.exp_oldclk, self.exp_clk):
#Sample on rising/falling clock edge
self.handle_bit(miso, mosi, clk, cs)
self.oldclk, self.oldcs = clk, cs

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,41 @@
##
## This file is part of the libsigrokdecode project.
##
## Copyright (C) 2012 Uwe Hermann <uwe@hermann-uwe.de>
##
## 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
##
'''
UART (Universal Asynchronous Receiver Transmitter) is a simple serial
communication protocol which allows two devices to talk to each other.
This decoder should work on all "UART-like" async protocols with one
start bit (0), 5-9 databits, an (optional) parity bit, and one or more
stop bits (1), in this order.
It can be run on one signal line (RX or TX) only, or on two lines (RX + TX).
There are various standards for the physical layer specification of the
signals, including RS232, (TTL) UART, RS485, and others. However, the logic
level of the respective pins is only relevant when acquiring the data via
a logic analyzer (you have to select the correct logic analyzer and/or
the correct place where to probe). Once the data is in digital form and
matches the "UART" description above, this protocol decoder can work with
it though, no matter whether the source was on TTL UART levels, or RS232,
or others.
'''
from .pd import Decoder

View File

@ -0,0 +1,311 @@
##
## This file is part of the libsigrokdecode project.
##
## Copyright (C) 2011-2014 Uwe Hermann <uwe@hermann-uwe.de>
## Copyright (C) 2016 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
## 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
##
import sigrokdecode as srd
from math import floor, ceil
'''
OUTPUT_PYTHON format:
Packet:
[<ptype>, <pdata>]
This is the list of <ptype>s and their respective <pdata> values:
- 'STARTBIT': The data is the (integer) value of the start bit (0/1).
- 'DATA': This is always a tuple containing two items:
- 1st item: the (integer) value of the UART data. Valid values
range from 0 to 512 (as the data can be up to 9 bits in size).
- 2nd item: the list of individual data bits and their ss/es numbers.
- 'PARITYBIT': The data is the (integer) value of the parity bit (0/1).
- 'STOPBIT': The data is the (integer) value of the stop bit (0 or 1).
- 'INVALID STARTBIT': The data is the (integer) value of the start bit (0/1).
- 'INVALID STOPBIT': The data is the (integer) value of the stop bit (0/1).
- 'PARITY ERROR': The data is a tuple with two entries. The first one is
the expected parity value, the second is the actual parity value.
- TODO: Frame error?
'''
# Given a parity type to check (odd, even, zero, one), the value of the
# parity bit, the value of the data, and the length of the data (5-9 bits,
# usually 8 bits) return True if the parity is correct, False otherwise.
# 'none' is _not_ allowed as value for 'parity_type'.
def parity_ok(parity_type, parity_bit, data, num_data_bits):
# Handle easy cases first (parity bit is always 1 or 0).
if parity_type == 'zero':
return parity_bit == 0
elif parity_type == 'one':
return parity_bit == 1
# Count number of 1 (high) bits in the data (and the parity bit itself!).
ones = bin(data).count('1') + parity_bit
# Check for odd/even parity.
if parity_type == 'odd':
return (ones % 2) == 1
elif parity_type == 'even':
return (ones % 2) == 0
class SamplerateError(Exception):
pass
class Decoder(srd.Decoder):
api_version = 2
id = '0:uart'
name = '0:UART'
longname = 'Universal Asynchronous Receiver/Transmitter'
desc = 'Asynchronous, serial bus.'
license = 'gplv2+'
inputs = ['logic']
outputs = ['uart']
channels = (
{'id': 'rxtx', 'name': 'RX/TX', 'desc': 'UART transceive line'},
)
options = (
{'id': 'baudrate', 'desc': 'Baud rate', 'default': 9600},
{'id': 'num_data_bits', 'desc': 'Data bits', 'default': 8,
'values': (5, 6, 7, 8, 9)},
{'id': 'parity_type', 'desc': 'Parity type', 'default': 'none',
'values': ('none', 'odd', 'even', 'zero', 'one')},
{'id': 'parity_check', 'desc': 'Check parity?', 'default': 'yes',
'values': ('yes', 'no')},
{'id': 'num_stop_bits', 'desc': 'Stop bits', 'default': 1.0,
'values': (0.0, 0.5, 1.0, 1.5)},
{'id': 'bit_order', 'desc': 'Bit order', 'default': 'lsb-first',
'values': ('lsb-first', 'msb-first')},
{'id': 'format', 'desc': 'Data format', 'default': 'ascii',
'values': ('ascii', 'dec', 'hex', 'oct', 'bin')},
{'id': 'invert', 'desc': 'Invert Signal?', 'default': 'no',
'values': ('yes', 'no')},
)
annotations = (
('108', 'data', 'data'),
('7', 'start', 'start bits'),
('6', 'parity-ok', 'parity OK bits'),
('0', 'parity-err', 'parity error bits'),
('1', 'stop', 'stop bits'),
('1000', 'warnings', 'warnings'),
('109', 'data-bits', 'data bits'),
)
annotation_rows = (
('data', 'RX/TX', (0, 1, 2, 3, 4)),
#('data-bits', 'Bits', (6,)),
#('warnings', 'Warnings', (5,)),
)
binary = (
('rxtx', 'RX/TX dump'),
)
def put_ann_bit(self, width, data):
s = self.bitstart
self.put(floor(s), floor(s + width), self.out_ann, data)
def put_python_bit(self, width, data):
s = self.bitstart
self.put(floor(s), floor(s + width), self.out_python, data)
def put_ann_byte(self, data):
ss, s = self.bytestart, self.bitstart
self.put(floor(ss), floor(s + self.bit_width), self.out_ann, data)
def put_python_byte(self, data):
ss, s = self.bytestart, self.bitstart
self.put(floor(ss), floor(s + self.bit_width), self.out_python, data)
def put_binary_byte(self, data):
ss, s = self.bytestart, self.bitstart
self.put(floor(ss), floor(s + self.bit_width), self.out_binary, data)
def __init__(self):
self.samplerate = None
self.samplenum = 0
self.startbit = -1
self.bitcount = 0
self.databyte = 0
self.paritybit = -1
self.stopbit1 = -1
self.bitstart = -1
self.bytestart = -1
self.state = 'FIND START'
self.oldbit = -1
self.databits = []
def start(self):
self.out_python = self.register(srd.OUTPUT_PYTHON)
self.out_binary = self.register(srd.OUTPUT_BINARY)
self.out_ann = self.register(srd.OUTPUT_ANN)
if not self.samplerate:
raise SamplerateError('Cannot decode without samplerate.')
if self.samplerate < self.options['baudrate']*4:
raise SamplerateError('Samplerate is too low for current baudrate setting, 4x at least!')
if self.options['invert'] == 'yes':
self.exp_logic = 1
else:
self.exp_logic = 0
def metadata(self, key, value):
if key == srd.SRD_CONF_SAMPLERATE:
self.samplerate = value
# The width of one UART bit in number of samples.
self.bit_width = float(self.samplerate) / float(self.options['baudrate'])
def frame_start(self, signal):
# Save the sample number where the start bit begins.
self.bitstart = self.samplenum
self.state = 'GET START BIT'
def get_start_bit(self, signal):
self.startbit = signal
# The startbit must be 0. If not, we report an error.
#if self.startbit != 0:
#self.put_python_bit(self.bit_width, ['INVALID STARTBIT', 0, self.startbit])
#self.put_ann_bit(self.bit_width, [5, ['Frame error', 'Frame err', 'FE']])
# TODO: Abort? Ignore rest of the frame?
self.bitcount = 0
self.databyte = 0
self.state = 'GET DATA BITS'
#self.put_python_bit(self.bit_width, ['STARTBIT', 0, self.startbit])
self.put_ann_bit(self.bit_width, [1, ['Start bit', 'Start', 'S']])
def get_data_bits(self, signal):
# Save the sample number of where the bit begins.
self.bitstart += self.bit_width
if self.bitcount == 0 :
self.bytestart = self.bitstart
# Get the next data bit in LSB-first or MSB-first fashion.
if self.options['bit_order'] == 'lsb-first':
self.databyte >>= 1
self.databyte |= \
(signal << (self.options['num_data_bits'] - 1))
else:
self.databyte <<= 1
self.databyte |= (signal << 0)
#self.put_ann_bit(self.bit_width, [6, ['%d' % signal]])
# Store individual data bits and their start/end samplenumbers.
#s, halfbit = self.samplenum, int(self.bit_width / 2)
#self.databits.append([signal, s - halfbit, s + halfbit])
# Return here, unless we already received all data bits.
if self.bitcount < self.options['num_data_bits'] - 1:
self.bitcount += 1
return
if self.options['parity_type'] == 'none':
self.state = 'GET STOP BITS'
else:
self.state = 'GET PARITY BIT'
#self.put_python_byte(['DATA', 0, (self.databyte, self.databits)])
b, f = self.databyte, self.options['format']
if f == 'ascii':
c = chr(b) if b in range(30, 126 + 1) else '[%02X]' % b
self.put_ann_byte([0, [c]])
elif f == 'dec':
self.put_ann_byte([0, [str(b)]])
elif f == 'hex':
self.put_ann_byte([0, [hex(b)[2:].zfill(2).upper()]])
elif f == 'oct':
self.put_ann_byte([0, [oct(b)[2:].zfill(3)]])
elif f == 'bin':
self.put_ann_byte([0, [bin(b)[2:].zfill(8)]])
#self.put_binary_byte([0, bytes([b])])
#self.put_binary_byte([2, bytes([b])])
#self.databits = []
def get_parity_bit(self, signal):
# Save the sample number of where the bit begins.
self.bitstart += self.bit_width
self.paritybit = signal
self.state = 'GET STOP BITS'
if parity_ok(self.options['parity_type'], self.paritybit,
self.databyte, self.options['num_data_bits']):
# self.put_python_bit(self.bit_width, ['PARITYBIT', 0, self.paritybit])
self.put_ann_bit(self.bit_width, [2, ['Parity bit', 'Parity', 'P']])
else:
# # TODO: Return expected/actual parity values.
# self.put_python_bit(self.bit_width, ['PARITY ERROR', 0, (0, 1)]) # FIXME: Dummy tuple...
self.put_ann_bit(self.bit_width, [3, ['Parity error', 'Parity err', 'PE']])
# TODO: Currently only supports 1 stop bit.
def get_stop_bits(self, signal):
# Save the sample number of where the bit begins.
self.bitstart += self.bit_width
#self.stopbit1 = signal
# Stop bits must be 1. If not, we report an error.
#if self.stopbit1 != 1:
# self.put_python_bit(self.bit_width, ['INVALID STOPBIT', 0, self.stopbit1])
# self.put_ann_bit(self.bit_width, [5, ['Frame error', 'Frame err', 'FE']])
# TODO: Abort? Ignore the frame? Other?
self.state = 'FIND START'
#self.put_python_bit(int(self.bit_width * self.options['num_stop_bits']), ['STOPBIT', 0, self.stopbit1])
self.put_ann_bit(int(self.bit_width * self.options['num_stop_bits']), [4, ['Stop bit', 'Stop', 'T']])
def decode(self, ss, es, logic):
for (self.samplenum, pins) in logic:
# In default case, the iteration gap is 1
logic.logic_mask = 0
logic.edge_index = 0
(signal,) = pins
if self.options['invert'] == 'yes':
signal = not signal
# State machine.
if self.state == 'FIND START':
if (self.oldbit == 1 and signal == 0):
self.frame_start(signal)
logic.itercnt += (self.bit_width - 1) / 2.0
else:
logic.exp_logic = self.exp_logic
logic.logic_mask = 1
logic.cur_pos = self.samplenum
signal = 1
elif self.state == 'GET START BIT':
self.get_start_bit(signal)
logic.itercnt += self.bit_width
elif self.state == 'GET DATA BITS':
self.get_data_bits(signal)
logic.itercnt += self.bit_width
elif self.state == 'GET PARITY BIT':
self.get_parity_bit(signal)
logic.itercnt += self.bit_width
elif self.state == 'GET STOP BITS':
self.get_stop_bits(signal)
logic.itercnt += (self.options['num_stop_bits'] - 0.75) * self.bit_width
signal = 0
# Save current RX/TX values for the next round.
self.oldbit = signal

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,26 @@
##
## This file is part of the libsigrokdecode project.
##
## Copyright (C) 2012 Uwe Hermann <uwe@hermann-uwe.de>
##
## 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
##
'''
I²C (Inter-Integrated Circuit) is a bidirectional, multi-master
bus using two signals (SCL = serial clock line, SDA = serial data line).
'''
from .pd import Decoder

View File

@ -0,0 +1,341 @@
##
## This file is part of the libsigrokdecode project.
##
## Copyright (C) 2010-2014 Uwe Hermann <uwe@hermann-uwe.de>
## Copyright (C) 2016 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
## 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
##
# TODO: Look into arbitration, collision detection, clock synchronisation, etc.
# TODO: Implement support for 10bit slave addresses.
# TODO: Implement support for inverting SDA/SCL levels (0->1 and 1->0).
# TODO: Implement support for detecting various bus errors.
import sigrokdecode as srd
'''
OUTPUT_PYTHON format:
Packet:
[<ptype>, <pdata>]
<ptype>:
- 'START' (START condition)
- 'START REPEAT' (Repeated START condition)
- 'ADDRESS READ' (Slave address, read)
- 'ADDRESS WRITE' (Slave address, write)
- 'DATA READ' (Data, read)
- 'DATA WRITE' (Data, write)
- 'STOP' (STOP condition)
- 'ACK' (ACK bit)
- 'NACK' (NACK bit)
- 'BITS' (<pdata>: list of data/address bits and their ss/es numbers)
<pdata> is the data or address byte associated with the 'ADDRESS*' and 'DATA*'
command. Slave addresses do not include bit 0 (the READ/WRITE indication bit).
For example, a slave address field could be 0x51 (instead of 0xa2).
For 'START', 'START REPEAT', 'STOP', 'ACK', and 'NACK' <pdata> is None.
'''
# CMD: [annotation-type-index, long annotation, short annotation]
proto = {
'START': [0, 'Start', 'S'],
'START REPEAT': [1, 'Start repeat', 'Sr'],
'STOP': [2, 'Stop', 'P'],
'ACK': [3, 'ACK', 'A'],
'NACK': [4, 'NACK', 'N'],
'READ': [5, 'Read', 'R'],
'WRITE': [6, 'Write', 'W'],
'BIT': [7, 'Bit', 'B'],
'ADDRESS READ': [8, 'Address read', 'AR'],
'ADDRESS WRITE': [9, 'Address write', 'AW'],
'DATA READ': [10, 'Data read', 'DR'],
'DATA WRITE': [11, 'Data write', 'DW'],
}
class SamplerateError(Exception):
pass
class Decoder(srd.Decoder):
api_version = 2
id = '1:i2c'
name = '1:I²C'
longname = 'Inter-Integrated Circuit'
desc = 'Two-wire, multi-master, serial bus.'
license = 'gplv2+'
inputs = ['logic']
outputs = ['i2c']
channels = (
{'id': 'scl', 'name': 'SCL', 'desc': 'Serial clock line'},
{'id': 'sda', 'name': 'SDA', 'desc': 'Serial data line'},
)
options = (
{'id': 'address_format', 'desc': 'Displayed slave address format',
'default': 'shifted', 'values': ('shifted', 'unshifted')},
)
annotations = (
('7', 'start', 'Start condition'),
('6', 'repeat-start', 'Repeat start condition'),
('1', 'stop', 'Stop condition'),
('5', 'ack', 'ACK'),
('0', 'nack', 'NACK'),
('12', 'read', 'Read'),
('11', 'write', 'Write'),
('108', 'bit', 'Data/address bit'),
('112', 'address-read', 'Address read'),
('111', 'address-write', 'Address write'),
('110', 'data-read', 'Data read'),
('109', 'data-write', 'Data write'),
('1000', 'warnings', 'Human-readable warnings'),
)
annotation_rows = (
('bits', 'Bits', (7,)),
('addr-data', 'Address/Data', (0, 1, 2, 3, 4, 5, 6, 8, 9, 10, 11)),
('warnings', 'Warnings', (12,)),
)
binary = (
('address-read', 'Address read'),
('address-write', 'Address write'),
('data-read', 'Data read'),
('data-write', 'Data write'),
)
def __init__(self):
self.samplerate = None
self.ss = self.es = self.ss_byte = -1
self.samplenum = None
self.bitcount = 0
self.databyte = 0
self.wr = -1
self.is_repeat_start = 0
self.state = 'FIND START'
self.oldscl = self.oldsda = -1
self.pdu_start = None
#self.pdu_bits = 0
self.bits = []
def metadata(self, key, value):
if key == srd.SRD_CONF_SAMPLERATE:
self.samplerate = value
def start(self):
self.out_python = self.register(srd.OUTPUT_PYTHON)
self.out_ann = self.register(srd.OUTPUT_ANN)
self.out_binary = self.register(srd.OUTPUT_BINARY)
self.out_bitrate = self.register(srd.OUTPUT_META,
meta=(int, 'Bitrate', 'Bitrate from Start bit to Stop bit'))
if not self.samplerate:
raise SamplerateError('Cannot decode without samplerate.')
def putx(self, data):
self.put(self.ss, self.es, self.out_ann, data)
def putp(self, data):
self.put(self.ss, self.es, self.out_python, data)
#def putb(self, data):
# self.put(self.ss, self.es, self.out_binary, data)
def found_start(self, scl, sda):
self.ss, self.es = self.samplenum, self.samplenum
self.pdu_start = self.samplenum
#self.pdu_bits = 0
cmd = 'START REPEAT' if (self.is_repeat_start == 1) else 'START'
self.putp([cmd, None])
self.putx([proto[cmd][0], proto[cmd][1:]])
self.state = 'FIND ADDRESS'
self.bitcount = self.databyte = 0
self.is_repeat_start = 1
self.wr = -1
self.bits = []
# Gather 7 bits of address, 1 bit of rd/wr, plus the ACK/NACK bit.
def found_address(self, scl, sda):
# Address and data are transmitted MSB-first.
self.databyte <<= 1
self.databyte |= sda
# Remember the start of the first data/address bit.
if self.bitcount == 0:
self.ss_byte = self.samplenum
# Store individual bits and their start/end samplenumbers.
# In the list, index 0 represents the MSB (I²C transmits MSB-first).
self.bits.insert(0, [sda, self.samplenum, self.samplenum])
if self.bitcount > 0:
self.bits[1][2] = self.samplenum
if self.bitcount == 7:
self.bitwidth = self.bits[1][2] - self.bits[2][2]
self.bits[0][2] += self.bitwidth
# Return if we haven't collected all 8 + 1 bits, yet.
if self.bitcount < 7:
self.bitcount += 1
return
# The READ/WRITE bit is only in address bytes, not data bytes.
self.wr = 0 if (self.databyte & 1) else 1
if self.options['address_format'] == 'shifted':
self.databyte = self.databyte >> 1
cmd = 'ADDRESS WRITE' if self.wr else 'ADDRESS READ'
#bin_class = 1 if self.wr else 0
self.ss, self.es = self.ss_byte, self.samplenum
self.putp(['BITS', self.bits])
self.putp([cmd, self.databyte])
#self.putb([bin_class, bytes([self.databyte])])
for bit in reversed(self.bits):
self.put(bit[1], bit[2], self.out_ann, [7, ['%d' % bit[0]]])
self.putx([proto[cmd][0], ['%s: %02X' % (proto[cmd][1], self.databyte),
'%s: %02X' % (proto[cmd][2], self.databyte), '%02X' % self.databyte]])
cmd = 'WRITE' if self.wr else 'READ'
self.ss, self.es = self.samplenum, self.samplenum + self.bitwidth
w = ['Write', 'Wr', 'W'] if self.wr else ['Read', 'Rd', 'R']
self.putx([proto[cmd][0], w])
# Done with this packet.
self.bitcount = self.databyte = 0
self.bits = []
self.state = 'FIND ACK'
# Gather 8 bits of data plus the ACK/NACK bit.
def found_data(self, scl, sda):
# Address and data are transmitted MSB-first.
self.databyte <<= 1
self.databyte |= sda
# Remember the start of the first data/address bit.
if self.bitcount == 0:
self.ss_byte = self.samplenum
# Store individual bits and their start/end samplenumbers.
# In the list, index 0 represents the MSB (I²C transmits MSB-first).
self.bits.insert(0, [sda, self.samplenum, self.samplenum])
if self.bitcount > 0:
self.bits[1][2] = self.samplenum
if self.bitcount == 7:
self.bitwidth = self.bits[1][2] - self.bits[2][2]
self.bits[0][2] += self.bitwidth
# Return if we haven't collected all 8 + 1 bits, yet.
if self.bitcount < 7:
self.bitcount += 1
return
cmd = 'DATA WRITE' if self.wr else 'DATA READ'
#bin_class = 3 if self.wr else 2
self.ss, self.es = self.ss_byte, self.samplenum + self.bitwidth
self.putp(['BITS', self.bits])
self.putp([cmd, self.databyte])
#self.putb([bin_class, bytes([self.databyte])])
for bit in reversed(self.bits):
self.put(bit[1], bit[2], self.out_ann, [7, ['%d' % bit[0]]])
self.putx([proto[cmd][0], ['%s: %02X' % (proto[cmd][1], self.databyte),
'%s: %02X' % (proto[cmd][2], self.databyte), '%02X' % self.databyte]])
# Done with this packet.
self.bitcount = self.databyte = 0
self.bits = []
self.state = 'FIND ACK'
def get_ack(self, scl, sda):
self.ss, self.es = self.samplenum, self.samplenum + self.bitwidth
cmd = 'NACK' if (sda == 1) else 'ACK'
self.putp([cmd, None])
self.putx([proto[cmd][0], proto[cmd][1:]])
# There could be multiple data bytes in a row, so either find
# another data byte or a STOP condition next.
self.state = 'FIND DATA'
def found_stop(self, scl, sda):
# Meta bitrate
#elapsed = 1 / float(self.samplerate) * (self.samplenum - self.pdu_start + 1)
#bitrate = int(1 / elapsed * self.pdu_bits)
#self.put(self.ss_byte, self.samplenum, self.out_bitrate, bitrate)
cmd = 'STOP'
self.ss, self.es = self.samplenum, self.samplenum
self.putp([cmd, None])
self.putx([proto[cmd][0], proto[cmd][1:]])
self.state = 'FIND START'
self.is_repeat_start = 0
self.wr = -1
self.bits = []
def decode(self, ss, es, logic):
for (self.samplenum, pins) in logic:
(scl, sda) = pins
#self.pdu_bits += 1
logic.logic_mask = 0b11
logic.cur_pos = self.samplenum
logic.edge_index = -1
# State machine.
if self.state == 'FIND START':
# START condition (S): SDA = falling, SCL = high
if (self.oldsda == 1 and sda == 0) and scl == 1:
self.found_start(scl, sda)
logic.exp_logic = 0b01
logic.logic_mask = 0b01
logic.edge_index = 0
scl = 0
else:
logic.exp_logic = 0b01
logic.logic_mask = 0b11
logic.edge_index = 1
sda = 1
elif self.state == 'FIND ADDRESS':
# Data sampling of receiver: SCL = rising
if self.oldscl == 0 and scl == 1:
self.found_address(scl, sda)
# START condition (S): SDA = falling, SCL = high
elif (self.oldsda == 1 and sda == 0) and scl == 1:
self.found_start(scl, sda)
# STOP condition (P): SDA = rising, SCL = high
elif (self.oldsda == 0 and sda == 1) and scl == 1:
self.found_stop(scl, sda)
elif self.state == 'FIND DATA':
# Data sampling of receiver: SCL = rising
if self.oldscl == 0 and scl == 1:
self.found_data(scl, sda)
# START condition (S): SDA = falling, SCL = high
elif (self.oldsda == 1 and sda == 0) and scl == 1:
self.found_start(scl, sda)
# STOP condition (P): SDA = rising, SCL = high
elif (self.oldsda == 0 and sda == 1) and scl == 1:
self.found_stop(scl, sda)
elif self.state == 'FIND ACK':
# Data sampling of receiver: SCL = rising
if self.oldscl == 0 and scl == 1:
self.get_ack(scl, sda)
logic.exp_logic = 0b01
logic.logic_mask = 0b01
logic.edge_index = 0
scl = 0
# Save current SDA/SCL values for the next round.
self.oldscl, self.oldsda = scl, sda

Binary file not shown.

Binary file not shown.

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More