Hi all.
I've been lurking around here for about a month now learning my way to getting up to speed on pic programming, I have done numerous basicX and stamp projects in the past, but since discovering the speed and ability of direct programming, the time of stamps is in the way past now. Want to say it's amazing how helpful these forums are, armed with the power of search
there is no reason why anyone can't be up and running in a flash...

So that aside here's my first roadblock, I would like to get up to speed in using asm interrupts
decided to make a project that utilizes a rotary quadrature encoder, (panel type) it's not going to be machine driven, just for human interaction. after searching and discovering numerous threads about multiple ways to read the encoder, I wanted to try what looks like an elegant method of reading the port change interrupt on RB<7:4> to change a variable in the background letting me just check that variable in the main program loop, to display on a basic parallel lcd. so I will first describe my setup/pic/ect.. then explain what issues I am experiencing. Thanks in advance for any help or insight..

I am using a PIC16F876A

Here is my hardware wiring.

( 1) MCLR --> 4.7k --> 5v+
( 2) RA0 --> LCD Data
( 3) RA1 --> LCD Data
( 4) RA2 --> LCD Data
( 5) RA3 --> LCD Data
( 6) RA4 -->
( 7) RA5 -->
( 8) Vss --> Gnd
( 9) OSC1 --> 20mhz Osc
(10) OSC2 --> 20mhz Osc
(11) RC0 --> Status Led1
(12) RC1 -->
(13) RC2 --> Status Led2
(14) RC3 -->
(15) RC4 -->
(16) RC5 -->
(17) RC6 -->
(18) RC7 --> LCD Backlight
(19) Vss --> Gnd
(20) Vdd --> 5v+ --> .1uf Cap --> Gnd
(21) RB0 --> Encoder PushButton --> 10k --> 5v+
(22) RB1 --> LCD RS Bit
(23) RB2 --> LCD Enable Bit
(24) RB3 -->
(25) RB4 -->
(26) RB5 -->
(27) RB6 --> Encoder Phase A --> 10k --> 5v+
(28) RB7 --> Encoder Phase B --> 10k --> 5v+

I have been reading thru the following threads to learn as much as I can about using
various ways to read an encoder.

http://www.picbasic.co.uk/forum/showthread.php?t=1552
Ive based my ISR on Lucianos code from the above thread. (Thanks!!!)

also have looked at using timer interrupts for encoder reading
http://www.picbasic.co.uk/forum/showthread.php?t=1886
I have plans later for the timer, so going to try to stick with portB change for now. (baby steps)

I've also found some other code (non asm, just picbasic) that does a pretty good job
can't seem to find the post at the moment.. but it had a real wierd issue, going one direction
I would miss every 3rd step, but the other way it was perfect..
I know I don't really need the precision that an asm interrupt has for a slow turning encoder,
but would also like to use this oppertunity to learn how to do it efficiently.

so first here is my code...
Code:
'problem code

'setup PIC Config Fuses
    @ Device pic16F876A, HS_OSC, BOD_OFF, PWRT_ON, WDT_OFF, PROTECT_OFF

'************************ DEFINES HERE *************************************
DEFINE OSC 20               ' set to 20mhz
DEFINE LCD_DREG PORTA       ' Set Data Registers port
DEFINE LCD_DBIT 0           ' Set starting data bit
DEFINE LCD_RSREG PORTB      ' Set LCD RS Port
DEFINE LCD_RSBIT 1          ' Set LCD RS Bit
DEFINE LCD_EREG PORTB       ' Set LCD Enable Port
DEFINE LCD_EBIT 2           ' Set LCD Enable Bit
DEFINE LCD_BITS 4           ' Set LCD 4bit Mode
DEFINE LCD_LINES 2          ' Set number of LCD Lines
DEFINE LCD_COMMANDUS 2000   ' Set Command Delay time in uS
DEFINE LCD_DATAUS 60        ' Set Data delay time in uS 

clear                       'clear out variables

'*********************** CHIP REGISTER SETUP *******************************

ADCON0 = 7
ADCON1 = 7              ' turn off analog porta, set to digital IO
CMCON =  7              ' Turn off Port A Comparator
TRISA = 0               ' output ports
TRISB = %11111001       ' set input and output ports
TRISC = 0               ' output ports

