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