Make EXI use CoreTiming events like everything else instead of having its own slow special check.

Microphone is probably wrong/mistimed because it doesn't take into
account cycles late, but that's not a new issue here.
This commit is contained in:
comex 2014-11-03 00:03:41 -05:00
parent 204598a082
commit 9f683f353b
9 changed files with 36 additions and 28 deletions

View File

@ -23,6 +23,10 @@ static int changeDevice;
static int updateInterrupts; static int updateInterrupts;
static CEXIChannel *g_Channels[MAX_EXI_CHANNELS]; static CEXIChannel *g_Channels[MAX_EXI_CHANNELS];
static void ChangeDeviceCallback(u64 userdata, int cyclesLate);
static void UpdateInterruptsCallback(u64 userdata, int cycles_late);
void Init() void Init()
{ {
InitSRAM(); InitSRAM();
@ -82,7 +86,7 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
} }
} }
void ChangeDeviceCallback(u64 userdata, int cyclesLate) static void ChangeDeviceCallback(u64 userdata, int cyclesLate)
{ {
u8 channel = (u8)(userdata >> 32); u8 channel = (u8)(userdata >> 32);
u8 type = (u8)(userdata >> 16); u8 type = (u8)(userdata >> 16);
@ -116,11 +120,6 @@ IEXIDevice* FindDevice(TEXIDevices device_type, int customIndex)
} }
void UpdateInterrupts() void UpdateInterrupts()
{
CoreTiming::ScheduleEvent_Threadsafe(0, updateInterrupts, 0);
}
void UpdateInterruptsCallback(u64 userdata, int cyclesLate)
{ {
// Interrupts are mapped a bit strangely: // Interrupts are mapped a bit strangely:
// Channel 0 Device 0 generates interrupt on channel 0 // Channel 0 Device 0 generates interrupt on channel 0
@ -135,4 +134,19 @@ void UpdateInterruptsCallback(u64 userdata, int cyclesLate)
ProcessorInterface::SetInterrupt(ProcessorInterface::INT_CAUSE_EXI, causeInt); ProcessorInterface::SetInterrupt(ProcessorInterface::INT_CAUSE_EXI, causeInt);
} }
static void UpdateInterruptsCallback(u64 userdata, int cycles_late)
{
UpdateInterrupts();
}
void ScheduleUpdateInterrupts_Threadsafe(int cycles_late)
{
CoreTiming::ScheduleEvent_Threadsafe(cycles_late, updateInterrupts, 0);
}
void ScheduleUpdateInterrupts(int cycles_late)
{
CoreTiming::ScheduleEvent(cycles_late, updateInterrupts, 0);
}
} // end of namespace ExpansionInterface } // end of namespace ExpansionInterface

View File

@ -27,10 +27,10 @@ void PauseAndLock(bool doLock, bool unpauseOnUnlock);
void RegisterMMIO(MMIO::Mapping* mmio, u32 base); void RegisterMMIO(MMIO::Mapping* mmio, u32 base);
void UpdateInterruptsCallback(u64 userdata, int cyclesLate);
void UpdateInterrupts(); void UpdateInterrupts();
void ScheduleUpdateInterrupts_Threadsafe(int cycles_late);
void ScheduleUpdateInterrupts(int cycles_late);
void ChangeDeviceCallback(u64 userdata, int cyclesLate);
void ChangeDevice(const u8 channel, const TEXIDevices device_type, const u8 device_num); void ChangeDevice(const u8 channel, const TEXIDevices device_type, const u8 device_num);
CEXIChannel* GetChannel(u32 index); CEXIChannel* GetChannel(u32 index);

View File

