Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,9 @@ if HW_DREAMSOURCELAB_DSLOGIC
src_libdrivers_la_SOURCES += \
src/hardware/dreamsourcelab-dslogic/protocol.h \
src/hardware/dreamsourcelab-dslogic/protocol.c \
src/hardware/dreamsourcelab-dslogic/protocol_v1.c \
src/hardware/dreamsourcelab-dslogic/protocol_v2.h \
src/hardware/dreamsourcelab-dslogic/protocol_v2.c \
src/hardware/dreamsourcelab-dslogic/api.c
endif
if HW_FLUKE_45
Expand Down
2 changes: 2 additions & 0 deletions contrib/60-libsigrok.rules
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ ATTRS{idVendor}=="2a0e", ATTRS{idProduct}=="0003", ENV{ID_SIGROK}="1"
ATTRS{idVendor}=="2a0e", ATTRS{idProduct}=="0002", ENV{ID_SIGROK}="1"
# DreamSourceLab DSLogic Plus
ATTRS{idVendor}=="2a0e", ATTRS{idProduct}=="0020", ENV{ID_SIGROK}="1"
# DreamSourceLab DSLogic Plus (hardware revision)
ATTRS{idVendor}=="2a0e", ATTRS{idProduct}=="0034", ENV{ID_SIGROK}="1"
# DreamSourceLab DSLogic Basic
ATTRS{idVendor}=="2a0e", ATTRS{idProduct}=="0021", ENV{ID_SIGROK}="1"

Expand Down
38 changes: 29 additions & 9 deletions src/hardware/dreamsourcelab-dslogic/api.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,23 +26,33 @@ static const struct dslogic_profile supported_device[] = {
/* DreamSourceLab DSLogic */
{ 0x2a0e, 0x0001, "DreamSourceLab", "DSLogic", NULL,
"dreamsourcelab-dslogic-fx2.fw",
0, "DreamSourceLab", "DSLogic", 256 * 1024 * 1024},
0, "DreamSourceLab", "DSLogic", 256 * 1024 * 1024,
DSL_PROTO_V1, &dslogic_v1_ops},
/* DreamSourceLab DSCope */
{ 0x2a0e, 0x0002, "DreamSourceLab", "DSCope", NULL,
"dreamsourcelab-dscope-fx2.fw",
0, "DreamSourceLab", "DSCope", 256 * 1024 * 1024},
0, "DreamSourceLab", "DSCope", 256 * 1024 * 1024,
DSL_PROTO_V1, &dslogic_v1_ops},
/* DreamSourceLab DSLogic Pro */
{ 0x2a0e, 0x0003, "DreamSourceLab", "DSLogic Pro", NULL,
"dreamsourcelab-dslogic-pro-fx2.fw",
0, "DreamSourceLab", "DSLogic", 256 * 1024 * 1024},
0, "DreamSourceLab", "DSLogic", 256 * 1024 * 1024,
DSL_PROTO_V1, &dslogic_v1_ops},
/* DreamSourceLab DSLogic Plus */
{ 0x2a0e, 0x0020, "DreamSourceLab", "DSLogic Plus", NULL,
"dreamsourcelab-dslogic-plus-fx2.fw",
0, "DreamSourceLab", "DSLogic", 256 * 1024 * 1024},
0, "DreamSourceLab", "DSLogic", 256 * 1024 * 1024,
DSL_PROTO_V1, &dslogic_v1_ops},
/* DreamSourceLab DSLogic Plus (hardware revision, PID 0x0034) */
{ 0x2a0e, 0x0034, "DreamSourceLab", "DSLogic Plus", NULL,
"dreamsourcelab-dslogic-plus-fx2.fw",
0, "DreamSourceLab", "DSLogic", 256 * 1024 * 1024,
DSL_PROTO_V2, &dslogic_v2_ops},
/* DreamSourceLab DSLogic Basic */
{ 0x2a0e, 0x0021, "DreamSourceLab", "DSLogic Basic", NULL,
"dreamsourcelab-dslogic-basic-fx2.fw",
0, "DreamSourceLab", "DSLogic", 256 * 1024},
0, "DreamSourceLab", "DSLogic", 256 * 1024,
DSL_PROTO_V1, &dslogic_v1_ops},

