summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/8364_paula.h
blob: 4dbd041c93f5c5c2ed4b7fcb7f711e7c548d55bf (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
// license: BSD-3-Clause
// copyright-holders: Aaron Giles, Dirk Best
/***************************************************************************

    Commodore 8364 "Paula"

    Multi-purpose chip that is part of the Amiga chipset. The name "Paula"
    is derived from "Ports, Audio, UART and Logic". It features 4-channel
    DMA driven audio, the floppy controller, a serial receiver/transmitter,
    analog inputs and contains the interrupt controller.

                ____ ____
        D8   1 |*   u    | 48  D9
        D7   2 |         | 47  D10
        D6   3 |         | 46  D11
        D5   4 |         | 45  D12
        D4   5 |         | 44  D13
        D3   6 |         | 43  D14
        D2   7 |         | 42  D15
       GND   8 |         | 41  RXD
        D1   9 |         | 40  TXD
        D0  10 |         | 39  DKWE
      /RES  11 |         | 38  /DKWD
      DMAL  12 |         | 37  /DKRD
     /IPL0  13 |         | 36  POT1Y
     /IPL1  14 |         | 35  POT1X
     /IPL2  15 |         | 34  ANAGND
     /INT2  16 |         | 33  POT0Y
     /INT3  17 |         | 32  POT0X
     /INT6  18 |         | 31  AUDL
      RGA8  19 |         | 30  AUDR
      RGA7  20 |         | 29  CCKQ
      RGA6  21 |         | 28  CCK
      RGA5  22 |         | 27  VCC
      RGA4  23 |         | 26  RGA1
      RGA3  24 |_________| 25  RGA2

***************************************************************************/

#pragma once

#ifndef MAME_DEVICES_MACHINE_8364_PAULA_H
#define MAME_DEVICES_MACHINE_8364_PAULA_H



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

#define MCFG_PAULA_MEM_READ_CB(_devcb) \
	devcb = &paula_8364_device::set_mem_r_callback(*device, DEVCB_##_devcb);

#define MCFG_PAULA_INT_CB(_devcb) \
	devcb = &paula_8364_device::set_int_w_callback(*device, DEVCB_##_devcb);


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

// ======================> paula_8364_device

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

	// configuration
	template<class _Object> static devcb_base &set_mem_r_callback(device_t &device, _Object object)
		{ return downcast<paula_8364_device &>(device).m_mem_r.set_callback(object); }

	template<class _Object> static devcb_base &set_int_w_callback(device_t &device, _Object object)
		{ return downcast<paula_8364_device &>(device).m_int_w.set_callback(object); }

	DECLARE_READ16_MEMBER(reg_r);
	DECLARE_WRITE16_MEMBER(reg_w);

	void update();

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

	// sound stream update overrides
	virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) override;

private:
	enum
	{
		CHAN_0 = 0,
		CHAN_1 = 1,
		CHAN_2 = 2,
		CHAN_3 = 3
	};

	enum
	{
		REG_DMACONR = 0x02/2,
		REG_ADKCONR = 0x10/2,
		REG_DMACON  = 0x96/2,
		REG_INTREQ  = 0x9c/2,
		REG_ADKCON  = 0x9e/2,
		REG_AUD0LCH = 0xa0/2,  // to be moved, not part of paula
		REG_AUD0LCL = 0xa2/2,  // to be moved, not part of paula
		REG_AUD0LEN = 0xa4/2,
		REG_AUD0PER = 0xa6/2,
		REG_AUD0VOL = 0xa8/2,
		REG_AUD0DAT = 0xaa/2,
		REG_AUD1LCH = 0xb0/2,  // to be moved, not part of paula
		REG_AUD1LCL = 0xb2/2,  // to be moved, not part of paula
		REG_AUD1LEN = 0xb4/2,
		REG_AUD1PER = 0xb6/2,
		REG_AUD1VOL = 0xb8/2,
		REG_AUD1DAT = 0xba/2,
		REG_AUD2LCH = 0xc0/2,  // to be moved, not part of paula
		REG_AUD2LCL = 0xc2/2,  // to be moved, not part of paula
		REG_AUD2LEN = 0xc4/2,
		REG_AUD2PER = 0xc6/2,
		REG_AUD2VOL = 0xc8/2,
		REG_AUD2DAT = 0xca/2,
		REG_AUD3LCH = 0xd0/2,  // to be moved, not part of paula
		REG_AUD3LCL = 0xd2/2,  // to be moved, not part of paula
		REG_AUD3LEN = 0xd4/2,
		REG_AUD3PER = 0xd6/2,
		REG_AUD3VOL = 0xd8/2,
		REG_AUD3DAT = 0xda/2
	};

	static const int CLOCK_DIVIDER = 16;

	struct audio_channel
	{
		emu_timer *irq_timer;
		uint32_t curlocation;
		uint16_t curlength;
		uint16_t curticks;
		uint8_t index;
		bool dma_enabled;
		bool manualmode;
		int8_t latched;

		// custom chip registers
		uint32_t loc;  // to be moved, not part of paula
		uint16_t len;
		uint16_t per;
		uint16_t vol;
		uint16_t dat;
	};

	void dma_reload(audio_channel *chan);

	// callbacks
	devcb_read16 m_mem_r;
	devcb_write_line m_int_w;

	// internal state
	uint16_t m_dmacon;
	uint16_t m_adkcon;

	audio_channel m_channel[4];
	sound_stream *m_stream;

	TIMER_CALLBACK_MEMBER( signal_irq );
};

// device type definition
extern const device_type PAULA_8364;

#endif // MAME_DEVICES_MACHINE_8364_PAULA_H