summaryrefslogtreecommitdiff
path: root/vga-sync/src/sketch.ino
blob: 438508da1784544293e3c5edf1b3971f5bcfa602 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
/* VGA Sync Generator
 * 11/11/08 - dwan : dwanafite@yahoo.fr
 *
 * Based on :
 *  - RG Matrix Example v.2 8/1/08, by BroHogan, from the Arduino Playground
 *  - Simplest universal VGA/PAL terminal, by Ibragimov Maxim Rafikovich, http://www.vga-avr.narod.ru/main.html
 *  - the very useful Timer/Counter/Prescaler Calculator, http://www.et06.dk/atmega_timers/
 *  - Arduino.cc Port Manipulation Tutorial
 *
 * This program outputs pretty accurate VGA syncronization signals. It's using a timer interrupt on timer2, so hopefully you can make other cool things in loop().
 */

// 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. See this wonderful page : http://www.anatekcorp.com/driving.htm
// 1 NOP = 62,5 ns wasted

#define NOP asm("nop")

#define vga_field_line_count 525         // number of VGA lines
#define ISR_FREQ 0x3F                    // Sets the speed of the ISR - LOWER IS FASTER - 62

volatile unsigned int linecount;

void setup()
{
  //Serial.begin(9600);         // set up Serial library at 9600 bps
  DDRB |= B00000111;
  DDRD |= B11100000;            // it sets pins 7, 6 and 5 as output without changing the value of pins 0 & 1, which are RX & TX
  //       76543210 <- pin translation

  PORTB |= B00000111;
  PORTD |= B11000000;   // sets pins 7 (hSync) and 6 (vSync) HIGH
  //        76543210;
  
  setISRtimer();                        // setup the timer
  startISR();                           // start the timer to toggle shutdown
}

void loop()
{ 
 
}

///////////////////////////// ISR Timer Functions ///////////////////////////
ISR(TIMER2_COMPA_vect)
{
        // Stop video
        // pin 5 LOW
        PORTD &= ~(1 << 5);
        
        // Front porch
        NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP;
        
        
        // Count number of lines
    if (++linecount == vga_field_line_count)
    {
    linecount = 0;
    }

    // can it be vsync tiem nao ?
    if ((linecount == 10 )||(linecount == 11 ))
    {
        // hsync LOW
        // vsync LOW
        PORTD &= ~(1 << 7);
        PORTD &= ~(1 << 6);
    }
    else    // ,hsync only
    {
        // hsync LOW
        // vsync HIGH
        PORTD &= ~(1 << 7);
        PORTD |= (1 << 6);
    }
    
    NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP;
    NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP;
    NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP;
    NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP;
       
        // nonetheless,
    // hsync HIGH
    PORTD |= (1 << 7); 
    
    NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP;
    NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP;
    NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP; NOP;
    NOP;
    
    // Start video if we are in a visible area
        if (linecount > 45)
        {
        // pin 5 HIGH
        PORTD |= (1 << 5);
        }
}

void setISRtimer(){  // setup ISR timer controling toggleing
  TCCR2A = 0x02;                        // WGM22=0 + WGM21=1 + WGM20=0 = Mode2 (CTC)
  TCCR2B = (1 << CS01);                 // /8 prescaler (2MHz)
  TCNT2 = 0;                            // clear counter
  OCR2A = ISR_FREQ;                     // set TOP (divisor) - see #define
}

void startISR(){  // Starts the ISR
  TCNT2 = 0;                            // clear counter (needed here also)
  TIMSK2|=(1<<OCIE2A);                  // set interrupts=enabled (calls ISR(TIMER2_COMPA_vect)
}

void stopISR(){    // Stops the ISR
  TIMSK2&=~(1<<OCIE2A);                  // disable interrupts
}