|
Using
a Graphics-Based LCD
Module with C
by Bob Perrin and Tak Auyeung
Start ý Software
Overview ý The Bottom Layer ý Initializing
the LCD Display ý Shadow Display ý
Drawing Dots and Lines ý Printing
Text ý Extensions ý Sources
and PDF
PRINTING TEXT
The interesting aspect of printing text
is not how to put the pixels on the screen, but where to get the pixels.
Creating binary files of a custom font format byte-by-byte is out
of the question. It is equally unreasonable to implement a custom
font-editor program. It is more pragmatic to investigate existing
font file formats and evaluate their applicability.
Borland C++ 4.52 (and earlier versions)
includes a Resource Workshop program that, among other abilities,
visually edits font files. The Windows font file format for fixed-pitch
raster fonts is easy to interpret. Thus, it is reasonable to make
the graphics LCD driver able to use Windows fixed-pitch raster font
files.
There is one efficiency issue, however.
Each bitmap in the Windows font file is comprised of one or more eight-pixel-wide
vertical strips. The first byte of a font bitmap corresponds to pixels
(0,0) to (7,0) of the bitmap. If the font is wider than eight pixels,
the second strip, starting with the byte that represents pixels (8,0)
to (15,0) of the bitmap, follows the last byte of the first strip.
The pixel arrangement in a Windows raster font file is different from
the pixel arrangement of the Hantronix HDG12864F-1.
One simple solution is to draw the font
rotated. If the bitmaps are rotated counter-clockwise by 90ý, the
ordering of the bytes in the font bitmaps matches the ordering of
bytes on the LCD. However, this approach makes it inconvenient to
draw fonts or to use any existing font files. (Note that it is illegal
to distribute copyrighted font files without the permission of the
owner.)
The LCD driver provides a function for
loading a Windows font file. The function fntLoad loads the
font file into a memory structure. The first argument is a string
of the pathname of the file. A DOS-based controller certainly makes
it easy to separate fonts as files separated from the application.
The second argument is a pointer to a valid struct _fontInfo
structure. The function fntLoad examines the font file to ensure
it is the right type (version 3.00, fixed pitch, and raster), then
allocates memory to store the converted bitmaps of the font. When
a font is no longer useful, the application can call fntUnload
to free the memory allocated to store the bitmap. Note that fntUnload
does not de-allocate the storage used by the struct _fontInfo
pointed to by the first argument.
Two functions, scrDrawChar and
scrDrawString, implement the logic for displaying characters
on the screen. Both functions require a pointer to a struct _scrBuffer
that represents the shadowed state of the LCD. Both functions also
require a pointer to a struct _fontInfo that indicates the
font to use for printing. The function scrDrawChar requires
a third argument of const char to indicate which character
to print. The function scrDrawString requires a third argument
of const char * to indicate the string to print. For safety
purposes, the scrDrawString function also requires a fourth
argument of unsigned type to indicate the maximum length to print.
The last argument of both functions is a struct _point that
indicates the coordinate of the upper-left corner of the printed text.
PUTTING IT TOGETHER
After discussing the implementation of
various fragments of the driver software, it is important to summarize
the API so that a developer can immediately start to use the code.
First, it is important to declare or allocate the storage for the
shadowed state of the LCD. The simplest method is to declare a local
or global variable of struct _scrBuffer.
The following sequence initializes both
the LCD and shadowed state to a blank screen:
lcdInit();
scrSetBrush(&scrBuffer,SCR_BRUSH_OVR);
scrFill(&scrBuffer,0);
If the application draws text, it should
declare or allocate storage of struct _fontInfo for loaded
fonts. The simplest method is to declare a local or global variable
of struct _fontInfo for each font.
The following function call loads a font
file named 6x8.fnt to a memory-based variable named fontInfo
(of type struct _fontInfo).
fntLoad("6x8.fnt",&fontInfo);
When a font is no longer useful, fntUnload(&fontInfo)
frees the memory allocated.
The API presented allows the applications
programmer to do a number of common tasks. Setting and clearing points,
drawing lines, filling rectangles and displaying text are the most
common graphics primitives used. The following list provides a simple
set of instructions for using the API found in glcd.c and glcd.h
to draw simple graphic and text objects.
ý To draw a dot, first initialize a
struct _point object that represents the coordinates of the
point, then call scrDrawDot.
ý To draw a line, initialize two struct
_point objects that represent the end-points of the line, then
call scrDrawLine.
ý To draw a filled rectangle, first
initialize two struct _point objects that represent the upper-left
and lower-right corners of the rectangle, then call scrFillBox
to fill the rectangle.
ý To use a pattern to fill the entire
screen, call scrFill.
ý To display a character, first initialize
a struct _point object that represents the upper-left corner
of the character, then call scrDrawChar.
ý To display a string, first initialize
a struct _point object that represents the upper-left corner
of the string, then call scrDrawString.
PREVIOUS
NEXT
Circuit Cellar provides up-to-date information
for engineers. Visit www.circuitcellar.com
for more information and additional articles.
For subscription information, call (860) 875-2199, subscribe@circuitcellar.com
or subscribe
online. ýCircuit Cellar, the Magazine for Computer Applications.
Posted with permission.
|