For optical encoder I use this:
Code:
; PIC18F4520 

DEFINE OSC 4

INCLUDE "DT_INTS-14.bas"        ; Base Interrupt System
INCLUDE "ReEnterPBP.bas"        ; Include if using PBP interrupts

TRISA    = %00000000 ' Make all PortA pins output
TRISB    = %11001000

Define LCD_DREG PORTA
Define LCD_DBIT 0
Define LCD_RSREG PORTA
define LCD_RSBIT 4
define LCD_EREG PORTA 
define LCD_EBIT 6
define LCD_BITS 4
define LCD_LINES 2
define LCD_COMMANDUS 2000
define LCD_DATAUS 50

; encoder ch A PortB.6
; encoder ch B PortB.7

wsave       VAR BYTE $70     SYSTEM  ; alternate save location for W 
enc_new     VAR BYTE bank0
enc_old     VAR BYTE bank0
enc_counter VAR word bank0
Flag        var BYTE bank0

asm
INT_LIST  macro    ; IntSource,        Label,  Type, Resetflag?
        INT_Handler    RBC_INT, _enc,  ASM,  yes
    endm
    INT_CREATE     ; Creates the interrupt processor
endasm

; Set variable value @ startup       
enc_new = 0
enc_old= 0
enc_counter = 0
Flag = 0
@ INT_ENABLE RBC_INT  ; enable external (INT) interrupts 

Main_Loop:                                         
Lcdout $fe, 1
lcdout  Dec enc_counter  
goto Main_Loop

enc:
asm    
    ;Read latest input from PORTB & put the value in _enc_new.
         MOVE?CB 1,_Flag
         movf    PORTB,W
         movwf  _enc_new
                               ;Strip off all but the 2 MSBs in _enc_new.
         movlw    B'11000000'  ;Create bit mask (bits 7 & 6).
         andwf   _enc_new,F    ;Zero bits 5 thru 0.
                               ;Determine the direction of the Rotary encoder.  
         rlcf     _enc_old,F   ;left shift it into _enc_old to align bit 6 of 
                               ;_enc_old with bit 7 of _enc_new.
         movf    _enc_new,W    ;Move the contents of _enc_new to W in order to XOR.
         xorwf   _enc_old,F    ;XOR previous inputs (in _enc_old) with latest
                               ;inputs (in W) to determine CW or CCW.
 
         btfsc   _enc_old,7    ;Test bit 7 of result (in _enc_old).  Skip next line
                               ;if it is 0 (direction is CCW).
         goto    Up            ;Bit is 1 (direction is CW).  Go around Down
                               ;and increment counter.

Down
     ;Decrements _enc_counter because the rotary encoder moved CCW.
     ;Decrements _enc_counter (16 bit value), sets Z on exit.
              
        decf    _enc_counter,F      ; Decrement low byte
        incfsz  _enc_counter,W      ; Check for underflow
        incf    _enc_counter+1,F    ; Update
        decf    _enc_counter+1,F    ; Fixup
        movf    _enc_counter,W
        iorwf   _enc_counter+1,W    ; Set Z bit
        
    ;Add here code for the CCW LED if needed.
         
         goto    Continue          ;Branch around UP.
Up
    ;Increments _enc_counter because the rotary encoder moved CW.
    ;Increments _enc_counter (16 bit value), sets Z on exit.
        incfsz  _enc_counter,W      ; Add one to low byte
        decf    _enc_counter+1,F    ; No carry (negates next step)
        incf    _enc_counter+1,F    ; Add one to high byte
        movwf   _enc_counter        ; Store updated low byte back.
        iorwf   _enc_counter+1,W    ; Set Z flag
        
    ;Add here code for the CW LED if needed.
    
Continue 
         
    ;Assign the latest encoder inputs (in _enc_new) to _enc_old.
         movf     _enc_new,W
         movwf   _enc_old
         INT_RETURN
    ;============ END OF THE ROTARY ENCODER CODE =====
    endasm