Pad: Delay ACK after receiving byte
The controller routines in the BIOS seem to depend on this, if they happen at the same time depending on what part of the code it was in, it'll assume no controller is connected.
This commit is contained in:
parent
9fa8eb239e
commit
4798f35e40
|
@ -100,7 +100,7 @@ u32 Pad::ReadRegister(u32 offset)
|
||||||
{
|
{
|
||||||
case 0x00: // JOY_DATA
|
case 0x00: // JOY_DATA
|
||||||
{
|
{
|
||||||
if (!m_transmit_buffer_full)
|
if (!m_receive_buffer_full)
|
||||||
Log_DevPrintf("Read from RX fifo when empty");
|
Log_DevPrintf("Read from RX fifo when empty");
|
||||||
|
|
||||||
const u8 value = m_receive_buffer;
|
const u8 value = m_receive_buffer;
|
||||||
|
@ -209,21 +209,20 @@ void Pad::WriteRegister(u32 offset, u32 value)
|
||||||
|
|
||||||
void Pad::Execute(TickCount ticks)
|
void Pad::Execute(TickCount ticks)
|
||||||
{
|
{
|
||||||
switch (m_state)
|
if (m_state == State::Idle)
|
||||||
{
|
return;
|
||||||
case State::Idle:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case State::Transmitting:
|
m_ticks_remaining -= ticks;
|
||||||
{
|
if (m_ticks_remaining > 0)
|
||||||
m_ticks_remaining -= ticks;
|
{
|
||||||
if (m_ticks_remaining <= 0)
|
m_system->SetDowncount(m_ticks_remaining);
|
||||||
DoTransfer();
|
return;
|
||||||
else
|
|
||||||
m_system->SetDowncount(m_ticks_remaining);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_state == State::Transmitting)
|
||||||
|
DoTransfer();
|
||||||
|
else
|
||||||
|
DoACK();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Pad::SoftReset()
|
void Pad::SoftReset()
|
||||||
|
@ -344,26 +343,48 @@ void Pad::DoTransfer()
|
||||||
|
|
||||||
m_receive_buffer = data_in;
|
m_receive_buffer = data_in;
|
||||||
m_receive_buffer_full = true;
|
m_receive_buffer_full = true;
|
||||||
m_JOY_STAT.ACKINPUT |= ack;
|
|
||||||
|
|
||||||
// device no longer active?
|
// device no longer active?
|
||||||
if (!ack)
|
if (!ack)
|
||||||
m_active_device = ActiveDevice::None;
|
|
||||||
|
|
||||||
if (m_JOY_STAT.ACKINPUT && m_JOY_CTRL.ACKINTEN)
|
|
||||||
{
|
{
|
||||||
Log_DebugPrintf("Triggering interrupt");
|
m_active_device = ActiveDevice::None;
|
||||||
|
EndTransfer();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const TickCount ack_timer = GetACKTicks();
|
||||||
|
Log_DebugPrintf("Delaying ACK for %d ticks", ack_timer);
|
||||||
|
m_state = State::WaitingForACK;
|
||||||
|
m_ticks_remaining += ack_timer;
|
||||||
|
if (m_ticks_remaining <= 0)
|
||||||
|
DoACK();
|
||||||
|
else
|
||||||
|
m_system->SetDowncount(m_ticks_remaining);
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateJoyStat();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Pad::DoACK()
|
||||||
|
{
|
||||||
|
m_JOY_STAT.ACKINPUT = true;
|
||||||
|
|
||||||
|
if (m_JOY_CTRL.ACKINTEN)
|
||||||
|
{
|
||||||
|
Log_DebugPrintf("Triggering ACK interrupt");
|
||||||
m_JOY_STAT.INTR = true;
|
m_JOY_STAT.INTR = true;
|
||||||
m_interrupt_controller->InterruptRequest(InterruptController::IRQ::IRQ7);
|
m_interrupt_controller->InterruptRequest(InterruptController::IRQ::IRQ7);
|
||||||
}
|
}
|
||||||
|
|
||||||
EndTransfer();
|
EndTransfer();
|
||||||
UpdateJoyStat();
|
|
||||||
|
if (CanTransfer())
|
||||||
|
BeginTransfer();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Pad::EndTransfer()
|
void Pad::EndTransfer()
|
||||||
{
|
{
|
||||||
DebugAssert(m_state == State::Transmitting);
|
DebugAssert(m_state == State::Transmitting || m_state == State::WaitingForACK);
|
||||||
Log_DebugPrintf("Ending transfer");
|
Log_DebugPrintf("Ending transfer");
|
||||||
|
|
||||||
m_state = State::Idle;
|
m_state = State::Idle;
|
||||||
|
|
|
@ -39,7 +39,8 @@ private:
|
||||||
enum class State : u32
|
enum class State : u32
|
||||||
{
|
{
|
||||||
Idle,
|
Idle,
|
||||||
Transmitting
|
Transmitting,
|
||||||
|
WaitingForACK
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class ActiveDevice : u8
|
enum class ActiveDevice : u8
|
||||||
|
@ -88,15 +89,17 @@ private:
|
||||||
BitField<u16, u8, 8, 1> clk_polarity;
|
BitField<u16, u8, 8, 1> clk_polarity;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool IsTransmitting() const { return m_state == State::Transmitting; }
|
bool IsTransmitting() const { return m_state != State::Idle; }
|
||||||
bool CanTransfer() const { return m_transmit_buffer_full && m_JOY_CTRL.SELECT && m_JOY_CTRL.TXEN; }
|
bool CanTransfer() const { return m_transmit_buffer_full && m_JOY_CTRL.SELECT && m_JOY_CTRL.TXEN; }
|
||||||
|
|
||||||
TickCount GetTransferTicks() const { return static_cast<TickCount>(ZeroExtend32(m_JOY_BAUD) * 8); }
|
TickCount GetTransferTicks() const { return static_cast<TickCount>(ZeroExtend32(m_JOY_BAUD) * 8); }
|
||||||
|
TickCount GetACKTicks() const { return 32; }
|
||||||
|
|
||||||
void SoftReset();
|
void SoftReset();
|
||||||
void UpdateJoyStat();
|
void UpdateJoyStat();
|
||||||
void BeginTransfer();
|
void BeginTransfer();
|
||||||
void DoTransfer();
|
void DoTransfer();
|
||||||
|
void DoACK();
|
||||||
void EndTransfer();
|
void EndTransfer();
|
||||||
void ResetDeviceTransferState();
|
void ResetDeviceTransferState();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue