using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
using System.Threading;
using Uestc.Auto6.Dso.ComModel;
using Uestc.Auto6.Dso.Hardware.Calibration.Data.Base;
using Uestc.Auto6.Dso.MathExt;
using System.Diagnostics.CodeAnalysis;
namespace Uestc.Auto6.Dso.Hardware.Driver
{
///
/// 模拟通道波形采集
///
public abstract class AbstractAcquirer_AnalogChannel : AbstractAcquirer
{
internal Abstract_LongStorage? LongStorage
{
get;
init;
}
///
/// 正在采集的采集参数
///
internal readonly AcquireAttribute AcquingParameters = new AcquireAttribute();
///
/// 已经采集的数据的采集参数。在读回数据后赋值
///
internal readonly AcquireAttribute AcquedParameters = new AcquireAttribute();
Dictionary> EmptyAcqBdCoefTablesSendDefine = new Dictionary>();
///
/// 获取采集板各种系数表的发送配置。只有DBI项目存在!!!
///
internal virtual Dictionary> AcqBdCoefTablesSendDefine
{
get => EmptyAcqBdCoefTablesSendDefine;
}
internal virtual Dictionary? ChannelPerScaleAmpFreqCoefficientsDefine
{
get => ourChannelPerScaleAmpFreqCoefficientsDefine;
}
private readonly Dictionary? ourChannelPerScaleAmpFreqCoefficientsDefine = new()
{
["C1_1"] = new AmpCoefficientFileInfo() { FileName = $@".\AfcCaliDataFiles\Afc_C1_1mV.txt" },
["C1_2"] = new AmpCoefficientFileInfo() { FileName = $@".\AfcCaliDataFiles\Afc_C1_2mV.txt" },
["C1_5"] = new AmpCoefficientFileInfo() { FileName = $@".\AfcCaliDataFiles\Afc_C1_5mV.txt" },
["C1_10"] = new AmpCoefficientFileInfo() { FileName = $@".\AfcCaliDataFiles\Afc_C1_10mV.txt" },
["C1_20"] = new AmpCoefficientFileInfo() { FileName = $@".\AfcCaliDataFiles\Afc_C1_20mV.txt" },
["C1_50"] = new AmpCoefficientFileInfo() { FileName = $@".\AfcCaliDataFiles\Afc_C1_50mV.txt" },
["C1_100"] = new AmpCoefficientFileInfo() { FileName = $@".\AfcCaliDataFiles\Afc_C1_100mV.txt" },
["C1_200"] = new AmpCoefficientFileInfo() { FileName = $@".\AfcCaliDataFiles\Afc_C1_200mV.txt" },
["C1_500"] = new AmpCoefficientFileInfo() { FileName = $@".\AfcCaliDataFiles\Afc_C1_500mV.txt" },
["C1_1000"] = new AmpCoefficientFileInfo() { FileName = $@".\AfcCaliDataFiles\Afc_C1_1000mV.txt" },
["C2_1"] = new AmpCoefficientFileInfo() { FileName = $@".\AfcCaliDataFiles\Afc_C2_1mV.txt" },
["C2_2"] = new AmpCoefficientFileInfo() { FileName = $@".\AfcCaliDataFiles\Afc_C2_2mV.txt" },
["C2_5"] = new AmpCoefficientFileInfo() { FileName = $@".\AfcCaliDataFiles\Afc_C2_5mV.txt" },
["C2_10"] = new AmpCoefficientFileInfo() { FileName = $@".\AfcCaliDataFiles\Afc_C2_10mV.txt" },
["C2_20"] = new AmpCoefficientFileInfo() { FileName = $@".\AfcCaliDataFiles\Afc_C2_20mV.txt" },
["C2_50"] = new AmpCoefficientFileInfo() { FileName = $@".\AfcCaliDataFiles\Afc_C2_50mV.txt" },
["C2_100"] = new AmpCoefficientFileInfo() { FileName = $@".\AfcCaliDataFiles\Afc_C2_100mV.txt" },
["C2_200"] = new AmpCoefficientFileInfo() { FileName = $@".\AfcCaliDataFiles\Afc_C2_200mV.txt" },
["C2_500"] = new AmpCoefficientFileInfo() { FileName = $@".\AfcCaliDataFiles\Afc_C2_500mV.txt" },
["C2_1000"] = new AmpCoefficientFileInfo() { FileName = $@".\AfcCaliDataFiles\Afc_C2_1000mV.txt" },
["C3_1"] = new AmpCoefficientFileInfo() { FileName = $@".\AfcCaliDataFiles\Afc_C3_1mV.txt" },
["C3_2"] = new AmpCoefficientFileInfo() { FileName = $@".\AfcCaliDataFiles\Afc_C3_2mV.txt" },
["C3_5"] = new AmpCoefficientFileInfo() { FileName = $@".\AfcCaliDataFiles\Afc_C3_5mV.txt" },
["C3_10"] = new AmpCoefficientFileInfo() { FileName = $@".\AfcCaliDataFiles\Afc_C3_10mV.txt" },
["C3_20"] = new AmpCoefficientFileInfo() { FileName = $@".\AfcCaliDataFiles\Afc_C3_20mV.txt" },
["C3_50"] = new AmpCoefficientFileInfo() { FileName = $@".\AfcCaliDataFiles\Afc_C3_50mV.txt" },
["C3_100"] = new AmpCoefficientFileInfo() { FileName = $@".\AfcCaliDataFiles\Afc_C3_100mV.txt" },
["C3_200"] = new AmpCoefficientFileInfo() { FileName = $@".\AfcCaliDataFiles\Afc_C3_200mV.txt" },
["C3_500"] = new AmpCoefficientFileInfo() { FileName = $@".\AfcCaliDataFiles\Afc_C3_500mV.txt" },
["C3_1000"] = new AmpCoefficientFileInfo() { FileName = $@".\AfcCaliDataFiles\Afc_C3_1000mV.txt" },
["C4_1"] = new AmpCoefficientFileInfo() { FileName = $@".\AfcCaliDataFiles\Afc_C4_1mV.txt" },
["C4_2"] = new AmpCoefficientFileInfo() { FileName = $@".\AfcCaliDataFiles\Afc_C4_2mV.txt" },
["C4_5"] = new AmpCoefficientFileInfo() { FileName = $@".\AfcCaliDataFiles\Afc_C4_5mV.txt" },
["C4_10"] = new AmpCoefficientFileInfo() { FileName = $@".\AfcCaliDataFiles\Afc_C4_10mV.txt" },
["C4_20"] = new AmpCoefficientFileInfo() { FileName = $@".\AfcCaliDataFiles\Afc_C4_20mV.txt" },
["C4_50"] = new AmpCoefficientFileInfo() { FileName = $@".\AfcCaliDataFiles\Afc_C4_50mV.txt" },
["C4_100"] = new AmpCoefficientFileInfo() { FileName = $@".\AfcCaliDataFiles\Afc_C4_100mV.txt" },
["C4_200"] = new AmpCoefficientFileInfo() { FileName = $@".\AfcCaliDataFiles\Afc_C4_200mV.txt" },
["C4_500"] = new AmpCoefficientFileInfo() { FileName = $@".\AfcCaliDataFiles\Afc_C4_500mV.txt" },
["C4_1000"] = new AmpCoefficientFileInfo() { FileName = $@".\AfcCaliDataFiles\Afc_C4_1000mV.txt" },
};
internal virtual List>? FirstInitChannelBdAdcInputDefines => null;
#region 触发深度等
internal virtual void DiscardDotAtTriggerTypeIsSerialMode()
{
if ((!Hd.CurrDebugVarints.bEnable_DigitTrigger) || Hd.CurrDebugVarints.bEnable_AdcDataDebugMode)
return;
if (Hd.CurrHdMessage!.Trigger!.TrigType != TriggerType.Serial)
return;
UInt32 trigSource = Hd.currProduct.Ctrl_Trigger!.CurrentTrigSource();
if (trigSource >= ChannelIdExt.AnaChnlNum)
return;
ChannelBdAdcInputDefine channelBdAdcInputDefine = GetChannelAcqBdAdcInputCorresponding((int)trigSource) ?? new ChannelBdAdcInputDefine() { BdNo = AcqBdNo.B3 };
UInt32 skipcount = (UInt32)(Hd.currProduct!.AcqBd!.ReadReg(AcqBdReg.R.Decoder_TimeDelaycntlock, channelBdAdcInputDefine.BdNo));
UInt32 skipcount_bound = (UInt32)(Hd.currProduct?.Acquirer_AnalogChannel?.AcquingParameters.HardwareExtractNum) - 1;
if (skipcount < skipcount_bound)
{
skipcount = skipcount +(UInt32) (Hd.currProduct?.Acquirer_AnalogChannel?.AcquingParameters.HardwareExtractNum);
}
SerialProtocolType protocolType = Hd.CurrHdMessage!.Trigger!.TrigDecoder!.ProtocolType;
if ((Hd.CurrHdMessage!.Trigger!.TrigDecoder.ProtocolOptions is HdMessage.ProtocolUSBOptions usb && usb.SignalRate == ProtocolUSB.SignalRate.HighRate ) || protocolType == SerialProtocolType.PCIe || protocolType == SerialProtocolType.SATA || Hd.CurrHdMessage!.Timebase!.TmbScaleIndex <= (int)AnaChnlTimebaseIndex.Lv100n)
skipcount = 0;
long mergeRoadCount = 40;
if (Hd.currProduct.ProductType == ProductType.B21_DBI16G || Hd.currProduct.ProductType == ProductType.B21_DBI20G || Hd.currProduct.ProductType == ProductType.B21_MD8G || Hd.currProduct.ProductType == ProductType.B21_HB8G)
mergeRoadCount = 80;
skipcount = (UInt32)(mergeRoadCount * skipcount / ((long)(Hd.currProduct?.Acquirer_AnalogChannel?.AcquingParameters.HardwareExtractNum ?? 1U)));
if (skipcount > 0 && (skipcount<500)) //500????????
{
for (int displayChIndex = 0; displayChIndex < ChannelIdExt.AnaChnlNum; displayChIndex++)
AcqedDataPool.AnalogChData.AllChannelData[displayChIndex].RemoveRange(0, (int)skipcount);
}
}
internal virtual UInt32 DefaultTrigSensitivity
{
get => 100;
}
internal virtual Int32 Trig_LS_TrigOffset
{
get
{
return 8 * 15;
}
}
internal virtual Int32 Trig_LS_DiscardNumMax
{
get
{
return 4096;
}
}
internal virtual ChannelBdAdcInputDefine? GetChannelAcqBdAdcInputCorresponding(int channelIndex) => null;
internal const int Trig_XDepthFixedAddDots = 400;
internal virtual TrigSourceParams GetTrigSourceParams(UInt32 trigChannelFromSoft)
{
UInt32 AcqBd_TrigCtrl_1st_SourceWhichAdcStartWith0 = 0;
UInt32 ProcBd_TrigCtrl_1st_SourceWhichAcqBdStartWith0 = 0;
UInt32 ProcBd_TrigCtrl_2nd_SourceWhichChannelStartWith0 = 0;
//1.判断触发信号来自于采集板哪个ADC,所有采集板配置相同,所有被选中通道的触发信号都送到处理板做二次选择
//相当于对应一个采集板上的哪个ADC。以触发的物理通道接入的那个ADC为准。ADC1:发0,ADC2:发1,两片:发0
if (trigChannelFromSoft < ChannelIdExt.AnaChnlNum)
{
if (Hd.currProduct!.Acquirer_AnalogChannel!.ChannelBdAdcInputDefines != null)
AcqBd_TrigCtrl_1st_SourceWhichAdcStartWith0 = (UInt32)Hd.currProduct!.Acquirer_AnalogChannel!.ChannelBdAdcInputDefines![0][(int)trigChannelFromSoft][0].AdcIndex;
}
//2.一级触发源:表示来自于那个采集板的信号。用0,1,2,表示。
if (trigChannelFromSoft < ChannelIdExt.AnaChnlNum)
{
uint acqBdIndex = 0;
if (Hd.currProduct!.Acquirer_AnalogChannel!.ChannelBdAdcInputDefines != null)
{
AcqBdNo acqBd = Hd.currProduct!.Acquirer_AnalogChannel!.ChannelBdAdcInputDefines![0][(int)trigChannelFromSoft][0].BdNo;
for (AcqBdNo acqBdNo = AcqBdNo.B1; acqBdNo <= AcqBdNo.B8; acqBdNo++)
{
if (Hd.currProduct?.AcqBd?.ExistsDefines?[(int)acqBdNo] ?? false)
{
if (acqBd == acqBdNo)
break;
acqBdIndex++;
}
}
}
ProcBd_TrigCtrl_1st_SourceWhichAcqBdStartWith0 = acqBdIndex;
}
//二级触发,表示对应的物理通道,与DMA中的数据路数一致
if (trigChannelFromSoft < ChannelIdExt.AnaChnlNum)
ProcBd_TrigCtrl_2nd_SourceWhichChannelStartWith0 = trigChannelFromSoft;
else
ProcBd_TrigCtrl_2nd_SourceWhichChannelStartWith0 = (uint)(trigChannelFromSoft % ChannelIdExt.AnaChnlNum);//乱整
return new TrigSourceParams()
{
AcqBd_TrigCtrl_1st_SourceWhichAdcStartWith0 = AcqBd_TrigCtrl_1st_SourceWhichAdcStartWith0,
ProcBd_TrigCtrl_1st_SourceWhichAcqBdStartWith0 = ProcBd_TrigCtrl_1st_SourceWhichAcqBdStartWith0,
ProcBd_TrigCtrl_2nd_SourceWhichChannelStartWith0 = ProcBd_TrigCtrl_2nd_SourceWhichChannelStartWith0
};
}
private Boolean IsInterpolation()
{
return Hd.currProduct?.Acquirer_AnalogChannel?.AcquingParameters.InterpolationNum > 1 ? true : false;
}
internal virtual Int64 GetTrigXDepth()
{
double tmbScale = Hd.CurrHdMessage?.Timebase?.TmbScale ?? 1.0;
double tmbPosition = Hd.CurrHdMessage?.Timebase?.TmbPosition ?? 0;
double perDataByfs_AtStorage = (Hd.currProduct?.Acquirer_AnalogChannel?.AcquingParameters.PerDataByfs_AtStorage ?? 50_000_000); //20G sample,50_000_000
Int64 depth = (Int64)((tmbScale * Constants.VIS_XDIVS_NUM / 2 - tmbPosition) * 1_000_000_000 / perDataByfs_AtStorage);
if (!Hd.AnalogChannel?.IsNeedPostProcessByMatlab ?? false)
return depth;
else
return depth + Trig_XDepthFixedAddDots;
}
//point 1
///
/// 应该这样计算
///
///
///
///
internal virtual UInt32 GetAcqBdTrigDiscardColumnNums(Int64 xdepth, UInt32 trigSource)
{
if (xdepth < 0)
return 0;
double mergeRoadCount = 40d;
UInt64 discard_tmp = (UInt64)(xdepth % mergeRoadCount); ;
if (IsInterpolation())
{
AnaChnlTimebaseIndex TmbScaleIndex = (AnaChnlTimebaseIndex)(Hd.CurrHdMessage?.Timebase?.TmbScaleIndex ?? (int)AnaChnlTimebaseIndex.Lv10n);//20220218
if (discard_tmp == 0)
return (uint)(discard_tmp + mergeRoadCount * (ulong)Hd.currProduct.Ctrl_Trigger!.InterpolationLevelDiscardNumTable![TmbScaleIndex] - 2 + 20);
else
return (uint)((mergeRoadCount - discard_tmp) * (ulong)Hd.currProduct.Ctrl_Trigger!.InterpolationLevelDiscardNumTable![TmbScaleIndex] + mergeRoadCount - 2 + 20);
}
else
{
if (discard_tmp == 0)
return (uint)(discard_tmp - 2 + 20);
else
return (uint)(mergeRoadCount - discard_tmp - 2 + 20);
}
}
//point 2
internal virtual UInt32 ourGetSigProDiscardNum() //计算总的数字信号处理丢点数
{
int LengthOfInterpFilter_1st = Hd.currProduct!.HardwareConfig!.LocalCoefficientsTableMeanings[Calibration.Data.Base.CoefficientsTableType.Coefficients1].LengthOfPartA; //一级插值滤波器阶数
int LengthOfInterpFilter_2nd = Hd.currProduct!.HardwareConfig!.LocalCoefficientsTableMeanings[Calibration.Data.Base.CoefficientsTableType.Coefficients1].LengthOfPartB; //二级插值滤波器阶数
//int LengthOfTiadc = Hd.currProduct!.HardwareConfig!.LocalCoefficientsTableMeanings[Calibration.Data.Base.CoefficientsTableType.Coefficients2].Length; //TIADC滤波器阶数
UInt32 TiADCDiscard = 256; //进入TIADC模块会丢掉256个点
int LengthOfAfc = 0;
if (Hd.currProduct!.HardwareConfig!.LocalCoefficientsTableMeanings.ContainsKey(Calibration.Data.Base.CoefficientsTableType.Coefficients3))
LengthOfAfc = Hd.currProduct!.HardwareConfig!.LocalCoefficientsTableMeanings[Calibration.Data.Base.CoefficientsTableType.Coefficients3].Length; //AFC滤波器阶数
int LengthOfPfc = 0;
if (Hd.currProduct!.HardwareConfig!.LocalCoefficientsTableMeanings.ContainsKey(Calibration.Data.Base.CoefficientsTableType.Coefficients4))
LengthOfPfc = Hd.currProduct!.HardwareConfig!.LocalCoefficientsTableMeanings[Calibration.Data.Base.CoefficientsTableType.Coefficients4].Length; //PFC滤波器阶数
UInt32 InterpDiscard = ourGetInterpDiscardNum(LengthOfInterpFilter_1st, LengthOfInterpFilter_2nd);
//UInt32 Discard = (uint)(InterpDiscard + LengthOfTiadc / 2 + LengthOfAfc / 2 + LengthOfPfc / 2);
UInt32 Discard = (uint)(InterpDiscard + TiADCDiscard + LengthOfAfc / 2 + 2 * LengthOfPfc / 5);
return Discard;
}
internal virtual UInt32 ourGetInterpDiscardNum(int LengthOfInterpFilter_1st, int LengthOfInterpFilter_2nd) //计算总的插值滤波器丢点数
{
AnaChnlTimebaseIndex currAnaChnlTimebaseIndex = (AnaChnlTimebaseIndex)(Hd.CurrHdMessage?.Timebase?.TmbScaleIndex ?? (int)AnaChnlTimebaseIndex.Lv100u);
UInt32 ExtractNum = (UInt32)(Hd.currProduct?.Acquirer_AnalogChannel?.AcquingParameters.HardwareExtractNum ?? 1U);
UInt32 InterpNum = (UInt32)(Hd.currProduct?.Acquirer_AnalogChannel?.AcquingParameters.InterpolationNum ?? 1U);
UInt32 Max_1stInterpRatio = 10; //一级最大插值倍率
UInt32 DiscardBforeInterp = 2; //进入插值模块之前丢掉两个点
UInt32 InterpDiscard = 0;
if (InterpNum > Max_1stInterpRatio)
InterpDiscard = (UInt32)(DiscardBforeInterp * InterpNum + LengthOfInterpFilter_1st / ExtractNum / 2);
else
InterpDiscard = (UInt32)((DiscardBforeInterp * InterpNum + LengthOfInterpFilter_1st / ExtractNum / 2) * InterpNum + LengthOfInterpFilter_2nd / ExtractNum / 2);
return InterpDiscard;
}
internal virtual UInt64 GetProcBd_LA_TrigCtrl_1st_PreDepth(Int64 xdepth, uint trigSource)
{
return GetProcBdTrigCtrl_1st_PreDepth(xdepth, trigSource);
}
internal virtual UInt64 GetProcBdTrigCtrl_1st_PreDepth(Int64 xdepth, uint trigSource)
{
//计算触发信号板间通信偏移量
uint trigChannel = (uint)trigSource;
UInt32 SigProDiscardNum = ourGetSigProDiscardNum();
AnaChnlTimebaseIndex curTimeBase = (AnaChnlTimebaseIndex)(Hd.CurrHdMessage?.Timebase?.TmbScaleIndex ?? (Int32)AnaChnlTimebaseIndex.Lv5n);
//if (!adjustnumTableNew.ContainsKey(curTimeBase))
// throw new Exception("adjustnumTableNew not contain curTimeBase:" + curTimeBase.ToString());
UInt32 adjust_num = 0;// adjustnumTableNew[curTimeBase];
UInt32 xdpeth_fix;
double mergeRoadCount;//并行路数
// ulong hardwareExtractNum = Hd.currProduct?.Acquirer_AnalogChannel?.AcquingParameters.HardwareExtractNum ?? 1; 硬件抽取数
if (Hd.CurrHdMessage!.Analog![trigSource].InputSource == AnaChnlIpnutSource.BNC)
{
mergeRoadCount = 40d;
}
else
{
mergeRoadCount = 80d;
}
bool condition = false;
if (condition == true)
{
xdpeth_fix = (UInt32)xdepth + SigProDiscardNum + adjust_num;
}
else
{
xdpeth_fix = (UInt32)xdepth + adjust_num;
}
UInt32 PreDepth = (UInt32)Math.Floor(xdpeth_fix / mergeRoadCount) + (UInt32)SysAutoCalibration.Default.Trig_AcqProcBdLooptimBySysClockCount((int)trigChannel);
return PreDepth;
}
//point 3
internal virtual UInt64 GetProcBdTrigCtrl_1st_PosDepth(Int64 xdepth, UInt32 trigSource)
{
if (xdepth > 0)
return 0;
ulong hardwareExtractNum = Hd.currProduct?.Acquirer_AnalogChannel?.AcquingParameters.HardwareExtractNum ?? 1;
double mergeRoadCount = 40d;
UInt64 result = (UInt64)Math.Floor(-xdepth / mergeRoadCount) * hardwareExtractNum;
return result;
}
//point 4
internal virtual UInt32 GetProcBdTrigCtrl_2nd_PreDepth(Int64 xdepth, UInt32 trigSource)
{
UInt32 result = 0;
if (xdepth > 0)
result = (uint)(xdepth);
return result;
}
//point 5
internal virtual UInt32 GetProcBdTrigCtrl_2nd_SearchRange(Int64 xdepth, UInt32 trigSource)
{
UInt32 result = 0;
if (xdepth < 0)
result = 0;
else if (IsInterpolation())
result = (uint)(16 * 1024 - (1000 - xdepth) - 1000);
else
result = 5000;
return result;
}
internal virtual (UInt32 Up, UInt32 Dn, UInt32 Edge) GetDigitTrigCompVolt()
{
UInt32 compVolt;
int trigSource = (int)Hd.currProduct!.Ctrl_Trigger!.CurrentTrigSource();
int trigSourceYPos = AbstractController_Trigger.AdcCenterValue;
bool isPositive = true;
if (trigSource < ChannelIdExt.AnaChnlNum)
{
HdMessage.AnalogOptions analogParameters = Hd.CurrHdMessage!.Analog![trigSource];
trigSourceYPos = (int)(Constants.SAMPS_PER_YDIV * analogParameters.Position / analogParameters.Scale + AbstractController_Trigger.AdcCenterValue);
}
else
return (0, 0, (UInt32)(((Hd.CurrHdMessage!.Trigger!.TrigType == TriggerType.Edge && ChannelIdExt.IsDigital((ChannelId)trigSource) ? 1 : 0) << 1) | ((Hd.CurrHdMessage!.Trigger!.Edge!.Slope == EdgeSlope.Rise ? 1 : 0))));//LA
switch (Hd.CurrHdMessage?.Trigger?.TrigType)
{
case TriggerType.Edge:
compVolt = (UInt32)((Hd.CurrHdMessage!.Trigger!.Edge!.PosIndex) / Constants.IDX_PER_YDIV * AbstractController_Trigger.PerYDivAdcSamples + trigSourceYPos);
isPositive = Hd.CurrHdMessage!.Trigger!.Edge!.Slope == EdgeSlope.Rise;
break;
case TriggerType.PulseWidth:
compVolt = (UInt32)((Hd.CurrHdMessage!.Trigger!.Pulse!.PosIndex) / Constants.IDX_PER_YDIV * AbstractController_Trigger.PerYDivAdcSamples + trigSourceYPos);//正脉宽以下降沿为判断基准,反之亦然
isPositive = Hd.CurrHdMessage!.Trigger!.Pulse!.Polarity == PulsePolarity.Positive;
break;
case TriggerType.Runt:
compVolt = (UInt32)((Hd.CurrHdMessage!.Trigger!.Runt!.LowerPosIndex) / Constants.IDX_PER_YDIV * AbstractController_Trigger.PerYDivAdcSamples + trigSourceYPos);//同上
isPositive = Hd.CurrHdMessage!.Trigger!.Runt!.Polarity == PulsePolarity.Positive;
break;
case TriggerType.Transition:
compVolt = (UInt32)((Hd.CurrHdMessage!.Trigger!.Transition!.LowerPosIndex) / Constants.IDX_PER_YDIV * AbstractController_Trigger.PerYDivAdcSamples + trigSourceYPos);
isPositive = Hd.CurrHdMessage!.Trigger!.Transition!.Slope == EdgeSlope.Rise;
break;
case TriggerType.TimeOut:
compVolt = (UInt32)((Hd.CurrHdMessage!.Trigger!.TimeOut!.PosIndex) / Constants.IDX_PER_YDIV * AbstractController_Trigger.PerYDivAdcSamples + trigSourceYPos);
isPositive = Hd.CurrHdMessage!.Trigger!.TimeOut!.Polarity == LevelPolarity.Positive;
break;
case TriggerType.Glitch:
compVolt = (UInt32)((Hd.CurrHdMessage!.Trigger!.Glitch!.PosIndex) / Constants.IDX_PER_YDIV * AbstractController_Trigger.PerYDivAdcSamples + trigSourceYPos);
isPositive = Hd.CurrHdMessage!.Trigger!.Glitch!.Polarity == PulsePolarity.Positive;
break;
case TriggerType.SetupHold:
compVolt = (UInt32)((Hd.CurrHdMessage!.Trigger!.SetupHold!.ClkPosition.Value) * 10 / Constants.IDX_PER_YDIV * AbstractController_Trigger.PerYDivAdcSamples + trigSourceYPos);
break;
case TriggerType.Pattern:
//10是换算
compVolt = (UInt32)((Hd.CurrHdMessage?.Trigger?.Pattern.Positions[trigSource].Value) * 10 / Constants.IDX_PER_YDIV * AbstractController_Trigger.PerYDivAdcSamples + trigSourceYPos);
isPositive = Hd.CurrHdMessage!.Trigger!.Pattern!.Positions[trigSource].Condition == PatLevelCondition.GreaterThan;
break;
case TriggerType.State:
compVolt = (UInt32)((Hd.CurrHdMessage?.Trigger?.State?.Positions[trigSource].Value) * 10 / Constants.IDX_PER_YDIV * AbstractController_Trigger.PerYDivAdcSamples + trigSourceYPos);
break;
case TriggerType.Interval:
compVolt = (UInt32)((Hd.CurrHdMessage!.Trigger!.Interval!.PosIndex) / Constants.IDX_PER_YDIV * AbstractController_Trigger.PerYDivAdcSamples + AbstractController_Trigger.AdcCenterValue);
isPositive = Hd.CurrHdMessage!.Trigger!.Interval!.Polarity == PulsePolarity.Positive;
break;
case TriggerType.Window:
compVolt = (UInt32)((Hd.CurrHdMessage!.Trigger!.Window!.LowerPosIndex) / Constants.IDX_PER_YDIV * AbstractController_Trigger.PerYDivAdcSamples + AbstractController_Trigger.AdcCenterValue);
isPositive = (Hd.CurrHdMessage?.Trigger?.Window?.Range ?? WindowRange.Inside) == WindowRange.Outside;
break;
default:
compVolt = (UInt32)((Hd.CurrHdMessage!.Trigger!.Edge!.PosIndex) / Constants.IDX_PER_YDIV * AbstractController_Trigger.PerYDivAdcSamples + trigSourceYPos);
isPositive = Hd.CurrHdMessage!.Trigger!.Edge!.Slope == EdgeSlope.Rise;
break;
}
uint currDefaultTrigSensitivity = DefaultTrigSensitivity;
if ((TriggerCoupling)(Hd.CurrHdMessage?.Trigger?.Edge?.Coupling ?? TriggerCoupling.DC) == TriggerCoupling.NR)
currDefaultTrigSensitivity /= 2;
switch (Hd.CurrHdMessage?.Trigger?.TrigType)
{
case TriggerType.PulseWidth:
case TriggerType.Runt:
case TriggerType.TimeOut:
case TriggerType.Glitch:
case TriggerType.Pattern:
case TriggerType.Window:
if (isPositive)
{
if ((compVolt - DefaultTrigSensitivity) < 0)
compVolt = DefaultTrigSensitivity;
return (Up: compVolt + DefaultTrigSensitivity, Dn: compVolt, 1);
}
else
{
if ((compVolt + DefaultTrigSensitivity) > 4095)
compVolt = 4095 - DefaultTrigSensitivity;
return (Up: compVolt, Dn: compVolt - DefaultTrigSensitivity, 0);
}
break;
default:
if (isPositive)
{
if ((compVolt - DefaultTrigSensitivity) < 0)
compVolt = DefaultTrigSensitivity;
return (Up: compVolt, Dn: compVolt - DefaultTrigSensitivity, 1);
}
else
{
if ((compVolt + DefaultTrigSensitivity) > 4095)
compVolt = 4095 - DefaultTrigSensitivity;
return (Up: compVolt + DefaultTrigSensitivity, Dn: compVolt, 0);
}
break;
}
}
internal virtual void Trig_SpecailConfig(Int64 xdepth, UInt32 trigSource)
{
if (Hd.CurrHdMessage?.Timebase?.TmbScaleIndex! > (int)AnaChnlTimebaseIndex.Lv5n)
{
HdIO.WriteReg(ProcBdReg.W.TrigCtrl_2nd_SerialTrigEnable, Hd.CurrDebugVarints.bEnable_DigitTrigger ? 9U : 0);
Hd.currProduct?.AcqBd?.WriteToAllFpga(AcqBdReg.W.TrigCtrl_Location_TrigDiscardColumnEn, Hd.CurrDebugVarints.bEnable_DigitTrigger ? 1U : 0U);
}
else
{
HdIO.WriteReg(ProcBdReg.W.TrigCtrl_2nd_SerialTrigEnable, Hd.CurrDebugVarints.bEnable_DigitTrigger ? 9U : 0);
Hd.currProduct?.AcqBd?.WriteToAllFpga(AcqBdReg.W.TrigCtrl_Location_TrigDiscardColumnEn, Hd.CurrDebugVarints.bEnable_DigitTrigger ? 1U : 0U);
}
}
#endregion
protected virtual UInt64 MaxPerDataByps
{
get;
set;
} = 50;//20G 采样
protected const long uS2fs = 1_000_000_000;
internal record ExtractNumInterpolationNumPair(UInt64 ExtractNum, UInt32 InterpolationNum, UInt32 HardwareFifoLen, UInt32 SoftwareFifoLen);
#region LA 抽取插值表
internal virtual Dictionary LA_ExtractInterpolationNumTable => standardLA_ExtractInterpolationNumTable;
private static Dictionary standardLA_ExtractInterpolationNumTable = new()
{
//小于80,必须能够整除,大于80,10的倍数就可以
// ExtractNum,InterpolationNum,HardwareFifoLen,SoftwareFifoLen
[AnaChnlTimebaseIndex.Lv20p] = new ExtractNumInterpolationNumPair(1, 400, 800, 800),
[AnaChnlTimebaseIndex.Lv50p] = new ExtractNumInterpolationNumPair(1, 200, 1000, 1000),
[AnaChnlTimebaseIndex.Lv100p] = new ExtractNumInterpolationNumPair(1, 100, 1000, 1000),
[AnaChnlTimebaseIndex.Lv200p] = new ExtractNumInterpolationNumPair(1, 40, 800, 800),
[AnaChnlTimebaseIndex.Lv500p] = new ExtractNumInterpolationNumPair(1, 20, 1000, 1000),
[AnaChnlTimebaseIndex.Lv1n] = new ExtractNumInterpolationNumPair(1, 10, 1000, 1000),
[AnaChnlTimebaseIndex.Lv2n] = new ExtractNumInterpolationNumPair(1, 5, 1000, 1000), //50/I * L=scale *10
[AnaChnlTimebaseIndex.Lv5n] = new ExtractNumInterpolationNumPair(1, 2, 1000, 1000),//5ns时10G才开始需要插值,20G这里刚好不需要插值
[AnaChnlTimebaseIndex.Lv10n] = new ExtractNumInterpolationNumPair(1, 1, 1000, 1000),
[AnaChnlTimebaseIndex.Lv20n] = new ExtractNumInterpolationNumPair(1, 1, 2000, 2000),
[AnaChnlTimebaseIndex.Lv50n] = new ExtractNumInterpolationNumPair(1, 1, 5000, 5000),//以上采用20G,也可采用10G
[AnaChnlTimebaseIndex.Lv100n] = new ExtractNumInterpolationNumPair(1, 1, 10_000, 10_000),//以下必须采用10G
[AnaChnlTimebaseIndex.Lv200n] = new ExtractNumInterpolationNumPair(2, 1, 10_000, 10_000),
[AnaChnlTimebaseIndex.Lv500n] = new ExtractNumInterpolationNumPair(5, 1, 10_000, 10_000),
[AnaChnlTimebaseIndex.Lv1u] = new ExtractNumInterpolationNumPair(10, 1, 10_000, 10_000),
[AnaChnlTimebaseIndex.Lv2u] = new ExtractNumInterpolationNumPair(20, 1, 10_000, 10_000),
[AnaChnlTimebaseIndex.Lv5u] = new ExtractNumInterpolationNumPair(50, 1, 10_000, 10_000),
[AnaChnlTimebaseIndex.Lv10u] = new ExtractNumInterpolationNumPair(100, 1, 10_000, 10_000),
[AnaChnlTimebaseIndex.Lv20u] = new ExtractNumInterpolationNumPair(200, 1, 10_000, 10_000),
[AnaChnlTimebaseIndex.Lv50u] = new ExtractNumInterpolationNumPair(500, 1, 10_000, 10_000),
[AnaChnlTimebaseIndex.Lv100u] = new ExtractNumInterpolationNumPair(1_000, 1, 10_000, 10_000),
[AnaChnlTimebaseIndex.Lv200u] = new ExtractNumInterpolationNumPair(2_000, 1, 10_000, 10_000),
[AnaChnlTimebaseIndex.Lv500u] = new ExtractNumInterpolationNumPair(5_000, 1, 10_000, 10_000),
[AnaChnlTimebaseIndex.Lv1m] = new ExtractNumInterpolationNumPair(10_000, 1, 10_000, 10_000),
[AnaChnlTimebaseIndex.Lv2m] = new ExtractNumInterpolationNumPair(20_000, 1, 10_000, 10_000),
[AnaChnlTimebaseIndex.Lv5m] = new ExtractNumInterpolationNumPair(50_000, 1, 10_000, 10_000),
[AnaChnlTimebaseIndex.Lv10m] = new ExtractNumInterpolationNumPair(100_000, 1, 10_000, 10_000),
[AnaChnlTimebaseIndex.Lv20m] = new ExtractNumInterpolationNumPair(200_000, 1, 10_000, 10_000),
[AnaChnlTimebaseIndex.Lv50m] = new ExtractNumInterpolationNumPair(500_000, 1, 10_000, 10_000),
[AnaChnlTimebaseIndex.Lv100m] = new ExtractNumInterpolationNumPair(1_000_000, 1, 10_000, 10_000),
[AnaChnlTimebaseIndex.Lv200m] = new ExtractNumInterpolationNumPair(2_000_000, 1, 10_000, 10_000),
[AnaChnlTimebaseIndex.Lv500m] = new ExtractNumInterpolationNumPair(5_000_000, 1, 10_000, 10_000),
[AnaChnlTimebaseIndex.Lv1] = new ExtractNumInterpolationNumPair(10_000_000, 1, 10_000, 10_000),
[AnaChnlTimebaseIndex.Lv2] = new ExtractNumInterpolationNumPair(20_000_000, 1, 10_000, 10_000),
[AnaChnlTimebaseIndex.Lv5] = new ExtractNumInterpolationNumPair(50_000_000, 1, 10_000, 10_000),
};
#endregion
internal UInt32 DDR_TrigAddrTableStartAddr { get => 1000; }//与硬件协商
public virtual int ReadTriggerStatus()
{
return 0;
}
internal override void Init()
{
InitPhyAnalogChAmplitudeTemperaturesCompensationCoefficient();
LongStorage?.Init();
InitAmpCoefficientFile();
}
internal virtual void InitAmpCoefficientFile()
{
if (ChannelPerScaleAmpFreqCoefficientsDefine == null)
return;
foreach(var v in ChannelPerScaleAmpFreqCoefficientsDefine)
{
var info = v.Value;
int[]? dataArray = Misc.ReadCaliCoefDataFronmFile(info.FileName);
if (dataArray == null)
{
info.CRCCode = 0; info.bOk = false;
continue;
}
info.CRCCode = Misc.GenerateCRCCode(dataArray!);
info.bOk = true;
}
}
internal virtual HdCmd ResponseSpecialScpiCmd(string message)
{
return HdCmd.None;
}
protected virtual bool bOpenAverageModule
{
get
{
if (Hd.CurrDebugVarints.bEnable_ProcBd_Average)
{
if (AcquingParameters.HardwareExtractNum > 1)
return false;
if (Hd.CurrHdMessage!.Timebase!.AcqLength == AnaChnlStorageMode.Long)
return false;
if (Hd.CurrHdMessage!.Trigger!.Mode != TriggerMode.Auto)
return false;
if (Hd.CurrHdMessage!.Timebase!.AcqLength == AnaChnlStorageMode.Fast)
return false;
return true;
}
else
return false;
}
}
internal override void InitAcq()
{
Hd.currProduct?.AcqBd?.WriteToAllFpga(AcqBdReg.W.LSCtrl_StorageMode, AcquingParameters.bIsLongStorageMode ? 1 : 0U);
//Acquisition.SwitchDataPathMuxTo(DMAReadSourceMuxType.AnalogChanneData);
HdIO.WriteReg(ProcBdReg.W.Average_Enable, bOpenAverageModule ? 1U : 0);
if (!AcquingParameters.bIsLongStorageMode)
{
HdIO.WriteReg(PcieBdReg.W.DataPath_pcie_linkdemux_select, (UInt32)DMAReadSourceMuxType.AnalogChanneData);
HdIO.WriteReg(ProcBdReg.W.DataPath_pro_linkdemux_select, (UInt32)DMAReadSourceMuxType.AnalogChanneData);
HdIO.WriteReg(ProcBdReg.W.DataPath_pro_linkmux_select, (UInt32)DMAReadSourceMuxType.AnalogChanneData);
//Hd.currProduct?.AcqBd?.WriteToAllFpga(AcqBdReg.W.FifoCtrl_FullProgDepth, 1024);//采集板并行FIFO深度
Hd.currProduct?.AcqBd?.WriteToAllFpga(AcqBdReg.W.FifoCtrl_FullProgDepth, 500);//采集板并行FIFO深度
Hd.currProduct?.AcqBd?.WriteToAllFpga(AcqBdReg.W.LSCtrl_StorageMode, AcquingParameters.bIsLongStorageMode ? 1u : 0);
HdIO.WriteReg(PcieBdReg.W.DataPath_pcie_linkdemux_select, (UInt32)DMAReadSourceMuxType.AnalogChanneData);
#region 发送FIFO深度
//在DPX模式下,可能更改此参数,故需要重发
HdIO.WriteReg(ProcBdReg.W.DataPath_pro_linkdemux_select, (UInt32)DMAReadSourceMuxType.AnalogChanneData);
bool bEnableInterpolation = Hd.CurrDebugVarints.bEnable_AcqbdInterpolation;
if (bEnableInterpolation)
bEnableInterpolation = AcquingParameters.InterpolationNum > 1;
Hd.currProduct?.AcqBd?.WriteToAllFpga(AcqBdReg.W.Interpolate_Enable, bEnableInterpolation ? 1U : 0);
bool bFast = (Hd.CurrHdMessage?.Timebase?.AcqLength ?? AnaChnlStorageMode.Normal) == AnaChnlStorageMode.Fast;
if (bFast) return;
Hd.currProduct?.AcqBd?.WriteToAllFpga(AcqBdReg.W.DataPath_acq_linkmux_select, 0);
//Hd.currProduct?.AcqBd?.WriteToAllFpga(AcqBdReg.W.TrigCtrl_AcqSerialFIFODepth, 16000);//采集板串行FIFO深度 16000 -->25600 zy0830 --> 53248
HdIO.WriteReg(ProcBdReg.W.FifoCtrl_FullProgDepth, 12288);//12288 -->22528 --> 53248
HdIO.WriteReg(PcieBdReg.W.FifoCtrl_FullProgDepth, 12288);
HdIO.WriteReg(PcieBdReg.W.FifoCtrl_ReadFromFIFO_Num, 15000);//zy0830 15000-->25000--> 53248
#endregion
}
else
{
LongStorage?.InitAcq();
}
}
protected virtual void AnalogChannelDataSplit(int dotCount)
{
for (int curr_channelIndex = 0; curr_channelIndex < ChannelIdExt.AnaChnlNum; curr_channelIndex++)
{
for (int dotIndex = 0; dotIndex < dotCount; dotIndex++)//0
{
ushort data = curr_channelIndex switch
{
0 => (UInt16)((AcqedDataPool.AnalogChData.DMAData[8 * dotIndex]) | ((AcqedDataPool.AnalogChData.DMAData[8 * dotIndex + 1] & 0x0F) << 8)),
1 => (UInt16)(((AcqedDataPool.AnalogChData.DMAData[8 * dotIndex + 1] & 0xF0) >> 4 | AcqedDataPool.AnalogChData.DMAData[8 * dotIndex + 2] << 4)),
2 => (UInt16)((AcqedDataPool.AnalogChData.DMAData[8 * dotIndex + 3] | (AcqedDataPool.AnalogChData.DMAData[8 * dotIndex + 4] & 0x0F) << 8)),
3 => (UInt16)(((AcqedDataPool.AnalogChData.DMAData[8 * dotIndex + 4] & 0xF0) >> 4 | AcqedDataPool.AnalogChData.DMAData[8 * dotIndex + 5] << 4)),
_ => 0,
};
AcqedDataPool.AnalogChData.AllChannelData[curr_channelIndex].Add(data);
}
}
DiscardDotAtTriggerTypeIsSerialMode();
AbstractController_AnalogChannel.SoftwareBandwidthProcess();
}
internal override bool ReadAcqData()
{
bDataVaild = false;
bool bOk = false;
if (Hd.CurrHdMessage == null)
return bOk;
AcquingParameters.CloneTo(AcquedParameters);
Int32 scanExistDots = 0;
if (HdIO.CurrDriver == null || !HdIO.CurrDriver.bOpen || Hd.bPowerOff)
{
if (Hd.CurrHdMessage?.Timebase?.IsScan ?? false)
{
//模拟
Random random = new Random();
int a = random.Next(100, 1000);
AcqAnalogChannelSimulateWaveform();
for (int iChannelID = 0; iChannelID < ChannelIdExt.AnaChnlNum; iChannelID++)
AcqedDataPool.AnalogChData.AllChannelData[iChannelID].RemoveRange(a, AcqedDataPool.AnalogChData.AllChannelData[iChannelID].Count - a);
return true;
}
else
return AcqAnalogChannelSimulateWaveform();
}
if (!AcquingParameters.bIsLongStorageMode)
{
if (Hd.CurrHdMessage!.Timebase!.IsScan)
{
scanExistDots = (Int32)HdIO.ReadReg(ProcBdReg.R.Scan_DatacountUploading);
HdIO.WriteReg(ProcBdReg.W.Scan_DatacountPassback, (UInt32)(scanExistDots | 0x0 << 14));
HdIO.WriteReg(ProcBdReg.W.Scan_DatacountPassback, (UInt32)(scanExistDots | 0x1 << 14));
HdIO.CheckRegisterValue((UInt32)PcieBdReg.R.FifoCtrl_FullFlag, 0x01, 1, 4);
bOk = HdIO.DMARead(DMAReadDataTypes.AnalogChannelFifo, (uint)AcquingParameters.AnaWaveDMALength, ref AcqedDataPool.AnalogChData.DMAData);
HdIO.WriteReg(ProcBdReg.W.Scan_DatacountPassback, (UInt32)(scanExistDots | 0x0 << 14));
}
else
{
bool bFast = (Hd.CurrHdMessage?.Timebase?.AcqLength ?? AnaChnlStorageMode.Normal) == AnaChnlStorageMode.Fast;
if (!bFast)
{
HdIO.WriteReg((uint)PcieBdReg.W.ReadFromAcqOrDpo, 0);
HdIO.WriteReg((uint)PcieBdReg.W.ReadTotalBytes, (uint)AcquingParameters.AnaWaveDMALength);
bOk = HdIO.DMARead(0, (uint)AcquingParameters.AnaWaveDMALength, ref AcqedDataPool.AnalogChData.DMAData);
}
else
{
Int64 currPerXDivByps = (Int64)((Hd.CurrHdMessage?.Timebase?.TmbScale ?? 1) * 1_000_000);//TmbScale 以us为单位,*1_000_000,us==>ps
UInt32 length = 0;
if (ChannelIdExt.AnaChnlNum <= 4)
length = (UInt32)(((currPerXDivByps * Constants.VIS_XDIVS_NUM) * 8 * 1000 + AcquingParameters.PerDataByfs_AtStorage - 1) / ((long)AcquingParameters.PerDataByfs_AtStorage));
else
length = (UInt32)(((currPerXDivByps * Constants.VIS_XDIVS_NUM) * 16 * 1000 + AcquingParameters.PerDataByfs_AtStorage - 1) / ((long)AcquingParameters.PerDataByfs_AtStorage));
// UInt32 length = 8192;//须归一化256byte整除
length = ((length / 1024 + 1) * 1024);
HdIO.WriteReg(PcieBdReg.W.DataPath_pcie_linkdemux_select, (UInt32)DMAReadSourceMuxType.AnalogChanneData);
HdIO.WriteReg((uint)PcieBdReg.W.ReadFromAcqOrDpo, 0);
HdIO.WriteReg((uint)PcieBdReg.W.ReadTotalBytes, length);
bOk = HdIO.DMARead(0, length, ref AcqedDataPool.AnalogChData.DMAData);
}
}
}
else
{
LongStorage?.SwitchPingpong();
bOk = LongStorage?.ReadTrigPosTable() ?? false;
bOk = LongStorage?.ReadAcqedData() ?? false;
return bOk;
}
bDataVaild = bOk;
if (!bOk)
return bOk;
#region 数据拆分 本拆分方法是按通道交替组织数据的方式进行拆分的。不同的硬件的数据组织方式,需要修改此拆分方法。
Monitor.Enter(AcqedDataPool.UpdateDataLock);
int channelCount = ChannelIdExt.AnaChnlNum;
if (Hd.currProduct.ProductType == ProductType.B21_DBI16G)
channelCount = 4;
while (AcqedDataPool.AnalogChData.AllChannelData.Count < channelCount)
AcqedDataPool.AnalogChData.AllChannelData.Add(new List());
for (int iChannelID = 0; iChannelID < channelCount; iChannelID++)
AcqedDataPool.AnalogChData.AllChannelData[iChannelID].Clear();
int channelDotCount = 0;
if (Hd.CurrHdMessage?.Timebase?.IsScan ?? false)
{
channelDotCount = scanExistDots > Constants.CHNL_DATA_NUM ? Constants.CHNL_DATA_NUM : scanExistDots;
}
else
channelDotCount = Constants.CHNL_DATA_NUM;
AnalogChannelDataSplit(channelDotCount);
Monitor.Exit(AcqedDataPool.UpdateDataLock);
#endregion
return bOk;
}
internal override void PostProcess()
{
if (!AcquingParameters.bIsLongStorageMode)
{
if (IsNeedPostProcessByMatlab)
{
#region 需要MATLAB处理
#endregion
}
}
else
{
//长存储时的处理
LongStorage?.PostProcess();
}
}
#region Core->U2调用函数
public virtual bool TryTakeWave(Int32 channelIndex, [NotNullWhen(true)] out List waveData, [NotNullWhen(true)] out WfmSampleInfo wfmSampleInfo)
{
waveData = new List();
wfmSampleInfo = new WfmSampleInfo();
wfmSampleInfo.SampleIntervalByus = AcquedParameters.PerDataByfs_AfterPostProcess * 1.0 / 1E9;//1_000:fs==>ps
if ((channelIndex < 0) || (channelIndex > ChannelIdExt.AnaChnlNum - 1))
return false;
if ((Hd.CurrHdMessage?.Timebase?.AcqLength ?? AnaChnlStorageMode.Normal) == AnaChnlStorageMode.Long)
{
Hd.bAcqedNewData = LongStorage?.TakeWave() ?? false;
if (Hd.bAcqedNewData)
wfmSampleInfo.SampleIntervalByus = AcquedParameters.PerDataByfs_AfterPostProcess * 1.0 / 1E9;//1_000:fs==>ps
}
if (AcqedDataPool.AnalogChData.AllChannelData.Count <= channelIndex)
return false;
Monitor.Enter(AcqedDataPool.UpdateDataLock);
waveData.AddRange(AcqedDataPool.AnalogChData.AllChannelData[channelIndex]);
Monitor.Exit(AcqedDataPool.UpdateDataLock);
return Hd.bAcqedNewData;
}
public virtual Double TakeSamplingRate()
{
return 1E15 / AcquingParameters.PerDataByfs_AtStorage;
}
public virtual bool TryTakeDdrSourceWave(Int32 channel, double startTimeBySecond, double totalTime, [NotNullWhen(true)] out List waveData, [NotNullWhen(true)] out WfmSampleInfo wfmSampleInfo)
{
if (LongStorage != null)
return LongStorage!.TryTakeDdrSourceWave(channel, startTimeBySecond, totalTime, out waveData, out wfmSampleInfo);
else
{
waveData = new List();
wfmSampleInfo = new WfmSampleInfo() { SampleIntervalByus = 0.5 };
return false;
}
}
public bool TryTakeSegmentWave(Int32 channelIndex, Int32 segmentIndex, out List waveData, out WfmSampleInfo wfmSampleInfo, out Double SecondByps)
{
waveData = new List();
wfmSampleInfo = new WfmSampleInfo();
wfmSampleInfo.SampleIntervalByus = AcquedParameters.PerDataByfs_AfterPostProcess * 1.0 / 1E9;
if (segmentIndex < (LongStorage?.TrigAddressTable.Count ?? 0))
SecondByps = LongStorage?.TrigAddressTable[segmentIndex].FrameTimeByns ?? 0.0;
else
SecondByps = 0.0;
return LongStorage?.TryTakeSegmentWave(channelIndex, segmentIndex, out waveData) ?? false;
}
public Int32 TryTakeCollectedSegmentCnt()
{
return LongStorage?.ReadCollectedFrameCnt() ?? 0;
}
#endregion
protected virtual bool AcqAnalogChannelSimulateWaveform()
{
//AcqedDataPool.AnalogChData.AllChannelData.Clear();
//ushort[] list = { 2048, 1648, 1248, 2448 };
//for (int channelID = 0; channelID < ChannelIdExt.AnaChnlNum; channelID++)
//{
// AcqedDataPool.AnalogChData.AllChannelData.Add(new List());
// for (int i = 0; i < 10000; i++)
// AcqedDataPool.AnalogChData.AllChannelData[channelID].Add(list[channelID]);
//}
Monitor.Enter(AcqedDataPool.UpdateDataLock);
AcqedDataPool.AnalogChData.AllChannelData.Clear();
int Length = Constants.CHNL_DATA_NUM;
double SampIntByns = Hd.CurrHdMessage?.Timebase?.TmbScale * Constants.VIS_XDIVS_NUM * 1000 / Constants.CHNL_DATA_NUM ?? 0.5;
//var cycles = Length * (SampIntByns * 1E-9) * (Constants.AWG_SIN_FRQ_DEF * 1E-6);
double cycles = 10;
double NoiseByPercent = 0.05;
ArbWfmType[] allChannelArbWfmType;
if (!Hd.bPowerOff)
allChannelArbWfmType = new ArbWfmType[] { ArbWfmType.Sinc, ArbWfmType.Square, ArbWfmType.Ramp, ArbWfmType.DC, ArbWfmType.Sinc, ArbWfmType.Square, ArbWfmType.Ramp, ArbWfmType.Haversine };
else
allChannelArbWfmType = new ArbWfmType[] { ArbWfmType.DC, ArbWfmType.DC, ArbWfmType.DC, ArbWfmType.DC, ArbWfmType.DC, ArbWfmType.DC, ArbWfmType.DC, ArbWfmType.DC };
int channelCount = ChannelIdExt.AnaChnlNum;
if (Hd.currProduct.ProductType == ProductType.B21_DBI16G || Hd.currProduct.ProductType == ProductType.B21_DBI20G)
channelCount = 4;//按子带数来处理,而不是物理通道数
for (int channelID = 0; channelID < channelCount; channelID++)
{
double anaChannelPosition = 0;// Constants.IDX_PER_YDIV * 5;// Hd.CurrHdMessage?.Analog?[channelID].PositionIndex ?? 0;
double amplitude = 1.0;// (Hd.CurrHdMessage?.Analog?[channelID].Scale ?? 0) * 6;
ArbWfmType arbWfmType = allChannelArbWfmType[channelID];
IEnumerable y = arbWfmType switch
{
ArbWfmType.Pulse or ArbWfmType.Square => Generator.Rectangular(anaChannelPosition, amplitude, cycles / Length, Length, 0.05, NoiseByPercent, 0.1),
ArbWfmType.DC => Generator.DirectCurrent(anaChannelPosition, amplitude, Length, 0.05),
ArbWfmType.Haversine => Generator.Haversine(anaChannelPosition, amplitude, cycles / Length, Length, NoiseByPercent, 0.05),
_ => Generator.Sine(anaChannelPosition, amplitude, cycles / Length, Length, 0.02, 0.0),
};
y = y.Select(o => o * 1E3);
double pos0 = 0;
if (channelID < ChannelIdExt.AnaChnlNum)//因为DBI的缘故,子带模式与物理通道模式不一样
pos0 = (Hd.CurrHdMessage?.Analog?[channelID].PositionIndex ?? 0) / Constants.IDX_PER_YDIV * Constants.SAMPS_PER_YDIV + Constants.MAX_ADC_RES / 2;
else
pos0 = (Hd.CurrHdMessage?.Analog?[ChannelIdExt.AnaChnlNum - 1].PositionIndex ?? 0) / Constants.IDX_PER_YDIV * Constants.SAMPS_PER_YDIV + Constants.MAX_ADC_RES / 2;
y = y.Select((o) => o /*(Hd.CurrHdMessage?.Analog?[channelID].Scale ?? 100)*/ / Constants.IDX_PER_YDIV * Constants.SAMPS_PER_YDIV + pos0);
Double[] data = y.ToArray();// .ToRowVector();
AcqedDataPool.AnalogChData.AllChannelData.Add(new List());
for (int i = 0; i < Length; i++)
AcqedDataPool.AnalogChData.AllChannelData[channelID].Add((ushort)(data[i]));
}
AcquedParameters.PerDataByfs_AfterPostProcess = (Hd.CurrHdMessage?.Timebase?.TmbScale * Constants.VIS_XDIVS_NUM * 1000_000_000 / Constants.CHNL_DATA_NUM ?? 50 * 1000);
AbstractController_AnalogChannel.SoftwareBandwidthProcess();
Monitor.Exit(AcqedDataPool.UpdateDataLock);
return true;
}
#region Cali Tool 调用函数
public virtual bool TakeAllChannelWaveform(out List> waveData)
{
waveData = new List>();
Monitor.Enter(AcqedDataPool.UpdateDataLock);
for (int channelIndex = 0; channelIndex < ChannelIdExt.AnaChnlNum; channelIndex++)
{
List oneChannelData = new List();
oneChannelData.AddRange(AcqedDataPool.AnalogChData.AllChannelData[channelIndex].ToArray());
if (oneChannelData.Count < Constants.CHNL_DATA_NUM)
oneChannelData.AddRange(new ushort[Constants.CHNL_DATA_NUM - oneChannelData.Count]);//补齐数据长度,否则Tool端可能不能读到数据
waveData.Add(oneChannelData);
}
Monitor.Exit(AcqedDataPool.UpdateDataLock);
return true;
}
public virtual bool TakeAdcWaveform(out List> waveData)
{
waveData = new List>();
int totalCoreCount = ChannelIdExt.AnaChnlNum * Constants.ADC_NUM * Constants.ADC_CORE_NUM;
for (int coreIndex = 0; coreIndex < totalCoreCount; coreIndex++)
waveData.Add(new List());
Monitor.Enter(AcqedDataPool.UpdateDataLock);
int totalCoreIndex = 0;
for (int channelIndex = 0; channelIndex < ChannelIdExt.AnaChnlNum; channelIndex++)
{
for (int adcIndex = 0; adcIndex < Constants.ADC_NUM; adcIndex++)
{
for (int coreIndex = 0; coreIndex < Constants.ADC_CORE_NUM; coreIndex++)
{
for (int dotIndex = 0; dotIndex < Constants.CORE_DATA_NUM; dotIndex++)
{
ushort data = (adcIndex % Constants.ADC_NUM, coreIndex) switch
{
(0, 0) => AcqedDataPool.AnalogChData.AllChannelData[channelIndex][dotIndex * 4],
(0, 1) => AcqedDataPool.AnalogChData.AllChannelData[channelIndex][dotIndex * 4 + 2],
(1, 0) => AcqedDataPool.AnalogChData.AllChannelData[channelIndex][dotIndex * 4 + 1],
(1, 1) => AcqedDataPool.AnalogChData.AllChannelData[channelIndex][dotIndex * 4 + 3],
_ => 0,
};
waveData[totalCoreIndex].Add(data);
}
totalCoreIndex++;
}
}
}
Monitor.Exit(AcqedDataPool.UpdateDataLock);
return true;
}
#endregion
internal virtual bool IsNeedPostProcessByMatlab => false;
internal virtual void AnalogChannelActiveChanged() { }
private Dictionary _ExtramTable = new Dictionary()
{
// 抽取倍数 下发参数
{1, 0 },
{2, 1 },
{4, 2 },
{5, 3 },
{8, 4 },
{10, 5 },
{20, 6 },
{40, 7 },
};
///
/// 根据抽取模式和并行路数下发抽取参数
///
/// 抽取倍数:最大是36位
/// 并行路数:40/80
///
internal void ConfigExtramNum(UInt64 extramNum, UInt32 parallelRoads, AnaChnlAcqMode extramMode)
{
if (_ExtramTable.ContainsKey(extramNum) && extramNum < parallelRoads)
{
Hd.currProduct?.AcqBd?.WriteToAllFpga(AcqBdReg.W.Decimation_Decimation_Multiple_Pattern, _ExtramTable[extramNum]);
Hd.currProduct?.AcqBd?.WriteToAllFpga(AcqBdReg.W.Decimation_Decimation_quotient_L16, 0);
Hd.currProduct?.AcqBd?.WriteToAllFpga(AcqBdReg.W.Decimation_Decimation_quotient_M16, 0);
Hd.currProduct?.AcqBd?.WriteToAllFpga(AcqBdReg.W.Decimation_Decimation_quotient_H4, 0);
Hd.currProduct?.AcqBd?.WriteToAllFpga(AcqBdReg.W.Decimation_Decimation_remainder_additional_Processing, 0);
return;
}
Hd.currProduct?.AcqBd?.WriteToAllFpga(AcqBdReg.W.Decimation_Decimation_Multiple_Pattern, 8);
UInt64 decimationQuotient;
UInt64 remainderAdditional;
switch (extramMode)
{
case AnaChnlAcqMode.Normal:
decimationQuotient = extramNum / parallelRoads;
remainderAdditional = (extramNum / (parallelRoads / 4)) % 4;
break;
case AnaChnlAcqMode.Peak:
decimationQuotient = extramNum * 2 / parallelRoads;
if (extramNum * 2 % parallelRoads == 0)
remainderAdditional = 0x1 << 7;
else
remainderAdditional = parallelRoads / (extramNum * 2 % parallelRoads);
break;
case AnaChnlAcqMode.HighRes:
decimationQuotient = extramNum / parallelRoads;
if (extramNum % parallelRoads == 0)
remainderAdditional = 0x1 << 7;
else
remainderAdditional = parallelRoads / (extramNum % parallelRoads);
break;
default:
return;
}
Hd.currProduct?.AcqBd?.WriteToAllFpga(AcqBdReg.W.Decimation_Decimation_remainder_additional_Processing, (UInt32)remainderAdditional);
Hd.currProduct?.AcqBd?.WriteToAllFpga(AcqBdReg.W.Decimation_Decimation_quotient_L16, (UInt32)(decimationQuotient & 0xffff));
Hd.currProduct?.AcqBd?.WriteToAllFpga(AcqBdReg.W.Decimation_Decimation_quotient_M16, (UInt32)(decimationQuotient >> 16 & 0xffff));
Hd.currProduct?.AcqBd?.WriteToAllFpga(AcqBdReg.W.Decimation_Decimation_quotient_H4, (UInt32)(decimationQuotient >> 32 & 0xf));
}
struct ExtramPara
{
internal UInt32 Multiple_Pattern;
internal UInt64 RemainderAdditional;
internal UInt64 DecimationQuotient;
}
private ExtramPara GetExtramPara(UInt64 extramNum, UInt32 parallelRoads, AnaChnlAcqMode extramMode)
{
ExtramPara ectram = new ExtramPara();
if (_ExtramTable.ContainsKey(extramNum) && extramNum < parallelRoads)
{
ectram.Multiple_Pattern = _ExtramTable[extramNum];
ectram.RemainderAdditional = 0;
ectram.DecimationQuotient = 0;
}
else
{
ectram.Multiple_Pattern = 8;
switch (extramMode)
{
case AnaChnlAcqMode.Normal:
ectram.DecimationQuotient = extramNum / parallelRoads;
ectram.RemainderAdditional = (extramNum / (parallelRoads / 4)) % 4;
break;
case AnaChnlAcqMode.Peak:
ectram.DecimationQuotient = extramNum * 2 / parallelRoads;
if (extramNum * 2 % parallelRoads == 0)
ectram.RemainderAdditional = 0x1 << 7;
else
ectram.RemainderAdditional = parallelRoads / (extramNum * 2 % parallelRoads);
break;
case AnaChnlAcqMode.HighRes:
ectram.DecimationQuotient = extramNum / parallelRoads;
if (extramNum % parallelRoads == 0)
ectram.RemainderAdditional = 0x1 << 7;
else
ectram.RemainderAdditional = parallelRoads / (extramNum % parallelRoads);
break;
default:
break;
}
}
return ectram;
}
internal void ConfigExtramNum(UInt64 extramNum, UInt32 parallelRoads, AnaChnlAcqMode extramMode, AcqBdNo acqBd)
{
ExtramPara ectramPara = GetExtramPara(extramNum, parallelRoads, extramMode);
Hd.currProduct?.AcqBd?.WriteReg(AcqBdReg.W.Decimation_Decimation_Multiple_Pattern, acqBd, ectramPara.Multiple_Pattern);
Hd.currProduct?.AcqBd?.WriteReg(AcqBdReg.W.Decimation_Decimation_remainder_additional_Processing, acqBd, (UInt32)ectramPara.RemainderAdditional);
Hd.currProduct?.AcqBd?.WriteReg(AcqBdReg.W.Decimation_Decimation_quotient_L16, acqBd, (UInt32)(ectramPara.DecimationQuotient & 0xffff));
Hd.currProduct?.AcqBd?.WriteReg(AcqBdReg.W.Decimation_Decimation_quotient_M16, acqBd, (UInt32)(ectramPara.DecimationQuotient >> 16 & 0xffff));
Hd.currProduct?.AcqBd?.WriteReg(AcqBdReg.W.Decimation_Decimation_quotient_H4, acqBd, (UInt32)(ectramPara.DecimationQuotient >> 32 & 0xf));
}
internal virtual void ConfigLongStorage()
{
Hd.currProduct?.AcqBd?.WriteToAllFpga(AcqBdReg.W.LSCtrl_StorageMode, AcquingParameters.bIsLongStorageMode ? 1 : 0U);
Hd.currProduct?.AcqBd?.WriteToAllFpga(AcqBdReg.W.LSCtrl_RcdRstEnable, AcquingParameters.LS_SegmentCount > 1 ? 1u : 0);
}
internal virtual void FilterChannelAtSpecailBandwidth(ChannelId channelId)
{
//Uestc.Auto6.Dso.MathExt.Filter.
}
internal virtual void ConfigExtractProcessRoadParameters()
{
//要使FIFO 满,在确保ADC工作正常的情况下,需要正确配置的参数包括:
//采集板
//1、FifoCtrl_OutSpeed 串并转换CH_MODE_SamplingMode
//2、CH_MODE_SamplingMode
//3、Interpolate_Enable 、Interpolate_Ratio
//4、Decimation_Hardware、Decimation_HighResolution、Decimation_Peak等整个采集板处理路径
//5、FIFO深度FifoCtrl_FullProgDepth(可以在初始化时一次性设置)
//处理板
//FifoCtrl_ParallelFifoDepth、FifoCtrl_FullProgDepth(可以在初始化时一次性设置)
//PCIE 板
//FifoCtrl_ProgEmpty、FifoCtrl_FullProgDepth、FifoCtrl_ReadFromFIFO_Num(可以在初始化时一次性设置)
//FifoCtrl_ChannelMode
//modifyNote20220117 1、原来的不同模式采用不同的寄存器,现在呢?
bool bEnableInterpolation = Hd.CurrDebugVarints.bEnable_AcqbdInterpolation;
if (bEnableInterpolation)
{
if ((Hd.currProduct?.Acquirer_AnalogChannel?.AcquingParameters.InterpolationNum ?? 1) <= 1)
bEnableInterpolation = false;
}
Hd.currProduct?.AcqBd?.WriteToAllFpga(AcqBdReg.W.Interpolate_Enable, bEnableInterpolation ? 1U : 0U);
UInt32 acqMode = (Hd.CurrHdMessage?.Timebase?.AcqMode ?? AnaChnlAcqMode.Normal) switch
{
AnaChnlAcqMode.Peak => 1,
AnaChnlAcqMode.HighRes => 3,
_ => 0,
};
HdIO.WriteReg(ProcBdReg.W.ext_10m_ext_10m_sel, Hd.CurrHdMessage!.Timebase!.ClockSrc==AnaChnlClkSrc.Inner ? 0U : 1U);
UInt64 extractNum = (UInt64)(Hd.currProduct?.Acquirer_AnalogChannel?.AcquingParameters.HardwareExtractNum ?? 1U);
Hd.currProduct?.AcqBd?.WriteToAllFpga(AcqBdReg.W.Interpolate_Ratio, (UInt32)(Hd.currProduct?.Acquirer_AnalogChannel?.AcquingParameters.InterpolationNum ?? 1));
Hd.currProduct?.AcqBd?.WriteToAllFpga(AcqBdReg.W.Decimation_Decimation_L16, (UInt32)(extractNum & 0xffff));
Hd.currProduct?.AcqBd?.WriteToAllFpga(AcqBdReg.W.Decimation_Decimation_M16, (UInt32)((extractNum >> 16) & 0xffff));
Hd.currProduct?.AcqBd?.WriteToAllFpga(AcqBdReg.W.Decimation_Decimation_H16, (UInt32)(extractNum >> 32) & 0xffff);
Hd.currProduct?.AcqBd?.WriteToAllFpga(AcqBdReg.W.Decimation_DecimationMode, acqMode & 0xffff);
ConfigExtramNum(extractNum, Hd.currProduct!.Acquirer_AnalogChannel!.AcquingParameters.AcqAdcMergeRoadCount, (Hd.CurrHdMessage?.Timebase?.AcqMode ?? AnaChnlAcqMode.Normal));
Hd.currProduct?.AcqBd?.WriteToAllFpga(AcqBdReg.W.FifoCtrl_OutSpeed, 1U);
AnaChnlStorageMode anaChnlAcqLength = (Hd.CurrHdMessage?.Timebase?.AcqLength ?? AnaChnlStorageMode.Normal);
Hd.currProduct?.AcqBd?.WriteToAllFpga(AcqBdReg.W.LSCtrl_StorageMode, anaChnlAcqLength == AnaChnlStorageMode.Long ? 1U : 0U);
if (anaChnlAcqLength == AnaChnlStorageMode.Long)
{
//merged modify
//Hd.currProduct?.AcqBd?.WriteToAllFpga(AcqBdReg.W.LSCtrl_SegmentCount, (UInt32)(Hd.currProduct?.Acquirer_AnalogChannel?.AcquingParameters.LS_SegmentCount ?? 1));
//end merged modify
UInt32 tmp = (UInt32)(Hd.currProduct?.Acquirer_AnalogChannel?.AcquingParameters.LS_Addr_FirstSegment ?? 0);
Hd.currProduct?.AcqBd?.WriteToAllFpga(AcqBdReg.W.LSCtrl_SegmentBeginAddr_L, (UInt32)(tmp) & 0xffff);
Hd.currProduct?.AcqBd?.WriteToAllFpga(AcqBdReg.W.LSCtrl_SegmentBeginAddr_L, (UInt32)(tmp >> 16) & 0xffff);
tmp = (UInt32)(Hd.currProduct?.Acquirer_AnalogChannel?.AcquingParameters.LS_Addr_PreTrig ?? 0);
Hd.currProduct?.AcqBd?.WriteToAllFpga(AcqBdReg.W.LSCtrl_TrigAddrTableStartAddr_L, (UInt32)tmp & 0xffff);
Hd.currProduct?.AcqBd?.WriteToAllFpga(AcqBdReg.W.LSCtrl_TrigAddrTableStartAddr_H, (UInt32)(tmp >> 16) & 0xffff);
tmp = (UInt32)(Hd.currProduct?.Acquirer_AnalogChannel?.AcquingParameters.LS_SegmentAddrCount ?? 0);
Hd.currProduct?.AcqBd?.WriteToAllFpga(AcqBdReg.W.LSCtrl_SegmentBeginAddr_L, (UInt32)tmp & 0xffff);
Hd.currProduct?.AcqBd?.WriteToAllFpga(AcqBdReg.W.LSCtrl_SegmentBeginAddr_H, (UInt32)(tmp >> 16) & 0xffff);
tmp = (UInt32)(Hd.currProduct?.Acquirer_AnalogChannel?.AcquingParameters.LS_Addr_TrigTable ?? 0);
Hd.currProduct?.AcqBd?.WriteToAllFpga(AcqBdReg.W.LSCtrl_TrigAddrTableStartAddr_L, (UInt32)tmp & 0xffff);
Hd.currProduct?.AcqBd?.WriteToAllFpga(AcqBdReg.W.LSCtrl_TrigAddrTableStartAddr_H, (UInt32)(tmp >> 16) & 0xffff);
AnaChnlAcqMode anaChnlAcqMode = Hd.CurrHdMessage?.Timebase?.AcqMode ?? AnaChnlAcqMode.Normal;
//Hd.currProduct?.AcqBd?.WriteToAllFpga(AcqBdReg.W.LSCtrl_PickMode, anaChnlAcqMode == AnaChnlAcqMode.Peak ? 0U : 1U);
//Hd.currProduct?.AcqBd?.WriteToAllFpga(AcqBdReg.W.LSCtrl_PickMode, anaChnlAcqMode == AnaChnlAcqMode.Peak ? 0U : 1U);
}
}
internal virtual Dictionary>>? ChannelBdAdcInputDefines
{
get;
}
internal virtual Int32 Dpx_AcqFifoDepth()
{
Int64 currPerXDivByps = (Int64)((Hd.CurrHdMessage?.Timebase?.TmbScale ?? 1) * 1_000_000);//TmbScale 以us为单位,*1_000_000,us==>ps
return (Int32)((currPerXDivByps * 1000 * Constants.VIS_XDIVS_NUM / Hd.currProduct!.Acquirer_AnalogChannel!.AcquingParameters.PerDataByfs_AtStorage + 200) / 40);
}
#region AFC(幅频特性) 系数
private Dictionary lastChannelYScale = new Dictionary()
{
[ChannelId.C1] = AnaChnlScaleIndex.Lv100,
[ChannelId.C2] = AnaChnlScaleIndex.Lv100,
[ChannelId.C3] = AnaChnlScaleIndex.Lv100,
[ChannelId.C4] = AnaChnlScaleIndex.Lv100,
[ChannelId.C5] = AnaChnlScaleIndex.Lv100,
[ChannelId.C6] = AnaChnlScaleIndex.Lv100,
[ChannelId.C7] = AnaChnlScaleIndex.Lv100,
[ChannelId.C8] = AnaChnlScaleIndex.Lv100,
};
protected virtual void CheckResendAfc()
{
Calibration.Data.Base.CoefficientsTableType coefficientsTableType = CoefficientsTableType.Coefficients8;
bool bFound = false;
foreach (var v in Hd.currProduct!.HardwareConfig!.LocalCoefficientsTableMeanings)
{
if (v.Value.CoeffType == CommCoefficientsTableType.AcqBd_AFC)
{
coefficientsTableType = v.Key;
bFound = true;
break;
}
}
if (!bFound)
return;
bFound = false;
for (int channelId = (int)ChannelId.C1; channelId < ChannelIdExt.AnaChnlNum; channelId++)
{
if (lastChannelYScale[(ChannelId)channelId] != (AnaChnlScaleIndex)Hd.CurrHdMessage!.Analog![channelId]!.ScaleIndex)
{
lastChannelYScale[(ChannelId)channelId] = (AnaChnlScaleIndex)Hd.CurrHdMessage!.Analog![channelId]!.ScaleIndex;
bFound = true;
}
}
if (bFound)
{
CaliDataManager.DataChangedCoefficientsTableType.Add(coefficientsTableType);
Hd.LocalCommands |= (long)HdCmd.CaliDataChanged;
}
}
internal virtual bool Afc_Sender_ByRegisterMode(CoefficientsTableType coefficientsTableType, int[] dataArray, AcqBdNo acqBdNo, ChannelId channelId)
{
int partALength = Hd.currProduct!.HardwareConfig!.LocalCoefficientsTableMeanings[coefficientsTableType].LengthOfPartA;
int dataCount = dataArray.Length;
for (int i = 0; i < dataCount; i++)
{
Hd.currProduct!.AcqBd!.WriteReg(AcqBdReg.W.Fir_FactorTableWriteEnable, acqBdNo, 0);
if (i < partALength) //10G系数
Hd.currProduct!.AcqBd!.WriteReg(AcqBdReg.W.Fir_FactorTableWriteAddr, acqBdNo, (UInt32)i);
else //20G系数(修改系数长度后需要修改此处)
Hd.currProduct!.AcqBd!.WriteReg(AcqBdReg.W.Fir_FactorTableWriteAddr, acqBdNo, (UInt32)(i + 0b00100000000 - partALength));//(适用200阶)下发地址11位,通过高位为1下发的则是20G的系数
Int32 data = dataArray[i];
//低16位
Hd.currProduct!.AcqBd!.WriteReg(AcqBdReg.W.Fir_FactorTableWriteData_L, acqBdNo, (UInt32)data & 0xffff);
//高位
Hd.currProduct!.AcqBd!.WriteReg(AcqBdReg.W.Fir_FactorTableWriteData_H, acqBdNo, (UInt32)(data >> 16) & 0xff);
HdIO.DelayByUs(10);
Hd.currProduct!.AcqBd!.WriteReg(AcqBdReg.W.Fir_FactorTableWriteEnable, acqBdNo, 1);
}
Hd.currProduct!.AcqBd!.WriteReg(AcqBdReg.W.Fir_FactorTableWriteEnable, acqBdNo, 0);
Hd.currProduct!.AcqBd!.WriteReg(AcqBdReg.W.Fir_Enable, acqBdNo, Hd.CurrDebugVarints.bEnable_AcqBd_Afc ? 1U : 0);
return true;
}
internal virtual bool Afc_Sender_ByDMAMode(CoefficientsTableType coefficientsTableType, int[] dataArray, AcqBdNo acqBdNo, ChannelId channelId)
{
return false;
}
///
/// Key = $"{acqBdNo}_{((ChannelId)channelId)}",Value=crcCode
///
protected Dictionary AfcSendHistory = new Dictionary();
internal virtual void ClearSendHistory() => AfcSendHistory.Clear();
internal virtual void SendCoefficients_Afc(CoefficientsTableType coefficientsTableType, bool bForce)
{
if (Hd.currProduct!.Acquirer_AnalogChannel!.ChannelPerScaleAmpFreqCoefficientsDefine == null)
return;
Dictionary>>? channelBdAdcInputDefines = Hd.currProduct?.Acquirer_AnalogChannel?.ChannelBdAdcInputDefines;
if (channelBdAdcInputDefines == null)
return;
for (int channelId = (int)ChannelId.C1; channelId < ChannelIdExt.AnaChnlNum; channelId++)
{
string key = ((ChannelId)channelId).ToString() + "_" + ((int)Hd.CurrHdMessage!.Analog![channelId].Scale).ToString();
if (Hd.currProduct!.Acquirer_AnalogChannel!.ChannelPerScaleAmpFreqCoefficientsDefine.TryGetValue(key, out var info))
{
if (!info.bOk)
continue;
AcqBdNo acqBdNo = channelBdAdcInputDefines[1][(int)channelId][0].BdNo;//1=20G, 0=只取第一条记录,与ADC的顺序无关
string SendHistoryKey = $"{acqBdNo}_{((ChannelId)channelId)}";
if (AfcSendHistory.ContainsKey(SendHistoryKey))
{
if (AfcSendHistory[SendHistoryKey] == info.CRCCode)
continue;
AfcSendHistory[SendHistoryKey] = info.CRCCode;
}
else
AfcSendHistory.Add(SendHistoryKey, info.CRCCode);
int[]? dataArray = Misc.ReadCaliCoefDataFronmFile(info.FileName);
if (Hd.currProduct!.HardwareConfig!.DownloadBlockDataMode == DownloadBlockDataMode.DMA)
Afc_Sender_ByDMAMode(coefficientsTableType, dataArray!, acqBdNo, (ChannelId)channelId);
else
Afc_Sender_ByRegisterMode(coefficientsTableType, dataArray!, acqBdNo, (ChannelId)channelId);
}
}
return;
}
#endregion
internal virtual bool AutoCaliAtInit(HdMessage? hdMessage) => false;
internal virtual Boolean IsInterpolation_LS(Int32 channelId)
{
return false;
}
#region 模拟通道幅度增益温度补偿
protected DateTime LastPhyAnalogChAmplitudeTemperaturesCompensationCalced_Datetime = DateTime.Now;
Dictionary PhyAnalogChAmplitudeTemperaturesCompensationCoefficientFile = new Dictionary()
{
{ChannelId.C1,$@".\CaliData\CoeFiles\AnalogChannelTemperatureCompensation_C1.txt" },
{ChannelId.C2,$@".\CaliData\CoeFiles\AnalogChannelTemperatureCompensation_C2.txt" },
{ChannelId.C3,$@".\CaliData\CoeFiles\AnalogChannelTemperatureCompensation_C3.txt" },
{ChannelId.C4,$@".\CaliData\CoeFiles\AnalogChannelTemperatureCompensation_C4.txt" },
{ChannelId.C5,$@".\CaliData\CoeFiles\AnalogChannelTemperatureCompensation_C5.txt" },
{ChannelId.C6,$@".\CaliData\CoeFiles\AnalogChannelTemperatureCompensation_C6.txt" },
};
Dictionary> allChannelAmplitudeTemperaturesCompensationCoefficient = new Dictionary>();
protected List LastPhyAnalogChAmplitudeTemperaturesCompensationCoefficient = new List() { 1, 1, 1, 1, 1, 1, 1, 1 };
protected List PhyAnalogChAmplitudeBaselineTemperature = new List() { 40, 40, 40, 40, 40, 40, 40, 40 };//校准基准温度
internal virtual void InitPhyAnalogChAmplitudeTemperaturesCompensationCoefficient()
{
allChannelAmplitudeTemperaturesCompensationCoefficient.Clear();
string rootPath = AppDomain.CurrentDomain.BaseDirectory;
for (ChannelId channelId = ChannelId.C1; channelId <= ChannelId.C8; channelId++)
{
if (PhyAnalogChAmplitudeTemperaturesCompensationCoefficientFile.ContainsKey(channelId))
{
var result = Misc.ReadAmplitudeTemperaturesCompensationCoefficientFile(PhyAnalogChAmplitudeTemperaturesCompensationCoefficientFile[channelId], out double baselineTemperature);
if (result.Count > 0)
{
if (allChannelAmplitudeTemperaturesCompensationCoefficient.ContainsKey(channelId))
allChannelAmplitudeTemperaturesCompensationCoefficient[channelId] = result;
else
allChannelAmplitudeTemperaturesCompensationCoefficient.Add(channelId, result);
PhyAnalogChAmplitudeBaselineTemperature[(int)channelId] = baselineTemperature;
}
}
}
}
internal virtual bool GetPhyAnalogChAmplitudeTemperaturesCompensationCoefficient(out List Coefficient)
{
Coefficient = LastPhyAnalogChAmplitudeTemperaturesCompensationCoefficient;
if ((DateTime.Now - LastPhyAnalogChAmplitudeTemperaturesCompensationCalced_Datetime).TotalMilliseconds < Acquisition.PhyAnalogChAmplitudeTemperaturesCompensationIntervalByMs)
return false;
double currTemperature = SysMonitor.Default.AnalogChannelTemperatures[0];//只有一个通道板
for (ChannelId channelId = ChannelId.C1; channelId <= ChannelIdExt.MaxAChId; channelId++)
{
ChannelId key = channelId;
if (allChannelAmplitudeTemperaturesCompensationCoefficient.ContainsKey(key))
{
double result = 1;
KeyValuePair first;
try
{
first = allChannelAmplitudeTemperaturesCompensationCoefficient[key].First((o) => o.Key <= currTemperature);
}
catch
{
first = (allChannelAmplitudeTemperaturesCompensationCoefficient[key].First());
result = first.Value;
if (allChannelAmplitudeTemperaturesCompensationCoefficient[key].ContainsKey(PhyAnalogChAmplitudeBaselineTemperature[(int)key]))
result = result / allChannelAmplitudeTemperaturesCompensationCoefficient[key][PhyAnalogChAmplitudeBaselineTemperature[(int)key]];
LastPhyAnalogChAmplitudeTemperaturesCompensationCoefficient[(int)channelId] = result;
return true;
}
KeyValuePair last;
try
{
last = allChannelAmplitudeTemperaturesCompensationCoefficient[key].First((o) => o.Key >= currTemperature);
}
catch
{
last = allChannelAmplitudeTemperaturesCompensationCoefficient[key].Last();
result = last.Value;
if (allChannelAmplitudeTemperaturesCompensationCoefficient[key].ContainsKey(PhyAnalogChAmplitudeBaselineTemperature[(int)key]))
result = result / allChannelAmplitudeTemperaturesCompensationCoefficient[key][PhyAnalogChAmplitudeBaselineTemperature[(int)key]];
LastPhyAnalogChAmplitudeTemperaturesCompensationCoefficient[(int)channelId] = result;
return true; ;
}
if (Math.Abs(first.Key - currTemperature) < 0.01)//==
result = first.Value;
else if (Math.Abs(last.Key - currTemperature) < 0.01)//==
result = last.Value;
else if (first.Key != last.Key)
result = first.Value + (last.Value - first.Value) * (currTemperature - first.Key) / (last.Key - first.Key);//局部线性插值
if (allChannelAmplitudeTemperaturesCompensationCoefficient[channelId].ContainsKey(PhyAnalogChAmplitudeBaselineTemperature[(int)channelId]))
result = result / allChannelAmplitudeTemperaturesCompensationCoefficient[channelId][PhyAnalogChAmplitudeBaselineTemperature[(int)channelId]];
LastPhyAnalogChAmplitudeTemperaturesCompensationCoefficient[(int)channelId] = result;
}
}
LastPhyAnalogChAmplitudeTemperaturesCompensationCalced_Datetime = DateTime.Now;
return true;
}
#endregion
#region Dpx
internal virtual DpxAcqParameters CreateDpxAcqParameters()
{
bool bInterpolation = Hd.currProduct?.Acquirer_AnalogChannel?.AcquingParameters.InterpolationNum > 1 ? true : false;//修改为真正得读取插值
bool bEdgeTrig = Hd.CurrHdMessage?.Trigger?.TrigType == TriggerType.Edge;
bool bSerialDpx = (bInterpolation | (!bEdgeTrig));
Int64 currPerXDivByps = (Int64)((Hd.CurrHdMessage?.Timebase?.TmbScale ?? 1) * 1_000_000);//TmbScale 以us为单位,*1_000_000,us==>ps
Int32 ParallelMapFifoDepth = (Int32)(currPerXDivByps * 1000 * Constants.VIS_XDIVS_NUM / (long)AcquingParameters.PerDataByfs_AtStorage / 5 / 4);//PerDataByfs_AtStorage 或者Dpx_PerDataByfs_AtStorage
Int32 SoftFifoDepth = (Int32)(currPerXDivByps * 1024 * Constants.VIS_XDIVS_NUM / (long)AcquingParameters.PerDataByfs_AtStorage / 4 + 15);
return new DpxAcqParameters()
{
bSerialDpx = bSerialDpx
};
}
#endregion
}
internal class ChannelBdAdcInputDefine
{
public AcqBdNo BdNo { get; set; }
public Int32 AdcIndex { get; set; }
public int InputPort_AIs1 { get; set; }
public bool bIs20GMode { get; set; } = false;
}
internal class AmpCoefficientFileInfo
{
public string FileName = "";
public int CRCCode = 0;
public bool bOk=false;
}
}