Vous êtes sur la page 1sur 5

The Small Graphic LCD Solution

Displaying Bitmap Images Easily on Small Graphic LCDs

I) A Brief History Leading up to Small Graphics


With the ever increasing struggle to keep up with technology, more and more engineers
are given the difficult task of integrating state of the art optical devices into their products. And
with this task comes the unpleasant job of coming up with the software to interface to these new
devices. The most common optical device in the commercial marketplace is the Liquid Crystal
Display (LCD). The LCD industry has broken down this technology into three main areas;
Segmented, Alphanumeric, and Small Graphic Displays.
Both the Segmented and Alphanumeric displays are very limited in their capabilities in
the sense that they just display numbers and characters. Often times these types of displays are
sufficient to meet the requirements of the product being manufactured. But with our current era
of multimedia, the customer expects to see a lot more out of their new product.
This brings us to an area of LCDs that currently has the attention of most of the world.
This is the area of Small Graphic LCD Displays. While Small Graphic Displays have been
around for sometime, they have never been so compact and cost effective as they are today. A
Small Graphic Display will usually range in resolution from 32x80 to 240x320 (240 pixels down
and 320 across). The Small Graphic display is fully graphical, which means the pixels are
configured tightly side by side, so as to resemble a miniature laptop computer screen. With a full
graphic display there is no end to what you can visually represent. If your goal is to simply
display text, you can do that in whatever font, size, and attribute you desire. As well as
displaying things like logos, graphs, charts, or any other image that will differentiate your
product from the competition.

II) Hurdles in Upgrading Your Display


The main reason a lot of companies have not upgraded their display devices to a Small
Graphic Display is due to the misconception of the added cost and bulk of a larger display. But
with new advancements in LCD technologies, Small Graphic Displays can now be found in sizes
that are comparable with the other types of LCD displays and at roughly the same price. So you
might ask yourself what other reason could there be to keep my company from upgrading our
display to a more attractive and powerful Small Graphic LCD. The main hurdle in upgrading
your display lies in the software.
Most LCD displays have a built-in controller that maps their memory and controls the
signals that are sent to the display drivers. These controllers are made to interface in a parallel
fashion to a microprocessor. This means that all the software written for the display will be done
in a low level language like C++ or Assembly code.

If your display is Segmented or Alphanumeric, then the amount of data needed to control
the display is relatively small, due to the fact that the controllers on these displays have a built in
ROM that stores predefined numbers and characters. So all you have to do is place your cursor
to the appropriate place on your display and define which character should be placed there.
But if you upgraded to a Small Graphics Display (say 240x320) and you want to display a
screen full of graphical images, then you would have a total of 76,800 pixels that must be either
turned on or off by your program. Now most companies will create small subroutines that
construct 8x8 or 8x16 character sizes, and refer to these subroutines when constructing their
screen. But if that is the extent they are going to use their Small Graphics Display then they are
no better off than if they went to a larger Alphanumeric Display. To take advantage of all 76,800
pixels would require a compilation of an extreme amount of data. And without the aid of any
higher level language to help out, this data would have to come from manually created designs
and drawings on special graph paper. Each picture would then have to be converted into 9,600
bytes of data. This time becomes exponential when we consider the amount of images most
companies would like to create, along with the usual rework that will accompany this process.
By the time the final software becomes complete, the end product might not be on the cutting
edge anymore and they would have been better off staying with their old Alphanumeric Display.

III) The Software Solution


The solution explained in this document is in the combining of the high level language of
Microsoft Windows with the low level assembly code or C++ of the users program. The end
result is perfect bitmap pictures on your LCD screen that are defined, edited, and brushed up in
Microsoft Paint, or any other bitmap generating program.
The unit shown above is Densitrons 240x320 Small Graphic Display along with their
HLX80C51 Prototyping kit. The HLX kit has an 8051 based microprocessor and 64K Bytes of
flash memory on board. The assembly code running this display is 400 lines long. This
incorporates the initialization code, display commands like clear, and the subroutines for
painting the display with the bitmap images. By using the technique outlined in this document to
incorporate bitmap pictures onto the LCD display, the user program size will remain the same,
about 400 lines, but the data will be extracted out of a bitmap image. Not only is this time
reducing, but the pictures are more easily drawn, edited, and copied from other software
applications available in Windows or on the Internet.
To create your bitmaps you can use any bitmap program available to you. The program
we are using to explain this procedure is MS Paint. After opening up this program, the
Attribute menu should be selected. At the prompt you can enter the LCD display size you will
be using. Then choose the monochrome bitmap option in this window. You can now close the
Attribute window and start drawing, typing, or pasting in all the images you want to use. Once
you have saved all of the pictures you will be using, then the bitmaps should be attached to the
end of your assembled or compiled program in the order they are to be used. This can be done by
using the COPY/B command in DOS. The COPY/B differs from the regular COPY command
by copying directly as a binary format, and not adding an additional byte of data at the end as is
done when using the COPY command for DOS text files.

