Skip to content

Latest commit

 

History

History
 
 

VGA

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Due VGA Library
by stimmer

V0.987654321 - 23/11/2013

1) Quick start
==============

Place the VGA folder in your libraries directory
Start or restart the Arduino IDE


For VGA mono:
-------------
Upload File->Examples->VGA->HelloWorld

Connect pin 42 to VGA VSync (pin 14 on VGA D-connector)
Connect pin 43 to VGA HSync (pin 13 on VGA D-connector)
Connect GND to VGA GND (pins 5,6,7,8,10 on VGA D-connector)
Connect SPI MOSI pin (bottom middle pin on 6-pin SPI connector) through
a 100 ohm resistor to VGA Red, Green and Blue pins (pins 1,2 and 3 on D-connector)
Turn on monitor :-)

If the monitor has trouble, try some small resistors between 42 and VSync, and 43 
and HSync (10 to 100 ohm)


For VGA colour:
---------------
Upload File->Examples->VGA->HelloWorldColour
Connect Due to monitor as follows:

Due pin 34 -> 820R resistor -> VGA pin 3 (blue)
Due pin 35 -> 390R resistor -> VGA pin 3 (blue)

Due pin 36 -> 2k2 resistor -> VGA pin 2 (green)
Due pin 37 -> 1k resistor -> VGA pin 2 (green)
Due pin 38 -> 470R resistor -> VGA pin 2 (green)

Due pin 39 -> 2k2 resistor -> VGA pin 1 (red)
Due pin 40 -> 1k resistor -> VGA pin 1 (red)
Due pin 41 -> 470R resistor -> VGA pin 1(red)

Due pin 42 -> VGA pin 14 (VSync)
Due pin 43 -> VGA pin 13 (HSync)

Due pin GND -> VGA pins 5,6,7,8,10


For NTSC/PAL:
-------------
Upload File->Examples->VGA->DrawingTestNTSC (or DrawingTestPAL)
Connect Due to TV as follows:

Due pin 36 -> 3k3  resistor -> Video In
Due pin 37 -> 1k6  resistor -> Video In
Due pin 38 -> 820R resistor -> Video In
Due pin 39 -> 390R resistor -> Video In
Due pin 40 -> 200R resistor -> Video In
Due pin 41 -> 100R resistor -> Video In

Due pin GND -> Video GND

On some TVs this will not work. You may need a 100uF capacitor between
the resistors and Video In. 

2) Basic usage
==============

The library is very simple to use - see the examples
#include <VGA.h> at the top of your sketch,

VGA.begin(640,480); in setup for mono or
VGA.begin(320,240,VGA_COLOUR); for colour. 

Then call various drawing functions, eg:
drawPixel(x, y, col); sets a single pixel to colour col
drawLine(x0, y0, x1, y1, col); draws a line from (x0,y0) to (x1,y1)
fillCircle(x, y, r, col); circle, center (x,y) radius r

For text, use VGA.print(...) and VGA.println(...) just like Serial.print(...) and
Serial.println(...) 

3) Colours
==========

In mono mode, 1 is white, 0 is black, and -1 inverts the pixel.

In colour mode (and PAL and NTSC modes), colours are interpreted in 
binary as RRRGGGBB. So for example:

0b11111111 = 255 = white    0b11110000 = 240 = orange
0b11100000 = 224 = red      0b10010010 = 146 = grey
0b00011100 = 28 = green	    0b10000011 = 227 = purple
0b00000011 = 3 = blue       0b00000000 = 0 = black

In the draw* and fill* functions, negative colour values XOR with the current colour 
of the pixel, ie newcol=oldcol^(-col)

4) API
======

int  VGA.begin(int x, int y, int m=VGA_MONO);
  
  Initializes the display, resolution (x,y). m is VGA_MONO or VGA_COLOUR
  Returns: 0 on success, negative on failure
  Not all resolutions work on all monitors. Highest recommended resolutions are 
  800x600 in mono and 320x240 in colour. 
    

int  VGA.beginNTSC();

  Initializes the display in NTSC mode, 320x200 pixels.
  Returns: 0 on success, negative on failure

  
int  VGA.beginPAL();

  Initializes the display in PAL mode, 320x240 pixels.
  Returns: 0 on success, negative on failure

  
void VGA.end();
  
  Stops the display, and frees memory.

  
void VGA.clear(int col=0);
  
  Clears the screen to colour col, or black if col is not specified.


void VGA.drawPixel(int x, int y, int col);
  
  Draws pixel at (x,y) in colour col

  
void VGA.drawLine(int x0, int y0, int x1, int y1, int col);
  
  Draws line from (x0,y0) to (x1,y1) in colour col


void VGA.drawTri(int x0,int y0,int x1,int y1,int x2,int y2,int col);
void VGA.fillTri(int x0,int y0,int x1,int y1,int x2,int y2,int col);

  Draws or fills triangle (x0,y0),(x1,y1),(x2,y2) in colour col
  

void VGA.drawRect(int x0, int y0, int x1, int y1, int col);
void VGA.fillRect(int x0, int y0, int x1, int y1, int col);

  Draws or fills rectangle with corners (x0,y0),(x1,y1) in colour col
  

void VGA.drawCircle(int x, int y, int r, int col);
void VGA.fillCircle(int x, int y, int r, int col);

  Draws or fills circle center (x,y) radius r in colour col
  

void VGA.drawEllipse(int x0, int y0, int x1, int y1, int col);
void VGA.fillEllipse(int x0, int y0, int x1, int y1, int col);

  Draws or fills ellipse bounded by rectangle (x0,y0),(x1,y1) in colour col


