int buffer_gethdr(int server, mxArray *plhs[], const mxArray *prhs[])
{
	int verbose = 0;
	int result  = 0;

	message_t *request  = NULL;
	message_t *response = NULL;

	/* this is for the Matlab specific output */
	const char *field_names[NUMBER_OF_FIELDS] = {"nchans", "nsamples", "nevents", "fsample", "data_type", "bufsize"};

	/* allocate the elements that will be used in the communication */
	request      = malloc(sizeof(message_t));
	request->def = malloc(sizeof(messagedef_t));
	request->buf = NULL;
	request->def->version = VERSION;
	request->def->command = GET_HDR;
	request->def->bufsize = 0;
	
	if (verbose) print_request(request->def);
	result = clientrequest(server, request, &response);
	
	if (result == 0) {
		if (verbose) print_response(response->def);

		if (response->def->command==GET_OK) {
			headerdef_t *headerdef = (headerdef_t *) response->buf;
			
			if (verbose) print_headerdef(headerdef);

			plhs[0] = mxCreateStructMatrix(1, 1, NUMBER_OF_FIELDS, field_names);
			mxSetFieldByNumber(plhs[0], 0, 0, mxCreateDoubleScalar((double)(headerdef->nchans)));
			mxSetFieldByNumber(plhs[0], 0, 1, mxCreateDoubleScalar((double)(headerdef->nsamples)));
			mxSetFieldByNumber(plhs[0], 0, 2, mxCreateDoubleScalar((double)(headerdef->nevents)));
			mxSetFieldByNumber(plhs[0], 0, 3, mxCreateDoubleScalar((double)(headerdef->fsample)));
			mxSetFieldByNumber(plhs[0], 0, 4, mxCreateDoubleScalar((double)(headerdef->data_type)));
			mxSetFieldByNumber(plhs[0], 0, 5, mxCreateDoubleScalar((double)(headerdef->bufsize)));
			
			addChunksToMatrix(plhs[0], (const char *) response->buf + sizeof(headerdef_t), headerdef->bufsize, headerdef->nchans);
		}
		else {
			result = response->def->command;
		}
	}

	if (response) {
		FREE(response->def);
		FREE(response->buf);
		FREE(response);
	}

	if (request) {
		FREE(request->def);
		FREE(request->buf);
		FREE(request);
	}

	return result;
}
Exemple #2
0
void buffer_flushdat(char *hostname, int port, mxArray *plhs[], const mxArray *prhs[])
{
	int server;
    int verbose = 0;

	message_t *request  = NULL;
	message_t *response = NULL;
	header_t  *header   = NULL;

	/* allocate the elements that will be used in the communication */
	request      = malloc(sizeof(message_t));
	request->def = malloc(sizeof(messagedef_t));
	request->buf = NULL;
	request->def->version = VERSION;
	request->def->command = FLUSH_DAT;
	request->def->bufsize = 0;

	/* open the TCP socket */
	if ((server = open_connection(hostname, port)) < 0) {
		mexErrMsgTxt("ERROR: failed to create socket\n");
	}

	if (verbose) print_request(request->def);
	clientrequest(server, request, &response);
	if (verbose) print_response(response->def);
	close_connection(server);

	if (response->def->command!=FLUSH_OK) {
		mexErrMsgTxt("ERROR: the buffer returned an error\n");
	}

	if (request) {
		FREE(request->def);
		FREE(request->buf);
		FREE(request);
	}
	if (response) {
		FREE(response->def);
		FREE(response->buf);
		FREE(response);
	}

	return;
}
int buffer_flushevt(int server, mxArray *plhs[], const mxArray *prhs[])
{
	int verbose = 0;
	int result;
  
	message_t *request  = NULL;
	message_t *response = NULL;

	/* allocate the elements that will be used in the communication */
	request      = malloc(sizeof(message_t));
	request->def = malloc(sizeof(messagedef_t));
	request->buf = NULL;
	request->def->version = VERSION;
	request->def->command = FLUSH_EVT;
	request->def->bufsize = 0;

	if (verbose) print_request(request->def);
	result = clientrequest(server, request, &response);
	if (verbose) print_response(response->def);

	if (result == 0) {
		if (response->def->command!=FLUSH_OK) {
			result = response->def->command;
		}
	}

	if (request) {
		FREE(request->def);
		FREE(request->buf);
		FREE(request);
	}
	if (response) {
		FREE(response->def);
		FREE(response->buf);
		FREE(response);
	}

	return result;
}
Exemple #4
0
/** Wait for new samples/events in the FieldTrip buffer
	@param ft_buffer  	FieldTrip connection
	@param current		Previous (already handled!) number of samples/events (must not be NULL!)
	@param result		Current number of samples/events (must not be NULL!)
	@param ms			Timeout in milliseconds
	@return 	0 on success, -1 on error
*/
int rda_aux_wait_dat(int ft_buffer, const samples_events_t *previous, samples_events_t *result, int ms) {
	int r;
	message_t req, *resp = NULL;
	messagedef_t msg_def;
	waitdef_t wait_def;
	
	wait_def.threshold = *previous;
	wait_def.milliseconds = ms;
	
	req.def = &msg_def;
	req.buf = &wait_def;
	msg_def.version = VERSION;
	msg_def.command = WAIT_DAT;
	msg_def.bufsize = sizeof(waitdef_t);
	
	r = clientrequest(ft_buffer, &req, &resp);
	
	if (r<0) {
		*result = *previous;
		return r;
	}
	
	if (resp == NULL || resp->def == NULL || resp->buf == NULL || 
		resp->def->command != WAIT_OK || 
		resp->def->bufsize != sizeof(samples_events_t)) {
		printf("Bad response from WAIT_DAT call\n");
		r = -1;
		*result = *previous;
		goto cleanup;
	}
	memcpy(result, resp->buf, sizeof(samples_events_t));
cleanup:
	if (resp) {
		if (resp->buf) free(resp->buf);
		if (resp->def) free(resp->def);
		free(resp);
	}
	return r;
}
int send_header_to_FT()
{
  int c, namelen = 0, status = 0;
  char *namevec = NULL, *name;
  message_t     *request  = NULL;
  message_t     *response = NULL;
  header_t      *header   = NULL;
  ft_chunk_t    *chunk    = NULL;
  
  // collect the channel names
/*  for (c = 0; c < nchan; c++) {
    name = ch_info[c]->ch_name;
    printf("Found channel name '%s'\n", name);
    namevec = realloc(namevec, namelen + strlen(name) + 1);
    strcpy(namevec + namelen, name);
    namelen = namelen + strlen(name) + 1;
  }
  chunk = malloc(sizeof(ft_chunk_t));
  chunk->def.type = FT_CHUNK_CHANNEL_NAMES;
  chunk->def.size = namelen;
  memcpy(chunk->data, namevec, namelen);
*/
  // allocate the elements that will be used in the communication 
  request      = malloc(sizeof(message_t));
  request->def = malloc(sizeof(messagedef_t));
  request->buf = NULL;
  request->def->version = VERSION;
  request->def->bufsize = 0;
  
  header      = malloc(sizeof(header_t));
  header->def = malloc(sizeof(headerdef_t));
  header->buf = NULL;
	
  dacq_log("Creating a header for %d channels and sampling rate of %g Hz\n", nchan, sfreq);
  header->def->nchans    = nchan;
  header->def->nsamples  = 0;
  header->def->nevents   = 0;
  header->def->fsample   = sfreq;
  header->def->data_type = DATATYPE_FLOAT32;
  header->def->bufsize   = 0;
  FREE(header->buf);

  // initialization phase, send the header 
  request->def->command = PUT_HDR;
  request->def->bufsize = append(&request->buf, request->def->bufsize, header->def, sizeof(headerdef_t));
  request->def->bufsize = append(&request->buf, request->def->bufsize, header->buf, header->def->bufsize);
	
  status = clientrequest(fieldtrip_sock, request, &response);
  if (status) {
    dacq_log("Something wrong with FieldTrip buffer during initialization, status %d. Quiting.\n", status);
    clean_up();
    exit(1);
  }
  
  // How to send the channel name "chunk"?

  dacq_log("Header sent\n");
  
  // FIXME do someting with the response, i.e. check that it is OK 
  FREE(request);
  FREE(response);
  FREE(namevec);
  FREE(chunk);

  return(0);
}
Exemple #6
0
int send_header_to_FT()
{
  int c, namelen = 0, status = 0;
  char *namevec = NULL, *name;
  message_t     *request  = NULL;
  message_t     *response = NULL;
  header_t      *header   = NULL;
  ft_chunk_t    *chunk    = NULL;

  dacq_log("Creating a header: %d channels, sampling rate %g Hz\n", nchan, sfreq);
  
  // Construct the channel name chunk
  for (c = 0; c < nchan; c++) {
    name = ch_info[c]->ch_name;
    namevec = realloc(namevec, namelen + strlen(name) + 1);
    strcpy(namevec + namelen, name);
    namelen = namelen + strlen(name) + 1;
  }
  chunk = malloc(sizeof(ft_chunkdef_t) + namelen * sizeof(char));
  chunk->def.type = FT_CHUNK_CHANNEL_NAMES;
  chunk->def.size = namelen;
  memcpy(chunk->data, namevec, namelen);  // I don't like this kind of assumptions on how structures are laid out in memory
  FREE(namevec);

  // Construct the header with the channel name chunk
  header      = malloc(sizeof(header_t));
  header->def = malloc(sizeof(headerdef_t));
  header->def->nchans    = nchan;
  header->def->nsamples  = 0;
  header->def->nevents   = 0;
  header->def->fsample   = sfreq;
  header->def->data_type = DATATYPE_FLOAT32;
  header->def->bufsize   = sizeof(ft_chunkdef_t) + namelen * sizeof(char);
  header->buf = chunk;

  // Construct the message with the header
  request      = malloc(sizeof(message_t));
  request->def = malloc(sizeof(messagedef_t));
  request->buf = NULL;
  request->def->version = VERSION;
  request->def->bufsize = 0;
  request->def->command = PUT_HDR;
  request->def->bufsize = append(&request->buf, request->def->bufsize, header->def, sizeof(headerdef_t));
  request->def->bufsize = append(&request->buf, request->def->bufsize, header->buf, header->def->bufsize);

  // Send the message to the buffer
  status = clientrequest(fieldtrip_sock, request, &response);
  if (status) {
    dacq_log("Something wrong with FieldTrip buffer during initialization, status %d. Exiting.\n", status);
    clean_up();
    exit(1);
  }
  dacq_log("Header sent to the FieldTrip buffer\n");
  
  // FIXME: Do someting with the response, i.e. check that it is OK 

  FREE(request->def);
  FREE(request);
  FREE(header->def);
  FREE(header);
  FREE(chunk);
  FREE(response->def);
  FREE(response);
  return(0);
}
Exemple #7
0
void handleStartPacket(int ftSocket, int size, void *buf) {
	rda_msg_start_t *header = (rda_msg_start_t *) buf;
	double *dRes = (double *) ((char *) buf + sizeof(rda_msg_start_t));
	char *nameStart;
	int sizeNames;
	
	printf("\nRDA start packet (%i bytes) -- %i channels, Ts=%.1fus\n\n", size, header->nChannels, header->dSamplingInterval);
	numChannels = header->nChannels;
	
	goodToSend = 0;
	
	if (numChannels > 0) {
		int i;
		char *name = (char *) buf + sizeof(rda_msg_start_t) + numChannels*sizeof(double);

		nameStart = name;
		
		printf("Channel  Resolution  Name\n");
		
		for (i=0;i<numChannels;i++) {
			int maxLen = size - (name - (char *) buf);
			int len = strnlen(name, maxLen);
			
			if (len>=maxLen) {
				fprintf(stderr, "Invalid START packet received (unterminated channel names) -- ignoring.\n");
				return;
			}
			if (i<MAX_PRINT_CHN) {
				printf("%5i    %10.3f  '%s'\n", i, dRes[i], name);
			}
			name+=len+1;
		}
		
		sizeNames = name - nameStart;
		
		if (numChannels > MAX_PRINT_CHN) {
			printf("Suppressed output of further %i channels\n", numChannels - MAX_PRINT_CHN);
		}
	} else {
		fprintf(stderr, "Invalid START packet received -- channel number = %i\n", numChannels);
		return;
	}
	
	if (ftSocket != -1) {
		message_t request, *response;
		messagedef_t msgdef;
		char *msgbuf;
		headerdef_t *hdr;
		ft_chunk_t *chunk;
		int res;
		int sizeChunks = 2*sizeof(ft_chunkdef_t) + sizeNames + numChannels*sizeof(double);
		int sizeAll    = sizeof(headerdef_t) + sizeChunks;
		
		msgbuf = (char *) malloc(sizeAll);
		hdr = (headerdef_t *) msgbuf;
		if (hdr == NULL) {
			fprintf(stderr, "Out of memory -- not sending header\n");
			return;
		}
		
		request.def = &msgdef;
		request.buf = msgbuf;
	
		msgdef.version = VERSION;
		msgdef.command = PUT_HDR;
		msgdef.bufsize = sizeAll;
		
		hdr->nchans = numChannels;
		hdr->nsamples  = 0;
		hdr->nevents   = 0;
		hdr->fsample   = 1.0e6/header->dSamplingInterval;
		hdr->data_type = DATATYPE_FLOAT32; 
		hdr->bufsize   = sizeChunks;
		
		chunk = (ft_chunk_t *) (msgbuf + sizeof(headerdef_t));
		chunk->def.type = FT_CHUNK_CHANNEL_NAMES;
		chunk->def.size = sizeNames;
		memcpy(chunk->data, nameStart, sizeNames);
		
		chunk = (ft_chunk_t *) (msgbuf + sizeof(headerdef_t) + sizeof(ft_chunkdef_t) + sizeNames);
		chunk->def.type = FT_CHUNK_RESOLUTIONS;
		chunk->def.size = numChannels*sizeof(double);
		memcpy(chunk->data, (char *) buf + sizeof(rda_msg_start_t), numChannels*sizeof(double));
		
		res = clientrequest(ftSocket, &request, &response);
		
		if (res == 0) {
			if (response->def->command == PUT_OK) {
				goodToSend = 1;
				samplesWritten = 0;
			}
			free(response->def);
			if (response->buf) free(response->buf);
			free(response);
		}
	}
}
Exemple #8
0
void handleDataPacket(int ftSocket, int size, void *buf) {
	rda_msg_data_t *header = (rda_msg_data_t *) buf;
	int isInt, sizeData;
		
	message_t request, *response;
	messagedef_t reqdef;
	request.def = &reqdef;
	
	isInt = (header->hdr.nType == RDA_INT_MSG) ? 1 : 0;
	sizeData = (isInt ? sizeof(INT16_T) : sizeof(float)) * header->nPoints * numChannels;
	
	printf("RDA data block %4i (%i bytes):  %4i samples, %2i markers\n", header->nBlock, header->hdr.nSize, header->nPoints, header->nMarkers);	
	
	if (header->nMarkers > 0) {
		char *evbuf;
		
		/* offset of markers into RDA packet */
		int offset = sizeof(rda_msg_data_t) + sizeData;
		/* maximum length of all the "type" strings combined (actually a bit more because of trailing zeros) */
		int maxSizeTypes = size - offset - sizeof(rda_marker_t)*header->nMarkers;
		/* offset + size of events in evbuf */
		int evsiz = 0;
		
		evbuf = (char *) malloc(header->nMarkers*(sizeof(eventdef_t) + sizeof(INT32_T)) + maxSizeTypes);
		if (evbuf == NULL) {
			fprintf(stderr, "Out of memory\n");
			return;
		}
		
		while (offset + sizeof(rda_marker_t) <= size) {
			rda_marker_t *marker = (rda_marker_t *) ((char *) buf + offset);
			char *markerType = (char *) buf + offset + sizeof(rda_marker_t);
			int maxLen = size - (markerType - (char *) buf);
			int typeLen = strnlen(markerType, maxLen);
			eventdef_t *evdef;
			
			printf("Marker: Pos=%i  Length=%i  Channel=%i  Type=%.*s\n", marker->nPosition, marker->nPoints, marker->nChannel, maxLen, markerType);
			
			offset+=marker->nSize;
			
			evdef = (eventdef_t *) evbuf + evsiz;
			evdef->type_type = DATATYPE_CHAR;
			evdef->type_numel = typeLen;
			evdef->value_type = DATATYPE_INT32;
			evdef->value_numel = 1;
			evdef->sample = samplesWritten + marker->nPosition;
			evdef->offset = 0;
			evdef->duration = marker->nPoints;
			evdef->bufsize = typeLen + sizeof(INT32_T);
			
			memcpy(evbuf + evsiz + sizeof(eventdef_t), markerType, typeLen);
			*((INT32_T *) (evbuf + evsiz + sizeof(eventdef_t) + typeLen)) = marker->nChannel;
			
			evsiz += evdef->bufsize + sizeof(eventdef_t);
		}
		
		reqdef.version = VERSION;
		reqdef.command = PUT_EVT;
		reqdef.bufsize = evsiz;
		request.buf = evbuf;
		if (clientrequest(ftSocket, &request, &response)) {
			fprintf(stderr, "Error when writing events to buffer.\n");
		} else {
			if (response->def->command != PUT_OK) {
				fprintf(stderr, "Buffer server returned an error (writing events).\n");
			}
			free(response->def);
			if (response->buf) free(response->buf);
			free(response);
		}
		free(evbuf);
	}	
	
	if (goodToSend && header->nPoints > 0) {
		/* Write samples to FieldTrip buffer */
		datadef_t *ddef = (datadef_t *) malloc(sizeof(datadef_t) + sizeData);
		if (ddef == NULL) {
			fprintf(stderr, "Out of memory!\n");
			return;
		}
		ddef->nsamples = header->nPoints;
		ddef->nchans = numChannels;
		ddef->data_type = isInt ? DATATYPE_INT16 : DATATYPE_FLOAT32;
		ddef->bufsize = sizeData;
		/* ddef+1 points at first byte after datadef, header+1 points at first byte after RDA header */
		memcpy(ddef + 1, header + 1, sizeData);
		
		reqdef.version = VERSION;
		reqdef.command = PUT_DAT;
		reqdef.bufsize = sizeof(datadef_t) + sizeData;
		request.buf = ddef;
		if (clientrequest(ftSocket, &request, &response)) {
			fprintf(stderr, "Error when writing samples to buffer.\n");
		} else {
			if (response->def->command != PUT_OK) {
				fprintf(stderr, "Buffer server returned an error (writing samples).\n");
			} else {
				samplesWritten += header->nPoints;
			}
			free(response->def);
			if (response->buf) free(response->buf);
			free(response);
		}
		free(ddef);
	}	
}
Exemple #9
0
void buffer_putevt(char *hostname, int port, mxArray * plhs[], const mxArray * prhs[])
{
  size_t n;
  int server, fieldnumber;
  mxArray *field;
  char msg[512];
  
  message_t   *request  = NULL;
  message_t   *response = NULL;
  event_t     *event   = NULL;
  
  /* allocate the event */
  event      = malloc(sizeof(event_t));
  event->def = malloc(sizeof(eventdef_t));
  event->buf = NULL;
  event->def->bufsize   = 0;
  
  /* allocate the request message */
  request      = malloc(sizeof(message_t));
  request->def = malloc(sizeof(messagedef_t));
  request->buf = NULL;
  request->def->version = VERSION;
  request->def->command = PUT_EVT;
  request->def->bufsize = 0;
  
  /* define the event, it has the fields type_type type_numel value_type value_numel sample offset duration */
  
  /* FIXME loop over mutiple events in case of an event-array */
  
  fieldnumber = mxGetFieldNumber(prhs[0], "type_type");
  if (fieldnumber<0) {
    mexErrMsgTxt("field 'type_type' is missing");
    goto cleanup;
  }
  else
  {
    field = mxGetFieldByNumber(prhs[0], 0, fieldnumber);
    if (!mxIsNumeric(field) || mxIsEmpty(field)) {
      mexErrMsgTxt("invalid data type for 'type_type'");
      goto cleanup;
    }
    else
      event->def->type_type = (UINT32_T)mxGetScalar(field) ;
  }
  
  fieldnumber = mxGetFieldNumber(prhs[0], "type_numel");
  if (fieldnumber<0) {
    mexErrMsgTxt("field 'type_numel' is missing");
    goto cleanup;
  }
  else
  {
    field = mxGetFieldByNumber(prhs[0], 0, fieldnumber);
    if (!mxIsNumeric(field) || mxIsEmpty(field)) {
      mexErrMsgTxt("invalid data type for 'type_numel'");
      goto cleanup;
    }
    else
      event->def->type_numel = (UINT32_T)mxGetScalar(field) ;
  }
  
  fieldnumber = mxGetFieldNumber(prhs[0], "value_type");
  if (fieldnumber<0) {
    mexErrMsgTxt("field 'value_type' is missing");
    goto cleanup;
  }
  else
  {
    field = mxGetFieldByNumber(prhs[0], 0, fieldnumber);
    if (!mxIsNumeric(field) || mxIsEmpty(field)) {
      mexErrMsgTxt("invalid data type for 'value_type'");
      goto cleanup;
    }
    else
      event->def->value_type = (UINT32_T)mxGetScalar(field) ;
  }
  
  fieldnumber = mxGetFieldNumber(prhs[0], "value_numel");
  if (fieldnumber<0) {
    mexErrMsgTxt("field 'value_numel' is missing");
    goto cleanup;
  }
  else
  {
    field = mxGetFieldByNumber(prhs[0], 0, fieldnumber);
    if (!mxIsNumeric(field) || mxIsEmpty(field)) {
      mexErrMsgTxt("invalid data type for 'value_numel'");
      goto cleanup;
    }
    else
      event->def->value_numel = (UINT32_T)mxGetScalar(field) ;
  }
  
  fieldnumber = mxGetFieldNumber(prhs[0], "sample");
  if (fieldnumber<0) {
    mexErrMsgTxt("field 'sample' is missing");
    goto cleanup;
  }
  else
  {
    field = mxGetFieldByNumber(prhs[0], 0, fieldnumber);
    if (!mxIsNumeric(field) || mxIsEmpty(field)) {
      mexErrMsgTxt("invalid data type for 'sample'");
      goto cleanup;
    }
    else
      event->def->sample = (INT32_T)mxGetScalar(field) ;
  }
  
  fieldnumber = mxGetFieldNumber(prhs[0], "offset");
  if (fieldnumber<0) {
    mexErrMsgTxt("field 'offset' is missing");
    goto cleanup;
  }
  else
  {
    field = mxGetFieldByNumber(prhs[0], 0, fieldnumber);
    if (!mxIsNumeric(field) || mxIsEmpty(field)) {
      mexErrMsgTxt("invalid data type for 'offset'");
      goto cleanup;
    }
    else
      event->def->offset = (INT32_T)mxGetScalar(field) ;
  }
  
  fieldnumber = mxGetFieldNumber(prhs[0], "duration");
  if (fieldnumber<0) {
    mexErrMsgTxt("field 'duration' is missing");
    goto cleanup;
  }
  else
  {
    field = mxGetFieldByNumber(prhs[0], 0, fieldnumber);
    if (!mxIsNumeric(field) || mxIsEmpty(field)) {
      mexErrMsgTxt("invalid data type for 'duration'");
      goto cleanup;
    }
    else
      event->def->duration = (INT32_T)mxGetScalar(field) ;
  }
  
  fieldnumber = mxGetFieldNumber(prhs[0], "bufsize");
  if (fieldnumber<0) {
    mexErrMsgTxt("field 'bufsize' is missing");
    goto cleanup;
  }
  else
  {
    field = mxGetFieldByNumber(prhs[0], 0, fieldnumber);
    if (!mxIsNumeric(field) || mxIsEmpty(field)) {
      mexErrMsgTxt("invalid data type for 'bufsize'");
      goto cleanup;
    }
    else
      event->def->bufsize = (INT32_T)mxGetScalar(field) ;
  }
  
  fieldnumber = mxGetFieldNumber(prhs[0], "buf");
  if (fieldnumber<0) {
    mexErrMsgTxt("field 'buf' is missing");
    goto cleanup;
  }
  else
  {
    field = mxGetFieldByNumber(prhs[0], 0, fieldnumber);
    if (!mxIsUint8(field)) {
      mexErrMsgTxt("invalid data type for 'buf'");
      goto cleanup;
    }
    else if (mxGetNumberOfElements(field) != event->def->bufsize ) {
      mexErrMsgTxt("invalid number of elements (buf)");
      goto cleanup;
    }
    else {
      /* FIXME check the allocation */
      event->buf = malloc(event->def->bufsize);
      memcpy(event->buf, mxGetPr(field), event->def->bufsize);
    }
  }
  
  /* construct a PUT_EVT request */
  request->def->bufsize = append(&request->buf, request->def->bufsize, event->def, sizeof(eventdef_t));
  request->def->bufsize = append(&request->buf, request->def->bufsize, event->buf, event->def->bufsize);
  
  /* the event structure is not needed any more */
  FREE(event->def);
  FREE(event->buf);
  FREE(event);
  
  /* open the TCP socket */
  if ((server = open_connection(hostname, port)) < 0) {
    sprintf(msg, "ERROR: failed to create socket (%d)\n", server);
		mexErrMsgTxt(msg);
  }
  
  /* write the request, read the response */
  clientrequest(server, request, &response);
  close_connection(server);
  
  /* the request structure is not needed any more */
  if (request) {
    FREE(request->def);
    FREE(request->buf);
    FREE(request);
  }
  
  /* check that the response is PUT_OK */
  if (!response)
    mexErrMsgTxt("unknown error in response\n");
  else if (!response->def)
    mexErrMsgTxt("unknown error in response\n");
  else if (response->def->command!=PUT_OK)
  {
    sprintf(msg, "ERROR: the buffer returned an error (%d)\n", response->def->command);
		mexErrMsgTxt(msg);
  }
  
  /* the response structure is not needed any more */
  if (response) {
    FREE(response->def);
    FREE(response->buf);
    FREE(response);
  }
  
  return;
  
  cleanup:
    FREE(event->def);
    FREE(event->buf);
    FREE(event);
    if (request) {
      FREE(request->def);
      FREE(request->buf);
      FREE(request);
    }
    if (response) {
      FREE(response->def);
      FREE(response->buf);
      FREE(response);
    }
    
    return;
}
Exemple #10
0
int main(int argc, char *argv[])
{
  struct sockaddr_in si_me, si_other;
  socklen_t slen = sizeof(struct sockaddr_in);
  int udpsocket, n;
  char buf[BUFLEN];

  struct {
    uint16_t version;
    uint16_t nchans;
    uint16_t nbit;
    uint16_t fsample;
    uint16_t sec;
    uint16_t smp;
  } packet_v0;

  struct {
    uint8_t version;
    uint8_t nchans;
    uint16_t diagnostic_word;
    uint16_t mode_word;
    uint16_t fsample;
    uint32_t smp;
  } packet_v3;

  /* this is the common denominator of packet format v0 and v3 */
  struct {
    uint16_t version;
    uint16_t nchans;
    uint16_t nbit;
    uint16_t fsample;
    uint32_t smp;
  } packet;

  int sample = 0, status = 0, verbose = 0;
  host_t host;

  /* these represent the acquisition system properties */
  int nchans         = 16;   /* will be updated later on */
  int fsample        = 1000; /* will be updated later on */
  int nbit           = 16;
  int blocksize      = 43;

  /* these are used in the communication with the FT buffer and represent statefull information */
  int ftSocket           = -1;
  ft_buffer_server_t *ftServer;
  message_t    *request  = NULL;
  message_t    *response = NULL;
  header_t     *header   = NULL;
  data_t       *data     = NULL;

  printf(usage);

  if (argc>1)
    strcpy(host.name, argv[1]);
  else {
    strcpy(host.name, FTHOST);
  }

  if (argc>2)
    host.port = atoi(argv[2]);
  else {
    host.port = FTPORT;
  }

  fprintf(stderr, "jaga2ft: hostname     =  %s\n", host.name);
  fprintf(stderr, "jaga2ft: port         =  %d\n", host.port);

  /* Spawn tcpserver or connect to remote buffer */
  if (strcmp(host.name, "-") == 0) {
    ftServer = ft_start_buffer_server(host.port, NULL, NULL, NULL);
    if (ftServer==NULL) {
      fprintf(stderr, "jaga2ft: could not start up a local buffer serving at port %i\n", host.port);
      return 1;
    }
    ftSocket = 0;
    printf("jaga2ft: streaming to local buffer on port %i\n", host.port);
  }
  else {
    ftSocket = open_connection(host.name, host.port);

    if (ftSocket < 0) {
      fprintf(stderr, "jaga2ft: could not connect to remote buffer at %s:%i\n", host.name, host.port);
      return 1;
    }
    printf("jaga2ft: streaming to remote buffer at %s:%i\n", host.name, host.port);
  }  

  /* open the UDP server */
  if ((udpsocket=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1)
    diep("socket udp");
  int enable = 1;
  if (setsockopt(udpsocket, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)) < 0)
    diep("setsockopt");
  memset((char *) &si_me, 0, sizeof(si_me));
  si_me.sin_family      = AF_INET;
  si_me.sin_port        = htons(JAGAPORT);
  si_me.sin_addr.s_addr = htonl(INADDR_ANY);
  if (bind(udpsocket, &si_me, sizeof(si_me))==-1)
    diep("bind udp");

  /* allocate the elements that will be used in the communication to the FT buffer */
  request      = malloc(sizeof(message_t));
  request->def = malloc(sizeof(messagedef_t));
  request->buf = NULL;
  request->def->version = VERSION;
  request->def->bufsize = 0;

  header      = malloc(sizeof(header_t));
  header->def = malloc(sizeof(headerdef_t));
  header->buf = NULL;

  data      = malloc(sizeof(data_t));
  data->def = malloc(sizeof(datadef_t));
  data->buf = NULL;

  /* read the first packet to get some information */
  if ((n=recvfrom(udpsocket, buf, BUFLEN, 0, &si_other, &slen))==-1)
    diep("recvfrom()");
  if (verbose>0)
    printf("jaga2ft: received %d byte packet from %s:%d\n", n, inet_ntoa(si_other.sin_addr), ntohs(si_other.sin_port));

  /* parse the UDP package */
  if (buf[0]==0) {
    packet_v0.version = *(uint16_t *)(buf+0);
    packet_v0.nchans  = *(uint16_t *)(buf+2);
    packet_v0.nbit    = *(uint16_t *)(buf+4);
    packet_v0.fsample = *(uint16_t *)(buf+6);
    packet_v0.sec     = *(uint16_t *)(buf+8);
    packet_v0.smp     = *(uint16_t *)(buf+10);
    /* the packets are quite similar, the data starts at the same location */
    packet.version = packet_v0.version;
    packet.nchans  = packet_v0.nchans;
    packet.nbit    = packet_v0.nbit;
    packet.fsample = packet_v0.fsample;
    packet.smp     = packet_v0.smp;
  }
  else if (buf[0]==3) {
    packet_v3.version         = *(uint8_t  *)(buf+0);
    packet_v3.nchans          = *(uint8_t  *)(buf+1);
    packet_v3.diagnostic_word = *(uint16_t *)(buf+2);
    packet_v3.mode_word       = *(uint16_t *)(buf+4);
    packet_v3.fsample         = *(uint16_t *)(buf+6);
    packet_v3.smp             = *(uint32_t *)(buf+8);
    /* the packets are quite similar, the data starts at the same location */
    packet.version = packet_v3.version;
    packet.nchans  = packet_v3.nchans;
    packet.nbit    = 16;
    packet.fsample = packet_v3.fsample;
    packet.smp     = packet_v3.smp;
  }
  else {
    fprintf(stderr, "invalid packet version");
    exit(1);
  }

  /* update the defaults */
  nchans  = packet.nchans;
  fsample = packet.fsample;

  /* define the header */
  header->def->nchans    = nchans;
  header->def->nsamples  = 0;
  header->def->nevents   = 0;
  header->def->fsample   = fsample;
  header->def->data_type = DATATYPE_UINT16;
  header->def->bufsize   = 0;

  /* define the constant part of the data and allocate space for the variable part */
  data->def->nchans    = nchans;
  data->def->nsamples  = blocksize;
  data->def->data_type = DATATYPE_UINT16;
  data->def->bufsize   = WORDSIZE_UINT16*nchans*blocksize;

  /* initialization phase, send the header */
  request->def->command = PUT_HDR;
  request->def->bufsize = append(&request->buf, request->def->bufsize, header->def, sizeof(headerdef_t));
  request->def->bufsize = append(&request->buf, request->def->bufsize, header->buf, header->def->bufsize);

  /* this is not needed any more */
  cleanup_header(&header);

  status = clientrequest(ftSocket, request, &response);
  if (verbose>0) fprintf(stderr, "jaga2ft: clientrequest returned %d\n", status);
  if (status) {
    fprintf(stderr, "jaga2ft: could not send request to buffer\n");
    exit(1);
  }

  if (status || response==NULL || response->def == NULL) {
    fprintf(stderr, "jaga2ft: err2\n");
    exit(1);
  }

  cleanup_message(&request);

  if (response->def->command != PUT_OK) {
    fprintf(stderr, "jaga2ft: error in 'put header' request.\n");
    exit(1);
  }

  cleanup_message(&response);

  /* register CTRL-C handler */
  signal(SIGINT, abortHandler);

  printf("Starting to listen - press CTRL-C to quit\n");

  /* add a small pause between writing header + first data block */
  usleep(200000);

  while (keepRunning) 
  {

    if (verbose>1) 
      for (n=0; n<12; n++) 
	printf("buf[%2u] = %hhu\n", n, buf[n]);

    /* parse the UDP package */
    if (buf[0]==0) {
      packet_v0.version = *(uint16_t *)(buf+0);
      packet_v0.nchans  = *(uint16_t *)(buf+2);
      packet_v0.nbit    = *(uint16_t *)(buf+4);
      packet_v0.fsample = *(uint16_t *)(buf+6);
      packet_v0.sec     = *(uint16_t *)(buf+8);
      packet_v0.smp     = *(uint16_t *)(buf+10);
      /* the packets are quite similar, the data starts at the same location */
      packet.version = packet_v0.version;
      packet.nchans  = packet_v0.nchans;
      packet.nbit    = packet_v0.nbit;
      packet.fsample = packet_v0.fsample;
      packet.smp     = packet_v0.smp;
    }
    else if (buf[0]==3) {
      packet_v3.version         = *(uint8_t  *)(buf+0);
      packet_v3.nchans          = *(uint8_t  *)(buf+1);
      packet_v3.diagnostic_word = *(uint16_t *)(buf+2);
      packet_v3.mode_word       = *(uint16_t *)(buf+4);
      packet_v3.fsample         = *(uint16_t *)(buf+6);
      packet_v3.smp             = *(uint32_t *)(buf+8);
      /* the packets are quite similar, the data starts at the same location */
      packet.version = packet_v3.version;
      packet.nchans  = packet_v3.nchans;
      packet.nbit    = 16;
      packet.fsample = packet_v3.fsample;
      packet.smp     = packet_v3.smp;
    }
    else {
      fprintf(stderr, "invalid packet version");
      exit(1);
    }

    /* point to the data */
    data->buf = (buf+12);

    /* do some sanity checks */
    if (packet.nchans!=nchans) {
      fprintf(stderr, "jaga2ft: inconsistent number of channels %hu\n", packet.nchans);
      exit(1);
    }
    if (packet.nbit!=nbit) {
      fprintf(stderr, "jaga2ft: inconsistent number of bits %hu\n", packet.nbit);
      exit(1);
    }
    if (packet.fsample!=fsample) {
      fprintf(stderr, "jaga2ft: inconsistent sampling rate %hu\n", packet.fsample);
      exit(1);
    }

    /* create the request */
    request      = malloc(sizeof(message_t));
    request->def = malloc(sizeof(messagedef_t));
    request->buf = NULL;
    request->def->version = VERSION;
    request->def->bufsize = 0;
    request->def->command = PUT_DAT;
    request->def->bufsize = append(&request->buf, request->def->bufsize, data->def, sizeof(datadef_t));
    request->def->bufsize = append(&request->buf, request->def->bufsize, data->buf, data->def->bufsize);

    status = clientrequest(ftSocket, request, &response);
    if (verbose>0) fprintf(stderr, "jaga2ft: clientrequest returned %d\n", status);
    if (status) {
      fprintf(stderr, "jaga2ft: err3\n");
      exit(1);
    }

    if (status) {
      fprintf(stderr, "jaga2ft: err4\n");
      exit(1);
    }

    sample += blocksize;
    printf("jaga2ft: sample count = %i\n", sample);

    /* FIXME do someting with the response, i.e. check that it is OK */
    cleanup_message(&request);

    if (response == NULL || response->def == NULL || response->def->command!=PUT_OK) {
      fprintf(stderr, "Error when writing samples.\n");
    }
    cleanup_message(&response);

    /* read the next packet */
    if ((n=recvfrom(udpsocket, buf, BUFLEN, 0, &si_other, &slen))==-1)
      diep("recvfrom()");
    if (verbose>0)
      printf("jaga2ft: received %d byte packet from %s:%d\n", n, inet_ntoa(si_other.sin_addr), ntohs(si_other.sin_port));

  } /* while(1) */

  data->buf = NULL; /* this is not allocated on the heap but pointing to somewhere on the stack */
  cleanup_data(&data);
  close(udpsocket);

  if (ftSocket > 0) {
    close_connection(ftSocket);
  } else {
    ft_stop_buffer_server(ftServer);
  }
  return 0;
}
Exemple #11
0
void buffer_getdat(char *hostname, int port, mxArray *plhs[], const mxArray *prhs[])
{
  int server;
  int verbose = 0;
  size_t n;
  double *val;
  char msg[512];
  
  message_t *request  = NULL;
  message_t *response = NULL;
  header_t  *header   = NULL;
  data_t    *data     = NULL;
  datasel_t datasel;
  
  /* this is for the Matlab specific output */
  const char *field_names[NUMBER_OF_FIELDS] = {"nchans", "nsamples", "data_type", "bufsize", "buf"};
  mxArray *datp;
  
  /* allocate the elements that will be used in the communication */
  request      = malloc(sizeof(message_t));
  request->def = malloc(sizeof(messagedef_t));
  request->buf = NULL;
  request->def->version = VERSION;
  request->def->command = GET_DAT;
  request->def->bufsize = 0;
  
  if ((prhs[0]!=NULL) && (mxGetNumberOfElements(prhs[0])==2) && (mxIsDouble(prhs[0])) && (!mxIsComplex(prhs[0]))) {
    /* fprintf(stderr, "args OK\n"); */
    val = (double *)mxGetData(prhs[0]);
    datasel.begsample = (UINT32_T)(val[0]);
    datasel.endsample = (UINT32_T)(val[1]);
    if (verbose) print_datasel(&datasel);
    request->def->bufsize = append(&request->buf, request->def->bufsize, &datasel, sizeof(datasel_t));
  }
  
  /* open the TCP socket */
  if ((server = open_connection(hostname, port)) < 0) {
    sprintf(msg, "ERROR: failed to create socket (%d)\n", server);
		mexErrMsgTxt(msg);
  }
  
  if (verbose) print_request(request->def);
  clientrequest(server, request, &response);
  if (verbose) print_response(response->def);
  close_connection(server);
  
  if (response->def->command==GET_OK) {
    data      = malloc(sizeof(data_t));
    data->def = response->buf;
    data->buf = (char *)response->buf + sizeof(datadef_t);
    if (verbose) print_datadef(data->def);
    
    switch (data->def->data_type) {
      case DATATYPE_INT8:
        datp = mxCreateNumericMatrix(data->def->nchans, data->def->nsamples, mxINT8_CLASS, mxREAL);
        memcpy(mxGetPr(datp), data->buf, data->def->nchans*data->def->nsamples*WORDSIZE_INT8);
        break;
      case DATATYPE_INT16:
        datp = mxCreateNumericMatrix(data->def->nchans, data->def->nsamples, mxINT16_CLASS, mxREAL);
        memcpy(mxGetPr(datp), data->buf, data->def->nchans*data->def->nsamples*WORDSIZE_INT16);
        break;
      case DATATYPE_INT32:
        datp = mxCreateNumericMatrix(data->def->nchans, data->def->nsamples, mxINT32_CLASS, mxREAL);
        memcpy(mxGetPr(datp), data->buf, data->def->nchans*data->def->nsamples*WORDSIZE_INT32);
        break;
      case DATATYPE_INT64:
        datp = mxCreateNumericMatrix(data->def->nchans, data->def->nsamples, mxINT64_CLASS, mxREAL);
        memcpy(mxGetPr(datp), data->buf, data->def->nchans*data->def->nsamples*WORDSIZE_INT64);
        break;
      case DATATYPE_FLOAT32:
        datp = mxCreateNumericMatrix(data->def->nchans, data->def->nsamples, mxSINGLE_CLASS, mxREAL);
        memcpy(mxGetPr(datp), data->buf, data->def->nchans*data->def->nsamples*WORDSIZE_FLOAT32);
        break;
      case DATATYPE_FLOAT64:
        datp = mxCreateNumericMatrix(data->def->nchans, data->def->nsamples, mxDOUBLE_CLASS, mxREAL);
        memcpy(mxGetPr(datp), data->buf, data->def->nchans*data->def->nsamples*WORDSIZE_FLOAT64);
        break;
        default:
          mexErrMsgTxt("ERROR; unsupported data type\n");
    }
    
    plhs[0] = mxCreateStructMatrix(1, 1, NUMBER_OF_FIELDS, field_names);
    mxSetFieldByNumber(plhs[0], 0, 0, mxCreateDoubleScalar((double)data->def->nchans));
    mxSetFieldByNumber(plhs[0], 0, 1, mxCreateDoubleScalar((double)(data->def->nsamples)));
    mxSetFieldByNumber(plhs[0], 0, 2, mxCreateDoubleScalar((double)(data->def->data_type)));
    mxSetFieldByNumber(plhs[0], 0, 3, mxCreateDoubleScalar((double)(data->def->bufsize)));
    mxSetFieldByNumber(plhs[0], 0, 4, datp);
    FREE(data);
  }
  else {
    sprintf(msg, "ERROR: the buffer returned an error (%d)\n", response->def->command);
		mexErrMsgTxt(msg);
  }
  
  if (request) {
    FREE(request->def);
    FREE(request->buf);
    FREE(request);
  }
  if (response) {
    FREE(response->def);
    FREE(response->buf);
    FREE(response);
  }
  
  return;
}
Exemple #12
0
/** Prepares "start" RDA packet with channel names determined from the corresponding chunk (or empty)
	Also converts to little-endian if this machine is big endian
	@param hdr  Points to headerdef_t structure, will be filled, may not be NULL
	@return created start item, or NULL on error (connection / out of memory)
*/
rda_buffer_item_t *rda_aux_get_hdr_prep_start(int ft_buffer, headerdef_t *hdr) {
	rda_buffer_item_t *item = NULL;
	const ft_chunk_t *chunk;
	rda_msg_start_t *R;
	char *str;
	double *dRes;
	const void *dResSource;
	size_t bytesTotal;
	int i,r,numExtraZeros,sizeOrgNames;
	message_t req, *resp = NULL;
	messagedef_t msg_def;	
	
	req.def = &msg_def;
	req.buf = NULL;
	msg_def.version = VERSION;
	msg_def.command = GET_HDR;
	msg_def.bufsize = 0;
	
	r = clientrequest(ft_buffer, &req, &resp);
	if (r<0 || resp == NULL || resp->def == NULL) {
		goto cleanup;
	}
	
	if (resp->def->command != GET_OK || resp->def->bufsize < sizeof(headerdef_t) || resp->buf == NULL) {
		goto cleanup;
	}
	
	memcpy(hdr, resp->buf, sizeof(headerdef_t));
	
	/* Ok, we have the basic header, now look for proper FT_CHUNK_RESOLUTIONS */
	chunk = find_chunk(resp->buf, sizeof(headerdef_t), resp->def->bufsize, FT_CHUNK_RESOLUTIONS);
	if (chunk != NULL && chunk->def.size == hdr->nchans*sizeof(double)) {
		dResSource = chunk->data;
		/* fine - we just need a memcpy later on */
	} else {
		dResSource = NULL;
		/* no suitable chunk found - set defaults later on */
	}
	
	/* Now see if we can find channel names */
	chunk = find_chunk(resp->buf, sizeof(headerdef_t), resp->def->bufsize, FT_CHUNK_CHANNEL_NAMES);
	if (chunk != NULL && chunk->def.size >= hdr->nchans) {
		/* The chunk seems ok - check whether we really have N (0-terminated) strings */
		int k,nz = 0;
		for (k = 0; k<chunk->def.size && nz<=hdr->nchans; k++) {
			if (chunk->data[k] == 0) nz++;
		}
		/* Okay, either k is at the end and we have nz<=N, or we have reached N=nz before the
		   end of the chunk. In both cases, it's safe to transmit the first 'k' bytes and
		   add (N-nz) trailing zeros */
		numExtraZeros = hdr->nchans - nz;
		sizeOrgNames = k;
	} else {
		sizeOrgNames = 0;
		numExtraZeros = hdr->nchans;
	}
	
	bytesTotal = sizeof(rda_msg_start_t) + hdr->nchans*(sizeof(double)) + sizeOrgNames + numExtraZeros;
		
	item = rda_aux_alloc_item(bytesTotal);
	if (item == NULL) goto cleanup;
		
	R = (rda_msg_start_t *) item->data;
	memcpy(R->hdr.guid, _rda_guid, sizeof(_rda_guid));
	R->hdr.nSize = bytesTotal;
	R->hdr.nType = RDA_START_MSG;
	R->nChannels = hdr->nchans;
	R->dSamplingInterval = 1.0e6/(double) hdr->fsample;	/* should be in microseconds */
	
	if (_i_am_big_endian_) {
		/* take care of hdr.nSize, hdr.nType, nChannels */
		ft_swap32(3, &(R->hdr.nSize)); 
		ft_swap64(1, &(R->dSamplingInterval));
	}
	
	/* R+1 points to first byte after header info */
	dRes = (double *) ((void *)(R+1)); 
	if (dResSource == NULL) {
		/* Fill with resolution = 1.0 -- we have nothing better */
		for (i=0;i<hdr->nchans;i++) dRes[i]=1.0;
	} else {
		memcpy(dRes, dResSource, hdr->nchans * sizeof(double));
	}
	/* swap byte order if necessary */
	if (_i_am_big_endian_) {
		ft_swap64(hdr->nchans, dRes);
	}
	
	/* Let 'str' point to first byte after the resolution values */
	str = (char *) ((void *)(dRes + hdr->nchans));
	if (sizeOrgNames > 0) {
		memcpy(str, chunk->data, sizeOrgNames);
	}
	for (i=0;i<numExtraZeros;i++) str[sizeOrgNames + i] = 0;
	
	/* done */
cleanup:
	if (resp) {
		if (resp->def) free(resp->def);
		if (resp->buf) free(resp->buf);
		free(resp);
	}
	return item;
}	
Exemple #13
0
/** Retrieves samples and markers and returns them in as a new 'item', or NULL on errors.
*/
rda_buffer_item_t *rda_aux_get_samples_and_markers(int ft_buffer, const samples_events_t *last, const samples_events_t *cur, int numBlock, int use16bit) {
	rda_buffer_item_t *item = NULL;
	int numEvt = 0,numChans = 0,numSmp = 0;
	message_t req, *respSmp = NULL, *respEvt = NULL;
	messagedef_t msg_def;
	datadef_t *ddef;
	size_t bytesSamples = 0, bytesMarkers = 0;
	
	/* First, try to grab the samples */
	if (cur->nsamples > last->nsamples) {
		datasel_t dat_sel;
		
		msg_def.version = VERSION;
		msg_def.command = GET_DAT;
		msg_def.bufsize = sizeof(dat_sel);
		dat_sel.begsample = last->nsamples;
		dat_sel.endsample = cur->nsamples-1;
		req.def = &msg_def;
		req.buf = &dat_sel;
	
		if (clientrequest(ft_buffer, &req, &respSmp)<0) {
			goto cleanup;
		}
		
		numSmp = cur->nsamples - last->nsamples;
		
		if (respSmp == NULL || respSmp->def == NULL || respSmp->buf == NULL || respSmp->def->command != GET_OK) {
			goto cleanup;
		} else {
			ddef = (datadef_t *) respSmp->buf;
			
			if (ddef->nsamples != numSmp) goto cleanup;
			
			numChans = ddef->nchans;
			bytesSamples  = (use16bit ? sizeof(INT16_T) : sizeof(float)) * numSmp * numChans;
		}
	} 
	
	/* Now, try to grab the markers */
	if (cur->nevents > last->nevents) {
		eventsel_t evt_sel;
		int offset = 0;
		
		msg_def.version = VERSION;
		msg_def.command = GET_EVT;
		msg_def.bufsize = sizeof(evt_sel);
		evt_sel.begevent = last->nevents;
		evt_sel.endevent = cur->nevents-1;
		req.def = &msg_def;
		req.buf = &evt_sel;
	
		if (clientrequest(ft_buffer, &req, &respEvt) < 0) {
			goto cleanup;
		}
		if (respEvt == NULL || respEvt->def == NULL || respEvt->buf == NULL || respEvt->def->command != GET_OK) {
			goto cleanup;
		}
		
		/* count the number of events, increase bytesTotal as required */
		while (offset + sizeof(eventdef_t) <= respEvt->def->bufsize) {
			eventdef_t *evdef = (eventdef_t *) ((char *)respEvt->buf + offset);
			offset += sizeof(eventdef_t) + evdef->bufsize;
			
			if (evdef->bufsize < evdef->type_numel*wordsize_from_type(evdef->type_type) + evdef->value_numel*wordsize_from_type(evdef->value_type)) {
				fprintf(stderr,"Invalid event received: Buffer to small for given value/type description\n");
				continue;	/* Skip to next event */
			}
			
			bytesMarkers += sizeof(rda_marker_t);
			if (evdef->type_type == DATATYPE_CHAR) {
				if (evdef->value_type == DATATYPE_CHAR) {
					/* Transform into TYPE:VALUE\0 */
					bytesMarkers += evdef->type_numel + evdef->value_numel + 2;
				} else {
					/* Transform into TYPE:-\0 */
					bytesMarkers += evdef->type_numel + 3;
				}
			} else {
				if (evdef->value_type == DATATYPE_CHAR) {
					/* Transform into FT:VALUE\0 */
					bytesMarkers += evdef->value_numel + 4;
				} else {
					/* Transform into FT:-\0 */
					bytesMarkers += 5; 
				}
			}
			numEvt++;
		}
	}
	
	/* Now, allocate an item with enough space for both samples and markers */
	item = rda_aux_alloc_item(sizeof(rda_msg_data_t) + bytesSamples + bytesMarkers);
	if (item == NULL) {
		fprintf(stderr, "Out of memory\n");
		goto cleanup;
	}
	
	item->blockNumber = numBlock;
	
	/* Okay, we've got the samples in respSmp, events in respEvt, and a big enough 'item'.
		First fill in the header.
	*/
	{
		rda_msg_data_t *R = (rda_msg_data_t *) item->data;

		memcpy(R->hdr.guid, _rda_guid, sizeof(_rda_guid));
		R->hdr.nType = use16bit ? RDA_INT_MSG : RDA_FLOAT_MSG;
		R->hdr.nSize = item->size;
		R->nBlock = numBlock; 
		R->nPoints = numSmp;
		R->nMarkers = numEvt;
		if (_i_am_big_endian_) {
			/* take care of hdr.nSize, hdr.nType, nBlocks, nPoints, nMarkers */
			ft_swap32(5, &(R->hdr.nSize)); 
		}
	}
	
	/* Now, fill in the samples, possibly using conversion */
	if (numSmp > 0) {
		char *dataDest = ((char *) item->data + sizeof(rda_msg_data_t));
		char *dataSrc  = ((char *) respSmp->buf + sizeof(datadef_t));
		int numTotal = numSmp * numChans;
		
		if (use16bit) {
			if (_i_am_big_endian_) {
				/* copy + swap the 16 bit samples */
				int i;
				for (i=0;i<numTotal;i++) {
					dataDest[0] = dataSrc[1];
					dataDest[1] = dataSrc[0];
					dataDest+=2;
					dataSrc+=2;
				}
			} else {
				/* just copy the samples */
				memcpy(dataDest, dataSrc, bytesSamples);
			}
		} else {
			rda_aux_convert_to_float(numTotal, dataDest, ddef->data_type, dataSrc);
			if (_i_am_big_endian_) ft_swap32(numTotal, dataDest);
		}
	}
	
	/* Finally, fill in the events */
	if (numEvt>0) {
		char *ptr = (char *) item->data + sizeof(rda_msg_data_t) + bytesSamples;
		int offset = 0;
		
		/* count the number of events, increase bytesTotal as required */
		while (offset + sizeof(eventdef_t) <= respEvt->def->bufsize) {
			eventdef_t *evdef = (eventdef_t *) ((char *)respEvt->buf + offset);
			char *evbuf = (char *)respEvt->buf + offset + sizeof(eventdef_t);
			rda_marker_t *marker = (rda_marker_t *) ptr;
			int i, markerPos;
			
			offset += sizeof(eventdef_t) + evdef->bufsize;			
			
			if (evdef->bufsize < evdef->type_numel*wordsize_from_type(evdef->type_type) + evdef->value_numel*wordsize_from_type(evdef->value_type)) {
				continue; /* skip to next event */
			}
			
			markerPos = evdef->sample - (last->nsamples +1); /* relative to first sample in this block */
			marker->nPosition = (markerPos > 0) ? markerPos : 0;  /* needs to be unsigned! */
			marker->nChannel  = -1; /* All channels, FieldTrip doesn't have this*/
			marker->nPoints   = evdef->duration;
			
			ptr += sizeof(rda_marker_t);
			
			if (evdef->type_type == DATATYPE_CHAR) {
				/* copy type */
				for (i=0;i<evdef->type_numel;i++) {
					*ptr++ = *evbuf++;
				}
			} else {
				*ptr++ = 'F';
				*ptr++ = 'T';
				/* Skip bytes in event->buffer */
				evbuf += evdef->type_numel;
			}
			*ptr++ = ':';				
			if (evdef->value_type == DATATYPE_CHAR) {
				/* copy value */
				for (i=0;i<evdef->value_numel;i++) {
					*ptr++ = *evbuf++;
				}
			} else {
				*ptr++ = '-';
			}
			/* add trailing 0, see how big the complete marker got */
			*ptr++ = 0;
			marker->nSize = (ptr - (char *) marker);
			
			if (_i_am_big_endian_) {
				/* convert the 4 int32's in the marker definition */
				ft_swap32(4, (void *) marker);
			}
		}		
	} 
	/* Done */
cleanup:
	if (respSmp) {
		FREE(respSmp->buf);
		FREE(respSmp->def);
		free(respSmp);
	}
	if (respEvt) {
		FREE(respEvt->buf);
		FREE(respEvt->def);
		free(respEvt);
	}
	return item;
}
Exemple #14
0
void *event_thread(void *arg) {
	long tdif;
	host_t *host = (host_t *)arg;

	/* these will be sent as event */
    int sample  = 0;
    int value   = 0;
    char *type  = "trigger";

	/* these are used in the communication and represent statefull information */
	int server             = -1;
	message_t    *request  = NULL;
	message_t    *response = NULL;
	header_t     *header   = NULL;
	data_t       *data     = NULL;
	event_t      *event    = NULL;

	/* these represent the acquisition system properties */
	int fsample        = 250;
	int blocksize      = 125;

	/* this is to prevent closing the thread at an unwanted moment and memory from leaking */
	int oldcancelstate, oldcanceltype;
	pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldcancelstate);
	pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldcanceltype);
	pthread_cleanup_push(cleanup_message, request);
	pthread_cleanup_push(cleanup_message, response);
	pthread_cleanup_push(cleanup_header,  header);
	pthread_cleanup_push(cleanup_data,    data);
	pthread_cleanup_push(cleanup_event,   event);
	pthread_cleanup_push(cleanup_socket,  &server);

	/* this determines the hostname and port on which the client will write */
	if (!arg)
		exit(1);

	fprintf(stderr, "event: host.name =  %s\n", host->name);
	fprintf(stderr, "event: host.port =  %d\n", host->port);

	/* allocate the elements that will be used in the communication */
	request      = malloc(sizeof(message_t));
	request->def = malloc(sizeof(messagedef_t));
	request->buf = NULL;
	request->def->version = VERSION;
	request->def->bufsize = 0;

	header      = malloc(sizeof(header_t));
	header->def = malloc(sizeof(headerdef_t));
	header->buf = NULL;

	data      = malloc(sizeof(data_t));
	data->def = malloc(sizeof(datadef_t));
	data->buf = NULL;

	event      = malloc(sizeof(event_t));
	event->def = malloc(sizeof(eventdef_t));
	event->buf = NULL;

	while (1) {

		/* increment the trigger value on each iteration */
		value++;
		sample += blocksize;

		/* construct the event definition */
		event->def->type_type   = DATATYPE_CHAR; 
		event->def->type_numel  = strlen(type);
		event->def->value_type  = DATATYPE_INT32;
		event->def->value_numel = 1;
		event->def->sample      = sample;
		event->def->offset      = 0;
		event->def->duration    = 0;
		event->def->bufsize     = 0; /* see below */
		event->buf              = NULL;

		/* add the variable information to the event buffer */
		event->def->bufsize = append(&event->buf, event->def->bufsize, type,   event->def->type_numel);	/* type is a char-array */
		event->def->bufsize = append(&event->buf, event->def->bufsize, &value, WORDSIZE_INT32);			/* value is an integer  */

		/* construct the request */
		request->def->command = PUT_EVT;
		request->def->bufsize = append(&request->buf, request->def->bufsize, event->def, sizeof(eventdef_t));
		request->def->bufsize = append(&request->buf, request->def->bufsize, event->buf, event->def->bufsize);

		server = open_connection(host->name, host->port);
		clientrequest(server, request, &response);
		if (server>=0)
			closesocket(server);

		/* FIXME do someting with the response, i.e. check that it is OK */
		request->def->bufsize = 0;
		FREE(request->buf);
		event->def->bufsize = 0;
		FREE(event->buf);
		if (response) {
			FREE(response->def);
			FREE(response->buf);
			FREE(response);
		}

		/* approximate delay in microseconds */
		tdif = (long)(blocksize * 1000000 / fsample);
		usleep(tdif);

	} /* while(1) */

