Skip to content

Commit

Permalink
- added support to ATMega2560
Browse files Browse the repository at this point in the history
  • Loading branch information
Sandro committed Apr 14, 2019
1 parent 70885fd commit 002fff3
Show file tree
Hide file tree
Showing 11 changed files with 615 additions and 49 deletions.
38 changes: 26 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,26 +1,28 @@
# VGAX Library for Arduino UNO
# VGAX Library for Arduino UNO and MEGA

COPYRIGHT (C) 2014 Sandro Maffiodo
[[email protected]](mailto:[email protected])
[http://www.assezeta.com/sandromaffiodo](http://www.assezeta.com/sandromaffiodo)
[http://www.sandromaffiodo.com](http://www.sandromaffiodo.com)

![screenshot0](docs/screenshot3.jpg)

YouTube videos:

[<img width='30%' src='https://i.ytimg.com/vi/PfN_sQffLkg/mqdefault.jpg'/>](https://youtu.be/PfN_sQffLkg)
[<img width='30%' src='https://i.ytimg.com/vi/Yvdf-pfneA4/mqdefault.jpg'/>](https://youtu.be/Yvdf-pfneA4)
[<img width='30%' src='https://i.ytimg.com/vi/W9ebehFDDRA/mqdefault.jpg'/>](https://youtu.be/W9ebehFDDRA)
[<img width='20%' src='https://i.ytimg.com/vi/PfN_sQffLkg/mqdefault.jpg'/>](https://youtu.be/PfN_sQffLkg)
[<img width='20%' src='https://i.ytimg.com/vi/Yvdf-pfneA4/mqdefault.jpg'/>](https://youtu.be/Yvdf-pfneA4)
[<img width='20%' src='https://i.ytimg.com/vi/W9ebehFDDRA/mqdefault.jpg'/>](https://youtu.be/W9ebehFDDRA)
[<img width='20%' src='https://i.ytimg.com/vi/Qs3uyhzUcfA/mqdefault.jpg'/>](https://youtu.be/Qs3uyhzUcfA)

Some photos:

[<img width='20%' src='docs/screenshot1.jpg'/>](docs/screenshot1.jpg)
[<img width='20%' src='docs/screenshot5.jpg'/>](docs/screenshot5.jpg)
[<img width='20%' src='docs/screenshot2.jpg'/>](docs/screenshot2.jpg)
[<img width='20%' src='docs/screenshot6.jpg'/>](docs/screenshot6.jpg)

## What is VGAX?

This is a VGA library for Arduino UNO.
This is a VGA library for Arduino UNO and Arduino MEGA.
To use this library you need only 4 resistors and one DSUB15 connector.
This library require an ATMega328 MCU (or higher) MCU. Does not work with ATTINY family or ATMega168.

Expand All @@ -33,13 +35,21 @@ Thanks to Roberto Melzi [RobCai](https://www.youtube.com/channel/UCgQK0QAMUV5L4O

## Video

The library implement a 120x60px framebuffer where each pixel is stored as 2 bits (4 colors).
The framebuffer is stored inside SRAM and require 1800 bytes. Your programs cannot use more than 200 bytes so be carefull! If you want, you can use another Arduino UNO to drive the one that use VGAX library.
The library implement a 120x60px framebuffer where each pixel is stored as 2 bits (4 colors). On Arduino MEGA resolution can be increased to 120x240px.
The framebuffer is stored inside SRAM and require at least 1800 bytes. This mean that on ATMega328 your programs cannot use more than 200 bytes so be carefull! If you want, you can use another Arduino UNO to drive the one that use VGAX library. On ATMega2560 you have more SRAM but if you expand the framebuffer to 120x240px free SRAM will be 800 bytes.

VGAX framebuffer use 2bit for each pixel. Inside each byte are stored 4 pixels, packed in this order: leftmost pixel is in the highest 2bits, rightmost pixel is on the lowest 2bits:

![framebuffer.png](docs/framebuffer.png)

On Arduino MEGA (ATMega2560) framebuffer can be extended to 120x90px with squared pixels or 120x240px with rectangular pixels. You can enable these alternatives resolutions by uncommenting these constants on VGAX.h header:

//uncomment ATMEGA2560_HIGHRES to use 120x90px squared pixels
//#define ATMEGA2560_HIGHRES

//uncomment ATMEGA2560_HIGHRES to use 120x240px rectangular pixels
//#define ATMEGA2560_MAXRES

## Audio

This library implement an async tone (audio) generation too! The audio signal is
Expand All @@ -58,11 +68,12 @@ You need:
Then connect them like the following schema.
*NOTE: The DSUB15 connector is shown from rear view*

![wire.png](docs/wire0.png)
![wire0.png](docs/wire0.png)
![wire1.png](docs/wire1.png)

### 4 Colors
The 4 colors generated from the library are not predefined.
You can connect the PIN6 and PIN7 with two of the VGA DSUB15 RGB pins, selecting the color combination that you prefer.
On Arduino UNO you can connect the pin 6 and pin 7 with two of the VGA DSUB15 RGB pins, selecting the color combination that you prefer.

These are some of the possible combinations, done without additional components:

Expand All @@ -78,6 +89,7 @@ These are some of the possible combinations, done without additional components:

![color5.png](docs/color5.png)

Pin 6 and pin 7 on Arduino MEGA must be changed to pin 30 and pin 31 but the same logic of choosing colors can be applyed on MEGA.

## PIN and PORT

Expand All @@ -87,6 +99,8 @@ PORTD pins**.
The vertical synchronization signal is generated on pin 9. Gammon's version use
the pin 10 but i prefer to keep pins 10 11 12 13 free for common SPI usage.

On Arduino MEGA PORTD is substituted to PORTA, vertical sync is pin 11 and horizontal pin is 9.

## Interrupt

VGAX library generate the video signal using only interrupts, so, inside main() function, you can do anything you want. Your code will be interrupted when VGA signal needs to be generated.
Expand All @@ -97,11 +111,11 @@ VGAX library generate the video signal using only interrupts, so, inside main()

## Timers

This library uses **all the 3 timers** of ATMega328 MCU.
This library uses **all the 3 timers** of ATMega328 MCU. On ATMega2560 there are more unused timers.

*TIMER1* and *TIMER2* are configured to generate HSYNC and VSYNC pulses.
The setup code for these two timers has been [created by Nick Gammon](http://www.gammon.com.au/forum/?id=11608).
I have only made some modifications to use pin 9 instead of pin 10.
I have only made some modifications to use pin 9 instead of pin 10. On ATMega2560 HSYNC and VSYNC are different.

*TIMER0* is used to fix the interrupt jitter. I have modified an assembler trick
originally writen by [Charles CNLOHR](https://github.com/cnlohr/avrcraft/tree/master/terminal).
Expand Down
59 changes: 44 additions & 15 deletions VGAX.cpp
Original file line number Diff line number Diff line change
@@ -1,20 +1,38 @@
#include "VGAX.h"

//HSYNC pin used by TIMER2
#define HSYNCPIN 3
#if defined(__AVR_ATmega2560__)
#define HSYNCPIN 9
#else
#define HSYNCPIN 3
#endif

//These two pin cannot be modified without modify the HSYNC assembler code
#define COLORPIN0 6
#define COLORPIN1 7
#if defined(__AVR_ATmega2560__)
#define COLORPIN0 30
#define COLORPIN1 31
#else
#define COLORPIN0 6
#define COLORPIN1 7
#endif

//VSYNC pin used by TIMER1. Can be 9 or 10
#define VSYNCPIN 9
#if defined(__AVR_ATmega2560__)
#define VSYNCPIN 11
#else
#define VSYNCPIN 9
#endif

//Number of VGA lines to be skipped (black lines)
/*These lines includes the vertical sync pulse and back porch.
Minimum value must be 35 (calculate from Nick Gammon)
You can modify this value to center the framebuffer vertically, or not*/
#define SKIPLINES 90
#if defined(__AVR_ATmega2560__) && \
(defined(ATMEGA2560_HIGHRES) || defined(ATMEGA2560_MAXRES))
#define SKIPLINES 32
#else
#define SKIPLINES 90
#endif

static byte afreq, afreq0;
unsigned vtimer;
Expand Down Expand Up @@ -83,14 +101,19 @@ ISR(TIMER2_OVF_vect) {
//code from https://github.com/cnlohr/avrcraft/tree/master/terminal
//modified from 4 nop align to 8 nop align
#define DEJITTER_OFFSET 1
#define DEJITTER_SYNC -3
#define DEJITTER_SYNC -2
asm volatile(
" lds r16, %[timer0] \n\t" //
//" add r16, %[toffset] \n\t" //
#if defined(__AVR_ATmega2560__)
" add r16, %[toffset] \n\t" //
#endif
" subi r16, %[tsync] \n\t" //
" andi r16, 7 \n\t" //
" call TL \n\t" //
"TL: \n\t" //
#if defined(__AVR_ATmega2560__)
" pop r17 \n\t" //ATMEGA2560 has a 22bit PC!
#endif
" pop r31 \n\t" //
" pop r30 \n\t" //
" adiw r30, (LW-TL-5) \n\t" //
Expand Down Expand Up @@ -149,12 +172,21 @@ ISR(TIMER2_OVF_vect) {
" ldi r16, 0 \n\t" //
" out %[port], r16 \n\t" //write black for next pixels
:
#if defined(__AVR_ATmega2560__)
: [port] "I" (_SFR_IO_ADDR(PORTC)),
#else
: [port] "I" (_SFR_IO_ADDR(PORTD)),
#endif
"z" "I" (/*rline*/(byte*)vgaxfb + rlinecnt*VGAX_BWIDTH)
: "r16", "r17", "r20", "r21", "memory");

//increment framebuffer line counter after 6 VGA lines
if (++aline==5) {
#if defined(__AVR_ATmega2560__) && defined(ATMEGA2560_MAXRES)
#define CLONED_LINES (2-1)
#else
#define CLONED_LINES (6-1)
#endif
if (++aline==CLONED_LINES) {
aline=-1;
rlinecnt++;
} else {
Expand All @@ -179,20 +211,20 @@ void VGAX::begin(bool enableTone) {
//disable TIMER0 interrupt
TIMSK0=0;
TCCR0A=0;
TCCR0B=1; //enable 16MHz counter (used to fix the HSYNC interrupt jitter)
TCCR0B=(1 << CS00); //enable 16MHz counter (used to fix the HSYNC interrupt jitter)
OCR0A=0;
OCR0B=0;
TCNT0=0;
//TIMER1 - vertical sync pulses
pinMode(VSYNCPIN, OUTPUT);
#if VSYNCPIN==10
#if VSYNCPIN==10 //ATMEGA328 PIN 10
TCCR1A=bit(WGM10) | bit(WGM11) | bit(COM1B1);
TCCR1B=bit(WGM12) | bit(WGM13) | bit(CS12) | bit(CS10); //1024 prescaler
OCR1A=259; //16666 / 64 uS=260 (less one)
OCR1B=0; //64 / 64 uS=1 (less one)
TIFR1=bit(TOV1); //clear overflow flag
TIMSK1=bit(TOIE1); //interrupt on overflow on TIMER1
#else
#else //ATMEGA328 PIN 9 or ATMEGA2560 PIN 11
TCCR1A=bit(WGM11) | bit(COM1A1);
TCCR1B=bit(WGM12) | bit(WGM13) | bit(CS12) | bit(CS10); //1024 prescaler
ICR1=259; //16666 / 64 uS=260 (less one)
Expand Down Expand Up @@ -229,10 +261,7 @@ void VGAX::clear(byte color) {
c&=3;
register byte c0=(c*4) | c;
c0|=c0*16;
unsigned cnt=VGAX_BSIZE;
byte *o=(byte*)vgaxfb;
while (cnt--)
*o++=c0;
memset(vgaxfb, c0, VGAX_BSIZE);
}
void VGAX::copy(byte *src) {
byte *o=(byte*)vgaxfb;
Expand Down
18 changes: 15 additions & 3 deletions VGAX.h
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
/*
VGAX Library for Arduino UNO (ATMega328 MCU)
VGAX Library for Arduino UNO (ATMega328) and Arduino MEGA (ATMega2560)
Source code url: https://github.com/smaffer/vgax
120x60px VGA framebuffer with 4 colors
COPYRIGHT (C) 2014 Sandro Maffiodo
[email protected]
http://www.assezeta.com/sandromaffiodo
http://www.sandromaffiodo.com
based on the "VGA color video generation" by Nick Gammon:
http://www.gammon.com.au/forum/?id=11608.
Expand All @@ -28,7 +28,19 @@ HERE you can find some inline documentation about the VGAX library class
#endif
#include <avr/pgmspace.h>

#define VGAX_HEIGHT 60 //number of lines
//uncomment ATMEGA2560_HIGHRES to use 120x90px squared pixels
//#define ATMEGA2560_HIGHRES

//uncomment ATMEGA2560_HIGHRES to use 120x240px rectangular pixels
#define ATMEGA2560_MAXRES

#if defined(ATMEGA2560_MAXRES)
#define VGAX_HEIGHT 240 //number of lines
#elif defined(ATMEGA2560_HIGHRES)
#define VGAX_HEIGHT 80 //number of lines
#else
#define VGAX_HEIGHT 60 //number of lines
#endif
#define VGAX_BWIDTH 30 //number of bytes in a row
#define VGAX_WIDTH (VGAX_BWIDTH*4) //number of pixels in a row
#define VGAX_BSIZE (VGAX_BWIDTH*VGAX_HEIGHT) //size of framebuffer in bytes
Expand Down
2 changes: 1 addition & 1 deletion VGAXUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ Utils for VGAX Library
COPYRIGHT (C) 2014 Sandro Maffiodo
[email protected]
http://www.assezeta.com/sandromaffiodo
http://www.sandromaffiodo.com
Some of these methods are from TVOut library created by Myles Metzer (thank you!)
https://code.google.com/p/arduino-tvout/
Expand Down
23 changes: 8 additions & 15 deletions blit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,14 @@ void VGAX::blit(byte *src, byte swidth, byte sheight, char dx, char dy) {
byte sw=swidth, sx=0;
char ldx=dx;
while (sw--) {
/*if ((sx & 3)==0 && (sw & 3)==0) {
putpixel4(ldx, dy, pgm_read_byte(srcline + (sx>>2)));
sw-=3;
sx+=4;
ldx+=4;
} else*/ {
//get sprite pixel
byte p=pgm_read_byte(srcline + (sx>>2));
byte bitpos=6-(sx & 3)*2;
byte spixel=(p >> bitpos);
//set framebuffer pixel
putpixel(ldx, dy, spixel);
sx++;
ldx++;
}
//get sprite pixel
byte p=pgm_read_byte(srcline + (sx>>2));
byte bitpos=6-(sx & 3)*2;
byte spixel=(p >> bitpos);
//set framebuffer pixel
putpixel(ldx, dy, spixel);
sx++;
ldx++;
}
srcline+=slinesize;
dy++;
Expand Down
Binary file added docs/screenshot6.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/wire0.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/wire1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions examples/BitFont/BitFont.ino
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,8 @@ void loop() {
else
vga.noTone();
vga.clear(11);
vga.printPROGMEM((byte*)fnt_nanofont_data, FNT_NANOFONT_SYMBOLS_COUNT, FNT_NANOFONT_HEIGHT, 3, 1, str0, x, 10, 1);
vga.printPROGMEM((byte*)fnt_nanofont_data, FNT_NANOFONT_SYMBOLS_COUNT, FNT_NANOFONT_HEIGHT, 3, 1, str1, x, 17, 2);
vga.printPROGMEM((byte*)fnt_nanofont_data, FNT_NANOFONT_SYMBOLS_COUNT, FNT_NANOFONT_HEIGHT, 3, 1, str0, x, VGAX_HEIGHT/2-3, 1);
vga.printPROGMEM((byte*)fnt_nanofont_data, FNT_NANOFONT_SYMBOLS_COUNT, FNT_NANOFONT_HEIGHT, 3, 1, str1, x, VGAX_HEIGHT/2+4, 2);
x++;
if (x==VGAX_WIDTH)
x=-VGAX_WIDTH;
Expand Down
Loading

0 comments on commit 002fff3

Please sign in to comment.