Example #1
0
        public void HandleFfbSetPacket(object packet)
        {
            IntPtr   _packet  = (IntPtr)packet;
            FFBPType type     = new FFBPType();
            uint     status   = 0;
            int      dataSize = 0;

            byte[] data   = new byte[256];
            uint   ioctrl = 0;

            status = _joystick.Ffb_h_Type(_packet, ref type);
            status = _joystick.Ffb_h_Packet(_packet, ref ioctrl, ref dataSize, ref data);

            byte[] ffbData = new byte[dataSize];
            Array.Copy(data, 0, ffbData, 0, dataSize);

            string reportName = FfbReportTypeMapper[type];

            Func <object, object> mapHandler = FfbReportMapper[reportName];


            Console.WriteLine(reportName);
            Console.WriteLine(string.Join(" ", ffbData.Select(b => b.ToString())));

            if (type > FFBPType.PT_NEWEFREP)
            {
                try
                {
                    object getObject  = _ffbEngine.Get[reportName]();
                    byte[] packetData = (byte[])mapHandler(getObject);
                    //TODO: send to the driver...
                }
                catch (Exception e)
                {
                    _logger.WriteLog(e.ToString());
                }
            }
            else
            {
                try
                {
                    object mappedReport = mapHandler(packet);
                    _ffbEngine.Set[reportName](mappedReport);
                }
                catch (Exception e)
                {
                    _logger.WriteLog(e.ToString());
                }
            }
        }
Example #2
0
 public UInt32 Ffb_h_Type(IntPtr Packet, ref FFBPType Type)
 {
     return(_Ffb_h_Type(Packet, ref Type));
 }
Example #3
0
 private static extern UInt32 _Ffb_h_Type(IntPtr Packet, ref FFBPType Type);
Example #4
0
        public void ProcessFFBPacket(IntPtr data, object userData, Action <FFBEventArgs> callback)
        {
            FFBEventArgs args       = new FFBEventArgs();
            FFBPType     packetType = new FFBPType();

            this.joystick.Ffb_h_Type(data, ref packetType);

            // extract FFB data from packet based on packet type
            switch (packetType)
            {
            case FFBPType.PT_EFFREP:     // Effect Report
                vJoy.FFB_EFF_REPORT effectReport = new vJoy.FFB_EFF_REPORT();
                if (this.joystick.Ffb_h_Eff_Report(data, ref effectReport) == ERROR_SUCCESS)
                {
                    // TODO
                }
                break;

            case FFBPType.PT_ENVREP:     // Envelope Report
                vJoy.FFB_EFF_ENVLP envelopeReport = new vJoy.FFB_EFF_ENVLP();
                if (this.joystick.Ffb_h_Eff_Envlp(data, ref envelopeReport) == ERROR_SUCCESS)
                {
                    // TODO
                }
                break;

            case FFBPType.PT_CONDREP:     // Conditional Report
                vJoy.FFB_EFF_COND conditionalReport = new vJoy.FFB_EFF_COND();
                if (this.joystick.Ffb_h_Eff_Cond(data, ref conditionalReport) == ERROR_SUCCESS)
                {
                    // TODO
                }
                break;

            case FFBPType.PT_PRIDREP:     // Periodic Report
                vJoy.FFB_EFF_PERIOD periodicReport = new vJoy.FFB_EFF_PERIOD();
                if (this.joystick.Ffb_h_Eff_Period(data, ref periodicReport) == ERROR_SUCCESS)
                {
                    // TODO
                }
                break;

            case FFBPType.PT_CONSTREP:     // Constant Force Report
                vJoy.FFB_EFF_CONSTANT constantForceReport = new vJoy.FFB_EFF_CONSTANT();
                if (this.joystick.Ffb_h_Eff_Constant(data, ref constantForceReport) == ERROR_SUCCESS)
                {
                    // TODO
                }
                break;

            case FFBPType.PT_RAMPREP:     // Ramp Force Report
                vJoy.FFB_EFF_RAMP rampForceReport = new vJoy.FFB_EFF_RAMP();
                if (this.joystick.Ffb_h_Eff_Ramp(data, ref rampForceReport) == ERROR_SUCCESS)
                {
                    // TODO
                }
                break;

            case FFBPType.PT_EFOPREP:     // Effect Operation Report
                vJoy.FFB_EFF_OP op = new vJoy.FFB_EFF_OP();
                if (this.joystick.Ffb_h_EffOp(data, ref op) == ERROR_SUCCESS)
                {
                    // TODO
                }
                break;

            case FFBPType.PT_CTRLREP:     // Device Control Report
                FFB_CTRL control = new FFB_CTRL();
                if (this.joystick.Ffb_h_DevCtrl(data, ref control) == ERROR_SUCCESS)
                {
                    // TODO
                }
                break;

            case FFBPType.PT_GAINREP:     // Device Gain Report
                byte gain = 0;
                if (this.joystick.Ffb_h_DevGain(data, ref gain) == ERROR_SUCCESS)
                {
                    // TODO
                }
                break;
            }

            callback(args);
        }
Example #5
0
 public UInt32 Ffb_h_Type(IntPtr Packet, ref FFBPType Type) { return _Ffb_h_Type(Packet, ref  Type); }
Example #6
0
 private static extern UInt32 _Ffb_h_Type(IntPtr Packet, ref FFBPType Type);
Example #7
0
        void FfbRecieved(IntPtr data, IntPtr userData)
        {
            int      devId = 0;
            FFBPType someT = new FFBPType();

            if (vjoy.Ffb_h_DeviceID(data, ref devId) == 0 &&
                vjoy.Ffb_h_Type(data, ref someT) == 0)
            {
                if (someT == FFBPType.PT_EFOPREP)
                {
                    vJoy.FFB_EFF_OP a = new vJoy.FFB_EFF_OP();
                    vjoy.Ffb_h_EffOp(data, ref a);
                    if (devId == 1)
                    {
                        if (a.EffectOp == FFBOP.EFF_STOP)
                        {
                            Interlocked.Exchange(ref gcn1Ffb, 0);
                        }
                        else
                        {
                            Interlocked.Exchange(ref gcn1Ffb, gcn1FfbDur * a.LoopCount);
                        }
                    }
                    else if (devId == 2)
                    {
                        if (a.EffectOp == FFBOP.EFF_STOP)
                        {
                            Interlocked.Exchange(ref gcn2Ffb, 0);
                        }
                        else
                        {
                            Interlocked.Exchange(ref gcn2Ffb, gcn2FfbDur * a.LoopCount);
                        }
                    }
                    else if (devId == 3)
                    {
                        if (a.EffectOp == FFBOP.EFF_STOP)
                        {
                            Interlocked.Exchange(ref gcn3Ffb, 0);
                        }
                        else
                        {
                            Interlocked.Exchange(ref gcn3Ffb, gcn3FfbDur * a.LoopCount);
                        }
                    }
                    else if (devId == 4)
                    {
                        if (a.EffectOp == FFBOP.EFF_STOP)
                        {
                            Interlocked.Exchange(ref gcn4Ffb, 0);
                        }
                        else
                        {
                            Interlocked.Exchange(ref gcn4Ffb, gcn4FfbDur * a.LoopCount);
                        }
                    }
                }
                else if (someT == FFBPType.PT_EFFREP)
                {
                    vJoy.FFB_EFF_REPORT b = new vJoy.FFB_EFF_REPORT();
                    vjoy.Ffb_h_Eff_Report(data, ref b);
                    if (devId == 1)
                    {
                        gcn1FfbDur = b.Duration;
                        if (b.Duration == 0xFFFF)
                        {
                            gcn1FfbInf = true;
                        }
                        else
                        {
                            gcn1FfbInf = false;
                        }
                    }
                    else if (devId == 2)
                    {
                        gcn2FfbDur = b.Duration;
                        if (b.Duration == 0xFFFF)
                        {
                            gcn2FfbInf = true;
                        }
                        else
                        {
                            gcn2FfbInf = false;
                        }
                    }
                    else if (devId == 3)
                    {
                        gcn3FfbDur = b.Duration;
                        if (b.Duration == 0xFFFF)
                        {
                            gcn3FfbInf = true;
                        }
                        else
                        {
                            gcn3FfbInf = false;
                        }
                    }
                    else if (devId == 4)
                    {
                        gcn4FfbDur = b.Duration;
                        if (b.Duration == 0xFFFF)
                        {
                            gcn4FfbInf = true;
                        }
                        else
                        {
                            gcn4FfbInf = false;
                        }
                    }
                }
                else if (someT == FFBPType.PT_CTRLREP)
                {
                    FFB_CTRL ctrl = new FFB_CTRL();
                    vjoy.Ffb_h_DevCtrl(data, ref ctrl);
                    if (ctrl == FFB_CTRL.CTRL_DEVRST || ctrl == FFB_CTRL.CTRL_STOPALL)
                    {
                        if (devId == 1)
                        {
                            Interlocked.Exchange(ref gcn1Ffb, 0);
                        }
                        else if (devId == 2)
                        {
                            Interlocked.Exchange(ref gcn2Ffb, 0);
                        }
                        else if (devId == 3)
                        {
                            Interlocked.Exchange(ref gcn3Ffb, 0);
                        }
                        else if (devId == 4)
                        {
                            Interlocked.Exchange(ref gcn4Ffb, 0);
                        }
                    }
                    //else
                    //    Log(null, new LogEventArgs("Unimplemented CTRL: " + ctrl));
                }
                else if (someT == FFBPType.PT_PRIDREP)
                {
                    vJoy.FFB_EFF_PERIOD a = new vJoy.FFB_EFF_PERIOD();
                    if (vjoy.Ffb_h_Eff_Period(data, ref a) != 0)
                    {
                        Log(null, new LogEventArgs("Ffb_h_Eff_Period error"));
                    }
                    else
                    {
                        if (devId == 1)
                        {
                            gcn1FfbActive = (a.Period > 0 && a.Magnitude > 0);
                        }
                        else if (devId == 2)
                        {
                            gcn2FfbActive = (a.Period > 0 && a.Magnitude > 0);
                        }
                        else if (devId == 3)
                        {
                            gcn3FfbActive = (a.Period > 0 && a.Magnitude > 0);
                        }
                        else if (devId == 4)
                        {
                            gcn4FfbActive = (a.Period > 0 && a.Magnitude > 0);
                        }
                    }
                    //Log(null, new LogEventArgs(" " + a.Magnitude + " " + a.Period + " " + a.Phase));
                }
                else if (someT == FFBPType.PT_GAINREP)
                {
                    byte gain = new byte();
                    if (vjoy.Ffb_h_DevGain(data, ref gain) != 0)
                    {
                        Log(null, new LogEventArgs("Ffb_h_DevGain error"));
                    }
                }
                else if (someT == FFBPType.PT_NEWEFREP)
                {
                    FFBEType a = new FFBEType();
                    if (vjoy.Ffb_h_EffNew(data, ref a) != 0)
                    {
                        Log(null, new LogEventArgs("Ffb_h_EffNew error"));
                    }
                }
                else if (someT == FFBPType.PT_BLKFRREP || someT == FFBPType.PT_BLKLDREP)
                {
                    int index = 0;
                    if (vjoy.Ffb_h_EBI(data, ref index) != 0)
                    {
                        Log(null, new LogEventArgs("Ffb_h_EBI error"));
                    }
                }
                else if (someT == FFBPType.PT_CONSTREP)
                {
                    vJoy.FFB_EFF_CONSTANT a = new vJoy.FFB_EFF_CONSTANT();
                    if (vjoy.Ffb_h_Eff_Constant(data, ref a) != 0)
                    {
                        Log(null, new LogEventArgs("Ffb_h_Eff_Constant error"));
                    }
                    else
                    {
                        if (devId == 1)
                        {
                            gcn1FfbActive = (a.Magnitude != 0);
                        }
                        else if (devId == 2)
                        {
                            gcn2FfbActive = (a.Magnitude != 0);
                        }
                        else if (devId == 3)
                        {
                            gcn3FfbActive = (a.Magnitude != 0);
                        }
                        else if (devId == 4)
                        {
                            gcn4FfbActive = (a.Magnitude != 0);
                        }
                    }
                }
                else if (someT == FFBPType.PT_RAMPREP)
                {
                    vJoy.FFB_EFF_RAMP a = new vJoy.FFB_EFF_RAMP();
                    if (vjoy.Ffb_h_Eff_Ramp(data, ref a) != 0)
                    {
                        Log(null, new LogEventArgs("Ffb_h_Eff_Ramp error"));
                    }
                    else
                    {
                        if (devId == 1)
                        {
                            gcn1FfbActive = (a.Start != 0 || a.End != 0);
                        }
                        else if (devId == 2)
                        {
                            gcn2FfbActive = (a.Start != 0 || a.End != 0);
                        }
                        else if (devId == 3)
                        {
                            gcn3FfbActive = (a.Start != 0 || a.End != 0);
                        }
                        else if (devId == 4)
                        {
                            gcn4FfbActive = (a.Start != 0 || a.End != 0);
                        }
                    }
                }
                //else
                //    Log(null, new LogEventArgs("Unimplemented force feedback command: " + someT));
            }
        }
