From ee9d2420b59f26da329b965ca0f7e29954dcb5cd Mon Sep 17 00:00:00 2001 From: idwpan <51302919+idwpan@users.noreply.github.com> Date: Sat, 16 Aug 2025 12:28:10 -0400 Subject: [PATCH 1/8] Add settings dialog to configure sample limits --- .../LogicAnalyzer/Classes/GeneralSettings.cs | 8 +++ .../Dialogs/GeneralSettingsDialog.axaml | 22 +++++++ .../Dialogs/GeneralSettingsDialog.axaml.cs | 44 +++++++++++++ .../LogicAnalyzer/LogicAnalyzer.csproj | 13 ++-- .../LogicAnalyzer/MainWindow.axaml | 7 +- .../LogicAnalyzer/MainWindow.axaml.cs | 65 +++++++++++++++---- 6 files changed, 137 insertions(+), 22 deletions(-) create mode 100644 Software/LogicAnalyzer/LogicAnalyzer/Classes/GeneralSettings.cs create mode 100644 Software/LogicAnalyzer/LogicAnalyzer/Dialogs/GeneralSettingsDialog.axaml create mode 100644 Software/LogicAnalyzer/LogicAnalyzer/Dialogs/GeneralSettingsDialog.axaml.cs diff --git a/Software/LogicAnalyzer/LogicAnalyzer/Classes/GeneralSettings.cs b/Software/LogicAnalyzer/LogicAnalyzer/Classes/GeneralSettings.cs new file mode 100644 index 00000000..2b6a73ee --- /dev/null +++ b/Software/LogicAnalyzer/LogicAnalyzer/Classes/GeneralSettings.cs @@ -0,0 +1,8 @@ +namespace LogicAnalyzer.Classes +{ + public class GeneralSettings + { + public int MinSamples { get; set; } = 10; + public int MaxSamples { get; set; } = 10000; + } +} diff --git a/Software/LogicAnalyzer/LogicAnalyzer/Dialogs/GeneralSettingsDialog.axaml b/Software/LogicAnalyzer/LogicAnalyzer/Dialogs/GeneralSettingsDialog.axaml new file mode 100644 index 00000000..ab855341 --- /dev/null +++ b/Software/LogicAnalyzer/LogicAnalyzer/Dialogs/GeneralSettingsDialog.axaml @@ -0,0 +1,22 @@ + + + + Min samples: + + Max samples: + + + + + + + + diff --git a/Software/LogicAnalyzer/LogicAnalyzer/Dialogs/GeneralSettingsDialog.axaml.cs b/Software/LogicAnalyzer/LogicAnalyzer/Dialogs/GeneralSettingsDialog.axaml.cs new file mode 100644 index 00000000..88694613 --- /dev/null +++ b/Software/LogicAnalyzer/LogicAnalyzer/Dialogs/GeneralSettingsDialog.axaml.cs @@ -0,0 +1,44 @@ +using Avalonia.Controls; +using LogicAnalyzer.Extensions; +using System; + +namespace LogicAnalyzer.Dialogs +{ + public partial class GeneralSettingsDialog : Window + { + public int MinSamples { get; set; } + public int MaxSamples { get; set; } + + public GeneralSettingsDialog() + { + InitializeComponent(); + btnAccept.Click += BtnAccept_Click; + btnCancel.Click += BtnCancel_Click; + } + + protected override void OnOpened(EventArgs e) + { + base.OnOpened(e); + this.FixStartupPosition(); + nudMin.Value = MinSamples; + nudMax.Value = MaxSamples; + } + + private void BtnCancel_Click(object? sender, Avalonia.Interactivity.RoutedEventArgs e) + { + Close(false); + } + + private async void BtnAccept_Click(object? sender, Avalonia.Interactivity.RoutedEventArgs e) + { + if (nudMax.Value < nudMin.Value) + { + await this.ShowError("Invalid settings", "Max samples must be greater than Min samples."); + return; + } + MinSamples = (int)nudMin.Value; + MaxSamples = (int)nudMax.Value; + Close(true); + } + } +} diff --git a/Software/LogicAnalyzer/LogicAnalyzer/LogicAnalyzer.csproj b/Software/LogicAnalyzer/LogicAnalyzer/LogicAnalyzer.csproj index 54dfe14f..ce354e03 100644 --- a/Software/LogicAnalyzer/LogicAnalyzer/LogicAnalyzer.csproj +++ b/Software/LogicAnalyzer/LogicAnalyzer/LogicAnalyzer.csproj @@ -48,11 +48,14 @@ - - - SelectedRegionDialog.axaml - - + + + SelectedRegionDialog.axaml + + + GeneralSettingsDialog.axaml + + diff --git a/Software/LogicAnalyzer/LogicAnalyzer/MainWindow.axaml b/Software/LogicAnalyzer/LogicAnalyzer/MainWindow.axaml index 2500f211..a2dea9c4 100644 --- a/Software/LogicAnalyzer/LogicAnalyzer/MainWindow.axaml +++ b/Software/LogicAnalyzer/LogicAnalyzer/MainWindow.axaml @@ -17,9 +17,10 @@ - - - + + + + diff --git a/Software/LogicAnalyzer/LogicAnalyzer/MainWindow.axaml.cs b/Software/LogicAnalyzer/LogicAnalyzer/MainWindow.axaml.cs index d11d5dd1..eaa195af 100644 --- a/Software/LogicAnalyzer/LogicAnalyzer/MainWindow.axaml.cs +++ b/Software/LogicAnalyzer/LogicAnalyzer/MainWindow.axaml.cs @@ -61,7 +61,8 @@ public partial class MainWindow : PersistableWindowBase List knownDevices = new List(); KnownDevice? currentKnownDevice = null; - ProfilesSet? profiles; + ProfilesSet? profiles; + GeneralSettings generalSettings; public bool PreviewPinned { get { return samplePreviewer.Pinned; } set { samplePreviewer.Pinned = value; } } @@ -118,9 +119,10 @@ public MainWindow() mnuSave.Click += mnuSave_Click; mnuExit.Click += MnuExit_Click; mnuExport.Click += MnuExport_Click; - mnuNetSettings.Click += MnuNetSettings_Click; - mnuDocs.Click += MnuDocs_Click; - mnuAbout.Click += MnuAbout_Click; + mnuNetSettings.Click += MnuNetSettings_Click; + mnuGeneralSettings.Click += MnuGeneralSettings_Click; + mnuDocs.Click += MnuDocs_Click; + mnuAbout.Click += MnuAbout_Click; AddHandler(InputElement.KeyDownEvent, MainWindow_KeyDown, handledEventsToo: true); pnlPower.PointerPressed += (o, e) => GetPowerStatus(); @@ -160,8 +162,18 @@ public MainWindow() Task.Run(() => LoadKnownDevices()); - RefreshPorts(); - LoadProfiles(); + RefreshPorts(); + LoadProfiles(); + + generalSettings = AppSettingsManager.GetSettings("GeneralSettings.json") ?? new GeneralSettings(); + tkInScreen.Minimum = generalSettings.MinSamples; + tkInScreen.Maximum = generalSettings.MaxSamples; + lblMinSamples.Text = generalSettings.MinSamples.ToString(); + lblMaxSamples.Text = generalSettings.MaxSamples.ToString(); + if (tkInScreen.Value < tkInScreen.Minimum) + tkInScreen.Value = tkInScreen.Minimum; + if (tkInScreen.Value > tkInScreen.Maximum) + tkInScreen.Value = tkInScreen.Maximum; try { @@ -1083,8 +1095,8 @@ private async void SampleMarker_MeasureSamples(object? sender, SamplesEventArgs } - private async void MnuNetSettings_Click(object? sender, RoutedEventArgs e) - { + private async void MnuNetSettings_Click(object? sender, RoutedEventArgs e) + { if (driver == null) return; @@ -1104,8 +1116,32 @@ private async void MnuNetSettings_Click(object? sender, RoutedEventArgs e) await this.ShowError("Error", "Error updating network settings, restart the device and try again."); else await this.ShowInfo("Updated", "Network settings updated successfully."); - } - } + } + } + + private async void MnuGeneralSettings_Click(object? sender, RoutedEventArgs e) + { + var dlg = new GeneralSettingsDialog + { + MinSamples = generalSettings.MinSamples, + MaxSamples = generalSettings.MaxSamples + }; + + if (await dlg.ShowDialog(this)) + { + generalSettings.MinSamples = dlg.MinSamples; + generalSettings.MaxSamples = dlg.MaxSamples; + AppSettingsManager.PersistSettings("GeneralSettings.json", generalSettings); + tkInScreen.Minimum = generalSettings.MinSamples; + tkInScreen.Maximum = generalSettings.MaxSamples; + lblMinSamples.Text = generalSettings.MinSamples.ToString(); + lblMaxSamples.Text = generalSettings.MaxSamples.ToString(); + if (tkInScreen.Value < tkInScreen.Minimum) + tkInScreen.Value = tkInScreen.Minimum; + if (tkInScreen.Value > tkInScreen.Maximum) + tkInScreen.Value = tkInScreen.Maximum; + } + } private async void MnuExport_Click(object? sender, RoutedEventArgs e) { @@ -1764,10 +1800,11 @@ private void syncUI() btnAbort.IsEnabled = isCapturing; - mnuProfiles.IsEnabled = hasDriver && !isCapturing; - mnuSettings.IsEnabled = canConfigureWiFi; - mnuSave.IsEnabled = hasCapture; - mnuExport.IsEnabled = hasCapture; + mnuProfiles.IsEnabled = hasDriver && !isCapturing; + mnuSettings.IsEnabled = true; + mnuNetSettings.IsEnabled = canConfigureWiFi; + mnuSave.IsEnabled = hasCapture; + mnuExport.IsEnabled = hasCapture; lblBootloader.IsVisible = hasDriver && !isCapturing; lblInfo.IsVisible = hasDriver; From 7b52b2133b790f918a1c861d142252ee98f4aa79 Mon Sep 17 00:00:00 2001 From: idwpan <51302919+idwpan@users.noreply.github.com> Date: Sat, 16 Aug 2025 12:38:37 -0400 Subject: [PATCH 2/8] Show slider value on hover --- .../LogicAnalyzer/LogicAnalyzer/MainWindow.axaml | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/Software/LogicAnalyzer/LogicAnalyzer/MainWindow.axaml b/Software/LogicAnalyzer/LogicAnalyzer/MainWindow.axaml index a2dea9c4..efc3523e 100644 --- a/Software/LogicAnalyzer/LogicAnalyzer/MainWindow.axaml +++ b/Software/LogicAnalyzer/LogicAnalyzer/MainWindow.axaml @@ -92,9 +92,16 @@ 10000 - - - + + + Information From 767a8c8b68daffc89f17f97cc7859cc0dc8204e5 Mon Sep 17 00:00:00 2001 From: idwpan <51302919+idwpan@users.noreply.github.com> Date: Sat, 16 Aug 2025 14:33:39 -0400 Subject: [PATCH 3/8] show tooltip when moving slider --- .../Dialogs/GeneralSettingsDialog.axaml | 4 +-- .../LogicAnalyzer/MainWindow.axaml | 33 ++++++++++--------- .../LogicAnalyzer/MainWindow.axaml.cs | 15 +++++++++ 3 files changed, 35 insertions(+), 17 deletions(-) diff --git a/Software/LogicAnalyzer/LogicAnalyzer/Dialogs/GeneralSettingsDialog.axaml b/Software/LogicAnalyzer/LogicAnalyzer/Dialogs/GeneralSettingsDialog.axaml index ab855341..a0884117 100644 --- a/Software/LogicAnalyzer/LogicAnalyzer/Dialogs/GeneralSettingsDialog.axaml +++ b/Software/LogicAnalyzer/LogicAnalyzer/Dialogs/GeneralSettingsDialog.axaml @@ -9,9 +9,9 @@ Width="300" Height="180" CanResize="False" WindowStartupLocation="CenterOwner"> - Min samples: + Min display samples: - Max samples: + Max display samples: diff --git a/Software/LogicAnalyzer/LogicAnalyzer/MainWindow.axaml b/Software/LogicAnalyzer/LogicAnalyzer/MainWindow.axaml index efc3523e..5b2ef014 100644 --- a/Software/LogicAnalyzer/LogicAnalyzer/MainWindow.axaml +++ b/Software/LogicAnalyzer/LogicAnalyzer/MainWindow.axaml @@ -17,10 +17,10 @@ - - - - + + + + @@ -91,17 +91,20 @@ 10000 - - - - + + + + + Information diff --git a/Software/LogicAnalyzer/LogicAnalyzer/MainWindow.axaml.cs b/Software/LogicAnalyzer/LogicAnalyzer/MainWindow.axaml.cs index eaa195af..0a35c2aa 100644 --- a/Software/LogicAnalyzer/LogicAnalyzer/MainWindow.axaml.cs +++ b/Software/LogicAnalyzer/LogicAnalyzer/MainWindow.axaml.cs @@ -53,6 +53,7 @@ public partial class MainWindow : PersistableWindowBase //bool preserveSamples = false; Timer tmrHideSamples; + DispatcherTimer tmrSliderToolTip; List sampleDisplays = new List(); List regionDisplays = new List(); @@ -136,6 +137,13 @@ public MainWindow() }); }); + tmrSliderToolTip = new DispatcherTimer { Interval = TimeSpan.FromSeconds(1) }; + tmrSliderToolTip.Tick += (o, e) => + { + ToolTip.SetIsOpen(tkInScreen, false); + tmrSliderToolTip.Stop(); + }; + this.Closed += (o, e) => { if (driver != null && driver.IsCapturing) @@ -1597,6 +1605,13 @@ private void tkInScreen_ValueChanged(object? sender, Avalonia.AvaloniaPropertyCh { updateSampleDisplays(); + if (e.Property == RangeBase.ValueProperty) + { + ToolTip.SetIsOpen(tkInScreen, true); + tmrSliderToolTip.Stop(); + tmrSliderToolTip.Start(); + } + } private async void mnuSave_Click(object? sender, RoutedEventArgs e) From 2e1bf4433c934afa0b621e7a7852871eb8742e37 Mon Sep 17 00:00:00 2001 From: idwpan <51302919+idwpan@users.noreply.github.com> Date: Sat, 16 Aug 2025 15:36:59 -0400 Subject: [PATCH 4/8] allow moving minimap by dragging mouse --- .../Controls/SamplePreviewer.axaml.cs | 78 +++++++++ .../LogicAnalyzer/MainWindow.axaml.cs | 160 +++++++++--------- 2 files changed, 161 insertions(+), 77 deletions(-) diff --git a/Software/LogicAnalyzer/LogicAnalyzer/Controls/SamplePreviewer.axaml.cs b/Software/LogicAnalyzer/LogicAnalyzer/Controls/SamplePreviewer.axaml.cs index ab174925..6e7e6b05 100644 --- a/Software/LogicAnalyzer/LogicAnalyzer/Controls/SamplePreviewer.axaml.cs +++ b/Software/LogicAnalyzer/LogicAnalyzer/Controls/SamplePreviewer.axaml.cs @@ -1,5 +1,6 @@ using Avalonia; using Avalonia.Controls; +using Avalonia.Input; using Avalonia.Media; using Avalonia.Media.Imaging; using LogicAnalyzer.Classes; @@ -23,10 +24,14 @@ public partial class SamplePreviewer : UserControl, ISampleDisplay public int VisibleSamples { get; private set; } public event EventHandler? PinnedChanged; + public event EventHandler? ViewChanged; bool pinned = false; public bool Pinned { get { return pinned; } set { pinned = value; if (PinnedChanged != null) PinnedChanged(this, new PinnedEventArgs { Pinned = pinned }); } } + bool dragging = false; + double dragOffset = 0; + public SamplePreviewer() { InitializeComponent(); @@ -125,6 +130,74 @@ public void UpdateVisibleSamples(int FirstSample, int VisibleSamples) InvalidateVisual(); } + protected override void OnPointerPressed(PointerPressedEventArgs e) + { + base.OnPointerPressed(e); + + if (e.Source == lblPin) + return; + + var point = e.GetPosition(this); + double ratio = Bounds.Width / sampleCount; + double visibleWidth = VisibleSamples * ratio; + double startX = FirstSample * ratio; + + if (point.X >= startX && point.X <= startX + visibleWidth) + { + dragOffset = point.X - startX; + } + else + { + dragOffset = visibleWidth / 2.0; + updateView(point.X); + } + + dragging = true; + e.Pointer.Capture(this); + } + + protected override void OnPointerMoved(PointerEventArgs e) + { + base.OnPointerMoved(e); + + if (!dragging) + return; + + var point = e.GetPosition(this); + updateView(point.X); + } + + protected override void OnPointerReleased(PointerReleasedEventArgs e) + { + base.OnPointerReleased(e); + + if (!dragging) + return; + + dragging = false; + e.Pointer.Capture(null); + + var point = e.GetPosition(this); + updateView(point.X); + } + + void updateView(double x) + { + if (sampleCount == 0) + return; + + double ratio = Bounds.Width / sampleCount; + double newStart = x - dragOffset; + int first = (int)(newStart / ratio); + + if (first < 0) + first = 0; + if (first > sampleCount - VisibleSamples) + first = sampleCount - VisibleSamples; + + ViewChanged?.Invoke(this, new ViewChangedEventArgs { FirstSample = first }); + } + private void TextBlock_PointerPressed(object? sender, Avalonia.Input.PointerPressedEventArgs e) { pinned = !pinned; @@ -137,5 +210,10 @@ public class PinnedEventArgs : EventArgs { public bool Pinned { get; set; } } + + public class ViewChangedEventArgs : EventArgs + { + public int FirstSample { get; set; } + } } } diff --git a/Software/LogicAnalyzer/LogicAnalyzer/MainWindow.axaml.cs b/Software/LogicAnalyzer/LogicAnalyzer/MainWindow.axaml.cs index 0a35c2aa..74c867c0 100644 --- a/Software/LogicAnalyzer/LogicAnalyzer/MainWindow.axaml.cs +++ b/Software/LogicAnalyzer/LogicAnalyzer/MainWindow.axaml.cs @@ -62,8 +62,8 @@ public partial class MainWindow : PersistableWindowBase List knownDevices = new List(); KnownDevice? currentKnownDevice = null; - ProfilesSet? profiles; - GeneralSettings generalSettings; + ProfilesSet? profiles; + GeneralSettings generalSettings; public bool PreviewPinned { get { return samplePreviewer.Pinned; } set { samplePreviewer.Pinned = value; } } @@ -98,7 +98,8 @@ public MainWindow() sampleMarker.SamplesInserted += SampleMarker_SamplesInserted; sampleMarker.SamplesDeleted += SampleMarker_SamplesDeleted; - samplePreviewer.PinnedChanged += SamplePreviewer_PinnedChanged; + samplePreviewer.PinnedChanged += SamplePreviewer_PinnedChanged; + samplePreviewer.ViewChanged += SamplePreviewer_ViewChanged; sampleViewer.PointerWheelChanged += SampleViewer_PointerWheelChanged; tkInScreen.PointerWheelChanged += TkInScreen_PointerWheelChanged; @@ -120,10 +121,10 @@ public MainWindow() mnuSave.Click += mnuSave_Click; mnuExit.Click += MnuExit_Click; mnuExport.Click += MnuExport_Click; - mnuNetSettings.Click += MnuNetSettings_Click; - mnuGeneralSettings.Click += MnuGeneralSettings_Click; - mnuDocs.Click += MnuDocs_Click; - mnuAbout.Click += MnuAbout_Click; + mnuNetSettings.Click += MnuNetSettings_Click; + mnuGeneralSettings.Click += MnuGeneralSettings_Click; + mnuDocs.Click += MnuDocs_Click; + mnuAbout.Click += MnuAbout_Click; AddHandler(InputElement.KeyDownEvent, MainWindow_KeyDown, handledEventsToo: true); pnlPower.PointerPressed += (o, e) => GetPowerStatus(); @@ -144,7 +145,7 @@ public MainWindow() tmrSliderToolTip.Stop(); }; - this.Closed += (o, e) => + this.Closed += (o, e) => { if (driver != null && driver.IsCapturing) { @@ -170,18 +171,18 @@ public MainWindow() Task.Run(() => LoadKnownDevices()); - RefreshPorts(); - LoadProfiles(); - - generalSettings = AppSettingsManager.GetSettings("GeneralSettings.json") ?? new GeneralSettings(); - tkInScreen.Minimum = generalSettings.MinSamples; - tkInScreen.Maximum = generalSettings.MaxSamples; - lblMinSamples.Text = generalSettings.MinSamples.ToString(); - lblMaxSamples.Text = generalSettings.MaxSamples.ToString(); - if (tkInScreen.Value < tkInScreen.Minimum) - tkInScreen.Value = tkInScreen.Minimum; - if (tkInScreen.Value > tkInScreen.Maximum) - tkInScreen.Value = tkInScreen.Maximum; + RefreshPorts(); + LoadProfiles(); + + generalSettings = AppSettingsManager.GetSettings("GeneralSettings.json") ?? new GeneralSettings(); + tkInScreen.Minimum = generalSettings.MinSamples; + tkInScreen.Maximum = generalSettings.MaxSamples; + lblMinSamples.Text = generalSettings.MinSamples.ToString(); + lblMaxSamples.Text = generalSettings.MaxSamples.ToString(); + if (tkInScreen.Value < tkInScreen.Minimum) + tkInScreen.Value = tkInScreen.Minimum; + if (tkInScreen.Value > tkInScreen.Maximum) + tkInScreen.Value = tkInScreen.Maximum; try { @@ -254,7 +255,7 @@ private async void MnuLoad_Click(object? sender, RoutedEventArgs e) if (driver == null) { await this.ShowError("Load profile", "No device connected, cannot load profile."); - return; + return; } var mnu = sender as MenuItem; @@ -296,16 +297,16 @@ private async void MnuLoad_Click(object? sender, RoutedEventArgs e) private async void AddProfile_Click(object? sender, RoutedEventArgs e) { - var dlg = MessageBoxManager.GetMessageBoxCustom(new MsBox.Avalonia.Dto.MessageBoxCustomParams + var dlg = MessageBoxManager.GetMessageBoxCustom(new MsBox.Avalonia.Dto.MessageBoxCustomParams { ButtonDefinitions = new List { new MsBox.Avalonia.Models.ButtonDefinition { Name = "Cancel", IsCancel = true, IsDefault = false }, new MsBox.Avalonia.Models.ButtonDefinition { Name = "Save", IsCancel = false, IsDefault = true } }, - InputParams = new MsBox.Avalonia.Dto.InputParams - { - Label = "New profile name:", Multiline = false + InputParams = new MsBox.Avalonia.Dto.InputParams + { + Label = "New profile name:", Multiline = false }, Icon = MsBox.Avalonia.Enums.Icon.Setting, ContentTitle = "Add profile", @@ -506,6 +507,11 @@ private void SamplePreviewer_PinnedChanged(object? sender, SamplePreviewer.Pinne } } + private void SamplePreviewer_ViewChanged(object? sender, SamplePreviewer.ViewChangedEventArgs e) + { + updateSamplesInDisplay(e.FirstSample, (int)tkInScreen.Value); + } + private void ChannelViewer_ChannelVisibilityChanged(object? sender, EventArgs e) { UpdateVisibility(); @@ -548,14 +554,14 @@ private void SgManager_DecodingComplete(object? sender, SigrokDecoderManager.Dec if (e.Annotations != null && e.Annotations.Any()) { - + foreach(var grp in e.Annotations) { annotationsViewer.AddAnnotationsGroup(grp); } - + } annotationsViewer.EndUpdate(); @@ -604,8 +610,8 @@ private async void MnuDocs_Click(object? sender, RoutedEventArgs e) { OpenUrl("https://github.com/gusmanb/logicanalyzer/wiki"); } - catch - { + catch + { await this.ShowError("Cannot open page.", "Cannot start the default browser. You can access the online documentation in https://github.com/gusmanb/logicanalyzer/wiki"); } } @@ -795,10 +801,10 @@ private async void MnuNew_Click(object? sender, RoutedEventArgs e) dlgCreate.InsertMode = false; dlgCreate.Initialize( channels, - names, + names, stn.PreTriggerSamples + stn.PostTriggerSamples, stn.PreTriggerSamples + stn.PostTriggerSamples); - + var samples = await dlgCreate.ShowDialog(this); if (samples == null) @@ -806,7 +812,7 @@ private async void MnuNew_Click(object? sender, RoutedEventArgs e) session = stn; driver = drv; - + for (int chan = 0; chan < stn.CaptureChannels.Length; chan++) stn.CaptureChannels[chan].Samples = samples[chan]; @@ -867,7 +873,7 @@ private async void SampleMarker_SamplesInserted(object? sender, SampleEventArgs return; await InsertSamples(e.Sample, samples); - + } private async Task InsertSamples(int sample, IEnumerable newSamples) @@ -1068,7 +1074,7 @@ private void UpdateSamples(int firstSample, int totalSamples, int finalPreSample if (finalRegions.Count > 0) addRegions(finalRegions); - + scrSamplePos.Maximum = totalSamples - 1; updateSamplesInDisplay(firstSample - 1, (int)tkInScreen.Value); @@ -1103,8 +1109,8 @@ private async void SampleMarker_MeasureSamples(object? sender, SamplesEventArgs } - private async void MnuNetSettings_Click(object? sender, RoutedEventArgs e) - { + private async void MnuNetSettings_Click(object? sender, RoutedEventArgs e) + { if (driver == null) return; @@ -1124,32 +1130,32 @@ private async void MnuNetSettings_Click(object? sender, RoutedEventArgs e) await this.ShowError("Error", "Error updating network settings, restart the device and try again."); else await this.ShowInfo("Updated", "Network settings updated successfully."); - } - } - - private async void MnuGeneralSettings_Click(object? sender, RoutedEventArgs e) - { - var dlg = new GeneralSettingsDialog - { - MinSamples = generalSettings.MinSamples, - MaxSamples = generalSettings.MaxSamples - }; - - if (await dlg.ShowDialog(this)) - { - generalSettings.MinSamples = dlg.MinSamples; - generalSettings.MaxSamples = dlg.MaxSamples; - AppSettingsManager.PersistSettings("GeneralSettings.json", generalSettings); - tkInScreen.Minimum = generalSettings.MinSamples; - tkInScreen.Maximum = generalSettings.MaxSamples; - lblMinSamples.Text = generalSettings.MinSamples.ToString(); - lblMaxSamples.Text = generalSettings.MaxSamples.ToString(); - if (tkInScreen.Value < tkInScreen.Minimum) - tkInScreen.Value = tkInScreen.Minimum; - if (tkInScreen.Value > tkInScreen.Maximum) - tkInScreen.Value = tkInScreen.Maximum; - } - } + } + } + + private async void MnuGeneralSettings_Click(object? sender, RoutedEventArgs e) + { + var dlg = new GeneralSettingsDialog + { + MinSamples = generalSettings.MinSamples, + MaxSamples = generalSettings.MaxSamples + }; + + if (await dlg.ShowDialog(this)) + { + generalSettings.MinSamples = dlg.MinSamples; + generalSettings.MaxSamples = dlg.MaxSamples; + AppSettingsManager.PersistSettings("GeneralSettings.json", generalSettings); + tkInScreen.Minimum = generalSettings.MinSamples; + tkInScreen.Maximum = generalSettings.MaxSamples; + lblMinSamples.Text = generalSettings.MinSamples.ToString(); + lblMaxSamples.Text = generalSettings.MaxSamples.ToString(); + if (tkInScreen.Value < tkInScreen.Minimum) + tkInScreen.Value = tkInScreen.Minimum; + if (tkInScreen.Value > tkInScreen.Maximum) + tkInScreen.Value = tkInScreen.Maximum; + } + } private async void MnuExport_Click(object? sender, RoutedEventArgs e) { @@ -1286,7 +1292,7 @@ private async void btnOpenClose_Click(object? sender, EventArgs e) syncUI(); } - + } else { @@ -1420,8 +1426,8 @@ private void StoreKnownDevice(KnownDevice cdev) private KnownDevice? GetKnownDevice(DetectedDevice[] detected) { - var device = knownDevices.FirstOrDefault(d => d.Entries.Length == detected.Length && - d.Entries.All(e => + var device = knownDevices.FirstOrDefault(d => d.Entries.Length == detected.Length && + d.Entries.All(e => detected.Any(dd => dd.SerialNumber == e.SerialNumber))); return device; @@ -1448,7 +1454,7 @@ void GetPowerStatus() string[] parts = powerStatus.Split("_"); - if(parts.Length == 2 ) + if(parts.Length == 2 ) { lblVoltage.Text = parts[0]; @@ -1460,9 +1466,9 @@ void GetPowerStatus() if (oldSrc is IDisposable) ((IDisposable)oldSrc).Dispose(); } - + } - + private void btnRefresh_Click(object? sender, RoutedEventArgs e) { RefreshPorts(); @@ -1495,7 +1501,7 @@ void RefreshPorts() ddPorts.ItemsSource = null; ddPorts.ItemsSource = portItems.ToArray(); ddPorts.SelectedIndex = 0; - + } private async void btnRepeat_Click(object? sender, RoutedEventArgs e) @@ -1520,7 +1526,7 @@ private async void btnCapture_Click(object? sender, RoutedEventArgs e) return; var dialog = new CaptureDialog(); - + dialog.Initialize(driver); if (!await dialog.ShowDialog(this)) @@ -1535,7 +1541,7 @@ private async void btnCapture_Click(object? sender, RoutedEventArgs e) var settingsFile = $"cpSettings{driver.DriverType}.json"; var settings = session.Clone(); - + foreach(var channel in settings.CaptureChannels) channel.Samples = null; @@ -1699,7 +1705,7 @@ private async void mnuOpen_Click(object? sender, RoutedEventArgs e) LoadInfo(); } } - catch(Exception ex) + catch(Exception ex) { await this.ShowError("Unhandled exception", $"{ex.Message} - {ex.StackTrace}"); } @@ -1815,11 +1821,11 @@ private void syncUI() btnAbort.IsEnabled = isCapturing; - mnuProfiles.IsEnabled = hasDriver && !isCapturing; - mnuSettings.IsEnabled = true; - mnuNetSettings.IsEnabled = canConfigureWiFi; - mnuSave.IsEnabled = hasCapture; - mnuExport.IsEnabled = hasCapture; + mnuProfiles.IsEnabled = hasDriver && !isCapturing; + mnuSettings.IsEnabled = true; + mnuNetSettings.IsEnabled = canConfigureWiFi; + mnuSave.IsEnabled = hasCapture; + mnuExport.IsEnabled = hasCapture; lblBootloader.IsVisible = hasDriver && !isCapturing; lblInfo.IsVisible = hasDriver; From 37eefc3f74291088dcc9af99f5ff1b731e14e953 Mon Sep 17 00:00:00 2001 From: idwpan <51302919+idwpan@users.noreply.github.com> Date: Sun, 31 Aug 2025 14:44:53 -0400 Subject: [PATCH 5/8] Restrict min/max samples based on device limits --- .../Dialogs/GeneralSettingsDialog.axaml.cs | 16 +++++++++++++-- .../LogicAnalyzer/MainWindow.axaml.cs | 20 ++++++++++++++++++- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/Software/LogicAnalyzer/LogicAnalyzer/Dialogs/GeneralSettingsDialog.axaml.cs b/Software/LogicAnalyzer/LogicAnalyzer/Dialogs/GeneralSettingsDialog.axaml.cs index 88694613..ae380a10 100644 --- a/Software/LogicAnalyzer/LogicAnalyzer/Dialogs/GeneralSettingsDialog.axaml.cs +++ b/Software/LogicAnalyzer/LogicAnalyzer/Dialogs/GeneralSettingsDialog.axaml.cs @@ -9,6 +9,9 @@ public partial class GeneralSettingsDialog : Window public int MinSamples { get; set; } public int MaxSamples { get; set; } + public int MinSamplesLimit { get; set; } + public int MaxSamplesLimit { get; set; } + public GeneralSettingsDialog() { InitializeComponent(); @@ -20,8 +23,17 @@ protected override void OnOpened(EventArgs e) { base.OnOpened(e); this.FixStartupPosition(); - nudMin.Value = MinSamples; - nudMax.Value = MaxSamples; + nudMin.Minimum = MinSamplesLimit; + nudMin.Maximum = MaxSamplesLimit; + nudMax.Minimum = MinSamplesLimit; + nudMax.Maximum = MaxSamplesLimit; + + nudMin.Value = Math.Clamp(MinSamples, MinSamplesLimit, MaxSamplesLimit); + nudMax.Value = Math.Clamp(MaxSamples, MinSamplesLimit, MaxSamplesLimit); + + var tooltip = $"Min: {MinSamplesLimit:#,##0}\r\nMax: {MaxSamplesLimit:#,##0}"; + ToolTip.SetTip(nudMin, tooltip); + ToolTip.SetTip(nudMax, tooltip); } private void BtnCancel_Click(object? sender, Avalonia.Interactivity.RoutedEventArgs e) diff --git a/Software/LogicAnalyzer/LogicAnalyzer/MainWindow.axaml.cs b/Software/LogicAnalyzer/LogicAnalyzer/MainWindow.axaml.cs index 74c867c0..6b7bd543 100644 --- a/Software/LogicAnalyzer/LogicAnalyzer/MainWindow.axaml.cs +++ b/Software/LogicAnalyzer/LogicAnalyzer/MainWindow.axaml.cs @@ -1135,10 +1135,24 @@ private async void MnuNetSettings_Click(object? sender, RoutedEventArgs e) private async void MnuGeneralSettings_Click(object? sender, RoutedEventArgs e) { + // some defaults when not connected to a device + int minSamples = 1; + int maxSamples = 10000; + + if (driver != null) + { + var channels = session?.CaptureChannels?.Select(c => (int)c.ChannelNumber).ToArray() ?? Enumerable.Range(0, driver.ChannelCount).ToArray(); + var limits = driver.GetLimits(channels); + minSamples = limits.MinPreSamples + limits.MinPostSamples; + maxSamples = limits.MaxPreSamples + limits.MaxPostSamples; + } + var dlg = new GeneralSettingsDialog { MinSamples = generalSettings.MinSamples, - MaxSamples = generalSettings.MaxSamples + MaxSamples = generalSettings.MaxSamples, + MinSamplesLimit = minSamples, + MaxSamplesLimit = maxSamples }; if (await dlg.ShowDialog(this)) @@ -1289,6 +1303,10 @@ private async void btnOpenClose_Click(object? sender, EventArgs e) if (driver != null) { driver.CaptureCompleted += Driver_CaptureCompleted; + var settingsFile = $"cpSettings{driver.DriverType}.json"; + session = AppSettingsManager.GetSettings(settingsFile) ?? new CaptureSession(); + updateChannels(true); + LoadInfo(); syncUI(); } From 497054a86a9b4d8c1335f0600ddae4f5a3978a10 Mon Sep 17 00:00:00 2001 From: idwpan <51302919+idwpan@users.noreply.github.com> Date: Mon, 1 Sep 2025 12:17:30 -0400 Subject: [PATCH 6/8] fix max total samples value --- Software/LogicAnalyzer/LogicAnalyzer/MainWindow.axaml.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Software/LogicAnalyzer/LogicAnalyzer/MainWindow.axaml.cs b/Software/LogicAnalyzer/LogicAnalyzer/MainWindow.axaml.cs index 6b7bd543..d97b3aa6 100644 --- a/Software/LogicAnalyzer/LogicAnalyzer/MainWindow.axaml.cs +++ b/Software/LogicAnalyzer/LogicAnalyzer/MainWindow.axaml.cs @@ -1144,7 +1144,7 @@ private async void MnuGeneralSettings_Click(object? sender, RoutedEventArgs e) var channels = session?.CaptureChannels?.Select(c => (int)c.ChannelNumber).ToArray() ?? Enumerable.Range(0, driver.ChannelCount).ToArray(); var limits = driver.GetLimits(channels); minSamples = limits.MinPreSamples + limits.MinPostSamples; - maxSamples = limits.MaxPreSamples + limits.MaxPostSamples; + maxSamples = limits.MaxTotalSamples; } var dlg = new GeneralSettingsDialog From 12920a18da743b1962a2fd22313a6d73c0adb520 Mon Sep 17 00:00:00 2001 From: idwpan <51302919+idwpan@users.noreply.github.com> Date: Mon, 1 Sep 2025 12:20:06 -0400 Subject: [PATCH 7/8] remove elipsis in general menu header --- Software/LogicAnalyzer/LogicAnalyzer/MainWindow.axaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Software/LogicAnalyzer/LogicAnalyzer/MainWindow.axaml b/Software/LogicAnalyzer/LogicAnalyzer/MainWindow.axaml index 5b2ef014..e90dea8f 100644 --- a/Software/LogicAnalyzer/LogicAnalyzer/MainWindow.axaml +++ b/Software/LogicAnalyzer/LogicAnalyzer/MainWindow.axaml @@ -18,7 +18,7 @@ - + From 395e8cbda0159b121347484690c9d93e6c446bda Mon Sep 17 00:00:00 2001 From: idwpan <51302919+idwpan@users.noreply.github.com> Date: Mon, 1 Sep 2025 12:35:42 -0400 Subject: [PATCH 8/8] misc cleanup --- .../Controls/SamplePreviewer.axaml.cs | 7 +- .../LogicAnalyzer/MainWindow.axaml.cs | 72 +++++++++---------- 2 files changed, 36 insertions(+), 43 deletions(-) diff --git a/Software/LogicAnalyzer/LogicAnalyzer/Controls/SamplePreviewer.axaml.cs b/Software/LogicAnalyzer/LogicAnalyzer/Controls/SamplePreviewer.axaml.cs index 6e7e6b05..f967dfc9 100644 --- a/Software/LogicAnalyzer/LogicAnalyzer/Controls/SamplePreviewer.axaml.cs +++ b/Software/LogicAnalyzer/LogicAnalyzer/Controls/SamplePreviewer.axaml.cs @@ -188,12 +188,9 @@ void updateView(double x) double ratio = Bounds.Width / sampleCount; double newStart = x - dragOffset; - int first = (int)(newStart / ratio); - if (first < 0) - first = 0; - if (first > sampleCount - VisibleSamples) - first = sampleCount - VisibleSamples; + int first = (int)(newStart / ratio); + first = Math.Clamp(first, 0, sampleCount - VisibleSamples); ViewChanged?.Invoke(this, new ViewChangedEventArgs { FirstSample = first }); } diff --git a/Software/LogicAnalyzer/LogicAnalyzer/MainWindow.axaml.cs b/Software/LogicAnalyzer/LogicAnalyzer/MainWindow.axaml.cs index d97b3aa6..e7d9b0da 100644 --- a/Software/LogicAnalyzer/LogicAnalyzer/MainWindow.axaml.cs +++ b/Software/LogicAnalyzer/LogicAnalyzer/MainWindow.axaml.cs @@ -98,7 +98,7 @@ public MainWindow() sampleMarker.SamplesInserted += SampleMarker_SamplesInserted; sampleMarker.SamplesDeleted += SampleMarker_SamplesDeleted; - samplePreviewer.PinnedChanged += SamplePreviewer_PinnedChanged; + samplePreviewer.PinnedChanged += SamplePreviewer_PinnedChanged; samplePreviewer.ViewChanged += SamplePreviewer_ViewChanged; sampleViewer.PointerWheelChanged += SampleViewer_PointerWheelChanged; @@ -133,7 +133,7 @@ public MainWindow() { Dispatcher.UIThread.InvokeAsync(() => { - if(!samplePreviewer.Pinned) + if (!samplePreviewer.Pinned) samplePreviewer.IsVisible = false; }); }); @@ -153,7 +153,7 @@ public MainWindow() driver.Dispose(); } - if(decoderProvider != null) + if (decoderProvider != null) decoderProvider.Dispose(); }; @@ -169,7 +169,7 @@ public MainWindow() regionDisplays.Add(sampleMarker); regionDisplays.Add(annotationsViewer); - Task.Run(() => LoadKnownDevices()); + Task.Run(() => LoadKnownDevices()); RefreshPorts(); LoadProfiles(); @@ -179,10 +179,7 @@ public MainWindow() tkInScreen.Maximum = generalSettings.MaxSamples; lblMinSamples.Text = generalSettings.MinSamples.ToString(); lblMaxSamples.Text = generalSettings.MaxSamples.ToString(); - if (tkInScreen.Value < tkInScreen.Minimum) - tkInScreen.Value = tkInScreen.Minimum; - if (tkInScreen.Value > tkInScreen.Maximum) - tkInScreen.Value = tkInScreen.Maximum; + tkInScreen.Value = Math.Clamp(tkInScreen.Value, tkInScreen.Minimum, tkInScreen.Maximum); try { @@ -209,7 +206,7 @@ private void LoadProfiles() if (profiles != null) { - foreach(var profile in profiles.Profiles) + foreach (var profile in profiles.Profiles) { var mnuProfile = new MenuItem { Header = profile.Name }; mnuProfiles.Items.Add(mnuProfile); @@ -270,7 +267,7 @@ private async void MnuLoad_Click(object? sender, RoutedEventArgs e) if (driver.IsCapturing) { - if (! await this.ShowConfirm("Load profile", "There is a capture in progress. Do you want to stop it and load the profile?")) + if (!await this.ShowConfirm("Load profile", "There is a capture in progress. Do you want to stop it and load the profile?")) return; driver.StopCapture(); @@ -306,7 +303,8 @@ private async void AddProfile_Click(object? sender, RoutedEventArgs e) }, InputParams = new MsBox.Avalonia.Dto.InputParams { - Label = "New profile name:", Multiline = false + Label = "New profile name:", + Multiline = false }, Icon = MsBox.Avalonia.Enums.Icon.Setting, ContentTitle = "Add profile", @@ -318,7 +316,7 @@ private async void AddProfile_Click(object? sender, RoutedEventArgs e) var result = await dlg.ShowWindowDialogAsync(this); - if(result == "Save") + if (result == "Save") { var profileName = dlg.InputValue; @@ -343,7 +341,7 @@ private async void AddProfile_Click(object? sender, RoutedEventArgs e) private async void LblForget_PointerPressed(object? sender, PointerPressedEventArgs e) { - if(currentKnownDevice != null) + if (currentKnownDevice != null) { if (await this.ShowConfirm("Forget device", "Are you sure you want to forget this device?")) @@ -364,7 +362,7 @@ private void LoadKnownDevices() { var knownDevices = AppSettingsManager.GetSettings>("knownDevices.json"); - if(knownDevices != null) + if (knownDevices != null) this.knownDevices = knownDevices; } @@ -393,7 +391,7 @@ private async void LblBootloader_PointerPressed(object? sender, PointerPressedEv private async void LblInfo_PointerPressed(object? sender, PointerPressedEventArgs e) { - if(driver != null) + if (driver != null) { var dlg = new AnalyzerInfoDialog(); dlg.Initialize(driver); @@ -406,7 +404,7 @@ private async void LblInfo_PointerPressed(object? sender, PointerPressedEventArg private void ScrSamplePos_PointerWheelChanged(object? sender, PointerWheelEventArgs e) { - if(e.Delta.Y < 0) + if (e.Delta.Y < 0) { var currentVal = scrSamplePos.Value; int newVal = (int)(currentVal - scrSamplePos.Maximum / 20); @@ -466,7 +464,7 @@ private void SampleViewer_PointerWheelChanged(object? sender, PointerWheelEventA var currentValue = scrSamplePos.Value; currentValue += (int)increment; - if(currentValue > scrSamplePos.Maximum) + if (currentValue > scrSamplePos.Maximum) currentValue = (int)scrSamplePos.Maximum; updateSamplesInDisplay((int)currentValue, (int)tkInScreen.Value); @@ -519,10 +517,10 @@ private void ChannelViewer_ChannelVisibilityChanged(object? sender, EventArgs e) private void Visibility_PointerPressed(object? sender, PointerPressedEventArgs e) { - if(session?.CaptureChannels == null) + if (session?.CaptureChannels == null) return; - foreach(var channel in session.CaptureChannels) + foreach (var channel in session.CaptureChannels) channel.Hidden = false; UpdateVisibility(); @@ -540,7 +538,7 @@ private void TkInScreen_PointerWheelChanged(object? sender, PointerWheelEventArg { tkInScreen.Value = Math.Min(tkInScreen.Maximum, tkInScreen.Value * 1.5); } - else if(e.Delta.Y < 0) + else if (e.Delta.Y < 0) { tkInScreen.Value = Math.Max(tkInScreen.Minimum, tkInScreen.Value / 1.5); } @@ -556,7 +554,7 @@ private void SgManager_DecodingComplete(object? sender, SigrokDecoderManager.Dec { - foreach(var grp in e.Annotations) + foreach (var grp in e.Annotations) { annotationsViewer.AddAnnotationsGroup(grp); } @@ -744,7 +742,7 @@ private async void SampleMarker_ShiftSamples(object? sender, EventArgs e) { var samples = channel.Samples; - if(samples == null) + if (samples == null) continue; int idx = Array.IndexOf(channelViewer.Channels, channel); @@ -790,7 +788,7 @@ private async void MnuNew_Click(object? sender, RoutedEventArgs e) var drv = new EmulatedAnalyzerDriver(5); dlg.Initialize(drv); - if(await dlg.ShowDialog(this)) + if (await dlg.ShowDialog(this)) { var stn = dlg.SelectedSettings; var channels = stn.CaptureChannels.Select(c => c.ChannelNumber).ToArray(); @@ -840,7 +838,7 @@ private async void SampleMarker_SamplesPasted(object? sender, SampleEventArgs e) return; } - if(copiedSamples != null) + if (copiedSamples != null) await InsertSamples(e.Sample, copiedSamples); } @@ -895,7 +893,7 @@ private async Task InsertSamples(int sample, IEnumerable newSamples) return; } - for(int chan = 0; chan < session.CaptureChannels.Length; chan++) + for (int chan = 0; chan < session.CaptureChannels.Length; chan++) { var channel = session.CaptureChannels[chan]; var cSamples = channel.Samples; @@ -1139,6 +1137,7 @@ private async void MnuGeneralSettings_Click(object? sender, RoutedEventArgs e) int minSamples = 1; int maxSamples = 10000; + // get device limits when connected if (driver != null) { var channels = session?.CaptureChannels?.Select(c => (int)c.ChannelNumber).ToArray() ?? Enumerable.Range(0, driver.ChannelCount).ToArray(); @@ -1164,10 +1163,7 @@ private async void MnuGeneralSettings_Click(object? sender, RoutedEventArgs e) tkInScreen.Maximum = generalSettings.MaxSamples; lblMinSamples.Text = generalSettings.MinSamples.ToString(); lblMaxSamples.Text = generalSettings.MaxSamples.ToString(); - if (tkInScreen.Value < tkInScreen.Minimum) - tkInScreen.Value = tkInScreen.Minimum; - if (tkInScreen.Value > tkInScreen.Maximum) - tkInScreen.Value = tkInScreen.Maximum; + tkInScreen.Value = Math.Clamp(tkInScreen.Value, tkInScreen.Minimum, tkInScreen.Maximum); } } @@ -1277,7 +1273,7 @@ private async void btnOpenClose_Click(object? sender, EventArgs e) if (port == null) return; - switch(port.Port) + switch (port.Port) { case "Autodetect": driver = await BeginAutodetect(); @@ -1294,7 +1290,7 @@ private async void btnOpenClose_Click(object? sender, EventArgs e) } } - catch(Exception ex) + catch (Exception ex) { await this.ShowError("Error", $"Cannot connect to device: ({ex.Message})."); return; @@ -1459,7 +1455,7 @@ void GetPowerStatus() return; } - if(driver.IsCapturing) + if (driver.IsCapturing) return; var powerStatus = driver.GetVoltageStatus(); @@ -1472,7 +1468,7 @@ void GetPowerStatus() string[] parts = powerStatus.Split("_"); - if(parts.Length == 2 ) + if (parts.Length == 2) { lblVoltage.Text = parts[0]; @@ -1552,7 +1548,7 @@ private async void btnCapture_Click(object? sender, RoutedEventArgs e) session = dialog.SelectedSettings; - if(!await BeginCapture()) + if (!await BeginCapture()) return; this.Title = Version; @@ -1560,7 +1556,7 @@ private async void btnCapture_Click(object? sender, RoutedEventArgs e) var settingsFile = $"cpSettings{driver.DriverType}.json"; var settings = session.Clone(); - foreach(var channel in settings.CaptureChannels) + foreach (var channel in settings.CaptureChannels) channel.Samples = null; AppSettingsManager.PersistSettings(settingsFile, settings); @@ -1695,7 +1691,7 @@ private async void mnuOpen_Click(object? sender, RoutedEventArgs e) if (ex.Samples != null) { - for(int buc = 0; buc < session.CaptureChannels.Length; buc++) + for (int buc = 0; buc < session.CaptureChannels.Length; buc++) ExtractSamples(session.CaptureChannels[buc], buc, ex.Samples); } @@ -1723,7 +1719,7 @@ private async void mnuOpen_Click(object? sender, RoutedEventArgs e) LoadInfo(); } } - catch(Exception ex) + catch (Exception ex) { await this.ShowError("Unhandled exception", $"{ex.Message} - {ex.StackTrace}"); } @@ -1746,7 +1742,7 @@ void LoadInfo() private string GenerateStringTrigger(ushort triggerPattern, int bitCount) { string value = ""; - for(int buc = 0; buc < bitCount; buc++) + for (int buc = 0; buc < bitCount; buc++) value += (triggerPattern & (1 << buc)) == 0 ? "0" : "1"; return value; }