]> sigrok.org Git - libsigrok.git/commitdiff
demo: Implement logic triggering.
authorluftek <redacted>
Tue, 9 Oct 2018 17:20:56 +0000 (19:20 +0200)
committerUwe Hermann <redacted>
Sun, 14 Oct 2018 19:37:40 +0000 (21:37 +0200)
Analog triggers and other items still need more work.

src/hardware/demo/api.c
src/hardware/demo/protocol.c
src/hardware/demo/protocol.h
src/soft-trigger.c

index 32ca88dd106d55da14ac7f5e03b58ddb90214e0c..190dc83637a48ff6fa7c0a68fec0699abb3e2616 100644 (file)
@@ -143,6 +143,8 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options)
        devc->logic_pattern = DEFAULT_LOGIC_PATTERN;
        devc->num_analog_channels = num_analog_channels;
        devc->limit_frames = limit_frames;
+       devc->capture_ratio = 20;
+       devc->stl = NULL;
 
        if (num_logic_channels > 0) {
                /* Logic channels, all in one channel group. */
@@ -434,6 +436,7 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi)
        uint8_t mask;
        GHashTableIter iter;
        void *value;
+       struct sr_trigger *trigger;
 
        devc = sdi->priv;
        devc->sent_samples = 0;
@@ -499,6 +502,18 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi)
        devc->spent_us = 0;
        devc->step = 0;
 
+       /* Store Triggers to stl and preset trigger_fired */
+       if ((trigger = sr_session_trigger_get(sdi->session))) {
+               int pre_trigger_samples = 0;
+               if (devc->limit_samples > 0)
+                       pre_trigger_samples = (devc->capture_ratio * devc->limit_samples) / 100;
+               devc->stl = soft_trigger_logic_new(sdi, trigger, pre_trigger_samples);
+               if (!devc->stl)
+                       return SR_ERR_MALLOC;
+               devc->trigger_fired = FALSE;
+       } else
+               devc->trigger_fired = TRUE;
+
        return SR_OK;
 }
 
@@ -514,6 +529,11 @@ static int dev_acquisition_stop(struct sr_dev_inst *sdi)
 
        std_session_send_df_end(sdi);
 
+       if (devc->stl) {
+               soft_trigger_logic_free(devc->stl);
+               devc->stl = NULL;
+       }
+
        return SR_OK;
 }
 
index 4358d290ce1250a4d3c80b5385f7fa41515f54c9..994c955dbeb1d263f0de83c16804a27d80c174ff 100644 (file)
@@ -456,6 +456,8 @@ SR_PRIV int demo_prepare_data(int fd, int revents, void *cb_data)
        void *value;
        uint64_t samples_todo, logic_done, analog_done, analog_sent, sending_now;
        int64_t elapsed_us, limit_us, todo_us;
+       int64_t trigger_offset;
+       int pre_trigger_samples;
 
        (void)fd;
        (void)revents;
@@ -513,25 +515,39 @@ SR_PRIV int demo_prepare_data(int fd, int revents, void *cb_data)
        analog_done = devc->num_analog_channels > 0 ? 0 : samples_todo;
        if (!devc->enabled_analog_channels)
                analog_done = samples_todo;
