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
|
// license:BSD-3-Clause
// copyright-holders:Barry Rodewald
/*
* ym3802.h - Yamaha YM3802/YM3523 MCS MIDI Communication and Service Controller
*
* * Registers:
* reg0 : IVR (read-only)
* reg1 : RGR (bit 8 = reset, bits 0-3 = register bank select)
* reg2 : ISR (read-only)
* reg3 : ICR (write-only)
* reg4-reg7 banked registers
* reg4 : IOR DMR RRR RSR TRR TSR FSR SRR GTR(L) EDR
* reg5 : IMR DCR RMR RCR TMR TCR FCR SCR GTR(H) ---
* reg6 : IER DSR AMR RDR --- TDR CCR SPR(L) MTR(L) EOR/EIR
* reg7 : --- DNR ADR --- --- --- CDR SPR(H) MTR(H) ---
*/
#ifndef DEVICES_MACHINE_YM3802_H
#define DEVICES_MACHINE_YM3802_H
#pragma once
#include <queue>
#define MCFG_YM3802_IRQ_HANDLER(_devcb) \
devcb = &downcast<ym3802_device &>(*device).set_irq_handler(DEVCB_##_devcb);
#define MCFG_YM3802_TXD_HANDLER(_devcb) \
devcb = &downcast<ym3802_device &>(*device).set_txd_handler(DEVCB_##_devcb);
class ym3802_device : public device_t, public device_serial_interface
{
public:
// construction/destruction
ym3802_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// configuration helpers
template <class Object> devcb_base &set_irq_handler(Object &&cb) { return m_irq_handler.set_callback(std::forward<Object>(cb)); }
template <class Object> devcb_base &set_txd_handler(Object &&cb) { return m_txd_handler.set_callback(std::forward<Object>(cb)); }
DECLARE_READ8_MEMBER(read);
DECLARE_WRITE8_MEMBER(write);
uint8_t vector() { return m_vector; }
protected:
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;
private:
enum
{
REG_IVR = 0, // Interrupt Vector (read only)
REG_RGR, // Register Group / System Control
REG_ISR, // Interrupt Service (read only)
REG_ICR, // Interrupt Clear (write only)
REG_IOR, // Interrupt Vector Offset Request
REG_IMR, // Interrupt Mode Control
REG_IER, // Interrupt Enable Request
REG_UNUSED1,
REG_DMR = 14, // Real Time Message Control
REG_DCR, // Real Time Message Request
REG_DSR, // FIFO IRx Data
REG_DNR, // FIFO IRx Control
REG_RRR = 24, // Rx Rate
REG_RMR, // Rx Mode
REG_AMR, // Address Hunter Maker
REG_ADR, // Address Hunter Device
REG_RSR = 34, // FIFO Rx Buffer Status
REG_RCR, // FIFO Rx Buffer Control
REG_RDR, // FIFO Rx Data
REG_UNUSED2,
REG_TRR = 44, // Tx Rate
REG_TMR, // Tx Mode
REG_UNUSED3,
REG_UNUSED4,
REG_TSR = 54, // FIFO Tx Status
REG_TCR, // FIFO Tx Control
REG_TDR, // FIFO Tx Data
REG_UNUSED5,
REG_FSR = 64, // FSK status
REG_FCR, // FSK control
REG_CCR, // Click Counter Control
REG_CDR, // Click Counter Data (7-bit)
REG_SRR = 74, // Recording Counter current value
REG_SCR, // Sequencer Control
REG_SPR_LOW, // Playback Counter (low 8-bits)
REG_SPR_HIGH, // Playback Counter (high 7-bits)
REG_GTR_LOW = 84, // General Timer (low 8-bits)
REG_GTR_HIGH, // General Timer (high 6-bits)
REG_MTR_LOW, // MIDI Clock Timer (low 8-bits)
REG_MTR_HIGH, // MIDI Clock Timer (high 6-bits)
REG_EDR = 94, // External I/O Direction
REG_EOR, // External I/O Output Data
REG_EIR, // External I/O Input Data
REG_UNUSED7,
REG_MAX = 100
};
enum
{
IRQ_MIDI_MSG = 0x01,
IRQ_CLICK = 0x02,
IRQ_MIDI_CLK = 0x02,
IRQ_PLAYBACK_COUNT = 0x04,
IRQ_RECORDING_COUNT = 0x08,
IRQ_OFFLINE = 0x10,
IRQ_BREAK = 0x10,
IRQ_FIFORX_RDY = 0x20,
IRQ_FIFOTX_EMPTY = 0x40,
IRQ_GENERAL_TIMER = 0x80
};
enum
{
TIMER_SYSTEM_CLOCK = 0x200, // CLK input - anywhere from 1MHz up to 4MHz
TIMER_TX_CLOCK,
TIMER_MIDI_CLOCK // CLKM input - usually either 1MHz or 0.5MHz, or CLKF input - usually 614.4kHz
};
void transmit_clk();
void midi_clk();
void reset_midi_timer();
void set_comms_mode();
void set_irq(uint8_t irq);
void reset_irq(uint8_t irq);
devcb_write_line m_irq_handler;
devcb_write_line m_txd_handler;
devcb_read_line m_rxd_handler;
emu_timer* m_clock_timer;
emu_timer* m_midi_timer;
emu_timer* m_midi_counter_timer;
std::vector<uint8_t> m_reg;
uint8_t m_wdr;
uint64_t m_prev_rate;
uint8_t m_irq_status;
uint16_t m_general_counter;
uint16_t m_midi_counter;
uint16_t m_midi_counter_base;
//uint8_t m_midi_counter_divider;
uint8_t m_click_counter;
uint8_t m_click_counter_base;
uint8_t m_vector;
std::queue<uint8_t> m_tx_fifo;
std::queue<uint8_t> m_rx_fifo;
std::queue<uint8_t> m_itx_fifo;
std::queue<uint8_t> m_irx_fifo;
bool m_tx_busy;
uint64_t m_clkm_rate;
uint64_t m_clkf_rate;
};
DECLARE_DEVICE_TYPE(YM3802, ym3802_device)
#endif // DEVICES_MACHINE_YM3802_H
|