[sigrok-firmware-fx2lafw] 03/06: New upstream version 0.1.4

Zoltan Gyarmati zgyarmati-guest at moszumanska.debian.org
Wed Mar 29 21:53:53 UTC 2017


This is an automated email from the git hooks/post-receive script.

zgyarmati-guest pushed a commit to branch master
in repository sigrok-firmware-fx2lafw.

commit 8341ab013c60449ca07d42e8b05e022dd84043b6
Author: Zoltan Gyarmati <mr.zoltan.gyarmati at gmail.com>
Date:   Wed Mar 1 01:25:52 2017 +0100

    New upstream version 0.1.4
---
 ChangeLog                                          | 416 ++++++++++++++++
 Makefile.am                                        |  54 +-
 Makefile.in                                        |  53 +-
 NEWS                                               |  17 +
 README                                             |  55 ++-
 configure                                          |  20 +-
 configure.ac                                       |   2 +-
 gpif-acquisition.c                                 |  50 +-
 hantek_6022be.c                                    | 469 ++++++++++++++++++
 hw/braintechnology-usb-lps/dscr.a51                |   3 +
 hw/cwav-usbeeax/dscr.a51                           |   3 +
 hw/cwav-usbeedx/dscr.a51                           |   3 +
 hw/cwav-usbeesx/dscr.a51                           |   3 +
 hw/{cwav-usbeedx => cwav-usbeezx}/dscr.a51         |   7 +-
 hw/cypress-fx2/dscr.a51                            |   3 +
 .../dscr.a51                                       |  12 +-
 .../dscr.a51                                       |  12 +-
 hw/saleae-logic/dscr.a51                           |   3 +
 hw/sigrok-fx2-16ch/dscr.a51                        |   3 +
 hw/sigrok-fx2-8ch/dscr.a51                         |   3 +
 include/command.h                                  |   2 +
 .../dscr.a51 => include/common.inc                 |  60 ++-
 include/dscr.inc                                   |  55 +--
 include/dscr_hantek_6022be.inc                     | 355 ++++++++++++++
 include/fx2lafw.h                                  |   2 +-
 sainsmart_dds120.c                                 | 543 +++++++++++++++++++++
 26 files changed, 2080 insertions(+), 128 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 218f610..e328554 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,419 @@
+commit 2970556e910ee24673d909816c4cc6cf784fae4c
+Author: Uwe Hermann <uwe at hermann-uwe.de>
+Date:   Tue Oct 4 13:21:24 2016 +0200
+
+    configure.ac: Bump package version to 0.1.4.
+
+commit 1940f9fc5f94c31b9ac1172bdcbfdf775e8dd346
+Author: Uwe Hermann <uwe at hermann-uwe.de>
+Date:   Tue Oct 4 13:20:52 2016 +0200
+
+    NEWS: Add list of user-visible changes so far.
+
+commit b2893cc9f1b6a2fa4a53f32a85f29195b3ac4878
+Author: Uwe Hermann <uwe at hermann-uwe.de>
+Date:   Tue Oct 4 13:22:29 2016 +0200
+
+    Increase FX2LAFW_VERSION_MINOR to 2.
+    
+    There have been changes since the last release, but they have been
+    compatible ones that don't require any host-side (libsigrok) changes,
+    thus only increase FX2LAFW_VERSION_MINOR (but not FX2LAFW_VERSION_MAJOR).
+
+commit e59a70a92242d4c0d53ea0b065f61b43c2c43b03
+Author: Uwe Hermann <uwe at hermann-uwe.de>
+Date:   Sun Oct 30 12:12:31 2016 +0100
+
+    Use per-device USB serial number strings.
+    
+    These are not actual "serial numbers" in the strict sense, i.e. two
+    devices of the same type (e.g. two USBee ZX devices) would have the
+    same string.
+    
+    Using two different actual serial numbers in such a case is not possible
+    since both devices would get the exact same firmware file (uploaded to
+    RAM via USB) and thus the exact same hardcoded "serial number". All devices
+    where fx2lafw is currently used don't have an EEPROM where the firmware
+    (and thus a different serial number) could be stored persistently; it's
+    always re-uploaded to the device's RAM upon connecting the device to USB.
+    
+    However, the USB serial number field is still useful in that we can
+    store a nice device(-type) indicator string there. The benefit is that
+    an lsusb of an fx2lafw (after firmware upload) would yield something
+    specific like "USBee ZX" or "Hantek 6022BE" in addition to the very
+    generic "fx2lafw".
+
+commit 3878baac72b0db18a254b84f65a65a0f033e9be4
+Author: Uwe Hermann <uwe at hermann-uwe.de>
+Date:   Mon Oct 31 14:44:35 2016 +0100
+
+    Add "fx2lafw-" prefix to the 6022BE/DDS120 firmware files.
+
+commit b2fc269ae6d7586d8f8024354a490ecd55f77834
+Author: Uwe Hermann <uwe at hermann-uwe.de>
+Date:   Wed Oct 12 22:24:02 2016 +0200
+
+    Use the same VID/PID for Hantek 6022BE and SainSmart DDS120.
+    
+    (one of the official sigrok VID/PIDs, 1D50:608E)
+    
+    Encode the fact that they're different versions/revisions/variants
+    of the same device (more or less rebadges with only little changes)
+    in the USB product version field.
+
+commit 46e097cc30a9680362c4a0122e10dea79455ab01
+Author: Uwe Hermann <uwe at hermann-uwe.de>
+Date:   Wed Oct 12 22:16:13 2016 +0200
+
+    Makefile.am: Remove unneeded duplication.
+
+commit 01c919588b6ba25f926d97f899cfd2a5a082f453
+Author: Uwe Hermann <uwe at hermann-uwe.de>
+Date:   Sat Oct 8 16:41:10 2016 +0200
+
+    Add and use macros to simplify USB descriptor files.
+    
+    The macros in include/common.inc were provided by
+    Stefan Brüns <stefan.bruens at rwth-aachen.de>, thanks!
+
+commit 520598e2a91a2f68780744346ffb3998be50a9d4
+Author: Uwe Hermann <uwe at hermann-uwe.de>
+Date:   Sat Sep 3 15:33:51 2016 +0200
+
+    Makefile.am: Add dscr_hantek_6022be.inc to the tarball.
+
+commit 5fea0267f505f1ccc06c4516e246d875a4ae73bf
+Author: Uwe Hermann <uwe at hermann-uwe.de>
+Date:   Wed Aug 10 09:52:55 2016 +0200
+
+    HACKING: Prefer git pull requests over mailing list patches.
+    
+    Also, drop the reference to gitorious.org (no longer available).
+
+commit eccff92104ffb44e4344c87fc6743eec20b06694
+Author: Uwe Hermann <uwe at hermann-uwe.de>
+Date:   Wed Aug 10 09:44:45 2016 +0200
+
+    README: Drop obsolete and unneeded section.
+    
+    The firmware requirements should be documented in libsigrok itself, the
+    firmware in this repo doesn't know anything about its users per se.
+
+commit 6aa5d1f472dd35faed9085f6b2b24fa218314043
+Author: Uwe Hermann <uwe at hermann-uwe.de>
+Date:   Wed Aug 10 09:42:19 2016 +0200
+
+    gpif-acquisition.c: Minor cosmetics, drop obsolete comment.
+
+commit b93872aadb4d9aa576b9ce8d56dd2d0d8f953230
+Author: Paul Fertser <fercerpav at gmail.com>
+Date:   Fri Jul 15 23:19:10 2016 +0300
+
+    Refactor and bugfix the delay adding code for analog capture
+    
+    There're two essential modifications in this change:
+    
+    1. Fix timing for capture frequencies less than 200 kHz;
+    2. Sample ADC output after CLK is set low, as per the TLC5510
+    datasheet.
+    
+    The second point is also important as the capture state sets CLK low,
+    so with the previous code there might have been a very short glitch on
+    this line during capture. Not confirmed by measurements, but it's
+    cleaner this way.
+    
+    Signed-off-by: Paul Fertser <fercerpav at gmail.com>
+
+commit 1f99664cd09baa9bc584c884d7fd509d332d984e
+Author: Paul Fertser <fercerpav at gmail.com>
+Date:   Fri Jul 15 23:19:09 2016 +0300
+
+    Remove bogus part of OUTPUT used for analog sampling
+    
+    Since TRICTL = 0, FX2 always either pushes or pulls the CTLx pins.
+    
+    Signed-off-by: Paul Fertser <fercerpav at gmail.com>
+
+commit 10bb1488807fc35a95d2158b118b03bfc026ee4b
+Author: Paul Fertser <fercerpav at gmail.com>
+Date:   Fri Jul 15 23:19:08 2016 +0300
+
+    Fix typo in gpif_make_data_dp_state function name
+    
+    Signed-off-by: Paul Fertser <fercerpav at gmail.com>
+
+commit 41e02f6589989a2ef0c1d3c2be4317a662f393be
+Author: Paul Fertser <fercerpav at gmail.com>
+Date:   Fri Jul 15 23:19:07 2016 +0300
+
+    Change arguments of gpif_make_delay_state() to remove layering violation
+    
+    This function is called only for adding delay states to the waveform
+    so OPCODE is always the same.
+    
+    While at it, fix confusing comments.
+    
+    Signed-off-by: Paul Fertser <fercerpav at gmail.com>
+
+commit b68bc8eaca5454a158a0472afe45aac8c7f20717
+Author: Uwe Hermann <uwe at hermann-uwe.de>
+Date:   Wed Aug 10 09:38:14 2016 +0200
+
+    dscr*.inc: Document polling intervals better.
+
+commit 1cba57320f126176f6e45f3d0930e0fe9967a370
+Author: Uwe Hermann <uwe at hermann-uwe.de>
+Date:   Wed Aug 10 08:23:09 2016 +0200
+
+    dscr_hantek_6022be.inc: Fix incorrect comments, add additional ones.
+
+commit 3c9925a24936ed1cb225aa61e7d0971b7c9f680f
+Author: Uwe Hermann <uwe at hermann-uwe.de>
+Date:   Wed Aug 10 08:19:20 2016 +0200
+
+    dscr_hantek_6022be.inc: Change vendor string to "sigrok".
+
+commit e0c25b8e13abdba0de4dc57006dc195f4200b38a
+Author: Uwe Hermann <uwe at hermann-uwe.de>
+Date:   Wed Aug 10 08:07:32 2016 +0200
+
+    dscr_hantek_6022be.inc: Cosmetic and consistency changes.
+    
+    This makes the file a lot more readable and also easier to compare
+    to the other dscr.inc files.
+    
+    Also, fix some typos (or copy-paste errors) in some comments.
+
+commit ae087fd964d575a79f39ae086a035a3e4edf88bc
+Author: Uwe Hermann <uwe at hermann-uwe.de>
+Date:   Wed Aug 10 07:40:43 2016 +0200
+
+    dscr.inc: Shorten representation of two strings.
+
+commit bb9fd89f1c2668855475a441e1a5f2092a10fa3a
+Author: Uwe Hermann <uwe at hermann-uwe.de>
+Date:   Thu Aug 4 17:24:00 2016 +0200
+
+    hantek-6022be/sainsmart-dds120: Hook up correct per-device VID/PID.
+
+commit 4349f28686db6fe1f0c8863246f653277afb8b01
+Author: Uwe Hermann <uwe at hermann-uwe.de>
+Date:   Thu Aug 4 17:18:14 2016 +0200
+
+    Deduplicate hantek-6022be/sainsmart-dds120's dscr.inc.
+
+commit e16027445b508591ec8830fd74d0542e52a1c1d3
+Author: Uwe Hermann <uwe at hermann-uwe.de>
+Date:   Thu Aug 4 17:16:48 2016 +0200
+
+    hantek-6022be/sainsmart-dds120: Use the same USB product string.
+
+commit 823ff1e02ab3d100c1ef0d0fe3bbcc6b05aba446
+Author: Uwe Hermann <uwe at hermann-uwe.de>
+Date:   Wed Jul 13 00:10:21 2016 +0200
+
+    README: Mention the Sainsmart DDS120 firmware.
+
+commit 66255d9cae682fe637319bd59678ddf03595e466
+Author: Uwe Hermann <uwe at hermann-uwe.de>
+Date:   Tue Jul 12 23:48:13 2016 +0200
+
+    Add CWAV USBee ZX firmware support.
+    
+    This fixes bug #764.
+
+commit 386296a75ef7c2b3fbbd668de838a16bc13ee461
+Author: Benjamin Larsson <benjamin at southpole.se>
+Date:   Thu May 19 00:36:25 2016 +0200
+
+    Silence warnings
+    
+    The following warnings are fixed by this:
+    
+     hantek_6022be.c:424: warning 158: overflow in implicit constant conversion
+     sainsmart_dds120.c:359: warning 158: overflow in implicit constant conversion
+     sainsmart_dds120.c:363: warning 158: overflow in implicit constant conversion
+     sainsmart_dds120.c:366: warning 158: overflow in implicit constant conversion
+     sainsmart_dds120.c:370: warning 158: overflow in implicit constant conversion
+     sainsmart_dds120.c:494: warning 158: overflow in implicit constant conversion
+
+commit 24373950c5858ea7761ac8aa77b51c717558316b
+Author: Uwe Hermann <uwe at hermann-uwe.de>
+Date:   Thu May 19 00:17:16 2016 +0200
+
+    Add a few more code comments.
+
+commit 552a42e560835b12a1f8a51eec750792a196c6e5
+Author: Benjamin Larsson <benjamin at southpole.se>
+Date:   Wed May 18 22:50:06 2016 +0200
+
+    fx2lafw: clock CTL1 the same as CTL2
+    
+    The LHT00SU1 has it's clock pins swapped compared to other hardware.
+    By duplicating the CTL2 pin both the socket and the adc will
+    have the same clock frequency.
+
+commit 5b8b366d255733ca647f96c19a4c77a00583508e
+Author: Markus Siegert <markus at drsiegert.de>
+Date:   Sun Apr 10 22:03:13 2016 +0200
+
+    Use 1D50:608E for open source Sainsmart DDS120 firmware
+
+commit a425fae9a25f54af8d514aff8824382f7b317ba4
+Author: Benjamin Larsson <benjamin at southpole.se>
+Date:   Sat Apr 23 18:22:19 2016 +0200
+
+    Support changing calibration pulse frequency
+
+commit 33c275bbd292b21149cb76094e280b6ea2f62cae
+Author: Benjamin Larsson <benjamin at southpole.se>
+Date:   Sat Apr 23 18:19:12 2016 +0200
+
+    Add more sample rates
+
+commit 75ad0fa51ea581cbea1f1c0fb173856822c6e971
+Author: Benjamin Larsson <benjamin at southpole.se>
+Date:   Sun Apr 3 17:39:07 2016 +0200
+
+    Add support for setting Sainsmart AC/DC coupling
+
+commit ce1d0a869e4761d30b698b6bb1ea015a0470f09e
+Author: Benjamin Larsson <benjamin at southpole.se>
+Date:   Fri Mar 18 22:12:56 2016 +0100
+
+    Initial Sainsmart DDS120 firmware
+
+commit 8f87f8779a3977bd3cb8ec5003f43acdc44dbba6
+Author: Benjamin Larsson <benjamin at southpole.se>
+Date:   Thu Apr 28 00:58:26 2016 +0200
+
+    Add CMD_START_FLAGS_CLK_CTL2 command flag
+    
+    This command will generate a suitable clock on pin CTL2 for
+    devices with an analog input.
+
+commit c7d1f48c01801ba990fe6f9e881c688e5c90d24e
+Author: Benjamin Larsson <benjamin at southpole.se>
+Date:   Thu Apr 28 00:49:10 2016 +0200
+
+    Enable more control over the GPIF state machine
+
+commit a77606e9b63d2333f1253b8e0cb8071aed6d8609
+Author: Uwe Hermann <uwe at hermann-uwe.de>
+Date:   Thu Mar 10 23:31:18 2016 +0100
+
+    hw/hantek-6022be/dscr.a51: License header cosmetics.
+
+commit 38e32023c4b2dc92d51d969e1958bd1ee941804f
+Author: Uwe Hermann <uwe at hermann-uwe.de>
+Date:   Thu Mar 10 23:24:16 2016 +0100
+
+    hantek_6022be.c: Simplify handle_vendorcommand().
+
+commit 374453b93a012f483dc9da29ac4713b561e1aacb
+Author: Uwe Hermann <uwe at hermann-uwe.de>
+Date:   Thu Mar 10 23:19:48 2016 +0100
+
+    hantek_6022be.c: Minor cosmetics.
+
+commit 0ab4ea5da80c9f3d3e523dcaa259f5e97dcda0b8
+Author: Uwe Hermann <uwe at hermann-uwe.de>
+Date:   Thu Mar 10 23:15:05 2016 +0100
+
+    hantek_6022be.c: Make a few variables and functions static.
+
+commit fb4075d535596e9721f89d1cd98ab5ebe4540a2f
+Author: Uwe Hermann <uwe at hermann-uwe.de>
+Date:   Thu Mar 10 23:12:24 2016 +0100
+
+    hantek_6022be.c: Move main() for consistency.
+
+commit cc789c14085a371976fa7ef1bc281eb7bac34086
+Author: Uwe Hermann <uwe at hermann-uwe.de>
+Date:   Thu Mar 10 23:10:06 2016 +0100
+
+    hantek_6022be.c: Adapt to fx2lafw coding style, minor simplifications.
+
+commit 484b3aa0cf59216dee289c187fc6a232fdcf8ded
+Author: Uwe Hermann <uwe at hermann-uwe.de>
+Date:   Thu Mar 10 22:43:41 2016 +0100
+
+    hantek_6022be.c: Drop unneeded debug code, random cruft.
+
+commit 52ec81d349f5917587e98519b04ff109cf5cf32e
+Author: Uwe Hermann <uwe at hermann-uwe.de>
+Date:   Thu Mar 10 22:38:52 2016 +0100
+
+    README: Update to mention the Hantek 6022BE firmware.
+
+commit 1974eccb66634e2d7535a892d1c703665f757408
+Author: Uwe Hermann <uwe at hermann-uwe.de>
+Date:   Thu Mar 10 22:19:14 2016 +0100
+
+    hantek_6022be.c: Fix build error.
+    
+    Drop handle_get_descriptor(), since it's already provided by
+    fx2lib/lib/setupdat.c, in order to fix the following linker error:
+    
+      Multiple definition of _handle_get_descriptor
+      Makefile:925: recipe for target 'hw/hantek-6022be/hantek-6022be.ihx' failed
+
+commit 6139dad4829bf7d412f4ad847cf1d02aecb20bbe
+Author: Uwe Hermann <uwe at hermann-uwe.de>
+Date:   Thu Mar 10 21:46:29 2016 +0100
+
+    Makefile.am: Hook up building of hantek-6022be.fw.
+    
+    The FX2 firmware for the Hantek 6022BE USB-based oscilloscope uses most
+    of the existing fx2lafw build infrastructure and our existing fx2lib setup,
+    but requires slightly different sdcc linker settings due to different code
+    and XRAM sizes and locations, etc.
+
+commit 189db3d41e4c3d8a4aec5ec605c03df75577d531
+Author: Uwe Hermann <uwe at hermann-uwe.de>
+Date:   Thu Mar 10 21:02:12 2016 +0100
+
+    Add FX2 firmware for the Hantek 6022BE USB scope.
+    
+    This firmware was originally created by Jochen Hoenicke in 05/2015
+    for the Hantek6022API github project by Robert Cope. Full credit for
+    the implementation of the firmware goes to Jochen Hoenicke, thanks!
+    
+    Github project:
+    
+      https://github.com/rpcope1/Hantek6022API
+    
+    We're incorporating the firmware into the sigrok-firmware-fx2lafw
+    repo/tarball for convenience of sigrok users. E.g. so that they can
+    easily get it with the other fx2lafw firmware files from distro
+    packages, the build scripts in sigrok-util automatically build/install
+    it, the sigrok Windows installers automatically ship it, the sigrok
+    Android APKs automatically ship it, etc. etc.
+    
+    The files we're integrating into fx2lafw from Hantek6022API are taken from
+    the PyHT6022/HantekFirmware/custom directory of that repo, using the state
+    as of 03/2016 (the files were last modified in 05/2015, though).
+    
+    The git hash of the last relevant commit there was:
+    
+      0498e2ab239aabb1084c19e1e24faf56764b217e
+    
+    Files integrated into fx2lafw:
+    
+     - hw/hantek-6022be/dscr.a51: Copied unmodified.
+    
+     - hantek_6022be.c: This file is created by appending the
+       contents of the original device.c and fw.c together without
+       other modifications.
+    
+    The license of both files is LGPL 2.1 (or later).
+
+commit 05f4369545dad41969b112893a8bb4146e98fc0a
+Author: Uwe Hermann <uwe at hermann-uwe.de>
+Date:   Thu Mar 10 21:01:29 2016 +0100
+
+    README: Update prebuilt firmware download location.
+
 commit a6fb49c00691a917a1734afbf3071ca2ad0c1c46
 Author: Uwe Hermann <uwe at hermann-uwe.de>
 Date:   Thu Nov 26 23:41:51 2015 +0100
