Search
lxdream.org :: lxdream/src/aica/aica.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/aica/aica.c
changeset 463:0655796f9bb5
prev434:8af49a412d92
next465:3bd7be575792
author nkeynes
date Wed Oct 24 21:24:09 2007 +0000 (15 years ago)
permissions -rw-r--r--
last change Implement channel position readback
view annotate diff log raw
     1 /**
     2  * $Id: aica.c,v 1.24 2007-10-24 21:24:09 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 <time.h>
    22 #include "dream.h"
    23 #include "dreamcast.h"
    24 #include "mem.h"
    25 #include "aica/aica.h"
    26 #include "armcore.h"
    27 #include "aica/audio.h"
    28 #define MMIO_IMPL
    29 #include "aica.h"
    31 MMIO_REGION_READ_DEFFN( AICA0 )
    32 MMIO_REGION_READ_DEFFN( AICA1 )
    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 /* 20 years in seconds */
    47 #define RTC_OFFSET 631152000
    48 unsigned int aica_time_of_day = 0;
    50 /**
    51  * Initialize the AICA subsystem. Note requires that 
    52  */
    53 void aica_init( void )
    54 {
    55     register_io_regions( mmio_list_spu );
    56     MMIO_NOTRACE(AICA0);
    57     MMIO_NOTRACE(AICA1);
    58     arm_mem_init();
    59     aica_reset();
    60 }
    62 void aica_reset( void )
    63 {
    64     arm_reset();
    65     aica_event(2); /* Pre-deliver a timer interrupt */
    66     aica_time_of_day = 0x5bfc8900;
    67 }
    69 void aica_start( void )
    70 {
    72 }
    74 /**
    75  * Keep track of what we've done so far this second, to try to keep the
    76  * precision of samples/second.
    77  */
    78 int samples_done = 0;
    79 uint32_t nanosecs_done = 0;
    81 uint32_t aica_run_slice( uint32_t nanosecs )
    82 {
    83     /* Run arm instructions */
    84     int reset = MMIO_READ( AICA2, AICA_RESET );
    85     if( (reset & 1) == 0 ) { /* Running */
    86 	int num_samples = (int)((uint64_t)AICA_SAMPLE_RATE * (nanosecs_done + nanosecs) / 1000000000) - samples_done;
    87 	num_samples = arm_run_slice( num_samples );
    88 	audio_mix_samples( num_samples );
    90 	samples_done += num_samples;
    91 	nanosecs_done += nanosecs;
    92     }
    93     if( nanosecs_done > 1000000000 ) {
    94 	samples_done -= AICA_SAMPLE_RATE;
    95 	nanosecs_done -= 1000000000;
    96 	aica_time_of_day++;
    97     }
    98     return nanosecs;
    99 }
   101 void aica_stop( void )
   102 {
   104 }
   106 void aica_save_state( FILE *f )
   107 {
   108     arm_save_state( f );
   109 }
   111 int aica_load_state( FILE *f )
   112 {
   113     return arm_load_state( f );
   114 }
   116 int aica_event_pending = 0;
   117 int aica_clear_count = 0;
   119 /* Note: This is probably not necessarily technically correct but it should
   120  * work in the meantime.
   121  */
   123 void aica_event( int event )
   124 {
   125     if( aica_event_pending == 0 )
   126 	armr.int_pending |= CPSR_F;
   127     aica_event_pending |= (1<<event);
   129     int pending = MMIO_READ( AICA2, AICA_IRQ );
   130     if( pending == 0 || event < pending )
   131 	MMIO_WRITE( AICA2, AICA_IRQ, event );
   132 }
   134 void aica_clear_event( )
   135 {
   136     aica_clear_count++;
   137     if( aica_clear_count == 4 ) {
   138 	int i;
   139 	aica_clear_count = 0;
   141 	for( i=0; i<8; i++ ) {
   142 	    if( aica_event_pending & (1<<i) ) {
   143 		aica_event_pending &= ~(1<<i);
   144 		break;
   145 	    }
   146 	}
   147 	for( ;i<8; i++ ) {
   148 	    if( aica_event_pending & (1<<i) ) {
   149 		MMIO_WRITE( AICA2, AICA_IRQ, i );
   150 		break;
   151 	    }
   152 	}
   153 	if( aica_event_pending == 0 )
   154 	    armr.int_pending &= ~CPSR_F;
   155     }
   156 }
   158 void aica_enable( void )
   159 {
   160     mmio_region_AICA2_write( AICA_RESET, MMIO_READ(AICA2,AICA_RESET) & ~1 );
   161 }
   163 /** Channel register structure:
   164  * 00  4  Channel config
   165  * 04  4  Waveform address lo (16 bits)
   166  * 08  4  Loop start address
   167  * 0C  4  Loop end address
   168  * 10  4  Volume envelope
   169  * 14  4  Init to 0x1F
   170  * 18  4  Frequency (floating point)
   171  * 1C  4  ?? 
   172  * 20  4  ??
   173  * 24  1  Pan
   174  * 25  1  ??
   175  * 26  
   176  * 27  
   177  * 28  1  ??
   178  * 29  1  Volume
   179  * 2C
   180  * 30
   181  */
   183 /* Write to channels 0-31 */
   184 void mmio_region_AICA0_write( uint32_t reg, uint32_t val )
   185 {
   186     MMIO_WRITE( AICA0, reg, val );
   187     aica_write_channel( reg >> 7, reg % 128, val );
   188     //    DEBUG( "AICA0 Write %08X => %08X", val, reg );
   189 }
   191 /* Write to channels 32-64 */
   192 void mmio_region_AICA1_write( uint32_t reg, uint32_t val )
   193 {
   194     MMIO_WRITE( AICA1, reg, val );
   195     aica_write_channel( (reg >> 7) + 32, reg % 128, val );
   196     // DEBUG( "AICA1 Write %08X => %08X", val, reg );
   197 }
   199 /**
   200  * AICA control registers 
   201  */
   202 void mmio_region_AICA2_write( uint32_t reg, uint32_t val )
   203 {
   204     uint32_t tmp;
   205     switch( reg ) {
   206     case AICA_RESET:
   207 	tmp = MMIO_READ( AICA2, AICA_RESET );
   208 	if( (tmp & 1) == 1 && (val & 1) == 0 ) {
   209 	    /* ARM enabled - execute a core reset */
   210 	    DEBUG( "ARM enabled" );
   211 	    arm_reset();
   212 	    samples_done = 0;
   213 	    nanosecs_done = 0;
   214 	} else if( (tmp&1) == 0 && (val&1) == 1 ) {
   215 	    DEBUG( "ARM disabled" );
   216 	}
   217 	MMIO_WRITE( AICA2, AICA_RESET, val );
   218 	break;
   219     case AICA_IRQCLEAR:
   220 	aica_clear_event();
   221 	break;
   222     default:
   223 	MMIO_WRITE( AICA2, reg, val );
   224 	break;
   225     }
   226 }
   228 int32_t mmio_region_AICA2_read( uint32_t reg )
   229 {
   230     audio_channel_t channel;
   231     uint32_t channo;
   232     int32_t val;
   233     switch( reg ) {
   234     case AICA_CHANSTATE:
   235 	channo = (MMIO_READ( AICA2, AICA_CHANSEL ) >> 8) & 0x3F;
   236 	channel = audio_get_channel(channo);
   237 	if( channel->loop == LOOP_LOOPED ) {
   238 	    val = 0x8000;
   239 	    channel->loop = LOOP_ON;
   240 	} else {
   241 	    val = 0;
   242 	}
   243 	return val;
   244     case AICA_CHANPOSN:
   245 	channo = (MMIO_READ( AICA2, AICA_CHANSEL ) >> 8) & 0x3F;
   246 	channel = audio_get_channel(channo);
   247 	return channel->posn;
   248     default:
   249 	return MMIO_READ( AICA2, reg );
   250     }
   251 }
   253 int32_t mmio_region_AICARTC_read( uint32_t reg )
   254 {
   255     int32_t rv = 0;
   256     switch( reg ) {
   257     case AICA_RTCHI:
   258         rv = (aica_time_of_day >> 16) & 0xFFFF;
   259 	break;
   260     case AICA_RTCLO:
   261 	rv = aica_time_of_day & 0xFFFF;
   262 	break;
   263     }
   264     // DEBUG( "Read AICA RTC %d => %08X", reg, rv );
   265     return rv;
   266 }
   269 void mmio_region_AICARTC_write( uint32_t reg, uint32_t val )
   270 {
   271     switch( reg ) {
   272     case AICA_RTCEN:
   273 	MMIO_WRITE( AICARTC, reg, val&0x01 );
   274 	break;
   275     case AICA_RTCLO:
   276 	if( MMIO_READ( AICARTC, AICA_RTCEN ) & 0x01 ) {
   277 	    aica_time_of_day = (aica_time_of_day & 0xFFFF0000) | (val & 0xFFFF);
   278 	}
   279 	break;
   280     case AICA_RTCHI:
   281 	if( MMIO_READ( AICARTC, AICA_RTCEN ) & 0x01 ) {
   282 	    aica_time_of_day = (aica_time_of_day & 0xFFFF) | (val<<16);
   283 	    MMIO_WRITE( AICARTC, AICA_RTCEN, 0 );
   284 	}
   285 	break;
   286     }
   287 }
   289 /**
   290  * Translate the channel frequency to a sample rate. The frequency is a
   291  * 14-bit floating point number, where bits 0..9 is the mantissa,
   292  * 11..14 is the signed exponent (-8 to +7). Bit 10 appears to
   293  * be unused.
   294  *
   295  * @return sample rate in samples per second.
   296  */
   297 uint32_t aica_frequency_to_sample_rate( uint32_t freq )
   298 {
   299     uint32_t exponent = (freq & 0x3800) >> 11;
   300     uint32_t mantissa = freq & 0x03FF;
   301     uint32_t rate;
   302     if( freq & 0x4000 ) {
   303 	/* neg exponent - rate < 44100 */
   304 	exponent = 8 - exponent;
   305 	rate = (44100 >> exponent) +
   306 	    ((44100 * mantissa) >> (10+exponent));
   307     } else {
   308 	/* pos exponent - rate > 44100 */
   309 	rate = (44100 << exponent) +
   310 	    ((44100 * mantissa) >> (10-exponent));
   311     }
   312     return rate;
   313 }
   315 void aica_start_stop_channels()
   316 {
   317     int i;
   318     for( i=0; i<32; i++ ) {
   319 	uint32_t val = MMIO_READ( AICA0, i<<7 );
   320 	audio_start_stop_channel(i, val&0x4000);
   321     }
   322     for( ; i<64; i++ ) {
   323 	uint32_t val = MMIO_READ( AICA1, (i-32)<<7 );
   324 	audio_start_stop_channel(i, val&0x4000);
   325     }
   326 }
   328 /**
   329  * Derived directly from Dan Potter's log table
   330  */
   331 uint8_t aica_volume_table[256] = {
   332       0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   1,
   333       1,   1,   1,   1,   1,   1,   2,   2,   2,   2,   2,   3,   3,   3,   3,   4,
   334       4,   4,   4,   5,   5,   5,   5,   6,   6,   6,   7,   7,   7,   8,   8,   9,
   335       9,   9,  10,  10,  11,  11,  11,  12,  12,  13,  13,  14,  14,  15,  15,  16,
   336      16,  17,  17,  18,  18,  19,  19,  20,  20,  21,  22,  22,  23,  23,  24,  25,
   337      25,  26,  27,  27,  28,  29,  29,  30,  31,  31,  32,  33,  34,  34,  35,  36,
   338      37,  37,  38,  39,  40,  40,  41,  42,  43,  44,  45,  45,  46,  47,  48,  49,
   339      50,  51,  52,  52,  53,  54,  55,  56,  57,  58,  59,  60,  61,  62,  63,  64,
   340      65,  66,  67,  68,  69,  70,  71,  72,  73,  74,  76,  77,  78,  79,  80,  81,
   341      82,  83,  85,  86,  87,  88,  89,  90,  92,  93,  94,  95,  97,  98,  99, 100,
   342     102, 103, 104, 105, 107, 108, 109, 111, 112, 113, 115, 116, 117, 119, 120, 121,
   343     123, 124, 126, 127, 128, 130, 131, 133, 134, 136, 137, 139, 140, 142, 143, 145,
   344     146, 148, 149, 151, 152, 154, 155, 157, 159, 160, 162, 163, 165, 167, 168, 170,
   345     171, 173, 175, 176, 178, 180, 181, 183, 185, 187, 188, 190, 192, 194, 195, 197,
   346     199, 201, 202, 204, 206, 208, 210, 211, 213, 215, 217, 219, 221, 223, 224, 226,
   347     228, 230, 232, 234, 236, 238, 240, 242, 244, 246, 248, 250, 252, 253, 254, 255 };
   350 void aica_write_channel( int channelNo, uint32_t reg, uint32_t val ) 
   351 {
   352     val &= 0x0000FFFF;
   353     audio_channel_t channel = audio_get_channel(channelNo);
   354     switch( reg ) {
   355     case 0x00: /* Config + high address bits*/
   356 	channel->start = (channel->start & 0xFFFF) | ((val&0x1F) << 16);
   357 	if( val & 0x200 ) 
   358 	    channel->loop = LOOP_ON;
   359 	else 
   360 	    channel->loop = LOOP_OFF;
   361 	switch( (val >> 7) & 0x03 ) {
   362 	case 0:
   363 	    channel->sample_format = AUDIO_FMT_16BIT;
   364 	    break;
   365 	case 1:
   366 	    channel->sample_format = AUDIO_FMT_8BIT;
   367 	    break;
   368 	case 2:
   369 	case 3:
   370 	    channel->sample_format = AUDIO_FMT_ADPCM;
   371 	    break;
   372 	}
   373 	if( val & 0x8000 ) {
   374 	    aica_start_stop_channels();
   375 	}
   376 	break;
   377     case 0x04: /* Low 16 address bits */
   378 	channel->start = (channel->start & 0x001F0000) | val;
   379 	break;
   380     case 0x08: /* Loop start */
   381 	channel->loop_start = val;
   382 	break;
   383     case 0x0C: /* End */
   384 	channel->end = val;
   385 	break;
   386     case 0x10: /* Envelope register 1 */
   387 	break;
   388     case 0x14: /* Envelope register 2 */
   389 	break;
   390     case 0x18: /* Frequency */
   391 	channel->sample_rate = aica_frequency_to_sample_rate ( val );
   392 	break;
   393     case 0x1C: /* ??? */
   394     case 0x20: /* ??? */
   395     case 0x24: /* Volume? /pan */
   396 	val = val & 0x1F;
   397 	if( val <= 0x0F ) 
   398 	    val = 0x0F - val; /* Convert to smooth pan over 0..31 */
   399 	channel->pan = val;
   400 	break;
   401     case 0x28: /* Volume */
   402 	channel->vol = aica_volume_table[val & 0xFF];
   403 	break;
   404     default: /* ??? */
   405 	break;
   406     }
   408 }
.