* Values are "channel", "units", "off". Defaults to "units".
*
* time: Whether or not the first column should include the time the sample
- * was taken. Defaults to TRUE.
+ * was taken. Defaults to FALSE.
*
* trigger: Whether or not to add a "trigger" column as the last column.
* Defaults to FALSE.
*
- * dedup: Don't output duplicate rows. Defaults to TRUE. If time is off, then
+ * dedup: Don't output duplicate rows. Defaults to FALSE. If time is off, then
* this is forced to be off.
*/
uint32_t num_samples;
uint32_t channel_count, logic_channel_count;
uint32_t channels_seen;
- uint64_t period;
- uint64_t sample_time;
+ uint64_t sample_rate;
+ uint64_t sample_scale;
+ uint64_t out_sample_count;
uint8_t *previous_sample;
float *analog_samples;
uint8_t *logic_samples;
GString *header;
GSList *channels, *l;
unsigned int num_channels, i;
- uint64_t samplerate = 0, sr;
char *samplerate_s;
ctx = o->priv;
header = g_string_sized_new(512);
- if (ctx->period == 0) {
+ if (ctx->sample_rate == 0) {
if (sr_config_get(o->sdi->driver, o->sdi, NULL,
SR_CONF_SAMPLERATE, &gvar) == SR_OK) {
- samplerate = g_variant_get_uint64(gvar);
+ ctx->sample_rate = g_variant_get_uint64(gvar);
g_variant_unref(gvar);
}
i = 0;
- sr = 1;
- while (sr < samplerate) {
+ ctx->sample_scale = 1;
+ while (ctx->sample_scale < ctx->sample_rate) {
i++;
- sr *= 1000;
+ ctx->sample_scale *= 1000;
}
- if (samplerate)
- ctx->period = sr / samplerate;
if (i < ARRAY_SIZE(xlabels))
ctx->xlabel = xlabels[i];
- sr_info("Set sample period to %" PRIu64 " %s",
- ctx->period, ctx->xlabel);
+ sr_info("Set sample rate, scale to %" PRIu64 ", %" PRIu64 " %s",
+ ctx->sample_rate, ctx->sample_scale, ctx->xlabel);
}
ctx->title = (o->sdi && o->sdi->driver) ? o->sdi->driver->longname : "unknown";
g_string_append_printf(header,
"%s CSV generated by %s %s\n%s from %s on %s",
ctx->comment, PACKAGE_NAME,
- SR_PACKAGE_VERSION_STRING, ctx->comment,
+ sr_package_version_string_get(), ctx->comment,
ctx->title, ctime(&hdr->starttime.tv_sec));
/* Columns / channels */
g_string_truncate(header, header->len - 1);
}
g_string_append_printf(header, "\n");
- if (samplerate != 0) {
- samplerate_s = sr_samplerate_string(samplerate);
+ if (ctx->sample_rate != 0) {
+ samplerate_s = sr_samplerate_string(ctx->sample_rate);
g_string_append_printf(header, "%s Samplerate: %s\n",
ctx->comment, samplerate_s);
g_free(samplerate_s);
ctx->did_header = TRUE;
}
+ /* Time column requested but samplerate unknown. Emit a warning. */
+ if (ctx->time && !ctx->sample_rate)
+ sr_warn("Samplerate unknown, cannot provide timestamps.");
+
return header;
}
const struct sr_datafeed_analog *analog)
{
int ret;
- unsigned int i, j, c, num_channels;
+ size_t num_rcvd_ch, num_have_ch;
+ size_t idx_have, idx_smpl, idx_rcvd;
+ size_t idx_send;
struct sr_analog_meaning *meaning;
GSList *l;
float *fdata = NULL;
+ struct sr_channel *ch;
if (!ctx->analog_samples) {
ctx->analog_samples = g_malloc(analog->num_samples
ctx->num_samples, analog->num_samples);
meaning = analog->meaning;
- num_channels = g_slist_length(meaning->channels);
- ctx->channels_seen += num_channels;
- sr_dbg("Processing packet of %u analog channels", num_channels);
- fdata = g_malloc(analog->num_samples * num_channels * sizeof(float));
+ num_rcvd_ch = g_slist_length(meaning->channels);
+ ctx->channels_seen += num_rcvd_ch;
+ sr_dbg("Processing packet of %zu analog channels", num_rcvd_ch);
+ fdata = g_malloc(analog->num_samples * num_rcvd_ch * sizeof(float));
if ((ret = sr_analog_to_float(analog, fdata)) != SR_OK)
sr_warn("Problems converting data to floating point values.");
- for (i = 0; i < ctx->num_analog_channels + ctx->num_logic_channels; i++) {
- if (ctx->channels[i].ch->type == SR_CHANNEL_ANALOG) {
- sr_dbg("Looking for channel %s",
- ctx->channels[i].ch->name);
- for (l = meaning->channels, c = 0; l; l = l->next, c++) {
- struct sr_channel *ch = l->data;
- sr_dbg("Checking %s", ch->name);
- if (ctx->channels[i].ch == l->data) {
- if (ctx->label_do && !ctx->label_names) {
- sr_analog_unit_to_string(analog,
- &ctx->channels[i].label);
- }
- for (j = 0; j < analog->num_samples; j++)
- ctx->analog_samples[j * ctx->num_analog_channels + i] = fdata[j * num_channels + c];
- break;
- }
+ num_have_ch = ctx->num_analog_channels + ctx->num_logic_channels;
+ idx_send = 0;
+ for (idx_have = 0; idx_have < num_have_ch; idx_have++) {
+ if (ctx->channels[idx_have].ch->type != SR_CHANNEL_ANALOG)
+ continue;
+ sr_dbg("Looking for channel %s",
+ ctx->channels[idx_have].ch->name);
+ for (l = meaning->channels, idx_rcvd = 0; l; l = l->next, idx_rcvd++) {
+ ch = l->data;
+ sr_dbg("Checking %s", ch->name);
+ if (ctx->channels[idx_have].ch != ch)
+ continue;
+ if (ctx->label_do && !ctx->label_names) {
+ sr_analog_unit_to_string(analog,
+ &ctx->channels[idx_have].label);
}
+ for (idx_smpl = 0; idx_smpl < analog->num_samples; idx_smpl++)
+ ctx->analog_samples[idx_smpl * ctx->num_analog_channels + idx_send] = fdata[idx_smpl * num_rcvd_ch + idx_rcvd];
+ break;
}
+ idx_send++;
}
g_free(fdata);
}
static void dump_saved_values(struct context *ctx, GString **out)
{
unsigned int i, j, analog_size, num_channels;
+ double sample_time_dbl;
+ uint64_t sample_time_u64;
float *analog_sample, value;
uint8_t *logic_sample;
if (ctx->label_do) {
if (ctx->time)
g_string_append_printf(*out, "%s%s",
- ctx->label_names ? "Time" :
- ctx->xlabel, ctx->value);
+ ctx->label_names ? "Time" : ctx->xlabel,
+ ctx->value);
for (i = 0; i < num_channels; i++) {
g_string_append_printf(*out, "%s%s",
ctx->channels[i].label, ctx->value);
ctx->previous_sample = g_malloc0(analog_size + ctx->num_logic_channels);
for (i = 0; i < ctx->num_samples; i++) {
- ctx->sample_time += ctx->period;
analog_sample =
&ctx->analog_samples[i * ctx->num_analog_channels];
logic_sample =
analog_sample, analog_size);
}
- if (ctx->time)
+ if (ctx->time && !ctx->sample_rate) {
+ g_string_append_printf(*out, "0%s", ctx->value);
+ } else if (ctx->time) {
+ sample_time_dbl = ctx->out_sample_count++;
+ sample_time_dbl /= ctx->sample_rate;
+ sample_time_dbl *= ctx->sample_scale;
+ sample_time_u64 = sample_time_dbl;
g_string_append_printf(*out, "%" PRIu64 "%s",
- ctx->sample_time, ctx->value);
+ sample_time_u64, ctx->value);
+ }
for (j = 0; j < num_channels; j++) {
if (ctx->channels[j].ch->type == SR_CHANNEL_ANALOG) {
static const struct sr_option *get_options(void)
{
+ GSList *l = NULL;
+
if (!options[0].def) {
options[0].def = g_variant_ref_sink(g_variant_new_string(""));
options[1].def = g_variant_ref_sink(g_variant_new_boolean(TRUE));
options[5].def = g_variant_ref_sink(g_variant_new_string(";"));
options[6].def = g_variant_ref_sink(g_variant_new_boolean(TRUE));
options[7].def = g_variant_ref_sink(g_variant_new_string("units"));
- options[8].def = g_variant_ref_sink(g_variant_new_boolean(TRUE));
+ l = g_slist_append(l, g_variant_ref_sink(g_variant_new_string("units")));
+ l = g_slist_append(l, g_variant_ref_sink(g_variant_new_string("channel")));
+ l = g_slist_append(l, g_variant_ref_sink(g_variant_new_string("off")));
+ options[7].values = l;
+ options[8].def = g_variant_ref_sink(g_variant_new_boolean(FALSE));
options[9].def = g_variant_ref_sink(g_variant_new_boolean(FALSE));
- options[10].def = g_variant_ref_sink(g_variant_new_boolean(TRUE));
+ options[10].def = g_variant_ref_sink(g_variant_new_boolean(FALSE));
}
return options;