summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/smpc.h
blob: 2321448a67fe616d901506703b81718219a1f87d (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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
// license:LGPL-2.1+
// copyright-holders:Angelo Salese, R. Belmont
// TODO: make separate device when code is decoupled better
//DECLARE_WRITE8_MEMBER( stv_SMPC_w );
//DECLARE_READ8_MEMBER( stv_SMPC_r );
//DECLARE_WRITE8_MEMBER( saturn_SMPC_w );
//DECLARE_READ8_MEMBER( saturn_SMPC_r );

#ifndef MAME_MACHINE_SMPC_HLE_H
#define MAME_MACHINE_SMPC_HLE_H

#pragma once

#include "screen.h"
#include "bus/sat_ctrl/ctrl.h"
#include "machine/nvram.h"


//**************************************************************************
//  INTERFACE CONFIGURATION MACROS
//**************************************************************************

#define MCFG_SMPC_HLE_ADD(tag, clock) \
	MCFG_DEVICE_ADD((tag), SMPC_HLE, (clock))

#define MCFG_SMPC_HLE_SCREEN(screen_tag) \
	downcast<smpc_hle_device &>(*device).set_screen_tag(screen_tag);

#define MCFG_SMPC_HLE_CONTROL_PORTS(ctrl1_tag, ctrl2_tag) \
	downcast<smpc_hle_device &>(*device).set_control_port_tags(ctrl1_tag, ctrl2_tag);

#define MCFG_SMPC_HLE_PDR1_IN_CB(_devcb) \
	downcast<smpc_hle_device &>(*device).set_pdr1_in_handler(DEVCB_##_devcb);

#define MCFG_SMPC_HLE_PDR2_IN_CB(_devcb) \
	downcast<smpc_hle_device &>(*device).set_pdr2_in_handler(DEVCB_##_devcb);

#define MCFG_SMPC_HLE_PDR1_OUT_CB(_devcb) \
	downcast<smpc_hle_device &>(*device).set_pdr1_out_handler(DEVCB_##_devcb);

#define MCFG_SMPC_HLE_PDR2_OUT_CB(_devcb) \
	downcast<smpc_hle_device &>(*device).set_pdr2_out_handler(DEVCB_##_devcb);

#define MCFG_SMPC_HLE_MASTER_RESET_CB(_devcb) \
	downcast<smpc_hle_device &>(*device).set_master_reset_handler(DEVCB_##_devcb);

#define MCFG_SMPC_HLE_MASTER_NMI_CB(_devcb) \
	downcast<smpc_hle_device &>(*device).set_master_nmi_handler(DEVCB_##_devcb);

#define MCFG_SMPC_HLE_SLAVE_RESET_CB(_devcb) \
	downcast<smpc_hle_device &>(*device).set_slave_reset_handler(DEVCB_##_devcb);

#define MCFG_SMPC_HLE_SOUND_RESET_CB(_devcb) \
	downcast<smpc_hle_device &>(*device).set_sound_reset_handler(DEVCB_##_devcb);

#define MCFG_SMPC_HLE_SYSTEM_RESET_CB(_devcb) \
	downcast<smpc_hle_device &>(*device).set_system_reset_handler(DEVCB_##_devcb);

#define MCFG_SMPC_HLE_SYSTEM_HALT_CB(_devcb) \
	downcast<smpc_hle_device &>(*device).set_system_halt_handler(DEVCB_##_devcb);

#define MCFG_SMPC_HLE_DOT_SELECT_CB(_devcb) \
	downcast<smpc_hle_device &>(*device).set_dot_select_handler(DEVCB_##_devcb);

// set_irq_handler doesn't work in Saturn driver???
#define MCFG_SMPC_HLE_IRQ_HANDLER_CB(_devcb) \
	downcast<smpc_hle_device &>(*device).set_interrupt_handler(DEVCB_##_devcb);


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

// ======================> smpc_hle_device

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

	// I/O operations
//  void io_map(address_map &map);
	DECLARE_READ8_MEMBER( read );
	DECLARE_WRITE8_MEMBER( write );

	DECLARE_INPUT_CHANGED_MEMBER( trigger_nmi_r );

	void m68k_reset_trigger();

	bool get_iosel(bool which);

	uint8_t get_ddr(bool which);

//  system delegation
	template<class Object>
	devcb_base &set_master_reset_handler(Object &&cb)
	{ return m_mshres.set_callback(std::forward<Object>(cb)); }

	template<class Object>
	devcb_base &set_master_nmi_handler(Object &&cb)
	{ return m_mshnmi.set_callback(std::forward<Object>(cb)); }

	template<class Object>
	devcb_base &set_slave_reset_handler(Object &&cb)
	{ return m_sshres.set_callback(std::forward<Object>(cb)); }

	template<class Object>
	devcb_base &set_sound_reset_handler(Object &&cb)
	{ return m_sndres.set_callback(std::forward<Object>(cb)); }

	template<class Object>
	devcb_base &set_system_reset_handler(Object &&cb)
	{ return m_sysres.set_callback(std::forward<Object>(cb)); }

	template<class Object>
	devcb_base &set_system_halt_handler(Object &&cb)
	{ return m_syshalt.set_callback(std::forward<Object>(cb)); }

	template<class Object>
	devcb_base &set_dot_select_handler(Object &&cb)
	{ return m_dotsel.set_callback(std::forward<Object>(cb)); }


//  PDR delegation
	template<class Object>
	devcb_base &set_pdr1_in_handler(Object &&cb)
	{ return m_pdr1_read.set_callback(std::forward<Object>(cb)); }

	template<class Object>
	devcb_base &set_pdr2_in_handler(Object &&cb)
	{ return m_pdr2_read.set_callback(std::forward<Object>(cb)); }

	template<class Object>
	devcb_base &set_pdr1_out_handler(Object &&cb)
	{ return m_pdr1_write.set_callback(std::forward<Object>(cb)); }

	template<class Object>
	devcb_base &set_pdr2_out_handler(Object &&cb)
	{ return m_pdr2_write.set_callback(std::forward<Object>(cb)); }

	// interrupt handler
	template<class Object>
	devcb_base &set_interrupt_handler(Object &&cb)
	{ return m_irq_line.set_callback(std::forward<Object>(cb)); }

	void set_region_code(uint8_t rgn) { m_region_code = rgn; }
	void set_screen_tag(const char *tag) { m_screen.set_tag(tag); }
	void set_control_port_tags(const char *tag1, const char *tag2)
	{
		m_ctrl1_tag = tag1;
		m_ctrl2_tag = tag2;
		// TODO: checking against nullptr still returns a device!?
		m_has_ctrl_ports = true;
	}

protected:
	// device-level overrides
//  virtual void device_validity_check(validity_checker &valid) const override;
	virtual void device_add_mconfig(machine_config &config) override;
	virtual void device_start() override;
	virtual void device_reset() override;
	virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
	virtual space_config_vector memory_space_config() const override;

private:

	const address_space_config      m_space_config;
	enum {
		COMMAND_ID = 1,
		RTC_ID,
		INTBACK_ID,
		SNDRES_ID
	};

	emu_timer *m_cmd_timer;
	emu_timer *m_rtc_timer;
	emu_timer *m_intback_timer;
	emu_timer *m_sndres_timer;
	const char *m_ctrl1_tag;
	const char *m_ctrl2_tag;
	bool m_has_ctrl_ports;

	bool m_sf;
	bool m_cd_sf;
	uint8_t m_sr;
	uint8_t m_ddr1, m_ddr2;
	uint8_t m_pdr1_readback, m_pdr2_readback;
	bool m_iosel1, m_iosel2;
	bool m_exle1, m_exle2;
	uint8_t m_ireg[7];
	uint8_t m_intback_buf[3];
	uint8_t m_oreg[32];
	uint8_t m_rtc_data[7];
	uint8_t m_smem[5];
	uint8_t m_comreg;
	// in usec
	// timing table, from manual in usec
	const uint32_t m_cmd_table_timing[0x20] =
	{
		30, 30, // MASTER ON / OFF
		30, 30, // SLAVE ON / OFF
		10, 10, // <unknown>
		30, 30, // SOUND ON / OFF
		40, 40, // CD ON / OFF
		30, 30, 30, // NETLINK ON / OFF / <unknown>
		100*1000, 100*1000, 100*1000, // SYSTEM RESET / ClocK CHaNGe 352 / 320
		320*1000, // INTBACK
		30, 30, 30, 30, 30, // <unknown>
		70, 40, 30, 30, 30, // SETTIME / SETSMEM / NMIREQ / RESENAB / RESDISA
		30, 30, 30, 30 // <unknown>
	};
	bool m_command_in_progress;
	bool m_NMI_reset;
	bool m_cur_dotsel;

	void master_sh2_nmi();
	void irq_request();

	void resolve_intback();
	void intback_continue_request();
	void handle_rtc_increment();
	void read_saturn_ports();

	void sr_set(uint8_t data);
	void sr_ack();
	void sf_ack(bool cd_enable);
	void sf_set();
	int DectoBCD(int num);
	int m_intback_stage;
	int m_pmode;
	uint8_t m_region_code;

	required_device<nvram_device> m_mini_nvram;
	devcb_write_line m_mshres;
	devcb_write_line m_mshnmi;
	devcb_write_line m_sshres;
//  devcb_write_line m_sshnmi;
	devcb_write_line m_sndres;
	devcb_write_line m_sysres;
//  devcb_write_line m_cdres;
	devcb_write_line m_syshalt;
	devcb_write_line m_dotsel;
	devcb_read8 m_pdr1_read;
	devcb_read8 m_pdr2_read;
	devcb_write8 m_pdr1_write;
	devcb_write8 m_pdr2_write;
	devcb_write_line m_irq_line;
	saturn_control_port_device *m_ctrl1;
	saturn_control_port_device *m_ctrl2;

	required_device<screen_device> m_screen;

	void smpc_regs(address_map &map);

	DECLARE_WRITE8_MEMBER( ireg_w );
	DECLARE_WRITE8_MEMBER( command_register_w );
	DECLARE_READ8_MEMBER( oreg_r );
	DECLARE_READ8_MEMBER( status_register_r );
	DECLARE_WRITE8_MEMBER( status_flag_w );
	DECLARE_READ8_MEMBER( status_flag_r );
	DECLARE_READ8_MEMBER( pdr1_r );
	DECLARE_READ8_MEMBER( pdr2_r );
	DECLARE_WRITE8_MEMBER( pdr1_w );
	DECLARE_WRITE8_MEMBER( pdr2_w );
	DECLARE_WRITE8_MEMBER( ddr1_w );
	DECLARE_WRITE8_MEMBER( ddr2_w );
	DECLARE_WRITE8_MEMBER( iosel_w );
	DECLARE_WRITE8_MEMBER( exle_w );
};


// device type definition
DECLARE_DEVICE_TYPE(SMPC_HLE, smpc_hle_device)



//**************************************************************************
//  GLOBAL VARIABLES
//**************************************************************************


#endif // MAME_MACHINE_SMPC_HLE_H