It's not that it's OK to "Be interrupted", but it's OK to be in the routine that does the interrupting.
PAUSEUS has a couple shortcomings. One, is that it uses PBP's system variables (R0-R8). So it corrupts PBP's flow if it's used in an ASM interrupt without "Instant Interrupts".
The second is that PAUSEUS has a minimum delay of around 24us @ 4mhz since it figures out the delay Count at run time.
The DelayUS macro can pause for a little as 1us by calculating the delay at Compile Time, and adding a single NOP if that's all that's needed. Or a 3cycle loop and 2 NOP's if running at 20mhz. And it doesn't use any PBP system vars.
It can be useful in other programs as well, so I'll show it here again for those that aren't as diligent as you Steve.
Code:
VP_DelayCount VAR WORD BANK0 ; Used for DelayUS only
ASM
;----[Similar to PAUSEUS, but ASM interrupt compatible]---(accurate to 1uS)--
DelayUS macro T
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
endm
ENDASM
Bookmarks