1/* This file is part of the Dreamcast function library.
2 * Please see libdream.c for further details.
3 *
4 * (c)2000 Dan Potter
5 * modify BERO
6 */
7#include "aica.h"
8
9#include <arch/irq.h>
10#include <dc/spu.h>
11
12/* #define dc_snd_base ((volatile unsigned char *)0x00800000) */ /* arm side */
13#define dc_snd_base ((volatile unsigned char *)0xa0700000) /* dc side */
14
15/* Some convienence macros */
16#define	SNDREGADDR(x)	(0xa0700000 + (x))
17#define	CHNREGADDR(ch,x)	SNDREGADDR(0x80*(ch)+(x))
18
19
20#define SNDREG32(x)	(*(volatile unsigned long *)SNDREGADDR(x))
21#define SNDREG8(x)	(*(volatile unsigned char *)SNDREGADDR(x))
22#define CHNREG32(ch, x) (*(volatile unsigned long *)CHNREGADDR(ch,x))
23#define CHNREG8(ch, x)	(*(volatile unsigned long *)CHNREGADDR(ch,x))
24
25#define G2_LOCK(OLD) \
26	do { \
27		if (!irq_inside_int()) \
28			OLD = irq_disable(); \
29		/* suspend any G2 DMA here... */ \
30		while((*(volatile unsigned int *)0xa05f688c) & 0x20) \
31			; \
32	} while(0)
33
34#define G2_UNLOCK(OLD) \
35	do { \
36		/* resume any G2 DMA here... */ \
37		if (!irq_inside_int()) \
38			irq_restore(OLD); \
39	} while(0)
40
41
42void aica_init() {
43	int i, j, old = 0;
44
45	/* Initialize AICA channels */
46	G2_LOCK(old);
47	SNDREG32(0x2800) = 0x0000;
48
49	for (i=0; i<64; i++) {
50		for (j=0; j<0x80; j+=4) {
51			if ((j&31)==0) g2_fifo_wait();
52			CHNREG32(i, j) = 0;
53		}
54		g2_fifo_wait();
55		CHNREG32(i,0) = 0x8000;
56		CHNREG32(i,20) = 0x1f;
57	}
58
59	SNDREG32(0x2800) = 0x000f;
60	g2_fifo_wait();
61	G2_UNLOCK(old);
62}
63
64/* Translates a volume from linear form to logarithmic form (required by
65   the AICA chip */
66/* int logs[] = {
67
680, 40, 50, 58, 63, 68, 73, 77, 80, 83, 86, 89, 92, 94, 97, 99, 101, 103,
69105, 107, 109, 111, 112, 114, 116, 117, 119, 120, 122, 123, 125, 126, 127,
70129, 130, 131, 133, 134, 135, 136, 137, 139, 140, 141, 142, 143, 144, 145,
71146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 156, 157, 158, 159,
72160, 161, 162, 162, 163, 164, 165, 166, 166, 167, 168, 169, 170, 170, 171,
73172, 172, 173, 174, 175, 175, 176, 177, 177, 178, 179, 180, 180, 181, 182,
74182, 183, 183, 184, 185, 185, 186, 187, 187, 188, 188, 189, 190, 190, 191,
75191, 192, 193, 193, 194, 194, 195, 196, 196, 197, 197, 198, 198, 199, 199,
76200, 201, 201, 202, 202, 203, 203, 204, 204, 205, 205, 206, 206, 207, 207,
77208, 208, 209, 209, 210, 210, 211, 211, 212, 212, 213, 213, 214, 214, 215,
78215, 216, 216, 217, 217, 217, 218, 218, 219, 219, 220, 220, 221, 221, 222,
79222, 222, 223, 223, 224, 224, 225, 225, 225, 226, 226, 227, 227, 228, 228,
80228, 229, 229, 230, 230, 230, 231, 231, 232, 232, 232, 233, 233, 234, 234,
81234, 235, 235, 236, 236, 236, 237, 237, 238, 238, 238, 239, 239, 240, 240,
82240, 241, 241, 241, 242, 242, 243, 243, 243, 244, 244, 244, 245, 245, 245,
83246, 246, 247, 247, 247, 248, 248, 248, 249, 249, 249, 250, 250, 250, 251,
84251, 251, 252, 252, 252, 253, 253, 253, 254, 254, 254, 255
85
86}; */
87
88const static unsigned char logs[] = {
89	0, 15, 22, 27, 31, 35, 39, 42, 45, 47, 50, 52, 55, 57, 59, 61,
90	63, 65, 67, 69, 71, 73, 74, 76, 78, 79, 81, 82, 84, 85, 87, 88,
91	90, 91, 92, 94, 95, 96, 98, 99, 100, 102, 103, 104, 105, 106,
92	108, 109, 110, 111, 112, 113, 114, 116, 117, 118, 119, 120, 121,
93	122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134,
94	135, 136, 137, 138, 138, 139, 140, 141, 142, 143, 144, 145, 146,
95	146, 147, 148, 149, 150, 151, 152, 152, 153, 154, 155, 156, 156,
96	157, 158, 159, 160, 160, 161, 162, 163, 164, 164, 165, 166, 167,
97	167, 168, 169, 170, 170, 171, 172, 173, 173, 174, 175, 176, 176,
98	177, 178, 178, 179, 180, 181, 181, 182, 183, 183, 184, 185, 185,
99	186, 187, 187, 188, 189, 189, 190, 191, 191, 192, 193, 193, 194,
100	195, 195, 196, 197, 197, 198, 199, 199, 200, 200, 201, 202, 202,
101	203, 204, 204, 205, 205, 206, 207, 207, 208, 209, 209, 210, 210,
102	211, 212, 212, 213, 213, 214, 215, 215, 216, 216, 217, 217, 218,
103	219, 219, 220, 220, 221, 221, 222, 223, 223, 224, 224, 225, 225,
104	226, 227, 227, 228, 228, 229, 229, 230, 230, 231, 232, 232, 233,
105	233, 234, 234, 235, 235, 236, 236, 237, 237, 238, 239, 239, 240,
106	240, 241, 241, 242, 242, 243, 243, 244, 244, 245, 245, 246, 246,
107	247, 247, 248, 248, 249, 249, 250, 250, 251, 251, 252, 252, 253, 254, 255
108};
109
110/* For the moment this is going to have to suffice, until we really
111   figure out what these mean. */
112#define AICA_PAN(x) ((x)==0x80?(0):((x)<0x80?(0x1f):(0x0f)))
113#define AICA_VOL(x) (0xff - logs[128 + (((x) & 0xff) / 2)])
114//#define AICA_VOL(x) (0xff - logs[x&255])
115
116static inline unsigned  AICA_FREQ(unsigned freq)	{
117	unsigned long freq_lo, freq_base = 5644800;
118	int freq_hi = 7;
119
120	/* Need to convert frequency to floating point format
121	   (freq_hi is exponent, freq_lo is mantissa)
122	   Formula is ferq = 44100*2^freq_hi*(1+freq_lo/1024) */
123	while (freq < freq_base && freq_hi > -8) {
124		freq_base >>= 1;
125		--freq_hi;
126	}
127	while (freq < freq_base && freq_hi > -8) {
128		freq_base >>= 1;
129		freq_hi--;
130	}
131	freq_lo = (freq<<10) / freq_base;
132	return (freq_hi << 11) | (freq_lo & 1023);
133}
134
135/* Sets up a sound channel completely. This is generally good if you want
136   a quick and dirty way to play notes. If you want a more comprehensive
137   set of routines (more like PC wavetable cards) see below.
138
139   ch is the channel to play on (0 - 63)
140   smpptr is the pointer to the sound data; if you're running off the
141     SH4, then this ought to be (ptr - 0xa0800000); otherwise it's just
142     ptr. Basically, it's an offset into sound ram.
143   mode is one of the mode constants (16 bit, 8 bit, ADPCM)
144   nsamp is the number of samples to play (not number of bytes!)
145   freq is the sampling rate of the sound
146   vol is the volume, 0 to 0xff (0xff is louder)
147   pan is a panning constant -- 0 is left, 128 is center, 255 is right.
148
149   This routine (and the similar ones) owe a lot to Marcus' sound example --
150   I hadn't gotten quite this far into dissecting the individual regs yet. */
151void aica_play(int ch,int mode,unsigned long smpptr,int loopst,int loopend,int freq,int vol,int pan,int loopflag) {
152/*	int i;
153*/
154	int val;
155	int old = 0;
156
157	/* Stop the channel (if it's already playing) */
158	aica_stop(ch);
159	/* doesn't seem to be needed, but it's here just in case */
160/*
161	for (i=0; i<256; i++) {
162		asm("nop");
163		asm("nop");
164		asm("nop");
165		asm("nop");
166	}
167*/
168	G2_LOCK(old);
169	/* Envelope setup. The first of these is the loop point,
170	   e.g., where the sample starts over when it loops. The second
171	   is the loop end. This is the full length of the sample when
172	   you are not looping, or the loop end point when you are (though
173	   storing more than that is a waste of memory if you're not doing
174	   volume enveloping). */
175	CHNREG32(ch, 8) = loopst & 0xffff;
176	CHNREG32(ch, 12) = loopend & 0xffff;
177
178	/* Write resulting values */
179	CHNREG32(ch, 24) = AICA_FREQ(freq);
180
181	/* Set volume, pan, and some other things that we don't know what
182	   they do =) */
183	CHNREG32(ch, 36) = AICA_PAN(pan) | (0xf<<8);
184	/* Convert the incoming volume and pan into hardware values */
185	/* Vol starts at zero so we can ramp */
186	vol = AICA_VOL(vol);
187	CHNREG32(ch, 40) = 0x24 | (vol<<8);
188	/* Convert the incoming volume and pan into hardware values */
189	/* Vol starts at zero so we can ramp */
190
191	/* If we supported volume envelopes (which we don't yet) then
192	   this value would set that up. The top 4 bits determine the
193	   envelope speed. f is the fastest, 1 is the slowest, and 0
194	   seems to be an invalid value and does weird things). The
195	   default (below) sets it into normal mode (play and terminate/loop).
196	CHNREG32(ch, 16) = 0xf010;
197	*/
198	CHNREG32(ch, 16) = 0x1f;	/* No volume envelope */
199
200
201	/* Set sample format, buffer address, and looping control. If
202	   0x0200 mask is set on reg 0, the sample loops infinitely. If
203	   it's not set, the sample plays once and terminates. We'll
204	   also set the bits to start playback here. */
205	CHNREG32(ch, 4) = smpptr & 0xffff;
206	val = 0xc000 | 0x0000 | (mode<<7) | (smpptr >> 16);
207	if (loopflag) val|=0x200;
208
209	CHNREG32(ch, 0) = val;
210
211	G2_UNLOCK(old);
212
213	/* Enable playback */
214	/* CHNREG32(ch, 0) |= 0xc000; */
215	g2_fifo_wait();
216
217#if 0
218	for (i=0xff; i>=vol; i--) {
219		if ((i&7)==0) g2_fifo_wait();
220		CHNREG32(ch, 40) =  0x24 | (i<<8);;
221	}
222
223	g2_fifo_wait();
224#endif
225}
226
227/* Stop the sound on a given channel */
228void aica_stop(int ch) {
229	g2_write_32(CHNREGADDR(ch, 0),(g2_read_32(CHNREGADDR(ch, 0)) & ~0x4000) | 0x8000);
230	g2_fifo_wait();
231}
232
233
234/* The rest of these routines can change the channel in mid-stride so you
235   can do things like vibrato and panning effects. */
236
237/* Set channel volume */
238void aica_vol(int ch,int vol) {
239//	g2_write_8(CHNREGADDR(ch, 41),AICA_VOL(vol));
240	g2_write_32(CHNREGADDR(ch, 40),(g2_read_32(CHNREGADDR(ch, 40))&0xffff00ff)|(AICA_VOL(vol)<<8) );
241	g2_fifo_wait();
242}
243
244/* Set channel pan */
245void aica_pan(int ch,int pan) {
246//	g2_write_8(CHNREGADDR(ch, 36),AICA_PAN(pan));
247	g2_write_32(CHNREGADDR(ch, 36),(g2_read_32(CHNREGADDR(ch, 36))&0xffffff00)|(AICA_PAN(pan)) );
248	g2_fifo_wait();
249}
250
251/* Set channel frequency */
252void aica_freq(int ch,int freq) {
253	g2_write_32(CHNREGADDR(ch, 24),AICA_FREQ(freq));
254	g2_fifo_wait();
255}
256
257/* Get channel position */
258int aica_get_pos(int ch) {
259#if 1
260	/* Observe channel ch */
261	g2_write_32(SNDREGADDR(0x280c),(g2_read_32(SNDREGADDR(0x280c))&0xffff00ff) | (ch<<8));
262	g2_fifo_wait();
263	/* Update position counters */
264	return g2_read_32(SNDREGADDR(0x2814)) & 0xffff;
265#else
266	/* Observe channel ch */
267	g2_write_8(SNDREGADDR(0x280d),ch);
268	/* Update position counters */
269	return g2_read_32(SNDREGADDR(0x2814)) & 0xffff;
270#endif
271}
272