mirror of
https://github.com/DreamSourceLab/DSView.git
synced 2025-01-13 13:32:53 +08:00
Improve usb transfer and othre minor issues
This commit is contained in:
parent
4cc02c8d78
commit
f15aa50d32
@ -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
|
||||
@ -119,106 +120,146 @@ 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/mainwindow.cpp
|
||||
pv/devicemanager.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/data/signaldata.cpp
|
||||
pv/data/logicsnapshot.cpp
|
||||
pv/data/logic.cpp
|
||||
pv/data/analogsnapshot.cpp
|
||||
pv/data/analog.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/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/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/data/groupsnapshot.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/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/view.cpp
|
||||
pv/view/viewport.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/mainwindow.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/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/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/dialogs/about.h
|
||||
pv/dialogs/search.h
|
||||
pv/dock/dsotriggerdock.h
|
||||
pv/view/trace.h
|
||||
pv/view/view.h
|
||||
pv/view/viewport.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)
|
||||
|
@ -662,7 +662,7 @@ QAbstractSpinBox {
|
||||
background-color: #201F1F;
|
||||
color: silver;
|
||||
border-radius: 2px;
|
||||
min-width: 50px;
|
||||
min-width: 60px;
|
||||
}
|
||||
|
||||
QAbstractSpinBox:up-button
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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. */
|
||||
|
@ -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>
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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));
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
@ -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()) {
|
||||
|
@ -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()
|
||||
|
@ -53,7 +53,7 @@ private:
|
||||
|
||||
public:
|
||||
WaitingDialog(QWidget *parent, boost::shared_ptr<pv::device::DevInst> dev_inst);
|
||||
void start();
|
||||
int start();
|
||||
|
||||
protected:
|
||||
void accept();
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -90,6 +90,7 @@ private:
|
||||
QPushButton _pre_button;
|
||||
QPushButton _nxt_button;
|
||||
widgets::FakeLineEdit* _search_value;
|
||||
QPushButton *_search_button;
|
||||
};
|
||||
|
||||
} // namespace dock
|
||||
|
@ -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 +
|
||||
#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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
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();
|
||||
@ -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);
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -85,6 +85,8 @@ private:
|
||||
QAction *_action_export;
|
||||
QAction *_action_capture;
|
||||
|
||||
QTimer _screenshot_timer;
|
||||
|
||||
};
|
||||
|
||||
} // namespace toolbars
|
||||
|
@ -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));
|
||||
//}
|
||||
|
||||
_updating_sample_rate = false;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
@ -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++) {
|
||||
|
@ -21,7 +21,8 @@
|
||||
|
||||
#include "dsldial.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
|
||||
namespace pv {
|
||||
namespace view {
|
||||
|
@ -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);
|
||||
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,6 +608,9 @@ int DsoSignal::get_trig_vpos() const
|
||||
|
||||
double DsoSignal::get_trig_vrate() const
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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()
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -238,14 +238,36 @@ void Viewport::paintSignals(QPainter &p)
|
||||
//plot measure arrow
|
||||
paintMeasure(p);
|
||||
|
||||
//plot waiting trigger
|
||||
if (_waiting_trig > 0) {
|
||||
p.setPen(Trace::DARK_FORE);
|
||||
QString text = "Waiting Trig";
|
||||
//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)
|
||||
text += ".";
|
||||
p.drawText(_view.get_view_rect(), Qt::AlignLeft | Qt::AlignTop, text);
|
||||
type_str += ".";
|
||||
} else {
|
||||
type_str = "Trig'd";
|
||||
}
|
||||
}
|
||||
p.setPen(Trace::DARK_FORE);
|
||||
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,6 +1304,11 @@ void Viewport::on_drag_timer()
|
||||
_drag_strength /= DragDamping;
|
||||
if (_drag_strength != 0)
|
||||
_drag_timer.start(DragTimerInterval);
|
||||
} 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();
|
||||
|
@ -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
BIN
DSView/res/DSCope.bin
Normal file → Executable file
Binary file not shown.
BIN
DSView/res/DSCope.fw
Normal file → Executable file
BIN
DSView/res/DSCope.fw
Normal file → Executable file
Binary file not shown.
6
DSView/res/DSCope1.def.dsc
Normal file → Executable file
6
DSView/res/DSCope1.def.dsc
Normal file → Executable 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,
|
||||
|
@ -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
BIN
DSView/res/DSCope20.bin
Executable file
Binary file not shown.
BIN
DSView/res/DSCope20.fw
Executable file
BIN
DSView/res/DSCope20.fw
Executable file
Binary file not shown.
BIN
DSView/res/DSLogic.fw
Normal file → Executable file
BIN
DSView/res/DSLogic.fw
Normal file → Executable file
Binary file not shown.
46
DSView/res/DSLogic0.def.dsc
Normal file → Executable file
46
DSView/res/DSLogic0.def.dsc
Normal file → Executable file
@ -1,11 +1,12 @@
|
||||
{
|
||||
{
|
||||
"Channel Mode": "Use Channels 0~15 (Max 100MHz)",
|
||||
"Device": "DSLogic",
|
||||
"DeviceMode": 0,
|
||||
"Filter Targets": "None",
|
||||
"Horizontal trigger position": "0",
|
||||
"Operation Mode": "Normal",
|
||||
"Sample count": "16777216",
|
||||
"Sample rate": "100000000",
|
||||
"Operation Mode": "Buffer Mode",
|
||||
"Sample count": "1048576",
|
||||
"Sample rate": "1000000",
|
||||
"Threshold Level": 1,
|
||||
"Trigger hold off": "0",
|
||||
"Trigger slope": "0",
|
||||
@ -14,7 +15,7 @@
|
||||
"Using External Clock": 0,
|
||||
"channel": [
|
||||
{
|
||||
"colour": "#16191a",
|
||||
"colour": "#6a6a6a",
|
||||
"enabled": true,
|
||||
"index": 0,
|
||||
"name": "0",
|
||||
@ -22,7 +23,7 @@
|
||||
"type": 10000
|
||||
},
|
||||
{
|
||||
"colour": "#8f5202",
|
||||
"colour": "#6a6a6a",
|
||||
"enabled": true,
|
||||
"index": 1,
|
||||
"name": "1",
|
||||
@ -30,7 +31,7 @@
|
||||
"type": 10000
|
||||
},
|
||||
{
|
||||
"colour": "#cc0000",
|
||||
"colour": "#6a6a6a",
|
||||
"enabled": true,
|
||||
"index": 2,
|
||||
"name": "2",
|
||||
@ -38,7 +39,7 @@
|
||||
"type": 10000
|
||||
},
|
||||
{
|
||||
"colour": "#f57900",
|
||||
"colour": "#6a6a6a",
|
||||
"enabled": true,
|
||||
"index": 3,
|
||||
"name": "3",
|
||||
@ -46,7 +47,7 @@
|
||||
"type": 10000
|
||||
},
|
||||
{
|
||||
"colour": "#edd400",
|
||||
"colour": "#6a6a6a",
|
||||
"enabled": true,
|
||||
"index": 4,
|
||||
"name": "4",
|
||||
@ -54,7 +55,7 @@
|
||||
"type": 10000
|
||||
},
|
||||
{
|
||||
"colour": "#73d216",
|
||||
"colour": "#6a6a6a",
|
||||
"enabled": true,
|
||||
"index": 5,
|
||||
"name": "5",
|
||||
@ -62,7 +63,7 @@
|
||||
"type": 10000
|
||||
},
|
||||
{
|
||||
"colour": "#3465a4",
|
||||
"colour": "#6a6a6a",
|
||||
"enabled": true,
|
||||
"index": 6,
|
||||
"name": "6",
|
||||
@ -70,7 +71,7 @@
|
||||
"type": 10000
|
||||
},
|
||||
{
|
||||
"colour": "#75507b",
|
||||
"colour": "#6a6a6a",
|
||||
"enabled": true,
|
||||
"index": 7,
|
||||
"name": "7",
|
||||
@ -78,7 +79,7 @@
|
||||
"type": 10000
|
||||
},
|
||||
{
|
||||
"colour": "#16191a",
|
||||
"colour": "#6a6a6a",
|
||||
"enabled": true,
|
||||
"index": 8,
|
||||
"name": "8",
|
||||
@ -86,7 +87,7 @@
|
||||
"type": 10000
|
||||
},
|
||||
{
|
||||
"colour": "#8f5202",
|
||||
"colour": "#6a6a6a",
|
||||
"enabled": true,
|
||||
"index": 9,
|
||||
"name": "9",
|
||||
@ -94,7 +95,7 @@
|
||||
"type": 10000
|
||||
},
|
||||
{
|
||||
"colour": "#cc0000",
|
||||
"colour": "#6a6a6a",
|
||||
"enabled": true,
|
||||
"index": 10,
|
||||
"name": "10",
|
||||
@ -102,7 +103,7 @@
|
||||
"type": 10000
|
||||
},
|
||||
{
|
||||
"colour": "#f57900",
|
||||
"colour": "#6a6a6a",
|
||||
"enabled": true,
|
||||
"index": 11,
|
||||
"name": "11",
|
||||
@ -110,7 +111,7 @@
|
||||
"type": 10000
|
||||
},
|
||||
{
|
||||
"colour": "#edd400",
|
||||
"colour": "#6a6a6a",
|
||||
"enabled": true,
|
||||
"index": 12,
|
||||
"name": "12",
|
||||
@ -118,7 +119,7 @@
|
||||
"type": 10000
|
||||
},
|
||||
{
|
||||
"colour": "#73d216",
|
||||
"colour": "#6a6a6a",
|
||||
"enabled": true,
|
||||
"index": 13,
|
||||
"name": "13",
|
||||
@ -126,7 +127,7 @@
|
||||
"type": 10000
|
||||
},
|
||||
{
|
||||
"colour": "#3465a4",
|
||||
"colour": "#6a6a6a",
|
||||
"enabled": true,
|
||||
"index": 14,
|
||||
"name": "14",
|
||||
@ -134,7 +135,7 @@
|
||||
"type": 10000
|
||||
},
|
||||
{
|
||||
"colour": "#75507b",
|
||||
"colour": "#6a6a6a",
|
||||
"enabled": true,
|
||||
"index": 15,
|
||||
"name": "15",
|
||||
@ -227,7 +228,7 @@
|
||||
"triggerLogic8": 1,
|
||||
"triggerLogic9": 1,
|
||||
"triggerMode": 0,
|
||||
"triggerPos": 0,
|
||||
"triggerPos": 1,
|
||||
"triggerSerial": 0,
|
||||
"triggerStages": 0,
|
||||
"triggerStart": "X X X X X X X X X X X X X X X X",
|
||||
@ -263,6 +264,7 @@
|
||||
"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"
|
||||
"triggerValue19": "X X X X X X X X X X X X X X X X",
|
||||
"triggerVcnt": 1
|
||||
}
|
||||
}
|
||||
|
@ -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
10
DSView/res/DSLogic1.def.dsc
Normal file → Executable 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,
|
||||
|
@ -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
18
DSView/res/DSLogic2.def.dsc
Normal file → Executable 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
|
||||
}
|
||||
]
|
||||
|
@ -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
BIN
DSView/res/DSLogic33.bin
Normal file → Executable file
Binary file not shown.
BIN
DSView/res/DSLogic50.bin
Normal file → Executable file
BIN
DSView/res/DSLogic50.bin
Normal file → Executable file
Binary file not shown.
BIN
DSView/res/DSLogicPro.bin
Normal file → Executable file
BIN
DSView/res/DSLogicPro.bin
Normal file → Executable file
Binary file not shown.
BIN
DSView/res/DSLogicPro.fw
Normal file → Executable file
BIN
DSView/res/DSLogicPro.fw
Normal file → Executable file
Binary file not shown.
10
INSTALL
10
INSTALL
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
@ -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
@ -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;
|
||||
@ -569,12 +597,17 @@ static int config_set(int id, GVariant *data, struct sr_dev_inst *sdi,
|
||||
} else if (id == SR_CONF_LIMIT_SAMPLES) {
|
||||
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);
|
||||
|
@ -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",
|
||||
|
@ -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"
|
||||
|
BIN
libsigrokdecode4DSL/.decoder.c.swp
Normal file
BIN
libsigrokdecode4DSL/.decoder.c.swp
Normal file
Binary file not shown.
38
libsigrokdecode4DSL/.gitignore
vendored
Normal file
38
libsigrokdecode4DSL/.gitignore
vendored
Normal 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
|
BIN
libsigrokdecode4DSL/.type_decoder.c.swp
Normal file
BIN
libsigrokdecode4DSL/.type_decoder.c.swp
Normal file
Binary file not shown.
7
libsigrokdecode4DSL/AUTHORS
Normal file
7
libsigrokdecode4DSL/AUTHORS
Normal 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
674
libsigrokdecode4DSL/COPYING
Normal 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
2318
libsigrokdecode4DSL/Doxyfile
Normal file
File diff suppressed because it is too large
Load Diff
200
libsigrokdecode4DSL/HACKING
Normal file
200
libsigrokdecode4DSL/HACKING
Normal 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.
|
||||
|
96
libsigrokdecode4DSL/Makefile.am
Normal file
96
libsigrokdecode4DSL/Makefile.am
Normal 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
223
libsigrokdecode4DSL/NEWS
Normal 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
101
libsigrokdecode4DSL/README
Normal 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
24
libsigrokdecode4DSL/autogen.sh
Executable 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"
|
161
libsigrokdecode4DSL/configure.ac
Normal file
161
libsigrokdecode4DSL/configure.ac
Normal 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
|
BIN
libsigrokdecode4DSL/contrib/sigrok-logo-notext.png
Normal file
BIN
libsigrokdecode4DSL/contrib/sigrok-logo-notext.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.4 KiB |
856
libsigrokdecode4DSL/decoder.c
Normal file
856
libsigrokdecode4DSL/decoder.c
Normal 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;
|
||||
}
|
||||
|
||||
/** @} */
|
26
libsigrokdecode4DSL/decoders/0-i2c/__init__.py
Executable file
26
libsigrokdecode4DSL/decoders/0-i2c/__init__.py
Executable 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
|
343
libsigrokdecode4DSL/decoders/0-i2c/pd.py
Executable file
343
libsigrokdecode4DSL/decoders/0-i2c/pd.py
Executable 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
|
BIN
libsigrokdecode4DSL/decoders/0-spi/.pd.py.swo
Executable file
BIN
libsigrokdecode4DSL/decoders/0-spi/.pd.py.swo
Executable file
Binary file not shown.
BIN
libsigrokdecode4DSL/decoders/0-spi/.pd.py.swp
Executable file
BIN
libsigrokdecode4DSL/decoders/0-spi/.pd.py.swp
Executable file
Binary file not shown.
32
libsigrokdecode4DSL/decoders/0-spi/__init__.py
Executable file
32
libsigrokdecode4DSL/decoders/0-spi/__init__.py
Executable 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
|
293
libsigrokdecode4DSL/decoders/0-spi/pd.py
Executable file
293
libsigrokdecode4DSL/decoders/0-spi/pd.py
Executable 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
|
BIN
libsigrokdecode4DSL/decoders/0-uart/.pd.py.swo
Executable file
BIN
libsigrokdecode4DSL/decoders/0-uart/.pd.py.swo
Executable file
Binary file not shown.
BIN
libsigrokdecode4DSL/decoders/0-uart/.pd.py.swp
Executable file
BIN
libsigrokdecode4DSL/decoders/0-uart/.pd.py.swp
Executable file
Binary file not shown.
41
libsigrokdecode4DSL/decoders/0-uart/__init__.py
Executable file
41
libsigrokdecode4DSL/decoders/0-uart/__init__.py
Executable 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
|
311
libsigrokdecode4DSL/decoders/0-uart/pd.py
Executable file
311
libsigrokdecode4DSL/decoders/0-uart/pd.py
Executable 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
|
BIN
libsigrokdecode4DSL/decoders/1-i2c/.pd.py.swo
Executable file
BIN
libsigrokdecode4DSL/decoders/1-i2c/.pd.py.swo
Executable file
Binary file not shown.
BIN
libsigrokdecode4DSL/decoders/1-i2c/.pd.py.swp
Executable file
BIN
libsigrokdecode4DSL/decoders/1-i2c/.pd.py.swp
Executable file
Binary file not shown.
26
libsigrokdecode4DSL/decoders/1-i2c/__init__.py
Executable file
26
libsigrokdecode4DSL/decoders/1-i2c/__init__.py
Executable 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
|
341
libsigrokdecode4DSL/decoders/1-i2c/pd.py
Executable file
341
libsigrokdecode4DSL/decoders/1-i2c/pd.py
Executable 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
|
BIN
libsigrokdecode4DSL/decoders/1-spi/.pd.py.swn
Executable file
BIN
libsigrokdecode4DSL/decoders/1-spi/.pd.py.swn
Executable file
Binary file not shown.
BIN
libsigrokdecode4DSL/decoders/1-spi/.pd.py.swo
Executable file
BIN
libsigrokdecode4DSL/decoders/1-spi/.pd.py.swo
Executable file
Binary file not shown.
BIN
libsigrokdecode4DSL/decoders/1-spi/.pd.py.swp
Executable file
BIN
libsigrokdecode4DSL/decoders/1-spi/.pd.py.swp
Executable file
Binary file not shown.
32
libsigrokdecode4DSL/decoders/1-spi/__init__.py
Executable file
32
libsigrokdecode4DSL/decoders/1-spi/__init__.py
Executable 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
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user