Close
0%
0%

RA8875 VGA

Let's use a LCD driver to drive a VGA monitor. It sounds fun.

Similar projects worth following
The RA8875 is a fairly cheap IC for driving LCD screens. It has a nice library built by Adafruit, and has decent support. It is cheaper and requires no programming, compared to an FPGA, which is often used to drive VGA. Perhaps it is better to use a modern LCD driver IC to create a VGA signal? Let's find out!

It is common to use FPGAs to create a VGA signal for a given project.  There are several issues with this:

  1. The FPGA must be configured
  2. The FPGA configuration may not provide a standard protocol
  3. Speed limitations due to it not being "real" hardware
  4. Higher cost

We can also use microcontrollers, like the Parallax Propeller, but these are limited by memory, and implementing the behavior in software often creates a lot of limitations.  It is clear that some dedicated video chip should be used.  Ideally, it should be cheap, fairly standardized, and capable.  As it turns out, the RA8875 seems to meet these requirements, and I'd guess other chips may as well.  To my knowledge, there are very few dedicated VGA chips that meet these requirements.

It makes sense that an LCD driver IC would work so well: devices needing these sort of chips are mass produced and have been for over a decade.  Generally, devices needing these ICs have lower resolutions and are sold for lower prices, so the chips more fit our needs for a simpler and cheaper video output.

Will it actually work?

The RA8875 provides the needed HSYNC and VSYNC signals for VGA - I would assume that driving and LCD monitor, from a protocol perspective, is not different from any other video protocol in using HSYNC, VSYNC, and video timing.  Essentially, the RA8875 just sends a stream of color data, very much similarly to CRT scanning behavior.  As far as I can tell, there are no important differences, and when configuring the RA8875, similar timing parameters to that of VGA must be specified, namely the width of various video periods.  In fact, the protocol somewhat reminds me of the uPD7220's protocol - see my project on that chip, where I did something similar: #uPD7220 Retro Graphics Card (and VGA hack) 

In short, I can see no reason this wouldn't work.  The only catch, is that a few other chips are needed to adapt it to work for VGA:

  • THS8135PHP - This converts the digital color from the RA8875 to the analog color needed for VGA
  • 74ALVC164245DDG - Level shifts the RA8875's 3.3v logic to 1.8v, required for the THS8135PHP
  • Other logic: configures polarity of HSYNC and VSYNC, more level shifting, 1.8v regulation

A multifunctional PCB

Since the RA8875 is an LCD driver, I can make one PCB design that can be used for driving an LCD, or providing a VGA signal.  The hardware and software interface to a microcontroller does not change.

The board design I'm making for this project has an 8-bit parallel interface compatible with my #Z80 overpowered computer, as this bus is the standard I'm using for everything now.  The board also has an ESP32, which is optional - this way the board can be used stand-alone, or to implement a software defined keyboard (more on that in a different project).  And, of course, an LCD interface can be used instead of VGA if desired.  This board is basically designed to be assembled a-la-carte for whatever needs a project has.

Brief RA8875 Specifications

  • Up to 800x480 pixels
  • Both 8-bit parallel interface and SPI interface available
  • 768KB internal RAM
  • Hardware accelerated drawing of shapes, and two fonts provided for faster text drawing

These specifications are part of the reason I would want to set up a VGA driver this way - this is a very powerful IC that isn't that difficult to use in a project, and seems somewhat flexible.

Adafruit has an RA8875 breakout and some nice screens to go with it - I rather like it.  Only complaint is that they don't have one with capacitive touch :P - in any case, my favorite setup so far is an Adafruit 7.0" touchscreen, the RA8875 breakout, and a manually added 7.0" GT911 capacitive touch panel, which I got off of Ebay, and fit perfectly. Now I am going to roll my own board for a nicer project, and more control over the design.  And, of course, to support VGA!

RA8875_graphics_device_v1.1.zip

KiCAD files for the version that actually works right

Zip Archive - 792.69 kB - 09/03/2024 at 17:36

Download

RA8875_graphics_device_v1.0.zip

KiCAD files for the first version of the board

Zip Archive - 710.88 kB - 08/04/2024 at 00:32

