comparison src/audio/dc/aica.c @ 1662:782fd950bd46 SDL-1.3

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