|
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
|