• Please review our updated Terms and Rules here

Two CGA Questions (6845 Operation)

cr1901

Veteran Member
Joined
Dec 28, 2011
Messages
817
Location
NJ
I'm fairly close to being able to visualize how the old CGA/MDA cards work with a 6845 work- from the first character of the first row to vertical retrace. However, even after reading the 6845 datasheet, the CGA Adapter Manual, and the 6845/CGA Wikipedia pages, I still have two questions re: the operation of the 6845 (probably related). Specifically, the math isn't adding up for me:

  1. This is how I understand CGA operation: The CGA adapter cheats the 6845, a character-oriented controller, into doing graphics mode by making the 6845 think that it's drawing to a terminal that has characters that are two scanlines high and 100 character rows total before retrace begins (for 200 scanlines). This is done because internally the 6845 cannot support more than 128 character rows, and we need at least 200 scanlines, so 1 scanline/row doesn't work. 16000 bytes / 200 scanlines = 80 bytes per scanline. In this configuration, thanks to the 128 row limit, MA13 is never asserted so RA0 effectively takes over the role of MA13. Unfortunately, since RA0 doesn't increment at the same rate as MA13, this accounts for the framebuffer being split across address ranges.

    The above would mean for 320x200 operation, each byte would contain 4 pixels (2 bits/pixel) and 640x200 mode, each bit represents a different pixel (on/off per pixel). Indeed, this checks out with the description of the gfx modes. However, in the CGA Adapter Manual, I see that the 6845 is programmed for 40 horizontal elements/scanline- there's only time for 40 dot-clock events before the display is blanked (display output on 6845 is asserted) and hsync is asserted soon after! I don't see how this reconciles with the description I presented above, but indeed these are the parameters stored in the BIOS ROM, so my math must be off somewhere. What am I missing?

  2. The CGA Monitor Adapter treats 160x100 (which is a tweaked 40x25 text mode- presumably a typo and they meant 80x25) as having PELs (Picture Elements- pixels?) 2-high by 2-wide. Additionally, both 320x200 and 640x200 are treated as having PELs that are 1-high by 1-wide. What are these dimensions in terms of? scanlines-high and dots-wide? Both 320x200 and 640x200 are programmed using the same exact settings on the 6845, so this makes me think each PEL in 320x200 is 1-high by 2-wide (i.e. each color is held for two dot clocks), and 640x200 as 1-high by 1-wide.

What am I missing?

EDIT: I think I'm going to have to become more intimately familiar with the IBM CGA card circuitry than I ever wanted to. Some things I've noticed about the 6845 on the card: MA13 is a no-connect. MA12 is only enabled if the Graphics Mode in the status register is set. The MSB (Address Line 7 during CAS) of the Video DRAM, which would be normally be provided by MA13, is provided by HCLK. Hmmm...

EDIT2: The 6845's clock speed varies depending on whether the the HiRes Mode in the status register is set- it APPEARS to be halved if HiRes mode is not set. So it seems the answer to my question 2 is that IBM is in fact correct.
 
Last edited:
However, in the CGA Adapter Manual, I see that the 6845 is programmed for 40 horizontal elements/scanline- there's only time for 40 dot-clock events before the display is blanked (display output on 6845 is asserted) and hsync is asserted soon after! I don't see how this reconciles with the description I presented above,

The answer is that one horizontal element (character) in graphics modes is two bytes, not one. In fact one character is two bytes in all modes - in text modes those two bytes are a character and an attribute. In graphics modes they are side-by-side packed pixel data. So the screen is 40 characters wide in graphics modes and 40-column text mode, and 80 characters wide in 80-column text mode. The VRAM layout as seen by the CRTC is different to the VRAM layout as seen by the CPU.

What are these dimensions in terms of? scanlines-high and dots-wide? Both 320x200 and 640x200 are programmed using the same exact settings on the 6845, so this makes me think each PEL in 320x200 is 1-high by 2-wide (i.e. each color is held for two dot clocks), and 640x200 as 1-high by 1-wide.

Yes, that's right.

MA12 is only enabled if the Graphics Mode in the status register is set.

Actually it's only enabled in text mode (ANDed with -GRPH). So you can set start addresses anywhere in the 16kB in text mode, and only in the first 8kB in graphics modes.
 
The answer is that one horizontal element (character) in graphics modes is two bytes, not one.
Is this why the DRAM on the CGA in fact has D0-D1 data inputs/outputs? I have not been able to find a datasheet for it, but it was something I noticed.