@ -35,8 +35,6 @@ CEXIChannel::CEXIChannel(u32 ChannelId) :
for (auto& device : m_pDevices) for (auto& device : m_pDevices)
device.reset(EXIDevice_Create(EXIDEVICE_NONE, m_ChannelId)); device.reset(EXIDevice_Create(EXIDEVICE_NONE, m_ChannelId));
updateInterrupts = CoreTiming::RegisterEvent("EXIInterrupt", UpdateInterrupts);
} }
CEXIChannel::~CEXIChannel() CEXIChannel::~CEXIChannel()
@ -93,7 +91,7 @@ void CEXIChannel::RegisterMMIO(MMIO::Mapping* mmio, u32 base)
if (pDevice != nullptr) if (pDevice != nullptr)
pDevice->SetCS(m_Status.CHIP_SELECT); pDevice->SetCS(m_Status.CHIP_SELECT);
CoreTiming::ScheduleEvent_Threadsafe_Immediate(updateInterrupts, 0); ExpansionInterface::UpdateInterrupts();
}) })
); );
@ -156,7 +154,7 @@ void CEXIChannel::RegisterMMIO(MMIO::Mapping* mmio, u32 base)
void CEXIChannel::SendTransferComplete() void CEXIChannel::SendTransferComplete()
{ {
m_Status.TCINT = 1; m_Status.TCINT = 1;
CoreTiming::ScheduleEvent_Threadsafe_Immediate(updateInterrupts, 0); ExpansionInterface::UpdateInterrupts();
} }
void CEXIChannel::RemoveDevices() void CEXIChannel::RemoveDevices()
@ -185,16 +183,11 @@ void CEXIChannel::AddDevice(IEXIDevice* pDevice, const int device_num, bool noti
if (m_ChannelId != 2) if (m_ChannelId != 2)
{ {
m_Status.EXTINT = 1; m_Status.EXTINT = 1;
CoreTiming::ScheduleEvent_Threadsafe_Immediate(updateInterrupts, 0); ExpansionInterface::UpdateInterrupts();
} }
} }
} }
void CEXIChannel::UpdateInterrupts(u64 userdata, int cyclesLate)
{
ExpansionInterface::UpdateInterrupts();
}
bool CEXIChannel::IsCausingInterrupt() bool CEXIChannel::IsCausingInterrupt()
{ {
if (m_ChannelId != 2 && GetDevice(1)->IsInterruptSet()) if (m_ChannelId != 2 && GetDevice(1)->IsInterruptSet())

View File

@ -83,10 +83,6 @@ private:
// Since channels operate a bit differently from each other // Since channels operate a bit differently from each other
u32 m_ChannelId; u32 m_ChannelId;
int updateInterrupts;
static void UpdateInterrupts(u64 userdata, int cyclesLate);
public: public:
// get device // get device
IEXIDevice* GetDevice(const u8 _CHIP_SELECT); IEXIDevice* GetDevice(const u8 _CHIP_SELECT);

View File

@ -4,6 +4,7 @@
#include "Core/Core.h" #include "Core/Core.h"
#include "Core/HW/EXI.h"
#include "Core/HW/EXI_Device.h" #include "Core/HW/EXI_Device.h"
#include "Core/HW/EXI_DeviceAMBaseboard.h" #include "Core/HW/EXI_DeviceAMBaseboard.h"
@ -87,6 +88,7 @@ void CEXIAMBaseboard::TransferByte(u8& _byte)
m_have_irq = true; m_have_irq = true;
else if (m_command[0] == 0x82) else if (m_command[0] == 0x82)
m_have_irq = false; m_have_irq = false;
ExpansionInterface::UpdateInterrupts();
} }
else if (m_position > 4) else if (m_position > 4)
{ {

View File

@ -4,6 +4,7 @@
#include "Common/Network.h" #include "Common/Network.h"
#include "Core/ConfigManager.h" #include "Core/ConfigManager.h"
#include "Core/HW/EXI.h"
#include "Core/HW/EXI_Device.h" #include "Core/HW/EXI_Device.h"
#include "Core/HW/EXI_DeviceEthernet.h" #include "Core/HW/EXI_DeviceEthernet.h"
#include "Core/HW/Memmap.h" #include "Core/HW/Memmap.h"
@ -123,6 +124,7 @@ void CEXIETHERNET::ImmWrite(u32 data, u32 size)
exi_status.interrupt_mask = data; exi_status.interrupt_mask = data;
break; break;
} }
ExpansionInterface::UpdateInterrupts();
} }
else else
{ {
@ -401,6 +403,7 @@ void CEXIETHERNET::SendComplete()
mBbaMem[BBA_IR] |= INT_T; mBbaMem[BBA_IR] |= INT_T;
exi_status.interrupt |= exi_status.TRANSFER; exi_status.interrupt |= exi_status.TRANSFER;
ExpansionInterface::ScheduleUpdateInterrupts_Threadsafe(0);
} }
mBbaMem[BBA_LTPS] = 0; mBbaMem[BBA_LTPS] = 0;
@ -571,6 +574,7 @@ bool CEXIETHERNET::RecvHandlePacket()
mBbaMem[BBA_IR] |= INT_R; mBbaMem[BBA_IR] |= INT_R;
exi_status.interrupt |= exi_status.TRANSFER; exi_status.interrupt |= exi_status.TRANSFER;
ExpansionInterface::ScheduleUpdateInterrupts_Threadsafe(0);
} }
else else
{ {

View File

@ -263,6 +263,7 @@ void CEXIMemoryCard::CmdDone()
status &= ~MC_STATUS_BUSY; status &= ~MC_STATUS_BUSY;
m_bInterruptSet = 1; m_bInterruptSet = 1;
ExpansionInterface::UpdateInterrupts();
} }
void CEXIMemoryCard::TransferComplete() void CEXIMemoryCard::TransferComplete()

View File

@ -7,6 +7,7 @@
#if HAVE_PORTAUDIO #if HAVE_PORTAUDIO
#include "Core/CoreTiming.h" #include "Core/CoreTiming.h"
#include "Core/HW/EXI.h"
#include "Core/HW/EXI_Device.h" #include "Core/HW/EXI_Device.h"
#include "Core/HW/EXI_DeviceMic.h" #include "Core/HW/EXI_DeviceMic.h"
#include "Core/HW/GCPad.h" #include "Core/HW/GCPad.h"
@ -176,8 +177,9 @@ void CEXIMic::SetCS(int cs)
void CEXIMic::UpdateNextInterruptTicks() void CEXIMic::UpdateNextInterruptTicks()
{ {
next_int_ticks = CoreTiming::GetTicks() + int diff = (SystemTimers::GetTicksPerSecond() / sample_rate) * buff_size_samples;
(SystemTimers::GetTicksPerSecond() / sample_rate) * buff_size_samples; next_int_ticks = CoreTiming::GetTicks() + diff;
ExpansionInterface::ScheduleUpdateInterrupts(diff);
} }
bool CEXIMic::IsInterruptSet() bool CEXIMic::IsInterruptSet()

View File

@ -303,10 +303,6 @@ void UpdatePerformanceMonitor(u32 cycles, u32 num_load_stores, u32 num_fp_inst)
void CheckExceptions() void CheckExceptions()
{ {
// Make sure we are checking against the latest EXI status. This is required
// for devices which interrupt frequently, such as the gc mic
ExpansionInterface::UpdateInterrupts();
// Read volatile data once // Read volatile data once
u32 exceptions = ppcState.Exceptions; u32 exceptions = ppcState.Exceptions;