comparison src/audio/dc/aica.c @ 1895:c121d94672cb

SDL 1.2 is moving to a branch, and SDL 1.3 is becoming the head.
author Sam Lantinga <slouken@libsdl.org>
date Mon, 10 Jul 2006 21:04:37 +0000
parents 11134dc42da8
children
comparison
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: */