tvgfx: 416x226 Monochrome ATmega1284p Composite Video

About

Inspired by Myles Metzer's arduino-tvout project I decided to find out what one could achieve by porting this code to the ATmega1284p. This device is the biggest member of the AVR 8 bit family available in a through-hole package. Not only does it have 128KBytes of flash memory which is useful fo storing fonts and bitmaps but also it does have 16KBytes of RAM - part of which can be used for video memory. 

So here is what I came up with:
  • 416x226 (NTSC) or 416x256 (PAL) resolution
  • Atmega1284p running at 16MHz (20MHz would result in higher resolution but RAM could be a limitation then)
  • fully graphic monochrome display
  • uses just two pins on the ATmega (PD3 for video content output and PD5 for sync output)
  • uses SPI to output the actual video data timer 1 to generate sync signals
  • absolute minimal external components: just two resistors to combine sync and video into one composite signal, see Myles' page for details
  • written mostly in C
  • since a reasonably conforming (see below) NTSC or PAL BAS signal is produced, any cheap composite-in TFT display can be used 
  • code comes with a pretty elaborate vector graphics engine (lines, rectangles, circles, ellipses, arcs, splines - all in variable thickness)
  • code will handle tvout's font format and comes with a large collection of free fonts
  • also provided is a small script to convert bitmap fonts in bdf format to tvout (see below)

Screenshots

Images were taken from a $30 car TFT display (7 inch)



Fonts

While tvgfx uses the font format described in arduino-tvout's wiki and is certainly capable of using the existing tvout fonts, because of the much higher resolution output larger fonts are needed. Rather than designing some manually, I decided to write a small converter script called bdf2tvout.py which will convert standard bitmap fonts in bdf format to tvout/tvgfx font source code. 

The script will handle monospaced as well as proportional spaced fonts (you can force generation of fixed-space font output using the -f option) and allows one to specify a character subset to convert (-s and -t options) which is useful to keep the amount of flash allocated down especially for larger fonts that e.g. just contain uppercase characters.

[guenter@dagobert fonts]$ python bdf2tvout.py -h
Usage: bdf2tvout.py [options] font.bdf

Options:
  -h, --help            show this help message and exit
  -n FONTNAME, --name=FONTNAME
                        Font name (default: 'font')
  -f, --fixed           Generate fix-width font (default: variable width)
  -s START_CODE, --start=START_CODE
                        Start from this character code (default:32)
  -t STOP_CODE, --stop=STOP_CODE
                        Stop at this character code (default: 126)

There are quite a few sources of hand-crafted bdf fonts out there, you will also find a lot of them in common Linux distributions. Some of the free ones I have already converted and added to the demo package of tvgfx (see tvfonts subdirectory):
  • angle16.c
  • cybercafe16.c
  • medieval16.c
  • polytonic20.c
  • spangle16.c
  • sun22.c
  • t16.c
  • tamsynb12.c
  • tamsynb14.c
  • tamsynb15.c
  • tamsynb17.c
  • tamsynb20.c
  • tamsynb9.c
  • tamsynr12.c
  • tamsynr14.c
  • tamsynr15.c
  • tamsynr17.c
  • tamsynr20.c
  • tamsynr9.c
  • tangle16.c
  • terminus16.c
  • tvout6.c
  • tvout8.c
  • waukegan13.c
  • waukegan14.c
  • waukegan17.c
  • waukegan18.c
  • waukegan26.c
  • waukegan27.c
  • waukegan33.c
  • waukegan34.c
  • waukeganeb13.c
  • waukeganeb17.c
  • waukeganeb26.c
  • waukeganeb34.c
But, of course most fonts out there nowadays are vector fonts which tvgfx cannot handle directly. There is, however a way to convert those as well: First, use FontForge to render the font into a bdf bitmap (several, actually - one for each size you'd like to have). Next step is optional, but highly recommended: use a bitmap font editor like gbdfed to optimize the generated bitmap font (make rounding symmetrical, remove characters that are not needed, ...). Then, finally run bdf2tvout.py.

Caution: If you add more then 64KBytes worth of fonts and bitmaps to your firmware image, you will have to use FAR pointer addressing which will result in a ~20% performance penalty. If not, you can make tvgfx use optimized 16 bit pointer by specifying -DTVGFX_FASTFONTS on the compiler command line (see CDEFS setting in the Makefile).

Video Settings

You want to toy around with the video timings until you find settings which result in a stable, clear picture and best resolution (smallest borders) for your device. Especially cheap composite input TFT monitors frequently have their own idea what timings and resolutions they like.

In tvgfx/video.h the settings

#define XSize       52   // bytes per scanline
#define XLineDelay  73   // actual line output starts at XLineTimer+XLineDelay

control HSync - if you increase XLineDelay frame contents shift right, decreasing the value shifts left. You might be able to increase or decrease XSize so it will match the actual visible picture (you don't want to waste memory on parts of the image not visible, but also you want the usable image to stretch from left to right monitor border as much as possible).

For Y Sync you can switch between PAL and NTSC - especially for TFT monitors you want to use whatever matches the monitor's native resolution best. In my case it turned out the monitor was NTSC native - so giving it NTSC signals and activating image stretch to 16:9 aspect ratio resulted in nice, clean, nearly square pixels.

SVG Support

Now this is a very experimental feature: Since the vector graphics engine is actually capable of rendering all the primitives defined by SVG it is possible to turn SVG graphics into C-Source code which is then rendered on the ATmega (see shuttle image above). 

It would take quite some effort to implement a generic SVG-to-tvgfx converter - a very first sketch of what one could look like is attached to this article. It is implemented in python and right now is only able to handle flat, path-only SVGs produced by Inkscape. So in order to use it on any other SVG you'll (at least!) have to open it in Inkscape, flatten the whole thing, turn everything into a graph and save it as an Inkscape SVG. You will probably still have to edit either the SVG or (preferred!) the converter script to make it handle features not implemented yet.

If you want to give it a try, I suggest starting with one of the sample images provided, e.g.

$ python svg2tvgfx.py shuttle1.svg

the script will produce a lot of debug output on the console, but finally it should also produce a file called code.c which contains the source code that will render the image using tvgfx:

#include "tvgfx/tvgfx.h"
#include "tvfonts/allfonts.h"

void draw_shuttle(void) {
 tvgfx_move_to (311.920470, 222.732730);
 tvgfx_cbezier_to (301.482790, 226.324930, 290.010960, 224.863630, 280.793310, 219.367830);
 tvgfx_cbezier_to (261.294380, 210.983030, 241.974710, 202.127030, 222.417170, 193.913930);
...

Credits

Copyright / License


 Permission is hereby granted, free of charge, to any person
 obtaining a copy of this software and associated documentation
 files (the "Software"), to deal in the Software without
 restriction, including without limitation the rights to use,
 copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the
 Software is furnished to do so, subject to the following
 conditions:

 The above copyright notice and this permission notice shall be
 included in all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 OTHER DEALINGS IN THE SOFTWARE.

ċ
bdf2tvout.py
(6k)
Guenter Bartsch,
Apr 17, 2013, 4:08 AM
ċ
svg2tvgfx.tgz
(96k)
Guenter Bartsch,
Apr 17, 2013, 3:38 AM
ċ
tvgfx_firmware.tgz
(384k)
Guenter Bartsch,
Apr 17, 2013, 4:20 AM
Comments