To output an NTSC output, the video needs to be encoded in a very special way. This means that the digital video signal has to be converted into a single analog output with color information modulated over the brightness signal. While it seems logical to use a dedicated IC for this, I wanted to do this entirely digital and only use a DAC for the analog signal. This allows me to fully control the NTSC signal, which I want to be progressive, and helps me understand the NTSC encoding, which is quite interesting. As a bonus, this saves cost and complexity of the PCB, as only a simple 8 bit resistor DAC + OpAmp is needed.
!!! info
I will not explain here how NTSC encoding works. For that, use [this 7-part blog by Sagar](https://sagargv.blogspot.com/2011/04/ntsc-demystified-part-1-b-video-and.html), as it very clearly explains everything, even how to get a progressive signal.
The NTSC encoder consists of three parts:
The timing of the progressive NTSC video signal is generated as follows:
Using a clock of 14.31818MHz:
HLINECYCLES = 910; // hline: 910 cycles for 63.555us (227.5 color burst cycles), 0.3V
VLINES = 263; // frame: 263 lines per frame, all the same, for 240P
HSYNCCYCLES = 67; // hsync: first 67 cycles of line, 0V
VSYNCCYCLES = 421; // vsync: first line: 421 cycles, apparently no hsync needed, 0V
HACTIVESTART = 196; // 0.35V Black to 1V White
HACTIVEDURATION = 640; //
VACTIVESTART = 40; //
VACTIVEDURATION = 200; //
COLORBURSTSTART = 70; // start a bit after hsync, 4.7+ (2.2/2) = 5.8, but a bit earlier, because extra cycle
COLORBURSTDURATION = 60; // 10 color burst cycles = 10*4 = 36
As seen by HACTIVEDURATION
, we have a horizontal resolution of 640, which we can easily divide by two.
Color is added using a 114.5454MHz clock, which is 32 times the 3.579MHz color carrier frequency, allowing for 32 different phases. In combination with the amplitude of this signal, a lot of colors can be made.
In order to convert the 256 possible RGB color values to a luma value, color phase and color amplitude, a lookup table is used generated by using Graphics/RGBtoNTSC.py
.
The NTSC base signal, resulting luma value and resulting color modulation signal are added. Clipping is applied to keep the resulting value within the range of the 8 bit DAC.