2
0
forked from Ivasoft/DSView

Add more decoders

This commit is contained in:
DreamSourceLab
2018-05-27 17:10:57 +08:00
parent 95e17968d1
commit 5a806e496f
62 changed files with 3020 additions and 1077 deletions

View File

@@ -29,6 +29,7 @@
/libtool
/version.h
__pycache__/
*.pyc
stamp-h?
# Files generated by the testsuite

View File

@@ -23,7 +23,12 @@ AM_LIBTOOLFLAGS = --silent
GNUMAKEFLAGS = --no-print-directory
DECODERS_DIR = $(pkgdatadir)/decoders
# Do not hard-code the decoders location on Windows.
if WIN32
AM_CPPFLAGS =
else
AM_CPPFLAGS = -DDECODERS_DIR='"$(DECODERS_DIR)"'
endif
# The tests CFLAGS are a superset of the libsigrokdecode CFLAGS.
AM_CFLAGS = $(SRD_EXTRA_CFLAGS) $(SRD_WFLAGS) $(TESTS_CFLAGS)
@@ -70,7 +75,7 @@ tests_main_SOURCES = \
tests/inst.c \
tests/session.c
tests_main_CPPFLAGS = -DDECODERS_DIR='"$(abs_top_srcdir)/decoders"'
tests_main_CPPFLAGS = -DDECODERS_TESTDIR='"$(abs_top_srcdir)/decoders"'
tests_main_LDADD = libsigrokdecode4DSL.la $(SRD_EXTRA_LIBS) $(TESTS_LIBS)
MAINTAINERCLEANFILES = ChangeLog

View File