'************************ PROGRAM VARIABLES HERE ***************************

symbol led = portc.2        ' status led
symbol led2 = portc.0       ' status led2
symbol lcdbkl = portc.7     ' lcd pannel backlight
symbol sw1 = portb.0        ' encoder switch

enc_old VAR BYTE
enc_new VAR BYTE
enc_counter VAR WORD
enc_counter_old VAR WORD


'*********************** ASSEMBLY INTERUPT VARIABLES ***********************
wsave   var     byte $20 system
wsave1  var     byte $a0 system  ' Necessary for devices with RAM in bank1
wsave2  var     byte $120 system ' Necessary for devices with RAM in bank2
wsave3  var     byte $1a0 system ' Necessary for devices with RAM in bank3
ssave   var     byte bank0 system
psave   var     byte bank0 system     

goto start			'skip over interupt handler
'*********************** ASSEMBLY INTERUPT HANDLER *************************

define  INTHAND myint
Asm
       
myint 
  	; BCF INTCON,GIE ;Should I have this????
	; Save W, STATUS and PCLATH registers, if not done previously
	movwf   wsave
        swapf   STATUS, W
        clrf    STATUS
        movwf   ssave
        movf    PCLATH, W
        movwf   psave  
         
        movlw   high 100      ; Wait 100us to debounce encoder
        movwf   R0 + 1
        movlw   low 500
        call    PAUSEUSL


	;====== BEGINNING OF THE ROTARY ENCODER CODE ========
	;The Rotary Encoder is connected to PORTB  
	;The A signal of the encoder connected to the PIN portB.7
	;The B signal of the encoder connected to the PIN portB.6
	;
	;The 3 variables used are declared in the PicBasic code.
	;
	;	enc_new VAR BYTE
	;	enc_old VAR BYTE
	;	enc_counter VAR WORD
	;
	;================================================
		
	;Read latest input from PORTB & put the value in _enc_new.
     	movf    PORTB,W
     	movwf  _enc_new

     	;Strip off all but the 2 MSBs in _enc_new.
     	movlw	0xc0    	     ;Create bit mask (bits 7 & 6). b'11000000' ?
     	andwf   _enc_new,F       ;Zero bits 5 thru 0.

     	;Determine the direction of the Rotary encoder.  
     	rlf     _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.
     	bsf     _led		    ;turn on led
     	
     	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.
	   bsf     _led2		    ;turn on led
	
Continue     	
     	;Assign the latest encoder inputs (in _enc_new) to _enc_old.
     	movf 	_enc_new,W
     	movwf   _enc_old

        ; Restore saved registers
        movf    psave, W
        movwf   PCLATH
        swapf   ssave, W
        movwf   STATUS
        swapf   wsave, F
        swapf   wsave, W
        bcf     INTCON, RBIF		  ; Clear the Interupt Flag
        RETFIE                 	  	  ; Return from interrupt
endasm

'***************************************************************************
'************************* PROGRAM STARTS HERE *****************************
'***************************************************************************

START:              ' Main Program starts here

LCDOUT $FE,1		'Init The LCD
pause 500		    'wait for LCD to start 

lcdout $FE,1,"ENCODER"	    'display splash screen
LCDOUT $FE,$C0," TEST "       
high lcdbkl                 ' turn on backlight


'************************** SET DEFAULT SETTINGS HERE **********************
pause 2000		    ' just wait a bit to read splash screen
enc_counter = 1024	' set default encoder value
enc_counter_old = 1024	
lcdout $FE,1,"ENCODER"  ' change display
INTCON = %10001000      ' Enable PortB Change Interupts  


'************************** TESTING ROUTINES HERE **************************
test:
            if  enc_counter <> enc_counter_old then 'see if value has changed
                enc_counter_old = enc_counter		'move new value to old
                lcdout $fe,$C0, DEC5 enc_counter	'display enc_counter value
                low led		                        'turn off CCW led
                low led2	                        'turn off CW led
            endif
goto test
ok, questions I have.. [oops post is getting too long... see next post]