00001
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
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
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,
00084 -1,
00085 3,
00086 "24bit",
00087 "Mr. Default Patient",
00088 "Ms. Default Recorder",
00089 "date",
00090 "time",
00091 "24bit OpenCNV",
00092 2,
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
00136
00137
00138
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
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
00167 }
00168 }
00169 }
00171 if (didMatch) {
00172 char *pstr = "xx";
00174
00175
00176
00177
00178
00179
00180 pstr = "OpenCNV";
00181
00182
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
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
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];
00356 int writepos = 0;
00357
00358 int len;
00359
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(¤t);
00403 strcpy(current.hdr.recordingStartDate, getDMY());
00404 strcpy(current.hdr.recordingStartTime, getHMS());
00405
00406
00407
00408 writeEDFString(¤t, 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);
00457
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) ) {
00467 my_read(sock_fd, responseBuf, MAXLEN, &ib);
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