Example #8
0
        // Convert Packet type to String
        public static bool PacketType2Str(FFBPType Type, out string Str)
        {
            bool stat = true;

            Str = "";

            switch (Type)
            {
            case FFBPType.PT_EFFREP:
                Str = "Effect Report";
                break;

            case FFBPType.PT_ENVREP:
                Str = "Envelope Report";
                break;

            case FFBPType.PT_CONDREP:
                Str = "Condition Report";
                break;

            case FFBPType.PT_PRIDREP:
                Str = "Periodic Report";
                break;

            case FFBPType.PT_CONSTREP:
                Str = "Constant Force Report";
                break;

            case FFBPType.PT_RAMPREP:
                Str = "Ramp Force Report";
                break;

            case FFBPType.PT_CSTMREP:
                Str = "Custom Force Data Report";
                break;

            case FFBPType.PT_SMPLREP:
                Str = "Download Force Sample";
                break;

            case FFBPType.PT_EFOPREP:
                Str = "Effect Operation Report";
                break;

            case FFBPType.PT_BLKFRREP:
                Str = "PID Block Free Report";
                break;

            case FFBPType.PT_CTRLREP:
                Str = "PID Device Control";
                break;

            case FFBPType.PT_GAINREP:
                Str = "Device Gain Report";
                break;

            case FFBPType.PT_SETCREP:
                Str = "Set Custom Force Report";
                break;

            case FFBPType.PT_NEWEFREP:
                Str = "Create New Effect Report";
                break;

            case FFBPType.PT_BLKLDREP:
                Str = "Block Load Report";
                break;

            case FFBPType.PT_POOLREP:
                Str = "PID Pool Report";
                break;

            default:
                stat = false;
                break;
            }

            return(stat);
        }
