App sync code, handles button presses from mixer and syncs changes from VM. Included python code from the mixer. Some other PCB changes, but still needs improvements

This commit is contained in:
2024-05-16 23:42:27 -05:00
parent efdbb11f92
commit 700e87f807
39 changed files with 4246 additions and 3514 deletions

View File

@@ -1,7 +0,0 @@
namespace HidSliders.Hid
{
public class Class1
{
}
}

View File

@@ -0,0 +1,87 @@
using System.Reactive.Subjects;
using HidLibrary;
namespace HidSliders.Hid
{
public class HidInterface
{
private IHidDevice? _device;
private Subject<int[]> _sliderUpdate = new();
private Subject<List<MixerButton>> _buttonsUpdate = new();
public IObservable<int[]> SliderObservable => _sliderUpdate;
public IObservable<List<MixerButton>> ButtonsObservable => _buttonsUpdate;
public bool ConnectDevice(int vendorId, int devId)
{
var enumerator = new HidEnumerator();
IEnumerable<IHidDevice> hidDevices = enumerator.Enumerate(vendorId, [devId]);
_device = hidDevices.FirstOrDefault();
if (_device is { IsConnected: true })
{
_device.OpenDevice();
_device.MonitorDeviceEvents = true;
_device.ReadReport(OnReport);
_device.Removed += DeviceOnRemoved;
_device.Inserted += DeviceOnInserted;
}
return _device?.IsConnected ?? false;
}
private void DeviceOnInserted()
{
_sliderUpdate = new Subject<int[]>();
_buttonsUpdate = new Subject<List<MixerButton>>();
}
private void DeviceOnRemoved()
{
_sliderUpdate.OnCompleted();
_buttonsUpdate.OnCompleted();
}
private void ReadSliders(byte[] reportSliderBytes)
{
var reportChunk = new byte[4];
var sliderValues = new int[5];
for (int i = 0; i < 5; i++)
{
Array.Copy(reportSliderBytes, i * 2, reportChunk, 0, 2);
sliderValues[i] = BitConverter.ToInt32(reportChunk);
}
_sliderUpdate.OnNext(sliderValues);
}
private void ReadButtons(byte[] reportButtonBytes)
{
if (reportButtonBytes.Length != 8)
{
throw new ArgumentException("incoming report data was not padded to 8 bytes");
}
var buttonLong = BitConverter.ToInt64(reportButtonBytes);
_buttonsUpdate.OnNext(MixerButtonHelper.GetSetFlags(buttonLong));
}
private void ReadReport(byte[] reportBytes)
{
var buttons = new byte[8];
var sliders = new byte[10];
Array.Copy(reportBytes, 0, buttons, 0, 6);
Array.Copy(reportBytes, 6, sliders, 0, 10);
ReadSliders(sliders);
ReadButtons(buttons);
}
private void OnReport(HidReport report)
{
if (!_device!.IsConnected) return;
ReadReport(report.Data);
_device!.ReadReport(OnReport);
}
}
}

View File

@@ -7,7 +7,8 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="hidlibrary" Version="3.3.40" />
<PackageReference Include="hidlibrary" Version="3.2.49" />
<PackageReference Include="System.Reactive" Version="6.0.0" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,75 @@
namespace HidSliders.Hid;
[Flags]
public enum MixerButton : long
{
Button1 = 1L << 0, // 1
Button2 = 1L << 1, // 2
Button3 = 1L << 2, // 4
Button4 = 1L << 3, // 8
Button5 = 1L << 4, // 16
Button6 = 1L << 5, // 32
Button7 = 1L << 6, // 64
Button8 = 1L << 7, // 128
Button9 = 1L << 8, // 256
Button10 = 1L << 9, // 512
Button11 = 1L << 10, // 1024
Button12 = 1L << 11, // 2048
Button13 = 1L << 12, // 4096
Button14 = 1L << 13, // 8192
Button15 = 1L << 14, // 16384
Button16 = 1L << 15, // 32768
Button17 = 1L << 16, // 65536
Button18 = 1L << 17, // 131072
Button19 = 1L << 18, // 262144
Button20 = 1L << 19, // 524288
Button21 = 1L << 20, // 1048576
Button22 = 1L << 21, // 2097152
Button23 = 1L << 22, // 4194304
Button24 = 1L << 23, // 8388608
Button25 = 1L << 24, // 16777216
Button26 = 1L << 25, // 33554432
Button27 = 1L << 26, // 67108864
Button28 = 1L << 27, // 134217728
Button29 = 1L << 28, // 268435456
Button30 = 1L << 29, // 536870912
Button31 = 1L << 30, // 1073741824
Button32 = 1L << 31, // 2147483648
Button33 = 1L << 32, // 4294967296
Button34 = 1L << 33, // 8589934592
Button35 = 1L << 34, // 17179869184
Button36 = 1L << 35, // 34359738368
Button37 = 1L << 36, // 68719476736
Button38 = 1L << 37, // 137438953472
Button39 = 1L << 38, // 274877906944
Button40 = 1L << 39, // 549755813888
Button41 = 1L << 40, // 1099511627776
Button42 = 1L << 41, // 2199023255552
Button43 = 1L << 42, // 4398046511104
Button44 = 1L << 43, // 8796093022208
Button45 = 1L << 44 // 17592186044416
}
[Flags]
public enum ButtonGroups : long
{
Channel1 = 0b00001_00000000_00000000_00000000_00000000_11111111,
Channel2 = 0b00010_00000000_00000000_00000000_11111111_00000000,
Channel3 = 0b00100_00000000_00000000_11111111_00000000_00000000,
Channel4 = 0b01000_00000000_11111111_00000000_00000000_00000000,
Channel5 = 0b10000_11111111_00000000_00000000_00000000_00000000,
}
[Flags]
public enum ChannelButton
{
ChannelA1 = 1 << 0,
ChannelA2 = 1 << 1,
ChannelA3 = 1 << 2,
ChannelA4 = 1 << 3,
ChannelA5 = 1 << 4,
ChannelB1 = 1 << 5,
ChannelB2 = 1 << 6,
ChannelB3 = 1 << 7,
ChannelMute = 1 << 8,
}

