Search
lxdream.org :: lxdream/src/aica/aica.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/aica/aica.c
changeset 301:1ace395139c3
prev241:776e46e58d6d
next431:248dd77a9e44
author nkeynes
date Wed Jan 17 09:37:22 2007 +0000 (17 years ago)
permissions -rw-r--r--
last change Implement writing to the RTC registers
view annotate diff log raw
     1 /**
     2  * $Id: aica.c,v 1.21 2007-01-17 09:37:22 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 }
   251 void mmio_region_AICARTC_write( uint32_t reg, uint32_t val )
   252 {
   253     switch( reg ) {
   254     case AICA_RTCEN:
   255 	MMIO_WRITE( AICARTC, reg, val&0x01 );
   256 	break;
   257     case AICA_RTCLO:
   258 	if( MMIO_READ( AICARTC, AICA_RTCEN ) & 0x01 ) {
   259 	    aica_time_of_day = (aica_time_of_day & 0xFFFF0000) | (val & 0xFFFF);
   260 	}
   261 	break;
   262     case AICA_RTCHI:
   263 	if( MMIO_READ( AICARTC, AICA_RTCEN ) & 0x01 ) {
   264 	    aica_time_of_day = (aica_time_of_day & 0xFFFF) | (val<<16);
   265 	    MMIO_WRITE( AICARTC, AICA_RTCEN, 0 );
   266 	}
   267 	break;
   268     }
   269 }
   271 /**
   272  * Translate the channel frequency to a sample rate. The frequency is a
   273  * 14-bit floating point number, where bits 0..9 is the mantissa,
   274  * 11..14 is the signed exponent (-8 to +7). Bit 10 appears to
   275  * be unused.
   276  *
   277  * @return sample rate in samples per second.
   278  */
   279 uint32_t aica_frequency_to_sample_rate( uint32_t freq )
   280 {
   281     uint32_t exponent = (freq & 0x3800) >> 11;
   282     uint32_t mantissa = freq & 0x03FF;
   283     uint32_t rate;
   284     if( freq & 0x4000 ) {
   285 	/* neg exponent - rate < 44100 */
   286 	exponent = 8 - exponent;
   287 	rate = (44100 >> exponent) +
   288 	    ((44100 * mantissa) >> (10+exponent));
   289     } else {
   290 	/* pos exponent - rate > 44100 */
   291 	rate = (44100 << exponent) +
   292 	    ((44100 * mantissa) >> (10-exponent));
   293     }
   294     return rate;
   295 }
   297 /**
   298  * Derived directly from Dan Potter's log table
   299  */
   300 uint8_t aica_volume_table[256] = {
   301       0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   1,
   302       1,   1,   1,   1,   1,   1,   2,   2,   2,   2,   2,   3,   3,   3,   3,   4,
   303       4,   4,   4,   5,   5,   5,   5,   6,   6,   6,   7,   7,   7,   8,   8,   9,
   304       9,   9,  10,  10,  11,  11,  11,  12,  12,  13,  13,  14,  14,  15,  15,  16,
   305      16,  17,  17,  18,  18,  19,  19,  20,  20,  21,  22,  22,  23,  23,  24,  25,
   306      25,  26,  27,  27,  28,  29,  29,  30,  31,  31,  32,  33,  34,  34,  35,  36,
   307      37,  37,  38,  39,  40,  40,  41,  42,  43,  44,  45,  45,  46,  47,  48,  49,
   308      50,  51,  52,  52,  53,  54,  55,  56,  57,  58,  59,  60,  61,  62,  63,  64,
   309      65,  66,  67,  68,  69,  70,  71,  72,  73,  74,  76,  77,  78,  79,  80,  81,
   310      82,  83,  85,  86,  87,  88,  89,  90,  92,  93,  94,  95,  97,  98,  99, 100,
   311     102, 103, 104, 105, 107, 108, 109, 111, 112, 113, 115, 116, 117, 119, 120, 121,
   312     123, 124, 126, 127, 128, 130, 131, 133, 134, 136, 137, 139, 140, 142, 143, 145,
   313     146, 148, 149, 151, 152, 154, 155, 157, 159, 160, 162, 163, 165, 167, 168, 170,
   314     171, 173, 175, 176, 178, 180, 181, 183, 185, 187, 188, 190, 192, 194, 195, 197,
   315     199, 201, 202, 204, 206, 208, 210, 211, 213, 215, 217, 219, 221, 223, 224, 226,
   316     228, 230, 232, 234, 236, 238, 240, 242, 244, 246, 248, 250, 252, 253, 254, 255 };
   319 void aica_write_channel( int channelNo, uint32_t reg, uint32_t val ) 
   320 {
   321     val &= 0x0000FFFF;
   322     audio_channel_t channel = audio_get_channel(channelNo);
   323     switch( reg ) {
   324     case 0x00: /* Config + high address bits*/
   325 	channel->start = (channel->start & 0xFFFF) | ((val&0x1F) << 16);
   326 	if( val & 0x200 ) 
   327 	    channel->loop = TRUE;
   328 	else 
   329 	    channel->loop = FALSE;
   330 	switch( (val >> 7) & 0x03 ) {
   331 	case 0:
   332 	    channel->sample_format = AUDIO_FMT_16BIT;
   333 	    break;
   334 	case 1:
   335 	    channel->sample_format = AUDIO_FMT_8BIT;
   336 	    break;
   337 	case 2:
   338 	case 3:
   339 	    channel->sample_format = AUDIO_FMT_ADPCM;
   340 	    break;
   341 	}
   342 	switch( (val >> 14) & 0x03 ) {
   343 	case 2: 
   344 	    audio_stop_channel( channelNo ); 
   345 	    break;
   346 	case 3: 
   347 	    audio_start_channel( channelNo ); 
   348 	    break;
   349 	default:
   350 	    break;
   351 	    /* Hrmm... */
   352 	}
   353 	break;
   354     case 0x04: /* Low 16 address bits */
   355 	channel->start = (channel->start & 0x001F0000) | val;
   356 	break;
   357     case 0x08: /* Loop start */
   358 	channel->loop_start = val;
   359 	break;
   360     case 0x0C: /* End */
   361 	channel->end = val;
   362 	break;
   363     case 0x10: /* Envelope register 1 */
   364 	break;
   365     case 0x14: /* Envelope register 2 */
   366 	break;
   367     case 0x18: /* Frequency */
   368 	channel->sample_rate = aica_frequency_to_sample_rate ( val );
   369 	break;
   370     case 0x1C: /* ??? */
   371     case 0x20: /* ??? */
   372     case 0x24: /* Volume? /pan */
   373 	val = val & 0x1F;
   374 	if( val <= 0x0F ) 
   375 	    val = 0x0F - val; /* Convert to smooth pan over 0..31 */
   376 	channel->pan = val;
   377 	break;
   378     case 0x28: /* Volume */
   379 	channel->vol = aica_volume_table[val & 0xFF];
   380 	break;
   381     default: /* ??? */
   382 	break;
   383     }
   385 }
.