; ---------------------------------------------------------------------------------------- tools box
; --------------------------------------------------------------------------------------------------
variable BANK0 = 0x20 ; first free byte in bank0
variable BANK1 = 0xA0 ; first free byte in bank1
variable BANK2 = 0x110 ; first free byte in bank2
variable BANK3 = 0x190 ; first free byte in bank3
variable BANK4 = 0x70 ; first free byte in shared bank
CBLOCK BANK0
_W0 ; working register
_W1 ; working register
_M1BAK ; macro register backup
_WBAK ; W backup
_PCLATHBAK ; PCLATH backup
ENDC
variable BANK0 = _PCLATHBAK+1
CBLOCK BANK4
_M1 ; macro register
_STATUSBAK ; STATUS backup
ENDC
variable BANK4 = _STATUSBAK+1
SAVEREG macro
movwf _WBAK ; save W
swapf STATUS,W ; W <- STATUS [ 3:0 , 7:4 ]
movwf _STATUSBAK ; save STATUS, without change Z flag
clrf STATUS ; STATUS <- 0 then BANK0
movf _M1,W ;
movwf __M1BAK ; save _M1 (macro register)
movf PCLATH,W ;
movwf _PCLATHBAK ; save PCLATH
clrf PCLATH ; PCLATH <- 0 then PAGE0
endm
RESTREG macro
movf _M1BAK,W ;
movwf _M1 ; restore _M1
movf _PCLATHBAK,W ;
movwf PCLATH ; restore PCLATH
swapf _STATUSBAK,W ;
movwf STATUS ; restore STATUS
swapf _WBAK,F ;
swapf _WBAK,W ; restore W
retfie ; return & GIE <- 1
endm
; ----------------------------------------------------------------------
; MACRO DEDIEE AU TEST DES CAUSES D'INTERRUPTION
; ----------------------------------------------------------------------
; ISR : Interrupt Service Routine= adresse de la routine d'interruption
; IER : Interrupt Enable Register= numero du registre du bit enable
; IEB : Interrupt Enable Bit = numero du bit enable dans IER
; IFR : Interrupt Flag Register = numero du registre du bit drapeau
; IFB : Interrupt Flag Bit = numero du bit drapeau dans IFR
; ENABLE : drapeau d'activation du test de cause, 3 valeurs possibles
; ----------------------------------------------------------------------
variable never_enable = 0 ; interruption jamais utilisée
variable always_enable = 1 ; interruption utilisée et non masquable
variable maybe_enable = 2 ; interruption utilisée et masquable
variable _pie1_copied = 0 ; à 1 quand la recopie de registre est faite
variable _pie2_copied = 0 ; à 1 quand la recopie de registre est faite
ISRCALL macro ISR,IER,IEB,IFR,IFB,ENABLE
if (ENABLE!=never_enable) ; si l'interruption est utilisée on entre
if (ENABLE==maybe_enable) ; sinon si l'int pas tjs util on teste ena
variable _IER = IER ; par defaut le registre enable est IER
if (IER==PIE1)
variable _IER = _W0 ; changement de registre enable
endif
if (IER==PIE2)
variable _IER = _W1 ; changement de registre enable
endif
if ((IER==PIE1)&&(_pie1_copied==0))
variable _pie1_copied = 1
bsf STATUS,RP0 ; passe du bank0 au bank1
movf PIE1,w ; va chercher le registre PIE1
bcf STATUS,RP0 ; passe du bank0 au bank1
movwf _W0 ; et en fait une copie
endif
if ((IER==PIE2)&&(_pie2_copied==0))
variable _pie2_copied = 1
bsf STATUS,RP0 ; passe du bank0 au bank1
movf PIE2,w ; va chercher le registre PIE2
bcf STATUS,RP0 ; passe du bank0 au bank1
movwf _W1 ; et en fait une copie
endif
btfss _IER, IEB ; on teste juste le bit enable
goto $+3 ; le bit enable n'est pas à 1, on saute
endif
btfsc IFR, IFB ; saute à la routine de traitement si FLAG = 1
goto ISR ; routine de traitement de l'ISR
endif
endm
BTOB macro @from,@to ; bank to bank change RP bits from @from to @to
if (((@from & 0x080) == 0) && ((@to & 0x080) != 0))
bsf STATUS, RP0
endif
if (((@from & 0x080) != 0) && ((@to & 0x080) == 0))
bcf STATUS, RP0
endif
if (((@from & 0x100) == 0) && ((@to & 0x100) != 0))
bsf STATUS, RP1
endif
if (((@from & 0x100) != 0) && ((@to & 0x100) == 0))
bcf STATUS, RP1
endif
endm
; --------------------------------------------------------------------------------------- Arithmetic
; --------------------------------------------------------------------------------------------------
add macro @r1,@r2,@r3 ; add @r1 = @r2 + @r3
movf @r3,w
if (@r1 != @r2)
addwf @r2,w
movwf @r1
else
addwf @r2,f
endif
endm
sub macro @r1,@r2,@r3 ; subtract @r1 = @r2 - @r3
movf @r3,w
if (@r1 != @r2)
subwf @r2,w
movwf @r1
else
subwf @r2,f
endif
endm
addi macro @r1,@r2,@i3 ; add immediate @r1 = @r2 + @i3
if ((@r1 == @r2) && (@i3 == 1))
incf @r1,f
else
movlw @i3
if (@r1 != @r2)
addwf @r2,w
movwf @r1
else
addwf @r2,f
endif
endif
endm
subi macro @r1,@r2,@i3 ; subtract immediate @r1 = @r2 - @r3
if ((@r1 == @r2) && (@i3 == 1))
decf @r1,f
else
movlw @i3
if (@r1 != @r2)
subwf @r2,w
movwf @r1
else
subwf @r2,f
endif
endif
endm
; ------------------------------------------------------------------------------------------ Logical
; --------------------------------------------------------------------------------------------------
and macro @r1,@r2,@r3 ; and @r1 = @r2 & @r3
movf @r3,w
if (@r1 != @r2)
andwf @r2,w
movwf @r1
else
andwf @r2,f
endif
endm
or macro @r1,@r2,@r3 ; or @r1 = @r2 | @r3
movf @r3,w
iorwf @r2,w
movwf @r1
endm
xor macro @r1,@r2,@r3 ; exclusive or @r1 = @r2 ^ @r3
movf @r3,w
xorwf @r2,w
movwf @r1
endm
andi macro @r1,@r2,@i3 ; and immediate @r1 = @r2 & @i3
movlw @i3,w
andwf @r2,w
movwf @r1
endm
ori macro @r1,@r2,@i3 ; or immediate @r1 = @r2 | @i3
movlw @i3,w
iorwf @r2,w
movwf @r1
endm
xori macro @r1,@r2,@i3 ; exclusive or immediate @r1 = @r2 ^ @i3
movlw @i3
xorwf @r2,w
movwf @r1
endm
sll macro @r1,@r2 ; shift left logical @r1 = @r2 << 1
bcf STATUS,c
rlf @r2,w
movwf @r1
endm
srl macro @r1,@r2 ; shift right logical @r1 = @r2 >> 1
bcf STATUS,c
rrf @r2,w
movwf @r1
endm
rl macro @r1,@r2 ; rotate left @r1 = (@r2 << 1) | @r2.7
rlf @r2,w
rlf @r2,w
movwf @r1
endm
rr macro @r1,@r2 ; rotate right @r1 = @r2.0 | (@r2 >> 1)
rrf @r2,w
rrf @r2,w
movwf @r1
endm
; ------------------------------------------------------------------------------------ Data transfer
; SFR registers are only acceded through mfsfr and mtsfr
; all registers indirectly acceded with push, pop, lb, sb are olny in bank 2 ou 3
; --------------------------------------------------------------------------------------------------
li macro @r1,@i2 ; load immediate @r1 = immediate @i2
if (@i2)
movlw @i2
movwf @r1
else
clrf @r1
endif
endm
move macro @r1,@r2 ; move reg to reg @r1 = @r2
movf @r2,w
movwf @r1
endm
mfsfr macro @r1,@sfr ; move from sfr reg @r1 = @sfr
BTOB @r1,@sfr
movf @sfr,w
BTOB @sfr,@r1
movwf @r1
endm
mtsfr macro @r1,@sfr ; move to sfr reg @sfr = @r1
movf @r1,w
BTOB @r1,@sfr
movwf @sfr
BTOB @sfr,@r1
endm
pushi macro @i1,@r2 ; push byte memory[--_SP_] = @i1
bsf STATUS, IRP
decf @r2,f
decf @r2,w
movwf FSR
movlw @i1
movwf INDF
endm
push macro @r1,@r2 ; push byte memory[--@r2] = @r1
bsf STATUS, IRP
decf @r2,f
decf @r2,w
movwf FSR
movf @r1,w
movwf INDF
endm
pop macro @r1,@r2 ; pop byte @r1 = memory[@r2++]
bsf STATUS, IRP
movf @r2,w
movwf FSR
incf @r2,f
movf INDF,w
movwf @r1
endm
sb macro @r1,@i2,@r3 ; store word Memory[@r3+@i2] = @r1
bsf STATUS, IRP
movf @r3,w
addlw @i2
movwf FSR
movf @r1,w
movwf INDF
endm
lb macro @r1,@i2,@r3 ; load word @r1 = Memory[@r3+@i2]
bsf STATUS, IRP
movf @r3,w
addlw @i2
movwf FSR
movf INDF,w
movwf @r1
endm
; ------------------------------------------------------------------------------- Conditional branch
; --------------------------------------------------------------------------------------------------
brpc macro @r1 ; branch relative PC goto PC + 1 + @r1
movlw high($+7)
movwf PCLATH
movlw $+5
addwf @r1,w
btfsc STATUS,C
incf PCLATH,f
movwf PCL
endm
beq macro @r1,@r2,@l3 ; branch on equal if (@r1 == @r2) go @l3
movf @r1,w
subwf @r2,w
btfsc STATUS,Z
goto @l3
endm
bne macro @r1,@r2,@l3 ; branch on not equal if (@r1 != @r2) go @l3
movf @r1,w
subwf @r2,w
btfss STATUS,Z
goto @l3
endm
beqi macro @r1,@r2,@l3 ; branch on equal if (@r1 == @r2) go @l3
movf @r1,w
subwf @r2,w
btfsc STATUS,Z
goto @l3
endm
bnei macro @r1,@r2,@l3 ; branch on not equal if (@r1 != @r2) go @l3
movf @r1,w
subwf @r2,w
btfss STATUS,Z
goto @l3
endm
bgtu macro @r1,@r2,@l3 ; branch if greater than if (@r1 > @r2) go @l3
movf @r1, W
subwf @r2, W
btfss STATUS, C
goto @l3
endm
bgeu macro @r1,@r2,@l3 ; branch if greater or equal if (@r1 >= @r2) go @l3
movf @r2, W
subwf @r1, W
btfsc STATUS, C
goto @l3
endm
bltu macro @r1,@r2,@l3 ; branch if lower than if (@r1 < @r2) go @l3
movf @r2, W
subwf @r1, W
btfss STATUS, C
goto @l3
endm
bleu macro @r1,@r2,@l3 ; branch if lower or equal if (@r1 <= @r2) go @l3
movf @r1, W
subwf @r2, W
btfsc STATUS, C
goto @l3
endm
bgtiu macro @r1,@i2,@l3 ; branch if greater than if (@r1 > @i2) go @l3
movf @r1, W
sublw @i2
btfss STATUS, C
goto @l3
endm
bgeiu macro @r1,@i2,@l3 ; branch if greater or equal if (@r1 >= @i2) go @l3
movlw @i2
subwf @r1, W
btfsc STATUS, C
goto @l3
endm
bltiu macro @r1,@i2,@l3 ; branch if lower than if (@r1 < @i2) go @l3
movlw @i2
subwf @r1, W
btfss STATUS, C
goto @l3
endm
bleiu macro @r1,@i2,@l3 ; branch if lower or equal if (@r1 <= @i2) go @l3
movf @r1, W
sublw @i2
btfsc STATUS, C
goto @l3
endm
bgts macro @r1,@r2,@l3 ; branch if greater than if (@r1 > @r2) go @l3
movf @r2, W
addlw 0x80
movwf _M1
movf @r1, W
addlw 0x80
subwf _M1, W
btfss STATUS, C
goto @l3
endm
bges macro @r1,@r2,@l3 ; branch if greater or equal if (@r1 >= @r2) go @l3
movf @r1, W
addlw 0x80
movwf _M1
movf @r2, W
addlw 0x80
subwf _M1, W
btfsc STATUS, C
goto @l3
endm
blts macro @r1,@r2,@l3 ; branch if lower than if (@r1 < @r2) go @l3
movf @r1, W
addlw 0x80
movwf _M1
movf @r2, W
addlw 0x80
subwf _M1, W
btfss STATUS, C
goto @l3
endm
bles macro @r1,@r2,@l3 ; branch if lower or equal if (@r1 <= @r2) go @l3
movf @r2, W
addlw 0x80
movwf _M1
movf @r1, W
addlw 0x80
subwf _M1, W
btfsc STATUS, C
goto @l3
endm
bgtis macro @r1,@i2,@l3 ; branch if greater than if (@r1 > @i2) go @l3
movf @r1, W
addlw 0x80
sublw 0x80 | @i2
btfss STATUS, C
goto @l3
endm
bgeis macro @r1,@i2,@l3 ; branch if greater or equal if (@r1 >= @i2) go @l3
movf @r1, W
addlw 0x80
sublw 0x80 | @i2
btfss STATUS,Z
btfss STATUS, C
goto @l3
endm
bltis macro @r1,@i2,@l3 ; branch if lower than if (@r1 < @i2) go @l3
movf @r1, W
addlw 0x80
movwf _M1
movlw 0x80 | @i2
subwf _M1, W
btfss STATUS, C
goto @l3
endm
bleis macro @r1,@i2,@l3 ; branch if lower or equal if (@r1 <= @i2) go @l3
movf @r1, W
addlw 0x80
sublw 0x80 | @i2
btfsc STATUS, C
goto @l3
endm