symbian-qemu-0.9.1-12/libsdl-trunk/src/audio/dc/aica.c
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     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 
       
    42 void 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 
       
    68 0, 40, 50, 58, 63, 68, 73, 77, 80, 83, 86, 89, 92, 94, 97, 99, 101, 103,
       
    69 105, 107, 109, 111, 112, 114, 116, 117, 119, 120, 122, 123, 125, 126, 127,
       
    70 129, 130, 131, 133, 134, 135, 136, 137, 139, 140, 141, 142, 143, 144, 145,
       
    71 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 156, 157, 158, 159,
       
    72 160, 161, 162, 162, 163, 164, 165, 166, 166, 167, 168, 169, 170, 170, 171,
       
    73 172, 172, 173, 174, 175, 175, 176, 177, 177, 178, 179, 180, 180, 181, 182,
       
    74 182, 183, 183, 184, 185, 185, 186, 187, 187, 188, 188, 189, 190, 190, 191,
       
    75 191, 192, 193, 193, 194, 194, 195, 196, 196, 197, 197, 198, 198, 199, 199,
       
    76 200, 201, 201, 202, 202, 203, 203, 204, 204, 205, 205, 206, 206, 207, 207,
       
    77 208, 208, 209, 209, 210, 210, 211, 211, 212, 212, 213, 213, 214, 214, 215,
       
    78 215, 216, 216, 217, 217, 217, 218, 218, 219, 219, 220, 220, 221, 221, 222,
       
    79 222, 222, 223, 223, 224, 224, 225, 225, 225, 226, 226, 227, 227, 228, 228,
       
    80 228, 229, 229, 230, 230, 230, 231, 231, 232, 232, 232, 233, 233, 234, 234,
       
    81 234, 235, 235, 236, 236, 236, 237, 237, 238, 238, 238, 239, 239, 240, 240,
       
    82 240, 241, 241, 241, 242, 242, 243, 243, 243, 244, 244, 244, 245, 245, 245,
       
    83 246, 246, 247, 247, 247, 248, 248, 248, 249, 249, 249, 250, 250, 250, 251,
       
    84 251, 251, 252, 252, 252, 253, 253, 253, 254, 254, 254, 255
       
    85 
       
    86 }; */
       
    87 
       
    88 const 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 
       
   116 static 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. */
       
   151 void 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 */
       
   228 void 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 */
       
   238 void 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 */
       
   245 void 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 */
       
   252 void 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 */
       
   258 int 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 }