Browse Source

新增数据缓存及fifo读取功能

luo 4 days ago
parent
commit
5b383f115e

+ 2 - 0
Client/Dynamicloadsimulationdevice/ViewModels/MainWindowViewModel.cs

@@ -80,6 +80,8 @@ namespace Dynamicloadsimulationdevice.ViewModels
             OilSourceControl =IModel.Tools.PluginsLoader.Defalut.Load<IOilSourceControl.IOilSourceControl>(PluginPath).FirstOrDefault();
             if(OilSourceControl!=null)
             {
+                OilSourceControl.LocalCommunication = () => CommunicationViewModel.Instance.LocalCommunication;
+                OilSourceControl.RemoteCommunication = () => CommunicationViewModel.Instance.ServiceCommunication;
                 var v = GetAssemblyViewModels(OilSourceControl.GetType().Assembly);
                 DisplayViewModels.AddRange(v);
             }

+ 1 - 1
NIFPGA/FPGAArrayReadProperty.cs

@@ -59,6 +59,6 @@ namespace NIFPGA
             }
         }
         public uint Count { get; }
-        public T[] Values  => GetValues(); 
+        public T[] Value  => GetValues(); 
     }
 }

+ 1 - 1
NIFPGA/FPGAArrayWriteProperty.cs

@@ -106,6 +106,6 @@ namespace NIFPGA
             }
         }
         public uint Count { get; }
-        public T[] Values { get => GetValues(); set => SetValue(value); }
+        public T[] Value { get => GetValues(); set => SetValue(value); }
     }
 }

+ 57 - 13
Service/ShakerFpga/ShakerFpgaSourceGenerator.cs

@@ -82,7 +82,7 @@ namespace ShakerFpga
         }
         private void GeneratorRegister(Register register, StringBuilder stringBuilder)
         {
-            string protype = GetProType(register);
+            string protype = GetProType(register,out var typename);
             string proname = $"{register.Name.Split('_')[0]}";
             proname = RemovePropertySpecialcharacters(proname);
             stringBuilder.AppendLine($"        private {protype} _{proname};");
@@ -104,14 +104,33 @@ namespace ShakerFpga
                 stringBuilder.AppendLine($"        ///<para> 数据类型:{type}</para>");
             }
             stringBuilder.AppendLine($"        /// </summary>");
-            stringBuilder.AppendLine($"        public {protype} {proname}");
-            stringBuilder.AppendLine("        {");
-            stringBuilder.AppendLine("            get");
-            stringBuilder.AppendLine("            {");
-            stringBuilder.AppendLine($"                _" + proname + $" ??= ({protype})fpga.Properties[\"{register.Name}\"];");
-            stringBuilder.AppendLine($"                return _" + proname + ";");
-            stringBuilder.AppendLine("            }");
-            stringBuilder.AppendLine("        }");
+            if(register.Indicator)
+            {
+                stringBuilder.AppendLine($"        public {typename} {proname}");
+                stringBuilder.AppendLine("        {");
+                stringBuilder.AppendLine("            get");
+                stringBuilder.AppendLine("            {");
+                stringBuilder.AppendLine($"                _" + proname + $" ??= ({protype})fpga.Properties[\"{register.Name}\"];");
+                stringBuilder.AppendLine($"                return _" + proname + ".Value;");
+                stringBuilder.AppendLine("            }");
+                stringBuilder.AppendLine("        }");
+            }
+            else
+            {
+                stringBuilder.AppendLine($"        public {typename} {proname}");
+                stringBuilder.AppendLine("        {");
+                stringBuilder.AppendLine("            get");
+                stringBuilder.AppendLine("            {");
+                stringBuilder.AppendLine($"                _" + proname + $" ??= ({protype})fpga.Properties[\"{register.Name}\"];");
+                stringBuilder.AppendLine($"                return _" + proname + ".Value;");
+                stringBuilder.AppendLine("            }");
+                stringBuilder.AppendLine("            set");
+                stringBuilder.AppendLine("            {");
+                stringBuilder.AppendLine($"                _" + proname + $" ??= ({protype})fpga.Properties[\"{register.Name}\"];");
+                stringBuilder.AppendLine($"                _" + proname + ".Value = value;");
+                stringBuilder.AppendLine("            }");
+                stringBuilder.AppendLine("        }");
+            }
         }
         private void GeneratorFifo(DMA dma,StringBuilder stringBuilder)
         {
@@ -197,13 +216,15 @@ namespace ShakerFpga
             string proname = Regex.Replace(s,@"\((.+?)\)","", RegexOptions.IgnoreCase).Replace("(", "_").Replace(")", "_").Replace("/", "_").Replace("__", "_").Trim('_');
             return char.ToUpper(proname[0]) + proname.Substring(1);
         }
