X-Git-Url: https://sigrok.org/gitweb/?p=libsigrok.git;a=blobdiff_plain;f=src%2Fhardware%2Fsaleae-logic16%2Fprotocol.c;h=ce8db37f169c6a5b03dc495c6da3081775aeb3af;hp=785833432749f2f71f772a841699197e5d56da41;hb=HEAD;hpb=155b680da482cea2381becb73c51cfb838bff31e diff --git a/src/hardware/saleae-logic16/protocol.c b/src/hardware/saleae-logic16/protocol.c index 78583343..ce8db37f 100644 --- a/src/hardware/saleae-logic16/protocol.c +++ b/src/hardware/saleae-logic16/protocol.c @@ -19,8 +19,7 @@ * along with this program. If not, see . */ -#include "protocol.h" - +#include #include #include #include @@ -28,18 +27,15 @@ #include #include #include -#include "libsigrok.h" +#include #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) @@ -66,6 +62,101 @@ #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 */, ®0)) != SR_OK) + return ret; + + if ((ret = read_fpga_register(sdi, 7 /* No mapping */, ®7)) != 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) { - sr_err("Invalid FPGA bitstream version: 0x%02x != 0x10.", 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,64 +460,74 @@ 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; - switch (vrange) { - case VOLTAGE_RANGE_18_33_V: - filename = FPGA_FIRMWARE_18; - break; - case VOLTAGE_RANGE_5_V: - filename = 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; - } + if (devc->fpga_variant != FPGA_VARIANT_MCUPRO) { + switch (vrange) { + case VOLTAGE_RANGE_18_33_V: + name = FPGA_FIRMWARE_18; + break; + case VOLTAGE_RANGE_5_V: + name = FPGA_FIRMWARE_33; + break; + default: + sr_err("Unsupported voltage range."); + return SR_ERR; + } - buf[0] = COMMAND_FPGA_UPLOAD_INIT; - if ((ret = do_ep1_command(sdi, buf, 1, NULL, 0)) != SR_OK) { - fclose(fw); - return ret; - } + 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; - while (1) { - chunksize = fread(buf, 1, sizeof(buf), fw); - if (chunksize == 0) - break; + 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; + } - for (offset = 0; offset < chunksize; offset += 62) { - len = (offset + 62 > chunksize ? - chunksize - offset : 62); + sum = 0; + while (1) { + 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; 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); + command[1] = chunksize; + + ret = do_ep1_command(sdi, command, chunksize + 2, + NULL, 0); if (ret != SR_OK) { - fclose(fw); + sr_resource_close(drvc->sr_ctx, &bitstream); return ret; } + sum += chunksize; } - - sr_info("Uploaded %d bytes.", chunksize); + sr_resource_close(drvc->sr_ctx, &bitstream); + sr_info("FPGA bitstream upload (%" PRIu64 " bytes) done.", sum); } - fclose(fw); - sr_info("FPGA bitstream upload done."); + + /* 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; @@ -420,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; @@ -447,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; @@ -461,50 +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, ®1)) != SR_OK) + if ((ret = read_fpga_register(sdi, FPGA_REG(STATUS_CONTROL), &sta_con_reg)) != SR_OK) return ret; - if (reg1 != 0x08) { - sr_dbg("Invalid state at acquisition setup: 0x%02x != 0x08.", reg1); - return SR_ERR; + /* Ignore FIFO overflow on previous capture */ + sta_con_reg &= ~FPGA_STATUS_CONTROL(OVERFLOW); + + 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, ®1)) != SR_OK) + if ((ret = read_fpga_register(sdi, FPGA_REG(STATUS_CONTROL), &sta_con_reg)) != SR_OK) return ret; - if (reg1 != 0x48) { - sr_dbg("Invalid state at acquisition setup: 0x%02x != 0x48.", reg1); - return SR_ERR; + 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, ®10)) != SR_OK) + if ((ret = read_fpga_register(sdi, FPGA_REG(MODE), &mode_reg)) != SR_OK) return ret; - if (reg10 != clock_select) { - sr_dbg("Invalid state at acquisition setup: 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; @@ -516,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) @@ -529,33 +674,47 @@ 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; 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, ®1)) != SR_OK) + if ((ret = read_fpga_register(sdi, FPGA_REG(STATUS_CONTROL), &sta_con_reg)) != SR_OK) return ret; - if (reg1 != 0x08) { - sr_dbg("Invalid state at acquisition stop: 0x%02x != 0x08.", reg1); + 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, ®8)) != SR_OK) - return ret; - if ((ret = read_fpga_register(sdi, 9, ®9)) != SR_OK) - return ret; + if (devc->fpga_variant == FPGA_VARIANT_ORIGINAL) { + uint8_t reg8, reg9; + + if ((ret = read_fpga_register(sdi, 8, ®8)) != SR_OK) + return ret; + + if ((ret = read_fpga_register(sdi, 9, ®9)) != SR_OK) + return ret; + } + + 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; + } return SR_OK; } SR_PRIV int logic16_init_device(const struct sr_dev_inst *sdi) { + uint8_t version; struct dev_context *devc; int ret; @@ -569,6 +728,17 @@ SR_PRIV int logic16_init_device(const struct sr_dev_inst *sdi) if ((ret = read_eeprom(sdi, 8, 8, devc->eeprom_data)) != SR_OK) return ret; + /* mcupro Saleae16 has firmware pre-stored in FPGA. + So, we can query it right away. */ + 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; + } else { + sr_info("Original Saleae Logic16 detected."); + devc->fpga_variant = FPGA_VARIANT_ORIGINAL; + } + ret = upload_fpga_bitstream(sdi, devc->selected_voltage_range); if (ret != SR_OK) return ret; @@ -578,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; @@ -679,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; @@ -688,6 +854,7 @@ SR_PRIV void logic16_receive_transfer(struct libusb_transfer *transfer) struct dev_context *devc; size_t new_samples, num_samples; int trigger_offset; + int pre_trigger_samples; sdi = transfer->user_data; devc = sdi->priv; @@ -701,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: @@ -745,46 +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); - if (trigger_offset > -1) { - 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); }