From: Bert Vermeulen Date: Mon, 16 Dec 2013 00:31:46 +0000 (+0100) Subject: Code drop from DreamSourceLabs first source release. X-Git-Url: https://sigrok.org/gitaction?a=commitdiff_plain;h=refs%2Fheads%2Fdslogic;p=libsigrok.git Code drop from DreamSourceLabs first source release. --- diff --git a/Makefile.am b/Makefile.am index 68dbed53..52c9f0e4 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,5 +1,5 @@ ## -## This file is part of the libsigrok project. +## This file is part of the libsigrok4DSLogic project. ## ## Copyright (C) 2010-2012 Bert Vermeulen ## Copyright (C) 2012 Alexandru Gagniuc @@ -22,11 +22,11 @@ ACLOCAL_AMFLAGS = -I autostuff AM_CPPFLAGS = -I$(top_srcdir) -SUBDIRS = contrib hardware input output tests +SUBDIRS = hardware input output tests -lib_LTLIBRARIES = libsigrok.la +lib_LTLIBRARIES = libsigrok4DSLogic.la -libsigrok_la_SOURCES = \ +libsigrok4DSLogic_la_SOURCES = \ backend.c \ device.c \ session.c \ @@ -36,24 +36,25 @@ libsigrok_la_SOURCES = \ filter.c \ strutil.c \ log.c \ + trigger.c \ version.c \ error.c \ std.c -libsigrok_la_LIBADD = \ +libsigrok4DSLogic_la_LIBADD = \ $(LIBOBJS) \ - hardware/libsigrokhardware.la \ - input/libsigrokinput.la \ - output/libsigrokoutput.la + hardware/libsigrok4DSLogichardware.la \ + input/libsigrok4DSLogicinput.la \ + output/libsigrok4DSLogicoutput.la -libsigrok_la_LDFLAGS = $(SR_LIB_LDFLAGS) +libsigrok4DSLogic_la_LDFLAGS = $(SR_LIB_LDFLAGS) -library_includedir = $(includedir)/libsigrok +library_includedir = $(includedir)/libsigrok4DSLogic library_include_HEADERS = libsigrok.h proto.h version.h noinst_HEADERS = libsigrok-internal.h pkgconfigdir = $(libdir)/pkgconfig -pkgconfig_DATA = libsigrok.pc +pkgconfig_DATA = libsigrok4DSLogic.pc EXTRA_DIST = Doxyfile README.devices diff --git a/README b/README index 0e74f7b0..437294c4 100644 --- a/README +++ b/README @@ -1,6 +1,9 @@ ------------------------------------------------------------------------------- README ------------------------------------------------------------------------------- +libsigrok4DSLogic is a shared library which provides the basic API +for DSLogic hardware. +libsigrok4DSLogic is based on libsigrok, a shared library from the sigrok project. The sigrok project aims at creating a portable, cross-platform, Free/Libre/Open-Source signal analysis software suite that supports various @@ -38,23 +41,21 @@ Requirements - libzip >= 0.8 - libusb-1.0 >= 1.0.9 (optional, used by most drivers) - libftdi >= 0.16 (optional, used by some drivers) - - libudev >= 151 (optional, used by some drivers) - libasound / alsa-lib >= 1.0 (optional, only used by the alsa driver) - check >= 0.9.4 (optional, only needed to run unit tests) Building and installing ----------------------- +Get the libsigrok4DSLogic source code from: www.dreamsourcelab.com/download.html +In order to build it, run: -In order to get the libsigrok source code and build it, run: - - $ git clone git://sigrok.org/libsigrok $ cd libsigrok $ ./autogen.sh $ ./configure $ make -For installing libsigrok: +For installing libsigrok4DSLogic: $ make install @@ -63,24 +64,10 @@ See INSTALL or the following wiki page for more (OS-specific) instructions: http://sigrok.org/wiki/Building -Device-specific issues ----------------------- - -Please check README.devices for some notes and hints about device- or -driver-specific issues to be aware of. - - -Firmware --------- - -Some devices supported by libsigrok need a firmware to be uploaded before the -device can be used. See README.devices for details. - - Copyright and license --------------------- -libsigrok is licensed under the terms of the GNU General Public License +libsigrok4DSLogic is licensed under the terms of the GNU General Public License (GPL), version 3 or later. While some individual source code files are licensed under the GPLv2+, and @@ -109,4 +96,5 @@ Website ------- http://sigrok.org/wiki/Libsigrok + http://dreamsourcelab.com diff --git a/autogen.sh b/autogen.sh old mode 100755 new mode 100644 diff --git a/configure.ac b/configure.ac index e475f6fd..a54b23a4 100644 --- a/configure.ac +++ b/configure.ac @@ -27,8 +27,8 @@ m4_define([sr_package_version_minor], [2]) m4_define([sr_package_version_micro], [0]) m4_define([sr_package_version], [sr_package_version_major.sr_package_version_minor.sr_package_version_micro]) -AC_INIT([libsigrok], [sr_package_version], [sigrok-devel@lists.sourceforge.net], - [libsigrok], [http://www.sigrok.org]) +AC_INIT([libsigrok4DSLogic], [sr_package_version], [support@dreamsourcelab.com], + [libsigrok4DSLogic], [http://www.dreamsourcelab.com]) AC_CONFIG_HEADER([config.h]) AC_CONFIG_MACRO_DIR([autostuff]) AC_CONFIG_AUX_DIR([autostuff]) @@ -67,7 +67,7 @@ PKG_PROG_PKG_CONFIG([0.22]) # 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_CURRENT=1 -SR_LIB_VERSION_REVISION=0 +SR_LIB_VERSION_REVISION=2 SR_LIB_VERSION_AGE=0 SR_LIB_VERSION="$SR_LIB_VERSION_CURRENT:$SR_LIB_VERSION_REVISION:$SR_LIB_VERSION_AGE" SR_LIB_LDFLAGS="-version-info $SR_LIB_VERSION" @@ -77,126 +77,31 @@ AC_SUBST(SR_LIB_VERSION_AGE) AC_SUBST(SR_LIB_VERSION) AC_SUBST(SR_LIB_LDFLAGS) -# Hardware support '--enable' options. - AC_ARG_ENABLE(all-drivers, AC_HELP_STRING([--enable-all-drivers], - [enable all drivers by default [default=yes]]), - [HW_ENABLED_DEFAULT="$enableval"], - [HW_ENABLED_DEFAULT="yes"]) - -AC_ARG_ENABLE(agilent-dmm, AC_HELP_STRING([--enable-agilent-dmm], - [enable Agilent DMM support [default=yes]]), - [HW_AGILENT_DMM="$enableval"], - [HW_AGILENT_DMM=$HW_ENABLED_DEFAULT]) - -AC_ARG_ENABLE(alsa, AC_HELP_STRING([--enable-alsa], - [enable ALSA driver support [default=yes]]), - [HW_ALSA="$enableval"], - [HW_ALSA=$HW_ENABLED_DEFAULT]) - -AC_ARG_ENABLE(asix-sigma, AC_HELP_STRING([--enable-asix-sigma], - [enable ASIX SIGMA/SIGMA2 support [default=yes]]), - [LA_ASIX_SIGMA="$enableval"], - [LA_ASIX_SIGMA=$HW_ENABLED_DEFAULT]) - -AC_ARG_ENABLE(brymen-dmm, AC_HELP_STRING([--enable-brymen-dmm], - [enable Brymen DMM support [default=yes]]), - [HW_BRYMEN_DMM="$enableval"], - [HW_BRYMEN_DMM=$HW_ENABLED_DEFAULT]) - -AC_ARG_ENABLE(chronovu-la8, AC_HELP_STRING([--enable-chronovu-la8], - [enable ChronoVu LA8 support [default=yes]]), - [LA_CHRONOVU_LA8="$enableval"], - [LA_CHRONOVU_LA8=$HW_ENABLED_DEFAULT]) - -AC_ARG_ENABLE(colead-slm, AC_HELP_STRING([--enable-colead-slm], - [enable Colead SLM support [default=yes]]), - [HW_COLEAD_SLM="$enableval"], - [HW_COLEAD_SLM=$HW_ENABLED_DEFAULT]) + [enable all drivers by default [default=yes]]), + [HW_ENABLED_DEFAULT="$enableval"], + [HW_ENABLED_DEFAULT="yes"]) AC_ARG_ENABLE(demo, AC_HELP_STRING([--enable-demo], [enable demo driver support [default=yes]]), - [LA_DEMO="$enableval"], - [LA_DEMO=$HW_ENABLED_DEFAULT]) - -AC_ARG_ENABLE(fluke-dmm, AC_HELP_STRING([--enable-fluke-dmm], - [enable Fluke DMM support [default=yes]]), - [HW_FLUKE_DMM="$enableval"], - [HW_FLUKE_DMM=$HW_ENABLED_DEFAULT]) - -AC_ARG_ENABLE(fx2lafw, AC_HELP_STRING([--enable-fx2lafw], - [enable fx2lafw support (for FX2 LAs). [default=yes]]), - [LA_FX2LAFW="$enableval"], - [LA_FX2LAFW=$HW_ENABLED_DEFAULT]) - -AC_ARG_ENABLE(hantek-dso, AC_HELP_STRING([--enable-hantek-dso], - [enable Hantek DSO support [default=yes]]), - [HW_HANTEK_DSO="$enableval"], - [HW_HANTEK_DSO=$HW_ENABLED_DEFAULT]) - -AC_ARG_ENABLE(lascar-el-usb, AC_HELP_STRING([--enable-lascar-el-usb], - [enable Lascar EL-USB support [default=yes]]), - [HW_LASCAR_EL_USB="$enableval"], - [HW_LASCAR_EL_USB=$HW_ENABLED_DEFAULT]) - -AC_ARG_ENABLE(link-mso19, AC_HELP_STRING([--enable-link-mso19], - [enable Link Instruments MSO-19 support [default=yes]]), - [LA_LINK_MSO19="$enableval"], - [LA_LINK_MSO19=$HW_ENABLED_DEFAULT]) - -AC_ARG_ENABLE(mic-985xx, AC_HELP_STRING([--enable-mic-985xx], - [enable MIC 985xx support [default=yes]]), - [HW_MIC_985XX="$enableval"], - [HW_MIC_985XX=$HW_ENABLED_DEFAULT]) - -AC_ARG_ENABLE(nexus-osciprime, AC_HELP_STRING([--enable-nexus-osciprime], - [enable Nexus Osciprime support [default=yes]]), - [HW_NEXUS_OSCIPRIME="$enableval"], - [HW_NEXUS_OSCIPRIME=$HW_ENABLED_DEFAULT]) - -AC_ARG_ENABLE(ols, AC_HELP_STRING([--enable-ols], - [enable OpenBench Logic Sniffer (OLS) support [default=yes]]), - [LA_OLS="$enableval"], - [LA_OLS=$HW_ENABLED_DEFAULT]) - -AC_ARG_ENABLE(rigol-ds1xx2, AC_HELP_STRING([--enable-rigol-ds1xx2], - [enable Rigol DS1xx2 support [default=yes]]), - [HW_RIGOL_DS1XX2="$enableval"], - [HW_RIGOL_DS1XX2=$HW_ENABLED_DEFAULT]) - -AC_ARG_ENABLE(serial-dmm, AC_HELP_STRING([--enable-serial-dmm], - [enable serial DMM support [default=yes]]), - [HW_SERIAL_DMM="$enableval"], - [HW_SERIAL_DMM=$HW_ENABLED_DEFAULT]) - -AC_ARG_ENABLE(tondaj-sl-814, AC_HELP_STRING([--enable-tondaj-sl-814], - [enable Tondaj SL-814 support [default=yes]]), - [HW_TONDAJ_SL_814="$enableval"], - [HW_TONDAJ_SL_814=$HW_ENABLED_DEFAULT]) - -AC_ARG_ENABLE(uni-t-dmm, AC_HELP_STRING([--enable-uni-t-dmm], - [enable UNI-T DMM support [default=yes]]), - [HW_UNI_T_DMM="$enableval"], - [HW_UNI_T_DMM=$HW_ENABLED_DEFAULT]) - -AC_ARG_ENABLE(victor-dmm, AC_HELP_STRING([--enable-victor-dmm], - [enable victor-dmm support [default=yes]]), - [HW_VICTOR_DMM="$enableval"], - [HW_VICTOR_DMM=$HW_ENABLED_DEFAULT]) - -AC_ARG_ENABLE(zeroplus-logic-cube, - AC_HELP_STRING([--enable-zeroplus-logic-cube], - [enable ZEROPLUS Logic Cube support [default=yes]]), - [LA_ZEROPLUS_LOGIC_CUBE="$enableval"], - [LA_ZEROPLUS_LOGIC_CUBE=$HW_ENABLED_DEFAULT]) - + [HW_DEMO="$enableval"], + [HW_DEMO=$HW_ENABLED_DEFAULT]) # Checks for libraries. +case "$host" in +*mingw*) + # We need to link against the Winsock2 library for SCPI over TCP. + LIBS="$LIBS -lws2_32";; +esac + # This variable collects the pkg-config names of all detected libs. # It is then used to construct the "Requires.private:" field in the -# libsigrok.pc file. +# libsigrok4DSLogic.pc file. SR_PKGLIBS="" +# libm (the standard math library) is always needed. +AC_SEARCH_LIBS([pow], [m]) + # libglib-2.0 is always needed. Abort if it's not found. # Note: glib-2.0 is part of the libsigrok API (hard pkg-config requirement). # We require at least 2.32.0 due to e.g. g_variant_new_fixed_array(). @@ -204,10 +109,27 @@ AM_PATH_GLIB_2_0([2.32.0], [CFLAGS="$CFLAGS $GLIB_CFLAGS"; LIBS="$LIBS $GLIB_LIBS"]) # libzip is always needed. Abort if it's not found. -PKG_CHECK_MODULES([libzip], [libzip >= 0.8], +PKG_CHECK_MODULES([libzip], [libzip >= 0.10], [CFLAGS="$CFLAGS $libzip_CFLAGS"; LIBS="$LIBS $libzip_LIBS"; SR_PKGLIBS="$SR_PKGLIBS libzip"]) +# libserialport is only needed for some hardware drivers. Disable the +# respective drivers if it is not found. +PKG_CHECK_MODULES([libserialport], [libserialport >= 0.1.0], + [have_libserialport="yes"; CFLAGS="$CFLAGS $libserialport_CFLAGS"; + LIBS="$LIBS $libserialport_LIBS"; + SR_PKGLIBS="$SR_PKGLIBS libserialport"], + [have_libserialport="no"]) + +# Define HAVE_LIBSERIALPORT in config.h if we found libserialport. +if test "x$have_libserialport" != "xno"; then + AC_DEFINE_UNQUOTED(HAVE_LIBSERIALPORT, [1], + [Specifies whether we have libserialport.]) +fi + +# Serial port helper code is only compiled in if libserialport was found. +AM_CONDITIONAL(NEED_SERIAL, test "x$have_libserialport" != xno) + # libusb-1.0 is only needed for some hardware drivers. Disable the respective # drivers if it is not found. case "$host" in @@ -223,10 +145,7 @@ case "$host" in [have_libusb1_0="yes"; CFLAGS="$CFLAGS $libusb_CFLAGS"; LIBS="$LIBS $libusb_LIBS"; SR_PKGLIBS="$SR_PKGLIBS libusb-1.0"], - [have_libusb1_0="no"; LA_FX2LAFW="no"; HW_HANTEK_DSO="no"; - HW_LASCAR_EL_USB="no"; HW_NEXUS_OSCIPRIME="no"; - HW_UNI_T_DMM="no"; HW_VICTOR_DMM="no"; - LA_ZEROPLUS_LOGIC_CUBE="no"]) + [have_libusb1_0="no"]) # Define HAVE_LIBUSB_1_0 in config.h if we found libusb-1.0. if test "x$have_libusb1_0" != "xno"; then @@ -236,27 +155,7 @@ case "$host" in ;; esac -# USB + FX2 firmware helper code is only compiled in if libusb-1.0 was found. -AM_CONDITIONAL(NEED_USB, test "x$have_libusb1_0" != xno) - -# libftdi is only needed for some hardware drivers. Disable them if not found. -PKG_CHECK_MODULES([libftdi], [libftdi >= 0.16], - [CFLAGS="$CFLAGS $libftdi_CFLAGS"; - LIBS="$LIBS $libftdi_LIBS"; - SR_PKGLIBS="$SR_PKGLIBS libftdi"], - [LA_ASIX_SIGMA="no"; LA_CHRONOVU_LA8="no"]) -# libudev is only needed for some hardware drivers. Disable them if not found. -PKG_CHECK_MODULES([libudev], [libudev >= 151], - [CFLAGS="$CFLAGS $libudev_CFLAGS"; LIBS="$LIBS $libudev_LIBS"; - SR_PKGLIBS="$SR_PKGLIBS libudev"], - [LA_LINK_MSO19="no"]) - -# ALSA is only needed for some hardware drivers. Disable them if not found. -PKG_CHECK_MODULES([alsa], [alsa >= 1.0], - [CFLAGS="$CFLAGS $alsa_CFLAGS"; LIBS="$LIBS $alsa_LIBS"; - SR_PKGLIBS="$SR_PKGLIBS alsa"], - [HW_ALSA="no"]) # The Check unit testing framework is optional. Disable if not found. PKG_CHECK_MODULES([check], [check >= 0.9.4], @@ -264,135 +163,29 @@ PKG_CHECK_MODULES([check], [check >= 0.9.4], LIBS="$LIBS $check_LIBS"], [have_check="no"]) AM_CONDITIONAL(HAVE_CHECK, test x"$have_check" = "xyes") -# The Rigol DS1xx2 driver currently uses the Linux kernel usbtmc module -# (though it is planned to rewrite the driver to be portable later). -# Thus, it will be disabled for non-Linux builds for now. -case "$host" in -*linux*) - # Do nothing. Whether the driver is enabled is determined by the - # previous --enable-all-drivers/--disable-all-drivers and/or any - # --enable-rigol-ds1xx2/--disable-rigol-ds1xx2 options. - ;; -*) - # Disable the driver for builds that don't target Linux. - HW_RIGOL_DS1XX2="no" - ;; -esac +# The OLS driver uses serial port file descriptors directly, and therefore +# will not currently work on Windows. + AC_SUBST(SR_PKGLIBS) # Now set AM_CONDITIONALs and AC_DEFINEs for the enabled/disabled drivers. -AM_CONDITIONAL(HW_AGILENT_DMM, test x$HW_AGILENT_DMM = xyes) -if test "x$HW_AGILENT_DMM" = "xyes"; then - AC_DEFINE(HAVE_HW_AGILENT_DMM, 1, [Agilent DMM support]) -fi - -AM_CONDITIONAL(HW_ALSA, test x$HW_ALSA = xyes) -if test "x$HW_ALSA" = "xyes"; then - AC_DEFINE(HAVE_HW_ALSA, 1, [ALSA driver support]) -fi - -AM_CONDITIONAL(LA_ASIX_SIGMA, test x$LA_ASIX_SIGMA = xyes) -if test "x$LA_ASIX_SIGMA" = "xyes"; then - AC_DEFINE(HAVE_LA_ASIX_SIGMA, 1, [ASIX SIGMA/SIGMA2 support]) -fi - -AM_CONDITIONAL(HW_BRYMEN_DMM, test x$HW_BRYMEN_DMM = xyes) -if test "x$HW_BRYMEN_DMM" = "xyes"; then - AC_DEFINE(HAVE_HW_BRYMEN_DMM, 1, [Brymen DMM support]) -fi - -AM_CONDITIONAL(LA_CHRONOVU_LA8, test x$LA_CHRONOVU_LA8 = xyes) -if test "x$LA_CHRONOVU_LA8" = "xyes"; then - AC_DEFINE(HAVE_LA_CHRONOVU_LA8, 1, [ChronoVu LA8 support]) -fi -AM_CONDITIONAL(HW_COLEAD_SLM, test x$HW_COLEAD_SLM = xyes) -if test "x$HW_COLEAD_SLM" = "xyes"; then - AC_DEFINE(HAVE_HW_COLEAD_SLM, 1, [Colead SLM support]) -fi -AM_CONDITIONAL(LA_DEMO, test x$LA_DEMO = xyes) -if test "x$LA_DEMO" = "xyes"; then +AM_CONDITIONAL(HW_DEMO, test x$HW_DEMO = xyes) +if test "x$HW_DEMO" = "xyes"; then AC_DEFINE(HAVE_LA_DEMO, 1, [Demo driver support]) fi -AM_CONDITIONAL(HW_FLUKE_DMM, test x$HW_FLUKE_DMM = xyes) -if test "x$HW_FLUKE_DMM" = "xyes"; then - AC_DEFINE(HAVE_HW_FLUKE_DMM, 1, [Fluke DMM support]) -fi - -AM_CONDITIONAL(LA_FX2LAFW, test x$LA_FX2LAFW = xyes) -if test "x$LA_FX2LAFW" = "xyes"; then - AC_DEFINE(HAVE_LA_FX2LAFW, 1, [fx2lafw support]) -fi - -AM_CONDITIONAL(HW_HANTEK_DSO, test x$HW_HANTEK_DSO = xyes) -if test "x$HW_HANTEK_DSO" = "xyes"; then - AC_DEFINE(HAVE_HW_HANTEK_DSO, 1, [Hantek DSO support]) -fi - -AM_CONDITIONAL(HW_LASCAR_EL_USB, test x$HW_LASCAR_EL_USB = xyes) -if test "x$HW_LASCAR_EL_USB" = "xyes"; then - AC_DEFINE(HAVE_HW_LASCAR_EL_USB, 1, [Lascar EL-USB support]) -fi - -AM_CONDITIONAL(LA_LINK_MSO19, test x$LA_LINK_MSO19 = xyes) -if test "x$LA_LINK_MSO19" = "xyes"; then - AC_DEFINE(HAVE_LA_LINK_MSO19, 1, [Link Instruments MSO-19 support]) -fi - -AM_CONDITIONAL(HW_MIC_985XX, test x$HW_MIC_985XX = xyes) -if test "x$HW_MIC_985XX" = "xyes"; then - AC_DEFINE(HAVE_HW_MIC_985XX, 1, [MIC 985xx support]) -fi - -AM_CONDITIONAL(HW_NEXUS_OSCIPRIME, test x$HW_NEXUS_OSCIPRIME = xyes) -if test "x$HW_NEXUS_OSCIPRIME" = "xyes"; then - AC_DEFINE(HAVE_HW_NEXUS_OSCIPRIME, 1, [Nexus Osciprime support]) -fi -AM_CONDITIONAL(LA_OLS, test x$LA_OLS = xyes) -if test "x$LA_OLS" = "xyes"; then - AC_DEFINE(HAVE_LA_OLS, 1, [OpenBench Logic Sniffer (OLS) support]) -fi - -AM_CONDITIONAL(HW_RIGOL_DS1XX2, test x$HW_RIGOL_DS1XX2 = xyes) -if test "x$HW_RIGOL_DS1XX2" = "xyes"; then - AC_DEFINE(HAVE_HW_RIGOL_DS1XX2, 1, [Rigol DS1xx2 support]) -fi - -AM_CONDITIONAL(HW_SERIAL_DMM, test x$HW_SERIAL_DMM = xyes) -if test "x$HW_SERIAL_DMM" = "xyes"; then - AC_DEFINE(HAVE_HW_SERIAL_DMM, 1, [Serial DMM support]) -fi - -AM_CONDITIONAL(HW_TONDAJ_SL_814, test x$HW_TONDAJ_SL_814 = xyes) -if test "x$HW_TONDAJ_SL_814" = "xyes"; then - AC_DEFINE(HAVE_HW_TONDAJ_SL_814, 1, [Tondaj SL-814 support]) -fi - -AM_CONDITIONAL(HW_UNI_T_DMM, test x$HW_UNI_T_DMM = xyes) -if test "x$HW_UNI_T_DMM" = "xyes"; then - AC_DEFINE(HAVE_HW_UNI_T_DMM, 1, [UNI-T DMM support]) -fi - -AM_CONDITIONAL(HW_VICTOR_DMM, test x$HW_VICTOR_DMM = xyes) -if test "x$HW_VICTOR_DMM" = "xyes"; then - AC_DEFINE(HAVE_HW_VICTOR_DMM, 1, [Victor DMM support]) -fi - -AM_CONDITIONAL(LA_ZEROPLUS_LOGIC_CUBE, test x$LA_ZEROPLUS_LOGIC_CUBE = xyes) -if test "x$LA_ZEROPLUS_LOGIC_CUBE" = "xyes"; then - AC_DEFINE(HAVE_LA_ZEROPLUS_LOGIC_CUBE, 1, [ZEROPLUS Logic Cube support]) -fi # Checks for header files. # These are already checked: inttypes.h stdint.h stdlib.h string.h unistd.h. AC_CHECK_HEADERS([fcntl.h sys/time.h termios.h]) # Checks for typedefs, structures, and compiler characteristics. +AC_C_BIGENDIAN AC_C_INLINE AC_TYPE_INT8_T AC_TYPE_INT16_T @@ -422,34 +215,11 @@ AC_SUBST(SR_PACKAGE_VERSION_MICRO) AC_SUBST(SR_PACKAGE_VERSION) AC_CONFIG_FILES([Makefile version.h hardware/Makefile - hardware/agilent-dmm/Makefile - hardware/alsa/Makefile - hardware/asix-sigma/Makefile - hardware/brymen-dmm/Makefile - hardware/chronovu-la8/Makefile - hardware/colead-slm/Makefile - hardware/common/Makefile - hardware/lascar-el-usb/Makefile - hardware/mic-985xx/Makefile - hardware/nexus-osciprime/Makefile - hardware/rigol-ds1xx2/Makefile - hardware/tondaj-sl-814/Makefile - hardware/victor-dmm/Makefile - hardware/common/dmm/Makefile hardware/demo/Makefile - hardware/fluke-dmm/Makefile - hardware/fx2lafw/Makefile - hardware/hantek-dso/Makefile - hardware/link-mso19/Makefile - hardware/openbench-logic-sniffer/Makefile - hardware/serial-dmm/Makefile - hardware/uni-t-dmm/Makefile - hardware/zeroplus-logic-cube/Makefile input/Makefile output/Makefile output/text/Makefile - libsigrok.pc - contrib/Makefile + libsigrok4DSLogic.pc tests/Makefile ]) @@ -468,7 +238,7 @@ echo "Detected libraries:" echo # Note: This only works for libs with pkg-config integration. -for lib in "glib-2.0 >= 2.32.0" "libzip >= 0.8" "libusb-1.0 >= 1.0.9" "libftdi >= 0.16" "libudev >= 151" "alsa >= 1.0" "check >= 0.9.4"; do +for lib in "glib-2.0 >= 2.32.0" "libzip >= 0.10" "libserialport >= 0.1.0" "libusb-1.0 >= 1.0.9" "libftdi >= 0.16" "libudev >= 151" "alsa >= 1.0" "check >= 0.9.4"; do if `$PKG_CONFIG --exists $lib`; then ver=`$PKG_CONFIG --modversion $lib` answer="yes ($ver)" @@ -479,26 +249,6 @@ for lib in "glib-2.0 >= 2.32.0" "libzip >= 0.8" "libusb-1.0 >= 1.0.9" "libftdi > done echo -e "\nEnabled hardware drivers:\n" -echo " - agilent-dmm..................... $HW_AGILENT_DMM" -echo " - alsa............................ $HW_ALSA" -echo " - asix-sigma...................... $LA_ASIX_SIGMA" -echo " - brymen-dmm...................... $HW_BRYMEN_DMM" -echo " - chronovu-la8.................... $LA_CHRONOVU_LA8" -echo " - colead-slm...................... $HW_COLEAD_SLM" -echo " - demo............................ $LA_DEMO" -echo " - fluke-dmm....................... $HW_FLUKE_DMM" -echo " - fx2lafw......................... $LA_FX2LAFW" -echo " - hantek-dso...................... $HW_HANTEK_DSO" -echo " - lascar-el-usb................... $HW_LASCAR_EL_USB" -echo " - link-mso19...................... $LA_LINK_MSO19" -echo " - mic-985xx....................... $HW_MIC_985XX" -echo " - nexus-osciprime................. $HW_NEXUS_OSCIPRIME" -echo " - openbench-logic-sniffer......... $LA_OLS" -echo " - rigol-ds1xx2.................... $HW_RIGOL_DS1XX2" -echo " - serial-dmm...................... $HW_SERIAL_DMM" -echo " - tondaj-sl-814................... $HW_TONDAJ_SL_814" -echo " - uni-t-dmm....................... $HW_UNI_T_DMM" -echo " - victor-dmm...................... $HW_VICTOR_DMM" -echo " - zeroplus-logic-cube............. $LA_ZEROPLUS_LOGIC_CUBE" +echo " - demo............................ $HW_DEMO" echo diff --git a/device.c b/device.c index a49faa8d..cca0bcd3 100644 --- a/device.c +++ b/device.c @@ -225,7 +225,7 @@ SR_API gboolean sr_dev_has_option(const struct sr_dev_inst *sdi, int key) } /** @private */ -SR_PRIV struct sr_dev_inst *sr_dev_inst_new(int index, int status, +SR_PRIV struct sr_dev_inst *sr_dev_inst_new(int mode, int index, int status, const char *vendor, const char *model, const char *version) { struct sr_dev_inst *sdi; @@ -236,6 +236,7 @@ SR_PRIV struct sr_dev_inst *sr_dev_inst_new(int index, int status, } sdi->driver = NULL; + sdi->mode = mode; sdi->index = index; sdi->status = status; sdi->inst_type = -1; @@ -250,6 +251,20 @@ SR_PRIV struct sr_dev_inst *sr_dev_inst_new(int index, int status, } /** @private */ +SR_PRIV void sr_dev_probes_free(struct sr_dev_inst *sdi) +{ + struct sr_probe *probe; + GSList *l; + + for (l = sdi->probes; l; l = l->next) { + probe = l->data; + g_free(probe->name); + g_free(probe); + } + + sdi->probes = NULL; +} + SR_PRIV void sr_dev_inst_free(struct sr_dev_inst *sdi) { struct sr_probe *probe; diff --git a/hardware/Makefile.am b/hardware/Makefile.am index 3c093b76..4f5d0a7b 100644 --- a/hardware/Makefile.am +++ b/hardware/Makefile.am @@ -19,117 +19,14 @@ ## SUBDIRS = \ - agilent-dmm \ - alsa \ - asix-sigma \ - brymen-dmm \ - chronovu-la8 \ - colead-slm \ - common \ - demo \ - fluke-dmm \ - fx2lafw \ - hantek-dso \ - lascar-el-usb \ - link-mso19 \ - mic-985xx \ - nexus-osciprime \ - openbench-logic-sniffer \ - rigol-ds1xx2 \ - serial-dmm \ - tondaj-sl-814 \ - uni-t-dmm \ - victor-dmm \ - zeroplus-logic-cube + demo -noinst_LTLIBRARIES = libsigrokhardware.la +noinst_LTLIBRARIES = libsigrok4DSLogichardware.la -libsigrokhardware_la_SOURCES = +libsigrok4DSLogichardware_la_SOURCES = -libsigrokhardware_la_LIBADD = \ - common/libsigrokhwcommon.la +libsigrok4DSLogichardware_la_LIBADD = -if HW_AGILENT_DMM -libsigrokhardware_la_LIBADD += agilent-dmm/libsigrokhwagilentdmm.la +if HW_DEMO +libsigrok4DSLogichardware_la_LIBADD += demo/libsigrok4DSLogic_hw_demo.la endif - -if HW_ALSA -libsigrokhardware_la_LIBADD += alsa/libsigrokhwalsa.la -endif - -if LA_ASIX_SIGMA -libsigrokhardware_la_LIBADD += asix-sigma/libsigrokhwasixsigma.la -endif - -if HW_BRYMEN_DMM -libsigrokhardware_la_LIBADD += brymen-dmm/libsigrok_hw_brymen_dmm.la -endif - -if LA_CHRONOVU_LA8 -libsigrokhardware_la_LIBADD += chronovu-la8/libsigrokhwchronovula8.la -endif - -if HW_COLEAD_SLM -libsigrokhardware_la_LIBADD += colead-slm/libsigrok_hw_colead_slm.la -endif - -if LA_DEMO -libsigrokhardware_la_LIBADD += demo/libsigrokhwdemo.la -endif - -if HW_FLUKE_DMM -libsigrokhardware_la_LIBADD += fluke-dmm/libsigrokhwflukedmm.la -endif - -if LA_FX2LAFW -libsigrokhardware_la_LIBADD += fx2lafw/libsigrokhwfx2lafw.la -endif - -if HW_HANTEK_DSO -libsigrokhardware_la_LIBADD += hantek-dso/libsigrokhw_hantek_dso.la -endif - -if HW_LASCAR_EL_USB -libsigrokhardware_la_LIBADD += lascar-el-usb/libsigrok_hw_lascar_el_usb.la -endif - -if LA_LINK_MSO19 -libsigrokhardware_la_LIBADD += link-mso19/libsigrokhwlinkmso19.la -endif - -if HW_MIC_985XX -libsigrokhardware_la_LIBADD += mic-985xx/libsigrok_hw_mic_985xx.la -endif - -if HW_NEXUS_OSCIPRIME -libsigrokhardware_la_LIBADD += nexus-osciprime/libsigrok_hw_nexus_osciprime.la -endif - -if LA_OLS -libsigrokhardware_la_LIBADD += openbench-logic-sniffer/libsigrokhwols.la -endif - -if HW_RIGOL_DS1XX2 -libsigrokhardware_la_LIBADD += rigol-ds1xx2/libsigrok_hw_rigol_ds1xx2.la -endif - -if HW_SERIAL_DMM -libsigrokhardware_la_LIBADD += serial-dmm/libsigrokhwserialdmm.la -endif - -if HW_TONDAJ_SL_814 -libsigrokhardware_la_LIBADD += tondaj-sl-814/libsigrok_hw_tondaj_sl_814.la -endif - -if HW_UNI_T_DMM -libsigrokhardware_la_LIBADD += uni-t-dmm/libsigrok_hw_uni_t_dmm.la -endif - -if HW_VICTOR_DMM -libsigrokhardware_la_LIBADD += victor-dmm/libsigrok_hw_victor_dmm.la -endif - -if LA_ZEROPLUS_LOGIC_CUBE -libsigrokhardware_la_LIBADD += zeroplus-logic-cube/libsigrokhwzeroplus.la -endif - diff --git a/hardware/demo/Makefile.am b/hardware/demo/Makefile.am index d1759914..9bb85dd7 100644 --- a/hardware/demo/Makefile.am +++ b/hardware/demo/Makefile.am @@ -17,15 +17,15 @@ ## along with this program. If not, see . ## -if LA_DEMO +if HW_DEMO # Local lib, this is NOT meant to be installed! -noinst_LTLIBRARIES = libsigrokhwdemo.la +noinst_LTLIBRARIES = libsigrok4DSLogic_hw_demo.la -libsigrokhwdemo_la_SOURCES = \ +libsigrok4DSLogic_hw_demo_la_SOURCES = \ demo.c -libsigrokhwdemo_la_CFLAGS = \ +libsigrok4DSLogic_hw_demo_la_CFLAGS = \ -I$(top_srcdir) endif diff --git a/hardware/demo/demo.c b/hardware/demo/demo.c index 98c95457..67df85e4 100644 --- a/hardware/demo/demo.c +++ b/hardware/demo/demo.c @@ -23,6 +23,7 @@ #include #include #include +#include #ifdef _WIN32 #include #include @@ -41,42 +42,34 @@ #define sr_err(s, args...) sr_err(LOG_PREFIX s, ## args) /* TODO: Number of probes should be configurable. */ -#define NUM_PROBES 8 +#define NUM_PROBES 16 #define DEMONAME "Demo device" /* The size of chunks to send through the session bus. */ /* TODO: Should be configurable. */ -#define BUFSIZE 4096 +#define BUFSIZE 1024*1024 -#define STR_PATTERN_SIGROK "sigrok" -#define STR_PATTERN_RANDOM "random" -#define STR_PATTERN_INC "incremental" -#define STR_PATTERN_ALL_LOW "all-low" -#define STR_PATTERN_ALL_HIGH "all-high" +#define PERIOD 4000 -/* Supported patterns which we can generate */ -enum { - /** - * Pattern which spells "sigrok" using '0's (with '1's as "background") - * when displayed using the 'bits' output format. - */ - PATTERN_SIGROK, - - /** Pattern which consists of (pseudo-)random values on all probes. */ - PATTERN_RANDOM, - - /** - * Pattern which consists of incrementing numbers. - * TODO: Better description. - */ - PATTERN_INC, +#define PI 3.14159265 - /** Pattern where all probes have a low logic state. */ - PATTERN_ALL_LOW, +#define CONST_LEN 50 - /** Pattern where all probes have a high logic state. */ - PATTERN_ALL_HIGH, +/* Supported patterns which we can generate */ +enum { + PATTERN_SINE = 0, + PATTERN_SQUARE = 1, + PATTERN_TRIANGLE = 2, + PATTERN_SAWTOOTH = 3, + PATTERN_RANDOM = 4, +}; +static const char *pattern_strings[] = { + "Sine", + "Square", + "Triangle", + "Sawtooth", + "Random", }; /* Private, per-device-instance driver context. */ @@ -91,6 +84,12 @@ struct dev_context { uint64_t samples_counter; void *cb_data; int64_t starttime; + int stop; + + int trigger_stage; + uint16_t trigger_mask; + uint16_t trigger_value; + uint16_t trigger_edge; }; static const int hwcaps[] = { @@ -103,37 +102,38 @@ static const int hwcaps[] = { SR_CONF_CONTINUOUS, }; -static const uint64_t samplerates[] = { - SR_HZ(1), - SR_GHZ(1), - SR_HZ(1), +static const int hwoptions[] = { + SR_CONF_PATTERN_MODE, }; -static const char *pattern_strings[] = { - "sigrok", - "random", - "incremental", - "all-low", - "all-high", +static const uint64_t samplerates[] = { + SR_KHZ(10), + SR_KHZ(20), + SR_KHZ(50), + SR_KHZ(100), + SR_KHZ(200), + SR_KHZ(500), + SR_MHZ(1), + SR_MHZ(2), + SR_MHZ(5), + SR_MHZ(10), + SR_MHZ(20), + SR_MHZ(50), + SR_MHZ(100), + SR_MHZ(200), }; + + /* We name the probes 0-7 on our demo driver. */ static const char *probe_names[NUM_PROBES + 1] = { - "0", "1", "2", "3", "4", "5", "6", "7", + "Channel 0", "Channel 1", "Channel 2", "Channel 3", + "Channel 4", "Channel 5", "Channel 6", "Channel 7", + "Channel 8", "Channel 9", "Channel 10", "Channel 11", + "Channel 12", "Channel 13", "Channel 14", "Channel 15", NULL, }; -static uint8_t pattern_sigrok[] = { - 0x4c, 0x92, 0x92, 0x92, 0x64, 0x00, 0x00, 0x00, - 0x82, 0xfe, 0xfe, 0x82, 0x00, 0x00, 0x00, 0x00, - 0x7c, 0x82, 0x82, 0x92, 0x74, 0x00, 0x00, 0x00, - 0xfe, 0x12, 0x12, 0x32, 0xcc, 0x00, 0x00, 0x00, - 0x7c, 0x82, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00, - 0xfe, 0x10, 0x28, 0x44, 0x82, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xbe, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; - /* Private, per-device-instance driver context. */ /* TODO: struct context as with the other drivers. */ @@ -141,6 +141,8 @@ static uint8_t pattern_sigrok[] = { SR_PRIV struct sr_dev_driver demo_driver_info; static struct sr_dev_driver *di = &demo_driver_info; +extern struct ds_trigger *trigger; + static int hw_dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data); static int clear_instances(void) @@ -170,20 +172,13 @@ static GSList *hw_scan(GSList *options) devices = NULL; - sdi = sr_dev_inst_new(0, SR_ST_ACTIVE, DEMONAME, NULL, NULL); + sdi = sr_dev_inst_new(LOGIC, 0, SR_ST_ACTIVE, DEMONAME, NULL, NULL); if (!sdi) { - sr_err("Device instance creation failed."); + sr_err("Device instance creation failed."); return NULL; } sdi->driver = di; - for (i = 0; probe_names[i]; i++) { - if (!(probe = sr_probe_new(i, SR_PROBE_LOGIC, TRUE, - probe_names[i]))) - return NULL; - sdi->probes = g_slist_append(sdi->probes, probe); - } - devices = g_slist_append(devices, sdi); drvc->instances = g_slist_append(drvc->instances, sdi); @@ -193,13 +188,29 @@ static GSList *hw_scan(GSList *options) } devc->sdi = sdi; - devc->cur_samplerate = SR_KHZ(200); + devc->cur_samplerate = SR_MHZ(200); devc->limit_samples = 0; devc->limit_msec = 0; - devc->sample_generator = PATTERN_SIGROK; + devc->sample_generator = PATTERN_SINE; sdi->priv = devc; + if (sdi->mode == LOGIC) { + for (i = 0; probe_names[i]; i++) { + if (!(probe = sr_probe_new(i, SR_PROBE_LOGIC, TRUE, + probe_names[i]))) + return NULL; + sdi->probes = g_slist_append(sdi->probes, probe); + } + } else if (sdi->mode == ANALOG) { + for (i = 0; i < DS_MAX_ANALOG_PROBES_NUM; i++) { + if (!(probe = sr_probe_new(i, SR_PROBE_ANALOG, TRUE, + probe_names[i]))) + return NULL; + sdi->probes = g_slist_append(sdi->probes, probe); + } + } + return devices; } @@ -266,24 +277,11 @@ static int config_get(int id, GVariant **data, const struct sr_dev_inst *sdi) case SR_CONF_LIMIT_MSEC: *data = g_variant_new_uint64(devc->limit_msec); break; - case SR_CONF_PATTERN_MODE: - switch (devc->sample_generator) { - case PATTERN_SIGROK: - *data = g_variant_new_string(STR_PATTERN_SIGROK); - break; - case PATTERN_RANDOM: - *data = g_variant_new_string(STR_PATTERN_RANDOM); - break; - case PATTERN_INC: - *data = g_variant_new_string(STR_PATTERN_INC); - break; - case PATTERN_ALL_LOW: - *data = g_variant_new_string(STR_PATTERN_ALL_LOW); - break; - case PATTERN_ALL_HIGH: - *data = g_variant_new_string(STR_PATTERN_ALL_HIGH); - break; - } + case SR_CONF_DEVICE_MODE: + *data = g_variant_new_string(mode_strings[sdi->mode]); + break; + case SR_CONF_PATTERN_MODE: + *data = g_variant_new_string(pattern_strings[devc->sample_generator]); break; default: return SR_ERR_NA; @@ -292,10 +290,11 @@ static int config_get(int id, GVariant **data, const struct sr_dev_inst *sdi) return SR_OK; } -static int config_set(int id, GVariant *data, const struct sr_dev_inst *sdi) +static int config_set(int id, GVariant *data, struct sr_dev_inst *sdi) { - int ret; + int i, ret; const char *stropt; + struct sr_probe *probe; struct dev_context *const devc = sdi->priv; @@ -318,27 +317,54 @@ static int config_set(int id, GVariant *data, const struct sr_dev_inst *sdi) devc->limit_samples = 0; sr_dbg("%s: setting limit_msec to %" PRIu64, __func__, devc->limit_msec); - ret = SR_OK; - } else if (id == SR_CONF_PATTERN_MODE) { + ret = SR_OK; + } else if (id == SR_CONF_DEVICE_MODE) { + stropt = g_variant_get_string(data, NULL); + ret = SR_OK; + if (!strcmp(stropt, mode_strings[LOGIC])) { + sdi->mode = LOGIC; + sr_dev_probes_free(sdi); + for (i = 0; probe_names[i]; i++) { + if (!(probe = sr_probe_new(i, SR_PROBE_LOGIC, TRUE, + probe_names[i]))) + ret = SR_ERR; + else + sdi->probes = g_slist_append(sdi->probes, probe); + } + } else if (!strcmp(stropt, mode_strings[ANALOG])) { + sdi->mode = ANALOG; + sr_dev_probes_free(sdi); + for (i = 0; i < DS_MAX_ANALOG_PROBES_NUM; i++) { + if (!(probe = sr_probe_new(i, SR_PROBE_ANALOG, TRUE, + probe_names[i]))) + ret = SR_ERR; + else + sdi->probes = g_slist_append(sdi->probes, probe); + } + } else { + ret = SR_ERR; + } + sr_dbg("%s: setting mode to %d", __func__, sdi->mode); + }else if (id == SR_CONF_PATTERN_MODE) { stropt = g_variant_get_string(data, NULL); - ret = SR_OK; - if (!strcmp(stropt, STR_PATTERN_SIGROK)) { - devc->sample_generator = PATTERN_SIGROK; - } else if (!strcmp(stropt, STR_PATTERN_RANDOM)) { - devc->sample_generator = PATTERN_RANDOM; - } else if (!strcmp(stropt, STR_PATTERN_INC)) { - devc->sample_generator = PATTERN_INC; - } else if (!strcmp(stropt, STR_PATTERN_ALL_LOW)) { - devc->sample_generator = PATTERN_ALL_LOW; - } else if (!strcmp(stropt, STR_PATTERN_ALL_HIGH)) { - devc->sample_generator = PATTERN_ALL_HIGH; + ret = SR_OK; + if (!strcmp(stropt, pattern_strings[PATTERN_SINE])) { + devc->sample_generator = PATTERN_SINE; + } else if (!strcmp(stropt, pattern_strings[PATTERN_SQUARE])) { + devc->sample_generator = PATTERN_SQUARE; + } else if (!strcmp(stropt, pattern_strings[PATTERN_TRIANGLE])) { + devc->sample_generator = PATTERN_TRIANGLE; + } else if (!strcmp(stropt, pattern_strings[PATTERN_SAWTOOTH])) { + devc->sample_generator = PATTERN_SAWTOOTH; + } else if (!strcmp(stropt, pattern_strings[PATTERN_RANDOM])) { + devc->sample_generator = PATTERN_RANDOM; } else { - ret = SR_ERR; + ret = SR_ERR; } - sr_dbg("%s: setting pattern to %d", + sr_dbg("%s: setting pattern to %d", __func__, devc->sample_generator); } else { - ret = SR_ERR_NA; + ret = SR_ERR_NA; } return ret; @@ -352,108 +378,213 @@ static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi) (void)sdi; switch (key) { - case SR_CONF_DEVICE_OPTIONS: - *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32, - hwcaps, ARRAY_SIZE(hwcaps), sizeof(int32_t)); + case SR_CONF_DEVICE_OPTIONS: +// *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32, +// hwcaps, ARRAY_SIZE(hwcaps), sizeof(int32_t)); + *data = g_variant_new_from_data(G_VARIANT_TYPE("ai"), + hwcaps, ARRAY_SIZE(hwcaps)*sizeof(int32_t), TRUE, NULL, NULL); break; - case SR_CONF_SAMPLERATE: + case SR_CONF_DEVICE_CONFIGS: +// *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32, +// hwcaps, ARRAY_SIZE(hwcaps), sizeof(int32_t)); + *data = g_variant_new_from_data(G_VARIANT_TYPE("ai"), + hwoptions, ARRAY_SIZE(hwoptions)*sizeof(int32_t), TRUE, NULL, NULL); + break; + case SR_CONF_SAMPLERATE: g_variant_builder_init(&gvb, G_VARIANT_TYPE("a{sv}")); - gvar = g_variant_new_fixed_array(G_VARIANT_TYPE("t"), samplerates, - ARRAY_SIZE(samplerates), sizeof(uint64_t)); - g_variant_builder_add(&gvb, "{sv}", "samplerate-steps", gvar); +// gvar = g_variant_new_fixed_array(G_VARIANT_TYPE("t"), samplerates, +// ARRAY_SIZE(samplerates), sizeof(uint64_t)); + gvar = g_variant_new_from_data(G_VARIANT_TYPE("at"), + samplerates, ARRAY_SIZE(samplerates)*sizeof(uint64_t), TRUE, NULL, NULL); + g_variant_builder_add(&gvb, "{sv}", "samplerates", gvar); *data = g_variant_builder_end(&gvb); break; - case SR_CONF_PATTERN_MODE: + case SR_CONF_DEVICE_MODE: + *data = g_variant_new_strv(mode_strings, ARRAY_SIZE(mode_strings)); + break; + case SR_CONF_PATTERN_MODE: *data = g_variant_new_strv(pattern_strings, ARRAY_SIZE(pattern_strings)); break; default: - return SR_ERR_NA; + return SR_ERR_NA; } - return SR_OK; + return SR_OK; } -static void samples_generator(uint8_t *buf, uint64_t size, +static void samples_generator(uint16_t *buf, uint64_t size, struct dev_context *devc) { - static uint64_t p = 0; + static uint16_t p = 0; uint64_t i; - - /* TODO: Needed? */ - memset(buf, 0, size); + uint16_t demo_data; switch (devc->sample_generator) { - case PATTERN_SIGROK: /* sigrok pattern */ - for (i = 0; i < size; i++) { - *(buf + i) = ~(pattern_sigrok[ - p++ % sizeof(pattern_sigrok)] >> 1); - } + case PATTERN_SINE: /* Sine */ + for (i = 0; i < size; i++) { + if (i%CONST_LEN == 0) { + demo_data = 0x8000 * sin(2 * PI * p / 0xffff) + 0x8000; + p += CONST_LEN; + } + *(buf + i) = demo_data; + } break; + case PATTERN_SQUARE: + for (i = 0; i < size; i++) { + if (i%CONST_LEN == 0) { + demo_data = p > 0x7fff ? 0xf000 : 0x1000; + p += CONST_LEN; + } + *(buf + i) = demo_data; + } + break; + case PATTERN_TRIANGLE: + for (i = 0; i < size; i++) { + if (i%CONST_LEN == 0) { + demo_data = p > 0x7fff ? 0xffff * (2.0f * (0x10000 - p) / 0x10000) : + 0xffff * (2.0f * p / 0x10000); + p += CONST_LEN; + } + *(buf + i) = demo_data; + } + break; + case PATTERN_SAWTOOTH: + for (i = 0; i < size; i++) { + if (i%CONST_LEN == 0) { + demo_data = p; + p += CONST_LEN; + } + *(buf + i) = demo_data; + } + break; case PATTERN_RANDOM: /* Random */ - for (i = 0; i < size; i++) - *(buf + i) = (uint8_t)(rand() & 0xff); - break; - case PATTERN_INC: /* Simple increment */ - for (i = 0; i < size; i++) - *(buf + i) = p++; - break; - case PATTERN_ALL_LOW: /* All probes are low */ - memset(buf, 0x00, size); - break; - case PATTERN_ALL_HIGH: /* All probes are high */ - memset(buf, 0xff, size); + for (i = 0; i < size; i++) { + if (i%CONST_LEN == 0) + demo_data = (uint16_t)(rand() * (0x10000 * 1.0f / RAND_MAX)); + *(buf + i) = demo_data; + } break; default: - sr_err("Unknown pattern: %d.", devc->sample_generator); + sr_err("Unknown pattern: %d.", devc->sample_generator); break; } } /* Callback handling data */ -static int receive_data(int fd, int revents, void *cb_data) +static int receive_data(int fd, int revents, const struct sr_dev_inst *sdi) { - struct dev_context *devc = cb_data; - struct sr_datafeed_packet packet; - struct sr_datafeed_logic logic; - uint8_t buf[BUFSIZE]; + struct dev_context *devc = sdi->priv; + struct sr_datafeed_packet packet; + struct sr_datafeed_logic logic; + struct sr_datafeed_analog analog; + //uint16_t buf[BUFSIZE]; + uint16_t *buf; static uint64_t samples_to_send, expected_samplenum, sending_now; int64_t time, elapsed; + static uint16_t last_sample = 0; + uint16_t cur_sample; + int i; (void)fd; (void)revents; + if (!(buf = g_try_malloc(BUFSIZE*sizeof(uint16_t)))) { + sr_err("buf for receive_data malloc failed."); + return FALSE; + } + /* How many "virtual" samples should we have collected by now? */ time = g_get_monotonic_time(); elapsed = time - devc->starttime; + devc->starttime = time; expected_samplenum = elapsed * devc->cur_samplerate / 1000000; /* Of those, how many do we still have to send? */ - samples_to_send = expected_samplenum - devc->samples_counter; - - if (devc->limit_samples) { - samples_to_send = MIN(samples_to_send, - devc->limit_samples - devc->samples_counter); - } - - while (samples_to_send > 0) { - sending_now = MIN(samples_to_send, sizeof(buf)); - samples_to_send -= sending_now; + //samples_to_send = (expected_samplenum - devc->samples_counter) / CONST_LEN * CONST_LEN; + samples_to_send = expected_samplenum / CONST_LEN * CONST_LEN; + + if (devc->limit_samples) { + if (sdi->mode == LOGIC) + samples_to_send = MIN(samples_to_send, + devc->limit_samples - devc->samples_counter); + else if (sdi->mode == ANALOG) + samples_to_send = MIN(samples_to_send, + devc->limit_samples); + } + + while (samples_to_send > 0) { + sending_now = MIN(samples_to_send, BUFSIZE); samples_generator(buf, sending_now, devc); - packet.type = SR_DF_LOGIC; - packet.payload = &logic; - logic.length = sending_now; - logic.unitsize = 1; - logic.data = buf; - sr_session_send(devc->cb_data, &packet); - devc->samples_counter += sending_now; + if (devc->trigger_stage != 0) { + for (i = 0; i < sending_now; i++) { + if (devc->trigger_edge == 0) { + if ((*(buf + i) | devc->trigger_mask) == + (devc->trigger_value | devc->trigger_mask)) { + devc->trigger_stage = 0; + break; + } + } else { + cur_sample = *(buf + i); + if (((last_sample & devc->trigger_edge) == + (~devc->trigger_value & devc->trigger_edge)) && + ((cur_sample | devc->trigger_mask) == + (devc->trigger_value | devc->trigger_mask)) && + ((cur_sample & devc->trigger_edge) == + (devc->trigger_value & devc->trigger_edge))) { + devc->trigger_stage = 0; + break; + } + last_sample = cur_sample; + } + } + if (devc->trigger_stage == 0) { + struct ds_trigger_pos demo_trigger_pos; + demo_trigger_pos.real_pos = i; + packet.type = SR_DF_TRIGGER; + packet.payload = &demo_trigger_pos; + sr_session_send(sdi, &packet); + } + } + + if (devc->trigger_stage == 0){ + samples_to_send -= sending_now; + if (sdi->mode == LOGIC) { + packet.type = SR_DF_LOGIC; + packet.payload = &logic; + logic.length = sending_now * (NUM_PROBES >> 3); + logic.unitsize = (NUM_PROBES >> 3); + logic.data = buf; + } else if (sdi->mode == ANALOG) { + packet.type = SR_DF_ANALOG; + packet.payload = &analog; + analog.probes = sdi->probes; + analog.num_samples = sending_now; + analog.mq = SR_MQ_VOLTAGE; + analog.unit = SR_UNIT_VOLT; + analog.mqflags = SR_MQFLAG_AC; + analog.data = buf; + } + + sr_session_send(sdi, &packet); + if (sdi->mode == LOGIC) + devc->samples_counter += sending_now; + else if (sdi->mode == ANALOG) + devc->samples_counter = (devc->samples_counter + sending_now) % devc->limit_samples; + } else { + break; + } } - if (devc->limit_samples && - devc->samples_counter >= devc->limit_samples) { - sr_info("Requested number of samples reached."); - hw_dev_acquisition_stop(devc->sdi, cb_data); - return TRUE; - } + if (sdi->mode == LOGIC && + devc->limit_samples && + devc->samples_counter >= devc->limit_samples) { + sr_info("Requested number of samples reached."); + hw_dev_acquisition_stop(sdi, NULL); + g_free(buf); + return TRUE; + } + + g_free(buf); return TRUE; } @@ -463,11 +594,29 @@ static int hw_dev_acquisition_start(const struct sr_dev_inst *sdi, { struct dev_context *const devc = sdi->priv; - if (sdi->status != SR_ST_ACTIVE) - return SR_ERR_DEV_CLOSED; + (void)cb_data; + + if (sdi->status != SR_ST_ACTIVE) + return SR_ERR_DEV_CLOSED; - devc->cb_data = cb_data; + //devc->cb_data = cb_data; devc->samples_counter = 0; + devc->stop = FALSE; + + /* + * trigger setting + */ + if (!trigger->trigger_en || sdi->mode == ANALOG) { + devc->trigger_stage = 0; + } else { + devc->trigger_mask = ds_trigger_get_mask0(TriggerStages); + devc->trigger_value = ds_trigger_get_value0(TriggerStages); + devc->trigger_edge = ds_trigger_get_edge0(TriggerStages); + if (devc->trigger_edge != 0) + devc->trigger_stage = 2; + else + devc->trigger_stage = 1; + } /* * Setting two channels connected by a pipe is a remnant from when the @@ -492,11 +641,12 @@ static int hw_dev_acquisition_start(const struct sr_dev_inst *sdi, /* Make channels to unbuffered. */ g_io_channel_set_buffered(devc->channel, FALSE); - sr_session_source_add_channel(devc->channel, G_IO_IN | G_IO_ERR, - 40, receive_data, devc); + sr_session_source_add_channel(devc->channel, G_IO_IN | G_IO_ERR, + 100, receive_data, sdi); /* Send header packet to the session bus. */ - std_session_send_df_header(cb_data, LOG_PREFIX); + //std_session_send_df_header(cb_data, LOG_PREFIX); + std_session_send_df_header(sdi, LOG_PREFIX); /* We use this timestamp to decide how many more samples to send. */ devc->starttime = g_get_monotonic_time(); @@ -513,18 +663,27 @@ static int hw_dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data) sr_dbg("Stopping aquisition."); - sr_session_source_remove_channel(devc->channel); + devc->stop = TRUE; + sr_session_source_remove_channel(devc->channel); g_io_channel_shutdown(devc->channel, FALSE, NULL); g_io_channel_unref(devc->channel); devc->channel = NULL; /* Send last packet. */ - packet.type = SR_DF_END; - sr_session_send(devc->cb_data, &packet); + packet.type = SR_DF_END; + sr_session_send(sdi, &packet); return SR_OK; } +static int hw_dev_test(struct sr_dev_inst *sdi) +{ + if (sdi) + return SR_OK; + else + return SR_ERR; +} + SR_PRIV struct sr_dev_driver demo_driver_info = { .name = "demo", .longname = "Demo driver and pattern generator", @@ -539,6 +698,7 @@ SR_PRIV struct sr_dev_driver demo_driver_info = { .config_list = config_list, .dev_open = hw_dev_open, .dev_close = hw_dev_close, + .dev_test = hw_dev_test, .dev_acquisition_start = hw_dev_acquisition_start, .dev_acquisition_stop = hw_dev_acquisition_stop, .priv = NULL, diff --git a/hwdriver.c b/hwdriver.c index d4ae5605..d362f13b 100644 --- a/hwdriver.c +++ b/hwdriver.c @@ -57,11 +57,15 @@ static struct sr_config_info sr_config_info_data[] = { "Serial communication", NULL}, {SR_CONF_SAMPLERATE, SR_T_UINT64, "samplerate", "Sample rate", NULL}, - {SR_CONF_CAPTURE_RATIO, SR_T_UINT64, "captureratio", + {SR_CONF_CLOCK_TYPE, SR_T_BOOL, "clocktype", + "Using External Clock", NULL}, + {SR_CONF_CAPTURE_RATIO, SR_T_UINT64, "captureratio", "Pre-trigger capture ratio", NULL}, - {SR_CONF_PATTERN_MODE, SR_T_CHAR, "pattern", - "Pattern generator mode", NULL}, - {SR_CONF_TRIGGER_TYPE, SR_T_CHAR, "triggertype", + {SR_CONF_DEVICE_MODE, SR_T_CHAR, "device", + "Device Mode", NULL}, + {SR_CONF_PATTERN_MODE, SR_T_CHAR, "pattern", + "Pattern mode", NULL}, + {SR_CONF_TRIGGER_TYPE, SR_T_CHAR, "triggertype", "Trigger types", NULL}, {SR_CONF_RLE, SR_T_BOOL, "rle", "Run Length Encoding", NULL}, @@ -87,180 +91,20 @@ static struct sr_config_info sr_config_info_data[] = { }; /** @cond PRIVATE */ -#ifdef HAVE_HW_BRYMEN_DMM -extern SR_PRIV struct sr_dev_driver brymen_bm857_driver_info; -#endif -#ifdef HAVE_HW_COLEAD_SLM -extern SR_PRIV struct sr_dev_driver colead_slm_driver_info; -#endif #ifdef HAVE_LA_DEMO extern SR_PRIV struct sr_dev_driver demo_driver_info; #endif -#ifdef HAVE_HW_LASCAR_EL_USB -extern SR_PRIV struct sr_dev_driver lascar_el_usb_driver_info; -#endif -#ifdef HAVE_HW_MIC_985XX -extern SR_PRIV struct sr_dev_driver mic_98581_driver_info; -extern SR_PRIV struct sr_dev_driver mic_98583_driver_info; -#endif -#ifdef HAVE_HW_NEXUS_OSCIPRIME -extern SR_PRIV struct sr_dev_driver nexus_osciprime_driver_info; -#endif -#ifdef HAVE_LA_OLS -extern SR_PRIV struct sr_dev_driver ols_driver_info; -#endif -#ifdef HAVE_HW_RIGOL_DS1XX2 -extern SR_PRIV struct sr_dev_driver rigol_ds1xx2_driver_info; -#endif -#ifdef HAVE_HW_TONDAJ_SL_814 -extern SR_PRIV struct sr_dev_driver tondaj_sl_814_driver_info; -#endif -#ifdef HAVE_HW_VICTOR_DMM -extern SR_PRIV struct sr_dev_driver victor_dmm_driver_info; -#endif -#ifdef HAVE_LA_ZEROPLUS_LOGIC_CUBE -extern SR_PRIV struct sr_dev_driver zeroplus_logic_cube_driver_info; -#endif -#ifdef HAVE_LA_ASIX_SIGMA -extern SR_PRIV struct sr_dev_driver asix_sigma_driver_info; -#endif -#ifdef HAVE_LA_CHRONOVU_LA8 -extern SR_PRIV struct sr_dev_driver chronovu_la8_driver_info; -#endif -#ifdef HAVE_LA_LINK_MSO19 -extern SR_PRIV struct sr_dev_driver link_mso19_driver_info; -#endif -#ifdef HAVE_HW_ALSA -extern SR_PRIV struct sr_dev_driver alsa_driver_info; -#endif -#ifdef HAVE_LA_FX2LAFW -extern SR_PRIV struct sr_dev_driver fx2lafw_driver_info; -#endif -#ifdef HAVE_HW_HANTEK_DSO -extern SR_PRIV struct sr_dev_driver hantek_dso_driver_info; -#endif -#ifdef HAVE_HW_AGILENT_DMM -extern SR_PRIV struct sr_dev_driver agdmm_driver_info; -#endif -#ifdef HAVE_HW_FLUKE_DMM -extern SR_PRIV struct sr_dev_driver flukedmm_driver_info; -#endif -#ifdef HAVE_HW_SERIAL_DMM -extern SR_PRIV struct sr_dev_driver digitek_dt4000zc_driver_info; -extern SR_PRIV struct sr_dev_driver tekpower_tp4000zc_driver_info; -extern SR_PRIV struct sr_dev_driver metex_me31_driver_info; -extern SR_PRIV struct sr_dev_driver peaktech_3410_driver_info; -extern SR_PRIV struct sr_dev_driver mastech_mas345_driver_info; -extern SR_PRIV struct sr_dev_driver va_va18b_driver_info; -extern SR_PRIV struct sr_dev_driver metex_m3640d_driver_info; -extern SR_PRIV struct sr_dev_driver peaktech_4370_driver_info; -extern SR_PRIV struct sr_dev_driver pce_pce_dm32_driver_info; -extern SR_PRIV struct sr_dev_driver radioshack_22_168_driver_info; -extern SR_PRIV struct sr_dev_driver radioshack_22_805_driver_info; -extern SR_PRIV struct sr_dev_driver radioshack_22_812_driver_info; -extern SR_PRIV struct sr_dev_driver tecpel_dmm_8060_ser_driver_info; -extern SR_PRIV struct sr_dev_driver tecpel_dmm_8061_ser_driver_info; -extern SR_PRIV struct sr_dev_driver voltcraft_vc820_ser_driver_info; -extern SR_PRIV struct sr_dev_driver voltcraft_vc840_ser_driver_info; -extern SR_PRIV struct sr_dev_driver uni_t_ut61d_ser_driver_info; -extern SR_PRIV struct sr_dev_driver uni_t_ut61e_ser_driver_info; -#endif -#ifdef HAVE_HW_UNI_T_DMM -extern SR_PRIV struct sr_dev_driver tecpel_dmm_8060_driver_info; -extern SR_PRIV struct sr_dev_driver tecpel_dmm_8061_driver_info; -extern SR_PRIV struct sr_dev_driver uni_t_ut61d_driver_info; -extern SR_PRIV struct sr_dev_driver uni_t_ut61e_driver_info; -extern SR_PRIV struct sr_dev_driver voltcraft_vc820_driver_info; -extern SR_PRIV struct sr_dev_driver voltcraft_vc840_driver_info; +#ifdef HAVE_LA_DSLOGIC +extern SR_PRIV struct sr_dev_driver DSLogic_driver_info; #endif /** @endcond */ static struct sr_dev_driver *drivers_list[] = { -#ifdef HAVE_HW_BRYMEN_DMM - &brymen_bm857_driver_info, -#endif -#ifdef HAVE_HW_COLEAD_SLM - &colead_slm_driver_info, -#endif #ifdef HAVE_LA_DEMO &demo_driver_info, #endif -#ifdef HAVE_HW_LASCAR_EL_USB - &lascar_el_usb_driver_info, -#endif -#ifdef HAVE_HW_MIC_985XX - &mic_98581_driver_info, - &mic_98583_driver_info, -#endif -#ifdef HAVE_HW_NEXUS_OSCIPRIME - &nexus_osciprime_driver_info, -#endif -#ifdef HAVE_LA_OLS - &ols_driver_info, -#endif -#ifdef HAVE_HW_RIGOL_DS1XX2 - &rigol_ds1xx2_driver_info, -#endif -#ifdef HAVE_HW_TONDAJ_SL_814 - &tondaj_sl_814_driver_info, -#endif -#ifdef HAVE_HW_VICTOR_DMM - &victor_dmm_driver_info, -#endif -#ifdef HAVE_LA_ZEROPLUS_LOGIC_CUBE - &zeroplus_logic_cube_driver_info, -#endif -#ifdef HAVE_LA_ASIX_SIGMA - &asix_sigma_driver_info, -#endif -#ifdef HAVE_LA_CHRONOVU_LA8 - &chronovu_la8_driver_info, -#endif -#ifdef HAVE_LA_LINK_MSO19 - &link_mso19_driver_info, -#endif -#ifdef HAVE_HW_ALSA - &alsa_driver_info, -#endif -#ifdef HAVE_LA_FX2LAFW - &fx2lafw_driver_info, -#endif -#ifdef HAVE_HW_HANTEK_DSO - &hantek_dso_driver_info, -#endif -#ifdef HAVE_HW_AGILENT_DMM - &agdmm_driver_info, -#endif -#ifdef HAVE_HW_FLUKE_DMM - &flukedmm_driver_info, -#endif -#ifdef HAVE_HW_SERIAL_DMM - &digitek_dt4000zc_driver_info, - &tekpower_tp4000zc_driver_info, - &metex_me31_driver_info, - &peaktech_3410_driver_info, - &mastech_mas345_driver_info, - &va_va18b_driver_info, - &metex_m3640d_driver_info, - &peaktech_4370_driver_info, - &pce_pce_dm32_driver_info, - &radioshack_22_168_driver_info, - &radioshack_22_805_driver_info, - &radioshack_22_812_driver_info, - &tecpel_dmm_8060_ser_driver_info, - &tecpel_dmm_8061_ser_driver_info, - &voltcraft_vc820_ser_driver_info, - &voltcraft_vc840_ser_driver_info, - &uni_t_ut61d_ser_driver_info, - &uni_t_ut61e_ser_driver_info, -#endif -#ifdef HAVE_HW_UNI_T_DMM - &tecpel_dmm_8060_driver_info, - &tecpel_dmm_8061_driver_info, - &uni_t_ut61d_driver_info, - &uni_t_ut61e_driver_info, - &voltcraft_vc820_driver_info, - &voltcraft_vc840_driver_info, +#ifdef HAVE_LA_DSLOGIC + &DSLogic_driver_info, #endif NULL, }; @@ -553,7 +397,7 @@ SR_PRIV int sr_source_remove(int fd) SR_PRIV int sr_source_add(int fd, int events, int timeout, sr_receive_data_callback_t cb, void *cb_data) { - return sr_session_source_add(fd, events, timeout, cb, cb_data); + return sr_session_source_add(fd, events, timeout, cb, cb_data); } /** @} */ diff --git a/input/Makefile.am b/input/Makefile.am index e0fa66ed..f878db35 100644 --- a/input/Makefile.am +++ b/input/Makefile.am @@ -19,15 +19,14 @@ ## # Local lib, this is NOT meant to be installed! -noinst_LTLIBRARIES = libsigrokinput.la +noinst_LTLIBRARIES = libsigrok4DSLogicinput.la -libsigrokinput_la_SOURCES = \ - binary.c \ - chronovu_la8.c \ - input.c \ - vcd.c \ - wav.c +libsigrok4DSLogicinput_la_SOURCES = \ + in_binary.c \ + in_vcd.c \ + in_wav.c \ + input.c -libsigrokinput_la_CFLAGS = \ +libsigrok4DSLogicinput_la_CFLAGS = \ -I$(top_srcdir) diff --git a/input/in_binary.c b/input/in_binary.c new file mode 100644 index 00000000..2d52c306 --- /dev/null +++ b/input/in_binary.c @@ -0,0 +1,158 @@ +/* + * This file is part of the libsigrok project. + * + * Copyright (C) 2013 Bert Vermeulen + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include "libsigrok.h" +#include "libsigrok-internal.h" + +/* Message logging helpers with subsystem-specific prefix string. */ +#define LOG_PREFIX "input/binary: " +#define sr_log(l, s, args...) sr_log(l, LOG_PREFIX s, ## args) +#define sr_spew(s, args...) sr_spew(LOG_PREFIX s, ## args) +#define sr_dbg(s, args...) sr_dbg(LOG_PREFIX s, ## args) +#define sr_info(s, args...) sr_info(LOG_PREFIX s, ## args) +#define sr_warn(s, args...) sr_warn(LOG_PREFIX s, ## args) +#define sr_err(s, args...) sr_err(LOG_PREFIX s, ## args) + +#define CHUNKSIZE (512 * 1024) +#define DEFAULT_NUM_PROBES 8 + +struct context { + uint64_t samplerate; +}; + +static int format_match(const char *filename) +{ + (void)filename; + + /* This module will handle anything you throw at it. */ + return TRUE; +} + +static int init(struct sr_input *in, const char *filename) +{ + struct sr_probe *probe; + int num_probes, i; + char name[SR_MAX_PROBENAME_LEN + 1]; + char *param; + struct context *ctx; + + (void)filename; + + if (!(ctx = g_try_malloc0(sizeof(*ctx)))) { + sr_err("Input format context malloc failed."); + return SR_ERR_MALLOC; + } + + num_probes = DEFAULT_NUM_PROBES; + ctx->samplerate = 0; + + if (in->param) { + param = g_hash_table_lookup(in->param, "numprobes"); + if (param) { + num_probes = strtoul(param, NULL, 10); + if (num_probes < 1) + return SR_ERR; + } + + param = g_hash_table_lookup(in->param, "samplerate"); + if (param) { + if (sr_parse_sizestring(param, &ctx->samplerate) != SR_OK) + return SR_ERR; + } + } + + /* Create a virtual device. */ + in->sdi = sr_dev_inst_new(LOGIC, 0, SR_ST_ACTIVE, NULL, NULL, NULL); + in->internal = ctx; + + for (i = 0; i < num_probes; i++) { + snprintf(name, SR_MAX_PROBENAME_LEN, "%d", i); + /* TODO: Check return value. */ + if (!(probe = sr_probe_new(i, SR_PROBE_LOGIC, TRUE, name))) + return SR_ERR; + in->sdi->probes = g_slist_append(in->sdi->probes, probe); + } + + return SR_OK; +} + +static int loadfile(struct sr_input *in, const char *filename) +{ + struct sr_datafeed_packet packet; + struct sr_datafeed_meta meta; + struct sr_datafeed_logic logic; + struct sr_config *src; + unsigned char buffer[CHUNKSIZE]; + int fd, size, num_probes; + struct context *ctx; + + ctx = in->internal; + + if ((fd = open(filename, O_RDONLY)) == -1) + return SR_ERR; + + num_probes = g_slist_length(in->sdi->probes); + + /* Send header packet to the session bus. */ + std_session_send_df_header(in->sdi, LOG_PREFIX); + + if (ctx->samplerate) { + packet.type = SR_DF_META; + packet.payload = &meta; + src = sr_config_new(SR_CONF_SAMPLERATE, + g_variant_new_uint64(ctx->samplerate)); + meta.config = g_slist_append(NULL, src); + sr_session_send(in->sdi, &packet); + sr_config_free(src); + } + + /* Chop up the input file into chunks & send it to the session bus. */ + packet.type = SR_DF_LOGIC; + packet.payload = &logic; + logic.unitsize = (num_probes + 7) / 8; + logic.data = buffer; + while ((size = read(fd, buffer, CHUNKSIZE)) > 0) { + logic.length = size; + sr_session_send(in->sdi, &packet); + } + close(fd); + + /* Send end packet to the session bus. */ + packet.type = SR_DF_END; + sr_session_send(in->sdi, &packet); + + g_free(ctx); + in->internal = NULL; + + return SR_OK; +} + +SR_PRIV struct sr_input_format input_binary = { + .id = "binary", + .description = "Raw binary", + .format_match = format_match, + .init = init, + .loadfile = loadfile, +}; diff --git a/input/in_vcd.c b/input/in_vcd.c new file mode 100644 index 00000000..a143b1cb --- /dev/null +++ b/input/in_vcd.c @@ -0,0 +1,609 @@ +/* + * This file is part of the libsigrok project. + * + * Copyright (C) 2012 Petteri Aimonen + * + * 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 . + */ + +/* The VCD input module has the following options: + * + * numprobes: Maximum number of probes to use. The probes are + * detected in the same order as they are listed + * in the $var sections of the VCD file. + * + * skip: Allows skipping until given timestamp in the file. + * This can speed up analyzing of long captures. + * + * Value < 0: Skip until first timestamp listed in + * the file. (default) + * + * Value = 0: Do not skip, instead generate samples + * beginning from timestamp 0. + * + * Value > 0: Start at the given timestamp. + * + * downsample: Divide the samplerate by the given factor. + * This can speed up analyzing of long captures. + * + * compress: Compress idle periods longer than this value. + * This can speed up analyzing of long captures. + * Default 0 = don't compress. + * + * Based on Verilog standard IEEE Std 1364-2001 Version C + * + * Supported features: + * - $var with 'wire' and 'reg' types of scalar variables + * - $timescale definition for samplerate + * - multiple character variable identifiers + * + * Most important unsupported features: + * - vector variables (bit vectors etc.) + * - analog, integer and real number variables + * - $dumpvars initial value declaration + * - $scope namespaces + */ + +/* */ + +#include +#include +#include +#include +#include "libsigrok.h" +#include "libsigrok-internal.h" + +/* Message logging helpers with subsystem-specific prefix string. */ +#define LOG_PREFIX "input/vcd: " +#define sr_log(l, s, args...) sr_log(l, LOG_PREFIX s, ## args) +#define sr_spew(s, args...) sr_spew(LOG_PREFIX s, ## args) +#define sr_dbg(s, args...) sr_dbg(LOG_PREFIX s, ## args) +#define sr_info(s, args...) sr_info(LOG_PREFIX s, ## args) +#define sr_warn(s, args...) sr_warn(LOG_PREFIX s, ## args) +#define sr_err(s, args...) sr_err(LOG_PREFIX s, ## args) + +#define DEFAULT_NUM_PROBES 8 + +/* Read until specific type of character occurs in file. + * Skip input if dest is NULL. + * Modes: + * 'W' read until whitespace + * 'N' read until non-whitespace, and ungetc() the character + * '$' read until $end + */ +static gboolean read_until(FILE *file, GString *dest, char mode) +{ + char prev[4] = ""; + long startpos = ftell(file); + for(;;) + { + int c = fgetc(file); + + if (c == EOF) + { + if (mode == '$') + sr_err("Unexpected EOF, read started at %ld.", startpos); + return FALSE; + } + + if (mode == 'W' && g_ascii_isspace(c)) + return TRUE; + + if (mode == 'N' && !g_ascii_isspace(c)) + { + ungetc(c, file); + return TRUE; + } + + if (mode == '$') + { + prev[0] = prev[1]; prev[1] = prev[2]; prev[2] = prev[3]; prev[3] = c; + if (prev[0] == '$' && prev[1] == 'e' && prev[2] == 'n' && prev[3] == 'd') + { + if (dest != NULL) + g_string_truncate(dest, dest->len - 3); + + return TRUE; + } + } + + if (dest != NULL) + g_string_append_c(dest, c); + } +} + +/* Reads a single VCD section from input file and parses it to structure. + * e.g. $timescale 1ps $end => "timescale" "1ps" + */ +static gboolean parse_section(FILE *file, gchar **name, gchar **contents) +{ + gboolean status; + GString *sname, *scontents; + + /* Skip any initial white-space */ + if (!read_until(file, NULL, 'N')) return FALSE; + + /* Section tag should start with $. */ + if (fgetc(file) != '$') + { + sr_err("Expected $ at beginning of section."); + return FALSE; + } + + /* Read the section tag */ + sname = g_string_sized_new(32); + status = read_until(file, sname, 'W'); + + /* Skip whitespace before content */ + status = status && read_until(file, NULL, 'N'); + + /* Read the content */ + scontents = g_string_sized_new(128); + status = status && read_until(file, scontents, '$'); + g_strchomp(scontents->str); + + /* Release strings if status is FALSE, return them if status is TRUE */ + *name = g_string_free(sname, !status); + *contents = g_string_free(scontents, !status); + return status; +} + +struct probe +{ + gchar *name; + gchar *identifier; +}; + +struct context +{ + uint64_t samplerate; + int maxprobes; + int probecount; + int downsample; + unsigned compress; + int64_t skip; + GSList *probes; +}; + +static void free_probe(void *data) +{ + struct probe *probe = data; + g_free(probe->name); + g_free(probe->identifier); + g_free(probe); +} + +static void release_context(struct context *ctx) +{ + g_slist_free_full(ctx->probes, free_probe); + g_free(ctx); +} + +/* Remove empty parts from an array returned by g_strsplit. */ +static void remove_empty_parts(gchar **parts) +{ + gchar **src = parts; + gchar **dest = parts; + while (*src != NULL) + { + if (**src != '\0') + { + *dest++ = *src; + } + + src++; + } + + *dest = NULL; +} + +/* Parse VCD header to get values for context structure. + * The context structure should be zeroed before calling this. + */ +static gboolean parse_header(FILE *file, struct context *ctx) +{ + uint64_t p, q; + gchar *name = NULL, *contents = NULL; + gboolean status = FALSE; + struct probe *probe; + + while (parse_section(file, &name, &contents)) + { + sr_dbg("Section '%s', contents '%s'.", name, contents); + + if (g_strcmp0(name, "enddefinitions") == 0) + { + status = TRUE; + break; + } + else if (g_strcmp0(name, "timescale") == 0) + { + /* The standard allows for values 1, 10 or 100 + * and units s, ms, us, ns, ps and fs. */ + if (sr_parse_period(contents, &p, &q) == SR_OK) + { + ctx->samplerate = q / p; + if (q % p != 0) + { + /* Does not happen unless time value is non-standard */ + sr_warn("Inexact rounding of samplerate, %" PRIu64 " / %" PRIu64 " to %" PRIu64 " Hz.", + q, p, ctx->samplerate); + } + + sr_dbg("Samplerate: %" PRIu64, ctx->samplerate); + } + else + { + sr_err("Parsing timescale failed."); + } + } + else if (g_strcmp0(name, "var") == 0) + { + /* Format: $var type size identifier reference $end */ + gchar **parts = g_strsplit_set(contents, " \r\n\t", 0); + remove_empty_parts(parts); + + if (g_strv_length(parts) != 4) + { + sr_warn("$var section should have 4 items"); + } + else if (g_strcmp0(parts[0], "reg") != 0 && g_strcmp0(parts[0], "wire") != 0) + { + sr_info("Unsupported signal type: '%s'", parts[0]); + } + else if (strtol(parts[1], NULL, 10) != 1) + { + sr_info("Unsupported signal size: '%s'", parts[1]); + } + else if (ctx->probecount >= ctx->maxprobes) + { + sr_warn("Skipping '%s' because only %d probes requested.", parts[3], ctx->maxprobes); + } + else + { + sr_info("Probe %d is '%s' identified by '%s'.", ctx->probecount, parts[3], parts[2]); + probe = g_malloc(sizeof(struct probe)); + probe->identifier = g_strdup(parts[2]); + probe->name = g_strdup(parts[3]); + ctx->probes = g_slist_append(ctx->probes, probe); + ctx->probecount++; + } + + g_strfreev(parts); + } + + g_free(name); name = NULL; + g_free(contents); contents = NULL; + } + + g_free(name); + g_free(contents); + + return status; +} + +static int format_match(const char *filename) +{ + FILE *file; + gchar *name = NULL, *contents = NULL; + gboolean status; + + file = fopen(filename, "r"); + if (file == NULL) + return FALSE; + + /* If we can parse the first section correctly, + * then it is assumed to be a VCD file. + */ + status = parse_section(file, &name, &contents); + status = status && (*name != '\0'); + + g_free(name); + g_free(contents); + fclose(file); + + return status; +} + +static int init(struct sr_input *in, const char *filename) +{ + struct sr_probe *probe; + int num_probes, i; + char name[SR_MAX_PROBENAME_LEN + 1]; + char *param; + struct context *ctx; + + (void)filename; + + if (!(ctx = g_try_malloc0(sizeof(*ctx)))) { + sr_err("Input format context malloc failed."); + return SR_ERR_MALLOC; + } + + num_probes = DEFAULT_NUM_PROBES; + ctx->samplerate = 0; + ctx->downsample = 1; + ctx->skip = -1; + + if (in->param) { + param = g_hash_table_lookup(in->param, "numprobes"); + if (param) { + num_probes = strtoul(param, NULL, 10); + if (num_probes < 1) + { + release_context(ctx); + return SR_ERR; + } + } + + param = g_hash_table_lookup(in->param, "downsample"); + if (param) { + ctx->downsample = strtoul(param, NULL, 10); + if (ctx->downsample < 1) + { + ctx->downsample = 1; + } + } + + param = g_hash_table_lookup(in->param, "compress"); + if (param) { + ctx->compress = strtoul(param, NULL, 10); + } + + param = g_hash_table_lookup(in->param, "skip"); + if (param) { + ctx->skip = strtoul(param, NULL, 10) / ctx->downsample; + } + } + + /* Maximum number of probes to parse from the VCD */ + ctx->maxprobes = num_probes; + + /* Create a virtual device. */ + in->sdi = sr_dev_inst_new(LOGIC, 0, SR_ST_ACTIVE, NULL, NULL, NULL); + in->internal = ctx; + + for (i = 0; i < num_probes; i++) { + snprintf(name, SR_MAX_PROBENAME_LEN, "%d", i); + + if (!(probe = sr_probe_new(i, SR_PROBE_LOGIC, TRUE, name))) + { + release_context(ctx); + return SR_ERR; + } + + in->sdi->probes = g_slist_append(in->sdi->probes, probe); + } + + return SR_OK; +} + +#define CHUNKSIZE 1024 + +/* Send N samples of the given value. */ +static void send_samples(const struct sr_dev_inst *sdi, uint64_t sample, uint64_t count) +{ + struct sr_datafeed_packet packet; + struct sr_datafeed_logic logic; + uint64_t buffer[CHUNKSIZE]; + uint64_t i; + unsigned chunksize = CHUNKSIZE; + + if (count < chunksize) + chunksize = count; + + for (i = 0; i < chunksize; i++) + { + buffer[i] = sample; + } + + packet.type = SR_DF_LOGIC; + packet.payload = &logic; + logic.unitsize = sizeof(uint64_t); + logic.data = buffer; + + while (count) + { + if (count < chunksize) + chunksize = count; + + logic.length = sizeof(uint64_t) * chunksize; + + sr_session_send(sdi, &packet); + count -= chunksize; + } +} + +/* Parse the data section of VCD */ +static void parse_contents(FILE *file, const struct sr_dev_inst *sdi, struct context *ctx) +{ + GString *token = g_string_sized_new(32); + + uint64_t prev_timestamp = 0; + uint64_t prev_values = 0; + + /* Read one space-delimited token at a time. */ + while (read_until(file, NULL, 'N') && read_until(file, token, 'W')) + { + if (token->str[0] == '#' && g_ascii_isdigit(token->str[1])) + { + /* Numeric value beginning with # is a new timestamp value */ + uint64_t timestamp; + timestamp = strtoull(token->str + 1, NULL, 10); + + if (ctx->downsample > 1) + timestamp /= ctx->downsample; + + /* Skip < 0 => skip until first timestamp. + * Skip = 0 => don't skip + * Skip > 0 => skip until timestamp >= skip. + */ + if (ctx->skip < 0) + { + ctx->skip = timestamp; + prev_timestamp = timestamp; + } + else if (ctx->skip > 0 && timestamp < (uint64_t)ctx->skip) + { + prev_timestamp = ctx->skip; + } + else if (timestamp == prev_timestamp) + { + /* Ignore repeated timestamps (e.g. sigrok outputs these) */ + } + else + { + if (ctx->compress != 0 && timestamp - prev_timestamp > ctx->compress) + { + /* Compress long idle periods */ + prev_timestamp = timestamp - ctx->compress; + } + + sr_dbg("New timestamp: %" PRIu64, timestamp); + + /* Generate samples from prev_timestamp up to timestamp - 1. */ + send_samples(sdi, prev_values, timestamp - prev_timestamp); + prev_timestamp = timestamp; + } + } + else if (token->str[0] == '$' && token->len > 1) + { + /* This is probably a $dumpvars, $comment or similar. + * $dump* contain useful data, but other tags will be skipped until $end. */ + if (g_strcmp0(token->str, "$dumpvars") == 0 || + g_strcmp0(token->str, "$dumpon") == 0 || + g_strcmp0(token->str, "$dumpoff") == 0 || + g_strcmp0(token->str, "$end") == 0) + { + /* Ignore, parse contents as normally. */ + } + else + { + /* Skip until $end */ + read_until(file, NULL, '$'); + } + } + else if (strchr("bBrR", token->str[0]) != NULL) + { + /* A vector value. Skip it and also the following identifier. */ + read_until(file, NULL, 'N'); + read_until(file, NULL, 'W'); + } + else if (strchr("01xXzZ", token->str[0]) != NULL) + { + /* A new 1-bit sample value */ + int i, bit; + GSList *l; + struct probe *probe; + + bit = (token->str[0] == '1'); + + g_string_erase(token, 0, 1); + if (token->len == 0) + { + /* There was a space between value and identifier. + * Read in the rest. + */ + read_until(file, NULL, 'N'); + read_until(file, token, 'W'); + } + + for (i = 0, l = ctx->probes; i < ctx->probecount && l; i++, l = l->next) + { + probe = l->data; + + if (g_strcmp0(token->str, probe->identifier) == 0) + { + sr_dbg("Probe %d new value %d.", i, bit); + + /* Found our probe */ + if (bit) + prev_values |= (1 << i); + else + prev_values &= ~(1 << i); + + break; + } + } + + if (i == ctx->probecount) + { + sr_dbg("Did not find probe for identifier '%s'.", token->str); + } + } + else + { + sr_warn("Skipping unknown token '%s'.", token->str); + } + + g_string_truncate(token, 0); + } + + g_string_free(token, TRUE); +} + +static int loadfile(struct sr_input *in, const char *filename) +{ + struct sr_datafeed_packet packet; + struct sr_datafeed_meta meta; + struct sr_config *src; + FILE *file; + struct context *ctx; + uint64_t samplerate; + + ctx = in->internal; + + if ((file = fopen(filename, "r")) == NULL) + return SR_ERR; + + if (!parse_header(file, ctx)) + { + sr_err("VCD parsing failed"); + fclose(file); + return SR_ERR; + } + + /* Send header packet to the session bus. */ + std_session_send_df_header(in->sdi, LOG_PREFIX); + + /* Send metadata about the SR_DF_LOGIC packets to come. */ + packet.type = SR_DF_META; + packet.payload = &meta; + samplerate = ctx->samplerate / ctx->downsample; + src = sr_config_new(SR_CONF_SAMPLERATE, g_variant_new_uint64(samplerate)); + meta.config = g_slist_append(NULL, src); + sr_session_send(in->sdi, &packet); + sr_config_free(src); + + /* Parse the contents of the VCD file */ + parse_contents(file, in->sdi, ctx); + + /* Send end packet to the session bus. */ + packet.type = SR_DF_END; + sr_session_send(in->sdi, &packet); + + fclose(file); + release_context(ctx); + in->internal = NULL; + + return SR_OK; +} + +SR_PRIV struct sr_input_format input_vcd = { + .id = "vcd", + .description = "Value Change Dump", + .format_match = format_match, + .init = init, + .loadfile = loadfile, +}; diff --git a/input/in_wav.c b/input/in_wav.c new file mode 100644 index 00000000..773b6b8e --- /dev/null +++ b/input/in_wav.c @@ -0,0 +1,211 @@ +/* + * This file is part of the libsigrok project. + * + * Copyright (C) 2013 Bert Vermeulen + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include "libsigrok.h" +#include "libsigrok-internal.h" + +/* Message logging helpers with subsystem-specific prefix string. */ +#define LOG_PREFIX "input/wav: " +#define sr_log(l, s, args...) sr_log(l, LOG_PREFIX s, ## args) +#define sr_spew(s, args...) sr_spew(LOG_PREFIX s, ## args) +#define sr_dbg(s, args...) sr_dbg(LOG_PREFIX s, ## args) +#define sr_info(s, args...) sr_info(LOG_PREFIX s, ## args) +#define sr_warn(s, args...) sr_warn(LOG_PREFIX s, ## args) +#define sr_err(s, args...) sr_err(LOG_PREFIX s, ## args) + +#define CHUNK_SIZE 4096 + +struct context { + uint64_t samplerate; + int samplesize; + int num_channels; +}; + +static int get_wav_header(const char *filename, char *buf) +{ + struct stat st; + int fd, l; + + l = strlen(filename); + if (l <= 4 || strcasecmp(filename + l - 4, ".wav")) + return SR_ERR; + + if (stat(filename, &st) == -1) + return SR_ERR; + if (st.st_size <= 45) + /* Minimum size of header + 1 8-bit mono PCM sample. */ + return SR_ERR; + + if ((fd = open(filename, O_RDONLY)) == -1) + return SR_ERR; + + l = read(fd, buf, 40); + close(fd); + if (l != 40) + return SR_ERR; + + return SR_OK; +} + +static int format_match(const char *filename) +{ + char buf[40]; + + if (get_wav_header(filename, buf) != SR_OK) + return FALSE; + + if (strncmp(buf, "RIFF", 4)) + return FALSE; + if (strncmp(buf + 8, "WAVE", 4)) + return FALSE; + if (strncmp(buf + 12, "fmt ", 4)) + return FALSE; + if (GUINT16_FROM_LE(*(uint16_t *)(buf + 20)) != 1) + /* Not PCM. */ + return FALSE; + if (strncmp(buf + 36, "data", 4)) + return FALSE; + + return TRUE; +} + +static int init(struct sr_input *in, const char *filename) +{ + struct sr_probe *probe; + struct context *ctx; + char buf[40], probename[8]; + int i; + + if (get_wav_header(filename, buf) != SR_OK) + return SR_ERR; + + if (!(ctx = g_try_malloc0(sizeof(struct context)))) + return SR_ERR_MALLOC; + + /* Create a virtual device. */ + in->sdi = sr_dev_inst_new(LOGIC, 0, SR_ST_ACTIVE, NULL, NULL, NULL); + in->sdi->priv = ctx; + + ctx->samplerate = GUINT32_FROM_LE(*(uint32_t *)(buf + 24)); + ctx->samplesize = GUINT16_FROM_LE(*(uint16_t *)(buf + 34)) / 8; + if (ctx->samplesize != 1 && ctx->samplesize != 2 && ctx->samplesize != 4) { + sr_err("only 8, 16 or 32 bits per sample supported."); + return SR_ERR; + } + + if ((ctx->num_channels = GUINT16_FROM_LE(*(uint16_t *)(buf + 22))) > 20) { + sr_err("%d channels seems crazy.", ctx->num_channels); + return SR_ERR; + } + + for (i = 0; i < ctx->num_channels; i++) { + snprintf(probename, 8, "CH%d", i + 1); + if (!(probe = sr_probe_new(0, SR_PROBE_ANALOG, TRUE, probename))) + return SR_ERR; + in->sdi->probes = g_slist_append(in->sdi->probes, probe); + } + + return SR_OK; +} + +static int loadfile(struct sr_input *in, const char *filename) +{ + struct sr_datafeed_packet packet; + struct sr_datafeed_meta meta; + struct sr_datafeed_analog analog; + struct sr_config *src; + struct context *ctx; + float fdata[CHUNK_SIZE]; + uint64_t sample; + int num_samples, chunk_samples, s, c, fd, l; + char buf[CHUNK_SIZE]; + + ctx = in->sdi->priv; + + /* Send header packet to the session bus. */ + std_session_send_df_header(in->sdi, LOG_PREFIX); + + packet.type = SR_DF_META; + packet.payload = &meta; + src = sr_config_new(SR_CONF_SAMPLERATE, + g_variant_new_uint64(ctx->samplerate)); + meta.config = g_slist_append(NULL, src); + sr_session_send(in->sdi, &packet); + sr_config_free(src); + + if ((fd = open(filename, O_RDONLY)) == -1) + return SR_ERR; + + lseek(fd, 40, SEEK_SET); + l = read(fd, buf, 4); + num_samples = GUINT32_FROM_LE((uint32_t)*(buf)); + num_samples /= ctx->samplesize / ctx->num_channels; + while (TRUE) { + if ((l = read(fd, buf, CHUNK_SIZE)) < 1) + break; + chunk_samples = l / ctx->samplesize / ctx->num_channels; + for (s = 0; s < chunk_samples; s++) { + for (c = 0; c < ctx->num_channels; c++) { + sample = 0; + memcpy(&sample, buf + s * ctx->samplesize + c, ctx->samplesize); + switch (ctx->samplesize) { + case 1: + /* 8-bit PCM samples are unsigned. */ + fdata[s + c] = (uint8_t)sample / 255.0; + break; + case 2: + fdata[s + c] = GINT16_FROM_LE(sample) / 32767.0; + break; + case 4: + fdata[s + c] = GINT32_FROM_LE(sample) / 65535.0; + break; + } + } + } + packet.type = SR_DF_ANALOG; + packet.payload = &analog; + analog.probes = in->sdi->probes; + analog.num_samples = chunk_samples; + analog.mq = 0; + analog.unit = 0; + analog.data = fdata; + sr_session_send(in->sdi, &packet); + } + + close(fd); + packet.type = SR_DF_END; + sr_session_send(in->sdi, &packet); + + return SR_OK; +} + + +SR_PRIV struct sr_input_format input_wav = { + .id = "wav", + .description = "WAV file", + .format_match = format_match, + .init = init, + .loadfile = loadfile, +}; + diff --git a/input/input.c b/input/input.c index fa0bf438..68ae49e4 100644 --- a/input/input.c +++ b/input/input.c @@ -50,7 +50,7 @@ */ /** @cond PRIVATE */ -extern SR_PRIV struct sr_input_format input_chronovu_la8; + extern SR_PRIV struct sr_input_format input_binary; extern SR_PRIV struct sr_input_format input_vcd; extern SR_PRIV struct sr_input_format input_wav; @@ -58,7 +58,6 @@ extern SR_PRIV struct sr_input_format input_wav; static struct sr_input_format *input_module_list[] = { &input_vcd, - &input_chronovu_la8, &input_wav, /* This one has to be last, because it will take any input. */ &input_binary, diff --git a/libsigrok-internal.h b/libsigrok-internal.h index 57005cd2..aa8086ea 100644 --- a/libsigrok-internal.h +++ b/libsigrok-internal.h @@ -84,11 +84,12 @@ SR_PRIV int sr_err(const char *format, ...); /*--- device.c --------------------------------------------------------------*/ SR_PRIV struct sr_probe *sr_probe_new(int index, int type, - gboolean enabled, const char *name); + gboolean enabled, const char *name); +SR_PRIV void sr_dev_probes_free(struct sr_dev_inst *sdi); /* Generic device instances */ -SR_PRIV struct sr_dev_inst *sr_dev_inst_new(int index, int status, - const char *vendor, const char *model, const char *version); +SR_PRIV struct sr_dev_inst *sr_dev_inst_new(int mode, int index, int status, + const char *vendor, const char *model, const char *version); SR_PRIV void sr_dev_inst_free(struct sr_dev_inst *sdi); #ifdef HAVE_LIBUSB_1_0 @@ -112,7 +113,7 @@ SR_PRIV struct sr_config *sr_config_new(int key, GVariant *data); SR_PRIV void sr_config_free(struct sr_config *src); SR_PRIV int sr_source_remove(int fd); SR_PRIV int sr_source_add(int fd, int events, int timeout, - sr_receive_data_callback_t cb, void *cb_data); + sr_receive_data_callback_t cb, void *cb_data); /*--- session.c -------------------------------------------------------------*/ @@ -135,6 +136,14 @@ SR_PRIV int std_session_send_df_header(const struct sr_dev_inst *sdi, SR_PRIV int std_dev_clear(const struct sr_dev_driver *driver, std_dev_clear_t clear_private); +/*--- trigger.c -------------------------------------------------*/ +SR_PRIV uint64_t sr_trigger_get_mask0(uint16_t stage); +SR_PRIV uint64_t sr_trigger_get_mask1(uint16_t stage); +SR_PRIV uint64_t sr_trigger_get_value0(uint16_t stage); +SR_PRIV uint64_t sr_trigger_get_value1(uint16_t stage); +SR_PRIV uint64_t sr_trigger_get_edge0(uint16_t stage); +SR_PRIV uint64_t sr_trigger_get_edge1(uint16_t stage); + /*--- hardware/common/serial.c ----------------------------------------------*/ enum { @@ -180,84 +189,6 @@ SR_PRIV GSList *sr_usb_find(libusb_context *usb_ctx, const char *conn); SR_PRIV int sr_usb_open(libusb_context *usb_ctx, struct sr_usb_dev_inst *usb); #endif -/*--- hardware/common/dmm/es51922.c -----------------------------------------*/ - -#define ES51922_PACKET_SIZE 14 - -struct es51922_info { - gboolean is_judge, is_vbar, is_voltage, is_auto, is_micro, is_current; - gboolean is_milli, is_resistance, is_continuity, is_diode, is_lpf; - gboolean is_frequency, is_duty_cycle, is_capacitance, is_temperature; - gboolean is_celsius, is_fahrenheit, is_adp, is_sign, is_batt, is_ol; - gboolean is_max, is_min, is_rel, is_rmr, is_ul, is_pmax, is_pmin; - gboolean is_dc, is_ac, is_vahz, is_hold, is_nano, is_kilo, is_mega; -}; - -SR_PRIV gboolean sr_es51922_packet_valid(const uint8_t *buf); -SR_PRIV int sr_es51922_parse(const uint8_t *buf, float *floatval, - struct sr_datafeed_analog *analog, void *info); - -/*--- hardware/common/dmm/fs9922.c ------------------------------------------*/ - -#define FS9922_PACKET_SIZE 14 - -struct fs9922_info { - gboolean is_auto, is_dc, is_ac, is_rel, is_hold, is_bpn, is_z1, is_z2; - gboolean is_max, is_min, is_apo, is_bat, is_nano, is_z3, is_micro; - gboolean is_milli, is_kilo, is_mega, is_beep, is_diode, is_percent; - gboolean is_z4, is_volt, is_ampere, is_ohm, is_hfe, is_hertz, is_farad; - gboolean is_celsius, is_fahrenheit; - int bargraph_sign, bargraph_value; -}; - -SR_PRIV gboolean sr_fs9922_packet_valid(const uint8_t *buf); -SR_PRIV int sr_fs9922_parse(const uint8_t *buf, float *floatval, - struct sr_datafeed_analog *analog, void *info); - -/*--- hardware/common/dmm/fs9721.c ------------------------------------------*/ - -#define FS9721_PACKET_SIZE 14 - -struct fs9721_info { - gboolean is_ac, is_dc, is_auto, is_rs232, is_micro, is_nano, is_kilo; - gboolean is_diode, is_milli, is_percent, is_mega, is_beep, is_farad; - gboolean is_ohm, is_rel, is_hold, is_ampere, is_volt, is_hz, is_bat; - gboolean is_c2c1_11, is_c2c1_10, is_c2c1_01, is_c2c1_00, is_sign; -}; - -SR_PRIV gboolean sr_fs9721_packet_valid(const uint8_t *buf); -SR_PRIV int sr_fs9721_parse(const uint8_t *buf, float *floatval, - struct sr_datafeed_analog *analog, void *info); -SR_PRIV void sr_fs9721_00_temp_c(struct sr_datafeed_analog *analog, void *info); -SR_PRIV void sr_fs9721_01_temp_c(struct sr_datafeed_analog *analog, void *info); -SR_PRIV void sr_fs9721_10_temp_c(struct sr_datafeed_analog *analog, void *info); -SR_PRIV void sr_fs9721_01_10_temp_f_c(struct sr_datafeed_analog *analog, void *info); - -/*--- hardware/common/dmm/metex14.c -----------------------------------------*/ - -#define METEX14_PACKET_SIZE 14 - -struct metex14_info { - gboolean is_ac, is_dc, is_resistance, is_capacity, is_temperature; - gboolean is_diode, is_frequency, is_ampere, is_volt, is_farad; - gboolean is_hertz, is_ohm, is_celsius, is_nano, is_micro, is_milli; - gboolean is_kilo, is_mega, is_gain, is_decibel, is_hfe, is_unitless; -}; - -SR_PRIV int sr_metex14_packet_request(struct sr_serial_dev_inst *serial); -SR_PRIV gboolean sr_metex14_packet_valid(const uint8_t *buf); -SR_PRIV int sr_metex14_parse(const uint8_t *buf, float *floatval, - struct sr_datafeed_analog *analog, void *info); - -/*--- hardware/common/dmm/rs9lcd.c ------------------------------------------*/ - -#define RS9LCD_PACKET_SIZE 9 - -/* Dummy info struct. The parser does not use it. */ -struct rs9lcd_info { int dummy; }; -SR_PRIV gboolean sr_rs9lcd_packet_valid(const uint8_t *buf); -SR_PRIV int sr_rs9lcd_parse(const uint8_t *buf, float *floatval, - struct sr_datafeed_analog *analog, void *info); #endif diff --git a/libsigrok.h b/libsigrok.h index 6cda5543..523aabcb 100644 --- a/libsigrok.h +++ b/libsigrok.h @@ -26,6 +26,14 @@ #include #include +#ifdef WIN32 +#define WINVER 0x0500 +#define _WIN32_WINNT WINVER +#include +#else +#include +#endif + #ifdef __cplusplus extern "C" { #endif @@ -80,6 +88,10 @@ enum { }; #define SR_MAX_PROBENAME_LEN 32 +#define DS_MAX_ANALOG_PROBES_NUM 8 +#define TriggerStages 16 +#define TriggerProbes 16 +#define TriggerCountBits 16 /* Handy little macros */ #define SR_HZ(n) (n) @@ -129,7 +141,7 @@ enum { #define SR_PRIV #endif -typedef int (*sr_receive_data_callback_t)(int fd, int revents, void *cb_data); +typedef int (*sr_receive_data_callback_t)(int fd, int revents, const struct sr_dev_inst *sdi); /** Data types used by sr_config_info(). */ enum { @@ -280,9 +292,14 @@ struct sr_datafeed_meta { struct sr_datafeed_logic { uint64_t length; uint16_t unitsize; + uint16_t data_error; void *data; }; +struct sr_datafeed_trigger { + +}; + struct sr_datafeed_analog { /** The probes for which data is included in this packet. */ GSList *probes; @@ -533,6 +550,16 @@ enum { SR_PROBE_ANALOG, }; +enum { + LOGIC = 0, + ANALOG = 1, +}; + +static const char *mode_strings[] = { + "Logic Analyzer", + "Oscilloscope", +}; + struct sr_probe { /* The index field will go: use g_slist_length(sdi->probes) instead. */ int index; @@ -622,6 +649,9 @@ enum { /** The device supports setting a pre/post-trigger capture ratio. */ SR_CONF_CAPTURE_RATIO, + /** */ + SR_CONF_DEVICE_MODE, + /** The device supports setting a pattern (pattern generator mode). */ SR_CONF_PATTERN_MODE, @@ -664,6 +694,9 @@ enum { /** Number of vertical divisions, as related to SR_CONF_VDIV. */ SR_CONF_NUM_VDIV, + /** clock type (internal/external) */ + SR_CONF_CLOCK_TYPE, + /*--- Special stuff -------------------------------------------------*/ /** Scan options supported by the driver. */ @@ -671,6 +704,7 @@ enum { /** Device options for a particular device. */ SR_CONF_DEVICE_OPTIONS, + SR_CONF_DEVICE_CONFIGS, /** Session filename. */ SR_CONF_SESSIONFILE, @@ -721,6 +755,7 @@ struct sr_dev_inst { int index; int status; int inst_type; + int mode; char *vendor; char *model; char *version; @@ -771,6 +806,7 @@ struct sr_dev_driver { /* Device-specific */ int (*dev_open) (struct sr_dev_inst *sdi); int (*dev_close) (struct sr_dev_inst *sdi); + int (*dev_test) (struct sr_dev_inst *sdi); int (*dev_acquisition_start) (const struct sr_dev_inst *sdi, void *cb_data); int (*dev_acquisition_stop) (struct sr_dev_inst *sdi, @@ -804,10 +840,70 @@ struct sr_session { * an async fashion. We need to make sure the session is stopped from * within the session thread itself. */ - GMutex stop_mutex; +// GMutex stop_mutex; gboolean abort_session; }; +enum { + SIMPLE_TRIGGER = 0, + ADV_TRIGGER, +}; + +struct ds_trigger { + uint16_t trigger_en; + uint16_t trigger_mode; + uint16_t trigger_pos; + uint16_t trigger_stages; + unsigned char trigger_logic[TriggerStages+1]; + unsigned char trigger0_inv[TriggerStages+1]; + unsigned char trigger1_inv[TriggerStages+1]; + char trigger0[TriggerStages+1][TriggerProbes]; + char trigger1[TriggerStages+1][TriggerProbes]; + uint16_t trigger0_count[TriggerStages+1]; + uint16_t trigger1_count[TriggerStages+1]; +}; + +struct ds_trigger_pos { + uint32_t real_pos; + uint32_t ram_saddr; + unsigned char first_block[504]; +}; + +//struct libusbhp_t; +typedef void (*libusbhp_hotplug_cb_fn)(struct libusbhp_device_t *device, + void *user_data); +#ifdef __linux__ +#include + +struct dev_list_t { + char *path; + unsigned short vid; + unsigned short pid; + struct dev_list_t *next; +}; +#endif/*__linux__*/ + +struct libusbhp_t { +#ifdef __linux__ + struct udev* hotplug; + struct udev_monitor* hotplug_monitor; + struct dev_list_t *devlist; +#endif/*__linux__*/ +#ifdef _WIN32 + HWND hwnd; + HDEVNOTIFY hDeviceNotify; + WNDCLASSEX wcex; +#endif/*_WIN32*/ + libusbhp_hotplug_cb_fn attach; + libusbhp_hotplug_cb_fn detach; + void *user_data; +}; + +struct libusbhp_device_t { + unsigned short idVendor; + unsigned short idProduct; +}; + #include "proto.h" #include "version.h" diff --git a/libsigrok4DSLogic.pc.in b/libsigrok4DSLogic.pc.in new file mode 100644 index 00000000..92a23611 --- /dev/null +++ b/libsigrok4DSLogic.pc.in @@ -0,0 +1,15 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: libsigrok4DSLogic +Description: Backend library of DSLogic software based on libsigrok +URL: http://www.dreamsourcelab.com +Requires: glib-2.0 +Requires.private: @SR_PKGLIBS@ +Version: @VERSION@ +Libs: -L${libdir} -lsigrok4DSLogic +Libs.private: -lm +Cflags: -I${includedir} + diff --git a/libusbhp.c b/libusbhp.c new file mode 100644 index 00000000..c93f0795 --- /dev/null +++ b/libusbhp.c @@ -0,0 +1,392 @@ +/* + * This file is part of the DSLogic project. + */ + +#include "libsigrok.h" +#include "hardware/DSLogic/dslogic.h" + +#ifdef __linux__ +#include +#include +#include +#include +#include +#endif/*__linux__*/ + +#ifdef _WIN32 +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#endif/*_WIN32*/ + + + +#ifdef __linux__ +static void dev_list_add(struct libusbhp_t *h, const char *path, + unsigned short vid, unsigned short pid) +{ + struct dev_list_t *dev = + (struct dev_list_t*)malloc(sizeof(struct dev_list_t)); + dev->path = strdup(path); + dev->vid = vid; + dev->pid = pid; + dev->next = NULL; + + struct dev_list_t *p = h->devlist; + if(!p) { + h->devlist = dev; + return; + } + + while(p->next) { + p = p->next; + } + + p->next = dev; +} + +static int dev_list_remove(struct libusbhp_t *h, const char *path) +{ + struct dev_list_t *p = h->devlist; + if(!p) return 1; + + if(!strcmp(p->path, path)) { + h->devlist = p->next; + free(p->path); + free(p); + return 0; + } + + while(p->next) { + if(!strcmp(p->next->path, path)) { + struct dev_list_t *pp = p->next; + p->next = pp->next; + free(pp->path); + free(pp->next); + free(pp); + return 0; + } + p = p->next; + } + + // Not found + return 1; +} + +static int dev_list_find(struct libusbhp_t *h, const char *path, + unsigned short *vid, unsigned short *pid) +{ + struct dev_list_t *p = h->devlist; + while(p) { + if(!strcmp(p->path, path)) { + *vid = p->vid; + *pid = p->pid; + return 0; + } + p = p->next; + } + + // Not found + return 1; +} +#endif/*__linux__*/ + +#ifdef _WIN32 +SR_PRIV LRESULT CALLBACK WinProcCallback(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) +{ + struct libusbhp_t *h = (struct libusbhp_t*)GetWindowLong(hwnd, GWL_USERDATA); + + switch(msg) { + case WM_DEVICECHANGE: + { + PDEV_BROADCAST_HDR phdr = (PDEV_BROADCAST_HDR)lp; + + if(!phdr || phdr->dbch_devicetype != DBT_DEVTYP_DEVICEINTERFACE) break; + + PDEV_BROADCAST_DEVICEINTERFACE devif = + (PDEV_BROADCAST_DEVICEINTERFACE)lp; + + HDEVINFO devinfolist = SetupDiCreateDeviceInfoList(NULL, NULL); + + SP_DEVICE_INTERFACE_DATA devifdata; + memset(&devifdata, 0, sizeof(devifdata)); + devifdata.cbSize = sizeof(devifdata); + BOOL b = SetupDiOpenDeviceInterface(devinfolist, devif->dbcc_name, 0, + &devifdata); + + DWORD required; + SP_DEVICE_INTERFACE_DETAIL_DATA devdetaildata; + memset(&devdetaildata, 0, sizeof(devdetaildata)); + devdetaildata.cbSize = sizeof(devdetaildata); + + SP_DEVINFO_DATA devinfodata; + memset(&devinfodata, 0, sizeof(devinfodata)); + devinfodata.cbSize = sizeof(devinfodata); + b = SetupDiGetDeviceInterfaceDetail(devinfolist, &devifdata, + &devdetaildata, + sizeof(devdetaildata), + &required, &devinfodata); + + TCHAR deviceidw[1024]; + b = SetupDiGetDeviceInstanceIdW(devinfolist, &devinfodata, deviceidw, + sizeof(deviceidw), NULL); + + char deviceid[1024]; + //size_t sz; + //wcstombs_s(&sz, deviceid, deviceidw, sizeof(deviceid) - 1); + wcstombs(deviceid, deviceidw, sizeof(deviceid) - 1); + + char *vid = strstr(deviceid, "VID_"); + if(vid != NULL) vid += 4; + + char *pid = strstr(deviceid, "PID_"); + if(pid != NULL) pid += 4; + + struct libusbhp_device_t *device = NULL; + + if(pid || vid) { + device = + (struct libusbhp_device_t*)malloc(sizeof(struct libusbhp_device_t)); + } + + if(pid) { + pid[4] = '\0'; + device->idProduct = (unsigned short)strtol(pid, NULL, 16); + } + + if(vid) { + vid[4] = '\0'; + device->idVendor = (unsigned short)strtol(vid, NULL, 16); + } + + if ((device->idVendor == supported_fx2[0].vid) && + (device->idProduct == supported_fx2[0].pid)) { + switch(wp) { + case DBT_DEVICEARRIVAL: + if(h->attach) h->attach(device, h->user_data); + break; + case DBT_DEVICEREMOVECOMPLETE: + if(h->detach) h->detach(device, h->user_data); + break; + case DBT_DEVNODES_CHANGED: + default: + break; + } + } + + if(device) free(device); + } + break; + default: + break; + } + + return DefWindowProc(hwnd, msg, wp, lp); +} +#endif/*OS_WINDOWS*/ + +SR_API int libusbhp_init(struct libusbhp_t **handle) +{ + struct libusbhp_t *h = (struct libusbhp_t *)malloc(sizeof(struct libusbhp_t)); + + h->attach = NULL; + h->detach = NULL; + h->user_data = NULL; + +#ifdef __linux__ + h->devlist = NULL; + + // create the udev object + h->hotplug = udev_new(); + if(!h->hotplug) + { + printf("Cannot create udev object\n"); + free(h); + return 1; + } + + // create the udev monitor + h->hotplug_monitor = udev_monitor_new_from_netlink(h->hotplug, "udev"); + + // start receiving hotplug events + udev_monitor_filter_add_match_subsystem_devtype(h->hotplug_monitor, + "usb", "usb_device"); + udev_monitor_enable_receiving(h->hotplug_monitor); + + struct udev_enumerate *de = udev_enumerate_new (h->hotplug); + udev_enumerate_add_match_subsystem(de, "usb"); + udev_enumerate_scan_devices(de); + + struct udev_list_entry *lst = udev_enumerate_get_list_entry(de); + while(lst) { + struct udev_device *dev = + udev_device_new_from_syspath(h->hotplug, + udev_list_entry_get_name(lst)); + + if(udev_device_get_devnode(dev)) { + unsigned short idVendor = + strtol(udev_device_get_sysattr_value(dev, "idVendor"), NULL, 16); + unsigned short idProduct = + strtol(udev_device_get_sysattr_value(dev, "idProduct"), NULL, 16); + + dev_list_add(h, udev_device_get_devnode(dev), idVendor, idProduct); + } + + udev_device_unref(dev); + + lst = udev_list_entry_get_next(lst); + } + + udev_enumerate_unref(de); + +#endif/*__linux__*/ + +#ifdef _WIN32 + memset(&h->wcex, 0, sizeof(h->wcex)); + h->wcex.cbSize = sizeof(WNDCLASSEX); + h->wcex.lpfnWndProc = WinProcCallback; + h->wcex.hInstance = GetModuleHandle(NULL); + h->wcex.lpszClassName = TEXT("UsbHotplugClass"); + h->wcex.cbWndExtra = sizeof(struct libusbhp_t*); // Size of data. + + RegisterClassEx(&h->wcex); + + h->hwnd = + CreateWindowEx(0, h->wcex.lpszClassName, TEXT("UsbHotplug"), 0, 0, 0, 0, + 0, 0, NULL, GetModuleHandle(NULL), NULL); + + SetWindowLong(h->hwnd, GWL_USERDATA, (LONG)h); + + + DEV_BROADCAST_DEVICEINTERFACE *filter = + (DEV_BROADCAST_DEVICEINTERFACE*)malloc(sizeof(DEV_BROADCAST_DEVICEINTERFACE)); + + memset(filter, 0, sizeof(DEV_BROADCAST_DEVICEINTERFACE)); + filter->dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE); + filter->dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; + filter->dbcc_classguid = GUID_DEVINTERFACE_USB_DEVICE; + + h->hDeviceNotify = + RegisterDeviceNotification(h->hwnd, filter, DEVICE_NOTIFY_WINDOW_HANDLE); + + if(h->hDeviceNotify == 0) { + //printf("RegisterDeviceNotification error\n"); + free(h); + return 1; + } +#endif/*_WIN32*/ + + *handle = h; + return 0; +} + +SR_API void libusbhp_exit(struct libusbhp_t *h) +{ +#ifdef __linux__ + // destroy the udev monitor + udev_monitor_unref(h->hotplug_monitor); + + // destroy the udev object + udev_unref(h->hotplug); +#endif/*__linux__*/ + +#ifdef _WIN32 + UnregisterDeviceNotification(h->hDeviceNotify); + DestroyWindow(h->hwnd); + UnregisterClass(h->wcex.lpszClassName, h->wcex.hInstance); +#endif/*_WIN32*/ + + free(h); +} + +SR_API int libusbhp_handle_events_timeout(struct libusbhp_t *h, struct timeval *tv) +{ + int ms = tv->tv_sec * 1000 + tv->tv_usec / 1000; + +#ifdef __linux__ + // create the poll item + struct pollfd items[1]; + items[0].fd = udev_monitor_get_fd(h->hotplug_monitor); + items[0].events = POLLIN; + items[0].revents = 0; + + // while there are hotplug events to process + while(poll(items, 1, ms) > 0) { + // receive the relevant device + struct udev_device* dev = udev_monitor_receive_device(h->hotplug_monitor); + if(!dev) { + // error receiving device, skip it + continue; + } + + if(!strcmp(udev_device_get_action(dev), "add")) { + struct libusbhp_device_t device; + + device.idVendor = + strtol(udev_device_get_sysattr_value(dev, "idVendor"), NULL, 16); + device.idProduct = + strtol(udev_device_get_sysattr_value(dev, "idProduct"), NULL, 16); + + dev_list_add(h, udev_device_get_devnode(dev), + device.idVendor, device.idProduct); + + if(h->attach) h->attach(&device, h->user_data); + } + + if(!strcmp(udev_device_get_action(dev), "remove")) { + struct libusbhp_device_t device; + + int res = dev_list_find(h, udev_device_get_devnode(dev), + &device.idVendor, &device.idProduct); + + if(res) { + if(h->detach) h->detach(NULL, h->user_data); + } else { + dev_list_remove(h, udev_device_get_devnode(dev)); + if(h->detach) h->detach(&device, h->user_data); + } + } + + // destroy the relevant device + udev_device_unref(dev); + + // clear the revents + items[0].revents = 0; + } +#endif/*__linux__*/ + +#ifdef _WIN32 + UINT_PTR timer = SetTimer(h->hwnd, 0, ms, NULL); + + MSG msg; + int ret = GetMessage(&msg, NULL, 0, 0); + + if(ret <= 0) return 0; + + TranslateMessage(&msg); + DispatchMessage(&msg); + + KillTimer(h->hwnd, timer); +#endif/*_WIN32*/ + + return 0; +} + +SR_API void libusbhp_register_hotplug_listeners(struct libusbhp_t *handle, + libusbhp_hotplug_cb_fn connected_cb, + libusbhp_hotplug_cb_fn disconnected_cb, + void *user_data) +{ + handle->attach = connected_cb; + handle->detach = disconnected_cb; + handle->user_data = user_data; +} diff --git a/output/Makefile.am b/output/Makefile.am index 62f9842c..2bbe59c8 100644 --- a/output/Makefile.am +++ b/output/Makefile.am @@ -20,21 +20,18 @@ SUBDIRS = text # Local lib, this is NOT meant to be installed! -noinst_LTLIBRARIES = libsigrokoutput.la +noinst_LTLIBRARIES = libsigrok4DSLogicoutput.la -libsigrokoutput_la_SOURCES = \ - binary.c \ - vcd.c \ - ols.c \ - gnuplot.c \ - chronovu_la8.c \ - csv.c \ - analog.c \ +libsigrok4DSLogicoutput_la_SOURCES = \ + out_binary.c \ + out_vcd.c \ + out_csv.c \ + out_analog.c \ output.c -libsigrokoutput_la_CFLAGS = \ +libsigrok4DSLogicoutput_la_CFLAGS = \ -I$(top_srcdir) -libsigrokoutput_la_LIBADD = \ - text/libsigrokoutputtext.la +libsigrok4DSLogicoutput_la_LIBADD = \ + text/libsigrok4DSLogicoutputtext.la diff --git a/output/out_analog.c b/output/out_analog.c new file mode 100644 index 00000000..684f8826 --- /dev/null +++ b/output/out_analog.c @@ -0,0 +1,251 @@ +/* + * This file is part of the libsigrok project. + * + * Copyright (C) 2012 Bert Vermeulen + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include "libsigrok.h" +#include "libsigrok-internal.h" + +/* Message logging helpers with subsystem-specific prefix string. */ +#define LOG_PREFIX "output/analog: " +#define sr_log(l, s, args...) sr_log(l, LOG_PREFIX s, ## args) +#define sr_spew(s, args...) sr_spew(LOG_PREFIX s, ## args) +#define sr_dbg(s, args...) sr_dbg(LOG_PREFIX s, ## args) +#define sr_info(s, args...) sr_info(LOG_PREFIX s, ## args) +#define sr_warn(s, args...) sr_warn(LOG_PREFIX s, ## args) +#define sr_err(s, args...) sr_err(LOG_PREFIX s, ## args) + +struct context { + int num_enabled_probes; + GPtrArray *probelist; +}; + +static int init(struct sr_output *o) +{ + struct context *ctx; + struct sr_probe *probe; + GSList *l; + + sr_spew("Initializing output module."); + + if (!o || !o->sdi) + return SR_ERR_ARG; + + if (!(ctx = g_try_malloc0(sizeof(struct context)))) { + sr_err("Output module context malloc failed."); + return SR_ERR_MALLOC; + } + o->internal = ctx; + + /* Get the number of probes and their names. */ + ctx->probelist = g_ptr_array_new(); + for (l = o->sdi->probes; l; l = l->next) { + probe = l->data; + if (!probe || !probe->enabled) + continue; + g_ptr_array_add(ctx->probelist, probe->name); + ctx->num_enabled_probes++; + } + + return SR_OK; +} + +static void si_printf(float value, GString *out, char *unitstr) +{ + float v; + + if (signbit(value)) + v = -(value); + else + v = value; + + if (v < 1e-12 || v > 1e+12) + g_string_append_printf(out, "%f %s", value, unitstr); + else if (v > 1e+9) + g_string_append_printf(out, "%f G%s", value / 1e+9, unitstr); + else if (v > 1e+6) + g_string_append_printf(out, "%f M%s", value / 1e+6, unitstr); + else if (v > 1e+3) + g_string_append_printf(out, "%f k%s", value / 1e+3, unitstr); + else if (v < 1e-9) + g_string_append_printf(out, "%f n%s", value * 1e+9, unitstr); + else if (v < 1e-6) + g_string_append_printf(out, "%f u%s", value * 1e+6, unitstr); + else if (v < 1e-3) + g_string_append_printf(out, "%f m%s", value * 1e+3, unitstr); + else + g_string_append_printf(out, "%f %s", value, unitstr); + +} + +static void fancyprint(int unit, int mqflags, float value, GString *out) +{ + switch (unit) { + case SR_UNIT_VOLT: + si_printf(value, out, "V"); + break; + case SR_UNIT_AMPERE: + si_printf(value, out, "A"); + break; + case SR_UNIT_OHM: + si_printf(value, out, ""); + g_string_append_unichar(out, 0x2126); + break; + case SR_UNIT_FARAD: + si_printf(value, out, "F"); + break; + case SR_UNIT_KELVIN: + si_printf(value, out, "K"); + break; + case SR_UNIT_CELSIUS: + si_printf(value, out, ""); + g_string_append_unichar(out, 0x00b0); + g_string_append_c(out, 'C'); + break; + case SR_UNIT_FAHRENHEIT: + si_printf(value, out, ""); + g_string_append_unichar(out, 0x00b0); + g_string_append_c(out, 'F'); + break; + case SR_UNIT_HERTZ: + si_printf(value, out, "Hz"); + break; + case SR_UNIT_PERCENTAGE: + g_string_append_printf(out, "%f%%", value); + break; + case SR_UNIT_BOOLEAN: + if (value > 0) + g_string_append_printf(out, "TRUE"); + else + g_string_append_printf(out, "FALSE"); + break; + case SR_UNIT_SECOND: + si_printf(value, out, "s"); + break; + case SR_UNIT_SIEMENS: + si_printf(value, out, "S"); + break; + case SR_UNIT_DECIBEL_MW: + si_printf(value, out, "dBu"); + break; + case SR_UNIT_DECIBEL_VOLT: + si_printf(value, out, "dBV"); + break; + case SR_UNIT_DECIBEL_SPL: + if (mqflags & SR_MQFLAG_SPL_FREQ_WEIGHT_A) + si_printf(value, out, "dB(A)"); + else if (mqflags & SR_MQFLAG_SPL_FREQ_WEIGHT_C) + si_printf(value, out, "dB(C)"); + else if (mqflags & SR_MQFLAG_SPL_FREQ_WEIGHT_Z) + si_printf(value, out, "dB(Z)"); + else + /* No frequency weighting, or non-standard "flat" */ + si_printf(value, out, "dB(SPL)"); + if (mqflags & SR_MQFLAG_SPL_TIME_WEIGHT_S) + g_string_append(out, " S"); + else if (mqflags & SR_MQFLAG_SPL_TIME_WEIGHT_F) + g_string_append(out, " F"); + if (mqflags & SR_MQFLAG_SPL_LAT) + g_string_append(out, " LAT"); + else if (mqflags & SR_MQFLAG_SPL_PCT_OVER_ALARM) + /* Not a standard function for SLMs, so this is + * a made-up notation. */ + g_string_append(out, " %oA"); + break; + case SR_UNIT_CONCENTRATION: + g_string_append_printf(out, "%f ppm", value * 1000000); + break; + default: + si_printf(value, out, ""); + break; + } + if ((mqflags & (SR_MQFLAG_AC | SR_MQFLAG_DC)) == (SR_MQFLAG_AC | SR_MQFLAG_DC)) + g_string_append_printf(out, " AC+DC"); + else if (mqflags & SR_MQFLAG_AC) + g_string_append_printf(out, " AC"); + else if (mqflags & SR_MQFLAG_DC) + g_string_append_printf(out, " DC"); + g_string_append_c(out, '\n'); +} + +static int receive(struct sr_output *o, const struct sr_dev_inst *sdi, + const struct sr_datafeed_packet *packet, GString **out) +{ + const struct sr_datafeed_analog *analog; + struct sr_probe *probe; + GSList *l; + const float *fdata; + int i, p; + + (void)sdi; + + *out = NULL; + if (!o || !o->sdi) + return SR_ERR_ARG; + + switch (packet->type) { + case SR_DF_FRAME_BEGIN: + *out = g_string_new("FRAME-BEGIN\n"); + break; + case SR_DF_FRAME_END: + *out = g_string_new("FRAME-END\n"); + break; + case SR_DF_ANALOG: + analog = packet->payload; + fdata = (const float *)analog->data; + *out = g_string_sized_new(512); + for (i = 0; i < analog->num_samples; i++) { + for (l = analog->probes, p = 0; l; l = l->next, p++) { + probe = l->data; + g_string_append_printf(*out, "%s: ", probe->name); + fancyprint(analog->unit, analog->mqflags, + fdata[i + p], *out); + } + } + break; + } + + return SR_OK; +} + +static int cleanup(struct sr_output *o) +{ + struct context *ctx; + + if (!o || !o->sdi) + return SR_ERR_ARG; + ctx = o->internal; + + g_ptr_array_free(ctx->probelist, 1); + g_free(ctx); + o->internal = NULL; + + return SR_OK; +} + +SR_PRIV struct sr_output_format output_analog = { + .id = "analog", + .description = "Analog data", + .df_type = SR_DF_ANALOG, + .init = init, + .receive = receive, + .cleanup = cleanup +}; diff --git a/output/out_binary.c b/output/out_binary.c new file mode 100644 index 00000000..2fd858eb --- /dev/null +++ b/output/out_binary.c @@ -0,0 +1,77 @@ +/* + * This file is part of the libsigrok project. + * + * Copyright (C) 2010 Uwe Hermann + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include "libsigrok.h" +#include "libsigrok-internal.h" + +/* Message logging helpers with subsystem-specific prefix string. */ +#define LOG_PREFIX "output/binary: " +#define sr_log(l, s, args...) sr_log(l, LOG_PREFIX s, ## args) +#define sr_spew(s, args...) sr_spew(LOG_PREFIX s, ## args) +#define sr_dbg(s, args...) sr_dbg(LOG_PREFIX s, ## args) +#define sr_info(s, args...) sr_info(LOG_PREFIX s, ## args) +#define sr_warn(s, args...) sr_warn(LOG_PREFIX s, ## args) +#define sr_err(s, args...) sr_err(LOG_PREFIX s, ## args) + +static int data(struct sr_output *o, const uint8_t *data_in, + uint64_t length_in, uint8_t **data_out, uint64_t *length_out) +{ + uint8_t *outbuf; + + (void)o; + + if (!data_in) { + sr_err("%s: data_in was NULL", __func__); + return SR_ERR_ARG; + } + + if (!length_out) { + sr_err("%s: length_out was NULL", __func__); + return SR_ERR_ARG; + } + + if (length_in == 0) { + sr_err("%s: length_in was 0", __func__); + return SR_ERR_ARG; + } + + if (!(outbuf = g_try_malloc0(length_in))) { + sr_err("%s: outbuf malloc failed", __func__); + return SR_ERR_MALLOC; + } + + memcpy(outbuf, data_in, length_in); + *data_out = outbuf; + *length_out = length_in; + + return SR_OK; +} + +SR_PRIV struct sr_output_format output_binary = { + .id = "binary", + .description = "Raw binary", + .df_type = SR_DF_LOGIC, + .init = NULL, + .data = data, + .event = NULL, +}; diff --git a/output/out_csv.c b/output/out_csv.c new file mode 100644 index 00000000..0a7c5044 --- /dev/null +++ b/output/out_csv.c @@ -0,0 +1,225 @@ +/* + * This file is part of the libsigrok project. + * + * Copyright (C) 2011 Uwe Hermann + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include "config.h" /* Needed for PACKAGE_STRING and others. */ +#include "libsigrok.h" +#include "libsigrok-internal.h" + +/* Message logging helpers with subsystem-specific prefix string. */ +#define LOG_PREFIX "output/csv: " +#define sr_log(l, s, args...) sr_log(l, LOG_PREFIX s, ## args) +#define sr_spew(s, args...) sr_spew(LOG_PREFIX s, ## args) +#define sr_dbg(s, args...) sr_dbg(LOG_PREFIX s, ## args) +#define sr_info(s, args...) sr_info(LOG_PREFIX s, ## args) +#define sr_warn(s, args...) sr_warn(LOG_PREFIX s, ## args) +#define sr_err(s, args...) sr_err(LOG_PREFIX s, ## args) + +struct context { + unsigned int num_enabled_probes; + unsigned int unitsize; + uint64_t samplerate; + GString *header; + char separator; +}; + +/* + * TODO: + * - Option to specify delimiter character and/or string. + * - Option to (not) print metadata as comments. + * - Option to specify the comment character(s), e.g. # or ; or C/C++-style. + * - Option to (not) print samplenumber / time as extra column. + * - Option to "compress" output (only print changed samples, VCD-like). + * - Option to print comma-separated bits, or whole bytes/words (for 8/16 + * probe LAs) as ASCII/hex etc. etc. + * - Trigger support. + */ + +static int init(struct sr_output *o) +{ + struct context *ctx; + struct sr_probe *probe; + GSList *l; + GVariant *gvar; + int num_probes; + time_t t; + + if (!o) { + sr_err("%s: o was NULL", __func__); + return SR_ERR_ARG; + } + + if (!o->sdi) { + sr_err("%s: o->sdi was NULL", __func__); + return SR_ERR_ARG; + } + + if (!(ctx = g_try_malloc0(sizeof(struct context)))) { + sr_err("%s: ctx malloc failed", __func__); + return SR_ERR_MALLOC; + } + + o->internal = ctx; + + /* Get the number of probes, and the unitsize. */ + for (l = o->sdi->probes; l; l = l->next) { + probe = l->data; + if (probe->enabled) + ctx->num_enabled_probes++; + } + + ctx->unitsize = (ctx->num_enabled_probes + 7) / 8; + + num_probes = g_slist_length(o->sdi->probes); + + if (sr_config_get(o->sdi->driver, SR_CONF_SAMPLERATE, &gvar, + o->sdi) == SR_OK) { + ctx->samplerate = g_variant_get_uint64(gvar); + g_variant_unref(gvar); + } else + ctx->samplerate = 0; + + ctx->separator = ','; + ctx->header = g_string_sized_new(512); + + t = time(NULL); + + /* Some metadata */ + g_string_append_printf(ctx->header, "; CSV, generated by %s on %s", + PACKAGE_STRING, ctime(&t)); + g_string_append_printf(ctx->header, "; Samplerate: %"PRIu64"\n", + ctx->samplerate); + + /* Columns / channels */ + g_string_append_printf(ctx->header, "; Channels (%d/%d): ", + ctx->num_enabled_probes, num_probes); + for (l = o->sdi->probes; l; l = l->next) { + probe = l->data; + if (probe->enabled) + g_string_append_printf(ctx->header, "%s, ", probe->name); + } + g_string_append_printf(ctx->header, "\n"); + + return SR_OK; +} + +static int event(struct sr_output *o, int event_type, uint8_t **data_out, + uint64_t *length_out) +{ + struct context *ctx; + + if (!o) { + sr_err("%s: o was NULL", __func__); + return SR_ERR_ARG; + } + + if (!(ctx = o->internal)) { + sr_err("%s: o->internal was NULL", __func__); + return SR_ERR_ARG; + } + + if (!data_out) { + sr_err("%s: data_out was NULL", __func__); + return SR_ERR_ARG; + } + + switch (event_type) { + case SR_DF_TRIGGER: + sr_dbg("%s: SR_DF_TRIGGER event", __func__); + /* TODO */ + *data_out = NULL; + *length_out = 0; + break; + case SR_DF_END: + sr_dbg("%s: SR_DF_END event", __func__); + /* TODO */ + *data_out = NULL; + *length_out = 0; + g_free(o->internal); + o->internal = NULL; + break; + default: + sr_err("%s: unsupported event type: %d", __func__, event_type); + *data_out = NULL; + *length_out = 0; + break; + } + + return SR_OK; +} + +static int data(struct sr_output *o, const uint8_t *data_in, + uint64_t length_in, uint8_t **data_out, uint64_t *length_out) +{ + struct context *ctx; + GString *outstr; + uint64_t sample, i; + int j; + + if (!o) { + sr_err("%s: o was NULL", __func__); + return SR_ERR_ARG; + } + + if (!(ctx = o->internal)) { + sr_err("%s: o->internal was NULL", __func__); + return SR_ERR_ARG; + } + + if (!data_in) { + sr_err("%s: data_in was NULL", __func__); + return SR_ERR_ARG; + } + + if (ctx->header) { + /* First data packet. */ + outstr = ctx->header; + ctx->header = NULL; + } else { + outstr = g_string_sized_new(512); + } + + for (i = 0; i <= length_in - ctx->unitsize; i += ctx->unitsize) { + memcpy(&sample, data_in + i, ctx->unitsize); + for (j = ctx->num_enabled_probes - 1; j >= 0; j--) { + g_string_append_printf(outstr, "%d%c", + (int)((sample & (1 << j)) >> j), + ctx->separator); + } + g_string_append_printf(outstr, "\n"); + } + + *data_out = (uint8_t *)outstr->str; + *length_out = outstr->len; + g_string_free(outstr, FALSE); + + return SR_OK; +} + +SR_PRIV struct sr_output_format output_csv = { + .id = "csv", + .description = "Comma-separated values (CSV)", + .df_type = SR_DF_LOGIC, + .init = init, + .data = data, + .event = event, +}; diff --git a/output/out_vcd.c b/output/out_vcd.c new file mode 100644 index 00000000..04d7fcbb --- /dev/null +++ b/output/out_vcd.c @@ -0,0 +1,231 @@ +/* + * This file is part of the libsigrok project. + * + * Copyright (C) 2010 Uwe Hermann + * Copyright (C) 2013 Bert Vermeulen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include "config.h" /* Needed for PACKAGE and others. */ +#include "libsigrok.h" +#include "libsigrok-internal.h" + +/* Message logging helpers with subsystem-specific prefix string. */ +#define LOG_PREFIX "output/vcd: " +#define sr_log(l, s, args...) sr_log(l, LOG_PREFIX s, ## args) +#define sr_spew(s, args...) sr_spew(LOG_PREFIX s, ## args) +#define sr_dbg(s, args...) sr_dbg(LOG_PREFIX s, ## args) +#define sr_info(s, args...) sr_info(LOG_PREFIX s, ## args) +#define sr_warn(s, args...) sr_warn(LOG_PREFIX s, ## args) +#define sr_err(s, args...) sr_err(LOG_PREFIX s, ## args) + +struct context { + int num_enabled_probes; + GArray *probeindices; + GString *header; + uint8_t *prevsample; + int period; + uint64_t samplerate; + unsigned int unitsize; +}; + +static const char *vcd_header_comment = "\ +$comment\n Acquisition with %d/%d probes at %s\n$end\n"; + +static int init(struct sr_output *o) +{ + struct context *ctx; + struct sr_probe *probe; + GSList *l; + GVariant *gvar; + int num_probes, i; + char *samplerate_s, *frequency_s, *timestamp; + time_t t; + + if (!(ctx = g_try_malloc0(sizeof(struct context)))) { + sr_err("%s: ctx malloc failed", __func__); + return SR_ERR_MALLOC; + } + + o->internal = ctx; + ctx->num_enabled_probes = 0; + ctx->probeindices = g_array_new(FALSE, FALSE, sizeof(int)); + + for (l = o->sdi->probes; l; l = l->next) { + probe = l->data; + if (!probe->enabled) + continue; + ctx->probeindices = g_array_append_val( + ctx->probeindices, probe->index); + ctx->num_enabled_probes++; + } + if (ctx->num_enabled_probes > 94) { + sr_err("VCD only supports 94 probes."); + return SR_ERR; + } + + ctx->unitsize = (ctx->num_enabled_probes + 7) / 8; + ctx->header = g_string_sized_new(512); + num_probes = g_slist_length(o->sdi->probes); + + /* timestamp */ + t = time(NULL); + timestamp = g_strdup(ctime(&t)); + timestamp[strlen(timestamp)-1] = 0; + g_string_printf(ctx->header, "$date %s $end\n", timestamp); + g_free(timestamp); + + /* generator */ + g_string_append_printf(ctx->header, "$version %s %s $end\n", + PACKAGE, PACKAGE_VERSION); + + if (sr_config_get(o->sdi->driver, SR_CONF_SAMPLERATE, &gvar, + o->sdi) == SR_OK) { + ctx->samplerate = g_variant_get_uint64(gvar); + g_variant_unref(gvar); + if (!((samplerate_s = sr_samplerate_string(ctx->samplerate)))) { + g_string_free(ctx->header, TRUE); + g_free(ctx); + return SR_ERR; + } + g_string_append_printf(ctx->header, vcd_header_comment, + ctx->num_enabled_probes, num_probes, samplerate_s); + g_free(samplerate_s); + } + + /* timescale */ + /* VCD can only handle 1/10/100 (s - fs), so scale up first */ + if (ctx->samplerate > SR_MHZ(1)) + ctx->period = SR_GHZ(1); + else if (ctx->samplerate > SR_KHZ(1)) + ctx->period = SR_MHZ(1); + else + ctx->period = SR_KHZ(1); + if (!(frequency_s = sr_period_string(ctx->period))) { + g_string_free(ctx->header, TRUE); + g_free(ctx); + return SR_ERR; + } + g_string_append_printf(ctx->header, "$timescale %s $end\n", frequency_s); + g_free(frequency_s); + + /* scope */ + g_string_append_printf(ctx->header, "$scope module %s $end\n", PACKAGE); + + /* Wires / channels */ + for (i = 0, l = o->sdi->probes; l; l = l->next, i++) { + probe = l->data; + if (!probe->enabled) + continue; + g_string_append_printf(ctx->header, "$var wire 1 %c %s $end\n", + (char)('!' + i), probe->name); + } + + g_string_append(ctx->header, "$upscope $end\n" + "$enddefinitions $end\n$dumpvars\n"); + + if (!(ctx->prevsample = g_try_malloc0(ctx->unitsize))) { + g_string_free(ctx->header, TRUE); + g_free(ctx); + sr_err("%s: ctx->prevsample malloc failed", __func__); + return SR_ERR_MALLOC; + } + + return SR_OK; +} + +static int receive(struct sr_output *o, const struct sr_dev_inst *sdi, + const struct sr_datafeed_packet *packet, GString **out) +{ + const struct sr_datafeed_logic *logic; + struct context *ctx; + unsigned int i; + int p, curbit, prevbit, index; + uint8_t *sample; + static uint64_t samplecount = 0; + + (void)sdi; + + *out = NULL; + if (!o || !o->internal) + return SR_ERR_ARG; + ctx = o->internal; + + if (packet->type == SR_DF_END) { + *out = g_string_new("$dumpoff\n$end\n"); + return SR_OK; + } else if (packet->type != SR_DF_LOGIC) + return SR_OK; + + if (ctx->header) { + /* The header is still here, this must be the first packet. */ + *out = ctx->header; + ctx->header = NULL; + } else { + *out = g_string_sized_new(512); + } + + logic = packet->payload; + for (i = 0; i <= logic->length - logic->unitsize; i += logic->unitsize) { + samplecount++; + + sample = logic->data + i; + + for (p = 0; p < ctx->num_enabled_probes; p++) { + index = g_array_index(ctx->probeindices, int, p); + curbit = (sample[p / 8] & (((uint8_t) 1) << index)) >> index; + prevbit = (ctx->prevsample[p / 8] & (((uint64_t) 1) << index)) >> index; + + /* VCD only contains deltas/changes of signals. */ + if (prevbit == curbit) + continue; + + /* Output which signal changed to which value. */ + g_string_append_printf(*out, "#%" PRIu64 "\n%i%c\n", + (uint64_t)(((float)samplecount / ctx->samplerate) + * ctx->period), curbit, (char)('!' + p)); + } + + memcpy(ctx->prevsample, sample, ctx->unitsize); + } + + return SR_OK; +} + +static int cleanup(struct sr_output *o) +{ + struct context *ctx; + + if (!o || !o->internal) + return SR_ERR_ARG; + + ctx = o->internal; + g_free(ctx); + + return SR_OK; +} + +struct sr_output_format output_vcd = { + .id = "vcd", + .description = "Value Change Dump (VCD)", + .df_type = SR_DF_LOGIC, + .init = init, + .receive = receive, + .cleanup = cleanup, +}; diff --git a/output/output.c b/output/output.c index a3e5dc79..62ce0c18 100644 --- a/output/output.c +++ b/output/output.c @@ -54,9 +54,7 @@ extern SR_PRIV struct sr_output_format output_text_hex; extern SR_PRIV struct sr_output_format output_text_ascii; extern SR_PRIV struct sr_output_format output_binary; extern SR_PRIV struct sr_output_format output_vcd; -extern SR_PRIV struct sr_output_format output_ols; -extern SR_PRIV struct sr_output_format output_gnuplot; -extern SR_PRIV struct sr_output_format output_chronovu_la8; + extern SR_PRIV struct sr_output_format output_csv; extern SR_PRIV struct sr_output_format output_analog; /* extern SR_PRIV struct sr_output_format output_analog_gnuplot; */ @@ -68,9 +66,6 @@ static struct sr_output_format *output_module_list[] = { &output_text_ascii, &output_binary, &output_vcd, - &output_ols, - &output_gnuplot, - &output_chronovu_la8, &output_csv, &output_analog, /* &output_analog_gnuplot, */ diff --git a/output/text/Makefile.am b/output/text/Makefile.am index 348892c0..a6edae8d 100644 --- a/output/text/Makefile.am +++ b/output/text/Makefile.am @@ -19,15 +19,15 @@ ## # Local lib, this is NOT meant to be installed! -noinst_LTLIBRARIES = libsigrokoutputtext.la +noinst_LTLIBRARIES = libsigrok4DSLogicoutputtext.la -libsigrokoutputtext_la_SOURCES = \ +libsigrok4DSLogicoutputtext_la_SOURCES = \ text.c \ text.h \ bits.c \ hex.c \ ascii.c -libsigrokoutputtext_la_CFLAGS = \ +libsigrok4DSLogicoutputtext_la_CFLAGS = \ -I$(top_srcdir) diff --git a/proto.h b/proto.h index 821846f2..322dc2d2 100644 --- a/proto.h +++ b/proto.h @@ -103,11 +103,11 @@ SR_API int sr_session_stop(void); SR_API int sr_session_save(const char *filename, const struct sr_dev_inst *sdi, unsigned char *buf, int unitsize, int units); SR_API int sr_session_source_add(int fd, int events, int timeout, - sr_receive_data_callback_t cb, void *cb_data); + sr_receive_data_callback_t cb, const struct sr_dev_inst *sdi); SR_API int sr_session_source_add_pollfd(GPollFD *pollfd, int timeout, - sr_receive_data_callback_t cb, void *cb_data); + sr_receive_data_callback_t cb, const struct sr_dev_inst *sdi); SR_API int sr_session_source_add_channel(GIOChannel *channel, int events, - int timeout, sr_receive_data_callback_t cb, void *cb_data); + int timeout, sr_receive_data_callback_t cb, const struct sr_dev_inst *sdi); SR_API int sr_session_source_remove(int fd); SR_API int sr_session_source_remove_pollfd(GPollFD *pollfd); SR_API int sr_session_source_remove_channel(GIOChannel *channel); @@ -151,4 +151,29 @@ SR_API const char *sr_lib_version_string_get(void); SR_API const char *sr_strerror(int error_code); SR_API const char *sr_strerror_name(int error_code); +/*--- libusbhp.c ------------------------------------------------------------*/ +SR_API int libusbhp_init(struct libusbhp_t **handle); + +SR_API void libusbhp_exit(struct libusbhp_t *handle); + +SR_API int libusbhp_handle_events_timeout(struct libusbhp_t *handle, struct timeval *tv); + +SR_API void libusbhp_register_hotplug_listeners(struct libusbhp_t *handle, + libusbhp_hotplug_cb_fn connected_cb, + libusbhp_hotplug_cb_fn disconnected_cb, + void *user_data); + +/*--- trigger.c ------------------------------------------------------------*/ +SR_API int ds_trigger_init(void); +SR_API int ds_trigger_destroy(void); +SR_API int ds_trigger_stage_set_value(uint16_t stage, uint16_t probes, char *trigger0, char *trigger1); +SR_API int ds_trigger_stage_set_logic(uint16_t stage, uint16_t probes, unsigned char trigger_logic); +SR_API int ds_trigger_stage_set_inv(uint16_t stage, uint16_t probes, unsigned char trigger0_inv, unsigned char trigger1_inv); +SR_API int ds_trigger_stage_set_count(uint16_t stage, uint16_t probes, uint16_t trigger0_count, uint16_t trigger1_count); +SR_API int ds_trigger_probe_set(uint16_t probe, unsigned char trigger0, unsigned char trigger1); +SR_API int ds_trigger_set_stage(uint16_t stages); +SR_API int ds_trigger_set_pos(uint16_t position); +SR_API int ds_trigger_set_en(uint16_t enable); +SR_API int ds_trigger_set_mode(uint16_t mode); + #endif diff --git a/session.c b/session.c index 4fa5dafe..29e19085 100644 --- a/session.c +++ b/session.c @@ -85,7 +85,7 @@ SR_API struct sr_session *sr_session_new(void) session->source_timeout = -1; session->abort_session = FALSE; - g_mutex_init(&session->stop_mutex); +// g_mutex_init(&session->stop_mutex); return session; } @@ -106,9 +106,21 @@ SR_API int sr_session_destroy(void) sr_session_dev_remove_all(); + sr_session_datafeed_callback_remove_all(); + + if (session->sources) { + g_free(session->sources); + session->sources = NULL; + } + + if (session->pollfds) { + g_free(session->pollfds); + session->pollfds = NULL; + } + /* TODO: Error checks needed? */ - g_mutex_clear(&session->stop_mutex); +// g_mutex_clear(&session->stop_mutex); g_free(session); session = NULL; @@ -259,13 +271,13 @@ static int sr_session_run_poll(void) * we check the flag after processing every source, not * just once per main event loop. */ - g_mutex_lock(&session->stop_mutex); +// g_mutex_lock(&session->stop_mutex); if (session->abort_session) { sr_session_stop_sync(); /* But once is enough. */ session->abort_session = FALSE; } - g_mutex_unlock(&session->stop_mutex); +// g_mutex_unlock(&session->stop_mutex); } } @@ -376,7 +388,7 @@ SR_PRIV int sr_session_stop_sync(void) sdi = l->data; if (sdi->driver) { if (sdi->driver->dev_acquisition_stop) - sdi->driver->dev_acquisition_stop(sdi, sdi); + sdi->driver->dev_acquisition_stop(sdi, NULL); } } @@ -403,9 +415,9 @@ SR_API int sr_session_stop(void) return SR_ERR_BUG; } - g_mutex_lock(&session->stop_mutex); +// g_mutex_lock(&session->stop_mutex); session->abort_session = TRUE; - g_mutex_unlock(&session->stop_mutex); +// g_mutex_unlock(&session->stop_mutex); return SR_OK; } @@ -506,7 +518,7 @@ SR_PRIV int sr_session_send(const struct sr_dev_inst *sdi, * SR_ERR_MALLOC upon memory allocation errors. */ static int _sr_session_source_add(GPollFD *pollfd, int timeout, - sr_receive_data_callback_t cb, void *cb_data, gintptr poll_object) + sr_receive_data_callback_t cb, const struct sr_dev_inst *sdi, gintptr poll_object) { struct source *new_sources, *s; GPollFD *new_pollfds; @@ -536,7 +548,7 @@ static int _sr_session_source_add(GPollFD *pollfd, int timeout, s = &new_sources[session->num_sources++]; s->timeout = timeout; s->cb = cb; - s->cb_data = cb_data; + s->cb_data = sdi; s->poll_object = poll_object; session->pollfds = new_pollfds; session->sources = new_sources; @@ -561,14 +573,14 @@ static int _sr_session_source_add(GPollFD *pollfd, int timeout, * SR_ERR_MALLOC upon memory allocation errors. */ SR_API int sr_session_source_add(int fd, int events, int timeout, - sr_receive_data_callback_t cb, void *cb_data) + sr_receive_data_callback_t cb, const struct sr_dev_inst *sdi) { GPollFD p; p.fd = fd; p.events = events; - return _sr_session_source_add(&p, timeout, cb, cb_data, (gintptr)fd); + return _sr_session_source_add(&p, timeout, cb, sdi, (gintptr)fd); } /** @@ -583,10 +595,10 @@ SR_API int sr_session_source_add(int fd, int events, int timeout, * SR_ERR_MALLOC upon memory allocation errors. */ SR_API int sr_session_source_add_pollfd(GPollFD *pollfd, int timeout, - sr_receive_data_callback_t cb, void *cb_data) + sr_receive_data_callback_t cb, const struct sr_dev_inst *sdi) { - return _sr_session_source_add(pollfd, timeout, cb, - cb_data, (gintptr)pollfd); + return _sr_session_source_add(pollfd, timeout, cb, + sdi, (gintptr)pollfd); } /** @@ -602,7 +614,7 @@ SR_API int sr_session_source_add_pollfd(GPollFD *pollfd, int timeout, * SR_ERR_MALLOC upon memory allocation errors. */ SR_API int sr_session_source_add_channel(GIOChannel *channel, int events, - int timeout, sr_receive_data_callback_t cb, void *cb_data) + int timeout, sr_receive_data_callback_t cb, const struct sr_dev_inst *sdi) { GPollFD p; @@ -613,7 +625,7 @@ SR_API int sr_session_source_add_channel(GIOChannel *channel, int events, p.events = events; #endif - return _sr_session_source_add(&p, timeout, cb, cb_data, (gintptr)channel); + return _sr_session_source_add(&p, timeout, cb, sdi, (gintptr)channel); } /** diff --git a/session_driver.c b/session_driver.c index 9df848d4..b040c072 100644 --- a/session_driver.c +++ b/session_driver.c @@ -47,6 +47,7 @@ struct session_vdev { struct zip_file *capfile; int bytes_read; uint64_t samplerate; + uint64_t total_samples; int unitsize; int num_probes; }; @@ -58,7 +59,7 @@ static const int hwcaps[] = { 0, }; -static int receive_data(int fd, int revents, void *cb_data) +static int receive_data(int fd, int revents, const struct sr_dev_inst *cb_sdi) { struct sr_dev_inst *sdi; struct session_vdev *vdev; @@ -95,7 +96,7 @@ static int receive_data(int fd, int revents, void *cb_data) logic.unitsize = vdev->unitsize; logic.data = buf; vdev->bytes_read += ret; - sr_session_send(cb_data, &packet); + sr_session_send(cb_sdi, &packet); } else { /* done with this capture file */ zip_fclose(vdev->capfile); @@ -107,7 +108,7 @@ static int receive_data(int fd, int revents, void *cb_data) if (!got_data) { packet.type = SR_DF_END; - sr_session_send(cb_data, &packet); + sr_session_send(cb_sdi, &packet); sr_session_source_remove(-1); } @@ -160,6 +161,13 @@ static int config_get(int id, GVariant **data, const struct sr_dev_inst *sdi) } else return SR_ERR; break; + case SR_CONF_LIMIT_SAMPLES: + if (sdi) { + vdev = sdi->priv; + *data = g_variant_new_uint64(vdev->total_samples); + } else + return SR_ERR; + break; default: return SR_ERR_ARG; } @@ -189,6 +197,9 @@ static int config_set(int id, GVariant *data, const struct sr_dev_inst *sdi) case SR_CONF_CAPTURE_UNITSIZE: vdev->unitsize = g_variant_get_uint64(data); break; + case SR_CONF_LIMIT_SAMPLES: + vdev->total_samples = g_variant_get_uint64(data); + break; case SR_CONF_CAPTURE_NUM_PROBES: vdev->num_probes = g_variant_get_uint64(data); break; @@ -207,8 +218,10 @@ static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi) switch (key) { case SR_CONF_DEVICE_OPTIONS: - *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32, - hwcaps, ARRAY_SIZE(hwcaps), sizeof(int32_t)); +// *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32, +// hwcaps, ARRAY_SIZE(hwcaps), sizeof(int32_t)); + *data = g_variant_new_from_data(G_VARIANT_TYPE("ai"), + hwcaps, ARRAY_SIZE(hwcaps)*sizeof(int32_t), TRUE, NULL, NULL); break; default: return SR_ERR_ARG; @@ -248,10 +261,10 @@ static int hw_dev_acquisition_start(const struct sr_dev_inst *sdi, } /* Send header packet to the session bus. */ - std_session_send_df_header(cb_data, LOG_PREFIX); + std_session_send_df_header(sdi, LOG_PREFIX); /* freewheeling source */ - sr_session_source_add(-1, 0, 0, receive_data, cb_data); + sr_session_source_add(-1, 0, 0, receive_data, sdi); return SR_OK; } diff --git a/session_file.c b/session_file.c index 4838a6be..43ba01c3 100644 --- a/session_file.c +++ b/session_file.c @@ -84,27 +84,9 @@ SR_API int sr_session_load(const char *filename) return SR_ERR; } - /* check "version" */ - version = 0; - if (!(zf = zip_fopen(archive, "version", 0))) { - sr_dbg("Not a sigrok session file."); - return SR_ERR; - } - if ((ret = zip_fread(zf, s, 10)) == -1) { - sr_dbg("Not a valid sigrok session file."); - return SR_ERR; - } - zip_fclose(zf); - s[ret] = 0; - version = strtoull(s, NULL, 10); - if (version != 1) { - sr_dbg("Not a valid sigrok session file version."); - return SR_ERR; - } - /* read "metadata" */ - if (zip_stat(archive, "metadata", 0, &zs) == -1) { - sr_dbg("Not a valid sigrok session file."); + if (zip_stat(archive, "header", 0, &zs) == -1) { + sr_dbg("Not a valid DSLogic session file."); return SR_ERR; } @@ -129,10 +111,10 @@ SR_API int sr_session_load(const char *filename) capturefiles = g_ptr_array_new_with_free_func(g_free); sections = g_key_file_get_groups(kf, NULL); for (i = 0; sections[i]; i++) { - if (!strcmp(sections[i], "global")) + if (!strcmp(sections[i], "version")) /* nothing really interesting in here yet */ continue; - if (!strncmp(sections[i], "device ", 7)) { + if (!strncmp(sections[i], "header", 6)) { /* device section */ sdi = NULL; enabled_probes = total_probes = 0; @@ -140,7 +122,7 @@ SR_API int sr_session_load(const char *filename) for (j = 0; keys[j]; j++) { val = g_key_file_get_string(kf, sections[i], keys[j], NULL); if (!strcmp(keys[j], "capturefile")) { - sdi = sr_dev_inst_new(devcnt, SR_ST_ACTIVE, NULL, NULL, NULL); + sdi = sr_dev_inst_new(LOGIC, devcnt, SR_ST_ACTIVE, NULL, NULL, NULL); sdi->driver = &session_driver; if (devcnt == 0) /* first device, init the driver */ @@ -160,6 +142,10 @@ SR_API int sr_session_load(const char *filename) tmp_u64 = strtoull(val, NULL, 10); sdi->driver->config_set(SR_CONF_CAPTURE_UNITSIZE, g_variant_new_uint64(tmp_u64), sdi); + } else if (!strcmp(keys[j], "total samples")) { + tmp_u64 = strtoull(val, NULL, 10); + sdi->driver->config_set(SR_CONF_LIMIT_SAMPLES, + g_variant_new_uint64(tmp_u64), sdi); } else if (!strcmp(keys[j], "total probes")) { total_probes = strtoull(val, NULL, 10); sdi->driver->config_set(SR_CONF_CAPTURE_NUM_PROBES, @@ -213,15 +199,15 @@ SR_API int sr_session_load(const char *filename) SR_API int sr_session_save(const char *filename, const struct sr_dev_inst *sdi, unsigned char *buf, int unitsize, int units) { - GSList *l; - GVariant *gvar; - FILE *meta; - struct sr_probe *probe; - struct zip *zipfile; - struct zip_source *versrc, *metasrc, *logicsrc; - int tmpfile, ret, probecnt; - uint64_t samplerate; - char version[1], rawname[16], metafile[32], *s; + GSList *l; + GVariant *gvar; + FILE *meta; + struct sr_probe *probe; + struct zip *zipfile; + struct zip_source *versrc, *metasrc, *logicsrc; + int tmpfile, ret, probecnt; + uint64_t samplerate; + char rawname[16], metafile[32], *s; if (!filename) { sr_err("%s: filename was NULL", __func__); @@ -233,77 +219,68 @@ SR_API int sr_session_save(const char *filename, const struct sr_dev_inst *sdi, if (!(zipfile = zip_open(filename, ZIP_CREATE, &ret))) return SR_ERR; - /* "version" */ - version[0] = '1'; - if (!(versrc = zip_source_buffer(zipfile, version, 1, 0))) - return SR_ERR; - if (zip_add(zipfile, "version", versrc) == -1) { - sr_info("error saving version into zipfile: %s", - zip_strerror(zipfile)); - return SR_ERR; - } + /* init "metadata" */ + strcpy(metafile, "DSLogic-meta-XXXXXX"); + if ((tmpfile = g_mkstemp(metafile)) == -1) + return SR_ERR; + close(tmpfile); + meta = g_fopen(metafile, "wb"); + fprintf(meta, "[version]\n"); + fprintf(meta, "DSLogic version = %s\n", PACKAGE_VERSION); - /* init "metadata" */ - strcpy(metafile, "sigrok-meta-XXXXXX"); - if ((tmpfile = g_mkstemp(metafile)) == -1) - return SR_ERR; - close(tmpfile); - meta = g_fopen(metafile, "wb"); - fprintf(meta, "[global]\n"); - fprintf(meta, "sigrok version = %s\n", PACKAGE_VERSION); + /* metadata */ + fprintf(meta, "[header]\n"); + if (sdi->driver) + fprintf(meta, "driver = %s\n", sdi->driver->name); - /* metadata */ - fprintf(meta, "[device 1]\n"); - if (sdi->driver) - fprintf(meta, "driver = %s\n", sdi->driver->name); + /* metadata */ + fprintf(meta, "capturefile = data\n"); + fprintf(meta, "unitsize = %d\n", unitsize); + fprintf(meta, "total samples = %d\n", units); + fprintf(meta, "total probes = %d\n", g_slist_length(sdi->probes)); + if (sr_dev_has_option(sdi, SR_CONF_SAMPLERATE)) { + if (sr_config_get(sdi->driver, SR_CONF_SAMPLERATE, + &gvar, sdi) == SR_OK) { + samplerate = g_variant_get_uint64(gvar); + s = sr_samplerate_string(samplerate); + fprintf(meta, "samplerate = %s\n", s); + g_free(s); + g_variant_unref(gvar); + } + } + probecnt = 1; + for (l = sdi->probes; l; l = l->next) { + probe = l->data; + if (probe->enabled) { + if (probe->name) + fprintf(meta, "probe%d = %s\n", probecnt, probe->name); + if (probe->trigger) + fprintf(meta, " trigger%d = %s\n", probecnt, probe->trigger); + probecnt++; + } + } - /* metadata */ - fprintf(meta, "capturefile = logic-1\n"); - fprintf(meta, "unitsize = %d\n", unitsize); - fprintf(meta, "total probes = %d\n", g_slist_length(sdi->probes)); - if (sr_dev_has_option(sdi, SR_CONF_SAMPLERATE)) { - if (sr_config_get(sdi->driver, SR_CONF_SAMPLERATE, - &gvar, sdi) == SR_OK) { - samplerate = g_variant_get_uint64(gvar); - s = sr_samplerate_string(samplerate); - fprintf(meta, "samplerate = %s\n", s); - g_free(s); - g_variant_unref(gvar); - } - } - probecnt = 1; - for (l = sdi->probes; l; l = l->next) { - probe = l->data; - if (probe->enabled) { - if (probe->name) - fprintf(meta, "probe%d = %s\n", probecnt, probe->name); - if (probe->trigger) - fprintf(meta, " trigger%d = %s\n", probecnt, probe->trigger); - probecnt++; - } - } - - if (!(logicsrc = zip_source_buffer(zipfile, buf, - units * unitsize, FALSE))) - return SR_ERR; - snprintf(rawname, 15, "logic-1"); - if (zip_add(zipfile, rawname, logicsrc) == -1) - return SR_ERR; - fclose(meta); + if (!(logicsrc = zip_source_buffer(zipfile, buf, + units * unitsize, FALSE))) + return SR_ERR; + snprintf(rawname, 15, "data"); + if (zip_add(zipfile, rawname, logicsrc) == -1) + return SR_ERR; + fclose(meta); - if (!(metasrc = zip_source_file(zipfile, metafile, 0, -1))) - return SR_ERR; - if (zip_add(zipfile, "metadata", metasrc) == -1) - return SR_ERR; + if (!(metasrc = zip_source_file(zipfile, metafile, 0, -1))) + return SR_ERR; + if (zip_add(zipfile, "header", metasrc) == -1) + return SR_ERR; - if ((ret = zip_close(zipfile)) == -1) { - sr_info("error saving zipfile: %s", zip_strerror(zipfile)); - return SR_ERR; - } + if ((ret = zip_close(zipfile)) == -1) { + sr_info("error saving zipfile: %s", zip_strerror(zipfile)); + return SR_ERR; + } - unlink(metafile); + unlink(metafile); - return SR_OK; + return SR_OK; } /** @} */ diff --git a/tests/Makefile.am b/tests/Makefile.am index 6c8a8605..25f9438e 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -35,6 +35,6 @@ check_main_SOURCES = \ check_main_CFLAGS = @check_CFLAGS@ -check_main_LDADD = $(top_builddir)/libsigrok.la @check_LIBS@ +check_main_LDADD = $(top_builddir)/libsigrok4DSLogic.la @check_LIBS@ endif diff --git a/trigger.c b/trigger.c new file mode 100644 index 00000000..d8a2aae5 --- /dev/null +++ b/trigger.c @@ -0,0 +1,291 @@ +/* + * This file is part of the DSLogic project. + */ + +#include +#include +#include +#include +#include +#include +#include "libsigrok.h" +#include "libsigrok-internal.h" + +/* Message logging helpers with subsystem-specific prefix string. */ +#define LOG_PREFIX "session: " +#define sr_log(l, s, args...) sr_log(l, LOG_PREFIX s, ## args) +#define sr_spew(s, args...) sr_spew(LOG_PREFIX s, ## args) +#define sr_dbg(s, args...) sr_dbg(LOG_PREFIX s, ## args) +#define sr_info(s, args...) sr_info(LOG_PREFIX s, ## args) +#define sr_warn(s, args...) sr_warn(LOG_PREFIX s, ## args) +#define sr_err(s, args...) sr_err(LOG_PREFIX s, ## args) + +/** + * @file + * + * init, set DSLogic trigger. + */ + +/** + * @defgroup Trigger handling + * + * init, set DSLogic trigger + * + * @{ + */ + +struct ds_trigger *trigger; + +/** + * recovery trigger to initial status. + * + * @return SR_OK upon success. + */ +SR_API int ds_trigger_init(void) +{ + int i, j; + + if (!(trigger = g_try_malloc0(sizeof(struct ds_trigger)))) { + sr_err("Trigger malloc failed."); + return SR_ERR_MALLOC; + } + + trigger->trigger_en = 0; + trigger->trigger_mode = SIMPLE_TRIGGER; + trigger->trigger_pos = 0; + trigger->trigger_stages = 0; + + for (i = 0; i <= TriggerStages; i++) { + for (j = 0; j < TriggerProbes; j++) { + trigger->trigger0[i][j] = 'X'; + trigger->trigger1[i][j] = 'X'; + } + trigger->trigger0_count[i] = 0; + trigger->trigger1_count[i] = 0; + trigger->trigger0_inv[i] = 0; + trigger->trigger1_inv[i] = 0; + trigger->trigger_logic[i] = 1; + } + + + return SR_OK; +} + +SR_API int ds_trigger_destroy(void) +{ + if (trigger) + g_free(trigger); + + return SR_OK; +} + +/** + * set trigger based on stage + * + * @return SR_OK upon success. + */ +SR_API int ds_trigger_stage_set_value(uint16_t stage, uint16_t probes, char *trigger0, char *trigger1) +{ + assert(stage < TriggerStages); + assert(probes <= TriggerProbes); + + int j; + + for (j = 0; j< probes; j++) { + trigger->trigger0[stage][probes - j - 1] = *(trigger0 + j * 2); + trigger->trigger1[stage][probes - j - 1] = *(trigger1 + j * 2); + } + + return SR_OK; +} +SR_API int ds_trigger_stage_set_logic(uint16_t stage, uint16_t probes, unsigned char trigger_logic) +{ + assert(stage < TriggerStages); + assert(probes <= TriggerProbes); + + trigger->trigger_logic[stage] = trigger_logic; + + return SR_OK; +} +SR_API int ds_trigger_stage_set_inv(uint16_t stage, uint16_t probes, unsigned char trigger0_inv, unsigned char trigger1_inv) +{ + assert(stage < TriggerStages); + assert(probes <= TriggerProbes); + + trigger->trigger0_inv[stage] = trigger0_inv; + trigger->trigger1_inv[stage] = trigger1_inv; + + return SR_OK; +} +SR_API int ds_trigger_stage_set_count(uint16_t stage, uint16_t probes, uint16_t trigger0_count, uint16_t trigger1_count) +{ + assert(stage < TriggerStages); + assert(probes <= TriggerProbes); + + trigger->trigger0_count[stage] = trigger0_count; + trigger->trigger1_count[stage] = trigger1_count; + + return SR_OK; +} + +/** + * set trigger based on probe + * + * @return SR_OK upon success. + */ +SR_API int ds_trigger_probe_set(uint16_t probe, unsigned char trigger0, unsigned char trigger1) +{ + assert(probe < TriggerProbes); + + trigger->trigger0[TriggerStages][probe] = trigger0; + trigger->trigger1[TriggerStages][probe] = trigger1; + + return SR_OK; +} + +/** + * set trigger stage + * + * @return SR_OK upon success. + */ +SR_API int ds_trigger_set_stage(uint16_t stages) +{ + assert(stages <= TriggerStages); + + trigger->trigger_stages = stages; + + return SR_OK; +} + +/** + * set trigger position + * + * @return SR_OK upon success. + */ +SR_API int ds_trigger_set_pos(uint16_t position) +{ + assert(position <= 100); + assert(position >= 0); + + trigger->trigger_pos = position; + + return SR_OK; +} + +/** + * set trigger en + * + * @return SR_OK upon success. + */ +SR_API int ds_trigger_set_en(uint16_t enable) +{ + + trigger->trigger_en = enable; + + return SR_OK; +} + +/** + * set trigger mode + * + * @return SR_OK upon success. + */ +SR_API int ds_trigger_set_mode(uint16_t mode) +{ + + trigger->trigger_mode = mode; + + return SR_OK; +} + +/* + * + */ +SR_PRIV uint64_t ds_trigger_get_mask0(uint16_t stage) +{ + assert(stage <= TriggerStages); + + uint64_t mask = 0; + int i; + + for (i = TriggerProbes - 1; i >= 0 ; i--) { + mask = (mask << 1); + mask += (trigger->trigger0[stage][i] == 'X' | trigger->trigger0[stage][i] == 'C'); + } + + return mask; +} +SR_PRIV uint64_t ds_trigger_get_mask1(uint16_t stage) +{ + assert(stage <= TriggerStages); + + uint64_t mask = 0; + int i; + + for (i = TriggerProbes - 1; i >= 0 ; i--) { + mask = (mask << 1); + mask += (trigger->trigger1[stage][i] == 'X' | trigger->trigger1[stage][i] == 'C'); + } + + return mask; +} +SR_PRIV uint64_t ds_trigger_get_value0(uint16_t stage) +{ + assert(stage <= TriggerStages); + + uint64_t value = 0; + int i; + + for (i = TriggerProbes - 1; i >= 0 ; i--) { + value = (value << 1); + value += (trigger->trigger0[stage][i] == '1' | trigger->trigger0[stage][i] == 'R'); + } + + return value; +} +SR_PRIV uint64_t ds_trigger_get_value1(uint16_t stage) +{ + assert(stage <= TriggerStages); + + uint64_t value = 0; + int i; + + for (i = TriggerProbes - 1; i >= 0 ; i--) { + value = (value << 1); + value += (trigger->trigger1[stage][i] == '1' | trigger->trigger1[stage][i] == 'R'); + } + + return value; +} +SR_PRIV uint64_t ds_trigger_get_edge0(uint16_t stage) +{ + assert(stage <= TriggerStages); + + uint64_t edge = 0; + int i; + + for (i = TriggerProbes - 1; i >= 0 ; i--) { + edge = (edge << 1); + edge += (trigger->trigger0[stage][i] == 'R' | trigger->trigger0[stage][i] == 'F' | + trigger->trigger0[stage][i] == 'C'); + } + + return edge; +} +SR_PRIV uint64_t ds_trigger_get_edge1(uint16_t stage) +{ + assert(stage <= TriggerStages); + + uint64_t edge = 0; + int i; + + for (i = TriggerProbes - 1; i >= 0 ; i--) { + edge = (edge << 1); + edge += (trigger->trigger1[stage][i] == 'R' | trigger->trigger1[stage][i] == 'F' | + trigger->trigger1[stage][i] == 'C'); + } + + return edge; +} + +/** @} */