]> sigrok.org Git - libsigrok.git/blobdiff - src/hardware/kingst-la2016/protocol.c
kingst-la2016: complete hardware setup in probe, set features in open
[libsigrok.git] / src / hardware / kingst-la2016 / protocol.c
index 102c5cc4b5da87ff16e44c69d13819d9453730fe..9ecaa7180961d4c18299705a4916c7a8b23ba24a 100644 (file)
@@ -615,7 +615,7 @@ static int set_trigger_config(const struct sr_dev_inst *sdi)
 static int set_sample_config(const struct sr_dev_inst *sdi)
 {
        struct dev_context *devc;
-       double clock_divisor;
+       uint64_t min_samplerate, eff_samplerate;
        uint16_t divider_u16;
        uint64_t limit_samples;
        uint64_t pre_trigger_samples;
@@ -631,17 +631,15 @@ static int set_sample_config(const struct sr_dev_inst *sdi)
                        devc->cur_samplerate);
                return SR_ERR_ARG;
        }
-       if (devc->cur_samplerate < MIN_SAMPLE_RATE_LA2016) {
+       min_samplerate = devc->model->samplerate;
+       min_samplerate /= 65536;
+       if (devc->cur_samplerate < min_samplerate) {
                sr_err("Too low a sample rate: %" PRIu64 ".",
                        devc->cur_samplerate);
                return SR_ERR_ARG;
        }
-
-       clock_divisor = devc->model->samplerate / (double)devc->cur_samplerate;
-       if (clock_divisor > 65535)
-               return SR_ERR_ARG;
-       divider_u16 = (uint16_t)(clock_divisor + 0.5);
-       devc->cur_samplerate = devc->model->samplerate / divider_u16;
+       divider_u16 = devc->model->samplerate / devc->cur_samplerate;
+       eff_samplerate = devc->model->samplerate / divider_u16;
 
        ret = sr_sw_limits_get_remain(&devc->sw_limits,
                &limit_samples, NULL, NULL, NULL);
@@ -650,12 +648,14 @@ static int set_sample_config(const struct sr_dev_inst *sdi)
                return ret;
        }
        if (limit_samples > LA2016_NUM_SAMPLES_MAX) {
-               sr_err("Too high a sample depth: %" PRIu64 ".", limit_samples);
-               return SR_ERR_ARG;
+               sr_warn("Too high a sample depth: %" PRIu64 ", capping.",
+                       limit_samples);
+               limit_samples = LA2016_NUM_SAMPLES_MAX;
        }
-       if (limit_samples < LA2016_NUM_SAMPLES_MIN) {
-               sr_err("Too low a sample depth: %" PRIu64 ".", limit_samples);
-               return SR_ERR_ARG;
+       if (limit_samples == 0) {
+               limit_samples = LA2016_NUM_SAMPLES_MAX;
+               sr_dbg("Passing %" PRIu64 " to HW for unlimited samples.",
+                       limit_samples);
        }
 
        /*
@@ -670,23 +670,36 @@ static int set_sample_config(const struct sr_dev_inst *sdi)
         * 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).
+        *
+        * TODO Determine whether the pre-trigger memory size gets
+        * specified in samples or in bytes. A previous implementation
+        * suggests bytes but this is suspicious when every other spec
+        * is in terms of samples.
         */
-       pre_trigger_samples = limit_samples * devc->capture_ratio / 100;
-       pre_trigger_memory = LA2016_PRE_MEM_LIMIT_BASE;
-       pre_trigger_memory *= devc->capture_ratio;
-       pre_trigger_memory /= 100;
+       if (devc->trigger_involved) {
+               pre_trigger_samples = limit_samples;
+               pre_trigger_samples *= devc->capture_ratio;
+               pre_trigger_samples /= 100;
+               pre_trigger_memory = devc->model->memory_bits;
+               pre_trigger_memory *= UINT64_C(1024 * 1024 * 1024);
+               pre_trigger_memory /= 8; /* devc->model->channel_count ? */
+               pre_trigger_memory *= devc->capture_ratio;
+               pre_trigger_memory /= 100;
+       } else {
+               sr_dbg("No trigger setup, skipping pre-trigger config.");
+               pre_trigger_samples = 1;
+               pre_trigger_memory = 0;
+       }
+       /* Ensure non-zero value after LSB shift out in HW reg. */
+       if (pre_trigger_memory < 0x100) {
+               pre_trigger_memory = 0x100;
+       }
 
        sr_dbg("Set sample config: %" PRIu64 "kHz, %" PRIu64 " samples.",
-               devc->cur_samplerate / 1000, limit_samples);
+               eff_samplerate / SR_KHZ(1), limit_samples);
        sr_dbg("Capture ratio %" PRIu64 "%%, count %" PRIu64 ", mem %" PRIu64 ".",
                devc->capture_ratio, pre_trigger_samples, pre_trigger_memory);
 
-       if (!devc->trigger_involved) {
-               sr_dbg("Voiding pre-trigger setup. No trigger involved.");
-               pre_trigger_samples = 1;
-               pre_trigger_memory = 0x100;
-       }
-
        /*
         * The acquisition configuration occupies a total of 16 bytes:
         * - A 34bit total samples count limit (up to 10 billions) that
@@ -1225,6 +1238,7 @@ SR_PRIV int la2016_identify_device(const struct sr_dev_inst *sdi,
 {
        struct dev_context *devc;
        uint8_t buf[8];
+       size_t rdoff, rdlen;
        const uint8_t *rdptr;
        uint8_t date_yy, date_mm;
        uint8_t dinv_yy, dinv_mm;
@@ -1242,13 +1256,23 @@ SR_PRIV int la2016_identify_device(const struct sr_dev_inst *sdi,
         * to 2020-04. This information can help identify the vintage of
         * devices when unknown magic numbers are seen.
         */
