summaryrefslogtreecommitdiffstats
path: root/src/devices/machine/68340.h
blob: fcec19e453d98ce30590025c17363fb443899746 (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
// license:BSD-3-Clause
// copyright-holders:David Haywood
/* 68340 */
#ifndef MAME_MACHINE_68340_H
#define MAME_MACHINE_68340_H

#pragma once

#include "cpu/m68000/m68000.h"

#include "68340sim.h"
#include "68340dma.h"
#include "68340ser.h"
#include "68340tmu.h"

//**************************************************************************
//  INTERFACE CONFIGURATION MACROS
//**************************************************************************
#define MCFG_MC68340_PA_INPUT_CB(_devcb) \
	devcb = &downcast<m68340_cpu_device &>(*device).set_pa_in_callback(DEVCB_##_devcb);

#define MCFG_MC68340_PA_OUTPUT_CB(_devcb) \
	devcb = &downcast<m68340_cpu_device &>(*device).set_pa_out_callback(DEVCB_##_devcb);

#define MCFG_MC68340_PB_INPUT_CB(_devcb) \
	devcb = &downcast<m68340_cpu_device &>(*device).set_pb_in_callback(DEVCB_##_devcb);

#define MCFG_MC68340_PB_OUTPUT_CB(_devcb) \
	devcb = &downcast<m68340_cpu_device &>(*device).set_pb_out_callback(DEVCB_##_devcb);

#define MCFG_MC68340_ADD_CRYSTAL(_crystal) \
	downcast<m68340_cpu_device &>(*device).set_crystal(_crystal);

#define MCFG_MC68340_TOUT1_OUTPUT_CB(_devcb) \
	devcb = &downcast<m68340_cpu_device &>(*device).set_tout1_out_callback(DEVCB_##_devcb);

#define MCFG_MC68340_TIN1_INPUT_CB(_devcb) \
	devcb = &downcast<m68340_cpu_device &>(*device).set_tin1_out_callback(DEVCB_##_devcb);

#define MCFG_MC68340_TGATE1_INPUT_CB(_devcb) \
	devcb = &downcast<m68340_cpu_device &>(*device).set_tgate1_out_callback(DEVCB_##_devcb);

#define MCFG_MC68340_TOUT2_OUTPUT_CB(_devcb) \
	devcb = &downcast<m68340_cpu_device &>(*device).set_tout2_out_callback(DEVCB_##_devcb);

#define MCFG_MC68340_TIN2_INPUT_CB(_devcb) \
	devcb = &downcast<m68340_cpu_device &>(*device).set_tin2_out_callback(DEVCB_##_devcb);

#define MCFG_MC68340_TGATE2_INPUT_CB(_devcb) \
	devcb = &downcast<m68340_cpu_device &>(*device).set_tgate2_out_callback(DEVCB_##_devcb);

class m68340_cpu_device : public fscpu32_device
{
	friend class mc68340_serial_module_device;
	friend class mc68340_timer_module_device;

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

	template <class Object> devcb_base &set_pa_in_callback(Object &&cb){ return m_pa_in_cb.set_callback (std::forward<Object>(cb)); }
	template <class Object> devcb_base &set_pa_out_callback(Object &&cb){ return m_pa_out_cb.set_callback (std::forward<Object>(cb)); }
	template <class Object> devcb_base &set_pb_in_callback(Object &&cb){ return m_pb_in_cb.set_callback (std::forward<Object>(cb)); }
	template <class Object> devcb_base &set_pb_out_callback(Object &&cb){ return m_pb_out_cb.set_callback (std::forward<Object>(cb)); }

	template <class Object> devcb_base &set_tout1_out_callback(Object &&cb){ return m_timer1->m_tout_out_cb.set_callback (std::forward<Object>(cb)); }
	template <class Object> devcb_base &set_tin1_in_callback(Object &&cb)  { return m_timer1->m_tin_in_cb.set_callback (std::forward<Object>(cb)); }
	template <class Object> devcb_base &set_tgate1_in_callback(Object &&cb){ return m_timer1->m_tgate_in_cb.set_callback (std::forward<Object>(cb)); }
	template <class Object> devcb_base &set_tout2_out_callback(Object &&cb){ return m_timer2->m_tout_out_cb.set_callback (std::forward<Object>(cb)); }
	template <class Object> devcb_base &set_tin2_in_callback(Object &&cb)  { return m_timer2->m_tin_in_cb.set_callback (std::forward<Object>(cb)); }
	template <class Object> devcb_base &set_tgate2_in_callback(Object &&cb){ return m_timer2->m_tgate_in_cb.set_callback (std::forward<Object>(cb)); }

	uint16_t get_cs(offs_t address);

	void set_crystal(const XTAL &crystal) { set_crystal(crystal.value()); }

	// Timer input methods, can be used instead of the corresponding polling MCFG callbacks
	DECLARE_WRITE_LINE_MEMBER( tin1_w )  { m_timer1->tin_w(state);  }
	DECLARE_WRITE_LINE_MEMBER( tgate1_w ){ m_timer1->tgate_w(state); }
	DECLARE_WRITE_LINE_MEMBER( tin2_w )  { m_timer2->tin_w(state);  }
	DECLARE_WRITE_LINE_MEMBER( tgate2_w ){ m_timer2->tgate_w(state); }

protected:
	virtual void device_start() override;
	virtual void device_reset() override;
	virtual void device_add_mconfig(machine_config &config) override;

private:
	required_device<mc68340_serial_module_device> m_serial;
	required_device<mc68340_timer_module_device> m_timer1;
	required_device<mc68340_timer_module_device> m_timer2;

	TIMER_CALLBACK_MEMBER(periodic_interrupt_timer_callback);

	void start_68340_sim();
	void do_pit_irq();
	void do_tick_pit();

	int calc_cs(offs_t address) const;
	int get_timer_index(mc68340_timer_module_device *timer) { return (timer == m_timer1) ? 0 : 1; }

	int m_currentcs;
	uint32_t m_clock_mode;
	uint32_t m_modck;
	uint32_t m_crystal;
	uint32_t m_extal;

	// TODO: Support Limp mode and external clock with no PLL
	void set_crystal(int crystal)
	{
		m_crystal = crystal;
		m_clock_mode |= (m68340_sim::CLOCK_MODCK | m68340_sim::CLOCK_PLL);
	}

	READ32_MEMBER( m68340_internal_base_r );
	WRITE32_MEMBER( m68340_internal_base_w );
	READ32_MEMBER( m68340_internal_dma_r );
	WRITE32_MEMBER( m68340_internal_dma_w );
	READ16_MEMBER( m68340_internal_sim_r );
	READ8_MEMBER( m68340_internal_sim_ports_r );
	READ32_MEMBER( m68340_internal_sim_cs_r );
	WRITE16_MEMBER( m68340_internal_sim_w );
	WRITE8_MEMBER( m68340_internal_sim_ports_w );
	WRITE32_MEMBER( m68340_internal_sim_cs_w );

	// Clock/VCO setting TODO: support external clock with PLL and Limp mode
	DECLARE_WRITE_LINE_MEMBER( set_modck );
	DECLARE_WRITE_LINE_MEMBER( extal_w );

	void m68340_internal_map(address_map &map);

	/* 68340 peripheral modules */
	m68340_sim*    m_m68340SIM;
	m68340_dma*    m_m68340DMA;

	uint32_t m_m68340_base;

	emu_timer *m_irq_timer;

	devcb_write8        m_pa_out_cb;
	devcb_read8         m_pa_in_cb;
	devcb_write8        m_pb_out_cb;
	devcb_read8         m_pb_in_cb;
};

DECLARE_DEVICE_TYPE(M68340, m68340_cpu_device)

#endif // MAME_MACHINE_68340_H