summaryrefslogblamecommitdiffstatshomepage
path: root/src/devices/machine/z80sio.h
blob: 0f73998aa05cb5a93eed2cd858d1a9ddbd650aae (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12











                                                                            

                                                                           

                                                                          

                                                                         

                                                                              

                                                                           
                                                                          



                                                                           


                                                                            



                                                                        
                                                                             
                                                                             
                                                                           
                                                                           
                                                                                 

                                                                              


                                                                             



                                                                           
                                                                      
                                                                    
                                                            





                                                      


                                                        















                                                         


                                                                            



                             
 
                             

                                                                            
                               

                                                                            


                             

                                                                            
                    





                                                                            
                                      
 
                                   

                                        
                                    

       
                                                                                                        
 
                                 


                                
 
                                  








                                                
 

                                         
 

                                      
 
                                                                

                                           



                                            
                         
                                  

                                               
                                  







                                                
 
          



                                 
                           

          

            


                                         

          


                         
                                            

                                            
          
 


                          

                                            



                                            

                                            
          
 



                                                                              












                                                                          

          






                                                      
 




                                                       
                                    


                                

                                       
                                       

                         


                                 
 

                                                       
                                          
                                                                              


                                                                              
                                                     




                                                  
 
                                                       

                  

                            



                                                               




                                                                   

                                                                 
                                                              

                                                            

                  

                                                  
 

                                                 
                                                   



                                                             
                            


                              
 
          



                                   
                                   
                                     
                                              
 
                               
                               
                            
                            
                            
                                                           
                               
                                            
 
                                


                                 
                                
                                                                                         
                             


                                                           














                                                                                                       


  


































                                                                                                         


                                           


                              

                               


  


                                        
                                                
 
                                    
 
       
                                   
                                                                                                       
 
















                                                                                                   
 













                                                                 

                                
                           






                                                                        






                                                                                               

          
                                                                                                                         
 
                                 
                                                                                   
                                                       

                                             
                                                                         

                                              


                                                  



                                        




                                                        
 
                                                                                                 








                                                
                                              

                         




                                             

                                         

                                              

                                              
                                                

  
                                             
 
       















                                                                                                                            
  
 
                                                  
 
       
                                                                                                            

  




                                                                                                        


                                                                     










                                                                         
                          
                                                  
                                                     
                                                       
                                                   
 
                               
// license:BSD-3-Clause
// copyright-holders:Curt Coder, Joakim Larsson Edstrom
/***************************************************************************

    Z80-SIO Serial Input/Output

****************************************************************************
             _____   _____               _____               _____
       D1  1|*    \_/     |40 D0       _/     |40 D0       _/     |40 D0
       D3  2|             |39 D2      :       |39 D2      :       |39 D2
       D5  3|             |38 D4      :       |38 D4      :       |38 D4
       D7  4|             |37 D6      :       |37 D6      :       |37 D6
     _INT  5|             |36 _IORQ   :       |36 _IORQ   :       |36 _IORQ
      IEO  6|             |35 _CE     :       |35 _CE     :       |35 _CE
      IEI  7|             |34 B/_A    :       |34 B/_A    :       |34 B/_A
      _M1  8|             |33 C/_D    :       |33 C/_D    :       |33 C/_D
      VDD  9|  DIP40      |32 _RD     : DIP40 |32 _RD     : DIP40 |32 _RD
 _W//RDYA 10|  Z80        |31 GND     : Z80   |31 GND     : Z80   |31 GND
   _SYNCA 11|  SIO/0      |30 _W/_RDYB: SIO/1 |30 _W/_RDYB: SIO/2 |30 _W/_RDYB
     RxDA 12|             |29 _SYNCB  :       |29 _SYNCB  :       |29 _SYNCB
    _RxCA 13|             |28 RxDB    :       |28 RxDB    :       |28 _RxCB
    _TxCA 14|             |27 _RxTxCB :       |27 _RxCB   :       |27 _TxCB
     TxDA 15|             |26 TxDB    :       |26 _TxCB   :       |26 TxDB
    _DTRA 16|             |25 _DTRB   :       |25 TxD_B   :       |25 _DTRB
    _RTSA 17|             |24 _RTSB   :       |24 _RTSB   :       |24 _RTSB
    _CTSA 18|             |23 _CTSB   :       |23 _CTSB   :       |23 _CTSB
    _DCDA 19|             |22 _DCDB   :       |22 _DCDB   :       |22 _DCDB
      CLK 20|_____________|21 _RESET  :_______|21 _RESET  :_______|21 _RESET

                             *I                                   *I
         *I         N         O                 *I                 O
          N D D D D / D D D D R                  N D D D D D D D D R*C
          T 7 5 3 1 C 0 2 4 6 Q                  T 7 5 3 1 0 2 4 6 Q E
         +----------------------+               +----------------------+
      IEI|34                  22| *CE        IEI|6 5 4 3 2 1 44  42  40|B/ *A
      IEO|35                  21| B/ *A      IEO|8             43  41  |C/ *D
      *M1|                      | C/ *D      *M1|9                   37|*RD
      +5v|                      | *RD        +5V|10                  36|GND
*W/ *RDYA|       QFP44          | GND  *W/ *RDYA|11    PLCC44        35|*W/ *RDYB
      N/C|      Z80 SIO/3       | N/C     *SYNCA|12   Z80 SIO/4      34|*SYNCB
   *SYNCA|       Z804C43        | *W/ *RDYB RxDA|13                  33|RxDB
     RxDA|                      | *SYNCB   *RxCA|14                  32|*RxCB
    *RxCA|42                    | RxDB     *TxCA|15                  31|*TxCB
    *TxCA|43                1 1 | *RxCB     TxDA|  19  21  23  25    30|TxDB
     TxDA`. 2 3 4 5 6 7 8 9 0 1 | *TxCB      N/C|18  20  22  24  26  29|N/C
           `--------------------+               +----------------------+
         *D*R*C*D C*R*D*C*R*D*T                 *D*R*C*D C*R*D*C*R*D N
          T T T C L E C*T T T x                  T T T C L E C T T T /
          R S S D K S D S S R D                  R S S D K S D S S R C
          A A A A   E B B B B B                  A A A A   E B B B B
                    T                                      T
                                 _____   _____
                           D1  1|*    \_/     |48 D0
                           D3  2|             |47 D2
                           D5  3|             |46 D4
                           D7  4|             |45 D6
                        _INTR  5|             |44 R/_W
                          CLK  6|             |43 _IACK
                        XTAL1  7|             |42 _DTACK
                        XTAL2  8|             |41 _CS
                       _RESET  9|             |40 _RxRDYB
                      _RxRDYA 10|             |39 _TxRDYB
                      _TxRDYA 11|  DIP48      |38 GND
                          Vcc 12|  MK68564    |37 _IEI
                         _IEO 13|  SIO        |36 _SYNCB
                       _SYNCA 14|             |35 _TxCB
                        _TxCA 15|             |34 _RxCB
                        _RxCA 16|             |29 RxDB
                         RxDA 17|             |28 TxDB
                         TxDA 18|             |27 _DTRB
                        _DTRA 19|             |26 _RTSB
                        _RTSA 20|             |25 _CTSB
                        _CTSA 21|             |24 _DCDB
                        _DCDA 22|             |23 A1
                           A2 23|             |22 A3
                           A4 24|_____________|21 A5

***************************************************************************/

#ifndef MAME_MACHINE_Z80SIO_H
#define MAME_MACHINE_Z80SIO_H

#pragma once

#include "machine/z80daisy.h"

//**************************************************************************
//  DEVICE CONFIGURATION MACROS
//**************************************************************************

#define SIO_CHANA_TAG   "cha"
#define SIO_CHANB_TAG   "chb"


//**************************************************************************
//  TYPE DEFINITIONS
//**************************************************************************

// ======================> z80sio_channel

class z80sio_device;

class z80sio_channel : public device_t
{
	friend class z80sio_device;
	friend class i8274_new_device;
	friend class upd7201_new_device;
	friend class mk68564_device;

public:
	z80sio_channel(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);

	// read register handlers
	uint8_t do_sioreg_rr0();
	uint8_t do_sioreg_rr1();
	uint8_t do_sioreg_rr2();

	// write register handlers
	void do_sioreg_wr0(uint8_t data);
	void do_sioreg_wr0_resets(uint8_t data);
	void do_sioreg_wr1(uint8_t data);
	void do_sioreg_wr2(uint8_t data);
	void do_sioreg_wr3(uint8_t data);
	void do_sioreg_wr4(uint8_t data);
	void do_sioreg_wr5(uint8_t data);
	void do_sioreg_wr6(uint8_t data);
	void do_sioreg_wr7(uint8_t data);

	uint8_t control_read();
	void control_write(uint8_t data);

	uint8_t data_read();
	void data_write(uint8_t data);

	DECLARE_WRITE_LINE_MEMBER( write_rx ) { m_rxd = state; }
	DECLARE_WRITE_LINE_MEMBER( cts_w );
	DECLARE_WRITE_LINE_MEMBER( dcd_w );
	DECLARE_WRITE_LINE_MEMBER( rxc_w );
	DECLARE_WRITE_LINE_MEMBER( txc_w );
	DECLARE_WRITE_LINE_MEMBER( sync_w );

	// Register state
	// read registers     enum
	uint8_t m_rr0; // REG_RR0_STATUS
	uint8_t m_rr1; // REG_RR1_SPEC_RCV_COND
	// write registers    enum
	uint8_t m_wr0; // REG_WR0_COMMAND_REGPT
	uint8_t m_wr1; // REG_WR1_INT_DMA_ENABLE
	uint8_t m_wr2; // REG_WR2_INT_VECTOR
	uint8_t m_wr3; // REG_WR3_RX_CONTROL
	uint8_t m_wr4; // REG_WR4_RX_TX_MODES
	uint8_t m_wr5; // REG_WR5_TX_CONTROL
	uint8_t m_wr6; // REG_WR6_SYNC_OR_SDLC_A
	uint8_t m_wr7; // REG_WR7_SYNC_OR_SDLC_F

protected:
	enum
	{
		INT_TRANSMIT = 0,
		INT_EXTERNAL,
		INT_RECEIVE
	};

	enum
	{
		INT_RCV_SPC_PRI_LVL  = 0,
		INT_TRANSMIT_PRI_LVL = 1,
		INT_EXTERNAL_PRI_LVL = 2
	};

	// Read registers
	enum
	{
		REG_RR0_STATUS          = 0,
		REG_RR1_SPEC_RCV_COND   = 1,
		REG_RR2_INTERRUPT_VECT  = 2
	};

	// Write registers
	enum
	{
		REG_WR0_COMMAND_REGPT   = 0,
		REG_WR1_INT_DMA_ENABLE  = 1,
		REG_WR2_INT_VECTOR      = 2,
		REG_WR3_RX_CONTROL      = 3,
		REG_WR4_RX_TX_MODES     = 4,
		REG_WR5_TX_CONTROL      = 5,
		REG_WR6_SYNC_OR_SDLC_A  = 6,
		REG_WR7_SYNC_OR_SDLC_F  = 7
	};

	// used in a flag bitmap variable
	enum : uint8_t
	{
		TX_FLAG_CRC     = 1U << 0,  // include in checksum calculation
		TX_FLAG_FRAMING = 1U << 1,  // transmitting framing bits
		TX_FLAG_ABORT_TX= 1U << 2,  // transmitting abort sequence
		TX_FLAG_CRC_TX  = 1U << 3,  // transmitting CRC value
		TX_FLAG_DATA_TX = 1U << 4   // transmitting frame data
	};

	// Sync/SDLC FSM states
	enum
	{
		SYNC_FSM_HUNT = 0,  // Hunt for start sync/flag
		SYNC_FSM_EVICT = 1, // Evict flag from sync SR
		SYNC_FSM_1ST_CHAR = 2,  // Receiving 1st character
		SYNC_FSM_IN_FRAME = 3   // Inside a frame
	};

	z80sio_channel(
			const machine_config &mconfig,
			device_type type,
			const char *tag,
			device_t *owner,
			uint32_t clock,
			uint8_t rr1_auto_reset);

	// device-level overrides
	virtual void device_resolve_objects() override;
	virtual void device_start() override;
	virtual void device_reset() override;

	void update_dtr_rts_break();
	void set_dtr(int state);
	void set_rts(int state);

	int get_clock_mode() const;
	int get_rx_word_length() const;
	int get_tx_word_length() const;

	// receiver state
	int m_rx_fifo_depth;
	uint32_t m_rx_data_fifo;
	uint32_t m_rx_error_fifo;

	int m_rx_clock;     // receive clock line state
	int m_rx_count;     // clocks until next sample
	bool m_dlyd_rxd;    // delayed RxD
	int m_rx_bit;       // receive data bit (0 = start bit, 1 = LSB, etc.)
	int m_rx_bit_limit; // bits to assemble for next character (sync/SDLC)
	int m_rx_sync_fsm;  // Sync/SDLC FSM state
	uint8_t m_rx_one_cnt;   // SDLC: counter to delete stuffed zeros
	uint16_t m_rx_sr;   // receive shift register
	uint8_t m_rx_sync_sr;   // rx sync SR
	uint8_t m_rx_crc_delay; // rx CRC delay SR
	uint16_t m_rx_crc;  // rx CRC accumulator
	bool m_rx_crc_en;   // rx CRC enabled
	bool m_rx_parity;   // accumulated parity

	int m_rx_first;     // first character received

	int m_rxd;

	// transmitter state
	uint8_t m_tx_data;

	int m_tx_clock;     // transmit clock line state
	int m_tx_count;     // clocks until next bit transition
	bool m_tx_phase;    // phase of bit clock
	bool m_tx_parity;   // accumulated parity
	bool m_tx_in_pkt;   // In active part of packet (sync mode)
	bool m_tx_forced_sync;  // Force sync/flag
	uint32_t m_tx_sr;   // transmit shift register
	uint16_t m_tx_crc;  // calculated transmit checksum
	uint8_t m_tx_hist;  // transmit history (for bitstuffing)
	uint8_t m_tx_flags; // internal transmit control flags
	uint8_t m_tx_delay; // 2-bit tx delay (4 half-bits)
	uint8_t m_all_sent_delay;   // SR for all-sent delay

	int m_txd;
	int m_dtr;          // data terminal ready
	int m_rts;          // request to send

	// external/status monitoring
	int m_ext_latched;  // changed data lines
	int m_brk_latched;  // break status latched
	int m_cts;          // clear to send line state
	int m_dcd;          // data carrier detect line state
	int m_sync;         // sync line state

	// synchronous state

	int m_index;
	z80sio_device *m_uart;

protected:
	// helpers
	void out_txd_cb(int state);
	void out_rts_cb(int state);
	void out_dtr_cb(int state);
	void set_ready(bool ready);
	bool receive_allowed() const;
	virtual bool transmit_allowed() const;

	void receive_enabled();
	void enter_hunt_mode();
	void sync_receive();
	void sdlc_receive();
	void receive_data();
	void queue_received(uint16_t data, uint32_t error);
	void advance_rx_fifo();
	uint8_t get_special_rx_mask() const;

	bool is_tx_idle() const;
	void transmit_enable();
	void transmit_complete();
	void async_tx_setup();
	void sync_tx_sr_empty();
	void tx_setup(uint16_t data, int bits, bool framing, bool crc_tx, bool abort_tx);
	void tx_setup_idle();
	bool get_tx_empty() const;
	void set_tx_empty(bool prev_state, bool new_state);
	void update_crc(uint16_t& crc , bool bit);

	void reset_ext_status();
	void read_ext();
	void trigger_ext_int();

	uint8_t const m_rr1_auto_reset;
};


// ======================> i8274_channel

class i8274_channel : public z80sio_channel
{
public:
	i8274_channel(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
};


// ======================> mk68564_channel

class mk68564_channel : public z80sio_channel
{
	friend class mk68564_device;

public:
	mk68564_channel(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);

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

	virtual bool transmit_allowed() const override;

private:
	uint8_t cmdreg_r();
	void cmdreg_w(uint8_t data);
	uint8_t modectl_r();
	void modectl_w(uint8_t data);
	uint8_t intctl_r();
	void intctl_w(uint8_t data);
	uint8_t sync1_r();
	void sync1_w(uint8_t data);
	uint8_t sync2_r();
	void sync2_w(uint8_t data);
	uint8_t rcvctl_r();
	void rcvctl_w(uint8_t data);
	uint8_t xmtctl_r();
	void xmtctl_w(uint8_t data);
	uint8_t tcreg_r();
	void tcreg_w(uint8_t data);
	uint8_t brgctl_r();
	void brgctl_w(uint8_t data);

	void brg_update();
	TIMER_CALLBACK_MEMBER(brg_timeout);

	bool m_tx_auto_enable;
	uint8_t m_brg_tc;
	uint8_t m_brg_control;
	bool m_brg_state;
	emu_timer *m_brg_timer;
};


// ======================> z80sio_device

class z80sio_device :  public device_t,
		public device_z80daisy_interface
{
	friend class z80sio_channel;

public:
	// construction/destruction
	z80sio_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);

	auto out_txda_callback() { return m_out_txd_cb[0].bind(); }
	auto out_txdb_callback() { return m_out_txd_cb[1].bind(); }
	auto out_dtra_callback() { return m_out_dtr_cb[0].bind(); }
	auto out_dtrb_callback() { return m_out_dtr_cb[1].bind(); }
	auto out_rtsa_callback() { return m_out_rts_cb[0].bind(); }
	auto out_rtsb_callback() { return m_out_rts_cb[1].bind(); }
	auto out_wrdya_callback() { return m_out_wrdy_cb[0].bind(); }
	auto out_wrdyb_callback() { return m_out_wrdy_cb[1].bind(); }
	auto out_synca_callback() { return m_out_sync_cb[0].bind(); }
	auto out_syncb_callback() { return m_out_sync_cb[1].bind(); }
	auto out_int_callback() { return m_out_int_cb.bind(); }
	auto out_rxdrqa_callback() { return m_out_rxdrq_cb[0].bind(); }
	auto out_rxdrqb_callback() { return m_out_rxdrq_cb[1].bind(); }
	auto out_txdrqa_callback() { return m_out_txdrq_cb[0].bind(); }
	auto out_txdrqb_callback() { return m_out_txdrq_cb[1].bind(); }

	template <typename T> void set_cputag(T &&tag) { m_hostcpu.set_tag(std::forward<T>(tag)); }

	uint8_t cd_ba_r(offs_t offset);
	void cd_ba_w(offs_t offset, uint8_t data);
	uint8_t ba_cd_r(offs_t offset);
	void ba_cd_w(offs_t offset, uint8_t data);

	uint8_t da_r() { return m_chanA->data_read(); }
	void da_w(uint8_t data) { m_chanA->data_write(data); }
	uint8_t db_r() { return m_chanB->data_read(); }
	void db_w(uint8_t data) { m_chanB->data_write(data); }

	uint8_t ca_r() { return m_chanA->control_read(); }
	void ca_w(uint8_t data) { m_chanA->control_write(data); }
	uint8_t cb_r() { return m_chanB->control_read(); }
	void cb_w(uint8_t data) { m_chanB->control_write(data); }

	// interrupt acknowledge
	virtual int m1_r();

	DECLARE_WRITE_LINE_MEMBER( rxa_w ) { m_chanA->write_rx(state); }
	DECLARE_WRITE_LINE_MEMBER( rxb_w ) { m_chanB->write_rx(state); }
	DECLARE_WRITE_LINE_MEMBER( ctsa_w ) { m_chanA->cts_w(state); }
	DECLARE_WRITE_LINE_MEMBER( ctsb_w ) { m_chanB->cts_w(state); }
	DECLARE_WRITE_LINE_MEMBER( dcda_w ) { m_chanA->dcd_w(state); }
	DECLARE_WRITE_LINE_MEMBER( dcdb_w ) { m_chanB->dcd_w(state); }
	DECLARE_WRITE_LINE_MEMBER( rxca_w ) { m_chanA->rxc_w(state); }
	DECLARE_WRITE_LINE_MEMBER( rxcb_w ) { m_chanB->rxc_w(state); }
	DECLARE_WRITE_LINE_MEMBER( txca_w ) { m_chanA->txc_w(state); }
	DECLARE_WRITE_LINE_MEMBER( txcb_w ) { m_chanB->txc_w(state); }
	DECLARE_WRITE_LINE_MEMBER( rxtxcb_w ) { m_chanB->rxc_w(state); m_chanB->txc_w(state); }
	DECLARE_WRITE_LINE_MEMBER( synca_w ) { m_chanA->sync_w(state); }
	DECLARE_WRITE_LINE_MEMBER( syncb_w ) { m_chanB->sync_w(state); }

protected:
	z80sio_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);

	// device-level overrides
	virtual void device_validity_check(validity_checker &valid) const override;
	virtual void device_resolve_objects() override;
	virtual void device_start() override;
	virtual void device_reset() override;
	virtual void device_add_mconfig(machine_config &config) override;

	// device_z80daisy_interface overrides
	virtual int z80daisy_irq_state() override;
	virtual int z80daisy_irq_ack() override;
	virtual void z80daisy_irq_reti() override;

	// internal interrupt management
	void check_interrupts();
	void reset_interrupts();
	void trigger_interrupt(int index, int type);
	void clear_interrupt(int index, int type);
	void return_from_interrupt();
	virtual uint8_t read_vector();
	virtual int const *interrupt_priorities() const;

	int get_channel_index(z80sio_channel const *ch) const { return (ch == m_chanA) ? 0 : 1; }

	enum
	{
		CHANNEL_A = 0,
		CHANNEL_B
	};

	required_device<z80sio_channel> m_chanA;
	required_device<z80sio_channel> m_chanB;
	optional_device<cpu_device> m_hostcpu;

	// internal state
	devcb_write_line    m_out_txd_cb[2];
	devcb_write_line    m_out_dtr_cb[2];
	devcb_write_line    m_out_rts_cb[2];
	devcb_write_line    m_out_wrdy_cb[2];
	devcb_write_line    m_out_sync_cb[2];

	devcb_write_line    m_out_int_cb;
	devcb_write_line    m_out_rxdrq_cb[2];
	devcb_write_line    m_out_txdrq_cb[2];

	int m_int_state[8]; // interrupt state
	int m_int_source[8]; // interrupt source
};

