Copper
The Copper is a simple programmed system which allows certain Next Registers to be altered automatically at certain scanline positions.
"Copper" is a strangulation of "co-processor" and is a term taken from the Amiga which had a similar function. The copper on the Spectrum Next is not associated with the Raspberry Pi 'coprocessor'.
A program is uploaded to the Copper by sending it, byte by byte, to Copper Data ($60). Each Copper instruction is 16 bits wide and there are only 2 opcodes, so only a single bit in an instruction determines the operation. The two operations are:
Opcode | Bit pattern | Effect |
---|---|---|
WAIT | %1hhhhhhv %vvvvvvvv | Wait for raster line v (0-311) and horizontal position h*8 (h is 0-55) (duration 1 CLOCK) |
MOVE | %0rrrrrrr %vvvvvvvv | Write value v to Next register r (duration 2 CLOCKS) |
NOOP | %00000000 %00000000 | Special case of "value 0 to port 0" works as "no operation" (duration 1 CLOCK) |
HALT | %11111111 %11111111 | Special case of "WAIT 63,511" works as "halt" instruction |
The copper's program storage is 2k big; since each instruction is 2 bytes it can store exactly 1024 instructions, numbered 0-1023. The copper is controlled by a word accessed through Next Registers Copper Control Low Byte ($61) and Copper Control High Byte ($62). The internal "program counter" (CPC) has 10 bits (0-1023), auto-incrementing it after each instruction, wrapping around after last one back to first one.
The copper control word has the structure: %cc000iii %iiiiiiii. I is the storage position (0-2047) (for writing instructions with Copper Data ($60)), and c is used to set the behaviour mode of the copper, as follows:
C bits | Effect |
---|---|
%00 | STOP, copper does nothing (CPC keeps its current value) |
%01 | reset CPC to 0, then START |
%10 | START (resumes from current CPC) |
%11 | reset CPC to 0, then START; Also VBLANK does reset CPC to 0 |
When c bits are identical to previously written value, the control mode is ignored, and only write-index I is modified.
If you don't want the copper program to loop infinitely, then you can mark the "end" of the copper program by waiting for a line higher than 311 ("HALT" instruction). Since these lines will never be reached, the copper will essentially halt until reset.
The precise timing and many more details are currently documented in distribution file "/docs/extra-hw/copper/COPPER-v0.1c.TXT".
(core 2.0) the copper code is executed at 14MHz, and the COPPER-v0.1c.TXT document above describes timing of the core2.0. (core 3.0) the copper code is executed at 28MHz, the precise timing is not documented yet
From practical test (with the Swedish-flags copper test) the coordinates for WAIT are identical, MOVE is twice as fast (flags are half of original width because each pixel is created by single MOVE instruction).
Important values affecting pixel display are now sampled at the same moment when the pixel is drawn (no test yet to describe what does that mean at sub-pixel accuracy terms and in which order the copper MOVEs should be done with what kind of lead in case you want to set for example 6 different display-affecting registers, by theoretical approach of single MOVE taking half-pixel width you should start precisely 3 pixels ahead of the edge where all values should be set, but YMMV) (overall it's probably much wiser to avoid situations where you need sub-pixel precision, or test with the real board heavily)