_\~ /\ |\| |) /? () |\/| /\ /= /= | () |) ()
/homepage /list +normal

Contact: yt tw fb in mail git


Posts: [all] terminal ebook epub arduino esp8266 espvgax vgax game javascript php scifi obfuscated ioccc piano music book youtube curl

Arduino VGAX Library

vgaxA0

When i have bought my first Arduino UNO i have started to test some libraries for video signal generation. One of the first interesting library was TVOut. A simple lib that allow you to generate a COMPOSITE video signal out of an ATMEGA328 MCU, using only some resistors and a COMPOSITE video connector.

VGAX Inspirations

The first inspiration for VGAX come from TVOut library: A simple VGA library for Arduino that can work with simple cheap components!

Online i have found some interesting articles about Arduino VGA video signal generation, written by Nick Gammon. These articles and his works was the starting point for the development of my VGAX Library.

vgaxA0

My writing of VGAX was also inspired by the work of Petri Häkkinen, creator of the game TORUM QUEST II (for ATMEGA328!!). Here a link to his Blog. Here a link to his post on the Arduino Forum.

torum-quest Youtube Video

VGAX Assembler core

The creation of VGAX was a little tricky. I've spent many nights around the interrupt jitter problem, trying to adjust some dejitter code founds online.. An Hell!

To write the Assembler core of VGAX i've studied the official ATMEL ATMEGA328 Instruction Set Manual (190 pages), searching for the best instructions to generate the PIXEL stream output without losing too many CPU cycles. The idea was to use these instructions, for each byte of the framebuffer, inside an unrolled loop

.rept 30             // output 4 pixels (unrolled loop)
    ld r16, Z+       
    out %[port], r16 // write pixel 1 
    mul r16, r20     // left shift 2
    out %[port], r0  // write pixel 2
    mul r0, r20      // left shift 2
    out %[port], r0  // write pixel 3
    mul r0, r20      // left shift 2
    out %[port], r0  // write pixel 4
.endr                

The first good thing is that LD and MUL instructions require both 2 CPU cycles, so the output of the four pixels, packed inside a single byte, is done with the same number of CPU cycles for each pixel (3 cycles, LD=2, MUL=2, OUT=1). This equal timing ensures that all generated pixels will be displayed with the same size (horizontal width).

The second tricky thing is that the two VGA PINs are written with a single OUT instruction that writes an 8bits hardware PORT... but bits cannot be rearranged without losing time.. so the idea was to (pre)arrange the 4 pixels in one byte keeping the order of the bits aligned to the output pins of the 8BIT PORT. First pixel is stored in the higher 2 bits of byte.

pixel-packing

The hardware PORT uses the PIN from 0 to 7 so i have wired the two VGA PINs to PIN6 and PIN7.

PORT-wiring

When a byte is read from the LD instruction, the first pixel bits are already on the 6th and 7th bits, ready to be written out from the OUT instruction. The next MUL will shift the second pixel bits to the right position (6th and 7th bits of the PORT) and written out. This is repeated for the remaining two pixels.

ld r16, Z+       
out %[port], r16 // pixel1 bits are aligned on PORT 6th and 7th bits
mul r16, r20     // shift 2 pixel up
out %[port], r0  // pixel2 bits are now aligned

Resolution limitations

Many people ask me if is possible to increase the horizontal resolution of the VGA signal (120px).

Arduino ATMEGA328 has only 2048 bytes of RAM! The VGAX framebuffer have a resolution of 120x60px with 2bpp, almost all the MCU RAM is used (1800 bytes). This is the first limitation that cannot allow an increase of the horizontal resolution without losing color depth (2bpp). But there is another important reason that does not allow a greater horizontal resolution: the CPU speed!

ATMEGA328, inside Arduino, runs at 16Mhz. VGA signal require a 25Mhz PIXEL output speed. If you calculate the number of CPU cycles used to send PIXEL out you obtain this formula:

25Mhz : 640px = (16Mhz / 3clocks) : RES
RES = (640 * 5.3) / 25
RES = 136px~

So, the maximum resolution possible, at 16Mhz, using 3 CPU cycles for each pixel, is 136px! VGAX for ATMEGA328, with the dejitter code and the audio signal generation, reach a resolution of 120px for each horizontal line, near the maximum resolution possible.

Sharing

Here is hosted my VGAX Library, on GitHub. Here my post on the Arduino Forum.

This library was used from some people around the world. I thanks everybody for have spent some time using VGAX! Many thanks to Rob Cai that has recreated some classic games like Tetris, Pong and Breakout, using VGAX!

ct make

VGAX was reviewed in an article of the C'T MAKE newspaper, number of 03/2017. When i read this article i am always happy! :-)