class i8274_new_device : public z80sio_device
{
public:
	i8274_new_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);

	virtual int m1_r() override;

protected:
	i8274_new_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);

	// device_t overrides
	virtual void device_add_mconfig(machine_config &config) override;

	// device_z80daisy_interface overrides
	virtual int z80daisy_irq_ack() override;
	virtual void z80daisy_irq_reti() override;

	virtual uint8_t read_vector() override;
	virtual int const *interrupt_priorities() const override;
};

class upd7201_new_device : public i8274_new_device
{
public:
	upd7201_new_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
};

class mk68564_device : public i8274_new_device
{
public:
	mk68564_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);

	void set_xtal(uint32_t clock);
	void set_xtal(const XTAL &clock) { set_xtal(clock.value()); }

	uint8_t read(offs_t offset);
	void write(offs_t offset, uint8_t data);

protected:
	// device_t overrides
	virtual void device_add_mconfig(machine_config &config) override;

private:
	void vectrg_w(uint8_t data);
};

// device type declaration
DECLARE_DEVICE_TYPE(Z80SIO,         z80sio_device)
DECLARE_DEVICE_TYPE(I8274_NEW,      i8274_new_device)
DECLARE_DEVICE_TYPE(UPD7201_NEW,    upd7201_new_device)
DECLARE_DEVICE_TYPE(MK68564,        mk68564_device)

#endif // MAME_MACHINE_Z80SIO_H