SR_PRIV int zp_set_samplerate(struct dev_context *devc, uint64_t samplerate) { int i; for (i = 0; ARRAY_SIZE(samplerates_200); i++) if (samplerate == samplerates_200[i]) break; if (i == ARRAY_SIZE(samplerates_200) || samplerate > devc->max_samplerate) { sr_err("Unsupported samplerate: %" PRIu64 "Hz.", samplerate); return SR_ERR_ARG; } sr_info("Setting samplerate to %" PRIu64 "Hz.", samplerate); if (samplerate >= SR_MHZ(1)) analyzer_set_freq(samplerate / SR_MHZ(1), FREQ_SCALE_MHZ); else if (samplerate >= SR_KHZ(1)) analyzer_set_freq(samplerate / SR_KHZ(1), FREQ_SCALE_KHZ); else analyzer_set_freq(samplerate, FREQ_SCALE_HZ); devc->cur_samplerate = samplerate; return SR_OK; }
END_TEST START_TEST(test_mhz) { test_samplerate(1000000, "1 MHz"); test_samplerate(28000000, "28 MHz"); test_samplerate(775000000, "775 MHz"); test_samplerate(1234567, "1.234567 MHz"); test_samplerate(12345678, "12.345678 MHz"); test_samplerate(123456789, "123.456789 MHz"); test_samplerate(1230007, "1.230007 MHz"); test_samplerate(1034567, "1.034567 MHz"); test_samplerate(1000007, "1.000007 MHz"); test_samplerate(1234000, "1.234 MHz"); /* Again, but now using SR_MHZ(). */ test_samplerate(SR_MHZ(1), "1 MHz"); test_samplerate(SR_MHZ(28), "28 MHz"); test_samplerate(SR_MHZ(775), "775 MHz"); test_samplerate(SR_MHZ(1.234567), "1.234567 MHz"); test_samplerate(SR_MHZ(12.345678), "12.345678 MHz"); test_samplerate(SR_MHZ(123.456789), "123.456789 MHz"); test_samplerate(SR_MHZ(1.230007), "1.230007 MHz"); test_samplerate(SR_MHZ(1.034567), "1.034567 MHz"); test_samplerate(SR_MHZ(1.000007), "1.000007 MHz"); test_samplerate(SR_MHZ(1.234000), "1.234 MHz"); }
static int set_samplerate(struct sr_dev_inst *sdi, uint64_t samplerate) { struct context *ctx; if (!sdi) { sr_err("zp: %s: sdi was NULL", __func__); return SR_ERR_ARG; } if (!(ctx = sdi->priv)) { sr_err("zp: %s: sdi->priv was NULL", __func__); return SR_ERR_ARG; } sr_info("zp: Setting samplerate to %" PRIu64 "Hz.", samplerate); if (samplerate > SR_MHZ(1)) analyzer_set_freq(samplerate / SR_MHZ(1), FREQ_SCALE_MHZ); else if (samplerate > SR_KHZ(1)) analyzer_set_freq(samplerate / SR_KHZ(1), FREQ_SCALE_KHZ); else analyzer_set_freq(samplerate, FREQ_SCALE_HZ); ctx->cur_samplerate = samplerate; return SR_OK; }
SR_PRIV int command_start_acquisition(libusb_device_handle *devhdl, uint64_t samplerate, gboolean samplewide) { struct cmd_start_acquisition cmd; int delay = 0, ret; /* Compute the sample rate. */ if (samplewide && samplerate > MAX_16BIT_SAMPLE_RATE) { sr_err("Unable to sample at %" PRIu64 "Hz " "when collecting 16-bit samples.", samplerate); return SR_ERR; } if ((SR_MHZ(48) % samplerate) == 0) { cmd.flags = CMD_START_FLAGS_CLK_48MHZ; delay = SR_MHZ(48) / samplerate - 1; if (delay > MAX_SAMPLE_DELAY) delay = 0; } if (delay == 0 && (SR_MHZ(30) % samplerate) == 0) { cmd.flags = CMD_START_FLAGS_CLK_30MHZ; delay = SR_MHZ(30) / samplerate - 1; } sr_info("GPIF delay = %d, clocksource = %sMHz.", delay, (cmd.flags & CMD_START_FLAGS_CLK_48MHZ) ? "48" : "30"); if (delay <= 0 || delay > MAX_SAMPLE_DELAY) { sr_err("Unable to sample at %" PRIu64 "Hz.", samplerate); return SR_ERR; } cmd.sample_delay_h = (delay >> 8) & 0xff; cmd.sample_delay_l = delay & 0xff; /* Select the sampling width. */ cmd.flags |= samplewide ? CMD_START_FLAGS_SAMPLE_16BIT : CMD_START_FLAGS_SAMPLE_8BIT; /* Send the control message. */ ret = libusb_control_transfer(devhdl, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_OUT, CMD_START, 0x0000, 0x0000, (unsigned char *)&cmd, sizeof(cmd), 100); if (ret < 0) { sr_err("Unable to send start command: %s.", libusb_error_name(ret)); return SR_ERR; } return SR_OK; }
/** * Convert the LA8 'divcount' value to the respective samplerate (in Hz). * * LA8 hardware: sample period = (divcount + 1) * 10ns. * Min. value for divcount: 0x00 (10ns sample period, 100MHz samplerate). * Max. value for divcount: 0xfe (2550ns sample period, 392.15kHz samplerate). * * @param divcount The divcount value as needed by the hardware. * * @return The samplerate in Hz, or 0xffffffffffffffff upon errors. */ static uint64_t divcount_to_samplerate(uint8_t divcount) { if (divcount == 0xff) return 0xffffffffffffffffULL; return SR_MHZ(100) / (divcount + 1); }
/** * Convert a numeric period value to the "natural" string representation * of its period value. * * The period is specified as a rational number's numerator and denominator. * * E.g. a pair of (1, 5) would be converted to "200 ms", (10, 100) to "100 ms". * * @param v_p The period numerator. * @param v_q The period denominator. * * @return A newly allocated string representation of the period value, * or NULL upon errors. The caller is responsible to g_free() the * memory. * * @since 0.5.0 */ SR_API char *sr_period_string(uint64_t v_p, uint64_t v_q) { double freq, v; int prec; freq = 1 / ((double)v_p / v_q); if (freq > SR_GHZ(1)) { v = (double)v_p / v_q * 1000000000000.0; prec = ((v - (uint64_t)v) < FLT_MIN) ? 0 : 3; return g_strdup_printf("%.*f ps", prec, v); } else if (freq > SR_MHZ(1)) { v = (double)v_p / v_q * 1000000000.0; prec = ((v - (uint64_t)v) < FLT_MIN) ? 0 : 3; return g_strdup_printf("%.*f ns", prec, v); } else if (freq > SR_KHZ(1)) { v = (double)v_p / v_q * 1000000.0; prec = ((v - (uint64_t)v) < FLT_MIN) ? 0 : 3; return g_strdup_printf("%.*f us", prec, v); } else if (freq > 1) { v = (double)v_p / v_q * 1000.0; prec = ((v - (uint64_t)v) < FLT_MIN) ? 0 : 3; return g_strdup_printf("%.*f ms", prec, v); } else { v = (double)v_p / v_q; prec = ((v - (uint64_t)v) < FLT_MIN) ? 0 : 3; return g_strdup_printf("%.*f s", prec, v); } }
/** * Convert a "natural" string representation of a size value to uint64_t. * * E.g. a value of "3k" or "3 K" would be converted to 3000, a value * of "15M" would be converted to 15000000. * * Value representations other than decimal (such as hex or octal) are not * supported. Only 'k' (kilo), 'm' (mega), 'g' (giga) suffixes are supported. * Spaces (but not other whitespace) between value and suffix are allowed. * * @param sizestring A string containing a (decimal) size value. * @param size Pointer to uint64_t which will contain the string's size value. * * @return SR_OK upon success, SR_ERR upon errors. * * @since 0.1.0 */ SR_API int sr_parse_sizestring(const char *sizestring, uint64_t *size) { uint64_t multiplier; int done; double frac_part; char *s; *size = strtoull(sizestring, &s, 10); multiplier = 0; frac_part = 0; done = FALSE; while (s && *s && multiplier == 0 && !done) { switch (*s) { case ' ': break; case '.': frac_part = g_ascii_strtod(s, &s); break; case 'k': case 'K': multiplier = SR_KHZ(1); break; case 'm': case 'M': multiplier = SR_MHZ(1); break; case 'g': case 'G': multiplier = SR_GHZ(1); break; case 't': case 'T': multiplier = SR_GHZ(1000); break; case 'p': case 'P': multiplier = SR_GHZ(1000 * 1000); break; case 'e': case 'E': multiplier = SR_GHZ(1000 * 1000 * 1000); break; default: done = TRUE; s--; } s++; } if (multiplier > 0) { *size *= multiplier; *size += frac_part * multiplier; } else { *size += frac_part; } if (s && *s && g_ascii_strcasecmp(s, "Hz")) return SR_ERR; return SR_OK; }
/** * Convert a numeric frequency value to the "natural" string representation * of its period. * * E.g. a value of 3000000 would be converted to "3 us", 20000 to "50 ms". * * @param frequency The frequency in Hz. * * @return A newly allocated string representation of the frequency value, * or NULL upon errors. The caller is responsible to g_free() the * memory. * * @since 0.1.0 */ SR_API char *sr_period_string(uint64_t frequency) { char *o; int r; /* Allocate enough for a uint64_t as string + " ms". */ o = g_malloc0(30 + 1); if (frequency >= SR_GHZ(1)) r = snprintf(o, 30, "%" PRIu64 " ns", frequency / 1000000000); else if (frequency >= SR_MHZ(1)) r = snprintf(o, 30, "%" PRIu64 " us", frequency / 1000000); else if (frequency >= SR_KHZ(1)) r = snprintf(o, 30, "%" PRIu64 " ms", frequency / 1000); else r = snprintf(o, 30, "%" PRIu64 " s", frequency); if (r < 0) { /* Something went wrong... */ g_free(o); return NULL; } return o; }
static struct sr_dev_inst *create_device(struct sr_usb_dev_inst *usb, enum sr_dev_inst_status status, int64_t fw_updated) { struct sr_dev_inst *sdi; struct dev_context *devc; char channel_name[8]; int i; sdi = g_malloc0(sizeof(struct sr_dev_inst)); sdi->status = status; sdi->vendor = g_strdup("LeCroy"); sdi->model = g_strdup("LogicStudio16"); sdi->inst_type = SR_INST_USB; sdi->conn = usb; for (i = 0; i < 16; i++) { snprintf(channel_name, sizeof(channel_name), "D%i", i); sr_channel_new(sdi, i, SR_CHANNEL_LOGIC, TRUE, channel_name); } devc = g_malloc0(sizeof(struct dev_context)); sdi->priv = devc; devc->fw_updated = fw_updated; devc->capture_ratio = 50; lls_set_samplerate(sdi, SR_MHZ(500)); return sdi; }
/** * Convert a numeric value value to its "natural" string representation * in SI units. * * E.g. a value of 3000000, with units set to "W", would be converted * to "3 MW", 20000 to "20 kW", 31500 would become "31.5 kW". * * @param x The value to convert. * @param unit The unit to append to the string, or NULL if the string * has no units. * * @return A newly allocated string representation of the samplerate value, * or NULL upon errors. The caller is responsible to g_free() the * memory. * * @since 0.2.0 */ SR_API char *sr_si_string_u64(uint64_t x, const char *unit) { uint8_t i; uint64_t quot, divisor[] = { SR_HZ(1), SR_KHZ(1), SR_MHZ(1), SR_GHZ(1), SR_GHZ(1000), SR_GHZ(1000 * 1000), SR_GHZ(1000 * 1000 * 1000), }; const char *p, prefix[] = "\0kMGTPE"; char fmt[16], fract[20] = "", *f; if (!unit) unit = ""; for (i = 0; (quot = x / divisor[i]) >= 1000; i++); if (i) { sprintf(fmt, ".%%0%d"PRIu64, i * 3); f = fract + sprintf(fract, fmt, x % divisor[i]) - 1; while (f >= fract && strchr("0.", *f)) *f-- = 0; } p = prefix + i; return g_strdup_printf("%" PRIu64 "%s %.1s%s", quot, fract, p, unit); }
/** * Convert a numeric value value to its "natural" string representation. * in SI units * * E.g. a value of 3000000, with units set to "W", would be converted * to "3 MW", 20000 to "20 kW", 31500 would become "31.5 kW". * * @param x The value to convert. * @param unit The unit to append to the string, or NULL if the string * has no units. * * @return A g_try_malloc()ed string representation of the samplerate value, * or NULL upon errors. The caller is responsible to g_free() the * memory. */ SR_API char *sr_si_string_u64(uint64_t x, const char *unit) { if (unit == NULL) unit = ""; if ((x >= SR_GHZ(1)) && (x % SR_GHZ(1) == 0)) { return g_strdup_printf("%" PRIu64 " G%s", x / SR_GHZ(1), unit); } else if ((x >= SR_GHZ(1)) && (x % SR_GHZ(1) != 0)) { return g_strdup_printf("%" PRIu64 ".%" PRIu64 " G%s", x / SR_GHZ(1), x % SR_GHZ(1), unit); } else if ((x >= SR_MHZ(1)) && (x % SR_MHZ(1) == 0)) { return g_strdup_printf("%" PRIu64 " M%s", x / SR_MHZ(1), unit); } else if ((x >= SR_MHZ(1)) && (x % SR_MHZ(1) != 0)) { return g_strdup_printf("%" PRIu64 ".%" PRIu64 " M%s", x / SR_MHZ(1), x % SR_MHZ(1), unit); } else if ((x >= SR_KHZ(1)) && (x % SR_KHZ(1) == 0)) { return g_strdup_printf("%" PRIu64 " k%s", x / SR_KHZ(1), unit); } else if ((x >= SR_KHZ(1)) && (x % SR_KHZ(1) != 0)) { return g_strdup_printf("%" PRIu64 ".%" PRIu64 " K%s", x / SR_KHZ(1), x % SR_KHZ(1), unit); } else { return g_strdup_printf("%" PRIu64 " %s", x, unit); } sr_err("%s: Error creating SI units string.", __func__); return NULL; }
static int setup_acquisition(const struct sr_dev_inst *sdi) { static const struct regval capture_init[] = { {REG_CAP_CTRL, 0}, {REG_DURATION, 0}, {REG_MEM_CTRL, MEM_CTRL_RESET}, {REG_MEM_CTRL, 0}, {REG_MEM_CTRL, MEM_CTRL_WRITE}, {REG_CAP_CTRL, CAP_CTRL_FIFO32_FULL | CAP_CTRL_FIFO64_FULL}, {REG_CAP_CTRL, CAP_CTRL_FIFO_EMPTY}, {REG_CAP_CTRL, 0}, {REG_CAP_COUNT, MEMORY_DEPTH - 5}, }; struct dev_context *devc; struct sr_usb_dev_inst *usb; uint32_t divider_count, trigger_setup; int ret; devc = sdi->priv; usb = sdi->conn; ret = lwla_write_reg(usb, REG_CHAN_MASK, devc->channel_mask); if (ret != SR_OK) return ret; if (devc->samplerate > 0 && devc->samplerate < SR_MHZ(100)) divider_count = SR_MHZ(100) / devc->samplerate - 1; else divider_count = 0; ret = lwla_write_reg(usb, REG_DIV_COUNT, divider_count); if (ret != SR_OK) return ret; ret = lwla_write_regs(usb, capture_init, ARRAY_SIZE(capture_init)); if (ret != SR_OK) return ret; trigger_setup = ((devc->trigger_edge_mask & 0xFFFF) << 16) | (devc->trigger_values & 0xFFFF); return lwla_write_reg(usb, REG_TRG_SEL, trigger_setup); }
SR_PRIV void fill_supported_samplerates_if_needed(void) { int i; if (chronovu_la8_samplerates[0] != 0) return; for (i = 0; i < 255; i++) chronovu_la8_samplerates[254 - i] = SR_MHZ(100) / (i + 1); }
SR_PRIV void fill_supported_samplerates_if_needed(void) { int i; /* Do nothing if supported_samplerates[] is already filled. */ if (supported_samplerates[0] != 0) return; /* Fill supported_samplerates[] with the proper values. */ for (i = 0; i < 255; i++) supported_samplerates[254 - i] = SR_MHZ(100) / (i + 1); supported_samplerates[255] = 0; }
/** * Convert a samplerate (in Hz) to the 'divcount' value the LA8 wants. * * LA8 hardware: sample period = (divcount + 1) * 10ns. * Min. value for divcount: 0x00 (10ns sample period, 100MHz samplerate). * Max. value for divcount: 0xfe (2550ns sample period, 392.15kHz samplerate). * * @param samplerate The samplerate in Hz. * @return The divcount value as needed by the hardware, or 0xff upon errors. */ SR_PRIV uint8_t samplerate_to_divcount(uint64_t samplerate) { if (samplerate == 0) { sr_err("%s: samplerate was 0.", __func__); return 0xff; } if (!is_valid_samplerate(samplerate)) { sr_err("%s: Can't get divcount, samplerate invalid.", __func__); return 0xff; } return (SR_MHZ(100) / samplerate) - 1; }
static int config_get(uint32_t key, GVariant **data, const struct sr_dev_inst *sdi, const struct sr_channel_group *cg) { (void)sdi; (void)cg; switch (key) { case SR_CONF_SAMPLERATE: /* The ScanaPLUS samplerate is 100MHz and can't be changed. */ *data = g_variant_new_uint64(SR_MHZ(100)); break; default: return SR_ERR_NA; } return SR_OK; }
/** * Convert a "natural" string representation of a size value to uint64_t. * * E.g. a value of "3k" or "3 K" would be converted to 3000, a value * of "15M" would be converted to 15000000. * * Value representations other than decimal (such as hex or octal) are not * supported. Only 'k' (kilo), 'm' (mega), 'g' (giga) suffixes are supported. * Spaces (but not other whitespace) between value and suffix are allowed. * * @param sizestring A string containing a (decimal) size value. * @param size Pointer to uint64_t which will contain the string's size value. * * @return SR_OK upon success, SR_ERR upon errors. */ SR_API int sr_parse_sizestring(const char *sizestring, uint64_t *size) { int multiplier, done; char *s; *size = strtoull(sizestring, &s, 10); multiplier = 0; done = FALSE; while (s && *s && multiplier == 0 && !done) { switch (*s) { case ' ': break; case 'k': case 'K': multiplier = SR_KHZ(1); break; case 'm': case 'M': multiplier = SR_MHZ(1); break; case 'g': case 'G': multiplier = SR_GHZ(1); break; default: done = TRUE; s--; } s++; } if (multiplier > 0) *size *= multiplier; if (*s && strcasecmp(s, "Hz")) return SR_ERR; return SR_OK; }
static int config_set(uint32_t key, GVariant *data, const struct sr_dev_inst *sdi, const struct sr_channel_group *cg) { struct dev_context *devc; (void)cg; if (sdi->status != SR_ST_ACTIVE) return SR_ERR_DEV_CLOSED; devc = sdi->priv; switch (key) { case SR_CONF_SAMPLERATE: if (g_variant_get_uint64(data) != SR_MHZ(100)) { sr_err("ScanaPLUS only supports samplerate = 100MHz."); return SR_ERR_ARG; } /* Nothing to do, the ScanaPLUS samplerate is always 100MHz. */ break; case SR_CONF_LIMIT_MSEC: if (g_variant_get_uint64(data) == 0) return SR_ERR_ARG; devc->limit_msec = g_variant_get_uint64(data); break; case SR_CONF_LIMIT_SAMPLES: if (g_variant_get_uint64(data) == 0) return SR_ERR_ARG; devc->limit_samples = g_variant_get_uint64(data); break; default: return SR_ERR_NA; } return SR_OK; }
static GSList *scan(struct sr_dev_driver *di, GSList *options) { struct sr_dev_inst *sdi; struct drv_context *drvc; struct dev_context *devc; const struct zp_model *prof; struct libusb_device_descriptor des; struct libusb_device_handle *hdl; libusb_device **devlist; GSList *devices; int ret, i, j; char serial_num[64], connection_id[64]; (void)options; drvc = di->priv; devices = NULL; /* Find all ZEROPLUS analyzers and add them to device list. */ libusb_get_device_list(drvc->sr_ctx->libusb_ctx, &devlist); /* TODO: Errors. */ for (i = 0; devlist[i]; i++) { ret = libusb_get_device_descriptor(devlist[i], &des); if (ret != 0) { sr_err("Failed to get device descriptor: %s.", libusb_error_name(ret)); continue; } if ((ret = libusb_open(devlist[i], &hdl)) < 0) continue; if (des.iSerialNumber == 0) { serial_num[0] = '\0'; } else if ((ret = libusb_get_string_descriptor_ascii(hdl, des.iSerialNumber, (unsigned char *) serial_num, sizeof(serial_num))) < 0) { sr_warn("Failed to get serial number string descriptor: %s.", libusb_error_name(ret)); continue; } libusb_close(hdl); usb_get_port_path(devlist[i], connection_id, sizeof(connection_id)); prof = NULL; for (j = 0; j < zeroplus_models[j].vid; j++) { if (des.idVendor == zeroplus_models[j].vid && des.idProduct == zeroplus_models[j].pid) { prof = &zeroplus_models[j]; } } /* Skip if the device was not found. */ if (!prof) continue; sr_info("Found ZEROPLUS %s.", prof->model_name); /* Register the device with libsigrok. */ sdi = g_malloc0(sizeof(struct sr_dev_inst)); sdi->status = SR_ST_INACTIVE; sdi->vendor = g_strdup(VENDOR_NAME); sdi->model = g_strdup(prof->model_name); sdi->driver = di; sdi->serial_num = g_strdup(serial_num); sdi->connection_id = g_strdup(connection_id); /* Allocate memory for our private driver context. */ devc = g_malloc0(sizeof(struct dev_context)); sdi->priv = devc; devc->prof = prof; devc->num_channels = prof->channels; #ifdef ZP_EXPERIMENTAL devc->max_sample_depth = 128 * 1024; devc->max_samplerate = 200; #else devc->max_sample_depth = prof->sample_depth * 1024; devc->max_samplerate = prof->max_sampling_freq; #endif devc->max_samplerate *= SR_MHZ(1); devc->memory_size = MEMORY_SIZE_8K; // memset(devc->trigger_buffer, 0, NUM_TRIGGER_STAGES); /* Fill in channellist according to this device's profile. */ for (j = 0; j < devc->num_channels; j++) sr_channel_new(sdi, j, SR_CHANNEL_LOGIC, TRUE, channel_names[j]); devices = g_slist_append(devices, sdi); drvc->instances = g_slist_append(drvc->instances, sdi); sdi->inst_type = SR_INST_USB; sdi->conn = sr_usb_dev_inst_new( libusb_get_bus_number(devlist[i]), libusb_get_device_address(devlist[i]), NULL); } libusb_free_device_list(devlist, 1); return devices; }
/* Set up the acquisition state record. */ static int init_acquisition_state(const struct sr_dev_inst *sdi) { struct dev_context *devc; struct sr_usb_dev_inst *usb; struct acquisition_state *acq; devc = sdi->priv; usb = sdi->conn; if (devc->acquisition) { sr_err("Acquisition still in progress?"); return SR_ERR; } if (devc->cfg_clock_source == CLOCK_INTERNAL && devc->samplerate == 0) { sr_err("Samplerate not set."); return SR_ERR; } acq = g_try_malloc0(sizeof(struct acquisition_state)); if (!acq) return SR_ERR_MALLOC; acq->xfer_in = libusb_alloc_transfer(0); if (!acq->xfer_in) { g_free(acq); return SR_ERR_MALLOC; } acq->xfer_out = libusb_alloc_transfer(0); if (!acq->xfer_out) { libusb_free_transfer(acq->xfer_in); g_free(acq); return SR_ERR_MALLOC; } libusb_fill_bulk_transfer(acq->xfer_out, usb->devhdl, EP_COMMAND, (unsigned char *)acq->xfer_buf_out, 0, &transfer_out_completed, (struct sr_dev_inst *)sdi, USB_TIMEOUT_MS); libusb_fill_bulk_transfer(acq->xfer_in, usb->devhdl, EP_REPLY, (unsigned char *)acq->xfer_buf_in, sizeof(acq->xfer_buf_in), &transfer_in_completed, (struct sr_dev_inst *)sdi, USB_TIMEOUT_MS); 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); /* Ramp up clock speed to enable samplerates above 100 MS/s. */ acq->clock_boost = (devc->samplerate > SR_MHZ(100)); /* If only one of the limits is set, derive the other one. */ if (devc->limit_msec == 0 && devc->limit_samples > 0) acq->duration_max = devc->limit_samples * 1000 / devc->samplerate + 1; else if (devc->limit_samples == 0 && devc->limit_msec > 0) acq->samples_max = devc->limit_msec * devc->samplerate / 1000; } else { acq->clock_boost = TRUE; if (devc->cfg_clock_edge == EDGE_POSITIVE) sr_info("External clock, rising edge."); else sr_info("External clock, falling edge."); } acq->rle_enabled = devc->cfg_rle; devc->acquisition = acq; return SR_OK; }
static GSList *scan(GSList *options) { struct sr_dev_inst *sdi; struct sr_channel *ch; struct drv_context *drvc; struct dev_context *devc; const struct zp_model *prof; struct libusb_device_descriptor des; libusb_device **devlist; GSList *devices; int ret, devcnt, i, j; (void)options; drvc = di->priv; devices = NULL; /* Find all ZEROPLUS analyzers and add them to device list. */ devcnt = 0; libusb_get_device_list(drvc->sr_ctx->libusb_ctx, &devlist); /* TODO: Errors. */ for (i = 0; devlist[i]; i++) { ret = libusb_get_device_descriptor(devlist[i], &des); if (ret != 0) { sr_err("Failed to get device descriptor: %s.", libusb_error_name(ret)); continue; } prof = NULL; for (j = 0; j < zeroplus_models[j].vid; j++) { if (des.idVendor == zeroplus_models[j].vid && des.idProduct == zeroplus_models[j].pid) { prof = &zeroplus_models[j]; } } /* Skip if the device was not found. */ if (!prof) continue; sr_info("Found ZEROPLUS %s.", prof->model_name); /* Register the device with libsigrok. */ if (!(sdi = sr_dev_inst_new(devcnt, SR_ST_INACTIVE, VENDOR_NAME, prof->model_name, NULL))) { sr_err("%s: sr_dev_inst_new failed", __func__); return NULL; } sdi->driver = di; /* Allocate memory for our private driver context. */ if (!(devc = g_try_malloc0(sizeof(struct dev_context)))) { sr_err("Device context malloc failed."); return NULL; } sdi->priv = devc; devc->prof = prof; devc->num_channels = prof->channels; #ifdef ZP_EXPERIMENTAL devc->max_sample_depth = 128 * 1024; devc->max_samplerate = 200; #else devc->max_sample_depth = prof->sample_depth * 1024; devc->max_samplerate = prof->max_sampling_freq; #endif devc->max_samplerate *= SR_MHZ(1); devc->memory_size = MEMORY_SIZE_8K; // memset(devc->trigger_buffer, 0, NUM_TRIGGER_STAGES); /* Fill in channellist according to this device's profile. */ for (j = 0; j < devc->num_channels; j++) { if (!(ch = sr_channel_new(j, SR_CHANNEL_LOGIC, TRUE, channel_names[j]))) return NULL; sdi->channels = g_slist_append(sdi->channels, ch); } devices = g_slist_append(devices, sdi); drvc->instances = g_slist_append(drvc->instances, sdi); sdi->inst_type = SR_INST_USB; sdi->conn = sr_usb_dev_inst_new( libusb_get_bus_number(devlist[i]), libusb_get_device_address(devlist[i]), NULL); devcnt++; } libusb_free_device_list(devlist, 1); return devices; }
SR_PRIV int scanaplus_receive_data(int fd, int revents, void *cb_data) { int bytes_read; struct sr_dev_inst *sdi; struct dev_context *devc; uint64_t max, n; (void)fd; (void)revents; if (!(sdi = cb_data)) return TRUE; if (!(devc = sdi->priv)) return TRUE; if (!devc->ftdic) return TRUE; /* Get a block of data. */ bytes_read = ftdi_read_data(devc->ftdic, devc->compressed_buf, COMPRESSED_BUF_SIZE); if (bytes_read < 0) { sr_err("Failed to read FTDI data (%d): %s.", bytes_read, ftdi_get_error_string(devc->ftdic)); sdi->driver->dev_acquisition_stop(sdi, sdi); return FALSE; } if (bytes_read == 0) { sr_spew("Received 0 bytes, nothing to do."); return TRUE; } /* * After a ScanaPLUS acquisition starts, a bunch of samples will be * returned as all-zero, no matter which signals are actually present * on the channels. This is probably due to the FPGA reconfiguring some * of its internal state/config during this time. * * As far as we know there is apparently no way for the PC-side to * know when this "reconfiguration" starts or ends. The FTDI chip * will return all-zero "dummy" samples during this time, which is * indistinguishable from actual all-zero samples. * * We currently simply ignore the first 64kB of data after an * acquisition starts. Empirical tests have shown that the * "reconfigure" time is a lot less than that usually. */ if (devc->compressed_bytes_ignored < COMPRESSED_BUF_SIZE) { /* Ignore the first 64kB of data of every acquisition. */ sr_spew("Ignoring first 64kB chunk of data."); devc->compressed_bytes_ignored += COMPRESSED_BUF_SIZE; return TRUE; } /* TODO: Handle bytes_read which is not a multiple of 2? */ scanaplus_uncompress_block(devc, bytes_read); n = devc->samples_sent + (devc->bytes_received / 2); max = (SR_MHZ(100) / 1000) * devc->limit_msec; if (devc->limit_samples && (n >= devc->limit_samples)) { send_samples(devc, devc->limit_samples - devc->samples_sent); sr_info("Requested number of samples reached."); sdi->driver->dev_acquisition_stop(sdi, cb_data); return TRUE; } else if (devc->limit_msec && (n >= max)) { send_samples(devc, max - devc->samples_sent); sr_info("Requested time limit reached."); sdi->driver->dev_acquisition_stop(sdi, cb_data); return TRUE; } else { send_samples(devc, devc->bytes_received / 2); } return TRUE; }
// SR_CONF_RLE, 0, }; /* * Probes are numbered 0 to 7. * * See also: http://www.linkinstruments.com/images/mso19_1113.gif */ SR_PRIV const char *mso19_probe_names[NUM_PROBES + 1] = { "0", "1", "2", "3", "4", "5", "6", "7", NULL }; static const struct sr_samplerates samplerates = { .low = SR_HZ(100), .high = SR_MHZ(200), .step = SR_HZ(100), .list = NULL, }; SR_PRIV struct sr_dev_driver link_mso19_driver_info; static struct sr_dev_driver *di = &link_mso19_driver_info; static int hw_init(struct sr_context *sr_ctx) { return std_hw_init(sr_ctx, di, DRIVER_LOG_DOMAIN); } static GSList *hw_scan(GSList *options) { int i;
* The hardware supports more samplerates than these, but these are the * options hardcoded into the vendor's Windows GUI. */ static const uint64_t samplerates_100[] = { SR_HZ(100), SR_HZ(500), SR_KHZ(1), SR_KHZ(5), SR_KHZ(25), SR_KHZ(50), SR_KHZ(100), SR_KHZ(200), SR_KHZ(400), SR_KHZ(800), SR_MHZ(1), SR_MHZ(10), SR_MHZ(25), SR_MHZ(50), SR_MHZ(80), SR_MHZ(100), }; const uint64_t samplerates_200[] = { SR_HZ(100), SR_HZ(500), SR_KHZ(1), SR_KHZ(5), SR_KHZ(25), SR_KHZ(50), SR_KHZ(100),
SR_PRIV int fx2lafw_command_start_acquisition(const struct sr_dev_inst *sdi) { struct dev_context *devc; struct sr_usb_dev_inst *usb; uint64_t samplerate; struct cmd_start_acquisition cmd; int delay, ret; devc = sdi->priv; usb = sdi->conn; samplerate = devc->cur_samplerate; /* Compute the sample rate. */ if (devc->sample_wide && samplerate > MAX_16BIT_SAMPLE_RATE) { sr_err("Unable to sample at %" PRIu64 "Hz " "when collecting 16-bit samples.", samplerate); return SR_ERR; } delay = 0; cmd.flags = cmd.sample_delay_h = cmd.sample_delay_l = 0; if ((SR_MHZ(48) % samplerate) == 0) { cmd.flags = CMD_START_FLAGS_CLK_48MHZ; delay = SR_MHZ(48) / samplerate - 1; if (delay > MAX_SAMPLE_DELAY) delay = 0; } if (delay == 0 && (SR_MHZ(30) % samplerate) == 0) { cmd.flags = CMD_START_FLAGS_CLK_30MHZ; delay = SR_MHZ(30) / samplerate - 1; } sr_dbg("GPIF delay = %d, clocksource = %sMHz.", delay, (cmd.flags & CMD_START_FLAGS_CLK_48MHZ) ? "48" : "30"); if (delay <= 0 || delay > MAX_SAMPLE_DELAY) { sr_err("Unable to sample at %" PRIu64 "Hz.", samplerate); return SR_ERR; } cmd.sample_delay_h = (delay >> 8) & 0xff; cmd.sample_delay_l = delay & 0xff; /* Select the sampling width. */ cmd.flags |= devc->sample_wide ? CMD_START_FLAGS_SAMPLE_16BIT : CMD_START_FLAGS_SAMPLE_8BIT; /* Enable CTL2 clock. */ cmd.flags |= (g_slist_length(devc->enabled_analog_channels) > 0) ? CMD_START_FLAGS_CLK_CTL2 : 0; /* Send the control message. */ ret = libusb_control_transfer(usb->devhdl, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_OUT, CMD_START, 0x0000, 0x0000, (unsigned char *)&cmd, sizeof(cmd), USB_TIMEOUT); if (ret < 0) { sr_err("Unable to send start command: %s.", libusb_error_name(ret)); return SR_ERR; } return SR_OK; }
* * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <config.h> #include "protocol.h" SR_PRIV const struct cv_profile cv_profiles[] = { { CHRONOVU_LA8, "LA8", "ChronoVu LA8", 8, SR_MHZ(100), 2, 0.8388608 }, { CHRONOVU_LA16, "LA16", "ChronoVu LA16", 16, SR_MHZ(200), 4, 0.042 }, ALL_ZERO }; /* LA8: channels are numbered 0-7. LA16: channels are numbered 0-15. */ SR_PRIV const char *cv_channel_names[] = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", }; static int close_usb_reset_sequencer(struct dev_context *devc); SR_PRIV void cv_fill_samplerates_if_needed(const struct sr_dev_inst *sdi) { int i;
SR_CONF_CONN | SR_CONF_GET, SR_CONF_LIMIT_FRAMES | SR_CONF_GET | SR_CONF_SET, SR_CONF_SAMPLERATE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST, SR_CONF_TRIGGER_SOURCE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST, SR_CONF_TRIGGER_SLOPE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST, SR_CONF_BUFFERSIZE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST, }; static const uint32_t cgopts[] = { SR_CONF_VDIV | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST, SR_CONF_COUPLING | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST, SR_CONF_PROBE_FACTOR | SR_CONF_GET | SR_CONF_SET, }; static const uint64_t samplerates[] = { SR_MHZ(100), SR_MHZ(50), SR_MHZ(25), SR_MHZ(20), SR_MHZ(10), SR_MHZ(5), SR_KHZ(2500), SR_MHZ(2), SR_MHZ(1), SR_KHZ(500), SR_KHZ(250), SR_KHZ(200), SR_KHZ(100), SR_KHZ(50), SR_KHZ(25), SR_KHZ(20), SR_KHZ(10), SR_KHZ(5), SR_HZ(2500), SR_KHZ(2), SR_KHZ(1), SR_HZ(500), SR_HZ(250), SR_HZ(200), SR_HZ(100), SR_HZ(50), SR_HZ(25), SR_HZ(20) }; /* must be in sync with readout_steps[] in protocol.c */ static const uint64_t buffersizes[] = { 2 * 500, 3 * 500, 4 * 500, 5 * 500, 6 * 500, 7 * 500, 8 * 500, 9 * 500, 10 * 500, 12 * 500 - 2, 14 * 500 - 2, 16 * 500 - 2, 18 * 500 - 2, 20 * 500 - 2, 10240 - 2 };
SR_TRIGGER_EDGE, }; static const uint64_t samplerates[] = { SR_HZ(1000), SR_HZ(2500), SR_KHZ(5), SR_KHZ(10), SR_KHZ(25), SR_KHZ(50), SR_KHZ(100), SR_KHZ(250), SR_KHZ(500), SR_KHZ(1000), SR_KHZ(2500), SR_MHZ(5), SR_MHZ(10), SR_MHZ(25), SR_MHZ(50), SR_MHZ(100), SR_MHZ(250), SR_MHZ(500), }; static struct sr_dev_inst *create_device(struct sr_usb_dev_inst *usb, enum sr_dev_inst_status status, int64_t fw_updated) { struct sr_dev_inst *sdi; struct dev_context *devc; char channel_name[8]; int i;
static int dev_open(struct sr_dev_inst *sdi) { struct dev_context *devc; struct drv_context *drvc; struct sr_usb_dev_inst *usb; libusb_device **devlist, *dev; struct libusb_device_descriptor des; int device_count, ret, i; drvc = di->priv; usb = sdi->conn; if (!(devc = sdi->priv)) { sr_err("%s: sdi->priv was NULL", __func__); return SR_ERR_ARG; } device_count = libusb_get_device_list(drvc->sr_ctx->libusb_ctx, &devlist); if (device_count < 0) { sr_err("Failed to retrieve device list."); return SR_ERR; } dev = NULL; for (i = 0; i < device_count; i++) { if ((ret = libusb_get_device_descriptor(devlist[i], &des))) { sr_err("Failed to get device descriptor: %s.", libusb_error_name(ret)); continue; } if (libusb_get_bus_number(devlist[i]) == usb->bus && libusb_get_device_address(devlist[i]) == usb->address) { dev = devlist[i]; break; } } if (!dev) { sr_err("Device on bus %d address %d disappeared!", usb->bus, usb->address); return SR_ERR; } if (!(ret = libusb_open(dev, &(usb->devhdl)))) { sdi->status = SR_ST_ACTIVE; sr_info("Opened device %d on %d.%d interface %d.", sdi->index, usb->bus, usb->address, USB_INTERFACE); } else { sr_err("Failed to open device: %s.", libusb_error_name(ret)); return SR_ERR; } ret = libusb_set_configuration(usb->devhdl, USB_CONFIGURATION); if (ret < 0) { sr_err("Unable to set USB configuration %d: %s.", USB_CONFIGURATION, libusb_error_name(ret)); return SR_ERR; } ret = libusb_claim_interface(usb->devhdl, USB_INTERFACE); if (ret != 0) { sr_err("Unable to claim interface: %s.", libusb_error_name(ret)); return SR_ERR; } /* Set default configuration after power on. */ if (analyzer_read_status(usb->devhdl) == 0) analyzer_configure(usb->devhdl); analyzer_reset(usb->devhdl); analyzer_initialize(usb->devhdl); //analyzer_set_memory_size(MEMORY_SIZE_512K); // analyzer_set_freq(g_freq, g_freq_scale); analyzer_set_trigger_count(1); // analyzer_set_ramsize_trigger_address((((100 - g_pre_trigger) // * get_memory_size(g_memory_size)) / 100) >> 2); #if 0 if (g_double_mode == 1) analyzer_set_compression(COMPRESSION_DOUBLE); else if (g_compression == 1) analyzer_set_compression(COMPRESSION_ENABLE); else #endif analyzer_set_compression(COMPRESSION_NONE); if (devc->cur_samplerate == 0) { /* Samplerate hasn't been set. Default to 1MHz. */ analyzer_set_freq(1, FREQ_SCALE_MHZ); devc->cur_samplerate = SR_MHZ(1); } if (devc->cur_threshold == 0) set_voltage_threshold(devc, 1.5); return SR_OK; }
static const int hwcaps[] = { SR_CONF_LOGIC_ANALYZER, SR_CONF_SAMPLERATE, SR_CONF_LIMIT_SAMPLES, SR_CONF_TRIGGER_TYPE, SR_CONF_CAPTURE_RATIO, }; SR_PRIV const uint64_t sl2_samplerates[NUM_SAMPLERATES] = { SR_KHZ(1.25), SR_KHZ(10), SR_KHZ(50), SR_KHZ(100), SR_KHZ(250), SR_KHZ(500), SR_MHZ(1), SR_MHZ(2.5), SR_MHZ(5), SR_MHZ(10), SR_MHZ(20), }; static const char *probe_names[NUM_PROBES + 1] = { "0", "1", "2", "3", NULL, }; SR_PRIV struct sr_dev_driver ikalogic_scanalogic2_driver_info; static struct sr_dev_driver *di = &ikalogic_scanalogic2_driver_info; static int init(struct sr_context *sr_ctx)