-
+       
        while (logic_done < samples_todo || analog_done < samples_todo) {
                /* Logic */
                if (logic_done < samples_todo) {
                        sending_now = MIN(samples_todo - logic_done,
                                        LOGIC_BUFSIZE / devc->logic_unitsize);
                        logic_generator(sdi, sending_now * devc->logic_unitsize);
-                       packet.type = SR_DF_LOGIC;
-                       packet.payload = &logic;
-                       logic.length = sending_now * devc->logic_unitsize;
-                       logic.unitsize = devc->logic_unitsize;
-                       logic.data = devc->logic_data;
-                       logic_fixup_feed(devc, &logic);
-                       sr_session_send(sdi, &packet);
-                       logic_done += sending_now;
+                       /* Trigger */
+                       if (!devc->trigger_fired) {
+                               trigger_offset = soft_trigger_logic_check(devc->stl,
+                                               devc->logic_data, sending_now * devc->logic_unitsize, 
+                                               &pre_trigger_samples);
+                               if (trigger_offset > -1)
+                                       devc->trigger_fired = TRUE;
+                                       logic_done = pre_trigger_samples;
+                       } else
+                               trigger_offset = 0;
+
+                       /* Remaining data */
+                       if (devc->trigger_fired && trigger_offset < (unsigned int)sending_now) {
+                               packet.type = SR_DF_LOGIC;
+                               packet.payload = &logic;
+                               logic.length = (sending_now - trigger_offset) * devc->logic_unitsize;
+                               logic.unitsize = devc->logic_unitsize;
+                               logic.data = devc->logic_data + trigger_offset * devc->logic_unitsize;
+                               logic_fixup_feed(devc, &logic);
+                               sr_session_send(sdi, &packet);
+                               logic_done += sending_now - trigger_offset;
+                       }
                }
 
                /* Analog, one channel at a time */
-               if (analog_done < samples_todo) {
+               if (devc->trigger_fired && analog_done < samples_todo) {
                        analog_sent = 0;
 
                        g_hash_table_iter_init(&iter, devc->ch_ag);
@@ -542,16 +558,17 @@ SR_PRIV int demo_prepare_data(int fd, int revents, void *cb_data)
                        }
                        analog_done += analog_sent;
                }
+
+               /* If trigger didn't happen continue to next iteration
+                * Allow the client to stop this process
+                */
+               if (!devc->trigger_fired)
+                       break;
        }
-       /* At this point, both logic_done and analog_done should be
-        * exactly equal to samples_todo, or else.
-        */
-       if (logic_done != samples_todo || analog_done != samples_todo) {
-               sr_err("BUG: Sample count mismatch.");
-               return G_SOURCE_REMOVE;
-       }
-       devc->sent_samples += samples_todo;
-       devc->sent_frame_samples += samples_todo;
+
+       uint64_t min = MIN(logic_done, analog_done);
+       devc->sent_samples += min;
+       devc->sent_frame_samples += min;
        devc->spent_us += todo_us;
 
        if (devc->limit_frames && devc->sent_frame_samples >= SAMPLES_PER_FRAME) {
index cf1cca60e4207c6a18c8f82b186719bf496e7a53..82fb5d23553829b62604ffcf94e5d67fd602c529 100644 (file)
@@ -119,6 +119,8 @@ struct dev_context {
        uint8_t first_partial_logic_mask;
        /* Triggers */
        uint64_t capture_ratio;
+       gboolean trigger_fired;
+       struct soft_trigger_logic *stl;
 };
 
 static const char *analog_pattern_str[] = {
index c92365e2baf4eb43aea24baf5115d7c871950ea0..d932c65c07d26f9bbc6a9bbbdf0ff20195aa4732 100644 (file)
 #define LOG_PREFIX "soft-trigger"
 /* @endcond */
 
+static size_t logic_channel_unitsize(GSList *channels)
+{
+       size_t number = 0;
+       struct sr_channel *channel;
+       GSList *l;
+
+       for (l = channels; l; l = l->next) {
+               channel = l->data;
+               if (channel->type == SR_CHANNEL_LOGIC)
+                       number += 1;
+       }
+       sr_dbg("number of logic channels: %d", (int) number);
+       return (number + 7) / 8;
+} 
+
+
 SR_PRIV struct soft_trigger_logic *soft_trigger_logic_new(
                const struct sr_dev_inst *sdi, struct sr_trigger *trigger,
                int pre_trigger_samples)
@@ -35,7 +51,8 @@ SR_PRIV struct soft_trigger_logic *soft_trigger_logic_new(
        stl = g_malloc0(sizeof(struct soft_trigger_logic));
        stl->sdi = sdi;
        stl->trigger = trigger;
-       stl->unitsize = (g_slist_length(sdi->channels) + 7) / 8;
+       /* Retreive number of logic channels, unitsize */
+       stl->unitsize = logic_channel_unitsize(sdi->channels);
        stl->prev_sample = g_malloc0(stl->unitsize);
        stl->pre_trigger_size = stl->unitsize * pre_trigger_samples;
        stl->pre_trigger_buffer = g_try_malloc(stl->pre_trigger_size);