118 lines
4.4 KiB
C#
118 lines
4.4 KiB
C#
|
|
using System.Text.Json;
|
||
|
|
using Pcie8586Probe.Acquisition;
|
||
|
|
using Pcie8586Probe.Models;
|
||
|
|
|
||
|
|
namespace Pcie8586Probe.Tests;
|
||
|
|
|
||
|
|
public sealed class AcquisitionTests
|
||
|
|
{
|
||
|
|
[Theory]
|
||
|
|
[InlineData(InputRange.PlusMinus5V, 0x8000, 0.0)]
|
||
|
|
[InlineData(InputRange.PlusMinus5V, 0x0000, -5.0)]
|
||
|
|
[InlineData(InputRange.PlusMinus1V, 0x8000, 0.0)]
|
||
|
|
[InlineData(InputRange.PlusMinus1V, 0x0000, -1.0)]
|
||
|
|
public void CodeToVolts_ConvertsExpectedValues(InputRange range, ushort code, double expected)
|
||
|
|
{
|
||
|
|
var actual = CodeConverter.CodeToVolts(code, range);
|
||
|
|
|
||
|
|
Assert.Equal(expected, actual, precision: 6);
|
||
|
|
}
|
||
|
|
|
||
|
|
[Fact]
|
||
|
|
public void CodeToVolts_MaxCode_IsJustBelowPositiveFullScale()
|
||
|
|
{
|
||
|
|
Assert.InRange(CodeConverter.CodeToVolts(0xFFFF, InputRange.PlusMinus5V), 4.9998, 5.0);
|
||
|
|
Assert.InRange(CodeConverter.CodeToVolts(0xFFFF, InputRange.PlusMinus1V), 0.9999, 1.0);
|
||
|
|
}
|
||
|
|
|
||
|
|
[Theory]
|
||
|
|
[InlineData(1)]
|
||
|
|
[InlineData(2)]
|
||
|
|
[InlineData(4)]
|
||
|
|
[InlineData(8)]
|
||
|
|
public void Deinterleave_SplitsInterleavedSamples(int channelCount)
|
||
|
|
{
|
||
|
|
var raw = new ushort[channelCount * 3];
|
||
|
|
for (var sample = 0; sample < 3; sample++)
|
||
|
|
{
|
||
|
|
for (var channel = 0; channel < channelCount; channel++)
|
||
|
|
{
|
||
|
|
raw[sample * channelCount + channel] = (ushort)(0x8000 + channel + sample * 10);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
var result = CodeConverter.Deinterleave(raw, channelCount, InputRange.PlusMinus5V);
|
||
|
|
|
||
|
|
Assert.Equal(channelCount, result.Length);
|
||
|
|
for (var channel = 0; channel < channelCount; channel++)
|
||
|
|
{
|
||
|
|
Assert.Equal(3, result[channel].Length);
|
||
|
|
Assert.Equal(CodeConverter.CodeToVolts((ushort)(0x8000 + channel), InputRange.PlusMinus5V), result[channel][0]);
|
||
|
|
Assert.Equal(CodeConverter.CodeToVolts((ushort)(0x8000 + channel + 20), InputRange.PlusMinus5V), result[channel][2]);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
[Fact]
|
||
|
|
public void Recorder_CapturesExactTargetLength_AndClipSlices()
|
||
|
|
{
|
||
|
|
var recorder = new Recorder();
|
||
|
|
recorder.Start(TimeSpan.FromMilliseconds(10), 1_000_000);
|
||
|
|
|
||
|
|
var first = MakeBlock(channelCount: 2, samplesPerChannel: 6_000, start: 0);
|
||
|
|
var second = MakeBlock(channelCount: 2, samplesPerChannel: 6_000, start: 6_000);
|
||
|
|
|
||
|
|
Assert.Null(recorder.Add(first));
|
||
|
|
var recorded = recorder.Add(second);
|
||
|
|
|
||
|
|
Assert.NotNull(recorded);
|
||
|
|
Assert.Equal(10_000, recorded.SamplesPerChannel);
|
||
|
|
|
||
|
|
var clip = SampleBlockAssembler.Slice(recorded, 2_000, 3_000);
|
||
|
|
Assert.Equal(3_000, clip.SamplesPerChannel);
|
||
|
|
Assert.Equal(recorded.Channels[0][2_000], clip.Channels[0][0]);
|
||
|
|
}
|
||
|
|
|
||
|
|
[Fact]
|
||
|
|
public async Task WaveformWriter_WritesInterleavedFloat32AndMetadata()
|
||
|
|
{
|
||
|
|
var block = new SampleBlock(
|
||
|
|
[
|
||
|
|
[1.0, 2.0],
|
||
|
|
[3.0, 4.0]
|
||
|
|
],
|
||
|
|
1_000_000,
|
||
|
|
0,
|
||
|
|
DateTimeOffset.Now);
|
||
|
|
var directory = Path.Combine(Path.GetTempPath(), "Pcie8586ProbeTests", Guid.NewGuid().ToString("N"));
|
||
|
|
|
||
|
|
var result = await WaveformWriter.WriteAsync(block, directory, "capture", InputRange.PlusMinus5V, CancellationToken.None);
|
||
|
|
|
||
|
|
var bytes = await File.ReadAllBytesAsync(result.BinaryPath);
|
||
|
|
Assert.Equal(16, bytes.Length);
|
||
|
|
Assert.Equal(1.0f, BitConverter.ToSingle(bytes, 0));
|
||
|
|
Assert.Equal(3.0f, BitConverter.ToSingle(bytes, 4));
|
||
|
|
Assert.Equal(2.0f, BitConverter.ToSingle(bytes, 8));
|
||
|
|
Assert.Equal(4.0f, BitConverter.ToSingle(bytes, 12));
|
||
|
|
|
||
|
|
using var metadata = JsonDocument.Parse(await File.ReadAllTextAsync(result.MetadataPath));
|
||
|
|
Assert.Equal(2, metadata.RootElement.GetProperty("channel_count").GetInt32());
|
||
|
|
Assert.Equal("interleaved", metadata.RootElement.GetProperty("layout").GetString());
|
||
|
|
Assert.Equal("float32", metadata.RootElement.GetProperty("dtype").GetString());
|
||
|
|
}
|
||
|
|
|
||
|
|
private static SampleBlock MakeBlock(int channelCount, int samplesPerChannel, long start)
|
||
|
|
{
|
||
|
|
var channels = new double[channelCount][];
|
||
|
|
for (var channel = 0; channel < channelCount; channel++)
|
||
|
|
{
|
||
|
|
channels[channel] = new double[samplesPerChannel];
|
||
|
|
for (var sample = 0; sample < samplesPerChannel; sample++)
|
||
|
|
{
|
||
|
|
channels[channel][sample] = channel + (start + sample) / 1_000_000.0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return new SampleBlock(channels, 1_000_000, start, DateTimeOffset.Now);
|
||
|
|
}
|
||
|
|
}
|