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