ALL_ZERO
};
Expand Down Expand Up @@ -255,7 +265,8 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options)

devc->samplerates = samplerates;
devc->num_samplerates = ARRAY_SIZE(samplerates);
has_firmware = usb_match_manuf_prod(devlist[i], "DreamSourceLab", "USB-based Instrument");
has_firmware = usb_match_manuf_prod(devlist[i], "DreamSourceLab", "USB-based Instrument")
|| usb_match_manuf_prod(devlist[i], "DreamSourceLab", "USB-based DSL Instrument v2");

if (has_firmware) {
/* Already has the firmware, so fix the new address. */
Expand Down Expand Up @@ -298,6 +309,8 @@ static int dev_open(struct sr_dev_inst *sdi)
devc = sdi->priv;
usb = sdi->conn;

devc->ops = devc->profile->ops;

/*
* If the firmware was recently uploaded, wait up to MAX_RENUM_DELAY_MS
* milliseconds for the FX2 to renumerate.
Expand Down Expand Up @@ -352,8 +365,15 @@ static int dev_open(struct sr_dev_inst *sdi)
}


if ((ret = dslogic_fpga_firmware_upload(sdi)) != SR_OK)
if ((ret = devc->ops->fpga_firmware_upload(sdi)) != SR_OK)
return ret;
if ((ret = devc->ops->security_check(sdi)) != SR_OK)
return ret;
/* DSView writes VTH_ADDR right after dsl_dev_open returns
* (dslogic.c). Without this, the FPGA threshold DAC
* is uninitialised and subsequent arm-sequence status polls may
* stall. Use a sensible default (1.0V on 3.3V logic). */
(void)devc->ops->set_voltage_threshold(sdi, 1.0, 1.0);

if (devc->cur_samplerate == 0) {
/* Samplerate hasn't been set; default to the slowest one. */
Expand All @@ -362,7 +382,7 @@ static int dev_open(struct sr_dev_inst *sdi)

if (devc->cur_threshold == 0.0) {
devc->cur_threshold = thresholds[1][0];
return dslogic_set_voltage_threshold(sdi, devc->cur_threshold);
return devc->ops->set_voltage_threshold(sdi, devc->cur_threshold, devc->cur_threshold);
}

return SR_OK;
Expand Down Expand Up @@ -484,7 +504,7 @@ static int config_set(uint32_t key, GVariant *data,
return dslogic_fpga_firmware_upload(sdi);
} else {
g_variant_get(data, "(dd)", &low, &high);
return dslogic_set_voltage_threshold(sdi, (low + high) / 2.0);
return devc->ops->set_voltage_threshold(sdi, low, high);
}
break;
case SR_CONF_EXTERNAL_CLOCK:
Expand Down
97 changes: 69 additions & 28 deletions src/hardware/dreamsourcelab-dslogic/protocol.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <glib.h>
#include <glib/gstdio.h>
#include "protocol.h"
#include "protocol_v2.h"

#define DS_CMD_GET_FW_VERSION 0xb0
#define DS_CMD_GET_REVID_VERSION 0xb1
Expand Down Expand Up @@ -178,7 +179,7 @@ static int command_get_revid_version(struct sr_dev_inst *sdi, uint8_t *revid)
return SR_OK;
}

static int command_start_acquisition(const struct sr_dev_inst *sdi)
SR_PRIV int command_start_acquisition(const struct sr_dev_inst *sdi)
{
struct sr_usb_dev_inst *usb;
struct dslogic_mode mode;
Expand All @@ -199,7 +200,7 @@ static int command_start_acquisition(const struct sr_dev_inst *sdi)
return SR_OK;
}

static int command_stop_acquisition(const struct sr_dev_inst *sdi)
SR_PRIV int command_stop_acquisition(const struct sr_dev_inst *sdi)
{
struct sr_usb_dev_inst *usb;
struct dslogic_mode mode;
Expand Down Expand Up @@ -425,7 +426,7 @@ static bool set_trigger(const struct sr_dev_inst *sdi, struct fpga_config *cfg)
return num_trigger_stages != 0;
}

static int fpga_configure(const struct sr_dev_inst *sdi)
SR_PRIV int fpga_configure(const struct sr_dev_inst *sdi)
{
const struct dev_context *const devc = sdi->priv;
const struct sr_usb_dev_inst *const usb = sdi->conn;
Expand Down Expand Up @@ -601,29 +602,65 @@ SR_PRIV int dslogic_dev_open(struct sr_dev_inst *sdi, struct sr_dev_driver *di)
}
}

ret = command_get_fw_version(usb->devhdl, &vi);
if (ret != SR_OK) {
sr_err("Failed to get firmware version.");
break;
}

ret = command_get_revid_version(sdi, &revid);
if (ret != SR_OK) {
sr_err("Failed to get REVID.");
break;
}

/*
* Changes in major version mean incompatible/API changes, so
* bail out if we encounter an incompatible version.
* Different minor versions are OK, they should be compatible.
* The V1 firmware-version probe uses bRequest 0xb0, which
* collides with the V2 envelope opcode CMD_CTL_WR. Only run
* the V1 probe + version check for V1 devices.
*/
if (vi.major != DSLOGIC_REQUIRED_VERSION_MAJOR) {
sr_err("Expected firmware version %d.x, "
"got %d.%d.", DSLOGIC_REQUIRED_VERSION_MAJOR,
vi.major, vi.minor);
ret = SR_ERR;
break;
if (devc->profile->protocol_version == DSL_PROTO_V1) {
ret = command_get_fw_version(usb->devhdl, &vi);
if (ret != SR_OK) {
sr_err("Failed to get firmware version.");
break;
}

ret = command_get_revid_version(sdi, &revid);
if (ret != SR_OK) {
sr_err("Failed to get REVID.");
break;
}

/*
* Changes in major version mean incompatible/API changes,
* so bail out if we encounter an incompatible version.
* Different minor versions are OK, they should be compatible.
*/
if (vi.major != DSLOGIC_REQUIRED_VERSION_MAJOR) {
sr_err("Expected firmware version %d.x, "
"got %d.%d.", DSLOGIC_REQUIRED_VERSION_MAJOR,
vi.major, vi.minor);
ret = SR_ERR;
break;
}
} else {
/*
* V2 hello reads - DSView's hw_dev_open starts with
* DSL_CTL_FW_VERSION read (dsl.c) and dsl_dev_open
* follows with a DSL_CTL_HW_STATUS read (dsl.c).
* These appear to prime the firmware's state machine; without
* them, later HW_STATUS reads in the arm path stall. We
* don't validate the values - just perform the reads.
*/
{
uint8_t v2_fw_ver[2] = {0, 0};
uint8_t v2_hw_status = 0;
struct ctl_rd_cmd v2_rd;

v2_rd.header.dest = DSL_CTL_FW_VERSION;
v2_rd.header.offset = 0;
v2_rd.header.size = 2;
v2_rd.data = v2_fw_ver;
if (command_ctl_rd_v2(usb->devhdl, v2_rd) == SR_OK)
sr_info("V2 firmware version: %u.%u",
v2_fw_ver[0], v2_fw_ver[1]);

v2_rd.header.dest = DSL_CTL_HW_STATUS;
v2_rd.header.offset = 0;
v2_rd.header.size = 1;
v2_rd.data = &v2_hw_status;
if (command_ctl_rd_v2(usb->devhdl, v2_rd) == SR_OK)
sr_dbg("V2 HW_STATUS: 0x%02x", v2_hw_status);
}
}

sr_info("Opened device on %d.%d (logical) / %s (physical), "
Expand Down Expand Up @@ -1050,13 +1087,15 @@ SR_PRIV int dslogic_acquisition_start(const struct sr_dev_inst *sdi)

usb_source_add(sdi->session, devc->ctx, timeout, receive_data, drvc);

if ((ret = command_stop_acquisition(sdi)) != SR_OK)
/* Stop any prior acquisition, then arm and start. Matches DSView's order
* at dslogic.c (STOP -> arm -> START). */
if ((ret = devc->ops->acquisition_stop(sdi)) != SR_OK)
return ret;

if ((ret = fpga_configure(sdi)) != SR_OK)
if ((ret = devc->ops->fpga_config(sdi)) != SR_OK)
return ret;

if ((ret = command_start_acquisition(sdi)) != SR_OK)
if ((ret = devc->ops->acquisition_start(sdi)) != SR_OK)
return ret;

sr_dbg("Getting trigger.");
Expand Down Expand Up @@ -1086,7 +1125,9 @@ SR_PRIV int dslogic_acquisition_start(const struct sr_dev_inst *sdi)

SR_PRIV int dslogic_acquisition_stop(struct sr_dev_inst *sdi)
{
command_stop_acquisition(sdi);
struct dev_context *devc = sdi->priv;

devc->ops->acquisition_stop(sdi);
abort_acquisition(sdi->priv);
return SR_OK;
}
30 changes: 30 additions & 0 deletions src/hardware/dreamsourcelab-dslogic/protocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,29 @@
#include <libsigrok/libsigrok.h>
#include "libsigrok-internal.h"

struct sr_dev_inst; /* forward */

enum dslogic_protocol_version {
DSL_PROTO_V1 = 0, /* flat opcodes 0xb0-0xb8 (legacy DSLogic firmware) */
DSL_PROTO_V2 = 1, /* envelope CMD_CTL_WR/RD with ctl_header (DSView 1.3.2-era firmware) */
};

struct dslogic_protocol_ops {
int (*fpga_firmware_upload)(const struct sr_dev_inst *sdi);
int (*fpga_config)(const struct sr_dev_inst *sdi);
int (*acquisition_start)(const struct sr_dev_inst *sdi);
int (*acquisition_stop)(const struct sr_dev_inst *sdi);
int (*set_samplerate)(const struct sr_dev_inst *sdi, uint64_t rate);
int (*set_voltage_threshold)(const struct sr_dev_inst *sdi, double low, double high);
int (*set_trigger)(const struct sr_dev_inst *sdi);
int (*set_external_clock)(const struct sr_dev_inst *sdi, gboolean ext);
int (*set_clock_edge)(const struct sr_dev_inst *sdi, int edge);
int (*security_check)(const struct sr_dev_inst *sdi);
};

extern const struct dslogic_protocol_ops dslogic_v1_ops;
extern const struct dslogic_protocol_ops dslogic_v2_ops;

#define LOG_PREFIX "dreamsourcelab-dslogic"

#define USB_INTERFACE 0
Expand Down Expand Up @@ -103,10 +126,14 @@ struct dslogic_profile {

/* Memory depth in bits. */
uint64_t mem_depth;

enum dslogic_protocol_version protocol_version;
const struct dslogic_protocol_ops *ops;
};

struct dev_context {
const struct dslogic_profile *profile;
const struct dslogic_protocol_ops *ops;
/*
* Since we can't keep track of a DSLogic device after upgrading
* the firmware (it renumerates into a different device address
Expand Down Expand Up @@ -142,11 +169,14 @@ struct dev_context {
double cur_threshold;
};

SR_PRIV int fpga_configure(const struct sr_dev_inst *sdi);
SR_PRIV int dslogic_fpga_firmware_upload(const struct sr_dev_inst *sdi);
SR_PRIV int dslogic_set_voltage_threshold(const struct sr_dev_inst *sdi, double threshold);
SR_PRIV int dslogic_dev_open(struct sr_dev_inst *sdi, struct sr_dev_driver *di);
SR_PRIV struct dev_context *dslogic_dev_new(void);
SR_PRIV int dslogic_acquisition_start(const struct sr_dev_inst *sdi);
SR_PRIV int dslogic_acquisition_stop(struct sr_dev_inst *sdi);
SR_PRIV int command_start_acquisition(const struct sr_dev_inst *sdi);
SR_PRIV int command_stop_acquisition(const struct sr_dev_inst *sdi);

#endif
Loading