Blame | Last modification | View Log | Download | RSS feed
; LCD.ASM
; PROGETTO: B1601
; Compilatore Avocet X6502
; Gestione LCD
_CHIP_INC_ .SET 1
_KEYB_INC_ .SET 1
.INCLUDE inc\global.inc
.INCLUDE inc\dirp01.inc
; BIT di LCDFlag
; maschera 0 0 0 0 1 D C B
LCDFB_B .EQU 0 ; BLINK cursore
LCDFB_C .EQU 1 ; Cursore ON/OFF
LCDFB_D .EQU 2 ; Display ON/OFF
; maschera 0 0 0 1 SC RL X X
LCDFB_RL .EQU 3 ; Shift Destra/Sinistra
LCDFB_SC .EQU 4 ; Shift Cursore/Display
; maschera 0 0 0 0 0 1 I/D SH
LCDFB_SH .EQU 5 ; Shift completo
LCDFB_ID .EQU 6 ; Incremento/Decremento
LCDFB_R .EQU 7 ; LCD Ready
LCDMAXCOL .EQU 20
LCDMAXROW .EQU 4
;----------------------------------------------------------------------------
; SEGMENTO CODEF8
;----------------------------------------------------------------------------
.CODEF8
.GLOBAL _LCDFlag, LCDSetup, _LCDAtXY, LCDHex
_LCDFlag .EQU (DP01ADDR + LCDFlag)
; NOTA - le funzioni seguenti vanno chiamate in modo 8 bit
.LONGA off
.LONGI off
; valore T2 VIA per ritardo 2ms
D2MSCNT .EQU (2 * 1000 * PHI2)
; valore T2 VIA per ritardo 45us
D45USCNT .EQU (45 * PHI2)
; out LCD carattere A at riga X e colonna Y
_LCDAtXY:
php
phd ; salva DP
pea #DP01ADDR ; imposta DB
pld
CPU08
jsr SendLCDAt
pld ; ripristina DP
plp
rts
HexDigit:
and #$0F
cmp #10
bcc ?01
adc #('A'-11)
rts
?01: adc #'0'
rts
Byte2Hex:
pha
lsr a
lsr a
lsr a
lsr a
jsr HexDigit
tax
pla
bra HexDigit
LCDHex:
php
phd ; salva DP
pea #DP01ADDR ; imposta DB
pld
CPU08
phx
phy
stx LCDTmp
jsr Byte2Hex
sta LCDVal
stx LCDVal+1
lda LCDTmp
ply
jsr SetLCDAddr
lda LCDVal+1
jsr SendLCDData
lda LCDVal
jsr SendLCDData
lda #' '
jsr SendLCDData
plx
pld ; ripristina DP
plp
rts
.GLOBAL LCDHexL, LCDClrXL
LCDHexL:
jsr LCDHex
rtl
LCDClrXL:
jsr ClearLCDRow
rtl
;----------------------------------------------------------
; LCDSetup - chiamata da IOInit
;----------------------------------------------------------
; LCDSetup - Inizializza LCD dopo reset
; In - A -> flag
; Out - imposta LCDFlag
; Registri - A
LCDSetup:
php
phd ; salva DP
pea #DP01ADDR ; imposta DB
pld
CPU08
jsr InitLCD
pld ; ripristina DP
plp
rts
; NOTA - le funzioni locali seguenti vanno chiamate con DP = DP01ADDR
; e in modo 8 bit
;----------------------------------------------------------
; ClearLCDRow
;----------------------------------------------------------
; ClearLCDRow - Cancella una riga del display
; In - X = riga da cancellare
; Out - X = riga da cancellare
; Registri - nessuno
ClearLCDRow:
bit LCDFlag ; esce se LCD non presente
bpl ?03
cpx #LCDMAXROW
bcc ?01
ldx #LCDMAXROW
?01: pha
phy
txa ; A = row
ldy #0 ; Y = col
jsr SetLCDAddr
ldy #LCDMAXCOL
?02: lda #' '
jsr SendLCDData
dey
bne ?02
txa
jsr SetLCDAddr
ply
pla
?03: rts
Delay45us:
ldx #(.LOW.D45USCNT)
lda #(.HIGH.D45USCNT)
bra DoDelay
Delay2ms:
ldx #(.LOW.D2MSCNT)
lda #(.HIGH.D2MSCNT)
DoDelay:
stx VIA0+VIAT2CL
sta VIA0+VIAT2CH
lda #T2IFRB
?01: bit VIA0+VIAIFR ; test T2 flag
beq ?01 ; attende timeout
rts
;----------------------------------------------------------
; InitLCD
;----------------------------------------------------------
; InitLCD - Inizializza LCD dopo reset
; In - nessuno
; Out - imposta LCDFlag
; Registri - A
InitLCD:
sta LCDFlag
cmp #0
beq ?98
;lda #$80 ; imposta flag LCD presente
;tsb LCDFlag
;;bra ?99
lda #$38
clc
jsr WriteLCD2
jsr Delay45us
lda #$0C
clc
jsr WriteLCD2
jsr Delay45us
lda #$01
clc
jsr WriteLCD2
jsr Delay2ms
lda #00111000B ; 8 bit - 4 righe - font 5 x 8
;lda #00110000B ; 8 bit - 4 righe - font 5 x 8
lda #00000010B ; Incremento - no shift
;jsr SendLCDCmd
jsr SetLCDMode
?98: rts
?99:
jsr OffLCD ; LCD OFF
lda #00111100B ; 8 bit - 4 righe - font 5 x 8
jsr SendLCDCmd
jsr OnLCD ; LCD ON
lda #00000010B ; Incremento - no shift
;jsr SendLCDCmd
jsr SetLCDMode
bra ClearLCD ; cancella display
;----------------------------------------------------------
; SetLCDAddr
;----------------------------------------------------------
; SetLCDAddr - Imposta indirizzo DD RAM LCD
; In - A = riga LCD
; Y = colonna LCD
; Out - DD-RAM LCD impostata
; Registri - A
SetLCDAddr:
sty LCDTmp ; salva colonna
clc
ror a ; Bit0 e Bit1 in Bit6 e Bit7
ror a
ror a
and #$C0 ; maschera on bit6 e bit7
bpl ?01 ; riga = 0, 1
ora #$14 ; riga 2,3 - somma offset
?01: clc
adc LCDTmp ; somma colonna
ora #$80 ; Bit7 = 1 - setta DD RAM
brl SendLCDCmd ; invia comando a LCD
;----------------------------------------------------------
; ClearLCD
;----------------------------------------------------------
; ClearLCD - cancella LCD
; In - nessuno
; Out - nessuno
; Registri - A
ClearLCD:
lda #$01
brl SendLCDCmd
;----------------------------------------------------------
; HomeLCD
;----------------------------------------------------------
; HomeLCD - posiziona cursore a 0,0
; In - nessuno
; Out - nessuno
; Registri - A
HomeLCD:
lda #$02
brl SendLCDCmd
;----------------------------------------------------------
; OnLCD
;----------------------------------------------------------
; OnLCD - LCD ON
; In - nessuno
; Out - LCDFlag
; Registri - A
OnLCD:
lda #LCDFB_D
tsb LCDFlag ; LCDFlag<2>->1 LCD ON
bra SetLCDCurs2
;----------------------------------------------------------
; CursLCDOn
;----------------------------------------------------------
; CursLCDOn - Cursore LCD ON
; In - nessuno
; Out - LCDFlag
; Registri - A
CursLCDOn:
lda #LCDFB_C
tsb LCDFlag ; LCDFlag<1>->1 CURSORE LCD ON
bra SetLCDCurs2
;----------------------------------------------------------
; BlinkLCDOn
;----------------------------------------------------------
; BlinkLCDOn - Blink Cursore LCD ON
; In - nessuno
; Out - LCDFlag
; Registri - A
BlinkLCDOn:
lda #LCDFB_B
tsb LCDFlag ; LCDFlag<0>->1 BLINK CURSORE LCD ON
bra SetLCDCurs2
;----------------------------------------------------------
; OffLCD
;----------------------------------------------------------
; OffLCD - LCD OFF
; In - nessuno
; Out - LCDFlag
; Registri - A
OffLCD:
lda #LCDFB_D
trb LCDFlag ; LCDFlag<2>->0 LCD OFF
bra SetLCDCurs2
;----------------------------------------------------------
; CursLCDOff
;----------------------------------------------------------
; CursLCDOff - Cursore LCD OFF
; In - nessuno
; Out - LCDFlag
; Registri - A
CursLCDOff:
lda #LCDFB_C
trb LCDFlag ; LCDFlag<1>->0 CURSORE LCD OFF
bra SetLCDCurs2
;----------------------------------------------------------
; BlinkLCDOff
;----------------------------------------------------------
; BlinkLCDOff - Blink Cursore LCD OFF
; In - nessuno
; Out - LCDFlag
; Registri - A
BlinkLCDOff:
lda #LCDFB_B
trb LCDFlag ; LCDFlag<0>->0 BLINK CURSORE LCD OFF
bra SetLCDCurs2
;----------------------------------------------------------
; SetLCDCurs
;----------------------------------------------------------
; SetLCDCurs - Imposta cursore e stato on/off LCD
; In - A: flag -> 0 0 0 0 0 D C B
; Out - LCDFlag
; Registri - A
SetLCDCurs:
and #00000111B ; maschera on D C B
sta LCDTmp ; salva flag
lda LCDFlag
and #11111000B ; maschera off D C B
ora LCDTmp ; nuovo flag
sta LCDFlag
;----------------------------------------------------------
; SetLCDCurs2 - interna
;----------------------------------------------------------
; SetLCDCurs2 - Imposta cursore e stato on/off LCD
; In - nessuno
; Out - imposta LCD in base ai bit D C B di LCDFlag
; Registri - A
SetLCDCurs2:
lda LCDFlag
and #00000111B ; maschera on D C B
ora #00001000B ; comando cursore
bra SendLCDCmd
;----------------------------------------------------------
; ShiftLCDCursL
;----------------------------------------------------------
; ShiftLCDCursL - Shifta cursore LCD a sinistra
; In - nessuno
; Out - imposta LCDFlag
; Registri - A
ShiftLCDCursL:
lda #(LCDFB_SC.OR.LCDFB_RL) ; LCDFlag<4>->0 - Shift Cursore
trb LCDFlag ; LCDFlag<3>->0 - Shift sinistra
bra SetLCDShift2
;----------------------------------------------------------
; ShiftLCDCursR
;----------------------------------------------------------
; ShiftLCDCursR - Shifta cursore LCD a destra
; In - nessuno
; Out - imposta LCDFlag
; Registri - A
ShiftLCDCursR:
lda #LCDFB_SC
trb LCDFlag ; LCDFlag<4>->0 - Shift Cursore
lda #LCDFB_RL
tsb LCDFlag ; LCDFlag<3>->1 - Shift destra
bra SetLCDShift2
;----------------------------------------------------------
; ShiftLCDLeft
;----------------------------------------------------------
; ShiftLCDLeft - Shifta LCD a sinistra
; In - nessuno
; Out - imposta LCDFlag
; Registri - A
ShiftLCDLeft:
lda #LCDFB_SC
tsb LCDFlag ; LCDFlag<4>->1 - Shift Display
lda #LCDFB_RL
trb LCDFlag ; LCDFlag<3>->0 - Shift sinistra
bra SetLCDShift2
;----------------------------------------------------------
; ShiftLCDRight
;----------------------------------------------------------
; ShiftLCDRight - Shifta LCD a destra
; In - nessuno
; Out - imposta LCDFlag
; Registri - A
ShiftLCDRight:
lda #(LCDFB_SC.OR.LCDFB_RL) ; LCDFlag<4>->1 - Shift Display
tsb LCDFlag ; LCDFlag<3>->1 - Shift destra
bra SetLCDShift2
;----------------------------------------------------------
; ShiftLCD
;----------------------------------------------------------
; ShiftLCD - Shifta display e/o cursore
; In - A: 0 0 0 0 0 0 SC RL
; Out - imposta LCDFlag
; Registri - A
ShiftLCD:
and #00000011B ; maschera bit SC RL
asl a ; sposta SC ed RL in Bit4 e Bit3
asl a
asl a
sta LCDTmp
lda LCDFlag
and #11100111B ; maschera off SC ed RL del flag
ora LCDTmp ; imposta nuovo flag
sta LCDFlag
;----------------------------------------------------------
; SetLCDShift2 - interna
;----------------------------------------------------------
; SetLCDShift2 - Shifta display e/o cursore in base a LCDFlag
; In - nessuno
; Out - nessuno
; Registri - A
SetLCDShift2:
lda LCDFlag
and #00011000B ; maschera SC ed RL
lsr a ; shifta 1 bit a destra
ora #00010000B ; imposta comando shift
bra SendLCDCmd
;----------------------------------------------------------
; SetLCDMode
;----------------------------------------------------------
; SetLCDMode - imposta entry mode LCD
; In - A: 0 0 0 0 0 0 ID SH
; Out - imposta LCDFlag
; Registri - A
SetLCDMode:
and #00000011B ; maschera on bit ID e SH
pha ; salva
asl a ; sposta ID in Bit6
asl a
asl a
asl a
asl a
sta LCDTmp
lda LCDFlag
and #10011111B ; maschera off bit ID e SH
ora LCDTmp ; imposta nuovo flag
sta LCDFlag
pla ; ripristina A
ora #00000100b ; IMPOSTA COMANDO
;----------------------------------------------------------
; SendLCDCmd - interna
;----------------------------------------------------------
; SendLCDCmd - Invia comando a LCD
; In - A = comando
; Out - nessuno
; Registri - A
SendLCDCmd:
bit LCDFlag ; esce se LCD non presente
bpl _90
clc ; invia comando
;----------------------------------------------------------
; WriteLCD - interna
;----------------------------------------------------------
; WriteLCD - Invia comando/data a LCD
; In - C = 0 -> invia comando
; C = 1 -> invia data
; - A = dato/comando
; Out - nessuno
; Registri - A
WriteLCD:
jsr WaitLCD ; attende LCD pronto
WriteLCD2:
php
sei
phx ; salva X
phb ; salva DBR
ldx #0 ; imposta DBR = 0
phx
plb
ldx #00000010B ; E->0, RW->1, RS->0
stx PIA1+PIAPRA
stz PIA1+PIACRB ; accesso a DDRB
ldx #11111111B ; pota B in uscita
stx PIA1+PIADDRB
ldx #00000100B
stx PIA1+PIACRB ; accesso a PRB
sta PIA1+PIAPRB ; dato
lda #00000000B ; E->0, RW->0, RS->0
bcc ?01 ; comando - RS = 0
ora #00000001B ; dato - RS = 1
?01: sta PIA1+PIAPRA
ora #00000100B ; E->1
sta PIA1+PIAPRA
nop
nop
nop
nop
and #11111011B ; E->0
sta PIA1+PIAPRA
ora #00000010B ; RW->1
sta PIA1+PIAPRA
stz PIA1+PIADDRB ; porta B in input
ldx #00000100B
stx PIA1+PIACRB ; accesso a PRB
plb ; ripristina DBR
plx
plp
_90: rts
;----------------------------------------------------------
; SendLCDData
;----------------------------------------------------------
; SendLCDData - Invia dato a LCD
; In - A = dato
; Out - nessuno
; Registri - A
SendLCDData:
bit LCDFlag ; esce se LCD non presente
bpl _90
sec
bcs WriteLCD
;----------------------------------------------------------
; SendLCDAt
;----------------------------------------------------------
; SendLCDAt - Invia dato a riga/colonna
; In - A = dato
; X = riga
; Y = colonna
; Out - X, Y
; Registri - A
SendLCDAt:
bit LCDFlag ; esce se LCD non presente
bpl _90
cpx #LCDMAXROW
bcc ?01
ldx #LCDMAXROW-1
?01: cpy #LCDMAXCOL
bcc ?02
ldy #LCDMAXCOL-1
?02: pha ; salva dato
txa ; A = row
jsr SetLCDAddr
pla ; A = dato
sec
bra WriteLCD
;----------------------------------------------------------
; WaitLCD - interna
;----------------------------------------------------------
; WaitLCD - Attende Busy Flag LCD = 0
; In - nessuno
; Out - nessuno
; Registri - nessuno - P salvato
WaitLCD:
php ; salva P
pha ; salva A
?01: clc ; legge status
jsr ReadLCD
and #$80 ; test Busy Flag (bit 7)
bne ?01 ; attende LCD pronto
pla ; ripristina A
plp ; ripristina P
rts
;----------------------------------------------------------
; GetLCDData
;----------------------------------------------------------
; GetLCDData - Legge dato da LCD
; In - nessuno
; Out - A = dato
; Registri - A
GetLCDData:
bit LCDFlag ; esce se LCD non presente
bpl _90
sec
;----------------------------------------------------------
; ReadLCD - interna
;----------------------------------------------------------
; ReadLCD - Legge status/data da LCD
; In - C = 0 -> legge status
; C = 1 -> legge data
; Out - A = status/data
; Registri - A
ReadLCD:
php
sei
phb ; salva DBR
phx ; salva X
ldx #0 ; imposta DBR = 0
phx
plb
stz PIA1+PIACRB
stz PIA1+PIADDRB
ldx #00000100B
stx PIA1+PIACRB ; accesso a PRB
lda #00000010B ; E->0, RW->1, RS->0
bcc ?01 ; legge status
ora #00000001B ; legge dato - RS->1
?01: sta PIA1+PIAPRA
nop
nop
nop
nop
ora #00000100B ; E->1
sta PIA1+PIAPRA
nop
nop
nop
nop
nop
nop
?02: ldx PIA1+PIAPRB ; legge bus LCD
cpx PIA1+PIAPRB ; attende lettura stabile
bne ?02
and #11111011B ; E->0
sta PIA1+PIAPRA
txa
plx ; ripristina X
plb ; ripristina DBR
plp
rts
;----------------------------------------------------------
; GetLCDAddr
;----------------------------------------------------------
; GetLCDAddr - Legge indirizzo corrente da LCD
; In - nessuno
; Out - A = indirizzo
; Registri - A
GetLCDAddr:
bit LCDFlag ; esce se LCD non presente
bpl ?01
clc ; legge status
jsr ReadLCD
and #01111111B ; maschera busy flag
?01: rts