183 lines
5.2 KiB
C#
183 lines
5.2 KiB
C#
|
|
using System.Text.Json.Serialization;
|
||
|
|
|
||
|
|
namespace Substation;
|
||
|
|
|
||
|
|
public static class Freq
|
||
|
|
{
|
||
|
|
public static byte Compress(int ms)
|
||
|
|
{
|
||
|
|
if (ms is >= 10 and <= 100) return (byte)ms;
|
||
|
|
if (ms is > 100 and <= 600) return (byte)((ms - 100) / 5 + 100);
|
||
|
|
if (ms is > 600 and <= 1000) return (byte)((ms - 600) / 10 + 200);
|
||
|
|
return 10;
|
||
|
|
}
|
||
|
|
|
||
|
|
public static byte[] Compress4(int[] ms)
|
||
|
|
{
|
||
|
|
if (ms.Length != 4) throw new ArgumentException("freq must have exactly 4 values", nameof(ms));
|
||
|
|
return new byte[]
|
||
|
|
{
|
||
|
|
Compress(ms[0]), Compress(ms[1]), Compress(ms[2]), Compress(ms[3])
|
||
|
|
};
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
public static class Intensity
|
||
|
|
{
|
||
|
|
public static byte Clamp(int v) => (byte)Math.Clamp(v, 0, 100);
|
||
|
|
|
||
|
|
public static byte[] Clamp4(int[] v)
|
||
|
|
{
|
||
|
|
if (v.Length != 4) throw new ArgumentException("intensity must have exactly 4 values", nameof(v));
|
||
|
|
return new byte[] { Clamp(v[0]), Clamp(v[1]), Clamp(v[2]), Clamp(v[3]) };
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
public enum StrengthMode : byte
|
||
|
|
{
|
||
|
|
None = 0b00,
|
||
|
|
Add = 0b01,
|
||
|
|
Sub = 0b10,
|
||
|
|
Abs = 0b11
|
||
|
|
}
|
||
|
|
|
||
|
|
public enum LimitMode
|
||
|
|
{
|
||
|
|
Clamp = 0,
|
||
|
|
Scale = 1
|
||
|
|
}
|
||
|
|
|
||
|
|
public static class B0
|
||
|
|
{
|
||
|
|
public static byte PackModes(StrengthMode a, StrengthMode b) =>
|
||
|
|
(byte)(((int)a << 2) | (int)b);
|
||
|
|
|
||
|
|
public static byte[] Build(
|
||
|
|
byte seq,
|
||
|
|
StrengthMode modeA, StrengthMode modeB,
|
||
|
|
byte strengthA, byte strengthB,
|
||
|
|
byte[] freqA, byte[] intA,
|
||
|
|
byte[] freqB, byte[] intB)
|
||
|
|
{
|
||
|
|
if (freqA.Length != 4 || intA.Length != 4 || freqB.Length != 4 || intB.Length != 4)
|
||
|
|
throw new ArgumentException("wave arrays must be 4 bytes each");
|
||
|
|
|
||
|
|
var f = new byte[20];
|
||
|
|
f[0] = 0xB0;
|
||
|
|
f[1] = (byte)((seq << 4) | (PackModes(modeA, modeB) & 0x0F));
|
||
|
|
f[2] = strengthA;
|
||
|
|
f[3] = strengthB;
|
||
|
|
Buffer.BlockCopy(freqA, 0, f, 4, 4);
|
||
|
|
Buffer.BlockCopy(intA, 0, f, 8, 4);
|
||
|
|
Buffer.BlockCopy(freqB, 0, f, 12, 4);
|
||
|
|
Buffer.BlockCopy(intB, 0, f, 16, 4);
|
||
|
|
return f;
|
||
|
|
}
|
||
|
|
|
||
|
|
public static readonly byte[] ChannelOff =
|
||
|
|
{ 0, 0, 0, 0 };
|
||
|
|
|
||
|
|
public static readonly byte[] IntensityOff =
|
||
|
|
{ 0, 0, 0, 101 };
|
||
|
|
}
|
||
|
|
|
||
|
|
public static class BF
|
||
|
|
{
|
||
|
|
public static byte[] Build(
|
||
|
|
byte capA, byte capB,
|
||
|
|
byte freqBalA, byte freqBalB,
|
||
|
|
byte intBalA, byte intBalB)
|
||
|
|
{
|
||
|
|
return new byte[]
|
||
|
|
{
|
||
|
|
0xBF, capA, capB, freqBalA, freqBalB, intBalA, intBalB
|
||
|
|
};
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
public record WaveFrame(byte[] Freq, byte[] Intensity);
|
||
|
|
|
||
|
|
public class Command
|
||
|
|
{
|
||
|
|
[JsonPropertyName("op")] public string Op { get; set; } = "";
|
||
|
|
|
||
|
|
[JsonPropertyName("channel")]
|
||
|
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||
|
|
public string? Channel { get; set; }
|
||
|
|
|
||
|
|
[JsonPropertyName("mode")]
|
||
|
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||
|
|
public string? Mode { get; set; }
|
||
|
|
|
||
|
|
[JsonPropertyName("value")]
|
||
|
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||
|
|
public int? Value { get; set; }
|
||
|
|
|
||
|
|
[JsonPropertyName("freq")]
|
||
|
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||
|
|
public int[]? Freq { get; set; }
|
||
|
|
|
||
|
|
[JsonPropertyName("intensity")]
|
||
|
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||
|
|
public int[]? Intensity { get; set; }
|
||
|
|
|
||
|
|
[JsonPropertyName("frames")]
|
||
|
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||
|
|
public FrameDto[]? Frames { get; set; }
|
||
|
|
|
||
|
|
[JsonPropertyName("softcapA")]
|
||
|
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||
|
|
public int? SoftCapA { get; set; }
|
||
|
|
|
||
|
|
[JsonPropertyName("softcapB")]
|
||
|
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||
|
|
public int? SoftCapB { get; set; }
|
||
|
|
|
||
|
|
[JsonPropertyName("freqBalA")]
|
||
|
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||
|
|
public int? FreqBalA { get; set; }
|
||
|
|
|
||
|
|
[JsonPropertyName("freqBalB")]
|
||
|
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||
|
|
public int? FreqBalB { get; set; }
|
||
|
|
|
||
|
|
[JsonPropertyName("intBalA")]
|
||
|
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||
|
|
public int? IntBalA { get; set; }
|
||
|
|
|
||
|
|
[JsonPropertyName("intBalB")]
|
||
|
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||
|
|
public int? IntBalB { get; set; }
|
||
|
|
}
|
||
|
|
|
||
|
|
public class FrameDto
|
||
|
|
{
|
||
|
|
[JsonPropertyName("freq")] public int[]? Freq { get; set; }
|
||
|
|
[JsonPropertyName("intensity")] public int[]? Intensity { get; set; }
|
||
|
|
}
|
||
|
|
|
||
|
|
public class OkResponse
|
||
|
|
{
|
||
|
|
[JsonPropertyName("ok")] public bool Ok => true;
|
||
|
|
[JsonPropertyName("msg")]
|
||
|
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||
|
|
public string? Msg { get; set; }
|
||
|
|
}
|
||
|
|
|
||
|
|
public class ErrResponse
|
||
|
|
{
|
||
|
|
[JsonPropertyName("ok")] public bool Ok => false;
|
||
|
|
[JsonPropertyName("error")] public string Error { get; set; } = "";
|
||
|
|
}
|
||
|
|
|
||
|
|
public class StatusResponse
|
||
|
|
{
|
||
|
|
[JsonPropertyName("ok")] public bool Ok => true;
|
||
|
|
[JsonPropertyName("event")]
|
||
|
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||
|
|
public string? Event { get; set; }
|
||
|
|
[JsonPropertyName("connected")] public bool Connected { get; set; }
|
||
|
|
[JsonPropertyName("strengthA")] public int StrengthA { get; set; }
|
||
|
|
[JsonPropertyName("strengthB")] public int StrengthB { get; set; }
|
||
|
|
}
|