bigal_scorpio
Active Member
Hi to all,
I was planning on making a PIC Dice for my young grandson and found a program that looks just the job.
Unfortunately its for the PIC12F675 and I only have some PIC12F629s.
The datasheet covers both PICs and the only difference I can see is the 629 not having any Analog capacity where as the 675 does.
Would this program work on the 629? Because its in ASM I can't figure out what does what. I only know Basic so could anyone out there check the code and see if anything needs changing please.
Thanks for looking.........Al
I was planning on making a PIC Dice for my young grandson and found a program that looks just the job.
Unfortunately its for the PIC12F675 and I only have some PIC12F629s.
The datasheet covers both PICs and the only difference I can see is the 629 not having any Analog capacity where as the 675 does.
Would this program work on the 629? Because its in ASM I can't figure out what does what. I only know Basic so could anyone out there check the code and see if anything needs changing please.
Thanks for looking.........Al
Code:
; ********************************************
; 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 & _PWRTE_ON & _INTRC_OSC_NOCLKOUT
; ********************************************
; Equates and Variables
cblock 0x20
dtime ;delay sub
ltime ;delay sub
rollCnt ;pseudo roll
dieNum ;pseudo roll
throw ;actual throw num
blankto ;blank time out count
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
; 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 STATUS,Z
goto _rsetone
movf dieNum,W
call _lookup
movwf GPIO
movf rollCnt,W
call _Delay
incf rollCnt,F
incf rollCnt,F
movf rollCnt,W
sublw 0x80 ; must be an even number
btfss STATUS,Z ; or it never breaks out of the loop
goto _rloop
return
;
; ********************************************
; 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 STATUS,RP0 ; Sel Bank 0
movlw 0x07 ;
movwf CMCON ; Disable Analogue on GPIO pins
movlw b'00001001' ;
movwf INTCON ; Enable GPIO state change int
; See 12F675 data sheet P19
bsf STATUS,RP0 ; Sel Bank 1
call 0x3FF ; calls RETLW with factory setting
movwf OSCCAL ; Set int OSC to factory calibrated
clrf ANSEL ; Disable Analogue on GPIO pins
movlw b'11101000' ; Specifiy GPIO port direction
movwf TRISIO ; Set GPIO ports as xxIOIOOO
bcf OPTION_REG,NOT_GPPU ; enable weak pull-up
bsf WPU, 5 ; enable wpu on GPIO 5 only
bsf IOC, 5 ; enable Int-On-Change GPIO 5
bcf STATUS,RP0 ; Sel Bank 0
movlw 0x20 ; set up 20mS wait
call _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
; see 12F675 data sheet, P19 Section 3.1
bcf INTCON,GPIF
bsf STATUS,RP0 ; Sel bank 1
movlw 0xFF ; Setup W for TRISIO all input
movwf TRISIO ; Write to TRISIO. Reduce power in sleep mode
sleep ; Go to sleep
nop ;
movlw b'11101000' ; Wake from sleep and set
movwf TRISIO ; TRISIO for correct input and output
bcf STATUS,RP0 ; Sel Bank 0
movf GPIO,W ; Read GPIO register
bcf INTCON,GPIF ; and clear GPIF flag in interrupt register.
movlw d'5' ; load W with 5 (5mS)
call _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
;
_throwdie movlw 0x17 ; Turn off LEDs while counting
movwf GPIO
clrf throw ; Reset throw to 0 for each new throw.
; Number of instruction cycles per loop for this block is 12. Code _evenup wastes 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 cycle
; 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 throw,F ; add 1 to throw #1
movf throw,W ; get throw and put in W #1
xorlw 7 ; compare to 7 #1
; (result is only 0 when both No's equal)
btfss STATUS,Z ; if less than 7 #1 or #2 if Z=1
goto _evenup ; go to _evenup #2 only for Z=0
clrf throw ; else set throw #1 Z=1
incf throw,F ; count back to 1 #1 Z=1
goto _sw1down ; and goto sw1 check #2 Z=1
_evenup nop ; This is here to even out the #1 Z=0
nop ; number of instructions executed #1 Z=0
nop ; when throw count isn't reset to 1 #1 Z=0
_sw1down btfss GPIO,5 ; Is SW1 down? #1
goto _loop ; keep counting if it is #2
; we don't debounce the swich because
; any bounce just helps to make it
; more random
; ********************************************
; switch released
; call rolling subroutine
; then display the thrown number on the LEDs
;
call _roller ; Switch has been released so call rolling die sub
movf throw,W ; Finished rolling it so get throw value
call _lookup ; call display data lookup
movwf GPIO ; and display the throw on the LEDs
; ********************************************
; 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.
;
movlw 0xD0 ; Set count for 20 second display timeout
movwf blankto ; move to working file register
_blankdly movlw 0x01 ; call delay subroutine
call _LDelay ; with W = 100mS
btfss GPIO,5 ; on return check if SW1 has been pressed
goto _throwdie ; if it has, goto the main throw code
decfsz blankto,F ; otherwise decrement display timeout
goto _blankdly ; and carry on with the timeout count
; the fadeout section of code causes the LEDs to fade down at the end of the
; 20 second timeout period. This uses a single count value for the fadeout period
; and this is used to control the on/off duty cycle of the LEDs as they fade down
; so the period remains constant but the on/off ratio goes from 99/1 -> 1/99
_fadeout movlw 0xFE ; Set length of fadeout period > = longer
movwf blankto ; but don't set to 0xFF
_fading movf throw,w ; get last throw number
call _lookup ; find LED data for throw number
movwf GPIO ; display throw
movf blankto,W ; get value in blankto, put in W
call _fadelay ; and call fade delay subroutine
movlw 0x17 ; set data for all LEDs off in W
movwf GPIO ; write to LEDS
comf blankto,W ; complement blankto and put in W
call _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
_fadelay movwf dtime ; Enter with W set to outer loop count so save this
_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 " Electronic Die for 12F675 - Pete Griffiths 2004. R6.17052004"
end