X-Git-Url: https://sigrok.org/gitweb/?a=blobdiff_plain;f=src%2Finput%2Ftrace32_ad.c;h=779c0dac058df5032d4baa5eea006bb55e73d855;hb=cdb134eb19e23528ec9c9dd89805087ea3edb9b6;hp=06fc52146fd376c86f4b556d816791e91085011e;hpb=6d2897e394950bb661a27fd33dbcd14d8c56c61f;p=libsigrok.git diff --git a/src/input/trace32_ad.c b/src/input/trace32_ad.c index 06fc5214..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,18 +78,20 @@ 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 { gboolean meta_sent; - gboolean header_read, records_read; + gboolean header_read, records_read, trigger_sent; char format, device, record_mode, compression; char pod_status[MAX_POD_COUNT]; struct sr_channel *channels[MAX_POD_COUNT][17]; /* 16 + CLK */ 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; } @@ -467,13 +480,14 @@ static void process_record_pi(struct sr_input *in, gsize start) return; } - if (timestamp == inc->trigger_timestamp) { + if (timestamp == inc->trigger_timestamp && !inc->trigger_sent) { sr_dbg("Trigger @%lf s, record #%d.", timestamp * TIMESTAMP_RESOLUTION, inc->cur_record); packet.type = SR_DF_TRIGGER; packet.payload = NULL; sr_session_send(in->sdi, &packet); + inc->trigger_sent = TRUE; } /* Is this the last record in the file? */ @@ -483,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) @@ -493,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); } @@ -519,13 +533,14 @@ static void process_record_iprobe(struct sr_input *in, gsize start) single_payload[2] = R8(in->buf->str + start + 10) & 1; payload_len = 3; - if (timestamp == inc->trigger_timestamp) { + if (timestamp == inc->trigger_timestamp && !inc->trigger_sent) { sr_dbg("Trigger @%lf s, record #%d.", timestamp * TIMESTAMP_RESOLUTION, inc->cur_record); packet.type = SR_DF_TRIGGER; packet.payload = NULL; sr_session_send(in->sdi, &packet); + inc->trigger_sent = TRUE; } /* Is this the last record in the file? */ @@ -535,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) @@ -545,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); } @@ -673,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); } @@ -729,7 +744,6 @@ static int receive(struct sr_input *in, GString *buf) static int end(struct sr_input *in) { struct context *inc; - struct sr_datafeed_packet packet; int ret; inc = in->priv; @@ -741,14 +755,27 @@ static int end(struct sr_input *in) flush_output_buffer(in); - if (inc->meta_sent) { - packet.type = SR_DF_END; - sr_session_send(in->sdi, &packet); - } + if (inc->meta_sent) + 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 }, @@ -764,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 }; @@ -782,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; @@ -798,4 +829,5 @@ SR_PRIV struct sr_input_module input_trace32_ad = { .init = init, .receive = receive, .end = end, + .reset = reset, };