]> sigrok.org Git - libsigrok.git/blobdiff - hardware/sysclk-lwla/protocol.c
Add struct sr_session parameter to all session source backends.
[libsigrok.git] / hardware / sysclk-lwla / protocol.c
index b154de666bb634215fdc8f71d0cea2304d1dcb40..f1ae8b3d5d1fe1c1b146fa5d41ddb3eeb0f7ad50 100644 (file)
@@ -20,9 +20,6 @@
 #include "protocol.h"
 #include <string.h>
 
-/* Bit mask covering all 34 channels. */
-#define ALL_CHANNELS_MASK (((uint64_t)1 << NUM_PROBES) - 1)
-
 /* Bit mask for the RLE repeat-count-follows flag. */
 #define RLE_FLAG_LEN_FOLLOWS ((uint64_t)1 << 35)
 
 /* Number of 64-bit words read from the capture status memory. */
 #define CAP_STAT_LEN 5
 
-/* The bitstream filenames are indexed by the clock source enumeration.
+/* The bitstream filenames are indexed by the clock_config enumeration.
  */
-static const char *const bitstream_map[] = {
-       FIRMWARE_DIR "/sysclk-lwla1034-off.bitstream",
-       FIRMWARE_DIR "/sysclk-lwla1034-int.bitstream",
-       FIRMWARE_DIR "/sysclk-lwla1034-extpos.bitstream",
-       FIRMWARE_DIR "/sysclk-lwla1034-extneg.bitstream",
+static const char bitstream_map[][32] = {
+       "sysclk-lwla1034-off.rbf",
+       "sysclk-lwla1034-int.rbf",
+       "sysclk-lwla1034-extpos.rbf",
+       "sysclk-lwla1034-extneg.rbf",
 };
 
 /* Submit an already filled-in USB transfer.
@@ -66,6 +63,7 @@ static int capture_setup(const struct sr_dev_inst *sdi)
        struct dev_context *devc;
        struct acquisition_state *acq;
        uint64_t divider_count;
+       uint64_t trigger_mask;
        uint64_t memory_limit;
        uint16_t command[3 + 10*4];
 
@@ -105,10 +103,18 @@ static int capture_setup(const struct sr_dev_inst *sdi)
        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);
+       trigger_mask = devc->trigger_mask;
+       /* Set bits to select external TRG input edge. */
+       if (devc->cfg_trigger_source == TRIGGER_EXT_TRG)
+               switch (devc->cfg_trigger_slope) {
+               case EDGE_POSITIVE: trigger_mask |= (uint64_t)1 << 35; break; 
+               case EDGE_NEGATIVE: trigger_mask |= (uint64_t)1 << 34; break; 
+               }
+
+       command[19] = LWLA_WORD_0(trigger_mask);
+       command[20] = LWLA_WORD_1(trigger_mask);
+       command[21] = LWLA_WORD_2(trigger_mask);
+       command[22] = LWLA_WORD_3(trigger_mask);
 
        /* Set the capture memory full threshold. This is slightly less
         * than the actual maximum, most likely in order to compensate for
@@ -290,10 +296,9 @@ static void process_capture_length(const struct sr_dev_inst *sdi)
                devc->transfer_error = TRUE;
                return;
        }
-       acq->mem_addr_fill = LWLA_READ32(acq->xfer_buf_in);
+       acq->mem_addr_fill = LWLA_TO_UINT32(acq->xfer_buf_in[0]);
 
-       sr_dbg("%lu words in capture buffer.",
-              (unsigned long)acq->mem_addr_fill);
+       sr_dbg("%zu words in capture buffer.", acq->mem_addr_fill);
 
        if (acq->mem_addr_fill > 0 && sdi->status == SR_ST_ACTIVE)
                issue_read_start(sdi);
@@ -349,6 +354,8 @@ static void process_capture_status(const struct sr_dev_inst *sdi)
        uint64_t duration;
        struct dev_context *devc;
        struct acquisition_state *acq;
+       unsigned int mem_fill;
+       unsigned int flags;
 
        devc = sdi->priv;
        acq  = devc->acquisition;
@@ -364,10 +371,9 @@ static void process_capture_status(const struct sr_dev_inst *sdi)
         * 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]);
-       duration           = LWLA_READ32(&acq->xfer_buf_in[8]);
-       acq->capture_flags = LWLA_READ32(&acq->xfer_buf_in[16])
-                               & STATUS_FLAG_MASK;
+       mem_fill = LWLA_TO_UINT32(acq->xfer_buf_in[0]);
+       duration = LWLA_TO_UINT32(acq->xfer_buf_in[4]);
+       flags    = LWLA_TO_UINT32(acq->xfer_buf_in[8]) & STATUS_FLAG_MASK;
 
        /* The LWLA1034 runs at 125 MHz if the clock divider is bypassed.
         * However, the time base used for the duration is apparently not
@@ -381,10 +387,16 @@ static void process_capture_status(const struct sr_dev_inst *sdi)
        else
                acq->duration_now = duration;
 
-       sr_spew("Captured %zu words, %" PRIu64 " ms, flags 0x%02X",
-               acq->mem_addr_fill, acq->duration_now, acq->capture_flags);
+       sr_spew("Captured %u words, %" PRIu64 " ms, flags 0x%02X.",
+               mem_fill, acq->duration_now, flags);
+
+       if ((flags & STATUS_TRIGGERED) > (acq->capture_flags & STATUS_TRIGGERED))
+               sr_info("Capture triggered.");
+
+       acq->capture_flags = flags;
 
        if (acq->duration_now >= acq->duration_max) {
+               sr_dbg("Time limit reached, stopping capture.");
                issue_stop_capture(sdi);
                return;
        }
@@ -449,7 +461,7 @@ static int process_sample_data(const struct sr_dev_inst *sdi)
        struct dev_context *devc;
        struct acquisition_state *acq;
        uint8_t *out_p;
-       uint16_t *slice;
+       uint32_t *slice;
        struct sr_datafeed_packet packet;
        struct sr_datafeed_logic logic;
        size_t expect_len;
@@ -469,12 +481,12 @@ static int process_sample_data(const struct sr_dev_inst *sdi)
 
        in_words_left = MIN(acq->mem_addr_stop - acq->mem_addr_done,
                            READ_CHUNK_LEN);
-       expect_len = LWLA1034_MEMBUF_LEN(in_words_left) * sizeof(uint16_t);
+       expect_len = LWLA1034_MEMBUF_LEN(in_words_left) * sizeof(uint32_t);
        actual_len = acq->xfer_in->actual_length;
 
        if (actual_len != expect_len) {
-               sr_err("Received size %lu does not match expected size %lu.",
-                      (unsigned long)actual_len, (unsigned long)expect_len);
+               sr_err("Received size %zu does not match expected size %zu.",
+                      actual_len, expect_len);
                devc->transfer_error = TRUE;
                return SR_ERR;
        }
@@ -527,13 +539,13 @@ static int process_sample_data(const struct sr_dev_inst *sdi)
                        break; /* done with current chunk */
 
                /* Now work on the current slice. */
-               high_nibbles = LWLA_READ32(&slice[8 * 2]);
-               word = LWLA_READ32(&slice[si * 2]);
+               high_nibbles = LWLA_TO_UINT32(slice[8]);
+               word = LWLA_TO_UINT32(slice[si]);
                word |= (high_nibbles << (4 * si + 4)) & ((uint64_t)0xF << 32);
 
                if (acq->rle == RLE_STATE_DATA) {
                        acq->sample = word & ALL_CHANNELS_MASK;
-                       acq->run_len = ((word >> NUM_PROBES) & 1) + 1;
+                       acq->run_len = ((word >> NUM_CHANNELS) & 1) + 1;
                        if (word & RLE_FLAG_LEN_FOLLOWS)
                                acq->rle = RLE_STATE_LEN;
                } else {
@@ -542,10 +554,9 @@ static int process_sample_data(const struct sr_dev_inst *sdi)
                }
 
                /* Move to next word. */
-               if (++si >= 8) {
-                       si = 0;
-                       slice += 9 * 2;
-               }
+               si = (si + 1) % 8;
+               if (si == 0)
+                       slice += 9;
                --in_words_left;
        }
 
