Prepares RioJoy.Core for the net40 (Windows XP) target, which has no System.Memory, ValueTask, or System.Text.Json: - IRioTransport and the whole protocol/framing layer now use byte[] + Task (RioPacket.Payload, PacketParser/Builder, RioChecksum, replies, AnalogReport, RioHidReport). At 9600 baud Span bought nothing; the SerialPortTransport bridge copies disappear entirely. - ConfigStore/OverlayTemplateStore switch to Newtonsoft 13 with the same conventions (indented, PascalCase, string enums, null-skipping); verified against the real STJ-written config.json and regions.json (load + round-trip). System.Memory and System.Text.Json packages dropped. 275 tests green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
86 lines
2.6 KiB
C#
86 lines
2.6 KiB
C#
using RioJoy.Core.Calibration;
|
|
using RioJoy.Core.Hid;
|
|
using RioJoy.Core.Mapping;
|
|
using Xunit;
|
|
|
|
namespace RioJoy.Core.Tests.Hid;
|
|
|
|
public class RioHidReportTests
|
|
{
|
|
[Fact]
|
|
public void DefaultReport_CentersAxesAndHat()
|
|
{
|
|
var report = new RioHidReport();
|
|
byte[] b = report.ToArray();
|
|
|
|
Assert.Equal(RioHidReport.Size, b.Length);
|
|
// Each axis = 16383 = 0x3FFF, little-endian.
|
|
for (int offset = 0; offset < 12; offset += 2)
|
|
{
|
|
Assert.Equal(0xFF, b[offset]);
|
|
Assert.Equal(0x3F, b[offset + 1]);
|
|
}
|
|
|
|
Assert.Equal(0x0F, b[12] & 0x0F); // hat centered/null
|
|
}
|
|
|
|
[Fact]
|
|
public void SetAxis_WritesLittleEndian_AndClamps()
|
|
{
|
|
var report = new RioHidReport();
|
|
report.SetAxis(JoyAxis.Z, 0x1234);
|
|
Assert.Equal(0x34, report.ToArray()[4]);
|
|
Assert.Equal(0x12, report.ToArray()[5]);
|
|
|
|
report.SetAxis(JoyAxis.Z, 70000); // over max → clamped to 32767
|
|
Assert.Equal(0xFF, report.ToArray()[4]);
|
|
Assert.Equal(0x7F, report.ToArray()[5]);
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(RioHat.Up, 0x00)]
|
|
[InlineData(RioHat.Right, 0x01)]
|
|
[InlineData(RioHat.Down, 0x02)]
|
|
[InlineData(RioHat.Left, 0x03)]
|
|
[InlineData(RioHat.Centered, 0x0F)]
|
|
public void SetHat_EncodesNibble(RioHat hat, int expected)
|
|
{
|
|
var report = new RioHidReport();
|
|
report.SetHat(hat);
|
|
Assert.Equal(expected, report.ToArray()[12] & 0x0F);
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(1, 13, 0x01)] // button 1 → byte 13 bit 0
|
|
[InlineData(8, 13, 0x80)] // button 8 → byte 13 bit 7
|
|
[InlineData(9, 14, 0x01)] // button 9 → byte 14 bit 0
|
|
[InlineData(96, 24, 0x80)] // button 96 → byte 24 bit 7
|
|
public void SetButton_SetsCorrectBit(int button, int byteIndex, int mask)
|
|
{
|
|
var report = new RioHidReport();
|
|
report.SetButton(button, pressed: true);
|
|
Assert.Equal(mask, report.ToArray()[byteIndex]);
|
|
|
|
report.SetButton(button, pressed: false);
|
|
Assert.Equal(0, report.ToArray()[byteIndex]);
|
|
}
|
|
|
|
[Fact]
|
|
public void SetButton_RejectsOutOfRange()
|
|
{
|
|
var report = new RioHidReport();
|
|
Assert.Throws<ArgumentOutOfRangeException>(() => report.SetButton(0, true));
|
|
Assert.Throws<ArgumentOutOfRangeException>(() => report.SetButton(97, true));
|
|
}
|
|
|
|
[Fact]
|
|
public void Buttons_ComposeIndependently()
|
|
{
|
|
var report = new RioHidReport();
|
|
report.SetButton(1, true);
|
|
report.SetButton(2, true);
|
|
report.SetButton(1, false);
|
|
Assert.Equal(0x02, report.ToArray()[13]); // only button 2 remains
|
|
}
|
|
}
|