NTSC NES Composite Video Levels

Discuss emulation of the Nintendo Entertainment System and Famicom.

Moderator: Moderators

User avatar
blargg
Posts: 3717
Joined: Mon Sep 27, 2004 8:33 am
Location: Central Texas, USA
Contact:

NTSC NES Composite Video Levels

Post by blargg »

Today I figured out a way to determine the NTSC NES video waveform without having to get an oscilloscope. I was able to underclock my NES by replacing the 21 MHz crystal with a 3.6 MHz crystal, then use my PC's video capture in grayscale mode as a high-speed waveform digitizer. My NES actually ran OK (I could still use my devcart, but with the serial running at 1/6 the normal rate). I measured the video waveform fairly reliably and put those values into my NTSC emulator. This is how a test palette and Super Mario Bros. display with it:

Image

Super Mario Bros.

I still need to measure the effect of the emphasis bits, then check things over and post updated NTSC emulator code (the changes are slight, just involving the table initialization). I'm excited about finishing this.
BlueHawk

Post by BlueHawk »

Nice job with that :). I'll be sure to implement the results into my emulator :D.
User avatar
kyuusaku
Posts: 1665
Joined: Mon Sep 27, 2004 2:13 pm

Post by kyuusaku »

Great job, it looks right!
User avatar
Zepper
Formerly Fx3
Posts: 3264
Joined: Fri Nov 12, 2004 4:59 pm
Location: Brazil
Contact:

Post by Zepper »

*roll eyes*
Should I use MSPaint and the color drop to fetch the RGB values? ^_^;;

EDIT- Obivously I was joking here.
Last edited by Zepper on Tue Feb 07, 2006 4:51 pm, edited 1 time in total.
NewRisingSun
Posts: 1312
Joined: Thu May 19, 2005 11:30 am

Post by NewRisingSun »

Just the levels, please, no RGB. :)

Also, did you use signal clamping for that screenshot, or did the 3x colors turn out that way by themselves? Or do the 3x colors really have a different amplitude than the rest? Because if they do, the 2C02 document (which claims equal amplitude throughout all colors) would need updating.

Of course, if we understand emulation also as a hardware-documentation project (the way MAME does), we won't be satisfied with the bare values, but instead understand how these values come about (resistor ladder etc.).

Thanks for doing these tests. Now it should be possible do get an emulated video output that matches standard as well as current NTSC tv sets 100%. The last video frontier to conquer is find out about the exact non-standard behavior of Japanese 80's tv sets, thus getting all the color nuances as the original programmers intended.

Edit:
Here, I made a .PAL file from Blargg's screenshot. Note that this screenshot is at a hue knob setting of minus 15 or so degrees. If you compare this with a "video-essentials" calibrated TV (hue knob at +/- zero degrees, no hue change), it'll be a little bit more greenish.
Last edited by NewRisingSun on Mon Feb 06, 2006 7:16 am, edited 6 times in total.
WedNESday
Posts: 1231
Joined: Thu Sep 15, 2005 9:23 am
Location: Berlin, Germany
Contact:

Post by WedNESday »

RGB will be fine for me thanks. Although I have to admit, the colours do look a bit fuzzy.
User avatar
Zepper
Formerly Fx3
Posts: 3264
Joined: Fri Nov 12, 2004 4:59 pm
Location: Brazil
Contact:

Post by Zepper »

WedNESday wrote:RGB will be fine for me thanks. Although I have to admit, the colours do look a bit fuzzy.
Uh huh, indeed.
[sarcasm] Thanks for the PAL file, NRS! [/sarcasm]
Last edited by Zepper on Tue Feb 07, 2006 4:52 pm, edited 1 time in total.
User avatar
blargg
Posts: 3717
Joined: Mon Sep 27, 2004 8:33 am
Location: Central Texas, USA
Contact:

Post by blargg »

I re-did the measurements using a high-quality video digitizer card (Scion VG-5). This gave me excellent digitizations of the waveforms, without any annoying filtering. Here is an example at full resolution of colors $0F, $30, $06, $16, $0F, $26, $36, $30 (the square waves are at the 3.5 MHz colorburst frequency):

Image

All my raw data in a WAVE file and my measurements of it are available below. I am still working on the emphasis measurements and effect on the TV image.

nes_ntsc_levels.zip

These are the relevant results so far, the luma amplitudes and chroma sine wave amplitudes. These are close to what I made before, but I correct an error on my part of using the chroma square wave amplitude directly without adjusting by 1.27 (to get the amplitude of the fundamental sine wave). I updated the previous pictures to reflect this. See note at end of message

ntsc_emu5.zip (updated)

Code: Select all

/* Luma amplitudes */
float luma [3] [4] = {
    0.39, 0.67, 1.00, 1.00, /* x0 */
    0.14, 0.34, 0.66, 0.86, /* x1-xC */
    -0.12,0.00, 0.31, 0.72  /* xD */
};