Example #9
0
        /// <summary>
        /// Called when vJoy has a new FFB packet.
        /// WARNING This is called from a thread pool managed by windows.
        /// The thread itself is created and managed by vJoyInterface.dll.
        /// Do not overload it, else you will me missing FFB packets from
        /// third party application.
        /// </summary>
        /// <param name="ffbDataPtr"></param>
        /// <param name="userData"></param>
        public void FfbReceiverFunction(IntPtr data, object userdata)
        {
            // Packet Header
            //copy ffb packet to managed structure
            InternalFfbPacket packet = (InternalFfbPacket)Marshal.PtrToStructure(data, typeof(InternalFfbPacket));

            /////// Packet Device ID, and Type Block Index (if exists)
            #region Packet Device ID, and Type Block Index
#if DUMP_FFB_FRAME
            if (vJoyManager.Config.Application.VerbosevJoyFFBReceiverDumpFrames)
            {
                DumpFrame(data);
            }
#endif

            uint     DeviceID = 0, BlockIndex = 0;
            FFBPType Type = new FFBPType();

            if ((uint)ERROR.ERROR_SUCCESS == Joystick.Ffb_h_DeviceID(data, ref DeviceID))
            {
                if (BFFManager.Config.Application.VerbosevJoyFFBReceiverDumpFrames)
                {
                    LogFormat(LogLevels.DEBUG, " > Device ID: {0}", DeviceID);
                }
            }

            // Effect block index only used when simultaneous effects should be done by
            // underlying hardware, which is not the case for a single motor driving wheel
            if ((uint)ERROR.ERROR_SUCCESS == Joystick.Ffb_h_EffectBlockIndex(data, ref BlockIndex))
            {
                if (BFFManager.Config.Application.VerbosevJoyFFBReceiverDumpFrames)
                {
                    LogFormat(LogLevels.DEBUG, " > Effect Block Index: {0}", BlockIndex);
                }
            }

            if ((uint)ERROR.ERROR_SUCCESS == Joystick.Ffb_h_Type(data, ref Type))
            {
                if (BFFManager.Config.Application.VerbosevJoyFFBReceiverDumpFrames)
                {
                    if (!PacketType2Str(Type, out var TypeStr))
                    {
                        LogFormat(LogLevels.DEBUG, " > Packet Type: {0}", Type);
                    }
                    else
                    {
                        LogFormat(LogLevels.DEBUG, " > Packet Type: {0}", TypeStr);
                    }
                }
                switch (Type)
                {
                case FFBPType.PT_POOLREP:
                    if (BFFManager.Config.Application.VerbosevJoyFFBReceiverDumpFrames)
                    {
                        LogFormat(LogLevels.DEBUG, " > Pool report handled by driver side");
                    }
                    break;

                case FFBPType.PT_BLKLDREP:
                    if (BFFManager.Config.Application.VerbosevJoyFFBReceiverDumpFrames)
                    {
                        LogFormat(LogLevels.DEBUG, " > Block Load report handled by driver side");
                    }
                    break;

                case FFBPType.PT_BLKFRREP:
                    FFBManager.FreeEffect(BlockIndex);
                    // Update PID
                    Joystick.FfbReadPID(DeviceID, ref PIDBlock);
                    if (BFFManager.Config.Application.VerbosevJoyFFBReceiverDumpFrames)
                    {
                        LogFormat(LogLevels.DEBUG, " > Block Free effect id {0}", PIDBlock.NextFreeEID);
                    }
                    break;
                }
            }



            #endregion

            #region PID Device Control
            FFB_CTRL Control = new FFB_CTRL();
            if ((uint)ERROR.ERROR_SUCCESS == Joystick.Ffb_h_DevCtrl(data, ref Control) && DevCtrl2Str(Control, out var CtrlStr))
            {
                if (BFFManager.Config.Application.VerbosevJoyFFBReceiverDumpFrames)
                {
                    LogFormat(LogLevels.DEBUG, " >> PID Device Control: {0}", CtrlStr);
                }
                switch (Control)
                {
                case FFB_CTRL.CTRL_DEVRST:
                    // Update PID data to get the resetted values from driver side
                    Joystick.FfbReadPID(DeviceID, ref PIDBlock);
                    // device reset
                    FFBManager.DevReset();
                    break;

                case FFB_CTRL.CTRL_ENACT:
                    FFBManager.DevEnable();
                    break;

                case FFB_CTRL.CTRL_DISACT:
                    FFBManager.DevDisable();
                    break;

                case FFB_CTRL.CTRL_STOPALL:
                    FFBManager.StopAllEffects();
                    break;
                }
            }

            #endregion

            #region Create new effect
            FFBEType EffectType    = new FFBEType();
            uint     NewBlockIndex = 0;
            if ((uint)ERROR.ERROR_SUCCESS == Joystick.Ffb_h_CreateNewEffect(data, ref EffectType, ref NewBlockIndex))
            {
                FFBManager.CreateNewEffect(NewBlockIndex);
                // Update PID
                Joystick.FfbReadPID(Id, ref PIDBlock);

                if (BFFManager.Config.Application.VerbosevJoyFFBReceiverDumpFrames)
                {
                    if (EffectType2Str(EffectType, out var TypeStr))
                    {
                        LogFormat(LogLevels.DEBUG, " >> Effect Type: {0}", TypeStr);
                    }
                    else
                    {
                        LogFormat(LogLevels.DEBUG, " >> Effect Type: Unknown({0})", EffectType);
                    }
                    LogFormat(LogLevels.DEBUG, " >> New Effect ID: {0}", NewBlockIndex);
                    if (NewBlockIndex != PIDBlock.PIDBlockLoad.EffectBlockIndex)
                    {
                        LogFormat(LogLevels.DEBUG, "!!! BUG NewBlockIndex=" + NewBlockIndex + " <> pid=" + ((int)PIDBlock.PIDBlockLoad.EffectBlockIndex));
                    }
                    LogFormat(LogLevels.DEBUG, " >> LoadStatus {0}", PIDBlock.PIDBlockLoad.LoadStatus);
                }
            }
            #endregion

            #region Condition
            vJoy.FFB_EFF_COND Condition = new vJoy.FFB_EFF_COND();
            if ((uint)ERROR.ERROR_SUCCESS == Joystick.Ffb_h_Eff_Cond(data, ref Condition))
            {
                if (BFFManager.Config.Application.VerbosevJoyFFBReceiverDumpFrames)
                {
                    if (Condition.isY)
                    {
                        LogFormat(LogLevels.DEBUG, " >> Y Axis");
                    }
                    else
                    {
                        LogFormat(LogLevels.DEBUG, " >> X Axis");
                    }
                    LogFormat(LogLevels.DEBUG, " >> Center Point Offset: {0}", TwosCompWord2Int(Condition.CenterPointOffset));
                    LogFormat(LogLevels.DEBUG, " >> Positive Coefficient: {0}", TwosCompWord2Int(Condition.PosCoeff));
                    LogFormat(LogLevels.DEBUG, " >> Negative Coefficient: {0}", TwosCompWord2Int(Condition.NegCoeff));
                    LogFormat(LogLevels.DEBUG, " >> Positive Saturation: {0}", Condition.PosSatur);
                    LogFormat(LogLevels.DEBUG, " >> Negative Saturation: {0}", Condition.NegSatur);
                    LogFormat(LogLevels.DEBUG, " >> Dead Band: {0}", Condition.DeadBand);
                }
                // Skip all processing if Y axis (single axis for wheel FFB!)
                if (Condition.isY)
                {
                    // Leave early!
                    return;
                }

                FFBManager.SetLimitsParams(BlockIndex,
                                           TwosCompWord2Int(Condition.CenterPointOffset) * Scale_FFB_to_u,
                                           Condition.DeadBand * Scale_FFB_to_u,
                                           TwosCompWord2Int(Condition.PosCoeff) * Scale_FFB_to_u,
                                           TwosCompWord2Int(Condition.NegCoeff) * Scale_FFB_to_u,
                                           Condition.PosSatur * Scale_FFB_to_u,
                                           -Condition.NegSatur * Scale_FFB_to_u);
            }
            #endregion

            #region Effect Report
            vJoy.FFB_EFF_REPORT Effect = new vJoy.FFB_EFF_REPORT();
            if ((uint)ERROR.ERROR_SUCCESS == Joystick.Ffb_h_Eff_Report(data, ref Effect))
            {
                if (BFFManager.Config.Application.VerbosevJoyFFBReceiverDumpFrames)
                {
                    if (!EffectType2Str(Effect.EffectType, out var TypeStr))
                    {
                        LogFormat(LogLevels.DEBUG, " >> Effect Report: {0} {1}", (int)Effect.EffectType, Effect.EffectType.ToString());
                    }
                    else
                    {
                        LogFormat(LogLevels.DEBUG, " >> Effect Report: {0}", TypeStr);
                    }
                    LogFormat(LogLevels.DEBUG, " >> AxisEnabledDirection: {0}", (ushort)Effect.AxesEnabledDirection);
                }
                if (Effect.Polar)
                {
                    if (BFFManager.Config.Application.VerbosevJoyFFBReceiverDumpFrames)
                    {
                        LogFormat(LogLevels.DEBUG, " >> Direction: {0} deg ({1})", Polar2Deg(Effect.Direction), Effect.Direction);
                    }
                    FFBManager.SetDirection(BlockIndex, Polar2Deg(Effect.Direction));
                }
                else
                {
                    if (BFFManager.Config.Application.VerbosevJoyFFBReceiverDumpFrames)
                    {
                        LogFormat(LogLevels.DEBUG, " >> X Direction: {0}", Effect.DirX);
                        LogFormat(LogLevels.DEBUG, " >> Y Direction: {0}", Effect.DirY);
                    }
                    FFBManager.SetDirection(BlockIndex, Effect.DirX);
                }

                if (BFFManager.Config.Application.VerbosevJoyFFBReceiverDumpFrames)
                {
                    if (Effect.Duration == 0xFFFF)
                    {
                        LogFormat(LogLevels.DEBUG, " >> Duration: Infinit");
                    }
                    else
                    {
                        LogFormat(LogLevels.DEBUG, " >> Duration: {0} MilliSec", (int)(Effect.Duration));
                    }

                    if (Effect.TrigerRpt == 0xFFFF)
                    {
                        LogFormat(LogLevels.DEBUG, " >> Trigger Repeat: Infinit");
                    }
                    else
                    {
                        LogFormat(LogLevels.DEBUG, " >> Trigger Repeat: {0}", (int)(Effect.TrigerRpt));
                    }

                    if (Effect.SamplePrd == 0xFFFF)
                    {
                        LogFormat(LogLevels.DEBUG, " >> Sample Period: Infinit");
                    }
                    else
                    {
                        LogFormat(LogLevels.DEBUG, " >> Sample Period: {0}", (int)(Effect.SamplePrd));
                    }

                    if (Effect.StartDelay == 0xFFFF)
                    {
                        LogFormat(LogLevels.DEBUG, " >> Start Delay: max ");
                    }
                    else
                    {
                        LogFormat(LogLevels.DEBUG, " >> Start Delay: {0}", (int)(Effect.StartDelay));
                    }


                    LogFormat(LogLevels.DEBUG, " >> Gain: {0}%%", Byte2Percent(Effect.Gain));
                }

                if (Effect.Duration == 65535)
                {
                    FFBManager.SetDuration(BlockIndex, -1.0);
                }
                else
                {
                    FFBManager.SetDuration(BlockIndex, Effect.Duration);
                }
                if (Effect.StartDelay == 65535)
                {
                    FFBManager.SetStartDelay(BlockIndex, 0);
                }
                else
                {
                    FFBManager.SetStartDelay(BlockIndex, Effect.StartDelay);
                }

                FFBManager.SetEffectGain(BlockIndex, Byte2Percent(Effect.Gain) * 0.01);
                switch (Effect.EffectType)
                {
                case FFBEType.ET_CONST:
                    FFBManager.SetEffect(BlockIndex, FFBManager.EffectTypes.CONSTANT_TORQUE);
                    break;

                case FFBEType.ET_RAMP:
                    FFBManager.SetEffect(BlockIndex, FFBManager.EffectTypes.RAMP);
                    break;

                case FFBEType.ET_INRT:
                    FFBManager.SetEffect(BlockIndex, FFBManager.EffectTypes.INERTIA);
                    break;

                case FFBEType.ET_SPRNG:
                    FFBManager.SetEffect(BlockIndex, FFBManager.EffectTypes.SPRING);
                    break;

                case FFBEType.ET_DMPR:
                    FFBManager.SetEffect(BlockIndex, FFBManager.EffectTypes.DAMPER);
                    break;

                case FFBEType.ET_FRCTN:
                    FFBManager.SetEffect(BlockIndex, FFBManager.EffectTypes.FRICTION);
                    break;

                // Periodic
                case FFBEType.ET_SQR:
                    FFBManager.SetEffect(BlockIndex, FFBManager.EffectTypes.SQUARE);
                    break;

                case FFBEType.ET_SINE:
                    FFBManager.SetEffect(BlockIndex, FFBManager.EffectTypes.SINE);
                    break;

                case FFBEType.ET_TRNGL:
                    FFBManager.SetEffect(BlockIndex, FFBManager.EffectTypes.TRIANGLE);
                    break;

                case FFBEType.ET_STUP:
                    FFBManager.SetEffect(BlockIndex, FFBManager.EffectTypes.SAWTOOTHUP);
                    break;

                case FFBEType.ET_STDN:
                    FFBManager.SetEffect(BlockIndex, FFBManager.EffectTypes.SAWTOOTHDOWN);
                    break;
                }
            }
            #endregion

            #region Effect Operation
            vJoy.FFB_EFF_OP Operation = new vJoy.FFB_EFF_OP();
            if ((uint)ERROR.ERROR_SUCCESS == Joystick.Ffb_h_EffOp(data, ref Operation) && EffectOpStr(Operation.EffectOp, out var EffOpStr))
            {
                if (BFFManager.Config.Application.VerbosevJoyFFBReceiverDumpFrames)
                {
                    LogFormat(LogLevels.DEBUG, " >> Effect Operation: {0}", EffOpStr);
                    if (Operation.LoopCount == 0xFF)
                    {
                        LogFormat(LogLevels.DEBUG, " >> Loop until stopped");
                    }
                    else
                    {
                        LogFormat(LogLevels.DEBUG, " >> Loop {0} times", (int)(Operation.LoopCount));
                    }
                }

                switch (Operation.EffectOp)
                {
                case FFBOP.EFF_START:
                    // Start the effect identified by the Effect Handle.
                    FFBManager.StartEffect(BlockIndex, (int)(Operation.LoopCount));
                    break;

                case FFBOP.EFF_STOP:
                    // Stop the effect identified by the Effect Handle.
                    FFBManager.StopEffect(BlockIndex);
                    break;

                case FFBOP.EFF_SOLO:
                    // Start the effect identified by the Effect Handle and stop all other effects.
                    FFBManager.StartEffect(BlockIndex, 1);
                    break;
                }
            }
            #endregion

            #region Global Device Gain
            byte Gain = 0;
            if ((uint)ERROR.ERROR_SUCCESS == Joystick.Ffb_h_DevGain(data, ref Gain))
            {
                if (BFFManager.Config.Application.VerbosevJoyFFBReceiverDumpFrames)
                {
                    LogFormat(LogLevels.DEBUG, " >> Global Device Gain: {0}", Byte2Percent(Gain));
                }
                FFBManager.SetDeviceGain(Byte2Percent(Gain) * 0.01);
            }

            #endregion

            #region Envelope
            vJoy.FFB_EFF_ENVLP Envelope = new vJoy.FFB_EFF_ENVLP();
            if ((uint)ERROR.ERROR_SUCCESS == Joystick.Ffb_h_Eff_Envlp(data, ref Envelope))
            {
                if (BFFManager.Config.Application.VerbosevJoyFFBReceiverDumpFrames)
                {
                    LogFormat(LogLevels.DEBUG, " >> Attack Level: {0}", Envelope.AttackLevel);
                    LogFormat(LogLevels.DEBUG, " >> Fade Level: {0}", Envelope.FadeLevel);
                    LogFormat(LogLevels.DEBUG, " >> Attack Time: {0}", (int)(Envelope.AttackTime));
                    LogFormat(LogLevels.DEBUG, " >> Fade Time: {0}", (int)(Envelope.FadeTime));
                }
                FFBManager.SetEnveloppeParams(BlockIndex, Envelope.AttackTime, Envelope.AttackLevel, Envelope.FadeTime, Envelope.FadeLevel);
            }

            #endregion

            #region Periodic
            vJoy.FFB_EFF_PERIOD EffPrd = new vJoy.FFB_EFF_PERIOD();
            if ((uint)ERROR.ERROR_SUCCESS == Joystick.Ffb_h_Eff_Period(data, ref EffPrd))
            {
                if (BFFManager.Config.Application.VerbosevJoyFFBReceiverDumpFrames)
                {
                    LogFormat(LogLevels.DEBUG, " >> Magnitude: {0}", EffPrd.Magnitude);
                    LogFormat(LogLevels.DEBUG, " >> Offset: {0}", TwosCompWord2Int(EffPrd.Offset));
                    LogFormat(LogLevels.DEBUG, " >> Phase: {0}", EffPrd.Phase * 3600 / 255);
                    LogFormat(LogLevels.DEBUG, " >> Period: {0}", (int)(EffPrd.Period));
                }
                FFBManager.SetPeriodicParams(BlockIndex, (double)EffPrd.Magnitude * Scale_FFB_to_u, TwosCompWord2Int(EffPrd.Offset) * Scale_FFB_to_u, EffPrd.Phase * 0.01, EffPrd.Period);
            }
            #endregion

            #region Ramp Effect
            vJoy.FFB_EFF_RAMP RampEffect = new vJoy.FFB_EFF_RAMP();
            if ((uint)ERROR.ERROR_SUCCESS == Joystick.Ffb_h_Eff_Ramp(data, ref RampEffect))
            {
                if (BFFManager.Config.Application.VerbosevJoyFFBReceiverDumpFrames)
                {
                    LogFormat(LogLevels.DEBUG, " >> Ramp Start: {0}", TwosCompWord2Int(RampEffect.Start));
                    LogFormat(LogLevels.DEBUG, " >> Ramp End: {0}", TwosCompWord2Int(RampEffect.End));
                }
                FFBManager.SetRampParams(BlockIndex, RampEffect.Start * Scale_FFB_to_u, RampEffect.End * Scale_FFB_to_u);
            }

            #endregion

            #region Constant Effect
            vJoy.FFB_EFF_CONSTANT CstEffect = new vJoy.FFB_EFF_CONSTANT();
            if ((uint)ERROR.ERROR_SUCCESS == Joystick.Ffb_h_Eff_Constant(data, ref CstEffect))
            {
                if (BFFManager.Config.Application.VerbosevJoyFFBReceiverDumpFrames)
                {
                    LogFormat(LogLevels.DEBUG, " >> Block Index: {0}", TwosCompWord2Int(CstEffect.EffectBlockIndex));
                    LogFormat(LogLevels.DEBUG, " >> Magnitude: {0}", TwosCompWord2Int(CstEffect.Magnitude));
                }
                FFBManager.SetConstantTorqueEffect(BlockIndex, (double)CstEffect.Magnitude * Scale_FFB_to_u);
            }

            #endregion
        }
        private static void OnEffectObj(IntPtr data, object userData)
        {
            int      id    = 0;
            FFBPType type  = 0;
            int      DSize = 0;

            Byte[] arr     = new Byte[20];
            UInt32 wType   = 0;
            IntPtr bytes   = IntPtr.Zero;
            string TypeStr = "";


            // Get FFB packet raw data
            var result = joystick.Ffb_h_Packet(data, ref wType, ref DSize, ref arr);

            dlg.FfbTextBox_Write(String.Format("\r\n\r\n ============= FFB Packet size Size {0} =============", DSize + 8));

            // Get the ID of the device that this DDB packet refers to
            result = joystick.Ffb_h_DeviceID(data, ref id);
            dlg.FfbTextBox_Write(String.Format("\r\n > Device ID: {0}", id));

            // Get the type of the packet
            result = joystick.Ffb_h_Type(data, ref type);
            if (result == 0)
            {
                bool ok = PacketType2Str(type, ref TypeStr);
                if (!ok)
                {
                    dlg.FfbTextBox_Write(String.Format("\r\n > Packet Type: {0}", type));
                }
                else
                {
                    dlg.FfbTextBox_Write(String.Format("\r\n > Packet Type: {0}", TypeStr));
                }
            }
            ;

            // Get the index of the effect block (Always 1)
            int iBlock = 0;

            result = joystick.Ffb_h_EBI(data, ref iBlock);
            if (result == 0)
            {
                dlg.FfbTextBox_Write(String.Format("\r\n > Effect Block Index: {0}", iBlock));
            }

            // TODO: Add constant magnitude

            #region Effect Report
            // Effect Report
            vJoy.FFB_EFF_REPORT Effect = new vJoy.FFB_EFF_REPORT();
            result = joystick.Ffb_h_Eff_Report(data, ref Effect);
            if (result == 0)
            {
                ///// This is an Effect Block
                // Effect type
                if (!EffectType2Str(Effect.EffectType, ref TypeStr))
                {
                    dlg.FfbTextBox_Write(String.Format("\r\n >> Effect Report: {0}", Effect.EffectType));
                }
                else
                {
                    dlg.FfbTextBox_Write(String.Format("\r\n >> Effect Report: {0}", TypeStr));
                }

                // Effect Direction
                if (Effect.Polar)
                {
                    dlg.FfbTextBox_Write(String.Format("\r\n >> Direction: {0} deg ({1:D2})", Polar2Deg(Effect.Direction), Effect.Direction));
                }
                else
                {
                    dlg.FfbTextBox_Write(String.Format("\r\n >> X Direction: {0:X2}", Effect.DirX));
                    dlg.FfbTextBox_Write(String.Format("\r\n >> Y Direction: {0:X2}", Effect.DirY));
                };

                // Duration of the effect
                if (Effect.Duration == 0xFFFF)
                {
                    dlg.FfbTextBox_Write(String.Format("\r\n >> Duration: Infinit"));
                }
                else
                {
                    dlg.FfbTextBox_Write(String.Format("\r\n >> Duration: {0} MilliSec", (int)(Effect.Duration)));
                }

                // Trigger Repeat
                if (Effect.TrigerRpt == 0xFFFF)
                {
                    dlg.FfbTextBox_Write(String.Format("\r\n >> Trigger Repeat: Infinit"));
                }
                else
                {
                    dlg.FfbTextBox_Write(String.Format("\r\n >> Trigger Repeat: {0}", (int)(Effect.TrigerRpt)));
                }

                // Sample Period
                if (Effect.SamplePrd == 0xFFFF)
                {
                    dlg.FfbTextBox_Write(String.Format("\r\n >> Sample Period: Infinit"));
                }
                else
                {
                    dlg.FfbTextBox_Write(String.Format("\r\n >> Sample Period: {0}", (int)(Effect.SamplePrd)));
                }


                // Gain
                dlg.FfbTextBox_Write(String.Format("\r\n >> Gain: {0}%", Byte2Percent(Effect.Gain)));
            }
            ;

            #endregion   Effect Report

            #region PID Device Control
            // Device Control (Global controls such as Device Reset, Device Pause .....
            FFB_CTRL Control = FFB_CTRL.CTRL_STOPALL;
            string   CtrlStr = "";
            if ((0 == joystick.Ffb_h_DevCtrl(data, ref Control)) && DevCtrl2Str(Control, ref CtrlStr))
            {
                dlg.FfbTextBox_Write(String.Format("\r\n >> PID Device Control: {0}", CtrlStr));
            }

            #endregion

            #region Effect Operation
            vJoy.FFB_EFF_OP Operation = new vJoy.FFB_EFF_OP();
            string          EffOpStr  = "";
            if (0 == joystick.Ffb_h_EffOp(data, ref Operation) && EffectOpStr(Operation.EffectOp, ref EffOpStr))
            {
                dlg.FfbTextBox_Write(String.Format("\r\n >> Effect Operation: {0}", EffOpStr));
                if (Operation.LoopCount == 0xFF)
                {
                    dlg.FfbTextBox_Write(String.Format("\r\n >> Loop until stopped"));
                }
                else
                {
                    dlg.FfbTextBox_Write(String.Format("\r\n >> Loop {0} times", (int)(Operation.LoopCount)));
                }
            }
            ;
            #endregion

            #region Global Device Gain
            Byte Gain = 0;
            if (0 == joystick.Ffb_h_DevGain(data, ref Gain))
            {
                dlg.FfbTextBox_Write(String.Format("\r\n >> Global Device Gain: {0}", Byte2Percent(Gain)));
            }

            #endregion

            #region Condition
            vJoy.FFB_EFF_COND Condition = new vJoy.FFB_EFF_COND();
            if (0 == joystick.Ffb_h_Eff_Cond(data, ref Condition))
            {
                if (Condition.isY)
                {
                    dlg.FfbTextBox_Write(String.Format("\r\n >> Y Axis"));
                }
                else
                {
                    dlg.FfbTextBox_Write(String.Format("\r\n >> X Axis"));
                }
                dlg.FfbTextBox_Write(String.Format("\r\n >> Center Point Offset: {0}", Condition.CenterPointOffset));
                dlg.FfbTextBox_Write(String.Format("\r\n >> Positive Coefficient: {0}", Condition.PosCoeff));
                dlg.FfbTextBox_Write(String.Format("\r\n >> Negative Coefficient: {0}", Condition.NegCoeff));
                dlg.FfbTextBox_Write(String.Format("\r\n >> Positive Saturation: {0}", Condition.PosSatur));
                dlg.FfbTextBox_Write(String.Format("\r\n >> Negative Saturation: {0}", Condition.NegSatur));
                dlg.FfbTextBox_Write(String.Format("\r\n >> Dead Band: {0}", Condition.DeadBand));
            }
            #endregion

            #region Envelope
            vJoy.FFB_EFF_ENVLP Envelope = new vJoy.FFB_EFF_ENVLP();
            if (0 == joystick.Ffb_h_Eff_Envlp(data, ref Envelope))
            {
                dlg.FfbTextBox_Write(String.Format("\r\n >> Attack Level: {0}", Envelope.AttackLevel));
                dlg.FfbTextBox_Write(String.Format("\r\n >> Fade Level: {0}", Envelope.FadeLevel));
                dlg.FfbTextBox_Write(String.Format("\r\n >> Attack Time: {0}", (int)(Envelope.AttackTime)));
                dlg.FfbTextBox_Write(String.Format("\r\n >> Fade Time: {0}", (int)(Envelope.FadeTime)));
            }
            ;
            #endregion

            #region Periodic
            vJoy.FFB_EFF_PERIOD EffPrd = new vJoy.FFB_EFF_PERIOD();
            if (0 == joystick.Ffb_h_Eff_Period(data, ref EffPrd))
            {
                dlg.FfbTextBox_Write(String.Format("\r\n >> Magnitude: {0}", EffPrd.Magnitude));
                dlg.FfbTextBox_Write(String.Format("\r\n >> Offset: {0}", EffPrd.Offset));
                dlg.FfbTextBox_Write(String.Format("\r\n >> Phase: {0}", EffPrd.Phase));
                dlg.FfbTextBox_Write(String.Format("\r\n >> Period: {0}", (int)(EffPrd.Period)));
            }
            ;
            #endregion

            #region Effect Type
            FFBEType EffectType = FFBEType.ET_NONE;
            if (0 == joystick.Ffb_h_EffNew(data, ref EffectType))
            {
                if (EffectType2Str(EffectType, ref TypeStr))
                {
                    dlg.FfbTextBox_Write(String.Format("\r\n >> Effect Type: {0}", TypeStr));
                }
                else
                {
                    dlg.FfbTextBox_Write(String.Format("\r\n >> Effect Type: Unknown"));
                }
            }
            #endregion

            #region Ramp Effect
            vJoy.FFB_EFF_RAMP RampEffect = new vJoy.FFB_EFF_RAMP();
            if (0 == joystick.Ffb_h_Eff_Ramp(data, ref RampEffect))
            {
                dlg.FfbTextBox_Write(String.Format("\r\n >> Ramp Start: {0}", RampEffect.Start));
                dlg.FfbTextBox_Write(String.Format("\r\n >> Ramp End: {0}", RampEffect.End));
            }
            ;
            #endregion

            #region Constant Effect
            vJoy.FFB_EFF_CONSTANT ConstantEffect = new vJoy.FFB_EFF_CONSTANT();
            if (0 == joystick.Ffb_h_Eff_Constant(data, ref ConstantEffect))
            {
                dlg.FfbTextBox_Write(String.Format("\r\n >> Constant Magnitude: {0}", ConstantEffect.Magnitude));
            }
            ;

            #endregion
            dlg.FfbTextBox_Write(String.Format("\r\n ==============================================\r\n"));
        }
        // Convert Packet type to String
        private static bool PacketType2Str(FFBPType Type, ref string Str)
        {
            bool stat = true;

            switch (Type)
            {
                case FFBPType.PT_EFFREP:
                    Str = "Effect Report";
                    break;
                case FFBPType.PT_ENVREP:
                    Str = "Envelope Report";
                    break;
                case FFBPType.PT_CONDREP:
                    Str = "Condition Report";
                    break;
                case FFBPType.PT_PRIDREP:
                    Str = "Periodic Report";
                    break;
                case FFBPType.PT_CONSTREP:
                    Str = "Constant Force Report";
                    break;
                case FFBPType.PT_RAMPREP:
                    Str = "Ramp Force Report";
                    break;
                case FFBPType.PT_CSTMREP:
                    Str = "Custom Force Data Report";
                    break;
                case FFBPType.PT_SMPLREP:
                    Str = "Download Force Sample";
                    break;
                case FFBPType.PT_EFOPREP:
                    Str = "Effect Operation Report";
                    break;
                case FFBPType.PT_BLKFRREP:
                    Str = "PID Block Free Report";
                    break;
                case FFBPType.PT_CTRLREP:
                    Str = "PID Device Control";
                    break;
                case FFBPType.PT_GAINREP:
                    Str = "Device Gain Report";
                    break;
                case FFBPType.PT_SETCREP:
                    Str = "Set Custom Force Report";
                    break;
                case FFBPType.PT_NEWEFREP:
                    Str = "Create New Effect Report";
                    break;
                case FFBPType.PT_BLKLDREP:
                    Str = "Block Load Report";
                    break;
                case FFBPType.PT_POOLREP:
                    Str = "PID Pool Report";
                    break;
                default:
                    stat = false;
                    break;
            }


            return stat;
        }
