#include "AdeptHeaders.hpp" #include "Joystick.hpp" //############################################################################ //############################### Input Filters ############################## //############################################################################ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Construct a Unipolar input filter // UnipolarFilter::UnipolarFilter( Scalar minimum, Scalar maximum, Scalar dead_band, Direction direction, LimitType limit_type ): inputAverage(5,0.0f) { positiveDirection = direction; Calibrate(minimum, maximum, dead_band); limitType = limit_type; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // UnipolarFilter::~UnipolarFilter() { Check_Object(this); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Scalar UnipolarFilter::Update(Scalar value) { Check_Object(this); // //------------------------------------------------ // Generate average, use for min/max determination //------------------------------------------------ // switch (limitType) { case PanningLimits: { inputAverage.Add(value); Scalar average = inputAverage.CalculateOlympicAverage(); if (average < inputMin) { inputMax -= inputMin - average; inputMin = average; } else if (average > inputMax) { inputMin += average - inputMax; inputMax = average; } } break; case FloatingLimits: { inputAverage.Add(value); Scalar average = inputAverage.CalculateOlympicAverage(); if (average < inputMin) { Calibrate(average, inputMax, deadBand); } else if (average > inputMax) { Calibrate(inputMin, average, deadBand); } } break; } // //------------------------------------------------------------------------- // In the case of a unipolar filter, subtract out the minimum value and the // deadband, the scale the remainder base on the range //------------------------------------------------------------------------- // Scalar result = 0.0f; value -= inputMin + lowerDeadband; if (value>0 && lowerRange>0) { if (value > lowerRange) { result = 1.0f; } else { result = static_cast(value)/lowerRange; Verify(result >= 0.0f && result <= 1.0f); } } if (positiveDirection == DecreasingPositive) { result = 1.0f - result; } return result; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Recalibrates the filter // void UnipolarFilter::Calibrate( Scalar minimum, Scalar maximum, Scalar dead_band ) { Check_Object(this); Verify(dead_band >= 0.0f); Verify(maximum >= minimum); deadBand = dead_band; inputMin = minimum; inputMax = maximum; lowerDeadband = (inputMax-inputMin)*deadBand + 0.5f; lowerRange = (inputMax-lowerDeadband) - (inputMin+lowerDeadband); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void UnipolarFilter::BeginAlignment() { Check_Object(this); Scalar average = inputAverage.CalculateAverage(); Calibrate(average, average, deadBand); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void UnipolarFilter::EndAlignment() { Check_Object(this); // //---------------------------------------------------------- // Move the edges of the filter ranges back by three percent //---------------------------------------------------------- // Scalar delta = (inputMax - inputMin) * 0.03f; inputMax -= delta; inputMin += delta; Calibrate(inputMin, inputMax, deadBand); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void UnipolarFilter::SetDeadBand(Scalar percent) { Check_Object(this); Calibrate(inputMin, inputMax, percent); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Construct a Bipolar input filter // BipolarFilter::BipolarFilter( Scalar minimum, Scalar center, Scalar maximum, Scalar dead_band, Direction direction, LimitType limit_type ): UnipolarFilter(minimum, maximum, dead_band, direction, limit_type) { Verify(limit_type != PanningLimits); Calibrate(minimum, center, maximum, dead_band); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // BipolarFilter::~BipolarFilter() { Check_Object(this); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Scalar BipolarFilter::Update(Scalar value) { Check_Object(this); // //------------------------------------------------ // Generate average, use for min/max determination //------------------------------------------------ // switch (limitType) { case FloatingLimits: { inputAverage.Add(value); Scalar average = inputAverage.CalculateOlympicAverage(); if (average < inputMin) { Calibrate(average, inputCenter, inputMax, deadBand); } else if (average > inputMax) { Calibrate(inputMin, inputCenter, average, deadBand); } } break; } // //----------------------------------------------------------- // Figure out which half of the input we will be dealing with //----------------------------------------------------------- // Scalar result = 0.0f; value -= inputCenter; // //------------------------------------------------------------------ // If we are in the lower half of the input and beyond the deadband, // scale the input against the lower half range //------------------------------------------------------------------ // if (value < 0) { value += lowerDeadband; if (value<0 && lowerRange>=0) { if (value <= -lowerRange) { result = -1.0f; } else { result = value/lowerRange; Verify(result >= -1.0f && result < 0.0f); } } } // //-------------------------------------------------------------------- // Otherwise, we are in the upper half of the input. If we are beyond // the deadband, scale the input against the upper half range //-------------------------------------------------------------------- // else { value -= upperDeadband; if (value>0 && upperRange>=0) { if (value >= upperRange) { result = 1.0f; } else { result = value/upperRange; Verify(result >= 0.0f && result <= 1.0f); } } } if (positiveDirection == DecreasingPositive) { result = -result; } return result; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Recalibrates the filter // void BipolarFilter::Calibrate( Scalar minimum, Scalar center, Scalar maximum, Scalar dead_band ) { Check_Object(this); Verify(dead_band >= 0.0f); Verify(minimum <= maximum); Verify(center >= minimum); Verify(center <= maximum); deadBand = dead_band; inputMin = minimum; inputCenter = center; inputMax = maximum; lowerDeadband = (inputCenter-inputMin)*deadBand; lowerRange = center - (inputMin+lowerDeadband); upperDeadband = (inputMax-inputCenter)*deadBand; upperRange = (inputMax-upperDeadband) - inputCenter; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void BipolarFilter::BeginAlignment() { Check_Object(this); Scalar average = inputAverage.CalculateAverage(); Calibrate(average, average, average, deadBand); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void BipolarFilter::EndAlignment() { Check_Object(this); // //--------------------------------------------------------------------- // Calculate the new center point by the current joystick average, then // move the edges of the joystick ranges back by three percent //--------------------------------------------------------------------- // Scalar average = inputAverage.CalculateAverage(); inputMax -= (inputMax - average) * 0.03f; inputMin += (average - inputMin) * 0.03f; Calibrate(inputMin, average, inputMax, deadBand); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void BipolarFilter::SetDeadBand(Scalar percent) { Check_Object(this); Calibrate(inputMin, inputCenter, inputMax, percent); } //########################################################################### //############################ Joystick classes ############################# //########################################################################### //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Joystick::Joystick( DWORD stick_id, Scalar x_dead_band, Scalar y_dead_band, Scalar throttle_dead_band, Scalar rudder_dead_band ) { Check_Pointer(this); buttonCount = CalculateButtonCount(stick_id); joystickID = stick_id; m_ShiftButton = -1; // //-------------------------------- // Initialize the member variables //-------------------------------- // hatValue = -1.0f; lastHatValue = -1.0f; hatStatus = NoHat; // //------------------------------ // Build the filterpointer array //------------------------------ // memset(axisValues,0,sizeof(axisValues)); memset(axisFilters,0,sizeof(axisFilters)); // //--------------------------------------------------- // Set up the filters for X and Y, which we will have //--------------------------------------------------- // gosJoystick_Info ji; gosJoystick_GetInfo(stick_id, &ji); m_ForceFeedback = ji.bIsForceFeedback; Verify(ji.bAxisValid & (1< 0) { hatStatus = HasAHat; } // //------------------------ // Add the throttle device //------------------------ // if (ji.bAxisValid & (1<(12); //ELEMENTS(ji.bAxisValid)); } // //---------------------- // Add the rudder device //---------------------- // if (ji.bAxisValid & (1<(12); //ELEMENTS(ji.bAxisValid)); } // //------------------------------- // Read the initial button states //------------------------------- // buttonValues = new bool[buttonCount]; Register_Pointer(buttonValues); for (DWORD i=0; i(axis) < AxisCount); Check_Object(axisFilters[axis]); axisValues[axis] = axisFilters[axis]->Update(value); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Joystick::AdoptFilter( int axis, UnipolarFilter *filter ) { Check_Object(this); Verify(static_cast(axis) < AxisCount); Register_Object(filter); axisFilters[axis] = filter; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Joystick::SetDeadBand(Scalar percent) { Check_Object(this); for (int i=0; iSetDeadBand(percent); } } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Joystick::SetXDeadBand(Scalar percent) { Check_Object(this); if (axisFilters[XAxis]) { Check_Object(axisFilters[XAxis]); axisFilters[XAxis]->SetDeadBand(percent); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Joystick::SetYDeadBand(Scalar percent) { Check_Object(this); if (axisFilters[YAxis]) { Check_Object(axisFilters[YAxis]); axisFilters[YAxis]->SetDeadBand(percent); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Joystick::SetThrottleDeadBand(Scalar percent) { Check_Object(this); if (axisFilters[ThrottleAxis]) { Check_Object(axisFilters[ThrottleAxis]); axisFilters[ThrottleAxis]->SetDeadBand(percent); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Joystick::SetRudderDeadBand(Scalar percent) { Check_Object(this); if (axisFilters[RudderAxis]) { Check_Object(axisFilters[RudderAxis]); axisFilters[RudderAxis]->SetDeadBand(percent); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Joystick::Update( int mode_mask, ControlsUpdateManagerOf *joystick_axis_group, ControlsUpdateManagerOf *joystick_button_group, ControlsUpdateManagerOf *joystick_hat ) { Check_Object(this); Check_Pointer(joystick_axis_group); Check_Pointer(joystick_button_group); // //---------------------------------- // First update the joystick buttons //---------------------------------- // Check_Pointer(buttonValues); for (DWORD i=0; i(joystickXInput) <= JOY_SLIDER2); FilterInput(XAxis, gosJoystick_GetAxis(joystickID, joystickXInput)); Check_Object(&joystick_axis_group[XAxis]); joystick_axis_group[XAxis].Update(&axisValues[XAxis], 1); Verify(static_cast(joystickYInput) <= JOY_SLIDER2); FilterInput(YAxis, gosJoystick_GetAxis(joystickID, joystickYInput)); Check_Object(&joystick_axis_group[YAxis]); joystick_axis_group[YAxis].Update(&axisValues[YAxis], 1); // //------------------ // Read the throttle //------------------ // if (static_cast(throttleInput) <= JOY_SLIDER2) { FilterInput( ThrottleAxis, gosJoystick_GetAxis(joystickID, throttleInput) ); Check_Object(&joystick_axis_group[ThrottleAxis]); joystick_axis_group[ThrottleAxis].Update( &axisValues[ThrottleAxis], 1 ); } // //---------------- // Read the rudder //---------------- // if (static_cast(rudderInput) <= JOY_SLIDER2) { FilterInput( RudderAxis, gosJoystick_GetAxis(joystickID, rudderInput) ); Check_Object(&joystick_axis_group[RudderAxis]); joystick_axis_group[RudderAxis].Update( &axisValues[RudderAxis], 1 ); } // //---------------------- // Read the joystick hat //---------------------- // if (HasHat()) { axisValues[HatAxis] = gosJoystick_GetAxis(joystickID, JOY_HAT1); Check_Object(&joystick_axis_group[HatAxis]); joystick_axis_group[HatAxis].Update( &axisValues[HatAxis], 1 ); hatValue = axisValues[HatAxis]; if (hatValue != lastHatValue) { Check_Object(joystick_hat); int temp = 1; if (hatValue == -1.0f) {} // Left down else if ((hatValue>= 0.625f) && (hatValue <= 0.875f)) joystick_hat[0].Update(&temp, 1); // Right down else if ((hatValue>= 0.125f) && (hatValue <= 0.375f)) joystick_hat[1].Update(&temp, 1); // Bottom down else if ((hatValue> 0.375f) && (hatValue < 0.625f)) joystick_hat[3].Update(&temp, 1); // Top down else if ((hatValue > 0.875f) || (hatValue < 0.125f)) joystick_hat[2].Update(&temp, 1); temp = 0; if (lastHatValue == -1.0f) {} // Left up else if ((lastHatValue>= 0.625f) && (lastHatValue <= 0.875f)) joystick_hat[0].Update(&temp, 1); // Right up else if ((lastHatValue>= 0.125f) && (lastHatValue <= 0.375f)) joystick_hat[1].Update(&temp, 1); // Bottom up else if ((lastHatValue> 0.375f) && (lastHatValue < 0.625f)) joystick_hat[3].Update(&temp, 1); // Top up else if ((lastHatValue > 0.875f) || (lastHatValue < 0.125f)) joystick_hat[2].Update(&temp, 1); lastHatValue = hatValue; } } else { hatValue = -1.0f; } #if 0 // //--------------------------------------------------- // Check to see which button values have been pressed //--------------------------------------------------- // int state = buttonsPressed; int button; for (i=0; state; ++i, state>>=1) { if (state&1) { button = ControlsManager::JoystickButtonIDBase + i; Check_Pointer(joystick_button_group); Check_Object(&joystick_button_group[i]); joystick_button_group[i].Update(&button, mode_mask); } } // //---------------------------------------------------- // Check to see which button values have been released //---------------------------------------------------- // state = buttonsReleased; for (i=0; state; ++i, state>>=1) { if (state&1) { button = -ControlsManager::JoystickButtonIDBase - i; Check_Pointer(joystick_button_group); Check_Object(&joystick_button_group[i]); joystick_button_group[i].Update(&button, mode_mask); } } #endif } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // int Joystick::CalculateButtonCount(DWORD stick_id) { gosJoystick_Info ji; gosJoystick_GetInfo(stick_id, &ji); return ji.nButtons; } bool Joystick::ShiftButton (void) { if (m_ShiftButton == -1) return false; if (buttonCount <= m_ShiftButton) return false; return gosJoystick_ButtonStatus(joystickID, m_ShiftButton); }