1 // license:BSD-3-Clause
2 // copyright-holders:Antoine Mine
3 /**********************************************************************
4 
5   Copyright (C) Antoine Mine' 2006
6 
7   Motorola 6854 emulation (network interface).
8 
9 **********************************************************************/
10 
11 #ifndef MAME_MACHINE_MC6854_H
12 #define MAME_MACHINE_MC6854_H
13 
14 #pragma once
15 
16 
17 class mc6854_device : public device_t
18 {
19 public:
20 	static constexpr unsigned MAX_FRAME_LENGTH = 65536; // arbitrary value, you may need to enlarge it if you get truncated frames
21 
22 	typedef device_delegate<void (uint8_t *data, int length)> out_frame_delegate;
23 
24 	mc6854_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
25 
out_irq_cb()26 	auto out_irq_cb()  { return m_out_irq_cb.bind(); }
out_rdsr_cb()27 	auto out_rdsr_cb() { return m_out_rdsr_cb.bind(); }
out_tdsr_cb()28 	auto out_tdsr_cb() { return m_out_tdsr_cb.bind(); }
out_txd_cb()29 	auto out_txd_cb()  { return m_out_txd_cb.bind(); }
out_rts_cb()30 	auto out_rts_cb()  { return m_out_rts_cb.bind(); }
out_dtr_cb()31 	auto out_dtr_cb()  { return m_out_dtr_cb.bind(); }
32 
set_out_frame_callback(T &&...args)33 	template <typename... T> void set_out_frame_callback(T &&... args) { m_out_frame_cb.set(std::forward<T>(args)...); }
34 
35 	/* interface to CPU via address/data bus*/
36 	uint8_t read(offs_t offset);
37 	void write(offs_t offset, uint8_t data);
dma_r()38 	uint8_t dma_r(){ return read(2); }
39 
40 	/* low-level, bit-based interface */
41 	DECLARE_WRITE_LINE_MEMBER( set_rx );
42 
43 	/* high-level, frame-based interface */
44 	int send_frame( uint8_t* data, int length ); /* ret -1 if busy */
45 
46 	/* control lines */
47 	DECLARE_WRITE_LINE_MEMBER( set_cts ); /* 1 = clear-to-send, 0 = busy */
48 	DECLARE_WRITE_LINE_MEMBER( set_dcd ); /* 1 = carrier, 0 = no carrier */
49 
50 	/* clock */
51 	DECLARE_WRITE_LINE_MEMBER( rxc_w );
52 	DECLARE_WRITE_LINE_MEMBER( txc_w );
53 
54 protected:
55 	// device-level overrides
56 	virtual void device_start() override;
57 	virtual void device_reset() override;
58 	bool receive_allowed() const;
59 
60 private:
61 	static constexpr unsigned FIFO_SIZE = 3; // hardcoded size of the 6854 FIFO (this is a hardware limit)
62 
63 	// internal state
64 	devcb_write_line  m_out_irq_cb; /* interrupt request */
65 	devcb_write_line  m_out_rdsr_cb; /* Rx fifo DMA request */
66 	devcb_write_line  m_out_tdsr_cb; /* Tx fifo DMA request */
67 
68 	/* low-level, bit-based interface */
69 	devcb_write_line  m_out_txd_cb; /* transmit bit */
70 
71 	/* high-level, frame-based interface */
72 	out_frame_delegate   m_out_frame_cb;
73 
74 	/* control lines */
75 	devcb_write_line  m_out_rts_cb; /* 1 = transmitting, 0 = idle */
76 	devcb_write_line  m_out_dtr_cb; /* 1 = data transmit ready, 0 = busy */
77 
78 	/* registers */
79 	uint8_t m_cr1, m_cr2, m_cr3, m_cr4; /* control registers */
80 	uint8_t m_sr1, m_sr2;           /* status registers */
81 
82 	uint8_t m_cts, m_dcd;
83 
84 	/* transmit state */
85 	uint8_t  m_tstate;
86 	uint16_t m_tfifo[FIFO_SIZE];  /* X x 8-bit FIFO + full & last marker bits */
87 	uint8_t  m_tones;             /* counter for zero-insertion */
88 	emu_timer *m_ttimer;       /* when to ask for more data */
89 
90 	/* receive state */
91 	uint8_t  m_rstate;
92 	uint32_t m_rreg;              /* shift register */
93 	uint8_t  m_rones;             /* count '1 bits */
94 	uint8_t  m_rsize;             /* bits in the shift register */
95 	uint16_t m_rfifo[FIFO_SIZE];  /* X x 8-bit FIFO + full & addr marker bits */
96 	bool     m_rxd;
97 	bool     m_rxc;
98 
99 	/* frame-based interface*/
100 	uint8_t  m_frame[MAX_FRAME_LENGTH];
101 	uint32_t m_flen, m_fpos;
102 
103 
104 	/* meaning of tstate / rtate:
105 	   0 = idle / waiting for frame flag
106 	   1 = flag sync
107 	   2 = 8-bit address field(s)
108 	   3-4 = 8-bit control field(s)
109 	   5 = 8-bit logical control field(s)
110 	   6 = variable-length data field(s)
111 	*/
112 
113 	void send_bits( uint32_t data, int len, int zi );
114 	void tfifo_push( uint8_t data );
115 	void tfifo_terminate( );
116 	TIMER_CALLBACK_MEMBER(tfifo_cb);
117 	void tfifo_clear( );
118 
119 	void rfifo_push( uint8_t d );
120 	void rfifo_terminate( );
121 	uint8_t rfifo_pop( );
122 	void rfifo_clear( );
123 
124 	void update_sr2( );
125 	void update_sr1( );
126 };
127 
128 DECLARE_DEVICE_TYPE(MC6854, mc6854_device)
129 
130 
131 /* we provide two interfaces:
132    - a bit-based interface:   out_tx, set_rx
133    - a frame-based interface: out_frame, send_frame
134 
135    The bit-based interface is low-level and slow.
136    Use it to simulate the actual bits sent into the wires, e.g., to connect
137    the emulator to another bit-based emulated network device, or an actual
138    device.
139 
140    The frame-based interface is higher-level and faster.
141    It passes bytes directly from one end to the other without bothering with
142    the actual bit-encoding, synchronization, and CRC.
143 
144    Once completed, a frame is sent through out_frame. Aborted frames are not
145    transmitted at all. No start flag, stop flag, or crc bits are transmitted.
146    send_frame makes a frame available to the CPU through the 6854 (it may
147    fail and return -1 if the 6854 is not ready to accept the frame; even
148    if the frame is accepted and 0 is returned, the CPU may abort it). Ony
149    full frames are accepted.
150 */
151 
152 #endif // MAME_MACHINE_MC6854_H
153