diff --git a/Makefile.am b/Makefile.am
index 4d859b1..712d177 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -24,6 +24,8 @@ SUFFIXES = .a51 .c .fw .ihx .rel
 
 # Flags for firmware hex file generation
 SDCC_LINK_FLAGS = --code-size 0x1c00 --xram-size 0x0200 --xram-loc 0x1c00 -Wl"-b DSCR_AREA=0x1e00" -Wl"-b INT2JT=0x1f00"
+SDCC_LINK_FLAGS_HANTEK_6022BE = --code-size 0x3c00 --xram-size 0x0100 --xram-loc 0x3c00 -Wl"-b DSCR_AREA=0x3d00" -Wl"-b INT2JT=0x3f00"
+SDCC_LINK_FLAGS_SAINSMART_DDS120 = $(SDCC_LINK_FLAGS_HANTEK_6022BE)
 
 # Include paths
 as_includes = -I$(srcdir)/include
@@ -42,10 +44,13 @@ dirstamps = \
 	hw/cwav-usbeeax/$(dirstamp) \
 	hw/cwav-usbeedx/$(dirstamp) \
 	hw/cwav-usbeesx/$(dirstamp) \
+	hw/cwav-usbeezx/$(dirstamp) \
 	hw/cypress-fx2/$(dirstamp) \
 	hw/saleae-logic/$(dirstamp) \
 	hw/sigrok-fx2-8ch/$(dirstamp) \
-	hw/sigrok-fx2-16ch/$(dirstamp)
+	hw/sigrok-fx2-16ch/$(dirstamp) \
+	hw/hantek-6022be/$(dirstamp) \
+	hw/sainsmart-dds120/$(dirstamp)
 
 # Final firmware files
 firmware_binaries = \
@@ -53,14 +58,18 @@ firmware_binaries = \
 	hw/cwav-usbeeax/fx2lafw-cwav-usbeeax.fw \
 	hw/cwav-usbeedx/fx2lafw-cwav-usbeedx.fw \
 	hw/cwav-usbeesx/fx2lafw-cwav-usbeesx.fw \
+	hw/cwav-usbeezx/fx2lafw-cwav-usbeezx.fw \
 	hw/cypress-fx2/fx2lafw-cypress-fx2.fw \
 	hw/saleae-logic/fx2lafw-saleae-logic.fw \
 	hw/sigrok-fx2-8ch/fx2lafw-sigrok-fx2-8ch.fw \
-	hw/sigrok-fx2-16ch/fx2lafw-sigrok-fx2-16ch.fw
+	hw/sigrok-fx2-16ch/fx2lafw-sigrok-fx2-16ch.fw \
+	hw/hantek-6022be/fx2lafw-hantek-6022be.fw \
+	hw/sainsmart-dds120/fx2lafw-sainsmart-dds120.fw
 
 fx2lafw_headers = \
 	include/command.h \
 	include/dscr.inc \
+	include/common.inc \
 	include/fx2lafw.h \
 	include/gpif-acquisition.h
 
@@ -72,6 +81,26 @@ fx2lafw_objects = \
 	fx2lafw.rel \
 	gpif-acquisition.rel
 
+hantek_6022be_headers = \
+	include/dscr_hantek_6022be.inc \
+	include/common.inc
+
+hantek_6022be_sources = \
+	hantek_6022be.c
+
+hantek_6022be_objects = \
+	hantek_6022be.rel
+
+sainsmart_dds120_headers = \
+	include/dscr_hantek_6022be.inc \
+	include/common.inc
+
+sainsmart_dds120_sources = \
+	sainsmart_dds120.c
+
+sainsmart_dds120_objects = \
+	sainsmart_dds120.rel
+
 fx2lib_headers = \
 	fx2lib/include/autovector.h \
 	fx2lib/include/delay.h \
@@ -205,15 +234,18 @@ hw_sources = \
 	hw/cwav-usbeeax/dscr.a51 \
 	hw/cwav-usbeedx/dscr.a51 \
 	hw/cwav-usbeesx/dscr.a51 \
+	hw/cwav-usbeezx/dscr.a51 \
 	hw/cypress-fx2/dscr.a51 \
 	hw/saleae-logic/dscr.a51 \
 	hw/sigrok-fx2-8ch/dscr.a51 \
-	hw/sigrok-fx2-16ch/dscr.a51
+	hw/sigrok-fx2-16ch/dscr.a51 \
+	hw/hantek-6022be/dscr.a51 \
+	hw/sainsmart-dds120/dscr.a51
 
 firmwaredir = $(datadir)/sigrok-firmware
 firmware_DATA = $(firmware_binaries)
 