-        private string GetProType(Register register)
+        private string GetProType(Register register,out string nomalTypeNames)
         {
+            nomalTypeNames = "";
             string value = "";
             switch (register.Datatype)
             {
                 case NIFPGA.lvbitx.Datatype.Boolean:
-                    if(!register.Indicator)
+                    nomalTypeNames = "bool";
+                    if (!register.Indicator)
                     {
                         value = "FPGAWriteProperty<bool>";
                     }
@@ -213,6 +234,7 @@ namespace ShakerFpga
                     }
                     break;
                 case NIFPGA.lvbitx.Datatype.Int8:
+                    nomalTypeNames = "sbyte";
                     if (!register.Indicator)
                     {
                         value = "FPGAWriteProperty<sbyte>";
@@ -223,6 +245,7 @@ namespace ShakerFpga
                     }
                     break;
                 case NIFPGA.lvbitx.Datatype.Uint8:
+                    nomalTypeNames = "byte";
                     if (!register.Indicator)
                     {
                         value = "FPGAWriteProperty<byte>";
@@ -233,6 +256,7 @@ namespace ShakerFpga
                     }
                     break;
                 case NIFPGA.lvbitx.Datatype.Int16:
+                    nomalTypeNames = "short";
                     if (!register.Indicator)
                     {
                         value = "FPGAWriteProperty<short>";
@@ -243,6 +267,7 @@ namespace ShakerFpga
                     }
                     break;
                 case NIFPGA.lvbitx.Datatype.Uint16:
+                    nomalTypeNames = "ushort";
                     if (!register.Indicator)
                     {
                         value = "FPGAWriteProperty<ushort>";
@@ -253,6 +278,7 @@ namespace ShakerFpga
                     }
                     break;
                 case NIFPGA.lvbitx.Datatype.Int32:
+                    nomalTypeNames = "int";
                     if (!register.Indicator)
                     {
                         value = "FPGAWriteProperty<int>";
@@ -263,6 +289,7 @@ namespace ShakerFpga
                     }
                     break;
                 case NIFPGA.lvbitx.Datatype.Uint32:
+                    nomalTypeNames = "uint";
                     if (!register.Indicator)
                     {
                         value = "FPGAWriteProperty<uint>";
@@ -273,6 +300,7 @@ namespace ShakerFpga
                     }
                     break;
                 case NIFPGA.lvbitx.Datatype.Int64:
+                    nomalTypeNames = "long";
                     if (!register.Indicator)
                     {
                         value = "FPGAWriteProperty<long>";
@@ -283,6 +311,7 @@ namespace ShakerFpga
                     }
                     break;
                 case NIFPGA.lvbitx.Datatype.Uint64:
+                    nomalTypeNames = "ulong";
                     if (!register.Indicator)
                     {
                         value = "FPGAWriteProperty<ulong>";
@@ -293,6 +322,7 @@ namespace ShakerFpga
                     }
                     break;
                 case NIFPGA.lvbitx.Datatype.Float:
+                    nomalTypeNames = "float";
                     if (!register.Indicator)
                     {
                         value = "FPGAWriteProperty<float>";
@@ -303,6 +333,7 @@ namespace ShakerFpga
                     }
                     break;
                 case NIFPGA.lvbitx.Datatype.Double:
+                    nomalTypeNames = "double";
                     if (!register.Indicator)
                     {
                         value = "FPGAWriteProperty<double>";
@@ -313,7 +344,8 @@ namespace ShakerFpga
                     }
                     break;
                 case NIFPGA.lvbitx.Datatype.FXP:
-                    if(!register.Indicator)
+                    nomalTypeNames = "double";
+                    if (!register.Indicator)
                     {
                         value = "FPGAFXPWriteProperty";
                     }
@@ -326,7 +358,8 @@ namespace ShakerFpga
                     switch (register.ArrayValueType)
                     {
                         case NIFPGA.lvbitx.Datatype.Boolean:
-                            if(!register.Indicator)
+                            nomalTypeNames = "bool[]";
+                            if (!register.Indicator)
                             {
                                 value = "FPGAArrayWriteProperty<bool>";
                             }
@@ -336,6 +369,7 @@ namespace ShakerFpga
                             }
                             break;
                         case NIFPGA.lvbitx.Datatype.Int8:
+                            nomalTypeNames = "sbyte[]";
                             if (!register.Indicator)
                             {
                                 value = "FPGAArrayWriteProperty<sbyte>";
@@ -346,6 +380,7 @@ namespace ShakerFpga
                             }
                             break;
                         case NIFPGA.lvbitx.Datatype.Uint8:
+                            nomalTypeNames = "byte[]";
                             if (!register.Indicator)
                             {
                                 value = "FPGAArrayWriteProperty<byte>";
@@ -356,6 +391,7 @@ namespace ShakerFpga
                             }
                             break;
                         case NIFPGA.lvbitx.Datatype.Int16:
+                            nomalTypeNames = "short[]";
                             if (!register.Indicator)
                             {
                                 value = "FPGAArrayWriteProperty<short>";
@@ -366,6 +402,7 @@ namespace ShakerFpga
                             }
                             break;
                         case NIFPGA.lvbitx.Datatype.Uint16:
+                            nomalTypeNames = "ushort[]";
                             if (!register.Indicator)
                             {
                                 value = "FPGAArrayWriteProperty<ushort>";
@@ -376,6 +413,7 @@ namespace ShakerFpga
                             }
                             break;
                         case NIFPGA.lvbitx.Datatype.Int32:
+                            nomalTypeNames = "int[]";
                             if (!register.Indicator)
                             {
                                 value = "FPGAArrayWriteProperty<int>";
@@ -386,6 +424,7 @@ namespace ShakerFpga
                             }
                             break;
                         case NIFPGA.lvbitx.Datatype.Uint32:
+                            nomalTypeNames = "uint[]";
                             if (!register.Indicator)
                             {
                                 value = "FPGAArrayWriteProperty<uint>";
@@ -396,6 +435,7 @@ namespace ShakerFpga
                             }
                             break;
                         case NIFPGA.lvbitx.Datatype.Int64:
+                            nomalTypeNames = "long[]";
                             if (!register.Indicator)
                             {
                                 value = "FPGAArrayWriteProperty<long>";
@@ -406,6 +446,7 @@ namespace ShakerFpga
                             }
                             break;
                         case NIFPGA.lvbitx.Datatype.Uint64:
+                            nomalTypeNames = "ulong[]";
                             if (!register.Indicator)
                             {
                                 value = "FPGAArrayWriteProperty<ulong>";
@@ -416,6 +457,7 @@ namespace ShakerFpga
                             }
                             break;
                         case NIFPGA.lvbitx.Datatype.Float:
+                            nomalTypeNames = "float[]";
                             if (!register.Indicator)
                             {
                                 value = "FPGAArrayWriteProperty<float>";
@@ -426,6 +468,7 @@ namespace ShakerFpga
                             }
                             break;
                         case NIFPGA.lvbitx.Datatype.Double:
+                            nomalTypeNames = "double[]";
                             if (!register.Indicator)
                             {
                                 value = "FPGAArrayWriteProperty<double>";
@@ -436,6 +479,7 @@ namespace ShakerFpga
                             }
                             break;
                         case NIFPGA.lvbitx.Datatype.FXP:
+                            nomalTypeNames = "double[]";
                             if (!register.Indicator)
                             {
                                 value = "FPGAArrayFXPWriteProperty";

+ 4 - 32
Service/ShakerService/Service.Init.cs

@@ -11,38 +11,10 @@ namespace ShakerService
 {
     partial class Service
 	{
+		private List<ViewModelBase> viewModels = new List<ViewModelBase>();
 		private string fpgename = "RIOO";
 		public void Init()
 		{
-            EventBus.EventBroker.Instance.GetEvent(Shaker.Model.Topic.LOG).Subscrip((sender, args) =>
-            {
-                if (args.Data.Length > 0 && args.Data[0] is string s)
-                {
-					Tools.Log.Default.Info(s);
-                }
-            });
-            ShakerFpga.ShakerFpga.CreateFpga(SIMDFxpConvert.SIMDFxpConverter.Instance);
-			nisyscfg.NISyscfg syscfg = new nisyscfg.NISyscfg();
-			syscfg.Init();
-			syscfg.Filter.IsDevice = true;
-			syscfg.Filter.IsChassis = false;
-			syscfg.Filter.IsSimulated = false;
-			syscfg.Filter.IsNIProduct = true;
-			syscfg.Filter.IsPresent = true;
-			syscfg.Filter.ServiceType = NISysCfgServiceType.NISysCfgServiceTypeLocalFpga;
-			var h = syscfg.SearchHardware();
-			if (h.Count > 0)
-			{
-				fpgename = h.First().ExpertUserAlias;
-			}
-			else
-			{
-				fpgename = "RIOO";
-			}
-			syscfg.Close();
-			string path = AppDomain.CurrentDomain.BaseDirectory;
-			string file = System.IO.Directory.GetFiles(path, "*.lvbitx").FirstOrDefault() ?? string.Empty;
-			ShakerFpga.ShakerFpga.Instance.Open(file,fpgename, NIFPGA.NiFpga_OpenAttribute.NiFpga_OpenAttribute_NoRun);
 			this.GetType().Assembly.GetTypes()
 				.Where(x => x.IsAnsiClass && !x.IsAbstract && x.IsAssignableTo(typeof(ViewModelBase)))
 				.Select(x =>
@@ -57,10 +29,10 @@ namespace ShakerService
 				{
 					var pro = x.GetProperty("Instance", BindingFlags.Public | BindingFlags.Static);
 					var initmethod = x.GetMethod(nameof(ViewModelBase.Init), BindingFlags.Instance | BindingFlags.Public);
-					if(pro!=null && initmethod!=null)
+					if(pro!=null && initmethod!=null && pro.GetValue(null) is ViewModelBase vm)
 					{
-						var val = pro.GetValue(null);
-						initmethod.Invoke(val,null);
+						initmethod.Invoke(vm,null);
+						viewModels.Add(vm);
 					}
 				});
 			this.GetType().GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic)

+ 40 - 0
Service/ShakerService/Service.ReadFifo.cs

@@ -0,0 +1,40 @@
+using ShakerService.Tools;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ShakerService
+{
+    internal partial class Service
+    {
+        private void ReadFifo()
+        {
+            int perframelen = ViewModel.ShakerConfigViewModel.Instance.MaxResultChannelCount * ViewModel.ShakerConfigViewModel.Instance.SampleRate;
+            uint readlen = 0;
+            while(!maintokenSource.IsCancellationRequested)
+            {
+                if(ShakerFpga.ShakerFpga.Instance.波形数据.ElementsRemaining>=perframelen)
+                {
+                    ShakerFpga.ShakerFpga.Instance.波形数据.Read(ref ShakerDataCache.Instance.GetDataCacheref(0), (uint)perframelen, 100, ref readlen);
+                    SendData(ShakerDataCache.Instance.DataCache, (uint)ShakerDataCache.Instance.RowCount, (uint)ShakerDataCache.Instance.ColnumCount);
+                    break;
+                }
+                else
+                {
+                    Task.Delay(10).Wait();
+                }
+            }
+        }
+        private void SendData(byte[] data, uint rowcount, uint colnumcount)
+        {
+            //异步发送数据
+            Task.Run(() =>
+            {
+                Log.Default.Info("发送数据");
+                Communication.Instance.Context.GetEvent(Shaker.Model.Topic.DATA)?.Publish(this, null, Shaker.Tools.Tools.CompressionBytes(data), rowcount, colnumcount);
+            });
+        }
+    }
+}

+ 46 - 0
Service/ShakerService/Service.cs

@@ -7,6 +7,7 @@ using System.Collections.Generic;
 using System.Diagnostics.CodeAnalysis;
 using System.Linq;
 using System.Net;
+using System.Reflection;
 using System.Text;
 using System.Threading.Tasks;
 
@@ -14,6 +15,41 @@ namespace ShakerService
 {
     internal partial class Service
     {
+        public Service()
+        {
+            DateTime dateTime = File.GetLastWriteTime(Assembly.GetEntryAssembly()!.Location);
+            Log.Default.Info($"程序生成时间:{dateTime:F}");
+
+            EventBus.EventBroker.Instance.GetEvent(Shaker.Model.Topic.LOG).Subscrip((sender, args) =>
+            {
+                if (args.Data.Length > 0 && args.Data[0] is string s)
+                {
+                    Tools.Log.Default.Info(s);
+                }
+            });
+            ShakerFpga.ShakerFpga.CreateFpga(SIMDFxpConvert.SIMDFxpConverter.Instance);
+            nisyscfg.NISyscfg syscfg = new nisyscfg.NISyscfg();
+            syscfg.Init();
+            syscfg.Filter.IsDevice = true;
+            syscfg.Filter.IsChassis = false;
+            syscfg.Filter.IsSimulated = false;
+            syscfg.Filter.IsNIProduct = true;
+            syscfg.Filter.IsPresent = true;
+            syscfg.Filter.ServiceType = NISysCfgServiceType.NISysCfgServiceTypeLocalFpga;
+            var h = syscfg.SearchHardware();
+            if (h.Count > 0)
+            {
+                fpgename = h.First().ExpertUserAlias;
+            }
+            else
+            {
+                fpgename = "RIOO";
+            }
+            syscfg.Close();
+            string path = AppDomain.CurrentDomain.BaseDirectory;
+            string file = System.IO.Directory.GetFiles(path, "*.lvbitx").FirstOrDefault() ?? string.Empty;
+            ShakerFpga.ShakerFpga.Instance.Open(file, fpgename, NIFPGA.NiFpga_OpenAttribute.NiFpga_OpenAttribute_NoRun);
+        }
         [AllowNull]
         private IDeviceDiscovery.IDeviceDiscovery deviceDiscovery;
         [AllowNull]
@@ -44,6 +80,7 @@ namespace ShakerService
                     };
                 };
                 deviceDiscovery.Start();
+                Log.Default.Info($"监听端口{deviceDiscovery.DiscoveryPort}");
             }
             oilSourceService = IModel.Tools.PluginsLoader.Defalut.Load<IOilSourceService.IOilSourceService>(path)?.FirstOrDefault();
             if (oilSourceService != null)
@@ -65,6 +102,15 @@ namespace ShakerService
             }
         }
         private void RTInit()
+        {
+            ShakerFpga.ShakerFpga.Instance.Reset();
+            ShakerFpga.ShakerFpga.Instance.零位改 = false;
+            viewModels.ForEach(x => x.SetFpga());
+            ShakerFpga.ShakerFpga.Instance.Run();
+            Log.Default.Info("初始化FPGA");
+            RTInitFifo();
+        }
+        private void RTInitFifo()
         {
 
         }

+ 48 - 0
Service/ShakerService/ShakerDataCache.cs

@@ -0,0 +1,48 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ShakerService
+{
+    internal unsafe struct ShakerDataCache
+    {
+        public int RowCount;
+        public int ColnumCount;
+        private byte[] _DataCache = new byte[0];
+        public byte[] DataCache => _DataCache;
+        
+        public ShakerDataCache()
+        {
+
+        }
+        static ShakerDataCache()
+        {
+        }
+        public void InitDataCache(int rowcount,int colnumcount)
+        {
+            if (rowcount*colnumcount <= 0 || rowcount*colnumcount == RowCount*ColnumCount) return;
+
+            RowCount = rowcount;
+            ColnumCount = colnumcount;
+            _DataCache = new byte[rowcount*colnumcount*Unsafe.SizeOf<float>()];            
+        }
+        public ref float GetDataCacheref(int row)
+        {
+            int offset = row * Unsafe.SizeOf<float>() * ColnumCount;
+            return ref Unsafe.As<byte, float>(ref _DataCache[offset]);
+        }
+        public float[] GetAnalogData(int row)
+        {
+            float[] data = new float[ColnumCount];
+            int offset = row * Unsafe.SizeOf<float>() * ColnumCount;
+            Unsafe.CopyBlock(ref Unsafe.As<float, byte>(ref data[0]), ref _DataCache[offset], (uint)(ColnumCount * Unsafe.SizeOf<float>()));
+            return data;
+
+        }
+        public static ShakerDataCache Instance = new ShakerDataCache();
+    }
+}

+ 68 - 0
Service/ShakerService/Tools/CpuUsage.cs

@@ -0,0 +1,68 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ShakerService.Tools
+{
+    public class CpuUsage
+    {
+        DateTime dateTime = DateTime.MinValue;
+        double lastusage = 0;
+        private const string ProcStatPath = "/proc/stat";
+
+        private string _previousCpuData;
+        private long _previousTotalUserTime;
+        private long _previousTotalUserNiceTime;
+        private long _previousTotalSystemTime;
+        private long _previousTotalIdleTime;
+
+        public CpuUsage()
+        {
+            if (!System.IO.File.Exists(ProcStatPath)) return;
+            _previousCpuData = ReadCpuData();
+            ParseCpuData(_previousCpuData, out _previousTotalUserTime, out _previousTotalUserNiceTime, out _previousTotalSystemTime, out _previousTotalIdleTime);
+        }
+
+        public double GetCpuUsage()
+        {
+            if ((DateTime.Now - dateTime).TotalMilliseconds < 2000) return lastusage;
+            dateTime = DateTime.Now;
+            if (!System.IO.File.Exists(ProcStatPath)) return lastusage;
+            string currentCpuData = ReadCpuData();
+            ParseCpuData(currentCpuData, out long currentTotalUserTime, out long currentTotalUserNiceTime, out long currentTotalSystemTime, out long currentTotalIdleTime);
+
+            long totalUserTime = currentTotalUserTime - _previousTotalUserTime;
+            long totalUserNiceTime = currentTotalUserNiceTime - _previousTotalUserNiceTime;
+            long totalSystemTime = currentTotalSystemTime - _previousTotalSystemTime;
+            long totalIdleTime = currentTotalIdleTime - _previousTotalIdleTime;
+
+            long totalCpuTime = totalUserTime + totalUserNiceTime + totalSystemTime + totalIdleTime;
+
+            lastusage = (double)(totalUserTime + totalSystemTime) / totalCpuTime;
+
+            _previousTotalUserTime = currentTotalUserTime;
+            _previousTotalUserNiceTime = currentTotalUserNiceTime;
+            _previousTotalSystemTime = currentTotalSystemTime;
+            _previousTotalIdleTime = currentTotalIdleTime;
+
+            return lastusage;
+        }
+
+        private string ReadCpuData()
+        {
+            return File.ReadLines(ProcStatPath).First(line => line.StartsWith("cpu "));
+        }
+
+        private void ParseCpuData(string cpuData, out long totalUserTime, out long totalUserNiceTime, out long totalSystemTime, out long totalIdleTime)
+        {
+            string[] cpuDataArray = cpuData.Split(' ').Where(s => !string.IsNullOrEmpty(s)).ToArray();
+            totalUserTime = long.Parse(cpuDataArray[1]);
+            totalUserNiceTime = long.Parse(cpuDataArray[2]);
+            totalSystemTime = long.Parse(cpuDataArray[3]);
+            totalIdleTime = long.Parse(cpuDataArray[4]);
+        }
+    }
+
+}

+ 6 - 6
Service/ShakerService/ViewModel/BalancingControlViewModel.cs

@@ -49,12 +49,12 @@ namespace ShakerService.ViewModel
         public override void SetFpga()
         {
             base.SetFpga();
-            ShakerFpga.ShakerFpga.Instance.静支撑增益.Value = CurrentModel.StaticSupportGain;
-            ShakerFpga.ShakerFpga.Instance.空台面压力.Value = [.. PreloadingQuality.Select(x => x * ShakerConfigViewModel.Instance.G / Area)];
-            ShakerFpga.ShakerFpga.Instance.静支撑开环驱动.Value = StaticSupportOpenLoopDrvier;
-            ShakerFpga.ShakerFpga.Instance.静支撑积分.Value = EnabledIntegration;
-            ShakerFpga.ShakerFpga.Instance.静支撑闭环.Value = StaticSupportCloseLoop;
-            ShakerFpga.ShakerFpga.Instance.支撑缸积分.Value = BalancingIntegration;
+            ShakerFpga.ShakerFpga.Instance.静支撑增益 = CurrentModel.StaticSupportGain;
+            ShakerFpga.ShakerFpga.Instance.空台面压力 = [.. PreloadingQuality.Select(x => x * ShakerConfigViewModel.Instance.G / Area)];
+            ShakerFpga.ShakerFpga.Instance.静支撑开环驱动 = StaticSupportOpenLoopDrvier;
+            ShakerFpga.ShakerFpga.Instance.静支撑积分 = EnabledIntegration;
+            ShakerFpga.ShakerFpga.Instance.静支撑闭环 = StaticSupportCloseLoop;
+            ShakerFpga.ShakerFpga.Instance.支撑缸积分 = BalancingIntegration;
         }
         private protected override void ReadModel()
         {

+ 2 - 2
Service/ShakerService/ViewModel/FlutterViewModel.cs

@@ -42,8 +42,8 @@ namespace ShakerService.ViewModel
         public override void SetFpga()
         {
             base.SetFpga();
-            ShakerFpga.ShakerFpga.Instance.颤震频率.Value = CurrentModel.Frequency * 2 / ShakerConfigViewModel.Instance.SampleRate;
-            ShakerFpga.ShakerFpga.Instance.颤振信号幅值.Value = CurrentModel.Amplitude;
+            ShakerFpga.ShakerFpga.Instance.颤震频率 = CurrentModel.Frequency * 2 / ShakerConfigViewModel.Instance.SampleRate;
+            ShakerFpga.ShakerFpga.Instance.颤振信号幅值 = CurrentModel.Amplitude;
         }
         public static FlutterViewModel Instance { get; } = new FlutterViewModel();
     }

+ 4 - 4
Service/ShakerService/ViewModel/ForceBalanceControlViewModel.cs

@@ -92,10 +92,10 @@ namespace ShakerService.ViewModel
         public override void SetFpga()
         {
             base.SetFpga();
-            ShakerFpga.ShakerFpga.Instance.水平力反馈增益.Value = HorizontalForceBalanceGain;
-            ShakerFpga.ShakerFpga.Instance.竖直力反馈增益.Value = VerticalForceBalanceGain;
-            ShakerFpga.ShakerFpga.Instance.合成矩阵.Value = [.. CompositionMatrix];
-            ShakerFpga.ShakerFpga.Instance.自由度分解列矩阵.Value = [.. FreedomDecompositionMatrix];
+            ShakerFpga.ShakerFpga.Instance.水平力反馈增益 = HorizontalForceBalanceGain;
+            ShakerFpga.ShakerFpga.Instance.竖直力反馈增益 = VerticalForceBalanceGain;
+            ShakerFpga.ShakerFpga.Instance.合成矩阵 = [.. CompositionMatrix];
+            ShakerFpga.ShakerFpga.Instance.自由度分解列矩阵 = [.. FreedomDecompositionMatrix];
         }
         public static ForceBalanceControlViewModel Instance { get; } = new ForceBalanceControlViewModel();
     }

