Hi,

I think Darrel wrote something about that ... some times ago.

this was the origin of "LCD on Any pin" !

Here it is ...

Code:
'****************************************************************
'*  Name    : VirtualPort.bas                                   *
'*  Author  : Darrel Taylor                                     *
'*  Date    : 3/20/2006                                         *
'*  Version : 1.1                                               *
'*  Notes   : Allows you to control non-contiguous PINs/BITs    *
'*          : as if they were a contiguous PORT/Register        *
'****************************************************************
'*  See this Webpage for more info                              *
'*  http://www.picbasic.co.uk/forum/showthread.php?t=4074       *
'****************************************************************
'*  with assistance from:                                       *
'*   1.1    SteveB                                              *
'*   1.2    ?                                                   *
'****************************************************************

disable debug


VP_DelayCount  VAR WORD BANK0  ; Used for internal Delay only

ASM
PortVar set 0
   ; nolist

;----[Defines a Virtual PIN in a Virtual PORT]--------------------------------
Vpin  macro  Vb, P, Pbit
  local Vaddr, VarBit
    if (Vb < 16)                                 ; If Var bit# is < 16 
      if (Pbit < 8)                              ; and Port bit# is < 8
          if (PortAction < 2)                      
              if (Vb > 7)                        ; Var Bit > 7, use high word
Vaddr  = PortVar + 1
VarBit = Vb - 8
              else
Vaddr  = PortVar
VarBit = Vb
              endif
          endif
          if (PortAction == 0)                   ; read
              MOVE?TT  P, Pbit, Vaddr, VarBit      
          else
              if (PortAction == 1)               ; write
                  MOVE?TT  Vaddr, VarBit, P, Pbit  
              else
                  if (PortAction == 2)           ; output
                      PhysicalPort  P            ; only if it's a Real PORT
                      if (Found == 1)
                          OUTPUT?T  P, Pbit
                      endif
                  else
                      if (PortAction == 3)       ; input
                          PhysicalPort  P        ; only if it's a Real PORT
                          if (Found == 1)
                              INPUT?T  P, Pbit
                          endif       
                      endif
                  endif
              endif
          endif
      else
            error Vpin - PORT BIT [Pbit] Out of Range
      endif  
    else
        error Vpin - Variable BIT [Vb] Out of Range
    endif  
  endm

;----[Copy a bit to a Pin]----------------------------------------------------
Vbit  macro  Rin,Bin, Rout,Bout
    MOVE?TT  Rin,Bin, Rout,Bout
  endm
  
;----[Read a Virtual Port]----------------------------------------------------
ReadPort  macro PortVar, PinMacro
  ; nolist
PortAction = 0  ; Read
       PinMacro
    list  
  endm
    
;----[Write a variable to a Virtual Port]-------------------------------------
WritePort  macro PortVar, PinMacro
  ; nolist
PortAction = 1
        PinMacro
    list  
  endm
  
;----[Set ALL pins of a virtual Port to OUTPUT]-------------------------------
OutputPort  macro  PinMacro
  ; nolist
PortAction = 2
        PinMacro
    list  
  endm
    
;----[Set ALL pins of a virtual Port to INPUT]--------------------------------
InputPort  macro PinMacro
  ; nolist
PortAction = 3
        PinMacro
    list  
  endm

; These 4 are useful for Port Control Pins, such as Enable and Direction pins
; They don't change the TRIS state during INPUT/OUTPUT calls, which makes
; bi-directional ports a lot easier.
  
;----[Make a Pin LOW]---- Does not change TRIS bit ---------------------------
PinHigh  macro  P, B
  ; nolist
    if (PortAction < 2)   ; Don't do anything on Input or Output pass
        MOVE?CT  1, P, B  ; Make Pin HIGH
    endif
    list  
  endm

;----[Make a Pin LOW]---- Does not change TRIS bit ---------------------------
PinLow  macro  P, B
  ; nolist
    if (PortAction < 2)   ; Don't do anything on Input or Output pass
        MOVE?CT  0, P, B  ; Make Pin LOW
    endif
    list  
  endm