-dist_noinst_DATA = $(fx2lafw_headers) $(fx2lafw_sources) $(fx2lib_headers) $(fx2lib_sources) $(fx2lib_ints_sources) $(hw_sources)
+dist_noinst_DATA = $(fx2lafw_headers) $(fx2lafw_sources) $(hantek_6022be_headers) $(hantek_6022be_sources) $(sainsmart_dds120_sources) $(sainsmart_dds120_headers) $(fx2lib_headers) $(fx2lib_sources) $(fx2lib_ints_sources) $(hw_sources)
 dist_noinst_SCRIPTS = autogen.sh
 
 MOSTLYCLEANFILES = *.asm fx2lib/lib/*.asm fx2lib/lib/*.lib fx2lib/lib/interrupts/*.asm fx2lib/lib/interrupts/*.lib
@@ -265,6 +297,7 @@ dist-bin: $(firmware_binaries)
 
 # List dependencies
 $(fx2lafw_objects): $(fx2lafw_headers)
+$(hantek_6022be_objects): $(hantek_6022be_headers)
 $(fx2lib_objects): fx2lib/lib/$(dirstamp) $(fx2lib_headers)
 $(fx2lib_ints_objects): fx2lib/lib/interrupts/$(dirstamp) $(fx2lib_headers)
 
@@ -272,10 +305,14 @@ hw/braintechnology-usb-lps/dscr.rel: hw/braintechnology-usb-lps/$(dirstamp) incl
 hw/cwav-usbeeax/dscr.rel: hw/cwav-usbeeax/$(dirstamp) include/dscr.inc
 hw/cwav-usbeedx/dscr.rel: hw/cwav-usbeedx/$(dirstamp) include/dscr.inc
 hw/cwav-usbeesx/dscr.rel: hw/cwav-usbeesx/$(dirstamp) include/dscr.inc
+hw/cwav-usbeezx/dscr.rel: hw/cwav-usbeezx/$(dirstamp) include/dscr.inc
 hw/cypress-fx2/dscr.rel: hw/cypress-fx2/$(dirstamp) include/dscr.inc
 hw/saleae-logic/dscr.rel: hw/saleae-logic/$(dirstamp) include/dscr.inc
 hw/sigrok-fx2-8ch/dscr.rel: hw/sigrok-fx2-8ch/$(dirstamp) include/dscr.inc
 hw/sigrok-fx2-16ch/dscr.rel: hw/sigrok-fx2-16ch/$(dirstamp) include/dscr.inc
+hw/hantek-6022be/dscr.rel: hw/hantek-6022be/$(dirstamp) include/dscr_hantek_6022be.inc
+hw/sainsmart-dds120/dscr.rel: hw/sainsmart-dds120/$(dirstamp) include/dscr_hantek_6022be.inc
+
 
 # Create build subdirectories
 $(dirstamps):
@@ -302,6 +339,9 @@ hw/cwav-usbeedx/fx2lafw-cwav-usbeedx.ihx: hw/cwav-usbeedx/dscr.rel $(fx2lafw_obj
 hw/cwav-usbeesx/fx2lafw-cwav-usbeesx.ihx: hw/cwav-usbeesx/dscr.rel $(fx2lafw_objects) $(fx2lib_libs)
 	$(AM_V_GEN)$(SDCC) -mmcs51 $(SDCC_LINK_FLAGS) -o $@ hw/cwav-usbeesx/dscr.rel $(fx2lafw_objects) $(fx2lib_libs)
 
+hw/cwav-usbeezx/fx2lafw-cwav-usbeezx.ihx: hw/cwav-usbeezx/dscr.rel $(fx2lafw_objects) $(fx2lib_libs)
+	$(AM_V_GEN)$(SDCC) -mmcs51 $(SDCC_LINK_FLAGS) -o $@ hw/cwav-usbeezx/dscr.rel $(fx2lafw_objects) $(fx2lib_libs)
+
 hw/cypress-fx2/fx2lafw-cypress-fx2.ihx: hw/cypress-fx2/dscr.rel $(fx2lafw_objects) $(fx2lib_libs)
 	$(AM_V_GEN)$(SDCC) -mmcs51 $(SDCC_LINK_FLAGS) -o $@ hw/cypress-fx2/dscr.rel $(fx2lafw_objects) $(fx2lib_libs)
 
@@ -314,6 +354,12 @@ hw/sigrok-fx2-8ch/fx2lafw-sigrok-fx2-8ch.ihx: hw/sigrok-fx2-8ch/dscr.rel $(fx2la
 hw/sigrok-fx2-16ch/fx2lafw-sigrok-fx2-16ch.ihx: hw/sigrok-fx2-16ch/dscr.rel $(fx2lafw_objects) $(fx2lib_libs)
 	$(AM_V_GEN)$(SDCC) -mmcs51 $(SDCC_LINK_FLAGS) -o $@ hw/sigrok-fx2-16ch/dscr.rel $(fx2lafw_objects) $(fx2lib_libs)
 
+hw/hantek-6022be/fx2lafw-hantek-6022be.ihx: hw/hantek-6022be/dscr.rel $(hantek_6022be_objects) $(fx2lib_libs)
+	$(AM_V_GEN)$(SDCC) -mmcs51 $(SDCC_LINK_FLAGS_HANTEK_6022BE) -o $@ hw/hantek-6022be/dscr.rel $(hantek_6022be_objects) $(fx2lib_libs)
+
+hw/sainsmart-dds120/fx2lafw-sainsmart-dds120.ihx: hw/sainsmart-dds120/dscr.rel $(sainsmart_dds120_objects) $(fx2lib_libs)
+	$(AM_V_GEN)$(SDCC) -mmcs51 $(SDCC_LINK_FLAGS_SAINSMART_DDS120) -o $@ hw/sainsmart-dds120/dscr.rel $(sainsmart_dds120_objects) $(fx2lib_libs)
+
 .a51.rel:
 	$(SF_V_SDAS)$(SDAS8051) -glos $(as_includes) $@ $<
 
diff --git a/Makefile.in b/Makefile.in
index 2cc5478..95213e8 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -257,6 +257,8 @@ SUFFIXES = .a51 .c .fw .ihx .rel
 
 # Flags for firmware hex file generation
 SDCC_LINK_FLAGS = --code-size 0x1c00 --xram-size 0x0200 --xram-loc 0x1c00 -Wl"-b DSCR_AREA=0x1e00" -Wl"-b INT2JT=0x1f00"
+SDCC_LINK_FLAGS_HANTEK_6022BE = --code-size 0x3c00 --xram-size 0x0100 --xram-loc 0x3c00 -Wl"-b DSCR_AREA=0x3d00" -Wl"-b INT2JT=0x3f00"
+SDCC_LINK_FLAGS_SAINSMART_DDS120 = $(SDCC_LINK_FLAGS_HANTEK_6022BE)
 
 # Include paths
 as_includes = -I$(srcdir)/include
@@ -274,10 +276,13 @@ dirstamps = \
 	hw/cwav-usbeeax/$(dirstamp) \
 	hw/cwav-usbeedx/$(dirstamp) \
 	hw/cwav-usbeesx/$(dirstamp) \
+	hw/cwav-usbeezx/$(dirstamp) \
 	hw/cypress-fx2/$(dirstamp) \
 	hw/saleae-logic/$(dirstamp) \
 	hw/sigrok-fx2-8ch/$(dirstamp) \
-	hw/sigrok-fx2-16ch/$(dirstamp)
+	hw/sigrok-fx2-16ch/$(dirstamp) \
+	hw/hantek-6022be/$(dirstamp) \
+	hw/sainsmart-dds120/$(dirstamp)
 
 
 # Final firmware files
@@ -286,14 +291,18 @@ firmware_binaries = \
 	hw/cwav-usbeeax/fx2lafw-cwav-usbeeax.fw \
 	hw/cwav-usbeedx/fx2lafw-cwav-usbeedx.fw \
 	hw/cwav-usbeesx/fx2lafw-cwav-usbeesx.fw \
+	hw/cwav-usbeezx/fx2lafw-cwav-usbeezx.fw \
 	hw/cypress-fx2/fx2lafw-cypress-fx2.fw \
 	hw/saleae-logic/fx2lafw-saleae-logic.fw \
 	hw/sigrok-fx2-8ch/fx2lafw-sigrok-fx2-8ch.fw \
-	hw/sigrok-fx2-16ch/fx2lafw-sigrok-fx2-16ch.fw
+	hw/sigrok-fx2-16ch/fx2lafw-sigrok-fx2-16ch.fw \
+	hw/hantek-6022be/fx2lafw-hantek-6022be.fw \
+	hw/sainsmart-dds120/fx2lafw-sainsmart-dds120.fw
 
 fx2lafw_headers = \
 	include/command.h \
 	include/dscr.inc \
+	include/common.inc \
 	include/fx2lafw.h \
 	include/gpif-acquisition.h
 
@@ -305,6 +314,26 @@ fx2lafw_objects = \
 	fx2lafw.rel \
 	gpif-acquisition.rel
 
+hantek_6022be_headers = \
+	include/dscr_hantek_6022be.inc \
+	include/common.inc
+
+hantek_6022be_sources = \
+	hantek_6022be.c
+
+hantek_6022be_objects = \
+	hantek_6022be.rel
+
+sainsmart_dds120_headers = \
+	include/dscr_hantek_6022be.inc \
+	include/common.inc
+
+sainsmart_dds120_sources = \
+	sainsmart_dds120.c
+
+sainsmart_dds120_objects = \
+	sainsmart_dds120.rel
+
 fx2lib_headers = \
 	fx2lib/include/autovector.h \
 	fx2lib/include/delay.h \
@@ -438,14 +467,17 @@ hw_sources = \
 	hw/cwav-usbeeax/dscr.a51 \
 	hw/cwav-usbeedx/dscr.a51 \
 	hw/cwav-usbeesx/dscr.a51 \
+	hw/cwav-usbeezx/dscr.a51 \
 	hw/cypress-fx2/dscr.a51 \
 	hw/saleae-logic/dscr.a51 \
 	hw/sigrok-fx2-8ch/dscr.a51 \
-	hw/sigrok-fx2-16ch/dscr.a51
+	hw/sigrok-fx2-16ch/dscr.a51 \
+	hw/hantek-6022be/dscr.a51 \
+	hw/sainsmart-dds120/dscr.a51
 
 firmwaredir = $(datadir)/sigrok-firmware
 firmware_DATA = $(firmware_binaries)
-dist_noinst_DATA = $(fx2lafw_headers) $(fx2lafw_sources) $(fx2lib_headers) $(fx2lib_sources) $(fx2lib_ints_sources) $(hw_sources)
+dist_noinst_DATA = $(fx2lafw_headers) $(fx2lafw_sources) $(hantek_6022be_headers) $(hantek_6022be_sources) $(sainsmart_dds120_sources) $(sainsmart_dds120_headers) $(fx2lib_headers) $(fx2lib_sources) $(fx2lib_ints_sources) $(hw_sources)
 dist_noinst_SCRIPTS = autogen.sh
 MOSTLYCLEANFILES = *.asm fx2lib/lib/*.asm fx2lib/lib/*.lib fx2lib/lib/interrupts/*.asm fx2lib/lib/interrupts/*.lib
 CLEANFILES = $(firmware_binaries)
@@ -860,6 +892,7 @@ dist-bin: $(firmware_binaries)
 
 # List dependencies
 $(fx2lafw_objects): $(fx2lafw_headers)
+$(hantek_6022be_objects): $(hantek_6022be_headers)
 $(fx2lib_objects): fx2lib/lib/$(dirstamp) $(fx2lib_headers)
 $(fx2lib_ints_objects): fx2lib/lib/interrupts/$(dirstamp) $(fx2lib_headers)
 
@@ -867,10 +900,13 @@ hw/braintechnology-usb-lps/dscr.rel: hw/braintechnology-usb-lps/$(dirstamp) incl
 hw/cwav-usbeeax/dscr.rel: hw/cwav-usbeeax/$(dirstamp) include/dscr.inc
 hw/cwav-usbeedx/dscr.rel: hw/cwav-usbeedx/$(dirstamp) include/dscr.inc
 hw/cwav-usbeesx/dscr.rel: hw/cwav-usbeesx/$(dirstamp) include/dscr.inc
+hw/cwav-usbeezx/dscr.rel: hw/cwav-usbeezx/$(dirstamp) include/dscr.inc
 hw/cypress-fx2/dscr.rel: hw/cypress-fx2/$(dirstamp) include/dscr.inc
 hw/saleae-logic/dscr.rel: hw/saleae-logic/$(dirstamp) include/dscr.inc
 hw/sigrok-fx2-8ch/dscr.rel: hw/sigrok-fx2-8ch/$(dirstamp) include/dscr.inc
 hw/sigrok-fx2-16ch/dscr.rel: hw/sigrok-fx2-16ch/$(dirstamp) include/dscr.inc
+hw/hantek-6022be/dscr.rel: hw/hantek-6022be/$(dirstamp) include/dscr_hantek_6022be.inc
+hw/sainsmart-dds120/dscr.rel: hw/sainsmart-dds120/$(dirstamp) include/dscr_hantek_6022be.inc
 
 # Create build subdirectories
 $(dirstamps):
@@ -897,6 +933,9 @@ hw/cwav-usbeedx/fx2lafw-cwav-usbeedx.ihx: hw/cwav-usbeedx/dscr.rel $(fx2lafw_obj
 hw/cwav-usbeesx/fx2lafw-cwav-usbeesx.ihx: hw/cwav-usbeesx/dscr.rel $(fx2lafw_objects) $(fx2lib_libs)
 	$(AM_V_GEN)$(SDCC) -mmcs51 $(SDCC_LINK_FLAGS) -o $@ hw/cwav-usbeesx/dscr.rel $(fx2lafw_objects) $(fx2lib_libs)
 
+hw/cwav-usbeezx/fx2lafw-cwav-usbeezx.ihx: hw/cwav-usbeezx/dscr.rel $(fx2lafw_objects) $(fx2lib_libs)
+	$(AM_V_GEN)$(SDCC) -mmcs51 $(SDCC_LINK_FLAGS) -o $@ hw/cwav-usbeezx/dscr.rel $(fx2lafw_objects) $(fx2lib_libs)
+
 hw/cypress-fx2/fx2lafw-cypress-fx2.ihx: hw/cypress-fx2/dscr.rel $(fx2lafw_objects) $(fx2lib_libs)
 	$(AM_V_GEN)$(SDCC) -mmcs51 $(SDCC_LINK_FLAGS) -o $@ hw/cypress-fx2/dscr.rel $(fx2lafw_objects) $(fx2lib_libs)
 
@@ -909,6 +948,12 @@ hw/sigrok-fx2-8ch/fx2lafw-sigrok-fx2-8ch.ihx: hw/sigrok-fx2-8ch/dscr.rel $(fx2la
 hw/sigrok-fx2-16ch/fx2lafw-sigrok-fx2-16ch.ihx: hw/sigrok-fx2-16ch/dscr.rel $(fx2lafw_objects) $(fx2lib_libs)
 	$(AM_V_GEN)$(SDCC) -mmcs51 $(SDCC_LINK_FLAGS) -o $@ hw/sigrok-fx2-16ch/dscr.rel $(fx2lafw_objects) $(fx2lib_libs)
 
+hw/hantek-6022be/fx2lafw-hantek-6022be.ihx: hw/hantek-6022be/dscr.rel $(hantek_6022be_objects) $(fx2lib_libs)
+	$(AM_V_GEN)$(SDCC) -mmcs51 $(SDCC_LINK_FLAGS_HANTEK_6022BE) -o $@ hw/hantek-6022be/dscr.rel $(hantek_6022be_objects) $(fx2lib_libs)
+
+hw/sainsmart-dds120/fx2lafw-sainsmart-dds120.ihx: hw/sainsmart-dds120/dscr.rel $(sainsmart_dds120_objects) $(fx2lib_libs)
+	$(AM_V_GEN)$(SDCC) -mmcs51 $(SDCC_LINK_FLAGS_SAINSMART_DDS120) -o $@ hw/sainsmart-dds120/dscr.rel $(sainsmart_dds120_objects) $(fx2lib_libs)
+
 .a51.rel:
 	$(SF_V_SDAS)$(SDAS8051) -glos $(as_includes) $@ $<
 
diff --git a/NEWS b/NEWS
index 652924b..905fac5 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,20 @@
+0.1.4 (2016-10-31)
+------------------
+
+ * Add FX2 firmware for the Hantek 6022BE and SainSmart DDS120 USB scopes.
+   These firmware files use the official sigrok USB VID/PID of 1D50:608E.
+   The USB VID/PID pairs are allocated for fx2lafw via the OpenMoko project:
+   http://wiki.openmoko.org/wiki/USB_Product_IDs
+ * Add analog channel support for the USBee AX (and potentially other devices).
+   Only one analog channel is supported. Switching channels (in case there
+   are multiple analog channels) is not yet implemented.
+ * Add support for the USBee ZX (bug #764).
+ * Use per-device USB product string descriptors.
+ * Bump the firmware version (major.minor) to 1.2. This version is
+   backwards-compatible and doesn't require host-side (libsigrok) changes.
+ * README: Update prebuilt firmware download location, other cleanups.
+ * HACKING: Prefer git pull requests over mailing list patches.
+
 0.1.3 (2015-11-26)
 ------------------
 
diff --git a/README b/README
index 404fc23..e0d25a1 100644
--- a/README
+++ b/README
@@ -7,7 +7,8 @@ Free/Libre/Open-Source signal analysis software suite that supports various
 device types (such as logic analyzers, oscilloscopes, multimeters, and more).
 
 sigrok-firmware-fx2lafw is a Free/Libre/Open-source firmware for logic
-analyzers based on the Cypress EZ-USB FX2(LP) chip.
+analyzers based on the Cypress EZ-USB FX2(LP) chip, as well as the
+Hantek 6022BE and Sainsmart DDS120 USB oscilloscopes.
 
 
 Status
@@ -35,9 +36,6 @@ Notes:
 
    This project has been tested to work with sdcc 2.9 and 3.x.
 
- - You need libsigrok >= 0.1.1 in order to make use of fx2lafw. Earlier
-   versions didn't have support for FX2 devices using this firmware.
-
 
 Building and installing
 -----------------------
@@ -69,9 +67,9 @@ Pre-built firmware files
 ------------------------
 
 There are also pre-built firmware files that can be used without having
-to build them from source. You can download those from SourceForge:
+to build them from source. You can download those from:
 
-  http://sourceforge.net/projects/sigrok/files/binary/sigrok-firmware-fx2lafw/
+  http://sigrok.org/download/binary/sigrok-firmware-fx2lafw/
 
 
 fx2lib
@@ -89,14 +87,55 @@ The following files/directories were removed, as they're not needed
 for our purposes: CHANGELOG, COPYING*, docs/, examples/, fw/, and utils/.
 
 
+Hantek 6022BE firmware
+----------------------
+
+The Hantek 6022BE firmware was originally created by Jochen Hoenicke in
+05/2015 for the Hantek6022API github project by Robert Cope. Full credit
+for the implementation of the firmware goes to Jochen Hoenicke, thanks!
+
+Github project:
+
+  https://github.com/rpcope1/Hantek6022API
+
+We've incorporated the Hantek 6022BE firmware into the sigrok-firmware-fx2lafw
+repo/tarball for convenience of sigrok users. E.g. so that they can
+easily get it with the other fx2lafw firmware files from distro
+packages, the build scripts in sigrok-util automatically build/install
+it, the sigrok Windows installers automatically ship it, the sigrok
+Android APKs automatically ship it, etc. etc.
+
+The files we've integrated into fx2lafw from Hantek6022API were taken from
+the PyHT6022/HantekFirmware/custom directory of that repo, using the state
+as of 03/2016 (the files were last modified in 05/2015, though).
+
+The git hash of the last relevant commit there was:
+
+  0498e2ab239aabb1084c19e1e24faf56764b217e
+
+Files integrated into fx2lafw:
+
+ - hw/hantek-6022be/dscr.a51: Copied unmodified.
+
+ - hantek_6022be.c: This file was originally created by appending the
+   contents of the original device.c and fw.c together.
+
+
+Sainsmart DDS120 firmware
+-------------------------
+
+The Sainsmart DDS120 firmware is heavily based upon the original Hantek 6022BE
+firmware, so the items mentioned above apply here as well.
+
+
 Copyright and license
 ---------------------
 
 sigrok-firmware-fx2lafw is licensed under the terms of the GNU General Public
 License (GPL), version 2 or later.
 
-It uses additional helper code (fx2lib), licensed under the GNU LGPL
-(version 2.1 or later).
+It uses additional helper code (fx2lib, Hantek 6022BE, and Sainsmart DDS120
+firmware), licensed under the GNU LGPL (version 2.1 or later).
 
 While some individual source code files are licensed under the LGPLv2.1+, and
 some files are licensed under the GPLv2+, this doesn't change the fact that
diff --git a/configure b/configure
index 5a8782c..f7185fe 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for sigrok-firmware-fx2lafw 0.1.3.
+# Generated by GNU Autoconf 2.69 for sigrok-firmware-fx2lafw 0.1.4.
 #
 # Report bugs to <sigrok-devel at lists.sourceforge.net>.
 #
@@ -639,8 +639,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='sigrok-firmware-fx2lafw'
 PACKAGE_TARNAME='sigrok-firmware-fx2lafw'
-PACKAGE_VERSION='0.1.3'
-PACKAGE_STRING='sigrok-firmware-fx2lafw 0.1.3'
+PACKAGE_VERSION='0.1.4'
+PACKAGE_STRING='sigrok-firmware-fx2lafw 0.1.4'
 PACKAGE_BUGREPORT='sigrok-devel at lists.sourceforge.net'
 PACKAGE_URL='http://www.sigrok.org'
 
@@ -1280,7 +1280,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures sigrok-firmware-fx2lafw 0.1.3 to adapt to many kinds of systems.
+\`configure' configures sigrok-firmware-fx2lafw 0.1.4 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1348,7 +1348,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of sigrok-firmware-fx2lafw 0.1.3:";;
+     short | recursive ) echo "Configuration of sigrok-firmware-fx2lafw 0.1.4:";;
    esac
   cat <<\_ACEOF
 
@@ -1423,7 +1423,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-sigrok-firmware-fx2lafw configure 0.1.3
+sigrok-firmware-fx2lafw configure 0.1.4
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -1440,7 +1440,7 @@ cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by sigrok-firmware-fx2lafw $as_me 0.1.3, which was
+It was created by sigrok-firmware-fx2lafw $as_me 0.1.4, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -2305,7 +2305,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='sigrok-firmware-fx2lafw'
- VERSION='0.1.3'
+ VERSION='0.1.4'
 
 
 # Some tools Automake needs.
@@ -3266,7 +3266,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by sigrok-firmware-fx2lafw $as_me 0.1.3, which was
+This file was extended by sigrok-firmware-fx2lafw $as_me 0.1.4, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -3320,7 +3320,7 @@ _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-sigrok-firmware-fx2lafw config.status 0.1.3
+sigrok-firmware-fx2lafw config.status 0.1.4
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
diff --git a/configure.ac b/configure.ac
index 6a8f8be..68f5965 100644
--- a/configure.ac
+++ b/configure.ac
@@ -21,7 +21,7 @@
 # We require at least autoconf 2.63 (AC_INIT format changed there).
 AC_PREREQ([2.63])
 
-AC_INIT([sigrok-firmware-fx2lafw], [0.1.3],
+AC_INIT([sigrok-firmware-fx2lafw], [0.1.4],
 	[sigrok-devel at lists.sourceforge.net],
 	[sigrok-firmware-fx2lafw], [http://www.sigrok.org])
 AC_CONFIG_AUX_DIR([autostuff])
diff --git a/gpif-acquisition.c b/gpif-acquisition.c
index 8734abe..18cdd79 100644
--- a/gpif-acquisition.c
+++ b/gpif-acquisition.c
@@ -46,10 +46,7 @@ static void gpif_setup_registers(void)
 	/* TODO. Value probably irrelevant, as we don't use RDY* signals? */
 	GPIFREADYCFG = 0;
 
