Search
lxdream.org :: lxdream/src/aica/aica.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/aica/aica.c
changeset 929:fd8cb0c82f5f
prev829:517425d04f1b
next934:3acd3b3ee6d1
author nkeynes
date Tue Dec 23 05:48:05 2008 +0000 (15 years ago)
branchlxdream-mem
permissions -rw-r--r--
last change More refactoring and general cleanup. Most things should be working again now.
Split off cache and start real implementation, breaking save states in the process
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 MMIO_REGION_WRITE_FN( AICA0, reg, val )
   198 {
   199     reg &= 0xFFF;
   200     MMIO_WRITE( AICA0, reg, val );
   201     aica_write_channel( reg >> 7, reg % 128, val );
   202     //    DEBUG( "AICA0 Write %08X => %08X", val, reg );
   203 }
   205 /* Write to channels 32-64 */
   206 MMIO_REGION_WRITE_FN( AICA1, reg, val )
   207 {
   208     reg &= 0xFFF;
   209     MMIO_WRITE( AICA1, reg, val );
   210     aica_write_channel( (reg >> 7) + 32, reg % 128, val );
   211     // DEBUG( "AICA1 Write %08X => %08X", val, reg );
   212 }
   214 /**
   215  * AICA control registers 
   216  */
   217 MMIO_REGION_WRITE_FN( AICA2, reg, val )
   218 {
   219     uint32_t tmp;
   220     reg &= 0xFFF;
   222     switch( reg ) {
   223     case AICA_RESET:
   224         tmp = MMIO_READ( AICA2, AICA_RESET );
   225         if( (tmp & 1) == 1 && (val & 1) == 0 ) {
   226             /* ARM enabled - execute a core reset */
   227             DEBUG( "ARM enabled" );
   228             arm_reset();
   229             aica_state.samples_done = 0;
   230             aica_state.nanosecs_done = 0;
   231         } else if( (tmp&1) == 0 && (val&1) == 1 ) {
   232             DEBUG( "ARM disabled" );
   233         }
   234         MMIO_WRITE( AICA2, AICA_RESET, val );
   235         break;
   236     case AICA_IRQCLEAR:
   237         aica_clear_event();
   238         break;
   239     case AICA_FIFOIN: /* Read-only */
   240         break;
   241     default:
   242         MMIO_WRITE( AICA2, reg, val );
   243         break;
   244     }
   245 }
   247 MMIO_REGION_READ_FN( AICA2, reg )
   248 {
   249     audio_channel_t channel;
   250     uint32_t channo;
   251     int32_t val;
   252     reg &= 0xFFF;
   253     switch( reg ) {
   254     case AICA_CHANSTATE:
   255         channo = (MMIO_READ( AICA2, AICA_CHANSEL ) >> 8) & 0x3F;
   256         channel = audio_get_channel(channo);
   257         if( channel->loop == LOOP_LOOPED ) {
   258             val = 0x8000;
   259             channel->loop = LOOP_ON;
   260         } else {
   261             val = 0;
   262         }
   263         return val;
   264     case AICA_CHANPOSN:
   265         channo = (MMIO_READ( AICA2, AICA_CHANSEL ) >> 8) & 0x3F;
   266         channel = audio_get_channel(channo);
   267         return channel->posn;
   268     default:
   269         return MMIO_READ( AICA2, reg );
   270     }
   271 }
   273 MMIO_REGION_READ_FN( AICARTC, reg )
   274 {
   275     int32_t rv = 0;
   276     reg &= 0xFFF;
   277     switch( reg ) {
   278     case AICA_RTCHI:
   279         rv = (aica_state.time_of_day >> 16) & 0xFFFF;
   280         break;
   281     case AICA_RTCLO:
   282         rv = aica_state.time_of_day & 0xFFFF;
   283         break;
   284     }
   285     // DEBUG( "Read AICA RTC %d => %08X", reg, rv );
   286     return rv;
   287 }
   289 MMIO_REGION_WRITE_FN( AICARTC, reg, val )
   290 {
   291     reg &= 0xFFF;
   292     switch( reg ) {
   293     case AICA_RTCEN:
   294         MMIO_WRITE( AICARTC, reg, val&0x01 );
   295         break;
   296     case AICA_RTCLO:
   297         if( MMIO_READ( AICARTC, AICA_RTCEN ) & 0x01 ) {
   298             aica_state.time_of_day = (aica_state.time_of_day & 0xFFFF0000) | (val & 0xFFFF);
   299         }
   300         break;
   301     case AICA_RTCHI:
   302         if( MMIO_READ( AICARTC, AICA_RTCEN ) & 0x01 ) {
   303             aica_state.time_of_day = (aica_state.time_of_day & 0xFFFF) | (val<<16);
   304             MMIO_WRITE( AICARTC, AICA_RTCEN, 0 );
   305         }
   306         break;
   307     }
   308 }
   310 /**
   311  * Translate the channel frequency to a sample rate. The frequency is a
   312  * 14-bit floating point number, where bits 0..9 is the mantissa,
   313  * 11..14 is the signed exponent (-8 to +7). Bit 10 appears to
   314  * be unused.
   315  *
   316  * @return sample rate in samples per second.
   317  */
   318 uint32_t aica_frequency_to_sample_rate( uint32_t freq )
   319 {
   320     uint32_t exponent = (freq & 0x3800) >> 11;
   321     uint32_t mantissa = freq & 0x03FF;
   322     uint32_t rate;
   323     if( freq & 0x4000 ) {
   324         /* neg exponent - rate < 44100 */
   325         exponent = 8 - exponent;
   326         rate = (44100 >> exponent) +
   327         ((44100 * mantissa) >> (10+exponent));
   328     } else {
   329         /* pos exponent - rate > 44100 */
   330         rate = (44100 << exponent) +
   331         ((44100 * mantissa) >> (10-exponent));
   332     }
   333     return rate;
   334 }
   336 void aica_start_stop_channels()
   337 {
   338     int i;
   339     for( i=0; i<32; i++ ) {
   340         uint32_t val = MMIO_READ( AICA0, i<<7 );
   341         audio_start_stop_channel(i, val&0x4000);
   342     }
   343     for( ; i<64; i++ ) {
   344         uint32_t val = MMIO_READ( AICA1, (i-32)<<7 );
   345         audio_start_stop_channel(i, val&0x4000);
   346     }
   347 }
   349 /**
   350  * Derived directly from Dan Potter's log table
   351  */
   352 uint8_t aica_volume_table[256] = {
   353         0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   1,
   354         1,   1,   1,   1,   1,   1,   2,   2,   2,   2,   2,   3,   3,   3,   3,   4,
   355         4,   4,   4,   5,   5,   5,   5,   6,   6,   6,   7,   7,   7,   8,   8,   9,
   356         9,   9,  10,  10,  11,  11,  11,  12,  12,  13,  13,  14,  14,  15,  15,  16,
   357         16,  17,  17,  18,  18,  19,  19,  20,  20,  21,  22,  22,  23,  23,  24,  25,
   358         25,  26,  27,  27,  28,  29,  29,  30,  31,  31,  32,  33,  34,  34,  35,  36,
   359         37,  37,  38,  39,  40,  40,  41,  42,  43,  44,  45,  45,  46,  47,  48,  49,
   360         50,  51,  52,  52,  53,  54,  55,  56,  57,  58,  59,  60,  61,  62,  63,  64,
   361         65,  66,  67,  68,  69,  70,  71,  72,  73,  74,  76,  77,  78,  79,  80,  81,
   362         82,  83,  85,  86,  87,  88,  89,  90,  92,  93,  94,  95,  97,  98,  99, 100,
   363         102, 103, 104, 105, 107, 108, 109, 111, 112, 113, 115, 116, 117, 119, 120, 121,
   364         123, 124, 126, 127, 128, 130, 131, 133, 134, 136, 137, 139, 140, 142, 143, 145,
   365         146, 148, 149, 151, 152, 154, 155, 157, 159, 160, 162, 163, 165, 167, 168, 170,
   366         171, 173, 175, 176, 178, 180, 181, 183, 185, 187, 188, 190, 192, 194, 195, 197,
   367         199, 201, 202, 204, 206, 208, 210, 211, 213, 215, 217, 219, 221, 223, 224, 226,
   368         228, 230, 232, 234, 236, 238, 240, 242, 244, 246, 248, 250, 252, 253, 254, 255 };
   371 void aica_write_channel( int channelNo, uint32_t reg, uint32_t val ) 
   372 {
   373     val &= 0x0000FFFF;
   374     audio_channel_t channel = audio_get_channel(channelNo);
   375     switch( reg ) {
   376     case 0x00: /* Config + high address bits*/
   377         channel->start = (channel->start & 0xFFFF) | ((val&0x1F) << 16);
   378         if( val & 0x200 ) 
   379             channel->loop = LOOP_ON;
   380         else 
   381             channel->loop = LOOP_OFF;
   382         switch( (val >> 7) & 0x03 ) {
   383         case 0:
   384             channel->sample_format = AUDIO_FMT_16BIT;
   385             break;
   386         case 1:
   387             channel->sample_format = AUDIO_FMT_8BIT;
   388             break;
   389         case 2:
   390         case 3:
   391             channel->sample_format = AUDIO_FMT_ADPCM;
   392             break;
   393         }
   394         if( val & 0x8000 ) {
   395             aica_start_stop_channels();
   396         }
   397         break;
   398         case 0x04: /* Low 16 address bits */
   399             channel->start = (channel->start & 0x001F0000) | val;
   400             break;
   401         case 0x08: /* Loop start */
   402             channel->loop_start = val;
   403             break;
   404         case 0x0C: /* End */
   405             channel->end = val;
   406             break;
   407         case 0x10: /* Envelope register 1 */
   408             break;
   409         case 0x14: /* Envelope register 2 */
   410             break;
   411         case 0x18: /* Frequency */
   412             channel->sample_rate = aica_frequency_to_sample_rate ( val );
   413             break;
   414         case 0x1C: /* ??? */
   415         case 0x20: /* ??? */
   416         case 0x24: /* Volume? /pan */
   417             val = val & 0x1F;
   418             if( val <= 0x0F ) 
   419                 val = 0x0F - val; /* Convert to smooth pan over 0..31 */
   420             channel->pan = val;
   421             break;
   422         case 0x28: /* Volume */
   423             // This isn't remotely correct, but it will have to suffice until I have
   424             // time to figure out what's actually going on here... 
   425             channel->vol = aica_volume_table[max((val & 0xFF),((val>>8)&0xFF))];
   426             break;
   427         default: /* ??? */
   428             break;
   429     }
   431 }
.