; LCD_F84.ASM
; LCD_RESET - provides a means for the user to manually reset the LCD
; - brings RA.0 (serial lead) low for 2.5 secs. During this
; time, the user should manually reset the LCD.
; - routine then clears the LCD and ouptuts ten dots.
; - LCD is then cleared again.
; - W and STATUS are saved.
; LCD_DEBUG
; - displays W content and the state of the Z and C flags on line 1.
; - prints value of location 40H as a character on line 2.
; - displays values of locations 10, 11, 12, 13 on line 3.
; - locations 14, 15, 16, 17 on line 4.
; - this is followed by a one second delay.
; - the W and STATUS registers are saved and restored in returning
; to the calling program.
;
; LCD_CHAR - displays character in W on LCD. W and STATUS are saved.
; LCD_VAL - converts value in W to two hex characters and displays on LCD.
;
; LCD_BCD_WORD - displays quantity in 41H and 42H as unsigned decimal
; quantity. Note, this is limited to 9999 decimal.
; LIST p=16f84
; #include <\mplab\p16f84.inc>
; __CONFIG 11h
RADIX HEX
CONSTANT _MAX_VAR=4FH
CONSTANT TX=0 ; PORTA, Bit 0
_SER_DATA EQU _MAX_VAR-0 ; 4F
_SER_LOOP EQU _MAX_VAR-1 ; 4E
_SER_TIME EQU _MAX_VAR-2 ; 4D
_TEMP1 EQU _MAX_VAR-3 ; 4C
_TEMP2 EQU _MAX_VAR-4 ; 4B
_H EQU _MAX_VAR-3 ; 4C
_L EQU _MAX_VAR-4 ; 4B
_TH EQU _MAX_VAR-5 ; 4A
_HU EQU _MAX_VAR-6 ; 49
_TE EQU _MAX_VAR-7 ; 48
_UN EQU _MAX_VAR-8 ; 47
_SAVE_W EQU _MAX_VAR-9 ; 46
_SAVE_STAT EQU _MAX_VAR-0A ; 45
_LOOP1 EQU _MAX_VAR-1 ; used for pace timing, same location as _SER_LOOP
_LOOP2 EQU _MAX_VAR-2 ; used for pace timing, same location as _SER_TIME
_N_MSEC EQU _MAX_VAR-0B ; 44
_N1 EQU _MAX_VAR-0C ; 43
ORG 300H
LCD_BCD_WORD: ; displays a natural binary word in locations 41 and 42
; in decimal.
MOVWF _SAVE_W ; save W and STATUS
SWAPF STATUS, W
MOVWF _SAVE_STAT
SWAPF _SAVE_STAT, F ; status saved in true form
MOVF 41H, W
MOVWF _H
MOVF 42H, W
MOVWF _L
CLRF _TH
CLRF _HU
CLRF _TE
CLRF _UN
_BCD_1:
MOVLW .1
SUBWF _L, F
BTFSC STATUS, C ; a borrow occurred
GOTO _INC_DEC
MOVLW .1
SUBWF _H, F
BTFSC STATUS, C
GOTO _INC_DEC
SWAPF _TH, W
IORWF _HU, W
CALL _LCD_VAL
SWAPF _TE, W
IORWF _UN, W
CALL _LCD_VAL
GOTO _RETURN
_INC_DEC:
CLRWDT
INCF _UN, F
MOVLW .10
SUBWF _UN, W
BTFSS STATUS, Z
GOTO _BCD_1
CLRF _UN
INCF _TE, F
MOVLW .10
SUBWF _TE, W
BTFSS STATUS, Z
GOTO _BCD_1
CLRF _TE
INCF _HU, F
MOVLW .10
SUBWF _HU, W
BTFSS STATUS, Z
GOTO _BCD_1
CLRF _HU
INCF _TH, F
GOTO _BCD_1
LCD_RESET:
MOVWF _SAVE_W ; save W and STATUS
SWAPF STATUS, W
MOVWF _SAVE_STAT
SWAPF _SAVE_STAT, F ; save in true form
BSF STATUS, RP0
BCF TRISA, 0
BCF STATUS, RP0
BCF PORTA, 0 ; output a zero to LCD
MOVLW .10
MOVWF _N1
_RESET_1:
MOVLW .250
MOVWF _N_MSEC
CALL _DELAY_N
DECFSZ _N1, F
GOTO _RESET_1
MOVLW 0CH
CALL _LCD_CHAR
MOVLW .10
MOVWF _N1
_RESET_2:
MOVLW "."
CALL _LCD_CHAR
DECFSZ _N1, F
GOTO _RESET_2
MOVLW .4 ; one second delay
MOVWF _N1
_RESET_3:
MOVLW .250
MOVWF _N_MSEC
CALL _DELAY_N
DECFSZ _N1, F
GOTO _RESET_3
MOVLW 0CH
CALL _LCD_CHAR
GOTO _RETURN
LCD_DELAY: ; delays number of msecs in W
MOVWF _SAVE_W ; save W and STATUS
SWAPF STATUS, W
MOVWF _SAVE_STAT
SWAPF _SAVE_STAT, F ; save in true form
MOVF _SAVE_W, W ; get W
MOVWF _N_MSEC
CALL _DELAY_N
GOTO _RETURN
LCD_DEBUG:
MOVWF _SAVE_W ; save W and STATUS
SWAPF STATUS, W
MOVWF _SAVE_STAT
SWAPF _SAVE_STAT, F
MOVLW 0CH ; clear the LCD
CALL _LCD_CHAR
MOVLW "W" ; W=
CALL _LCD_CHAR
MOVLW "="
CALL _LCD_CHAR
MOVF _SAVE_W, W ; display value of W in hex
CALL _LCD_VAL
MOVLW " "
CALL _LCD_CHAR
MOVLW "Z" ; Z=
CALL _LCD_CHAR
MOVLW "="
CALL _LCD_CHAR
BTFSS _SAVE_STAT, Z
MOVLW "0"
BTFSC _SAVE_STAT, Z
MOVLW "1"
CALL _LCD_CHAR ; display either a zero or one
MOVLW " "
CALL _LCD_CHAR
MOVLW "C" ; C=
CALL _LCD_CHAR
MOVLW "="
CALL _LCD_CHAR
BTFSS _SAVE_STAT, C
MOVLW "0"
BTFSC _SAVE_STAT, C
MOVLW "1"
CALL _LCD_CHAR ; display either a zero or a one
MOVLW 0DH ; go to second line
CALL _LCD_CHAR
MOVLW 0AH
CALL _LCD_CHAR
MOVF 40H, W ; display location 40H as a char
CALL _LCD_CHAR
MOVLW 0DH ; go to third line
CALL _LCD_CHAR
MOVLW 0AH
CALL _LCD_CHAR
MOVLW 10H ; initialize pointer to RAM location 10
MOVWF FSR
MOVLW .4 ; four values on line
MOVWF _N1
_DEBUG_1:
MOVF INDF, W
CALL _LCD_VAL ; display values in loc 10, 11, 12, 13
INCF FSR, F
MOVLW " "
CALL _LCD_CHAR
DECFSZ _N1, F
GOTO _DEBUG_1
MOVLW 0DH ; go to 4th line
CALL _LCD_CHAR
MOVLW 0AH
CALL _LCD_CHAR
MOVLW .4 ; same for 14, 15, 16 and 17
MOVWF _N1
_DEBUG_2:
MOVF INDF, W
CALL _LCD_VAL
MOVLW " "
CALL _LCD_CHAR
INCF FSR, F
DECFSZ _N1, F
GOTO _DEBUG_2
MOVLW .250
MOVWF _N_MSEC
CALL _DELAY_N ; 250 msecs
CALL _DELAY_N
CALL _DELAY_N
CALL _DELAY_N
GOTO _RETURN
LCD_VAL: ; converts byte in W to two characters and outputs
MOVWF _SAVE_W ; save W and STATUS
SWAPF STATUS, W
MOVWF _SAVE_STAT
SWAPF _SAVE_STAT, F ; save it in true form
MOVF _SAVE_W, W ; get back W
_LCD_VAL:
MOVWF _TEMP1 ; save a copy of W
MOVF PCLATH, W
MOVWF _TEMP2 ; save PCLATH
MOVLW .3 ; page 3
MOVWF PCLATH
SWAPF _TEMP1, W ; high nibble now in lo nibble of W
ANDLW 0FH ;
CALL _HEX_LOOK
CALL _SEROUT
MOVF _TEMP1, W
ANDLW 0FH
CALL _HEX_LOOK
CALL _SEROUT
MOVF _TEMP2, W
MOVWF PCLATH ; previous value of PCLATH
GOTO _RETURN
_HEX_LOOK:
ADDWF PCL, F
DT "0", "1", "2", "3", "4", "5", "6", "7"
DT "8", "9", "A", "B", "C", "D", "E", "F"
LCD_CHAR: ; outputs character in W to LCD
MOVWF _SAVE_W ; save W and STATUS
SWAPF STATUS, W
MOVWF _SAVE_STAT
SWAPF _SAVE_STAT, F ; save in true form
MOVF _SAVE_W, W ; get back W
_LCD_CHAR:
CALL _SEROUT
MOVLW .10
MOVWF _N_MSEC
CALL _DELAY_N
GOTO _RETURN
_SEROUT: ; transmits content of W at 9600 Baud
MOVWF _SER_DATA
BSF STATUS, RP0 ; make TX bit an output
BCF TRISA, TX ;
BCF STATUS, RP0
BCF PORTA, TX ; set to stop bit
MOVLW .255
MOVWF _SER_TIME ; be sure stop bit has been high present
_SEROUT1: ; for some time
DECFSZ _SER_TIME, F
GOTO _SEROUT1
MOVLW .9
MOVWF _SER_LOOP
BCF STATUS, C ; set C to 0, start bit
_SEROUT2:
BTFSC STATUS, C
BCF PORTA, TX ; send a one
BTFSS STATUS, C
BSF PORTA, TX ; or a zero
MOVLW .31
MOVWF _SER_TIME ; one bit delay. 104 usecs at 9600 baud
_SEROUT3:
DECFSZ _SER_TIME, F
GOTO _SEROUT3
;NOP ; CHANGE
RRF _SER_DATA, F ; least sign bit now in C
DECFSZ _SER_LOOP, F ; does not affect status
GOTO _SEROUT2 ; next character
BCF PORTA, TX ; send stop bit
RETURN
_DELAY_N: ; delays number of msecs specified in _N_MSEC
MOVF _N_MSEC, W
MOVWF _LOOP1
_DELAY_1:
MOVLW .247 ; close to 1.0 msec delay when set to .247
MOVWF _LOOP2
_DELAY_2:
CLRWDT
DECFSZ _LOOP2, F ; decrement and leave result in LOOP2
; skip next statement if zero
GOTO _DELAY_2
DECFSZ _LOOP1, F
GOTO _DELAY_1
RETURN
_RETURN:
SWAPF _SAVE_STAT, W
MOVWF _TEMP2
SWAPF _TEMP2, W
MOVWF STATUS
SWAPF _SAVE_W, W ; get back W without altering STATUS
MOVWF _TEMP2
SWAPF _TEMP2, W
RETURN