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 */
|
||||
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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 -----------------------------------------------------*/
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue