]> sigrok.org Git - libsigrok.git/blobdiff - src/hardware/saleae-logic16/protocol.c
output/csv: use intermediate time_t var, silence compiler warning
[libsigrok.git] / src / hardware / saleae-logic16 / protocol.c
index d60bf3e7a50aa20c4236b072aaf864a743adc698..ce8db37f169c6a5b03dc495c6da3081775aeb3af 100644 (file)
@@ -19,8 +19,7 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "protocol.h"
-
+#include <config.h>
 #include <stdint.h>
 #include <string.h>
 #include <glib.h>
 #include <stdio.h>
 #include <errno.h>
 #include <math.h>
-#include "libsigrok.h"
+#include <libsigrok/libsigrok.h>
 #include "libsigrok-internal.h"
+#include "protocol.h"
 
-#define FPGA_FIRMWARE_18       FIRMWARE_DIR"/saleae-logic16-fpga-18.bitstream"
-#define FPGA_FIRMWARE_33       FIRMWARE_DIR"/saleae-logic16-fpga-33.bitstream"
+#define FPGA_FIRMWARE_18       "saleae-logic16-fpga-18.bitstream"
+#define FPGA_FIRMWARE_33       "saleae-logic16-fpga-33.bitstream"
 
 #define MAX_SAMPLE_RATE                SR_MHZ(100)
-#define MAX_4CH_SAMPLE_RATE    SR_MHZ(50)
-#define MAX_7CH_SAMPLE_RATE    SR_MHZ(40)
-#define MAX_8CH_SAMPLE_RATE    SR_MHZ(32)
-#define MAX_10CH_SAMPLE_RATE   SR_MHZ(25)
-#define MAX_13CH_SAMPLE_RATE   SR_MHZ(16)
+#define MAX_SAMPLE_RATE_X_CH   SR_MHZ(300)
 
 #define BASE_CLOCK_0_FREQ      SR_MHZ(100)
 #define BASE_CLOCK_1_FREQ      SR_MHZ(160)
 
 #define MAX_EMPTY_TRANSFERS            64
 
+/* Register mappings for old and new bitstream versions */
+
+enum fpga_register_id {
+       FPGA_REGISTER_VERSION,
+       FPGA_REGISTER_STATUS_CONTROL,
+       FPGA_REGISTER_CHANNEL_SELECT_LOW,
+       FPGA_REGISTER_CHANNEL_SELECT_HIGH,
+       FPGA_REGISTER_SAMPLE_RATE_DIVISOR,
+       FPGA_REGISTER_LED_BRIGHTNESS,
+       FPGA_REGISTER_PRIMER_DATA1,
+       FPGA_REGISTER_PRIMER_CONTROL,
+       FPGA_REGISTER_MODE,
+       FPGA_REGISTER_PRIMER_DATA2,
+       FPGA_REGISTER_MAX = FPGA_REGISTER_PRIMER_DATA2
+};
+
+enum fpga_status_control_bit {
+       FPGA_STATUS_CONTROL_BIT_RUNNING,
+       FPGA_STATUS_CONTROL_BIT_UPDATE,
+       FPGA_STATUS_CONTROL_BIT_UNKNOWN1,
+       FPGA_STATUS_CONTROL_BIT_OVERFLOW,
+       FPGA_STATUS_CONTROL_BIT_UNKNOWN2,
+       FPGA_STATUS_CONTROL_BIT_MAX = FPGA_STATUS_CONTROL_BIT_UNKNOWN2
+};
+
+enum fpga_mode_bit {
+       FPGA_MODE_BIT_CLOCK,
+       FPGA_MODE_BIT_UNKNOWN1,
+       FPGA_MODE_BIT_UNKNOWN2,
+       FPGA_MODE_BIT_MAX = FPGA_MODE_BIT_UNKNOWN2
+};
+
+static const uint8_t fpga_register_map_old[FPGA_REGISTER_MAX + 1] = {
+       [FPGA_REGISTER_VERSION]                 = 0,
+       [FPGA_REGISTER_STATUS_CONTROL]          = 1,
+       [FPGA_REGISTER_CHANNEL_SELECT_LOW]      = 2,
+       [FPGA_REGISTER_CHANNEL_SELECT_HIGH]     = 3,
+       [FPGA_REGISTER_SAMPLE_RATE_DIVISOR]     = 4,
+       [FPGA_REGISTER_LED_BRIGHTNESS]          = 5,
+       [FPGA_REGISTER_PRIMER_DATA1]            = 6,
+       [FPGA_REGISTER_PRIMER_CONTROL]          = 7,
+       [FPGA_REGISTER_MODE]                    = 10,
+       [FPGA_REGISTER_PRIMER_DATA2]            = 12,
+};
+
+static const uint8_t fpga_register_map_new[FPGA_REGISTER_MAX + 1] = {
+       [FPGA_REGISTER_VERSION]                 = 7,
+       [FPGA_REGISTER_STATUS_CONTROL]          = 15,
+       [FPGA_REGISTER_CHANNEL_SELECT_LOW]      = 1,
+       [FPGA_REGISTER_CHANNEL_SELECT_HIGH]     = 6,
+       [FPGA_REGISTER_SAMPLE_RATE_DIVISOR]     = 11,
+       [FPGA_REGISTER_LED_BRIGHTNESS]          = 5,
+       [FPGA_REGISTER_PRIMER_DATA1]            = 14,
+       [FPGA_REGISTER_PRIMER_CONTROL]          = 2,
+       [FPGA_REGISTER_MODE]                    = 4,
+       [FPGA_REGISTER_PRIMER_DATA2]            = 3,
+};
+
+static const uint8_t fpga_status_control_bit_map_old[FPGA_STATUS_CONTROL_BIT_MAX + 1] = {
+       [FPGA_STATUS_CONTROL_BIT_RUNNING]       = 0x01,
+       [FPGA_STATUS_CONTROL_BIT_UPDATE]        = 0x02,
+       [FPGA_STATUS_CONTROL_BIT_UNKNOWN1]      = 0x08,
+       [FPGA_STATUS_CONTROL_BIT_OVERFLOW]      = 0x20,
+       [FPGA_STATUS_CONTROL_BIT_UNKNOWN2]      = 0x40,
+};
+
+static const uint8_t fpga_status_control_bit_map_new[FPGA_STATUS_CONTROL_BIT_MAX + 1] = {
+       [FPGA_STATUS_CONTROL_BIT_RUNNING]       = 0x20,
+       [FPGA_STATUS_CONTROL_BIT_UPDATE]        = 0x08,
+       [FPGA_STATUS_CONTROL_BIT_UNKNOWN1]      = 0x10,
+       [FPGA_STATUS_CONTROL_BIT_OVERFLOW]      = 0x01,
+       [FPGA_STATUS_CONTROL_BIT_UNKNOWN2]      = 0x04,
+};
+
+static const uint8_t fpga_mode_bit_map_old[FPGA_MODE_BIT_MAX + 1] = {
+       [FPGA_MODE_BIT_CLOCK]           = 0x01,
+       [FPGA_MODE_BIT_UNKNOWN1]        = 0x40,
+       [FPGA_MODE_BIT_UNKNOWN2]        = 0x80,
+};
+
+static const uint8_t fpga_mode_bit_map_new[FPGA_MODE_BIT_MAX + 1] = {
+       [FPGA_MODE_BIT_CLOCK]           = 0x04,
+       [FPGA_MODE_BIT_UNKNOWN1]        = 0x80,
+       [FPGA_MODE_BIT_UNKNOWN2]        = 0x01,
+};
+
+#define FPGA_REG(x) \
+       (devc->fpga_register_map[FPGA_REGISTER_ ## x])
+
+#define FPGA_STATUS_CONTROL(x) \
+       (devc->fpga_status_control_bit_map[FPGA_STATUS_CONTROL_BIT_ ## x])
+
+#define FPGA_MODE(x) \
+       (devc->fpga_mode_bit_map[FPGA_MODE_BIT_ ## x])
+
 static void encrypt(uint8_t *dest, const uint8_t *src, uint8_t cnt)
 {
        uint8_t state1 = 0x9b, state2 = 0x54;
@@ -107,7 +198,7 @@ static int do_ep1_command(const struct sr_dev_inst *sdi,
        usb = sdi->conn;
 
        if (cmd_len < 1 || cmd_len > 64 || reply_len > 64 ||
-           command == NULL || (reply_len > 0 && reply == NULL))
+           !command || (reply_len > 0 && !reply))
                return SR_ERR_ARG;
 
        encrypt(buf, command, cmd_len);
@@ -120,7 +211,7 @@ static int do_ep1_command(const struct sr_dev_inst *sdi,
        }
        if (xfer != cmd_len) {
                sr_dbg("Failed to send EP1 command 0x%02x: incorrect length "
-                      "%d != %d.", xfer, cmd_len);
+                      "%d != %d.", command[0], xfer, cmd_len);
                return SR_ERR;
        }
 
@@ -136,7 +227,7 @@ static int do_ep1_command(const struct sr_dev_inst *sdi,
        }
        if (xfer != reply_len) {
                sr_dbg("Failed to receive reply to EP1 command 0x%02x: "
-                      "incorrect length %d != %d.", xfer, reply_len);
+                      "incorrect length %d != %d.", command[0], xfer, reply_len);
                return SR_ERR;
        }
 
@@ -165,7 +256,7 @@ static int upload_led_table(const struct sr_dev_inst *sdi,
        uint8_t chunk, command[64];
        int ret;
 
-       if (cnt < 1 || cnt + offset > 64 || table == NULL)
+       if (cnt < 1 || cnt + offset > 64 || !table)
                return SR_ERR_ARG;
 
        while (cnt > 0) {
@@ -248,32 +339,76 @@ static uint8_t map_eeprom_data(uint8_t v)
        return (((v ^ 0x80) + 0x44) ^ 0xd5) + 0x69;
 }
 
+static int setup_register_mapping(const struct sr_dev_inst *sdi)
+{
+       struct dev_context *devc;
+       int ret;
+
+       devc = sdi->priv;
+
+       if (devc->fpga_variant != FPGA_VARIANT_MCUPRO) {
+               uint8_t reg0, reg7;
+
+               /*
+                * Check for newer bitstream version by polling the
+                * version register at the old and new location.
+                */
+
+               if ((ret = read_fpga_register(sdi, 0 /* No mapping */, &reg0)) != SR_OK)
+                       return ret;
+
+               if ((ret = read_fpga_register(sdi, 7 /* No mapping */, &reg7)) != SR_OK)
+                       return ret;
+
+               if (reg0 == 0 && reg7 > 0x10) {
+                       sr_info("Original Saleae Logic16 using new bitstream.");
+                       devc->fpga_variant = FPGA_VARIANT_ORIGINAL_NEW_BITSTREAM;
+               } else {
+                       sr_info("Original Saleae Logic16 using old bitstream.");
+                       devc->fpga_variant = FPGA_VARIANT_ORIGINAL;
+               }
+       }
+
+       if (devc->fpga_variant == FPGA_VARIANT_ORIGINAL_NEW_BITSTREAM) {
+               devc->fpga_register_map = fpga_register_map_new;
+               devc->fpga_status_control_bit_map = fpga_status_control_bit_map_new;
+               devc->fpga_mode_bit_map = fpga_mode_bit_map_new;
+       } else {
+               devc->fpga_register_map = fpga_register_map_old;
+               devc->fpga_status_control_bit_map = fpga_status_control_bit_map_old;
+               devc->fpga_mode_bit_map = fpga_mode_bit_map_old;
+       }
+
+       return SR_OK;
+}
+
 static int prime_fpga(const struct sr_dev_inst *sdi)
 {
+       struct dev_context *devc = sdi->priv;
        uint8_t eeprom_data[16];
-       uint8_t old_reg_10, version;
+       uint8_t old_mode_reg, version;
        uint8_t regs[8][2] = {
-               {10, 0x00},
-               {10, 0x40},
-               {12, 0},
-               {10, 0xc0},
-               {10, 0x40},
-               {6, 0},
-               {7, 1},
-               {7, 0}
+               {FPGA_REG(MODE), 0x00},
+               {FPGA_REG(MODE), FPGA_MODE(UNKNOWN1)},
+               {FPGA_REG(PRIMER_DATA2), 0},
+               {FPGA_REG(MODE), FPGA_MODE(UNKNOWN1) | FPGA_MODE(UNKNOWN2)},
+               {FPGA_REG(MODE), FPGA_MODE(UNKNOWN1)},
+               {FPGA_REG(PRIMER_DATA1), 0},
+               {FPGA_REG(PRIMER_CONTROL), 1},
+               {FPGA_REG(PRIMER_CONTROL), 0}
        };
        int i, ret;
 
        if ((ret = read_eeprom(sdi, 16, 16, eeprom_data)) != SR_OK)
                return ret;
 
-       if ((ret = read_fpga_register(sdi, 10, &old_reg_10)) != SR_OK)
+       if ((ret = read_fpga_register(sdi, FPGA_REG(MODE), &old_mode_reg)) != SR_OK)
                return ret;
 
-       regs[0][1] = (old_reg_10 &= 0x7f);
-       regs[1][1] |= old_reg_10;
-       regs[3][1] |= old_reg_10;
-       regs[4][1] |= old_reg_10;
+       regs[0][1] = (old_mode_reg &= ~FPGA_MODE(UNKNOWN2));
+       regs[1][1] |= old_mode_reg;
+       regs[3][1] |= old_mode_reg;
+       regs[4][1] |= old_mode_reg;
 
        for (i = 0; i < 16; i++) {
                regs[2][1] = eeprom_data[i];
@@ -286,15 +421,14 @@ static int prime_fpga(const struct sr_dev_inst *sdi)
                        return ret;
        }
 
-       if ((ret = write_fpga_register(sdi, 10, old_reg_10)) != SR_OK)
+       if ((ret = write_fpga_register(sdi, FPGA_REG(MODE), old_mode_reg)) != SR_OK)
                return ret;
 
-       if ((ret = read_fpga_register(sdi, 0, &version)) != SR_OK)
+       if ((ret = read_fpga_register(sdi, FPGA_REG(VERSION), &version)) != SR_OK)
                return ret;
 
-       if (version != 0x10 && version != 0x40 && version != 0x41) {
-               sr_err("Unsupported FPGA version: 0x%02x.", version);
-               return SR_ERR;
+       if (version != 0x10 && version != 0x13 && version != 0x40 && version != 0x41) {
+               sr_warn("Unsupported FPGA version: 0x%02x.", version);
        }
 
        return SR_OK;
@@ -308,7 +442,7 @@ static void make_heartbeat(uint8_t *table, int len)
        len >>= 3;
        for (i = 0; i < 2; i++)
                for (j = 0; j < len; j++)
-                       *table++ = sin(j * M_PI / len) * 255;
+                       *table++ = sin(j * G_PI / len) * 255;
 }
 
 static int configure_led(const struct sr_dev_inst *sdi)
@@ -326,67 +460,75 @@ static int configure_led(const struct sr_dev_inst *sdi)
 static int upload_fpga_bitstream(const struct sr_dev_inst *sdi,
                                 enum voltage_range vrange)
 {
+       uint64_t sum;
+       struct sr_resource bitstream;
        struct dev_context *devc;
-       int offset, chunksize, ret;
-       const char *filename;
-       uint8_t len, buf[256 * 62], command[64];
-       FILE *fw;
+       struct drv_context *drvc;
+       const char *name;
+       ssize_t chunksize;
+       int ret;
+       uint8_t command[64];
 
        devc = sdi->priv;
+       drvc = sdi->driver->context;
 
        if (devc->cur_voltage_range == vrange)
                return SR_OK;
 
-       if (devc->fpga_variant == FPGA_VARIANT_ORIGINAL) {
+       if (devc->fpga_variant != FPGA_VARIANT_MCUPRO) {
                switch (vrange) {
                case VOLTAGE_RANGE_18_33_V:
-                       filename = FPGA_FIRMWARE_18;
+                       name = FPGA_FIRMWARE_18;
                        break;
                case VOLTAGE_RANGE_5_V:
-                       filename = FPGA_FIRMWARE_33;
+                       name = FPGA_FIRMWARE_33;
                        break;
                default:
                        sr_err("Unsupported voltage range.");
                        return SR_ERR;
                }
 
-               sr_info("Uploading FPGA bitstream at %s.", filename);
-               if ((fw = g_fopen(filename, "rb")) == NULL) {
-                       sr_err("Unable to open bitstream file %s for reading: %s.",
-                              filename, strerror(errno));
-                       return SR_ERR;
-               }
+               sr_info("Uploading FPGA bitstream '%s'.", name);
+               ret = sr_resource_open(drvc->sr_ctx, &bitstream,
+                               SR_RESOURCE_FIRMWARE, name);
+               if (ret != SR_OK)
+                       return ret;
 
-               buf[0] = COMMAND_FPGA_UPLOAD_INIT;
-               if ((ret = do_ep1_command(sdi, buf, 1, NULL, 0)) != SR_OK) {
-                       fclose(fw);
+               command[0] = COMMAND_FPGA_UPLOAD_INIT;
+               if ((ret = do_ep1_command(sdi, command, 1, NULL, 0)) != SR_OK) {
+                       sr_resource_close(drvc->sr_ctx, &bitstream);
                        return ret;
                }
 
+               sum = 0;
                while (1) {
-                       chunksize = fread(buf, 1, sizeof(buf), fw);
+                       chunksize = sr_resource_read(drvc->sr_ctx, &bitstream,
+                                       &command[2], sizeof(command) - 2);
+                       if (chunksize < 0) {
+                               sr_resource_close(drvc->sr_ctx, &bitstream);
+                               return SR_ERR;
+                       }
                        if (chunksize == 0)
                                break;
-
-                       for (offset = 0; offset < chunksize; offset += 62) {
-                               len = (offset + 62 > chunksize ?
-                                       chunksize - offset : 62);
-                               command[0] = COMMAND_FPGA_UPLOAD_SEND_DATA;
-                               command[1] = len;
-                               memcpy(command + 2, buf + offset, len);
-                               ret = do_ep1_command(sdi, command, len + 2, NULL, 0);
-                               if (ret != SR_OK) {
-                                       fclose(fw);
-                                       return ret;
-                               }
+                       command[0] = COMMAND_FPGA_UPLOAD_SEND_DATA;
+                       command[1] = chunksize;
+
+                       ret = do_ep1_command(sdi, command, chunksize + 2,
+                                       NULL, 0);
+                       if (ret != SR_OK) {
+                               sr_resource_close(drvc->sr_ctx, &bitstream);
+                               return ret;
                        }
-
-                       sr_info("Uploaded %d bytes.", chunksize);
+                       sum += chunksize;
                }
-               fclose(fw);
-               sr_info("FPGA bitstream upload done.");
+               sr_resource_close(drvc->sr_ctx, &bitstream);
+               sr_info("FPGA bitstream upload (%" PRIu64 " bytes) done.", sum);
        }
 
+       /* This needs to be called before accessing any FPGA registers. */
+       if ((ret = setup_register_mapping(sdi)) != SR_OK)
+               return ret;
+
        if ((ret = prime_fpga(sdi)) != SR_OK)
                return ret;
 
@@ -422,7 +564,7 @@ static int abort_acquisition_sync(const struct sr_dev_inst *sdi)
 SR_PRIV int logic16_setup_acquisition(const struct sr_dev_inst *sdi,
                             uint64_t samplerate, uint16_t channels)
 {
-       uint8_t clock_select, reg1, reg10;
+       uint8_t clock_select, sta_con_reg, mode_reg;
        uint64_t div;
        int i, ret, nchan = 0;
        struct dev_context *devc;
@@ -449,11 +591,7 @@ SR_PRIV int logic16_setup_acquisition(const struct sr_dev_inst *sdi,
                if (channels & (1U << i))
                        nchan++;
 
-       if ((nchan >= 13 && samplerate > MAX_13CH_SAMPLE_RATE) ||
-           (nchan >= 10 && samplerate > MAX_10CH_SAMPLE_RATE) ||
-           (nchan >= 8  && samplerate > MAX_8CH_SAMPLE_RATE) ||
-           (nchan >= 7  && samplerate > MAX_7CH_SAMPLE_RATE) ||
-           (nchan >= 4  && samplerate > MAX_4CH_SAMPLE_RATE)) {
+       if (nchan * samplerate > MAX_SAMPLE_RATE_X_CH) {
                sr_err("Unable to sample at %" PRIu64 "Hz "
                       "with this many channels.", samplerate);
                return SR_ERR;
@@ -463,53 +601,52 @@ SR_PRIV int logic16_setup_acquisition(const struct sr_dev_inst *sdi,
        if (ret != SR_OK)
                return ret;
 
-       if ((ret = read_fpga_register(sdi, 1, &reg1)) != SR_OK)
+       if ((ret = read_fpga_register(sdi, FPGA_REG(STATUS_CONTROL), &sta_con_reg)) != SR_OK)
                return ret;
 
        /* Ignore FIFO overflow on previous capture */
-       reg1 &= ~0x20;
+       sta_con_reg &= ~FPGA_STATUS_CONTROL(OVERFLOW);
 
-       if (devc->fpga_variant == FPGA_VARIANT_ORIGINAL && reg1 != 0x08) {
-               sr_dbg("Invalid state at acquisition setup register 1: 0x%02x != 0x08.", reg1);
-               return SR_ERR;
+       if (devc->fpga_variant != FPGA_VARIANT_MCUPRO && sta_con_reg != FPGA_STATUS_CONTROL(UNKNOWN1)) {
+               sr_dbg("Invalid state at acquisition setup register 1: 0x%02x != 0x%02x. "
+                      "Proceeding anyway.", sta_con_reg, FPGA_STATUS_CONTROL(UNKNOWN1));
        }
 
-       if ((ret = write_fpga_register(sdi, 1, 0x40)) != SR_OK)
+       if ((ret = write_fpga_register(sdi, FPGA_REG(STATUS_CONTROL), FPGA_STATUS_CONTROL(UNKNOWN2))) != SR_OK)
                return ret;
 
-       if ((ret = write_fpga_register(sdi, 10, clock_select)) != SR_OK)
+       if ((ret = write_fpga_register(sdi, FPGA_REG(MODE), (clock_select? FPGA_MODE(CLOCK) : 0))) != SR_OK)
                return ret;
 
-       if ((ret = write_fpga_register(sdi, 4, (uint8_t)(div - 1))) != SR_OK)
+       if ((ret = write_fpga_register(sdi, FPGA_REG(SAMPLE_RATE_DIVISOR), (uint8_t)(div - 1))) != SR_OK)
                return ret;
 
-       if ((ret = write_fpga_register(sdi, 2, (uint8_t)(channels & 0xff))) != SR_OK)
+       if ((ret = write_fpga_register(sdi, FPGA_REG(CHANNEL_SELECT_LOW), (uint8_t)(channels & 0xff))) != SR_OK)
                return ret;
 
-       if ((ret = write_fpga_register(sdi, 3, (uint8_t)(channels >> 8))) != SR_OK)
+       if ((ret = write_fpga_register(sdi, FPGA_REG(CHANNEL_SELECT_HIGH), (uint8_t)(channels >> 8))) != SR_OK)
                return ret;
 
-       if ((ret = write_fpga_register(sdi, 1, 0x42)) != SR_OK)
+       if ((ret = write_fpga_register(sdi, FPGA_REG(STATUS_CONTROL), FPGA_STATUS_CONTROL(UNKNOWN2) | FPGA_STATUS_CONTROL(UPDATE))) != SR_OK)
                return ret;
 
-       if ((ret = write_fpga_register(sdi, 1, 0x40)) != SR_OK)
+       if ((ret = write_fpga_register(sdi, FPGA_REG(STATUS_CONTROL), FPGA_STATUS_CONTROL(UNKNOWN2))) != SR_OK)
                return ret;
 
-       if ((ret = read_fpga_register(sdi, 1, &reg1)) != SR_OK)
+       if ((ret = read_fpga_register(sdi, FPGA_REG(STATUS_CONTROL), &sta_con_reg)) != SR_OK)
                return ret;
 
-       if (devc->fpga_variant == FPGA_VARIANT_ORIGINAL && reg1 != 0x48) {
-               sr_dbg("Invalid state at acquisition setup register 1: 0x%02x != 0x48. "
-                      "Proceeding anyway.", reg1);
+       if (devc->fpga_variant != FPGA_VARIANT_MCUPRO && sta_con_reg != (FPGA_STATUS_CONTROL(UNKNOWN2) | FPGA_STATUS_CONTROL(UNKNOWN1))) {
+               sr_dbg("Invalid state at acquisition setup register 1: 0x%02x != 0x%02x. "
+                      "Proceeding anyway.", sta_con_reg, FPGA_STATUS_CONTROL(UNKNOWN2) | FPGA_STATUS_CONTROL(UNKNOWN1));
        }
 
-       if ((ret = read_fpga_register(sdi, 10, &reg10)) != SR_OK)
+       if ((ret = read_fpga_register(sdi, FPGA_REG(MODE), &mode_reg)) != SR_OK)
                return ret;
 
-       if (devc->fpga_variant == FPGA_VARIANT_ORIGINAL && reg10 != clock_select) {
-               sr_dbg("Invalid state at acquisition setup register 10: 0x%02x != 0x%02x.",
-                      reg10, clock_select);
-               return SR_ERR;
+       if (devc->fpga_variant != FPGA_VARIANT_MCUPRO && mode_reg != (clock_select? FPGA_MODE(CLOCK) : 0)) {
+               sr_dbg("Invalid state at acquisition setup register 10: 0x%02x != 0x%02x. "
+                      "Proceeding anyway.", mode_reg, (clock_select? FPGA_MODE(CLOCK) : 0));
        }
 
        return SR_OK;
@@ -521,11 +658,14 @@ SR_PRIV int logic16_start_acquisition(const struct sr_dev_inst *sdi)
                COMMAND_START_ACQUISITION,
        };
        int ret;
+       struct dev_context *devc;
+
+       devc = sdi->priv;
 
        if ((ret = do_ep1_command(sdi, command, 1, NULL, 0)) != SR_OK)
                return ret;
 
-       return write_fpga_register(sdi, 1, 0x41);
+       return write_fpga_register(sdi, FPGA_REG(STATUS_CONTROL), FPGA_STATUS_CONTROL(UNKNOWN2) | FPGA_STATUS_CONTROL(RUNNING));
 }
 
 SR_PRIV int logic16_abort_acquisition(const struct sr_dev_inst *sdi)
@@ -534,7 +674,7 @@ SR_PRIV int logic16_abort_acquisition(const struct sr_dev_inst *sdi)
                COMMAND_ABORT_ACQUISITION_ASYNC,
        };
        int ret;
-       uint8_t reg1, reg8, reg9;
+       uint8_t sta_con_reg;
        struct dev_context *devc;
 
        devc = sdi->priv;
@@ -542,24 +682,29 @@ SR_PRIV int logic16_abort_acquisition(const struct sr_dev_inst *sdi)
        if ((ret = do_ep1_command(sdi, command, 1, NULL, 0)) != SR_OK)
                return ret;
 
-       if ((ret = write_fpga_register(sdi, 1, 0x00)) != SR_OK)
+       if ((ret = write_fpga_register(sdi, FPGA_REG(STATUS_CONTROL), 0x00)) != SR_OK)
                return ret;
 
-       if ((ret = read_fpga_register(sdi, 1, &reg1)) != SR_OK)
+       if ((ret = read_fpga_register(sdi, FPGA_REG(STATUS_CONTROL), &sta_con_reg)) != SR_OK)
                return ret;
 
-       if (devc->fpga_variant == FPGA_VARIANT_ORIGINAL && (reg1 & ~0x20) != 0x08) {
-               sr_dbg("Invalid state at acquisition stop: 0x%02x != 0x08.", reg1 & ~0x20);
+       if (devc->fpga_variant != FPGA_VARIANT_MCUPRO && (sta_con_reg & ~FPGA_STATUS_CONTROL(OVERFLOW)) != FPGA_STATUS_CONTROL(UNKNOWN1)) {
+               sr_dbg("Invalid state at acquisition stop: 0x%02x != 0x%02x.", sta_con_reg & ~0x20, FPGA_STATUS_CONTROL(UNKNOWN1));
                return SR_ERR;
        }
 
-       if ((ret = read_fpga_register(sdi, 8, &reg8)) != SR_OK)
-               return ret;
 
-       if ((ret = read_fpga_register(sdi, 9, &reg9)) != SR_OK)
-               return ret;
+       if (devc->fpga_variant == FPGA_VARIANT_ORIGINAL) {
+               uint8_t reg8, reg9;
+
+               if ((ret = read_fpga_register(sdi, 8, &reg8)) != SR_OK)
+                       return ret;
+
+               if ((ret = read_fpga_register(sdi, 9, &reg9)) != SR_OK)
+                       return ret;
+       }
 
-       if (devc->fpga_variant == FPGA_VARIANT_ORIGINAL && reg1 & 0x20) {
+       if (devc->fpga_variant != FPGA_VARIANT_MCUPRO && sta_con_reg & FPGA_STATUS_CONTROL(OVERFLOW)) {
                sr_warn("FIFO overflow, capture data may be truncated.");
                return SR_ERR;
        }
@@ -585,7 +730,7 @@ SR_PRIV int logic16_init_device(const struct sr_dev_inst *sdi)
 
        /* mcupro Saleae16 has firmware pre-stored in FPGA.
           So, we can query it right away. */
-       if (read_fpga_register(sdi, 0, &version) == SR_OK &&
+       if (read_fpga_register(sdi, 0 /* No mapping */, &version) == SR_OK &&
            (version == 0x40 || version == 0x41)) {
                sr_info("mcupro Saleae16 detected.");
                devc->fpga_variant = FPGA_VARIANT_MCUPRO;
@@ -603,16 +748,12 @@ SR_PRIV int logic16_init_device(const struct sr_dev_inst *sdi)
 
 static void finish_acquisition(struct sr_dev_inst *sdi)
 {
-       struct sr_datafeed_packet packet;
        struct dev_context *devc;
 
        devc = sdi->priv;
 
-       /* Terminate session. */
-       packet.type = SR_DF_END;
-       sr_session_send(devc->cb_data, &packet);
+       std_session_send_df_end(sdi);
 
-       /* Remove fds from polling. */
        usb_source_remove(sdi->session, devc->ctx);
 
        devc->num_transfers = 0;
@@ -704,7 +845,7 @@ static size_t convert_sample_data(struct dev_context *devc,
        return ret;
 }
 
-SR_PRIV void logic16_receive_transfer(struct libusb_transfer *transfer)
+SR_PRIV void LIBUSB_CALL logic16_receive_transfer(struct libusb_transfer *transfer)
 {
        gboolean packet_has_error = FALSE;
        struct sr_datafeed_packet packet;
@@ -727,8 +868,8 @@ SR_PRIV void logic16_receive_transfer(struct libusb_transfer *transfer)
                return;
        }
 
-       sr_info("receive_transfer(): status %d received %d bytes.",
-               transfer->status, transfer->actual_length);
+       sr_info("receive_transfer(): status %s received %d bytes.",
+               libusb_error_name(transfer->status), transfer->actual_length);
 
        switch (transfer->status) {
        case LIBUSB_TRANSFER_NO_DEVICE:
@@ -771,47 +912,51 @@ SR_PRIV void logic16_receive_transfer(struct libusb_transfer *transfer)
        new_samples = convert_sample_data(devc, devc->convbuffer,
                        devc->convbuffer_size, transfer->buffer, transfer->actual_length);
 
-       if (new_samples > 0) {
-               if (devc->trigger_fired) {
-                       /* Send the incoming transfer to the session bus. */
+       if (new_samples <= 0) {
+               resubmit_transfer(transfer);
+               return;
+       }
+
+       /* At least one new sample. */
+       if (devc->trigger_fired) {
+               /* Send the incoming transfer to the session bus. */
+               packet.type = SR_DF_LOGIC;
+               packet.payload = &logic;
+               if (devc->limit_samples &&
+                               new_samples > devc->limit_samples - devc->sent_samples)
+                       new_samples = devc->limit_samples - devc->sent_samples;
+               logic.length = new_samples * 2;
+               logic.unitsize = 2;
+               logic.data = devc->convbuffer;
+               sr_session_send(sdi, &packet);
+               devc->sent_samples += new_samples;
+       } else {
+               trigger_offset = soft_trigger_logic_check(devc->stl,
+                               devc->convbuffer, new_samples * 2, &pre_trigger_samples);
+               if (trigger_offset > -1) {
+                       devc->sent_samples += pre_trigger_samples;
                        packet.type = SR_DF_LOGIC;
                        packet.payload = &logic;
+                       num_samples = new_samples - trigger_offset;
                        if (devc->limit_samples &&
-                                       new_samples > devc->limit_samples - devc->sent_samples)
-                               new_samples = devc->limit_samples - devc->sent_samples;
-                       logic.length = new_samples * 2;
+                                       num_samples > devc->limit_samples - devc->sent_samples)
+                               num_samples = devc->limit_samples - devc->sent_samples;
+                       logic.length = num_samples * 2;
                        logic.unitsize = 2;
-                       logic.data = devc->convbuffer;
-                       sr_session_send(devc->cb_data, &packet);
-                       devc->sent_samples += new_samples;
-               } else {
-                       trigger_offset = soft_trigger_logic_check(devc->stl,
-                                       devc->convbuffer, new_samples * 2, &pre_trigger_samples);
-                       if (trigger_offset > -1) {
-                               devc->sent_samples += pre_trigger_samples;
-                               packet.type = SR_DF_LOGIC;
-                               packet.payload = &logic;
-                               num_samples = new_samples - trigger_offset;
-                               if (devc->limit_samples &&
-                                               num_samples > devc->limit_samples - devc->sent_samples)
-                                       num_samples = devc->limit_samples - devc->sent_samples;
-                               logic.length = num_samples * 2;
-                               logic.unitsize = 2;
-                               logic.data = devc->convbuffer + trigger_offset * 2;
-                               sr_session_send(devc->cb_data, &packet);
-                               devc->sent_samples += num_samples;
-
-                               devc->trigger_fired = TRUE;
-                       }
-               }
+                       logic.data = devc->convbuffer + trigger_offset * 2;
+                       sr_session_send(sdi, &packet);
+                       devc->sent_samples += num_samples;
 
-               if (devc->limit_samples &&
-                               (uint64_t)devc->sent_samples >= devc->limit_samples) {
-                       devc->sent_samples = -2;
-                       free_transfer(transfer);
-                       return;
+                       devc->trigger_fired = TRUE;
                }
        }
 
+       if (devc->limit_samples &&
+                       (uint64_t)devc->sent_samples >= devc->limit_samples) {
+               devc->sent_samples = -2;
+               free_transfer(transfer);
+               return;
+       }
+
        resubmit_transfer(transfer);
 }