filename | src/aica/aica.c |
changeset | 829:517425d04f1b |
prev | 736:a02d1475ccfd |
next | 929:fd8cb0c82f5f |
next | 953:f4a156508ad1 |
author | nkeynes |
date | Mon Oct 06 01:05:12 2008 +0000 (15 years ago) |
permissions | -rw-r--r-- |
last change | Move bundle/system paths into paths.c, install lxdreamrc into the bundle (Fix OSX bundle missing default configuration) |
view | annotate | diff | log | raw |
1 /**
2 * $Id$
3 *
4 * This module implements the AICA's IO interfaces, as well
5 * as providing the core AICA module to the system.
6 *
7 * Copyright (c) 2005 Nathan Keynes.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 */
20 #define MODULE aica_module
22 #include <time.h>
23 #include "dream.h"
24 #include "dreamcast.h"
25 #include "mem.h"
26 #include "aica/aica.h"
27 #include "armcore.h"
28 #include "aica/audio.h"
29 #define MMIO_IMPL
30 #include "aica.h"
32 MMIO_REGION_READ_DEFFN( AICA0 )
33 MMIO_REGION_READ_DEFFN( AICA1 )
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 struct aica_state_struct {
48 uint32_t time_of_day;
49 /**
50 * Keep track of what we've done so far this second, to try to keep the
51 * precision of samples/second.
52 */
53 uint32_t samples_done;
54 uint32_t nanosecs_done;
55 /**
56 * Event (IRQ) state
57 */
58 int event_pending;
59 int clear_count;
60 };
62 static struct aica_state_struct aica_state;
65 /**
66 * Initialize the AICA subsystem. Note requires that
67 */
68 void aica_init( void )
69 {
70 register_io_regions( mmio_list_spu );
71 MMIO_NOTRACE(AICA0);
72 MMIO_NOTRACE(AICA1);
73 arm_mem_init();
74 aica_reset();
75 }
77 void aica_reset( void )
78 {
79 arm_reset();
80 aica_state.time_of_day = 0x5bfc8900;
81 aica_state.samples_done = 0;
82 aica_state.nanosecs_done = 0;
83 aica_state.event_pending = 0;
84 aica_state.clear_count = 0;
85 // aica_event(2); /* Pre-deliver a timer interrupt */
86 }
88 void aica_start( void )
89 {
91 }
93 uint32_t aica_run_slice( uint32_t nanosecs )
94 {
95 /* Run arm instructions */
96 int reset = MMIO_READ( AICA2, AICA_RESET );
97 if( (reset & 1) == 0 ) { /* Running */
98 int num_samples = (int)((uint64_t)AICA_SAMPLE_RATE * (aica_state.nanosecs_done + nanosecs) / 1000000000) - aica_state.samples_done;
99 num_samples = arm_run_slice( num_samples );
100 audio_mix_samples( num_samples );
102 aica_state.samples_done += num_samples;
103 aica_state.nanosecs_done += nanosecs;
104 }
105 if( aica_state.nanosecs_done > 1000000000 ) {
106 aica_state.samples_done -= AICA_SAMPLE_RATE;
107 aica_state.nanosecs_done -= 1000000000;
108 aica_state.time_of_day++;
109 }
110 return nanosecs;
111 }
113 void aica_stop( void )
114 {
116 }
118 void aica_save_state( FILE *f )
119 {
120 fwrite( &aica_state, sizeof(struct aica_state_struct), 1, f );
121 arm_save_state( f );
122 audio_save_state(f);
123 }
125 int aica_load_state( FILE *f )
126 {
127 fread( &aica_state, sizeof(struct aica_state_struct), 1, f );
128 arm_load_state( f );
129 return audio_load_state(f);
130 }
132 /* Note: This is probably not necessarily technically correct but it should
133 * work in the meantime.
134 */
136 void aica_event( int event )
137 {
138 if( aica_state.event_pending == 0 )
139 armr.int_pending |= CPSR_F;
140 aica_state.event_pending |= (1<<event);
142 int pending = MMIO_READ( AICA2, AICA_IRQ );
143 if( pending == 0 || event < pending )
144 MMIO_WRITE( AICA2, AICA_IRQ, event );
145 }
147 void aica_clear_event( )
148 {
149 aica_state.clear_count++;
150 if( aica_state.clear_count == 4 ) {
151 int i;
152 aica_state.clear_count = 0;
154 for( i=0; i<8; i++ ) {
155 if( aica_state.event_pending & (1<<i) ) {
156 aica_state.event_pending &= ~(1<<i);
157 break;
158 }
159 }
160 for( ;i<8; i++ ) {
161 if( aica_state.event_pending & (1<<i) ) {
162 MMIO_WRITE( AICA2, AICA_IRQ, i );
163 break;
164 }
165 }
166 if( aica_state.event_pending == 0 )
167 armr.int_pending &= ~CPSR_F;
168 }
169 }
171 void aica_enable( void )
172 {
173 mmio_region_AICA2_write( AICA_RESET, MMIO_READ(AICA2,AICA_RESET) & ~1 );
174 }
176 /** Channel register structure:
177 * 00 4 Channel config
178 * 04 4 Waveform address lo (16 bits)
179 * 08 4 Loop start address
180 * 0C 4 Loop end address
181 * 10 4 Volume envelope
182 * 14 4 Init to 0x1F
183 * 18 4 Frequency (floating point)
184 * 1C 4 ??
185 * 20 4 ??
186 * 24 1 Pan
187 * 25 1 ??
188 * 26
189 * 27
190 * 28 1 ??
191 * 29 1 Volume
192 * 2C
193 * 30
194 */
196 /* Write to channels 0-31 */
197 void mmio_region_AICA0_write( uint32_t reg, uint32_t val )
198 {
199 MMIO_WRITE( AICA0, reg, val );
200 aica_write_channel( reg >> 7, reg % 128, val );
201 // DEBUG( "AICA0 Write %08X => %08X", val, reg );
202 }
204 /* Write to channels 32-64 */
205 void mmio_region_AICA1_write( uint32_t reg, uint32_t val )
206 {
207 MMIO_WRITE( AICA1, reg, val );
208 aica_write_channel( (reg >> 7) + 32, reg % 128, val );
209 // DEBUG( "AICA1 Write %08X => %08X", val, reg );
210 }
212 /**
213 * AICA control registers
214 */
215 void mmio_region_AICA2_write( uint32_t reg, uint32_t val )
216 {
217 uint32_t tmp;
219 switch( reg ) {
220 case AICA_RESET:
221 tmp = MMIO_READ( AICA2, AICA_RESET );
222 if( (tmp & 1) == 1 && (val & 1) == 0 ) {
223 /* ARM enabled - execute a core reset */
224 DEBUG( "ARM enabled" );
225 arm_reset();
226 aica_state.samples_done = 0;
227 aica_state.nanosecs_done = 0;
228 } else if( (tmp&1) == 0 && (val&1) == 1 ) {
229 DEBUG( "ARM disabled" );
230 }
231 MMIO_WRITE( AICA2, AICA_RESET, val );
232 break;
233 case AICA_IRQCLEAR:
234 aica_clear_event();
235 break;
236 case AICA_FIFOIN: /* Read-only */
237 break;
238 default:
239 MMIO_WRITE( AICA2, reg, val );
240 break;
241 }
242 }
244 int32_t mmio_region_AICA2_read( uint32_t reg )
245 {
246 audio_channel_t channel;
247 uint32_t channo;
248 int32_t val;
249 switch( reg ) {
250 case AICA_CHANSTATE:
251 channo = (MMIO_READ( AICA2, AICA_CHANSEL ) >> 8) & 0x3F;
252 channel = audio_get_channel(channo);
253 if( channel->loop == LOOP_LOOPED ) {
254 val = 0x8000;
255 channel->loop = LOOP_ON;
256 } else {
257 val = 0;
258 }
259 return val;
260 case AICA_CHANPOSN:
261 channo = (MMIO_READ( AICA2, AICA_CHANSEL ) >> 8) & 0x3F;
262 channel = audio_get_channel(channo);
263 return channel->posn;
264 default:
265 return MMIO_READ( AICA2, reg );
266 }
267 }
269 int32_t mmio_region_AICARTC_read( uint32_t reg )
270 {
271 int32_t rv = 0;
272 switch( reg ) {
273 case AICA_RTCHI:
274 rv = (aica_state.time_of_day >> 16) & 0xFFFF;
275 break;
276 case AICA_RTCLO:
277 rv = aica_state.time_of_day & 0xFFFF;
278 break;
279 }
280 // DEBUG( "Read AICA RTC %d => %08X", reg, rv );
281 return rv;
282 }
285 void mmio_region_AICARTC_write( uint32_t reg, uint32_t val )
286 {
287 switch( reg ) {
288 case AICA_RTCEN:
289 MMIO_WRITE( AICARTC, reg, val&0x01 );
290 break;
291 case AICA_RTCLO:
292 if( MMIO_READ( AICARTC, AICA_RTCEN ) & 0x01 ) {
293 aica_state.time_of_day = (aica_state.time_of_day & 0xFFFF0000) | (val & 0xFFFF);
294 }
295 break;
296 case AICA_RTCHI:
297 if( MMIO_READ( AICARTC, AICA_RTCEN ) & 0x01 ) {
298 aica_state.time_of_day = (aica_state.time_of_day & 0xFFFF) | (val<<16);
299 MMIO_WRITE( AICARTC, AICA_RTCEN, 0 );
300 }
301 break;
302 }
303 }
305 /**
306 * Translate the channel frequency to a sample rate. The frequency is a
307 * 14-bit floating point number, where bits 0..9 is the mantissa,
308 * 11..14 is the signed exponent (-8 to +7). Bit 10 appears to
309 * be unused.
310 *
311 * @return sample rate in samples per second.
312 */
313 uint32_t aica_frequency_to_sample_rate( uint32_t freq )
314 {
315 uint32_t exponent = (freq & 0x3800) >> 11;
316 uint32_t mantissa = freq & 0x03FF;
317 uint32_t rate;
318 if( freq & 0x4000 ) {
319 /* neg exponent - rate < 44100 */
320 exponent = 8 - exponent;
321 rate = (44100 >> exponent) +
322 ((44100 * mantissa) >> (10+exponent));
323 } else {
324 /* pos exponent - rate > 44100 */
325 rate = (44100 << exponent) +
326 ((44100 * mantissa) >> (10-exponent));
327 }
328 return rate;
329 }
331 void aica_start_stop_channels()
332 {
333 int i;
334 for( i=0; i<32; i++ ) {
335 uint32_t val = MMIO_READ( AICA0, i<<7 );
336 audio_start_stop_channel(i, val&0x4000);
337 }
338 for( ; i<64; i++ ) {
339 uint32_t val = MMIO_READ( AICA1, (i-32)<<7 );
340 audio_start_stop_channel(i, val&0x4000);
341 }
342 }
344 /**
345 * Derived directly from Dan Potter's log table
346 */
347 uint8_t aica_volume_table[256] = {
348 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
349 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 4,
350 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 9,
351 9, 9, 10, 10, 11, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16,
352 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 22, 22, 23, 23, 24, 25,
353 25, 26, 27, 27, 28, 29, 29, 30, 31, 31, 32, 33, 34, 34, 35, 36,
354 37, 37, 38, 39, 40, 40, 41, 42, 43, 44, 45, 45, 46, 47, 48, 49,
355 50, 51, 52, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
356 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 76, 77, 78, 79, 80, 81,
357 82, 83, 85, 86, 87, 88, 89, 90, 92, 93, 94, 95, 97, 98, 99, 100,
358 102, 103, 104, 105, 107, 108, 109, 111, 112, 113, 115, 116, 117, 119, 120, 121,
359 123, 124, 126, 127, 128, 130, 131, 133, 134, 136, 137, 139, 140, 142, 143, 145,
360 146, 148, 149, 151, 152, 154, 155, 157, 159, 160, 162, 163, 165, 167, 168, 170,
361 171, 173, 175, 176, 178, 180, 181, 183, 185, 187, 188, 190, 192, 194, 195, 197,
362 199, 201, 202, 204, 206, 208, 210, 211, 213, 215, 217, 219, 221, 223, 224, 226,
363 228, 230, 232, 234, 236, 238, 240, 242, 244, 246, 248, 250, 252, 253, 254, 255 };
366 void aica_write_channel( int channelNo, uint32_t reg, uint32_t val )
367 {
368 val &= 0x0000FFFF;
369 audio_channel_t channel = audio_get_channel(channelNo);
370 switch( reg ) {
371 case 0x00: /* Config + high address bits*/
372 channel->start = (channel->start & 0xFFFF) | ((val&0x1F) << 16);
373 if( val & 0x200 )
374 channel->loop = LOOP_ON;
375 else
376 channel->loop = LOOP_OFF;
377 switch( (val >> 7) & 0x03 ) {
378 case 0:
379 channel->sample_format = AUDIO_FMT_16BIT;
380 break;
381 case 1:
382 channel->sample_format = AUDIO_FMT_8BIT;
383 break;
384 case 2:
385 case 3:
386 channel->sample_format = AUDIO_FMT_ADPCM;
387 break;
388 }
389 if( val & 0x8000 ) {
390 aica_start_stop_channels();
391 }
392 break;
393 case 0x04: /* Low 16 address bits */
394 channel->start = (channel->start & 0x001F0000) | val;
395 break;
396 case 0x08: /* Loop start */
397 channel->loop_start = val;
398 break;
399 case 0x0C: /* End */
400 channel->end = val;
401 break;
402 case 0x10: /* Envelope register 1 */
403 break;
404 case 0x14: /* Envelope register 2 */
405 break;
406 case 0x18: /* Frequency */
407 channel->sample_rate = aica_frequency_to_sample_rate ( val );
408 break;
409 case 0x1C: /* ??? */
410 case 0x20: /* ??? */
411 case 0x24: /* Volume? /pan */
412 val = val & 0x1F;
413 if( val <= 0x0F )
414 val = 0x0F - val; /* Convert to smooth pan over 0..31 */
415 channel->pan = val;
416 break;
417 case 0x28: /* Volume */
418 // This isn't remotely correct, but it will have to suffice until I have
419 // time to figure out what's actually going on here...
420 channel->vol = aica_volume_table[max((val & 0xFF),((val>>8)&0xFF))];
421 break;
422 default: /* ??? */
423 break;
424 }
426 }
.