]> sigrok.org Git - libsigrok.git/commitdiff
dslogic: Add support for voltage threshold
authorDiego Asanza <redacted>
Wed, 4 May 2016 17:28:37 +0000 (19:28 +0200)
committerUwe Hermann <redacted>
Mon, 16 May 2016 16:18:58 +0000 (18:18 +0200)
The DSLogic provides two FPGA images: one for 3.3V and the other for 5V logic.
The DSLogic Pro allows to set an arbitrary voltage threshold via USB command.

This commit adds support for the DSLogic to load the FPGA image according to
an user-selectable voltage threshold.

For the DSLogic Pro, one of two fixed voltage thresholds are set, depending on
the user-selected value.

Tested with DSLogic and DSLogic Pro.

Signed-off-by: Diego Asanza <redacted>
Tested-by: Andrew Bradford <redacted>
src/hardware/fx2lafw/api.c
src/hardware/fx2lafw/dslogic.c
src/hardware/fx2lafw/dslogic.h
src/hardware/fx2lafw/protocol.h

index fe5ba9fe9b49ce49aefe6e632f0edb5c3c09d9d8..2eb5ac7ce3c6861d2b1ff79d74e76d4e6e1998a3 100644 (file)
@@ -21,6 +21,7 @@
 #include <config.h>
 #include "protocol.h"
 #include "dslogic.h"
