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:
parent
204598a082
commit
9f683f353b
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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,14 +183,9 @@ 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CEXIChannel::UpdateInterrupts(u64 userdata, int cyclesLate)
|
|
||||||
{
|
|
||||||
ExpansionInterface::UpdateInterrupts();
|
ExpansionInterface::UpdateInterrupts();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CEXIChannel::IsCausingInterrupt()
|
bool CEXIChannel::IsCausingInterrupt()
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue