Difference between revisions of "CRTC"

From CPCWiki - THE Amstrad CPC encyclopedia!
Jump to: navigation, search
(MA buffering)
(Hardware scrolling)
 
(449 intermediate revisions by the same user not shown)
Line 1: Line 1:
The '''CRTC''' (Cathode Ray Tube Controller) helps to generate the video signal of the Amstrad CPC.
+
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.
  
NOTE: 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.
+
This chip is also used in the [[BBC Micro]], [[Sharp X1]], [[MicroBee]], [[Commodore PET]] and the early graphics cards (MDA, Hercules, CGA, Plantronics Colorplus) for [[IBM PC]]. And it is found in some [https://www.msx.org/wiki/Hitachi_HD6845 MSX1 expansions], providing an 80-column text mode.
 +
 
 +
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 [https://shaker.logonsystem.eu/ CRTC Compendium] documentation, condensed and rearranged for clarity. For details, timing diagrams, code examples, coding tips, and more, refer to that documentation.
  
 
<br>
 
<br>
Line 7: Line 11:
 
== 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 Plus 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 CRTC was a common part available from many different manufacturers. During the life of the CPC, Amstrad sourced the CRTC from various manufacturers.  
Line 31: Line 37:
 
|AMS40489||Amstrad||3 (note 1)
 
|AMS40489||Amstrad||3 (note 1)
 
|-
 
|-
|40226||Amstrad||4 (note 2)
+
|AMS40226||Amstrad||4 (note 2)
 
|}
 
|}
  
 
'''NOTES'''  
 
'''NOTES'''  
  
1. The CRTC functionality is integrated into the CPC+ ASIC. This type exists only in the CPC464+,CPC6128+ and GX4000.  
+
1. The CRTC functionality is integrated into the CPC+ ASIC. This type exists only in the 464 Plus, 6128 Plus 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.
 
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.  
+
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. The type number system was originally used by demo programmers.  
 
+
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:  
 
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,
+
* 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  
 
* to adapt the software so that it will run with the detected 6845  
* In most cases, the type of the detected 6845 is reported.
+
* In most cases, the type of the detected 6845 is reported
 
+
4. As far as I know, the KC compact used HD6845R only.
+
 
+
<br>
+
 
+
== Timings and relating with Z80 instructions count ==
+
 
+
Some informations like : how many Z80 instructions can I fit within a scan line ? Within a screen ? Etc... See http://www.cpcwiki.eu/forum/programming/frame-flyback-and-interrupts/msg25106/#msg25106
+
(To be extracted/edited to conform to wiki good practices).
+
  
 
<br>
 
<br>
Line 65: Line 60:
 
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 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
+
The recommended I/O port addresses are:
  
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
 
!I/O port address
 
!I/O port address
 +
!/CS (A14)
 +
!R/W (A9)
 +
!RS (A8)
 
!Function
 
!Function
 
!Read/Write
 
!Read/Write
 
|-
 
|-
|&BCxx||Select 6845 register||Write only
+
|&BCxx||0||0||0||Select 6845 register||Write only
 
|-
 
|-
|&BDxx||Write 6845 register data||Write only
+
|&BDxx||0||0||1||Write to selected internal 6845 register||Write only
 
|-
 
|-
|&BExx||(note 1)||Read 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 1)||Read only
+
|&BFxx||0||1||1||Read from selected internal 6845 register||Read only
 
|-
 
|-
 
|}
 
|}
  
'''NOTE'''
+
The CRTC is not connected to the CPU's RD and WR pins, so it cannot detect the bus's I/O direction. Therefore, executing an IN instruction to the select or write functions causes the CRTC to write the unpredictable data provided by the high-impedance bus to its registers.
  
1. The function of these I/O ports is dependant on the CRTC type
+
<br>
+
 
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.
+
=== Z80 I/O access timings ===
 +
 
 +
