Search
lxdream.org :: lxdream/src/aica/aica.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/aica/aica.c
changeset 561:533f6b478071
prev473:bbbeca9ccf13
next642:c7383f21f122
author nkeynes
date Tue Jan 01 05:08:38 2008 +0000 (12 years ago)
branchlxdream-mmu
permissions -rw-r--r--
last change Enable Id keyword on all source files
view annotate diff log raw
     1 /**
     2  * $Id$
     3  * 
     4  * This module implements the AICA's IO interfaces, as well
     5  * as providing the core AICA module to the system.
     6  *
     7  * Copyright (c) 2005 Nathan Keynes.
     8  *
     9  * This program is free software; you can redistribute it and/or modify
    10  * it under the terms of the GNU General Public License as published by
    11  * the Free Software Foundation; either version 2 of the License, or
    12  * (at your option) any later version.
    13  *
    14  * This program is distributed in the hope that it will be useful,
    15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    17  * GNU General Public License for more details.
    18  */
    20 #define MODULE aica_module
    22 #include <time.h>
    23 #include "dream.h"
    24 #include "dreamcast.h"
    25 #include "mem.h"
    26 #include "aica/aica.h"
    27 #include "armcore.h"
    28 #include "aica/audio.h"
    29 #define MMIO_IMPL
    30 #include "aica.h"
    32 MMIO_REGION_READ_DEFFN( AICA0 )
    33 MMIO_REGION_READ_DEFFN( AICA1 )
    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 struct aica_state_struct {
    48     uint32_t time_of_day;
    49     /**
    50      * Keep track of what we've done so far this second, to try to keep the
    51      * precision of samples/second.
    52      */
    53     uint32_t samples_done;
    54     uint32_t nanosecs_done;
    55     /**
    56      * Event (IRQ) state
    57      */
    58     int event_pending;
    59     int clear_count;
    60 };
    62 static struct aica_state_struct aica_state;
    65 /**
    66  * Initialize the AICA subsystem. Note requires that 
    67  */
    68 void aica_init( void )
    69 {
    70     register_io_regions( mmio_list_spu );
    71     MMIO_NOTRACE(AICA0);
    72     MMIO_NOTRACE(AICA1);
    73     arm_mem_init();
    74     aica_reset();
    75 }
    77 void aica_reset( void )
    78 {
    79     arm_reset();
    80     aica_state.time_of_day = 0x5bfc8900;
    81     aica_state.samples_done = 0;
    82     aica_state.nanosecs_done = 0;
    83     aica_state.event_pending = 0;
    84     aica_state.clear_count = 0;
    85     aica_event(2); /* Pre-deliver a timer interrupt */
    86 }
    88 void aica_start( void )
    89 {
    91 }
    93 uint32_t aica_run_slice( uint32_t nanosecs )
    94 {
    95     /* Run arm instructions */
    96     int reset = MMIO_READ( AICA2, AICA_RESET );
    97     if( (reset & 1) == 0 ) { /* Running */
    98 	int num_samples = (int)((uint64_t)AICA_SAMPLE_RATE * (aica_state.nanosecs_done + nanosecs) / 1000000000) - aica_state.samples_done;
    99 	num_samples = arm_run_slice( num_samples );
   100 	audio_mix_samples( num_samples );
   102 	aica_state.samples_done += num_samples;
   103 	aica_state.nanosecs_done += nanosecs;
   104     }
   105     if( aica_state.nanosecs_done > 1000000000 ) {
   106 	aica_state.samples_done -= AICA_SAMPLE_RATE;
   107 	aica_state.nanosecs_done -= 1000000000;
   108 	aica_state.time_of_day++;
   109     }
   110     return nanosecs;
   111 }
   113 void aica_stop( void )
   114 {
   116 }
   118 void aica_save_state( FILE *f )
   119 {
   120     fwrite( &aica_state, sizeof(struct aica_state_struct), 1, f );
   121     arm_save_state( f );
   122     audio_save_state(f);
   123 }
   125 int aica_load_state( FILE *f )
   126 {
   127     fread( &aica_state, sizeof(struct aica_state_struct), 1, f );
   128     arm_load_state( f );
   129     return audio_load_state(f);
   130 }
   132 /* Note: This is probably not necessarily technically correct but it should
   133  * work in the meantime.
   134  */
   136 void aica_event( int event )
   137 {
   138     if( aica_state.event_pending == 0 )
   139 	armr.int_pending |= CPSR_F;
   140     aica_state.event_pending |= (1<<event);
   142     int pending = MMIO_READ( AICA2, AICA_IRQ );
   143     if( pending == 0 || event < pending )
   144 	MMIO_WRITE( AICA2, AICA_IRQ, event );
   145 }
   147 void aica_clear_event( )
   148 {
   149     aica_state.clear_count++;
   150     if( aica_state.clear_count == 4 ) {
   151 	int i;
   152 	aica_state.clear_count = 0;
   154 	for( i=0; i<8; i++ ) {
   155 	    if( aica_state.event_pending & (1<<i) ) {
   156 		aica_state.event_pending &= ~(1<<i);
   157 		break;
   158 	    }
   159 	}
   160 	for( ;i<8; i++ ) {
   161 	    if( aica_state.event_pending & (1<<i) ) {
   162 		MMIO_WRITE( AICA2, AICA_IRQ, i );
   163 		break;
   164 	    }
   165 	}
   166 	if( aica_state.event_pending == 0 )
   167 	    armr.int_pending &= ~CPSR_F;
   168     }
   169 }
   171 void aica_enable( void )
   172 {
   173     mmio_region_AICA2_write( AICA_RESET, MMIO_READ(AICA2,AICA_RESET) & ~1 );
   174 }
   176 /** Channel register structure:
   177  * 00  4  Channel config
   178  * 04  4  Waveform address lo (16 bits)
   179  * 08  4  Loop start address
   180  * 0C  4  Loop end address
   181  * 10  4  Volume envelope
   182  * 14  4  Init to 0x1F
   183  * 18  4  Frequency (floating point)
   184  * 1C  4  ?? 
   185  * 20  4  ??
   186  * 24  1  Pan
   187  * 25  1  ??
   188  * 26  
   189  * 27  
   190  * 28  1  ??
   191  * 29  1  Volume
   192  * 2C
   193  * 30
   194  */
   196 /* Write to channels 0-31 */
   197 void mmio_region_AICA0_write( uint32_t reg, uint32_t val )
   198 {
   199     MMIO_WRITE( AICA0, reg, val );
   200     aica_write_channel( reg >> 7, reg % 128, val );
   201     //    DEBUG( "AICA0 Write %08X => %08X", val, reg );
   202 }
   204 /* Write to channels 32-64 */
   205 void mmio_region_AICA1_write( uint32_t reg, uint32_t val )
   206 {
   207     MMIO_WRITE( AICA1, reg, val );
   208     aica_write_channel( (reg >> 7) + 32, reg % 128, val );
   209     // DEBUG( "AICA1 Write %08X => %08X", val, reg );
   210 }
   212 /**
   213  * AICA control registers 
   214  */
   215 void mmio_region_AICA2_write( uint32_t reg, uint32_t val )
   216 {
   217     uint32_t tmp;
   219     switch( reg ) {
   220     case AICA_RESET:
   221 	tmp = MMIO_READ( AICA2, AICA_RESET );
   222 	if( (tmp & 1) == 1 && (val & 1) == 0 ) {
   223 	    /* ARM enabled - execute a core reset */
   224 	    DEBUG( "ARM enabled" );
   225 	    arm_reset();
   226 	    aica_state.samples_done = 0;
   227 	    aica_state.nanosecs_done = 0;
   228 	} else if( (tmp&1) == 0 && (val&1) == 1 ) {
   229 	    DEBUG( "ARM disabled" );
   230 	}
   231 	MMIO_WRITE( AICA2, AICA_RESET, val );
   232 	break;
   233     case AICA_IRQCLEAR:
   234 	aica_clear_event();
   235 	break;
   236     default:
   237 	MMIO_WRITE( AICA2, reg, val );
   238 	break;
   239     }
   240 }
   242 int32_t mmio_region_AICA2_read( uint32_t reg )
   243 {
   244     audio_channel_t channel;
   245     uint32_t channo;
   246     int32_t val;
   247     switch( reg ) {
   248     case AICA_CHANSTATE:
   249 	channo = (MMIO_READ( AICA2, AICA_CHANSEL ) >> 8) & 0x3F;
   250 	channel = audio_get_channel(channo);
   251 	if( channel->loop == LOOP_LOOPED ) {
   252 	    val = 0x8000;
   253 	    channel->loop = LOOP_ON;
   254 	} else {
   255 	    val = 0;
   256 	}
   257 	return val;
   258     case AICA_CHANPOSN:
   259 	channo = (MMIO_READ( AICA2, AICA_CHANSEL ) >> 8) & 0x3F;
   260 	channel = audio_get_channel(channo);
   261 	return channel->posn;
   262     default:
   263 	return MMIO_READ( AICA2, reg );
   264     }
   265 }
   267 int32_t mmio_region_AICARTC_read( uint32_t reg )
   268 {
   269     int32_t rv = 0;
   270     switch( reg ) {
   271     case AICA_RTCHI:
   272         rv = (aica_state.time_of_day >> 16) & 0xFFFF;
   273 	break;
   274     case AICA_RTCLO:
   275 	rv = aica_state.time_of_day & 0xFFFF;
   276 	break;
   277     }
   278     // DEBUG( "Read AICA RTC %d => %08X", reg, rv );
   279     return rv;
   280 }
   283 void mmio_region_AICARTC_write( uint32_t reg, uint32_t val )
   284 {
   285     switch( reg ) {
   286     case AICA_RTCEN:
   287 	MMIO_WRITE( AICARTC, reg, val&0x01 );
   288 	break;
   289     case AICA_RTCLO:
   290 	if( MMIO_READ( AICARTC, AICA_RTCEN ) & 0x01 ) {
   291 	    aica_state.time_of_day = (aica_state.time_of_day & 0xFFFF0000) | (val & 0xFFFF);
   292 	}
   293 	break;
   294     case AICA_RTCHI:
   295 	if( MMIO_READ( AICARTC, AICA_RTCEN ) & 0x01 ) {
   296 	    aica_state.time_of_day = (aica_state.time_of_day & 0xFFFF) | (val<<16);
   297 	    MMIO_WRITE( AICARTC, AICA_RTCEN, 0 );
   298 	}
   299 	break;
   300     }
   301 }
   303 /**
   304  * Translate the channel frequency to a sample rate. The frequency is a
   305  * 14-bit floating point number, where bits 0..9 is the mantissa,
   306  * 11..14 is the signed exponent (-8 to +7). Bit 10 appears to
   307  * be unused.
   308  *
   309  * @return sample rate in samples per second.
   310  */
   311 uint32_t aica_frequency_to_sample_rate( uint32_t freq )
   312 {
   313     uint32_t exponent = (freq & 0x3800) >> 11;
   314     uint32_t mantissa = freq & 0x03FF;
   315     uint32_t rate;
   316     if( freq & 0x4000 ) {
   317 	/* neg exponent - rate < 44100 */
   318 	exponent = 8 - exponent;
   319 	rate = (44100 >> exponent) +
   320 	    ((44100 * mantissa) >> (10+exponent));
   321     } else {
   322 	/* pos exponent - rate > 44100 */
   323 	rate = (44100 << exponent) +
   324 	    ((44100 * mantissa) >> (10-exponent));
   325     }
   326     return rate;
   327 }
   329 void aica_start_stop_channels()
   330 {
   331     int i;
   332     for( i=0; i<32; i++ ) {
   333 	uint32_t val = MMIO_READ( AICA0, i<<7 );
   334 	audio_start_stop_channel(i, val&0x4000);
   335     }
   336     for( ; i<64; i++ ) {
   337 	uint32_t val = MMIO_READ( AICA1, (i-32)<<7 );
   338 	audio_start_stop_channel(i, val&0x4000);
   339     }
   340 }
   342 /**
   343  * Derived directly from Dan Potter's log table
   344  */
   345 uint8_t aica_volume_table[256] = {
   346       0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   1,
   347       1,   1,   1,   1,   1,   1,   2,   2,   2,   2,   2,   3,   3,   3,   3,   4,
   348       4,   4,   4,   5,   5,   5,   5,   6,   6,   6,   7,   7,   7,   8,   8,   9,
   349       9,   9,  10,  10,  11,  11,  11,  12,  12,  13,  13,  14,  14,  15,  15,  16,
   350      16,  17,  17,  18,  18,  19,  19,  20,  20,  21,  22,  22,  23,  23,  24,  25,
   351      25,  26,  27,  27,  28,  29,  29,  30,  31,  31,  32,  33,  34,  34,  35,  36,
   352      37,  37,  38,  39,  40,  40,  41,  42,  43,  44,  45,  45,  46,  47,  48,  49,
   353      50,  51,  52,  52,  53,  54,  55,  56,  57,  58,  59,  60,  61,  62,  63,  64,
   354      65,  66,  67,  68,  69,  70,  71,  72,  73,  74,  76,  77,  78,  79,  80,  81,
   355      82,  83,  85,  86,  87,  88,  89,  90,  92,  93,  94,  95,  97,  98,  99, 100,
   356     102, 103, 104, 105, 107, 108, 109, 111, 112, 113, 115, 116, 117, 119, 120, 121,
   357     123, 124, 126, 127, 128, 130, 131, 133, 134, 136, 137, 139, 140, 142, 143, 145,
   358     146, 148, 149, 151, 152, 154, 155, 157, 159, 160, 162, 163, 165, 167, 168, 170,
   359     171, 173, 175, 176, 178, 180, 181, 183, 185, 187, 188, 190, 192, 194, 195, 197,
   360     199, 201, 202, 204, 206, 208, 210, 211, 213, 215, 217, 219, 221, 223, 224, 226,
   361     228, 230, 232, 234, 236, 238, 240, 242, 244, 246, 248, 250, 252, 253, 254, 255 };
   364 void aica_write_channel( int channelNo, uint32_t reg, uint32_t val ) 
   365 {
   366     val &= 0x0000FFFF;
   367     audio_channel_t channel = audio_get_channel(channelNo);
   368     switch( reg ) {
   369     case 0x00: /* Config + high address bits*/
   370 	channel->start = (channel->start & 0xFFFF) | ((val&0x1F) << 16);
   371 	if( val & 0x200 ) 
   372 	    channel->loop = LOOP_ON;
   373 	else 
   374 	    channel->loop = LOOP_OFF;
   375 	switch( (val >> 7) & 0x03 ) {
   376 	case 0:
   377 	    channel->sample_format = AUDIO_FMT_16BIT;
   378 	    break;
   379 	case 1:
   380 	    channel->sample_format = AUDIO_FMT_8BIT;
   381 	    break;
   382 	case 2:
   383 	case 3:
   384 	    channel->sample_format = AUDIO_FMT_ADPCM;
   385 	    break;
   386 	}
   387 	if( val & 0x8000 ) {
   388 	    aica_start_stop_channels();
   389 	}
   390 	break;
   391     case 0x04: /* Low 16 address bits */
   392 	channel->start = (channel->start & 0x001F0000) | val;
   393 	break;
   394     case 0x08: /* Loop start */
   395 	channel->loop_start = val;
   396 	break;
   397     case 0x0C: /* End */
   398 	channel->end = val;
   399 	break;
   400     case 0x10: /* Envelope register 1 */
   401 	break;
   402     case 0x14: /* Envelope register 2 */
   403 	break;
   404     case 0x18: /* Frequency */
   405 	channel->sample_rate = aica_frequency_to_sample_rate ( val );
   406 	break;
   407     case 0x1C: /* ??? */
   408     case 0x20: /* ??? */
   409     case 0x24: /* Volume? /pan */
   410 	val = val & 0x1F;
   411 	if( val <= 0x0F ) 
   412 	    val = 0x0F - val; /* Convert to smooth pan over 0..31 */
   413 	channel->pan = val;
   414 	break;
   415     case 0x28: /* Volume */
   416 	// This isn't remotely correct, but it will have to suffice until I have
   417 	// time to figure out what's actually going on here... 
   418 	channel->vol = aica_volume_table[max((val & 0xFF),((val>>8)&0xFF))];
   419 	break;
   420     default: /* ??? */
   421 	break;
   422     }
   424 }
.