I'm trying to re-create a hardware serial port with pure software. I need a non-blocking RECEIVE port because I need to add a 3rd port to my 8723.

Most of the interrupt-driven routines I have seen have a very large processor overhead because they sample all the time and because they sample often so as to get the bit timing right.

I'm trying an approach that uses INT0. It watches for the first falling edge of the START bit, then starts a TMR4 interrupt to time the rest of the bits. Using this approach should use zero processing power when a byte isn't coming in, and not too many cycles when one is. INT0 is turned on only to detect the falling edge of the START bit. TMR4 int is turned on only when receiving bits.

The trouble is - the following code always returns 0xff whenever I send it a character. Can someone tell me what I'm doing wrong? RxD is coming through a MAX232 and is fed to PORTB.0

Code:
          T4CON = %00000110   ; T4 ON, /16 prescale, no postscalers
         INTCON = %11000000  ; Global Int enable, peripheral INT enable
         INTCON2 = %00000000
         
         PIE3.3 = 0 ;Turn off Int on tmr 4
         IPR3.3 =1           ; High priority for INT4


         bit_cntr  VAR BYTE
         rcv_byte  VAR BYTE
         byteready VAR BYTE
         rcv_buffer   VAR BYTE
;-----------------------------------------------------------------------

        INCLUDE "DT_INTS-18.bas"         ; Base Interrupt System

  
ASM
INT_LIST  macro    ; IntSource,        Label,  Type, ResetFlag?
              INT_Handler    INT0_INT,   GetStart,   ASM,  no 
              INT_Handler    TMR4_INT,   BitTimer,   ASM,  no

          endm
    INT_CREATE               ; Creates the interrupt processor
ENDASM
                         
Goto OverInt

'---[INT - interrupt handler]---------------------------------------------------
   
ASM
GetStart  
      bcf T4CON,2   ; Turn off Timer 4
      movlw 0x97   ; w /16 prescaler gives 156uSec dly @ 40Mhz = 1.5 bit times
      movwf TMR4
      bsf T4CON,2     ; Turn timer 4 on
      bsf  PIE3,3     ; turn on the Timer4 INT
      movlw 0x08      ; load the bit counter  
      movwf _bit_cntr
      bcf INTCON,4   ; shut off the INT0 interrupt
      bcf  INTCON,1   ; clear INT0 int flag bit
      INT_RETURN
ENDASM     
     
ASM
BitTimer
      bcf T4CON,2     ; Turn Timer4 off 
      movlw 0xBF      ; 104uSec   / 16, 40 Mhz  1 bit time
      movwf TMR4      ; load it
      bsf T4CON,2     ; Turn it back on
      btfss PORTB,0   ; check status of portB.0
      bcf   STATUS,C  ; move bit into carry
      btfsc PORTB,0   ; check status of portb.0
      bsf   STATUS,C   ; move bit into carry
      rrcf   _rcv_byte,f ; shift carry into rec'd byte
      decfsz _bit_cntr,f ; decrement the bit counter
      bra   Donebit      ; get out and wait for next int
      bra Donebyte       ; got 8  bits
      
Donebit      
      bcf  PIR3,3        ; clear the int flag
      bsf  PIE3,3        ; start the TMR4 int again
      INT_RETURN
      
Donebyte      
      movff _rcv_byte,_rcv_buffer
      movff _rcv_buffer,PORTD  ; this is a debug, just to see rec'd byte on LEDS
      bcf  PIR3,3       ; clear the int flag
      bsf INTCON,4   ; turn on the INT0 interrupt for next byte
      INT_RETURN
ENDASM      
      
          
OVERINT:

    TRISD = 0
    PORTD = 0
    TRISE = 0
    INTCON.1 = 0
    PIE3.3 = 0
    PIR3.3 = 0   
         
         PAUSE 100
    
@    INT_ENABLE INT0_INT  
  
  
WAITT:

    GOTO WAITT