-	/*
-	 * Set TRICTL = 0, thus CTL0-CTL5 are CMOS outputs.
-	 * TODO: Probably irrelevant, as we don't use CTL0-CTL5?
-	 */
+	/* Set TRICTL = 0, thus CTL0-CTL5 are CMOS outputs. */
 	GPIFCTLCFG = 0;
 
 	/* When GPIF is idle, tri-state the data bus. */
@@ -132,7 +129,7 @@ void gpif_init_la(void)
 	gpif_acquiring = FALSE;
 }
 
-static void gpif_make_delay_state(volatile BYTE *pSTATE, uint8_t delay)
+static void gpif_make_delay_state(volatile BYTE *pSTATE, uint8_t delay, uint8_t output)
 {
 	/*
 	 * DELAY
@@ -143,15 +140,14 @@ static void gpif_make_delay_state(volatile BYTE *pSTATE, uint8_t delay)
 	/*
 	 * OPCODE
 	 * SGL=0, GIN=0, INCAD=0, NEXT=0, DATA=0, DP=0
-	 * Collect data in this state.
 	 */
-	pSTATE[8] = 0x00;
+	pSTATE[8] = 0;
 
 	/*
 	 * OUTPUT
-	 * OE[0:3]=0, CTL[0:3]=0
+	 * CTL[0:5]=output
 	 */
-	pSTATE[16] = 0x00;
+	pSTATE[16] = output;
 
 	/*
 	 * LOGIC FUNCTION
@@ -160,7 +156,7 @@ static void gpif_make_delay_state(volatile BYTE *pSTATE, uint8_t delay)
 	pSTATE[24] = 0x00;
 }
 
-static void gpid_make_data_dp_state(volatile BYTE *pSTATE)
+static void gpif_make_data_dp_state(volatile BYTE *pSTATE)
 {
 	/*
 	 * BRANCH
@@ -176,7 +172,7 @@ static void gpid_make_data_dp_state(volatile BYTE *pSTATE)
 
 	/*
 	 * OUTPUT
-	 * OE[0:3]=0, CTL[0:3]=0
+	 * CTL[0:5]=0
 	 */
 	pSTATE[16] = 0x00;
 
@@ -197,11 +193,10 @@ bool gpif_acquisition_start(const struct cmd_start_acquisition *cmd)
 	while (!(GPIFTRIG & 0x80));
 
 	/* Configure the EP2 FIFO. */
-	if (cmd->flags & CMD_START_FLAGS_SAMPLE_16BIT) {
+	if (cmd->flags & CMD_START_FLAGS_SAMPLE_16BIT)
 		EP2FIFOCFG = bmAUTOIN | bmWORDWIDE;
-	} else {
+	else
 		EP2FIFOCFG = bmAUTOIN;
-	}
 	SYNCDELAY();
 
 	/* Set IFCONFIG to the correct clock source. */
@@ -218,14 +213,31 @@ bool gpif_acquisition_start(const struct cmd_start_acquisition *cmd)
 	    cmd->sample_delay_h >= 6)
 		return false;
 
-	for (i = 0; i < cmd->sample_delay_h; i++)
-		gpif_make_delay_state(pSTATE++, 0);
+	if (cmd->flags & CMD_START_FLAGS_CLK_CTL2) {
+		uint8_t delay_1, delay_2 = cmd->sample_delay_l;
+
+		/* We need a pulse where the CTL1/2 pins alternate states. */
+		if (cmd->sample_delay_h) {
+			for (i = 0; i < cmd->sample_delay_h; i++)
+				gpif_make_delay_state(pSTATE++, 0, 0x06);
+		} else {
+			delay_1 = delay_2 / 2;
+			delay_2 -= delay_1;
+			gpif_make_delay_state(pSTATE++, delay_1, 0x06);
+		}
+
+		/* sample_delay_l is always != 0 for the supported rates. */
+		gpif_make_delay_state(pSTATE++, delay_2, 0x00);
+	} else {
+		for (i = 0; i < cmd->sample_delay_h; i++)
+			gpif_make_delay_state(pSTATE++, 0, 0x00);
 
-	if (cmd->sample_delay_l != 0)
-		gpif_make_delay_state(pSTATE++, cmd->sample_delay_l);
+		if (cmd->sample_delay_l != 0)
+			gpif_make_delay_state(pSTATE++, cmd->sample_delay_l, 0x00);
+	}
 
 	/* Populate S1 - the decision point. */
-	gpid_make_data_dp_state(pSTATE++);
+	gpif_make_data_dp_state(pSTATE++);
 
 	/* Execute the whole GPIF waveform once. */
 	gpif_set_tc16(1);
