Advertisement
sspence65

Arduino Color VGA

Nov 25th, 2013
401
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 6.14 KB | None | 0 0
  1. /*
  2.  VGA colour video generation
  3.  
  4.  Author:   Nick Gammon
  5.  Date:     22nd April 2012
  6.  Version:  1.0
  7.  
  8.  Version 1.0: initial release
  9.  
  10.  Connections:
  11.  
  12.  D3 : Horizontal Sync (68 ohms in series) --> Pin 13 on DB15 socket
  13.  D4 : Red pixel output (470 ohms in series) --> Pin 1 on DB15 socket
  14.  D5 : Green pixel output (470 ohms in series) --> Pin 2 on DB15 socket
  15.  D6 : Blue pixel output (470 ohms in series) --> Pin 3 on DB15 socket
  16.  D10 : Vertical Sync (68 ohms in series) --> Pin 14 on DB15 socket
  17.  
  18.  Gnd : --> Pins 5, 6, 7, 8, 10 on DB15 socket
  19.  
  20.  
  21.  Note: As written, this sketch has 34 bytes of free SRAM memory.
  22.  
  23.  PERMISSION TO DISTRIBUTE
  24.  
  25.  Permission is hereby granted, free of charge, to any person obtaining a copy of this software
  26.  and associated documentation files (the "Software"), to deal in the Software without restriction,
  27.  including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
  28.  and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
  29.  subject to the following conditions:
  30.  
  31.  The above copyright notice and this permission notice shall be included in
  32.  all copies or substantial portions of the Software.
  33.  
  34.  
  35.  LIMITATION OF LIABILITY
  36.  
  37.  The software is provided "as is", without warranty of any kind, express or implied,
  38.  including but not limited to the warranties of merchantability, fitness for a particular
  39.  purpose and noninfringement. In no event shall the authors or copyright holders be liable
  40.  for any claim, damages or other liability, whether in an action of contract,
  41.  tort or otherwise, arising from, out of or in connection with the software
  42.  or the use or other dealings in the software.
  43.  
  44. */
  45.  
  46. #include <TimerHelpers.h>
  47. #include <avr/pgmspace.h>
  48. #include <avr/sleep.h>
  49.  
  50. const byte hSyncPin = 3;     // <------- HSYNC
  51.  
  52. const byte redPin = 4;       // <------- Red pixel data
  53. const byte greenPin = 5;     // <------- Green pixel data
  54. const byte bluePin = 6;      // <------- Blue pixel data
  55.  
  56. const byte vSyncPin = 10;    // <------- VSYNC
  57.  
  58. const int horizontalBytes = 60;  // 480 pixels wide
  59. const int verticalPixels = 480;  // 480 pixels high
  60.  
  61. // Timer 1 - Vertical sync
  62.  
  63. // output    OC1B   pin 16  (D10) <------- VSYNC
  64.  
  65. //   Period: 16.64 mS (60 Hz)
  66. //      1/60 * 1e6 = 16666.66 uS
  67. //   Pulse for 64 uS  (2 x HSync width of 32 uS)
  68. //    Sync pulse: 2 lines
  69. //    Back porch: 33 lines
  70. //    Active video: 480 lines
  71. //    Front porch: 10 lines
  72. //       Total: 525 lines
  73.  
  74. // Timer 2 - Horizontal sync
  75.  
  76. // output    OC2B   pin 5  (D3)   <------- HSYNC
  77.  
  78. //   Period: 32 uS (31.25 kHz)
  79. //      (1/60) / 525 * 1e6 = 31.74 uS
  80. //   Pulse for 4 uS (96 times 39.68 nS)
  81. //    Sync pulse: 96 pixels
  82. //    Back porch: 48 pixels
  83. //    Active video: 640 pixels
  84. //    Front porch: 16 pixels
  85. //       Total: 800 pixels
  86.  
  87. // Pixel time =  ((1/60) / 525 * 1e9) / 800 = 39.68  nS
  88. //  frequency =  1 / (((1/60) / 525 * 1e6) / 800) = 25.2 MHz
  89.  
  90. // However in practice, it we can only pump out pixels at 375 nS each because it
  91. //  takes 6 clock cycles to read one in from RAM and send it out the port.
  92.  
  93. const int verticalLines = verticalPixels / 16;  
  94. const int horizontalPixels = horizontalBytes * 8;
  95.  
  96. const byte verticalBackPorchLines = 35;  // includes sync pulse?
  97. const int verticalFrontPorchLines = 525 - verticalBackPorchLines;
  98.  
  99. volatile int vLine;
  100. volatile int messageLine;
  101. volatile byte backPorchLinesToGo;
  102.  
  103. #define nop asm volatile ("nop\n\t")
  104.  
  105. // bitmap - gets sent to PORTD
  106. // For D4/D5/D6 bits need to be shifted left 4 bits
  107. //  ie. 00BGR0000
  108.  
  109. char message [verticalLines]  [horizontalBytes];
  110.  
  111. // ISR: Vsync pulse
  112. ISR (TIMER1_OVF_vect)
  113.   {
  114.   vLine = 0;
  115.   messageLine = 0;
  116.   backPorchLinesToGo = verticalBackPorchLines;
  117.   } // end of TIMER1_OVF_vect
  118.  
  119. // ISR: Hsync pulse ... this interrupt merely wakes us up
  120. ISR (TIMER2_OVF_vect)
  121.   {
  122.   } // end of TIMER2_OVF_vect
  123.  
  124.  
  125. void setup()
  126.   {
  127.  
  128.   // initial bitmap ... change to suit
  129.   for (int y = 0; y < verticalLines; y++)
  130.     for (int x = 0; x < horizontalBytes; x++)
  131.       message [y] [x] = (x + y) << 4;
  132.    
  133.   // disable Timer 0
  134.   TIMSK0 = 0;  // no interrupts on Timer 0
  135.   OCR0A = 0;   // and turn it off
  136.   OCR0B = 0;
  137.  
  138.   // Timer 1 - vertical sync pulses
  139.   pinMode (vSyncPin, OUTPUT);
  140.   Timer1::setMode (15, Timer1::PRESCALE_1024, Timer1::CLEAR_B_ON_COMPARE);
  141.   OCR1A = 259;  // 16666 / 64 uS = 260 (less one)
  142.   OCR1B = 0;    // 64 / 64 uS = 1 (less one)
  143.   TIFR1 = bit (TOV1);   // clear overflow flag
  144.   TIMSK1 = bit (TOIE1);  // interrupt on overflow on timer 1
  145.  
  146.   // Timer 2 - horizontal sync pulses
  147.   pinMode (hSyncPin, OUTPUT);
  148.   Timer2::setMode (7, Timer2::PRESCALE_8, Timer2::CLEAR_B_ON_COMPARE);
  149.   OCR2A = 63;   // 32 / 0.5 uS = 64 (less one)
  150.   OCR2B = 7;    // 4 / 0.5 uS = 8 (less one)
  151.   TIFR2 = bit (TOV2);   // clear overflow flag
  152.   TIMSK2 = bit (TOIE2);  // interrupt on overflow on timer 2
  153.  
  154.   // prepare to sleep between horizontal sync pulses  
  155.   set_sleep_mode (SLEEP_MODE_IDLE);  
  156.  
  157.   // pins for outputting the colour information
  158.   pinMode (redPin, OUTPUT);
  159.   pinMode (greenPin, OUTPUT);
  160.   pinMode (bluePin, OUTPUT);
  161.  
  162. }  // end of setup
  163.  
  164. // draw a single scan line
  165. void doOneScanLine ()
  166.   {
  167.    
  168.   // after vsync we do the back porch
  169.   if (backPorchLinesToGo)
  170.     {
  171.     backPorchLinesToGo--;
  172.     return;  
  173.     }  // end still doing back porch
  174.    
  175.   // if all lines done, do the front porch
  176.   if (vLine >= verticalPixels)
  177.     return;
  178.    
  179.   // pre-load pointer for speed
  180.   register char * messagePtr =  & (message [messageLine] [0] );
  181.  
  182.   delayMicroseconds (1);
  183.  
  184.   // how many pixels to send
  185.   register byte i = horizontalBytes;
  186.  
  187.   // blit pixel data to screen    
  188.   while (i--)
  189.     PORTD = * messagePtr++;
  190.  
  191.   // stretch final pixel
  192.   nop; nop; nop;
  193.  
  194.   PORTD = 0;  // back to black
  195.   // finished this line
  196.   vLine++;
  197.  
  198.   // every 16 pixels it is time to move to a new line in our text
  199.   if ((vLine & 0xF) == 0)
  200.     messageLine++;
  201.    
  202.   }  // end of doOneScanLine
  203.  
  204. void loop()
  205.   {
  206.   // sleep to ensure we start up in a predictable way
  207.   sleep_mode ();
  208.   doOneScanLine ();
  209.  }  // end of loop
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement