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
Bookmarks