For these attached bitmaps to be of use you must have a subroutine in your program that
can pull the data out of the lower memory and send it to the display. This requires knowledge of
how the bitmap information is stored.
For a bitmap program, the first 62 bytes of data call out the protocol for the rest of the
bitmap code (like the type, size, and layout of the bitmap). Since this information will already be
known (monochrome and layout dimensions), the first 62 bytes can be skipped. The 63rd byte
will define the first eight pixels in the lower left hand corner of the display. The following bytes
will then be sent sequentially to the screen until you hit the right hand edge of your display. The
next byte will either be the first byte on the next row up (on the left hand side), or it will be a
padded zero that the bitmap program has placed in there to maintain certain integers for row
length.
Padded zeros are used when the number of bytes in a row are not divisible by 4. So if you
had 16 bytes of data per row (16x8 = 128 pixel across), then you would have no padded zeros
because 16 is divisible by 4. But if your number of bytes of data per row was 30 (30x8 = 240
pixels across), then 4 would not go evenly into 30. At this point we would round up the number
to the nearest integer that 4 will go into. This number would be 32. And since we have 30 bytes
of data, 32-30 = 2; so there are 2 bytes of padded zeros in your bitmap before the next line of
data begins. Your internal program will have to reflect this and disregard these zeros before
going on with the 33rd byte of data. (see Table 1 for quick reference to your display)
So for example, if you had a 128x240 display, you would set up your assembly code so it
would strip off the first 62 bytes of data from the bitmap file and discard that information. The
63rd byte would be the first byte in the lower left hand side of the LCD display. Then the next
29 bytes of data (2408 = 30) would get placed directly to the display. Now the next 2 bytes (the
padded zeros - see Table 1) must be discarded. The next byte of data will then be placed in the
next row up and over on the left hand side. The user will continue this process until he has
walked up the display all 128 lines.

Table 1 - Correlation between bitmap resolution and padded zeros


Bitmap Resolution
32x80
32x202
33x100
64x128
64x240
64x480
128x128
128x240
128x256
200x640
240x320

Bytes Per Row


10
26
13
16
30
60
16
30
32
80
40

Padded Zeros Per Row


2
4
3
0
2
0
0
2
0
0
0

Totals Divisible By 4
12
30
16
16
32
60
16
32
32
80
40

If you access the upper bitmap memory by using the data pointer address in your
microprocessor, then once you paint the first page and increment the data pointer, you will be
looking at the first byte of the next picture in your list. There is one thing to remember about a
bitmap that is different from a LCD display. In bitmap programs, a 1 in binary is an off pixel
and a 0 in binary is an on pixel. This is the opposite on the LCD. So the user will need to
perform an Exclusive-Or with the number FF Hex and the data to be placed on the display.
This operation will turn the bytes around so they may be viewed properly. If you dont do this
operation, your picture will be the inverse image of your original picture.
For an example of the subroutine that extracted the bitmap data to produce the picture
above, please see the 8051 assembly code listed below. The display above is a 240x320 Small
Graphics Display with a SED1330 controller chip. If you are using a display that is not using the
SED1330 controller chip, this same code can be used with modifications to the WRCMD and
WRDATA subroutines and possibly some alterations on the direction the data is clocked in. The
direction used in the SED1330 is the same as the T6963 controller chip. If you are using the
HD61830 you will need to switch the direction of the data being clocked in (i.e. D7 becomes D0,
D6 becomes D1, etc.)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; This is a base program for clocking in bitmaps to the SED1330 on a 240x320 LCD display
; using 8051 assembly code.
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
START:
MOV 30H,#3EH
;SETS UP THE INNER LOOP TO 62
MOV 31H,#01H
;SETS UP FOR NULL DATA
LCALL CK_DATA
;GO GET DATA
MOV B,#0F0H
;SETS UP INNER LOOP FOR 240 LINES OF DATA
MOV 32H,#008H
;SETS LOWER CURSOR ADDRESS (address where program ends/bitmap begins)
MOV 33H,#02AH
;SETS UPPER CURSOR ADDRESS
DO_OVER:
PUSH B
;STORE VALUE
MOV 30H,#28H
;SETS UP THE INNER LOOP TO 40 CHARACTERS PER LINE
MOV 31H,#00H
;SETS UP FOR VALID DATA
LCALL SET_CUR
;SETS THE INITIAL ADDRESS ON DISPLAY
LCALL CK_DATA
;GO GET DATA
POP
B
;RECALLS INNER LOOP
DJNZ B,CONTINUE
;IF NOT ZERO, THEN REDO (moving up one line on display if doing over)
RET
;
CONTINUE:
MOV A,0D0H
;RECALL CARRY FLAG
ANL A,#7FH
;CLEAR THE CARRY FLAG
MOV 0D0H,A
;STORE FLAG
MOV A,32H
;RECALL LOWER CURSOR ADDRESS
SUBB A,#28H
;SUBTRACT 40 FROM THIS ADDRESS TO MOVE UP ONE LINE
MOV 32H,A
;RESTORE THE NEW LOWER ADDRESS
MOV A,0D0H
;RECALL CARRY FLAG
ANL A,#80H
;STRIP OFF CARRY FLAG
CJNE A,#80H,NO_CARRY ;SEE IF FLAG IS SET (if set then must bump down higher address by 1)
MOV A,33H
;RECALL UPPER CURSOR ADDRESS
SUBB A,#01H
;SUBTRACT 1 FORM UPPER
MOV 33H,A
;RESTORE THE VALUE
NO_CARRY:
LJMP DO_OVER
;DO INNER ROUTINE OVER AGAIN
CK_DATA:
MOV A,31H
;RECALL BYTE FOR NULL OR VALID DATA
CJNE A,#00H,GET_DATA ;SEE IF NULL DATA OR NOT (selects appropriate subroutine)
DATA_IN:
LCALL DATA_ARM
;GET THE VALID DATA
LCALL WRCHAR
;SEND IT TO THE DISPLAY
DJNZ 30H,DATA_IN
;COMPARE LOOP AND DECREMENT UNTIL ZERO
RET
;
GET_DATA:
LCALL DATA_ARM
;GET THE NULL DATA

