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.