soft-trigger: Add support for pre-triggering.
This commit is contained in:
parent
bc96d5f08f
commit
fe5a735553
|
@ -361,7 +361,7 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi,
|
||||||
|
|
||||||
/* Configure triggers & send header packet */
|
/* Configure triggers & send header packet */
|
||||||
if ((trigger = sr_session_trigger_get(sdi->session))) {
|
if ((trigger = sr_session_trigger_get(sdi->session))) {
|
||||||
devc->stl = soft_trigger_logic_new(sdi, trigger);
|
devc->stl = soft_trigger_logic_new(sdi, trigger, 0);
|
||||||
devc->trigger_fired = FALSE;
|
devc->trigger_fired = FALSE;
|
||||||
} else
|
} else
|
||||||
devc->trigger_fired = TRUE;
|
devc->trigger_fired = TRUE;
|
||||||
|
|
|
@ -67,9 +67,7 @@ SR_PRIV int beaglelogic_receive_data(int fd, int revents, void *cb_data)
|
||||||
} else {
|
} else {
|
||||||
/* Check for trigger */
|
/* Check for trigger */
|
||||||
trigger_offset = soft_trigger_logic_check(devc->stl,
|
trigger_offset = soft_trigger_logic_check(devc->stl,
|
||||||
logic.data,
|
logic.data, packetsize, NULL);
|
||||||
packetsize);
|
|
||||||
|
|
||||||
if (trigger_offset > -1) {
|
if (trigger_offset > -1) {
|
||||||
trigger_offset *= logic.unitsize;
|
trigger_offset *= logic.unitsize;
|
||||||
logic.length = MIN(packetsize - trigger_offset,
|
logic.length = MIN(packetsize - trigger_offset,
|
||||||
|
|
|
@ -567,7 +567,7 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data)
|
||||||
devc->empty_transfer_count = 0;
|
devc->empty_transfer_count = 0;
|
||||||
|
|
||||||
if ((trigger = sr_session_trigger_get(sdi->session))) {
|
if ((trigger = sr_session_trigger_get(sdi->session))) {
|
||||||
devc->stl = soft_trigger_logic_new(sdi, trigger);
|
devc->stl = soft_trigger_logic_new(sdi, trigger, 0);
|
||||||
devc->trigger_fired = FALSE;
|
devc->trigger_fired = FALSE;
|
||||||
} else
|
} else
|
||||||
devc->trigger_fired = TRUE;
|
devc->trigger_fired = TRUE;
|
||||||
|
|
|
@ -458,7 +458,7 @@ SR_PRIV void fx2lafw_receive_transfer(struct libusb_transfer *transfer)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
trigger_offset = soft_trigger_logic_check(devc->stl,
|
trigger_offset = soft_trigger_logic_check(devc->stl,
|
||||||
transfer->buffer, transfer->actual_length);
|
transfer->buffer, transfer->actual_length, NULL);
|
||||||
if (trigger_offset > -1) {
|
if (trigger_offset > -1) {
|
||||||
packet.type = SR_DF_LOGIC;
|
packet.type = SR_DF_LOGIC;
|
||||||
packet.payload = &logic;
|
packet.payload = &logic;
|
||||||
|
|
|
@ -719,7 +719,7 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data)
|
||||||
memset(devc->channel_data, 0, sizeof(devc->channel_data));
|
memset(devc->channel_data, 0, sizeof(devc->channel_data));
|
||||||
|
|
||||||
if ((trigger = sr_session_trigger_get(sdi->session))) {
|
if ((trigger = sr_session_trigger_get(sdi->session))) {
|
||||||
devc->stl = soft_trigger_logic_new(sdi, trigger);
|
devc->stl = soft_trigger_logic_new(sdi, trigger, 0);
|
||||||
devc->trigger_fired = FALSE;
|
devc->trigger_fired = FALSE;
|
||||||
} else
|
} else
|
||||||
devc->trigger_fired = TRUE;
|
devc->trigger_fired = TRUE;
|
||||||
|
|
|
@ -785,7 +785,7 @@ SR_PRIV void logic16_receive_transfer(struct libusb_transfer *transfer)
|
||||||
devc->sent_samples += new_samples;
|
devc->sent_samples += new_samples;
|
||||||
} else {
|
} else {
|
||||||
trigger_offset = soft_trigger_logic_check(devc->stl,
|
trigger_offset = soft_trigger_logic_check(devc->stl,
|
||||||
devc->convbuffer, new_samples * 2);
|
devc->convbuffer, new_samples * 2, NULL);
|
||||||
if (trigger_offset > -1) {
|
if (trigger_offset > -1) {
|
||||||
packet.type = SR_DF_LOGIC;
|
packet.type = SR_DF_LOGIC;
|
||||||
packet.payload = &logic;
|
packet.payload = &logic;
|
||||||
|
|
|
@ -646,13 +646,18 @@ struct soft_trigger_logic {
|
||||||
int unitsize;
|
int unitsize;
|
||||||
int cur_stage;
|
int cur_stage;
|
||||||
uint8_t *prev_sample;
|
uint8_t *prev_sample;
|
||||||
|
uint8_t *pre_trigger_buffer;
|
||||||
|
uint8_t *pre_trigger_head;
|
||||||
|
int pre_trigger_size;
|
||||||
|
int pre_trigger_fill;
|
||||||
};
|
};
|
||||||
|
|
||||||
SR_PRIV struct soft_trigger_logic *soft_trigger_logic_new(
|
SR_PRIV struct soft_trigger_logic *soft_trigger_logic_new(
|
||||||
const struct sr_dev_inst *sdi, struct sr_trigger *trigger);
|
const struct sr_dev_inst *sdi, struct sr_trigger *trigger,
|
||||||
|
int pre_trigger_samples);
|
||||||
SR_PRIV void soft_trigger_logic_free(struct soft_trigger_logic *st);
|
SR_PRIV void soft_trigger_logic_free(struct soft_trigger_logic *st);
|
||||||
SR_PRIV int soft_trigger_logic_check(struct soft_trigger_logic *st, uint8_t *buf,
|
SR_PRIV int soft_trigger_logic_check(struct soft_trigger_logic *st, uint8_t *buf,
|
||||||
int len);
|
int len, int *pre_trigger_samples);
|
||||||
|
|
||||||
/*--- hardware/serial.c -----------------------------------------------------*/
|
/*--- hardware/serial.c -----------------------------------------------------*/
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,8 @@
|
||||||
/* @endcond */
|
/* @endcond */
|
||||||
|
|
||||||
SR_PRIV struct soft_trigger_logic *soft_trigger_logic_new(
|
SR_PRIV struct soft_trigger_logic *soft_trigger_logic_new(
|
||||||
const struct sr_dev_inst *sdi, struct sr_trigger *trigger)
|
const struct sr_dev_inst *sdi, struct sr_trigger *trigger,
|
||||||
|
int pre_trigger_samples)
|
||||||
{
|
{
|
||||||
struct soft_trigger_logic *stl;
|
struct soft_trigger_logic *stl;
|
||||||
|
|
||||||
|
@ -35,16 +36,83 @@ SR_PRIV struct soft_trigger_logic *soft_trigger_logic_new(
|
||||||
stl->trigger = trigger;
|
stl->trigger = trigger;
|
||||||
stl->unitsize = (g_slist_length(sdi->channels) + 7) / 8;
|
stl->unitsize = (g_slist_length(sdi->channels) + 7) / 8;
|
||||||
stl->prev_sample = g_malloc0(stl->unitsize);
|
stl->prev_sample = g_malloc0(stl->unitsize);
|
||||||
|
stl->pre_trigger_size = stl->unitsize * pre_trigger_samples;
|
||||||
|
stl->pre_trigger_buffer = g_malloc(stl->pre_trigger_size);
|
||||||
|
stl->pre_trigger_head = stl->pre_trigger_buffer;
|
||||||
|
|
||||||
|
if (stl->pre_trigger_size > 0 && stl->pre_trigger_buffer == NULL) {
|
||||||
|
soft_trigger_logic_free(stl);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return stl;
|
return stl;
|
||||||
}
|
}
|
||||||
|
|
||||||
SR_PRIV void soft_trigger_logic_free(struct soft_trigger_logic *stl)
|
SR_PRIV void soft_trigger_logic_free(struct soft_trigger_logic *stl)
|
||||||
{
|
{
|
||||||
|
g_free(stl->pre_trigger_buffer);
|
||||||
g_free(stl->prev_sample);
|
g_free(stl->prev_sample);
|
||||||
g_free(stl);
|
g_free(stl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void pre_trigger_append(struct soft_trigger_logic *stl,
|
||||||
|
uint8_t *buf, int len)
|
||||||
|
{
|
||||||
|
/* Avoid uselessly copying more than the pre-trigger size. */
|
||||||
|
if (len > stl->pre_trigger_size) {
|
||||||
|
buf += len - stl->pre_trigger_size;
|
||||||
|
len = stl->pre_trigger_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update the filling level of the pre-trigger circular buffer. */
|
||||||
|
stl->pre_trigger_fill = MIN(stl->pre_trigger_fill + len,
|
||||||
|
stl->pre_trigger_size);
|
||||||
|
|
||||||
|
/* Actually copy data to the pre-trigger circular buffer. */
|
||||||
|
while (len > 0) {
|
||||||
|
size_t size = MIN(stl->pre_trigger_buffer + stl->pre_trigger_size
|
||||||
|
- stl->pre_trigger_head, len);
|
||||||
|
memcpy(stl->pre_trigger_head, buf, size);
|
||||||
|
stl->pre_trigger_head += size;
|
||||||
|
if (stl->pre_trigger_head >= stl->pre_trigger_buffer
|
||||||
|
+ stl->pre_trigger_size)
|
||||||
|
stl->pre_trigger_head = stl->pre_trigger_buffer;
|
||||||
|
buf += size;
|
||||||
|
len -= size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pre_trigger_send(struct soft_trigger_logic *stl,
|
||||||
|
int *pre_trigger_samples)
|
||||||
|
{
|
||||||
|
struct sr_datafeed_packet packet;
|
||||||
|
struct sr_datafeed_logic logic;
|
||||||
|
|
||||||
|
packet.type = SR_DF_LOGIC;
|
||||||
|
packet.payload = &logic;
|
||||||
|
logic.unitsize = stl->unitsize;
|
||||||
|
|
||||||
|
if (pre_trigger_samples)
|
||||||
|
*pre_trigger_samples = 0;
|
||||||
|
|
||||||
|
/* If pre-trigger buffer not full, rewind head to the first valid sample. */
|
||||||
|
if (stl->pre_trigger_fill < stl->pre_trigger_size)
|
||||||
|
stl->pre_trigger_head = stl->pre_trigger_buffer;
|
||||||
|
|
||||||
|
/* Send logic packets for the pre-trigger circular buffer content. */
|
||||||
|
while (stl->pre_trigger_fill > 0) {
|
||||||
|
size_t size = MIN(stl->pre_trigger_buffer + stl->pre_trigger_size
|
||||||
|
- stl->pre_trigger_head, stl->pre_trigger_fill);
|
||||||
|
logic.length = size;
|
||||||
|
logic.data = stl->pre_trigger_head;
|
||||||
|
sr_session_send(stl->sdi, &packet);
|
||||||
|
stl->pre_trigger_head = stl->pre_trigger_buffer;
|
||||||
|
stl->pre_trigger_fill -= size;
|
||||||
|
if (pre_trigger_samples)
|
||||||
|
*pre_trigger_samples += size / stl->unitsize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean logic_check_match(struct soft_trigger_logic *stl,
|
static gboolean logic_check_match(struct soft_trigger_logic *stl,
|
||||||
uint8_t *sample, struct sr_trigger_match *match)
|
uint8_t *sample, struct sr_trigger_match *match)
|
||||||
{
|
{
|
||||||
|
@ -80,7 +148,7 @@ static gboolean logic_check_match(struct soft_trigger_logic *stl,
|
||||||
/* Returns the offset (in samples) within buf of where the trigger
|
/* Returns the offset (in samples) within buf of where the trigger
|
||||||
* occurred, or -1 if not triggered. */
|
* occurred, or -1 if not triggered. */
|
||||||
SR_PRIV int soft_trigger_logic_check(struct soft_trigger_logic *stl,
|
SR_PRIV int soft_trigger_logic_check(struct soft_trigger_logic *stl,
|
||||||
uint8_t *buf, int len)
|
uint8_t *buf, int len, int *pre_trigger_samples)
|
||||||
{
|
{
|
||||||
struct sr_datafeed_packet packet;
|
struct sr_datafeed_packet packet;
|
||||||
struct sr_trigger_stage *stage;
|
struct sr_trigger_stage *stage;
|
||||||
|
@ -116,7 +184,11 @@ SR_PRIV int soft_trigger_logic_check(struct soft_trigger_logic *stl,
|
||||||
/* Advance to next stage. */
|
/* Advance to next stage. */
|
||||||
stl->cur_stage++;
|
stl->cur_stage++;
|
||||||
} else {
|
} else {
|
||||||
/* Matched on last stage, fire trigger. */
|
/* Matched on last stage, send pre-trigger data. */
|
||||||
|
pre_trigger_append(stl, buf, i);
|
||||||
|
pre_trigger_send(stl, pre_trigger_samples);
|
||||||
|
|
||||||
|
/* Fire trigger. */
|
||||||
offset = i / stl->unitsize;
|
offset = i / stl->unitsize;
|
||||||
|
|
||||||
packet.type = SR_DF_TRIGGER;
|
packet.type = SR_DF_TRIGGER;
|
||||||
|
@ -142,6 +214,9 @@ SR_PRIV int soft_trigger_logic_check(struct soft_trigger_logic *stl,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (offset == -1)
|
||||||
|
pre_trigger_append(stl, buf, len);
|
||||||
|
|
||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue