luo пре 4 недеља
родитељ
комит
92b4255370

+ 5 - 61
Avalonia/ShakerApp/ViewModels/MainPage/OutSignalMainPageViewModel.cs

@@ -18,50 +18,13 @@ namespace ShakerApp.ViewModels
     {
         public MainPageType PageType => MainPageType.OutSignal;
 
-        [AllowNull]
-        private  TimeDomainMenuViewModel selectedType;
+        public ViewModels.AnalogSignalPreviewViewModel AnalogSignal { get; } = new AnalogSignalPreviewViewModel()
+        {
+            AttachTitle = MainPageType.OutSignal.Description(),
+        };
 
         private OutSignalMainPageViewModel()
         {
-            Enum.GetValues<TimeDomainType>().ToList()
-                .ForEach(x =>
-                {
-                    Menu.Add(new TimeDomainMenuViewModel()
-                    {
-                        TimeDomainType = x,
-                        IsEnabled = true,
-                        Unit = x.GetUnit(),
-                    });
-                });
-            if(Menu.Count>0)
-            {
-                SelectedType = Menu.First();
-            }
-            PlotModel.Axes.Add(new OxyPlot.Axes.TimeSpanAxis()
-            {
-                Title = App.Current?.FindResource("Time") + "",
-                Unit = "s",
-                Position = OxyPlot.Axes.AxisPosition.Bottom,
-                MaximumPadding =0,
-                MinimumPadding =0,
-                MajorGridlineStyle = OxyPlot.LineStyle.Solid,
-            });
-            PlotModel.Axes.Add(new OxyPlot.Axes.LinearAxis()
-            {
-                Title=App.Current?.FindResource("Ampt")+ "",
-                Unit=SelectedType.Unit,
-                Position = OxyPlot.Axes.AxisPosition.Left,
-                MajorGridlineStyle = OxyPlot.LineStyle.Solid,
-            });
-            PlotModel.Title = $"{App.Current?.FindResource(MainPageType.OutSignal.Description())}-{App.Current?.FindResource(SelectedType.Key)}";
-            GetEvent(ShakerSettingViewModel.LANGUAGECHANGEDEVENT).Subscrip((_, _) =>
-            {
-                PlotModel.InvalidatePlot(false);
-                PlotModel.Title = $"{App.Current?.FindResource(MainPageType.OutSignal.Description())}-{App.Current?.FindResource(SelectedType.Key)}";
-                PlotModel.Axes[0].Title = App.Current?.FindResource("Time") + "";
-                PlotModel.Axes[1].Title = Title = App.Current?.FindResource("Ampt") + "";
-                PlotModel.InvalidatePlot(true);
-            });
             
         }
         static OutSignalMainPageViewModel()
@@ -80,26 +43,7 @@ namespace ShakerApp.ViewModels
         {
         }
 
-        public AvaloniaList<TimeDomainMenuViewModel> Menu { get; } = new AvaloniaList<TimeDomainMenuViewModel>();
-        public TimeDomainMenuViewModel SelectedType 
-        {
-            get => selectedType;
-            set
-            {
-                SetProperty(ref selectedType, value);
-                foreach(var val in Menu)
-                {
-                    val.IsChecked = val.TimeDomainType == value.TimeDomainType;
-                }
-                PlotModel.Title = $"{App.Current?.FindResource(MainPageType.OutSignal.Description())}-{App.Current?.FindResource(value.Key)}";
-                if (PlotModel.Axes.Count < 2) return;
-                PlotModel.InvalidatePlot(false);
-                PlotModel.Axes[1].Unit = value.Unit;
-                PlotModel.InvalidatePlot(true);
-            }
-        }
-        public OxyPlot.PlotController Controller { get; private set; } = new OxyPlot.PlotController();
-        public OxyPlot.PlotModel PlotModel { get; private set; } = new OxyPlot.PlotModel();
+        
         public static OutSignalMainPageViewModel Instance { get; } = new OutSignalMainPageViewModel();
     }
 }

+ 4 - 4
Avalonia/ShakerApp/ViewModels/MainPage/TimeDomainMenuViewModel.cs

@@ -4,16 +4,16 @@ using ShakerApp.Tools;
 
 namespace ShakerApp.ViewModels
 {
-    public sealed class TimeDomainMenuViewModel:ViewModelBase<IModel>
+    public sealed class TimeDomainMenuViewModel: CommunityToolkit.Mvvm.ComponentModel.ObservableObject
     {
-        private TimeDomainType timeDomainType = Models.TimeDomainType.Displacement;
+        private AnalogType analogType = AnalogType.Displacement;
         private bool isEnabled = true;
         private string unit = string.Empty;
         private bool isChecked = false;
 
-        public Models.TimeDomainType TimeDomainType { get => timeDomainType; set =>SetProperty(ref timeDomainType , value); }
+        public AnalogType AnalogType { get => analogType; set =>SetProperty(ref analogType , value); }
         public bool IsEnabled { get => isEnabled; set =>SetProperty(ref isEnabled , value); }
-        public string Key => TimeDomainType.Description();
+        public string Key => AnalogType.Description();
         public string Unit { get => unit; set =>SetProperty(ref unit , value); }
         public bool IsChecked { get => isChecked; set =>SetProperty(ref isChecked , value); }
 

+ 46 - 8
Avalonia/ShakerApp/ViewModels/SignalPreview/AnalogSignalPreviewViewModel.cs

@@ -17,9 +17,18 @@ namespace ShakerApp.ViewModels
 {
     public class AnalogSignalPreviewViewModel:ViewModelBase<IModel>,IDataPreview
     {
+        public string AttachTitle 
+        { 
+            get => attachTitle;
+            set
+            {
+                if (attachTitle == value) return;
+                attachTitle = value;
+                UpdatePlotTitle(SelectedAnalog);
+            }
+        }
         List<OxyPlot.Series.LineSeries> lineSeries = new List<OxyPlot.Series.LineSeries>();
         private object locker = new object();
-        public AvaloniaList<KeyValuePair<string, AnalogType>> AllAnalogTypes { get; } = new AvaloniaList<KeyValuePair<string, AnalogType>>();
         public AvaloniaList<ViewModels.StatisticsViewModel> Statistics { get; } = new AvaloniaList<StatisticsViewModel>();
         private AnalogType selectedAnalog;
         private bool canChangedAnalog = true;
@@ -49,7 +58,7 @@ namespace ShakerApp.ViewModels
                 MajorGridlineStyle = OxyPlot.LineStyle.Solid,
                 Position = OxyPlot.Axes.AxisPosition.Left,
             });
-            PlotModel.Title = App.Current?.FindResource("ValveDriveSignal") + "";
+            UpdatePlotTitle(lasttype);
             PlotModel.Legends.Add(new OxyPlot.Legends.Legend()
             {
                 ShowInvisibleSeries = true,
@@ -78,21 +87,26 @@ namespace ShakerApp.ViewModels
             {
                 lock(locker)
                 {
-                    AllAnalogTypes.Clear();
+                    Menu.Clear();
                     ShakerConfigViewModel.Instance.AnalogSignals
                     .DistinctBy(x=>x.Value.AnalogType)
-                    //.Where(x=>x.Value.AnalogType != AnalogType.DivideAcceleration)
                     .ToList()
                         .ForEach(x =>
                         {
-                            AllAnalogTypes.Add(new KeyValuePair<string, AnalogType>(x.Value.AnalogType.Description(), x.Value.AnalogType));
+                            Menu.Add(new TimeDomainMenuViewModel()
+                            {
+                                IsChecked = false,
+                                IsEnabled = true,
+                                AnalogType = x.Value.AnalogType,
+                                Unit = x.Value.Unit,
+                            });
                         });
                     if (CanChangedAnalog)
                     {
-                        int index = AllAnalogTypes.ToList().FindIndex(x => x.Value == lasttype);
+                        int index = Menu.ToList().FindIndex(x => x.AnalogType == lasttype);
                         if (index == -1)
                         {
-                            SelectedAnalog = AllAnalogTypes.First().Value;
+                            SelectedAnalog = Menu.First().AnalogType;
                         }
                         else
                         {
@@ -105,12 +119,32 @@ namespace ShakerApp.ViewModels
                     }
                 }
             });
+
+
+            GetEvent(ViewModels.ShakerSettingViewModel.LANGUAGECHANGEDEVENT).Subscrip((_, _) =>
+            {
+                PlotModel.InvalidatePlot(false);
+                PlotModel.Axes[0].Title = App.Current?.FindResource("Time") + "";
+                PlotModel.Axes[1].Title = App.Current?.FindResource("Ampt") + "";
+                UpdatePlotTitle(SelectedAnalog);
+                var config = ShakerConfigViewModel.Instance.Model.AnalogSignalConfigs.First(x => x.AnalogType == SelectedAnalog);
+                for(int i=0;i<PlotModel.Series.Count;i++)
+                {
+                    PlotModel.Series[i].Title = App.Current?.FindResource(config.Name) + "";
+                }
+            });
         }
         [AllowNull]
         public Control Control { get; }
         private AnalogType lasttype = AnalogType.Displacement;
         private bool statisticsVisibily = true;
+        private string attachTitle = string.Empty;
 
+        private void UpdatePlotTitle(AnalogType analogType)
+        {
+            PlotModel.Title = string.IsNullOrEmpty(AttachTitle) ? App.Current?.FindResource(analogType.Description()) + "" : $"{App.Current?.FindResource(AttachTitle)}-{App.Current?.FindResource(analogType.Description())}";
+        }
+        public AvaloniaList<TimeDomainMenuViewModel> Menu { get; } = new AvaloniaList<TimeDomainMenuViewModel>();
         public AnalogSignalPreviewViewModel(Shaker.Models.AnalogType analogType,bool createcontrol = false):this(createcontrol)
         {
             lasttype = analogType;
@@ -132,6 +166,10 @@ namespace ShakerApp.ViewModels
                 lineSeries.Clear();
                 PlotModel.Series.Clear();
                 Statistics.Clear();
+                for(int i=0;i<Menu.Count;i++)
+                {
+                    Menu[i].IsChecked = Menu[i].AnalogType == type;
+                }
                 var config = ShakerConfigViewModel.Instance.Model.AnalogSignalConfigs.First(x => x.AnalogType == type);
                 PlotModel.Axes[1].Unit = config.Unit;
                 var allconfig = ShakerConfigViewModel.Instance.Model.AnalogSignalConfigs.Where(x => x.AnalogType == type).ToList();
@@ -150,7 +188,7 @@ namespace ShakerApp.ViewModels
                     lineSeries.Add(series);
                 }
                 PlotModel.InvalidatePlot(false);
-                PlotModel.Title = App.Current?.FindResource(type.Description()) + "";
+                UpdatePlotTitle(type);
                 lineSeries.ForEach(x => PlotModel.Series.Add(x));
                 PlotModel.InvalidatePlot(true);
             }

+ 5 - 66
Avalonia/ShakerApp/Views/MainPage/OutSignalMainPage.axaml

@@ -18,72 +18,11 @@
     <Grid ColumnDefinitions="150,*">
         <StackPanel Grid.Column="0">
             <view:ShakerMiniStatusControl />
-            <view:OilMinView />
+            <view:OilMinView IsVisible="{Binding Source={x:Static vm:OilSourceStatusViewModel.Instance}, Path=IsEnabled}" />
         </StackPanel>
-        <Grid Grid.Column="1">
-            <oxy:PlotView
-                Background="Transparent"
-                Controller="{Binding Controller}"
-                Model="{Binding PlotModel}" />
-            <Button
-                HorizontalAlignment="Right"
-                VerticalAlignment="Top"
-                Classes="Basic">
-                <PathIcon Data="{StaticResource SettingGeometry}" />
-                <Button.Flyout>
-                    <Flyout ShowMode="Standard">
-                        <suki:GlassCard>
-                            <suki:GroupBox Header="{DynamicResource SelectSignalType}">
-                                <ItemsControl ItemsSource="{Binding Menu}">
-                                    <ItemsControl.ItemTemplate>
-                                        <DataTemplate>
-                                            <Grid
-                                                Name="item"
-                                                Height="{StaticResource ItemHeight}"
-                                                x:DataType="vm:TimeDomainMenuViewModel"
-                                                Background="Transparent"
-                                                Cursor="Hand">
-                                                <Interaction.Behaviors>
-                                                    <EventTriggerBehavior EventName="PointerReleased">
-                                                        <ChangePropertyAction
-                                                            PropertyName="SelectedType"
-                                                            TargetObject="{Binding Source={x:Static vm:OutSignalMainPageViewModel.Instance}}"
-                                                            Value="{Binding #item.DataContext}" />
-                                                    </EventTriggerBehavior>
-                                                </Interaction.Behaviors>
-                                                <Grid.Styles>
-                                                    <Style Selector="Grid:pointerover">
-                                                        <Setter Property="Background" Value="LightGray" />
-                                                    </Style>
-                                                </Grid.Styles>
-                                                <Grid.ColumnDefinitions>
-                                                    <ColumnDefinition Width="30" />
-                                                    <ColumnDefinition Width="*" />
-                                                </Grid.ColumnDefinitions>
-                                                <PathIcon Data="{x:Static suki:Icons.Check}" IsVisible="{Binding IsChecked}" />
-                                                <Line
-                                                    HorizontalAlignment="Right"
-                                                    VerticalAlignment="Center"
-                                                    Stroke="LightGray"
-                                                    StrokeThickness="2"
-                                                    StartPoint="0,4"
-                                                    EndPoint="0,24" />
-                                                <TextBlock
-                                                    Grid.Column="1"
-                                                    Margin="10,0,0,0"
-                                                    HorizontalAlignment="Left"
-                                                    VerticalAlignment="Center"
-                                                    Text="{local:ResourceBinding Key}" />
-                                            </Grid>
-                                        </DataTemplate>
-                                    </ItemsControl.ItemTemplate>
-                                </ItemsControl>
-                            </suki:GroupBox>
-                        </suki:GlassCard>
-                    </Flyout>
-                </Button.Flyout>
-            </Button>
-
-        </Grid>
+        <ContentControl
+            Grid.Column="1"
+            Content="{Binding Content, Converter={StaticResource Type2ViewConverter}}"
+            DataContext="{Binding Source={x:Static vm:OutSignalMainPageViewModel.Instance}, Path=AnalogSignal}" />
     </Grid>
 </UserControl>

+ 1 - 1
Avalonia/ShakerApp/Views/MainPage/RandomMainPage.axaml

@@ -19,7 +19,7 @@
         <ScrollViewer Grid.Column="0">
             <StackPanel>
                 <view:ShakerMiniStatusControl />
-                <view:OilMinView />
+                <view:OilMinView IsVisible="{Binding Source={x:Static vm:OilSourceStatusViewModel.Instance}, Path=IsEnabled}" />
                 <Expander ExpandDirection="Down" IsExpanded="True">
                     <Expander.Header>
                         <TextBlock

+ 1 - 1
Avalonia/ShakerApp/Views/MainPage/SineMainPage.axaml

@@ -18,7 +18,7 @@
         <ScrollViewer Grid.Column="0">
             <StackPanel>
                 <view:ShakerMiniStatusControl />
-                <view:OilMinView />
+                <view:OilMinView IsVisible="{Binding Source={x:Static vm:OilSourceStatusViewModel.Instance}, Path=IsEnabled}" />
                 <Expander ExpandDirection="Down">
                     <Expander.Header>
                         <TextBlock

+ 72 - 15
Avalonia/ShakerApp/Views/SignalPreview/AnalogSignalPreviewView.axaml

@@ -6,6 +6,7 @@
     xmlns:local="using:ShakerApp"
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
     xmlns:oxy="http://oxyplot.org/avalonia"
+    xmlns:suki="https://github.com/kikipoulet/SukiUI"
     xmlns:vm="using:ShakerApp.ViewModels"
     d:DesignHeight="450"
     d:DesignWidth="800"
@@ -20,25 +21,81 @@
             HorizontalAlignment="Right"
             VerticalAlignment="Top"
             Orientation="Horizontal">
-            <StackPanel IsVisible="{Binding CanChangedAnalog}" Orientation="Horizontal">
-                <TextBlock VerticalAlignment="Center" Text="{DynamicResource SelectSignalType}" />
-                <ComboBox
-                    Width="160"
-                    ItemsSource="{Binding AllAnalogTypes}"
-                    SelectedValue="{Binding Path=SelectedAnalog}"
-                    SelectedValueBinding="{Binding Value}">
-                    <ComboBox.ItemTemplate>
-                        <DataTemplate>
-                            <TextBlock Text="{local:ResourceBinding Key}" />
-                        </DataTemplate>
-                    </ComboBox.ItemTemplate>
-
-                </ComboBox>
-            </StackPanel>
             <StackPanel Margin="10,0,0,0" Orientation="Horizontal">
                 <TextBlock VerticalAlignment="Center" Text="{DynamicResource Statistics}" />
                 <ToggleSwitch IsChecked="{Binding StatisticsVisibily, Mode=TwoWay}" />
             </StackPanel>
+
+            <Button
+                HorizontalAlignment="Right"
+                VerticalAlignment="Top"
+                Classes="Basic"
+                IsVisible="{Binding CanChangedAnalog}">
+                <PathIcon Data="{StaticResource SettingGeometry}" />
+                <Button.Flyout>
+                    <Flyout ShowMode="Standard">
+                        <suki:GlassCard
+                            Background="Black"
+                            CornerRadius="10"
+                            Opacity="1"
+                            OpacityMask="Black">
+                            <suki:GroupBox>
+                                <suki:GroupBox.Header>
+                                    <TextBlock Foreground="White" Text="{DynamicResource SelectSignalType}" />
+                                </suki:GroupBox.Header>
+                                <ItemsControl ItemsSource="{Binding Menu}">
+                                    <ItemsControl.ItemTemplate>
+                                        <DataTemplate>
+                                            <Grid
+                                                Name="item"
+                                                Height="{StaticResource ItemHeight}"
+                                                x:DataType="vm:TimeDomainMenuViewModel"
+                                                Background="Transparent"
+                                                Cursor="Hand">
+                                                <Interaction.Behaviors>
+                                                    <EventTriggerBehavior EventName="PointerReleased">
+                                                        <ChangePropertyAction
+                                                            PropertyName="SelectedAnalog"
+                                                            TargetObject="{Binding $parent[Button].DataContext}"
+                                                            Value="{Binding #item.DataContext.AnalogType}" />
+                                                    </EventTriggerBehavior>
+                                                </Interaction.Behaviors>
+                                                <Grid.Styles>
+                                                    <Style Selector="Grid:pointerover">
+                                                        <Setter Property="Background" Value="LightGray" />
+                                                    </Style>
+                                                </Grid.Styles>
+                                                <Grid.ColumnDefinitions>
+                                                    <ColumnDefinition Width="30" />
+                                                    <ColumnDefinition Width="*" />
+                                                </Grid.ColumnDefinitions>
+                                                <PathIcon
+                                                    Data="{x:Static suki:Icons.Check}"
+                                                    Foreground="White"
+                                                    IsVisible="{Binding IsChecked}" />
+                                                <Line
+                                                    HorizontalAlignment="Right"
+                                                    VerticalAlignment="Center"
+                                                    Stroke="LightGray"
+                                                    StrokeThickness="2"
+                                                    StartPoint="0,4"
+                                                    EndPoint="0,24" />
+                                                <TextBlock
+                                                    Grid.Column="1"
+                                                    Margin="10,0,0,0"
+                                                    HorizontalAlignment="Left"
+                                                    VerticalAlignment="Center"
+                                                    Foreground="White"
+                                                    Text="{local:ResourceBinding Key}" />
+                                            </Grid>
+                                        </DataTemplate>
+                                    </ItemsControl.ItemTemplate>
+                                </ItemsControl>
+                            </suki:GroupBox>
+                        </suki:GlassCard>
+                    </Flyout>
+                </Button.Flyout>
+            </Button>
         </StackPanel>
         <Border
             Margin="80,60"

+ 15 - 9
NIFPGA/FPGAArrayFXPReadProperty.cs

@@ -1,4 +1,5 @@
 using FxpConvert.Common;
+using System.Runtime.CompilerServices;
 
 namespace NIFPGA
 {
@@ -7,7 +8,7 @@ namespace NIFPGA
         Interop.NiFpgaDll_ReadArrayU8 Read;
         private NiFpga_FxpTypeInfo _TypeInfo;
         private IFxpConvert _Convert;
-        private byte[] tempbuffer = new byte[0];
+        private ulong[] tempbuffer = new ulong[0];
         private ulong[] tempvalue = new ulong[0];
         private double[] doubles = new double[0];
         internal FPGAArrayFXPReadProperty(FPGASession session, uint indicator, uint count, NiFpga_FxpTypeInfo typeInfo, IFxpConvert convert) : base(session, indicator, true)
@@ -17,24 +18,29 @@ namespace NIFPGA
             tempvalue = new ulong[count];
             doubles = new double[count];
             _TypeInfo = typeInfo;
-            tempbuffer = new byte[(int)Math.Ceiling(typeInfo.wordLength * count / 8.0)];
+            tempbuffer = new ulong[(int)Math.Ceiling(typeInfo.wordLength * count / (8*8.0))];
             Read = _Session.GetDelegate<Interop.NiFpgaDll_ReadArrayU8>();
         }
 
         private double[] GetData()
         {
-            lock (Read)
+            _Session.CheckResult(Read(_Session.Session, Indicator, ref Unsafe.As<ulong, byte>(ref tempbuffer[0]), (uint)tempbuffer.Length * 8));
+
+            int tempdatalen = Unsafe.SizeOf<ulong>() * 8;
+            ulong mask = (1ul << _TypeInfo.wordLength) - 1;
+            for (int i = 0; i < Count; i++)
             {
-                _Session.CheckResult(Read(_Session.Session, Indicator, ref tempbuffer[0], (uint)tempbuffer.Length));
-                string s = string.Empty;
-                for (int i = 0; i < tempbuffer.Length; i++)
+                int index = i * _TypeInfo.wordLength / tempdatalen;
+                int bitindex = tempdatalen - (i * _TypeInfo.wordLength % tempdatalen);
+                if (bitindex >= _TypeInfo.wordLength)
                 {
-                    s += tempbuffer[i].ToString("b").PadLeft(8, '0');
+                    tempvalue[i] = (tempbuffer[index] >> (bitindex - _TypeInfo.wordLength)) & mask;
                 }
-                for (int i = 0; i < tempvalue.Length; i++)
+                else
                 {
-                    tempvalue[i] = System.Convert.ToUInt64(s.Substring(i * _TypeInfo.wordLength, _TypeInfo.wordLength), 2);
+                    tempvalue[i] = (((tempbuffer[index] & ((1ul << bitindex) - 1)) << (_TypeInfo.wordLength - bitindex)) | (tempbuffer[index + 1] >> (tempdatalen - (_TypeInfo.wordLength - bitindex))));
                 }
+            }
 
                 _Convert.FxpConvertToDouble(ref tempvalue[0], _TypeInfo, ref doubles[0], Count);
                 return doubles;

+ 27 - 24
NIFPGA/FPGAArrayFXPWriteProperty.cs

@@ -1,5 +1,6 @@
 using FxpConvert.Common;
 using System.Reflection;
+using System.Runtime.CompilerServices;
 
 namespace NIFPGA
 {
@@ -9,34 +10,39 @@ namespace NIFPGA
         Interop.NiFpgaDll_WriteArrayU8 Write;
         private NiFpga_FxpTypeInfo _TypeInfo;
         private IFxpConvert _Convert;
-        private byte[] tempbuffer = new byte[0];
-        private ulong[] tempvalue = new ulong[0];
+        private ulong[] tempbuffer = new ulong[0];
         private double[] doubles = new double[0];
+        private ulong[] tempvalue = new ulong[0];
         internal FPGAArrayFXPWriteProperty(FPGASession session, uint indicator, uint count,NiFpga_FxpTypeInfo typeInfo, IFxpConvert convert) : base(session, indicator,false)
         {
             _Convert = convert;
             Count = count;
-            tempvalue = new ulong[count];
             doubles = new double[count];
+            tempvalue = new ulong[count];
             _TypeInfo = typeInfo;
-            tempbuffer = new byte[(int)Math.Ceiling(typeInfo.wordLength*count / 8.0)];
+            tempbuffer = new ulong[(int)Math.Ceiling(typeInfo.wordLength * count / (Unsafe.SizeOf<ulong>() * 8.0))];
             Read = _Session.GetDelegate<Interop.NiFpgaDll_ReadArrayU8>();
             Write = _Session.GetDelegate<Interop.NiFpgaDll_WriteArrayU8>();
         }
         private double[] GetData()
         {
-            lock (Read)
+            _Session.CheckResult(Read(_Session.Session, Indicator, ref Unsafe.As<ulong,byte>(ref tempbuffer[0]), (uint)tempbuffer.Length*8));
+
+            int tempdatalen = Unsafe.SizeOf<ulong>() * 8;
+            ulong mask = (1ul << _TypeInfo.wordLength) - 1;
+            for (int i = 0; i < Count; i++)
             {
-                _Session.CheckResult(Read(_Session.Session, Indicator, ref tempbuffer[0], (uint)tempbuffer.Length));
-                string s = string.Empty;
-                for (int i = 0; i < tempbuffer.Length; i++)
+                int index = i * _TypeInfo.wordLength / tempdatalen;
+                int bitindex = tempdatalen - (i * _TypeInfo.wordLength % tempdatalen);
+                if (bitindex >= _TypeInfo.wordLength)
                 {
-                    s += tempbuffer[i].ToString("b").PadLeft(8, '0');
+                    tempvalue[i] = (tempbuffer[index] >> (bitindex - _TypeInfo.wordLength)) & mask;
                 }
-                for (int i = 0; i < tempvalue.Length; i++)
+                else
                 {
-                    tempvalue[i] = System.Convert.ToUInt64(s.Substring(i * _TypeInfo.wordLength, _TypeInfo.wordLength), 2);
+                    tempvalue[i] = (((tempbuffer[index] & ((1ul << bitindex) - 1)) << (_TypeInfo.wordLength - bitindex)) | (tempbuffer[index + 1] >> (tempdatalen - (_TypeInfo.wordLength - bitindex))));
                 }
+            }
 
                 _Convert.FxpConvertToDouble(ref tempvalue[0], _TypeInfo, ref doubles[0], Count);
                 return doubles;
@@ -44,21 +50,18 @@ namespace NIFPGA
         }
         private void SetData(double[] values)
         {
-            lock (Read)
+            if (values.Length != Count) return;
+            _Convert.DoubleConvertToDxp(ref values[0], _TypeInfo, ref tempvalue[0], Count);
+            string s = string.Empty;
+            for(int i=0;i<tempvalue.Length;i++)
             {
-                if (values.Length != Count) return;
-                _Convert.DoubleConvertToDxp(ref values[0], _TypeInfo, ref tempvalue[0], Count);
-                string s = string.Empty;
-                for (int i = 0; i < tempvalue.Length; i++)
-                {
-                    s += tempvalue[i].ToString("b").PadLeft(64, '0').Substring(64 - _TypeInfo.wordLength, _TypeInfo.wordLength);
-                }
-                for (int i = 0; i < tempbuffer.Length; i++)
-                {
-                    tempbuffer[i] = System.Convert.ToByte(s.Substring(i * 8, Math.Min(8, s.Length - i * 8)), 2);
-                }
-                _Session.CheckResult(Write(_Session.Session, Indicator, ref tempbuffer[0], (uint)tempbuffer.Length));
+                s += tempvalue[i].ToString("b").PadLeft(64, '0').Substring(64 - _TypeInfo.wordLength, _TypeInfo.wordLength);
+            }
+            for(int i=0;i< tempbuffer.Length;i++)
+            {
+                tempbuffer[i] = System.Convert.ToByte(s.Substring(i * 8, Math.Min(8, s.Length - i * 8)),2);
             }
+            _Session.CheckResult(Write(_Session.Session,Indicator, ref tempbuffer[0], (uint)tempbuffer.Length));
         }
         public uint Count { get; }
         public double[] Value { get => GetData(); set => SetData(value); }

+ 1 - 1
NIFPGA/FPGAArrayReadProperty.cs

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