Friday, March 15, 2013

AVR VGA Generation

I have always wanted to create a VGA generator. It has been a personal goal of mine for some time. Over the past couple of weeks I toyed with the idea and finally decided to implement one. I decided to implement it as a framebuffer to allow for general purpose display rather than application specific display. I implemented my own small colour gamut to be memory and CPU efficient.

I have made the source code available on Github.

Daft Punk from Tron Legacy
VGA Controller on a Breadboard

 The first thing I did was order some new AVRs. I ordered the ATmega1284p because it has 16kB of RAM and 128kB of program memory. My original idea was to clock the MCU at 20MHz. I successfully created an H_SYNC and V_SYNC generator at this clock rate but found it difficult to implement the frame buffer properly. When the chip is clocked at 20MHz, there are only 508 cycles per line of active video. According to the VGA specification the pixel clock is 25.175MHz. I decided to overclock my microcontroller to 25MHz to get 640 clock cycles per line. This makes the code cleaner and allows for a higher resolution frame buffer.

The AVR Logo

Designing the Colour Space

The next step was to decide on a colour gamut. I needed something that I could write out to the I/O pins very quickly and also be memory efficient. I decided to implement RGB222. This is a simple and small colour gamut with 2^6 = 64 colours. There are two bits for each Red, Green and Blue. The two remaining two bits are unused.
RGB222 Byte
You might argue that I should assign bits 6 and 7 to either of the 3 channels, but I decided not to do this. I decided that it would make the creation of grey colours more difficult. This colour space allows for 1 byte per pixel. Since the AVR allows for single-cycle writes to the 0th page of RAM, I can also output this colour in a single instruction. This allows me to hit the theoretical 25MHz pixel clock. Woohoo!

I implemented the palette in Gimp so that I could index images and apply dithering. You can download a copy of the palette below if you would like to experiment with it. This palette is compatible with both Gimp and Inkscape.


Designing the Framebuffer

I have 16kB of RAM to work with and I must keep the aspect ratio of the frame buffer 4:3. It would also be beneficial if horizontal could divide into 640 and vertical could divide into 480 evenly. I crunched some numbers using one of my favourite tools, WolframAlpha, and decided that 128x96 was my best bet. A frame buffer of this size requires 12288 bytes of RAM. It allows 5 instructions for drawing each pixel and requires that each line be drawn 5 times.

To make this RGB222 color space come to life I had to design a DAC. I decided to use a weighted R/R2 DAC, taking into account the input impedance of the monitor (75 ohms). I end up with a circuit as shown below. There are three of these circuits connected to one of the 8-bit ports on the microcontroller.
One of the 3 DACs

DAC Assembled on a Breadboard
 In practice, I decided to use 470 and 220 ohm resistors. This isn't ideal, it applies a skew to the colour space. Ideally these resistors would be low tolerance.

Implementation in Software

The entire VGA generation and buffer is implemented in assembly under the GNU toolchain. I decided to implement the active video region as an unrolled loop that I include in the main assembly file. It takes 2 instructions to write one pixel to the display and 2 padding nops. The ld takes 2 cycles which comes to a total of 5 cycles.

ld r18, Z+
out r18

The H_SYNC and V_SYNC are a series of software delays. The current version has no provision for dynamic graphics. This is something that I will be working on in the future.

Displaying an Image

I have written a crude program in C# to convert an indexed image to the binary format accepted by the microcontroller.

The first thing the CPU does after it boots is copy image data into the frame buffer memory. After this, the standard VGA generation routines continuously draw this frame out on the VGA lines.

Next Steps

