filename | src/aica/aica.c |
changeset | 301:1ace395139c3 |
prev | 241:776e46e58d6d |
next | 431:248dd77a9e44 |
author | nkeynes |
date | Sun Feb 11 10:09:32 2007 +0000 (17 years ago) |
permissions | -rw-r--r-- |
last change | Bug 27: Implement opengl framebuffer objects Rewrite much of the final video output stage. Now uses generic "render buffers", implemented on GL using framebuffer objects + textures. |
view | annotate | diff | log | raw |
1 /**
2 * $Id: aica.c,v 1.21 2007-01-17 09:37:22 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 <time.h>
22 #include "dream.h"
23 #include "dreamcast.h"
24 #include "mem.h"
25 #include "aica/aica.h"
26 #include "armcore.h"
27 #include "aica/audio.h"
28 #define MMIO_IMPL
29 #include "aica.h"
31 MMIO_REGION_READ_DEFFN( AICA0 )
32 MMIO_REGION_READ_DEFFN( AICA1 )
33 MMIO_REGION_READ_DEFFN( AICA2 )
35 void aica_init( void );
36 void aica_reset( void );
37 void aica_start( void );
38 void aica_stop( void );
39 void aica_save_state( FILE *f );
40 int aica_load_state( FILE *f );
41 uint32_t aica_run_slice( uint32_t );
43 struct dreamcast_module aica_module = { "AICA", aica_init, aica_reset,
44 aica_start, aica_run_slice, aica_stop,
45 aica_save_state, aica_load_state };
47 /* 20 years in seconds */
48 #define RTC_OFFSET 631152000
49 unsigned int aica_time_of_day = 0;
51 /**
52 * Initialize the AICA subsystem. Note requires that
53 */
54 void aica_init( void )
55 {
56 register_io_regions( mmio_list_spu );
57 MMIO_NOTRACE(AICA0);
58 MMIO_NOTRACE(AICA1);
59 arm_mem_init();
60 aica_reset();
61 }
63 void aica_reset( void )
64 {
65 struct timeval tv;
66 arm_reset();
67 aica_event(2); /* Pre-deliver a timer interrupt */
69 // gettimeofday( &tv, NULL );
70 // aica_time_of_day = tv.tv_sec + RTC_OFFSET;
71 aica_time_of_day = 0x5bfc8900;
72 }
74 void aica_start( void )
75 {
77 }
79 /**
80 * Keep track of what we've done so far this second, to try to keep the
81 * precision of samples/second.
82 */
83 int samples_done = 0;
84 uint32_t nanosecs_done = 0;
86 uint32_t aica_run_slice( uint32_t nanosecs )
87 {
88 /* Run arm instructions */
89 int reset = MMIO_READ( AICA2, AICA_RESET );
90 if( (reset & 1) == 0 ) { /* Running */
91 int num_samples = (int)((uint64_t)AICA_SAMPLE_RATE * (nanosecs_done + nanosecs) / 1000000000) - samples_done;
92 num_samples = arm_run_slice( num_samples );
93 audio_mix_samples( num_samples );
95 samples_done += num_samples;
96 nanosecs_done += nanosecs;
97 }
98 if( nanosecs_done > 1000000000 ) {
99 samples_done -= AICA_SAMPLE_RATE;
100 nanosecs_done -= 1000000000;
101 aica_time_of_day++;
102 }
103 return nanosecs;
104 }
106 void aica_stop( void )
107 {
109 }
111 void aica_save_state( FILE *f )
112 {
113 arm_save_state( f );
114 }
116 int aica_load_state( FILE *f )
117 {
118 return arm_load_state( f );
119 }
121 int aica_event_pending = 0;
122 int aica_clear_count = 0;
124 /* Note: This is probably not necessarily technically correct but it should
125 * work in the meantime.
126 */
128 void aica_event( int event )
129 {
130 if( aica_event_pending == 0 )
131 armr.int_pending |= CPSR_F;
132 aica_event_pending |= (1<<event);
134 int pending = MMIO_READ( AICA2, AICA_IRQ );
135 if( pending == 0 || event < pending )
136 MMIO_WRITE( AICA2, AICA_IRQ, event );
137 }
139 void aica_clear_event( )
140 {
141 aica_clear_count++;
142 if( aica_clear_count == 4 ) {
143 int i;
144 aica_clear_count = 0;
146 for( i=0; i<8; i++ ) {
147 if( aica_event_pending & (1<<i) ) {
148 aica_event_pending &= ~(1<<i);
149 break;
150 }
151 }
152 for( ;i<8; i++ ) {
153 if( aica_event_pending & (1<<i) ) {
154 MMIO_WRITE( AICA2, AICA_IRQ, i );
155 break;
156 }
157 }
158 if( aica_event_pending == 0 )
159 armr.int_pending &= ~CPSR_F;
160 }
161 }
163 void aica_enable( void )
164 {
165 mmio_region_AICA2_write( AICA_RESET, MMIO_READ(AICA2,AICA_RESET) & ~1 );
166 }
168 /** Channel register structure:
169 * 00 4 Channel config
170 * 04 4 Waveform address lo (16 bits)
171 * 08 4 Loop start address
172 * 0C 4 Loop end address
173 * 10 4 Volume envelope
174 * 14 4 Init to 0x1F
175 * 18 4 Frequency (floating point)
176 * 1C 4 ??
177 * 20 4 ??
178 * 24 1 Pan
179 * 25 1 ??
180 * 26
181 * 27
182 * 28 1 ??
183 * 29 1 Volume
184 * 2C
185 * 30
186 *
188 /* Write to channels 0-31 */
189 void mmio_region_AICA0_write( uint32_t reg, uint32_t val )
190 {
191 MMIO_WRITE( AICA0, reg, val );
192 aica_write_channel( reg >> 7, reg % 128, val );
193 // DEBUG( "AICA0 Write %08X => %08X", val, reg );
194 }
196 /* Write to channels 32-64 */
197 void mmio_region_AICA1_write( uint32_t reg, uint32_t val )
198 {
199 MMIO_WRITE( AICA1, reg, val );
200 aica_write_channel( (reg >> 7) + 32, reg % 128, val );
201 // DEBUG( "AICA1 Write %08X => %08X", val, reg );
202 }
204 /**
205 * AICA control registers
206 */
207 void mmio_region_AICA2_write( uint32_t reg, uint32_t val )
208 {
209 uint32_t tmp;
210 switch( reg ) {
211 case AICA_RESET:
212 tmp = MMIO_READ( AICA2, AICA_RESET );
213 if( (tmp & 1) == 1 && (val & 1) == 0 ) {
214 /* ARM enabled - execute a core reset */
215 DEBUG( "ARM enabled" );
216 arm_reset();
217 samples_done = 0;
218 nanosecs_done = 0;
219 } else if( (tmp&1) == 0 && (val&1) == 1 ) {
220 DEBUG( "ARM disabled" );
221 }
222 MMIO_WRITE( AICA2, AICA_RESET, val );
223 break;
224 case AICA_IRQCLEAR:
225 aica_clear_event();
226 break;
227 default:
228 MMIO_WRITE( AICA2, reg, val );
229 break;
230 }
231 }
234 int32_t mmio_region_AICARTC_read( uint32_t reg )
235 {
236 struct timeval tv;
237 int32_t rv = 0;
238 switch( reg ) {
239 case AICA_RTCHI:
240 rv = (aica_time_of_day >> 16) & 0xFFFF;
241 break;
242 case AICA_RTCLO:
243 rv = aica_time_of_day & 0xFFFF;
244 break;
245 }
246 // DEBUG( "Read AICA RTC %d => %08X", reg, rv );
247 return rv;
248 }
251 void mmio_region_AICARTC_write( uint32_t reg, uint32_t val )
252 {
253 switch( reg ) {
254 case AICA_RTCEN:
255 MMIO_WRITE( AICARTC, reg, val&0x01 );
256 break;
257 case AICA_RTCLO:
258 if( MMIO_READ( AICARTC, AICA_RTCEN ) & 0x01 ) {
259 aica_time_of_day = (aica_time_of_day & 0xFFFF0000) | (val & 0xFFFF);
260 }
261 break;
262 case AICA_RTCHI:
263 if( MMIO_READ( AICARTC, AICA_RTCEN ) & 0x01 ) {
264 aica_time_of_day = (aica_time_of_day & 0xFFFF) | (val<<16);
265 MMIO_WRITE( AICARTC, AICA_RTCEN, 0 );
266 }
267 break;
268 }
269 }
271 /**
272 * Translate the channel frequency to a sample rate. The frequency is a
273 * 14-bit floating point number, where bits 0..9 is the mantissa,
274 * 11..14 is the signed exponent (-8 to +7). Bit 10 appears to
275 * be unused.
276 *
277 * @return sample rate in samples per second.
278 */
279 uint32_t aica_frequency_to_sample_rate( uint32_t freq )
280 {
281 uint32_t exponent = (freq & 0x3800) >> 11;
282 uint32_t mantissa = freq & 0x03FF;
283 uint32_t rate;
284 if( freq & 0x4000 ) {
285 /* neg exponent - rate < 44100 */
286 exponent = 8 - exponent;
287 rate = (44100 >> exponent) +
288 ((44100 * mantissa) >> (10+exponent));
289 } else {
290 /* pos exponent - rate > 44100 */
291 rate = (44100 << exponent) +
292 ((44100 * mantissa) >> (10-exponent));
293 }
294 return rate;
295 }
297 /**
298 * Derived directly from Dan Potter's log table
299 */
300 uint8_t aica_volume_table[256] = {
301 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
302 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 4,
303 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 9,
304 9, 9, 10, 10, 11, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16,
305 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 22, 22, 23, 23, 24, 25,
306 25, 26, 27, 27, 28, 29, 29, 30, 31, 31, 32, 33, 34, 34, 35, 36,
307 37, 37, 38, 39, 40, 40, 41, 42, 43, 44, 45, 45, 46, 47, 48, 49,
308 50, 51, 52, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
309 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 76, 77, 78, 79, 80, 81,
310 82, 83, 85, 86, 87, 88, 89, 90, 92, 93, 94, 95, 97, 98, 99, 100,
311 102, 103, 104, 105, 107, 108, 109, 111, 112, 113, 115, 116, 117, 119, 120, 121,
312 123, 124, 126, 127, 128, 130, 131, 133, 134, 136, 137, 139, 140, 142, 143, 145,
313 146, 148, 149, 151, 152, 154, 155, 157, 159, 160, 162, 163, 165, 167, 168, 170,
314 171, 173, 175, 176, 178, 180, 181, 183, 185, 187, 188, 190, 192, 194, 195, 197,
315 199, 201, 202, 204, 206, 208, 210, 211, 213, 215, 217, 219, 221, 223, 224, 226,
316 228, 230, 232, 234, 236, 238, 240, 242, 244, 246, 248, 250, 252, 253, 254, 255 };
319 void aica_write_channel( int channelNo, uint32_t reg, uint32_t val )
320 {
321 val &= 0x0000FFFF;
322 audio_channel_t channel = audio_get_channel(channelNo);
323 switch( reg ) {
324 case 0x00: /* Config + high address bits*/
325 channel->start = (channel->start & 0xFFFF) | ((val&0x1F) << 16);
326 if( val & 0x200 )
327 channel->loop = TRUE;
328 else
329 channel->loop = FALSE;
330 switch( (val >> 7) & 0x03 ) {
331 case 0:
332 channel->sample_format = AUDIO_FMT_16BIT;
333 break;
334 case 1:
335 channel->sample_format = AUDIO_FMT_8BIT;
336 break;
337 case 2:
338 case 3:
339 channel->sample_format = AUDIO_FMT_ADPCM;
340 break;
341 }
342 switch( (val >> 14) & 0x03 ) {
343 case 2:
344 audio_stop_channel( channelNo );
345 break;
346 case 3:
347 audio_start_channel( channelNo );
348 break;
349 default:
350 break;
351 /* Hrmm... */
352 }
353 break;
354 case 0x04: /* Low 16 address bits */
355 channel->start = (channel->start & 0x001F0000) | val;
356 break;
357 case 0x08: /* Loop start */
358 channel->loop_start = val;
359 break;
360 case 0x0C: /* End */
361 channel->end = val;
362 break;
363 case 0x10: /* Envelope register 1 */
364 break;
365 case 0x14: /* Envelope register 2 */
366 break;
367 case 0x18: /* Frequency */
368 channel->sample_rate = aica_frequency_to_sample_rate ( val );
369 break;
370 case 0x1C: /* ??? */
371 case 0x20: /* ??? */
372 case 0x24: /* Volume? /pan */
373 val = val & 0x1F;
374 if( val <= 0x0F )
375 val = 0x0F - val; /* Convert to smooth pan over 0..31 */
376 channel->pan = val;
377 break;
378 case 0x28: /* Volume */
379 channel->vol = aica_volume_table[val & 0xFF];
380 break;
381 default: /* ??? */
382 break;
383 }
385 }
.