;----[Similar to PAUSEUS, but ASM interrupt compatible]---(accurate to 1uS)---
DelayUS  macro T
  ; nolist
  local InstCount, LoopCount, DelayLoop, LoopsDone, LeftOver, Offset
; -- Calculate number of 3 cycle loops plus leftover nop's to execute --
InstCount = ((OSC*10/4)*T+5)/10  ; Inst cycles required for delay (Rounded UP)
LoopCount = InstCount / 3
    if (LoopCount > 255)
Offset = (LoopCount >> 8) * 7 + 4
    else
Offset = 0
    endif
; -- Adjust for HighByte --
InstCount = InstCount - Offset
    if (Offset > (LoopCount & 0FFh))
InstCount = InstCount - 4
    endif
LoopCount = InstCount / 3
    if (LoopCount > 255)
Offset = (LoopCount >> 8) * 7
    else
Offset = 0
    endif
LeftOver  = InstCount % 3
;-------------------------------------------
    if (LoopCount > 0)
        MOVE?CW  LoopCount, _VP_DelayCount
DelayLoop
        decfsz   _VP_DelayCount, F               ;  1
        goto     DelayLoop                       ;  2    3 per loop, under 256
    
        if (LoopCount > 255)
            movf     _VP_DelayCount + 1, W       ;  1    
            btfsc    STATUS, Z                   ;  1    
            goto     LoopsDone                   ;  2    4 on last loop
            
            decf     _VP_DelayCount + 1, F       ;  1    
            goto     DelayLoop                   ;  2    7 per highbyte count 
LoopsDone
        endif
    endif
    if (LeftOver > 0)
        nop
    endif
    if (LeftOver > 1)
        nop
    endif

    list  
  endm
  
;----[Pulse a Pin LOW for a specified number of uS]---------------------------
PulseLow  macro P, B, Time
  ; nolist
    PhysicalPort  P            
    if (Found == 1)            ; only if it's a Real PORT
        if (PortAction < 2)
          MOVE?CT  0, P, B
          DelayUS  Time
          MOVE?CT  1, P, B
        endif
    else
        error "PulseLow - Can only Pulse a Physical Pin"
    endif
    list  
  endm

;----[Pulse a Pin HIGH for a specified number of uS]---------------------------
PulseHigh  macro P, B, Time
  ; nolist
    PhysicalPort  P            
    if (Found == 1)            ; only if it's a Real PORT
        if (PortAction < 2)
          MOVE?CT  1, P, B
          DelayUS  Time
          MOVE?CT  0, P, B
        endif
    else
        error "PulseHigh - Can only Pulse a Physical Pin"
    endif
    list  
  endm
  
;----[Is the PIN a Physical PIN or just a register?]-----(Compile Time Only)--
PhysicalPort macro P
  ; nolist
Found = 0
    ifdef GPIO
        if P == GPIO
Found = 1
        endif
    endif
    ifdef PORTA
        if P == PORTA
Found = 1
        endif
    endif
    ifdef PORTB
        if P == PORTB
Found = 1
        endif
    endif
    ifdef PORTC
        if P == PORTC
Found = 1
        endif
    endif
    ifdef PORTD
        if P == PORTD 
Found = 1
        endif
    endif
    ifdef PORTE
        if P == PORTE
Found = 1
        endif
    endif
    ifdef PORTF
        if P == PORTF
Found = 1
        endif
    endif
    ifdef PORTG
        if P == PORTG
Found = 1
        endif
    endif
    ifdef PORTH
        if P == PORTH
Found = 1
        endif
    endif
    ifdef PORTI
        if P == PORTI
Found = 1
        endif
    endif
    ifdef PORTJ
        if P == PORTJ
Found = 1
        endif
    endif
    ifdef PORTK
        if P == PORTK
Found = 1
        endif
    endif
  
    list
  endm
    
  list
ENDASM
                                                    
disable debug
;----[Trick PBP into including certain macro's]---Doesn't use any code space--
@  ifdef NotCompiled
@DummyPort = 0
 DummyPort VAR BYTE EXT
       OUTPUT DummyPort.0       ; OUTPUT?T
       INPUT  DummyPort.0       ; INPUT?T
@  endif

enable debug
Alain