My next goal is to implement a command set that is active during the vertical blanking interval. I would like to allow another microcontroller to send commands to this VGA controller such as set pixel. This would allow for dynamic graphics to be generated.


  1. Why not put both extra bits into the G channel? This gives you enhanced color depth where the human eye will most notice it but still allows your matched greys.

    1. I had considered the fact that the eye is most sensitive to green light, but didn't consider assigning both bits to the green channel.

      Good idea!

    2. dường như cũng giống như nàng, đều có một chủng hương vị rất dễ chịu, mà trên người hắn còn truyền đến từng tia khí tức mát lạnh khiến nàng cảm giác rất khoan khoái.

      Sau vài phút, Tôn Hinh Hinh đột nhiên cảm thấy có chút gì đó là lạ, dường như mọi người đều đang nhìn nàng, mà mấy người bên cạnh còn đang nhỏ giọng bàn tán.

      - Tên này thật là 'Trâu'!

      - Là lợi hại, chắc là luyện qua kungfu? Hạ bàn cũng rất chắc chắndongtam
      game mu
      nhạc sàn
      tư vấn luật
      dịch vụ thành lập công ty trọn gói
      công ty luật
      tổng đài tư vấn pháp luật
      thành lập công ty
      chém gió
      trung tâm ngoại ngữ.

      - Đúng thế, thật như là không bao giờ ngã vậy.

      - Ta đã nói nhìn hắn thế kia thì làm sao có thể cưa được mỹ nữ cơ chứ, hóa ra là thâm tàng bất lộ!

      Mới đầu Tôn Hinh Hinh còn tưởng rằng mục tiêu của nhưng người này là nàng, nhưng nghe một lúc lại phát hiện dường như những người này đang bàn tán về Hạ Thiên, nàng nhìn một chút bốn

  2. A nice solution I saw before was instead of using them as colours use them as brightness; so the 4 possible values give 4 levels of brightness for each of the 64 combinations of colours -- however I think it complicates the DAC layout somewhat.

    Interesting project; I think VGA is a lot nicer than composite; You must have seen the uzebox project by now?

  3. This comment has been removed by the author.

  4. I make an assembler project using avrstudio 5
    and included all the project files
    when I build the Project
    it give me that error
    invalid entry file , value cannot be null

    Any ideas ?

    1. Hi Mohammad,

      I am unsure of why you would get this error. You I suspect that the error message you have posted is truncated. Is there any indication of line number that this error occurred on?

      I know that AVR Studio will include its' own header file (for register definitions). You may need to remove this.

    2. This is the Project I have Created

      If you can help me with the error I will be very glad for that
      Thanks :)

    3. Finally I Solved the Entry File Problem
      But there are some errors in the assemply code in main.s
      You must use = operatot when you use .equ instruction
      I Edited that
      what about your code
      is it compiled and rub without the = operator ?

    4. I have no idea what assembler you are using. I assume something AVR Studio (which is potentially GNU). The code I have posted assembles on my system (Arch Linux).

  5. You could use remainding 2 bits left from RGB222 (RRGGBBxx) as intensity bits (RRGGBBII), similar trick to what old ZX Spectrum did. That way you get 256 colors with correct grays as you would expect. Implementation is quite simple, and can be seen for example here:

  6. Hi,
    your project inspred me to do something similar on a beefier hardware (Beaglebone Black). Thanks for sharing the idea!

  7. Hii can you have all project in atmel studio? because i don't know about linux and it command. if you have project in atmel studio than please send it to my following email address.

  8. عند التواصل مع شركة لتنظف المنازل فى السعوديه يجب عليك كعميل ان تتأكد من عده عوامل يجب تتوافرها كالخدمة المطلوبه ومساحة المنزل المراد تنظيفه وهل توجد مناطق معينه يجب التركيز والعمل عليها بكثره داخل المنزل , ماهي نوعيه المواد المستخدمه فى العمليه , هل يتطلب الامر ان يتم نقل الاثاث الي خارج المنزل أم لا ؟ وهكذا.
    شركات تنظيف بالرياض
    أيضاً يجب الحصول علي رأي افراد الاسره او الاصدقاء , هذا لان تعيين شخص لتنظيف منزلك ليس امراً عليك القيام به على عجله من امرك وتذكر ان الاناس الذين توظفهم للدخول الى بيتك وتنظيفه قد لا يكونون جديرين بالثقه إذا كانت الشركه التي تعينهم لم تخضع الي فحص واجراء تراخيص اللازمه للقيام بثل هذه الاعمال. وسيكون من الافضل الاستماع الي أراء الاناس الذين استخدموا خدمات هذه الشركات من قبل وهذا قد يعطي تلميحاً عن اي نوع من الخدمه ستتوقع من تلك الشركه ويفضل الاستماع الي 3 اراء على الاقل لتصل الي قرار فى اختيار الشركه المناسبه.

    بعض الحوادث قد تقع اثناء القيام بعمليه التنظيف وهذا نتيجه بعض الاخطاء التي ممكن حدوثها , لذلك لا تثق ولا تتعامل مع شركه تنظيف لا تملك تصاريح وتراخيص وتأمين كامل لجميع الاضرار , إختيار الشركه التي تتحمل مسؤليه جميع الحوادث والاخطاء لها الافضليه والاولويه , بالاضافه الي الاتصال والتأكيد على انه تم عمل فحص لجميع الافراد الذين سيتواجدون داخل منزلك والتحقق من بطاقات (إثبات الهويه).