diff FXAnalyse.c @ 88:9b7588cd4013

Move data acquisition into separate thread The data acquisition thread transfers data to the main thread trough a Thread Safe Queue. This separation allows for making the data acquisition system pluggable. The old file based communication to the KK counter is implemented along with a very simple fake data provider.
author Daniele Nicolodi <daniele.nicolodi@obspm.fr>
date Thu, 21 Mar 2013 18:24:45 +0100
parents 0950d4b3a45c
children c9e4f63c2033
line wrap: on
line diff
--- a/FXAnalyse.c	Thu Mar 21 12:08:27 2013 +0100
+++ b/FXAnalyse.c	Thu Mar 21 18:24:45 2013 +0100
@@ -14,8 +14,6 @@
 #include "DDS_Fox.h" 
 #include "muParserDLL.h"
 
-#define FXLINELENGTH 123
-#define LOGFILEPATH "C:\\Femto\\Software\\FXQE80"
 #define DATAFOLDER "Z:\\Measures-2013"
 
 #define DEDRIFT_DDS_FREQUENCY 70000000
@@ -26,10 +24,22 @@
 static int EstimateN3Panel;
 static int LoggingPanel;
 
-char LogFileName[MAX_PATHNAME_LEN];
+// data acquisition status
+int acquiring;
+// data queue
+CmtTSQHandle dataQueue;
+// data provider thread
+CmtThreadFunctionID dataProviderThread;
 
-double utc = 0;
+// data providers
+int CVICALLBACK FakeDataProvider (void *functionData);
+int CVICALLBACK FileDataProvider (void *functionData);
 
+// select which data provider to use
+#define DataProvider FileDataProvider
+
+
+double utc;
 double Ch1, Ch2, Ch3, Ch4;
 double Math1, Math2, Math3, Math4, Math5;
 double N1, N2, N3, N4;
@@ -44,9 +54,8 @@
 
 muParserHandle_t MathParser1, MathParser2, MathParser3, MathParser4, MathParser5;
 
-int Acquiring = FALSE;
 
-long OldLogFilePtr = 0;
+
 double Ndiv = 8.0;
 
 int settling = 0;
@@ -233,7 +242,8 @@
 }
 
 
-void writeData(char *folder, char *name, char *id, char *date, char *time, double utc, double value)
+void writeData(const char *folder, const char *name, const char *id, 
+		const char *timestr, double utc, double value)
 {
 	char line[1024];
 	char filename[FILENAME_MAX];
@@ -242,12 +252,20 @@
 	snprintf(filename, sizeof(filename), "%s\\%s-%s.txt", folder, id, name);
 	
 	int fd = OpenFile(filename, VAL_WRITE_ONLY, VAL_APPEND, VAL_ASCII);
-	Fmt(line, "%s\t%s\t%f[p3]\t%f[p3]", date, time, utc, value);
+	Fmt(line, "%s\t%f[p3]\t%f[p3]", timestr, utc, value);
 	WriteLine(fd, line, -1);
 	CloseFile(fd);
 }
 
 
+#define NCHAN 4
+#define DATA_EVENT_SIZE (NCHAN + 1)
+#define DATA_QUEUE_SIZE (128 * DATA_EVENT_SIZE)
+
+void CVICALLBACK DataAvailableCB (CmtTSQHandle queueHandle, unsigned int event,
+		int value, void *callbackData);
+
+
 int main (int argc, char *argv[])
 {
 	double frequency;
@@ -265,8 +283,6 @@
 	if ((LoggingPanel = LoadPanel (0, "FXAnalyse.uir", LOGGING)) < 0)
 		return -1;
 	
-	DisplayPanel (MainPanel);
-	
 	// initialize 4x AD9959 DDS box
 	DDS4xAD9912_Reset(&DDS4xAD9912);
 	GetCtrlVal(MainPanel, PANEL_DDS1, &frequency);
@@ -318,6 +334,15 @@
 	mupDefineVar(MathParser5, "Math4", &Math4);
 	GetCtrlVal(MainPanel, PANEL_MATHSTRING5, expr);
 	mupSetExpr(MathParser5, expr);
+
+	// data queue
+	CmtNewTSQ(DATA_QUEUE_SIZE, sizeof(double), 0, &dataQueue);
+
+	// register callback to execute when data will be in the data queue
+	CmtInstallTSQCallback(dataQueue, EVENT_TSQ_ITEMS_IN_QUEUE, DATA_EVENT_SIZE,
+		DataAvailableCB, NULL, CmtGetCurrentThreadID(), NULL);
+	
+	DisplayPanel(MainPanel);
 	
 	RunUserInterface();
 	
@@ -469,50 +494,23 @@
 }
 
 
