1 /*
2
3 Copyright (C) 2021 Alois Schloegl <alois.schloegl@gmail.com>
4
5 This file is part of the "BioSig for C/C++" repository
6 (biosig4c++) at http://biosig.sf.net/
7
8 BioSig is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 3
11 of the License, or (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
20
21 */
22
23
24 #include <assert.h>
25 #include <ctype.h>
26 #include <stddef.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30
31 #include "../biosig.h"
32
33 /******************************************************************************
34 read CADWELL file formats (EAS, EZ3, ARC)
35 ******************************************************************************/
sopen_cadwell_read(HDRTYPE * hdr)36 void sopen_cadwell_read(HDRTYPE* hdr) {
37
38 if (VERBOSE_LEVEL > 8) fprintf(stdout,"%s (line %d) %s(hdr)\n", __FILE__, __LINE__, __func__);
39
40 if (hdr->TYPE==EAS) {
41 /* 12 bit ADC ?
42 200 Hz
43 77*800 samples
44 EEGData section has a periodicity of 202*2 (404 bytes)
45 800samples*16channels*2byte=25600 = 0x6400)
46 */
47 hdr->NS = 16; // so far all example files had 16 channels
48 hdr->SPR = 1;
49 hdr->NRec = 0;
50 unsigned lengthHeader0 = leu32p(hdr->AS.Header + 0x30);
51 unsigned lengthHeader1 = leu32p(hdr->AS.Header + 0x34); // this is varying amoung data sets - meaning unknown
52 assert(lengthHeader0==0x0400);
53
54 for (int k=0; k*0x20 < lengthHeader1; k++) {
55 char *sectName = hdr->AS.Header + 0x6c + k*0x20;
56 size_t sectPos= leu32p(hdr->AS.Header + 0x7c + k*0x20);
57 size_t sectN1 = leu32p(hdr->AS.Header + 0x80 + k*0x20);
58 size_t sectN2 = leu32p(hdr->AS.Header + 0x84 + k*0x20);
59 size_t sectN3 = leu32p(hdr->AS.Header + 0x88 + k*0x20);
60
61 if (!sectPos
62 || memcmp("SctHdr\0\0", hdr->AS.Header+sectPos, 8)
63 || memcmp(hdr->AS.Header+sectPos+8, sectName, 16))
64 {
65 if (VERBOSE_LEVEL > 8) fprintf(stdout,"%s (line %d): break loop (0x%x %s)\n",__FILE__,__LINE__, sectPos, sectName);
66 break;
67 }
68
69 uint64_t curSec, nextSec;
70 int flag=1;
71 do {
72 curSec = leu64p(hdr->AS.Header + sectPos + 24);
73 nextSec = leu64p(hdr->AS.Header + sectPos + 32);
74
75 if (VERBOSE_LEVEL > 7) fprintf(stdout,"%s (line %d): 0x%08x %s 0x%08lx 0x%08lx \n",__FILE__,__LINE__, sectPos, sectName, curSec, nextSec);
76 if (flag && !strcmp(sectName,"EEGData")) {
77 if (VERBOSE_LEVEL > 7) fprintf(stdout,"%s (line %d): 0x%08x %s 0x%08lx 0x%08lx \n",__FILE__,__LINE__, sectPos, sectName, curSec, nextSec);
78 FILE *fid2=fopen("tmp.bin","w");
79 fwrite(hdr->AS.Header + curSec+120, 1, nextSec-curSec-120,fid2);
80 fclose(fid2);
81 FILE *fid=fopen("tmp.asc","w");
82 for (size_t k0=curSec+8*15; k0 < nextSec; k0+=2) {
83 fprintf(fid,"%d\n",bei16p(hdr->AS.Header + curSec + k0+1));
84 }
85 fclose(fid);
86 flag = 0;
87 }
88 sectPos = nextSec;
89 } while (nextSec != (size_t)-1L);
90 }
91 biosigERROR(hdr, B4C_FORMAT_UNSUPPORTED, "Format EAS(Cadwell): unsupported ");
92 }
93
94 else if (hdr->TYPE==EZ3) {
95 hdr->VERSION = strtod((char*)hdr->AS.Header+21, NULL);
96 // 16 bit ADC ?
97 // 250 Hz ?
98
99 if (VERBOSE_LEVEL > 7) fprintf(stdout,"%s (line %d)0x%8x\n",__FILE__,__LINE__,hdr->HeadLen);
100
101 uint32_t posH1 = leu32p(hdr->AS.Header + 0x10);
102 if (VERBOSE_LEVEL > 7) fprintf(stdout,"%s (line %d)0x%8x\n",__FILE__,__LINE__,posH1);
103
104 uint32_t posH1b = leu32p(hdr->AS.Header + 0x20);
105 if (VERBOSE_LEVEL > 7) fprintf(stdout,"%s (line %d)0x%8x\n",__FILE__,__LINE__,posH1b);
106
107 uint32_t posH2 = leu32p(hdr->AS.Header + 0x38);
108 if (VERBOSE_LEVEL > 7) fprintf(stdout,"%s (line %d)0x%8x\n",__FILE__,__LINE__,posH2);
109
110 uint32_t posH2b = leu32p(hdr->AS.Header + posH1 + 0x38);
111
112 if (VERBOSE_LEVEL > 7) fprintf(stdout,"%s (line %d) 0x%08x 0x%08x 0x%08x 0x%08x \n",__FILE__,__LINE__,posH1,posH1b,posH2,posH2b);
113
114 assert(posH1==posH1b);
115 assert(posH2==posH2b);
116
117 if (VERBOSE_LEVEL > 7) fprintf(stdout,"%s (line %d)\n",__FILE__,__LINE__);
118
119 // start date/time
120 {
121 char *tmp = hdr->AS.Header + 0x5c;
122 struct tm t;
123 t.tm_year = strtol(tmp,&tmp,10)-1900;
124 t.tm_mon = strtol(tmp+1,&tmp,10)-1;
125 t.tm_mday = strtol(tmp+1,&tmp,10);
126 t.tm_hour = strtol(tmp+1,&tmp,10);
127 t.tm_min = strtol(tmp+1,&tmp,10);
128 t.tm_sec = strtol(tmp+1,&tmp,10);
129 hdr->T0 = tm_time2gdf_time(&t);
130 }
131
132 uint32_t pos0=posH1+0x40;
133 for (size_t k = posH1+0x40; k < posH2; k += 0x30) {
134 char *tmp = hdr->AS.Header + k + 1;
135 uint32_t pos = leu32p(hdr->AS.Header + k + 0x28);
136 if (tmp[0]=='\0') break;
137
138 if (VERBOSE_LEVEL > 7) fprintf(stdout,"%s (line %d): Label=<%s> %10d(0x%08x) [sz=%d]\n",__FILE__,__LINE__, tmp, pos, pos, pos-pos0);
139 pos0=pos;
140 }
141
142 biosigERROR(hdr, B4C_FORMAT_UNSUPPORTED, "Format EZ3(Cadwell): unsupported ");
143 }
144 else if (hdr->TYPE==ARC) {
145 biosigERROR(hdr, B4C_FORMAT_UNSUPPORTED, "Format ARC(Cadwell): unsupported ");
146 }
147 }
148
149