Download

  • Text is looking good :)

    Dylan Brophy08/15/2024 at 03:36 0 comments

    I've got the #Arduino Desktop running the card and a keyboard, so I have an actual interface/prompt now.  The text is looking pretty good, but there are streaks from the text so there must be something messed up in the video signal.

    There is some trailing white blur after the text, so I wonder if the voltage on the RGB lines is not dropping as fast as it should or something.  Here I ran some commands to test out the text.

    Just last night or so I didn't even have the pixels working right, and to be completely honest, I have no idea exactly what made the pixels want to show up.  My theory is that adding a software reset before initialization fixes it, but I don't really know, and due to the nature of resets it's not the easiest thing to test.  Whatever, it works, and it seems to work consistently.  Here's the reset code:

    writeCommand(RA8875_PWRR);
    writeData(RA8875_PWRR_SOFTRESET);
    writeData(RA8875_PWRR_NORMAL);
    bootloader_delay(1);

     Now, when I did get the pixels working, it was still messed up:

    It's hard to tell in the picture, but the pixels are not exact and kinda messed up.  The video quality also changed when I touched the back of the board, which would seem to indicate a signal integrity issue.  In fact, it seemed that many of the pixels were dropped completely, but there was a pattern to it, so the text was still somewhat legible.  I thought the RA8875's connections to the PCB must have been bad, which made *some* sense, since I had replaced the RA8875 chip twice and there wasn't much solder left on the pins.  I checked this, and the video did look a little better, but it still was wrong.  I decided to try changing the pixel clock polarity, and this fixed the problem.  Again, the relevant code:

    GraphicsDisplayDevice* initVideoCard(ParallelBusDevice* bus) {
      timing_params_t timing;
    
      timing.pixclk = RA8875_PCSR_PDATR;
      timing.hsync_nondisp = 88;
      timing.hsync_start = 40;
      timing.hsync_pw = 128;
      timing.hsync_finetune = 0;
      timing.vsync_nondisp = 23 + (600 - 480) / 2;
      timing.vsync_start = 1 + (600 - 480) / 2;
      timing.vsync_pw = 4;
      timing.voffset = 0;
      timing.width = 800;
      timing.height = 480;
    
      // SYSCLK = ((PLLC1 & 15) + 1) * 20Mhz / 4
      // For PLLC1 = 7, SYSCLK = 40Mhz
      timing.PLLC1 = RA8875_PLLC1_PLLDIV1 + 7;
    
      return new RA8875Parallel(bus, &timing);
    }

    This is the correct code to make the RA8875 output a valid 800x480 VGA signal.  I based it on my experimentation, and on the tinyvga site, which is a great resource by the way:  http://tinyvga.com/vga-timing/800x600@60Hz

    The timing I'm using is for 800x600, but I lengthened the vertical porches to make up the difference in y resolution.

  • Drawing (badly) to VGA Monitor!

    Dylan Brophy08/14/2024 at 04:01 0 comments

    So, my design idea WILL work!  I did have my doubts, but it turns out it will actually work.  Here is what it's drawing, which should be text, but clearly isn't:

    There is this white strip, which is basically a rectangle where the text should be - like it's filling it.  I don't know exactly why it's doing this yet, but it probably has to do with my setPixel routine, which is used for drawing the font:

    void RA8875::setPixel(int x, int y, uint16_t color) {
    	// The actual pixel write code doesn't draw anything at all
    	/*writeReg16(RA8875_CURH0, x);
    	writeReg16(RA8875_CURV0, y);
    	writeCommand(RA8875_MRWC);
    	writeBytes((char*)&color, 2);*/
    
    	// At least this draws *something*
    	fillRect(x, y, x, y, color);
    } 

    The setPixel should write directly to the display memory, but for some reason the direct write to memory is not working.  So I decided I would try just drawing rectangles to temporarily solve this issue, which clearly didn't work either.  I'm still investigating it, but from the looks of it, the corner of the rectangle is probably always starting at coordinates 0, 0 for some reason.  Here's the related code:

    void RA8875::fillRect(int x1, int y1, int x2, int y2, uint16_t color) {
    
    	int x = min(x1, x2);
    	int y = min(y1, y2);
    	int w = abs(x2 - x1) + 1;
    	int h = abs(y2 - y1) + 1;
    
    	// I'm suspicious of 16-bit register numbers not divisible by zero...
    	writeReg16(0x91, x);
    	writeReg16(0x93, y);
    	writeReg16(0x95, w);
    	writeReg16(0x97, h);
    	writeColor24(color);
    
    	writeReg(RA8875_DCR, 0xB0); // Use 0x90 if you just want to draw the edges
    
    	// Wait for the command to finish
    	waitPoll(RA8875_DCR, RA8875_DCR_LINESQUTRI_STATUS);
    } 

    Really, none of this seems out of the ordinary other than the odd register numbers.   I'll need to study the datasheet a bit more.

    The important part, is that the design fundamentally can work.

    The main thing I was missing since last log, was that I didn't turn on the display in my code.  I thought this was just for the LCD backlight driver, but turns out there won't be any color without turning the display "on" either.  I guess that sorta makes sense, although it is strange that it would still send the sync signals without the color data.  Again, here is the relevant code:

    writeReg(RA8875_PWRR, RA8875_PWRR_NORMAL | RA8875_PWRR_DISPON);

    This code was based on Adafruit's RA8875 library, which works great if you are using a SPI interface.  This code also seems related to this repository, and I am not sure how they are related, but it is another good repository to look at for RA8875 driver code, and really any LCD driver - there are a LOT of drivers supported: https://github.com/ZinggJM/GxTFT/blob/master/src/GxCTRL/GxCTRL_RA8875P/GxCTRL_RA8875P.cpp

    I integrated ideas from both of these sources, as well as added/modified some of my own.  I felt they both deserve credit, and also are just good reference points for anyone else.  If you are interested in the driver I am writing, the source is here: https://git.nuclaer-servers.com/Nuclaer/ntios-2020/-/blob/cb48037977205ada23a78f7c474f36f2d2665fa2/drivers/graphics/ra8875.cpp

    The commit, as of this log, is 14837b6.

  • It's Alive!

    Dylan Brophy08/13/2024 at 03:43 0 comments

    I have successfully connected the new board to the new Teensy-based #Arduino Desktop, and although I do not have a *valid* signal yet, I do have a signal, and the data exchange is working :-)

    Obviously, at this point, I have assembled the PCB.  There was a PCB bug, screwing up the direction of the level translator, but after fixing this I was able to communicate with the RA8875.

    Based on the Adafruit RA8875 library (https://github.com/adafruit/Adafruit_RA8875), it seems we can query register 0 and should expect 0x75 to be returned, to confirm proper connection.  Sure enough, this worked exactly.  After this, we can initialize the video registers.  I just used Adafruit's settings for their 480x800 displays. At some point while loading the registers, the attached monitor woke up and told me the signal was invalid - which indicates that I am actually sending at least the sync data over the wire, even if incorrectly!

    This all was after connecting the RA8875 IC backwards, of course.  Well, it still worked after I flipped it despite this abuse, so I'm grateful.

    The next thing for me to do is write a small library for talking to it, or perhaps a library for #NTIOS. The initialization sequence doesn't look too complex, if anything it will just be difficult to get the right settings.

  • Board Assembly

    Dylan Brophy08/09/2024 at 21:53 0 comments

    I'm assembling a prototype for this board, which *hopefully* will provide working VGA output:

    Circuit board assembly on my kitchen table

    I'm missing just three components, which includes the video DAC, so sadly I will not be able to test until tomorrow.  I just want to get it rather close to assembled today, to get ahead of it.  I created my cart on mouser, and forgot to check out, until I realized I was missing something; you know how it goes.

    I'm configuring this one for VGA only, so I'm not installing any of the LCD circuitry, like the backlight driver or LCD/CTP connectors.  I'm going to connect it to my #Arduino Desktop, so the ESP32 will not be needed either.  Altogether, this assembly will be rather simple.  Soon I'll also assemble one for LCD only; hopefully everything works perfectly.

View all 4 project logs

Enjoy this project?

Share

Discussions

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates