#include "protocol.h"
/*
- * The ASIX Sigma supports arbitrary integer frequency divider in
- * the 50MHz mode. The divider is in range 1...256 , allowing for
- * very precise sampling rate selection. This driver supports only
- * a subset of the sampling rates.
+ * The ASIX SIGMA hardware supports fixed 200MHz and 100MHz sample rates
+ * (by means of separate firmware images). As well as 50MHz divided by
+ * an integer divider in the 1..256 range (by the "typical" firmware).
+ * Which translates to a strict lower boundary of around 195kHz.
+ *
+ * This driver "suggests" a subset of the available rates by listing a
+ * few discrete values, while setter routines accept any user specified
+ * rate that is supported by the hardware.
*/
SR_PRIV const uint64_t samplerates[] = {
- SR_KHZ(200), /* div=250 */
- SR_KHZ(250), /* div=200 */
- SR_KHZ(500), /* div=100 */
- SR_MHZ(1), /* div=50 */
- SR_MHZ(5), /* div=10 */
- SR_MHZ(10), /* div=5 */
- SR_MHZ(25), /* div=2 */
- SR_MHZ(50), /* div=1 */
- SR_MHZ(100), /* Special FW needed */
- SR_MHZ(200), /* Special FW needed */
+ /* 50MHz and integer divider. 1/2/5 steps (where possible). */
+ SR_KHZ(200), SR_KHZ(500),
+ SR_MHZ(1), SR_MHZ(2), SR_MHZ(5),
+ SR_MHZ(10), SR_MHZ(25), SR_MHZ(50),
+ /* 100MHz/200MHz, fixed rates in special firmware. */
+ SR_MHZ(100), SR_MHZ(200),
};
SR_PRIV const size_t samplerates_count = ARRAY_SIZE(samplerates);
static const char *firmware_files[] = {
- "asix-sigma-50.fw", /* Up to 50MHz sample rate, 8bit divider. */
- "asix-sigma-100.fw", /* 100MHz sample rate, fixed. */
- "asix-sigma-200.fw", /* 200MHz sample rate, fixed. */
- "asix-sigma-50sync.fw", /* Synchronous clock from external pin. */
- "asix-sigma-phasor.fw", /* Frequency counter. */
+ [SIGMA_FW_50MHZ] = "asix-sigma-50.fw", /* 50MHz, 8bit divider. */
+ [SIGMA_FW_100MHZ] = "asix-sigma-100.fw", /* 100MHz, fixed. */
+ [SIGMA_FW_200MHZ] = "asix-sigma-200.fw", /* 200MHz, fixed. */
+ [SIGMA_FW_SYNC] = "asix-sigma-50sync.fw", /* Sync from external pin. */
+ [SIGMA_FW_FREQ] = "asix-sigma-phasor.fw", /* Frequency counter. */
};
#define SIGMA_FIRMWARE_SIZE_LIMIT (256 * 1024)
/*
* Initiate slave serial mode for configuration download. Which is done
* by pulsing PROG_B and sensing INIT_B. Make sure CCLK is idle before
- * initiating the configuration download. Run a "suicide sequence" first
- * to terminate the regular FPGA operation before reconfiguration.
+ * initiating the configuration download.
+ *
+ * Run a "suicide sequence" first to terminate the regular FPGA operation
+ * before reconfiguration. The FTDI cable is single channel, and shares
+ * pins which are used for data communication in FIFO mode with pins that
+ * are used for FPGA configuration in bitbang mode. Hardware defaults for
+ * unconfigured hardware, and runtime conditions after FPGA configuration
+ * need to cooperate such that re-configuration of the FPGA can start.
*/
-static int sigma_fpga_init_bitbang(struct dev_context *devc)
+static int sigma_fpga_init_bitbang_once(struct dev_context *devc)
{
uint8_t suicide[] = {
BB_PIN_D7 | BB_PIN_D2,
sigma_write(suicide, sizeof(suicide), devc);
sigma_write(suicide, sizeof(suicide), devc);
sigma_write(suicide, sizeof(suicide), devc);
+ g_usleep(10 * 1000);
/* Section 2. part 2), pulse PROG. */
sigma_write(init_array, sizeof(init_array), devc);
+ g_usleep(10 * 1000);
ftdi_usb_purge_buffers(&devc->ftdic);
/* Wait until the FPGA asserts INIT_B. */
return SR_ERR_TIMEOUT;
}
+/*
+ * This is belt and braces. Re-run the bitbang initiation sequence a few
+ * times should first attempts fail. Failure is rare but can happen (was
+ * observed during driver development).
+ */
+static int sigma_fpga_init_bitbang(struct dev_context *devc)
+{
+ size_t retries;
+ int ret;
+
+ retries = 10;
+ while (retries--) {
+ ret = sigma_fpga_init_bitbang_once(devc);
+ if (ret == SR_OK)
+ return ret;
+ if (ret != SR_ERR_TIMEOUT)
+ return ret;
+ }
+ return ret;
+}
+
/*
* Configure the FPGA for logic-analyzer mode.
*/
}
static int upload_firmware(struct sr_context *ctx,
- int firmware_idx, struct dev_context *devc)
+ struct dev_context *devc, enum sigma_firmware_idx firmware_idx)
{
int ret;
unsigned char *buf;
size_t buf_size;
const char *firmware;
- /* Avoid downloading the same firmware multiple times. */
+ /* Check for valid firmware file selection. */
+ if (firmware_idx >= ARRAY_SIZE(firmware_files))
+ return SR_ERR_ARG;
firmware = firmware_files[firmware_idx];
- if (devc->cur_firmware == firmware_idx) {
+ if (!firmware || !*firmware)
+ return SR_ERR_ARG;
+
+ /* Avoid downloading the same firmware multiple times. */
+ if (devc->firmware_idx == firmware_idx) {
sr_info("Not uploading firmware file '%s' again.", firmware);
return SR_OK;
}
+ devc->state.state = SIGMA_CONFIG;
+
/* Set the cable to bitbang mode. */
ret = ftdi_set_bitmode(&devc->ftdic, BB_PINMASK, BITMODE_BITBANG);
if (ret < 0) {
return ret;
/* Keep track of successful firmware download completion. */
- devc->cur_firmware = firmware_idx;
+ devc->state.state = SIGMA_IDLE;
+ devc->firmware_idx = firmware_idx;
sr_info("Firmware uploaded.");
return SR_OK;
}
/*
- * Sigma doesn't support limiting the number of samples, so we have to
- * translate the number and the samplerate to an elapsed time.
+ * The driver supports user specified time or sample count limits. The
+ * device's hardware supports neither, and hardware compression prevents
+ * reliable detection of "fill levels" (currently reached sample counts)
+ * from register values during acquisition. That's why the driver needs
+ * to apply some heuristics:
+ *
+ * - The (optional) sample count limit and the (normalized) samplerate
+ * get mapped to an estimated duration for these samples' acquisition.
+ * - The (optional) time limit gets checked as well. The lesser of the
+ * two limits will terminate the data acquisition phase. The exact
+ * sample count limit gets enforced in session feed submission paths.
+ * - Some slack needs to be given to account for hardware pipelines as
+ * well as late storage of last chunks after compression thresholds
+ * are tripped. The resulting data set will span at least the caller
+ * specified period of time, which shall be perfectly acceptable.
*
- * In addition we need to ensure that the last data cluster has passed
- * the hardware pipeline, and became available to the PC side. With RLE
- * compression up to 327ms could pass before another cluster accumulates
- * at 200kHz samplerate when input pins don't change.
+ * With RLE compression active, up to 64K sample periods can pass before
+ * a cluster accumulates. Which translates to 327ms at 200kHz. Add two
+ * times that period for good measure, one is not enough to flush the
+ * hardware pipeline (observation from an earlier experiment).
*/
-SR_PRIV uint64_t sigma_limit_samples_to_msec(const struct dev_context *devc,
- uint64_t limit_samples)
+SR_PRIV int sigma_set_acquire_timeout(struct dev_context *devc)
{
- uint64_t limit_msec;
+ int ret;
+ GVariant *data;
+ uint64_t user_count, user_msecs;
uint64_t worst_cluster_time_ms;
+ uint64_t count_msecs, acquire_msecs;
- limit_msec = limit_samples * 1000 / devc->cur_samplerate;
- worst_cluster_time_ms = 65536 * 1000 / devc->cur_samplerate;
- /*
- * One cluster time is not enough to flush pipeline when sampling
- * grounded pins with 1 sample limit at 200kHz. Hence the 2* fix.
- */
- return limit_msec + 2 * worst_cluster_time_ms;
+ sr_sw_limits_init(&devc->acq_limits);
+
+ /* Get sample count limit, convert to msecs. */
+ ret = sr_sw_limits_config_get(&devc->cfg_limits,
+ SR_CONF_LIMIT_SAMPLES, &data);
+ if (ret != SR_OK)
+ return ret;
+ user_count = g_variant_get_uint64(data);
+ g_variant_unref(data);
+ count_msecs = 0;
+ if (user_count)
+ count_msecs = 1000 * user_count / devc->samplerate + 1;
+
+ /* Get time limit, which is in msecs. */
+ ret = sr_sw_limits_config_get(&devc->cfg_limits,
+ SR_CONF_LIMIT_MSEC, &data);
+ if (ret != SR_OK)
+ return ret;
+ user_msecs = g_variant_get_uint64(data);
+ g_variant_unref(data);
+
+ /* Get the lesser of them, with both being optional. */
+ acquire_msecs = ~0ull;
+ if (user_count && count_msecs < acquire_msecs)
+ acquire_msecs = count_msecs;
+ if (user_msecs && user_msecs < acquire_msecs)
+ acquire_msecs = user_msecs;
+ if (acquire_msecs == ~0ull)
+ return SR_OK;
+
+ /* Add some slack, and use that timeout for acquisition. */
+ worst_cluster_time_ms = 1000 * 65536 / devc->samplerate;
+ acquire_msecs += 2 * worst_cluster_time_ms;
+ data = g_variant_new_uint64(acquire_msecs);
+ ret = sr_sw_limits_config_set(&devc->acq_limits,
+ SR_CONF_LIMIT_MSEC, data);
+ g_variant_unref(data);
+ if (ret != SR_OK)
+ return ret;
+
+ sr_sw_limits_acquisition_start(&devc->acq_limits);
+ return SR_OK;
}
-SR_PRIV int sigma_set_samplerate(const struct sr_dev_inst *sdi, uint64_t samplerate)
+/*
+ * Check whether a caller specified samplerate matches the device's
+ * hardware constraints (can be used for acquisition). Optionally yield
+ * a value that approximates the original spec.
+ *
+ * This routine assumes that input specs are in the 200kHz to 200MHz
+ * range of supported rates, and callers typically want to normalize a
+ * given value to the hardware capabilities. Values in the 50MHz range
+ * get rounded up by default, to avoid a more expensive check for the
+ * closest match, while higher sampling rate is always desirable during
+ * measurement. Input specs which exactly match hardware capabilities
+ * remain unaffected. Because 100/200MHz rates also limit the number of
+ * available channels, they are not suggested by this routine, instead
+ * callers need to pick them consciously.
+ */
+SR_PRIV int sigma_normalize_samplerate(uint64_t want_rate, uint64_t *have_rate)
+{
+ uint64_t div, rate;
+
+ /* Accept exact matches for 100/200MHz. */
+ if (want_rate == SR_MHZ(200) || want_rate == SR_MHZ(100)) {
+ if (have_rate)
+ *have_rate = want_rate;
+ return SR_OK;
+ }
+
+ /* Accept 200kHz to 50MHz range, and map to near value. */
+ if (want_rate >= SR_KHZ(200) && want_rate <= SR_MHZ(50)) {
+ div = SR_MHZ(50) / want_rate;
+ rate = SR_MHZ(50) / div;
+ if (have_rate)
+ *have_rate = rate;
+ return SR_OK;
+ }
+
+ return SR_ERR_ARG;
+}
+
+SR_PRIV int sigma_set_samplerate(const struct sr_dev_inst *sdi)
{
struct dev_context *devc;
struct drv_context *drvc;
- size_t i;
+ uint64_t samplerate;
int ret;
int num_channels;
devc = sdi->priv;
drvc = sdi->driver->context;
- ret = SR_OK;
- /* Reject rates that are not in the list of supported rates. */
- for (i = 0; i < samplerates_count; i++) {
- if (samplerates[i] == samplerate)
- break;
- }
- if (i >= samplerates_count || samplerates[i] == 0)
- return SR_ERR_SAMPLERATE;
+ /* Accept any caller specified rate which the hardware supports. */
+ ret = sigma_normalize_samplerate(devc->samplerate, &samplerate);
+ if (ret != SR_OK)
+ return ret;
/*
* Depending on the samplerates of 200/100/50- MHz, specific
*/
num_channels = devc->num_channels;
if (samplerate <= SR_MHZ(50)) {
- ret = upload_firmware(drvc->sr_ctx, 0, devc);
+ ret = upload_firmware(drvc->sr_ctx, devc, SIGMA_FW_50MHZ);
num_channels = 16;
} else if (samplerate == SR_MHZ(100)) {
- ret = upload_firmware(drvc->sr_ctx, 1, devc);
+ ret = upload_firmware(drvc->sr_ctx, devc, SIGMA_FW_100MHZ);
num_channels = 8;
} else if (samplerate == SR_MHZ(200)) {
- ret = upload_firmware(drvc->sr_ctx, 2, devc);
+ ret = upload_firmware(drvc->sr_ctx, devc, SIGMA_FW_200MHZ);
num_channels = 4;
}
/*
- * Derive the sample period from the sample rate as well as the
- * number of samples that the device will communicate within
- * an "event" (memory organization internal to the device).
+ * The samplerate affects the number of available logic channels
+ * as well as a sample memory layout detail (the number of samples
+ * which the device will communicate within an "event").
*/
if (ret == SR_OK) {
devc->num_channels = num_channels;
- devc->cur_samplerate = samplerate;
devc->samples_per_event = 16 / devc->num_channels;
- devc->state.state = SIGMA_IDLE;
- }
-
- /*
- * Support for "limit_samples" is implemented by stopping
- * acquisition after a corresponding period of time.
- * Re-calculate that period of time, in case the limit is
- * set first and the samplerate gets (re-)configured later.
- */
- if (ret == SR_OK && devc->limit_samples) {
- uint64_t msecs;
- msecs = sigma_limit_samples_to_msec(devc, devc->limit_samples);
- devc->limit_msec = msecs;
}
return ret;
struct sr_dev_inst *sdi;
struct sr_datafeed_packet packet;
struct sr_datafeed_logic logic;
- struct sr_sw_limits limit_samples;
};
static int alloc_submit_buffer(struct sr_dev_inst *sdi)
if (!buffer->sample_data)
return SR_ERR_MALLOC;
buffer->write_pointer = buffer->sample_data;
- sr_sw_limits_init(&buffer->limit_samples);
+ sr_sw_limits_init(&devc->feed_limits);
buffer->sdi = sdi;
memset(&buffer->logic, 0, sizeof(buffer->logic));
return SR_OK;
}
-static int setup_submit_buffer(struct dev_context *devc)
+static int setup_submit_limit(struct dev_context *devc)
{
- struct submit_buffer *buffer;
+ struct sr_sw_limits *limits;
int ret;
GVariant *data;
uint64_t total;
- buffer = devc->buffer;
+ limits = &devc->feed_limits;
+
+ ret = sr_sw_limits_config_get(&devc->cfg_limits,
+ SR_CONF_LIMIT_SAMPLES, &data);
+ if (ret != SR_OK)
+ return ret;
+ total = g_variant_get_uint64(data);
+ g_variant_unref(data);
- total = devc->limit_samples;
+ sr_sw_limits_init(limits);
if (total) {
data = g_variant_new_uint64(total);
- ret = sr_sw_limits_config_set(&buffer->limit_samples,
+ ret = sr_sw_limits_config_set(limits,
SR_CONF_LIMIT_SAMPLES, data);
g_variant_unref(data);
if (ret != SR_OK)
return ret;
}
- sr_sw_limits_acquisition_start(&buffer->limit_samples);
+ sr_sw_limits_acquisition_start(limits);
return SR_OK;
}
uint16_t sample, size_t count)
{
struct submit_buffer *buffer;
+ struct sr_sw_limits *limits;
int ret;
buffer = devc->buffer;
- if (sr_sw_limits_check(&buffer->limit_samples))
+ limits = &devc->feed_limits;
+ if (sr_sw_limits_check(limits))
count = 0;
/*
if (ret != SR_OK)
return ret;
}
- sr_sw_limits_update_samples_read(&buffer->limit_samples, 1);
- if (sr_sw_limits_check(&buffer->limit_samples))
+ sr_sw_limits_update_samples_read(limits, 1);
+ if (sr_sw_limits_check(limits))
break;
}
/* Ignore disabled channels with a trigger. */
continue;
channelbit = 1 << (match->channel->index);
- if (devc->cur_samplerate >= SR_MHZ(100)) {
+ if (devc->samplerate >= SR_MHZ(100)) {
/* Fast trigger support. */
if (trigger_set) {
sr_err("Only a single pin trigger is "
sample = 0;
for (i = 0; i < events_in_cluster; i++) {
item16 = sigma_dram_cluster_data(dram_cluster, i);
- if (devc->cur_samplerate == SR_MHZ(200)) {
+ if (devc->samplerate == SR_MHZ(200)) {
sample = sigma_deinterlace_200mhz_data(item16, 0);
check_and_submit_sample(devc, sample, 1, triggered);
sample = sigma_deinterlace_200mhz_data(item16, 1);
check_and_submit_sample(devc, sample, 1, triggered);
sample = sigma_deinterlace_200mhz_data(item16, 3);
check_and_submit_sample(devc, sample, 1, triggered);
- } else if (devc->cur_samplerate == SR_MHZ(100)) {
+ } else if (devc->samplerate == SR_MHZ(100)) {
sample = sigma_deinterlace_100mhz_data(item16, 0);
check_and_submit_sample(devc, sample, 1, triggered);
sample = sigma_deinterlace_100mhz_data(item16, 1);
/* Check if trigger is in this chunk. */
if (trigger_event < EVENTS_PER_ROW) {
- if (devc->cur_samplerate <= SR_MHZ(50)) {
+ if (devc->samplerate <= SR_MHZ(50)) {
trigger_event -= MIN(EVENTS_PER_CLUSTER - 1,
trigger_event);
}
trg_event = triggerpos & 0x1ff;
}
- devc->sent_samples = 0;
-
/*
* Determine how many "DRAM lines" of 1024 bytes each we need to
* retrieve from the Sigma hardware, so that we have a complete
ret = alloc_submit_buffer(sdi);
if (ret != SR_OK)
return FALSE;
- ret = setup_submit_buffer(devc);
+ ret = setup_submit_limit(devc);
if (ret != SR_OK)
return FALSE;
dl_lines_done = 0;
static int sigma_capture_mode(struct sr_dev_inst *sdi)
{
struct dev_context *devc;
- uint64_t running_msec;
- uint64_t current_time;
devc = sdi->priv;
-
- /*
- * Check if the selected sampling duration passed. Sample count
- * limits are covered by this enforced timeout as well.
- */
- current_time = g_get_monotonic_time();
- running_msec = (current_time - devc->start_time) / 1000;
- if (running_msec >= devc->limit_msec)
+ if (sr_sw_limits_check(&devc->acq_limits))
return download_capture(sdi);
return TRUE;