cleanup:
	/* from now on it is save to cancel the thread */
	pthread_setcancelstate(oldcancelstate, NULL);
	pthread_setcanceltype(oldcanceltype, NULL);

	pthread_cleanup_pop(1);  /* server */
	pthread_cleanup_pop(1);  /* event */
	pthread_cleanup_pop(1);  /* data */
	pthread_cleanup_pop(1);  /* header */
	pthread_cleanup_pop(1);  /* response */
	pthread_cleanup_pop(1);  /* request */

	pthread_exit(NULL);
	return NULL;
}
Exemple #15
0
int main(int argc, char *argv[]) {
  host_t host;
  
    /* these variables are for the threading */
  int rc;
  pthread_t tid;
  
    /* these variables are for writing the data */
  int i, j, k, status = 0, verbose = 0, samplecount = 0;
  time_t tic, toc;
  time_t elapsed;
  
  /* these represent the acquisition system properties */
  int fsample        = 512; /* this is just for the header */
  int nchans         = 32;
  int nsamples       = 64;
  int stateless      = 0;	  /* boolean */
  
  /* these are used in the communication and represent statefull information */
  int server             = -1;
  message_t    *request  = NULL;
  message_t    *response = NULL;
  header_t     *header   = NULL;
  data_t       *data     = NULL;
  event_t      *event    = NULL;
    
  
    /* start with defaults */
  sprintf(host.name, DEFAULT_HOSTNAME);
  host.port = DEFAULT_PORT;
  
  if (argc>1)
    sprintf(host.name, argv[1]);
  
  if (argc>2)
    host.port = atoi(argv[2]);
  
  if (argc>3)
    nchans = atoi(argv[3]);
  
  if (argc>4)
    nsamples = atoi(argv[4]);
  
  if (argc>5)
    stateless = atoi(argv[5]);
  

  check_datatypes();
  
  if (verbose>0) fprintf(stderr, "test_benchmark: host.name =  %s\n", host.name);
  if (verbose>0) fprintf(stderr, "test_benchmark: host.port =  %d\n", host.port);

  /* allocate the elements that will be used in the communication */
  request      = malloc(sizeof(message_t));
  request->def = malloc(sizeof(messagedef_t));
  request->buf = NULL;
  request->def->version = VERSION;
  request->def->bufsize = 0;
  
  header      = malloc(sizeof(header_t));
  header->def = malloc(sizeof(headerdef_t));
  header->buf = NULL;
  
  data      = malloc(sizeof(data_t));
  data->def = malloc(sizeof(datadef_t));
  data->buf = NULL;
  
  event      = malloc(sizeof(event_t));
  event->def = malloc(sizeof(eventdef_t));
  event->buf = NULL;
  
  /* define the header */
  header->def->nchans    = nchans;
  header->def->nsamples  = 0;
  header->def->nevents   = 0;
  header->def->fsample   = fsample;
  header->def->data_type = DATATYPE_FLOAT32;
  header->def->bufsize   = 0;
  FREE(header->buf);
  
  /* define the constant part of the data and allocate space for the variable part */
  data->def->nchans    = nchans;
  data->def->nsamples  = nsamples;
  data->def->data_type = DATATYPE_FLOAT32;
  data->def->bufsize   = WORDSIZE_FLOAT32*nchans*nsamples;
  FREE(data->buf);
  data->buf            = malloc(WORDSIZE_FLOAT32*nchans*nsamples);
    
    /* create the random data */
    for (j=0; j<nsamples; j++)
      for (i=0; i<nchans;    i++)
        ((FLOAT32_T *)(data->buf))[j*nchans+i] = 2.0*((FLOAT32_T)rand())/RAND_MAX - 1.0;
  
  /* initialization phase, send the header */
  request->def->command = PUT_HDR;
  request->def->bufsize = append(&request->buf, request->def->bufsize, header->def, sizeof(headerdef_t));
  request->def->bufsize = append(&request->buf, request->def->bufsize, header->buf, header->def->bufsize);
  
  server = open_connection(host.name, host.port);
  status = clientrequest(server, request, &response);
  if (verbose>0) fprintf(stderr, "test_benchmark: clientrequest returned %d\n", status);
  if (status) {
    fprintf(stderr, "random: err1\n");
    goto cleanup;
  }
  
  if (stateless) {
    status = close_connection(server);
    if (status) {
      fprintf(stderr, "random: err2\n");
      goto cleanup;
    }
  }
  
  cleanup_message(&request);
  cleanup_message(&response);
  request = NULL;
  response = NULL;
  
  tic = time(NULL);
  
  while (1) {
    
    /* create the request */
    request      = malloc(sizeof(message_t));
    request->def = malloc(sizeof(messagedef_t));
    request->buf = NULL;
    request->def->version = VERSION;
    request->def->bufsize = 0;
    request->def->command = PUT_DAT;
    request->def->bufsize = append(&request->buf, request->def->bufsize, data->def, sizeof(datadef_t));
    request->def->bufsize = append(&request->buf, request->def->bufsize, data->buf, data->def->bufsize);
    
    if (stateless)
      server = open_connection(host.name, host.port);
    
    status = clientrequest(server, request, &response);
    if (verbose>0) fprintf(stderr, "random: clientrequest returned %d\n", status);
    if (status) {
      fprintf(stderr, "random: err3\n");
      goto cleanup;
    }

    if (stateless) {
      status = close_connection(server);
      if (status) {
        fprintf(stderr, "random: err4\n");
        goto cleanup;
      }
    }

    cleanup_message(&request);
    cleanup_message(&response);
    request = NULL;
    response = NULL;
    
    samplecount += nsamples*nchans;
    toc = time(NULL);
    elapsed = toc-tic;
    
   fprintf(stderr, "samplecount = %d, elapsed = %d, samples/sec = %f\n", samplecount, elapsed, ((float)(samplecount))/((float)elapsed));
    
  } /* while(1) */
  
  cleanup:
    cleanup_event(&event);
    cleanup_data(&data);
    cleanup_header(&header);
    cleanup_message(&request);
    cleanup_message(&response);
    
    pthread_exit(0);
    return 0;
}
Exemple #16
0
/** Background thread for grabbing setup and data packets from the internal, overallocated ringbuffer.
    This thread stops automatically if the socket pair is closed in the main thread.
*/
void *dataToFieldTripThread(void *arg) {
	ACQ_OverAllocType *pack;
	EventChain EC;
	int slot, res, i,j;
	int numChannels = 0, numSamples;
	int warningGiven = 0;
	messagedef_t reqdef;
	message_t request, *response;
	
	EC.evs = NULL;
	EC.sizeAlloc = 0;
	
	request.def = &reqdef;
	
	while (1) {
		res = read(mySockets[1], &slot, sizeof(int));
		
		if (res == 0) break; /* socket pair was closed - exit */
		
		if (res != sizeof(int)) {
			fprintf(stderr, "Error when reading from socket pair\n");
			break;
		}
		
		if (slot<0 || slot>=INT_RB_SIZE) {
			fprintf(stderr, "Got errorneous slot number from socket pair\n");
			break;
		}
		
		pack = &intPackets[slot];
		
		if (pack->message_type == ACQ_MSGQ_SETUP_COLLECTION) {
			UINT32_T size;
			headerdef_t *hdef;	/* contains header information + chunks !!! */
			
			hdef = handleRes4((const char *) pack->data, &size);
			/* clear internal ringbuffer slot */
			pack->message_type = ACQ_MSGQ_INVALID;
			
			if (hdef == NULL) continue;	/* problem while picking up header -- ignore this packet */
			
			/* prepare PUT_HDR request here, but only send it along with first data block */
			reqdef.version = VERSION;
			reqdef.command = PUT_HDR;
			reqdef.bufsize = size;
			request.buf = hdef;
				
			res = clientrequest(ftSocket, &request, &response);
				
			if (res < 0) {
				fprintf(stderr, "Error in FieldTrip connection\n");
			} else if (response) {
				if (response->def->command != PUT_OK) {
					fprintf(stderr, "Error in PUT_HDR\n");
				} else {
					/* printf("FT: Transmitted header\n"); */
					
					/* set numChannels variable to the value we picked up
					   this also enables transmitting data in following packets
					*/
					numChannels = hdef->nchans;
					warningGiven = 0;
				}
				cleanup_message((void **) &response);
			}
			free(hdef);
			
		} else if (pack->message_type == ACQ_MSGQ_DATA) {
			datadef_t *ddef; 
			int sampleNumber;
			
			if (numChannels == 0) {
				fprintf(stderr, "No header written yet -- ignoring data packet\n");
				pack->message_type = ACQ_MSGQ_INVALID;
				continue;
			}
			
			if (!warningGiven && pack->numChannels != numChannels) {
				printf("\nWARNING: Channel count in first data packet does not equal header information from .res4 file (%i channels)\n\n", numChannels);
				warningGiven = 1;
			}
			
			sampleNumber = pack->sampleNumber;
			numSamples   = pack->numSamples;
			
			/* Put the FT datadef at the location of the current ACQ packet definition.
			   This just fits, no memcpy'ing of the samples again... */
			ddef = (datadef_t *) &pack->messageId; 
			
			ddef->nsamples = numSamples;
			ddef->nchans = numChannels;
			ddef->data_type = DATATYPE_INT32;
			ddef->bufsize = sizeof(int) * numSamples * numChannels;
			
			reqdef.version = VERSION;
			reqdef.command = PUT_DAT;
			reqdef.bufsize = ddef->bufsize + sizeof(datadef_t);
			request.buf = ddef; /* data is still behind that */
			
			res = clientrequest(ftSocket, &request, &response);
			
			if (res < 0) {
				fprintf(stderr, "Error in FieldTrip connection (writing data)\n");
			} else if (response) {
				if (response->def->command != PUT_OK) {
					fprintf(stderr, "Error in PUT_DAT\n");
				} else {
					/* printf("FT: Transmitted samples\n"); */
				}
				cleanup_message((void **) &response);
			}
			
			/* look at trigger channels and add events to chain, clear this first */
			EC.size = EC.num = 0;
			for (j=0;j<numSamples;j++) {
				int *sj = pack->data + j*numChannels;
				for (i=0;i<numTriggerChannels;i++) {
					int sji = sj[triggerChannel[i]];
					if (sji != lastValue[i] && sji > 0) addTriggerEvent(&EC, i, sampleNumber + j, sji);
					lastValue[i] = sji;
				}
			}
			if (EC.size > 0) {
				reqdef.version = VERSION;
				reqdef.command = PUT_EVT;
				reqdef.bufsize = EC.size;
				request.buf = EC.evs;
				
				res = clientrequest(ftSocket, &request, &response);
			
				if (res < 0) {
					fprintf(stderr, "Error in FieldTrip connection (writing events)\n");
				} else if (response) {
					if (response->def->command != PUT_OK) {
						fprintf(stderr, "Error in PUT_EVT\n");
					} else {
						printf("Wrote %i events (%i bytes)\n", EC.num, reqdef.bufsize);
						/* printf("FT: Transmitted samples\n"); */
					}
				}
				cleanup_message((void **) &response);
			}
		} else {
			fprintf(stderr,"Converter thread: Packet contains neither SETUP nor DATA (%i)...\n", pack->message_type);
		}
		pack->message_type = ACQ_MSGQ_INVALID;
	}
	printf("Leaving converter thread...\n");
	close(mySockets[1]);
	if (EC.sizeAlloc > 0) free(EC.evs);
	return NULL;
}
Exemple #17
0
int main(int argc, char *argv[]) {
    int n, i, c, count = 0, sample = 0, chan = 0, status = 0, verbose = 0, labelSize;
    unsigned char buf[OPENBCI_BUFLEN], byte;
    char *labelString;
    SerialPort SP;
    host_t host;
    struct timespec tic, toc;

    /* these represent the general acquisition system properties */
    int nchans         = OPENBCI_NCHANS;
    float fsample      = OPENBCI_FSAMPLE;

    /* these are used in the communication with the FT buffer and represent statefull information */
    int ftSocket           = -1;
    ft_buffer_server_t *ftServer;
    message_t     *request  = NULL;
    message_t     *response = NULL;
    header_t      *header   = NULL;
    data_t        *data     = NULL;
    ft_chunkdef_t *label    = NULL;

    /* this contains the configuration details */
    configuration config;

    /* configure the default settings */
    config.blocksize     = 10;
    config.port          = 1972;
    config.hostname      = strdup("-");
    config.serial        = strdup("/dev/tty.usbserial-DN0094FY");
    config.reset         = strdup("on");
    config.datalog       = strdup("off");
    config.testsignal    = strdup("off");
    config.timestamp     = strdup("on");
    config.timeref       = strdup("start");

    config.enable_chan1  = strdup("on");
    config.enable_chan2  = strdup("on");
    config.enable_chan3  = strdup("on");
    config.enable_chan4  = strdup("on");
    config.enable_chan5  = strdup("on");
    config.enable_chan6  = strdup("on");
    config.enable_chan7  = strdup("on");
    config.enable_chan8  = strdup("on");
    config.enable_chan9  = strdup("on");
    config.enable_chan10 = strdup("on");
    config.enable_chan11 = strdup("on");

    config.label_chan1  = strdup("ADC1");
    config.label_chan2  = strdup("ADC2");
    config.label_chan3  = strdup("ADC3");
    config.label_chan4  = strdup("ADC4");
    config.label_chan5  = strdup("ADC5");
    config.label_chan6  = strdup("ADC6");
    config.label_chan7  = strdup("ADC7");
    config.label_chan8  = strdup("ADC8");
    config.label_chan9  = strdup("AccelerationX");
    config.label_chan10 = strdup("AccelerationY");
    config.label_chan11 = strdup("AccelerationZ");
    config.label_chan12 = strdup("TimeStamp");

    config.setting_chan1  = strdup("x1060110X");
    config.setting_chan2  = strdup("x2060110X");
    config.setting_chan3  = strdup("x3060110X");
    config.setting_chan4  = strdup("x4060110X");
    config.setting_chan5  = strdup("x5060110X");
    config.setting_chan6  = strdup("x6060110X");
    config.setting_chan7  = strdup("x7060110X");
    config.setting_chan8  = strdup("x8060110X");

    config.impedance_chan1  = strdup("z100Z");
    config.impedance_chan2  = strdup("z200Z");
    config.impedance_chan3  = strdup("z300Z");
    config.impedance_chan4  = strdup("z400Z");
    config.impedance_chan5  = strdup("z500Z");
    config.impedance_chan6  = strdup("z600Z");
    config.impedance_chan7  = strdup("z700Z");
    config.impedance_chan8  = strdup("z800Z");

    if (argc<2) {
        printf(usage);
        exit(0);
    }

    if (argc==2) {
        if (strncmp(argv[1], "/dev", 4)==0 || strncasecmp(argv[1], "COM", 3)==0)
            /* the second argument is the serial port */
            config.serial = strdup(argv[1]);
        else {
            /* the second argument is the configuration file */
            fprintf(stderr, "openbci2ft: loading configuration from '%s'\n", argv[1]);
            if (ini_parse(argv[1], iniHandler, &config) < 0) {
                fprintf(stderr, "Can't load '%s'\n", argv[1]);
                return 1;
            }
        }
    }

    if (argc>2)
        strcpy(host.name, argv[2]);
    else {
        strcpy(host.name, config.hostname);
    }

    if (argc>3)
        host.port = atoi(argv[3]);
    else {
        host.port = config.port;
    }

#define ISTRUE(s) strcasecmp(s, "on")==0
    nchans = 0;
    if (ISTRUE(config.enable_chan1))
        nchans++;
    if (ISTRUE(config.enable_chan2))
        nchans++;
    if (ISTRUE(config.enable_chan3))
        nchans++;
    if (ISTRUE(config.enable_chan4))
        nchans++;
    if (ISTRUE(config.enable_chan5))
        nchans++;
    if (ISTRUE(config.enable_chan6))
        nchans++;
    if (ISTRUE(config.enable_chan7))
        nchans++;
    if (ISTRUE(config.enable_chan8))
        nchans++;
    if (ISTRUE(config.enable_chan9))
        nchans++;
    if (ISTRUE(config.enable_chan10))
        nchans++;
    if (ISTRUE(config.enable_chan11))
        nchans++;
    if (ISTRUE(config.timestamp))
        nchans++;

    fprintf(stderr, "openbci2ft: serial       =  %s\n", config.serial);
    fprintf(stderr, "openbci2ft: hostname     =  %s\n", host.name);
    fprintf(stderr, "openbci2ft: port         =  %d\n", host.port);
    fprintf(stderr, "openbci2ft: blocksize    =  %d\n", config.blocksize);
    fprintf(stderr, "openbci2ft: reset        =  %s\n", config.reset);
    fprintf(stderr, "openbci2ft: datalog      =  %s\n", config.datalog);
    fprintf(stderr, "openbci2ft: timestamp    =  %s\n", config.timestamp);
    fprintf(stderr, "openbci2ft: testsignal   =  %s\n", config.testsignal);

    /* Spawn tcpserver or connect to remote buffer */
    if (strcmp(host.name, "-") == 0) {
        ftServer = ft_start_buffer_server(host.port, NULL, NULL, NULL);
        if (ftServer==NULL) {
            fprintf(stderr, "openbci2ft: could not start up a local buffer serving at port %i\n", host.port);
            return 1;
        }
        ftSocket = 0;
        printf("openbci2ft: streaming to local buffer on port %i\n", host.port);
    }
    else {
        ftSocket = open_connection(host.name, host.port);

        if (ftSocket < 0) {
            fprintf(stderr, "openbci2ft: could not connect to remote buffer at %s:%i\n", host.name, host.port);
            return 1;
        }
        printf("openbci2ft: streaming to remote buffer at %s:%i\n", host.name, host.port);
    }

    /* allocate the elements that will be used in the communication to the FT buffer */
    request      = malloc(sizeof(message_t));
    request->def = malloc(sizeof(messagedef_t));
    request->buf = NULL;
    request->def->version = VERSION;
    request->def->bufsize = 0;

    header      = malloc(sizeof(header_t));
    header->def = malloc(sizeof(headerdef_t));
    header->buf = NULL;

    data      = malloc(sizeof(data_t));
    data->def = malloc(sizeof(datadef_t));
    data->buf = NULL;

    /* define the header */
    header->def->nchans    = nchans;
    header->def->fsample   = fsample;
    header->def->nsamples  = 0;
    header->def->nevents   = 0;
    header->def->data_type = DATATYPE_FLOAT32;
    header->def->bufsize   = 0;

    /* FIXME add the channel names */
    labelSize = 0; /* count the number of bytes required */
    if (ISTRUE (config.enable_chan1))
        labelSize += strlen (config.label_chan1) + 1;
    if (ISTRUE (config.enable_chan2))
        labelSize += strlen (config.label_chan2) + 1;
    if (ISTRUE (config.enable_chan3))
        labelSize += strlen (config.label_chan3) + 1;
    if (ISTRUE (config.enable_chan4))
        labelSize += strlen (config.label_chan4) + 1;
    if (ISTRUE (config.enable_chan5))
        labelSize += strlen (config.label_chan5) + 1;
    if (ISTRUE (config.enable_chan6))
        labelSize += strlen (config.label_chan6) + 1;
    if (ISTRUE (config.enable_chan7))
        labelSize += strlen (config.label_chan7) + 1;
    if (ISTRUE (config.enable_chan8))
        labelSize += strlen (config.label_chan8) + 1;
    if (ISTRUE (config.enable_chan9))
        labelSize += strlen (config.label_chan9) + 1;
    if (ISTRUE (config.enable_chan10))
        labelSize += strlen (config.label_chan10) + 1;
    if (ISTRUE (config.enable_chan11))
        labelSize += strlen (config.label_chan11) + 1;
    if (ISTRUE (config.timestamp))
        labelSize += strlen (config.label_chan12) + 1;

    if (verbose > 0)
        fprintf (stderr, "openbci2ft: labelSize = %d\n", labelSize);

    /* go over all channels for a 2nd time, now copying the strings to the destination */
    labelString = (char *) malloc (labelSize * sizeof(char));
    labelSize   = 0; 
    if (ISTRUE (config.enable_chan1)) {
        strcpy (labelString+labelSize, config.label_chan1);
        labelSize += strlen (config.label_chan1) + 1;
    }
    if (ISTRUE (config.enable_chan2)) {
        strcpy (labelString+labelSize, config.label_chan2);
        labelSize += strlen (config.label_chan2) + 1;
    }
    if (ISTRUE (config.enable_chan3)) {
        strcpy (labelString+labelSize, config.label_chan3);
        labelSize += strlen (config.label_chan3) + 1;
    }
    if (ISTRUE (config.enable_chan4)) {
        strcpy (labelString+labelSize, config.label_chan4);
        labelSize += strlen (config.label_chan4) + 1;
    }
    if (ISTRUE (config.enable_chan5)) {
        strcpy (labelString+labelSize, config.label_chan5);
        labelSize += strlen (config.label_chan5) + 1;
    }
    if (ISTRUE (config.enable_chan6)) {
        strcpy (labelString+labelSize, config.label_chan6);
        labelSize += strlen (config.label_chan6) + 1;
    }
    if (ISTRUE (config.enable_chan7)) {
        strcpy (labelString+labelSize, config.label_chan7);
        labelSize += strlen (config.label_chan7) + 1;
    }
    if (ISTRUE (config.enable_chan8)) {
        strcpy (labelString+labelSize, config.label_chan8);
        labelSize += strlen (config.label_chan8) + 1;
    }
    if (ISTRUE (config.enable_chan9)) {
        strcpy (labelString+labelSize, config.label_chan9);
        labelSize += strlen (config.label_chan9) + 1;
    }
    if (ISTRUE (config.enable_chan10)) {
        strcpy (labelString+labelSize, config.label_chan10);
        labelSize += strlen (config.label_chan10) + 1;
    }
    if (ISTRUE (config.enable_chan11)) {
        strcpy (labelString+labelSize, config.label_chan11);
        labelSize += strlen (config.label_chan11) + 1;
    }
    if (ISTRUE (config.timestamp)) {
        strcpy (labelString+labelSize, config.label_chan12);
        labelSize += strlen (config.label_chan12) + 1;
    }

    /* add the channel label chunk to the header */
    label = (ft_chunkdef_t *) malloc (sizeof (ft_chunkdef_t));
    label->type = FT_CHUNK_CHANNEL_NAMES;
    label->size = labelSize;
    header->def->bufsize = append (&header->buf, header->def->bufsize, label, sizeof (ft_chunkdef_t));
    header->def->bufsize = append (&header->buf, header->def->bufsize, labelString, labelSize);
    FREE (label);
    FREE (labelString);

    /* define the constant part of the data and allocate space for the variable part */
    data->def->nchans = nchans;
    data->def->nsamples = config.blocksize;
    data->def->data_type = DATATYPE_FLOAT32;
    data->def->bufsize = WORDSIZE_FLOAT32 * nchans * config.blocksize;
    data->buf = malloc (data->def->bufsize);

    /* initialization phase, send the header */
    request->def->command = PUT_HDR;
    request->def->bufsize = append (&request->buf, request->def->bufsize, header->def, sizeof (headerdef_t));
    request->def->bufsize = append (&request->buf, request->def->bufsize, header->buf, header->def->bufsize);

    /* this is not needed any more */
    cleanup_header (&header);

    status = clientrequest (ftSocket, request, &response);
    if (verbose > 0)
        fprintf (stderr, "openbci2ft: clientrequest returned %d\n", status);
    if (status)
    {
        fprintf (stderr, "openbci2ft: could not send request to buffer\n");
        exit (1);
    }

    if (status || response == NULL || response->def == NULL)
    {
        fprintf (stderr, "openbci2ft: error in %s on line %d\n", __FILE__,
                __LINE__);
        exit (1);
    }

    cleanup_message (&request);

    if (response->def->command != PUT_OK)
    {
        fprintf (stderr, "openbci2ft: error in 'put header' request.\n");
        exit (1);
    }

    cleanup_message (&response);

    /* open the serial port */
    fprintf (stderr, "openbci2ft: opening serial port ...\n");
    if (!serialOpenByName (&SP, config.serial))
    {
        fprintf (stderr, "Could not open serial port %s\n", config.serial);
        return 1;
    }

    if (!serialSetParameters (&SP, 115200, 8, 0, 0, 0))
    {
        fprintf (stderr, "Could not modify serial port parameters\n");
        return 1;
    }

    fprintf (stderr, "openbci2ft: opening serial port ... ok\n");

    /* 8-bit board will always be initialized upon opening serial port, 32-bit board needs explicit initialization */

    fprintf (stderr, "openbci2ft: initializing ...\n");
    fprintf (stderr,
            "openbci2ft: press reset on the OpenBCI board if this takes too long\n");

    if (ISTRUE (config.reset))
        serialWrite (&SP, 1, "v");	/* soft reset, this will return $$$ */
    else
        serialWrite (&SP, 1, "D");	/* query default channel settings, this will also return $$$ */

    /* wait for '$$$' which indicates that the OpenBCI has been initialized */
    c = 0;
    while (c != 3)
    {
        usleep (1000);
        n = serialRead (&SP, 1, &byte);
        if (n == 1)
        {
            if (byte == '$')
                c++;
            else
                c = 0;
        }
    }				/* while waiting for '$$$' */

    if (strcasecmp (config.datalog, "14s") == 0)
        serialWrite (&SP, 1, "a");
    else if (strcasecmp (config.datalog, "5min") == 0)
        serialWrite (&SP, 1, "A");
    else if (strcasecmp (config.datalog, "15min") == 0)
        serialWrite (&SP, 1, "S");
    else if (strcasecmp (config.datalog, "30min") == 0)
        serialWrite (&SP, 1, "F");
    else if (strcasecmp (config.datalog, "1hr") == 0)
        serialWrite (&SP, 1, "G");
    else if (strcasecmp (config.datalog, "2hr") == 0)
        serialWrite (&SP, 1, "H");
    else if (strcasecmp (config.datalog, "4hr") == 0)
        serialWrite (&SP, 1, "J");
    else if (strcasecmp (config.datalog, "12hr") == 0)
        serialWrite (&SP, 1, "K");
    else if (strcasecmp (config.datalog, "24hr") == 0)
        serialWrite (&SP, 1, "L");
    else if (strcasecmp (config.datalog, "off") != 0)
    {
        fprintf (stderr, "Incorrect specification of datalog\n");
        return 1;
    }

    serialWriteSlow (&SP, strlen (config.setting_chan1), config.setting_chan1);
    serialWriteSlow (&SP, strlen (config.setting_chan2), config.setting_chan2);
    serialWriteSlow (&SP, strlen (config.setting_chan3), config.setting_chan3);
    serialWriteSlow (&SP, strlen (config.setting_chan4), config.setting_chan4);
    serialWriteSlow (&SP, strlen (config.setting_chan5), config.setting_chan5);
    serialWriteSlow (&SP, strlen (config.setting_chan6), config.setting_chan6);
    serialWriteSlow (&SP, strlen (config.setting_chan7), config.setting_chan7);
    serialWriteSlow (&SP, strlen (config.setting_chan8), config.setting_chan8);

    if (strcasecmp (config.testsignal, "gnd") == 0)
        serialWrite (&SP, 1, "0");
    else if (strcasecmp (config.testsignal, "dc") == 0)
        serialWrite (&SP, 1, "-");
    else if (strcasecmp (config.testsignal, "1xSlow") == 0)
        serialWrite (&SP, 1, "=");
    else if (strcasecmp (config.testsignal, "1xFast") == 0)
        serialWrite (&SP, 1, "p");
    else if (strcasecmp (config.testsignal, "2xSlow") == 0)
        serialWrite (&SP, 1, "[");
    else if (strcasecmp (config.testsignal, "2xFast") == 0)
        serialWrite (&SP, 1, "]");
    else if (strcasecmp (config.testsignal, "off") != 0)
    {
        fprintf (stderr, "Incorrect specification of testsignal\n");
        return 1;
    }

    fprintf (stderr, "openbci2ft: initializing ... ok\n");

    printf ("Starting to listen - press CTRL-C to quit\n");

    /* register CTRL-C handler */
    signal (SIGINT, abortHandler);

    /* start streaming data */
    serialWrite (&SP, 1, "b");

    /* determine the reference time for the timestamps */
    if (strcasecmp (config.timeref, "start") == 0)
    {
        /* since the start of the acquisition */
        get_monotonic_time (&tic, TIMESTAMP_REF_BOOT);
    }
    else if (strcasecmp (config.timeref, "boot") == 0)
    {
        /* since the start of the day */
        tic.tv_sec = 0;
        tic.tv_nsec = 0;
    }
    else if (strcasecmp (config.timeref, "epoch") == 0)
    {
        /* since the start of the epoch, i.e. 1-1-1970 */
        tic.tv_sec = 0;
        tic.tv_nsec = 0;
    }
    else
    {
        fprintf (stderr,
                "Incorrect specification of timeref, should be 'start', 'day' or 'epoch'\n");
        return 1;
    }

    while (keepRunning)
    {

        sample = 0;
        while (sample < config.blocksize)
        {
            /* wait for the first byte of the following packet */
            buf[0] = 0;
            while (buf[0] != 0xA0)
            {
                if (serialInputPending (&SP))
                    n = serialRead (&SP, 1, buf);
                else
                    usleep (1000);
            }			/* while */

            /*
             * Header
             *   Byte 1: 0xA0
             *   Byte 2: Sample Number
             *
             * EEG Data
             * Note: values are 24-bit signed, MSB first
             *   Bytes 3-5: Data value for EEG channel 1
             *   Bytes 6-8: Data value for EEG channel 2
             *   Bytes 9-11: Data value for EEG channel 3
             *   Bytes 12-14: Data value for EEG channel 4
             *   Bytes 15-17: Data value for EEG channel 5
             *   Bytes 18-20: Data value for EEG channel 6
             *   Bytes 21-23: Data value for EEG channel 6
             *   Bytes 24-26: Data value for EEG channel 8
             *
             * Accelerometer Data
             * Note: values are 16-bit signed, MSB first
             *   Bytes 27-28: Data value for accelerometer channel X
             *   Bytes 29-30: Data value for accelerometer channel Y
             *   Bytes 31-32: Data value for accelerometer channel Z
             *
             * Footer
             *   Byte 33: 0xC0
             */

            /* read the remaining 32 bytes of the packet */
            while (n < OPENBCI_BUFLEN)
                if (serialInputPending (&SP))
                    n += serialRead (&SP, (OPENBCI_BUFLEN - n), buf + n);
                else
                    usleep (1000);

            if (verbose > 1)
            {
                for (i = 0; i < OPENBCI_BUFLEN; i++)
                    printf ("%02x ", buf[i]);
                printf ("\n");
            }

            chan = 0;
            if (ISTRUE (config.enable_chan1))
                ((FLOAT32_T *) (data->buf))[nchans * sample + (chan++)] =
                    OPENBCI_CALIB1 * (buf[2] << 24 | buf[3] << 16 | buf[4] << 8) /
                    255;
            if (ISTRUE (config.enable_chan2))
                ((FLOAT32_T *) (data->buf))[nchans * sample + (chan++)] =
                    OPENBCI_CALIB1 * (buf[5] << 24 | buf[6] << 16 | buf[7] << 8) /
                    255;
            if (ISTRUE (config.enable_chan3))
                ((FLOAT32_T *) (data->buf))[nchans * sample + (chan++)] =
                    OPENBCI_CALIB1 * (buf[8] << 24 | buf[9] << 16 | buf[10] << 8) /
                    255;
            if (ISTRUE (config.enable_chan4))
                ((FLOAT32_T *) (data->buf))[nchans * sample + (chan++)] =
                    OPENBCI_CALIB1 * (buf[11] << 24 | buf[12] << 16 | buf[13] << 8) /
                    255;
            if (ISTRUE (config.enable_chan5))
                ((FLOAT32_T *) (data->buf))[nchans * sample + (chan++)] =
                    OPENBCI_CALIB1 * (buf[14] << 24 | buf[15] << 16 | buf[16] << 8) /
                    255;
            if (ISTRUE (config.enable_chan6))
                ((FLOAT32_T *) (data->buf))[nchans * sample + (chan++)] =
                    OPENBCI_CALIB1 * (buf[17] << 24 | buf[18] << 16 | buf[19] << 8) /
                    255;
            if (ISTRUE (config.enable_chan7))
                ((FLOAT32_T *) (data->buf))[nchans * sample + (chan++)] =
                    OPENBCI_CALIB1 * (buf[20] << 24 | buf[21] << 16 | buf[22] << 8) /
                    255;
            if (ISTRUE (config.enable_chan8))
                ((FLOAT32_T *) (data->buf))[nchans * sample + (chan++)] =
                    OPENBCI_CALIB1 * (buf[23] << 24 | buf[24] << 16 | buf[25] << 8) /
                    255;

            if (ISTRUE (config.enable_chan9))
                ((FLOAT32_T *) (data->buf))[nchans * sample + (chan++)] =
                    OPENBCI_CALIB2 * (buf[26] << 24 | buf[27] << 16) / 32767;
            if (ISTRUE (config.enable_chan10))
                ((FLOAT32_T *) (data->buf))[nchans * sample + (chan++)] =
                    OPENBCI_CALIB2 * (buf[28] << 24 | buf[29] << 16) / 32767;
            if (ISTRUE (config.enable_chan11))
                ((FLOAT32_T *) (data->buf))[nchans * sample + (chan++)] =
                    OPENBCI_CALIB2 * (buf[28] << 24 | buf[31] << 16) / 32767;

            if (ISTRUE (config.timestamp))
            {
                if (strcasecmp (config.timeref, "start") == 0)
                    get_monotonic_time (&toc, TIMESTAMP_REF_BOOT);
                else if (strcasecmp (config.timeref, "boot") == 0)
                    get_monotonic_time (&toc, TIMESTAMP_REF_BOOT);
                else if (strcasecmp (config.timeref, "epoch") == 0)
                    get_monotonic_time (&toc, TIMESTAMP_REF_EPOCH);
                ((FLOAT32_T *) (data->buf))[nchans * sample + (chan++)] =
                    get_elapsed_time (&tic, &toc);
            }

            sample++;
        }				/* while c<config.blocksize */

        count += sample;
        printf ("openbci2ft: sample count = %i\n", count);

        /* create the request */
        request = malloc (sizeof (message_t));
        request->def = malloc (sizeof (messagedef_t));
        request->buf = NULL;
        request->def->version = VERSION;
        request->def->bufsize = 0;
        request->def->command = PUT_DAT;

        request->def->bufsize = append (&request->buf, request->def->bufsize, data->def, sizeof (datadef_t));
        request->def->bufsize = append (&request->buf, request->def->bufsize, data->buf, data->def->bufsize);

        status = clientrequest (ftSocket, request, &response);
        if (verbose > 0)
            fprintf (stderr, "openbci2ft: clientrequest returned %d\n", status);
        if (status)
        {
            fprintf (stderr, "openbci2ft: error in %s on line %d\n", __FILE__,
                    __LINE__);
            exit (1);
        }

        if (status)
        {
            fprintf (stderr, "openbci2ft: error in %s on line %d\n", __FILE__,
                    __LINE__);
            exit (1);
        }

        /* FIXME do someting with the response, i.e. check that it is OK */
        cleanup_message (&request);

        if (response == NULL || response->def == NULL
                || response->def->command != PUT_OK)
        {
            fprintf (stderr, "Error when writing samples.\n");
        }
        cleanup_message (&response);

    }				/* while keepRunning */

    /* stop streaming data */
    serialWrite (&SP, 1, "s");

    cleanup_data (&data);

    if (ftSocket > 0)
    {
        close_connection (ftSocket);
    }
    else
    {
        ft_stop_buffer_server (ftServer);
    }

    return 0;
}				/* main */
Exemple #18
0
int main(int argc, char *argv[])
{
		int n, i, c, sample = 0, status = 0, verbose = 0;
		unsigned char buf[BUFLEN], byte;
		SerialPort SP;
		host_t host;

		/* these represent the acquisition system properties */
		int nchans         = OPENBCI_NCHANS;
		int blocksize      = BLOCKSIZE;
		float fsample      = OPENBCI_FSAMPLE;

		/* these are used in the communication with the FT buffer and represent statefull information */
		int ftSocket           = -1;
		ft_buffer_server_t *ftServer;
		message_t    *request  = NULL;
		message_t    *response = NULL;
		header_t     *header   = NULL;
		data_t       *data     = NULL;

		if (argc<2) {
				printf(usage);
				exit(0);
		}

		if (argc>2)
				strcpy(host.name, argv[2]);
		else {
				strcpy(host.name, FTHOST);
		}

		if (argc>3)
				host.port = atoi(argv[3]);
		else {
				host.port = FTPORT;
		}

		fprintf(stderr, "openbci2ft: device       =  %s\n", argv[1]);
		fprintf(stderr, "openbci2ft: hostname     =  %s\n", host.name);
		fprintf(stderr, "openbci2ft: port         =  %d\n", host.port);

		/* Spawn tcpserver or connect to remote buffer */
		if (strcmp(host.name, "-") == 0) {
				ftServer = ft_start_buffer_server(host.port, NULL, NULL, NULL);
				if (ftServer==NULL) {
						fprintf(stderr, "openbci2ft: could not start up a local buffer serving at port %i\n", host.port);
						return 1;
				}
				ftSocket = 0;
				printf("openbci2ft: streaming to local buffer on port %i\n", host.port);
		}
		else {
				ftSocket = open_connection(host.name, host.port);

				if (ftSocket < 0) {
						fprintf(stderr, "openbci2ft: could not connect to remote buffer at %s:%i\n", host.name, host.port);
						return 1;
				}
				printf("openbci2ft: streaming to remote buffer at %s:%i\n", host.name, host.port);
		}  

		/* allocate the elements that will be used in the communication to the FT buffer */
		request      = malloc(sizeof(message_t));
		request->def = malloc(sizeof(messagedef_t));
		request->buf = NULL;
		request->def->version = VERSION;
		request->def->bufsize = 0;

		header      = malloc(sizeof(header_t));
		header->def = malloc(sizeof(headerdef_t));
		header->buf = NULL;

		data      = malloc(sizeof(data_t));
		data->def = malloc(sizeof(datadef_t));
		data->buf = NULL;

		/* define the header */
		header->def->nchans    = nchans;
		header->def->fsample   = fsample;
		header->def->nsamples  = 0;
		header->def->nevents   = 0;
		header->def->data_type = DATATYPE_FLOAT32;
		header->def->bufsize   = 0;

		/* define the constant part of the data and allocate space for the variable part */
		data->def->nchans    = nchans;
		data->def->nsamples  = blocksize;
		data->def->data_type = DATATYPE_FLOAT32;
		data->def->bufsize   = WORDSIZE_FLOAT32*nchans*blocksize;
		data->buf            = malloc(data->def->bufsize);

		/* initialization phase, send the header */
		request->def->command = PUT_HDR;
		request->def->bufsize = append(&request->buf, request->def->bufsize, header->def, sizeof(headerdef_t));
		request->def->bufsize = append(&request->buf, request->def->bufsize, header->buf, header->def->bufsize);

		/* this is not needed any more */
		cleanup_header(&header);

		status = clientrequest(ftSocket, request, &response);
		if (verbose>0)
				fprintf(stderr, "openbci2ft: clientrequest returned %d\n", status);
		if (status) {
				fprintf(stderr, "openbci2ft: could not send request to buffer\n");
				exit(1);
		}

		if (status || response==NULL || response->def == NULL) {
				fprintf(stderr, "openbci2ft: error in %s on line %d\n", __FILE__, __LINE__);
				exit(1);
		}

		cleanup_message(&request);

		if (response->def->command != PUT_OK) {
				fprintf(stderr, "openbci2ft: error in 'put header' request.\n");
				exit(1);
		}

		cleanup_message(&response);

		/* open the serial port */
		fprintf(stderr, "openbci2ft: opening serial port ...\n");
		if (!serialOpenByName(&SP, argv[1])) {
				fprintf(stderr, "Could not open serial port %s\n", argv[1]);
				return 1;
		}

		if (!serialSetParameters(&SP, 115200, 8, 0, 0, 0)) {
				fprintf(stderr, "Could not modify serial port parameters\n");
				return 1;
		}

		fprintf(stderr, "openbci2ft: opening serial port ... ok\n");

		/* 8-bit board will always be initialized upon opening serial port, 32-bit board needs explicit initialization */
		fprintf(stderr, "openbci2ft: initializing ...\n");

		serialWrite(&SP, 1, "v");
		fprintf(stderr, "openbci2ft: press reset on the OpenBCI board if this takes too long\n");
		usleep(1000);

		/* wait for '$$$' which indicates that the OpenBCI has been initialized */
		c = 0;
		while (c!=3) {
				n = serialRead(&SP, 1, &byte);
				if (n==1) {
						if (byte=='$')
								c++;
						else
								c = 0;
				}
		} /* while waiting for '$$$' */

		fprintf(stderr, "openbci2ft: initializing ... ok\n");

		printf("Starting to listen - press CTRL-C to quit\n");

		/* register CTRL-C handler */
		signal(SIGINT, abortHandler);

		/* start streaming data */
		serialWrite(&SP, 1, "b");

		while (keepRunning) {

				c = 0;
				while (c<blocksize) {
						/* wait for the first byte of the packet */
						buf[0]=0;
						while (buf[0]!=0xA0) {
								if (serialInputPending(&SP))
										n = serialRead(&SP, 1, buf);
								else
										usleep(1000);
						} /* while */

						/* read the remaining 32 bytes of the packet */
						while (n<BUFLEN)
								if (serialInputPending(&SP))
										n += serialRead(&SP, (BUFLEN-n), buf+n);
								else
										usleep(100000);

						if (verbose>1) {
								for (i=0; i<BUFLEN; i++)
										printf("%02x ", buf[i]);
								printf("\n");
						}

						((FLOAT32_T *)(data->buf))[nchans*c + 0] = OPENBCI_CALIB1 * (buf[ 2]<<24 | buf[ 3]<<16 | buf[ 4]<<8)/255;
						((FLOAT32_T *)(data->buf))[nchans*c + 1] = OPENBCI_CALIB1 * (buf[ 5]<<24 | buf[ 6]<<16 | buf[ 7]<<8)/255;
						((FLOAT32_T *)(data->buf))[nchans*c + 2] = OPENBCI_CALIB1 * (buf[ 8]<<24 | buf[ 9]<<16 | buf[10]<<8)/255;
						((FLOAT32_T *)(data->buf))[nchans*c + 3] = OPENBCI_CALIB1 * (buf[11]<<24 | buf[12]<<16 | buf[13]<<8)/255;
						((FLOAT32_T *)(data->buf))[nchans*c + 4] = OPENBCI_CALIB1 * (buf[14]<<24 | buf[15]<<16 | buf[16]<<8)/255;
						((FLOAT32_T *)(data->buf))[nchans*c + 5] = OPENBCI_CALIB1 * (buf[17]<<24 | buf[18]<<16 | buf[19]<<8)/255;
						((FLOAT32_T *)(data->buf))[nchans*c + 6] = OPENBCI_CALIB1 * (buf[20]<<24 | buf[21]<<16 | buf[22]<<8)/255;
						((FLOAT32_T *)(data->buf))[nchans*c + 7] = OPENBCI_CALIB1 * (buf[23]<<24 | buf[24]<<16 | buf[25]<<8)/255;

						((FLOAT32_T *)(data->buf))[nchans*c + 8] = OPENBCI_CALIB2 * (buf[26]<<24 | buf[27]<<16)/32767;
						((FLOAT32_T *)(data->buf))[nchans*c + 9] = OPENBCI_CALIB2 * (buf[28]<<24 | buf[29]<<16)/32767;
						((FLOAT32_T *)(data->buf))[nchans*c +10] = OPENBCI_CALIB2 * (buf[28]<<24 | buf[31]<<16)/32767;

						c++;
				} /* while c<blocksize */

				sample += blocksize;
				printf("openbci2ft: sample count = %i\n", sample);

				/*
				 * Header
				 *   Byte 1: 0xA0
				 *   Byte 2: Sample Number
				 *
				 * EEG Data
				 * Note: values are 24-bit signed, MSB first
				 *   Bytes 3-5: Data value for EEG channel 1
				 *   Bytes 6-8: Data value for EEG channel 2
				 *   Bytes 9-11: Data value for EEG channel 3
				 *   Bytes 12-14: Data value for EEG channel 4
				 *   Bytes 15-17: Data value for EEG channel 5
				 *   Bytes 18-20: Data value for EEG channel 6
				 *   Bytes 21-23: Data value for EEG channel 6
				 *   Bytes 24-26: Data value for EEG channel 8
				 *
				 * Accelerometer Data
				 * Note: values are 16-bit signed, MSB first
				 *   Bytes 27-28: Data value for accelerometer channel X
				 *   Bytes 29-30: Data value for accelerometer channel Y
				 *   Bytes 31-32: Data value for accelerometer channel Z
				 *
				 * Footer
				 *   Byte 33: 0xC0
				 */

				/* create the request */
				request      = malloc(sizeof(message_t));
				request->def = malloc(sizeof(messagedef_t));
				request->buf = NULL;
				request->def->version = VERSION;
				request->def->bufsize = 0;
				request->def->command = PUT_DAT;
				request->def->bufsize = append(&request->buf, request->def->bufsize, data->def, sizeof(datadef_t));
				request->def->bufsize = append(&request->buf, request->def->bufsize, data->buf, data->def->bufsize);

				status = clientrequest(ftSocket, request, &response);
				if (verbose>0)
						fprintf(stderr, "openbci2ft: clientrequest returned %d\n", status);
				if (status) {
						fprintf(stderr, "openbci2ft: error in %s on line %d\n", __FILE__, __LINE__);
						exit(1);
				}

				if (status) {
						fprintf(stderr, "openbci2ft: error in %s on line %d\n", __FILE__, __LINE__);
						exit(1);
				}

				/* FIXME do someting with the response, i.e. check that it is OK */
				cleanup_message(&request);

				if (response == NULL || response->def == NULL || response->def->command!=PUT_OK) {
						fprintf(stderr, "Error when writing samples.\n");
				}
				cleanup_message(&response);

		} /* while keepRunning */

		/* stop streaming data */
		serialWrite(&SP, 1, "s");

		cleanup_data(&data);

		if (ftSocket > 0) {
				close_connection(ftSocket);
		} else {
				ft_stop_buffer_server(ftServer);
		}
		return 0;
} /* main */
Exemple #19
0
int buffer_puthdr(int server, mxArray * plhs[], const mxArray * prhs[])
{
	int fieldnumber;
	mxArray *field;
	int result;
  
	message_t     request;
	messagedef_t  request_def;
	message_t    *response = NULL;
	headerdef_t   header_def;
	
	ft_chunkdef_t chunk_def;
  
  /* allocate the request message */
	request.def = &request_def;
	request.buf = NULL;
	request_def.version = VERSION;
	request_def.command = PUT_HDR;
	request_def.bufsize = 0;
  
  /* define the header, it has the fields "nchans", "nsamples", "nevents", "fsample", "data_type" */
  	if (mxGetNumberOfElements(prhs[0])!=1)
		mexErrMsgTxt("Only one header can be put into the buffer at a time.");

	fieldnumber = mxGetFieldNumber(prhs[0], "nchans");
	if (fieldnumber<0) 
		mexErrMsgTxt("field 'nchans' is missing");
	field = mxGetFieldByNumber(prhs[0], 0, fieldnumber);
	if (!mxIsNumeric(field) || mxIsEmpty(field)) 
		mexErrMsgTxt("invalid data type for 'nchans'");
	header_def.nchans    = (UINT32_T)mxGetScalar(field) ;
	
	fieldnumber = mxGetFieldNumber(prhs[0], "nsamples");
	if (fieldnumber<0) 
		mexErrMsgTxt("field 'nsamples' is missing");
    field = mxGetFieldByNumber(prhs[0], 0, fieldnumber);
    if (!mxIsNumeric(field) || mxIsEmpty(field)) 
		mexErrMsgTxt("invalid data type for 'nsamples'");
	header_def.nsamples    = (UINT32_T)mxGetScalar(field) ;
  
	fieldnumber = mxGetFieldNumber(prhs[0], "nevents");
	if (fieldnumber<0) 
		mexErrMsgTxt("field is missing 'nevents'");
	field = mxGetFieldByNumber(prhs[0], 0, fieldnumber);
	if (!mxIsNumeric(field) || mxIsEmpty(field)) 
		mexErrMsgTxt("invalid data type for 'nevents'");
	header_def.nevents    = (UINT32_T)mxGetScalar(field) ;
  
	fieldnumber = mxGetFieldNumber(prhs[0], "fsample");
	if (fieldnumber<0) 
		mexErrMsgTxt("field is missing 'fsample'");
    field = mxGetFieldByNumber(prhs[0], 0, fieldnumber);
    if (!mxIsNumeric(field) || mxIsEmpty(field)) 
		mexErrMsgTxt("invalid data type for 'fsample'");
	header_def.fsample    = (float)mxGetScalar(field) ;
  
	fieldnumber = mxGetFieldNumber(prhs[0], "data_type");
	if (fieldnumber<0) 
		mexErrMsgTxt("field 'data_type' is missing");
	field = mxGetFieldByNumber(prhs[0], 0, fieldnumber);
	if (!mxIsNumeric(field) || mxIsEmpty(field)) 
		mexErrMsgTxt("invalid data type for 'data_type'");
	header_def.data_type    = (UINT32_T)mxGetScalar(field) ;
	
	/* construct a PUT_HDR request */
	request_def.bufsize = ft_mx_append(&request.buf, request_def.bufsize, &header_def, sizeof(headerdef_t));
	
	/* append existing chunks to request.buf, set correct header_def.bufsize at the end */
	fieldnumber = mxGetFieldNumber(prhs[0], "nifti_1");
	if (fieldnumber>=0) {
		field = mxGetFieldByNumber(prhs[0], 0, fieldnumber);
		if (!mxIsUint8(field) || mxGetNumberOfElements(field)!=SIZE_NIFTI_1) {
			mexWarnMsgTxt("invalid data type for field 'nifti_1' -- ignoring");
		} else {
			chunk_def.size = SIZE_NIFTI_1;
			chunk_def.type = FT_CHUNK_NIFTI1;
		
			request_def.bufsize = ft_mx_append(&request.buf, request_def.bufsize, &chunk_def, sizeof(chunk_def));
			request_def.bufsize = ft_mx_append(&request.buf, request_def.bufsize, mxGetData(field), chunk_def.size);
		}
	}
	
	fieldnumber = mxGetFieldNumber(prhs[0], "siemensap");
	if (fieldnumber>=0) {
		field = mxGetFieldByNumber(prhs[0], 0, fieldnumber);
		if (!mxIsUint8(field)) {
			mexWarnMsgTxt("invalid data type for field 'siemensap' -- ignoring");
		} else {
			chunk_def.size = mxGetNumberOfElements(field);
			chunk_def.type = FT_CHUNK_SIEMENS_AP;
		
			request_def.bufsize = ft_mx_append(&request.buf, request_def.bufsize, &chunk_def, sizeof(chunk_def));
			request_def.bufsize = ft_mx_append(&request.buf, request_def.bufsize, mxGetData(field), chunk_def.size);
		}
	}
	
	fieldnumber = mxGetFieldNumber(prhs[0], "ctf_res4");
	if (fieldnumber>=0) {
		field = mxGetFieldByNumber(prhs[0], 0, fieldnumber);
		if (!mxIsUint8(field)) {
			mexWarnMsgTxt("invalid data type for field 'ctf_res4' -- ignoring");
		} else {
			chunk_def.size = mxGetNumberOfElements(field);
			chunk_def.type = FT_CHUNK_CTF_RES4;
		
			request_def.bufsize = ft_mx_append(&request.buf, request_def.bufsize, &chunk_def, sizeof(chunk_def));
			request_def.bufsize = ft_mx_append(&request.buf, request_def.bufsize, mxGetData(field), chunk_def.size);
		}
	}	
	
	fieldnumber = mxGetFieldNumber(prhs[0], "channel_names");
	if (fieldnumber>=0) {
		ft_chunk_t *chunk = NULL;
		field = mxGetFieldByNumber(prhs[0], 0, fieldnumber);
		chunk = encodeChannelNames(field, header_def.nchans);
		if (chunk == NULL) {
			mexWarnMsgTxt("invalid data type for field 'channel_names' -- ignoring.");
		} else {
			request_def.bufsize = ft_mx_append(&request.buf, request_def.bufsize, chunk, sizeof(ft_chunkdef_t) + chunk->def.size);
			mxFree(chunk);
		}
	}
	
	fieldnumber = mxGetFieldNumber(prhs[0], "resolutions");
	if (fieldnumber>=0) {
		ft_chunk_t *chunk = NULL;
		field = mxGetFieldByNumber(prhs[0], 0, fieldnumber);
		chunk = encodeResolutions(field, header_def.nchans);
		if (chunk == NULL) {
			mexWarnMsgTxt("invalid data type for field 'resolutions' -- ignoring.");
		} else {
			request_def.bufsize = ft_mx_append(&request.buf, request_def.bufsize, chunk, sizeof(ft_chunkdef_t) + chunk->def.size);
			mxFree(chunk);
		}
	}		
	
	/* header->def->bufsize is the request->def->bufsize - sizeof(header->def) */
	((headerdef_t *) request.buf)->bufsize = request_def.bufsize - sizeof(headerdef_t);
	
	/* write the request, read the response */
	result = clientrequest(server, &request, &response);
  
	/* the request structure is not needed any more, but only .buf needs to be free'd */
    if (request.buf != NULL) mxFree(request.buf);
	
	if (result == 0) {
		/* check that the response is PUT_OK */
		if (!response)
			mexErrMsgTxt("unknown error in response\n");
		if (!response->def) {
			FREE(response->buf);
			FREE(response);
			mexErrMsgTxt("unknown error in response\n");
		}
		if (response->def->command!=PUT_OK) {
			result = response->def->command;
		}
	}
	/* the response structure is not needed any more */
	if (response) {
		FREE(response->def);
		FREE(response->buf);
		FREE(response);
	}
	return result;
}
Exemple #20
0
int buffer_getevt(int server, mxArray *plhs[], const mxArray *prhs[])
{
  int verbose = 0;
  int i, nevents;
  int offset;
  double *val;
  int result;
  
  mxArray *bufptr;
  
  
  message_t *request  = NULL;
  message_t *response = NULL;
  eventsel_t eventsel;
  
  /* this is for the Matlab specific output */
  const char *field_names[] = {
    "type",
    "value",
    "sample",
    "offset",
    "duration"
  };
  
  /* allocate the elements that will be used in the communication */
  request      = malloc(sizeof(message_t));
  request->def = malloc(sizeof(messagedef_t));
  request->buf = NULL;
  request->def->version = VERSION;
  request->def->command = GET_EVT;
  request->def->bufsize = 0;
  
  if ((prhs[0]!=NULL) && (mxGetNumberOfElements(prhs[0])==2) && (mxIsDouble(prhs[0])) && (!mxIsComplex(prhs[0]))) {
    /* fprintf(stderr, "args OK\n"); */
    val = (double *)mxGetData(prhs[0]);
    eventsel.begevent = (UINT32_T)(val[0]);
    eventsel.endevent = (UINT32_T)(val[1]);
    if (verbose) print_eventsel(&eventsel);
    request->def->bufsize = append(&request->buf, request->def->bufsize, &eventsel, sizeof(eventsel_t));
  }
  
  if (verbose) print_request(request->def);
  result = clientrequest(server, request, &response);
  if (verbose) print_response(response->def);
  
  if (result == 0) {
    if (response->def->command==GET_OK) {
	  eventdef_t *event_def;
      /* first count the number of events */
      nevents = 0;
      offset = 0;
      while (offset<response->def->bufsize) {
        event_def = (eventdef_t *)((char *)response->buf + offset);
        /* event_buf = (char *)response->buf + offset + sizeof(eventdef_t); */
        if (verbose) print_eventdef(event_def);
        offset += sizeof(eventdef_t) + event_def->bufsize;
        nevents++;
      }
      
      /* create a structure array that can hold all events */
      plhs[0] = mxCreateStructMatrix(1, nevents, NUMBER_OF_FIELDS, field_names);
      
      offset = 0;
      for (i=0; i<nevents; i++) {
	  	char *buf_type,*buf_value;
		
        event_def = (eventdef_t *) ((char *)response->buf + offset);
		buf_type = (char *) response->buf + offset + sizeof(eventdef_t);
		buf_value = buf_type + event_def->type_numel * wordsize_from_type(event_def->type_type);
                
		mxSetFieldByNumber(plhs[0], i, 0, matrix_from_ft_type_data(event_def->type_type, 1, event_def->type_numel, buf_type));
		mxSetFieldByNumber(plhs[0], i, 1, matrix_from_ft_type_data(event_def->value_type, 1, event_def->value_numel, buf_value));
        mxSetFieldByNumber(plhs[0], i, 2, mxCreateDoubleScalar((double)event_def->sample+1)); /* 1-based in Matlab, 0-based in protocol */
        mxSetFieldByNumber(plhs[0], i, 3, mxCreateDoubleScalar((double)event_def->offset));
        mxSetFieldByNumber(plhs[0], i, 4, mxCreateDoubleScalar((double)event_def->duration));
        offset += sizeof(eventdef_t) + event_def->bufsize;
      }
    }
    else {
      result = response->def->command;
    }
  }
  
  if (request) {
    FREE(request->def);
    FREE(request->buf);
    FREE(request);
  }
  if (response) {
    FREE(response->def);
    FREE(response->buf);
    FREE(response);
  }
  
  return result;
}