; file: buttontest.asm ; ; test input on gpio3. ; INCLUDE "P12F509.INC" INCLUDE "macross12f509.inc" ; the LEDS-Dark value for the GPIO. ; We use this for init or xoring. ALLOFF EQU 0x00 ; available file registers 0x7-0x1f (25 registers) ; (there are more at 0x30-0x3f but only by ; FSR indirect addressing.) CBLOCK 0x07 rnd ; for randomizer count d0,d1,d2 ; for various timing and misc p0,p1,p2 ; pattern params bitsOut whichPattern led0:2 ; 1st: linear brightness, 2nd: running sum, 3rd: target brightness led0Target led1:2 led1Target led2:2 led2Target led3:2 led3Target led4:2 led4Target cblock07End ; keep this last ENDC IF cblock07End > 0x20 ERROR "CBLOCK07 exceeded" ENDIF ; more memory locations CBLOCK 0x30 k0:5 ; another block of five led-brightnesses xTilNextPattern ; counter for changing pattern without button use cblock30End ; keep this last ENDC IF cblock30End > 0x40 ERROR "CBLOCK30 exceeded" ENDIF ; MACROS ; Poke a random value into a file register ; mask is anded, and min is added ; RANDF x,31,10 to get 10..41 RANDF MACRO fregdst,mask,min CALLLO Rnd MOVFW rnd IF mask != 0xff ANDLW mask ENDIF MOVWF fregdst IF min != 0 MOVLW min ADDWF fregdst,f ENDIF ENDM ; full-range random function, with lower 50% pinned to zero CLIFFRAND MACRO _dstReg CALLLO Rnd IFBC rnd,7 CLRF rnd MOVFF rnd,_dstReg ENDM ; full-range random function, cliff50, xor first with another then stash CLIFFRANDX MACRO _dstReg,_xorWithReg CALLLO Rnd IFBC rnd,7 CLRF rnd XMOVFW _xorWithReg XORWF rnd,W XMOVWF _dstReg 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". StepDac MACRO dacState,dest MOVFW dacState ADDWF dacState+1,F RLF dest,F ; put led in low bit ENDM LedsOff MACRO MOVLF ALLOFF,GPIO ; lights off while we rethink ENDM ; Check the button input and just bail on whatever's ; happening if the button is pressed. Note that we ; rely on jump table entries being present in both ; pages. CheckButton MACRO IFBC GPIO,3 ; button grounded = pressed GOTO GotoHandleButton ENDM ORG 0 ; lets begin ; we keep a matching jump table at 0x000 and 0x200, ; for certain key routines that we want to "just work" GOTOHILO Start GotoHandleButton: GOTOHILO HandleButton ; ---------------------------------- ; UTILITIES ; Delay 1 pip Delay: MOVLF 1,d2 ; Delay by d2 pips DelayD2: CLRF d0 CLRF d1 _delay: INCFSZ d0,f GOTO _delay CheckButton INCFSZ d1,f GOTO _delay DECFSZ d2,f GOTO _delay RETLW 0 ; Delay a pip *without* checking the button DelayNoButton: CLRF d0 MOVLF 0x60,d1 _delayNB: DECFSZ d0,f GOTO _delayNB DECFSZ d1,f GOTO _delayNB RETLW 0 ; the count register has bits 0..4. present them on the LEDs. DisplayCount: MOVFF count,bitsOut RLF bitsOut,w ANDLW 0x30 MOVWF bitsOut MOVFW count ANDLW 0x07 IORWF bitsOut,f XORLF ALLOFF,bitsOut MOVFF bitsOut,GPIO RETLW 0 RefreshLeds: ; advance each dac CLRF bitsOut StepDac led4,bitsOut StepDac led3,bitsOut ; just a zero for bit 3 BCF STATUS,C RLF bitsOut,f StepDac led2,bitsOut StepDac led1,bitsOut StepDac led0,bitsOut MOVFW bitsOut XORLW ALLOFF ; invert for sink led MOVWF GPIO CLRWDT RETLW 0 ; move each LED to its target value, pausing ; d2 tween each step. ; do 256 steps to be sure. ; uses: d0, d1. GlideLeds256: ; glide LEDs all the way... CLRF d0 ; outer counter, make sure we do 256 altogether GlideLeds: ; glide LEDs by d0 steps _glideLedsLoop1: CALL RefreshLeds MIGFPIN led0,led0+2 CALL RefreshLeds MIGFPIN led1,led1+2 CALL RefreshLeds MIGFPIN led2,led2+2 CALL RefreshLeds MIGFPIN led3,led3+2 CALL RefreshLeds MIGFPIN led4,led4+2 ; now delay by d2 refreshes... CALL RefreshLeds ; refresh leds by d2 times. MOVFF d2,d1 ; 2 NOPS 6 _glideLedsLoop: CheckButton CALL RefreshLeds NOPS 5 DECFSZ d1,f GOTO _glideLedsLoop NOP CALL RefreshLeds NOPS 5 DECFSZ d0,f GOTO _glideLedsLoop1 RETLW 0 ; load up bits 0..4 of count to the target ; brightnesses of the LEDs. CountToTarget: CLRF led0Target CLRF led1Target CLRF led2Target CLRF led3Target CLRF led4Target MOVLW 0xff IFBS count,0 MOVWF led0Target IFBS count,1 MOVWF led1Target IFBS count,2 MOVWF led2Target IFBS count,3 MOVWF led3Target IFBS count,4 MOVWF led4Target RETLW 0 ; load up bits 0..4 of count to the current ; brightnesses of the LEDs. CountToBrighness: CLRF led0 CLRF led1 CLRF led2 CLRF led3 CLRF led4 MOVLW 0xff IFBS count,0 MOVWF led0 IFBS count,1 MOVWF led1 IFBS count,2 MOVWF led2 IFBS count,3 MOVWF led3 IFBS count,4 MOVWF led4 RETLW 0 Fadeout: CLRF led0Target CLRF led1Target CLRF led2Target CLRF led3Target CLRF led4Target MOVLF 0x40,d2 GOTO GlideLeds256 ; ; Put a (very psuedo) random number into ; the 'rnd' file register. Rnd: MOVFW rnd ADDWF TMR0,w RLF rnd,f RLF rnd,f ADDWF rnd,f RETLW 0 ; ---------------------------------- ; MAIN Start: ;CALL delay ; All five outputs to "out" ; GPIO 3 can only be "in" MOVLW b'00001000' TRIS GPIO MOVLW b'00011111' ; OPTION IFBS STATUS,GPWUF GOTO pastInit ; these inits done only the first time CLRF whichPattern pastInit: switchToPattern: CheckButton CLRF count PATTERN_COUNT EQU 5 ; switch statement for whichPattern MOVFF whichPattern,d0 ; hijack d0 INCF d0,f DECF d0,f IFZ GOTO GotoP1 DECF d0,f IFZ GOTO GotoP2 DECF d0,f IFZ GOTO GotoP3 DECF d0,f IFZ GOTO GotoP4 DECF d0,f IFZ GOTO GotoP5 GOTO GotoP5 GotoP1: GOTOHILO Pattern1 GotoP2: GOTOHILO Pattern2 GotoP3: GOTOHILO Pattern3 GotoP4: GOTOHILO Pattern4 GotoP5: GOTOHILO Pattern5 ; -------------------------------------------------- Pattern1: MOVLF 3,xTilNextPattern _p1_setup: ; k0[5] == keys to XOR between two color choices ; p0 = how many times to keep the same colors ; p1 = how long to fade between ; p2 = how long to hold a color CLIFFRAND led0Target CLIFFRAND led1Target CLIFFRAND led2Target CLIFFRAND led3Target CLIFFRAND led4Target CLIFFRANDX k0+0,led0Target CLIFFRANDX k0+1,led1Target CLIFFRANDX k0+2,led2Target CLIFFRANDX k0+3,led3Target CLIFFRANDX k0+4,led4Target RANDF p0,0x1f,0x5 ; keep same color RANDF p1,0x3f,0x03 ; fade time RANDF p2,0x1f,0x02 ; hold time _p1_a: MOVFF p1,d2 ; glidetime CALL GlideLeds256 MOVFF p2,d2 CALL GlideLeds CALL GlideLeds CALL GlideLeds XMOVFW k0+0 XORWF led0Target,f XMOVFW k0+1 XORWF led1Target,f XMOVFW k0+2 XORWF led2Target,f XMOVFW k0+3 XORWF led3Target,f XMOVFW k0+4 XORWF led4Target,f DECFSZ p0,f GOTO _p1_a XDECFSZ xTilNextPattern GOTO _p1_setup GOTOHILO Pattern2 Pattern3: MOVLF 1,count _pattern3: CALLLO DisplayCount CALL Delay CALL Delay BCF STATUS,C BTFSC count,4 BSF STATUS,C RLF count,f GOTO _pattern3 ; fading binary step ; p0 step value, an odd number ; p1 time ; p2 how far fade gets Pattern4: CALL Rnd MOVFW rnd IORLW 1 MOVWF p0 RANDF p1,0x7f,10 RANDF p2,0x7f,0x70 _pattern4: CLRF led0Target CLRF led1Target CLRF led2Target CLRF led3Target CLRF led4Target MOVLW 0xff IFBS count,0 MOVWF led0Target IFBS count,1 MOVWF led1Target IFBS count,2 MOVWF led2Target IFBS count,3 MOVWF led3Target IFBS count,4 MOVWF led4Target MOVFF p1,d2 MOVFF p2,d0 CALL GlideLeds MOVFW count ADDWF p0,w ANDLW 0x1f MOVWF count IFNZ GOTO _pattern4 GOTO Pattern4 ; setup again Pattern5: ; SLEEP! or "off"ish ; danger... hopefully upon waking we'd get here, and ; increment past the sleeping pattern. ohoh. CheckButton LedsOff; lights off please. SLEEP ; ----------------------------- ; Button Checking ;CheckButton: ; BTFSC GPIO,3 ; normally high ; RETLW 0 ; button is pressed... ; increment whichPattern, and show it as 1..n lit up HandleButton: INCF whichPattern,f MOVFW whichPattern XORLW PATTERN_COUNT IFZ CLRF whichPattern ; show it... MOVFF whichPattern,d0 INCF d0,f CLRF count _showWhichPattern BSF STATUS,C RLF count,f DECFSZ d0,f GOTO _showWhichPattern CALL DisplayCount ; debounce by waiting, then awaiting button-up CALL DelayNoButton _buttonStillDown: ;while button down, flash 1..n for whichPattern INCF d0,f IFZ INCF d1,f MOVFW bitsOut IFBS d1,5 MOVLW ALLOFF MOVWF GPIO IFBC GPIO,3 GOTO _buttonStillDown ; button released, delay to debounce CALL DelayNoButton ; and selected. GOTO switchToPattern ORG 0x200 ; lets begin ; we keep a matching jump table at 0x000 and 0x200, ; for certain key routines that we want to "just work" GOTOHILO Start XGotoHandleButton: GOTOHILO HandleButton ; one-hot, fading out ; p0: time to choose no rates, &c ; p1: how much fading to do ; p2: how much to step Pattern2: MOVLF 3,xTilNextPattern CLRF led0Target CLRF led1Target CLRF led2Target CLRF led3Target CLRF led4Target MOVLF 0,count h_pattern2Setup ; glide-time (higher is slower) RANDF d2,0x3f,0x20 ; 0x20..0x60 ; MOVLF 0x40,d2 RANDF p1,0x7f,0x40 ; 0x40..0xc0, number of fadesteps RANDF p2,0x3,1 ; how much to bump each time ; MOVLF 11,p0 ; do this many before new setup RANDF p0,0x1f,11 ; change pattern after this many h_pattern2: ; set led[count] brightness to ff, vi IFS MOVLW led0 ADDWF count,w ADDWF count,w ADDWF count,w MOVWF FSR MOVLF 0xff,INDF ;MOVLF 0x90,d0 MOVFF p1,d0 CALLLO GlideLeds LedsOff ; bump count wrap at 5 MOVFF p2,d0 h_pattern2BumpCount INCF count,f MOVFW count XORLW 5 IFZ CLRF count DECFSZ d0,f GOTO h_pattern2BumpCount ; time for new everythings? DECFSZ p0,f GOTO h_pattern2 XDECFSZ xTilNextPattern ; reset params! GOTO h_pattern2Setup GOTOHILO Pattern1 END