view kk-data-provider.c @ 183:791ca26fee6a

Rewrite data writing to file Fmt() uses by default truncation to conver double arguments to their text representation. Rounding must be used. Rewrite using standard C functions to get rid of this problem (and probably make it more efficient). Extend to handle arbitrary number of channels and to report errors on opening the data files.
author Daniele Nicolodi <daniele.nicolodi@obspm.fr>
date Fri, 21 Feb 2014 18:42:30 +0100
parents c96f5f64c946
children bc980095a24d
line wrap: on
line source

/* FXAnalise data provider which directly interfaces with the KK FX80E counter */

#include <ansi_c.h>
#include <userint.h>
#include <formatio.h>
#include <utility.h>
#include <inifile.h>

#include "config.h"
#include "data-provider.h"
#include "KKFX80E.h"

#define DEFAULT_PORT "COM4:115200"
#define DEFAULT_NCHAN 4
#define TIMEOUT 1 /* seconds */

#define strneq(a, b, len) (strncmp((a), (b), (len)) == 0)

int CVICALLBACK KKDataProvider (void *functionData)
{
	int mainThreadId;
	int rv;
	char *resp;
	struct event event;
	int nchan;
	char port[256];
	
	/* get main thread id to post messages to it */
	mainThreadId = CmtGetMainThreadID();
	
	/* configuration file path */ 
	char path[MAX_PATHNAME_LEN];
	GetIniFilePath(path); 

	/* load configuration file */ 
	IniText configuration = Ini_New(TRUE);
	Ini_ReadFromFile(configuration, path);

	/* get serial port name configuration */
	rv = Ini_GetStringIntoBuffer(configuration, "KK", "port", port, sizeof(port));
	if (! rv)
		strncpy(port, DEFAULT_PORT, sizeof(port));
	
	/* channel number */
	rv = Ini_GetInt(configuration, "KK", "nchan", &nchan);
	if (! rv)
		nchan = DEFAULT_NCHAN;
	
	/* free */ 
	Ini_Dispose(configuration);

	/* initialize library */
	FX_Init();
	
	/* connect to KK FX80E counter */
	rv = FX_Open(port);
	if (! rv) {
		SendMessage(mainThreadId, FX_Error());
		goto error;
	}
	
	/* clear transmit buffer */
	rv = FX_Send("\x80");
	if (! rv) {
		SendMessage(mainThreadId, FX_Error());
		goto error;
	}
	rv = FX_Recv(&resp, TIMEOUT);
	if (! rv) {
		SendMessage(mainThreadId, FX_Error());
		goto error;
	}
	
	/* set report interval 1sec */
	rv = FX_Send("\x29");
	if (! rv) {
		SendMessage(mainThreadId, FX_Error());
		goto error;
	}
	rv = FX_Recv(&resp, TIMEOUT);
	if (! rv) {
		SendMessage(mainThreadId, FX_Error());
		goto error;
	}
	
	/* read nchan channels */
	char *cmd = "\x30";
	cmd[0] += nchan;
	rv = FX_Send(cmd);
	if (! rv) {
		SendMessage(mainThreadId, FX_Error());
		goto error;
	}
	rv = FX_Recv(&resp, TIMEOUT);
	if (! rv) {
		SendMessage(mainThreadId, FX_Error());
		goto error;
	}
	
	/* set mode to instantaneous frequency measurement */
	rv = FX_Send("\x42");
	if (! rv) {
		SendMessage(mainThreadId, FX_Error());
		goto error;
	}
	rv = FX_Recv(&resp, TIMEOUT);
	if (! rv) {
		SendMessage(mainThreadId, FX_Error());
		goto error;
	}
	
	/* switch scrambler off */
	rv = FX_Send("\x50");
	if (! rv) {
		SendMessage(mainThreadId, FX_Error());
		goto error;
	}
	rv = FX_Recv(&resp, TIMEOUT);
	if (! rv) {
		SendMessage(mainThreadId, FX_Error());
		goto error;
	}
	
	/* enable synchronization */
	rv = FX_Send("\x0F");
	if (! rv) {
		SendMessage(mainThreadId, FX_Error());
		goto error;
	}
	rv = FX_Recv(&resp, TIMEOUT);
	if (! rv) {
		SendMessage(mainThreadId, FX_Error());
		goto error;
	}
	
	while (acquiring) {
		/* receive data from counter */
		FX_Recv(&resp, TIMEOUT);
		if (! resp) {
			SendMessage(mainThreadId, FX_Error());
			break;
		}
		
		if (strneq(resp, "2900", 4)) {
			
			/* timestamp */
			gettimeofday(&event.time, NULL);
			
			/* parse received data */
			rv = Scan(resp + 6, "%f; %f; %f; %f; %f; %f; %f; %f",
				&event.data[0], &event.data[1], &event.data[2], &event.data[3],
				&event.data[4], &event.data[5], &event.data[6], &event.data[7]);
			if (rv != nchan) {
				SendMessage(mainThreadId, "KK Counter: data conversion error");
				goto error;
			}
			
			/* convert from kHz to Hz */
			for (int i = 0; i < nchan; i++)
				event.data[i] *= 1000.0;
			
			/* push data into the data queue */
			CmtWriteTSQData(dataQueue, &event, 1, TSQ_INFINITE_TIMEOUT, 0);
		
		} else if (strneq(resp, "7000", 4)) {
			/* ignore heart beat packet */
		} else if (strneq(resp, "7015", 4)) {
			/* ignore undocumented packet. it is sent by newer kk counters
			   for each data packet. it probably contains a sample count along
			   with some other information */
		} else if (strneq(resp, "7020", 4)) {
			/* undocumented packet. it probably reports the header for
			   subsequent data packets. match it against expected value  */
			if (strcmp(resp + 6, "$2900")) {
				SendMessage(mainThreadId, "KK Counter: %s", resp);
			}
		} else if (strneq(resp, "7F51", 4)) {
			/* measurement interval synchronized */
			SendMessage(mainThreadId, "KK Counter measurement interval synchronized");
		} else {
			/* send message to the main thread */
			SendMessage(mainThreadId, "KK Counter: %s", resp);
		}
	}
	
error:
	/* close serial port */
	FX_Close();
	/* free allocated resources */
	FX_Free();
	
	return 0;
}