The clock provided to the CRTC by the ASIC/Pre-ASIC is phase-shifted compared to the one provided by the Gate Array.
 +
 
 +
{| 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>
 
<br>
  
==Addressing==
+
==Video Memory Address (VMA)==
  
The video memory address VMA of the [[Gate Array]] is constructed from the CRTC MA and RA signals.
+
The VMA of the [[Gate Array]] is constructed from the CRTC MA and RA signals:
  
 
{| class="wikitable"
 
{| class="wikitable"
Line 105: Line 132:
 
|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 138: Line 165:
  
 
CRTC pins RA3, RA4, MA10, MA11 are not connected on CPC.
 
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.
 +
 +
{| 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>
 +
 +
=== 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 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 [https://www.cpc-power.com/index.php?page=detail&num=1839 Roland on the Ropes], released in 1984.
 +
 +
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.
 +
 +
<br>
 +
 +
== Split screen ==
 +
 +
While there is usually 1 CRTC frame per screen frame, the screen frame can be divided into multiple CRTC frames of varying proportions.
 +
 +
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>
 
<br>
Line 157: Line 282:
 
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.
  
The DISPTMG signal is composited from its 3 internal subcomponents: HBORDER (Horizontal), VBORDER (Vertical), IBORDER (Immediate) by using the NOR function.
+
While border is active, all the CRTC counters continue to increment normally and addresses continue to be generated.
  
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.
+
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>
 
<br>
  
== HSYNC and VSYNC ==
+
=== HBORDER ===
  
On CPC, HSYNC and VSYNC from the CRTC are passed to the [[Gate Array]] for further modification. See its wiki page.
+
On all CRTCs, HBORDER is disabled when HCC=0 and enabled when HCC=R1.
  
The HSYNC width value is interpreted differently between CRTCs. On CRTCs 0/1, if 0 is programmed no HSYNC is generated. On CRTCs 2/3/4, if 0 is programmed this gives a HSYNC width of 16.
+
The exception is for CRTC2 during an HSYNC: the HCC=0 check is skipped, so HBORDER stays on.
  
CRTCs 1/2 have a fixed VSYNC width value of 16. VSYNC width can be configured with Register 3 on CRTCs 0/3/4. If 0 is programmed this gives 16 lines of VSYNC.
+
<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.
  
The bit 0 of port B of the PPI changes to 1 as soon as the VSYNC signal is produced by the CRTC.
+
On CRTCs 3/4, the condition VCC=R6 is tested only at each new character line start (when VLC=0 and HCC=0).
  
 
<br>
 
<br>
  
== CRTC registers ==
+
=== SBORDER ===
  
The Internal registers of the 6845 are:
+
Split border is a technique similar to split rasters, except that it is handled by the CRTC instead of the [[Gate Array]].
  
{| class="wikitable"
+
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.
|-
+
!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.
+
It is not possible to force DISPTMG on CRTC 2.
  
On CRTC 1, registers 18-30 read as 0, register 31 reads as 0xff.
+
<br>
  
Details about Reg. 12 and Reg. 13 specifically:
+
=== Border bytes ===
  
  .------- REG 12 --------.  .------- REG 13 --------.
+
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.
  |                      |  |                      |
+
  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  |
+
  '--'--'--------------'  '--'--'---------------'
+
  
So, it's possible to use 32KB screen size (used for [[Programming:Overscan|overscan]]) by setting bits 11 and 10 both to 1 (of Register 12). 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.
+
==== 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, 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 SBORDER is activated. But on CRTCs 0/2, the first raster line shows an alternation of bytes of VBORDER and displayable characters.
 +
 
 +
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>
 
<br>
  
== CRTC register differences ==
+
== HSYNC ==
  
The following tables list the functions that can be accessed for each type:
+
The HSYNC signal from the CRTC is not directly connected to the display. It is passed to the [[Gate Array]] for further modification. See its wiki page.
  
Type 0
+
While HSYNC is active, all the CRTC counters continue to increment normally and addresses continue to be generated.
  
{| class="wikitable"
+
On all CRTCs, while an HSYNC is ongoing, the condition HCC=R2 is ignored. So we cannot trigger a new HSYNC during an HSYNC.
!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
+
=== Contiguous HSYNCs ===
  
{| class="wikitable"
+
On CRTC 0, two HSYNCs cannot be contiguous. They are always separated by at least 1 CRTC character. What happens is that when HSC=R3 and HCC=R2, the condition HSC=R3 takes precedence over the condition HCC=R2 and HSYNC is stopped.
!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
+
On CRTCs 1/2/3/4, HSYNCs can be contiguous.
  
{| class="wikitable"
+
=== Signal delay ===
!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
+
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.
  
{| class="wikitable"
+
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 to match the display signal.
!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:  
+
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. Fortunately, the issue is easy to fix, by adjusting the HSYNC width with CRTC register 3.
 +
 
 +
=== 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.
 +
 
 +
=== Screen wobbling and Fine horizontal hardware scroll ===
 +
 
 +
These effects use invalid HSYNC signals, which are poorly supported by modern displays. However, these effects were used in commercial-era CPC games, so it's fine if you choose to use them.
 +
 
 +
When R2 increases by 1, the screen is shifted to the left by 16 mode2 pixels.
 +
 
 +
When R2 decreases by 1, the screen is shifted to the right by 16 mode2 pixels.
 +
 
 +
When R3l increases by 1 (and if <6), the screen is shifted to the left by 8 mode2 pixels.
 +
 
 +
When R3l decreases by 1 (and if >2), the screen is shifted to the right by 8 mode2 pixels.
 +
 
 +
The shift is not instantaneous but follows a logarithmic attenuation across several raster lines. This property can be used to get even finer horizontal control by modifying R2/R3 on each raster line.
 +
 
 +
[[Longshot]] has demonstrated [https://youtu.be/1q7RQykZoKY horizontal hardware scroll] with one-pixel precision in mode1 on all CRTCs. However, because you have to synchronize with each line, it takes a lot of CPU time if it's done in fullscreen (272 lines).
 +
 
 +
<br>
 +
 
 +
== VSYNC ==
 +
 
 +
The VSYNC signal from the CRTC is not directly connected to the display. It is passed to the [[Gate Array]] for further modification. See its wiki page.
 +
 
 +
While VSYNC is active, all the CRTC counters continue to increment normally and addresses continue to be generated.
 +
 
 +
On all CRTCs, while a VSYNC is ongoing, the condition VCC=R7 is ignored. So we cannot trigger a new VSYNC during a 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.
 +
 
 +
=== Blocked VSYNC ===
 +
 
 +
On CRTC 0, if R7 is modified with the value of VCC when HCC<2, we are in blocked VSYNC. Then, the VSYNC can no longer occur on VCC=R7 until an unblocking condition is produced (VCC or R7 update). Source: §16.4 "Conditions to consider" of the CRTC Compendium
 +
 
 +
=== 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.
 +
 
 +
=== PPI VSYNC ===
 +
 
 +
The VSYNC pin of the CRTC is directly connected to bit0 of port B of the PPI. There is no delay involved.
 +
 
 +
On Amstrad CPC (not Plus!), it is also possible to reverse the direction of PPI port B to output a "fake" VSYNC signal directly from the PPI to the Gate Array.
 +
 
 +
As an exception, the Ghost VSYNC of CRTC 2 overpowers the Fake VSYNC.
 +
 
 +
=== Subpixel vertical hardware scroll ===
 +
 
 +
By tuning very precisely when the VSYNC signal is sent to the monitor,  Longshot has demonstrated [https://youtu.be/bSjRU6Wye00 vertical hardware scroll] with a precision of 1/128th of a pixel. Furthermore, subpixel vertical scrolling consumes very little CPU.
 +
 
 +
=== 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.
 +
 
 +
As an exception, on CRTCs 3/4, if R7=0 then mid-VSYNC will instead occur on the odd field. Source: §19.7 "Mid-VSYNC" of the CRTC Compendium.
 +
 
 +
<br>
 +
 
 +
== Interlace modes ==
 +
 
 +
Note: A lot of details about the CRTC interlace implementations are missing in this article. Consider it as an introduction to the topic.
 +
 
 +
[[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>
 +
 
 +
== CRTC registers ==
 +
 
 +
The Internal registers of the 6845 are:
  
 
{| class="wikitable"
 
{| class="wikitable"
 +
|-
 
!rowspan=2|Register Index
 
!rowspan=2|Register Index
 
!rowspan=2|Register Name
 
!rowspan=2|Register Name
!colspan=3|Type
+
!colspan=3|Read/Write
 +
!rowspan=2|Range
 +
!rowspan=2|CPC Setting
 +
!rowspan=2|Notes
 
|-
 
|-
!0
+
!CRTC 0
!1 & 2
+
!CRTCs 1/2
!3 & 4
+
!CRTCs 3/4
 
|-
 
|-
|0||Horizontal Total (-1)||colspan=3 style="text-align: center;"|Write Only
+
|0||Horizontal Total (-1)||colspan=3 style="text-align: center;"|Write||00000000||63||Width of the screen, in characters. Should always be 63 (64 characters). 1 character == 1μs.
 
|-
 
|-
|1||Horizontal Displayed||colspan=3 style="text-align: center;"|Write Only
+
|1||Horizontal Displayed||colspan=3 style="text-align: center;"|Write||00000000||40||Number of characters displayed. Once horizontal character count (HCC) matches this value, DISPTMG is set to 1.
 
|-
 
|-
|2||Horizontal Sync Position||colspan=3 style="text-align: center;"|Write Only
+
|2||Horizontal Sync Position||colspan=3 style="text-align: center;"|Write||00000000||46||When to start the HSync signal.
 
|-
 
|-
|3||Horizontal and Vertical Sync Widths||colspan=3 style="text-align: center;"|Write Only
+
|3||Horizontal and Vertical Sync Widths||colspan=3 style="text-align: center;"|Write||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)||colspan=3 style="text-align: center;"|Write Only
+
|4||Vertical Total (-1)||colspan=3 style="text-align: center;"|Write||x0000000||38||Height of the screen, in characters.
 
|-
 
|-
|5||Vertical Total Adjust||colspan=3 style="text-align: center;"|Write Only
+
|5||Vertical Total Adjust||colspan=3 style="text-align: center;"|Write||xxx00000||0||Measured in scanlines, can be used for smooth vertical scrolling on CPC.
 
|-
 
|-
|6||Vertical Displayed||colspan=3 style="text-align: center;"|Write Only
+
|6||Vertical Displayed||colspan=3 style="text-align: center;"|Write||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||colspan=3 style="text-align: center;"|Write Only
+
|7||Vertical Sync Position||colspan=3 style="text-align: center;"|Write||x0000000||30||When to start the VSync signal, in characters.
 
|-
 
|-
|8||Interlace and Skew||colspan=3 style="text-align: center;"|Write Only
+
|8||Interlace and Skew||colspan=3 style="text-align: center;"|Write||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)||colspan=3 style="text-align: center;"|Write Only
+
|9||Maximum Raster Address (aka Number of Scan Lines) (-1)||colspan=3 style="text-align: center;"|Write||xxx00000||7||Maximum scan line address on CPC can hold between 0 and 7, higher values' upper bits are ignored.
 
|-
 
|-
|10||Cursor Start Raster||Write Only||Write Only||Read/Write
+
|10||Cursor Start Raster||style="text-align: center;"|Write||style="text-align: center;"|Write||Read/Write||xBP00000||0||B = Blink On/Off; P = Blink Period Control (16 or 32 frames). Sets first raster row of character that cursor is on to invert.
 
|-
 
|-
|11||Cursor End Raster||Write Only||Write Only||Read/Write
+
|11||Cursor End Raster||style="text-align: center;"|Write||style="text-align: center;"|Write||Read/Write||xxx00000||0||Sets last raster row of character that cursor is on to invert.
 
|-
 
|-
|12||Display Start Address (High)||Read/Write||Write Only||Read/Write  
+
|12||Display Start Address (High)||Read/Write||style="text-align: center;"|Write||Read/Write||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)||Read/Write||Write Only||Read/Write
+
|13||Display Start Address (Low)||Read/Write||style="text-align: center;"|Write||Read/Write||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)||colspan=3 style="text-align: center;"|Read/Write
+
|14||Cursor Address (High)||colspan=3 style="text-align: center;"|Read/Write||xx000000||0||
 
|-
 
|-
|15||Cursor Address (Low)||colspan=3 style="text-align: center;"|Read/Write
+
|15||Cursor Address (Low)||colspan=3 style="text-align: center;"|Read/Write||00000000||0||
 
|-
 
|-
|16||Light Pen Address (High)||colspan=3 style="text-align: center;"|Read Only
+
|16||Light Pen Address (High)||colspan=3 style="text-align: center;"|Read||xx000000||||On CRTC1, bit6 of Status register goes to 0 when R16 is read.
 
|-
 
|-
|17||Light Pen Address (Low)||colspan=3 style="text-align: center;"|Read Only
+
|17||Light Pen Address (Low)||colspan=3 style="text-align: center;"|Read||00000000||||On CRTC1, bit6 of Status register goes to 0 when R17 is read.
 
|-
 
|-
 
|}
 
|}
  
'''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.
  
* 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.
+
<br>
  
* CRTC types 3 and 4 are identical in every way, except for the unlocking mechanism, split-screen and 8-bit printer port functionalities specific to the ASIC.
+
=== Register access ===
  
* See the document "Extra CPC Plus Hardware Information" for more details.
+
On all CRTCs, only the 5 least significant bits of the selected register number are considered to write to a register. The other bits are ignored.
  
<br>
+
On CRTCs 0/1/2, only the 5 least significant bits of the selected register number are considered to read a register:
 +
* On CRTCs 0/2, registers 18-31 read as 0
 +
* On CRTC 1, registers 18-30 read as 0, register 31 reads as &FF
  
=== 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:
 
+
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"
 
{| class="wikitable"
Line 424: Line 540:
 
|}
 
|}
  
Therefore, as an example, reading register 4 will give the same result as reading register 12 or 20.
+
<br>
 +
 
 +
== CRTC register differences ==
 +
 
 +
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.
  
 
<br>
 
<br>
Line 517: Line 637:
  
 
Type 0:
 
Type 0:
*Bits 7..4 define Vertical Sync Width. If 0 is programmed this gives 16 lines of VSYNC.
+
*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.
+
*Bits 3..0 define Horizontal Sync Width. If 0 is programmed, no HSYNC is generated (and therefore, no interrupts).
  
 
Type 1:
 
Type 1:
 
*Bits 7..4 are ignored. Vertical Sync is fixed at 16 lines.
 
*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.
+
*Bits 3..0 define Horizontal Sync Width. If 0 is programmed, no HSYNC is generated (and therefore, no interrupts).
  
 
Type 2:
 
Type 2:
 
*Bits 7..4 are ignored. Vertical Sync is fixed at 16 lines.
 
*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.
+
*Bits 3..0 define Horizontal Sync Width. If 0 is programmed, this gives a HSYNC width of 16.
  
 
Types 3/4:
 
Types 3/4:
*Bits 7..4 define Vertical Sync Width. If 0 is programmed this gives 16 lines of VSYNC.
+
*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 3..0 define Horizontal Sync Width. If 0 is programmed, this gives a HSYNC width of 16.
  
 
<br>
 
<br>
Line 540: Line 660:
 
*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 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 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).
+
*Bits 1..0 define the interlace mode (00 = No Interlace ; 01 = Interlace Sync ; 10 = No Interlace ; 11 = Interlace Sync and Video).
  
 
Types 1/2:
 
Types 1/2:
 
*Bits 7..2 are ignored.
 
*Bits 7..2 are ignored.
 
*Bits 1..0 define the interlace mode.
 
*Bits 1..0 define the interlace mode.
 
 
2 interlace modes are available:
 
* In interlace sync mode, the same information is painted in both fields to enhance readability. In this mode, reprogramming the CRTC is not necessary
 
* In interlace sync and video mode, alternating lines are displayed in the even and odd field to double the resolution. In this mode, it is necessary to reprogram the CRTC as if we were building a frame of 624 lines. The 625th line is managed automatically by the CRTC
 
[[File:CRTC Interlace modes.png]]
 
 
<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>
 
<br>
Line 568: Line 674:
 
Its use is described in the documentation for the Rockwell R6545 in combination with R18, R19 and R8 and the Status 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.
+
In the UM6845R it appears to have no effect. Reading and writing does nothing. Reading it returns &FF.
  
 
R31 doesn't exist on CRTCs 0/2/3/4.
 
R31 doesn't exist on CRTCs 0/2/3/4.
Line 578: Line 684:
 
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.
  
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 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 Kevin Thacker's CPC 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.  
 
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.  
Line 597: Line 703:
 
50 PRINT"crtc 3/4"
 
50 PRINT"crtc 3/4"
 
</pre>
 
</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>
 
<br>
  
Line 614: Line 723:
 
! Abbr
 
! Abbr
 
! Alternate name
 
! Alternate name
 +
! Compared with
 
! Comment
 
! Comment
 
|-
 
|-
Line 619: Line 729:
 
|HCC
 
|HCC
 
|C0
 
|C0
|
+
|R0, R1, R2
 +
| Increments on every clock cycle
 
|-
 
|-
 
|Horizontal Sync Counter
 
|Horizontal Sync Counter
 
|HSC
 
|HSC
 
|C3l
 
|C3l
 +
|R3l
 
|
 
|
 
|-
 
|-
Line 629: Line 741:
 
|VCC
 
|VCC
 
|C4
 
|C4
 +
|R4, R6, R7
 
|
 
|
 
|-
 
|-
Line 634: Line 747:
 
|VSC
 
|VSC
 
|C3h
 
|C3h
 +
|R3h
 +
|R3h is fixed to 0 on CRTCs 1/2. This gives 16 lines of VSYNC
 
|-
 
|-
 
|Vertical Line Counter
 
|Vertical Line Counter
 
|VLC
 
|VLC
 
|C9
 
|C9
|If non-interlace, this counter is exposed on CRTC pins RA0..RA4
+
|R9, R10, R11
 +
|If not in IVM mode, this counter is exposed on CRTC pins RA0..RA4
 
|-
 
|-
 
|Vertical Total Adjust Counter
 
|Vertical Total Adjust Counter
 
|VTAC
 
|VTAC
 
|C5
 
|C5
 +
|R5
 
|This counter does not exist on CRTCs 0/3/4. C9 is reused instead
 
|This counter does not exist on CRTCs 0/3/4. C9 is reused instead
 
|-
 
|-
 
|Frame Counter
 
|Frame Counter
 
|FC
 
|FC
 +
|
 
|
 
|
 
|Used to alternate frames in interlace and for CRTC cursor blinking
 
|Used to alternate frames in interlace and for CRTC cursor blinking
Line 652: Line 770:
 
|Memory Address
 
|Memory Address
 
|MA
 
|MA
 +
|
 
|
 
|
 
|This counter is exposed on CRTC pins MA0..MA13
 
|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. A buffer MA' is needed because MA has to be reloaded at each raster line start.
+
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>
 
<br>
Line 663: Line 782:
  
 
=== MA buffering ===
 
=== MA buffering ===
 +
 +
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.
  
 
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.
 
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, where MA' captures R12/R13 instead of MA at the last line of the frame.
+
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>
 
<br>
Line 672: Line 793:
 
=== MA reload ===
 
=== MA reload ===
  
On CRTCs 0/3/4, at the first raster line start of the frame, MA and MA' are loaded with R12/R13.
+
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 CRTC frame start.
 +
 
 +
==== Rupture For Dummies (R5 bug) ====
 +
 
 +
CRTC 1 has a bug that occurs when R5 is updated with a non-zero value when HCC=R0 and VLC≠R9, but only when R5 was previously 0. This changes the MA update source to R12/R13 instead of MA'. The CRTC then loads R12/R13 into MA at the beginning of every scanline, regardless of the VCC value.
 +
 
 +
This R5 bug also messes with the frame parity management. However, it is possible to fix the parity of the frame by activating/deactivating the IVM interlace mode.
 +
 
 +
The vertical adjustment operates normally after the RFD is triggered. If vertical adjustment is not needed, R5 can be reset at any time after the RFD is activated.
  
On CRTC 2, at the first raster line start of the frame, MA is loaded with MA' as for all the raster line start of the frame.
+
This CRTC bug divides the CPC demoscene community, with some considering it fully understood, while others find it still perplexing as it seems like the bug itself is bugged.
  
On CRTC 1, on every raster line start of the first character line of the frame (ie. when VCC=0), MA is reloaded with R12/R13 instead of MA'. This discrepancy is a major source of incompatibility if the programmer does not take care. In demos and games, to be compatible with CRTC 1, program R12/R13 when VCC!=0. This will then take effect at the next frame start.
+
This effect is used in the [https://www.cpc-power.com/index.php?page=detail&num=19308 DSC4 demo].
  
 
<br>
 
<br>
Line 682: Line 815:
 
=== VSC (C3h) overflow ===
 
=== 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 continue to count up to its maximum value (15) before looping back and counting up again until it reaches the new value of R3h.
+
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.
 
On CRTCs 1/2, the VSYNC width is fixed to 16 characters. It is not possible to modify it. Therefore, VSC cannot be overflowed.
Line 690: Line 823:
 
=== HSC (C3l) overflow ===
 
=== 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 continue to count up to its maximum value (15) before looping back and counting up again until it reaches the new value of R3l.
+
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.
 
The only exception is for CRTC 1 with a value of 0, which immediately cancels the current HSYNC.
Line 699: Line 832:
  
 
On all CRTCs, if Vertical Total (R4) is changed with a value less than VCC, then:
 
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 continue to 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, 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
 
* 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
  
Line 719: Line 852:
 
* 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 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
 
* 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>
 
<br>
Line 725: Line 860:
  
 
During vertical adjustment mode, if Vertical Total Adjust (R5) is changed with a value less than the current VTAC, then:
 
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 continue to count up to its maximum value (31) before looping back and counting up again until it reaches the new value of R5
+
* 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
 
* 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>
 
<br>
Line 739: Line 876:
  
 
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.
 
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>
 +
 +
=== Counter freezes ===
 +
 +
On CRTCs 1/2/3/4, R0 accepts all values without causing any problems for counters.
 +
 +
On CRTC 0:
 +
* Setting R0 to 0 will cause numerous issues that stem from the fact that VLC is frozen. As HCC never reaches 1, the logic that increments VLC is never triggered.
 +
* The logic that triggers vertical adjustment is broken if R0<2.
  
 
<br>
 
<br>
Line 757: Line 904:
 
=== Motorola ===
 
=== Motorola ===
 
[[File:Motorola CRTC Block Diagram.png]]
 
[[File:Motorola CRTC Block Diagram.png]]
 +
 +
<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 (160x100x16, 320x100x4, 640x100x2) 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>
 
<br>
Line 762: Line 921:
 
== Datasheets ==
 
== Datasheets ==
  
 +
==== Used by Amstrad ====
 
* [[Media:hd6845.hitachi.pdf|HD6845S (Hitachi)]] aka Type 0
 
* [[Media:hd6845.hitachi.pdf|HD6845S (Hitachi)]] aka Type 0
 
* [[Media:UM6845-UMC.pdf|UM6845 (UMC)]] aka Type 0
 
* [[Media:UM6845-UMC.pdf|UM6845 (UMC)]] aka Type 0
 
* [[Media:Um6845r.umc.pdf|UM6845R (UMC)]] aka Type 1
 
* [[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:Mc6845.motorola.pdf|MC6845 (Motorola)]] aka Type 2
* [[Media:CPC_Plus_Asic_Schematic.GIF|AMS40489 (Amstrad)]] aka Type 3
+
* [[Media:CPC_Plus_Asic_Schematic.GIF|AMS40489 (Amstrad)]] aka Type 3 ([[ASIC]])
* [[AMS40226 (Amstrad)]] aka Type 4
+
* [[AMS40226 (Amstrad)]] aka Type 4 (Pre-ASIC)
*[[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]
+
  
 
<br>
 
<br>
  
=== Unused clones ===
+
==== Unused clones ====
* [[CM607P]] a Bulgarian clone made in Pravetz factory
+
* [[CM607P]] a Bulgarian clone made in Pravetz factory. It is used in the [[Aleste 520EX]].
* [[Media:EF6845P.pdf|EF6845]] by Thomson Semiconductors
+
* [[Media:hd6845.hitachi.pdf|HD6845R]] by Hitachi. According to Kevin Thacker, the [[KC Compact]] used HD6845R only.
 
* [[Media:UM6845E-UMC.pdf|UM6845E]] by UMC
 
* [[Media:UM6845E-UMC.pdf|UM6845E]] by UMC
 +
* [[Media:Mc6845.pdf|MC6845-1]] by Motorola
 
* [[Media:F6845.pdf|F6845]] by Fairchild
 
* [[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
+
* [[Media:EF6845P.pdf|EF6845]] by Thomson Semiconductors
 +
* [[Media:VL6845 VTi.pdf|VL6845]] by VTi
 +
* [[Media:C6845 CRTC (CAST).pdf|C6845]] by Cast
 +
* [[Media:Mos 6545-1 crtc.pdf|CRTC 6545]] (MOS, Rockwell, Synertek) is pin-compatible with the 6845. Its differences are found in the R8 register.
 +
* [[Media:MB89321B FUJ.pdf|MB89321B]] by Fujitsu. It is pin-compatible with the 6845
 +
* [[Media:MB89321A datasheet CRTC.pdf|MB89321A]] by Fujitsu. Enhanced version that adds smooth scroll, screen partitioning, independent scrolling of screen partitions, and other convenient features
 
* [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
 
* [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
  
Line 795: Line 960:
 
* [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://pulkomandy.github.io/shinra.github.io/crtc.html Differences between CRTC types]
+
* [https://pulkomandy.github.io/shinra.github.io/crtc.html PulkoMandy's table] [https://www.theoddys.com/acorn/the_6845_crtc/6845%20Variants.xlsx Oddy's table] Differences between CRTC types
 
* [[Media:Dossier Rupture(Gozeur Paradox).pdf]]
 
* [[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.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: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>
 
<br>

Latest revision as of 17:53, 20 December 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 early graphics cards (MDA, Hercules, CGA, Plantronics Colorplus) for IBM PC. And it is found in some MSX1 expansions, providing an 80-column text mode.

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, condensed and rearranged 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 Plus 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.

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)
AMS40226 Amstrad 4 (note 2)

NOTES

1. The CRTC functionality is integrated into the CPC+ ASIC. This type exists only in the 464 Plus, 6128 Plus 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. 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


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 /CS (A14) R/W (A9) RS (A8) Function Read/Write
&BCxx 0 0 0 Select 6845 register Write only
&BDxx 0 0 1 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 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's I/O direction. Therefore, executing an IN instruction to the select or write functions causes the CRTC to write the unpredictable data provided by the high-impedance bus to its registers.


Z80 I/O access timings

The clock provided to the CRTC by the ASIC/Pre-ASIC is phase-shifted compared to the one provided by the Gate Array.

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


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.

CRTC Display Start Address
Register 12 Register 13
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
Unused Video Page Page Size Start Address (1024 positions)
Bit 13 Bit 12 Video Page
0 0 0000 - 3FFF
0 1 4000 - 7FFF
1 0 8000 - BFFF
1 1 C000 - FFFF
Bit 11 Bit 10 Page Size
0 0 16KB
0 1 16KB
1 0 16KB
1 1 32KB


Hardware scrolling

The start address can be manipulated to achieve horizontal and/or vertical hardware scrolling:

  • To move right: start_address = start_address + 1
  • To move left: start_address = start_address - 1
  • To move down: start_address = start_address + R1
  • To move up: start_address = start_address - R1

However, it is a position in word (16 bits), not in byte. So, the 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 Roland on the Ropes, released in 1984.

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 Super Cauldron, released in 1993.


Split screen

While there is usually 1 CRTC frame per screen frame, the screen frame can be divided into multiple CRTC frames of varying proportions.

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), 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.


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.


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).


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.


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.

If border skew is used, 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 SBORDER is activated. But on CRTCs 0/2, the first raster line shows an alternation of bytes of VBORDER and displayable characters.

To see the border bytes with your own eyes, type this BASIC line after reset:

BORDER 6:OUT &BC00,6:OUT &BD00,0


HSYNC

The HSYNC signal from the CRTC is not directly connected to the display. It is passed to the Gate Array for further modification. See its wiki page.

While HSYNC is active, all the CRTC counters continue to increment normally and addresses continue to be generated.

On all CRTCs, while an HSYNC is ongoing, the condition HCC=R2 is ignored. So we cannot trigger a new HSYNC during an HSYNC.

Contiguous HSYNCs

On CRTC 0, two HSYNCs cannot be contiguous. They are always separated by at least 1 CRTC character. What happens is that when HSC=R3 and HCC=R2, the condition HSC=R3 takes precedence over the condition HCC=R2 and HSYNC is stopped.

On CRTCs 1/2/3/4, HSYNCs can be contiguous.

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 to match the display 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. Fortunately, the issue is easy to fix, by adjusting the HSYNC width with CRTC register 3.

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.

Screen wobbling and Fine horizontal hardware scroll

These effects use invalid HSYNC signals, which are poorly supported by modern displays. However, these effects were used in commercial-era CPC games, so it's fine if you choose to use them.

When R2 increases by 1, the screen is shifted to the left by 16 mode2 pixels.

When R2 decreases by 1, the screen is shifted to the right by 16 mode2 pixels.

When R3l increases by 1 (and if <6), the screen is shifted to the left by 8 mode2 pixels.

When R3l decreases by 1 (and if >2), the screen is shifted to the right by 8 mode2 pixels.

The shift is not instantaneous but follows a logarithmic attenuation across several raster lines. This property can be used to get even finer horizontal control by modifying R2/R3 on each raster line.

Longshot has demonstrated horizontal hardware scroll with one-pixel precision in mode1 on all CRTCs. However, because you have to synchronize with each line, it takes a lot of CPU time if it's done in fullscreen (272 lines).


VSYNC

The VSYNC signal from the CRTC is not directly connected to the display. It is passed to the Gate Array for further modification. See its wiki page.

While VSYNC is active, all the CRTC counters continue to increment normally and addresses continue to be generated.

On all CRTCs, while a VSYNC is ongoing, the condition VCC=R7 is ignored. So we cannot trigger a new VSYNC during a 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.

Blocked VSYNC

On CRTC 0, if R7 is modified with the value of VCC when HCC<2, we are in blocked VSYNC. Then, the VSYNC can no longer occur on VCC=R7 until an unblocking condition is produced (VCC or R7 update). Source: §16.4 "Conditions to consider" of the CRTC Compendium

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.

PPI VSYNC

The VSYNC pin of the CRTC is directly connected to bit0 of port B of the PPI. There is no delay involved.

On Amstrad CPC (not Plus!), it is also possible to reverse the direction of PPI port B to output a "fake" VSYNC signal directly from the PPI to the Gate Array.

As an exception, the Ghost VSYNC of CRTC 2 overpowers the Fake VSYNC.

Subpixel vertical hardware scroll

By tuning very precisely when the VSYNC signal is sent to the monitor, Longshot has demonstrated vertical hardware scroll with a precision of 1/128th of a pixel. Furthermore, subpixel vertical scrolling consumes very little CPU.

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.

As an exception, on CRTCs 3/4, if R7=0 then mid-VSYNC will instead occur on the odd field. Source: §19.7 "Mid-VSYNC" of the CRTC Compendium.


Interlace modes

Note: A lot of details about the CRTC interlace implementations are missing in this article. Consider it as an introduction to the topic.

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.


CRTC registers

The Internal registers of the 6845 are:

Register Index Register Name Read/Write Range CPC Setting Notes
CRTC 0 CRTCs 1/2 CRTCs 3/4
0 Horizontal Total (-1) Write 00000000 63 Width of the screen, in characters. Should always be 63 (64 characters). 1 character == 1μs.
1 Horizontal Displayed Write 00000000 40 Number of characters displayed. Once horizontal character count (HCC) matches this value, DISPTMG is set to 1.
2 Horizontal Sync Position Write 00000000 46 When to start the HSync signal.
3 Horizontal and Vertical Sync Widths Write 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) Write x0000000 38 Height of the screen, in characters.
5 Vertical Total Adjust Write xxx00000 0 Measured in scanlines, can be used for smooth vertical scrolling on CPC.
6 Vertical Displayed Write 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 Write x0000000 30 When to start the VSync signal, in characters.
8 Interlace and Skew Write 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) Write xxx00000 7 Maximum scan line address on CPC can hold between 0 and 7, higher values' upper bits are ignored.
10 Cursor Start Raster Write Write Read/Write xBP00000 0 B = Blink On/Off; P = Blink Period Control (16 or 32 frames). Sets first raster row of character that cursor is on to invert.
11 Cursor End Raster Write Write Read/Write xxx00000 0 Sets last raster row of character that cursor is on to invert.
12 Display Start Address (High) Read/Write Write Read/Write 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) Read/Write Write Read/Write 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) Read/Write xx000000 0
15 Cursor Address (Low) Read/Write 00000000 0
16 Light Pen Address (High) Read xx000000 On CRTC1, bit6 of Status register goes to 0 when R16 is read.
17 Light Pen Address (Low) Read 00000000 On CRTC1, bit6 of Status register goes to 0 when R17 is read.

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.


Register access

On all CRTCs, only the 5 least significant bits of the selected register number are considered to write to a register. The other bits are ignored.

On CRTCs 0/1/2, only the 5 least significant bits of the selected register number are considered to read a register:

  • On CRTCs 0/2, registers 18-31 read as 0
  • On CRTC 1, registers 18-30 read as 0, register 31 reads as &FF

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)


CRTC register differences

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.


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 (and therefore, no interrupts).

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 (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, 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.


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.


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 &FF.

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 Kevin Thacker's CPC 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"

Distinguishing between CRTCs 3 and 4 can be done by trying to unlock the ASIC or by testing the PPI chip. On ASIC, if PPI Port B is set as output it will behave the same as input.


CRTC Timing Diagrams

CRTC Timing Diagram Rockwell.png


CRTC timing small.gif


Internal Counters

Counter name Abbr Alternate name Compared with Comment
Horizontal Character Counter HCC C0 R0, R1, R2 Increments on every clock cycle
Horizontal Sync Counter HSC C3l R3l
Vertical Character Counter VCC C4 R4, R6, R7
Vertical Sync Counter VSC C3h R3h R3h is fixed to 0 on CRTCs 1/2. This gives 16 lines of VSYNC
Vertical Line Counter VLC C9 R9, R10, R11 If not in IVM mode, this counter is exposed on CRTC pins RA0..RA4
Vertical Total Adjust Counter VTAC C5 R5 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

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).


CRTC counter differences

MA buffering

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.

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.


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 CRTC frame start.

Rupture For Dummies (R5 bug)

CRTC 1 has a bug that occurs when R5 is updated with a non-zero value when HCC=R0 and VLC≠R9, but only when R5 was previously 0. This changes the MA update source to R12/R13 instead of MA'. The CRTC then loads R12/R13 into MA at the beginning of every scanline, regardless of the VCC value.

This R5 bug also messes with the frame parity management. However, it is possible to fix the parity of the frame by activating/deactivating the IVM interlace mode.

The vertical adjustment operates normally after the RFD is triggered. If vertical adjustment is not needed, R5 can be reset at any time after the RFD is activated.

This CRTC bug divides the CPC demoscene community, with some considering it fully understood, while others find it still perplexing as it seems like the bug itself is bugged.

This effect is used in the DSC4 demo.


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.


Counter freezes

On CRTCs 1/2/3/4, R0 accepts all values without causing any problems for counters.

On CRTC 0:

  • Setting R0 to 0 will cause numerous issues that stem from the fact that VLC is frozen. As HCC never reaches 1, the logic that increments VLC is never triggered.
  • The logic that triggers vertical adjustment is broken if R0<2.


Block Diagrams

Hitachi

CRTC Block Diagram.png


UMC

UMC CRTC Block Diagram.png


Motorola

Motorola CRTC Block Diagram.png


CRTC-II (aka Type 5)

The 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: Split-screen in BASIC. And 3 new graphics modes (160x100x16, 320x100x4, 640x100x2) are available: New graphics modes in BASIC.

This is the cheapest way to upgrade the CPC's graphics capabilities, costing only 1.29€. Source


Datasheets

Used by Amstrad


Unused clones

  • CM607P a Bulgarian clone made in Pravetz factory. It is used in the Aleste 520EX.
  • HD6845R by Hitachi. According to Kevin Thacker, the KC Compact used HD6845R only.
  • UM6845E by UMC
  • MC6845-1 by Motorola
  • F6845 by Fairchild
  • EF6845 by Thomson Semiconductors
  • VL6845 by VTi
  • C6845 by Cast
  • CRTC 6545 (MOS, Rockwell, Synertek) is pin-compatible with the 6845. Its differences are found in the R8 register.
  • MB89321B by Fujitsu. It is pin-compatible with the 6845
  • MB89321A by Fujitsu. Enhanced version that adds smooth scroll, screen partitioning, independent scrolling of screen partitions, and other convenient features
  • BeebFpga MiSTer OpenCores Verilog/VHDL implementations of the 6845


Tools about CRTC


Links


Related pages