diff --git a/Electronics/LogicAnalyzer/LogicAnalyzer/LogicAnalyzer-backups/LogicAnalyzer-2022-06-28_083750.zip b/Electronics/LogicAnalyzer/LogicAnalyzer/LogicAnalyzer-backups/LogicAnalyzer-2022-06-28_083750.zip deleted file mode 100644 index 27de05f..0000000 Binary files a/Electronics/LogicAnalyzer/LogicAnalyzer/LogicAnalyzer-backups/LogicAnalyzer-2022-06-28_083750.zip and /dev/null differ diff --git a/Electronics/LogicAnalyzer/LogicAnalyzer/LogicAnalyzer-backups/LogicAnalyzer-2022-06-28_090636.zip b/Electronics/LogicAnalyzer/LogicAnalyzer/LogicAnalyzer-backups/LogicAnalyzer-2022-06-28_090636.zip deleted file mode 100644 index a518d58..0000000 Binary files a/Electronics/LogicAnalyzer/LogicAnalyzer/LogicAnalyzer-backups/LogicAnalyzer-2022-06-28_090636.zip and /dev/null differ diff --git a/Electronics/LogicAnalyzer/LogicAnalyzer/LogicAnalyzer-backups/LogicAnalyzer-2022-07-01_110111.zip b/Electronics/LogicAnalyzer/LogicAnalyzer/LogicAnalyzer-backups/LogicAnalyzer-2022-07-01_110111.zip deleted file mode 100644 index a518d58..0000000 Binary files a/Electronics/LogicAnalyzer/LogicAnalyzer/LogicAnalyzer-backups/LogicAnalyzer-2022-07-01_110111.zip and /dev/null differ diff --git a/Electronics/LogicAnalyzer/LogicAnalyzer/LogicAnalyzer-backups/LogicAnalyzer-2022-07-01_195911.zip b/Electronics/LogicAnalyzer/LogicAnalyzer/LogicAnalyzer-backups/LogicAnalyzer-2022-07-01_195911.zip deleted file mode 100644 index 0734c10..0000000 Binary files a/Electronics/LogicAnalyzer/LogicAnalyzer/LogicAnalyzer-backups/LogicAnalyzer-2022-07-01_195911.zip and /dev/null differ diff --git a/Electronics/LogicAnalyzer/LogicAnalyzer/LogicAnalyzer-backups/LogicAnalyzer-2022-07-01_201155.zip b/Electronics/LogicAnalyzer/LogicAnalyzer/LogicAnalyzer-backups/LogicAnalyzer-2022-07-01_201155.zip deleted file mode 100644 index c7e0933..0000000 Binary files a/Electronics/LogicAnalyzer/LogicAnalyzer/LogicAnalyzer-backups/LogicAnalyzer-2022-07-01_201155.zip and /dev/null differ diff --git a/Electronics/LogicAnalyzer/LogicAnalyzer/LogicAnalyzer-backups/LogicAnalyzer-2022-07-01_202636.zip b/Electronics/LogicAnalyzer/LogicAnalyzer/LogicAnalyzer-backups/LogicAnalyzer-2022-07-01_202636.zip deleted file mode 100644 index 87c9f06..0000000 Binary files a/Electronics/LogicAnalyzer/LogicAnalyzer/LogicAnalyzer-backups/LogicAnalyzer-2022-07-01_202636.zip and /dev/null differ diff --git a/Electronics/LogicAnalyzer/LogicAnalyzer/LogicAnalyzer-backups/LogicAnalyzer-2023-01-12_160609.zip b/Electronics/LogicAnalyzer/LogicAnalyzer/LogicAnalyzer-backups/LogicAnalyzer-2023-01-12_160609.zip new file mode 100644 index 0000000..d31fc94 Binary files /dev/null and b/Electronics/LogicAnalyzer/LogicAnalyzer/LogicAnalyzer-backups/LogicAnalyzer-2023-01-12_160609.zip differ diff --git a/Electronics/LogicAnalyzer/LogicAnalyzer/LogicAnalyzer-backups/LogicAnalyzer-2023-01-12_161609.zip b/Electronics/LogicAnalyzer/LogicAnalyzer/LogicAnalyzer-backups/LogicAnalyzer-2023-01-12_161609.zip new file mode 100644 index 0000000..19dbc90 Binary files /dev/null and b/Electronics/LogicAnalyzer/LogicAnalyzer/LogicAnalyzer-backups/LogicAnalyzer-2023-01-12_161609.zip differ diff --git a/Electronics/LogicAnalyzer/LogicAnalyzer/LogicAnalyzer-backups/LogicAnalyzer-2023-01-12_162609.zip b/Electronics/LogicAnalyzer/LogicAnalyzer/LogicAnalyzer-backups/LogicAnalyzer-2023-01-12_162609.zip new file mode 100644 index 0000000..4e18975 Binary files /dev/null and b/Electronics/LogicAnalyzer/LogicAnalyzer/LogicAnalyzer-backups/LogicAnalyzer-2023-01-12_162609.zip differ diff --git a/Electronics/LogicAnalyzer/LogicAnalyzer/LogicAnalyzer-backups/LogicAnalyzer-2023-01-12_163609.zip b/Electronics/LogicAnalyzer/LogicAnalyzer/LogicAnalyzer-backups/LogicAnalyzer-2023-01-12_163609.zip new file mode 100644 index 0000000..a261ffd Binary files /dev/null and b/Electronics/LogicAnalyzer/LogicAnalyzer/LogicAnalyzer-backups/LogicAnalyzer-2023-01-12_163609.zip differ diff --git a/Electronics/LogicAnalyzer/LogicAnalyzer/LogicAnalyzer-backups/LogicAnalyzer-2023-01-12_164329.zip b/Electronics/LogicAnalyzer/LogicAnalyzer/LogicAnalyzer-backups/LogicAnalyzer-2023-01-12_164329.zip new file mode 100644 index 0000000..d622266 Binary files /dev/null and b/Electronics/LogicAnalyzer/LogicAnalyzer/LogicAnalyzer-backups/LogicAnalyzer-2023-01-12_164329.zip differ diff --git a/Electronics/LogicAnalyzer/LogicAnalyzer/LogicAnalyzer-backups/LogicAnalyzer-2023-01-12_170304.zip b/Electronics/LogicAnalyzer/LogicAnalyzer/LogicAnalyzer-backups/LogicAnalyzer-2023-01-12_170304.zip new file mode 100644 index 0000000..d622266 Binary files /dev/null and b/Electronics/LogicAnalyzer/LogicAnalyzer/LogicAnalyzer-backups/LogicAnalyzer-2023-01-12_170304.zip differ diff --git a/Software/LogicAnalyzer/CLCapture/Program.cs b/Software/LogicAnalyzer/CLCapture/Program.cs index 2883d18..ebdc63c 100644 --- a/Software/LogicAnalyzer/CLCapture/Program.cs +++ b/Software/LogicAnalyzer/CLCapture/Program.cs @@ -130,8 +130,25 @@ return await Parser.Default.ParseArguments(args) if (opts.Trigger.TriggerType == CLTriggerType.Edge) { Console.WriteLine("Starting edge triggered capture..."); - driver.StartCapture(opts.SamplingFrequency, opts.PreSamples, opts.PostSamples, + var resStart = driver.StartCapture(opts.SamplingFrequency, opts.PreSamples, opts.PostSamples, channels, opts.Trigger.Channel - 1, opts.Trigger.Value == "0", CaptureFinished); + + if (resStart != CaptureError.None) + { + switch (resStart) + { + case CaptureError.Busy: + Console.WriteLine("Device is busy, stop the capture before starting a new one."); + return -1; + case CaptureError.BadParams: + Console.WriteLine("Specified parameters are incorrect.\r\n\r\n -Frequency must be between 3.1Khz and 100Mhz\r\n -PreSamples must be between 2 and 31743\r\n -PostSamples must be between 512 and 32767\r\n -Total samples cannot exceed 32767"); + return -1; + case CaptureError.HardwareError: + Console.WriteLine("Device reported error starting capture. Restart the device and try again."); + return -1; + } + } + Console.WriteLine("Capture running..."); } else @@ -150,8 +167,25 @@ return await Parser.Default.ParseArguments(args) triggerPattern |= (UInt16)(1 << buc); } - driver.StartPatternCapture(opts.SamplingFrequency, opts.PreSamples, opts.PostSamples, + var resStart = driver.StartPatternCapture(opts.SamplingFrequency, opts.PreSamples, opts.PostSamples, channels, opts.Trigger.Channel - 1, bitCount, triggerPattern, opts.Trigger.TriggerType == CLTriggerType.Fast, CaptureFinished); + + if (resStart != CaptureError.None) + { + switch (resStart) + { + case CaptureError.Busy: + Console.WriteLine("Device is busy, stop the capture before starting a new one."); + return -1; + case CaptureError.BadParams: + Console.WriteLine("Specified parameters are incorrect.\r\n\r\n -Frequency must be between 3.1Khz and 100Mhz\r\n -PreSamples must be between 2 and 31743\r\n -PostSamples must be between 512 and 32767\r\n -Total samples cannot exceed 32767"); + return -1; + case CaptureError.HardwareError: + Console.WriteLine("Device reported error starting capture. Restart the device and try again."); + return -1; + } + } + Console.WriteLine("Capture running..."); } diff --git a/Software/LogicAnalyzer/LogicAnalyzer/Classes/ExportedCapture.cs b/Software/LogicAnalyzer/LogicAnalyzer/Classes/ExportedCapture.cs index 39aca22..c8c7d1e 100644 --- a/Software/LogicAnalyzer/LogicAnalyzer/Classes/ExportedCapture.cs +++ b/Software/LogicAnalyzer/LogicAnalyzer/Classes/ExportedCapture.cs @@ -1,5 +1,4 @@ -using LogicAnalyzer.Classes; -using Newtonsoft.Json; +using Newtonsoft.Json; using SharedDriver; using System; using System.Collections.Generic; @@ -7,7 +6,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; -namespace LogicAnalyzer +namespace LogicAnalyzer.Classes { public class ExportedCapture { diff --git a/Software/LogicAnalyzer/LogicAnalyzer/Classes/GraphicObjectsCache.cs b/Software/LogicAnalyzer/LogicAnalyzer/Classes/GraphicObjectsCache.cs index ef03064..c0cb0ae 100644 --- a/Software/LogicAnalyzer/LogicAnalyzer/Classes/GraphicObjectsCache.cs +++ b/Software/LogicAnalyzer/LogicAnalyzer/Classes/GraphicObjectsCache.cs @@ -25,7 +25,7 @@ namespace LogicAnalyzer.Classes public static Pen GetPen(Color PenColor, double PenThickness, IDashStyle Style = null) { - string key = "COLOR" + PenColor.ToString() + PenThickness.ToString() + (Style?.ToString() ?? ""); + string key = "COLOR" + PenColor.ToString() + PenThickness.ToString() + GetDashName(Style); if (!_pens.ContainsKey(key)) { @@ -39,7 +39,7 @@ namespace LogicAnalyzer.Classes public static Pen GetPen(IBrush PenBrush, double PenThickness, IDashStyle Style = null) { - string key = "BRUSH" + PenBrush.GetHashCode().ToString() + PenThickness.ToString() + (Style?.ToString() ?? ""); + string key = "BRUSH" + PenBrush.GetHashCode().ToString() + PenThickness.ToString() + GetDashName(Style); if (!_pens.ContainsKey(key)) { @@ -50,5 +50,10 @@ namespace LogicAnalyzer.Classes return _pens[key]; } + + static string GetDashName(IDashStyle Style) + { + return Style == null ? "" : string.Join("", Style.Dashes) + "-" + Style.Offset.ToString(); + } } } diff --git a/Software/LogicAnalyzer/LogicAnalyzer/Classes/SelectedSampleRegion.cs b/Software/LogicAnalyzer/LogicAnalyzer/Classes/SelectedSampleRegion.cs index 3fee98f..b70025b 100644 --- a/Software/LogicAnalyzer/LogicAnalyzer/Classes/SelectedSampleRegion.cs +++ b/Software/LogicAnalyzer/LogicAnalyzer/Classes/SelectedSampleRegion.cs @@ -19,7 +19,7 @@ namespace LogicAnalyzer.Classes { public int FirstSample { get; set; } public int LastSample { get; set; } - public int SampleCount { get { return LastSample - FirstSample; } } + public int SampleCount { get { return Math.Abs(LastSample - FirstSample); } } public string RegionName { get; set; } = ""; public Color RegionColor { get; set; } = Color.FromArgb(128, 255,255,255); diff --git a/Software/LogicAnalyzer/LogicAnalyzer/Controls/ChannelViewer.axaml.cs b/Software/LogicAnalyzer/LogicAnalyzer/Controls/ChannelViewer.axaml.cs index b50617e..3d7b448 100644 --- a/Software/LogicAnalyzer/LogicAnalyzer/Controls/ChannelViewer.axaml.cs +++ b/Software/LogicAnalyzer/LogicAnalyzer/Controls/ChannelViewer.axaml.cs @@ -123,4 +123,15 @@ namespace LogicAnalyzer.Controls { public SelectedSampleRegion? Region { get; set; } } + + public class SamplesEventArgs : EventArgs + { + public int FirstSample { get; set; } + public int SampleCount { get; set; } + } + + public class UserMarkerEventArgs : EventArgs + { + public int Position { get; set; } + } } diff --git a/Software/LogicAnalyzer/LogicAnalyzer/Controls/SampleMarker.axaml b/Software/LogicAnalyzer/LogicAnalyzer/Controls/SampleMarker.axaml index a7f7afb..d8f389b 100644 --- a/Software/LogicAnalyzer/LogicAnalyzer/Controls/SampleMarker.axaml +++ b/Software/LogicAnalyzer/LogicAnalyzer/Controls/SampleMarker.axaml @@ -8,5 +8,12 @@ + + + + + + + diff --git a/Software/LogicAnalyzer/LogicAnalyzer/Controls/SampleMarker.axaml.cs b/Software/LogicAnalyzer/LogicAnalyzer/Controls/SampleMarker.axaml.cs index d2c57a6..ba6d78b 100644 --- a/Software/LogicAnalyzer/LogicAnalyzer/Controls/SampleMarker.axaml.cs +++ b/Software/LogicAnalyzer/LogicAnalyzer/Controls/SampleMarker.axaml.cs @@ -50,14 +50,59 @@ namespace LogicAnalyzer.Controls public event EventHandler RegionCreated; public event EventHandler RegionDeleted; + public event EventHandler SamplesDeleted; + public event EventHandler UserMarkerSelected; + List regions = new List(); SelectedSampleRegion? regionUnderConstruction; + SelectedSampleRegion[] regionsToDelete = null; + + int? userMarker = null; public SelectedSampleRegion[] SelectedRegions { get { return regions.ToArray(); } } public SampleMarker() { InitializeComponent(); + mnuDeleteRegions.Click += MnuDeleteRegions_Click; + mnuDeleteRegionsSamples.Click += MnuDeleteRegionsSamples_Click; + } + + private void MnuDeleteRegionsSamples_Click(object? sender, Avalonia.Interactivity.RoutedEventArgs e) + { + var minDelete = regionsToDelete.Select(r => Math.Min(r.FirstSample, r.LastSample)).Min(); + var maxDelete = regionsToDelete.Select(r => Math.Max(r.LastSample, r.FirstSample)).Max(); + + int len = maxDelete - minDelete; + + if (RegionDeleted != null) + { + foreach (var region in regionsToDelete) + { + RegionDeleted(this, new RegionEventArgs { Region = region }); + RemoveRegion(region); + } + } + + if (SamplesDeleted != null) + SamplesDeleted(this, new SamplesEventArgs { FirstSample = minDelete, SampleCount = len }); + } + + private void MnuDeleteRegions_Click(object? sender, Avalonia.Interactivity.RoutedEventArgs e) + { + var minDelete = regionsToDelete.Select(r => Math.Min(r.FirstSample, r.LastSample)).Min(); + var maxDelete = regionsToDelete.Select(r => Math.Max(r.LastSample, r.FirstSample)).Max(); + + int len = maxDelete - minDelete; + + if (RegionDeleted != null) + { + foreach (var region in regionsToDelete) + { + RegionDeleted(this, new RegionEventArgs { Region = region }); + RemoveRegion(region); + } + } } public void AddRegion(SelectedSampleRegion Region) @@ -111,8 +156,8 @@ namespace LogicAnalyzer.Controls if (regionUnderConstruction != null) { - - double start = (regionUnderConstruction.FirstSample - FirstSample) * sampleWidth; + int first = Math.Min(regionUnderConstruction.FirstSample, regionUnderConstruction.LastSample); + double start = (first - FirstSample) * sampleWidth; double end = sampleWidth * regionUnderConstruction.SampleCount; context.FillRectangle(GraphicObjectsCache.GetBrush(regionUnderConstruction.RegionColor), new Rect(start, 0, end, this.Bounds.Height)); @@ -122,7 +167,8 @@ namespace LogicAnalyzer.Controls { foreach (var region in regions) { - double start = (region.FirstSample - FirstSample) * sampleWidth; + int first = Math.Min(region.FirstSample, region.LastSample); + 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); @@ -138,6 +184,11 @@ namespace LogicAnalyzer.Controls double y2 = this.Bounds.Height; context.DrawLine(GraphicObjectsCache.GetPen(Foreground, 1), new Point(x, y1), new Point(x, y2)); + + x = buc * sampleWidth; + y1 = halfHeight * 1.75f; + + context.DrawLine(GraphicObjectsCache.GetPen(Foreground, 1), new Point(x, y1), new Point(x, y2)); } base.Render(context); @@ -191,7 +242,7 @@ namespace LogicAnalyzer.Controls int ovrSample = (int)(pos.Position.X / sampleWidth) + FirstSample; - regionUnderConstruction = new SelectedSampleRegion { FirstSample = ovrSample, LastSample = ovrSample + 1 }; + regionUnderConstruction = new SelectedSampleRegion { FirstSample = ovrSample, LastSample = ovrSample }; this.InvalidateVisual(); } } @@ -229,12 +280,48 @@ namespace LogicAnalyzer.Controls double sampleWidth = this.Bounds.Width / (float)VisibleSamples; int ovrSample = (int)(pos.Position.X / sampleWidth) + FirstSample; regionUnderConstruction.LastSample = ovrSample + 1; + + if (regionUnderConstruction.LastSample < regionUnderConstruction.FirstSample) + { + int val = regionUnderConstruction.FirstSample; + regionUnderConstruction.FirstSample = regionUnderConstruction.LastSample; + regionUnderConstruction.LastSample = val; + } + var rgn = regionUnderConstruction; regionUnderConstruction = null; if (rgn.SampleCount > 0) { - ShowDialog(rgn); + if (rgn.SampleCount == 1) + { + + if(userMarker != null && userMarker == rgn.FirstSample) + userMarker = null; + + if (e.InputModifiers.HasFlag(InputModifiers.Shift) && userMarker != null) + { + + if (this.UserMarkerSelected != null) + this.UserMarkerSelected(this, new UserMarkerEventArgs { Position = userMarker.Value }); + + rgn.FirstSample = userMarker.Value; + + userMarker = null; + + ShowDialog(rgn); + return; + } + + userMarker = rgn.FirstSample; + + if (this.UserMarkerSelected != null) + this.UserMarkerSelected(this, new UserMarkerEventArgs { Position = rgn.FirstSample }); + + this.InvalidateVisual(); + } + else + ShowDialog(rgn); } else @@ -245,18 +332,26 @@ namespace LogicAnalyzer.Controls double sampleWidth = this.Bounds.Width / (float)VisibleSamples; int ovrSample = (int)(pos.Position.X / sampleWidth) + FirstSample; - var toDelete = regions.Where(r => ovrSample >= r.FirstSample && ovrSample < r.LastSample).ToArray(); + var toDelete = regions.Where(r => ovrSample >= Math.Min(r.FirstSample , r.LastSample) && ovrSample < Math.Max(r.FirstSample, r.LastSample)).ToArray(); - foreach (var region in toDelete) + if (toDelete != null && toDelete.Length > 0) { - if (ovrSample >= region.FirstSample && ovrSample < region.LastSample) - { - if (RegionDeleted != null) - RegionDeleted(this, new RegionEventArgs { Region = region }); - - RemoveRegion(region); - } + regionsToDelete= toDelete; + rgnDeleteMenu.PlacementRect = new Rect(pos.Position.X, pos.Position.Y, 1, 1); + rgnDeleteMenu.Open(); } + + //foreach (var region in toDelete) + //{ + // if (ovrSample >= region.FirstSample && ovrSample < region.LastSample) + // { + + // if (RegionDeleted != null) + // RegionDeleted(this, new RegionEventArgs { Region = region }); + + // RemoveRegion(region); + // } + //} } } } diff --git a/Software/LogicAnalyzer/LogicAnalyzer/Controls/SampleViewer.axaml.cs b/Software/LogicAnalyzer/LogicAnalyzer/Controls/SampleViewer.axaml.cs index 6b0b1e1..f718424 100644 --- a/Software/LogicAnalyzer/LogicAnalyzer/Controls/SampleViewer.axaml.cs +++ b/Software/LogicAnalyzer/LogicAnalyzer/Controls/SampleViewer.axaml.cs @@ -19,6 +19,8 @@ namespace LogicAnalyzer.Controls public int SamplesInScreen { get; set; } public int FirstSample { get; set; } + public int? UserMarker { get; set; } + bool updating = false; List regions = new List(); @@ -26,8 +28,11 @@ namespace LogicAnalyzer.Controls public SelectedSampleRegion[] SelectedRegions { get { return regions.ToArray(); } } List analysisData = new List(); - Color sampleLineColor = Color.FromArgb(80,120,120,120); + Color sampleLineColor = Color.FromArgb(80, 120, 120, 120); Color triggerLineColor = Colors.White; + Color userLineColor = Colors.Cyan; + DashStyle halfDash = new DashStyle(new double[] { 1, 8 }, 0); + DashStyle fullDash = new DashStyle(new double[] { 4, 5 }, 0); public SampleViewer() { InitializeComponent(); @@ -107,7 +112,8 @@ namespace LogicAnalyzer.Controls { foreach (var region in regions) { - double start = (region.FirstSample - FirstSample) * sampleWidth; + int first = Math.Min(region.FirstSample, region.LastSample); + double start = (first - FirstSample) * sampleWidth; double end = sampleWidth * region.SampleCount; context.FillRectangle(GraphicObjectsCache.GetBrush(region.RegionColor), new Rect(start, 0, end, this.Bounds.Height)); } @@ -120,11 +126,16 @@ namespace LogicAnalyzer.Controls uint prevSample = buc == 0 ? 0 : Samples[buc - 1]; double lineX = (buc - FirstSample) * sampleWidth; - context.DrawLine(GraphicObjectsCache.GetPen(sampleLineColor, 1, DashStyle.Dash), new Point(lineX + sampleWidth / 2, 0), new Point(lineX + sampleWidth / 2, thisBounds.Height)); + context.DrawLine(GraphicObjectsCache.GetPen(sampleLineColor, 1, fullDash), new Point(lineX + sampleWidth / 2, 0), new Point(lineX + sampleWidth / 2, thisBounds.Height)); + + context.DrawLine(GraphicObjectsCache.GetPen(sampleLineColor, 1, halfDash), new Point(lineX, 0), new Point(lineX, thisBounds.Height)); if (buc == PreSamples) context.DrawLine(GraphicObjectsCache.GetPen(triggerLineColor, 2), new Point(lineX, 0), new Point(lineX, thisBounds.Height)); + if(UserMarker != null && UserMarker == buc) + context.DrawLine(GraphicObjectsCache.GetPen(userLineColor, 2, DashStyle.DashDot), new Point(lineX, 0), new Point(lineX, thisBounds.Height)); + for (int chan = 0; chan < ChannelCount; chan++) { double lineY; diff --git a/Software/LogicAnalyzer/LogicAnalyzer/Dialogs/CaptureDialog.axaml b/Software/LogicAnalyzer/LogicAnalyzer/Dialogs/CaptureDialog.axaml index 5b7dd57..dfdaba1 100644 --- a/Software/LogicAnalyzer/LogicAnalyzer/Dialogs/CaptureDialog.axaml +++ b/Software/LogicAnalyzer/LogicAnalyzer/Dialogs/CaptureDialog.axaml @@ -27,11 +27,11 @@ Pre samples: - + Post samples: - + diff --git a/Software/LogicAnalyzer/LogicAnalyzer/MainWindow.axaml.cs b/Software/LogicAnalyzer/LogicAnalyzer/MainWindow.axaml.cs index e8ced6a..5880a62 100644 --- a/Software/LogicAnalyzer/LogicAnalyzer/MainWindow.axaml.cs +++ b/Software/LogicAnalyzer/LogicAnalyzer/MainWindow.axaml.cs @@ -40,6 +40,8 @@ namespace LogicAnalyzer btnAbort.Click += btnAbort_Click; sampleMarker.RegionCreated += sampleMarker_RegionCreated; sampleMarker.RegionDeleted += sampleMarker_RegionDeleted; + sampleMarker.UserMarkerSelected += sampleMarker_UserMarkerSelected; + sampleMarker.SamplesDeleted += SampleMarker_SamplesDeleted; tkInScreen.PropertyChanged += tkInScreen_ValueChanged; scrSamplePos.Scroll += scrSamplePos_ValueChanged; mnuOpen.Click += mnuOpen_Click; @@ -50,6 +52,124 @@ namespace LogicAnalyzer RefreshPorts(); } + private async void SampleMarker_SamplesDeleted(object? sender, SamplesEventArgs e) + { + var lastSample = e.FirstSample + e.SampleCount - 1; + var triggerSample = sampleViewer.PreSamples - 1; + + var containsTrigger = e.FirstSample <= triggerSample && lastSample >= triggerSample; + + if(containsTrigger) + { + await ShowError("Error", "Cannot delete the trigger sample."); + return; + } + + var preDelete = sampleViewer.Samples.Take(e.FirstSample); + var postDelete = sampleViewer.Samples.Skip(e.FirstSample + e.SampleCount); + + var finalSamples = preDelete.Concat(postDelete).ToArray(); + + var finalPreSamples = e.FirstSample > triggerSample ? sampleViewer.PreSamples : sampleViewer.PreSamples - e.SampleCount; + + var regions = sampleViewer.SelectedRegions; + List finalRegions = new List(); + + foreach(var region in regions) + { + int minRegion = Math.Min(region.FirstSample, region.LastSample); + int maxRegion = Math.Max(region.FirstSample, region.LastSample); + + if (minRegion >= e.FirstSample && maxRegion <= lastSample) //removed + continue; + + if (maxRegion <= e.FirstSample && maxRegion <= lastSample) //Region before delete, do not modify + { + finalRegions.Add(region); + continue; + } + else if (minRegion >= e.FirstSample && minRegion >= lastSample) //Region after delete, offset n samples + { + region.FirstSample -= e.SampleCount; + region.LastSample -= e.SampleCount; + finalRegions.Add(region); + continue; + } + else if (minRegion >= e.FirstSample && maxRegion > lastSample) //Begin of region cropped + { + region.FirstSample = lastSample + 1; + region.LastSample = maxRegion; + + if (region.LastSample - region.FirstSample < 1) //Regions smaller than 2 samples are removed + continue; + + region.FirstSample -= e.SampleCount; + region.LastSample -= e.SampleCount; + finalRegions.Add(region); + continue; + } + else if (minRegion < e.FirstSample && maxRegion <= lastSample) //End of region cropped + { + region.FirstSample = minRegion; + region.LastSample = e.FirstSample; + + if (region.LastSample - region.FirstSample < 1) //Regions smaller than 2 samples are removed + continue; + + finalRegions.Add(region); + continue; + } + else //Deleted samples are inside region (not possible, just left for sanity) + { + region.LastSample -= e.SampleCount; + + if (region.LastSample - region.FirstSample < 1) //Regions smaller than 2 samples are removed + continue; + + finalRegions.Add(region); + continue; + } + } + + sampleViewer.BeginUpdate(); + sampleViewer.Samples = finalSamples; + sampleViewer.PreSamples = finalPreSamples; + sampleViewer.SamplesInScreen = Math.Min(100, finalSamples.Length / 10); + + if(sampleViewer.FirstSample > finalSamples.Length - 1) + sampleViewer.FirstSample = finalSamples.Length - 1; + + sampleViewer.ClearRegions(); + sampleViewer.ClearAnalyzedChannels(); + + if (finalRegions.Count > 0) + sampleViewer.AddRegions(finalRegions); + + sampleViewer.EndUpdate(); + + sampleMarker.VisibleSamples = sampleViewer.SamplesInScreen; + sampleMarker.FirstSample = sampleViewer.FirstSample; + sampleMarker.ClearRegions(); + + if (finalRegions.Count > 0) + sampleMarker.AddRegions(finalRegions); + + scrSamplePos.Maximum = finalSamples.Length - 1; + scrSamplePos.Value = e.FirstSample - 1; + } + + private void sampleMarker_UserMarkerSelected(object? sender, UserMarkerEventArgs e) + { + sampleViewer.BeginUpdate(); + + if (sampleViewer.UserMarker != null && sampleViewer.UserMarker == e.Position) + sampleViewer.UserMarker = null; + else + sampleViewer.UserMarker = e.Position; + + sampleViewer.EndUpdate(); + } + protected override void OnOpened(EventArgs e) { base.OnOpened(e); @@ -320,26 +440,41 @@ namespace LogicAnalyzer if (settings.TriggerType != 0) { - if (!driver.StartPatternCapture(settings.Frequency, settings.PreTriggerSamples, settings.PostTriggerSamples, settings.CaptureChannels, settings.TriggerChannel, settings.TriggerBitCount, settings.TriggerPattern, settings.TriggerType == 2 ? true : false)) - { - await ShowError("Error", "Device reported error starting capture. Restart the device and try again."); - return; - } + var error = driver.StartPatternCapture(settings.Frequency, settings.PreTriggerSamples, settings.PostTriggerSamples, settings.CaptureChannels, settings.TriggerChannel, settings.TriggerBitCount, settings.TriggerPattern, settings.TriggerType == 2 ? true : false); + + if(error != CaptureError.None) + await ShowError(error); } else { - if (!driver.StartCapture(settings.Frequency, settings.PreTriggerSamples, settings.PostTriggerSamples, settings.CaptureChannels, settings.TriggerChannel, settings.TriggerInverted)) - { - await ShowError("Error", "Device reported error starting capture. Restart the device and try again."); - return; - } + var error = driver.StartCapture(settings.Frequency, settings.PreTriggerSamples, settings.PostTriggerSamples, settings.CaptureChannels, settings.TriggerChannel, settings.TriggerInverted); + + if (error != CaptureError.None) + await ShowError(error); } + btnCapture.IsEnabled = false; btnRepeat.IsEnabled = false; btnOpenClose.IsEnabled = false; btnAbort.IsEnabled = true; } + private async Task ShowError(CaptureError error) + { + switch (error) + { + case CaptureError.Busy: + await ShowError("Error", "Device is busy, stop the capture before starting a new one."); + return; + case CaptureError.BadParams: + await ShowError("Error", "Specified parameters are incorrect.\r\n\r\n -Frequency must be between 3.1Khz and 100Mhz\r\n -PreSamples must be between 2 and 31743\r\n -PostSamples must be between 512 and 32767\r\n -Total samples cannot exceed 32767"); + return; + case CaptureError.HardwareError: + await ShowError("Error", "Device reported error starting capture. Restart the device and try again."); + return; + } + } + private void scrSamplePos_ValueChanged(object? sender, ScrollEventArgs e) { if (sampleViewer.Samples != null) diff --git a/Software/LogicAnalyzer/SharedDriver/LogicAnalyzerDriver.cs b/Software/LogicAnalyzer/SharedDriver/LogicAnalyzerDriver.cs index d184bfb..4fd3f55 100644 --- a/Software/LogicAnalyzer/SharedDriver/LogicAnalyzerDriver.cs +++ b/Software/LogicAnalyzer/SharedDriver/LogicAnalyzerDriver.cs @@ -45,14 +45,14 @@ namespace SharedDriver baseStream.ReadTimeout = Timeout.Infinite; } - public bool StartCapture(int Frequency, int PreSamples, int PostSamples, int[] Channels, int TriggerChannel, bool TriggerInverted, Action? CaptureCompletedHandler = null) + public CaptureError StartCapture(int Frequency, int PreSamples, int PostSamples, int[] Channels, int TriggerChannel, bool TriggerInverted, Action? CaptureCompletedHandler = null) { if (capturing) - return false; + return CaptureError.Busy; - if (Channels == null || Channels.Length == 0 || PreSamples < 2 || PreSamples > (16 * 1024) || (PreSamples + PostSamples) >= (32 * 1024) || Frequency > 100000000) - return false; + if (Channels == null || Channels.Length == 0 || PreSamples < 2 || PreSamples > (30 * 1024 - 1) || PostSamples < 512 || (PreSamples + PostSamples) >= (32 * 1024) || Frequency < 3100 || Frequency > 100000000) + return CaptureError.BadParams; channelCount = Channels.Length; triggerChannel = Array.IndexOf(Channels, TriggerChannel); @@ -89,18 +89,18 @@ namespace SharedDriver { capturing = true; Task.Run(() => ReadCapture(PreSamples + PostSamples)); - return true; + return CaptureError.None; } - return false; + return CaptureError.HardwareError; } - public bool StartPatternCapture(int Frequency, int PreSamples, int PostSamples, int[] Channels, int TriggerChannel, int TriggerBitCount, UInt16 TriggerPattern, bool Fast, Action? CaptureCompletedHandler = null) + public CaptureError StartPatternCapture(int Frequency, int PreSamples, int PostSamples, int[] Channels, int TriggerChannel, int TriggerBitCount, UInt16 TriggerPattern, bool Fast, Action? CaptureCompletedHandler = null) { if (capturing) - return false; + return CaptureError.Busy; - if (Channels == null || Channels.Length == 0 || PreSamples < 2 || PreSamples > (16 * 1024) || (PreSamples + PostSamples) >= (32 * 1024) || Frequency > 100000000) - return false; + if (Channels == null || Channels.Length == 0 || PreSamples < 2 || PreSamples > (30 * 1024 - 1) || PostSamples < 512 || (PreSamples + PostSamples) >= (32 * 1024) || Frequency < 3100 || Frequency > 100000000) + return CaptureError.BadParams; channelCount = Channels.Length; triggerChannel = Array.IndexOf(Channels, TriggerChannel); @@ -138,9 +138,9 @@ namespace SharedDriver { capturing = true; Task.Run(() => ReadCapture(PreSamples + PostSamples)); - return true; + return CaptureError.None; } - return false; + return CaptureError.HardwareError; } public bool StopCapture() @@ -321,6 +321,14 @@ namespace SharedDriver } + public enum CaptureError + { + None, + Busy, + BadParams, + HardwareError + } + public class CaptureEventArgs : EventArgs { public int TriggerChannel { get; set; }