;***************************************************************************
;                                                                     
;	LCD TEST ROUTINE for demonstration of LCD animation V1.03
;	=========================================================
;
;	written by Peter Luethi, 16.05.1999, Dietikon, Switzerland
;	http://www.electronic-engineering.ch
;	last update: 31.12.2004
;
;	V1.03:	Added line test and 'walking square'.
;		(06.06.2004)
;
;	V1.02:	Improved animation.
;		(19.04.2004)
;
;	V1.01:	Added user-defined characters, defined in macro
;		LCDspecialChars in assembler module file m_lcdx.asm.
;		(x.x.1999?)
;
;	V1.00:	Initial release, for Hitachi HD44780 LCD controllers
;		and compatibles.
;		(16.05.1999)
;
;	This code and accompanying files may be distributed freely and
;	modified, provided this header with my name and this notice remain
;	intact. Ownership rights remain with me.
;	You may not sell this software without my approval.
;
;	This software comes with no guarantee or warranty except for my
;	good intentions. By using this code you agree to indemnify me from
;	any liability that might arise from its use.
;
;	
;	SPECIFICATIONS:
;	===============
;	Processor:			Microchip PIC 16X84
;	Clock Frequency:		4.00 MHz (HS mode)
;	Throughput:			1 MIPS
;	LCD Transmission Mode:		4 Bit on D4 - D7 (MSB),
;					uses high nibble of the LCD port
;	LCD Connections:		7 Wires
;					(4 Data, 3 Command)
;	Total LCD Connections:		10 Wires
;					(4 Data, 3 Command, 1 Vdd, 1 GND, 1 Contrast)
;	Code Size of entire Program:	approx. 557 instruction words
;	Required Hardware:		HD44780 compatible dot matrix LCD
;					(2x16, 2x20 or 2x40 characters)
;
;
;	DESCRIPTION:
;	============
;	Developed on PIC 16F84, but executeable on all PIC 16XXX.
;	Demonstrates LCD initialization and the use of various LCD commands.
;	Shows 2 self-defined characters and 15 special characters.
;
;***************************************************************************

;***** COMPILATION MESSAGES & WARNINGS *****

	ERRORLEVEL -207 	; Found label after column 1.
	ERRORLEVEL -302 	; Register in operand not in bank 0.

;***** PROCESSOR DECLARATION & CONFIGURATION *****

	;PROCESSOR 16F84
	;#include "p16f84.inc"

	PROCESSOR 16F84a
	#include "p16f84a.inc"
	
	; embed Configuration Data within .asm File.
	__CONFIG   _CP_OFF & _WDT_OFF & _PWRTE_ON & _HS_OSC

;***** MEMORY STRUCTURE *****

	ORG     0x00			; processor reset vector
  	goto    MAIN

	ORG     0x04			; interrupt vector location
	goto	MAIN			; no ISR

;***** PORT DECLARATION *****


;***** CONSTANT DECLARATION *****

	CONSTANT BASE = 0x0C		; base address of user file registers
	CONSTANT LCDWAIT = 0x01		; clk in [0..5] MHz
	CONSTANT LCDSPEED = 0x00	; clk in [0..9] MHz

;***** REGISTER DECLARATION *****	

	TEMP1	equ	BASE+d'6'	; Universal Temporary Register
	TEMP2	equ	BASE+d'7'

	FLAGreg	equ	BASE+d'8'
	#define	LCDbusy FLAGreg,0x00	; LCD busy flag declared within flag register
	#define	LCDcflag FLAGreg,0x01

;***** INCLUDE FILES *****

	#include "..\..\m_bank.asm"
	#include "..\..\m_wait.asm"

	;*** LCD module versions for fixed ports (e.g. PortB) ***
	LCDtris	equ	TRISB
	LCDport	equ	PORTB

;	#include "..\..\m_lcd.asm"
	#include "..\..\m_lcdx.asm"	; with user-defined characters
;	#include "..\..\m_lcd_bf.asm"
;	#include "..\..\m_lcdxbf.asm"	; with user-defined characters


	;*** configurable LCD module versions for modular ports (e.g. PortA & PortB) ***
;	LCDtris	equ	TRISA		; LCD data on low nibble of portA
;	LCDport	equ	PORTA
;	#define	LCD_ENtris TRISB,0x01	; EN on portB,1
;	#define	LCD_EN     PORTB,0x01	; Enable Output / "CLK"
;	#define	LCD_RStris TRISB,0x02	; RS on portB,2
;	#define	LCD_RS     PORTB,0x02	; Register Select
;	#define	LCD_RWtris TRISB,0x03	; RW on portB,3
;	#define	LCD_RW     PORTB,0x03	; Read/Write

;	#include "..\..\m_lcde.asm"
;	#include "..\..\m_lcde_bf.asm"
;	#include "..\..\m_lcdexbf.asm"	; with user-defined characters


;***** MACROS *****


;***** SUBROUTINES *****


;************** MAIN **************

