Allow to choose channel colors

This commit is contained in:
Agustín Gimenez 2024-05-12 13:18:09 +02:00
parent 4e575109a9
commit b59577ec04
5 changed files with 90 additions and 27 deletions

View File

@ -1,4 +1,5 @@
using System; using Avalonia.Media;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
@ -30,6 +31,7 @@ namespace LogicAnalyzer.Classes
public string TextualChannelNumber { get { return $"Channel {ChannelNumber + 1}"; } } public string TextualChannelNumber { get { return $"Channel {ChannelNumber + 1}"; } }
public int ChannelNumber { get; set; } public int ChannelNumber { get; set; }
public string ChannelName { get; set; } = ""; public string ChannelName { get; set; } = "";
public Color? ChannelColor { get; set; }
} }
public class OldCaptureSettings public class OldCaptureSettings

View File

@ -25,6 +25,8 @@ namespace LogicAnalyzer.Controls
} }
} }
public event EventHandler<ChannelEventArgs> ChannelClick;
private void CreateControls() private void CreateControls()
{ {
ChannelGrid.Children.Clear(); ChannelGrid.Children.Clear();
@ -67,7 +69,10 @@ namespace LogicAnalyzer.Controls
newChannelLabel.Text = channels[buc].TextualChannelNumber; 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); newChannelGrid.Children.Add(newChannelLabel);
@ -100,6 +105,24 @@ namespace LogicAnalyzer.Controls
ChannelGrid.EndBatchUpdate(); 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) void NewChannelTextbox_TextChanged(AvaloniaPropertyChangedEventArgs e)
{ {
((e.Sender as TextBox).Tag as CaptureChannel).ChannelName = e.NewValue?.ToString(); ((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 class RegionEventArgs : EventArgs
{ {
public SampleRegion? Region { get; set; } public SampleRegion? Region { get; set; }

View File

@ -21,25 +21,27 @@ namespace LogicAnalyzer.Controls
InitializeComponent(); InitializeComponent();
} }
public void UpdateSamples(UInt128[] Samples, int ChannelCount) public void UpdateSamples(CaptureChannel[] Channels, UInt128[] Samples)
{ {
if (ChannelCount > 24) int channelCount = Channels.Length;
ChannelCount = 24;
if (channelCount > 24)
channelCount = 24;
int width = Math.Max(Math.Min(Samples.Length, 4096), 1024); 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 sWidth = (float)width / (float)Samples.Length;
float high = cHeight / 6; float high = cHeight / 6;
float low = cHeight - high; float low = cHeight - high;
using SKBitmap skb = new SKBitmap(width, 144); 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 colors[buc] = new SKPaint
{ {
@ -56,7 +58,7 @@ namespace LogicAnalyzer.Controls
UInt128 sample = Samples[x]; UInt128 sample = Samples[x];
UInt128 prevSample = Samples[x == 0 ? x : x - 1]; 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 curVal = sample & ((UInt128)1 << chan);
UInt128 prevVal = prevSample & ((UInt128)1 << chan); UInt128 prevVal = prevSample & ((UInt128)1 << chan);

View File

@ -18,7 +18,9 @@ namespace LogicAnalyzer.Controls
public int PreSamples { get; set; } public int PreSamples { get; set; }
public int[]? Bursts { get; set; } public int[]? Bursts { get; set; }
public UInt128[] Samples { 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 SamplesInScreen { get; set; }
public int FirstSample { get; set; } public int FirstSample { get; set; }
public int? UserMarker { get; set; } public int? UserMarker { get; set; }
@ -91,6 +93,9 @@ namespace LogicAnalyzer.Controls
public override void Render(DrawingContext context) public override void Render(DrawingContext context)
{ {
int ChannelCount = Channels?.Length ?? 0;
int minSize = ChannelCount * MIN_CHANNEL_HEIGHT; int minSize = ChannelCount * MIN_CHANNEL_HEIGHT;
if (Parent.Bounds.Height > minSize && this.Height != double.NaN) if (Parent.Bounds.Height > minSize && this.Height != double.NaN)
@ -173,12 +178,12 @@ namespace LogicAnalyzer.Controls
else else
lineY = (chan + 1) * channelHeight - margin; 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) if (curVal != prevVal && buc != 0)
{ {
lineY = chan * channelHeight + margin; 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));
} }
} }

View File

@ -7,6 +7,7 @@ using Avalonia.Media.Imaging;
using Avalonia.Platform; using Avalonia.Platform;
using Avalonia.Shared.PlatformSupport; using Avalonia.Shared.PlatformSupport;
using Avalonia.Threading; using Avalonia.Threading;
using AvaloniaColorPicker;
using AvaloniaEdit.Utils; using AvaloniaEdit.Utils;
using LogicAnalyzer.Classes; using LogicAnalyzer.Classes;
using LogicAnalyzer.Controls; using LogicAnalyzer.Controls;
@ -24,6 +25,7 @@ using System.Diagnostics;
using System.IO; using System.IO;
using System.IO.Ports; using System.IO.Ports;
using System.Linq; using System.Linq;
using System.Net.WebSockets;
using System.Reflection; using System.Reflection;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text; using System.Text;
@ -70,6 +72,8 @@ namespace LogicAnalyzer
sampleMarker.SamplesInserted += SampleMarker_SamplesInserted; sampleMarker.SamplesInserted += SampleMarker_SamplesInserted;
sampleMarker.SamplesDeleted += SampleMarker_SamplesDeleted; sampleMarker.SamplesDeleted += SampleMarker_SamplesDeleted;
channelViewer.ChannelClick += ChannelViewer_ChannelClick;
tkInScreen.PropertyChanged += tkInScreen_ValueChanged; tkInScreen.PropertyChanged += tkInScreen_ValueChanged;
scrSamplePos.Scroll += scrSamplePos_ValueChanged; scrSamplePos.Scroll += scrSamplePos_ValueChanged;
scrSamplePos.PointerEnter += ScrSamplePos_PointerEnter; 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) private async void MnuAbout_Click(object? sender, RoutedEventArgs e)
{ {
var aboutDialog = new AboutDialog(); var aboutDialog = new AboutDialog();
@ -283,7 +307,7 @@ namespace LogicAnalyzer
sampleViewer.BeginUpdate(); sampleViewer.BeginUpdate();
sampleViewer.Samples = samples; sampleViewer.Samples = samples;
sampleViewer.EndUpdate(); sampleViewer.EndUpdate();
samplePreviewer.UpdateSamples(samples, sampleViewer.ChannelCount); samplePreviewer.UpdateSamples(channelViewer.Channels, samples);
samplePreviewer.ViewPosition = sampleViewer.FirstSample; samplePreviewer.ViewPosition = sampleViewer.FirstSample;
} }
} }
@ -352,7 +376,7 @@ namespace LogicAnalyzer
sampleViewer.BeginUpdate(); sampleViewer.BeginUpdate();
sampleViewer.Samples = samples; sampleViewer.Samples = samples;
sampleViewer.PreSamples = settings.PreTriggerSamples; sampleViewer.PreSamples = settings.PreTriggerSamples;
sampleViewer.ChannelCount = settings.CaptureChannels.Length; sampleViewer.Channels = settings.CaptureChannels;
sampleViewer.SamplesInScreen = Math.Min(100, samples.Length / 10); sampleViewer.SamplesInScreen = Math.Min(100, samples.Length / 10);
sampleViewer.FirstSample = Math.Max(settings.PreTriggerSamples - 10, 0); sampleViewer.FirstSample = Math.Max(settings.PreTriggerSamples - 10, 0);
sampleViewer.ClearRegions(); sampleViewer.ClearRegions();
@ -360,8 +384,10 @@ namespace LogicAnalyzer
sampleViewer.EndUpdate(); sampleViewer.EndUpdate();
channelViewer.Channels = settings.CaptureChannels;
samplePreviewer.ViewPosition = sampleViewer.FirstSample; samplePreviewer.ViewPosition = sampleViewer.FirstSample;
samplePreviewer.UpdateSamples(samples, sampleViewer.ChannelCount); samplePreviewer.UpdateSamples(channelViewer.Channels, samples);
sampleMarker.VisibleSamples = sampleViewer.SamplesInScreen; sampleMarker.VisibleSamples = sampleViewer.SamplesInScreen;
sampleMarker.FirstSample = sampleViewer.FirstSample; sampleMarker.FirstSample = sampleViewer.FirstSample;
@ -372,8 +398,6 @@ namespace LogicAnalyzer
scrSamplePos.Value = sampleViewer.FirstSample; scrSamplePos.Value = sampleViewer.FirstSample;
tkInScreen.Value = sampleViewer.SamplesInScreen; tkInScreen.Value = sampleViewer.SamplesInScreen;
channelViewer.Channels = settings.CaptureChannels;
mnuSave.IsEnabled = true; mnuSave.IsEnabled = true;
mnuProtocols.IsEnabled = true; mnuProtocols.IsEnabled = true;
mnuExport.IsEnabled = true; mnuExport.IsEnabled = true;
@ -587,7 +611,7 @@ namespace LogicAnalyzer
sampleViewer.EndUpdate(); sampleViewer.EndUpdate();
samplePreviewer.UpdateSamples(finalSamples, sampleViewer.ChannelCount); samplePreviewer.UpdateSamples(channelViewer.Channels, finalSamples);
samplePreviewer.ViewPosition = sampleViewer.FirstSample; samplePreviewer.ViewPosition = sampleViewer.FirstSample;
sampleMarker.VisibleSamples = sampleViewer.SamplesInScreen; sampleMarker.VisibleSamples = sampleViewer.SamplesInScreen;
@ -630,7 +654,7 @@ namespace LogicAnalyzer
List<byte[]> samples = new List<byte[]>(); List<byte[]> samples = new List<byte[]>();
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)); samples.Add(ExtractSamples(buc, sampleViewer.Samples, e.FirstSample, e.SampleCount));
var names = channelViewer.Channels.Select(c => c.ChannelName).ToArray(); var names = channelViewer.Channels.Select(c => c.ChannelName).ToArray();
@ -729,7 +753,7 @@ namespace LogicAnalyzer
sampleViewer.BeginUpdate(); sampleViewer.BeginUpdate();
sampleViewer.Samples = e.Samples; sampleViewer.Samples = e.Samples;
sampleViewer.PreSamples = e.PreSamples; sampleViewer.PreSamples = e.PreSamples;
sampleViewer.ChannelCount = e.ChannelCount; sampleViewer.Channels = settings.CaptureChannels;
if(!preserveSamples) if(!preserveSamples)
sampleViewer.SamplesInScreen = Math.Min(100, e.Samples.Length / 10); sampleViewer.SamplesInScreen = Math.Min(100, e.Samples.Length / 10);
@ -756,15 +780,15 @@ namespace LogicAnalyzer
sampleViewer.ClearAnalyzedChannels(); sampleViewer.ClearAnalyzedChannels();
sampleViewer.EndUpdate(); sampleViewer.EndUpdate();
samplePreviewer.UpdateSamples(e.Samples, sampleViewer.ChannelCount); channelViewer.Channels = settings.CaptureChannels;
samplePreviewer.UpdateSamples(channelViewer.Channels, e.Samples);
samplePreviewer.ViewPosition = sampleViewer.FirstSample; samplePreviewer.ViewPosition = sampleViewer.FirstSample;
scrSamplePos.Maximum = e.Samples.Length - 1; scrSamplePos.Maximum = e.Samples.Length - 1;
scrSamplePos.Value = sampleViewer.FirstSample; scrSamplePos.Value = sampleViewer.FirstSample;
tkInScreen.Value = sampleViewer.SamplesInScreen; tkInScreen.Value = sampleViewer.SamplesInScreen;
channelViewer.Channels = settings.CaptureChannels;
sampleMarker.VisibleSamples = sampleViewer.SamplesInScreen; sampleMarker.VisibleSamples = sampleViewer.SamplesInScreen;
sampleMarker.FirstSample = sampleViewer.FirstSample; sampleMarker.FirstSample = sampleViewer.FirstSample;
sampleMarker.ClearRegions(); sampleMarker.ClearRegions();
@ -1296,7 +1320,7 @@ namespace LogicAnalyzer
sampleViewer.BeginUpdate(); sampleViewer.BeginUpdate();
sampleViewer.Samples = ex.Samples; sampleViewer.Samples = ex.Samples;
sampleViewer.PreSamples = ex.Settings.PreTriggerSamples; 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.SamplesInScreen = Math.Min(100, ex.Samples.Length / 10);
sampleViewer.FirstSample = Math.Max(ex.Settings.PreTriggerSamples - 10, 0); sampleViewer.FirstSample = Math.Max(ex.Settings.PreTriggerSamples - 10, 0);
sampleViewer.ClearRegions(); sampleViewer.ClearRegions();
@ -1307,7 +1331,9 @@ namespace LogicAnalyzer
sampleViewer.EndUpdate(); sampleViewer.EndUpdate();
samplePreviewer.UpdateSamples(ex.Samples, sampleViewer.ChannelCount); channelViewer.Channels = ex.Settings.CaptureChannels;
samplePreviewer.UpdateSamples(channelViewer.Channels, ex.Samples);
samplePreviewer.ViewPosition = sampleViewer.FirstSample; samplePreviewer.ViewPosition = sampleViewer.FirstSample;
sampleMarker.VisibleSamples = sampleViewer.SamplesInScreen; sampleMarker.VisibleSamples = sampleViewer.SamplesInScreen;
@ -1322,7 +1348,7 @@ namespace LogicAnalyzer
scrSamplePos.Value = sampleViewer.FirstSample; scrSamplePos.Value = sampleViewer.FirstSample;
tkInScreen.Value = sampleViewer.SamplesInScreen; tkInScreen.Value = sampleViewer.SamplesInScreen;
channelViewer.Channels = ex.Settings.CaptureChannels;
mnuSave.IsEnabled = true; mnuSave.IsEnabled = true;
mnuProtocols.IsEnabled = true; mnuProtocols.IsEnabled = true;