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