00001
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044 #include <assert.h>
00045 #include <openedf.h>
00046 #include <string.h>
00047 #include <stdlib.h>
00048 #include <sys/time.h>
00049 #include <pctimer.h>
00050 #include <ctype.h>
00051 #include <nsutil.h>
00052 #include <nsnet.h>
00053
00054 const char *helpText =
00055 "writeedf v 0.35 by Rudi Cilibrasi, Moritz von Buttlar\n"
00056 "\n"
00057 "Usage: writeedf [options] <filename>\n"
00058 "\n"
00059 " -p port Port number to use (default 8336)\n"
00060 " -n hostname Host name of the NeuroCaster server to connect to\n"
00061 " (this defaults to 'localhost')\n"
00062 " -s <num> Only record this many seconds.\n"
00063 " (default is to record until interrupted)\n"
00064 " -e <intnum> Integer ID specifying which EEG to log (default: 0)\n"
00065 " -b use bdf format (same as edf, only 24 bits/sample) \n"
00066 " -c write as CSV array (can be imported to Excel, Scilab,etc.)"
00067 "The filename specifies the new EDF file to create.\n"
00068 ;
00069
00070 #define MINLINELENGTH 4
00071 #define DELIMS " \r\n"
00072
00075 struct Options {
00076 char hostname[MAXLEN];
00077 unsigned short port;
00078 char filename[MAXLEN];
00079 int eegNum;
00080 int isFilenameSet;
00081 int isBdf;
00082 int isArray;
00083 int isLimittedTime;
00084 double seconds;
00085 };
00086
00087
00088 struct EDFDecodedConfig cfg;
00089 static struct OutputBuffer ob;
00090 struct InputBuffer ib;
00091 char lineBuf[MAXLEN];
00092 int blockCounter = 0;
00093
00094 char *dataarray;
00095 long samples[MAXCHANNELS];
00096
00097 size_t sampleSize;
00098 unsigned int frameCount;
00099 struct Options opts;
00100
00103 void resetSampleBuffer()
00104 {
00105 frameCount = 0;
00106 }
00107
00110 void writeSampleBuffer(unsigned int Channel,unsigned int SampleNr, char Byte0, char Byte1, char Byte2) {
00111 if (opts.isBdf) {
00112 dataarray[Channel*cfg.chan[0].sampleCount*sampleSize+SampleNr*sampleSize]=Byte0;
00113 dataarray[Channel*cfg.chan[0].sampleCount*sampleSize+SampleNr*sampleSize+1]=Byte1;
00114 dataarray[Channel*cfg.chan[0].sampleCount*sampleSize+SampleNr*sampleSize+2]=Byte2;
00115 }
00116 else {
00117 dataarray[Channel*cfg.chan[0].sampleCount*sampleSize+SampleNr*sampleSize]=Byte1;
00118 dataarray[Channel*cfg.chan[0].sampleCount*sampleSize+SampleNr*sampleSize+1]=Byte2;
00119 }
00120 }
00121
00124 void initSampleBuffer()
00125 {
00126 if (opts.isBdf)
00127 sampleSize=sizeof(unsigned char[3]);
00128 else
00129 sampleSize=sizeof(unsigned char[2]);
00130 dataarray = (unsigned char *) malloc(cfg.hdr.dataRecordChannels*
00131 sampleSize*cfg.chan[0].sampleCount*sizeof(unsigned char) );
00132 resetSampleBuffer();
00133 assert(dataarray != NULL && "Cannot allocate memory!");
00134 }
00135
00136
00139 void writeBufferToFile()
00140 {
00141 FILE *fp;
00142 fp = fopen(opts.filename, "a");
00143 rprintf("File opened for block write, frameCount: %d \n",frameCount);
00144 assert(fp != NULL && "Cannot open file!");
00146 fseek(fp, 0, SEEK_END);
00148 fwrite(dataarray, sizeof(unsigned char) , cfg.hdr.dataRecordChannels*frameCount*sampleSize, fp);
00149 fclose(fp);
00150 rprintf("Wrote block %d\n", blockCounter);
00151 blockCounter += 1;
00152 resetSampleBuffer();
00153 }
00154
00155
00158 void handleSamples(int packetCounter, int channels)
00159 {
00160 static int lastPacketCounter = 0;
00161 int i;
00162 unsigned char c1,c2,c3=0;
00163 if (lastPacketCounter + 1 != packetCounter && packetCounter != 0 && lastPacketCounter != 0) {
00164 rprintf("May have missed packet: got packetCounters %d and %d\n", lastPacketCounter, packetCounter);
00165 }
00166 lastPacketCounter = packetCounter;
00167 for (i = 3; i < channels+3; ++i) {
00168
00169
00170
00171
00172
00173 if (opts.isBdf) {
00174 c1=((samples[i]) & (0xff));
00175 c2=((samples[i]>>8) & (0xff));
00176 c3=((samples[i]>>16) & (0xff));
00177
00178 }
00179 else {
00180 c1=((samples[i]) & (0xff));
00181 c2=((samples[i]>>8) & (0xff));
00182 if ((samples[i]>>16) & (0x80)) c2=c2+(0x80);
00183 }
00184
00185 rprintf(" Sample: %d c1: %d c2: %d c3: %d \n",samples[i],c1,c2,c3);
00186 writeSampleBuffer(i-3,frameCount,c1,c2,c3);
00187 }
00188 frameCount += 1;
00189 if (frameCount==cfg.chan[0].sampleCount) {
00190 writeBufferToFile();
00191 }
00192 }
00193
00194
00195
00196
00200 int isANumber(const char *str) {
00201 int i;
00202 for (i = 0; str[i]; ++i)
00203 if ( (!isdigit(str[i])) && (!(str[i]=='-')) )
00204 return 0;
00205 return 1;
00206 }
00207
00210 void serverDied(void)
00211 {
00212 rprintf("Server died!\n");
00213 exit(1);
00214 }
00215
00216
00217
00218 int main(int argc, char **argv)
00219 {
00220 char EDFPacket[MAXHEADERLEN];
00221 char cmdbuf[80];
00222 int EDFLen = MAXHEADERLEN;
00223 FILE *fp;
00224 fd_set toread;
00225 int linePos = 0;
00226 int i;
00227 double tStart;
00228 sock_t sock_fd;
00229 int retval;
00230
00231 strcpy(opts.hostname, DEFAULTHOST);
00232 opts.port = DEFAULTPORT;
00233 opts.isBdf=0;
00234 opts.seconds=100000;
00235 for (i = 1; i < argc; ++i) {
00236 char *opt = argv[i];
00237 if (opt[0] == '-') {
00238 switch (opt[1]) {
00239 case 'h':
00240 printf("%s", helpText);
00241 exit(0);
00242 break;
00243 case 's':
00244 opts.seconds = atof(argv[i+1]);
00245 opts.isLimittedTime = 1;
00246 i += 1;
00247 break;
00248 case 'e':
00249 opts.eegNum = atoi(argv[i+1]);
00250 i += 1;
00251 break;
00252 case 'n':
00253 strcpy(opts.hostname, argv[i+1]);
00254 i += 1;
00255 break;
00256 case 'p':
00257 opts.port = atoi(argv[i+1]);
00258 i += 1;
00259 break;
00260 case 'b':
00261 opts.isBdf=1;
00262 break;
00263 case 'c':
00264 opts.isArray=1;
00265 break;
00266 }
00267 }
00268 else {
00269 if (opts.isFilenameSet) {
00270 fprintf(stderr, "Error: only one edf file allowed: %s and %s\n",
00271 opts.filename, argv[i]);
00272 exit(1);
00273 }
00274 strcpy(opts.filename, argv[i]);
00275 opts.isFilenameSet = 1;
00276 }
00277 }
00279 if (!opts.isFilenameSet) {
00280 fprintf(stderr, "Must supply the filename of the EDF to write.\n");
00281 exit(1);
00282 }
00284 fp = fopen(opts.filename, "wb");
00285 assert(fp != NULL && "Cannot open file!");
00286
00288 rinitNetworking();
00289 sock_fd = rsocket();
00290 if (sock_fd < 0) {
00291 perror("socket");
00292 rexit(1);
00293 }
00294
00295 retval = rconnectName(sock_fd, opts.hostname, opts.port);
00296 if (retval != 0) {
00297 rprintf("connect error\n");
00298 rexit(1);
00299 }
00300
00301 rprintf("Socket connected.\n");
00302 fflush(stdout);
00303
00305 writeString(sock_fd, "display\n", &ob);
00306 getOK(sock_fd, &ib);
00307 rprintf("Finished display, doing getheader.\n");
00308 sprintf(cmdbuf, "getheader %d\n", opts.eegNum);
00309 writeString(sock_fd, cmdbuf, &ob);
00310 getOK(sock_fd, &ib);
00311 if (isEOF(sock_fd, &ib))
00312 serverDied();
00313 EDFLen = readline(sock_fd, EDFPacket, sizeof(EDFPacket), &ib);
00314 rprintf("Got EDF Header <%s>\n", EDFPacket);
00315
00317 readEDFString(&cfg, EDFPacket, EDFLen);
00319 if ( (cfg.hdr.dataFormat[0]=='2') && (cfg.hdr.dataFormat[1]=='4') ) {
00320 opts.isBdf=1;
00321 rprintf("24bit data format auto detected \n");
00322 }
00323 rprintf("Header Record bytes: %d \n",cfg.hdr.headerRecordBytes);
00324
00326 if (opts.isArray==0) fwrite(EDFPacket, 1, cfg.hdr.headerRecordBytes, fp);
00327 fclose(fp);
00328
00329 initSampleBuffer();
00330 rprintf("Now sending watch command \n");
00331 sprintf(cmdbuf, "watch %d\n", opts.eegNum);
00332 writeString(sock_fd, cmdbuf, &ob);
00333 getOK(sock_fd, &ib);
00334 tStart = pctimer();
00335 FD_ZERO(&toread);
00336 FD_SET(sock_fd, &toread);
00337 rprintf("Starting data read loop \n");
00338 while ( (tStart+opts.seconds) > pctimer() ) {
00339 char *cur;
00340 int curParam = 0;
00341 int packetCounter=0, channels=0;
00342 rselect(sock_fd+1, &toread, NULL, NULL);
00343 linePos = readline(sock_fd, lineBuf, sizeof(EDFPacket), &ib);
00344 if (isEOF(sock_fd, &ib)) {
00345 rprintf("EOF sock_fd \n");
00346 break;
00347 }
00348 if (linePos < MINLINELENGTH)
00349 continue;
00350 if (lineBuf[0] != '!')
00351 continue;
00352 curParam=0;
00353 for (cur = strtok(lineBuf, DELIMS); cur ; cur = strtok(NULL, DELIMS)) {
00354 if (isANumber(cur)){
00355 samples[curParam]=atol(cur);
00356 rprintf("Nr.: %d \t Wert: %d \t \n",curParam,samples[curParam]);
00357 curParam++;
00358 }
00359 }
00361 if (curParam < 3)
00362 continue;
00363 packetCounter=samples[1];
00364 channels=samples[2];
00365 rprintf("got samples, channels: %d \t packetCounter: %d \n",channels,packetCounter);
00366 handleSamples(packetCounter,channels);
00367 }
00368
00369
00370 rprintf("Ending data read loop \n");
00371
00372 return 0;
00373 }