The display is controlled by the CRTC and the Gate-Array.
The CRTC generates horizontal and vertical sync signals, and can be used to generate a variety of screen displays.
The Gate-Array converts bytes into pixels using the current screen-mode and palette settings.
Therefore we can synchronise with the CRTC, to an exact point where the internal counters are exactly what we want, or to a exact position on the display.
By synchronising to the display cycle any effect using the CRTC and Gate-Array is possible:
The VSYNC signal of the CRTC is connected directly to PPI port B, therefore it is possible to test the state of the VSYNC.
It is possible to synchronise to the start of the VSYNC using the following code: e.g.
ld b,&f5 ;; PPI port B input .wait_vsync in a,(c) ;; [4] read PPI port B input ;; (bit 0 = "1" if vsync is active, ;; or bit 0 = "0" if vsync is in-active) rra ;; [1] put bit 0 into carry flag jp nc,wait_vsync ;; [3] if carry not set, loop, otherwise continue .continue
Note: This code assumes that the VSYNC is not already active before the code is executed.
However, this will not be accurate enough:
Therefore the timing can differ.
In reality the timing can vary each frame, and depends on the program code following the synchronisation code.
Therefore, if we relied on VSYNC alone our effect would not be stable. For rasters this would mean they would "shake" which is useless for for split rasters.
The best method to synchronise is done by using interrupts for the following reasons:
On the CPC and KC Compact there is a single interrupt source.
On the CPC+ there are 3 interrupt sources (programmable raster interrupt, DMA channel 0, DMA channel 1 and DMA channel 2).
In practice we use both methods of synchronisation.
The VSYNC is used as a reference point in a display cycle, therefore we use VSYNC synchronisation to get to this point. Then we use interrupts to perform exact synchronisation within the display cycle.
On the CPC, we are limited to the standard interrupt. This is generated by the Gate-Array using HSYNCs from the CRTC. See the document about interrupt generation for furthur information.
The position can be predicted, and to some limited degree, controlled. To position our effect exactly where we wanted, we would have to wait a specified number of interrupts until we are close to the position we want, then waste some time until we are at exactly the position we require.
e.g.
di ;; disable maskable interrupts im 1 ;; interrupt mode 0 (jump to interrupt handler at &0038) ld hl,&c9fb ;; poke EI,RET to interrupt handler. ld (&0038),hl ei ;; enable interrupts ;; first synchronise with the vsync ld b,&f5 .vsync_sync in a,(c) rra jr nc,vsync_sync ;; wait 3 interrupts so we are close to the position ;; we want halt halt halt ;; at this point we are synchronised to the monitor draw cycle ;; now waste some time until we are at the exact point ld b,32 .waste_time djnz waste_time ;; we are now synchronised to exactly the point we want . . .
On the CPC+, with the ASIC special features enabled, we can use programmable raster interrupts, or DMA interrupts.
Programmable raster interrupts are the best, because we can define the exact scan-line we want the interrupt to trigger on. DMA interrupts are best if we want a regular repeating interrupt. e.g. every 8 scanlines.
The following example shows how to use raster interrupt.
e.g.
;; disable interrupts di ;; unlock asic to gain access to asic registers ld b,&bc ld hl,sequence ld e,17 .seq ld a,(hl) out (c),a inc hl dec e jr nz,seq ;; page-in asic registers ld bc,&7fb8 out (c),c ;; setup interrupt handler im 1 ;; write EI:RET to interrupt handler ld hl,&c9fb ld (&0038),hl ;; enable interrupts ei ld b,&f5 .vsync_sync in a,(c) rra jr nc,vsync_sync ;; set scan-line that interrupt will be triggered on ld a,30 ;; set the programmable raster interrupt register of the CPC+ ld (&6800),a halt ;; we are now synchronised to line 30 of the visible area ;; if we require, we can waste some time, to get to the exact point we want . . . ;; this is the sequence to unlock the ASIC extra features .sequence defb &ff,&00,&ff,&77,&b3,&51,&a8,&d4,&62,&39,&9c,&46,&2b,&15,&8a,&cd,&ee