@@ -576,7 +587,7 @@ static void end_acquisition(struct sr_dev_inst *sdi)
        devc->state = STATE_IDLE;
 
        /* Remove USB file descriptors from polling. */
-       usb_source_remove(drvc->sr_ctx);
+       usb_source_remove(sdi->session, drvc->sr_ctx);
 
        packet.type = SR_DF_END;
        sr_session_send(sdi, &packet);
@@ -691,14 +702,10 @@ SR_PRIV int lwla_init_device(const struct sr_dev_inst *sdi)
 
        devc = sdi->priv;
 
-       /* Select internal clock if it hasn't been set yet */
-       if (devc->selected_clock_source == CLOCK_SOURCE_NONE)
-               devc->selected_clock_source = CLOCK_SOURCE_INT;
-
        /* Force reload of bitstream */
-       devc->cur_clock_source = CLOCK_SOURCE_NONE;
+       devc->cur_clock_config = CONF_CLOCK_NONE;
 
-       ret = lwla_set_clock_source(sdi);
+       ret = lwla_set_clock_config(sdi);
 
        if (ret != SR_OK)
                return ret;
@@ -710,50 +717,101 @@ SR_PRIV int lwla_init_device(const struct sr_dev_inst *sdi)
        ret = lwla_read_reg(sdi->conn, REG_CMD_CTRL1, &value);
        if (ret != SR_OK)
                return ret;
