* and equidistant rows, there is no fancy support for textual unit
* suffixes nor gaps in the stream of samples nor other non-linearity,
* just '-' ignore the column if the format is not supported).
+ *
+ * IMPORTANT! Make sure the .format_match() logic matches the default
+ * values for the input module's options. Ideally the format match test
+ * shall pass for all input data that is supported by default.
*/
/*
* TODO
*
- * - Extend support for analog input data.
- * - Determine why analog samples of 'double' data type get scrambled
- * in sigrok-cli screen output. Is analog.encoding->unitsize not
- * handled properly? A sigrok-cli or libsigrok (src/output) issue?
- * - Reconsider the channel creation after format processing. Current
- * logic may "bleed" channel names into the analog group when logic
- * channels' columns follow analog columns (seen with "-,2a,x8").
- * Trying to sort it out, a naive change used to map logic channels'
- * data to incorrect bitmap positions. The whole channel numbering
- * needs reconsideration. Probably it's easiest to first create _all_
- * logic channels so that they have adjacent numbers starting at 0
- * (addressing logic bits), then all analog channels (again adjacent)
- * to simplify the calculation of their index in the sample set as
- * well as their sdi channel index from the "analog column index".
- * - Optionally get sample rate from timestamp column. Just best-effort
- * approach, not necessarily reliable. Users can always specify rates.
+ * - Unbreak analog data when submitted in the 'double' data type. This
+ * was observed with sigrok-cli screen output. Is analog.encoding->unitsize
+ * not handled appropriately? Is it a sigrok-cli or libsigrok issue?
* - Add a test suite for input modules in general, and CSV in specific?
* Becomes more important with the multitude of options and their
* interaction. Could cover edge cases (BOM presence, line termination
enum single_col_format text_format;
size_t channel_offset;
size_t channel_count;
- size_t channel_index;
int analog_digits;
+ GString **channel_names;
};
struct context {
csv_analog_t *analog_datafeed_buffer; /**!< Queue for analog datafeed. */
size_t analog_datafeed_buf_size;
size_t analog_datafeed_buf_fill;
- GSList **analog_datafeed_channels;
int *analog_datafeed_digits;
+ GSList **analog_datafeed_channels;
/* Current line number. */
size_t line_number;
char *column;
const char *caption;
int channel_type, channel_sdi_nr;
+ void *channel;
int ret;
inc = in->priv;
inc->column_seen_count = g_strv_length(column_texts);
- /* Split the input spec, count involved columns and bits. */
+ /* Split the input spec, count involved columns and channels. */
formats = g_strsplit(column_format, ",", 0);
if (!formats) {
sr_err("Cannot parse columns format %s (comma split).", column_format);
sr_dbg("Column format %s -> %zu columns, %zu logic, %zu analog channels.",
column_format, column_count, logic_count, analog_count);
- /* Allocate and fill in "column processing" details. Create channels. */
+ /* Allocate and fill in "column processing" details. */
inc->column_want_count = column_count;
if (inc->column_seen_count < inc->column_want_count) {
sr_err("Insufficient input text width for desired data amount, got %zu but want %zu columns.",
g_strfreev(formats);
return SR_ERR_ARG;
}
+ inc->logic_channels = logic_count;
+ inc->analog_channels = analog_count;
+ inc->analog_datafeed_digits = g_malloc0(inc->analog_channels * sizeof(inc->analog_datafeed_digits[0]));
+ inc->analog_datafeed_channels = g_malloc0(inc->analog_channels * sizeof(inc->analog_datafeed_channels[0]));
inc->column_details = g_malloc0_n(column_count, sizeof(inc->column_details[0]));
column_idx = channel_idx = analog_idx = 0;
channel_name = g_string_sized_new(64);
if (!caption || !*caption)
caption = NULL;
/*
- * TODO Need we first create _all_ logic channels,
- * before creating analog channels? Just store the
- * parameters here (index, type, name) and have the
- * creation sequence done outside of the format
- * spec parse loop.
+ * Collect channel creation details here, but defer
+ * actual creation of the channels such that all
+ * logic channels can get created first and analog
+ * channels only get created afterwards.
*/
+ detail->channel_names = g_malloc0(detail->channel_count * sizeof(detail->channel_names[0]));
for (create_idx = 0; create_idx < detail->channel_count; create_idx++) {
if (caption && detail->channel_count == 1) {
g_string_assign(channel_name, caption);
g_string_printf(channel_name, "%zu",
detail->channel_offset + create_idx);
}
- if (format_is_analog(detail->text_format)) {
- channel_sdi_nr = logic_count + detail->channel_offset + create_idx;
- channel_type = SR_CHANNEL_ANALOG;
- detail->channel_index = g_slist_length(in->sdi->channels);
- } else if (format_is_logic(detail->text_format)) {
- channel_sdi_nr = detail->channel_offset + create_idx;
- channel_type = SR_CHANNEL_LOGIC;
- } else {
- continue;
- }
- sr_channel_new(in->sdi, channel_sdi_nr,
- channel_type, TRUE, channel_name->str);
+ detail->channel_names[create_idx] = g_string_new_len(channel_name->str, channel_name->len);
}
}
}
- inc->logic_channels = channel_idx;
- inc->analog_channels = analog_idx;
g_string_free(channel_name, TRUE);
g_strfreev(formats);
+ /* Create channels in strict logic to analog order. */
+ channel_type = SR_CHANNEL_LOGIC;
+ for (column_idx = 0; column_idx < inc->column_want_count; column_idx++) {
+ detail = &inc->column_details[column_idx];
+ if (!format_is_logic(detail->text_format))
+ continue;
+ for (create_idx = 0; create_idx < detail->channel_count; create_idx++) {
+ caption = detail->channel_names[create_idx]->str;
+ channel_sdi_nr = g_slist_length(in->sdi->channels);
+ sr_channel_new(in->sdi, channel_sdi_nr, channel_type, TRUE, caption);
+ }
+ }
+ channel_type = SR_CHANNEL_ANALOG;
+ for (column_idx = 0; column_idx < inc->column_want_count; column_idx++) {
+ detail = &inc->column_details[column_idx];
+ if (!format_is_analog(detail->text_format))
+ continue;
+ caption = detail->channel_names[0]->str;
+ channel_sdi_nr = g_slist_length(in->sdi->channels);
+ channel = sr_channel_new(in->sdi, channel_sdi_nr, channel_type, TRUE, caption);
+ channel_idx = channel_sdi_nr - inc->logic_channels;
+ inc->analog_datafeed_digits[channel_idx] = detail->analog_digits;
+ inc->analog_datafeed_channels[channel_idx] = g_slist_append(NULL, channel);
+ }
+
return SR_OK;
}
if (inc->analog_channels) {
size_t sample_size, sample_count;
- size_t detail_idx;
- struct column_details *detail;
- int *digits_item;
- void *channel;
sample_size = sizeof(inc->analog_datafeed_buffer[0]);
inc->analog_datafeed_buf_size = CHUNK_SIZE;
inc->analog_datafeed_buf_size /= sample_size;
goto out;
}
inc->analog_datafeed_buf_fill = 0;
- inc->analog_datafeed_channels = g_malloc0(inc->analog_channels * sizeof(inc->analog_datafeed_channels[0]));
- inc->analog_datafeed_digits = g_malloc0(inc->analog_channels * sizeof(inc->analog_datafeed_digits[0]));
- digits_item = inc->analog_datafeed_digits;
- for (detail_idx = 0; detail_idx < inc->column_want_count; detail_idx++) {
- detail = &inc->column_details[detail_idx];
- if (!format_is_analog(detail->text_format))
- continue;
- channel = g_slist_nth_data(in->sdi->channels, detail->channel_index);
- inc->analog_datafeed_channels[detail->channel_offset] = g_slist_append(NULL, channel);
- *digits_item++ = detail->analog_digits;
- }
}
out:
const struct column_details *details;
col_parse_cb parse_func;
int ret;
- char *p, **lines, *line, **columns, *column;
+ char *processed_up_to;
+ char **lines, *line, **columns, *column;
inc = in->priv;
if (!inc->started) {
if (!in->buf->len)
return SR_OK;
if (is_eof) {
- p = in->buf->str + in->buf->len;
+ processed_up_to = in->buf->str + in->buf->len;
} else {
- p = g_strrstr_len(in->buf->str, in->buf->len, inc->termination);
- if (!p)
- return SR_ERR;
- *p = '\0';
- p += strlen(inc->termination);
+ processed_up_to = g_strrstr_len(in->buf->str, in->buf->len,
+ inc->termination);
+ if (!processed_up_to)
+ return SR_OK;
+ *processed_up_to = '\0';
+ processed_up_to += strlen(inc->termination);
}
- g_strstrip(in->buf->str);
+ /* Split input text lines and process their columns. */
ret = SR_OK;
lines = g_strsplit(in->buf->str, inc->termination, 0);
for (line_idx = 0; (line = lines[line_idx]); line_idx++) {
g_strfreev(columns);
}
g_strfreev(lines);
- g_string_erase(in->buf, 0, p - in->buf->str);
+ g_string_erase(in->buf, 0, processed_up_to - in->buf->str);
return ret;
}