using System; using System.Collections.Generic; using System.Text; using Uestc.Auto6.Dso.ComModel; using Uestc.Auto6.Dso.Hardware.Calibration.Data.Base; namespace Uestc.Auto6.Dso.Hardware.Driver { internal record TrigSourceParams { public UInt32 AcqBd_TrigCtrl_1st_SourceWhichAdcStartWith0; public UInt32 ProcBd_TrigCtrl_1st_SourceWhichAcqBdStartWith0; public UInt32 ProcBd_TrigCtrl_2nd_SourceWhichChannelStartWith0; } internal abstract class AbstractController_Trigger { internal virtual int PrimaryClockPeriodByps => 4000;//当前系统时钟周期4000ps,频率250MHz public Dictionary InterpolationLevelDiscardNumTable = new Dictionary(); protected virtual void ourConfigTriggerSource() { uint trigChannel = CurrentTrigSource(); var currTrigSourceParams = Hd.currProduct!.Acquirer_AnalogChannel!.GetTrigSourceParams(trigChannel); //1.判断触发信号来自于采集板哪个ADC,所有采集板配置相同,所有被选中通道的触发信号都送到处理板做二次选择 //相当于对应一个采集板上的哪个ADC。以触发的物理通道接入的那个ADC为准。ADC1:发0,ADC2:发1,两片:发0 Hd.currProduct?.AcqBd?.WriteToAllFpga(AcqBdReg.W.TrigCtrl_1st_SourceSelect, (uint)currTrigSourceParams.AcqBd_TrigCtrl_1st_SourceWhichAdcStartWith0); //2.一级触发源:表示来自于那个采集板的信号。用0,1,2,表示。 HdIO.WriteReg(ProcBdReg.W.TrigCtrl_1st_SourceControl, currTrigSourceParams.ProcBd_TrigCtrl_1st_SourceWhichAcqBdStartWith0); //二级触发,表示对应的物理通道,与DMA中的数据路数一致 HdIO.WriteReg(ProcBdReg.W.TrigCtrl_2nd_SourceSelect, currTrigSourceParams.ProcBd_TrigCtrl_2nd_SourceWhichChannelStartWith0); //Hd.currProduct?.AcqBd?.WriteToAllFpga(0x92c4, 0); //Hd.currProduct?.AcqBd?.WriteToAllFpga(0x92b0, 0); //LA if (ChannelIdExt.IsDigital((ChannelId)trigChannel)) { HdIO.WriteReg(ProcBdReg.W.LA_TrigSourceSel, (UInt32)((ChannelId)trigChannel - ChannelId.D1 + 1)); } HdIO.WriteReg(ProcBdReg.W.LA_TrigEdgeSel, (UInt32)(((Hd.CurrHdMessage!.Trigger!.TrigType == TriggerType.Edge && ChannelIdExt.IsDigital((ChannelId)trigChannel) ? 1 : 0) << 1) | ((Hd.CurrHdMessage!.Trigger!.Edge!.Slope == EdgeSlope.Rise ? 1 : 0)))); } protected virtual void ourConfigTriggerMode() { //触发模式,只能在FPGA端处理,故归入数字触发模块 UInt32 trigMode = Hd.CurrHdMessage?.Trigger?.Mode == TriggerMode.Auto ? 1U : 0; //Hd.currProduct?.AcqBd?.WriteToAllFpga(AcqBdReg.W.TrigCtrl_AutoModeEnable, trigMode);//一级触发部分移至处理板 HdIO.WriteReg(ProcBdReg.W.TrigCtrl_2nd_AutoModeEnable, trigMode);//2级触发模式 HdIO.WriteReg(ProcBdReg.W.TrigCtrl_1st_AutoModeEnable, (200 << 1) | trigMode); //1级触发模式 Hd.currProduct?.AcqBd?.WriteToAllFpga(AcqBdReg.W.LSCtrl_AutoTrigSet, (trigMode << 15) | 1); //Hd.currProduct?.AcqBd?.WriteToAllFpga(AcqBdReg.W.TrigCtrl_FindRange, 500); //HdIO.WriteReg(ProcBdReg.W.TrigCtrl_2nd_SearchRange, 5000); } protected virtual void ourConfigTriggerClock() { //AdjSource() } protected virtual void ourConfigHoldOff() { uint holdOfftime = (uint)(Hd.CurrHdMessage?.Trigger?.HoldoffByps ?? Constants.MIN_HOLDOFF_PS) / (UInt32)Hd.currProduct!.Ctrl_Trigger!.PrimaryClockPeriodByps; uint Eventcnt = (uint)(Hd.CurrHdMessage?.Trigger?.HoldoffByCnt ?? Constants.MIN_HOLDOFF_EVENT); if (Hd.CurrHdMessage?.Trigger?.HoldoffType == DelayOpt.Time) { Hd.currProduct!.AcqBd!.WriteToAllFpga(AcqBdReg.W.TrigCtrl_holdtime_widthL, holdOfftime & 0xffff); Hd.currProduct!.AcqBd!.WriteToAllFpga(AcqBdReg.W.TrigCtrl_holdtime_widthH, (holdOfftime >> 16) & 0xffff); Hd.currProduct!.AcqBd!.WriteToAllFpga(AcqBdReg.W.TrigCtrl_holdtime_set, 0); } else { Hd.currProduct!.AcqBd!.WriteToAllFpga(AcqBdReg.W.TrigCtrl_holdtime_widthL, Eventcnt & 0xffff); Hd.currProduct!.AcqBd!.WriteToAllFpga(AcqBdReg.W.TrigCtrl_holdtime_widthH, (Eventcnt >> 16) & 0xffff); Hd.currProduct!.AcqBd!.WriteToAllFpga(AcqBdReg.W.TrigCtrl_holdtime_set, 1); } HdIO.WriteReg(ProcBdReg.W.TrigCtrl_1st_HoldOffTimeL, 4 & 0xffff); HdIO.WriteReg(ProcBdReg.W.TrigCtrl_1st_HoldOffTimeH, (holdOfftime >> 16) & 0xffff); //原PutTSysHoldOff() } /// /// 采集Fifo阶段的深度 /// protected virtual void ourConfigFifoStageDepth_WithAcqLength() { if (Hd.CurrHdMessage?.Timebase?.AcqLength != AnaChnlStorageMode.Long) { Int64 xdepth = Hd.currProduct!.Acquirer_AnalogChannel!.GetTrigXDepth(); Int64 hardwareExtractNum = (Int64)(Hd.currProduct?.Acquirer_AnalogChannel?.AcquingParameters.HardwareExtractNum ?? 1); //xdepth = 1000; Int64 xdepth_tmp = hardwareExtractNum switch { 1 => xdepth / 80 + 19, 2 => xdepth * 2 / 80 + 19, _ => (Int64)(xdepth * (Int64)hardwareExtractNum / 80 + hardwareExtractNum * 3), }; //xdepth_tmp = 500 * 2 / 80; HdIO.WriteReg(ProcBdReg.W.TrigCtrl_1st_PreDepthSetL, (UInt32)xdepth_tmp & 0xffff); HdIO.WriteReg(ProcBdReg.W.TrigCtrl_1st_PreDepthSetM, (UInt32)(xdepth_tmp >> 16) & 0xffff); HdIO.WriteReg(ProcBdReg.W.TrigCtrl_1st_PreDepthSetH, (UInt32)(xdepth_tmp >> 32) & 0xfff); HdIO.WriteReg(ProcBdReg.W.TrigCtrl_1st_PosDepthSetL, 0); HdIO.WriteReg(ProcBdReg.W.TrigCtrl_1st_PosDepthSetM, 0); HdIO.WriteReg(ProcBdReg.W.TrigCtrl_1st_PosDepthSetH, 0); //Hd.currProduct?.AcqBd?.WriteToAllFpga(AcqBdReg.W.TrigCtrl_PreDepth, (UInt32)xdepth); } else { // DDR中的数据分辨率已经确定,在此只需要发送抽点数就可以了。 // DDR中触发点的时间已经确定,计算就可得到需要发送的触发位置了。 } } internal static Int32 PerYDivAdcSamples = Constants.VIS_ADC_RES / Constants.VIS_YDIVS_NUM; internal static Int32 AdcCenterValue = Constants.MAX_ADC_RES / 2; internal virtual uint DefaultTrigSensitivity { get => Hd.currProduct!.Acquirer_AnalogChannel!.DefaultTrigSensitivity; } internal virtual uint CurrentTrigSource() { uint trigSource = (uint)(Hd.CurrHdMessage?.Trigger?.Edge?.Source ?? ChannelId.C1); switch (Hd.CurrHdMessage?.Trigger?.TrigType) { case TriggerType.Edge: trigSource = (uint)(Hd.CurrHdMessage?.Trigger?.Edge?.Source ?? ChannelId.C1); break; case TriggerType.PulseWidth: trigSource = (uint)(Hd.CurrHdMessage?.Trigger?.Pulse?.Source ?? ChannelId.C1); break; case TriggerType.Runt: trigSource = (uint)(Hd.CurrHdMessage?.Trigger?.Runt?.Source ?? ChannelId.C1); break; case TriggerType.Transition: trigSource = (uint)(Hd.CurrHdMessage?.Trigger?.Transition?.Source ?? ChannelId.C1); break; case TriggerType.SetupHold: trigSource = (uint)(Hd.CurrHdMessage?.Trigger?.SetupHold?.ClkSource ?? ChannelId.C1);//改了 break; case TriggerType.Glitch: trigSource = (uint)(Hd.CurrHdMessage?.Trigger?.Glitch?.Source ?? ChannelId.C1); break; case TriggerType.Window: trigSource = (uint)(Hd.CurrHdMessage?.Trigger?.Window?.Source ?? ChannelId.C1); break; case TriggerType.TimeOut: trigSource = (uint)(Hd.CurrHdMessage?.Trigger?.TimeOut?.Source ?? ChannelId.C1); break; default: trigSource = (uint)(Hd.CurrHdMessage?.Trigger?.Edge?.Source ?? ChannelId.C1); break; } //if ((int)trigSource >= ChannelIdExt.AnaChnlNum) // trigSource = (uint)ChannelId.C1; return trigSource; } /// /// 配置数字触发相关参数。如丢点数,搜索宽度等。 /// internal virtual void ourConfigDgtParameter() { Hd.currProduct?.AcqBd?.WriteToAllFpga(AcqBdReg.W.TrigCtrl_Location_TrigDiscardColumnEn, Hd.CurrDebugVarints!.bEnable_DigitTrigger ? 1U : 0); //HdIO.WriteReg(ProcBdReg.W.TrigCtrl_2nd_SerialTrigEnable, Hd.CurrDebugVarints!.bEnable_DigitTrigger ? 1U : 0); if (Hd.CurrHdMessage!.Trigger!.TrigType == TriggerType.Serial) HdIO.WriteReg(ProcBdReg.W.TrigCtrl_2nd_SerialTrigEnable, 0); var compVolt = Hd.currProduct!.Acquirer_AnalogChannel!.GetDigitTrigCompVolt(); Hd.currProduct?.AcqBd?.WriteToAllFpga(AcqBdReg.W.TrigCtrl_1st_CompareVoltage1Up, (uint)(compVolt.Up));//0x87e Hd.currProduct?.AcqBd?.WriteToAllFpga(AcqBdReg.W.TrigCtrl_1st_CompareVoltage1Down, (uint)(compVolt.Dn));//0x74a Hd.currProduct?.AcqBd?.WriteToAllFpga(AcqBdReg.W.TrigCtrl_1st_EdgeSelect, compVolt.Edge);//compVolt.Edge HdIO.WriteReg(ProcBdReg.W.TrigCtrl_2nd_EdgeSelect, compVolt.Edge); //处理板二级触发边沿选择 int trigSource = (int)CurrentTrigSource(); if (trigSource < ChannelIdExt.AnaChnlNum) { if (Hd.CurrHdMessage!.Analog![trigSource].InputSource != AnaChnlIpnutSource.SMA) { HdIO.WriteReg(ProcBdReg.W.TrigCtrl_2nd_CompareVoltage1Up, (uint)(compVolt.Up)); //处理板二级触发迟滞高电平选择 HdIO.WriteReg(ProcBdReg.W.TrigCtrl_2nd_CompareVoltage1Down, (uint)(compVolt.Dn)); //处理板二级触发迟滞低电平选择 } } HdIO.WriteReg(ProcBdReg.W.TrigCtrl_1st_CaliTrigDelayEnable, 0); HdIO.WriteReg(ProcBdReg.W.TrigCtrl_1st_CalibrationNum, 0); } /// /// 开关数字触发 /// /// protected virtual void ourSwitchDgtStatus(bool bOpen) { } #region TriggerTypeAndParameter protected virtual void ourConfigTypeAndParameter() { if (Hd.CurrHdMessage == null) return; TriggerType currType = Hd.CurrHdMessage?.Trigger?.TrigType ?? TriggerType.Edge; #region Step1 设置类型 #endregion #region Step2 设置类型需要的参数 if (triggerTypeDefineTable.ContainsKey(currType)) { if (TriggerTypeDefineTable[currType].Value != null) TriggerTypeDefineTable[currType].Value.Invoke(); } #endregion } #endregion //不同产品对改变进行不同的配置 protected virtual Dictionary> TriggerTypeDefineTable { get => triggerTypeDefineTable; } private readonly Dictionary> triggerTypeDefineTable = new Dictionary>(); protected virtual void Init() { triggerTypeDefineTable.Clear(); triggerTypeDefineTable.Add(TriggerType.Edge, new(0x01, CtrlTrigger_Standard.Config_Edge)); triggerTypeDefineTable.Add(TriggerType.Glitch, new(0x02, CtrlTrigger_Standard.Config_Glitch)); triggerTypeDefineTable.Add(TriggerType.MultiQulified, new(0x03, CtrlTrigger_Standard.Config_MultiQulified)); triggerTypeDefineTable.Add(TriggerType.Pattern, new(0x04, CtrlTrigger_Standard.Config_Pattern)); triggerTypeDefineTable.Add(TriggerType.PulseWidth, new(0x05, CtrlTrigger_Standard.Config_PulseWidth)); triggerTypeDefineTable.Add(TriggerType.Runt, new(0x06, CtrlTrigger_Standard.Config_Runt)); triggerTypeDefineTable.Add(TriggerType.Serial, new(0x07, CtrlTrigger_Standard.Config_Serial)); triggerTypeDefineTable.Add(TriggerType.SetupHold, new(0x08, CtrlTrigger_Standard.Config_SetupHold)); triggerTypeDefineTable.Add(TriggerType.State, new(0x09, CtrlTrigger_Standard.Config_State)); triggerTypeDefineTable.Add(TriggerType.TimeOut, new(0x0a, CtrlTrigger_Standard.Config_TimeOut)); triggerTypeDefineTable.Add(TriggerType.Transition, new(0x0b, CtrlTrigger_Standard.Config_Transition)); triggerTypeDefineTable.Add(TriggerType.Video, new(0x0c, CtrlTrigger_Standard.Config_Video)); triggerTypeDefineTable.Add(TriggerType.Window, new(0x0d, CtrlTrigger_Standard.Config_Window)); triggerTypeDefineTable.Add(TriggerType.Interval, new(0x0e, CtrlTrigger_Standard.Config_Interval)); } protected Action? _ConfigTriggerSource; protected Action? _ConfigTriggerMode; protected Action? _ConfigTriggerClock; protected Action? _ConfigHoldOff; protected Action? _ConfigDgtParameter; protected Action? _SwitchDgtStatus; protected Action? _ConfigTypeAndParameter; protected Action? _ConfigFifoStageDepth_WithAcqLength; public static void ConfigTriggerSource() => Hd.currProduct?.Ctrl_Trigger?._ConfigTriggerSource?.Invoke(); public static void ConfigTriggerMode() => Hd.currProduct?.Ctrl_Trigger?._ConfigTriggerMode?.Invoke(); public static void ConfigTriggerClock() => Hd.currProduct?.Ctrl_Trigger?._ConfigTriggerClock?.Invoke(); public static void ConfigHoldOff() => Hd.currProduct?.Ctrl_Trigger?._ConfigHoldOff?.Invoke(); public static void ConfigDgtParameter() => Hd.currProduct?.Ctrl_Trigger?._ConfigDgtParameter?.Invoke(); public static void SwitchDgtStatus(bool bOpen) => Hd.currProduct?.Ctrl_Trigger?._SwitchDgtStatus?.Invoke(bOpen); public static void ConfigTypeAndParameter() => Hd.currProduct?.Ctrl_Trigger?._ConfigTypeAndParameter?.Invoke(); public static void ConfigFifoStageDepth_WithAcqLength() => Hd.currProduct?.Ctrl_Trigger?._ConfigFifoStageDepth_WithAcqLength?.Invoke(); public static Dictionary AcqBdProcBdLoopDelayOf4nsCount = new Dictionary(); public static void GetAcqBdProcBdLoopDelayOf4nsCount() { // } } }