forked from Ivasoft/DSView
Add data export(csv only) support @ DSO mode
This commit is contained in:
@@ -601,6 +601,7 @@ static int set_probes(struct sr_dev_inst *sdi, int num_probes)
|
||||
return SR_ERR;
|
||||
if (sdi->mode == DSO) {
|
||||
probe->vdiv = 1000;
|
||||
probe->vfactor = 1;
|
||||
probe->vpos = 0;
|
||||
probe->coupling = SR_DC_COUPLING;
|
||||
probe->trig_value = 0x80;
|
||||
|
||||
@@ -642,6 +642,7 @@ static int set_probes(struct sr_dev_inst *sdi, int num_probes)
|
||||
return SR_ERR;
|
||||
if (sdi->mode == DSO) {
|
||||
probe->vdiv = 1000;
|
||||
probe->vfactor = 1;
|
||||
probe->coupling = SR_DC_COUPLING;
|
||||
probe->trig_value = 0x80;
|
||||
}
|
||||
|
||||
@@ -323,7 +323,7 @@ struct sr_datafeed_dso {
|
||||
uint64_t mqflags;
|
||||
/** The analog value(s). The data is interleaved according to
|
||||
* the probes list. */
|
||||
float *data;
|
||||
void *data;
|
||||
};
|
||||
|
||||
struct sr_datafeed_analog {
|
||||
@@ -559,6 +559,7 @@ struct sr_channel {
|
||||
char *name;
|
||||
char *trigger;
|
||||
uint64_t vdiv;
|
||||
uint16_t vfactor;
|
||||
double vpos;
|
||||
uint8_t coupling;
|
||||
uint8_t trig_value;
|
||||
|
||||
@@ -33,9 +33,13 @@ struct context {
|
||||
char separator;
|
||||
gboolean header_done;
|
||||
int *channel_index;
|
||||
float *channel_vdiv;
|
||||
double *channel_vpos;
|
||||
uint64_t timebase;
|
||||
uint64_t mask;
|
||||
uint64_t pre_data;
|
||||
uint64_t index;
|
||||
int type;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -57,8 +61,6 @@ static int init(struct sr_output *o, GHashTable *options)
|
||||
GSList *l;
|
||||
int i;
|
||||
|
||||
(void)options;
|
||||
|
||||
if (!o || !o->sdi)
|
||||
return SR_ERR_ARG;
|
||||
|
||||
@@ -67,27 +69,34 @@ static int init(struct sr_output *o, GHashTable *options)
|
||||
ctx->separator = ',';
|
||||
ctx->mask = 0;
|
||||
ctx->index = 0;
|
||||
ctx->type = g_variant_get_int16(g_hash_table_lookup(options, "type"));
|
||||
ctx->timebase = g_variant_get_uint64(g_hash_table_lookup(options, "timebase"));
|
||||
|
||||
/* Get the number of channels, and the unitsize. */
|
||||
for (l = o->sdi->channels; l; l = l->next) {
|
||||
ch = l->data;
|
||||
if (ch->type != SR_CHANNEL_LOGIC)
|
||||
if (ch->type != ctx->type)
|
||||
continue;
|
||||
if (!ch->enabled)
|
||||
continue;
|
||||
ctx->num_enabled_channels++;
|
||||
}
|
||||
ctx->channel_index = g_malloc(sizeof(int) * ctx->num_enabled_channels);
|
||||
ctx->channel_vdiv = g_malloc(sizeof(float) * ctx->num_enabled_channels);
|
||||
ctx->channel_vpos = g_malloc(sizeof(double) * ctx->num_enabled_channels);
|
||||
|
||||
/* Once more to map the enabled channels. */
|
||||
for (i = 0, l = o->sdi->channels; l; l = l->next) {
|
||||
ch = l->data;
|
||||
if (ch->type != SR_CHANNEL_LOGIC)
|
||||
if (ch->type != ctx->type)
|
||||
continue;
|
||||
if (!ch->enabled)
|
||||
continue;
|
||||
ctx->channel_index[i++] = ch->index;
|
||||
ctx->channel_index[i] = ch->index;
|
||||
ctx->mask |= (1 << ch->index);
|
||||
ctx->channel_vdiv[i] = ch->vdiv * ch->vfactor >= 500 ? ch->vdiv * ch->vfactor / 100.0f : ch->vdiv * ch->vfactor * 10.0f;
|
||||
ctx->channel_vpos[i] = ch->vdiv * ch->vfactor >= 500 ? ch->vpos / 1000 : ch->vpos;
|
||||
i++;
|
||||
}
|
||||
|
||||
return SR_OK;
|
||||
@@ -102,7 +111,6 @@ static GString *gen_header(const struct sr_output *o)
|
||||
GSList *l;
|
||||
time_t t;
|
||||
int num_channels, i;
|
||||
char *samplerate_s;
|
||||
|
||||
ctx = o->priv;
|
||||
header = g_string_sized_new(512);
|
||||
@@ -113,7 +121,10 @@ static GString *gen_header(const struct sr_output *o)
|
||||
PACKAGE_STRING, ctime(&t));
|
||||
|
||||
/* Columns / channels */
|
||||
num_channels = g_slist_length(o->sdi->channels);
|
||||
if (ctx->type == SR_CHANNEL_LOGIC)
|
||||
num_channels = g_slist_length(o->sdi->channels);
|
||||
else
|
||||
num_channels = ctx->num_enabled_channels;
|
||||
g_string_append_printf(header, "; Channels (%d/%d)\n",
|
||||
ctx->num_enabled_channels, num_channels);
|
||||
|
||||
@@ -125,19 +136,34 @@ static GString *gen_header(const struct sr_output *o)
|
||||
}
|
||||
}
|
||||
if (ctx->samplerate != 0) {
|
||||
samplerate_s = sr_samplerate_string(ctx->samplerate);
|
||||
g_string_append_printf(header, "; Samplerate: %s\n", samplerate_s);
|
||||
char *samplerate_s = sr_samplerate_string(ctx->samplerate);
|
||||
g_string_append_printf(header, "; Sample rate: %s\n", samplerate_s);
|
||||
g_free(samplerate_s);
|
||||
}
|
||||
|
||||
g_string_append_printf(header, "Time(s),");
|
||||
if (sr_config_get(o->sdi->driver, o->sdi, NULL, NULL, SR_CONF_LIMIT_SAMPLES,
|
||||
&gvar) == SR_OK) {
|
||||
uint64_t depth = g_variant_get_uint64(gvar);
|
||||
g_variant_unref(gvar);
|
||||
char *depth_s = sr_samplecount_string(depth);
|
||||
g_string_append_printf(header, "; Sample count: %s\n", depth_s);
|
||||
g_free(depth_s);
|
||||
}
|
||||
|
||||
if (ctx->type == SR_CHANNEL_LOGIC)
|
||||
g_string_append_printf(header, "Time(s),");
|
||||
for (i = 0, l = o->sdi->channels; l; l = l->next, i++) {
|
||||
ch = l->data;
|
||||
if (ch->type != SR_CHANNEL_LOGIC)
|
||||
if (ch->type != ctx->type)
|
||||
continue;
|
||||
if (!ch->enabled)
|
||||
continue;
|
||||
g_string_append_printf(header, " %s,", ch->name);
|
||||
if (ctx->type == SR_CHANNEL_DSO) {
|
||||
char *unit_s = (ch->vdiv * ch->vfactor) >= 500 ? "V" : "mV";
|
||||
g_string_append_printf(header, " %s (Unit: %s),", ch->name, unit_s);
|
||||
} else {
|
||||
g_string_append_printf(header, " %s,", ch->name);
|
||||
}
|
||||
}
|
||||
if (o->sdi->channels)
|
||||
/* Drop last separator. */
|
||||
@@ -152,12 +178,13 @@ static int receive(const struct sr_output *o, const struct sr_datafeed_packet *p
|
||||
{
|
||||
const struct sr_datafeed_meta *meta;
|
||||
const struct sr_datafeed_logic *logic;
|
||||
const struct sr_datafeed_dso *dso;
|
||||
const struct sr_config *src;
|
||||
GSList *l;
|
||||
struct context *ctx;
|
||||
int idx;
|
||||
uint64_t i, j;
|
||||
gchar *p, c;
|
||||
unsigned char *p, c;
|
||||
|
||||
*out = NULL;
|
||||
if (!o || !o->sdi)
|
||||
@@ -200,6 +227,28 @@ static int receive(const struct sr_output *o, const struct sr_datafeed_packet *p
|
||||
ctx->pre_data = (*(uint64_t *)(logic->data + i) & ctx->mask);
|
||||
}
|
||||
break;
|
||||
case SR_DF_DSO:
|
||||
dso = packet->payload;
|
||||
if (!ctx->header_done) {
|
||||
*out = gen_header(o);
|
||||
ctx->header_done = TRUE;
|
||||
} else {
|
||||
*out = g_string_sized_new(512);
|
||||
}
|
||||
|
||||
for (i = 0; i < dso->num_samples; i++) {
|
||||
for (j = 0; j < ctx->num_enabled_channels; j++) {
|
||||
idx = ctx->channel_index[j];
|
||||
p = dso->data + i * ctx->num_enabled_channels + idx * ((ctx->num_enabled_channels > 1) ? 1 : 0);
|
||||
g_string_append_printf(*out, "%0.2f", (128 - *p) * ctx->channel_vdiv[j] / 255 - ctx->channel_vpos[j]);
|
||||
g_string_append_c(*out, ctx->separator);
|
||||
}
|
||||
|
||||
/* Drop last separator. */
|
||||
g_string_truncate(*out, (*out)->len - 1);
|
||||
g_string_append_printf(*out, "\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return SR_OK;
|
||||
|
||||
@@ -141,6 +141,7 @@ SR_API char *sr_iec_string_u64(uint64_t x, const char *unit);
|
||||
SR_API char *sr_samplerate_string(uint64_t samplerate);
|
||||
SR_API char *sr_samplecount_string(uint64_t samplecount);
|
||||
SR_API char *sr_period_string(uint64_t frequency);
|
||||
SR_API char *sr_time_string(uint64_t time);
|
||||
SR_API char *sr_voltage_string(uint64_t v_p, uint64_t v_q);
|
||||
SR_API char **sr_parse_triggerstring(const struct sr_dev_inst *sdi,
|
||||
const char *triggerstring);
|
||||
|
||||
@@ -211,6 +211,47 @@ SR_API char *sr_period_string(uint64_t frequency)
|
||||
return o;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a numeric time(ns) value to the "natural" string representation
|
||||
* of its period.
|
||||
*
|
||||
* E.g. a value of 3000000 would be converted to "3 ms", 20000 to "20 us".
|
||||
*
|
||||
* @param time The time in ns.
|
||||
*
|
||||
* @return A g_try_malloc()ed string representation of the time value,
|
||||
* or NULL upon errors. The caller is responsible to g_free() the
|
||||
* memory.
|
||||
*/
|
||||
SR_API char *sr_time_string(uint64_t time)
|
||||
{
|
||||
char *o;
|
||||
int r;
|
||||
|
||||
/* Allocate enough for a uint64_t as string + " ms". */
|
||||
if (!(o = g_try_malloc0(30 + 1))) {
|
||||
sr_err("%s: o malloc failed", __func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (time >= 1000000000)
|
||||
r = snprintf(o, 30, "%" PRIu64 " s", time / 1000000000);
|
||||
else if (time >= 1000000)
|
||||
r = snprintf(o, 30, "%" PRIu64 " ms", time / 1000000);
|
||||
else if (time >= 1000)
|
||||
r = snprintf(o, 30, "%" PRIu64 " us", time / 1000);
|
||||
else
|
||||
r = snprintf(o, 30, "%" PRIu64 " ns", time);
|
||||
|
||||
if (r < 0) {
|
||||
/* Something went wrong... */
|
||||
g_free(o);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a numeric voltage value to the "natural" string representation
|
||||
* of its voltage value. The voltage is specified as a rational number's
|
||||
|
||||
Reference in New Issue
Block a user