forked from Ivasoft/DSView
Add more decoders
This commit is contained in:
1
libsigrokdecode4DSL/.gitignore
vendored
1
libsigrokdecode4DSL/.gitignore
vendored
@@ -29,6 +29,7 @@
|
||||
/libtool
|
||||
/version.h
|
||||
__pycache__/
|
||||
*.pyc
|
||||
stamp-h?
|
||||
|
||||
# Files generated by the testsuite
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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':
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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':
|
||||
|
||||
@@ -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']:
|
||||
|
||||
20
libsigrokdecode4DSL/decoders/common/__init__.py
Executable file
20
libsigrokdecode4DSL/decoders/common/__init__.py
Executable file
@@ -0,0 +1,20 @@
|
||||
##
|
||||
## This file is part of the libsigrokdecode project.
|
||||
##
|
||||
## Copyright (C) 2016 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation; either version 2 of the License, or
|
||||
## (at your option) any later version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
## GNU General Public License for more details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License
|
||||
## along with this program; if not, write to the Free Software
|
||||
## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
##
|
||||
|
||||
20
libsigrokdecode4DSL/decoders/common/plugtrx/__init__.py
Executable file
20
libsigrokdecode4DSL/decoders/common/plugtrx/__init__.py
Executable file
@@ -0,0 +1,20 @@
|
||||
##
|
||||
## This file is part of the libsigrokdecode project.
|
||||
##
|
||||
## Copyright (C) 2016 Bert Vermeulen <bert@biot.com>
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation; either version 3 of the License, or
|
||||
## (at your option) any later version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
## GNU General Public License for more details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License
|
||||
## along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
##
|
||||
|
||||
from .mod import *
|
||||
192
libsigrokdecode4DSL/decoders/common/plugtrx/mod.py
Executable file
192
libsigrokdecode4DSL/decoders/common/plugtrx/mod.py
Executable file
@@ -0,0 +1,192 @@
|
||||
##
|
||||
## This file is part of the libsigrokdecode project.
|
||||
##
|
||||
## Copyright (C) 2016 Bert Vermeulen <bert@biot.com>
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation; either version 3 of the License, or
|
||||
## (at your option) any later version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
## GNU General Public License for more details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License
|
||||
## along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
##
|
||||
|
||||
# This module contains definitions for use by pluggable network adapters,
|
||||
# such as SFP, XFP etc.
|
||||
|
||||
MODULE_ID = {
|
||||
0x01: 'GBIC',
|
||||
0x02: 'Integrated module/connector',
|
||||
0x03: 'SFP',
|
||||
0x04: '300-pin XBI',
|
||||
0x05: 'XENPAK',
|
||||
0x06: 'XFP',
|
||||
0x07: 'XFF',
|
||||
0x08: 'XFP-E',
|
||||
0x09: 'XPAK',
|
||||
0x0a: 'X2',
|
||||
}
|
||||
|
||||
ALARM_THRESHOLDS = {
|
||||
0: 'Temp high alarm',
|
||||
2: 'Temp low alarm',
|
||||
4: 'Temp high warning',
|
||||
6: 'Temp low warning',
|
||||
16: 'Bias high alarm',
|
||||
18: 'Bias low alarm',
|
||||
20: 'Bias high warning',
|
||||
22: 'Bias low warning',
|
||||
24: 'TX power high alarm',
|
||||
26: 'TX power low alarm',
|
||||
28: 'TX power high warning',
|
||||
30: 'TX power low warning',
|
||||
32: 'RX power high alarm',
|
||||
34: 'RX power low alarm',
|
||||
36: 'RX power high warning',
|
||||
38: 'RX power low warning',
|
||||
40: 'AUX 1 high alarm',
|
||||
42: 'AUX 1 low alarm',
|
||||
44: 'AUX 1 high warning',
|
||||
46: 'AUX 1 low warning',
|
||||
48: 'AUX 2 high alarm',
|
||||
50: 'AUX 2 low alarm',
|
||||
52: 'AUX 2 high warning',
|
||||
54: 'AUX 2 low warning',
|
||||
}
|
||||
|
||||
AD_READOUTS = {
|
||||
0: 'Module temperature',
|
||||
4: 'TX bias current',
|
||||
6: 'Measured TX output power',
|
||||
8: 'Measured RX input power',
|
||||
10: 'AUX 1 measurement',
|
||||
12: 'AUX 2 measurement',
|
||||
}
|
||||
|
||||
GCS_BITS = [
|
||||
'TX disable',
|
||||
'Soft TX disable',
|
||||
'MOD_NR',
|
||||
'P_Down',
|
||||
'Soft P_Down',
|
||||
'Interrupt',
|
||||
'RX_LOS',
|
||||
'Data_Not_Ready',
|
||||
'TX_NR',
|
||||
'TX_Fault',
|
||||
'TX_CDR not locked',
|
||||
'RX_NR',
|
||||
'RX_CDR not locked',
|
||||
]
|
||||
|
||||
CONNECTOR = {
|
||||
0x01: 'SC',
|
||||
0x02: 'Fibre Channel style 1 copper',
|
||||
0x03: 'Fibre Channel style 2 copper',
|
||||
0x04: 'BNC/TNC',
|
||||
0x05: 'Fibre Channel coax',
|
||||
0x06: 'FiberJack',
|
||||
0x07: 'LC',
|
||||
0x08: 'MT-RJ',
|
||||
0x09: 'MU',
|
||||
0x0a: 'SG',
|
||||
0x0b: 'Optical pigtail',
|
||||
0x20: 'HSSDC II',
|
||||
0x21: 'Copper pigtail',
|
||||
}
|
||||
|
||||
TRANSCEIVER = [
|
||||
# 10GB Ethernet
|
||||
['10GBASE-SR', '10GBASE-LR', '10GBASE-ER', '10GBASE-LRM', '10GBASE-SW',
|
||||
'10GBASE-LW', '10GBASE-EW'],
|
||||
# 10GB Fibre Channel
|
||||
['1200-MX-SN-I', '1200-SM-LL-L', 'Extended Reach 1550 nm',
|
||||
'Intermediate reach 1300 nm FP'],
|
||||
# 10GB Copper
|
||||
[],
|
||||
# 10GB low speed
|
||||
['1000BASE-SX / 1xFC MMF', '1000BASE-LX / 1xFC SMF', '2xFC MMF',
|
||||
'2xFC SMF', 'OC48-SR', 'OC48-IR', 'OC48-LR'],
|
||||
# 10GB SONET/SDH interconnect
|
||||
['I-64.1r', 'I-64.1', 'I-64.2r', 'I-64.2', 'I-64.3', 'I-64.5'],
|
||||
# 10GB SONET/SDH short haul
|
||||
['S-64.1', 'S-64.2a', 'S-64.2b', 'S-64.3a', 'S-64.3b', 'S-64.5a', 'S-64.5b'],
|
||||
# 10GB SONET/SDH long haul
|
||||
['L-64.1', 'L-64.2a', 'L-64.2b', 'L-64.2c', 'L-64.3', 'G.959.1 P1L1-2D2'],
|
||||
# 10GB SONET/SDH very long haul
|
||||
['V-64.2a', 'V-64.2b', 'V-64.3'],
|
||||
]
|
||||
|
||||
SERIAL_ENCODING = [
|
||||
'64B/66B',
|
||||
'8B/10B',
|
||||
'SONET scrambled',
|
||||
'NRZ',
|
||||
'RZ',
|
||||
]
|
||||
|
||||
XMIT_TECH = [
|
||||
'850 nm VCSEL',
|
||||
'1310 nm VCSEL',
|
||||
'1550 nm VCSEL',
|
||||
'1310 nm FP',
|
||||
'1310 nm DFB',
|
||||
'1550 nm DFB',
|
||||
'1310 nm EML'
|
||||
'1550 nm EML'
|
||||
'copper',
|
||||
]
|
||||
|
||||
CDR = [
|
||||
'9.95Gb/s',
|
||||
'10.3Gb/s',
|
||||
'10.5Gb/s',
|
||||
'10.7Gb/s',
|
||||
'11.1Gb/s',
|
||||
'(unknown)',
|
||||
'lineside loopback mode',
|
||||
'XFI loopback mode',
|
||||
]
|
||||
|
||||
DEVICE_TECH = [
|
||||
['no wavelength control', 'sctive wavelength control'],
|
||||
['uncooled transmitter device', 'cooled transmitter'],
|
||||
['PIN detector', 'APD detector'],
|
||||
['transmitter not tunable', 'transmitter tunable'],
|
||||
]
|
||||
|
||||
ENHANCED_OPTS = [
|
||||
'VPS',
|
||||
'soft TX_DISABLE',
|
||||
'soft P_Down',
|
||||
'VPS LV regulator mode',
|
||||
'VPS bypassed regulator mode',
|
||||
'active FEC control',
|
||||
'wavelength tunability',
|
||||
'CMU',
|
||||
]
|
||||
|
||||
AUX_TYPES = [
|
||||
'not implemented',
|
||||
'APD bias voltage',
|
||||
'(unknown)',
|
||||
'TEC current',
|
||||
'laser temperature',
|
||||
'laser wavelength',
|
||||
'5V supply voltage',
|
||||
'3.3V supply voltage',
|
||||
'1.8V supply voltage',
|
||||
'-5.2V supply voltage',
|
||||
'5V supply current',
|
||||
'(unknown)',
|
||||
'(unknown)',
|
||||
'3.3V supply current',
|
||||
'1.8V supply current',
|
||||
'-5.2V supply current',
|
||||
]
|
||||
21
libsigrokdecode4DSL/decoders/common/sdcard/__init__.py
Executable file
21
libsigrokdecode4DSL/decoders/common/sdcard/__init__.py
Executable file
@@ -0,0 +1,21 @@
|
||||
##
|
||||
## This file is part of the libsigrokdecode project.
|
||||
##
|
||||
## Copyright (C) 2012-2014 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation; either version 2 of the License, or
|
||||
## (at your option) any later version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
## GNU General Public License for more details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License
|
||||
## along with this program; if not, write to the Free Software
|
||||
## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
##
|
||||
|
||||
from .mod import *
|
||||
186
libsigrokdecode4DSL/decoders/common/sdcard/mod.py
Executable file
186
libsigrokdecode4DSL/decoders/common/sdcard/mod.py
Executable file
@@ -0,0 +1,186 @@
|
||||
##
|
||||
## This file is part of the libsigrokdecode project.
|
||||
##
|
||||
## Copyright (C) 2012-2014 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation; either version 2 of the License, or
|
||||
## (at your option) any later version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
## GNU General Public License for more details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License
|
||||
## along with this program; if not, write to the Free Software
|
||||
## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
##
|
||||
|
||||
# Normal commands (CMD)
|
||||
# Unlisted items are 'Reserved' as per SD spec. The 'Unknown' items don't
|
||||
# seem to be mentioned in the spec, but aren't marked as reserved either.
|
||||
cmd_names = {
|
||||
0: 'GO_IDLE_STATE',
|
||||
1: 'SEND_OP_COND', # Reserved in SD mode
|
||||
2: 'ALL_SEND_CID',
|
||||
3: 'SEND_RELATIVE_ADDR',
|
||||
4: 'SET_DSR',
|
||||
5: 'IO_SEND_OP_COND', # SDIO-only
|
||||
6: 'SWITCH_FUNC', # New since spec 1.10
|
||||
7: 'SELECT/DESELECT_CARD',
|
||||
8: 'SEND_IF_COND',
|
||||
9: 'SEND_CSD',
|
||||
10: 'SEND_CID',
|
||||
11: 'VOLTAGE_SWITCH',
|
||||
12: 'STOP_TRANSMISSION',
|
||||
13: 'SEND_STATUS',
|
||||
# 14: Reserved
|
||||
15: 'GO_INACTIVE_STATE',
|
||||
16: 'SET_BLOCKLEN',
|
||||
17: 'READ_SINGLE_BLOCK',
|
||||
18: 'READ_MULTIPLE_BLOCK',
|
||||
19: 'SEND_TUNING_BLOCK',
|
||||
20: 'SPEED_CLASS_CONTROL',
|
||||
# 21-22: Reserved
|
||||
23: 'SET_BLOCK_COUNT',
|
||||
24: 'WRITE_BLOCK',
|
||||
25: 'WRITE_MULTIPLE_BLOCK',
|
||||
26: 'Reserved for manufacturer',
|
||||
27: 'PROGRAM_CSD',
|
||||
28: 'SET_WRITE_PROT',
|
||||
29: 'CLR_WRITE_PROT',
|
||||
30: 'SEND_WRITE_PROT',
|
||||
# 31: Reserved
|
||||
32: 'ERASE_WR_BLK_START', # SPI mode: ERASE_WR_BLK_START_ADDR
|
||||
33: 'ERASE_WR_BLK_END', # SPI mode: ERASE_WR_BLK_END_ADDR
|
||||
34: 'Reserved for CMD6', # New since spec 1.10
|
||||
35: 'Reserved for CMD6', # New since spec 1.10
|
||||
36: 'Reserved for CMD6', # New since spec 1.10
|
||||
37: 'Reserved for CMD6', # New since spec 1.10
|
||||
38: 'ERASE',
|
||||
# 39: Reserved
|
||||
40: 'Reserved for security specification',
|
||||
# 41: Reserved
|
||||
42: 'LOCK_UNLOCK',
|
||||
# 43-49: Reserved
|
||||
50: 'Reserved for CMD6', # New since spec 1.10
|
||||
# 51: Reserved
|
||||
52: 'IO_RW_DIRECT', # SDIO-only
|
||||
53: 'IO_RW_EXTENDED', # SDIO-only
|
||||
54: 'Unknown',
|
||||
55: 'APP_CMD',
|
||||
56: 'GEN_CMD',
|
||||
57: 'Reserved for CMD6', # New since spec 1.10
|
||||
58: 'READ_OCR', # Reserved in SD mode
|
||||
59: 'CRC_ON_OFF', # Reserved in SD mode
|
||||
60: 'Reserved for manufacturer',
|
||||
61: 'Reserved for manufacturer',
|
||||
62: 'Reserved for manufacturer',
|
||||
63: 'Reserved for manufacturer',
|
||||
}
|
||||
|
||||
# Application-specific commands (ACMD)
|
||||
# Unlisted items are 'Reserved' as per SD spec. The 'Unknown' items don't
|
||||
# seem to be mentioned in the spec, but aren't marked as reserved either.
|
||||
acmd_names = {
|
||||
# 1-5: Reserved
|
||||
6: 'SET_BUS_WIDTH',
|
||||
# 7-12: Reserved
|
||||
13: 'SD_STATUS',
|
||||
14: 'Reserved for Security Application',
|
||||
15: 'Reserved for Security Application',
|
||||
16: 'Reserved for Security Application',
|
||||
# 17: Reserved
|
||||
18: 'Reserved for SD security applications',
|
||||
# 19-21: Reserved
|
||||
22: 'SEND_NUM_WR_BLOCKS',
|
||||
23: 'SET_WR_BLK_ERASE_COUNT',
|
||||
# 24: Reserved
|
||||
25: 'Reserved for SD security applications',
|
||||
26: 'Reserved for SD security applications',
|
||||
27: 'Reserved for security specification',
|
||||
28: 'Reserved for security specification',
|
||||
# 29: Reserved
|
||||
30: 'Reserved for security specification',
|
||||
31: 'Reserved for security specification',
|
||||
32: 'Reserved for security specification',
|
||||
33: 'Reserved for security specification',
|
||||
34: 'Reserved for security specification',
|
||||
35: 'Reserved for security specification',
|
||||
# 36-37: Reserved
|
||||
38: 'Reserved for SD security applications',
|
||||
# 39-40: Reserved
|
||||
41: 'SD_SEND_OP_COND',
|
||||
42: 'SET_CLR_CARD_DETECT',
|
||||
43: 'Reserved for SD security applications',
|
||||
44: 'Reserved for SD security applications',
|
||||
45: 'Reserved for SD security applications',
|
||||
46: 'Reserved for SD security applications',
|
||||
47: 'Reserved for SD security applications',
|
||||
48: 'Reserved for SD security applications',
|
||||
49: 'Reserved for SD security applications',
|
||||
50: 'Unknown',
|
||||
51: 'SEND_SCR',
|
||||
52: 'Reserved for security specification',
|
||||
53: 'Reserved for security specification',
|
||||
54: 'Reserved for security specification',
|
||||
55: 'Non-existant', # Doesn't exist (equivalent to CMD55)
|
||||
56: 'Reserved for security specification',
|
||||
57: 'Reserved for security specification',
|
||||
58: 'Reserved for security specification',
|
||||
59: 'Reserved for security specification',
|
||||
60: 'Unknown',
|
||||
61: 'Unknown',
|
||||
62: 'Unknown',
|
||||
63: 'Unknown',
|
||||
}
|
||||
|
||||
accepted_voltages = {
|
||||
0b0001: '2.7-3.6V',
|
||||
0b0010: 'reserved for low voltage range',
|
||||
0b0100: 'reserved',
|
||||
0b1000: 'reserved',
|
||||
# All other values: "not defined".
|
||||
}
|
||||
|
||||
card_status = {
|
||||
0: 'Reserved for manufacturer test mode',
|
||||
1: 'Reserved for manufacturer test mode',
|
||||
2: 'Reserved for application specific commands',
|
||||
3: 'AKE_SEQ_ERROR',
|
||||
4: 'Reserved for SDIO card',
|
||||
5: 'APP_CMD',
|
||||
6: 'Unknown',
|
||||
7: 'Unknown',
|
||||
8: 'READY_FOR_DATA',
|
||||
9: 'CURRENT_STATE', # CURRENT_STATE is a 4-bit value (decimal: 0..15).
|
||||
10: 'CURRENT_STATE',
|
||||
11: 'CURRENT_STATE',
|
||||
12: 'CURRENT_STATE',
|
||||
13: 'ERASE_RESET',
|
||||
14: 'CARD_ECC_DISABLED',
|
||||
15: 'WP_ERASE_SKIP',
|
||||
16: 'CSD_OVERWRITE',
|
||||
17: 'Reserved for DEFERRED_RESPONSE', # See eSD addendum
|
||||
18: 'Reserved',
|
||||
19: 'ERROR',
|
||||
20: 'CC_ERROR',
|
||||
21: 'CARD_ECC_FAILED',
|
||||
22: 'ILLEGAL_COMMAND',
|
||||
23: 'COM_CRC_ERROR',
|
||||
24: 'LOCK_UNLOCK_FAILED',
|
||||
25: 'CARD_IS_LOCKED',
|
||||
26: 'WP_VIOLATION',
|
||||
27: 'ERASE_PARAM',
|
||||
28: 'ERASE_SEQ_ERROR',
|
||||
29: 'BLOCK_LEN_ERROR',
|
||||
30: 'ADDRESS_ERROR',
|
||||
31: 'OUT_OF_RANGE',
|
||||
}
|
||||
|
||||
sd_status = {
|
||||
# 311:0: Reserved for manufacturer
|
||||
# 391:312: Reserved
|
||||
}
|
||||
21
libsigrokdecode4DSL/decoders/common/srdhelper/__init__.py
Executable file
21
libsigrokdecode4DSL/decoders/common/srdhelper/__init__.py
Executable file
@@ -0,0 +1,21 @@
|
||||
##
|
||||
## This file is part of the libsigrokdecode project.
|
||||
##
|
||||
## Copyright (C) 2012-2014 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation; either version 2 of the License, or
|
||||
## (at your option) any later version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
## GNU General Public License for more details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License
|
||||
## along with this program; if not, write to the Free Software
|
||||
## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
##
|
||||
|
||||
from .mod import *
|
||||
23
libsigrokdecode4DSL/decoders/common/srdhelper/mod.py
Executable file
23
libsigrokdecode4DSL/decoders/common/srdhelper/mod.py
Executable file
@@ -0,0 +1,23 @@
|
||||
##
|
||||
## This file is part of the libsigrokdecode project.
|
||||
##
|
||||
## Copyright (C) 2012-2014 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation; either version 2 of the License, or
|
||||
## (at your option) any later version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
## GNU General Public License for more details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License
|
||||
## along with this program; if not, write to the Free Software
|
||||
## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
##
|
||||
|
||||
# Return the specified BCD number (max. 8 bits) as integer.
|
||||
def bcd2int(b):
|
||||
return (b & 0x0f) + ((b >> 4) * 10)
|
||||
@@ -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
|
||||
|
||||
@@ -14,7 +14,8 @@
|
||||
## GNU General Public License for more details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License
|
||||
## along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
## along with this program; if not, write to the Free Software
|
||||
## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
##
|
||||
|
||||
'''
|
||||
|
||||
@@ -14,7 +14,8 @@
|
||||
## GNU General Public License for more details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License
|
||||
## along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
## along with this program; if not, write to the Free Software
|
||||
## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
##
|
||||
|
||||
import sigrokdecode as srd
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
25
libsigrokdecode4DSL/decoders/em4305/__init__.py
Executable file
25
libsigrokdecode4DSL/decoders/em4305/__init__.py
Executable file
@@ -0,0 +1,25 @@
|
||||
##
|
||||
## This file is part of the libsigrokdecode project.
|
||||
##
|
||||
## Copyright (C) 2015 Benjamin Larsson <benjamin@southpole.se>
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation; either version 2 of the License, or
|
||||
## (at your option) any later version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
## GNU General Public License for more details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License
|
||||
## along with this program; if not, write to the Free Software
|
||||
## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
##
|
||||
|
||||
'''
|
||||
EM4305 is a 100-150kHz RFID protocol.
|
||||
'''
|
||||
|
||||
from .pd import Decoder
|
||||
397
libsigrokdecode4DSL/decoders/em4305/pd.py
Executable file
397
libsigrokdecode4DSL/decoders/em4305/pd.py
Executable file
@@ -0,0 +1,397 @@
|
||||
##
|
||||
## This file is part of the libsigrokdecode project.
|
||||
##
|
||||
## Copyright (C) 2016 Benjamin Larsson <benjamin@southpole.se>
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation; either version 2 of the License, or
|
||||
## (at your option) any later version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
## GNU General Public License for more details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License
|
||||
## along with this program; if not, write to the Free Software
|
||||
## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
##
|
||||
|
||||
import sigrokdecode as srd
|
||||
|
||||
class SamplerateError(Exception):
|
||||
pass
|
||||
|
||||
class Decoder(srd.Decoder):
|
||||
api_version = 2
|
||||
id = 'em4305'
|
||||
name = 'EM4305'
|
||||
longname = 'RFID EM4205/EM4305'
|
||||
desc = 'EM4205/EM4305 100-150kHz RFID protocol.'
|
||||
license = 'gplv2+'
|
||||
inputs = ['logic']
|
||||
outputs = ['em4305']
|
||||
channels = (
|
||||
{'id': 'data', 'name': 'Data', 'desc': 'Data line'},
|
||||
)
|
||||
options = (
|
||||
{'id': 'coilfreq', 'desc': 'Coil frequency', 'default': 125000},
|
||||
{'id': 'first_field_stop', 'desc': 'First field stop min', 'default': 40},
|
||||
{'id': 'w_gap', 'desc': 'Write gap min', 'default': 12},
|
||||
{'id': 'w_one_max', 'desc': 'Write one max', 'default': 32},
|
||||
{'id': 'w_zero_on_min', 'desc': 'Write zero on min', 'default': 15},
|
||||
{'id': 'w_zero_off_max', 'desc': 'Write zero off max', 'default': 27},
|
||||
{'id': 'em4100_decode', 'desc': 'EM4100 decode', 'default': 'on',
|
||||
'values': ('on', 'off')},
|
||||
)
|
||||
annotations = (
|
||||
('bit_value', 'Bit value'),
|
||||
('first_field_stop', 'First field stop'),
|
||||
('write_gap', 'Write gap'),
|
||||
('write_mode_exit', 'Write mode exit'),
|
||||
('bit', 'Bit'),
|
||||
('opcode', 'Opcode'),
|
||||
('lock', 'Lock'),
|
||||
('data', 'Data'),
|
||||
('password', 'Password'),
|
||||
('address', 'Address'),
|
||||
('bitrate', 'Bitrate'),
|
||||
)
|
||||
annotation_rows = (
|
||||
('bits', 'Bits', (0,)),
|
||||
('structure', 'Structure', (1, 2, 3, 4)),
|
||||
('fields', 'Fields', (5, 6, 7, 8, 9)),
|
||||
('decode', 'Decode', (10,)),
|
||||
)
|
||||
|
||||
def __init__(self):
|
||||
self.samplerate = None
|
||||
self.oldpin = None
|
||||
self.last_samplenum = None
|
||||
self.state = 'FFS_SEARCH'
|
||||
self.bits_pos = [[0 for col in range(3)] for row in range(70)]
|
||||
self.br_string = ['RF/8', 'RF/16', 'Unused', 'RF/32', 'RF/40',
|
||||
'Unused', 'Unused', 'RF/64',]
|
||||
self.encoder = ['not used', 'Manchester', 'Bi-phase', 'not used']
|
||||
self.delayed_on = ['No delay', 'Delayed on - BP/8', 'Delayed on - BP/4', 'No delay']
|
||||
self.em4100_decode1_partial = 0
|
||||
self.cmds = ['Invalid', 'Login', 'Write word', 'Invalid', 'Read word', 'Disable', 'Protect', 'Invalid']
|
||||
|
||||
def metadata(self, key, value):
|
||||
if key == srd.SRD_CONF_SAMPLERATE:
|
||||
self.samplerate = value
|
||||
self.field_clock = self.samplerate / self.options['coilfreq']
|
||||
self.wzmax = self.options['w_zero_off_max'] * self.field_clock
|
||||
self.wzmin = self.options['w_zero_on_min'] * self.field_clock
|
||||
self.womax = self.options['w_one_max'] * self.field_clock
|
||||
self.ffs = self.options['first_field_stop'] * self.field_clock
|
||||
self.writegap = self.options['w_gap'] * self.field_clock
|
||||
self.nogap = 300 * self.field_clock
|
||||
|
||||
def start(self):
|
||||
self.out_ann = self.register(srd.OUTPUT_ANN)
|
||||
|
||||
def decode_config(self, idx):
|
||||
bitrate = self.get_3_bits(idx+2)
|
||||
self.put(self.bits_pos[idx][1], self.bits_pos[idx+5][2],
|
||||
self.out_ann, [10, ['Data rate: ' + \
|
||||
self.br_string[bitrate], self.br_string[bitrate]]])
|
||||
encoding = self.bits_pos[idx+6][0]<<0 | self.bits_pos[idx+7][0]<<1
|
||||
self.put(self.bits_pos[idx+6][1], self.bits_pos[idx+10][2],
|
||||
self.out_ann, [10, ['Encoder: ' + \
|
||||
self.encoder[encoding], self.encoder[encoding]]])
|
||||
self.put(self.bits_pos[idx+11][1], self.bits_pos[idx+12][2], self.out_ann,
|
||||
[10, ['Zero bits', 'ZB']])
|
||||
delay_on = self.bits_pos[idx+13][0]<<0 | self.bits_pos[idx+14][0]<<1
|
||||
self.put(self.bits_pos[idx+13][1], self.bits_pos[idx+14][2],
|
||||
self.out_ann, [10, ['Delayed on: ' + \
|
||||
self.delayed_on[delay_on], self.delayed_on[delay_on]]])
|
||||
lwr = self.bits_pos[idx+15][0]<<3 | self.bits_pos[idx+16][0]<<2 | \
|
||||
self.bits_pos[idx+18][0]<<1 | self.bits_pos[idx+19][0]<<0
|
||||
self.put(self.bits_pos[idx+15][1], self.bits_pos[idx+19][2],
|
||||
self.out_ann, [10, ['Last default read word: %d' % lwr, 'LWR: %d' % lwr, '%d' % lwr]])
|
||||
self.put(self.bits_pos[idx+20][1], self.bits_pos[idx+20][2],
|
||||
self.out_ann, [10, ['Read login: %d' % self.bits_pos[idx+20][0], '%d' % self.bits_pos[idx+20][0]]])
|
||||
self.put(self.bits_pos[idx+21][1], self.bits_pos[idx+21][2], self.out_ann,
|
||||
[10, ['Zero bits', 'ZB']])
|
||||
self.put(self.bits_pos[idx+22][1], self.bits_pos[idx+22][2],
|
||||
self.out_ann, [10, ['Write login: %d' % self.bits_pos[idx+22][0], '%d' % self.bits_pos[idx+22][0]]])
|
||||
self.put(self.bits_pos[idx+23][1], self.bits_pos[idx+24][2], self.out_ann,
|
||||
[10, ['Zero bits', 'ZB']])
|
||||
self.put(self.bits_pos[idx+25][1], self.bits_pos[idx+25][2],
|
||||
self.out_ann, [10, ['Disable: %d' % self.bits_pos[idx+25][0], '%d' % self.bits_pos[idx+25][0]]])
|
||||
self.put(self.bits_pos[idx+27][1], self.bits_pos[idx+27][2],
|
||||
self.out_ann, [10, ['Reader talk first: %d' % self.bits_pos[idx+27][0], 'RTF: %d' % self.bits_pos[idx+27][0]]])
|
||||
self.put(self.bits_pos[idx+28][1], self.bits_pos[idx+28][2], self.out_ann,
|
||||
[10, ['Zero bits', 'ZB']])
|
||||
self.put(self.bits_pos[idx+29][1], self.bits_pos[idx+29][2],
|
||||
self.out_ann, [10, ['Pigeon mode: %d' % self.bits_pos[idx+29][0], '%d' % self.bits_pos[idx+29][0]]])
|
||||
self.put(self.bits_pos[idx+30][1], self.bits_pos[idx+34][2],
|
||||
self.out_ann, [10, ['Reserved', 'Res', 'R']])
|
||||
|
||||
def put4bits(self, idx):
|
||||
bits = self.bits_pos[idx][0]<<3 | self.bits_pos[idx+1][0]<<2 | \
|
||||
self.bits_pos[idx+2][0]<<1 | self.bits_pos[idx+3][0]
|
||||
self.put(self.bits_pos[idx][1], self.bits_pos[idx+3][2], self.out_ann,
|
||||
[10, ['%X' % bits]])
|
||||
|
||||
def em4100_decode1(self, idx):
|
||||
self.put(self.bits_pos[idx][1], self.bits_pos[idx+9][2], self.out_ann,
|
||||
[10, ['EM4100 header', 'EM header', 'Header', 'H']])
|
||||
self.put4bits(idx+10)
|
||||
bits = self.bits_pos[idx+15][0]<<3 | self.bits_pos[idx+16][0]<<2 | \
|
||||
self.bits_pos[idx+18][0]<<1 | self.bits_pos[idx+19][0]<<0
|
||||
self.put(self.bits_pos[idx+15][1], self.bits_pos[idx+19][2], self.out_ann,
|
||||
[10, ['%X' % bits]])
|
||||
self.put4bits(idx+21)
|
||||
self.put4bits(idx+27)
|
||||
self.em4100_decode1_partial = self.bits_pos[idx+32][0]<<3 | \
|
||||
self.bits_pos[idx+33][0]<<2 | self.bits_pos[idx+34][0]<<1
|
||||
self.put(self.bits_pos[idx+32][1], self.bits_pos[idx+34][2],
|
||||
self.out_ann, [10, ['Partial nibble']])
|
||||
|
||||
def em4100_decode2(self, idx):
|
||||
if self.em4100_decode1_partial != 0:
|
||||
bits = self.em4100_decode1_partial + self.bits_pos[idx][0]
|
||||
self.put(self.bits_pos[idx][1], self.bits_pos[idx][2],
|
||||
self.out_ann, [10, ['%X' % bits]])
|
||||
self.em4100_decode1_partial = 0
|
||||
else:
|
||||
self.put(self.bits_pos[idx][1], self.bits_pos[idx][2],
|
||||
self.out_ann, [10, ['Partial nibble']])
|
||||
|
||||
self.put4bits(idx+2)
|
||||
bits = self.bits_pos[idx+7][0]<<3 | self.bits_pos[idx+9][0]<<2 | \
|
||||
self.bits_pos[idx+10][0]<<1 | self.bits_pos[idx+11][0]<<0
|
||||
self.put(self.bits_pos[idx+7][1], self.bits_pos[idx+11][2], self.out_ann,
|
||||
[10, ['%X' % bits]])
|
||||
self.put4bits(idx+13)
|
||||
self.put4bits(idx+19)
|
||||
bits = self.bits_pos[idx+24][0]<<3 | self.bits_pos[idx+25][0]<<2 | \
|
||||
self.bits_pos[idx+27][0]<<1 | self.bits_pos[idx+28][0]<<0
|
||||
self.put(self.bits_pos[idx+24][1], self.bits_pos[idx+28][2], self.out_ann,
|
||||
[10, ['%X' % bits]])
|
||||
self.put(self.bits_pos[idx+30][1], self.bits_pos[idx+34][2],
|
||||
self.out_ann, [10, ['EM4100 trailer']])
|
||||
|
||||
def get_32_bits(self, idx):
|
||||
return self.get_8_bits(idx+27)<<24 | self.get_8_bits(idx+18)<<16 | \
|
||||
self.get_8_bits(idx+9)<<8 | self.get_8_bits(idx)
|
||||
|
||||
def get_8_bits(self, idx):
|
||||
retval = 0
|
||||
for i in range(0, 8):
|
||||
retval <<= 1
|
||||
retval |= self.bits_pos[i+idx][0]
|
||||
return retval
|
||||
|
||||
def get_3_bits(self, idx):
|
||||
return self.bits_pos[idx][0]<<2 | self.bits_pos[idx+1][0]<<1 | \
|
||||
self.bits_pos[idx+2][0]
|
||||
|
||||
def get_4_bits(self, idx):
|
||||
return self.bits_pos[idx][0]<<0 | self.bits_pos[idx+1][0]<<1 | \
|
||||
self.bits_pos[idx+2][0]<<2 | self.bits_pos[idx+3][0]<<3
|
||||
|
||||
def print_row_parity(self, idx, length):
|
||||
parity = 0
|
||||
for i in range(0, length):
|
||||
parity += self.bits_pos[i+idx][0]
|
||||
parity = parity & 0x1
|
||||
if parity == self.bits_pos[idx+length][0]:
|
||||
self.put(self.bits_pos[idx+length][1], self.bits_pos[idx+length][2], self.out_ann,
|
||||
[5, ['Row parity OK', 'Parity OK', 'OK']])
|
||||
else:
|
||||
self.put(self.bits_pos[idx+length][1], self.bits_pos[idx+length][2], self.out_ann,
|
||||
[5, ['Row parity failed', 'Parity failed', 'Fail']])
|
||||
|
||||
def print_col_parity(self, idx):
|
||||
data_1 = self.get_8_bits(idx)
|
||||
data_2 = self.get_8_bits(idx+9)
|
||||
data_3 = self.get_8_bits(idx+9+9)
|
||||
data_4 = self.get_8_bits(idx+9+9+9)
|
||||
col_par = self.get_8_bits(idx+9+9+9+9)
|
||||
col_par_calc = data_1^data_2^data_3^data_4
|
||||
|
||||
if col_par == col_par_calc:
|
||||
self.put(self.bits_pos[idx+9+9+9+9][1], self.bits_pos[idx+9+9+9+9+7][2], self.out_ann,
|
||||
[5, ['Column parity OK', 'Parity OK', 'OK']])
|
||||
else:
|
||||
self.put(self.bits_pos[idx+9+9+9+9][1], self.bits_pos[idx+9+9+9+9+7][2], self.out_ann,
|
||||
[5, ['Column parity failed', 'Parity failed', 'Fail']])
|
||||
|
||||
def print_8bit_data(self, idx):
|
||||
data = self.get_8_bits(idx)
|
||||
self.put(self.bits_pos[idx][1], self.bits_pos[idx+7][2], self.out_ann,
|
||||
[9, ['Data' + ': %X' % data, '%X' % data]])
|
||||
|
||||
def put_fields(self):
|
||||
if self.bit_nr == 50:
|
||||
self.put(self.bits_pos[0][1], self.bits_pos[0][2], self.out_ann,
|
||||
[4, ['Logic zero']])
|
||||
self.put(self.bits_pos[1][1], self.bits_pos[4][2], self.out_ann,
|
||||
[4, ['Command', 'Cmd', 'C']])
|
||||
self.put(self.bits_pos[5][1], self.bits_pos[49][2], self.out_ann,
|
||||
[4, ['Password', 'Passwd', 'Pass', 'P']])
|
||||
# Get command.
|
||||
cmd = self.get_3_bits(1)
|
||||
self.put(self.bits_pos[1][1], self.bits_pos[3][2], self.out_ann,
|
||||
[5, [self.cmds[cmd]]])
|
||||
self.print_row_parity(1, 3)
|
||||
|
||||
# Print data.
|
||||
self.print_8bit_data(5)
|
||||
self.print_row_parity(5, 8)
|
||||
self.print_8bit_data(14)
|
||||
self.print_row_parity(14, 8)
|
||||
self.print_8bit_data(23)
|
||||
self.print_row_parity(23, 8)
|
||||
self.print_8bit_data(32)
|
||||
self.print_row_parity(32, 8)
|
||||
self.print_col_parity(5)
|
||||
if self.bits_pos[49][0] == 0:
|
||||
self.put(self.bits_pos[49][1], self.bits_pos[49][2], self.out_ann,
|
||||
[5, ['Stop bit', 'Stop', 'SB']])
|
||||
else:
|
||||
self.put(self.bits_pos[49][1], self.bits_pos[49][2], self.out_ann,
|
||||
[5, ['Stop bit error', 'Error']])
|
||||
|
||||
if cmd == 1:
|
||||
password = self.get_32_bits(5)
|
||||
self.put(self.bits_pos[12][1], self.bits_pos[46][2], self.out_ann,
|
||||
[10, ['Login password: %X' % password]])
|
||||
|
||||
if self.bit_nr == 57:
|
||||
self.put(self.bits_pos[0][1], self.bits_pos[0][2], self.out_ann,
|
||||
[4, ['Logic zero', 'LZ']])
|
||||
self.put(self.bits_pos[1][1], self.bits_pos[4][2], self.out_ann,
|
||||
[4, ['Command', 'Cmd', 'C']])
|
||||
self.put(self.bits_pos[5][1], self.bits_pos[11][2], self.out_ann,
|
||||
[4, ['Address', 'Addr', 'A']])
|
||||
self.put(self.bits_pos[12][1], self.bits_pos[56][2], self.out_ann,
|
||||
[4, ['Data', 'Da', 'D']])
|
||||
|
||||
# Get command.
|
||||
cmd = self.get_3_bits(1)
|
||||
self.put(self.bits_pos[1][1], self.bits_pos[3][2], self.out_ann,
|
||||
[5, [self.cmds[cmd]]])
|
||||
self.print_row_parity(1, 3)
|
||||
|
||||
# Get address.
|
||||
addr = self.get_4_bits(5)
|
||||
self.put(self.bits_pos[5][1], self.bits_pos[8][2], self.out_ann,
|
||||
[9, ['Addr' + ': %d' % addr, '%d' % addr]])
|
||||
self.put(self.bits_pos[9][1], self.bits_pos[10][2], self.out_ann,
|
||||
[5, ['Zero bits', 'ZB']])
|
||||
self.print_row_parity(5, 6)
|
||||
# Print data.
|
||||
self.print_8bit_data(12)
|
||||
self.print_row_parity(12, 8)
|
||||
self.print_8bit_data(21)
|
||||
self.print_row_parity(21, 8)
|
||||
self.print_8bit_data(30)
|
||||
self.print_row_parity(30, 8)
|
||||
self.print_8bit_data(39)
|
||||
self.print_row_parity(39, 8)
|
||||
self.print_col_parity(12)
|
||||
if self.bits_pos[56][0] == 0:
|
||||
self.put(self.bits_pos[56][1], self.bits_pos[56][2], self.out_ann,
|
||||
[5, ['Stop bit', 'Stop', 'SB']])
|
||||
else:
|
||||
self.put(self.bits_pos[56][1], self.bits_pos[56][2], self.out_ann,
|
||||
[5, ['Stop bit error', 'Error']])
|
||||
|
||||
if addr == 4:
|
||||
self.decode_config(12)
|
||||
|
||||
if addr == 2:
|
||||
password = self.get_32_bits(12)
|
||||
self.put(self.bits_pos[12][1], self.bits_pos[46][2], self.out_ann,
|
||||
[10, ['Write password: %X' % password]])
|
||||
|
||||
# If we are programming EM4100 data we can decode it halfway.
|
||||
if addr == 5 and self.options['em4100_decode'] == 'on':
|
||||
self.em4100_decode1(12)
|
||||
if addr == 6 and self.options['em4100_decode'] == 'on':
|
||||
self.em4100_decode2(12)
|
||||
|
||||
self.bit_nr = 0
|
||||
|
||||
def add_bits_pos(self, bit, ss_bit, es_bit):
|
||||
if self.bit_nr < 70:
|
||||
self.bits_pos[self.bit_nr][0] = bit
|
||||
self.bits_pos[self.bit_nr][1] = ss_bit
|
||||
self.bits_pos[self.bit_nr][2] = es_bit
|
||||
self.bit_nr += 1
|
||||
|
||||
def decode(self, ss, es, data):
|
||||
if not self.samplerate:
|
||||
raise SamplerateError('Cannot decode without samplerate.')
|
||||
for (self.samplenum, (pin,)) in data:
|
||||
data.itercnt += 1
|
||||
# Ignore identical samples early on (for performance reasons).
|
||||
if self.oldpin == pin:
|
||||
continue
|
||||
|
||||
if self.oldpin is None:
|
||||
self.oldpin = pin
|
||||
self.last_samplenum = self.samplenum
|
||||
self.oldsamplenum = 0
|
||||
self.old_gap_end = 0
|
||||
self.gap_detected = 0
|
||||
self.bit_nr = 0
|
||||
continue
|
||||
|
||||
if self.oldpin != pin:
|
||||
pl = self.samplenum - self.oldsamplenum
|
||||
pp = pin
|
||||
samples = self.samplenum - self.last_samplenum
|
||||
|
||||
if self.state == 'FFS_DETECTED':
|
||||
if pl > self.writegap:
|
||||
self.gap_detected = 1
|
||||
if (self.last_samplenum - self.old_gap_end) > self.nogap:
|
||||
self.gap_detected = 0
|
||||
self.state = 'FFS_SEARCH'
|
||||
self.put(self.old_gap_end, self.last_samplenum,
|
||||
self.out_ann, [3, ['Write mode exit']])
|
||||
self.put_fields()
|
||||
|
||||
if self.state == 'FFS_SEARCH':
|
||||
if pl > self.ffs:
|
||||
self.gap_detected = 1
|
||||
self.put(self.last_samplenum, self.samplenum,
|
||||
self.out_ann, [1, ['First field stop', 'Field stop', 'FFS']])
|
||||
self.state = 'FFS_DETECTED'
|
||||
|
||||
if self.gap_detected == 1:
|
||||
self.gap_detected = 0
|
||||
if (self.last_samplenum - self.old_gap_end) > self.wzmin \
|
||||
and (self.last_samplenum - self.old_gap_end) < self.wzmax:
|
||||
self.put(self.old_gap_end, self.samplenum,
|
||||
self.out_ann, [0, ['0']])
|
||||
self.add_bits_pos(0, self.old_gap_end, self.samplenum)
|
||||
if (self.last_samplenum - self.old_gap_end) > self.womax \
|
||||
and (self.last_samplenum-self.old_gap_end) < self.nogap:
|
||||
# One or more 1 bits
|
||||
one_bits = (int)((self.last_samplenum - self.old_gap_end) / self.womax)
|
||||
for ox in range(0, one_bits):
|
||||
bs = (int)(self.old_gap_end+ox*self.womax)
|
||||
be = (int)(self.old_gap_end+ox*self.womax + self.womax)
|
||||
self.put(bs, be, self.out_ann, [0, ['1']])
|
||||
self.add_bits_pos(1, bs, be)
|
||||
if (self.samplenum - self.last_samplenum) > self.wzmin \
|
||||
and (self.samplenum - self.last_samplenum) < self.wzmax:
|
||||
bs = (int)(self.old_gap_end+one_bits*self.womax)
|
||||
self.put(bs, self.samplenum, self.out_ann, [0, ['0']])
|
||||
self.add_bits_pos(0, bs, self.samplenum)
|
||||
|
||||
self.old_gap_end = self.samplenum
|
||||
|
||||
if self.state == 'SKIP':
|
||||
self.state = 'FFS_SEARCH'
|
||||
|
||||
self.oldsamplenum = self.samplenum
|
||||
self.last_samplenum = self.samplenum
|
||||
self.oldpin = pin
|
||||
@@ -14,7 +14,8 @@
|
||||
## GNU General Public License for more details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License
|
||||
## along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
## along with this program; if not, write to the Free Software
|
||||
## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
##
|
||||
|
||||
'''
|
||||
|
||||
@@ -14,7 +14,8 @@
|
||||
## GNU General Public License for more details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License
|
||||
## along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
## along with this program; if not, write to the Free Software
|
||||
## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
##
|
||||
|
||||
import sigrokdecode as srd
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
##
|
||||
## This file is part of the libsigrokdecode project.
|
||||
##
|
||||
## Copyright (C) 2013 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
## Copyright (C) 2013-2016 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
## Copyright (C) 2016 Chris Dreher <chrisdreher@hotmail.com>
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
@@ -18,40 +19,41 @@
|
||||
## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
##
|
||||
|
||||
# Each status byte has 3 string names, each shorter than the previous
|
||||
status_bytes = {
|
||||
# Channel voice messages
|
||||
0x80: 'note off',
|
||||
0x90: 'note on', # However, velocity = 0 means "note off".
|
||||
0xa0: 'polyphonic key pressure / aftertouch',
|
||||
0xb0: 'control change',
|
||||
0xc0: 'program change',
|
||||
0xd0: 'channel pressure / aftertouch',
|
||||
0xe0: 'pitch bend change',
|
||||
0x80: ['note off', 'note off', 'N off'],
|
||||
0x90: ['note on', 'note on', 'N on'], # However, velocity = 0 means "note off".
|
||||
0xa0: ['polyphonic key pressure / aftertouch', 'key pressure', 'KP' ],
|
||||
0xb0: ['control change', 'ctrl chg', 'CC'],
|
||||
0xc0: ['program change', 'prgm chg', 'PC'],
|
||||
0xd0: ['channel pressure / aftertouch', 'channel pressure', 'CP'],
|
||||
0xe0: ['pitch bend change', 'pitch bend', 'PB'],
|
||||
|
||||
# Channel mode messages
|
||||
# 0xb0: 'select channel mode', # Note: Same as 'control change'.
|
||||
|
||||
# System exclusive messages
|
||||
0xf0: 'system exclusive (SysEx)',
|
||||
0xf0: ['system exclusive', 'SysEx', 'SE'],
|
||||
|
||||
# System common messages
|
||||
0xf1: 'MIDI time code quarter frame',
|
||||
0xf2: 'song position pointer',
|
||||
0xf3: 'song select',
|
||||
0xf4: 'undefined',
|
||||
0xf5: 'undefined',
|
||||
0xf6: 'tune request',
|
||||
0xf7: 'end of system exclusive (EOX)',
|
||||
0xf1: ['MIDI time code quarter frame', 'MIDI time code', 'MIDI time'],
|
||||
0xf2: ['song position pointer', 'song position', 'song pos'],
|
||||
0xf3: ['song select', 'song select', 'song sel'],
|
||||
0xf4: ['undefined 0xf4', 'undef 0xf4', 'undef'],
|
||||
0xf5: ['undefined 0xf5', 'undef 0xf5', 'undef'],
|
||||
0xf6: ['tune request', 'tune request', 'tune req'],
|
||||
0xf7: ['end of system exclusive (EOX)', 'end of SysEx', 'EOX'],
|
||||
|
||||
# System real time messages
|
||||
0xf8: 'timing clock',
|
||||
0xf9: 'undefined',
|
||||
0xfa: 'start',
|
||||
0xfb: 'continue',
|
||||
0xfc: 'stop',
|
||||
0xfd: 'undefined',
|
||||
0xfe: 'active sensing',
|
||||
0xff: 'system reset',
|
||||
0xf8: ['timing clock', 'timing clock', 'clock'],
|
||||
0xf9: ['undefined 0xf9', 'undef 0xf9', 'undef'],
|
||||
0xfa: ['start', 'start', 's'],
|
||||
0xfb: ['continue', 'continue', 'cont'],
|
||||
0xfc: ['stop', 'stop', 'st'],
|
||||
0xfd: ['undefined 0xfd', 'undef 0xfd', 'undef'],
|
||||
0xfe: ['active sensing', 'active sensing', 'sensing'],
|
||||
0xff: ['system reset', 'reset', 'rst'],
|
||||
}
|
||||
|
||||
# Universal system exclusive (SysEx) messages, non-realtime (0x7e)
|
||||
@@ -156,37 +158,37 @@ universal_sysex_realtime = {
|
||||
|
||||
# Note: Not all IDs are used/listed, i.e. there are some "holes".
|
||||
sysex_manufacturer_ids = {
|
||||
# American group
|
||||
(0x01): 'Sequential',
|
||||
(0x02): 'IDP',
|
||||
(0x03): 'Voyetra/Octave-Plateau',
|
||||
(0x04): 'Moog',
|
||||
(0x05): 'Passport Designs',
|
||||
(0x06): 'Lexicon',
|
||||
(0x07): 'Kurzweil',
|
||||
(0x08): 'Fender',
|
||||
(0x09): 'Gulbransen',
|
||||
(0x0a): 'AKG Acoustics',
|
||||
(0x0b): 'Voyce Music',
|
||||
(0x0c): 'Waveframe Corp',
|
||||
(0x0d): 'ADA Signal Processors',
|
||||
(0x0e): 'Garfield Electronics',
|
||||
(0x0f): 'Ensoniq',
|
||||
(0x10): 'Oberheim',
|
||||
(0x11): 'Apple Computer',
|
||||
(0x12): 'Grey Matter Response',
|
||||
(0x13): 'Digidesign',
|
||||
(0x14): 'Palm Tree Instruments',
|
||||
(0x15): 'JLCooper Electronics',
|
||||
(0x16): 'Lowrey',
|
||||
(0x17): 'Adams-Smith',
|
||||
(0x18): 'Emu Systems',
|
||||
(0x19): 'Harmony Systems',
|
||||
(0x1a): 'ART',
|
||||
(0x1b): 'Baldwin',
|
||||
(0x1c): 'Eventide',
|
||||
(0x1d): 'Inventronics',
|
||||
(0x1f): 'Clarity',
|
||||
# American group (range 01-1f, 000001-001f7f)
|
||||
(0x01,): 'Sequential',
|
||||
(0x02,): 'IDP',
|
||||
(0x03,): 'Voyetra/Octave-Plateau',
|
||||
(0x04,): 'Moog',
|
||||
(0x05,): 'Passport Designs',
|
||||
(0x06,): 'Lexicon',
|
||||
(0x07,): 'Kurzweil',
|
||||
(0x08,): 'Fender',
|
||||
(0x09,): 'Gulbransen',
|
||||
(0x0a,): 'AKG Acoustics',
|
||||
(0x0b,): 'Voyce Music',
|
||||
(0x0c,): 'Waveframe Corp',
|
||||
(0x0d,): 'ADA Signal Processors',
|
||||
(0x0e,): 'Garfield Electronics',
|
||||
(0x0f,): 'Ensoniq',
|
||||
(0x10,): 'Oberheim',
|
||||
(0x11,): 'Apple Computer',
|
||||
(0x12,): 'Grey Matter Response',
|
||||
(0x13,): 'Digidesign',
|
||||
(0x14,): 'Palm Tree Instruments',
|
||||
(0x15,): 'JLCooper Electronics',
|
||||
(0x16,): 'Lowrey',
|
||||
(0x17,): 'Adams-Smith',
|
||||
(0x18,): 'Emu Systems',
|
||||
(0x19,): 'Harmony Systems',
|
||||
(0x1a,): 'ART',
|
||||
(0x1b,): 'Baldwin',
|
||||
(0x1c,): 'Eventide',
|
||||
(0x1d,): 'Inventronics',
|
||||
(0x1f,): 'Clarity',
|
||||
|
||||
(0x00, 0x00, 0x01): 'Time Warner Interactive',
|
||||
(0x00, 0x00, 0x07): 'Digital Music Corp.',
|
||||
@@ -306,32 +308,32 @@ sysex_manufacturer_ids = {
|
||||
(0x00, 0x01, 0x02): 'Crystal Semiconductor',
|
||||
(0x00, 0x01, 0x03): 'Rockwell Semiconductor',
|
||||
|
||||
# European group
|
||||
(0x20): 'Passac',
|
||||
(0x21): 'SIEL',
|
||||
(0x22): 'Synthaxe',
|
||||
(0x24): 'Hohner',
|
||||
(0x25): 'Twister',
|
||||
(0x26): 'Solton',
|
||||
(0x27): 'Jellinghaus MS',
|
||||
(0x28): 'Southworth Music Systems',
|
||||
(0x29): 'PPG',
|
||||
(0x2a): 'JEN',
|
||||
(0x2b): 'SSL Limited',
|
||||
(0x2c): 'Audio Veritrieb',
|
||||
(0x2f): 'Elka',
|
||||
# European group (range 20-3f, 002000-003f7f)
|
||||
(0x20,): 'Passac',
|
||||
(0x21,): 'SIEL',
|
||||
(0x22,): 'Synthaxe',
|
||||
(0x24,): 'Hohner',
|
||||
(0x25,): 'Twister',
|
||||
(0x26,): 'Solton',
|
||||
(0x27,): 'Jellinghaus MS',
|
||||
(0x28,): 'Southworth Music Systems',
|
||||
(0x29,): 'PPG',
|
||||
(0x2a,): 'JEN',
|
||||
(0x2b,): 'SSL Limited',
|
||||
(0x2c,): 'Audio Veritrieb',
|
||||
(0x2f,): 'Elka',
|
||||
|
||||
(0x30): 'Dynacord',
|
||||
(0x31): 'Viscount',
|
||||
(0x33): 'Clavia Digital Instruments',
|
||||
(0x34): 'Audio Architecture',
|
||||
(0x35): 'GeneralMusic Corp.',
|
||||
(0x39): 'Soundcraft Electronics',
|
||||
(0x3b): 'Wersi',
|
||||
(0x3c): 'Avab Elektronik Ab',
|
||||
(0x3d): 'Digigram',
|
||||
(0x3e): 'Waldorf Electronics',
|
||||
(0x3f): 'Quasimidi',
|
||||
(0x30,): 'Dynacord',
|
||||
(0x31,): 'Viscount',
|
||||
(0x33,): 'Clavia Digital Instruments',
|
||||
(0x34,): 'Audio Architecture',
|
||||
(0x35,): 'GeneralMusic Corp.',
|
||||
(0x39,): 'Soundcraft Electronics',
|
||||
(0x3b,): 'Wersi',
|
||||
(0x3c,): 'Avab Elektronik Ab',
|
||||
(0x3d,): 'Digigram',
|
||||
(0x3e,): 'Waldorf Electronics',
|
||||
(0x3f,): 'Quasimidi',
|
||||
|
||||
(0x00, 0x20, 0x00): 'Dream',
|
||||
(0x00, 0x20, 0x01): 'Strand Lighting',
|
||||
@@ -378,92 +380,462 @@ sysex_manufacturer_ids = {
|
||||
(0x00, 0x20, 0x2d): 'Blue Chip Music Tech',
|
||||
(0x00, 0x20, 0x2e): 'BEE OH Corp',
|
||||
|
||||
# Japanese group
|
||||
(0x40): 'Kawai',
|
||||
(0x41): 'Roland',
|
||||
(0x42): 'Korg',
|
||||
(0x43): 'Yamaha',
|
||||
(0x44): 'Casio',
|
||||
(0x46): 'Kamiya Studio',
|
||||
(0x47): 'Akai',
|
||||
(0x48): 'Japan Victor',
|
||||
(0x49): 'Mesosha',
|
||||
(0x4a): 'Hoshino Gakki',
|
||||
(0x4b): 'Fujitsu Elect',
|
||||
(0x4c): 'Sony',
|
||||
(0x4d): 'Nisshin Onpa',
|
||||
(0x4e): 'TEAC',
|
||||
(0x50): 'Matsushita Electric',
|
||||
(0x51): 'Fostex',
|
||||
(0x52): 'Zoom',
|
||||
(0x53): 'Midori Electronics',
|
||||
(0x54): 'Matsushita Communication Industrial',
|
||||
(0x55): 'Suzuki Musical Inst. Mfg.',
|
||||
# Japanese group (range 40-5f, 004000-005f7f)
|
||||
(0x40,): 'Kawai',
|
||||
(0x41,): 'Roland',
|
||||
(0x42,): 'Korg',
|
||||
(0x43,): 'Yamaha',
|
||||
(0x44,): 'Casio',
|
||||
(0x46,): 'Kamiya Studio',
|
||||
(0x47,): 'Akai',
|
||||
(0x48,): 'Japan Victor',
|
||||
(0x49,): 'Mesosha',
|
||||
(0x4a,): 'Hoshino Gakki',
|
||||
(0x4b,): 'Fujitsu Elect',
|
||||
(0x4c,): 'Sony',
|
||||
(0x4d,): 'Nisshin Onpa',
|
||||
(0x4e,): 'TEAC',
|
||||
(0x50,): 'Matsushita Electric',
|
||||
(0x51,): 'Fostex',
|
||||
(0x52,): 'Zoom',
|
||||
(0x53,): 'Midori Electronics',
|
||||
(0x54,): 'Matsushita Communication Industrial',
|
||||
(0x55,): 'Suzuki Musical Inst. Mfg.',
|
||||
|
||||
# Other (range 60-7c, 006000-007f7f)
|
||||
|
||||
# Special (7d-7f)
|
||||
(0x7d,): 'Non-Commercial',
|
||||
(0x7e,): 'Universal Non-Realtime',
|
||||
(0x7f,): 'Universal Realtime',
|
||||
}
|
||||
|
||||
control_functions = {
|
||||
0x00: 'bank select',
|
||||
0x01: 'modulation wheel/lever',
|
||||
0x02: 'breath controller',
|
||||
# 0x03: undefined
|
||||
0x04: 'foot controller',
|
||||
0x05: 'portamento time',
|
||||
0x06: 'data entry MSB',
|
||||
0x07: 'channel volume (formerly main volume)',
|
||||
0x08: 'balance',
|
||||
# 0x09: undefined
|
||||
0x0a: 'pan',
|
||||
0x0b: 'expression controller',
|
||||
0x0c: 'effect control 1',
|
||||
0x0d: 'effect control 2',
|
||||
# 0x0e-0x0f: undefined
|
||||
0x10: 'general purpose controller 1',
|
||||
0x11: 'general purpose controller 2',
|
||||
0x12: 'general purpose controller 3',
|
||||
0x13: 'general purpose controller 4',
|
||||
# 0x14-0x1f: undefined
|
||||
# 0x20-0x3f: LSB for values 0x00-0x1f
|
||||
0x40: 'damper pedal (sustain)',
|
||||
0x41: 'portamento on/off',
|
||||
0x42: 'sostenuto',
|
||||
0x43: 'soft pedal',
|
||||
0x44: 'legato footswitch', # vv: 00-3f = normal, 40-7f = legato
|
||||
0x45: 'hold 2',
|
||||
0x46: 'sound controller 1 (default: sound variation)',
|
||||
0x47: 'sound controller 2 (default: timbre / harmonic intensity)',
|
||||
0x48: 'sound controller 3 (default: release time)',
|
||||
0x49: 'sound controller 4 (default: attack time)',
|
||||
0x4a: 'sound controller 5 (default: brightness)',
|
||||
0x4b: 'sound controller 6 (GM2 default: decay time)',
|
||||
0x4c: 'sound controller 7 (GM2 default: vibrato rate)',
|
||||
0x4d: 'sound controller 8 (GM2 default: vibrato depth)',
|
||||
0x4e: 'sound controller 9 (GM2 default: vibrato delay)',
|
||||
0x4f: 'sound controller 10',
|
||||
0x50: 'general purpose controller 5',
|
||||
0x51: 'general purpose controller 6',
|
||||
0x52: 'general purpose controller 7',
|
||||
0x53: 'general purpose controller 8',
|
||||
0x54: 'portamento control',
|
||||
0x00: ['bank select MSB', 'bank MSB', 'bank-M'],
|
||||
0x01: ['modulation wheel/lever MSB', 'modulation MSB', 'mod-M'],
|
||||
0x02: ['breath controller MSB', 'breath MSB', 'breath-M'],
|
||||
# 0x03: undefined MSB
|
||||
0x04: ['foot controller MSB', 'foot MSB', 'foot-M'],
|
||||
0x05: ['portamento time MSB', 'portamento MSB', 'porta-M'],
|
||||
0x06: ['data entry MSB', 'data entry MSB', 'data-M'],
|
||||
0x07: ['channel volume MSB (formerly main volume)', 'channel volume MSB', 'ch vol-M'],
|
||||
0x08: ['balance MSB', 'bal MSB', 'bal-M'],
|
||||
# 0x09: undefined MSB
|
||||
0x0a: ['pan MSB', 'pan MSB', 'pan-M'],
|
||||
0x0b: ['expression controller MSB', 'expression MSB', 'expr-M'],
|
||||
0x0c: ['effect control 1 MSB', 'effect 1 MSB', 'eff-1-M'],
|
||||
0x0d: ['effect control 2 MSB', 'effect 2 MSB', 'eff-2-M'],
|
||||
# 0x0e-0x0f: undefined MSB
|
||||
0x10: ['general purpose controller 1 MSB', 'GP ctrl 1 MSB', 'GPC-1-M'],
|
||||
0x11: ['general purpose controller 2 MSB', 'GP ctrl 2 MSB', 'GPC-2-M'],
|
||||
0x12: ['general purpose controller 3 MSB', 'GP ctrl 3 MSB', 'GPC-3-M'],
|
||||
0x13: ['general purpose controller 4 MSB', 'GP ctrl 4 MSB', 'GPC-4-M'],
|
||||
# 0x14-0x1f: undefined MSB
|
||||
0x20: ['bank select LSB', 'bank LSB', 'bank-L'],
|
||||
0x21: ['modulation wheel/lever LSB', 'modulation LSB', 'mod-L'],
|
||||
0x22: ['breath controller LSB', 'breath LSB', 'breath-L'],
|
||||
# 0x23: undefined LSB
|
||||
0x24: ['foot controller LSB', 'foot LSB', 'foot-L'],
|
||||
0x25: ['portamento time LSB', 'portamento LSB', 'porta-L'],
|
||||
0x26: ['data entry LSB', 'data entry LSB', 'data-L'],
|
||||
0x27: ['channel volume LSB (formerly main volume)', 'channel volume LSB', 'ch vol-L'],
|
||||
0x28: ['balance LSB', 'bal LSB', 'bal-L'],
|
||||
# 0x29: undefined LSB
|
||||
0x2a: ['pan LSB', 'pan LSB', 'pan-L'],
|
||||
0x2b: ['expression controller LSB', 'expression LSB', 'expr-L'],
|
||||
0x2c: ['effect control 1 LSB', 'effect 1 LSB', 'eff-1-L'],
|
||||
0x2d: ['effect control 2 LSB', 'effect 2 LSB', 'eff-2-L'],
|
||||
# 0x2e-0x2f: undefined LSB
|
||||
0x30: ['general purpose controller 1 LSB', 'GP ctrl 1 LSB', 'GPC-1-L'],
|
||||
0x31: ['general purpose controller 2 LSB', 'GP ctrl 2 LSB', 'GPC-2-L'],
|
||||
0x32: ['general purpose controller 3 LSB', 'GP ctrl 3 LSB', 'GPC-3-L'],
|
||||
0x33: ['general purpose controller 4 LSB', 'GP ctrl 4 LSB', 'GPC-4-L'],
|
||||
# 0x34-0x3f: undefined LSB
|
||||
0x40: ['damper pedal (sustain)', 'sustain', 'sust'],
|
||||
0x41: ['portamento on/off', 'porta on/off', 'porta on/off'],
|
||||
0x42: ['sostenuto', 'sostenuto', 'sostenuto'],
|
||||
0x43: ['soft pedal', 'soft pedal', 'soft pedal'],
|
||||
0x44: ['legato footswitch', 'legato switch', 'legato'], # vv: 00-3f = normal, 40-7f = legato
|
||||
0x45: ['hold 2', 'hold 2', 'hold 2'],
|
||||
0x46: ['sound controller 1 (default: sound variation)', 'sound ctrl 1', 'snd ctrl 1'],
|
||||
0x47: ['sound controller 2 (default: timbre / harmonic intensity)', 'sound ctrl 2', 'snd ctrl 2'],
|
||||
0x48: ['sound controller 3 (default: release time)', 'sound ctrl 3', 'snd ctrl 3'],
|
||||
0x49: ['sound controller 4 (default: attack time)', 'sound ctrl 4', 'snd ctrl 4'],
|
||||
0x4a: ['sound controller 5 (default: brightness)', 'sound ctrl 5', 'snd ctrl 5'],
|
||||
0x4b: ['sound controller 6 (GM2 default: decay time)', 'sound ctrl 6', 'snd ctrl 6'],
|
||||
0x4c: ['sound controller 7 (GM2 default: vibrato rate)', 'sound ctrl 7', 'snd ctrl 7'],
|
||||
0x4d: ['sound controller 8 (GM2 default: vibrato depth)', 'sound ctrl 8', 'snd ctrl 8'],
|
||||
0x4e: ['sound controller 9 (GM2 default: vibrato delay)', 'sound ctrl 9', 'snd ctrl 9'],
|
||||
0x4f: ['sound controller 10', 'sound ctrl 10', 'snd ctrl 10'],
|
||||
0x50: ['general purpose controller 5', 'GP controller 5', 'GPC-5'],
|
||||
0x51: ['general purpose controller 6', 'GP controller 6', 'GPC-6'],
|
||||
0x52: ['general purpose controller 7', 'GP controller 7', 'GPC-7'],
|
||||
0x53: ['general purpose controller 8', 'GP controller 8', 'GPC-8'],
|
||||
0x54: ['portamento control', 'portamento ctrl', 'porta ctrl'],
|
||||
# 0x55-0x5a: undefined
|
||||
0x5b: 'effects 1 depth (formerly external effects depth)',
|
||||
0x5c: 'effects 2 depth (formerly tremolo depth)',
|
||||
0x5d: 'effects 3 depth (formerly chorus depth)',
|
||||
0x5e: 'effects 4 depth (formerly celeste/detune depth)',
|
||||
0x5f: 'effects 5 depth (formerly phaser depth)',
|
||||
0x60: 'data increment',
|
||||
0x61: 'data decrement',
|
||||
0x62: 'non-registered parameter number LSB',
|
||||
0x63: 'non-registered parameter number MSB',
|
||||
0x64: 'registered parameter number LSB',
|
||||
0x65: 'registered parameter number MSB',
|
||||
0x5b: ['effects 1 depth (formerly external effects depth)', 'effects 1 depth', 'eff 1 depth'],
|
||||
0x5c: ['effects 2 depth (formerly tremolo depth)', 'effects 2 depth', 'eff 2 depth'],
|
||||
0x5d: ['effects 3 depth (formerly chorus depth)', 'effects 3 depth', 'eff 3 depth'],
|
||||
0x5e: ['effects 4 depth (formerly celeste/detune depth)', 'effects 4 depth', 'eff 4 depth'],
|
||||
0x5f: ['effects 5 depth (formerly phaser depth)', 'effects 5 depth', 'eff 5 depth'],
|
||||
0x60: ['data increment', 'data inc', 'data++'],
|
||||
0x61: ['data decrement', 'data dec', 'data--'],
|
||||
0x62: ['Non-Registered Parameter Number LSB', 'NRPN LSB', 'NRPN-L'],
|
||||
0x63: ['Non-Registered Parameter Number MSB', 'NRPN MSB', 'NRPN-M'],
|
||||
0x64: ['Registered Parameter Number LSB', 'RPN LSB', 'RPN-L'],
|
||||
0x65: ['Registered Parameter Number MSB', 'RPN MSB', 'RPN-M'],
|
||||
# 0x66-0x77: undefined
|
||||
# 0x78-0x7f: reserved for channel mode messages
|
||||
0x78: 'all sound off',
|
||||
0x79: 'reset all controllers',
|
||||
0x7a: 'local control on/off',
|
||||
0x7b: 'all notes off',
|
||||
0x7c: 'omni mode off', # all notes off
|
||||
0x7d: 'omni mode on', # all notes off
|
||||
0x7e: 'poly mode off', # mono mode on, all notes off
|
||||
0x7f: 'poly mode on', # mono mode off, all notes off
|
||||
0x78: ['all sound off', 'all snd off', 'snd off'],
|
||||
0x79: ['reset all controllers', 'reset all ctrls', 'reset ctrls'],
|
||||
0x7a: ['local control', 'local ctrl', 'local ctrl'],
|
||||
0x7b: ['all notes off', 'notes off', 'notes off'],
|
||||
0x7c: ['omni mode off', 'omni off', 'omni off'], # all notes off
|
||||
0x7d: ['omni mode on', 'omni on', 'omni on'], # all notes off
|
||||
0x7e: ['mono mode on', 'mono on', 'mono'], # mono mode on, all notes off
|
||||
0x7f: ['poly mode on', 'poly on', 'poly'], # mono mode off, all notes off
|
||||
}
|
||||
|
||||
gm_instruments = {
|
||||
1: 'Acoustic Grand Piano',
|
||||
2: 'Bright Acoustic Piano',
|
||||
3: 'Electric Grand Piano',
|
||||
4: 'Honky-tonk Piano',
|
||||
5: 'Electric Piano 1',
|
||||
6: 'Electric Piano 2',
|
||||
7: 'Harpsichord',
|
||||
8: 'Clavi',
|
||||
9: 'Celesta',
|
||||
10: 'Glockenspiel',
|
||||
11: 'Music Box',
|
||||
12: 'Vibraphone',
|
||||
13: 'Marimba',
|
||||
14: 'Xylophone',
|
||||
15: 'Tubular Bells',
|
||||
16: 'Dulcimer',
|
||||
17: 'Drawbar Organ',
|
||||
18: 'Percussive Organ',
|
||||
19: 'Rock Organ',
|
||||
20: 'Church Organ',
|
||||
21: 'Reed Organ',
|
||||
22: 'Accordion',
|
||||
23: 'Harmonica',
|
||||
24: 'Tango Accordion',
|
||||
25: 'Acoustic Guitar (nylon)',
|
||||
26: 'Acoustic Guitar (steel)',
|
||||
27: 'Electric Guitar (jazz)',
|
||||
28: 'Electric Guitar (clean)',
|
||||
29: 'Electric Guitar (muted)',
|
||||
30: 'Overdriven Guitar',
|
||||
31: 'Distortion Guitar',
|
||||
32: 'Guitar harmonics',
|
||||
33: 'Acoustic Bass',
|
||||
34: 'Electric Bass (finger)',
|
||||
35: 'Electric Bass (pick)',
|
||||
36: 'Fretless Bass',
|
||||
37: 'Slap Bass 1',
|
||||
38: 'Slap Bass 2',
|
||||
39: 'Synth Bass 1',
|
||||
40: 'Synth Bass 2',
|
||||
41: 'Violin',
|
||||
42: 'Viola',
|
||||
43: 'Cello',
|
||||
44: 'Contrabass',
|
||||
45: 'Tremolo Strings',
|
||||
46: 'Pizzicato Strings',
|
||||
47: 'Orchestral Harp',
|
||||
48: 'Timpani',
|
||||
49: 'String Ensemble 1',
|
||||
50: 'String Ensemble 2',
|
||||
51: 'SynthStrings 1',
|
||||
52: 'SynthStrings 2',
|
||||
53: 'Choir Aahs',
|
||||
54: 'Voice Oohs',
|
||||
55: 'Synth Voice',
|
||||
56: 'Orchestra Hit',
|
||||
57: 'Trumpet',
|
||||
58: 'Trombone',
|
||||
59: 'Tuba',
|
||||
60: 'Muted Trumpet',
|
||||
61: 'French Horn',
|
||||
62: 'Brass Section',
|
||||
63: 'SynthBrass 1',
|
||||
64: 'SynthBrass 2',
|
||||
65: 'Soprano Sax',
|
||||
66: 'Alto Sax',
|
||||
67: 'Tenor Sax',
|
||||
68: 'Baritone Sax',
|
||||
69: 'Oboe',
|
||||
70: 'English Horn',
|
||||
71: 'Bassoon',
|
||||
72: 'Clarinet',
|
||||
73: 'Piccolo',
|
||||
74: 'Flute',
|
||||
75: 'Recorder',
|
||||
76: 'Pan Flute',
|
||||
77: 'Blown Bottle',
|
||||
78: 'Shakuhachi',
|
||||
79: 'Whistle',
|
||||
80: 'Ocarina',
|
||||
81: 'Lead 1 (square)',
|
||||
82: 'Lead 2 (sawtooth)',
|
||||
83: 'Lead 3 (calliope)',
|
||||
84: 'Lead 4 (chiff)',
|
||||
85: 'Lead 5 (charang)',
|
||||
86: 'Lead 6 (voice)',
|
||||
87: 'Lead 7 (fifths)',
|
||||
88: 'Lead 8 (bass + lead)',
|
||||
89: 'Pad 1 (new age)',
|
||||
90: 'Pad 2 (warm)',
|
||||
91: 'Pad 3 (polysynth)',
|
||||
92: 'Pad 4 (choir)',
|
||||
93: 'Pad 5 (bowed)',
|
||||
94: 'Pad 6 (metallic)',
|
||||
95: 'Pad 7 (halo)',
|
||||
96: 'Pad 8 (sweep)',
|
||||
97: 'FX 1 (rain)',
|
||||
98: 'FX 2 (soundtrack)',
|
||||
99: 'FX 3 (crystal)',
|
||||
100: 'FX 4 (atmosphere)',
|
||||
101: 'FX 5 (brightness)',
|
||||
102: 'FX 6 (goblins)',
|
||||
103: 'FX 7 (echoes)',
|
||||
104: 'FX 8 (sci-fi)',
|
||||
105: 'Sitar',
|
||||
106: 'Banjo',
|
||||
107: 'Shamisen',
|
||||
108: 'Koto',
|
||||
109: 'Kalimba',
|
||||
110: 'Bag pipe',
|
||||
111: 'Fiddle',
|
||||
112: 'Shanai',
|
||||
113: 'Tinkle Bell',
|
||||
114: 'Agogo',
|
||||
115: 'Steel Drums',
|
||||
116: 'Woodblock',
|
||||
117: 'Taiko Drum',
|
||||
118: 'Melodic Tom',
|
||||
119: 'Synth Drum',
|
||||
120: 'Reverse Cymbal',
|
||||
121: 'Guitar Fret Noise',
|
||||
122: 'Breath Noise',
|
||||
123: 'Seashore',
|
||||
124: 'Bird Tweet',
|
||||
125: 'Telephone Ring',
|
||||
126: 'Helicopter',
|
||||
127: 'Applause',
|
||||
128: 'Gunshot',
|
||||
}
|
||||
|
||||
drum_kit = {
|
||||
1: 'GM Standard Kit',
|
||||
9: 'GS Room Kit',
|
||||
17: 'GS Power Kit',
|
||||
25: 'GS Power Kit',
|
||||
26: 'GS TR-808 Kit',
|
||||
33: 'GS Jazz Kit',
|
||||
41: 'GS Brush Kit',
|
||||
49: 'GS Orchestra Kit',
|
||||
57: 'GS Sound FX Kit',
|
||||
128: 'GS CM-64/CM-32 Kit',
|
||||
}
|
||||
|
||||
# Each quarter frame type has 2 string names, each shorter than the previous
|
||||
quarter_frame_type = {
|
||||
0: ['frame count LS nibble', 'frame LSN'],
|
||||
1: ['frame count MS nibble', 'frame MSN'],
|
||||
2: ['seconds LS nibble', 'sec LSN'],
|
||||
3: ['seconds MS nibble', 'sec MSN'],
|
||||
4: ['minutes LS nibble', 'min LSN'],
|
||||
5: ['minutes MS nibble', 'min MSN'],
|
||||
6: ['hours LS nibble', 'hrs LSN'],
|
||||
7: ['hours MS nibble and SMPTE type', 'hrs MSN'],
|
||||
}
|
||||
|
||||
smpte_type = {
|
||||
0: '24 fps',
|
||||
1: '25 fps',
|
||||
2: '30 fps (drop-frame)',
|
||||
3: '30 fps (non-drop)',
|
||||
}
|
||||
|
||||
chromatic_notes = {
|
||||
0: 'C-1',
|
||||
1: 'C#-1',
|
||||
2: 'D-1',
|
||||
3: 'D#-1',
|
||||
4: 'E-1',
|
||||
5: 'F-1',
|
||||
6: 'F#-1',
|
||||
7: 'G-1',
|
||||
8: 'G#-1',
|
||||
9: 'A-1',
|
||||
10: 'A#-1',
|
||||
11: 'B-1',
|
||||
12: 'C0',
|
||||
13: 'C#0',
|
||||
14: 'D0',
|
||||
15: 'D#0',
|
||||
16: 'E0',
|
||||
17: 'F0',
|
||||
18: 'F#0',
|
||||
19: 'G0',
|
||||
20: 'G#0',
|
||||
21: 'A0',
|
||||
22: 'A#0',
|
||||
23: 'B0',
|
||||
24: 'C1',
|
||||
25: 'C#1',
|
||||
26: 'D1',
|
||||
27: 'D#1',
|
||||
28: 'E1',
|
||||
29: 'F1',
|
||||
30: 'F#1',
|
||||
31: 'G1',
|
||||
32: 'G#1',
|
||||
33: 'A1',
|
||||
34: 'A#1',
|
||||
35: 'B1',
|
||||
36: 'C2',
|
||||
37: 'C#2',
|
||||
38: 'D2',
|
||||
39: 'D#2',
|
||||
40: 'E2',
|
||||
41: 'F2',
|
||||
42: 'F#2',
|
||||
43: 'G2',
|
||||
44: 'G#2',
|
||||
45: 'A2',
|
||||
46: 'A#2',
|
||||
47: 'B2',
|
||||
48: 'C3',
|
||||
49: 'C#3',
|
||||
50: 'D3',
|
||||
51: 'D#3',
|
||||
52: 'E3',
|
||||
53: 'F3',
|
||||
54: 'F#3',
|
||||
55: 'G3',
|
||||
56: 'G#3',
|
||||
57: 'A3',
|
||||
58: 'A#3',
|
||||
59: 'B3',
|
||||
60: 'C4',
|
||||
61: 'C#4',
|
||||
62: 'D4',
|
||||
63: 'D#4',
|
||||
64: 'E4',
|
||||
65: 'F4',
|
||||
66: 'F#4',
|
||||
67: 'G4',
|
||||
68: 'G#4',
|
||||
69: 'A4',
|
||||
70: 'A#4',
|
||||
71: 'B4',
|
||||
72: 'C5',
|
||||
73: 'C#5',
|
||||
74: 'D5',
|
||||
75: 'D#5',
|
||||
76: 'E5',
|
||||
77: 'F5',
|
||||
78: 'F#5',
|
||||
79: 'G5',
|
||||
80: 'G#5',
|
||||
81: 'A5',
|
||||
82: 'A#5',
|
||||
83: 'B5',
|
||||
84: 'C6',
|
||||
85: 'C#6',
|
||||
86: 'D6',
|
||||
87: 'D#6',
|
||||
88: 'E6',
|
||||
89: 'F6',
|
||||
90: 'F#6',
|
||||
91: 'G6',
|
||||
92: 'G#6',
|
||||
93: 'A6',
|
||||
94: 'A#6',
|
||||
95: 'B6',
|
||||
96: 'C7',
|
||||
97: 'C#7',
|
||||
98: 'D7',
|
||||
99: 'D#7',
|
||||
100: 'E7',
|
||||
101: 'F7',
|
||||
102: 'F#7',
|
||||
103: 'G7',
|
||||
104: 'G#7',
|
||||
105: 'A7',
|
||||
106: 'A#7',
|
||||
107: 'B7',
|
||||
108: 'C8',
|
||||
109: 'C#8',
|
||||
110: 'D8',
|
||||
111: 'D#8',
|
||||
112: 'E8',
|
||||
113: 'F8',
|
||||
114: 'F#8',
|
||||
115: 'G8',
|
||||
116: 'G#8',
|
||||
117: 'A8',
|
||||
118: 'A#8',
|
||||
119: 'B8',
|
||||
120: 'C9',
|
||||
121: 'C#9',
|
||||
122: 'D9',
|
||||
123: 'D#9',
|
||||
124: 'E9',
|
||||
125: 'F9',
|
||||
126: 'F#9',
|
||||
127: 'G9',
|
||||
}
|
||||
|
||||
percussion_notes = {
|
||||
35: 'Acoustic Bass Drum',
|
||||
36: 'Bass Drum 1',
|
||||
37: 'Side Stick',
|
||||
38: 'Acoustic Snare',
|
||||
39: 'Hand Clap',
|
||||
40: 'Electric Snare',
|
||||
41: 'Low Floor Tom',
|
||||
42: 'Closed Hi Hat',
|
||||
43: 'High Floor Tom',
|
||||
44: 'Pedal Hi-Hat',
|
||||
45: 'Low Tom',
|
||||
46: 'Open Hi-Hat',
|
||||
47: 'Low-Mid Tom',
|
||||
48: 'Hi Mid Tom',
|
||||
49: 'Crash Cymbal 1',
|
||||
50: 'High Tom',
|
||||
51: 'Ride Cymbal 1',
|
||||
52: 'Chinese Cymbal',
|
||||
53: 'Ride Bell',
|
||||
54: 'Tambourine',
|
||||
55: 'Splash Cymbal',
|
||||
56: 'Cowbell',
|
||||
57: 'Crash Cymbal 2',
|
||||
58: 'Vibraslap',
|
||||
59: 'Ride Cymbal 2',
|
||||
60: 'Hi Bongo',
|
||||
61: 'Low Bongo',
|
||||
62: 'Mute Hi Conga',
|
||||
63: 'Open Hi Conga',
|
||||
64: 'Low Conga',
|
||||
65: 'High Timbale',
|
||||
66: 'Low Timbale',
|
||||
67: 'High Agogo',
|
||||
68: 'Low Agogo',
|
||||
69: 'Cabasa',
|
||||
70: 'Maracas',
|
||||
71: 'Short Whistle',
|
||||
72: 'Long Whistle',
|
||||
73: 'Short Guiro',
|
||||
74: 'Long Guiro',
|
||||
75: 'Claves',
|
||||
76: 'Hi Wood Block',
|
||||
77: 'Low Wood Block',
|
||||
78: 'Mute Cuica',
|
||||
79: 'Open Cuica',
|
||||
80: 'Mute Triangle',
|
||||
81: 'Open Triangle',
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
##
|
||||
## This file is part of the libsigrokdecode project.
|
||||
##
|
||||
## Copyright (C) 2013 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
## Copyright (C) 2013-2016 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
## Copyright (C) 2016 Chris Dreher <chrisdreher@hotmail.com>
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
@@ -35,11 +36,19 @@ class Decoder(srd.Decoder):
|
||||
outputs = ['midi']
|
||||
annotations = (
|
||||
('text-verbose', 'Human-readable text (verbose)'),
|
||||
('text-sysreal-verbose', 'Human-readable SysReal text (verbose)'),
|
||||
('text-error', 'Human-readable Error text'),
|
||||
)
|
||||
annotation_rows = (
|
||||
('normal', 'Normal', (0, 2)),
|
||||
('sys-real', 'SysReal', (1,)),
|
||||
)
|
||||
|
||||
def __init__(self):
|
||||
self.cmd = []
|
||||
self.state = 'IDLE'
|
||||
self.status_byte = 0
|
||||
self.explicit_status_byte = False
|
||||
self.cmd = []
|
||||
self.ss = None
|
||||
self.es = None
|
||||
self.ss_block = None
|
||||
@@ -51,130 +60,524 @@ class Decoder(srd.Decoder):
|
||||
def putx(self, data):
|
||||
self.put(self.ss_block, self.es_block, self.out_ann, data)
|
||||
|
||||
def handle_channel_msg_0x80(self):
|
||||
def get_note_name(self, channel, note):
|
||||
if channel != 10:
|
||||
return chromatic_notes[note]
|
||||
else:
|
||||
return 'assuming ' + percussion_notes.get(note, 'undefined')
|
||||
|
||||
def check_for_garbage_flush(self, is_flushed):
|
||||
if is_flushed:
|
||||
if self.explicit_status_byte:
|
||||
self.cmd.insert(0, self.status_byte)
|
||||
self.handle_garbage_msg(None)
|
||||
|
||||
def soft_clear_status_byte(self):
|
||||
self.explicit_status_byte = False
|
||||
|
||||
def hard_clear_status_byte(self):
|
||||
self.status_byte = 0
|
||||
self.explicit_status_byte = False
|
||||
|
||||
def set_status_byte(self, newbyte):
|
||||
self.status_byte = newbyte
|
||||
self.explicit_status_byte = True
|
||||
|
||||
def handle_channel_msg_0x80(self, is_flushed):
|
||||
# Note off: 8n kk vv
|
||||
# n = channel, kk = note, vv = velocity
|
||||
c = self.cmd
|
||||
if len(c) < 3:
|
||||
if len(c) < 2:
|
||||
self.check_for_garbage_flush(is_flushed)
|
||||
return
|
||||
self.es_block = self.es
|
||||
msg, chan, note, velocity = c[0] & 0xf0, (c[0] & 0x0f) + 1, c[1], c[2]
|
||||
self.putx([0, ['Channel %d: %s (note = %d, velocity = %d)' % \
|
||||
(chan, status_bytes[msg], note, velocity)]])
|
||||
msg, chan = self.status_byte & 0xf0, (self.status_byte & 0x0f) + 1
|
||||
note, velocity = c[0], c[1]
|
||||
note_name = self.get_note_name(chan, note)
|
||||
self.putx([0, ['Channel %d: %s (note = %d \'%s\', velocity = %d)' % \
|
||||
(chan, status_bytes[msg][0], note, note_name, velocity),
|
||||
'ch %d: %s %d, velocity = %d' % \
|
||||
(chan, status_bytes[msg][1], note, velocity),
|
||||
'%d: %s %d, vel %d' % \
|
||||
(chan, status_bytes[msg][2], note, velocity)]])
|
||||
self.cmd, self.state = [], 'IDLE'
|
||||
self.soft_clear_status_byte()
|
||||
|
||||
def handle_channel_msg_0x90(self):
|
||||
def handle_channel_msg_0x90(self, is_flushed):
|
||||
# Note on: 9n kk vv
|
||||
# n = channel, kk = note, vv = velocity
|
||||
# If velocity == 0 that actually means 'note off', though.
|
||||
c = self.cmd
|
||||
if len(c) < 3:
|
||||
if len(c) < 2:
|
||||
self.check_for_garbage_flush(is_flushed)
|
||||
return
|
||||
self.es_block = self.es
|
||||
msg, chan, note, velocity = c[0] & 0xf0, (c[0] & 0x0f) + 1, c[1], c[2]
|
||||
s = 'note off' if (velocity == 0) else status_bytes[msg]
|
||||
self.putx([0, ['Channel %d: %s (note = %d, velocity = %d)' % \
|
||||
(chan, s, note, velocity)]])
|
||||
msg, chan = self.status_byte & 0xf0, (self.status_byte & 0x0f) + 1
|
||||
note, velocity = c[0], c[1]
|
||||
s = status_bytes[0x80] if (velocity == 0) else status_bytes[msg]
|
||||
note_name = self.get_note_name(chan, note)
|
||||
self.putx([0, ['Channel %d: %s (note = %d \'%s\', velocity = %d)' % \
|
||||
(chan, s[0], note, note_name, velocity),
|
||||
'ch %d: %s %d, velocity = %d' % \
|
||||
(chan, s[1], note, velocity),
|
||||
'%d: %s %d, vel %d' % \
|
||||
(chan, s[2], note, velocity)]])
|
||||
self.cmd, self.state = [], 'IDLE'
|
||||
self.soft_clear_status_byte()
|
||||
|
||||
def handle_channel_msg_0xa0(self):
|
||||
def handle_channel_msg_0xa0(self, is_flushed):
|
||||
# Polyphonic key pressure / aftertouch: An kk vv
|
||||
# n = channel, kk = polyphonic key pressure, vv = pressure value
|
||||
pass # TODO
|
||||
c = self.cmd
|
||||
if len(c) < 2:
|
||||
self.check_for_garbage_flush(is_flushed)
|
||||
return
|
||||
self.es_block = self.es
|
||||
msg, chan = self.status_byte & 0xf0, (self.status_byte & 0x0f) + 1
|
||||
note, pressure = c[0], c[1]
|
||||
note_name = self.get_note_name(chan, note)
|
||||
self.putx([0, ['Channel %d: %s of %d for note = %d \'%s\'' % \
|
||||
(chan, status_bytes[msg][0], pressure, note, note_name),
|
||||
'ch %d: %s %d for note %d' % \
|
||||
(chan, status_bytes[msg][1], pressure, note),
|
||||
'%d: %s %d, N %d' % \
|
||||
(chan, status_bytes[msg][2], pressure, note)]])
|
||||
self.cmd, self.state = [], 'IDLE'
|
||||
self.soft_clear_status_byte()
|
||||
|
||||
def handle_controller_0x44(self):
|
||||
# Legato footswitch: Bn 44 vv
|
||||
# n = channel, vv = value (<= 0x3f: normal, > 0x3f: legato)
|
||||
chan, vv = (self.cmd[0] & 0x0f) + 1, self.cmd[2]
|
||||
t = 'normal' if vv <= 0x3f else 'legato'
|
||||
self.putx([0, ['Channel %d: control function \'%s\' = %s' % \
|
||||
(chan, control_functions[0x44], t)]])
|
||||
c = self.cmd
|
||||
msg, chan = self.status_byte & 0xf0, (self.status_byte & 0x0f) + 1
|
||||
vv = c[1]
|
||||
t = ('normal', 'no') if vv <= 0x3f else ('legato', 'yes')
|
||||
self.putx([0, ['Channel %d: %s \'%s\' = %s' % \
|
||||
(chan, status_bytes[msg][0],
|
||||
control_functions[0x44][0], t[0]),
|
||||
'ch %d: %s \'%s\' = %s' % \
|
||||
(chan, status_bytes[msg][1],
|
||||
control_functions[0x44][1], t[0]),
|
||||
'%d: %s \'%s\' = %s' % \
|
||||
(chan, status_bytes[msg][2],
|
||||
control_functions[0x44][2], t[1])]])
|
||||
|
||||
def handle_controller_0x54(self):
|
||||
# Portamento control (PTC): Bn 54 kk
|
||||
# n = channel, kk = source note for pitch reference
|
||||
chan, kk = (self.cmd[0] & 0x0f) + 1, self.cmd[2]
|
||||
self.putx([0, ['Channel %d: control function \'%s\' (source note ' \
|
||||
'= %d)' % (chan, control_functions[0x54], kk)]])
|
||||
c = self.cmd
|
||||
msg, chan = self.status_byte & 0xf0, (self.status_byte & 0x0f) + 1
|
||||
kk = c[1]
|
||||
kk_name = self.get_note_name(chan, kk)
|
||||
self.putx([0, ['Channel %d: %s \'%s\' (source note = %d / %s)' % \
|
||||
(chan, status_bytes[msg][0],
|
||||
control_functions[0x54][0], kk, kk_name),
|
||||
'ch %d: %s \'%s\' (source note = %d)' % \
|
||||
(chan, status_bytes[msg][1],
|
||||
control_functions[0x54][1], kk),
|
||||
'%d: %s \'%s\' (src N %d)' % \
|
||||
(chan, status_bytes[msg][2],
|
||||
control_functions[0x54][2], kk)]])
|
||||
|
||||
def handle_controller_generic(self):
|
||||
c = self.cmd
|
||||
chan, fn, param = (c[0] & 0x0f) + 1, c[1], c[2]
|
||||
ctrl_fn = control_functions.get(fn, 'undefined')
|
||||
self.putx([0, ['Channel %d: control change to function \'%s\' ' \
|
||||
'(param = 0x%02x)' % (chan, ctrl_fn, param)]])
|
||||
msg, chan = self.status_byte & 0xf0, (self.status_byte & 0x0f) + 1
|
||||
fn, param = c[0], c[1]
|
||||
default_name = 'undefined'
|
||||
ctrl_fn = control_functions.get(fn, default_name)
|
||||
if ctrl_fn == default_name:
|
||||
ctrl_fn = ('undefined 0x%02x' % fn, 'undef 0x%02x' % fn, '0x%02x' % fn)
|
||||
self.putx([0, ['Channel %d: %s \'%s\' (param = 0x%02x)' % \
|
||||
(chan, status_bytes[msg][0], ctrl_fn[0], param),
|
||||
'ch %d: %s \'%s\' (param = 0x%02x)' % \
|
||||
(chan, status_bytes[msg][1], ctrl_fn[1], param),
|
||||
'%d: %s \'%s\' is 0x%02x' % \
|
||||
(chan, status_bytes[msg][2], ctrl_fn[2], param)]])
|
||||
|
||||
def handle_channel_msg_0xb0(self):
|
||||
def handle_channel_mode(self):
|
||||
# Channel Mode: Bn mm vv
|
||||
# n = channel, mm = mode number (120 - 127), vv = value
|
||||
c = self.cmd
|
||||
msg, chan = self.status_byte & 0xf0, (self.status_byte & 0x0f) + 1
|
||||
mm, vv = c[0], c[1]
|
||||
mode_fn = control_functions.get(mm, ('undefined', 'undef', 'undef'))
|
||||
# Decode the value based on the mode number.
|
||||
vv_string = ('', '')
|
||||
if mm == 122: # mode = local control?
|
||||
if vv == 0:
|
||||
vv_string = ('off', 'off')
|
||||
elif vv == 127: # mode = poly mode on?
|
||||
vv_string = ('on', 'on')
|
||||
else:
|
||||
vv_string = ('(non-standard param value of 0x%02x)' % vv,
|
||||
'0x%02x' % vv)
|
||||
elif mm == 126: # mode = mono mode on?
|
||||
if vv != 0:
|
||||
vv_string = ('(%d channels)' % vv, '(%d ch)' % vv)
|
||||
else:
|
||||
vv_string = ('(channels \'basic\' through 16)',
|
||||
'(ch \'basic\' thru 16)')
|
||||
elif vv != 0: # All other channel mode messages expect vv == 0.
|
||||
vv_string = ('(non-standard param value of 0x%02x)' % vv,
|
||||
'0x%02x' % vv)
|
||||
self.putx([0, ['Channel %d: %s \'%s\' %s' % \
|
||||
(chan, status_bytes[msg][0], mode_fn[0], vv_string[0]),
|
||||
'ch %d: %s \'%s\' %s' % \
|
||||
(chan, status_bytes[msg][1], mode_fn[1], vv_string[1]),
|
||||
'%d: %s \'%s\' %s' % \
|
||||
(chan, status_bytes[msg][2], mode_fn[2], vv_string[1])]])
|
||||
self.cmd, self.state = [], 'IDLE'
|
||||
self.soft_clear_status_byte()
|
||||
|
||||
def handle_channel_msg_0xb0(self, is_flushed):
|
||||
# Control change (or channel mode messages): Bn cc vv
|
||||
# n = channel, cc = control number (0 - 119), vv = control value
|
||||
c = self.cmd
|
||||
if (len(c) >= 2) and (c[1] in range(0x78, 0x7f + 1)):
|
||||
# This is not a control change, but rather a channel mode message.
|
||||
# TODO: Handle channel mode messages.
|
||||
return
|
||||
if len(c) < 3:
|
||||
if len(c) < 2:
|
||||
self.check_for_garbage_flush(is_flushed)
|
||||
return
|
||||
self.es_block = self.es
|
||||
handle_ctrl = getattr(self, 'handle_controller_0x%02x' % c[1],
|
||||
if c[0] in range(0x78, 0x7f + 1):
|
||||
self.handle_channel_mode()
|
||||
return
|
||||
handle_ctrl = getattr(self, 'handle_controller_0x%02x' % c[0],
|
||||
self.handle_controller_generic)
|
||||
handle_ctrl()
|
||||
self.cmd, self.state = [], 'IDLE'
|
||||
self.soft_clear_status_byte()
|
||||
|
||||
def handle_channel_msg_0xc0(self):
|
||||
def handle_channel_msg_0xc0(self, is_flushed):
|
||||
# Program change: Cn pp
|
||||
# n = channel, pp = program number (0 - 127)
|
||||
pass # TODO
|
||||
|
||||
def handle_channel_msg_0xd0(self):
|
||||
# Channel pressure / aftertouch: Dn vv
|
||||
# n = channel, vv = pressure value
|
||||
pass # TODO
|
||||
|
||||
def handle_channel_msg_0xe0(self):
|
||||
# Pitch bend change: En ll mm
|
||||
# n = channel, ll = pitch bend change LSB, mm = pitch bend change MSB
|
||||
pass # TODO
|
||||
|
||||
def handle_channel_msg_generic(self):
|
||||
msg_type = self.cmd[0] & 0xf0
|
||||
self.putx([0, ['Unknown channel message type: 0x%02x' % msg_type]])
|
||||
# TODO: Handle properly.
|
||||
|
||||
def handle_channel_msg(self, newbyte):
|
||||
self.cmd.append(newbyte)
|
||||
msg_type = self.cmd[0] & 0xf0
|
||||
handle_msg = getattr(self, 'handle_channel_msg_0x%02x' % msg_type,
|
||||
self.handle_channel_msg_generic)
|
||||
handle_msg()
|
||||
|
||||
def handle_sysex_msg(self, newbyte):
|
||||
# SysEx message: 1 status byte, x data bytes, EOX byte
|
||||
self.cmd.append(newbyte)
|
||||
if newbyte != 0xf7: # EOX
|
||||
c = self.cmd
|
||||
if len(c) < 1:
|
||||
self.check_for_garbage_flush(is_flushed)
|
||||
return
|
||||
self.es_block = self.es
|
||||
# TODO: Get message ID, vendor ID, message contents, etc.
|
||||
self.putx([0, ['SysEx message']])
|
||||
msg, chan = self.status_byte & 0xf0, (self.status_byte & 0x0f) + 1
|
||||
pp = self.cmd[0] + 1
|
||||
change_type = 'instrument'
|
||||
name = ''
|
||||
if chan != 10: # channel != percussion
|
||||
name = gm_instruments.get(pp, 'undefined')
|
||||
else:
|
||||
change_type = 'drum kit'
|
||||
name = drum_kit.get(pp, 'undefined')
|
||||
self.putx([0, ['Channel %d: %s to %s %d (assuming %s)' % \
|
||||
(chan, status_bytes[msg][0], change_type, pp, name),
|
||||
'ch %d: %s to %s %d' % \
|
||||
(chan, status_bytes[msg][1], change_type, pp),
|
||||
'%d: %s %d' % \
|
||||
(chan, status_bytes[msg][2], pp)]])
|
||||
self.cmd, self.state = [], 'IDLE'
|
||||
self.soft_clear_status_byte()
|
||||
|
||||
def handle_channel_msg_0xd0(self, is_flushed):
|
||||
# Channel pressure / aftertouch: Dn vv
|
||||
# n = channel, vv = pressure value
|
||||
c = self.cmd
|
||||
if len(c) < 1:
|
||||
self.check_for_garbage_flush(is_flushed)
|
||||
return
|
||||
self.es_block = self.es
|
||||
msg, chan = self.status_byte & 0xf0, (self.status_byte & 0x0f) + 1
|
||||
vv = self.cmd[0]
|
||||
self.putx([0, ['Channel %d: %s %d' % (chan, status_bytes[msg][0], vv),
|
||||
'ch %d: %s %d' % (chan, status_bytes[msg][1], vv),
|
||||
'%d: %s %d' % (chan, status_bytes[msg][2], vv)]])
|
||||
self.cmd, self.state = [], 'IDLE'
|
||||
self.soft_clear_status_byte()
|
||||
|
||||
def handle_channel_msg_0xe0(self, is_flushed):
|
||||
# Pitch bend change: En ll mm
|
||||
# n = channel, ll = pitch bend change LSB, mm = pitch bend change MSB
|
||||
c = self.cmd
|
||||
if len(c) < 2:
|
||||
self.check_for_garbage_flush(is_flushed)
|
||||
return
|
||||
self.es_block = self.es
|
||||
msg, chan = self.status_byte & 0xf0, (self.status_byte & 0x0f) + 1
|
||||
ll, mm = self.cmd[0], self.cmd[1]
|
||||
decimal = (mm << 7) + ll
|
||||
self.putx([0, ['Channel %d: %s 0x%02x 0x%02x (%d)' % \
|
||||
(chan, status_bytes[msg][0], ll, mm, decimal),
|
||||
'ch %d: %s 0x%02x 0x%02x (%d)' % \
|
||||
(chan, status_bytes[msg][1], ll, mm, decimal),
|
||||
'%d: %s (%d)' % \
|
||||
(chan, status_bytes[msg][2], decimal)]])
|
||||
self.cmd, self.state = [], 'IDLE'
|
||||
self.soft_clear_status_byte()
|
||||
|
||||
def handle_channel_msg_generic(self, is_flushed):
|
||||
# TODO: It should not be possible to hit this code.
|
||||
# It currently can not be unit tested.
|
||||
msg_type = self.status_byte & 0xf0
|
||||
self.es_block = self.es
|
||||
self.putx([2, ['Unknown channel message type: 0x%02x' % msg_type]])
|
||||
self.cmd, self.state = [], 'IDLE'
|
||||
self.soft_clear_status_byte()
|
||||
|
||||
def handle_channel_msg(self, newbyte):
|
||||
if newbyte is not None:
|
||||
if newbyte >= 0x80:
|
||||
self.set_status_byte(newbyte)
|
||||
else:
|
||||
self.cmd.append(newbyte)
|
||||
msg_type = self.status_byte & 0xf0
|
||||
handle_msg = getattr(self, 'handle_channel_msg_0x%02x' % msg_type,
|
||||
self.handle_channel_msg_generic)
|
||||
handle_msg(newbyte is None)
|
||||
|
||||
def handle_sysex_msg(self, newbyte):
|
||||
# SysEx message: 1 status byte, 1-3 manuf. bytes, x data bytes, EOX byte
|
||||
#
|
||||
# SysEx messages are variable length, can be terminated by EOX or
|
||||
# by any non-SysReal status byte, and it clears self.status_byte.
|
||||
#
|
||||
# Note: All System message codes don't utilize self.status_byte.
|
||||
self.hard_clear_status_byte()
|
||||
if newbyte != 0xf7 and newbyte is not None: # EOX
|
||||
self.cmd.append(newbyte)
|
||||
return
|
||||
self.es_block = self.es
|
||||
# Note: Unlike other methods, this code pops bytes out of self.cmd
|
||||
# to isolate the data.
|
||||
msg = self.cmd.pop(0)
|
||||
if len(self.cmd) < 1:
|
||||
self.putx([2, ['%s: truncated manufacturer code (<1 bytes)' % \
|
||||
status_bytes[msg][0],
|
||||
'%s: truncated manufacturer (<1 bytes)' % \
|
||||
status_bytes[msg][1],
|
||||
'%s: trunc. manu.' % status_bytes[msg][2]]])
|
||||
self.cmd, self.state = [], 'IDLE'
|
||||
return
|
||||
# Extract the manufacturer name (or SysEx realtime or non-realtime).
|
||||
m1 = self.cmd.pop(0)
|
||||
manu = (m1,)
|
||||
if m1 == 0x00: # If byte == 0, then 2 more manufacturer bytes follow.
|
||||
if len(self.cmd) < 2:
|
||||
self.putx([2, ['%s: truncated manufacturer code (<3 bytes)' % \
|
||||
status_bytes[msg][0],
|
||||
'%s: truncated manufacturer (<3 bytes)' % \
|
||||
status_bytes[msg][1],
|
||||
'%s: trunc. manu.' % status_bytes[msg][2]]])
|
||||
self.cmd, self.state = [], 'IDLE'
|
||||
return
|
||||
manu = (m1, self.cmd.pop(0), self.cmd.pop(0))
|
||||
default_name = 'undefined'
|
||||
manu_name = sysex_manufacturer_ids.get(manu, default_name)
|
||||
if manu_name == default_name:
|
||||
if len(manu) == 3:
|
||||
manu_name = ('%s (0x%02x 0x%02x 0x%02x)' % \
|
||||
(default_name, manu[0], manu[1], manu[2]),
|
||||
default_name)
|
||||
else:
|
||||
manu_name = ('%s (0x%02x)' % (default_name, manu[0]),
|
||||
default_name)
|
||||
else:
|
||||
manu_name = (manu_name, manu_name)
|
||||
# Extract the payload, display in 1 of 2 formats
|
||||
# TODO: Write methods to decode SysEx realtime & non-realtime payloads.
|
||||
payload0 = ''
|
||||
payload1 = ''
|
||||
while len(self.cmd) > 0:
|
||||
byte = self.cmd.pop(0)
|
||||
payload0 += '0x%02x ' % (byte)
|
||||
payload1 += '%02x ' % (byte)
|
||||
if payload0 == '':
|
||||
payload0 = '<empty>'
|
||||
payload1 = '<>'
|
||||
payload = (payload0, payload1)
|
||||
self.putx([0, ['%s: for \'%s\' with payload %s' % \
|
||||
(status_bytes[msg][0], manu_name[0], payload[0]),
|
||||
'%s: \'%s\', payload %s' % \
|
||||
(status_bytes[msg][1], manu_name[1], payload[1]),
|
||||
'%s: \'%s\', payload %s' % \
|
||||
(status_bytes[msg][2], manu_name[1], payload[1])]])
|
||||
self.cmd, self.state = [], 'IDLE'
|
||||
|
||||
def handle_syscommon_midi_time_code_quarter_frame_msg(self, newbyte):
|
||||
# MIDI time code quarter frame: F1 nd
|
||||
# n = message type
|
||||
# d = values
|
||||
#
|
||||
# Note: All System message codes don't utilize self.status_byte,
|
||||
# and System Exclusive and System Common clear it.
|
||||
c = self.cmd
|
||||
if len(c) < 2:
|
||||
if newbyte is None:
|
||||
self.handle_garbage_msg(None)
|
||||
return
|
||||
msg = c[0]
|
||||
nn, dd = (c[1] & 0x70) >> 4, c[1] & 0x0f
|
||||
group = ('System Common', 'SysCom', 'SC')
|
||||
self.es_block = self.es
|
||||
if nn != 7: # If message type does not contain SMPTE type.
|
||||
self.putx([0, ['%s: %s of %s, value 0x%01x' % \
|
||||
(group[0], status_bytes[msg][0],
|
||||
quarter_frame_type[nn][0], dd),
|
||||
'%s: %s of %s, value 0x%01x' % \
|
||||
(group[1], status_bytes[msg][1],
|
||||
quarter_frame_type[nn][1], dd),
|
||||
'%s: %s of %s, value 0x%01x' % \
|
||||
(group[2], status_bytes[msg][2],
|
||||
quarter_frame_type[nn][1], dd)]])
|
||||
self.cmd, self.state = [], 'IDLE'
|
||||
return
|
||||
tt = (dd & 0x6) >> 1
|
||||
self.putx([0, ['%s: %s of %s, value 0x%01x for %s' % \
|
||||
(group[0], status_bytes[msg][0], \
|
||||
quarter_frame_type[nn][0], dd, smpte_type[tt]),
|
||||
'%s: %s of %s, value 0x%01x for %s' % \
|
||||
(group[1], status_bytes[msg][1], \
|
||||
quarter_frame_type[nn][1], dd, smpte_type[tt]),
|
||||
'%s: %s of %s, value 0x%01x for %s' % \
|
||||
(group[2], status_bytes[msg][2], \
|
||||
quarter_frame_type[nn][1], dd, smpte_type[tt])]])
|
||||
self.cmd, self.state = [], 'IDLE'
|
||||
|
||||
def handle_syscommon_msg(self, newbyte):
|
||||
pass # TODO
|
||||
# System common messages
|
||||
#
|
||||
# There are 5 simple formats (which are directly handled here) and
|
||||
# 1 complex one called MIDI time code quarter frame.
|
||||
#
|
||||
# Note: While the MIDI lists 0xf7 as a "system common" message, it
|
||||
# is actually only used with SysEx messages so it is processed there.
|
||||
#
|
||||
# Note: All System message codes don't utilize self.status_byte.
|
||||
self.hard_clear_status_byte()
|
||||
if newbyte is not None:
|
||||
self.cmd.append(newbyte)
|
||||
c = self.cmd
|
||||
msg = c[0]
|
||||
group = ('System Common', 'SysCom', 'SC')
|
||||
if msg == 0xf1:
|
||||
# MIDI time code quarter frame
|
||||
self.handle_syscommon_midi_time_code_quarter_frame_msg(newbyte)
|
||||
return
|
||||
elif msg == 0xf2:
|
||||
# Song position pointer: F2 ll mm
|
||||
# ll = LSB position, mm = MSB position
|
||||
if len(c) < 3:
|
||||
if newbyte is None:
|
||||
self.handle_garbage_msg(None)
|
||||
return
|
||||
ll, mm = c[1], c[2]
|
||||
decimal = (mm << 7) + ll
|
||||
self.es_block = self.es
|
||||
self.putx([0, ['%s: %s 0x%02x 0x%02x (%d)' % \
|
||||
(group[0], status_bytes[msg][0], ll, mm, decimal),
|
||||
'%s: %s 0x%02x 0x%02x (%d)' % \
|
||||
(group[1], status_bytes[msg][1], ll, mm, decimal),
|
||||
'%s: %s (%d)' % \
|
||||
(group[2], status_bytes[msg][2], decimal)]])
|
||||
elif msg == 0xf3:
|
||||
# Song select: F3 ss
|
||||
# ss = song selection number
|
||||
if len(c) < 2:
|
||||
if newbyte is None:
|
||||
self.handle_garbage_msg(None)
|
||||
return
|
||||
ss = c[1]
|
||||
self.es_block = self.es
|
||||
self.putx([0, ['%s: %s number %d' % \
|
||||
(group[0], status_bytes[msg][0], ss),
|
||||
'%s: %s number %d' % \
|
||||
(group[1], status_bytes[msg][1], ss),
|
||||
'%s: %s # %d' % \
|
||||
(group[2], status_bytes[msg][2], ss)]])
|
||||
elif msg == 0xf4 or msg == 0xf5 or msg == 0xf6:
|
||||
# Undefined 0xf4, Undefined 0xf5, and Tune Request (respectively).
|
||||
# All are only 1 byte long with no data bytes.
|
||||
self.es_block = self.es
|
||||
self.putx([0, ['%s: %s' % (group[0], status_bytes[msg][0]),
|
||||
'%s: %s' % (group[1], status_bytes[msg][1]),
|
||||
'%s: %s' % (group[2], status_bytes[msg][2])]])
|
||||
self.cmd, self.state = [], 'IDLE'
|
||||
|
||||
def handle_sysrealtime_msg(self, newbyte):
|
||||
# System realtime message: 0b11111ttt (t = message type)
|
||||
#
|
||||
# Important: These messages are handled differently from all others
|
||||
# because they are allowed to temporarily interrupt other messages.
|
||||
# The interrupted messages resume after the realtime message is done.
|
||||
# Thus, they mostly leave 'self' the way it was found.
|
||||
#
|
||||
# Note: All System message codes don't utilize self.status_byte.
|
||||
old_ss_block, old_es_block = self.ss_block, self.es_block
|
||||
self.ss_block, self.es_block = self.ss, self.es
|
||||
group = ('System Realtime', 'SysReal', 'SR')
|
||||
self.putx([1, ['%s: %s' % (group[0], status_bytes[newbyte][0]),
|
||||
'%s: %s' % (group[1], status_bytes[newbyte][1]),
|
||||
'%s: %s' % (group[2], status_bytes[newbyte][2])]])
|
||||
self.ss_block, self.es_block = old_ss_block, old_es_block
|
||||
# Deliberately not resetting self.cmd or self.state.
|
||||
|
||||
def handle_garbage_msg(self, newbyte):
|
||||
# Handle messages that are either not handled or are corrupt.
|
||||
self.es_block = self.es
|
||||
self.putx([0, ['System realtime message: %s' % status_bytes[newbyte]]])
|
||||
if newbyte is not None:
|
||||
self.cmd.append(newbyte)
|
||||
return
|
||||
payload = '<empty>'
|
||||
max_bytes = 16 # Put a limit on the length on the hex dump.
|
||||
for index in range(len(self.cmd)):
|
||||
if index == max_bytes:
|
||||
payload += ' ...'
|
||||
break
|
||||
if index == 0:
|
||||
payload = '0x%02x' % self.cmd[index]
|
||||
else:
|
||||
payload += ' 0x%02x' % self.cmd[index]
|
||||
self.putx([2, ['UNHANDLED DATA: %s' % payload,
|
||||
'UNHANDLED', '???', '?']])
|
||||
self.cmd, self.state = [], 'IDLE'
|
||||
self.hard_clear_status_byte()
|
||||
|
||||
def handle_state(self, state, newbyte):
|
||||
# 'newbyte' can either be:
|
||||
# 1. Value between 0x00-0xff, deal with the byte normally.
|
||||
# 2. Value of 'None' which means "flush any buffered data".
|
||||
if state == 'HANDLE CHANNEL MSG':
|
||||
self.handle_channel_msg(newbyte)
|
||||
elif state == 'HANDLE SYSEX MSG':
|
||||
self.handle_sysex_msg(newbyte)
|
||||
elif state == 'HANDLE SYSCOMMON MSG':
|
||||
self.handle_syscommon_msg(newbyte)
|
||||
elif state == 'HANDLE SYSREALTIME MSG':
|
||||
self.handle_sysrealtime_msg(newbyte)
|
||||
elif state == 'BUFFER GARBAGE MSG':
|
||||
self.handle_garbage_msg(newbyte)
|
||||
|
||||
def get_next_state(self, newbyte):
|
||||
# 'newbyte' must be a valid byte between 0x00 and 0xff.
|
||||
#
|
||||
# Try to determine the state based off of the 'newbyte' parameter.
|
||||
if newbyte in range(0x80, 0xef + 1):
|
||||
return 'HANDLE CHANNEL MSG'
|
||||
if newbyte == 0xf0:
|
||||
return 'HANDLE SYSEX MSG'
|
||||
if newbyte in range(0xf1, 0xf7):
|
||||
return'HANDLE SYSCOMMON MSG'
|
||||
if newbyte in range(0xf8, 0xff + 1):
|
||||
return 'HANDLE SYSREALTIME MSG'
|
||||
# Passing 0xf7 is an error; messages don't start with 0xf7.
|
||||
if newbyte == 0xf7:
|
||||
return 'BUFFER GARBAGE MSG'
|
||||
# Next, base the state off of self.status_byte.
|
||||
if self.status_byte < 0x80:
|
||||
return 'BUFFER GARBAGE MSG'
|
||||
return self.get_next_state(self.status_byte)
|
||||
|
||||
def decode(self, ss, es, data):
|
||||
ptype, rxtx, pdata = data
|
||||
state = 'IDLE'
|
||||
|
||||
# For now, ignore all UART packets except the actual data packets.
|
||||
if ptype != 'DATA':
|
||||
return
|
||||
|
||||
self.ss, self.es = ss, es
|
||||
|
||||
# We're only interested in the byte value (not individual bits).
|
||||
pdata = pdata[0]
|
||||
|
||||
@@ -183,29 +586,39 @@ class Decoder(srd.Decoder):
|
||||
# - Most messages: 1 status byte, 1-2 data bytes.
|
||||
# - Real-time system messages: always 1 byte.
|
||||
# - SysEx messages: 1 status byte, n data bytes, EOX byte.
|
||||
#
|
||||
# Aspects of the MIDI protocol that complicate decoding:
|
||||
# - MIDI System Realtime messages can briefly interrupt other
|
||||
# messages already in progress.
|
||||
# - "Running Status" allows for omitting the status byte in most
|
||||
# scenarios if sequential messages have the same status byte.
|
||||
# - System Exclusive (SysEx) messages can be terminated by ANY
|
||||
# status byte (not limited to EOX byte).
|
||||
|
||||
# State machine.
|
||||
if self.state == 'IDLE':
|
||||
# Wait until we see a status byte (bit 7 must be set).
|
||||
if pdata < 0x80:
|
||||
return # TODO: How to handle? Ignore?
|
||||
if pdata >= 0x80 and pdata != 0xf7:
|
||||
state = self.get_next_state(pdata)
|
||||
if state != 'HANDLE SYSREALTIME MSG' and self.state != 'IDLE':
|
||||
# Flush the previous data since a new message is starting.
|
||||
self.handle_state(self.state, None)
|
||||
# Cache ss and es -after- flushing previous data.
|
||||
self.ss, self.es = ss, es
|
||||
# This is a status byte, remember the start sample.
|
||||
self.ss_block = ss
|
||||
if pdata in range(0x80, 0xef + 1):
|
||||
self.state = 'HANDLE CHANNEL MSG'
|
||||
elif pdata == 0xf0:
|
||||
self.state = 'HANDLE SYSEX MSG'
|
||||
elif pdata in range(0xf1, 0xf7 + 1):
|
||||
self.state = 'HANDLE SYSCOMMON MSG'
|
||||
elif pdata in range(0xf8, 0xff + 1):
|
||||
self.state = 'HANDLE SYSREALTIME MSG'
|
||||
if state != 'HANDLE SYSREALTIME MSG':
|
||||
self.ss_block = ss
|
||||
elif self.state == 'IDLE' or self.state == 'BUFFER GARBAGE MSG':
|
||||
# Deal with "running status" or that we're buffering garbage.
|
||||
self.ss, self.es = ss, es
|
||||
if self.state == 'IDLE':
|
||||
self.ss_block = ss
|
||||
state = self.get_next_state(pdata)
|
||||
else:
|
||||
self.ss, self.es = ss, es
|
||||
state = self.state
|
||||
|
||||
# Yes, this is intentionally _not_ an 'elif' here.
|
||||
if self.state == 'HANDLE CHANNEL MSG':
|
||||
self.handle_channel_msg(pdata)
|
||||
elif self.state == 'HANDLE SYSEX MSG':
|
||||
self.handle_sysex_msg(pdata)
|
||||
elif self.state == 'HANDLE SYSCOMMON MSG':
|
||||
self.handle_syscommon_msg(pdata)
|
||||
elif self.state == 'HANDLE SYSREALTIME MSG':
|
||||
self.handle_sysrealtime_msg(pdata)
|
||||
if state != 'HANDLE SYSREALTIME MSG':
|
||||
self.state = state
|
||||
if state == 'BUFFER GARBAGE MSG':
|
||||
self.status_byte = 0
|
||||
self.handle_state(state, pdata)
|
||||
|
||||
@@ -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'
|
||||
|
||||
|
||||
26
libsigrokdecode4DSL/decoders/ps2/__init__.py
Executable file
26
libsigrokdecode4DSL/decoders/ps2/__init__.py
Executable file
@@ -0,0 +1,26 @@
|
||||
##
|
||||
## This file is part of the libsigrokdecode project.
|
||||
##
|
||||
## Copyright (C) 2016 Daniel Schulte <trilader@schroedingers-bit.net>
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation; either version 2 of the License, or
|
||||
## (at your option) any later version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
## GNU General Public License for more details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License
|
||||
## along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
##
|
||||
|
||||
'''
|
||||
This protocol decoder can decode PS/2 device -> host communication.
|
||||
|
||||
Host -> device communication is currently not supported.
|
||||
'''
|
||||
|
||||
from .pd import Decoder
|
||||
145
libsigrokdecode4DSL/decoders/ps2/pd.py
Executable file
145
libsigrokdecode4DSL/decoders/ps2/pd.py
Executable file
@@ -0,0 +1,145 @@
|
||||
##
|
||||
## This file is part of the libsigrokdecode project.
|
||||
##
|
||||
## Copyright (C) 2016 Daniel Schulte <trilader@schroedingers-bit.net>
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation; either version 2 of the License, or
|
||||
## (at your option) any later version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
## GNU General Public License for more details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License
|
||||
## along with this program; if not, write to the Free Software
|
||||
## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
##
|
||||
|
||||
import sigrokdecode as srd
|
||||
from collections import namedtuple
|
||||
|
||||
class Ann:
|
||||
BIT, START, STOP, PARITY_OK, PARITY_ERR, DATA, WORD = range(7)
|
||||
|
||||
Bit = namedtuple('Bit', 'val ss es')
|
||||
|
||||
class Decoder(srd.Decoder):
|
||||
api_version = 2
|
||||
id = 'ps2'
|
||||
name = 'PS/2'
|
||||
longname = 'PS/2'
|
||||
desc = 'PS/2 keyboard/mouse interface.'
|
||||
license = 'gplv2+'
|
||||
inputs = ['logic']
|
||||
outputs = ['ps2']
|
||||
channels = (
|
||||
{'id': 'clk', 'name': 'Clock', 'desc': 'Clock line'},
|
||||
{'id': 'data', 'name': 'Data', 'desc': 'Data line'},
|
||||
)
|
||||
annotations = (
|
||||
('bit', 'Bit'),
|
||||
('start-bit', 'Start bit'),
|
||||
('stop-bit', 'Stop bit'),
|
||||
('parity-ok', 'Parity OK bit'),
|
||||
('parity-err', 'Parity error bit'),
|
||||
('data-bit', 'Data bit'),
|
||||
('word', 'Word'),
|
||||
)
|
||||
annotation_rows = (
|
||||
('bits', 'Bits', (0,)),
|
||||
('fields', 'Fields', (1, 2, 3, 4, 5, 6)),
|
||||
)
|
||||
|
||||
def __init__(self):
|
||||
self.bits = []
|
||||
self.prev_pins = None
|
||||
self.prev_clock = None
|
||||
self.samplenum = 0
|
||||
self.clock_was_high = False
|
||||
self.bitcount = 0
|
||||
|
||||
def start(self):
|
||||
self.out_ann = self.register(srd.OUTPUT_ANN)
|
||||
|
||||
def putb(self, bit, ann_idx):
|
||||
b = self.bits[bit]
|
||||
self.put(b.ss, b.es, self.out_ann, [ann_idx, [str(b.val)]])
|
||||
|
||||
def putx(self, bit, ann):
|
||||
self.put(self.bits[bit].ss, self.bits[bit].es, self.out_ann, ann)
|
||||
|
||||
def handle_bits(self, datapin):
|
||||
# Ignore non start condition bits (useful during keyboard init).
|
||||
if self.bitcount == 0 and datapin == 1:
|
||||
return
|
||||
|
||||
# Store individual bits and their start/end samplenumbers.
|
||||
self.bits.append(Bit(datapin, self.samplenum, self.samplenum))
|
||||
|
||||
# Fix up end sample numbers of the bits.
|
||||
if self.bitcount > 0:
|
||||
b = self.bits[self.bitcount - 1]
|
||||
self.bits[self.bitcount - 1] = Bit(b.val, b.ss, self.samplenum)
|
||||
if self.bitcount == 11:
|
||||
self.bitwidth = self.bits[1].es - self.bits[2].es
|
||||
b = self.bits[-1]
|
||||
self.bits[-1] = Bit(b.val, b.ss, b.es + self.bitwidth)
|
||||
|
||||
# Find all 11 bits. Start + 8 data + odd parity + stop.
|
||||
if self.bitcount < 11:
|
||||
self.bitcount += 1
|
||||
return
|
||||
|
||||
# Extract data word.
|
||||
word = 0
|
||||
for i in range(8):
|
||||
word |= (self.bits[i + 1].val << i)
|
||||
|
||||
# Calculate parity.
|
||||
parity_ok = (bin(word).count('1') + self.bits[9].val) % 2 == 1
|
||||
|
||||
# Emit annotations.
|
||||
for i in range(11):
|
||||
self.putb(i, Ann.BIT)
|
||||
self.putx(0, [Ann.START, ['Start bit', 'Start', 'S']])
|
||||
self.put(self.bits[1].ss, self.bits[8].es, self.out_ann, [Ann.WORD,
|
||||
['Data: %02x' % word, 'D: %02x' % word, '%02x' % word]])
|
||||
if parity_ok:
|
||||
self.putx(9, [Ann.PARITY_OK, ['Parity OK', 'Par OK', 'P']])
|
||||
else:
|
||||
self.putx(9, [Ann.PARITY_ERR, ['Parity error', 'Par err', 'PE']])
|
||||
self.putx(10, [Ann.STOP, ['Stop bit', 'Stop', 'St', 'T']])
|
||||
|
||||
self.bits, self.bitcount = [], 0
|
||||
|
||||
def find_clk_edge(self, clock_pin, data_pin):
|
||||
# Ignore sample if the clock pin hasn't changed.
|
||||
if clock_pin == self.prev_clock:
|
||||
return
|
||||
self.prev_clock = clock_pin
|
||||
|
||||
# Sample on falling clock edge.
|
||||
if clock_pin == 1:
|
||||
return
|
||||
|
||||
# Found the correct clock edge, now get the bits.
|
||||
self.handle_bits(data_pin)
|
||||
|
||||
def decode(self, ss, es, data):
|
||||
for (self.samplenum, pins) in data:
|
||||
data.itercnt += 1
|
||||
clock_pin, data_pin = pins[0], pins[1]
|
||||
|
||||
# Ignore identical samples.
|
||||
if self.prev_pins == pins:
|
||||
continue
|
||||
self.prev_pins = pins
|
||||
|
||||
if clock_pin == 0 and not self.clock_was_high:
|
||||
continue
|
||||
self.clock_was_high = True
|
||||
|
||||
self.find_clk_edge(clock_pin, data_pin)
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
##
|
||||
## This file is part of the sigrok project.
|
||||
## This file is part of the libsigrokdecode project.
|
||||
##
|
||||
## Copyright (C) 2015 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
##
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
##
|
||||
## This file is part of the sigrok project.
|
||||
## This file is part of the libsigrokdecode project.
|
||||
##
|
||||
## Copyright (C) 2015 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
##
|
||||
@@ -19,7 +19,7 @@
|
||||
##
|
||||
|
||||
import sigrokdecode as srd
|
||||
from .lists import *
|
||||
from common.sdcard import (cmd_names, acmd_names, accepted_voltages, card_status, sd_status)
|
||||
|
||||
class Decoder(srd.Decoder):
|
||||
api_version = 2
|
||||
@@ -61,7 +61,7 @@ class Decoder(srd.Decoder):
|
||||
('cmd', 'Commands', tuple(range(128))),
|
||||
)
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
def __init__(self):
|
||||
self.state = 'GET COMMAND TOKEN'
|
||||
self.token = []
|
||||
self.oldpins = None
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
##
|
||||
## This file is part of the libsigrokdecode project.
|
||||
##
|
||||
## Copyright (C) 2011-2015 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
## Copyright (C) 2011-2016 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
@@ -21,9 +21,31 @@
|
||||
import sigrokdecode as srd
|
||||
from .lists import *
|
||||
|
||||
L = len(cmds)
|
||||
|
||||
# Don't forget to keep this in sync with 'cmds' is lists.py.
|
||||
class Ann:
|
||||
WRSR, PP, READ, WRDI, RDSR, WREN, FAST_READ, SE, RDSCUR, WRSCUR, \
|
||||
RDSR2, CE, ESRY, DSRY, REMS, RDID, RDP_RES, CP, ENSO, DP, READ2X, \
|
||||
EXSO, CE2, BE, REMS2, \
|
||||
BIT, FIELD, WARN = range(L + 3)
|
||||
|
||||
def cmd_annotation_classes():
|
||||
return tuple([tuple([cmd[0].lower(), cmd[1]]) for cmd in cmds.values()])
|
||||
|
||||
def decode_dual_bytes(sio0, sio1):
|
||||
# Given a byte in SIO0 (MOSI) of even bits and a byte in
|
||||
# SIO1 (MISO) of odd bits, return a tuple of two bytes.
|
||||
def combine_byte(even, odd):
|
||||
result = 0
|
||||
for bit in range(4):
|
||||
if even & (1 << bit):
|
||||
result |= 1 << (bit*2)
|
||||
if odd & (1 << bit):
|
||||
result |= 1 << ((bit*2) + 1)
|
||||
return result
|
||||
return (combine_byte(sio0 >> 4, sio1 >> 4), combine_byte(sio0, sio1))
|
||||
|
||||
def decode_status_reg(data):
|
||||
# TODO: Additional per-bit(s) self.put() calls with correct start/end.
|
||||
|
||||
@@ -59,21 +81,40 @@ class Decoder(srd.Decoder):
|
||||
inputs = ['spi']
|
||||
outputs = ['spiflash']
|
||||
annotations = cmd_annotation_classes() + (
|
||||
('bits', 'Bits'),
|
||||
('bits2', 'Bits2'),
|
||||
('warnings', 'Warnings'),
|
||||
('bit', 'Bit'),
|
||||
('field', 'Field'),
|
||||
('warning', 'Warning'),
|
||||
)
|
||||
annotation_rows = (
|
||||
('bits', 'Bits', (24, 25)),
|
||||
('commands', 'Commands', tuple(range(23 + 1))),
|
||||
('warnings', 'Warnings', (26,)),
|
||||
('bits', 'Bits', (L + 0,)),
|
||||
('fields', 'Fields', (L + 1,)),
|
||||
('commands', 'Commands', tuple(range(len(cmds)))),
|
||||
('warnings', 'Warnings', (L + 2,)),
|
||||
)
|
||||
options = (
|
||||
{'id': 'chip', 'desc': 'Chip', 'default': tuple(chips.keys())[0],
|
||||
'values': tuple(chips.keys())},
|
||||
{'id': 'format', 'desc': 'Data format', 'default': 'hex',
|
||||
'values': ('hex', 'ascii')},
|
||||
)
|
||||
|
||||
def __init__(self):
|
||||
self.device_id = -1
|
||||
self.on_end_transaction = None
|
||||
self.end_current_transaction()
|
||||
|
||||
# Build dict mapping command keys to handler functions. Each
|
||||
# command in 'cmds' (defined in lists.py) has a matching
|
||||
# handler self.handle_<shortname>.
|
||||
def get_handler(cmd):
|
||||
s = 'handle_%s' % cmds[cmd][0].lower().replace('/', '_')
|
||||
return getattr(self, s)
|
||||
self.cmd_handlers = dict((cmd, get_handler(cmd)) for cmd in cmds.keys())
|
||||
|
||||
def end_current_transaction(self):
|
||||
if self.on_end_transaction is not None: # Callback for CS# transition.
|
||||
self.on_end_transaction()
|
||||
self.on_end_transaction = None
|
||||
self.state = None
|
||||
self.cmdstate = 1
|
||||
self.addr = 0
|
||||
@@ -82,43 +123,78 @@ class Decoder(srd.Decoder):
|
||||
def start(self):
|
||||
self.out_ann = self.register(srd.OUTPUT_ANN)
|
||||
self.chip = chips[self.options['chip']]
|
||||
self.vendor = self.options['chip'].split('_')[0]
|
||||
|
||||
def putx(self, data):
|
||||
# Simplification, most annotations span exactly one SPI byte/packet.
|
||||
self.put(self.ss, self.es, self.out_ann, data)
|
||||
|
||||
def putb(self, data):
|
||||
self.put(self.block_ss, self.block_es, self.out_ann, data)
|
||||
def putf(self, data):
|
||||
self.put(self.ss_field, self.es_field, self.out_ann, data)
|
||||
|
||||
def putc(self, data):
|
||||
self.put(self.ss_cmd, self.es_cmd, self.out_ann, data)
|
||||
|
||||
def device(self):
|
||||
return device_name[self.vendor].get(self.device_id, 'Unknown')
|
||||
|
||||
def vendor_device(self):
|
||||
return '%s %s' % (self.chip['vendor'], self.device())
|
||||
|
||||
def cmd_ann_list(self):
|
||||
x, s = cmds[self.state][0], cmds[self.state][1]
|
||||
return ['Command: %s (%s)' % (s, x), 'Command: %s' % s,
|
||||
'Cmd: %s' % s, 'Cmd: %s' % x, x]
|
||||
|
||||
def cmd_vendor_dev_list(self):
|
||||
c, d = cmds[self.state], 'Device = %s' % self.vendor_device()
|
||||
return ['%s (%s): %s' % (c[1], c[0], d), '%s: %s' % (c[1], d),
|
||||
'%s: %s' % (c[0], d), d, self.vendor_device()]
|
||||
|
||||
def emit_cmd_byte(self):
|
||||
self.ss_cmd = self.ss
|
||||
self.putx([Ann.FIELD, self.cmd_ann_list()])
|
||||
self.addr = 0
|
||||
|
||||
def emit_addr_bytes(self, mosi):
|
||||
self.addr |= (mosi << ((4 - self.cmdstate) * 8))
|
||||
b = ((3 - (self.cmdstate - 2)) * 8) - 1
|
||||
self.putx([Ann.BIT,
|
||||
['Address bits %d..%d: 0x%02x' % (b, b - 7, mosi),
|
||||
'Addr bits %d..%d: 0x%02x' % (b, b - 7, mosi),
|
||||
'Addr bits %d..%d' % (b, b - 7), 'A%d..A%d' % (b, b - 7)]])
|
||||
if self.cmdstate == 2:
|
||||
self.ss_field = self.ss
|
||||
if self.cmdstate == 4:
|
||||
self.es_field = self.es
|
||||
self.putf([Ann.FIELD, ['Address: 0x%06x' % self.addr,
|
||||
'Addr: 0x%06x' % self.addr, '0x%06x' % self.addr]])
|
||||
|
||||
def handle_wren(self, mosi, miso):
|
||||
self.putx([0, ['Command: %s' % cmds[self.state][1]]])
|
||||
self.putx([Ann.WREN, self.cmd_ann_list()])
|
||||
self.state = None
|
||||
|
||||
def handle_wrdi(self, mosi, miso):
|
||||
pass # TODO
|
||||
|
||||
# TODO: Check/display device ID / name
|
||||
def handle_rdid(self, mosi, miso):
|
||||
if self.cmdstate == 1:
|
||||
# Byte 1: Master sends command ID.
|
||||
self.ss_block = self.ss
|
||||
self.putx([2, ['Command: %s' % cmds[self.state][1]]])
|
||||
self.emit_cmd_byte()
|
||||
elif self.cmdstate == 2:
|
||||
# Byte 2: Slave sends the JEDEC manufacturer ID.
|
||||
self.putx([2, ['Manufacturer ID: 0x%02x' % miso]])
|
||||
self.putx([Ann.FIELD, ['Manufacturer ID: 0x%02x' % miso]])
|
||||
elif self.cmdstate == 3:
|
||||
# Byte 3: Slave sends the memory type (0x20 for this chip).
|
||||
self.putx([2, ['Memory type: 0x%02x' % miso]])
|
||||
# Byte 3: Slave sends the memory type.
|
||||
self.putx([Ann.FIELD, ['Memory type: 0x%02x' % miso]])
|
||||
elif self.cmdstate == 4:
|
||||
# Byte 4: Slave sends the device ID.
|
||||
self.device_id = miso
|
||||
self.putx([2, ['Device ID: 0x%02x' % miso]])
|
||||
self.putx([Ann.FIELD, ['Device ID: 0x%02x' % miso]])
|
||||
|
||||
if self.cmdstate == 4:
|
||||
# TODO: Check self.device_id is valid & exists in device_names.
|
||||
# TODO: Same device ID? Check!
|
||||
d = 'Device: Macronix %s' % device_name[self.device_id]
|
||||
self.put(self.ss_block, self.es, self.out_ann, [0, [d]])
|
||||
self.es_cmd = self.es
|
||||
self.putc([Ann.RDID, self.cmd_vendor_dev_list()])
|
||||
self.state = None
|
||||
else:
|
||||
self.cmdstate += 1
|
||||
@@ -130,52 +206,69 @@ class Decoder(srd.Decoder):
|
||||
# When done, the master de-asserts CS# again.
|
||||
if self.cmdstate == 1:
|
||||
# Byte 1: Master sends command ID.
|
||||
self.putx([3, ['Command: %s' % cmds[self.state][1]]])
|
||||
self.emit_cmd_byte()
|
||||
elif self.cmdstate >= 2:
|
||||
# Bytes 2-x: Slave sends status register as long as master clocks.
|
||||
if self.cmdstate <= 3: # TODO: While CS# asserted.
|
||||
self.putx([24, ['Status register: 0x%02x' % miso]])
|
||||
self.putx([25, [decode_status_reg(miso)]])
|
||||
|
||||
if self.cmdstate == 3: # TODO: If CS# got de-asserted.
|
||||
self.state = None
|
||||
return
|
||||
self.es_cmd = self.es
|
||||
self.putx([Ann.BIT, [decode_status_reg(miso)]])
|
||||
self.putx([Ann.FIELD, ['Status register']])
|
||||
self.putc([Ann.RDSR, self.cmd_ann_list()])
|
||||
self.cmdstate += 1
|
||||
|
||||
def handle_rdsr2(self, mosi, miso):
|
||||
# Read status register 2: Master asserts CS#, sends RDSR2 command,
|
||||
# reads status register 2 byte. If CS# is kept asserted, the status
|
||||
# register 2 can be read continuously / multiple times in a row.
|
||||
# When done, the master de-asserts CS# again.
|
||||
if self.cmdstate == 1:
|
||||
# Byte 1: Master sends command ID.
|
||||
self.emit_cmd_byte()
|
||||
elif self.cmdstate >= 2:
|
||||
# Bytes 2-x: Slave sends status register 2 as long as master clocks.
|
||||
self.es_cmd = self.es
|
||||
# TODO: Decode status register 2 correctly.
|
||||
self.putx([Ann.BIT, [decode_status_reg(miso)]])
|
||||
self.putx([Ann.FIELD, ['Status register 2']])
|
||||
self.putc([Ann.RDSR2, self.cmd_ann_list()])
|
||||
self.cmdstate += 1
|
||||
|
||||
def handle_wrsr(self, mosi, miso):
|
||||
pass # TODO
|
||||
# Write status register: Master asserts CS#, sends WRSR command,
|
||||
# writes 1 or 2 status register byte(s).
|
||||
# When done, the master de-asserts CS# again. If this doesn't happen
|
||||
# the WRSR command will not be executed.
|
||||
if self.cmdstate == 1:
|
||||
# Byte 1: Master sends command ID.
|
||||
self.emit_cmd_byte()
|
||||
elif self.cmdstate == 2:
|
||||
# Byte 2: Master sends status register 1.
|
||||
self.putx([Ann.BIT, [decode_status_reg(miso)]])
|
||||
self.putx([Ann.FIELD, ['Status register 1']])
|
||||
elif self.cmdstate == 3:
|
||||
# Byte 3: Master sends status register 2.
|
||||
# TODO: Decode status register 2 correctly.
|
||||
self.putx([Ann.BIT, [decode_status_reg(miso)]])
|
||||
self.putx([Ann.FIELD, ['Status register 2']])
|
||||
self.es_cmd = self.es
|
||||
self.putc([Ann.WRSR, self.cmd_ann_list()])
|
||||
self.cmdstate += 1
|
||||
|
||||
def handle_read(self, mosi, miso):
|
||||
# Read data bytes: Master asserts CS#, sends READ command, sends
|
||||
# 3-byte address, reads >= 1 data bytes, de-asserts CS#.
|
||||
if self.cmdstate == 1:
|
||||
# Byte 1: Master sends command ID.
|
||||
self.putx([5, ['Command: %s' % cmds[self.state][1]]])
|
||||
self.emit_cmd_byte()
|
||||
elif self.cmdstate in (2, 3, 4):
|
||||
# Bytes 2/3/4: Master sends read address (24bits, MSB-first).
|
||||
self.addr |= (mosi << ((4 - self.cmdstate) * 8))
|
||||
# self.putx([0, ['Read address, byte %d: 0x%02x' % \
|
||||
# (4 - self.cmdstate, mosi)]])
|
||||
if self.cmdstate == 4:
|
||||
self.putx([24, ['Read address: 0x%06x' % self.addr]])
|
||||
self.addr = 0
|
||||
self.emit_addr_bytes(mosi)
|
||||
elif self.cmdstate >= 5:
|
||||
# Bytes 5-x: Master reads data bytes (until CS# de-asserted).
|
||||
# TODO: For now we hardcode 256 bytes per READ command.
|
||||
if self.cmdstate <= 256 + 4: # TODO: While CS# asserted.
|
||||
self.data.append(miso)
|
||||
# self.putx([0, ['New read byte: 0x%02x' % miso]])
|
||||
|
||||
if self.cmdstate == 256 + 4: # TODO: If CS# got de-asserted.
|
||||
# s = ', '.join(map(hex, self.data))
|
||||
s = ''.join(map(chr, self.data))
|
||||
self.putx([24, ['Read data']])
|
||||
self.putx([25, ['Read data: %s' % s]])
|
||||
self.data = []
|
||||
self.state = None
|
||||
return
|
||||
|
||||
self.es_field = self.es # Will be overwritten for each byte.
|
||||
if self.cmdstate == 5:
|
||||
self.ss_field = self.ss
|
||||
self.on_end_transaction = lambda: self.output_data_block('Data', Ann.READ)
|
||||
self.data.append(miso)
|
||||
self.cmdstate += 1
|
||||
|
||||
def handle_fast_read(self, mosi, miso):
|
||||
@@ -183,60 +276,70 @@ class Decoder(srd.Decoder):
|
||||
# 3-byte address + 1 dummy byte, reads >= 1 data bytes, de-asserts CS#.
|
||||
if self.cmdstate == 1:
|
||||
# Byte 1: Master sends command ID.
|
||||
self.putx([5, ['Command: %s' % cmds[self.state][1]]])
|
||||
self.emit_cmd_byte()
|
||||
elif self.cmdstate in (2, 3, 4):
|
||||
# Bytes 2/3/4: Master sends read address (24bits, MSB-first).
|
||||
self.putx([24, ['AD%d: 0x%02x' % (self.cmdstate - 1, mosi)]])
|
||||
if self.cmdstate == 2:
|
||||
self.block_ss = self.ss
|
||||
self.addr |= (mosi << ((4 - self.cmdstate) * 8))
|
||||
self.emit_addr_bytes(mosi)
|
||||
elif self.cmdstate == 5:
|
||||
self.putx([24, ['Dummy byte: 0x%02x' % mosi]])
|
||||
self.block_es = self.es
|
||||
self.putb([5, ['Read address: 0x%06x' % self.addr]])
|
||||
self.addr = 0
|
||||
self.putx([Ann.BIT, ['Dummy byte: 0x%02x' % mosi]])
|
||||
elif self.cmdstate >= 6:
|
||||
# Bytes 6-x: Master reads data bytes (until CS# de-asserted).
|
||||
# TODO: For now we hardcode 32 bytes per FAST READ command.
|
||||
self.es_field = self.es # Will be overwritten for each byte.
|
||||
if self.cmdstate == 6:
|
||||
self.block_ss = self.ss
|
||||
if self.cmdstate <= 32 + 5: # TODO: While CS# asserted.
|
||||
self.data.append(miso)
|
||||
if self.cmdstate == 32 + 5: # TODO: If CS# got de-asserted.
|
||||
self.block_es = self.es
|
||||
s = ' '.join([hex(b)[2:] for b in self.data])
|
||||
self.putb([25, ['Read data: %s' % s]])
|
||||
self.data = []
|
||||
self.state = None
|
||||
return
|
||||
|
||||
self.ss_field = self.ss
|
||||
self.on_end_transaction = lambda: self.output_data_block('Data', Ann.FAST_READ)
|
||||
self.data.append(miso)
|
||||
self.cmdstate += 1
|
||||
|
||||
def handle_2read(self, mosi, miso):
|
||||
pass # TODO
|
||||
# 2x I/O read (fast read dual I/O): Master asserts CS#, sends 2READ
|
||||
# command, sends 3-byte address + 1 dummy byte, reads >= 1 data bytes,
|
||||
# de-asserts CS#. All data after the command is sent via two I/O pins.
|
||||
# MOSI = SIO0 = even bits, MISO = SIO1 = odd bits.
|
||||
if self.cmdstate != 1:
|
||||
b1, b2 = decode_dual_bytes(mosi, miso)
|
||||
if self.cmdstate == 1:
|
||||
# Byte 1: Master sends command ID.
|
||||
self.emit_cmd_byte()
|
||||
elif self.cmdstate == 2:
|
||||
# Bytes 2/3(/4): Master sends read address (24bits, MSB-first).
|
||||
# Handle bytes 2 and 3 here.
|
||||
self.emit_addr_bytes(b1)
|
||||
self.cmdstate = 3
|
||||
self.emit_addr_bytes(b2)
|
||||
elif self.cmdstate == 4:
|
||||
# Byte 5: Dummy byte. Also handle byte 4 (address LSB) here.
|
||||
self.emit_addr_bytes(b1)
|
||||
self.cmdstate = 5
|
||||
self.putx([Ann.BIT, ['Dummy byte: 0x%02x' % b2]])
|
||||
elif self.cmdstate >= 6:
|
||||
# Bytes 6-x: Master reads data bytes (until CS# de-asserted).
|
||||
self.es_field = self.es # Will be overwritten for each byte.
|
||||
if self.cmdstate == 6:
|
||||
self.ss_field = self.ss
|
||||
self.on_end_transaction = lambda: self.output_data_block('Data', Ann.READ2X)
|
||||
self.data.append(b1)
|
||||
self.data.append(b2)
|
||||
self.cmdstate += 1
|
||||
|
||||
# TODO: Warn/abort if we don't see the necessary amount of bytes.
|
||||
# TODO: Warn if WREN was not seen before.
|
||||
def handle_se(self, mosi, miso):
|
||||
if self.cmdstate == 1:
|
||||
# Byte 1: Master sends command ID.
|
||||
self.addr = 0
|
||||
self.ss_block = self.ss
|
||||
self.putx([8, ['Command: %s' % cmds[self.state][1]]])
|
||||
self.emit_cmd_byte()
|
||||
elif self.cmdstate in (2, 3, 4):
|
||||
# Bytes 2/3/4: Master sends sector address (24bits, MSB-first).
|
||||
self.addr |= (mosi << ((4 - self.cmdstate) * 8))
|
||||
# self.putx([0, ['Sector address, byte %d: 0x%02x' % \
|
||||
# (4 - self.cmdstate, mosi)]])
|
||||
self.emit_addr_bytes(mosi)
|
||||
|
||||
if self.cmdstate == 4:
|
||||
self.es_cmd = self.es
|
||||
d = 'Erase sector %d (0x%06x)' % (self.addr, self.addr)
|
||||
self.put(self.ss_block, self.es, self.out_ann, [24, [d]])
|
||||
self.putc([Ann.SE, [d]])
|
||||
# TODO: Max. size depends on chip, check that too if possible.
|
||||
if self.addr % 4096 != 0:
|
||||
# Sector addresses must be 4K-aligned (same for all 3 chips).
|
||||
d = 'Warning: Invalid sector address!'
|
||||
self.put(self.ss_block, self.es, self.out_ann, [101, [d]])
|
||||
self.putc([Ann.WARN, ['Warning: Invalid sector address!']])
|
||||
self.state = None
|
||||
else:
|
||||
self.cmdstate += 1
|
||||
@@ -255,31 +358,17 @@ class Decoder(srd.Decoder):
|
||||
# page address, sends >= 1 data bytes, de-asserts CS#.
|
||||
if self.cmdstate == 1:
|
||||
# Byte 1: Master sends command ID.
|
||||
self.putx([12, ['Command: %s' % cmds[self.state][1]]])
|
||||
self.emit_cmd_byte()
|
||||
elif self.cmdstate in (2, 3, 4):
|
||||
# Bytes 2/3/4: Master sends page address (24bits, MSB-first).
|
||||
self.addr |= (mosi << ((4 - self.cmdstate) * 8))
|
||||
# self.putx([0, ['Page address, byte %d: 0x%02x' % \
|
||||
# (4 - self.cmdstate, mosi)]])
|
||||
if self.cmdstate == 4:
|
||||
self.putx([24, ['Page address: 0x%06x' % self.addr]])
|
||||
self.addr = 0
|
||||
self.emit_addr_bytes(mosi)
|
||||
elif self.cmdstate >= 5:
|
||||
# Bytes 5-x: Master sends data bytes (until CS# de-asserted).
|
||||
# TODO: For now we hardcode 256 bytes per page / PP command.
|
||||
if self.cmdstate <= 256 + 4: # TODO: While CS# asserted.
|
||||
self.data.append(mosi)
|
||||
# self.putx([0, ['New data byte: 0x%02x' % mosi]])
|
||||
|
||||
if self.cmdstate == 256 + 4: # TODO: If CS# got de-asserted.
|
||||
# s = ', '.join(map(hex, self.data))
|
||||
s = ''.join(map(chr, self.data))
|
||||
self.putx([24, ['Page data']])
|
||||
self.putx([25, ['Page data: %s' % s]])
|
||||
self.data = []
|
||||
self.state = None
|
||||
return
|
||||
|
||||
self.es_field = self.es # Will be overwritten for each byte.
|
||||
if self.cmdstate == 5:
|
||||
self.ss_field = self.ss
|
||||
self.on_end_transaction = lambda: self.output_data_block('Data', Ann.PP)
|
||||
self.data.append(mosi)
|
||||
self.cmdstate += 1
|
||||
|
||||
def handle_cp(self, mosi, miso):
|
||||
@@ -289,38 +378,52 @@ class Decoder(srd.Decoder):
|
||||
pass # TODO
|
||||
|
||||
def handle_rdp_res(self, mosi, miso):
|
||||
pass # TODO
|
||||
if self.cmdstate == 1:
|
||||
# Byte 1: Master sends command ID.
|
||||
self.emit_cmd_byte()
|
||||
elif self.cmdstate in (2, 3, 4):
|
||||
# Bytes 2/3/4: Master sends three dummy bytes.
|
||||
self.putx([Ann.FIELD, ['Dummy byte: %02x' % mosi]])
|
||||
elif self.cmdstate == 5:
|
||||
# Byte 5: Slave sends device ID.
|
||||
self.es_cmd = self.es
|
||||
self.device_id = miso
|
||||
self.putx([Ann.FIELD, ['Device ID: %s' % self.device()]])
|
||||
d = 'Device = %s' % self.vendor_device()
|
||||
self.putc([Ann.RDP_RES, self.cmd_vendor_dev_list()])
|
||||
self.state = None
|
||||
self.cmdstate += 1
|
||||
|
||||
def handle_rems(self, mosi, miso):
|
||||
if self.cmdstate == 1:
|
||||
# Byte 1: Master sends command ID.
|
||||
self.ss_block = self.ss
|
||||
self.putx([16, ['Command: %s' % cmds[self.state][1]]])
|
||||
self.emit_cmd_byte()
|
||||
elif self.cmdstate in (2, 3):
|
||||
# Bytes 2/3: Master sends two dummy bytes.
|
||||
# TODO: Check dummy bytes? Check reply from device?
|
||||
self.putx([24, ['Dummy byte: %s' % mosi]])
|
||||
self.putx([Ann.FIELD, ['Dummy byte: 0x%02x' % mosi]])
|
||||
elif self.cmdstate == 4:
|
||||
# Byte 4: Master sends 0x00 or 0x01.
|
||||
# 0x00: Master wants manufacturer ID as first reply byte.
|
||||
# 0x01: Master wants device ID as first reply byte.
|
||||
self.manufacturer_id_first = True if (mosi == 0x00) else False
|
||||
d = 'manufacturer' if (mosi == 0x00) else 'device'
|
||||
self.putx([24, ['Master wants %s ID first' % d]])
|
||||
self.putx([Ann.FIELD, ['Master wants %s ID first' % d]])
|
||||
elif self.cmdstate == 5:
|
||||
# Byte 5: Slave sends manufacturer ID (or device ID).
|
||||
self.ids = [miso]
|
||||
d = 'Manufacturer' if self.manufacturer_id_first else 'Device'
|
||||
self.putx([24, ['%s ID' % d]])
|
||||
self.putx([Ann.FIELD, ['%s ID: 0x%02x' % (d, miso)]])
|
||||
elif self.cmdstate == 6:
|
||||
# Byte 6: Slave sends device ID (or manufacturer ID).
|
||||
self.ids.append(miso)
|
||||
d = 'Manufacturer' if self.manufacturer_id_first else 'Device'
|
||||
self.putx([24, ['%s ID' % d]])
|
||||
d = 'Device' if self.manufacturer_id_first else 'Manufacturer'
|
||||
self.putx([Ann.FIELD, ['%s ID: 0x%02x' % (d, miso)]])
|
||||
|
||||
if self.cmdstate == 6:
|
||||
id = self.ids[1] if self.manufacturer_id_first else self.ids[0]
|
||||
self.putx([24, ['Device: Macronix %s' % device_name[id]]])
|
||||
self.device_id = id
|
||||
self.es_cmd = self.es
|
||||
self.putc([Ann.REMS, self.cmd_vendor_dev_list()])
|
||||
self.state = None
|
||||
else:
|
||||
self.cmdstate += 1
|
||||
@@ -346,34 +449,37 @@ class Decoder(srd.Decoder):
|
||||
def handle_dsry(self, mosi, miso):
|
||||
pass # TODO
|
||||
|
||||
def decode(self, ss, es, data):
|
||||
def output_data_block(self, label, idx):
|
||||
# Print accumulated block of data
|
||||
# (called on CS# de-assert via self.on_end_transaction callback).
|
||||
self.es_cmd = self.es # End on the CS# de-assert sample.
|
||||
if self.options['format'] == 'hex':
|
||||
s = ' '.join([('%02x' % b) for b in self.data])
|
||||
else:
|
||||
s = ''.join(map(chr, self.data))
|
||||
self.putf([Ann.FIELD, ['%s (%d bytes)' % (label, len(self.data))]])
|
||||
self.putc([idx, ['%s (addr 0x%06x, %d bytes): %s' % \
|
||||
(cmds[self.state][1], self.addr, len(self.data), s)]])
|
||||
|
||||
def decode(self, ss, es, data):
|
||||
ptype, mosi, miso = data
|
||||
|
||||
# if ptype == 'DATA':
|
||||
# self.putx([0, ['MOSI: 0x%02x, MISO: 0x%02x' % (mosi, miso)]])
|
||||
self.ss, self.es = ss, es
|
||||
|
||||
# if ptype == 'CS-CHANGE':
|
||||
# if mosi == 1 and miso == 0:
|
||||
# self.putx([0, ['Asserting CS#']])
|
||||
# elif mosi == 0 and miso == 1:
|
||||
# self.putx([0, ['De-asserting CS#']])
|
||||
if ptype == 'CS-CHANGE':
|
||||
self.end_current_transaction()
|
||||
|
||||
if ptype != 'DATA':
|
||||
return
|
||||
|
||||
self.ss, self.es = ss, es
|
||||
|
||||
# If we encountered a known chip command, enter the resp. state.
|
||||
if self.state is None:
|
||||
self.state = mosi
|
||||
self.cmdstate = 1
|
||||
|
||||
# Handle commands.
|
||||
if self.state in cmds:
|
||||
s = 'handle_%s' % cmds[self.state][0].lower().replace('/', '_')
|
||||
handle_reg = getattr(self, s)
|
||||
handle_reg(mosi, miso)
|
||||
else:
|
||||
self.putx([24, ['Unknown command: 0x%02x' % mosi]])
|
||||
try:
|
||||
self.cmd_handlers[self.state](mosi, miso)
|
||||
except KeyError:
|
||||
self.putx([Ann.BIT, ['Unknown command: 0x%02x' % mosi]])
|
||||
self.state = None
|
||||
|
||||
@@ -17,7 +17,8 @@
|
||||
## GNU General Public License for more details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License
|
||||
## along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
## along with this program; if not, write to the Free Software
|
||||
## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
##
|
||||
|
||||
'''
|
||||
|
||||
@@ -17,7 +17,8 @@
|
||||
## GNU General Public License for more details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License
|
||||
## along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
## along with this program; if not, write to the Free Software
|
||||
## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
##
|
||||
|
||||
import sigrokdecode as srd
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -141,8 +141,8 @@ class Decoder(srd.Decoder):
|
||||
self.request = {}
|
||||
self.request_id = 0
|
||||
self.transaction_state = 'IDLE'
|
||||
self.transaction_ss = None
|
||||
self.transaction_es = None
|
||||
self.ss_transaction = None
|
||||
self.es_transaction = None
|
||||
self.transaction_ep = None
|
||||
self.transaction_addr = None
|
||||
self.wrote_pcap_header = False
|
||||
@@ -182,7 +182,7 @@ class Decoder(srd.Decoder):
|
||||
addr = self.transaction_addr
|
||||
if not (addr, ep) in self.request:
|
||||
self.request[(addr, ep)] = {'setup_data': [], 'data': [],
|
||||
'type': None, 'ss': self.transaction_ss, 'es': None,
|
||||
'type': None, 'ss': self.ss_transaction, 'es': None,
|
||||
'id': self.request_id, 'addr': addr, 'ep': ep}
|
||||
self.request_id += 1
|
||||
request_started = 1
|
||||
@@ -192,16 +192,16 @@ class Decoder(srd.Decoder):
|
||||
if request['type'] in (None, 'BULK IN') and self.transaction_type == 'IN':
|
||||
request['type'] = 'BULK IN'
|
||||
request['data'] += self.transaction_data
|
||||
request['es'] = self.transaction_es
|
||||
request['es'] = self.es_transaction
|
||||
self.handle_request(request_started, request_end)
|
||||
elif request['type'] in (None, 'BULK OUT') and self.transaction_type == 'OUT':
|
||||
request['type'] = 'BULK OUT'
|
||||
request['data'] += self.transaction_data
|
||||
request['es'] = self.transaction_es
|
||||
request['es'] = self.es_transaction
|
||||
self.handle_request(request_started, request_end)
|
||||
|
||||
# CONTROL, SETUP stage
|
||||
elif request['type'] == None and self.transaction_type == 'SETUP':
|
||||
elif request['type'] is None and self.transaction_type == 'SETUP':
|
||||
request['setup_data'] = self.transaction_data
|
||||
request['wLength'] = struct.unpack('<H',
|
||||
bytes(self.transaction_data[6:8]))[0]
|
||||
@@ -223,11 +223,11 @@ class Decoder(srd.Decoder):
|
||||
|
||||
# CONTROL, STATUS stage
|
||||
elif request['type'] == 'SETUP IN' and self.transaction_type == 'OUT':
|
||||
request['es'] = self.transaction_es
|
||||
request['es'] = self.es_transaction
|
||||
self.handle_request(0, request_end)
|
||||
|
||||
elif request['type'] == 'SETUP OUT' and self.transaction_type == 'IN':
|
||||
request['es'] = self.transaction_es
|
||||
request['es'] = self.es_transaction
|
||||
self.handle_request(0, request_end)
|
||||
|
||||
else:
|
||||
@@ -306,12 +306,12 @@ class Decoder(srd.Decoder):
|
||||
if pname == 'SOF':
|
||||
return
|
||||
if self.transaction_state == 'TOKEN RECEIVED':
|
||||
transaction_timeout = self.transaction_es
|
||||
transaction_timeout = self.es_transaction
|
||||
# Token length is 35 bits, timeout is 16..18 bit times
|
||||
# (USB 2.0 7.1.19.1).
|
||||
transaction_timeout += int((self.transaction_es - self.transaction_ss) / 2)
|
||||
transaction_timeout += int((self.es_transaction - self.ss_transaction) / 2)
|
||||
if ss > transaction_timeout:
|
||||
self.transaction_es = transaction_timeout
|
||||
self.es_transaction = transaction_timeout
|
||||
self.handshake = 'timeout'
|
||||
self.handle_transfer()
|
||||
self.transaction_state = 'IDLE'
|
||||
@@ -323,8 +323,8 @@ class Decoder(srd.Decoder):
|
||||
|
||||
sync, pid, addr, ep, crc5 = pinfo
|
||||
self.transaction_data = []
|
||||
self.transaction_ss = ss
|
||||
self.transaction_es = es
|
||||
self.ss_transaction = ss
|
||||
self.es_transaction = es
|
||||
self.transaction_state = 'TOKEN RECEIVED'
|
||||
self.transaction_ep = ep
|
||||
self.transaction_addr = addr
|
||||
@@ -347,7 +347,7 @@ class Decoder(srd.Decoder):
|
||||
|
||||
self.handshake = pname
|
||||
self.transaction_state = 'IDLE'
|
||||
self.transaction_es = es
|
||||
self.es_transaction = es
|
||||
self.handle_transfer()
|
||||
|
||||
elif pname == 'PRE':
|
||||
|
||||
@@ -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 = []
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* This file is part of the libsigrokdecode project.
|
||||
*
|
||||
* Copyright (C) 2012 Bert Vermeulen <bert@biot.com>
|
||||
* Copyright (C) 2016 DreamSourceLab <support@dreamsourcelab.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -88,19 +89,19 @@ SRD_PRIV void srd_exception_catch(char **error, const char *format, ...)
|
||||
PyObject *py_mod, *py_func, *py_tracefmt;
|
||||
char *msg, *etype_name, *evalue_str, *tracefmt_str;
|
||||
const char *etype_name_fallback;
|
||||
char *final_msg;
|
||||
char *final_msg;
|
||||
|
||||
py_etype = py_evalue = py_etraceback = py_mod = py_func = NULL;
|
||||
|
||||
va_start(args, format);
|
||||
va_start(args, format);
|
||||
msg = g_strdup_vprintf(format, args);
|
||||
va_end(args);
|
||||
|
||||
PyErr_Fetch(&py_etype, &py_evalue, &py_etraceback);
|
||||
if (!py_etype) {
|
||||
/* No current exception, so just print the message. */
|
||||
final_msg = g_strjoin(":", msg, "unknown error", NULL);
|
||||
srd_err("%s.", final_msg);
|
||||
final_msg = g_strjoin(":", msg, "unknown error", NULL);
|
||||
srd_err("%s.", final_msg);
|
||||
goto cleanup;
|
||||
}
|
||||
PyErr_NormalizeException(&py_etype, &py_evalue, &py_etraceback);
|
||||
@@ -109,16 +110,16 @@ SRD_PRIV void srd_exception_catch(char **error, const char *format, ...)
|
||||
evalue_str = py_stringify(py_evalue);
|
||||
etype_name_fallback = (etype_name) ? etype_name : "(unknown exception)";
|
||||
|
||||
if (evalue_str)
|
||||
final_msg = g_strjoin(":", msg, etype_name_fallback, evalue_str, NULL);
|
||||
if (evalue_str)
|
||||
final_msg = g_strjoin(":", msg, etype_name_fallback, evalue_str, NULL);
|
||||
else
|
||||
final_msg = g_strjoin(":", msg, etype_name_fallback, NULL);
|
||||
|
||||
srd_err("%s.", final_msg);
|
||||
final_msg = g_strjoin(":", msg, etype_name_fallback, NULL);
|
||||
|
||||
g_free(evalue_str);
|
||||
g_free(etype_name);
|
||||
|
||||
srd_err("%s.", final_msg);
|
||||
|
||||
/* If there is no traceback object, we are done. */
|
||||
if (!py_etraceback)
|
||||
goto cleanup;
|
||||
@@ -147,8 +148,8 @@ SRD_PRIV void srd_exception_catch(char **error, const char *format, ...)
|
||||
}
|
||||
|
||||
cleanup:
|
||||
if (error)
|
||||
*error = g_strdup(final_msg);
|
||||
if (error)
|
||||
*error = g_strdup(final_msg);
|
||||
Py_XDECREF(py_func);
|
||||
Py_XDECREF(py_mod);
|
||||
Py_XDECREF(py_etraceback);
|
||||
@@ -159,5 +160,5 @@ cleanup:
|
||||
PyErr_Clear();
|
||||
|
||||
g_free(msg);
|
||||
g_free(final_msg);
|
||||
g_free(final_msg);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 2011 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
* Copyright (C) 2012 Bert Vermeulen <bert@biot.com>
|
||||
* Copyright (C) 2016 DreamSourceLab <support@dreamsourcelab.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -32,19 +33,19 @@
|
||||
/* Custom Python types: */
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
struct srd_decoder_inst *di;
|
||||
uint64_t start_samplenum;
|
||||
float itercnt;
|
||||
uint8_t **inbuf;
|
||||
const uint8_t *inbuf_const;
|
||||
uint64_t samplenum;
|
||||
PyObject *sample;
|
||||
PyObject_HEAD
|
||||
struct srd_decoder_inst *di;
|
||||
uint64_t start_samplenum;
|
||||
float itercnt;
|
||||
uint8_t **inbuf;
|
||||
const uint8_t *inbuf_const;
|
||||
uint64_t samplenum;
|
||||
PyObject *sample;
|
||||
|
||||
uint64_t exp_logic;
|
||||
int edge_index;
|
||||
uint64_t logic_mask;
|
||||
uint64_t cur_pos;
|
||||
uint64_t exp_logic;
|
||||
int edge_index;
|
||||
uint64_t logic_mask;
|
||||
uint64_t cur_pos;
|
||||
} srd_logic;
|
||||
|
||||
/* srd.c */
|
||||
@@ -61,7 +62,7 @@ SRD_PRIV struct srd_decoder_inst *srd_inst_find_by_obj( const GSList *stack,
|
||||
SRD_PRIV int srd_inst_start(struct srd_decoder_inst *di, char **error);
|
||||
SRD_PRIV int srd_inst_decode(const struct srd_decoder_inst *di, uint8_t chunk_type,
|
||||
uint64_t start_samplenum, uint64_t end_samplenum,
|
||||
const uint8_t **inbuf, const uint8_t *inbuf_const, char **error);
|
||||
const uint8_t **inbuf, const uint8_t *inbuf_const, char **error);
|
||||
SRD_PRIV void srd_inst_free(struct srd_decoder_inst *di);
|
||||
SRD_PRIV void srd_inst_free_all(struct srd_session *sess, GSList *stack);
|
||||
|
||||
@@ -111,7 +112,7 @@ SRD_PRIV GVariant *py_obj_to_variant(PyObject *py_obj);
|
||||
* will assume non-standard Microsoft printf syntax.
|
||||
*/
|
||||
SRD_PRIV void srd_exception_catch(char **error, const char *format, ...)
|
||||
__attribute__((__format__ (__gnu_printf__, 2, 3)));
|
||||
__attribute__((__format__ (__gnu_printf__, 2, 3)));
|
||||
#else
|
||||
SRD_PRIV void srd_exception_catch(char **error, const char *format, ...) G_GNUC_PRINTF(2, 3);
|
||||
#endif
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 2010 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
* Copyright (C) 2012 Bert Vermeulen <bert@biot.com>
|
||||
* Copyright (C) 2016 DreamSourceLab <support@dreamsourcelab.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -185,7 +186,7 @@ struct srd_decoder {
|
||||
* supported annotation output.
|
||||
*/
|
||||
GSList *annotations;
|
||||
GSList *ann_types;
|
||||
GSList *ann_types;
|
||||
|
||||
/**
|
||||
* List of annotation rows (row items: id, description, and a list
|
||||
@@ -222,8 +223,8 @@ struct srd_channel {
|
||||
char *desc;
|
||||
/** The index of the channel, i.e. its order in the list of channels. */
|
||||
int order;
|
||||
/** The type of the channel, such us: sclk/sdata/.../others */
|
||||
int type;
|
||||
/** The type of the channel, such us: sclk/sdata/.../others */
|
||||
int type;
|
||||
};
|
||||
|
||||
struct srd_decoder_option {
|
||||
@@ -242,18 +243,18 @@ struct srd_decoder_annotation_row {
|
||||
struct srd_decoder_inst {
|
||||
struct srd_decoder *decoder;
|
||||
struct srd_session *sess;
|
||||
void *py_inst;
|
||||
void *py_logic;
|
||||
void *py_inst;
|
||||
void *py_logic;
|
||||
char *inst_id;
|
||||
GSList *pd_output;
|
||||
int dec_num_channels;
|
||||
int *dec_channelmap;
|
||||
uint8_t *channel_samples;
|
||||
GSList *next_di;
|
||||
uint64_t cur_pos;
|
||||
uint64_t logic_mask;
|
||||
uint64_t exp_logic;
|
||||
int edge_index;
|
||||
uint64_t cur_pos;
|
||||
uint64_t logic_mask;
|
||||
uint64_t exp_logic;
|
||||
int edge_index;
|
||||
};
|
||||
|
||||
struct srd_pd_output {
|
||||
@@ -275,7 +276,7 @@ struct srd_proto_data {
|
||||
};
|
||||
struct srd_proto_data_annotation {
|
||||
int ann_class;
|
||||
int ann_type;
|
||||
int ann_type;
|
||||
char **ann_text;
|
||||
};
|
||||
struct srd_proto_data_binary {
|
||||
@@ -304,7 +305,7 @@ SRD_API int srd_session_metadata_set(struct srd_session *sess, int key,
|
||||
GVariant *data);
|
||||
SRD_API int srd_session_send(struct srd_session *sess, uint8_t chunk_type,
|
||||
uint64_t start_samplenum, uint64_t end_samplenum,
|
||||
const uint8_t **inbuf, const uint8_t *inbuf_const, char **error);
|
||||
const uint8_t **inbuf, const uint8_t *inbuf_const, char **error);
|
||||
SRD_API int srd_session_destroy(struct srd_session *sess);
|
||||
SRD_API int srd_pd_output_callback_add(struct srd_session *sess,
|
||||
int output_type, srd_pd_output_callback cb, void *cb_data);
|
||||
|
||||
@@ -17,9 +17,9 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "libsigrokdecode.h" /* First, so we avoid a _POSIX_C_SOURCE warning. */
|
||||
#include "libsigrokdecode-internal.h"
|
||||
#include "config.h"
|
||||
#include "libsigrokdecode-internal.h" /* First, so we avoid a _POSIX_C_SOURCE warning. */
|
||||
#include "libsigrokdecode.h"
|
||||
|
||||
/** @cond PRIVATE */
|
||||
|
||||
@@ -55,12 +55,11 @@ PyMODINIT_FUNC PyInit_sigrokdecode(void)
|
||||
if (PyModule_AddObject(mod, "Decoder", Decoder_type) < 0)
|
||||
goto err_out;
|
||||
|
||||
logic_type = srd_logic_type_new();
|
||||
if (!logic_type)
|
||||
goto err_out;
|
||||
if (PyModule_AddObject(mod, "srd_logic", logic_type) < 0) {
|
||||
goto err_out;
|
||||
}
|
||||
logic_type = srd_logic_type_new();
|
||||
if (!logic_type)
|
||||
goto err_out;
|
||||
if (PyModule_AddObject(mod, "srd_logic", logic_type) < 0)
|
||||
goto err_out;
|
||||
|
||||
/* Expose output types as symbols in the sigrokdecode module */
|
||||
if (PyModule_AddIntConstant(mod, "OUTPUT_ANN", SRD_OUTPUT_ANN) < 0)
|
||||
@@ -75,13 +74,13 @@ PyMODINIT_FUNC PyInit_sigrokdecode(void)
|
||||
if (PyModule_AddIntConstant(mod, "SRD_CONF_SAMPLERATE", SRD_CONF_SAMPLERATE) < 0)
|
||||
goto err_out;
|
||||
|
||||
srd_logic_type = logic_type;
|
||||
srd_logic_type = logic_type;
|
||||
mod_sigrokdecode = mod;
|
||||
|
||||
return mod;
|
||||
err_out:
|
||||
Py_XDECREF(mod);
|
||||
srd_exception_catch(NULL, "Failed to initialize module");
|
||||
srd_exception_catch(NULL, "Failed to initialize module");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 2010 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
* Copyright (C) 2013 Bert Vermeulen <bert@biot.com>
|
||||
* Copyright (C) 2016 DreamSourceLab <support@dreamsourcelab.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -117,7 +118,7 @@ SRD_API int srd_session_start(struct srd_session *sess, char **error)
|
||||
ret = SRD_OK;
|
||||
for (d = sess->di_list; d; d = d->next) {
|
||||
di = d->data;
|
||||
if ((ret = srd_inst_start(di, error)) != SRD_OK)
|
||||
if ((ret = srd_inst_start(di, error)) != SRD_OK)
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -232,7 +233,7 @@ SRD_API int srd_session_metadata_set(struct srd_session *sess, int key,
|
||||
*/
|
||||
SRD_API int srd_session_send(struct srd_session *sess, uint8_t chunk_type,
|
||||
uint64_t start_samplenum, uint64_t end_samplenum,
|
||||
const uint8_t **inbuf, const uint8_t *inbuf_const, char **error)
|
||||
const uint8_t **inbuf, const uint8_t *inbuf_const, char **error)
|
||||
{
|
||||
GSList *d;
|
||||
int ret;
|
||||
@@ -243,8 +244,8 @@ SRD_API int srd_session_send(struct srd_session *sess, uint8_t chunk_type,
|
||||
}
|
||||
|
||||
for (d = sess->di_list; d; d = d->next) {
|
||||
if ((ret = srd_inst_decode(d->data, chunk_type, start_samplenum,
|
||||
end_samplenum, inbuf, inbuf_const, error)) != SRD_OK)
|
||||
if ((ret = srd_inst_decode(d->data, chunk_type, start_samplenum,
|
||||
end_samplenum, inbuf, inbuf_const, error)) != SRD_OK)
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include "../libsigrokdecode.h" /* First, to avoid compiler warning. */
|
||||
#include <libsigrokdecode.h> /* First, to avoid compiler warning. */
|
||||
#include <stdlib.h>
|
||||
#include <check.h>
|
||||
#include "lib.h"
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include "../libsigrokdecode.h" /* First, to avoid compiler warning. */
|
||||
#include <libsigrokdecode.h> /* First, to avoid compiler warning. */
|
||||
#include <stdlib.h>
|
||||
#include <check.h>
|
||||
#include "lib.h"
|
||||
@@ -32,7 +32,7 @@ START_TEST(test_load_all)
|
||||
{
|
||||
int ret;
|
||||
|
||||
srd_init(DECODERS_DIR);
|
||||
srd_init(DECODERS_TESTDIR);
|
||||
ret = srd_decoder_load_all();
|
||||
fail_unless(ret == SRD_OK, "srd_decoder_load_all() failed: %d.", ret);
|
||||
srd_exit();
|
||||
@@ -61,7 +61,7 @@ START_TEST(test_load)
|
||||
{
|
||||
int ret;
|
||||
|
||||
srd_init(DECODERS_DIR);
|
||||
srd_init(DECODERS_TESTDIR);
|
||||
ret = srd_decoder_load("uart");
|
||||
fail_unless(ret == SRD_OK, "srd_decoder_load(uart) failed: %d.", ret);
|
||||
ret = srd_decoder_load("spi");
|
||||
@@ -78,7 +78,7 @@ END_TEST
|
||||
*/
|
||||
START_TEST(test_load_bogus)
|
||||
{
|
||||
srd_init(DECODERS_DIR);
|
||||
srd_init(DECODERS_TESTDIR);
|
||||
/* http://sigrok.org/bugzilla/show_bug.cgi?id=176 */
|
||||
fail_unless(srd_decoder_load(NULL) != SRD_OK);
|
||||
fail_unless(srd_decoder_load("") != SRD_OK);
|
||||
@@ -101,7 +101,7 @@ END_TEST
|
||||
*/
|
||||
START_TEST(test_load_valid_and_bogus)
|
||||
{
|
||||
srd_init(DECODERS_DIR);
|
||||
srd_init(DECODERS_TESTDIR);
|
||||
fail_unless(srd_decoder_load("") != SRD_OK);
|
||||
fail_unless(srd_decoder_load("uart") == SRD_OK);
|
||||
fail_unless(srd_decoder_load("") != SRD_OK);
|
||||
@@ -122,7 +122,7 @@ START_TEST(test_load_multiple)
|
||||
{
|
||||
int ret;
|
||||
|
||||
srd_init(DECODERS_DIR);
|
||||
srd_init(DECODERS_TESTDIR);
|
||||
ret = srd_decoder_load("uart");
|
||||
fail_unless(ret == SRD_OK, "Loading uart PD 1x failed: %d", ret);
|
||||
ret = srd_decoder_load("uart");
|
||||
@@ -149,13 +149,121 @@ START_TEST(test_load_nonexisting_pd_dir)
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/*
|
||||
* Check whether srd_decoder_unload_all() works.
|
||||
* If it returns != SRD_OK (or segfaults) this test will fail.
|
||||
*/
|
||||
START_TEST(test_unload_all)
|
||||
{
|
||||
int ret;
|
||||
|
||||
srd_init(DECODERS_TESTDIR);
|
||||
ret = srd_decoder_load_all();
|
||||
fail_unless(ret == SRD_OK, "srd_decoder_load_all() failed: %d.", ret);
|
||||
ret = srd_decoder_unload_all();
|
||||
fail_unless(ret == SRD_OK, "srd_decoder_unload_all() failed: %d.", ret);
|
||||
srd_exit();
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/*
|
||||
* Check whether srd_decoder_unload_all() works without prior srd_init().
|
||||
* If it returns != SRD_OK (or segfaults) this test will fail.
|
||||
*/
|
||||
START_TEST(test_unload_all_no_init)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = srd_decoder_unload_all();
|
||||
fail_unless(ret == SRD_OK, "srd_decoder_unload_all() failed: %d.", ret);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/*
|
||||
* Check whether srd_decoder_unload_all() works multiple times.
|
||||
* If it returns != SRD_OK (or segfaults) this test will fail.
|
||||
*/
|
||||
START_TEST(test_unload_all_multiple)
|
||||
{
|
||||
int ret, i;
|
||||
|
||||
srd_init(DECODERS_TESTDIR);
|
||||
for (i = 0; i < 10; i++) {
|
||||
ret = srd_decoder_load_all();
|
||||
fail_unless(ret == SRD_OK, "srd_decoder_load_all() failed: %d.", ret);
|
||||
ret = srd_decoder_unload_all();
|
||||
fail_unless(ret == SRD_OK, "srd_decoder_unload_all() failed: %d.", ret);
|
||||
}
|
||||
srd_exit();
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/*
|
||||
* Check whether srd_decoder_unload_all() works multiple times (no load).
|
||||
* If it returns != SRD_OK (or segfaults) this test will fail.
|
||||
*/
|
||||
START_TEST(test_unload_all_multiple_noload)
|
||||
{
|
||||
int ret, i;
|
||||
|
||||
srd_init(DECODERS_TESTDIR);
|
||||
for (i = 0; i < 10; i++) {
|
||||
ret = srd_decoder_unload_all();
|
||||
fail_unless(ret == SRD_OK, "srd_decoder_unload_all() failed: %d.", ret);
|
||||
}
|
||||
srd_exit();
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/*
|
||||
* Check whether srd_decoder_unload() works.
|
||||
* If it returns != SRD_OK (or segfaults) this test will fail.
|
||||
*/
|
||||
START_TEST(test_unload)
|
||||
{
|
||||
int ret;
|
||||
struct srd_decoder *dec;
|
||||
|
||||
srd_init(DECODERS_TESTDIR);
|
||||
ret = srd_decoder_load("uart");
|
||||
fail_unless(ret == SRD_OK, "srd_decoder_load(uart) failed: %d.", ret);
|
||||
dec = srd_decoder_get_by_id("uart");
|
||||
fail_unless(dec != NULL);
|
||||
ret = srd_decoder_unload(dec);
|
||||
fail_unless(ret == SRD_OK, "srd_decoder_unload() failed: %d.", ret);
|
||||
srd_exit();
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/*
|
||||
* Check whether srd_decoder_unload(NULL) fails.
|
||||
* If it returns SRD_OK (or segfaults) this test will fail.
|
||||
*/
|
||||
START_TEST(test_unload_null)
|
||||
{
|
||||
srd_init(DECODERS_TESTDIR);
|
||||
fail_unless(srd_decoder_unload(NULL) != SRD_OK);
|
||||
srd_exit();
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/*
|
||||
* Check whether srd_decoder_unload(NULL) fails without prior srd_init().
|
||||
* If it returns SRD_OK (or segfaults) this test will fail.
|
||||
*/
|
||||
START_TEST(test_unload_null_no_init)
|
||||
{
|
||||
fail_unless(srd_decoder_unload(NULL) != SRD_OK);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/*
|
||||
* Check whether srd_decoder_list() returns a non-empty list.
|
||||
* If it returns an empty list (or segfaults) this test will fail.
|
||||
*/
|
||||
START_TEST(test_decoder_list)
|
||||
{
|
||||
srd_init(DECODERS_DIR);
|
||||
srd_init(DECODERS_TESTDIR);
|
||||
srd_decoder_load_all();
|
||||
fail_unless(srd_decoder_list() != NULL);
|
||||
srd_exit();
|
||||
@@ -169,7 +277,7 @@ END_TEST
|
||||
*/
|
||||
START_TEST(test_decoder_list_no_load)
|
||||
{
|
||||
srd_init(DECODERS_DIR);
|
||||
srd_init(DECODERS_TESTDIR);
|
||||
fail_unless(srd_decoder_list() == NULL);
|
||||
srd_exit();
|
||||
}
|
||||
@@ -205,7 +313,7 @@ END_TEST
|
||||
*/
|
||||
START_TEST(test_decoder_list_correct_numbers)
|
||||
{
|
||||
srd_init(DECODERS_DIR);
|
||||
srd_init(DECODERS_TESTDIR);
|
||||
fail_unless(g_slist_length((GSList *)srd_decoder_list()) == 0);
|
||||
srd_decoder_load("spi");
|
||||
fail_unless(g_slist_length((GSList *)srd_decoder_list()) == 1);
|
||||
@@ -225,7 +333,7 @@ END_TEST
|
||||
*/
|
||||
START_TEST(test_get_by_id)
|
||||
{
|
||||
srd_init(DECODERS_DIR);
|
||||
srd_init(DECODERS_TESTDIR);
|
||||
srd_decoder_load("uart");
|
||||
fail_unless(srd_decoder_get_by_id("uart") != NULL);
|
||||
fail_unless(srd_decoder_get_by_id("can") == NULL);
|
||||
@@ -242,7 +350,7 @@ END_TEST
|
||||
*/
|
||||
START_TEST(test_get_by_id_multiple)
|
||||
{
|
||||
srd_init(DECODERS_DIR);
|
||||
srd_init(DECODERS_TESTDIR);
|
||||
srd_decoder_load("uart");
|
||||
fail_unless(srd_decoder_get_by_id("uart") != NULL);
|
||||
fail_unless(srd_decoder_get_by_id("uart") != NULL);
|
||||
@@ -258,7 +366,7 @@ END_TEST
|
||||
*/
|
||||
START_TEST(test_get_by_id_bogus)
|
||||
{
|
||||
srd_init(DECODERS_DIR);
|
||||
srd_init(DECODERS_TESTDIR);
|
||||
fail_unless(srd_decoder_get_by_id(NULL) == NULL);
|
||||
fail_unless(srd_decoder_get_by_id("") == NULL);
|
||||
fail_unless(srd_decoder_get_by_id(" ") == NULL);
|
||||
@@ -282,7 +390,7 @@ START_TEST(test_doc_get)
|
||||
{
|
||||
struct srd_decoder *dec;
|
||||
|
||||
srd_init(DECODERS_DIR);
|
||||
srd_init(DECODERS_TESTDIR);
|
||||
srd_decoder_load("uart");
|
||||
dec = srd_decoder_get_by_id("uart");
|
||||
fail_unless(srd_decoder_doc_get(dec) != NULL);
|
||||
@@ -297,7 +405,7 @@ END_TEST
|
||||
*/
|
||||
START_TEST(test_doc_get_null)
|
||||
{
|
||||
srd_init(DECODERS_DIR);
|
||||
srd_init(DECODERS_TESTDIR);
|
||||
fail_unless(srd_decoder_doc_get(NULL) == NULL);
|
||||
srd_exit();
|
||||
}
|
||||
@@ -322,6 +430,17 @@ Suite *suite_decoder(void)
|
||||
tcase_add_test(tc, test_load_nonexisting_pd_dir);
|
||||
suite_add_tcase(s, tc);
|
||||
|
||||
tc = tcase_create("unload");
|
||||
tcase_add_checked_fixture(tc, srdtest_setup, srdtest_teardown);
|
||||
tcase_add_test(tc, test_unload_all);
|
||||
tcase_add_test(tc, test_unload_all_no_init);
|
||||
tcase_add_test(tc, test_unload_all_multiple);
|
||||
tcase_add_test(tc, test_unload_all_multiple_noload);
|
||||
tcase_add_test(tc, test_unload);
|
||||
tcase_add_test(tc, test_unload_null);
|
||||
tcase_add_test(tc, test_unload_null_no_init);
|
||||
suite_add_tcase(s, tc);
|
||||
|
||||
tc = tcase_create("list");
|
||||
tcase_add_checked_fixture(tc, srdtest_setup, srdtest_teardown);
|
||||
tcase_add_test(tc, test_decoder_list);
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include "../libsigrokdecode.h" /* First, to avoid compiler warning. */
|
||||
#include <libsigrokdecode.h> /* First, to avoid compiler warning. */
|
||||
#include <stdlib.h>
|
||||
#include <check.h>
|
||||
#include "lib.h"
|
||||
@@ -33,7 +33,7 @@ START_TEST(test_inst_new)
|
||||
struct srd_session *sess;
|
||||
struct srd_decoder_inst *inst;
|
||||
|
||||
srd_init(DECODERS_DIR);
|
||||
srd_init(DECODERS_TESTDIR);
|
||||
srd_decoder_load("uart");
|
||||
srd_session_new(&sess);
|
||||
inst = srd_inst_new(sess, "uart", NULL);
|
||||
@@ -53,7 +53,7 @@ START_TEST(test_inst_new_multiple)
|
||||
|
||||
inst1 = inst2 = inst3 = NULL;
|
||||
|
||||
srd_init(DECODERS_DIR);
|
||||
srd_init(DECODERS_TESTDIR);
|
||||
srd_decoder_load_all();
|
||||
srd_session_new(&sess);
|
||||
|
||||
@@ -90,7 +90,7 @@ START_TEST(test_inst_option_set_empty)
|
||||
struct srd_decoder_inst *inst;
|
||||
GHashTable *options;
|
||||
|
||||
srd_init(DECODERS_DIR);
|
||||
srd_init(DECODERS_TESTDIR);
|
||||
srd_decoder_load_all();
|
||||
srd_session_new(&sess);
|
||||
inst = srd_inst_new(sess, "uart", NULL);
|
||||
@@ -114,7 +114,7 @@ START_TEST(test_inst_option_set_bogus)
|
||||
struct srd_decoder_inst *inst;
|
||||
GHashTable *options;
|
||||
|
||||
srd_init(DECODERS_DIR);
|
||||
srd_init(DECODERS_TESTDIR);
|
||||
srd_decoder_load_all();
|
||||
srd_session_new(&sess);
|
||||
inst = srd_inst_new(sess, "uart", NULL);
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include "../libsigrokdecode.h" /* First, to avoid compiler warning. */
|
||||
#include <libsigrokdecode.h> /* First, to avoid compiler warning. */
|
||||
#include <stdlib.h>
|
||||
#include <check.h>
|
||||
#include "lib.h"
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include "../libsigrokdecode-internal.h" /* First, to avoid compiler warning. */
|
||||
#include "../libsigrokdecode.h"
|
||||
#include <libsigrokdecode-internal.h> /* First, to avoid compiler warning. */
|
||||
#include <libsigrokdecode.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <check.h>
|
||||
|
||||
@@ -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')
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 2010 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
* Copyright (C) 2012 Bert Vermeulen <bert@biot.com>
|
||||
* Copyright (C) 2016 DreamSourceLab <support@dreamsourcelab.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -21,7 +22,6 @@
|
||||
#include "config.h"
|
||||
#include "libsigrokdecode-internal.h" /* First, so we avoid a _POSIX_C_SOURCE warning. */
|
||||
#include "libsigrokdecode.h"
|
||||
#include "config.h"
|
||||
/**
|
||||
* Import a Python module by name.
|
||||
*
|
||||
@@ -72,7 +72,7 @@ SRD_PRIV int py_attr_as_str(PyObject *py_obj, const char *attr, char **outstr)
|
||||
}
|
||||
|
||||
if (!(py_str = PyObject_GetAttrString(py_obj, attr))) {
|
||||
srd_exception_catch(NULL, "Failed to get attribute '%s'", attr);
|
||||
srd_exception_catch(NULL, "Failed to get attribute '%s'", attr);
|
||||
return SRD_ERR_PYTHON;
|
||||
}
|
||||
|
||||
@@ -125,22 +125,22 @@ SRD_PRIV int py_dictitem_as_str(PyObject *py_obj, const char *key,
|
||||
*/
|
||||
SRD_PRIV int py_dictitem_to_int(PyObject *py_obj, const char *key)
|
||||
{
|
||||
PyObject *py_value;
|
||||
long type;
|
||||
PyObject *py_value;
|
||||
long type;
|
||||
|
||||
if (!PyDict_Check(py_obj)) {
|
||||
srd_dbg("Object is not a dictionary.");
|
||||
return -1;
|
||||
}
|
||||
if (!PyDict_Check(py_obj)) {
|
||||
srd_dbg("Object is not a dictionary.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!(py_value = PyDict_GetItemString(py_obj, key))) {
|
||||
srd_dbg("Dictionary has no attribute '%s'.", key);
|
||||
return -1;
|
||||
}
|
||||
if (!(py_value = PyDict_GetItemString(py_obj, key))) {
|
||||
srd_dbg("Dictionary has no attribute '%s'.", key);
|
||||
return -1;
|
||||
}
|
||||
|
||||
type = PyLong_Check(py_value) ? PyLong_AsLong(py_value) : -1;
|
||||
type = PyLong_Check(py_value) ? PyLong_AsLong(py_value) : -1;
|
||||
|
||||
return type;
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -174,7 +174,7 @@ SRD_PRIV int py_str_as_str(PyObject *py_str, char **outstr)
|
||||
return SRD_OK;
|
||||
}
|
||||
}
|
||||
srd_exception_catch(NULL, "Failed to extract string");
|
||||
srd_exception_catch(NULL, "Failed to extract string");
|
||||
|
||||
return SRD_ERR_PYTHON;
|
||||
}
|
||||
@@ -205,7 +205,7 @@ SRD_PRIV int py_strseq_to_char(PyObject *py_strseq, char ***out_strv)
|
||||
|
||||
seq_len = PySequence_Size(py_strseq);
|
||||
if (seq_len < 0) {
|
||||
srd_exception_catch(NULL, "Failed to obtain sequence size");
|
||||
srd_exception_catch(NULL, "Failed to obtain sequence size");
|
||||
return SRD_ERR_PYTHON;
|
||||
}
|
||||
|
||||
@@ -242,7 +242,7 @@ SRD_PRIV int py_strseq_to_char(PyObject *py_strseq, char ***out_strv)
|
||||
|
||||
err_out:
|
||||
g_strfreev(strv);
|
||||
srd_exception_catch(NULL, "Failed to obtain string item");
|
||||
srd_exception_catch(NULL, "Failed to obtain string item");
|
||||
|
||||
return SRD_ERR_PYTHON;
|
||||
}
|
||||
@@ -272,7 +272,7 @@ SRD_PRIV GVariant *py_obj_to_variant(PyObject *py_obj)
|
||||
Py_DECREF(py_bytes);
|
||||
}
|
||||
if (!var)
|
||||
srd_exception_catch(NULL, "Failed to extract string value");
|
||||
srd_exception_catch(NULL, "Failed to extract string value");
|
||||
|
||||
} else if (PyLong_Check(py_obj)) { /* integer */
|
||||
int64_t val;
|
||||
@@ -281,7 +281,7 @@ SRD_PRIV GVariant *py_obj_to_variant(PyObject *py_obj)
|
||||
if (!PyErr_Occurred())
|
||||
var = g_variant_new_int64(val);
|
||||
else
|
||||
srd_exception_catch(NULL, "Failed to extract integer value");
|
||||
srd_exception_catch(NULL, "Failed to extract integer value");
|
||||
|
||||
} else if (PyFloat_Check(py_obj)) { /* float */
|
||||
double val;
|
||||
@@ -290,7 +290,7 @@ SRD_PRIV GVariant *py_obj_to_variant(PyObject *py_obj)
|
||||
if (!PyErr_Occurred())
|
||||
var = g_variant_new_double(val);
|
||||
else
|
||||
srd_exception_catch(NULL, "Failed to extract float value");
|
||||
srd_exception_catch(NULL, "Failed to extract float value");
|
||||
|
||||
} else {
|
||||
srd_err("Failed to extract value of unsupported type.");
|
||||
|
||||
Reference in New Issue
Block a user