diff --git a/Common/Common.csproj b/Common/Common.csproj
index adc6a0025..2b80d5d7d 100644
--- a/Common/Common.csproj
+++ b/Common/Common.csproj
@@ -67,6 +67,7 @@
+
diff --git a/TBF/Rig/TestMethods/iPerlCommunication/iPerlHead/OptoTelegramRaw.cs b/Common/Iperl/OptoTelegramRaw.cs
similarity index 67%
rename from TBF/Rig/TestMethods/iPerlCommunication/iPerlHead/OptoTelegramRaw.cs
rename to Common/Iperl/OptoTelegramRaw.cs
index da5b0a1bb..c17bdff67 100644
--- a/TBF/Rig/TestMethods/iPerlCommunication/iPerlHead/OptoTelegramRaw.cs
+++ b/Common/Iperl/OptoTelegramRaw.cs
@@ -4,9 +4,18 @@
using System;
using System.Globalization;
-namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
+namespace Common.Iperl
{
- public class OptoTelegramRaw
+ public enum OptoTelegramFlags : byte
+ {
+ OK = 0,
+ OK_TestStart,
+ OK_TestEnd,
+ InvalidTelegram, /// Wrong telegram format of checksum error
+ SyncError,
+ }
+
+ public class OptoTelegramRaw
{
public static readonly int Length = 42;
private static CultureInfo culture;
@@ -96,16 +105,16 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
///
/// A complete byte array data
/// true = telegram OK, false = telegram NOK
- public bool UpdateFromString(string telegram, int counter, ref Int64 volumeRawExtLast, ref Int64 timestampExtLast)
+ public bool UpdateFromString(string telegram, int counter, float refFlow, ref Int64 volumeRawExtLast, ref Int64 timestampExtLast, bool isLog = false)
{
DateTime = DateTime.Now;
Counter = counter;
- RefFlow = (float)Sequences.ProcessData.RefFlow.Val;
+ RefFlow = refFlow;
if ((telegram == null) || (telegram.Length < Length) ||
(telegram[6] != '\t') || (telegram[11] != '\t') || (telegram[16] != '\t') ||
(telegram[23] != '\t') || (telegram[28] != '\t') || (telegram[37] != '\t') ||
- (telegram[40] != '\r') || (telegram[41] != '\n'))
+ (!isLog && (telegram[40] != '\r' || telegram[41] != '\n')))
{
Flags = OptoTelegramFlags.InvalidTelegram;
return false;
@@ -183,7 +192,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
public bool UpdateFromStringDummy(string telegram)
{
DateTime = DateTime.Now;
- RefFlow = (float)Sequences.ProcessData.RefFlow.Val;
+ RefFlow = 0;
if ((telegram == null) || (telegram.Length < Length) ||
(telegram[6] != '\t') || (telegram[11] != '\t') || (telegram[16] != '\t') ||
@@ -229,104 +238,30 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
else /// if (flags == OptoTelegramFlags.OK / OptoTelegramFlags.OK_TestStart / OptoTelegramFlags.OK_TestEnd)
{
return string.Format("{0}:{1}:{2}.{3}\t{4} :\t{5}\t{6}\t{7}\t{8}\t{9}\t{10}\t{11}\t{12}\t{13}\t{14}\t{15}\t{16}\t{17}\t{18}\t{19}\t{20}\t{21}\t{22}",
- /* 0 */ DateTime.Hour.ToString("D2"),
- /* 1 */ DateTime.Minute.ToString("D2"),
- /* 2 */ DateTime.Second.ToString("D2"),
- /* 3 */ DateTime.Millisecond.ToString("D4"),
- /* 4 */ Counter,
- /* 5 */ EmfRaw.ToString("X6"),
- /* 6 */ MagneticFieldRaw.ToString("X4"),
- /* 7 */ FlowRaw.ToString("X4"),
- /* 8 */ VolumeRaw.ToString("X6"),
- /* 9 */ Impedance.ToString("X4"),
- /* 10 */ Timestamp.ToString("X8"),
- /* 11 */ CheckSum.ToString("X2"),
- /* 12 */ EMF().ToString("F4", culture),
- /* 13 */ MagneticField().ToString("F0", culture),
- /* 14 */ Flow(scalingFactor).ToString("F2", culture),
- /* 15 */ Volume(scalingFactor).ToString("F4", culture),
- /* 16 */ FlipTime().ToString("F0", culture),
- /* 17 */ TimestampDec().ToString("F4", culture),
- /* 18 */ (RefFlow * 1000).ToString("F2", culture),
- /* 19 */ VolumeDelta(scalingFactor, previous).ToString("F4", culture),
- /* 20 */ TimeDelta().ToString("F3", culture),
- /* 21 */ scalingFactor.ToString("F1", culture),
- /* 22 */ Label());
+ DateTime.Hour.ToString("D2"),
+ DateTime.Minute.ToString("D2"),
+ DateTime.Second.ToString("D2"),
+ DateTime.Millisecond.ToString("D4"),
+ Counter,
+ EmfRaw.ToString("X6"),
+ MagneticFieldRaw.ToString("X4"),
+ FlowRaw.ToString("X4"),
+ VolumeRaw.ToString("X6"),
+ Impedance.ToString("X4"),
+ Timestamp.ToString("X8"),
+ CheckSum.ToString("X2"),
+ EMF().ToString("F4", culture),
+ MagneticField().ToString("F0", culture),
+ Flow(scalingFactor).ToString("F2", culture),
+ Volume(scalingFactor).ToString("F4", culture),
+ FlipTime().ToString("F0", culture),
+ TimestampDec().ToString("F4", culture),
+ (RefFlow * 1000).ToString("F2", culture),
+ VolumeDelta(scalingFactor, previous).ToString("F4", culture),
+ TimeDelta().ToString("F3", culture),
+ scalingFactor.ToString("F1", culture),
+ Label());
}
}
-
- ///
- /// Filter RefFlow data in an array of OptoTelegramRaw objects by a FIR filter:
- ///
- /// kSize = 5, kSize2 = 2
- ///
- /// i k
- /// ---------------------------------------------------------------------------
- /// 0 -5 filtered[0] = data[0]
- /// 1 -4 filtered[1] = data[1]
- /// 2 -3 filtered[2] = data[0]*k[0] + ... + data[4]*k[4]
- /// 3 -2 filtered[3] = data[1]*k[0] + ... + data[5]*k[4]
- /// 4 -1 filtered[4] = data[2]*k[0] + ... + data[6]*k[4]
- /// 5 0 data[0] = filtered[0], filtered[0] = data[3]*k[0] + ... + data[7]*k[4]
- /// 6 1 data[1] = filtered[1], filtered[1] = data[4]*k[0] + ... + data[8]*k[4]
- /// 7 ...
- ///
- /// array of OptoTelegramRaw objects
- /// Index of the first optoData item to process
- /// Index of the last optoData item to process
- public static void FIRFilterFlow(OptoTelegramRaw[] optoData, int from, int to)
- {
- float[] kernel = new float[] { 0.1f, 0.2f, 0.4f, 0.2f, 0.1f };
- int kSize = kernel.Length;
- int kSize2 = kernel.Length / 2;
-
- float[] filtered = new float[kSize];
-
- for (int i = from; i <= to; i++)
- {
- if ((i < from + kSize2) || (i > to - kSize2))
- {
- /// Beginning or end of optoData buffer => Just copy data (=do not filter)
- filtered[i % kSize] = optoData[BufferIdx(i)].RefFlow;
- }
- else
- {
- /// Make a convolution of optoData and the kernel
- float weightedSum = 0;
- for (int j = -kSize2; j <= kSize2; j++)
- weightedSum += optoData[BufferIdx(i + j)].RefFlow * kernel[j + kSize2];
-
- filtered[i % kSize] = weightedSum;
- }
-
- if (i >= from + kSize)
- {
- /// filtered[] buffer full => copy filtered data to optoData
- optoData[BufferIdx(i - kSize)].RefFlow = filtered[i % kSize];
- }
- }
-
- for (int i = to - kSize + 1; i <= to; i++)
- {
- if (i >= 0) optoData[BufferIdx(i)].RefFlow = filtered[i % kSize];
- }
- }
-
- ///
- /// Get index to optoData buffer
- ///
- /// Original unwrapped index
- /// Index to the buffer
- public static int BufferIdx(int index)
- {
- if (index < IperlHead.MaxOptoDataCount)
- {
- return index;
- }
- else
- {
- return IperlHead.StartOptoDataCount + (index - IperlHead.MaxOptoDataCount) % IperlHead.EndOptoDataCount;
- }
- }
}
}
diff --git a/Common/Utils.cs b/Common/Utils.cs
index f62157d9b..a1c1173ac 100644
--- a/Common/Utils.cs
+++ b/Common/Utils.cs
@@ -284,5 +284,46 @@ namespace Common
(userName.Equals("gilles") && password.Equals("alibaba")) ||
(userName.Equals(passwordOfDay) && password.Equals(passwordOfDay));
}
+
+ public static void CalculateFeatureVector(Iperl.OptoTelegramRaw[] optoData, int optoDataCount, int startIx, int endIx, ref float[] x)
+ {
+ if (startIx < 0 || endIx >= optoDataCount || startIx >= endIx) return;
+
+ int n = 0;
+ Int64 sumFlow = 0;
+ Int64 sumFlow2 = 0;
+ Int64 sumEmf = 0;
+ Int64 sumEmf2 = 0;
+ Int64 sumMagF = 0;
+ Int64 sumMagF2 = 0;
+ Int64 sumImp = 0;
+ Int64 sumImp2 = 0;
+
+ for (int ix = startIx; ix <= endIx; ix++)
+ {
+ if (optoData[ix].Flags == Iperl.OptoTelegramFlags.OK ||
+ optoData[ix].Flags == Iperl.OptoTelegramFlags.OK_TestStart ||
+ optoData[ix].Flags == Iperl.OptoTelegramFlags.OK_TestEnd)
+ {
+ n++;
+ sumFlow += optoData[ix].FlowRaw;
+ sumFlow2 += ((int)optoData[ix].FlowRaw * (int)optoData[ix].FlowRaw);
+ sumEmf += (int)optoData[ix].EmfRaw;
+ sumEmf2 += ((Int64)optoData[ix].EmfRaw * (Int64)optoData[ix].EmfRaw);
+ sumMagF += optoData[ix].MagneticFieldRaw;
+ sumMagF2 += ((int)optoData[ix].MagneticFieldRaw * (int)optoData[ix].MagneticFieldRaw);
+ sumImp += optoData[ix].Impedance;
+ sumImp2 += ((int)optoData[ix].Impedance * (int)optoData[ix].Impedance);
+ }
+ }
+
+ if (n >= 2)
+ {
+ if (x.Length > 0) x[0] = ((float)sumFlow2 - (float)sumFlow * (float)sumFlow / n) / (n - 1);
+ if (x.Length > 1) x[1] = ((float)sumEmf2 - (float)sumEmf * (float)sumEmf / n) / (n - 1);
+ if (x.Length > 2) x[2] = ((float)sumMagF2 - (float)sumMagF * (float)sumMagF / n) / (n - 1);
+ if (x.Length > 3) x[3] = ((float)sumImp2 - (float)sumImp * (float)sumImp / n) / (n - 1);
+ }
+ }
}
}
diff --git a/TBF.sln b/TBF.sln
index f9749771a..f12e0e9ce 100644
--- a/TBF.sln
+++ b/TBF.sln
@@ -3,6 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2012
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TBF", "TBF\TBF.csproj", "{8648FD92-CDA1-4C3A-B5F9-FE547CE1FA48}"
ProjectSection(ProjectDependencies) = postProject
+ {7EBEEA14-91C4-48D7-AF0A-7A4BC3FF9A28} = {7EBEEA14-91C4-48D7-AF0A-7A4BC3FF9A28}
{C8939821-BA5C-4988-A3D0-BF53B74865C7} = {C8939821-BA5C-4988-A3D0-BF53B74865C7}
{211B5E3F-9996-48A7-ABDE-C878DD2D71C2} = {211B5E3F-9996-48A7-ABDE-C878DD2D71C2}
{0C0A1F4D-1363-4544-A7C5-196C76D26CCA} = {0C0A1F4D-1363-4544-A7C5-196C76D26CCA}
diff --git a/TBF/Rig/TestMethods/iPerlCommunication/iPerlHead/Enums.cs b/TBF/Rig/TestMethods/iPerlCommunication/iPerlHead/Enums.cs
index dd9adcac8..84c4c2fd9 100644
--- a/TBF/Rig/TestMethods/iPerlCommunication/iPerlHead/Enums.cs
+++ b/TBF/Rig/TestMethods/iPerlCommunication/iPerlHead/Enums.cs
@@ -99,15 +99,6 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
Count /// Number of flow states
}
- public enum OptoTelegramFlags : byte
- {
- OK = 0,
- OK_TestStart,
- OK_TestEnd,
- InvalidTelegram, /// Wrong telegram format of checksum error
- SyncError,
- }
-
public enum OptoState
{
Read,
diff --git a/TBF/Rig/TestMethods/iPerlCommunication/iPerlHead/IperlHead.cs b/TBF/Rig/TestMethods/iPerlCommunication/iPerlHead/IperlHead.cs
index fe983d768..6ff856e32 100644
--- a/TBF/Rig/TestMethods/iPerlCommunication/iPerlHead/IperlHead.cs
+++ b/TBF/Rig/TestMethods/iPerlCommunication/iPerlHead/IperlHead.cs
@@ -1,11 +1,12 @@
///
-/// Copyright (c) 2015-2020 Sensus Slovensko a.s.
+/// Copyright (c) 2015-2021 Sensus Slovensko a.s.
///
using System;
using System.IO;
using System.IO.Ports;
using log4net;
using Common;
+using Common.Iperl;
using Config.Entities;
using TBF.Rig.Generic;
using TBF.Rig.GenericDevices;
@@ -613,8 +614,8 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
/// Stop this operation
public void Stop()
{
- int startIx = OptoTelegramRaw.BufferIdx(TestStartTelegramIx);
- int endIx = OptoTelegramRaw.BufferIdx(TestEndTelegramIx);
+ int startIx = BufferIdx(TestStartTelegramIx);
+ int endIx = BufferIdx(TestEndTelegramIx);
log.WarnFormat("IperlHeadd.Stop() startIx={0} endIx={1} optoData.Len={2} filename={3}", startIx, endIx, optoData.Length, !string.IsNullOrEmpty(optoDataLogFileName) ? optoDataLogFileName : "");
@@ -634,17 +635,17 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
StopParsingOptoSerialPort();
if (optoDataCount <= MaxOptoDataCount)
{
- OptoTelegramRaw.FIRFilterFlow(optoData, 0, optoDataCount - 1);
+ FIRFilterFlow(optoData, 0, optoDataCount - 1);
}
else
{
- OptoTelegramRaw.FIRFilterFlow(optoData, 0, StartOptoDataCount - 1);
- OptoTelegramRaw.FIRFilterFlow(optoData, (optoDataCount - EndOptoDataCount), optoDataCount - 1);
+ FIRFilterFlow(optoData, 0, StartOptoDataCount - 1);
+ FIRFilterFlow(optoData, (optoDataCount - EndOptoDataCount), optoDataCount - 1);
}
log.DebugFormat("Flow filtering end, feature vector calculation start: {0:HH:mm:ss.fff}", DateTime.Now);
- CalculateFeatureVector(optoData, optoDataCount, startIx, endIx, ref x);
+ Common.Utils.CalculateFeatureVector(optoData, optoDataCount, startIx, endIx, ref x);
log.DebugFormat("Feature vector calculation end, save opto-file start: {0:HH:mm:ss.fff}", DateTime.Now);
@@ -662,51 +663,10 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
}
}
- void CalculateFeatureVector(OptoTelegramRaw[] optoData, int optoDataCount, int startIx, int endIx, ref float[] x)
- {
- if (startIx < 0 || endIx >= optoDataCount || startIx >= endIx) return;
-
- int n = 0;
- Int64 sumFlow = 0;
- Int64 sumFlow2 = 0;
- Int64 sumEmf = 0;
- Int64 sumEmf2 = 0;
- Int64 sumMagF = 0;
- Int64 sumMagF2 = 0;
- Int64 sumImp = 0;
- Int64 sumImp2 = 0;
-
- for (int ix = startIx; ix <= endIx; ix++)
- {
- if (optoData[ix].Flags == OptoTelegramFlags.OK ||
- optoData[ix].Flags == OptoTelegramFlags.OK_TestStart ||
- optoData[ix].Flags == OptoTelegramFlags.OK_TestEnd)
- {
- n++;
- sumFlow += optoData[ix].FlowRaw;
- sumFlow2 += ((int)optoData[ix].FlowRaw * (int)optoData[ix].FlowRaw);
- sumEmf += (int)optoData[ix].EmfRaw;
- sumEmf2 += ((Int64)optoData[ix].EmfRaw * (Int64)optoData[ix].EmfRaw);
- sumMagF += optoData[ix].MagneticFieldRaw;
- sumMagF2 += ((int)optoData[ix].MagneticFieldRaw * (int)optoData[ix].MagneticFieldRaw);
- sumImp += optoData[ix].Impedance;
- sumImp2 += ((int)optoData[ix].Impedance * (int)optoData[ix].Impedance);
- }
- }
-
- if (n >= 2)
- {
- if (x.Length > 0) x[0] = ((float)sumFlow2 - (float)sumFlow * (float)sumFlow / n) / (n - 1);
- if (x.Length > 1) x[1] = ((float)sumEmf2 - (float)sumEmf * (float)sumEmf / n) / (n - 1);
- if (x.Length > 2) x[2] = ((float)sumMagF2 - (float)sumMagF * (float)sumMagF / n) / (n - 1);
- if (x.Length > 3) x[3] = ((float)sumImp2 - (float)sumImp * (float)sumImp / n) / (n - 1);
- }
- }
-
///
/// Save opto data to a file.
///
- string SaveOptoData()
+ string SaveOptoData()
{
if (!string.IsNullOrEmpty(optoDataLogFileName))
{
@@ -747,11 +707,10 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
optoLogFile.WriteLine(" ...");
/// Second part of the buffer is an overflowed circular buffer
- optoLogFile.WriteLine(optoData[OptoTelegramRaw.BufferIdx(optoDataCount)].ToString(scalFact, null));
+ optoLogFile.WriteLine(optoData[BufferIdx(optoDataCount)].ToString(scalFact, null));
for (int i = optoDataCount - EndOptoDataCount + 1; i < optoDataCount; i++)
{
- optoLogFile.WriteLine(optoData[OptoTelegramRaw.BufferIdx(i)]
- .ToString(scalFact, optoData[OptoTelegramRaw.BufferIdx(i - 1)]));
+ optoLogFile.WriteLine(optoData[BufferIdx(i)].ToString(scalFact, optoData[BufferIdx(i - 1)]));
}
}
@@ -844,7 +803,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
/// CR+LF found
if (optoState == OptoState.Read)
{
- int bufferIx = OptoTelegramRaw.BufferIdx(optoDataCount);
+ int bufferIx = BufferIdx(optoDataCount);
if (pos < OptoTelegramRaw.Length - 2)
{
@@ -857,7 +816,10 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
}
synchronized = true;
}
- else if (optoData[bufferIx].UpdateFromString(allRcvd.Substring(pos - OptoTelegramRaw.Length + 2), optoDataCount, ref volumeRawExtLast, ref timestampExtLast))
+ else if (optoData[bufferIx].UpdateFromString(allRcvd.Substring(pos - OptoTelegramRaw.Length + 2),
+ optoDataCount,
+ Convert.ToSingle(Sequences.ProcessData.RefFlow.Val),
+ ref volumeRawExtLast, ref timestampExtLast))
{
/// CR+LF was found && (pos >= OptoTelegramRaw.Length - 2) && the telegram is OK
flowDirectionDetection.WriteToFifo(volumeRawExtLast, timestampExtLast);
@@ -884,7 +846,10 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
synchronized = true;
}
// CR+LF found and (pos >= OptoTelegram.Length - 2)
- else if (toBeFlushed.UpdateFromString(allRcvd.Substring(pos - OptoTelegramRaw.Length + 2), 0, ref volumeRawExtLast, ref timestampExtLast))
+ else if (toBeFlushed.UpdateFromString(allRcvd.Substring(pos - OptoTelegramRaw.Length + 2),
+ 0,
+ Convert.ToSingle(Sequences.ProcessData.RefFlow.Val),
+ ref volumeRawExtLast, ref timestampExtLast))
{
flowDirectionDetection.WriteToFifo(volumeRawExtLast, timestampExtLast);
synchronized2 = synchronized;
@@ -971,9 +936,9 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
switch (units)
{
default:
- case VolumeUnits.m3: return Common.Units.ConvertFrom(Common.Unit.m3, 1.0); /// liter
- case VolumeUnits.UK_gallon: return Common.Units.ConvertFrom(Common.Unit.UKgal, 1.0); /// liter
- case VolumeUnits.US_gallon: return Common.Units.ConvertFrom(Common.Unit.USgal, 1.0); /// liter
+ case VolumeUnits.m3: return Common.Units.ConvertFrom(Common.Unit.m3, 1.0); /// 1 liter
+ case VolumeUnits.UK_gallon: return Common.Units.ConvertFrom(Common.Unit.UKgal, 1.0); /// 1 imperial gallon
+ case VolumeUnits.US_gallon: return Common.Units.ConvertFrom(Common.Unit.USgal, 1.0); /// 1 US gallon
}
}
@@ -1032,7 +997,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
Int64 sum = 0;
for (int i = unwrappedIx - samplesCount2; i <= unwrappedIx + samplesCount2; i++)
{
- int wrappedIx = OptoTelegramRaw.BufferIdx(i);
+ int wrappedIx = BufferIdx(i);
if (optoData[wrappedIx].Flags != OptoTelegramFlags.OK &&
optoData[wrappedIx].Flags != OptoTelegramFlags.OK_TestStart &&
@@ -1061,7 +1026,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
Int64 sum = 0;
for (int i = unwrappedIx - samplesCount2; i <= unwrappedIx + samplesCount2; i++)
{
- int wrappedIx = OptoTelegramRaw.BufferIdx(i);
+ int wrappedIx = BufferIdx(i);
if (optoData[wrappedIx].Flags != OptoTelegramFlags.OK &&
optoData[wrappedIx].Flags != OptoTelegramFlags.OK_TestStart &&
@@ -1076,6 +1041,80 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
return sum / (double)(8192 * (2 * samplesCount2 + 1));
}
+ ///
+ /// Filter RefFlow data in an array of OptoTelegramRaw objects by a FIR filter:
+ ///
+ /// kSize = 5, kSize2 = 2
+ ///
+ /// i k
+ /// ---------------------------------------------------------------------------
+ /// 0 -5 filtered[0] = data[0]
+ /// 1 -4 filtered[1] = data[1]
+ /// 2 -3 filtered[2] = data[0]*k[0] + ... + data[4]*k[4]
+ /// 3 -2 filtered[3] = data[1]*k[0] + ... + data[5]*k[4]
+ /// 4 -1 filtered[4] = data[2]*k[0] + ... + data[6]*k[4]
+ /// 5 0 data[0] = filtered[0], filtered[0] = data[3]*k[0] + ... + data[7]*k[4]
+ /// 6 1 data[1] = filtered[1], filtered[1] = data[4]*k[0] + ... + data[8]*k[4]
+ /// 7 ...
+ ///
+ /// array of OptoTelegramRaw objects
+ /// Index of the first optoData item to process
+ /// Index of the last optoData item to process
+ public static void FIRFilterFlow(OptoTelegramRaw[] optoData, int from, int to)
+ {
+ float[] kernel = new float[] { 0.1f, 0.2f, 0.4f, 0.2f, 0.1f };
+ int kSize = kernel.Length;
+ int kSize2 = kernel.Length / 2;
+
+ float[] filtered = new float[kSize];
+
+ for (int i = from; i <= to; i++)
+ {
+ if ((i < from + kSize2) || (i > to - kSize2))
+ {
+ /// Beginning or end of optoData buffer => Just copy data (=do not filter)
+ filtered[i % kSize] = optoData[BufferIdx(i)].RefFlow;
+ }
+ else
+ {
+ /// Make a convolution of optoData and the kernel
+ float weightedSum = 0;
+ for (int j = -kSize2; j <= kSize2; j++)
+ weightedSum += optoData[BufferIdx(i + j)].RefFlow * kernel[j + kSize2];
+
+ filtered[i % kSize] = weightedSum;
+ }
+
+ if (i >= from + kSize)
+ {
+ /// filtered[] buffer full => copy filtered data to optoData
+ optoData[BufferIdx(i - kSize)].RefFlow = filtered[i % kSize];
+ }
+ }
+
+ for (int i = to - kSize + 1; i <= to; i++)
+ {
+ if (i >= 0) optoData[BufferIdx(i)].RefFlow = filtered[i % kSize];
+ }
+ }
+
+ ///
+ /// Get index to optoData buffer
+ ///
+ /// Original unwrapped index
+ /// Index to the buffer
+ public static int BufferIdx(int index)
+ {
+ if (index < IperlHead.MaxOptoDataCount)
+ {
+ return index;
+ }
+ else
+ {
+ return IperlHead.StartOptoDataCount + (index - IperlHead.MaxOptoDataCount) % IperlHead.EndOptoDataCount;
+ }
+ }
+
public void WriteBinary(BinaryWriter writer)
{
writer.Write(Disabled);
diff --git a/TBF/TBF.csproj b/TBF/TBF.csproj
index 81e25a9bb..f75e375ca 100644
--- a/TBF/TBF.csproj
+++ b/TBF/TBF.csproj
@@ -1487,7 +1487,6 @@
-