; Sunrise Intenselator ; 2013-08-14 ; code for a device which shows medical-style heart & breath levels ; and occasionally blinds you ; ; Using wbl16a board, RA0-RA4 are colored LEDs ; RB4 drives a (blinding) 10w high intensity beam. list p=16F628 #include #include "macross.inc" __CONFIG _CP_OFF & _WDT_ON & _PWRTE_ON & _BODEN_OFF &_INTRC_OSC_NOCLKOUT & _MCLRE_OFF & _LVP_OFF ERRORLEVEL -302 ; All-bank variables (16 bytes) CBLOCK 70h cblock70End ENDC IF cblock70End > 0x7F ERROR "CBLOCK70 exceeded" ENDIF ; Bank 0 variables (80 bytes) CBLOCK 20h ; whichPattern, by integer index. whichPattern ; random state rnd ; Only clear from here on higher. ; Some state persists across universes. clearFromHere ; counters for GlideLed and Delay r0 r1 r2 ; temps for each pattern p0 p1 p2 p3 ; glideTime is how many refreshes we do per glide tick. ; bigger value is slower. At 255, a full glide/fadeout takes ~5 seconds. glideTime ; patternCount is how many cycles to stay with this pattern patternCount patternCountLow ; (times 256) led0:3 ; 1st: linear brightness, 2nd: running sum, 3rd: target brightness led1:3 led2:3 led3:3 led4:3 ; the HIGH BRIGHT MOSFET led6:3 bitsOut ; Various Pattern State ; pattern 1: Orange Cycle greenStep pinkStep ; pattern 2: Scan Cycle whichOrange ; bit pattern for which oranges to flash during warning cycle orangeFlashCount ; how many times to flash orange during warning cycle cblock20End ENDC IF cblock20End > 0x6f ERROR "CBLOCK20 exceeded" ENDIF ; ok. org 0x0000 goto INIT org 0x0004 goto IRQ IRQ: GOTO IRQ ; ; 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 RETURN ; 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 RefreshLeds: ; advance each dac CLRF bitsOut StepDac led6,bitsOut ; just a zero for bit 5 BCF STATUS,C RLF bitsOut,f StepDac led4,bitsOut StepDac led3,bitsOut StepDac led2,bitsOut StepDac led1,bitsOut StepDac led0,bitsOut MOVFW bitsOut MOVWF PORTB CLRWDT RETLW 0 ; move each LED to its target value, pausing ; (which is to say, repeating the dacs) ; glideTime tween each step. ; do 256 steps to be sure. ; uses: r0, r1. GlideLeds: CLRF r0 ; outer counter, make sure we do 256 altogether _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 CALL RefreshLeds MIGFPIN led6,led6+2 ; now delay by glideTime refreshes... CALL RefreshLeds MOVFF glideTime,r1 ; 2 NOPS 6 _glideLedsLoop: CALL RefreshLeds NOPS 5 DECFSZ r1,f GOTO _glideLedsLoop NOP CALL RefreshLeds NOPS 5 DECFSZ r0,f GOTO _glideLedsLoop1 RETURN FadeoutLeds: MOVLF 30,glideTime CLRF led0+2 CLRF led1+2 CLRF led2+2 CLRF led3+2 CLRF led4+2 CLRF led6+2 CALL GlideLeds CALL GlideLeds RETURN EndPattern: CALL FadeoutLeds INCF whichPattern,F MOVFW whichPattern SUBLW 2 ; highest pattern number IFZ CLRF whichPattern _waitForWdt: GOTO _waitForWdt INIT: CLRWDT ; + -------------------------------- ; | Hardware setup ; | as per datasheet, set up port, tris, and CMCON. MOVLF clearFromHere,FSR ClearMemLoop: CLRF INDF INCF FSR,F CLRWDT IFBC FSR,7 GOTO ClearMemLoop MOVLW 0x07 MOVWF CMCON ; no comparAtors on PORTA thanks CLRF PORTA CLRF PORTB BANK1 BCF OPTION_REG,T0CS ; Timer 0 increments every Instruction Cycle BSF OPTION_REG,PS0 ; divider for watchdog counter, make it slowest. BSF OPTION_REG,PS1 BSF OPTION_REG,PS1 CLRF TRISA ; Port A is output CLRF TRISB ; Port B is output BANK0 ; which pattern to use. MOVFW whichPattern SUBLW 0 IFZ GOTO FlickerCycle SUBLW 1 IFZ GOTO OrangeCycle SUBLW 1 IFZ GOTO ScanCycle GOTO FlickerCycle OrangeCycle: CLRWDT MOVLF 0x55,glideTime RANDF glideTime,0x7f,0x1f RANDF patternCount,0x3f,2 lp1: MOVLF 0xff,led0 MOVLF 0,led0+2 CALL GlideLeds MOVLF 0xff,led1 MOVLF 0,led1+2 CALL GlideLeds MOVLF 0xff,led2 MOVLF 0,led2+2 CALL GlideLeds MOVLW 0x66 ADDWF led3+2,F MOVLW 0x91 ADDWF led6+2,F DECFSZ patternCount,F GOTO lp1 GOTO EndPattern GlideLeds6: MOVLF 6,glideTime GOTO GlideLeds GlideLeds2: MOVLF 2,glideTime GOTO GlideLeds GlideLeds20: MOVLF 20,glideTime GOTO GlideLeds GlideLeds50: MOVLF 50,glideTime GOTO GlideLeds Delay: CLRWDT MOVWF r1 CLRF r0 _del MOVLF 30,r2 _del1 CLRWDT DECFSZ r2,F GOTO _del1 DECFSZ r0,F GOTO _del DECFSZ r1,F GOTO _del RETURN ; set only some of the oranges on SetSomeOrange: CLRF led0+2 CLRF led1+2 CLRF led2+2 MOVLW 0xff IFBS whichOrange,0 MOVWF led0+2 IFBS whichOrange,1 MOVWF led1+2 IFBS whichOrange,2 MOVWF led2+2 RETURN ; flash some of the oranges ; flashed orangeFlashCount time, On then Off FlashSomeOrange: CALL SetSomeOrange CALL GlideLeds2 CALL GlideLeds50 CLRF led0+2 CLRF led1+2 CLRF led2+2 CALL GlideLeds2 CALL GlideLeds50 DECFSZ orangeFlashCount,F GOTO FlashSomeOrange RETURN ; scan cycle first pulses the lamps in a predefined warning ; sequence, then ramps up the white light, very slowly, ; then strobes it. ScanCycle: CLRWDT MOVLF 0x01,whichOrange MOVLF 5,orangeFlashCount CALL FlashSomeOrange MOVLF 0x03,whichOrange MOVLF 4,orangeFlashCount CALL FlashSomeOrange MOVLF 0x07,whichOrange MOVLF 3,orangeFlashCount CALL FlashSomeOrange GOTO EndPattern ; flicker the LEDS hard on and off, randomly quite rapidly. ; then flash the bright light, not very bright. FlickerCycle: RANDF patternCount,0x7,3 RANDF p0,0x0f,3 ; how many flickers in each batch RANDF p1,0x7,3 ; how many batches, each with a blink at the end _fc0: MOVFF p1,p3 ; p3 is our batch countdown _fc1: MOVFF p0,p2 ; p2 is our flicker countdown _fc2: CALL Rnd MOVFW rnd ANDLW 0x4f ; bits 0 1 2 3 6 MOVWF PORTB MOVLW 2 CALL Delay DECFSZ p2,F GOTO _fc2 ; pause after flicker batch CLRF PORTB MOVLW 80 CALL Delay DECFSZ p3,F GOTO _fc1 MOVLF 0x40,PORTB ; here?? MOVLW 80 CALL Delay ; did batches of flickers, now flash the big guy ; p2 is our flash counter RANDF p2,0x1f,2 _fc3: MOVLF 0x40,led4 MOVLF 0x0,led4+2 MOVLF 0x80,led0 MOVLF 0x0,led0+2 CALL GlideLeds2 CALL GlideLeds2 DECFSZ p2,F GOTO _fc3 MOVLW 0xc0 CALL Delay ; And repeat the whole thing, maybe DECFSZ patternCount,F GOTO _fc0 GOTO EndPattern END