162 lines
6.4 KiB
C#
162 lines
6.4 KiB
C#
///
|
|
/// Copyright (c) 2021 Sensus Slovensko a.s.
|
|
///
|
|
using System;
|
|
using log4net;
|
|
using TBF.Rig.Sequences;
|
|
using TBF.Rig.Uni.Diverter;
|
|
|
|
namespace TBF.Rig.ControlBoard.Uni
|
|
{
|
|
public class DivTransitionData
|
|
{
|
|
private static readonly ILog log = LogManager.GetLogger(typeof(DivTransitionData));
|
|
|
|
/// Used in FrameFitsData(), etc.
|
|
public const int MessageLen = 255;
|
|
public const byte MessageCode = (byte)'K';
|
|
|
|
/// Associated diverter and plotter
|
|
public static Diverter Diverter;
|
|
public static bool ToTank;
|
|
public static Statistics Plotter;
|
|
public static int DiverterAssociationValidUntil;
|
|
|
|
/// Diverter transition data
|
|
public byte[] Samples;
|
|
public int Resolution_ms;
|
|
public int TransitionTime_ms;
|
|
|
|
const int SamplesCount = 247;
|
|
|
|
DivTransitionData()
|
|
{
|
|
Samples = new byte[SamplesCount];
|
|
Resolution_ms = Const.DivTimeResolution;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns tru when receive data fit the message frame
|
|
/// </summary>
|
|
/// <param name="rcvdData">Received data</param>
|
|
/// <param name="cumulativeSums">Cumulative sums of received data bytes</param>
|
|
/// <param name="rcvdBytesCount">Received bytes count</param>
|
|
/// <param name="offset">Offset of the message</param>
|
|
/// <returns>true when frame fits data</returns>
|
|
public static bool FrameFitsData(byte[] rcvdData, int[] cumulativeSums, int rcvdBytesCount, int offset)
|
|
{
|
|
if (offset + MessageLen > rcvdBytesCount) return false;
|
|
|
|
int checksum = cumulativeSums[offset + MessageLen - 3] - cumulativeSums[offset];
|
|
|
|
return rcvdData[offset] == Const.STX &&
|
|
rcvdData[offset + 1] == 0x01 &&
|
|
rcvdData[offset + 2] == ((MessageLen - 5) & 0xFF) &&
|
|
rcvdData[offset + 3] == MessageCode &&
|
|
rcvdData[offset + MessageLen - 2] == (checksum & 0xFF) &&
|
|
rcvdData[offset + MessageLen - 1] == ((checksum >> 8) & 0xFF);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Proces received data
|
|
/// </summary>
|
|
/// <param name="rcvdData">Received data</param>
|
|
/// <param name="offset">Offset of the message</param>
|
|
public static DivTransitionData GetData(byte[] rcvdData, int offset)
|
|
{
|
|
log.DebugFormat("DivTransitionDataGetData() ... Diverter = {0}, DiverterAssociationValidUntil-StateMachine.Time = {1}s left",
|
|
(Diverter != null) ? Diverter.Name : "none", DiverterAssociationValidUntil - StateMachine.Time);
|
|
|
|
var data = new DivTransitionData();
|
|
for (int i = 0; i < SamplesCount; i++)
|
|
{
|
|
data.Samples[i] = rcvdData[offset + 6 + i];
|
|
}
|
|
|
|
if (Diverter != null && StateMachine.Time <= DiverterAssociationValidUntil)
|
|
{
|
|
data.TransitionTime_ms = Const.DivTimeResolution * CalculateDivTransitionTime(data.Samples, Diverter.ThresholdLo, Diverter.ThresholdHi);
|
|
log.InfoFormat("{0} transition time = {1} ms", Diverter.Name, data.TransitionTime_ms);
|
|
if (ToTank)
|
|
{
|
|
if (Diverter != null && Diverter.SwitchTimeStart != null) Diverter.SwitchTimeStart.Val = data.TransitionTime_ms / 1000.0f;
|
|
}
|
|
else
|
|
{
|
|
if (Diverter != null && Diverter.SwitchTimeEnd != null) Diverter.SwitchTimeEnd.Val = data.TransitionTime_ms / 1000.0f;
|
|
}
|
|
|
|
if (Plotter != null)
|
|
{
|
|
int rangeLo = Math.Min(Diverter.AdcValueToSink, Diverter.AdcValueToTank);
|
|
int rangeHi = Math.Max(Diverter.AdcValueToSink, Diverter.AdcValueToTank);
|
|
if (rangeLo != rangeHi)
|
|
{
|
|
float denominator = Convert.ToSingle(rangeHi - rangeLo);
|
|
for (int i = 0; i < SamplesCount; i++)
|
|
{
|
|
float y = Convert.ToSingle(data.Samples[i] - rangeLo) / denominator;
|
|
Plotter.Update(y);
|
|
}
|
|
}
|
|
Plotter.Stop();
|
|
}
|
|
}
|
|
|
|
return data;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Analyze diverter transition data and calculate transition time
|
|
/// </summary>
|
|
/// <param name="samples">Raw data samples</param>
|
|
/// <param name="thresholdLo">Threshod level Low</param>
|
|
/// <param name="thresholdHi">Threshold level High</param>
|
|
/// <returns>Transition time in sasmple periods</returns>
|
|
static int CalculateDivTransitionTime(byte[] samples, int thresholdLo, int thresholdHi)
|
|
{
|
|
bool startedRising = false;
|
|
bool startedFalling = false;
|
|
bool stopped = false;
|
|
|
|
int transitionStartIdx = 0;
|
|
int transitionEndIdx = 0;
|
|
|
|
int level = 4*samples[0];
|
|
for (int i = 1; i < SamplesCount; i++)
|
|
{
|
|
if (!startedRising && !startedFalling)
|
|
{
|
|
if (level <= thresholdLo && 4*samples[i] > thresholdLo)
|
|
{
|
|
transitionStartIdx = i;
|
|
startedRising = true;
|
|
}
|
|
else if (level >= thresholdHi && 4*samples[i] < thresholdHi)
|
|
{
|
|
transitionStartIdx = i;
|
|
startedFalling = true;
|
|
}
|
|
}
|
|
else if (startedRising && !stopped && level < thresholdHi && 4*samples[i] >= thresholdHi)
|
|
{
|
|
transitionEndIdx = i;
|
|
stopped = true;
|
|
break;
|
|
}
|
|
else if (startedFalling && !stopped && level > thresholdLo && 4*samples[i] <= thresholdLo)
|
|
{
|
|
transitionEndIdx = i;
|
|
stopped = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
log.DebugFormat("CalculateDivTransitionTime() ... thresholdLo={0} thresholdHi={1} startIx={2} endIx={3} time = {4} ms",
|
|
thresholdLo, thresholdHi, transitionStartIdx, transitionEndIdx, 2 * (transitionEndIdx - transitionStartIdx));
|
|
|
|
return transitionEndIdx - transitionStartIdx;
|
|
}
|
|
}
|
|
}
|