summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/bus/spectrum/musicmachine.cpp
blob: f8eb8679bcb9a53234bd5a271e6c04673aee0126 (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
// license:BSD-3-Clause
// copyright-holders:Andrei I. Holub
/*
 * The Music Machine - MIDI and sampling expansion
 * by Ram Electronics Ltd
 */

#include "emu.h"
#include "musicmachine.h"

#include "bus/midi/midi.h"
#include "machine/6850acia.h"
#include "machine/clock.h"
#include "sound/dac.h"

#include "speaker.h"


namespace {

class spectrum_musicmachine_device  : public device_t, public device_spectrum_expansion_interface
{
public:
	// construction/destruction
	spectrum_musicmachine_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);

	void write_acia_clock(u8 data);

protected:
	// device_t implementation
	virtual void device_start() override ATTR_COLD;
	virtual void device_reset() override ATTR_COLD;
	virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;

	// device_spectrum_expansion_interface implementation
	virtual u8 iorq_r(offs_t offset) override;
	virtual void iorq_w(offs_t offset, u8 data) override;

private:
	required_device<acia6850_device> m_acia;
	required_device<dac_byte_interface> m_dac;

	bool m_irq_select;
};


void spectrum_musicmachine_device::device_add_mconfig(machine_config &config)
{
	ACIA6850(config, m_acia).txd_handler().set("mdout", FUNC(midi_port_device::write_txd));
	m_acia->irq_handler().set(DEVICE_SELF_OWNER, FUNC(spectrum_expansion_slot_device::nmi_w));
	MIDI_PORT(config, "mdin", midiin_slot, "midiin").rxd_handler().set(m_acia, FUNC(acia6850_device::write_rxd));
	MIDI_PORT(config, "mdout", midiout_slot, "midiout");
	clock_device &acia_clock(CLOCK(config, "acia_clock", 31250*16));
	acia_clock.signal_handler().set(FUNC(spectrum_musicmachine_device::write_acia_clock));

	SPEAKER(config, "speaker").front_center();
	ZN429E(config, m_dac, 0).add_route(ALL_OUTPUTS, "speaker", 0.2);
}


//**************************************************************************
//  LIVE DEVICE
//**************************************************************************

spectrum_musicmachine_device::spectrum_musicmachine_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
	device_t(mconfig, SPECTRUM_MUSICMACHINE, tag, owner, clock)
	, device_spectrum_expansion_interface(mconfig, *this)
	, m_acia(*this,"acia")
	, m_dac(*this,"dac")
{
}

//-------------------------------------------------
//  device_start - device-specific startup
//-------------------------------------------------

void spectrum_musicmachine_device::device_start()
{
	save_item(NAME(m_irq_select));
}

//-------------------------------------------------
//  device_reset - device-specific reset
//-------------------------------------------------

void spectrum_musicmachine_device::device_reset()
{
	m_irq_select = false;
}

void spectrum_musicmachine_device::write_acia_clock(u8 data)
{
	m_acia->write_txc(data);
	m_acia->write_rxc(data);
}

u8 spectrum_musicmachine_device::iorq_r(offs_t offset)
{
	u8 data = (offset & 1) ? m_slot->fb_r() : 0xff;

	switch (offset & 0xff)
	{
		case 0x7f:
			if ((offset & 0x3ff) == 0x27f)
				data = m_acia->status_r();
			else if ((offset & 0x3ff) == 0x37f)
				data = m_acia->data_r();
			break;
		case 0xbf:
			// TODO ADC_READ
			break;
		case 0xdf:
			// TODO Strobe: ADC_START
			break;
	}

	return data;
}

void spectrum_musicmachine_device::iorq_w(offs_t offset, u8 data)
{
	switch (offset & 0xff)
	{
		case 0x5f:
			m_irq_select = data & 1;
			break;
		case 0x7f:
			if ((offset & 0x3ff) == 0x07f)
				m_acia->control_w(data);
			else if ((offset & 0x3ff) == 0x17f)
				m_acia->data_w(data);
			break;
		case 0x9f:
			m_dac->write(data);
			break;
		case 0xdf:
			// TODO Strobe: ADC_START
			break;
	}
}

} // anonymous namespace


//**************************************************************************
//  DEVICE DEFINITIONS
//**************************************************************************

DEFINE_DEVICE_TYPE_PRIVATE(SPECTRUM_MUSICMACHINE, device_spectrum_expansion_interface, spectrum_musicmachine_device, "spectrummusic", "The Music Machine (ZX)")