#pragma once #include "common/bitfield.h" #include "common/fifo_queue.h" #include "types.h" #include #include class StateWrapper; class System; class InterruptController; class PadDevice; class Pad { public: Pad(); ~Pad(); bool Initialize(System* system, InterruptController* interrupt_controller); void Reset(); bool DoState(StateWrapper& sw); PadDevice* GetController(u32 slot) { return m_controllers[slot].get(); } void SetController(u32 slot, std::shared_ptr dev) { m_controllers[slot] = dev; } PadDevice* GetMemoryCard(u32 slot) { return m_memory_cards[slot].get(); } void SetMemoryCard(u32 slot, std::shared_ptr dev) { m_memory_cards[slot] = dev; } u32 ReadRegister(u32 offset); void WriteRegister(u32 offset, u32 value); void Execute(TickCount ticks); private: static constexpr u32 NUM_SLOTS = 2; enum class State : u32 { Idle, Transmitting }; enum class ActiveDevice : u8 { None, Controller, MemoryCard }; union JOY_CTRL { u16 bits; BitField TXEN; BitField SELECT; BitField RXEN; BitField ACK; BitField RESET; BitField RXIMODE; BitField TXINTEN; BitField RXINTEN; BitField ACKINTEN; BitField SLOT; }; union JOY_STAT { u32 bits; BitField TXRDY; BitField RXFIFONEMPTY; BitField TXDONE; BitField ACKINPUT; BitField INTR; BitField TMR; }; union JOY_MODE { u16 bits; BitField reload_factor; BitField character_length; BitField parity_enable; BitField parity_type; BitField clk_polarity; }; bool IsTransmitting() const { return m_state == State::Transmitting; } bool CanTransfer() const { return !m_TX_FIFO.IsEmpty() && !m_RX_FIFO.IsFull() && m_JOY_CTRL.SELECT && m_JOY_CTRL.TXEN; } TickCount GetTransferTicks() const { return static_cast(ZeroExtend32(m_JOY_BAUD) * 8); } void SoftReset(); void UpdateJoyStat(); void BeginTransfer(); void DoTransfer(); void EndTransfer(); void ResetDeviceTransferState(); System* m_system = nullptr; InterruptController* m_interrupt_controller = nullptr; State m_state = State::Idle; TickCount m_ticks_remaining = 0; JOY_CTRL m_JOY_CTRL = {}; JOY_STAT m_JOY_STAT = {}; JOY_MODE m_JOY_MODE = {}; u16 m_JOY_BAUD = 0; ActiveDevice m_active_device = ActiveDevice::None; InlineFIFOQueue m_RX_FIFO; InlineFIFOQueue m_TX_FIFO; std::array, NUM_SLOTS> m_controllers; std::array, NUM_SLOTS> m_memory_cards; };