mirror of
https://github.com/JasonYANG170/logicanalyzer.git
synced 2024-11-23 12:06:27 +00:00
Updated analyzers
This commit is contained in:
parent
40a9b788da
commit
3765865c50
|
@ -5,12 +5,6 @@ cmake_minimum_required(VERSION 3.13)
|
||||||
set(CMAKE_C_STANDARD 11)
|
set(CMAKE_C_STANDARD 11)
|
||||||
set(CMAKE_CXX_STANDARD 17)
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
|
||||||
# set(PICO_BOARD pico_w)
|
|
||||||
|
|
||||||
# Initialise pico_sdk from installed location
|
|
||||||
# (note this can come from environment, CMake cache etc)
|
|
||||||
set(PICO_SDK_PATH "F:/PicoSDK/Pico/pico-sdk")
|
|
||||||
|
|
||||||
# Pull in Raspberry Pi Pico SDK (must be before project)
|
# Pull in Raspberry Pi Pico SDK (must be before project)
|
||||||
include(pico_sdk_import.cmake)
|
include(pico_sdk_import.cmake)
|
||||||
|
|
||||||
|
@ -42,7 +36,7 @@ pico_enable_stdio_usb(LogicAnalyzer 1)
|
||||||
# Regular pico: empty
|
# Regular pico: empty
|
||||||
# Pico W without WiFi support: pico_cyw43_arch_none
|
# Pico W without WiFi support: pico_cyw43_arch_none
|
||||||
# Pico W with WiFi support: pico_cyw43_arch_lwip_poll
|
# Pico W with WiFi support: pico_cyw43_arch_lwip_poll
|
||||||
# set (CYW_LIB pico_cyw43_arch_lwip_poll)
|
set (CYW_LIB pico_cyw43_arch_lwip_poll)
|
||||||
# set (CYW_LIB pico_cyw43_arch_none)
|
# set (CYW_LIB pico_cyw43_arch_none)
|
||||||
|
|
||||||
# Add any user requested libraries
|
# Add any user requested libraries
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
#define FIRMWARE_VERSION "V5_1"
|
#define FIRMWARE_VERSION "V5_1"
|
||||||
|
|
||||||
//Select the board type to build the firmware for
|
//Select the board type to build the firmware for
|
||||||
#define BUILD_PICO
|
//#define BUILD_PICO
|
||||||
//#define BUILD_PICO_W
|
//#define BUILD_PICO_W
|
||||||
//#define BUILD_PICO_W_WIFI
|
#define BUILD_PICO_W_WIFI
|
||||||
//#define BUILD_ZERO
|
//#define BUILD_ZERO
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -15,7 +15,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SerialProtocolAnalyzer", "S
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "I2CProtocolAnalyzer", "I2CProtocolAnalyzer\I2CProtocolAnalyzer.csproj", "{74E41F50-E208-4690-84C6-51012C2F26E2}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "I2CProtocolAnalyzer", "I2CProtocolAnalyzer\I2CProtocolAnalyzer.csproj", "{74E41F50-E208-4690-84C6-51012C2F26E2}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SignalDescriptionLanguage", "SignalDescriptionLanguage\SignalDescriptionLanguage.csproj", "{BD4731B1-B7CE-49C9-9982-77FA9B95C19F}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SignalDescriptionLanguage", "SignalDescriptionLanguage\SignalDescriptionLanguage.csproj", "{BD4731B1-B7CE-49C9-9982-77FA9B95C19F}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ParallelProtocolAnalyzer", "ParallelProtocolAnalyzer\ParallelProtocolAnalyzer.csproj", "{952FD20C-7C12-407B-A264-BA5F429BDD3C}"
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
@ -51,6 +53,10 @@ Global
|
||||||
{BD4731B1-B7CE-49C9-9982-77FA9B95C19F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{BD4731B1-B7CE-49C9-9982-77FA9B95C19F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{BD4731B1-B7CE-49C9-9982-77FA9B95C19F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{BD4731B1-B7CE-49C9-9982-77FA9B95C19F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{BD4731B1-B7CE-49C9-9982-77FA9B95C19F}.Release|Any CPU.Build.0 = Release|Any CPU
|
{BD4731B1-B7CE-49C9-9982-77FA9B95C19F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{952FD20C-7C12-407B-A264-BA5F429BDD3C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{952FD20C-7C12-407B-A264-BA5F429BDD3C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{952FD20C-7C12-407B-A264-BA5F429BDD3C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{952FD20C-7C12-407B-A264-BA5F429BDD3C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|
|
@ -6,6 +6,7 @@ using Avalonia.Media;
|
||||||
using Avalonia.Threading;
|
using Avalonia.Threading;
|
||||||
using LogicAnalyzer.Classes;
|
using LogicAnalyzer.Classes;
|
||||||
using LogicAnalyzer.Dialogs;
|
using LogicAnalyzer.Dialogs;
|
||||||
|
using LogicAnalyzer.Protocols;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
@ -62,6 +63,7 @@ namespace LogicAnalyzer.Controls
|
||||||
|
|
||||||
|
|
||||||
List<SampleRegion> regions = new List<SampleRegion>();
|
List<SampleRegion> regions = new List<SampleRegion>();
|
||||||
|
List<ProtocolAnalyzedChannel> analysisData = new List<ProtocolAnalyzedChannel>();
|
||||||
|
|
||||||
SelectedSamples? selectedSamples = null;
|
SelectedSamples? selectedSamples = null;
|
||||||
SampleRegion? selectedRegion = null;
|
SampleRegion? selectedRegion = null;
|
||||||
|
@ -69,6 +71,7 @@ namespace LogicAnalyzer.Controls
|
||||||
int? userMarker = null;
|
int? userMarker = null;
|
||||||
int mnuSample = 0;
|
int mnuSample = 0;
|
||||||
bool samplesCopied = false;
|
bool samplesCopied = false;
|
||||||
|
bool updating = false;
|
||||||
|
|
||||||
public SampleMarker()
|
public SampleMarker()
|
||||||
{
|
{
|
||||||
|
@ -163,6 +166,37 @@ namespace LogicAnalyzer.Controls
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void BeginUpdate()
|
||||||
|
{
|
||||||
|
updating = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void EndUpdate()
|
||||||
|
{
|
||||||
|
updating = false;
|
||||||
|
InvalidateVisual();
|
||||||
|
}
|
||||||
|
public void AddAnalyzedChannel(ProtocolAnalyzedChannel Data)
|
||||||
|
{
|
||||||
|
analysisData.Add(Data);
|
||||||
|
}
|
||||||
|
public void AddAnalyzedChannels(IEnumerable<ProtocolAnalyzedChannel> Data)
|
||||||
|
{
|
||||||
|
analysisData.AddRange(Data);
|
||||||
|
}
|
||||||
|
public bool RemoveAnalyzedChannel(ProtocolAnalyzedChannel Data)
|
||||||
|
{
|
||||||
|
return analysisData.Remove(Data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ClearAnalyzedChannels()
|
||||||
|
{
|
||||||
|
foreach (var data in analysisData)
|
||||||
|
data.Dispose();
|
||||||
|
|
||||||
|
analysisData.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
public void AddRegion(SampleRegion Region)
|
public void AddRegion(SampleRegion Region)
|
||||||
{
|
{
|
||||||
regions.Add(Region);
|
regions.Add(Region);
|
||||||
|
@ -202,70 +236,97 @@ namespace LogicAnalyzer.Controls
|
||||||
|
|
||||||
public override void Render(DrawingContext context)
|
public override void Render(DrawingContext context)
|
||||||
{
|
{
|
||||||
context.FillRectangle(Background, new Rect(0, 0, Bounds.Width, Bounds.Height));
|
|
||||||
|
|
||||||
if (VisibleSamples == 0)
|
var bounds = new Rect(0, 0, Bounds.Width, Bounds.Height);
|
||||||
return;
|
|
||||||
|
|
||||||
double sampleWidth = this.Bounds.Width / VisibleSamples;
|
using (context.PushClip(bounds))
|
||||||
double halfWidth = sampleWidth / 2;
|
|
||||||
double halfHeight = this.Bounds.Height / 2f;
|
|
||||||
|
|
||||||
|
|
||||||
if (selectedSamples != null)
|
|
||||||
{
|
{
|
||||||
int first = selectedSamples.Start;
|
|
||||||
double start = (first - FirstSample) * sampleWidth;
|
|
||||||
double end = sampleWidth * selectedSamples.SampleCount;
|
|
||||||
context.FillRectangle(GraphicObjectsCache.GetBrush(Color.FromArgb(128, 255, 255, 255)), new Rect(start, 0, end, this.Bounds.Height));
|
|
||||||
|
|
||||||
}
|
if(updating)
|
||||||
|
return;
|
||||||
|
|
||||||
if (regions.Count > 0)
|
context.FillRectangle(Background, bounds);
|
||||||
{
|
|
||||||
foreach (var region in regions)
|
if (VisibleSamples == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
double sampleWidth = this.Bounds.Width / VisibleSamples;
|
||||||
|
double halfWidth = sampleWidth / 2;
|
||||||
|
double halfHeight = this.Bounds.Height / 2f;
|
||||||
|
|
||||||
|
|
||||||
|
if (selectedSamples != null)
|
||||||
{
|
{
|
||||||
int first = region.FirstSample;
|
int first = selectedSamples.Start;
|
||||||
double start = (first - FirstSample) * sampleWidth;
|
double start = (first - FirstSample) * sampleWidth;
|
||||||
double end = sampleWidth * region.SampleCount;
|
double end = sampleWidth * selectedSamples.SampleCount;
|
||||||
context.FillRectangle(GraphicObjectsCache.GetBrush(region.RegionColor), new Rect(start, 0, end, this.Bounds.Height));
|
context.FillRectangle(GraphicObjectsCache.GetBrush(Color.FromArgb(128, 255, 255, 255)), new Rect(start, 0, end, this.Bounds.Height));
|
||||||
FormattedText text = new FormattedText(region.RegionName, Typeface.Default, 12, TextAlignment.Left, TextWrapping.NoWrap, Size.Infinity);
|
|
||||||
context.DrawText(GraphicObjectsCache.GetBrush(Colors.White), new Point(start + (end / 2) - (text.Bounds.Width / 2), 5), text);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
int increment;
|
if (regions.Count > 0)
|
||||||
|
|
||||||
if (VisibleSamples < 101)
|
|
||||||
increment = 1;
|
|
||||||
else if (VisibleSamples < 501)
|
|
||||||
increment = 5;
|
|
||||||
else if (VisibleSamples < 1001)
|
|
||||||
increment = 10;
|
|
||||||
else
|
|
||||||
increment = 20;
|
|
||||||
|
|
||||||
//Draw ticks
|
|
||||||
for (int buc = 0; buc < VisibleSamples; buc += increment)
|
|
||||||
{
|
|
||||||
double x = buc * sampleWidth;
|
|
||||||
double y1 = halfHeight * 1.5f;
|
|
||||||
double y2 = this.Bounds.Height;
|
|
||||||
|
|
||||||
context.DrawLine(GraphicObjectsCache.GetPen(Foreground, 1), new Point(x, y1), new Point(x, y2));
|
|
||||||
|
|
||||||
if (increment == 1)
|
|
||||||
{
|
{
|
||||||
x = buc * sampleWidth +halfWidth;
|
foreach (var region in regions)
|
||||||
y1 = halfHeight * 1.75f;
|
{
|
||||||
|
int first = region.FirstSample;
|
||||||
|
double start = (first - FirstSample) * sampleWidth;
|
||||||
|
double end = sampleWidth * region.SampleCount;
|
||||||
|
context.FillRectangle(GraphicObjectsCache.GetBrush(region.RegionColor), new Rect(start, 0, end, this.Bounds.Height));
|
||||||
|
FormattedText text = new FormattedText(region.RegionName, Typeface.Default, 12, TextAlignment.Left, TextWrapping.NoWrap, Size.Infinity);
|
||||||
|
context.DrawText(GraphicObjectsCache.GetBrush(Colors.White), new Point(start + (end / 2) - (text.Bounds.Width / 2), 5), text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int increment;
|
||||||
|
|
||||||
|
if (VisibleSamples < 101)
|
||||||
|
increment = 1;
|
||||||
|
else if (VisibleSamples < 501)
|
||||||
|
increment = 5;
|
||||||
|
else if (VisibleSamples < 1001)
|
||||||
|
increment = 10;
|
||||||
|
else
|
||||||
|
increment = 20;
|
||||||
|
|
||||||
|
//Draw ticks
|
||||||
|
for (int buc = 0; buc < VisibleSamples; buc += increment)
|
||||||
|
{
|
||||||
|
double x = buc * sampleWidth;
|
||||||
|
double y1 = halfHeight * 1.5f;
|
||||||
|
double y2 = this.Bounds.Height;
|
||||||
|
|
||||||
context.DrawLine(GraphicObjectsCache.GetPen(Foreground, 1), new Point(x, y1), new Point(x, y2));
|
context.DrawLine(GraphicObjectsCache.GetPen(Foreground, 1), new Point(x, y1), new Point(x, y2));
|
||||||
|
|
||||||
|
if (increment == 1)
|
||||||
|
{
|
||||||
|
x = buc * sampleWidth + halfWidth;
|
||||||
|
y1 = halfHeight * 1.75f;
|
||||||
|
|
||||||
|
context.DrawLine(GraphicObjectsCache.GetPen(Foreground, 1), new Point(x, y1), new Point(x, y2));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
if (analysisData.Count > 0)
|
||||||
|
{
|
||||||
|
foreach (var chan in analysisData)
|
||||||
|
{
|
||||||
|
foreach (var evt in chan.Segments)
|
||||||
|
{
|
||||||
|
double x1 = (evt.FirstSample - FirstSample) * sampleWidth;
|
||||||
|
double x2 = (evt.LastSample + 1 - FirstSample) * sampleWidth;
|
||||||
|
double y1 = 0;
|
||||||
|
double y2 = this.Bounds.Height;
|
||||||
|
|
||||||
base.Render(context);
|
Rect r = new Rect(new Point(x1, y1), new Point(x2, y2));
|
||||||
|
context.FillRectangle(GraphicObjectsCache.GetBrush(chan.BackColor), r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
base.Render(context);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnPointerMoved(PointerEventArgs e)
|
protected override void OnPointerMoved(PointerEventArgs e)
|
||||||
|
|
|
@ -3,6 +3,7 @@ using Avalonia.Controls;
|
||||||
using Avalonia.Interactivity;
|
using Avalonia.Interactivity;
|
||||||
using Avalonia.Markup.Xaml;
|
using Avalonia.Markup.Xaml;
|
||||||
using Avalonia.Media;
|
using Avalonia.Media;
|
||||||
|
using LogicAnalyzer.Classes;
|
||||||
using LogicAnalyzer.Extensions;
|
using LogicAnalyzer.Extensions;
|
||||||
using LogicAnalyzer.Protocols;
|
using LogicAnalyzer.Protocols;
|
||||||
using System;
|
using System;
|
||||||
|
@ -19,6 +20,9 @@ namespace LogicAnalyzer.Dialogs
|
||||||
ProtocolAnalyzerBase analyzer;
|
ProtocolAnalyzerBase analyzer;
|
||||||
public ProtocolAnalyzerBase Analyzer { get { return analyzer; } set { analyzer = value; LoadControls(); } }
|
public ProtocolAnalyzerBase Analyzer { get { return analyzer; } set { analyzer = value; LoadControls(); } }
|
||||||
|
|
||||||
|
AnalysisSettings? initialSettings;
|
||||||
|
public AnalysisSettings? InitialSettings { get { return initialSettings; } set { initialSettings = value; LoadControls(); } }
|
||||||
|
|
||||||
Channel[] channels;
|
Channel[] channels;
|
||||||
public Channel[] Channels { get { return channels; } set { channels = value; LoadControls(); } }
|
public Channel[] Channels { get { return channels; } set { channels = value; LoadControls(); } }
|
||||||
|
|
||||||
|
@ -60,10 +64,18 @@ namespace LogicAnalyzer.Dialogs
|
||||||
{
|
{
|
||||||
var signal = signals[buc];
|
var signal = signals[buc];
|
||||||
|
|
||||||
pnlControls.Children.Add(new TextBlock{ IsVisible = true, Name = $"Label_Signal{buc}", Text = $"Channel for signal { signal.SignalName }:" });
|
pnlControls.Children.Add(new TextBlock{ IsVisible = true, Name = $"Label_Signal{buc}", Text = signal.IsBus ? $"First channel of bus {signal.SignalName}" : $"Channel for signal { signal.SignalName }:" });
|
||||||
|
|
||||||
var list = new ComboBox { IsVisible = true, Name = $"List_Signal{buc}", Items = channelsSource.ToArray(), HorizontalAlignment=Avalonia.Layout.HorizontalAlignment.Stretch, Margin= new Thickness(0,10,20,0) };
|
var list = new ComboBox { IsVisible = true, Name = $"List_Signal{buc}", Items = channelsSource.ToArray(), HorizontalAlignment=Avalonia.Layout.HorizontalAlignment.Stretch, Margin= new Thickness(0,10,20,0) };
|
||||||
|
|
||||||
|
if (initialSettings != null)
|
||||||
|
{
|
||||||
|
var chan = initialSettings.Channels?.FirstOrDefault(c => c.SignalName == signal.SignalName && c.BusIndex == 0);
|
||||||
|
|
||||||
|
if(chan != null)
|
||||||
|
list.SelectedIndex = chan.ChannelIndex + 1;
|
||||||
|
}
|
||||||
|
|
||||||
pnlControls.Children.Add(list);
|
pnlControls.Children.Add(list);
|
||||||
|
|
||||||
list.SelectionChanged += SignalChannel_SelectedIndexChanged;
|
list.SelectionChanged += SignalChannel_SelectedIndexChanged;
|
||||||
|
@ -87,13 +99,32 @@ namespace LogicAnalyzer.Dialogs
|
||||||
case ProtocolAnalyzerSetting.ProtocolAnalyzerSettingType.Boolean:
|
case ProtocolAnalyzerSetting.ProtocolAnalyzerSettingType.Boolean:
|
||||||
|
|
||||||
var ck = new CheckBox { IsVisible = true, Name = $"Check_Index{buc}", Content = set.CheckCaption, Margin = new Thickness(0, 10, 20, 0) };
|
var ck = new CheckBox { IsVisible = true, Name = $"Check_Index{buc}", Content = set.CheckCaption, Margin = new Thickness(0, 10, 20, 0) };
|
||||||
|
|
||||||
|
if (initialSettings != null)
|
||||||
|
{
|
||||||
|
var setV = initialSettings.Settings?.FirstOrDefault(s => s.SettingIndex == buc);
|
||||||
|
|
||||||
|
if(setV != null)
|
||||||
|
ck.IsChecked = (bool)(setV.Value ?? false);
|
||||||
|
}
|
||||||
|
|
||||||
pnlControls.Children.Add(ck);
|
pnlControls.Children.Add(ck);
|
||||||
|
|
||||||
ck.Checked += BooleanSetting_CheckedChanged;
|
ck.Checked += BooleanSetting_CheckedChanged;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ProtocolAnalyzerSetting.ProtocolAnalyzerSettingType.Integer:
|
case ProtocolAnalyzerSetting.ProtocolAnalyzerSettingType.Integer:
|
||||||
|
|
||||||
var nud = new NumericUpDown { IsVisible = true, Name = $"Numeric_Index{buc}", Minimum = set.IntegerMinimumValue, Maximum = set.IntegerMaximumValue, HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Stretch, Margin = new Thickness(0, 10, 20, 0) };
|
var nud = new NumericUpDown { IsVisible = true, Name = $"Numeric_Index{buc}", Minimum = set.IntegerMinimumValue, Maximum = set.IntegerMaximumValue, HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Stretch, Margin = new Thickness(0, 10, 20, 0), Value = set.IntegerMinimumValue };
|
||||||
|
|
||||||
|
if (initialSettings != null)
|
||||||
|
{
|
||||||
|
var setV = initialSettings.Settings?.FirstOrDefault(s => s.SettingIndex == buc);
|
||||||
|
|
||||||
|
if (setV != null)
|
||||||
|
nud.Value = (int)(setV.Value ?? 0);
|
||||||
|
}
|
||||||
|
|
||||||
pnlControls.Children.Add(nud);
|
pnlControls.Children.Add(nud);
|
||||||
nud.ValueChanged += IntegerSetting_ValueChanged;
|
nud.ValueChanged += IntegerSetting_ValueChanged;
|
||||||
break;
|
break;
|
||||||
|
@ -101,6 +132,15 @@ namespace LogicAnalyzer.Dialogs
|
||||||
case ProtocolAnalyzerSetting.ProtocolAnalyzerSettingType.List:
|
case ProtocolAnalyzerSetting.ProtocolAnalyzerSettingType.List:
|
||||||
|
|
||||||
var list = new ComboBox { IsVisible = true, Name = $"List_Index{buc}", Items = set.ListValues, HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Stretch, Margin = new Thickness(0, 10, 20, 0) };
|
var list = new ComboBox { IsVisible = true, Name = $"List_Index{buc}", Items = set.ListValues, HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Stretch, Margin = new Thickness(0, 10, 20, 0) };
|
||||||
|
|
||||||
|
if (initialSettings != null)
|
||||||
|
{
|
||||||
|
var setV = initialSettings.Settings?.FirstOrDefault(s => s.SettingIndex == buc);
|
||||||
|
|
||||||
|
if (setV != null)
|
||||||
|
list.SelectedIndex = Array.IndexOf(set.ListValues, setV.Value);
|
||||||
|
}
|
||||||
|
|
||||||
pnlControls.Children.Add(list);
|
pnlControls.Children.Add(list);
|
||||||
list.SelectionChanged += ListSetting_SelectedIndexChanged;
|
list.SelectionChanged += ListSetting_SelectedIndexChanged;
|
||||||
break;
|
break;
|
||||||
|
@ -112,6 +152,7 @@ namespace LogicAnalyzer.Dialogs
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ValidateSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ListSetting_SelectedIndexChanged(object? sender, RoutedEventArgs e)
|
private void ListSetting_SelectedIndexChanged(object? sender, RoutedEventArgs e)
|
||||||
|
@ -137,9 +178,16 @@ namespace LogicAnalyzer.Dialogs
|
||||||
void ValidateSettings()
|
void ValidateSettings()
|
||||||
{
|
{
|
||||||
var st = ComposeSettings();
|
var st = ComposeSettings();
|
||||||
var ch = ComposeChannels();
|
|
||||||
|
|
||||||
if (st == null || ch == null)
|
if (st == null)
|
||||||
|
{
|
||||||
|
btnAccept.IsEnabled = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var ch = ComposeChannels(st);
|
||||||
|
|
||||||
|
if (ch == null)
|
||||||
{
|
{
|
||||||
btnAccept.IsEnabled = false;
|
btnAccept.IsEnabled = false;
|
||||||
return;
|
return;
|
||||||
|
@ -221,7 +269,7 @@ namespace LogicAnalyzer.Dialogs
|
||||||
return settingsValues.ToArray();
|
return settingsValues.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
ProtocolAnalyzerSelectedChannel[]? ComposeChannels()
|
ProtocolAnalyzerSelectedChannel[]? ComposeChannels(ProtocolAnalyzerSettingValue[] values)
|
||||||
{
|
{
|
||||||
if (analyzer == null || channels == null)
|
if (analyzer == null || channels == null)
|
||||||
return null;
|
return null;
|
||||||
|
@ -240,11 +288,37 @@ namespace LogicAnalyzer.Dialogs
|
||||||
if (list.SelectedIndex == -1)
|
if (list.SelectedIndex == -1)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
selectedChannels.Add(new ProtocolAnalyzerSelectedChannel
|
var size = signal.IsBus ? analyzer.GetBusWidth(signal, values) : 1;
|
||||||
|
|
||||||
|
if (size == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int idx = list.SelectedIndex - 1;
|
||||||
|
|
||||||
|
if (idx + size > channels.Length)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (size == 1)
|
||||||
{
|
{
|
||||||
ChannelIndex = list.SelectedIndex - 1,
|
|
||||||
SignalName = signal.SignalName
|
selectedChannels.Add(new ProtocolAnalyzerSelectedChannel
|
||||||
});
|
{
|
||||||
|
ChannelIndex = idx,
|
||||||
|
SignalName = signal.SignalName
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int bucS = 0; bucS < size; bucS++)
|
||||||
|
{
|
||||||
|
selectedChannels.Add(new ProtocolAnalyzerSelectedChannel
|
||||||
|
{
|
||||||
|
ChannelIndex = idx + bucS,
|
||||||
|
SignalName = signal.SignalName,
|
||||||
|
BusIndex = bucS
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return selectedChannels.ToArray();
|
return selectedChannels.ToArray();
|
||||||
|
@ -258,7 +332,7 @@ namespace LogicAnalyzer.Dialogs
|
||||||
private void btnAccept_Click(object? sender, RoutedEventArgs e)
|
private void btnAccept_Click(object? sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
SelectedSettings = ComposeSettings();
|
SelectedSettings = ComposeSettings();
|
||||||
SelectedChannels = ComposeChannels();
|
SelectedChannels = ComposeChannels(SelectedSettings);
|
||||||
this.Close(true);
|
this.Close(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -366,6 +366,7 @@ namespace LogicAnalyzer
|
||||||
sampleMarker.VisibleSamples = sampleViewer.SamplesInScreen;
|
sampleMarker.VisibleSamples = sampleViewer.SamplesInScreen;
|
||||||
sampleMarker.FirstSample = sampleViewer.FirstSample;
|
sampleMarker.FirstSample = sampleViewer.FirstSample;
|
||||||
sampleMarker.ClearRegions();
|
sampleMarker.ClearRegions();
|
||||||
|
sampleMarker.ClearAnalyzedChannels();
|
||||||
|
|
||||||
scrSamplePos.Maximum = samples.Length - 1;
|
scrSamplePos.Maximum = samples.Length - 1;
|
||||||
scrSamplePos.Value = sampleViewer.FirstSample;
|
scrSamplePos.Value = sampleViewer.FirstSample;
|
||||||
|
@ -592,6 +593,7 @@ namespace LogicAnalyzer
|
||||||
sampleMarker.VisibleSamples = sampleViewer.SamplesInScreen;
|
sampleMarker.VisibleSamples = sampleViewer.SamplesInScreen;
|
||||||
sampleMarker.FirstSample = sampleViewer.FirstSample;
|
sampleMarker.FirstSample = sampleViewer.FirstSample;
|
||||||
sampleMarker.ClearRegions();
|
sampleMarker.ClearRegions();
|
||||||
|
sampleMarker.ClearAnalyzedChannels();
|
||||||
|
|
||||||
if (finalRegions.Count > 0)
|
if (finalRegions.Count > 0)
|
||||||
sampleMarker.AddRegions(finalRegions);
|
sampleMarker.AddRegions(finalRegions);
|
||||||
|
@ -766,6 +768,7 @@ namespace LogicAnalyzer
|
||||||
sampleMarker.VisibleSamples = sampleViewer.SamplesInScreen;
|
sampleMarker.VisibleSamples = sampleViewer.SamplesInScreen;
|
||||||
sampleMarker.FirstSample = sampleViewer.FirstSample;
|
sampleMarker.FirstSample = sampleViewer.FirstSample;
|
||||||
sampleMarker.ClearRegions();
|
sampleMarker.ClearRegions();
|
||||||
|
sampleMarker.ClearAnalyzedChannels();
|
||||||
|
|
||||||
btnCapture.IsEnabled = true;
|
btnCapture.IsEnabled = true;
|
||||||
btnRepeat.IsEnabled = true;
|
btnRepeat.IsEnabled = true;
|
||||||
|
@ -852,6 +855,9 @@ namespace LogicAnalyzer
|
||||||
sampleViewer.BeginUpdate();
|
sampleViewer.BeginUpdate();
|
||||||
sampleViewer.AddAnalyzedChannels(analysisResult);
|
sampleViewer.AddAnalyzedChannels(analysisResult);
|
||||||
sampleViewer.EndUpdate();
|
sampleViewer.EndUpdate();
|
||||||
|
sampleMarker.BeginUpdate();
|
||||||
|
sampleMarker.AddAnalyzedChannels(analysisResult);
|
||||||
|
sampleMarker.EndUpdate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -860,6 +866,9 @@ namespace LogicAnalyzer
|
||||||
sampleViewer.BeginUpdate();
|
sampleViewer.BeginUpdate();
|
||||||
sampleViewer.ClearAnalyzedChannels();
|
sampleViewer.ClearAnalyzedChannels();
|
||||||
sampleViewer.EndUpdate();
|
sampleViewer.EndUpdate();
|
||||||
|
sampleMarker.BeginUpdate();
|
||||||
|
sampleMarker.ClearAnalyzedChannels();
|
||||||
|
sampleMarker.EndUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void ProtocolAnalyzer_Click(object? sender, RoutedEventArgs e)
|
private async void ProtocolAnalyzer_Click(object? sender, RoutedEventArgs e)
|
||||||
|
@ -873,6 +882,10 @@ namespace LogicAnalyzer
|
||||||
|
|
||||||
var dlg = new ProtocolAnalyzerSettingsDialog();
|
var dlg = new ProtocolAnalyzerSettingsDialog();
|
||||||
{
|
{
|
||||||
|
|
||||||
|
if (analysisSettings != null && analysisSettings.Analyzer == analyzer)
|
||||||
|
dlg.InitialSettings = analysisSettings;
|
||||||
|
|
||||||
dlg.Analyzer = analyzer;
|
dlg.Analyzer = analyzer;
|
||||||
dlg.Channels = channelViewer.Channels.Select(c =>
|
dlg.Channels = channelViewer.Channels.Select(c =>
|
||||||
{
|
{
|
||||||
|
@ -907,6 +920,10 @@ namespace LogicAnalyzer
|
||||||
sampleViewer.BeginUpdate();
|
sampleViewer.BeginUpdate();
|
||||||
sampleViewer.AddAnalyzedChannels(analysisResult);
|
sampleViewer.AddAnalyzedChannels(analysisResult);
|
||||||
sampleViewer.EndUpdate();
|
sampleViewer.EndUpdate();
|
||||||
|
|
||||||
|
sampleMarker.BeginUpdate();
|
||||||
|
sampleMarker.AddAnalyzedChannels(analysisResult);
|
||||||
|
sampleMarker.EndUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
analysisSettings = new AnalysisSettings { Analyzer = analyzer, Channels = channels, Settings = dlg.SelectedSettings };
|
analysisSettings = new AnalysisSettings { Analyzer = analyzer, Channels = channels, Settings = dlg.SelectedSettings };
|
||||||
|
@ -1296,6 +1313,7 @@ namespace LogicAnalyzer
|
||||||
sampleMarker.VisibleSamples = sampleViewer.SamplesInScreen;
|
sampleMarker.VisibleSamples = sampleViewer.SamplesInScreen;
|
||||||
sampleMarker.FirstSample = sampleViewer.FirstSample;
|
sampleMarker.FirstSample = sampleViewer.FirstSample;
|
||||||
sampleMarker.ClearRegions();
|
sampleMarker.ClearRegions();
|
||||||
|
sampleMarker.ClearAnalyzedChannels();
|
||||||
|
|
||||||
if (ex.SelectedRegions != null)
|
if (ex.SelectedRegions != null)
|
||||||
sampleMarker.AddRegions(ex.SelectedRegions);
|
sampleMarker.AddRegions(ex.SelectedRegions);
|
||||||
|
|
|
@ -73,6 +73,10 @@ namespace LogicAnalyzer.Protocols
|
||||||
public string SignalName { get; set; }
|
public string SignalName { get; set; }
|
||||||
//If true the signal must be provided, else the signal is optional
|
//If true the signal must be provided, else the signal is optional
|
||||||
public bool Required { get; set; }
|
public bool Required { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// If true the signal is a bus and the size will be requested to the protocol analyzer
|
||||||
|
/// </summary>
|
||||||
|
public bool IsBus { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -82,6 +86,8 @@ namespace LogicAnalyzer.Protocols
|
||||||
{
|
{
|
||||||
//Signal name for which the channel was selected
|
//Signal name for which the channel was selected
|
||||||
public string SignalName { get; set; }
|
public string SignalName { get; set; }
|
||||||
|
//Index (for buses)
|
||||||
|
public int BusIndex { get; set; }
|
||||||
//Channel index in the channel viewer
|
//Channel index in the channel viewer
|
||||||
public int ChannelIndex { get; set; }
|
public int ChannelIndex { get; set; }
|
||||||
//List of samples
|
//List of samples
|
||||||
|
|
|
@ -35,6 +35,15 @@ namespace LogicAnalyzer.Protocols
|
||||||
/// <returns>An array of analyzed channels</returns>
|
/// <returns>An array of analyzed channels</returns>
|
||||||
public abstract ProtocolAnalyzedChannel[] Analyze(int SamplingRate, int TriggerSample, ProtocolAnalyzerSettingValue[] SelectedSettings, ProtocolAnalyzerSelectedChannel[] SelectedChannels);
|
public abstract ProtocolAnalyzedChannel[] Analyze(int SamplingRate, int TriggerSample, ProtocolAnalyzerSettingValue[] SelectedSettings, ProtocolAnalyzerSelectedChannel[] SelectedChannels);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Informs the analyzer of the size of a bus. By default returns 0 (bus not used).
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="Signal">The bus to get the size for</param>
|
||||||
|
/// <param name="SelectedSettings">The settings the user selected</param>
|
||||||
|
/// <returns>The size of the bus</returns>
|
||||||
|
public virtual int GetBusWidth(ProtocolAnalyzerSignal Signal, ProtocolAnalyzerSettingValue[] SelectedSettings)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ namespace LogicAnalyzer.Protocols
|
||||||
|
|
||||||
public override void RenderSegment(ProtocolAnalyzedChannel Channel, ProtocolAnalyzerDataSegment Segment, DrawingContext G, Rect RenderArea)
|
public override void RenderSegment(ProtocolAnalyzedChannel Channel, ProtocolAnalyzerDataSegment Segment, DrawingContext G, Rect RenderArea)
|
||||||
{
|
{
|
||||||
FormattedText text = new FormattedText(Segment.Value, segmentFont, 12, TextAlignment.Center, TextWrapping.NoWrap, Size.Infinity);
|
FormattedText text = new FormattedText(Segment.Value, segmentFont, 12, TextAlignment.Left, TextWrapping.NoWrap, Size.Infinity);
|
||||||
|
|
||||||
double midY = RenderArea.Y + (RenderArea.Height / 2.0);
|
double midY = RenderArea.Y + (RenderArea.Height / 2.0);
|
||||||
double rectHeight = text.Bounds.Height + 10;
|
double rectHeight = text.Bounds.Height + 10;
|
||||||
|
@ -26,9 +26,6 @@ namespace LogicAnalyzer.Protocols
|
||||||
double bottomY = midY + (rectHeight / 2.0);
|
double bottomY = midY + (rectHeight / 2.0);
|
||||||
double minWidth = text.Bounds.Width + 10.0;
|
double minWidth = text.Bounds.Width + 10.0;
|
||||||
|
|
||||||
if (RenderArea.Width < minWidth)
|
|
||||||
return;
|
|
||||||
|
|
||||||
PathFigure container = new PathFigure();
|
PathFigure container = new PathFigure();
|
||||||
container.StartPoint = new Point(RenderArea.X, midY);
|
container.StartPoint = new Point(RenderArea.X, midY);
|
||||||
container.Segments.Add(new LineSegment { Point = new Point(RenderArea.X + 5, topY) });
|
container.Segments.Add(new LineSegment { Point = new Point(RenderArea.X + 5, topY) });
|
||||||
|
@ -42,11 +39,11 @@ namespace LogicAnalyzer.Protocols
|
||||||
PathGeometry gContainer = new PathGeometry();
|
PathGeometry gContainer = new PathGeometry();
|
||||||
gContainer.Figures.Add(container);
|
gContainer.Figures.Add(container);
|
||||||
|
|
||||||
//G.FillRectangle(GraphicObjectsCache.GetBrush(Channel.BackColor), RenderArea);
|
|
||||||
//G.DrawRectangle(GraphicObjectsCache.GetPen(Channel.ForeColor, 1), RenderArea);
|
|
||||||
|
|
||||||
G.DrawGeometry(GraphicObjectsCache.GetBrush(Channel.BackColor), GraphicObjectsCache.GetPen(Channel.ForeColor, 1), gContainer);
|
G.DrawGeometry(GraphicObjectsCache.GetBrush(Channel.BackColor), GraphicObjectsCache.GetPen(Channel.ForeColor, 1), gContainer);
|
||||||
|
|
||||||
|
if (RenderArea.Width < minWidth)
|
||||||
|
return;
|
||||||
|
|
||||||
G.DrawText(GraphicObjectsCache.GetBrush(Channel.ForeColor), new Point(RenderArea.X + (RenderArea.Width / 2 - text.Bounds.Width / 2), RenderArea.Y + (RenderArea.Height / 2 - text.Bounds.Height / 2)), text);
|
G.DrawText(GraphicObjectsCache.GetBrush(Channel.ForeColor), new Point(RenderArea.X + (RenderArea.Width / 2 - text.Bounds.Width / 2), RenderArea.Y + (RenderArea.Height / 2 - text.Bounds.Height / 2)), text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,475 @@
|
||||||
|
using Avalonia.Media;
|
||||||
|
using AvaloniaEdit.Document;
|
||||||
|
using LogicAnalyzer.Controls;
|
||||||
|
using LogicAnalyzer.Protocols;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
namespace ParallelProtocolAnalyzer
|
||||||
|
{
|
||||||
|
public class ParallelAnalyzer : ProtocolAnalyzerBase
|
||||||
|
{
|
||||||
|
private SimpleSegmentRenderer renderer = new SimpleSegmentRenderer();
|
||||||
|
|
||||||
|
const string CS_SIGNAL_NAME = "CS";
|
||||||
|
const string RD_SIGNAL_NAME = "RD";
|
||||||
|
const string WR_SIGNAL_NAME = "WR";
|
||||||
|
const string DATA_SIGNAL_NAME = "Data";
|
||||||
|
const string ADDR_SIGNAL_NAME = "Address";
|
||||||
|
const string RISING_EDGE = "Rising";
|
||||||
|
const string FALLING_EDGE = "Falling";
|
||||||
|
const string READ_OP = "Read";
|
||||||
|
const string WRITE_OP = "Write";
|
||||||
|
public override string ProtocolName
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return "Parallel";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static ProtocolAnalyzerSetting[] settings = new ProtocolAnalyzerSetting[]
|
||||||
|
{
|
||||||
|
new ProtocolAnalyzerSetting
|
||||||
|
{
|
||||||
|
SettingType = ProtocolAnalyzerSetting.ProtocolAnalyzerSettingType.List,
|
||||||
|
Caption = "CS edge",
|
||||||
|
ListValues = new string[]{ RISING_EDGE, FALLING_EDGE }
|
||||||
|
},
|
||||||
|
new ProtocolAnalyzerSetting
|
||||||
|
{
|
||||||
|
SettingType = ProtocolAnalyzerSetting.ProtocolAnalyzerSettingType.List,
|
||||||
|
Caption = "RD edge",
|
||||||
|
ListValues = new string[]{ RISING_EDGE, FALLING_EDGE }
|
||||||
|
},
|
||||||
|
new ProtocolAnalyzerSetting
|
||||||
|
{
|
||||||
|
SettingType = ProtocolAnalyzerSetting.ProtocolAnalyzerSettingType.List,
|
||||||
|
Caption = "WR edge",
|
||||||
|
ListValues = new string[]{ RISING_EDGE, FALLING_EDGE }
|
||||||
|
},
|
||||||
|
new ProtocolAnalyzerSetting
|
||||||
|
{
|
||||||
|
SettingType = ProtocolAnalyzerSetting.ProtocolAnalyzerSettingType.Integer,
|
||||||
|
Caption = "Read offset (in samples)",
|
||||||
|
IntegerMinimumValue = 0,
|
||||||
|
IntegerMaximumValue = 32
|
||||||
|
},
|
||||||
|
new ProtocolAnalyzerSetting
|
||||||
|
{
|
||||||
|
SettingType = ProtocolAnalyzerSetting.ProtocolAnalyzerSettingType.Integer,
|
||||||
|
Caption = "Write offset (in samples)",
|
||||||
|
IntegerMinimumValue = 0,
|
||||||
|
IntegerMaximumValue = 32
|
||||||
|
},
|
||||||
|
new ProtocolAnalyzerSetting
|
||||||
|
{
|
||||||
|
SettingType = ProtocolAnalyzerSetting.ProtocolAnalyzerSettingType.Integer,
|
||||||
|
Caption = "Data width",
|
||||||
|
IntegerMinimumValue = 4,
|
||||||
|
IntegerMaximumValue = 32
|
||||||
|
},
|
||||||
|
new ProtocolAnalyzerSetting
|
||||||
|
{
|
||||||
|
SettingType = ProtocolAnalyzerSetting.ProtocolAnalyzerSettingType.Integer,
|
||||||
|
Caption = "Address width",
|
||||||
|
IntegerMinimumValue = 0,
|
||||||
|
IntegerMaximumValue = 32
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public override ProtocolAnalyzerSetting[] Settings
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return settings;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ProtocolAnalyzerSignal[] signals = new ProtocolAnalyzerSignal[]
|
||||||
|
{
|
||||||
|
new ProtocolAnalyzerSignal
|
||||||
|
{
|
||||||
|
SignalName = CS_SIGNAL_NAME,
|
||||||
|
Required = false
|
||||||
|
},
|
||||||
|
new ProtocolAnalyzerSignal
|
||||||
|
{
|
||||||
|
SignalName = RD_SIGNAL_NAME,
|
||||||
|
Required = false
|
||||||
|
},
|
||||||
|
new ProtocolAnalyzerSignal
|
||||||
|
{
|
||||||
|
SignalName = WR_SIGNAL_NAME,
|
||||||
|
Required = false
|
||||||
|
},
|
||||||
|
new ProtocolAnalyzerSignal
|
||||||
|
{
|
||||||
|
SignalName = DATA_SIGNAL_NAME,
|
||||||
|
Required = true,
|
||||||
|
IsBus = true
|
||||||
|
},
|
||||||
|
new ProtocolAnalyzerSignal
|
||||||
|
{
|
||||||
|
SignalName = ADDR_SIGNAL_NAME,
|
||||||
|
Required = false,
|
||||||
|
IsBus = true
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
public override ProtocolAnalyzerSignal[] Signals
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return signals;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetBusWidth(ProtocolAnalyzerSignal Signal, ProtocolAnalyzerSettingValue[] SelectedSettings)
|
||||||
|
{
|
||||||
|
if (Signal.SignalName == DATA_SIGNAL_NAME)
|
||||||
|
return (int)SelectedSettings[5].Value;
|
||||||
|
|
||||||
|
if(Signal.SignalName == ADDR_SIGNAL_NAME)
|
||||||
|
return (int)SelectedSettings[6].Value;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override ProtocolAnalyzedChannel[] Analyze(int SamplingRate, int TriggerSample, ProtocolAnalyzerSettingValue[] SelectedSettings, ProtocolAnalyzerSelectedChannel[] SelectedChannels)
|
||||||
|
{
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The protocol analysis can work in two ways:
|
||||||
|
* 1-The CS signal is provided, this is used as the sampling trigger, RD/WR signals will determine
|
||||||
|
* if the OP is read or write, if none of these are provided then the operation is undetermined.
|
||||||
|
*
|
||||||
|
* 2-The CS signal is not provided, then the RD and/or WR signals will be used as trigger
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool csTrigger = false;
|
||||||
|
bool useRD = false;
|
||||||
|
bool useWR = false;
|
||||||
|
|
||||||
|
//Check which trigger signals are used
|
||||||
|
csTrigger = SelectedChannels.Any(c => c.SignalName == CS_SIGNAL_NAME);
|
||||||
|
useRD = SelectedChannels.Any(c => c.SignalName == RD_SIGNAL_NAME);
|
||||||
|
useWR = SelectedChannels.Any(c => c.SignalName == WR_SIGNAL_NAME);
|
||||||
|
|
||||||
|
int csEdge = 0;
|
||||||
|
int rdEdge = 0;
|
||||||
|
int wrEdge = 0;
|
||||||
|
|
||||||
|
//Obtain the edges
|
||||||
|
if (csTrigger && SelectedSettings[0].Value?.ToString() == RISING_EDGE)
|
||||||
|
csEdge = 1;
|
||||||
|
|
||||||
|
if(useRD && SelectedSettings[1].Value?.ToString() == RISING_EDGE)
|
||||||
|
rdEdge = 1;
|
||||||
|
|
||||||
|
if(useWR && SelectedSettings[2].Value?.ToString() == RISING_EDGE)
|
||||||
|
wrEdge = 1;
|
||||||
|
|
||||||
|
//Get the sampling offsets
|
||||||
|
int readOffset = (int)SelectedSettings[3].Value;
|
||||||
|
int writeOffset = (int)SelectedSettings[4].Value;
|
||||||
|
|
||||||
|
//Compose the control channels
|
||||||
|
List<ControlChannel> controls = new List<ControlChannel>();
|
||||||
|
|
||||||
|
if (csTrigger)
|
||||||
|
controls.Add(new ControlChannel { Edge = (byte)csEdge, Samples = SelectedChannels.First(c => c.SignalName == CS_SIGNAL_NAME).Samples, SignalName = CS_SIGNAL_NAME });
|
||||||
|
|
||||||
|
if(useRD)
|
||||||
|
controls.Add(new ControlChannel { Edge = (byte)rdEdge, Samples = SelectedChannels.First(c => c.SignalName == RD_SIGNAL_NAME).Samples, SignalName = RD_SIGNAL_NAME });
|
||||||
|
|
||||||
|
if(useWR)
|
||||||
|
controls.Add(new ControlChannel { Edge = (byte)wrEdge, Samples = SelectedChannels.First(c => c.SignalName == WR_SIGNAL_NAME).Samples, SignalName = WR_SIGNAL_NAME });
|
||||||
|
|
||||||
|
//Compose the data channels
|
||||||
|
byte[][] dataBits = SelectedChannels.Where(c => c.SignalName == DATA_SIGNAL_NAME).OrderBy(c => c.BusIndex).Select(c => c.Samples).ToArray();
|
||||||
|
|
||||||
|
//Compose the address channels
|
||||||
|
byte[][] addressBits = SelectedChannels.Where(c => c.SignalName == ADDR_SIGNAL_NAME).OrderBy(c => c.BusIndex).Select(c => c.Samples).ToArray();
|
||||||
|
|
||||||
|
//Find all ops
|
||||||
|
List<OpData> foundOps = new List<OpData>();
|
||||||
|
int offset = 0;
|
||||||
|
|
||||||
|
OpData? next = FindNextOp(controls, dataBits, addressBits, readOffset, writeOffset, ref offset);
|
||||||
|
|
||||||
|
while (next != null)
|
||||||
|
{
|
||||||
|
foundOps.Add(next);
|
||||||
|
next = FindNextOp(controls, dataBits, addressBits, readOffset, writeOffset, ref offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Compose all the data segments
|
||||||
|
var segments = foundOps.Select(o => ComposeSegment(o, addressBits.Length, dataBits.Length));
|
||||||
|
|
||||||
|
List<ProtocolAnalyzedChannel> results = new List<ProtocolAnalyzedChannel>();
|
||||||
|
|
||||||
|
//If we are using a CS trigger...
|
||||||
|
if (csTrigger)
|
||||||
|
{
|
||||||
|
var csChannel = SelectedChannels.First(c => c.SignalName == CS_SIGNAL_NAME);
|
||||||
|
|
||||||
|
//All the operations are shown in the CS channel
|
||||||
|
ProtocolAnalyzedChannel csChannelData = new ProtocolAnalyzedChannel(csChannel.SignalName, csChannel.ChannelIndex, renderer, segments.ToArray(), Colors.White, Color.FromArgb(100, Colors.Blue.R, Colors.Blue.G, Colors.Blue.B));
|
||||||
|
|
||||||
|
results.Add(csChannelData);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (useRD)
|
||||||
|
{
|
||||||
|
var rdChannel = SelectedChannels.First(c => c.SignalName == RD_SIGNAL_NAME);
|
||||||
|
|
||||||
|
//Show read ops in RD channel
|
||||||
|
ProtocolAnalyzedChannel csChannelData = new ProtocolAnalyzedChannel(rdChannel.SignalName, rdChannel.ChannelIndex, renderer, segments.Where(s => s.Value.Contains(READ_OP)).ToArray(), Colors.White, Color.FromArgb(100, Colors.Green.R, Colors.Green.G, Colors.Green.B));
|
||||||
|
|
||||||
|
results.Add(csChannelData);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (useWR)
|
||||||
|
{
|
||||||
|
var wrChannel = SelectedChannels.First(c => c.SignalName == WR_SIGNAL_NAME);
|
||||||
|
|
||||||
|
//Show read ops in RD channel
|
||||||
|
ProtocolAnalyzedChannel csChannelData = new ProtocolAnalyzedChannel(wrChannel.SignalName, wrChannel.ChannelIndex, renderer, segments.Where(s => s.Value.Contains(WRITE_OP)).ToArray(), Colors.White, Color.FromArgb(100, Colors.Red.R, Colors.Red.G, Colors.Red.B));
|
||||||
|
|
||||||
|
results.Add(csChannelData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return results.ToArray();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private ProtocolAnalyzerDataSegment ComposeSegment(OpData o, int AddressBits, int DataBits)
|
||||||
|
{
|
||||||
|
int addressNibbles = (AddressBits / 4) + ((AddressBits % 4) == 0 ? 0 : 1);
|
||||||
|
int dataNibbles = (DataBits / 4) + ((DataBits % 4) == 0 ? 0 : 1);
|
||||||
|
|
||||||
|
ProtocolAnalyzerDataSegment segment = new ProtocolAnalyzerDataSegment();
|
||||||
|
segment.FirstSample = o.Start;
|
||||||
|
segment.LastSample = o.End - 1;
|
||||||
|
string value = "";
|
||||||
|
|
||||||
|
if (addressNibbles != 0 && o.Address != null)
|
||||||
|
value += $"A: 0x{o.Address.Value.ToString($"X{addressNibbles}")}\r\n";
|
||||||
|
|
||||||
|
if (o.Operation != null)
|
||||||
|
value += $"{o.Operation}: 0x{o.Value.ToString($"X{dataNibbles}")}";
|
||||||
|
else
|
||||||
|
value += $"V: 0x{o.Value.ToString($"X{dataNibbles}")}";
|
||||||
|
|
||||||
|
segment.Value = value;
|
||||||
|
|
||||||
|
return segment;
|
||||||
|
}
|
||||||
|
|
||||||
|
private OpData? FindNextOp(IEnumerable<ControlChannel> controls, byte[][] dataBits, byte[][] addressBits, int readOffset, int writeOffset, ref int offset)
|
||||||
|
{
|
||||||
|
int max = dataBits[0].Length;
|
||||||
|
|
||||||
|
int start = -1;
|
||||||
|
int end = max;
|
||||||
|
|
||||||
|
//Find the trigger and range
|
||||||
|
if (controls.Any(c => c.SignalName == CS_SIGNAL_NAME))
|
||||||
|
{
|
||||||
|
var cs = controls.First(c => c.SignalName == CS_SIGNAL_NAME);
|
||||||
|
|
||||||
|
for (int buc = offset; buc < max; buc++)
|
||||||
|
{
|
||||||
|
if (cs.Samples[buc] == cs.Edge)
|
||||||
|
{
|
||||||
|
start = buc;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (start == -1)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
for (int buc = start; buc < max; buc++)
|
||||||
|
{
|
||||||
|
if (cs.Samples[buc] != cs.Edge)
|
||||||
|
{
|
||||||
|
end = buc;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ControlChannel? trigger = null;
|
||||||
|
|
||||||
|
for (int buc = offset; buc < max; buc++)
|
||||||
|
{
|
||||||
|
foreach(var control in controls)
|
||||||
|
{
|
||||||
|
if (control.Samples[buc] == control.Edge)
|
||||||
|
{
|
||||||
|
trigger = control;
|
||||||
|
start = buc;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (trigger != null)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (trigger == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
for (int buc = start; buc < max; buc++)
|
||||||
|
{
|
||||||
|
if (trigger.Samples[buc] != trigger.Edge)
|
||||||
|
{
|
||||||
|
end = buc;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
OpData op = new OpData { Start = start, End = end };
|
||||||
|
|
||||||
|
int samplePos = start;
|
||||||
|
|
||||||
|
op.Operation = GetOp(controls, samplePos);
|
||||||
|
op.Address = GetAddress(addressBits, samplePos);
|
||||||
|
|
||||||
|
if (op.Operation == READ_OP)
|
||||||
|
{
|
||||||
|
if (start + readOffset < end)
|
||||||
|
samplePos = start + readOffset;
|
||||||
|
else
|
||||||
|
samplePos = end - 1;
|
||||||
|
}
|
||||||
|
else if (op.Operation == WRITE_OP)
|
||||||
|
{
|
||||||
|
if (start + writeOffset < end)
|
||||||
|
samplePos = start + writeOffset;
|
||||||
|
else
|
||||||
|
samplePos = end - 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int maxOffset = readOffset > writeOffset ? readOffset : writeOffset;
|
||||||
|
|
||||||
|
if (start + maxOffset < end)
|
||||||
|
samplePos = start + maxOffset;
|
||||||
|
else
|
||||||
|
samplePos = end - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
op.Value = GetData(dataBits, samplePos);
|
||||||
|
|
||||||
|
offset = end;
|
||||||
|
|
||||||
|
return op;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string? GetOp(IEnumerable<ControlChannel> controls, int samplePos)
|
||||||
|
{
|
||||||
|
var rdChannel = controls.FirstOrDefault(c => c.SignalName == RD_SIGNAL_NAME);
|
||||||
|
var wrChannel = controls.FirstOrDefault(c => c.SignalName == WR_SIGNAL_NAME);
|
||||||
|
|
||||||
|
if(rdChannel == null && wrChannel == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (rdChannel != null && rdChannel.Samples[samplePos] == rdChannel.Edge)
|
||||||
|
return READ_OP;
|
||||||
|
|
||||||
|
if (wrChannel != null && wrChannel.Samples[samplePos] == wrChannel.Edge)
|
||||||
|
return WRITE_OP;
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private uint? GetAddress(byte[][] addressBits, int samplePos)
|
||||||
|
{
|
||||||
|
if(addressBits == null || addressBits.Length == 0)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
uint address = 0;
|
||||||
|
|
||||||
|
for (int buc = 0; buc < addressBits.Length; buc++)
|
||||||
|
address |= (uint)(addressBits[buc][samplePos] << buc);
|
||||||
|
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
|
private uint GetData(byte[][] dataBits, int samplePos)
|
||||||
|
{
|
||||||
|
uint value = 0;
|
||||||
|
|
||||||
|
for(int buc = 0; buc < dataBits.Length; buc++)
|
||||||
|
value |= (uint)(dataBits[buc][samplePos] << buc);
|
||||||
|
|
||||||
|
return value;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool ValidateSettings(ProtocolAnalyzerSettingValue[] SelectedSettings, ProtocolAnalyzerSelectedChannel[] SelectedChannels)
|
||||||
|
{
|
||||||
|
bool csTrigger = false;
|
||||||
|
bool useRD = false;
|
||||||
|
bool useWR = false;
|
||||||
|
|
||||||
|
//Check which trigger signals are used
|
||||||
|
csTrigger = SelectedChannels.Any(c => c.SignalName == CS_SIGNAL_NAME);
|
||||||
|
useRD = SelectedChannels.Any(c => c.SignalName == RD_SIGNAL_NAME);
|
||||||
|
useWR = SelectedChannels.Any(c => c.SignalName == WR_SIGNAL_NAME);
|
||||||
|
|
||||||
|
//If no control signal selected then configuration is invalid
|
||||||
|
if (!csTrigger && !useRD && !useWR)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
//If CS signal is selected, check for the edge selection
|
||||||
|
if(csTrigger && SelectedSettings[0].Value == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
//If RD signal is selected, check for the edge selection
|
||||||
|
if (useRD && SelectedSettings[1].Value == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
//If WR signal is selected, check for the edge selection
|
||||||
|
if (useWR && SelectedSettings[2].Value == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
int addressSize = 0;
|
||||||
|
|
||||||
|
if (SelectedSettings[5].Value != null)
|
||||||
|
addressSize = (int)SelectedSettings[5].Value;
|
||||||
|
|
||||||
|
//If an address size is provided check for its channels
|
||||||
|
if (addressSize > 0 && !SelectedChannels.Any(c => c.SignalName == ADDR_SIGNAL_NAME))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
//Check for the data channels
|
||||||
|
if (!SelectedChannels.Any(c => c.SignalName == DATA_SIGNAL_NAME))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ControlChannel
|
||||||
|
{
|
||||||
|
public string SignalName { get; set; }
|
||||||
|
public byte[] Samples { get; set; }
|
||||||
|
public byte Edge { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private class OpData
|
||||||
|
{
|
||||||
|
public int Start { get; set; }
|
||||||
|
public int End { get; set; }
|
||||||
|
public uint? Address { get; set; }
|
||||||
|
public uint Value { get; set; }
|
||||||
|
public string? Operation { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\LogicAnalyzer\LogicAnalyzer.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
Loading…
Reference in New Issue
Block a user