; file: buttontest.asm ; ; test input on gpio3. ; INCLUDE "P12F509.INC" INCLUDE "macross12f509.inc" PATTERNCOUNT EQU 5 LEDCOUNT EQU 4 LEDSOFFVALUE EQU 0x0 ; 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,d3 ; for various timing and misc p0,p1,p2,p3 ; pattern params bitsOut whichPattern patternRepeatCount led0:2 ; 1st: linear brightness, 2nd: running sum, 3rd: target brightness led0Target led1:2 led1Target led2:2 led2Target led3:2 led3Target cblock07End ; keep this last ENDC IF cblock07End > 0x20 ERROR "CBLOCK07 exceeded" ENDIF CBLOCK 0x30 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 CALL Rnd MOVFW rnd IF mask != 0xff ANDLW mask ENDIF MOVWF fregdst IF min != 0 MOVLW min ADDWF fregdst,f ENDIF ENDM ; X := max(0,(X - X/16) | 1) ; a pleasant exponential fade ish FADE16 MACRO fregdst LOCAL _pastFade16 MOVF fregdst,f ; leave in place, but check z IFZ GOTO _pastFade16 SWAPF fregdst,W ANDLW 0x0f IORLW 0x01 SUBWF fregdst,f _pastFade16: 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 LEDSOFFVALUE,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 ; TABLE DOWN LOW PrimeNumber: MOVFW p2 ADDWF PCL,f RETLW 2 RETLW 3 RETLW 5 RETLW 7 RETLW 11 RETLW 13 RETLW 17 RETLW 0 ; ---------------------------------- ; UTILITIES ; Delay 1 pip Delay: MOVLF 1,d2 ; Delay by d2 pips DelayD2: CLRF d0 CLRF d1 _delay: DECFSZ d0,f GOTO _delay CheckButton DECFSZ 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 DisplayCount: MOVFF count,bitsOut RLF bitsOut,w ANDLW 0x30 MOVWF bitsOut MOVFW count ANDLW 0x07 IORWF bitsOut,f MOVFW bitsOut ANDLW (1 << LEDCOUNT) - 1 XORLW LEDSOFFVALUE MOVWF GPIO RETLW 0 RefreshLeds: ; advance each dac CLRF 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 LEDSOFFVALUE ; invert for sink led MOVWF GPIO CLRWDT RETLW 0 ; pretty exponential fade -- ; d0 = number of steps 10 is brief, 50 is mostly or all done ; d1 (optional entry FadeLedsD1) = rate, 16 is normal ; changes d0-d3 FadeLeds: MOVLF 16,d1 ; and fall in FadeLedsD1 _fla: FADE16 led0 CALL RefreshLeds FADE16 led1 CALL RefreshLeds FADE16 led2 CALL RefreshLeds FADE16 led3 ; hold for d2 times, * k (use d1) MOVFF d1,d2 CheckButton _flb: MOVLF 16,d3 _flc: CALL RefreshLeds DECFSZ d3,f GOTO _flc DECFSZ d2,f GOTO _flb ; continue fading, d0 times DECFSZ d0,f GOTO _fla RETLW 0 HoldLeds256: CLRF d0 HoldLeds: MOVFF led0,led0Target MOVFF led1,led1Target MOVFF led2,led2Target MOVFF led3,led3Target GOTO GlideLeds Fadeout: CLRF count CALL CountToTarget MOVLF 0x40,d2 GOTO GlideLeds256 ; 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,led0Target CALL RefreshLeds MIGFPIN led1,led1Target CALL RefreshLeds MIGFPIN led2,led2Target CALL RefreshLeds MIGFPIN led3,led3Target ; 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 MOVLW 0xff IFBS count,0 MOVWF led0Target IFBS count,1 MOVWF led1Target IFBS count,2 MOVWF led2Target IFBS count,3 MOVWF led3Target RETLW 0 ; load up bits 0..4 of count to the current ; brightnesses of the LEDs. CountToBrightness: CLRF led0 CLRF led1 CLRF led2 CLRF led3 ; and fall into ; apply only the 1's to the new brightness ; let 0's fade, or whatever BoostCountToBrightness: MOVLW 0xff IFBS count,0 MOVWF led0 IFBS count,1 MOVWF led1 IFBS count,2 MOVWF led2 IFBS count,3 MOVWF led3 RETLW 0 ; ; 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: ; show 2,3,5,7 ... RANDF p0,7,23 ; time between counting flashes RANDF p1,63,40 ; long time, between numbers CLRF p2 ; index into our digit table MOVLF 200,d0 CALL FadeLeds ; clean start _p1a: ; fetch next number CALL PrimeNumber MOVWF p3 MOVF p3,W ; zero is the last entry, to quit IFZ GOTO NextPattern INCF p2,f ; bump to next digit ; flash p1 times... count in p3 ; MOVFF p1,p3 ; BTFSC p1,3 ; if p1>=2^n ; CLRF p1 ; p1=0 ; INCF p1,f ; and bump p1 for more, next time _p1b: ; begin a flash (distributed around edge) MOVLF 0x1,count CALL BoostCountToBrightness MOVLF 10,d0 ; how many steps CALL FadeLeds MOVLF 0x2,count CALL BoostCountToBrightness MOVLF 10,d0 ; how many steps CALL FadeLeds MOVLF 0x4,count CALL BoostCountToBrightness MOVLF 10,d0 ; how many steps CALL FadeLeds ; light the last candle, and fade all the way out. MOVLF 0x8,count CALL BoostCountToBrightness MOVFF p0,d0 ; longer steps tween MOVLF 28,d0 ; steps CALL FadeLeds ; count flashes, before the BIG pause DECFSZ p3,f GOTO _p1b ; big pause between flash groups... MOVLF 80,d0 MOVLF 10,d2 ; faderate, always the same... CALL FadeLeds ; and loop forever GOTO _p1a ; and maybe start over DECFSZ patternRepeatCount,f GOTO Pattern1 GOTO NextPattern ; hot-cool pattern, 6 long, pause, repeat Pattern2: RANDF patternRepeatCount,0xf,6 RANDF p0,0xff,0 ; the pattern RANDF p1,0x3,4 ; pattern length _p2a: MOVFF p0,p3 ; p3 will be rotated MOVFF p1,p2 ; countdown for pips _p2b: MOVLW 0x15 ; dim value BTFSC p3,0 MOVLW 0xff ; bright value RRF p3,f ; and shift right, destructively MOVWF led0 MOVWF led1 MOVWF led2 MOVWF led3 MOVLF 9,d2 CALL HoldLeds256 CLRF count CALL CountToBrightness CALL CountToTarget MOVLF 12,d2 CALL GlideLeds DECFSZ p2,f ; pattern length GOTO _p2b MOVLF 130,d2 CALL GlideLeds DECFSZ patternRepeatCount,f GOTO _p2a GOTO NextPattern ; searchlight -- bright spot orbits around Pattern3: RANDF patternRepeatCount,0x3f,10 ; quarter turns RANDF p0,0x1f,20 ; speed of rotation MOVLF 0xff,led0Target MOVLF 0x0,led1Target MOVLF 0x06,led2Target MOVLF 0x0,led3Target _p3a: MOVFF p0,d2 CALL GlideLeds256 MOVFF led0Target,p3 MOVFF led1Target,led0Target MOVFF led2Target,led1Target MOVFF led3Target,led2Target MOVFF p3,led3Target DECFSZ patternRepeatCount,f GOTO _p3a CALL Fadeout GOTO NextPattern Pattern4: RANDF patternRepeatCount,0xf,15 _p4a: RANDF p0,0xff,0 RANDF count,0xff,0 RANDF p1,0x1f,8 _p4b: CALL BoostCountToBrightness MOVLF 25,d0 ; fadesteps MOVLF 2,d1 ; faderate CALL FadeLeds MOVFW p0 XORWF count RRF p0,w RRF p0,f DECFSZ p1,f GOTO _p4b ; finish it... MOVLF 190,d0 MOVLF 2,d1 CALL FadeLeds DECFSZ patternRepeatCount,f GOTO _p4a GOTO NextPattern Pattern5: MOVLF 0x50,patternRepeatCount _p5a: CALL CountToBrightness MOVLF 10,d2 CALL HoldLeds256 DECFSZ patternRepeatCount GOTO NextPattern ; ----------------------------- ; 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 LEDSOFFVALUE MOVWF GPIO IFBC GPIO,3 GOTO _buttonStillDown ; button released, delay to debounce CALL DelayNoButton ; and selected. GOTO switchToPattern NextPattern: ; much like the button handler, but just get on with it INCF whichPattern,f MOVFW whichPattern XORLW PATTERNCOUNT IFZ CLRF whichPattern GOTO switchToPattern ORG 0x200 GOTOHILO Start GOTOHILO HandleButton END ch time BCF STATUS,C RRF patternTime,f INCF patternTime,f DECFSZ patternCount,f GOTO _p3loop Pattern4: ; various groups on RANDF patternTime,0x3f,0x80 RANDF patternCount,0x7,13 _p4loop: ; set each led to 0 or 80 RANDF led0+2,0x80,0 RANDF led1+2,0x80,0 RANDF led2+2,0x80,0 RANDF led4+2,0x80,0 RANDF led5+2,0x80,0 CALL GlideLeds CALL FadeoutLeds DECFSZ patternCount,f GOTO _p4loop ; now, we wait for the Watch Dog Timer ; to fire. since its on a separatre clock, ; it lets the timer advance a very random ; amount, increasing our diversity. WaitUntilTimeout: GOTO WaitUntilTimeout GOTO PatternsStart ; ----------------------------- ; High Code ; Code up here in needs to track STATUS:PA0 for ; the 9th bit of the address on GOTO or CALL. We ; keep it set while up here. We clear it to GOTO ; a low address, and temporarily clear it to ; CALL a low address ; ORG 0x200 Pattern7High: MOVLF 0xf0,led0 MOVLF 0x80,led1 MOVLF 0x40,led2 MOVLF 0x20,led4 MOVLF 0x10,led5 CALLLO FadeoutLeds GOTOHILO _p7b END ; EOF CLRF led4+2 CLRF led5+2 MOVLF 0xff,led0+2 CALL GlideLeds MOVLF 0xff,led1+2 CALL GlideLeds MOVLF 0xff,led2+2 CALL GlideLeds MOVLF 0xff,led4+2 CALL GlideLeds MOVLF 0xff,led5+2 CALL GlideLeds CALL FadeoutLeds CALL FadeoutLeds ; make count faster each time BCF STATUS,C RRF patternTime,f INCF patternTime,f DECFSZ patternCount,f GOTO _p3loop Pattern4: ; various groups on RANDF patternTime,0x3f,0x80 RANDF patternCount,0x7,13 _p4loop: ; set each led to 0 or 80 RANDF led0+2,0x80,0 RANDF led1+2,0x80,0 RANDF led2+2,0x80,0 RANDF led4+2,0x80,0 RANDF led5+2,0x80,0 CALL GlideLeds CALL FadeoutLeds DECFSZ patternCount,f GOTO _p4loop ; now, we wait for the Watch Dog Timer ; to fire. since its on a separatre clock, ; it lets the timer advance a very random ; amount, increasing our diversity. WaitUntilTimeout: GOTO WaitUntilTimeout GOTO PatternsStart END ; EOF s ; ORG 0x200 Pattern7High: MOVLF 0xf0,led0 MOVLF 0x80,led1 MOVLF 0x40,led2 MOVLF 0x20,led4 MOVLF 0x10,led5 CALLLO FadeoutLeds GOTOHILO _p7b END ; EOF CLRF led4+2 CLRF led5+2 MOVLF 0xff,led0+2 CALL GlideLeds MOVLF 0xff,led1+2 CALL GlideLeds MOVLF 0xff,led2+2 CALL GlideLeds MOVLF 0xff,led4+2 CALL GlideLeds MOVLF 0xff,led5+2 CALL GlideLeds CALL FadeoutLeds CALL FadeoutLeds ; make count faster each time BCF STATUS,C RRF patternTime,f INCF patternTime,f DECFSZ patternCount,f GOTO _p3loop Pattern4: ; various groups on RANDF patternTime,0x3f,0x80 RANDF patternCount,0x7,13 _p4loop: ; set each led to 0 or 80 RANDF led0+2,0x80,0 RANDF led1+2,0x80,0 RANDF led2+2,0x80,0 RANDF led4+2,0x80,0 RANDF led5+2,0x80,0 CALL GlideLeds CALL FadeoutLeds DECFSZ patternCount,f GOTO _p4loop ; now, we wait for the Watch Dog Timer ; to fire. since its on a separatre clock, ; it lets the timer advance a very random ; amount, increasing our diversity. WaitUntilTimeout: GOTO WaitUntilTimeout GOTO PatternsStart END ; EOF WaitUntilTimeout GOTO PatternsStart END ; EOF art END ; EOF ; to fire. since its on a separatre clock, ; it lets the timer advance a very random ; amount, increasing our diversity. WaitUntilTimeout: GOTO WaitUntilTimeout GOTO PatternsStart END ; EOF WaitUntilTimeout GOTO PatternsStart END ; EOF NDF led0+2,0x80,0 RANDF led1+2,0x80,0 RANDF led2+2,0x80,0 RANDF led4+2,0x80,0 RANDF led5+2,0x80,0 CALL GlideLeds CALL FadeoutLeds DECFSZ patternCount,f GOTO _p4loop ; now, we wait for the Watch Dog Timer ; to fire. since its on a separatre clock, ; it lets the timer advance a very random ; amount, increasing our diversity. WaitUntilTimeout: GOTO WaitUntilTimeout GOTO PatternsStart END ; EOF WaitUntilTimeout GOTO PatternsStart END ; EOF