SPC music playback tools for real snes apu

Dependencies:   mbed

Revision:
2:62e6e22f8be2
Parent:
1:02a06cd10a33
diff -r 02a06cd10a33 -r 62e6e22f8be2 apu.cpp
--- a/apu.cpp	Mon Jan 09 13:58:58 2017 +0000
+++ b/apu.cpp	Wed Jan 11 16:00:29 2017 +0000
@@ -1,206 +1,210 @@
-/* hwapu - SPC music playback tools for real snes apu
- * Copyright (C) 2004-2005  Raphael Assenat <raph@raphnet.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#include <stdio.h>
-#include <string.h>/**/
 #include "apu.h"
-#include <time.h>
-// #include <sys/time.h>
 #include "mbed.h"
-
+#include "gpio.h"
 
-//#define TRACE_RW
+// cmd.cpp
+extern int g_verbose;
 
-extern int g_verbose; // from main.c
+static int port0 = 0;
 
-/******************** G L O B A L S ************************************/
-static int port0=0;
-static APU_ops *apu_ops = NULL;
-
-void apu_setOps(APU_ops *ops)
+void apu_init(void)
 {
-    apu_ops = ops;
+    port0 = 0;
+    gpio_init();
 }
 
-static int SetPort0 (short data)
+// Reset the APU by whatever means it needs reset.
+void apu_reset(void)
 {
-    port0=data;
-    return 0;
+    gpio_reset();
 }
 
-void apu_write (int address, unsigned char data)
+unsigned char apu_read(int address)
 {
-//#ifdef TRACE_RW
-//  printf("apu_write: a=%d, %02x\n", address, data);
-//#endif
-    apu_ops->write(address, data);  
-}
+    unsigned char tmp = gpio_read(address);
 
-unsigned char apu_read (int address)
-{
-    unsigned char tmp = apu_ops->read(address);
-//#ifdef TRACE_RW
 //  printf("apu_read: a=%d -> %02x\n", address, tmp);
-//#endif
 
     return tmp;
 }
 
-/* Write to address 'address', write the previously
- * read value from port0 back to port 0 and wait
- * for port0 value to be different from the written one.
- */
-int apu_writeHandshake(int address, int data)
+void apu_write(int address, unsigned char data)
 {
-//  int i;
-//  i = 0;
-    apu_write(address, data);
-    apu_write(0,port0);
-    
-    if (!apu_waitInport(0, port0, 500)) {
-        return 1;
-    }
-    port0++;
-    if (port0 == 256)
-        port0 = 0;
+//  printf("apu_write: a=%d, %02x\n", address, data);
 
-    return 0;
-    
-
+    gpio_write(address, data);  
 }
 
