        LIST P=16F676
        ERRORLEVEL  -302
        __config (_INTRC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_OFF & _MCLRE_OFF & _CP_OFF)

;
LCD_DATA                EQU     PORTC
LCD_DATA_TRIS           EQU     TRISC
;
LCD_CNTL                EQU     PORTA
;
;
; LCD Display Commands and Control Signal names.
;
E                       EQU     2               ; LCD Enable control line
RW                      EQU     1               ; LCD Read/Write control line
RS                      EQU     0               ; LCD Register Select control line
;
;
;
TEMP                    EQU     0x030
T0WRK                   EQU     0x031
CHAR                    EQU     0x032
;
                        org     0
                        GOTO    START

                        org     4
                        CLRF    INTCON
                        CLRF    T0WRK
                        RETFIE

DELAY
                        BSF     STATUS, RP0     ; Bank 1
                        MOVWF   OPTION_REG
                        BCF     STATUS, RP0     ; Bank 0
                        CLRF    TMR0
                        MOVLW   0x0A0
                        MOVWF   INTCON
                        MOVLW   0x01
                        MOVWF   T0WRK
TEST
                        BTFSS   T0WRK, 0
                        RETURN
                        GOTO    TEST


START
                        CLRF    STATUS          ; Do initialization (Bank 0)
                        CLRF    INTCON
                        CLRF    PIR1

;Config PORTA and PORTC

                        CLRF    PORTA
                        CLRF    PORTC
                        BSF     STATUS, RP0     ; Bank 1
                        CLRF    TRISA           ; PORTA are outputs
                        CLRF    TRISC           ; PORTC are outputs
                        BCF     STATUS, RP0     ; Bank 0

; Initilize the LCD Display Module

                        MOVLW   0x044
                        CALL    DELAY
                        MOVLW   0x044
                        CALL    DELAY

                        MOVLW   0x03
                        MOVWF   LCD_DATA
                        BSF     LCD_CNTL, E
                        NOP
                        BCF     LCD_CNTL, E
                        MOVLW   0x044
                        CALL    DELAY

                        MOVLW   0x03
                        MOVWF   LCD_DATA
                        BSF     LCD_CNTL, E
                        NOP
                        BCF     LCD_CNTL, E
                        MOVLW   0x04F
                        CALL    DELAY

                        MOVLW   0x03
                        MOVWF   LCD_DATA
                        BSF     LCD_CNTL, E
                        NOP
                        BCF     LCD_CNTL, E
                        MOVLW   0x04F
                        CALL    DELAY

                        MOVLW   0x028
                        CALL    SEND_CMD

                        MOVLW   0x08
                        CALL    SEND_CMD

                        MOVLW   0x02
                        CALL    SEND_CMD

;Send a message the hard way

                        movlw   'M'
                        call    SEND_CHAR
                        movlw   'i'
                        call    SEND_CHAR
                        movlw   'c'
                        call    SEND_CHAR
                        movlw   'r'
                        call    SEND_CHAR
                        movlw   'o'
                        call    SEND_CHAR
                        movlw   'c'
                        call    SEND_CHAR
                        movlw   'h'
                        call    SEND_CHAR
                        movlw   'i'
                        call    SEND_CHAR
                        movlw   'p'
                        call    SEND_CHAR
loop
                        goto    loop            ;Stay here forever


;*******************************************************************
;* The LCD Module Subroutines                                      *
;*******************************************************************


;*******************************************************************
;*SendChar - Sends character to LCD                                *
;*This routine sends the character to the LCD, upper nibble first. *
;*******************************************************************

SEND_CHAR
                        MOVWF   CHAR            ; Character to be sent is in W
                        CALL    BUSY_CHECK      ; Wait for LCD to be ready
                        SWAPF   CHAR, W
                        ANDLW   0x0F            ; Get upper nibble
                        MOVWF   LCD_DATA        ; Send data to LCD
                        BCF     LCD_CNTL, RW    ; Set LCD to read
                        BSF     LCD_CNTL, RS    ; Set LCD to data mode
                        BSF     LCD_CNTL, E     ; toggle E for LCD
                        BCF     LCD_CNTL, E
                        MOVF    CHAR, W
                        ANDLW   0x0F            ; Get lower nibble
                        MOVWF   LCD_DATA        ; Send data to LCD
                        BSF     LCD_CNTL, E     ; toggle E for LCD
                        BCF     LCD_CNTL, E
                        RETURN

;*******************************************************************
;* SendCmd - Sends command to LCD                                  *
;* This routine sends the command to the LCD, upper nibble first.  *
;*******************************************************************

SEND_CMD
                        MOVWF   CHAR            ; Character to be sent is in W
                        CALL    BUSY_CHECK      ; Wait for LCD to be ready
                        SWAPF   CHAR, W
                        ANDLW   0x0F            ; Get upper nibble
                        MOVWF   LCD_DATA        ; Send data to LCD
                        BCF     LCD_CNTL, RW    ; Set LCD to read
                        BCF     LCD_CNTL, RS    ; Set LCD to command mode
                        BSF     LCD_CNTL, E     ; toggle E for LCD
                        BCF     LCD_CNTL, E
                        MOVF    CHAR, W
                        ANDLW   0x0F            ; Get lower nibble
                        MOVWF   LCD_DATA        ; Send data to LCD
                        BSF     LCD_CNTL, E     ; toggle E for LCD
                        BCF     LCD_CNTL, E
                        RETURN

;*******************************************************************
;* This routine checks the busy flag, returns when not busy        *
;*  Affects:                                                       *
;*      TEMP - Returned with busy/address                          *
;*******************************************************************

BUSY_CHECK
                        BSF     STATUS, RP0     ; Bank 1
                        MOVLW   0xFF            ; Set PortB for input
                        MOVWF   LCD_DATA_TRIS
                        BCF     STATUS, RP0     ; Bank 0
                        BCF     LCD_CNTL, RS    ; Set LCD for Command mode
                        BSF     LCD_CNTL, RW    ; Setup to read busy flag
                        BSF     LCD_CNTL, E     ; Set E high
                        BCF     LCD_CNTL, E     ; Set E low
                        SWAPF   LCD_DATA, W     ; Read upper nibble busy flag, DDRam address
                        ANDLW   0xF0            ; Mask out lower nibble
                        MOVWF   TEMP            ;
                        BSF     LCD_CNTL, E     ; Toggle E to get lower nibble
                        BCF     LCD_CNTL, E
                        MOVF    LCD_DATA, W     ; Read lower nibble busy flag, DDRam address
                        ANDLW   0x0F            ; Mask out upper nibble
                        IORWF   TEMP, F         ; Combine nibbles
                        BTFSC   TEMP, 7         ; Check busy flag, high = busy
                        GOTO    BUSY_CHECK      ; If busy, check again
                        BCF     LCD_CNTL, RW
                        BSF     STATUS, RP0     ; Bank 1
                        MOVLW   0xF0            ;
                        MOVWF   LCD_DATA_TRIS   ; RB7 - 4 = inputs, RB3 - 0 = output
                        BCF     STATUS, RP0     ; Bank 0
                        RETURN

                        end