Example #12
0
        /// <summary>
        /// Called when vJoy has a new FFB packet.
        /// WARNING This is called from a thread pool managed by windows.
        /// The thread itself is created and managed by vJoyInterface.dll.
        /// Do not overload it, else you will me missing FFB packets from
        /// third party application.
        /// </summary>
        /// <param name="ffbDataPtr"></param>
        /// <param name="userData"></param>
        public void FfbFunction1(IntPtr data, object userdata)
        {
            // Packet Header
            //copy ffb packet to managed structure
            InternalFfbPacket packet = (InternalFfbPacket)Marshal.PtrToStructure(data, typeof(InternalFfbPacket));

            // Packet Header
            LogFormat("============= FFB Packet =============");

            /////// Packet Device ID, and Type Block Index (if exists)
            #region Packet Device ID, and Type Block Index


            uint     DeviceID = 0, BlockIndex = 0;
            FFBPType Type = new FFBPType();

            if ((uint)ERROR.ERROR_SUCCESS == Joystick.Ffb_h_DeviceID(data, ref DeviceID))
            {
                LogFormat(" > Device ID: {0}", DeviceID);
            }

            // Effect block index only used when simultaneous effects should be done by
            // underlying hardware, which is not the case for a single motor driving wheel
            if ((uint)ERROR.ERROR_SUCCESS == Joystick.Ffb_h_EffectBlockIndex(data, ref BlockIndex))
            {
                LogFormat(" > Effect Block Index: {0}", BlockIndex);
            }

            if ((uint)ERROR.ERROR_SUCCESS == Joystick.Ffb_h_Type(data, ref Type))
            {
                if (!PacketType2Str(Type, out var TypeStr))
                {
                    LogFormat(" > Packet Type: {0}", Type);
                }
                else
                {
                    LogFormat(" > Packet Type: {0}", TypeStr);
                }
                switch (Type)
                {
                case FFBPType.PT_POOLREP:
                    LogFormat(" > Pool report handled by driver side");
                    break;

                case FFBPType.PT_BLKLDREP:
                    LogFormat(" > Block Load report handled by driver side");
                    break;

                case FFBPType.PT_BLKFRREP:
                    //FFBManager.FreeEffect(BlockIndex);
                    // Update PID
                    Joystick.FfbReadPID(DeviceID, ref PIDBlock);
                    LogFormat(" > Block Free effect id {0}", PIDBlock.NextFreeEID);
                    break;
                }
            }



            #endregion

            #region PID Device Control
            FFB_CTRL Control = new FFB_CTRL();
            if ((uint)ERROR.ERROR_SUCCESS == Joystick.Ffb_h_DevCtrl(data, ref Control) && DevCtrl2Str(Control, out var CtrlStr))
            {
                LogFormat(" >> PID Device Control: {0}", CtrlStr);
                switch (Control)
                {
                case FFB_CTRL.CTRL_DEVRST:
                    // Update PID data to get the resetted values from driver side
                    Joystick.FfbReadPID(DeviceID, ref PIDBlock);
                    // device reset
                    break;

                case FFB_CTRL.CTRL_ENACT:
                    break;

                case FFB_CTRL.CTRL_DISACT:
                    break;

                case FFB_CTRL.CTRL_STOPALL:
                    break;
                }
            }

            #endregion


            #region Create new effect
            FFBEType EffectType    = new FFBEType();
            uint     NewBlockIndex = 0;
            if ((uint)ERROR.ERROR_SUCCESS == Joystick.Ffb_h_CreateNewEffect(data, ref EffectType, ref NewBlockIndex))
            {
                // Create new effect

                // Update PID
                Joystick.FfbReadPID(Id, ref PIDBlock);

                if (EffectType2Str(EffectType, out var TypeStr))
                {
                    LogFormat(" >> Effect Type: {0}", TypeStr);
                }
                else
                {
                    LogFormat(" >> Effect Type: Unknown({0})", EffectType);
                }
                LogFormat(" >> New Effect ID: {0}", NewBlockIndex);
                if (NewBlockIndex != PIDBlock.PIDBlockLoad.EffectBlockIndex)
                {
                    LogFormat("!!! BUG NewBlockIndex=" + NewBlockIndex + " <> pid=" + ((int)PIDBlock.PIDBlockLoad.EffectBlockIndex));
                }
                LogFormat(" >> LoadStatus {0}", PIDBlock.PIDBlockLoad.LoadStatus);
            }
            #endregion

            #region Condition
            vJoy.FFB_EFF_COND Condition = new vJoy.FFB_EFF_COND();
            if ((uint)ERROR.ERROR_SUCCESS == Joystick.Ffb_h_Eff_Cond(data, ref Condition))
            {
                if (Condition.isY)
                {
                    LogFormat(" >> Y Axis");
                }
                else
                {
                    LogFormat(" >> X Axis");
                }
                LogFormat(" >> Center Point Offset: {0}", TwosCompWord2Int(Condition.CenterPointOffset));
                LogFormat(" >> Positive Coefficient: {0}", TwosCompWord2Int(Condition.PosCoeff));
                LogFormat(" >> Negative Coefficient: {0}", TwosCompWord2Int(Condition.NegCoeff));
                LogFormat(" >> Positive Saturation: {0}", Condition.PosSatur);
                LogFormat(" >> Negative Saturation: {0}", Condition.NegSatur);
                LogFormat(" >> Dead Band: {0}", Condition.DeadBand);
            }
            #endregion

            #region Effect Report
            vJoy.FFB_EFF_REPORT Effect = new vJoy.FFB_EFF_REPORT();
            if ((uint)ERROR.ERROR_SUCCESS == Joystick.Ffb_h_Eff_Report(data, ref Effect))
            {
                if (!EffectType2Str(Effect.EffectType, out var TypeStr))
                {
                    LogFormat(" >> Effect Report: {0} {1}", (int)Effect.EffectType, Effect.EffectType.ToString());
                }
                else
                {
                    LogFormat(" >> Effect Report: {0}", TypeStr);
                }
                LogFormat(" >> AxisEnabledDirection: {0}", (ushort)Effect.AxesEnabledDirection);
                if (Effect.Polar)
                {
                    LogFormat(" >> Direction: {0} deg ({1})", Polar2Deg(Effect.Direction), Effect.Direction);
                }
                else
                {
                    LogFormat(" >> X Direction: {0}", Effect.DirX);
                    LogFormat(" >> Y Direction: {0}", Effect.DirY);
                }

                if (Effect.Duration == 0xFFFF)
                {
                    LogFormat(" >> Duration: Infinit");
                }
                else
                {
                    LogFormat(" >> Duration: {0} MilliSec", (int)(Effect.Duration));
                }

                if (Effect.TrigerRpt == 0xFFFF)
                {
                    LogFormat(" >> Trigger Repeat: Infinit");
                }
                else
                {
                    LogFormat(" >> Trigger Repeat: {0}", (int)(Effect.TrigerRpt));
                }

                if (Effect.SamplePrd == 0xFFFF)
                {
                    LogFormat(" >> Sample Period: Infinit");
                }
                else
                {
                    LogFormat(" >> Sample Period: {0}", (int)(Effect.SamplePrd));
                }

                if (Effect.StartDelay == 0xFFFF)
                {
                    LogFormat(" >> Start Delay: max ");
                }
                else
                {
                    LogFormat(" >> Start Delay: {0}", (int)(Effect.StartDelay));
                }


                LogFormat(" >> Gain: {0}%%", Byte2Percent(Effect.Gain));
            }
            #endregion

            #region Effect Operation
            vJoy.FFB_EFF_OP Operation = new vJoy.FFB_EFF_OP();
            if ((uint)ERROR.ERROR_SUCCESS == Joystick.Ffb_h_EffOp(data, ref Operation) && EffectOpStr(Operation.EffectOp, out var EffOpStr))
            {
                LogFormat(" >> Effect Operation: {0}", EffOpStr);
                if (Operation.LoopCount == 0xFF)
                {
                    LogFormat(" >> Loop until stopped");
                }
                else
                {
                    LogFormat(" >> Loop {0} times", (int)(Operation.LoopCount));
                }

                switch (Operation.EffectOp)
                {
                case FFBOP.EFF_START:
                    // Start the effect identified by the Effect Handle.
                    break;

                case FFBOP.EFF_STOP:
                    // Stop the effect identified by the Effect Handle.
                    break;

                case FFBOP.EFF_SOLO:
                    // Start the effect identified by the Effect Handle and stop all other effects.
                    break;
                }
            }
            #endregion

            #region Global Device Gain
            byte Gain = 0;
            if ((uint)ERROR.ERROR_SUCCESS == Joystick.Ffb_h_DevGain(data, ref Gain))
            {
                LogFormat(" >> Global Device Gain: {0}", Byte2Percent(Gain));
            }

            #endregion

            #region Envelope
            vJoy.FFB_EFF_ENVLP Envelope = new vJoy.FFB_EFF_ENVLP();
            if ((uint)ERROR.ERROR_SUCCESS == Joystick.Ffb_h_Eff_Envlp(data, ref Envelope))
            {
                LogFormat(" >> Attack Level: {0}", Envelope.AttackLevel);
                LogFormat(" >> Fade Level: {0}", Envelope.FadeLevel);
                LogFormat(" >> Attack Time: {0}", (int)(Envelope.AttackTime));
                LogFormat(" >> Fade Time: {0}", (int)(Envelope.FadeTime));
            }

            #endregion

            #region Periodic
            vJoy.FFB_EFF_PERIOD EffPrd = new vJoy.FFB_EFF_PERIOD();
            if ((uint)ERROR.ERROR_SUCCESS == Joystick.Ffb_h_Eff_Period(data, ref EffPrd))
            {
                LogFormat(" >> Magnitude: {0}", EffPrd.Magnitude);
                LogFormat(" >> Offset: {0}", TwosCompWord2Int(EffPrd.Offset));
                LogFormat(" >> Phase: {0}", EffPrd.Phase * 3600 / 255);
                LogFormat(" >> Period: {0}", (int)(EffPrd.Period));
            }
            #endregion

            #region Ramp Effect
            vJoy.FFB_EFF_RAMP RampEffect = new vJoy.FFB_EFF_RAMP();
            if ((uint)ERROR.ERROR_SUCCESS == Joystick.Ffb_h_Eff_Ramp(data, ref RampEffect))
            {
                LogFormat(" >> Ramp Start: {0}", TwosCompWord2Int(RampEffect.Start));
                LogFormat(" >> Ramp End: {0}", TwosCompWord2Int(RampEffect.End));
            }

            #endregion

            #region Constant Effect
            vJoy.FFB_EFF_CONSTANT CstEffect = new vJoy.FFB_EFF_CONSTANT();
            if ((uint)ERROR.ERROR_SUCCESS == Joystick.Ffb_h_Eff_Constant(data, ref CstEffect))
            {
                LogFormat(" >> Block Index: {0}", TwosCompWord2Int(CstEffect.EffectBlockIndex));
                LogFormat(" >> Magnitude: {0}", TwosCompWord2Int(CstEffect.Magnitude));
            }

            #endregion


            DumpFrame(data);
            LogFormat("======================================");
        }
