Thanks Bruce, Paul and Steve,

And yes I did cheat, by using a module that I had already written.

I started writing VirtualPort in response to this post from Osiris
http://www.picbasic.co.uk/forum/showthread.php?t=3554

He was looking for a way to have a 16-bit port that was scattered across random pins. By the time I got it working, Melanie had already given him what he needed, so I didn't bother posting it.

But, I soon realized that it was going to be more usefull than originally intended so continued to add more macro's and features, and have managed to do some pretty cool stuff with it.

Here's how the 16-bit port for Osiris looked...
Code:
MyPort   VAR Word  SYSTEM
ASM  
MyPortPins  macro        ; these define which bits go with which pins
    Vpin   0, PORTB,0
    Vpin   1, PORTC,4
    Vpin   2, PORTA,0
    Vpin   3, PORTC,1
    Vpin   4, PORTC,3
    Vpin   5, PORTC,0
    Vpin   6, PORTA,1
    Vpin   7, PORTC,5
    Vpin   8, PORTB,2
    Vpin   9, PORTB,3
    Vpin  10, PORTC,2
    Vpin  11, PORTC,0
    Vpin  12, PORTB,4
    Vpin  13, PORTB,6
    Vpin  14, PORTB,5
    Vpin  15, PORTC,7
  endm
ENDASM

@  OutputPort  MyPortPins
@  WritePort   MyPort, MyPortPins

@  InputPort   MyPortPins
@  ReadPort    MyPort, MyPortPins
This creates a full 16-bit bi-directional port that can be placed on ANY pins in ANY order.<HR>
Additional macros can also allow control of Direction, Enable, Latch pulses etc. in the same structure. Here's an 8-bit port with flow control
Code:
Direction  VAR PORTB.5
Enable     VAR PORTB.1

ASM
Port8_Read  macro
    PinLow _Direction   ; Set direction pin for Read
    Vpin   0, PORTB,0
    Vpin   1, PORTC,4
    Vpin   2, PORTA,0
    Vpin   3, PORTC,1
    Vpin   4, PORTC,3
    Vpin   5, PORTC,0
    Vpin   6, PORTA,1
    Vpin   7, PORTC,5
    PulseLow  Enable, 2 ; Low pulse for 2uS
  endm

Port8_Write  macro
    PinHigh _Direction   ; Set direction pin for Write
    Vpin   0, PORTB,0
    Vpin   1, PORTC,4
    Vpin   2, PORTA,0
    Vpin   3, PORTC,1
    Vpin   4, PORTC,3
    Vpin   5, PORTC,0
    Vpin   6, PORTA,1
    Vpin   7, PORTC,5
    PulseLow  Enable, 2 ; Low pulse for 2uS
  endm
ENDASM

@  OutputPort  Port8_Write
@  WritePort   MyPort, Port8_Write

@  InputPort   Port8_Read
@  ReadPort    MyPort, Port8_Read
Or that can be simplified like this...
Code:
ASM
Port8_Pins  macro
    Vpin   0, PORTB,0
    Vpin   1, PORTC,4
    Vpin   2, PORTA,0
    Vpin   3, PORTC,1
    Vpin   4, PORTC,3
    Vpin   5, PORTC,0
    Vpin   6, PORTA,1
    Vpin   7, PORTC,5
    PulseLow  Enable, 2 ; Low pulse for 2uS
  endm

Port8_Read  macro
    PinLow _Direction   ; Set direction pin for Read
    Port8_Pins
  endm

Port8_Write  macro
    PinHigh _Direction   ; Set direction pin for Write
    Port8_Pins
  endm
ENDASM
<hr>

Another similar question that keeps popping up every now and then, is how to use an LCD that's not connected to a contiguous nibble of a port.

This program allows you to do that, and also ties it in with LCDOUT for a "transparent" interface.
Code:
INCLUDE "HighJack.bas"
@  HighJack  LCDOUT,  _LCDsend

Clear
INCLUDE "VirtualPort.bas"

