]> sigrok.org Git - libsigrok.git/commitdiff
asix-sigma: rephrase sample memory iteration position and trigger check
authorGerhard Sittig <redacted>
Wed, 27 May 2020 05:06:45 +0000 (07:06 +0200)
committerGerhard Sittig <redacted>
Sun, 31 May 2020 21:46:21 +0000 (23:46 +0200)
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.

src/hardware/asix-sigma/protocol.c
src/hardware/asix-sigma/protocol.h

index ce6974c6ec38a767f6e61bd9766ddbd2ca5837ee..8491d7431af8213616506634cba4f0fed159d2c3 100644 (file)
@@ -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);
index 9fcbdd30f75f21a603a7ffdcf83f5a53570d45ed..ab5f6019a9277f05aed7f2887a5481af7443471c 100644 (file)
@@ -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;