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. */
uint8_t mask;
GHashTableIter iter;
void *value;
+ struct sr_trigger *trigger;
devc = sdi->priv;
devc->sent_samples = 0;
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;
}
std_session_send_df_end(sdi);
+ if (devc->stl) {
+ soft_trigger_logic_free(devc->stl);
+ devc->stl = NULL;
+ }
+
return SR_OK;
}
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;
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);
}
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) {
#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)
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);