session_file.c \
session_driver.c \
hwdriver.c \
+ trigger.c \
strutil.c \
log.c \
version.c \
for (l = sdi->channels; l; l = l->next) {
ch = l->data;
g_free(ch->name);
- g_free(ch->trigger);
g_free(ch);
}
g_slist_free(sdi->channels);
enum {
/** The enabled state of the channel has been changed. */
SR_CHANNEL_SET_ENABLED = 1 << 0,
- /** The trigger setup of the channel has been changed. */
- SR_CHANNEL_SET_TRIGGER = 1 << 1,
};
SR_PRIV struct sr_channel *sr_channel_new(int index, int type,
GSList *devs;
/** List of struct datafeed_callback pointers. */
GSList *datafeed_callbacks;
+ struct sr_trigger *trigger;
GTimeVal starttime;
gboolean running;
const struct sr_datafeed_packet *packet);
SR_PRIV int sr_session_stop_sync(void);
SR_PRIV int sr_sessionfile_check(const char *filename);
+SR_PRIV struct sr_trigger *sr_session_trigger_get(void);
/*--- std.c -----------------------------------------------------------------*/
SR_MQFLAG_AVG = 0x40000,
};
+enum sr_trigger_matches {
+ SR_TRIGGER_ZERO = 1,
+ SR_TRIGGER_ONE,
+ SR_TRIGGER_RISING,
+ SR_TRIGGER_FALLING,
+ SR_TRIGGER_EDGE,
+ SR_TRIGGER_OVER,
+ SR_TRIGGER_UNDER,
+};
+
+/** The representation of a trigger, consisting of one or more stages
+ * containing one or more matches on a channel.
+ */
+struct sr_trigger {
+ /** A name for this trigger. This may be NULL if none is needed. */
+ char *name;
+ /** List of pointers to struct sr_trigger_stage. */
+ GSList *stages;
+};
+
+/** A trigger stage. */
+struct sr_trigger_stage {
+ /** Starts at 0. */
+ int stage;
+ /** List of pointers to struct sr_trigger_match. */
+ GSList *matches;
+};
+
+/** A channel to match and what to match it on. */
+struct sr_trigger_match {
+ /** The channel to trigger on. */
+ struct sr_channel *channel;
+ /** The trigger match to use.
+ * For logic channels, only the following matches may be used:
+ * SR_TRIGGER_ZERO
+ * SR_TRIGGER_ONE
+ * SR_TRIGGER_RISING
+ * SR_TRIGGER_FALLING
+ * SR_TRIGGER_EDGE
+ *
+ * For analog channels, only these matches may be used:
+ * SR_TRIGGER_RISING
+ * SR_TRIGGER_FALLING
+ * SR_TRIGGER_OVER
+ * SR_TRIGGER_UNDER
+ *
+ */
+ int match;
+ /** If the trigger match is one of SR_TRIGGER_OVER or SR_TRIGGER_UNDER,
+ * this contains the value to compare against. */
+ float value;
+};
+
/**
* @struct sr_context
* Opaque structure representing a libsigrok context.
/** Information on single channel. */
struct sr_channel {
- /** Number of channels, starting at 0. */
+ /** The index of this channel, starting at 0. Logic channels will
+ * be encoded according to this index in SR_DF_LOGIC packets. */
int index;
/** Channel type (SR_CHANNEL_LOGIC, ...) */
int type;
gboolean enabled;
/** Name of channel. */
char *name;
- /** Trigger string, format like used by sigrok-cli */
- char *trigger;
};
/** Structure for groups of channels that have common properties. */
SR_API int sr_session_dev_remove_all(void);
SR_API int sr_session_dev_add(const struct sr_dev_inst *sdi);
SR_API int sr_session_dev_list(GSList **devlist);
+SR_API int sr_session_trigger_set(struct sr_trigger *trig);
/* Datafeed setup */
SR_API int sr_session_datafeed_callback_remove_all(void);
const struct sr_datafeed_packet *packet, GString **out);
SR_API int sr_output_free(struct sr_output *o);
+/*--- trigger.c -------------------------------------------------------------*/
+
+SR_API struct sr_trigger *sr_trigger_new(char *name);
+SR_API void sr_trigger_free(struct sr_trigger *trig);
+SR_API struct sr_trigger_stage *sr_trigger_stage_new(struct sr_trigger *trig);
+SR_API int sr_trigger_match_add(struct sr_trigger_stage *stage,
+ struct sr_channel *ch, int trigger_match, float value);
+
/*--- strutil.c -------------------------------------------------------------*/
SR_API char *sr_si_string_u64(uint64_t x, const char *unit);
return SR_OK;
}
+SR_PRIV struct sr_trigger *sr_session_trigger_get(void)
+{
+ return session->trigger;
+}
+
+SR_API int sr_session_trigger_set(struct sr_trigger *trig)
+{
+ session->trigger = trig;
+
+ return SR_OK;
+}
+
/**
* Call every device in the session's callback.
*
return SR_OK;
}
+
+static int verify_trigger(struct sr_trigger *trigger)
+{
+ struct sr_trigger_stage *stage;
+ struct sr_trigger_match *match;
+ GSList *l, *m;
+
+ if (!trigger->stages) {
+ sr_err("No trigger stages defined.");
+ return SR_ERR;
+ }
+
+ sr_spew("Checking trigger:");
+ for (l = trigger->stages; l; l = l->next) {
+ stage = l->data;
+ if (!stage->matches) {
+ sr_err("Stage %d has no matches defined.", stage->stage);
+ return SR_ERR;
+ }
+ for (m = stage->matches; m; m = m->next) {
+ match = m->data;
+ if (!match->channel) {
+ sr_err("Stage %d match has no channel.", stage->stage);
+ return SR_ERR;
+ }
+ if (!match->match) {
+ sr_err("Stage %d match is not defined.", stage->stage);
+ return SR_ERR;
+ }
+ sr_spew("Stage %d match on channel %s, match %d", stage->stage,
+ match->channel->name, match->match);
+ }
+ }
+
+ return SR_OK;
+}
/**
* Start a session.
*
return SR_ERR_BUG;
}
+ if (session->trigger && verify_trigger(session->trigger) != SR_OK)
+ return SR_ERR;
+
sr_info("Starting.");
ret = SR_OK;
--- /dev/null
+/*
+ * This file is part of the libsigrok project.
+ *
+ * Copyright (C) 2014 Bert Vermeulen <bert@biot.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "libsigrok.h"
+#include "libsigrok-internal.h"
+
+/* * @cond PRIVATE */
+#define LOG_PREFIX "trigger"
+/* * @endcond */
+
+SR_API struct sr_trigger *sr_trigger_new(char *name)
+{
+ struct sr_trigger *trig;
+
+ trig = g_malloc0(sizeof(struct sr_trigger));
+ if (name)
+ trig->name = g_strdup(name);
+
+ return trig;
+}
+
+SR_API void sr_trigger_free(struct sr_trigger *trig)
+{
+ struct sr_trigger_stage *stage;
+ GSList *l;
+
+ for (l = trig->stages; l; l = l->next) {
+ stage = l->data;
+ g_slist_free_full(stage->matches, g_free);
+ }
+ g_slist_free_full(trig->stages, (GDestroyNotify)g_slist_free);
+
+ g_free(trig->name);
+ g_free(trig);
+}
+
+SR_API struct sr_trigger_stage *sr_trigger_stage_new(struct sr_trigger *trig)
+{
+ struct sr_trigger_stage *stage;
+
+ stage = g_malloc0(sizeof(struct sr_trigger_stage));
+ stage->stage = g_slist_length(trig->stages);
+ trig->stages = g_slist_append(trig->stages, stage);
+
+ return stage;
+}
+
+SR_API int sr_trigger_match_add(struct sr_trigger_stage *stage,
+ struct sr_channel *ch, int trigger_match, float value)
+{
+ struct sr_trigger_match *match;
+
+ if (ch->type == SR_CHANNEL_LOGIC) {
+ if (trigger_match != SR_TRIGGER_ZERO &&
+ trigger_match != SR_TRIGGER_ONE &&
+ trigger_match != SR_TRIGGER_RISING &&
+ trigger_match != SR_TRIGGER_FALLING &&
+ trigger_match != SR_TRIGGER_EDGE) {
+ sr_err("Invalid trigger match for a logic channel.");
+ return SR_ERR_ARG;
+ }
+
+
+ } else if (ch->type == SR_CHANNEL_ANALOG) {
+ if (trigger_match != SR_TRIGGER_FALLING &&
+ trigger_match != SR_TRIGGER_OVER &&
+ trigger_match != SR_TRIGGER_UNDER) {
+ sr_err("Invalid trigger match for an analog channel.");
+ return SR_ERR_ARG;
+ }
+ }
+
+ match = g_malloc0(sizeof(struct sr_trigger_match));
+ match->channel = ch;
+ match->match = trigger_match;
+ match->value = value;
+ stage->matches = g_slist_append(stage->matches, match);
+
+ return SR_OK;
+}