VGAX Support for ATMega2560 14/04/2019
I've added support for ATMega2560 to my library VGAX! Now the library can be configured to generate 120x90px (with squared pixels) or 120x240px (rectangular pixels).
The wiring is simple, like for ATMega328. You can wire up an Arduino MEGA board with some cheap components:
To enable 120x90px resolution you need to uncomment the constant ATMEGA2560_HIGHRES on VGAX.h header. To enable 120x240px uncomment ATMEGA2560_MAXRES.
The tricky part to add support for ATMega2560 has been adapting the interrupt dejitter code. I've found that the original code, writen by Charles CNLOHR assume to work on an AVR MCU with a 16bit Program Counter. ATMega2560, like others fat MCU, has a 22bit Program Counter! So, when Charles pop PC from stack, code must be modified to pop 3 bytes instead of 2 (22bit PC requires 3 bytes):
#define DEJITTER_OFFSET 1 #define DEJITTER_SYNC -2 asm volatile( " lds r16, %[timer0] \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" // " add r30, r16 \n\t" // //" adc r31, __zero_reg__ \n\t" // " ijmp \n\t" // "LW: \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" // "LBEND: \n\t" // : : [timer0] "i" (&TCNT0), [toffset] "i" ((uint8_t)DEJITTER_OFFSET), [tsync] "i" ((uint8_t)DEJITTER_SYNC) : "r30", "r31", "r16", "r17");
MCU PORTD must be changed to PORTA becouse PORTD does not have 8 pins, so all the assumptions made in VGAX for ATMega328 cannot work with PORTD for ATMega2560. Colors pins must be moved from pin 6 and pin 7 to pin 30 and pin 31 (higher 2 bits of PORTA in ATMega2560).
TIMER0 setup must be also modified to work fine on both ATMega328 and ATMega2560.
That's all! :)
ATMega2560 has 8KB of SRAM, more space for framebuffer to increase vertical resolution from 60 to 90 or 240px. In theory with ATMega2560 a new library can be created to use 256 colors (with RRRGGGBB pixel format) or 16 colors (RGBH-RGBH double pixels in single byte format). I think to try to write, in the future, these variations of VGAX inside new differents libraries (VGAX256 and VGAX16 ?).
Arduino ESPVGAX Library 15/08/2018
This is a VGA Arduino library for ESP8266. It can display a 512x480 image with 1bit per pixel.
Like my VGAX Library, this Library require cheap components. You can generate a signal from an ESP8266 with less then 5$ :-)
ESPVGAX require a DSUB15 connector (aka VGA connector) and one 330Ohm resistor:
You can wire the VGA connector in some different modes that allow you to choose your preferred white color. For example you can choose to wire it up to use black and green colors, or black and purple.
You can find more informations about colors combinations here.
The Library also support two modes where colors can be increased from the standard 2 colors.
The first additional mode allow you to hook up an hardware PIN to one of the VGA pins (different from the primary color that you have selected in the first wiring). Thi hardware PIN is always ON when VGA signal pixeldata is generated, so you can change the background color from black to another color. This change is permanent and you cannot turn ON/OFF this background color variation.
The idea behind the second additional mode is this: ESP8266 HSPI can send data to VGA as a serial stream of bits, so it can only turn one VGA PIN ON/OFF at a time. But VGA timing has gaps between lines that can allow more code to be executed, before and after sending the stream of bits. So, before sending the data, the Library can turn ON/OFF some other bits and change the color combination used in each horizontal line (480 lines).
The VGA signals can become unstable if your code uses Wifi, Serial, and other Arduino classes. You can find more informations here.
Arduino BITNINJA 09/09/2018
This game is a small platform game, like Super Mario Bros, designed by me. After my nomination in the IOCCC 2014 Contest, i have ported some of the logic of the SMB Engine that i have developed for the Contest.
BITNINJA implements these features:
- input controller LEFT+RIGHT+JUMP with three buttons
- cutscene for splash screen, credits, introduction and epilogue
- background music for cutscene
- 5 playable levels
- collision detections
- 6 max enemies in each level
Becouse VGAX uses 1800 bytes of RAM and the Arduino UNO ATMEGA328 MCU has only 2048 bytes of RAM, the game is optimized to use only 41 bytes of global RAM. All the images, sprites, songs and level definitions are stored in the MCU FLASH ROM. Doing the math: 2048-1800-41=207 bytes are "free", used for the MCU STACK where local variables and parameters are stored.
The 41 bytes required for BITNINJA to run are subdivided like this:
- 11 bytes for player movement and game cutscene
- 24 bytes for 6 enemies (4 byte for each enemy)
- 6 bytes for music
The hardware required is pretty cheap:
- a DSUB15 male connector (VGA)
- 2 68ohm resistors
- 2 470ohm resistors
- 2 22pf capacitors
- 1 16Mhz oscillator
- 3 passive buttons
- 1 audio buzzer
- 1 microusb female connector
The wiring and soldering is documented inside VGAX library documentation, except for the wiring of the standalone ATMEGA328 MCU but you can easily find online How to run ATMEGA328 standalone.
Here you can see a video of BITNINJA testing running on the Arduino UNO, before the standalone board creation. The level you see in the video is a test. The 5 levels inside the final version are different than the one in the video.
This is the final board, with a piece of plexi on the bottom:
I am planning to take a video of all 5 levels, running on the final standalone board. When i will do the video i will post it here!
Arduino VGAX Library 02/09/2018
When i have bought my first Arduino UNO i have started to test some libraries for video signal generation. One of the first interesting library was TVOut. A simple lib that allow you to generate a COMPOSITE video signal out of an ATMEGA328 MCU, using only some resistors and a COMPOSITE video connector.
The first inspiration for VGAX come from TVOut library: A simple VGA library for Arduino that can work with simple cheap components!
Online i have found some interesting articles about Arduino VGA video signal generation, written by Nick Gammon. These articles and his works was the starting point for the development of my VGAX Library.
VGAX Assembler core
The creation of VGAX was a little tricky. I've spent many nights around the interrupt jitter problem, trying to adjust some dejitter code founds online.. An Hell!
To write the Assembler core of VGAX i've studied the official ATMEL ATMEGA328 Instruction Set Manual (190 pages), searching for the best instructions to generate the PIXEL stream output without losing too many CPU cycles. The idea was to use these instructions, for each byte of the framebuffer, inside an unrolled loop
.rept 30 // output 4 pixels (unrolled loop) ld r16, Z+ out %[port], r16 // write pixel 1 mul r16, r20 // left shift 2 out %[port], r0 // write pixel 2 mul r0, r20 // left shift 2 out %[port], r0 // write pixel 3 mul r0, r20 // left shift 2 out %[port], r0 // write pixel 4 .endr
The first good thing is that LD and MUL instructions require both 2 CPU cycles, so the output of the four pixels, packed inside a single byte, is done with the same number of CPU cycles for each pixel (3 cycles, LD=2, MUL=2, OUT=1). This equal timing ensures that all generated pixels will be displayed with the same size (horizontal width).
The second tricky thing is that the two VGA PINs are written with a single OUT instruction that writes an 8bits hardware PORT... but bits cannot be rearranged without losing time.. so the idea was to (pre)arrange the 4 pixels in one byte keeping the order of the bits aligned to the output pins of the 8BIT PORT. First pixel is stored in the higher 2 bits of byte.
The hardware PORT uses the PIN from 0 to 7 so i have wired the two VGA PINs to PIN6 and PIN7.
When a byte is read from the LD instruction, the first pixel bits are already on the 6th and 7th bits, ready to be written out from the OUT instruction. The next MUL will shift the second pixel bits to the right position (6th and 7th bits of the PORT) and written out. This is repeated for the remaining two pixels.
ld r16, Z+ out %[port], r16 // pixel1 bits are aligned on PORT 6th and 7th bits mul r16, r20 // shift 2 pixel up out %[port], r0 // pixel2 bits are now aligned
Many people ask me if is possible to increase the horizontal resolution of the VGA signal (120px).
Arduino ATMEGA328 has only 2048 bytes of RAM! The VGAX framebuffer have a resolution of 120x60px with 2bpp, almost all the MCU RAM is used (1800 bytes). This is the first limitation that cannot allow an increase of the horizontal resolution without losing color depth (2bpp). But there is another important reason that does not allow a greater horizontal resolution: the CPU speed!
ATMEGA328, inside Arduino, runs at 16Mhz. VGA signal require a 25Mhz PIXEL output speed. If you calculate the number of CPU cycles used to send PIXEL out you obtain this formula:
25Mhz : 640px = (16Mhz / 3clocks) : RES RES = (640 * 5.3) / 25 RES = 136px~
So, the maximum resolution possible, at 16Mhz, using 3 CPU cycles for each pixel, is 136px! VGAX for ATMEGA328, with the dejitter code and the audio signal generation, reach a resolution of 120px for each horizontal line, near the maximum resolution possible.
This library was used from some people around the world. I thanks everybody for have spent some time using VGAX! Many thanks to Rob Cai that has recreated some classic games like Tetris, Pong and Breakout, using VGAX!
VGAX was reviewed in an article of the C'T MAKE newspaper, number of 03/2017. When i read this article i am always happy! :-)