Saturday, 22 November 2014

Working on the anti-aliaser

I finally got around to plumbing the alpha-blender together to begin testing it for use with anti-aliasing text.

Not surprisingly, there are some things that aren't quite right. Primarily, Xilinx's reference implementation of an alpha blender doesn't quite seem up to the 192MHz pixel clock.  In particular, the blue channel is failing to meet timing closure, and seems to be delayed by a few pixels, as can be seen in the screen shots here:  


The displacement is a fixed number of physical pixels, as can be seen if I change the horizontal scaling of the text generator:



The timing failure isn't too surprising, given that the alpha blender uses a double-clock rate to multiplex the DSP operations to save a bit of silicon.  However, it means that the blender is effectively running at 192MHz x 2 = 384MHz. 

I think I will have to modify the blender so that it doesn't need to multiplex DSP blocks, and can hopefully then meet timing, and avoid the colour planes separating like this.

Wednesday, 19 November 2014

Proportional font glitches fixed

It is almost a week since I fixed some underlying faults in the hardware support for drawing proportional fonts, together with some bugs in my font file generator that was trimming the right-most pixels from some glyphs.

However, it is only tonight that I have managed to get the display working, because the character generator logic in the VIC-IV would seize up when trying to display variable-width full-colour characters. I eventually tracked the bug down to the paint_ready flag never being cleared if the VIC-IV was asked to draw a one-pixel wide 256-colour character.

This came about because the logic previously assumed that there would always be a 2nd-to-last pixel in a character, which is clearly not true when a character is trimmed to be just a single pixel wide.

Now that I have that fixed, I can finally draw variable-width anti-aliased* fonts.  The following two screen shots are of the same Unicode string being rendered using 10 point and 20 point versions of the same font. You can get an idea of the size of characters from the grid of junk at the bottom of each.



Again, the matrix-like tint is due to the colour-cube approximation of the VNC viewer I used to capture the image.  The characters look pure white on the VGA display.

Obviously the 20 point version (top) looks nicer than the 10 point version.  That said, to my wooden eye, they both look pretty decent.  The kerning looks acceptable, and both ascenders and descenders on characters are drawing fine.

I haven't optimised the unicode printing routine code at all yet, so it is still fairly slow to draw. Nonetheless, I can draw those several words in well under a frame, as can be seen in the following screenshot where I set the border to white while the drawing happens:


Earlier I said that I can now draw anti-aliased characters.  This is currently true only if I want to consume the entire 256-colour palette on fake alpha-values.  As discussed in earlier posts, I am part-way through implementing a real alpha-blender that will allow each character to be a different colour, and appear on a different background.

I also need to get around to implementing variable height characters, so that there are no large blank regions between lines when the upper rows of pixels in the top-most row of characters of a font are unused.

The other thing I hope to work on soon is to update the little programme I wrote to display the unicode text so that it can access fonts located outside of the first 64KB of RAM.  This will use the new 32-bit indirect zero-page addressing modes.  Then I will be able to display text from different fonts on the same display.



Sunday, 16 November 2014

First steps towards a C65GS laptop

From the outset I had thought about what form-factor the C65GS would have as a computer.

Basically it was a question of whether to make it something that looks and feels like the original C65, or whether to make it into a laptop.

Nostalgia said that something that looked like the original would be nice.  However, the realisation that being able to create 3D-printed or injection moulded replicas of the C65 case would be extremely expensive put a dampner on that idea.

Also, as I got working on the C65GS I found myself increasingly desiring a portable computer - both for taking places to show and so that it could be used for some light general productivity.

So I have been thinking about how to do this, and taking a look at what some other very clever people have done in the past.  The most interesting one is this laptop commodore 64, made using original parts.  This is interesting to me, because it was created using a real C64 keyboard, and he fabricated the case parts himself.  While I don't plan to use a real C64 keyboard for mine, I do intend to use the real C65 keyboard I bought on ebay recently.  Fortunately, the C65 keyboard already has the function keys moved to the top, and so is narrow enough to be used unmodified in a 15" laptop.

More of how Ben fabricates custom cases like this is covered in another post of his.

However, before I get to that point, I need to work out exactly what I intend to cram into the thing.

Obviously the Nexys4 FPGA board needs to go in.

I have already sourced 4 x 30Wh LiFePO4 rechargeable batteries, sufficient to skirt the air-line limits in several countries, but also enough to run a bright screen for a few hours at least.  I'll need to find a charger circuit for them, perhaps something like this that should allow me to put 15.6V in and charge the batteries.  The output from the batteries then can be fed into one of these to provide enough 12V for a 15" LCD panel, and a very similar one of these to provide ample 5V for the FPGA board and related circuitry.

