X-Git-Url: https://sigrok.org/gitweb/?a=blobdiff_plain;f=src%2Finput%2Ftrace32_ad.c;h=779c0dac058df5032d4baa5eea006bb55e73d855;hb=cdb134eb19e23528ec9c9dd89805087ea3edb9b6;hp=4ac06cf565c1792b2df0c0b7437e166d8e8f6d80;hpb=3be42bc22f8b36599a448273c12a76d3e0f7a940;p=libsigrok.git diff --git a/src/input/trace32_ad.c b/src/input/trace32_ad.c index 4ac06cf5..779c0dac 100644 --- a/src/input/trace32_ad.c +++ b/src/input/trace32_ad.c @@ -45,20 +45,18 @@ #define LOG_PREFIX "input/trace32_ad" -#define MAX_CHUNK_SIZE 4096 -#define OUTBUF_FLUSH_SIZE 10240 +#define CHUNK_SIZE (4 * 1024 * 1024) #define MAX_POD_COUNT 12 #define HEADER_SIZE 80 -#define TIMESTAMP_RESOLUTION ((double)0.000000000078125) /* 0.078125 ns */ +#define TIMESTAMP_RESOLUTION ((double)0.000000000078125) /* 0.078125 ns */ /* * The resolution equals a sampling freq of 12.8 GHz. That's a bit high * for inter-record sample generation, so we scale it down to 200 MHz * for now. That way, the scaling factor becomes 32. */ -#define SAMPLING_FREQ 200000000 -#define TIMESTAMP_SCALE ((1 / TIMESTAMP_RESOLUTION) / SAMPLING_FREQ) +#define DEFAULT_SAMPLERATE 200 enum { AD_FORMAT_BINHDR = 1, /* Binary header, binary data, textual setup info */ @@ -80,7 +78,7 @@ enum { enum { AD_COMPR_NONE = 0, /* File created with /NOCOMPRESS */ - AD_COMPR_QCOMP = 6 /* File created with /COMPRESS or /QUICKCOMPRESS */ + AD_COMPR_QCOMP = 6, /* File created with /COMPRESS or /QUICKCOMPRESS */ }; struct context { @@ -92,6 +90,8 @@ struct context { uint64_t trigger_timestamp; uint32_t record_size, record_count, cur_record; int32_t last_record; + uint64_t samplerate; + double timestamp_scale; GString *out_buf; }; @@ -130,6 +130,12 @@ static int init(struct sr_input *in, GHashTable *options) inc = in->priv; + /* Calculate the desired timestamp scaling factor. */ + inc->samplerate = 1000000 * + g_variant_get_uint32(g_hash_table_lookup(options, "samplerate")); + + inc->timestamp_scale = ((1 / TIMESTAMP_RESOLUTION) / (double)inc->samplerate); + /* Enable the pods the user chose to see. */ for (pod = 0; pod < MAX_POD_COUNT; pod++) { g_snprintf(id, sizeof(id), "pod%c", get_pod_name_from_id(pod)); @@ -145,7 +151,7 @@ static int init(struct sr_input *in, GHashTable *options) return SR_ERR; } - inc->out_buf = g_string_sized_new(OUTBUF_FLUSH_SIZE); + inc->out_buf = g_string_sized_new(CHUNK_SIZE); return SR_OK; } @@ -207,12 +213,18 @@ static int process_header(GString *buf, struct context *inc) inc->format = AD_FORMAT_TXTHDR; g_free(format_name_sig); g_free(format_name); - sr_err("This format isn't implemented yet, aborting."); + if (inc) + sr_err("This format isn't implemented yet, aborting."); + else + sr_dbg("Not a supported trace32 input file."); return SR_ERR; } else { g_free(format_name_sig); g_free(format_name); - sr_err("Don't know this file format, aborting."); + if (inc) + sr_err("Don't know this file format, aborting."); + else + sr_dbg("Not a trace32 input file."); return SR_ERR; } @@ -246,8 +258,8 @@ static int process_header(GString *buf, struct context *inc) inc->device = device_id; inc->trigger_timestamp = RL64(buf->str + 32); - inc->compression = R8(buf->str + 48); /* Maps to the enum. */ - inc->record_mode = R8(buf->str + 55); /* Maps to the enum. */ + inc->compression = R8(buf->str + 48); /* Maps to the enum. */ + inc->record_mode = R8(buf->str + 55); /* Maps to the enum. */ inc->record_size = record_size; inc->record_count = RL32(buf->str + 60); inc->last_record = RL32S(buf->str + 64); @@ -284,13 +296,13 @@ static void create_channels(struct sr_input *in) continue; for (channel = 0; channel < 16; channel++) { - snprintf(name, 8, "%c%d", get_pod_name_from_id(pod), channel); + snprintf(name, sizeof(name), "%c%d", get_pod_name_from_id(pod), channel); inc->channels[pod][channel] = sr_channel_new(in->sdi, chan_id, SR_CHANNEL_LOGIC, TRUE, name); chan_id++; } - snprintf(name, 8, "CLK%c", get_pod_name_from_id(pod)); + snprintf(name, sizeof(name), "CLK%c", get_pod_name_from_id(pod)); inc->channels[pod][16] = sr_channel_new(in->sdi, chan_id, SR_CHANNEL_LOGIC, TRUE, name); chan_id++; @@ -304,15 +316,16 @@ static void send_metadata(struct sr_input *in) struct sr_config *src; struct context *inc; + inc = in->priv; + packet.type = SR_DF_META; packet.payload = &meta; - src = sr_config_new(SR_CONF_SAMPLERATE, g_variant_new_uint64(SAMPLING_FREQ)); + src = sr_config_new(SR_CONF_SAMPLERATE, g_variant_new_uint64(inc->samplerate)); meta.config = g_slist_append(NULL, src); sr_session_send(in->sdi, &packet); g_slist_free(meta.config); sr_config_free(src); - inc = in->priv; inc->meta_sent = TRUE; } @@ -484,7 +497,7 @@ static void process_record_pi(struct sr_input *in, gsize start) } else { /* It's not, so fill the time gap by sending lots of data. */ next_timestamp = RL64(buf->str + start + inc->record_size); - packet_count = (int)(next_timestamp - timestamp) / TIMESTAMP_SCALE; + packet_count = (int)(next_timestamp - timestamp) / inc->timestamp_scale; /* Make sure we send at least one data set. */ if (packet_count == 0) @@ -494,7 +507,7 @@ static void process_record_pi(struct sr_input *in, gsize start) g_string_append_len(inc->out_buf, single_payload, payload_len); } - if (inc->out_buf->len >= OUTBUF_FLUSH_SIZE) + if (inc->out_buf->len >= CHUNK_SIZE) flush_output_buffer(in); } @@ -537,7 +550,7 @@ static void process_record_iprobe(struct sr_input *in, gsize start) } else { /* It's not, so fill the time gap by sending lots of data. */ next_timestamp = RL64(in->buf->str + start + inc->record_size); - packet_count = (int)(next_timestamp - timestamp) / TIMESTAMP_SCALE; + packet_count = (int)(next_timestamp - timestamp) / inc->timestamp_scale; /* Make sure we send at least one data set. */ if (packet_count == 0) @@ -547,7 +560,7 @@ static void process_record_iprobe(struct sr_input *in, gsize start) g_string_append_len(inc->out_buf, single_payload, payload_len); } - if (inc->out_buf->len >= OUTBUF_FLUSH_SIZE) + if (inc->out_buf->len >= CHUNK_SIZE) flush_output_buffer(in); } @@ -675,7 +688,7 @@ static int process_buffer(struct sr_input *in) } if (!inc->meta_sent) { - std_session_send_df_header(in->sdi, LOG_PREFIX); + std_session_send_df_header(in->sdi); send_metadata(in); } @@ -743,11 +756,26 @@ static int end(struct sr_input *in) flush_output_buffer(in); if (inc->meta_sent) - std_session_send_df_end(in->sdi, LOG_PREFIX); + std_session_send_df_end(in->sdi); return ret; } +static int reset(struct sr_input *in) +{ + struct context *inc = in->priv; + + inc->meta_sent = FALSE; + inc->header_read = FALSE; + inc->records_read = FALSE; + inc->trigger_sent = FALSE; + inc->cur_record = 0; + + g_string_truncate(in->buf, 0); + + return SR_OK; +} + static struct sr_option options[] = { { "podA", "Import pod A / iprobe", "Create channels and data for pod A / iprobe", NULL, NULL }, @@ -763,6 +791,9 @@ static struct sr_option options[] = { { "podM", "Import pod M", "Create channels and data for pod M", NULL, NULL }, { "podN", "Import pod N", "Create channels and data for pod N", NULL, NULL }, { "podO", "Import pod O", "Create channels and data for pod O", NULL, NULL }, + + { "samplerate", "Reduced sample rate (MHz)", "Reduce the original sample rate of 12.8 GHz to the specified sample rate in MHz", NULL, NULL }, + ALL_ZERO }; @@ -781,6 +812,7 @@ static const struct sr_option *get_options(void) options[9].def = g_variant_ref_sink(g_variant_new_boolean(FALSE)); options[10].def = g_variant_ref_sink(g_variant_new_boolean(FALSE)); options[11].def = g_variant_ref_sink(g_variant_new_boolean(FALSE)); + options[12].def = g_variant_ref_sink(g_variant_new_uint32(DEFAULT_SAMPLERATE)); } return options; @@ -797,4 +829,5 @@ SR_PRIV struct sr_input_module input_trace32_ad = { .init = init, .receive = receive, .end = end, + .reset = reset, };