New approach to the fabled NES ethernet adapter
Moderators: B00daW, Moderators
The product number is generated based on features. Download and look at their product catalog pdf file. The part I ordered samples of is listed on page 38 and 39 of the catalog. On page 39, it shows you how to generate the product number for the part you want. The part number I used was EBC24DKSN which means the following:
E - PBT/Phosphor Bronze (Standard) Materials
B - 0.000010" gold plating (Standard)
C - contact centers are 0.100" apart (matches expansion port)
24 - the number of positions (48 contacts)
D - Dual Readout (pins for both sides)
KS - Cantilever bellows (this puts the contact point as close to the opening as it can be to make sure that it gets deep enough to make contact)
N - no mounting holes
E - PBT/Phosphor Bronze (Standard) Materials
B - 0.000010" gold plating (Standard)
C - contact centers are 0.100" apart (matches expansion port)
24 - the number of positions (48 contacts)
D - Dual Readout (pins for both sides)
KS - Cantilever bellows (this puts the contact point as close to the opening as it can be to make sure that it gets deep enough to make contact)
N - no mounting holes
More good news. I was looking over the datasheet for the PIC18F97J60 and it says the following:
This is exactly what I had in mind. I've got to look at the specs to see how many lines, in addition to the data lines, are needed to drive this interface. This will make it trivial to connect the 2A03 to the PIC for mmap I/O communication.In addition, one of the general purpose I/O ports can be reconfigured as an 8-bit Parallel Slave Port for direct processor-to-processor communications.
Here's a Schmartboard for prototyping with the 100-pin TQFP with 0.40" pitch: http://www.schmartboard.com/index.asp?p ... _qfp&id=72
OK, so I worked out a pretty good design for the EtherNES:
Here's a quick description of how it is laid out:
1. Any cart that wishes to use the EtherNES must connect pin 14 (2A03 R/W) to pin 16 (Exp. 42) on the cart as well as pins 39-41 (2A03 A12, A13, A14) to pins 52-54 (Exp. 7-9). This routes the CPU's R/W signal and the remaining MSB address bits to the expansion port.
2. The EtherNES connects expansion port pin 3 (premix audio in) with expansion port pin 6 (cart pin 51) giving carts the ability to inject custom audio into the mixer. It could be fun to put a SID chip on a cart and create a SID player for the NES.
3. The connection between the expansion port and the PIC18F97J60 is done using exp. pins 5, 7-9, 14, 25-32, 42, 47, and 48.
4. Pins 25-32 are the data lines from the CPU bus. The logic coming from the CPU is 5V logic but the PIC can handle voltages up to 6V on it's I/O pins (in digital mode) even though it is a 3.3V part. The data lines are connected to the parallel slave port (PSP) data lines on the PIC.
5. Pin 5 and pins 7-9 from the expansion port is connected to the PSP /CS pin on the PIC through some logic that drives the /CS low when A15 is high and A12-A14 are low. The EtherNES will be memory mapped to $8000-$8FFF. Any read/write to that memory range will activate the PSP connection between the 2A03 and the PIC. I know this cuts a big hole in the cart ROM area but with a good mapper, you should be able to get around it.
6. Pin 14 is the 2A03 /IRQ signal. This is pulled low by the PIC whenever a packet is received. My design has it tied to the PIC's port B, pin 0 so all I have to do is write 0 to port B to interrupt the 2A03. The 2A03 will then handle the wakeup by sending the read packet command to the PIC and reading by the bytes to process them.
7. Pin 42 is the rerouted 2A03 R/W signal. It is connected to the PIC's PSP /RD and /WR lines. The connection to the /RD line is inverted. This means that when the 2A03 is doing a read operation, it drives the R/W line high which in turn drives the PIC's /RD line low and the /WR line high signaling a read. During a read, I think the PIC fires an internal interrupt to handle the read on the bus. The interrupt handler must write the next byte to the PSP bus. When the 2A03 is doing a write, the R/W is driven low which in turn drives the PIC's /RD high and /WR low. This causes the PIC to latch the data that is on the PSP data bus and then fire an interrupt for processing.
8. I'm going to use an LM3940 to step down the 5V from the NES to the 3.3V needed by the PIC.
9. The design calls for an RJ-45 MagJack ethernet port with integrated magnetics and LED's. The PIC's integrated ethernet MAC and PHY are connected to it.
10. The PIC only uses a 25MHz external clock connected to OSC1 and OSC2. The 25MHz reference clock is required for the ethernet to function. There's no need to provide a secondary clock because we're not really concerned with low-power modes.
11. There is also an ICSP for programming the PIC.
12. The logic that decodes the address lines to generate the chip select logic should probably also generate the reset trigger for the PIC. I'll have to look at this, but when the 2A03 is reset, it accesses a specific memory address to read the next address to jump to. If we detected the reset vector read and generated a reset to the PIC, punching the reset button on the NES would also reset the EtherNES. I'm not sure if this is necessary, but just something I thought of just now.
I talked to the Sullins connector people and it looks like they don't have a standard COTS part that will mate with the expansion port. I'm going to have to talk to them about having custom ones made.
Does anybody here have expertise in designing PCB's using Eagle or one of the other PCB cad tools? I could use some help. I'm 90% sure that my schematic will work. I just need some help getting the parts laid out in a PCB design that can be ordered from one of the PCB fabs.
[Extra WIIIIIDE image]
(The graphic is wrong, now that I've written this all out. The SN74LVCC4245A buffers are not needed and I need to route three more address lines from the cart port to the expansion port to force the memory mapping to $8XXX.)
Here's a quick description of how it is laid out:
1. Any cart that wishes to use the EtherNES must connect pin 14 (2A03 R/W) to pin 16 (Exp. 42) on the cart as well as pins 39-41 (2A03 A12, A13, A14) to pins 52-54 (Exp. 7-9). This routes the CPU's R/W signal and the remaining MSB address bits to the expansion port.
2. The EtherNES connects expansion port pin 3 (premix audio in) with expansion port pin 6 (cart pin 51) giving carts the ability to inject custom audio into the mixer. It could be fun to put a SID chip on a cart and create a SID player for the NES.
3. The connection between the expansion port and the PIC18F97J60 is done using exp. pins 5, 7-9, 14, 25-32, 42, 47, and 48.
4. Pins 25-32 are the data lines from the CPU bus. The logic coming from the CPU is 5V logic but the PIC can handle voltages up to 6V on it's I/O pins (in digital mode) even though it is a 3.3V part. The data lines are connected to the parallel slave port (PSP) data lines on the PIC.
5. Pin 5 and pins 7-9 from the expansion port is connected to the PSP /CS pin on the PIC through some logic that drives the /CS low when A15 is high and A12-A14 are low. The EtherNES will be memory mapped to $8000-$8FFF. Any read/write to that memory range will activate the PSP connection between the 2A03 and the PIC. I know this cuts a big hole in the cart ROM area but with a good mapper, you should be able to get around it.
6. Pin 14 is the 2A03 /IRQ signal. This is pulled low by the PIC whenever a packet is received. My design has it tied to the PIC's port B, pin 0 so all I have to do is write 0 to port B to interrupt the 2A03. The 2A03 will then handle the wakeup by sending the read packet command to the PIC and reading by the bytes to process them.
7. Pin 42 is the rerouted 2A03 R/W signal. It is connected to the PIC's PSP /RD and /WR lines. The connection to the /RD line is inverted. This means that when the 2A03 is doing a read operation, it drives the R/W line high which in turn drives the PIC's /RD line low and the /WR line high signaling a read. During a read, I think the PIC fires an internal interrupt to handle the read on the bus. The interrupt handler must write the next byte to the PSP bus. When the 2A03 is doing a write, the R/W is driven low which in turn drives the PIC's /RD high and /WR low. This causes the PIC to latch the data that is on the PSP data bus and then fire an interrupt for processing.
8. I'm going to use an LM3940 to step down the 5V from the NES to the 3.3V needed by the PIC.
9. The design calls for an RJ-45 MagJack ethernet port with integrated magnetics and LED's. The PIC's integrated ethernet MAC and PHY are connected to it.
10. The PIC only uses a 25MHz external clock connected to OSC1 and OSC2. The 25MHz reference clock is required for the ethernet to function. There's no need to provide a secondary clock because we're not really concerned with low-power modes.
11. There is also an ICSP for programming the PIC.
12. The logic that decodes the address lines to generate the chip select logic should probably also generate the reset trigger for the PIC. I'll have to look at this, but when the 2A03 is reset, it accesses a specific memory address to read the next address to jump to. If we detected the reset vector read and generated a reset to the PIC, punching the reset button on the NES would also reset the EtherNES. I'm not sure if this is necessary, but just something I thought of just now.
I talked to the Sullins connector people and it looks like they don't have a standard COTS part that will mate with the expansion port. I'm going to have to talk to them about having custom ones made.
Does anybody here have expertise in designing PCB's using Eagle or one of the other PCB cad tools? I could use some help. I'm 90% sure that my schematic will work. I just need some help getting the parts laid out in a PCB design that can be ordered from one of the PCB fabs.
[Extra WIIIIIDE image]
(The graphic is wrong, now that I've written this all out. The SN74LVCC4245A buffers are not needed and I need to route three more address lines from the cart port to the expansion port to force the memory mapping to $8XXX.)
Alternatively, the NES could issue a soft-reset command to the PIC (detect the reset on the NES side in software, easy to do by setting a pattern to unused RAM after testing for it - I like the upper $100 page since no one hardly uses that area).Wookie wrote: 12. The logic that decodes the address lines to generate the chip select logic should probably also generate the reset trigger for the PIC. I'll have to look at this, but when the 2A03 is reset, it accesses a specific memory address to read the next address to jump to. If we detected the reset vector read and generated a reset to the PIC, punching the reset button on the NES would also reset the EtherNES. I'm not sure if this is necessary, but just something I thought of just now.
Yeah I didn't think it'd be that easy, but it looks like this can be pulled off.I talked to the Sullins connector people and it looks like they don't have a standard COTS part that will mate with the expansion port. I'm going to have to talk to them about having custom ones made.
I do, I've done several NES boards. Here's my best example, Squeedo rev2. I would be interested in helping out and doing the board layout. Also notice the PIC on the Squeedo PCB, I'd like to play around with that too. I could probably pretty easily run my sound synth code on the PIC you'll use.Does anybody here have expertise in designing PCB's using Eagle or one of the other PCB cad tools? I could use some help. I'm 90% sure that my schematic will work. I just need some help getting the parts laid out in a PCB design that can be ordered from one of the PCB fabs.
- Super-Hampster
- Posts: 185
- Joined: Fri May 12, 2006 4:40 pm
This isn't very powerpak friendly since the powerpak already uses pin 54 (exp 9) for audio. Wouldn't it be possible to use pins 51-53 (exp six - eight) Instead, and bridge expansion pins 3 and 9 as the powerpak requires? I'm not sure if the powerpak has the ability to use expansion pins other than 54, but if it does you could use it for developing ethernet capable games.Wookie wrote:OK, so I worked out a pretty good design for the EtherNES:
Here's a quick description of how it is laid out:
1. Any cart that wishes to use the EtherNES must connect pin 14 (2A03 R/W) to pin 16 (Exp. 42) on the cart as well as pins 39-41 (2A03 A12, A13, A14) to pins 52-54 (Exp. 7-9). This routes the CPU's R/W signal and the remaining MSB address bits to the expansion port.
2. The EtherNES connects expansion port pin 3 (premix audio in) with expansion port pin 6 (cart pin 51) giving carts the ability to inject custom audio into the mixer. It could be fun to put a SID chip on a cart and create a SID player for the NES.
BTW this is an exciting and ambitious project. I can't wait to see how it comes out.
Super-Hamster is right about the PowerPak pins. I plan on developing my EtherNES compatible game using a PowerPak Lite that I plan on modifying to route the right signals to the expansion port.
I haven't looked at the PowerPak Lite schematic in any detail at the moment. I propose that we choose pins that don't conflict with the popular dev carts.
I appreciate the offers of help. It's going to take all of us to pull this off.
Memblers, what PCB CAD tool did you use for the Squeedo? I'm trying to learn PCB CAD tools and manufacturing. lidnariq, we'll probably need your help getting the parallel slave port (PSP) working. I'm not sure if my design is correct, I still need to read the datasheet a little more.
I think the next steps are this:
1. Talk to the Sullins connector people and get a quote for a custom connector that mates with the expansion port. I'm thinking I'll probably have to scavenge a port from a dead NES and mail it to them.
2. Draw up a proposed schematic and get as many eyes on it as possible to work out any potential hardware bugs. The questions I still have in my mind are:
- can we really get away with connecting the 5V TTL logic from the 2A03 to the PIC PSP?
- how will the two chips talk through the PSP?
3. Take a close look at the PowerPak and PowerPak Lite to see which pins we can use to route signals to the expansion port that don't conflict with the PowerPaks.
Anyway, stay tuned for more.
I haven't looked at the PowerPak Lite schematic in any detail at the moment. I propose that we choose pins that don't conflict with the popular dev carts.
I appreciate the offers of help. It's going to take all of us to pull this off.
Memblers, what PCB CAD tool did you use for the Squeedo? I'm trying to learn PCB CAD tools and manufacturing. lidnariq, we'll probably need your help getting the parallel slave port (PSP) working. I'm not sure if my design is correct, I still need to read the datasheet a little more.
I think the next steps are this:
1. Talk to the Sullins connector people and get a quote for a custom connector that mates with the expansion port. I'm thinking I'll probably have to scavenge a port from a dead NES and mail it to them.
2. Draw up a proposed schematic and get as many eyes on it as possible to work out any potential hardware bugs. The questions I still have in my mind are:
- can we really get away with connecting the 5V TTL logic from the 2A03 to the PIC PSP?
- how will the two chips talk through the PSP?
3. Take a close look at the PowerPak and PowerPak Lite to see which pins we can use to route signals to the expansion port that don't conflict with the PowerPaks.
Anyway, stay tuned for more.
The only 2 (un)commonly used expansion pins, I don't know the numbers off-hand but one is to enable/disable mapper access (so CopyNES can write to memory that overlaps mapper regs) and the other of course is for audio-in.
If you're interested, here's the PIC setup in Squeedo:
http://memblers.com/NES/mapschem.png
Despite what it says on there, I eventually used a PIC18F4525 (same pinout).
Things to notice:
-PPU A12 is connected to a timer input that is able to be pre-scaled by 8. Automatic scanline-counting.
-M2 is also connected to a timer input, for an NES CPU cycle counter.
-74HC377 latches PRG A0-A7 when the NES writes to the PSP. With this, the PIC can distinguish accesses between $5000-$50FF (the PIC's interrupt code uses it for a jump table).
Communicating between the NES data bus and PSP is a little tricky, but I wouldn't say it's hard to do. Sounds like you're on the right track.
I would strongly encourage moving the address decoding to $5000, or anywhere else that doesn't overlap everyone's favorite memory. Squeedo has enables for $5xxx and $6000-$7FFF, that's done with a 74HC139 and one NAND gate. You could do the same by bringing in PRG/CE, or inverting A15. You will need to bring in the M2 (Phi2) signal also, I didn't see that in your schematic. M2 needs to be high when you use the PSP /CE.
Also another suggestion is to hook the PIC up to the controller port pins that are on the exp connector. This could perhaps pave the way for Famicom and NES2 compatibility, serial mode instead of parallel. Also maybe it could make for a hacky way to play-back gameplay recordings or do multiplayer.
I use Proteus by Labcenter. I've tried Eagle, ExpressPCB (proprietary - don't bother), gEDA, and KiCad. Unfortunately in the Proteus demo version you can't save, but that's what I learned on and found it to be Good. gEDA and KiCad are free, but seemed kind of harder to use (it's been a while so they probably were older versions at the time also).Memblers, what PCB CAD tool did you use for the Squeedo? I'm trying to learn PCB CAD tools and manufacturing.
If you're interested, here's the PIC setup in Squeedo:
http://memblers.com/NES/mapschem.png
Despite what it says on there, I eventually used a PIC18F4525 (same pinout).
Things to notice:
-PPU A12 is connected to a timer input that is able to be pre-scaled by 8. Automatic scanline-counting.
-M2 is also connected to a timer input, for an NES CPU cycle counter.
-74HC377 latches PRG A0-A7 when the NES writes to the PSP. With this, the PIC can distinguish accesses between $5000-$50FF (the PIC's interrupt code uses it for a jump table).
Communicating between the NES data bus and PSP is a little tricky, but I wouldn't say it's hard to do. Sounds like you're on the right track.
I would strongly encourage moving the address decoding to $5000, or anywhere else that doesn't overlap everyone's favorite memory. Squeedo has enables for $5xxx and $6000-$7FFF, that's done with a 74HC139 and one NAND gate. You could do the same by bringing in PRG/CE, or inverting A15. You will need to bring in the M2 (Phi2) signal also, I didn't see that in your schematic. M2 needs to be high when you use the PSP /CE.
Also another suggestion is to hook the PIC up to the controller port pins that are on the exp connector. This could perhaps pave the way for Famicom and NES2 compatibility, serial mode instead of parallel. Also maybe it could make for a hacky way to play-back gameplay recordings or do multiplayer.
-
bucky o'hare
- Posts: 160
- Joined: Fri Sep 22, 2006 9:52 am
- Location: philly
Would you like one?Wookie wrote:1. Talk to the Sullins connector people and get a quote for a custom connector that mates with the expansion port. I'm thinking I'll probably have to scavenge a port from a dead NES and mail it to them.
I made the mistake of doing a basic sound mod a while back and hot plugging. I think I fried my 2a03.
The possibilities of this project are overwhelming.
Alright, technical detail #1: the parallel slave port (PSP).
I'm trying to figure out two things:
1. Can we interface the 5V 2A03 logic directly to the PIC? The data sheet says yes. The PIC is 6V tolerant on all I/O pins in digital mode, so we should be able to go from 5V to 3.3V. The logic threshold for the 2A03 is less than 3.3V so the PIC should be able to drive the pins the other way too. (from 3.3V to 5V).
2. How do we use the PSP in the PIC firmware? It is a "slave" port meaning that the PIC must respond to the read and writes coming from the 2A03. What happens inside the PIC when the 2A03 executes a read operation? How about a write? I'm reading PIC programming books now to figure it out.
I'm trying to figure out two things:
1. Can we interface the 5V 2A03 logic directly to the PIC? The data sheet says yes. The PIC is 6V tolerant on all I/O pins in digital mode, so we should be able to go from 5V to 3.3V. The logic threshold for the 2A03 is less than 3.3V so the PIC should be able to drive the pins the other way too. (from 3.3V to 5V).
2. How do we use the PSP in the PIC firmware? It is a "slave" port meaning that the PIC must respond to the read and writes coming from the 2A03. What happens inside the PIC when the 2A03 executes a read operation? How about a write? I'm reading PIC programming books now to figure it out.
Looking at this book: http://books.google.com/books?id=CB9GaA ... #PPA328,M2 on page 326-329, it looks like the PIC has a one byte PSP output buffer and a one byte PSP input buffer. The PIC has an internal parallel slave port interrupt bit (PSPIF) which I assume means we can set an interrupt condition on. (UPDATE: yes the PSPIF can trigger a PSP interrupt, which we will do.)
If that is true then we can use an ISR to check the parallel slave port output buffer full (OBF) and input buffer full (IBF) flags to see if the 2A03 did a write to the PIC or a read from the PIC and act accordingly.
If the 2A03 writes to the PIC, the IBF flag will be set. The ISR would then disable the PSP interrupt, read the byte from the input buffer, move it to an internal command buffer, adjust the internal command buffer write pointer for the next write, clear the IBF flag, set an "input" flag to signal the main loop, re-enable the PSP interrupt, and return.
The main loop would check the input flag and see that it is true. It will then scan the bytes it hasn't seen yet, looking for an "end of command" byte or checking to see if the expected number of bytes in the command have been received (see below about the packet protocol). If it sees a complete packet, then it know the 2A03 has written an entire command to the PIC. It then processes the command and writes the response to the output memory area.
Sending data back from the PIC to the 2A03 is similar, just in reverse. When the PIC has something to send back to the 2A03, it will prime the pump by putting the entire response into an output memory area in RAM, write the first byte into the PSP output buffer and then set the I/O line tied to the 2A03's interrupt pin low to let it know there is data ready. (This will have to be a little more complicated than this because there could be other packets still waiting to be read by the 2A03). The 2A03 will execute a read operation which will read the byte from the PSP output buffer. That will trigger an interrupt in the PIC which will disable the PSP interrupt, see that the output buffer flag (OBF) flag is false, copy the next byte from the output buffer memory block to the PSP output buffer, adjust the output buffer memory block read pointer, set the OBF, and re-enable the PSP interrupt. It is then ready for the next read by the 2A03.
We're going to have to check the timing on this to make sure that the PIC is fast enough to do all of that in an ISR before the 2A03 tries to read the next byte. If the PIC isn't fast enough, we'll have to change the protocol so that the 2A03 only reads one byte when its /IRQ line gets yanked on by the PIC. That will slow things down a bit, but I don't think it will matter much.
As for the protocol between the two chips, I was thinking of a "standard" command and response packet protocol. There are two approaches to packets. One approach is to use an "end of packet" byte or byte sequence. The other is to include the packet length in the packet header. Both have their pluses and minuses. The "end of packet" byte or byte sequence means that we have to take precautions to ensure that the "end of packet" value(s) never occur inside of the body of the packet. We'd have to come up with some kind of encoding scheme to get around that. The option of including a length value in the packet header is probably the best option. The length just tells both processors how many bytes to wait for before processing, no encoding of the payload is required.
Anyway, that's about it for the 2A03 <---> PIC interfacing through the PSP.
If that is true then we can use an ISR to check the parallel slave port output buffer full (OBF) and input buffer full (IBF) flags to see if the 2A03 did a write to the PIC or a read from the PIC and act accordingly.
If the 2A03 writes to the PIC, the IBF flag will be set. The ISR would then disable the PSP interrupt, read the byte from the input buffer, move it to an internal command buffer, adjust the internal command buffer write pointer for the next write, clear the IBF flag, set an "input" flag to signal the main loop, re-enable the PSP interrupt, and return.
The main loop would check the input flag and see that it is true. It will then scan the bytes it hasn't seen yet, looking for an "end of command" byte or checking to see if the expected number of bytes in the command have been received (see below about the packet protocol). If it sees a complete packet, then it know the 2A03 has written an entire command to the PIC. It then processes the command and writes the response to the output memory area.
Sending data back from the PIC to the 2A03 is similar, just in reverse. When the PIC has something to send back to the 2A03, it will prime the pump by putting the entire response into an output memory area in RAM, write the first byte into the PSP output buffer and then set the I/O line tied to the 2A03's interrupt pin low to let it know there is data ready. (This will have to be a little more complicated than this because there could be other packets still waiting to be read by the 2A03). The 2A03 will execute a read operation which will read the byte from the PSP output buffer. That will trigger an interrupt in the PIC which will disable the PSP interrupt, see that the output buffer flag (OBF) flag is false, copy the next byte from the output buffer memory block to the PSP output buffer, adjust the output buffer memory block read pointer, set the OBF, and re-enable the PSP interrupt. It is then ready for the next read by the 2A03.
We're going to have to check the timing on this to make sure that the PIC is fast enough to do all of that in an ISR before the 2A03 tries to read the next byte. If the PIC isn't fast enough, we'll have to change the protocol so that the 2A03 only reads one byte when its /IRQ line gets yanked on by the PIC. That will slow things down a bit, but I don't think it will matter much.
As for the protocol between the two chips, I was thinking of a "standard" command and response packet protocol. There are two approaches to packets. One approach is to use an "end of packet" byte or byte sequence. The other is to include the packet length in the packet header. Both have their pluses and minuses. The "end of packet" byte or byte sequence means that we have to take precautions to ensure that the "end of packet" value(s) never occur inside of the body of the packet. We'd have to come up with some kind of encoding scheme to get around that. The option of including a length value in the packet header is probably the best option. The length just tells both processors how many bytes to wait for before processing, no encoding of the payload is required.
Anyway, that's about it for the 2A03 <---> PIC interfacing through the PSP.
I just realized that yanking on the 2A03's /IRQ line won't be enough to signal that the PIC has data to read. We'll also have to assert one or more of the controller pins in the expansion bus. If I'm reading the docs right, controller input signals an interrupt in the 2A03 as well. If it does, then the 2A03 can read the controller port during the ISR and check the expansion port bits to figure out if the interrupt was triggered by controller input or by the EtherNES. If it was triggered by controller input, it can then do the little dance necessary to clock in the controller button status. If it was triggered by the EtherNES, it can set a flag that signals the main loop to read in a command response.
Does anybody know for sure if the controller input signals an interrupt? I guess it really doesn't matter. We can still use the scheme while polling the controllers for input.
Does anybody know for sure if the controller input signals an interrupt? I guess it really doesn't matter. We can still use the scheme while polling the controllers for input.