-       sr_info("Received test word 0x%08X back.", value);
+       sr_dbg("Received test word 0x%08X back.", value);
        if (value != 0x12345678)
                return SR_ERR;
 
        ret = lwla_read_reg(sdi->conn, REG_CMD_CTRL4, &value);
        if (ret != SR_OK)
                return ret;
-       sr_info("Received test word 0x%08X back.", value);
+       sr_dbg("Received test word 0x%08X back.", value);
        if (value != 0x12345678)
                return SR_ERR;
 
        ret = lwla_read_reg(sdi->conn, REG_CMD_CTRL3, &value);
        if (ret != SR_OK)
                return ret;
-       sr_info("Received test word 0x%08X back.", value);
+       sr_dbg("Received test word 0x%08X back.", value);
        if (value != 0x87654321)
                return SR_ERR;
 
        return ret;
 }
 
-/* Select the LWLA clock source.  If the clock source changed from the
- * previous setting, this will download a new bitstream to the FPGA.
+SR_PRIV int lwla_convert_trigger(const struct sr_dev_inst *sdi)
+{
+       struct dev_context *devc;
+       struct sr_trigger *trigger;
+       struct sr_trigger_stage *stage;
+       struct sr_trigger_match *match;
+       const GSList *l, *m;
+       uint64_t channel_index;
+
+       devc = sdi->priv;
+
+       devc->trigger_mask = 0;
+       devc->trigger_values = 0;
+       devc->trigger_edge_mask = 0;
+
+       if (!(trigger = sr_session_trigger_get(sdi->session)))
+               return SR_OK;
+
+       if (g_slist_length(trigger->stages) > 1) {
+               sr_err("This device only supports 1 trigger stage.");
+               return SR_ERR;
+       }
+
+       for (l = trigger->stages; l; l = l->next) {
+               stage = l->data;
+               for (m = stage->matches; m; m = m->next) {
+                       match = m->data;
+                       if (!match->channel->enabled)
+                               /* Ignore disabled channels with a trigger. */
+                               continue;
+                       channel_index = 1 << match->channel->index;
+                       devc->trigger_mask |= channel_index;
+                       switch (match->match) {
+                       case SR_TRIGGER_ONE:
+                               devc->trigger_values |= channel_index;
+                               break;
+                       case SR_TRIGGER_RISING:
+                               devc->trigger_values |= channel_index;
+                               /* Fall through for edge mask. */
+                       case SR_TRIGGER_FALLING:
+                               devc->trigger_edge_mask |= channel_index;
+                               break;
+                       }
+               }
+       }
+
+       return SR_OK;
+}
+
+/* Select the LWLA clock configuration.  If the clock source changed from
+ * the previous setting, this will download a new bitstream to the FPGA.
  */
