;*****************************************************************************
;  This Code Sends the data to the LCD in 4 Bit mode and
;   writes the string: "Hello".
;
;  The data is shifted out to a 74LS174 with The High Order Bit being a "Gate"
;   Bit connected to the LCD's "E" line.  The next Highest Bit goes to the
;   LCD's "RS" Bit.  The lowest Bit goes to D4 (and each Bit is higher from
;   there).
;
;
;  Hardware Notes:
;   Reset is tied directly to Vcc and PWRT is Enabled.
;   The PIC is a 16C84 Running at 4 MHz.
;   PortA.0 is the Data Bit
;   PortA.1 is the Clock Bit
;
;
;  Data Being Sent looks like:
;
;          Clear S/R           Shift Data      Strobe
;
;         ÚÄÄÄÄÄÄÄÄÄÄÄÄÄ¿     ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;         ³             ³     ³              ³
;
;                      ÚÄÄÄÄÄÄÄÄÄÄ±±±±±±±±±±    Ú¿
;  Data  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ                    ÄÄÄÄÙÀÄÄ
;        ÄÄ¿Ú¿Ú¿Ú¿Ú¿Ú¿ÚÄÄÄÄÄÄÄÄÄ¿Ú¿Ú¿Ú¿Ú¿Ú¿ÚÄÄÄÄÄÄÄÄ
;  Clock   ÀÙÀÙÀÙÀÙÀÙÀÙ         ÀÙÀÙÀÙÀÙÀÙÀÙ
;                                               Ú¿
;  E     ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙÀÄÄ
;
;  Shift Data:
;  Bit 1 - Always High (Gate for "E")
;  Bit 2 - RS Bit
;  Bit 3 - LCD D4
;  Bit 4 - LCD D5
;  Bit 5 - LCD D6
;  Bit 6 - LCD D7
;
;  Myke Predko
;  99.03.13
; Jan 2007 - tilføjet DELEY-routine så ting sker på displayet
;  OZ6YM, Palle 2007.01.31
;******************************************************************************
  LIST P=16f84a, R=DEC          ;  16C84 Runs at 4 MHz
  errorlevel 0,-305
  INCLUDE "p16f84a.inc"


;  Register Usage
 CBLOCK 0x00C                   ;  Start Registers at End of the Values
Dlay                            ;  8 Bit Delay Variable
Temp				;  Temporary Value Used When Sending Out Data
NOTemp				;  Temporary Value to "NybbleOutput"
COUNT1
COUNT2
COUNT3
 ENDC


;  Define Information
#DEFINE Data PORTA,0
#DEFINE Clock PORTA, 1


;  Macros
ClockStrobe MACRO		;  Strobe the Data Bit
  	bsf	Clock
  	bcf	Clock
 	ENDM

EStrobe	MACRO			;  Strobe the "E" Bit
  	bsf	Data
  	bcf Data
 	ENDM


 PAGE
 __CONFIG _CP_OFF & _XT_OSC & _PWRTE_ON  & _WDT_OFF

;  Note that the WatchDog Timer is OFF
;  Demo Code, Loop Forever Toggling PA0 (Flashing the LED)

  org    0

  clrf   PORTA

  	movlw  	0x01C          	;  Enable PA0 & PA1 for Output
 	bsf    	STATUS, RP0
  	movwf  	TRISA ^ 0x080
  	bcf    	STATUS, RP0
Start
 	call    Dlay5          	;  Wait 20 msecs before Reset
 	call    Dlay5
 	call    Dlay5
 	call    Dlay5

  	bcf     STATUS, C      	;  Clear Carry (Instruction Out)
  	movlw   0x03           	;  Reset Command
  	call    NybbleOut      	;  Send the Nybble
  	call	Dlay5		;  Wait 5 msecs before Sending Again

  	EStrobe
  	call	Dlay160		;  Wait 160 usecs before Sending the Third Time

  	EStrobe
  	call	Dlay160		;  Wait 160 usecs before Sending the Third Time

  	bcf     STATUS, C              
  	movlw   0x02            ;  Set 4 Bit Mode
  	call    NybbleOut              
  	call	Dlay160		

  	movlw	0x028		;  Note that it is a 2 Line Display
  	call	SendINS

  	movlw	0x008		;  Turn off the Display
  	call	SendINS

  	movlw	0x001		;  Clear the Display RAM
  	call	SendINS
  	call	Dlay5		;  Note, Can take up to 4.1 msecs

  	movlw	0x006		;  Enable Cursor Move Direction
  	call	SendINS

  	movlw	0x00C		;  Turn the LCD Back On
  	call	SendINS

  	clrf	FSR		;  Output the Message

