From e59a4dc665f3e1fff598a12c9f019fcb5da38728 Mon Sep 17 00:00:00 2001 From: Michael Huth Date: Wed, 6 Mar 2024 01:07:12 +0100 Subject: [PATCH 1/2] bugfix: FIFO2WAVE does not work with single point ranges - there exists a bug in Igor Pro 9 where FIFO2WAVE does not work with ranges of a single point - These ranges can appear in DAQ however: - If the background task is called very fast. However due to the 1/60 s minimul rate this is very unlikely and happens in reality basically never - If the last fifo position is one point before the planned end, i.e. size of the AD channel wave. Then on next readout only one point is read, even if V_FIFOChunks would allow more. This was an approach to minimize copying unnecessary data. Workaround: The workaround includes two changes: 1. Readout only if there are at least two new samples in the FIFO. 2. Readout all new samples in the FIFO and then copy only the needed part, specifically at the end of acquisition. Change 1 guarantees that there are always 2 points or more read from the FIFO. Change 2 moves the possible single point transfer to our copy part. Logical differences Before: * Enter readout for 1 to N new samples in FIFO. * Readout X samples, where X is min(N, neededNumberOfSamples), neededNumberOfSamples is the size of the AD channel wave minus the last FIFO position. If that difference is one, a readout of a single point can be attempted here. * Copy X samples from the readOut wave to the AD channel Now: * Enter readout for 2 to N new samples in FIFO. * Readout N samples * Copy X samples, where X is min(N, neededNumberOfSamples) from the readOut wave to the AD channel After the change the algorithm is slightly less efficient because FIFO2WAVE copies always all new samples to the readout wave, even if for AD channel are less needed at the end of acquisiton. --- Packages/MIES/MIES_DataAcquisition_Multi.ipf | 10 ++++++---- .../HardwareBasic/UTF_BasicHardwareTests.ipf | 19 +++++++++++++++++++ 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/Packages/MIES/MIES_DataAcquisition_Multi.ipf b/Packages/MIES/MIES_DataAcquisition_Multi.ipf index 181cbb6667..d2b9f3370d 100644 --- a/Packages/MIES/MIES_DataAcquisition_Multi.ipf +++ b/Packages/MIES/MIES_DataAcquisition_Multi.ipf @@ -16,7 +16,7 @@ Function DQM_FIFOMonitor(s) STRUCT BackgroundStruct &s variable deviceID, isFinished, hardwareType - variable i, j, err, fifoLatest, result, channel, lastTP, gotTPChannels + variable i, j, err, fifoLatest, result, channel, lastTP, gotTPChannels, newSamplesCount variable bufferSize string device, fifoChannelName, fifoName, errMsg WAVE ActiveDeviceList = GetDQMActiveDeviceList() @@ -44,7 +44,9 @@ Function DQM_FIFOMonitor(s) fifoName = GetNIFIFOName(deviceID) FIFOStatus/Q $fifoName ASSERT(V_Flag != 0,"FIFO does not exist!") - if(fifoPosGlobal == V_FIFOChunks) + newSamplesCount = V_FIFOChunks - fifoPosGlobal + if(newSamplesCount < 2) + // workaround for Igor Pro bug 5092 continue // no new data -> next device endif @@ -55,11 +57,11 @@ Function DQM_FIFOMonitor(s) fifoChannelName = StringByKey("NAME" + num2str(j), S_Info) channel = str2num(fifoChannelName) WAVE NIChannel = NIDataWave[channel] + FIFO2WAVE/R=[fifoPosGlobal, fifoPosGlobal + newSamplesCount - 1] $fifoName, $fifoChannelName, wNIReadOut; AbortOnRTE + bufferSize = DimSize(NIChannel, ROWS) fifoLatest = min(V_FIFOChunks, bufferSize) isFinished = (fifoLatest == bufferSize) ? 1 : isFinished - - FIFO2WAVE/R=[fifoPosGlobal, fifoLatest - 1] $fifoName, $fifoChannelName, wNIReadOut; AbortOnRTE multithread NIChannel[fifoPosGlobal, fifoLatest - 1] = wNIReadOut[p - fifoPosGlobal] SetScale/P x, 0, DimDelta(wNIReadOut, ROWS) * ONE_TO_MILLI, "ms", NIChannel diff --git a/Packages/tests/HardwareBasic/UTF_BasicHardwareTests.ipf b/Packages/tests/HardwareBasic/UTF_BasicHardwareTests.ipf index b482b9b250..d874f55156 100644 --- a/Packages/tests/HardwareBasic/UTF_BasicHardwareTests.ipf +++ b/Packages/tests/HardwareBasic/UTF_BasicHardwareTests.ipf @@ -2271,3 +2271,22 @@ End static Function CheckIfNoTTLonTP_REENTRY([string str]) PASS() End + +#ifdef TESTS_WITH_NI_HARDWARE +// UTF_TD_GENERATOR DeviceNameGeneratorMD1 +static Function TestNIAcquisitionReliability([str]) + string str + + STRUCT DAQSettings s + InitDAQSettingsFromString(s, "MD1_RA1_I0_L0_BKG1_FFR:10:_RES1000" + \ + "__HS0_DA0_AD0_CM:VC:_ST:EpochTest6_DA_0:") + + AcquireData_NG(s, str) +End + +static Function TestNIAcquisitionReliability_REENTRY([str]) + string str + + CHECK_EQUAL_VAR(GetSetVariable(str, "SetVar_Sweep"), 1000) +End +#endif From 2be4a2c66e319b2fcf3fde87fa5d84b5fce76793 Mon Sep 17 00:00:00 2001 From: Michael Huth Date: Fri, 8 Mar 2024 20:46:32 +0100 Subject: [PATCH 2/2] Tests: Increase timeout for acquisition in tests to 15 mins - NI reliability test seems to need a bit more time on the CI machine --- Packages/tests/UTF_HardwareHelperFunctions.ipf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Packages/tests/UTF_HardwareHelperFunctions.ipf b/Packages/tests/UTF_HardwareHelperFunctions.ipf index d33de56f39..8080613111 100644 --- a/Packages/tests/UTF_HardwareHelperFunctions.ipf +++ b/Packages/tests/UTF_HardwareHelperFunctions.ipf @@ -350,7 +350,7 @@ Function RegisterReentryFunction(string testcase) if(FuncRefIsAssigned(FuncRefInfo(reentryFuncPlain)) || FuncRefIsAssigned(FuncRefInfo(reentryFuncMDStr)) || FuncRefIsAssigned(FuncRefInfo(reentryFuncRefWave)) || FuncRefIsAssigned(FuncRefInfo(reentryFuncMDD))) CtrlNamedBackGround DAQWatchdog, start, period=120, proc=WaitUntilDAQDone_IGNORE CtrlNamedBackGround TPWatchdog, start, period=120, proc=WaitUntilTPDone_IGNORE - RegisterUTFMonitor(TASKNAMES + "DAQWatchdog;TPWatchdog", BACKGROUNDMONMODE_AND, reentryFuncName, timeout = 600, failOnTimeout = 1) + RegisterUTFMonitor(TASKNAMES + "DAQWatchdog;TPWatchdog", BACKGROUNDMONMODE_AND, reentryFuncName, timeout = 900, failOnTimeout = 1) endif End