;----[ Change these to match your LCD ]---------------------------------------
LCD_DB4   VAR PORTB.0
LCD_DB5   VAR PORTB.4
LCD_DB6   VAR PORTC.6
LCD_DB7   VAR PORTC.3
LCD_RS    VAR PORTD.1
LCD_E     VAR PORTD.0
LCD_Lines     CON 2    ' # of Lines on LCD,  1 or 2+
LCD_DATAUS    CON 50   ' Data delay time in us 
LCD_COMMANDUS CON 2000 ' Command delay time in us 
 

;----[Virtual LCD Port --- 4bit mode]----------------(Don't Change)-----------
ASM
LCD_Port_HNIB  macro           ; Port definition for LCD High Nibble
    Vbit   LCDCDFLAG, _LCD_RS  ; Select Command/Data register
    Vpin   4, _LCD_DB4         ; Put the High Nibble on the bus
    Vpin   5, _LCD_DB5
    Vpin   6, _LCD_DB6
    Vpin   7, _LCD_DB7
    PulseLow  _LCD_E, 2        ; pulse the Enable Pin for 2 us
  endm
;-----------------------    
LCD_Port_LNIB  macro           ; Port definition for LCD Low Nibble 
    Vpin   0, _LCD_DB4         ; Put the Low Nibble on the bus
    Vpin   1, _LCD_DB5
    Vpin   2, _LCD_DB6
    Vpin   3, _LCD_DB7
    PulseLow  _LCD_E, 2        ; pulse the Enable Pin for 2 us
  endm
  
  OutputPort  LCD_Port_HNIB    ; Set LCD bus to OUTPUT
ENDASM


;----[Main program starts here]-----------------------------------------------
LoopCount  VAR WORD
  

Main:
  lcdout $FE,$80, dec LoopCount
  LoopCount = LoopCount + 1
goto Main

;----[Send a byte to the Virtual LCD PORT]--------called by LCDOUT------------
TempChar        var  byte
Char            VAR  Byte
LCD_Initialized VAR  FLAGS.1
RSS             VAR  FLAGS.0                ; LCD RS State

;-------
LCDsend:
      @  MOVE?AB  _TempChar                 ; Get char sent by LCDOUT, in WREG
      if !LCD_Initialized then LCD_Init     ; Make sure LCD was Initialized 
  LCDAfterInit:
      if TempChar = $FE then RSS=0 : goto LCDsendDone ; next char is Command 
      Char = TempChar
  LCDsendCOM:
      @  WritePort   _Char, LCD_Port_HNIB   ; send the High Nibble
  LCDsendShortCOM:
      @  WritePort   _Char, LCD_Port_LNIB   ; send the Low Nibble

      if LCD_RS OR (Char > 2) then
          PAUSEUS LCD_DATAUS                ; Data delay time in us 
      else
          PAUSEUS LCD_COMMANDUS             ; Command delay
      endif
      if LCD_Initialized then RSS = 1       ; Set RS to Data next time
  LCDsendDone:
return

;----[Initialize the LCD]-----------------------------------------------------
LCD_Init:
    LOW LCD_RS : HIGH LCD_E   ; Start with RS LOW and Enable High
    Char = 3   : gosub  LCDsendShortCOM : pause 6
                 gosub  LCDsendShortCOM : PAUSE 1
                 gosub  LCDsendShortCOM : PAUSE 1
    Char = 2   : gosub  LCDsendShortCOM : PAUSE 1  ; Start 4-bit mode
    Char = $28 : gosub  LCDsendCOM  ; Function Set, 4-bit, 2-line, 5x7
    Char = $0C : gosub  LCDsendCOM  ; Display ON
    Char = $01 : gosub  LCDsendCOM  ; Clear Screen
    Char = $06 : gosub  LCDsendCOM  ; Entry Mode
    LCD_Initialized = 1             ; LCD has been Initialized
goto LCDAfterInit
Of course this relies on another program I wrote, "HighJack", to actually link in to LCDOUT. But nobody bothered to respond to this thread
http://www.picbasic.co.uk/forum/showthread.php?t=3290

so I never bothered posting it.
<br>