Refactoring finished; AVE working again

This commit is contained in:
Pokechu22 2022-09-06 14:00:21 -07:00
parent 5893ea9660
commit c553cd5dbf
3 changed files with 142 additions and 82 deletions

View file

@ -295,8 +295,6 @@ void I2CBus::SCLRisingEdge(const bool sda)
{
current_byte = byte.value();
}
// INFO_LOG_FMT(WII_IPC, "AVE: Read from {:02x} ({}) -> {:02x}", device_address.value(),
// IOS::GetAVERegisterName(device_address.value()), current_byte);
}
// Dolphin_Debugger::PrintCallstack(Common::Log::LogType::WII_IPC, Common::Log::LogLevel::LINFO);
}
@ -508,6 +506,8 @@ void I2CSlaveAutoIncrementing::DoState(PointerWrap& p)
}
p.Do(m_active);
p.Do(m_device_address);
DoDeviceState(p);
}
}; // namespace Common

View file

@ -26,9 +26,28 @@ public:
// transmitting device to NACK a read; only the receiver can NACK.
virtual std::optional<u8> ReadByte() = 0;
virtual bool WriteByte(u8 value) = 0;
protected:
template <typename T>
static u8 RawRead(T* reg_data, u8 addr)
{
static_assert(std::is_standard_layout_v<T> && std::is_trivially_copyable_v<T>);
static_assert(0x100 == sizeof(T));
return reinterpret_cast<u8*>(reg_data)[addr];
}
template <typename T>
static void RawWrite(T* reg_data, u8 addr, u8 value)
{
static_assert(std::is_standard_layout_v<T> && std::is_trivially_copyable_v<T>);
static_assert(0x100 == sizeof(T));
reinterpret_cast<u8*>(reg_data)[addr] = value;
}
};
class I2CSlaveAutoIncrementing : I2CSlave
class I2CSlaveAutoIncrementing : public I2CSlave
{
public:
I2CSlaveAutoIncrementing(u8 slave_addr) : m_slave_addr(slave_addr) {}
@ -40,12 +59,14 @@ public:
std::optional<u8> ReadByte() override;
bool WriteByte(u8 value) override;
virtual void DoState(PointerWrap& p);
void DoState(PointerWrap& p);
protected:
virtual u8 ReadByte(u8 addr) = 0;
virtual void WriteByte(u8 addr, u8 value) = 0;
virtual void DoDeviceState(PointerWrap& p) = 0;
private:
const u8 m_slave_addr;
bool m_active = false;

View file

@ -120,84 +120,6 @@ struct AVEState
};
#pragma pack()
static_assert(sizeof(AVEState) == 0x100);
Common::I2CSlaveSimple<0x70, AVEState> ave_state;
std::bitset<sizeof(AVEState)> ave_ever_logged;
Common::I2CBus i2c_state;
static CoreTiming::EventType* updateInterrupts;
WiiIPC::WiiIPC(Core::System& system) : m_system(system)
{
}
WiiIPC::~WiiIPC() = default;
void WiiIPC::DoState(PointerWrap& p)
{
p.Do(m_ppc_msg);
p.Do(m_arm_msg);
p.Do(m_ctrl);
p.Do(m_ppc_irq_flags);
p.Do(m_ppc_irq_masks);
p.Do(m_arm_irq_flags);
p.Do(m_arm_irq_masks);
p.Do(m_gpio_dir);
p.Do(m_gpio_out);
i2c_state.DoState(p);
p.Do(ave_state.data);
p.Do(m_resets);
}
void WiiIPC::InitState()
{
m_ctrl = CtrlRegister();
m_ppc_msg = 0;
m_arm_msg = 0;
m_ppc_irq_flags = 0;
m_ppc_irq_masks = 0;
m_arm_irq_flags = 0;
m_arm_irq_masks = 0;
// The only inputs are POWER, EJECT_BTN, SLOT_IN, EEP_MISO, and sometimes AVE_SCL and AVE_SDA;
// Broadway only has access to SLOT_IN, AVE_SCL, and AVE_SDA.
m_gpio_dir = {
GPIO::POWER, GPIO::SHUTDOWN, GPIO::FAN, GPIO::DC_DC, GPIO::DI_SPIN, GPIO::SLOT_LED,
GPIO::SENSOR_BAR, GPIO::DO_EJECT, GPIO::EEP_CS, GPIO::EEP_CLK, GPIO::EEP_MOSI, GPIO::AVE_SCL,
GPIO::AVE_SDA, GPIO::DEBUG0, GPIO::DEBUG1, GPIO::DEBUG2, GPIO::DEBUG3, GPIO::DEBUG4,
GPIO::DEBUG5, GPIO::DEBUG6, GPIO::DEBUG7,
};
m_gpio_out = {};
// A cleared bit indicates the device is reset/off, so set everything to 1 (this may not exactly
// match hardware)
m_resets = 0xffffffff;
m_ppc_irq_masks |= INT_CAUSE_IPC_BROADWAY;
i2c_state = {};
ave_state = {};
ave_state.data.video_output_config = 0x23;
ave_ever_logged.reset();
}
void WiiIPC::Init()
{
InitState();
m_event_type_update_interrupts =
m_system.GetCoreTiming().RegisterEvent("IPCInterrupt", UpdateInterruptsCallback);
}
void WiiIPC::Reset()
{
INFO_LOG_FMT(WII_IPC, "Resetting ...");
InitState();
}
void WiiIPC::Shutdown()
{
}
std::string_view GetAVERegisterName(u8 address)
{
@ -243,6 +165,123 @@ std::string_view GetAVERegisterName(u8 address)
return fmt::format("Unknown ({:02x})", address);
}
class AVEDevice : public Common::I2CSlaveAutoIncrementing
{
public:
AVEDevice() : I2CSlaveAutoIncrementing(0x70) {}
void Reset()
{
m_registers = {};
ave_ever_logged = {};
}
AVEState m_registers{};
protected:
u8 ReadByte(u8 addr) override
{
const u8 result = RawRead(&m_registers, addr);
INFO_LOG_FMT(WII_IPC, "AVE: Read from {:02x} ({}) -> {:02x}", addr, GetAVERegisterName(addr),
result);
return result;
}
void WriteByte(u8 addr, u8 value) override
{
const u8 old_value = RawRead(&m_registers, addr);
RawWrite(&m_registers, addr, value);
if (old_value != value || !ave_ever_logged[addr])
{
INFO_LOG_FMT(WII_IPC, "AVE: Write to {:02x} ({}): {:02x} -> {:02x}", addr,
GetAVERegisterName(addr), old_value, value);
ave_ever_logged[addr] = true;
}
else
{
DEBUG_LOG_FMT(WII_IPC, "AVE: Write to {:02x} ({}): {:02x}", addr, GetAVERegisterName(addr),
value);
}
}
void DoDeviceState(PointerWrap& p) override { p.Do(m_registers); }
private:
std::bitset<sizeof(AVEState)> ave_ever_logged{}; // logging only, not saved
};
AVEDevice ave_state;
Common::I2CBus i2c_state;
WiiIPC::WiiIPC(Core::System& system) : m_system(system)
{
}
WiiIPC::~WiiIPC() = default;
void WiiIPC::DoState(PointerWrap& p)
{
p.Do(m_ppc_msg);
p.Do(m_arm_msg);
p.Do(m_ctrl);
p.Do(m_ppc_irq_flags);
p.Do(m_ppc_irq_masks);
p.Do(m_arm_irq_flags);
p.Do(m_arm_irq_masks);
p.Do(m_gpio_dir);
p.Do(m_gpio_out);
i2c_state.DoState(p);
ave_state.DoState(p);
p.Do(m_resets);
}
void WiiIPC::InitState()
{
m_ctrl = CtrlRegister();
m_ppc_msg = 0;
m_arm_msg = 0;
m_ppc_irq_flags = 0;
m_ppc_irq_masks = 0;
m_arm_irq_flags = 0;
m_arm_irq_masks = 0;
// The only inputs are POWER, EJECT_BTN, SLOT_IN, EEP_MISO, and sometimes AVE_SCL and AVE_SDA;
// Broadway only has access to SLOT_IN, AVE_SCL, and AVE_SDA.
m_gpio_dir = {
GPIO::POWER, GPIO::SHUTDOWN, GPIO::FAN, GPIO::DC_DC, GPIO::DI_SPIN, GPIO::SLOT_LED,
GPIO::SENSOR_BAR, GPIO::DO_EJECT, GPIO::EEP_CS, GPIO::EEP_CLK, GPIO::EEP_MOSI, GPIO::AVE_SCL,
GPIO::AVE_SDA, GPIO::DEBUG0, GPIO::DEBUG1, GPIO::DEBUG2, GPIO::DEBUG3, GPIO::DEBUG4,
GPIO::DEBUG5, GPIO::DEBUG6, GPIO::DEBUG7,
};
m_gpio_out = {};
// A cleared bit indicates the device is reset/off, so set everything to 1 (this may not exactly
// match hardware)
m_resets = 0xffffffff;
m_ppc_irq_masks |= INT_CAUSE_IPC_BROADWAY;
i2c_state = {};
ave_state.Reset();
}
void WiiIPC::Init()
{
InitState();
m_event_type_update_interrupts =
m_system.GetCoreTiming().RegisterEvent("IPCInterrupt", UpdateInterruptsCallback);
}
void WiiIPC::Reset()
{
INFO_LOG_FMT(WII_IPC, "Resetting ...");
InitState();
}
void WiiIPC::Shutdown()
{
}
static u32 ReadGPIOIn(Core::System& system)
{
Common::Flags<GPIO> gpio_in;