I had originally looked for a 13" 1920x1200 panel, but those are rare as hens teeth, so have settled for a 15.4" one.  After a bit of hunting it looks like this panel and this LCD driver kit should work together, and will accept the 1920x1200 60Hz VGA signal from the FPGA board.

This leaves the joystick/keyboard/IEC serial and other ports, plus speaker driver PCB as the great unknown in terms of internal components. However, even without that PCB, I am starting to have a think about how things would be arranged in the eventual case.

I will probably use a similar approach to Ben's portable C64, and have an external lead that connects the panel in the top half of the case to the lower half.  Because I am using VGA connections, I am contemplating making the cable easily removable, at least from one end, so that it is easy to connect to an external monitor, or indeed use the 15" panel as a VGA display for something else when required.

I might buy a panel and LCD driver kit just to get my head around getting those working together and with the FPGA board, and then incrementally work on everything else as I get the opportunity.

Friday, 14 November 2014

Migrating to Vivado (Part 3)

Vivado is still refusing to synthesise the various BRAM blocks correctly.

I have, however, had a response to my post on the Xilinx Community Forums asking for more information about the problem, which I have provided.

Let's hope that they can suggest a solution.

Thursday, 13 November 2014

Migrating to Vivado (Part 2)

The title says it all.

I have managed to massage the C65GS source so that it synthesis in Vivado.

This involved some silly things that Vivado should really support, like casting ports in a module. Don't worry about what that means. Just understand that it is something really simple, and Vivado chokes on it.

However, that dwarfs into insignificance with the real problem: Vivado fails to detect when to use BRAM (the little RAM blocks in the FPGA), and instead tries to implement them using logic.  This means that Vivado thinks I need an FPGA 5x bigger than I have, even though ISE can synthesise it to fit in less than 1/2 the current one.

Oddly, it does realise that two small memories should be BRAMs, as the following output from Vivado shows (you might need to make your display really wide to see the gory detail).

Start RAM, DSP and Shift Register Reporting
---------------------------------------------------------------------------------

Block RAM:
+------------+-------------------------+------------------------+---+---+------------------------+---+---+--------------+--------+--------+------------------------+
|Module Name | RTL Object              | PORT A (depth X width) | W | R | PORT B (depth X width) | W | R | OUT_REG      | RAMB18 | RAMB36 | Hierarchical Name      | 
+------------+-------------------------+------------------------+---+---+------------------------+---+---+--------------+--------+--------+------------------------+
|framepacker | thumnailbuffer0/ram_reg | 4 K X 8(READ_FIRST)    | W |   | 4 K X 8(WRITE_FIRST)   |   | R | Port A and B | 0      | 1      | framepacker/extram__26 | 
|viciv       | rasterbuffer1/ram_reg   | 2 K X 9(READ_FIRST)    | W |   | 2 K X 9(WRITE_FIRST)   |   | R | Port A and B | 1      | 0      | viciv/extram__42       | 
+------------+-------------------------+------------------------+---+---+------------------------+---+---+--------------+--------+--------+------------------------+