@@ -21,7 +21,7 @@
AC_PREREQ([2.63])
# libsigrokdecode package version number (NOT the same as shared lib version!).
AC_INIT([libsigrokdecode4DSL], [0.4.0],
AC_INIT([libsigrokdecode4DSL], [0.5.0],
[support@dreamsourcelab.com], [libsigrokdecode4DSL],
[http://www.dreamsourcelab.com])
AC_CONFIG_MACRO_DIR([m4])
@@ -62,7 +62,10 @@ SR_PKG_VERSION_SET([SRD_PACKAGE_VERSION], [AC_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])
# Format: current:revision:age.
SR_LIB_VERSION_SET([SRD_LIB_VERSION], [3:0:0])
AM_CONDITIONAL([WIN32], [test -z "${host_os##mingw*}" || test -z "${host_os##cygwin*}"])
############################
## Package dependencies ##
@@ -83,14 +86,14 @@ 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])
[python3 >= 3.2], [python-3.5 >= 3.5], [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])
AC_CHECK_PROGS([PYTHON3], [python3.5 python3.4 python3.3 python3.2 python3])
AS_IF([test "x$PYTHON3" = x],
[AC_MSG_ERROR([Cannot find Python 3 interpreter.])])
@@ -128,7 +131,7 @@ 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([LIBSIGROKDECODE], [glib-2.0 >= 2.28.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`
@@ -154,7 +157,7 @@ Compile configuration:
- C compiler warnings............. $SRD_WFLAGS
Detected libraries (required):
- glib-2.0 >= 2.24.0.............. $srd_glib_version
- glib-2.0 >= 2.28.0.............. $srd_glib_version
$srd_pkglibs_summary
Detected libraries (optional):
$srd_pkglibs_opt_summary

View File

@@ -156,21 +156,21 @@ static void decoder_free(struct srd_decoder *dec)
if (!dec)
return;
Py_XDECREF(dec->py_dec);
Py_XDECREF(dec->py_mod);
Py_XDECREF(dec->py_dec);
Py_XDECREF(dec->py_mod);
g_slist_free_full(dec->options, &decoder_option_free);
g_slist_free_full(dec->binary, (GDestroyNotify)&g_strfreev);
g_slist_free_full(dec->annotation_rows, &annotation_row_free);
g_slist_free_full(dec->annotations, (GDestroyNotify)&g_strfreev);
g_slist_free_full(dec->opt_channels, &channel_free);
g_slist_free_full(dec->channels, &channel_free);
g_slist_free_full(dec->options, &decoder_option_free);
g_slist_free_full(dec->binary, (GDestroyNotify)&g_strfreev);
g_slist_free_full(dec->annotation_rows, &annotation_row_free);
g_slist_free_full(dec->annotations, (GDestroyNotify)&g_strfreev);
g_slist_free_full(dec->opt_channels, &channel_free);
g_slist_free_full(dec->channels, &channel_free);
g_free(dec->license);
g_free(dec->desc);
g_free(dec->longname);
g_free(dec->name);
g_free(dec->id);
g_free(dec->license);
g_free(dec->desc);
g_free(dec->longname);
g_free(dec->name);
g_free(dec->id);
g_free(dec);
}
@@ -215,14 +215,14 @@ static int get_channels(const struct srd_decoder *d, const char *attr,
if (py_dictitem_as_str(py_entry, "id", &pdch->id) != SRD_OK)
goto err_out;
if (py_dictitem_as_str(py_entry, "name", &pdch->name) != SRD_OK)
if (py_dictitem_as_str(py_entry, "name", &pdch->name) != SRD_OK)
goto err_out;
if (py_dictitem_as_str(py_entry, "desc", &pdch->desc) != SRD_OK)
goto err_out;
pdch->type = py_dictitem_to_int(py_entry, "type");
if (pdch->type < 0)
pdch->type = SRD_CHANNEL_COMMON;
pdch->type = py_dictitem_to_int(py_entry, "type");
if (pdch->type < 0)
pdch->type = SRD_CHANNEL_COMMON;
pdch->order = offset + i;
}
@@ -232,7 +232,7 @@ static int get_channels(const struct srd_decoder *d, const char *attr,
return SRD_OK;
except_out:
srd_exception_catch(NULL, "Failed to get %s list of %s decoder",
srd_exception_catch(NULL, "Failed to get %s list of %s decoder",
attr, d->name);
err_out:
g_slist_free_full(pdchl, &channel_free);
@@ -348,7 +348,7 @@ static int get_options(struct srd_decoder *d)
return SRD_OK;
except_out:
srd_exception_catch(NULL, "Failed to get %s decoder options", d->name);
srd_exception_catch(NULL, "Failed to get %s decoder options", d->name);
err_out:
g_slist_free_full(options, &decoder_option_free);
Py_XDECREF(py_opts);
@@ -364,8 +364,8 @@ static int get_annotations(struct srd_decoder *dec)
GSList *annotations;
char **annpair;
ssize_t i;
int ann_type = 7;
unsigned int j;
int ann_type = 7;
unsigned int j;
if (!PyObject_HasAttrString(dec->py_dec, "annotations"))
return SRD_OK;
@@ -382,7 +382,7 @@ static int get_annotations(struct srd_decoder *dec)
goto err_out;
}
for (i = 0; i < PyTuple_Size(py_annlist); i++) {
for (i = 0; i < PyTuple_Size(py_annlist); i++) {
py_ann = PyTuple_GetItem(py_annlist, i);
if (!py_ann)
goto except_out;
@@ -390,7 +390,7 @@ static int get_annotations(struct srd_decoder *dec)
if (!PyTuple_Check(py_ann) || (PyTuple_Size(py_ann) != 3 && PyTuple_Size(py_ann) != 2)) {
srd_err("Protocol decoder %s annotation %zd should "
"be a tuple with two or three elements.",
dec->name, i);
dec->name, i + 1);
goto err_out;
}
if (py_strseq_to_char(py_ann, &annpair) != SRD_OK)
@@ -399,14 +399,14 @@ static int get_annotations(struct srd_decoder *dec)
annotations = g_slist_prepend(annotations, annpair);
if (PyTuple_Size(py_ann) == 3) {
ann_type = 0;
for (j = 0; j < strlen(annpair[0]); j++)
ann_type = ann_type * 10 + (annpair[0][j] - '0');
dec->ann_types = g_slist_append(dec->ann_types, GINT_TO_POINTER(ann_type));
} else if (PyTuple_Size(py_ann) == 2) {
dec->ann_types = g_slist_append(dec->ann_types, GINT_TO_POINTER(ann_type));
ann_type++;
}
ann_type = 0;
for (j = 0; j < strlen(annpair[0]); j++)
ann_type = ann_type * 10 + (annpair[0][j] - '0');
dec->ann_types = g_slist_append(dec->ann_types, GINT_TO_POINTER(ann_type));
} else if (PyTuple_Size(py_ann) == 2) {
dec->ann_types = g_slist_append(dec->ann_types, GINT_TO_POINTER(ann_type));
ann_type++;
}
}
dec->annotations = annotations;
Py_DECREF(py_annlist);
@@ -414,7 +414,7 @@ static int get_annotations(struct srd_decoder *dec)
return SRD_OK;
except_out:
srd_exception_catch(NULL, "Failed to get %s decoder annotations", dec->name);
srd_exception_catch(NULL, "Failed to get %s decoder annotations", dec->name);
err_out:
g_slist_free_full(annotations, (GDestroyNotify)&g_strfreev);
Py_XDECREF(py_annlist);
@@ -510,7 +510,7 @@ static int get_annotation_rows(struct srd_decoder *dec)
return SRD_OK;
except_out:
srd_exception_catch(NULL, "Failed to get %s decoder annotation rows",
srd_exception_catch(NULL, "Failed to get %s decoder annotation rows",
dec->name);
err_out:
g_slist_free_full(annotation_rows, &annotation_row_free);
@@ -566,7 +566,7 @@ static int get_binary_classes(struct srd_decoder *dec)
return SRD_OK;
except_out:
srd_exception_catch(NULL, "Failed to get %s decoder binary classes",
srd_exception_catch(NULL, "Failed to get %s decoder binary classes",
dec->name);
err_out:
g_slist_free_full(bin_classes, (GDestroyNotify)&g_strfreev);
@@ -585,8 +585,8 @@ static int check_method(PyObject *py_dec, const char *mod_name,
py_method = PyObject_GetAttrString(py_dec, method_name);
if (!py_method) {
srd_exception_catch(NULL, "Protocol decoder %s Decoder class "
"has no %s() method", mod_name, method_name);
srd_exception_catch(NULL, "Protocol decoder %s Decoder class "
"has no %s() method", mod_name, method_name);
return SRD_ERR_PYTHON;
}
@@ -636,12 +636,12 @@ SRD_PRIV long srd_decoder_apiver(const struct srd_decoder *d)
*/
SRD_API int srd_decoder_load(const char *module_name)
{
PyObject *py_basedec;
PyObject *py_basedec;
struct srd_decoder *d;
long apiver;
int is_subclass;
const char *fail_txt;
if (!srd_check_init())
return SRD_ERR;
@@ -699,8 +699,8 @@ SRD_API int srd_decoder_load(const char *module_name)
*/
apiver = srd_decoder_apiver(d);
if (apiver != 2) {
srd_exception_catch(NULL, "Only PD API version 2 is supported, "
"decoder %s has version %ld", module_name, apiver);
srd_exception_catch(NULL, "Only PD API version 2 is supported, "
"decoder %s has version %ld", module_name, apiver);
fail_txt = "API version mismatch";
goto err_out;
}
@@ -776,7 +776,7 @@ SRD_API int srd_decoder_load(const char *module_name)
fail_txt = "cannot get binary classes";
goto err_out;
}
/* Append it to the list of loaded decoders. */
pd_list = g_slist_append(pd_list, d);
@@ -784,11 +784,11 @@ SRD_API int srd_decoder_load(const char *module_name)
except_out:
if (fail_txt) {
srd_exception_catch(NULL, "Failed to load decoder %s: %s",
srd_exception_catch(NULL, "Failed to load decoder %s: %s",
module_name, fail_txt);
fail_txt = NULL;
} else {
srd_exception_catch(NULL, "Failed to load decoder %s", module_name);
srd_exception_catch(NULL, "Failed to load decoder %s", module_name);
}
err_out:
if (fail_txt)
@@ -823,7 +823,7 @@ SRD_API char *srd_decoder_doc_get(const struct srd_decoder *dec)
return NULL;
if (!(py_str = PyObject_GetAttrString(dec->py_mod, "__doc__"))) {
srd_exception_catch(NULL, "Failed to get docstring");
srd_exception_catch(NULL, "Failed to get docstring");
return NULL;
}

View File

@@ -250,7 +250,7 @@ class Decoder(srd.Decoder):
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_oldclk = 0
self.exp_clk = 1
else:
self.exp_oldclk = 1
@@ -272,7 +272,7 @@ class Decoder(srd.Decoder):
#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 = []
@@ -288,6 +288,6 @@ class Decoder(srd.Decoder):
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.handle_bit(miso, mosi, clk, cs)
self.oldclk, self.oldcs = clk, cs

View File

@@ -281,7 +281,7 @@ class Decoder(srd.Decoder):
(signal,) = pins
if self.options['invert'] == 'yes':
signal = not signal
signal = not signal
# State machine.
if self.state == 'FIND START':

View File

@@ -179,7 +179,7 @@ class Decoder(srd.Decoder):
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
self.bits[0][2] += self.bitwidth
# Return if we haven't collected all 8 + 1 bits, yet.
if self.bitcount < 7:
@@ -233,7 +233,7 @@ class Decoder(srd.Decoder):
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
self.bits[0][2] += self.bitwidth
# Return if we haven't collected all 8 + 1 bits, yet.
if self.bitcount < 7:

View File

@@ -252,7 +252,7 @@ class Decoder(srd.Decoder):
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_oldclk = 0
self.exp_clk = 1
else:
self.exp_oldclk = 1
@@ -273,7 +273,7 @@ class Decoder(srd.Decoder):
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 = []
@@ -289,6 +289,6 @@ class Decoder(srd.Decoder):
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.handle_bit(miso, mosi, clk, cs)
self.oldclk, self.oldcs = clk, cs

View File

@@ -281,7 +281,7 @@ class Decoder(srd.Decoder):
(signal,) = pins
if self.options['invert'] == 'yes':
signal = not signal
signal = not signal
# State machine.
if self.state == 'FIND START':

View File

@@ -47,7 +47,7 @@ class Decoder(srd.Decoder):
self.syncbuf = []
self.prevsample = 0
self.stream = 0
self.stream_ss = None
self.ss_stream = None
self.bytenum = 0
def start(self):
@@ -57,10 +57,10 @@ class Decoder(srd.Decoder):
def stream_changed(self, ss, stream):
if self.stream != stream:
if self.stream != 0:
self.put(self.stream_ss, ss, self.out_ann,
self.put(self.ss_stream, ss, self.out_ann,
[0, ['Stream %d' % self.stream, 'S%d' % self.stream]])
self.stream = stream
self.stream_ss = ss
self.ss_stream = ss
def emit_byte(self, ss, es, byte):
if self.stream == self.options['stream']:

View File

@@ -0,0 +1,20 @@
##
## This file is part of the libsigrokdecode project.
##
## Copyright (C) 2016 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
##

View File

@@ -0,0 +1,20 @@
##
## This file is part of the libsigrokdecode project.
##
## Copyright (C) 2016 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/>.
##
from .mod import *

View File

@@ -0,0 +1,192 @@
##
## This file is part of the libsigrokdecode project.
##
## Copyright (C) 2016 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/>.
##
# This module contains definitions for use by pluggable network adapters,
# such as SFP, XFP etc.
MODULE_ID = {
0x01: 'GBIC',
0x02: 'Integrated module/connector',
0x03: 'SFP',
0x04: '300-pin XBI',
0x05: 'XENPAK',
0x06: 'XFP',
0x07: 'XFF',
0x08: 'XFP-E',
0x09: 'XPAK',
0x0a: 'X2',
}
ALARM_THRESHOLDS = {
0: 'Temp high alarm',
2: 'Temp low alarm',
4: 'Temp high warning',
6: 'Temp low warning',
16: 'Bias high alarm',
18: 'Bias low alarm',
20: 'Bias high warning',
22: 'Bias low warning',
24: 'TX power high alarm',
26: 'TX power low alarm',
28: 'TX power high warning',
30: 'TX power low warning',
32: 'RX power high alarm',
34: 'RX power low alarm',
36: 'RX power high warning',
38: 'RX power low warning',
40: 'AUX 1 high alarm',
42: 'AUX 1 low alarm',
44: 'AUX 1 high warning',
46: 'AUX 1 low warning',
48: 'AUX 2 high alarm',
50: 'AUX 2 low alarm',
52: 'AUX 2 high warning',
54: 'AUX 2 low warning',
}
AD_READOUTS = {
0: 'Module temperature',
4: 'TX bias current',
6: 'Measured TX output power',
8: 'Measured RX input power',
10: 'AUX 1 measurement',
12: 'AUX 2 measurement',
}
GCS_BITS = [
'TX disable',
'Soft TX disable',
'MOD_NR',
'P_Down',
'Soft P_Down',
'Interrupt',
'RX_LOS',
'Data_Not_Ready',
'TX_NR',
'TX_Fault',
'TX_CDR not locked',
'RX_NR',
'RX_CDR not locked',
]
CONNECTOR = {
0x01: 'SC',
0x02: 'Fibre Channel style 1 copper',
0x03: 'Fibre Channel style 2 copper',
0x04: 'BNC/TNC',
0x05: 'Fibre Channel coax',
0x06: 'FiberJack',
0x07: 'LC',
0x08: 'MT-RJ',
0x09: 'MU',
0x0a: 'SG',
0x0b: 'Optical pigtail',
0x20: 'HSSDC II',
0x21: 'Copper pigtail',
}
TRANSCEIVER = [
# 10GB Ethernet
['10GBASE-SR', '10GBASE-LR', '10GBASE-ER', '10GBASE-LRM', '10GBASE-SW',
'10GBASE-LW', '10GBASE-EW'],
# 10GB Fibre Channel
['1200-MX-SN-I', '1200-SM-LL-L', 'Extended Reach 1550 nm',
'Intermediate reach 1300 nm FP'],
# 10GB Copper
[],
# 10GB low speed
['1000BASE-SX / 1xFC MMF', '1000BASE-LX / 1xFC SMF', '2xFC MMF',
'2xFC SMF', 'OC48-SR', 'OC48-IR', 'OC48-LR'],
# 10GB SONET/SDH interconnect
['I-64.1r', 'I-64.1', 'I-64.2r', 'I-64.2', 'I-64.3', 'I-64.5'],
# 10GB SONET/SDH short haul
['S-64.1', 'S-64.2a', 'S-64.2b', 'S-64.3a', 'S-64.3b', 'S-64.5a', 'S-64.5b'],
# 10GB SONET/SDH long haul
['L-64.1', 'L-64.2a', 'L-64.2b', 'L-64.2c', 'L-64.3', 'G.959.1 P1L1-2D2'],
# 10GB SONET/SDH very long haul
['V-64.2a', 'V-64.2b', 'V-64.3'],
]
SERIAL_ENCODING = [
'64B/66B',
'8B/10B',
'SONET scrambled',
'NRZ',
'RZ',
]
XMIT_TECH = [
'850 nm VCSEL',
'1310 nm VCSEL',
'1550 nm VCSEL',
'1310 nm FP',
'1310 nm DFB',
'1550 nm DFB',
'1310 nm EML'
'1550 nm EML'
'copper',
]
CDR = [
'9.95Gb/s',
'10.3Gb/s',
'10.5Gb/s',
'10.7Gb/s',
'11.1Gb/s',
'(unknown)',
'lineside loopback mode',
'XFI loopback mode',
]
DEVICE_TECH = [
['no wavelength control', 'sctive wavelength control'],
['uncooled transmitter device', 'cooled transmitter'],
['PIN detector', 'APD detector'],
['transmitter not tunable', 'transmitter tunable'],
]
ENHANCED_OPTS = [
'VPS',
'soft TX_DISABLE',
'soft P_Down',
'VPS LV regulator mode',
'VPS bypassed regulator mode',
'active FEC control',
'wavelength tunability',
'CMU',
]
AUX_TYPES = [
'not implemented',
'APD bias voltage',
'(unknown)',
'TEC current',
'laser temperature',
'laser wavelength',
'5V supply voltage',
'3.3V supply voltage',
'1.8V supply voltage',
'-5.2V supply voltage',
'5V supply current',
'(unknown)',
'(unknown)',
'3.3V supply current',
'1.8V supply current',
'-5.2V supply current',
]

View File

@@ -0,0 +1,21 @@
##
## This file is part of the libsigrokdecode project.
##
## Copyright (C) 2012-2014 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
##
from .mod import *

View File

@@ -0,0 +1,186 @@
##
## This file is part of the libsigrokdecode project.
##
## Copyright (C) 2012-2014 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
##
# Normal commands (CMD)
# Unlisted items are 'Reserved' as per SD spec. The 'Unknown' items don't
# seem to be mentioned in the spec, but aren't marked as reserved either.
cmd_names = {
0: 'GO_IDLE_STATE',
1: 'SEND_OP_COND', # Reserved in SD mode
2: 'ALL_SEND_CID',
3: 'SEND_RELATIVE_ADDR',
4: 'SET_DSR',
5: 'IO_SEND_OP_COND', # SDIO-only
6: 'SWITCH_FUNC', # New since spec 1.10
7: 'SELECT/DESELECT_CARD',
8: 'SEND_IF_COND',
9: 'SEND_CSD',
10: 'SEND_CID',
11: 'VOLTAGE_SWITCH',
12: 'STOP_TRANSMISSION',
13: 'SEND_STATUS',
# 14: Reserved
15: 'GO_INACTIVE_STATE',
16: 'SET_BLOCKLEN',
17: 'READ_SINGLE_BLOCK',
18: 'READ_MULTIPLE_BLOCK',
19: 'SEND_TUNING_BLOCK',
20: 'SPEED_CLASS_CONTROL',
# 21-22: Reserved
23: 'SET_BLOCK_COUNT',
24: 'WRITE_BLOCK',
25: 'WRITE_MULTIPLE_BLOCK',
26: 'Reserved for manufacturer',
27: 'PROGRAM_CSD',
28: 'SET_WRITE_PROT',
29: 'CLR_WRITE_PROT',
30: 'SEND_WRITE_PROT',
# 31: Reserved
32: 'ERASE_WR_BLK_START', # SPI mode: ERASE_WR_BLK_START_ADDR
33: 'ERASE_WR_BLK_END', # SPI mode: ERASE_WR_BLK_END_ADDR
34: 'Reserved for CMD6', # New since spec 1.10
35: 'Reserved for CMD6', # New since spec 1.10
36: 'Reserved for CMD6', # New since spec 1.10
37: 'Reserved for CMD6', # New since spec 1.10
38: 'ERASE',
# 39: Reserved
40: 'Reserved for security specification',
# 41: Reserved
42: 'LOCK_UNLOCK',
# 43-49: Reserved
50: 'Reserved for CMD6', # New since spec 1.10
# 51: Reserved
52: 'IO_RW_DIRECT', # SDIO-only
53: 'IO_RW_EXTENDED', # SDIO-only
54: 'Unknown',
55: 'APP_CMD',
56: 'GEN_CMD',
57: 'Reserved for CMD6', # New since spec 1.10
58: 'READ_OCR', # Reserved in SD mode
59: 'CRC_ON_OFF', # Reserved in SD mode
60: 'Reserved for manufacturer',
61: 'Reserved for manufacturer',
62: 'Reserved for manufacturer',
63: 'Reserved for manufacturer',
}
# Application-specific commands (ACMD)
# Unlisted items are 'Reserved' as per SD spec. The 'Unknown' items don't
# seem to be mentioned in the spec, but aren't marked as reserved either.
acmd_names = {
# 1-5: Reserved
6: 'SET_BUS_WIDTH',
# 7-12: Reserved
13: 'SD_STATUS',
14: 'Reserved for Security Application',
15: 'Reserved for Security Application',
16: 'Reserved for Security Application',
# 17: Reserved
18: 'Reserved for SD security applications',
# 19-21: Reserved
22: 'SEND_NUM_WR_BLOCKS',
23: 'SET_WR_BLK_ERASE_COUNT',
# 24: Reserved
25: 'Reserved for SD security applications',
26: 'Reserved for SD security applications',
27: 'Reserved for security specification',
28: 'Reserved for security specification',
# 29: Reserved
30: 'Reserved for security specification',
31: 'Reserved for security specification',
32: 'Reserved for security specification',
33: 'Reserved for security specification',
34: 'Reserved for security specification',
35: 'Reserved for security specification',
# 36-37: Reserved
38: 'Reserved for SD security applications',
# 39-40: Reserved
41: 'SD_SEND_OP_COND',
42: 'SET_CLR_CARD_DETECT',
43: 'Reserved for SD security applications',
44: 'Reserved for SD security applications',
45: 'Reserved for SD security applications',
46: 'Reserved for SD security applications',
47: 'Reserved for SD security applications',
48: 'Reserved for SD security applications',
49: 'Reserved for SD security applications',
50: 'Unknown',
51: 'SEND_SCR',
52: 'Reserved for security specification',
53: 'Reserved for security specification',
54: 'Reserved for security specification',
55: 'Non-existant', # Doesn't exist (equivalent to CMD55)
56: 'Reserved for security specification',
57: 'Reserved for security specification',
58: 'Reserved for security specification',
59: 'Reserved for security specification',
60: 'Unknown',
61: 'Unknown',
62: 'Unknown',
63: 'Unknown',
}
accepted_voltages = {
0b0001: '2.7-3.6V',
0b0010: 'reserved for low voltage range',
0b0100: 'reserved',
0b1000: 'reserved',
# All other values: "not defined".
}
card_status = {
0: 'Reserved for manufacturer test mode',
1: 'Reserved for manufacturer test mode',
2: 'Reserved for application specific commands',
3: 'AKE_SEQ_ERROR',
4: 'Reserved for SDIO card',
5: 'APP_CMD',
6: 'Unknown',
7: 'Unknown',
8: 'READY_FOR_DATA',
9: 'CURRENT_STATE', # CURRENT_STATE is a 4-bit value (decimal: 0..15).
10: 'CURRENT_STATE',
11: 'CURRENT_STATE',
12: 'CURRENT_STATE',
13: 'ERASE_RESET',
14: 'CARD_ECC_DISABLED',
15: 'WP_ERASE_SKIP',
16: 'CSD_OVERWRITE',
17: 'Reserved for DEFERRED_RESPONSE', # See eSD addendum
18: 'Reserved',
19: 'ERROR',
20: 'CC_ERROR',
21: 'CARD_ECC_FAILED',
22: 'ILLEGAL_COMMAND',
23: 'COM_CRC_ERROR',
24: 'LOCK_UNLOCK_FAILED',
25: 'CARD_IS_LOCKED',
26: 'WP_VIOLATION',
27: 'ERASE_PARAM',
28: 'ERASE_SEQ_ERROR',
29: 'BLOCK_LEN_ERROR',
30: 'ADDRESS_ERROR',
31: 'OUT_OF_RANGE',
}
sd_status = {
# 311:0: Reserved for manufacturer
# 391:312: Reserved
}

View File

@@ -0,0 +1,21 @@
##
## This file is part of the libsigrokdecode project.
##
## Copyright (C) 2012-2014 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
##
from .mod import *

View File

@@ -0,0 +1,23 @@
##
## This file is part of the libsigrokdecode project.
##
## Copyright (C) 2012-2014 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
##
# Return the specified BCD number (max. 8 bits) as integer.
def bcd2int(b):
return (b & 0x0f) + ((b >> 4) * 10)

View File

@@ -20,10 +20,7 @@
import sigrokdecode as srd
import calendar
# Return the specified BCD number (max. 8 bits) as integer.
def bcd2int(b):
return (b & 0x0f) + ((b >> 4) * 10)
from common.srdhelper import bcd2int
class SamplerateError(Exception):
pass
@@ -68,7 +65,7 @@ class Decoder(srd.Decoder):
('warnings', 'Warnings', (19,)),
)
def __init__(self, **kwargs):
def __init__(self):
self.samplerate = None
self.state = 'WAIT FOR RISING EDGE'
self.oldpins = None

View File

@@ -14,7 +14,8 @@
## 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/>.
## along with this program; if not, write to the Free Software
## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
##
'''

View File

@@ -14,7 +14,8 @@
## 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/>.
## 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

View File

@@ -21,6 +21,7 @@
import re
import sigrokdecode as srd
from common.srdhelper import bcd2int
days_of_week = (
'Sunday', 'Monday', 'Tuesday', 'Wednesday',
@@ -51,10 +52,6 @@ def regs_and_bits():
l += [('bit-' + re.sub('\/| ', '-', b).lower(), b + ' bit') for b in bits]
return tuple(l)
# Return the specified BCD number (max. 8 bits) as integer.
def bcd2int(b):
return (b & 0x0f) + ((b >> 4) * 10)
class Decoder(srd.Decoder):
api_version = 2
id = 'ds1307'
@@ -78,7 +75,7 @@ class Decoder(srd.Decoder):
('warnings', 'Warnings', (28,)),
)
def __init__(self, **kwargs):
def __init__(self):
self.state = 'IDLE'
self.hours = -1
self.minutes = -1

View File

@@ -73,12 +73,12 @@ class Decoder(srd.Decoder):
('binary', 'Binary'),
)
def __init__(self, **kwargs):
def __init__(self):
self.reset()
def start(self):
self.out_ann = self.register(srd.OUTPUT_ANN)
self.out_bin = self.register(srd.OUTPUT_BINARY)
self.out_binary = self.register(srd.OUTPUT_BINARY)
self.chip = chips[self.options['chip']]
self.addr_counter = self.options['addr_counter']
@@ -86,7 +86,7 @@ class Decoder(srd.Decoder):
self.put(self.ss_block, self.es_block, self.out_ann, data)
def putbin(self, data):
self.put(self.ss_block, self.es_block, self.out_bin, data)
self.put(self.ss_block, self.es_block, self.out_binary, data)
def putbits(self, bit1, bit2, bits, data):
self.put(bits[bit1][1], bits[bit2][2], self.out_ann, data)
@@ -165,7 +165,7 @@ class Decoder(srd.Decoder):
self.putb([cls, ['%s (%s): %s' % (s, self.addr_and_len(), \
self.hexbytes(self.chip['addr_bytes'])),
'%s (%s)' % (s, self.addr_and_len()), s, a, s[0]]])
self.putbin((0, bytes(self.bytebuf[self.chip['addr_bytes']:])))
self.putbin([0, bytes(self.bytebuf[self.chip['addr_bytes']:])])
def addr_and_len(self):
if self.chip['addr_bytes'] == 1:
@@ -215,7 +215,7 @@ class Decoder(srd.Decoder):
[8, ['Data', 'D']])
self.putb([11, ['Current address read: %02X' % self.bytebuf[0],
'Current address read', 'Cur addr read', 'CAR', 'C']])
self.putbin((0, bytes([self.bytebuf[0]])))
self.putbin([0, bytes([self.bytebuf[0]])])
self.addr_counter += 1
elif self.is_random_access_read:
# Random access read: word address, one data byte.

View File

@@ -74,12 +74,12 @@ class Decoder(srd.Decoder):
self.oldpl = 0
self.oldsamplenum = 0
self.last_bit_pos = 0
self.first_ss = 0
self.ss_first = 0
self.first_one = 0
self.state = 'HEADER'
self.data = 0
self.data_bits = 0
self.data_ss = 0
self.ss_data = 0
self.data_parity = 0
self.payload_cnt = 0
self.data_col_parity = [0, 0, 0, 0, 0, 0]
@@ -105,14 +105,14 @@ class Decoder(srd.Decoder):
if self.first_one > 0:
self.first_one += 1
if self.first_one == 9:
self.put(self.first_ss, es, self.out_ann,
self.put(self.ss_first, es, self.out_ann,
[1, ['Header', 'Head', 'He', 'H']])
self.first_one = 0
self.state = 'PAYLOAD'
return
if self.first_one == 0:
self.first_one = 1
self.first_ss = ss
self.ss_first = ss
if bit == 0:
self.first_one = 0
@@ -121,14 +121,14 @@ class Decoder(srd.Decoder):
if self.state == 'PAYLOAD':
self.payload_cnt += 1
if self.data_bits == 0:
self.data_ss = ss
self.ss_data = ss
self.data = 0
self.data_parity = 0
self.data_bits += 1
if self.data_bits == 5:
s = 'Version/customer' if self.payload_cnt <= 10 else 'Data'
c = 2 if self.payload_cnt <= 10 else 3
self.put(self.data_ss, ss, self.out_ann,
self.put(self.ss_data, ss, self.out_ann,
[c, [s + ': %X' % self.data, '%X' % self.data]])
s = 'OK' if self.data_parity == bit else 'ERROR'
c = 4 if s == 'OK' else 5
@@ -150,7 +150,7 @@ class Decoder(srd.Decoder):
if self.state == 'TRAILER':
self.payload_cnt += 1
if self.data_bits == 0:
self.data_ss = ss
self.ss_data = ss
self.data = 0
self.data_parity = 0
self.data_bits += 1
@@ -172,7 +172,7 @@ class Decoder(srd.Decoder):
# Emit an annotation for valid-looking tags.
all_col_parity_ok = (self.data_col_parity[1:5] == self.col_parity[1:5])
if all_col_parity_ok and self.all_row_parity_ok:
self.put(self.first_ss, es, self.out_ann,
self.put(self.ss_first, es, self.out_ann,
[9, ['Tag: %010X' % self.tag, 'Tag', 'T']])
self.tag = 0

View File

@@ -0,0 +1,25 @@
##
## This file is part of the libsigrokdecode project.
##
## Copyright (C) 2015 Benjamin Larsson <benjamin@southpole.se>
##
## 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
##
'''
EM4305 is a 100-150kHz RFID protocol.
'''
from .pd import Decoder

View File

@@ -0,0 +1,397 @@
##
## This file is part of the libsigrokdecode project.
##
## Copyright (C) 2016 Benjamin Larsson <benjamin@southpole.se>
##
## 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
class SamplerateError(Exception):
pass
class Decoder(srd.Decoder):
api_version = 2
id = 'em4305'
name = 'EM4305'
longname = 'RFID EM4205/EM4305'
desc = 'EM4205/EM4305 100-150kHz RFID protocol.'
license = 'gplv2+'
inputs = ['logic']
outputs = ['em4305']
channels = (
{'id': 'data', 'name': 'Data', 'desc': 'Data line'},
)
options = (
{'id': 'coilfreq', 'desc': 'Coil frequency', 'default': 125000},
{'id': 'first_field_stop', 'desc': 'First field stop min', 'default': 40},
{'id': 'w_gap', 'desc': 'Write gap min', 'default': 12},
{'id': 'w_one_max', 'desc': 'Write one max', 'default': 32},
{'id': 'w_zero_on_min', 'desc': 'Write zero on min', 'default': 15},
{'id': 'w_zero_off_max', 'desc': 'Write zero off max', 'default': 27},
{'id': 'em4100_decode', 'desc': 'EM4100 decode', 'default': 'on',
'values': ('on', 'off')},
)
annotations = (
('bit_value', 'Bit value'),
('first_field_stop', 'First field stop'),
('write_gap', 'Write gap'),
('write_mode_exit', 'Write mode exit'),
('bit', 'Bit'),
('opcode', 'Opcode'),
('lock', 'Lock'),
('data', 'Data'),
('password', 'Password'),
('address', 'Address'),
('bitrate', 'Bitrate'),
)
annotation_rows = (
('bits', 'Bits', (0,)),
('structure', 'Structure', (1, 2, 3, 4)),
('fields', 'Fields', (5, 6, 7, 8, 9)),
('decode', 'Decode', (10,)),
)
def __init__(self):
self.samplerate = None
self.oldpin = None
self.last_samplenum = None
self.state = 'FFS_SEARCH'
self.bits_pos = [[0 for col in range(3)] for row in range(70)]
self.br_string = ['RF/8', 'RF/16', 'Unused', 'RF/32', 'RF/40',
'Unused', 'Unused', 'RF/64',]
self.encoder = ['not used', 'Manchester', 'Bi-phase', 'not used']
self.delayed_on = ['No delay', 'Delayed on - BP/8', 'Delayed on - BP/4', 'No delay']
self.em4100_decode1_partial = 0
self.cmds = ['Invalid', 'Login', 'Write word', 'Invalid', 'Read word', 'Disable', 'Protect', 'Invalid']
def metadata(self, key, value):
if key == srd.SRD_CONF_SAMPLERATE:
self.samplerate = value
self.field_clock = self.samplerate / self.options['coilfreq']
self.wzmax = self.options['w_zero_off_max'] * self.field_clock
self.wzmin = self.options['w_zero_on_min'] * self.field_clock
self.womax = self.options['w_one_max'] * self.field_clock
self.ffs = self.options['first_field_stop'] * self.field_clock
self.writegap = self.options['w_gap'] * self.field_clock
self.nogap = 300 * self.field_clock
def start(self):
self.out_ann = self.register(srd.OUTPUT_ANN)
def decode_config(self, idx):
bitrate = self.get_3_bits(idx+2)
self.put(self.bits_pos[idx][1], self.bits_pos[idx+5][2],
self.out_ann, [10, ['Data rate: ' + \
self.br_string[bitrate], self.br_string[bitrate]]])
encoding = self.bits_pos[idx+6][0]<<0 | self.bits_pos[idx+7][0]<<1
self.put(self.bits_pos[idx+6][1], self.bits_pos[idx+10][2],
self.out_ann, [10, ['Encoder: ' + \
self.encoder[encoding], self.encoder[encoding]]])
self.put(self.bits_pos[idx+11][1], self.bits_pos[idx+12][2], self.out_ann,
[10, ['Zero bits', 'ZB']])
delay_on = self.bits_pos[idx+13][0]<<0 | self.bits_pos[idx+14][0]<<1
self.put(self.bits_pos[idx+13][1], self.bits_pos[idx+14][2],
self.out_ann, [10, ['Delayed on: ' + \
self.delayed_on[delay_on], self.delayed_on[delay_on]]])
lwr = self.bits_pos[idx+15][0]<<3 | self.bits_pos[idx+16][0]<<2 | \
self.bits_pos[idx+18][0]<<1 | self.bits_pos[idx+19][0]<<0
self.put(self.bits_pos[idx+15][1], self.bits_pos[idx+19][2],
self.out_ann, [10, ['Last default read word: %d' % lwr, 'LWR: %d' % lwr, '%d' % lwr]])
self.put(self.bits_pos[idx+20][1], self.bits_pos[idx+20][2],
self.out_ann, [10, ['Read login: %d' % self.bits_pos[idx+20][0], '%d' % self.bits_pos[idx+20][0]]])
self.put(self.bits_pos[idx+21][1], self.bits_pos[idx+21][2], self.out_ann,
[10, ['Zero bits', 'ZB']])
self.put(self.bits_pos[idx+22][1], self.bits_pos[idx+22][2],
self.out_ann, [10, ['Write login: %d' % self.bits_pos[idx+22][0], '%d' % self.bits_pos[idx+22][0]]])
self.put(self.bits_pos[idx+23][1], self.bits_pos[idx+24][2], self.out_ann,
[10, ['Zero bits', 'ZB']])
self.put(self.bits_pos[idx+25][1], self.bits_pos[idx+25][2],
self.out_ann, [10, ['Disable: %d' % self.bits_pos[idx+25][0], '%d' % self.bits_pos[idx+25][0]]])
self.put(self.bits_pos[idx+27][1], self.bits_pos[idx+27][2],
self.out_ann, [10, ['Reader talk first: %d' % self.bits_pos[idx+27][0], 'RTF: %d' % self.bits_pos[idx+27][0]]])
self.put(self.bits_pos[idx+28][1], self.bits_pos[idx+28][2], self.out_ann,
[10, ['Zero bits', 'ZB']])
self.put(self.bits_pos[idx+29][1], self.bits_pos[idx+29][2],
self.out_ann, [10, ['Pigeon mode: %d' % self.bits_pos[idx+29][0], '%d' % self.bits_pos[idx+29][0]]])
self.put(self.bits_pos[idx+30][1], self.bits_pos[idx+34][2],
self.out_ann, [10, ['Reserved', 'Res', 'R']])
def put4bits(self, idx):
bits = self.bits_pos[idx][0]<<3 | self.bits_pos[idx+1][0]<<2 | \
self.bits_pos[idx+2][0]<<1 | self.bits_pos[idx+3][0]
self.put(self.bits_pos[idx][1], self.bits_pos[idx+3][2], self.out_ann,
[10, ['%X' % bits]])
def em4100_decode1(self, idx):
self.put(self.bits_pos[idx][1], self.bits_pos[idx+9][2], self.out_ann,
[10, ['EM4100 header', 'EM header', 'Header', 'H']])
self.put4bits(idx+10)
bits = self.bits_pos[idx+15][0]<<3 | self.bits_pos[idx+16][0]<<2 | \
self.bits_pos[idx+18][0]<<1 | self.bits_pos[idx+19][0]<<0
self.put(self.bits_pos[idx+15][1], self.bits_pos[idx+19][2], self.out_ann,
[10, ['%X' % bits]])
self.put4bits(idx+21)
self.put4bits(idx+27)
self.em4100_decode1_partial = self.bits_pos[idx+32][0]<<3 | \
self.bits_pos[idx+33][0]<<2 | self.bits_pos[idx+34][0]<<1
self.put(self.bits_pos[idx+32][1], self.bits_pos[idx+34][2],
self.out_ann, [10, ['Partial nibble']])
def em4100_decode2(self, idx):
if self.em4100_decode1_partial != 0:
bits = self.em4100_decode1_partial + self.bits_pos[idx][0]
self.put(self.bits_pos[idx][1], self.bits_pos[idx][2],
self.out_ann, [10, ['%X' % bits]])
self.em4100_decode1_partial = 0
else:
self.put(self.bits_pos[idx][1], self.bits_pos[idx][2],
self.out_ann, [10, ['Partial nibble']])
self.put4bits(idx+2)
bits = self.bits_pos[idx+7][0]<<3 | self.bits_pos[idx+9][0]<<2 | \
self.bits_pos[idx+10][0]<<1 | self.bits_pos[idx+11][0]<<0
self.put(self.bits_pos[idx+7][1], self.bits_pos[idx+11][2], self.out_ann,
[10, ['%X' % bits]])
self.put4bits(idx+13)
self.put4bits(idx+19)
bits = self.bits_pos[idx+24][0]<<3 | self.bits_pos[idx+25][0]<<2 | \
self.bits_pos[idx+27][0]<<1 | self.bits_pos[idx+28][0]<<0
self.put(self.bits_pos[idx+24][1], self.bits_pos[idx+28][2], self.out_ann,
[10, ['%X' % bits]])
self.put(self.bits_pos[idx+30][1], self.bits_pos[idx+34][2],
self.out_ann, [10, ['EM4100 trailer']])
def get_32_bits(self, idx):
return self.get_8_bits(idx+27)<<24 | self.get_8_bits(idx+18)<<16 | \
self.get_8_bits(idx+9)<<8 | self.get_8_bits(idx)
def get_8_bits(self, idx):
retval = 0
for i in range(0, 8):
retval <<= 1
retval |= self.bits_pos[i+idx][0]
return retval
def get_3_bits(self, idx):
return self.bits_pos[idx][0]<<2 | self.bits_pos[idx+1][0]<<1 | \
self.bits_pos[idx+2][0]
def get_4_bits(self, idx):
return self.bits_pos[idx][0]<<0 | self.bits_pos[idx+1][0]<<1 | \
self.bits_pos[idx+2][0]<<2 | self.bits_pos[idx+3][0]<<3
def print_row_parity(self, idx, length):
parity = 0
for i in range(0, length):
parity += self.bits_pos[i+idx][0]
parity = parity & 0x1
if parity == self.bits_pos[idx+length][0]:
self.put(self.bits_pos[idx+length][1], self.bits_pos[idx+length][2], self.out_ann,
[5, ['Row parity OK', 'Parity OK', 'OK']])
else:
self.put(self.bits_pos[idx+length][1], self.bits_pos[idx+length][2], self.out_ann,
[5, ['Row parity failed', 'Parity failed', 'Fail']])
def print_col_parity(self, idx):
data_1 = self.get_8_bits(idx)
data_2 = self.get_8_bits(idx+9)
data_3 = self.get_8_bits(idx+9+9)
data_4 = self.get_8_bits(idx+9+9+9)
col_par = self.get_8_bits(idx+9+9+9+9)
col_par_calc = data_1^data_2^data_3^data_4
if col_par == col_par_calc:
self.put(self.bits_pos[idx+9+9+9+9][1], self.bits_pos[idx+9+9+9+9+7][2], self.out_ann,
[5, ['Column parity OK', 'Parity OK', 'OK']])
else:
self.put(self.bits_pos[idx+9+9+9+9][1], self.bits_pos[idx+9+9+9+9+7][2], self.out_ann,
[5, ['Column parity failed', 'Parity failed', 'Fail']])
def print_8bit_data(self, idx):
data = self.get_8_bits(idx)
self.put(self.bits_pos[idx][1], self.bits_pos[idx+7][2], self.out_ann,
[9, ['Data' + ': %X' % data, '%X' % data]])
def put_fields(self):
if self.bit_nr == 50:
self.put(self.bits_pos[0][1], self.bits_pos[0][2], self.out_ann,
[4, ['Logic zero']])
self.put(self.bits_pos[1][1], self.bits_pos[4][2], self.out_ann,
[4, ['Command', 'Cmd', 'C']])
self.put(self.bits_pos[5][1], self.bits_pos[49][2], self.out_ann,
[4, ['Password', 'Passwd', 'Pass', 'P']])
# Get command.
cmd = self.get_3_bits(1)
self.put(self.bits_pos[1][1], self.bits_pos[3][2], self.out_ann,
[5, [self.cmds[cmd]]])
self.print_row_parity(1, 3)
# Print data.
self.print_8bit_data(5)
self.print_row_parity(5, 8)
self.print_8bit_data(14)
self.print_row_parity(14, 8)
self.print_8bit_data(23)
self.print_row_parity(23, 8)
self.print_8bit_data(32)
self.print_row_parity(32, 8)
self.print_col_parity(5)
if self.bits_pos[49][0] == 0:
self.put(self.bits_pos[49][1], self.bits_pos[49][2], self.out_ann,
[5, ['Stop bit', 'Stop', 'SB']])
else:
self.put(self.bits_pos[49][1], self.bits_pos[49][2], self.out_ann,
[5, ['Stop bit error', 'Error']])
if cmd == 1:
password = self.get_32_bits(5)
self.put(self.bits_pos[12][1], self.bits_pos[46][2], self.out_ann,
[10, ['Login password: %X' % password]])
if self.bit_nr == 57:
self.put(self.bits_pos[0][1], self.bits_pos[0][2], self.out_ann,
[4, ['Logic zero', 'LZ']])
self.put(self.bits_pos[1][1], self.bits_pos[4][2], self.out_ann,
[4, ['Command', 'Cmd', 'C']])
self.put(self.bits_pos[5][1], self.bits_pos[11][2], self.out_ann,
[4, ['Address', 'Addr', 'A']])
self.put(self.bits_pos[12][1], self.bits_pos[56][2], self.out_ann,
[4, ['Data', 'Da', 'D']])
# Get command.
cmd = self.get_3_bits(1)
self.put(self.bits_pos[1][1], self.bits_pos[3][2], self.out_ann,
[5, [self.cmds[cmd]]])
self.print_row_parity(1, 3)
# Get address.
addr = self.get_4_bits(5)
self.put(self.bits_pos[5][1], self.bits_pos[8][2], self.out_ann,
[9, ['Addr' + ': %d' % addr, '%d' % addr]])
self.put(self.bits_pos[9][1], self.bits_pos[10][2], self.out_ann,
[5, ['Zero bits', 'ZB']])
self.print_row_parity(5, 6)
# Print data.
self.print_8bit_data(12)
self.print_row_parity(12, 8)
self.print_8bit_data(21)
self.print_row_parity(21, 8)
self.print_8bit_data(30)
self.print_row_parity(30, 8)
self.print_8bit_data(39)
self.print_row_parity(39, 8)
self.print_col_parity(12)
if self.bits_pos[56][0] == 0:
self.put(self.bits_pos[56][1], self.bits_pos[56][2], self.out_ann,
[5, ['Stop bit', 'Stop', 'SB']])
else:
self.put(self.bits_pos[56][1], self.bits_pos[56][2], self.out_ann,
[5, ['Stop bit error', 'Error']])
if addr == 4:
self.decode_config(12)
if addr == 2:
password = self.get_32_bits(12)
self.put(self.bits_pos[12][1], self.bits_pos[46][2], self.out_ann,
[10, ['Write password: %X' % password]])
# If we are programming EM4100 data we can decode it halfway.
if addr == 5 and self.options['em4100_decode'] == 'on':
self.em4100_decode1(12)
if addr == 6 and self.options['em4100_decode'] == 'on':
self.em4100_decode2(12)
self.bit_nr = 0
def add_bits_pos(self, bit, ss_bit, es_bit):
if self.bit_nr < 70:
self.bits_pos[self.bit_nr][0] = bit
self.bits_pos[self.bit_nr][1] = ss_bit
self.bits_pos[self.bit_nr][2] = es_bit
self.bit_nr += 1
def decode(self, ss, es, data):
if not self.samplerate:
raise SamplerateError('Cannot decode without samplerate.')
for (self.samplenum, (pin,)) in data:
data.itercnt += 1
# Ignore identical samples early on (for performance reasons).
if self.oldpin == pin:
continue
if self.oldpin is None:
self.oldpin = pin
self.last_samplenum = self.samplenum
self.oldsamplenum = 0
self.old_gap_end = 0
self.gap_detected = 0
self.bit_nr = 0
continue
if self.oldpin != pin:
pl = self.samplenum - self.oldsamplenum
pp = pin
samples = self.samplenum - self.last_samplenum
if self.state == 'FFS_DETECTED':
if pl > self.writegap:
self.gap_detected = 1
if (self.last_samplenum - self.old_gap_end) > self.nogap:
self.gap_detected = 0
self.state = 'FFS_SEARCH'
self.put(self.old_gap_end, self.last_samplenum,
self.out_ann, [3, ['Write mode exit']])
self.put_fields()
if self.state == 'FFS_SEARCH':
if pl > self.ffs:
self.gap_detected = 1
self.put(self.last_samplenum, self.samplenum,
self.out_ann, [1, ['First field stop', 'Field stop', 'FFS']])
self.state = 'FFS_DETECTED'
if self.gap_detected == 1:
self.gap_detected = 0
if (self.last_samplenum - self.old_gap_end) > self.wzmin \
and (self.last_samplenum - self.old_gap_end) < self.wzmax:
self.put(self.old_gap_end, self.samplenum,
self.out_ann, [0, ['0']])
self.add_bits_pos(0, self.old_gap_end, self.samplenum)
if (self.last_samplenum - self.old_gap_end) > self.womax \
and (self.last_samplenum-self.old_gap_end) < self.nogap:
# One or more 1 bits
one_bits = (int)((self.last_samplenum - self.old_gap_end) / self.womax)
for ox in range(0, one_bits):
bs = (int)(self.old_gap_end+ox*self.womax)
be = (int)(self.old_gap_end+ox*self.womax + self.womax)
self.put(bs, be, self.out_ann, [0, ['1']])
self.add_bits_pos(1, bs, be)
if (self.samplenum - self.last_samplenum) > self.wzmin \
and (self.samplenum - self.last_samplenum) < self.wzmax:
bs = (int)(self.old_gap_end+one_bits*self.womax)
self.put(bs, self.samplenum, self.out_ann, [0, ['0']])
self.add_bits_pos(0, bs, self.samplenum)
self.old_gap_end = self.samplenum
if self.state == 'SKIP':
self.state = 'FFS_SEARCH'
self.oldsamplenum = self.samplenum
self.last_samplenum = self.samplenum
self.oldpin = pin

View File

@@ -14,7 +14,8 @@
## 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/>.
## along with this program; if not, write to the Free Software
## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
##
'''

View File

@@ -14,7 +14,8 @@
## 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/>.
## 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

View File

@@ -1,7 +1,8 @@
##
## This file is part of the libsigrokdecode project.
##
## Copyright (C) 2013 Uwe Hermann <uwe@hermann-uwe.de>
## Copyright (C) 2013-2016 Uwe Hermann <uwe@hermann-uwe.de>
## Copyright (C) 2016 Chris Dreher <chrisdreher@hotmail.com>
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
@@ -18,40 +19,41 @@
## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
##
# Each status byte has 3 string names, each shorter than the previous
status_bytes = {
# Channel voice messages
0x80: 'note off',
0x90: 'note on', # However, velocity = 0 means "note off".
0xa0: 'polyphonic key pressure / aftertouch',
0xb0: 'control change',
0xc0: 'program change',
0xd0: 'channel pressure / aftertouch',
0xe0: 'pitch bend change',
0x80: ['note off', 'note off', 'N off'],
0x90: ['note on', 'note on', 'N on'], # However, velocity = 0 means "note off".
0xa0: ['polyphonic key pressure / aftertouch', 'key pressure', 'KP' ],
0xb0: ['control change', 'ctrl chg', 'CC'],
0xc0: ['program change', 'prgm chg', 'PC'],
0xd0: ['channel pressure / aftertouch', 'channel pressure', 'CP'],
0xe0: ['pitch bend change', 'pitch bend', 'PB'],
# Channel mode messages
# 0xb0: 'select channel mode', # Note: Same as 'control change'.
# System exclusive messages
0xf0: 'system exclusive (SysEx)',
0xf0: ['system exclusive', 'SysEx', 'SE'],
# System common messages
0xf1: 'MIDI time code quarter frame',
0xf2: 'song position pointer',
0xf3: 'song select',
0xf4: 'undefined',
0xf5: 'undefined',
0xf6: 'tune request',
0xf7: 'end of system exclusive (EOX)',
0xf1: ['MIDI time code quarter frame', 'MIDI time code', 'MIDI time'],
0xf2: ['song position pointer', 'song position', 'song pos'],
0xf3: ['song select', 'song select', 'song sel'],
0xf4: ['undefined 0xf4', 'undef 0xf4', 'undef'],
0xf5: ['undefined 0xf5', 'undef 0xf5', 'undef'],
0xf6: ['tune request', 'tune request', 'tune req'],
0xf7: ['end of system exclusive (EOX)', 'end of SysEx', 'EOX'],
# System real time messages
0xf8: 'timing clock',
0xf9: 'undefined',
0xfa: 'start',
0xfb: 'continue',
0xfc: 'stop',
0xfd: 'undefined',
0xfe: 'active sensing',
0xff: 'system reset',
0xf8: ['timing clock', 'timing clock', 'clock'],
0xf9: ['undefined 0xf9', 'undef 0xf9', 'undef'],
0xfa: ['start', 'start', 's'],
0xfb: ['continue', 'continue', 'cont'],
0xfc: ['stop', 'stop', 'st'],
0xfd: ['undefined 0xfd', 'undef 0xfd', 'undef'],
0xfe: ['active sensing', 'active sensing', 'sensing'],
0xff: ['system reset', 'reset', 'rst'],
}
# Universal system exclusive (SysEx) messages, non-realtime (0x7e)
@@ -156,37 +158,37 @@ universal_sysex_realtime = {
# Note: Not all IDs are used/listed, i.e. there are some "holes".
sysex_manufacturer_ids = {
# American group
(0x01): 'Sequential',
(0x02): 'IDP',
(0x03): 'Voyetra/Octave-Plateau',
(0x04): 'Moog',
(0x05): 'Passport Designs',
(0x06): 'Lexicon',
(0x07): 'Kurzweil',
(0x08): 'Fender',
(0x09): 'Gulbransen',
(0x0a): 'AKG Acoustics',
(0x0b): 'Voyce Music',
(0x0c): 'Waveframe Corp',
(0x0d): 'ADA Signal Processors',
(0x0e): 'Garfield Electronics',
(0x0f): 'Ensoniq',
(0x10): 'Oberheim',
(0x11): 'Apple Computer',
(0x12): 'Grey Matter Response',
(0x13): 'Digidesign',
(0x14): 'Palm Tree Instruments',
(0x15): 'JLCooper Electronics',
(0x16): 'Lowrey',
(0x17): 'Adams-Smith',
(0x18): 'Emu Systems',
(0x19): 'Harmony Systems',
(0x1a): 'ART',
(0x1b): 'Baldwin',
(0x1c): 'Eventide',
(0x1d): 'Inventronics',
(0x1f): 'Clarity',
# American group (range 01-1f, 000001-001f7f)
(0x01,): 'Sequential',
(0x02,): 'IDP',
(0x03,): 'Voyetra/Octave-Plateau',
(0x04,): 'Moog',
(0x05,): 'Passport Designs',
(0x06,): 'Lexicon',
(0x07,): 'Kurzweil',
(0x08,): 'Fender',
(0x09,): 'Gulbransen',
(0x0a,): 'AKG Acoustics',
(0x0b,): 'Voyce Music',
(0x0c,): 'Waveframe Corp',
(0x0d,): 'ADA Signal Processors',
(0x0e,): 'Garfield Electronics',
(0x0f,): 'Ensoniq',
(0x10,): 'Oberheim',
(0x11,): 'Apple Computer',
(0x12,): 'Grey Matter Response',
(0x13,): 'Digidesign',
(0x14,): 'Palm Tree Instruments',
(0x15,): 'JLCooper Electronics',
(0x16,): 'Lowrey',
(0x17,): 'Adams-Smith',
(0x18,): 'Emu Systems',
(0x19,): 'Harmony Systems',
(0x1a,): 'ART',
(0x1b,): 'Baldwin',
(0x1c,): 'Eventide',
(0x1d,): 'Inventronics',
(0x1f,): 'Clarity',
(0x00, 0x00, 0x01): 'Time Warner Interactive',
(0x00, 0x00, 0x07): 'Digital Music Corp.',
@@ -306,32 +308,32 @@ sysex_manufacturer_ids = {
(0x00, 0x01, 0x02): 'Crystal Semiconductor',
(0x00, 0x01, 0x03): 'Rockwell Semiconductor',
# European group
(0x20): 'Passac',
(0x21): 'SIEL',
(0x22): 'Synthaxe',
(0x24): 'Hohner',
(0x25): 'Twister',
(0x26): 'Solton',
(0x27): 'Jellinghaus MS',
(0x28): 'Southworth Music Systems',
(0x29): 'PPG',
(0x2a): 'JEN',
(0x2b): 'SSL Limited',
(0x2c): 'Audio Veritrieb',
(0x2f): 'Elka',
# European group (range 20-3f, 002000-003f7f)
(0x20,): 'Passac',
(0x21,): 'SIEL',
(0x22,): 'Synthaxe',
(0x24,): 'Hohner',
(0x25,): 'Twister',
(0x26,): 'Solton',
(0x27,): 'Jellinghaus MS',
(0x28,): 'Southworth Music Systems',
(0x29,): 'PPG',
(0x2a,): 'JEN',
(0x2b,): 'SSL Limited',
(0x2c,): 'Audio Veritrieb',
(0x2f,): 'Elka',
(0x30): 'Dynacord',
(0x31): 'Viscount',
(0x33): 'Clavia Digital Instruments',
(0x34): 'Audio Architecture',
(0x35): 'GeneralMusic Corp.',
(0x39): 'Soundcraft Electronics',
(0x3b): 'Wersi',
(0x3c): 'Avab Elektronik Ab',
(0x3d): 'Digigram',
(0x3e): 'Waldorf Electronics',
(0x3f): 'Quasimidi',
(0x30,): 'Dynacord',
(0x31,): 'Viscount',
(0x33,): 'Clavia Digital Instruments',
(0x34,): 'Audio Architecture',
(0x35,): 'GeneralMusic Corp.',
(0x39,): 'Soundcraft Electronics',
(0x3b,): 'Wersi',
(0x3c,): 'Avab Elektronik Ab',
(0x3d,): 'Digigram',
(0x3e,): 'Waldorf Electronics',
(0x3f,): 'Quasimidi',
(0x00, 0x20, 0x00): 'Dream',
(0x00, 0x20, 0x01): 'Strand Lighting',
@@ -378,92 +380,462 @@ sysex_manufacturer_ids = {
(0x00, 0x20, 0x2d): 'Blue Chip Music Tech',
(0x00, 0x20, 0x2e): 'BEE OH Corp',
# Japanese group
(0x40): 'Kawai',
(0x41): 'Roland',
(0x42): 'Korg',
(0x43): 'Yamaha',
(0x44): 'Casio',
(0x46): 'Kamiya Studio',
(0x47): 'Akai',
(0x48): 'Japan Victor',
(0x49): 'Mesosha',
(0x4a): 'Hoshino Gakki',
(0x4b): 'Fujitsu Elect',
(0x4c): 'Sony',
(0x4d): 'Nisshin Onpa',
(0x4e): 'TEAC',
(0x50): 'Matsushita Electric',
(0x51): 'Fostex',
(0x52): 'Zoom',
(0x53): 'Midori Electronics',
(0x54): 'Matsushita Communication Industrial',
(0x55): 'Suzuki Musical Inst. Mfg.',
# Japanese group (range 40-5f, 004000-005f7f)
(0x40,): 'Kawai',
(0x41,): 'Roland',
(0x42,): 'Korg',
(0x43,): 'Yamaha',
(0x44,): 'Casio',
(0x46,): 'Kamiya Studio',
(0x47,): 'Akai',
(0x48,): 'Japan Victor',
(0x49,): 'Mesosha',
(0x4a,): 'Hoshino Gakki',
(0x4b,): 'Fujitsu Elect',
(0x4c,): 'Sony',
(0x4d,): 'Nisshin Onpa',
(0x4e,): 'TEAC',
(0x50,): 'Matsushita Electric',
(0x51,): 'Fostex',
(0x52,): 'Zoom',
(0x53,): 'Midori Electronics',
(0x54,): 'Matsushita Communication Industrial',
(0x55,): 'Suzuki Musical Inst. Mfg.',
# Other (range 60-7c, 006000-007f7f)
# Special (7d-7f)
(0x7d,): 'Non-Commercial',
(0x7e,): 'Universal Non-Realtime',
(0x7f,): 'Universal Realtime',
}
control_functions = {
0x00: 'bank select',
0x01: 'modulation wheel/lever',
0x02: 'breath controller',
# 0x03: undefined
0x04: 'foot controller',
0x05: 'portamento time',
0x06: 'data entry MSB',
0x07: 'channel volume (formerly main volume)',
0x08: 'balance',
# 0x09: undefined
0x0a: 'pan',
0x0b: 'expression controller',
0x0c: 'effect control 1',
0x0d: 'effect control 2',
# 0x0e-0x0f: undefined
0x10: 'general purpose controller 1',
0x11: 'general purpose controller 2',
0x12: 'general purpose controller 3',
0x13: 'general purpose controller 4',
# 0x14-0x1f: undefined
# 0x20-0x3f: LSB for values 0x00-0x1f
0x40: 'damper pedal (sustain)',
0x41: 'portamento on/off',
0x42: 'sostenuto',
0x43: 'soft pedal',
0x44: 'legato footswitch', # vv: 00-3f = normal, 40-7f = legato
0x45: 'hold 2',
0x46: 'sound controller 1 (default: sound variation)',
0x47: 'sound controller 2 (default: timbre / harmonic intensity)',
0x48: 'sound controller 3 (default: release time)',
0x49: 'sound controller 4 (default: attack time)',
0x4a: 'sound controller 5 (default: brightness)',
0x4b: 'sound controller 6 (GM2 default: decay time)',
0x4c: 'sound controller 7 (GM2 default: vibrato rate)',
0x4d: 'sound controller 8 (GM2 default: vibrato depth)',
0x4e: 'sound controller 9 (GM2 default: vibrato delay)',
0x4f: 'sound controller 10',
0x50: 'general purpose controller 5',
0x51: 'general purpose controller 6',
0x52: 'general purpose controller 7',
0x53: 'general purpose controller 8',
0x54: 'portamento control',
0x00: ['bank select MSB', 'bank MSB', 'bank-M'],
0x01: ['modulation wheel/lever MSB', 'modulation MSB', 'mod-M'],
0x02: ['breath controller MSB', 'breath MSB', 'breath-M'],
# 0x03: undefined MSB
0x04: ['foot controller MSB', 'foot MSB', 'foot-M'],
0x05: ['portamento time MSB', 'portamento MSB', 'porta-M'],
0x06: ['data entry MSB', 'data entry MSB', 'data-M'],
0x07: ['channel volume MSB (formerly main volume)', 'channel volume MSB', 'ch vol-M'],
0x08: ['balance MSB', 'bal MSB', 'bal-M'],
# 0x09: undefined MSB
0x0a: ['pan MSB', 'pan MSB', 'pan-M'],
0x0b: ['expression controller MSB', 'expression MSB', 'expr-M'],
0x0c: ['effect control 1 MSB', 'effect 1 MSB', 'eff-1-M'],
0x0d: ['effect control 2 MSB', 'effect 2 MSB', 'eff-2-M'],
# 0x0e-0x0f: undefined MSB
0x10: ['general purpose controller 1 MSB', 'GP ctrl 1 MSB', 'GPC-1-M'],
0x11: ['general purpose controller 2 MSB', 'GP ctrl 2 MSB', 'GPC-2-M'],
0x12: ['general purpose controller 3 MSB', 'GP ctrl 3 MSB', 'GPC-3-M'],
0x13: ['general purpose controller 4 MSB', 'GP ctrl 4 MSB', 'GPC-4-M'],
# 0x14-0x1f: undefined MSB
0x20: ['bank select LSB', 'bank LSB', 'bank-L'],
0x21: ['modulation wheel/lever LSB', 'modulation LSB', 'mod-L'],
0x22: ['breath controller LSB', 'breath LSB', 'breath-L'],
# 0x23: undefined LSB
0x24: ['foot controller LSB', 'foot LSB', 'foot-L'],
0x25: ['portamento time LSB', 'portamento LSB', 'porta-L'],
0x26: ['data entry LSB', 'data entry LSB', 'data-L'],
0x27: ['channel volume LSB (formerly main volume)', 'channel volume LSB', 'ch vol-L'],
0x28: ['balance LSB', 'bal LSB', 'bal-L'],
# 0x29: undefined LSB
0x2a: ['pan LSB', 'pan LSB', 'pan-L'],
0x2b: ['expression controller LSB', 'expression LSB', 'expr-L'],
0x2c: ['effect control 1 LSB', 'effect 1 LSB', 'eff-1-L'],
0x2d: ['effect control 2 LSB', 'effect 2 LSB', 'eff-2-L'],
# 0x2e-0x2f: undefined LSB
0x30: ['general purpose controller 1 LSB', 'GP ctrl 1 LSB', 'GPC-1-L'],
0x31: ['general purpose controller 2 LSB', 'GP ctrl 2 LSB', 'GPC-2-L'],
0x32: ['general purpose controller 3 LSB', 'GP ctrl 3 LSB', 'GPC-3-L'],
0x33: ['general purpose controller 4 LSB', 'GP ctrl 4 LSB', 'GPC-4-L'],
# 0x34-0x3f: undefined LSB
0x40: ['damper pedal (sustain)', 'sustain', 'sust'],
0x41: ['portamento on/off', 'porta on/off', 'porta on/off'],
0x42: ['sostenuto', 'sostenuto', 'sostenuto'],
0x43: ['soft pedal', 'soft pedal', 'soft pedal'],
0x44: ['legato footswitch', 'legato switch', 'legato'], # vv: 00-3f = normal, 40-7f = legato
0x45: ['hold 2', 'hold 2', 'hold 2'],
0x46: ['sound controller 1 (default: sound variation)', 'sound ctrl 1', 'snd ctrl 1'],
0x47: ['sound controller 2 (default: timbre / harmonic intensity)', 'sound ctrl 2', 'snd ctrl 2'],
0x48: ['sound controller 3 (default: release time)', 'sound ctrl 3', 'snd ctrl 3'],
0x49: ['sound controller 4 (default: attack time)', 'sound ctrl 4', 'snd ctrl 4'],
0x4a: ['sound controller 5 (default: brightness)', 'sound ctrl 5', 'snd ctrl 5'],
0x4b: ['sound controller 6 (GM2 default: decay time)', 'sound ctrl 6', 'snd ctrl 6'],
0x4c: ['sound controller 7 (GM2 default: vibrato rate)', 'sound ctrl 7', 'snd ctrl 7'],
0x4d: ['sound controller 8 (GM2 default: vibrato depth)', 'sound ctrl 8', 'snd ctrl 8'],
0x4e: ['sound controller 9 (GM2 default: vibrato delay)', 'sound ctrl 9', 'snd ctrl 9'],
0x4f: ['sound controller 10', 'sound ctrl 10', 'snd ctrl 10'],
0x50: ['general purpose controller 5', 'GP controller 5', 'GPC-5'],
0x51: ['general purpose controller 6', 'GP controller 6', 'GPC-6'],
0x52: ['general purpose controller 7', 'GP controller 7', 'GPC-7'],
0x53: ['general purpose controller 8', 'GP controller 8', 'GPC-8'],
0x54: ['portamento control', 'portamento ctrl', 'porta ctrl'],
# 0x55-0x5a: undefined
0x5b: 'effects 1 depth (formerly external effects depth)',
0x5c: 'effects 2 depth (formerly tremolo depth)',
0x5d: 'effects 3 depth (formerly chorus depth)',
0x5e: 'effects 4 depth (formerly celeste/detune depth)',
0x5f: 'effects 5 depth (formerly phaser depth)',
0x60: 'data increment',
0x61: 'data decrement',
0x62: 'non-registered parameter number LSB',
0x63: 'non-registered parameter number MSB',
0x64: 'registered parameter number LSB',
0x65: 'registered parameter number MSB',
0x5b: ['effects 1 depth (formerly external effects depth)', 'effects 1 depth', 'eff 1 depth'],
0x5c: ['effects 2 depth (formerly tremolo depth)', 'effects 2 depth', 'eff 2 depth'],
0x5d: ['effects 3 depth (formerly chorus depth)', 'effects 3 depth', 'eff 3 depth'],
0x5e: ['effects 4 depth (formerly celeste/detune depth)', 'effects 4 depth', 'eff 4 depth'],
0x5f: ['effects 5 depth (formerly phaser depth)', 'effects 5 depth', 'eff 5 depth'],
0x60: ['data increment', 'data inc', 'data++'],
0x61: ['data decrement', 'data dec', 'data--'],
0x62: ['Non-Registered Parameter Number LSB', 'NRPN LSB', 'NRPN-L'],
0x63: ['Non-Registered Parameter Number MSB', 'NRPN MSB', 'NRPN-M'],
0x64: ['Registered Parameter Number LSB', 'RPN LSB', 'RPN-L'],
0x65: ['Registered Parameter Number MSB', 'RPN MSB', 'RPN-M'],
# 0x66-0x77: undefined
# 0x78-0x7f: reserved for channel mode messages
0x78: 'all sound off',
0x79: 'reset all controllers',
0x7a: 'local control on/off',
0x7b: 'all notes off',
0x7c: 'omni mode off', # all notes off
0x7d: 'omni mode on', # all notes off
0x7e: 'poly mode off', # mono mode on, all notes off
0x7f: 'poly mode on', # mono mode off, all notes off
0x78: ['all sound off', 'all snd off', 'snd off'],
0x79: ['reset all controllers', 'reset all ctrls', 'reset ctrls'],
0x7a: ['local control', 'local ctrl', 'local ctrl'],
0x7b: ['all notes off', 'notes off', 'notes off'],
0x7c: ['omni mode off', 'omni off', 'omni off'], # all notes off
0x7d: ['omni mode on', 'omni on', 'omni on'], # all notes off
0x7e: ['mono mode on', 'mono on', 'mono'], # mono mode on, all notes off
0x7f: ['poly mode on', 'poly on', 'poly'], # mono mode off, all notes off
}
gm_instruments = {
1: 'Acoustic Grand Piano',
2: 'Bright Acoustic Piano',
3: 'Electric Grand Piano',
4: 'Honky-tonk Piano',
5: 'Electric Piano 1',
6: 'Electric Piano 2',
7: 'Harpsichord',
8: 'Clavi',
9: 'Celesta',
10: 'Glockenspiel',
11: 'Music Box',
12: 'Vibraphone',
13: 'Marimba',
14: 'Xylophone',
15: 'Tubular Bells',
16: 'Dulcimer',
17: 'Drawbar Organ',
18: 'Percussive Organ',
19: 'Rock Organ',
20: 'Church Organ',
21: 'Reed Organ',
22: 'Accordion',
23: 'Harmonica',
24: 'Tango Accordion',
25: 'Acoustic Guitar (nylon)',
26: 'Acoustic Guitar (steel)',
27: 'Electric Guitar (jazz)',
28: 'Electric Guitar (clean)',
29: 'Electric Guitar (muted)',
30: 'Overdriven Guitar',
31: 'Distortion Guitar',
32: 'Guitar harmonics',
33: 'Acoustic Bass',
34: 'Electric Bass (finger)',
35: 'Electric Bass (pick)',
36: 'Fretless Bass',
37: 'Slap Bass 1',
38: 'Slap Bass 2',
39: 'Synth Bass 1',
40: 'Synth Bass 2',
41: 'Violin',
42: 'Viola',
43: 'Cello',
44: 'Contrabass',
45: 'Tremolo Strings',
46: 'Pizzicato Strings',
47: 'Orchestral Harp',
48: 'Timpani',
49: 'String Ensemble 1',
50: 'String Ensemble 2',
51: 'SynthStrings 1',
52: 'SynthStrings 2',
53: 'Choir Aahs',
54: 'Voice Oohs',
55: 'Synth Voice',
56: 'Orchestra Hit',
57: 'Trumpet',
58: 'Trombone',
59: 'Tuba',
60: 'Muted Trumpet',
61: 'French Horn',
62: 'Brass Section',
63: 'SynthBrass 1',
64: 'SynthBrass 2',
65: 'Soprano Sax',
66: 'Alto Sax',
67: 'Tenor Sax',
68: 'Baritone Sax',
69: 'Oboe',
70: 'English Horn',
71: 'Bassoon',
72: 'Clarinet',
73: 'Piccolo',
74: 'Flute',
75: 'Recorder',
76: 'Pan Flute',
77: 'Blown Bottle',
78: 'Shakuhachi',
79: 'Whistle',
80: 'Ocarina',
81: 'Lead 1 (square)',
82: 'Lead 2 (sawtooth)',
83: 'Lead 3 (calliope)',
84: 'Lead 4 (chiff)',
85: 'Lead 5 (charang)',
86: 'Lead 6 (voice)',
87: 'Lead 7 (fifths)',
88: 'Lead 8 (bass + lead)',
89: 'Pad 1 (new age)',
90: 'Pad 2 (warm)',
91: 'Pad 3 (polysynth)',
92: 'Pad 4 (choir)',
93: 'Pad 5 (bowed)',
94: 'Pad 6 (metallic)',
95: 'Pad 7 (halo)',
96: 'Pad 8 (sweep)',
97: 'FX 1 (rain)',
98: 'FX 2 (soundtrack)',
99: 'FX 3 (crystal)',
100: 'FX 4 (atmosphere)',
101: 'FX 5 (brightness)',
102: 'FX 6 (goblins)',
103: 'FX 7 (echoes)',
104: 'FX 8 (sci-fi)',
105: 'Sitar',
106: 'Banjo',
107: 'Shamisen',
108: 'Koto',
109: 'Kalimba',
110: 'Bag pipe',
111: 'Fiddle',
112: 'Shanai',
113: 'Tinkle Bell',
114: 'Agogo',
115: 'Steel Drums',
116: 'Woodblock',
117: 'Taiko Drum',
118: 'Melodic Tom',
119: 'Synth Drum',
120: 'Reverse Cymbal',
121: 'Guitar Fret Noise',
122: 'Breath Noise',
123: 'Seashore',
124: 'Bird Tweet',
125: 'Telephone Ring',
126: 'Helicopter',
127: 'Applause',
128: 'Gunshot',
}
drum_kit = {
1: 'GM Standard Kit',
9: 'GS Room Kit',
17: 'GS Power Kit',
25: 'GS Power Kit',
26: 'GS TR-808 Kit',
33: 'GS Jazz Kit',
41: 'GS Brush Kit',
49: 'GS Orchestra Kit',
57: 'GS Sound FX Kit',
128: 'GS CM-64/CM-32 Kit',
}
# Each quarter frame type has 2 string names, each shorter than the previous
quarter_frame_type = {
0: ['frame count LS nibble', 'frame LSN'],
1: ['frame count MS nibble', 'frame MSN'],
2: ['seconds LS nibble', 'sec LSN'],
3: ['seconds MS nibble', 'sec MSN'],
4: ['minutes LS nibble', 'min LSN'],
5: ['minutes MS nibble', 'min MSN'],
6: ['hours LS nibble', 'hrs LSN'],
7: ['hours MS nibble and SMPTE type', 'hrs MSN'],
}
smpte_type = {
0: '24 fps',
1: '25 fps',
2: '30 fps (drop-frame)',
3: '30 fps (non-drop)',
}
chromatic_notes = {
0: 'C-1',
1: 'C#-1',
2: 'D-1',
3: 'D#-1',
4: 'E-1',
5: 'F-1',
6: 'F#-1',
7: 'G-1',
8: 'G#-1',
9: 'A-1',
10: 'A#-1',
11: 'B-1',
12: 'C0',
13: 'C#0',
14: 'D0',
15: 'D#0',
16: 'E0',
17: 'F0',
18: 'F#0',
19: 'G0',
20: 'G#0',
21: 'A0',
22: 'A#0',
23: 'B0',
24: 'C1',
25: 'C#1',
26: 'D1',
27: 'D#1',
28: 'E1',
29: 'F1',
30: 'F#1',
31: 'G1',
32: 'G#1',
33: 'A1',
34: 'A#1',
35: 'B1',
36: 'C2',
37: 'C#2',
38: 'D2',
39: 'D#2',
40: 'E2',
41: 'F2',
42: 'F#2',
43: 'G2',
44: 'G#2',
45: 'A2',
46: 'A#2',
47: 'B2',
48: 'C3',
49: 'C#3',
50: 'D3',
51: 'D#3',
52: 'E3',
53: 'F3',
54: 'F#3',
55: 'G3',
56: 'G#3',
57: 'A3',
58: 'A#3',
59: 'B3',
60: 'C4',
61: 'C#4',
62: 'D4',
63: 'D#4',
64: 'E4',
65: 'F4',
66: 'F#4',
67: 'G4',
68: 'G#4',
69: 'A4',
70: 'A#4',
71: 'B4',
72: 'C5',
73: 'C#5',
74: 'D5',
75: 'D#5',
76: 'E5',
77: 'F5',
78: 'F#5',
79: 'G5',
80: 'G#5',
81: 'A5',
82: 'A#5',
83: 'B5',
84: 'C6',
85: 'C#6',
86: 'D6',
87: 'D#6',
88: 'E6',
89: 'F6',
90: 'F#6',
91: 'G6',
92: 'G#6',
93: 'A6',
94: 'A#6',
95: 'B6',
96: 'C7',
97: 'C#7',
98: 'D7',
99: 'D#7',
100: 'E7',
101: 'F7',
102: 'F#7',
103: 'G7',
104: 'G#7',
105: 'A7',
106: 'A#7',
107: 'B7',
108: 'C8',
109: 'C#8',
110: 'D8',
111: 'D#8',
112: 'E8',
113: 'F8',
114: 'F#8',
115: 'G8',
116: 'G#8',
117: 'A8',
118: 'A#8',
119: 'B8',
120: 'C9',
121: 'C#9',
122: 'D9',
123: 'D#9',
124: 'E9',
125: 'F9',
126: 'F#9',
127: 'G9',
}
percussion_notes = {
35: 'Acoustic Bass Drum',
36: 'Bass Drum 1',
37: 'Side Stick',
38: 'Acoustic Snare',
39: 'Hand Clap',
40: 'Electric Snare',
41: 'Low Floor Tom',
42: 'Closed Hi Hat',
43: 'High Floor Tom',
44: 'Pedal Hi-Hat',
45: 'Low Tom',
46: 'Open Hi-Hat',
47: 'Low-Mid Tom',
48: 'Hi Mid Tom',
49: 'Crash Cymbal 1',
50: 'High Tom',
51: 'Ride Cymbal 1',
52: 'Chinese Cymbal',
53: 'Ride Bell',
54: 'Tambourine',
55: 'Splash Cymbal',
56: 'Cowbell',
57: 'Crash Cymbal 2',
58: 'Vibraslap',
59: 'Ride Cymbal 2',
60: 'Hi Bongo',
61: 'Low Bongo',
62: 'Mute Hi Conga',
63: 'Open Hi Conga',
64: 'Low Conga',
65: 'High Timbale',
66: 'Low Timbale',
67: 'High Agogo',
68: 'Low Agogo',
69: 'Cabasa',
70: 'Maracas',
71: 'Short Whistle',
72: 'Long Whistle',
73: 'Short Guiro',
74: 'Long Guiro',
75: 'Claves',
76: 'Hi Wood Block',
77: 'Low Wood Block',
78: 'Mute Cuica',
79: 'Open Cuica',
80: 'Mute Triangle',
81: 'Open Triangle',
}

View File

@@ -1,7 +1,8 @@
##
## This file is part of the libsigrokdecode project.
##
## Copyright (C) 2013 Uwe Hermann <uwe@hermann-uwe.de>
## Copyright (C) 2013-2016 Uwe Hermann <uwe@hermann-uwe.de>
## Copyright (C) 2016 Chris Dreher <chrisdreher@hotmail.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
@@ -35,11 +36,19 @@ class Decoder(srd.Decoder):
outputs = ['midi']
annotations = (
('text-verbose', 'Human-readable text (verbose)'),
('text-sysreal-verbose', 'Human-readable SysReal text (verbose)'),
('text-error', 'Human-readable Error text'),
)
annotation_rows = (
('normal', 'Normal', (0, 2)),
('sys-real', 'SysReal', (1,)),
)
def __init__(self):
self.cmd = []
self.state = 'IDLE'
self.status_byte = 0
self.explicit_status_byte = False
self.cmd = []
self.ss = None
self.es = None
self.ss_block = None
@@ -51,130 +60,524 @@ class Decoder(srd.Decoder):
def putx(self, data):
self.put(self.ss_block, self.es_block, self.out_ann, data)
def handle_channel_msg_0x80(self):
def get_note_name(self, channel, note):
if channel != 10:
return chromatic_notes[note]
else:
return 'assuming ' + percussion_notes.get(note, 'undefined')
def check_for_garbage_flush(self, is_flushed):
if is_flushed:
if self.explicit_status_byte:
self.cmd.insert(0, self.status_byte)
self.handle_garbage_msg(None)
def soft_clear_status_byte(self):
self.explicit_status_byte = False
def hard_clear_status_byte(self):
self.status_byte = 0
self.explicit_status_byte = False
def set_status_byte(self, newbyte):
self.status_byte = newbyte
self.explicit_status_byte = True
def handle_channel_msg_0x80(self, is_flushed):
# Note off: 8n kk vv
# n = channel, kk = note, vv = velocity
c = self.cmd
if len(c) < 3:
if len(c) < 2:
self.check_for_garbage_flush(is_flushed)
return
self.es_block = self.es
msg, chan, note, velocity = c[0] & 0xf0, (c[0] & 0x0f) + 1, c[1], c[2]
self.putx([0, ['Channel %d: %s (note = %d, velocity = %d)' % \
(chan, status_bytes[msg], note, velocity)]])
msg, chan = self.status_byte & 0xf0, (self.status_byte & 0x0f) + 1
note, velocity = c[0], c[1]
note_name = self.get_note_name(chan, note)
self.putx([0, ['Channel %d: %s (note = %d \'%s\', velocity = %d)' % \
(chan, status_bytes[msg][0], note, note_name, velocity),
'ch %d: %s %d, velocity = %d' % \
(chan, status_bytes[msg][1], note, velocity),
'%d: %s %d, vel %d' % \
(chan, status_bytes[msg][2], note, velocity)]])
self.cmd, self.state = [], 'IDLE'
self.soft_clear_status_byte()
def handle_channel_msg_0x90(self):
def handle_channel_msg_0x90(self, is_flushed):
# Note on: 9n kk vv
# n = channel, kk = note, vv = velocity
# If velocity == 0 that actually means 'note off', though.
c = self.cmd
if len(c) < 3:
if len(c) < 2:
self.check_for_garbage_flush(is_flushed)
return
self.es_block = self.es
msg, chan, note, velocity = c[0] & 0xf0, (c[0] & 0x0f) + 1, c[1], c[2]
s = 'note off' if (velocity == 0) else status_bytes[msg]
self.putx([0, ['Channel %d: %s (note = %d, velocity = %d)' % \
(chan, s, note, velocity)]])
msg, chan = self.status_byte & 0xf0, (self.status_byte & 0x0f) + 1
note, velocity = c[0], c[1]
s = status_bytes[0x80] if (velocity == 0) else status_bytes[msg]
note_name = self.get_note_name(chan, note)
self.putx([0, ['Channel %d: %s (note = %d \'%s\', velocity = %d)' % \
(chan, s[0], note, note_name, velocity),
'ch %d: %s %d, velocity = %d' % \
(chan, s[1], note, velocity),
'%d: %s %d, vel %d' % \
(chan, s[2], note, velocity)]])
self.cmd, self.state = [], 'IDLE'
self.soft_clear_status_byte()
def handle_channel_msg_0xa0(self):
def handle_channel_msg_0xa0(self, is_flushed):
# Polyphonic key pressure / aftertouch: An kk vv
# n = channel, kk = polyphonic key pressure, vv = pressure value
pass # TODO
c = self.cmd
if len(c) < 2:
self.check_for_garbage_flush(is_flushed)
return
self.es_block = self.es
msg, chan = self.status_byte & 0xf0, (self.status_byte & 0x0f) + 1
note, pressure = c[0], c[1]
note_name = self.get_note_name(chan, note)
self.putx([0, ['Channel %d: %s of %d for note = %d \'%s\'' % \
(chan, status_bytes[msg][0], pressure, note, note_name),
'ch %d: %s %d for note %d' % \
(chan, status_bytes[msg][1], pressure, note),
'%d: %s %d, N %d' % \
(chan, status_bytes[msg][2], pressure, note)]])
self.cmd, self.state = [], 'IDLE'
self.soft_clear_status_byte()
def handle_controller_0x44(self):
# Legato footswitch: Bn 44 vv
# n = channel, vv = value (<= 0x3f: normal, > 0x3f: legato)
chan, vv = (self.cmd[0] & 0x0f) + 1, self.cmd[2]
t = 'normal' if vv <= 0x3f else 'legato'
self.putx([0, ['Channel %d: control function \'%s\' = %s' % \
(chan, control_functions[0x44], t)]])
c = self.cmd
msg, chan = self.status_byte & 0xf0, (self.status_byte & 0x0f) + 1
vv = c[1]
t = ('normal', 'no') if vv <= 0x3f else ('legato', 'yes')
self.putx([0, ['Channel %d: %s \'%s\' = %s' % \
(chan, status_bytes[msg][0],
control_functions[0x44][0], t[0]),
'ch %d: %s \'%s\' = %s' % \
(chan, status_bytes[msg][1],
control_functions[0x44][1], t[0]),
'%d: %s \'%s\' = %s' % \
(chan, status_bytes[msg][2],
control_functions[0x44][2], t[1])]])
def handle_controller_0x54(self):
# Portamento control (PTC): Bn 54 kk
# n = channel, kk = source note for pitch reference
chan, kk = (self.cmd[0] & 0x0f) + 1, self.cmd[2]
self.putx([0, ['Channel %d: control function \'%s\' (source note ' \
'= %d)' % (chan, control_functions[0x54], kk)]])
c = self.cmd
msg, chan = self.status_byte & 0xf0, (self.status_byte & 0x0f) + 1
kk = c[1]
kk_name = self.get_note_name(chan, kk)
self.putx([0, ['Channel %d: %s \'%s\' (source note = %d / %s)' % \
(chan, status_bytes[msg][0],
control_functions[0x54][0], kk, kk_name),
'ch %d: %s \'%s\' (source note = %d)' % \
(chan, status_bytes[msg][1],
control_functions[0x54][1], kk),
'%d: %s \'%s\' (src N %d)' % \
(chan, status_bytes[msg][2],
control_functions[0x54][2], kk)]])
def handle_controller_generic(self):
c = self.cmd
chan, fn, param = (c[0] & 0x0f) + 1, c[1], c[2]
ctrl_fn = control_functions.get(fn, 'undefined')
self.putx([0, ['Channel %d: control change to function \'%s\' ' \
'(param = 0x%02x)' % (chan, ctrl_fn, param)]])
msg, chan = self.status_byte & 0xf0, (self.status_byte & 0x0f) + 1
fn, param = c[0], c[1]
default_name = 'undefined'
ctrl_fn = control_functions.get(fn, default_name)
if ctrl_fn == default_name:
ctrl_fn = ('undefined 0x%02x' % fn, 'undef 0x%02x' % fn, '0x%02x' % fn)
self.putx([0, ['Channel %d: %s \'%s\' (param = 0x%02x)' % \
(chan, status_bytes[msg][0], ctrl_fn[0], param),
'ch %d: %s \'%s\' (param = 0x%02x)' % \
(chan, status_bytes[msg][1], ctrl_fn[1], param),
'%d: %s \'%s\' is 0x%02x' % \
(chan, status_bytes[msg][2], ctrl_fn[2], param)]])
def handle_channel_msg_0xb0(self):
def handle_channel_mode(self):
# Channel Mode: Bn mm vv
# n = channel, mm = mode number (120 - 127), vv = value
c = self.cmd
msg, chan = self.status_byte & 0xf0, (self.status_byte & 0x0f) + 1
mm, vv = c[0], c[1]
mode_fn = control_functions.get(mm, ('undefined', 'undef', 'undef'))
# Decode the value based on the mode number.
vv_string = ('', '')
if mm == 122: # mode = local control?
if vv == 0:
vv_string = ('off', 'off')
elif vv == 127: # mode = poly mode on?
vv_string = ('on', 'on')
else:
vv_string = ('(non-standard param value of 0x%02x)' % vv,
'0x%02x' % vv)
elif mm == 126: # mode = mono mode on?
if vv != 0:
vv_string = ('(%d channels)' % vv, '(%d ch)' % vv)
else:
vv_string = ('(channels \'basic\' through 16)',
'(ch \'basic\' thru 16)')
elif vv != 0: # All other channel mode messages expect vv == 0.
vv_string = ('(non-standard param value of 0x%02x)' % vv,
'0x%02x' % vv)
self.putx([0, ['Channel %d: %s \'%s\' %s' % \
(chan, status_bytes[msg][0], mode_fn[0], vv_string[0]),
'ch %d: %s \'%s\' %s' % \
(chan, status_bytes[msg][1], mode_fn[1], vv_string[1]),
'%d: %s \'%s\' %s' % \
(chan, status_bytes[msg][2], mode_fn[2], vv_string[1])]])
self.cmd, self.state = [], 'IDLE'
self.soft_clear_status_byte()
def handle_channel_msg_0xb0(self, is_flushed):
# Control change (or channel mode messages): Bn cc vv
# n = channel, cc = control number (0 - 119), vv = control value
c = self.cmd
if (len(c) >= 2) and (c[1] in range(0x78, 0x7f + 1)):
# This is not a control change, but rather a channel mode message.
# TODO: Handle channel mode messages.
return
if len(c) < 3:
if len(c) < 2:
self.check_for_garbage_flush(is_flushed)
return
self.es_block = self.es
handle_ctrl = getattr(self, 'handle_controller_0x%02x' % c[1],
if c[0] in range(0x78, 0x7f + 1):
self.handle_channel_mode()
return
handle_ctrl = getattr(self, 'handle_controller_0x%02x' % c[0],
self.handle_controller_generic)
handle_ctrl()
self.cmd, self.state = [], 'IDLE'
self.soft_clear_status_byte()
def handle_channel_msg_0xc0(self):
def handle_channel_msg_0xc0(self, is_flushed):
# Program change: Cn pp
# n = channel, pp = program number (0 - 127)
pass # TODO
def handle_channel_msg_0xd0(self):
# Channel pressure / aftertouch: Dn vv
# n = channel, vv = pressure value
pass # TODO
def handle_channel_msg_0xe0(self):
# Pitch bend change: En ll mm
# n = channel, ll = pitch bend change LSB, mm = pitch bend change MSB
pass # TODO
def handle_channel_msg_generic(self):
msg_type = self.cmd[0] & 0xf0
self.putx([0, ['Unknown channel message type: 0x%02x' % msg_type]])
# TODO: Handle properly.
def handle_channel_msg(self, newbyte):
self.cmd.append(newbyte)
msg_type = self.cmd[0] & 0xf0
handle_msg = getattr(self, 'handle_channel_msg_0x%02x' % msg_type,
self.handle_channel_msg_generic)
handle_msg()
def handle_sysex_msg(self, newbyte):
# SysEx message: 1 status byte, x data bytes, EOX byte
self.cmd.append(newbyte)
if newbyte != 0xf7: # EOX
c = self.cmd
if len(c) < 1:
self.check_for_garbage_flush(is_flushed)
return
self.es_block = self.es
# TODO: Get message ID, vendor ID, message contents, etc.
self.putx([0, ['SysEx message']])
msg, chan = self.status_byte & 0xf0, (self.status_byte & 0x0f) + 1
pp = self.cmd[0] + 1
change_type = 'instrument'
name = ''
if chan != 10: # channel != percussion
name = gm_instruments.get(pp, 'undefined')
else:
change_type = 'drum kit'
name = drum_kit.get(pp, 'undefined')
self.putx([0, ['Channel %d: %s to %s %d (assuming %s)' % \
(chan, status_bytes[msg][0], change_type, pp, name),
'ch %d: %s to %s %d' % \
(chan, status_bytes[msg][1], change_type, pp),
'%d: %s %d' % \
(chan, status_bytes[msg][2], pp)]])
self.cmd, self.state = [], 'IDLE'
self.soft_clear_status_byte()
def handle_channel_msg_0xd0(self, is_flushed):
# Channel pressure / aftertouch: Dn vv
# n = channel, vv = pressure value
c = self.cmd
if len(c) < 1:
self.check_for_garbage_flush(is_flushed)
return
self.es_block = self.es
msg, chan = self.status_byte & 0xf0, (self.status_byte & 0x0f) + 1
vv = self.cmd[0]
self.putx([0, ['Channel %d: %s %d' % (chan, status_bytes[msg][0], vv),
'ch %d: %s %d' % (chan, status_bytes[msg][1], vv),
'%d: %s %d' % (chan, status_bytes[msg][2], vv)]])
self.cmd, self.state = [], 'IDLE'
self.soft_clear_status_byte()
def handle_channel_msg_0xe0(self, is_flushed):
# Pitch bend change: En ll mm
# n = channel, ll = pitch bend change LSB, mm = pitch bend change MSB
c = self.cmd
if len(c) < 2:
self.check_for_garbage_flush(is_flushed)
return
self.es_block = self.es
msg, chan = self.status_byte & 0xf0, (self.status_byte & 0x0f) + 1
ll, mm = self.cmd[0], self.cmd[1]
decimal = (mm << 7) + ll
self.putx([0, ['Channel %d: %s 0x%02x 0x%02x (%d)' % \
(chan, status_bytes[msg][0], ll, mm, decimal),
'ch %d: %s 0x%02x 0x%02x (%d)' % \
(chan, status_bytes[msg][1], ll, mm, decimal),
'%d: %s (%d)' % \
(chan, status_bytes[msg][2], decimal)]])
self.cmd, self.state = [], 'IDLE'
self.soft_clear_status_byte()
def handle_channel_msg_generic(self, is_flushed):
# TODO: It should not be possible to hit this code.
# It currently can not be unit tested.
msg_type = self.status_byte & 0xf0
self.es_block = self.es
self.putx([2, ['Unknown channel message type: 0x%02x' % msg_type]])
self.cmd, self.state = [], 'IDLE'
self.soft_clear_status_byte()
def handle_channel_msg(self, newbyte):
if newbyte is not None:
if newbyte >= 0x80:
self.set_status_byte(newbyte)
else:
self.cmd.append(newbyte)
msg_type = self.status_byte & 0xf0
handle_msg = getattr(self, 'handle_channel_msg_0x%02x' % msg_type,
self.handle_channel_msg_generic)
handle_msg(newbyte is None)
def handle_sysex_msg(self, newbyte):
# SysEx message: 1 status byte, 1-3 manuf. bytes, x data bytes, EOX byte
#
# SysEx messages are variable length, can be terminated by EOX or
# by any non-SysReal status byte, and it clears self.status_byte.
#
# Note: All System message codes don't utilize self.status_byte.
self.hard_clear_status_byte()
if newbyte != 0xf7 and newbyte is not None: # EOX
self.cmd.append(newbyte)
return
self.es_block = self.es
# Note: Unlike other methods, this code pops bytes out of self.cmd
# to isolate the data.
msg = self.cmd.pop(0)
if len(self.cmd) < 1:
self.putx([2, ['%s: truncated manufacturer code (<1 bytes)' % \
status_bytes[msg][0],
'%s: truncated manufacturer (<1 bytes)' % \
status_bytes[msg][1],
'%s: trunc. manu.' % status_bytes[msg][2]]])
self.cmd, self.state = [], 'IDLE'
return
# Extract the manufacturer name (or SysEx realtime or non-realtime).
m1 = self.cmd.pop(0)
manu = (m1,)
if m1 == 0x00: # If byte == 0, then 2 more manufacturer bytes follow.
if len(self.cmd) < 2:
self.putx([2, ['%s: truncated manufacturer code (<3 bytes)' % \
status_bytes[msg][0],
'%s: truncated manufacturer (<3 bytes)' % \
status_bytes[msg][1],
'%s: trunc. manu.' % status_bytes[msg][2]]])
self.cmd, self.state = [], 'IDLE'
return
manu = (m1, self.cmd.pop(0), self.cmd.pop(0))
default_name = 'undefined'
manu_name = sysex_manufacturer_ids.get(manu, default_name)
if manu_name == default_name:
if len(manu) == 3:
manu_name = ('%s (0x%02x 0x%02x 0x%02x)' % \
(default_name, manu[0], manu[1], manu[2]),
default_name)
else:
manu_name = ('%s (0x%02x)' % (default_name, manu[0]),
default_name)
else:
manu_name = (manu_name, manu_name)
# Extract the payload, display in 1 of 2 formats
# TODO: Write methods to decode SysEx realtime & non-realtime payloads.
payload0 = ''
payload1 = ''
while len(self.cmd) > 0:
byte = self.cmd.pop(0)
payload0 += '0x%02x ' % (byte)
payload1 += '%02x ' % (byte)
if payload0 == '':
payload0 = '<empty>'
payload1 = '<>'
payload = (payload0, payload1)
self.putx([0, ['%s: for \'%s\' with payload %s' % \
(status_bytes[msg][0], manu_name[0], payload[0]),
'%s: \'%s\', payload %s' % \
(status_bytes[msg][1], manu_name[1], payload[1]),
'%s: \'%s\', payload %s' % \
(status_bytes[msg][2], manu_name[1], payload[1])]])
self.cmd, self.state = [], 'IDLE'
def handle_syscommon_midi_time_code_quarter_frame_msg(self, newbyte):
# MIDI time code quarter frame: F1 nd
# n = message type
# d = values
#
# Note: All System message codes don't utilize self.status_byte,
# and System Exclusive and System Common clear it.
c = self.cmd
if len(c) < 2:
if newbyte is None:
self.handle_garbage_msg(None)
return
msg = c[0]
nn, dd = (c[1] & 0x70) >> 4, c[1] & 0x0f
group = ('System Common', 'SysCom', 'SC')
self.es_block = self.es
if nn != 7: # If message type does not contain SMPTE type.
self.putx([0, ['%s: %s of %s, value 0x%01x' % \
(group[0], status_bytes[msg][0],
quarter_frame_type[nn][0], dd),
'%s: %s of %s, value 0x%01x' % \
(group[1], status_bytes[msg][1],
quarter_frame_type[nn][1], dd),
'%s: %s of %s, value 0x%01x' % \
(group[2], status_bytes[msg][2],
quarter_frame_type[nn][1], dd)]])
self.cmd, self.state = [], 'IDLE'
return
tt = (dd & 0x6) >> 1
self.putx([0, ['%s: %s of %s, value 0x%01x for %s' % \
(group[0], status_bytes[msg][0], \
quarter_frame_type[nn][0], dd, smpte_type[tt]),
'%s: %s of %s, value 0x%01x for %s' % \
(group[1], status_bytes[msg][1], \
quarter_frame_type[nn][1], dd, smpte_type[tt]),
'%s: %s of %s, value 0x%01x for %s' % \
(group[2], status_bytes[msg][2], \
quarter_frame_type[nn][1], dd, smpte_type[tt])]])
self.cmd, self.state = [], 'IDLE'
def handle_syscommon_msg(self, newbyte):
pass # TODO
# System common messages
#
# There are 5 simple formats (which are directly handled here) and
# 1 complex one called MIDI time code quarter frame.
#
# Note: While the MIDI lists 0xf7 as a "system common" message, it
# is actually only used with SysEx messages so it is processed there.
#
# Note: All System message codes don't utilize self.status_byte.
self.hard_clear_status_byte()
if newbyte is not None:
self.cmd.append(newbyte)
c = self.cmd
msg = c[0]
group = ('System Common', 'SysCom', 'SC')
if msg == 0xf1:
# MIDI time code quarter frame
self.handle_syscommon_midi_time_code_quarter_frame_msg(newbyte)
return
elif msg == 0xf2:
# Song position pointer: F2 ll mm
# ll = LSB position, mm = MSB position
if len(c) < 3:
if newbyte is None:
self.handle_garbage_msg(None)
return
ll, mm = c[1], c[2]
decimal = (mm << 7) + ll
self.es_block = self.es
self.putx([0, ['%s: %s 0x%02x 0x%02x (%d)' % \
(group[0], status_bytes[msg][0], ll, mm, decimal),
'%s: %s 0x%02x 0x%02x (%d)' % \
(group[1], status_bytes[msg][1], ll, mm, decimal),
'%s: %s (%d)' % \
(group[2], status_bytes[msg][2], decimal)]])
elif msg == 0xf3:
# Song select: F3 ss
# ss = song selection number
if len(c) < 2:
if newbyte is None:
self.handle_garbage_msg(None)
return
ss = c[1]
self.es_block = self.es
self.putx([0, ['%s: %s number %d' % \
(group[0], status_bytes[msg][0], ss),
'%s: %s number %d' % \
(group[1], status_bytes[msg][1], ss),
'%s: %s # %d' % \
(group[2], status_bytes[msg][2], ss)]])
elif msg == 0xf4 or msg == 0xf5 or msg == 0xf6:
# Undefined 0xf4, Undefined 0xf5, and Tune Request (respectively).
# All are only 1 byte long with no data bytes.
self.es_block = self.es
self.putx([0, ['%s: %s' % (group[0], status_bytes[msg][0]),
'%s: %s' % (group[1], status_bytes[msg][1]),
'%s: %s' % (group[2], status_bytes[msg][2])]])
self.cmd, self.state = [], 'IDLE'
def handle_sysrealtime_msg(self, newbyte):
# System realtime message: 0b11111ttt (t = message type)
#
# Important: These messages are handled differently from all others
# because they are allowed to temporarily interrupt other messages.
# The interrupted messages resume after the realtime message is done.
# Thus, they mostly leave 'self' the way it was found.
#
# Note: All System message codes don't utilize self.status_byte.
old_ss_block, old_es_block = self.ss_block, self.es_block
self.ss_block, self.es_block = self.ss, self.es
group = ('System Realtime', 'SysReal', 'SR')
self.putx([1, ['%s: %s' % (group[0], status_bytes[newbyte][0]),
'%s: %s' % (group[1], status_bytes[newbyte][1]),
'%s: %s' % (group[2], status_bytes[newbyte][2])]])
self.ss_block, self.es_block = old_ss_block, old_es_block
# Deliberately not resetting self.cmd or self.state.
def handle_garbage_msg(self, newbyte):
# Handle messages that are either not handled or are corrupt.
self.es_block = self.es
self.putx([0, ['System realtime message: %s' % status_bytes[newbyte]]])
if newbyte is not None:
self.cmd.append(newbyte)
return
payload = '<empty>'
max_bytes = 16 # Put a limit on the length on the hex dump.
for index in range(len(self.cmd)):
if index == max_bytes:
payload += ' ...'
break
if index == 0:
payload = '0x%02x' % self.cmd[index]
else:
payload += ' 0x%02x' % self.cmd[index]
self.putx([2, ['UNHANDLED DATA: %s' % payload,
'UNHANDLED', '???', '?']])
self.cmd, self.state = [], 'IDLE'
self.hard_clear_status_byte()
def handle_state(self, state, newbyte):
# 'newbyte' can either be:
# 1. Value between 0x00-0xff, deal with the byte normally.
# 2. Value of 'None' which means "flush any buffered data".
if state == 'HANDLE CHANNEL MSG':
self.handle_channel_msg(newbyte)
elif state == 'HANDLE SYSEX MSG':
self.handle_sysex_msg(newbyte)
elif state == 'HANDLE SYSCOMMON MSG':
self.handle_syscommon_msg(newbyte)
elif state == 'HANDLE SYSREALTIME MSG':
self.handle_sysrealtime_msg(newbyte)
elif state == 'BUFFER GARBAGE MSG':
self.handle_garbage_msg(newbyte)
def get_next_state(self, newbyte):
# 'newbyte' must be a valid byte between 0x00 and 0xff.
#
# Try to determine the state based off of the 'newbyte' parameter.
if newbyte in range(0x80, 0xef + 1):
return 'HANDLE CHANNEL MSG'
if newbyte == 0xf0:
return 'HANDLE SYSEX MSG'
if newbyte in range(0xf1, 0xf7):
return'HANDLE SYSCOMMON MSG'
if newbyte in range(0xf8, 0xff + 1):
return 'HANDLE SYSREALTIME MSG'
# Passing 0xf7 is an error; messages don't start with 0xf7.
if newbyte == 0xf7:
return 'BUFFER GARBAGE MSG'
# Next, base the state off of self.status_byte.
if self.status_byte < 0x80:
return 'BUFFER GARBAGE MSG'
return self.get_next_state(self.status_byte)
def decode(self, ss, es, data):
ptype, rxtx, pdata = data
state = 'IDLE'
# For now, ignore all UART packets except the actual data packets.
if ptype != 'DATA':
return
self.ss, self.es = ss, es
# We're only interested in the byte value (not individual bits).
pdata = pdata[0]
@@ -183,29 +586,39 @@ class Decoder(srd.Decoder):
# - Most messages: 1 status byte, 1-2 data bytes.
# - Real-time system messages: always 1 byte.
# - SysEx messages: 1 status byte, n data bytes, EOX byte.
#
# Aspects of the MIDI protocol that complicate decoding:
# - MIDI System Realtime messages can briefly interrupt other
# messages already in progress.
# - "Running Status" allows for omitting the status byte in most
# scenarios if sequential messages have the same status byte.
# - System Exclusive (SysEx) messages can be terminated by ANY
# status byte (not limited to EOX byte).
# State machine.
if self.state == 'IDLE':
# Wait until we see a status byte (bit 7 must be set).
if pdata < 0x80:
return # TODO: How to handle? Ignore?
if pdata >= 0x80 and pdata != 0xf7:
state = self.get_next_state(pdata)
if state != 'HANDLE SYSREALTIME MSG' and self.state != 'IDLE':
# Flush the previous data since a new message is starting.
self.handle_state(self.state, None)
# Cache ss and es -after- flushing previous data.
self.ss, self.es = ss, es
# This is a status byte, remember the start sample.
self.ss_block = ss
if pdata in range(0x80, 0xef + 1):
self.state = 'HANDLE CHANNEL MSG'
elif pdata == 0xf0:
self.state = 'HANDLE SYSEX MSG'
elif pdata in range(0xf1, 0xf7 + 1):
self.state = 'HANDLE SYSCOMMON MSG'
elif pdata in range(0xf8, 0xff + 1):
self.state = 'HANDLE SYSREALTIME MSG'
if state != 'HANDLE SYSREALTIME MSG':
self.ss_block = ss
elif self.state == 'IDLE' or self.state == 'BUFFER GARBAGE MSG':
# Deal with "running status" or that we're buffering garbage.
self.ss, self.es = ss, es
if self.state == 'IDLE':
self.ss_block = ss
state = self.get_next_state(pdata)
else:
self.ss, self.es = ss, es
state = self.state
# Yes, this is intentionally _not_ an 'elif' here.
if self.state == 'HANDLE CHANNEL MSG':
self.handle_channel_msg(pdata)
elif self.state == 'HANDLE SYSEX MSG':
self.handle_sysex_msg(pdata)
elif self.state == 'HANDLE SYSCOMMON MSG':
self.handle_syscommon_msg(pdata)
elif self.state == 'HANDLE SYSREALTIME MSG':
self.handle_sysrealtime_msg(pdata)
if state != 'HANDLE SYSREALTIME MSG':
self.state = state
if state == 'BUFFER GARBAGE MSG':
self.status_byte = 0
self.handle_state(state, pdata)

View File

@@ -182,7 +182,7 @@ class Decoder(srd.Decoder):
self.cnt_overdrive_presence = int(samplerate * x) - 1
x = float(self.options['cnt_overdrive_reset']) / 1000000.0
self.cnt_overdrive_reset = int(samplerate * x) - 1
# Organize values into lists.
self.cnt_bit = [self.cnt_normal_bit, self.cnt_overdrive_bit]
self.cnt_presence = [self.cnt_normal_presence, self.cnt_overdrive_presence]
@@ -286,4 +286,3 @@ class Decoder(srd.Decoder):
# Wait for next slot.
self.state = 'WAIT FOR FALLING EDGE'

View File

@@ -0,0 +1,26 @@
##
## This file is part of the libsigrokdecode project.
##
## Copyright (C) 2016 Daniel Schulte <trilader@schroedingers-bit.net>
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 2 of the License, or
## (at your option) any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program. If not, see <http://www.gnu.org/licenses/>.
##
'''
This protocol decoder can decode PS/2 device -> host communication.
Host -> device communication is currently not supported.
'''
from .pd import Decoder

View File

@@ -0,0 +1,145 @@
##
## This file is part of the libsigrokdecode project.
##
## Copyright (C) 2016 Daniel Schulte <trilader@schroedingers-bit.net>
##
## 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
class Ann:
BIT, START, STOP, PARITY_OK, PARITY_ERR, DATA, WORD = range(7)
Bit = namedtuple('Bit', 'val ss es')
class Decoder(srd.Decoder):
api_version = 2
id = 'ps2'
name = 'PS/2'
longname = 'PS/2'
desc = 'PS/2 keyboard/mouse interface.'
license = 'gplv2+'
inputs = ['logic']
outputs = ['ps2']
channels = (
{'id': 'clk', 'name': 'Clock', 'desc': 'Clock line'},
{'id': 'data', 'name': 'Data', 'desc': 'Data line'},
)
annotations = (
('bit', 'Bit'),
('start-bit', 'Start bit'),
('stop-bit', 'Stop bit'),
('parity-ok', 'Parity OK bit'),
('parity-err', 'Parity error bit'),
('data-bit', 'Data bit'),
('word', 'Word'),
)
annotation_rows = (
('bits', 'Bits', (0,)),
('fields', 'Fields', (1, 2, 3, 4, 5, 6)),
)
def __init__(self):
self.bits = []
self.prev_pins = None
self.prev_clock = None
self.samplenum = 0
self.clock_was_high = False
self.bitcount = 0
def start(self):
self.out_ann = self.register(srd.OUTPUT_ANN)
def putb(self, bit, ann_idx):
b = self.bits[bit]
self.put(b.ss, b.es, self.out_ann, [ann_idx, [str(b.val)]])
def putx(self, bit, ann):
self.put(self.bits[bit].ss, self.bits[bit].es, self.out_ann, ann)
def handle_bits(self, datapin):
# Ignore non start condition bits (useful during keyboard init).
if self.bitcount == 0 and datapin == 1:
return
# Store individual bits and their start/end samplenumbers.
self.bits.append(Bit(datapin, self.samplenum, self.samplenum))
# Fix up end sample numbers of the bits.
if self.bitcount > 0:
b = self.bits[self.bitcount - 1]
self.bits[self.bitcount - 1] = Bit(b.val, b.ss, self.samplenum)
if self.bitcount == 11:
self.bitwidth = self.bits[1].es - self.bits[2].es
b = self.bits[-1]
self.bits[-1] = Bit(b.val, b.ss, b.es + self.bitwidth)
# Find all 11 bits. Start + 8 data + odd parity + stop.
if self.bitcount < 11:
self.bitcount += 1
return
# Extract data word.
word = 0
for i in range(8):
word |= (self.bits[i + 1].val << i)
# Calculate parity.
parity_ok = (bin(word).count('1') + self.bits[9].val) % 2 == 1
# Emit annotations.
for i in range(11):
self.putb(i, Ann.BIT)
self.putx(0, [Ann.START, ['Start bit', 'Start', 'S']])
self.put(self.bits[1].ss, self.bits[8].es, self.out_ann, [Ann.WORD,
['Data: %02x' % word, 'D: %02x' % word, '%02x' % word]])
if parity_ok:
self.putx(9, [Ann.PARITY_OK, ['Parity OK', 'Par OK', 'P']])
else:
self.putx(9, [Ann.PARITY_ERR, ['Parity error', 'Par err', 'PE']])
self.putx(10, [Ann.STOP, ['Stop bit', 'Stop', 'St', 'T']])
self.bits, self.bitcount = [], 0
def find_clk_edge(self, clock_pin, data_pin):
# Ignore sample if the clock pin hasn't changed.
if clock_pin == self.prev_clock:
return
self.prev_clock = clock_pin
# Sample on falling clock edge.
if clock_pin == 1:
return
# Found the correct clock edge, now get the bits.
self.handle_bits(data_pin)
def decode(self, ss, es, data):
for (self.samplenum, pins) in data:
data.itercnt += 1
clock_pin, data_pin = pins[0], pins[1]
# Ignore identical samples.
if self.prev_pins == pins:
continue
self.prev_pins = pins
if clock_pin == 0 and not self.clock_was_high:
continue
self.clock_was_high = True
self.find_clk_edge(clock_pin, data_pin)

View File

@@ -49,7 +49,7 @@ class Decoder(srd.Decoder):
def __init__(self):
self.samplerate = None
self.oldpin = None
self.packet_ss = None
self.ss_packet = None
self.ss = None
self.es = None
self.bits = []
@@ -66,10 +66,10 @@ class Decoder(srd.Decoder):
if len(self.bits) == 24:
grb = reduce(lambda a, b: (a << 1) | b, self.bits)
rgb = (grb & 0xff0000) >> 8 | (grb & 0x00ff00) << 8 | (grb & 0x0000ff)
self.put(self.packet_ss, samplenum, self.out_ann,
self.put(self.ss_packet, samplenum, self.out_ann,
[2, ['#%06x' % rgb]])
self.bits = []
self.packet_ss = None
self.ss_packet = None
def decode(self, ss, es, data):
if not self.samplerate:
@@ -99,7 +99,7 @@ class Decoder(srd.Decoder):
self.inreset = True
self.bits = []
self.packet_ss = None
self.ss_packet = None
self.ss = None
if not self.oldpin and pin:
@@ -116,8 +116,8 @@ class Decoder(srd.Decoder):
self.bits.append(bit_)
self.handle_bits(samplenum)
if self.packet_ss is None:
self.packet_ss = samplenum
if self.ss_packet is None:
self.ss_packet = samplenum
self.ss = samplenum

View File

@@ -19,10 +19,7 @@
##
import sigrokdecode as srd
# Return the specified BCD number (max. 8 bits) as integer.
def bcd2int(b):
return (b & 0x0f) + ((b >> 4) * 10)
from common.srdhelper import bcd2int
def reg_list():
l = []
@@ -55,7 +52,7 @@ class Decoder(srd.Decoder):
('date-time', 'Date/time', (9, 10)),
)
def __init__(self, **kwargs):
def __init__(self):
self.state = 'IDLE'
self.hours = -1
self.minutes = -1

View File

@@ -1,5 +1,5 @@
##
## This file is part of the sigrok project.
## This file is part of the libsigrokdecode project.
##
## Copyright (C) 2015 Uwe Hermann <uwe@hermann-uwe.de>
##

View File

@@ -1,5 +1,5 @@
##
## This file is part of the sigrok project.
## This file is part of the libsigrokdecode project.
##
## Copyright (C) 2015 Uwe Hermann <uwe@hermann-uwe.de>
##
@@ -19,7 +19,7 @@
##
import sigrokdecode as srd
from .lists import *
from common.sdcard import (cmd_names, acmd_names, accepted_voltages, card_status, sd_status)
class Decoder(srd.Decoder):
api_version = 2
@@ -61,7 +61,7 @@ class Decoder(srd.Decoder):
('cmd', 'Commands', tuple(range(128))),
)
def __init__(self, **kwargs):
def __init__(self):
self.state = 'GET COMMAND TOKEN'
self.token = []
self.oldpins = None

View File

@@ -19,57 +19,7 @@
##
import sigrokdecode as srd
# Normal commands (CMD)
cmd_names = {
0: 'GO_IDLE_STATE',
1: 'SEND_OP_COND',
6: 'SWITCH_FUNC',
8: 'SEND_IF_COND',
9: 'SEND_CSD',
10: 'SEND_CID',
12: 'STOP_TRANSMISSION',
13: 'SEND_STATUS',
16: 'SET_BLOCKLEN',
17: 'READ_SINGLE_BLOCK',
18: 'READ_MULTIPLE_BLOCK',
24: 'WRITE_BLOCK',
25: 'WRITE_MULTIPLE_BLOCK',
27: 'PROGRAM_CSD',
28: 'SET_WRITE_PROT',
29: 'CLR_WRITE_PROT',
30: 'SEND_WRITE_PROT',
32: 'ERASE_WR_BLK_START_ADDR',
33: 'ERASE_WR_BLK_END_ADDR',
38: 'ERASE',
42: 'LOCK_UNLOCK',
55: 'APP_CMD',
56: 'GEN_CMD',
58: 'READ_OCR',
59: 'CRC_ON_OFF',
# CMD60-63: Reserved for manufacturer
}
# Application-specific commands (ACMD)
acmd_names = {
13: 'SD_STATUS',
18: 'Reserved for SD security applications',
22: 'SEND_NUM_WR_BLOCKS',
23: 'SET_WR_BLK_ERASE_COUNT',
25: 'Reserved for SD security applications',
26: 'Reserved for SD security applications',
38: 'Reserved for SD security applications',
41: 'SD_SEND_OP_COND',
42: 'SET_CLR_CARD_DETECT',
43: 'Reserved for SD security applications',
44: 'Reserved for SD security applications',
45: 'Reserved for SD security applications',
46: 'Reserved for SD security applications',
47: 'Reserved for SD security applications',
48: 'Reserved for SD security applications',
49: 'Reserved for SD security applications',
51: 'SEND_SCR',
}
from common.sdcard import (cmd_names, acmd_names)
class Decoder(srd.Decoder):
api_version = 2
@@ -96,7 +46,7 @@ class Decoder(srd.Decoder):
('cmd-reply', 'Commands/replies', tuple(range(134))),
)
def __init__(self, **kwargs):
def __init__(self):
self.state = 'IDLE'
self.ss, self.es = 0, 0
self.ss_bit, self.es_bit = 0, 0
@@ -122,7 +72,12 @@ class Decoder(srd.Decoder):
def cmd_name(self, cmd):
c = acmd_names if self.is_acmd else cmd_names
return c.get(cmd, 'Unknown')
s = c.get(cmd, 'Unknown')
# SD mode names for CMD32/33: ERASE_WR_BLK_{START,END}.
# SPI mode names for CMD32/33: ERASE_WR_BLK_{START,END}_ADDR.
if cmd in (32, 33):
s += '_ADDR'
return s
def handle_command_token(self, mosi, miso):
# Command tokens (6 bytes) are sent (MSB-first) by the host.

View File

@@ -18,41 +18,63 @@
## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
##
# Dict which maps command IDs to their names and descriptions.
cmds = {
0x06: ('WREN', 'Write enable'),
0x04: ('WRDI', 'Write disable'),
0x9f: ('RDID', 'Read identification'),
0x05: ('RDSR', 'Read status register'),
0x01: ('WRSR', 'Write status register'),
0x03: ('READ', 'Read data'),
0x0b: ('FAST/READ', 'Fast read data'),
0xbb: ('2READ', '2x I/O read'),
0x20: ('SE', 'Sector erase'),
0xd8: ('BE', 'Block erase'),
0x60: ('CE', 'Chip erase'),
0xc7: ('CE2', 'Chip erase'), # Alternative command ID
0x02: ('PP', 'Page program'),
0xad: ('CP', 'Continuously program mode'),
0xb9: ('DP', 'Deep power down'),
0xab: ('RDP/RES', 'Release from deep powerdown / Read electronic ID'),
0x90: ('REMS', 'Read electronic manufacturer & device ID'),
0xef: ('REMS2', 'Read ID for 2x I/O mode'),
0xb1: ('ENSO', 'Enter secured OTP'),
0xc1: ('EXSO', 'Exit secured OTP'),
0x2b: ('RDSCUR', 'Read security register'),
0x2f: ('WRSCUR', 'Write security register'),
0x70: ('ESRY', 'Enable SO to output RY/BY#'),
0x80: ('DSRY', 'Disable SO to output RY/BY#'),
}
from collections import OrderedDict
# OrderedDict which maps command IDs to their names and descriptions.
# Please keep this sorted by command ID.
# Don't forget to update 'Ann' in pd.py if you add/remove items here.
cmds = OrderedDict([
(0x01, ('WRSR', 'Write status register')),
(0x02, ('PP', 'Page program')),
(0x03, ('READ', 'Read data')),
(0x04, ('WRDI', 'Write disable')),
(0x05, ('RDSR', 'Read status register')),
(0x06, ('WREN', 'Write enable')),
(0x0b, ('FAST/READ', 'Fast read data')),
(0x20, ('SE', 'Sector erase')),
(0x2b, ('RDSCUR', 'Read security register')),
(0x2f, ('WRSCUR', 'Write security register')),
(0x35, ('RDSR2', 'Read status register 2')),
(0x60, ('CE', 'Chip erase')),
(0x70, ('ESRY', 'Enable SO to output RY/BY#')),
(0x80, ('DSRY', 'Disable SO to output RY/BY#')),
(0x90, ('REMS', 'Read electronic manufacturer & device ID')),
(0x9f, ('RDID', 'Read identification')),
(0xab, ('RDP/RES', 'Release from deep powerdown / Read electronic ID')),
(0xad, ('CP', 'Continuously program mode')),
(0xb1, ('ENSO', 'Enter secured OTP')),
(0xb9, ('DP', 'Deep power down')),
(0xbb, ('2READ', '2x I/O read')), # a.k.a. "Fast read dual I/O".
(0xc1, ('EXSO', 'Exit secured OTP')),
(0xc7, ('CE2', 'Chip erase')), # Alternative command ID
(0xd8, ('BE', 'Block erase')),
(0xef, ('REMS2', 'Read ID for 2x I/O mode')),
])
device_name = {
0x14: 'MX25L1605D',
0x15: 'MX25L3205D',
0x16: 'MX25L6405D',
'fidelix': {
0x15: 'FM25Q32',
},
'macronix': {
0x14: 'MX25L1605D',
0x15: 'MX25L3205D',
0x16: 'MX25L6405D',
},
}
chips = {
# FIDELIX
'fidelix_fm25q32': {
'vendor': 'FIDELIX',
'model': 'FM25Q32',
'res_id': 0x15,
'rems_id': 0xa115,
'rems2_id': 0xa115,
'rdid_id': 0xa14016,
'page_size': 256,
'sector_size': 4 * 1024,
'block_size': 64 * 1024,
},
# Macronix
'macronix_mx25l1605d': {
'vendor': 'Macronix',

View File

@@ -1,7 +1,7 @@
##
## This file is part of the libsigrokdecode project.
##
## Copyright (C) 2011-2015 Uwe Hermann <uwe@hermann-uwe.de>
## Copyright (C) 2011-2016 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
@@ -21,9 +21,31 @@
import sigrokdecode as srd
from .lists import *
L = len(cmds)
# Don't forget to keep this in sync with 'cmds' is lists.py.
class Ann:
WRSR, PP, READ, WRDI, RDSR, WREN, FAST_READ, SE, RDSCUR, WRSCUR, \
RDSR2, CE, ESRY, DSRY, REMS, RDID, RDP_RES, CP, ENSO, DP, READ2X, \
EXSO, CE2, BE, REMS2, \
BIT, FIELD, WARN = range(L + 3)
def cmd_annotation_classes():
return tuple([tuple([cmd[0].lower(), cmd[1]]) for cmd in cmds.values()])
def decode_dual_bytes(sio0, sio1):
# Given a byte in SIO0 (MOSI) of even bits and a byte in
# SIO1 (MISO) of odd bits, return a tuple of two bytes.
def combine_byte(even, odd):
result = 0
for bit in range(4):
if even & (1 << bit):
result |= 1 << (bit*2)
if odd & (1 << bit):
result |= 1 << ((bit*2) + 1)
return result
return (combine_byte(sio0 >> 4, sio1 >> 4), combine_byte(sio0, sio1))
def decode_status_reg(data):
# TODO: Additional per-bit(s) self.put() calls with correct start/end.
@@ -59,21 +81,40 @@ class Decoder(srd.Decoder):
inputs = ['spi']
outputs = ['spiflash']
annotations = cmd_annotation_classes() + (
('bits', 'Bits'),
('bits2', 'Bits2'),
('warnings', 'Warnings'),
('bit', 'Bit'),
('field', 'Field'),
('warning', 'Warning'),
)
annotation_rows = (
('bits', 'Bits', (24, 25)),
('commands', 'Commands', tuple(range(23 + 1))),
('warnings', 'Warnings', (26,)),
('bits', 'Bits', (L + 0,)),
('fields', 'Fields', (L + 1,)),
('commands', 'Commands', tuple(range(len(cmds)))),
('warnings', 'Warnings', (L + 2,)),
)
options = (
{'id': 'chip', 'desc': 'Chip', 'default': tuple(chips.keys())[0],
'values': tuple(chips.keys())},
{'id': 'format', 'desc': 'Data format', 'default': 'hex',
'values': ('hex', 'ascii')},
)
def __init__(self):
self.device_id = -1
self.on_end_transaction = None
self.end_current_transaction()
# Build dict mapping command keys to handler functions. Each
# command in 'cmds' (defined in lists.py) has a matching
# handler self.handle_<shortname>.
def get_handler(cmd):
s = 'handle_%s' % cmds[cmd][0].lower().replace('/', '_')
return getattr(self, s)
self.cmd_handlers = dict((cmd, get_handler(cmd)) for cmd in cmds.keys())
def end_current_transaction(self):
if self.on_end_transaction is not None: # Callback for CS# transition.
self.on_end_transaction()
self.on_end_transaction = None
self.state = None
self.cmdstate = 1
self.addr = 0
@@ -82,43 +123,78 @@ class Decoder(srd.Decoder):
def start(self):
self.out_ann = self.register(srd.OUTPUT_ANN)
self.chip = chips[self.options['chip']]
self.vendor = self.options['chip'].split('_')[0]
def putx(self, data):
# Simplification, most annotations span exactly one SPI byte/packet.
self.put(self.ss, self.es, self.out_ann, data)
def putb(self, data):
self.put(self.block_ss, self.block_es, self.out_ann, data)
def putf(self, data):
self.put(self.ss_field, self.es_field, self.out_ann, data)
def putc(self, data):
self.put(self.ss_cmd, self.es_cmd, self.out_ann, data)
def device(self):
return device_name[self.vendor].get(self.device_id, 'Unknown')
def vendor_device(self):
return '%s %s' % (self.chip['vendor'], self.device())
def cmd_ann_list(self):
x, s = cmds[self.state][0], cmds[self.state][1]
return ['Command: %s (%s)' % (s, x), 'Command: %s' % s,
'Cmd: %s' % s, 'Cmd: %s' % x, x]
def cmd_vendor_dev_list(self):
c, d = cmds[self.state], 'Device = %s' % self.vendor_device()
return ['%s (%s): %s' % (c[1], c[0], d), '%s: %s' % (c[1], d),
'%s: %s' % (c[0], d), d, self.vendor_device()]
def emit_cmd_byte(self):
self.ss_cmd = self.ss
self.putx([Ann.FIELD, self.cmd_ann_list()])
self.addr = 0
def emit_addr_bytes(self, mosi):
self.addr |= (mosi << ((4 - self.cmdstate) * 8))
b = ((3 - (self.cmdstate - 2)) * 8) - 1
self.putx([Ann.BIT,
['Address bits %d..%d: 0x%02x' % (b, b - 7, mosi),
'Addr bits %d..%d: 0x%02x' % (b, b - 7, mosi),
'Addr bits %d..%d' % (b, b - 7), 'A%d..A%d' % (b, b - 7)]])
if self.cmdstate == 2:
self.ss_field = self.ss
if self.cmdstate == 4:
self.es_field = self.es
self.putf([Ann.FIELD, ['Address: 0x%06x' % self.addr,
'Addr: 0x%06x' % self.addr, '0x%06x' % self.addr]])
def handle_wren(self, mosi, miso):
self.putx([0, ['Command: %s' % cmds[self.state][1]]])
self.putx([Ann.WREN, self.cmd_ann_list()])
self.state = None
def handle_wrdi(self, mosi, miso):
pass # TODO
# TODO: Check/display device ID / name
def handle_rdid(self, mosi, miso):
if self.cmdstate == 1:
# Byte 1: Master sends command ID.
self.ss_block = self.ss
self.putx([2, ['Command: %s' % cmds[self.state][1]]])
self.emit_cmd_byte()
elif self.cmdstate == 2:
# Byte 2: Slave sends the JEDEC manufacturer ID.
self.putx([2, ['Manufacturer ID: 0x%02x' % miso]])
self.putx([Ann.FIELD, ['Manufacturer ID: 0x%02x' % miso]])
elif self.cmdstate == 3:
# Byte 3: Slave sends the memory type (0x20 for this chip).
self.putx([2, ['Memory type: 0x%02x' % miso]])
# Byte 3: Slave sends the memory type.
self.putx([Ann.FIELD, ['Memory type: 0x%02x' % miso]])
elif self.cmdstate == 4:
# Byte 4: Slave sends the device ID.
self.device_id = miso
self.putx([2, ['Device ID: 0x%02x' % miso]])
self.putx([Ann.FIELD, ['Device ID: 0x%02x' % miso]])
if self.cmdstate == 4:
# TODO: Check self.device_id is valid & exists in device_names.
# TODO: Same device ID? Check!
d = 'Device: Macronix %s' % device_name[self.device_id]
self.put(self.ss_block, self.es, self.out_ann, [0, [d]])
self.es_cmd = self.es
self.putc([Ann.RDID, self.cmd_vendor_dev_list()])
self.state = None
else:
self.cmdstate += 1
@@ -130,52 +206,69 @@ class Decoder(srd.Decoder):
# When done, the master de-asserts CS# again.
if self.cmdstate == 1:
# Byte 1: Master sends command ID.
self.putx([3, ['Command: %s' % cmds[self.state][1]]])
self.emit_cmd_byte()
elif self.cmdstate >= 2:
# Bytes 2-x: Slave sends status register as long as master clocks.
if self.cmdstate <= 3: # TODO: While CS# asserted.
self.putx([24, ['Status register: 0x%02x' % miso]])
self.putx([25, [decode_status_reg(miso)]])
if self.cmdstate == 3: # TODO: If CS# got de-asserted.
self.state = None
return
self.es_cmd = self.es
self.putx([Ann.BIT, [decode_status_reg(miso)]])
self.putx([Ann.FIELD, ['Status register']])
self.putc([Ann.RDSR, self.cmd_ann_list()])
self.cmdstate += 1
def handle_rdsr2(self, mosi, miso):
# Read status register 2: Master asserts CS#, sends RDSR2 command,
# reads status register 2 byte. If CS# is kept asserted, the status
# register 2 can be read continuously / multiple times in a row.
# When done, the master de-asserts CS# again.
if self.cmdstate == 1:
# Byte 1: Master sends command ID.
self.emit_cmd_byte()
elif self.cmdstate >= 2:
# Bytes 2-x: Slave sends status register 2 as long as master clocks.
self.es_cmd = self.es
# TODO: Decode status register 2 correctly.
self.putx([Ann.BIT, [decode_status_reg(miso)]])
self.putx([Ann.FIELD, ['Status register 2']])
self.putc([Ann.RDSR2, self.cmd_ann_list()])
self.cmdstate += 1
def handle_wrsr(self, mosi, miso):
pass # TODO
# Write status register: Master asserts CS#, sends WRSR command,
# writes 1 or 2 status register byte(s).
# When done, the master de-asserts CS# again. If this doesn't happen
# the WRSR command will not be executed.
if self.cmdstate == 1:
# Byte 1: Master sends command ID.
self.emit_cmd_byte()
elif self.cmdstate == 2:
# Byte 2: Master sends status register 1.
self.putx([Ann.BIT, [decode_status_reg(miso)]])
self.putx([Ann.FIELD, ['Status register 1']])
elif self.cmdstate == 3:
# Byte 3: Master sends status register 2.
# TODO: Decode status register 2 correctly.
self.putx([Ann.BIT, [decode_status_reg(miso)]])
self.putx([Ann.FIELD, ['Status register 2']])
self.es_cmd = self.es
self.putc([Ann.WRSR, self.cmd_ann_list()])
self.cmdstate += 1
def handle_read(self, mosi, miso):
# Read data bytes: Master asserts CS#, sends READ command, sends
# 3-byte address, reads >= 1 data bytes, de-asserts CS#.
if self.cmdstate == 1:
# Byte 1: Master sends command ID.
self.putx([5, ['Command: %s' % cmds[self.state][1]]])
self.emit_cmd_byte()
elif self.cmdstate in (2, 3, 4):
# Bytes 2/3/4: Master sends read address (24bits, MSB-first).
self.addr |= (mosi << ((4 - self.cmdstate) * 8))
# self.putx([0, ['Read address, byte %d: 0x%02x' % \
# (4 - self.cmdstate, mosi)]])
if self.cmdstate == 4:
self.putx([24, ['Read address: 0x%06x' % self.addr]])
self.addr = 0
self.emit_addr_bytes(mosi)
elif self.cmdstate >= 5:
# Bytes 5-x: Master reads data bytes (until CS# de-asserted).
# TODO: For now we hardcode 256 bytes per READ command.
if self.cmdstate <= 256 + 4: # TODO: While CS# asserted.
self.data.append(miso)
# self.putx([0, ['New read byte: 0x%02x' % miso]])
if self.cmdstate == 256 + 4: # TODO: If CS# got de-asserted.
# s = ', '.join(map(hex, self.data))
s = ''.join(map(chr, self.data))
self.putx([24, ['Read data']])
self.putx([25, ['Read data: %s' % s]])
self.data = []
self.state = None
return
self.es_field = self.es # Will be overwritten for each byte.
if self.cmdstate == 5:
self.ss_field = self.ss
self.on_end_transaction = lambda: self.output_data_block('Data', Ann.READ)
self.data.append(miso)
self.cmdstate += 1
def handle_fast_read(self, mosi, miso):
@@ -183,60 +276,70 @@ class Decoder(srd.Decoder):
# 3-byte address + 1 dummy byte, reads >= 1 data bytes, de-asserts CS#.
if self.cmdstate == 1:
# Byte 1: Master sends command ID.
self.putx([5, ['Command: %s' % cmds[self.state][1]]])
self.emit_cmd_byte()
elif self.cmdstate in (2, 3, 4):
# Bytes 2/3/4: Master sends read address (24bits, MSB-first).
self.putx([24, ['AD%d: 0x%02x' % (self.cmdstate - 1, mosi)]])
if self.cmdstate == 2:
self.block_ss = self.ss
self.addr |= (mosi << ((4 - self.cmdstate) * 8))
self.emit_addr_bytes(mosi)
elif self.cmdstate == 5:
self.putx([24, ['Dummy byte: 0x%02x' % mosi]])
self.block_es = self.es
self.putb([5, ['Read address: 0x%06x' % self.addr]])
self.addr = 0
self.putx([Ann.BIT, ['Dummy byte: 0x%02x' % mosi]])
elif self.cmdstate >= 6:
# Bytes 6-x: Master reads data bytes (until CS# de-asserted).
# TODO: For now we hardcode 32 bytes per FAST READ command.
self.es_field = self.es # Will be overwritten for each byte.
if self.cmdstate == 6:
self.block_ss = self.ss
if self.cmdstate <= 32 + 5: # TODO: While CS# asserted.
self.data.append(miso)
if self.cmdstate == 32 + 5: # TODO: If CS# got de-asserted.
self.block_es = self.es
s = ' '.join([hex(b)[2:] for b in self.data])
self.putb([25, ['Read data: %s' % s]])
self.data = []
self.state = None
return
self.ss_field = self.ss
self.on_end_transaction = lambda: self.output_data_block('Data', Ann.FAST_READ)
self.data.append(miso)
self.cmdstate += 1
def handle_2read(self, mosi, miso):
pass # TODO
# 2x I/O read (fast read dual I/O): Master asserts CS#, sends 2READ
# command, sends 3-byte address + 1 dummy byte, reads >= 1 data bytes,
# de-asserts CS#. All data after the command is sent via two I/O pins.
# MOSI = SIO0 = even bits, MISO = SIO1 = odd bits.
if self.cmdstate != 1:
b1, b2 = decode_dual_bytes(mosi, miso)
if self.cmdstate == 1:
# Byte 1: Master sends command ID.
self.emit_cmd_byte()
elif self.cmdstate == 2:
# Bytes 2/3(/4): Master sends read address (24bits, MSB-first).
# Handle bytes 2 and 3 here.
self.emit_addr_bytes(b1)
self.cmdstate = 3
self.emit_addr_bytes(b2)
elif self.cmdstate == 4:
# Byte 5: Dummy byte. Also handle byte 4 (address LSB) here.
self.emit_addr_bytes(b1)
self.cmdstate = 5
self.putx([Ann.BIT, ['Dummy byte: 0x%02x' % b2]])
elif self.cmdstate >= 6:
# Bytes 6-x: Master reads data bytes (until CS# de-asserted).
self.es_field = self.es # Will be overwritten for each byte.
if self.cmdstate == 6:
self.ss_field = self.ss
self.on_end_transaction = lambda: self.output_data_block('Data', Ann.READ2X)
self.data.append(b1)
self.data.append(b2)
self.cmdstate += 1
# TODO: Warn/abort if we don't see the necessary amount of bytes.
# TODO: Warn if WREN was not seen before.
def handle_se(self, mosi, miso):
if self.cmdstate == 1:
# Byte 1: Master sends command ID.
self.addr = 0
self.ss_block = self.ss
self.putx([8, ['Command: %s' % cmds[self.state][1]]])
self.emit_cmd_byte()
elif self.cmdstate in (2, 3, 4):
# Bytes 2/3/4: Master sends sector address (24bits, MSB-first).
self.addr |= (mosi << ((4 - self.cmdstate) * 8))
# self.putx([0, ['Sector address, byte %d: 0x%02x' % \
# (4 - self.cmdstate, mosi)]])
self.emit_addr_bytes(mosi)
if self.cmdstate == 4:
self.es_cmd = self.es
d = 'Erase sector %d (0x%06x)' % (self.addr, self.addr)
self.put(self.ss_block, self.es, self.out_ann, [24, [d]])
self.putc([Ann.SE, [d]])
# TODO: Max. size depends on chip, check that too if possible.
if self.addr % 4096 != 0:
# Sector addresses must be 4K-aligned (same for all 3 chips).
d = 'Warning: Invalid sector address!'
self.put(self.ss_block, self.es, self.out_ann, [101, [d]])
self.putc([Ann.WARN, ['Warning: Invalid sector address!']])
self.state = None
else:
self.cmdstate += 1
@@ -255,31 +358,17 @@ class Decoder(srd.Decoder):
# page address, sends >= 1 data bytes, de-asserts CS#.
if self.cmdstate == 1:
# Byte 1: Master sends command ID.
self.putx([12, ['Command: %s' % cmds[self.state][1]]])
self.emit_cmd_byte()
elif self.cmdstate in (2, 3, 4):
# Bytes 2/3/4: Master sends page address (24bits, MSB-first).
self.addr |= (mosi << ((4 - self.cmdstate) * 8))
# self.putx([0, ['Page address, byte %d: 0x%02x' % \
# (4 - self.cmdstate, mosi)]])
if self.cmdstate == 4:
self.putx([24, ['Page address: 0x%06x' % self.addr]])
self.addr = 0
self.emit_addr_bytes(mosi)
elif self.cmdstate >= 5:
# Bytes 5-x: Master sends data bytes (until CS# de-asserted).
# TODO: For now we hardcode 256 bytes per page / PP command.
if self.cmdstate <= 256 + 4: # TODO: While CS# asserted.
self.data.append(mosi)
# self.putx([0, ['New data byte: 0x%02x' % mosi]])
if self.cmdstate == 256 + 4: # TODO: If CS# got de-asserted.
# s = ', '.join(map(hex, self.data))
s = ''.join(map(chr, self.data))
self.putx([24, ['Page data']])
self.putx([25, ['Page data: %s' % s]])
self.data = []
self.state = None
return
self.es_field = self.es # Will be overwritten for each byte.
if self.cmdstate == 5:
self.ss_field = self.ss
self.on_end_transaction = lambda: self.output_data_block('Data', Ann.PP)
self.data.append(mosi)
self.cmdstate += 1
def handle_cp(self, mosi, miso):
@@ -289,38 +378,52 @@ class Decoder(srd.Decoder):
pass # TODO
def handle_rdp_res(self, mosi, miso):
pass # TODO
if self.cmdstate == 1:
# Byte 1: Master sends command ID.
self.emit_cmd_byte()
elif self.cmdstate in (2, 3, 4):
# Bytes 2/3/4: Master sends three dummy bytes.
self.putx([Ann.FIELD, ['Dummy byte: %02x' % mosi]])
elif self.cmdstate == 5:
# Byte 5: Slave sends device ID.
self.es_cmd = self.es
self.device_id = miso
self.putx([Ann.FIELD, ['Device ID: %s' % self.device()]])
d = 'Device = %s' % self.vendor_device()
self.putc([Ann.RDP_RES, self.cmd_vendor_dev_list()])
self.state = None
self.cmdstate += 1
def handle_rems(self, mosi, miso):
if self.cmdstate == 1:
# Byte 1: Master sends command ID.
self.ss_block = self.ss
self.putx([16, ['Command: %s' % cmds[self.state][1]]])
self.emit_cmd_byte()
elif self.cmdstate in (2, 3):
# Bytes 2/3: Master sends two dummy bytes.
# TODO: Check dummy bytes? Check reply from device?
self.putx([24, ['Dummy byte: %s' % mosi]])
self.putx([Ann.FIELD, ['Dummy byte: 0x%02x' % mosi]])
elif self.cmdstate == 4:
# Byte 4: Master sends 0x00 or 0x01.
# 0x00: Master wants manufacturer ID as first reply byte.
# 0x01: Master wants device ID as first reply byte.
self.manufacturer_id_first = True if (mosi == 0x00) else False
d = 'manufacturer' if (mosi == 0x00) else 'device'
self.putx([24, ['Master wants %s ID first' % d]])
self.putx([Ann.FIELD, ['Master wants %s ID first' % d]])
elif self.cmdstate == 5:
# Byte 5: Slave sends manufacturer ID (or device ID).
self.ids = [miso]
d = 'Manufacturer' if self.manufacturer_id_first else 'Device'
self.putx([24, ['%s ID' % d]])
self.putx([Ann.FIELD, ['%s ID: 0x%02x' % (d, miso)]])
elif self.cmdstate == 6:
# Byte 6: Slave sends device ID (or manufacturer ID).
self.ids.append(miso)
d = 'Manufacturer' if self.manufacturer_id_first else 'Device'
self.putx([24, ['%s ID' % d]])
d = 'Device' if self.manufacturer_id_first else 'Manufacturer'
self.putx([Ann.FIELD, ['%s ID: 0x%02x' % (d, miso)]])
if self.cmdstate == 6:
id = self.ids[1] if self.manufacturer_id_first else self.ids[0]
self.putx([24, ['Device: Macronix %s' % device_name[id]]])
self.device_id = id
self.es_cmd = self.es
self.putc([Ann.REMS, self.cmd_vendor_dev_list()])
self.state = None
else:
self.cmdstate += 1
@@ -346,34 +449,37 @@ class Decoder(srd.Decoder):
def handle_dsry(self, mosi, miso):
pass # TODO
def decode(self, ss, es, data):
def output_data_block(self, label, idx):
# Print accumulated block of data
# (called on CS# de-assert via self.on_end_transaction callback).
self.es_cmd = self.es # End on the CS# de-assert sample.
if self.options['format'] == 'hex':
s = ' '.join([('%02x' % b) for b in self.data])
else:
s = ''.join(map(chr, self.data))
self.putf([Ann.FIELD, ['%s (%d bytes)' % (label, len(self.data))]])
self.putc([idx, ['%s (addr 0x%06x, %d bytes): %s' % \
(cmds[self.state][1], self.addr, len(self.data), s)]])
def decode(self, ss, es, data):
ptype, mosi, miso = data
# if ptype == 'DATA':
# self.putx([0, ['MOSI: 0x%02x, MISO: 0x%02x' % (mosi, miso)]])
self.ss, self.es = ss, es
# if ptype == 'CS-CHANGE':
# if mosi == 1 and miso == 0:
# self.putx([0, ['Asserting CS#']])
# elif mosi == 0 and miso == 1:
# self.putx([0, ['De-asserting CS#']])
if ptype == 'CS-CHANGE':
self.end_current_transaction()
if ptype != 'DATA':
return
self.ss, self.es = ss, es
# If we encountered a known chip command, enter the resp. state.
if self.state is None:
self.state = mosi
self.cmdstate = 1
# Handle commands.
if self.state in cmds:
s = 'handle_%s' % cmds[self.state][0].lower().replace('/', '_')
handle_reg = getattr(self, s)
handle_reg(mosi, miso)
else:
self.putx([24, ['Unknown command: 0x%02x' % mosi]])
try:
self.cmd_handlers[self.state](mosi, miso)
except KeyError:
self.putx([Ann.BIT, ['Unknown command: 0x%02x' % mosi]])
self.state = None

View File

@@ -17,7 +17,8 @@
## 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/>.
## along with this program; if not, write to the Free Software
## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
##
'''

View File

@@ -17,7 +17,8 @@
## 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/>.
## 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

View File

@@ -52,7 +52,7 @@ class Decoder(srd.Decoder):
def __init__(self):
self.oldstep = None
self.prev_step_ss = None
self.ss_prev_step = None
self.pos = 0
self.prev_speed = None
self.prev_pos = None
@@ -70,18 +70,18 @@ class Decoder(srd.Decoder):
self.unit = 'mm'
def step(self, ss, direction):
if self.prev_step_ss is not None:
delta = ss - self.prev_step_ss
if self.ss_prev_step is not None:
delta = ss - self.ss_prev_step
speed = self.samplerate / delta / self.scale
speed_txt = self.format % speed
pos_txt = self.format % (self.pos / self.scale)
self.put(self.prev_step_ss, ss, self.out_ann,
self.put(self.ss_prev_step, ss, self.out_ann,
[0, [speed_txt + ' ' + self.unit + '/s', speed_txt]])
self.put(self.prev_step_ss, ss, self.out_ann,
self.put(self.ss_prev_step, ss, self.out_ann,
[1, [pos_txt + ' ' + self.unit, pos_txt]])
self.pos += (1 if direction else -1)
self.prev_step_ss = ss
self.ss_prev_step = ss
def metadata(self, key, value):
if key == srd.SRD_CONF_SAMPLERATE:

View File

@@ -20,19 +20,29 @@
##
import sigrokdecode as srd
from collections import deque
class SamplerateError(Exception):
pass
def normalize_time(t):
if t >= 1.0:
return '%.3f s' % t
return '%.3f s (%.3f Hz)' % (t, (1/t))
elif t >= 0.001:
return '%.3f ms' % (t * 1000.0)
if 1/t/1000 < 1:
return '%.3f ms (%.3f Hz)' % (t * 1000.0, (1/t))
else:
return '%.3f ms (%.3f kHz)' % (t * 1000.0, (1/t)/1000)
elif t >= 0.000001:
return '%.3f μs' % (t * 1000.0 * 1000.0)
if 1/t/1000/1000 < 1:
return '%.3f μs (%.3f kHz)' % (t * 1000.0 * 1000.0, (1/t)/1000)
else:
return '%.3f μs (%.3f MHz)' % (t * 1000.0 * 1000.0, (1/t)/1000/1000)
elif t >= 0.000000001:
return '%.3f ns' % (t * 1000.0 * 1000.0 * 1000.0)
if 1/t/1000/1000/1000:
return '%.3f ns (%.3f MHz)' % (t * 1000.0 * 1000.0 * 1000.0, (1/t)/1000/1000)
else:
return '%.3f ns (%.3f GHz)' % (t * 1000.0 * 1000.0 * 1000.0, (1/t)/1000/1000/1000)
else:
return '%f' % t
@@ -40,7 +50,7 @@ class Decoder(srd.Decoder):
api_version = 2
id = 'timing'
name = 'Timing'
longname = 'Timing calculation'
longname = 'Timing calculation with frequency and averaging'
desc = 'Calculate time between edges.'
license = 'gplv2+'
inputs = ['logic']
@@ -50,15 +60,22 @@ class Decoder(srd.Decoder):
)
annotations = (
('time', 'Time'),
('average', 'Average'),
)
annotation_rows = (
('time', 'Time', (0,)),
('average', 'Average', (1,)),
)
options = (
{ 'id': 'avg_period', 'desc': 'Averaging period', 'default': 100 },
)
def __init__(self):
self.samplerate = None
self.oldpin = None
self.last_samplenum = None
self.last_n = deque()
self.chunks = 0
def metadata(self, key, value):
if key == srd.SRD_CONF_SAMPLERATE:
@@ -73,10 +90,6 @@ class Decoder(srd.Decoder):
for (self.samplenum, (pin,)) in data:
data.itercnt += 1
# Ignore identical samples early on (for performance reasons).
if self.oldpin == pin:
continue
if self.oldpin is None:
self.oldpin = pin
self.last_samplenum = self.samplenum
@@ -85,10 +98,26 @@ class Decoder(srd.Decoder):
if self.oldpin != pin:
samples = self.samplenum - self.last_samplenum
t = samples / self.samplerate
self.chunks += 1
# Report the timing normalized.
self.put(self.last_samplenum, self.samplenum, self.out_ann,
[0, [normalize_time(t)]])
# Don't insert the first chunk into the averaging as it is
# not complete probably.
if self.last_samplenum is None or self.chunks < 2:
# Report the timing normalized.
self.put(self.last_samplenum, self.samplenum, self.out_ann,
[0, [normalize_time(t)]])
else:
if t > 0:
self.last_n.append(t)
if len(self.last_n) > self.options['avg_period']:
self.last_n.popleft()
# Report the timing normalized.
self.put(self.last_samplenum, self.samplenum, self.out_ann,
[0, [normalize_time(t)]])
self.put(self.last_samplenum, self.samplenum, self.out_ann,
[1, [normalize_time(sum(self.last_n) / len(self.last_n))]])
# Store data for next round.
self.last_samplenum = self.samplenum

View File

@@ -141,8 +141,8 @@ class Decoder(srd.Decoder):
self.request = {}
self.request_id = 0
self.transaction_state = 'IDLE'
self.transaction_ss = None
self.transaction_es = None
self.ss_transaction = None
self.es_transaction = None
self.transaction_ep = None
self.transaction_addr = None
self.wrote_pcap_header = False
@@ -182,7 +182,7 @@ class Decoder(srd.Decoder):
addr = self.transaction_addr
if not (addr, ep) in self.request:
self.request[(addr, ep)] = {'setup_data': [], 'data': [],
'type': None, 'ss': self.transaction_ss, 'es': None,
'type': None, 'ss': self.ss_transaction, 'es': None,
'id': self.request_id, 'addr': addr, 'ep': ep}
self.request_id += 1
request_started = 1
@@ -192,16 +192,16 @@ class Decoder(srd.Decoder):
if request['type'] in (None, 'BULK IN') and self.transaction_type == 'IN':
request['type'] = 'BULK IN'
request['data'] += self.transaction_data
request['es'] = self.transaction_es
request['es'] = self.es_transaction
self.handle_request(request_started, request_end)
elif request['type'] in (None, 'BULK OUT') and self.transaction_type == 'OUT':
request['type'] = 'BULK OUT'
request['data'] += self.transaction_data
request['es'] = self.transaction_es
request['es'] = self.es_transaction
self.handle_request(request_started, request_end)
# CONTROL, SETUP stage
elif request['type'] == None and self.transaction_type == 'SETUP':
elif request['type'] is None and self.transaction_type == 'SETUP':
request['setup_data'] = self.transaction_data
request['wLength'] = struct.unpack('<H',
bytes(self.transaction_data[6:8]))[0]
@@ -223,11 +223,11 @@ class Decoder(srd.Decoder):
# CONTROL, STATUS stage
elif request['type'] == 'SETUP IN' and self.transaction_type == 'OUT':
request['es'] = self.transaction_es
request['es'] = self.es_transaction
self.handle_request(0, request_end)
elif request['type'] == 'SETUP OUT' and self.transaction_type == 'IN':
request['es'] = self.transaction_es
request['es'] = self.es_transaction
self.handle_request(0, request_end)
else:
@@ -306,12 +306,12 @@ class Decoder(srd.Decoder):
if pname == 'SOF':
return
if self.transaction_state == 'TOKEN RECEIVED':
transaction_timeout = self.transaction_es
transaction_timeout = self.es_transaction
# Token length is 35 bits, timeout is 16..18 bit times
# (USB 2.0 7.1.19.1).
transaction_timeout += int((self.transaction_es - self.transaction_ss) / 2)
transaction_timeout += int((self.es_transaction - self.ss_transaction) / 2)
if ss > transaction_timeout:
self.transaction_es = transaction_timeout
self.es_transaction = transaction_timeout
self.handshake = 'timeout'
self.handle_transfer()
self.transaction_state = 'IDLE'
@@ -323,8 +323,8 @@ class Decoder(srd.Decoder):
sync, pid, addr, ep, crc5 = pinfo
self.transaction_data = []
self.transaction_ss = ss
self.transaction_es = es
self.ss_transaction = ss
self.es_transaction = es
self.transaction_state = 'TOKEN RECEIVED'
self.transaction_ep = ep
self.transaction_addr = addr
@@ -347,7 +347,7 @@ class Decoder(srd.Decoder):
self.handshake = pname
self.transaction_state = 'IDLE'
self.transaction_es = es
self.es_transaction = es
self.handle_transfer()
elif pname == 'PRE':

View File

@@ -55,7 +55,7 @@ class Decoder(srd.Decoder):
self._d1_prev = None
self._state = None
self._ss_state = None
self.ss_state = None
self.ss_bit = None
self.es_bit = None
@@ -98,8 +98,8 @@ class Decoder(srd.Decoder):
elif self._state == 'invalid':
ann = [1, [self._state]]
if ann:
self.put(self._ss_state, self.samplenum, self.out_ann, ann)
self._ss_state = self.samplenum
self.put(self.ss_state, self.samplenum, self.out_ann, ann)
self.ss_state = self.samplenum
self._state = state
self._bits = []

View File

@@ -18,177 +18,9 @@
##
import sigrokdecode as srd
MODULE_ID = {
0x01: 'GBIC',
0x02: 'Integrated module/connector',
0x03: 'SFP',
0x04: '300-pin XBI',
0x05: 'XENPAK',
0x06: 'XFP',
0x07: 'XFF',
0x08: 'XFP-E',
0x09: 'XPAK',
0x0a: 'X2',
}
ALARM_THRESHOLDS = {
0: "Temp high alarm",
2: "Temp low alarm",
4: "Temp high warning",
6: "Temp low warning",
16: "Bias high alarm",
18: "Bias low alarm",
20: "Bias high warning",
22: "Bias low warning",
24: "TX power high alarm",
26: "TX power low alarm",
28: "TX power high warning",
30: "TX power low warning",
32: "RX power high alarm",
34: "RX power low alarm",
36: "RX power high warning",
38: "RX power low warning",
40: "AUX 1 high alarm",
42: "AUX 1 low alarm",
44: "AUX 1 high warning",
46: "AUX 1 low warning",
48: "AUX 2 high alarm",
50: "AUX 2 low alarm",
52: "AUX 2 high warning",
54: "AUX 2 low warning",
}
AD_READOUTS = {
0: "Module temperature",
4: "TX bias current",
6: "Measured TX output power",
8: "Measured RX input power",
10: "AUX 1 measurement",
12: "AUX 2 measurement",
}
GCS_BITS = [
"TX disable",
"Soft TX disable",
"MOD_NR",
"P_Down",
"Soft P_Down",
"Interrupt",
"RX_LOS",
"Data_Not_Ready",
"TX_NR",
"TX_Fault",
"TX_CDR not locked",
"RX_NR",
"RX_CDR not locked",
]
CONNECTOR = {
0x01: "SC",
0x02: "Fibre Channel style 1 copper",
0x03: "Fibre Channel style 2 copper",
0x04: "BNC/TNC",
0x05: "Fibre Channel coax",
0x06: "FiberJack",
0x07: "LC",
0x08: "MT-RJ",
0x09: "MU",
0x0a: "SG",
0x0b: "Optical pigtail",
0x20: "HSSDC II",
0x21: "Copper pigtail",
}
TRANSCEIVER = [
# 10GB Ethernet
["10GBASE-SR", "10GBASE-LR", "10GBASE-ER", "10GBASE-LRM", "10GBASE-SW",
"10GBASE-LW", "10GBASE-EW"],
# 10GB Fibre Channel
["1200-MX-SN-I", "1200-SM-LL-L", "Extended Reach 1550 nm",
"Intermediate reach 1300 nm FP"],
# 10GB Copper
[],
# 10GB low speed
["1000BASE-SX / 1xFC MMF", "1000BASE-LX / 1xFC SMF", "2xFC MMF",
"2xFC SMF", "OC48-SR", "OC48-IR", "OC48-LR"],
# 10GB SONET/SDH interconnect
["I-64.1r", "I-64.1", "I-64.2r", "I-64.2", "I-64.3", "I-64.5"],
# 10GB SONET/SDH short haul
["S-64.1", "S-64.2a", "S-64.2b", "S-64.3a", "S-64.3b", "S-64.5a", "S-64.5b"],
# 10GB SONET/SDH long haul
["L-64.1", "L-64.2a", "L-64.2b", "L-64.2c", "L-64.3", "G.959.1 P1L1-2D2"],
# 10GB SONET/SDH very long haul
["V-64.2a", "V-64.2b", "V-64.3"],
]
SERIAL_ENCODING = [
"64B/66B",
"8B/10B",
"SONET scrambled",
"NRZ",
"RZ",
]
XMIT_TECH = [
"850 nm VCSEL",
"1310 nm VCSEL",
"1550 nm VCSEL",
"1310 nm FP",
"1310 nm DFB",
"1550 nm DFB",
"1310 nm EML"
"1550 nm EML"
"copper",
]
CDR = [
"9.95Gb/s",
"10.3Gb/s",
"10.5Gb/s",
"10.7Gb/s",
"11.1Gb/s",
"(unknown)",
"lineside loopback mode",
"XFI loopback mode",
]
DEVICE_TECH = [
["no wavelength control", "sctive wavelength control"],
["uncooled transmitter device", "cooled transmitter"],
["PIN detector", "APD detector"],
["transmitter not tunable", "transmitter tunable"],
]
ENHANCED_OPTS = [
"VPS",
"soft TX_DISABLE",
"soft P_Down",
"VPS LV regulator mode",
"VPS bypassed regulator mode",
"active FEC control",
"wavelength tunability",
"CMU",
]
AUX_TYPES = [
"not implemented",
"APD bias voltage",
"(unknown)",
"TEC current",
"laser temperature",
"laser wavelength",
"5V supply voltage",
"3.3V supply voltage",
"1.8V supply voltage",
"-5.2V supply voltage",
"5V supply current",
"(unknown)",
"(unknown)",
"3.3V supply current",
"1.8V supply current",
"-5.2V supply current",
]
from common.plugtrx import (MODULE_ID, ALARM_THRESHOLDS, AD_READOUTS, GCS_BITS,
CONNECTOR, TRANSCEIVER, SERIAL_ENCODING, XMIT_TECH, CDR, DEVICE_TECH,
ENHANCED_OPTS, AUX_TYPES)
class Decoder(srd.Decoder):
api_version = 2
@@ -204,7 +36,7 @@ class Decoder(srd.Decoder):
('fields', 'XFP structure fields'),
)
def __init__(self, **kwargs):
def __init__(self):
# Received data items, used as an index into samplenum/data
self.cnt = -1
# Start/end sample numbers per data item

View File

@@ -2,6 +2,7 @@
* This file is part of the libsigrokdecode project.
*
* 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
@@ -88,19 +89,19 @@ SRD_PRIV void srd_exception_catch(char **error, const char *format, ...)
PyObject *py_mod, *py_func, *py_tracefmt;
char *msg, *etype_name, *evalue_str, *tracefmt_str;
const char *etype_name_fallback;
char *final_msg;
char *final_msg;
py_etype = py_evalue = py_etraceback = py_mod = py_func = NULL;
va_start(args, format);
va_start(args, format);
msg = g_strdup_vprintf(format, args);
va_end(args);
PyErr_Fetch(&py_etype, &py_evalue, &py_etraceback);
if (!py_etype) {
/* No current exception, so just print the message. */
final_msg = g_strjoin(":", msg, "unknown error", NULL);
srd_err("%s.", final_msg);
final_msg = g_strjoin(":", msg, "unknown error", NULL);
srd_err("%s.", final_msg);
goto cleanup;
}
PyErr_NormalizeException(&py_etype, &py_evalue, &py_etraceback);
@@ -109,16 +110,16 @@ SRD_PRIV void srd_exception_catch(char **error, const char *format, ...)
evalue_str = py_stringify(py_evalue);
etype_name_fallback = (etype_name) ? etype_name : "(unknown exception)";
if (evalue_str)
final_msg = g_strjoin(":", msg, etype_name_fallback, evalue_str, NULL);
if (evalue_str)
final_msg = g_strjoin(":", msg, etype_name_fallback, evalue_str, NULL);
else
final_msg = g_strjoin(":", msg, etype_name_fallback, NULL);
srd_err("%s.", final_msg);
final_msg = g_strjoin(":", msg, etype_name_fallback, NULL);
g_free(evalue_str);
g_free(etype_name);
srd_err("%s.", final_msg);
/* If there is no traceback object, we are done. */
if (!py_etraceback)
goto cleanup;
@@ -147,8 +148,8 @@ SRD_PRIV void srd_exception_catch(char **error, const char *format, ...)
}
cleanup:
if (error)
*error = g_strdup(final_msg);
if (error)
*error = g_strdup(final_msg);
Py_XDECREF(py_func);
Py_XDECREF(py_mod);
Py_XDECREF(py_etraceback);
@@ -159,5 +160,5 @@ cleanup:
PyErr_Clear();
g_free(msg);
g_free(final_msg);
g_free(final_msg);
}

View File

@@ -156,7 +156,7 @@ SRD_API int srd_inst_option_set(struct srd_decoder_inst *di,
/* Not harmful even if we used the default. */
g_hash_table_remove(options, sdo->id);
}
Py_DECREF(py_di_options);
Py_DECREF(py_di_options);
if (g_hash_table_size(options) != 0)
srd_warn("Unknown options specified for '%s'", di->inst_id);
@@ -165,7 +165,7 @@ SRD_API int srd_inst_option_set(struct srd_decoder_inst *di,
err_out:
Py_XDECREF(py_optval);
if (PyErr_Occurred()) {
srd_exception_catch(NULL, "Stray exception in srd_inst_option_set().");
srd_exception_catch(NULL, "Stray exception in srd_inst_option_set()");
ret = SRD_ERR_PYTHON;
}
@@ -343,7 +343,7 @@ SRD_API struct srd_decoder_inst *srd_inst_new(struct srd_session *sess,
/* Create a new instance of this decoder class. */
if (!(di->py_inst = PyObject_CallObject(dec->py_dec, NULL))) {
if (PyErr_Occurred())
srd_exception_catch(NULL, "Failed to create %s instance: ",
srd_exception_catch(NULL, "Failed to create %s instance",
decoder_id);
g_free(di->dec_channelmap);
g_free(di);
@@ -498,7 +498,7 @@ SRD_PRIV struct srd_decoder_inst *srd_inst_find_by_obj(const GSList *stack,
/** @private */
SRD_PRIV int srd_inst_start(struct srd_decoder_inst *di, char **error)
{
srd_logic *logic;
srd_logic *logic;
PyObject *py_res;
GSList *l;
struct srd_decoder_inst *next_di;
@@ -508,26 +508,26 @@ SRD_PRIV int srd_inst_start(struct srd_decoder_inst *di, char **error)
di->inst_id);
if (!(py_res = PyObject_CallMethod(di->py_inst, "start", NULL))) {
srd_exception_catch(error, "Decoder %s",
srd_exception_catch(error, "Protocol decoder instance %s",
di->inst_id);
return SRD_ERR_PYTHON;
}
Py_DecRef(py_res);
Py_DecRef(py_res);
if ((di->decoder->channels || di->decoder->opt_channels) != 0 ) {
//logic = PyObject_New(srd_logic, &srd_logic_type);
if ((di->decoder->channels || di->decoder->opt_channels) != 0 ) {
//logic = PyObject_New(srd_logic, &srd_logic_type);
logic = PyObject_New(srd_logic, (PyTypeObject *)srd_logic_type);
Py_INCREF(logic);
logic->di = (struct srd_decoder_inst *)di;
logic->sample = PyList_New(2);
//Py_INCREF(logic->sample);
di->py_logic = logic;
}
Py_INCREF(logic);
logic->di = (struct srd_decoder_inst *)di;
logic->sample = PyList_New(2);
//Py_INCREF(logic->sample);
di->py_logic = logic;
}
/* Start all the PDs stacked on top of this one. */
for (l = di->next_di; l; l = l->next) {
next_di = l->data;
if ((ret = srd_inst_start(next_di, error)) != SRD_OK)
if ((ret = srd_inst_start(next_di, error)) != SRD_OK)
return ret;
}
@@ -535,7 +535,7 @@ SRD_PRIV int srd_inst_start(struct srd_decoder_inst *di, char **error)
}
/**
* Run the specified decoder function.
* Decode a chunk of samples.
*
* @param di The decoder instance to call. Must not be NULL.
* @param start_samplenum The starting sample number for the buffer's sample
@@ -548,58 +548,56 @@ SRD_PRIV int srd_inst_start(struct srd_decoder_inst *di, char **error)
* @return SRD_OK upon success, a (negative) error code otherwise.
*
* @private
*
* @since 0.4.0
*/
SRD_PRIV int srd_inst_decode(const struct srd_decoder_inst *di, uint8_t chunk_type,
uint64_t start_samplenum, uint64_t end_samplenum,
const uint8_t **inbuf, const uint8_t *inbuf_const, char **error)
const uint8_t **inbuf, const uint8_t *inbuf_const, char **error)
{
PyObject *py_res;
srd_logic *logic;
/* Return an error upon unusable input. */
if (!di) {
*error = g_strdup("Empty decoder instance");
*error = g_strdup("Empty decoder instance");
return SRD_ERR_ARG;
}
if (end_samplenum < start_samplenum) {
*error = g_strdup("Invalid start/end index couple");
if (end_samplenum < start_samplenum) {
*error = g_strdup("Invalid start/end index couple");
return SRD_ERR_ARG;
}
srd_dbg("Calling decode(), start sample %" PRIu64 ", end sample %"
PRIu64 " (%" PRIu64 " samples, instance %s.",
start_samplenum, end_samplenum,
end_samplenum - start_samplenum + 1, di->inst_id);
PRIu64 " (%" PRIu64 " samples, instance %s.",
start_samplenum, end_samplenum,
end_samplenum - start_samplenum + 1, di->inst_id);
/*
* Create new srd_logic object. Each iteration around the PD's loop
* will fill one sample into this object.
*/
logic = di->py_logic;
logic = di->py_logic;
logic->start_samplenum = start_samplenum;
if (chunk_type == 0) {
logic->itercnt = 0; // *inbuf is a byte pointer, 8bit align
logic->logic_mask = 0;
}
logic->inbuf = (uint8_t **)inbuf;
logic->inbuf_const = inbuf_const;
logic->samplenum = end_samplenum - start_samplenum + 1;
Py_INCREF(logic);
if (chunk_type == 0) {
logic->itercnt = 0; // *inbuf is a byte pointer, 8bit align
logic->logic_mask = 0;
}
logic->inbuf = (uint8_t **)inbuf;
logic->inbuf_const = inbuf_const;
logic->samplenum = end_samplenum - start_samplenum + 1;
Py_INCREF(logic);
//Py_IncRef(di->py_inst);
//Py_IncRef(di->py_inst);
if (!(py_res = PyObject_CallMethod(di->py_inst, "decode",
"KKO", start_samplenum, end_samplenum, logic))) {
srd_exception_catch(error, "Decoder %s",
srd_exception_catch(error, "Protocol decoder instance %s",
di->inst_id);
return SRD_ERR_PYTHON;
}
Py_DecRef(py_res);
Py_DecRef(py_res);
if (logic->logic_mask == 0) {
logic->itercnt -= logic->samplenum;
}
if (logic->logic_mask == 0) {
logic->itercnt -= logic->samplenum;
}
return SRD_OK;
}
@@ -609,16 +607,16 @@ SRD_PRIV void srd_inst_free(struct srd_decoder_inst *di)
{
GSList *l;
struct srd_pd_output *pdo;
srd_logic *logic = di->py_logic;
srd_logic *logic = di->py_logic;
srd_dbg("Freeing instance %s", di->inst_id);
if ((di->decoder->channels || di->decoder->opt_channels) != 0 ) {
if (logic && logic->sample)
Py_XDECREF(logic->sample);
if (logic)
Py_XDECREF(logic);
}
if ((di->decoder->channels || di->decoder->opt_channels) != 0 ) {
if (logic && logic->sample)
Py_XDECREF(logic->sample);
if (logic)
Py_XDECREF(logic);
}
Py_DecRef(di->py_inst);
g_free(di->inst_id);

View File

@@ -3,6 +3,7 @@
*
* Copyright (C) 2011 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
@@ -32,19 +33,19 @@
/* Custom Python types: */
typedef struct {
PyObject_HEAD
struct srd_decoder_inst *di;
uint64_t start_samplenum;
float itercnt;
uint8_t **inbuf;
const uint8_t *inbuf_const;
uint64_t samplenum;
PyObject *sample;
PyObject_HEAD
struct srd_decoder_inst *di;
uint64_t start_samplenum;
float itercnt;
uint8_t **inbuf;
const uint8_t *inbuf_const;
uint64_t samplenum;
PyObject *sample;
uint64_t exp_logic;
int edge_index;
uint64_t logic_mask;
uint64_t cur_pos;
uint64_t exp_logic;
int edge_index;
uint64_t logic_mask;
uint64_t cur_pos;
} srd_logic;
/* srd.c */
@@ -61,7 +62,7 @@ SRD_PRIV struct srd_decoder_inst *srd_inst_find_by_obj( const GSList *stack,
SRD_PRIV int srd_inst_start(struct srd_decoder_inst *di, char **error);
SRD_PRIV int srd_inst_decode(const struct srd_decoder_inst *di, uint8_t chunk_type,
uint64_t start_samplenum, uint64_t end_samplenum,
const uint8_t **inbuf, const uint8_t *inbuf_const, char **error);
const uint8_t **inbuf, const uint8_t *inbuf_const, char **error);
SRD_PRIV void srd_inst_free(struct srd_decoder_inst *di);
SRD_PRIV void srd_inst_free_all(struct srd_session *sess, GSList *stack);
@@ -111,7 +112,7 @@ SRD_PRIV GVariant *py_obj_to_variant(PyObject *py_obj);
* will assume non-standard Microsoft printf syntax.
*/
SRD_PRIV void srd_exception_catch(char **error, const char *format, ...)
__attribute__((__format__ (__gnu_printf__, 2, 3)));
__attribute__((__format__ (__gnu_printf__, 2, 3)));
#else
SRD_PRIV void srd_exception_catch(char **error, const char *format, ...) G_GNUC_PRINTF(2, 3);
#endif

View File

@@ -3,6 +3,7 @@
*
* 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
@@ -185,7 +186,7 @@ struct srd_decoder {
* supported annotation output.
*/
GSList *annotations;
GSList *ann_types;
GSList *ann_types;
/**
* List of annotation rows (row items: id, description, and a list
@@ -222,8 +223,8 @@ struct srd_channel {
char *desc;
/** The index of the channel, i.e. its order in the list of channels. */
int order;
/** The type of the channel, such us: sclk/sdata/.../others */
int type;
/** The type of the channel, such us: sclk/sdata/.../others */
int type;
};
struct srd_decoder_option {
@@ -242,18 +243,18 @@ struct srd_decoder_annotation_row {
struct srd_decoder_inst {
struct srd_decoder *decoder;
struct srd_session *sess;
void *py_inst;
void *py_logic;
void *py_inst;
void *py_logic;
char *inst_id;
GSList *pd_output;
int dec_num_channels;
int *dec_channelmap;
uint8_t *channel_samples;
GSList *next_di;
uint64_t cur_pos;
uint64_t logic_mask;
uint64_t exp_logic;
int edge_index;
uint64_t cur_pos;
uint64_t logic_mask;
uint64_t exp_logic;
int edge_index;
};
struct srd_pd_output {
@@ -275,7 +276,7 @@ struct srd_proto_data {
};
struct srd_proto_data_annotation {
int ann_class;
int ann_type;
int ann_type;
char **ann_text;
};
struct srd_proto_data_binary {
@@ -304,7 +305,7 @@ SRD_API int srd_session_metadata_set(struct srd_session *sess, int key,
GVariant *data);
SRD_API int srd_session_send(struct srd_session *sess, uint8_t chunk_type,
uint64_t start_samplenum, uint64_t end_samplenum,
const uint8_t **inbuf, const uint8_t *inbuf_const, char **error);
const uint8_t **inbuf, const uint8_t *inbuf_const, char **error);
SRD_API int srd_session_destroy(struct srd_session *sess);
SRD_API int srd_pd_output_callback_add(struct srd_session *sess,
int output_type, srd_pd_output_callback cb, void *cb_data);

View File

@@ -17,9 +17,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "libsigrokdecode.h" /* First, so we avoid a _POSIX_C_SOURCE warning. */
#include "libsigrokdecode-internal.h"
#include "config.h"
#include "libsigrokdecode-internal.h" /* First, so we avoid a _POSIX_C_SOURCE warning. */
#include "libsigrokdecode.h"
/** @cond PRIVATE */
@@ -55,12 +55,11 @@ PyMODINIT_FUNC PyInit_sigrokdecode(void)
if (PyModule_AddObject(mod, "Decoder", Decoder_type) < 0)
goto err_out;
logic_type = srd_logic_type_new();
if (!logic_type)
goto err_out;
if (PyModule_AddObject(mod, "srd_logic", logic_type) < 0) {
goto err_out;
}
logic_type = srd_logic_type_new();
if (!logic_type)
goto err_out;
if (PyModule_AddObject(mod, "srd_logic", logic_type) < 0)
goto err_out;
/* Expose output types as symbols in the sigrokdecode module */
if (PyModule_AddIntConstant(mod, "OUTPUT_ANN", SRD_OUTPUT_ANN) < 0)
@@ -75,13 +74,13 @@ PyMODINIT_FUNC PyInit_sigrokdecode(void)
if (PyModule_AddIntConstant(mod, "SRD_CONF_SAMPLERATE", SRD_CONF_SAMPLERATE) < 0)
goto err_out;
srd_logic_type = logic_type;
srd_logic_type = logic_type;
mod_sigrokdecode = mod;
return mod;
err_out:
Py_XDECREF(mod);
srd_exception_catch(NULL, "Failed to initialize module");
srd_exception_catch(NULL, "Failed to initialize module");
return NULL;
}

View File

@@ -3,6 +3,7 @@
*
* Copyright (C) 2010 Uwe Hermann <uwe@hermann-uwe.de>
* Copyright (C) 2013 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
@@ -117,7 +118,7 @@ SRD_API int srd_session_start(struct srd_session *sess, char **error)
ret = SRD_OK;
for (d = sess->di_list; d; d = d->next) {
di = d->data;
if ((ret = srd_inst_start(di, error)) != SRD_OK)
if ((ret = srd_inst_start(di, error)) != SRD_OK)
break;
}
@@ -232,7 +233,7 @@ SRD_API int srd_session_metadata_set(struct srd_session *sess, int key,
*/
SRD_API int srd_session_send(struct srd_session *sess, uint8_t chunk_type,
uint64_t start_samplenum, uint64_t end_samplenum,
const uint8_t **inbuf, const uint8_t *inbuf_const, char **error)
const uint8_t **inbuf, const uint8_t *inbuf_const, char **error)
{
GSList *d;
int ret;
@@ -243,8 +244,8 @@ SRD_API int srd_session_send(struct srd_session *sess, uint8_t chunk_type,
}
for (d = sess->di_list; d; d = d->next) {
if ((ret = srd_inst_decode(d->data, chunk_type, start_samplenum,
end_samplenum, inbuf, inbuf_const, error)) != SRD_OK)
if ((ret = srd_inst_decode(d->data, chunk_type, start_samplenum,
end_samplenum, inbuf, inbuf_const, error)) != SRD_OK)
return ret;
}

View File

@@ -142,9 +142,9 @@ static int searchpath_add_xdg_dir(const char *datadir)
SRD_API int srd_init(const char *path)
{
const char *const *sys_datadirs;
const char *env_path;
size_t i;
int ret;
const char *env_path;
if (max_session_id != -1) {
srd_err("libsigrokdecode is already initialized.");
@@ -158,6 +158,7 @@ SRD_API int srd_init(const char *path)
/* Initialize the Python interpreter. */
Py_InitializeEx(0);
/* Locations relative to the XDG system data directories. */
sys_datadirs = g_get_system_data_dirs();
for (i = g_strv_length((char **)sys_datadirs); i > 0; i--) {
@@ -167,13 +168,13 @@ SRD_API int srd_init(const char *path)
return ret;
}
}
#ifdef DECODERS_DIR
#ifdef DECODERS_DIR
/* Hardcoded decoders install location, if defined. */
if ((ret = srd_decoder_searchpath_add(DECODERS_DIR)) != SRD_OK) {
Py_Finalize();
return ret;
}
#endif
#endif
/* Location relative to the XDG user data directory. */
ret = searchpath_add_xdg_dir(g_get_user_data_dir());
if (ret != SRD_OK) {

View File

@@ -19,7 +19,7 @@
*/
#include <config.h>
#include "../libsigrokdecode.h" /* First, to avoid compiler warning. */
#include <libsigrokdecode.h> /* First, to avoid compiler warning. */
#include <stdlib.h>
#include <check.h>
#include "lib.h"

View File

@@ -19,7 +19,7 @@
*/
#include <config.h>
#include "../libsigrokdecode.h" /* First, to avoid compiler warning. */
#include <libsigrokdecode.h> /* First, to avoid compiler warning. */
#include <stdlib.h>
#include <check.h>
#include "lib.h"
@@ -32,7 +32,7 @@ START_TEST(test_load_all)
{
int ret;
srd_init(DECODERS_DIR);
srd_init(DECODERS_TESTDIR);
ret = srd_decoder_load_all();
fail_unless(ret == SRD_OK, "srd_decoder_load_all() failed: %d.", ret);
srd_exit();
@@ -61,7 +61,7 @@ START_TEST(test_load)
{
int ret;
srd_init(DECODERS_DIR);
srd_init(DECODERS_TESTDIR);
ret = srd_decoder_load("uart");
fail_unless(ret == SRD_OK, "srd_decoder_load(uart) failed: %d.", ret);
ret = srd_decoder_load("spi");
@@ -78,7 +78,7 @@ END_TEST
*/
START_TEST(test_load_bogus)
{
srd_init(DECODERS_DIR);
srd_init(DECODERS_TESTDIR);
/* http://sigrok.org/bugzilla/show_bug.cgi?id=176 */
fail_unless(srd_decoder_load(NULL) != SRD_OK);
fail_unless(srd_decoder_load("") != SRD_OK);
@@ -101,7 +101,7 @@ END_TEST
*/
START_TEST(test_load_valid_and_bogus)
{
srd_init(DECODERS_DIR);
srd_init(DECODERS_TESTDIR);
fail_unless(srd_decoder_load("") != SRD_OK);
fail_unless(srd_decoder_load("uart") == SRD_OK);
fail_unless(srd_decoder_load("") != SRD_OK);
@@ -122,7 +122,7 @@ START_TEST(test_load_multiple)
{
int ret;
srd_init(DECODERS_DIR);
srd_init(DECODERS_TESTDIR);
ret = srd_decoder_load("uart");
fail_unless(ret == SRD_OK, "Loading uart PD 1x failed: %d", ret);
ret = srd_decoder_load("uart");
@@ -149,13 +149,121 @@ START_TEST(test_load_nonexisting_pd_dir)
}
END_TEST
/*
* Check whether srd_decoder_unload_all() works.
* If it returns != SRD_OK (or segfaults) this test will fail.
*/
START_TEST(test_unload_all)
{
int ret;
srd_init(DECODERS_TESTDIR);
ret = srd_decoder_load_all();
fail_unless(ret == SRD_OK, "srd_decoder_load_all() failed: %d.", ret);
ret = srd_decoder_unload_all();
fail_unless(ret == SRD_OK, "srd_decoder_unload_all() failed: %d.", ret);
srd_exit();
}
END_TEST
/*
* Check whether srd_decoder_unload_all() works without prior srd_init().
* If it returns != SRD_OK (or segfaults) this test will fail.
*/
START_TEST(test_unload_all_no_init)
{
int ret;
ret = srd_decoder_unload_all();
fail_unless(ret == SRD_OK, "srd_decoder_unload_all() failed: %d.", ret);
}
END_TEST
/*
* Check whether srd_decoder_unload_all() works multiple times.
* If it returns != SRD_OK (or segfaults) this test will fail.
*/
START_TEST(test_unload_all_multiple)
{
int ret, i;
srd_init(DECODERS_TESTDIR);
for (i = 0; i < 10; i++) {
ret = srd_decoder_load_all();
fail_unless(ret == SRD_OK, "srd_decoder_load_all() failed: %d.", ret);
ret = srd_decoder_unload_all();
fail_unless(ret == SRD_OK, "srd_decoder_unload_all() failed: %d.", ret);
}
srd_exit();
}
END_TEST
/*
* Check whether srd_decoder_unload_all() works multiple times (no load).
* If it returns != SRD_OK (or segfaults) this test will fail.
*/
START_TEST(test_unload_all_multiple_noload)
{
int ret, i;
srd_init(DECODERS_TESTDIR);
for (i = 0; i < 10; i++) {
ret = srd_decoder_unload_all();
fail_unless(ret == SRD_OK, "srd_decoder_unload_all() failed: %d.", ret);
}
srd_exit();
}
END_TEST
/*
* Check whether srd_decoder_unload() works.
* If it returns != SRD_OK (or segfaults) this test will fail.
*/
START_TEST(test_unload)
{
int ret;
struct srd_decoder *dec;
srd_init(DECODERS_TESTDIR);
ret = srd_decoder_load("uart");
fail_unless(ret == SRD_OK, "srd_decoder_load(uart) failed: %d.", ret);
dec = srd_decoder_get_by_id("uart");
fail_unless(dec != NULL);
ret = srd_decoder_unload(dec);
fail_unless(ret == SRD_OK, "srd_decoder_unload() failed: %d.", ret);
srd_exit();
}
END_TEST
/*
* Check whether srd_decoder_unload(NULL) fails.
* If it returns SRD_OK (or segfaults) this test will fail.
*/
START_TEST(test_unload_null)
{
srd_init(DECODERS_TESTDIR);
fail_unless(srd_decoder_unload(NULL) != SRD_OK);
srd_exit();
}
END_TEST
/*
* Check whether srd_decoder_unload(NULL) fails without prior srd_init().
* If it returns SRD_OK (or segfaults) this test will fail.
*/
START_TEST(test_unload_null_no_init)
{
fail_unless(srd_decoder_unload(NULL) != SRD_OK);
}
END_TEST
/*
* Check whether srd_decoder_list() returns a non-empty list.
* If it returns an empty list (or segfaults) this test will fail.
*/
START_TEST(test_decoder_list)
{
srd_init(DECODERS_DIR);
srd_init(DECODERS_TESTDIR);
srd_decoder_load_all();
fail_unless(srd_decoder_list() != NULL);
srd_exit();
@@ -169,7 +277,7 @@ END_TEST
*/
START_TEST(test_decoder_list_no_load)
{
srd_init(DECODERS_DIR);
srd_init(DECODERS_TESTDIR);
fail_unless(srd_decoder_list() == NULL);
srd_exit();
}
@@ -205,7 +313,7 @@ END_TEST
*/
START_TEST(test_decoder_list_correct_numbers)
{
srd_init(DECODERS_DIR);
srd_init(DECODERS_TESTDIR);
fail_unless(g_slist_length((GSList *)srd_decoder_list()) == 0);
srd_decoder_load("spi");
fail_unless(g_slist_length((GSList *)srd_decoder_list()) == 1);
@@ -225,7 +333,7 @@ END_TEST
*/
START_TEST(test_get_by_id)
{
srd_init(DECODERS_DIR);
srd_init(DECODERS_TESTDIR);
srd_decoder_load("uart");
fail_unless(srd_decoder_get_by_id("uart") != NULL);
fail_unless(srd_decoder_get_by_id("can") == NULL);
@@ -242,7 +350,7 @@ END_TEST
*/
START_TEST(test_get_by_id_multiple)
{
srd_init(DECODERS_DIR);
srd_init(DECODERS_TESTDIR);
srd_decoder_load("uart");
fail_unless(srd_decoder_get_by_id("uart") != NULL);
fail_unless(srd_decoder_get_by_id("uart") != NULL);
@@ -258,7 +366,7 @@ END_TEST
*/
START_TEST(test_get_by_id_bogus)
{
srd_init(DECODERS_DIR);
srd_init(DECODERS_TESTDIR);
fail_unless(srd_decoder_get_by_id(NULL) == NULL);
fail_unless(srd_decoder_get_by_id("") == NULL);
fail_unless(srd_decoder_get_by_id(" ") == NULL);
@@ -282,7 +390,7 @@ START_TEST(test_doc_get)
{
struct srd_decoder *dec;
srd_init(DECODERS_DIR);
srd_init(DECODERS_TESTDIR);
srd_decoder_load("uart");
dec = srd_decoder_get_by_id("uart");
fail_unless(srd_decoder_doc_get(dec) != NULL);
@@ -297,7 +405,7 @@ END_TEST
*/
START_TEST(test_doc_get_null)
{
srd_init(DECODERS_DIR);
srd_init(DECODERS_TESTDIR);
fail_unless(srd_decoder_doc_get(NULL) == NULL);
srd_exit();
}
@@ -322,6 +430,17 @@ Suite *suite_decoder(void)
tcase_add_test(tc, test_load_nonexisting_pd_dir);
suite_add_tcase(s, tc);
tc = tcase_create("unload");
tcase_add_checked_fixture(tc, srdtest_setup, srdtest_teardown);
tcase_add_test(tc, test_unload_all);
tcase_add_test(tc, test_unload_all_no_init);
tcase_add_test(tc, test_unload_all_multiple);
tcase_add_test(tc, test_unload_all_multiple_noload);
tcase_add_test(tc, test_unload);
tcase_add_test(tc, test_unload_null);
tcase_add_test(tc, test_unload_null_no_init);
suite_add_tcase(s, tc);
tc = tcase_create("list");
tcase_add_checked_fixture(tc, srdtest_setup, srdtest_teardown);
tcase_add_test(tc, test_decoder_list);

View File

@@ -19,7 +19,7 @@
*/
#include <config.h>
#include "../libsigrokdecode.h" /* First, to avoid compiler warning. */
#include <libsigrokdecode.h> /* First, to avoid compiler warning. */
#include <stdlib.h>
#include <check.h>
#include "lib.h"
@@ -33,7 +33,7 @@ START_TEST(test_inst_new)
struct srd_session *sess;
struct srd_decoder_inst *inst;
srd_init(DECODERS_DIR);
srd_init(DECODERS_TESTDIR);
srd_decoder_load("uart");
srd_session_new(&sess);
inst = srd_inst_new(sess, "uart", NULL);
@@ -53,7 +53,7 @@ START_TEST(test_inst_new_multiple)
inst1 = inst2 = inst3 = NULL;
srd_init(DECODERS_DIR);
srd_init(DECODERS_TESTDIR);
srd_decoder_load_all();
srd_session_new(&sess);
@@ -90,7 +90,7 @@ START_TEST(test_inst_option_set_empty)
struct srd_decoder_inst *inst;
GHashTable *options;
srd_init(DECODERS_DIR);
srd_init(DECODERS_TESTDIR);
srd_decoder_load_all();
srd_session_new(&sess);
inst = srd_inst_new(sess, "uart", NULL);
@@ -114,7 +114,7 @@ START_TEST(test_inst_option_set_bogus)
struct srd_decoder_inst *inst;
GHashTable *options;
srd_init(DECODERS_DIR);
srd_init(DECODERS_TESTDIR);
srd_decoder_load_all();
srd_session_new(&sess);
inst = srd_inst_new(sess, "uart", NULL);

View File

@@ -19,7 +19,7 @@
*/
#include <config.h>
#include "../libsigrokdecode.h" /* First, to avoid compiler warning. */
#include <libsigrokdecode.h> /* First, to avoid compiler warning. */
#include <stdlib.h>
#include <check.h>
#include "lib.h"

View File

@@ -19,8 +19,8 @@
*/
#include <config.h>
#include "../libsigrokdecode-internal.h" /* First, to avoid compiler warning. */
#include "../libsigrokdecode.h"
#include <libsigrokdecode-internal.h> /* First, to avoid compiler warning. */
#include <libsigrokdecode.h>
#include <stdint.h>
#include <stdlib.h>
#include <check.h>

View File

@@ -24,7 +24,21 @@ from shutil import copy
from getopt import getopt
def install(srcdir, dstdir):
_inst_pp_col_max = 80
_inst_pp_col = 0
def _install_pretty_print(item):
"""Pretty print an install item. Enforce maximum line width."""
global _inst_pp_col
if item is None:
_inst_pp_col = 0
return
_inst_pp_col += len(item)
if _inst_pp_col > _inst_pp_col_max:
print()
_inst_pp_col = len(item)
print(item, end = "")
def install(srcdir, dstdir, s):
worklist = []
for pd in os.listdir(srcdir):
pd_dir = srcdir + '/' + pd
@@ -39,17 +53,13 @@ def install(srcdir, dstdir):
install_list.extend(config_get_extra_install(pd_file))
elif f[-3:] == '.py':
install_list.append(f)
worklist.append((pd, pd_dir, install_list))
if install_list:
worklist.append((pd, pd_dir, install_list))
print("Installing %d protocol decoders:" % len(worklist))
col = 0
worklist.sort()
print("Installing %d %s:" % (len(worklist), s))
for pd, pd_dir, install_list in worklist:
msg = pd + ' '
if (col + len(msg) > 80):
print()
col = 0
print(msg, end='')
col += len(msg)
_install_pretty_print("{} ".format(pd))
pd_dst = os.path.join(dstdir, pd)
try:
os.mkdir(pd_dst)
@@ -61,6 +71,7 @@ def install(srcdir, dstdir):
for f in install_list:
copy(os.path.join(pd_dir, f), pd_dst)
print()
_install_pretty_print(None)
def config_get_extra_install(config_file):
@@ -107,6 +118,7 @@ except Exception as e:
if len(args) != 0 or dst is None:
usage()
install(src, dst)
install(src, dst, 'protocol decoders')
install(src + '/common', dst + '/common', 'common modules')

View File

@@ -45,11 +45,11 @@ static const char *output_type_name(unsigned int idx)
static int convert_annotation(struct srd_decoder_inst *di, PyObject *obj,
struct srd_proto_data *pdata)
{
PyObject *py_tmp;
PyObject *py_tmp;
struct srd_proto_data_annotation *pda;
unsigned int ann_class;
unsigned int ann_class;
char **ann_text;
gpointer ann_type_ptr;
gpointer ann_type_ptr;
/* Should be a list of [annotation class, [string, ...]]. */
if (!PyList_Check(obj)) {
@@ -76,18 +76,18 @@ static int convert_annotation(struct srd_decoder_inst *di, PyObject *obj,
"first element was not an integer.", di->decoder->name);
return SRD_ERR_PYTHON;
}
ann_class = PyLong_AsLong(py_tmp);
ann_class = PyLong_AsLong(py_tmp);
// if (!(pdo = g_slist_nth_data(di->decoder->annotations, ann_class))) {
// srd_err("Protocol decoder %s submitted data to unregistered "
// "annotation class %d.", di->decoder->name, ann_class);
// return SRD_ERR_PYTHON;
// }
if (ann_class >= g_slist_length(di->decoder->ann_types)) {
srd_err("Protocol decoder %s submitted data to unregistered "
"annotation class %d.", di->decoder->name, ann_class);
return SRD_ERR_PYTHON;
}
ann_type_ptr = g_slist_nth_data(di->decoder->ann_types, ann_class);
if (ann_class >= g_slist_length(di->decoder->ann_types)) {
srd_err("Protocol decoder %s submitted data to unregistered "
"annotation class %d.", di->decoder->name, ann_class);
return SRD_ERR_PYTHON;
}
ann_type_ptr = g_slist_nth_data(di->decoder->ann_types, ann_class);
/* Second element must be a list. */
py_tmp = PyList_GetItem(obj, 1);
@@ -104,7 +104,7 @@ static int convert_annotation(struct srd_decoder_inst *di, PyObject *obj,
pda = g_malloc(sizeof(struct srd_proto_data_annotation));
pda->ann_class = ann_class;
pda->ann_type = GPOINTER_TO_INT(ann_type_ptr);
pda->ann_type = GPOINTER_TO_INT(ann_type_ptr);
pda->ann_text = ann_text;
pdata->data = pda;
@@ -209,17 +209,17 @@ static int convert_meta(struct srd_proto_data *pdata, PyObject *obj)
static PyObject *Decoder_put(PyObject *self, PyObject *args)
{
GSList *l;
PyObject *py_data, *py_res;
struct srd_decoder_inst *di, *next_di;
struct srd_pd_output *pdo;
struct srd_proto_data *pdata;
uint64_t start_sample, end_sample;
int output_id;
struct srd_pd_callback *cb;
struct srd_proto_data_binary *pdb;
struct srd_proto_data_annotation *pda;
char **annotations;
GSList *l;
PyObject *py_data, *py_res;
struct srd_decoder_inst *di, *next_di;
struct srd_pd_output *pdo;
struct srd_proto_data *pdata;
uint64_t start_sample, end_sample;
int output_id;
struct srd_pd_callback *cb;
struct srd_proto_data_binary *pdb;
struct srd_proto_data_annotation *pda;
char **annotations;
if (!(di = srd_inst_find_by_obj(NULL, self))) {
/* Shouldn't happen. */
@@ -253,74 +253,74 @@ static PyObject *Decoder_put(PyObject *self, PyObject *args)
pdata->end_sample = end_sample;
pdata->pdo = pdo;
switch (pdo->output_type) {
case SRD_OUTPUT_ANN:
/* Annotations are only fed to callbacks. */
if ((cb = srd_pd_output_callback_find(di->sess, pdo->output_type))) {
/* Convert from PyDict to srd_proto_data_annotation. */
if (convert_annotation(di, py_data, pdata) != SRD_OK) {
/* An error was already logged. */
break;
}
cb->cb(pdata, cb->cb_data);
pda = pdata->data;
annotations = (char**)pda->ann_text;
while(*annotations) {
g_free(*annotations);
annotations++;
}
g_free(pda->ann_text);
g_free(pda);
}
break;
case SRD_OUTPUT_PYTHON:
for (l = di->next_di; l; l = l->next) {
next_di = l->data;
srd_spew("Sending %" PRIu64 "-%" PRIu64 " to instance %s",
start_sample, end_sample, next_di->inst_id);
if (!(py_res = PyObject_CallMethod(
next_di->py_inst, "decode", "KKO", start_sample,
end_sample, py_data))) {
srd_exception_catch(NULL, "Calling %s decode() failed",
next_di->inst_id);
}
Py_XDECREF(py_res);
}
if ((cb = srd_pd_output_callback_find(di->sess, pdo->output_type))) {
/* Frontends aren't really supposed to get Python
* callbacks, but it's useful for testing. */
pdata->data = py_data;
cb->cb(pdata, cb->cb_data);
}
break;
case SRD_OUTPUT_BINARY:
if ((cb = srd_pd_output_callback_find(di->sess, pdo->output_type))) {
/* Convert from PyDict to srd_proto_data_binary. */
if (convert_binary(di, py_data, pdata) != SRD_OK) {
/* An error was already logged. */
break;
}
cb->cb(pdata, cb->cb_data);
pdb = pdata->data;
g_free(pdb->data);
g_free(pdb);
}
break;
case SRD_OUTPUT_META:
if ((cb = srd_pd_output_callback_find(di->sess, pdo->output_type))) {
/* Annotations need converting from PyObject. */
if (convert_meta(pdata, py_data) != SRD_OK) {
/* An exception was already set up. */
break;
}
cb->cb(pdata, cb->cb_data);
}
break;
default:
srd_err("Protocol decoder %s submitted invalid output type %d.",
di->decoder->name, pdo->output_type);
break;
}
switch (pdo->output_type) {
case SRD_OUTPUT_ANN:
/* Annotations are only fed to callbacks. */
if ((cb = srd_pd_output_callback_find(di->sess, pdo->output_type))) {
/* Convert from PyDict to srd_proto_data_annotation. */
if (convert_annotation(di, py_data, pdata) != SRD_OK) {
/* An error was already logged. */
break;
}
cb->cb(pdata, cb->cb_data);
pda = pdata->data;
annotations = (char**)pda->ann_text;
while(*annotations) {
g_free(*annotations);
annotations++;
}
g_free(pda->ann_text);
g_free(pda);
}
break;
case SRD_OUTPUT_PYTHON:
for (l = di->next_di; l; l = l->next) {
next_di = l->data;
srd_spew("Sending %" PRIu64 "-%" PRIu64 " to instance %s",
start_sample, end_sample, next_di->inst_id);
if (!(py_res = PyObject_CallMethod(
next_di->py_inst, "decode", "KKO", start_sample,
end_sample, py_data))) {
srd_exception_catch(NULL, "Calling %s decode() failed",
next_di->inst_id);
}
Py_XDECREF(py_res);
}
if ((cb = srd_pd_output_callback_find(di->sess, pdo->output_type))) {
/* Frontends aren't really supposed to get Python
* callbacks, but it's useful for testing. */
pdata->data = py_data;
cb->cb(pdata, cb->cb_data);
}
break;
case SRD_OUTPUT_BINARY:
if ((cb = srd_pd_output_callback_find(di->sess, pdo->output_type))) {
/* Convert from PyDict to srd_proto_data_binary. */
if (convert_binary(di, py_data, pdata) != SRD_OK) {
/* An error was already logged. */
break;
}
cb->cb(pdata, cb->cb_data);
pdb = pdata->data;
g_free(pdb->data);
g_free(pdb);
}
break;
case SRD_OUTPUT_META:
if ((cb = srd_pd_output_callback_find(di->sess, pdo->output_type))) {
/* Annotations need converting from PyObject. */
if (convert_meta(pdata, py_data) != SRD_OK) {
/* An exception was already set up. */
break;
}
cb->cb(pdata, cb->cb_data);
}
break;
default:
srd_err("Protocol decoder %s submitted invalid output type %d.",
di->decoder->name, pdo->output_type);
break;
}
g_free(pdata);

View File

@@ -33,21 +33,21 @@ static PyObject *srd_logic_iternext(PyObject *self)
{
srd_logic *logic;
PyObject *py_samplenum, *py_samples;
int i;
int i;
logic = (srd_logic *)self;
uint64_t offset = floor(logic->itercnt);
logic->di->cur_pos = logic->cur_pos;
logic->di->logic_mask = logic->logic_mask;
logic->di->exp_logic = logic->exp_logic;
logic->di->edge_index = -1;
if (logic->logic_mask != 0 && logic->edge_index != -1)
logic->di->edge_index = logic->di->dec_channelmap[logic->edge_index];
uint64_t offset = floor(logic->itercnt);
logic->di->cur_pos = logic->cur_pos;
logic->di->logic_mask = logic->logic_mask;
logic->di->exp_logic = logic->exp_logic;
logic->di->edge_index = -1;
if (logic->logic_mask != 0 && logic->edge_index != -1)
logic->di->edge_index = logic->di->dec_channelmap[logic->edge_index];
if (offset > logic->samplenum || logic->logic_mask != 0) {
/* End iteration loop. */
return NULL;
}
if (offset > logic->samplenum || logic->logic_mask != 0) {
/* End iteration loop. */
return NULL;
}
/*
* Convert the bit-packed sample to an array of bytes, with only 0x01
@@ -59,39 +59,39 @@ static PyObject *srd_logic_iternext(PyObject *self)
/* Value of unused channel is 0xff, instead of 0 or 1. */
logic->di->channel_samples[i] = 0xff;
} else {
if (*(logic->inbuf + i) == NULL) {
logic->di->channel_samples[i] = *(logic->inbuf_const + i) ? 1 : 0;
} else {
uint64_t inbuf_offset = (offset + (logic->start_samplenum % 8));
uint8_t *ptr = *(logic->inbuf + i) + (inbuf_offset / 8);
logic->di->channel_samples[i] = *ptr & (1 << (inbuf_offset % 8)) ? 1 : 0;
}
if (*(logic->inbuf + i) == NULL) {
logic->di->channel_samples[i] = *(logic->inbuf_const + i) ? 1 : 0;
} else {
uint64_t inbuf_offset = (offset + (logic->start_samplenum % 8));
uint8_t *ptr = *(logic->inbuf + i) + (inbuf_offset / 8);
logic->di->channel_samples[i] = *ptr & (1 << (inbuf_offset % 8)) ? 1 : 0;
}
}
}
/* Prepare the next samplenum/sample list in this iteration. */
py_samplenum = PyLong_FromUnsignedLongLong(logic->start_samplenum + offset);
PyList_SetItem(logic->sample, 0, py_samplenum);
py_samples = PyBytes_FromStringAndSize((const char *)logic->di->channel_samples,
logic->di->dec_num_channels);
PyList_SetItem(logic->sample, 1, py_samples);
Py_INCREF(logic->sample);
py_samplenum = PyLong_FromUnsignedLongLong(logic->start_samplenum + offset);
PyList_SetItem(logic->sample, 0, py_samplenum);
py_samples = PyBytes_FromStringAndSize((const char *)logic->di->channel_samples,
logic->di->dec_num_channels);
PyList_SetItem(logic->sample, 1, py_samples);
Py_INCREF(logic->sample);
return logic->sample;
return logic->sample;
}
static PyMemberDef srd_logic_members[] = {
{"itercnt", T_FLOAT, offsetof(srd_logic, itercnt), 0,
"next expacted samples offset"},
{"logic_mask", T_ULONGLONG, offsetof(srd_logic, logic_mask), 0,
"next expacted logic value mask"},
{"exp_logic", T_ULONGLONG, offsetof(srd_logic, exp_logic), 0,
"next expacted logic value"},
{"edge_index", T_INT, offsetof(srd_logic, edge_index), 0,
"channel index of next expacted edge"},
{"cur_pos", T_ULONGLONG, offsetof(srd_logic, cur_pos), 0,
"current sample position"},
{NULL} /* Sentinel */
{"itercnt", T_FLOAT, offsetof(srd_logic, itercnt), 0,
"next expacted samples offset"},
{"logic_mask", T_ULONGLONG, offsetof(srd_logic, logic_mask), 0,
"next expacted logic value mask"},
{"exp_logic", T_ULONGLONG, offsetof(srd_logic, exp_logic), 0,
"next expacted logic value"},
{"edge_index", T_INT, offsetof(srd_logic, edge_index), 0,
"channel index of next expacted edge"},
{"cur_pos", T_ULONGLONG, offsetof(srd_logic, cur_pos), 0,
"current sample position"},
{NULL} /* Sentinel */
};
//static PyMemberDef srd_logic_members[] = {
@@ -115,20 +115,20 @@ static PyMemberDef srd_logic_members[] = {
*/
SRD_PRIV PyObject *srd_logic_type_new(void)
{
PyType_Spec spec;
PyType_Slot slots[] = {
{ Py_tp_doc, "sigrokdecode logic sample object" },
{ Py_tp_iter, (void *)&srd_logic_iter },
{ Py_tp_iternext, (void *)&srd_logic_iternext },
{ Py_tp_new, (void *)&PyType_GenericNew },
{ Py_tp_members, srd_logic_members },
{ 0, NULL }
};
spec.name = "srd_logic";
spec.basicsize = sizeof(srd_logic);
spec.itemsize = 0;
spec.flags = Py_TPFLAGS_DEFAULT;
spec.slots = slots;
PyType_Spec spec;
PyType_Slot slots[] = {
{ Py_tp_doc, "sigrokdecode logic sample object" },
{ Py_tp_iter, (void *)&srd_logic_iter },
{ Py_tp_iternext, (void *)&srd_logic_iternext },
{ Py_tp_new, (void *)&PyType_GenericNew },
{ Py_tp_members, srd_logic_members },
{ 0, NULL }
};
spec.name = "srd_logic";
spec.basicsize = sizeof(srd_logic);
spec.itemsize = 0;
spec.flags = Py_TPFLAGS_DEFAULT;
spec.slots = slots;
return PyType_FromSpec(&spec);
return PyType_FromSpec(&spec);
}

View File

@@ -3,6 +3,7 @@
*
* 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
@@ -21,7 +22,6 @@
#include "config.h"
#include "libsigrokdecode-internal.h" /* First, so we avoid a _POSIX_C_SOURCE warning. */
#include "libsigrokdecode.h"
#include "config.h"
/**
* Import a Python module by name.
*
@@ -72,7 +72,7 @@ SRD_PRIV int py_attr_as_str(PyObject *py_obj, const char *attr, char **outstr)
}
if (!(py_str = PyObject_GetAttrString(py_obj, attr))) {
srd_exception_catch(NULL, "Failed to get attribute '%s'", attr);
srd_exception_catch(NULL, "Failed to get attribute '%s'", attr);
return SRD_ERR_PYTHON;
}
@@ -125,22 +125,22 @@ SRD_PRIV int py_dictitem_as_str(PyObject *py_obj, const char *key,
*/
SRD_PRIV int py_dictitem_to_int(PyObject *py_obj, const char *key)
{
PyObject *py_value;
long type;
PyObject *py_value;
long type;
if (!PyDict_Check(py_obj)) {
srd_dbg("Object is not a dictionary.");
return -1;
}
if (!PyDict_Check(py_obj)) {
srd_dbg("Object is not a dictionary.");
return -1;
}
if (!(py_value = PyDict_GetItemString(py_obj, key))) {
srd_dbg("Dictionary has no attribute '%s'.", key);
return -1;
}
if (!(py_value = PyDict_GetItemString(py_obj, key))) {
srd_dbg("Dictionary has no attribute '%s'.", key);
return -1;
}
type = PyLong_Check(py_value) ? PyLong_AsLong(py_value) : -1;
type = PyLong_Check(py_value) ? PyLong_AsLong(py_value) : -1;
return type;
return type;
}
/**
@@ -174,7 +174,7 @@ SRD_PRIV int py_str_as_str(PyObject *py_str, char **outstr)
return SRD_OK;
}
}
srd_exception_catch(NULL, "Failed to extract string");
srd_exception_catch(NULL, "Failed to extract string");
return SRD_ERR_PYTHON;
}
@@ -205,7 +205,7 @@ SRD_PRIV int py_strseq_to_char(PyObject *py_strseq, char ***out_strv)
seq_len = PySequence_Size(py_strseq);
if (seq_len < 0) {
srd_exception_catch(NULL, "Failed to obtain sequence size");
srd_exception_catch(NULL, "Failed to obtain sequence size");
return SRD_ERR_PYTHON;
}
@@ -242,7 +242,7 @@ SRD_PRIV int py_strseq_to_char(PyObject *py_strseq, char ***out_strv)
err_out:
g_strfreev(strv);
srd_exception_catch(NULL, "Failed to obtain string item");
srd_exception_catch(NULL, "Failed to obtain string item");
return SRD_ERR_PYTHON;
}
@@ -272,7 +272,7 @@ SRD_PRIV GVariant *py_obj_to_variant(PyObject *py_obj)
Py_DECREF(py_bytes);
}
if (!var)
srd_exception_catch(NULL, "Failed to extract string value");
srd_exception_catch(NULL, "Failed to extract string value");
} else if (PyLong_Check(py_obj)) { /* integer */
int64_t val;
@@ -281,7 +281,7 @@ SRD_PRIV GVariant *py_obj_to_variant(PyObject *py_obj)
if (!PyErr_Occurred())
var = g_variant_new_int64(val);
else
srd_exception_catch(NULL, "Failed to extract integer value");
srd_exception_catch(NULL, "Failed to extract integer value");
} else if (PyFloat_Check(py_obj)) { /* float */
double val;
@@ -290,7 +290,7 @@ SRD_PRIV GVariant *py_obj_to_variant(PyObject *py_obj)
if (!PyErr_Occurred())
var = g_variant_new_double(val);
else
srd_exception_catch(NULL, "Failed to extract float value");
srd_exception_catch(NULL, "Failed to extract float value");
} else {
srd_err("Failed to extract value of unsupported type.");