(→Links) |
(→Split screen) |
||
(473 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
− | + | The 6845 '''CRTC''' (Cathode Ray Tube Controller) chip was created by Motorola in 1977. It works with the [[Gate Array]] to generate the video signal on the Amstrad CPC. This chip is also used in the [[BBC Micro]], [[Sharp X1]], [[MicroBee]], [[Commodore PET]] and the CGA graphics card for [[IBM PC]]. | |
+ | NOTES: | ||
+ | * This document describes the functionality in terms of the CPC with its separate CRTC and Gate-Array. The Plus has both integrated into the same IC, but could be considered to have two functional blocks, one for CRTC and one for Gate-Array. In this document the term 'Gate-Array' is used, but this also applies to the ASIC. | ||
+ | * Much information has been drawn from the CRTC Compendium documentation and condensed for clarity. For details, timing diagrams, code examples, coding tips, and more, refer to that documentation. | ||
− | + | <br> | |
− | + | ||
− | + | ||
== Overview == | == Overview == | ||
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 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 chip really is just a bunch of counters and equality operators. But the devil is in the details, and that's what we will discuss in this article. | ||
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 CRTC was a common part available from many different manufacturers. During the life of the CPC, Amstrad sourced the CRTC from various manufacturers. | ||
Line 16: | Line 19: | ||
This table lists the known ICs used, with their part number, manufacturer and type number. | This table lists the known ICs used, with their part number, manufacturer and type number. | ||
− | {| | + | {| class="wikitable" |
− | + | |- | |
+ | !Part number | ||
+ | !Manufacturer | ||
+ | !Type number (note 3) | ||
|- | |- | ||
|HD6845S||Hitachi||0 | |HD6845S||Hitachi||0 | ||
Line 50: | Line 56: | ||
4. As far as I know, the KC compact used HD6845R only. | 4. As far as I know, the KC compact used HD6845R only. | ||
− | + | <br> | |
− | + | == Z80 I/O access timings == | |
− | ( | + | |
+ | {| class="wikitable" | ||
+ | |+ | ||
+ | ! Instructions !! Duration !! I/O CRTCs 0/1/2 !! I/O CRTCs 3/4 | ||
+ | |- | ||
+ | | OUT (C),r8 || 4 µsec || '''3rd µsec''' || 4th µsec | ||
+ | |- | ||
+ | | OUT (C),0 || 4 µsec || '''3rd µsec''' || 4th µsec | ||
+ | |- | ||
+ | | OUT (n),A || 3 µsec || 3rd µsec || 3rd µsec | ||
+ | |- | ||
+ | | OUTI || 5 µsec || 5th µsec || 5th µsec | ||
+ | |- | ||
+ | | OUTD || 5 µsec || 5th µsec || 5th µsec | ||
+ | |- | ||
+ | | IN r8,(C) || 4 µsec || 4th µsec || 4th µsec | ||
+ | |- | ||
+ | | INI || 5 µsec || '''4th µsec''' || '''4th µsec''' | ||
+ | |- | ||
+ | | IND || 5 µsec || '''4th µsec''' || '''4th µsec''' | ||
+ | |- | ||
+ | | IN A,(n) || 3 µsec || 3rd µsec || 3rd µsec | ||
+ | |} | ||
+ | |||
+ | <br> | ||
==Programming== | ==Programming== | ||
Line 61: | Line 91: | ||
The recommended I/O port addresses are | The recommended I/O port addresses are | ||
− | {| | + | {| class="wikitable" |
− | + | |- | |
+ | !I/O port address | ||
+ | !Function | ||
+ | !Read/Write | ||
|- | |- | ||
|&BCxx||Select 6845 register||Write only | |&BCxx||Select 6845 register||Write only | ||
Line 74: | Line 107: | ||
|} | |} | ||
− | ''' | + | '''NOTES''' |
1. The function of these I/O ports is dependant on the CRTC type | 1. The function of these I/O ports is dependant on the CRTC type | ||
− | 2. | + | 2. The CRTC is not connected to the CPU's RD and WR pins, so the CRTC is not aware of the CPU bus I/O direction. Therefore, if you perform an IN instruction to the select or write functions, it will write data to the CRTC from the current data on the bus. |
− | + | <br> | |
− | + | ==Video Memory Address (VMA)== | |
− | {| | + | The VMA of the [[Gate Array]] is constructed from the CRTC MA and RA signals: |
− | + | ||
+ | {| class="wikitable" | ||
+ | |- | ||
+ | !Video Memory Address | ||
+ | !Signal source | ||
+ | !Signal name | ||
|- | |- | ||
|A15||6845||MA13 | |A15||6845||MA13 | ||
Line 91: | Line 129: | ||
|A14||6845||MA12 | |A14||6845||MA12 | ||
|- | |- | ||
− | |A13||6845||RA2 | + | |A13||6845||'''RA2''' |
|- | |- | ||
− | |A12||6845||RA1 | + | |A12||6845||'''RA1''' |
|- | |- | ||
− | |A11||6845||RA0 | + | |A11||6845||'''RA0''' |
|- | |- | ||
|A10||6845||MA9 | |A10||6845||MA9 | ||
Line 121: | Line 159: | ||
|} | |} | ||
− | CRTC generates the address, Gate | + | CRTC generates the address, Gate Array reads the data and converts it to pixels based on its current graphics mode and palette. |
− | + | CRTC pins RA3, RA4, MA10, MA11 are not connected on CPC. | |
− | + | <br> | |
+ | |||
+ | === Overscan bits === | ||
+ | |||
+ | It's possible to use 32KB screen size (used for [[Programming:Overscan|overscan]]) by setting bits 11 and 10 of Register 12 both to 1. 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. | ||
+ | |||
+ | .------- 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 | ||
+ | | | ||
+ | '-------------------------------> Video Page | ||
+ | |||
+ | .--.--.---------------. .--.--.--------------. | ||
+ | |13|12| Video Page | |11|10| Video Buffer | | ||
+ | |--|--|---------------| |--|--|--------------| | ||
+ | | 0| 0| 0000 - 3FFF | | 0| 0| 16KB | | ||
+ | |--|--|---------------| |--|--|--------------| | ||
+ | | 0| 1| 4000 - 7FFF | | 0| 1| 16KB | | ||
+ | |--|--|---------------| |--|--|--------------| | ||
+ | | 1| 0| 8000 - BFFF | | 1| 0| 16KB | | ||
+ | |--|--|---------------| |--|--|--------------| | ||
+ | | 1| 1| C000 - FFFF | | 1| 1| '''32KB''' | | ||
+ | '--'--'---------------' '--'--'--------------' | ||
+ | |||
+ | <br> | ||
+ | |||
+ | === Split screen === | ||
+ | |||
+ | Some rules of thumb [https://www.cpcwiki.eu/forum/programming/advice-on-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, 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 (##) = 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; 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. | ||
+ | |||
+ | <br> | ||
+ | |||
+ | == CUDISP (aka CURSOR) == | ||
+ | |||
+ | CUDISP (Cursor Display) signal defines the hardware cursor. | ||
+ | |||
+ | CRTC pin CUDISP is not connected to the Gate Array, so it has no effect on a barebone CPC or Plus machine. | ||
+ | |||
+ | However, this signal is provided to the 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. | 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), IBORDER (Immediate) 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. | ||
+ | |||
+ | On CRTC 2, when HSYNC is active, the condition HCC=0 does not disable HBORDER, unlike the other CRTCs. | ||
+ | |||
+ | <br> | ||
+ | |||
+ | === Immediate border === | ||
+ | |||
+ | DISPTMG can be immediately 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 === | ||
+ | |||
+ | ==== 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. | ||
+ | |||
+ | If border skew is used then the border byte will skew and change into a full character-width border instead. | ||
+ | |||
+ | ==== Border conflict ==== | ||
+ | If R1=0 and HCC=0, we expect HBORDER to activate as HCC=R1 and we also expect HBORDER to deactivate as HCC=0. In this situation, all CRTCs activate HBORDER. | ||
+ | |||
+ | If R6=0 and VCC=0, we expect VBORDER to activate as VCC=R6 and we also expect VBORDER to deactivate as VCC=0. In this situation, all CRTCs activate VBORDER. On CRTC 1, even IBORDER is activated. But on CRTCs 0/2, the first raster line shows an alternation of bytes of VBORDER and displayable characters. | ||
+ | |||
+ | ==== Border byte precision ==== | ||
+ | This behaviour exhibited by CRTCs 0/2 shows that, despite their 1MHz clock speed, they can change state at a rate equivalent to 2MHz chips by responding to both the rising and falling edges of each clock cycle. | ||
+ | |||
+ | 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> | ||
+ | |||
+ | <br> | ||
== HSYNC and VSYNC == | == HSYNC and VSYNC == | ||
− | + | The HSYNC and VSYNC signals from the CRTC are not directly connected to the display. They are passed to the [[Gate Array]] for further modification. See its wiki page. | |
− | + | On all CRTCs, while a VSYNC is ongoing, the condition VCC=R7 is ignored. So we cannot trigger a new VSYNC during a VSYNC. Similarly, we cannot trigger a new HSYNC during an HSYNC. | |
− | + | <br> | |
− | + | === HSYNC === | |
− | On | + | The HSYNC width value is interpreted differently between CRTCs. On CRTCs 0/1, if 0 is programmed then no HSYNC is generated (and therefore, no interrupts). On CRTCs 2/3/4, if 0 is programmed then this gives an HSYNC width of 16. |
− | + | ==== Signal delay ==== | |
− | + | On all CRTCs, there is a 1µs delay in display between when the CRTC provides a video pointer, and when the Gate Array displays the corresponding 16-bit character. | |
− | == The | + | But on CRTCs 0/1/2, there is no delay for HSYNC. On CRTCs 3/4, the Amstrad engineers fixed the issue by adding a 1µs delay for the HSYNC signal. |
+ | |||
+ | So now we have a bigger issue: on CRTCs 3/4, HSYNC occurs 1µs later than on CRTCs 0/1/2. Interrupts being dependent on HSYNC, this is a serious compatibility issue for time-sensitive code. It also explains why the CTM monitor has to be calibrated differently on CRTCs 3/4. | ||
+ | |||
+ | ==== Discolouration effect ==== | ||
+ | |||
+ | On CRT monitors from other brands, a colour calibration can happen just after the C-HSYNC pulse. | ||
+ | |||
+ | So even when a fully valid C-HSYNC pulse of 4µs is emitted, an HSYNC shorter than usual combined with a coloured border can induce a discolouration effect on those monitors. | ||
+ | |||
+ | <br> | ||
+ | |||
+ | === VSYNC === | ||
+ | |||
+ | Bit0 of port B of the PPI is directly connected to the VSYNC pin of the CRTC. | ||
+ | |||
+ | CRTCs 1/2 have a fixed VSYNC width value of 16. VSYNC width can be configured with R3 on CRTCs 0/3/4. If 0 is programmed this gives 16 lines of VSYNC. | ||
+ | |||
+ | On CRTCs 0/1/2, the sole condition to trigger a VSYNC is that VCC=R7. While on CRTCs 3/4, it is necessary to have VCC=R7 and HCC=0 and VLC=0 to trigger a VSYNC. | ||
+ | |||
+ | ==== Ghost VSYNC ==== | ||
+ | |||
+ | On CRTC 2, if a VSYNC is triggered during an HSYNC, the CRTC produces a ghost VSYNC. The CRTC then counts the lines as if a VSYNC were taking place by preventing a new VSYNC from occurring, but without the VSYNC pin being enabled. | ||
+ | |||
+ | ==== Mid-VSYNC ==== | ||
+ | |||
+ | On all CRTCs, in both interlace modes, a mid-VSYNC is generated when VCC=R7 on the even field. The VSYNC pulse starts in the middle of the raster line, at HCC=R0/2. | ||
+ | |||
+ | <br> | ||
+ | |||
+ | == CRTC registers == | ||
The Internal registers of the 6845 are: | The Internal registers of the 6845 are: | ||
− | {| | + | {| class="wikitable" |
− | + | |- | |
+ | !Register Index | ||
+ | !Register Name | ||
+ | !Range | ||
+ | !CPC Setting | ||
+ | !Notes | ||
|- | |- | ||
− | |0||Horizontal Total||00000000||63||Width of the screen, in characters. Should always be 63 (64 characters). 1 character == 1μs. | + | |0||Horizontal Total (-1)||00000000||63||Width of the screen, in characters. Should always be 63 (64 characters). 1 character == 1μs. |
|- | |- | ||
|1||Horizontal Displayed||00000000||40||Number of characters displayed. Once horizontal character count (HCC) matches this value, DISPTMG is set to 1. | |1||Horizontal Displayed||00000000||40||Number of characters displayed. Once horizontal character count (HCC) matches this value, DISPTMG is set to 1. | ||
|- | |- | ||
− | |2||Horizontal Sync Position||00000000||46||When to start the HSync signal. | + | |2||Horizontal Sync Position ||00000000||46||When to start the HSync signal. |
|- | |- | ||
− | |3||Horizontal and Vertical Sync Widths||VVVVHHHH||128+14|| | + | |3||Horizontal and Vertical Sync Widths||VVVVHHHH||128+14||VSync width in scan-lines (Not present on all CRTCs, fixed to 16 lines on these) ; HSync pulse width in characters. |
|- | |- | ||
− | |4||Vertical Total||x0000000||38||Height of the screen, in characters. | + | |4||Vertical Total (-1)||x0000000||38||Height of the screen, in characters. |
|- | |- | ||
|5||Vertical Total Adjust||xxx00000||0||Measured in scanlines, can be used for smooth vertical scrolling on CPC. | |5||Vertical Total Adjust||xxx00000||0||Measured in scanlines, can be used for smooth vertical scrolling on CPC. | ||
Line 166: | Line 348: | ||
|6||Vertical Displayed||x0000000||25||Height of displayed screen in characters. Once vertical character count (VCC) matches this value, DISPTMG is set to 1. | |6||Vertical Displayed||x0000000||25||Height of displayed screen in characters. Once vertical character count (VCC) matches this value, DISPTMG is set to 1. | ||
|- | |- | ||
− | |7||Vertical Sync | + | |7||Vertical Sync Position||x0000000||30||When to start the VSync signal, in characters. |
|- | |- | ||
− | |8||Interlace and Skew|| | + | |8||Interlace and Skew||CCDDxxII||0||CC: Cursor Skew (Only in CRTCs 0, 3 and 4). DD: Display Skew (Only in CRTCs 0, 3 and 4). II: Interlace Mode. |
|- | |- | ||
− | |9||Maximum Raster Address||xxx00000||7||Maximum scan line address on CPC can hold between 0 and 7, higher values' upper bits are ignored | + | |9||Maximum Raster Address (aka Number of Scan Lines) (-1)||xxx00000||7||Maximum scan line address on CPC can hold between 0 and 7, higher values' upper bits are ignored |
|- | |- | ||
− | |10||Cursor Start Raster||xBP00000||0||Cursor not | + | |10||Cursor Start Raster||xBP00000||0||Cursor signal is not connected to the Gate Array but is provided to the expansion port. B = Blink On/Off; P = Blink Period Control (Slow/Fast). Sets first raster row of character that cursor is on to invert. |
|- | |- | ||
|11||Cursor End Raster||xxx00000||0||Sets last raster row of character that cursor is on to invert | |11||Cursor End Raster||xxx00000||0||Sets last raster row of character that cursor is on to invert | ||
|- | |- | ||
− | |12||Display Start Address (High)||xx000000||48 | + | |12||Display Start Address (High)||xx000000||48||On Amstrad Plus, bit7 of the printer port is controlled by bit3 of CRTC R12 (ie. bit11 of Display Start Address) |
|- | |- | ||
|13||Display Start Address (Low)||00000000||0||Allows you to offset the start of screen memory for hardware scrolling, and if using memory from address &0000 with the firmware. | |13||Display Start Address (Low)||00000000||0||Allows you to offset the start of screen memory for hardware scrolling, and if using memory from address &0000 with the firmware. | ||
Line 184: | Line 366: | ||
|15||Cursor Address (Low)||00000000||0 | |15||Cursor Address (Low)||00000000||0 | ||
|- | |- | ||
− | |16||Light Pen Address (High)||xx000000||||Read Only | + | |16||Light Pen Address (High)||xx000000||||Read Only. On CRTC1, bit6 of Status register goes to 0 when R16 is read |
|- | |- | ||
− | |17||Light Pen Address (Low)||00000000||||Read Only | + | |17||Light Pen Address (Low)||00000000||||Read Only. On CRTC1, bit6 of Status register goes to 0 when R17 is read |
|- | |- | ||
|} | |} | ||
− | + | On CRTCs 0/2, registers 18-31 read as 0. | |
− | registers 18- | + | |
− | + | On CRTC 1, registers 18-30 read as 0, register 31 reads as 0xff. | |
− | + | <br> | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | == CRTC register differences == | |
The following tables list the functions that can be accessed for each type: | The following tables list the functions that can be accessed for each type: | ||
Line 234: | Line 384: | ||
Type 0 | Type 0 | ||
− | {| | + | {| class="wikitable" |
− | + | !b1 | |
+ | !b0 | ||
+ | !Function | ||
+ | !Read/Write | ||
|- | |- | ||
|0||0||Select internal 6845 register||Write Only | |0||0||Select internal 6845 register||Write Only | ||
Line 243: | Line 396: | ||
|1||0||-||- | |1||0||-||- | ||
|- | |- | ||
− | |1||1||Read from selected internal 6845 register||Read | + | |1||1||Read from selected internal 6845 register||Read Only |
|- | |- | ||
|} | |} | ||
Line 249: | Line 402: | ||
Type 1 | Type 1 | ||
− | {| | + | {| class="wikitable" |
− | + | !b1 | |
+ | !b0 | ||
+ | !Function | ||
+ | !Read/Write | ||
|- | |- | ||
|0||0||Select internal 6845 register||Write Only | |0||0||Select internal 6845 register||Write Only | ||
Line 258: | Line 414: | ||
|1||0||Read Status Register||Read Only | |1||0||Read Status Register||Read Only | ||
|- | |- | ||
− | |1||1||Read from selected internal 6845 register||Read | + | |1||1||Read from selected internal 6845 register||Read Only |
|} | |} | ||
Type 2 | Type 2 | ||
− | {| | + | {| class="wikitable" |
− | + | !b1 | |
+ | !b0 | ||
+ | !Function | ||
+ | !Read/Write | ||
|- | |- | ||
|0||0||Select internal 6845 register||Write Only | |0||0||Select internal 6845 register||Write Only | ||
Line 272: | Line 431: | ||
|1||0||-||- | |1||0||-||- | ||
|- | |- | ||
− | |1||1||Read from selected internal 6845 register||Read | + | |1||1||Read from selected internal 6845 register||Read Only |
|- | |- | ||
|} | |} | ||
Line 278: | Line 437: | ||
Type 3 and 4 | Type 3 and 4 | ||
− | {| | + | {| class="wikitable" |
− | + | !b1 | |
+ | !b0 | ||
+ | !Function | ||
+ | !Read/Write | ||
|- | |- | ||
|0||0||Select internal 6845 register||Write Only | |0||0||Select internal 6845 register||Write Only | ||
Line 287: | Line 449: | ||
|1||0||Read from selected internal 6845 register||Read Only | |1||0||Read from selected internal 6845 register||Read Only | ||
|- | |- | ||
− | |1||1||Read from selected internal 6845 register||Read | + | |1||1||Read from selected internal 6845 register||Read Only |
|- | |- | ||
|} | |} | ||
Line 293: | Line 455: | ||
It is not possible to read from all the internal registers, this table shows the read/write status of each register for each type: | It is not possible to read from all the internal registers, this table shows the read/write status of each register for each type: | ||
− | {| | + | {| class="wikitable" |
− | + | !rowspan=2|Register Index | |
+ | !rowspan=2|Register Name | ||
+ | !colspan=3|Type | ||
|- | |- | ||
− | + | !0 | |
+ | !1 & 2 | ||
+ | !3 & 4 | ||
|- | |- | ||
− | |0||Horizontal Total|| | + | |0||Horizontal Total (-1)||colspan=3 style="text-align: center;"|Write Only |
|- | |- | ||
− | |1||Horizontal Displayed|| | + | |1||Horizontal Displayed||colspan=3 style="text-align: center;"|Write Only |
|- | |- | ||
− | |2||Horizontal Sync Position|| | + | |2||Horizontal Sync Position||colspan=3 style="text-align: center;"|Write Only |
|- | |- | ||
− | |3||Horizontal and Vertical Sync Widths|| | + | |3||Horizontal and Vertical Sync Widths||colspan=3 style="text-align: center;"|Write Only |
|- | |- | ||
− | |4||Vertical Total|| | + | |4||Vertical Total (-1)||colspan=3 style="text-align: center;"|Write Only |
|- | |- | ||
− | |5||Vertical Total Adjust|| | + | |5||Vertical Total Adjust||colspan=3 style="text-align: center;"|Write Only |
|- | |- | ||
− | |6||Vertical Displayed|| | + | |6||Vertical Displayed||colspan=3 style="text-align: center;"|Write Only |
|- | |- | ||
− | |7||Vertical Sync | + | |7||Vertical Sync Position||colspan=3 style="text-align: center;"|Write Only |
|- | |- | ||
− | |8||Interlace and Skew|| | + | |8||Interlace and Skew||colspan=3 style="text-align: center;"|Write Only |
|- | |- | ||
− | |9||Maximum Raster Address|| | + | |9||Maximum Raster Address (aka Number of Scan Lines) (-1)||colspan=3 style="text-align: center;"|Write Only |
|- | |- | ||
− | |10||Cursor Start Raster||Write Only||Write Only||Write | + | |10||Cursor Start Raster||Write Only||Write Only||Read/Write |
|- | |- | ||
− | |11||Cursor End Raster||Write Only||Write Only||Write | + | |11||Cursor End Raster||Write Only||Write Only||Read/Write |
|- | |- | ||
− | |12||Display Start Address (High)||Read/Write | + | |12||Display Start Address (High)||Read/Write||Write Only||Read/Write |
|- | |- | ||
− | |13||Display Start Address (Low)||Read/Write | + | |13||Display Start Address (Low)||Read/Write||Write Only||Read/Write |
|- | |- | ||
− | |14||Cursor Address (High)|| | + | |14||Cursor Address (High)||colspan=3 style="text-align: center;"|Read/Write |
|- | |- | ||
− | |15||Cursor Address (Low)|| | + | |15||Cursor Address (Low)||colspan=3 style="text-align: center;"|Read/Write |
|- | |- | ||
− | |16||Light Pen Address (High)|| | + | |16||Light Pen Address (High)||colspan=3 style="text-align: center;"|Read Only |
|- | |- | ||
− | |17||Light Pen Address (Low)|| | + | |17||Light Pen Address (Low)||colspan=3 style="text-align: center;"|Read Only |
|- | |- | ||
|} | |} | ||
Line 338: | Line 504: | ||
'''Notes''' | '''Notes''' | ||
− | + | * On CRTCs 0/1/2, if a Write Only register is read from, "0" is returned. The register accessing scheme on CRTCs 3/4 makes it impossible to happen. | |
− | + | * CRTC types 3 and 4 are identical in every way, except for the unlocking mechanism, split screen, hardware soft scroll and 8-bit printer port functionalities specific to the ASIC. | |
− | + | * See the document "Extra CPC Plus Hardware Information" for more details. | |
− | + | <br> | |
− | + | === Reading from CRTC registers on ASIC/Pre-ASIC === | |
− | + | On CRTCs 3/4, only the 3 least significant bits of the selected register number are considered to read a register according to the following table: | |
− | + | ||
− | + | {| class="wikitable" | |
+ | !Nb | ||
+ | !Register | ||
+ | !Definition | ||
+ | |- | ||
+ | |0||R16||Light Pen Address (High) | ||
+ | |- | ||
+ | |1||R17||Light Pen Address (Low) | ||
+ | |- | ||
+ | |2||R10||Cursor Start Raster | ||
+ | |- | ||
+ | |3||R11||Cursor End Raster | ||
+ | |- | ||
+ | |4||R12||Display Start Address (High) | ||
+ | |- | ||
+ | |5||R13||Display Start Address (Low) | ||
+ | |- | ||
+ | |6||R14||Cursor Address (High) | ||
+ | |- | ||
+ | |7||R15||Cursor Address (Low) | ||
+ | |} | ||
− | + | Therefore, as an example, reading register 4 will give the same result as reading register 12 or 20. | |
− | + | ||
− | + | <br> | |
− | + | === R10/R11 on ASIC/Pre-ASIC === | |
− | + | ||
− | + | The cursor raster registers R10/R11 act as status registers when read on CRTCs 3/4. They behave as normal cursor raster registers upon write. | |
− | + | {| class="wikitable" | |
− | + | ! R10 - Bit number | |
+ | ! Bit value | ||
+ | ! Event | ||
+ | |- | ||
+ | |0 | ||
+ | |1 | ||
+ | |C0=R0 | ||
+ | |- | ||
+ | |1 | ||
+ | |0 | ||
+ | |C0=R0/2 | ||
+ | |- | ||
+ | |2 | ||
+ | |0 | ||
+ | |C0=R1-1 (if R0>=R1) | ||
+ | |- | ||
+ | |3 | ||
+ | |0 | ||
+ | |C0=R2 | ||
+ | |- | ||
+ | |4 | ||
+ | |0 | ||
+ | |C0=R2+R3 | ||
+ | |- | ||
+ | |5 | ||
+ | |0 | ||
+ | 1 | ||
+ | |R3h>0 : C0=0..R0 on the line R3h from Vsync (C4=R7) | ||
+ | R3h=0 : C0=0..R0 over 15 lines from Vsync (C4=R7) | ||
+ | |- | ||
+ | |6 | ||
+ | |1 | ||
+ | |Always 1 | ||
+ | |- | ||
+ | |7 | ||
+ | |0 | ||
+ | 0 | ||
+ | |C0=0..R0-1 : VMA.Lsb=0xFF | ||
+ | C0=R0 : VMA'.Lsb=0x00 (same cond if C0=R0=0) | ||
+ | |} | ||
− | == | + | {| class="wikitable" |
+ | ! R11 - Bit number | ||
+ | ! Bit value | ||
+ | ! Event | ||
+ | |- | ||
+ | |0 | ||
+ | |0 | ||
+ | |C4=R4 and C9=R9 and C0=R0 : Last char of screen | ||
+ | |- | ||
+ | |1 | ||
+ | |0 | ||
+ | |C4=R6-1 and C9=R9 and C0=R0 : Last char displayed | ||
+ | |- | ||
+ | |2 | ||
+ | |0 | ||
+ | |C4=R7-1 and C9=R9 and C0=R0 : Last char before Vsync | ||
+ | |- | ||
+ | |3 | ||
+ | |0/1 | ||
+ | |Timer 16 CRTC frames | ||
+ | |- | ||
+ | |4 | ||
+ | |1 | ||
+ | |Always 1 | ||
+ | |- | ||
+ | |5 | ||
+ | |0 | ||
+ | |C9=R9 : C0=0 to R0 | ||
+ | |- | ||
+ | |6 | ||
+ | |0 | ||
+ | |Always 0 | ||
+ | |- | ||
+ | |7 | ||
+ | |1 | ||
+ | |(C9=R9 and C0=R0) or (C9=0 and C0=0 to R0-1) | ||
+ | |} | ||
− | + | <br> | |
− | + | === 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. | ||
− | + | Type 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. | ||
− | + | 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 this gives a HSYNC width of 16. | ||
− | + | Types 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. | ||
− | + | ==== R3 fine horizontal hardware scroll ==== | |
− | + | If R3l is set to 5 instead of 6 or more, then the frame is shifted to the right on the CTM monitor with an offset of half a CRTC character. This is due to the effect of shortening the C-HSYNC produced by the [[Gate Array]]. | |
− | + | Even further, continuously switching these values between each raster line, instead of once per frame, will divide by 2 the difference between the 2 positions and so will give an offset of a quarter of a CRTC character. | |
− | == UM6845R | + | And smartly combining R2 and R3 horizontal screen wobbling effects at every raster line will give 1-pixel mode1 horizontal hardware scroll. |
+ | |||
+ | As these effects rely on invalid video signals, they are badly supported on modern displays. | ||
+ | |||
+ | <br> | ||
+ | |||
+ | === Interlace and Skew (R8) === | ||
+ | |||
+ | Types 0/3/4: | ||
+ | *Bits 7..6 define the skew (delay) of the CUDISP signal (00 = Non-skew ; 01 = One-character skew ; 10 = Two-character skew ; 11 = Non-output). | ||
+ | *Bits 5..4 define the skew (delay) of the 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 the interlace mode (00 = No Interlace; 01 = Interlace Sync; 10 = No Interlace; 11 = Interlace Sync and Video). | ||
+ | |||
+ | Types 1/2: | ||
+ | *Bits 7..2 are ignored. | ||
+ | *Bits 1..0 define the interlace mode. | ||
+ | |||
+ | [[File:CRTC Interlace modes.png]] | ||
+ | |||
+ | For a CRTC character line with n raster lines, R9 must be set to n-1 on all CRTCs, regardless of the interlace settings. The exception is for CRTCs 0/3/4 in IVM mode, where R9 must be set to n-2. | ||
+ | |||
+ | ==== Interlace sync mode (ISM) ==== | ||
+ | |||
+ | In this mode, the same information is painted in both fields to enhance readability. Reprogramming the CRTC is not necessary. | ||
+ | |||
+ | ==== Interlace sync and video mode (IVM) ==== | ||
+ | |||
+ | In this mode, alternating lines are displayed in the even and odd field to double the resolution. | ||
+ | |||
+ | On the even field, the CRTC displays the lines for which VLC is even. On the odd field, the CRTC displays the lines for which VLC is odd. | ||
+ | |||
+ | It is necessary to reprogram the CRTC as if we were building a frame of 624 lines. | ||
+ | |||
+ | CRTC 2 is the exception: R4, R5, R6, R7 do not need to be reprogrammed as it considers each character line to be a double character line. | ||
+ | |||
+ | ==== Interlace adjustment line ==== | ||
+ | |||
+ | On all CRTCs, in both interlace modes, an additional line (the 625th line) is added automatically by the CRTC at the end of the even field. This line is added after the lines of the vertical adjustment mode. | ||
+ | |||
+ | <br> | ||
+ | |||
+ | === Vertical Displayed (R6) === | ||
+ | |||
+ | On CRTCs 0/1/2, the condition VCC=R6 is considered immediately to activate the VBORDER. The only exception is for CRTC 1 with a value of 0, which triggers an immediate BORDER without the condition VCC=R6 being required. | ||
+ | |||
+ | On CRTCs 3/4, the condition VCC=R6 is tested only at new character line start. The update of R6 during the character line is therefore not considered. | ||
+ | |||
+ | <br> | ||
+ | |||
+ | === 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. | ||
+ | |||
+ | R31 doesn't exist on CRTCs 0/2/3/4. | ||
+ | |||
+ | <br> | ||
+ | |||
+ | === Status register on Type 1 === | ||
The UM6845R has a status register that can be read using port &BExx. | The UM6845R has a status register that can be read using port &BExx. | ||
Line 399: | Line 727: | ||
All the other bits read as 0 and don't have any function. | All the other bits read as 0 and don't have any function. | ||
− | == CRTC Timing | + | <br> |
+ | |||
+ | == CRTC Type Detection == | ||
+ | <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> | ||
+ | <br> | ||
+ | |||
+ | == CRTC Timing Diagrams == | ||
+ | [[File:CRTC Timing Diagram Rockwell.png]] | ||
+ | |||
+ | <br> | ||
+ | |||
[[File:CRTC timing small.gif]] | [[File:CRTC timing small.gif]] | ||
+ | |||
+ | <br> | ||
+ | |||
+ | == Internal Counters == | ||
+ | |||
+ | {| class="wikitable" | ||
+ | ! Counter name | ||
+ | ! Abbr | ||
+ | ! Alternate name | ||
+ | ! Comment | ||
+ | |- | ||
+ | |Horizontal Character Counter | ||
+ | |HCC | ||
+ | |C0 | ||
+ | | | ||
+ | |- | ||
+ | |Horizontal Sync Counter | ||
+ | |HSC | ||
+ | |C3l | ||
+ | | | ||
+ | |- | ||
+ | |Vertical Character Counter | ||
+ | |VCC | ||
+ | |C4 | ||
+ | | | ||
+ | |- | ||
+ | |Vertical Sync Counter | ||
+ | |VSC | ||
+ | |C3h | ||
+ | |- | ||
+ | |Vertical Line Counter | ||
+ | |VLC | ||
+ | |C9 | ||
+ | |If not in IVM mode, this counter is exposed on CRTC pins RA0..RA4 | ||
+ | |- | ||
+ | |Vertical Total Adjust Counter | ||
+ | |VTAC | ||
+ | |C5 | ||
+ | |This counter does not exist on CRTCs 0/3/4. C9 is reused instead | ||
+ | |- | ||
+ | |Frame Counter | ||
+ | |FC | ||
+ | | | ||
+ | |Used to alternate frames in interlace and for CRTC cursor blinking | ||
+ | |- | ||
+ | |Memory Address | ||
+ | |MA | ||
+ | | | ||
+ | |This counter is exposed on CRTC pins MA0..MA13 | ||
+ | |} | ||
+ | |||
+ | No matter its type, the CRTC never buffers any of its counters, except for the video pointer MA. The buffer MA' is needed because MA has to be reloaded at the beginning of every raster line. | ||
+ | |||
+ | <br> | ||
+ | |||
+ | == CRTC counter differences == | ||
+ | |||
+ | === MA reload === | ||
+ | |||
+ | On CRTCs 0/3/4, at the beginning of the first raster line of the frame, MA and MA' are loaded with R12/R13. Otherwise, MA is loaded with MA'. | ||
+ | |||
+ | On CRTC 2, at the beginning of every raster line of the frame (including the first one), MA is loaded with MA'. | ||
+ | |||
+ | On CRTC 1, at the beginning of every raster line of the first character line of the frame (ie. when VCC=0), MA is loaded with R12/R13 instead of MA'. '''This is a major source of incompatibility if the programmer does not take care.''' In demos and games, to be compatible with all CRTCs, program R12/R13 only when VCC != 0. This will then take effect at the next frame start. | ||
+ | |||
+ | <br> | ||
+ | |||
+ | === MA buffering === | ||
+ | |||
+ | At the end of the display of the last raster line of each character line (ie. when HCC=R1 and VLC=R9), MA' captures the current value of MA. | ||
+ | |||
+ | CRTC 2 is the exception: at the end of the display of the last raster line of the frame, MA' captures R12/R13 instead of MA. | ||
+ | |||
+ | <br> | ||
+ | |||
+ | === VSC (C3h) overflow === | ||
+ | |||
+ | During a VSYNC on CRTCs 0/3/4, if VSYNC Width (R3h) is changed with a value less than the current VSC, then VSC overflows and will count up to its maximum value (15) before looping back and counting up again until it reaches the new value of R3h. | ||
+ | |||
+ | On CRTCs 1/2, the VSYNC width is fixed to 16 characters. It is not possible to modify it. Therefore, VSC cannot be overflowed. | ||
+ | |||
+ | <br> | ||
+ | |||
+ | === HSC (C3l) overflow === | ||
+ | |||
+ | During an HSYNC, if HSYNC Width (R3l) is changed with a value less than the current HSC, then HSC overflows and will count up to its maximum value (15) before looping back and counting up again until it reaches the new value of R3l. | ||
+ | |||
+ | The only exception is for CRTC 1 with a value of 0, which immediately cancels the current HSYNC. | ||
+ | |||
+ | <br> | ||
+ | |||
+ | === VCC (C4) overflow === | ||
+ | |||
+ | On all CRTCs, if Vertical Total (R4) is changed with a value less than VCC, then: | ||
+ | * if this update was done when VCC < R4, then VCC overflows and will count up to its maximum value (127) before looping back and counting up again until it reaches the new value of R4 | ||
+ | * if this update was done when VCC = R4, the current character line was already decided to be the last one of the current frame. No update to R4 will make the CRTC change its mind for the current frame | ||
+ | |||
+ | The only exception when VCC = R4 is for CRTC 1 with a value of 0, which will cause VCC to overflow. | ||
+ | |||
+ | <br> | ||
+ | |||
+ | === HCC (C0) overflow === | ||
+ | |||
+ | If Horizontal Total (R0) is changed with a value less than the current HCC, then: | ||
+ | * on CRTCs 0/1/2, HCC overflows and will count up to its maximum value (255) before looping back and counting up again until it reaches the new value of R0 | ||
+ | * on CRTCs 3/4, the current line is considered finished and HCC is immediately reset to 0 on the next line | ||
+ | |||
+ | <br> | ||
+ | |||
+ | === VLC (C9) overflow === | ||
+ | |||
+ | If Number of Scan Lines (R9) is changed with a value less than the current VLC, then: | ||
+ | * on CRTCs 0/1/2, VLC overflows and will count up to its maximum value (31) before looping back and counting up again until it reaches the new value of R9 | ||
+ | * on CRTCs 3/4, the current line is considered the last one of this CRTC character and VLC will reset to 0 on the next line | ||
+ | |||
+ | As an exception, on CRTCs 0/2, if VLC is modified during the last frame line, then the updated value will not be considered for the current frame. | ||
+ | |||
+ | <br> | ||
+ | |||
+ | === VTAC (C5/C9) overflow === | ||
+ | |||
+ | During vertical adjustment mode, if Vertical Total Adjust (R5) is changed with a value less than the current VTAC, then: | ||
+ | * on CRTCs 0/1/2, VTAC overflows and will count up to its maximum value (31) before looping back and counting up again until it reaches the new value of R5 | ||
+ | * on CRTCs 3/4, the current line is considered the last one of the current frame and vertical adjustment will end | ||
+ | |||
+ | As an exception, on CRTCs 0/2, if VTAC is modified during the last frame line, then the updated value will not be considered for the current frame. | ||
+ | |||
+ | <br> | ||
+ | |||
+ | === Vertical Adjustment mode === | ||
+ | |||
+ | On CRTCs 3/4, this mode does not increment VCC, so VCC remains equal to R4. | ||
+ | |||
+ | On CRTC 0, this mode increments VCC, causing it to exceed R4, but this increment occurs only once. | ||
+ | |||
+ | On CRTCs 1/2, this mode increments VCC, causing it to exceed R4, and this increment can happen multiple times depending on the values of R5 and R9. | ||
+ | |||
+ | Also, only CRTCs 1/2 have a dedicated C5 counter. On CRTCs 0/3/4, during Vertical Adjustment, C9 has to fullfil the VTAC role which means that it cannot fullfil its VLC role. This impacts address generation as R9 is not considered anymore. | ||
+ | |||
+ | <br> | ||
+ | |||
+ | === RA in IVM interlace mode === | ||
+ | |||
+ | When IVM mode is activated, VLC continues to increment normally. However, RA is not identical to VLC anymore. Instead, VLC is considered shifted left by 1 bit, and bit0 represents the parity of the field (even/odd). | ||
+ | |||
+ | <br> | ||
+ | |||
+ | == Block Diagrams == | ||
+ | |||
+ | === Hitachi === | ||
+ | |||
+ | [[File:CRTC Block Diagram.png]] | ||
+ | |||
+ | <br> | ||
+ | |||
+ | === UMC === | ||
+ | [[File:UMC CRTC Block Diagram.png]] | ||
+ | |||
+ | <br> | ||
+ | |||
+ | === Motorola === | ||
+ | [[File:Motorola CRTC Block Diagram.png]] | ||
+ | |||
+ | <br> | ||
+ | |||
+ | == CRTC-II (aka Type 5) == | ||
+ | |||
+ | According to the datasheet, the HD6345 is upward-compatible with the HD6845S in pin and software. And it brings these new features: | ||
+ | *Screen Partition (horizontally split into 4 screens) with paging and scrolling for each screen | ||
+ | *Smooth Scrolling in the vertical direction | ||
+ | *External Synchronization in Master-Slave or TV Syne modes | ||
+ | *Interrupt request by vertical blanking or light pen strobe detection | ||
+ | *Double-size vertical display by Raster Interpolation | ||
+ | *Sync Position Adjustment | ||
+ | *Light Pen Raster Address | ||
+ | *Second Hardware Cursor | ||
+ | *Display Memory Width Setting | ||
+ | *Up to 256 character rows per field | ||
+ | *Programmable Timing Signal for dual-port RAM in MPRAM mode | ||
+ | *Three-state Control of MA/RA Output | ||
+ | |||
+ | This chip was never used by Amstrad. However, some CPC enthusiasts have replaced the original CRTC chip in their CPC with this one. [https://www.youtube.com/watch?v=bCTf3DWFVc4 Split-screen functionality demoed 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 == | == Datasheets == | ||
− | * [[Media:hd6845.hitachi.pdf|HD6845S (Hitachi) | + | ==== Used by Amstrad ==== |
− | * [[Media: | + | * [[Media:hd6845.hitachi.pdf|HD6845S (Hitachi)]] aka Type 0 |
− | * [[Media:Um6845r.umc.pdf|UM6845R (UMC) | + | * [[Media:UM6845-UMC.pdf|UM6845 (UMC)]] aka Type 0 |
− | * [[Media:Mc6845.motorola.pdf|MC6845 (Motorola) | + | * [[Media:Um6845r.umc.pdf|UM6845R (UMC)]] aka Type 1 |
+ | * [[Media:Mc6845.motorola.pdf|MC6845 (Motorola)]] aka Type 2 [[Media:Mc6845.pdf|Other datasheet version]] | ||
+ | * [[Media:CPC_Plus_Asic_Schematic.GIF|AMS40489 (Amstrad)]] aka Type 3 ([[ASIC]]) | ||
+ | * [[AMS40226 (Amstrad)]] aka Type 4 (Pre-ASIC) | ||
− | * [[ | + | ==== DIY upgrade ==== |
+ | *[[Media:CRTC-5-HD6345.pdf|HD6345 (Hitachi)]] aka Type 5 - Upgraded pin-compatible CRTC chip with advanced functionalities [https://thecheshirec.at/2024/05/07/un-crtc6345-sur-amstrad-cpc/ Upgrading the CPC to HD6345] | ||
− | == | + | ==== Unused clones ==== |
− | * [CM607P | + | * [[CM607P]] a Bulgarian clone made in Pravetz factory (maybe used on [[KC Compact]] and [[Aleste 520EX]]) |
− | * [EF6845P | + | * [[Media:EF6845P.pdf|EF6845]] by Thomson Semiconductors |
+ | * [[Media:UM6845E-UMC.pdf|UM6845E]] by UMC | ||
+ | * [[Media:F6845.pdf|F6845]] by Fairchild | ||
+ | * [[Media:Mos 6545-1 crtc.pdf|CRTC 6545]] (MOS, Rockwell, Synertek) is pin-compatible with the 6845 and only has minor differences | ||
+ | * [https://github.com/hoglet67/BeebFpga/blob/dev/src/common/mc6845.vhd BeebFpga] [https://github.com/MiSTer-devel/Amstrad_MiSTer/blob/master/rtl/UM6845R.v MiSTer] [https://opencores.org/websvn/filedetails?repname=System09&path=%2FSystem09%2Ftrunk%2Frtl%2FVHDL%2Fcrtc6845.vhd OpenCores] Verilog/VHDL implementations of the 6845 | ||
+ | |||
+ | <br> | ||
== Tools about CRTC == | == Tools about CRTC == | ||
* [http://www.cpcwiki.eu/imgs/9/99/Elmar_Krieger-SPECIAL_EFFECTS.dsk some BASIC tools to detect CRTC types 0-1-2 and show some effects] by [[Elmar Krieger]] (DSK for Emulators) | * [http://www.cpcwiki.eu/imgs/9/99/Elmar_Krieger-SPECIAL_EFFECTS.dsk some BASIC tools to detect CRTC types 0-1-2 and show some effects] by [[Elmar Krieger]] (DSK for Emulators) | ||
− | * [[File: | + | * [[File:Shaker26.dsk]] Shaker - Suite of CRTC tests associated with the CPC CRTC compendium (many of them will not work correctly on emulators and that was the purpose of the tests, to help create more compatible emulation) |
* [[File:Shaker addon.dsk]] Shaker Add-On (Pixel 1 Hard Scroll / Vertical Rupture all Crtc) | * [[File:Shaker addon.dsk]] Shaker Add-On (Pixel 1 Hard Scroll / Vertical Rupture all Crtc) | ||
+ | |||
+ | <br> | ||
== Links == | == Links == | ||
Line 426: | Line 968: | ||
* [http://www.grimware.org/doku.php/documentations/devices/crtc CRTC documentation from Grimware] | * [http://www.grimware.org/doku.php/documentations/devices/crtc CRTC documentation from Grimware] | ||
* [http://quasar.cpcscene.net/doku.php?id=assem:crtc Quasar CRTC documentation (in french)] | * [http://quasar.cpcscene.net/doku.php?id=assem:crtc Quasar CRTC documentation (in french)] | ||
− | * [https:// | + | * [https://pulkomandy.github.io/shinra.github.io/crtc.html Differences between CRTC types] |
+ | * [[Media:Dossier Rupture(Gozeur Paradox).pdf]] | ||
* [[Media:Dossier CRTC(Ramlaid Mortel).pdf]] Les entrailles du CRTC | * [[Media:Dossier CRTC(Ramlaid Mortel).pdf]] Les entrailles du CRTC | ||
* [https://thecheshirec.at/tag/crtc6845/ Leçons CRTC (CheshireCat)] | * [https://thecheshirec.at/tag/crtc6845/ Leçons CRTC (CheshireCat)] | ||
− | * [[Media:ACCC1. | + | * [[Media:ACCC1.8-EN.pdf]] [[Media:ACCC1.8-FR.pdf]] CPC CRTC Compendium - Latest (04/2024!) document containing in-depth info about CRTC programming on CPC. |
+ | * [[Media:CRTC Compendium Podcast.mp3]] The CRTC Compendium digested in podcast format | ||
+ | |||
+ | <br> | ||
==Related pages== | ==Related pages== | ||
Line 441: | Line 987: | ||
*[[Synchronising with the CRTC and display]] : technic and details on the relationship between Gate Array and CRTC. | *[[Synchronising with the CRTC and display]] : technic and details on the relationship between Gate Array and CRTC. | ||
− | [[Category:Hardware]] [[Category:CPC Internal Components]] [[Category:Programming]] [[Category:Datasheet]] [[Category:Graphic]] | + | [[Category:Hardware]] [[Category:CPC Internal Components]] [[Category:Electronic Component]] [[Category:Programming]] [[Category:Datasheet]] [[Category:Graphic]] |
Latest revision as of 13:03, 26 October 2024
The 6845 CRTC (Cathode Ray Tube Controller) chip was created by Motorola in 1977. It works with the Gate Array to generate the video signal on the Amstrad CPC. This chip is also used in the BBC Micro, Sharp X1, MicroBee, Commodore PET and the CGA graphics card for IBM PC.
NOTES:
- This document describes the functionality in terms of the CPC with its separate CRTC and Gate-Array. The Plus has both integrated into the same IC, but could be considered to have two functional blocks, one for CRTC and one for Gate-Array. In this document the term 'Gate-Array' is used, but this also applies to the ASIC.
- Much information has been drawn from the CRTC Compendium documentation and condensed for clarity. For details, timing diagrams, code examples, coding tips, and more, refer to that documentation.
Overview
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 chip really is just a bunch of counters and equality operators. But the devil is in the details, and that's what we will discuss in this article.
The CRTC was a common part available from many different manufacturers. During the life of the CPC, Amstrad sourced the CRTC from various manufacturers.
All ICs used were based on the same design but have a different implementation. As a result they do not operate identically in all situations. This document highlights these differences.
This table lists the known ICs used, with their part number, manufacturer and type number.
Part number | Manufacturer | Type number (note 3) |
---|---|---|
HD6845S | Hitachi | 0 |
UM6845 | UMC | 0 |
UM6845R | UMC | 1 |
MC6845 | Motorola | 2 |
AMS40489 | Amstrad | 3 (note 1) |
40226 | Amstrad | 4 (note 2) |
NOTES
1. The CRTC functionality is integrated into the CPC+ ASIC. This type exists only in the CPC464+,CPC6128+ and GX4000.
2. This type exists in "cost-down" CPC464 and CPC6128 systems. In the "cost-down" the CRTC functionality is integrated into a single ASIC IC. This ASIC is often refered to as the "Pre-ASIC" because it preceeded the CPC+ ASIC. The CRTC functionality of the Pre-ASIC is almost identical to the CRTC within the ASIC.
3. In the Amstrad community each 6845 implementation has been assigned a type number. This type identifies a group of implementations which operate in exactly the same way.
As far as I know, the type number system was originally used by demo programmers.
It is possible to detect the 6845 present 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.
4. As far as I know, the KC compact used HD6845R only.
Z80 I/O access timings
Instructions | Duration | I/O CRTCs 0/1/2 | I/O CRTCs 3/4 |
---|---|---|---|
OUT (C),r8 | 4 µsec | 3rd µsec | 4th µsec |
OUT (C),0 | 4 µsec | 3rd µsec | 4th µsec |
OUT (n),A | 3 µsec | 3rd µsec | 3rd µsec |
OUTI | 5 µsec | 5th µsec | 5th µsec |
OUTD | 5 µsec | 5th µsec | 5th µsec |
IN r8,(C) | 4 µsec | 4th µsec | 4th µsec |
INI | 5 µsec | 4th µsec | 4th µsec |
IND | 5 µsec | 4th µsec | 4th µsec |
IN A,(n) | 3 µsec | 3rd µsec | 3rd µsec |
Programming
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
I/O port address | Function | Read/Write |
---|---|---|
&BCxx | Select 6845 register | Write only |
&BDxx | Write 6845 register data | Write only |
&BExx | (note 1) | Read only |
&BFxx | (note 1) | Read only |
NOTES
1. The function of these I/O ports is dependant on the CRTC type
2. The CRTC is not connected to the CPU's RD and WR pins, so the CRTC is not aware of the CPU bus I/O direction. Therefore, if you perform an IN instruction to the select or write functions, it will write data to the CRTC from the current data on the bus.
Video Memory Address (VMA)
The VMA of the Gate Array is constructed from the CRTC MA and RA signals:
Video Memory Address | Signal source | Signal name |
---|---|---|
A15 | 6845 | MA13 |
A14 | 6845 | MA12 |
A13 | 6845 | RA2 |
A12 | 6845 | RA1 |
A11 | 6845 | RA0 |
A10 | 6845 | MA9 |
A9 | 6845 | MA8 |
A8 | 6845 | MA7 |
A7 | 6845 | MA6 |
A6 | 6845 | MA5 |
A5 | 6845 | MA4 |
A4 | 6845 | MA3 |
A3 | 6845 | MA2 |
A2 | 6845 | MA1 |
A1 | 6845 | MA0 |
A0 | Gate-Array | CCLK |
CRTC generates the address, Gate Array reads the data and converts it to pixels based on its current graphics mode and palette.
CRTC pins RA3, RA4, MA10, MA11 are not connected on CPC.
Overscan bits
It's possible to use 32KB screen size (used for overscan) by setting bits 11 and 10 of Register 12 both to 1. 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.
.------- 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 | '-------------------------------> Video Page
.--.--.---------------. .--.--.--------------. |13|12| Video Page | |11|10| Video Buffer | |--|--|---------------| |--|--|--------------| | 0| 0| 0000 - 3FFF | | 0| 0| 16KB | |--|--|---------------| |--|--|--------------| | 0| 1| 4000 - 7FFF | | 0| 1| 16KB | |--|--|---------------| |--|--|--------------| | 1| 0| 8000 - BFFF | | 1| 0| 16KB | |--|--|---------------| |--|--|--------------| | 1| 1| C000 - FFFF | | 1| 1| 32KB | '--'--'---------------' '--'--'--------------'
Split screen
Some rules of thumb 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, 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 (##) = 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; 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.
CUDISP (aka CURSOR)
CUDISP (Cursor Display) signal defines the hardware cursor.
CRTC pin CUDISP is not connected to the Gate Array, so it has no effect on a barebone CPC or Plus machine.
However, this signal is provided to the expansion port. And it is used by the PlayCity and Play2CPC expansions.
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), IBORDER (Immediate) 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.
On CRTC 2, when HSYNC is active, the condition HCC=0 does not disable HBORDER, unlike the other CRTCs.
Immediate border
DISPTMG can be immediately 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.
Border bytes
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.
If border skew is used then the border byte will skew and change into a full character-width border instead.
Border conflict
If R1=0 and HCC=0, we expect HBORDER to activate as HCC=R1 and we also expect HBORDER to deactivate as HCC=0. In this situation, all CRTCs activate HBORDER.
If R6=0 and VCC=0, we expect VBORDER to activate as VCC=R6 and we also expect VBORDER to deactivate as VCC=0. In this situation, all CRTCs activate VBORDER. On CRTC 1, even IBORDER is activated. But on CRTCs 0/2, the first raster line shows an alternation of bytes of VBORDER and displayable characters.
Border byte precision
This behaviour exhibited by CRTCs 0/2 shows that, despite their 1MHz clock speed, they can change state at a rate equivalent to 2MHz chips by responding to both the rising and falling edges of each clock cycle.
To see the border bytes with your own eyes, type this BASIC line after reset:
BORDER 6:OUT &BC00,6:OUT &BD00,0
HSYNC and VSYNC
The HSYNC and VSYNC signals from the CRTC are not directly connected to the display. They are passed to the Gate Array for further modification. See its wiki page.
On all CRTCs, while a VSYNC is ongoing, the condition VCC=R7 is ignored. So we cannot trigger a new VSYNC during a VSYNC. Similarly, we cannot trigger a new HSYNC during an HSYNC.
HSYNC
The HSYNC width value is interpreted differently between CRTCs. On CRTCs 0/1, if 0 is programmed then no HSYNC is generated (and therefore, no interrupts). On CRTCs 2/3/4, if 0 is programmed then this gives an HSYNC width of 16.
Signal delay
On all CRTCs, there is a 1µs delay in display between when the CRTC provides a video pointer, and when the Gate Array displays the corresponding 16-bit character.
But on CRTCs 0/1/2, there is no delay for HSYNC. On CRTCs 3/4, the Amstrad engineers fixed the issue by adding a 1µs delay for the HSYNC signal.
So now we have a bigger issue: on CRTCs 3/4, HSYNC occurs 1µs later than on CRTCs 0/1/2. Interrupts being dependent on HSYNC, this is a serious compatibility issue for time-sensitive code. It also explains why the CTM monitor has to be calibrated differently on CRTCs 3/4.
Discolouration effect
On CRT monitors from other brands, a colour calibration can happen just after the C-HSYNC pulse.
So even when a fully valid C-HSYNC pulse of 4µs is emitted, an HSYNC shorter than usual combined with a coloured border can induce a discolouration effect on those monitors.
VSYNC
Bit0 of port B of the PPI is directly connected to the VSYNC pin of the CRTC.
CRTCs 1/2 have a fixed VSYNC width value of 16. VSYNC width can be configured with R3 on CRTCs 0/3/4. If 0 is programmed this gives 16 lines of VSYNC.
On CRTCs 0/1/2, the sole condition to trigger a VSYNC is that VCC=R7. While on CRTCs 3/4, it is necessary to have VCC=R7 and HCC=0 and VLC=0 to trigger a VSYNC.
Ghost VSYNC
On CRTC 2, if a VSYNC is triggered during an HSYNC, the CRTC produces a ghost VSYNC. The CRTC then counts the lines as if a VSYNC were taking place by preventing a new VSYNC from occurring, but without the VSYNC pin being enabled.
Mid-VSYNC
On all CRTCs, in both interlace modes, a mid-VSYNC is generated when VCC=R7 on the even field. The VSYNC pulse starts in the middle of the raster line, at HCC=R0/2.
CRTC registers
The Internal registers of the 6845 are:
Register Index | Register Name | Range | CPC Setting | Notes |
---|---|---|---|---|
0 | Horizontal Total (-1) | 00000000 | 63 | Width of the screen, in characters. Should always be 63 (64 characters). 1 character == 1μs. |
1 | Horizontal Displayed | 00000000 | 40 | Number of characters displayed. Once horizontal character count (HCC) matches this value, DISPTMG is set to 1. |
2 | Horizontal Sync Position | 00000000 | 46 | When to start the HSync signal. |
3 | Horizontal and Vertical Sync Widths | VVVVHHHH | 128+14 | VSync width in scan-lines (Not present on all CRTCs, fixed to 16 lines on these) ; HSync pulse width in characters. |
4 | Vertical Total (-1) | x0000000 | 38 | Height of the screen, in characters. |
5 | Vertical Total Adjust | xxx00000 | 0 | Measured in scanlines, can be used for smooth vertical scrolling on CPC. |
6 | Vertical Displayed | x0000000 | 25 | Height of displayed screen in characters. Once vertical character count (VCC) matches this value, DISPTMG is set to 1. |
7 | Vertical Sync Position | x0000000 | 30 | When to start the VSync signal, in characters. |
8 | Interlace and Skew | CCDDxxII | 0 | CC: Cursor Skew (Only in CRTCs 0, 3 and 4). DD: Display Skew (Only in CRTCs 0, 3 and 4). II: Interlace Mode. |
9 | Maximum Raster Address (aka Number of Scan Lines) (-1) | xxx00000 | 7 | Maximum scan line address on CPC can hold between 0 and 7, higher values' upper bits are ignored |
10 | Cursor Start Raster | xBP00000 | 0 | Cursor signal is not connected to the Gate Array but is provided to the expansion port. B = Blink On/Off; P = Blink Period Control (Slow/Fast). Sets first raster row of character that cursor is on to invert. |
11 | Cursor End Raster | xxx00000 | 0 | Sets last raster row of character that cursor is on to invert |
12 | Display Start Address (High) | xx000000 | 48 | On Amstrad Plus, bit7 of the printer port is controlled by bit3 of CRTC R12 (ie. bit11 of Display Start Address) |
13 | Display Start Address (Low) | 00000000 | 0 | Allows you to offset the start of screen memory for hardware scrolling, and if using memory from address &0000 with the firmware. |
14 | Cursor Address (High) | xx000000 | 0 | |
15 | Cursor Address (Low) | 00000000 | 0 | |
16 | Light Pen Address (High) | xx000000 | Read Only. On CRTC1, bit6 of Status register goes to 0 when R16 is read | |
17 | Light Pen Address (Low) | 00000000 | Read Only. On CRTC1, bit6 of Status register goes to 0 when R17 is read |
On CRTCs 0/2, registers 18-31 read as 0.
On CRTC 1, registers 18-30 read as 0, register 31 reads as 0xff.
CRTC register differences
The following tables list the functions that can be accessed for each type:
Type 0
b1 | b0 | Function | Read/Write |
---|---|---|---|
0 | 0 | Select internal 6845 register | Write Only |
0 | 1 | Write to selected internal 6845 register | Write Only |
1 | 0 | - | - |
1 | 1 | Read from selected internal 6845 register | Read Only |
Type 1
b1 | b0 | Function | Read/Write |
---|---|---|---|
0 | 0 | Select internal 6845 register | Write Only |
0 | 1 | Write to selected internal 6845 register | Write Only |
1 | 0 | Read Status Register | Read Only |
1 | 1 | Read from selected internal 6845 register | Read Only |
Type 2
b1 | b0 | Function | Read/Write |
---|---|---|---|
0 | 0 | Select internal 6845 register | Write Only |
0 | 1 | Write to selected internal 6845 register | Write Only |
1 | 0 | - | - |
1 | 1 | Read from selected internal 6845 register | Read Only |
Type 3 and 4
b1 | b0 | Function | Read/Write |
---|---|---|---|
0 | 0 | Select internal 6845 register | Write Only |
0 | 1 | Write to selected internal 6845 register | Write Only |
1 | 0 | Read from selected internal 6845 register | Read Only |
1 | 1 | Read from selected internal 6845 register | Read Only |
It is not possible to read from all the internal registers, this table shows the read/write status of each register for each type:
Register Index | Register Name | Type | ||
---|---|---|---|---|
0 | 1 & 2 | 3 & 4 | ||
0 | Horizontal Total (-1) | Write Only | ||
1 | Horizontal Displayed | Write Only | ||
2 | Horizontal Sync Position | Write Only | ||
3 | Horizontal and Vertical Sync Widths | Write Only | ||
4 | Vertical Total (-1) | Write Only | ||
5 | Vertical Total Adjust | Write Only | ||
6 | Vertical Displayed | Write Only | ||
7 | Vertical Sync Position | Write Only | ||
8 | Interlace and Skew | Write Only | ||
9 | Maximum Raster Address (aka Number of Scan Lines) (-1) | Write Only | ||
10 | Cursor Start Raster | Write Only | Write Only | Read/Write |
11 | Cursor End Raster | Write Only | Write Only | Read/Write |
12 | Display Start Address (High) | Read/Write | Write Only | Read/Write |
13 | Display Start Address (Low) | Read/Write | Write Only | Read/Write |
14 | Cursor Address (High) | Read/Write | ||
15 | Cursor Address (Low) | Read/Write | ||
16 | Light Pen Address (High) | Read Only | ||
17 | Light Pen Address (Low) | Read Only |
Notes
- On CRTCs 0/1/2, if a Write Only register is read from, "0" is returned. The register accessing scheme on CRTCs 3/4 makes it impossible to happen.
- CRTC types 3 and 4 are identical in every way, except for the unlocking mechanism, split screen, hardware soft scroll and 8-bit printer port functionalities specific to the ASIC.
- See the document "Extra CPC Plus Hardware Information" for more details.
Reading from CRTC registers on ASIC/Pre-ASIC
On CRTCs 3/4, only the 3 least significant bits of the selected register number are considered to read a register according to the following table:
Nb | Register | Definition |
---|---|---|
0 | R16 | Light Pen Address (High) |
1 | R17 | Light Pen Address (Low) |
2 | R10 | Cursor Start Raster |
3 | R11 | Cursor End Raster |
4 | R12 | Display Start Address (High) |
5 | R13 | Display Start Address (Low) |
6 | R14 | Cursor Address (High) |
7 | R15 | Cursor Address (Low) |
Therefore, as an example, reading register 4 will give the same result as reading register 12 or 20.
R10/R11 on ASIC/Pre-ASIC
The cursor raster registers R10/R11 act as status registers when read on CRTCs 3/4. They behave as normal cursor raster registers upon write.
R10 - Bit number | Bit value | Event |
---|---|---|
0 | 1 | C0=R0 |
1 | 0 | C0=R0/2 |
2 | 0 | C0=R1-1 (if R0>=R1) |
3 | 0 | C0=R2 |
4 | 0 | C0=R2+R3 |
5 | 0
1 |
R3h>0 : C0=0..R0 on the line R3h from Vsync (C4=R7)
R3h=0 : C0=0..R0 over 15 lines from Vsync (C4=R7) |
6 | 1 | Always 1 |
7 | 0
0 |
C0=0..R0-1 : VMA.Lsb=0xFF
C0=R0 : VMA'.Lsb=0x00 (same cond if C0=R0=0) |
R11 - Bit number | Bit value | Event |
---|---|---|
0 | 0 | C4=R4 and C9=R9 and C0=R0 : Last char of screen |
1 | 0 | C4=R6-1 and C9=R9 and C0=R0 : Last char displayed |
2 | 0 | C4=R7-1 and C9=R9 and C0=R0 : Last char before Vsync |
3 | 0/1 | Timer 16 CRTC frames |
4 | 1 | Always 1 |
5 | 0 | C9=R9 : C0=0 to R0 |
6 | 0 | Always 0 |
7 | 1 | (C9=R9 and C0=R0) or (C9=0 and C0=0 to R0-1) |
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.
Type 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.
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 this gives a HSYNC width of 16.
Types 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.
R3 fine horizontal hardware scroll
If R3l is set to 5 instead of 6 or more, then the frame is shifted to the right on the CTM monitor with an offset of half a CRTC character. This is due to the effect of shortening the C-HSYNC produced by the Gate Array.
Even further, continuously switching these values between each raster line, instead of once per frame, will divide by 2 the difference between the 2 positions and so will give an offset of a quarter of a CRTC character.
And smartly combining R2 and R3 horizontal screen wobbling effects at every raster line will give 1-pixel mode1 horizontal hardware scroll.
As these effects rely on invalid video signals, they are badly supported on modern displays.
Interlace and Skew (R8)
Types 0/3/4:
- Bits 7..6 define the skew (delay) of the CUDISP signal (00 = Non-skew ; 01 = One-character skew ; 10 = Two-character skew ; 11 = Non-output).
- Bits 5..4 define the skew (delay) of the 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 the interlace mode (00 = No Interlace; 01 = Interlace Sync; 10 = No Interlace; 11 = Interlace Sync and Video).
Types 1/2:
- Bits 7..2 are ignored.
- Bits 1..0 define the interlace mode.
For a CRTC character line with n raster lines, R9 must be set to n-1 on all CRTCs, regardless of the interlace settings. The exception is for CRTCs 0/3/4 in IVM mode, where R9 must be set to n-2.
Interlace sync mode (ISM)
In this mode, the same information is painted in both fields to enhance readability. Reprogramming the CRTC is not necessary.
Interlace sync and video mode (IVM)
In this mode, alternating lines are displayed in the even and odd field to double the resolution.
On the even field, the CRTC displays the lines for which VLC is even. On the odd field, the CRTC displays the lines for which VLC is odd.
It is necessary to reprogram the CRTC as if we were building a frame of 624 lines.
CRTC 2 is the exception: R4, R5, R6, R7 do not need to be reprogrammed as it considers each character line to be a double character line.
Interlace adjustment line
On all CRTCs, in both interlace modes, an additional line (the 625th line) is added automatically by the CRTC at the end of the even field. This line is added after the lines of the vertical adjustment mode.
Vertical Displayed (R6)
On CRTCs 0/1/2, the condition VCC=R6 is considered immediately to activate the VBORDER. The only exception is for CRTC 1 with a value of 0, which triggers an immediate BORDER without the condition VCC=R6 being required.
On CRTCs 3/4, the condition VCC=R6 is tested only at new character line start. The update of R6 during the character line is therefore not considered.
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.
R31 doesn't exist on CRTCs 0/2/3/4.
Status register on Type 1
The UM6845R has a status register that can be read using port &BExx.
Bit 6 is set to 1 if there is a strobe input to the /LPEN signal. It is cleared to 0 when either R17 or R16 (LPEN address) of the CRTC are read. It signals there is a valid LPEN input. On my CPC (arnoldemu) with UM6845R, it is triggered at power on, R17 and R16 have the values 0 when read.
Bit 5 is set to 1 when CRTC is in "vertical blanking". Vertical blanking is when the vertical border is active. i.e. VCC>=R6.
It is cleared when the frame is started (VCC=0). It is not directly related to the DISPTMG output (used by the CPC to display the border colour) because that output is a combination of horizontal and vertical blanking. This bit will be 0 when pixels are being displayed.
All the other bits read as 0 and don't have any function.
CRTC Type Detection
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"
CRTC Timing Diagrams
Internal Counters
Counter name | Abbr | Alternate name | Comment |
---|---|---|---|
Horizontal Character Counter | HCC | C0 | |
Horizontal Sync Counter | HSC | C3l | |
Vertical Character Counter | VCC | C4 | |
Vertical Sync Counter | VSC | C3h | |
Vertical Line Counter | VLC | C9 | If not in IVM mode, this counter is exposed on CRTC pins RA0..RA4 |
Vertical Total Adjust Counter | VTAC | C5 | This counter does not exist on CRTCs 0/3/4. C9 is reused instead |
Frame Counter | FC | Used to alternate frames in interlace and for CRTC cursor blinking | |
Memory Address | MA | This counter is exposed on CRTC pins MA0..MA13 |
No matter its type, the CRTC never buffers any of its counters, except for the video pointer MA. The buffer MA' is needed because MA has to be reloaded at the beginning of every raster line.
CRTC counter differences
MA reload
On CRTCs 0/3/4, at the beginning of the first raster line of the frame, MA and MA' are loaded with R12/R13. Otherwise, MA is loaded with MA'.
On CRTC 2, at the beginning of every raster line of the frame (including the first one), MA is loaded with MA'.
On CRTC 1, at the beginning of every raster line of the first character line of the frame (ie. when VCC=0), MA is loaded with R12/R13 instead of MA'. This is a major source of incompatibility if the programmer does not take care. In demos and games, to be compatible with all CRTCs, program R12/R13 only when VCC != 0. This will then take effect at the next frame start.
MA buffering
At the end of the display of the last raster line of each character line (ie. when HCC=R1 and VLC=R9), MA' captures the current value of MA.
CRTC 2 is the exception: at the end of the display of the last raster line of the frame, MA' captures R12/R13 instead of MA.
VSC (C3h) overflow
During a VSYNC on CRTCs 0/3/4, if VSYNC Width (R3h) is changed with a value less than the current VSC, then VSC overflows and will count up to its maximum value (15) before looping back and counting up again until it reaches the new value of R3h.
On CRTCs 1/2, the VSYNC width is fixed to 16 characters. It is not possible to modify it. Therefore, VSC cannot be overflowed.
HSC (C3l) overflow
During an HSYNC, if HSYNC Width (R3l) is changed with a value less than the current HSC, then HSC overflows and will count up to its maximum value (15) before looping back and counting up again until it reaches the new value of R3l.
The only exception is for CRTC 1 with a value of 0, which immediately cancels the current HSYNC.
VCC (C4) overflow
On all CRTCs, if Vertical Total (R4) is changed with a value less than VCC, then:
- if this update was done when VCC < R4, then VCC overflows and will count up to its maximum value (127) before looping back and counting up again until it reaches the new value of R4
- if this update was done when VCC = R4, the current character line was already decided to be the last one of the current frame. No update to R4 will make the CRTC change its mind for the current frame
The only exception when VCC = R4 is for CRTC 1 with a value of 0, which will cause VCC to overflow.
HCC (C0) overflow
If Horizontal Total (R0) is changed with a value less than the current HCC, then:
- on CRTCs 0/1/2, HCC overflows and will count up to its maximum value (255) before looping back and counting up again until it reaches the new value of R0
- on CRTCs 3/4, the current line is considered finished and HCC is immediately reset to 0 on the next line
VLC (C9) overflow
If Number of Scan Lines (R9) is changed with a value less than the current VLC, then:
- on CRTCs 0/1/2, VLC overflows and will count up to its maximum value (31) before looping back and counting up again until it reaches the new value of R9
- on CRTCs 3/4, the current line is considered the last one of this CRTC character and VLC will reset to 0 on the next line
As an exception, on CRTCs 0/2, if VLC is modified during the last frame line, then the updated value will not be considered for the current frame.
VTAC (C5/C9) overflow
During vertical adjustment mode, if Vertical Total Adjust (R5) is changed with a value less than the current VTAC, then:
- on CRTCs 0/1/2, VTAC overflows and will count up to its maximum value (31) before looping back and counting up again until it reaches the new value of R5
- on CRTCs 3/4, the current line is considered the last one of the current frame and vertical adjustment will end
As an exception, on CRTCs 0/2, if VTAC is modified during the last frame line, then the updated value will not be considered for the current frame.
Vertical Adjustment mode
On CRTCs 3/4, this mode does not increment VCC, so VCC remains equal to R4.
On CRTC 0, this mode increments VCC, causing it to exceed R4, but this increment occurs only once.
On CRTCs 1/2, this mode increments VCC, causing it to exceed R4, and this increment can happen multiple times depending on the values of R5 and R9.
Also, only CRTCs 1/2 have a dedicated C5 counter. On CRTCs 0/3/4, during Vertical Adjustment, C9 has to fullfil the VTAC role which means that it cannot fullfil its VLC role. This impacts address generation as R9 is not considered anymore.
RA in IVM interlace mode
When IVM mode is activated, VLC continues to increment normally. However, RA is not identical to VLC anymore. Instead, VLC is considered shifted left by 1 bit, and bit0 represents the parity of the field (even/odd).
Block Diagrams
CRTC-II (aka Type 5)
According to the datasheet, the HD6345 is upward-compatible with the HD6845S in pin and software. And it brings these new features:
- Screen Partition (horizontally split into 4 screens) with paging and scrolling for each screen
- Smooth Scrolling in the vertical direction
- External Synchronization in Master-Slave or TV Syne modes
- Interrupt request by vertical blanking or light pen strobe detection
- Double-size vertical display by Raster Interpolation
- Sync Position Adjustment
- Light Pen Raster Address
- Second Hardware Cursor
- Display Memory Width Setting
- Up to 256 character rows per field
- Programmable Timing Signal for dual-port RAM in MPRAM mode
- Three-state Control of MA/RA Output
This chip was never used by Amstrad. However, some CPC enthusiasts have replaced the original CRTC chip in their CPC with this one. Split-screen functionality demoed in BASIC
This is the cheapest way to upgrade the CPC's graphics capabilities, costing only 1.29€. Source
Datasheets
Used by Amstrad
- HD6845S (Hitachi) aka Type 0
- UM6845 (UMC) aka Type 0
- UM6845R (UMC) aka Type 1
- MC6845 (Motorola) aka Type 2 Other datasheet version
- AMS40489 (Amstrad) aka Type 3 (ASIC)
- AMS40226 (Amstrad) aka Type 4 (Pre-ASIC)
DIY upgrade
- HD6345 (Hitachi) aka Type 5 - Upgraded pin-compatible CRTC chip with advanced functionalities Upgrading the CPC to HD6345
Unused clones
- CM607P a Bulgarian clone made in Pravetz factory (maybe used on KC Compact and Aleste 520EX)
- EF6845 by Thomson Semiconductors
- UM6845E by UMC
- F6845 by Fairchild
- CRTC 6545 (MOS, Rockwell, Synertek) is pin-compatible with the 6845 and only has minor differences
- BeebFpga MiSTer OpenCores Verilog/VHDL implementations of the 6845
Tools about CRTC
- some BASIC tools to detect CRTC types 0-1-2 and show some effects by Elmar Krieger (DSK for Emulators)
- File:Shaker26.dsk Shaker - Suite of CRTC tests associated with the CPC CRTC compendium (many of them will not work correctly on emulators and that was the purpose of the tests, to help create more compatible emulation)
- File:Shaker addon.dsk Shaker Add-On (Pixel 1 Hard Scroll / Vertical Rupture all Crtc)
Links
- Wikipedia on the CRTC
- CRTC documentation from Grimware
- Quasar CRTC documentation (in french)
- Differences between CRTC types
- Media:Dossier Rupture(Gozeur Paradox).pdf
- Media:Dossier CRTC(Ramlaid Mortel).pdf Les entrailles du CRTC
- Leçons CRTC (CheshireCat)
- Media:ACCC1.8-EN.pdf Media:ACCC1.8-FR.pdf CPC CRTC Compendium - Latest (04/2024!) document containing in-depth info about CRTC programming on CPC.
- Media:CRTC Compendium Podcast.mp3 The CRTC Compendium digested in podcast format
Related pages
- Synchronising with the CRTC and display : technic and details on the relationship between Gate Array and CRTC.