diff --git a/Software/LogicAnalyzer/LogicAnalyzer/Classes/CaptureSettings.cs b/Software/LogicAnalyzer/LogicAnalyzer/Classes/CaptureSettings.cs index 746db05..cdc824a 100644 --- a/Software/LogicAnalyzer/LogicAnalyzer/Classes/CaptureSettings.cs +++ b/Software/LogicAnalyzer/LogicAnalyzer/Classes/CaptureSettings.cs @@ -1,4 +1,5 @@ -using System; +using Avalonia.Media; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -30,6 +31,7 @@ namespace LogicAnalyzer.Classes public string TextualChannelNumber { get { return $"Channel {ChannelNumber + 1}"; } } public int ChannelNumber { get; set; } public string ChannelName { get; set; } = ""; + public Color? ChannelColor { get; set; } } public class OldCaptureSettings diff --git a/Software/LogicAnalyzer/LogicAnalyzer/Controls/ChannelViewer.axaml.cs b/Software/LogicAnalyzer/LogicAnalyzer/Controls/ChannelViewer.axaml.cs index fdef170..25baae1 100644 --- a/Software/LogicAnalyzer/LogicAnalyzer/Controls/ChannelViewer.axaml.cs +++ b/Software/LogicAnalyzer/LogicAnalyzer/Controls/ChannelViewer.axaml.cs @@ -25,6 +25,8 @@ namespace LogicAnalyzer.Controls } } + public event EventHandler ChannelClick; + private void CreateControls() { ChannelGrid.Children.Clear(); @@ -67,7 +69,10 @@ namespace LogicAnalyzer.Controls newChannelLabel.Text = channels[buc].TextualChannelNumber; - newChannelLabel.Foreground = GraphicObjectsCache.GetBrush(AnalyzerColors.FgChannelColors[buc % 24]); + newChannelLabel.Foreground = GraphicObjectsCache.GetBrush(channels[buc].ChannelColor ?? AnalyzerColors.FgChannelColors[buc % 24]); + + newChannelLabel.Tag = channels[buc]; + newChannelLabel.PointerPressed += NewChannelLabel_PointerPressed; newChannelGrid.Children.Add(newChannelLabel); @@ -100,6 +105,24 @@ namespace LogicAnalyzer.Controls ChannelGrid.EndBatchUpdate(); } + private void NewChannelLabel_PointerPressed(object? sender, Avalonia.Input.PointerPressedEventArgs e) + { + var label = sender as TextBlock; + + if (label == null) + return; + + var channel = label.Tag as CaptureChannel; + + if(channel == null) + return; + + if (ChannelClick == null) + return; + + ChannelClick(sender , new ChannelEventArgs { Channel = channel }); + } + void NewChannelTextbox_TextChanged(AvaloniaPropertyChangedEventArgs e) { ((e.Sender as TextBox).Tag as CaptureChannel).ChannelName = e.NewValue?.ToString(); @@ -111,6 +134,11 @@ namespace LogicAnalyzer.Controls } } + public class ChannelEventArgs : EventArgs + { + public required CaptureChannel Channel { get; set; } + } + public class RegionEventArgs : EventArgs { public SampleRegion? Region { get; set; } diff --git a/Software/LogicAnalyzer/LogicAnalyzer/Controls/SamplePreviewer.axaml.cs b/Software/LogicAnalyzer/LogicAnalyzer/Controls/SamplePreviewer.axaml.cs index a3bef3a..4ccecf3 100644 --- a/Software/LogicAnalyzer/LogicAnalyzer/Controls/SamplePreviewer.axaml.cs +++ b/Software/LogicAnalyzer/LogicAnalyzer/Controls/SamplePreviewer.axaml.cs @@ -21,25 +21,27 @@ namespace LogicAnalyzer.Controls InitializeComponent(); } - public void UpdateSamples(UInt128[] Samples, int ChannelCount) + public void UpdateSamples(CaptureChannel[] Channels, UInt128[] Samples) { - if (ChannelCount > 24) - ChannelCount = 24; + int channelCount = Channels.Length; + + if (channelCount > 24) + channelCount = 24; int width = Math.Max(Math.Min(Samples.Length, 4096), 1024); - float cHeight = 144 / (float)ChannelCount; + float cHeight = 144 / (float)channelCount; float sWidth = (float)width / (float)Samples.Length; float high = cHeight / 6; float low = cHeight - high; using SKBitmap skb = new SKBitmap(width, 144); - SKPaint[] colors = new SKPaint[ChannelCount]; + SKPaint[] colors = new SKPaint[channelCount]; - for (int buc = 0; buc < ChannelCount; buc++) + for (int buc = 0; buc < channelCount; buc++) { - var avColor = AnalyzerColors.FgChannelColors[buc]; + var avColor = Channels[buc].ChannelColor ?? AnalyzerColors.FgChannelColors[buc]; colors[buc] = new SKPaint { @@ -56,7 +58,7 @@ namespace LogicAnalyzer.Controls UInt128 sample = Samples[x]; UInt128 prevSample = Samples[x == 0 ? x : x - 1]; - for (int chan = 0; chan < ChannelCount; chan++) + for (int chan = 0; chan < channelCount; chan++) { UInt128 curVal = sample & ((UInt128)1 << chan); UInt128 prevVal = prevSample & ((UInt128)1 << chan); diff --git a/Software/LogicAnalyzer/LogicAnalyzer/Controls/SampleViewer.axaml.cs b/Software/LogicAnalyzer/LogicAnalyzer/Controls/SampleViewer.axaml.cs index 4034d5c..f594516 100644 --- a/Software/LogicAnalyzer/LogicAnalyzer/Controls/SampleViewer.axaml.cs +++ b/Software/LogicAnalyzer/LogicAnalyzer/Controls/SampleViewer.axaml.cs @@ -18,7 +18,9 @@ namespace LogicAnalyzer.Controls public int PreSamples { get; set; } public int[]? Bursts { get; set; } public UInt128[] Samples { get; set; } - public int ChannelCount { get; set; } + + public CaptureChannel[]? Channels { get; set; } + //public int ChannelCount { get; set; } public int SamplesInScreen { get; set; } public int FirstSample { get; set; } public int? UserMarker { get; set; } @@ -91,6 +93,9 @@ namespace LogicAnalyzer.Controls public override void Render(DrawingContext context) { + + int ChannelCount = Channels?.Length ?? 0; + int minSize = ChannelCount * MIN_CHANNEL_HEIGHT; if (Parent.Bounds.Height > minSize && this.Height != double.NaN) @@ -173,12 +178,12 @@ namespace LogicAnalyzer.Controls else lineY = (chan + 1) * channelHeight - margin; - context.DrawLine(GraphicObjectsCache.GetPen(AnalyzerColors.FgChannelColors[chan], 2), new Point(lineX, lineY), new Point(lineX + sampleWidth, lineY)); + context.DrawLine(GraphicObjectsCache.GetPen(Channels?[chan].ChannelColor ?? AnalyzerColors.FgChannelColors[chan], 2), new Point(lineX, lineY), new Point(lineX + sampleWidth, lineY)); if (curVal != prevVal && buc != 0) { lineY = chan * channelHeight + margin; - context.DrawLine(GraphicObjectsCache.GetPen(AnalyzerColors.FgChannelColors[chan], 2), new Point(lineX, lineY), new Point(lineX, lineY + channelHeight - margin * 2)); + context.DrawLine(GraphicObjectsCache.GetPen(Channels?[chan].ChannelColor ?? AnalyzerColors.FgChannelColors[chan], 2), new Point(lineX, lineY), new Point(lineX, lineY + channelHeight - margin * 2)); } } diff --git a/Software/LogicAnalyzer/LogicAnalyzer/MainWindow.axaml.cs b/Software/LogicAnalyzer/LogicAnalyzer/MainWindow.axaml.cs index 3cb94d6..edda8da 100644 --- a/Software/LogicAnalyzer/LogicAnalyzer/MainWindow.axaml.cs +++ b/Software/LogicAnalyzer/LogicAnalyzer/MainWindow.axaml.cs @@ -7,6 +7,7 @@ using Avalonia.Media.Imaging; using Avalonia.Platform; using Avalonia.Shared.PlatformSupport; using Avalonia.Threading; +using AvaloniaColorPicker; using AvaloniaEdit.Utils; using LogicAnalyzer.Classes; using LogicAnalyzer.Controls; @@ -24,6 +25,7 @@ using System.Diagnostics; using System.IO; using System.IO.Ports; using System.Linq; +using System.Net.WebSockets; using System.Reflection; using System.Runtime.InteropServices; using System.Text; @@ -70,6 +72,8 @@ namespace LogicAnalyzer sampleMarker.SamplesInserted += SampleMarker_SamplesInserted; sampleMarker.SamplesDeleted += SampleMarker_SamplesDeleted; + channelViewer.ChannelClick += ChannelViewer_ChannelClick; + tkInScreen.PropertyChanged += tkInScreen_ValueChanged; scrSamplePos.Scroll += scrSamplePos_ValueChanged; scrSamplePos.PointerEnter += ScrSamplePos_PointerEnter; @@ -96,6 +100,26 @@ namespace LogicAnalyzer }); } + private async void ChannelViewer_ChannelClick(object? sender, ChannelEventArgs e) + { + var picker = new ColorPickerWindow(); + + if (e.Channel.ChannelColor != null) + picker.Color = e.Channel.ChannelColor.Value; + else + picker.Color = AnalyzerColors.FgChannelColors[e.Channel.ChannelNumber]; + + var color = await picker.ShowDialog(this); + + if (color == null) + return; + + e.Channel.ChannelColor = color; + (sender as TextBlock).Foreground = GraphicObjectsCache.GetBrush(color.Value); + samplePreviewer.UpdateSamples(channelViewer.Channels, sampleViewer.Samples); + sampleViewer.InvalidateVisual(); + } + private async void MnuAbout_Click(object? sender, RoutedEventArgs e) { var aboutDialog = new AboutDialog(); @@ -283,7 +307,7 @@ namespace LogicAnalyzer sampleViewer.BeginUpdate(); sampleViewer.Samples = samples; sampleViewer.EndUpdate(); - samplePreviewer.UpdateSamples(samples, sampleViewer.ChannelCount); + samplePreviewer.UpdateSamples(channelViewer.Channels, samples); samplePreviewer.ViewPosition = sampleViewer.FirstSample; } } @@ -352,7 +376,7 @@ namespace LogicAnalyzer sampleViewer.BeginUpdate(); sampleViewer.Samples = samples; sampleViewer.PreSamples = settings.PreTriggerSamples; - sampleViewer.ChannelCount = settings.CaptureChannels.Length; + sampleViewer.Channels = settings.CaptureChannels; sampleViewer.SamplesInScreen = Math.Min(100, samples.Length / 10); sampleViewer.FirstSample = Math.Max(settings.PreTriggerSamples - 10, 0); sampleViewer.ClearRegions(); @@ -360,8 +384,10 @@ namespace LogicAnalyzer sampleViewer.EndUpdate(); + channelViewer.Channels = settings.CaptureChannels; + samplePreviewer.ViewPosition = sampleViewer.FirstSample; - samplePreviewer.UpdateSamples(samples, sampleViewer.ChannelCount); + samplePreviewer.UpdateSamples(channelViewer.Channels, samples); sampleMarker.VisibleSamples = sampleViewer.SamplesInScreen; sampleMarker.FirstSample = sampleViewer.FirstSample; @@ -372,8 +398,6 @@ namespace LogicAnalyzer scrSamplePos.Value = sampleViewer.FirstSample; tkInScreen.Value = sampleViewer.SamplesInScreen; - channelViewer.Channels = settings.CaptureChannels; - mnuSave.IsEnabled = true; mnuProtocols.IsEnabled = true; mnuExport.IsEnabled = true; @@ -587,7 +611,7 @@ namespace LogicAnalyzer sampleViewer.EndUpdate(); - samplePreviewer.UpdateSamples(finalSamples, sampleViewer.ChannelCount); + samplePreviewer.UpdateSamples(channelViewer.Channels, finalSamples); samplePreviewer.ViewPosition = sampleViewer.FirstSample; sampleMarker.VisibleSamples = sampleViewer.SamplesInScreen; @@ -630,7 +654,7 @@ namespace LogicAnalyzer List samples = new List(); - for (int buc = 0; buc < sampleViewer.ChannelCount; buc++) + for (int buc = 0; buc < (sampleViewer.Channels?.Length ?? 0); buc++) samples.Add(ExtractSamples(buc, sampleViewer.Samples, e.FirstSample, e.SampleCount)); var names = channelViewer.Channels.Select(c => c.ChannelName).ToArray(); @@ -729,7 +753,7 @@ namespace LogicAnalyzer sampleViewer.BeginUpdate(); sampleViewer.Samples = e.Samples; sampleViewer.PreSamples = e.PreSamples; - sampleViewer.ChannelCount = e.ChannelCount; + sampleViewer.Channels = settings.CaptureChannels; if(!preserveSamples) sampleViewer.SamplesInScreen = Math.Min(100, e.Samples.Length / 10); @@ -756,15 +780,15 @@ namespace LogicAnalyzer sampleViewer.ClearAnalyzedChannels(); sampleViewer.EndUpdate(); - samplePreviewer.UpdateSamples(e.Samples, sampleViewer.ChannelCount); + channelViewer.Channels = settings.CaptureChannels; + + samplePreviewer.UpdateSamples(channelViewer.Channels, e.Samples); samplePreviewer.ViewPosition = sampleViewer.FirstSample; scrSamplePos.Maximum = e.Samples.Length - 1; scrSamplePos.Value = sampleViewer.FirstSample; tkInScreen.Value = sampleViewer.SamplesInScreen; - channelViewer.Channels = settings.CaptureChannels; - sampleMarker.VisibleSamples = sampleViewer.SamplesInScreen; sampleMarker.FirstSample = sampleViewer.FirstSample; sampleMarker.ClearRegions(); @@ -1296,7 +1320,7 @@ namespace LogicAnalyzer sampleViewer.BeginUpdate(); sampleViewer.Samples = ex.Samples; sampleViewer.PreSamples = ex.Settings.PreTriggerSamples; - sampleViewer.ChannelCount = ex.Settings.CaptureChannels.Length; + sampleViewer.Channels = ex.Settings.CaptureChannels; sampleViewer.SamplesInScreen = Math.Min(100, ex.Samples.Length / 10); sampleViewer.FirstSample = Math.Max(ex.Settings.PreTriggerSamples - 10, 0); sampleViewer.ClearRegions(); @@ -1307,7 +1331,9 @@ namespace LogicAnalyzer sampleViewer.EndUpdate(); - samplePreviewer.UpdateSamples(ex.Samples, sampleViewer.ChannelCount); + channelViewer.Channels = ex.Settings.CaptureChannels; + + samplePreviewer.UpdateSamples(channelViewer.Channels, ex.Samples); samplePreviewer.ViewPosition = sampleViewer.FirstSample; sampleMarker.VisibleSamples = sampleViewer.SamplesInScreen; @@ -1322,7 +1348,7 @@ namespace LogicAnalyzer scrSamplePos.Value = sampleViewer.FirstSample; tkInScreen.Value = sampleViewer.SamplesInScreen; - channelViewer.Channels = ex.Settings.CaptureChannels; + mnuSave.IsEnabled = true; mnuProtocols.IsEnabled = true;