filename | src/aica/aica.c |
changeset | 929:fd8cb0c82f5f |
prev | 829:517425d04f1b |
next | 934:3acd3b3ee6d1 |
author | nkeynes |
date | Tue Dec 23 05:48:05 2008 +0000 (15 years ago) |
branch | lxdream-mem |
permissions | -rw-r--r-- |
last change | More refactoring and general cleanup. Most things should be working again now. Split off cache and start real implementation, breaking save states in the process |
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 MMIO_REGION_WRITE_FN( AICA0, reg, val )
198 {
199 reg &= 0xFFF;
200 MMIO_WRITE( AICA0, reg, val );
201 aica_write_channel( reg >> 7, reg % 128, val );
202 // DEBUG( "AICA0 Write %08X => %08X", val, reg );
203 }
205 /* Write to channels 32-64 */
206 MMIO_REGION_WRITE_FN( AICA1, reg, val )
207 {
208 reg &= 0xFFF;
209 MMIO_WRITE( AICA1, reg, val );
210 aica_write_channel( (reg >> 7) + 32, reg % 128, val );
211 // DEBUG( "AICA1 Write %08X => %08X", val, reg );
212 }
214 /**
215 * AICA control registers
216 */
217 MMIO_REGION_WRITE_FN( AICA2, reg, val )
218 {
219 uint32_t tmp;
220 reg &= 0xFFF;
222 switch( reg ) {
223 case AICA_RESET:
224 tmp = MMIO_READ( AICA2, AICA_RESET );
225 if( (tmp & 1) == 1 && (val & 1) == 0 ) {
226 /* ARM enabled - execute a core reset */
227 DEBUG( "ARM enabled" );
228 arm_reset();
229 aica_state.samples_done = 0;
230 aica_state.nanosecs_done = 0;
231 } else if( (tmp&1) == 0 && (val&1) == 1 ) {
232 DEBUG( "ARM disabled" );
233 }
234 MMIO_WRITE( AICA2, AICA_RESET, val );
235 break;
236 case AICA_IRQCLEAR:
237 aica_clear_event();
238 break;
239 case AICA_FIFOIN: /* Read-only */
240 break;
241 default:
242 MMIO_WRITE( AICA2, reg, val );
243 break;
244 }
245 }
247 MMIO_REGION_READ_FN( AICA2, reg )
248 {
249 audio_channel_t channel;
250 uint32_t channo;
251 int32_t val;
252 reg &= 0xFFF;
253 switch( reg ) {
254 case AICA_CHANSTATE:
255 channo = (MMIO_READ( AICA2, AICA_CHANSEL ) >> 8) & 0x3F;
256 channel = audio_get_channel(channo);
257 if( channel->loop == LOOP_LOOPED ) {
258 val = 0x8000;
259 channel->loop = LOOP_ON;
260 } else {
261 val = 0;
262 }
263 return val;
264 case AICA_CHANPOSN:
265 channo = (MMIO_READ( AICA2, AICA_CHANSEL ) >> 8) & 0x3F;
266 channel = audio_get_channel(channo);
267 return channel->posn;
268 default:
269 return MMIO_READ( AICA2, reg );
270 }
271 }
273 MMIO_REGION_READ_FN( AICARTC, reg )
274 {
275 int32_t rv = 0;
276 reg &= 0xFFF;
277 switch( reg ) {
278 case AICA_RTCHI:
279 rv = (aica_state.time_of_day >> 16) & 0xFFFF;
280 break;
281 case AICA_RTCLO:
282 rv = aica_state.time_of_day & 0xFFFF;
283 break;
284 }
285 // DEBUG( "Read AICA RTC %d => %08X", reg, rv );
286 return rv;
287 }
289 MMIO_REGION_WRITE_FN( AICARTC, reg, val )
290 {
291 reg &= 0xFFF;
292 switch( reg ) {
293 case AICA_RTCEN:
294 MMIO_WRITE( AICARTC, reg, val&0x01 );
295 break;
296 case AICA_RTCLO:
297 if( MMIO_READ( AICARTC, AICA_RTCEN ) & 0x01 ) {
298 aica_state.time_of_day = (aica_state.time_of_day & 0xFFFF0000) | (val & 0xFFFF);
299 }
300 break;
301 case AICA_RTCHI:
302 if( MMIO_READ( AICARTC, AICA_RTCEN ) & 0x01 ) {
303 aica_state.time_of_day = (aica_state.time_of_day & 0xFFFF) | (val<<16);
304 MMIO_WRITE( AICARTC, AICA_RTCEN, 0 );
305 }
306 break;
307 }
308 }
310 /**
311 * Translate the channel frequency to a sample rate. The frequency is a
312 * 14-bit floating point number, where bits 0..9 is the mantissa,
313 * 11..14 is the signed exponent (-8 to +7). Bit 10 appears to
314 * be unused.
315 *
316 * @return sample rate in samples per second.
317 */
318 uint32_t aica_frequency_to_sample_rate( uint32_t freq )
319 {
320 uint32_t exponent = (freq & 0x3800) >> 11;
321 uint32_t mantissa = freq & 0x03FF;
322 uint32_t rate;
323 if( freq & 0x4000 ) {
324 /* neg exponent - rate < 44100 */
325 exponent = 8 - exponent;
326 rate = (44100 >> exponent) +
327 ((44100 * mantissa) >> (10+exponent));
328 } else {
329 /* pos exponent - rate > 44100 */
330 rate = (44100 << exponent) +
331 ((44100 * mantissa) >> (10-exponent));
332 }
333 return rate;
334 }
336 void aica_start_stop_channels()
337 {
338 int i;
339 for( i=0; i<32; i++ ) {
340 uint32_t val = MMIO_READ( AICA0, i<<7 );
341 audio_start_stop_channel(i, val&0x4000);
342 }
343 for( ; i<64; i++ ) {
344 uint32_t val = MMIO_READ( AICA1, (i-32)<<7 );
345 audio_start_stop_channel(i, val&0x4000);
346 }
347 }
349 /**
350 * Derived directly from Dan Potter's log table
351 */
352 uint8_t aica_volume_table[256] = {
353 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
354 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 4,
355 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 9,
356 9, 9, 10, 10, 11, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16,
357 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 22, 22, 23, 23, 24, 25,
358 25, 26, 27, 27, 28, 29, 29, 30, 31, 31, 32, 33, 34, 34, 35, 36,
359 37, 37, 38, 39, 40, 40, 41, 42, 43, 44, 45, 45, 46, 47, 48, 49,
360 50, 51, 52, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
361 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 76, 77, 78, 79, 80, 81,
362 82, 83, 85, 86, 87, 88, 89, 90, 92, 93, 94, 95, 97, 98, 99, 100,
363 102, 103, 104, 105, 107, 108, 109, 111, 112, 113, 115, 116, 117, 119, 120, 121,
364 123, 124, 126, 127, 128, 130, 131, 133, 134, 136, 137, 139, 140, 142, 143, 145,
365 146, 148, 149, 151, 152, 154, 155, 157, 159, 160, 162, 163, 165, 167, 168, 170,
366 171, 173, 175, 176, 178, 180, 181, 183, 185, 187, 188, 190, 192, 194, 195, 197,
367 199, 201, 202, 204, 206, 208, 210, 211, 213, 215, 217, 219, 221, 223, 224, 226,
368 228, 230, 232, 234, 236, 238, 240, 242, 244, 246, 248, 250, 252, 253, 254, 255 };
371 void aica_write_channel( int channelNo, uint32_t reg, uint32_t val )
372 {
373 val &= 0x0000FFFF;
374 audio_channel_t channel = audio_get_channel(channelNo);
375 switch( reg ) {
376 case 0x00: /* Config + high address bits*/
377 channel->start = (channel->start & 0xFFFF) | ((val&0x1F) << 16);
378 if( val & 0x200 )
379 channel->loop = LOOP_ON;
380 else
381 channel->loop = LOOP_OFF;
382 switch( (val >> 7) & 0x03 ) {
383 case 0:
384 channel->sample_format = AUDIO_FMT_16BIT;
385 break;
386 case 1:
387 channel->sample_format = AUDIO_FMT_8BIT;
388 break;
389 case 2:
390 case 3:
391 channel->sample_format = AUDIO_FMT_ADPCM;
392 break;
393 }
394 if( val & 0x8000 ) {
395 aica_start_stop_channels();
396 }
397 break;
398 case 0x04: /* Low 16 address bits */
399 channel->start = (channel->start & 0x001F0000) | val;
400 break;
401 case 0x08: /* Loop start */
402 channel->loop_start = val;
403 break;
404 case 0x0C: /* End */
405 channel->end = val;
406 break;
407 case 0x10: /* Envelope register 1 */
408 break;
409 case 0x14: /* Envelope register 2 */
410 break;
411 case 0x18: /* Frequency */
412 channel->sample_rate = aica_frequency_to_sample_rate ( val );
413 break;
414 case 0x1C: /* ??? */
415 case 0x20: /* ??? */
416 case 0x24: /* Volume? /pan */
417 val = val & 0x1F;
418 if( val <= 0x0F )
419 val = 0x0F - val; /* Convert to smooth pan over 0..31 */
420 channel->pan = val;
421 break;
422 case 0x28: /* Volume */
423 // This isn't remotely correct, but it will have to suffice until I have
424 // time to figure out what's actually going on here...
425 channel->vol = aica_volume_table[max((val & 0xFF),((val>>8)&0xFF))];
426 break;
427 default: /* ??? */
428 break;
429 }
431 }
.