]> sigrok.org Git - libsigrok.git/blobdiff - src/hardware/asix-sigma/protocol.c
asix-sigma: Acquisition stop, symbolic identifiers for mode register fields
[libsigrok.git] / src / hardware / asix-sigma / protocol.c
index 98cfce7a185b1b4dd45a2940b372a04b227a5fd2..ab3342a0af0812b5b3ead235b3842e0cd2f3d5ba 100644 (file)
@@ -184,14 +184,16 @@ static int sigma_read_dram(uint16_t startchunk, size_t numchunks,
 {
        size_t i;
        uint8_t buf[4096];
-       int idx = 0;
+       int idx;
 
        /* Send the startchunk. Index start with 1. */
-       buf[0] = startchunk >> 8;
-       buf[1] = startchunk & 0xff;
-       sigma_write_register(WRITE_MEMROW, buf, 2, devc);
+       idx = 0;
+       buf[idx++] = startchunk >> 8;
+       buf[idx++] = startchunk & 0xff;
+       sigma_write_register(WRITE_MEMROW, buf, idx, devc);
 
        /* Read the DRAM. */
+       idx = 0;
        buf[idx++] = REG_DRAM_BLOCK;
        buf[idx++] = REG_DRAM_WAIT_ACK;
 
@@ -328,9 +330,10 @@ static int sigma_fpga_init_bitbang(struct dev_context *devc)
 static int sigma_fpga_init_la(struct dev_context *devc)
 {
        /* Initialize the logic analyzer mode. */
+       uint8_t mode_regval = WMR_SDRAMINIT;
        uint8_t logic_mode_start[] = {
                REG_ADDR_LOW  | (READ_ID & 0xf),
-               REG_ADDR_HIGH | (READ_ID >> 8),
+               REG_ADDR_HIGH | (READ_ID >> 4),
                REG_READ_ADDR,  /* Read ID register. */
 
                REG_ADDR_LOW | (WRITE_TEST & 0xf),
@@ -343,8 +346,8 @@ static int sigma_fpga_init_la(struct dev_context *devc)
                REG_READ_ADDR,  /* Read scratch register. */
 
                REG_ADDR_LOW | (WRITE_MODE & 0xf),
-               REG_DATA_LOW | 0x0,
-               REG_DATA_HIGH_WRITE | 0x8,
+               REG_DATA_LOW | (mode_regval & 0xf),
+               REG_DATA_HIGH_WRITE | (mode_regval >> 4),
        };
 
        uint8_t result[3];
@@ -442,10 +445,18 @@ static int upload_firmware(struct sr_context *ctx,
        unsigned char *buf;
        unsigned char pins;
        size_t buf_size;
-       const char *firmware = sigma_firmware_files[firmware_idx];
-       struct ftdi_context *ftdic = &devc->ftdic;
+       const char *firmware;
+       struct ftdi_context *ftdic;
+
+       /* Avoid downloading the same firmware multiple times. */
+       firmware = sigma_firmware_files[firmware_idx];
+       if (devc->cur_firmware == firmware_idx) {
+               sr_info("Not uploading firmware file '%s' again.", firmware);
+               return SR_OK;
+       }
 
        /* Make sure it's an ASIX SIGMA. */
+       ftdic = &devc->ftdic;
        ret = ftdi_usb_open_desc(ftdic, USB_VENDOR, USB_PRODUCT,
                                 USB_DESCRIPTION, NULL);
        if (ret < 0) {
@@ -938,12 +949,18 @@ static int decode_chunk_ts(struct sigma_dram_line *dram_line,
                           struct sr_dev_inst *sdi)
 {
        struct sigma_dram_cluster *dram_cluster;
-       struct dev_context *devc = sdi->priv;
-       unsigned int clusters_in_line =
-               (events_in_line + (EVENTS_PER_CLUSTER - 1)) / EVENTS_PER_CLUSTER;
+       struct dev_context *devc;
+       unsigned int clusters_in_line;
        unsigned int events_in_cluster;
        unsigned int i;
-       uint32_t trigger_cluster = ~0, triggered = 0;
+       uint32_t trigger_cluster, triggered;
+
+       devc = sdi->priv;
+       clusters_in_line = events_in_line;
+       clusters_in_line += EVENTS_PER_CLUSTER - 1;
+       clusters_in_line /= EVENTS_PER_CLUSTER;
+       trigger_cluster = ~0;
+       triggered = 0;
 
        /* Check if trigger is in this chunk. */
        if (trigger_event < (64 * 7)) {
@@ -978,17 +995,22 @@ static int decode_chunk_ts(struct sigma_dram_line *dram_line,
 
 static int download_capture(struct sr_dev_inst *sdi)
 {
-       struct dev_context *devc = sdi->priv;
        const uint32_t chunks_per_read = 32;
+
+       struct dev_context *devc;
        struct sigma_dram_line *dram_line;
        int bufsz;
        uint32_t stoppos, triggerpos;
        uint8_t modestatus;
-
        uint32_t i;
        uint32_t dl_lines_total, dl_lines_curr, dl_lines_done;
-       uint32_t dl_events_in_line = 64 * 7;
-       uint32_t trg_line = ~0, trg_event = ~0;
+       uint32_t dl_events_in_line;
+       uint32_t trg_line, trg_event;
+
+       devc = sdi->priv;
+       dl_events_in_line = 64 * 7;
+       trg_line = ~0;
+       trg_event = ~0;
 
        dram_line = g_try_malloc0(chunks_per_read * sizeof(*dram_line));
        if (!dram_line)
@@ -996,18 +1018,26 @@ static int download_capture(struct sr_dev_inst *sdi)
 
        sr_info("Downloading sample data.");
 
-       /* Stop acquisition. */
-       sigma_set_register(WRITE_MODE, 0x11, devc);
+       /*
+        * Ask the hardware to stop data acquisition. Reception of the
+        * FORCESTOP request makes the hardware "disable RLE" (store
+        * clusters to DRAM regardless of whether pin state changes) and
+        * raise the POSTTRIGGERED flag.
+        */
+       sigma_set_register(WRITE_MODE, WMR_FORCESTOP | WMR_SDRAMWRITEEN, devc);
+       do {
+               modestatus = sigma_get_register(READ_MODE, devc);
+       } while (!(modestatus & RMR_POSTTRIGGERED));
 
        /* Set SDRAM Read Enable. */
-       sigma_set_register(WRITE_MODE, 0x02, devc);
+       sigma_set_register(WRITE_MODE, WMR_SDRAMREADEN, devc);
 
        /* Get the current position. */
        sigma_read_pos(&stoppos, &triggerpos, devc);
 
        /* Check if trigger has fired. */
        modestatus = sigma_get_register(READ_MODE, devc);
-       if (modestatus & 0x20) {
+       if (modestatus & RMR_TRIGGERED) {
                trg_line = triggerpos >> 9;
                trg_event = triggerpos & 0x1ff;
        }
@@ -1072,13 +1102,13 @@ static int download_capture(struct sr_dev_inst *sdi)
  */
 static int sigma_capture_mode(struct sr_dev_inst *sdi)
 {
-       struct dev_context *devc = sdi->priv;
-
+       struct dev_context *devc;
        uint64_t running_msec;
        struct timeval tv;
-
        uint32_t stoppos, triggerpos;
 
+       devc = sdi->priv;
+
        /* Check if the selected sampling duration passed. */
        gettimeofday(&tv, 0);
        running_msec = (tv.tv_sec - devc->start_tv.tv_sec) * 1000 +