OutLoop
  	movf	FSR, w		;  Get the Offset to Output
  	incf	FSR
  	call	Message
  	iorlw	0		;  At the End of the Message?
  	btfsc	STATUS, Z
  	goto	Loop		;  Yes - Equal to Zero
  	call	SendCHAR	;  Output the ASCII Character
	call 	DELAY		; make delay between character (OZ6YM)
	call 	DELAY
	call 	DELAY
    	goto	OutLoop

Loop
	call 	DELAY		; make delay and start all over (OZ6YM)
	call 	DELAY
	call 	DELAY	
	call 	DELAY
	call 	DELAY
	call 	DELAY
	call 	DELAY
	call 	DELAY
	call 	DELAY
				;  Loop Forever when Done
  	goto	Start


;  Subroutines
Message				;  Message to Output
  	addwf	PCL		;  Output the Characters
  	dt	" Hello World    de OZ6YM", 0

SendCHAR			;  Send the Character to the LCD
  	movwf	Temp		;  Save the Temporary Value
  	swapf	Temp, w		;  Send the High Nybble
  	bsf	STATUS, C	;  RS = 1
  	call	NybbleOut
  	movf	Temp, w		;  Send the Low Nybble
  	bsf	STATUS, C
  	call	NybbleOut
  	return

SendINS				;  Send the Instruction to the LCD
  	movwf	Temp		;  Save the Temporary Value
  	swapf	Temp, w		;  Send the High Nybble
  	bcf	STATUS, C	;  RS = 0
  	call	NybbleOut
  	movf	Temp, w		;  Send the Low Nybble
  	bcf	STATUS, C
  	call	NybbleOut
  	return

NybbleOut			;  Send a Nybble to the LCD

  	movwf	NOTemp		;  Save the Nybble to Shift Out
  	swapf	NOTemp		;  Setup to Output to the High Part of the Byte
  	movlw	6		;  Clear the Shift Register
  	movwf	Dlay

NOLoop1
  	ClockStrobe
  	decfsz 	Dlay
   	goto	NOLoop1
  	bsf	Data		;  Put out the Gate Bit
  	ClockStrobe
  	bcf	Data		;  Put out the RS Bit
  	rlf	PORTA
  	ClockStrobe
  	movlw	4		;  Now, Shift out the Data
  	movwf	Dlay

NOLoop2
  	rlf	NOTemp		;  Shift Through the Nybble to Output
  	bcf	Data		;  Clear the Data Bit (which is the Clock)
  	rlf	PORTA		;  Shift the Carry into the Shift Register
  	ClockStrobe
  	decfsz  Dlay
   	goto	NOLoop2
  	EStrobe			;  Strobe out the LCD Data
  	return


Dlay160                 	;  Delay 160 usecs
  	movlw  	256 - ( 160 / 4 ); Loop Until Carry Set
  	addlw  	1
  	btfss  	STATUS, C
   	goto  	$-2
  	return

Dlay5                   	;  Delay 5 msecs
  	movlw  	4              	;  Set up the Delay
  	movwf  	Dlay
  	movlw  	256 - 0x0E8
  	addlw  	1
 	btfsc  	STATUS, Z
   	decfsz 	Dlay
    	goto 	$-3

  return

;Make ONE BIT DELAY - copy from CW-out (OZ6YM)
DELAY	MOVLW	B'00000001'	; setup delay 
	MOVWF	COUNT3		; This is where to set the speed
	MOVLW 	B'01111111'	; eksperimenter til din ønskede hastighed
	MOVWF	COUNT2

DEL1	decfsz	COUNT1,1	;Subtract one from COUNT1
	goto	DEL1		;If Count is zero carry on
	decfsz	COUNT2,1	;Subtract 1 from COUNT2
	goto	DEL1		;Go back to start of loop.
	decfsz	COUNT3,1	;Subtract 1 from COUNT3
	goto	DEL1		;Branch if zero

	RETURN			;full delay done

  end