void VGA.drawText(char *text, int x, int y, int fgcol, int bgcol= -256, int dir=0);

  Draws text at any pixel position. 
  (x,y) is the top-left corner of the text before rotation.
  fgcol is the colour of the text. bgcol is the colour of the text background
  or -256 for a transparent background.
  dir is the direction of the text. 0 is normal, 1 is up, 2 is upside-down and 3
  is down. -1 draws the text going downwards but with the individual characters 
  oriented normally.

void VGA.scroll(int x, int y, int w, int h, int dx, int dy,int col=0);

  Scrolls an area of the screen, top left corner (x,y), width w, height h
  by (dx,dy) pixels. If dx>0 scrolling is right, dx<0 is left. dy>0 is down,
  dy<0 is up.
  
  
void VGA.moveCursor(int column, int line);

  Moves the print position to (column, line)  
  
  
void VGA.setPrintWindow(int left, int top, int width, int height);

  Restricts the printing window to an area of width x height characters, at a 
  position left characters in and top characters down.

  
void VGA.unsetPrintWindow(){tww=tw;twh=th;twx=twy=0;}

  Restores the print window to be the whole screen.
  
  
void VGA.clearPrintWindow();

  Clears the print window to the current text paper colour.
  
  
void VGA.scrollPrintWindow();

  Scrolls the print window up one line and moves the print position to the bottom.
  
  
void VGA.setInk(int i){ink=i;}

  Sets the text colour to i.
  
  
void VGA.setPaper(int p){paper=p;}

  Sets the text background colour to p
  
  
virtual size_t VGA.write(const uint8_t *buffer, size_t size);
virtual size_t VGA.write(uint8_t c);

  These functions are similar to Serial.write, except output gets printed to
  the screen. These functions enable print and println to work correctly.
  

void VGA.waitBeam()
void VGA.waitSync()

  These functions wait for the beam position to be off-screen. waitBeam will return 
  immediately if the beam is already off-screen, waitSync will always wait for the 
  next frame. These can be used to reduce flicker.


void VGA.setMonitorFreqRange(int hmin, int hmax, int vmin, int vmax)
  
  This function can be tried if your monitor has trouble syncing to some modes.
  All frequencies are in Hz, eg setMonitorFreqRange(27000, 82000, 58, 65);
  Call this before VGA.begin(...)
  

void VGA.setSyncPolarity(bool h, bool v)
  
  Swaps the polarity of the sync signals. Most monitors don't need this.
  Call this before VGA.begin(...)

  
void VGA.putPPixelFast(int x, int y, int c)
int VGA.getPPixelFast(int x, int y)
void VGA.putCPixelFast(int x, int y, int c)
int VGA.getCPixelFast(int x, int y)
  
  Fast inline pixel put/get routines. The P functions are for mono modes and the
  C functions are for colour modes.
  
5) Low Level
============

In mono modes, the screen is arranged as an array of 16-bit words. Each line has enough words for the pixels (eg 40 words in 640x480 mode) plus 2 spare words which are used for blanking and must always be 0.

  uint16_t *VGA.pb; // Pixel buffer memory address
  int VGA.pw;	// Count of words from one line to the next (aka stride or pitch)
  int VGA.pbsize; // Total size of pixel buffer (note these sizes are 16-bit words)
  
The SAM3X also supports a bit-banding alias region in memory, where each bit is mapped to a 32-bit address.

  uint32_t *VGA.pbb; // Pixel buffer bit-banding alias address (read datasheet p75)
  int VGA.pbw;	 // Pixel buffer bit-banding stride (in 32-bit words)
  
To help understand usage of these, look at the following functions:
  void putPPixelFast(int x, int y, int c){pbb[y*VGA.pbw+(x^15)]=c;}
  int getPPixelFast(int x, int y){return pbb[y*VGA.pbw+(x^15)];}
  
In colour modes there are no spare words needed so the colour buffer is just an
array of uint8_t[width*height].

  uint8_t *VGA.cb;   // Colour buffer memory address
  int VGA.cw;	 // Colour buffer stride, in bytes
  int VGA.cbsize;	 // Size of colour buffer in bytes

6) How it works
===============

Don't ask ;-)

Basically it uses nested interrupts. Each line the PWM hardware generates the 
horizontal sync signal then interrupts the processor. Unfortunately it interrupts
at a very slightly different time each line, which would cause a shimmering
effect. So the PWM interrupt puts the processor to sleep, waiting to be interrupted 
again by a timer interrupt at higher priority. Since the processor wasn't doing
anything, this interrupt is precisely synchronized to the timer and the display
is rock solid :-)

The mono modes use DMA and SPI hardware (42MHz for 800x600!) and are therefore
quite fast. The SPI DMA uses another interrupt to signal the end of a line. 
Unfortunately at the end of transmission the SPI output goes HIGH, which would
cause a white line. That's why there are spare blanking words at the end of the
line - when the interrupt fires the DMA is out of data but the blanking words are 
still being output, so the interrupt routine quickly sets the pin back to PIO mode, 
putting it low, and avoiding the white line.

The colour mode uses DMA to the SMC - static memory controller - to output 8 bits
of data at a time to pins 34-41. No end-of-line interrupt is needed here because
the output goes high impedance when data is not being written. The pixel width
is controlled by changing the memory timing registers in the SMC.

The NTSC and PAL modes use a pair of DMA buffers. One is outputting the signal for
the line whilst the interrupt routine is filling the other buffer for the next line.
The colour burst and chroma phase tables have been precalculated (which is why these
modes use so much flash).

Have fun!