-SR_PRIV int lwla_set_clock_source(const struct sr_dev_inst *sdi)
+SR_PRIV int lwla_set_clock_config(const struct sr_dev_inst *sdi)
 {
        struct dev_context *devc;
        int ret;
-       enum clock_source selected;
-       size_t idx;
+       enum clock_config choice;
 
        devc = sdi->priv;
-       selected = devc->selected_clock_source;
 
-       if (devc->cur_clock_source != selected) {
-               devc->cur_clock_source = CLOCK_SOURCE_NONE;
-               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 (sdi->status == SR_ST_INACTIVE)
+               choice = CONF_CLOCK_NONE;
+       else if (devc->cfg_clock_source == CLOCK_INTERNAL)
+               choice = CONF_CLOCK_INT;
+       else if (devc->cfg_clock_edge == EDGE_POSITIVE)
+               choice = CONF_CLOCK_EXT_RISE;
+       else
+               choice = CONF_CLOCK_EXT_FALL;
+
+       if (choice != devc->cur_clock_config) {
+               devc->cur_clock_config = CONF_CLOCK_NONE;
+               ret = lwla_send_bitstream(sdi->conn, bitstream_map[choice]);
                if (ret == SR_OK)
-                       devc->cur_clock_source = selected;
+                       devc->cur_clock_config = choice;
                return ret;
        }
        return SR_OK;
@@ -773,14 +831,23 @@ SR_PRIV int lwla_setup_acquisition(const struct sr_dev_inst *sdi)
        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->limit_msec > 0) {
+               acq->duration_max = devc->limit_msec;
+               sr_info("Acquisition time limit %" PRIu64 " ms.",
+                       devc->limit_msec);
+       } else
+               acq->duration_max = MAX_LIMIT_MSEC;
+
+       if (devc->limit_samples > 0) {
+               acq->samples_max = devc->limit_samples;
+               sr_info("Acquisition sample count limit %" PRIu64 ".",
+                       devc->limit_samples);
+       } else
+               acq->samples_max = MAX_LIMIT_SAMPLES;
+
+       if (devc->cfg_clock_source == CLOCK_INTERNAL) {
+               sr_info("Internal clock, samplerate %" PRIu64 ".",
+                       devc->samplerate);
                if (devc->samplerate == 0)
                        return SR_ERR_BUG;
                /* At 125 MHz, the clock divider is bypassed. */
@@ -793,14 +860,13 @@ SR_PRIV int lwla_setup_acquisition(const struct sr_dev_inst *sdi)
                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:
+       } else {
                acq->bypass_clockdiv = TRUE;
-               break;
-       default:
-               sr_err("No valid clock source has been configured.");
-               return SR_ERR;
+
+               if (devc->cfg_clock_edge == EDGE_NEGATIVE)
+                       sr_info("External clock, falling edge.");
+               else
+                       sr_info("External clock, rising edge.");
        }
 
        regvals[0].reg = REG_MEM_CTRL2;
@@ -846,7 +912,9 @@ SR_PRIV int lwla_start_acquisition(const struct sr_dev_inst *sdi)
        usb  = sdi->conn;
        acq  = devc->acquisition;
 
-       acq->duration_now = 0;
+       acq->duration_now  = 0;
+       acq->mem_addr_fill = 0;
+       acq->capture_flags = 0;
 
        libusb_fill_bulk_transfer(acq->xfer_out, usb->devhdl, EP_COMMAND,
                                  (unsigned char *)acq->xfer_buf_out, 0,