+ 71 - 0
Service/ShakerService/ViewModel/FpgaVersionViewModel.cs

@@ -0,0 +1,71 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ShakerService.ViewModel
+{
+    internal sealed class FpgaVersionViewModel:ViewModelBase<Shaker.Models.FpgaVersionModel>
+    {
+        Tools.CpuUsage usage = new Tools.CpuUsage();
+
+        private System.Diagnostics.Process process;
+        private readonly int loopTime = 1000;
+
+        private FpgaVersionViewModel()
+        {
+            process = System.Diagnostics.Process.GetCurrentProcess();
+            IsStart = false;
+            CurrentModel.BitfileVersion = ShakerFpga.ShakerFpga.Instance.BitfileVersion;
+            CurrentModel.SignatureRegister = ShakerFpga.ShakerFpga.Instance.SignatureRegister;
+            CurrentModel.BitstreamVersion = ShakerFpga.ShakerFpga.Instance.BitstreamVersion;
+            CurrentModel.SignatureNames = ShakerFpga.ShakerFpga.Instance.SignatureNames;
+            CurrentModel.OSVersion = Environment.OSVersion.VersionString;
+            CurrentModel.FrameworkVersion = Environment.Version.ToString();
+            CurrentModel.MachineName = Environment.MachineName;
+            CurrentModel.CreateTime = File.GetLastWriteTime(Assembly.GetEntryAssembly()!.Location);
+            CurrentModel.Version = Assembly.GetEntryAssembly()?.GetName()?.Version?.ToString() ?? "Unknown";
+        }
+        static FpgaVersionViewModel()
+        {
+
+        }
+        public static FpgaVersionViewModel Instance { get; } = new FpgaVersionViewModel();
+        public string BitstreamMD5 => CurrentModel.BitfileVersion;
+        public string BitfileVersion => CurrentModel.BitfileVersion;
+        public string SignatureRegister => CurrentModel.SignatureRegister;
+        public string BitstreamVersion =>CurrentModel.BitstreamVersion;
+        public string SignatureNames =>CurrentModel.SignatureNames;
+        public string OSVersion =>CurrentModel.OSVersion;
+        public string FrameworkVersion =>CurrentModel.FrameworkVersion;
+        public string MachineName =>CurrentModel.MachineName;
+        public string Version =>CurrentModel.Version;
+        public DateTime CreateTime => CurrentModel.CreateTime;
+        public long MemoryUsage => CurrentModel.MemoryUsage;
+        public double CPUUsage => CurrentModel.CPUUsage;
+        public override bool AllowSave => false;
+        public async override void Start(CancellationToken token)
+        {
+            while(!token.IsCancellationRequested)
+            {
+                CurrentModel.MemoryUsage = process.WorkingSet64;
+                CurrentModel.CPUUsage = usage.GetCpuUsage();
+                SendData();
+                try
+                {
+                    await Task.Delay(loopTime, token);
+                }
+                catch(TaskCanceledException)
+                {
+                    break;
+                }
+                catch
+                {
+
+                }
+            }
+        }
+    }
+}

