demo: implement averaging support
Add support for averaging and avg_samples option to the demo device. Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
This commit is contained in:
parent
9ed444e622
commit
7a8a1aba37
|
@ -4,6 +4,7 @@
|
||||||
* Copyright (C) 2010 Uwe Hermann <uwe@hermann-uwe.de>
|
* Copyright (C) 2010 Uwe Hermann <uwe@hermann-uwe.de>
|
||||||
* Copyright (C) 2011 Olivier Fauchon <olivier@aixmarseille.com>
|
* Copyright (C) 2011 Olivier Fauchon <olivier@aixmarseille.com>
|
||||||
* Copyright (C) 2012 Alexandru Gagniuc <mr.nuke.me@gmail.com>
|
* Copyright (C) 2012 Alexandru Gagniuc <mr.nuke.me@gmail.com>
|
||||||
|
* Copyright (C) 2015 Bartosz Golaszewski <bgolaszewski@baylibre.com>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -103,6 +104,8 @@ struct analog_gen {
|
||||||
float pattern_data[ANALOG_BUFSIZE];
|
float pattern_data[ANALOG_BUFSIZE];
|
||||||
unsigned int num_samples;
|
unsigned int num_samples;
|
||||||
struct sr_datafeed_analog packet;
|
struct sr_datafeed_analog packet;
|
||||||
|
float avg_val; /* Average value */
|
||||||
|
unsigned num_avgs; /* Number of samples averaged */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Private, per-device-instance driver context. */
|
/* Private, per-device-instance driver context. */
|
||||||
|
@ -126,6 +129,8 @@ struct dev_context {
|
||||||
/* Analog */
|
/* Analog */
|
||||||
int32_t num_analog_channels;
|
int32_t num_analog_channels;
|
||||||
GHashTable *ch_ag;
|
GHashTable *ch_ag;
|
||||||
|
gboolean avg; /* True if averaging is enabled */
|
||||||
|
uint64_t avg_samples;
|
||||||
};
|
};
|
||||||
|
|
||||||
static const uint32_t drvopts[] = {
|
static const uint32_t drvopts[] = {
|
||||||
|
@ -144,6 +149,8 @@ static const uint32_t devopts[] = {
|
||||||
SR_CONF_LIMIT_SAMPLES | SR_CONF_GET | SR_CONF_SET,
|
SR_CONF_LIMIT_SAMPLES | SR_CONF_GET | SR_CONF_SET,
|
||||||
SR_CONF_LIMIT_MSEC | SR_CONF_GET | SR_CONF_SET,
|
SR_CONF_LIMIT_MSEC | SR_CONF_GET | SR_CONF_SET,
|
||||||
SR_CONF_SAMPLERATE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
|
SR_CONF_SAMPLERATE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
|
||||||
|
SR_CONF_AVERAGING | SR_CONF_GET | SR_CONF_SET,
|
||||||
|
SR_CONF_AVG_SAMPLES | SR_CONF_GET | SR_CONF_SET,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const uint32_t devopts_cg_logic[] = {
|
static const uint32_t devopts_cg_logic[] = {
|
||||||
|
@ -305,6 +312,8 @@ static GSList *scan(GSList *options)
|
||||||
devc->logic_unitsize = (devc->num_logic_channels + 7) / 8;
|
devc->logic_unitsize = (devc->num_logic_channels + 7) / 8;
|
||||||
devc->logic_pattern = PATTERN_SIGROK;
|
devc->logic_pattern = PATTERN_SIGROK;
|
||||||
devc->num_analog_channels = num_analog_channels;
|
devc->num_analog_channels = num_analog_channels;
|
||||||
|
devc->avg = FALSE;
|
||||||
|
devc->avg_samples = 0;
|
||||||
|
|
||||||
/* Logic channels, all in one channel group. */
|
/* Logic channels, all in one channel group. */
|
||||||
cg = g_malloc0(sizeof(struct sr_channel_group));
|
cg = g_malloc0(sizeof(struct sr_channel_group));
|
||||||
|
@ -347,6 +356,8 @@ static GSList *scan(GSList *options)
|
||||||
ag->packet.unit = SR_UNIT_VOLT;
|
ag->packet.unit = SR_UNIT_VOLT;
|
||||||
ag->packet.data = ag->pattern_data;
|
ag->packet.data = ag->pattern_data;
|
||||||
ag->pattern = pattern;
|
ag->pattern = pattern;
|
||||||
|
ag->avg_val = 0.0f;
|
||||||
|
ag->num_avgs = 0;
|
||||||
g_hash_table_insert(devc->ch_ag, ch, ag);
|
g_hash_table_insert(devc->ch_ag, ch, ag);
|
||||||
|
|
||||||
if (++pattern == ARRAY_SIZE(analog_pattern_str))
|
if (++pattern == ARRAY_SIZE(analog_pattern_str))
|
||||||
|
@ -422,6 +433,12 @@ static int config_get(uint32_t key, GVariant **data, const struct sr_dev_inst *s
|
||||||
case SR_CONF_LIMIT_MSEC:
|
case SR_CONF_LIMIT_MSEC:
|
||||||
*data = g_variant_new_uint64(devc->limit_msec);
|
*data = g_variant_new_uint64(devc->limit_msec);
|
||||||
break;
|
break;
|
||||||
|
case SR_CONF_AVERAGING:
|
||||||
|
*data = g_variant_new_boolean(devc->avg);
|
||||||
|
break;
|
||||||
|
case SR_CONF_AVG_SAMPLES:
|
||||||
|
*data = g_variant_new_uint64(devc->avg_samples);
|
||||||
|
break;
|
||||||
case SR_CONF_PATTERN_MODE:
|
case SR_CONF_PATTERN_MODE:
|
||||||
if (!cg)
|
if (!cg)
|
||||||
return SR_ERR_CHANNEL_GROUP;
|
return SR_ERR_CHANNEL_GROUP;
|
||||||
|
@ -486,6 +503,14 @@ static int config_set(uint32_t key, GVariant *data, const struct sr_dev_inst *sd
|
||||||
devc->limit_samples = 0;
|
devc->limit_samples = 0;
|
||||||
sr_dbg("Setting time limit to %" PRIu64"ms", devc->limit_msec);
|
sr_dbg("Setting time limit to %" PRIu64"ms", devc->limit_msec);
|
||||||
break;
|
break;
|
||||||
|
case SR_CONF_AVERAGING:
|
||||||
|
devc->avg = g_variant_get_boolean(data);
|
||||||
|
sr_dbg("%s averaging", devc->avg ? "Enabling" : "Disabling");
|
||||||
|
break;
|
||||||
|
case SR_CONF_AVG_SAMPLES:
|
||||||
|
devc->avg_samples = g_variant_get_uint64(data);
|
||||||
|
sr_dbg("Setting averaging rate to %" PRIu64, devc->avg_samples);
|
||||||
|
break;
|
||||||
case SR_CONF_PATTERN_MODE:
|
case SR_CONF_PATTERN_MODE:
|
||||||
if (!cg)
|
if (!cg)
|
||||||
return SR_ERR_CHANNEL_GROUP;
|
return SR_ERR_CHANNEL_GROUP;
|
||||||
|
@ -662,6 +687,65 @@ static void logic_generator(struct sr_dev_inst *sdi, uint64_t size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void send_analog_packet(struct analog_gen *ag,
|
||||||
|
struct sr_dev_inst *sdi,
|
||||||
|
uint64_t *analog_sent,
|
||||||
|
uint64_t analog_todo)
|
||||||
|
{
|
||||||
|
struct sr_datafeed_packet packet;
|
||||||
|
struct dev_context *devc;
|
||||||
|
uint64_t sending_now, to_avg;
|
||||||
|
int ag_pattern_pos;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
devc = sdi->priv;
|
||||||
|
packet.type = SR_DF_ANALOG;
|
||||||
|
packet.payload = &ag->packet;
|
||||||
|
|
||||||
|
if (!devc->avg) {
|
||||||
|
ag_pattern_pos = devc->analog_counter % ag->num_samples;
|
||||||
|
sending_now = MIN(analog_todo, ag->num_samples-ag_pattern_pos);
|
||||||
|
ag->packet.data = ag->pattern_data + ag_pattern_pos;
|
||||||
|
ag->packet.num_samples = sending_now;
|
||||||
|
sr_session_send(sdi, &packet);
|
||||||
|
|
||||||
|
/* Whichever channel group gets there first. */
|
||||||
|
*analog_sent = MAX(*analog_sent, sending_now);
|
||||||
|
} else {
|
||||||
|
ag_pattern_pos = devc->analog_counter % ag->num_samples;
|
||||||
|
to_avg = MIN(analog_todo, ag->num_samples-ag_pattern_pos);
|
||||||
|
|
||||||
|
for (i = 0; i < to_avg; i++) {
|
||||||
|
ag->avg_val = (ag->avg_val +
|
||||||
|
*(ag->pattern_data +
|
||||||
|
ag_pattern_pos + i)) / 2;
|
||||||
|
ag->num_avgs++;
|
||||||
|
/* Time to send averaged data? */
|
||||||
|
if (devc->avg_samples > 0 &&
|
||||||
|
ag->num_avgs >= devc->avg_samples)
|
||||||
|
goto do_send;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (devc->avg_samples == 0) {
|
||||||
|
/* We're averaging all the samples, so wait with
|
||||||
|
* sending until the very end.
|
||||||
|
*/
|
||||||
|
*analog_sent = ag->num_avgs;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
do_send:
|
||||||
|
ag->packet.data = &ag->avg_val;
|
||||||
|
ag->packet.num_samples = 1;
|
||||||
|
|
||||||
|
sr_session_send(sdi, &packet);
|
||||||
|
*analog_sent = ag->num_avgs;
|
||||||
|
|
||||||
|
ag->num_avgs = 0;
|
||||||
|
ag->avg_val = 0.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Callback handling data */
|
/* Callback handling data */
|
||||||
static int prepare_data(int fd, int revents, void *cb_data)
|
static int prepare_data(int fd, int revents, void *cb_data)
|
||||||
{
|
{
|
||||||
|
@ -670,7 +754,6 @@ static int prepare_data(int fd, int revents, void *cb_data)
|
||||||
struct sr_datafeed_packet packet;
|
struct sr_datafeed_packet packet;
|
||||||
struct sr_datafeed_logic logic;
|
struct sr_datafeed_logic logic;
|
||||||
struct analog_gen *ag;
|
struct analog_gen *ag;
|
||||||
int ag_pattern_pos;
|
|
||||||
GHashTableIter iter;
|
GHashTableIter iter;
|
||||||
void *value;
|
void *value;
|
||||||
uint64_t logic_todo, analog_todo, expected_samplenum, analog_sent, sending_now;
|
uint64_t logic_todo, analog_todo, expected_samplenum, analog_sent, sending_now;
|
||||||
|
@ -719,17 +802,8 @@ static int prepare_data(int fd, int revents, void *cb_data)
|
||||||
|
|
||||||
g_hash_table_iter_init(&iter, devc->ch_ag);
|
g_hash_table_iter_init(&iter, devc->ch_ag);
|
||||||
while (g_hash_table_iter_next(&iter, NULL, &value)) {
|
while (g_hash_table_iter_next(&iter, NULL, &value)) {
|
||||||
ag = value;
|
send_analog_packet(value, sdi,
|
||||||
packet.type = SR_DF_ANALOG;
|
&analog_sent, analog_todo);
|
||||||
packet.payload = &ag->packet;
|
|
||||||
ag_pattern_pos = devc->analog_counter % ag->num_samples;
|
|
||||||
sending_now = MIN(analog_todo, ag->num_samples-ag_pattern_pos);
|
|
||||||
ag->packet.data = ag->pattern_data + ag_pattern_pos;
|
|
||||||
ag->packet.num_samples = sending_now;
|
|
||||||
sr_session_send(sdi, &packet);
|
|
||||||
|
|
||||||
/* Whichever channel group gets there first. */
|
|
||||||
analog_sent = MAX(analog_sent, sending_now);
|
|
||||||
}
|
}
|
||||||
analog_todo -= analog_sent;
|
analog_todo -= analog_sent;
|
||||||
devc->analog_counter += analog_sent;
|
devc->analog_counter += analog_sent;
|
||||||
|
@ -739,6 +813,19 @@ static int prepare_data(int fd, int revents, void *cb_data)
|
||||||
if (!devc->continuous
|
if (!devc->continuous
|
||||||
&& (!devc->num_logic_channels || devc->logic_counter >= devc->limit_samples)
|
&& (!devc->num_logic_channels || devc->logic_counter >= devc->limit_samples)
|
||||||
&& (!devc->num_analog_channels || devc->analog_counter >= devc->limit_samples)) {
|
&& (!devc->num_analog_channels || devc->analog_counter >= devc->limit_samples)) {
|
||||||
|
/* If we're averaging everything - now is the time to send data */
|
||||||
|
if (devc->avg_samples == 0) {
|
||||||
|
g_hash_table_iter_init(&iter, devc->ch_ag);
|
||||||
|
while (g_hash_table_iter_next(&iter, NULL, &value)) {
|
||||||
|
ag = value;
|
||||||
|
packet.type = SR_DF_ANALOG;
|
||||||
|
packet.payload = &ag->packet;
|
||||||
|
ag->packet.data = &ag->avg_val;
|
||||||
|
ag->packet.num_samples = 1;
|
||||||
|
sr_session_send(sdi, &packet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sr_dbg("Requested number of samples reached.");
|
sr_dbg("Requested number of samples reached.");
|
||||||
dev_acquisition_stop(sdi, cb_data);
|
dev_acquisition_stop(sdi, cb_data);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
Loading…
Reference in New Issue