+#include <math.h>
 
 static const struct fx2lafw_profile supported_fx2[] = {
        /*
@@ -133,6 +134,16 @@ static const uint32_t devopts[] = {
        SR_CONF_CAPTURE_RATIO | SR_CONF_GET | SR_CONF_SET,
 };
 
+static const uint32_t dslogic_devopts[] = {
+       SR_CONF_CONTINUOUS | SR_CONF_SET,
+       SR_CONF_LIMIT_SAMPLES | SR_CONF_GET | SR_CONF_SET,
+       SR_CONF_VOLTAGE_THRESHOLD | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
+       SR_CONF_CONN | SR_CONF_GET,
+       SR_CONF_SAMPLERATE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
+       SR_CONF_TRIGGER_MATCH | SR_CONF_LIST,
+       SR_CONF_CAPTURE_RATIO | SR_CONF_GET | SR_CONF_SET,
+};
+
 static const int32_t soft_trigger_matches[] = {
        SR_TRIGGER_ZERO,
        SR_TRIGGER_ONE,
@@ -141,6 +152,15 @@ static const int32_t soft_trigger_matches[] = {
        SR_TRIGGER_EDGE,
 };
 
+static const struct {
+       int range;
+       gdouble low;
+       gdouble high;
+} volt_thresholds[] = {
+       { DS_VOLTAGE_RANGE_18_33_V, 0.7,     1.4 },
+       { DS_VOLTAGE_RANGE_5_V,     1.4,     3.6 },
+};
+
 static const uint64_t samplerates[] = {
        SR_KHZ(20),
        SR_KHZ(25),
@@ -461,18 +481,19 @@ static int dev_open(struct sr_dev_inst *sdi)
 
        if (devc->dslogic) {
                if (!strcmp(devc->profile->model, "DSLogic")) {
-                       fpga_firmware = DSLOGIC_FPGA_FIRMWARE;
-               } else if (!strcmp(devc->profile->model, "DSLogic Pro")) {
+                       if (devc->dslogic_voltage_threshold == DS_VOLTAGE_RANGE_18_33_V)
+                               fpga_firmware = DSLOGIC_FPGA_FIRMWARE_3V3;
+                       else
+                               fpga_firmware = DSLOGIC_FPGA_FIRMWARE_5V;
+               } else if (!strcmp(devc->profile->model, "DSLogic Pro")){
                        fpga_firmware = DSLOGIC_PRO_FPGA_FIRMWARE;
                } else if (!strcmp(devc->profile->model, "DSCope")) {
                        fpga_firmware = DSCOPE_FPGA_FIRMWARE;
                }
 
-               if ((ret = dslogic_fpga_firmware_upload(sdi,
-                               fpga_firmware)) != SR_OK)
+               if ((ret = dslogic_fpga_firmware_upload(sdi, fpga_firmware)) != SR_OK)
                        return ret;
        }
-
        if (devc->cur_samplerate == 0) {
                /* Samplerate hasn't been set; default to the slowest one. */
                devc->cur_samplerate = devc->samplerates[0];
@@ -504,6 +525,8 @@ static int config_get(uint32_t key, GVariant **data, const struct sr_dev_inst *s
 {
        struct dev_context *devc;
        struct sr_usb_dev_inst *usb;
+       GVariant *range[2];
+       unsigned int i;
        char str[128];
 
        (void)cg;
@@ -525,6 +548,16 @@ static int config_get(uint32_t key, GVariant **data, const struct sr_dev_inst *s
                snprintf(str, 128, "%d.%d", usb->bus, usb->address);
                *data = g_variant_new_string(str);
                break;
+       case SR_CONF_VOLTAGE_THRESHOLD:
+               for (i = 0; i < ARRAY_SIZE(volt_thresholds); i++) {
+                       if (volt_thresholds[i].range != devc->dslogic_voltage_threshold)
+                               continue;
+                       range[0] = g_variant_new_double(volt_thresholds[i].low);
+                       range[1] = g_variant_new_double(volt_thresholds[i].high);
+                       *data = g_variant_new_tuple(range, 2);
+                       break;
+               }
+               break;
        case SR_CONF_LIMIT_SAMPLES:
                *data = g_variant_new_uint64(devc->limit_samples);
                break;
@@ -547,6 +580,7 @@ static int config_set(uint32_t key, GVariant *data, const struct sr_dev_inst *sd
        struct dev_context *devc;
        uint64_t arg;
        int i, ret;
+       gdouble low, high;
 
        (void)cg;
 
@@ -579,6 +613,25 @@ static int config_set(uint32_t key, GVariant *data, const struct sr_dev_inst *sd
                devc->capture_ratio = g_variant_get_uint64(data);
                ret = (devc->capture_ratio > 100) ? SR_ERR : SR_OK;
                break;
+       case SR_CONF_VOLTAGE_THRESHOLD:
+               g_variant_get(data, "(dd)", &low, &high);
+               ret = SR_ERR_ARG;
+               for (i = 0; (unsigned int)i < ARRAY_SIZE(volt_thresholds); i++) {
+                       if (fabs(volt_thresholds[i].low - low) < 0.1 &&
+                           fabs(volt_thresholds[i].high - high) < 0.1) {
+                               devc->dslogic_voltage_threshold = volt_thresholds[i].range;
+                               break;
+                       }
+               }
+               if (!strcmp(devc->profile->model, "DSLogic")) {
+                       if (devc->dslogic_voltage_threshold == DS_VOLTAGE_RANGE_5_V)
+                               ret = dslogic_fpga_firmware_upload(sdi, DSLOGIC_FPGA_FIRMWARE_5V);
+                       else
+                               ret = dslogic_fpga_firmware_upload(sdi, DSLOGIC_FPGA_FIRMWARE_3V3);
+               }else if (!strcmp(devc->profile->model, "DSLogic Pro")){
+                       ret = dslogic_fpga_firmware_upload(sdi, DSLOGIC_PRO_FPGA_FIRMWARE);
+               }
+               break;
        default:
                ret = SR_ERR_NA;
        }
@@ -590,8 +643,9 @@ static int config_list(uint32_t key, GVariant **data, const struct sr_dev_inst *
                const struct sr_channel_group *cg)
 {
        struct dev_context *devc;
-       GVariant *gvar;
+       GVariant *gvar, *range[2];
        GVariantBuilder gvb;
+       unsigned int i;
 
        (void)cg;
 
@@ -603,10 +657,29 @@ static int config_list(uint32_t key, GVariant **data, const struct sr_dev_inst *
        case SR_CONF_DEVICE_OPTIONS:
                if (!sdi)
                        *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
-                                       drvopts, ARRAY_SIZE(drvopts), sizeof(uint32_t));
-               else
-                       *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
-                                       devopts, ARRAY_SIZE(devopts), sizeof(uint32_t));
+                                                         drvopts, ARRAY_SIZE(drvopts), sizeof(uint32_t));
+               else{
+                       devc = sdi->priv;
+                       if (!devc->dslogic)
+                               *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
+                                                                 devopts, ARRAY_SIZE(devopts), sizeof(uint32_t));
+                       else
+                               *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
+                                                                 dslogic_devopts, ARRAY_SIZE(dslogic_devopts), sizeof(uint32_t));
+               }
+               break;
+       case SR_CONF_VOLTAGE_THRESHOLD:
+               if (!sdi->priv) return SR_ERR_ARG;
+               devc = sdi->priv;
+               if (!devc->dslogic) return SR_ERR_NA;
+               g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
+               for (i = 0; i < ARRAY_SIZE(volt_thresholds); i++) {
+                       range[0] = g_variant_new_double(volt_thresholds[i].low);
+                       range[1] = g_variant_new_double(volt_thresholds[i].high);
+                       gvar = g_variant_new_tuple(range, 2);
+                       g_variant_builder_add_value(&gvb, gvar);
+               }
+               *data = g_variant_builder_end(&gvb);
                break;
        case SR_CONF_SAMPLERATE:
                if (!sdi->priv)
@@ -741,7 +814,7 @@ static void LIBUSB_CALL dslogic_trigger_receive(struct libusb_transfer *transfer
        } else if (transfer->status == LIBUSB_TRANSFER_COMPLETED
                        && transfer->actual_length == sizeof(struct dslogic_trigger_pos)) {
                tpos = (struct dslogic_trigger_pos *)transfer->buffer;
-               sr_info("tpos real_pos %d ram_saddr %d", tpos->real_pos, tpos->ram_saddr);
+               sr_info("tpos real_pos %d ram_saddr %d cnt %d", tpos->real_pos, tpos->ram_saddr, tpos->remain_cnt);
                devc->trigger_pos  = tpos->real_pos;
                g_free(tpos);
                start_transfers(sdi);
@@ -766,6 +839,15 @@ static int dslogic_trigger_request(const struct sr_dev_inst *sdi)
        if ((ret = dslogic_fpga_configure(sdi)) != SR_OK)
                return ret;
 
+       /* if this is a dslogic pro, set the voltage threshold */
+       if (!strcmp(devc->profile->model, "DSLogic Pro")){
+               if(devc->dslogic_voltage_threshold == DS_VOLTAGE_RANGE_18_33_V){
+                       dslogic_set_vth(sdi, 1.4);
+               }else{
+                       dslogic_set_vth(sdi, 3.3);
+               }
+       }
+
        if ((ret = dslogic_start_acquisition(sdi)) != SR_OK)
                return ret;
 
index 0e4c5599bceb3590e1859d733a603b121419989f..afd11a7d39404a0e62dc8ba7e7d22385bb155c4f 100644 (file)
 
 #define USB_TIMEOUT (3 * 1000)
 
+SR_PRIV int dslogic_set_vth(const struct sr_dev_inst *sdi, double vth)
+{
+       struct sr_usb_dev_inst *usb;
+       usb = sdi->conn;
+       int ret;
+       uint8_t cmd;
+
+       cmd = vth/5.0 * 255;
+       /* Send the control command. */
+       ret = libusb_control_transfer(usb->devhdl, LIBUSB_REQUEST_TYPE_VENDOR |
+       LIBUSB_ENDPOINT_OUT, DS_CMD_VTH, 0x0000, 0x0000,
+               (unsigned char *)&cmd, sizeof(cmd), 3000);
+       if (ret < 0) {
+               sr_err("Unable to send VTH command: %s.",
+               libusb_error_name(ret));
+               return SR_ERR;
+       }
+
+       return SR_OK;
+}
+
 SR_PRIV int dslogic_fpga_firmware_upload(const struct sr_dev_inst *sdi,
                const char *name)
 {
@@ -329,6 +350,7 @@ SR_PRIV int dslogic_fpga_configure(const struct sr_dev_inst *sdi)
                v16 = 1 << 13;
        if (devc->dslogic_external_clock)
                v16 |= 1 << 1;
+
        WL16(&cfg.mode, v16);
        v32 = ceil(SR_MHZ(100) * 1.0 / devc->cur_samplerate);
        WL32(&cfg.divider, v32);
index e6646513c6a40c0db1d1f555227596fbad7ab737..15068ec90106ffbc9f1d2ba95d7d944abbb03cda 100644 (file)
@@ -27,6 +27,7 @@
 #define DS_CMD_START                   0xb2
 #define DS_CMD_FPGA_FW                 0xb3
 #define DS_CMD_CONFIG                  0xb4
+#define DS_CMD_VTH                             0xb8
 
 #define DS_NUM_TRIGGER_STAGES          16
 #define DS_START_FLAGS_STOP            (1 << 7)
@@ -41,6 +42,11 @@ enum dslogic_operation_modes {
        DS_OP_LOOPBACK_TEST,
 };
 
+enum  {
+           DS_VOLTAGE_RANGE_18_33_V,   /* 1.8V and 3.3V logic */
+           DS_VOLTAGE_RANGE_5_V,       /* 5V logic */
+};
+
 struct dslogic_version {
        uint8_t major;
        uint8_t minor;
@@ -130,5 +136,6 @@ SR_PRIV int dslogic_fpga_firmware_upload(const struct sr_dev_inst *sdi,
 SR_PRIV int dslogic_start_acquisition(const struct sr_dev_inst *sdi);
 SR_PRIV int dslogic_stop_acquisition(const struct sr_dev_inst *sdi);
 SR_PRIV int dslogic_fpga_configure(const struct sr_dev_inst *sdi);
+SR_PRIV int dslogic_set_vth(const struct sr_dev_inst *sdi, double vth);
 
 #endif
index 54b2f97df9b3ea980b87520c01d26a5711bb798e..955045a60c0f3423d3997fb16a6259aad9290443 100644 (file)
@@ -55,7 +55,8 @@
 #define DEV_CAPS_16BIT         (1 << DEV_CAPS_16BIT_POS)
 #define DEV_CAPS_AX_ANALOG     (1 << DEV_CAPS_AX_ANALOG_POS)
 
-#define DSLOGIC_FPGA_FIRMWARE "dreamsourcelab-dslogic-fpga.fw"
+#define DSLOGIC_FPGA_FIRMWARE_5V "dreamsourcelab-dslogic-fpga-5v.fw"
+#define DSLOGIC_FPGA_FIRMWARE_3V3 "dreamsourcelab-dslogic-fpga-3v3.fw"
 #define DSCOPE_FPGA_FIRMWARE "dreamsourcelab-dscope-fpga.fw"
 #define DSLOGIC_PRO_FPGA_FIRMWARE "dreamsourcelab-dslogic-pro-fpga.fw"
 
@@ -135,6 +136,7 @@ struct dev_context {
        uint16_t dslogic_mode;
        uint32_t trigger_pos;
        int dslogic_external_clock;
+       int dslogic_voltage_threshold;
 };
 
 SR_PRIV int fx2lafw_command_start_acquisition(const struct sr_dev_inst *sdi);