The 6845 Cathode Ray Tube Controller (CRTC) is a programmable IC used to generate video displays. This IC is used in a variety of computers including the Amstrad CPC, Amstrad CPC+ and KC Compact.
The CRTC is a simple chip. It is made up of counters and equality operators, tied by simple logic. All the complexity stems from its multiple independent implementations with their subtle differences.
The CRTC was a common part available from many different manufacturers. During the life of the CPC, Amstrad sourced the CRTC from various manufacturers.
The 6845 is selected when bit 14 of the I/O port address is set to "0". Bit 9 and 8 of the I/O port address define the function to access. The remaining bits can be any value, but it is adviseable to set these to "1" to avoid conflict with other devices in the system.
The recommended I/O port addresses are:
{|{{Prettytable|width: 700px; font-size: 2em;}}|''I/O port address''||''Function''||''Read/Write''class="wikitable"
|-
|&BCxx||Select 6845 register||!I/O port address!/CS (A14)!R/W (A9)!RS (A8)!Function!Read/Write only
|-
|&BDxxBCxx||Write 0||0||0||Select 6845 register data||Write only
|-
|&BExxBDxx||0||0||(note 1)||Read Write to selected internal 6845 register||Write only
|-
|&BExx||0||1||0||* CRTCs 0/2: —* CRTC 1: Read Status Register* CRTCs 3/4: Read from selected internal 6845 register||Read only|-|&BFxx||(note 0||1)||1||Read from selected internal 6845 register||Read only
|-
|}
The CRTC is not connected to the CPU's RD and WR pins, so it cannot detect the bus''NOTE''' 1. The function of these s I/O ports is dependant on the CRTC type 2direction. If you perform Therefore, executing an IN instruction to the select or write functions it will write data to causes the CRTC from to write the current unpredictable data on provided by the high-impedance busto its registers.
==Addressing==
The following table defines VMA of the generated memory address [[Gate Array]] is constructed from the CRTC MA and Gate-Array RA signals. :
{|{{Prettytableclass="wikitable"|width: 700px; font-size: 2em;}}|''!Video Memory Address Signal''||''!Signal source''||''!Signal name''
|-
|A15||6845||MA13
|A14||6845||MA12
|-
|A13||6845||'''RA2 '''
|-
|A12||6845||'''RA1 '''
|-
|A11||6845||'''RA0 '''
|-
|A10||6845||MA9
|}
CRTC generates the address, Gate-Array reads the data and converts it to pixels based on the its current graphics modeand palette.
== DISPTMG ==CRTC pins RA3, RA4, MA10, MA11 are not connected on CPC.
DISPTMG signal defines the border<br> === Overscan bits === It is possible to use 32KB screen size (used for [[Programming:Overscan|overscan]]) by setting bits 11 and 10 of Register 12 both to 1. When DISPTMG Bits MA11 and MA10 of the address generated by the CRTC are not written on the address bus to access video memory; settings both bits to 1 is the only way to cause a carry to bit MA12 when address pass over the end of current video page to change the memory address to the next video page. {| class="wikitable"|+ CRTC Display Start Address|-! colspan="8" | Register 12! colspan="8" | Register 13|-! 15 !! 14 !! 13 !! 12 !! 11 !! 10 !! 9 !! 8! 7 !! 6 !! 5 !! 4 !! 3 !! 2 !! 1!! 0|-| colspan=" 2" | Unused| colspan="2" | Video Page| colspan="2" | Page Size| colspan="10" | Start Address (1024 positions)|} {| style="white-space: nowrap;"|-|{| class="wikitable" style="margin-right: 32px"|-! Bit 13 !! Bit 12 !! Video Page|-| 0 || 0 || 0000 - 3FFF|-| 0 || 1 || 4000 - 7FFF|-| 1 || 0 || 8000 - BFFF|-| 1 || 1 || C000 - FFFF|}|{| class="wikitable"|-! Bit 11 !! Bit 10 !! Page Size|-| 0 || 0 || 16KB|-| 0 || 1 || 16KB|-| 1 || 0 || 16KB|-| 1 || 1 || '''32KB'''|}|} <br> === Coarse hardware scrolling === The start address can be manipulated to achieve horizontal and/or vertical hardware scrolling: *To move right: <code>start_address := start_address + 1</code>*To move left: <code>start_address := start_address - 1</code>*To move down: <code>start_address := start_address + R1</code>*To move up: <code>start_address := start_address - R1</code> However, it is a position in word (16 bits), not in byte. So, the border colour screen will move two bytes at a time horizontally. Also, the precision will be one CRTC character vertically. The first game that used R12/R13 for both horizontal and vertical hardware scrolling is output [https://www.cpc-power.com/index.php?page=detail&num=1839 Roland on the Ropes], released in 1984. The following BASIC program demonstrates the coarse scrolling by setting the GateR12 and R13 registers based on keyboard input: <pre>10 ma%=020 IF INKEY(1)=0 THEN GOSUB 10030 IF INKEY(2)=0 THEN GOSUB 30040 IF INKEY(8)=0 THEN GOSUB 50050 IF INKEY(0)=0 THEN GOSUB 70060 GOTO 20100 ' right110 ma%=ma%+1: GOSUB 900: RETURN300 ' down310 ma%=ma%+40: GOSUB 900: RETURN500 ' left510 ma%=ABS(ma%-Array to 1): GOSUB 900: RETURN700 ' up710 ma%=ABS(ma%-40): GOSUB 900: RETURN900 ' set R12 and R13910 l%=ma% AND 255: h%=&30 OR ((ma%\256) AND 3) :OUT &BC00,13:OUT &BD00,l%: OUT &BC00,12:OUT &BD00,h%930 RETURN</pre> Which looks like the displayfollowing: [[File:CRTC-Coarse-scroll. The DISPTMG gif]] <br> === Advanced hardware scrolling === To achieve smoother hardware scrolling, other tricks are required in complement to R12/R13. Usually, R3 is used for smooth horizontal scroll and R5 for smooth vertical scroll. A good example of smooth hardware multidirectional scrolling game on CPC is [https://www.cpc-power.com/index.php?page=detail&num=2119 Super Cauldron], released in 1993. Everything you need to know about hardware scrolling on CPC can be forced using R8 found [https://www.cpcwiki.eu/forum/programming/hardware-scrolling-21687/ there]. <br> == Split screen (DISPTMG Skewaka Rupture) == While there is usually 1 CRTC frame per screen frame, the screen frame can be divided into multiple CRTC frames of varying proportions. This is useful for defining different scrolling zones in your screen frame. For example, it was used for hardware parallax scrolling in the game [https://www.cpc-power.com/index.php?page=detail&num=1307 The Living Daylights], released in 1987. [https://www.cpcwiki.eu/forum/programming/the-living-daylights-extra-colours-in-mode-1-rasters-screen-splits/ Source] And this is basically the bread and butter of innumerable CPC demos. Some rules of thumb [https://www.cpcwiki.eu/forum/programming/advice-on type 0-split-screen-code/msg242186/ Source]:* changes to the screen address have to be done anywhere in the previous split* changes to the height of the split have to be done inside the current split (after it has started,3 in the area of the size of the previous split)* changes to screen mode and colours are happening immediately CRTC registers and screen splitting:*reg 0 (63) = x-screenwidth (usually always 63)*reg 1 (50) = x-splitwidth (e.g.50)*reg 2 (51) = x-splitstart (e.g. 51)*reg 3 (08) = x-finestart (maybe use this for half-char scrolling)*reg 4 or by setting R6(##) =y-splitheight-1 (set this inside the current split)*reg 5 (00) = y-finestart*reg 6 (25) = y-max visible splitpart (same like 4)*reg 7 (##) = inside last split -> set to 0 on type ; inside first split, but after vblank -> set to 255*reg 9 (07) = y-lines/char-1 Set this inside the previous split:*reg12 (##) = address high (char / 256 + block * 16)*reg13 (##) = address low (char mod 256) Total height of all splits must be 39. It The [https://www.cpcwiki.eu/forum/programming/interrupt-positions-with-various-sized-screens/ IntPos tool] by Kevin Thacker can help visualize the potential split screen areas. Note: If all you want is multiple graphics modes in the same frame, you don't need to touch the CRTC at all. More information here: [https://www.cpc-power.com/cpcarchives/index.php?page=articles&num=184 Multi-Mode Graphique (FR)] <br> == CUDISP (aka CURSOR) == CUDISP (Cursor Display) signal defines the hardware cursor. CRTC pin CUDISP is not possible connected to force the DISPTMG Gate Array, so it has no effect on type 2 a barebone CPC or 5Plus machine. However, this signal is provided to the [[Connector:Expansion port]]. And it is used by the [[PlayCity]] and [[Play2CPC]] expansions. <br> == DISPTMG (aka Display Enable) == DISPTMG (Display Timing) signal defines the border. When DISPTMG is "0" the border colour is output by the Gate Array to the display.
The border has higher priority than pixels but lower priority than the black colour output when HSYNC/VSYNC are active.
While border is active, all the CRTC counters continue to increment normally and addresses continue to be generated.
The DISPTMG signal is composited from its 3 internal subcomponents: HBORDER (Horizontal), VBORDER (Vertical), SBORDER (Split) by using the NOR function. DISPTMG is "0" if at least one of its subcomponents is "1". These 3 subcomponents are all independent of each other.
<br>
=== HBORDER ===
On all CRTCs, HBORDER is disabled when HCC=0 and enabled when HCC=R1.
The exception is for CRTC2 during an HSYNC: the HCC=0 check is skipped, so HBORDER stays on.
<br>
=== VBORDER ===
On all CRTCs, VBORDER is disabled when VCC=0 and enabled when VCC=R6.
On CRTCs 0/1/2, the condition VCC=R6 is tested on every cycle.
On CRTCs 3/4, the condition VCC=R6 is tested only at each new character line start (when VLC=0 and HCC=0).
<br>
=== SBORDER ===
Split border is a technique similar to split rasters, except that it is handled by the CRTC instead of the [[Gate Array]].
DISPTMG can be temporarily forced to 0 by using R8 (DISPTMG Skew) on CRTCs 0/3/4, or by setting R6=0 on CRTC 1.
It is not possible to force DISPTMG on CRTC 2.
<br>
=== Border bytes ===
Despite their 1MHz clock speed, CRTCs 0/2 have been observed to change state at a rate equivalent to 2MHz chips by responding to both the rising and falling edges of each clock cycle.
==== Interline border ====
On CRTCs 0/2, R1>R0 generates one byte (0.5µs) of border at the end of the raster line. On CRTCs 1/3/4, it does not.
To see the border bytes with your own eyes, type this BASIC line after reset:
<pre>
BORDER 6:OUT &BC00,6:OUT &BD00,0
</pre>
== HSYNC and VSYNC ==
registers 18-30 read as 0 on type1, register 31 reads as 0x0ff.
Details about Reg. 12 and Reg. 13 specifically:<br>
.------- REG 12 --------. .------- REG 13 --------. | | | | 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 .--.--.--.--.--.--.--.--. .--.--.--.--.--.--.--.--. |X |X | | | | | | | | | | | | | | | | '--'--'--'--'--'--'--'--' '--'--'--'--'--'--'--'--' '--.--'--.--'---------------.-----------------' | | | | | '------> Offset for setting | | videoram | | (1024 positions) | | Bits 0..9 | | | '-------------------------> Video Buffer : note (1) | '-------------------------------> Video Page : note (2) note (1) note (2) .--.--.--------------. .--.--.---------------. |11|10| Video Buffer | |13|12| Video Page | |--|--|--------------| |--|--|---------------| | 0| 0| 16Ko | | 0| 0| 0000 - 3FFF | |--|--|--------------| |--|--|---------------| | 0| 1| 16Ko | | 0| 1| 4000 - 7FFF | |--|--|--------------| |--|--|---------------| | 1| 0| 16Ko | | 1| 0| 8000 - BFFF | |--|--|--------------| |--|--|---------------| | 1| 1| 32Ko | | 1| 1| C000 - FFFF | '--'--'--------------' '--'--'---------------'=== Screen size ===
So, it's possible to use 32KB We can calculate the screen size in words by multiplying R1 x R6 x (used for [[Programming:Overscan|overscan]]) by setting bits 11 and 10 both to R9+1 (of Register 12). Bits MA11 and MA10 of And then multiplying the address generated result by 2 to have the screen size in bytes. With the default CRTC are not written on the address bus to access video memory; settings both bits to values, we obtain 40 x 25 x (7+1 is the ) x 2 = 16000 bytes. So we can observe that only way to cause a carry to bit MA12 when address pass over the end part of current video page to change the memory address to the next video 16384 bytes (=16KB) pageof VRAM is actually displayed on screen. <br>
== CRTC Differences ==
== Horizontal and Vertical Sync (R3) ==
UM6845:=== Horizontal and Vertical Sync (R3) ===
Type 0:*Bits 7..4 define Vertical Sync Width. If 0 is programmed , this gives 16 lines of VSYNC.*Bits 3..0 define Horizontal Sync Width. If 0 is programmed , no HSYNC is generated(and therefore, no interrupts).
UM6845RType 1:*Bits 7..4 are ignored. Vertical Sync is fixed at 16 lines.*Bits 3..0 define Horizontal Sync Width. If 0 is programmed, no HSYNC is generated (and therefore, no interrupts).
Type 2:*Bits 7..4 are ignored. Vertical Sync is fixed at 16 lines.*Bits 3..0 define Horizontal Sync Width. If 0 is programmed no , this gives a HSYNC is generatedwidth of 16.
MC6845Types 3/4:*Bits 7..4 define Vertical Sync Width. If 0 is programmed, this gives 16 lines of VSYNC.*Bits 3..0 define Horizontal Sync Width. If 0 is programmed, this gives a HSYNC width of 16.
Bits 7..4 are ignored. Vertical Sync is fixed at 16 lines.Bits 3..0 define Horizontal Sync Width. If 0 is programmed this gives a HSYNC width of 16.<br>
Pre-ASIC/ASIC:=== Interlace and Skew (R8) ===
Types 0/3/4:*Bits 7..4 6 define Vertical Sync Widththe skew (delay) of the CUDISP signal (00 = Non-skew ; 01 = One-character skew ; 10 = Two-character skew ; 11 = Non-output). If 0 is programmed this gives 16 lines *Bits 5..4 define the skew (delay) of VSYNCthe DISPTMG signal (00 = Non-skew ; 01 = One-character skew ; 10 = Two-character skew ; 11 = Non-output).*Bits 3..2 are ignored.*Bits 1..0 define Horizontal the interlace mode (00 = No Interlace ; 01 = Interlace Sync Width. If 0 is programmed this gives a HSYNC width of 16; 10 = No Interlace ; 11 = Interlace Sync and Video).
Types 1/2:*Bits 7..2 are ignored.*Bits 1..0 define the interlace mode. <br> === UM6845R and R31 on Type 1 ===
R31 is described in the UM6845R documentation as "Dummy Register".
Its use is described in the documentation for the Rockwell R6545 in combination with R18, R19 and R8 and the Status Register.
In the UM6845R it appears to have no effect. Reading and writing does nothing. Reading it returns 0x0ff&FF.
R31 doesn't exist on types CRTCs 0,/2,/3/4. <br>
== UM6845R and R12/R13 ==
All the other bits read as 0 and don't have any function.
== CRTC Type Detection ==
It is possible to detect the CRTC Type using software methods, and this is done to:
* warn that the software was not designed for the detected 6845 and may function incorrectly
* to adapt the software so that it will run with the detected 6845
* In most cases, the type of the detected 6845 is reported
Detection routine in BASIC:
<pre>
10 MODE 1:' Reinitialize screen
20 OUT &BC00,31:IF INP(&BF00)=255 THEN PRINT"crtc 1":END
30 OUT &BC00,12:IF INP(&BF00)=0 THEN PRINT"crtc 2":END
40 OUT &BC00,20:IF INP(&BF00)=0 THEN PRINT"crtc 0":END
50 PRINT"crtc 3/4"
</pre>
Distinguishing between CRTCs 3 and 4 can be done by trying to [[Programming:Unlocking ASIC|unlock the ASIC]] or by testing the [[8255|PPI chip]]. On ASIC, if PPI Port B is set as output it will behave the same as input.
<br>
== CRTC Timing Diagrams ==
[[File:CRTC Timing Diagram Rockwell.png]]
<br>
[[File:CRTC timing small.gif]]
<br>
== Block Diagrams ==
{| class="wikitable"
|-
!Hitachi
!UMC
!Motorola
|-
|[[File:CRTC Block Diagram.png|Hitachi]]
|[[File:UMC CRTC Block Diagram.png|UMC]]
|[[File:Motorola CRTC Block Diagram.png|Motorola]]
|}
<br>
== CRTC-II (aka Type 5) ==
The [[Media:CRTC-5-HD6345.pdf|HD6345 datasheet]] states it is upward-compatible with the HD6845S in pin and software.
This chip was never used by Amstrad. However, some CPC enthusiasts have replaced the original CRTC chip in their CPC with this one.
With this chip, split-screen becomes easy: [https://thecheshirec.at/2024/05/20/des-splitscreens-en-basic-sur-crtc5/ Split-screen in BASIC]. And 3 new graphics modes (160x100x16c, 320x100x4c, 640x100x2c) are available: [https://thecheshirec.at/2024/11/10/trois-nouveaux-modes-video-grace-au-crtc-5/ New graphics modes in BASIC].
This is the cheapest way to upgrade the CPC's graphics capabilities, costing only 1.29€. [https://thecheshirec.at/2024/05/19/des-crtc5-a-129e/ Source]
<br>
== Datasheets ==
==== Used by Amstrad ====
* [[Media:hd6845.hitachi.pdf|HD6845S (Hitachi)]] aka Type 0