You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

517 lines
11 KiB

;==================================================================================================
; PCF8584 HD44780 I2C LCD UTILITY
;
; SOME GENERAL INFORMATION ON LCDS CAN BE SEEN HERE : FOCUSLCDS.COM/PRODUCT-CATEGORY/CHARACTER-LCD/
;
;==================================================================================================
;
.ECHO "i2clcd\n"
;
#INCLUDE "pcfi2c.inc"
;
; LCD COMMANDS
;
LCDFSET .EQU 00100000B ; 20H
LCD4BIT .EQU 00000000B ; 00H
LCD2LIN .EQU 00001000B ; 08H
LCDDON .EQU 00000100B ; 04H
LCDDMOV .EQU 00001000B ; 07H
LCDSGRA .EQU 01000000B ; 04H
LCDSDRA .EQU 10000000B ; 80H
LCDEMS .EQU 00000100B ; 04H
LCDELFT .EQU 00000010B ; 03H
;
LCDPINE .EQU 00000100B ; PIN 2
LCDPIND .EQU 00000001B ; PIN O
;
;
; STANDARD FORMATS - 8X1, 8X2, 16X1, 16X2, 16X4, 20X1, 20X2, 20X4, 24X2, 40X1, 40X2, 40X4
;
TIMEOUT .EQU 255
.ORG 100H
;INIT: CALL PCF_INIT
;
LD A,0
LD (DEBUGF),A
;
CALL LCDINIT ; SETUP THE LCD THROUGH THE PCF8574
LD HL,LCDDATA ; DISPLAY TEXT AT HL
PUSH HL
CALL LCDSTR
POP HL
CALL STOP ; CLOSE I2C CONNECTION
;
RET
;-----------------------------------------------------------------------------
;
LCDLITE .DB 00001000B
;
LCDINIT:
; CALL DEBUG
;
LD A,I2CLCDW ; SET SLAVE ADDRESS
OUT (REGS0),A
;
LD A,0C5H ; GENERATE START CONDITION
OUT (REGS1),A ; AND ISSUE THE SLAVE ADDRESS
CALL CHKPIN
;
; CALL DEBUG
;
LD HL,LCDINIT1
LD B,2
CALL WLN
;
CALL DELAY
;
LD HL,LCDINIT2
LD B,2
CALL WLN
;
CALL DELAY
;
; NOW WE ARE IN 4 BIT MODE
;
LD A,+(LCDFSET | LCD4BIT | LCD2LIN)
CALL LCDCMD
LD A,+(LCDDON | LCDDMOV)
CALL LCDCMD
LD A,+(LCDEMS | LCDELFT)
CALL LCDCMD
LD A,LCDSDRA
CALL LCDCMD
;
RET
;
;-----------------------------------------------------------------------------
;
WLN: LD A,(HL)
OUT (REGS0),A ; PUT DATA ON BUS
CALL CHKPIN
INC HL
DJNZ WLN
RET
;
;-----------------------------------------------------------------------------
; DISPLAY STRING AT HL, TERMINATED BY 0
;
LCDSTR: POP BC ; GET THE POINTER OF
POP HL ; THE TEXT TO DISPLAY
PUSH HL ; OFF THE STACK AND
PUSH BC ; PUT IT IN HL.
;
LCDST0: LD A,(HL) ; GET NEXT CHARACTER TO
OR A ; DISPLAY BUT RETURN
RET Z ; WHEN TERMINATOR REACHED
PUSH HL
;
CALL LCDATA ; OUTPUT TO LCD
POP HL
; RET C ; POINT TO NEXT
INC HL ; AND REPEAT
JR LCDST0
;
;-----------------------------------------------------------------------------
; SEND BYTE IN A TO LCD IN 4-BIT MODE
;
LCDATA: PUSH DE
LD D,A
LD A,(LCDLITE)
OR +(LCDPINE | LCDPIND)
JP LCDSND
LCDCMD: PUSH DE
LD D,A
LD A,(LCDLITE)
OR LCDPINE
LCDSND: LD E,A
LD A,D
PUSH BC
LD C,11110000B
AND C
OR E
LD (LCDBUF),A
AND ~LCDPINE
LD (LCDBUF+1),A
LD A,D
RLC A
RLC A
RLC A
RLC A
AND C
OR E
LD (LCDBUF+2),A
AND ~LCDPINE
LD (LCDBUF+3),A
;
LD HL,LCDBUF ; OUTPUT 1 BYTE WHICH
LD B,4 ; REQUIRES A FOUR
CALL WLN ; BYTE SEQUENCE
;
POP BC
POP DE
RET
;
LCDDATA:
.DB "TEST HOW BIG IS THIS LINE DOES IT WRAP",0
;
LCDINIT1:
.DB 00110100B
.DB 00011000B
;
LCDINIT2:
.DB 00100100B
.DB 00100000B
;
LCDBUF:
.DB 0, 0, 0, 0 ; BUFFER TO HOLD 4 BYTE SEQUENCE
; FLASH DEVICE READ
;
DEVMADR .EQU 0
READR: LD B,255
DLY1: DJNZ DLY1
;
LD A,D ; SET SLAVE ADDRESS
OUT (REGS0),A
;
LD A,0C5H ; GENERATE START CONDITION
OUT (REGS1),A ; AND ISSUE THE SLAVE ADDRESS
CALL CHKPIN
;
LD A,+(DEVMADR/256)
OUT (REGS0),A ; PUT ADDRESS MSB ON BUS
CALL CHKPIN
;
LD A,+(DEVMADR&$00FF)
OUT (REGS0),A ; PUT ADDRESS LSB ON BUS
CALL CHKPIN
;
LD A,045H ; START
OUT (REGS1),A
;
LD A,E ; ISSUE CONTROL BYTE + READ
OUT (REGS0),A
;
CALL READI2C ; DUMMY READ
JR NZ,ERREXT
;
READLP1:CALL READI2C
; JR Z,ERREXT
CP 1AH
PUSH AF
CALL COUT
POP AF
JR NZ,READLP1
;
LD A,PCF_ES0
OUT (REGS1),A
CALL CHKPIN
IN A,(REGS0)
CALL READI2C
CALL STOP
;
CALL NEWLINE
;
RET
;
;-----------------------------------------------------------------------------
;-----------------------------------------------------------------------------
RESET: LD A,0C2H ; STOP
OUT (REGS1),A
LD B,255
DLY2: DJNZ DLY2
LD A,0C1H
OUT (REGS1),A
RET
RDSTAT: LD BC,-1
STATLP: IN A,(REGS1)
AND 1
RET Z
LD A,B
OR C
DEC BC
JR NZ,STATLP
LD A,'T'
JP ERREXTT
;
ERREXT: LD A,'Q'
JR ERR
ERREXTT: POP HL
ERR: CALL COUT
CALL STOP
CALL RESET
RET
;
STOP: LD A,0C3H
OUT (REGS1),A
RET
;
DELAY: PUSH HL
LD HL,-1
DLOOP: LD A,H
OR L
DEC HL
JR NZ,DLOOP
POP HL
RET
;
CHKPIN: IN A,(REGS1) ; POLL FOR
BIT 7,A ; TRANSMISSION
JP NZ,CHKPIN ; TO FINISH
; IN A,(REGS1) ; CHECK FOR
BIT 3,A ; SLAVE
RET Z ; ACKNOWLEDGMENT
LD A,'A'
JP ERREXTT
;
; READ ONE BYTE FROM I2C
; RETURNS DATA IN A
; Z flag set is acknowledge received (correct operation)
;
READI2C:
IN A,(REGS1) ; READ S1 REGISTER
BIT 7,A ; CHECK PIN STATUS
JP NZ,READI2C
BIT 3,A ; CHECK LRB=0
RET NZ
IN A,(REGS0) ; GET DATA
RET
;
DEBUG: PUSH AF
PUSH DE
LD A,'['
CALL COUT
LD HL,DEBUGF
LD A,(HL)
INC (HL)
CALL HBTHE
LD A,']'
CALL COUT
POP DE
POP AF
RET
DEBUGF: .DB 00H
;
;-----------------------------------------------------------------------------
;
; LINUX DRIVER BASED CODE
;
; I2C_INB = IN A,(REGS0)
; I2C_OUTB = LD A,* | OUT (REGS0),A
; SET_PCF = LD A,* | OUT (REGS1),A
; GET_PCF = IN A,(REGS1)
;
;-----------------------------------------------------------------------------
I2C_START:
LD A,PCF_START_
OUT (REGS1),A
RET
;
;-----------------------------------------------------------------------------
I2C_REPSTART:
LD A,PCF_START_
OUT (REGS1),A
RET
;
;-----------------------------------------------------------------------------
I2C_STOP:
LD A,PCF_STOP_
OUT (REGS1),A
RET
;
;-----------------------------------------------------------------------------
HANDLE_LAB:
LABDLY .EQU 0F000H
LD A,PCF_PIN
OUT (REGS1),A
LD A,PCF_ES0
OUT (REGS1),A
;
LD HL,LABDLY
LABLP LD A,H
OR L
DEC HL
JR NZ,LABLP
;
IN A,(REGS1)
RET
;
;-----------------------------------------------------------------------------
WAIT_FOR_BB:
;
BBTIMO .EQU 255
;
LD HL,BBTIMO
BBNOTO IN A,(REGS1)
AND PCF_BB
RET Z
DEC HL
LD A,H
OR A
JR NZ,BBNOTO
CPL ; RET NZ IF TIMEOUT
BBNOTB RET ; RET Z IF BUS IS BUSY
;
;-----------------------------------------------------------------------------
WAIT_FOR_PIN:
;
; RETURN A=00/Z IF SUCCESSFULL
; RETURN A=FF/NZ IF TIMEOUT
; RETURN A=01/NZ IF LOST ARBITRATION
;
PINTIMO .EQU 16000
;
LD HL,PINTIMO
PINNOTO IN A,(REGS1)
LD (STATUS),A
LD B,A
AND PCF_PIN
RET Z
DEC HL
LD A,H
OR A
JR NZ,PINNOTO
CPL ; RET NZ IF TIMEOUT
PINNOTB RET ; RET Z IF BUS IS BUSY
;
LD B,A
AND PCF_LAB
CALL HANDLE_LAB
LD (STATUS),A
XOR A
INC A
RET
;
STATUS .DB 00H
;
;-----------------------------------------------------------------------------
PCF_INIT:
LD A,PCF_PIN ; S1=80H: S0 SELECTED, SERIAL
OUT (REGS1),A ; INTERFACE OFF
NOP
IN A,(REGS1) ; CHECK TO SEE S1 NOW USED AS R/W
AND 07FH ; CTRL. PCF8584 DOES THAT WHEN ESO
JR NZ,INIERR ; IS ZERO
;
LD A,PCF_OWN ; LOAD OWN ADDRESS IN S0,
OUT (REGS0),A ; EFFECTIVE ADDRESS IS (OWN <<1)
NOP
IN A,(REGS0) ; CHECK IT IS REALLY WRITTEN
CP PCF_OWN
JR NZ,SETERR
;
LD A,+(PCF_PIN | PCF_ES1) ; S1=0A0H
OUT (REGS1),A ; NEXT BYTE IN S2
NOP
IN A,(REGS1)
AND 07FH
CP PCF_ES1
JR NZ,REGERR
;
LD A,PCF_CLK ; LOAD CLOCK REGISTER S2
OUT (REGS0),A
NOP
IN A,(REGS0) ; CHECK IT'S REALLY WRITTEN, ONLY
AND 1FH ; THE LOWER 5 BITS MATTER
CP PCF_CLK
JR NZ,CLKERR
;
LD A,PCF_IDLE_
OUT (REGS1),A
NOP
IN A,(REGS1)
CP +(PCF_PIN | PCF_BB)
JR NZ,IDLERR
RET
;
;-----------------------------------------------------------------------------
PCF_SENDBYTES: ; HL POINTS TO DATA, BC = COUNT, A = 0 LAST A=1 NOT LAST
;
LD (LASTB),A
;
SB0: LD A,(HL)
OUT (REGS0),A
CALL WAIT_FOR_PIN
JR Z,SB1
CP 01H ; EXIT IF ARBITRATION ERROR
RET Z
CALL I2C_STOP ; MUST BE TIMEOUT
LD A,055H ; ERROR
RET
SB1: LD A,(STATUS)
AND PCF_LRB
JR NZ,SB2
LD A,055H
;
SB2: LD A,B
OR C
INC HL
JR NZ,SB0 ; CHECK IF FINISHED
;
SBGOOD: LD A,(LASTB)
OR A
JR NZ,DB3
CALL I2C_STOP
RET
DB3: CALL I2C_REPSTART
RET
;
LASTB .DB 00H
;
; I2C_INB = IN A,(REGS0)
; I2C_OUTB = LD A,* | OUT (REGS0),A
; SET_PCF = LD A,* | OUT (REGS1),A
; GET_PCF = IN A,(REGS1)
;
;-----------------------------------------------------------------------------
INIERR LD HL,NOPCF
CALL PRTSTR
RET
;
SETERR LD HL,WRTFAIL
CALL PRTSTR
RET
REGERR LD HL,REGFAIL
CALL PRTSTR
RET
;
CLKERR LD HL,CLKFAIL
CALL PRTSTR
RET
;
IDLERR LD HL,IDLFAIL
CALL PRTSTR
RET
;
NOPCF .DB "NO DEVICE FOUND",CR,LF,"$"
WRTFAIL .DB "SETTING DEVICE ID FAILED",CR,LF,"$"
REGFAIL .DB "CLOCK REGISTER SELECT ERROR",CR,LF,"$"
CLKFAIL .DB "CLOCK SET FAIL",CR,LF,"$"
IDLFAIL .DB "BUS IDLE FAILED",CR,LF,"$"
;
#INCLUDE "i2ccpm.inc"
;
BUFFER: .DS 256
;
.END