src/audio/dc/aica.c
changeset 1895 c121d94672cb
parent 1461 11134dc42da8
equal deleted inserted replaced
1894:c69cee13dd76 1895:c121d94672cb
     7 #include "aica.h"
     7 #include "aica.h"
     8 
     8 
     9 #include <arch/irq.h>
     9 #include <arch/irq.h>
    10 #include <dc/spu.h>
    10 #include <dc/spu.h>
    11 
    11 
    12 /* #define dc_snd_base ((volatile unsigned char *)0x00800000) */ /* arm side */
    12 #if 0
    13 #define dc_snd_base ((volatile unsigned char *)0xa0700000) /* dc side */
    13 #define dc_snd_base ((volatile unsigned char *)0x00800000)      /* arm side */
       
    14 #endif
       
    15 #define dc_snd_base ((volatile unsigned char *)0xa0700000)      /* dc side */
    14 
    16 
    15 /* Some convienence macros */
    17 /* Some convienence macros */
    16 #define	SNDREGADDR(x)	(0xa0700000 + (x))
    18 #define	SNDREGADDR(x)	(0xa0700000 + (x))
    17 #define	CHNREGADDR(ch,x)	SNDREGADDR(0x80*(ch)+(x))
    19 #define	CHNREGADDR(ch,x)	SNDREGADDR(0x80*(ch)+(x))
    18 
    20 
    37 		if (!irq_inside_int()) \
    39 		if (!irq_inside_int()) \
    38 			irq_restore(OLD); \
    40 			irq_restore(OLD); \
    39 	} while(0)
    41 	} while(0)
    40 
    42 
    41 
    43 
    42 void aica_init() {
    44 void
    43 	int i, j, old = 0;
    45 aica_init()
    44 	
    46 {
    45 	/* Initialize AICA channels */	
    47     int i, j, old = 0;
    46 	G2_LOCK(old);
    48 
    47 	SNDREG32(0x2800) = 0x0000;
    49     /* Initialize AICA channels */
    48 	
    50     G2_LOCK(old);
    49 	for (i=0; i<64; i++) {
    51     SNDREG32(0x2800) = 0x0000;
    50 		for (j=0; j<0x80; j+=4) {
    52 
    51 			if ((j&31)==0) g2_fifo_wait();
    53     for (i = 0; i < 64; i++) {
    52 			CHNREG32(i, j) = 0;
    54         for (j = 0; j < 0x80; j += 4) {
    53 		}
    55             if ((j & 31) == 0)
    54 		g2_fifo_wait();
    56                 g2_fifo_wait();
    55 		CHNREG32(i,0) = 0x8000;
    57             CHNREG32(i, j) = 0;
    56 		CHNREG32(i,20) = 0x1f;
    58         }
    57 	}
    59         g2_fifo_wait();
    58 
    60         CHNREG32(i, 0) = 0x8000;
    59 	SNDREG32(0x2800) = 0x000f;
    61         CHNREG32(i, 20) = 0x1f;
    60 	g2_fifo_wait();
    62     }
    61 	G2_UNLOCK(old);
    63 
       
    64     SNDREG32(0x2800) = 0x000f;
       
    65     g2_fifo_wait();
       
    66     G2_UNLOCK(old);
    62 }
    67 }
    63 
    68 
    64 /* Translates a volume from linear form to logarithmic form (required by
    69 /* Translates a volume from linear form to logarithmic form (required by
    65    the AICA chip */
    70    the AICA chip */
    66 /* int logs[] = {
    71 /* int logs[] = {
    84 251, 251, 252, 252, 252, 253, 253, 253, 254, 254, 254, 255
    89 251, 251, 252, 252, 252, 253, 253, 253, 254, 254, 254, 255
    85 
    90 
    86 }; */
    91 }; */
    87 
    92 
    88 const static unsigned char logs[] = {
    93 const static unsigned char logs[] = {
    89 	0, 15, 22, 27, 31, 35, 39, 42, 45, 47, 50, 52, 55, 57, 59, 61,
    94     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,
    95     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,
    96     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,
    97     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,
    98     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,
    99     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,
   100     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,
   101     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,
   102     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,
   103     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,
   104     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,
   105     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,
   106     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,
   107     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,
   108     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,
   109     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,
   110     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,
   111     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
   112     247, 247, 248, 248, 249, 249, 250, 250, 251, 251, 252, 252, 253, 254, 255
   108 };
   113 };
   109 
   114 
   110 /* For the moment this is going to have to suffice, until we really
   115 /* For the moment this is going to have to suffice, until we really
   111    figure out what these mean. */
   116    figure out what these mean. */
   112 #define AICA_PAN(x) ((x)==0x80?(0):((x)<0x80?(0x1f):(0x0f)))
   117 #define AICA_PAN(x) ((x)==0x80?(0):((x)<0x80?(0x1f):(0x0f)))
   113 #define AICA_VOL(x) (0xff - logs[128 + (((x) & 0xff) / 2)])
   118 #define AICA_VOL(x) (0xff - logs[128 + (((x) & 0xff) / 2)])
   114 //#define AICA_VOL(x) (0xff - logs[x&255])
   119 //#define AICA_VOL(x) (0xff - logs[x&255])
   115 
   120 
   116 static inline unsigned  AICA_FREQ(unsigned freq)	{
   121 static inline unsigned
   117 	unsigned long freq_lo, freq_base = 5644800;
   122 AICA_FREQ(unsigned freq)
   118 	int freq_hi = 7;
   123 {
   119 
   124     unsigned long freq_lo, freq_base = 5644800;
   120 	/* Need to convert frequency to floating point format
   125     int freq_hi = 7;
   121 	   (freq_hi is exponent, freq_lo is mantissa)
   126 
   122 	   Formula is ferq = 44100*2^freq_hi*(1+freq_lo/1024) */
   127     /* Need to convert frequency to floating point format
   123 	while (freq < freq_base && freq_hi > -8) {
   128        (freq_hi is exponent, freq_lo is mantissa)
   124 		freq_base >>= 1;
   129        Formula is ferq = 44100*2^freq_hi*(1+freq_lo/1024) */
   125 		--freq_hi;
   130     while (freq < freq_base && freq_hi > -8) {
   126 	}
   131         freq_base >>= 1;
   127 	while (freq < freq_base && freq_hi > -8) {
   132         --freq_hi;
   128 		freq_base >>= 1;
   133     }
   129 		freq_hi--;
   134     while (freq < freq_base && freq_hi > -8) {
   130 	}
   135         freq_base >>= 1;
   131 	freq_lo = (freq<<10) / freq_base;
   136         freq_hi--;
   132 	return (freq_hi << 11) | (freq_lo & 1023);
   137     }
       
   138     freq_lo = (freq << 10) / freq_base;
       
   139     return (freq_hi << 11) | (freq_lo & 1023);
   133 }
   140 }
   134 
   141 
   135 /* Sets up a sound channel completely. This is generally good if you want
   142 /* 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
   143    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.
   144    set of routines (more like PC wavetable cards) see below.
   146    vol is the volume, 0 to 0xff (0xff is louder)
   153    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.
   154    pan is a panning constant -- 0 is left, 128 is center, 255 is right.
   148 
   155 
   149    This routine (and the similar ones) owe a lot to Marcus' sound example -- 
   156    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. */
   157    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) {
   158 void
       
   159 aica_play(int ch, int mode, unsigned long smpptr, int loopst, int loopend,
       
   160           int freq, int vol, int pan, int loopflag)
       
   161 {
   152 /*	int i;
   162 /*	int i;
   153 */
   163 */
   154 	int val;
   164     int val;
   155 	int old = 0;
   165     int old = 0;
   156 
   166 
   157 	/* Stop the channel (if it's already playing) */
   167     /* Stop the channel (if it's already playing) */
   158 	aica_stop(ch);
   168     aica_stop(ch);
   159 	/* doesn't seem to be needed, but it's here just in case */
   169     /* doesn't seem to be needed, but it's here just in case */
   160 /*
   170 /*
   161 	for (i=0; i<256; i++) {
   171 	for (i=0; i<256; i++) {
   162 		asm("nop");
   172 		asm("nop");
   163 		asm("nop");
   173 		asm("nop");
   164 		asm("nop");
   174 		asm("nop");
   165 		asm("nop");
   175 		asm("nop");
   166 	}
   176 	}
   167 */
   177 */
   168 	G2_LOCK(old);
   178     G2_LOCK(old);
   169 	/* Envelope setup. The first of these is the loop point,
   179     /* Envelope setup. The first of these is the loop point,
   170 	   e.g., where the sample starts over when it loops. The second
   180        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
   181        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
   182        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
   183        storing more than that is a waste of memory if you're not doing
   174 	   volume enveloping). */
   184        volume enveloping). */
   175 	CHNREG32(ch, 8) = loopst & 0xffff;
   185     CHNREG32(ch, 8) = loopst & 0xffff;
   176 	CHNREG32(ch, 12) = loopend & 0xffff;
   186     CHNREG32(ch, 12) = loopend & 0xffff;
   177 	
   187 
   178 	/* Write resulting values */
   188     /* Write resulting values */
   179 	CHNREG32(ch, 24) = AICA_FREQ(freq);
   189     CHNREG32(ch, 24) = AICA_FREQ(freq);
   180 	
   190 
   181 	/* Set volume, pan, and some other things that we don't know what
   191     /* Set volume, pan, and some other things that we don't know what
   182 	   they do =) */
   192        they do =) */
   183 	CHNREG32(ch, 36) = AICA_PAN(pan) | (0xf<<8);
   193     CHNREG32(ch, 36) = AICA_PAN(pan) | (0xf << 8);
   184 	/* Convert the incoming volume and pan into hardware values */
   194     /* Convert the incoming volume and pan into hardware values */
   185 	/* Vol starts at zero so we can ramp */
   195     /* Vol starts at zero so we can ramp */
   186 	vol = AICA_VOL(vol);
   196     vol = AICA_VOL(vol);
   187 	CHNREG32(ch, 40) = 0x24 | (vol<<8);
   197     CHNREG32(ch, 40) = 0x24 | (vol << 8);
   188 	/* Convert the incoming volume and pan into hardware values */
   198     /* Convert the incoming volume and pan into hardware values */
   189 	/* Vol starts at zero so we can ramp */
   199     /* Vol starts at zero so we can ramp */
   190 
   200 
   191 	/* If we supported volume envelopes (which we don't yet) then
   201     /* If we supported volume envelopes (which we don't yet) then
   192 	   this value would set that up. The top 4 bits determine the
   202        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
   203        envelope speed. f is the fastest, 1 is the slowest, and 0
   194 	   seems to be an invalid value and does weird things). The
   204        seems to be an invalid value and does weird things). The
   195 	   default (below) sets it into normal mode (play and terminate/loop).
   205        default (below) sets it into normal mode (play and terminate/loop).
   196 	CHNREG32(ch, 16) = 0xf010;
   206        CHNREG32(ch, 16) = 0xf010;
   197 	*/
   207      */
   198 	CHNREG32(ch, 16) = 0x1f;	/* No volume envelope */
   208     CHNREG32(ch, 16) = 0x1f;    /* No volume envelope */
   199 	
   209 
   200 	
   210 
   201 	/* Set sample format, buffer address, and looping control. If
   211     /* Set sample format, buffer address, and looping control. If
   202 	   0x0200 mask is set on reg 0, the sample loops infinitely. If
   212        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
   213        it's not set, the sample plays once and terminates. We'll
   204 	   also set the bits to start playback here. */
   214        also set the bits to start playback here. */
   205 	CHNREG32(ch, 4) = smpptr & 0xffff;
   215     CHNREG32(ch, 4) = smpptr & 0xffff;
   206 	val = 0xc000 | 0x0000 | (mode<<7) | (smpptr >> 16);
   216     val = 0xc000 | 0x0000 | (mode << 7) | (smpptr >> 16);
   207 	if (loopflag) val|=0x200;
   217     if (loopflag)
   208 	
   218         val |= 0x200;
   209 	CHNREG32(ch, 0) = val;
   219 
   210 	
   220     CHNREG32(ch, 0) = val;
   211 	G2_UNLOCK(old);
   221 
   212 
   222     G2_UNLOCK(old);
   213 	/* Enable playback */
   223 
   214 	/* CHNREG32(ch, 0) |= 0xc000; */
   224     /* Enable playback */
   215 	g2_fifo_wait();
   225     /* CHNREG32(ch, 0) |= 0xc000; */
       
   226     g2_fifo_wait();
   216 
   227 
   217 #if 0
   228 #if 0
   218 	for (i=0xff; i>=vol; i--) {
   229     for (i = 0xff; i >= vol; i--) {
   219 		if ((i&7)==0) g2_fifo_wait();
   230         if ((i & 7) == 0)
   220 		CHNREG32(ch, 40) =  0x24 | (i<<8);;
   231             g2_fifo_wait();
   221 	}
   232         CHNREG32(ch, 40) = 0x24 | (i << 8);;
   222 
   233     }
   223 	g2_fifo_wait();
   234 
       
   235     g2_fifo_wait();
   224 #endif
   236 #endif
   225 }
   237 }
   226 
   238 
   227 /* Stop the sound on a given channel */
   239 /* Stop the sound on a given channel */
   228 void aica_stop(int ch) {
   240 void
   229 	g2_write_32(CHNREGADDR(ch, 0),(g2_read_32(CHNREGADDR(ch, 0)) & ~0x4000) | 0x8000);
   241 aica_stop(int ch)
   230 	g2_fifo_wait();
   242 {
       
   243     g2_write_32(CHNREGADDR(ch, 0),
       
   244                 (g2_read_32(CHNREGADDR(ch, 0)) & ~0x4000) | 0x8000);
       
   245     g2_fifo_wait();
   231 }
   246 }
   232 
   247 
   233 
   248 
   234 /* The rest of these routines can change the channel in mid-stride so you
   249 /* The rest of these routines can change the channel in mid-stride so you
   235    can do things like vibrato and panning effects. */
   250    can do things like vibrato and panning effects. */
   236    
   251 
   237 /* Set channel volume */
   252 /* Set channel volume */
   238 void aica_vol(int ch,int vol) {
   253 void
   239 //	g2_write_8(CHNREGADDR(ch, 41),AICA_VOL(vol));
   254 aica_vol(int ch, int vol)
   240 	g2_write_32(CHNREGADDR(ch, 40),(g2_read_32(CHNREGADDR(ch, 40))&0xffff00ff)|(AICA_VOL(vol)<<8) );
   255 {
   241 	g2_fifo_wait();
   256 //      g2_write_8(CHNREGADDR(ch, 41),AICA_VOL(vol));
       
   257     g2_write_32(CHNREGADDR(ch, 40),
       
   258                 (g2_read_32(CHNREGADDR(ch, 40)) & 0xffff00ff) |
       
   259                 (AICA_VOL(vol) << 8));
       
   260     g2_fifo_wait();
   242 }
   261 }
   243 
   262 
   244 /* Set channel pan */
   263 /* Set channel pan */
   245 void aica_pan(int ch,int pan) {
   264 void
   246 //	g2_write_8(CHNREGADDR(ch, 36),AICA_PAN(pan));
   265 aica_pan(int ch, int pan)
   247 	g2_write_32(CHNREGADDR(ch, 36),(g2_read_32(CHNREGADDR(ch, 36))&0xffffff00)|(AICA_PAN(pan)) );
   266 {
   248 	g2_fifo_wait();
   267 //      g2_write_8(CHNREGADDR(ch, 36),AICA_PAN(pan));
       
   268     g2_write_32(CHNREGADDR(ch, 36),
       
   269                 (g2_read_32(CHNREGADDR(ch, 36)) & 0xffffff00) |
       
   270                 (AICA_PAN(pan)));
       
   271     g2_fifo_wait();
   249 }
   272 }
   250 
   273 
   251 /* Set channel frequency */
   274 /* Set channel frequency */
   252 void aica_freq(int ch,int freq) {
   275 void
   253 	g2_write_32(CHNREGADDR(ch, 24),AICA_FREQ(freq));
   276 aica_freq(int ch, int freq)
   254 	g2_fifo_wait();
   277 {
       
   278     g2_write_32(CHNREGADDR(ch, 24), AICA_FREQ(freq));
       
   279     g2_fifo_wait();
   255 }
   280 }
   256 
   281 
   257 /* Get channel position */
   282 /* Get channel position */
   258 int aica_get_pos(int ch) {
   283 int
       
   284 aica_get_pos(int ch)
       
   285 {
   259 #if 1
   286 #if 1
   260 	/* Observe channel ch */
   287     /* Observe channel ch */
   261 	g2_write_32(SNDREGADDR(0x280c),(g2_read_32(SNDREGADDR(0x280c))&0xffff00ff) | (ch<<8));
   288     g2_write_32(SNDREGADDR(0x280c),
   262 	g2_fifo_wait();
   289                 (g2_read_32(SNDREGADDR(0x280c)) & 0xffff00ff) | (ch << 8));
   263 	/* Update position counters */
   290     g2_fifo_wait();
   264 	return g2_read_32(SNDREGADDR(0x2814)) & 0xffff;
   291     /* Update position counters */
       
   292     return g2_read_32(SNDREGADDR(0x2814)) & 0xffff;
   265 #else
   293 #else
   266 	/* Observe channel ch */
   294     /* Observe channel ch */
   267 	g2_write_8(SNDREGADDR(0x280d),ch);
   295     g2_write_8(SNDREGADDR(0x280d), ch);
   268 	/* Update position counters */
   296     /* Update position counters */
   269 	return g2_read_32(SNDREGADDR(0x2814)) & 0xffff;
   297     return g2_read_32(SNDREGADDR(0x2814)) & 0xffff;
   270 #endif
   298 #endif
   271 }
   299 }
       
   300 
       
   301 /* vi: set ts=4 sw=4 expandtab: */