Search
lxdream.org :: lxdream/src/aica/aica.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/aica/aica.c
changeset 82:81a4acf75f10
prev76:e9a0bd313036
next86:f151e63f9754
author nkeynes
date Tue Jan 17 12:54:02 2006 +0000 (16 years ago)
permissions -rw-r--r--
last change Add basic attempt at panning + proper volume
view annotate diff log raw
     1 /**
     2  * $Id: aica.c,v 1.15 2006-01-17 12:54:02 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 /** Channel register structure:
   154  * 00  4  Channel config
   155  * 04  4  Waveform address lo (16 bits)
   156  * 08  4  Loop start address
   157  * 0C  4  Loop end address
   158  * 10  4  Volume envelope
   159  * 14  4  Init to 0x1F
   160  * 18  4  Frequency (floating point)
   161  * 1C  4  ?? 
   162  * 20  4  ??
   163  * 24  1  Pan
   164  * 25  1  ??
   165  * 26  
   166  * 27  
   167  * 28  1  ??
   168  * 29  1  Volume
   169  * 2C
   170  * 30
   171  * 
   173 /* Write to channels 0-31 */
   174 void mmio_region_AICA0_write( uint32_t reg, uint32_t val )
   175 {
   176     MMIO_WRITE( AICA0, reg, val );
   177     aica_write_channel( reg >> 7, reg % 128, val );
   178     //    DEBUG( "AICA0 Write %08X => %08X", val, reg );
   179 }
   181 /* Write to channels 32-64 */
   182 void mmio_region_AICA1_write( uint32_t reg, uint32_t val )
   183 {
   184     MMIO_WRITE( AICA1, reg, val );
   185     aica_write_channel( (reg >> 7) + 32, reg % 128, val );
   186     // DEBUG( "AICA1 Write %08X => %08X", val, reg );
   187 }
   189 /**
   190  * AICA control registers 
   191  */
   192 void mmio_region_AICA2_write( uint32_t reg, uint32_t val )
   193 {
   194     uint32_t tmp;
   195     switch( reg ) {
   196     case AICA_RESET:
   197 	tmp = MMIO_READ( AICA2, AICA_RESET );
   198 	if( (tmp & 1) == 1 && (val & 1) == 0 ) {
   199 	    /* ARM enabled - execute a core reset */
   200 	    DEBUG( "ARM enabled" );
   201 	    arm_reset();
   202 	    samples_done = 0;
   203 	    nanosecs_done = 0;
   204 	} else if( (tmp&1) == 0 && (val&1) == 1 ) {
   205 	    DEBUG( "ARM disabled" );
   206 	}
   207 	MMIO_WRITE( AICA2, AICA_RESET, val );
   208 	break;
   209     case AICA_IRQCLEAR:
   210 	aica_clear_event();
   211 	break;
   212     default:
   213 	MMIO_WRITE( AICA2, reg, val );
   214 	break;
   215     }
   216 }
   218 /**
   219  * Translate the channel frequency to a sample rate. The frequency is a
   220  * 14-bit floating point number, where bits 0..9 is the mantissa,
   221  * 11..14 is the signed exponent (-8 to +7). Bit 10 appears to
   222  * be unused.
   223  *
   224  * @return sample rate in samples per second.
   225  */
   226 uint32_t aica_frequency_to_sample_rate( uint32_t freq )
   227 {
   228     uint32_t exponent = (freq & 0x3800) >> 11;
   229     uint32_t mantissa = freq & 0x03FF;
   230     uint32_t rate;
   231     if( freq & 0x4000 ) {
   232 	/* neg exponent - rate < 44100 */
   233 	exponent = 8 - exponent;
   234 	rate = (44100 >> exponent) +
   235 	    ((44100 * mantissa) >> (10+exponent));
   236     } else {
   237 	/* pos exponent - rate > 44100 */
   238 	rate = (44100 << exponent) +
   239 	    ((44100 * mantissa) >> (10-exponent));
   240     }
   241     return rate;
   242 }
   244 /**
   245  * Derived directly from Dan Potter's log table
   246  */
   247 uint8_t aica_volume_table[256] = {
   248       0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   1,
   249       1,   1,   1,   1,   1,   1,   2,   2,   2,   2,   2,   3,   3,   3,   3,   4,
   250       4,   4,   4,   5,   5,   5,   5,   6,   6,   6,   7,   7,   7,   8,   8,   9,
   251       9,   9,  10,  10,  11,  11,  11,  12,  12,  13,  13,  14,  14,  15,  15,  16,
   252      16,  17,  17,  18,  18,  19,  19,  20,  20,  21,  22,  22,  23,  23,  24,  25,
   253      25,  26,  27,  27,  28,  29,  29,  30,  31,  31,  32,  33,  34,  34,  35,  36,
   254      37,  37,  38,  39,  40,  40,  41,  42,  43,  44,  45,  45,  46,  47,  48,  49,
   255      50,  51,  52,  52,  53,  54,  55,  56,  57,  58,  59,  60,  61,  62,  63,  64,
   256      65,  66,  67,  68,  69,  70,  71,  72,  73,  74,  76,  77,  78,  79,  80,  81,
   257      82,  83,  85,  86,  87,  88,  89,  90,  92,  93,  94,  95,  97,  98,  99, 100,
   258     102, 103, 104, 105, 107, 108, 109, 111, 112, 113, 115, 116, 117, 119, 120, 121,
   259     123, 124, 126, 127, 128, 130, 131, 133, 134, 136, 137, 139, 140, 142, 143, 145,
   260     146, 148, 149, 151, 152, 154, 155, 157, 159, 160, 162, 163, 165, 167, 168, 170,
   261     171, 173, 175, 176, 178, 180, 181, 183, 185, 187, 188, 190, 192, 194, 195, 197,
   262     199, 201, 202, 204, 206, 208, 210, 211, 213, 215, 217, 219, 221, 223, 224, 226,
   263     228, 230, 232, 234, 236, 238, 240, 242, 244, 246, 248, 250, 252, 253, 254, 255 };
   266 void aica_write_channel( int channelNo, uint32_t reg, uint32_t val ) 
   267 {
   268     val &= 0x0000FFFF;
   269     audio_channel_t channel = audio_get_channel(channelNo);
   270     switch( reg ) {
   271     case 0x00: /* Config + high address bits*/
   272 	channel->start = (channel->start & 0xFFFF) | ((val&0x1F) << 16);
   273 	if( val & 0x200 ) 
   274 	    channel->loop = TRUE;
   275 	else 
   276 	    channel->loop = FALSE;
   277 	switch( (val >> 7) & 0x03 ) {
   278 	case 0:
   279 	    channel->sample_format = AUDIO_FMT_16BIT;
   280 	    break;
   281 	case 1:
   282 	    channel->sample_format = AUDIO_FMT_8BIT;
   283 	    break;
   284 	case 2:
   285 	case 3:
   286 	    channel->sample_format = AUDIO_FMT_ADPCM;
   287 	    break;
   288 	}
   289 	switch( (val >> 14) & 0x03 ) {
   290 	case 2: 
   291 	    audio_stop_channel( channelNo ); 
   292 	    break;
   293 	case 3: 
   294 	    audio_start_channel( channelNo ); 
   295 	    break;
   296 	default:
   297 	    break;
   298 	    /* Hrmm... */
   299 	}
   300 	break;
   301     case 0x04: /* Low 16 address bits */
   302 	channel->start = (channel->start & 0x001F0000) | val;
   303 	break;
   304     case 0x08: /* Loop start */
   305 	channel->loop_start = val;
   306 	break;
   307     case 0x0C: /* End */
   308 	channel->end = val;
   309 	break;
   310     case 0x10: /* Envelope register 1 */
   311 	break;
   312     case 0x14: /* Envelope register 2 */
   313 	break;
   314     case 0x18: /* Frequency */
   315 	channel->sample_rate = aica_frequency_to_sample_rate ( val );
   316 	break;
   317     case 0x1C: /* ??? */
   318     case 0x20: /* ??? */
   319     case 0x24: /* Volume? /pan */
   320 	val = val & 0x1F;
   321 	if( val <= 0x0F ) 
   322 	    val = 0x0F - val; /* Convert to smooth pan over 0..31 */
   323 	channel->pan = val;
   324 	break;
   325     case 0x28: /* Volume */
   326 	channel->vol = aica_volume_table[val & 0xFF];
   327 	break;
   328     default: /* ??? */
   329 	break;
   330     }
   332 }
.