+ 9 - 9
Service/ShakerService/ViewModel/ServoConfigViewModel.cs

@@ -59,18 +59,18 @@ namespace ShakerService.ViewModel
         public override void SetFpga()
         {
             base.SetFpga();
-            ShakerFpga.ShakerFpga.Instance.P参数.Value = [.. PI.Select(x => x.P)];
-            ShakerFpga.ShakerFpga.Instance.I参数.Value = [.. PI.Select(x => x.I)];
+            ShakerFpga.ShakerFpga.Instance.P参数 = [.. PI.Select(x => x.P)];
+            ShakerFpga.ShakerFpga.Instance.I参数 = [.. PI.Select(x => x.I)];
 
-            ShakerFpga.ShakerFpga.Instance.水平阀死区电压.Value = HorizontalBarrierPotential;
-            ShakerFpga.ShakerFpga.Instance.竖直阀死区电压.Value = VerticalBarrierPotential;
+            ShakerFpga.ShakerFpga.Instance.水平阀死区电压 = HorizontalBarrierPotential;
+            ShakerFpga.ShakerFpga.Instance.竖直阀死区电压 = VerticalBarrierPotential;
 
-            ShakerFpga.ShakerFpga.Instance.最大积分电压.Value = MaxIntegratedVoltage;
-            ShakerFpga.ShakerFpga.Instance.最大驱动电压.Value = MaxDriverVoltage;
+            ShakerFpga.ShakerFpga.Instance.最大积分电压 = MaxIntegratedVoltage;
+            ShakerFpga.ShakerFpga.Instance.最大驱动电压 = MaxDriverVoltage;
 
-            ShakerFpga.ShakerFpga.Instance.急停后驱动限幅值.Value = EmerhencyDriverLimitVoltage;
-            ShakerFpga.ShakerFpga.Instance.位移前馈增益.Value = DisplacementFeedforwardGain;
-            ShakerFpga.ShakerFpga.Instance.驱动超限电压.Value = DriverOverLimitVoltage;
+            ShakerFpga.ShakerFpga.Instance.急停后驱动限幅值 = EmerhencyDriverLimitVoltage;
+            ShakerFpga.ShakerFpga.Instance.位移前馈增益 = DisplacementFeedforwardGain;
+            ShakerFpga.ShakerFpga.Instance.驱动超限电压 = DriverOverLimitVoltage;
         }
         public static ServoConfigViewModel Instance { get; } = new ServoConfigViewModel();
         public IReadOnlyList<PIModel> PI => CurrentModel.PI;

