From: Gerhard Sittig Date: Wed, 27 May 2020 05:06:45 +0000 (+0200) Subject: asix-sigma: rephrase sample memory iteration position and trigger check X-Git-Url: https://sigrok.org/gitaction?a=commitdiff_plain;h=66d1790cc0731d61f97dd11dad3ab7e2d7e799e3;p=libsigrok.git asix-sigma: rephrase sample memory iteration position and trigger check Rephrase how the sample memory iteration position gets tracked, increment after every event slot already. Update the "last seen sample" status more often (an event slot can hold several sample items). Arrange for a period of time where software will check sample data for trigger matches. This improves the precision of the hardware provided trigger match location. Do send hardware provided trigger locations to the session feed even if the software check found no match on the data content. This covers user initiated button presses (which can unblock the acquisition when the application provided trigger condition never matches). Note that this implementation does manage the window of supervision, but does not yet check the sample values against the trigger condition. This gets added later. --- diff --git a/src/hardware/asix-sigma/protocol.c b/src/hardware/asix-sigma/protocol.c index ce6974c6..8491d743 100644 --- a/src/hardware/asix-sigma/protocol.c +++ b/src/hardware/asix-sigma/protocol.c @@ -1290,6 +1290,92 @@ static void sigma_location_break_down(struct sigma_location *loc) loc->cluster = loc->cluster / EVENTS_PER_CLUSTER; } +static gboolean sigma_location_is_eq(struct sigma_location *loc1, + struct sigma_location *loc2, gboolean with_event) +{ + + if (!loc1 || !loc2) + return FALSE; + + if (loc1->line != loc2->line) + return FALSE; + if (loc1->cluster != loc2->cluster) + return FALSE; + + if (with_event && loc1->event != loc2->event) + return FALSE; + + return TRUE; +} + +/* Decrement the broken-down location fields (leave 'raw' as is). */ +static void sigma_location_decrement(struct sigma_location *loc, + gboolean with_event) +{ + + if (!loc) + return; + + if (with_event) { + if (loc->event--) + return; + loc->event = EVENTS_PER_CLUSTER - 1; + } + + if (loc->cluster--) + return; + loc->cluster = CLUSTERS_PER_ROW - 1; + + if (loc->line--) + return; + loc->line = ROW_COUNT - 1; +} + +static void sigma_location_increment(struct sigma_location *loc) +{ + + if (!loc) + return; + + if (++loc->event < EVENTS_PER_CLUSTER) + return; + loc->event = 0; + if (++loc->cluster < CLUSTERS_PER_ROW) + return; + loc->cluster = 0; + if (++loc->line < ROW_COUNT) + return; + loc->line = 0; +} + +/* + * Determine the position where to open the period of trigger match + * checks. Setup an "impossible" location when triggers are not used. + * Start from the hardware provided 'trig' position otherwise, and + * go back a few clusters, but don't go before the 'start' position. + */ +static void rewind_trig_arm_pos(struct dev_context *devc, size_t count) +{ + struct sigma_sample_interp *interp; + + if (!devc) + return; + interp = &devc->interp; + + if (!devc->use_triggers) { + interp->trig_arm.raw = ~0; + sigma_location_break_down(&interp->trig_arm); + return; + } + + interp->trig_arm = interp->trig; + while (count--) { + if (sigma_location_is_eq(&interp->trig_arm, &interp->start, TRUE)) + break; + sigma_location_decrement(&interp->trig_arm, TRUE); + } +} + static int alloc_sample_buffer(struct dev_context *devc, size_t stop_pos, size_t trig_pos, uint8_t mode) { @@ -1329,6 +1415,15 @@ static int alloc_sample_buffer(struct dev_context *devc, sigma_location_break_down(&interp->trig); sigma_location_break_down(&interp->iter); + /* + * The hardware provided trigger location "is late" because of + * latency in hardware pipelines. It points to after the trigger + * condition match. Arrange for a software check of sample data + * matches starting just a little before the hardware provided + * location. The "4 clusters" distance is an arbitrary choice. + */ + rewind_trig_arm_pos(devc, 4 * EVENTS_PER_CLUSTER); + /* Determine which DRAM lines to fetch from the device. */ memset(&interp->fetch, 0, sizeof(interp->fetch)); interp->fetch.lines_total = interp->stop.line + 1; @@ -1547,21 +1642,36 @@ static gboolean sample_matches_trigger(struct dev_context *devc, uint16_t sample return FALSE; } +static int send_trigger_marker(struct dev_context *devc) +{ + int ret; + + ret = flush_submit_buffer(devc); + if (ret != SR_OK) + return ret; + ret = std_session_send_df_trigger(devc->buffer->sdi); + if (ret != SR_OK) + return ret; + + return SR_OK; +} + static int check_and_submit_sample(struct dev_context *devc, uint16_t sample, size_t count, gboolean check_trigger) { gboolean triggered; int ret; + /* + * Ignore the condition provided by the "inner loop" logic of + * sample memory iteration. Instead use device context status + * for the period with software trigger match checks. + */ + check_trigger = devc->interp.trig_chk.armed; + triggered = check_trigger && sample_matches_trigger(devc, sample); - if (triggered) { - ret = flush_submit_buffer(devc); - if (ret != SR_OK) - return ret; - ret = std_session_send_df_trigger(devc->buffer->sdi); - if (ret != SR_OK) - return ret; - } + if (triggered) + send_trigger_marker(devc); ret = addto_submit_buffer(devc, sample, count); if (ret != SR_OK) @@ -1570,6 +1680,46 @@ static int check_and_submit_sample(struct dev_context *devc, return SR_OK; } +static void sigma_location_check(struct dev_context *devc) +{ + struct sigma_sample_interp *interp; + + if (!devc) + return; + interp = &devc->interp; + + /* + * Manage the period of trigger match checks in software. + * Start supervision somewhere before the hardware provided + * location. Stop supervision after an arbitrary amount of + * event slots, or when a match was found. + */ + if (interp->trig_chk.armed) { + interp->trig_chk.evt_remain--; + if (!interp->trig_chk.evt_remain || interp->trig_chk.matched) + interp->trig_chk.armed = FALSE; + } + if (!interp->trig_chk.armed && !interp->trig_chk.matched) { + if (sigma_location_is_eq(&interp->iter, &interp->trig_arm, TRUE)) { + interp->trig_chk.armed = TRUE; + interp->trig_chk.matched = FALSE; + interp->trig_chk.evt_remain = 8 * EVENTS_PER_CLUSTER; + } + } + + /* + * Force a trigger marker when the software check found no match + * yet while the hardware provided position was reached. This + * very probably is a user initiated button press. + */ + if (interp->trig_chk.armed) { + if (sigma_location_is_eq(&interp->iter, &interp->trig, TRUE)) { + (void)send_trigger_marker(devc); + interp->trig_chk.matched = TRUE; + } + } +} + /* * Return the timestamp of "DRAM cluster". */ @@ -1669,23 +1819,31 @@ static void sigma_decode_dram_cluster(struct dev_context *devc, if (devc->interp.samples_per_event == 4) { sample = sigma_deinterlace_data_4x4(item16, 0); check_and_submit_sample(devc, sample, 1, triggered); + devc->interp.last.sample = sample; sample = sigma_deinterlace_data_4x4(item16, 1); check_and_submit_sample(devc, sample, 1, triggered); + devc->interp.last.sample = sample; sample = sigma_deinterlace_data_4x4(item16, 2); check_and_submit_sample(devc, sample, 1, triggered); + devc->interp.last.sample = sample; sample = sigma_deinterlace_data_4x4(item16, 3); check_and_submit_sample(devc, sample, 1, triggered); + devc->interp.last.sample = sample; } else if (devc->interp.samples_per_event == 2) { sample = sigma_deinterlace_data_2x8(item16, 0); check_and_submit_sample(devc, sample, 1, triggered); + devc->interp.last.sample = sample; sample = sigma_deinterlace_data_2x8(item16, 1); check_and_submit_sample(devc, sample, 1, triggered); + devc->interp.last.sample = sample; } else { sample = item16; check_and_submit_sample(devc, sample, 1, triggered); + devc->interp.last.sample = sample; } + sigma_location_increment(&devc->interp.iter); + sigma_location_check(devc); } - devc->interp.last.sample = sample; } /* @@ -1831,8 +1989,6 @@ static int download_capture(struct sr_dev_inst *sdi) dl_events_in_line, trigger_event); interp->fetch.curr_line++; interp->fetch.lines_done++; - interp->iter.line++; - interp->iter.line %= ROW_COUNT; } } flush_submit_buffer(devc); diff --git a/src/hardware/asix-sigma/protocol.h b/src/hardware/asix-sigma/protocol.h index 9fcbdd30..ab5f6019 100644 --- a/src/hardware/asix-sigma/protocol.h +++ b/src/hardware/asix-sigma/protocol.h @@ -369,7 +369,7 @@ struct dev_context { } last; struct sigma_location { size_t raw, line, cluster, event; - } start, stop, trig, iter; + } start, stop, trig, iter, trig_arm; struct { size_t lines_total, lines_done; size_t lines_per_read; /* USB transfer limit */ @@ -377,6 +377,11 @@ struct dev_context { struct sigma_dram_line *rcvd_lines; struct sigma_dram_line *curr_line; } fetch; + struct { + gboolean armed; + gboolean matched; + size_t evt_remain; + } trig_chk; } interp; uint64_t capture_ratio; struct sigma_trigger trigger;