filename | src/aica/aica.c |
changeset | 934:3acd3b3ee6d1 |
prev | 929:fd8cb0c82f5f |
next | 1067:d3c00ffccfcd |
author | nkeynes |
date | Wed Jan 07 04:39:58 2009 +0000 (15 years ago) |
branch | lxdream-mem |
permissions | -rw-r--r-- |
last change | Add missed file from previous commit - remove sh4_translate_flush_cache, change exit to use pre-recovery |
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 aica_reset();
74 }
76 void aica_reset( void )
77 {
78 arm_reset();
79 aica_state.time_of_day = 0x5bfc8900;
80 aica_state.samples_done = 0;
81 aica_state.nanosecs_done = 0;
82 aica_state.event_pending = 0;
83 aica_state.clear_count = 0;
84 // aica_event(2); /* Pre-deliver a timer interrupt */
85 }
87 void aica_start( void )
88 {
90 }
92 uint32_t aica_run_slice( uint32_t nanosecs )
93 {
94 /* Run arm instructions */
95 int reset = MMIO_READ( AICA2, AICA_RESET );
96 if( (reset & 1) == 0 ) { /* Running */
97 int num_samples = (int)((uint64_t)AICA_SAMPLE_RATE * (aica_state.nanosecs_done + nanosecs) / 1000000000) - aica_state.samples_done;
98 num_samples = arm_run_slice( num_samples );
99 audio_mix_samples( num_samples );
101 aica_state.samples_done += num_samples;
102 aica_state.nanosecs_done += nanosecs;
103 }
104 if( aica_state.nanosecs_done > 1000000000 ) {
105 aica_state.samples_done -= AICA_SAMPLE_RATE;
106 aica_state.nanosecs_done -= 1000000000;
107 aica_state.time_of_day++;
108 }
109 return nanosecs;
110 }
112 void aica_stop( void )
113 {
115 }
117 void aica_save_state( FILE *f )
118 {
119 fwrite( &aica_state, sizeof(struct aica_state_struct), 1, f );
120 arm_save_state( f );
121 audio_save_state(f);
122 }
124 int aica_load_state( FILE *f )
125 {
126 fread( &aica_state, sizeof(struct aica_state_struct), 1, f );
127 arm_load_state( f );
128 return audio_load_state(f);
129 }
131 /* Note: This is probably not necessarily technically correct but it should
132 * work in the meantime.
133 */
135 void aica_event( int event )
136 {
137 if( aica_state.event_pending == 0 )
138 armr.int_pending |= CPSR_F;
139 aica_state.event_pending |= (1<<event);
141 int pending = MMIO_READ( AICA2, AICA_IRQ );
142 if( pending == 0 || event < pending )
143 MMIO_WRITE( AICA2, AICA_IRQ, event );
144 }
146 void aica_clear_event( )
147 {
148 aica_state.clear_count++;
149 if( aica_state.clear_count == 4 ) {
150 int i;
151 aica_state.clear_count = 0;
153 for( i=0; i<8; i++ ) {
154 if( aica_state.event_pending & (1<<i) ) {
155 aica_state.event_pending &= ~(1<<i);
156 break;
157 }
158 }
159 for( ;i<8; i++ ) {
160 if( aica_state.event_pending & (1<<i) ) {
161 MMIO_WRITE( AICA2, AICA_IRQ, i );
162 break;
163 }
164 }
165 if( aica_state.event_pending == 0 )
166 armr.int_pending &= ~CPSR_F;
167 }
168 }
170 void aica_enable( void )
171 {
172 mmio_region_AICA2_write( AICA_RESET, MMIO_READ(AICA2,AICA_RESET) & ~1 );
173 }
175 /** Channel register structure:
176 * 00 4 Channel config
177 * 04 4 Waveform address lo (16 bits)
178 * 08 4 Loop start address
179 * 0C 4 Loop end address
180 * 10 4 Volume envelope
181 * 14 4 Init to 0x1F
182 * 18 4 Frequency (floating point)
183 * 1C 4 ??
184 * 20 4 ??
185 * 24 1 Pan
186 * 25 1 ??
187 * 26
188 * 27
189 * 28 1 ??
190 * 29 1 Volume
191 * 2C
192 * 30
193 */
195 /* Write to channels 0-31 */
196 MMIO_REGION_WRITE_FN( AICA0, reg, val )
197 {
198 reg &= 0xFFF;
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 MMIO_REGION_WRITE_FN( AICA1, reg, val )
206 {
207 reg &= 0xFFF;
208 MMIO_WRITE( AICA1, reg, val );
209 aica_write_channel( (reg >> 7) + 32, reg % 128, val );
210 // DEBUG( "AICA1 Write %08X => %08X", val, reg );
211 }
213 /**
214 * AICA control registers
215 */
216 MMIO_REGION_WRITE_FN( AICA2, reg, val )
217 {
218 uint32_t tmp;
219 reg &= 0xFFF;
221 switch( reg ) {
222 case AICA_RESET:
223 tmp = MMIO_READ( AICA2, AICA_RESET );
224 if( (tmp & 1) == 1 && (val & 1) == 0 ) {
225 /* ARM enabled - execute a core reset */
226 DEBUG( "ARM enabled" );
227 arm_reset();
228 aica_state.samples_done = 0;
229 aica_state.nanosecs_done = 0;
230 } else if( (tmp&1) == 0 && (val&1) == 1 ) {
231 DEBUG( "ARM disabled" );
232 }
233 MMIO_WRITE( AICA2, AICA_RESET, val );
234 break;
235 case AICA_IRQCLEAR:
236 aica_clear_event();
237 break;
238 case AICA_FIFOIN: /* Read-only */
239 break;
240 default:
241 MMIO_WRITE( AICA2, reg, val );
242 break;
243 }
244 }
246 MMIO_REGION_READ_FN( AICA2, reg )
247 {
248 audio_channel_t channel;
249 uint32_t channo;
250 int32_t val;
251 reg &= 0xFFF;
252 switch( reg ) {
253 case AICA_CHANSTATE:
254 channo = (MMIO_READ( AICA2, AICA_CHANSEL ) >> 8) & 0x3F;
255 channel = audio_get_channel(channo);
256 if( channel->loop == LOOP_LOOPED ) {
257 val = 0x8000;
258 channel->loop = LOOP_ON;
259 } else {
260 val = 0;
261 }
262 return val;
263 case AICA_CHANPOSN:
264 channo = (MMIO_READ( AICA2, AICA_CHANSEL ) >> 8) & 0x3F;
265 channel = audio_get_channel(channo);
266 return channel->posn;
267 default:
268 return MMIO_READ( AICA2, reg );
269 }
270 }
272 MMIO_REGION_READ_FN( AICARTC, reg )
273 {
274 int32_t rv = 0;
275 reg &= 0xFFF;
276 switch( reg ) {
277 case AICA_RTCHI:
278 rv = (aica_state.time_of_day >> 16) & 0xFFFF;
279 break;
280 case AICA_RTCLO:
281 rv = aica_state.time_of_day & 0xFFFF;
282 break;
283 }
284 // DEBUG( "Read AICA RTC %d => %08X", reg, rv );
285 return rv;
286 }
288 MMIO_REGION_WRITE_FN( AICARTC, reg, val )
289 {
290 reg &= 0xFFF;
291 switch( reg ) {
292 case AICA_RTCEN:
293 MMIO_WRITE( AICARTC, reg, val&0x01 );
294 break;
295 case AICA_RTCLO:
296 if( MMIO_READ( AICARTC, AICA_RTCEN ) & 0x01 ) {
297 aica_state.time_of_day = (aica_state.time_of_day & 0xFFFF0000) | (val & 0xFFFF);
298 }
299 break;
300 case AICA_RTCHI:
301 if( MMIO_READ( AICARTC, AICA_RTCEN ) & 0x01 ) {
302 aica_state.time_of_day = (aica_state.time_of_day & 0xFFFF) | (val<<16);
303 MMIO_WRITE( AICARTC, AICA_RTCEN, 0 );
304 }
305 break;
306 }
307 }
309 /**
310 * Translate the channel frequency to a sample rate. The frequency is a
311 * 14-bit floating point number, where bits 0..9 is the mantissa,
312 * 11..14 is the signed exponent (-8 to +7). Bit 10 appears to
313 * be unused.
314 *
315 * @return sample rate in samples per second.
316 */
317 uint32_t aica_frequency_to_sample_rate( uint32_t freq )
318 {
319 uint32_t exponent = (freq & 0x3800) >> 11;
320 uint32_t mantissa = freq & 0x03FF;
321 uint32_t rate;
322 if( freq & 0x4000 ) {
323 /* neg exponent - rate < 44100 */
324 exponent = 8 - exponent;
325 rate = (44100 >> exponent) +
326 ((44100 * mantissa) >> (10+exponent));
327 } else {
328 /* pos exponent - rate > 44100 */
329 rate = (44100 << exponent) +
330 ((44100 * mantissa) >> (10-exponent));
331 }
332 return rate;
333 }
335 void aica_start_stop_channels()
336 {
337 int i;
338 for( i=0; i<32; i++ ) {
339 uint32_t val = MMIO_READ( AICA0, i<<7 );
340 audio_start_stop_channel(i, val&0x4000);
341 }
342 for( ; i<64; i++ ) {
343 uint32_t val = MMIO_READ( AICA1, (i-32)<<7 );
344 audio_start_stop_channel(i, val&0x4000);
345 }
346 }
348 /**
349 * Derived directly from Dan Potter's log table
350 */
351 uint8_t aica_volume_table[256] = {
352 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
353 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 4,
354 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 9,
355 9, 9, 10, 10, 11, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16,
356 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 22, 22, 23, 23, 24, 25,
357 25, 26, 27, 27, 28, 29, 29, 30, 31, 31, 32, 33, 34, 34, 35, 36,
358 37, 37, 38, 39, 40, 40, 41, 42, 43, 44, 45, 45, 46, 47, 48, 49,
359 50, 51, 52, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
360 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 76, 77, 78, 79, 80, 81,
361 82, 83, 85, 86, 87, 88, 89, 90, 92, 93, 94, 95, 97, 98, 99, 100,
362 102, 103, 104, 105, 107, 108, 109, 111, 112, 113, 115, 116, 117, 119, 120, 121,
363 123, 124, 126, 127, 128, 130, 131, 133, 134, 136, 137, 139, 140, 142, 143, 145,
364 146, 148, 149, 151, 152, 154, 155, 157, 159, 160, 162, 163, 165, 167, 168, 170,
365 171, 173, 175, 176, 178, 180, 181, 183, 185, 187, 188, 190, 192, 194, 195, 197,
366 199, 201, 202, 204, 206, 208, 210, 211, 213, 215, 217, 219, 221, 223, 224, 226,
367 228, 230, 232, 234, 236, 238, 240, 242, 244, 246, 248, 250, 252, 253, 254, 255 };
370 void aica_write_channel( int channelNo, uint32_t reg, uint32_t val )
371 {
372 val &= 0x0000FFFF;
373 audio_channel_t channel = audio_get_channel(channelNo);
374 switch( reg ) {
375 case 0x00: /* Config + high address bits*/
376 channel->start = (channel->start & 0xFFFF) | ((val&0x1F) << 16);
377 if( val & 0x200 )
378 channel->loop = LOOP_ON;
379 else
380 channel->loop = LOOP_OFF;
381 switch( (val >> 7) & 0x03 ) {
382 case 0:
383 channel->sample_format = AUDIO_FMT_16BIT;
384 break;
385 case 1:
386 channel->sample_format = AUDIO_FMT_8BIT;
387 break;
388 case 2:
389 case 3:
390 channel->sample_format = AUDIO_FMT_ADPCM;
391 break;
392 }
393 if( val & 0x8000 ) {
394 aica_start_stop_channels();
395 }
396 break;
397 case 0x04: /* Low 16 address bits */
398 channel->start = (channel->start & 0x001F0000) | val;
399 break;
400 case 0x08: /* Loop start */
401 channel->loop_start = val;
402 break;
403 case 0x0C: /* End */
404 channel->end = val;
405 break;
406 case 0x10: /* Envelope register 1 */
407 break;
408 case 0x14: /* Envelope register 2 */
409 break;
410 case 0x18: /* Frequency */
411 channel->sample_rate = aica_frequency_to_sample_rate ( val );
412 break;
413 case 0x1C: /* ??? */
414 case 0x20: /* ??? */
415 case 0x24: /* Volume? /pan */
416 val = val & 0x1F;
417 if( val <= 0x0F )
418 val = 0x0F - val; /* Convert to smooth pan over 0..31 */
419 channel->pan = val;
420 break;
421 case 0x28: /* Volume */
422 // This isn't remotely correct, but it will have to suffice until I have
423 // time to figure out what's actually going on here...
424 channel->vol = aica_volume_table[max((val & 0xFF),((val>>8)&0xFF))];
425 break;
426 default: /* ??? */
427 break;
428 }
430 }
.