public static RailDriverBase GetInstance()
 {
     if (null == instance)
     {
         if (Environment.Is64BitProcess)
         {
             instance = new RailDriver64();
         }
         else
         {
             instance = new RailDriver32();
         }
     }
     return(instance);
 }
 /// <summary>
 /// Tries to find a RailDriver and initialize it
 /// </summary>
 /// <param name="basePath"></param>
 public UserInputRailDriver(string basePath)
 {
     try
     {
         Device = RailDriverBase.GetInstance();
         if (Device != null)
         {
             WriteBuffer = new byte[Device.WriteBufferSize];
             State       = new RailDriverState();
             SetLEDs(0x40, 0x40, 0x40);
             ReadCalibrationData(basePath);
             Device.OnDataRead += HandlePIEHidData;
         }
     }
     catch (Exception error)
     {
         Device = null;
         Trace.WriteLine(error);
     }
 }
        /// <summary>
        /// Data callback, called when RailDriver data is available
        /// </summary>
        /// <param name="data"></param>
        /// <param name="sourceDevice"></param>
        private void HandlePIEHidData(byte[] data, RailDriverBase sourceDevice)
        {
            if (sourceDevice != Device)
            {
                return;
            }
            State.SaveButtonData();
            byte[] rdata = null;
            while (0 == sourceDevice.ReadData(ref rdata)) //do this so don't ever miss any data
            {
#if false
                String output = "Callback: " + sourceDevice.Pid + ", ID: " + Device.ToString() + ", data=";
                for (int i = 0; i < sourceDevice.ReadLength; i++)
                {
                    output = output + rdata[i].ToString() + "  ";
                }
                Console.WriteLine(output);
#endif
                State.DirectionPercent = Percentage(rdata[1], FullReversed, Neutral, FullForward);

                State.ThrottlePercent = Percentage(rdata[2], ThrottleIdle, FullThrottle);

                State.DynamicBrakePercent = Percentage(rdata[2], ThrottleIdle, DynamicBrakeSetup, DynamicBrake);
                State.TrainBrakePercent   = Percentage(rdata[3], AutoBrakeRelease, FullAutoBrake);
                State.EngineBrakePercent  = Percentage(rdata[4], IndependentBrakeRelease, IndependentBrakeFull);
                float a      = .01f * State.EngineBrakePercent;
                float calOff = (1 - a) * BailOffDisengagedRelease + a * BailOffDisengagedFull;
                float calOn  = (1 - a) * BailOffEngagedRelease + a * BailOffEngagedFull;
                State.BailOff = Percentage(rdata[5], calOff, calOn) > 50;
                if (State.TrainBrakePercent >= 100)
                {
                    State.Emergency = Percentage(rdata[3], FullAutoBrake, EmergencyBrake) > 50;
                }

                State.Wipers = (int)(.01 * Percentage(rdata[6], Rotary1Position1, Rotary1Position2, Rotary1Position3) + 2.5);
                State.Lights = (int)(.01 * Percentage(rdata[7], Rotary2Position1, Rotary2Position2, Rotary2Position3) + 2.5);
                State.AddButtonData(rdata);
            }

            if (State.IsPressed(4, 0x30))
            {
                State.Emergency = true;
            }
            if (State.IsPressed(1, 0x40))
            {
                Active = !Active;
                EnableSpeaker(Active);
                if (Active)
                {
                    SetLEDs(0x80, 0x80, 0x80);
                    LEDSpeed          = -1;
                    UserInput.RDState = State;
                }
                else
                {
                    SetLEDs(0x40, 0x40, 0x40);
                    UserInput.RDState = null;
                }
            }
            State.Changed = true;
        }