]> sigrok.org Git - libsigrok.git/commitdiff
sysclk-lwla: Implement SR_CONF_LIMIT_MSEC.
authorDaniel Elstner <redacted>
Sat, 18 Jan 2014 15:08:39 +0000 (16:08 +0100)
committerDaniel Elstner <redacted>
Sat, 18 Jan 2014 15:08:39 +0000 (16:08 +0100)
Allow the acquisition to be constrained by time in addition to
a sample count limit.  Since the LWLA protocol actually provides
only a duration natively, implement the sample count limit on top
of the new duration limit.

With this change, limiting an acquisition in external clock mode
should finally work properly.

hardware/sysclk-lwla/api.c
hardware/sysclk-lwla/protocol.c
hardware/sysclk-lwla/protocol.h

index 05010275c7db664b7652071149892c2e25cde032..5b9f4330b75682271b82eb44ff23a27a07733c1f 100644 (file)
@@ -30,6 +30,7 @@ static const int32_t hwcaps[] = {
        SR_CONF_SAMPLERATE,
        SR_CONF_EXTERNAL_CLOCK,
        SR_CONF_TRIGGER_TYPE,
+       SR_CONF_LIMIT_MSEC,
        SR_CONF_LIMIT_SAMPLES,
 };
 
@@ -254,6 +255,9 @@ static int config_get(int key, GVariant **data, const struct sr_dev_inst *sdi,
        case SR_CONF_SAMPLERATE:
                *data = g_variant_new_uint64(devc->samplerate);
                break;
+       case SR_CONF_LIMIT_MSEC:
+               *data = g_variant_new_uint64(devc->limit_msec);
+               break;
        case SR_CONF_LIMIT_SAMPLES:
                *data = g_variant_new_uint64(devc->limit_samples);
                break;
@@ -271,8 +275,8 @@ static int config_get(int key, GVariant **data, const struct sr_dev_inst *sdi,
 static int config_set(int key, GVariant *data, const struct sr_dev_inst *sdi,
                      const struct sr_probe_group *probe_group)
 {
+       uint64_t value;
        struct dev_context *devc;
-       uint64_t rate;
 
        (void)probe_group;
 
@@ -282,15 +286,24 @@ static int config_set(int key, GVariant *data, const struct sr_dev_inst *sdi,
 
        switch (key) {
        case SR_CONF_SAMPLERATE:
-               rate = g_variant_get_uint64(data);
-               sr_info("Setting samplerate %" G_GUINT64_FORMAT, rate);
-               if (rate > samplerates[0]
-                   || rate < samplerates[G_N_ELEMENTS(samplerates) - 1])
+               value = g_variant_get_uint64(data);
+               sr_info("Setting samplerate %" PRIu64, value);
+               if (value < samplerates[G_N_ELEMENTS(samplerates) - 1]
+                               || value > samplerates[0])
                        return SR_ERR_SAMPLERATE;
-               devc->samplerate = rate;
+               devc->samplerate = value;
+               break;
+       case SR_CONF_LIMIT_MSEC:
+               value = g_variant_get_uint64(data);
+               if (value > MAX_LIMIT_MSEC)
+                       return SR_ERR_ARG;
+               devc->limit_msec = value;
                break;
        case SR_CONF_LIMIT_SAMPLES:
-               devc->limit_samples = g_variant_get_uint64(data);
+               value = g_variant_get_uint64(data);
+               if (value > MAX_LIMIT_SAMPLES)
+                       return SR_ERR_ARG;
+               devc->limit_samples = value;
                break;
        case SR_CONF_EXTERNAL_CLOCK:
                if (g_variant_get_boolean(data)) {
index fb629c268a683bd2ff45e6e3c3194de3801e966c..7c8cc80a13d45c84c48abf0e7aaced164c3acc37 100644 (file)
@@ -64,11 +64,13 @@ static int submit_transfer(struct dev_context *devc,
 static int capture_setup(const struct sr_dev_inst *sdi)
 {
        struct dev_context *devc;
+       struct acquisition_state *acq;
        uint64_t divider_count;
        uint64_t memory_limit;
        uint16_t command[3 + 10*4];
 
        devc = sdi->priv;
+       acq  = devc->acquisition;
 
        command[0] = LWLA_WORD(CMD_CAP_SETUP);
        command[1] = LWLA_WORD(0); /* address */
@@ -83,9 +85,7 @@ static int capture_setup(const struct sr_dev_inst *sdi)
         * 100 MHz. At the highest samplerate of 125 MHz the clock divider
         * is bypassed.
         */
-       if (devc->cur_clock_source == CLOCK_SOURCE_INT
-                       && devc->samplerate > 0
-                       && devc->samplerate < SR_MHZ(100))
+       if (!acq->bypass_clockdiv && devc->samplerate > 0)
                divider_count = SR_MHZ(100) / devc->samplerate - 1;
        else
                divider_count = 0;
@@ -231,8 +231,7 @@ static void issue_read_start(const struct sr_dev_inst *sdi)
        acq->sample  = 0;
        acq->run_len = 0;
 
-       acq->captured_samples    = 0;
-       acq->transferred_samples = 0;
+       acq->samples_done = 0;
 
        /* For some reason, the start address is 4 rather than 0. */
        acq->mem_addr_done = 4;
@@ -348,7 +347,6 @@ static void issue_stop_capture(const struct sr_dev_inst *sdi)
 static void process_capture_status(const struct sr_dev_inst *sdi)
 {
        uint64_t duration;
-       uint64_t timescale;
        struct dev_context *devc;
        struct acquisition_state *acq;
 
@@ -371,17 +369,22 @@ static void process_capture_status(const struct sr_dev_inst *sdi)
        acq->capture_flags = LWLA_READ32(&acq->xfer_buf_in[16])
                                & STATUS_FLAG_MASK;
 
-       /* The 125 MHz setting is special, and uses the same timebase
-        * for the duration field as the 100 MHz setting.
+       /* The LWLA1034 runs at 125 MHz if the clock divider is bypassed.
+        * However, the time base used for the duration is apparently not
+        * adjusted for this "boost" mode.  Whereas normally the duration
+        * unit is 1 ms, it is 0.8 ms when the clock divider is bypassed.
+        * As 0.8 = 100 MHz / 125 MHz, it seems that the internal cycle
+        * counter period is the same as at the 100 MHz setting.
         */
-       timescale = MIN(devc->samplerate, SR_MHZ(100));
-       acq->captured_samples = duration * timescale / 1000;
+       if (acq->bypass_clockdiv)
+               acq->duration_now = duration * 4 / 5;
+       else
+               acq->duration_now = duration;
 
-       sr_spew("Captured %lu words, %" PRIu64 " samples, flags 0x%02X",
-               (unsigned long)acq->mem_addr_fill,
-               acq->captured_samples, acq->capture_flags);
+       sr_spew("Captured %zu words, %" PRIu64 " ms, flags 0x%02X",
+               acq->mem_addr_fill, acq->duration_now, acq->capture_flags);
 
-       if (acq->captured_samples >= devc->limit_samples) {
+       if (acq->duration_now >= acq->duration_max) {
                issue_stop_capture(sdi);
                return;
        }
@@ -447,7 +450,7 @@ static gboolean send_logic_packet(const struct sr_dev_inst *sdi)
        devc = sdi->priv;
        acq  = devc->acquisition;
 
-       if (acq->transferred_samples >= devc->limit_samples)
+       if (acq->samples_done >= acq->samples_max)
                return TRUE;
 
        packet.type    = SR_DF_LOGIC;
@@ -460,12 +463,12 @@ static gboolean send_logic_packet(const struct sr_dev_inst *sdi)
        last = FALSE;
 
        /* Cut the packet short if necessary. */
-       if (acq->transferred_samples + samples >= devc->limit_samples) {
-               samples = devc->limit_samples - acq->transferred_samples;
+       if (acq->samples_done + samples >= acq->samples_max) {
+               samples = acq->samples_max - acq->samples_done;
                logic.length = samples * UNIT_SIZE;
                last = TRUE;
        }
-       acq->transferred_samples += samples;
+       acq->samples_done += samples;
        acq->out_offset = 0;
 
        /* Send off logic datafeed packet. */
@@ -500,7 +503,7 @@ static int process_sample_data(const struct sr_dev_inst *sdi)
        acq  = devc->acquisition;
 
        if (acq->mem_addr_done >= acq->mem_addr_stop
-                       || acq->transferred_samples >= devc->limit_samples)
+                       || acq->samples_done >= acq->samples_max)
                return SR_OK;
 
        in_words_left = MIN(acq->mem_addr_stop - acq->mem_addr_done,
@@ -681,7 +684,7 @@ static void receive_transfer_in(struct libusb_transfer *transfer)
        case STATE_READ_RESPONSE:
                if (process_sample_data(sdi) == SR_OK
                                && acq->mem_addr_next < acq->mem_addr_stop
-                               && acq->transferred_samples < devc->limit_samples)
+                               && acq->samples_done < acq->samples_max)
                        request_read_mem(sdi);
                else
                        issue_read_end(sdi);
@@ -777,12 +780,43 @@ SR_PRIV int lwla_setup_acquisition(const struct sr_dev_inst *sdi)
 {
        struct dev_context *devc;
        struct sr_usb_dev_inst *usb;
+       struct acquisition_state *acq;
        struct regval_pair regvals[7];
        int ret;
-       gboolean bypass;
 
        devc = sdi->priv;
        usb  = sdi->conn;
+       acq  = devc->acquisition;
+
+       /* By default, run virtually unlimited. */
+       acq->duration_max = (devc->limit_msec > 0)
+               ? devc->limit_msec : MAX_LIMIT_MSEC;
+       acq->samples_max = (devc->limit_samples > 0)
+               ? devc->limit_samples : MAX_LIMIT_SAMPLES;
+
+       switch (devc->cur_clock_source) {
+       case CLOCK_SOURCE_INT:
+               if (devc->samplerate == 0)
+                       return SR_ERR_BUG;
+               /* At 125 MHz, the clock divider is bypassed. */
+               acq->bypass_clockdiv = (devc->samplerate > SR_MHZ(100));
+
+               /* If only one of the limits is set, derive the other one. */
+               if (devc->limit_msec == 0 && devc->limit_samples > 0)
+                       acq->duration_max = devc->limit_samples
+                                       * 1000 / devc->samplerate + 1;
+               else if (devc->limit_samples == 0 && devc->limit_msec > 0)
+                       acq->samples_max = devc->limit_msec
+                                       * devc->samplerate / 1000;
+               break;
+       case CLOCK_SOURCE_EXT_FALL:
+       case CLOCK_SOURCE_EXT_RISE:
+               acq->bypass_clockdiv = TRUE;
+               break;
+       default:
+               sr_err("No valid clock source has been configured.");
+               return SR_ERR;
+       }
 
        regvals[0].reg = REG_MEM_CTRL2;
        regvals[0].val = 2;
@@ -802,20 +836,8 @@ SR_PRIV int lwla_setup_acquisition(const struct sr_dev_inst *sdi)
        regvals[5].reg = REG_CMD_CTRL1;
        regvals[5].val = 0;
 
-       switch (devc->cur_clock_source) {
-       case CLOCK_SOURCE_INT:
-               bypass = (devc->samplerate > SR_MHZ(100));
-               break;
-       case CLOCK_SOURCE_EXT_FALL:
-       case CLOCK_SOURCE_EXT_RISE:
-               bypass = TRUE;
-               break;
-       default:
-               bypass = FALSE;
-               break;
-       }
        regvals[6].reg = REG_DIV_BYPASS;
-       regvals[6].val = bypass;
+       regvals[6].val = acq->bypass_clockdiv;
 
        ret = lwla_write_regs(usb, regvals, G_N_ELEMENTS(regvals));
        if (ret != SR_OK)
@@ -839,6 +861,8 @@ SR_PRIV int lwla_start_acquisition(const struct sr_dev_inst *sdi)
        usb  = sdi->conn;
        acq  = devc->acquisition;
 
+       acq->duration_now = 0;
+
        libusb_fill_bulk_transfer(acq->xfer_out, usb->devhdl, EP_COMMAND,
                                  (unsigned char *)acq->xfer_buf_out, 0,
                                  &receive_transfer_out,
index 21bfe72994629ce293328e28066f373dbd6d7d74..d177836e196ac95d9f8b246c070da15c3ee95963 100644 (file)
  */
 #define DEFAULT_SAMPLERATE     SR_MHZ(125)
 
+/** Maximum configurable sample count limit.
+ */
+#define MAX_LIMIT_SAMPLES      (UINT64_C(1) << 48)
+
+/** Maximum configurable capture duration in milliseconds.
+ */
+#define MAX_LIMIT_MSEC         (UINT64_C(1) << 32)
+
 /** LWLA clock sources.
  */
 enum clock_source {
@@ -133,10 +141,15 @@ struct acquisition_state {
        uint64_t sample;
        uint64_t run_len;
 
-       /** Number of samples acquired so far. */
-       uint64_t captured_samples;
+       /** Maximum number of samples to process. */
+       uint64_t samples_max;
        /** Number of samples sent to the session bus. */
-       uint64_t transferred_samples;
+       uint64_t samples_done;
+
+       /** Maximum duration of capture, in milliseconds. */
+       uint64_t duration_max;
+       /** Running capture duration since trigger event. */
+       uint64_t duration_now;
 
        /** Capture memory fill level. */
        size_t mem_addr_fill;
@@ -154,6 +167,9 @@ struct acquisition_state {
 
        enum rle_state rle;
 
+       /** Whether to bypass the clock divider. */
+       gboolean bypass_clockdiv;
+
        /* Payload data buffers for outgoing and incoming transfers. */
        uint16_t xfer_buf_out[MAX_ACQ_SEND_WORDS];
        uint16_t xfer_buf_in[MAX_ACQ_RECV_WORDS];
@@ -168,6 +184,9 @@ struct dev_context {
        /** The samplerate selected by the user. */
        uint64_t samplerate;
 
+       /** The maximimum sampling duration, in milliseconds. */
+       uint64_t limit_msec;
+
        /** The maximimum number of samples to acquire. */
        uint64_t limit_samples;