Rev 4 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Timers;
using Microsoft.FlightSimulator.SimConnect;
using LibUsbDotNet;
using LibUsbDotNet.Main;
using LibUsbDotNet.DeviceNotify;
namespace NITNavComm {
public class NITNavCommDevice : NITDevice {
enum UsbCommands : byte {
CMD_LATCH_DISPLAY = 20,
CMD_SET_DISPLAY = 21,
};
private byte[,] display { get; set; }
private byte[] buttons {get; set; }
private sbyte[,] rotary;
private ushort[] points { get; set; }
public int flipcomm { get; set; }
public int flipnav { get; set; }
public uint simStatus { get; set; }
public int comStatus { get; set; }
public bool navAvailable { get; set; }
public bool avionicsMaster { get; set; }
private const int TIMER_COUNT = 4;
private const int TIMER_COMMSWAP = 0;
private const int TIMER_COMMFLIP = 1;
private const int TIMER_NAVSWAP = 2;
private const int TIMER_NAVFLIP = 3;
Timer[] timers = new Timer[TIMER_COUNT];
public NITNavCommDevice(NITDevice nitDevice) :
base(nitDevice.usbRegistry, "NITNavComm", nitDevice.vid, nitDevice.pid) {
this.init();
}
public NITNavCommDevice(UsbRegistry usbRegistry, string type, int vid, int pid) :
base(usbRegistry, "NITNavComm", 0x20a0, 0x4236) {
this.init();
}
private void init()
{
base.Open();
this.display = new byte[2, 10];
this.points = new ushort[2];
this.blankDisplay();
this.buttons = new byte[2];
this.buttons[0] = 0x00;
this.buttons[1] = 0x00;
this.rotary = new sbyte[2, 2];
this.resetAllRotary();
this.flipcomm = 0;
this.flipnav = 0;
this.simStatus = 0;
this.assigned = 1;
this.comStatus = 0;
this.navAvailable = true;
this.avionicsMaster = false;
for (int i = 0; i < TIMER_COUNT; i++) {
Timer timer = new Timer();
timer.Enabled = false;
timer.AutoReset = false;
timer.Interval = NITPanels.CFG_BUTTON_DEBOUNCE_TIME;
timer.Elapsed += OnDebounceTimer;
timers[i] = timer;
}
}
private static void OnDebounceTimer(Object source, ElapsedEventArgs e) {
Timer timer = (Timer)source;
timer.Enabled = false;
}
public override bool Close() {
this.blankDisplay();
return base.Close();
}
public void powerDown() {
this.resetAllRotary();
this.blankDisplay();
this.simStatus = 2;
}
public void powerUp() {
this.resetAllRotary();
this.simStatus = 0;
if (this.assigned == 1)
this.fsx.requestNavComm1Data();
else if (this.assigned == 2)
this.fsx.requestNavComm2Data();
}
public void blankDisplay() {
byte[] blank = { 0x0a, 0x0a, 0x0a, 0x0a, 0x0a };
for (byte i = 0; i < 4; i++)
setFreq(i, ref blank);
this.points[0] = 0x0000;
this.points[1] = 0x0000;
this.UpdateDisplay();
}
public byte[] getFreq(byte freq) {
byte[] ret = new byte[5];
switch (freq) {
case 0:
for (byte i = 0; i < 5; i++)
ret[i] = display[0, i];
break;
case 1:
for (byte i = 0; i < 5; i++)
ret[i] = display[0, i + 5];
break;
case 2:
for (byte i = 0; i < 5; i++)
ret[i] = display[1, i];
break;
case 3:
for (byte i = 0; i < 5; i++)
ret[i] = display[1, i + 5];
break;
}
return ret;
}
public void setFreq(byte freq, ref byte[] data) {
switch (freq) {
case 0:
for (byte i = 0; i < 5; i++)
display[0, i] = data[i];
break;
case 1:
for (byte i = 0; i < 5; i++)
display[0, i+5] = data[i];
break;
case 2:
for (byte i = 0; i < 5; i++)
display[1, i] = data[i];
break;
case 3:
for (byte i = 0; i < 5; i++)
display[1, i + 5] = data[i];
break;
}
}
public void setNavComFreqs(FSXObject.NavCom_Data data) {
byte[] freq0 = this.charArrayToBytes(data.Freq0.ToString().ToCharArray());
byte[] freq1 = this.charArrayToBytes(data.Freq1.ToString().ToCharArray());
byte[] freq2 = this.charArrayToBytes(data.Freq2.ToString().ToCharArray());
byte[] freq3 = this.charArrayToBytes(data.Freq3.ToString().ToCharArray());
this.setFreq(0, ref freq0);
this.setFreq(1, ref freq1);
this.setFreq(2, ref freq2);
this.setFreq(3, ref freq3);
this.UpdateDisplay();
}
private byte[] charArrayToBytes(char[] digits) {
byte[] bytes = new byte[5];
for (byte i = 0; i < 5; i++) {
bytes[i] = (byte)(digits[i] - '0');
}
return bytes;
}
public void setDisplay(byte dis, ref byte[] data) {
for (byte i = 0; i < data.Length; i++) {
display[dis, i] = data[i];
}
}
private void sendDigit(byte dis, byte dig, byte val, byte dp) {
ushort wxValue = (ushort)(dis <<8);
wxValue |= dig;
ushort wxIndex = (ushort)(dp << 8);
wxIndex |= val;
base.SendCommand(21, (short)wxValue, (short)wxIndex);
}
private void sendLatch(byte dis) {
if (!this.isOpen())
return;
base.SendCommand(20, (short)dis, 0);
}
public void updateInput() {
byte[] data = new byte[8];
int transferred;
base.SendCommand(30, 0, 0, data, out transferred);
this.buttons[0] = data[0];
this.rotary[0, 0] += (sbyte)data[1];
this.buttons[1] = data[2];
this.rotary[1, 0] += (sbyte)data[3];
}
public bool isSwapSet(byte dis) {
if ((this.buttons[dis] & 0x01)>0)
return true;
return false;
}
public bool isFlipSet(byte dis) {
if ((this.buttons[dis] & 0x02) > 0)
return true;
return false;
}
public sbyte getRotary(byte dis, byte rotary) {
return this.rotary[dis, rotary];
}
public void resetRotary(byte display, byte rotary) {
this.rotary[display, rotary] = 0x00;
}
public void resetAllRotary() {
this.rotary[0, 0] = 0x00;
this.rotary[0, 1] = 0x00;
this.rotary[1, 0] = 0x00;
this.rotary[1, 1] = 0x00;
}
private void sendData(byte dis) {
for (byte i = 0; i < 10; i++) {
//this.sendDigit(dis, i, display[dis, i], this.GetBit(this.points[dis], i));
this.sendDigit(dis, i, display[dis, i], 0);
}
}
public void UpdateDisplay() {
this.sendData(0);
this.sendData(1);
this.latchDisplay(0);
this.latchDisplay(1);
}
public void UpdateDisplay(byte dis) {
this.sendData(dis);
this.latchDisplay(dis);
}
private byte GetBit(ushort b, byte bitNumber) {
if ((b & (1 << bitNumber)) != 0)
return 1;
return 0;
}
private void latchDisplay(byte dis) {
this.sendLatch(dis);
}
public void swapFreq(byte display) {
if (display == 0) {
byte[] left = this.getFreq(0);
byte[] right = this.getFreq(1);
this.setFreq(0, ref right);
this.setFreq(1, ref left);
} else if (display == 1) {
byte[] left = this.getFreq(2);
byte[] right = this.getFreq(3);
this.setFreq(2, ref right);
this.setFreq(3, ref left);
}
}
public override void FsxInit() { }
public override void MapEvents() {
}
public override void FsxEvent(SIMCONNECT_RECV_SIMOBJECT_DATA data) {
if (data.dwRequestID == (uint)FSXObject.DATA_REQUESTS.AVIONICS) {
FSXObject.Avionics_Data avionics = (FSXObject.Avionics_Data)data.dwData[0];
this.avionicsMaster = avionics.avionics_master;
if (this.assigned == 1)
this.comStatus = (int)avionics.com1_status;
else
this.comStatus = (int)avionics.com2_status;
if (this.assigned == 1)
this.navAvailable = avionics.nav1_available;
else if (this.assigned == 2)
this.navAvailable = avionics.nav2_available;
if (!this.avionicsMaster || this.comStatus != 0) {
this.powerDown();
return;
}
if (this.avionicsMaster && this.comStatus == 0 && this.simStatus != 0) {
this.powerUp();
return;
}
}
if (this.simStatus != 0)
return;
if (this.assigned == 1 && data.dwRequestID == (uint)FSXObject.DATA_REQUESTS.NAVCOM1_REQ) {
FSXObject.NavCom_Data navcomdata = (FSXObject.NavCom_Data)data.dwData[0];
this.setNavComFreqs(navcomdata);
} else if (this.assigned == 2 && data.dwRequestID == (uint)FSXObject.DATA_REQUESTS.NAVCOM2_REQ) {
FSXObject.NavCom_Data navcomdata = (FSXObject.NavCom_Data)data.dwData[0];
this.setNavComFreqs(navcomdata);
}
}
public override void FsxReady() {
}
// @TODO: Make this work with COMM1/COMM2
public override void SimButtons() {
if (this.simStatus != 0)
return;
this.updateInput();
if (!timers[TIMER_COMMSWAP].Enabled && this.isSwapSet(0)) {
if (this.assigned == 1)
fsx.Comm1SwapFreq();
else
fsx.Comm2SwapFreq();
timers[TIMER_COMMSWAP].Enabled = true;
}
if (!timers[TIMER_NAVSWAP].Enabled && this.isSwapSet(1)) {
if (this.assigned == 1)
fsx.Nav1SwapFreq();
else
fsx.Nav2SwapFreq();
timers[TIMER_NAVSWAP].Enabled = true;
}
// Check if the MHz/KHz has been pressed
if (!timers[TIMER_COMMFLIP].Enabled && this.isFlipSet(0)) {
this.flipcomm = 1 - this.flipcomm;
timers[TIMER_COMMFLIP].Enabled = true;
}
if (!timers[TIMER_NAVFLIP].Enabled && this.isFlipSet(1)) {
this.flipnav = 1 - this.flipnav;
timers[TIMER_NAVFLIP].Enabled = true;
}
// Process the rotary encoders COMM1
sbyte delta = this.getRotary(0, 0);
this.resetRotary(0, 0);
if (delta != 0) {
if (delta < 0) {
delta = (sbyte)-delta;
if (this.flipcomm == 1)
if (this.assigned == 1)
fsx.Comm1DecFract();
else
fsx.Comm2DecFract();
else
if (this.assigned == 1)
fsx.Comm1DecWhole();
else
fsx.Comm2DecWhole();
} else {
if (this.flipcomm == 1)
if (this.assigned == 1)
fsx.Comm1IncFract();
else
fsx.Comm2IncFract();
else
if (this.assigned == 1)
fsx.Comm1IncWhole();
else
fsx.Comm2IncWhole();
}
}
// Process the rotary encoders NAV1
delta = this.getRotary(1, 0);
this.resetRotary(1, 0);
if (delta != 0) {
if (delta < 0) {
delta = (sbyte)-delta;
if (this.flipnav == 1)
if (this.assigned == 1)
fsx.Nav1DecFract();
else
fsx.Nav2DecFract();
else
if (this.assigned == 1)
fsx.Nav1DecWhole();
else
fsx.Nav2DecWhole();
} else {
if (this.flipcomm == 1)
if (this.assigned == 1)
fsx.Nav1IncFract();
else
fsx.Nav2IncFract();
else
if (this.assigned == 1)
fsx.Nav1IncWhole();
else
fsx.Nav2IncWhole();
}
}
}
}
}