diff --git a/.gitignore b/.gitignore
index 7d8da62..c826b0a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -360,4 +360,7 @@ MigrationBackup/
.ionide/
# Fody - auto-generated XML schema
-FodyWeavers.xsd
\ No newline at end of file
+FodyWeavers.xsd
+
+#Releases folder
+Releases/
\ No newline at end of file
diff --git a/Electronics/LogicAnalyzer/LevelShifter/LevelShifter-backups/LevelShifter-2022-07-13_141853.zip b/Electronics/LogicAnalyzer/LevelShifter/LevelShifter-backups/LevelShifter-2022-07-13_141853.zip
new file mode 100644
index 0000000..89a8d3d
Binary files /dev/null and b/Electronics/LogicAnalyzer/LevelShifter/LevelShifter-backups/LevelShifter-2022-07-13_141853.zip differ
diff --git a/Electronics/LogicAnalyzer/LevelShifter/LevelShifter-backups/LevelShifter-2022-07-13_170533.zip b/Electronics/LogicAnalyzer/LevelShifter/LevelShifter-backups/LevelShifter-2022-07-13_170533.zip
new file mode 100644
index 0000000..89a8d3d
Binary files /dev/null and b/Electronics/LogicAnalyzer/LevelShifter/LevelShifter-backups/LevelShifter-2022-07-13_170533.zip differ
diff --git a/Electronics/LogicAnalyzer/LevelShifter/LevelShifter.kicad_sch b/Electronics/LogicAnalyzer/LevelShifter/LevelShifter.kicad_sch
index b4e2b6f..5113e7d 100644
--- a/Electronics/LogicAnalyzer/LevelShifter/LevelShifter.kicad_sch
+++ b/Electronics/LogicAnalyzer/LevelShifter/LevelShifter.kicad_sch
@@ -1730,10 +1730,10 @@
(property "Reference" "C12" (id 0) (at 78.105 162.56 0)
(effects (font (size 1.27 1.27)) (justify left))
)
- (property "Value" "C" (id 1) (at 78.105 167.64 0)
+ (property "Value" "" (id 1) (at 71.12 170.18 0)
(effects (font (size 1.27 1.27)) (justify left))
)
- (property "Footprint" "Capacitor_SMD:C_0603_1608Metric" (id 2) (at 78.4352 168.91 0)
+ (property "Footprint" "" (id 2) (at 78.4352 168.91 0)
(effects (font (size 1.27 1.27)) hide)
)
(property "Datasheet" "~" (id 3) (at 77.47 165.1 0)
@@ -1749,10 +1749,10 @@
(property "Reference" "C8" (id 0) (at 65.405 162.56 0)
(effects (font (size 1.27 1.27)) (justify left))
)
- (property "Value" "C" (id 1) (at 65.405 167.64 0)
+ (property "Value" "" (id 1) (at 58.42 170.18 0)
(effects (font (size 1.27 1.27)) (justify left))
)
- (property "Footprint" "Capacitor_SMD:C_0603_1608Metric" (id 2) (at 65.7352 168.91 0)
+ (property "Footprint" "" (id 2) (at 65.7352 168.91 0)
(effects (font (size 1.27 1.27)) hide)
)
(property "Datasheet" "~" (id 3) (at 64.77 165.1 0)
@@ -1799,10 +1799,10 @@
(property "Reference" "C11" (id 0) (at 78.105 147.32 0)
(effects (font (size 1.27 1.27)) (justify left))
)
- (property "Value" "C" (id 1) (at 78.105 152.4 0)
+ (property "Value" "" (id 1) (at 71.12 154.94 0)
(effects (font (size 1.27 1.27)) (justify left))
)
- (property "Footprint" "Capacitor_SMD:C_0603_1608Metric" (id 2) (at 78.4352 153.67 0)
+ (property "Footprint" "" (id 2) (at 78.4352 153.67 0)
(effects (font (size 1.27 1.27)) hide)
)
(property "Datasheet" "~" (id 3) (at 77.47 149.86 0)
@@ -1818,10 +1818,10 @@
(property "Reference" "C4" (id 0) (at 52.705 162.56 0)
(effects (font (size 1.27 1.27)) (justify left))
)
- (property "Value" "C" (id 1) (at 52.705 167.64 0)
+ (property "Value" "" (id 1) (at 45.72 170.18 0)
(effects (font (size 1.27 1.27)) (justify left))
)
- (property "Footprint" "Capacitor_SMD:C_0603_1608Metric" (id 2) (at 53.0352 168.91 0)
+ (property "Footprint" "" (id 2) (at 53.0352 168.91 0)
(effects (font (size 1.27 1.27)) hide)
)
(property "Datasheet" "~" (id 3) (at 52.07 165.1 0)
@@ -1837,10 +1837,10 @@
(property "Reference" "C6" (id 0) (at 59.055 162.56 0)
(effects (font (size 1.27 1.27)) (justify left))
)
- (property "Value" "C" (id 1) (at 59.055 167.64 0)
+ (property "Value" "" (id 1) (at 52.07 167.64 0)
(effects (font (size 1.27 1.27)) (justify left))
)
- (property "Footprint" "Capacitor_SMD:C_0603_1608Metric" (id 2) (at 59.3852 168.91 0)
+ (property "Footprint" "" (id 2) (at 59.3852 168.91 0)
(effects (font (size 1.27 1.27)) hide)
)
(property "Datasheet" "~" (id 3) (at 58.42 165.1 0)
@@ -1856,10 +1856,10 @@
(property "Reference" "C1" (id 0) (at 46.355 147.32 0)
(effects (font (size 1.27 1.27)) (justify left))
)
- (property "Value" "C" (id 1) (at 46.355 152.4 0)
+ (property "Value" "" (id 1) (at 39.37 152.4 0)
(effects (font (size 1.27 1.27)) (justify left))
)
- (property "Footprint" "Capacitor_SMD:C_0603_1608Metric" (id 2) (at 46.6852 153.67 0)
+ (property "Footprint" "" (id 2) (at 46.6852 153.67 0)
(effects (font (size 1.27 1.27)) hide)
)
(property "Datasheet" "~" (id 3) (at 45.72 149.86 0)
@@ -1904,8 +1904,8 @@
(in_bom yes) (on_board yes) (fields_autoplaced)
(uuid 6cac8c39-815f-4cff-9d09-f222b31d9be6)
(property "Reference" "J2" (id 0) (at 214.63 73.66 0))
- (property "Value" "" (id 1) (at 214.63 76.2 0))
- (property "Footprint" "" (id 2) (at 213.36 97.79 0)
+ (property "Value" "Conn_02x15_Odd_Even" (id 1) (at 214.63 76.2 0))
+ (property "Footprint" "Connector_PinHeader_2.54mm:PinHeader_2x15_P2.54mm_Horizontal" (id 2) (at 213.36 97.79 0)
(effects (font (size 1.27 1.27)) hide)
)
(property "Datasheet" "~" (id 3) (at 213.36 97.79 0)
@@ -1949,10 +1949,10 @@
(property "Reference" "C7" (id 0) (at 65.405 147.32 0)
(effects (font (size 1.27 1.27)) (justify left))
)
- (property "Value" "C" (id 1) (at 65.405 152.4 0)
+ (property "Value" "" (id 1) (at 58.42 154.94 0)
(effects (font (size 1.27 1.27)) (justify left))
)
- (property "Footprint" "Capacitor_SMD:C_0603_1608Metric" (id 2) (at 65.7352 153.67 0)
+ (property "Footprint" "" (id 2) (at 65.7352 153.67 0)
(effects (font (size 1.27 1.27)) hide)
)
(property "Datasheet" "~" (id 3) (at 64.77 149.86 0)
@@ -1968,10 +1968,10 @@
(property "Reference" "C5" (id 0) (at 59.055 147.32 0)
(effects (font (size 1.27 1.27)) (justify left))
)
- (property "Value" "C" (id 1) (at 59.055 152.4 0)
+ (property "Value" "" (id 1) (at 52.07 152.4 0)
(effects (font (size 1.27 1.27)) (justify left))
)
- (property "Footprint" "Capacitor_SMD:C_0603_1608Metric" (id 2) (at 59.3852 153.67 0)
+ (property "Footprint" "" (id 2) (at 59.3852 153.67 0)
(effects (font (size 1.27 1.27)) hide)
)
(property "Datasheet" "~" (id 3) (at 58.42 149.86 0)
@@ -1987,10 +1987,10 @@
(property "Reference" "C3" (id 0) (at 52.705 147.32 0)
(effects (font (size 1.27 1.27)) (justify left))
)
- (property "Value" "C" (id 1) (at 52.705 152.4 0)
+ (property "Value" "" (id 1) (at 45.72 154.94 0)
(effects (font (size 1.27 1.27)) (justify left))
)
- (property "Footprint" "Capacitor_SMD:C_0603_1608Metric" (id 2) (at 53.0352 153.67 0)
+ (property "Footprint" "" (id 2) (at 53.0352 153.67 0)
(effects (font (size 1.27 1.27)) hide)
)
(property "Datasheet" "~" (id 3) (at 52.07 149.86 0)
@@ -2130,10 +2130,10 @@
(property "Reference" "C9" (id 0) (at 71.755 147.32 0)
(effects (font (size 1.27 1.27)) (justify left))
)
- (property "Value" "C" (id 1) (at 71.755 152.4 0)
+ (property "Value" "" (id 1) (at 64.77 152.4 0)
(effects (font (size 1.27 1.27)) (justify left))
)
- (property "Footprint" "Capacitor_SMD:C_0603_1608Metric" (id 2) (at 72.0852 153.67 0)
+ (property "Footprint" "" (id 2) (at 72.0852 153.67 0)
(effects (font (size 1.27 1.27)) hide)
)
(property "Datasheet" "~" (id 3) (at 71.12 149.86 0)
@@ -2149,10 +2149,10 @@
(property "Reference" "C2" (id 0) (at 46.355 162.56 0)
(effects (font (size 1.27 1.27)) (justify left))
)
- (property "Value" "C" (id 1) (at 46.355 167.64 0)
+ (property "Value" "" (id 1) (at 39.37 167.64 0)
(effects (font (size 1.27 1.27)) (justify left))
)
- (property "Footprint" "Capacitor_SMD:C_0603_1608Metric" (id 2) (at 46.6852 168.91 0)
+ (property "Footprint" "" (id 2) (at 46.6852 168.91 0)
(effects (font (size 1.27 1.27)) hide)
)
(property "Datasheet" "~" (id 3) (at 45.72 165.1 0)
@@ -2168,10 +2168,10 @@
(property "Reference" "C10" (id 0) (at 71.755 162.56 0)
(effects (font (size 1.27 1.27)) (justify left))
)
- (property "Value" "C" (id 1) (at 71.755 167.64 0)
+ (property "Value" "" (id 1) (at 64.77 167.64 0)
(effects (font (size 1.27 1.27)) (justify left))
)
- (property "Footprint" "Capacitor_SMD:C_0603_1608Metric" (id 2) (at 72.0852 168.91 0)
+ (property "Footprint" "" (id 2) (at 72.0852 168.91 0)
(effects (font (size 1.27 1.27)) hide)
)
(property "Datasheet" "~" (id 3) (at 71.12 165.1 0)
@@ -2185,8 +2185,8 @@
(in_bom yes) (on_board yes) (fields_autoplaced)
(uuid fd7a9d01-6879-446c-ae2d-79a9c89ce315)
(property "Reference" "J1" (id 0) (at 214.63 22.86 0))
- (property "Value" "" (id 1) (at 214.63 25.4 0))
- (property "Footprint" "" (id 2) (at 213.36 46.99 0)
+ (property "Value" "Conn_02x15_Odd_Even" (id 1) (at 214.63 25.4 0))
+ (property "Footprint" "Connector_PinSocket_2.54mm:PinSocket_2x15_P2.54mm_Horizontal" (id 2) (at 213.36 46.99 0)
(effects (font (size 1.27 1.27)) hide)
)
(property "Datasheet" "~" (id 3) (at 213.36 46.99 0)
@@ -2230,40 +2230,40 @@
(symbol_instances
(path "/64a70fbb-9737-4a9e-a1ce-8b5215897e72"
- (reference "C1") (unit 1) (value "C") (footprint "Capacitor_SMD:C_0603_1608Metric")
+ (reference "C1") (unit 1) (value "100nf 16v") (footprint "Capacitor_SMD:C_0603_1608Metric")
)
(path "/e0e76faf-8022-4b52-bc87-2867eed80d5a"
- (reference "C2") (unit 1) (value "C") (footprint "Capacitor_SMD:C_0603_1608Metric")
+ (reference "C2") (unit 1) (value "100nf 16v") (footprint "Capacitor_SMD:C_0603_1608Metric")
)
(path "/aef37177-f63f-4fa4-a49c-920b1eedfc74"
- (reference "C3") (unit 1) (value "C") (footprint "Capacitor_SMD:C_0603_1608Metric")
+ (reference "C3") (unit 1) (value "100nf 16v") (footprint "Capacitor_SMD:C_0603_1608Metric")
)
(path "/51686eed-d06e-40b4-867d-060618c735af"
- (reference "C4") (unit 1) (value "C") (footprint "Capacitor_SMD:C_0603_1608Metric")
+ (reference "C4") (unit 1) (value "100nf 16v") (footprint "Capacitor_SMD:C_0603_1608Metric")
)
(path "/8c5249bf-6898-4f48-87c8-9e04fb1996c5"
- (reference "C5") (unit 1) (value "C") (footprint "Capacitor_SMD:C_0603_1608Metric")
+ (reference "C5") (unit 1) (value "100nf 16v") (footprint "Capacitor_SMD:C_0603_1608Metric")
)
(path "/5efc62cb-051d-4992-9f32-0a92869698a9"
- (reference "C6") (unit 1) (value "C") (footprint "Capacitor_SMD:C_0603_1608Metric")
+ (reference "C6") (unit 1) (value "100nf 16v") (footprint "Capacitor_SMD:C_0603_1608Metric")
)
(path "/7c3c6d00-6412-4938-b80a-e13de4921c7f"
- (reference "C7") (unit 1) (value "C") (footprint "Capacitor_SMD:C_0603_1608Metric")
+ (reference "C7") (unit 1) (value "100nf 16v") (footprint "Capacitor_SMD:C_0603_1608Metric")
)
(path "/375174a7-7815-4e69-bf06-fe0dff3f2fe6"
- (reference "C8") (unit 1) (value "C") (footprint "Capacitor_SMD:C_0603_1608Metric")
+ (reference "C8") (unit 1) (value "100nf 16v") (footprint "Capacitor_SMD:C_0603_1608Metric")
)
(path "/d48f5449-e275-4df2-84bc-f40d43fc6ffe"
- (reference "C9") (unit 1) (value "C") (footprint "Capacitor_SMD:C_0603_1608Metric")
+ (reference "C9") (unit 1) (value "100nf 16v") (footprint "Capacitor_SMD:C_0603_1608Metric")
)
(path "/f9fc8b9f-a8d8-4e68-be4b-36a54206d91b"
- (reference "C10") (unit 1) (value "C") (footprint "Capacitor_SMD:C_0603_1608Metric")
+ (reference "C10") (unit 1) (value "100nf 16v") (footprint "Capacitor_SMD:C_0603_1608Metric")
)
(path "/4bc45da6-b375-42ac-ba9e-262a4323f1b0"
- (reference "C11") (unit 1) (value "C") (footprint "Capacitor_SMD:C_0603_1608Metric")
+ (reference "C11") (unit 1) (value "100nf 16v") (footprint "Capacitor_SMD:C_0603_1608Metric")
)
(path "/040e7661-85a0-483b-ae6c-7b6f489c582f"
- (reference "C12") (unit 1) (value "C") (footprint "Capacitor_SMD:C_0603_1608Metric")
+ (reference "C12") (unit 1) (value "100nf 16v") (footprint "Capacitor_SMD:C_0603_1608Metric")
)
(path "/fd7a9d01-6879-446c-ae2d-79a9c89ce315"
(reference "J1") (unit 1) (value "Conn_02x15_Odd_Even") (footprint "Connector_PinSocket_2.54mm:PinSocket_2x15_P2.54mm_Horizontal")
diff --git a/Software/LogicAnalyzer/CLCapture/CLCapture.csproj b/Software/LogicAnalyzer/CLCapture/CLCapture.csproj
new file mode 100644
index 0000000..4261cbe
--- /dev/null
+++ b/Software/LogicAnalyzer/CLCapture/CLCapture.csproj
@@ -0,0 +1,18 @@
+
+
+
+ Exe
+ net6.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Software/LogicAnalyzer/CLCapture/CLCaptureCommandLineOptions.cs b/Software/LogicAnalyzer/CLCapture/CLCaptureCommandLineOptions.cs
new file mode 100644
index 0000000..6f2bde0
--- /dev/null
+++ b/Software/LogicAnalyzer/CLCapture/CLCaptureCommandLineOptions.cs
@@ -0,0 +1,92 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using CommandLine;
+
+namespace CLCapture
+{
+ public class CLCaptureCommandLineOptions
+ {
+ [Value(0, Required = true, HelpText = "Device's serial port.")]
+ public string? SerialPort { get; set; }
+ [Value(1, Required = true, HelpText = "Desired sampling frequency.")]
+ public int SamplingFrequency { get; set; }
+ [Value(2, Required = true, HelpText = "List of channels to capture (channels sepparated by comma).")]
+ public string? Channels { get; set; }
+ [Value(3, Required = true, HelpText = "Number of samples to capture before the trigger.")]
+ public int PreSamples { get; set; }
+ [Value(4, Required = true, HelpText = "Number of samples to capture after the trigger.")]
+ public int PostSamples { get; set; }
+ [Value(5, Required = true, HelpText = "Trigger definition in the form of \"TriggerType:(Edge, Fast or Complex),Channel:(base trigger channel),Value:(string containing 1's and 0's indicating each trigger chanel state)\".")]
+ public CLTrigger? Trigger { get; set; }
+ [Value(6, Required = true, HelpText = "Name of the output file.")]
+ public string? OutputFile { get; set; }
+ }
+
+ public class CLTrigger
+ {
+ public CLTrigger(string Data)
+ {
+ string[] parts = Data.Split(",", StringSplitOptions.RemoveEmptyEntries);
+
+ if (parts == null || parts.Length != 3)
+ throw new ArgumentException("Invalid trigger parameters.");
+
+ foreach (var part in parts)
+ {
+ string[] components = part.Split(":", StringSplitOptions.RemoveEmptyEntries);
+
+ if(components == null || components.Length != 2)
+ throw new ArgumentException("Invalid trigger parameters.");
+
+ switch (components[0].ToLower())
+ {
+ case "triggertype":
+
+ CLTriggerType type;
+ var typeParsed = Enum.TryParse(components[1], true, out type);
+
+ if (!typeParsed)
+ throw new ArgumentException($"Unknown trigger type: {type}.");
+
+ TriggerType = type;
+
+ break;
+ case "channel":
+
+ int channel;
+
+ if(!int.TryParse(components[1], out channel))
+ throw new ArgumentException($"Invalid value for trigger channel.");
+
+ Channel = channel;
+
+ break;
+
+ case "value":
+
+ if(components[1].Any(v => v != '0' && v != '1'))
+ throw new ArgumentException($"Trigger values can only be composed of '0's or '1's.");
+
+ Value = components[1];
+
+ break;
+ default:
+ throw new ArgumentException($"Unknown trigger parameter: {components[0]}");
+ }
+ }
+ }
+ public CLTriggerType TriggerType { get; set; }
+ public int Channel { get; set; }
+ public string Value { get; set; }
+ }
+
+ public enum CLTriggerType
+ {
+ Edge,
+ Fast,
+ Complex
+ }
+}
diff --git a/Software/LogicAnalyzer/CLCapture/Program.cs b/Software/LogicAnalyzer/CLCapture/Program.cs
new file mode 100644
index 0000000..2883d18
--- /dev/null
+++ b/Software/LogicAnalyzer/CLCapture/Program.cs
@@ -0,0 +1,199 @@
+using CLCapture;
+using CommandLine;
+using SharedDriver;
+using System.IO.Ports;
+using System.Linq;
+using System.Text;
+
+TaskCompletionSource captureCompletedTask;
+
+return await Parser.Default.ParseArguments(args)
+ .MapResult(async (CLCaptureCommandLineOptions opts) =>
+ {
+ if (string.IsNullOrWhiteSpace(opts.OutputFile))
+ {
+ Console.WriteLine("Missing serial port.");
+ return -1;
+ }
+
+ if (opts.SerialPort == null)
+ {
+ Console.WriteLine("Missing serial port.");
+ return -1;
+ }
+
+ var ports = SerialPort.GetPortNames();
+
+ if (!ports.Any(p => p.ToLower() == opts.SerialPort.ToLower()))
+ {
+ Console.WriteLine("Cannot find specified serial port.");
+ return -1;
+ }
+
+ if (opts.SamplingFrequency > 100000000 || opts.SamplingFrequency < 3100)
+ {
+ Console.WriteLine("Requested sampling frequency out of range (3100-100000000).");
+ return -1;
+ }
+
+ int[]? channels = opts.Channels?.Split(",", StringSplitOptions.RemoveEmptyEntries).Select(c => int.Parse(c)).ToArray();
+
+ if (channels == null || channels.Any(c => c < 1 || c > 24))
+ {
+ Console.WriteLine("Specified capture channels out of range.");
+ return -1;
+ }
+
+ if (opts.PreSamples + opts.PostSamples > 32767)
+ {
+ Console.WriteLine("Total samples exceed the supported maximum (32767).");
+ return -1;
+ }
+
+ if (opts.Trigger == null)
+ {
+ Console.WriteLine("Invalid trigger definition.");
+ return -1;
+ }
+
+ if (opts.Trigger.Value == null)
+ {
+ Console.WriteLine("Invalid trigger value.");
+ return -1;
+ }
+
+ switch (opts.Trigger.TriggerType)
+ {
+ case CLTriggerType.Edge:
+
+ if (opts.Trigger.Channel < 1 || opts.Trigger.Channel > 24)
+ {
+ Console.WriteLine("Trigger channel out of range.");
+ return -1;
+ }
+
+ break;
+
+ case CLTriggerType.Fast:
+
+ if (opts.Trigger.Value.Length > 5)
+ {
+ Console.WriteLine("Fast trigger only supports up to 5 channels.");
+ return -1;
+ }
+
+ if (opts.Trigger.Value.Length + opts.Trigger.Channel > 17)
+ {
+ Console.WriteLine("Fast trigger can only be used with the first 16 channels.");
+ return -1;
+ }
+
+ break;
+
+ case CLTriggerType.Complex:
+
+ if (opts.Trigger.Value.Length > 16)
+ {
+ Console.WriteLine("Complex trigger only supports up to 16 channels.");
+ return -1;
+ }
+
+ if (opts.Trigger.Value.Length + opts.Trigger.Channel > 17)
+ {
+ Console.WriteLine("Complex trigger can only be used with the first 16 channels.");
+ return -1;
+ }
+
+ break;
+ }
+
+ LogicAnalyzerDriver driver;
+
+ Console.WriteLine($"Opening logic analyzer in port {opts.SerialPort}...");
+
+ try
+ {
+ driver = new LogicAnalyzerDriver(opts.SerialPort, 115200);
+ }
+ catch
+ {
+ Console.WriteLine($"Error detecting Logic Analyzer in port {opts.SerialPort}");
+ return -1;
+ }
+
+ Console.WriteLine($"Conneced to device {driver.DeviceVersion} in port {opts.SerialPort}");
+
+ captureCompletedTask = new TaskCompletionSource();
+
+ channels = opts.Channels.Split(",", StringSplitOptions.RemoveEmptyEntries).Select(c => int.Parse(c) - 1).ToArray();
+
+ if (opts.Trigger.TriggerType == CLTriggerType.Edge)
+ {
+ Console.WriteLine("Starting edge triggered capture...");
+ driver.StartCapture(opts.SamplingFrequency, opts.PreSamples, opts.PostSamples,
+ channels, opts.Trigger.Channel - 1, opts.Trigger.Value == "0", CaptureFinished);
+ Console.WriteLine("Capture running...");
+ }
+ else
+ {
+ if (opts.Trigger.TriggerType == CLTriggerType.Fast)
+ Console.WriteLine("Starting fast pattern triggered capture");
+ else
+ Console.WriteLine("Starting complex pattern triggered capture");
+
+ int bitCount = opts.Trigger.Value.Length;
+ ushort triggerPattern = 0;
+
+ for (int buc = 0; buc < opts.Trigger.Value.Length; buc++)
+ {
+ if (opts.Trigger.Value[buc] == '1')
+ triggerPattern |= (UInt16)(1 << buc);
+ }
+
+ driver.StartPatternCapture(opts.SamplingFrequency, opts.PreSamples, opts.PostSamples,
+ channels, opts.Trigger.Channel - 1, bitCount, triggerPattern, opts.Trigger.TriggerType == CLTriggerType.Fast, CaptureFinished);
+ Console.WriteLine("Capture running...");
+ }
+
+ var result = await captureCompletedTask.Task;
+
+ Console.WriteLine("Capture complete, writting output file...");
+
+ var file = File.Create(opts.OutputFile);
+ StreamWriter sw = new StreamWriter(file);
+
+ sw.WriteLine(String.Join(',', channels.Select(c => $"Channel {c+1}").ToArray()));
+
+ StringBuilder sb = new StringBuilder();
+
+ for (int sample = 0; sample < result.Samples.Length; sample++)
+ {
+ sb.Clear();
+
+ for (int buc = 0; buc < opts.Channels.Length; buc++)
+ {
+ if((result.Samples[sample] & (1 << buc)) == 0)
+ sb.Append("0,");
+ else
+ sb.Append("1,");
+ }
+
+ sw.WriteLine(sb.ToString());
+ }
+
+ sw.Close();
+ sw.Dispose();
+ file.Close();
+ file.Dispose();
+
+ Console.WriteLine("Done.");
+
+ return 1;
+
+ },
+ errs => Task.FromResult(-1));
+
+void CaptureFinished(CaptureEventArgs e)
+{
+ captureCompletedTask.SetResult(e);
+}
\ No newline at end of file
diff --git a/Software/LogicAnalyzer/CLCapture/Properties/launchSettings.json b/Software/LogicAnalyzer/CLCapture/Properties/launchSettings.json
new file mode 100644
index 0000000..dcdb277
--- /dev/null
+++ b/Software/LogicAnalyzer/CLCapture/Properties/launchSettings.json
@@ -0,0 +1,8 @@
+{
+ "profiles": {
+ "CLCapture": {
+ "commandName": "Project",
+ "commandLineArgs": "COM12 10000 1,2,3,4 512 1024 TriggerType:Edge,Channel:1,Value:1 Capture.csv"
+ }
+ }
+}
\ No newline at end of file
diff --git a/Software/LogicAnalyzer/LogicAnalyzer.sln b/Software/LogicAnalyzer/LogicAnalyzer.sln
index 8ed6b7f..31e35eb 100644
--- a/Software/LogicAnalyzer/LogicAnalyzer.sln
+++ b/Software/LogicAnalyzer/LogicAnalyzer.sln
@@ -7,6 +7,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LogicAnalyzer", "LogicAnaly
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SPIProtocolAnalyzer", "SPIProtocolAnalyzer\SPIProtocolAnalyzer.csproj", "{C2166CC8-3BD1-4563-BB9F-0001632B449A}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LogicAnalyzerMultiplatform", "LogicAnalyzerMultiplatform\LogicAnalyzerMultiplatform.csproj", "{713605B4-A2B7-4254-91C3-FC2A4F5653D8}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharedDriver", "SharedDriver\SharedDriver.csproj", "{544DB7FA-C828-48A1-922D-F63E2BD479F9}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CLCapture", "CLCapture\CLCapture.csproj", "{AA68B9F9-ABFC-443C-9304-E06F264840F6}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -21,6 +27,18 @@ Global
{C2166CC8-3BD1-4563-BB9F-0001632B449A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C2166CC8-3BD1-4563-BB9F-0001632B449A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C2166CC8-3BD1-4563-BB9F-0001632B449A}.Release|Any CPU.Build.0 = Release|Any CPU
+ {713605B4-A2B7-4254-91C3-FC2A4F5653D8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {713605B4-A2B7-4254-91C3-FC2A4F5653D8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {713605B4-A2B7-4254-91C3-FC2A4F5653D8}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {713605B4-A2B7-4254-91C3-FC2A4F5653D8}.Release|Any CPU.Build.0 = Release|Any CPU
+ {544DB7FA-C828-48A1-922D-F63E2BD479F9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {544DB7FA-C828-48A1-922D-F63E2BD479F9}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {544DB7FA-C828-48A1-922D-F63E2BD479F9}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {544DB7FA-C828-48A1-922D-F63E2BD479F9}.Release|Any CPU.Build.0 = Release|Any CPU
+ {AA68B9F9-ABFC-443C-9304-E06F264840F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {AA68B9F9-ABFC-443C-9304-E06F264840F6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {AA68B9F9-ABFC-443C-9304-E06F264840F6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {AA68B9F9-ABFC-443C-9304-E06F264840F6}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/Software/LogicAnalyzer/LogicAnalyzer/Classes/ExportedCapture.cs b/Software/LogicAnalyzer/LogicAnalyzer/Classes/ExportedCapture.cs
index 694c8aa..4ca7bc9 100644
--- a/Software/LogicAnalyzer/LogicAnalyzer/Classes/ExportedCapture.cs
+++ b/Software/LogicAnalyzer/LogicAnalyzer/Classes/ExportedCapture.cs
@@ -1,4 +1,5 @@
using Newtonsoft.Json;
+using SharedDriver;
using System;
using System.Collections.Generic;
using System.Linq;
diff --git a/Software/LogicAnalyzer/LogicAnalyzer/Dialogs/CaptureDialog.cs b/Software/LogicAnalyzer/LogicAnalyzer/Dialogs/CaptureDialog.cs
index 6bc66a3..c90063b 100644
--- a/Software/LogicAnalyzer/LogicAnalyzer/Dialogs/CaptureDialog.cs
+++ b/Software/LogicAnalyzer/LogicAnalyzer/Dialogs/CaptureDialog.cs
@@ -1,4 +1,5 @@
using Newtonsoft.Json;
+using SharedDriver;
using System;
using System.Collections.Generic;
using System.ComponentModel;
@@ -194,7 +195,7 @@ namespace LogicAnalyzer
if (trigger == -1)
{
- MessageBox.Show("Yo must select a trigger channel. How the heck did you managed to deselect all? ¬¬");
+ MessageBox.Show("You must select a trigger channel. How the heck did you managed to deselect all? ¬¬");
return;
}
diff --git a/Software/LogicAnalyzer/LogicAnalyzer/LogicAnalyzer.csproj b/Software/LogicAnalyzer/LogicAnalyzer/LogicAnalyzer.csproj
index 60db4c2..55aca7a 100644
--- a/Software/LogicAnalyzer/LogicAnalyzer/LogicAnalyzer.csproj
+++ b/Software/LogicAnalyzer/LogicAnalyzer/LogicAnalyzer.csproj
@@ -15,6 +15,10 @@
+
+
+
+
True
diff --git a/Software/LogicAnalyzer/LogicAnalyzer/MainForm.cs b/Software/LogicAnalyzer/LogicAnalyzer/MainForm.cs
index 9e31025..09c1f7c 100644
--- a/Software/LogicAnalyzer/LogicAnalyzer/MainForm.cs
+++ b/Software/LogicAnalyzer/LogicAnalyzer/MainForm.cs
@@ -1,5 +1,6 @@
using LogicAnalyzer.Protocols;
using Newtonsoft.Json;
+using SharedDriver;
using System.IO.Ports;
namespace LogicAnalyzer
diff --git a/Software/LogicAnalyzer/LogicAnalyzer/Properties/PublishProfiles/FolderProfile.pubxml.user b/Software/LogicAnalyzer/LogicAnalyzer/Properties/PublishProfiles/FolderProfile.pubxml.user
index 59db1ef..1e7b936 100644
--- a/Software/LogicAnalyzer/LogicAnalyzer/Properties/PublishProfiles/FolderProfile.pubxml.user
+++ b/Software/LogicAnalyzer/LogicAnalyzer/Properties/PublishProfiles/FolderProfile.pubxml.user
@@ -4,6 +4,6 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
-->
- True|2022-07-08T14:55:29.2331928Z;True|2022-07-03T16:20:52.1046389+02:00;
+ False|2022-07-13T14:45:35.3720563Z;True|2022-07-13T16:45:17.3874110+02:00;True|2022-07-08T18:00:09.3470232+02:00;True|2022-07-08T16:55:29.2331928+02:00;True|2022-07-03T16:20:52.1046389+02:00;
\ No newline at end of file
diff --git a/Software/LogicAnalyzer/LogicAnalyzerMultiplatform/.gitignore b/Software/LogicAnalyzer/LogicAnalyzerMultiplatform/.gitignore
new file mode 100644
index 0000000..48cc008
--- /dev/null
+++ b/Software/LogicAnalyzer/LogicAnalyzerMultiplatform/.gitignore
@@ -0,0 +1,454 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# Tye
+.tye/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Coverlet is a free, cross platform Code Coverage Tool
+coverage*.json
+coverage*.xml
+coverage*.info
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# Fody - auto-generated XML schema
+FodyWeavers.xsd
+
+##
+## Visual studio for Mac
+##
+
+
+# globs
+Makefile.in
+*.userprefs
+*.usertasks
+config.make
+config.status
+aclocal.m4
+install-sh
+autom4te.cache/
+*.tar.gz
+tarballs/
+test-results/
+
+# Mac bundle stuff
+*.dmg
+*.app
+
+# content below from: https://github.com/github/gitignore/blob/master/Global/macOS.gitignore
+# General
+.DS_Store
+.AppleDouble
+.LSOverride
+
+# Icon must end with two \r
+Icon
+
+
+# Thumbnails
+._*
+
+# Files that might appear in the root of a volume
+.DocumentRevisions-V100
+.fseventsd
+.Spotlight-V100
+.TemporaryItems
+.Trashes
+.VolumeIcon.icns
+.com.apple.timemachine.donotpresent
+
+# Directories potentially created on remote AFP share
+.AppleDB
+.AppleDesktop
+Network Trash Folder
+Temporary Items
+.apdisk
+
+# content below from: https://github.com/github/gitignore/blob/master/Global/Windows.gitignore
+# Windows thumbnail cache files
+Thumbs.db
+ehthumbs.db
+ehthumbs_vista.db
+
+# Dump file
+*.stackdump
+
+# Folder config file
+[Dd]esktop.ini
+
+# Recycle Bin used on file shares
+$RECYCLE.BIN/
+
+# Windows Installer files
+*.cab
+*.msi
+*.msix
+*.msm
+*.msp
+
+# Windows shortcuts
+*.lnk
+
+# JetBrains Rider
+.idea/
+*.sln.iml
+
+##
+## Visual Studio Code
+##
+.vscode/*
+!.vscode/settings.json
+!.vscode/tasks.json
+!.vscode/launch.json
+!.vscode/extensions.json
diff --git a/Software/LogicAnalyzer/LogicAnalyzerMultiplatform/App.axaml b/Software/LogicAnalyzer/LogicAnalyzerMultiplatform/App.axaml
new file mode 100644
index 0000000..db3be89
--- /dev/null
+++ b/Software/LogicAnalyzer/LogicAnalyzerMultiplatform/App.axaml
@@ -0,0 +1,7 @@
+
+
+
+
+
diff --git a/Software/LogicAnalyzer/LogicAnalyzerMultiplatform/App.axaml.cs b/Software/LogicAnalyzer/LogicAnalyzerMultiplatform/App.axaml.cs
new file mode 100644
index 0000000..1b5e5b3
--- /dev/null
+++ b/Software/LogicAnalyzer/LogicAnalyzerMultiplatform/App.axaml.cs
@@ -0,0 +1,24 @@
+using Avalonia;
+using Avalonia.Controls.ApplicationLifetimes;
+using Avalonia.Markup.Xaml;
+
+namespace LogicAnalyzerMultiplatform
+{
+ public partial class App : Application
+ {
+ public override void Initialize()
+ {
+ AvaloniaXamlLoader.Load(this);
+ }
+
+ public override void OnFrameworkInitializationCompleted()
+ {
+ if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
+ {
+ desktop.MainWindow = new MainWindow();
+ }
+
+ base.OnFrameworkInitializationCompleted();
+ }
+ }
+}
diff --git a/Software/LogicAnalyzer/LogicAnalyzerMultiplatform/Classes/ChannelColors.cs b/Software/LogicAnalyzer/LogicAnalyzerMultiplatform/Classes/ChannelColors.cs
new file mode 100644
index 0000000..7cd3135
--- /dev/null
+++ b/Software/LogicAnalyzer/LogicAnalyzerMultiplatform/Classes/ChannelColors.cs
@@ -0,0 +1,53 @@
+using Avalonia.Media;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LogicAnalyzerMultiplatform.Classes
+{
+ public static class AnalyzerColors
+ {
+ public static Color[] BgChannelColors => new Color[]
+ {
+ Color.FromRgb(32,32,32),
+ Color.FromRgb(64,64, 64),
+ };
+
+ public static Color[] FgChannelColors => new Color[]
+ {
+ Color.FromRgb(254, 0, 0),
+ Color.FromRgb(128, 255, 0),
+ Color.FromRgb(1, 255, 255),
+ Color.FromRgb(127, 0, 255),
+
+ Color.FromRgb(255, 64, 1),
+ Color.FromRgb(64, 255, 1),
+ Color.FromRgb(0, 192, 255),
+ Color.FromRgb(191, 0, 254),
+
+ Color.FromRgb(255, 127, 0),
+ Color.FromRgb(0, 255, 1),
+ Color.FromRgb(0, 128, 255),
+ Color.FromRgb(255, 0, 254),
+
+ Color.FromRgb(255, 192, 0),
+ Color.FromRgb(0, 255, 65),
+ Color.FromRgb(0, 65, 255),
+ Color.FromRgb(255, 0, 192),
+
+ Color.FromRgb(255, 255, 1),
+ Color.FromRgb(0, 254, 129),
+ Color.FromRgb(0, 0, 254),
+ Color.FromRgb(255, 0, 128),
+
+ Color.FromRgb(192, 255, 0),
+ Color.FromRgb(1, 255, 193),
+ Color.FromRgb(63, 0, 255),
+ Color.FromRgb(255, 1, 65),
+ };
+
+ public static Color TxtColor => Colors.White;
+ }
+}
diff --git a/Software/LogicAnalyzer/LogicAnalyzerMultiplatform/Controls/ChannelViewer.axaml b/Software/LogicAnalyzer/LogicAnalyzerMultiplatform/Controls/ChannelViewer.axaml
new file mode 100644
index 0000000..256c1db
--- /dev/null
+++ b/Software/LogicAnalyzer/LogicAnalyzerMultiplatform/Controls/ChannelViewer.axaml
@@ -0,0 +1,9 @@
+
+
+
+
diff --git a/Software/LogicAnalyzer/LogicAnalyzerMultiplatform/Controls/ChannelViewer.axaml.cs b/Software/LogicAnalyzer/LogicAnalyzerMultiplatform/Controls/ChannelViewer.axaml.cs
new file mode 100644
index 0000000..1835f72
--- /dev/null
+++ b/Software/LogicAnalyzer/LogicAnalyzerMultiplatform/Controls/ChannelViewer.axaml.cs
@@ -0,0 +1,107 @@
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Markup.Xaml;
+using Avalonia.Media;
+using LogicAnalyzerMultiplatform.Classes;
+using System;
+using System.Collections.Generic;
+
+namespace LogicAnalyzerMultiplatform.Controls
+{
+ public partial class ChannelViewer : UserControl
+ {
+ TextBox[] boxes;
+
+ int[] channels;
+ public int[] Channels
+ {
+ get { return channels; }
+ set
+ {
+ channels = value;
+ CreateControls();
+ }
+ }
+
+ private void CreateControls()
+ {
+ ChannelGrid.Children.Clear();
+
+ if (channels == null || channels.Length == 0)
+ return;
+
+ ChannelGrid.RowDefinitions.Clear();
+
+ List newBoxes = new List();
+
+ ChannelGrid.BeginBatchUpdate();
+
+ for (int buc = 0; buc < channels.Length; buc++)
+ {
+ //Create new row
+ ChannelGrid.RowDefinitions.Add(new RowDefinition(GridLength.Star));
+
+ //Create channel grid
+ var newChannelGrid = new Grid();
+
+ newChannelGrid.SetValue(Grid.RowProperty, buc);
+
+ newChannelGrid.VerticalAlignment = Avalonia.Layout.VerticalAlignment.Stretch;
+ newChannelGrid.HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Stretch;
+
+ newChannelGrid.RowDefinitions = new RowDefinitions("*,*");
+
+ newChannelGrid.Background = new SolidColorBrush(AnalyzerColors.BgChannelColors[buc % 2], 0.8f);
+
+ ChannelGrid.Children.Add(newChannelGrid);
+
+ //Create label
+ var newChannelLabel = new TextBlock();
+
+ newChannelLabel.SetValue(Grid.RowProperty, 0);
+
+ newChannelLabel.VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center;
+ newChannelLabel.HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center;
+
+ newChannelLabel.Text = $"Channel {channels[buc] + 1}";
+
+ newChannelLabel.Foreground = new SolidColorBrush(AnalyzerColors.FgChannelColors[buc]);
+
+ newChannelGrid.Children.Add(newChannelLabel);
+
+ //Create textbox
+ var newChannelTextbox = new TextBox();
+ newBoxes.Add(newChannelTextbox);
+
+ newChannelTextbox.SetValue(Grid.RowProperty, 1);
+
+ newChannelTextbox.VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center;
+ newChannelTextbox.HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Stretch;
+ newChannelTextbox.Margin = new Thickness(5, 0, 5, 0);
+
+ newChannelTextbox.Background = new SolidColorBrush(AnalyzerColors.BgChannelColors[1 - (buc % 2)], 0.8f);
+ newChannelTextbox.Foreground = new SolidColorBrush(AnalyzerColors.TxtColor, 1);
+
+ newChannelTextbox.MinHeight = newChannelTextbox.MaxHeight = newChannelTextbox.Height = 18;
+ newChannelTextbox.Padding = new Thickness(2);
+ newChannelTextbox.BorderThickness = new Thickness(0);
+ newChannelTextbox.FontSize = 10;
+ newChannelTextbox.TextAlignment = TextAlignment.Center;
+
+ newChannelGrid.Children.Add(newChannelTextbox);
+ }
+
+ boxes = newBoxes.ToArray();
+
+ ChannelGrid.EndBatchUpdate();
+
+ }
+
+ public ChannelViewer()
+ {
+ InitializeComponent();
+
+ Channels = new int[] { 1, 3, 5 };
+ }
+ }
+}
diff --git a/Software/LogicAnalyzer/LogicAnalyzerMultiplatform/LogicAnalyzerMultiplatform.csproj b/Software/LogicAnalyzer/LogicAnalyzerMultiplatform/LogicAnalyzerMultiplatform.csproj
new file mode 100644
index 0000000..d001be6
--- /dev/null
+++ b/Software/LogicAnalyzer/LogicAnalyzerMultiplatform/LogicAnalyzerMultiplatform.csproj
@@ -0,0 +1,30 @@
+
+
+ WinExe
+ net6.0
+ enable
+
+ copyused
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Software/LogicAnalyzer/LogicAnalyzerMultiplatform/MainWindow.axaml b/Software/LogicAnalyzer/LogicAnalyzerMultiplatform/MainWindow.axaml
new file mode 100644
index 0000000..0557f0a
--- /dev/null
+++ b/Software/LogicAnalyzer/LogicAnalyzerMultiplatform/MainWindow.axaml
@@ -0,0 +1,135 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Open device:
+ < None >
+
+
+
+
+
+
+
+
+
+
+ CONTENT
+
+
+
+
+ Adjustments
+
+
+ 10
+
+
+ Samples in screen
+
+
+ 200
+
+
+
+
+
+ Information
+
+
+
+ - Frequency:
+
+
+ 100000000
+
+
+
+
+ - Total samples:
+
+
+ 1536
+
+
+
+
+ - Pre samples:
+
+
+ 512
+
+
+
+
+ - Post samples:
+
+
+ 1024
+
+
+
+
+ - Channels:
+
+
+ 4
+
+
+
+
+ - Trigger:
+
+
+ Simple, Channel 1
+
+
+
+
+ - Value:
+
+
+ "10010"
+
+
+
+
+
+
+
diff --git a/Software/LogicAnalyzer/LogicAnalyzerMultiplatform/MainWindow.axaml.cs b/Software/LogicAnalyzer/LogicAnalyzerMultiplatform/MainWindow.axaml.cs
new file mode 100644
index 0000000..bdbb2aa
--- /dev/null
+++ b/Software/LogicAnalyzer/LogicAnalyzerMultiplatform/MainWindow.axaml.cs
@@ -0,0 +1,12 @@
+using Avalonia.Controls;
+
+namespace LogicAnalyzerMultiplatform
+{
+ public partial class MainWindow : Window
+ {
+ public MainWindow()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/Software/LogicAnalyzer/LogicAnalyzerMultiplatform/Program.cs b/Software/LogicAnalyzer/LogicAnalyzerMultiplatform/Program.cs
new file mode 100644
index 0000000..a21430a
--- /dev/null
+++ b/Software/LogicAnalyzer/LogicAnalyzerMultiplatform/Program.cs
@@ -0,0 +1,23 @@
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Controls.ApplicationLifetimes;
+using System;
+
+namespace LogicAnalyzerMultiplatform
+{
+ internal class Program
+ {
+ // Initialization code. Don't use any Avalonia, third-party APIs or any
+ // SynchronizationContext-reliant code before AppMain is called: things aren't initialized
+ // yet and stuff might break.
+ [STAThread]
+ public static void Main(string[] args) => BuildAvaloniaApp()
+ .StartWithClassicDesktopLifetime(args);
+
+ // Avalonia configuration, don't remove; also used by visual designer.
+ public static AppBuilder BuildAvaloniaApp()
+ => AppBuilder.Configure()
+ .UsePlatformDetect()
+ .LogToTrace();
+ }
+}
diff --git a/Software/LogicAnalyzer/LogicAnalyzer/Classes/CaptureSettings.cs b/Software/LogicAnalyzer/SharedDriver/CaptureSettings.cs
similarity index 93%
rename from Software/LogicAnalyzer/LogicAnalyzer/Classes/CaptureSettings.cs
rename to Software/LogicAnalyzer/SharedDriver/CaptureSettings.cs
index bf53830..86f71bb 100644
--- a/Software/LogicAnalyzer/LogicAnalyzer/Classes/CaptureSettings.cs
+++ b/Software/LogicAnalyzer/SharedDriver/CaptureSettings.cs
@@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
-namespace LogicAnalyzer
+namespace SharedDriver
{
public class CaptureSettings
{
diff --git a/Software/LogicAnalyzer/LogicAnalyzer/Classes/LogicAnalyzerDriver.cs b/Software/LogicAnalyzer/SharedDriver/LogicAnalyzerDriver.cs
similarity index 80%
rename from Software/LogicAnalyzer/LogicAnalyzer/Classes/LogicAnalyzerDriver.cs
rename to Software/LogicAnalyzer/SharedDriver/LogicAnalyzerDriver.cs
index 8c7670d..f3eecf2 100644
--- a/Software/LogicAnalyzer/LogicAnalyzer/Classes/LogicAnalyzerDriver.cs
+++ b/Software/LogicAnalyzer/SharedDriver/LogicAnalyzerDriver.cs
@@ -1,12 +1,8 @@
-using System;
-using System.Collections.Generic;
-using System.IO.Ports;
-using System.Linq;
+using System.IO.Ports;
using System.Runtime.InteropServices;
using System.Text;
-using System.Threading.Tasks;
-namespace LogicAnalyzer
+namespace SharedDriver
{
public class LogicAnalyzerDriver : IDisposable
{
@@ -16,12 +12,13 @@ namespace LogicAnalyzer
SerialPort sp;
public string? DeviceVersion { get; set; }
- public event EventHandler CaptureCompleted;
+ public event EventHandler? CaptureCompleted;
bool capturing = false;
private int channelCount;
private int triggerChannel;
private int preSamples;
+ private Action? currentCaptureHandler;
public LogicAnalyzerDriver(string SerialPort, int Bauds)
{
@@ -46,36 +43,19 @@ namespace LogicAnalyzer
baseStream.ReadTimeout = Timeout.Infinite;
}
- public bool StartCapture(int Frequency, int PreSamples, int PostSamples, int[] Channels, int TriggerChannel, bool TriggerInverted)
+ public bool StartCapture(int Frequency, int PreSamples, int PostSamples, int[] Channels, int TriggerChannel, bool TriggerInverted, Action? CaptureCompletedHandler = null)
{
if (capturing)
return false;
- if (Channels == null || Channels.Length == 0 || PreSamples < 2 || PreSamples > (16 * 1024) || (PreSamples + PostSamples) >= (32 * 1024) || Frequency > 100000000)
+ if (Channels == null || Channels.Length == 0 || PreSamples < 2 || PreSamples > (16 * 1024) || (PreSamples + PostSamples) >= (32 * 1024) || Frequency > 100000000)
return false;
- /*
- bool oneFound = false;
-
- for (int bitCount = 0; bitCount < 32; bitCount++)
- {
- if (((PreSamples * 4) & (1 << bitCount)) != 0)
- {
- if (oneFound)
- return false;
-
- oneFound = true;
- }
- }
-
- if (!oneFound)
- return false;
- */
-
channelCount = Channels.Length;
triggerChannel = Array.IndexOf(Channels, TriggerChannel);
preSamples = PreSamples;
+ currentCaptureHandler = CaptureCompletedHandler;
CaptureRequest request = new CaptureRequest
{
@@ -89,7 +69,7 @@ namespace LogicAnalyzer
postSamples = (uint)PostSamples
};
- for(int buc = 0; buc < Channels.Length; buc++)
+ for (int buc = 0; buc < Channels.Length; buc++)
request.channels[buc] = (byte)Channels[buc];
OutputPacket pack = new OutputPacket();
@@ -111,7 +91,7 @@ namespace LogicAnalyzer
}
return false;
}
- public bool StartPatternCapture(int Frequency, int PreSamples, int PostSamples, int[] Channels, int TriggerChannel, int TriggerBitCount, UInt16 TriggerPattern, bool Fast)
+ public bool StartPatternCapture(int Frequency, int PreSamples, int PostSamples, int[] Channels, int TriggerChannel, int TriggerBitCount, UInt16 TriggerPattern, bool Fast, Action? CaptureCompletedHandler = null)
{
if (capturing)
@@ -120,27 +100,10 @@ namespace LogicAnalyzer
if (Channels == null || Channels.Length == 0 || PreSamples < 2 || PreSamples > (16 * 1024) || (PreSamples + PostSamples) >= (32 * 1024) || Frequency > 100000000)
return false;
- /*
- bool oneFound = false;
-
- for (int bitCount = 0; bitCount < 32; bitCount++)
- {
- if (((PreSamples * 4) & (1 << bitCount)) != 0)
- {
- if (oneFound)
- return false;
-
- oneFound = true;
- }
- }
-
- if (!oneFound)
- return false;
- */
-
channelCount = Channels.Length;
triggerChannel = Array.IndexOf(Channels, TriggerChannel);
preSamples = PreSamples;
+ currentCaptureHandler = CaptureCompletedHandler;
CaptureRequest request = new CaptureRequest
{
@@ -177,7 +140,6 @@ namespace LogicAnalyzer
}
return false;
}
-
public void Dispose()
{
try
@@ -187,20 +149,20 @@ namespace LogicAnalyzer
}
catch { }
- try
+ try
{
baseStream.Close();
baseStream.Dispose();
}
catch { }
- try
+ try
{
readData.Close();
readData.Dispose();
}
catch { }
-
+
try
{
readResponse.Close();
@@ -216,22 +178,22 @@ namespace LogicAnalyzer
DeviceVersion = null;
CaptureCompleted = null;
}
-
void ReadCapture()
{
uint length = readData.ReadUInt32();
- uint[] samples = new uint[length];
+ uint[] samples = new uint[length];
- for(int buc = 0; buc < length; buc++)
+ for (int buc = 0; buc < length; buc++)
samples[buc] = readData.ReadUInt32();
- if (CaptureCompleted != null)
+ if (currentCaptureHandler != null)
+ currentCaptureHandler(new CaptureEventArgs { Samples = samples, ChannelCount = channelCount, TriggerChannel = triggerChannel, PreSamples = preSamples });
+ else if (CaptureCompleted != null)
CaptureCompleted(this, new CaptureEventArgs { Samples = samples, ChannelCount = channelCount, TriggerChannel = triggerChannel, PreSamples = preSamples });
capturing = false;
}
-
class OutputPacket
{
List dataBuffer = new List();
@@ -273,7 +235,7 @@ namespace LogicAnalyzer
finalData.Add(0x55);
finalData.Add(0xAA);
- for(int buc = 0; buc < dataBuffer.Count; buc++)
+ for (int buc = 0; buc < dataBuffer.Count; buc++)
{
if (dataBuffer[buc] == 0xAA || dataBuffer[buc] == 0x55 || dataBuffer[buc] == 0xF0)
{
@@ -283,13 +245,13 @@ namespace LogicAnalyzer
else
finalData.Add(dataBuffer[buc]);
}
-
+
finalData.Add(0xAA);
finalData.Add(0x55);
return finalData.ToArray();
-
+
}
}
@@ -317,4 +279,4 @@ namespace LogicAnalyzer
public int PreSamples { get; set; }
public uint[] Samples { get; set; }
}
-}
+}
\ No newline at end of file
diff --git a/Software/LogicAnalyzer/SharedDriver/SharedDriver.csproj b/Software/LogicAnalyzer/SharedDriver/SharedDriver.csproj
new file mode 100644
index 0000000..6a3b766
--- /dev/null
+++ b/Software/LogicAnalyzer/SharedDriver/SharedDriver.csproj
@@ -0,0 +1,13 @@
+
+
+
+ net6.0
+ enable
+ enable
+
+
+
+
+
+
+