]> sigrok.org Git - libsigrok.git/blobdiff - src/hardware/kingst-la2016/protocol.c
kingst-la2016: adjust register layout in acquisition configuration
[libsigrok.git] / src / hardware / kingst-la2016 / protocol.c
index 5ae79caaf13c13a5cd81823ec5a9beb5e725bcb8..8602147badc8655c8f01c5b5cce15219d479c976 100644 (file)
@@ -592,14 +592,14 @@ static int set_sample_config(const struct sr_dev_inst *sdi)
 {
        struct dev_context *devc;
        double clock_divisor;
-       uint64_t total;
-       int ret;
-       uint16_t divisor;
-       uint8_t buf[2 * sizeof(uint32_t) + 48 / 8 + sizeof(uint16_t)];
+       uint16_t divider_u16;
+       uint64_t pre_trigger_samples;
+       uint64_t pre_trigger_memory;
+       uint8_t buf[REG_TRIGGER - REG_SAMPLING]; /* Width of REG_SAMPLING. */
        uint8_t *wrptr;
+       int ret;
 
        devc = sdi->priv;
-       total = LA2016_PRE_MEM_LIMIT_BASE;
 
        if (devc->cur_samplerate > devc->max_samplerate) {
                sr_err("Too high a sample rate: %" PRIu64 ".",
@@ -608,10 +608,10 @@ static int set_sample_config(const struct sr_dev_inst *sdi)
        }
 
        clock_divisor = devc->max_samplerate / (double)devc->cur_samplerate;
-       if (clock_divisor > 0xffff)
-               clock_divisor = 0xffff;
-       divisor = (uint16_t)(clock_divisor + 0.5);
-       devc->cur_samplerate = devc->max_samplerate / divisor;
+       if (clock_divisor > 65535)
+               return SR_ERR_ARG;
+       divider_u16 = (uint16_t)(clock_divisor + 0.5);
+       devc->cur_samplerate = devc->max_samplerate / divider_u16;
 
        if (devc->limit_samples > MAX_SAMPLE_DEPTH) {
                sr_err("Too high a sample depth: %" PRIu64 ".",
@@ -619,21 +619,47 @@ static int set_sample_config(const struct sr_dev_inst *sdi)
                return SR_ERR;
        }
 
-       devc->pre_trigger_size = (devc->capture_ratio * devc->limit_samples) / 100;
+       /*
+        * The acquisition configuration communicates "pre-trigger"
+        * specs in several formats. sigrok users provide a percentage
+        * (0-100%), which translates to a pre-trigger samples count
+        * (assuming that a total samples count limit was specified).
+        * The device supports hardware compression, which depends on
+        * slowly changing input data to be effective. Fast changing
+        * input data may occupy more space in sample memory than its
+        * uncompressed form would. This is why a third parameter can
+        * limit the amount of sample memory to use for pre-trigger
+        * data. Only the upper 24 bits of that memory size spec get
+        * communicated to the device (written to its FPGA register).
+        */
+       pre_trigger_samples = devc->limit_samples * devc->capture_ratio / 100;
+       pre_trigger_memory = LA2016_PRE_MEM_LIMIT_BASE;
+       pre_trigger_memory *= devc->capture_ratio;
+       pre_trigger_memory /= 100;
 
-       sr_dbg("Set sample config: %" PRIu64 "kHz, %" PRIu64 " samples, trigger-pos %" PRIu64 "%%.",
-               devc->cur_samplerate / 1000,
-               devc->limit_samples,
-               devc->capture_ratio);
+       sr_dbg("Set sample config: %" PRIu64 "kHz, %" PRIu64 " samples.",
+               devc->cur_samplerate / 1000, devc->limit_samples);
+       sr_dbg("Capture ratio %" PRIu64 "%%, count %" PRIu64 ", mem %" PRIu64 ".",
+               devc->capture_ratio, pre_trigger_samples, pre_trigger_memory);
 
+       /*
+        * The acquisition configuration occupies a total of 16 bytes:
+        * - A 34bit total samples count limit (up to 10 billions) that
+        *   is kept in a 40bit register.
+        * - A 34bit pre-trigger samples count limit (up to 10 billions)
+        *   in another 40bit register.
+        * - A 32bit pre-trigger memory space limit (in bytes) of which
+        *   the upper 24bits are kept in an FPGA register.
+        * - A 16bit clock divider which gets applied to the maximum
+        *   samplerate of the device.
+        * - An 8bit register of unknown meaning. Currently always 0.
+        */
        wrptr = buf;
-       write_u32le_inc(&wrptr, devc->limit_samples);
+       write_u40le_inc(&wrptr, devc->limit_samples);
+       write_u40le_inc(&wrptr, pre_trigger_samples);
+       write_u24le_inc(&wrptr, pre_trigger_memory >> 8);
+       write_u16le_inc(&wrptr, divider_u16);
        write_u8_inc(&wrptr, 0);
-       write_u32le_inc(&wrptr, devc->pre_trigger_size);
-       write_u32le_inc(&wrptr, ((total * devc->capture_ratio) / 100) & 0xffffff00);
-       write_u16le_inc(&wrptr, divisor);
-       write_u8_inc(&wrptr, 0);
-
        ret = ctrl_out(sdi, CMD_FPGA_SPI, REG_SAMPLING, 0, buf, wrptr - buf);
        if (ret != SR_OK) {
                sr_err("Cannot setup acquisition configuration.");
@@ -662,14 +688,20 @@ static int set_sample_config(const struct sr_dev_inst *sdi)
  */
 static uint16_t run_state(const struct sr_dev_inst *sdi)
 {
-       uint16_t state;
-       static uint16_t previous_state = 0;
+       static uint16_t previous_state;
+
        int ret;
+       uint16_t state;
+       uint8_t buff[sizeof(state)];
+       const uint8_t *rdptr;
+       const char *label;
 
-       if ((ret = ctrl_in(sdi, CMD_FPGA_SPI, REG_RUN, 0, &state, sizeof(state))) != SR_OK) {
+       if ((ret = ctrl_in(sdi, CMD_FPGA_SPI, REG_RUN, 0, buff, sizeof(state))) != SR_OK) {
                sr_err("Cannot read run state.");
                return ret;
        }
+       rdptr = buff;
+       state = read_u16le_inc(&rdptr);
 
        /*
         * Avoid flooding the log, only dump values as they change.
@@ -677,17 +709,19 @@ static uint16_t run_state(const struct sr_dev_inst *sdi)
         */
        if (state != previous_state) {
                previous_state = state;
-               if ((state & 0x0003) == 0x01) {
-                       sr_dbg("Run state: 0x%04x (%s).", state, "idle");
-               } else if ((state & 0x000f) == 0x02) {
-                       sr_dbg("Run state: 0x%04x (%s).", state,
-                               "pre-trigger sampling");
-               } else if ((state & 0x000f) == 0x0a) {
-                       sr_dbg("Run state: 0x%04x (%s).", state,
-                               "sampling, waiting for trigger");
-               } else if ((state & 0x000f) == 0x0e) {
-                       sr_dbg("Run state: 0x%04x (%s).", state,
-                               "post-trigger sampling");
+               if ((state & 0x3) == 0x1) {
+                       label = "idle";
+               } else if ((state & 0xf) == 0x2) {
+                       label = "pre-trigger sampling";
+               } else if ((state & 0xf) == 0xa) {
+                       label = "sampling, waiting for trigger";
+               } else if ((state & 0xf) == 0xe) {
+                       label = "post-trigger sampling";
+               } else {
+                       label = NULL;
+               }
+               if (label && *label) {
+                       sr_dbg("Run state: 0x%04x (%s).", state, label);
                } else {
                        sr_dbg("Run state: 0x%04x.", state);
                }
@@ -1098,7 +1132,9 @@ SR_PRIV int la2016_init_device(const struct sr_dev_inst *sdi)
        struct dev_context *devc;
        uint16_t state;
        uint8_t buf[8];
-       int16_t purchase_date_bcd[2];
+       const uint8_t *rdptr;
+       uint8_t date_yy, date_mm;
+       uint8_t dinv_yy, dinv_mm;
        uint8_t magic;
        const char *bitstream_fn;
        int ret;
@@ -1106,20 +1142,24 @@ SR_PRIV int la2016_init_device(const struct sr_dev_inst *sdi)
        devc = sdi->priv;
 
        /*
-        * Four EEPROM bytes at offset 0x20 are purchase year and month
-        * in BCD format, with 16bit complemented checksum. For example
-        * 20 04 df fb translates to 2020-04. This can help identify the
-        * age of devices when unknown magic numbers are seen.
+        * Four EEPROM bytes at offset 0x20 are the manufacturing date,
+        * year and month in BCD format, followed by inverted values for
+        * consistency checks. For example bytes 20 04 df fb translate
+        * to 2020-04. This information can help identify the vintage of
+        * devices when unknown magic numbers are seen.
         */
-       if ((ret = ctrl_in(sdi, CMD_EEPROM, 0x20, 0, purchase_date_bcd, sizeof(purchase_date_bcd))) != SR_OK) {
-               sr_err("Cannot read purchase date in EEPROM.");
+       ret = ctrl_in(sdi, CMD_EEPROM, 0x20, 0, buf, 4 * sizeof(uint8_t));
+       if (ret != SR_OK) {
+               sr_err("Cannot read manufacture date in EEPROM.");
        } else {
-               sr_dbg("Purchase date: 20%02hx-%02hx.",
-                       (purchase_date_bcd[0]) & 0xff,
-                       (purchase_date_bcd[0] >> 8) & 0xff);
-               if (purchase_date_bcd[0] != (0x0ffff & ~purchase_date_bcd[1])) {
-                       sr_err("Purchase date fails checksum test.");
-               }
+               rdptr = &buf[0];
+               date_yy = read_u8_inc(&rdptr);
+               date_mm = read_u8_inc(&rdptr);
+               dinv_yy = read_u8_inc(&rdptr);
+               dinv_mm = read_u8_inc(&rdptr);
+               sr_info("Manufacture date: 20%02hx-%02hx.", date_yy, date_mm);
+               if ((date_mm ^ dinv_mm) != 0xff || (date_yy ^ dinv_yy) != 0xff)
+                       sr_warn("Manufacture date fails checksum test.");
        }
 
        /*
@@ -1164,17 +1204,18 @@ SR_PRIV int la2016_init_device(const struct sr_dev_inst *sdi)
                sr_err("Cannot read EEPROM device identifier bytes.");
                return ret;
        }
-
-       magic = 0;
-       if (buf[0] == (0xff & ~buf[1])) {
+       if ((buf[0] ^ buf[1]) == 0xff) {
                /* Primary copy of magic passes complement check. */
+               sr_dbg("Using primary copy of device type magic number.");
                magic = buf[0];
-       } else if (buf[4] == (0xff & ~buf[5])) {
+       } else if ((buf[4] ^ buf[5]) == 0xff) {
                /* Backup copy of magic passes complement check. */
                sr_dbg("Using backup copy of device type magic number.");
                magic = buf[4];
+       } else {
+               sr_err("Cannot find consistent device type identification.");
+               magic = 0;
        }
-
        sr_dbg("Device type: magic number is %hhu.", magic);
 
        /* Select the FPGA bitstream depending on the model. */