AnalogController: Rumble support

This commit is contained in:
Connor McLaughlin 2019-12-15 23:22:53 +10:00
parent 1d2bd11b02
commit cbcb9b02b0
4 changed files with 88 additions and 8 deletions

View file

@ -18,6 +18,7 @@ ControllerType AnalogController::GetType() const
void AnalogController::Reset()
{
m_analog_mode = false;
m_rumble_unlocked = false;
m_configuration_mode = false;
m_command_param = 0;
}
@ -28,9 +29,19 @@ bool AnalogController::DoState(StateWrapper& sw)
return false;
sw.Do(&m_analog_mode);
sw.Do(&m_rumble_unlocked);
sw.Do(&m_configuration_mode);
sw.Do(&m_command_param);
sw.Do(&m_state);
MotorState motor_state = m_motor_state;
sw.Do(&motor_state);
if (sw.IsReading())
{
for (u8 i = 0; i < NUM_MOTORS; i++)
SetMotorState(i, motor_state[i]);
}
return true;
}
@ -58,8 +69,6 @@ void AnalogController::SetAxisState(s32 axis_code, float value)
void AnalogController::SetAxisState(Axis axis, u8 value)
{
m_axis_state[static_cast<u8>(axis)] = value;
// TODO: Map to buttons in digital mode
}
void AnalogController::SetButtonState(Button button, bool pressed)
@ -78,6 +87,17 @@ void AnalogController::SetButtonState(s32 button_code, bool pressed)
SetButtonState(static_cast<Button>(button_code), pressed);
}
u32 AnalogController::GetVibrationMotorCount() const
{
return NUM_MOTORS;
}
float AnalogController::GetVibrationMotorStrength(u32 motor)
{
DebugAssert(motor < NUM_MOTORS);
return static_cast<float>(m_motor_state[motor]) * (1.0f / 255.0f);
}
void AnalogController::ResetTransferState()
{
m_state = State::Idle;
@ -95,6 +115,21 @@ u16 AnalogController::GetID() const
return m_analog_mode ? ANALOG_MODE_ID : DIGITAL_MODE_ID;
}
void AnalogController::SetAnalogMode(bool enabled)
{
if (m_analog_mode == enabled)
return;
Log_InfoPrintf("Controller switched to %s mode", enabled ? "analog" : "digital");
m_analog_mode = enabled;
}
void AnalogController::SetMotorState(u8 motor, u8 value)
{
DebugAssert(motor < NUM_MOTORS);
m_motor_state[motor] = value;
}
bool AnalogController::Transfer(const u8 data_in, u8* data_out)
{
bool ack;
@ -185,9 +220,29 @@ bool AnalogController::Transfer(const u8 data_in, u8* data_out)
break;
ID_STATE_MSB(State::GetStateIDMSB, State::GetStateButtonsLSB);
FIXED_REPLY_STATE(State::GetStateButtonsLSB, Truncate8(m_button_state), true, State::GetStateButtonsMSB);
FIXED_REPLY_STATE(State::GetStateButtonsMSB, Truncate8(m_button_state >> 8), m_analog_mode,
m_analog_mode ? State::GetStateRightAxisX : State::Idle);
case State::GetStateButtonsLSB:
{
if (m_rumble_unlocked)
SetMotorState(0, data_in);
*data_out = Truncate8(m_button_state);
m_state = State::GetStateButtonsMSB;
ack = true;
}
break;
case State::GetStateButtonsMSB:
{
if (m_rumble_unlocked)
SetMotorState(1, data_in);
*data_out = Truncate8(m_button_state >> 8);
m_state = m_analog_mode ? State::GetStateRightAxisX : State::Idle;
ack = m_analog_mode;
}
break;
FIXED_REPLY_STATE(State::GetStateRightAxisX, Truncate8(m_axis_state[static_cast<u8>(Axis::RightX)]), true,
State::GetStateRightAxisY);
FIXED_REPLY_STATE(State::GetStateRightAxisY, Truncate8(m_axis_state[static_cast<u8>(Axis::RightY)]), true,
@ -225,7 +280,7 @@ bool AnalogController::Transfer(const u8 data_in, u8* data_out)
{
Log_DebugPrintf("analog mode sel 0x%02x", data_in);
if (data_in != 0x00)
m_analog_mode = (m_command_param == 0x01);
SetAnalogMode(m_command_param == 0x01);
*data_out = 0x00;
m_state = State::Pad4Bytes;
@ -271,7 +326,7 @@ bool AnalogController::Transfer(const u8 data_in, u8* data_out)
case State::Command4CMode:
{
m_analog_mode = (data_in != 0x00);
SetAnalogMode(data_in != 0x00);
Log_DebugPrintf("analog mode %s by 0x4c", m_analog_mode ? "enabled" : "disabled");
*data_out = 0x00;
m_state = State::Command4C1;

View file

@ -38,6 +38,8 @@ public:
Count
};
static constexpr u8 NUM_MOTORS = 2;
AnalogController();
~AnalogController() override;
@ -61,7 +63,12 @@ public:
void SetAxisState(Axis axis, u8 value);
void SetButtonState(Button button, bool pressed);
u32 GetVibrationMotorCount() const override;
float GetVibrationMotorStrength(u32 motor) override;
private:
using MotorState = std::array<u8, NUM_MOTORS>;
enum class State : u8
{
Idle,
@ -115,6 +122,8 @@ private:
};
u16 GetID() const;
void SetAnalogMode(bool enabled);
void SetMotorState(u8 motor, u8 value);
bool m_analog_mode = false;
bool m_rumble_unlocked = false;
@ -126,7 +135,7 @@ private:
// buttons are active low
u16 m_button_state = UINT16_C(0xFFFF);
std::array<u8, 2> m_motor_state{};
MotorState m_motor_state{};
State m_state = State::Idle;
};

View file

@ -26,6 +26,16 @@ void Controller::SetAxisState(s32 axis_code, float value) {}
void Controller::SetButtonState(s32 button_code, bool pressed) {}
u32 Controller::GetVibrationMotorCount() const
{
return 0;
}
float Controller::GetVibrationMotorStrength(u32 motor)
{
return 0.0f;
}
std::unique_ptr<Controller> Controller::Create(ControllerType type)
{
switch (type)

View file

@ -36,6 +36,12 @@ public:
/// Changes the specified button state.
virtual void SetButtonState(s32 button_code, bool pressed);
/// Returns the number of vibration motors.
virtual u32 GetVibrationMotorCount() const;
/// Queries the state of the specified vibration motor. Values are normalized from 0..1.
virtual float GetVibrationMotorStrength(u32 motor);
/// Creates a new controller of the specified type.
static std::unique_ptr<Controller> Create(ControllerType type);