X-Git-Url: https://sigrok.org/gitweb/?a=blobdiff_plain;ds=sidebyside;f=src%2Fhardware%2Fasix-sigma%2Fprotocol.c;h=df59693db0e62841368ed10637db209ac853c02a;hb=HEAD;hp=1d0fc606707a28c31c21b2a2a0eea7b060b812e2;hpb=debe1ff66d6567f0733e74fefc185437e67a7ce2;p=libsigrok.git diff --git a/src/hardware/asix-sigma/protocol.c b/src/hardware/asix-sigma/protocol.c index 1d0fc606..14231651 100644 --- a/src/hardware/asix-sigma/protocol.c +++ b/src/hardware/asix-sigma/protocol.c @@ -625,7 +625,7 @@ static int sigma_fpga_init_bitbang_once(struct dev_context *devc) if (ret != SR_OK) return ret; g_usleep(10 * 1000); - ftdi_usb_purge_buffers(&devc->ftdi.ctx); + PURGE_FTDI_BOTH(&devc->ftdi.ctx); /* * Wait until the FPGA asserts INIT_B. Check in a maximum number @@ -889,7 +889,7 @@ static int upload_firmware(struct sr_context *ctx, struct dev_context *devc, ftdi_get_error_string(&devc->ftdi.ctx)); return SR_ERR; } - ftdi_usb_purge_buffers(&devc->ftdi.ctx); + PURGE_FTDI_BOTH(&devc->ftdi.ctx); while (sigma_read_raw(devc, &pins, sizeof(pins)) > 0) ; @@ -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; } @@ -1498,12 +1512,93 @@ static void free_sample_buffer(struct dev_context *devc) } /* - * In 100 and 200 MHz mode, only a single pin rising/falling can be - * set as trigger. In other modes, two rising/falling triggers can be set, - * in addition to value/mask trigger for any number of channels. + * Parse application provided trigger conditions to the driver's internal + * presentation. Yields a mask of pins of interest, and their expected + * pin levels or edges. + * + * In 100 and 200 MHz mode, only a single pin's rising/falling edge can be + * set as trigger. In 50- MHz modes, two rising/falling edges can be set, + * in addition to value/mask specs for any number of channels. + * + * Hardware implementation detail: When more than one edge is specified, + * then the condition is only considered a match when _all_ transitions + * are seen in the same 20ns check interval, regardless of the user's + * perceived samplerate which can be a fraction of 50MHz. Which reduces + * practical use to edges on a single pin in addition to data patterns. + * Which still covers a lot of users' typical scenarios. Not an issue, + * just something to remain aware of. + * + * The Sigma hardware also supports complex triggers which involve the + * logical combination of several patterns, pulse durations, counts of + * condition matches, A-then-B sequences, etc. But this has not been + * implemented yet here, and applications may lack means to express + * these conditions (present the complex conditions to users for entry + * and review, pass application specs to drivers covering the versatile + * combinations). + * + * Implementor's note: This routine currently exclusively accepts input + * in the form of sr_trigger stages, which results from "01rf-" choices + * on a multitude of individual GUI traces, or the CLI's --trigger spec + * which takes one list of = details. + * + * TODO Consider the addition of SR_CONF_TRIGGER_PATTERN support, which + * accepts a single free form string argument, and could describe a + * multi-bit pattern without the tedious trace name/index selection. + * Fortunately the number of channels is fixed for this device, we need + * not come up with variable length support and counts beyond 64. _When_ + * --trigger as well as SR_CONF_TRIGGER_PATTERN are supported, then the + * implementation needs to come up with priorities for these sources of + * input specs, or enforce exclusive use of either form (at one time, + * per acquisition / invocation). + * + * Text forms that may be worth supporting: + * - Simple forms, mere numbers, optional base specs. These are easiest + * to implement with existing common conversion helpers. + * triggerpattern=[/] + * triggerpattern=255 + * triggerpattern=45054 + * triggerpattern=0xaffe + * triggerpattern=0xa0f0/0xf0f0 + * triggerpattern=0b1010111111111110/0x7ffe + * - Alternative bit pattern form, including wildcards in a single value. + * This cannot use common conversion support, needs special handling. + * triggerpattern=0b1010xxxx1111xxx0 + * This is most similar to SR_CONF_TRIGGER_PATTERN as hameg-hmo uses + * it. Passes the app's spec via SCPI to the device. See section 2.3.5 + * "Pattern trigger" and :TRIG:A:PATT:SOUR in the Hameg document. + * - Prefixed form to tell the above variants apart, and support both of + * them at the same time. Additional optional separator for long digit + * runs, and edge support in the form which lists individual bits (not + * useful for dec/hex formats). + * triggerpattern=value=45054 + * triggerpattern=value=0b1010111111111110 + * triggerpattern=value=0xa0f0,mask=0xf0f0 + * triggerpattern=bits=1010-xxxx-1111-xxxx + * triggerpattern=bits=0010-r100 * - * The Sigma supports complex triggers using boolean expressions, but this - * has not been implemented yet. + * TODO Check this set of processing rules for completeness/correctness. + * - Do implement the prefixed format which covers most use cases, _and_ + * should be usable from CLI and GUI environments. + * - Default to 'bits=' prefix if none was found (and only accept one + * single key/value pair in that case with the default key). + * - Accept dash and space separators in the 'bits=' value. Stick with + * mere unseparated values for value and mask, use common conversion. + * This results in transparent dec/bin/oct/hex support. Underscores? + * - Accept 0/1 binary digits in 'bits=', as well as r/f/e edge specs. + * - Only use --trigger (struct sr_trigger) when SR_CONF_TRIGGER_PATTERN + * is absent? Or always accept --trigger in addition to the data pattern + * spec? Then only accept edge specs from --trigger, since data pattern + * was most importantly motivated by address/data bus inspection? + * - TODO Consider edge= as an optional additional spec in + * the value= and mask= group? Does that help make exclusive support + * for either --trigger or -c triggerpattern acceptable? + * triggerpattern=value=0xa0f0,mask=0xb0f0,edge=15r + * triggerpattern=bits=1r10-xxxx-1111-xxxx + * triggerpattern=1r10-xxxx-1111-xxxx + * - *Any* input spec regardless of format and origin must end up in the + * 'struct sigma_trigger' internal presentation used by this driver. + * It's desirable to have sigma_convert_trigger() do all the parsing, + * and constraint checking in a central location. */ SR_PRIV int sigma_convert_trigger(const struct sr_dev_inst *sdi) { @@ -1513,21 +1608,18 @@ SR_PRIV int sigma_convert_trigger(const struct sr_dev_inst *sdi) struct sr_trigger_match *match; const GSList *l, *m; uint16_t channelbit; - size_t trigger_set; + size_t edge_count; devc = sdi->priv; memset(&devc->trigger, 0, sizeof(devc->trigger)); devc->use_triggers = FALSE; + + /* TODO Consider additional SR_CONF_TRIGGER_PATTERN support. */ trigger = sr_session_trigger_get(sdi->session); if (!trigger) return SR_OK; - if (!ASIX_SIGMA_WITH_TRIGGER) { - sr_warn("Trigger support is not implemented. Ignoring the spec."); - return SR_OK; - } - - trigger_set = 0; + edge_count = 0; for (l = trigger->stages; l; l = l->next) { stage = l->data; for (m = stage->matches; m; m = m->next) { @@ -1538,7 +1630,7 @@ SR_PRIV int sigma_convert_trigger(const struct sr_dev_inst *sdi) channelbit = BIT(match->channel->index); if (devc->clock.samplerate >= SR_MHZ(100)) { /* Fast trigger support. */ - if (trigger_set) { + if (edge_count > 0) { sr_err("100/200MHz modes limited to single trigger pin."); return SR_ERR; } @@ -1551,7 +1643,7 @@ SR_PRIV int sigma_convert_trigger(const struct sr_dev_inst *sdi) return SR_ERR; } - trigger_set++; + edge_count++; } else { /* Simple trigger support (event). */ if (match->match == SR_TRIGGER_ONE) { @@ -1562,10 +1654,10 @@ SR_PRIV int sigma_convert_trigger(const struct sr_dev_inst *sdi) devc->trigger.simplemask |= channelbit; } else if (match->match == SR_TRIGGER_FALLING) { devc->trigger.fallingmask |= channelbit; - trigger_set++; + edge_count++; } else if (match->match == SR_TRIGGER_RISING) { devc->trigger.risingmask |= channelbit; - trigger_set++; + edge_count++; } /* @@ -1573,7 +1665,7 @@ SR_PRIV int sigma_convert_trigger(const struct sr_dev_inst *sdi) * but they are ORed and the current trigger syntax * does not permit ORed triggers. */ - if (trigger_set > 1) { + if (edge_count > 1) { sr_err("Limited to 1 edge trigger."); return SR_ERR; } @@ -2018,10 +2110,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; }