Search
lxdream.org :: lxdream/src/aica/aica.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/aica/aica.c
changeset 61:eb7a73c9bcae
prev44:8da2cbcffe24
next66:2ec5b6eb75e5
author nkeynes
date Mon Jan 02 14:50:12 2006 +0000 (15 years ago)
permissions -rw-r--r--
last change AICA IRQ event work in progress
view annotate diff log raw
     1 /**
     2  * $Id: aica.c,v 1.10 2006-01-02 14:50:12 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 "dream.h"
    22 #include "mem.h"
    23 #include "aica.h"
    24 #include "armcore.h"
    25 #define MMIO_IMPL
    26 #include "aica.h"
    28 MMIO_REGION_READ_DEFFN( AICA0 )
    29 MMIO_REGION_READ_DEFFN( AICA1 )
    30 MMIO_REGION_READ_DEFFN( AICA2 )
    32 void aica_init( void );
    33 void aica_reset( void );
    34 void aica_start( void );
    35 void aica_stop( void );
    36 void aica_save_state( FILE *f );
    37 int aica_load_state( FILE *f );
    38 uint32_t aica_run_slice( uint32_t );
    41 struct dreamcast_module aica_module = { "AICA", aica_init, aica_reset, 
    42 					aica_start, aica_run_slice, aica_stop,
    43 					aica_save_state, aica_load_state };
    45 /**
    46  * Initialize the AICA subsystem. Note requires that 
    47  */
    48 void aica_init( void )
    49 {
    50     register_io_regions( mmio_list_spu );
    51     MMIO_NOTRACE(AICA0);
    52     MMIO_NOTRACE(AICA1);
    53     arm_mem_init();
    54     arm_reset();
    55 }
    57 void aica_reset( void )
    58 {
    59     arm_reset();
    60 }
    62 void aica_start( void )
    63 {
    65 }
    67 uint32_t aica_run_slice( uint32_t nanosecs )
    68 {
    69     /* Run arm instructions */
    70     int reset = MMIO_READ( AICA2, AICA_RESET );
    71     if( (reset & 1) == 0 ) { 
    72 	/* Running */
    73         nanosecs = arm_run_slice( nanosecs );
    74     }
    75     /* Generate audio buffer */
    76     return nanosecs;
    77 }
    79 void aica_stop( void )
    80 {
    82 }
    84 void aica_save_state( FILE *f )
    85 {
    86     arm_save_state( f );
    87 }
    89 int aica_load_state( FILE *f )
    90 {
    91     return arm_load_state( f );
    92 }
    94 int aica_event_pending = 0;
    95 int aica_clear_count = 0;
    97 /* Note: This is probably not necessarily technically correct but it should
    98  * work in the meantime.
    99  */
   101 void aica_event( int event )
   102 {
   103     if( aica_event_pending == 0 )
   104 	armr.int_pending |= CPSR_F;
   105     aica_event_pending |= (1<<event);
   107     int pending = MMIO_READ( AICA2, AICA_IRQ );
   108     if( pending == 0 || event < pending )
   109 	MMIO_WRITE( AICA2, AICA_IRQ, event );
   110 }
   112 void aica_clear_event( )
   113 {
   114     aica_clear_count++;
   115     if( aica_clear_count == 4 ) {
   116 	int i;
   117 	aica_clear_count = 0;
   119 	for( i=0; i<8; i++ ) {
   120 	    if( aica_event_pending & (1<<i) ) {
   121 		aica_event_pending &= ~(1<<i);
   122 		break;
   123 	    }
   124 	}
   125 	for( ;i<8; i++ ) {
   126 	    if( aica_event_pending & (1<<i) ) {
   127 		MMIO_WRITE( AICA2, AICA_IRQ, i );
   128 		break;
   129 	    }
   130 	}
   131 	if( aica_event_pending == 0 )
   132 	    armr.int_pending &= ~CPSR_F;
   133     }
   134 }
   135 /** Channel register structure:
   136  * 00  4  Channel config
   137  * 04  4  Waveform address lo (16 bits)
   138  * 08  4  Loop start address
   139  * 0C  4  Loop end address
   140  * 10  4  Volume envelope
   141  * 14  4  Init to 0x1F
   142  * 18  4  Frequency (floating point)
   143  * 1C  4  ?? 
   144  * 20  4  ??
   145  * 24  1  Pan
   146  * 25  1  ??
   147  * 26  
   148  * 27  
   149  * 28  1  ??
   150  * 29  1  Volume
   151  * 2C
   152  * 30
   153  * 
   155 /* Write to channels 0-31 */
   156 void mmio_region_AICA0_write( uint32_t reg, uint32_t val )
   157 {
   158     //    aica_write_channel( reg >> 7, reg % 128, val );
   159     MMIO_WRITE( AICA0, reg, val );
   160     //    DEBUG( "AICA0 Write %08X => %08X", val, reg );
   161 }
   163 /* Write to channels 32-64 */
   164 void mmio_region_AICA1_write( uint32_t reg, uint32_t val )
   165 {
   166     //    aica_write_channel( (reg >> 7) + 32, reg % 128, val );
   167     MMIO_WRITE( AICA1, reg, val );
   168     // DEBUG( "AICA1 Write %08X => %08X", val, reg );
   169 }
   171 /* General registers */
   172 void mmio_region_AICA2_write( uint32_t reg, uint32_t val )
   173 {
   174     uint32_t tmp;
   175     switch( reg ) {
   176     case AICA_RESET:
   177 	tmp = MMIO_READ( AICA2, AICA_RESET );
   178 	if( (tmp & 1) == 1 && (val & 1) == 0 ) {
   179 	    /* ARM enabled - execute a core reset */
   180 	    DEBUG( "ARM enabled" );
   181 	    arm_reset();
   182 	} else if( (tmp&1) == 0 && (val&1) == 1 ) {
   183 	    DEBUG( "ARM disabled" );
   184 	}
   185 	MMIO_WRITE( AICA2, AICA_RESET, val );
   186 	break;
   187     case AICA_IRQCLEAR:
   188 	aica_clear_event();
   189 	break;
   190     default:
   191 	MMIO_WRITE( AICA2, reg, val );
   192 	break;
   193     }
   194 }
.