filename | src/aica/aica.c |
changeset | 86:f151e63f9754 |
prev | 82:81a4acf75f10 |
next | 106:9048bac046c3 |
author | nkeynes |
date | Wed Feb 15 13:11:50 2006 +0000 (18 years ago) |
permissions | -rw-r--r-- |
last change | Split pvr2.c out to separate files for TA and renderer, minor renames change pvrdma to use mem_copy_to_sh4 |
view | annotate | diff | log | raw |
1 /**
2 * $Id: aica.c,v 1.16 2006-01-22 22:40:05 nkeynes Exp $
3 *
4 * This is the core sound system (ie the bit which does the actual work)
5 *
6 * Copyright (c) 2005 Nathan Keynes.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 */
19 #define MODULE aica_module
21 #include "dream.h"
22 #include "dreamcast.h"
23 #include "mem.h"
24 #include "aica.h"
25 #include "armcore.h"
26 #include "audio.h"
27 #define MMIO_IMPL
28 #include "aica.h"
30 MMIO_REGION_READ_DEFFN( AICA0 )
31 MMIO_REGION_READ_DEFFN( AICA1 )
32 MMIO_REGION_READ_DEFFN( AICA2 )
34 void aica_init( void );
35 void aica_reset( void );
36 void aica_start( void );
37 void aica_stop( void );
38 void aica_save_state( FILE *f );
39 int aica_load_state( FILE *f );
40 uint32_t aica_run_slice( uint32_t );
42 struct dreamcast_module aica_module = { "AICA", aica_init, aica_reset,
43 aica_start, aica_run_slice, aica_stop,
44 aica_save_state, aica_load_state };
46 /**
47 * Initialize the AICA subsystem. Note requires that
48 */
49 void aica_init( void )
50 {
51 register_io_regions( mmio_list_spu );
52 MMIO_NOTRACE(AICA0);
53 MMIO_NOTRACE(AICA1);
54 arm_mem_init();
55 aica_reset();
56 audio_set_output( &esd_audio_driver, 44100, AUDIO_FMT_16BIT|AUDIO_FMT_STEREO );
57 }
59 void aica_reset( void )
60 {
61 arm_reset();
62 aica_event(2); /* Pre-deliver a timer interrupt */
63 }
65 void aica_start( void )
66 {
68 }
70 /**
71 * Keep track of what we've done so far this second, to try to keep the
72 * precision of samples/second.
73 */
74 int samples_done = 0;
75 uint32_t nanosecs_done = 0;
77 uint32_t aica_run_slice( uint32_t nanosecs )
78 {
79 /* Run arm instructions */
80 int reset = MMIO_READ( AICA2, AICA_RESET );
81 if( (reset & 1) == 0 ) { /* Running */
82 int num_samples = (int)((uint64_t)AICA_SAMPLE_RATE * (nanosecs_done + nanosecs) / 1000000000) - samples_done;
83 num_samples = arm_run_slice( num_samples );
84 audio_mix_samples( num_samples );
86 samples_done += num_samples;
87 nanosecs_done += nanosecs;
88 }
89 if( nanosecs_done > 1000000000 ) {
90 samples_done -= AICA_SAMPLE_RATE;
91 nanosecs_done -= 1000000000;
92 }
93 return nanosecs;
94 }
96 void aica_stop( void )
97 {
99 }
101 void aica_save_state( FILE *f )
102 {
103 arm_save_state( f );
104 }
106 int aica_load_state( FILE *f )
107 {
108 return arm_load_state( f );
109 }
111 int aica_event_pending = 0;
112 int aica_clear_count = 0;
114 /* Note: This is probably not necessarily technically correct but it should
115 * work in the meantime.
116 */
118 void aica_event( int event )
119 {
120 if( aica_event_pending == 0 )
121 armr.int_pending |= CPSR_F;
122 aica_event_pending |= (1<<event);
124 int pending = MMIO_READ( AICA2, AICA_IRQ );
125 if( pending == 0 || event < pending )
126 MMIO_WRITE( AICA2, AICA_IRQ, event );
127 }
129 void aica_clear_event( )
130 {
131 aica_clear_count++;
132 if( aica_clear_count == 4 ) {
133 int i;
134 aica_clear_count = 0;
136 for( i=0; i<8; i++ ) {
137 if( aica_event_pending & (1<<i) ) {
138 aica_event_pending &= ~(1<<i);
139 break;
140 }
141 }
142 for( ;i<8; i++ ) {
143 if( aica_event_pending & (1<<i) ) {
144 MMIO_WRITE( AICA2, AICA_IRQ, i );
145 break;
146 }
147 }
148 if( aica_event_pending == 0 )
149 armr.int_pending &= ~CPSR_F;
150 }
151 }
153 void aica_enable( void )
154 {
155 mmio_region_AICA2_write( AICA_RESET, MMIO_READ(AICA2,AICA_RESET) & ~1 );
156 }
158 /** Channel register structure:
159 * 00 4 Channel config
160 * 04 4 Waveform address lo (16 bits)
161 * 08 4 Loop start address
162 * 0C 4 Loop end address
163 * 10 4 Volume envelope
164 * 14 4 Init to 0x1F
165 * 18 4 Frequency (floating point)
166 * 1C 4 ??
167 * 20 4 ??
168 * 24 1 Pan
169 * 25 1 ??
170 * 26
171 * 27
172 * 28 1 ??
173 * 29 1 Volume
174 * 2C
175 * 30
176 *
178 /* Write to channels 0-31 */
179 void mmio_region_AICA0_write( uint32_t reg, uint32_t val )
180 {
181 MMIO_WRITE( AICA0, reg, val );
182 aica_write_channel( reg >> 7, reg % 128, val );
183 // DEBUG( "AICA0 Write %08X => %08X", val, reg );
184 }
186 /* Write to channels 32-64 */
187 void mmio_region_AICA1_write( uint32_t reg, uint32_t val )
188 {
189 MMIO_WRITE( AICA1, reg, val );
190 aica_write_channel( (reg >> 7) + 32, reg % 128, val );
191 // DEBUG( "AICA1 Write %08X => %08X", val, reg );
192 }
194 /**
195 * AICA control registers
196 */
197 void mmio_region_AICA2_write( uint32_t reg, uint32_t val )
198 {
199 uint32_t tmp;
200 switch( reg ) {
201 case AICA_RESET:
202 tmp = MMIO_READ( AICA2, AICA_RESET );
203 if( (tmp & 1) == 1 && (val & 1) == 0 ) {
204 /* ARM enabled - execute a core reset */
205 DEBUG( "ARM enabled" );
206 arm_reset();
207 samples_done = 0;
208 nanosecs_done = 0;
209 } else if( (tmp&1) == 0 && (val&1) == 1 ) {
210 DEBUG( "ARM disabled" );
211 }
212 MMIO_WRITE( AICA2, AICA_RESET, val );
213 break;
214 case AICA_IRQCLEAR:
215 aica_clear_event();
216 break;
217 default:
218 MMIO_WRITE( AICA2, reg, val );
219 break;
220 }
221 }
223 /**
224 * Translate the channel frequency to a sample rate. The frequency is a
225 * 14-bit floating point number, where bits 0..9 is the mantissa,
226 * 11..14 is the signed exponent (-8 to +7). Bit 10 appears to
227 * be unused.
228 *
229 * @return sample rate in samples per second.
230 */
231 uint32_t aica_frequency_to_sample_rate( uint32_t freq )
232 {
233 uint32_t exponent = (freq & 0x3800) >> 11;
234 uint32_t mantissa = freq & 0x03FF;
235 uint32_t rate;
236 if( freq & 0x4000 ) {
237 /* neg exponent - rate < 44100 */
238 exponent = 8 - exponent;
239 rate = (44100 >> exponent) +
240 ((44100 * mantissa) >> (10+exponent));
241 } else {
242 /* pos exponent - rate > 44100 */
243 rate = (44100 << exponent) +
244 ((44100 * mantissa) >> (10-exponent));
245 }
246 return rate;
247 }
249 /**
250 * Derived directly from Dan Potter's log table
251 */
252 uint8_t aica_volume_table[256] = {
253 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
254 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 4,
255 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 9,
256 9, 9, 10, 10, 11, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16,
257 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 22, 22, 23, 23, 24, 25,
258 25, 26, 27, 27, 28, 29, 29, 30, 31, 31, 32, 33, 34, 34, 35, 36,
259 37, 37, 38, 39, 40, 40, 41, 42, 43, 44, 45, 45, 46, 47, 48, 49,
260 50, 51, 52, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
261 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 76, 77, 78, 79, 80, 81,
262 82, 83, 85, 86, 87, 88, 89, 90, 92, 93, 94, 95, 97, 98, 99, 100,
263 102, 103, 104, 105, 107, 108, 109, 111, 112, 113, 115, 116, 117, 119, 120, 121,
264 123, 124, 126, 127, 128, 130, 131, 133, 134, 136, 137, 139, 140, 142, 143, 145,
265 146, 148, 149, 151, 152, 154, 155, 157, 159, 160, 162, 163, 165, 167, 168, 170,
266 171, 173, 175, 176, 178, 180, 181, 183, 185, 187, 188, 190, 192, 194, 195, 197,
267 199, 201, 202, 204, 206, 208, 210, 211, 213, 215, 217, 219, 221, 223, 224, 226,
268 228, 230, 232, 234, 236, 238, 240, 242, 244, 246, 248, 250, 252, 253, 254, 255 };
271 void aica_write_channel( int channelNo, uint32_t reg, uint32_t val )
272 {
273 val &= 0x0000FFFF;
274 audio_channel_t channel = audio_get_channel(channelNo);
275 switch( reg ) {
276 case 0x00: /* Config + high address bits*/
277 channel->start = (channel->start & 0xFFFF) | ((val&0x1F) << 16);
278 if( val & 0x200 )
279 channel->loop = TRUE;
280 else
281 channel->loop = FALSE;
282 switch( (val >> 7) & 0x03 ) {
283 case 0:
284 channel->sample_format = AUDIO_FMT_16BIT;
285 break;
286 case 1:
287 channel->sample_format = AUDIO_FMT_8BIT;
288 break;
289 case 2:
290 case 3:
291 channel->sample_format = AUDIO_FMT_ADPCM;
292 break;
293 }
294 switch( (val >> 14) & 0x03 ) {
295 case 2:
296 audio_stop_channel( channelNo );
297 break;
298 case 3:
299 audio_start_channel( channelNo );
300 break;
301 default:
302 break;
303 /* Hrmm... */
304 }
305 break;
306 case 0x04: /* Low 16 address bits */
307 channel->start = (channel->start & 0x001F0000) | val;
308 break;
309 case 0x08: /* Loop start */
310 channel->loop_start = val;
311 break;
312 case 0x0C: /* End */
313 channel->end = val;
314 break;
315 case 0x10: /* Envelope register 1 */
316 break;
317 case 0x14: /* Envelope register 2 */
318 break;
319 case 0x18: /* Frequency */
320 channel->sample_rate = aica_frequency_to_sample_rate ( val );
321 break;
322 case 0x1C: /* ??? */
323 case 0x20: /* ??? */
324 case 0x24: /* Volume? /pan */
325 val = val & 0x1F;
326 if( val <= 0x0F )
327 val = 0x0F - val; /* Convert to smooth pan over 0..31 */
328 channel->pan = val;
329 break;
330 case 0x28: /* Volume */
331 channel->vol = aica_volume_table[val & 0xFF];
332 break;
333 default: /* ??? */
334 break;
335 }
337 }
.