;----------------------------------------------------------------------------
; *// Practice program to interface a LCD to the PIC17C766. //*
;----------------------------------------------------------------------------
; Steven Kosmerchock
; Phoenix, Arizona USA
; URL: www.geocities.com/researchtriangle/lab/6584
;----------------------------------------------------------------------------
;------ Revision History -----
;REV. 1.00A ****** 08/14/00 SK (INITIAL RELEASE)
;
;
;
;-----------------------------**************---------------------------------
;***************************** c7662x20.asm *********************************
;-----------------------------**************---------------------------------
;Program is a practice program to interface a LCD to the PIC17C766 MCU. 
;
;----------------------------------------------------------------------------
;Source name: (.asm):	c7662x20.asm
;Project name: (.pjt):	c7662x20.pjt
;----------------------------------------------------------------------------
;
	errorlevel 2,-302		;Gets rid of the "Register not in BANK0" message.
;	
	INCLUDE		<p17C766.inc>	;Include standard equates file.
;
	TITLE		"PIC17C766 LCD Practice Program 1"
;
	list	p=17C766	;Set processor to the PIC17C766.
	radix	hex		;Default format is in HEX.
;----------------------------------------------------------------------------
W	equ	0
F	equ	1
Z	equ	2
rp0	equ	5
count1	equ	0x1a
count2	equ	0x1b
mcount	equ	0x1c
ncount	equ	0x1d
;----------------------------------------------------------------------------
; // Microcontroller Configurations Information & Setup //
;
; 	_MC_MODE: 	Puts MCU in FULL Microcontroller Mode.
; 	_BODEN_OFF: 	Turns Brown-Out Detect OFF.
;	_WDT_OFF: 	Turns Watch Dog Timer OFF.
; 	_EC_OSC:	Sets oscillator to "External Clock".
;
	__CONFIG	_MC_MODE & _BODEN_OFF & _WDT_OFF & _EC_OSC	
;
	org	0x000
;
;----------------------------------------------------------------------------
; // "init_ports" initializes and clears all I/O ports! // 
;
init_ports:
	nop
	movlb	0		;Switch to BANK0.
	clrf	PORTA,F		;Clear PORTA.
	clrf	PORTB,F		;Clear PORTB.
	movlb	1		;Switch to BANK1.
	clrf	PORTC,F		;Clear PORTC.
	clrf	PORTD,F		;Clear PORTD.
	clrf	PORTE,F		;Clear PORTE.
	movlb	5		;Switch to BANK5.
	clrf	PORTF,F		;Clear PORTF.
	clrf	PORTG,F		;Clear PORTG.
	movlb	8		;Switch to BANK8.
	clrf	PORTH,F		;Clear PORTH.
	clrf	PORTJ,F		;Clear PORTF.
;
;----------------------------------------------------------------------------
; // "define_ports" defines MCUs ports. User defined!! // 
;
define_ports:
	movlb	0		;Switch to BANK0.
	movlw	0xff		;Fill "W" with all 1's.
	movwf	PORTA		;Set PORTA 'HIGH' on all pins.
	movlw	0x00		;Fill "W" with all 0's.
	movwf	DDRB		;Set DDRB & PORTB to OUTPUTs.
	clrf	PORTB		;Clear PORTB.
	movlb	1		;Switch to BANK1.
	movlw	0xff		;Fill "W" with all 1's.
	movwf	DDRC		;Set DDRC & PORTC to INPUTs.
	movwf	DDRD		;Set DDRD & PORTD to INPUTs.
	movlw	0x01		;Fill "W" with all 0's.
	movwf	DDRE		;Set DDRE & PORTE to OUTPUTs.
	clrf	PORTE		;Clear PORTE.
	movlb	5		;Switch to BANK5.
	movlw	0x0e		;Load "W" with b'00001110'
	movwf	ADCON1		;Switch A/D to all DIGITAL I/O!
	movlw	0x00		;Load "W" with all 0's.
	movwf	DDRF		;Set DDRF & PORTF to OUTPUTs.
	movwf	DDRG		;Set DDRG & PORTG to OUTPUTs.
	movlb	8		;Switch to BANK8.
	movlw	0xff		;Fill "W" with all 1's.
	movwf	DDRH		;Set DDRH & PORTH to INPUTs.
	movwf	DDRJ		;Set DDRJ & PORTJ to INPUTs.
	movlw	b'10010000'	;Set "FSR0" to post auto-increment.
	movwf	ALUSTA
