asix-sigma: complete and extend capture mode supervision

Parse trigger specs early when acquisition starts, timeout calculation
needs to reflect on it. Either immediately start an acquisition timeout
for trigger-less configurations. Or prepare a timeout which spans the
post-trigger period, but only start its active period when the trigger
match was detected by the device's hardware.

Extend mode tracking during acquisition to handle other special cases.
Terminate acquisition when the user specified sample count limit exceeds
the hardware capacity, or when no limits were specified and the device's
memory is exhausted.

There is a slight inaccuracy in this approach, but the implementation
fails on the safe side. When both user specified limits and triggers are
involved, then at least the user specified time or sample count span is
provided. Usually more data is sent to the session feed, and all of the
requested period is covered. This is because of the software poll period
and the potential to start the timeout slightly late. As well as having
added some slack for hardware pipelines in the timeout calculation.
This commit is contained in:
Gerhard Sittig 2020-05-31 18:38:14 +02:00
parent debe1ff66d
commit f14e6f7e1a
3 changed files with 74 additions and 9 deletions

View File

@ -433,6 +433,13 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi)
devc = sdi->priv;
/* Convert caller's trigger spec to driver's internal format. */
ret = sigma_convert_trigger(sdi);
if (ret != SR_OK) {
sr_err("Could not configure triggers.");
return ret;
}
/*
* Setup the device's samplerate from the value which up to now
* just got checked and stored. As a byproduct this can pick and
@ -455,12 +462,6 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi)
if (ret != SR_OK)
return ret;
ret = sigma_convert_trigger(sdi);
if (ret != SR_OK) {
sr_err("Could not configure triggers.");
return ret;
}
/* Enter trigger programming mode. */
trigsel2 = TRGSEL2_RESET;
ret = sigma_set_register(devc, WRITE_TRIGGER_SELECT2, trigsel2);

View File

@ -939,6 +939,7 @@ SR_PRIV int sigma_set_acquire_timeout(struct dev_context *devc)
uint64_t count_msecs, acquire_msecs;
sr_sw_limits_init(&devc->limit.acquire);
devc->late_trigger_timeout = FALSE;
/* Get sample count limit, convert to msecs. */
ret = sr_sw_limits_config_get(&devc->limit.config,
@ -948,6 +949,10 @@ SR_PRIV int sigma_set_acquire_timeout(struct dev_context *devc)
user_count = g_variant_get_uint64(data);
g_variant_unref(data);
count_msecs = 0;
if (devc->use_triggers) {
user_count *= 100 - devc->capture_ratio;
user_count /= 100;
}
if (user_count)
count_msecs = 1000 * user_count / devc->clock.samplerate + 1;
@ -958,14 +963,18 @@ SR_PRIV int sigma_set_acquire_timeout(struct dev_context *devc)
return ret;
user_msecs = g_variant_get_uint64(data);
g_variant_unref(data);
if (devc->use_triggers) {
user_msecs *= 100 - devc->capture_ratio;
user_msecs /= 100;
}
/* Get the lesser of them, with both being optional. */
acquire_msecs = ~0ull;
acquire_msecs = ~UINT64_C(0);
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)
if (acquire_msecs == ~UINT64_C(0))
return SR_OK;
/* Add some slack, and use that timeout for acquisition. */
@ -978,7 +987,12 @@ SR_PRIV int sigma_set_acquire_timeout(struct dev_context *devc)
if (ret != SR_OK)
return ret;
sr_sw_limits_acquisition_start(&devc->limit.acquire);
/* Deferred or immediate (trigger-less) timeout period start. */
if (devc->use_triggers)
devc->late_trigger_timeout = TRUE;
else
sr_sw_limits_acquisition_start(&devc->limit.acquire);
return SR_OK;
}
@ -2018,10 +2032,59 @@ static int download_capture(struct sr_dev_inst *sdi)
static int sigma_capture_mode(struct sr_dev_inst *sdi)
{
struct dev_context *devc;
int ret;
uint32_t stoppos, triggerpos;
uint8_t mode;
gboolean full, wrapped, triggered, complete;
devc = sdi->priv;
/*
* Get and interpret current acquisition status. Some of these
* thresholds are rather arbitrary.
*/
ret = sigma_read_pos(devc, &stoppos, &triggerpos, &mode);
if (ret != SR_OK)
return FALSE;
stoppos >>= ROW_SHIFT;
full = stoppos >= ROW_COUNT - 2;
wrapped = mode & RMR_ROUND;
triggered = mode & RMR_TRIGGERED;
complete = mode & RMR_POSTTRIGGERED;
/*
* Acquisition completed in the hardware? Start or continue
* sample memory content download.
* (Can user initiated button presses result in auto stop?
* Will they "trigger", and later result in expired time limit
* of post trigger conditions?)
*/
if (complete)
return download_capture(sdi);
/*
* Previously configured acquisition period exceeded? Start
* sample download. Start the timeout period late when triggers
* are used (unknown period from acquisition start to trigger
* match).
*/
if (sr_sw_limits_check(&devc->limit.acquire))
return download_capture(sdi);
if (devc->late_trigger_timeout && triggered) {
sr_sw_limits_acquisition_start(&devc->limit.acquire);
devc->late_trigger_timeout = FALSE;
}
/*
* No trigger specified, and sample memory exhausted? Start
* download (may otherwise keep acquiring, even for infinite
* amounts of time without a user specified time/count limit).
* This handles situations when users specify limits which
* exceed the device's capabilities.
*/
(void)full;
if (!devc->use_triggers && wrapped)
return download_capture(sdi);
return TRUE;
}

View File

@ -386,6 +386,7 @@ struct dev_context {
uint64_t capture_ratio;
struct sigma_trigger trigger;
gboolean use_triggers;
gboolean late_trigger_timeout;
enum {
SIGMA_UNINITIALIZED = 0,
SIGMA_CONFIG,