diff --git a/libsigrokdecode4DSL/.gitignore b/libsigrokdecode4DSL/.gitignore index 36d0ef2c..88109f96 100755 --- a/libsigrokdecode4DSL/.gitignore +++ b/libsigrokdecode4DSL/.gitignore @@ -29,6 +29,7 @@ /libtool /version.h __pycache__/ +*.pyc stamp-h? # Files generated by the testsuite diff --git a/libsigrokdecode4DSL/Makefile.am b/libsigrokdecode4DSL/Makefile.am index 3141f2f3..2e0f8910 100644 --- a/libsigrokdecode4DSL/Makefile.am +++ b/libsigrokdecode4DSL/Makefile.am @@ -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 diff --git a/libsigrokdecode4DSL/configure.ac b/libsigrokdecode4DSL/configure.ac index 3b8deab6..002372ae 100644 --- a/libsigrokdecode4DSL/configure.ac +++ b/libsigrokdecode4DSL/configure.ac @@ -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 diff --git a/libsigrokdecode4DSL/decoder.c b/libsigrokdecode4DSL/decoder.c index 27dcbed0..4797844e 100644 --- a/libsigrokdecode4DSL/decoder.c +++ b/libsigrokdecode4DSL/decoder.c @@ -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; } diff --git a/libsigrokdecode4DSL/decoders/0-spi/pd.py b/libsigrokdecode4DSL/decoders/0-spi/pd.py index 90898f78..3417d630 100755 --- a/libsigrokdecode4DSL/decoders/0-spi/pd.py +++ b/libsigrokdecode4DSL/decoders/0-spi/pd.py @@ -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 diff --git a/libsigrokdecode4DSL/decoders/0-uart/pd.py b/libsigrokdecode4DSL/decoders/0-uart/pd.py index 1d89d1dd..21052515 100755 --- a/libsigrokdecode4DSL/decoders/0-uart/pd.py +++ b/libsigrokdecode4DSL/decoders/0-uart/pd.py @@ -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': diff --git a/libsigrokdecode4DSL/decoders/1-i2c/pd.py b/libsigrokdecode4DSL/decoders/1-i2c/pd.py index dc8c77f8..2572170b 100755 --- a/libsigrokdecode4DSL/decoders/1-i2c/pd.py +++ b/libsigrokdecode4DSL/decoders/1-i2c/pd.py @@ -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: diff --git a/libsigrokdecode4DSL/decoders/1-spi/pd.py b/libsigrokdecode4DSL/decoders/1-spi/pd.py index f6dba532..869f6f0b 100755 --- a/libsigrokdecode4DSL/decoders/1-spi/pd.py +++ b/libsigrokdecode4DSL/decoders/1-spi/pd.py @@ -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 diff --git a/libsigrokdecode4DSL/decoders/1-uart/pd.py b/libsigrokdecode4DSL/decoders/1-uart/pd.py index 159f1a37..e9b18953 100755 --- a/libsigrokdecode4DSL/decoders/1-uart/pd.py +++ b/libsigrokdecode4DSL/decoders/1-uart/pd.py @@ -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': diff --git a/libsigrokdecode4DSL/decoders/arm_tpiu/pd.py b/libsigrokdecode4DSL/decoders/arm_tpiu/pd.py index cf5e8750..d1113118 100755 --- a/libsigrokdecode4DSL/decoders/arm_tpiu/pd.py +++ b/libsigrokdecode4DSL/decoders/arm_tpiu/pd.py @@ -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']: diff --git a/libsigrokdecode4DSL/decoders/common/__init__.py b/libsigrokdecode4DSL/decoders/common/__init__.py new file mode 100755 index 00000000..c597431a --- /dev/null +++ b/libsigrokdecode4DSL/decoders/common/__init__.py @@ -0,0 +1,20 @@ +## +## This file is part of the libsigrokdecode project. +## +## Copyright (C) 2016 Uwe Hermann +## +## 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 +## + diff --git a/libsigrokdecode4DSL/decoders/common/plugtrx/__init__.py b/libsigrokdecode4DSL/decoders/common/plugtrx/__init__.py new file mode 100755 index 00000000..8dd0822b --- /dev/null +++ b/libsigrokdecode4DSL/decoders/common/plugtrx/__init__.py @@ -0,0 +1,20 @@ +## +## This file is part of the libsigrokdecode project. +## +## Copyright (C) 2016 Bert Vermeulen +## +## 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 . +## + +from .mod import * diff --git a/libsigrokdecode4DSL/decoders/common/plugtrx/mod.py b/libsigrokdecode4DSL/decoders/common/plugtrx/mod.py new file mode 100755 index 00000000..3d1b66dd --- /dev/null +++ b/libsigrokdecode4DSL/decoders/common/plugtrx/mod.py @@ -0,0 +1,192 @@ +## +## This file is part of the libsigrokdecode project. +## +## Copyright (C) 2016 Bert Vermeulen +## +## 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 . +## + +# 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', +] diff --git a/libsigrokdecode4DSL/decoders/common/sdcard/__init__.py b/libsigrokdecode4DSL/decoders/common/sdcard/__init__.py new file mode 100755 index 00000000..cf09d9dc --- /dev/null +++ b/libsigrokdecode4DSL/decoders/common/sdcard/__init__.py @@ -0,0 +1,21 @@ +## +## This file is part of the libsigrokdecode project. +## +## Copyright (C) 2012-2014 Uwe Hermann +## +## 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 * diff --git a/libsigrokdecode4DSL/decoders/common/sdcard/mod.py b/libsigrokdecode4DSL/decoders/common/sdcard/mod.py new file mode 100755 index 00000000..f553cf11 --- /dev/null +++ b/libsigrokdecode4DSL/decoders/common/sdcard/mod.py @@ -0,0 +1,186 @@ +## +## This file is part of the libsigrokdecode project. +## +## Copyright (C) 2012-2014 Uwe Hermann +## +## 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 +} diff --git a/libsigrokdecode4DSL/decoders/common/srdhelper/__init__.py b/libsigrokdecode4DSL/decoders/common/srdhelper/__init__.py new file mode 100755 index 00000000..cf09d9dc --- /dev/null +++ b/libsigrokdecode4DSL/decoders/common/srdhelper/__init__.py @@ -0,0 +1,21 @@ +## +## This file is part of the libsigrokdecode project. +## +## Copyright (C) 2012-2014 Uwe Hermann +## +## 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 * diff --git a/libsigrokdecode4DSL/decoders/common/srdhelper/mod.py b/libsigrokdecode4DSL/decoders/common/srdhelper/mod.py new file mode 100755 index 00000000..e65ab17e --- /dev/null +++ b/libsigrokdecode4DSL/decoders/common/srdhelper/mod.py @@ -0,0 +1,23 @@ +## +## This file is part of the libsigrokdecode project. +## +## Copyright (C) 2012-2014 Uwe Hermann +## +## 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) diff --git a/libsigrokdecode4DSL/decoders/dcf77/pd.py b/libsigrokdecode4DSL/decoders/dcf77/pd.py index 24318a46..ff5e6118 100755 --- a/libsigrokdecode4DSL/decoders/dcf77/pd.py +++ b/libsigrokdecode4DSL/decoders/dcf77/pd.py @@ -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 diff --git a/libsigrokdecode4DSL/decoders/dmx512/__init__.py b/libsigrokdecode4DSL/decoders/dmx512/__init__.py index b5e57836..9761dd5f 100644 --- a/libsigrokdecode4DSL/decoders/dmx512/__init__.py +++ b/libsigrokdecode4DSL/decoders/dmx512/__init__.py @@ -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 . +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ## ''' diff --git a/libsigrokdecode4DSL/decoders/dmx512/pd.py b/libsigrokdecode4DSL/decoders/dmx512/pd.py index 79270c75..7ec57d6e 100644 --- a/libsigrokdecode4DSL/decoders/dmx512/pd.py +++ b/libsigrokdecode4DSL/decoders/dmx512/pd.py @@ -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 . +## 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 diff --git a/libsigrokdecode4DSL/decoders/ds1307/pd.py b/libsigrokdecode4DSL/decoders/ds1307/pd.py index b784b6dd..f181fd99 100755 --- a/libsigrokdecode4DSL/decoders/ds1307/pd.py +++ b/libsigrokdecode4DSL/decoders/ds1307/pd.py @@ -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 diff --git a/libsigrokdecode4DSL/decoders/eeprom24xx/pd.py b/libsigrokdecode4DSL/decoders/eeprom24xx/pd.py index 0738c06b..73269a6d 100755 --- a/libsigrokdecode4DSL/decoders/eeprom24xx/pd.py +++ b/libsigrokdecode4DSL/decoders/eeprom24xx/pd.py @@ -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. diff --git a/libsigrokdecode4DSL/decoders/em4100/pd.py b/libsigrokdecode4DSL/decoders/em4100/pd.py index c686e520..b717db7b 100755 --- a/libsigrokdecode4DSL/decoders/em4100/pd.py +++ b/libsigrokdecode4DSL/decoders/em4100/pd.py @@ -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 diff --git a/libsigrokdecode4DSL/decoders/em4305/__init__.py b/libsigrokdecode4DSL/decoders/em4305/__init__.py new file mode 100755 index 00000000..1c1896a3 --- /dev/null +++ b/libsigrokdecode4DSL/decoders/em4305/__init__.py @@ -0,0 +1,25 @@ +## +## This file is part of the libsigrokdecode project. +## +## Copyright (C) 2015 Benjamin Larsson +## +## 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 diff --git a/libsigrokdecode4DSL/decoders/em4305/pd.py b/libsigrokdecode4DSL/decoders/em4305/pd.py new file mode 100755 index 00000000..9dd6c0e2 --- /dev/null +++ b/libsigrokdecode4DSL/decoders/em4305/pd.py @@ -0,0 +1,397 @@ +## +## This file is part of the libsigrokdecode project. +## +## Copyright (C) 2016 Benjamin Larsson +## +## 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 diff --git a/libsigrokdecode4DSL/decoders/gpib/__init__.py b/libsigrokdecode4DSL/decoders/gpib/__init__.py index 3b546ef1..3dae5637 100644 --- a/libsigrokdecode4DSL/decoders/gpib/__init__.py +++ b/libsigrokdecode4DSL/decoders/gpib/__init__.py @@ -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 . +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ## ''' diff --git a/libsigrokdecode4DSL/decoders/gpib/pd.py b/libsigrokdecode4DSL/decoders/gpib/pd.py index d3bb72f9..672de55e 100644 --- a/libsigrokdecode4DSL/decoders/gpib/pd.py +++ b/libsigrokdecode4DSL/decoders/gpib/pd.py @@ -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 . +## 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 diff --git a/libsigrokdecode4DSL/decoders/midi/lists.py b/libsigrokdecode4DSL/decoders/midi/lists.py index c72f5c9c..ce4c1aeb 100755 --- a/libsigrokdecode4DSL/decoders/midi/lists.py +++ b/libsigrokdecode4DSL/decoders/midi/lists.py @@ -1,7 +1,8 @@ ## ## This file is part of the libsigrokdecode project. ## -## Copyright (C) 2013 Uwe Hermann +## Copyright (C) 2013-2016 Uwe Hermann +## Copyright (C) 2016 Chris Dreher ## ## 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', } diff --git a/libsigrokdecode4DSL/decoders/midi/pd.py b/libsigrokdecode4DSL/decoders/midi/pd.py index 1616af10..18c439f4 100755 --- a/libsigrokdecode4DSL/decoders/midi/pd.py +++ b/libsigrokdecode4DSL/decoders/midi/pd.py @@ -1,7 +1,8 @@ ## ## This file is part of the libsigrokdecode project. ## -## Copyright (C) 2013 Uwe Hermann +## Copyright (C) 2013-2016 Uwe Hermann +## Copyright (C) 2016 Chris Dreher ## ## 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 = '' + 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 = '' + 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) diff --git a/libsigrokdecode4DSL/decoders/onewire_link/pd.py b/libsigrokdecode4DSL/decoders/onewire_link/pd.py index 0f4ed676..e1a7dd71 100755 --- a/libsigrokdecode4DSL/decoders/onewire_link/pd.py +++ b/libsigrokdecode4DSL/decoders/onewire_link/pd.py @@ -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' - diff --git a/libsigrokdecode4DSL/decoders/ps2/__init__.py b/libsigrokdecode4DSL/decoders/ps2/__init__.py new file mode 100755 index 00000000..75c47687 --- /dev/null +++ b/libsigrokdecode4DSL/decoders/ps2/__init__.py @@ -0,0 +1,26 @@ +## +## This file is part of the libsigrokdecode project. +## +## Copyright (C) 2016 Daniel Schulte +## +## 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 . +## + +''' +This protocol decoder can decode PS/2 device -> host communication. + +Host -> device communication is currently not supported. +''' + +from .pd import Decoder diff --git a/libsigrokdecode4DSL/decoders/ps2/pd.py b/libsigrokdecode4DSL/decoders/ps2/pd.py new file mode 100755 index 00000000..769352af --- /dev/null +++ b/libsigrokdecode4DSL/decoders/ps2/pd.py @@ -0,0 +1,145 @@ +## +## This file is part of the libsigrokdecode project. +## +## Copyright (C) 2016 Daniel Schulte +## +## 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) diff --git a/libsigrokdecode4DSL/decoders/rgb_led_ws281x/pd.py b/libsigrokdecode4DSL/decoders/rgb_led_ws281x/pd.py index cf0d3700..9777a613 100755 --- a/libsigrokdecode4DSL/decoders/rgb_led_ws281x/pd.py +++ b/libsigrokdecode4DSL/decoders/rgb_led_ws281x/pd.py @@ -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 diff --git a/libsigrokdecode4DSL/decoders/rtc8564/pd.py b/libsigrokdecode4DSL/decoders/rtc8564/pd.py index 24a68fbe..4ecc15a6 100755 --- a/libsigrokdecode4DSL/decoders/rtc8564/pd.py +++ b/libsigrokdecode4DSL/decoders/rtc8564/pd.py @@ -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 diff --git a/libsigrokdecode4DSL/decoders/sdcard_sd/__init__.py b/libsigrokdecode4DSL/decoders/sdcard_sd/__init__.py index a05f21aa..c43f6237 100755 --- a/libsigrokdecode4DSL/decoders/sdcard_sd/__init__.py +++ b/libsigrokdecode4DSL/decoders/sdcard_sd/__init__.py @@ -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 ## diff --git a/libsigrokdecode4DSL/decoders/sdcard_sd/pd.py b/libsigrokdecode4DSL/decoders/sdcard_sd/pd.py index 3654fbad..57e0484d 100755 --- a/libsigrokdecode4DSL/decoders/sdcard_sd/pd.py +++ b/libsigrokdecode4DSL/decoders/sdcard_sd/pd.py @@ -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 ## @@ -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 diff --git a/libsigrokdecode4DSL/decoders/sdcard_spi/pd.py b/libsigrokdecode4DSL/decoders/sdcard_spi/pd.py index bc761ee8..45490adb 100755 --- a/libsigrokdecode4DSL/decoders/sdcard_spi/pd.py +++ b/libsigrokdecode4DSL/decoders/sdcard_spi/pd.py @@ -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. diff --git a/libsigrokdecode4DSL/decoders/spiflash/lists.py b/libsigrokdecode4DSL/decoders/spiflash/lists.py index 4ed6aaf3..ba9f2c2b 100755 --- a/libsigrokdecode4DSL/decoders/spiflash/lists.py +++ b/libsigrokdecode4DSL/decoders/spiflash/lists.py @@ -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', diff --git a/libsigrokdecode4DSL/decoders/spiflash/pd.py b/libsigrokdecode4DSL/decoders/spiflash/pd.py index 1e3b916d..bc5f9ca8 100755 --- a/libsigrokdecode4DSL/decoders/spiflash/pd.py +++ b/libsigrokdecode4DSL/decoders/spiflash/pd.py @@ -1,7 +1,7 @@ ## ## This file is part of the libsigrokdecode project. ## -## Copyright (C) 2011-2015 Uwe Hermann +## Copyright (C) 2011-2016 Uwe Hermann ## ## 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_. + 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 diff --git a/libsigrokdecode4DSL/decoders/ssi32/__init__.py b/libsigrokdecode4DSL/decoders/ssi32/__init__.py index cd6890fa..fb7b4edd 100644 --- a/libsigrokdecode4DSL/decoders/ssi32/__init__.py +++ b/libsigrokdecode4DSL/decoders/ssi32/__init__.py @@ -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 . +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ## ''' diff --git a/libsigrokdecode4DSL/decoders/ssi32/pd.py b/libsigrokdecode4DSL/decoders/ssi32/pd.py index f2e79b8a..8c68e0df 100644 --- a/libsigrokdecode4DSL/decoders/ssi32/pd.py +++ b/libsigrokdecode4DSL/decoders/ssi32/pd.py @@ -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 . +## 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 diff --git a/libsigrokdecode4DSL/decoders/stepper_motor/pd.py b/libsigrokdecode4DSL/decoders/stepper_motor/pd.py index 74416fa6..aa2c2380 100755 --- a/libsigrokdecode4DSL/decoders/stepper_motor/pd.py +++ b/libsigrokdecode4DSL/decoders/stepper_motor/pd.py @@ -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: diff --git a/libsigrokdecode4DSL/decoders/timing/pd.py b/libsigrokdecode4DSL/decoders/timing/pd.py index e77fb14e..b558fa28 100755 --- a/libsigrokdecode4DSL/decoders/timing/pd.py +++ b/libsigrokdecode4DSL/decoders/timing/pd.py @@ -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 diff --git a/libsigrokdecode4DSL/decoders/usb_request/pd.py b/libsigrokdecode4DSL/decoders/usb_request/pd.py index efd880d7..67b092c6 100755 --- a/libsigrokdecode4DSL/decoders/usb_request/pd.py +++ b/libsigrokdecode4DSL/decoders/usb_request/pd.py @@ -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(' 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': diff --git a/libsigrokdecode4DSL/decoders/wiegand/pd.py b/libsigrokdecode4DSL/decoders/wiegand/pd.py index ba117df1..58ee49c5 100755 --- a/libsigrokdecode4DSL/decoders/wiegand/pd.py +++ b/libsigrokdecode4DSL/decoders/wiegand/pd.py @@ -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 = [] diff --git a/libsigrokdecode4DSL/decoders/xfp/pd.py b/libsigrokdecode4DSL/decoders/xfp/pd.py index 41aca0db..27135e58 100755 --- a/libsigrokdecode4DSL/decoders/xfp/pd.py +++ b/libsigrokdecode4DSL/decoders/xfp/pd.py @@ -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 diff --git a/libsigrokdecode4DSL/exception.c b/libsigrokdecode4DSL/exception.c index d389af31..dd029d1b 100644 --- a/libsigrokdecode4DSL/exception.c +++ b/libsigrokdecode4DSL/exception.c @@ -2,6 +2,7 @@ * This file is part of the libsigrokdecode project. * * Copyright (C) 2012 Bert Vermeulen + * Copyright (C) 2016 DreamSourceLab * * 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); } diff --git a/libsigrokdecode4DSL/instance.c b/libsigrokdecode4DSL/instance.c index e9dec740..1abcd0e3 100644 --- a/libsigrokdecode4DSL/instance.c +++ b/libsigrokdecode4DSL/instance.c @@ -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); diff --git a/libsigrokdecode4DSL/libsigrokdecode-internal.h b/libsigrokdecode4DSL/libsigrokdecode-internal.h index 0131907c..805d62a9 100644 --- a/libsigrokdecode4DSL/libsigrokdecode-internal.h +++ b/libsigrokdecode4DSL/libsigrokdecode-internal.h @@ -3,6 +3,7 @@ * * Copyright (C) 2011 Uwe Hermann * Copyright (C) 2012 Bert Vermeulen + * Copyright (C) 2016 DreamSourceLab * * 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 diff --git a/libsigrokdecode4DSL/libsigrokdecode.h b/libsigrokdecode4DSL/libsigrokdecode.h index 14bdd6a2..3d764f24 100644 --- a/libsigrokdecode4DSL/libsigrokdecode.h +++ b/libsigrokdecode4DSL/libsigrokdecode.h @@ -3,6 +3,7 @@ * * Copyright (C) 2010 Uwe Hermann * Copyright (C) 2012 Bert Vermeulen + * Copyright (C) 2016 DreamSourceLab * * 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); diff --git a/libsigrokdecode4DSL/module_sigrokdecode.c b/libsigrokdecode4DSL/module_sigrokdecode.c index 15c40f12..73243b2d 100644 --- a/libsigrokdecode4DSL/module_sigrokdecode.c +++ b/libsigrokdecode4DSL/module_sigrokdecode.c @@ -17,9 +17,9 @@ * along with this program. If not, see . */ -#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; } diff --git a/libsigrokdecode4DSL/session.c b/libsigrokdecode4DSL/session.c index 67954e30..24fde25b 100644 --- a/libsigrokdecode4DSL/session.c +++ b/libsigrokdecode4DSL/session.c @@ -3,6 +3,7 @@ * * Copyright (C) 2010 Uwe Hermann * Copyright (C) 2013 Bert Vermeulen + * Copyright (C) 2016 DreamSourceLab * * 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; } diff --git a/libsigrokdecode4DSL/srd.c b/libsigrokdecode4DSL/srd.c index a630db37..5933f881 100644 --- a/libsigrokdecode4DSL/srd.c +++ b/libsigrokdecode4DSL/srd.c @@ -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) { diff --git a/libsigrokdecode4DSL/tests/core.c b/libsigrokdecode4DSL/tests/core.c index 3b26a2e1..670d9bd8 100644 --- a/libsigrokdecode4DSL/tests/core.c +++ b/libsigrokdecode4DSL/tests/core.c @@ -19,7 +19,7 @@ */ #include -#include "../libsigrokdecode.h" /* First, to avoid compiler warning. */ +#include /* First, to avoid compiler warning. */ #include #include #include "lib.h" diff --git a/libsigrokdecode4DSL/tests/decoder.c b/libsigrokdecode4DSL/tests/decoder.c index 97d57678..2b887858 100644 --- a/libsigrokdecode4DSL/tests/decoder.c +++ b/libsigrokdecode4DSL/tests/decoder.c @@ -19,7 +19,7 @@ */ #include -#include "../libsigrokdecode.h" /* First, to avoid compiler warning. */ +#include /* First, to avoid compiler warning. */ #include #include #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); diff --git a/libsigrokdecode4DSL/tests/inst.c b/libsigrokdecode4DSL/tests/inst.c index 8d30b125..d52793aa 100644 --- a/libsigrokdecode4DSL/tests/inst.c +++ b/libsigrokdecode4DSL/tests/inst.c @@ -19,7 +19,7 @@ */ #include -#include "../libsigrokdecode.h" /* First, to avoid compiler warning. */ +#include /* First, to avoid compiler warning. */ #include #include #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); diff --git a/libsigrokdecode4DSL/tests/main.c b/libsigrokdecode4DSL/tests/main.c index 19c459d6..b84b20e3 100644 --- a/libsigrokdecode4DSL/tests/main.c +++ b/libsigrokdecode4DSL/tests/main.c @@ -19,7 +19,7 @@ */ #include -#include "../libsigrokdecode.h" /* First, to avoid compiler warning. */ +#include /* First, to avoid compiler warning. */ #include #include #include "lib.h" diff --git a/libsigrokdecode4DSL/tests/session.c b/libsigrokdecode4DSL/tests/session.c index 431ab5ec..0d352bd1 100644 --- a/libsigrokdecode4DSL/tests/session.c +++ b/libsigrokdecode4DSL/tests/session.c @@ -19,8 +19,8 @@ */ #include -#include "../libsigrokdecode-internal.h" /* First, to avoid compiler warning. */ -#include "../libsigrokdecode.h" +#include /* First, to avoid compiler warning. */ +#include #include #include #include diff --git a/libsigrokdecode4DSL/tools/install-decoders b/libsigrokdecode4DSL/tools/install-decoders index 465c70e4..3772bd5a 100755 --- a/libsigrokdecode4DSL/tools/install-decoders +++ b/libsigrokdecode4DSL/tools/install-decoders @@ -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') diff --git a/libsigrokdecode4DSL/type_decoder.c b/libsigrokdecode4DSL/type_decoder.c index 907b0d8c..08c5e775 100644 --- a/libsigrokdecode4DSL/type_decoder.c +++ b/libsigrokdecode4DSL/type_decoder.c @@ -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); diff --git a/libsigrokdecode4DSL/type_logic.c b/libsigrokdecode4DSL/type_logic.c index 6f934059..75143933 100644 --- a/libsigrokdecode4DSL/type_logic.c +++ b/libsigrokdecode4DSL/type_logic.c @@ -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); } diff --git a/libsigrokdecode4DSL/util.c b/libsigrokdecode4DSL/util.c index 6e9bb22b..d071256f 100644 --- a/libsigrokdecode4DSL/util.c +++ b/libsigrokdecode4DSL/util.c @@ -3,6 +3,7 @@ * * Copyright (C) 2010 Uwe Hermann * Copyright (C) 2012 Bert Vermeulen + * Copyright (C) 2016 DreamSourceLab * * 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.");