/* Chroma sine wave amplitudes */
float chroma [4] = { 0.26, 0.33, 0.34, 0.14 };
Just the levels, please, no RGB.
Agreed all the way. The RGB depends on the TV's decoder.
Also, did you use signal clamping for that screenshot, or did the 3x colors turn out that way by themselves? Or do the 3x colors really have a different amplitude than the rest?
The NES apparently clamps its NTSC signal on the RCA output. I fed the video card another video signal with pure white and it was about 4% higher than the highest NES levels, so the video digitizer itself isn't clamping either.
Here, I made a .PAL file from Blargg's screenshot. Note that this screenshot is at a hue knob setting of minus 15 or so degrees. If you compare this with a "video-essentials" calibrated TV (hue knob at +/- zero degrees, no hue change), it'll be a little bit more greenish.
Maybe I should remove that, so people don't prematurely go using it as a "correct" palette (espcially since it was wrong, due to the sine/square wave error mentioned above). People, all that's reliable here are the raw NTSC video waveform values. The images above are with my (somewhat crappy) NTSC emulator. That will be the next thing that gets polished up.

EDIT: Re-adjusted chroma amplitudes back to same values as square waves (i.e. no 1.27 factor anymore), as per later discussion.
Last edited by blargg on Thu Feb 09, 2006 3:58 pm, edited 1 time in total.
User avatar
blargg
Posts: 3717
Joined: Mon Sep 27, 2004 8:33 am
Location: Central Texas, USA
Contact:

Post by blargg »

A square wave of amplitude 1.0 is made of sine harmonics 1.27*sin(t) + 1.27*sin(3*t)/3 + 1.27*sin(5*t)/5 + ... So the unfiltered NES signal stays within video levels, but after a low-pass it can go above. This leaves the TV an opportunity to do further clamping that could affect the image.

As for absolute level, I did some rough comparisons (digitize normal video signal and compare levels) and it seems that $0F and $30 roughly match the black and white levels of my video camera (cheap Sony Handycam). Is there anything special to take this into account? I figure the absolute DC level of the signal only affects the luminance.

I'll try to measure the video signal outside the active area, but it's kind of hard because I can't get a clean uninterrupted sample of data. What I'm currently doing is feeding the 1/6 speed NES video signal to the capture card and supplying a separate video signal to another input for synchronization. This means that for each field I get a series of 240 blocks, each 640 samples, with around 160 samples delay between each block. At 1/6 the rate, 640 samples only gets a small part of the NES scanline. I don't see any way to tell the card to digitize data uninterrupted.

I've checked a few more things. The colorburst is at the same phase as color $x8. I'm almost done with emphasis. It's pretty simple as far as the effect on the raw waveform, but I'll have to do some Fourier analysis to determine the effective color phase and saturation since it causes non-50% duty waveforms.
NewRisingSun
Posts: 1312
Joined: Thu May 19, 2005 11:30 am

Post by NewRisingSun »

but I correct an error on my part of using the chroma square wave amplitude directly without adjusting by 1.27 (to get the amplitude of the fundamental sine wave).
I'm not sure you should do that in the NES video encoder, because that will adversely affect the luma artifacts as well. Also, at least on my calibrated TV, it looks exactly like the levels without the 1.27, so maybe we should just ditch that altogether.

Either way, it's obvious that the information in the 2c02 document which says that the saturation=amplitude is the same for all colors, is wrong and should be revised. Also, the 0x luma values of 0.15, 0.35, 0.65, 0.85 is not what I would call "linear". :)
The NES apparently clamps its NTSC signal on the RCA output
I'm not sure color 30's level is within the NTSC spec though. You said you normalized the waveform --- what is the exact voltage for that level?
It seems that $0F and $30 roughly match the black and white levels of my video camera (cheap Sony Handycam)
That's bad, because the NES' black level is actually the blanking level. In real NTSC, it should be 7.5% above blanking, so your camera isn't up to spec (the American one at least) either.
User avatar
Quietust
Posts: 1786
Joined: Sun Sep 19, 2004 10:59 pm
Contact:

Post by Quietust »

NewRisingSun wrote:That's bad, because the NES' black level is actually the blanking level. In real NTSC, it should be 7.5% above blanking, so your camera isn't up to spec (the American one at least) either.
Are you referring to color $0D, or are you referring to xE/xF/1D (which are all nearly the same very dark gray)?
Quietust, QMT Productions
P.S. If you don't get this note, let me know and I'll write you another.
NewRisingSun
Posts: 1312
Joined: Thu May 19, 2005 11:30 am

Post by NewRisingSun »

