3DS Capture Card?

The 3DS capture card business is dead. There are (were) a small group of individuals that created all the capture cards in existence, and now they have gone under.

This is my attempt at building an open source 3DS capture card. If this ever reaches fruition, I hope that I can just publish the design and leave the installation and production of these modules to other, more business minded people. My main reason for doing this project is to keep my FPGA skills in practice.

Signal Sniffing

Sniffing the video signals

I’ve managed to sniff the HSync, VSync, Clock, Red0, Blue0, and Green0 signals so far. For reference, I used the following diagram when wiring up my test signals.

Ignore the Altera. Xilinx is where it’s at.

The Signals

The video clock

I measured the video clock signal on my oscilloscope for better resolution. The video clock appears to be a 10MHz 1.8v logic signal. It’s just barely hitting the top and bottom thresholds for 1.8v logic, so I’ll need to be careful not to load this line too much.

All other measurements were with my Saleae.

Video control signal measurements

It looks like I found the control signals for the bottom touch screen. Keep in mind that the screen resolution of the bottom screen is 320×240.

VSync: 59.83 Hz. This lines up with a ~60 frame per second refresh rate

HSync: 24.78 kHz

HSync/Vsync: There are 415 HSync edges per Vsync edge.

Lines: 415 HSync pulses is way higher than the 320 horizontal resolution of the bottom screen. However, you can see in the waveform that there are a whole bunch of HSync pulses that happen when there’s no video data. If you count up the HSync pulses with video data, you end up with 319. This is much closer to the screen’s horizontal resolution of 320 pixels, maybe there’s a single line of black or something.

HSync/Clock: There are 452 clock edges per HSync

Pix/Line: Once again, 452 is way higher than the 240 vertical resolution of the 3DS. If you remove the edges where there’s no video data, you end up with 228 edges. This is close enough to 240 for me to be confident. I’m also only measuring the lowest bit of the video data, it’s completely possible that this bit is actually just 0 for the last few pixels of video.

My captures are here. They can be viewed in the Saleae Logic application

Control Signal Quirks

I noticed a couple interesting things when looking at the HSync and VSync control signals. Mainly, they’re not pulses. They stay high for many clock periods.

HSync stays high for two clock periods
VSync stays high for hundreds of clock periods

This doesn’t make a whole lot of sense to me. I assumed that these would be simple one clock period pulses so the screen’s data capture state machine is simpler. Maybe I have some fundamental misunderstanding of how exactly these signals work and what they do. My current plan is to feed them through a module that edge triggers them. This makes my data capture state machine simpler.

Preliminary Design

This is the data capture state machine I’ve designed.

Basic data capture state machine

This state machine listens for the control signals and records all 24 bits of video to block RAM at the same time.

My plan is to have two video buffers and swap which one gets written to each frame. The active one is recording video, the inactive one is being read by the HDMI encoder and transmitted. On the fly transmission would be cool, but I don’t think it will be possible in this case. Since I’ll eventually be recording two screens (remember, 3DS) , they’ll need to be stitched together by the FPGA and transmitted as one image. This would require me to store both frames somewhere. Otherwise I’d have to cut the framerate in half and only update one screen per frame.

Total memory usage is:

Bottom Screen Frame Buffer:
((320 pixels * 240 pixels) * 24 bits per pixel) = 1,843,200 bits

Top Screen Frame Buffer:
((400 pixels * 240 pixels) * 24 bits per pixel) = 2,304,000 bits
Technically the top 3DS screen is 800×240, but that’s so there’s 400×240 pixels per eye to create 3D. I don’t care about 3D, so I’ll only capture video that was intended for one eye.

Final Buffer Size
(Top Screen Buffer + Bottom Screen Buffer) * 2 = 8,294,400 bits = ~8.3Mb

Next Steps

The next thing to do is try to capture one frame and store it into memory. I won’t capture a full color frame, just a couple of the most significant bits of one color channel. That should be enough to tell if it’s working or not. After the frame is captured, I’ll dump the raw data to my machine via UART for viewing.

I’ve ordered a Pmod 64Mb Hyperram module from 1BitSquared that has more than enough room for two full frame buffers. It’s fast too, peak bandwidth is 333MB/s which is way more than the ~65MB/s that I’ll need.