diff --git a/hantek_6022be.c b/hantek_6022be.c
new file mode 100644
index 0000000..e089e96
--- /dev/null
+++ b/hantek_6022be.c
@@ -0,0 +1,469 @@
+/*
+ * This file is part of the sigrok-firmware-fx2lafw project.
+ *
+ * Copyright (C) 2009 Ubixum, Inc.
+ * Copyright (C) 2015 Jochen Hoenicke
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <fx2macros.h>
+#include <fx2ints.h>
+#include <autovector.h>
+#include <delay.h>
+#include <setupdat.h>
+
+/* Change to support as many interfaces as you need. */
+static BYTE altiface = 0;
+
+static volatile WORD ledcounter = 0;
+
+static volatile __bit dosud = FALSE;
+static volatile __bit dosuspend = FALSE;
+
+extern __code BYTE highspd_dscr;
+extern __code BYTE fullspd_dscr;
+
+void resume_isr(void) __interrupt RESUME_ISR
+{
+	CLEAR_RESUME();
+}
+
+void sudav_isr(void) __interrupt SUDAV_ISR
+{
+	dosud = TRUE;
+	CLEAR_SUDAV();
+}
+
+void usbreset_isr(void) __interrupt USBRESET_ISR
+{
+	handle_hispeed(FALSE);
+	CLEAR_USBRESET();
+}
+
+void hispeed_isr(void) __interrupt HISPEED_ISR
+{
+	handle_hispeed(TRUE);
+	CLEAR_HISPEED();
+}
+
+void suspend_isr(void) __interrupt SUSPEND_ISR
+{
+	dosuspend = TRUE;
+	CLEAR_SUSPEND();
+}
+
+void timer2_isr(void) __interrupt TF2_ISR
+{
+	PA7 = !PA7;
+	if (ledcounter) {
+		if (--ledcounter == 0) {
+			/* Clear LED. */
+			PC0 = 1;
+			PC1 = 1;
+		}
+	}
+	TF2 = 0;
+}
+
+/*
+ * This sets three bits for each channel, one channel at a time.
+ * For channel 0 we want to set bits 5, 6 & 7
+ * For channel 1 we want to set bits 2, 3 & 4
+ *
+ * We convert the input values that are strange due to original
+ * firmware code into the value of the three bits as follows:
+ *
+ * val -> bits
+ * 1  -> 010b
+ * 2  -> 001b
+ * 5  -> 000b
+ * 10 -> 011b
+ *
+ * The third bit is always zero since there are only four outputs connected
+ * in the serial selector chip.
+ *
+ * The multiplication of the converted value by 0x24 sets the relevant bits in
+ * both channels and then we mask it out to only affect the channel currently
+ * requested.
+ */
+static BOOL set_voltage(BYTE channel, BYTE val)
+{
+	BYTE bits, mask;
+
+	switch (val) {
+	case 1:
+		bits = 0x24 * 2;
+		break;
+	case 2:
+		bits = 0x24 * 1;
+		break;
+	case 5:
+		bits = 0x24 * 0;
+		break;
+	case 10:
+		bits = 0x24 * 3;
+		break;
+	default:
+		return FALSE;
+	}
+
+	mask = (channel) ? 0xe0 : 0x1c;
+	IOC = (IOC & ~mask) | (bits & mask);
+
+	return TRUE;
+}
+
+static BOOL set_numchannels(BYTE numchannels)
+{
+	if (numchannels == 1 || numchannels == 2) {
+		BYTE fifocfg = 7 + numchannels;
+		EP2FIFOCFG = fifocfg;
+		EP6FIFOCFG = fifocfg;
+		return TRUE;
+	}
+
+	return FALSE;
+}
+
+static void clear_fifo(void)
+{
+	GPIFABORT = 0xff;
+	SYNCDELAY3;
+	FIFORESET = 0x80;
+	SYNCDELAY3;
+	FIFORESET = 0x82;
+	SYNCDELAY3;
+	FIFORESET = 0x86;
+	SYNCDELAY3;
+	FIFORESET = 0;
+}
+
+static void stop_sampling(void)
+{
+	GPIFABORT = 0xff;
+	SYNCDELAY3;
+	INPKTEND = (altiface == 0) ? 6 : 2;
+}
+
+static void start_sampling(void)
+{
+	int i;
+
+	clear_fifo();
+
+	for (i = 0; i < 1000; i++);
+
+	while (!(GPIFTRIG & 0x80))
+		;
+
+	SYNCDELAY3;
+	GPIFTCB1 = 0x28;
+	SYNCDELAY3;
+	GPIFTCB0 = 0;
+	GPIFTRIG = (altiface == 0) ? 6 : 4;
+
+	/* Set green LED, don't clear LED. */
+	ledcounter = 0;
+	PC0 = 1;
+	PC1 = 0;
+}
+
+static void select_interface(BYTE alt)
+{
+	const BYTE *pPacketSize = \
+		((USBCS & bmHSM) ? &highspd_dscr : &fullspd_dscr)
+		+ (9 + (16 * alt) + 9 + 4);
+
+	altiface = alt;
+
+	if (alt == 0) {
+		/* Bulk on EP6. */
+		EP2CFG = 0x00;
+		EP6CFG = 0xe0;
+		EP6GPIFFLGSEL = 1;
+		EP6AUTOINLENL = pPacketSize[0];
+		EP6AUTOINLENH = pPacketSize[1];
+	} else {
+		/* Iso on EP2. */
+		EP2CFG = 0xd8;
+		EP6CFG = 0x00;
+		EP2GPIFFLGSEL = 1;
+		EP2AUTOINLENL = pPacketSize[0];
+		EP2AUTOINLENH = pPacketSize[1] & 0x7;
+		EP2ISOINPKTS = (pPacketSize[1] >> 3) + 1;
+	}
+}
+
+static const struct samplerate_info {
+	BYTE rate;
+	BYTE wait0;
+	BYTE wait1;
+	BYTE opc0;
+	BYTE opc1;
+	BYTE out0;
+	BYTE ifcfg;
+} samplerates[] = {
+	{ 48, 0x80,   0, 3, 0, 0x00, 0xea },
+	{ 30, 0x80,   0, 3, 0, 0x00, 0xaa },
+	{ 24,    1,   0, 2, 1, 0x40, 0xca },
+	{ 16,    1,   1, 2, 0, 0x40, 0xca },
+	{ 12,    2,   1, 2, 0, 0x40, 0xca },
+	{  8,    3,   2, 2, 0, 0x40, 0xca },
+	{  4,    6,   5, 2, 0, 0x40, 0xca },
+	{  2,   12,  11, 2, 0, 0x40, 0xca },
+	{  1,   24,  23, 2, 0, 0x40, 0xca },
+	{ 50,   48,  47, 2, 0, 0x40, 0xca },
+	{ 20,  120, 119, 2, 0, 0x40, 0xca },
+	{ 10,  240, 239, 2, 0, 0x40, 0xca },
+};
+
+static BOOL set_samplerate(BYTE rate)
+{
+	BYTE i = 0;
+
+	while (samplerates[i].rate != rate) {
+		i++;
+		if (i == sizeof(samplerates) / sizeof(samplerates[0]))
+			return FALSE;
+	}
+
+	IFCONFIG = samplerates[i].ifcfg;
+
+	AUTOPTRSETUP = 7;
+	AUTOPTRH2 = 0xE4; /* 0xE400: GPIF waveform descriptor 0. */
+	AUTOPTRL2 = 0x00;
+
+	/*
+	 * The program for low-speed, e.g. 1 MHz, is:
+	 * wait 24, CTL2=0, FIFO
+	 * wait 23, CTL2=1
+	 * jump 0, CTL2=1
+	 *
+	 * The program for 24 MHz is:
+	 * wait 1, CTL2=0, FIFO
+	 * jump 0, CTL2=1
+	 *
+	 * The program for 30/48 MHz is:
+	 * jump 0, CTL2=Z, FIFO, LOOP
+	 */
+
+	/* LENGTH / BRANCH 0-7 */
+	EXTAUTODAT2 = samplerates[i].wait0;
+	EXTAUTODAT2 = samplerates[i].wait1;
+	EXTAUTODAT2 = 1;
+	EXTAUTODAT2 = 0;
+	EXTAUTODAT2 = 0;
+	EXTAUTODAT2 = 0;
+	EXTAUTODAT2 = 0;
+	EXTAUTODAT2 = 0;
+
+	/* OPCODE 0-7 */
+	EXTAUTODAT2 = samplerates[i].opc0;
+	EXTAUTODAT2 = samplerates[i].opc1;
+	EXTAUTODAT2 = 1; /* DATA=0 DP=1 */
+	EXTAUTODAT2 = 0;
+	EXTAUTODAT2 = 0;
+	EXTAUTODAT2 = 0;
+	EXTAUTODAT2 = 0;
+	EXTAUTODAT2 = 0;
+
+	/* OUTPUT 0-7 */
+	EXTAUTODAT2 = samplerates[i].out0;
+	EXTAUTODAT2 = 0x44; /* OE0=1, CTL0=1 */
+	EXTAUTODAT2 = 0x44; /* OE0=1, CTL0=1 */
+	EXTAUTODAT2 = 0;
+	EXTAUTODAT2 = 0;
+	EXTAUTODAT2 = 0;
+	EXTAUTODAT2 = 0;
+	EXTAUTODAT2 = 0;
+
+	/* LOGIC FUNCTION 0-7 */
+	EXTAUTODAT2 = 0;
+	EXTAUTODAT2 = 0;
+	EXTAUTODAT2 = 0;
+	EXTAUTODAT2 = 0;
+	EXTAUTODAT2 = 0;
+	EXTAUTODAT2 = 0;
+	EXTAUTODAT2 = 0;
+	EXTAUTODAT2 = 0;
+
+	for (i = 0; i < 96; i++)
+		EXTAUTODAT2 = 0;
+
+	return TRUE;
+}
+
+/* Set *alt_ifc to the current alt interface for ifc. */
+BOOL handle_get_interface(BYTE ifc, BYTE *alt_ifc)
+{
+	(void)ifc;
+
+	*alt_ifc = altiface;
+
+	return TRUE;
+}
+
+/*
+ * Return TRUE if you set the interface requested.
+ *
+ * Note: This function should reconfigure and reset the endpoints
+ * according to the interface descriptors you provided.
+ */
+BOOL handle_set_interface(BYTE ifc,BYTE alt_ifc)
+{
+	if (ifc == 0)
+		select_interface(alt_ifc);
+
+	return TRUE;
+}
+
+BYTE handle_get_configuration(void)
+{
+	/* We only support configuration 0. */
+	return 0;
+}
+
+BOOL handle_set_configuration(BYTE cfg)
+{
+	/* We only support configuration 0. */
+	(void)cfg;
+
+	return TRUE;
+}
+
+BOOL handle_vendorcommand(BYTE cmd)
+{
+	stop_sampling();
+
+	/* Set red LED. */
+	PC0 = 0;
+	PC1 = 1;
+	ledcounter = 1000;
+
+	/* Clear EP0BCH/L for each valid command. */
+	if (cmd >= 0xe0 && cmd <= 0xe4) {
+		EP0BCH = 0;
+		EP0BCL = 0;
+		while (EP0CS & bmEPBUSY);
+	}
+
+	switch (cmd) {
+	case 0xe0:
+	case 0xe1:
+		set_voltage(cmd - 0xe0, EP0BUF[0]);
+		return TRUE;
+	case 0xe2:
+		set_samplerate(EP0BUF[0]);
+		return TRUE;
+	case 0xe3:
+		if (EP0BUF[0] == 1)
+			start_sampling();
+		return TRUE;
+	case 0xe4:
+		set_numchannels(EP0BUF[0]);
+		return TRUE;
+	}
+
+	return FALSE; /* Not handled by handlers. */
+}
+
+static void init(void)
+{
+	EP4CFG = 0;
+	EP8CFG = 0;
+
+	/* In idle mode tristate all outputs. */
+	GPIFIDLECTL = 0x00; /* Don't enable CTL0-5 outputs. */
+	GPIFCTLCFG = 0x80; /* TRICTL=1. CTL0-2: CMOS outputs, tri-statable. */
+	GPIFWFSELECT = 0x00;
+	GPIFREADYSTAT = 0x00;
+
+	stop_sampling();
+
+	set_voltage(0, 1);
+	set_voltage(1, 1);
+	set_samplerate(1);
+	set_numchannels(2);
+	select_interface(0);
+}
+
+static void main(void)
+{
+	/* Save energy. */
+	SETCPUFREQ(CLK_12M);
+
+	init();
+
+	/* Set up interrupts. */
+	USE_USB_INTS();
+
+	ENABLE_SUDAV();
+	ENABLE_USBRESET();
+	ENABLE_HISPEED(); 
+	ENABLE_SUSPEND();
+	ENABLE_RESUME();
+
+	/* Global (8051) interrupt enable. */
+	EA = 1;
+
+	/* Init timer2. */
+	RCAP2L = -500 & 0xff;
+	RCAP2H = (-500 & 0xff00) >> 8;
+	T2CON = 0;
+	ET2 = 1;
+	TR2 = 1;
+
+	RENUMERATE();
+
+	PORTCCFG = 0;
+	PORTACFG = 0;
+	OEC = 0xff;
+	OEA = 0x80;
+
+	while (TRUE) {
+		if (dosud) {
+			dosud = FALSE;
+			handle_setupdata();
+		}
+
+		if (dosuspend) {
+			dosuspend = FALSE;
+			do {
+				/* Make sure ext wakeups are cleared. */
+				WAKEUPCS |= bmWU|bmWU2;
+				SUSPEND = 1;
+				PCON |= 1;
+				__asm
+				nop
+				nop
+				nop
+				nop
+				nop
+				nop
+				nop
+				__endasm;
+			} while (!remote_wakeup_allowed && REMOTE_WAKEUP());
+
+			/* Resume (TRM 6.4). */
+			if (REMOTE_WAKEUP()) {
+				delay(5);
+				USBCS |= bmSIGRESUME;
+				delay(15);
+				USBCS &= ~bmSIGRESUME;
+			}
+		}
+	}
+}
diff --git a/hw/braintechnology-usb-lps/dscr.a51 b/hw/braintechnology-usb-lps/dscr.a51
index c82804b..e38eafd 100644
--- a/hw/braintechnology-usb-lps/dscr.a51
+++ b/hw/braintechnology-usb-lps/dscr.a51
@@ -22,3 +22,6 @@ VID = 0xd016	; Manufacturer ID (0x16d0)
 PID = 0x9804	; Product ID (0x0498)
 
 .include "dscr.inc"
+string_descriptor_a 3,^"Braintechnology USB-LPS"
+_dev_strings_end:
+	.dw	0x0000
diff --git a/hw/cwav-usbeeax/dscr.a51 b/hw/cwav-usbeeax/dscr.a51
index 335493f..7959cba 100644
--- a/hw/cwav-usbeeax/dscr.a51
+++ b/hw/cwav-usbeeax/dscr.a51
@@ -23,3 +23,6 @@ VID = 0xa908	; Manufacturer ID (0x08a9)
 PID = 0x1400	; Product ID (0x0014)
 
 .include "dscr.inc"
+string_descriptor_a 3,^"CWAV USBee AX"
+_dev_strings_end:
+	.dw	0x0000
diff --git a/hw/cwav-usbeedx/dscr.a51 b/hw/cwav-usbeedx/dscr.a51
index 8586b1f..c6a04fe 100644
--- a/hw/cwav-usbeedx/dscr.a51
+++ b/hw/cwav-usbeedx/dscr.a51
@@ -22,3 +22,6 @@ VID = 0xa908	; Manufacturer ID (0x08a9)
 PID = 0x1500	; Product ID (0x0015)
 
 .include "dscr.inc"
+string_descriptor_a 3,^"CWAV USBee DX"
+_dev_strings_end:
+	.dw	0x0000
diff --git a/hw/cwav-usbeesx/dscr.a51 b/hw/cwav-usbeesx/dscr.a51
index 35f93f7..cff9eb9 100644
--- a/hw/cwav-usbeesx/dscr.a51
+++ b/hw/cwav-usbeesx/dscr.a51
@@ -23,3 +23,6 @@ VID = 0xa908	; Manufacturer ID (0x08a9)
 PID = 0x0900	; Product ID (0x0009)
 
 .include "dscr.inc"
+string_descriptor_a 3,^"CWAV USBee SX"
+_dev_strings_end:
+	.dw	0x0000
diff --git a/hw/cwav-usbeedx/dscr.a51 b/hw/cwav-usbeezx/dscr.a51
similarity index 84%
copy from hw/cwav-usbeedx/dscr.a51
copy to hw/cwav-usbeezx/dscr.a51
index 8586b1f..f45f9cd 100644
--- a/hw/cwav-usbeedx/dscr.a51
+++ b/hw/cwav-usbeezx/dscr.a51
@@ -1,7 +1,7 @@
 ;;
 ;; This file is part of the sigrok-firmware-fx2lafw project.
 ;;
-;; Copyright (C) 2012 Ivan Fedorov <oxyum at oxyum.ru>
+;; Copyright (C) 2016 Uwe Hermann <uwe at hermann-uwe.de>
 ;;
 ;; This program is free software; you can redistribute it and/or modify
 ;; it under the terms of the GNU General Public License as published by
@@ -19,6 +19,9 @@
 ;;
 
 VID = 0xa908	; Manufacturer ID (0x08a9)
-PID = 0x1500	; Product ID (0x0015)
+PID = 0x0500	; Product ID (0x0005)
 
 .include "dscr.inc"
+string_descriptor_a 3,^"CWAV USBee ZX"
+_dev_strings_end:
+	.dw	0x0000
diff --git a/hw/cypress-fx2/dscr.a51 b/hw/cypress-fx2/dscr.a51
index 310e077..8243cee 100644
--- a/hw/cypress-fx2/dscr.a51
+++ b/hw/cypress-fx2/dscr.a51
@@ -23,3 +23,6 @@ VID = 0xb404	; Manufacturer ID (0x04b4)
 PID = 0x1386	; Product ID (0x8613)
 
 .include "dscr.inc"
