summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/6525tpi.h
blob: ed927d2e11a72b36fb925f6be1e666f78d115186 (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
// license:BSD-3-Clause
// copyright-holders:Peter Trauner
/*****************************************************************************
 *
 * machine/tpi6525.h
 *
 * mos tri port interface 6525
 * mos triple interface adapter 6523
 *
 * peter.trauner@jk.uni-linz.ac.at
 *
 * used in commodore b series
 * used in commodore c1551 floppy disk drive
 *
 * tia6523 is a tpi6525 without control register!?
 *
 * tia6523
 *   only some lines of port b and c are in the pinout!
 *
 * connector to floppy c1551 (delivered with c1551 as c16 expansion)
 *   port a for data read/write
 *   port b
 *   0 status 0
 *   1 status 1
 *   port c
 *   6 dav output edge data on port a available
 *   7 ack input edge ready for next datum
 *
 ****************************************************************************/

#ifndef __TPI6525_H__
#define __TPI6525_H__


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

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

	template<class _Object> static devcb_base &set_out_irq_callback(device_t &device, _Object object) { return downcast<tpi6525_device &>(device).m_out_irq_cb.set_callback(object); }
	template<class _Object> static devcb_base &set_in_pa_callback(device_t &device, _Object object) { return downcast<tpi6525_device &>(device).m_in_pa_cb.set_callback(object); }
	template<class _Object> static devcb_base &set_out_pa_callback(device_t &device, _Object object) { return downcast<tpi6525_device &>(device).m_out_pa_cb.set_callback(object); }
	template<class _Object> static devcb_base &set_in_pb_callback(device_t &device, _Object object) { return downcast<tpi6525_device &>(device).m_in_pb_cb.set_callback(object); }
	template<class _Object> static devcb_base &set_out_pb_callback(device_t &device, _Object object) { return downcast<tpi6525_device &>(device).m_out_pb_cb.set_callback(object); }
	template<class _Object> static devcb_base &set_in_pc_callback(device_t &device, _Object object) { return downcast<tpi6525_device &>(device).m_in_pc_cb.set_callback(object); }
	template<class _Object> static devcb_base &set_out_pc_callback(device_t &device, _Object object) { return downcast<tpi6525_device &>(device).m_out_pc_cb.set_callback(object); }
	template<class _Object> static devcb_base &set_out_ca_callback(device_t &device, _Object object) { return downcast<tpi6525_device &>(device).m_out_ca_cb.set_callback(object); }
	template<class _Object> static devcb_base &set_out_cb_callback(device_t &device, _Object object) { return downcast<tpi6525_device &>(device).m_out_cb_cb.set_callback(object); }

	DECLARE_READ8_MEMBER( read );
	DECLARE_WRITE8_MEMBER( write );

	DECLARE_WRITE_LINE_MEMBER( i0_w );
	DECLARE_WRITE_LINE_MEMBER( i1_w );
	DECLARE_WRITE_LINE_MEMBER( i2_w );
	DECLARE_WRITE_LINE_MEMBER( i3_w );
	DECLARE_WRITE_LINE_MEMBER( i4_w );

	DECLARE_READ8_MEMBER( pa_r );
	DECLARE_READ8_MEMBER( pb_r );
	DECLARE_READ8_MEMBER( pc_r );
	DECLARE_WRITE8_MEMBER( pa_w );
	DECLARE_WRITE8_MEMBER( pb_w );
	DECLARE_WRITE8_MEMBER( pc_w );

	WRITE_LINE_MEMBER( pb0_w ) { port_line_w(m_in_b, 0, state); }
	WRITE_LINE_MEMBER( pb1_w ) { port_line_w(m_in_b, 1, state); }
	WRITE_LINE_MEMBER( pb2_w ) { port_line_w(m_in_b, 2, state); }
	WRITE_LINE_MEMBER( pb3_w ) { port_line_w(m_in_b, 3, state); }
	WRITE_LINE_MEMBER( pb4_w ) { port_line_w(m_in_b, 4, state); }
	WRITE_LINE_MEMBER( pb5_w ) { port_line_w(m_in_b, 5, state); }
	WRITE_LINE_MEMBER( pb6_w ) { port_line_w(m_in_b, 6, state); }
	WRITE_LINE_MEMBER( pb7_w ) { port_line_w(m_in_b, 7, state); }

	uint8_t get_ddr_a();
	uint8_t get_ddr_b();
	uint8_t get_ddr_c();

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

private:
	// internal state
	devcb_write_line    m_out_irq_cb;

	devcb_read8         m_in_pa_cb;
	devcb_write8        m_out_pa_cb;

	devcb_read8         m_in_pb_cb;
	devcb_write8        m_out_pb_cb;

	devcb_read8         m_in_pc_cb;
	devcb_write8        m_out_pc_cb;

	devcb_write_line    m_out_ca_cb;
	devcb_write_line    m_out_cb_cb;

	uint8_t m_port_a, m_ddr_a, m_in_a;
	uint8_t m_port_b, m_ddr_b, m_in_b;
	uint8_t m_port_c, m_ddr_c, m_in_c;

	uint8_t m_ca_level, m_cb_level, m_interrupt_level;

	uint8_t m_cr;
	uint8_t m_air;

	uint8_t m_irq_level[5];

	void set_interrupt();
	void clear_interrupt();

	// helper function to write a single line
	static void port_line_w(uint8_t &port, int line, int state);
};

extern const device_type TPI6525;


#define MCFG_TPI6525_OUT_IRQ_CB(_devcb) \
	devcb = &tpi6525_device::set_out_irq_callback(*device, DEVCB_##_devcb);

#define MCFG_TPI6525_IN_PA_CB(_devcb) \
	devcb = &tpi6525_device::set_in_pa_callback(*device, DEVCB_##_devcb);

#define MCFG_TPI6525_OUT_PA_CB(_devcb) \
	devcb = &tpi6525_device::set_out_pa_callback(*device, DEVCB_##_devcb);

#define MCFG_TPI6525_IN_PB_CB(_devcb) \
	devcb = &tpi6525_device::set_in_pb_callback(*device, DEVCB_##_devcb);

#define MCFG_TPI6525_OUT_PB_CB(_devcb) \
	devcb = &tpi6525_device::set_out_pb_callback(*device, DEVCB_##_devcb);

#define MCFG_TPI6525_IN_PC_CB(_devcb) \
	devcb = &tpi6525_device::set_in_pc_callback(*device, DEVCB_##_devcb);

#define MCFG_TPI6525_OUT_PC_CB(_devcb) \
	devcb = &tpi6525_device::set_out_pc_callback(*device, DEVCB_##_devcb);

#define MCFG_TPI6525_OUT_CA_CB(_devcb) \
	devcb = &tpi6525_device::set_out_ca_callback(*device, DEVCB_##_devcb);

#define MCFG_TPI6525_OUT_CB_CB(_devcb) \
	devcb = &tpi6525_device::set_out_cb_callback(*device, DEVCB_##_devcb);


#endif /* __TPI6525_H__ */