]> rtime.felk.cvut.cz Git - can-benchmark.git/blob - gw-tests/canalyzer/mdfconv.c
Add MDF to ASCII converter
[can-benchmark.git] / gw-tests / canalyzer / mdfconv.c
1 /* Quick-and-dirt MDF file parser
2  * (c) 2011 Michal Sojka
3  * License: GPLv2+
4  *
5  * MDF Specification: http://www.vector.com/vi_mdf_en.html or
6  * https://www.vector.com/vi_downloadcenter_en.html?busprot=MDF&formular_treffer_submit=1&sprachumschaltung=1
7  */
8
9 #include <stdio.h>
10 #include <stdint.h>
11 #include <stdlib.h>
12 #include <error.h>
13
14 typedef uint32_t link;
15
16 struct idblock {
17         char file_identifier[8];
18         char format_identifier[8];
19         char program_identifier[8];
20         uint16_t default_byte_order;
21         uint16_t version_number;
22         uint16_t code_page_number;
23         char res1[2];
24         char res2[30];
25 } __attribute__((packed));
26
27 struct hdblock {
28         char hd[2];
29         uint16_t block_size;
30         link data_group_block;
31         link file_comment;
32         link program_block;
33         uint16_t number_of_data_groups;
34         char date[10];
35         char time[8];
36         char author[32];
37         char organization[32];
38         char project[32];
39         char subject[32];
40         uint64_t timestamp;
41         int16_t utc_time_offset;
42         uint16_t time_quality_class;
43         char timer_ident[32];
44 } __attribute__((packed));
45
46 struct dgblock {
47         char dg[2];
48         uint16_t block_size;
49         link next_dgblock;
50         link first_channel_group_block;
51         link trigger_block;
52         link data_block;
53         uint16_t num_chn_groups;
54         uint16_t num_rec_ids;
55         uint32_t res;
56 } __attribute__((packed));
57
58 struct cgblock {
59         char cg[2];
60         uint16_t block_size;
61         link next_channel_group_block;
62         link first_channel_block;
63         link comment;
64         uint16_t record_id;
65         uint16_t num_channels;
66         uint16_t size_of_data_record;
67         uint32_t num_records;
68         link first_sample_reduction_block;
69 } __attribute__((packed));
70
71 struct cnblock {
72         char cn[2];
73         uint16_t block_size;
74         link next_channel_block;
75         link conversion_formula;
76         link source_dep_ext;
77         link dependency_block;
78         link comment;
79         uint16_t channel_type;
80         char short_signal_name[32];
81         char signal_description[128];
82         uint16_t start_offset_in_bits;
83         uint16_t number_of_bits;
84         uint16_t signal_data_type;
85 } __attribute__((packed));
86
87 int main(int argc, char *argv[])
88 {
89         FILE *f;
90         struct idblock id;
91         struct hdblock hd;
92         struct dgblock dg;
93         struct cgblock cg;
94         unsigned i, cnidx;
95         struct cnblock *cn[20];
96         link cglink;
97         char *rec;
98
99         if (argc != 2) {
100                 error(1, 0, "Usage: %s <mdf_log_file>", argv[0]);
101         }
102         f = fopen(argv[1], "r");
103         fread(&id, sizeof(id), 1, f);
104         fseek(f, 64, SEEK_SET);
105         fread(&hd, sizeof(hd), 1, f);
106         fseek(f, hd.data_group_block, SEEK_SET);
107         fread(&dg, sizeof(dg), 1, f);
108
109         cglink = dg.first_channel_group_block;
110         while (cglink) {
111                 link cnlink;
112                 fseek(f, cglink, SEEK_SET);
113                 fread(&cg, sizeof(cg), 1, f);
114                 cnlink = cg.first_channel_block;
115                 cnidx = 0;
116                 while (cnlink) {
117                         fseek(f, cnlink, SEEK_SET);
118                         cn[cnidx] = malloc(sizeof(struct cnblock));
119                         fread(cn[cnidx], sizeof(struct cnblock), 1, f);
120                         cnlink = cn[cnidx]->next_channel_block;
121                         cnidx++;
122                 }
123                 cglink = cg.next_channel_group_block;
124         }
125
126         printf("#");
127         for (i=0; i<cnidx; i++) {
128                 struct cnblock *c = cn[i];
129                 printf("%s ", c->short_signal_name);
130         }
131         printf("\n");
132
133         rec = malloc(cg.size_of_data_record);
134
135         fseek(f, dg.data_block, SEEK_SET);
136         int j;
137         for (j=0; j<cg.num_records; j++) {
138                 uint8_t rec_id;
139                 switch (dg.num_rec_ids) {
140                 case 0: rec_id = 0; break;
141                 case 1: fread(&rec_id, sizeof(rec_id), 1, f); break;
142                 default: printf("Unsupported num_rec_ids\n");
143                 }
144                 if (rec_id == cg.record_id) {
145                         fread(rec, cg.size_of_data_record, 1, f);
146                         for (i=0; i<cnidx; i++) {
147                                 struct cnblock *c = cn[i];
148                                 switch (c->signal_data_type) {
149                                 case 0:
150                                         switch(c->number_of_bits) {
151                                         case  8: printf("%hhu", rec[c->start_offset_in_bits/8]); break;
152                                         case 16: printf("%hu", *(uint16_t*)&rec[c->start_offset_in_bits/8]); break;
153                                         case 32: printf("%u", *(uint32_t*)&rec[c->start_offset_in_bits/8]); break;
154                                         default: printf("?size%d", c->number_of_bits);
155                                         }
156                                         break;
157                                 case 1:
158                                         switch(c->number_of_bits) {
159                                         case  8: printf("%hhd", rec[c->start_offset_in_bits/8]); break;
160                                         case 16: printf("%hd", *(int16_t*)&rec[c->start_offset_in_bits/8]); break;
161                                         case 32: printf("%d", *(int32_t*)&rec[c->start_offset_in_bits/8]); break;
162                                         default: printf("?size%d", c->number_of_bits);
163                                         }
164                                         break;
165                                 default:
166                                         printf("?type%d", c->signal_data_type);
167                                 }
168                                 printf(" ");
169                         }
170                         printf("\n");
171                 } else
172                         error(1, 0, "Unknown record id %d\n", rec_id);
173         }
174         return 0;
175 }