Vous êtes sur la page 1sur 6

; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;

******************************************** Electronic Die Pete Griffiths, 17 May 2004 email: picdie@petesworld.demon.co.uk Copyright Pete Griffiths 2004 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation Use PIC type 12F675 with internal 4Mhz clock ******************************************** #include "P12F675.INC"

You must preserve the OSCCAL data in the destination device before writing this code to it. Set config register for: Code / Memory protection off Brown-out detect off MCLR disabled (use pin for IO) Watch Dog timer disabled Power on reset delay enabled Enable Internal Clock Osc, (set pins for IO)

__CONFIG _CPD_OFF & _CP_OFF & _BODEN_OFF & _MCLRE_OFF & _WDT_OFF & _P WRTE_ON & _INTRC_OSC_NOCLKOUT

; ******************************************** ; Equates and Variables cblock 0x20 dtime ltime rollCnt dieNum throw blankto endc ; ******************************************** ; Point reset vector to program start ; org 0x00 nop nop goto _main ; ; ; ; ; ; ******************************************** SUBROUTINE Lookup Table for GPIO Port Display Data Lookup table takes value in W and returns with port data for die in W Output low = LED on, high = LED off since PIC can sink ;delay sub ;delay sub ;pseudo roll ;pseudo roll ;actual throw num ;blank time out count

; 25mA but only source 20mA. ; ; As the 12F675 GPIO 3 port can only be configured as an input ; the LEDs connect to GPIO ports 0,1,2 and 4 ; where A=GPIO 0, B=1, C=2 and D=4. Arrange LEDs as shown below. ; For 3-4.5v supply, use 270R resistors between each LED and Vdd ; B C ; D A D ; C B ; _lookup addwf PCL,F ;Add W to PCL for computed goto. nop ; This needed because we enter with ; 1 =< W =< 6 and table reads with 0 offset ; DxBCA retlw b'10110' ;die 1 retlw b'10101' ;die 2 retlw b'10010' ;die 3 retlw b'10001' ;die 4 retlw b'10000' ;die 5 retlw b'00001' ;die 6 ; ; ******************************************** ; Subroutine ; Accurate delay routines ; Two routines. Both called with required delay period in W ; One has delay of W x 1mS. Other has delay of W x 100mS ; Accurate for 4Mhz clock ; _Delay movwf dtime ; Call for W x 1mS __Dcall call __1mS decfsz dtime,F goto __Dcall __DlyEnd return _LDelay movwf ltime ; Call for W x 100mS __Dlcall movlw d'100' call _Delay decfsz ltime,F goto __Dlcall return __1mS movlw 0xC6 _next nop addlw 0xFF btfss STATUS,Z goto _next nop nop nop return ; ******************************************** ; SUBROUTINE ; Displays a rolling die thats starts fast and slows to ; a stop about 3 seconds after SW1 released. ; _roller movlw 0x30 ; must be even number movwf rollCnt _rsetone clrf dieNum _rloop incf dieNum,F movf dieNum,W sublw 0x07

btfsc goto movf call movwf movf call incf incf movf sublw btfss goto return ; ; ; ; ; ; ; ; ; ;

STATUS,Z _rsetone dieNum,W _lookup GPIO rollCnt,W _Delay rollCnt,F rollCnt,F rollCnt,W 0x80 ; must be an even number STATUS,Z ; or it never breaks out of the loop _rloop

******************************************** Entry point for program from Reset Initialise GPIO 5,3 input, 4,2,1,0 outputs Set GPIO to digital IO Set INTCON register for interupt on GPIO 5 change disable Global interupts so it wakes from sleep but doesn't service interupt. Enable weak pull up on GPIO5 input. set outputs to high so LEDs are off

_intvect _main bcf movlw movwf movlw movwf bsf call movwf clrf movlw movwf bcf bsf bsf bcf movlw call

STATUS,RP0 0x07 CMCON b'00001001' INTCON

; Sel Bank 0 ; ; Disable Analogue on GPIO pins ; ; Enable GPIO state change int ; See 12F675 data sheet P19

STATUS,RP0 ; Sel Bank 1 0x3FF ; calls RETLW with factory setting OSCCAL ; Set int OSC to factory calibrated ANSEL ; Disable Analogue on GPIO pins b'11101000' ; Specifiy GPIO port direction TRISIO ; Set GPIO ports as xxIOIOOO OPTION_REG,NOT_GPPU ; enable weak pull-up WPU, 5 ; enable wpu on GPIO 5 only IOC, 5 ; enable Int-On-Change GPIO 5 STATUS,RP0 ; Sel Bank 0 0x20 ; set up 20mS wait _Delay ; after reset

