1 /* Quick-and-dirt MDF file parser
2 * (c) 2011 Michal Sojka
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
14 typedef uint32_t link;
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;
25 } __attribute__((packed));
30 link data_group_block;
33 uint16_t number_of_data_groups;
37 char organization[32];
41 int16_t utc_time_offset;
42 uint16_t time_quality_class;
44 } __attribute__((packed));
50 link first_channel_group_block;
53 uint16_t num_chn_groups;
56 } __attribute__((packed));
61 link next_channel_group_block;
62 link first_channel_block;
65 uint16_t num_channels;
66 uint16_t size_of_data_record;
68 link first_sample_reduction_block;
69 } __attribute__((packed));
74 link next_channel_block;
75 link conversion_formula;
77 link dependency_block;
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));
87 int main(int argc, char *argv[])
95 struct cnblock *cn[20];
100 error(1, 0, "Usage: %s <mdf_log_file>", argv[0]);
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);
109 cglink = dg.first_channel_group_block;
112 fseek(f, cglink, SEEK_SET);
113 fread(&cg, sizeof(cg), 1, f);
114 cnlink = cg.first_channel_block;
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;
123 cglink = cg.next_channel_group_block;
127 for (i=0; i<cnidx; i++) {
128 struct cnblock *c = cn[i];
129 printf("%s ", c->short_signal_name);
133 rec = malloc(cg.size_of_data_record);
135 fseek(f, dg.data_block, SEEK_SET);
137 for (j=0; j<cg.num_records; j++) {
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");
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) {
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);
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);
166 printf("?type%d", c->signal_data_type);
172 error(1, 0, "Unknown record id %d\n", rec_id);