-       ret = ctrl_in(sdi, CMD_EEPROM, 0x20, 0, buf, 4 * sizeof(uint8_t));
+       rdoff = 0x20;
+       rdlen = 4 * sizeof(uint8_t);
+       ret = ctrl_in(sdi, CMD_EEPROM, rdoff, 0, buf, rdlen);
        if (ret != SR_OK && !show_message) {
+               /* Non-fatal weak attempt during probe. Not worth logging. */
                sr_dbg("Cannot access EEPROM.");
                return SR_ERR_IO;
        } else if (ret != SR_OK) {
+               /* Failed attempt in regular use. Non-fatal. Worth logging. */
                sr_err("Cannot read manufacture date in EEPROM.");
        } else {
+               if (sr_log_loglevel_get() >= SR_LOG_SPEW) {
+                       GString *txt;
+                       txt = sr_hexdump_new(buf, rdlen);
+                       sr_spew("Manufacture date bytes %s.", txt->str);
+                       sr_hexdump_free(txt);
+               }
                rdptr = &buf[0];
                date_yy = read_u8_inc(&rdptr);
                date_mm = read_u8_inc(&rdptr);
@@ -1298,18 +1322,27 @@ SR_PRIV int la2016_identify_device(const struct sr_dev_inst *sdi,
         * LA2016 by faking its EEPROM content.
         */
        devc->identify_magic = 0;
-       if ((ret = ctrl_in(sdi, CMD_EEPROM, 0x08, 0, &buf, sizeof(buf))) != SR_OK) {
+       rdoff = 0x08;
+       rdlen = 8 * sizeof(uint8_t);
+       ret = ctrl_in(sdi, CMD_EEPROM, rdoff, 0, &buf, rdlen);
+       if (ret != SR_OK) {
                sr_err("Cannot read EEPROM device identifier bytes.");
                return ret;
        }
+       if (sr_log_loglevel_get() >= SR_LOG_SPEW) {
+               GString *txt;
+               txt = sr_hexdump_new(buf, rdlen);
+               sr_spew("EEPROM magic bytes %s.", txt->str);
+               sr_hexdump_free(txt);
+       }
        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];
+               sr_dbg("Using primary magic, value %d.", (int)magic);
        } 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];
+               sr_dbg("Using backup magic, value %d.", (int)magic);
        } else {
                sr_err("Cannot find consistent device type identification.");
                magic = 0;
@@ -1322,16 +1355,15 @@ SR_PRIV int la2016_identify_device(const struct sr_dev_inst *sdi,
                if (model->magic != magic)
                        continue;
                devc->model = model;
-               sr_info("EEPROM magic %d, model '%s'.", (int)magic, model->name);
+               sr_info("Model '%s', %zu channels, max %" PRIu64 "MHz.",
+                       model->name, model->channel_count,
+                       model->samplerate / SR_MHZ(1));
                devc->fpga_bitstream = g_strdup_printf(FPGA_FWFILE_FMT,
                        model->fpga_stem);
-               sr_info("Max %zu channels at %" PRIu64 "MHz samplerate.",
-                       model->channel_count, model->samplerate / SR_MHZ(1));
                sr_info("FPGA bitstream file '%s'.", devc->fpga_bitstream);
                break;
        }
        if (!devc->model) {
-               sr_spew("Device type: magic number is %hhu.", magic);
                sr_err("Cannot identify as one of the supported models.");
                return SR_ERR;
        }
@@ -1339,7 +1371,7 @@ SR_PRIV int la2016_identify_device(const struct sr_dev_inst *sdi,
        return SR_OK;
 }
 
-SR_PRIV int la2016_init_device(const struct sr_dev_inst *sdi)
+SR_PRIV int la2016_init_hardware(const struct sr_dev_inst *sdi)
 {
        struct dev_context *devc;
        const char *bitstream_fn;
@@ -1368,13 +1400,21 @@ SR_PRIV int la2016_init_device(const struct sr_dev_inst *sdi)
                sr_warn("Unexpected run state, want 0x85e9, got 0x%04x.", state);
        }
 
-       if ((ret = ctrl_out(sdi, CMD_BULK_RESET, 0x00, 0, NULL, 0)) != SR_OK) {
+       ret = ctrl_out(sdi, CMD_BULK_RESET, 0x00, 0, NULL, 0);
+       if (ret != SR_OK) {
                sr_err("Cannot reset USB bulk transfer.");
                return ret;
        }
 
        sr_dbg("Device should be initialized.");
 
+       return SR_OK;
+}
+
+SR_PRIV int la2016_init_params(const struct sr_dev_inst *sdi)
+{
+       int ret;
+
        ret = set_defaults(sdi);
        if (ret != SR_OK)
                return ret;
@@ -1382,11 +1422,12 @@ SR_PRIV int la2016_init_device(const struct sr_dev_inst *sdi)
        return SR_OK;
 }
 
-SR_PRIV int la2016_deinit_device(const struct sr_dev_inst *sdi)
+SR_PRIV int la2016_deinit_hardware(const struct sr_dev_inst *sdi)
 {
        int ret;
 
-       if ((ret = ctrl_out(sdi, CMD_FPGA_ENABLE, 0x00, 0, NULL, 0)) != SR_OK) {
+       ret = ctrl_out(sdi, CMD_FPGA_ENABLE, 0x00, 0, NULL, 0);
+       if (ret != SR_OK) {
                sr_err("Cannot deinitialize device's FPGA.");
                return ret;
        }