; file: macross12f509.inc ; ; started 20070715 poly@omino.com ; -------------------------------------------- ; various general purpose macros for the ; microchip 12f509 mcu. these generally follow ; conventions similar to the standard opcodes. ; it is generally assumed that the W and STATUS ; registers are affected ; --------------------------------------------- MOVLF MACRO v,freg IF v == 0 CLRF freg ELSE MOVLW v MOVWF freg ENDIF ENDM MOVLF16 MACRO _v,_freg MOVLF (_v & 0xff),_freg MOVLF (_v >> 8),(_freg + 1) ENDM ADDLF MACRO v,freg MOVLW v ADDWF freg,f ENDM ADDFF MACRO fregsrc,fregdst MOVFW fregsrc ADDWF fregdst,f ENDM SUBFF MACRO fregsrc,fregdst MOVFW fregsrc SUBWF fregdst,f ENDM MOVFF MACRO fregsrc,fregdst MOVFW fregsrc MOVWF fregdst ENDM ; simplifications of common "skip" functions IFZ MACRO BTFSC STATUS,Z ENDM IFNZ MACRO BTFSS STATUS,Z ENDM IFC MACRO BTFSC STATUS,C ENDM IFNC MACRO BTFSS STATUS,C ENDM IFBC MACRO _reg,_bit BTFSS _reg,_bit ENDM IFBS MACRO _reg,_bit BTFSC _reg,_bit ENDM ; Decrement a file register unless it's ; already at zero. 3 cycles every time. DECFPIN MACRO freg INCF freg,f DECFSZ freg,f DECF freg,f ENDM ; Increment or decrement a file register ; to bring it closer to the destination. ; already there? no change. ; 8 cycles & 8 instructions exactly. ; no gotos. MIGFPIN MACRO fregcur,fregdst MOVFW fregcur SUBWF fregdst,w MOVLW 1 ; assume increment IFNC MOVLW 0xff ; negative sub, so decrement IFZ MOVLW 0 ; oh, they were equal ADDWF fregcur,f ENDM ; increment reg, no higher than 0xff INCPINF MACRO reg INCF reg,f IFZ DECF reg,f ENDM ; decrement reg, no lower than 0x00 DECPINF MACRO reg MOVF reg,f ; leave in place, setz IFNZ DECF reg,f ENDM ; insert a handful of NOPs, as many as you ask for. NOPS MACRO cycles _delay_k SET cycles WHILE _delay_k > 0 _delay_k SET _delay_k - 1 NOP ENDW ENDM ; poke a value to an indirect reg ; 5c MOVLI MACRO _v,_iReg MOVLF _iReg,FSR MOVLF _v,INDF CLRF FSR ENDM MOVLI16 MACRO _v,_iReg BANKSEL _iReg ERRORLEVEL 1 MOVLF16 _v,_iReg ERRORLEVEL 0 BANKSEL 0 ENDM ; fetch one of our indirect registers to W ; 4c MOVIW MACRO _iReg MOVLF _iReg,FSR MOVFW INDF CLRF FSR ; otherwise upper bits affect MOVs ENDM ; move an indirect reg to a reg ; 5c MOVIF MACRO _iReg,_reg MOVIW _iReg MOVWF _reg ENDM MOVFI MACRO _reg,_iReg MOVFW _reg MOVWI _iReg ENDM ; Call from upper page to lower, restoring ; STATUS:PA0 to high. CALLLO MACRO _addr BCF STATUS,PA0 CALL _addr BSF STATUS,PA0 ENDM GOTOHILO MACRO _addr IF _addr >= 0x200 BSF STATUS,PA0 ELSE BCF STATUS,PA0 ENDIF ERRORLEVEL 1 GOTO (_addr & 0x01ff) ERRORLEVEL 0 ENDM CALLHILO MACRO _addr IF (_addr & 0x0100) > 0 ERROR "cant call 0x01xx or 0x03xx" ENDIF IF _addr >= 0x200 BSF STATUS,PA0 ELSE BCF STATUS,PA0 ENDIF ERRORLEVEL 1 CALL _addr ERRORLEVEL 0 ENDM ; decrement and skip if zero, but for register in any bank ; leaves back back at zero DECFSZ2 MACRO _addr MOVLF _addr,FSR ; set the indirect DECF INDF ; decrement it, set Z flag maybe BCF FSR,5 ; FSR back in lower bank, thanks BDFSS STATUS,Z ; skip if Z ENDM ; Each 1-bit dac is maintained as 2 bytes: ; the brightness and the running-sum. ; (a third byte is sometimes the "target brightness") ; Rotate the current 1-bit dac on-offness ; into the right side of "dest". ; cycles: 3 StepDac MACRO dacState,dest MOVFW dacState ADDWF dacState+1,F RLF dest,F ; put led in low bit ENDM ; Sometimes we mix "analog" and digital ; outputs. While stepDac does the 1-bit dac thing, ; this one, SlamDac treats the dac as "on" if it's ; above 127. ; cycles: 2 SlamDac MACRO dacState,dest RLF dacState,w RLF dest,F ENDM LedsOff MACRO MOVLF LEDSOFFVALUE,GPIO ; lights off while we rethink ENDM ; Poke a random value into a file register ; mask is anded, and min is added ; RANDF x,31,10 to get 10..41 ; 11c + 1 if mask != 0xff + 2 if min != 0 ; RANDF MACRO fregdst,mask,min CALL Rnd ; 9c MOVFW rnd IF mask != 0xff ANDLW mask ENDIF MOVWF fregdst IF min != 0 MOVLW min ADDWF fregdst,f ENDIF ENDM