Copied with permission from http://home.clear.net.nz/pages/joecolquitt/text2lcd.html
This page is a companion to
LCD BMP at
PICList and uses the same board and schematic
NOTE : - the routines here are not examples of compact code. They are intended
to show general methods and help the user understand how these graphic screens
work to develop their own s/w for line drawing, animations etc. For instance,
routines could be optimised as general modules which can receive a variety
of values, such as the result of an ADC conversion, x,y positions, scrolling
etc, rather than these hard-coded examples.
In these example routines, character data is stored in PIC program memory
and fetched with the table commands. It could be stored in other memory,
like an external EEPROM, and fetched with eg I2C or SPI. This may suit some
applications or micros better.
The examples given here are based on containing data within discrete pages.
However, with a little manipulation, data can be split so that eg an 8-bit
character straddles two pages.
For example, the top half of a character can be in the lower half of Page
2, and the lower half of the character goes into the top half of Page 3

Using Boolean operators (eg AND) and shifts of a character's shape data,
it can be placed anywhere and also merged with another for animations etc
and line drawings which, for example, cross.
The display memory can be read, enabling one character to 'pass through'
another by using logic such as inclusive-ORing (IOR) and AND-ing
The scrolling register, line_base ; would be unchanged for a static display.
However, putting line_base in a 0-64 loop will demonstrate what it does.
Any text on the screen moves upwards as line_base is increased (and conversely
will move down as line_base is decreased)
It will wrap-around and re-appear at the bottom of the screen, stopping at
its original position when line_base = 64 (actually 0 again, as the argument
of line_base won't reach into bits 6 and 7)
As well as the text/picture moving, the pages also move. In this routine,
the right-hand side of the screen scrolls upwards 8 lines. Page 0 rolls out
of the top of the screen and is now at the bottom of the screen, with Page
7 above it. The small box drawn in Page 0 is therefore at the bottom of the
screen, immediately to the right of centre.
bcf cs1 ;enable right-hand controller
usec
bsf cs2
usec
clrf temp0 ;scroll counter
scroll movfw temp0
addlw line_base
call write_c
call ms100 ;100ms delay, so scroll can be seen
incf temp0 ;increment, test for > 8
movlw .8
cpfsgt temp0 ;yes
bra scroll ;no, loop
;print position for box
movlw y_base+.0 ;column 0
call write_c
movlw page_base+.0 ;Page 0
call write_c
movlw b'11100011' ;box with a ding in it
call write_d
movlw b'10000001'
call write_d
movlw b'10011001'
call write_d
movlw b'10000001'
call write_d
movlw b'10000001'
call write_d
movlw b'11111111'
call write_d
By introducing new display data, the 128x64 area can appear to scroll up/down
through a much longer screen. Perhaps showing more menu options, or scrolling
to a new screen as an alternative to clearing and printing one.
Note that this screen has two controllers, and is really two 64x64 screens
that can be scrolled independently in either direction, so more than whole-screen
effects are possible.
------------------------------------------------------------------------------
As explained in the companion page, these LCDs display a data byte as a vertical
column.
Here's the shape (taken from the HD44780 datasheet) of a lower-case 't' which
is drawn rotated right, and its 5 bytes of data compiled in that orientation,
to become 5 columns.

------------------------------------------------------------------------------
;PIC (18F) set-up
#define do_alt flags,0 ;= 0 standard, = 1 descenders
;per KS0108 datasheet
;page_base = b'10111000' ;b8 + 0 - 7 (Page number)
;y_base = b'01000000' ;40 + address 0 - 63 (Column number)
;line_base = b'11000000' ;c0 + line 0 - 63 (Scrolling)
page_base = 0xb8
y_base = 0x40
line_base = 0xc0
rom_ram macro var ;macro to copy string from ROM to RAM
movlw upper(var) ;load TBLPTR with string address
movwf tblptru
movlw high(var)
movwf tblptrh
movlw low(var)
movwf tblptrl
tblrd*+
call get_txt
endm
dispw macro ;display WREG
call write_d
endm
;two arrays
cblock 0x0040
str_temp:32 ;RAM copy of string in ROM
endc
cblock 0x0060
chars:32 ;descender/not descender
endc
;Arbitrary data storage addresses in PIC program memory
strings = 0x1000
ch16 = 0x1200
asc5x7 = ch16+0x800
movlw 0x00 ;initialise scroll register
addlw line_base
call write_c
;----------------
Here are two examples of text. The top line is standard 5 x 7, as per a typical
alphanumeric (eg 16 x 2) LCD. The lower line shows the same with alternate
descender characters used instead

The routine below is in two sections, Pass 1 and Pass 2
The method I've chosen, because on this PIC I think it's as good as any other,
is (if the do_alt flag is set) to note during Pass 1 which characters will
be replaced with alternates.
Assuming do_alt is set -
After the rom_ram jazz macro has executed, a copy of the string is in a RAM
array at 0x0040
Before a character is printed in Pass 1, it's tested to see if it's a descender
character that can be replaced. If it is, then its standard ASCII number
is substituted by the alternate drawing. The top half of the character is
drawn in Pass 1 and the alternate ASCII is recorded in a separate array (at
0x0060) for printing the lower half of the character in Pass 2. If it isn't
a replaceable descender character, then a space (ie blank character) is
recorded
So, after Pass 1 j z z , g y p have been found, replaced, top halves drawn,
and the array created for Pass 2 drawing.

a E and t do not have any descender data, spaces are recorded for their lower
halves
;Display standard 16x2 characters, with optional alternate descender
;characters using extra data and a page lower
;
;If displaying descenders (or characters more than 8 pixels high)
;
;Test character to be displayed. If not a descender character
;then store 0x20 (space) at its position in an arrary. If it is a
;descender character, then store the alternate character number
;at its position in the array
alt_ch lfsr fsr0,chars ;for Pass 2 array, 0x20's and 128+
lfsr fsr1,str_temp ;RAM copy of ROM string
rom_ram jazz ;copy "jazz,Egypt" string from ROM to RAM
clrf postinc1 ;add trailing 0
lfsr fsr1,str_temp ;reset RAM string pointer
;----------------
;Pass 1, display character (optionally the top half of a tall character)
pass1 movlw low(asc5x7) ;5x7 character data base address
movwf tblptrl
movlw high(asc5x7)
movwf tblptrh
clrf tblptru
movfw postinc1 ;get character from string in RAM
skpnz ;exit if 0x00, ie end of string
goto pass2 ;Pass 1 complete
;----------------
;Optional, note any descender characters for Pass 2
call test_alt ;test if a descender character
movff alt_char,postinc0 ;store result in array for second pass
;----------------
addlw -0x20 ;subtract 0x20 from W
mullw .10 ;x 5 x 2 = offset from base address
;ie 5 words per character
movfw prodl ;add offset to base address
addwf tblptrl
movfw prodh
addwfc tblptrh
movlw .5 ;number of data bytes to retrieve
movwf temp0
movlw 0x00 ;display a blank leading column
call write_d
p1_data tblrd*+ ;fetch low byte of data word
movff tablat,wreg
call write_d ;display it
tblrd*+ ;fetch high byte of data word
;but ignore data for Pass 1
decfsz temp0
bra p1_data ;loop for 5 bytes
bra pass1 ;loop until end of string
;----------------
;Pass 2. Reset display position, display space or more data
pass2 btfss do_alt ;Pass 2 if doing descenders
return ;or exit for standard characters
movfw column
addlw y_base ;reset to column 10
call write_c
movfw page_copy ;next page down from Pass 1
call write_c
lfsr fsr0,chars ;array, spaces and descender characters
next_p2 movlw low(asc5x7) ;5x7 character data base address
movwf tblptrl
movlw high(asc5x7)
movwf tblptrh
clrf tblptru
movfw postinc0 ;get character from string in RAM
skpnz ;exit if 0x00, ie end of string
return
addlw -0x20 ;offset
mullw .10
movfw prodl ;add offset to base address
addwf tblptrl
movfw prodh
addwfc tblptrh
movlw .5 ;number of data bytes to retrieve
movwf temp0
movlw 0x00 ;display a blank leading column
call write_d
p2_data tblrd*+ ;fetch low byte of data word
;ignore it for Pass 2
tblrd*+ ;fetch high byte
movff tablat,wreg
call write_d ;display it
decfsz temp0
bra p2_data ;loop for 5 bytes
bra next_p2 ;next character
;----------------
;test character for substitution by one with a true descender
test_alt btfss do_alt ;exit if do_alt = 0
return ;ie do not detect and replace
movwf temp0 ;temp store character
movlw .128 ;alternate character base code
movwf alt_char
;test for , g j p q y or z
movfw temp0
xorlw ","
bz ch128 ;is ,
xorlw ","^"g"
bz ch129 ;is g
xorlw "g"^"j"
bz ch130 ;is j
xorlw "j"^"p"
bz ch131 ;is p
xorlw "p"^"q"
bz ch132 ;is q
xorlw "q"^"y"
bz ch133 ;is y
xorlw "y"^"z"
bz ch134 ;is z
movlw 0x20 ;ASCII space
movwf alt_char ;not descender, store lower-half space
movfw temp0 ;and restore character to W
return
;increment alt_char to match character's ASCII
ch134 incf alt_char ;ASCII code for alternate character
ch133 incf alt_char
ch132 incf alt_char
ch131 incf alt_char
ch130 incf alt_char
ch129 incf alt_char
ch128 nop
movfw alt_char ;replace standard with alternate
return
;================================================
; Copy a text string
;================================================
get_txt movfw tablat ;get characters until
btfsc wreg,7 ;W > 0x7f (ie FF terminator)
return
movwf postinc1 ;store in RAM
tblrd*+
bra get_txt
;================================================
; Data
;================================================
org strings
jazz db "jazz,Egypt",0xff
v_str db "Voltage",0xff
;------------
org ch16
;Standard LCD numbers, twice size, drawn rotated right
;(the sharp-eyed will notice the data repetition)
dw 0x0ffc,0x0ffc,0x3303,0x3303,0x30c3,0x30c3,0x3033,0x3033,0x0ffc,0x0ffc ;0
dw 0x0000,0x0000,0x300c,0x300c,0x3fff,0x3fff,0x3000,0x3000,0x0000,0x0000 ;1
dw 0x300c,0x300c,0x3c03,0x3c03,0x3303,0x3303,0x30c3,0x30c3,0x303c,0x303c ;2
dw 0x0c03,0x0c03,0x3003,0x3003,0x3033,0x3033,0x30cf,0x30cf,0x0f03,0x0f03 ;3
dw 0x03c0,0x03c0,0x0330,0x0330,0x030c,0x030c,0x3fff,0x3fff,0x0300,0x0300 ;4
dw 0x0c3f,0x0c3f,0x3033,0x3033,0x3033,0x3033,0x3033,0x3033,0x0fc3,0x0fc3 ;5
dw 0x0ff0,0x0ff0,0x30cc,0x30cc,0x30c3,0x30c3,0x30c3,0x30c3,0x0f00,0x0f00 ;6
dw 0x0003,0x0003,0x3f03,0x3f03,0x00c3,0x00c3,0x0033,0x0033,0x000f,0x000f ;7
dw 0x0f3c,0x0f3c,0x30c3,0x30c3,0x30c3,0x30c3,0x30c3,0x30c3,0x0f3c,0x0f3c ;8
dw 0x003c,0x003c,0x30c3,0x30c3,0x30c3,0x30c3,0x0cc3,0x0cc3,0x03fc,0x03fc ;9
;------------
org asc5x7 ;5x7 ASCII set without descenders
;Standard LCD characters, normal size, drawn rotated right
8-bit x 5 '0'

16-bit x 5 '0'

16-bit x 5 'g', including descender in upper byte

;16-bit data, can ignore leading 00 if descenders not needed
;
;ASCII 0x20 - 0x2f, d32 - d47
dw 0x0000,0x0000,0x0000,0x0000,0x0000 ;space
dw 0x0000,0x0000,0x005f,0x0000,0x0000 ;!
dw 0x0000,0x0007,0x0000,0x0007,0x0000 ;"
dw 0x0014,0x007f,0x0014,0x007f,0x0014 ;#
dw 0x0024,0x002a,0x007f,0x002a,0x0012 ;$
dw 0x0023,0x0013,0x0008,0x0064,0x0062 ;%
dw 0x0036,0x0049,0x0055,0x0022,0x0050 ;&
dw 0x0000,0x0005,0x0003,0x0000,0x0000 ;'
dw 0x0000,0x001c,0x0022,0x0041,0x0000 ;(
dw 0x0000,0x0041,0x0022,0x001c,0x0000 ;)
dw 0x0014,0x0008,0x003e,0x0008,0x0014 ;*
dw 0x0008,0x0008,0x003e,0x0008,0x0008 ;+
dw 0x0000,0x0050,0x0030,0x0000,0x0000 ;,
dw 0x0008,0x0008,0x0008,0x0008,0x0008 ;-
dw 0x0000,0x0060,0x0060,0x0000,0x0000 ;.
dw 0x0020,0x0010,0x0008,0x0004,0x0002 ;/
;ASCII 30 - 3f, 48 - 63
dw 0x003e,0x0051,0x0049,0x0045,0x003e ;0
dw 0x0000,0x0042,0x007f,0x0040,0x0000 ;1
dw 0x0042,0x0061,0x0051,0x0049,0x0046 ;2
dw 0x0021,0x0041,0x0045,0x004b,0x0031 ;3
dw 0x0018,0x0014,0x0012,0x007f,0x0010 ;4
dw 0x0027,0x0045,0x0045,0x0045,0x0039 ;5
dw 0x003c,0x004a,0x0049,0x0049,0x0030 ;6
dw 0x0001,0x0079,0x0005,0x0003,0x0001 ;7
dw 0x0036,0x0049,0x0049,0x0049,0x0036 ;8
dw 0x0006,0x0049,0x0049,0x0029,0x001e ;9
dw 0x0000,0x0036,0x0036,0x0000,0x0000 ;:
dw 0x0000,0x0056,0x0036,0x0000,0x0000 ;;
dw 0x0008,0x0014,0x0022,0x0041,0x0000 ;<
dw 0x0014,0x0014,0x0014,0x0014,0x0014 ;=
dw 0x0000,0x0041,0x0022,0x0014,0x0008 ;>
dw 0x0002,0x0001,0x0051,0x0009,0x0006 ;?
;ASCII 40 - 4f, 64 - 79
dw 0x0032,0x0049,0x0079,0x0041,0x003e ;@
dw 0x007e,0x0011,0x0011,0x0011,0x007e ;A
dw 0x007f,0x0049,0x0049,0x0049,0x0036 ;B
dw 0x003e,0x0041,0x0041,0x0041,0x0022 ;C
dw 0x007f,0x0041,0x0041,0x0022,0x001c ;D
dw 0x007f,0x0049,0x0049,0x0049,0x0041 ;E
dw 0x007f,0x0009,0x0009,0x0009,0x0001 ;F
dw 0x003e,0x0041,0x0049,0x0049,0x007a ;G
dw 0x007f,0x0008,0x0008,0x0008,0x007f ;H
dw 0x0000,0x0041,0x007f,0x0041,0x0000 ;I
dw 0x0020,0x0041,0x0041,0x003f,0x0001 ;J
dw 0x007f,0x0008,0x0014,0x0022,0x0041 ;K
dw 0x007f,0x0040,0x0040,0x0040,0x0040 ;L
dw 0x007f,0x0002,0x00c0,0x0002,0x007f ;M
dw 0x007f,0x0004,0x0008,0x0010,0x007f ;N
dw 0x007e,0x0041,0x0041,0x0041,0x007e ;O
;ASCII 50 - 5f, 80 - 95
dw 0x007f,0x0009,0x0009,0x0009,0x0006 ;P
dw 0x003e,0x0041,0x0051,0x0021,0x005e ;Q
dw 0x007f,0x0009,0x0019,0x0029,0x0046 ;R
dw 0x0026,0x0049,0x0049,0x0049,0x0032 ;S
dw 0x0001,0x0001,0x007f,0x0001,0x0001 ;T
dw 0x003f,0x0040,0x0040,0x0040,0x003f ;U
dw 0x001f,0x0020,0x0040,0x0020,0x001f ;V
dw 0x003f,0x0040,0x0030,0x0040,0x003f ;W
dw 0x0063,0x0014,0x0008,0x0014,0x0063 ;X
dw 0x0007,0x0008,0x0070,0x0008,0x0007 ;Y
dw 0x0061,0x0051,0x0049,0x0045,0x0043 ;Z
dw 0x0000,0x007f,0x0041,0x0041,0x0000 ;[
dw 0x0000,0x0000,0x0000,0x0000,0x0000 ;spare (Yen)
dw 0x0000,0x0041,0x0041,0x007f,0x0000 ;]
dw 0x0004,0x0002,0x0001,0x0002,0x0004 ;^
dw 0x0001,0x0001,0x0001,0x0001,0x0001 ;_
;ASCII 60 - 6f, 96 - 111
dw 0x0000,0x0001,0x0002,0x0004,0x0000 ;'
dw 0x0020,0x0054,0x0054,0x0054,0x0078 ;a
dw 0x007f,0x0048,0x0044,0x0044,0x0038 ;b
dw 0x0038,0x0044,0x0044,0x0044,0x0020 ;c
dw 0x0038,0x0044,0x0044,0x0048,0x007f ;d
dw 0x0038,0x0054,0x0054,0x0054,0x0018 ;e
dw 0x0008,0x007e,0x0009,0x0001,0x0002 ;f
dw 0x000c,0x0052,0x0052,0x0052,0x003e ;g
dw 0x007f,0x0008,0x0004,0x0004,0x0078 ;h
dw 0x0000,0x0044,0x007d,0x0040,0x0000 ;i
dw 0x0020,0x0040,0x0040,0x003d,0x0000 ;j
dw 0x007f,0x0010,0x0028,0x0044,0x0000 ;k
dw 0x0000,0x0041,0x007f,0x0040,0x0000 ;l
dw 0x007c,0x0004,0x0018,0x0004,0x0078 ;m
dw 0x007c,0x0008,0x0004,0x0004,0x0078 ;n
dw 0x0038,0x0044,0x0044,0x0044,0x0038 ;o
;ASCII 70 - 7f, 112 - 127
dw 0x007c,0x0014,0x0014,0x0014,0x0008 ;p
dw 0x0008,0x0014,0x0014,0x0018,0x007c ;q
dw 0x007c,0x0008,0x0004,0x0004,0x0008 ;r
dw 0x0048,0x0054,0x0054,0x0054,0x0020 ;s
dw 0x0004,0x003f,0x0044,0x0040,0x0020 ;t
dw 0x003c,0x0040,0x0040,0x0020,0x007c ;u
dw 0x001c,0x0020,0x0040,0x0020,0x001c ;v
dw 0x003c,0x0040,0x0030,0x0040,0x003c ;w
dw 0x0044,0x0028,0x0001,0x0028,0x0044 ;x
dw 0x000c,0x0050,0x0050,0x0050,0x003c ;y
dw 0x0044,0x0064,0x0054,0x004c,0x0044 ;z
dw 0x0000,0x0008,0x0036,0x0041,0x0000 ;{
dw 0x0000,0x0000,0x007f,0x0000,0x0000 ;|
dw 0x0000,0x0041,0x0036,0x0008,0x0000 ;}
dw 0x0008,0x0008,0x002a,0x001c,0x0008 ;->
dw 0x0008,0x001c,0x002a,0x0008,0x0008 ;<-
;alternates with descenders, ASCII 80 - 85, 128 - 134
dw 0x0000,0x0140,0x00c0,0x0000,0x0000 ;, ASCII 80, 128
dw 0x0038,0x0244,0x0244,0x0244,0x01f8 ;g ASCII 81, 129
dw 0x0100,0x0200,0x0204,0x01fd,0x0000 ;j ASCII 82, 130
dw 0x03f8,0x0044,0x0044,0x0044,0x0038 ;p ASCII 83, 131
dw 0x0038,0x0044,0x0144,0x02c4,0x0238 ;q ASCII 84, 132
dw 0x003c,0x0240,0x0240,0x0240,0x01fc ;y ASCII 85, 133
dw 0x0108,0x0244,0x0244,0x0224,0x01d8 ;z ASCII 86, 134
end
----------------------------------------------------------------------------------
;Display '278 in large numbers across mid-screen boundary
;with 'Voltage' label underneath
Once again, the 4-part code here shows just one way to do this
;Start display at a known (x,y) co-ordinate 48,16
;1st digit is contained entirely within controller 1's side
bsf cs1 ;select left-hand controller
usec
bcf cs2
usec
d278 movlw .48 ;48th column
movwf column
addlw y_base
call write_c
movlw .2 ;3rd page (starts @ line 16)
addlw page_base
call write_c
movlw low(ch16) ;data base address (ie character "0")
movwf tblptrl
movlw high(ch16)
movwf tblptrh
clrf tblptru
;----------------
movlw .2 ;offset to first digit "2"
mullw .20 ;at 20 bytes (10 words) of data per character
movfw prodl ;add character offset to base address
addwf tblptrl
movfw prodh
addwfc tblptrh
;----------------
;top half of character
movlw .10 ;data counter
movwf temp0
top_c1 tblrd*+ ;fetch low byte
movfw tablat
call write_d ;display it
tblrd*+ ;fetch, ignore, high byte
decfsz temp0 ;loop
bra top_c1
;bottom half of character
movfw column ;reset to coumn 48
addlw y_base
call write_c
movlw .3
addlw page_base ;next page, page 4 (starts @ line 24)
call write_c
;fetch same data words as before but use the high bytes
movlw low(ch16) ;data base address (ie character 0)
movwf tblptrl
movlw high(ch16)
movwf tblptrh
clrf tblptru
movlw .2 ;first digit
mullw .20 ;20 bytes of data per character
movfw prodl ;add character offset
addwf tblptrl ;to base address
movfw prodh
addwfc tblptrh
movlw .10 ;data counter
movwf temp0
bot_c1 tblrd*+ ;fetch low byte, ignore
tblrd*+
movfw tablat
call write_d ;display it
decfsz temp0 ;loop
bra bot_c1
;----------------
movlw 0x00 ;two-pixel space before next digit
call write_d ;column = 58
call write_d ; = 59
;column for start of second character = 60
;go back up a page for top half of next character
movlw .2 ;3rd page (starts @ line 16)
addlw page_base
call write_c
movlw low(ch16) ;data base address (ie character 0)
movwf tblptrl
movlw high(ch16)
movwf tblptrh
clrf tblptru
;----------------
movlw .7 ;offset to data for second digit "7"
mullw .20 ;at 20 bytes (10 words) of data per character
movfw prodl ;add character offset to base address
addwf tblptrl
movfw prodh
addwfc tblptrh
;----------------
;top half of character
clrf temp0 ;data counter
top_c2 tblrd*+ ;fetch low byte
movfw tablat
call write_d ;display it
tblrd*+ ;fetch, ignore, high byte
incf temp0 ;if temp0 = 10, top is finished
movlw .10
cpfslt temp0 ;else not 10, check for boundary
bra c2_low
;if column is < 64 then set cs1
;if column is = 64 then set cs2
movlw .4
cpfseq temp0 ;start column (60) + 4 data = 64
bra top_c2
bcf cs1 ;switch to right-hand controller
usec
bsf cs2
usec
movlw .0 ;and column 0
addlw y_base
call write_c
movlw .2
addlw page_base ;maintain page number
call write_c
bra top_c2 ;loop
;bottom half of character
c2_low bsf cs1 ;back to left-hand controller
usec
bcf cs2
usec
movlw .60 ;reset to column 60
addlw y_base
call write_c
movlw .3
addlw page_base ;down a page (starts @ line 24)
call write_c
;fetch same data words as before but use the high bytes
c2_datl movlw low(ch16) ;data base address (ie character 0)
movwf tblptrl
movlw high(ch16)
movwf tblptrh
clrf tblptru
movlw .7 ;second digit, "7"
mullw .20 ;20 bytes of data per character
movfw prodl ;add character offset
addwf tblptrl ;to base address
movfw prodh
addwfc tblptrh
clrf temp0 ;data counter
bot_c2 tblrd*+ ;fetch low byte, ignore
tblrd*+ ;fetch high byte
movfw tablat
call write_d ;display it
incf temp0 ;if temp0 = 10, bottom is finished
movlw .10
cpfslt temp0 ;not 10, check for boundary
bra digit3 ;else finished
;if column is < 64 then set cs1
;if column is > 63 then set cs2
movlw .4
cpfseq temp0
bra bot_c2
bcf cs1 ;switch to right-hand controller
usec
bsf cs2
usec
movlw .0 ;and column 0
addlw y_base
call write_c
movlw .3
addlw page_base
call write_c
bra bot_c2
;----------------
;3rd digit is contained entirely within controller 2's side
digit3 movlw 0x00 ;two-pixel space before next digit
call write_d
call write_d
movlw .2 ;3rd page (starts @ line 16)
addlw page_base
call write_c
movlw low(ch16) ;data base address (ie character 0)
movwf tblptrl
movlw high(ch16)
movwf tblptrh
clrf tblptru
;----------------
movlw .8 ;offset to third digit "8"
mullw .20 ;at 20 bytes (10 words) of data per character
movfw prodl ;add character offset to base address
addwf tblptrl
movfw prodh
addwfc tblptrh
;----------------
;top half of character
movlw .10 ;data counter
movwf temp0
top_c3 tblrd*+ ;fetch low byte
movfw tablat
call write_d ;display it
tblrd*+ ;fetch, ignore, high byte
decfsz temp0 ;loop
bra top_c3
;bottom half of character
movlw .8 ;reset to column 8
addlw y_base
call write_c
movlw .3
addlw page_base ;next page (starts @ line 24)
call write_c
;fetch same data words as before but use the high bytes
movlw low(ch16) ;data base address (ie character 0)
movwf tblptrl
movlw high(ch16)
movwf tblptrh
clrf tblptru
movlw .8 ;third digit
mullw .20 ;20 bytes of data per character
movfw prodl ;add character offset
addwf tblptrl ;to base address
movfw prodh
addwfc tblptrh
movlw .10 ;data counter
movwf temp0
bot_c3 tblrd*+ ;fetch low byte, ignore
tblrd*+
movfw tablat
call write_d ;display it
decfsz temp0 ;loop
bra bot_c3
call v_label ;the routine where you get to figure
;out how to break a character across
;the mid-screen boundary
| file: /Techref/microchip/io/dev/lcd/Txt2GraphicLCDPIC18F.htm, 27KB, , updated: 2013/6/10 16:50, local time: 2025/10/28 05:18,
216.73.216.22,10-3-83-201:LOG IN
|
| ©2025 These pages are served without commercial sponsorship. (No popup ads, etc...).Bandwidth abuse increases hosting cost forcing sponsorship or shutdown. This server aggressively defends against automated copying for any reason including offline viewing, duplication, etc... Please respect this requirement and DO NOT RIP THIS SITE. Questions? <A HREF="http://www.piclist.com/Techref/microchip/io/dev/lcd/Txt2GraphicLCDPIC18F.htm"> Text to graphic LCD using PIC 18F</A> |
| Did you find what you needed? |
|
o List host: MIT, Site host massmind.org, Top posters @none found - Page Editors: James Newton, David Cary, and YOU! * Roman Black of Black Robotics donates from sales of Linistep stepper controller kits. * Ashley Roll of Digital Nemesis donates from sales of RCL-1 RS232 to TTL converters. * Monthly Subscribers: Gregg Rew. on-going support is MOST appreciated! * Contributors: Richard Seriani, Sr. |
|
Ashley Roll has put together a really nice little unit here. Leave off the MAX232 and keep these handy for the few times you need true RS232! |
.