+string_descriptor_a 3,^"Cypress FX2"
+_dev_strings_end:
+	.dw	0x0000
diff --git a/hw/braintechnology-usb-lps/dscr.a51 b/hw/hantek-6022be/dscr.a51
similarity index 72%
copy from hw/braintechnology-usb-lps/dscr.a51
copy to hw/hantek-6022be/dscr.a51
index c82804b..942d327 100644
--- a/hw/braintechnology-usb-lps/dscr.a51
+++ b/hw/hantek-6022be/dscr.a51
@@ -1,7 +1,7 @@
 ;;
 ;; This file is part of the sigrok-firmware-fx2lafw project.
 ;;
-;; Copyright (C) 2012 Uwe Hermann <uwe at hermann-uwe.de>
+;; Copyright (C) 2016 Uwe Hermann <uwe at hermann-uwe.de>
 ;;
 ;; This program is free software; you can redistribute it and/or modify
 ;; it under the terms of the GNU General Public License as published by
@@ -18,7 +18,11 @@
 ;; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
 ;;
 
-VID = 0xd016	; Manufacturer ID (0x16d0)
-PID = 0x9804	; Product ID (0x0498)
+VID = 0x501d	; Manufacturer ID (0x1d50)
+PID = 0x8e60	; Product ID (0x608e)
+VER = 0x0100	; Product "version". 0x0001 == Hantek 6022BE.
 
-.include "dscr.inc"
+.include "dscr_hantek_6022be.inc"
+string_descriptor_a 3,^"Hantek 6022BE"
+_dev_strings_end:
+	.dw	0x0000
diff --git a/hw/braintechnology-usb-lps/dscr.a51 b/hw/sainsmart-dds120/dscr.a51
similarity index 72%
copy from hw/braintechnology-usb-lps/dscr.a51
copy to hw/sainsmart-dds120/dscr.a51
index c82804b..79f8e02 100644
--- a/hw/braintechnology-usb-lps/dscr.a51
+++ b/hw/sainsmart-dds120/dscr.a51
@@ -1,7 +1,7 @@
 ;;
 ;; This file is part of the sigrok-firmware-fx2lafw project.
 ;;
-;; Copyright (C) 2012 Uwe Hermann <uwe at hermann-uwe.de>
+;; Copyright (C) 2016 Uwe Hermann <uwe at hermann-uwe.de>
 ;;
 ;; This program is free software; you can redistribute it and/or modify
 ;; it under the terms of the GNU General Public License as published by
@@ -18,7 +18,11 @@
 ;; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
 ;;
 
-VID = 0xd016	; Manufacturer ID (0x16d0)
-PID = 0x9804	; Product ID (0x0498)
+VID = 0x501d	; Manufacturer ID (0x1d50)
+PID = 0x8e60	; Product ID (0x608e)
+VER = 0x0200	; Product "version". 0x0002 == SainSmart DDS120.
 
-.include "dscr.inc"
+.include "dscr_hantek_6022be.inc"
+string_descriptor_a 3,^"SainSmart DDS120"
+_dev_strings_end:
+	.dw	0x0000
diff --git a/hw/saleae-logic/dscr.a51 b/hw/saleae-logic/dscr.a51
index 81f3742..aba8cae 100644
--- a/hw/saleae-logic/dscr.a51
+++ b/hw/saleae-logic/dscr.a51
@@ -23,3 +23,6 @@ VID = 0x2509	; Manufacturer ID (0x0925)
 PID = 0x8138	; Product ID (0x3881)
 
 .include "dscr.inc"
+string_descriptor_a 3,^"Saleae Logic"
+_dev_strings_end:
+	.dw	0x0000
diff --git a/hw/sigrok-fx2-16ch/dscr.a51 b/hw/sigrok-fx2-16ch/dscr.a51
index d63d08c..5657bdd 100644
--- a/hw/sigrok-fx2-16ch/dscr.a51
+++ b/hw/sigrok-fx2-16ch/dscr.a51
@@ -22,3 +22,6 @@ VID = 0x501D	; Manufacturer ID (0x1D50)
 PID = 0x8D60	; Product ID (0x608D)
 
 .include "dscr.inc"
+string_descriptor_a 3,^"sigrok FX2 16ch"
+_dev_strings_end:
+	.dw	0x0000
diff --git a/hw/sigrok-fx2-8ch/dscr.a51 b/hw/sigrok-fx2-8ch/dscr.a51
index 4eecd9f..c9b23ea 100644
--- a/hw/sigrok-fx2-8ch/dscr.a51
+++ b/hw/sigrok-fx2-8ch/dscr.a51
@@ -22,3 +22,6 @@ VID = 0x501D    ; Manufacturer ID (0x1D50)
 PID = 0x8C60    ; Product ID (0x608C)
 
 .include "dscr.inc"
+string_descriptor_a 3,^"sigrok FX2 8ch"
+_dev_strings_end:
+	.dw	0x0000
diff --git a/include/command.h b/include/command.h
index 59a9f90..c965720 100644
--- a/include/command.h
+++ b/include/command.h
@@ -28,9 +28,11 @@
 #define CMD_START			0xb1
 #define CMD_GET_REVID_VERSION		0xb2
 
+#define CMD_START_FLAGS_CLK_CTL2_POS	4
 #define CMD_START_FLAGS_WIDE_POS	5
 #define CMD_START_FLAGS_CLK_SRC_POS	6
 
+#define CMD_START_FLAGS_CLK_CTL2	(1 << CMD_START_FLAGS_CLK_CTL2_POS)
 #define CMD_START_FLAGS_SAMPLE_8BIT	(0 << CMD_START_FLAGS_WIDE_POS)
 #define CMD_START_FLAGS_SAMPLE_16BIT	(1 << CMD_START_FLAGS_WIDE_POS)
 
