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 */
* 100 MHz. At the highest samplerate of 125 MHz the clock divider
* is bypassed.
*/
- if (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;
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;
devc->state = STATE_READ_PREPARE;
}
+/* Issue a command as an asynchronous USB transfer which returns the device
+ * to normal state after a read operation. Sets a new device context state
+ * on success.
+ */
static void issue_read_end(const struct sr_dev_inst *sdi)
{
struct dev_context *devc;
*/
static void process_capture_status(const struct sr_dev_inst *sdi)
{
+ uint64_t duration;
struct dev_context *devc;
struct acquisition_state *acq;
* in the FPGA. These fields are definitely less than 64 bit wide
* internally, and the unused bits occasionally even contain garbage.
*/
- acq->mem_addr_fill = LWLA_READ32(&acq->xfer_buf_in[0]);
- acq->captured_samples = LWLA_READ32(&acq->xfer_buf_in[8])
- * (uint64_t)100000;
- acq->capture_flags = LWLA_READ32(&acq->xfer_buf_in[16])
+ acq->mem_addr_fill = LWLA_READ32(&acq->xfer_buf_in[0]);
+ duration = LWLA_READ32(&acq->xfer_buf_in[8]);
+ acq->capture_flags = LWLA_READ32(&acq->xfer_buf_in[16])
& STATUS_FLAG_MASK;
- sr_spew("Captured %lu words, %" PRIu64 " samples, flags 0x%02X",
- (unsigned long)acq->mem_addr_fill,
- acq->captured_samples, acq->capture_flags);
+ /* 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.
+ */
+ if (acq->bypass_clockdiv)
+ acq->duration_now = duration * 4 / 5;
+ else
+ acq->duration_now = duration;
- if (acq->captured_samples >= devc->limit_samples) {
+ sr_spew("Captured %zu words, %" PRIu64 " ms, flags 0x%02X",
+ acq->mem_addr_fill, acq->duration_now, acq->capture_flags);
+
+ if (acq->duration_now >= acq->duration_max) {
issue_stop_capture(sdi);
return;
}
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;
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. */
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,
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);
struct dev_context *devc;
int ret;
enum clock_source selected;
+ size_t idx;
devc = sdi->priv;
selected = devc->selected_clock_source;
if (devc->cur_clock_source != selected) {
devc->cur_clock_source = CLOCK_SOURCE_NONE;
-
- if (selected >= 0 && selected < G_N_ELEMENTS(bitstream_map)) {
- ret = lwla_send_bitstream(sdi->conn,
- bitstream_map[selected]);
- if (ret == SR_OK)
- devc->cur_clock_source = selected;
- return ret;
+ idx = selected;
+ if (idx >= G_N_ELEMENTS(bitstream_map)) {
+ sr_err("Clock source (%d) out of range", selected);
+ return SR_ERR_BUG;
}
+ ret = lwla_send_bitstream(sdi->conn, bitstream_map[idx]);
+ if (ret == SR_OK)
+ devc->cur_clock_source = selected;
+ return ret;
}
return SR_OK;
}
{
struct dev_context *devc;
struct sr_usb_dev_inst *usb;
+ struct acquisition_state *acq;
struct regval_pair regvals[7];
int ret;
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;
regvals[5].val = 0;
regvals[6].reg = REG_DIV_BYPASS;
- regvals[6].val = (devc->samplerate > SR_MHZ(100)) ? 1 : 0;
+ regvals[6].val = acq->bypass_clockdiv;
ret = lwla_write_regs(usb, regvals, G_N_ELEMENTS(regvals));
if (ret != SR_OK)
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,