From: luftek Date: Tue, 9 Oct 2018 17:20:56 +0000 (+0200) Subject: demo: Implement logic triggering. X-Git-Url: https://sigrok.org/gitaction?a=commitdiff_plain;h=6fc51fb1eeddd7b024a672ef951e760b7b9f697f;p=libsigrok.git demo: Implement logic triggering. Analog triggers and other items still need more work. --- diff --git a/src/hardware/demo/api.c b/src/hardware/demo/api.c index 32ca88dd..190dc836 100644 --- a/src/hardware/demo/api.c +++ b/src/hardware/demo/api.c @@ -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; } diff --git a/src/hardware/demo/protocol.c b/src/hardware/demo/protocol.c index 4358d290..994c955d 100644 --- a/src/hardware/demo/protocol.c +++ b/src/hardware/demo/protocol.c @@ -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) { diff --git a/src/hardware/demo/protocol.h b/src/hardware/demo/protocol.h index cf1cca60..82fb5d23 100644 --- a/src/hardware/demo/protocol.h +++ b/src/hardware/demo/protocol.h @@ -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[] = { diff --git a/src/soft-trigger.c b/src/soft-trigger.c index c92365e2..d932c65c 100644 --- a/src/soft-trigger.c +++ b/src/soft-trigger.c @@ -26,6 +26,22 @@ #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);