Search
lxdream.org :: lxdream/src/aica/aica.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/aica/aica.c
changeset 736:a02d1475ccfd
prev642:c7383f21f122
next829:517425d04f1b
author nkeynes
date Mon Jul 21 00:08:34 2008 +0000 (15 years ago)
permissions -rw-r--r--
last change Add gettext.h and build sanely without libintl if it's not available
Remove x86dasm's config.h & opintl.h (no longer needed and actually wrong)
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 }
.