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

opencnvdriver.c

Go to the documentation of this file.
00001 
00008 /*
00009 NeuroServer
00010  
00011 A collection of programs to translate between EEG data and TCP network
00012 messages. This is a part of the OpenEEG project, see http://openeeg.sf.net
00013 for details.
00014     
00015 Copyright (C) 2003, 2004 Rudi Cilibrasi (cilibrar@ofb.net) 
00016      
00017 This library is free software; you can redistribute it and/or
00018 modify it under the terms of the GNU Lesser General Public
00019 License as published by the Free Software Foundation; either
00020 version 2.1 of the License, or (at your option) any later version.
00021          
00022 This library is distributed in the hope that it will be useful,
00023 but WITHOUT ANY WARRANTY; without even the implied warranty of
00024 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00025 Lesser General Public License for more details.
00026              
00027 You should have received a copy of the GNU Lesser General Public
00028 License along with this library; if not, write to the Free Software
00029 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00030 */
00031                 
00032 
00033 
00034 #include <stdio.h>
00035 #include <assert.h>
00036 #include <stdlib.h>
00037 #include <string.h>
00039 #include <nsnet.h>
00040 #include <nsutil.h>
00042 #include <nsser.h>
00044 #include <openedf.h>
00046 #include <config.h>
00048 #define PROTOWINDOW 12
00049 
00050 //#define DEBUGGING
00052 char buf[PROTOWINDOW];
00054 sock_t sock_fd;
00055 int bufCount;
00056 static int failCount = 0;
00058 static struct OutputBuffer ob;
00060 static struct InputBuffer ib;
00062 int hasMatchedProtocol;
00064 int isOpenCNV;
00066 int isPseudoEDF;
00068 int isValidPacket(unsigned short nchan, long *samples);
00070 int doesMatchOpenCNV(unsigned char c, long *vals);
00072 int mGetOK(sock_t fd, struct InputBuffer *ib);
00073 
00074 
00076 int mGetOK(sock_t fd, struct InputBuffer *ib)
00077 {
00078         return 0;
00079 }
00080 
00082 static struct EDFDecodedConfig openCNVCfg = {
00083                 { 0,                            // size of header in bytes (to be set later)
00084                         -1,                     // data record count, -1 if unknown
00085                         3,                      // channels
00086                         "24bit",                // data format version number
00087                         "Mr. Default Patient",
00088                         "Ms. Default Recorder",
00089                         "date",
00090                         "time",
00091                         "24bit OpenCNV",        // manufactorer ID
00092                         2,                      // seconds per data record
00093                 }, {
00094                                 {
00095                                         1001,           
00096                                         -512, 512,      
00097                                         -8388608, 8388607,
00098                                         "electrode 0",  
00099                                         "Red Dot Ag/AgCl",  
00100                                         "uV",           
00101                                         "LP:100 Hz",    
00102                                         ""              
00103                                 },
00104                                 {
00105                                         1001,           
00106                                         -512, 512,      
00107                                         -8388608, 8388607,      
00108                                         "electrode 1",  
00109                                         "Red Dot Ag/AgCl",  
00110                                         "uV",           
00111                                         "LP:100 Hz",    
00112                                         ""              
00113                                 },                                                              
00114                                         {
00115                                         1001,           
00116                                         0, 255,         
00117                                         0, 255,         
00118                                         "Stimulus State",       
00119                                         "----",  
00120                                         "State",                
00121                                         "none",         
00122                                         ""              
00123                                 }                                                               
00124                                 
00125                 }
00126         };
00127 
00128 static struct EDFDecodedConfig current;
00129 
00133 int isValidPacket(unsigned short chan, long *samples)
00134 {
00135 //      int i;
00136 //      if (chan != 2 && chan != 4 && chan !=5 && chan != 6) return 0;
00137 //      for (i = 0; i < chan; i++) {
00138 //              if (samples[i] > 16777216) return 0;
00139 //      }
00140         return 1;
00141 }
00142 
00143 
00144 
00146 void eatCharacter(unsigned char c)
00147 {
00149 #define MINGOOD 6
00150         static int goodCount;
00152         long vals[MAXCHANNELS];  
00153         int didMatch = 0;
00154         //int ns=3;
00156         if (hasMatchedProtocol) {
00157            didMatch = doesMatchOpenCNV(c, vals);
00158          } 
00160          else {
00161            didMatch = doesMatchOpenCNV(c, vals); 
00163            if (didMatch) {
00164             if (goodCount > MINGOOD) {
00165              hasMatchedProtocol = 1;
00166 //           isOpenCNV = 1;
00167             }
00168            }
00169          }
00171         if (didMatch) { 
00172                 char *pstr = "xx";
00174 //              if (isValidPacket(ns, vals)) {
00175 //                      goodCount += 1;
00176 //              }
00177 //              else {
00178 //                      rprintf("Warning: invalid serial packet ahead!\n");
00179 //              }
00180                 pstr = "OpenCNV";
00181 //              failCount = 0;
00182 //                printf("%c",c);       
00183 #ifdef DEBUGGING1
00184                 int i;  
00185                 printf("Got %s packet with %d values: ", pstr, ns);
00186                 for (i = 0; i < 3; ++i)
00187                  printf("%ld ", vals[i]);
00188                 printf("\n");
00189 #endif          
00190         }
00192         else {
00193                 failCount += 1;
00194                 if (failCount % PROTOWINDOW == 0) {
00195                         rprintf("Serial packet sync error -- missed window.\n");
00196                         goodCount = 0;
00197                 }
00198         }
00199 }
00200 
00201 
00210 void handleSamples(int packetCounter, int chan, long *vals)
00211 {
00212         char buf[MAXLEN];                                       
00213         int bufPos = 0;
00214   //long ChannelValue;
00215         int i;
00216 #ifdef DEBUGGING        
00217         printf("Got good packet with counter %d, %d chan\n", packetCounter, chan);
00218 #endif  
00219         chan=3;
00220         bufPos+=sprintf(buf, "! %d %d", packetCounter, chan);
00221         for (i = 0; i < 3; i++) {
00222           bufPos+=sprintf(buf+bufPos, " %ld",vals[i]); 
00223          }
00224         bufPos+=sprintf(buf+bufPos, "\r\n");
00225         writeString(sock_fd, buf, &ob);
00226         mGetOK(sock_fd, &ib);
00227 }
00228 
00232 
00233 int doesMatchOpenCNV(unsigned char c, long *vals)
00234 {
00235         enum P2State { waitingA5, waiting5A, waitingCounter,
00236                 waitingData };
00237         static int packetCounter = 0;
00238         static int chan = 0;
00239         static int i = 0;
00240         static enum P2State state = waitingA5;
00241 
00242         switch (state) {
00243                 case waitingA5:
00244                         if (c == 0xa5) {
00245                                 failCount = 0;
00246                                 state = waiting5A;
00247                         }
00248                         else {
00249                                 failCount += 1;
00250                                 if (failCount % PROTOWINDOW == 0) {
00251                                         rprintf("Sync error, packet lost.\n");
00252                                         return 0;
00253                                 }
00254                         }
00255                         break;
00256 
00257                 case waiting5A:
00258                         if (c == 0x5a)
00259                                 state = waitingCounter;
00260                         else
00261                                 state = waitingA5;
00262                                 return 0;
00263                         break;
00264 
00265 
00266                 case waitingCounter:
00267                         packetCounter = c;
00268                         i = 0;          
00269                         state = waitingData;
00270         
00271                         break;
00272 
00273                 case waitingData:
00274                         switch(i) {
00275                          case 0: vals[0] = 256*256*c;i++;break;                  
00276                          case 1: vals[0]+=256*c;i++;break;
00277                          case 2: vals[0]+=c;i++;vals[0]=vals[0]-8388608;break;
00278                          case 3: i++;break;                             
00279                          case 4: vals[1] = 256*256*c;i++;break;                  
00280                          case 5: vals[1]+=256*c;i++;break;
00281                          case 6: vals[1]+=c;vals[1]=vals[1]-8388608;i++;break;
00282                          case 7: i++;break;                             
00283                          case 8: vals[2]=c;                             
00284                                  i++;
00285                                  chan =  3; 
00286                                  handleSamples(packetCounter, chan , vals);
00287                                  state = waitingA5;break;
00288                           default:
00289                                 rprintf("Error: problem during waiting Data state\n");
00290                                 rexit(0);
00291                         }
00292                         break;
00293                 default:
00294                                 rprintf("Error: unknown state in OpenCNV protocol!\n");
00295                                 rexit(0);
00296                 }
00297         return 1;
00298 }
00299 
00301 void printHelp()
00302 {
00303         rprintf("OpenCNV Driver interfaces the OpenCNV system to the NeuroServer TCP/IP protocol\n");
00304         rprintf("Usage: opencnvdriver [-d serialDeviceName] [-m} [hostname] [portno]\n");
00305         rprintf("The default options are opencnvdriver -d %s %s %d\n",
00306                         DEFAULTDEVICE, DEFAULTHOST, DEFAULTPORT);
00307         rprintf("The -m option splits 24bit ADC data into an offset part and regular part, \n");
00308         rprintf("this allows the standard 16bit EDF format to be used with higher dynamic range data.");
00309         
00310         
00311                         
00312 }
00313 
00314 void decodeCommand(char command[MAXLEN],ser_t serport) {
00315 char writebuf[2];
00316 
00317  if ((command[0]=='g') && (command[1]=='o')) {
00318   writebuf[0]='T';
00319   writebuf[1]='1';
00320   writeSerial(serport,writebuf,2);
00321   }
00322  
00323  if ((command[0]=='n') && (command[1]=='o') && (command[2]=='g') && (command[3]=='o')) {
00324   writebuf[0]='T';
00325   writebuf[1]='3';
00326   writeSerial(serport,writebuf,2);
00327   }
00328   
00329   
00330  if ((command[0]=='2') && (command[1]=='0') && (command[2]=='0') ) {
00331 //  rprintf("OK\n");
00332  }
00333  else {
00334   rprintf("not OK: %c %c %c \n",command[0],command[1],command[2]);
00335  }
00336 }
00337 
00338 
00339 int main(int argc, char **argv)
00340 {
00341         char responseBuf[MAXLEN];
00342         int i;
00343         int retval;
00344         ser_t serport;
00345         char EDFPacket[MAXHEADERLEN];
00346         int EDFLen = MAXHEADERLEN;
00347         char smallbuf[PROTOWINDOW];
00349         char *hostname = NULL;
00350         char *deviceName = NULL;
00352         unsigned short portno = 0;
00353         struct timeval  when;
00354         
00355         char linebuf[MAXLEN+1]; // fifo command buffer
00356         int writepos = 0;        
00357         //int readpos = 0;
00358         int len;
00359         //unsigned int lpos = 0;
00360         
00361         rprintf("OpenCNV Driver v. %s-%s\n", VERSION, OSTYPESTR);
00362 
00363         rinitNetworking();
00364         
00365         isPseudoEDF=0;
00366         for (i = 1; argv[i]; ++i) {
00367                 if (argv[i][0] == '-' && argv[i][1] == 'h') {
00368                         printHelp();
00369                         exit(0);
00370                 }
00371                 if (argv[i][0] == '-' && argv[i][1] == 'd') {
00372                         if (argv[i+1] == NULL) {
00373                                 rprintf("Bad devicename option: %s\nExpected device name as next argument.\n", argv[i]);
00374                                 exit(1);
00375                         }
00376                         deviceName = argv[i+1];
00377                         i += 1;
00378                         continue;
00379                 }
00380                 if (argv[i][0] == '-' && argv[i][1] == 'm') {
00381                         isPseudoEDF=1;
00382                         continue;
00383 
00384                 }
00385                 if (hostname == NULL) {
00386                         hostname = argv[i];
00387                         continue;
00388                 }
00389                 if (portno == 0) {
00390                         portno = atoi(argv[i]);
00391                         continue;
00392                 }
00393         }
00394         if (deviceName == NULL)
00395                 deviceName = DEFAULTDEVICE;
00396         if (portno == 0)
00397                 portno = DEFAULTPORT;
00398         if (hostname == NULL)
00399                 hostname = DEFAULTHOST;
00401         current=openCNVCfg;
00402         setEDFHeaderBytes(&current);
00403   strcpy(current.hdr.recordingStartDate, getDMY());
00404   strcpy(current.hdr.recordingStartTime, getHMS());
00405 //        assert(isValidREDF(result));
00406 //      makeREDFConfig(&current, &openCNVCfg);
00407 //      write configuration into string 
00408         writeEDFString(&current, EDFPacket, &EDFLen);
00409 
00410 
00411         sock_fd = rsocket();
00412         if (sock_fd < 0) {
00413                 perror("socket");
00414                 rexit(1);
00415         }
00416         setblocking(sock_fd);
00417 
00418         rprintf("Attempting to connect to nsd at %s:%d\n", hostname, portno);
00419         retval = rconnectName(sock_fd, hostname, portno);
00420         if (retval != 0) {
00421                 rprintf("connect error\n");
00422                 rexit(1);
00423         }
00424         rprintf("Socket connected.\n");
00425         fflush(stdout);
00426 
00427         serport = openSerialPort(deviceName,115200);                    
00428         rprintf("Serial port %s opened.\n", deviceName);
00429         writeString(sock_fd, "eeg\n", &ob);     
00430         mGetOK(sock_fd, &ib);
00431         writeString(sock_fd, "setheader ", &ob);
00433         writeBytes(sock_fd, EDFPacket, EDFLen, &ob);
00434         writeString(sock_fd, "\n", &ob);
00435         mGetOK(sock_fd, &ib);
00436         updateMaxFd(sock_fd);
00437 #ifndef __MINGW32__
00438         updateMaxFd(serport);
00439 #endif
00440         when.tv_sec = 0;
00441         when.tv_usec = (int)(1000000 / openCNVCfg.chan[0].sampleCount * openCNVCfg.hdr.dataRecordSeconds);
00442         rprintf("Polling at %f Hertz or %i usec\n",(1e6/when.tv_usec), 
00443              when.tv_usec);
00444         for (;;) {
00445                 int i, readSerBytes;
00446                 int retval;
00447                 fd_set toread;
00448                 FD_ZERO(&toread);
00449                 FD_SET(sock_fd, &toread);
00450 #ifndef __MINGW32__
00451                 FD_SET(serport, &toread);
00452 #endif
00453                 when.tv_usec = (int)(1000000 / openCNVCfg.chan[0].sampleCount * openCNVCfg.hdr.dataRecordSeconds);
00454                 when.tv_sec = 0;
00455                 retval = rselect_timed(max_fd, &toread, NULL, NULL, &when);
00456                 readSerBytes = readSerial(serport, smallbuf, PROTOWINDOW);              // get one frame
00457 // timeout + exit, if no serial data available
00458                 if (readSerBytes < 0) {
00459                         rprintf("Serial error.\n");
00460                 }
00461                 if (readSerBytes > 0) {
00462                         for (i = 0; i < readSerBytes; ++i)
00463                                 eatCharacter(smallbuf[i]);    
00464                 }
00466                 if ( (FD_ISSET(sock_fd, &toread)) && (ib.read_cnt<=0) ) {       // did we get any new network data ? yes !
00467                         my_read(sock_fd, responseBuf, MAXLEN, &ib); // get data into input buffer
00468                         len=0;
00469                         for (i=0;i<ib.read_cnt;i++) {
00470                          linebuf[writepos]=ib.read_buf[i];
00471                          if (linebuf[writepos]=='\n') {
00472                           decodeCommand(linebuf,serport);
00473                           writepos=0;
00474                           }
00475                          else {
00476                           writepos++;
00477                          }
00478                          if (writepos>=256) writepos=0;
00479                         }
00480                         ib.read_cnt=0;
00481                 }
00482                 
00483 
00484                 if (isEOF(sock_fd, &ib)) {
00485                                         rprintf("Server died, exitting.\n");
00486                                         exit(0);
00487                 }
00488                 
00489         }
00490 
00491         return 0;
00492 }
00493 

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