diff --git a/hw/braintechnology-usb-lps/dscr.a51 b/include/common.inc
similarity index 71%
copy from hw/braintechnology-usb-lps/dscr.a51
copy to include/common.inc
index c82804b..55520d1 100644
--- a/hw/braintechnology-usb-lps/dscr.a51
+++ b/include/common.inc
@@ -1,24 +1,36 @@
-;;
-;; This file is part of the sigrok-firmware-fx2lafw project.
-;;
-;; Copyright (C) 2012 Uwe Hermann <uwe at hermann-uwe.de>
-;;
-;; This program is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2 of the License, or
-;; (at your option) any later version.
-;;
-;; This program is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-;; GNU General Public License for more details.
-;;
-;; You should have received a copy of the GNU General Public License
-;; along with this program; if not, write to the Free Software
-;; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
-;;
-
-VID = 0xd016	; Manufacturer ID (0x16d0)
-PID = 0x9804	; Product ID (0x0498)
-
-.include "dscr.inc"
+;;
+;; This file is part of the sigrok-firmware-fx2lafw project.
+;;
+;; Copyright (C) 2016 Stefan Brüns <stefan.bruens at rwth-aachen.de>
+;;
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2 of the License, or
+;; (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, write to the Free Software
+;; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+;;
+
+.macro string_descriptor_a n,str
+_string'n:
+	.nchr	len,"'str"
+	.db	len * 2 + 2
+	.db	3
+	.irpc	i,^"'str"
+		.db	''i, 0
+	.endm
+.endm
+
+.macro string_descriptor_lang n,l
+_string'n:
+	.db	4
+	.db	3
+	.dw	>l + (<l * 0x100)
+.endm
diff --git a/include/dscr.inc b/include/dscr.inc
index 5d0f059..9f53fa5 100644
--- a/include/dscr.inc
+++ b/include/dscr.inc
@@ -19,6 +19,8 @@
 ;; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
 ;;
 
+.include "common.inc"
+
 .module DEV_DSCR
 
 ; Descriptor types
@@ -58,7 +60,7 @@ _dev_dscr:
 	.dw	0x0100			; Product version (0.01)
 	.db	1			; Manufacturer string index
 	.db	2			; Product string index
-	.db	0			; Serial number string index (none)
+	.db	3			; Serial number string index (none)
 	.db	1			; Number of configurations
 dev_dscr_end:
 
@@ -111,7 +113,7 @@ highspd_dscr_end:
 	.db	ENDPOINT_TYPE_BULK	; Endpoint type (bulk)
 	.db	0x00			; Max. packet size, LSB (512 bytes)
 	.db	0x02			; Max. packet size, MSB (512 bytes)
-	.db	0x00			; Polling interval
+	.db	0x00			; Polling interval (ignored for bulk)
 
 highspd_dscr_realend:
 
@@ -151,7 +153,7 @@ fullspd_dscr_end:
 	.db	ENDPOINT_TYPE_BULK	; Endpoint type (bulk)
 	.db	0x40			; Max. packet size, LSB (64 bytes)
 	.db	0x00			; Max. packet size, MSB (64 bytes)
-	.db	0x00			; Polling interval
+	.db	0x00			; Polling interval (ignored for bulk)
 
 fullspd_dscr_realend:
 
@@ -164,48 +166,7 @@ fullspd_dscr_realend:
 _dev_strings:
 
 ; See http://www.usb.org/developers/docs/USB_LANGIDs.pdf for the full list.
-_string0:
-	.db	string0end - _string0
-	.db	DSCR_STRING_TYPE
-	.db	0x09, 0x04		; Language code 0x0409 (English, US)
-string0end:
-
-_string1:
-	.db	string1end - _string1
-	.db	DSCR_STRING_TYPE
-	.ascii	's'
-	.db	0
-	.ascii	'i'
-	.db	0
-	.ascii	'g'
-	.db	0
-	.ascii	'r'
-	.db	0
-	.ascii	'o'
-	.db	0
-	.ascii	'k'
-	.db	0
-string1end:
-
-_string2:
-	.db	string2end - _string2
-	.db	DSCR_STRING_TYPE
-	.ascii	'f'
-	.db	0
-	.ascii	'x'
-	.db	0
-	.ascii	'2'
-	.db	0
-	.ascii	'l'
-	.db	0
-	.ascii	'a'
-	.db	0
-	.ascii	'f'
-	.db	0
-	.ascii	'w'
-	.db	0
-string2end:
-
-_dev_strings_end:
-	.dw 0x0000
+string_descriptor_lang 0 0x0409 ; Language code 0x0409 (English, US)
 
+string_descriptor_a 1,^"sigrok"
+string_descriptor_a 2,^"fx2lafw"
diff --git a/include/dscr_hantek_6022be.inc b/include/dscr_hantek_6022be.inc
new file mode 100644
index 0000000..418c2c7
--- /dev/null
+++ b/include/dscr_hantek_6022be.inc
@@ -0,0 +1,355 @@
+;;
+;; This file is part of the sigrok-firmware-fx2lafw project.
+;;
+;; Copyright (C) 2009 Ubixum, Inc. 
+;;
+;; This library is free software; you can redistribute it and/or
+;; modify it under the terms of the GNU Lesser General Public
+;; License as published by the Free Software Foundation; either
+;; version 2.1 of the License, or (at your option) any later version.
+;;
+;; This library 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
+;; Lesser General Public License for more details.
+;;
+;; You should have received a copy of the GNU Lesser General Public
+;; License along with this library; if not, write to the Free Software
+;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+;;
+
+.include "common.inc"
+
+.module DEV_DSCR
+
+; Descriptor types
+DSCR_DEVICE_TYPE	= 1
+DSCR_CONFIG_TYPE	= 2
+DSCR_STRING_TYPE	= 3
+DSCR_INTERFACE_TYPE	= 4
+DSCR_ENDPOINT_TYPE	= 5
+DSCR_DEVQUAL_TYPE	= 6
+
+; Descriptor lengths
+DSCR_INTERFACE_LEN	= 9
+DSCR_ENDPOINT_LEN	= 7
+
+; Endpoint types
+ENDPOINT_TYPE_CONTROL	= 0
+ENDPOINT_TYPE_ISO	= 1
+ENDPOINT_TYPE_BULK	= 2
+ENDPOINT_TYPE_INT	= 3
+
+.globl _dev_dscr, _dev_qual_dscr, _highspd_dscr, _fullspd_dscr, _dev_strings, _dev_strings_end
+.area DSCR_AREA (CODE)
+
+; -----------------------------------------------------------------------------
+; Device descriptor
+; -----------------------------------------------------------------------------
+_dev_dscr:
+	.db	dev_dscr_end - _dev_dscr
+	.db	DSCR_DEVICE_TYPE
+	.dw	0x0002			; USB 2.0
+	.db	0xff			; Class (vendor specific)
+	.db	0xff			; Subclass (vendor specific)
+	.db	0xff			; Protocol (vendor specific)
+	.db	64			; Max. EP0 packet size
+	.dw	VID			; Manufacturer ID
+	.dw	PID			; Product ID
+	.dw	VER			; Product version/type
+	.db	1			; Manufacturer string index
+	.db	2			; Product string index
+	.db	3			; Serial number string index
+	.db	1			; Number of configurations
+dev_dscr_end:
+
+; -----------------------------------------------------------------------------
+; Device qualifier (for "other device speed")
+; -----------------------------------------------------------------------------
+_dev_qual_dscr:
+	.db	dev_qualdscr_end - _dev_qual_dscr
+	.db	DSCR_DEVQUAL_TYPE
+	.dw	0x0002			; USB 2.0
+	.db	0			; Class (0)
+	.db	0			; Subclass (0)
+	.db	0			; Protocol (0)
+	.db	64			; Max. EP0 packet size
+	.db	1			; Number of configurations
+	.db	0			; Extra reserved byte
+dev_qualdscr_end:
+
+; -----------------------------------------------------------------------------
+; High-Speed configuration descriptor
+; -----------------------------------------------------------------------------
+_highspd_dscr:
+	.db	highspd_dscr_end - _highspd_dscr
+	.db	DSCR_CONFIG_TYPE
+	; Total length of the configuration (1st line LSB, 2nd line MSB)
+	.db	(highspd_dscr_realend - _highspd_dscr) % 256
+	.db	(highspd_dscr_realend - _highspd_dscr) / 256
+	.db	1			; Number of interfaces
+	.db	1			; Configuration number
+	.db	0			; Configuration string (none)
+	.db	0x80			; Attributes (bus powered, no wakeup)
+	.db	0x37			; Max. power (110mA)
+highspd_dscr_end:
+
+	; Bulk interface 0, alt 0
+	.db	DSCR_INTERFACE_LEN
+	.db	DSCR_INTERFACE_TYPE
+	.db	0			; Interface index
+	.db	0			; Alternate setting index
+	.db	1			; Number of endpoints
+	.db	0xff			; Class (vendor specific)
+	.db	0			; Subclass (0)
+	.db	0			; Protocol (0)
+	.db	0			; String index (none)
+
+	; Endpoint 6 (IN)
+	.db	DSCR_ENDPOINT_LEN
+	.db	DSCR_ENDPOINT_TYPE
+	.db	0x86			; EP number (6), direction (IN)
+	.db	ENDPOINT_TYPE_BULK	; Endpoint type (bulk)
+	.db	0x00			; Max. packet size, LSB (512 bytes)
+	.db	0x02			; Max. packet size, MSB (512 bytes)
+	.db	0x00			; Polling interval (ignored for bulk)
+
+	; Isochronous interface 0, alt 1
+	.db	DSCR_INTERFACE_LEN
+	.db	DSCR_INTERFACE_TYPE
+	.db	0			; Interface index
+	.db	1			; Alternate setting index
+	.db	1			; Number of endpoints
+	.db	0xff			; Class (vendor specific)
+	.db	0			; Subclass (0)
+	.db	1			; Protocol (1)
+	.db	0			; String index (none)
+
+	; Endpoint 2 (IN)
+	.db	DSCR_ENDPOINT_LEN
+	.db	DSCR_ENDPOINT_TYPE
+	.db	0x82			; EP number (2), direction (IN)
+	.db	ENDPOINT_TYPE_ISO	; Endpoint type (iso)
+	.db	0x00			; Max. packet size, LSB (3*1024 bytes)
+	.db	0x14			; Max. packet size, MSB (3*1024 bytes)
+					; 12:11 = 0b10 (3 tr. per microframe)
+					; 10:00 = 1024
+	.db	0x01			; Polling interval (1 microframe)
+
+	; Isochronous interface 0, alt 2, 16MB/s
+	.db	DSCR_INTERFACE_LEN
+	.db	DSCR_INTERFACE_TYPE
+	.db	0			; Interface index
+	.db	2			; Alternate setting index
+	.db	1			; Number of endpoints
+	.db	0xff			; Class (vendor specific)
+	.db	0			; Subclass (0)
+	.db	1			; Protocol (1)
+	.db	0			; String index (none)
+
+	; Endpoint 2 (IN)
+	.db	DSCR_ENDPOINT_LEN
+	.db	DSCR_ENDPOINT_TYPE
+	.db	0x82			; EP number (2), direction (IN)
+	.db	ENDPOINT_TYPE_ISO	; Endpoint type (iso)
+	.db	0x00			; Max. packet size, LSB (2*1024 bytes)
+	.db	0x0c			; Max. packet size, MSB (2*1024 bytes)
+					; 12:11 = 0b01 (2 tr. per microframe)
+					; 10:00 = 1024
+	.db	0x01			; Polling interval (1 microframe)
+
+	; Isochronous interface 0, alt 3, 8MB/s
+	.db	DSCR_INTERFACE_LEN
+	.db	DSCR_INTERFACE_TYPE
+	.db	0			; Interface index
+	.db	3			; Alternate setting index
+	.db	1			; Number of endpoints
+	.db	0xff			; Class (vendor specific)
+	.db	0			; Subclass (0)
+	.db	1			; Protocol (1)
+	.db	0			; String index (none)
+
+	; Endpoint 2 (IN)
+	.db	DSCR_ENDPOINT_LEN
+	.db	DSCR_ENDPOINT_TYPE
+	.db	0x82			; EP number (2), direction (IN)
+	.db	ENDPOINT_TYPE_ISO	; Endpoint type (iso)
+	.db	0x00			; Max. packet size, LSB (1024 bytes)
+	.db	0x04			; Max. packet size, MSB (1024 bytes)
+	.db	0x01			; Polling interval (1 microframe)
+
+	; Isochronous interface 0, alt 4, 4MB/s
+	.db	DSCR_INTERFACE_LEN
+	.db	DSCR_INTERFACE_TYPE
+	.db	0			; Interface index
+	.db	4			; Alternate setting index
+	.db	1			; Number of endpoints
+	.db	0xff			; Class (vendor specific)
+	.db	0			; Subclass (0)
+	.db	1			; Protocol (1)
+	.db	0			; String index (none)
+
+	; Endpoint 2 (IN)
+	.db	DSCR_ENDPOINT_LEN
+	.db	DSCR_ENDPOINT_TYPE
+	.db	0x82			; EP number (2), direction (IN)
+	.db	ENDPOINT_TYPE_ISO	; Endpoint type (iso)
+	.db	0x00			; Max. packet size, LSB (1024 bytes)
+	.db	0x04			; Max. packet size, MSB (1024 bytes)
+	.db	0x02			; Polling interval (2 microframes)
+
+	; Isochronous interface 0, alt 5, 2MB/s
+	.db	DSCR_INTERFACE_LEN
+	.db	DSCR_INTERFACE_TYPE
+	.db	0			; Interface index
+	.db	5			; Alternate setting index
+	.db	1			; Number of endpoints
+	.db	0xff			; Class (vendor specific)
+	.db	0			; Subclass (0)
+	.db	1			; Protocol (1)
+	.db	0			; String index (none)
+
+	; Endpoint 2 (IN)
+	.db	DSCR_ENDPOINT_LEN
+	.db	DSCR_ENDPOINT_TYPE
+	.db	0x82			; EP number (2), direction (IN)
+	.db	ENDPOINT_TYPE_ISO	; Endpoint type (iso)
+	.db	0x00			; Max. packet size, LSB (1024 bytes)
+	.db	0x04			; Max. packet size, MSB (1024 bytes)
+	.db	0x03			; Polling interval (4 microframes)
+
+	; Isochronous interface 0, alt 6, 1MB/s
+	.db	DSCR_INTERFACE_LEN
+	.db	DSCR_INTERFACE_TYPE
+	.db	0			; Interface index
+	.db	6			; Alternate setting index
+	.db	1			; Number of endpoints
+	.db	0xff			; Class (vendor specific)
+	.db	0			; Subclass (0)
+	.db	1			; Protocol (1)
+	.db	0			; String index (none)
+
+	; Endpoint 2 (IN)
+	.db	DSCR_ENDPOINT_LEN
+	.db	DSCR_ENDPOINT_TYPE
+	.db	0x82			; EP number (2), direction (IN)
+	.db	ENDPOINT_TYPE_ISO	; Endpoint type (iso)
+	.db	0x00			; Max. packet size, LSB (1024 bytes)
+	.db	0x04			; Max. packet size, MSB (1024 bytes)
+	.db	0x04			; Polling interval (8 microframes)
+
+	; Isochronous interface 0, alt 7, 500kB/s
+	.db	DSCR_INTERFACE_LEN
+	.db	DSCR_INTERFACE_TYPE
+	.db	0			; Interface index
+	.db	7			; Alternate setting index
+	.db	1			; Number of endpoints
+	.db	0xff			; Class (vendor specific)
+	.db	0			; Subclass (0)
+	.db	1			; Protocol (1)
+	.db	0			; String index (none)
+
+	; Endpoint 2 (IN)
+	.db	DSCR_ENDPOINT_LEN
+	.db	DSCR_ENDPOINT_TYPE
+	.db	0x82			; EP number (2), direction (IN)
+	.db	ENDPOINT_TYPE_ISO	; Endpoint type (iso)
+	.db	0x00			; Max. packet size, LSB (512 bytes)
+	.db	0x02			; Max. packet size, MSB (512 bytes)
+	.db	0x04			; Polling interval (8 microframes)
+
+highspd_dscr_realend:
+
+	.even
+
+; -----------------------------------------------------------------------------
+; Full-Speed configuration descriptor
+; -----------------------------------------------------------------------------
+_fullspd_dscr:
+	.db	fullspd_dscr_end - _fullspd_dscr
+	.db	DSCR_CONFIG_TYPE
+	; Total length of the configuration (1st line LSB, 2nd line MSB)
+	.db	(fullspd_dscr_realend - _fullspd_dscr) % 256
+	.db	(fullspd_dscr_realend - _fullspd_dscr) / 256
+	.db	2			; Number of interfaces
+	.db	1			; Configuration number
+	.db	0			; Configuration string (none)
+	.db	0x80			; Attributes (bus powered, no wakeup)
+	.db	0x37			; Max. power (110mA)
+fullspd_dscr_end:
+
+	; Bulk interface 0, alt 0
+	.db	DSCR_INTERFACE_LEN
+	.db	DSCR_INTERFACE_TYPE
+	.db	0			; Interface index
+	.db	0			; Alternate setting index
+	.db	1			; Number of endpoints
+	.db	0xff			; Class (vendor specific)
+	.db	0			; Subclass (0)
+	.db	0			; Protocol (0)
+	.db	0			; String index (none)
+
+	; Endpoint 6 (IN)
+	.db	DSCR_ENDPOINT_LEN
+	.db	DSCR_ENDPOINT_TYPE
+	.db	0x86			; EP number (6), direction (IN)
+	.db	ENDPOINT_TYPE_BULK	; Endpoint type (bulk)
+	.db	0x40			; Max. packet size, LSB (64 bytes)
+	.db	0x00			; Max. packet size, MSB (64 bytes)
+	.db	0x00			; Polling interval (ignored for bulk)
+
+	; Isochronous interface 0, alt 1, 1MB/s
+	.db	DSCR_INTERFACE_LEN
+	.db	DSCR_INTERFACE_TYPE
+	.db	0			; Interface index
+	.db	1			; Alternate setting index
+	.db	1			; Number of endpoints
+	.db	0xff			; Class (vendor specific)
+	.db	0			; Subclass (0)
+	.db	1			; Protocol (1)
+	.db	0			; String index (none)
+
+	; Endpoint 2 (IN)
+	.db	DSCR_ENDPOINT_LEN
+	.db	DSCR_ENDPOINT_TYPE
+	.db	0x82			; EP number (2), direction (IN)
+	.db	ENDPOINT_TYPE_ISO	; Endpoint type (iso)
+	.db	0xff			; Max. packet size, LSB (1023 bytes)
+	.db	0x03			; Max. packet size, MSB (1023 bytes)
+	.db	0x01			; Polling interval (1 frame)
+
+	; Isochronous interface 0, alt 2, 500kB/s
+	.db	DSCR_INTERFACE_LEN
+	.db	DSCR_INTERFACE_TYPE
+	.db	0			; Interface index
+	.db	2			; Alternate setting index
+	.db	1			; Number of endpoints
+	.db	0xff			; Class (vendor specific)
+	.db	0			; Subclass (0)
+	.db	1			; Protocol (1)
+	.db	0			; String index (none)
+
+	; Endpoint 2 (IN)
+	.db	DSCR_ENDPOINT_LEN
+	.db	DSCR_ENDPOINT_TYPE
+	.db	0x82			; EP number (2), direction (IN)
+	.db	ENDPOINT_TYPE_ISO	; Endpoint type (iso)
+	.db	0x00			; Max. packet size, LSB (512 bytes)
+	.db	0x02			; Max. packet size, MSB (512 bytes)
+	.db	0x01			; Polling interval (1 frame)
+
+fullspd_dscr_realend:
+
+	.even
+
+; -----------------------------------------------------------------------------
+; Strings
+; -----------------------------------------------------------------------------
+
+_dev_strings:
+
+; See http://www.usb.org/developers/docs/USB_LANGIDs.pdf for the full list.
+string_descriptor_lang 0 0x0409 ; Language code 0x0409 (English, US)
+
+string_descriptor_a 1,^"sigrok"
+string_descriptor_a 2,^"fx2lafw"
diff --git a/include/fx2lafw.h b/include/fx2lafw.h
index bbc155b..abd877b 100644
--- a/include/fx2lafw.h
+++ b/include/fx2lafw.h
@@ -38,6 +38,6 @@
  * longer (properly) work with the new fx2lafw firmware.
  */
 #define FX2LAFW_VERSION_MAJOR	1
-#define FX2LAFW_VERSION_MINOR	1
+#define FX2LAFW_VERSION_MINOR	2
 
 #endif
diff --git a/sainsmart_dds120.c b/sainsmart_dds120.c
new file mode 100644
index 0000000..9f06af3
--- /dev/null
+++ b/sainsmart_dds120.c
@@ -0,0 +1,543 @@
+/*
+ * This file is part of the sigrok-firmware-fx2lafw project.
+ *
+ * Copyright (C) 2009 Ubixum, Inc.
+ * Copyright (C) 2015 Jochen Hoenicke
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <fx2macros.h>
+#include <fx2ints.h>
+#include <autovector.h>
+#include <delay.h>
+#include <setupdat.h>
+
+/* Change to support as many interfaces as you need. */
+static BYTE altiface = 0;
+
+static volatile __bit dosud = FALSE;
+static volatile __bit dosuspend = FALSE;
+
+extern __code BYTE highspd_dscr;
+extern __code BYTE fullspd_dscr;
+
+void resume_isr(void) __interrupt RESUME_ISR
+{
+	CLEAR_RESUME();
+}
+
+void sudav_isr(void) __interrupt SUDAV_ISR
+{
+	dosud = TRUE;
+	CLEAR_SUDAV();
+}
+
+void usbreset_isr(void) __interrupt USBRESET_ISR
+{
+	handle_hispeed(FALSE);
+	CLEAR_USBRESET();
+}
+
+void hispeed_isr(void) __interrupt HISPEED_ISR
+{
+	handle_hispeed(TRUE);
+	CLEAR_HISPEED();
+}
+
+void suspend_isr(void) __interrupt SUSPEND_ISR
+{
+	dosuspend = TRUE;
+	CLEAR_SUSPEND();
+}
+
+void timer2_isr(void) __interrupt TF2_ISR
+{
+	/* Toggle the 1kHz pin, only accurate up to ca 8MHz */
+	IOE = IOE^0x04;
+	TF2 = 0;
+}
+
+/**
+ * The gain stage is 2 stage approach. -6dB and -20dB on the first stage (attentuator). The second stage is then doing the gain by 3 different resistor values switched into the feedback loop.
+ * #Channel 0:
+ * PC1=1; PC2=0; PC3= 0 -> Gain x0.1 = -20dB
+ * PC1=1; PC2=0; PC3= 1 -> Gain x0.2 = -14dB
+ * PC1=1; PC2=1; PC3= 0 -> Gain x0.4 =  -8dB
+ * PC1=0; PC2=0; PC3= 0 -> Gain x0.5 =  -6dB
+ * PC1=0; PC2=0; PC3= 1 -> Gain x1   =   0dB
+ * PC1=0; PC2=1; PC3= 0 -> Gain x2   =  +6dB
+ * #Channel 1:
+ * PE1=1; PC4=0; PC5= 0 -> Gain x0.1 = -20dB 
+ * PE1=1; PC4=0; PC5= 1 -> Gain x0.2 = -14dB
+ * PE1=1; PC4=1; PC5= 0 -> Gain x0.4 =  -8dB
+ * PE1=0; PC4=0; PC5= 0 -> Gain x0.5 =  -6dB
+ * PE1=0; PC4=0; PC5= 1 -> Gain x1   =   0dB
+ * PE1=0; PC4=1; PC5= 0 -> Gain x2   =  +6dB
+ */
+static BOOL set_voltage(BYTE channel, BYTE val)
+{
+	BYTE bits_C, bit_E, mask_C, mask_E;
+
+	if (channel == 0) {
+		mask_C = 0x0E;
+		mask_E = 0x00;
+		bit_E = 0;
+		switch (val) {
+		case 1:
+			bits_C = 0x02;
+			break;
+		case 2:
+			bits_C = 0x06;
+			break;
+		case 5:
+			bits_C = 0x00;
+			break;
+		case 10:
+			bits_C = 0x04;
+			break;
+		case 20:
+			bits_C = 0x08;
+			break;
+		default:
+			return FALSE;
+		}
+	} else if (channel == 1) {
+		mask_C = 0x30;
+		mask_E = 0x02;
+		switch (val) {
+		case 1:
+			bits_C = 0x00;
+			bit_E = 0x02; 
+			break;
+		case 2:
+			bits_C = 0x10;
+			bit_E = 0x02; 
+			break;
+		case 5:
+			bits_C = 0x00;
+			bit_E = 0x00; 
+			break;
+		case 10:
+			bits_C = 0x10;
+			bit_E = 0x00; 
+			break;
+		case 20:
+			bits_C = 0x20;
+			bit_E = 0x00; 
+			break;
+		default:
+			return FALSE;
+		}
+	} else {
+		return FALSE;
+	}
+	IOC = (IOC & ~mask_C) | (bits_C & mask_C);
+	IOE = (IOE & ~mask_E) | (bit_E & mask_E);
+		
+	return TRUE;
+}
+
+
+/**
+ * Each LSB in the nibble of the byte controls the coupling per channel.
+ *
+ * Setting PE3 disables AC coupling capacitor on CH0.
+ * Setting PE0 disables AC coupling capacitor on CH1.
+ */
+static void set_coupling(BYTE coupling_cfg)
+{
+	if (coupling_cfg & 0x01)
+		IOE |= 0x08;
+	else
+		IOE &= ~0x08;
+
+	if (coupling_cfg & 0x10)
+		IOE |= 0x01;
+	else
+		IOE &= ~0x01;
+}
+
+static BOOL set_numchannels(BYTE numchannels)
+{
+	if (numchannels == 1 || numchannels == 2) {
+		BYTE fifocfg = 7 + numchannels;
+		EP2FIFOCFG = fifocfg;
+		EP6FIFOCFG = fifocfg;
+		return TRUE;
+	}
+
+	return FALSE;
+}
+
+static void clear_fifo(void)
+{
+	GPIFABORT = 0xff;
+	SYNCDELAY3;
+	FIFORESET = 0x80;
+	SYNCDELAY3;
+	FIFORESET = 0x82;
+	SYNCDELAY3;
+	FIFORESET = 0x86;
+	SYNCDELAY3;
+	FIFORESET = 0;
+}
+
+static void stop_sampling(void)
+{
+	GPIFABORT = 0xff;
+	SYNCDELAY3;
+	INPKTEND = (altiface == 0) ? 6 : 2;
+}
+
+static void start_sampling(void)
+{
+	int i;
+
+	clear_fifo();
+
+	for (i = 0; i < 1000; i++);
+
+	while (!(GPIFTRIG & 0x80))
+		;
+
+	SYNCDELAY3;
+	GPIFTCB1 = 0x28;
+	SYNCDELAY3;
+	GPIFTCB0 = 0;
+	GPIFTRIG = (altiface == 0) ? 6 : 4;
+
+}
+
+static void select_interface(BYTE alt)
+{
+	const BYTE *pPacketSize = \
+		((USBCS & bmHSM) ? &highspd_dscr : &fullspd_dscr)
+		+ (9 + (16 * alt) + 9 + 4);
+
+	altiface = alt;
+
+	if (alt == 0) {
+		/* Bulk on EP6. */
+		EP2CFG = 0x00;
+		EP6CFG = 0xe0;
+		EP6GPIFFLGSEL = 1;
+		EP6AUTOINLENL = pPacketSize[0];
+		EP6AUTOINLENH = pPacketSize[1];
+	} else {
+		/* Iso on EP2. */
+		EP2CFG = 0xd8;
+		EP6CFG = 0x00;
+		EP2GPIFFLGSEL = 1;
+		EP2AUTOINLENL = pPacketSize[0];
+		EP2AUTOINLENH = pPacketSize[1] & 0x7;
+		EP2ISOINPKTS = (pPacketSize[1] >> 3) + 1;
+	}
+}
+
+static const struct samplerate_info {
+	BYTE rate;
+	BYTE wait0;
+	BYTE wait1;
+	BYTE opc0;
+	BYTE opc1;
+	BYTE out0;
+	BYTE ifcfg;
+} samplerates[] = {
+	{ 48, 0x80,   0, 3, 0, 0x00, 0xea },
+	{ 30, 0x80,   0, 3, 0, 0x00, 0xaa },
+	{ 24,    1,   0, 2, 1, 0x40, 0xea },
+	{ 16,    1,   1, 2, 0, 0x40, 0xea },
+	{ 15,    1,   0, 2, 1, 0x40, 0xaa },
+	{ 12,    2,   1, 2, 0, 0x40, 0xea },
+	{ 11,    1,   1, 2, 0, 0x40, 0xaa },
+	{  8,    3,   2, 2, 0, 0x40, 0xea },
+	{  6,    2,   2, 2, 0, 0x40, 0xaa },
+	{  5,    3,   2, 2, 0, 0x40, 0xaa },
+	{  4,    6,   5, 2, 0, 0x40, 0xea },
+	{  3,    5,   4, 2, 0, 0x40, 0xaa },
+	{  2,   12,  11, 2, 0, 0x40, 0xea },
+	{  1,   24,  23, 2, 0, 0x40, 0xea },
+	{ 50,   48,  47, 2, 0, 0x40, 0xea },
+	{ 20,  120, 119, 2, 0, 0x40, 0xea },
+	{ 10,  240, 239, 2, 0, 0x40, 0xea },
+};
+
+static BOOL set_samplerate(BYTE rate)
+{
+	BYTE i = 0;
+
+	while (samplerates[i].rate != rate) {
+		i++;
+		if (i == sizeof(samplerates) / sizeof(samplerates[0]))
+			return FALSE;
+	}
+
+	IFCONFIG = samplerates[i].ifcfg;
+
+	AUTOPTRSETUP = 7;
+	AUTOPTRH2 = 0xE4; /* 0xE400: GPIF waveform descriptor 0. */
+	AUTOPTRL2 = 0x00;
+
+	/*
+	 * The program for low-speed, e.g. 1 MHz, is:
+	 * wait 24, CTL2=0, FIFO
+	 * wait 23, CTL2=1
+	 * jump 0, CTL2=1
+	 *
+	 * The program for 24 MHz is:
+	 * wait 1, CTL2=0, FIFO
+	 * jump 0, CTL2=1
+	 *
+	 * The program for 30/48 MHz is:
+	 * jump 0, CTL2=Z, FIFO, LOOP
+	 */
+
+	/* LENGTH / BRANCH 0-7 */
+	EXTAUTODAT2 = samplerates[i].wait0;
+	EXTAUTODAT2 = samplerates[i].wait1;
+	EXTAUTODAT2 = 1;
+	EXTAUTODAT2 = 0;
+	EXTAUTODAT2 = 0;
+	EXTAUTODAT2 = 0;
+	EXTAUTODAT2 = 0;
+	EXTAUTODAT2 = 0;
+
+	/* OPCODE 0-7 */
+	EXTAUTODAT2 = samplerates[i].opc0;
+	EXTAUTODAT2 = samplerates[i].opc1;
+	EXTAUTODAT2 = 1; /* DATA=0 DP=1 */
+	EXTAUTODAT2 = 0;
+	EXTAUTODAT2 = 0;
+	EXTAUTODAT2 = 0;
+	EXTAUTODAT2 = 0;
+	EXTAUTODAT2 = 0;
+
+	/* OUTPUT 0-7 */
+	EXTAUTODAT2 = samplerates[i].out0;
+	EXTAUTODAT2 = 0x44; /* OE0=1, CTL0=1 */
+	EXTAUTODAT2 = 0x44; /* OE0=1, CTL0=1 */
+	EXTAUTODAT2 = 0;
+	EXTAUTODAT2 = 0;
+	EXTAUTODAT2 = 0;
+	EXTAUTODAT2 = 0;
+	EXTAUTODAT2 = 0;
+
+	/* LOGIC FUNCTION 0-7 */
+	EXTAUTODAT2 = 0;
+	EXTAUTODAT2 = 0;
+	EXTAUTODAT2 = 0;
+	EXTAUTODAT2 = 0;
+	EXTAUTODAT2 = 0;
+	EXTAUTODAT2 = 0;
+	EXTAUTODAT2 = 0;
+	EXTAUTODAT2 = 0;
+
+	for (i = 0; i < 96; i++)
+		EXTAUTODAT2 = 0;
+
+	return TRUE;
+}
+
+static BOOL set_calibration_pulse(BYTE fs)
+{
+	switch (fs) {
+	case 0:		// 100Hz
+		RCAP2L = -10000 & 0xff;
+		RCAP2H = (-10000 & 0xff00) >> 8;
+		return TRUE;
+	case 1:		// 1kHz
+		RCAP2L = -1000 & 0xff;
+		RCAP2H = (-1000 & 0xff00) >> 8;
+		return TRUE;
+	case 10:	// 1kHz
+		RCAP2L = (BYTE)(-100 & 0xff);
+		RCAP2H = 0xff;
+		return TRUE;
+	case 50:	// 50kHz
+		RCAP2L = (BYTE)(-20 & 0xff);
+		RCAP2H = 0xff;
+		return TRUE;
+	default:
+		return FALSE;
+	}
+}
+
+/* Set *alt_ifc to the current alt interface for ifc. */
+BOOL handle_get_interface(BYTE ifc, BYTE *alt_ifc)
+{
+	(void)ifc;
+
+	*alt_ifc = altiface;
+
+	return TRUE;
+}
+
+/*
+ * Return TRUE if you set the interface requested.
+ *
+ * Note: This function should reconfigure and reset the endpoints
+ * according to the interface descriptors you provided.
+ */
+BOOL handle_set_interface(BYTE ifc,BYTE alt_ifc)
+{
+	if (ifc == 0)
+		select_interface(alt_ifc);
+
+	return TRUE;
+}
+
+BYTE handle_get_configuration(void)
+{
+	/* We only support configuration 0. */
+	return 0;
+}
+
+BOOL handle_set_configuration(BYTE cfg)
+{
+	/* We only support configuration 0. */
+	(void)cfg;
+
+	return TRUE;
+}
+
+BOOL handle_vendorcommand(BYTE cmd)
+{
+	stop_sampling();
+
+	/* Clear EP0BCH/L for each valid command. */
+	if (cmd >= 0xe0 && cmd <= 0xe6) {
+		EP0BCH = 0;
+		EP0BCL = 0;
+		while (EP0CS & bmEPBUSY);
+	}
+
+	switch (cmd) {
+	case 0xe0:
+	case 0xe1:
+		set_voltage(cmd - 0xe0, EP0BUF[0]);
+		return TRUE;
+	case 0xe2:
+		set_samplerate(EP0BUF[0]);
+		return TRUE;
+	case 0xe3:
+		if (EP0BUF[0] == 1)
+			start_sampling();
+		return TRUE;
+	case 0xe4:
+		set_numchannels(EP0BUF[0]);
+		return TRUE;
+	case 0xe5:
+		set_coupling(EP0BUF[0]);
+		return TRUE;
+	case 0xe6:
+		set_calibration_pulse(EP0BUF[0]);
+		return TRUE;
+	}
+
+	return FALSE; /* Not handled by handlers. */
+}
+
+static void init(void)
+{
+	EP4CFG = 0;
+	EP8CFG = 0;
+
+	/* In idle mode tristate all outputs. */
+	GPIFIDLECTL = 0x00; /* Don't enable CTL0-5 outputs. */
+	GPIFCTLCFG = 0x80; /* TRICTL=1. CTL0-2: CMOS outputs, tri-statable. */
+	GPIFWFSELECT = 0x00;
+	GPIFREADYSTAT = 0x00;
+
+	stop_sampling();
+
+	set_voltage(0, 1);
+	set_voltage(1, 1);
+	set_samplerate(1);
+	set_numchannels(2);
+	select_interface(0);
+}
+
+static void main(void)
+{
+	/* Save energy. */
+	SETCPUFREQ(CLK_12M);
+
+	init();
+
+	/* Set up interrupts. */
+	USE_USB_INTS();
+
+	ENABLE_SUDAV();
+	ENABLE_USBRESET();
+	ENABLE_HISPEED(); 
+	ENABLE_SUSPEND();
+	ENABLE_RESUME();
+
+	/* Global (8051) interrupt enable. */
+	EA = 1;
+
+	/* Init timer2. */
+	RCAP2L = -1000 & 0xff;
+	RCAP2H = (-1000 & 0xff00) >> 8;
+	T2CON = 0;
+	ET2 = 1;
+	TR2 = 1;
+
+	RENUMERATE_UNCOND();
+
+	PORTCCFG = 0;
+	PORTACFG = 0;
+	PORTECFG = 0;
+	OEE = 0xFF;
+	OEC = 0xff;
+	OEA = 0x80;
+
+	PA7 = 1;
+
+	while (TRUE) {
+		if (dosud) {
+			dosud = FALSE;
+			handle_setupdata();
+		}
+
+		if (dosuspend) {
+			dosuspend = FALSE;
+			do {
+				/* Make sure ext wakeups are cleared. */
+				WAKEUPCS |= bmWU|bmWU2;
+				SUSPEND = 1;
+				PCON |= 1;
+				__asm
+				nop
+				nop
+				nop
+				nop
+				nop
+				nop
+				nop
+				__endasm;
+			} while (!remote_wakeup_allowed && REMOTE_WAKEUP());
+
+			/* Resume (TRM 6.4). */
+			if (REMOTE_WAKEUP()) {
+				delay(5);
+				USBCS |= bmSIGRESUME;
+				delay(15);
+				USBCS &= ~bmSIGRESUME;
+			}
+		}
+	}
+}

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/sigrok-firmware-fx2lafw.git



More information about the debian-science-commits mailing list