.cseg
; look on http://home.iae.nl/users/pouweha/lcd/lcd0.shtml
;Proc Set2Write()
Set2Write:
cbi LCD_CR,LCD_RW ;Make R/!W low - Write operation
sbi LCD_DT_DR, LCD_D4 ;Make the data pins outputs
sbi LCD_DT_DR, LCD_D5
sbi LCD_DT_DR, LCD_D6
sbi LCD_DT_DR, LCD_D7
ret
; Proc Byte2Displ(DataByte)
Byte2Displ: ; To complete transfer byte, send hiNibble, then loNibble
rcall Set2Write
mov TempA, DataByte
swap TempA
rcall Nibble2Displ
mov TempA, DataByte
rcall Nibble2Displ
WaitByte2Displ:
rcall LCDBusyTest
brts WaitByte2Displ
ret
; Proc Nibble2Displ(loNiTempA)
Nibble2Displ:
andi TempA, $0F ; Filter loNibble of TempA
ror TempA
brcs LCD_D4Hi
cbi LCD_DT, LCD_D4
rjmp gLCD_D5
LCD_D4Hi:
sbi LCD_DT, LCD_D4
gLCD_D5:
ror TempA
brcs LCD_D5Hi
cbi LCD_DT, LCD_D5
rjmp gLCD_D6
LCD_D5Hi:
sbi LCD_DT, LCD_D5
gLCD_D6:
ror TempA
brcs LCD_D6Hi
cbi LCD_DT, LCD_D6
rjmp gLCD_D7
LCD_D6Hi:
sbi LCD_DT, LCD_D6
gLCD_D7:
ror TempA
brcs LCD_D7Hi
cbi LCD_DT, LCD_D7
rjmp LCD_DFin
LCD_D7Hi:
sbi LCD_DT, LCD_D7
LCD_DFin:
sbi LCD_CR, LCD_EN ;Toggle E High
nop
nop
nop
nop
cbi LCD_CR, LCD_EN ;Back to Low
; & in middle of EN Strobe Signal comes High
; & EN Strobe Signal falls down at the end
cbi LCD_DT, LCD_D4 ; Cleanup (EN disable, isn't important,
cbi LCD_DT, LCD_D5 ; what becomes on in/outputs, but this
cbi LCD_DT, LCD_D6 ; saves time for simulation read LCD
cbi LCD_DT, LCD_D7 ; lines - no more manual skip)
ret
;Proc Set2Read()
Set2Read:
cbi LCD_CR, LCD_EN
nop
nop
sbi LCD_CR, LCD_RW ; reading
cbi LCD_DT_DR, LCD_D4 ;Make the data pins inputs
cbi LCD_DT, LCD_D4 ; & switch off pullups
cbi LCD_DT_DR, LCD_D5
cbi LCD_DT, LCD_D5
cbi LCD_DT_DR, LCD_D6
cbi LCD_DT, LCD_D6
cbi LCD_DT_DR, LCD_D7
cbi LCD_DT, LCD_D7
nop
nop
sbi LCD_CR, LCD_EN ;Toggle _en High
ret
; Proc Displ2Nibble(loNiTempA)
Displ2Nibble:
;rgLCD_D4:
clr TempA
sbis LCD_IN, LCD_D4
rjmp rgLCD_D5
sbr TempA, 1<<0 ;
rgLCD_D5:
sbis LCD_IN, LCD_D5
rjmp rgLCD_D6
sbr TempA, 1<<1
rgLCD_D6:
sbis LCD_IN, LCD_D6
rjmp rgLCD_D7
sbr TempA, 1<<2
rgLCD_D7:
sbis LCD_IN, LCD_D7
rjmp rLCD_DFin
sbr TempA, 1<<3
rLCD_DFin:
ret
;Proc ReadEnd()
ReadEnd:
cbi LCD_CR, LCD_EN
nop
nop
cbi LCD_CR, LCD_RW ; reading off
ret
; Proc Displ2Byte(->DataAcc)
Displ2Byte: ; To complete recive byte, get hiNibble, then loNibble
rcall Set2Read
nop ; 8* nop ~= 1,09 microsecond wait
nop
nop
nop
nop
nop
nop
sbis LCD_CR, LCD_RS
rjmp RdAddrAndBusyFlg
clr CountBtH
ldi CountBtL, 0x01
; rcall _40delay ; wait multiply CountBtL by _40,15 microseconds delay
RdAddrAndBusyFlg:
rcall Displ2Nibble
cbi LCD_CR, LCD_EN
nop
mov DataAcc, TempA
; TempA MSB Nibble Cleared & no Set in Displ2Nibble
nop
sbi LCD_CR, LCD_EN ;Toggle _en High
nop
rcall Displ2Nibble
rcall ReadEnd
nop ; 8* cycles ~= 1,09 microsecond wait
nop
nop
nop
nop
swap DataAcc
or DataAcc, TempA
ret
; Proc LCDBusyTest(Busy=>T=1)
LCDBusyTest:
cbi LCD_CR, LCD_RS
clt
rcall Displ2Byte
sbrc DataAcc, 7
rjmp LCDBusy
clt
ret
LCDBusy:
set
ret
; Proc GetLCDAddr(Addr=>DataAcc)
GetLCDAddr:
rcall LCDBusyTest
brtc GetLCDAddrEnd
cbr DataAcc, (1<<7)
GetLCDAddrEnd:
ret
; Proc GetLCDData(Data=>DataAcc)
GetLCDData:
sbi LCD_CR, LCD_RS
rcall Displ2Byte
ret
; Proc PrintChar(DataAcc)
PrintChar:
ldi CountBtL, 5; 5 ; delay 25=~1 ms
rcall _40Delay
cbi LCD_CR, LCD_EN
nop
nop
sbi LCD_CR, LCD_RS ; Writing on display memory - RS high, R/!W low
rcall Byte2Displ
ret
; Proc CursHome()
CursHome:
;set mode {+$02} - returns cursor to home position, clears shifting the display
cbi LCD_CR, LCD_EN
ldi DataAcc, $02
rcall Byte2Displ
ret
; Proc CursReset()
CursReset:
;set mode {+$01} - returns cursor to home position, clears display
cbi LCD_CR, LCD_EN
ldi DataAcc, $01
rcall Byte2Displ
ret
; Proc CursOff()
CursOff:
;set mode {+$08}, displaying on {+$04}, no cursor on {*$02}, no cursor blinking {*$01}
cbi LCD_CR, LCD_EN
ldi DataAcc, $0C
rcall Byte2Displ
ret
; Proc CursOffBl()
CursOffBl:
;set mode {+$08}, displaying on {+$04}, no cursor on {*$02}, cursor blinking {+$01}
cbi LCD_CR, LCD_EN
ldi DataAcc, $0D
rcall Byte2Displ
ret
; Proc CursOn()
CursOn:
;set mode {+$08}, displaying on {+$04}, cursor on {+$02}, no cursor blinking {*$01}
cbi LCD_CR, LCD_EN
ldi DataAcc, $0E
rcall Byte2Displ
ret
; Proc CursOnBl()
CursOnBl:
;set mode {+$08}, displaying on {+$04}, cursor on {+$02}, cursor blinking {+$01}
cbi LCD_CR, LCD_EN
ldi DataAcc, $0F
rcall Byte2Displ
ret
; Proc CursGo(Addr=>DataAcc)
CursGo:
cbi LCD_CR, LCD_EN ; to perform, must be cleared, if forgiven
nop
nop
cbi LCD_CR, LCD_RW ; Write
nop
nop
cbi LCD_CR, LCD_RS ; Operation on display register
;set mode {+$80}, Address {$00 - $7F}
;Mode 0x80 - set cursor address, next operation
;with _rs High denotes to be putting char on display
ori DataAcc, $80
rcall Byte2Displ
ret
; Proc InitDisplay()
InitDisplay:
cbi LCD_CR, LCD_RS
nop
nop
cbi LCD_CR, LCD_RW
nop
nop
cbi LCD_CR, LCD_EN
sbi LCD_CR_DR, LCD_EN ;Make the control pins outputs
sbi LCD_CR_DR, LCD_RW
sbi LCD_CR_DR, LCD_RS
ldi CountBtL, 125 ; 5 ms
rcall _40Delay
ldi CountBtL, 249 ; 10 ms
rcall _40Delay
ldi CountBtL, $03 ; 3 times set 8bit mode to be sure so it's becomes
InitDispl0:
push CountBtL
ldi TempA, $03
rcall Nibble2Displ
ldi CountBtL, 5 ; delay 25=~1 ms
; ldi CountBtL, 25 ; ~1 ms delay
rcall _40Delay
pop CountBtL
dec CountBtL
brne InitDispl0
ldi TempA, $02 ; clear 8bit mode (it results 4bit mode)
rcall Nibble2Displ
ldi CountBtL, 5 ; delay 25=~1 ms
rcall _40Delay
;set mode {+$20}, no set 8bit mode {*$10}, 2 lines {+$08}, 5x10 points chars {+$04}
ldi DataAcc, $2C
rcall Byte2Displ
WaitInitMode0x20:
rcall LCDBusyTest
brts WaitInitMode0x20
;set mode {+$04}, incrase cursor address after displaying char {+$02}, shift the display {*$01}
ldi DataAcc, $06
rcall Byte2Displ
WaitInitMode0x04:
rcall LCDBusyTest
brts WaitInitMode0x04
rcall PLSigns
rcall CursReset
rcall CursOff ;n ;Bl
ret