fx2lafw: Imported software triggering from fx2lafw

This commit is contained in:
Joel Holdsworth 2012-03-21 20:42:41 +00:00
parent 97fbf6704e
commit 6c6781b6a7
2 changed files with 132 additions and 15 deletions

View File

@ -243,6 +243,50 @@ static void close_dev(struct sr_dev_inst *sdi)
sdi->status = SR_ST_INACTIVE;
}
static int configure_probes(struct context *ctx, GSList *probes)
{
struct sr_probe *probe;
GSList *l;
int probe_bit, stage, i;
char *tc;
for (i = 0; i < NUM_TRIGGER_STAGES; i++) {
ctx->trigger_mask[i] = 0;
ctx->trigger_value[i] = 0;
}
stage = -1;
for (l = probes; l; l = l->next) {
probe = (struct sr_probe *)l->data;
if (probe->enabled == FALSE)
continue;
probe_bit = 1 << (probe->index - 1);
if (!(probe->trigger))
continue;
stage = 0;
for (tc = probe->trigger; *tc; tc++) {
ctx->trigger_mask[stage] |= probe_bit;
if (*tc == '1')
ctx->trigger_value[stage] |= probe_bit;
stage++;
if (stage > NUM_TRIGGER_STAGES)
return SR_ERR;
}
}
if (stage == -1)
/*
* We didn't configure any triggers, make sure acquisition
* doesn't wait for any.
*/
ctx->trigger_stage = TRIGGER_FIRED;
else
ctx->trigger_stage = 0;
return SR_OK;
}
static struct context *fx2lafw_device_new(void)
{
struct context *ctx;
@ -252,6 +296,8 @@ static struct context *fx2lafw_device_new(void)
return NULL;
}
ctx->trigger_stage = TRIGGER_FIRED;
return ctx;
}
@ -500,7 +546,7 @@ static int hw_dev_config_set(int dev_index, int hwcap, void *value)
ctx->cur_samplerate = *(uint64_t *)value;
ret = SR_OK;
} else if (hwcap == SR_HWCAP_PROBECONFIG) {
ret = SR_OK;
ret = configure_probes(ctx, (GSList *) value);
} else if (hwcap == SR_HWCAP_LIMIT_SAMPLES) {
ctx->limit_samples = *(uint64_t *)value;
ret = SR_OK;
@ -545,7 +591,7 @@ static void receive_transfer(struct libusb_transfer *transfer)
struct sr_datafeed_packet packet;
struct sr_datafeed_logic logic;
struct context *ctx = transfer->user_data;
int cur_buflen;
int cur_buflen, trigger_offset, i;
unsigned char *cur_buf, *new_buf;
/*
@ -594,19 +640,81 @@ static void receive_transfer(struct libusb_transfer *transfer)
empty_transfer_count = 0;
}
/* Send the incoming transfer to the session bus. */
packet.type = SR_DF_LOGIC;
packet.payload = &logic;
logic.length = cur_buflen;
logic.unitsize = 1;
logic.data = cur_buf;
sr_session_send(ctx->session_dev_id, &packet);
g_free(cur_buf);
trigger_offset = 0;
if (ctx->trigger_stage >= 0) {
for (i = 0; i < cur_buflen; i++) {
ctx->num_samples += cur_buflen;
if (ctx->limit_samples &&
(unsigned int) ctx->num_samples > ctx->limit_samples) {
abort_acquisition(ctx);
if ((cur_buf[i] & ctx->trigger_mask[ctx->trigger_stage]) == ctx->trigger_value[ctx->trigger_stage]) {
/* Match on this trigger stage. */
ctx->trigger_buffer[ctx->trigger_stage] = cur_buf[i];
ctx->trigger_stage++;
if (ctx->trigger_stage == NUM_TRIGGER_STAGES || ctx->trigger_mask[ctx->trigger_stage] == 0) {
/* Match on all trigger stages, we're done. */
trigger_offset = i + 1;
/*
* TODO: Send pre-trigger buffer to session bus.
* Tell the frontend we hit the trigger here.
*/
packet.type = SR_DF_TRIGGER;
packet.payload = NULL;
sr_session_send(ctx->session_dev_id, &packet);
/*
* Send the samples that triggered it, since we're
* skipping past them.
*/
packet.type = SR_DF_LOGIC;
packet.payload = &logic;
logic.length = ctx->trigger_stage;
logic.unitsize = 1;
logic.data = ctx->trigger_buffer;
sr_session_send(ctx->session_dev_id, &packet);
ctx->trigger_stage = TRIGGER_FIRED;
break;
}
return;
}
/*
* We had a match before, but not in the next sample. However, we may
* have a match on this stage in the next bit -- trigger on 0001 will
* fail on seeing 00001, so we need to go back to stage 0 -- but at
* the next sample from the one that matched originally, which the
* counter increment at the end of the loop takes care of.
*/
if (ctx->trigger_stage > 0) {
i -= ctx->trigger_stage;
if (i < -1)
i = -1; /* Oops, went back past this buffer. */
/* Reset trigger stage. */
ctx->trigger_stage = 0;
}
}
}
if (ctx->trigger_stage == TRIGGER_FIRED) {
/* Send the incoming transfer to the session bus. */
packet.type = SR_DF_LOGIC;
packet.payload = &logic;
logic.length = cur_buflen - trigger_offset;
logic.unitsize = 1;
logic.data = cur_buf + trigger_offset;
sr_session_send(ctx->session_dev_id, &packet);
g_free(cur_buf);
ctx->num_samples += cur_buflen;
if (ctx->limit_samples &&
(unsigned int)ctx->num_samples > ctx->limit_samples) {
abort_acquisition(ctx);
}
} else {
/*
* TODO: Buffer pre-trigger data in capture
* ratio-sized buffer.
*/
}
}

View File

@ -22,12 +22,16 @@
#define USB_INTERFACE 0
#define USB_CONFIGURATION 1
#define TRIGGER_TYPES "01rf"
#define NUM_TRIGGER_STAGES 4
#define TRIGGER_TYPES "01"
#define MAX_RENUM_DELAY 3000 /* ms */
#define NUM_SIMUL_TRANSFERS 32
#define MAX_EMPTY_TRANSFERS (NUM_SIMUL_TRANSFERS * 2)
/* Software trigger implementation: positive values indicate trigger stage. */
#define TRIGGER_FIRED -1
struct fx2lafw_profile {
uint16_t vid;
uint16_t pid;
@ -56,6 +60,11 @@ struct context {
uint64_t cur_samplerate;
uint64_t limit_samples;
uint8_t trigger_mask[NUM_TRIGGER_STAGES];
uint8_t trigger_value[NUM_TRIGGER_STAGES];
int trigger_stage;
uint8_t trigger_buffer[NUM_TRIGGER_STAGES];
int num_samples;
void *session_dev_id;