; Electronic Die ; Pete Griffiths, May 2004 ; Use PIC type 16F84 at 4Mhz clock ; ; list p=pic16f84 ; #include "P16F84.INC" ; ; Equates and Variables dOuter EQU 0x20 ;delay sub dInner EQU 0x21 ;delay sub rollCnt EQU 0x22 ;pseudo roll dieNum EQU 0x23 ;pseudo roll throw EQU 0x24 ;actual throw num blankto EQU 0x25 ;blank time out count ; Point reset and interupt vectors ; both go to same place since we're not using ; interupts. Just the way I like to do it. ; org 0 goto _main org 4 goto _intvect ; Put this first to make sure table doesn't cross ; page boundary. ; Lookup table takes value in W and returns with ; port data for die in W ; Using low 4 bits of port B connect as shown ; Where A=bit 0, B=bit 1, C=bit 2, D=bit 3 ; Output low = LED on, high = LED off since PIC can sink ; 25mA but only source 20mA. ; B C ; D A D ; C B ; _lookup addwf PCL nop retlw b'1110' ;die 1 retlw b'1101' ;die 2 retlw b'1010' ;die 3 retlw b'1001' ;die 4 retlw b'1000' ;die 5 retlw b'0001' ;die 6 ; ; Delay loop ; Enter with W containing value for outLoop ; allows variable delay from one subroutine. ; _delay movwf dOuter _outLoop clrf dInner _inLoop decfsz dInner goto _inLoop decfsz dOuter goto _outLoop return ; ; Subroutine to display a rolling die ; that slows to a stop ; _roller movlw 0x65 movwf rollCnt _rsetone clrf dieNum _rloop incf dieNum movf dieNum,W sublw 7 btfsc STATUS,Z goto _rsetone movf dieNum,W call _lookup movwf PORTB movf rollCnt,W call _delay incf rollCnt movf rollCnt,W sublw 0x95 btfss STATUS,Z goto _rloop return ; Entry point for program from Reset ; Initialise port b as 7-4 input, 3-0 outputs ; set outputs to high so LEDs are off ; Set INTCON register for interupt on port B change ; disable Global interupts so it wakes from sleep ; but doesn't service interupt. ; Enables weak pull up on Port B inputs. _intvect _main movlw 0xF0 bsf STATUS,RP0 movwf TRISB bcf OPTION_REG,NOT_RBPU bcf STATUS,RP0 movlw 0x0F movwf PORTB movlw b'00001001' movwf INTCON ; put PIC to sleep and wake on SW1 / Port B7 ; then 'throw' die ; port B7 use internal weak pull up with SW1 n/o to ground. ; Uses interupt on change to wake PIC ; _sleepsw1 movf PORTB bcf INTCON,RBIF sleep nop movf PORTB bcf INTCON,RBIF ; once PIC wakes from sleep ; throw counter runs while SW1 is held down ; given the 4Mhz clock speed of the PIC this results in a ; fairly random number being generated _setone clrf throw _loop incf throw movf throw,W sublw 7 btfsc STATUS,Z goto _setone movf throw,W call _lookup movwf PORTB nop _sw1down btfss PORTB,7 goto _loop ; switch released ; call rolling subroutine ; then display the thrown number on the LEDs ; call _roller movf throw,W call _lookup movwf PORTB ; display throw for 20 seconds ; then blank display to save battery ; and go back to sleep awaiting next 'throw' ; checks for SW1 throw while displaying previous throw ; in which case it throws again without sleeping. ; movlw 0x80 movwf blankto _blankdly movlw 0xFF call _delay btfss PORTB,7 goto _setone decfsz blankto goto _blankdly movlw 0x0F movwf PORTB goto _sleepsw1 end