+ 41 - 20
Service/ShakerService/ViewModel/ShakerChannelConfigViewModel.cs

@@ -52,6 +52,10 @@ namespace ShakerService.ViewModel
         /// 平衡缸通道
         /// </summary>
         public IReadOnlyList<AOChannel> Balancing =>CurrentModel.Balancing;
+        /// <summary>
+        /// 返回通道定义
+        /// </summary>
+        public IReadOnlyList<ResultChannelType> ResultChannels => CurrentModel.ResultChannels;
         private protected override void SaveModel()
         {
             base.SaveModel();
@@ -74,6 +78,11 @@ namespace ShakerService.ViewModel
             {
                 Communication.Instance.DbConnection.Execute($"INSERT INTO {nameof(Balancing)} (Value) VALUES ({(int)CurrentModel.Balancing[i]});");
             }
+            Communication.Instance.DbConnection.DeleteAll<ResultChannelType>(tableName: nameof(ResultChannels));
+            for (int i = 0; i < CurrentModel.ResultChannels.Count; i++)
+            {
+                Communication.Instance.DbConnection.Execute($"INSERT INTO {nameof(ResultChannels)} (Value) VALUES ({(int)CurrentModel.ResultChannels[i]});");
+            }
         }
         private protected override void ReadModel()
         {
@@ -197,6 +206,18 @@ namespace ShakerService.ViewModel
             {
                 CurrentModel.Balancing.AddRange(Enumerable.Repeat(new AOChannel(), ShakerConfigViewModel.Instance.BalancingCount - CurrentModel.Balancing.Count));
             }
+
+
+            Communication.Instance.DbConnection.Execute($"CREATE TABLE IF NOT EXISTS {nameof(ResultChannels)} ({nameof(BaseModel.Id)} INTEGER PRIMARY KEY AUTOINCREMENT, Value INT);");
+            CurrentModel.ResultChannels = Communication.Instance.DbConnection.Query<ResultChannelType>($"SELECT Value FROM {nameof(ResultChannels)}")?.ToList() ?? new List<ResultChannelType>();
+            if (CurrentModel.ResultChannels.Count > ShakerConfigViewModel.Instance.MaxResultChannelCount)
+            {
+                CurrentModel.ResultChannels.RemoveRange(ShakerConfigViewModel.Instance.MaxResultChannelCount, CurrentModel.ResultChannels.Count - ShakerConfigViewModel.Instance.MaxResultChannelCount);
+            }
+            else if (CurrentModel.ResultChannels.Count < ShakerConfigViewModel.Instance.MaxResultChannelCount)
+            {
+                CurrentModel.ResultChannels.AddRange(Enumerable.Repeat(ResultChannelType.None, ShakerConfigViewModel.Instance.MaxResultChannelCount - CurrentModel.ResultChannels.Count));
+            }
             SaveModel();
         }
         private protected override void UpModel(ShakerChannelConfigModel model)