MAIN
	LCDinit			; LCD Initialization
	
	LCDchar	'C'
	LCDchar	'h'
	LCDchar	'a'
	LCDchar	'r'
	LCDchar	'a'
	LCDchar	'c'
	LCDchar	't'
	LCDchar	'e'
	LCDchar	'r'
	LCDchar	's'
	LCDchar	':'
	LCDchar	' '
	
	LCDchar	0x00		; user-defined characters
	LCDchar	0x01

	LCDline 2		; change to position on the second line

	LCDchar	0xE0
	LCDchar	0xE1
	LCDchar	0xE2
	LCDchar	0xE3
	LCDchar	0xE4
	LCDchar	0xE5
	LCDchar	0xE8
	LCDchar	0xEF
	
	LCDchar	0xF3
	LCDchar	0xF4
	LCDchar	0xF5
	LCDchar	0xF6
	LCDchar	0xF7
	LCDchar	0xF8
	LCDchar	0xFD
	

	WAITX	d'20',d'7'

	LCDcmd	LCDCLR

	LCDchar	'P'
	LCDchar	'I'
	LCDchar	'C'
	LCDchar	'1'
	LCDchar	'6'
	LCDchar	'F'
	LCDchar	'8'
	LCDchar	'4'
	LCDchar	' '
	LCDchar	'L'
	LCDchar	'C'
	LCDchar	'D'
	LCDchar	't'
	LCDchar	'e'
	LCDchar	's'
	LCDchar	't'

	movlw	0x03		; repeat INTRO three times
	movwf	TEMP1

INTRO	LCD_DDAdr 0x44		; change to position on the second line
	LCDchar	'*'
	WAIT	0x80
	LCDchar	'*'
	WAIT	0x80
	LCDchar	'*'
	WAIT	0x80
	LCDchar	'*'
	WAIT	0x80
	LCDchar	'*'
	WAIT	0x80
	LCDchar	'*'
	WAIT	0x80
	LCDchar	'*'
	WAIT	0x80
	LCDchar	'*'
	WAIT	0x80
	LCD_DDAdr 0x44
	LCDchar	' '
	LCDchar	' '
	LCDchar	' '
	LCDchar	' '
	LCDchar	' '
	LCDchar	' '
	LCDchar	' '
	
	LCDcmd	LCDCL		; cursor move direction left
	LCDchar	'*'
	WAIT	0x80
	LCDchar	'*'
	WAIT	0x80
	LCDchar	'*'
	WAIT	0x80
	LCDchar	'*'
	WAIT	0x80
	LCDchar	'*'
	WAIT	0x80
	LCDchar	'*'
	WAIT	0x80
	LCDchar	'*'
	WAIT	0x80
	LCDchar	'*'
	WAIT	0x80
	LCD_DDAdr 0x4B
	LCDchar	' '
	LCDchar	' '
	LCDchar	' '
	LCDchar	' '
	LCDchar	' '
	LCDchar	' '
	LCDchar	' '
	LCDcmd	LCDCR		; cursor move direction right

	decfsz	TEMP1,f
	goto	INTRO

	LCDchar	' '
	WAITX	d'8',d'7'
	LCDcmd	LCDCLR
	LCDcmd	LCDL4
	LCDchar	'L'
	LCDchar	'i'
	LCDchar	'n'
	LCDchar	'e'
	LCDchar	' '
	LCDchar	'4'
	LCDcmd	LCDL3
	LCDchar	'L'
	LCDchar	'i'
	LCDchar	'n'
	LCDchar	'e'
	LCDchar	' '
	LCDchar	'3'
	LCDcmd	LCDL2
	LCDchar	'L'
	LCDchar	'i'
	LCDchar	'n'
	LCDchar	'e'
	LCDchar	' '
	LCDchar	'2'
	LCDcmd	LCDL1
	LCDchar	'L'
	LCDchar	'i'
	LCDchar	'n'
	LCDchar	'e'
	LCDchar	' '
	LCDchar	'1'
	WAITX	d'16',d'7'

	LCDcmd	LCDCH		; cursor home
	movlw	d'80'
	movwf	TEMP1
LOOP1	LCDchar	0xFF		; send black square (positive)
	decfsz	TEMP1,f
	goto	LOOP1
	WAITX	d'16',d'7'

	LCDcmd	LCDCH		; cursor home
	LCDchar	0xFE		; send white square (negative)
	movlw	d'2'		; outer loop
	movwf	TEMP1
LOOP2	movlw	d'40'		; inner loop
	movwf	TEMP2
LOOP2b	WAIT	0xA0
	LCDcmd	LCDSR		; 'walking square' on line 1
	decfsz	TEMP2,f
	goto	LOOP2b
	LCDcmd	LCDCH		; cursor home
	LCDchar	0xFF
	LCDcmd	LCDL2		; 'walking sqare' on line 2
	LCDchar 0xFE
	decfsz	TEMP1,f
	goto	LOOP2
	LCDcmd	LCDCLR		; clear LCD

LOOP3	WAIT	0xFF
	LCD_DDAdr 0x00
	LCDchar	'H'
	LCDchar	'e'
	LCDchar	'l'
	LCDchar	'l'
	LCDchar	'o'
	LCDchar	' '
	WAIT	0xFF
	LCD_DDAdr 0x41
	LCDchar	' '
	LCDchar	' '
	LCDchar	' '
	LCDchar	'W'
	LCDchar	'o'
	LCDchar	'r'
	LCDchar	'l'
	LCDchar	'd'
	movlw	0x07
	movwf	TEMP1
LO_1	WAIT	0xC0
	LCDcmd	LCDSR		; shift right LCD display content
	decfsz	TEMP1,f
	goto	LO_1

	WAIT	0xFF
	LCD_DDAdr 0x00
	LCDchar	'H'
	LCDchar	'e'
	LCDchar	'r'
	LCDchar	'e'
	LCDchar	b'00100111'
	LCDchar	's'
	WAIT	0xFF
	LCD_DDAdr 0x41
	LCDchar	'P'
	LCDchar	'I'
	LCDchar	'C'
	LCDchar	'1'
	LCDchar	'6'
	LCDchar	'F'
	LCDchar	'8'
	LCDchar	'4'
	movlw	0x07
	movwf	TEMP1
LO_2	WAIT	0xC0
	LCDcmd	LCDSL		; shift left LCD display content
	decfsz	TEMP1,f
	goto	LO_2

	goto LOOP3
	END