;	call	pause
;	call	pause
;
start	call	blanks		;fill display RAM with blanks
	call	hello		;create message in display RAM
	call	del_5		;allows LCD to initialize itself
	call	initlcd		;initialize display
	call	disp80		;Send 80 characters to dsiplay (4x20)
;
;
circle	
	nop
	movlb	5
	movlw	0xaa
	movwf	PORTF
	goto	circle		;loops here, "done"!
;--------------------------------------------------------------------
blanks	movlb	0
	movlw	0x50		;count=80 ***(amount of characters to be- 
;					-displayed, can be changed!)***
	movwf	count1
	movlw	0x20		;first display RAM address (can be changed!)
	movwf	FSR0		;indirect addressing
	movlw	0x20		;ascii blank
store	movwf	INDF0		;store in display RAM location pointed to by fsr
	decfsz	count1,F	;80?	
	goto	incfsr		;not 80 yet!
	return			;YES!! reached 80!
incfsr	incf	FSR0,F		;increment FSR0
	goto	store
;--------------------------------------------------------------------
hello	movlb	0
	movlr	0x0000
	movlw	b'10100000'	
	movwf	0x20
	movlw	b'10100000'
	movwf	0x22
	movlw	b'10100000'
	movwf	0x24
	movlw	'P'
	movwf	0x26
	movlw	'I'
	movwf	0x28
	movlw	'C'
	movwf	0x2a	
	movlw	'1'
	movwf	0x2c
	movlw	'7'
	movwf	0x2e
	movlw	'C'
	movwf	0x30
	movlw	'7'
	movwf	0x32
	movlw	'6'
	movwf	0x34
	movlw	'6'
	movwf	0x36
	movlw	b'10100000'
	movwf	0x38
	movlw	'L'
	movwf	0x3a
	movlw	'C'
	movwf	0x3c
	movlw	'D'
	movwf	0x3e
	movlw	b'10100000'
	movwf	0x40
	movlw	b'10100000'
	movwf	0x42
	movlw	b'10100000'		
	movwf	0x44
	movlw	b'10100000'
	movwf	0x46
	movlw	b'10100000'		;20	
	movwf	0x48
	movlw	'I'
	movwf	0x4a
	movlw	'n'
	movwf	0x4c
	movlw	't'
	movwf	0x4e
	movlw	'e'
	movwf	0x50
	movlw	'r'
	movwf	0x52	
	movlw	'f'
	movwf	0x54
	movlw	'a'
	movwf	0x56
	movlw	'c'
	movwf	0x58
	movlw	'e'
	movwf	0x5a
	movlw	b'10100000'
	movwf	0x5c
	movlw	'E'
	movwf	0x5e
	movlw	'x'
	movwf	0x60
	movlw	'a'
	movwf	0x62
	movlw	'm'
	movwf	0x64
	movlw	'p'
	movwf	0x66
	movlw	'l'
	movwf	0x68
	movlw	'e'
	movwf	0x6a
	movlw	b'10100000'		
	movwf	0x6c
	movlw	b'10100000'		;40
	movwf	0x6e
	movlw	b'10100000'	
	movwf	0x70
	movlw	b'10100000'
	movwf	0x72
	movlw	b'10100000'
	movwf	0x74
	movlw	'P'
	movwf	0x76
	movlw	'I'
	movwf	0x78
	movlw	'C'
	movwf	0x7a	
	movlw	'1'
	movwf	0x7c
	movlw	'7'
	movwf	0x7e
	movlw	'C'
	movwf	0x80
	movlw	'7'
	movwf	0x82
	movlw	'6'
	movwf	0x84
	movlw	'6'
	movwf	0x86
	movlw	b'10100000'
	movwf	0x88
	movlw	'L'
	movwf	0x8a
	movlw	'C'
	movwf	0x8c
	movlw	'D'
	movwf	0x8e
	movlw	b'10100000'
	movwf	0x90
	movlw	b'10100000'
	movwf	0x92
	movlw	b'10100000'		
	movwf	0x94
	movlw	b'10100000'
	movwf	0x96
	movlw	b'10100000'		;20	
	movwf	0x98
	movlw	'I'
	movwf	0x9a
	movlw	'n'
	movwf	0x9c
	movlw	't'
	movwf	0x9e
	movlw	'e'
	movwf	0xa0
	movlw	'r'
	movwf	0xa2	
	movlw	'f'
	movwf	0xa4
	movlw	'a'
	movwf	0xa6
	movlw	'c'
	movwf	0xa8
	movlw	'e'
	movwf	0xaa
	movlw	b'10100000'
	movwf	0xac
	movlw	'E'
	movwf	0xae
	movlw	'x'
	movwf	0xb0
	movlw	'a'
	movwf	0xb2
	movlw	'm'
	movwf	0xb4
	movlw	'p'
	movwf	0xb6
	movlw	'l'
	movwf	0xb8
	movlw	'e'
	movwf	0xba
	movlw	b'10100000'		
	movwf	0xbc
	movlw	b'10100000'		;40
	movwf	0xbe
	return
