;**********************************************************TST_GLCD***********************************************************
; Author : R Raghunathan / 04 August 2003.
; Assembler : Pinnacle 52
;TST_GLCD is for testing out the functions of a 128 x 64 Graphic LCD module with Driver KS0108B from
; Samsung. The complete module has two such drivers - one for the left half of the display and the other
; for the right half - and the total columns add up to 128. The data sheet for the driver is silent on the
; memory map of the pixel - hence I have (tried to !) describe it below.
; A short description on the memory map of the pixels : ( A sketch would have been better - but then it
; cannot opened in a notepad !! So lets manage with a description)
; The following apply to the left half of the display and is the same for the right half. (To select the right half
; the CS1 bit is set and to select the left half the CS2 bit is set.)
; Each driver KS0108B controls a 64 column by 64 row pixel array. The 64 pixel row arrays are further
; grouped into 8 pages - and each page is 8 bits or 1 Byte tall. Thus when you write a Byte, based on the
; Page address and Column address, this "8 bit tall" area is filled up . The LSB bit of the data byte
; is at the top and the MSB bit is at the bottom.
; The first top most Page address is 0x0b8 and the lowermost page is 0x0c0. Likewise the left most column
; has an address of 0x040 and the rightmost column is at 0x080.
; Whenever you write or read data into the display RAM, the column address alone is incremented
; automatically by one. And when the increment happens after the last column (0x080), your code should
; should change the Column address to proceed as per need - else it rolls over and overwrites on the first
; column in the current page !
; For rest of the read / write instructions please refer to the data sheet of KS0108B
; In the coding X_Address refers to the page and Y_Address refers to the column and depending on whether
; CS1 or CS2 is set the write will happen either in the left or right column respectively.
; I have not used the write instructions with the busy bit checking. I found that this was unreliable in
; many occasions - maybe my code had a bug - so just introduced a 10micro delay before each write. There has
; been no problems on account of this.
;
; Timings suitable for 80c51RD2 running with 6MHz crystal in 6 Clock mode . ( Each Machine cycle = 1 microsecond )
; The module has the following routines for check out :
; ;FillChar ;To fill screen with same character
;HorLines ;To fill screen with 1 pixel wide Horizontal lines
;Box ; To draw a 2 pixel wide box margin
;User_Strng ; To display a user defined string
;FillDots ; To demonstrate the way Bytes are written in sequence and finally display a
; THANKS !
;============================================================================================
; port 0 is used for data lines ( each line has a 10k pull up )
; port 1 is used for control lines as listed below
; P1.0 ---RS
; P1.1 ---R / W
; P1.2 ---E
; P1.3 ---CS1
; P1.4 ---CS2
; The #RESET pin of the display is connected to +5V. In case you need to Reset the module without switching off
; power then allocate a port pin for this.
;============================================================================================
Select BIT 00H ; to select cs1 of cs2 (0\1)
SameChar BIT 01H ; to fill display with same character
InvertDis BIT 02H ; To invert display string - not used now
ORG 30H
X_Addr DS 1 ; can be used to pass page address in User_Strng routine ( not used now )
Y_Addr DS 1 ; can be used to pass column address in User_Strng routine ( not used now )
ORG 0000h
MAINl: mov sp, #60h ; Define stack start point
mov p0, #00h ; clear port0
mov p1, #00h ; clear port1
mov r1, #5
Del: call Dly150mS
djnz r1, Del ;150mS delay
call Clr_Disp ;Clear the screen
; After this you have calls to the 5 Demo routines - each demo except FillDots, lasts about 3 secs roughly..
setb SameChar
mov r1, #39 ;Load the ASCII number of character to be displayed here
call FillChar ;To fill screen with above character
call LDelay
call Clr_Disp
call HorLines ;To fill with Horizontal lines
call LDelay
call Clr_Disp
call Box ; To draw a box
call LDelay
call Clr_Disp
call User_Strng ; Display the user defined String
call LDelay
call Clr_Disp
call FillDots ; Fill screen and then display THANKS
jmp $
LDelay: mov r1, #20 ; General purpose delay routine
Del1: call Dly150mS
djnz r1, Del1 ;150 x 20 mS delay = 3 Secs
ret
VarDelay: mov r7, #20h ; General purpose delay routine
DV: mov r0, #0ffh
djnz r0, $
djnz r0, $
djnz r7, DV ; Delay = r7 value x 1536 micros
ret
Clr_Disp: clr Select ;for selection of cs1
call Init_Lcd ;Initialise cs1
call Page_Sel ;clears all pages of cs1
setb Select ;for selection of cs2
call Init_Lcd ;Initialise cs2
call Page_Sel ;clears all pages of cs2
clr Select
ret
Page_Sel: mov r5, #0b8h ;X address counter at First Page
pag_sel1: mov a, r5
call Write_Instr
mov a, #40h ;Y address counter at First Column
call Write_Instr
mov a, #00h ; To be cleared
mov r1, #64
next: call Write_Data
dec r1
cjne r1, #00,next ; Clear all columns in one page
inc r5
cjne r5, #0c0h, pag_sel1 ; Loop for clearing all pages
ret
;=========================================================================
; Routine to fill the display with a particular character
FillChar: mov r5, #0b8h ;X address counter at First Page
LupFill: clr Select ;for selection of cs1
call Write_XY
call CharLup ;fill left half / right half with same character
setb Select ;for selection of cs2
call Write_XY
inc r5 ;for all 8 pages
cjne r5, #0c0h, LupFill
ret
Write_XY: mov a, #40h ; Y address counter at First Column
call Write_Instr
mov a, r5 ; X address counter at 00h
call Write_Instr
call CharLup
ret
CharLup: mov r3, #00h
LupAgn: mov a, #00h
call Write_Data
mov dptr, #Font_Table
call Write_Char
mov a, #00h
call Write_Data
mov a, #00h
call Write_Data
jb SameChar, SameR1
call Dly150mS
inc r1 ;Load next character for display
SameR1: inc r3
cjne r1, #5fh, NxtChar
mov r1, #00h
NxtChar: cjne r3, #8, LupAgn
ret
;===========================================================================
FillDots: clr Select
mov r3, #0b8h ; First page
NextPage: mov a, r3 ; page counter
call Write_Instr
mov a, #040h ; First column..
call Write_Instr
mov r4, #0 ; CS1 column counter
mov r6, #0 ; Total coulmn counter
PagLup: call VarDelay ; So that you can see the filling...
mov a, #0ffh
call Write_Data
call Sel_Cs2
inc r6
cjne r6, #128, PagLup
clr Select
inc r3
cjne r3, #0c0h, NextPage
call Clr_Disp ; Now clear the screen
call Box ; Draw the box margin...
call User_Strng ; display THANKS! in the middle before returning
Over: ret
Sel_Cs2: inc r4 ; To automatically switch to CS2
cjne r4, #40h, NoCs2
setb Select ; change to right half...
mov a, r3 ; without this it writes to last page of CS2
call Write_Instr
mov a, #040h
call Write_Instr
NoCs2: ret
;===========================================================================
;Routine to draw horzontal lines in full screen
HorLines: mov r5, #0b8h ;Page counter
mov r3, #0 ;Column counter
clr Select ; Left half display selected
NxtPat: nop
Sect2: mov a, #40h
call Write_Instr ;Y start address
mov a, r5
call Write_Instr ;X start address
PLoop: mov a, #55h ;Horizontal hatching whole screen
call Write_Data
inc r3
cjne r3, #64, PLoop
mov r3, #0 ;Init column counter for next page
inc r5
cjne r5, #0c0h, NxtPat ; One page over. Do next
jnb Select, SetCs2
jb Select, Exit ; Second half also over - exit
SetCs2: setb Select
mov r5, #0b8h
mov r3, #0
jmp Sect2
Exit: ret
;========================================================================
;Routine to draw a box that is 2 pixel wide on the periphary of the display area.
Box: clr Select
BoxCs2: mov r3, #0
mov a, #0b8h
call Write_Instr
mov a, #40h
call Write_Instr ;First page first column CS1 (and then CS2)
TLineLup: mov a, #03h ;Horizontal line - 2 pixel wide..
call Write_Data
inc r3
cjne r3, #64, TLineLup
jb Select, BLine
setb Select
jmp BoxCs2
BLine: clr Select
BlnCs2: mov r3, #0
mov a, #0bfh ; Last page
call Write_Instr
mov a, #40h
call Write_Instr ;Last page first column CS1 (and then CS2)
BLineLup: mov a, #0C0h ;Horizontal line - 2 pixel wide..
call Write_Data
inc r3
cjne r3, #64, BLineLup
jb Select, RVerLine
setb Select
jmp BlnCs2
RVerLine: setb Select ;Already set. Just for comparing with LVerLine
mov r3, #0b8h
VerLup: mov a, r3
call Write_Instr
mov a, #7eh ;63rd column CS2
call Write_Instr
mov a, #0ffh
call Write_Data
mov a, #0ffh
call Write_Data
inc r3
cjne r3, #0c0h, VerLup
LVerLine: clr Select
mov r3, #0b8h
VerLup1: mov a, r3
call Write_Instr
mov a, #40h ;1st Column CS1. Always write column address AFTER page address
call Write_Instr
mov a, #0ffh
call Write_Data
mov a, #0ffh
call Write_Data
inc r3
cjne r3, #0c0h, VerLup1
ret
;==================================================================
; TIP : For demo, a fixed X and Y address is used. To make it universal you can pass these references
; via X_Addr and Y_Addr and InvertDis ram locations. And modify this code to handle them.
User_Strng: clr Select ; Display the user defined string...
mov a, #0b8h ; Start X address
call Write_Instr
mov r4, #70h ; Start Y address
mov a, r4
call Write_Instr
mov r5, #0
mov r3, #0
NextCh: mov dptr, #UserMssg
mov a, r3
movc a, @a+dptr ;Get the ASCII of Character
cjne a, #30h, ChkSpace ;check for "0" and if yes return
jmp EofString
ChkSpace: cjne a, #20h, Proceed ;check for Space
jmp Space
Proceed: clr c
subb a, #33 ;adjust the begining of the table
mov dptr, #Font_Table
mov b, #05h ;Offset for 5 columns for each character
mul ab
clr c
add a,dpl ;LSB in acc
mov dpl,a
mov a,b ;MSB in B
addc a, dph
mov dph, a ;DPTR now contains pointer to first data byte
NxtByte: mov a, #0
movc a, @a+dptr
;cpl a ; for inverted display
call Write_Data
call Swt_Cs2
inc dptr
inc r5
cjne r5, #5, NxtByte
mov a, #0
;cpl a ; for inverted display
call Write_Data ; 1 Pixel gap between characters
call Swt_Cs2
mov r5, #0
jmp NoSpace
Space: mov a, #0
;cpl a ; for inverted display
call Write_Data ; For 2 pixel space
call Swt_Cs2
mov a, #0
;cpl a ; for inverted display
call Write_Data
call Swt_Cs2
NoSpace: inc r3
jmp NextCh
EofString: ret
Swt_Cs2: inc r4 ; To automatically switch to CS2
cjne r4, #80h, NoSwt ; Last column = 80h
setb Select
nop
nop
mov a, #0b8h ; without this it writes to last page of CS2
call Write_Instr
mov a, #40h
call Write_Instr
NoSwt: ret
UserMssg: db 'THANKS ! 0 ' ; Message to display .Must terminate with a "0"
;===============================================================================
Init_Lcd: mov a, #3eh ; Display off
call Write_Instr
mov r7, 0ffh
djnz r7, $
mov a, #3fh ; Display on
call Write_Instr
mov r7, #0ffh
djnz r7, $
mov a, #0c0h ;
call Write_Instr
mov a, #40h ; Y address counter at First column
call Write_Instr
mov a, #0b8h ; X address counter at 00h
call Write_Instr
ret
Write_Char: clr c
push dph
push dpl
mov r2, #00h
mov a, r1 ;Get the ASCII of Character
mov b, #05h ;Offset for 5 columns for each character
mul ab
clr c
add a,dpl ;LSB in acc
mov dpl,a
mov a,b ;MSB in B
addc a, dph
mov dph, a ;DPTR now contains pointer to first data byte
Send_Next: mov a, #00h
add a, r2
movc a, @a+dptr
call Write_Data
inc r2
cjne r2, #05h, Send_Next ;Loop till all 5 data bytes are sent for the character
pop dpl
pop dph
ret
Write_Instr: jb Select, Cs_2
clr p1.4
setb p1.3 ;Chip select cs1 enabled
jmp WInstr
Cs_2: clr p1.3
setb p1.4 ;Chip select cs2 enabled
WInstr: nop
mov r0, #10
djnz r0, $
clr p1.1 ;Write mode selected
clr p1.0 ;Instruction mode selected
mov p0, acc ;Place Instruction on bus
setb p1.2 ;Enable High
nop
clr p1.2 ;Enable Low
nop
clr p1.3 ;put cs1 in non select mode
clr p1.4 ;put cs2 in non select mode
ret
Write_Data: jb Select, Cs_2a
clr p1.4
setb p1.3 ;Chip select cs1 enabled
jmp WData
Cs_2a: clr p1.3
setb p1.4 ;Chip select cs2 enabled
WData: nop
mov r0, #10
djnz r0, $
clr p1.1 ;Write mode selected
setb p1.0 ;Data mode selected
mov p0,a ;Place data on bus
setb p1.2 ;Enable High
nop
clr p1.2 ;Enable Low
nop
clr p1.3 ;put cs1 in non select mode
clr p1.4 ;put cs2 in non select mode
ret
Dly150mS: mov r7, #60h
d1: mov r0, #0ffh
djnz r0, $
djnz r0, $
djnz r7, d1
ret
Font_Table:
db 00h, 00h, 4fh, 00h, 00h ; '!'
db 00h, 07h, 00h, 07h, 00h ; '"'
db 14h, 7fh, 14h, 7fh, 14h ; '#'
db 24h, 2ah, 7fh, 2ah, 12h ; '$'
db 23h, 13h, 08h, 64h, 62h ; ' '
db 36h, 49h, 55h, 22h, 50h ; '&'
db 00h, 05h, 03h, 00h, 00h ; '''
db 00h, 1ch, 22h, 41h, 00h ; '('
db 00h, 41h, 22h, 1ch, 00h ; ')'
db 14h, 08h, 3eh, 08h, 14h ; '*'
db 08h, 08h, 3eh, 08h, 08h ; '+'
db 00h, 50h, 30h, 00h, 00h ; ','
db 08h, 08h, 08h, 08h, 08h ; '-'
db 00h, 60h, 60h, 00h, 00h ; '.'
db 20h, 10h, 08h, 04h, 02h ; '/'
db 3eh, 51h, 49h, 45h, 3eh ; '0'
db 00h, 42h, 7fh, 40h, 00h ; '1'
db 42h, 61h, 51h, 49h, 46h ; '2'
db 21h, 41h, 45h, 4bh, 31h ; '3'
db 18h, 14h, 12h, 7fh, 10h ; '4'
db 27h, 45h, 45h, 45h, 39h ; '5'
db 3ch, 4ah, 49h, 49h, 30h ; '6'
db 01h, 71h, 09h, 05h, 03h ; '7'
db 36h, 49h, 49h, 49h, 36h ; '8'
db 06h, 49h, 49h, 29h, 1eh ; '9'
db 00h, 36h, 36h, 00h, 00h ; ':'
db 00h, 56h, 36h, 00h, 00h ; ';'
db 08h, 14h, 22h, 41h, 00h ; '<'
db 14h, 14h, 14h, 14h, 14h ; '='
db 00h, 41h, 22h, 14h, 08h ; '>'
db 02h, 01h, 51h, 09h, 06h ; '?'
db 32h, 49h, 79h, 41h, 3eh ; ' '
db 7eh, 11h, 11h, 11h, 7eh ; 'A'
db 7fh, 49h, 49h, 49h, 36h ; 'B'
db 3eh, 41h, 41h, 41h, 22h ; 'C'
db 7fh, 41h, 41h, 22h, 1ch ; 'D'
db 7fh, 49h, 49h, 49h, 41h ; 'E'
db 7fh, 09h, 09h, 09h, 01h ; 'F'
db 3eh, 41h, 49h, 49h, 7ah ; 'G'
db 7fh, 08h, 08h, 08h, 7fh ; 'H'
db 00h, 41h, 7fh, 41h, 00h ; 'I'
db 20h, 40h, 41h, 3fh, 01h ; 'J'
db 7fh, 08h, 14h, 22h, 41h ; 'K'
db 7fh, 40h, 40h, 40h, 40h ; 'L'
db 7fh, 02h, 0ch, 02h, 7fh ; 'M'
db 7fh, 04h, 08h, 10h, 7fh ; 'N'
db 3eh, 41h, 41h, 41h, 3eh ; 'O'
db 7fh, 09h, 09h, 09h, 06h ; 'P'
db 3eh, 41h, 51h, 21h, 5eh ; 'Q'
db 7fh, 09h, 19h, 29h, 46h ; 'R'
db 46h, 49h, 49h, 49h, 31h ; 'S'
db 01h, 01h, 7fh, 01h, 01h ; 'T'
db 3fh, 40h, 40h, 40h, 3fh ; 'U'
db 1fh, 20h, 40h, 20h, 1fh ; 'V'
db 3fh, 40h, 38h, 40h, 3fh ; 'W'
db 63h, 14h, 08h, 14h, 63h ; 'X'
db 07h, 08h, 70h, 08h, 07h ; 'Y'
db 61h, 51h, 49h, 45h, 43h ; 'Z'
db 00h, 7fh, 41h, 41h, 00h ; '['
db 15h, 16h, 7ch, 16h, 15h ; ' '
db 00h, 41h, 41h, 7fh, 00h ; ']'
db 04h, 02h, 01h, 02h, 04h ; '^'
db 40h, 40h, 40h, 40h, 40h ; '_'
db 00h, 01h, 02h, 04h, 00h ; ' '
db 20h, 54h, 54h, 54h, 78h ; 'a'
db 7fh, 48h, 44h, 44h, 38h ; 'b'
db 38h, 44h, 44h, 44h, 20h ; 'c'
db 38h, 44h, 44h, 48h, 7fh ; 'd'
db 38h, 54h, 54h, 54h, 18h ; 'e'
db 08h, 7eh, 09h, 01h, 02h ; 'f'
db 0ch, 52h, 52h, 52h, 3eh ; 'g'
db 7fh, 08h, 04h, 04h, 78h ; 'h'
db 00h, 44h, 7dh, 40h, 00h ; 'i'
db 20h, 40h, 44h, 3dh, 00h ; 'j'
db 7fh, 10h, 28h, 44h, 00h ; 'k'
db 00h, 41h, 7fh, 40h, 00h ; 'l'
db 7ch, 04h, 18h, 04h, 78h ; 'm'
db 7ch, 08h, 04h, 04h, 78h ; 'n'
db 38h, 44h, 44h, 44h, 38h ; 'o'
db 7ch, 14h, 14h, 14h, 08h ; 'p'
db 08h, 14h, 14h, 18h, 7ch ; 'q'
db 7ch, 08h, 04h, 04h, 08h ; 'r'
db 48h, 54h, 54h, 54h, 20h ; 's'
db 04h, 3fh, 44h, 40h, 20h ; 't'
db 3ch, 40h, 40h, 20h, 7ch ; 'u'
db 1ch, 20h, 40h, 20h, 1ch ; 'v'
db 3ch, 40h, 30h, 40h, 3ch ; 'w'
db 44h, 28h, 10h, 28h, 44h ; 'x'
db 0ch, 50h, 50h, 50h, 3ch ; 'y'
db 44h, 64h, 54h, 4ch, 44h ; 'z'
db 00h, 08h, 36h, 41h, 00h ; '{'
db 00h, 00h, 7fh, 00h, 00h ; ' '
db 00h, 41h, 36h, 08h, 00h ; '}'
db 08h, 08h, 2ah, 1ch, 08h ; ' '
db 08h, 1ch, 2ah, 08h, 08h ; ' '
db 48h, 7eh, 49h, 49h, 4ah ; ' '
db 03h, 3bh, 44h, 44h, 44h ; ' '
db 03h, 7bh, 14h, 14h, 14h ; ' '
db 07h, 05h, 07h, 00h, 00h ; ' '
db 1ch, 54h, 3eh, 15h, 1ch ; ' '
db 22h, 55h, 2ah, 14h, 08h ; '>>'
db 08h, 14h, 2ah, 55h, 22h ; '<<'
db 22h, 14h, 08h, 14h, 22h ; 'X'
db 08h, 08h, 2ah, 08h, 08h ; ' '
db 18h, 24h, 18h, 24h, 18h ; ' '
db 44h, 44h, 5fh, 44h, 44h ; ' '
db 10h, 20h, 7fh, 01h, 01h ; ' '
db 00h, 00h, 51h, 4ah, 44h ; ' '
db 00h, 00h, 44h, 4ah, 51h ; ' '
db 49h, 49h, 49h, 49h, 49h ; ' '
db 5ch, 62h, 02h, 62h, 5ch ; ' '
db 40h, 3eh, 10h, 10h, 3eh ; ' '
db 42h, 66h, 5ah, 42h, 42h ; ' '
db 38h, 44h, 46h, 3ah, 02h ; ' '
db 44h, 3ch, 04h, 3ch, 44h ; ' '
db 7eh, 15h, 25h, 25h, 1ah ; ' '
db 5ch, 32h, 2ah, 26h, 1dh ; ' '
db 5eh, 09h, 09h, 09h, 5eh ; ' '
db 78h, 14h, 15h, 14h, 78h ; ' '
db 45h, 29h, 11h, 29h, 45h ; ' '
db 17h, 08h, 64h, 56h, 5dh ; '1/2'
db 17h, 08h, 14h, 1ah, 7dh ; '1/4'
db 30h, 28h, 24h, 28h, 30h ; ' '
db 12h, 09h, 12h, 24h, 12h ; ' '
db 04h, 02h, 7dh, 02h, 04h ; ' '
db 10h, 20h, 5fh, 20h, 10h ; ' '
db 08h, 1ch, 2ah, 08h, 08h ; ' '
db 00h, 00h, 77h, 00h, 00h ; '|'
db 0dh, 0bh, 00h, 54h, 7ch ; '2/3'
db 17h, 08h, 74h, 02h, 71h ; '1/11'
db 17h, 08h, 44h, 56h, 7dh ; '1/3'
db 15h, 1fh, 20h, 30h, 78h ; '3/4'
db 78h, 40h, 40h, 40h, 40h ; ' '
db 40h, 40h, 40h, 40h, 78h ; ' '
db 1ch, 22h, 7fh, 22h, 22h ; ' '
db 14h, 24h, 7fh, 24h, 14h ; ' '
db 14h, 12h, 7fh, 12h, 14h ; ' '
db 1ch, 22h, 24h, 18h, 26h ; ' '
db 14h, 22h, 7fh, 22h, 14h ; ' '
db 3eh, 49h, 49h, 49h, 3eh ; ' '
db 40h, 48h, 3eh, 09h, 01h ; ' '
db 01h, 01h, 01h, 01h, 01h ; ' '
db 00h, 7eh, 7eh, 7eh, 00h ; ' '
end