Additionally, am I correct in understanding that in HiRes mode the input CLK to the 6845 is full speed (14MHz), and halved in non-HiRes, effectively doubling the width per individual PEL/pixel? AIUI, the sync pulses that are sent to the monitor itself are NOT the same as the sync pulses output from the 6845, so the doubling in HSync period wouldn't screw up timings.
 
Is this why the DRAM on the CGA in fact has D0-D1 data inputs/outputs? I have not been able to find a datasheet for it, but it was something I noticed.

No, the two data lines are connected together, so only 16kB is actually usable. The circuit seems to be really designed for 16384x1 RAM chips, but I guess it was just that 16384x2 chips were available, fast enough and cheapest at the time.

The two bytes in each character are accessed sequentially, and which is currently being accessed is determined by pin 3 of U62 (i.e. CAS address line 7) which is -HCLK. That is 1.79MHz in low-res modes and 3.58MHz in 80-column (+HRES) mode.

Additionally, am I correct in understanding that in HiRes mode the input CLK to the 6845 is full speed (14MHz), and halved in non-HiRes, effectively doubling the width per individual PEL/pixel?

The input CLK to the 6845 is 1.79MHz in +HRES mode and 895kHz in all other modes (40-column text mode and both graphics modes). That corresponds to the rate of data transfer from RAM to the output during the active period (16 bits per character, so 1.79MB/s in -HRES and 3.58MB/s in +HRES).

That character clock is not to be confused with the pixel clock, though, since the pixel clock is 14.318MHz in 1bpp mode and 7.16MHz in 2bpp mode, and both of those use -HRES (895kHz character clock).

AIUI, the sync pulses that are sent to the monitor itself are NOT the same as the sync pulses output from the 6845, so the doubling in HSync period wouldn't screw up timings.

That's right to a first approximation. The sync pulse generated by the 6845 (with normal BIOS programmed values) is 10 character periods wide, in all modes. The CGA has hardware which transforms this pulse into the sync and burst sequence for proper composite display. That works out as 3 or 4 hchars[*] of front porch, 8 hchars of sync, 2 hchars of breezeway, 4 hchars of burst and 2 hchars of back porch. Adding those up gives a total of 20. The "3 or 4" is because the sync structure is timed by +LCLK, which will correspond to either even characters or odd characters from the CRTC when in +HRES mode, depending on exactly when the mode was set.

In +HRES mode this doesn't work out quite so well because when the +HSYNC from the 6845 goes low, the whole sync structure is abandoned. So that gives either 7 or 6 hchars of output horizontal sync and no breezeway, burst or back porch. 75%-87.5% of a normal sync pulse is plenty wide enough for any CRT (and most but not all modern monitors). However, the lack of a color burst means that you don't get composite colour in 80-column mode unless you change the border colour (usually to 6) or the 6845's sync width (changing it to the maximum of 16 character periods means the sync stops after 75% or 50% of the burst, which is usually enough to get colour).


[*] My own term for a period of time corresponding to 8 pixels in 1bpp mode, about 559ns.
 
While it's on my mind: Did you learn how this card works by annotating a printed-out version of the schematic, or do you find the IBM labeling sufficient?

FWIW, IBM does do good labeling IMO, but I'm still having trouble wrapping my head around the composite NTSC output. Do you know any good references for how an NTSC encoding might be designed with discrete (limited to TTL series, discrete transistors) components? The CGA card is proof it can be done, albeit not optimally :p.
 
While it's on my mind: Did you learn how this card works by annotating a printed-out version of the schematic, or do you find the IBM labeling sufficient?

I did print it and I annotated a little but mostly just made lots of notes in a text file. I usually have to double-check on the schematic to answer questions about the CGA card, but I've internalized enough that I can now do that with the unannotated PDF.

FWIW, IBM does do good labeling IMO, but I'm still having trouble wrapping my head around the composite NTSC output. Do you know any good references for how an NTSC encoding might be designed with discrete (limited to TTL series, discrete transistors) components? The CGA card is proof it can be done, albeit not optimally :p.

Can you be more specific about what you're having trouble with? The final output stage is fairly straightforward - there are 4 (or 6 for newer cards) digital outputs which are connected to resistors of different values. The current through each of these resistors is inversely proportional to the resistance (when the output is high) or zero (when the output is low). Then these currents are summed at the base of the transistor which just works as a current mirror so that you get a suitable voltage range at 75 ohm impedance.

The rest of it is just a matter of knowing how to generate NTSC signals (sync and burst pulses in the right place, 3.57MHz signals with the appropriate phase, amplitude and DC offset for the hue, saturation and lightness you want).