;--------------------------------------------------------------------
initlcd	movlb	1		
	bcf	PORTE,1		;E line low
	bcf	PORTE,2		;RS line low, set up for control
	call	del_125		;delay 125 microseconds (with 4MHZ XTAL!!)
	movlb	0
	movlw	0x38		;8-bit, 5X7
	movwf	PORTB		;0011 1100
	call	pulse		;pulse and delay
	movlb	0
	movlw	0x0c		;display on, cursor off
	movwf	PORTB		;0000 1100
	call	pulse		
	movlb	0
	movlw	0x06		;increment mode, no display shift
	movwf	PORTB		;0000 0110
	call	pulse	
	call	del_5		;delay 5 milliseconds-!!!!REQIUIRED 
;					before sending data!!!!
	return
;;------------------------------------------------------------------
disp40	movlb	1
	bcf	PORTE,1		;E line low
	bcf	PORTE,2		;RS line low,set up for control
	call	del_125		;delay 125 microseconds
	movlb	0
	movlw	0x80		;control word=address first half!
	movwf	PORTB
	call	pulse		;pulse and delay
	movlb	1
	bsf	PORTE,2		;RS=1, now you can set up for data
	call	del_125		;delay 125 microseconds (with 4MHz XTAL!!)
	movlb	0
	movlw	0x20		;initalize FSR0
	movwf	FSR0
getchar	movlb	0
	movpf	0x00,PORTB		;get character from display RAM location
;					pointed to by fsr
;	movwf	PORTB		
	call	pulse		;send data to display
	movlb	0
	movlw	0x8e		;40 th character sent (!!Half of TOTAL
;				characters to be sent!!)can be changed!!
	subwf	FSR0,W		;subtract w from FSR0
	btfsc	ALUSTA,Z	;test z flag
	goto	half		;set up for last 40 characters
	movlw	0xde		;test number..(can be changed to needs!!)
	subwf	FSR0,W		
	btfsc	ALUSTA,Z	;test z flag
	return			;80 characters sent to display
	incf	FSR0,F		;move to next character location
	goto	getchar
half	movlb	1
	bcf	PORTE,2		;RS=0, set up for control
	call	del_125		;delay 125 microseconds (with 4MHz XTAL!!)
	movlb	0
	movlw	0xc0		;control word=address second half
	movwf	PORTB		
	call	pulse		;pulse and delay
	movlb	1
	bsf	PORTE,2		;RS=1, set up for data
	incf	FSR0,F		;increment fsr to select next character
	call	del_125		;delay 125 microseconds (with 4MHz XTAL!!)
	goto	getchar
;--------------------------------------------------------------------
del_125	movlw	0x2a		;approx 42x3 cycles (decimal)
	movwf	count1		;load counter
repeat	decfsz	count1,f	;decrement counter
	goto	repeat		;not 0
	return			;counter=0, delay ends!
;--------------------------------------------------------------------
del_5	movlw	0x29		;decimal 40 (can be changed!!)
	movwf	count2		;to counter
delay	call	del_125		;delay 125 microseconds (with 4MHz XTAL!!)
	decfsz	count2,f	;do it 40 times=5 miliseconds!!
	goto	delay
	return			;counter-0, delay ends!
;--------------------------------------------------------------------
pulse	movlb	1
	bsf	PORTE,1		;pulse E line (turns on "ENABLE" of LCD)
	nop
	bcf	PORTE,1		;turns E line OFF!
	call	del_125		;delay 125 microseconds (with 4MHz XTAL!!)
	return
;----------------------------------------------------------------------------
pause	movlw	0xff
	movwf	mcount
loadn	movlw	0xff
	movwf	ncount
decn	decfsz	ncount,F
	goto	decn
	decfsz	mcount,F
	goto	loadn
	return
;----------------------------------------------------------------------------
	end			;END of program!!