Note: The table shows RAMs generated at current stage. Some RAM generation could be reversed due to later optimizations. Multiple instantiated RAMs are reported only once. "Hierarch
ical Name" reflects the hierarchical modules names of the RAM and only part of it is displayed.
Distributed RAM: 
+--------------+--------------------------+--------------------+----------------------+--------------------------------+----------------------+
|Module Name   | RTL Object               | Inference Criteria | Size (depth X width) | Primitives                     | Hierarchical Name    | 
+--------------+--------------------------+--------------------+----------------------+--------------------------------+----------------------+
|gs4510        | shadowram0/ram_reg       | Implied            | 128 K X 8            | RAM256X1S x 4096               | gs4510/ram__25       | 
|iomapper__GC0 | kickstartrom/ram_reg     | Implied            | 16 K X 8             | RAM256X1S x 512                | ram__26              | 
|framepacker   | videobuffer0/ram_reg     | Implied            | 4 K X 8              | RAM64X1D x 128  RAM64M x 128   | framepacker/ram__28  | 
|ethernet      | rxbuffer0/ram_reg        | Implied            | 4 K X 8              | RAM64X1D x 128  RAM64M x 128   | ethernet/ram__29     | 
|ethernet      | rrnet_rxbuffer/ram_reg   | Implied            | 4 K X 8              | RAM64X1D x 128  RAM64M x 128   | ethernet/ram__30     | 
|ethernet      | txbuffer0/ram_reg        | Implied            | 4 K X 8              | RAM64X1D x 128  RAM64M x 128   | ethernet/ram__31     | 
|sdcardio      | sdsectorbuffer0/ram_reg  | Implied            | 512 X 8              | RAM64X1D x 16  RAM64M x 16     | sdcardio/ram__32     | 
|sdcardio      | sdsectorbuffer1/ram_reg  | Implied            | 512 X 8              | RAM64X1D x 16  RAM64M x 16     | sdcardio/ram__33     | 
|sdcardio      | f011sectorbuffer/ram_reg | Implied            | 512 X 8              | RAM64X1D x 16  RAM64M x 16     | sdcardio/ram__34     | 
|uart_monitor  | membuf_reg               | Implied            | 16 X 8               | RAM16X1S x 8                   | uart_monitor/ram__35 | 
|uart_monitor  | historyram0/ram_reg      | Implied            | 1 K X 177            | RAM256X1S x 708                | uart_monitor/ram__37 | 
|viciv         | chipram0/ram_reg         | Implied            | 128 K X 9            | RAM128X1D x 9216               | viciv/ram__38        | 
|viciv         | colourram1/ram_reg       | Implied            | 64 K X 8             | RAM128X1D x 4096               | viciv/ram__39        | 
|viciv         | paletteram0/ram_reg      | Implied            | 1 K X 32             | RAM256X1S x 128                | viciv/ram__40        | 
|viciv         | charrom1/ram_reg         | Implied            | 4 K X 8              | RAM256X1S x 128                | viciv/ram__41        | 
|viciv         | sprite_x_reg             | Implied            | 8 X 8                | RAM16X1S x 8                   | viciv/ram__42        | 
|viciv         | sprite_data_offsets_reg  | Implied            | 8 X 6                | RAM32M x 1                     | viciv/ram__43        | 
|viciv         | sprite_colours_reg       | Implied            | 8 X 8                | RAM16X1S x 8                   | viciv/ram__44        | 
|viciv         | sprite_y_reg             | Implied            | 8 X 8                | RAM16X1S x 8                   | viciv/ram__45        | 
|viciv         | buffer1/ram_reg          | Implied            | 512 X 8              | RAM64X1D x 16  RAM64M x 16     | viciv/ram__46        | 
+--------------+--------------------------+--------------------+----------------------+--------------------------------+----------------------+

All the rest are being implemented as various types of fabric-based RAM.

I have asked for help on the Xilinx Community Forums to see if anyone knows whats going wrong, and how I can work around it.

But for now, it looks like I am using ISE for a bit longer still.

Monday, 10 November 2014

Migrating from ISE to Vivado (Part 1)

I am in the process of attempting to migrate C65GS development from Xilinx's old ISE development environment to their new Vivado.  The promise is a much better synthesis tool chain, with shorter synthesis times, better timing, and it should be easier to describe timing constraints which are a black art in ISE.

Vivado is only a couple of years old, which means that it is still quite unstable as these things go.

Just getting it to install can be interesting.

After downloading the 4.8GB (!) tarball, extracting it and running the xsetup program, it got stuck showing just the splash startup window.

Fortunately I was able to find the solution in the following thread:

http://forums.xilinx.com/t5/Installation-and-Licensing/Vivado-hangs-forever-with-white-window-during-startup-Linux/td-p/479058

Basically it boils down to setting the following shell variable, ideally in your .bashrc or similar ( don't forget to log out and in again or source the file for it to take effect after you have changed it).

export _JAVA_AWT_WM_NONREPARENTING=1

I am unable to comment on why this works, but simply confirm that it lets me at least see the installer.

Now to see if installation works ...

Even more progress on proportional fonts

Hot on the heals of the earlier fixes of the evening, descenders (the bits of characters that hang below the base-line) and bits poking out the top are now correctly draw as can be seen in the screen-shot below.

Along the way I have fixed bugs in my unicode printing programme, and also a couple of bugs in my true-type font rasteriser (the top pixel of characters could be chopped off, and character tiles were being written to the file in the wrong order).

As with the other screen-shots, the Matrix-like green tint is an artefact of the image capture process I am using, and the bad kerning is pending a patch to the FPGA so that it stops ignoring the least significant bit of the kerning field of each character.

Once the horizontal kerning has been fixed, that just leaves the vertical spacing to fix.  This will probably require both FPGA and more font-file format tweaking.


The above image is captured the same way as the one in the previous post. Then I realised that my VNC viewer was scaling the image, so below is the same image really without any scaling:




Just for further fun and to prove that it works for larger font sizes, I produced a 24 point version of the same font to try out:


This revealed a few new glitches, like why is the "t" in jupiter mostly missing.  There are also some other issues, like the width of the right vertical of "H", Alef (the right-most Hebrew character) that I will have to look into.

The disappearing "t" turned out to be a quick fix, so the final result for the night is as follows:


 Note also that with a big font the suppression of the spare blank raster lines becomes less important.  I still intend to fix it, however.