;;;;;;;;;;Проба работы в 4 битном режиме;;;;;;;;;;;;;
; LCD: D0-D7 подключены к RB0-RB7
; E - RA3, RS - RA2, R/W - GND
;================================================================
            LIST       P=16F84A
            __CONFIG   _XT_OSC & _CP_OFF & _PWRTE_OFF & _WDT_OFF
            include    P16F84A.inc
;================================================================

Var_1       equ        20h            ;
Var_2       equ        21h            ;
;================================================================
#define     RS         PORTA,2        ; вывод RS
#define     E          PORTA,3        ; вывод E
#define     LCD_PORT   PORTB
            org        0              ;
;================================================================
            clrf       STATUS         ; Настройка выводов МК
            clrf       PORTA          ;
            clrf       PORTB          ;
            bsf        STATUS,RP0     ;
            clrf       TRISA          ;
            clrf       TRISB          ;
            bcf        STATUS,RP0     ;
            
;=====================
; Variable Definitions

        cblock  H'20'
        delay_1
        delay_2
        delay_3
        tempLCD
        endc

;==============
; Reset Vector

        ;org   0x0000
        goto  Start

Init

;=====================
; Set up port and pins

        banksel TRISB           ; select TRISC bus
        movlw   B'00000000'     ; all pins output
        movwf   TRISB

        banksel PORTB            ; select LATC and clear
        clrf    PORTB

        return

;============================================
; Delay subroutine which lasts for 100 * cty

delay_long
        movwf   delay_3
delay_long_loop2
        movlw   D'13'
        movwf   delay_2
        clrf    delay_1
delay_long_loop1
        decfsz  delay_1,f
        goto    delay_long_loop1
        decfsz  delay_2,f
        goto    delay_long_loop1
        decfsz  delay_3,f
        goto    delay_long_loop2

        return

;============================
; Delay subroutine 1000 * cty

delay_short
        movwf   delay_2
delay_short_loop2
        movlw   D'249'
        movwf   delay_1
delay_short_loop1
        nop
        decfsz  delay_1,f
        goto    delay_short_loop1
        decfsz  delay_2,f
        goto    delay_short_loop2

        return

;==================
;LCD Initialisation

LCD_Init
        movlw   D'5'
        call    delay_long

        ;banksel PORTB
        bcf     RS          ; commands so RS bit set low
        movlw   b'00010000'           ; must be more than 15ms
        call    delay_short
        ;banksel PORTB
        movlw   0x03            ; send first high nibble
        movwf   LCD_PORT
        call    Nibble
        movlw   D'6'            ; must be more than 4.1ms
        call    delay_short
        ;banksel PORTB
        movlw   0x03            ; send second high nibble
        movwf   LCD_PORT
        call    Nibble
        movlw   D'1'            ; must be more than 100us
        call    delay_short
        ;banksel PORTB
        movlw   0x03            ; send third high nibble
        movwf   LCD_PORT
        call    Nibble
        movlw   D'5'            ; must be more than 5ms
        call    delay_short

        ;banksel PORTB
        movlw   0x02            ; set 4 bit mode
        movwf   LCD_PORT
        call    Nibble
        movlw   0x28            ; function set: 4 bit, 2 lines, 5 x 7 font
        call    LCD_Cmd
        movlw   0x08            ; display switch: D = 0, C = 0, B = 0
        call    LCD_Cmd
        call    LCD_Clear
        movlw   0x0C            ; display switch: D = 1, C = 0, B = 0
        call    LCD_Cmd

        movlw   0x06            ; input set: I/D = 1, S = 0
        call    LCD_Cmd

        ;banksel PORTB            ; make sure LATC port is clear
        clrf    PORTB

        movlw   D'50'           ; initialisation delay
        call    delay_long

        return

;============
; LCD Command

LCD_Cmd
        movwf   tempLCD           ; move contents of w into tempLCD
        swapf   tempLCD,w         ; swap contents of tempLCD put result in w
        andlw   0x0f              ; select high nibble
        movwf   LCD_PORT
        bcf     RS                ; RS set low due to instruction write
        call    Nibble
        movlw   D'1'
        call    delay_short

        movfw   tempLCD           ; move contents of tempLCD into w
        andlw   0x0f              ; select low nibble
        movwf   LCD_PORT
        bcf     RS            ; RS set low due to instruction write
        call    Nibble
        movlw   D'1'
        call    delay_short

        return

;==========
; LCD Write

LCD_Write
        movwf   tempLCD           ; move contents of w into tempLCD
        swapf   tempLCD,w         ; поменять местами содержимое tempLCD положить результат в w
        andlw   0xf                   ; Выбрать старший полубайт
        movwf   LCD_PORT          ; Записать в порт
        bsf     RS            ; RS set high due to instruction write
        call    Nibble
        movlw   D'1'
        call    delay_short
        movfw   tempLCD           ; move contents of tempLCD into w
        andlw   0xf               ; select low nibble
        movwf   LCD_PORT
        bsf     RS            ; RS set high due to instruction write
        call    Nibble
        movlw   D'5'              ; vary this delay to control writing speed
        call    delay_long
        return

;===========================
; Send nibble - toggle E pin

Nibble
        bsf     E             ; E set high
        movlw   D'1'
        call    delay_short
        bcf     E             ; E set low
        movlw   D'2'
        call    delay_short

        return

;===========
; LCD line 1

LCD_Line1
        movlw   0x80
        call    LCD_Cmd

        return

;===========
; LCD line 2

LCD_Line2
        movlw   0xC0
        call    LCD_Cmd

        return

;==============
; Clear Command

LCD_Clear
        movlw   0x01
        call    LCD_Cmd

        return

;============
; Write Space

LCD_Space
        movlw   0x20
        call    LCD_Write

        return

;=============
; Program main

Start
        call    Init
        call    LCD_Init

Main
        call    LCD_Clear
        call    LCD_Line1

Top_Line
        movlw   b'01001000' ; H
        call    LCD_Write
        movlw   'e'
        call    LCD_Write
        movlw   'l'
        call    LCD_Write
        movlw   'l'
        call    LCD_Write
        movlw   'o'
        call    LCD_Write
        call    LCD_Space
        movlw   'W'
        call    LCD_Write
        movlw   'o'
        call    LCD_Write
        movlw   'r'
        call    LCD_Write
        movlw   'l'
        call    LCD_Write
        movlw   'd'
        call    LCD_Write
        movlw   D'255'
        call    delay_long

Bottom_Line
        call    LCD_Line2
        movlw   'L'
        call    LCD_Write
        movlw   'C'
        call    LCD_Write
        movlw   'D'
        call    LCD_Write
        movlw   ' '
        call    LCD_Write
        call    LCD_Space
        movlw   'p'
        call    LCD_Write
        movlw   'i'
        call    LCD_Write
        movlw   'c'
        call    LCD_Write
        movlw   '1'
        call    LCD_Write
        movlw   '6'
        call    LCD_Write
        movlw   'f'
        call    LCD_Write
        movlw   D'255'
        call    delay_long

        goto    $                  ; loop forever

        end


