/// <summary>
        /// Combine all Ready MobileDevices into a single input and get ready for vJoy
        /// </summary>
        public PocketStrafeInput CombineMobileDevices(List <PocketStrafeMobileDevice> devices)
        {
            double avgPOV   = 0;
            int    avgCount = 0;

            double[]          valsf    = new double[PocketStrafePacketIndex.Count];
            PocketStrafeInput combined = new PocketStrafeInput();

            // Add vals and buttons from Ready devices
            combined.buttons = 0;

            for (int i = 0; i < MobileDevices.Count; i++)
            {
                if (!MobileDevices[i].Ready)
                {
                    continue;
                }

                combined.speed  += MobileDevices[i].State.speed;
                combined.buttons = combined.buttons | MobileDevices[i].State.buttons; // bitmask

                // rolling average of POV, no need to know beforehand how many devices are Ready
                if (MobileDevices[i].State.validPOV)
                {
                    avgCount++;
                    avgPOV = avgPOV * (avgCount - 1) / avgCount + MobileDevices[i].State.POV / avgCount;
                }
            }
            combined.POV = avgPOV;
            return(combined);
        }
 /// <summary>
 /// Pass data from socket to virtual device, and determine if interpolation should occur.
 /// </summary>
 /// <param name="data">Array of bytes representing UTF8 encoded string.</param>
 public void PassDataToDevices(byte[] data)
 {
     // Called by a socket thread whenver it rcvs data
     lock (locker)
     {
         PocketStrafeInput input = PocketStrafeData.GetData(data);
         MobileDevices[input.deviceNumber].SetState(input);
     }
 }
 private PocketStrafeInput Smooth(PocketStrafeInput input)
 {
     input.speed = Algorithm.LowPassFilter(
         input.speed,             // new data
         _LastInput.speed,        // last data
         _RCFilterStrength,       // strength
         UpdateIntervalSeconds    // delta-t in seconds
         );
     input.POV = Algorithm.UnwrapAngle(input.POV, _LastInput.POV);
     input.POV = Algorithm.LowPassFilter(
         input.POV,
         _LastInput.POV,
         _RCFilterStrength,
         UpdateIntervalSeconds
         );
     input.POV  = Algorithm.WrapAngle(input.POV);
     _LastInput = input;
     return(input);
 }