;*********************************************************************;
; LCD - V2.20 RGT : May 2010 ;
; Based on _ FLASH MECHASCREEN - V5.00 RRS : OCTOBER 2001 ;
; An LCD screen driving routine for 4 data line applications ;
; For LCDs with HITACHI HD44780 and compatible controllers. ;
; Written for a 2 line display, init should be changed for a 1 ;
; line display although it will work as is without displaying ;
; second message. ;
; All timings based on 4MHz oscillator. ;
; Version 2 has screen macro to ease handling of large amounts ;
; of text. ;
; Version 2.20 changed LCD PORT setup using #DEFINE to make ;
; changing port easier. e.g. 16F877A on ICD3 can't use PORTB.
;James & Jonty
;3rd NOV 2010 Testing out 4 stage temp check
;Version 6 Screen and LED
;LED Port B1 ;
;*********************************************************************;
LIST P=16F628A
INCLUDE P16F628A.INC
__CONFIG _CP_OFF&_BODEN_OFF&_PWRTE_ON&_WDT_OFF&_LVP_OFF&_MCLRE_OFF&_INTRC_OSC_NOCLKOUT
; PWRTE_ON enables power up timer delay ~72ms which should help screen to self initialise
#DEFINE LCD_PORT PORTB
#DEFINE LCD_TRIS TRISB
;LCD_PORT bits
DATA7 EQU .7 ; )
DATA6 EQU .6 ; )4 bit wide
DATA5 EQU .5 ; )data bus
DATA4 EQU .4 ; )
RS EQU .3 ; Register select - data or commands
E EQU .0 ; Chip enable
;R/W should be tied to 0V
;Vo use preset (10K) 0V-5V, will be near 0V end.
;RAM locations
SCREEN_DELAY_LOOP EQU 0x20
SCREEN_DELAY_LOOP1 EQU 0x21
MESS_POINTER EQU 0x22 ; Message pointer
WORD_STORE EQU 0x23 ; Store for commands / data information
TEMP_PCLATH EQU 0x24 ; Temp store for PCLATH during screen string routine
LOOP EQU 0X20 ;DELAY LOOP
LOOP1 EQU 0X21 ;DELAY LOOP
COUNT EQU 0X22
O_BYTE EQU 0X23
I_BYTE EQU 0X24
FLAGS EQU 0X25
CALC_CRC EQU 0X26 ;CALCULATED CRC
BCOUNT EQU 0X27
TEMP1 EQU 0X28 ;TEMP MEMORY DURING CALC_CRC
TEMP2 EQU 0X29 ;TEMP MEMORY DURING CALC_CRC
;SCRATCHPAD IS READ INTO 0X2A - 0X32
TEMP_LSB EQU 0X2A
TEMP_MSB EQU 0X2B
TH EQU 0X2C
TL EQU 0X2D
RES1 EQU 0X2E
RES2 EQU 0X2F
C_REMAIN EQU 0X30
C_PERC EQU 0X31
CRC EQU 0X32
; cywizard begin
dataL EQU 0x33
; cywizard end
;FLAGS BITS
PRESENCE EQU .0 ;PRESENCE
DS_ERROR EQU .1 ;CRC ERROR
;DS1820 BITS
DQ_BIT EQU .2
#DEFINE DQ PORTA,DQ_BIT
#DEFINE TRIS_DQ TRISA,DQ_BIT
;*******************************************************************************************
; Macro to call SEND_SCREEN_STRING, enables message strings to start beyond first 256 memory block
; and to cross block boundaries. Costs a few extra instructions per call, but greatly simplifies
; string handling when dealing with > 256 bytes.
LCD_STRING macro lookup_address
movf PCLATH,W ; Store current value of PCLATH
movwf TEMP_PCLATH ; PCLATH may change below or in SEND_SCREEN_STRING
if high(lookup_address) != 0 ; if start address of string is > 255
movlw high(lookup_address)
movwf PCLATH ; update PCLATH for string start address
endif
movlw low(lookup_address)
call SEND_SCREEN_STRING
movf TEMP_PCLATH,W
movwf PCLATH ; Return PCLATH to original value
endm
;*******************************************************************************************
ORG 0x00 ;Reset vector
goto START_OF_PROG
;*******************************************************************************************
; cywizard begin
; -------------------------------------------------------------
; SEND CHARACTER IN W VIA RS232 AND WAIT UNTIL FINISHED SENDING
; -------------------------------------------------------------
;
send_ser:
banksel TXREG
movwf TXREG ; send data in W
TransWt bsf STATUS,RP0 ; RAM PAGE 1
banksel TXSTA
WtHere btfss TXSTA,TRMT ; (1) transmission is complete if hi
goto WtHere
bcf STATUS,RP0 ; RAM PAGE 0
return
; cywizard end
;*******************************************************************************************
READ_SCRATCHPAD
;READ SCRATCHPAD, CHECK PRESENCE & CRC
bcf FLAGS,DS_ERROR
call DS_RESET
btfss FLAGS,PRESENCE
return ;NOT PRESENT
movlw 0XCC ;SKIP ROM
call OUT_BYTE
movlw 0X44 ;CONVERT TEMP
call OUT_BYTE
call PASSIVE_WAIT_CONVERSION
; call WAIT_CONVERSION ;CAN BE LONG _ DO OTHER THINGS?
call DS_RESET
btfss FLAGS,PRESENCE
return ;NOT PRESENT
movlw 0XCC ;SKIP ROM
call OUT_BYTE
movlw 0XBE ;READ SCRATCHPAD
call OUT_BYTE
clrf CALC_CRC
movlw TEMP_LSB ;ADDRESS TO STORE TEMP_LSB
movwf FSR
movlw .9 ;READ 9 BYTES FROM SCRATCHPAD
movwf BCOUNT
NEXT_CODE
call IN_BYTE
movwf INDF
movwf TEMP1
movlw .8
movwf COUNT ;8 BITS PER BYTE
incf FSR,F
decfsz BCOUNT,F
goto DO_CRC
movf TEMP1,W
subwf CALC_CRC,W ;Z WILL BE SET IF CRC CORRECT
btfss STATUS,Z
bsf FLAGS,DS_ERROR ;CRC WAS NOT CORRECT
return
DO_CRC
movf CALC_CRC,W
xorwf TEMP1,W
movwf TEMP2 ;STORE IN TEMP LOCATION THAT CAN BE ROTATED INTO C
rrf TEMP1,F ;ROTATE DATA READY FOR NEXT BIT
rrf TEMP2,W
btfss STATUS,C
goto NO_CARRY
movlw 0X18
xorwf CALC_CRC,F
NO_CARRY
rrf CALC_CRC,F
decfsz COUNT,F
goto DO_CRC
goto NEXT_CODE
;------------------------------------------------------
DS_RESET
; RESET DS1820 _ CHECK FOR PRESENCE PULSE!
bcf FLAGS,PRESENCE
call PIN_LO
movlw .48
call DELAY_10US ;48 X 10US ~480US
call PIN_HI
movlw .6
call DELAY_10US ;6 X 10US ~60US
btfss DQ ;CHECK PRESENCE PULSE
bsf FLAGS,PRESENCE ;PRESENT
movlw .42
call DELAY_10US ;42 X 10US ~420US
return
;------------------------------------------------------
PIN_LO
bcf DQ ;SET DATA PIN LOW, DO ONCE INITIALLY ?
bsf STATUS,RP0 ;SAFEST THIS WAY _ OTHER CODE MAY ACCIDENTLY CHANGE DQ?
bcf TRIS_DQ ;SET DATA PIN AS OUTPUT
bcf STATUS,RP0
return
;------------------------------------------------------
PIN_HI
bsf STATUS,RP0
bsf TRIS_DQ ;SET DATA AS INPUT WITH PULL UP!!!
bcf STATUS,RP0
return
;------------------------------------------------------
OUT_BYTE
movwf O_BYTE
movlw .8
movwf COUNT
OUT_BYTE_1
rrf O_BYTE,F
btfss STATUS,C
goto OUT_0
goto OUT_1
OUT_BYTE_2
decfsz COUNT,F
goto OUT_BYTE_1
return
OUT_0
call PIN_LO
movlw .6 ;60US DELAY
call DELAY_10US
call PIN_HI
goto OUT_BYTE_2
OUT_1
call PIN_LO ;MOMENTARY _ LONGISH!
call PIN_HI
movlw .6 ;60US DELAY
call DELAY_10US
goto OUT_BYTE_2
;------------------------------------------------------
IN_BYTE
movlw .8
movwf COUNT
clrf I_BYTE
IN_BYTE_1
call PIN_LO ;3US
nop ;4US
call PIN_HI ;11US
nop ;12US
bcf STATUS,C ;13US
btfsc DQ ;14US SAMPLE NEAR END OF 15US
bsf STATUS,C
rrf I_BYTE,F
movlw .4 ;40US + EXTRAS _ MIN OF 45US
call DELAY_10US
decfsz COUNT,F
goto IN_BYTE_1
movf I_BYTE,W
return
;------------------------------------------------------
WAIT_CONVERSION
;WAIT END OF CONVERSION WHILE ACTIVELEY POWERED
bcf DQ ;SET DATA PIN LOW ?? DO ONCE INITIALLY ??
bsf STATUS,RP0
bcf TRIS_DQ ;SET DATA PIN AS OUTPUT _ 0
nop ;1US
bsf TRIS_DQ ;SET AS DATA AS INPUT WITH PULL UP!!!
bcf STATUS,RP0 ;3US
goto $+1 ;5US
goto $+1 ;7US
goto $+1 ;9US
goto $+1 ;11US
goto $+1 ;13US
btfsc DQ ;14US SAMPLE NEAR END OF 15US
goto CONV_FINISHED
movlw .6 ;40US + EXTRAS _ MIN OF 45US
call DELAY_10US
goto WAIT_CONVERSION
CONV_FINISHED
movlw .4 ;40US + EXTRAS _ MIN OF 45US
call DELAY_10US
return
;------------------------------------------------------
PASSIVE_WAIT_CONVERSION
;WAIT END OF CONVERSION WHILE PASSIVELEY POWERED
;ALSO WORKS WHILE POWERED
;MUST DRIVE DQ HIGH DURING CONVERSION
bsf DQ
bsf STATUS,RP0
bcf TRIS_DQ ;DRIVE HIGH
bcf STATUS,RP0
movlw .4 ;4 * ~0.2S = ~800MS
movwf COUNT
call DELAY
decfsz COUNT,F
goto $-2
bsf STATUS,RP0
bsf TRIS_DQ ;FLOAT HIGH
bcf STATUS,RP0
bcf DQ
return
;------------------------------------------------------
DELAY
clrf LOOP ; ~ 0.2S DELAY (~256 X 256 X 3 US)
clrf LOOP1
ENCORE
decfsz LOOP,F
goto ENCORE
decfsz LOOP1,F
goto ENCORE
return
;------------------------------------------------------
DELAY_10US
movwf LOOP1
DELAY_10US_1
nop
nop
nop
nop
nop
nop
nop
decfsz LOOP1,F
goto DELAY_10US_1
return
;******************************************************************************
MESSAGE_DATA
; Screen lookup table.
; Each string starts with an address command byte and is terminated by a zero.
; DT means Define Table and is an assembler instruction, the assembler converts this to a
; series of retlw's, DT's are generally more readable except when defining chars.
movf MESS_POINTER,W
movwf PCL
; org 0x0f6 ; Debug only DELETE these 2 lines !!!!!!!!!!!!!!
; ; me testing macro !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
user_defs
; User defined char 5 x 7 plus 1 cursor line
; three most significant bits are ignored by screen
; MSB set to 1 to avoid 0 end of string marker in mid string.
retlw 0x48 ; Start address of second character (1) in character generator ram.
;char 1 ; The first character (0) is difficult to use as it can't be embedded
; in a string as 0 is used as end of string marker.
retlw b'10001010'
retlw b'10000000'
retlw b'10000100'
retlw b'10000100'
retlw b'10000000'
retlw b'10010001'
retlw b'10001110'
retlw b'10000000' ; cursor line, sometimes separated from other 7 rows
;char 2
retlw b'10001010' ; 0x50 start address of char 2
retlw b'10000000'
retlw b'10000100'
retlw b'10000100'
retlw b'10000000'
retlw b'10001110'
retlw b'10010001'
retlw b'10000000' ; cursor line, sometimes separated from other 7 rows
retlw 0 ; 0 marks end of string
really_hot_message
DT 0x80,"**** its hot", 0xC0,"Its above 30",0 ; 0x80 is effective address of first char on first line
; DT 0xC0,"Its above 30",0 ; string followed by userdefined chars 1 & 2 as defined above
; DT 0x80,"**** its hot",.1,.2,0
hot_message
DT 0x80,"Its hot",0 ; 0x80 is effective address of first char on first line
medium_message
DT 0x80,"Just right",0 ; 0x80 is effective address of first char on first line
cold_message ; 0xC0 is effective address of first char on second line
DT 0xC0,"Its a bit nippy!",0 ; string followed by userdefined chars 1 & 2 as defined above
;*******************************************************************************************
INITIALISE
movlw 0x07 ;PORTA comparator mode off
movwf CMCON ;normal digital I/O
clrf LCD_PORT
bsf STATUS,RP0 ; Change to bank 1
; cywizard begin
;movlw b'00000000' ; unused bits 0 & 1
movlw b'00000010' ; 2 bit is for RX setting it as input
; cywizard end
movwf LCD_TRIS ; Set data / control lines to Output
bcf STATUS,RP0 ; Go back to bank 0
bsf PORTA,1 ;LED ON
; cywizard begin
; ------------------------------------
; SET BAUD RATE TO COMMUNICATE WITH PC
; ------------------------------------
; Boot Baud Rate = 9600, No Parity, 1 Stop Bit
;
movlw 0x19 ; 0x19=9600 bps (0x0C=19200 bps)
banksel SPBRG
movwf SPBRG
movlw b'00100100' ; brgh = high (2)
banksel TXSTA
movwf TXSTA ; enable Async Transmission, set brgh
bcf STATUS,RP0 ; RAM PAGE 0
movlw b'10010000' ; enable Async Reception
banksel RCSTA
movwf RCSTA
;
; ------------------------------------
; PROVIDE A SETTLING TIME FOR START UP
; ------------------------------------
;
clrf dataL
settle decfsz dataL,F
goto settle
banksel RCREG
movf RCREG,W
movf RCREG,W
movf RCREG,W ; flush receive buffer
; cywizard end
movlw .20 ; ~15ms delay after screen power up before send to it
movwf SCREEN_DELAY_LOOP1 ; this delay is approx 15ms ( 20 x 256 x 3 us) @ 4MHz
clrf SCREEN_DELAY_LOOP
decfsz SCREEN_DELAY_LOOP,F
goto $-1
decfsz SCREEN_DELAY_LOOP1,F
goto $-3
movlw 0x20 ; set 4 bit data bus, at power up will be in 8 bit at this stage
call SEND_SCREEN_CMD ; will actually send 0x2? and 0x0? do D0-D3 float high/low
movlw 0x28 ; 4 bit, 2 line display
call SEND_SCREEN_CMD
movlw 0x06 ; Entry mode DD increment
call SEND_SCREEN_CMD
movlw 0x0E ; Display & cursor on, not flashing
call SEND_SCREEN_CMD ; Cursor is usefull while debuging, 0x0C for no cursor
call CLEAR_SCREEN
return
;*******************************************************************************************
CLEAR_SCREEN
movlw 0x01 ; Clear display, home cursor
call SEND_SCREEN_CMD
movlw .3 ; needs >= 1.64ms delay before next screen send
movwf SCREEN_DELAY_LOOP1 ; this delay is approx 2.3ms ( 3 x 256 x 3 us) @ 4MHz
clrf SCREEN_DELAY_LOOP
REP
decfsz SCREEN_DELAY_LOOP,F
goto REP
decfsz SCREEN_DELAY_LOOP1,F
goto REP
return
;*******************************************************************************************
SEND_SCREEN_CMD
bcf LCD_PORT,RS
goto SEND
SEND_SCREEN_DATA
bsf LCD_PORT,RS
SEND
movwf WORD_STORE ; Store all 8 bits of data
movlw B'00001111'
andwf LCD_PORT,F ; Clear data
movf WORD_STORE,W ; Collect data
andlw B'11110000' ; Strip bottom four bits
iorwf LCD_PORT,F ; Move data MSB Reg. B
nop ; all nops to allow port settle prior to next change
bsf LCD_PORT,E ; Enable screen
nop
bcf LCD_PORT,E
movlw B'00001111'
andwf LCD_PORT,F ; Clear data
swapf WORD_STORE,W ; Reverse nibbles of data
andlw B'11110000' ; Strip bottom four bits
iorwf LCD_PORT,F ; Move data LSB Reg. B
nop
bsf LCD_PORT,E ; Enable screen
nop
bcf LCD_PORT,E
movlw .12 ; Delay between screen sends needs to be >= 40us
movwf SCREEN_DELAY_LOOP ; ~12 x 3 us + call & return etc > 40 us between screen sends
GO_ROUND_AGAIN
decfsz SCREEN_DELAY_LOOP,F
goto GO_ROUND_AGAIN
return
;*******************************************************************************************
SEND_SCREEN_STRING
movwf MESS_POINTER
call MESSAGE_DATA ; Fetch address command
call SEND_SCREEN_CMD ; Send address set command
NEXT_DATA
incfsz MESS_POINTER,F ; Increment message pointer and check for overflow
goto NO_OVERFLOW
incf PCLATH,F ; inc PCLATH to move to next 256 memory block
NO_OVERFLOW
call MESSAGE_DATA ; fetch data
addlw .0 ; add zero, if data was 0 then Z of status will be set
btfsc STATUS,Z ; Test for stop byte
return ; This message finished, return
call SEND_SCREEN_DATA ; Display character
goto NEXT_DATA
;*******************************************************************************************
START_OF_PROG
call INITIALISE ; Set up port and screen
RE_READ
call READ_SCRATCHPAD
btfss FLAGS,PRESENCE
goto NOT_PRESENT
btfsc FLAGS,DS_ERROR
goto READ_ERROR
movf TEMP_MSB,F
btfss STATUS,Z
goto NEGATIVE
bcf STATUS,C
rrf TEMP_LSB,F
;TEMP_LSB IS DECIMAL TEMP
;PLUS 0.5 DEGREE IF C SET
; goto RE_READ
; cywizard begin
movf TEMP_LSB, W
call send_ser
; cywizard end
check_temp
call CLEAR_SCREEN
movlw .24 ; compare W with Decimal 25
subwf TEMP_LSB,W
btfsc STATUS,C ; result is C bit condition;
goto check_temp24
cold_result
call CLEAR_SCREEN
goto cold
check_temp24
call CLEAR_SCREEN
movlw .27 ; compare W with Decimal 25
subwf TEMP_LSB,W
btfsc STATUS,C ; result is C bit condition
goto check_temp30
medium_result
call CLEAR_SCREEN
goto medium
check_temp30
call CLEAR_SCREEN
movlw .30 ; compare W with Decimal 25
subwf TEMP_LSB,W
btfsc STATUS,C ; result is C bit condition
goto really_hot
hot
; bsf PORTB,1
LCD_STRING hot_message ; Display user defined graphic characters
goto RE_READ
really_hot
; bsf PORTB,1
LCD_STRING really_hot_message ; Display user defined graphic characters
goto RE_READ
cold
; bcf PORTB,1
LCD_STRING cold_message ; Display user defined graphic characters
goto RE_READ
medium
; bsf PORTB,1
LCD_STRING medium_message
goto RE_READ
NEGATIVE
;2'S COMPLIMENT NEGATIVE ROUTINE
NOT_PRESENT
;DS1820 NOT FOUND ROUTINE
READ_ERROR
;READ ERROR ROUTINE
FINISH
goto FINISH
END