@@ -317,46 +338,46 @@ namespace ShakerService.ViewModel
         public override void SetFpga()
         {
             base.SetFpga();
-            ShakerFpga.ShakerFpga.Instance.位移通道.Values = [.. Displacement.Select(x => (byte)x.Channel)];
+            ShakerFpga.ShakerFpga.Instance.位移通道 = [.. Displacement.Select(x => (byte)x.Channel)];
             /*
              * 位移灵敏度用户设置的单位为mv/mm,在这里需要转换成mm/V
              */
-            ShakerFpga.ShakerFpga.Instance.位移灵敏度.Value = [.. Displacement.Select(x => 1000 / x.Sensitivity)];
-            ShakerFpga.ShakerFpga.Instance.位移直偏.Value = [.. Displacement.Select(x => x.Bias)];
+            ShakerFpga.ShakerFpga.Instance.位移灵敏度 = [.. Displacement.Select(x => 1000 / x.Sensitivity)];
+            ShakerFpga.ShakerFpga.Instance.位移直偏 = [.. Displacement.Select(x => x.Bias)];
 
-            ShakerFpga.ShakerFpga.Instance.加速度通道.Values = [.. Acceleration.Select(x => (byte)x.Channel)];
+            ShakerFpga.ShakerFpga.Instance.加速度通道 = [.. Acceleration.Select(x => (byte)x.Channel)];
             /*
              * 加速度灵敏度用户设置的单位为mv/g,在这里需要转换成g/V
              */
-            ShakerFpga.ShakerFpga.Instance.加速度灵敏度.Value = [.. Acceleration.Select(x =>1000/ x.Sensitivity)];
+            ShakerFpga.ShakerFpga.Instance.加速度灵敏度 = [.. Acceleration.Select(x =>1000/ x.Sensitivity)];
 
-            ShakerFpga.ShakerFpga.Instance.外部输入通道.Values = [.. OutSignal.Select(x => (byte)x.Channel)];
-            ShakerFpga.ShakerFpga.Instance.外部输入增益.Value = [.. OutSignal.Select(x => x.Sensitivity)];
+            ShakerFpga.ShakerFpga.Instance.外部输入通道 = [.. OutSignal.Select(x => (byte)x.Channel)];
+            ShakerFpga.ShakerFpga.Instance.外部输入增益 = [.. OutSignal.Select(x => x.Sensitivity)];
 
-            ShakerFpga.ShakerFpga.Instance.压差通道.Values = [.. DifferentialPressure.Select(x => (byte)x.Channel)];
-            ShakerFpga.ShakerFpga.Instance.压差直偏.Value = [.. DifferentialPressure.Select(x => x.Bias)];
+            ShakerFpga.ShakerFpga.Instance.压差通道 = [.. DifferentialPressure.Select(x => (byte)x.Channel)];
+            ShakerFpga.ShakerFpga.Instance.压差直偏 = [.. DifferentialPressure.Select(x => x.Bias)];
             /*
              * 压差灵敏度用户设置的单位为V/MPa,在这里需要转换成MPa/V
              */
-            ShakerFpga.ShakerFpga.Instance.压差灵敏度.Value = [.. DifferentialPressure.Select(x => 1/x.Sensitivity)];
+            ShakerFpga.ShakerFpga.Instance.压差灵敏度 = [.. DifferentialPressure.Select(x => 1/x.Sensitivity)];
 
 
-            ShakerFpga.ShakerFpga.Instance.支撑压力通道.Values = [.. Pressure.Select(x => (byte)x.Channel)];
-            ShakerFpga.ShakerFpga.Instance.支撑压力直偏.Value = [.. Pressure.Select(x => x.Bias)];
+            ShakerFpga.ShakerFpga.Instance.支撑压力通道 = [.. Pressure.Select(x => (byte)x.Channel)];
+            ShakerFpga.ShakerFpga.Instance.支撑压力直偏 = [.. Pressure.Select(x => x.Bias)];
             /*
             * 支撑压力灵敏度用户设置的单位为V/MPa,在这里需要转换成MPa/V
             */
-            ShakerFpga.ShakerFpga.Instance.支撑压力灵敏度.Value = [.. Pressure.Select(x => 1/x.Sensitivity)];
+            ShakerFpga.ShakerFpga.Instance.支撑压力灵敏度 = [.. Pressure.Select(x => 1/x.Sensitivity)];
 
 
-            ShakerFpga.ShakerFpga.Instance.平衡缸通道.Values = [.. Balancing.Select(x => (byte)x)];
+            ShakerFpga.ShakerFpga.Instance.平衡缸通道 = [.. Balancing.Select(x => (byte)x)];
 
-            ShakerFpga.ShakerFpga.Instance.水平缸通道.Values = [.. Horizontal.Select(x => (byte)x.Channel)];
-            ShakerFpga.ShakerFpga.Instance.垂直缸通道.Values = [.. Vertical.Select(x => (byte)x.Channel)];
-            ShakerFpga.ShakerFpga.Instance.伺服驱动直偏.Value = [.. Horizontal.Select(x => x.Bias),..Vertical.Select(x => x.Bias)];
-            ShakerFpga.ShakerFpga.Instance.伺服缸极性.Values = [.. Horizontal.Select(x => x.Polarity == Shaker.Model.Polarity.Positive), ..Vertical.Select(x => x.Polarity == Shaker.Model.Polarity.Positive)];
-            ShakerFpga.ShakerFpga.Instance.伺服开环.Values = [.. Horizontal.Select(x => x.OpenLoop), .. Vertical.Select(x => x.OpenLoop)];
-            ShakerFpga.ShakerFpga.Instance.伺服阀开环驱动.Value = [.. Horizontal.Select(x => x.OpenLoopDriver), .. Vertical.Select(x => x.OpenLoopDriver)];
+            ShakerFpga.ShakerFpga.Instance.水平缸通道 = [.. Horizontal.Select(x => (byte)x.Channel)];
+            ShakerFpga.ShakerFpga.Instance.垂直缸通道 = [.. Vertical.Select(x => (byte)x.Channel)];
+            ShakerFpga.ShakerFpga.Instance.伺服驱动直偏 = [.. Horizontal.Select(x => x.Bias),..Vertical.Select(x => x.Bias)];
+            ShakerFpga.ShakerFpga.Instance.伺服缸极性 = [.. Horizontal.Select(x => x.Polarity == Shaker.Model.Polarity.Positive), ..Vertical.Select(x => x.Polarity == Shaker.Model.Polarity.Positive)];
+            ShakerFpga.ShakerFpga.Instance.伺服开环 = [.. Horizontal.Select(x => x.OpenLoop), .. Vertical.Select(x => x.OpenLoop)];
+            ShakerFpga.ShakerFpga.Instance.伺服阀开环驱动 = [.. Horizontal.Select(x => x.OpenLoopDriver), .. Vertical.Select(x => x.OpenLoopDriver)];
         }
         public static ShakerChannelConfigViewModel Instance { get; } = new ShakerChannelConfigViewModel();
     }

