// license:BSD-3-Clause // copyright-holders:Ryan Holtz #ifndef MAME_MACHINE_SPG2XX_IO_H #define MAME_MACHINE_SPG2XX_IO_H #pragma once #include "cpu/unsp/unsp.h" #include "screen.h" class spg2xx_io_device : public device_t { public: spg2xx_io_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); auto porta_out() { return m_porta_out.bind(); } auto portb_out() { return m_portb_out.bind(); } auto portc_out() { return m_portc_out.bind(); } auto porta_in() { return m_porta_in.bind(); } auto portb_in() { return m_portb_in.bind(); } auto portc_in() { return m_portc_in.bind(); } template auto adc_in() { return m_adc_in[Line].bind(); } auto i2c_w() { return m_i2c_w.bind(); } auto i2c_r() { return m_i2c_r.bind(); } auto uart_tx() { return m_uart_tx.bind(); } auto spi_tx() { return m_spi_tx.bind(); } auto chip_select() { return m_chip_sel.bind(); } void uart_rx(uint8_t data); void spi_rx(int state); void extint_w(int channel, bool state); uint16_t io_r(offs_t offset); void io_w(offs_t offset, uint16_t data); virtual uint16_t io_extended_r(offs_t offset); virtual void io_extended_w(offs_t offset, uint16_t data); auto pal_read_callback() { return m_pal_read_cb.bind(); }; auto write_timer_irq_callback() { return m_timer_irq_cb.bind(); }; auto write_uart_adc_irq_callback() { return m_uart_adc_irq_cb.bind(); }; auto write_external_irq_callback() { return m_external_irq_cb.bind(); }; auto write_ffrq_tmr1_irq_callback() { return m_ffreq_tmr1_irq_cb.bind(); }; auto write_ffrq_tmr2_irq_callback() { return m_ffreq_tmr2_irq_cb.bind(); }; auto write_fiq_vector_callback() { return m_fiq_vector_w.bind(); }; template uint16_t adc_r() { return m_adc_in[Line](); } protected: spg2xx_io_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, const uint32_t sprite_limit) : spg2xx_io_device(mconfig, type, tag, owner, clock) { } enum { REG_IO_MODE, REG_IOA_DATA, REG_IOA_BUFFER, REG_IOA_DIR, REG_IOA_ATTRIB, REG_IOA_MASK, REG_IOB_DATA, REG_IOB_BUFFER, REG_IOB_DIR, REG_IOB_ATTRIB, REG_IOB_MASK, REG_IOC_DATA, REG_IOC_BUFFER, REG_IOC_DIR, REG_IOC_ATTRIB, REG_IOC_MASK, REG_TIMEBASE_SETUP, REG_TIMEBASE_CLEAR, REG_TIMERA_DATA, REG_TIMERA_CTRL, REG_TIMERA_ON, REG_TIMERA_IRQCLR, REG_TIMERB_DATA, REG_TIMERB_CTRL, REG_TIMERB_ON, REG_TIMERB_IRQCLR, REG_VERT_LINE = 0x1c, REG_SYSTEM_CTRL = 0x20, REG_INT_CTRL, REG_INT_CLEAR, REG_EXT_MEMORY_CTRL, REG_WATCHDOG_CLEAR, REG_ADC_CTRL, REG_ADC_PAD, REG_ADC_DATA, REG_SLEEP_MODE, REG_WAKEUP_SOURCE, REG_WAKEUP_TIME, REG_NTSC_PAL, REG_PRNG1 = 0x2c, REG_PRNG2, REG_FIQ_SEL, REG_DATA_SEGMENT, REG_UART_CTRL, REG_UART_STATUS, REG_UART_RESET, REG_UART_BAUD1, REG_UART_BAUD2, REG_UART_TXBUF, REG_UART_RXBUF, REG_UART_RXFIFO, REG_SPI_CTRL = 0x40, REG_SPI_TXSTATUS, REG_SPI_TXDATA, REG_SPI_RXSTATUS, REG_SPI_RXDATA, REG_SPI_MISC, REG_SIO_SETUP = 0x50, REG_SIO_STATUS, REG_SIO_ADDRL, REG_SIO_ADDRH, REG_SIO_DATA, REG_SIO_AUTO_TX_NUM, REG_I2C_CMD = 0x58, REG_I2C_STATUS, REG_I2C_ACCESS, REG_I2C_ADDR, REG_I2C_SUBADDR, REG_I2C_DATA_OUT, REG_I2C_DATA_IN, REG_I2C_MODE, REG_REGULATOR_CTRL = 0x60, REG_CLOCK_CTRL, REG_IO_DRIVE_CTRL }; void check_extint_irq(int channel); void check_irqs(const uint16_t changed); static const device_timer_id TIMER_TMB1 = 0; static const device_timer_id TIMER_TMB2 = 1; static const device_timer_id TIMER_UART_TX = 4; static const device_timer_id TIMER_UART_RX = 5; static const device_timer_id TIMER_4KHZ = 6; static const device_timer_id TIMER_SRC_AB = 7; static const device_timer_id TIMER_SRC_C = 8; static const device_timer_id TIMER_RNG = 9; static const device_timer_id TIMER_WATCHDOG = 10; static const device_timer_id TIMER_SPI_TX = 11; static const device_timer_id TIMER_ADC0 = 12; static const device_timer_id TIMER_ADC1 = 13; static const device_timer_id TIMER_ADC2 = 14; static const device_timer_id TIMER_ADC3 = 15; virtual void device_start() override; virtual void device_reset() override; virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; uint16_t clock_rng(int which); void update_porta_special_modes(); void update_portb_special_modes(); void do_gpio(uint32_t offset, bool write); uint16_t do_special_gpio(uint32_t index, uint16_t mask); void update_timer_b_rate(); void update_timer_ab_src(); void update_timer_c_src(); void increment_timer_a(); void uart_transmit_tick(); void uart_receive_tick(); void system_timer_tick(); void do_spi_tx(); void set_spi_irq(bool set); void update_spi_irqs(); void do_i2c(); void do_adc_capture(int channel); uint16_t m_io_regs[0x100]; uint8_t m_uart_rx_fifo[8]; uint8_t m_uart_rx_fifo_start; uint8_t m_uart_rx_fifo_end; uint8_t m_uart_rx_fifo_count; bool m_uart_rx_available; bool m_uart_rx_irq; bool m_uart_tx_irq; uint8_t m_spi_tx_fifo[16]; uint8_t m_spi_tx_fifo_start; uint8_t m_spi_tx_fifo_end; uint8_t m_spi_tx_fifo_count; uint8_t m_spi_tx_buf; uint8_t m_spi_tx_bit; uint8_t m_spi_rx_fifo[16]; uint8_t m_spi_rx_fifo_start; uint8_t m_spi_rx_fifo_end; uint8_t m_spi_rx_fifo_count; uint8_t m_spi_rx_buf; uint8_t m_spi_rx_bit; bool m_extint[2]; devcb_write16 m_porta_out; devcb_write16 m_portb_out; devcb_write16 m_portc_out; devcb_read16 m_porta_in; devcb_read16 m_portb_in; devcb_read16 m_portc_in; devcb_read16::array<4> m_adc_in; emu_timer *m_adc_timer[4]; devcb_write8 m_i2c_w; devcb_read8 m_i2c_r; devcb_write8 m_uart_tx; devcb_write_line m_spi_tx; devcb_write8 m_chip_sel; uint16_t m_timer_a_preload; uint16_t m_timer_b_preload; uint16_t m_timer_b_divisor; uint16_t m_timer_b_tick_rate; emu_timer *m_tmb1; emu_timer *m_tmb2; emu_timer *m_timer_src_ab; emu_timer *m_timer_src_c; emu_timer *m_4khz_timer; uint32_t m_2khz_divider; uint32_t m_1khz_divider; uint32_t m_4hz_divider; uint32_t m_uart_baud_rate; emu_timer *m_uart_tx_timer; emu_timer *m_uart_rx_timer; emu_timer *m_rng_timer; emu_timer *m_watchdog_timer; uint32_t m_spi_rate; emu_timer* m_spi_tx_timer; uint8_t m_sio_bits_remaining; bool m_sio_writing; required_device m_cpu; required_device m_screen; devcb_read16 m_pal_read_cb; devcb_write_line m_timer_irq_cb; devcb_write_line m_uart_adc_irq_cb; devcb_write_line m_external_irq_cb; devcb_write_line m_ffreq_tmr1_irq_cb; devcb_write_line m_ffreq_tmr2_irq_cb; devcb_write8 m_fiq_vector_w; }; class spg24x_io_device : public spg2xx_io_device { public: template spg24x_io_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&cpu_tag, U &&screen_tag) : spg24x_io_device(mconfig, tag, owner, clock) { m_cpu.set_tag(std::forward(cpu_tag)); m_screen.set_tag(std::forward(screen_tag)); } spg24x_io_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); }; class spg28x_io_device : public spg2xx_io_device { public: template spg28x_io_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&cpu_tag, U &&screen_tag) : spg28x_io_device(mconfig, tag, owner, clock) { m_cpu.set_tag(std::forward(cpu_tag)); m_screen.set_tag(std::forward(screen_tag)); } spg28x_io_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); virtual void io_extended_w(offs_t offset, uint16_t data) override; }; DECLARE_DEVICE_TYPE(SPG24X_IO, spg24x_io_device) DECLARE_DEVICE_TYPE(SPG28X_IO, spg28x_io_device) #endif // MAME_MACHINE_SPG2XX_IO_H