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