+ 15 - 11
Service/ShakerService/ViewModel/ShakerConfigViewModel.cs

@@ -88,6 +88,10 @@ namespace ShakerService.ViewModel
         /// 外部输入通道数
         /// </summary>
         public byte OutSignalCount => CurrentModel.OutSignalCount;
+        /// <summary>
+        /// fifo中返回数据定义
+        /// </summary>
+        public int MaxResultChannelCount => CurrentModel.MaxResultChannelCount;
         private protected override void ReadModel()
         {
             base.ReadModel();
@@ -103,20 +107,20 @@ namespace ShakerService.ViewModel
         public override void SetFpga()
         {
             base.SetFpga();
-            ShakerFpga.ShakerFpga.Instance.采样率.Value = SampleRate;
-            ShakerFpga.ShakerFpga.Instance.采样间隔.Value = 1d / SampleRate;
-            ShakerFpga.ShakerFpga.Instance.LoopRate.Value = FpgaClock / SampleRate;
-            ShakerFpga.ShakerFpga.Instance.信号停止最大计数.Value = CurrentModel.MaxSignalStopCount;
-            ShakerFpga.ShakerFpga.Instance.信号停止计数间隔.Value = Tools.Tools.CalcInterval(CurrentModel.MaxSignalStopCount);
+            ShakerFpga.ShakerFpga.Instance.采样率 = SampleRate;
+            ShakerFpga.ShakerFpga.Instance.采样间隔 = 1d / SampleRate;
+            ShakerFpga.ShakerFpga.Instance.LoopRate = FpgaClock / SampleRate;
+            ShakerFpga.ShakerFpga.Instance.信号停止最大计数 = CurrentModel.MaxSignalStopCount;
+            ShakerFpga.ShakerFpga.Instance.信号停止计数间隔 = Tools.Tools.CalcInterval(CurrentModel.MaxSignalStopCount);
 
-            ShakerFpga.ShakerFpga.Instance.升台面最大计数.Value = CurrentModel.MaxRiseCount;
-            ShakerFpga.ShakerFpga.Instance.升台面计数间隔.Value = Tools.Tools.CalcInterval(CurrentModel.MaxRiseCount);
+            ShakerFpga.ShakerFpga.Instance.升台面最大计数 = CurrentModel.MaxRiseCount;
+            ShakerFpga.ShakerFpga.Instance.升台面计数间隔 = Tools.Tools.CalcInterval(CurrentModel.MaxRiseCount);
 
-            ShakerFpga.ShakerFpga.Instance.降台面最大计数.Value = CurrentModel.MaxDropCount;
-            ShakerFpga.ShakerFpga.Instance.降台面计数间隔.Value = Tools.Tools.CalcInterval(CurrentModel.MaxDropCount);
+            ShakerFpga.ShakerFpga.Instance.降台面最大计数 = CurrentModel.MaxDropCount;
+            ShakerFpga.ShakerFpga.Instance.降台面计数间隔 = Tools.Tools.CalcInterval(CurrentModel.MaxDropCount);
 
-            ShakerFpga.ShakerFpga.Instance.零位改最大计数.Value = CurrentModel.MaxZeroChangedCount;
-            ShakerFpga.ShakerFpga.Instance.零位改计数间隔.Value = Tools.Tools.CalcInterval(CurrentModel.MaxZeroChangedCount);
+            ShakerFpga.ShakerFpga.Instance.零位改最大计数 = CurrentModel.MaxZeroChangedCount;
+            ShakerFpga.ShakerFpga.Instance.零位改计数间隔 = Tools.Tools.CalcInterval(CurrentModel.MaxZeroChangedCount);
         }
     }
 }

+ 9 - 0
Service/ShakerService/ViewModel/ViewModelBase.cs

