]> sigrok.org Git - libsigrok.git/blobdiff - src/hardware/dreamsourcelab-dslogic/protocol.c
output/csv: use intermediate time_t var, silence compiler warning
[libsigrok.git] / src / hardware / dreamsourcelab-dslogic / protocol.c
index 43280cc56333e44586ebaee608e8cf07cca6783b..bb98d61a4b4f467f4eafa5cfb5d487b6a20f79ac 100644 (file)
@@ -20,6 +20,7 @@
 
 #include <config.h>
 #include <math.h>
+#include <stdbool.h>
 #include <glib.h>
 #include <glib/gstdio.h>
 #include "protocol.h"
@@ -98,7 +99,7 @@ struct cmd_start_acquisition {
        uint8_t sample_delay_l;
 };
 
-struct dslogic_fpga_config {
+struct fpga_config {
        uint32_t sync;
 
        uint16_t mode_header;
@@ -336,9 +337,9 @@ static uint16_t enabled_channel_mask(const struct sr_dev_inst *sdi)
 /*
  * Get the session trigger and configure the FPGA structure
  * accordingly.
+ * @return @c true if any triggers are enabled, @c false otherwise.
  */
-static void set_trigger(const struct sr_dev_inst *sdi,
-       struct dslogic_fpga_config *cfg)
+static bool set_trigger(const struct sr_dev_inst *sdi, struct fpga_config *cfg)
 {
        struct sr_trigger *trigger;
        struct sr_trigger_stage *stage;
@@ -355,23 +356,7 @@ static void set_trigger(const struct sr_dev_inst *sdi,
 
        cfg->ch_en = enabled_channel_mask(sdi);
 
-       cfg->trig_mask0[0] = 0xffff;
-       cfg->trig_mask1[0] = 0xffff;
-
-       cfg->trig_value0[0] = 0;
-       cfg->trig_value1[0] = 0;
-
-       cfg->trig_edge0[0] = 0;
-       cfg->trig_edge1[0] = 0;
-
-       cfg->trig_logic0[0] = 2;
-       cfg->trig_logic1[0] = 2;
-
-       cfg->trig_count[0] = 0;
-
-       cfg->trig_glb = num_enabled_channels << 4;
-
-       for (i = 1; i < NUM_TRIGGER_STAGES; i++) {
+       for (i = 0; i < NUM_TRIGGER_STAGES; i++) {
                cfg->trig_mask0[i] = 0xffff;
                cfg->trig_mask1[i] = 0xffff;
                cfg->trig_value0[i] = 0;
@@ -395,7 +380,7 @@ static void set_trigger(const struct sr_dev_inst *sdi,
 
        if (!(trigger = sr_session_trigger_get(sdi->session))) {
                sr_dbg("No session trigger found");
-               return;
+               return false;
        }
 
        for (l = trigger->stages; l; l = l->next) {
@@ -435,24 +420,23 @@ static void set_trigger(const struct sr_dev_inst *sdi,
                }
        }
 
-       cfg->trig_glb |= num_trigger_stages;
+       cfg->trig_glb = (num_enabled_channels << 4) | (num_trigger_stages - 1);
+
+       return num_trigger_stages != 0;
 }
 
 static int fpga_configure(const struct sr_dev_inst *sdi)
 {
-       struct dev_context *devc;
-       struct sr_usb_dev_inst *usb;
+       const struct dev_context *const devc = sdi->priv;
+       const struct sr_usb_dev_inst *const usb = sdi->conn;
        uint8_t c[3];
-       struct dslogic_fpga_config cfg;
-       uint16_t v16;
-       uint32_t v32;
+       struct fpga_config cfg;
+       uint16_t mode = 0;
+       uint32_t divider;
        int transferred, len, ret;
 
        sr_dbg("Configuring FPGA.");
 
-       usb = sdi->conn;
-       devc = sdi->priv;
-
        WL32(&cfg.sync, DS_CFG_START);
        WL16(&cfg.mode_header, DS_CFG_MODE);
        WL16(&cfg.divider_header, DS_CFG_DIVIDER);
@@ -464,7 +448,7 @@ static int fpga_configure(const struct sr_dev_inst *sdi)
        WL32(&cfg.end_sync, DS_CFG_END);
 
        /* Pass in the length of a fixed-size struct. Really. */
-       len = sizeof(struct dslogic_fpga_config) / 2;
+       len = sizeof(struct fpga_config) / 2;
        c[0] = len & 0xff;
        c[1] = (len >> 8) & 0xff;
        c[2] = (len >> 16) & 0xff;
@@ -478,26 +462,27 @@ static int fpga_configure(const struct sr_dev_inst *sdi)
                return SR_ERR;
        }
 
-       v16 = 0x0000;
+       if (set_trigger(sdi, &cfg))
+               mode |= DS_MODE_TRIG_EN;
 
        if (devc->mode == DS_OP_INTERNAL_TEST)
-               v16 = DS_MODE_INT_TEST;
+               mode |= DS_MODE_INT_TEST;
        else if (devc->mode == DS_OP_EXTERNAL_TEST)
-               v16 = DS_MODE_EXT_TEST;
+               mode |= DS_MODE_EXT_TEST;
        else if (devc->mode == DS_OP_LOOPBACK_TEST)
-               v16 = DS_MODE_LPB_TEST;
+               mode |= DS_MODE_LPB_TEST;
 
        if (devc->cur_samplerate == DS_MAX_LOGIC_SAMPLERATE * 2)
-               v16 |= DS_MODE_HALF_MODE;
+               mode |= DS_MODE_HALF_MODE;
        else if (devc->cur_samplerate == DS_MAX_LOGIC_SAMPLERATE * 4)
-               v16 |= DS_MODE_QUAR_MODE;
+               mode |= DS_MODE_QUAR_MODE;
 
        if (devc->continuous_mode)
-               v16 |= DS_MODE_STREAM_MODE;
+               mode |= DS_MODE_STREAM_MODE;
        if (devc->external_clock) {
-               v16 |= DS_MODE_CLK_TYPE;
+               mode |= DS_MODE_CLK_TYPE;
                if (devc->clock_edge == DS_EDGE_FALLING)
-                       v16 |= DS_MODE_CLK_EDGE;
+                       mode |= DS_MODE_CLK_EDGE;
        }
        if (devc->limit_samples > DS_MAX_LOGIC_DEPTH *
                ceil(devc->cur_samplerate * 1.0 / DS_MAX_LOGIC_SAMPLERATE)
@@ -505,19 +490,17 @@ static int fpga_configure(const struct sr_dev_inst *sdi)
                /* Enable RLE for long captures.
                 * Without this, captured data present errors.
                 */
-               v16 |= DS_MODE_RLE_MODE;
+               mode |= DS_MODE_RLE_MODE;
        }
 
-       WL16(&cfg.mode, v16);
-       v32 = ceil(DS_MAX_LOGIC_SAMPLERATE * 1.0 / devc->cur_samplerate);
-       WL32(&cfg.divider, v32);
+       WL16(&cfg.mode, mode);
+       divider = ceil(DS_MAX_LOGIC_SAMPLERATE * 1.0 / devc->cur_samplerate);
+       WL32(&cfg.divider, divider);
 
        /* Number of 16-sample units. */
        WL32(&cfg.count, devc->limit_samples / 16);
 
-       set_trigger(sdi, &cfg);
-
-       len = sizeof(struct dslogic_fpga_config);
+       len = sizeof(struct fpga_config);
        ret = libusb_bulk_transfer(usb->devhdl, 2 | LIBUSB_ENDPOINT_OUT,
                        (unsigned char *)&cfg, len, &transferred, USB_TIMEOUT);
        if (ret < 0 || transferred != len) {
@@ -560,7 +543,7 @@ SR_PRIV int dslogic_dev_open(struct sr_dev_inst *sdi, struct sr_dev_driver *di)
        struct dev_context *devc;
        struct drv_context *drvc;
        struct version_info vi;
-       int ret, i, device_count;
+       int ret = SR_ERR, i, device_count;
        uint8_t revid;
        char connection_id[64];
 
@@ -584,10 +567,10 @@ SR_PRIV int dslogic_dev_open(struct sr_dev_inst *sdi, struct sr_dev_driver *di)
 
                if ((sdi->status == SR_ST_INITIALIZING) ||
                                (sdi->status == SR_ST_INACTIVE)) {
-                       /*
-                        * Check device by its physical USB bus/port address.
-                        */
-                       usb_get_port_path(devlist[i], connection_id, sizeof(connection_id));
+                       /* Check device by its physical USB bus/port address. */
+                       if (usb_get_port_path(devlist[i], connection_id, sizeof(connection_id)) < 0)
+                               continue;
+
                        if (strcmp(sdi->connection_id, connection_id))
                                /* This is not the one. */
                                continue;
@@ -603,6 +586,7 @@ SR_PRIV int dslogic_dev_open(struct sr_dev_inst *sdi, struct sr_dev_driver *di)
                } else {
                        sr_err("Failed to open device: %s.",
                               libusb_error_name(ret));
+                       ret = SR_ERR;
                        break;
                }
 
@@ -611,7 +595,8 @@ SR_PRIV int dslogic_dev_open(struct sr_dev_inst *sdi, struct sr_dev_driver *di)
                                if ((ret = libusb_detach_kernel_driver(usb->devhdl, USB_INTERFACE)) < 0) {
                                        sr_err("Failed to detach kernel driver: %s.",
                                                libusb_error_name(ret));
-                                       return SR_ERR;
+                                       ret = SR_ERR;
+                                       break;
                                }
                        }
                }
@@ -637,10 +622,10 @@ SR_PRIV int dslogic_dev_open(struct sr_dev_inst *sdi, struct sr_dev_driver *di)
                        sr_err("Expected firmware version %d.x, "
                               "got %d.%d.", DSLOGIC_REQUIRED_VERSION_MAJOR,
                               vi.major, vi.minor);
+                       ret = SR_ERR;
                        break;
                }
 
-               sdi->status = SR_ST_ACTIVE;
                sr_info("Opened device on %d.%d (logical) / %s (physical), "
                        "interface %d, firmware %d.%d.",
                        usb->bus, usb->address, connection_id,
@@ -649,14 +634,14 @@ SR_PRIV int dslogic_dev_open(struct sr_dev_inst *sdi, struct sr_dev_driver *di)
                sr_info("Detected REVID=%d, it's a Cypress CY7C68013%s.",
                        revid, (revid != 1) ? " (FX2)" : "A (FX2LP)");
 
+               ret = SR_OK;
+
                break;
        }
-       libusb_free_device_list(devlist, 1);
 
-       if (sdi->status != SR_ST_ACTIVE)
-               return SR_ERR;
+       libusb_free_device_list(devlist, 1);
 
-       return SR_OK;
+       return ret;
 }
 
 SR_PRIV struct dev_context *dslogic_dev_new(void)
@@ -750,10 +735,12 @@ static void deinterleave_buffer(const uint8_t *src, size_t length,
                for (int bit = 0; bit != 64; bit++) {
                        const uint64_t *word_ptr = src_ptr;
                        sample = 0;
-                       for (size_t channel = 0; channel != channel_count;
+                       for (unsigned int channel = 0; channel != 16;
                                channel++) {
-                               if ((channel_mask & (1 << channel)) &&
-                                       (*word_ptr++ & (1ULL << bit)))
+                               const uint16_t m = channel_mask >> channel;
+                               if (!m)
+                                       break;
+                               if ((m & 1) && ((*word_ptr++ >> bit) & UINT64_C(1)))
                                        sample |= 1 << channel;
                        }
                        *dst_ptr++ = sample;
@@ -789,7 +776,6 @@ static void LIBUSB_CALL receive_transfer(struct libusb_transfer *transfer)
                (DSLOGIC_ATOMIC_BYTES * channel_count);
 
        gboolean packet_has_error = FALSE;
-       struct sr_datafeed_packet packet;
        unsigned int num_samples;
        int trigger_offset;
 
@@ -869,9 +855,7 @@ static void LIBUSB_CALL receive_transfer(struct libusb_transfer *transfer)
                        devc->sent_samples += trigger_offset;
                        /* Trigger position. */
                        devc->trigger_pos = 0;
-                       packet.type = SR_DF_TRIGGER;
-                       packet.payload = NULL;
-                       sr_session_send(sdi, &packet);
+                       std_session_send_df_trigger(sdi);
                        /* Post trigger samples. */
                        num_samples -= trigger_offset;
                        send_data(sdi, devc->deinterleave_buffer
@@ -929,6 +913,8 @@ static size_t get_buffer_size(const struct sr_dev_inst *sdi)
         */
        const size_t block_size = enabled_channel_count(sdi) * 512;
        const size_t s = 10 * to_bytes_per_ms(sdi);
+       if (!block_size)
+               return s;
        return ((s + block_size - 1) / block_size) * block_size;
 }
 
@@ -1031,8 +1017,8 @@ static void LIBUSB_CALL 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 cnt %d", tpos->real_pos,
-                       tpos->ram_saddr, tpos->remain_cnt);
+               sr_info("tpos real_pos %d ram_saddr %d cnt_h %d cnt_l %d", tpos->real_pos,
+                       tpos->ram_saddr, tpos->remain_cnt_h, tpos->remain_cnt_l);
                devc->trigger_pos = tpos->real_pos;
                g_free(tpos);
                start_transfers(sdi);