Subversion Repositories group.NITPanels

Rev

Rev 19 | 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 NITAudioSelDevice : NITDevice {

        public VolumeControl volcontrol = new VolumeControl();

        public const byte USBCMD_READ_BUTTONS = 100;
        public const byte USBCMD_LEDS_SET = 101;
        public const byte USBCMD_GET_ANALOG = 102;
        public const byte USBCMD_SET_POWER_LED = 103;

        // The min analg value we'll ever read from the pot
        // If the analog val ever drops below this, a uint to int
        //  conversion will make the number >17k. If its not low enough
        //  the volume will never be able to be musted. Should probably 
        //  be calibrated or the protection resistor removed from the 
        //  analog pot ground line
        public const uint DEV_ANALOG_MIN = 4;

        private int simStatus { get; set; }
        public byte ledStatus { get; set; }
        public byte buttonStatus { get; set; }
        public byte analogValue { get; set; }
        public byte powerLedStatus { get; set; }

        public bool avionicsMaster { get; set; }

        private const int TIMER_COUNT = 8;
        Timer[] timers = new Timer[TIMER_COUNT];
        Timer inputTimer = new Timer();
        
        public NITAudioSelDevice(NITDevice nitDevice) :
            base(nitDevice.usbRegistry, "NITAudioSel", nitDevice.vid, nitDevice.pid) {
            this.init();
        }

        public NITAudioSelDevice(UsbRegistry usbRegistry, string type, int vid, int pid) :
            base(usbRegistry, "NITAudioSel", 0x4242, 0xe231) {
            this.init();
        }

        private void init() {
            base.Open();

            this.simStatus = 0;
            this.ledStatus = 0x00;
            this.buttonStatus = 0x00;

            this.analogValue = 0x00;
            this.powerLedStatus = 0;

            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;
            }

            inputTimer.Enabled = false;
            inputTimer.AutoReset = true;
            inputTimer.Interval = NITPanels.CFG_INPUT_TIMER_INTERVAL;
            inputTimer.Elapsed += inputTimer_Elapsed;

            // VolControl Stuff
            // Default the user setting to the first device it not already set
            if (Properties.Settings.Default.volcontroldevice == ""
                && volcontrol.deviceCount > 0) {
                Properties.Settings.Default.volcontroldevice = volcontrol.devices.ElementAt(0);
                Properties.Settings.Default.Save();
            }

            // Retrieve the user setting for the selected device, find its index
            if (volcontrol.deviceCount > 0) {
                string selectedDevice = Properties.Settings.Default.volcontroldevice;
                for (int i = 0; i < volcontrol.deviceCount; i++) {
                    if (selectedDevice == volcontrol.devices.ElementAt(i)) {
                        volcontrol.selectedDeviceIndex = (uint)i;
                        break;
                    }
                }
            }
        }

        void inputTimer_Elapsed(object sender, ElapsedEventArgs e) {
            this.SimButtons();
        }

        private static void OnDebounceTimer(Object source, ElapsedEventArgs e) {
            Timer timer = (Timer)source;
            timer.Enabled = false;
        }

        public override bool Close() {
            this.powerDown();
            return base.Close();
        }

        public void powerDown() {
            this.inputTimer.Enabled = false;
            this.ClearDisplay();
            this.simStatus = 2;
        }

        public void powerUp() {
            this.simStatus = 0;
            this.fsx.requestAudioSelData();
            this.inputTimer.Enabled = true;
        }

        public override void FsxReady() {
            this.powerUp();
        }

        public override void reAssign() {
            if (this.simStatus != 0  && this.fsx != null)
                return;

            this.fsx.requestAudioSelData();
        }

        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.avionicsMaster) {
                    this.powerDown();
                    return;
                }

                if (this.avionicsMaster && this.simStatus != 0) {
                    this.powerUp();
                    return;
                }
            }

            if (this.simStatus != 0)
                return;

            if (data.dwRequestID != (uint)FSXObject.DATA_REQUESTS.AUDIOSEL_REQ)
                return;

            FSXObject.AudioSel_Data audioseldata = (FSXObject.AudioSel_Data)data.dwData[0];
            this.setLed(0, audioseldata.com1);
            this.setLed(1, audioseldata.com2);
            this.setLed(2, audioseldata.comb);
            this.setLed(3, audioseldata.vor1);
            this.setLed(4, audioseldata.vor2);
            this.setLed(5, audioseldata.mkr);
            this.setLed(6, audioseldata.dme);
            this.setLed(7, audioseldata.adf);

            this.UpdateDisplay();
        }

        public override void SimButtons() {
            if (this.simStatus != 0)
                return;

            this.updateInput();

            for (int i = 0; i <= 7; i++) {
                if (timers[i].Enabled)                              // Wait for the debounce before processing again
                    continue;

                if (NITPanels.readBit(this.buttonStatus, i)) {      // Check an audio button is pressed
                    this.fsx.AudioSelButton(i);                          //  and if so, send of the audio select event
                    timers[i].Enabled = true;                       //  and start up a timer to debounce the button
                }
            }


            // VolControl Stuff
            float setVolume = NITPanels.map_f(this.analogValue, DEV_ANALOG_MIN, 255, 0.00F, 1.00F);
            float devVolume = this.volcontrol.getDeviceVolume();
            if (setVolume != devVolume)
                this.volcontrol.setDeviceVolume(setVolume);

        }

        public void updateInput() {
            byte[] data = new byte[8];
            int transferred;
            base.SendCommand(NITAudioSelDevice.USBCMD_READ_BUTTONS, 0, 0, data, out transferred);
            this.buttonStatus = data[1];

            base.SendCommand(NITAudioSelDevice.USBCMD_GET_ANALOG, 0, 0, data, out transferred);
            this.analogValue = data[0];
        }

        public void UpdateDisplay() {
            base.SendCommand(NITAudioSelDevice.USBCMD_LEDS_SET, this.ledStatus, 0);
            base.SendCommand(NITAudioSelDevice.USBCMD_SET_POWER_LED, this.powerLedStatus, 0);
        }

        public void ClearDisplay() {
            this.ledStatus = 0x00;
            this.powerLedStatus = 0x00;
            this.UpdateDisplay();
        }

        public void setLed(int ledNum, double status) {
            if (status == 1)
                this.ledStatus = NITPanels.setBit(this.ledStatus, ledNum);
            else
                this.ledStatus = NITPanels.clearBit(this.ledStatus, ledNum);
        }

        public void setLed(int ledNum, bool status) {
            if (status)
                this.ledStatus = NITPanels.setBit(this.ledStatus, ledNum);
            else
                this.ledStatus = NITPanels.clearBit(this.ledStatus, ledNum);
        }

        public bool isLedSet(int ledNum) {
            return NITPanels.readBit(this.ledStatus, ledNum);
        }

        public bool isLedPwrSet() {
            if (this.powerLedStatus>0)
                return true;
            return false;
        }

        public void setLedPwr(bool status) {
            if (status)
                this.powerLedStatus = 1;
            else
                this.powerLedStatus = 0;
        }

        public bool isButtonSet(int buttonNum) {
            return NITPanels.readBit(this.buttonStatus, buttonNum);
        }
    }
}