Mercurial > hg > fxanalyse
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; }