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