Search
lxdream.org :: lxdream/src/aica/aica.c :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename src/aica/aica.c
changeset 465:3bd7be575792
prev463:0655796f9bb5
next473:bbbeca9ccf13
author nkeynes
date Sat Oct 27 05:47:21 2007 +0000 (16 years ago)
permissions -rw-r--r--
last change Fix AICA save state section to include the current audio + IO state
file annotate diff log raw
1.1 --- a/src/aica/aica.c Wed Oct 24 21:24:09 2007 +0000
1.2 +++ b/src/aica/aica.c Sat Oct 27 05:47:21 2007 +0000
1.3 @@ -1,7 +1,8 @@
1.4 /**
1.5 - * $Id: aica.c,v 1.24 2007-10-24 21:24:09 nkeynes Exp $
1.6 + * $Id: aica.c,v 1.25 2007-10-27 05:47:21 nkeynes Exp $
1.7 *
1.8 - * This is the core sound system (ie the bit which does the actual work)
1.9 + * This module implements the AICA's IO interfaces, as well
1.10 + * as providing the core AICA module to the system.
1.11 *
1.12 * Copyright (c) 2005 Nathan Keynes.
1.13 *
1.14 @@ -43,9 +44,23 @@
1.15 aica_start, aica_run_slice, aica_stop,
1.16 aica_save_state, aica_load_state };
1.17
1.18 -/* 20 years in seconds */
1.19 -#define RTC_OFFSET 631152000
1.20 -unsigned int aica_time_of_day = 0;
1.21 +struct aica_state_struct {
1.22 + uint32_t time_of_day;
1.23 + /**
1.24 + * Keep track of what we've done so far this second, to try to keep the
1.25 + * precision of samples/second.
1.26 + */
1.27 + uint32_t samples_done;
1.28 + uint32_t nanosecs_done;
1.29 + /**
1.30 + * Event (IRQ) state
1.31 + */
1.32 + int event_pending;
1.33 + int clear_count;
1.34 +};
1.35 +
1.36 +static struct aica_state_struct aica_state;
1.37 +
1.38
1.39 /**
1.40 * Initialize the AICA subsystem. Note requires that
1.41 @@ -62,8 +77,12 @@
1.42 void aica_reset( void )
1.43 {
1.44 arm_reset();
1.45 + aica_state.time_of_day = 0x5bfc8900;
1.46 + aica_state.samples_done = 0;
1.47 + aica_state.nanosecs_done = 0;
1.48 + aica_state.event_pending = 0;
1.49 + aica_state.clear_count = 0;
1.50 aica_event(2); /* Pre-deliver a timer interrupt */
1.51 - aica_time_of_day = 0x5bfc8900;
1.52 }
1.53
1.54 void aica_start( void )
1.55 @@ -71,29 +90,22 @@
1.56
1.57 }
1.58
1.59 -/**
1.60 - * Keep track of what we've done so far this second, to try to keep the
1.61 - * precision of samples/second.
1.62 - */
1.63 -int samples_done = 0;
1.64 -uint32_t nanosecs_done = 0;
1.65 -
1.66 uint32_t aica_run_slice( uint32_t nanosecs )
1.67 {
1.68 /* Run arm instructions */
1.69 int reset = MMIO_READ( AICA2, AICA_RESET );
1.70 if( (reset & 1) == 0 ) { /* Running */
1.71 - int num_samples = (int)((uint64_t)AICA_SAMPLE_RATE * (nanosecs_done + nanosecs) / 1000000000) - samples_done;
1.72 + int num_samples = (int)((uint64_t)AICA_SAMPLE_RATE * (aica_state.nanosecs_done + nanosecs) / 1000000000) - aica_state.samples_done;
1.73 num_samples = arm_run_slice( num_samples );
1.74 audio_mix_samples( num_samples );
1.75
1.76 - samples_done += num_samples;
1.77 - nanosecs_done += nanosecs;
1.78 + aica_state.samples_done += num_samples;
1.79 + aica_state.nanosecs_done += nanosecs;
1.80 }
1.81 - if( nanosecs_done > 1000000000 ) {
1.82 - samples_done -= AICA_SAMPLE_RATE;
1.83 - nanosecs_done -= 1000000000;
1.84 - aica_time_of_day++;
1.85 + if( aica_state.nanosecs_done > 1000000000 ) {
1.86 + aica_state.samples_done -= AICA_SAMPLE_RATE;
1.87 + aica_state.nanosecs_done -= 1000000000;
1.88 + aica_state.time_of_day++;
1.89 }
1.90 return nanosecs;
1.91 }
1.92 @@ -105,26 +117,27 @@
1.93
1.94 void aica_save_state( FILE *f )
1.95 {
1.96 + fwrite( &aica_state, sizeof(struct aica_state_struct), 1, f );
1.97 arm_save_state( f );
1.98 + audio_save_state(f);
1.99 }
1.100
1.101 int aica_load_state( FILE *f )
1.102 {
1.103 - return arm_load_state( f );
1.104 + fread( &aica_state, sizeof(struct aica_state_struct), 1, f );
1.105 + arm_load_state( f );
1.106 + return audio_load_state(f);
1.107 }
1.108
1.109 -int aica_event_pending = 0;
1.110 -int aica_clear_count = 0;
1.111 -
1.112 /* Note: This is probably not necessarily technically correct but it should
1.113 * work in the meantime.
1.114 */
1.115
1.116 void aica_event( int event )
1.117 {
1.118 - if( aica_event_pending == 0 )
1.119 + if( aica_state.event_pending == 0 )
1.120 armr.int_pending |= CPSR_F;
1.121 - aica_event_pending |= (1<<event);
1.122 + aica_state.event_pending |= (1<<event);
1.123
1.124 int pending = MMIO_READ( AICA2, AICA_IRQ );
1.125 if( pending == 0 || event < pending )
1.126 @@ -133,24 +146,24 @@
1.127
1.128 void aica_clear_event( )
1.129 {
1.130 - aica_clear_count++;
1.131 - if( aica_clear_count == 4 ) {
1.132 + aica_state.clear_count++;
1.133 + if( aica_state.clear_count == 4 ) {
1.134 int i;
1.135 - aica_clear_count = 0;
1.136 + aica_state.clear_count = 0;
1.137
1.138 for( i=0; i<8; i++ ) {
1.139 - if( aica_event_pending & (1<<i) ) {
1.140 - aica_event_pending &= ~(1<<i);
1.141 + if( aica_state.event_pending & (1<<i) ) {
1.142 + aica_state.event_pending &= ~(1<<i);
1.143 break;
1.144 }
1.145 }
1.146 for( ;i<8; i++ ) {
1.147 - if( aica_event_pending & (1<<i) ) {
1.148 + if( aica_state.event_pending & (1<<i) ) {
1.149 MMIO_WRITE( AICA2, AICA_IRQ, i );
1.150 break;
1.151 }
1.152 }
1.153 - if( aica_event_pending == 0 )
1.154 + if( aica_state.event_pending == 0 )
1.155 armr.int_pending &= ~CPSR_F;
1.156 }
1.157 }
1.158 @@ -202,6 +215,7 @@
1.159 void mmio_region_AICA2_write( uint32_t reg, uint32_t val )
1.160 {
1.161 uint32_t tmp;
1.162 +
1.163 switch( reg ) {
1.164 case AICA_RESET:
1.165 tmp = MMIO_READ( AICA2, AICA_RESET );
1.166 @@ -209,8 +223,8 @@
1.167 /* ARM enabled - execute a core reset */
1.168 DEBUG( "ARM enabled" );
1.169 arm_reset();
1.170 - samples_done = 0;
1.171 - nanosecs_done = 0;
1.172 + aica_state.samples_done = 0;
1.173 + aica_state.nanosecs_done = 0;
1.174 } else if( (tmp&1) == 0 && (val&1) == 1 ) {
1.175 DEBUG( "ARM disabled" );
1.176 }
1.177 @@ -255,10 +269,10 @@
1.178 int32_t rv = 0;
1.179 switch( reg ) {
1.180 case AICA_RTCHI:
1.181 - rv = (aica_time_of_day >> 16) & 0xFFFF;
1.182 + rv = (aica_state.time_of_day >> 16) & 0xFFFF;
1.183 break;
1.184 case AICA_RTCLO:
1.185 - rv = aica_time_of_day & 0xFFFF;
1.186 + rv = aica_state.time_of_day & 0xFFFF;
1.187 break;
1.188 }
1.189 // DEBUG( "Read AICA RTC %d => %08X", reg, rv );
1.190 @@ -274,12 +288,12 @@
1.191 break;
1.192 case AICA_RTCLO:
1.193 if( MMIO_READ( AICARTC, AICA_RTCEN ) & 0x01 ) {
1.194 - aica_time_of_day = (aica_time_of_day & 0xFFFF0000) | (val & 0xFFFF);
1.195 + aica_state.time_of_day = (aica_state.time_of_day & 0xFFFF0000) | (val & 0xFFFF);
1.196 }
1.197 break;
1.198 case AICA_RTCHI:
1.199 if( MMIO_READ( AICARTC, AICA_RTCEN ) & 0x01 ) {
1.200 - aica_time_of_day = (aica_time_of_day & 0xFFFF) | (val<<16);
1.201 + aica_state.time_of_day = (aica_state.time_of_day & 0xFFFF) | (val<<16);
1.202 MMIO_WRITE( AICARTC, AICA_RTCEN, 0 );
1.203 }
1.204 break;
.