Simulating VGA Signal

Anyone tried simulating a VGA signal using the Arduino?

I'm trying to use the Arduino for something similar to this:

but so far I have yet to succeed. Currently I do have some sort of a signal going, but my timing is off. My LCD monitor seems to detect a signal, and occasionally I get a quick flash of a red on the screen (I currently only have the Red signal driven).

the VGA Test Box (link, above) didn't quite give me enough accurate details, from my initial attempts, and I found the following that helped quite a bit:
http://www-mtl.mit.edu/Courses/6.111/labkit/vga.shtml
http://www.eecg.toronto.edu/~tm4/rgbout.html
http://www.eecg.toronto.edu/~jayar/ece241_05F/vga_new/index.html

I'm still working to try and at least get a steady red (or green/blue) screen signal, but in the meantime I was wondering if anyone here has tried simulating a VGA signal with the Arduino. If you have, any general suggestions/advice?

If a PIC can do it at 4MHz then the Arduino chip should have no problem at 16MHz. But the code you linked is in assembler and that application is only driving the VGA outputs. I think you would need to disable the timer0 interrupt (used for the millis counter) and use direct port i/o instead of digital write. It may be difficult getting the timing correct using C function calls so you may need to use assembler.

Good luck!

yes one problem I initially had was that digitalWrite was too slow, so I switched to using direct port manipulation. I'll try disabling timer0 for more accurate timing.

http://www.serasidis.gr/circuits/AVR_VGA/avr_vga.htm

Hello
I've coded exactly what you're looking for : http://olb7.free.fr/arduino/syncInterrupt.pde

640 * 480 @ 60Hz - FvSync = 60.3 Hz / FhSync = 31.3 kHz
HSync : pin 7 Arduino, pin 13 VGA
VSync : pin 6 Arduino, pin 14 VGA
Arduino's pin 5 is HIGH when video can be sent, LOW otherwise. I use it to power a transistor.

The sync routine is trigged by Timer2. You could achieve a slightly faster sync (31.5kHz) by using Timer1 instead. But it works well !

Keep us posted !

dwan, perhaps I am missing something, but it looks like your sketch is a sync generator but does not generate visible video. I wonder if Lt. Waffles can use your code as a framework and add in the display functionality from the code in westfw's link. What do you think?

BTW, does the millis interrupt on timer0 affected the sync pulse accuracy?

You're right, it only outputs sync signals. Nonetheless, it should be easy to obtain a steady color with minor modifications.

