+ command[0] = LWLA_WORD(CMD_CAP_SETUP);
+ command[1] = LWLA_WORD(0); /* address */
+ command[2] = LWLA_WORD(10); /* length */
+
+ command[3] = LWLA_WORD_0(devc->channel_mask);
+ command[4] = LWLA_WORD_1(devc->channel_mask);
+ command[5] = LWLA_WORD_2(devc->channel_mask);
+ command[6] = LWLA_WORD_3(devc->channel_mask);
+
+ /* Set the clock divide counter maximum for samplerates of up to
+ * 100 MHz. At the highest samplerate of 125 MHz the clock divider
+ * is bypassed.
+ */
+ if (devc->samplerate > 0 && devc->samplerate < SR_MHZ(100))
+ divider_count = SR_MHZ(100) / devc->samplerate - 1;
+ else
+ divider_count = 0;
+
+ command[7] = LWLA_WORD_0(divider_count);
+ command[8] = LWLA_WORD_1(divider_count);
+ command[9] = LWLA_WORD_2(divider_count);
+ command[10] = LWLA_WORD_3(divider_count);
+
+ command[11] = LWLA_WORD_0(devc->trigger_values);
+ command[12] = LWLA_WORD_1(devc->trigger_values);
+ command[13] = LWLA_WORD_2(devc->trigger_values);
+ command[14] = LWLA_WORD_3(devc->trigger_values);
+
+ command[15] = LWLA_WORD_0(devc->trigger_edge_mask);
+ command[16] = LWLA_WORD_1(devc->trigger_edge_mask);
+ command[17] = LWLA_WORD_2(devc->trigger_edge_mask);
+ command[18] = LWLA_WORD_3(devc->trigger_edge_mask);
+
+ command[19] = LWLA_WORD_0(devc->trigger_mask);
+ command[20] = LWLA_WORD_1(devc->trigger_mask);
+ command[21] = LWLA_WORD_2(devc->trigger_mask);
+ command[22] = LWLA_WORD_3(devc->trigger_mask);
+
+ /* Set the capture memory full threshold. This is slightly less
+ * than the actual maximum, most likely in order to compensate for
+ * pipeline latency.
+ */
+ memory_limit = MEMORY_DEPTH - 16;
+
+ command[23] = LWLA_WORD_0(memory_limit);
+ command[24] = LWLA_WORD_1(memory_limit);
+ command[25] = LWLA_WORD_2(memory_limit);
+ command[26] = LWLA_WORD_3(memory_limit);
+
+ /* Fill remaining 64-bit words with zeroes. */
+ memset(&command[27], 0, 16 * sizeof(uint16_t));
+
+ return lwla_send_command(sdi->conn, command, G_N_ELEMENTS(command));
+}
+
+/* Issue a register write command as an asynchronous USB transfer.
+ */
+static int issue_write_reg(const struct sr_dev_inst *sdi,
+ unsigned int reg, unsigned int value)
+{
+ struct dev_context *devc;
+ struct acquisition_state *acq;
+
+ devc = sdi->priv;
+ acq = devc->acquisition;
+
+ acq->xfer_buf_out[0] = LWLA_WORD(CMD_WRITE_REG);
+ acq->xfer_buf_out[1] = LWLA_WORD(reg);
+ acq->xfer_buf_out[2] = LWLA_WORD_0(value);
+ acq->xfer_buf_out[3] = LWLA_WORD_1(value);
+
+ acq->xfer_out->length = 4 * sizeof(uint16_t);
+
+ return submit_transfer(devc, acq->xfer_out);
+}
+
+/* Issue a register write command as an asynchronous USB transfer for the
+ * next register/value pair of the currently active register write sequence.
+ */
+static int issue_next_write_reg(const struct sr_dev_inst *sdi)
+{
+ struct dev_context *devc;
+ struct regval_pair *regval;
+ int ret;
+
+ devc = sdi->priv;
+
+ if (devc->reg_write_pos >= devc->reg_write_len) {
+ sr_err("Already written all registers in sequence.");
+ return SR_ERR_BUG;
+ }
+ regval = &devc->reg_write_seq[devc->reg_write_pos];
+
+ ret = issue_write_reg(sdi, regval->reg, regval->val);
+ if (ret != SR_OK)
+ return ret;
+
+ ++devc->reg_write_pos;
+ return SR_OK;
+}
+
+/* Issue a capture status request as an asynchronous USB transfer.
+ */
+static void request_capture_status(const struct sr_dev_inst *sdi)
+{
+ struct dev_context *devc;
+ struct acquisition_state *acq;
+
+ devc = sdi->priv;
+ acq = devc->acquisition;
+
+ acq->xfer_buf_out[0] = LWLA_WORD(CMD_CAP_STATUS);
+ acq->xfer_buf_out[1] = LWLA_WORD(CAP_STAT_ADDR);
+ acq->xfer_buf_out[2] = LWLA_WORD(CAP_STAT_LEN);
+
+ acq->xfer_out->length = 3 * sizeof(uint16_t);
+
+ if (submit_transfer(devc, acq->xfer_out) == SR_OK)
+ devc->state = STATE_STATUS_REQUEST;
+}
+
+/* Issue a request for the capture buffer fill level as
+ * an asynchronous USB transfer.
+ */
+static void request_capture_length(const struct sr_dev_inst *sdi)
+{
+ struct dev_context *devc;
+ struct acquisition_state *acq;
+
+ devc = sdi->priv;
+ acq = devc->acquisition;
+
+ acq->xfer_buf_out[0] = LWLA_WORD(CMD_READ_REG);
+ acq->xfer_buf_out[1] = LWLA_WORD(REG_MEM_FILL);
+
+ acq->xfer_out->length = 2 * sizeof(uint16_t);
+
+ if (submit_transfer(devc, acq->xfer_out) == SR_OK)
+ devc->state = STATE_LENGTH_REQUEST;
+}
+
+/* Initiate the capture memory read operation: Reset the acquisition state
+ * and start a sequence of register writes in order to set up the device for
+ * reading from the capture buffer.
+ */
+static void issue_read_start(const struct sr_dev_inst *sdi)
+{
+ struct dev_context *devc;
+ struct acquisition_state *acq;
+ struct regval_pair *regvals;
+
+ devc = sdi->priv;
+ acq = devc->acquisition;
+
+ /* Reset RLE state. */
+ acq->rle = RLE_STATE_DATA;
+ acq->sample = 0;
+ acq->run_len = 0;
+
+ acq->captured_samples = 0;
+ acq->transferred_samples = 0;
+
+ /* For some reason, the start address is 4 rather than 0. */
+ acq->mem_addr_done = 4;
+ acq->mem_addr_next = 4;
+ acq->mem_addr_stop = acq->mem_addr_fill;
+
+ /* Byte offset into the packet output buffer. */
+ acq->out_offset = 0;
+
+ regvals = devc->reg_write_seq;
+
+ regvals[0].reg = REG_DIV_BYPASS;
+ regvals[0].val = 1;
+
+ regvals[1].reg = REG_MEM_CTRL2;
+ regvals[1].val = 2;
+
+ regvals[2].reg = REG_MEM_CTRL4;
+ regvals[2].val = 4;
+
+ devc->reg_write_pos = 0;
+ devc->reg_write_len = 3;
+
+ if (issue_next_write_reg(sdi) == SR_OK)
+ devc->state = STATE_READ_PREPARE;
+}
+
+static void issue_read_end(const struct sr_dev_inst *sdi)
+{
+ struct dev_context *devc;
+
+ devc = sdi->priv;
+
+ if (issue_write_reg(sdi, REG_DIV_BYPASS, 0) == SR_OK)
+ devc->state = STATE_READ_END;
+}
+
+/* Decode an incoming reponse to a buffer fill level request and act on it
+ * as appropriate. Note that this function changes the device context state.
+ */
+static void process_capture_length(const struct sr_dev_inst *sdi)
+{
+ struct dev_context *devc;
+ struct acquisition_state *acq;
+
+ devc = sdi->priv;
+ acq = devc->acquisition;
+
+ if (acq->xfer_in->actual_length != 4) {
+ sr_err("Received size %d doesn't match expected size 4.",
+ acq->xfer_in->actual_length);
+ devc->transfer_error = TRUE;
+ return;
+ }
+ acq->mem_addr_fill = LWLA_READ32(acq->xfer_buf_in);
+
+ sr_dbg("%lu words in capture buffer.",
+ (unsigned long)acq->mem_addr_fill);
+
+ if (acq->mem_addr_fill > 0 && sdi->status == SR_ST_ACTIVE)
+ issue_read_start(sdi);
+ else
+ issue_read_end(sdi);
+}
+
+/* Initiate a sequence of register write commands with the effect of
+ * cancelling a running capture operation. This sets a new device state
+ * if issuing the first command succeeds.
+ */
+static void issue_stop_capture(const struct sr_dev_inst *sdi)
+{
+ struct dev_context *devc;
+ struct regval_pair *regvals;
+
+ devc = sdi->priv;
+
+ if (devc->stopping_in_progress)
+ return;
+
+ regvals = devc->reg_write_seq;
+
+ regvals[0].reg = REG_CMD_CTRL2;
+ regvals[0].val = 10;
+
+ regvals[1].reg = REG_CMD_CTRL3;
+ regvals[1].val = 0;
+
+ regvals[2].reg = REG_CMD_CTRL4;
+ regvals[2].val = 0;
+
+ regvals[3].reg = REG_CMD_CTRL1;
+ regvals[3].val = 0;
+
+ regvals[4].reg = REG_DIV_BYPASS;
+ regvals[4].val = 0;
+
+ devc->reg_write_pos = 0;
+ devc->reg_write_len = 5;
+
+ if (issue_next_write_reg(sdi) == SR_OK) {
+ devc->stopping_in_progress = TRUE;
+ devc->state = STATE_STOP_CAPTURE;
+ }
+}
+
+/* Decode an incoming capture status reponse and act on it as appropriate.
+ * Note that this function changes the device state.
+ */
+static void process_capture_status(const struct sr_dev_inst *sdi)
+{
+ struct dev_context *devc;
+ struct acquisition_state *acq;
+
+ devc = sdi->priv;
+ acq = devc->acquisition;
+
+ if (acq->xfer_in->actual_length != CAP_STAT_LEN * 8) {
+ sr_err("Received size %d doesn't match expected size %d.",
+ acq->xfer_in->actual_length, CAP_STAT_LEN * 8);
+ devc->transfer_error = TRUE;
+ return;
+ }
+
+ /* TODO: Find out the actual bit width of these fields as stored
+ * 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])
+ & 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);
+
+ if (acq->captured_samples >= devc->limit_samples) {
+ issue_stop_capture(sdi);
+ return;
+ }
+ devc->state = STATE_STATUS_WAIT;
+
+ if ((acq->capture_flags & STATUS_TRIGGERED) == 0) {
+ sr_spew("Waiting for trigger.");
+ } else if ((acq->capture_flags & STATUS_MEM_AVAIL) == 0) {
+ sr_dbg("Capture memory filled.");
+ request_capture_length(sdi);
+ } else if ((acq->capture_flags & STATUS_CAPTURING) != 0) {
+ sr_spew("Sampling in progress.");
+ }
+}
+
+/* Issue a capture buffer read request as an asynchronous USB transfer.
+ * The address and size of the memory area to read are derived from the
+ * current acquisition state.
+ */
+static void request_read_mem(const struct sr_dev_inst *sdi)
+{
+ struct dev_context *devc;
+ struct acquisition_state *acq;
+ size_t count;
+
+ devc = sdi->priv;
+ acq = devc->acquisition;
+
+ if (acq->mem_addr_next >= acq->mem_addr_stop)
+ return;
+
+ /* Always read a multiple of 8 device words. */
+ count = (acq->mem_addr_stop - acq->mem_addr_next + 7) / 8 * 8;
+ count = MIN(count, READ_CHUNK_LEN);
+
+ acq->xfer_buf_out[0] = LWLA_WORD(CMD_READ_MEM);
+ acq->xfer_buf_out[1] = LWLA_WORD_0(acq->mem_addr_next);
+ acq->xfer_buf_out[2] = LWLA_WORD_1(acq->mem_addr_next);
+ acq->xfer_buf_out[3] = LWLA_WORD_0(count);
+ acq->xfer_buf_out[4] = LWLA_WORD_1(count);
+
+ acq->xfer_out->length = 5 * sizeof(uint16_t);
+
+ if (submit_transfer(devc, acq->xfer_out) == SR_OK) {
+ acq->mem_addr_next += count;
+ devc->state = STATE_READ_REQUEST;
+ }
+}
+
+/* Send a packet of logic samples to the session bus. The payload is taken
+ * from the acquisition state. The return value indicates whether to stop
+ * reading more samples.
+ */
+static gboolean send_logic_packet(const struct sr_dev_inst *sdi)
+{
+ uint64_t samples;
+ struct dev_context *devc;
+ struct acquisition_state *acq;
+ struct sr_datafeed_packet packet;
+ struct sr_datafeed_logic logic;
+ int last;
+
+ devc = sdi->priv;
+ acq = devc->acquisition;