; ******************************************** ; put PIC to sleep and wake on SW1 / GPIO 5 ; then 'throw' die ; port GPIO 5 uses internal weak pull up with SW1 n/o to ground. ; Uses interupt on change to wake PIC ; _sleepsw1 movf GPIO,W ; Read GPIO clears Int-On-Change flag ; must read into W not back to F ; as it reads port not the output latch ; which may result in output data being ; inadvertently altered

bcf bsf movlw movwf sleep nop movlw movwf bcf movf bcf movlw call ; ; ; ; ; ; ; ;

; see 12F675 data sheet, P19 Section 3.1 INTCON,GPIF STATUS,RP0 ; Sel bank 1 0xFF ; Setup W for TRISIO all input TRISIO ; Write to TRISIO. Reduce power in sleep mode ; Go to sleep ; b'11101000' ; Wake from sleep and set TRISIO ; TRISIO for correct input and output STATUS,RP0 ; Sel Bank 0 GPIO,W ; Read GPIO register INTCON,GPIF ; and clear GPIF flag in interrupt register. d'5' ; load W with 5 (5mS) _Delay ; and call delay to debounce switch down.

******************************************** once PIC wakes from sleep the 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 Turn of LEDs while SW1 is down movlw 0x17 ; Turn off LEDs while counting movwf GPIO throw ; Reset throw to 0 for each new throw.

_throwdie clrf

; Number of instruction cycles per loop for this block is 12. Code _evenup waste s cycles to ; ensure that the same number of cycles elapse between checks of the SW1 switch so that ; there is an equal probability of it being released on any value of throw count . ; Block will loop 83,333 times per second with 4Mhz clock (1uS) instruction cycl e ; or 833 times in 10mS. Since the throw is determined by the length of time the SW1 switch ; is held down, it results in a fairly even distribution of numbers. Tested with 500 ; consecutive throws gave a mean value of 3.492. _loop incf movf xorlw btfss goto clrf incf goto _evenup nop nop nop _sw1down goto btfss _loop throw,F ; add 1 to throw #1 throw,W ; get throw and put in W #1 7 ; compare to 7 #1 ; (result is only 0 when both No's equal) STATUS,Z ; if less than 7 #1 or #2 if Z=1 _evenup ; go to _evenup #2 only for Z=0 throw ; else set throw #1 Z=1 throw,F ; count back to 1 #1 Z=1 _sw1down ; and goto sw1 check #2 Z=1 ; This is here to even out the #1 Z=0 ; number of instructions executed #1 Z=0 ; when throw count isn't reset to 1 #1 Z=0 GPIO,5 ; Is SW1 down? ; keep counting if it is #1 #2

; we don't debounce the swich because ; any bounce just helps to make it ; more random ; ; ; ; ; ub movf call movwf ; ; ; ; ; ; ; throw,W ; Finished rolling it so get throw value _lookup ; call display data lookup GPIO ; and display the throw on the LEDs ******************************************** switch released call rolling subroutine then display the thrown number on the LEDs call _roller ; Switch has been released so call rolling die s

******************************************** display thrown number 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. 0xD0 blankto movlw _LDelay ; Set count for 20 second display timeout ; move to working file register 0x01 ; call delay subroutine ; with W = 100mS

movlw movwf _blankdly call btfss goto

GPIO,5 ; on return check if SW1 has been pressed _throwdie ; if it has, goto the main throw code ; otherwise decrement display timeout ; and carry on with the timeout count LEDs to fade down at the end of the single count value for the fadeout peri duty cycle of the LEDs as they fade dow on/off ratio goes from 99/1 -> 1/99

decfsz blankto,F goto _blankdly

; the fadeout section of code causes the ; 20 second timeout period. This uses a od ; and this is used to control the on/off n ; so the period remains constant but the _fadeout movwf _fading movf call movwf movf call movlw movwf comf call

movlw 0xFE ; Set length of fadeout period > = longer blankto ; but don't set to 0xFF throw,w ; get last throw number _lookup ; find LED data for throw number GPIO ; display throw blankto,W ; get value in blankto, put in W _fadelay ; and call fade delay subroutine 0x17 ; set data for all LEDs off in W GPIO ; write to LEDS blankto,W ; complement blankto and put in W _fadelay ; and call fade delay routine

decfsz blankto,F ; -1 from blankto goto _fading ; keep fading until it reaches 0

goto ; ; ; ;

_sleepsw1

; goto sleep.

********************************************* Subroutine used by fadeout to give slow fade of LEDs before sleeping movwf dtime ; Enter with W set to outer loop count so save t

_fadelay his _fouter btfss

GPIO,5 ; check if SW1 has been pressed goto _throwdie ; if it has, goto the main throw code movlw 0x16 ; Inner loop count movwf ltime _finner decfsz ltime,F goto _finner decfsz dtime,F goto _fouter return ; ********************************************* dt end " Electronic Die for 12F675 - Pete Griffiths 2004. R6.17052004"

Vous aimerez peut-être aussi