-
+// Write many bytes using handshake (see apu_writeHandshake)
 int apu_writeBytes(unsigned char *data, int len)
 {
-    int i;
-#ifdef TRACE_RW
-    printf("apu_writeBytes: %d...\n", len);
-#endif
-    for (i=0; i<len; i++) {
-        if (apu_writeHandshake(1, data[i])) { return 1; }
+//  printf("apu_writeBytes: %d...\n", len);
+
+    for(int i=0; i<len; i++)
+    {
+        if(apu_writeHandshake(1, data[i]))
+        {
+            return 1;
+        }
     }
+
     return 0;
 }
 
-void apu_reset(void)    //Reset the APU by whatever means it needs reset.
+// Write to address 'address', write the previously
+// read value from port0 back to port 0 and wait
+// for port0 value to be different from the written one.
+int apu_writeHandshake(int address, int data)
 {
-    apu_ops->reset();   
+    apu_write(address, data);
+    apu_write(0, port0);
+    
+    if(!apu_waitInport(0, port0, 500))
+    {
+        return 1;
+    }
 
+    if(++port0 == 256)
+    {
+        port0 = 0;
+    }
+
+    return 0;
 }
 
-/* return false on timeout, otherwise true */
+// return false on timeout, otherwise true
 int apu_waitInport(int port, unsigned char data, int timeout_ms)
 {
-    // struct timeval tv_before, tv_now;
-    // gettimeofday(&tv_before, NULL);
-    int elaps_milli;
+//  printf("apu_waitInport: addr: %d, data: %02x\n", port, data);
+
+    int ms;
     Timer t;
     t.start();
 
-#ifdef TRACE_RW
-    printf("apu_waitInport: addr: %d, data: %02x\n",port,data);
-#endif
-    
-    while(apu_read(port)!=data) {
-        //usleep(1);
-//        gettimeofday(&tv_now, NULL);
-//        elaps_milli = (tv_now.tv_sec - tv_before.tv_sec) * 1000;
-//        elaps_milli += (tv_now.tv_usec-tv_before.tv_usec)/1000;
-        elaps_milli = t.read_ms();
-        if (elaps_milli > timeout_ms )
+    while(apu_read(port) != data)
+    {
+        ms = t.read_ms();
+        if(ms > timeout_ms)
         {
-            if (g_verbose) 
-                printf("timeout after %d milli\n", elaps_milli);
+            if(g_verbose)
+            { 
+                printf("timeout after %d milli\n", ms);
+            }
+
             return 0;
         }
     }
+
     return 1;
 }
 
+// Initialise an spc transfer at 'address'. 
+// To be used after reset of after jumping to rom
+//
+// Use apu_newTransfer for additional transfers
+// 
+// return -1 on error, 0 if success
 int apu_initTransfer(unsigned short address)
 {
-    /* Initializing the transfer */
-    /* Wait for port 2140 to be $aa */
-    if (!apu_waitInport(0, 0xaa, 500)) {
-        if (g_verbose) 
+    // Initializing the transfer
+    // Wait for port 2140 to be $aa
+    if(!apu_waitInport(0, 0xaa, 500))
+    {
+        if(g_verbose)
+        { 
             printf("Should read 0xaa, but reads %02x\n", apu_read(0));
-        return -1;
-    }
-    /* and Wait for port 2141 to be $bb */
-    if (!apu_waitInport(1, 0xbb, 500)) {
-        if (g_verbose) 
-            printf("Should read 0xaa, but reads %02x\n", apu_read(0));
+        }
+
         return -1;
     }
-    /* The spc is now ready */
 
-    /* Write any value other than 0 to 2141 */
-    apu_write(1, 1);
-    /* Write the destination address to poirt $2142 and $2143, with the
-     * low byte written at $2142 */
-    apu_write(2, address&0xff); // low
-    apu_write(3, (address&0xff00)>>8); // high So our code will go at $0002
-    /* Write $CC to port $2140 */
-    apu_write(0, 0xCC);
+    // and Wait for port 2141 to be $bb
+    if(!apu_waitInport(1, 0xbb, 500))
+    {
+        if(g_verbose)
+        { 
+            printf("Should read 0xaa, but reads %02x\n", apu_read(0));
+        }
 
-    /* Wait for $2140 to be $CC */
-    if (!apu_waitInport(0, 0xcc, 500)) {
-        if (g_verbose) 
-            printf("Should read 0xcc, but reads %02x\n", apu_read(0));
         return -1;
     }
 
-    SetPort0(0);
-    
+    // The spc is now ready
+
+    // Write any value other than 0 to 2141
+    apu_write(1, 1);
+
+    // Write the destination address to poirt $2142 and $2143, with the
+    // low byte written at $2142
+    apu_write(2, (address & 0x00ff));      // low
+    apu_write(3, (address & 0xff00) >> 8); // high So our code will go at $0002
+
+    // Write $CC to port $2140
+    apu_write(0, 0xCC);
+
+    // Wait for $2140 to be $CC
+    if(!apu_waitInport(0, 0xcc, 500))
+    {
+        if(g_verbose)
+        { 
+            printf("Should read 0xcc, but reads %02x\n", apu_read(0));
+        }
+
+        return -1;
+    }
+
+    port0 = 0;
     return 0;
 }
 
+// initialise a new transfer after the first transfer.
+//
+// returns 0 on success, -1 on error
 int apu_newTransfer(unsigned short address)
 {
     int i;
-    apu_write(1,1);
-    apu_write(3, (address&0xff00)>>8);
-    apu_write(2, (address & 0xff));
+    apu_write(1, 1);
+    apu_write(3, (address & 0xff00) >> 8);
+    apu_write(2, (address & 0x00ff));
+
+    i  = apu_read(0);
+    i += 2;
+    i &= 0xff;
 
-    i = apu_read(0);
-    i += 2; i &= 0xff;
-    if (!i) { i += 2; } // if it's 0, increase it again
+    // if it's 0, increase it again
+    if(!i)
+    {
+        i += 2;
+    }
     apu_write(0, i);
-    if (!apu_waitInport(0, i, 500)) {
-        fprintf(stderr, "apu_newTransfer: timeout\n"); return -1;
+
+    if(!apu_waitInport(0, i, 500))
+    {
+        fprintf(stderr, "apu_newTransfer: timeout\n");
+        return -1;
     }
     
-    SetPort0(0);
-    
+    port0 = 0;
     return 0;
 }
 
+// End transfer and jump to address
 void apu_endTransfer(unsigned short start_address)
 {
     int i;
     
     apu_write(1, 0);
-    apu_write(3, (start_address & 0xff00)>>8);
-    apu_write(2, (start_address & 0xff));
+    apu_write(3, (start_address & 0xff00) >> 8);
+    apu_write(2, (start_address & 0x00ff));
 
-    i = apu_read(0);
-    i +=2; i &= 0xff;
-    if (!i) { i+=2 ; } // if it's 0, increase it again
+    i  = apu_read(0);
+    i += 2;
+    i &= 0xff;
+
+    // if it's 0, increase it again
+    if(!i)
+    {
+        i+=2;
+    }
     apu_write(0, i);
 }
-
-