Are you referring to color $0D, or are you referring to xE/xF/1D (which are all nearly the same very dark gray)?
I am refering to the LEVELS.WAV file that Blargg posted. The blanking level during the front/back porch is the same level (minus 50 percent) as what is the level of color 0F, which is black. In American NTSC, "black" should be 7.5% higher than the blanking level, but the NES' black (color 0F) is AT blanking level, probably because in Japanese NTSC, they are the same.
Color 0D is at minus 65 percent and thus below blanking level (sync is minus 100 percent).
A square wave of amplitude 1.0 is made of sine harmonics 1.27*sin(t) + 1.27*sin(3*t)/3 + 1.27*sin(5*t)/5 +
This page describes a device that generates a sine wave from a square wave. It says that "the fundamental frequency component of a square wave is about 1.27 times the peak amplitude of the square wave", but more importantly, "and the amplitude of the sine wave output will be approximately 87 percent of the peak of the square wave". So the chroma amplitude should be 87 percent?
User avatar
blargg
Posts: 3717
Joined: Mon Sep 27, 2004 8:33 am
Location: Central Texas, USA
Contact:

Post by blargg »

OK, I was able to do scanline timing by timing how much of the signal is blanked out and having my digitizer program insert zero samples there to compensate. The time units are PPU clocks.

Code: Select all

25  sync
4   black
15  colorburst
5   black
1   odd pulse
15  left border (color 0)
256 active
11  right border (color 0)
9   black
------------------------------
341 scanline
Here is the raw waveform. I filled the screen with solid tiles of color $30 and set the background to color $0D (so you could see the difference between background and black fill). Note how the digitizer is adjusting the gain/offset periodically, making absolute level measurements useless for this sample. Only use it for timing.

ntsc_scanline.wav

Regarding the absolute video levels, ignore everything I've said so far. I've noticed that the card is doing some kind of adjustment of the digitizer's range based on the signal, so I can't do meaningful comparisons between separate signals. I'll have to come up with some other way (like quickly switching in a fixed voltage source while digitizing).
I'm not sure you should do that in the NES video encoder, because that will adversely affect the luma artifacts as well.
If the encoder is generating the filtered signal, it seems it must output the sine wave component of the square wave. The only way to avoid this translation is to generate the signal at many times the normal video bandwidth (which is admittedly the correct thing to do, since that would handle the chopped-off edges between pixels properly). We'd need some more optimization talent to make that work in real-time.

I found that same page for square wave levels. I'm assuming the latter quote "and the amplitude of the sine wave output will be approximately 87 percent of the peak of the square wave" refers to the output of the filter/amplifier described. Try it yourself; if you want to generate a square wave of amplitude 1.0 from sine waves, you'll have to incorporate a 1.27 factor somewhere. Am I correct that the only effect this issue has is on the color saturation? If so, then I'll trust your end-result comparisons.

EDIT: Updated timing table to be in PPU clocks (duh!).
Last edited by blargg on Mon Feb 06, 2006 1:26 pm, edited 1 time in total.
NewRisingSun
Posts: 1312
Joined: Thu May 19, 2005 11:30 am

Post by NewRisingSun »

Code: Select all

206     left border (15 pixels) 
3515    active (256 pixels) 
151     right border (11 pixels)
So 282 NES pixels, or 752 active pixels out of 910 total = 17.4% Blanking. Sounds good to me. So, to properly render a NES picture at the correct aspect ratio, stretch from 282 to 640 if you're working in RGB, or from 282 to 752 if you're doing NTSC artifacting, then shrink back to 640. Then you'll have everything correct. :)
Thanks for looking into this.
If the encoder is generating the filtered signal
I'm not sure we should worry about that at all. Empirically, my TV doesn't do that, because if I use the square wave amplitude as the chroma amplitude, everything looks right, whereas with *1.27, it looks oversatured. Is it possible that my TV just does not do the "filter to the fundamental sine wave" thing?
User avatar
blargg
Posts: 3717
Joined: Mon Sep 27, 2004 8:33 am
Location: Central Texas, USA
Contact:

Post by blargg »

Note that I updated the scanline timing table to be in PPU clocks (don't know why I didn't do this the first time).
Empirically, my TV doesn't do that, because if I use the square wave amplitude as the chroma amplitude, everything looks right, whereas with *1.27, it looks oversatured. Is it possible that my TV just does not do the "filter to the fundamental sine wave" thing?
If you've got a square wave at 3.579545 MHz (colorburst), then it's got a harmonic at 10.74 MHz, another at 17.90 MHz, etc. These are way beyond a video signal, so I'd expect a TV to remove them at some point. If they are removed, then the remaining sine wave at ~3.58 MHz will have an amplitude higher than you might expect, because the harmonics were canceling its peak somewhat.

Hmmm, I just realized that by running my NES at 1/6 its normal speed, any internal video filtering will behave differently. So I guess this puts the clamping issue into bigger doubt. On the bright side, that means I'm effectively measuring the signals before internal filtering, which might help map it out. I'll have to measure the video signal once I've put the original oscillator back in my NES. This digitizer doesn't filter the signal so I'll be able to still see the chroma signals and find if they're clamped. Argh, sorry for these confusions due to my setup. That's why I post the details so you can scrutinize my conclusions.

EDIT: You were right. Here's what the beginning of a scanline full of repeating $0F $31 $31 $30 (four pixels for each color) looks like from my NES running at full speed:

Image

Note how the chroma wave clamps at the same level as $30, without any overshoot.
Post Reply