]> sigrok.org Git - libsigrok.git/commitdiff
Add support for mcupro Logic16, a Saleae Logic16 clone.
authorPeter Zotov <redacted>
Fri, 22 Aug 2014 18:27:56 +0000 (22:27 +0400)
committerBert Vermeulen <redacted>
Thu, 28 Aug 2014 12:03:21 +0000 (14:03 +0200)
From sigrok's point of view, this analyzer has two differences:

  * It does not require uploading the firmware.
  * It returns garbage in some registers used for sanity checks.
    Saleae's software ignores that garbage; sigrok only does if it
    specifically detects the mcupro clone.

src/hardware/saleae-logic16/protocol.c
src/hardware/saleae-logic16/protocol.h

index 26db651581f7eb0ac8288526eeab9ee817349d9c..ac53cee88866553471003c6b011de0313f8604db 100644 (file)
@@ -292,8 +292,8 @@ static int prime_fpga(const struct sr_dev_inst *sdi)
        if ((ret = read_fpga_register(sdi, 0, &version)) != SR_OK)
                return ret;
 
-       if (version != 0x10) {
-               sr_err("Invalid FPGA bitstream version: 0x%02x != 0x10.", version);
+       if (version != 0x10 && version != 0x40 && version != 0x41) {
+               sr_err("Unsupported FPGA version: 0x%02x.", version);
                return SR_ERR;
        }
 
@@ -337,53 +337,55 @@ static int upload_fpga_bitstream(const struct sr_dev_inst *sdi,
        if (devc->cur_voltage_range == vrange)
                return SR_OK;
 
-       switch (vrange) {
-       case VOLTAGE_RANGE_18_33_V:
-               filename = FPGA_FIRMWARE_18;
-               break;
-       case VOLTAGE_RANGE_5_V:
-               filename = FPGA_FIRMWARE_33;
-               break;
-       default:
-               sr_err("Unsupported voltage range.");
-               return SR_ERR;
-       }
+       if (devc->fpga_variant == FPGA_VARIANT_ORIGINAL) {
+               switch (vrange) {
+               case VOLTAGE_RANGE_18_33_V:
+                       filename = FPGA_FIRMWARE_18;
+                       break;
+               case VOLTAGE_RANGE_5_V:
+                       filename = FPGA_FIRMWARE_33;
+                       break;
+               default:
+                       sr_err("Unsupported voltage range.");
+                       return SR_ERR;
+               }
 
-       sr_info("Uploading FPGA bitstream at %s.", filename);
-       if ((fw = g_fopen(filename, "rb")) == NULL) {
-               sr_err("Unable to open bitstream file %s for reading: %s.",
-                      filename, strerror(errno));
-               return SR_ERR;
-       }
+               sr_info("Uploading FPGA bitstream at %s.", filename);
+               if ((fw = g_fopen(filename, "rb")) == NULL) {
+                       sr_err("Unable to open bitstream file %s for reading: %s.",
+                              filename, strerror(errno));
+                       return SR_ERR;
+               }
 
-       buf[0] = COMMAND_FPGA_UPLOAD_INIT;
-       if ((ret = do_ep1_command(sdi, buf, 1, NULL, 0)) != SR_OK) {
-               fclose(fw);
-               return ret;
-       }
+               buf[0] = COMMAND_FPGA_UPLOAD_INIT;
+               if ((ret = do_ep1_command(sdi, buf, 1, NULL, 0)) != SR_OK) {
+                       fclose(fw);
+                       return ret;
+               }
 
-       while (1) {
-               chunksize = fread(buf, 1, sizeof(buf), fw);
-               if (chunksize == 0)
-                       break;
+               while (1) {
+                       chunksize = fread(buf, 1, sizeof(buf), fw);
+                       if (chunksize == 0)
+                               break;
 
-               for (offset = 0; offset < chunksize; offset += 62) {
-                       len = (offset + 62 > chunksize ?
-                               chunksize - offset : 62);
-                       command[0] = COMMAND_FPGA_UPLOAD_SEND_DATA;
-                       command[1] = len;
-                       memcpy(command + 2, buf + offset, len);
-                       ret = do_ep1_command(sdi, command, len + 2, NULL, 0);
-                       if (ret != SR_OK) {
-                               fclose(fw);
-                               return ret;
+                       for (offset = 0; offset < chunksize; offset += 62) {
+                               len = (offset + 62 > chunksize ?
+                                       chunksize - offset : 62);
+                               command[0] = COMMAND_FPGA_UPLOAD_SEND_DATA;
+                               command[1] = len;
+                               memcpy(command + 2, buf + offset, len);
+                               ret = do_ep1_command(sdi, command, len + 2, NULL, 0);
+                               if (ret != SR_OK) {
+                                       fclose(fw);
+                                       return ret;
+                               }
                        }
-               }
 
-               sr_info("Uploaded %d bytes.", chunksize);
+                       sr_info("Uploaded %d bytes.", chunksize);
+               }
+               fclose(fw);
+               sr_info("FPGA bitstream upload done.");
        }
-       fclose(fw);
-       sr_info("FPGA bitstream upload done.");
 
        if ((ret = prime_fpga(sdi)) != SR_OK)
                return ret;
@@ -467,7 +469,7 @@ SR_PRIV int logic16_setup_acquisition(const struct sr_dev_inst *sdi,
        /* Ignore FIFO overflow on previous capture */
        reg1 &= ~0x20;
 
-       if (reg1 != 0x08) {
+       if (devc->fpga_variant == FPGA_VARIANT_ORIGINAL && reg1 != 0x08) {
                sr_dbg("Invalid state at acquisition setup: 0x%02x != 0x08.", reg1);
                return SR_ERR;
        }
@@ -496,7 +498,7 @@ SR_PRIV int logic16_setup_acquisition(const struct sr_dev_inst *sdi,
        if ((ret = read_fpga_register(sdi, 1, &reg1)) != SR_OK)
                return ret;
 
-       if (reg1 != 0x48) {
+       if (devc->fpga_variant == FPGA_VARIANT_ORIGINAL && reg1 != 0x48) {
                sr_dbg("Invalid state at acquisition setup: 0x%02x != 0x48.", reg1);
                return SR_ERR;
        }
@@ -504,7 +506,7 @@ SR_PRIV int logic16_setup_acquisition(const struct sr_dev_inst *sdi,
        if ((ret = read_fpga_register(sdi, 10, &reg10)) != SR_OK)
                return ret;
 
-       if (reg10 != clock_select) {
+       if (devc->fpga_variant == FPGA_VARIANT_ORIGINAL && reg10 != clock_select) {
                sr_dbg("Invalid state at acquisition setup: 0x%02x != 0x%02x.",
                       reg10, clock_select);
                return SR_ERR;
@@ -533,6 +535,9 @@ SR_PRIV int logic16_abort_acquisition(const struct sr_dev_inst *sdi)
        };
        int ret;
        uint8_t reg1, reg8, reg9;
+       struct dev_context *devc;
+
+       devc = sdi->priv;
 
        if ((ret = do_ep1_command(sdi, command, 1, NULL, 0)) != SR_OK)
                return ret;
@@ -543,7 +548,7 @@ SR_PRIV int logic16_abort_acquisition(const struct sr_dev_inst *sdi)
        if ((ret = read_fpga_register(sdi, 1, &reg1)) != SR_OK)
                return ret;
 
-       if ((reg1 & ~0x20) != 0x08) {
+       if (devc->fpga_variant == FPGA_VARIANT_ORIGINAL && (reg1 & ~0x20) != 0x08) {
                sr_dbg("Invalid state at acquisition stop: 0x%02x != 0x08.", reg1 & ~0x20);
                return SR_ERR;
        }
@@ -554,7 +559,7 @@ SR_PRIV int logic16_abort_acquisition(const struct sr_dev_inst *sdi)
        if ((ret = read_fpga_register(sdi, 9, &reg9)) != SR_OK)
                return ret;
 
-       if (reg1 & 0x20) {
+       if (devc->fpga_variant == FPGA_VARIANT_ORIGINAL && reg1 & 0x20) {
                sr_warn("FIFO overflow, capture data may be truncated.");
                return SR_ERR;
        }
@@ -564,6 +569,7 @@ SR_PRIV int logic16_abort_acquisition(const struct sr_dev_inst *sdi)
 
 SR_PRIV int logic16_init_device(const struct sr_dev_inst *sdi)
 {
+       uint8_t version;
        struct dev_context *devc;
        int ret;
 
@@ -577,6 +583,17 @@ SR_PRIV int logic16_init_device(const struct sr_dev_inst *sdi)
        if ((ret = read_eeprom(sdi, 8, 8, devc->eeprom_data)) != SR_OK)
                return ret;
 
+       /* mcupro Saleae16 has firmware pre-stored in FPGA.
+          So, we can query it right away. */
+       if (read_fpga_register(sdi, 0, &version) == SR_OK &&
+           (version == 0x40 || version == 0x41)) {
+               sr_info("mcupro Saleae16 detected.");
+               devc->fpga_variant = FPGA_VARIANT_MCUPRO;
+       } else {
+               sr_info("Original Saleae Logic16 detected.");
+               devc->fpga_variant = FPGA_VARIANT_ORIGINAL;
+       }
+
        ret = upload_fpga_bitstream(sdi, devc->selected_voltage_range);
        if (ret != SR_OK)
                return ret;
index 8a1ded823900e7ae41c194f355d1a73b5f07fb15..cdfc3681c031aa8937a64c331425ad667c44414e 100644 (file)
@@ -35,8 +35,16 @@ enum voltage_range {
        VOLTAGE_RANGE_5_V,      /* 5V logic */
 };
 
+enum fpga_variant {
+       FPGA_VARIANT_ORIGINAL,
+       FPGA_VARIANT_MCUPRO    /* mcupro clone v4.6 with Actel FPGA */
+};
+
 /** Private, per-device-instance driver context. */
 struct dev_context {
+       /** Distinguishing between original Logic16 and clones */
+       enum fpga_variant fpga_variant;
+
        /*
         * Since we can't keep track of a Logic16 device after upgrading
         * the firmware (it renumerates into a different device address