The CGA's NTSC signal isn't perfectly compliant and doesn't display consistently on all output devices (especially the older one). Making a perfectly compliant signal would certainly be possible but it would probably be quite a lot of extra circuitry for a small improvement in compatibility. One way might be to have a proper (resistor ladder) DAC and store the correct sync pulses in a ROM. A truly compliant signal would also be interlaced, which might not be ideal for computer monitor use and introduces some additional complications.
 
Can you be more specific about what you're having trouble with? The final output stage is fairly straightforward - there are 4 (or 6 for newer cards) digital outputs which are connected to resistors of different values. The current through each of these resistors is inversely proportional to the resistance (when the output is high) or zero (when the output is low). Then these currents are summed at the base of the transistor which just works as a current mirror so that you get a suitable voltage range at 75 ohm impedance.
Since I wrote this question, I was able to learn (more or less) what's required to generate NTSC. I still haven't actually analyzed the output stage to figure out what the output voltage will be for a given input, but I think I should be okay. This ultimately leads into another question, incidentally coinciding with the release of 8088 MPH.

My main question now, unfortunately, is so involved, that it has required me to write a script to simulate the non-blanked period of NTSC and then plot the FFT. So far, I've only written enough to simulate one scanline, and I'm not even sure the colorburst is correct. Do you know of a good source besides ntsc-tv.com (a technically accurate, but extremely hard to follow site) that describes the spec's timing for an entire superframe? AIUI, the colorburst for two of the fields of a superframe is 180 out of phase with the other two fields.

My question, in short: I want to know mathematically how to get a specific color due to composite artifacts. I get that when the luma portion of the signal fluctuates fast enough, a chroma (QAM) decoder mistakes the luma fluctuations for chroma. Is there a nice mathematical formula/simulation to predict the artifact color output given a specific pattern of luma fluctuations?
 
My main question now, unfortunately, is so involved, that it has required me to write a script to simulate the non-blanked period of NTSC and then plot the FFT. So far, I've only written enough to simulate one scanline, and I'm not even sure the colorburst is correct. Do you know of a good source besides ntsc-tv.com (a technically accurate, but extremely hard to follow site) that describes the spec's timing for an entire superframe?

The one where I first learnt the details is Jim Blinn's "Dirty Pixels". Keith Jack's "Video Demystified" goes into more detail but is more of a textbook/reference.

AIUI, the colorburst for two of the fields of a superframe is 180 out of phase with the other two fields.

Standard NTSC is interlaced, so the two fields don't have the same scanlines. Therefore you can't directly compare their color bursts. Standard NTSC has 227.5 color carrier cycles per scanline so the color burst phase changes 180 degrees from one scanline to the next. CGA has 228 color carrier cycles per scanline so the color burst phase is the same on all scanlines.

My question, in short: I want to know mathematically how to get a specific color due to composite artifacts. I get that when the luma portion of the signal fluctuates fast enough, a chroma (QAM) decoder mistakes the luma fluctuations for chroma. Is there a nice mathematical formula/simulation to predict the artifact color output given a specific pattern of luma fluctuations?

Don't think of it as the decoder making a "mistake" - there's no difference between a luma signal that fluctuates at 3.58MHz and a chroma signal for a pure colour.

Here's the model I use to do the colour decoding in software. Doing it in hardware is very similar. Take the composite signal C(t) and multiply it by a sine wave and a cosine wave of color carrier frequency. Now you have three signals C(t), C(t)*sin(2*pi*f*t) and C(t)*cos(2*pi*f*t). Then filter these signals to remove frequencies of the color carrier and above (you will naturally remove some frequencies below the color carrier as will - exactly which you remove determines what frequencies correspond to changing luma and what frequencies correspond to changing chroma).

If you have a signal sampled at 4 times the color carrier frequency (14.318MHz - the CGA 1bpp pixel clock) you can perfectly remove the carrier by filtering with a Finite Impulse Response filter kernel which is polynomial in (1,1,1,1). The one I use is (1,4,7,8,7,4,1) which smooths things out a bit more and doesn't give such sharp edges. After you've done the filtering on your three signals you will have Y, I and Q which you can plug into the matrix at http://en.wikipedia.org/wiki/YIQ to get RGB. You will have to adjust your color carrier phase to get the right hues (that's what the color burst is for). I might also have I and Q the wrong way around (I can never remember which one is sin and which one is cos).

Some monitors do comb filtering (combining information on adjacent scanlines to improve horizontal luma resolution at the expense of vertical chroma resolution) but this only works properly on "natural" signals where the signal is correlated the right way. It also doesn't work properly on CGA signals because (as mentioned above) CGA doesn't reverse the phase from one scanline to the next.
 
Back
Top