summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/machine/mc6854.h
blob: 4f52c9a736bbf46304fad68473a36ebf7b40afdf (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
/**********************************************************************

  Copyright (C) Antoine Mine' 2006

  Motorola 6854 emulation (network interface).

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

#ifndef MC6854_H
#define MC6854_H


#define MAX_FRAME_LENGTH 65536
/* arbitrary value, you may need to enlarge it if you get truncated frames */

#define MC6854_FIFO_SIZE 3
/* hardcoded size of the 6854 FIFO (this is a hardware limit) */


/* ---------- configuration ------------ */

struct mc6854_interface
{
	devcb_write_line  m_out_irq_cb; /* interrupt request */

	/* low-level, bit-based interface */
	devcb_read_line   m_in_rxd_cb; /* receive bit */
	devcb_write_line  m_out_txd_cb; /* transmit bit */

	/* high-level, frame-based interface */
	void ( * m_out_frame ) ( device_t *device, UINT8* data, int length );

	/* control lines */
	devcb_write_line  m_out_rts_cb; /* 1 = transmitting, 0 = idle */
	devcb_write_line  m_out_dtr_cb; /* 1 = data transmit ready, 0 = busy */
};


class mc6854_device : public device_t,
								public mc6854_interface
{
public:
	mc6854_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
	~mc6854_device() {}

	/* interface to CPU via address/data bus*/
	DECLARE_READ8_MEMBER( read );
	DECLARE_WRITE8_MEMBER( write );

	/* low-level, bit-based interface */
	DECLARE_WRITE_LINE_MEMBER( set_rx );

	/* high-level, frame-based interface */
	int send_frame( UINT8* data, int length ); /* ret -1 if busy */

	/* control lines */
	DECLARE_WRITE_LINE_MEMBER( set_cts ); /* 1 = clear-to-send, 0 = busy */
	DECLARE_WRITE_LINE_MEMBER( set_dcd ); /* 1 = carrier, 0 = no carrier */

	/* clock */
	DECLARE_WRITE_LINE_MEMBER( rxc_w );
	DECLARE_WRITE_LINE_MEMBER( txc_w );

protected:
	// device-level overrides
	virtual void device_config_complete();
	virtual void device_start();
	virtual void device_reset();

private:
	// internal state
	devcb_resolved_write_line   m_out_irq_func;
	devcb_resolved_read_line    m_in_rxd_func;
	devcb_resolved_write_line   m_out_txd_func;
	devcb_resolved_write_line   m_out_rts_func;
	devcb_resolved_write_line   m_out_dtr_func;

	/* registers */
	UINT8 m_cr1, m_cr2, m_cr3, m_cr4; /* control registers */
	UINT8 m_sr1, m_sr2;           /* status registers */

	UINT8 m_cts, m_dcd;

	/* transmit state */
	UINT8  m_tstate;
	UINT16 m_tfifo[MC6854_FIFO_SIZE];  /* X x 8-bit FIFO + full & last marker bits */
	UINT8  m_tones;             /* counter for zero-insertion */
	emu_timer *m_ttimer;       /* when to ask for more data */

	/* receive state */
	UINT8  m_rstate;
	UINT32 m_rreg;              /* shift register */
	UINT8  m_rones;             /* count '1 bits */
	UINT8  m_rsize;             /* bits in the shift register */
	UINT16 m_rfifo[MC6854_FIFO_SIZE];  /* X x 8-bit FIFO + full & addr marker bits */

	/* frame-based interface*/
	UINT8  m_frame[MAX_FRAME_LENGTH];
	UINT32 m_flen, m_fpos;


	/* meaning of tstate / rtate:
	   0 = idle / waiting for frame flag
	   1 = flag sync
	   2 = 8-bit address field(s)
	   3-4 = 8-bit control field(s)
	   5 = 8-bit logical control field(s)
	   6 = variable-length data field(s)
	*/
	
	void send_bits( UINT32 data, int len, int zi );
	void tfifo_push( UINT8 data );
	void tfifo_terminate( );
	TIMER_CALLBACK_MEMBER(tfifo_cb);
	void tfifo_clear( );
	
	void rfifo_push( UINT8 d );
	void rfifo_terminate( );
	UINT8 rfifo_pop( );
	void rfifo_clear( );
	
	void update_sr2( );
	void update_sr1( );
};

extern const device_type MC6854;


/* we provide two interfaces:
   - a bit-based interface:   out_tx, set_rx
   - a frame-based interface: out_frame, send_frame

   The bit-based interface is low-level and slow.
   Use it to simulate the actual bits sent into the wires, e.g., to connect
   the emulator to another bit-based emulated network device, or an actual
   device.

   The frame-based interface is higher-level and faster.
   It passes bytes directly from one end to the other without bothering with
   the actual bit-encoding, synchronization, and CRC.
   Once completed, a frame is sent through out_frame. Aborted frames are not
   transmitted at all. No start flag, stop flag, or crc bits are trasmitted.
   send_frame makes a frame available to the CPU through the 6854 (it may
   fail and return -1 if the 6854 is not ready to accept the frame; even
   if the frame is accepted and 0 is returned, the CPU may abort it). Ony
   full frames are accepted.
*/


#define MCFG_MC6854_ADD(_tag, _intrf) \
	MCFG_DEVICE_ADD(_tag, MC6854, 0)          \
	MCFG_DEVICE_CONFIG(_intrf)

#define MCFG_MC6854_REMOVE(_tag)        \
	MCFG_DEVICE_REMOVE(_tag)


#endif