logicanalyzer/Software/LogicAnalyzer/CLCapture/Program.cs

380 lines
12 KiB
C#
Raw Normal View History

2022-07-13 15:07:56 +00:00
using CLCapture;
using CommandLine;
using SharedDriver;
using System.IO.Ports;
using System.Linq;
2023-01-31 22:12:43 +00:00
using System.Runtime.CompilerServices;
2022-07-13 15:07:56 +00:00
using System.Text;
2023-01-31 22:12:43 +00:00
using System.Text.RegularExpressions;
Regex regAddressPort = new Regex("[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+\\:[0-9]+");
Regex regAddress = new Regex("[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+");
LogicAnalyzerDriver? driver = null;
2022-07-13 15:07:56 +00:00
TaskCompletionSource<CaptureEventArgs> captureCompletedTask;
Console.CancelKeyPress += Console_CancelKeyPress;
2023-01-31 22:12:43 +00:00
return await Parser.Default.ParseArguments<CLCaptureOptions, CLNetworkOptions>(args)
.MapResult(
async (CLCaptureOptions opts) => await Capture(opts),
async (CLNetworkOptions opts) => Configure(opts),
errs => Task.FromResult(-1)
);
2022-07-13 15:07:56 +00:00
2023-01-31 22:12:43 +00:00
async Task<int> Capture(CLCaptureOptions opts)
{
bool isNetworkAddress = regAddressPort.IsMatch(opts.AddressPort);
var ports = SerialPort.GetPortNames();
if (!isNetworkAddress && !ports.Any(p => p.ToLower() == opts.AddressPort.ToLower()))
{
Console.WriteLine("Cannot find specified serial port or address has an incorrect format.");
return -1;
}
if (opts.SamplingFrequency > 100000000 || opts.SamplingFrequency < 3100)
{
Console.WriteLine("Requested sampling frequency out of range (3100-100000000).");
return -1;
}
2023-06-28 11:32:35 +00:00
CLChannel[]? channels;
2023-01-31 22:12:43 +00:00
2023-06-28 11:32:35 +00:00
try
{
//int[]? channels = opts.Channels?.Split(",", StringSplitOptions.RemoveEmptyEntries).Select(c => int.Parse(c)).ToArray();
channels = opts.Channels?.Split(",", StringSplitOptions.RemoveEmptyEntries).Select(c => new CLChannel(c)).ToArray();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
return -1;
}
if (channels == null || channels.Any(c => c.ChannelNumber < 1 || c.ChannelNumber > 24))
2023-01-31 22:12:43 +00:00
{
Console.WriteLine("Specified capture channels out of range.");
return -1;
}
2023-06-28 11:32:35 +00:00
int maxChannel = channels.Max(c => c.ChannelNumber);
2023-02-04 14:49:15 +00:00
int channelMode = maxChannel <= 8 ? 0 : (maxChannel <= 16 ? 1 : 2);
int channelCount = maxChannel <= 8 ? 8 : (maxChannel <= 16 ? 16 : 24);
int minPreSamples = 2;
int maxPreSamples = channelMode == 0 ? 98303 : (channelMode == 1 ? 49151 : 24576);
int minPostSamples = 512;
int maxPostSamples = channelMode == 0 ? 131069 : (channelMode == 1 ? 65533 : 32765);
int maxTotalSamples = channelMode == 0 ? 131071 : (channelMode == 1 ? 65535 : 32767);
if (opts.PreSamples + opts.PostSamples > maxTotalSamples)
{
Console.WriteLine($"Total samples exceed the supported maximum ({maxTotalSamples} for the {channelCount} channel mode).");
return -1;
}
if (opts.PreSamples < minPreSamples)
{
Console.WriteLine($"Pre-samples cannot be less than {minPreSamples}.");
return -1;
}
if (opts.PreSamples > maxPreSamples)
{
Console.WriteLine($"Pre-samples cannot be more than {maxPreSamples} for the {channelCount} channel mode.");
return -1;
}
if (opts.PostSamples < minPostSamples)
2023-01-31 22:12:43 +00:00
{
2023-02-04 14:49:15 +00:00
Console.WriteLine($"Post-samples cannot be less than {minPostSamples}.");
return -1;
}
if (opts.PostSamples > maxPostSamples)
{
Console.WriteLine($"Post-samples cannot be more than {maxPostSamples} for the {channelCount} channel mode.");
2023-01-31 22:12:43 +00:00
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)
2022-07-13 15:07:56 +00:00
{
2023-01-31 22:12:43 +00:00
Console.WriteLine("Trigger channel out of range.");
2022-07-13 15:07:56 +00:00
return -1;
}
2023-01-31 22:12:43 +00:00
break;
2022-07-13 15:07:56 +00:00
2023-01-31 22:12:43 +00:00
case CLTriggerType.Fast:
2022-07-13 15:07:56 +00:00
2023-01-31 22:12:43 +00:00
if (opts.Trigger.Value.Length > 5)
2022-07-13 15:07:56 +00:00
{
2023-01-31 22:12:43 +00:00
Console.WriteLine("Fast trigger only supports up to 5 channels.");
2022-07-13 15:07:56 +00:00
return -1;
}
2023-01-31 22:12:43 +00:00
if (opts.Trigger.Value.Length + opts.Trigger.Channel > 17)
2022-07-13 15:07:56 +00:00
{
2023-01-31 22:12:43 +00:00
Console.WriteLine("Fast trigger can only be used with the first 16 channels.");
2022-07-13 15:07:56 +00:00
return -1;
}
2023-01-31 22:12:43 +00:00
break;
case CLTriggerType.Complex:
2022-07-13 15:07:56 +00:00
2023-01-31 22:12:43 +00:00
if (opts.Trigger.Value.Length > 16)
2022-07-13 15:07:56 +00:00
{
2023-01-31 22:12:43 +00:00
Console.WriteLine("Complex trigger only supports up to 16 channels.");
2022-07-13 15:07:56 +00:00
return -1;
}
2023-01-31 22:12:43 +00:00
if (opts.Trigger.Value.Length + opts.Trigger.Channel > 17)
2022-07-13 15:07:56 +00:00
{
2023-01-31 22:12:43 +00:00
Console.WriteLine("Complex trigger can only be used with the first 16 channels.");
2022-07-13 15:07:56 +00:00
return -1;
}
2023-01-31 22:12:43 +00:00
break;
}
2022-07-13 15:07:56 +00:00
2023-02-04 14:49:15 +00:00
Console.WriteLine($"Opening logic analyzer in {opts.AddressPort}...");
2022-07-13 15:07:56 +00:00
2023-01-31 22:12:43 +00:00
try
{
2023-02-25 11:25:37 +00:00
driver = new LogicAnalyzerDriver(opts.AddressPort);
2023-01-31 22:12:43 +00:00
}
catch
{
Console.WriteLine($"Error detecting Logic Analyzer in port/address {opts.AddressPort}");
return -1;
}
2022-07-13 15:07:56 +00:00
2023-01-31 22:12:43 +00:00
Console.WriteLine($"Conneced to device {driver.DeviceVersion} in port/address {opts.AddressPort}");
2022-07-13 15:07:56 +00:00
2023-01-31 22:12:43 +00:00
captureCompletedTask = new TaskCompletionSource<CaptureEventArgs>();
2022-07-13 15:07:56 +00:00
2023-06-28 11:32:35 +00:00
int[] nChannels = channels.Select(c => c.ChannelNumber - 1).ToArray();
2022-07-13 15:07:56 +00:00
2023-01-31 22:12:43 +00:00
if (opts.Trigger.TriggerType == CLTriggerType.Edge)
{
Console.WriteLine("Starting edge triggered capture...");
var resStart = driver.StartCapture(opts.SamplingFrequency, opts.PreSamples, opts.PostSamples,
2023-06-28 11:32:35 +00:00
nChannels, opts.Trigger.Channel - 1, opts.Trigger.Value == "0", CaptureFinished);
2022-07-13 15:07:56 +00:00
2023-01-31 22:12:43 +00:00
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;
case CaptureError.UnexpectedError:
Console.WriteLine("Unexpected error. Restart the device and try again.");
return -1;
2023-01-31 22:12:43 +00:00
}
}
2022-07-13 15:07:56 +00:00
2023-01-31 22:12:43 +00:00
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");
2022-07-13 15:07:56 +00:00
2023-01-31 22:12:43 +00:00
int bitCount = opts.Trigger.Value.Length;
ushort triggerPattern = 0;
2022-07-13 15:07:56 +00:00
2023-01-31 22:12:43 +00:00
for (int buc = 0; buc < opts.Trigger.Value.Length; buc++)
{
if (opts.Trigger.Value[buc] == '1')
triggerPattern |= (UInt16)(1 << buc);
}
2022-07-13 15:07:56 +00:00
2023-01-31 22:12:43 +00:00
var resStart = driver.StartPatternCapture(opts.SamplingFrequency, opts.PreSamples, opts.PostSamples,
2023-06-28 11:32:35 +00:00
nChannels, opts.Trigger.Channel - 1, bitCount, triggerPattern, opts.Trigger.TriggerType == CLTriggerType.Fast, CaptureFinished);
2022-07-13 15:07:56 +00:00
2023-01-31 22:12:43 +00:00
if (resStart != CaptureError.None)
{
switch (resStart)
2022-07-13 15:07:56 +00:00
{
2023-01-31 22:12:43 +00:00
case CaptureError.Busy:
Console.WriteLine("Device is busy, stop the capture before starting a new one.");
return -1;
case CaptureError.BadParams:
2023-02-04 14:49:15 +00:00
Console.WriteLine("Specified parameters are incorrect. Check the documentation in the repository to validate them.");
2023-01-31 22:12:43 +00:00
return -1;
case CaptureError.HardwareError:
Console.WriteLine("Device reported error starting capture. Restart the device and try again.");
return -1;
case CaptureError.UnexpectedError:
Console.WriteLine("Unexpected error. Restart the device and try again.");
return -1;
2022-07-13 15:07:56 +00:00
}
2023-01-31 22:12:43 +00:00
}
2022-07-13 15:07:56 +00:00
2023-01-31 22:12:43 +00:00
Console.WriteLine("Capture running...");
}
2022-07-13 15:07:56 +00:00
2023-01-31 22:12:43 +00:00
var result = await captureCompletedTask.Task;
2022-07-13 15:07:56 +00:00
if (result.Samples == null)
{
Console.WriteLine("Capture aborted.");
return -1;
}
2023-01-31 22:12:43 +00:00
Console.WriteLine("Capture complete, writting output file...");
2022-07-13 15:07:56 +00:00
2023-01-31 22:12:43 +00:00
var file = File.Create(opts.OutputFile);
StreamWriter sw = new StreamWriter(file);
2022-07-13 15:07:56 +00:00
2023-06-28 11:32:35 +00:00
sw.WriteLine(String.Join(',', channels.Select(c => c.ChannelName).ToArray()));
2022-07-13 15:07:56 +00:00
2023-01-31 22:12:43 +00:00
StringBuilder sb = new StringBuilder();
2022-07-13 15:07:56 +00:00
2023-01-31 22:12:43 +00:00
for (int sample = 0; sample < result.Samples.Length; sample++)
{
sb.Clear();
2022-07-13 15:07:56 +00:00
2023-06-28 11:32:35 +00:00
for (int buc = 0; buc < nChannels.Length; buc++)
2023-01-31 22:12:43 +00:00
{
2023-06-28 11:32:35 +00:00
if ((result.Samples[sample] & ((UInt128)1 << nChannels[buc])) == 0)
2023-01-31 22:12:43 +00:00
sb.Append("0,");
else
sb.Append("1,");
}
2023-06-28 11:32:35 +00:00
sb.Remove(sb.Length - 1, 1);
2023-01-31 22:12:43 +00:00
sw.WriteLine(sb.ToString());
}
2022-07-13 15:07:56 +00:00
2023-01-31 22:12:43 +00:00
sw.Close();
sw.Dispose();
file.Close();
file.Dispose();
2022-07-13 15:07:56 +00:00
2023-01-31 22:12:43 +00:00
Console.WriteLine("Done.");
2022-07-13 15:07:56 +00:00
2023-01-31 22:12:43 +00:00
return 1;
}
2022-07-13 15:07:56 +00:00
2023-01-31 22:12:43 +00:00
int Configure(CLNetworkOptions opts)
{
var ports = SerialPort.GetPortNames();
if (!ports.Any(p => p.ToLower() == opts.SerialPort))
{
Console.WriteLine("Cannot find specified serial port.");
return -1;
}
if (opts.AccessPoint.Length > 32)
{
Console.WriteLine("Invalid access point name.");
return -1;
}
if (opts.Password.Length > 63)
{
Console.WriteLine("Invalid password.");
return -1;
}
if (!regAddress.IsMatch(opts.Address))
{
Console.WriteLine("Invalid IP address.");
return -1;
}
if (opts.Port < 1)
{
Console.WriteLine("Invalid TCP port.");
return -1;
}
2023-01-31 22:12:43 +00:00
Console.WriteLine($"Opening logic analyzer in port {opts.SerialPort}...");
try
{
2023-02-25 11:25:37 +00:00
driver = new LogicAnalyzerDriver(opts.SerialPort);
2023-01-31 22:12:43 +00:00
}
catch
{
Console.WriteLine($"Error detecting Logic Analyzer in port {opts.SerialPort}");
return -1;
}
Console.WriteLine($"Conneced to device {driver.DeviceVersion} in port {opts.SerialPort}");
if (driver.DeviceVersion == null || !driver.DeviceVersion.Contains("WIFI"))
{
Console.WriteLine($"Device does not support WiFi. Aborting operation.");
driver.Dispose();
return -1;
}
bool result = driver.SendNetworkConfig(opts.AccessPoint, opts.Password, opts.Address, opts.Port);
if (!result)
{
Console.WriteLine("Error updating the network settings, restart the device and try again.");
driver.Dispose();
return -1;
}
driver.Dispose();
Console.WriteLine("Done.");
return 1;
}
2022-07-13 15:07:56 +00:00
void CaptureFinished(CaptureEventArgs e)
{
captureCompletedTask.SetResult(e);
}
void Console_CancelKeyPress(object? sender, ConsoleCancelEventArgs e)
{
if (driver != null)
{
try
{
driver.StopCapture();
driver.Dispose();
}
catch { }
driver = null;
}
}