View File

@@ -0,0 +1,75 @@
namespace HidSliders.Hid;
public class MixerButtonHelper
{
public static List<MixerButton> GetSetFlags(long value)
{
var setFlags = new List<MixerButton>();
foreach (MixerButton flag in Enum.GetValues(typeof(MixerButton)))
{
if ((value & (long)flag) == (long)flag)
{
setFlags.Add(flag);
}
}
return setFlags;
}
public static ButtonGroups GetButtonGroup(MixerButton button)
{
var buttonValue = (long)button;
if (((long)ButtonGroups.Channel1 & buttonValue) != 0) return ButtonGroups.Channel1;
if (((long)ButtonGroups.Channel2 & buttonValue) != 0) return ButtonGroups.Channel2;
if (((long)ButtonGroups.Channel3 & buttonValue) != 0) return ButtonGroups.Channel3;
if (((long)ButtonGroups.Channel4 & buttonValue) != 0) return ButtonGroups.Channel4;
if (((long)ButtonGroups.Channel5 & buttonValue) != 0) return ButtonGroups.Channel5;
throw new ArgumentException("The provided button does not match any button group.", nameof(button));
}
public static ChannelButton GetChannelButton(MixerButton button)
{
return GetChannelButton(button, GetButtonGroup(button));
}
public static ChannelButton GetChannelButton(MixerButton button, ButtonGroups buttonGroup)
{
var longButton = (long)button;
if (longButton >= 0x10000000000)
{
return ChannelButton.ChannelMute;
}
int intButton = 0;
switch (buttonGroup)
{
case ButtonGroups.Channel1:
intButton = (int)(longButton >> 0);
break;
case ButtonGroups.Channel2:
intButton = (int)(longButton >> 8);
break;
case ButtonGroups.Channel3:
intButton = (int)(longButton >> 16);
break;
case ButtonGroups.Channel4:
intButton = (int)(longButton >> 24);
break;
case ButtonGroups.Channel5:
intButton = (int)(longButton >> 32);
break;
}
if (((int)ChannelButton.ChannelA1 & intButton) != 0) return ChannelButton.ChannelA1;
if (((int)ChannelButton.ChannelA2 & intButton) != 0) return ChannelButton.ChannelA2;
if (((int)ChannelButton.ChannelA3 & intButton) != 0) return ChannelButton.ChannelA3;
if (((int)ChannelButton.ChannelA4 & intButton) != 0) return ChannelButton.ChannelA4;
if (((int)ChannelButton.ChannelA5 & intButton) != 0) return ChannelButton.ChannelA5;
if (((int)ChannelButton.ChannelB1 & intButton) != 0) return ChannelButton.ChannelB1;
if (((int)ChannelButton.ChannelB2 & intButton) != 0) return ChannelButton.ChannelB2;
if (((int)ChannelButton.ChannelB3 & intButton) != 0) return ChannelButton.ChannelB3;
throw new ArgumentException("The provided button does not match any channel button in the specified button group.", nameof(button));
}
}