Rev 155 | 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 MapEvents(FSXObject fsx) {}public override void FsxEvent(FSXObject fsx, 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;elsethis.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(FSXObject fsx) {}// @TODO: Make this work with COMM1/COMM2public override void SimButtons(FSXObject fsx) {if (this.simStatus != 0)return;this.updateInput();if (!timers[TIMER_COMMSWAP].Enabled && this.isSwapSet(0)) {if (this.assigned == 1)fsx.Comm1SwapFreq();elsefsx.Comm2SwapFreq();timers[TIMER_COMMSWAP].Enabled = true;}if (!timers[TIMER_NAVSWAP].Enabled && this.isSwapSet(1)) {if (this.assigned == 1)fsx.Nav1SwapFreq();elsefsx.Nav2SwapFreq();timers[TIMER_NAVSWAP].Enabled = true;}// Check if the MHz/KHz has been pressedif (!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 COMM1sbyte 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();elsefsx.Comm2DecFract();elseif (this.assigned == 1)fsx.Comm1DecWhole();elsefsx.Comm2DecWhole();} else {if (this.flipcomm == 1)if (this.assigned == 1)fsx.Comm1IncFract();elsefsx.Comm2IncFract();elseif (this.assigned == 1)fsx.Comm1IncWhole();elsefsx.Comm2IncWhole();}}// Process the rotary encoders NAV1delta = 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();elsefsx.Nav2DecFract();elseif (this.assigned == 1)fsx.Nav1DecWhole();elsefsx.Nav2DecWhole();} else {if (this.flipcomm == 1)if (this.assigned == 1)fsx.Nav1IncFract();elsefsx.Nav2IncFract();elseif (this.assigned == 1)fsx.Nav1IncWhole();elsefsx.Nav2IncWhole();}}}}}