akkera 102
/
apuplay
SPC music playback tools for real snes apu
Embed:
(wiki syntax)
Show/hide line numbers
apu.cpp
00001 #include "apu.h" 00002 #include "mbed.h" 00003 #include "gpio.h" 00004 00005 // cmd.cpp 00006 extern int g_verbose; 00007 00008 static int port0 = 0; 00009 00010 void apu_init(void) 00011 { 00012 port0 = 0; 00013 gpio_init(); 00014 } 00015 00016 // Reset the APU by whatever means it needs reset. 00017 void apu_reset(void) 00018 { 00019 gpio_reset(); 00020 } 00021 00022 unsigned char apu_read(int address) 00023 { 00024 unsigned char tmp = gpio_read(address); 00025 00026 // printf("apu_read: a=%d -> %02x\n", address, tmp); 00027 00028 return tmp; 00029 } 00030 00031 void apu_write(int address, unsigned char data) 00032 { 00033 // printf("apu_write: a=%d, %02x\n", address, data); 00034 00035 gpio_write(address, data); 00036 } 00037 00038 // Write many bytes using handshake (see apu_writeHandshake) 00039 int apu_writeBytes(unsigned char *data, int len) 00040 { 00041 // printf("apu_writeBytes: %d...\n", len); 00042 00043 for(int i=0; i<len; i++) 00044 { 00045 if(apu_writeHandshake(1, data[i])) 00046 { 00047 return 1; 00048 } 00049 } 00050 00051 return 0; 00052 } 00053 00054 // Write to address 'address', write the previously 00055 // read value from port0 back to port 0 and wait 00056 // for port0 value to be different from the written one. 00057 int apu_writeHandshake(int address, int data) 00058 { 00059 apu_write(address, data); 00060 apu_write(0, port0); 00061 00062 if(!apu_waitInport(0, port0, 500)) 00063 { 00064 return 1; 00065 } 00066 00067 if(++port0 == 256) 00068 { 00069 port0 = 0; 00070 } 00071 00072 return 0; 00073 } 00074 00075 // return false on timeout, otherwise true 00076 int apu_waitInport(int port, unsigned char data, int timeout_ms) 00077 { 00078 // printf("apu_waitInport: addr: %d, data: %02x\n", port, data); 00079 00080 int ms; 00081 Timer t; 00082 t.start(); 00083 00084 while(apu_read(port) != data) 00085 { 00086 ms = t.read_ms(); 00087 if(ms > timeout_ms) 00088 { 00089 if(g_verbose) 00090 { 00091 printf("timeout after %d milli\n", ms); 00092 } 00093 00094 return 0; 00095 } 00096 } 00097 00098 return 1; 00099 } 00100 00101 // Initialise an spc transfer at 'address'. 00102 // To be used after reset of after jumping to rom 00103 // 00104 // Use apu_newTransfer for additional transfers 00105 // 00106 // return -1 on error, 0 if success 00107 int apu_initTransfer(unsigned short address) 00108 { 00109 // Initializing the transfer 00110 // Wait for port 2140 to be $aa 00111 if(!apu_waitInport(0, 0xaa, 500)) 00112 { 00113 if(g_verbose) 00114 { 00115 printf("Should read 0xaa, but reads %02x\n", apu_read(0)); 00116 } 00117 00118 return -1; 00119 } 00120 00121 // and Wait for port 2141 to be $bb 00122 if(!apu_waitInport(1, 0xbb, 500)) 00123 { 00124 if(g_verbose) 00125 { 00126 printf("Should read 0xaa, but reads %02x\n", apu_read(0)); 00127 } 00128 00129 return -1; 00130 } 00131 00132 // The spc is now ready 00133 00134 // Write any value other than 0 to 2141 00135 apu_write(1, 1); 00136 00137 // Write the destination address to poirt $2142 and $2143, with the 00138 // low byte written at $2142 00139 apu_write(2, (address & 0x00ff)); // low 00140 apu_write(3, (address & 0xff00) >> 8); // high So our code will go at $0002 00141 00142 // Write $CC to port $2140 00143 apu_write(0, 0xCC); 00144 00145 // Wait for $2140 to be $CC 00146 if(!apu_waitInport(0, 0xcc, 500)) 00147 { 00148 if(g_verbose) 00149 { 00150 printf("Should read 0xcc, but reads %02x\n", apu_read(0)); 00151 } 00152 00153 return -1; 00154 } 00155 00156 port0 = 0; 00157 return 0; 00158 } 00159 00160 // initialise a new transfer after the first transfer. 00161 // 00162 // returns 0 on success, -1 on error 00163 int apu_newTransfer(unsigned short address) 00164 { 00165 int i; 00166 apu_write(1, 1); 00167 apu_write(3, (address & 0xff00) >> 8); 00168 apu_write(2, (address & 0x00ff)); 00169 00170 i = apu_read(0); 00171 i += 2; 00172 i &= 0xff; 00173 00174 // if it's 0, increase it again 00175 if(!i) 00176 { 00177 i += 2; 00178 } 00179 apu_write(0, i); 00180 00181 if(!apu_waitInport(0, i, 500)) 00182 { 00183 fprintf(stderr, "apu_newTransfer: timeout\n"); 00184 return -1; 00185 } 00186 00187 port0 = 0; 00188 return 0; 00189 } 00190 00191 // End transfer and jump to address 00192 void apu_endTransfer(unsigned short start_address) 00193 { 00194 int i; 00195 00196 apu_write(1, 0); 00197 apu_write(3, (start_address & 0xff00) >> 8); 00198 apu_write(2, (start_address & 0x00ff)); 00199 00200 i = apu_read(0); 00201 i += 2; 00202 i &= 0xff; 00203 00204 // if it's 0, increase it again 00205 if(!i) 00206 { 00207 i+=2; 00208 } 00209 apu_write(0, i); 00210 }
Generated on Sat Jul 23 2022 19:14:25 by 1.7.2