soft-trigger: Add support for pre-triggering.

This commit is contained in:
Aurelien Jacobs 2014-11-25 12:23:34 +01:00
parent bc96d5f08f
commit fe5a735553
8 changed files with 91 additions and 13 deletions

View File

@ -361,7 +361,7 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi,
/* Configure triggers & send header packet */
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;
} else
devc->trigger_fired = TRUE;

View File

@ -67,9 +67,7 @@ SR_PRIV int beaglelogic_receive_data(int fd, int revents, void *cb_data)
} else {
/* Check for trigger */
trigger_offset = soft_trigger_logic_check(devc->stl,
logic.data,
packetsize);
logic.data, packetsize, NULL);
if (trigger_offset > -1) {
trigger_offset *= logic.unitsize;
logic.length = MIN(packetsize - trigger_offset,

View File

@ -567,7 +567,7 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data)
devc->empty_transfer_count = 0;
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;
} else
devc->trigger_fired = TRUE;

View File

@ -458,7 +458,7 @@ SR_PRIV void fx2lafw_receive_transfer(struct libusb_transfer *transfer)
}
} else {
trigger_offset = soft_trigger_logic_check(devc->stl,
transfer->buffer, transfer->actual_length);
transfer->buffer, transfer->actual_length, NULL);
if (trigger_offset > -1) {
packet.type = SR_DF_LOGIC;
packet.payload = &logic;

View File

@ -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));
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;
} else
devc->trigger_fired = TRUE;

View File

@ -785,7 +785,7 @@ SR_PRIV void logic16_receive_transfer(struct libusb_transfer *transfer)
devc->sent_samples += new_samples;
} else {
trigger_offset = soft_trigger_logic_check(devc->stl,
devc->convbuffer, new_samples * 2);
devc->convbuffer, new_samples * 2, NULL);
if (trigger_offset > -1) {
packet.type = SR_DF_LOGIC;
packet.payload = &logic;

View File

@ -646,13 +646,18 @@ struct soft_trigger_logic {
int unitsize;
int cur_stage;
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(
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 int soft_trigger_logic_check(struct soft_trigger_logic *st, uint8_t *buf,
int len);
int len, int *pre_trigger_samples);
/*--- hardware/serial.c -----------------------------------------------------*/

View File

@ -26,7 +26,8 @@
/* @endcond */
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;
@ -35,16 +36,83 @@ SR_PRIV struct soft_trigger_logic *soft_trigger_logic_new(
stl->trigger = trigger;
stl->unitsize = (g_slist_length(sdi->channels) + 7) / 8;
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;
}
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);
}
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,
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
* occurred, or -1 if not triggered. */
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_trigger_stage *stage;
@ -116,7 +184,11 @@ SR_PRIV int soft_trigger_logic_check(struct soft_trigger_logic *stl,
/* Advance to next stage. */
stl->cur_stage++;
} 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;
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;
}