As you see from the wired picture, don't repeat that, ever, if you plan on using the original connector again. That wiring spreads the connector pins, and will cause issues later on. I have 2 APU units that will not work nicely with the original connector anymore. One has stopped working nicely, with an audio channel connection, and the other has problems in the data connection. For those 2 units, I am looking to replace the connector with another that I can get easily.
I finally took an opportunity with an analog dial caliper, and measured a few things. The pin spacing on the footprint is definitely 79 mils. I was wrong on the row spacing though, It is also 79 mils as well, instead of the 100 mils I had assumed. (Didn't make a difference in putting it together though, since it is only 2 rows. Had it been 4 rows, then 100 mils would have been a problem.)
EDIT: Missed a detail, Pin size of the connector is 20 mils.
--------------
Here is the Arduino source code for the interface.
Still have to release the main program and source code for it as well.
- Code: Select all
//#define DATAMODETEXT 1
#ifdef DATAMODETEXT
int datamode=0;
#endif
/* IO Pin Mapping.
** Digital Pin 0 - RX
** Digital Pin 1 - TX
** Digital Pin 2-7 - SNES APU D2-7
** Digital Pin 8 - SNES APU address 0
** Digital Pin 9 - SNES APU address 1
** Digital Pin 10 - SNES APU /RD
** Digital Pin 11 - SNES APU /WR
** Digital Pin 12-13 - SNES APU D0-1
** Analog Pin 0 (AKA Digital Pin 14) - SNES APU /RESET
** Vcc - SNES APU address 6, SNES APU Vcc, SNES APU audio Vcc
** Gnd - SNES APU Gnd, SNES APU audio Gnd.
*/
unsigned char port0state;
void setup()
{
PORTB = 0x0F;
DDRB = 0x0F;
PORTC = 0x01;
DDRC = 0x01;
Serial.begin(57600);
Serial.println("SPC700 DATA LOADER V1.0");
}
unsigned char readdata(unsigned char address)
{
unsigned char data;
DDRB = 0x0F;
DDRD &= ~0xFC;
PORTB &= ~0x03;
PORTB |= (address & 0x03);
PORTB &= ~0x04;
__asm__ __volatile__ ("nop");
__asm__ __volatile__ ("nop");
data=((PINB&0x30)>>4) | (PIND&0xFC);
PORTB |= 0x04;
return data;
}
void writedata(unsigned char address, unsigned char data)
{
DDRB = 0x3F;
DDRD |= 0xFC;
PORTD &= ~0xFC;
PORTD |= (data & 0xFC);
PORTB &= ~0x33;
PORTB |= (address & 0x03);
PORTB |= ((data & 0x03)<<4);
PORTB &= ~0x08;
__asm__ __volatile__ ("nop");
__asm__ __volatile__ ("nop");
PORTB |= 0x08;
}
/*
unsigned char program_counter=0xFF;
uint32_t delay_count=0;
unsigned char Script700[64];
unsigned char Script700WorkArea[8];
unsigned char Script700RAM[64];*/
void ProcessScript700()
{
// --- TODO: Implement script 700 processing, and script700 uploading procedures.
// --- Limitations. Only ~512 bytes of working ram/code space to work with.
// --- No direct access to the APU ram/registers in any way, shape or form,
// --- other than IO ports F4-F7.
/*
if(program_counter==0xFF)
return;
if(delay_count)
{
if(delay_count>=32)
{
delay_count-=32;
delayMicroseconds(16);
}
else
{
delayMicroseconds(delay_count>>1);
delay_count=0;
}
return;
}
switch(Script700[program_counter&0x3F]&0x0F)
{
case 0: //Wait
delay_count = Script700[program_counter+1];
delay_count |= Script700[program_counter+2]<<8;
delay_count |= Script700[program_counter+1] << 16;
delay_count |= Script700[program_counter+1] << 24;
program_counter+=5;
break;
case 1: //Move
break;
default:
program_counter=0xFF;
break;
}*/
}
unsigned char readserial()
{
while (Serial.available() == 0)
ProcessScript700();
return Serial.read();
}
#ifdef DATAMODETEXT
unsigned char readhex()
{
unsigned char data[2];
data[0]=readserial();
data[1]=readserial();
if((data[0]>='0')&&(data[0]<='9'))
data[0]-='0';
else if ((data[0]>='A')&&(data[0]<='F'))
{
data[0]-='A';
data[0]+=10;
}
else if ((data[0]>='a')&&(data[0]<='f'))
{
data[0]-='a';
data[0]+=10;
}
else
data[0]=0;
if((data[1]>='0')&&(data[1]<='9'))
data[1]-='0';
else if ((data[1]>='A')&&(data[1]<='F'))
{
data[1]-='A';
data[1]+=10;
}
else if ((data[1]>='a')&&(data[1]<='f'))
{
data[1]-='a';
data[1]+=10;
}
else
data[1]=0;
return (data[0]<<4)|data[1];
}
#endif
void startapuwrite(uint16_t address, unsigned char *data, int len)
{
int i;
digitalWrite(14,LOW);
delay(1);
digitalWrite(14,HIGH);
while(readdata(0)!=0xAA);
while(readdata(1)!=0xBB);
writedata(3,address>>8);
writedata(2,address&0xFF);
writedata(1,1);
writedata(0,0xCC);
while(readdata(0)!=0xCC);
for(i=0;i<len;i++)
{
writedata(1,data[i]);
writedata(0,i&0xFF);
while(readdata(0)!=(i&0xFF));
}
}
/* // --- Implemented for faster emulator linking, on at least the initial code upload.
// The code will be skipped by usual fashion, but data recorded for to do the initial upload.
// Once the data is uploaded, all 8/16 bit read/writes will be passed on to the emulator to control.
// startapuwrite is not commented out, because it is being used for spc file uploading process.
void continueapuwrite(uint16_t address, unsigned char *data, int len)
{
int i;
i=readdata(0);
i+=2;
writedata(3,address>>8);
writedata(2,address&0xFF);
writedata(1,1);
writedata(0,i&0xFF);
while(readdata(0)!=(i&0xFF));
for(i=0;i<len;i++)
{
writedata(1,data[i]);
writedata(0,i&0xFF);
while(readdata(0)!=(i&0xFF));
}
}
void executeapu(uint16_t address)
{
int i;
i=readdata(0);
i+=2;
writedata(3,address>>8);
writedata(2,address&0xFF);
writedata(1,1);
writedata(0,i&0xFF);
//while(readdata(0)!=(i&0xFF)); //Commented just in case executed code clears the i+2 result immediately.
}*/
void APU_Wait(unsigned char address, unsigned char data)
{
while(readdata(address)!=data);
}
unsigned char DSPdata[16] =
{ //For loading the 128 byte DSP ram. DO NOT CHANGE.
0xC4, 0xF2, 0x64, 0xF4, 0xD0, 0xFC, 0xFA, 0xF5, 0xF3, 0xC4, 0xF4, 0xBC, 0x10, 0xF2, 0x2F, 0xB7,
}
;
void loop()
{
uint16_t i;
long time;
int checksum;
unsigned char address, data;
switch(readserial())
{
case 'D': //Set datamode between ascii and binary. In ascii mode, each data byte is transmitted
//as ascii hexadecimal notation. In binary mode, the byte transmitted on the serial
//line is taken literally for what it is.
#ifdef DATAMODETEXT
datamode=readserial()-'0';
if(datamode)
Serial.println("Data mode set to Text");
#else
readserial(); //Ignore this byte, but keep it here anyways.
#endif
break;
case 'Q': //Read all 4 IO ports in rapid fire succession.
#ifdef DATAMODETEXT
if(!datamode)
{
#endif
data=readdata(0);
Serial.print(data,BYTE);
data=readdata(1);
Serial.print(data,BYTE);
data=readdata(2);
Serial.print(data,BYTE);
data=readdata(3);
Serial.print(data,BYTE);
#ifdef DATAMODETEXT
}
else
{
Serial.print("Data on All 4 ports = ");
data=readdata(0);
if(data<16)
Serial.print(0,HEX);
Serial.print(data,HEX);
data=readdata(1);
if(data<16)
Serial.print(0,HEX);
Serial.print(data,HEX);
data=readdata(2);
if(data<16)
Serial.print(0,HEX);
Serial.print(data,HEX);
data=readdata(3);
if(data<16)
Serial.print(0,HEX);
Serial.println(data,HEX);
}
#endif
break;
case 'R': //Read a single IO port. Takes an address as a parameter, returns one byte.
address=readserial()-'0';
data=readdata(address);
#ifdef DATAMODETEXT
if(datamode)
{
Serial.print("Data at Address ");
Serial.print(address,DEC);
Serial.print(" is ");
if(data<16)
Serial.print(0,HEX);
Serial.println(data,HEX);
}
else
#endif
Serial.print(data,BYTE);
break;
case 'r': //Read and returns 2 consecutive IO ports.
address=readserial()-'0';
data=readdata(address+1);
#ifdef DATAMODETEXT
if(datamode)
{
Serial.print("Data at Address ");
Serial.print(address,DEC);
Serial.print(" is ");
if(data<16)
Serial.print(0,HEX);
Serial.print(data,HEX);
data=readdata(address);
if(data<16)
Serial.print(0,HEX);
Serial.println(data,HEX);
}
else
{
#endif
Serial.print(data,BYTE);
data=readdata(address);
Serial.print(data,BYTE);
#ifdef DATAMODETEXT
}
#endif
break;
case 's': //Reset the Audio Processing Unit
#ifdef DATAMODETEXT
if(datamode)
Serial.println("APU Reset");
#endif
digitalWrite(14,LOW);
delay(1);
digitalWrite(14,HIGH);
break;
case 'f': //Set the expected state of PORT 0 for the next write.
port0state=readserial();
break;
case 'F': //Upload SPC data at serial port speed.
//Serial.println("START");
//time=millis();
for(i=0;i<65280;i++)
{
//data=i&0xFF;
data=readserial();
writedata(1,data);
writedata(0,port0state);
while(readdata(0)!=port0state);
port0state++;
}
//Serial.print(millis()-time,DEC);
//Serial.println(" milliseconds to upload 64K");
Serial.print(1,BYTE);
break;
case 'G': //Upload the DSP register, and the first page of SPC data at serial port speed.
startapuwrite(0x0002,DSPdata,16);
writedata(2,0x02);
writedata(3,0x00);
writedata(1,0x00);
writedata(0,0x11);
while(readdata(0)!=0x11);
port0state=0;
for(i=0;i<128;i++)
{
data=readserial();
writedata(1,data);
writedata(0,port0state);
if(i<127)
while(readdata(0)!=port0state);
port0state++;
}
while(readdata(0)!=0xAA);
port0state=0;
writedata(2,0x02);
writedata(3,0x00);
writedata(1,0x01);
writedata(0,0xCC);
while(readdata(0)!=0xCC);
for(i=0;i<256;i++)
{
data=readserial();
if(i<2)
continue;
if(i>=0xF0)
continue;
writedata(1,data);
writedata(0,port0state);
while(readdata(0)!=port0state);
port0state++;
}
Serial.print('F',BYTE);
break;
case 'W': //Write a single IO port.
address=readserial()-'0';
#ifdef DATAMODETEXT
if(datamode)
data=readhex();
else
#endif
data=readserial();
writedata(address,data);
#ifdef DATAMODETEXT
if(datamode)
{
Serial.print("Writing 8bit ");
if(data<16)
Serial.print(0,HEX);
Serial.print(data,HEX);
Serial.print(" to address ");
Serial.println(address,DEC);
}
#endif
break;
case 'w': //Write 2 IO consecutive IO ports.
address=readserial()-'0';
#ifdef DATAMODETEXT
if(!datamode)
{
#endif
data=readserial();
writedata(address+1,data);
data=readserial();
writedata(address,data);
#ifdef DATAMODETEXT
}
else
{
data=readhex();
writedata(address+1,data);
Serial.print("Writing 16bit ");
if(data<16)
Serial.print(0,HEX);
Serial.print(data,HEX);
data=readhex();
writedata(address,data);
Serial.print(" ");
if(data<16)
Serial.print(0,HEX);
Serial.print(data,HEX);
Serial.print(" to address ");
Serial.println(address,DEC);
}
#endif
break;
}
}
--------
I just uncovered an almost show stopper. THe channels were wired in reverse. There is a fix though, for assembly of the 1.01 boards. Reverse the RED and WHITE RCA jacks, and go against what is labeled on board.
And as for the headphone and line out jack, criss-cross the resistors and the capacitors going to those jacks.
EDIT: Combined previous 3 posts into 1 post.