]> sigrok.org Git - libsigrok.git/blobdiff - src/input/trace32_ad.c
output/csv: use intermediate time_t var, silence compiler warning
[libsigrok.git] / src / input / trace32_ad.c
index 8d4afbdbf6031ffcbdffbdebbf4f7199d42a2723..ba89ad2c41b7479586ae7204762cb1a86a5f7f6b 100644 (file)
@@ -47,7 +47,6 @@
 
 #define CHUNK_SIZE        (4 * 1024 * 1024)
 #define MAX_POD_COUNT     12
-#define HEADER_SIZE       80
 
 #define SPACE             ' '
 #define CTRLZ             '\x1a'
@@ -64,7 +63,8 @@
 
 enum ad_format {
        AD_FORMAT_UNKNOWN,
-       AD_FORMAT_BINHDR,       /* Binary header, binary data, textual setup info */
+       AD_FORMAT_BINHDR1,      /* Binary header, binary data, textual setup info, v1 */
+       AD_FORMAT_BINHDR2,      /* Binary header, binary data, textual setup info, v2 */
        AD_FORMAT_TXTHDR,       /* Textual header, binary data */
 };
 
@@ -96,7 +96,7 @@ struct context {
        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;
+       uint32_t header_size, record_size, record_count, cur_record;
        int32_t last_record;
        uint64_t samplerate;
        double timestamp_scale;
@@ -163,7 +163,7 @@ static int init(struct sr_input *in, GHashTable *options)
 
        /* Calculate the desired timestamp scaling factor. */
        inc->samplerate = 1000000 *
-               g_variant_get_uint32(g_hash_table_lookup(options, "samplerate"));
+               g_variant_get_uint64(g_hash_table_lookup(options, "samplerate"));
 
        inc->timestamp_scale = ((1 / TIMESTAMP_RESOLUTION) / (double)inc->samplerate);
 
@@ -212,14 +212,19 @@ static int process_header(GString *buf, struct context *inc)
        enum ad_format format;
 
        /*
+        * First-level file header:
         * 0x00-1F  file format name
         * 0x20 u64 trigger timestamp
         * 0x28-2F  unused
         * 0x30 u8  compression
         * 0x31-35 ??
         *  0x32 u8 0x00 (PI), 0x01 (iprobe)
-        * 0x36 u8  0x08 (PI 250/500), 0x0A (iprobe 250)
-        * 0x37 u8  0x00 (250), 0x01 (500)
+        * 0x36 u8  device id: 0x08 (PI 250/500), 0x0A (iprobe 250)
+        */
+
+       /*
+        * Second-level file header, version 1:
+        * 0x37 u8  capture speed: 0x00 (250), 0x01 (500)
         * 0x38 u8  record size
         * 0x39-3B  const 0x00
         * 0x3C u32 number of records
@@ -230,6 +235,31 @@ static int process_header(GString *buf, struct context *inc)
         * 0x4E-4F ??
         */
 
+       /*
+        * Second-level file header, version 2:
+        * 0x37 u8  ??
+        * 0x38 u64 ??
+        * 0x40 u64 ??
+        * 0x48 u8  record size
+        * 0x49-4F  ??
+        * 0x50 u64 ??
+        * 0x58 u64 number of records
+        * 0x60 u64 ??
+        * 0x68 u64 ??
+        * 0x70 u64 ??
+        * 0x78 u64 ??
+        * 0x80 u64 ??
+        * 0x88 u64 ?? (timestamp of some kind?)
+        * 0x90 u64 ??
+        * 0x98-9E  ??
+        * 0x9F u8 capture speed: 0x00 (250), 0x01 (500)
+        * 0xA0 u64 ??
+        * 0xA8 u64 ??
+        * 0xB0 u64 ??
+        * 0xB8-CF  version string? (e.g. '93173--96069', same for all tested .ad files)
+        * 0xC8 u16 ??
+        */
+
        /*
         * Note: The routine is called from different contexts. Either
         * to auto-detect the file format (format_match(), 'inc' is NULL),
@@ -260,7 +290,7 @@ static int process_header(GString *buf, struct context *inc)
        format = AD_FORMAT_UNKNOWN;
        if (has_trace32) {
                /* Literal "trace32" leader, binary header follows. */
-               format = AD_FORMAT_BINHDR;
+               format = AD_FORMAT_BINHDR1;
        } else if (g_ascii_isdigit(format_name[0]) && (format_name[1] == SPACE)) {
                /* Digit and SPACE leader, currently unsupported text header. */
                format = AD_FORMAT_TXTHDR;
@@ -278,12 +308,17 @@ static int process_header(GString *buf, struct context *inc)
        if (!format)
                return SR_ERR;
 
+       /* If the device id is 0x00, we have a v2 format file. */
+       if (R8(buf->str + 0x36) == 0x00)
+               format = AD_FORMAT_BINHDR2;
+
        p = printable_name(format_name);
        if (inc)
                sr_dbg("File says it's \"%s\" -> format type %u.", p, format);
        g_free(p);
 
-       record_size = R8(buf->str + 0x38);
+       record_size = (format == AD_FORMAT_BINHDR1) ?
+               R8(buf->str + 0x38) : R8(buf->str + 0x48);
        device_id = 0;
 
        if (g_strcmp0(format_name, "trace32 power integrator data") == 0) {
@@ -312,10 +347,18 @@ static int process_header(GString *buf, struct context *inc)
        inc->device       = device_id;
        inc->trigger_timestamp = RL64(buf->str + 0x20);
        inc->compression  = R8(buf->str + 0x30); /* Maps to the enum. */
-       inc->record_mode  = R8(buf->str + 0x37); /* Maps to the enum. */
+       inc->header_size  = (format == AD_FORMAT_BINHDR1) ? 0x50 : 0xCA;
        inc->record_size  = record_size;
-       inc->record_count = RL32(buf->str + 0x3C);
-       inc->last_record  = RL32S(buf->str + 0x40);
+
+       if (format == AD_FORMAT_BINHDR1) {
+               inc->record_mode  = R8(buf->str + 0x37); /* Maps to the enum. */
+               inc->record_count = RL32(buf->str + 0x3C);
+               inc->last_record  = RL32S(buf->str + 0x40);
+       } else {
+               inc->record_mode  = R8(buf->str + 0x9F); /* Maps to the enum. */
+               inc->record_count = RL32(buf->str + 0x58);
+               inc->last_record  = inc->record_count;
+       }
 
        sr_dbg("Trigger occured at %lf s.",
                inc->trigger_timestamp * TIMESTAMP_RESOLUTION);
@@ -364,21 +407,11 @@ static void create_channels(struct sr_input *in)
 
 static void send_metadata(struct sr_input *in)
 {
-       struct sr_datafeed_packet packet;
-       struct sr_datafeed_meta meta;
-       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(inc->samplerate));
-       meta.config = g_slist_append(NULL, src);
-       sr_session_send(in->sdi, &packet);
-       g_slist_free(meta.config);
-       sr_config_free(src);
-
+       (void)sr_session_send_meta(in->sdi, SR_CONF_SAMPLERATE,
+               g_variant_new_uint64(inc->samplerate));
        inc->meta_sent = TRUE;
 }
 
@@ -404,7 +437,6 @@ static void flush_output_buffer(struct sr_input *in)
 
 static void process_record_pi(struct sr_input *in, gsize start)
 {
-       struct sr_datafeed_packet packet;
        struct context *inc;
        uint64_t timestamp, next_timestamp;
        uint32_t pod_data;
@@ -507,6 +539,7 @@ static void process_record_pi(struct sr_input *in, gsize start)
                        pod_data |= (RL16(buf->str + start + 0x29) & 32) << 11;
                        break;
                default:
+                       pod_data = 0;
                        sr_err("Don't know how to obtain data for pod %d.", pod);
                }
 
@@ -536,10 +569,7 @@ static void process_record_pi(struct sr_input *in, gsize start)
        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);
+               std_session_send_df_trigger(in->sdi);
                inc->trigger_sent = TRUE;
        }
 
@@ -566,7 +596,6 @@ static void process_record_pi(struct sr_input *in, gsize start)
 
 static void process_record_iprobe(struct sr_input *in, gsize start)
 {
-       struct sr_datafeed_packet packet;
        struct context *inc;
        uint64_t timestamp, next_timestamp;
        char single_payload[3];
@@ -589,10 +618,7 @@ static void process_record_iprobe(struct sr_input *in, gsize start)
        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);
+               std_session_send_df_trigger(in->sdi);
                inc->trigger_sent = TRUE;
        }
 
@@ -735,7 +761,7 @@ static int process_buffer(struct sr_input *in)
 
        if (!inc->header_read) {
                res = process_header(in->buf, inc);
-               g_string_erase(in->buf, 0, HEADER_SIZE);
+               g_string_erase(in->buf, 0, inc->header_size);
                if (res != SR_OK)
                        return res;
        }
@@ -865,7 +891,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));
+               options[12].def = g_variant_ref_sink(g_variant_new_uint64(DEFAULT_SAMPLERATE));
        }
 
        return options;