summaryrefslogblamecommitdiffstatshomepage
path: root/src/devices/machine/spg2xx_io.h
blob: c674ae72e6bc5952b095b41e597ec38c42176525 (plain) (tree)






















                                                                                                                            
                                                                              
 

                                               

                                                   
                                                 


                                                        
                               


                                               

                                                
 

                                                                 
 
                                                                 
 




                                                                                  
 
                                                                          
 

                                                                            





                                                                                                                                                        

















                               
 









                                   
 







                                       

                             
 


                                  
 



                                 
 

                                 
 







                                
 





                                    
 





                                     
 












                                          
                                           





                                                    


                                             










                                                                     
 

                                      





                                                                

                                 


                                   











                                     













                                    








                                  

                                        
 

                             

                               
                                  





















                                     
                               
                                    
 


                                  


                                     









                                                

                                    




























                                                                                                                                      
                                                                          





                                                
// 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 <size_t Line> 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 <size_t Line> 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_timers_irq();
	void check_data_irq();
	void check_external_irq();
	void check_hifreq_periodic_irq();
	void check_tmb_lofreq_key_irq();
	void check_all_irqs(const uint16_t changed);

	virtual void device_start() override;
	virtual void device_reset() override;

	TIMER_CALLBACK_MEMBER(timer_ab_tick);
	TIMER_CALLBACK_MEMBER(timer_c_tick);
	template <int Which> TIMER_CALLBACK_MEMBER(tmb_timer_tick);
	TIMER_CALLBACK_MEMBER(uart_transmit_tick);
	TIMER_CALLBACK_MEMBER(uart_receive_tick);
	TIMER_CALLBACK_MEMBER(system_timer_tick);
	TIMER_CALLBACK_MEMBER(rng_clock_tick);
	TIMER_CALLBACK_MEMBER(watchdog_tick);
	TIMER_CALLBACK_MEMBER(spi_tx_tick);
	template <int Which> TIMER_CALLBACK_MEMBER(adc_convert_tick);

	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 increment_timer_a();

	void set_spi_irq(bool set);
	void update_spi_irqs();

	void do_i2c();

	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<unsp_device> m_cpu;
	required_device<screen_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 <typename T, typename U>
	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<T>(cpu_tag));
		m_screen.set_tag(std::forward<U>(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 <typename T, typename U>
	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<T>(cpu_tag));
		m_screen.set_tag(std::forward<U>(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