From: Daniel Elstner Date: Sat, 18 Jan 2014 15:08:39 +0000 (+0100) Subject: sysclk-lwla: Implement SR_CONF_LIMIT_MSEC. X-Git-Tag: libsigrok-0.3.0~245 X-Git-Url: https://sigrok.org/gitaction?a=commitdiff_plain;h=29d587670df54e6dce281e942d1da0c0ee5a74f3;p=libsigrok.git sysclk-lwla: Implement SR_CONF_LIMIT_MSEC. 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. --- diff --git a/hardware/sysclk-lwla/api.c b/hardware/sysclk-lwla/api.c index 05010275..5b9f4330 100644 --- a/hardware/sysclk-lwla/api.c +++ b/hardware/sysclk-lwla/api.c @@ -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)) { diff --git a/hardware/sysclk-lwla/protocol.c b/hardware/sysclk-lwla/protocol.c index fb629c26..7c8cc80a 100644 --- a/hardware/sysclk-lwla/protocol.c +++ b/hardware/sysclk-lwla/protocol.c @@ -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, diff --git a/hardware/sysclk-lwla/protocol.h b/hardware/sysclk-lwla/protocol.h index 21bfe729..d177836e 100644 --- a/hardware/sysclk-lwla/protocol.h +++ b/hardware/sysclk-lwla/protocol.h @@ -89,6 +89,14 @@ */ #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;