Example #13
0
        //private EffectBlock effectBlockNew = null; //Block to be loaded
        private void func_OnEffectObj(IntPtr data, object userData)
        {
            Trace.WriteLine("");
            //Trace.WriteLine(vJoy_Extra.FfbGetEffect());
            const int ERROR_SUCCESS = 0;

            Trace.WriteLine(string.Format("Got FFB Packet"));
            int      id               = -1;
            FFBPType type             = (FFBPType)0;
            Int32    effectBlockIndex = -1;

            if (joystick.Ffb_h_DeviceID(data, ref id) != ERROR_SUCCESS)
            {
                Trace.WriteLine("Error: Unable to read DevID");
                return;
            }
            if (joystick.Ffb_h_Type(data, ref type) != ERROR_SUCCESS)
            {
                Trace.WriteLine("Error: Unable to read FFB type");
                return;
            }
            Trace.WriteLine(type.ToString());
            if (joystick.Ffb_h_EBI(data, ref effectBlockIndex) != ERROR_SUCCESS)
            {
                effectBlockIndex = -1;
            }
            FFBDevice srcDevice = devices[id - 1];

            //Read Based on Type
            switch (type)
            {
            case FFBPType.PT_EFFREP:
                vJoy.FFB_EFF_REPORT effectParam = new vJoy.FFB_EFF_REPORT();
                if (joystick.Ffb_h_Eff_Report(data, ref effectParam) != ERROR_SUCCESS)
                {
                    Trace.WriteLine("Error: Unable read Effect Param");
                    return;
                }
                Trace.WriteLine(string.Format("Got Effect Param on EBI: {0}", effectParam.EffectBlockIndex));
                //Trace.WriteLine(String.Format("EffectType: {0}", effectParam.EffectType.ToString()));
                //Trace.WriteLine(String.Format("Duration  : {0}", effectParam.Duration));
                //Trace.WriteLine(String.Format("TrigerRpt : {0}", effectParam.TrigerRpt));
                //Trace.WriteLine(String.Format("SamplePrd : {0}", effectParam.SamplePrd));
                //Trace.WriteLine(String.Format("Gain      : {0}", effectParam.Gain));
                //Trace.WriteLine(String.Format("TrigerBtn : {0}", effectParam.TrigerBtn));
                //Trace.WriteLine(String.Format("Polar     : {0}", effectParam.Polar));
                //Trace.WriteLine(String.Format("Dir1      : {0}", effectParam.DirX));
                //Trace.WriteLine(String.Format("Dir2      : {0}", effectParam.DirY));

                byte[] rawP         = new byte[0];
                int    len          = 0;
                uint   transfertype = 0;
                joystick.Ffb_h_Packet(data, ref transfertype, ref len, ref rawP);
                Trace.WriteLine(string.Format("TypeSpecificBlockOffset1 : {0}", BitConverter.ToUInt16(rawP, len - 4)));
                Trace.WriteLine(string.Format("TypeSpecificBlockOffset2 : {0}", BitConverter.ToUInt16(rawP, len - 2)));

                srcDevice.EffectBlocks[(byte)effectBlockIndex].ffbHeader = effectParam;
                break;

            case FFBPType.PT_ENVREP:
                vJoy.FFB_EFF_ENVLP envEffect = new vJoy.FFB_EFF_ENVLP();
                if (joystick.Ffb_h_Eff_Envlp(data, ref envEffect) != ERROR_SUCCESS)
                {
                    Trace.WriteLine("Error: Unable read Envelope Effect");
                    return;
                }
                srcDevice.EffectBlocks[(byte)effectBlockIndex].SecondaryEffectData(envEffect);
                Trace.WriteLine(string.Format("Got Envelope Effect on EBI: {0}", envEffect.EffectBlockIndex));
                //Trace.WriteLine(String.Format("Start : {0}", envEffect.AttackLevel));
                //Trace.WriteLine(String.Format("STime : {0}", envEffect.AttackTime));
                //Trace.WriteLine(String.Format("End   : {0}", envEffect.FadeLevel));
                //Trace.WriteLine(String.Format("ETime : {0}", envEffect.FadeTime));
                break;

            case FFBPType.PT_CONDREP:
                vJoy.FFB_EFF_COND condEffect = new vJoy.FFB_EFF_COND();
                if (joystick.Ffb_h_Eff_Cond(data, ref condEffect) != ERROR_SUCCESS)
                {
                    Trace.WriteLine("Error: Unable read Conditional Effect");
                    return;
                }
                Trace.WriteLine(string.Format("Got Conditional Effect on EBI (Not Supported): {0}", effectBlockIndex));
                break;

            case FFBPType.PT_PRIDREP:
                vJoy.FFB_EFF_PERIOD perEffect = new vJoy.FFB_EFF_PERIOD();
                if (joystick.Ffb_h_Eff_Period(data, ref perEffect) != ERROR_SUCCESS)
                {
                    Trace.WriteLine("Error: Unable read Periodic Effect");
                    return;
                }
                Trace.WriteLine(string.Format("Got Periodic Effect on EBI: {0}", perEffect.EffectBlockIndex));
                //Trace.WriteLine(String.Format("Magnitude : {0}", perEffect.Magnitude));
                //Trace.WriteLine(String.Format("Offset    : {0}", perEffect.Offset));
                //Trace.WriteLine(String.Format("Phase     : {0}", perEffect.Phase));
                //Trace.WriteLine(String.Format("Period    : {0}", perEffect.Period));
                srcDevice.EffectBlocks[(byte)effectBlockIndex].PrimaryEffectData(perEffect);
                break;

            case FFBPType.PT_CONSTREP:
                vJoy.FFB_EFF_CONSTANT constEffect = new vJoy.FFB_EFF_CONSTANT();
                if (joystick.Ffb_h_Eff_Constant(data, ref constEffect) != ERROR_SUCCESS)
                {
                    Trace.WriteLine("Error: Unable read Constant Effect");
                    return;
                }
                Trace.WriteLine(string.Format("Got Const Effect on EBI : {0}", constEffect.EffectBlockIndex));
                //Trace.WriteLine(String.Format("Magnitude : {0}", constEffect.Magnitude));
                srcDevice.EffectBlocks[(byte)effectBlockIndex].PrimaryEffectData(constEffect);
                break;

            case FFBPType.PT_RAMPREP:
                vJoy.FFB_EFF_RAMP rampEffect = new vJoy.FFB_EFF_RAMP();
                if (joystick.Ffb_h_Eff_Ramp(data, ref rampEffect) != ERROR_SUCCESS)
                {
                    Trace.WriteLine("Error: Unable read Ramp Effect");
                    return;
                }
                Trace.WriteLine(string.Format("Got Ramp Effect on EBI (Not Tested): {0}", rampEffect.EffectBlockIndex));
                //Trace.WriteLine(String.Format("Start : {0}", rampEffect.Start));
                //Trace.WriteLine(String.Format("End   : {0}", rampEffect.End));
                srcDevice.EffectBlocks[(byte)effectBlockIndex].PrimaryEffectData(rampEffect);
                break;

            case FFBPType.PT_CSTMREP:
                Trace.WriteLine("Error: Unkown command");
                break;

            case FFBPType.PT_SMPLREP:
                Trace.WriteLine("Error: Unkown command");
                break;

            case FFBPType.PT_EFOPREP:
                vJoy.FFB_EFF_OP effect_OP = new vJoy.FFB_EFF_OP();
                if (joystick.Ffb_h_EffOp(data, ref effect_OP) != ERROR_SUCCESS)
                {
                    Trace.WriteLine("Error: Unable read Effect OP");
                    return;
                }
                Trace.WriteLine(string.Format("Effect Command : {0}, Loops : {1}, EBI : {2} ", effect_OP.EffectOp.ToString(), effect_OP.LoopCount, effect_OP.EffectBlockIndex));
                switch (effect_OP.EffectOp)
                {
                case FFBOP.EFF_START:
                    lock (vibThreadSentry)
                    {
                        Trace.WriteLine("Effect Start");
                        srcDevice.EffectBlocks[(byte)effectBlockIndex].Start(effect_OP.LoopCount);
                    }
                    break;

                case FFBOP.EFF_STOP:
                    lock (vibThreadSentry)
                    {
                        Trace.WriteLine("Effect Stop");
                        srcDevice.EffectBlocks[(byte)effectBlockIndex].Stop();
                    }
                    break;

                default:
                    Trace.WriteLine("Error: Unkown command");
                    break;
                }
                break;

            case FFBPType.PT_BLKFRREP:
                Trace.WriteLine("Free Block");
                lock (vibThreadSentry)
                {
                    srcDevice.RemoveBlock((byte)effectBlockIndex);
                }
                break;

            case FFBPType.PT_CTRLREP:
                FFB_CTRL control = (FFB_CTRL)0;
                if (joystick.Ffb_h_DevCtrl(data, ref control) != ERROR_SUCCESS)
                {
                    Trace.WriteLine("Error: Unable read Dev Control");
                    return;
                }
                //byte[] rawP2 = new byte[0];
                //int len2 = 0;
                //uint transfertype2 = 0;
                //joystick.Ffb_h_Packet(data, ref transfertype2, ref len2, ref rawP2);
                //Trace.WriteLine(String.Format("DevControlThing : {0}", BitConverter.ToUInt16(rawP2, len2 - 2)));
                switch (control)
                {
                case FFB_CTRL.CTRL_ENACT:
                    Trace.WriteLine("Enable all actuators (Not Supported)");
                    break;

                case FFB_CTRL.CTRL_DISACT:
                    Trace.WriteLine("Disable all actuators (Not Supported)");
                    break;

                case FFB_CTRL.CTRL_STOPALL:
                    Trace.WriteLine("Stop All Effects");
                    //Set All To Zero + Pause
                    foreach (BaseEffectBlock peffect in srcDevice.EffectBlocks.Values)
                    {
                        peffect.Stop();
                    }
                    break;

                case FFB_CTRL.CTRL_DEVRST:
                    Trace.WriteLine("Reset Device");
                    lock (vibThreadSentry)
                    {
                        srcDevice.ClearBlocks();
                        srcDevice.DevicePaused = false;
                    }
                    break;

                case FFB_CTRL.CTRL_DEVPAUSE:
                    Trace.WriteLine("Pause all effects");
                    foreach (BaseEffectBlock peffect in srcDevice.EffectBlocks.Values)
                    {
                        peffect.DevPause();
                    }
                    srcDevice.DevicePaused = true;
                    break;

                case FFB_CTRL.CTRL_DEVCONT:
                    Trace.WriteLine("Resume all effects paused by DevPause");
                    foreach (BaseEffectBlock peffect in srcDevice.EffectBlocks.Values)
                    {
                        peffect.DevPause();
                    }
                    srcDevice.DevicePaused = false;
                    break;

                default:
                    Trace.WriteLine("Unkown Command");
                    break;
                }
                break;

            case FFBPType.PT_GAINREP:
                byte gain = 1;
                if (joystick.Ffb_h_DevGain(data, ref gain) != ERROR_SUCCESS)
                {
                    Trace.WriteLine("Error: Unable read Dev Gain Command");
                    return;
                }
                Trace.WriteLine((string.Format("Gain Set : {0}", gain)));
                srcDevice.DeviceGain = (float)gain / vJoyConstants.EFFECT_MAX_GAIN;
                break;

            case FFBPType.PT_SETCREP:
                Trace.WriteLine("Error: Unkown command");
                break;

            //Feature
            case FFBPType.PT_NEWEFREP:
                FFBEType nextEffect = (FFBEType)0;
                if (joystick.Ffb_h_EffNew(data, ref nextEffect) != ERROR_SUCCESS)
                {
                    Trace.WriteLine("Error: Unable read new effect");
                    return;
                }
                Trace.WriteLine((string.Format("Incomming Effect : {0}", nextEffect.ToString())));
                //Add + Load Block
                //Use effecct type as an index
                byte free_ebi = srcDevice.NextKey();
                if (free_ebi != 0)
                {
                    BaseEffectBlock newBlock;
                    switch (nextEffect)
                    {
                    //ET_NONE
                    case FFBEType.ET_CONST:
                        newBlock = new ConstEffectBlock();
                        break;

                    case FFBEType.ET_RAMP:
                        newBlock = new RampEffectBlock();
                        break;

                    case FFBEType.ET_SQR:
                        newBlock = new SquareEffectBlock();
                        break;

                    case FFBEType.ET_SINE:
                        newBlock = new SineEffectBlock();
                        break;

                    case FFBEType.ET_TRNGL:
                        newBlock = new TrangleEffectBlock();
                        break;

                    case FFBEType.ET_STUP:
                        newBlock = new SawUpEffectBlock();
                        break;

                    case FFBEType.ET_STDN:
                        newBlock = new SawDownEffectBlock();
                        break;

                    //Conditinal effects (unsurported)
                    case FFBEType.ET_SPRNG:
                    case FFBEType.ET_DMPR:
                    case FFBEType.ET_INRT:
                    case FFBEType.ET_FRCTN:
                        Trace.WriteLine("Unsupported Conditinal Effect");
                        newBlock = new NullEffectBlock();
                        break;

                    case FFBEType.ET_CSTM:         //Custom (need test case)
                        Trace.WriteLine("Unsupported Custom Effect");
                        newBlock = new NullEffectBlock();
                        break;

                    default:
                        Trace.WriteLine("Unkown Effect");
                        newBlock = new NullEffectBlock();
                        break;
                    }
                    if (newBlock != null)
                    {
                        newBlock.m_effectType = nextEffect;
                        //TODO, If Blockload support arrives
                        //Do AddBlock/ebi selection @ Blockload
                        lock (vibThreadSentry)
                        {
                            srcDevice.AddBlock(free_ebi, newBlock);
                        }
                    }
                }
                break;

            case FFBPType.PT_BLKLDREP:
                Trace.WriteLine("BULK LOAD (Not Supported)");
                break;

            case FFBPType.PT_POOLREP:
                Trace.WriteLine("Pool Report (Not supported)");
                break;

            default:
                Trace.WriteLine("Error: Unkown command");
                break;
            }
        }
Example #14
0
        /// <summary>
        /// Called when vJoy has a new FFB packet.
        /// WARNING This is called from a thread pool managed by windows.
        /// The thread itself is created and managed by vJoyInterface.dll.
        /// Do not overload it, else you will me missing FFB packets from
        /// third party application.
        /// </summary>
        /// <param name="ffbDataPtr"></param>
        /// <param name="userData"></param>
        public void FfbFunction1(IntPtr data, object userdata)
        {
            // Packet Header
            //copy ffb packet to managed structure
            InternalFfbPacket packet = (InternalFfbPacket)Marshal.PtrToStructure(data, typeof(InternalFfbPacket));

            /////// Packet Device ID, and Type Block Index (if exists)
            #region Packet Device ID, and Type Block Index
            int      DeviceID = 0, BlockIndex = 0;
            FFBPType Type = new FFBPType();
#if CONSOLE_DUMP
            string TypeStr = "";
            Console.WriteLine("============= FFB Packet size Size {0} =============", (int)(packet.DataSize));
#endif

            if ((uint)ERROR.ERROR_SUCCESS == Joystick.Ffb_h_DeviceID(data, ref DeviceID))
            {
#if CONSOLE_DUMP
                Console.WriteLine(" > Device ID: {0}", DeviceID);
#endif
            }
            if ((uint)ERROR.ERROR_SUCCESS == Joystick.Ffb_h_Type(data, ref Type))
            {
#if CONSOLE_DUMP
                if (!PacketType2Str(Type, ref TypeStr))
                {
                    Console.WriteLine(" > Packet Type: {0}", Type);
                }
                else
                {
                    Console.WriteLine(" > Packet Type: {0}", TypeStr);
                }
#endif
                switch (Type)
                {
                case FFBPType.PT_POOLREP:
                    Console.WriteLine("POOL REPORT !!!");
                    break;

                case FFBPType.PT_BLKLDREP:
                    Console.WriteLine("BLOCK LOAD REPORT !!!");
                    break;

                case FFBPType.PT_BLKFRREP:
                    Console.WriteLine("BLOCK FREE REPORT !!!");
                    break;
                }
            }

            // Effect block index only used when simultaneous effects should be done by
            // underlying hardware, which is not the case for a single motor driving wheel
            if ((uint)ERROR.ERROR_SUCCESS == Joystick.Ffb_h_EBI(data, ref BlockIndex))
            {
#if CONSOLE_DUMP
                Console.WriteLine(" > Effect Block Index: {0}", BlockIndex);
#endif
                // Remove 1 to get [0..n-1] range
                BlockIndex--;
            }
            #endregion

            #region Create new effect Type
            FFBEType EffectType = new FFBEType();
            if ((uint)ERROR.ERROR_SUCCESS == Joystick.Ffb_h_EffNew(data, ref EffectType))
            {
#if CONSOLE_DUMP
                if (EffectType2Str(EffectType, ref TypeStr))
                {
                    Console.WriteLine(" >> Effect Type: {0}", TypeStr);
                }
                else
                {
                    Console.WriteLine(" >> Effect Type: Unknown");
                }
#endif
            }

            #endregion

            #region Condition
            vJoy.FFB_EFF_COND Condition = new vJoy.FFB_EFF_COND();
            if ((uint)ERROR.ERROR_SUCCESS == Joystick.Ffb_h_Eff_Cond(data, ref Condition))
            {
#if CONSOLE_DUMP
                if (Condition.isY)
                {
                    Console.WriteLine(" >> Y Axis");
                }
                else
                {
                    Console.WriteLine(" >> X Axis");
                }
                Console.WriteLine(" >> Center Point Offset: {0}", TwosCompWord2Int(Condition.CenterPointOffset));
                Console.WriteLine(" >> Positive Coefficient: {0}", TwosCompWord2Int(Condition.PosCoeff));
                Console.WriteLine(" >> Negative Coefficient: {0}", TwosCompWord2Int(Condition.NegCoeff));
                Console.WriteLine(" >> Positive Saturation: {0}", Condition.PosSatur);
                Console.WriteLine(" >> Negative Saturation: {0}", Condition.NegSatur);
                Console.WriteLine(" >> Dead Band: {0}", Condition.DeadBand);
#endif
                // Skip all processing if Y axis (single axis for wheel FFB!)
                if (Condition.isY)
                {
                    // Leave early!
                    return;
                }

                FFBManager.SetLimitsParams(BlockIndex,
                                           TwosCompWord2Int(Condition.CenterPointOffset) * Scale_FFB_to_u,
                                           Condition.DeadBand * Scale_FFB_to_u,
                                           TwosCompWord2Int(Condition.PosCoeff) * Scale_FFB_to_u,
                                           TwosCompWord2Int(Condition.NegCoeff) * Scale_FFB_to_u,
                                           Condition.PosSatur * Scale_FFB_to_u,
                                           -Condition.NegSatur * Scale_FFB_to_u);
            }
            #endregion

            /////// Effect Report
            #region Effect Report
            vJoy.FFB_EFF_REPORT Effect = new vJoy.FFB_EFF_REPORT();
            if ((uint)ERROR.ERROR_SUCCESS == Joystick.Ffb_h_Eff_Report(data, ref Effect))
            {
#if CONSOLE_DUMP
                if (!EffectType2Str(Effect.EffectType, ref TypeStr))
                {
                    Console.WriteLine(" >> Effect Report: {0} {1}", (int)Effect.EffectType, Effect.EffectType.ToString());
                }
                else
                {
                    Console.WriteLine(" >> Effect Report: {0}", TypeStr);
                }
#endif
                if (Effect.Polar)
                {
#if CONSOLE_DUMP
                    Console.WriteLine(" >> Direction: {0} deg ({1})", Polar2Deg(Effect.Direction), Effect.Direction);
#endif
                    FFBManager.SetDirection(BlockIndex, Polar2Deg(Effect.Direction));
                }
                else
                {
#if CONSOLE_DUMP
                    Console.WriteLine(" >> X Direction: {0}", Effect.DirX);
                    Console.WriteLine(" >> Y Direction: {0}", Effect.DirY);
#endif
                    FFBManager.SetDirection(BlockIndex, Effect.DirX);
                }

#if CONSOLE_DUMP
                if (Effect.Duration == 0xFFFF)
                {
                    Console.WriteLine(" >> Duration: Infinit");
                }
                else
                {
                    Console.WriteLine(" >> Duration: {0} MilliSec", (int)(Effect.Duration));
                }

                if (Effect.TrigerRpt == 0xFFFF)
                {
                    Console.WriteLine(" >> Trigger Repeat: Infinit");
                }
                else
                {
                    Console.WriteLine(" >> Trigger Repeat: {0}", (int)(Effect.TrigerRpt));
                }

                if (Effect.SamplePrd == 0xFFFF)
                {
                    Console.WriteLine(" >> Sample Period: Infinit");
                }
                else
                {
                    Console.WriteLine(" >> Sample Period: {0}", (int)(Effect.SamplePrd));
                }


                Console.WriteLine(" >> Gain: {0}%%", Byte2Percent(Effect.Gain));
#endif
                if (Effect.Duration == 65535)
                {
                    FFBManager.SetDuration(BlockIndex, -1.0);
                }
                else
                {
                    FFBManager.SetDuration(BlockIndex, Effect.Duration);
                }

                FFBManager.SetEffectGain(BlockIndex, Byte2Percent(Effect.Gain) * 0.01);
                switch (Effect.EffectType)
                {
                case FFBEType.ET_CONST:
                    FFBManager.SetEffect(BlockIndex, AFFBManager.EffectTypes.CONSTANT_TORQUE);
                    break;

                case FFBEType.ET_RAMP:
                    FFBManager.SetEffect(BlockIndex, AFFBManager.EffectTypes.RAMP);
                    break;

                case FFBEType.ET_INRT:
                    FFBManager.SetEffect(BlockIndex, AFFBManager.EffectTypes.INERTIA);
                    break;

                case FFBEType.ET_SPRNG:
                    FFBManager.SetEffect(BlockIndex, AFFBManager.EffectTypes.SPRING);
                    break;

                case FFBEType.ET_DMPR:
                    FFBManager.SetEffect(BlockIndex, AFFBManager.EffectTypes.DAMPER);
                    break;

                case FFBEType.ET_FRCTN:
                    FFBManager.SetEffect(BlockIndex, AFFBManager.EffectTypes.FRICTION);
                    break;

                // Periodic
                case FFBEType.ET_SQR:
                    FFBManager.SetEffect(BlockIndex, AFFBManager.EffectTypes.SQUARE);
                    break;

                case FFBEType.ET_SINE:
                    FFBManager.SetEffect(BlockIndex, AFFBManager.EffectTypes.SINE);
                    break;

                case FFBEType.ET_TRNGL:
                    FFBManager.SetEffect(BlockIndex, AFFBManager.EffectTypes.TRIANGLE);
                    break;

                case FFBEType.ET_STUP:
                    FFBManager.SetEffect(BlockIndex, AFFBManager.EffectTypes.SAWTOOTHUP);
                    break;

                case FFBEType.ET_STDN:
                    FFBManager.SetEffect(BlockIndex, AFFBManager.EffectTypes.SAWTOOTHDOWN);
                    break;
                }
            }
            #endregion

            #region PID Device Control
            FFB_CTRL Control = new FFB_CTRL();
            string   CtrlStr = "";
            if ((uint)ERROR.ERROR_SUCCESS == Joystick.Ffb_h_DevCtrl(data, ref Control) && DevCtrl2Str(Control, ref CtrlStr))
            {
#if CONSOLE_DUMP
                Console.WriteLine(" >> PID Device Control: {0}", CtrlStr);
#endif
                switch (Control)
                {
                case FFB_CTRL.CTRL_DEVRST:
                    // device reset
                    FFBManager.DevReset();
                    break;

                case FFB_CTRL.CTRL_ENACT:
                    FFBManager.DevEnable();
                    break;

                case FFB_CTRL.CTRL_DISACT:
                    FFBManager.DevDisable();
                    break;
                }
            }

            #endregion

            #region Effect Operation
            vJoy.FFB_EFF_OP Operation = new vJoy.FFB_EFF_OP();
            string          EffOpStr  = "";
            if ((uint)ERROR.ERROR_SUCCESS == Joystick.Ffb_h_EffOp(data, ref Operation) && EffectOpStr(Operation.EffectOp, ref EffOpStr))
            {
#if CONSOLE_DUMP
                Console.WriteLine(" >> Effect Operation: {0}", EffOpStr);
                if (Operation.LoopCount == 0xFF)
                {
                    Console.WriteLine(" >> Loop until stopped");
                }
                else
                {
                    Console.WriteLine(" >> Loop {0} times", (int)(Operation.LoopCount));
                }
#endif

                switch (Operation.EffectOp)
                {
                case FFBOP.EFF_START:
                    // Start the effect identified by the Effect Handle.
                    FFBManager.StartEffect(BlockIndex, (int)(Operation.LoopCount));
                    break;

                case FFBOP.EFF_STOP:
                    // Stop the effect identified by the Effect Handle.
                    FFBManager.StopEffect(BlockIndex);
                    break;

                case FFBOP.EFF_SOLO:
                    // Start the effect identified by the Effect Handle and stop all other effects.
                    FFBManager.StartEffect(BlockIndex, 1);
                    break;
                }
            }
            #endregion

            #region Global Device Gain
            byte Gain = 0;
            if ((uint)ERROR.ERROR_SUCCESS == Joystick.Ffb_h_DevGain(data, ref Gain))
            {
#if CONSOLE_DUMP
                Console.WriteLine(" >> Global Device Gain: {0}", Byte2Percent(Gain));
#endif
                FFBManager.SetDeviceGain(Byte2Percent(Gain) * 0.01);
            }

            #endregion

            #region Envelope
            vJoy.FFB_EFF_ENVLP Envelope = new vJoy.FFB_EFF_ENVLP();
            if ((uint)ERROR.ERROR_SUCCESS == Joystick.Ffb_h_Eff_Envlp(data, ref Envelope))
            {
#if CONSOLE_DUMP
                Console.WriteLine(" >> Attack Level: {0}", Envelope.AttackLevel);
                Console.WriteLine(" >> Fade Level: {0}", Envelope.FadeLevel);
                Console.WriteLine(" >> Attack Time: {0}", (int)(Envelope.AttackTime));
                Console.WriteLine(" >> Fade Time: {0}", (int)(Envelope.FadeTime));
#endif
                FFBManager.SetEnveloppeParams(BlockIndex, Envelope.AttackTime, Envelope.AttackLevel, Envelope.FadeTime, Envelope.FadeLevel);
            }

            #endregion

            #region Periodic
            vJoy.FFB_EFF_PERIOD EffPrd = new vJoy.FFB_EFF_PERIOD();
            if ((uint)ERROR.ERROR_SUCCESS == Joystick.Ffb_h_Eff_Period(data, ref EffPrd))
            {
#if CONSOLE_DUMP
                Console.WriteLine(" >> Magnitude: {0}", EffPrd.Magnitude);
                Console.WriteLine(" >> Offset: {0}", TwosCompWord2Int(EffPrd.Offset));
                Console.WriteLine(" >> Phase: {0}", EffPrd.Phase * 3600 / 255);
                Console.WriteLine(" >> Period: {0}", (int)(EffPrd.Period));
#endif
                FFBManager.SetPeriodicParams(BlockIndex, (double)EffPrd.Magnitude * Scale_FFB_to_u, TwosCompWord2Int(EffPrd.Offset) * Scale_FFB_to_u, EffPrd.Phase * 0.01, EffPrd.Period);
            }
            #endregion


            #region Ramp Effect
            vJoy.FFB_EFF_RAMP RampEffect = new vJoy.FFB_EFF_RAMP();
            if ((uint)ERROR.ERROR_SUCCESS == Joystick.Ffb_h_Eff_Ramp(data, ref RampEffect))
            {
#if CONSOLE_DUMP
                Console.WriteLine(" >> Ramp Start: {0}", TwosCompWord2Int(RampEffect.Start));
                Console.WriteLine(" >> Ramp End: {0}", TwosCompWord2Int(RampEffect.End));
#endif
                FFBManager.SetRampParams(BlockIndex, RampEffect.Start * Scale_FFB_to_u, RampEffect.End * Scale_FFB_to_u);
            }

            #endregion

            #region Constant Effect
            vJoy.FFB_EFF_CONSTANT CstEffect = new vJoy.FFB_EFF_CONSTANT();
            if ((uint)ERROR.ERROR_SUCCESS == Joystick.Ffb_h_Eff_Constant(data, ref CstEffect))
            {
#if CONSOLE_DUMP
                Console.WriteLine(" >> Block Index: {0}", TwosCompWord2Int(CstEffect.EffectBlockIndex));
                Console.WriteLine(" >> Magnitude: {0}", TwosCompWord2Int(CstEffect.Magnitude));
#endif
                FFBManager.SetConstantTorqueEffect(BlockIndex, (double)CstEffect.Magnitude * Scale_FFB_to_u);
            }

            #endregion

#if DUMP_PACKET
            FfbFunction(data);
#endif
#if CONSOLE_DUMP
            Console.WriteLine("====================================================");
#endif
        }