]> rtime.felk.cvut.cz Git - can-benchmark.git/blobdiff - gw-tests/canalyzer/mdfconv.c
Add MDF to ASCII converter
[can-benchmark.git] / gw-tests / canalyzer / mdfconv.c
diff --git a/gw-tests/canalyzer/mdfconv.c b/gw-tests/canalyzer/mdfconv.c
new file mode 100644 (file)
index 0000000..64a32ef
--- /dev/null
@@ -0,0 +1,175 @@
+/* Quick-and-dirt MDF file parser
+ * (c) 2011 Michal Sojka
+ * License: GPLv2+
+ *
+ * MDF Specification: http://www.vector.com/vi_mdf_en.html or
+ * https://www.vector.com/vi_downloadcenter_en.html?busprot=MDF&formular_treffer_submit=1&sprachumschaltung=1
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <error.h>
+
+typedef uint32_t link;
+
+struct idblock {
+       char file_identifier[8];
+       char format_identifier[8];
+       char program_identifier[8];
+       uint16_t default_byte_order;
+       uint16_t version_number;
+       uint16_t code_page_number;
+       char res1[2];
+       char res2[30];
+} __attribute__((packed));
+
+struct hdblock {
+       char hd[2];
+       uint16_t block_size;
+       link data_group_block;
+       link file_comment;
+       link program_block;
+       uint16_t number_of_data_groups;
+       char date[10];
+       char time[8];
+       char author[32];
+       char organization[32];
+       char project[32];
+       char subject[32];
+       uint64_t timestamp;
+       int16_t utc_time_offset;
+       uint16_t time_quality_class;
+       char timer_ident[32];
+} __attribute__((packed));
+
+struct dgblock {
+       char dg[2];
+       uint16_t block_size;
+       link next_dgblock;
+       link first_channel_group_block;
+       link trigger_block;
+       link data_block;
+       uint16_t num_chn_groups;
+       uint16_t num_rec_ids;
+       uint32_t res;
+} __attribute__((packed));
+
+struct cgblock {
+       char cg[2];
+       uint16_t block_size;
+       link next_channel_group_block;
+       link first_channel_block;
+       link comment;
+       uint16_t record_id;
+       uint16_t num_channels;
+       uint16_t size_of_data_record;
+       uint32_t num_records;
+       link first_sample_reduction_block;
+} __attribute__((packed));
+
+struct cnblock {
+       char cn[2];
+       uint16_t block_size;
+       link next_channel_block;
+       link conversion_formula;
+       link source_dep_ext;
+       link dependency_block;
+       link comment;
+       uint16_t channel_type;
+       char short_signal_name[32];
+       char signal_description[128];
+       uint16_t start_offset_in_bits;
+       uint16_t number_of_bits;
+       uint16_t signal_data_type;
+} __attribute__((packed));
+
+int main(int argc, char *argv[])
+{
+       FILE *f;
+       struct idblock id;
+       struct hdblock hd;
+       struct dgblock dg;
+       struct cgblock cg;
+       unsigned i, cnidx;
+       struct cnblock *cn[20];
+       link cglink;
+       char *rec;
+
+       if (argc != 2) {
+               error(1, 0, "Usage: %s <mdf_log_file>", argv[0]);
+       }
+       f = fopen(argv[1], "r");
+       fread(&id, sizeof(id), 1, f);
+       fseek(f, 64, SEEK_SET);
+       fread(&hd, sizeof(hd), 1, f);
+       fseek(f, hd.data_group_block, SEEK_SET);
+       fread(&dg, sizeof(dg), 1, f);
+
+       cglink = dg.first_channel_group_block;
+       while (cglink) {
+               link cnlink;
+               fseek(f, cglink, SEEK_SET);
+               fread(&cg, sizeof(cg), 1, f);
+               cnlink = cg.first_channel_block;
+               cnidx = 0;
+               while (cnlink) {
+                       fseek(f, cnlink, SEEK_SET);
+                       cn[cnidx] = malloc(sizeof(struct cnblock));
+                       fread(cn[cnidx], sizeof(struct cnblock), 1, f);
+                       cnlink = cn[cnidx]->next_channel_block;
+                       cnidx++;
+               }
+               cglink = cg.next_channel_group_block;
+       }
+
+       printf("#");
+       for (i=0; i<cnidx; i++) {
+               struct cnblock *c = cn[i];
+               printf("%s ", c->short_signal_name);
+       }
+       printf("\n");
+
+       rec = malloc(cg.size_of_data_record);
+
+       fseek(f, dg.data_block, SEEK_SET);
+       int j;
+       for (j=0; j<cg.num_records; j++) {
+               uint8_t rec_id;
+               switch (dg.num_rec_ids) {
+               case 0: rec_id = 0; break;
+               case 1: fread(&rec_id, sizeof(rec_id), 1, f); break;
+               default: printf("Unsupported num_rec_ids\n");
+               }
+               if (rec_id == cg.record_id) {
+                       fread(rec, cg.size_of_data_record, 1, f);
+                       for (i=0; i<cnidx; i++) {
+                               struct cnblock *c = cn[i];
+                               switch (c->signal_data_type) {
+                               case 0:
+                                       switch(c->number_of_bits) {
+                                       case  8: printf("%hhu", rec[c->start_offset_in_bits/8]); break;
+                                       case 16: printf("%hu", *(uint16_t*)&rec[c->start_offset_in_bits/8]); break;
+                                       case 32: printf("%u", *(uint32_t*)&rec[c->start_offset_in_bits/8]); break;
+                                       default: printf("?size%d", c->number_of_bits);
+                                       }
+                                       break;
+                               case 1:
+                                       switch(c->number_of_bits) {
+                                       case  8: printf("%hhd", rec[c->start_offset_in_bits/8]); break;
+                                       case 16: printf("%hd", *(int16_t*)&rec[c->start_offset_in_bits/8]); break;
+                                       case 32: printf("%d", *(int32_t*)&rec[c->start_offset_in_bits/8]); break;
+                                       default: printf("?size%d", c->number_of_bits);
+                                       }
+                                       break;
+                               default:
+                                       printf("?type%d", c->signal_data_type);
+                               }
+                               printf(" ");
+                       }
+                       printf("\n");
+               } else
+                       error(1, 0, "Unknown record id %d\n", rec_id);
+       }
+       return 0;
+}