The Acorn core implementation progressed quite rapidly unlike how long it has taken me to write up my notes and publish these blog posts. The last remaining task for video generation was to support all the graphics/text modes as well as the colour palette.
This required another read through the advanced user guide to determine the pixel format for each mode/palette.
For 2bpp modes, a single byte will represent four pixels with each pixel having two bits (2bpp). The two bits that represent each pixel are: 7&3, 6&2, 5&1, 4&0. In 4bpp modes it’s 7&5&3&1, 6&4&2&0.
e.g the first pixel in 2bpp is made up of bits 7 and 3.
The pixel format seems a little strange at first. Why use bits 7 and 3 for the first pixel in 2bpp modes rather than consecutive bits 7 and 6? Let’s look at the other formats.
The logic to handle the 1bpp format of 7,6,5,4,3,2,1,0 uses a counter that goes from 7 down to 0 as well as a counter that determines how many times the same pixel should be output (twice in the case of mode 6 to display 320 pixels on a 640 resolution).
With the electron’s pixel format, this exact same logic works for 2bpp and 4bpp modes as the next pixel’s first bit is always -1 away from the current. With the rest of the bits that make up that pixels value a fixed offset away. -4 in the case of 2bpp and -2,-4,-6 for 4bpp.
Had a consecutive format been used, there would be a need for the pixel counter to run on a -1, -2 or -4 step size. As it, a -1 step size can be used by all modes.
case misc_control(MISC_DISPLAY_MODE) is when "000" | "011" | "100" | "110" | "111" => -- Mode 0,3,4,6 : 1bpp 7,6,5,4,3,2,1,0 logical_colour := "000" & pixel_data(pix_idx); when "001" | "101" => -- Mode 1,5 : 2bpp 7&3, 6&2, 5&1, 4&0 logical_colour := "00" & pixel_data(pix_idx) & pixel_data(pix_idx-4); when "010" => -- Mode 2 : 4bpp 7&5&3&1, 6&4&2&0 logical_colour := pixel_data(pix_idx) & pixel_data(pix_idx-2) & pixel_data(pix_idx-4) & pixel_data(pix_idx-6); when others => end case;
Whether that’s the reason for the pixel format, I’m not sure but it seems plausible to me.
When it comes to the palette format, (page 215 advanced user guide) I’m at a loss as to what the logic is behind the format used.
Note, the correct addresses for the 16 colour palette should be FE08 through FE0F (not FE08, FE09 repeating as shown).
I assume there is method to the madness and I’m just not seeing it.
For example, logical colour 5 would be the three bit colour comprised of FE13 bit 0 for Red, FE13 bit 4 for Green and FE12 bit 4 for Blue.
If anyone happens to know why this format was used and how that simplifies the logical colour to 3 bit RGB lookup, let me know because I’m at a loss to explain it. Whilst I feel I’m missing something that will make this more elegant, I’ve implemented it as a big case based LUT e.g the 2bpp LUT for mode 1 and 5 is:
when "001" | "101" => case to_integer(logical_colour) is -- 4 colour when 0 => rgb := colour_palettes(9)(0) & colour_palettes(9)(4) & colour_palettes(8)(4); when 1 => rgb := colour_palettes(9)(1) & colour_palettes(9)(5) & colour_palettes(8)(5); when 2 => rgb := colour_palettes(9)(2) & colour_palettes(8)(2) & colour_palettes(8)(6); when others => -- 3 rgb := colour_palettes(9)(3) & colour_palettes(8)(3) & colour_palettes(8)(7); end case; ...
With mode 6 already working, the rest of the graphics modes turned out to be reasonably straight forward to support. The trickiest part was ensuring modes 0..3 which need to take the CPUs RAM access slot, did so correctly.
Test programs can now be a little more colourful.
and here’s a short program my nephew typed in from the Electron User Guide
Just the cassette interface and sound to go before games should be playable.
After reaching this stage in development of the core, I decided to take a short break before tackling the cassette interface and sound which included a short holiday to Florida. During that time there’s been quite a nice surprise on the ULA front.
Dave from the Stardot forums has managed to get in touch with Harry Barman and received a scanned copy of the Electron ULA schematics for his troubles. A big thank you to Dave for chasing up and Harry for providing the schematics.
There are a few open questions in regards to the internal operation of the cassette interface such as the usage of CAS RC and how writes to the general counter may influence timing. Then there’s the question of why the palette format is the way it is.
Hopefully these schematics will help answer a few of them and perhaps confirm assumptions people have made about the inner workings.