@@ -2,6 +2,7 @@
 {
     internal abstract class ViewModelBase
     {
+        public  bool IsStart { get; private protected set; }
         public void Init()
         {
 
@@ -13,6 +14,14 @@
         public virtual void SetFpga()
         {
 
+        }
+        public virtual void Start(CancellationToken token)
+        {
+
+        }
+        private protected virtual void SendData()
+        {
+
         }
     }
     [AttributeUsage(AttributeTargets.Class)]

+ 23 - 1
Service/ShakerService/ViewModel/ViewModelBase{TModel}.cs

@@ -1,4 +1,5 @@
-using System;
+using ShakerService.Tools;
+using System;
 using System.Collections.Generic;
 using System.Diagnostics.CodeAnalysis;
 using System.Linq;
@@ -29,6 +30,27 @@ namespace ShakerService.ViewModel
         private protected virtual void ReadModel()
         {
 
+        }
+        private int lastSendDataError = 0;
+        private protected override void SendData()
+        {
+            try
+            {
+                base.SendData();
+                Communication.Instance.Context.GetEvent<TModel>()?.Publish(this, CurrentModel);
+                if(lastSendDataError!=0)
+                {
+                    lastSendDataError = 0;
+                }
+            }
+            catch(Exception ex)
+            {
+                if(ex.HResult!=lastSendDataError)
+                {
+                    Log.Default.Error("Error send data to FPGA," + ex.Message);
+                    lastSendDataError = ex.HResult;
+                }
+            }
         }
         private protected virtual void UpModel(TModel model)
         {

+ 30 - 0
Shaker.Model/Models/FpgaVersionModel.cs

@@ -0,0 +1,30 @@
+using IModel;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Shaker.Models
+{
+    public sealed class FpgaVersionModel : IModel.BaseModel
+    {
+        public string BitstreamMD5 = string.Empty;
+        public string BitfileVersion = string.Empty;
+        public string SignatureRegister = string.Empty;
+        public string BitstreamVersion = string.Empty;
+        public string SignatureNames = string.Empty;
+        public string OSVersion = string.Empty;
+        public string FrameworkVersion = string.Empty;
+        public string MachineName = string.Empty;
+        public string Version = string.Empty;
+        public DateTime CreateTime = DateTime.MinValue;
+        public long MemoryUsage = 0;
+        public double CPUUsage = 0;
+
+        public override object Clone()
+        {
+            return this.CloneBase();
+        }
+    }
+}

+ 5 - 0
Shaker.Model/Models/ShakerChannelConfigModel.cs

@@ -43,6 +43,11 @@ namespace Shaker.Models
         /// 平衡缸通道
         /// </summary>
         public List<AOChannel> Balancing = new List<AOChannel>();
+        /// <summary>
+        /// 结果通道
+        /// </summary>
+
+        public List<ResultChannelType> ResultChannels = new List<ResultChannelType>();
         public override object Clone()
         {
             return this.CloneBase();

+ 1 - 0
Shaker.Model/Models/ShakerConfigModel.cs

@@ -75,6 +75,7 @@ namespace Shaker.Models
         /// Fpga主时钟
         /// </summary>
         public uint FpgaClock = 40_000_000;
+        public int MaxResultChannelCount = 64;
         public uint MaxRiseCount = 6000;
         public uint MaxDropCount = 6000;
         public uint MaxZeroChangedCount = 6000;

+ 66 - 0
Shaker.Model/ResultChannelType.cs

@@ -0,0 +1,66 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Shaker.Model
+{
+    /// <summary>
+    /// fifo中数据定义
+    /// </summary>
+    public enum ResultChannelType
+    {
+        /// <summary>
+        /// 实际位移(mm)
+        /// </summary>
+        [Description("ResultChannelTypActualDisplacement")]
+        ActualDisplacement,
+        /// <summary>
+        /// 给定位移(mm)
+        /// </summary>
+        [Description("ResultChannelTypeGivenDisplacement")]
+        GivenDisplacement,
+        /// <summary>
+        /// 伺服阀驱动(V)
+        /// </summary>
+        [Description("ResultChannelTypeServoValveDrive")]
+        ServoValveDrive,
+        /// <summary>
+        /// 平衡缸驱动(V)
+        /// </summary>
+        [Description("ResultChannelTypeBalanceCylinderDrive")]
+        BalanceCylinderDrive,
+        /// <summary>
+        /// 平衡缸驱动(MPa)
+        /// </summary>
+        [Description("ResultChannelTypeSupportingPressureDrive")]
+        SupportingPressureDrive,
+        /// <summary>
+        /// 六自由度给定位移(mm)
+        /// </summary>
+        [Description("ResultChannelTypeSixFreedomsGivenDisplacement")]
+        SixFreedomsGivenDisplacement,
+        /// <summary>
+        /// 当前位置(mm)
+        /// </summary>
+        [Description("ResultChannelTypeCurrentLocation")]
+        CurrentLocation,
+        /// <summary>
+        /// 加速度(g)
+        /// </summary>
+        [Description("ResultChannelTypeAcceleration")]
+        Acceleration,
+        /// <summary>
+        /// 外部输入(V)
+        /// </summary>
+        [Description("ResultChannelTypeExternalInput")]
+        ExternalInput,
+        /// <summary>
+        /// 未定义
+        /// </summary>
+        [Description("ResultChannelTypeNone")]
+        None,
+    }
+}

+ 37 - 0
Shaker.Model/Tools/Tools.cs

@@ -20,5 +20,42 @@ namespace Shaker.Tools
         {
             return MessagePackSerializer.Deserialize<T>(data, options);
         }
+        /// <summary>
+        /// 压缩数据包
+        /// </summary>
+        /// <param name="arrays"></param>
+        /// <returns></returns>
+        public static byte[] CompressionBytes(byte[] arrays)
+        {
+            if (arrays == null || arrays.Length == 0) return new byte[0];
+            using (MemoryStream ms = new MemoryStream())
+            {
+                using (System.IO.Compression.DeflateStream ds = new System.IO.Compression.DeflateStream(ms, System.IO.Compression.CompressionLevel.SmallestSize, true))
+                {
+                    ds.Write(arrays, 0, arrays.Length);
+                }
+                return ms.ToArray();
+            }
+        }
+        /// <summary>
+        /// 解压数据包
+        /// </summary>
+        /// <param name="arrays"></param>
+        /// <returns></returns>
+        public static byte[] DecompressionBytes(byte[] arrays)
+        {
+            if (arrays == null || arrays.Length == 0) return new byte[0];
+            using (MemoryStream ms = new MemoryStream(arrays))
+            {
+                using (System.IO.Compression.DeflateStream ds = new System.IO.Compression.DeflateStream(ms, System.IO.Compression.CompressionMode.Decompress, true))
+                {
+                    using (MemoryStream memoryStream = new MemoryStream())
+                    {
+                        ds.CopyTo(memoryStream);
+                        return memoryStream.ToArray();
+                    }
+                }
+            }
+        }
     }
 }

+ 1 - 0
Shaker.Model/Topic.cs

@@ -19,5 +19,6 @@ namespace Shaker.Model
         public const string LOG="Log";
 
         public const string MIANWINDOWTOAST = "MainWindowToast";
+        public const string DATA = "Data";
     }
 }