SET_CUR:

DATA_ARM:

WRCHAR:

WRDATA:

WRCMD:

DJNZ 30H,GET_DATA
RET
MOV B,#46H
LCALL WRCMD
MOV B,32H
LCALL WRDATA
MOV B,33H
LCALL WRDATA
RET
MOV 82H,34H
MOV 83H,35H
MOV A,#00H
MOVC A,@A+DPTR
MOV B,A
INC
DPTR
MOV 34H,82H
MOV 35H,83H
RET
PUSH B
MOV B,#042H
LCALL WRCMD
POP
B
XRL
B,#0FFH
LCALL WRDATA
RET
MOV 0C0H,#03H
MOV 0C0H,#01H
MOV 090H,B
MOV 0C0H,#03H
RET
MOV 0C0H,#07H
MOV 0C0H,#05H
MOV 090H,B
MOV 0C0H,#07H
RET
.END

;SEE IF INNER LOOP IS ZERO


;
;SET ADDRESS POINTER
;CLOCK IN
;RECALL THE LOWER CURSOR POSITION
;CLOCK IN
;RECALL THE HIGHER CURSOR POSITION
;CLOCK IN
;
;MOV LOWER DATA POINTER ON THE STACK
;MOV HIGHER DATA POINTER ON THE STACK
;CLEAR OUT REGISTER FOR TRUE DATA POINTER
;GET THE DATA POINTED TO BY THE DATA POINTER
;SWAP DATA TO B REGISTER
;INCREMENT THE DATA POINTER
;RESTORE LOWER DATA (includes increment)
;RESTORE HIGHER DATA
;
;STORE DATA
;SETS WRITE DATA COMMAND
;CLOCK IN
;RECALL DATA
;INVERSE DATA TO PREVENT INVERSE VIDEO
;GO CLOCK IN
;
;SETS WR AND RD HIGH AND A0 LOW
;STROBE WR LOW
;PUTS DATA ON PORT 1
;STROBE WR HIGH
;
;SETS WR, RD, AND A0 HIGH
;STROBE WR LOW
;PUTS COMMAND ON PORT 1
;STROBE WR HIGH
;

There are a lot more tricks associated with the individual controller that you choose to
use. Some of them write the data left to right, some go right to left, and some go up to down.
You will have to slightly vary your address pointer on the LCD display to accommodate this.
There are also other tricks with using the pictures to act as your display background while you
move discrete bytes of data around inside the image (like in a video game). Densitron
Corporation has more information on these processes and how they can be implemented in your
particular display. If you would like more information on anything in this application note,
please contact Todd Fitzsimmons at Densitron Corporation America at 562-941-5000x247.

Submitted by Todd Fitzsimmons


Electrical Engineer
Densitron Corporation America
4/23/98

Vous aimerez peut-être aussi