-void CurrentFileName(char *fname)
-{
-	char day[3], month[3], year[3];
-	char *date = DateStr();
-	Scan(date, "%s>%s[w2]-%s[w2]-20%s[w2]", month, day, year);
-	Fmt(fname, "%s<%s\\%s%s%s_Frequ.txt", LOGFILEPATH, year, month, day);
-}
-
-
 int CVICALLBACK CB_OnStart (int panel, int control, int event,
 		void *callbackData, int eventData1, int eventData2)
 {
 	switch (event)
 	{
 		case EVENT_COMMIT:
-			if (Acquiring) {
-				PlotCh1.IndexPoint = 0;
-				PlotCh2.IndexPoint = 0;
-				PlotCh3.IndexPoint = 0;
-				PlotCh4.IndexPoint = 0;
-				PlotMath1.IndexPoint = 0;
-				PlotMath2.IndexPoint = 0; 
-				PlotMath3.IndexPoint = 0; 
-				PlotMath4.IndexPoint = 0; 
-				PlotMath5.IndexPoint = 0;
-				Allan_Reset(&AllanCh1);
-				Allan_Reset(&AllanCh2);
-				Allan_Reset(&AllanCh3);
-				Allan_Reset(&AllanCh4);
-				Allan_Reset(&AllanMath1);
-				Allan_Reset(&AllanMath2);
-				Allan_Reset(&AllanMath3);
-				Allan_Reset(&AllanMath4);
-				Allan_Reset(&AllanMath5);
-			}
-			Acquiring = TRUE;
-			SetCtrlAttribute(MainPanel, PANEL_STARTBUTTON, ATTR_LABEL_TEXT, "__RESET"); 
-			
-			CurrentFileName(LogFileName);
-			GetFileInfo(LogFileName, &OldLogFilePtr);
-			OldLogFilePtr -= OldLogFilePtr%FXLINELENGTH + FXLINELENGTH - 2;
+			if (acquiring)
+				break;
 			
 			logmsg("Start");
+			acquiring = 1;
 			
+			// start data provider thread
+			CmtScheduleThreadPoolFunctionAdv(
+				DEFAULT_THREAD_POOL_HANDLE, DataProvider, NULL,
+				THREAD_PRIORITY_HIGHEST, NULL, 0, NULL, 0, &dataProviderThread);
+
 			break;
 	}
 	return 0;
@@ -523,99 +521,49 @@
 {
 	switch (event) {
 		case EVENT_COMMIT:
-			Acquiring = FALSE ;
-			SetCtrlAttribute(MainPanel, PANEL_STARTBUTTON, ATTR_LABEL_TEXT, "__START");
+			if (! acquiring)
+				break;
+			
+			logmsg("Stop");
+			acquiring = 0;
+			
+			// wait for data provider thread to terminate
+			CmtWaitForThreadPoolFunctionCompletion(
+				DEFAULT_THREAD_POOL_HANDLE, dataProviderThread,
+				OPT_TP_PROCESS_EVENTS_WHILE_WAITING);
+			CmtReleaseThreadPoolFunctionID(
+				DEFAULT_THREAD_POOL_HANDLE, dataProviderThread);
+			
 			break;
 	}
 	return 0;
 }
 
-int CVICALLBACK CB_OnTimer (int panel, int control, int event,
-		void *callbackData, int eventData1, int eventData2)
+
+void CVICALLBACK DataAvailableCB (CmtTSQHandle queueHandle, unsigned int event,
+		int value, void *callbackData)
 {
-	int LogFile;
-	long LogFileSize;
-	char LineBuffer[FXLINELENGTH+10] = "\r\n_1 ";
-	
-	char TimeTag[] = "100103 000000.000";   // K+K time tag meaning here 2010 january the 3rd at 00:00:00.000
-	char Date[] = "03/01/2010" ;
-	char Time[] = "00:00:00.000" ;
-	char Year[] = "2010";
-	char ShortYear[] = "10";  // the last 2 digits of calendar year only
-	char Month[] = "01";
-	char Day[] = "03";
-	char Hour[] = "00";
-	char Min[] = "00" ;
-	char Sec[] = "00.000";
-	struct tm LocalTime ;
-	time_t utcTime;
-
-	int BoxChecked = FALSE; 
+	double data[DATA_EVENT_SIZE];
+	int BoxChecked = FALSE;
+	int read;
 	
 	switch (event) {
-		case EVENT_TIMER_TICK:
-			if (! Acquiring)
-				break;
-			
-			GetFileInfo(LogFileName, &LogFileSize);
-					
-			if (LogFileSize > OldLogFilePtr+2*FXLINELENGTH-2) {  // if a complete newline has been written
-						
-				SuspendTimerCallbacks();
-				
-				// Open Log file and get to the beginning of newly completed line
-				LogFile = OpenFile(LogFileName, VAL_READ_ONLY, VAL_OPEN_AS_IS, VAL_ASCII);
-				OldLogFilePtr += FXLINELENGTH;
-				SetFilePtr(LogFile, OldLogFilePtr, 0);
-				
-				// return the last complete string from the log file and scan it for date and time information 
-				
-				// first, the time tag, and store it in various formats
-				ReadFile(LogFile, TimeTag, 17);
-						
-				CopyBytes(Date,0,TimeTag,4,2);
-				CopyBytes(Date,3,TimeTag,2,2);   
-				CopyBytes(Date,8,TimeTag,0,2);
-				CopyBytes(Time,0,TimeTag,7,2);
-				CopyBytes(Time,3,TimeTag,9,2);
-				CopyBytes(Time,6,TimeTag,11,6);
-				SetCtrlVal(MainPanel, PANEL_DATE, Date);
-				SetCtrlVal(MainPanel, PANEL_TIME, Time); 
+		case EVENT_TSQ_ITEMS_IN_QUEUE:
+			/* read data from the data queue */
+			while (value >= DATA_EVENT_SIZE) {
 				
-				CopyBytes(Year,2,TimeTag,0,2); // first 2 bytes of year string remains "20"
-				CopyBytes(ShortYear,0,TimeTag,0,2);
-				CopyBytes(Month,0,TimeTag,2,2);
-				CopyBytes(Day,0,TimeTag,4,2);
-				CopyBytes(Hour,0,TimeTag,7,2);
-				CopyBytes(Min,0,TimeTag,9,2);
-				CopyBytes(Sec,0,TimeTag,11,6);
-				Fmt(&LocalTime.tm_year, "%d<%s", Year);
-				Fmt(&LocalTime.tm_mon,  "%d<%s", Month);
-				Fmt(&LocalTime.tm_mday, "%d<%s", Day);
-				Fmt(&LocalTime.tm_hour, "%d<%s", Hour);
-				Fmt(&LocalTime.tm_min,  "%d<%s", Min);
-				Fmt(&LocalTime.tm_sec,  "%d<%s", "00");    // special case to handle non integer number of UTC seconds
-				LocalTime.tm_hour += 0;
-				LocalTime.tm_min  -= 0;  
-				LocalTime.tm_sec  -= 0;  
-				LocalTime.tm_mon  -= 1;  	// january is month 0 for tm struct
-				LocalTime.tm_year -= 1900; // year is number of years since 1900 for tm struct
-				LocalTime.tm_isdst = -1;  // daylight saving flag MUST be set to -1 (unallocated is bugging and +1 is making 1 hour error in summer)
-				utcTime = mktime (&LocalTime);
-				utc = (double) utcTime + strtod(Sec,NULL);
+				read = CmtReadTSQData(queueHandle, data, DATA_EVENT_SIZE, TSQ_INFINITE_TIMEOUT, 0);
+				if (read != DATA_EVENT_SIZE)
+					logmsg("Error!");
+				value = value - read;
+				
+				utc = data[0];
+				Ch1 = data[1];
+				Ch2 = data[2];
+				Ch3 = data[3];
+				Ch4 = data[4];
+				
 				SetCtrlVal(MainPanel, PANEL_UTC, utc);
-				
-				// scan the line for counters's channels information
-				
-				ReadLine(LogFile, LineBuffer, FXLINELENGTH+9);
-				CloseFile(LogFile);
-				
-				Scan(LineBuffer, "%f%f%f%f", &Ch1, &Ch2, &Ch3, &Ch4);
-				Ch1 = 1000*Ch1;
-				Ch2 = 1000*Ch2;
-				Ch3 = 1000*Ch3;
-				Ch4 = 1000*Ch4;
-						
 				SetCtrlVal(MainPanel, PANEL_FREQ1, Ch1);
 				SetCtrlVal(MainPanel, PANEL_FREQ2, Ch2);
 				SetCtrlVal(MainPanel, PANEL_FREQ3, Ch3);  
@@ -1327,47 +1275,38 @@
 				}
 				
 				int save;
+				
 				// run id derived from current date in the form YYMMDD
 				char id[7];
-				snprintf(id, sizeof(id), "%2s%2s%2s", ShortYear, Month, Day);
+				FormatDateTimeString(utc, "%y%m%d", id, sizeof(id));
+				
+				// time
+				char timestr[24];
+				FormatDateTimeString(utc, "%d/%m/%Y %H:%M:%S.%3f", timestr, sizeof(timestr));
+				SetCtrlVal(MainPanel, PANEL_TIME, timestr);
 				
 				// write LO frequency (Math2) to disk
 				GetCtrlVal(MainPanel, PANEL_CHECKBOX_MATH2SAVE, &save);
 				if (save) {
-					writeData(DATAFOLDER, "Lo", id, Date, Time, utc, Math2);
-					writeData("C:\\Femto\\Results", "OptCavity", id, Date, Time, utc, Math2);
+					writeData(DATAFOLDER, "Lo", id, timestr, utc, Math2);
+					writeData("C:\\Femto\\Results", "OptCavity", id, timestr, utc, Math2);
 				}
 				
 				// write Hg frequency (Math3) to disk
 				GetCtrlVal(MainPanel, PANEL_CHECKBOX_MATH3SAVE, &save);
 				if (save) {
-					writeData(DATAFOLDER, "Hg", id, Date, Time, utc, Math3);
-					writeData("C:\\Femto\\Results", "HgCavity", id, Date, Time, utc, Math3);
+					writeData(DATAFOLDER, "Hg", id, timestr, utc, Math3);
+					writeData("C:\\Femto\\Results", "HgCavity", id, timestr, utc, Math3);
 				}
 				
 				// write ExtraMath (Math5) to disk
 				GetCtrlVal(MainPanel, PANEL_CHECKBOX_MATH5SAVE, &save);
 				if (save) {
-					writeData(DATAFOLDER, "Ex", id, Date, Time, utc, Math5);
+					writeData(DATAFOLDER, "Ex", id, timestr, utc, Math5);
 				}
-				
-				// Special case to handle change of day at next second
-				if ( LocalTime.tm_hour==23 && LocalTime.tm_min==59 && strtod(Sec,NULL)>=58 ) { 
-					Acquiring = FALSE;
-					do {
-						Delay(5.1);
-						CurrentFileName(LogFileName);
-					} while (!GetFileInfo(LogFileName, &OldLogFilePtr));
-					Acquiring = TRUE;
-					OldLogFilePtr = 2;
-				}
-				
-				ResumeTimerCallbacks(); 
-				
 			}		
 			break;
 	}
-	return 0;
 }