Main Page | Data Structures | File List | Data Fields | Globals | Related Pages

readedf.c

Go to the documentation of this file.
00001 /*
00002 NeuroServer
00003  
00004 A collection of programs to translate between EEG data and TCP network
00005 messages. This is a part of the OpenEEG project, see http://openeeg.sf.net
00006 for details.
00007     
00008 Copyright (C) 2003, 2004 Rudi Cilibrasi (cilibrar@ofb.net)
00009      
00010 This library is free software; you can redistribute it and/or
00011 modify it under the terms of the GNU Lesser General Public
00012 License as published by the Free Software Foundation; either
00013 version 2.1 of the License, or (at your option) any later version.
00014          
00015 This library is distributed in the hope that it will be useful,
00016 but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018 Lesser General Public License for more details.
00019              
00020 You should have received a copy of the GNU Lesser General Public
00021 License along with this library; if not, write to the Free Software
00022 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00023 */
00024                 
00025 #include <assert.h>
00026 #include <stdlib.h>
00027 #include <openedf.h>
00028 #include <string.h>
00029 #include <sys/time.h>
00030 #include <pctimer.h>
00031 #include <nsutil.h>
00032 #include <nsnet.h>
00033 
00034 const char *helpText =
00035 "readedf   v 0.43 by Rudi Cilibrasi\n"
00036 "\n"
00037 "Usage:  readedf [options] <filename>\n"
00038 "\n"
00039 "        -p port          Port number to use (default 8336)\n"
00040 "        -n hostname      Host name of the NeuroCaster server to connect to\n"
00041 "                         (this defaults to 'localhost')\n"
00042 "        -c numlist       Numlist must be a comma-separated list of integers\n"
00043 "                         that specify what channels to send. The first\n"
00044 "                         channel is numbered 0. The default is all channels.\n"
00045 "        -f               Fast Mode. Send data at maximum speed.\n"
00046 "                         Default behavior sends data at EDF sampling rate.\n"
00047 ;
00048 
00049 struct Options {
00050         int isMaxSpeed; // to turn off the gated loop
00051         int userSpecifiedChannels;
00052         int channelReadFlags[MAXCHANNELS];  // which channels to use
00053         char hostname[MAXLEN];
00054         char filename[MAXLEN];
00055         int isFilenameSet;
00056         unsigned short port;
00057 };
00058 
00059 struct Options opts;
00060 
00061 struct OutputBuffer ob;
00062 struct InputBuffer ib;
00063 
00064 #define SPEEDUPFACTOR 4.0
00065 
00066 void printHeader(const struct EDFDecodedHeader *hdr)
00067 {
00068         printf("The data record count is %d\n", hdr->dataRecordCount);
00069         printf("The data record channels is %d\n", hdr->dataRecordChannels);
00070         printf("The data record seconds is %f\n", hdr->dataRecordSeconds);
00071 }
00072 
00073 void handleSamples(sock_t sock_fd, int packetCounter, int chan, short *vals)
00074 {
00075         char buf[MAXLEN];
00076         int bufPos = 0;
00077         int i;
00078         bufPos += sprintf(buf+bufPos, "! %d %d", packetCounter, chan);
00079         for (i = 0; i < chan; ++i)
00080                 bufPos += sprintf(buf+bufPos, " %d", vals[i]);
00081         bufPos += sprintf(buf+bufPos, "\r\n");
00082         writen(sock_fd, buf, bufPos, &ob);
00083 //      rprintf("SENT:%s", buf);
00084 }
00085 
00086 int main(int argc, char **argv)
00087 {
00088         char EDFPacket[MAXHEADERLEN];
00089         double speedup = 1;
00090         int wantedChannels[MAXCHANNELS];
00091         int EDFLen = MAXHEADERLEN;
00092         struct EDFDecodedConfig cfg, normalized, forNC;
00093         struct EDFInputIterator *edfi;
00094         FILE *fp;
00095         int i;
00096         double t0;
00097         sock_t sock_fd;
00098         int retval;
00099         int chunksize;
00100         strcpy(opts.hostname, DEFAULTHOST);
00101         opts.port = DEFAULTPORT;
00102         for (i = 1; i < argc; ++i) {
00103                 char *opt = argv[i], *cur;
00104                 if (opt[0] == '-') {
00105                         switch (opt[1]) {
00106                                 case 'c':
00107                                         for (cur = strtok(argv[i+1], ", ");cur;cur=strtok(NULL,", "))
00108                                                 opts.channelReadFlags[atoi(cur)] = 1;
00109                                         opts.userSpecifiedChannels = 1;
00110                                         i += 1;
00111                                         break;
00112                                 case 'h':
00113                                         printf("%s", helpText);
00114                                         exit(0);
00115                                         break;
00116                                 case 'f':
00117                                         opts.isMaxSpeed = 1;
00118                                         break;
00119                                 case 'n':
00120                                         strcpy(opts.hostname, argv[i+1]);
00121                                         i += 1;
00122                                         break;
00123                                 case 'p':
00124                                         opts.port = atoi(argv[i+1]);
00125                                         i += 1;
00126                                         break;
00127                                 }
00128                         }
00129                 else {
00130                         if (opts.isFilenameSet) {
00131                                 fprintf(stderr, "Error: only one edf file allowed: %s and %s\n",
00132                                                 opts.filename, argv[i]);
00133                                 exit(1);
00134                         }
00135                         strcpy(opts.filename, argv[i]);
00136                         opts.isFilenameSet = 1;
00137                 }
00138         }
00139         rinitNetworking();
00140         if (!opts.userSpecifiedChannels) {
00141                 for (i = 0; i < MAXCHANNELS; ++i)
00142                         opts.channelReadFlags[i] = 1;
00143         }
00144         if (!opts.isFilenameSet) {
00145                 fprintf(stderr, "Must supply the filename of the EDF to read.\n");
00146                 exit(1);
00147         }
00148         fp = fopen(opts.filename, "rb");
00149         assert(fp != NULL && "Cannot open file!");
00150         retval = readEDF(fileno(fp), &cfg);
00151         printHeader(&cfg.hdr);
00152         makeREDFConfig(&normalized, &cfg);
00153         forNC = normalized;
00154         forNC.hdr.dataRecordChannels = 0;
00155         for (i = 0; i < normalized.hdr.dataRecordChannels; ++i) {
00156                 if (opts.channelReadFlags[i]) {
00157                         memcpy(&forNC.chan[forNC.hdr.dataRecordChannels], &normalized.chan[i], sizeof(normalized.chan[0]));
00158                         wantedChannels[forNC.hdr.dataRecordChannels] = i;
00159                         forNC.hdr.dataRecordChannels += 1;
00160                 }
00161         }
00162         if (forNC.hdr.dataRecordChannels == 0) {
00163                 fprintf(stderr, "Must specify some channels to read (e.g. -c 0,1 ).\n");
00164                 exit(1);
00165         }
00166                 
00167         setEDFHeaderBytes(&forNC);
00168 
00169         sock_fd = rsocket();
00170         if (sock_fd < 0) {
00171                 perror("socket");
00172                 rexit(1);
00173         }
00174 
00175         retval = rconnectName(sock_fd, opts.hostname, opts.port);
00176         if (retval != 0) {
00177                 rprintf("connect error\n");
00178                 rexit(1);
00179         }
00180         rprintf("Socket connected.\n");
00181         fflush(stdout);
00182 
00183         writeEDFString(&forNC, EDFPacket, &EDFLen);
00184         writeString(sock_fd, "eeg\n", &ob);
00185         writeString(sock_fd, "setheader ", &ob);
00186         writeBytes(sock_fd, EDFPacket, EDFLen, &ob);
00187         writeString(sock_fd, "\n", &ob);
00188         fflush(stdout);
00189         writeEDF(1, &forNC);
00190         rprintf("There are %f samples per second\n", getSamplesPerSecond(&forNC, 0));
00191         chunksize = getDataRecordChunkSize(&cfg);
00192 
00193         printf("The chunk size is %d\n", chunksize);
00194         printf("The header size is %d\n", cfg.hdr.headerRecordBytes);
00195         edfi = newEDFInputIterator(&cfg);
00196         t0 = pctimer();
00197         i = 0;
00198         if (opts.isMaxSpeed)
00199                 speedup = SPEEDUPFACTOR;
00200         for (;;) {
00201                 int retval, j;
00202                 short samples[MAXCHANNELS], tosend[MAXCHANNELS];
00203                 retval = fetchSamples(edfi, samples, fp);
00204                 if (retval != 0) break;
00205                 for (j = 0; j < forNC.hdr.dataRecordChannels; ++j)
00206                         tosend[j] = samples[wantedChannels[j]];
00207                 handleSamples(sock_fd, i%64, forNC.hdr.dataRecordChannels, tosend);
00208                 while (t0 + (double) i / (getSamplesPerSecond(&forNC, 0) * speedup) > pctimer()) {
00209                                 rsleep(20);
00210                         }
00211                 i += 1;
00212                 if (i % 1000 == 0) {
00213                         printf("Read %d timesamples and on datarecord %05d:%04d\n", i, edfi->dataRecordNum, edfi->sampleNum);
00214                         fflush(stdout);
00215                 }
00216                 stepEDFInputIterator(edfi);
00217                 getResponseCode(sock_fd, &ib);
00218         }
00219 
00220         fclose(fp);
00221         freeEDFInputIterator(edfi);
00222         return 0;
00223 }

Generated on Tue Feb 8 00:05:17 2005 for Neuroserver by doxygen 1.3.3