After quite a lot of research to find any documentation I could relating to the Electron, I took a copy of the Getting Started core and decided to tackle the core in roughly the following order
- Video Signal
- ULA RAM/Rom interface and video
- ULA Keyboard
- ULA Cassette
- ULA Sound
- Expansion port
In this and a few subsequent blog posts I’ll present an overview of these steps and the issues encountered along the way. Before all that, a small detour is needed to discuss the PAL standard.
The Electron supports several different graphics modes but each is based on a 640x256 resolution with the 320 and 160 modes having double/quad pixels and some of the text modes having 2 blank lines after every 8 vertical lines.
With no other part of the Electron implemented, there’s little to output video wise, but I wanted to get the signal itself working and at least output a fixed fill colour to the TV.
The Electron has two video outputs, composite out and RGBs. As a UK device, I also assumed it was producing a standard PAL signal, 576i @ 50Hz. However whilst reading up on the PAL standard and figuring out how the Replay_VideoTiming component worked in order to tweak it to generate a PAL signal based on the 16MHz clock the electron used, I happened upon an interesting “tweak” to the PAL spec.
The timing diagram above shows a complete frame of 625 lines that make up the PAL signal. As PAL is an interlaced standard, the data is split across two fields of 312.5 lines per field. Even lines are output in field one and odd lines in field 2. The second field is also offset by half a scan-line which results in the TV offsetting the two fields vertically. This produces a 576i display at 50Hz.
If however the short sync on line 313 is extended by another half a line, field 2 now starts on line 314 and its timing matches that of field 1.
Field 1 can thus be output twice and the lack of a half scan-line offset results in the removal of the vertical interlacing offset causing both the even and odd fields to overlay each other. This effectively reduces the vertical resolution in half to give a 288p @50Hz resolution rather than 576i @ 50HZ. The resulting progressive display has less flickering compared to the interlaced signal at the cost of vertical resolution.
If you’ve not fallen asleep yet, you may be thinking, 313 lines and the field duplicated, that’s 626 lines when PAL is only 625? This can be “fixed” by dropping the last “visible” line, 310 of each frame to give 624 lines. It may also work to drop 310 only from every other frame to match 625 lines, however this complicates implementation and doesn’t appear to be required.
Why would anyone want to use a non-interlaced mode on a tv screen if it (seemingly) halves the vertical resolution? Isn't the resolution of a regular tv set bad enough to begin with?
For why, refer to the section on “Non-interlaced modes” on Niccolo’s site which also has example images of the resulting scan-lines due to the skipped interlaced field offset, which may be familiar to many amiga owners.
That said, I have no evidence to show whether the Electron used a non-interlaced PAL signal or the more normal 576i, this may remain a mystery for a while longer until I either buy one or reverse engineering of the ULA happens. Regardless, I added timings for a 287p mode that runs off of a 16MHz dot clock to match the ULA clock. It may be useful for future projects and provided a excuse to learn how the Replay generates video signals.
Replay 287p Mode
To get this working with the Replay, I wanted to make use of the Replay_VideoTiming component that some other cores use and to make this mode available for other cores that may need it. This involves adding a new set of timing parameters to the Replay_VideoTiming_Pack as well as a few tweaks to the VideoTiming code itself to account for the extended pulse on line 313.
There’s not really any documentation on this, but in case you need to add a new mode or adjust an existing mode to work with a different video clock I’ll provide a rough overview.
constant c_Vidparam_832x287p_50_16MHz : r_Vidparam_int := ( -- 832x256p @ 50Hz 16MHz pclk rep_h => '0', total_h => 1024, active_h => 832, -- 91bp, 26fp, 75hs syncp_h => 26, syncw_h => 75, -- total_v => 312, active_v => 287, -- two lines dropped per field -- fline_f1_v => 22, lline_f1_v => 309, -- one line lost fline_f2_v => 0, lline_f2_v => 0, -- start_f1_v => 312, start_f2_v => 0, -- fsync_f1_v => 312, lsync_f1_v => 3, fsync_f2_v => 0, lsync_f2_v => 0, -- syncpol_h => '0', -- active low syncpol_v => '0', -- active low progressive => '1' );
Why 1024 total “pixels”? This is down to the 16MHz dot clock that the ULA will be using and as PAL runs with a horizontal frequency of 15.625kHz
As for the active pixels, from the timing diagram a full scan-line is 64µs in duration and looking at line 24 for example, either side of the active “grey” region, there’s the h-sync, back porch and front-porch. Converting those durations to pixels gives:
Rounding these of to 75, 91 and 26 pixels gives a sync duration of 192 pixels. With 1024 total pixels that means 832 active pixels. The Electron will only use 640 of those with a border either side.
syncp_h is the horizontal count in pixels for the front porch pulse, in this case 26 pixels. syncw_h is the h-sync duration in pixels, 75. The back porch is the remainder.
The last three entries are used to adjust the sync polarity and provide feedback to other parts of the framework on whether the setup is for progressive or interlaced.
The remaining entries are used to specify the different vertical line regions, where each field starts and ends and which lines are used for vsync. f1 (field 1), f2 (field 2), _v for vertical. prefix of f for first and l for last. Therefor fline_f1_v is the first visible line of field 1.
Lines 6 to 23.5 are used for blanking and do not carrying visible data. The first line with active data is line 23, however the values in the structure above are specified as “the end of the previous line”. i.e the first visible line of field 1 starts after the end of line 22.
As this is using non-interlaced, field 2 values are not needed. Also note that the field one sync begins where field 2 would have started (due to repeating the field), this would be after the end of line 312 but due to extending the 1/2 broad pulse on line 313 to a full broad, this moves the sync start to end of line 313. However, visible line 310 is dropped from each frame to prevent the overall line count exceeding the 625 lines of PAL. This brings the fsync back to 312.
With the timing diagram above and comparing figures to the 576i spec it should be reasonably straight forward to derive new timing information as needed. The Batsocks site also has a timing diagram for the non-interlaced format.
If you look at the VideoTiming vhd file in the Replay SVN, one part of the VideoTiming code I found particularly confusing at first was
cs_gate <= "10000"; -- normal,n1,n2,b1,b2 -- minus one as sampled at h_eol if (standard_ana = PAL) then if (v_cnt = 625) then cs_gate <= "00011"; end if; -- actually line 1 if (v_cnt = 2-1) then cs_gate <= "00011"; end if; if (v_cnt = 3-1) then cs_gate <= "00110"; end if; if (v_cnt = 4-1) then cs_gate <= "01100"; end if; if (v_cnt = 5-1) then cs_gate <= "01100"; end if; if (v_cnt = 311-1) then cs_gate <= "01100"; end if; if (v_cnt = 312-1) then cs_gate <= "01100"; end if; if (v_cnt = 313-1) then cs_gate <= "01001"; end if; if (v_cnt = 314-1) then cs_gate <= "00011"; end if; if (v_cnt = 315-1) then cs_gate <= "00011"; end if; ...
It was not at all clear to me what cs_gate did or what the “normal,n1,n2,b1,b2” bits represented.
Eventually I realized the bit sequences correspond to the normal, short and long pulses of the above timing diagram and it was this section of code that needed modifying to support a non-interlaced mode (PAL_P)
For example line one of the timing image (the green part) has two “broad” pulses, one in the middle of the scan-line and one at the end. These are indicated by b1 and b2. Line 5 shows two short (nibble) pulses one at the start of the scan-line and one in the middle, this is n1 and n2. Finally line 51 shows a full visible line which is the “normal” bit.
The 5 cs_gate bits are hence the first and second half of the scan-line and whether that pulse should be normal, short or broad. Where b1 is a broad pulse in the first half of the scan-line and b2 the second half. Normal represents a first half normal signal pulse or a full line if n2 and b2 are not set E.G
- Line 1 is “00011” or two broad pulses.
- Line 3 is “00110” or one broad pulse b1 and one short pulse n2.
- Line 4 is “01100” or two short pulses.
The above oscilloscope trace shows four signals, of relevance is the cyan a_cs line which is the analog CSync output. The trace was taken during an active VSync period covered by lines 311 to 318.5 in the original timing diagram, although lines 311 and 312 are off the screen to the left and lines 317+ are cut off to the right.
The initial long high pulse is the last bit of the first half of line 313 followed by going low for the second half of line 313 ending with a broad pulse. A total of 5 broad pulses occur which is the green field 2 start pulse section.
After the last broad pulse, there’s two short pulses which is line 316, the first of which follows very shortly after the last broad pulse of line 315.
In terms of cs_gate, line 313 is “01001”, a short pulse followed by a board pulse So for the non-interlaced mode this is switched to “01100”, two short pulses with the green broad pulses now starting on line 314+.
A couple of quirks remain to be solved.
The Electron outputs RGB with CSync via one connector and the other is plain old composite which includes, well, everything in a single signal/wire.
The core is currently outputting using CSync with the connection to the TV using Scart and 15.625kHz horizontal frequency as required by PAL.
CSync (composite sync) is a way to provide both H and V Sync on a single wire. A few other methods exist too.
In order to support monitor connections via VGA/DVI/HDMI separate H and V sync are needed as well as a horizontal frequency > 31kHz (although a few monitors do support 15.625kHz, most do not). A scan-line doubler will be needed to accomplish this as well as config options to switch between separate sync or csync.
With PAL working, I now have a way to provide a little debug output from the ULA by changing screen borders or the main fill colour. Not as flexible as using the simulator or chipscope, but useful in a pinch.
There’s quite a bit of detail I’ve skipped discussing in this post regarding the Electron’s graphics modes and how the ULA needs to pause the CPU in some modes, that’s for a future post. In the next blog post I’ll provide an overview of the Electrons hardware, specifically RAM, ROM and CPU.