My code is only a stripped-down version of Max Ibragimov's, so it should be ok to display more complex things, if you can understand all Ibragimov's work (that's not my case :slight_smile: ). I only took what i needed and understood from his code, given it's not exactly Arduino code and i'm not a skilled coder.

Concerning the accuracy of the sync signal, there is a bit of horizontal jitter. It could be caused by Timer0, i did not tried to stop it. Sometimes the sync is very steady, sometimes it jitters. Actually, i'm trying to cram in the arduino the TLC540 library from acleone, which uses Timer1 & 2 with my code snippet, which I modified to use Timer0. Sadly, i also need a serial link. Each time the arduino receives data, it breaks the VGA sync. For now, i only plan to use 2 168's (one for the sync and the other for serial and TLC stuff), as it only add a few euros to the price of my project.

The code in westfw's link handles the serial port just after the vertical sync pulse and before the first visible line so incoming serial data shouldn't affect the display. But that means that the Arduino serial handler has to be disabled and replaced.

After disabling the millis timer and the Serial interrupt handler and using directo port io, there would not be much left of the arduino core code.

Right, that's why i'm looking towards C programming. By handling serial in a non-arduino style, do we lose any critical feature of the arduino?

By handling serial in a non-arduino style, do we lose any critical feature of the arduino?

If you use the approach in wesfw's link you lose the Arduino Serial runtime support
My guess is that implementing a vga driver to the OP's requirements would eliminate most of the Arduino functionality. You could use the arduino IDE to create and download the code, but I would think that the running code would not have access to any of the Arduino specific input/output or time functions.

My guess is that implementing a vga driver to the OP's requirements would eliminate most of the Arduino functionality.

I agree; I posted the link as an "existence proof" that it can be done, but generating video from an AVR is very "invasive" - it consumes the majority of the resources of the chip, and any "application" being run would need to be very carefully crafted and probably not very arduino-like. It might be interesting to see how much could be preserved, though...

I'm aware that this would use up most of the Arduino's resources - this is going to be an LCD interface module. The only thing I need to try and fit in is to read in a few bytes of data, either through serial or GPIO.

The problem is not using up the resources, its that the way the resources are implemented on the arduino that would make the display jumpy. Bypassing the arduino serial port and implementing one that was only active only during the period the video signal was not being displayed (using the logic in the code linked in post #3) would solve this, but it will not be easy to program.

how would I use NTSC for this?

You would need to modify the timing for 525 line 60Hz. although the specs for NTSC are easy to find, modifying the code to meet the specs is not a trivial project.

dwan, I tried running your code to see if it works. I connected pin 5 to the red pin on the VGA, and it started occasionally flashing a red screen. It seems like the timing is off.

I didn't modify your code, though, and according to you it shouldn't be outputting video at all? Is getting the occasional red frame the expected behavior?

edit: how do I disable all timers to ensure better timing?

Is your wiring ok ?
As a reminder :
// HSync : pin 7 Arduino to pin 13 VGA
// VSync : pin 6 Arduino to pin 14 VGA
// Arduino's pin 5 is HIGH when video can be sent, LOW otherwise. I use it to power a transistor.

My screen syncs fine with this sketch, actually.

You're right, this sketch does not output video, only the sync signals. The occasional red screen you get is not the expected behaviour. The expected behaviour is a black screen, and your screen's ability to display its OSD.

Nonetheless, Arduino's pin 5 tells you when you can send video by switching to its HIGH state ; it's 5 volt, that's much higher than the required video voltage : you should not wire it to a video pin of your screen ! If you want to send a plain color with this pin, you have to make its high state to 1v max, and its impedance to 75 Ohm. Take a look at this : http://images.electronicsinfoline.com/View/Photo/10001/Vga.gif
As the ECG2322 component is not made anymore, I use BC177 or BC557.

If you understand this sketch well, you've seen that the sync routine is done with the help of Timer2, so disabling the timers is not recommended. However, i suggest you to avoid using a serial link with this sketch, as it breaks the sync signals -only when receiving data.

Good news, I managed to get a steady signal going. currently have a solid red screen. It's currently 540am here, so I'm going to go get some sleep... will clean up my code and probably post it soon.

a quick overview: I didn't go with an interrupt driven approach for more control over the timing. The result is probably not the most elegant solution, more of trial and error with an oscilloscope, although after fixing the sync pulse and frame lengths, it was mainly a matter of putting them in the right place.

dwan, while I didn't use an interrupt approach, you code still was helpful in understanding how the vsync and hysncs were supposed to go together, so thanks!

You're welcome !
I'm curious about your code, as my own code was at first non-interrupt driven. I gave up because of the endless trial and error process and the inaccuracy of the timing I had.

Sorry to resurrect an old thread, but I've been trying to do this same thing, and have been having problems.
After a lot of searching, trial, error, and reinventing of wheels, my code ends up looking kind of similar to dwan's:

int LineCount=1;

#define HSYNC_PIN B00010000
#define VSYNC_PIN B00100000
#define RED_PIN   B00000010
//#define HSYNC_PIN 12
//#define VSYNC_PIN 13

void setup_pins()
{
      //set HSYNC,VSYNC pins to out. we use low level here so our HSYNC routine can go fast.
      DDRB = HSYNC_PIN | VSYNC_PIN | RED_PIN;
}
void setup_timer()
{
      cli();

      //I'll set registers in documentation order.
            //we want WaveformGenerationMode 0b0100 - CountThenClear on OCR1A
      TCCR1A = 0;
            //ClockSelect 0b001 - no prescale.
      TCCR1B = 1<<WGM22|1<<CS10;
            //508 cycles, about what we want. at 16MHz, 508 cycles is 31.75 us. the ideal is closer to 31.77 us.
      OCR1A = 507;
            //generate interrupt on OCR1A
      TIMSK1 = 1<<OCIE1A;

      PORTB=HSYNC_PIN | VSYNC_PIN;
      sei();
}

#define ten_nops __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t")
#define eight_nops __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t")

/*basically, we do this:
lines 0-9 front porch
lines 10-11 Vsync
lines 12-44 BackPorch
lines 45-524 ActiveVideo

so, the logic is, if we're on line 10, start vsync, line 12, stop vsync.
If we're in 45-524, do an hsync.
*/


ISR(TIMER1_COMPA_vect)
{
    //accordin' to [the address of dwan's code. I can't post it in my first forum post. :P], apparently, we want to HSYNC every line, not just active ones.
      if(LineCount == 10)
      {
            PORTB &= ~VSYNC_PIN;
      }
      if(LineCount == 12)
      {
            PORTB |= VSYNC_PIN;
      }

            //DO_HSYNC
      ten_nops;
      PORTB &= ~HSYNC_PIN;
      ten_nops;ten_nops;ten_nops;ten_nops;ten_nops;eight_nops;
      PORTB |= HSYNC_PIN;
      ten_nops;eight_nops;

            //generate a smiley face
      if (LineCount >= 80){
      if (LineCount < 220)
      {
            if  (LineCount < 200)
            {
                  ten_nops;ten_nops;ten_nops;ten_nops;
                  PORTB|=RED_PIN;
                  ten_nops;ten_nops;
                  PORTB&=~RED_PIN;
                  ten_nops;ten_nops;
                  PORTB|=RED_PIN;
                  ten_nops;ten_nops;
                  PORTB&=~RED_PIN;
            }
            else
            {
                  ten_nops;
                  PORTB|=RED_PIN;
                  ten_nops;
                  PORTB&=~RED_PIN;
                  ten_nops;ten_nops;ten_nops;ten_nops;ten_nops;ten_nops;ten_nops;ten_nops;ten_nops;eight_nops;
                  PORTB|=RED_PIN;
                  ten_nops;
                  PORTB&=~RED_PIN;
            }
      }
      else
      {
            if (LineCount < 240)
            {
                  ten_nops;
                  PORTB|=RED_PIN;
                  ten_nops;ten_nops;ten_nops;ten_nops;ten_nops;ten_nops;ten_nops;ten_nops;ten_nops;ten_nops;eight_nops;eight_nops;eight_nops;
                  PORTB&=~RED_PIN;
            }
      }
      }
      LineCount++;
      if(LineCount>524)
      {
            LineCount=0;
      }
}


//ok, signal magic done. happy fun arduino stuff now?

void setup()
{
      setup_timer();
      setup_pins();
}
void loop()
{
}

That code is close to working. I have a fairly new CRT monitor, and an LCD monitor. The CRT will display the image, but with some odd lines and artifacts. The LCD either wont, or with some fiddling, will flash the image every few seconds.

Do you think it's perhaps because the timing is not exactly right? or something else? At the moment, I have VGA pin 3 connected directly to Arduino 8, VGA 13 to Arduino 12, and VGA 14 to arduino 13. Could that be the problem? I'm aware that the sync lines are 5v, but the video should only be 0.7v. But, the video actually displays on the CRT, just with sync issues.

On the CRT monitor, The image is fairly stable, but every couple lines, the HSYNC seems to be off or something, because the whole line jumps a bit to the left, or a couple inches to the right. As I've gotten the timing closer (moved from timer2 to timer1, for 16-bit goodness), the # of off lines decreased, but they still exist.

edit: I put 1.6 KOhms of resistance in line with the video pin. It visibly dims the display quite a bit, but the syncing issues remain.