예제 #1
0
        public static VirtualFFBPacket ProcessFFBPacket(IntPtr data, object userData)
        {
            VirtualFFBPacket FFBPacket = new VirtualFFBPacket();

            if (joystick.Ffb_h_Type(data, ref FFBPacket._FFBPType) == ERROR_SUCCESS)
            {
                joystick.Ffb_h_DeviceID(data, ref FFBPacket.ID);
                switch (FFBPacket._FFBPType)
                {
                case FFBPType.PT_EFFREP:     // Effect Report (also named EFFECT_CONST)
                    if (joystick.Ffb_h_Eff_Report(data, ref FFBPacket.FFB_EFF_REPORT) == ERROR_SUCCESS)
                    {
                        FFBPacket.BlockIndex = FFBPacket.FFB_EFF_REPORT.EffectBlockIndex;
                        logger.Debug($"[{FFBPacket.ID}][EBI={FFBPacket.BlockIndex}] Effect Report");
                        logger.Trace(FFBPacket.GenerateEffectInfo());
                    }
                    break;

                case FFBPType.PT_ENVREP:     // Envelope Report
                    if (joystick.Ffb_h_Eff_Envlp(data, ref FFBPacket.FFB_EFF_ENVLP) == ERROR_SUCCESS)
                    {
                        FFBPacket.BlockIndex = (uint)FFBPacket.FFB_EFF_ENVLP.EffectBlockIndex;
                        logger.Debug($"[{FFBPacket.ID}][EBI={FFBPacket.BlockIndex}] Envelope Report");
                    }
                    break;

                case FFBPType.PT_CONDREP:     // Condition Report !!
                    if (joystick.Ffb_h_Eff_Cond(data, ref FFBPacket.FFB_EFF_COND) == ERROR_SUCCESS)
                    {
                        FFBPacket.BlockIndex = (uint)FFBPacket.FFB_EFF_COND.EffectBlockIndex;
                        logger.Debug($"[{FFBPacket.ID}][EBI={FFBPacket.BlockIndex}] Condition Report");
                        StringBuilder dat = new StringBuilder();
                        dat.AppendFormat($"[{FFBPacket.ID}][EBI={FFBPacket.BlockIndex}] Condition Report\n");
                        dat.AppendFormat($"\t EBI={FFBPacket.FFB_EFF_COND.EffectBlockIndex}\n");
                        dat.AppendFormat($"\t Center={FFBPacket.FFB_EFF_COND.CenterPointOffset}\n");
                        dat.AppendFormat($"\t DeadBand={FFBPacket.FFB_EFF_COND.DeadBand}\n");
                        dat.AppendFormat($"\t isY={FFBPacket.FFB_EFF_COND.isY}\n");
                        dat.AppendFormat($"\t NegCoeff={FFBPacket.FFB_EFF_COND.NegCoeff}\n");
                        dat.AppendFormat($"\t NegSatur={FFBPacket.FFB_EFF_COND.NegSatur}\n");
                        dat.AppendFormat($"\t PosCoeff={FFBPacket.FFB_EFF_COND.PosCoeff}\n");
                        dat.AppendFormat($"\t PosSatur={FFBPacket.FFB_EFF_COND.PosSatur}");
                        logger.Trace(dat);
                    }
                    break;

                case FFBPType.PT_PRIDREP:     // Periodic Report
                    if (joystick.Ffb_h_Eff_Period(data, ref FFBPacket.FFB_EFF_PERIOD) == ERROR_SUCCESS)
                    {
                        FFBPacket.BlockIndex = (uint)FFBPacket.FFB_EFF_PERIOD.EffectBlockIndex;
                        logger.Debug($"[{FFBPacket.ID}][EBI={FFBPacket.BlockIndex}] Periodic Report");
                        StringBuilder dat = new StringBuilder();
                        dat.AppendFormat($"[{FFBPacket.ID}][EBI={FFBPacket.BlockIndex}] Periodic Report\n");
                        dat.AppendFormat($"\t EBI={FFBPacket.FFB_EFF_PERIOD.EffectBlockIndex}\n");
                        dat.AppendFormat($"\t Magnitude={FFBPacket.FFB_EFF_PERIOD.Magnitude}\n");
                        dat.AppendFormat($"\t Offset={FFBPacket.FFB_EFF_PERIOD.Offset}\n");
                        dat.AppendFormat($"\t Period={FFBPacket.FFB_EFF_PERIOD.Period}\n");
                        dat.AppendFormat($"\t Phase={FFBPacket.FFB_EFF_PERIOD.Phase}");
                        logger.Trace(dat);
                    }
                    break;

                case FFBPType.PT_CONSTREP:     // Constant Force Report
                    if (joystick.Ffb_h_Eff_Constant(data, ref FFBPacket.FFB_EFF_CONSTANT) == ERROR_SUCCESS)
                    {
                        FFBPacket.BlockIndex = (uint)FFBPacket.FFB_EFF_CONSTANT.EffectBlockIndex;
                        logger.Debug($"[{FFBPacket.ID}][EBI={FFBPacket.BlockIndex}] Constant Force Report, magnitude={FFBPacket.FFB_EFF_CONSTANT.Magnitude}");
                    }
                    break;

                case FFBPType.PT_RAMPREP:     // Ramp Force Report
                    if (joystick.Ffb_h_Eff_Ramp(data, ref FFBPacket.FFB_EFF_RAMP) == ERROR_SUCCESS)
                    {
                        FFBPacket.BlockIndex = (uint)FFBPacket.FFB_EFF_RAMP.EffectBlockIndex;
                        logger.Debug($"[{FFBPacket.ID}][EBI={FFBPacket.BlockIndex}] Ramp Force Report");
                        StringBuilder dat = new StringBuilder();
                        dat.AppendFormat($"[{FFBPacket.ID}][EBI={FFBPacket.BlockIndex}] Ramp Force Report\n");
                        dat.AppendFormat($"\t EBI={FFBPacket.FFB_EFF_RAMP.EffectBlockIndex}\n");
                        dat.AppendFormat($"\t Start={FFBPacket.FFB_EFF_RAMP.Start}\n");
                        dat.AppendFormat($"\t End={FFBPacket.FFB_EFF_RAMP.End}\n");
                        logger.Trace(dat);
                    }
                    break;

                case FFBPType.PT_CSTMREP:     // Custom Force Data Report
                    logger.Debug($"Custom Force Data Report");
                    break;

                case FFBPType.PT_SMPLREP:     // Download Force Sample
                    joystick.Ffb_h_EBI(data, ref FFBPacket.BlockIndex);
                    logger.Debug($"[{FFBPacket.ID}][EBI={FFBPacket.BlockIndex}] Download Force Sample");
                    break;

                case FFBPType.PT_EFOPREP:     // Effect Operation Report
                    if (joystick.Ffb_h_EffOp(data, ref FFBPacket.FFB_EFF_OP) == ERROR_SUCCESS)
                    {
                        FFBPacket.BlockIndex = (uint)FFBPacket.FFB_EFF_OP.EffectBlockIndex;
                        logger.Trace($"[{FFBPacket.ID}][EBI={FFBPacket.BlockIndex}] Effect Operation Report loop={FFBPacket.FFB_EFF_OP.LoopCount} action={FFBPacket.FFB_EFF_OP.EffectOp}");
                    }
                    break;

                case FFBPType.PT_BLKFRREP:     // PID Block Free Report
                    joystick.Ffb_h_EBI(data, ref FFBPacket.BlockIndex);
                    logger.Debug($"[{FFBPacket.ID}][EBI={FFBPacket.BlockIndex}] PID Block Free Report");
                    break;

                case FFBPType.PT_CTRLREP:     // PID Device Control
                    joystick.Ffb_h_DevCtrl(data, ref FFBPacket.FFB_CTRL);
                    logger.Debug($"[{FFBPacket.ID}][_] PID Device Control {FFBPacket.FFB_CTRL}");
                    break;

                case FFBPType.PT_GAINREP:     // Device Gain Report
                    joystick.Ffb_h_DevGain(data, ref FFBPacket.Gain);
                    logger.Debug($"[{FFBPacket.ID}][_] Device Gain Report={FFBPacket.Gain}");
                    break;

                case FFBPType.PT_SETCREP:     // Set Custom Force Report
                    joystick.Ffb_h_EBI(data, ref FFBPacket.BlockIndex);
                    logger.Debug($"[{FFBPacket.ID}][EBI={FFBPacket.BlockIndex}] Set Custom Force Report");
                    break;

                case FFBPType.PT_NEWEFREP:     // Create New Effect Report !!
                    joystick.Ffb_h_EBI(data, ref FFBPacket.BlockIndex);
                    joystick.Ffb_h_CreateNewEffect(data, ref FFBPacket.FFBENextType, ref FFBPacket.NextBlockIndex);
                    logger.Debug($"[{FFBPacket.ID}][EBI={FFBPacket.BlockIndex}] Create New Effect Report, next={FFBPacket.FFBENextType}[nextEBI={FFBPacket.NextBlockIndex}]");
                    break;

                case FFBPType.PT_BLKLDREP:     // Block Load Report
                    joystick.Ffb_h_EBI(data, ref FFBPacket.BlockIndex);
                    logger.Debug($"[{FFBPacket.ID}][EBI={FFBPacket.BlockIndex}] Block Load Report");
                    break;

                case FFBPType.PT_POOLREP:     // PID Pool Report
                    joystick.Ffb_h_EBI(data, ref FFBPacket.BlockIndex);
                    logger.Debug($"[{FFBPacket.ID}][EBI={FFBPacket.BlockIndex}] PID Pool Report");
                    break;
                }
                // FFBDataReceived?.Invoke(FFBPacket);
                return(FFBPacket);
            }
            return(null);
        }
예제 #2
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
        }
예제 #3
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("======================================");
        }